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