tifm_7xx1.c (10967B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * tifm_7xx1.c - TI FlashMedia driver 4 * 5 * Copyright (C) 2006 Alex Dubov <oakad@yahoo.com> 6 */ 7 8#include <linux/tifm.h> 9#include <linux/dma-mapping.h> 10#include <linux/module.h> 11 12#define DRIVER_NAME "tifm_7xx1" 13#define DRIVER_VERSION "0.8" 14 15#define TIFM_IRQ_ENABLE 0x80000000 16#define TIFM_IRQ_SOCKMASK(x) (x) 17#define TIFM_IRQ_CARDMASK(x) ((x) << 8) 18#define TIFM_IRQ_FIFOMASK(x) ((x) << 16) 19#define TIFM_IRQ_SETALL 0xffffffff 20 21static void tifm_7xx1_dummy_eject(struct tifm_adapter *fm, 22 struct tifm_dev *sock) 23{ 24} 25 26static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock) 27{ 28 unsigned long flags; 29 30 spin_lock_irqsave(&fm->lock, flags); 31 fm->socket_change_set |= 1 << sock->socket_id; 32 tifm_queue_work(&fm->media_switcher); 33 spin_unlock_irqrestore(&fm->lock, flags); 34} 35 36static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id) 37{ 38 struct tifm_adapter *fm = dev_id; 39 struct tifm_dev *sock; 40 unsigned int irq_status, cnt; 41 42 spin_lock(&fm->lock); 43 irq_status = readl(fm->addr + FM_INTERRUPT_STATUS); 44 if (irq_status == 0 || irq_status == (~0)) { 45 spin_unlock(&fm->lock); 46 return IRQ_NONE; 47 } 48 49 if (irq_status & TIFM_IRQ_ENABLE) { 50 writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); 51 52 for (cnt = 0; cnt < fm->num_sockets; cnt++) { 53 sock = fm->sockets[cnt]; 54 if (sock) { 55 if ((irq_status >> cnt) & TIFM_IRQ_FIFOMASK(1)) 56 sock->data_event(sock); 57 if ((irq_status >> cnt) & TIFM_IRQ_CARDMASK(1)) 58 sock->card_event(sock); 59 } 60 } 61 62 fm->socket_change_set |= irq_status 63 & ((1 << fm->num_sockets) - 1); 64 } 65 writel(irq_status, fm->addr + FM_INTERRUPT_STATUS); 66 67 if (fm->finish_me) 68 complete_all(fm->finish_me); 69 else if (!fm->socket_change_set) 70 writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE); 71 else 72 tifm_queue_work(&fm->media_switcher); 73 74 spin_unlock(&fm->lock); 75 return IRQ_HANDLED; 76} 77 78static unsigned char tifm_7xx1_toggle_sock_power(char __iomem *sock_addr) 79{ 80 unsigned int s_state; 81 int cnt; 82 83 writel(0x0e00, sock_addr + SOCK_CONTROL); 84 85 for (cnt = 16; cnt <= 256; cnt <<= 1) { 86 if (!(TIFM_SOCK_STATE_POWERED 87 & readl(sock_addr + SOCK_PRESENT_STATE))) 88 break; 89 90 msleep(cnt); 91 } 92 93 s_state = readl(sock_addr + SOCK_PRESENT_STATE); 94 if (!(TIFM_SOCK_STATE_OCCUPIED & s_state)) 95 return 0; 96 97 writel(readl(sock_addr + SOCK_CONTROL) | TIFM_CTRL_LED, 98 sock_addr + SOCK_CONTROL); 99 100 /* xd needs some extra time before power on */ 101 if (((readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7) 102 == TIFM_TYPE_XD) 103 msleep(40); 104 105 writel((s_state & TIFM_CTRL_POWER_MASK) | 0x0c00, 106 sock_addr + SOCK_CONTROL); 107 /* wait for power to stabilize */ 108 msleep(20); 109 for (cnt = 16; cnt <= 256; cnt <<= 1) { 110 if ((TIFM_SOCK_STATE_POWERED 111 & readl(sock_addr + SOCK_PRESENT_STATE))) 112 break; 113 114 msleep(cnt); 115 } 116 117 writel(readl(sock_addr + SOCK_CONTROL) & (~TIFM_CTRL_LED), 118 sock_addr + SOCK_CONTROL); 119 120 return (readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7; 121} 122 123inline static void tifm_7xx1_sock_power_off(char __iomem *sock_addr) 124{ 125 writel((~TIFM_CTRL_POWER_MASK) & readl(sock_addr + SOCK_CONTROL), 126 sock_addr + SOCK_CONTROL); 127} 128 129inline static char __iomem * 130tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num) 131{ 132 return base_addr + ((sock_num + 1) << 10); 133} 134 135static void tifm_7xx1_switch_media(struct work_struct *work) 136{ 137 struct tifm_adapter *fm = container_of(work, struct tifm_adapter, 138 media_switcher); 139 struct tifm_dev *sock; 140 char __iomem *sock_addr; 141 unsigned long flags; 142 unsigned char media_id; 143 unsigned int socket_change_set, cnt; 144 145 spin_lock_irqsave(&fm->lock, flags); 146 socket_change_set = fm->socket_change_set; 147 fm->socket_change_set = 0; 148 149 dev_dbg(fm->dev.parent, "checking media set %x\n", 150 socket_change_set); 151 152 if (!socket_change_set) { 153 spin_unlock_irqrestore(&fm->lock, flags); 154 return; 155 } 156 157 for (cnt = 0; cnt < fm->num_sockets; cnt++) { 158 if (!(socket_change_set & (1 << cnt))) 159 continue; 160 sock = fm->sockets[cnt]; 161 if (sock) { 162 printk(KERN_INFO 163 "%s : demand removing card from socket %u:%u\n", 164 dev_name(&fm->dev), fm->id, cnt); 165 fm->sockets[cnt] = NULL; 166 sock_addr = sock->addr; 167 spin_unlock_irqrestore(&fm->lock, flags); 168 device_unregister(&sock->dev); 169 spin_lock_irqsave(&fm->lock, flags); 170 tifm_7xx1_sock_power_off(sock_addr); 171 writel(0x0e00, sock_addr + SOCK_CONTROL); 172 } 173 174 spin_unlock_irqrestore(&fm->lock, flags); 175 176 media_id = tifm_7xx1_toggle_sock_power( 177 tifm_7xx1_sock_addr(fm->addr, cnt)); 178 179 // tifm_alloc_device will check if media_id is valid 180 sock = tifm_alloc_device(fm, cnt, media_id); 181 if (sock) { 182 sock->addr = tifm_7xx1_sock_addr(fm->addr, cnt); 183 184 if (!device_register(&sock->dev)) { 185 spin_lock_irqsave(&fm->lock, flags); 186 if (!fm->sockets[cnt]) { 187 fm->sockets[cnt] = sock; 188 sock = NULL; 189 } 190 spin_unlock_irqrestore(&fm->lock, flags); 191 } 192 if (sock) 193 tifm_free_device(&sock->dev); 194 } 195 spin_lock_irqsave(&fm->lock, flags); 196 } 197 198 writel(TIFM_IRQ_FIFOMASK(socket_change_set) 199 | TIFM_IRQ_CARDMASK(socket_change_set), 200 fm->addr + FM_CLEAR_INTERRUPT_ENABLE); 201 202 writel(TIFM_IRQ_FIFOMASK(socket_change_set) 203 | TIFM_IRQ_CARDMASK(socket_change_set), 204 fm->addr + FM_SET_INTERRUPT_ENABLE); 205 206 writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE); 207 spin_unlock_irqrestore(&fm->lock, flags); 208} 209 210static int __maybe_unused tifm_7xx1_suspend(struct device *dev_d) 211{ 212 struct pci_dev *dev = to_pci_dev(dev_d); 213 struct tifm_adapter *fm = pci_get_drvdata(dev); 214 int cnt; 215 216 dev_dbg(&dev->dev, "suspending host\n"); 217 218 for (cnt = 0; cnt < fm->num_sockets; cnt++) { 219 if (fm->sockets[cnt]) 220 tifm_7xx1_sock_power_off(fm->sockets[cnt]->addr); 221 } 222 223 device_wakeup_disable(dev_d); 224 return 0; 225} 226 227static int __maybe_unused tifm_7xx1_resume(struct device *dev_d) 228{ 229 struct pci_dev *dev = to_pci_dev(dev_d); 230 struct tifm_adapter *fm = pci_get_drvdata(dev); 231 int rc; 232 unsigned long timeout; 233 unsigned int good_sockets = 0, bad_sockets = 0; 234 unsigned long flags; 235 /* Maximum number of entries is 4 */ 236 unsigned char new_ids[4]; 237 DECLARE_COMPLETION_ONSTACK(finish_resume); 238 239 if (WARN_ON(fm->num_sockets > ARRAY_SIZE(new_ids))) 240 return -ENXIO; 241 242 pci_set_master(dev); 243 244 dev_dbg(&dev->dev, "resuming host\n"); 245 246 for (rc = 0; rc < fm->num_sockets; rc++) 247 new_ids[rc] = tifm_7xx1_toggle_sock_power( 248 tifm_7xx1_sock_addr(fm->addr, rc)); 249 spin_lock_irqsave(&fm->lock, flags); 250 for (rc = 0; rc < fm->num_sockets; rc++) { 251 if (fm->sockets[rc]) { 252 if (fm->sockets[rc]->type == new_ids[rc]) 253 good_sockets |= 1 << rc; 254 else 255 bad_sockets |= 1 << rc; 256 } 257 } 258 259 writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), 260 fm->addr + FM_SET_INTERRUPT_ENABLE); 261 dev_dbg(&dev->dev, "change sets on resume: good %x, bad %x\n", 262 good_sockets, bad_sockets); 263 264 fm->socket_change_set = 0; 265 if (good_sockets) { 266 fm->finish_me = &finish_resume; 267 spin_unlock_irqrestore(&fm->lock, flags); 268 timeout = wait_for_completion_timeout(&finish_resume, HZ); 269 dev_dbg(&dev->dev, "wait returned %lu\n", timeout); 270 writel(TIFM_IRQ_FIFOMASK(good_sockets) 271 | TIFM_IRQ_CARDMASK(good_sockets), 272 fm->addr + FM_CLEAR_INTERRUPT_ENABLE); 273 writel(TIFM_IRQ_FIFOMASK(good_sockets) 274 | TIFM_IRQ_CARDMASK(good_sockets), 275 fm->addr + FM_SET_INTERRUPT_ENABLE); 276 spin_lock_irqsave(&fm->lock, flags); 277 fm->finish_me = NULL; 278 fm->socket_change_set ^= good_sockets & fm->socket_change_set; 279 } 280 281 fm->socket_change_set |= bad_sockets; 282 if (fm->socket_change_set) 283 tifm_queue_work(&fm->media_switcher); 284 285 spin_unlock_irqrestore(&fm->lock, flags); 286 writel(TIFM_IRQ_ENABLE, 287 fm->addr + FM_SET_INTERRUPT_ENABLE); 288 289 return 0; 290} 291 292static int tifm_7xx1_dummy_has_ms_pif(struct tifm_adapter *fm, 293 struct tifm_dev *sock) 294{ 295 return 0; 296} 297 298static int tifm_7xx1_has_ms_pif(struct tifm_adapter *fm, struct tifm_dev *sock) 299{ 300 if (((fm->num_sockets == 4) && (sock->socket_id == 2)) 301 || ((fm->num_sockets == 2) && (sock->socket_id == 0))) 302 return 1; 303 304 return 0; 305} 306 307static int tifm_7xx1_probe(struct pci_dev *dev, 308 const struct pci_device_id *dev_id) 309{ 310 struct tifm_adapter *fm; 311 int pci_dev_busy = 0; 312 int rc; 313 314 rc = dma_set_mask(&dev->dev, DMA_BIT_MASK(32)); 315 if (rc) 316 return rc; 317 318 rc = pci_enable_device(dev); 319 if (rc) 320 return rc; 321 322 pci_set_master(dev); 323 324 rc = pci_request_regions(dev, DRIVER_NAME); 325 if (rc) { 326 pci_dev_busy = 1; 327 goto err_out; 328 } 329 330 pci_intx(dev, 1); 331 332 fm = tifm_alloc_adapter(dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM 333 ? 4 : 2, &dev->dev); 334 if (!fm) { 335 rc = -ENOMEM; 336 goto err_out_int; 337 } 338 339 INIT_WORK(&fm->media_switcher, tifm_7xx1_switch_media); 340 fm->eject = tifm_7xx1_eject; 341 fm->has_ms_pif = tifm_7xx1_has_ms_pif; 342 pci_set_drvdata(dev, fm); 343 344 fm->addr = pci_ioremap_bar(dev, 0); 345 if (!fm->addr) { 346 rc = -ENODEV; 347 goto err_out_free; 348 } 349 350 rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm); 351 if (rc) 352 goto err_out_unmap; 353 354 rc = tifm_add_adapter(fm); 355 if (rc) 356 goto err_out_irq; 357 358 writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), 359 fm->addr + FM_CLEAR_INTERRUPT_ENABLE); 360 writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), 361 fm->addr + FM_SET_INTERRUPT_ENABLE); 362 return 0; 363 364err_out_irq: 365 free_irq(dev->irq, fm); 366err_out_unmap: 367 iounmap(fm->addr); 368err_out_free: 369 tifm_free_adapter(fm); 370err_out_int: 371 pci_intx(dev, 0); 372 pci_release_regions(dev); 373err_out: 374 if (!pci_dev_busy) 375 pci_disable_device(dev); 376 return rc; 377} 378 379static void tifm_7xx1_remove(struct pci_dev *dev) 380{ 381 struct tifm_adapter *fm = pci_get_drvdata(dev); 382 int cnt; 383 384 fm->eject = tifm_7xx1_dummy_eject; 385 fm->has_ms_pif = tifm_7xx1_dummy_has_ms_pif; 386 writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); 387 free_irq(dev->irq, fm); 388 389 tifm_remove_adapter(fm); 390 391 for (cnt = 0; cnt < fm->num_sockets; cnt++) 392 tifm_7xx1_sock_power_off(tifm_7xx1_sock_addr(fm->addr, cnt)); 393 394 iounmap(fm->addr); 395 pci_intx(dev, 0); 396 pci_release_regions(dev); 397 398 pci_disable_device(dev); 399 tifm_free_adapter(fm); 400} 401 402static const struct pci_device_id tifm_7xx1_pci_tbl[] = { 403 { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11_FM, PCI_ANY_ID, 404 PCI_ANY_ID, 0, 0, 0 }, /* xx21 - the one I have */ 405 { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX12_FM, PCI_ANY_ID, 406 PCI_ANY_ID, 0, 0, 0 }, 407 { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX20_FM, PCI_ANY_ID, 408 PCI_ANY_ID, 0, 0, 0 }, 409 { } 410}; 411 412static SIMPLE_DEV_PM_OPS(tifm_7xx1_pm_ops, tifm_7xx1_suspend, tifm_7xx1_resume); 413 414static struct pci_driver tifm_7xx1_driver = { 415 .name = DRIVER_NAME, 416 .id_table = tifm_7xx1_pci_tbl, 417 .probe = tifm_7xx1_probe, 418 .remove = tifm_7xx1_remove, 419 .driver.pm = &tifm_7xx1_pm_ops, 420}; 421 422module_pci_driver(tifm_7xx1_driver); 423MODULE_AUTHOR("Alex Dubov"); 424MODULE_DESCRIPTION("TI FlashMedia host driver"); 425MODULE_LICENSE("GPL"); 426MODULE_DEVICE_TABLE(pci, tifm_7xx1_pci_tbl); 427MODULE_VERSION(DRIVER_VERSION);