Skip to content

Commit

Permalink
disable socket power in adapter driver instead of media one
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Alex Dubov authored and Pierre Ossman committed May 8, 2007
1 parent 36f021b commit 055b822
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 15 deletions.
27 changes: 24 additions & 3 deletions drivers/misc/tifm_7xx1.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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)
{
Expand All @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -357,6 +374,7 @@ static int tifm_7xx1_probe(struct pci_dev *dev,
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);
Expand All @@ -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);
Expand Down
13 changes: 1 addition & 12 deletions drivers/mmc/host/tifm_sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1021,25 +1021,14 @@ 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);
}

#ifdef CONFIG_PM

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)
Expand Down
1 change: 1 addition & 0 deletions include/linux/tifm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 055b822

Please sign in to comment.