From 055b8224140e7a7515bf8113ce675d58abffedf1 Mon Sep 17 00:00:00 2001 From: Alex Dubov Date: Tue, 1 May 2007 20:14:55 -0700 Subject: [PATCH] disable socket power in adapter driver instead of media one Socket power must be fully controlled by adapter driver. This also prevents unnecessary power-off of the socket when media driver is unloaded, yet media remains in the socket. Signed-off-by: Alex Dubov Signed-off-by: Pierre Ossman --- drivers/misc/tifm_7xx1.c | 27 ++++++++++++++++++++++++--- drivers/mmc/host/tifm_sd.c | 13 +------------ include/linux/tifm.h | 1 + 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index 1ba6c08541..c08ad8f823 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c @@ -105,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) { @@ -122,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) { @@ -133,6 +140,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; @@ -158,11 +166,12 @@ static void tifm_7xx1_switch_media(struct work_struct *work) "%s : demand removing card from socket %u:%u\n", fm->cdev.class_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); @@ -205,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); @@ -357,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); @@ -365,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); diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c index 7511f961c6..8b736e9684 100644 --- a/drivers/mmc/host/tifm_sd.c +++ b/drivers/mmc/host/tifm_sd.c @@ -1021,10 +1021,6 @@ static void tifm_sd_remove(struct tifm_dev *sock) mmc_remove_host(mmc); dev_dbg(&sock->dev, "after remove\n"); - /* The meaning of the bit majority in this constant is unknown. */ - writel(0xfff8 & readl(sock->addr + SOCK_CONTROL), - sock->addr + SOCK_CONTROL); - mmc_free_host(mmc); } @@ -1032,14 +1028,7 @@ static void tifm_sd_remove(struct tifm_dev *sock) static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state) { - struct mmc_host *mmc = tifm_get_drvdata(sock); - int rc; - - rc = mmc_suspend_host(mmc, state); - /* The meaning of the bit majority in this constant is unknown. */ - writel(0xfff8 & readl(sock->addr + SOCK_CONTROL), - sock->addr + SOCK_CONTROL); - return rc; + return mmc_suspend_host(tifm_get_drvdata(sock), state); } static int tifm_sd_resume(struct tifm_dev *sock) diff --git a/include/linux/tifm.h b/include/linux/tifm.h index 2a19698260..6b3a31805c 100644 --- a/include/linux/tifm.h +++ b/include/linux/tifm.h @@ -63,6 +63,7 @@ enum { #define TIFM_CTRL_LED 0x00000040 #define TIFM_CTRL_FAST_CLK 0x00000100 +#define TIFM_CTRL_POWER_MASK 0x00000007 #define TIFM_SOCK_STATE_OCCUPIED 0x00000008 #define TIFM_SOCK_STATE_POWERED 0x00000080 -- 2.39.5