X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=drivers%2Fmisc%2Ftifm_7xx1.c;h=54380da343a530ab4a4513eef7501d9e52b6d487;hb=70ec75c5b8e0bda7a16fb387f91e08545f379a0e;hp=eafa5575f312fe859ddeadc58c7d62158dcb7028;hpb=88de1b2fed2bbe9eb1b7310195be84cf143efb4f;p=~andy%2Flinux diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index eafa5575f31..54380da343a 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c @@ -11,7 +11,6 @@ #include #include -#include #define DRIVER_NAME "tifm_7xx1" #define DRIVER_VERSION "0.8" @@ -41,8 +40,7 @@ static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id) { struct tifm_adapter *fm = dev_id; struct tifm_dev *sock; - unsigned int irq_status; - unsigned int cnt; + unsigned int irq_status, cnt; spin_lock(&fm->lock); irq_status = readl(fm->addr + FM_INTERRUPT_STATUS); @@ -107,7 +105,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) { @@ -124,6 +123,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) { @@ -134,17 +139,17 @@ 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; - int cnt; - struct tifm_dev *sock; - unsigned int socket_change_set; + unsigned int socket_change_set, cnt; spin_lock_irqsave(&fm->lock, flags); 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) { @@ -159,13 +164,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); + fm->dev.bus_id, 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); @@ -208,8 +214,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); @@ -329,7 +343,7 @@ static int tifm_7xx1_probe(struct pci_dev *dev, if (!fm->addr) 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; @@ -360,6 +374,7 @@ 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; writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); @@ -368,6 +383,9 @@ static void tifm_7xx1_remove(struct pci_dev *dev) tifm_remove_adapter(fm); + for (cnt = 0; cnt < fm->num_sockets; cnt++) + tifm_7xx1_sock_power_off(tifm_7xx1_sock_addr(fm->addr, cnt)); + pci_set_drvdata(dev, NULL); iounmap(fm->addr);