diff options
| author | Alex Dubov <oakad@yahoo.com> | 2007-05-01 23:14:55 -0400 |
|---|---|---|
| committer | Pierre Ossman <drzeus@drzeus.cx> | 2007-05-08 16:41:47 -0400 |
| commit | 055b8224140e7a7515bf8113ce675d58abffedf1 (patch) | |
| tree | 32528d9920e9819079fce8e0d43f06d75c28da01 | |
| parent | 36f021b579d195cdc5fa6f3e2bab198b4bf70643 (diff) | |
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 <oakad@yahoo.com>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
| -rw-r--r-- | drivers/misc/tifm_7xx1.c | 27 | ||||
| -rw-r--r-- | drivers/mmc/host/tifm_sd.c | 13 | ||||
| -rw-r--r-- | 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 1ba6c085419a..c08ad8f823d2 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) | |||
| 105 | == TIFM_TYPE_XD) | 105 | == TIFM_TYPE_XD) |
| 106 | msleep(40); | 106 | msleep(40); |
| 107 | 107 | ||
| 108 | writel((s_state & 7) | 0x0c00, sock_addr + SOCK_CONTROL); | 108 | writel((s_state & TIFM_CTRL_POWER_MASK) | 0x0c00, |
| 109 | sock_addr + SOCK_CONTROL); | ||
| 109 | /* wait for power to stabilize */ | 110 | /* wait for power to stabilize */ |
| 110 | msleep(20); | 111 | msleep(20); |
| 111 | for (cnt = 16; cnt <= 256; cnt <<= 1) { | 112 | for (cnt = 16; cnt <= 256; cnt <<= 1) { |
| @@ -122,6 +123,12 @@ static unsigned char tifm_7xx1_toggle_sock_power(char __iomem *sock_addr) | |||
| 122 | return (readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7; | 123 | return (readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7; |
| 123 | } | 124 | } |
| 124 | 125 | ||
| 126 | inline static void tifm_7xx1_sock_power_off(char __iomem *sock_addr) | ||
| 127 | { | ||
| 128 | writel((~TIFM_CTRL_POWER_MASK) & readl(sock_addr + SOCK_CONTROL), | ||
| 129 | sock_addr + SOCK_CONTROL); | ||
| 130 | } | ||
| 131 | |||
| 125 | inline static char __iomem * | 132 | inline static char __iomem * |
| 126 | tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num) | 133 | tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num) |
| 127 | { | 134 | { |
| @@ -133,6 +140,7 @@ static void tifm_7xx1_switch_media(struct work_struct *work) | |||
| 133 | struct tifm_adapter *fm = container_of(work, struct tifm_adapter, | 140 | struct tifm_adapter *fm = container_of(work, struct tifm_adapter, |
| 134 | media_switcher); | 141 | media_switcher); |
| 135 | struct tifm_dev *sock; | 142 | struct tifm_dev *sock; |
| 143 | char __iomem *sock_addr; | ||
| 136 | unsigned long flags; | 144 | unsigned long flags; |
| 137 | unsigned char media_id; | 145 | unsigned char media_id; |
| 138 | unsigned int socket_change_set, cnt; | 146 | unsigned int socket_change_set, cnt; |
| @@ -158,11 +166,12 @@ static void tifm_7xx1_switch_media(struct work_struct *work) | |||
| 158 | "%s : demand removing card from socket %u:%u\n", | 166 | "%s : demand removing card from socket %u:%u\n", |
| 159 | fm->cdev.class_id, fm->id, cnt); | 167 | fm->cdev.class_id, fm->id, cnt); |
| 160 | fm->sockets[cnt] = NULL; | 168 | fm->sockets[cnt] = NULL; |
| 169 | sock_addr = sock->addr; | ||
| 161 | spin_unlock_irqrestore(&fm->lock, flags); | 170 | spin_unlock_irqrestore(&fm->lock, flags); |
| 162 | device_unregister(&sock->dev); | 171 | device_unregister(&sock->dev); |
| 163 | spin_lock_irqsave(&fm->lock, flags); | 172 | spin_lock_irqsave(&fm->lock, flags); |
| 164 | writel(0x0e00, tifm_7xx1_sock_addr(fm->addr, cnt) | 173 | tifm_7xx1_sock_power_off(sock_addr); |
| 165 | + SOCK_CONTROL); | 174 | writel(0x0e00, sock_addr + SOCK_CONTROL); |
| 166 | } | 175 | } |
| 167 | 176 | ||
| 168 | spin_unlock_irqrestore(&fm->lock, flags); | 177 | spin_unlock_irqrestore(&fm->lock, flags); |
| @@ -205,8 +214,16 @@ static void tifm_7xx1_switch_media(struct work_struct *work) | |||
| 205 | 214 | ||
| 206 | static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state) | 215 | static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state) |
| 207 | { | 216 | { |
| 217 | struct tifm_adapter *fm = pci_get_drvdata(dev); | ||
| 218 | int cnt; | ||
| 219 | |||
| 208 | dev_dbg(&dev->dev, "suspending host\n"); | 220 | dev_dbg(&dev->dev, "suspending host\n"); |
| 209 | 221 | ||
| 222 | for (cnt = 0; cnt < fm->num_sockets; cnt++) { | ||
| 223 | if (fm->sockets[cnt]) | ||
| 224 | tifm_7xx1_sock_power_off(fm->sockets[cnt]->addr); | ||
| 225 | } | ||
| 226 | |||
| 210 | pci_save_state(dev); | 227 | pci_save_state(dev); |
| 211 | pci_enable_wake(dev, pci_choose_state(dev, state), 0); | 228 | pci_enable_wake(dev, pci_choose_state(dev, state), 0); |
| 212 | pci_disable_device(dev); | 229 | pci_disable_device(dev); |
| @@ -357,6 +374,7 @@ err_out: | |||
| 357 | static void tifm_7xx1_remove(struct pci_dev *dev) | 374 | static void tifm_7xx1_remove(struct pci_dev *dev) |
| 358 | { | 375 | { |
| 359 | struct tifm_adapter *fm = pci_get_drvdata(dev); | 376 | struct tifm_adapter *fm = pci_get_drvdata(dev); |
| 377 | int cnt; | ||
| 360 | 378 | ||
| 361 | fm->eject = tifm_7xx1_dummy_eject; | 379 | fm->eject = tifm_7xx1_dummy_eject; |
| 362 | writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); | 380 | writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); |
| @@ -365,6 +383,9 @@ static void tifm_7xx1_remove(struct pci_dev *dev) | |||
| 365 | 383 | ||
| 366 | tifm_remove_adapter(fm); | 384 | tifm_remove_adapter(fm); |
| 367 | 385 | ||
| 386 | for (cnt = 0; cnt < fm->num_sockets; cnt++) | ||
| 387 | tifm_7xx1_sock_power_off(tifm_7xx1_sock_addr(fm->addr, cnt)); | ||
| 388 | |||
| 368 | pci_set_drvdata(dev, NULL); | 389 | pci_set_drvdata(dev, NULL); |
| 369 | 390 | ||
| 370 | iounmap(fm->addr); | 391 | iounmap(fm->addr); |
diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c index 7511f961c67b..8b736e968447 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) | |||
| 1021 | mmc_remove_host(mmc); | 1021 | mmc_remove_host(mmc); |
| 1022 | dev_dbg(&sock->dev, "after remove\n"); | 1022 | dev_dbg(&sock->dev, "after remove\n"); |
| 1023 | 1023 | ||
| 1024 | /* The meaning of the bit majority in this constant is unknown. */ | ||
| 1025 | writel(0xfff8 & readl(sock->addr + SOCK_CONTROL), | ||
| 1026 | sock->addr + SOCK_CONTROL); | ||
| 1027 | |||
| 1028 | mmc_free_host(mmc); | 1024 | mmc_free_host(mmc); |
| 1029 | } | 1025 | } |
| 1030 | 1026 | ||
| @@ -1032,14 +1028,7 @@ static void tifm_sd_remove(struct tifm_dev *sock) | |||
| 1032 | 1028 | ||
| 1033 | static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state) | 1029 | static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state) |
| 1034 | { | 1030 | { |
| 1035 | struct mmc_host *mmc = tifm_get_drvdata(sock); | 1031 | return mmc_suspend_host(tifm_get_drvdata(sock), state); |
| 1036 | int rc; | ||
| 1037 | |||
| 1038 | rc = mmc_suspend_host(mmc, state); | ||
| 1039 | /* The meaning of the bit majority in this constant is unknown. */ | ||
| 1040 | writel(0xfff8 & readl(sock->addr + SOCK_CONTROL), | ||
| 1041 | sock->addr + SOCK_CONTROL); | ||
| 1042 | return rc; | ||
| 1043 | } | 1032 | } |
| 1044 | 1033 | ||
| 1045 | static int tifm_sd_resume(struct tifm_dev *sock) | 1034 | static int tifm_sd_resume(struct tifm_dev *sock) |
diff --git a/include/linux/tifm.h b/include/linux/tifm.h index 2a196982601f..6b3a31805c72 100644 --- a/include/linux/tifm.h +++ b/include/linux/tifm.h | |||
| @@ -63,6 +63,7 @@ enum { | |||
| 63 | 63 | ||
| 64 | #define TIFM_CTRL_LED 0x00000040 | 64 | #define TIFM_CTRL_LED 0x00000040 |
| 65 | #define TIFM_CTRL_FAST_CLK 0x00000100 | 65 | #define TIFM_CTRL_FAST_CLK 0x00000100 |
| 66 | #define TIFM_CTRL_POWER_MASK 0x00000007 | ||
| 66 | 67 | ||
| 67 | #define TIFM_SOCK_STATE_OCCUPIED 0x00000008 | 68 | #define TIFM_SOCK_STATE_OCCUPIED 0x00000008 |
| 68 | #define TIFM_SOCK_STATE_POWERED 0x00000080 | 69 | #define TIFM_SOCK_STATE_POWERED 0x00000080 |
