Commit 19c1f3ca authored by Pierre Ossman's avatar Pierre Ossman Committed by Russell King

[MMC] wbsd suspend support

Proper handling of suspend/resume in the wbsd driver.
Signed-off-by: default avatarPierre Ossman <drzeus@drzeus.cx>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 84860bf0
...@@ -1032,6 +1032,8 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) ...@@ -1032,6 +1032,8 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
host->flags |= WBSD_FIGNORE_DETECT; host->flags |= WBSD_FIGNORE_DETECT;
} }
else else
{
if (setup & WBSD_DAT3_H)
{ {
setup &= ~WBSD_DAT3_H; setup &= ~WBSD_DAT3_H;
...@@ -1041,6 +1043,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) ...@@ -1041,6 +1043,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
*/ */
mod_timer(&host->ignore_timer, jiffies + HZ/100); mod_timer(&host->ignore_timer, jiffies + HZ/100);
} }
}
wbsd_write_index(host, WBSD_IDX_SETUP, setup); wbsd_write_index(host, WBSD_IDX_SETUP, setup);
/* /*
...@@ -1461,8 +1464,10 @@ static int __devinit wbsd_scan(struct wbsd_host* host) ...@@ -1461,8 +1464,10 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
{ {
id = 0xFFFF; id = 0xFFFF;
outb(unlock_codes[j], config_ports[i]); host->config = config_ports[i];
outb(unlock_codes[j], config_ports[i]); host->unlock_code = unlock_codes[j];
wbsd_unlock_config(host);
outb(WBSD_CONF_ID_HI, config_ports[i]); outb(WBSD_CONF_ID_HI, config_ports[i]);
id = inb(config_ports[i] + 1) << 8; id = inb(config_ports[i] + 1) << 8;
...@@ -1470,13 +1475,13 @@ static int __devinit wbsd_scan(struct wbsd_host* host) ...@@ -1470,13 +1475,13 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
outb(WBSD_CONF_ID_LO, config_ports[i]); outb(WBSD_CONF_ID_LO, config_ports[i]);
id |= inb(config_ports[i] + 1); id |= inb(config_ports[i] + 1);
wbsd_lock_config(host);
for (k = 0;k < sizeof(valid_ids)/sizeof(int);k++) for (k = 0;k < sizeof(valid_ids)/sizeof(int);k++)
{ {
if (id == valid_ids[k]) if (id == valid_ids[k])
{ {
host->chip_id = id; host->chip_id = id;
host->config = config_ports[i];
host->unlock_code = unlock_codes[i];
return 0; return 0;
} }
...@@ -1487,13 +1492,14 @@ static int __devinit wbsd_scan(struct wbsd_host* host) ...@@ -1487,13 +1492,14 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
DBG("Unknown hardware (id %x) found at %x\n", DBG("Unknown hardware (id %x) found at %x\n",
id, config_ports[i]); id, config_ports[i]);
} }
outb(LOCK_CODE, config_ports[i]);
} }
release_region(config_ports[i], 2); release_region(config_ports[i], 2);
} }
host->config = 0;
host->unlock_code = 0;
return -ENODEV; return -ENODEV;
} }
...@@ -1699,8 +1705,10 @@ static void __devexit wbsd_release_resources(struct wbsd_host* host) ...@@ -1699,8 +1705,10 @@ static void __devexit wbsd_release_resources(struct wbsd_host* host)
* Configure the resources the chip should use. * Configure the resources the chip should use.
*/ */
static void __devinit wbsd_chip_config(struct wbsd_host* host) static void wbsd_chip_config(struct wbsd_host* host)
{ {
wbsd_unlock_config(host);
/* /*
* Reset the chip. * Reset the chip.
*/ */
...@@ -1733,16 +1741,20 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host) ...@@ -1733,16 +1741,20 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host)
*/ */
wbsd_write_config(host, WBSD_CONF_ENABLE, 1); wbsd_write_config(host, WBSD_CONF_ENABLE, 1);
wbsd_write_config(host, WBSD_CONF_POWER, 0x20); wbsd_write_config(host, WBSD_CONF_POWER, 0x20);
wbsd_lock_config(host);
} }
/* /*
* Check that configured resources are correct. * Check that configured resources are correct.
*/ */
static int __devinit wbsd_chip_validate(struct wbsd_host* host) static int wbsd_chip_validate(struct wbsd_host* host)
{ {
int base, irq, dma; int base, irq, dma;
wbsd_unlock_config(host);
/* /*
* Select SD/MMC function. * Select SD/MMC function.
*/ */
...@@ -1758,6 +1770,8 @@ static int __devinit wbsd_chip_validate(struct wbsd_host* host) ...@@ -1758,6 +1770,8 @@ static int __devinit wbsd_chip_validate(struct wbsd_host* host)
dma = wbsd_read_config(host, WBSD_CONF_DRQ); dma = wbsd_read_config(host, WBSD_CONF_DRQ);
wbsd_lock_config(host);
/* /*
* Validate against given configuration. * Validate against given configuration.
*/ */
...@@ -1771,6 +1785,20 @@ static int __devinit wbsd_chip_validate(struct wbsd_host* host) ...@@ -1771,6 +1785,20 @@ static int __devinit wbsd_chip_validate(struct wbsd_host* host)
return 1; return 1;
} }
/*
* Powers down the SD function
*/
static void wbsd_chip_poweroff(struct wbsd_host* host)
{
wbsd_unlock_config(host);
wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
wbsd_lock_config(host);
}
/*****************************************************************************\ /*****************************************************************************\
* * * *
* Devices setup and shutdown * * Devices setup and shutdown *
...@@ -1844,7 +1872,11 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma, ...@@ -1844,7 +1872,11 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
*/ */
#ifdef CONFIG_PM #ifdef CONFIG_PM
if (host->config) if (host->config)
{
wbsd_unlock_config(host);
wbsd_write_config(host, WBSD_CONF_PME, 0xA0); wbsd_write_config(host, WBSD_CONF_PME, 0xA0);
wbsd_lock_config(host);
}
#endif #endif
/* /*
* Allow device to initialise itself properly. * Allow device to initialise itself properly.
...@@ -1885,16 +1917,11 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp) ...@@ -1885,16 +1917,11 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp)
mmc_remove_host(mmc); mmc_remove_host(mmc);
if (!pnp)
{
/* /*
* Power down the SD/MMC function. * Power down the SD/MMC function.
*/ */
wbsd_unlock_config(host); if (!pnp)
wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD); wbsd_chip_poweroff(host);
wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
wbsd_lock_config(host);
}
wbsd_release_resources(host); wbsd_release_resources(host);
...@@ -1955,23 +1982,59 @@ static void __devexit wbsd_pnp_remove(struct pnp_dev * dev) ...@@ -1955,23 +1982,59 @@ static void __devexit wbsd_pnp_remove(struct pnp_dev * dev)
*/ */
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int wbsd_suspend(struct device *dev, pm_message_t state) static int wbsd_suspend(struct device *dev, pm_message_t state)
{ {
DBGF("Not yet supported\n"); struct mmc_host *mmc = dev_get_drvdata(dev);
struct wbsd_host *host;
int ret;
if (!mmc)
return 0;
DBG("Suspending...\n");
ret = mmc_suspend_host(mmc, state);
if (!ret)
return ret;
host = mmc_priv(mmc);
wbsd_chip_poweroff(host);
return 0; return 0;
} }
static int wbsd_resume(struct device *dev) static int wbsd_resume(struct device *dev)
{ {
DBGF("Not yet supported\n"); struct mmc_host *mmc = dev_get_drvdata(dev);
struct wbsd_host *host;
if (!mmc)
return 0; return 0;
DBG("Resuming...\n");
host = mmc_priv(mmc);
wbsd_chip_config(host);
/*
* Allow device to initialise itself properly.
*/
mdelay(5);
wbsd_init_device(host);
return mmc_resume_host(mmc);
} }
#else
#else /* CONFIG_PM */
#define wbsd_suspend NULL #define wbsd_suspend NULL
#define wbsd_resume NULL #define wbsd_resume NULL
#endif
#endif /* CONFIG_PM */
static struct platform_device *wbsd_device; static struct platform_device *wbsd_device;
......
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