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 /* Maximum number of entries is 4 */ 243 unsigned char new_ids[4]; 244 DECLARE_COMPLETION_ONSTACK(finish_resume); 245 246 if (WARN_ON(fm->num_sockets > ARRAY_SIZE(new_ids))) 247 return -ENXIO; 248 249 pci_set_power_state(dev, PCI_D0); 250 pci_restore_state(dev); 251 rc = pci_enable_device(dev); 252 if (rc) 253 return rc; 254 pci_set_master(dev); 255 256 dev_dbg(&dev->dev, "resuming host\n"); 257 258 for (rc = 0; rc < fm->num_sockets; rc++) 259 new_ids[rc] = tifm_7xx1_toggle_sock_power( 260 tifm_7xx1_sock_addr(fm->addr, rc)); 261 spin_lock_irqsave(&fm->lock, flags); 262 for (rc = 0; rc < fm->num_sockets; rc++) { 263 if (fm->sockets[rc]) { 264 if (fm->sockets[rc]->type == new_ids[rc]) 265 good_sockets |= 1 << rc; 266 else 267 bad_sockets |= 1 << rc; 268 } 269 } 270 271 writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), 272 fm->addr + FM_SET_INTERRUPT_ENABLE); 273 dev_dbg(&dev->dev, "change sets on resume: good %x, bad %x\n", 274 good_sockets, bad_sockets); 275 276 fm->socket_change_set = 0; 277 if (good_sockets) { 278 fm->finish_me = &finish_resume; 279 spin_unlock_irqrestore(&fm->lock, flags); 280 timeout = wait_for_completion_timeout(&finish_resume, HZ); 281 dev_dbg(&dev->dev, "wait returned %lu\n", timeout); 282 writel(TIFM_IRQ_FIFOMASK(good_sockets) 283 | TIFM_IRQ_CARDMASK(good_sockets), 284 fm->addr + FM_CLEAR_INTERRUPT_ENABLE); 285 writel(TIFM_IRQ_FIFOMASK(good_sockets) 286 | TIFM_IRQ_CARDMASK(good_sockets), 287 fm->addr + FM_SET_INTERRUPT_ENABLE); 288 spin_lock_irqsave(&fm->lock, flags); 289 fm->finish_me = NULL; 290 fm->socket_change_set ^= good_sockets & fm->socket_change_set; 291 } 292 293 fm->socket_change_set |= bad_sockets; 294 if (fm->socket_change_set) 295 tifm_queue_work(&fm->media_switcher); 296 297 spin_unlock_irqrestore(&fm->lock, flags); 298 writel(TIFM_IRQ_ENABLE, 299 fm->addr + FM_SET_INTERRUPT_ENABLE); 300 301 return 0; 302 } 303 304 #else 305 306 #define tifm_7xx1_suspend NULL 307 #define tifm_7xx1_resume NULL 308 309 #endif /* CONFIG_PM */ 310 311 static int tifm_7xx1_dummy_has_ms_pif(struct tifm_adapter *fm, 312 struct tifm_dev *sock) 313 { 314 return 0; 315 } 316 317 static int tifm_7xx1_has_ms_pif(struct tifm_adapter *fm, struct tifm_dev *sock) 318 { 319 if (((fm->num_sockets == 4) && (sock->socket_id == 2)) 320 || ((fm->num_sockets == 2) && (sock->socket_id == 0))) 321 return 1; 322 323 return 0; 324 } 325 326 static int tifm_7xx1_probe(struct pci_dev *dev, 327 const struct pci_device_id *dev_id) 328 { 329 struct tifm_adapter *fm; 330 int pci_dev_busy = 0; 331 int rc; 332 333 rc = pci_set_dma_mask(dev, DMA_BIT_MASK(32)); 334 if (rc) 335 return rc; 336 337 rc = pci_enable_device(dev); 338 if (rc) 339 return rc; 340 341 pci_set_master(dev); 342 343 rc = pci_request_regions(dev, DRIVER_NAME); 344 if (rc) { 345 pci_dev_busy = 1; 346 goto err_out; 347 } 348 349 pci_intx(dev, 1); 350 351 fm = tifm_alloc_adapter(dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM 352 ? 4 : 2, &dev->dev); 353 if (!fm) { 354 rc = -ENOMEM; 355 goto err_out_int; 356 } 357 358 INIT_WORK(&fm->media_switcher, tifm_7xx1_switch_media); 359 fm->eject = tifm_7xx1_eject; 360 fm->has_ms_pif = tifm_7xx1_has_ms_pif; 361 pci_set_drvdata(dev, fm); 362 363 fm->addr = pci_ioremap_bar(dev, 0); 364 if (!fm->addr) { 365 rc = -ENODEV; 366 goto err_out_free; 367 } 368 369 rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm); 370 if (rc) 371 goto err_out_unmap; 372 373 rc = tifm_add_adapter(fm); 374 if (rc) 375 goto err_out_irq; 376 377 writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), 378 fm->addr + FM_CLEAR_INTERRUPT_ENABLE); 379 writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), 380 fm->addr + FM_SET_INTERRUPT_ENABLE); 381 return 0; 382 383 err_out_irq: 384 free_irq(dev->irq, fm); 385 err_out_unmap: 386 iounmap(fm->addr); 387 err_out_free: 388 tifm_free_adapter(fm); 389 err_out_int: 390 pci_intx(dev, 0); 391 pci_release_regions(dev); 392 err_out: 393 if (!pci_dev_busy) 394 pci_disable_device(dev); 395 return rc; 396 } 397 398 static void tifm_7xx1_remove(struct pci_dev *dev) 399 { 400 struct tifm_adapter *fm = pci_get_drvdata(dev); 401 int cnt; 402 403 fm->eject = tifm_7xx1_dummy_eject; 404 fm->has_ms_pif = tifm_7xx1_dummy_has_ms_pif; 405 writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); 406 free_irq(dev->irq, fm); 407 408 tifm_remove_adapter(fm); 409 410 for (cnt = 0; cnt < fm->num_sockets; cnt++) 411 tifm_7xx1_sock_power_off(tifm_7xx1_sock_addr(fm->addr, cnt)); 412 413 iounmap(fm->addr); 414 pci_intx(dev, 0); 415 pci_release_regions(dev); 416 417 pci_disable_device(dev); 418 tifm_free_adapter(fm); 419 } 420 421 static const struct pci_device_id tifm_7xx1_pci_tbl[] = { 422 { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11_FM, PCI_ANY_ID, 423 PCI_ANY_ID, 0, 0, 0 }, /* xx21 - the one I have */ 424 { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX12_FM, PCI_ANY_ID, 425 PCI_ANY_ID, 0, 0, 0 }, 426 { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX20_FM, PCI_ANY_ID, 427 PCI_ANY_ID, 0, 0, 0 }, 428 { } 429 }; 430 431 static struct pci_driver tifm_7xx1_driver = { 432 .name = DRIVER_NAME, 433 .id_table = tifm_7xx1_pci_tbl, 434 .probe = tifm_7xx1_probe, 435 .remove = tifm_7xx1_remove, 436 .suspend = tifm_7xx1_suspend, 437 .resume = tifm_7xx1_resume, 438 }; 439 440 module_pci_driver(tifm_7xx1_driver); 441 MODULE_AUTHOR("Alex Dubov"); 442 MODULE_DESCRIPTION("TI FlashMedia host driver"); 443 MODULE_LICENSE("GPL"); 444 MODULE_DEVICE_TABLE(pci, tifm_7xx1_pci_tbl); 445 MODULE_VERSION(DRIVER_VERSION); 446