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 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 307 static int tifm_7xx1_dummy_has_ms_pif(struct tifm_adapter *fm, 308 struct tifm_dev *sock) 309 { 310 return 0; 311 } 312 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 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 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 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