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 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; 36 tifm_queue_work(&fm->media_switcher); 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) 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 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 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, 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 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 244 pci_set_power_state(dev, PCI_D0); 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), 267 fm->addr + FM_SET_INTERRUPT_ENABLE); 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), 279 fm->addr + FM_CLEAR_INTERRUPT_ENABLE); 280 writel(TIFM_IRQ_FIFOMASK(good_sockets) 281 | TIFM_IRQ_CARDMASK(good_sockets), 282 fm->addr + FM_SET_INTERRUPT_ENABLE); 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) 290 tifm_queue_work(&fm->media_switcher); 291 292 spin_unlock_irqrestore(&fm->lock, flags); 293 writel(TIFM_IRQ_ENABLE, 294 fm->addr + FM_SET_INTERRUPT_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 346 fm = tifm_alloc_adapter(dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM 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), 371 fm->addr + FM_CLEAR_INTERRUPT_ENABLE); 372 writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), 373 fm->addr + FM_SET_INTERRUPT_ENABLE); 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; 399 writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); 400 mmiowb(); 401 free_irq(dev->irq, fm); 402 403 tifm_remove_adapter(fm); 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 [] = { 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 static int __init tifm_7xx1_init(void) 438 { 439 return pci_register_driver(&tifm_7xx1_driver); 440 } 441 442 static void __exit tifm_7xx1_exit(void) 443 { 444 pci_unregister_driver(&tifm_7xx1_driver); 445 } 446 447 MODULE_AUTHOR("Alex Dubov"); 448 MODULE_DESCRIPTION("TI FlashMedia host driver"); 449 MODULE_LICENSE("GPL"); 450 MODULE_DEVICE_TABLE(pci, tifm_7xx1_pci_tbl); 451 MODULE_VERSION(DRIVER_VERSION); 452 453 module_init(tifm_7xx1_init); 454 module_exit(tifm_7xx1_exit); 455