Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  tifm_7xx1.c - TI FlashMedia driver
0004  *
0005  *  Copyright (C) 2006 Alex Dubov <oakad@yahoo.com>
0006  */
0007 
0008 #include <linux/tifm.h>
0009 #include <linux/dma-mapping.h>
0010 #include <linux/module.h>
0011 
0012 #define DRIVER_NAME "tifm_7xx1"
0013 #define DRIVER_VERSION "0.8"
0014 
0015 #define TIFM_IRQ_ENABLE           0x80000000
0016 #define TIFM_IRQ_SOCKMASK(x)      (x)
0017 #define TIFM_IRQ_CARDMASK(x)      ((x) << 8)
0018 #define TIFM_IRQ_FIFOMASK(x)      ((x) << 16)
0019 #define TIFM_IRQ_SETALL           0xffffffff
0020 
0021 static void tifm_7xx1_dummy_eject(struct tifm_adapter *fm,
0022                   struct tifm_dev *sock)
0023 {
0024 }
0025 
0026 static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock)
0027 {
0028     unsigned long flags;
0029 
0030     spin_lock_irqsave(&fm->lock, flags);
0031     fm->socket_change_set |= 1 << sock->socket_id;
0032     tifm_queue_work(&fm->media_switcher);
0033     spin_unlock_irqrestore(&fm->lock, flags);
0034 }
0035 
0036 static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id)
0037 {
0038     struct tifm_adapter *fm = dev_id;
0039     struct tifm_dev *sock;
0040     unsigned int irq_status, cnt;
0041 
0042     spin_lock(&fm->lock);
0043     irq_status = readl(fm->addr + FM_INTERRUPT_STATUS);
0044     if (irq_status == 0 || irq_status == (~0)) {
0045         spin_unlock(&fm->lock);
0046         return IRQ_NONE;
0047     }
0048 
0049     if (irq_status & TIFM_IRQ_ENABLE) {
0050         writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
0051 
0052         for (cnt = 0; cnt < fm->num_sockets; cnt++) {
0053             sock = fm->sockets[cnt];
0054             if (sock) {
0055                 if ((irq_status >> cnt) & TIFM_IRQ_FIFOMASK(1))
0056                     sock->data_event(sock);
0057                 if ((irq_status >> cnt) & TIFM_IRQ_CARDMASK(1))
0058                     sock->card_event(sock);
0059             }
0060         }
0061 
0062         fm->socket_change_set |= irq_status
0063                      & ((1 << fm->num_sockets) - 1);
0064     }
0065     writel(irq_status, fm->addr + FM_INTERRUPT_STATUS);
0066 
0067     if (fm->finish_me)
0068         complete_all(fm->finish_me);
0069     else if (!fm->socket_change_set)
0070         writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
0071     else
0072         tifm_queue_work(&fm->media_switcher);
0073 
0074     spin_unlock(&fm->lock);
0075     return IRQ_HANDLED;
0076 }
0077 
0078 static unsigned char tifm_7xx1_toggle_sock_power(char __iomem *sock_addr)
0079 {
0080     unsigned int s_state;
0081     int cnt;
0082 
0083     writel(0x0e00, sock_addr + SOCK_CONTROL);
0084 
0085     for (cnt = 16; cnt <= 256; cnt <<= 1) {
0086         if (!(TIFM_SOCK_STATE_POWERED
0087               & readl(sock_addr + SOCK_PRESENT_STATE)))
0088             break;
0089 
0090         msleep(cnt);
0091     }
0092 
0093     s_state = readl(sock_addr + SOCK_PRESENT_STATE);
0094     if (!(TIFM_SOCK_STATE_OCCUPIED & s_state))
0095         return 0;
0096 
0097     writel(readl(sock_addr + SOCK_CONTROL) | TIFM_CTRL_LED,
0098            sock_addr + SOCK_CONTROL);
0099 
0100     /* xd needs some extra time before power on */
0101     if (((readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7)
0102         == TIFM_TYPE_XD)
0103         msleep(40);
0104 
0105     writel((s_state & TIFM_CTRL_POWER_MASK) | 0x0c00,
0106            sock_addr + SOCK_CONTROL);
0107     /* wait for power to stabilize */
0108     msleep(20);
0109     for (cnt = 16; cnt <= 256; cnt <<= 1) {
0110         if ((TIFM_SOCK_STATE_POWERED
0111              & readl(sock_addr + SOCK_PRESENT_STATE)))
0112             break;
0113 
0114         msleep(cnt);
0115     }
0116 
0117     writel(readl(sock_addr + SOCK_CONTROL) & (~TIFM_CTRL_LED),
0118            sock_addr + SOCK_CONTROL);
0119 
0120     return (readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7;
0121 }
0122 
0123 inline static void tifm_7xx1_sock_power_off(char __iomem *sock_addr)
0124 {
0125     writel((~TIFM_CTRL_POWER_MASK) & readl(sock_addr + SOCK_CONTROL),
0126            sock_addr + SOCK_CONTROL);
0127 }
0128 
0129 inline static char __iomem *
0130 tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num)
0131 {
0132     return base_addr + ((sock_num + 1) << 10);
0133 }
0134 
0135 static void tifm_7xx1_switch_media(struct work_struct *work)
0136 {
0137     struct tifm_adapter *fm = container_of(work, struct tifm_adapter,
0138                            media_switcher);
0139     struct tifm_dev *sock;
0140     char __iomem *sock_addr;
0141     unsigned long flags;
0142     unsigned char media_id;
0143     unsigned int socket_change_set, cnt;
0144 
0145     spin_lock_irqsave(&fm->lock, flags);
0146     socket_change_set = fm->socket_change_set;
0147     fm->socket_change_set = 0;
0148 
0149     dev_dbg(fm->dev.parent, "checking media set %x\n",
0150         socket_change_set);
0151 
0152     if (!socket_change_set) {
0153         spin_unlock_irqrestore(&fm->lock, flags);
0154         return;
0155     }
0156 
0157     for (cnt = 0; cnt < fm->num_sockets; cnt++) {
0158         if (!(socket_change_set & (1 << cnt)))
0159             continue;
0160         sock = fm->sockets[cnt];
0161         if (sock) {
0162             printk(KERN_INFO
0163                    "%s : demand removing card from socket %u:%u\n",
0164                    dev_name(&fm->dev), fm->id, cnt);
0165             fm->sockets[cnt] = NULL;
0166             sock_addr = sock->addr;
0167             spin_unlock_irqrestore(&fm->lock, flags);
0168             device_unregister(&sock->dev);
0169             spin_lock_irqsave(&fm->lock, flags);
0170             tifm_7xx1_sock_power_off(sock_addr);
0171             writel(0x0e00, sock_addr + SOCK_CONTROL);
0172         }
0173 
0174         spin_unlock_irqrestore(&fm->lock, flags);
0175 
0176         media_id = tifm_7xx1_toggle_sock_power(
0177                 tifm_7xx1_sock_addr(fm->addr, cnt));
0178 
0179         // tifm_alloc_device will check if media_id is valid
0180         sock = tifm_alloc_device(fm, cnt, media_id);
0181         if (sock) {
0182             sock->addr = tifm_7xx1_sock_addr(fm->addr, cnt);
0183 
0184             if (!device_register(&sock->dev)) {
0185                 spin_lock_irqsave(&fm->lock, flags);
0186                 if (!fm->sockets[cnt]) {
0187                     fm->sockets[cnt] = sock;
0188                     sock = NULL;
0189                 }
0190                 spin_unlock_irqrestore(&fm->lock, flags);
0191             }
0192             if (sock)
0193                 tifm_free_device(&sock->dev);
0194         }
0195         spin_lock_irqsave(&fm->lock, flags);
0196     }
0197 
0198     writel(TIFM_IRQ_FIFOMASK(socket_change_set)
0199            | TIFM_IRQ_CARDMASK(socket_change_set),
0200            fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
0201 
0202     writel(TIFM_IRQ_FIFOMASK(socket_change_set)
0203            | TIFM_IRQ_CARDMASK(socket_change_set),
0204            fm->addr + FM_SET_INTERRUPT_ENABLE);
0205 
0206     writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
0207     spin_unlock_irqrestore(&fm->lock, flags);
0208 }
0209 
0210 static int __maybe_unused tifm_7xx1_suspend(struct device *dev_d)
0211 {
0212     struct pci_dev *dev = to_pci_dev(dev_d);
0213     struct tifm_adapter *fm = pci_get_drvdata(dev);
0214     int cnt;
0215 
0216     dev_dbg(&dev->dev, "suspending host\n");
0217 
0218     for (cnt = 0; cnt < fm->num_sockets; cnt++) {
0219         if (fm->sockets[cnt])
0220             tifm_7xx1_sock_power_off(fm->sockets[cnt]->addr);
0221     }
0222 
0223     device_wakeup_disable(dev_d);
0224     return 0;
0225 }
0226 
0227 static int __maybe_unused tifm_7xx1_resume(struct device *dev_d)
0228 {
0229     struct pci_dev *dev = to_pci_dev(dev_d);
0230     struct tifm_adapter *fm = pci_get_drvdata(dev);
0231     int rc;
0232     unsigned long timeout;
0233     unsigned int good_sockets = 0, bad_sockets = 0;
0234     unsigned long flags;
0235     /* Maximum number of entries is 4 */
0236     unsigned char new_ids[4];
0237     DECLARE_COMPLETION_ONSTACK(finish_resume);
0238 
0239     if (WARN_ON(fm->num_sockets > ARRAY_SIZE(new_ids)))
0240         return -ENXIO;
0241 
0242     pci_set_master(dev);
0243 
0244     dev_dbg(&dev->dev, "resuming host\n");
0245 
0246     for (rc = 0; rc < fm->num_sockets; rc++)
0247         new_ids[rc] = tifm_7xx1_toggle_sock_power(
0248                     tifm_7xx1_sock_addr(fm->addr, rc));
0249     spin_lock_irqsave(&fm->lock, flags);
0250     for (rc = 0; rc < fm->num_sockets; rc++) {
0251         if (fm->sockets[rc]) {
0252             if (fm->sockets[rc]->type == new_ids[rc])
0253                 good_sockets |= 1 << rc;
0254             else
0255                 bad_sockets |= 1 << rc;
0256         }
0257     }
0258 
0259     writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
0260            fm->addr + FM_SET_INTERRUPT_ENABLE);
0261     dev_dbg(&dev->dev, "change sets on resume: good %x, bad %x\n",
0262         good_sockets, bad_sockets);
0263 
0264     fm->socket_change_set = 0;
0265     if (good_sockets) {
0266         fm->finish_me = &finish_resume;
0267         spin_unlock_irqrestore(&fm->lock, flags);
0268         timeout = wait_for_completion_timeout(&finish_resume, HZ);
0269         dev_dbg(&dev->dev, "wait returned %lu\n", timeout);
0270         writel(TIFM_IRQ_FIFOMASK(good_sockets)
0271                | TIFM_IRQ_CARDMASK(good_sockets),
0272                fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
0273         writel(TIFM_IRQ_FIFOMASK(good_sockets)
0274                | TIFM_IRQ_CARDMASK(good_sockets),
0275                fm->addr + FM_SET_INTERRUPT_ENABLE);
0276         spin_lock_irqsave(&fm->lock, flags);
0277         fm->finish_me = NULL;
0278         fm->socket_change_set ^= good_sockets & fm->socket_change_set;
0279     }
0280 
0281     fm->socket_change_set |= bad_sockets;
0282     if (fm->socket_change_set)
0283         tifm_queue_work(&fm->media_switcher);
0284 
0285     spin_unlock_irqrestore(&fm->lock, flags);
0286     writel(TIFM_IRQ_ENABLE,
0287            fm->addr + FM_SET_INTERRUPT_ENABLE);
0288 
0289     return 0;
0290 }
0291 
0292 static int tifm_7xx1_dummy_has_ms_pif(struct tifm_adapter *fm,
0293                       struct tifm_dev *sock)
0294 {
0295     return 0;
0296 }
0297 
0298 static int tifm_7xx1_has_ms_pif(struct tifm_adapter *fm, struct tifm_dev *sock)
0299 {
0300     if (((fm->num_sockets == 4) && (sock->socket_id == 2))
0301         || ((fm->num_sockets == 2) && (sock->socket_id == 0)))
0302         return 1;
0303 
0304     return 0;
0305 }
0306 
0307 static int tifm_7xx1_probe(struct pci_dev *dev,
0308                const struct pci_device_id *dev_id)
0309 {
0310     struct tifm_adapter *fm;
0311     int pci_dev_busy = 0;
0312     int rc;
0313 
0314     rc = dma_set_mask(&dev->dev, DMA_BIT_MASK(32));
0315     if (rc)
0316         return rc;
0317 
0318     rc = pci_enable_device(dev);
0319     if (rc)
0320         return rc;
0321 
0322     pci_set_master(dev);
0323 
0324     rc = pci_request_regions(dev, DRIVER_NAME);
0325     if (rc) {
0326         pci_dev_busy = 1;
0327         goto err_out;
0328     }
0329 
0330     pci_intx(dev, 1);
0331 
0332     fm = tifm_alloc_adapter(dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM
0333                 ? 4 : 2, &dev->dev);
0334     if (!fm) {
0335         rc = -ENOMEM;
0336         goto err_out_int;
0337     }
0338 
0339     INIT_WORK(&fm->media_switcher, tifm_7xx1_switch_media);
0340     fm->eject = tifm_7xx1_eject;
0341     fm->has_ms_pif = tifm_7xx1_has_ms_pif;
0342     pci_set_drvdata(dev, fm);
0343 
0344     fm->addr = pci_ioremap_bar(dev, 0);
0345     if (!fm->addr) {
0346         rc = -ENODEV;
0347         goto err_out_free;
0348     }
0349 
0350     rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm);
0351     if (rc)
0352         goto err_out_unmap;
0353 
0354     rc = tifm_add_adapter(fm);
0355     if (rc)
0356         goto err_out_irq;
0357 
0358     writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
0359            fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
0360     writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
0361            fm->addr + FM_SET_INTERRUPT_ENABLE);
0362     return 0;
0363 
0364 err_out_irq:
0365     free_irq(dev->irq, fm);
0366 err_out_unmap:
0367     iounmap(fm->addr);
0368 err_out_free:
0369     tifm_free_adapter(fm);
0370 err_out_int:
0371     pci_intx(dev, 0);
0372     pci_release_regions(dev);
0373 err_out:
0374     if (!pci_dev_busy)
0375         pci_disable_device(dev);
0376     return rc;
0377 }
0378 
0379 static void tifm_7xx1_remove(struct pci_dev *dev)
0380 {
0381     struct tifm_adapter *fm = pci_get_drvdata(dev);
0382     int cnt;
0383 
0384     fm->eject = tifm_7xx1_dummy_eject;
0385     fm->has_ms_pif = tifm_7xx1_dummy_has_ms_pif;
0386     writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
0387     free_irq(dev->irq, fm);
0388 
0389     tifm_remove_adapter(fm);
0390 
0391     for (cnt = 0; cnt < fm->num_sockets; cnt++)
0392         tifm_7xx1_sock_power_off(tifm_7xx1_sock_addr(fm->addr, cnt));
0393 
0394     iounmap(fm->addr);
0395     pci_intx(dev, 0);
0396     pci_release_regions(dev);
0397 
0398     pci_disable_device(dev);
0399     tifm_free_adapter(fm);
0400 }
0401 
0402 static const struct pci_device_id tifm_7xx1_pci_tbl[] = {
0403     { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11_FM, PCI_ANY_ID,
0404       PCI_ANY_ID, 0, 0, 0 }, /* xx21 - the one I have */
0405         { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX12_FM, PCI_ANY_ID,
0406       PCI_ANY_ID, 0, 0, 0 },
0407     { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX20_FM, PCI_ANY_ID,
0408       PCI_ANY_ID, 0, 0, 0 },
0409     { }
0410 };
0411 
0412 static SIMPLE_DEV_PM_OPS(tifm_7xx1_pm_ops, tifm_7xx1_suspend, tifm_7xx1_resume);
0413 
0414 static struct pci_driver tifm_7xx1_driver = {
0415     .name = DRIVER_NAME,
0416     .id_table = tifm_7xx1_pci_tbl,
0417     .probe = tifm_7xx1_probe,
0418     .remove = tifm_7xx1_remove,
0419     .driver.pm = &tifm_7xx1_pm_ops,
0420 };
0421 
0422 module_pci_driver(tifm_7xx1_driver);
0423 MODULE_AUTHOR("Alex Dubov");
0424 MODULE_DESCRIPTION("TI FlashMedia host driver");
0425 MODULE_LICENSE("GPL");
0426 MODULE_DEVICE_TABLE(pci, tifm_7xx1_pci_tbl);
0427 MODULE_VERSION(DRIVER_VERSION);