Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tifm_7xx1.c
Go to the documentation of this file.
1 /*
2  * tifm_7xx1.c - TI FlashMedia driver
3  *
4  * Copyright (C) 2006 Alex Dubov <[email protected]>
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 
25 static void tifm_7xx1_dummy_eject(struct tifm_adapter *fm,
26  struct tifm_dev *sock)
27 {
28 }
29 
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;
37  spin_unlock_irqrestore(&fm->lock, flags);
38 }
39 
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)
73  else if (!fm->socket_change_set)
74  writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
75  else
77 
78  spin_unlock(&fm->lock);
79  return IRQ_HANDLED;
80 }
81 
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) {
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) {
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 
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 *
134 tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num)
135 {
136  return base_addr + ((sock_num + 1) << 10);
137 }
138 
139 static void tifm_7xx1_switch_media(struct work_struct *work)
140 {
141  struct tifm_adapter *fm = container_of(work, struct tifm_adapter,
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) {
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),
205 
206  writel(TIFM_IRQ_FIFOMASK(socket_change_set)
207  | TIFM_IRQ_CARDMASK(socket_change_set),
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 
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 
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 int good_sockets = 0, bad_sockets = 0;
240  unsigned long flags;
241  unsigned char new_ids[fm->num_sockets];
242  DECLARE_COMPLETION_ONSTACK(finish_resume);
243 
245  pci_restore_state(dev);
246  rc = pci_enable_device(dev);
247  if (rc)
248  return rc;
249  pci_set_master(dev);
250 
251  dev_dbg(&dev->dev, "resuming host\n");
252 
253  for (rc = 0; rc < fm->num_sockets; rc++)
254  new_ids[rc] = tifm_7xx1_toggle_sock_power(
255  tifm_7xx1_sock_addr(fm->addr, rc));
256  spin_lock_irqsave(&fm->lock, flags);
257  for (rc = 0; rc < fm->num_sockets; rc++) {
258  if (fm->sockets[rc]) {
259  if (fm->sockets[rc]->type == new_ids[rc])
260  good_sockets |= 1 << rc;
261  else
262  bad_sockets |= 1 << rc;
263  }
264  }
265 
266  writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
268  dev_dbg(&dev->dev, "change sets on resume: good %x, bad %x\n",
269  good_sockets, bad_sockets);
270 
271  fm->socket_change_set = 0;
272  if (good_sockets) {
273  fm->finish_me = &finish_resume;
274  spin_unlock_irqrestore(&fm->lock, flags);
275  rc = wait_for_completion_timeout(&finish_resume, HZ);
276  dev_dbg(&dev->dev, "wait returned %d\n", rc);
277  writel(TIFM_IRQ_FIFOMASK(good_sockets)
278  | TIFM_IRQ_CARDMASK(good_sockets),
280  writel(TIFM_IRQ_FIFOMASK(good_sockets)
281  | TIFM_IRQ_CARDMASK(good_sockets),
283  spin_lock_irqsave(&fm->lock, flags);
284  fm->finish_me = NULL;
285  fm->socket_change_set ^= good_sockets & fm->socket_change_set;
286  }
287 
288  fm->socket_change_set |= bad_sockets;
289  if (fm->socket_change_set)
291 
292  spin_unlock_irqrestore(&fm->lock, flags);
293  writel(TIFM_IRQ_ENABLE,
295 
296  return 0;
297 }
298 
299 #else
300 
301 #define tifm_7xx1_suspend NULL
302 #define tifm_7xx1_resume NULL
303 
304 #endif /* CONFIG_PM */
305 
306 static int tifm_7xx1_dummy_has_ms_pif(struct tifm_adapter *fm,
307  struct tifm_dev *sock)
308 {
309  return 0;
310 }
311 
312 static int tifm_7xx1_has_ms_pif(struct tifm_adapter *fm, struct tifm_dev *sock)
313 {
314  if (((fm->num_sockets == 4) && (sock->socket_id == 2))
315  || ((fm->num_sockets == 2) && (sock->socket_id == 0)))
316  return 1;
317 
318  return 0;
319 }
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_BIT_MASK(32));
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 
347  ? 4 : 2, &dev->dev);
348  if (!fm) {
349  rc = -ENOMEM;
350  goto err_out_int;
351  }
352 
353  INIT_WORK(&fm->media_switcher, tifm_7xx1_switch_media);
354  fm->eject = tifm_7xx1_eject;
355  fm->has_ms_pif = tifm_7xx1_has_ms_pif;
356  pci_set_drvdata(dev, fm);
357 
358  fm->addr = pci_ioremap_bar(dev, 0);
359  if (!fm->addr)
360  goto err_out_free;
361 
362  rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm);
363  if (rc)
364  goto err_out_unmap;
365 
366  rc = tifm_add_adapter(fm);
367  if (rc)
368  goto err_out_irq;
369 
370  writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
372  writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
374  return 0;
375 
376 err_out_irq:
377  free_irq(dev->irq, fm);
378 err_out_unmap:
379  iounmap(fm->addr);
380 err_out_free:
381  pci_set_drvdata(dev, NULL);
382  tifm_free_adapter(fm);
383 err_out_int:
384  pci_intx(dev, 0);
385  pci_release_regions(dev);
386 err_out:
387  if (!pci_dev_busy)
388  pci_disable_device(dev);
389  return rc;
390 }
391 
392 static void tifm_7xx1_remove(struct pci_dev *dev)
393 {
394  struct tifm_adapter *fm = pci_get_drvdata(dev);
395  int cnt;
396 
397  fm->eject = tifm_7xx1_dummy_eject;
398  fm->has_ms_pif = tifm_7xx1_dummy_has_ms_pif;
400  mmiowb();
401  free_irq(dev->irq, fm);
402 
404 
405  for (cnt = 0; cnt < fm->num_sockets; cnt++)
406  tifm_7xx1_sock_power_off(tifm_7xx1_sock_addr(fm->addr, cnt));
407 
408  pci_set_drvdata(dev, NULL);
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 struct pci_device_id tifm_7xx1_pci_tbl [] = {
420  PCI_ANY_ID, 0, 0, 0 }, /* xx21 - the one I have */
422  PCI_ANY_ID, 0, 0, 0 },
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);