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