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