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 | ||