diff options
| author | Pierre Ossman <drzeus@drzeus.cx> | 2005-10-28 16:37:29 -0400 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2005-10-28 16:37:29 -0400 |
| commit | 19c1f3ca4272008a256cc153f3e3feb097799070 (patch) | |
| tree | af788b540d68396d9a94d6abf2379c1efc8e4e08 /drivers/mmc/wbsd.c | |
| parent | 84860bf0644d7c45afe7ddbd30731c3e3c371fae (diff) | |
[MMC] wbsd suspend support
Proper handling of suspend/resume in the wbsd driver.
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/mmc/wbsd.c')
| -rw-r--r-- | drivers/mmc/wbsd.c | 119 |
1 files changed, 91 insertions, 28 deletions
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index 25f7ce7b3bc0..3ace875decc4 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c | |||
| @@ -1033,13 +1033,16 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) | |||
| 1033 | } | 1033 | } |
| 1034 | else | 1034 | else |
| 1035 | { | 1035 | { |
| 1036 | setup &= ~WBSD_DAT3_H; | 1036 | if (setup & WBSD_DAT3_H) |
| 1037 | { | ||
| 1038 | setup &= ~WBSD_DAT3_H; | ||
| 1037 | 1039 | ||
| 1038 | /* | 1040 | /* |
| 1039 | * We cannot resume card detection immediatly | 1041 | * We cannot resume card detection immediatly |
| 1040 | * because of capacitance and delays in the chip. | 1042 | * because of capacitance and delays in the chip. |
| 1041 | */ | 1043 | */ |
| 1042 | mod_timer(&host->ignore_timer, jiffies + HZ/100); | 1044 | mod_timer(&host->ignore_timer, jiffies + HZ/100); |
| 1045 | } | ||
| 1043 | } | 1046 | } |
| 1044 | wbsd_write_index(host, WBSD_IDX_SETUP, setup); | 1047 | wbsd_write_index(host, WBSD_IDX_SETUP, setup); |
| 1045 | 1048 | ||
| @@ -1461,8 +1464,10 @@ static int __devinit wbsd_scan(struct wbsd_host* host) | |||
| 1461 | { | 1464 | { |
| 1462 | id = 0xFFFF; | 1465 | id = 0xFFFF; |
| 1463 | 1466 | ||
| 1464 | outb(unlock_codes[j], config_ports[i]); | 1467 | host->config = config_ports[i]; |
| 1465 | outb(unlock_codes[j], config_ports[i]); | 1468 | host->unlock_code = unlock_codes[j]; |
| 1469 | |||
| 1470 | wbsd_unlock_config(host); | ||
| 1466 | 1471 | ||
| 1467 | outb(WBSD_CONF_ID_HI, config_ports[i]); | 1472 | outb(WBSD_CONF_ID_HI, config_ports[i]); |
| 1468 | id = inb(config_ports[i] + 1) << 8; | 1473 | id = inb(config_ports[i] + 1) << 8; |
| @@ -1470,13 +1475,13 @@ static int __devinit wbsd_scan(struct wbsd_host* host) | |||
| 1470 | outb(WBSD_CONF_ID_LO, config_ports[i]); | 1475 | outb(WBSD_CONF_ID_LO, config_ports[i]); |
| 1471 | id |= inb(config_ports[i] + 1); | 1476 | id |= inb(config_ports[i] + 1); |
| 1472 | 1477 | ||
| 1478 | wbsd_lock_config(host); | ||
| 1479 | |||
| 1473 | for (k = 0;k < sizeof(valid_ids)/sizeof(int);k++) | 1480 | for (k = 0;k < sizeof(valid_ids)/sizeof(int);k++) |
| 1474 | { | 1481 | { |
| 1475 | if (id == valid_ids[k]) | 1482 | if (id == valid_ids[k]) |
| 1476 | { | 1483 | { |
| 1477 | host->chip_id = id; | 1484 | host->chip_id = id; |
| 1478 | host->config = config_ports[i]; | ||
| 1479 | host->unlock_code = unlock_codes[i]; | ||
| 1480 | 1485 | ||
| 1481 | return 0; | 1486 | return 0; |
| 1482 | } | 1487 | } |
| @@ -1487,13 +1492,14 @@ static int __devinit wbsd_scan(struct wbsd_host* host) | |||
| 1487 | DBG("Unknown hardware (id %x) found at %x\n", | 1492 | DBG("Unknown hardware (id %x) found at %x\n", |
| 1488 | id, config_ports[i]); | 1493 | id, config_ports[i]); |
| 1489 | } | 1494 | } |
| 1490 | |||
| 1491 | outb(LOCK_CODE, config_ports[i]); | ||
| 1492 | } | 1495 | } |
| 1493 | 1496 | ||
| 1494 | release_region(config_ports[i], 2); | 1497 | release_region(config_ports[i], 2); |
| 1495 | } | 1498 | } |
| 1496 | 1499 | ||
| 1500 | host->config = 0; | ||
| 1501 | host->unlock_code = 0; | ||
| 1502 | |||
| 1497 | return -ENODEV; | 1503 | return -ENODEV; |
| 1498 | } | 1504 | } |
| 1499 | 1505 | ||
| @@ -1699,8 +1705,10 @@ static void __devexit wbsd_release_resources(struct wbsd_host* host) | |||
| 1699 | * Configure the resources the chip should use. | 1705 | * Configure the resources the chip should use. |
| 1700 | */ | 1706 | */ |
| 1701 | 1707 | ||
| 1702 | static void __devinit wbsd_chip_config(struct wbsd_host* host) | 1708 | static void wbsd_chip_config(struct wbsd_host* host) |
| 1703 | { | 1709 | { |
| 1710 | wbsd_unlock_config(host); | ||
| 1711 | |||
| 1704 | /* | 1712 | /* |
| 1705 | * Reset the chip. | 1713 | * Reset the chip. |
| 1706 | */ | 1714 | */ |
| @@ -1733,16 +1741,20 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host) | |||
| 1733 | */ | 1741 | */ |
| 1734 | wbsd_write_config(host, WBSD_CONF_ENABLE, 1); | 1742 | wbsd_write_config(host, WBSD_CONF_ENABLE, 1); |
| 1735 | wbsd_write_config(host, WBSD_CONF_POWER, 0x20); | 1743 | wbsd_write_config(host, WBSD_CONF_POWER, 0x20); |
| 1744 | |||
| 1745 | wbsd_lock_config(host); | ||
| 1736 | } | 1746 | } |
| 1737 | 1747 | ||
| 1738 | /* | 1748 | /* |
| 1739 | * Check that configured resources are correct. | 1749 | * Check that configured resources are correct. |
| 1740 | */ | 1750 | */ |
| 1741 | 1751 | ||
| 1742 | static int __devinit wbsd_chip_validate(struct wbsd_host* host) | 1752 | static int wbsd_chip_validate(struct wbsd_host* host) |
| 1743 | { | 1753 | { |
| 1744 | int base, irq, dma; | 1754 | int base, irq, dma; |
| 1745 | 1755 | ||
| 1756 | wbsd_unlock_config(host); | ||
| 1757 | |||
| 1746 | /* | 1758 | /* |
| 1747 | * Select SD/MMC function. | 1759 | * Select SD/MMC function. |
| 1748 | */ | 1760 | */ |
| @@ -1758,6 +1770,8 @@ static int __devinit wbsd_chip_validate(struct wbsd_host* host) | |||
| 1758 | 1770 | ||
| 1759 | dma = wbsd_read_config(host, WBSD_CONF_DRQ); | 1771 | dma = wbsd_read_config(host, WBSD_CONF_DRQ); |
| 1760 | 1772 | ||
| 1773 | wbsd_lock_config(host); | ||
| 1774 | |||
| 1761 | /* | 1775 | /* |
| 1762 | * Validate against given configuration. | 1776 | * Validate against given configuration. |
| 1763 | */ | 1777 | */ |
| @@ -1771,6 +1785,20 @@ static int __devinit wbsd_chip_validate(struct wbsd_host* host) | |||
| 1771 | return 1; | 1785 | return 1; |
| 1772 | } | 1786 | } |
| 1773 | 1787 | ||
| 1788 | /* | ||
| 1789 | * Powers down the SD function | ||
| 1790 | */ | ||
| 1791 | |||
| 1792 | static void wbsd_chip_poweroff(struct wbsd_host* host) | ||
| 1793 | { | ||
| 1794 | wbsd_unlock_config(host); | ||
| 1795 | |||
| 1796 | wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD); | ||
| 1797 | wbsd_write_config(host, WBSD_CONF_ENABLE, 0); | ||
| 1798 | |||
| 1799 | wbsd_lock_config(host); | ||
| 1800 | } | ||
| 1801 | |||
| 1774 | /*****************************************************************************\ | 1802 | /*****************************************************************************\ |
| 1775 | * * | 1803 | * * |
| 1776 | * Devices setup and shutdown * | 1804 | * Devices setup and shutdown * |
| @@ -1844,7 +1872,11 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma, | |||
| 1844 | */ | 1872 | */ |
| 1845 | #ifdef CONFIG_PM | 1873 | #ifdef CONFIG_PM |
| 1846 | if (host->config) | 1874 | if (host->config) |
| 1875 | { | ||
| 1876 | wbsd_unlock_config(host); | ||
| 1847 | wbsd_write_config(host, WBSD_CONF_PME, 0xA0); | 1877 | wbsd_write_config(host, WBSD_CONF_PME, 0xA0); |
| 1878 | wbsd_lock_config(host); | ||
| 1879 | } | ||
| 1848 | #endif | 1880 | #endif |
| 1849 | /* | 1881 | /* |
| 1850 | * Allow device to initialise itself properly. | 1882 | * Allow device to initialise itself properly. |
| @@ -1885,16 +1917,11 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp) | |||
| 1885 | 1917 | ||
| 1886 | mmc_remove_host(mmc); | 1918 | mmc_remove_host(mmc); |
| 1887 | 1919 | ||
| 1920 | /* | ||
| 1921 | * Power down the SD/MMC function. | ||
| 1922 | */ | ||
| 1888 | if (!pnp) | 1923 | if (!pnp) |
| 1889 | { | 1924 | wbsd_chip_poweroff(host); |
| 1890 | /* | ||
| 1891 | * Power down the SD/MMC function. | ||
| 1892 | */ | ||
| 1893 | wbsd_unlock_config(host); | ||
| 1894 | wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD); | ||
| 1895 | wbsd_write_config(host, WBSD_CONF_ENABLE, 0); | ||
| 1896 | wbsd_lock_config(host); | ||
| 1897 | } | ||
| 1898 | 1925 | ||
| 1899 | wbsd_release_resources(host); | 1926 | wbsd_release_resources(host); |
| 1900 | 1927 | ||
| @@ -1955,23 +1982,59 @@ static void __devexit wbsd_pnp_remove(struct pnp_dev * dev) | |||
| 1955 | */ | 1982 | */ |
| 1956 | 1983 | ||
| 1957 | #ifdef CONFIG_PM | 1984 | #ifdef CONFIG_PM |
| 1985 | |||
| 1958 | static int wbsd_suspend(struct device *dev, pm_message_t state) | 1986 | static int wbsd_suspend(struct device *dev, pm_message_t state) |
| 1959 | { | 1987 | { |
| 1960 | DBGF("Not yet supported\n"); | 1988 | struct mmc_host *mmc = dev_get_drvdata(dev); |
| 1989 | struct wbsd_host *host; | ||
| 1990 | int ret; | ||
| 1991 | |||
| 1992 | if (!mmc) | ||
| 1993 | return 0; | ||
| 1994 | |||
| 1995 | DBG("Suspending...\n"); | ||
| 1996 | |||
| 1997 | ret = mmc_suspend_host(mmc, state); | ||
| 1998 | if (!ret) | ||
| 1999 | return ret; | ||
| 2000 | |||
| 2001 | host = mmc_priv(mmc); | ||
| 2002 | |||
| 2003 | wbsd_chip_poweroff(host); | ||
| 1961 | 2004 | ||
| 1962 | return 0; | 2005 | return 0; |
| 1963 | } | 2006 | } |
| 1964 | 2007 | ||
| 1965 | static int wbsd_resume(struct device *dev) | 2008 | static int wbsd_resume(struct device *dev) |
| 1966 | { | 2009 | { |
| 1967 | DBGF("Not yet supported\n"); | 2010 | struct mmc_host *mmc = dev_get_drvdata(dev); |
| 2011 | struct wbsd_host *host; | ||
| 1968 | 2012 | ||
| 1969 | return 0; | 2013 | if (!mmc) |
| 2014 | return 0; | ||
| 2015 | |||
| 2016 | DBG("Resuming...\n"); | ||
| 2017 | |||
| 2018 | host = mmc_priv(mmc); | ||
| 2019 | |||
| 2020 | wbsd_chip_config(host); | ||
| 2021 | |||
| 2022 | /* | ||
| 2023 | * Allow device to initialise itself properly. | ||
| 2024 | */ | ||
| 2025 | mdelay(5); | ||
| 2026 | |||
| 2027 | wbsd_init_device(host); | ||
| 2028 | |||
| 2029 | return mmc_resume_host(mmc); | ||
| 1970 | } | 2030 | } |
| 1971 | #else | 2031 | |
| 2032 | #else /* CONFIG_PM */ | ||
| 2033 | |||
| 1972 | #define wbsd_suspend NULL | 2034 | #define wbsd_suspend NULL |
| 1973 | #define wbsd_resume NULL | 2035 | #define wbsd_resume NULL |
| 1974 | #endif | 2036 | |
| 2037 | #endif /* CONFIG_PM */ | ||
| 1975 | 2038 | ||
| 1976 | static struct platform_device *wbsd_device; | 2039 | static struct platform_device *wbsd_device; |
| 1977 | 2040 | ||
