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