tifm_7xx1: simplify eject function
[pandora-kernel.git] / drivers / misc / tifm_7xx1.c
1 /*
2  *  tifm_7xx1.c - TI FlashMedia driver
3  *
4  *  Copyright (C) 2006 Alex Dubov <oakad@yahoo.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  */
11
12 #include <linux/tifm.h>
13 #include <linux/dma-mapping.h>
14
15 #define DRIVER_NAME "tifm_7xx1"
16 #define DRIVER_VERSION "0.7"
17
18 static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock)
19 {
20         unsigned long flags;
21
22         spin_lock_irqsave(&fm->lock, flags);
23         if (!fm->inhibit_new_cards) {
24                 fm->remove_mask |= 1 << sock->socket_id;
25                 queue_work(fm->wq, &fm->media_remover);
26         }
27         spin_unlock_irqrestore(&fm->lock, flags);
28 }
29
30 static void tifm_7xx1_remove_media(struct work_struct *work)
31 {
32         struct tifm_adapter *fm =
33                 container_of(work, struct tifm_adapter, media_remover);
34         unsigned long flags;
35         int cnt;
36         struct tifm_dev *sock;
37
38         if (!class_device_get(&fm->cdev))
39                 return;
40         spin_lock_irqsave(&fm->lock, flags);
41         for (cnt = 0; cnt < fm->max_sockets; cnt++) {
42                 if (fm->sockets[cnt] && (fm->remove_mask & (1 << cnt))) {
43                         printk(KERN_INFO DRIVER_NAME
44                                ": demand removing card from socket %d\n", cnt);
45                         sock = fm->sockets[cnt];
46                         fm->sockets[cnt] = NULL;
47                         fm->remove_mask &= ~(1 << cnt);
48
49                         writel(0x0e00, sock->addr + SOCK_CONTROL);
50
51                         writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
52                                 fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
53                         writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
54                                 fm->addr + FM_SET_INTERRUPT_ENABLE);
55
56                         spin_unlock_irqrestore(&fm->lock, flags);
57                         device_unregister(&sock->dev);
58                         spin_lock_irqsave(&fm->lock, flags);
59                 }
60         }
61         spin_unlock_irqrestore(&fm->lock, flags);
62         class_device_put(&fm->cdev);
63 }
64
65 static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id)
66 {
67         struct tifm_adapter *fm = dev_id;
68         struct tifm_dev *sock;
69         unsigned int irq_status;
70         unsigned int sock_irq_status, cnt;
71
72         spin_lock(&fm->lock);
73         irq_status = readl(fm->addr + FM_INTERRUPT_STATUS);
74         if (irq_status == 0 || irq_status == (~0)) {
75                 spin_unlock(&fm->lock);
76                 return IRQ_NONE;
77         }
78
79         if (irq_status & TIFM_IRQ_ENABLE) {
80                 writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
81
82                 for (cnt = 0; cnt <  fm->max_sockets; cnt++) {
83                         sock = fm->sockets[cnt];
84                         sock_irq_status = (irq_status >> cnt) &
85                                         (TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK);
86
87                         if (sock) {
88                                 if (sock_irq_status)
89                                         sock->signal_irq(sock, sock_irq_status);
90
91                                 if (irq_status & (1 << cnt))
92                                         fm->remove_mask |= 1 << cnt;
93                         } else {
94                                 if (irq_status & (1 << cnt))
95                                         fm->insert_mask |= 1 << cnt;
96                         }
97                 }
98         }
99         writel(irq_status, fm->addr + FM_INTERRUPT_STATUS);
100
101         if (!fm->inhibit_new_cards) {
102                 if (!fm->remove_mask && !fm->insert_mask) {
103                         writel(TIFM_IRQ_ENABLE,
104                                 fm->addr + FM_SET_INTERRUPT_ENABLE);
105                 } else {
106                         queue_work(fm->wq, &fm->media_remover);
107                         queue_work(fm->wq, &fm->media_inserter);
108                 }
109         }
110
111         spin_unlock(&fm->lock);
112         return IRQ_HANDLED;
113 }
114
115 static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, int is_x2)
116 {
117         unsigned int s_state;
118         int cnt;
119
120         writel(0x0e00, sock_addr + SOCK_CONTROL);
121
122         for (cnt = 0; cnt < 100; cnt++) {
123                 if (!(TIFM_SOCK_STATE_POWERED &
124                                 readl(sock_addr + SOCK_PRESENT_STATE)))
125                         break;
126                 msleep(10);
127         }
128
129         s_state = readl(sock_addr + SOCK_PRESENT_STATE);
130         if (!(TIFM_SOCK_STATE_OCCUPIED & s_state))
131                 return FM_NULL;
132
133         if (is_x2) {
134                 writel((s_state & 7) | 0x0c00, sock_addr + SOCK_CONTROL);
135         } else {
136                 // SmartMedia cards need extra 40 msec
137                 if (((readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7) == 1)
138                         msleep(40);
139                 writel(readl(sock_addr + SOCK_CONTROL) | TIFM_CTRL_LED,
140                        sock_addr + SOCK_CONTROL);
141                 msleep(10);
142                 writel((s_state & 0x7) | 0x0c00 | TIFM_CTRL_LED,
143                         sock_addr + SOCK_CONTROL);
144         }
145
146         for (cnt = 0; cnt < 100; cnt++) {
147                 if ((TIFM_SOCK_STATE_POWERED &
148                                 readl(sock_addr + SOCK_PRESENT_STATE)))
149                         break;
150                 msleep(10);
151         }
152
153         if (!is_x2)
154                 writel(readl(sock_addr + SOCK_CONTROL) & (~TIFM_CTRL_LED),
155                        sock_addr + SOCK_CONTROL);
156
157         return (readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7;
158 }
159
160 inline static char __iomem *
161 tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num)
162 {
163         return base_addr + ((sock_num + 1) << 10);
164 }
165
166 static void tifm_7xx1_insert_media(struct work_struct *work)
167 {
168         struct tifm_adapter *fm =
169                 container_of(work, struct tifm_adapter, media_inserter);
170         unsigned long flags;
171         tifm_media_id media_id;
172         char *card_name = "xx";
173         int cnt, ok_to_register;
174         unsigned int insert_mask;
175         struct tifm_dev *new_sock = NULL;
176
177         if (!class_device_get(&fm->cdev))
178                 return;
179         spin_lock_irqsave(&fm->lock, flags);
180         insert_mask = fm->insert_mask;
181         fm->insert_mask = 0;
182         if (fm->inhibit_new_cards) {
183                 spin_unlock_irqrestore(&fm->lock, flags);
184                 class_device_put(&fm->cdev);
185                 return;
186         }
187         spin_unlock_irqrestore(&fm->lock, flags);
188
189         for (cnt = 0; cnt < fm->max_sockets; cnt++) {
190                 if (!(insert_mask & (1 << cnt)))
191                         continue;
192
193                 media_id = tifm_7xx1_toggle_sock_power(tifm_7xx1_sock_addr(fm->addr, cnt),
194                                                        fm->max_sockets == 2);
195                 if (media_id) {
196                         ok_to_register = 0;
197                         new_sock = tifm_alloc_device(fm);
198                         if (new_sock) {
199                                 new_sock->addr = tifm_7xx1_sock_addr(fm->addr,
200                                                                         cnt);
201                                 new_sock->media_id = media_id;
202                                 new_sock->socket_id = cnt;
203                                 switch (media_id) {
204                                 case 1:
205                                         card_name = "xd";
206                                         break;
207                                 case 2:
208                                         card_name = "ms";
209                                         break;
210                                 case 3:
211                                         card_name = "sd";
212                                         break;
213                                 default:
214                                         break;
215                                 }
216                                 snprintf(new_sock->dev.bus_id, BUS_ID_SIZE,
217                                         "tifm_%s%u:%u", card_name, fm->id, cnt);
218                                 printk(KERN_INFO DRIVER_NAME
219                                         ": %s card detected in socket %d\n",
220                                         card_name, cnt);
221                                 spin_lock_irqsave(&fm->lock, flags);
222                                 if (!fm->sockets[cnt]) {
223                                         fm->sockets[cnt] = new_sock;
224                                         ok_to_register = 1;
225                                 }
226                                 spin_unlock_irqrestore(&fm->lock, flags);
227                                 if (!ok_to_register ||
228                                             device_register(&new_sock->dev)) {
229                                         spin_lock_irqsave(&fm->lock, flags);
230                                         fm->sockets[cnt] = NULL;
231                                         spin_unlock_irqrestore(&fm->lock,
232                                                                 flags);
233                                         tifm_free_device(&new_sock->dev);
234                                 }
235                         }
236                 }
237                 writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
238                        fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
239                 writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
240                        fm->addr + FM_SET_INTERRUPT_ENABLE);
241         }
242
243         writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
244         class_device_put(&fm->cdev);
245 }
246
247 static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state)
248 {
249         struct tifm_adapter *fm = pci_get_drvdata(dev);
250         unsigned long flags;
251
252         spin_lock_irqsave(&fm->lock, flags);
253         fm->inhibit_new_cards = 1;
254         fm->remove_mask = 0xf;
255         fm->insert_mask = 0;
256         writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
257         spin_unlock_irqrestore(&fm->lock, flags);
258         flush_workqueue(fm->wq);
259
260         tifm_7xx1_remove_media(&fm->media_remover);
261
262         pci_set_power_state(dev, PCI_D3hot);
263         pci_disable_device(dev);
264         pci_save_state(dev);
265         return 0;
266 }
267
268 static int tifm_7xx1_resume(struct pci_dev *dev)
269 {
270         struct tifm_adapter *fm = pci_get_drvdata(dev);
271         unsigned long flags;
272
273         pci_restore_state(dev);
274         pci_enable_device(dev);
275         pci_set_power_state(dev, PCI_D0);
276         pci_set_master(dev);
277
278         spin_lock_irqsave(&fm->lock, flags);
279         fm->inhibit_new_cards = 0;
280         writel(TIFM_IRQ_SETALL, fm->addr + FM_INTERRUPT_STATUS);
281         writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
282         writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SETALLSOCK,
283                 fm->addr + FM_SET_INTERRUPT_ENABLE);
284         fm->insert_mask = 0xf;
285         spin_unlock_irqrestore(&fm->lock, flags);
286         return 0;
287 }
288
289 static int tifm_7xx1_probe(struct pci_dev *dev,
290                         const struct pci_device_id *dev_id)
291 {
292         struct tifm_adapter *fm;
293         int pci_dev_busy = 0;
294         int rc;
295
296         rc = pci_set_dma_mask(dev, DMA_32BIT_MASK);
297         if (rc)
298                 return rc;
299
300         rc = pci_enable_device(dev);
301         if (rc)
302                 return rc;
303
304         pci_set_master(dev);
305
306         rc = pci_request_regions(dev, DRIVER_NAME);
307         if (rc) {
308                 pci_dev_busy = 1;
309                 goto err_out;
310         }
311
312         pci_intx(dev, 1);
313
314         fm = tifm_alloc_adapter();
315         if (!fm) {
316                 rc = -ENOMEM;
317                 goto err_out_int;
318         }
319
320         fm->dev = &dev->dev;
321         fm->max_sockets = (dev->device == 0x803B) ? 2 : 4;
322         fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->max_sockets,
323                                 GFP_KERNEL);
324         if (!fm->sockets)
325                 goto err_out_free;
326
327         INIT_WORK(&fm->media_inserter, tifm_7xx1_insert_media);
328         INIT_WORK(&fm->media_remover, tifm_7xx1_remove_media);
329         fm->eject = tifm_7xx1_eject;
330         pci_set_drvdata(dev, fm);
331
332         fm->addr = ioremap(pci_resource_start(dev, 0),
333                                 pci_resource_len(dev, 0));
334         if (!fm->addr)
335                 goto err_out_free;
336
337         rc = request_irq(dev->irq, tifm_7xx1_isr, SA_SHIRQ, DRIVER_NAME, fm);
338         if (rc)
339                 goto err_out_unmap;
340
341         rc = tifm_add_adapter(fm);
342         if (rc)
343                 goto err_out_irq;
344
345         writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
346         writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SETALLSOCK,
347                 fm->addr + FM_SET_INTERRUPT_ENABLE);
348
349         fm->insert_mask = 0xf;
350
351         return 0;
352
353 err_out_irq:
354         free_irq(dev->irq, fm);
355 err_out_unmap:
356         iounmap(fm->addr);
357 err_out_free:
358         pci_set_drvdata(dev, NULL);
359         tifm_free_adapter(fm);
360 err_out_int:
361         pci_intx(dev, 0);
362         pci_release_regions(dev);
363 err_out:
364         if (!pci_dev_busy)
365                 pci_disable_device(dev);
366         return rc;
367 }
368
369 static void tifm_7xx1_remove(struct pci_dev *dev)
370 {
371         struct tifm_adapter *fm = pci_get_drvdata(dev);
372         unsigned long flags;
373
374         spin_lock_irqsave(&fm->lock, flags);
375         fm->inhibit_new_cards = 1;
376         fm->remove_mask = 0xf;
377         fm->insert_mask = 0;
378         writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
379         spin_unlock_irqrestore(&fm->lock, flags);
380
381         flush_workqueue(fm->wq);
382
383         tifm_7xx1_remove_media(&fm->media_remover);
384
385         writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
386         free_irq(dev->irq, fm);
387
388         tifm_remove_adapter(fm);
389
390         pci_set_drvdata(dev, NULL);
391
392         iounmap(fm->addr);
393         pci_intx(dev, 0);
394         pci_release_regions(dev);
395
396         pci_disable_device(dev);
397         tifm_free_adapter(fm);
398 }
399
400 static struct pci_device_id tifm_7xx1_pci_tbl [] = {
401         { PCI_VENDOR_ID_TI, 0x8033, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
402           0 }, /* xx21 - the one I have */
403         { PCI_VENDOR_ID_TI, 0x803B, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
404           0 }, /* xx12 - should be also supported */
405         { }
406 };
407
408 static struct pci_driver tifm_7xx1_driver = {
409         .name = DRIVER_NAME,
410         .id_table = tifm_7xx1_pci_tbl,
411         .probe = tifm_7xx1_probe,
412         .remove = tifm_7xx1_remove,
413         .suspend = tifm_7xx1_suspend,
414         .resume = tifm_7xx1_resume,
415 };
416
417 static int __init tifm_7xx1_init(void)
418 {
419         return pci_register_driver(&tifm_7xx1_driver);
420 }
421
422 static void __exit tifm_7xx1_exit(void)
423 {
424         pci_unregister_driver(&tifm_7xx1_driver);
425 }
426
427 MODULE_AUTHOR("Alex Dubov");
428 MODULE_DESCRIPTION("TI FlashMedia host driver");
429 MODULE_LICENSE("GPL");
430 MODULE_DEVICE_TABLE(pci, tifm_7xx1_pci_tbl);
431 MODULE_VERSION(DRIVER_VERSION);
432
433 module_init(tifm_7xx1_init);
434 module_exit(tifm_7xx1_exit);