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 /drivers/misc/tifm_7xx1.c | |
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>
Diffstat (limited to 'drivers/misc/tifm_7xx1.c')
-rw-r--r-- | drivers/misc/tifm_7xx1.c | 27 |
1 files changed, 24 insertions, 3 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); |