Commit 055b8224 authored by Alex Dubov's avatar Alex Dubov Committed by Pierre Ossman

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: default avatarAlex Dubov <oakad@yahoo.com>
Signed-off-by: default avatarPierre Ossman <drzeus@drzeus.cx>
parent 36f021b5
......@@ -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);
......
......@@ -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)
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment