diff options
Diffstat (limited to 'drivers/misc/tifm_7xx1.c')
| -rw-r--r-- | drivers/misc/tifm_7xx1.c | 77 |
1 files changed, 52 insertions, 25 deletions
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index 1ba6c085419..a606c8901e1 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c @@ -11,6 +11,7 @@ #include <linux/tifm.h> #include <linux/dma-mapping.h> +#include <linux/module.h> #define DRIVER_NAME "tifm_7xx1" #define DRIVER_VERSION "0.8" @@ -105,7 +106,8 @@ static unsigned char tifm_7xx1_toggle_sock_power(char __iomem *sock_addr) == TIFM_TYPE_XD) msleep(40); - writel((s_state & 7) | 0x0c00, sock_addr + SOCK_CONTROL); + writel((s_state & TIFM_CTRL_POWER_MASK) | 0x0c00, + sock_addr + SOCK_CONTROL); /* wait for power to stabilize */ msleep(20); for (cnt = 16; cnt <= 256; cnt <<= 1) { @@ -122,6 +124,12 @@ static unsigned char tifm_7xx1_toggle_sock_power(char __iomem *sock_addr) return (readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7; } +inline static void tifm_7xx1_sock_power_off(char __iomem *sock_addr) +{ + writel((~TIFM_CTRL_POWER_MASK) & readl(sock_addr + SOCK_CONTROL), + sock_addr + SOCK_CONTROL); +} + inline static char __iomem * tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num) { @@ -133,6 +141,7 @@ static void tifm_7xx1_switch_media(struct work_struct *work) struct tifm_adapter *fm = container_of(work, struct tifm_adapter, media_switcher); struct tifm_dev *sock; + char __iomem *sock_addr; unsigned long flags; unsigned char media_id; unsigned int socket_change_set, cnt; @@ -141,7 +150,7 @@ static void tifm_7xx1_switch_media(struct work_struct *work) socket_change_set = fm->socket_change_set; fm->socket_change_set = 0; - dev_dbg(fm->cdev.dev, "checking media set %x\n", + dev_dbg(fm->dev.parent, "checking media set %x\n", socket_change_set); if (!socket_change_set) { @@ -156,13 +165,14 @@ static void tifm_7xx1_switch_media(struct work_struct *work) if (sock) { printk(KERN_INFO "%s : demand removing card from socket %u:%u\n", - fm->cdev.class_id, fm->id, cnt); + dev_name(&fm->dev), fm->id, cnt); fm->sockets[cnt] = NULL; + sock_addr = sock->addr; spin_unlock_irqrestore(&fm->lock, flags); device_unregister(&sock->dev); spin_lock_irqsave(&fm->lock, flags); - writel(0x0e00, tifm_7xx1_sock_addr(fm->addr, cnt) - + SOCK_CONTROL); + tifm_7xx1_sock_power_off(sock_addr); + writel(0x0e00, sock_addr + SOCK_CONTROL); } spin_unlock_irqrestore(&fm->lock, flags); @@ -205,8 +215,16 @@ static void tifm_7xx1_switch_media(struct work_struct *work) static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state) { + struct tifm_adapter *fm = pci_get_drvdata(dev); + int cnt; + dev_dbg(&dev->dev, "suspending host\n"); + for (cnt = 0; cnt < fm->num_sockets; cnt++) { + if (fm->sockets[cnt]) + tifm_7xx1_sock_power_off(fm->sockets[cnt]->addr); + } + pci_save_state(dev); pci_enable_wake(dev, pci_choose_state(dev, state), 0); pci_disable_device(dev); @@ -285,6 +303,21 @@ static int tifm_7xx1_resume(struct pci_dev *dev) #endif /* CONFIG_PM */ +static int tifm_7xx1_dummy_has_ms_pif(struct tifm_adapter *fm, + struct tifm_dev *sock) +{ + return 0; +} + +static int tifm_7xx1_has_ms_pif(struct tifm_adapter *fm, struct tifm_dev *sock) +{ + if (((fm->num_sockets == 4) && (sock->socket_id == 2)) + || ((fm->num_sockets == 2) && (sock->socket_id == 0))) + return 1; + + return 0; +} + static int tifm_7xx1_probe(struct pci_dev *dev, const struct pci_device_id *dev_id) { @@ -292,7 +325,7 @@ static int tifm_7xx1_probe(struct pci_dev *dev, int pci_dev_busy = 0; int rc; - rc = pci_set_dma_mask(dev, DMA_32BIT_MASK); + rc = pci_set_dma_mask(dev, DMA_BIT_MASK(32)); if (rc) return rc; @@ -319,14 +352,16 @@ static int tifm_7xx1_probe(struct pci_dev *dev, INIT_WORK(&fm->media_switcher, tifm_7xx1_switch_media); fm->eject = tifm_7xx1_eject; + fm->has_ms_pif = tifm_7xx1_has_ms_pif; pci_set_drvdata(dev, fm); - fm->addr = ioremap(pci_resource_start(dev, 0), - pci_resource_len(dev, 0)); - if (!fm->addr) + fm->addr = pci_ioremap_bar(dev, 0); + if (!fm->addr) { + rc = -ENODEV; goto err_out_free; + } - rc = request_irq(dev->irq, tifm_7xx1_isr, SA_SHIRQ, DRIVER_NAME, fm); + rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm); if (rc) goto err_out_unmap; @@ -335,6 +370,8 @@ static int tifm_7xx1_probe(struct pci_dev *dev, goto err_out_irq; writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), + fm->addr + FM_CLEAR_INTERRUPT_ENABLE); + writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), fm->addr + FM_SET_INTERRUPT_ENABLE); return 0; @@ -343,7 +380,6 @@ err_out_irq: err_out_unmap: iounmap(fm->addr); err_out_free: - pci_set_drvdata(dev, NULL); tifm_free_adapter(fm); err_out_int: pci_intx(dev, 0); @@ -357,15 +393,18 @@ err_out: static void tifm_7xx1_remove(struct pci_dev *dev) { struct tifm_adapter *fm = pci_get_drvdata(dev); + int cnt; fm->eject = tifm_7xx1_dummy_eject; + fm->has_ms_pif = tifm_7xx1_dummy_has_ms_pif; writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); mmiowb(); free_irq(dev->irq, fm); tifm_remove_adapter(fm); - pci_set_drvdata(dev, NULL); + for (cnt = 0; cnt < fm->num_sockets; cnt++) + tifm_7xx1_sock_power_off(tifm_7xx1_sock_addr(fm->addr, cnt)); iounmap(fm->addr); pci_intx(dev, 0); @@ -394,21 +433,9 @@ static struct pci_driver tifm_7xx1_driver = { .resume = tifm_7xx1_resume, }; -static int __init tifm_7xx1_init(void) -{ - return pci_register_driver(&tifm_7xx1_driver); -} - -static void __exit tifm_7xx1_exit(void) -{ - pci_unregister_driver(&tifm_7xx1_driver); -} - +module_pci_driver(tifm_7xx1_driver); MODULE_AUTHOR("Alex Dubov"); MODULE_DESCRIPTION("TI FlashMedia host driver"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, tifm_7xx1_pci_tbl); MODULE_VERSION(DRIVER_VERSION); - -module_init(tifm_7xx1_init); -module_exit(tifm_7xx1_exit); |
