diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2006-01-06 19:30:44 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-01-08 23:47:16 -0500 |
commit | 730745a5c45093982112ddc94cee6a9973455641 (patch) | |
tree | 1c36bd96c28d08e2b5d839ba3f4e37588aad2328 /drivers/macintosh/via-pmu.c | |
parent | 002ec58eb57bac2380f0ed5a4e88121b4bdb32ec (diff) |
[PATCH] 1/5 powerpc: Rework PowerMac i2c part 1
This is the first part of a rework of the PowerMac i2c code. It
completely reworks the "low_i2c" layer. It is now more flexible,
supports KeyWest, SMU and PMU i2c busses, and provides functions to
match device nodes to i2c busses and adapters.
This patch also extends & fix some bugs in the SMU driver related to i2c
support and removes the clock spreading hacks from the pmac feature code
rather than adapting them to the new API since they'll be replaced by
the platform function code completely in patch 3/5
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'drivers/macintosh/via-pmu.c')
-rw-r--r-- | drivers/macintosh/via-pmu.c | 264 |
1 files changed, 1 insertions, 263 deletions
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 3c0552016b91..aa481a88ccab 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c | |||
@@ -197,7 +197,6 @@ static int pmu_adb_reset_bus(void); | |||
197 | #endif /* CONFIG_ADB */ | 197 | #endif /* CONFIG_ADB */ |
198 | 198 | ||
199 | static int init_pmu(void); | 199 | static int init_pmu(void); |
200 | static int pmu_queue_request(struct adb_request *req); | ||
201 | static void pmu_start(void); | 200 | static void pmu_start(void); |
202 | static irqreturn_t via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs); | 201 | static irqreturn_t via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs); |
203 | static irqreturn_t gpio1_interrupt(int irq, void *arg, struct pt_regs *regs); | 202 | static irqreturn_t gpio1_interrupt(int irq, void *arg, struct pt_regs *regs); |
@@ -1802,258 +1801,6 @@ pmu_present(void) | |||
1802 | return via != 0; | 1801 | return via != 0; |
1803 | } | 1802 | } |
1804 | 1803 | ||
1805 | struct pmu_i2c_hdr { | ||
1806 | u8 bus; | ||
1807 | u8 mode; | ||
1808 | u8 bus2; | ||
1809 | u8 address; | ||
1810 | u8 sub_addr; | ||
1811 | u8 comb_addr; | ||
1812 | u8 count; | ||
1813 | }; | ||
1814 | |||
1815 | int | ||
1816 | pmu_i2c_combined_read(int bus, int addr, int subaddr, u8* data, int len) | ||
1817 | { | ||
1818 | struct adb_request req; | ||
1819 | struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; | ||
1820 | int retry; | ||
1821 | int rc; | ||
1822 | |||
1823 | for (retry=0; retry<16; retry++) { | ||
1824 | memset(&req, 0, sizeof(req)); | ||
1825 | |||
1826 | hdr->bus = bus; | ||
1827 | hdr->address = addr & 0xfe; | ||
1828 | hdr->mode = PMU_I2C_MODE_COMBINED; | ||
1829 | hdr->bus2 = 0; | ||
1830 | hdr->sub_addr = subaddr; | ||
1831 | hdr->comb_addr = addr | 1; | ||
1832 | hdr->count = len; | ||
1833 | |||
1834 | req.nbytes = sizeof(struct pmu_i2c_hdr) + 1; | ||
1835 | req.reply_expected = 0; | ||
1836 | req.reply_len = 0; | ||
1837 | req.data[0] = PMU_I2C_CMD; | ||
1838 | req.reply[0] = 0xff; | ||
1839 | rc = pmu_queue_request(&req); | ||
1840 | if (rc) | ||
1841 | return rc; | ||
1842 | while(!req.complete) | ||
1843 | pmu_poll(); | ||
1844 | if (req.reply[0] == PMU_I2C_STATUS_OK) | ||
1845 | break; | ||
1846 | mdelay(15); | ||
1847 | } | ||
1848 | if (req.reply[0] != PMU_I2C_STATUS_OK) | ||
1849 | return -1; | ||
1850 | |||
1851 | for (retry=0; retry<16; retry++) { | ||
1852 | memset(&req, 0, sizeof(req)); | ||
1853 | |||
1854 | mdelay(15); | ||
1855 | |||
1856 | hdr->bus = PMU_I2C_BUS_STATUS; | ||
1857 | req.reply[0] = 0xff; | ||
1858 | |||
1859 | req.nbytes = 2; | ||
1860 | req.reply_expected = 0; | ||
1861 | req.reply_len = 0; | ||
1862 | req.data[0] = PMU_I2C_CMD; | ||
1863 | rc = pmu_queue_request(&req); | ||
1864 | if (rc) | ||
1865 | return rc; | ||
1866 | while(!req.complete) | ||
1867 | pmu_poll(); | ||
1868 | if (req.reply[0] == PMU_I2C_STATUS_DATAREAD) { | ||
1869 | memcpy(data, &req.reply[1], req.reply_len - 1); | ||
1870 | return req.reply_len - 1; | ||
1871 | } | ||
1872 | } | ||
1873 | return -1; | ||
1874 | } | ||
1875 | |||
1876 | int | ||
1877 | pmu_i2c_stdsub_write(int bus, int addr, int subaddr, u8* data, int len) | ||
1878 | { | ||
1879 | struct adb_request req; | ||
1880 | struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; | ||
1881 | int retry; | ||
1882 | int rc; | ||
1883 | |||
1884 | for (retry=0; retry<16; retry++) { | ||
1885 | memset(&req, 0, sizeof(req)); | ||
1886 | |||
1887 | hdr->bus = bus; | ||
1888 | hdr->address = addr & 0xfe; | ||
1889 | hdr->mode = PMU_I2C_MODE_STDSUB; | ||
1890 | hdr->bus2 = 0; | ||
1891 | hdr->sub_addr = subaddr; | ||
1892 | hdr->comb_addr = addr & 0xfe; | ||
1893 | hdr->count = len; | ||
1894 | |||
1895 | req.data[0] = PMU_I2C_CMD; | ||
1896 | memcpy(&req.data[sizeof(struct pmu_i2c_hdr) + 1], data, len); | ||
1897 | req.nbytes = sizeof(struct pmu_i2c_hdr) + len + 1; | ||
1898 | req.reply_expected = 0; | ||
1899 | req.reply_len = 0; | ||
1900 | req.reply[0] = 0xff; | ||
1901 | rc = pmu_queue_request(&req); | ||
1902 | if (rc) | ||
1903 | return rc; | ||
1904 | while(!req.complete) | ||
1905 | pmu_poll(); | ||
1906 | if (req.reply[0] == PMU_I2C_STATUS_OK) | ||
1907 | break; | ||
1908 | mdelay(15); | ||
1909 | } | ||
1910 | if (req.reply[0] != PMU_I2C_STATUS_OK) | ||
1911 | return -1; | ||
1912 | |||
1913 | for (retry=0; retry<16; retry++) { | ||
1914 | memset(&req, 0, sizeof(req)); | ||
1915 | |||
1916 | mdelay(15); | ||
1917 | |||
1918 | hdr->bus = PMU_I2C_BUS_STATUS; | ||
1919 | req.reply[0] = 0xff; | ||
1920 | |||
1921 | req.nbytes = 2; | ||
1922 | req.reply_expected = 0; | ||
1923 | req.reply_len = 0; | ||
1924 | req.data[0] = PMU_I2C_CMD; | ||
1925 | rc = pmu_queue_request(&req); | ||
1926 | if (rc) | ||
1927 | return rc; | ||
1928 | while(!req.complete) | ||
1929 | pmu_poll(); | ||
1930 | if (req.reply[0] == PMU_I2C_STATUS_OK) | ||
1931 | return len; | ||
1932 | } | ||
1933 | return -1; | ||
1934 | } | ||
1935 | |||
1936 | int | ||
1937 | pmu_i2c_simple_read(int bus, int addr, u8* data, int len) | ||
1938 | { | ||
1939 | struct adb_request req; | ||
1940 | struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; | ||
1941 | int retry; | ||
1942 | int rc; | ||
1943 | |||
1944 | for (retry=0; retry<16; retry++) { | ||
1945 | memset(&req, 0, sizeof(req)); | ||
1946 | |||
1947 | hdr->bus = bus; | ||
1948 | hdr->address = addr | 1; | ||
1949 | hdr->mode = PMU_I2C_MODE_SIMPLE; | ||
1950 | hdr->bus2 = 0; | ||
1951 | hdr->sub_addr = 0; | ||
1952 | hdr->comb_addr = 0; | ||
1953 | hdr->count = len; | ||
1954 | |||
1955 | req.data[0] = PMU_I2C_CMD; | ||
1956 | req.nbytes = sizeof(struct pmu_i2c_hdr) + 1; | ||
1957 | req.reply_expected = 0; | ||
1958 | req.reply_len = 0; | ||
1959 | req.reply[0] = 0xff; | ||
1960 | rc = pmu_queue_request(&req); | ||
1961 | if (rc) | ||
1962 | return rc; | ||
1963 | while(!req.complete) | ||
1964 | pmu_poll(); | ||
1965 | if (req.reply[0] == PMU_I2C_STATUS_OK) | ||
1966 | break; | ||
1967 | mdelay(15); | ||
1968 | } | ||
1969 | if (req.reply[0] != PMU_I2C_STATUS_OK) | ||
1970 | return -1; | ||
1971 | |||
1972 | for (retry=0; retry<16; retry++) { | ||
1973 | memset(&req, 0, sizeof(req)); | ||
1974 | |||
1975 | mdelay(15); | ||
1976 | |||
1977 | hdr->bus = PMU_I2C_BUS_STATUS; | ||
1978 | req.reply[0] = 0xff; | ||
1979 | |||
1980 | req.nbytes = 2; | ||
1981 | req.reply_expected = 0; | ||
1982 | req.reply_len = 0; | ||
1983 | req.data[0] = PMU_I2C_CMD; | ||
1984 | rc = pmu_queue_request(&req); | ||
1985 | if (rc) | ||
1986 | return rc; | ||
1987 | while(!req.complete) | ||
1988 | pmu_poll(); | ||
1989 | if (req.reply[0] == PMU_I2C_STATUS_DATAREAD) { | ||
1990 | memcpy(data, &req.reply[1], req.reply_len - 1); | ||
1991 | return req.reply_len - 1; | ||
1992 | } | ||
1993 | } | ||
1994 | return -1; | ||
1995 | } | ||
1996 | |||
1997 | int | ||
1998 | pmu_i2c_simple_write(int bus, int addr, u8* data, int len) | ||
1999 | { | ||
2000 | struct adb_request req; | ||
2001 | struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; | ||
2002 | int retry; | ||
2003 | int rc; | ||
2004 | |||
2005 | for (retry=0; retry<16; retry++) { | ||
2006 | memset(&req, 0, sizeof(req)); | ||
2007 | |||
2008 | hdr->bus = bus; | ||
2009 | hdr->address = addr & 0xfe; | ||
2010 | hdr->mode = PMU_I2C_MODE_SIMPLE; | ||
2011 | hdr->bus2 = 0; | ||
2012 | hdr->sub_addr = 0; | ||
2013 | hdr->comb_addr = 0; | ||
2014 | hdr->count = len; | ||
2015 | |||
2016 | req.data[0] = PMU_I2C_CMD; | ||
2017 | memcpy(&req.data[sizeof(struct pmu_i2c_hdr) + 1], data, len); | ||
2018 | req.nbytes = sizeof(struct pmu_i2c_hdr) + len + 1; | ||
2019 | req.reply_expected = 0; | ||
2020 | req.reply_len = 0; | ||
2021 | req.reply[0] = 0xff; | ||
2022 | rc = pmu_queue_request(&req); | ||
2023 | if (rc) | ||
2024 | return rc; | ||
2025 | while(!req.complete) | ||
2026 | pmu_poll(); | ||
2027 | if (req.reply[0] == PMU_I2C_STATUS_OK) | ||
2028 | break; | ||
2029 | mdelay(15); | ||
2030 | } | ||
2031 | if (req.reply[0] != PMU_I2C_STATUS_OK) | ||
2032 | return -1; | ||
2033 | |||
2034 | for (retry=0; retry<16; retry++) { | ||
2035 | memset(&req, 0, sizeof(req)); | ||
2036 | |||
2037 | mdelay(15); | ||
2038 | |||
2039 | hdr->bus = PMU_I2C_BUS_STATUS; | ||
2040 | req.reply[0] = 0xff; | ||
2041 | |||
2042 | req.nbytes = 2; | ||
2043 | req.reply_expected = 0; | ||
2044 | req.reply_len = 0; | ||
2045 | req.data[0] = PMU_I2C_CMD; | ||
2046 | rc = pmu_queue_request(&req); | ||
2047 | if (rc) | ||
2048 | return rc; | ||
2049 | while(!req.complete) | ||
2050 | pmu_poll(); | ||
2051 | if (req.reply[0] == PMU_I2C_STATUS_OK) | ||
2052 | return len; | ||
2053 | } | ||
2054 | return -1; | ||
2055 | } | ||
2056 | |||
2057 | #ifdef CONFIG_PM | 1804 | #ifdef CONFIG_PM |
2058 | 1805 | ||
2059 | static LIST_HEAD(sleep_notifiers); | 1806 | static LIST_HEAD(sleep_notifiers); |
@@ -2358,9 +2105,6 @@ pmac_suspend_devices(void) | |||
2358 | return -EBUSY; | 2105 | return -EBUSY; |
2359 | } | 2106 | } |
2360 | 2107 | ||
2361 | /* Disable clock spreading on some machines */ | ||
2362 | pmac_tweak_clock_spreading(0); | ||
2363 | |||
2364 | /* Stop preemption */ | 2108 | /* Stop preemption */ |
2365 | preempt_disable(); | 2109 | preempt_disable(); |
2366 | 2110 | ||
@@ -2431,9 +2175,6 @@ pmac_wakeup_devices(void) | |||
2431 | mdelay(10); | 2175 | mdelay(10); |
2432 | preempt_enable(); | 2176 | preempt_enable(); |
2433 | 2177 | ||
2434 | /* Re-enable clock spreading on some machines */ | ||
2435 | pmac_tweak_clock_spreading(1); | ||
2436 | |||
2437 | /* Resume devices */ | 2178 | /* Resume devices */ |
2438 | device_resume(); | 2179 | device_resume(); |
2439 | 2180 | ||
@@ -3150,16 +2891,13 @@ static int __init init_pmu_sysfs(void) | |||
3150 | subsys_initcall(init_pmu_sysfs); | 2891 | subsys_initcall(init_pmu_sysfs); |
3151 | 2892 | ||
3152 | EXPORT_SYMBOL(pmu_request); | 2893 | EXPORT_SYMBOL(pmu_request); |
2894 | EXPORT_SYMBOL(pmu_queue_request); | ||
3153 | EXPORT_SYMBOL(pmu_poll); | 2895 | EXPORT_SYMBOL(pmu_poll); |
3154 | EXPORT_SYMBOL(pmu_poll_adb); | 2896 | EXPORT_SYMBOL(pmu_poll_adb); |
3155 | EXPORT_SYMBOL(pmu_wait_complete); | 2897 | EXPORT_SYMBOL(pmu_wait_complete); |
3156 | EXPORT_SYMBOL(pmu_suspend); | 2898 | EXPORT_SYMBOL(pmu_suspend); |
3157 | EXPORT_SYMBOL(pmu_resume); | 2899 | EXPORT_SYMBOL(pmu_resume); |
3158 | EXPORT_SYMBOL(pmu_unlock); | 2900 | EXPORT_SYMBOL(pmu_unlock); |
3159 | EXPORT_SYMBOL(pmu_i2c_combined_read); | ||
3160 | EXPORT_SYMBOL(pmu_i2c_stdsub_write); | ||
3161 | EXPORT_SYMBOL(pmu_i2c_simple_read); | ||
3162 | EXPORT_SYMBOL(pmu_i2c_simple_write); | ||
3163 | #if defined(CONFIG_PM) && defined(CONFIG_PPC32) | 2901 | #if defined(CONFIG_PM) && defined(CONFIG_PPC32) |
3164 | EXPORT_SYMBOL(pmu_enable_irled); | 2902 | EXPORT_SYMBOL(pmu_enable_irled); |
3165 | EXPORT_SYMBOL(pmu_battery_count); | 2903 | EXPORT_SYMBOL(pmu_battery_count); |