aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2007-12-11 09:25:59 -0500
committerPaul Mackerras <paulus@samba.org>2007-12-19 07:02:35 -0500
commitf91266edba3c6ef001819c5abe4c3a0643f66fc9 (patch)
tree9ca84ad4550288c3b467dea7197b935c345755d7 /drivers
parent887ef35ae4eb269839e0f296b132edc15477db1c (diff)
[POWERPC] powermac: Use generic suspend code
This adds platform_suspend_ops for PMU based machines, directly in the PMU driver. This allows suspending via /sys/power/state on powerbooks. The patch also replaces the PMU ioctl with a simple call to pm_suspend(PM_SUSPEND_MEM). Additionally, it cleans up some debug code. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/macintosh/via-pmu.c405
1 files changed, 173 insertions, 232 deletions
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 0e233185ad14..8f98257e6a15 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -10,13 +10,11 @@
10 * 10 *
11 * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi. 11 * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi.
12 * Copyright (C) 2001-2002 Benjamin Herrenschmidt 12 * Copyright (C) 2001-2002 Benjamin Herrenschmidt
13 * Copyright (C) 2006-2007 Johannes Berg
13 * 14 *
14 * THIS DRIVER IS BECOMING A TOTAL MESS ! 15 * THIS DRIVER IS BECOMING A TOTAL MESS !
15 * - Cleanup atomically disabling reply to PMU events after 16 * - Cleanup atomically disabling reply to PMU events after
16 * a sleep or a freq. switch 17 * a sleep or a freq. switch
17 * - Move sleep code out of here to pmac_pm, merge into new
18 * common PM infrastructure
19 * - Save/Restore PCI space properly
20 * 18 *
21 */ 19 */
22#include <stdarg.h> 20#include <stdarg.h>
@@ -64,7 +62,7 @@
64#include "via-pmu-event.h" 62#include "via-pmu-event.h"
65 63
66/* Some compile options */ 64/* Some compile options */
67#define DEBUG_SLEEP 65#undef DEBUG_SLEEP
68 66
69/* Misc minor number allocated for /dev/pmu */ 67/* Misc minor number allocated for /dev/pmu */
70#define PMU_MINOR 154 68#define PMU_MINOR 154
@@ -149,12 +147,9 @@ static spinlock_t pmu_lock;
149static u8 pmu_intr_mask; 147static u8 pmu_intr_mask;
150static int pmu_version; 148static int pmu_version;
151static int drop_interrupts; 149static int drop_interrupts;
152#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) 150#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
153static int option_lid_wakeup = 1; 151static int option_lid_wakeup = 1;
154#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */ 152#endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
155#if (defined(CONFIG_PM_SLEEP)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT_LEGACY)
156static int sleep_in_progress;
157#endif
158static unsigned long async_req_locks; 153static unsigned long async_req_locks;
159static unsigned int pmu_irq_stats[11]; 154static unsigned int pmu_irq_stats[11];
160 155
@@ -226,7 +221,7 @@ extern void enable_kernel_fp(void);
226 221
227#ifdef DEBUG_SLEEP 222#ifdef DEBUG_SLEEP
228int pmu_polled_request(struct adb_request *req); 223int pmu_polled_request(struct adb_request *req);
229int pmu_wink(struct adb_request *req); 224void pmu_blink(int n);
230#endif 225#endif
231 226
232/* 227/*
@@ -881,7 +876,7 @@ proc_read_options(char *page, char **start, off_t off,
881{ 876{
882 char *p = page; 877 char *p = page;
883 878
884#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) 879#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
885 if (pmu_kind == PMU_KEYLARGO_BASED && 880 if (pmu_kind == PMU_KEYLARGO_BASED &&
886 pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0) 881 pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
887 p += sprintf(p, "lid_wakeup=%d\n", option_lid_wakeup); 882 p += sprintf(p, "lid_wakeup=%d\n", option_lid_wakeup);
@@ -922,7 +917,7 @@ proc_write_options(struct file *file, const char __user *buffer,
922 *(val++) = 0; 917 *(val++) = 0;
923 while(*val == ' ') 918 while(*val == ' ')
924 val++; 919 val++;
925#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) 920#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
926 if (pmu_kind == PMU_KEYLARGO_BASED && 921 if (pmu_kind == PMU_KEYLARGO_BASED &&
927 pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0) 922 pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
928 if (!strcmp(label, "lid_wakeup")) 923 if (!strcmp(label, "lid_wakeup"))
@@ -1728,44 +1723,7 @@ pmu_present(void)
1728 return via != 0; 1723 return via != 0;
1729} 1724}
1730 1725
1731#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) 1726#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
1732#ifdef DEBUG_SLEEP
1733/* N.B. This doesn't work on the 3400 */
1734void
1735pmu_blink(int n)
1736{
1737 struct adb_request req;
1738
1739 memset(&req, 0, sizeof(req));
1740
1741 for (; n > 0; --n) {
1742 req.nbytes = 4;
1743 req.done = NULL;
1744 req.data[0] = 0xee;
1745 req.data[1] = 4;
1746 req.data[2] = 0;
1747 req.data[3] = 1;
1748 req.reply[0] = ADB_RET_OK;
1749 req.reply_len = 1;
1750 req.reply_expected = 0;
1751 pmu_polled_request(&req);
1752 mdelay(50);
1753 req.nbytes = 4;
1754 req.done = NULL;
1755 req.data[0] = 0xee;
1756 req.data[1] = 4;
1757 req.data[2] = 0;
1758 req.data[3] = 0;
1759 req.reply[0] = ADB_RET_OK;
1760 req.reply_len = 1;
1761 req.reply_expected = 0;
1762 pmu_polled_request(&req);
1763 mdelay(50);
1764 }
1765 mdelay(50);
1766}
1767#endif
1768
1769/* 1727/*
1770 * Put the powerbook to sleep. 1728 * Put the powerbook to sleep.
1771 */ 1729 */
@@ -1802,122 +1760,6 @@ restore_via_state(void)
1802 1760
1803extern void pmu_backlight_set_sleep(int sleep); 1761extern void pmu_backlight_set_sleep(int sleep);
1804 1762
1805static int
1806pmac_suspend_devices(void)
1807{
1808 int ret;
1809
1810 pm_prepare_console();
1811
1812 /* Sync the disks. */
1813 /* XXX It would be nice to have some way to ensure that
1814 * nobody is dirtying any new buffers while we wait. That
1815 * could be achieved using the refrigerator for processes
1816 * that swsusp uses
1817 */
1818 sys_sync();
1819
1820 /* Send suspend call to devices, hold the device core's dpm_sem */
1821 ret = device_suspend(PMSG_SUSPEND);
1822 if (ret) {
1823 printk(KERN_ERR "Driver sleep failed\n");
1824 return -EBUSY;
1825 }
1826
1827#ifdef CONFIG_PMAC_BACKLIGHT
1828 /* Tell backlight code not to muck around with the chip anymore */
1829 pmu_backlight_set_sleep(1);
1830#endif
1831
1832 /* Call platform functions marked "on sleep" */
1833 pmac_pfunc_i2c_suspend();
1834 pmac_pfunc_base_suspend();
1835
1836 /* Stop preemption */
1837 preempt_disable();
1838
1839 /* Make sure the decrementer won't interrupt us */
1840 asm volatile("mtdec %0" : : "r" (0x7fffffff));
1841 /* Make sure any pending DEC interrupt occurring while we did
1842 * the above didn't re-enable the DEC */
1843 mb();
1844 asm volatile("mtdec %0" : : "r" (0x7fffffff));
1845
1846 /* We can now disable MSR_EE. This code of course works properly only
1847 * on UP machines... For SMP, if we ever implement sleep, we'll have to
1848 * stop the "other" CPUs way before we do all that stuff.
1849 */
1850 local_irq_disable();
1851
1852 /* Broadcast power down irq
1853 * This isn't that useful in most cases (only directly wired devices can
1854 * use this but still... This will take care of sysdev's as well, so
1855 * we exit from here with local irqs disabled and PIC off.
1856 */
1857 ret = device_power_down(PMSG_SUSPEND);
1858 if (ret) {
1859 wakeup_decrementer();
1860 local_irq_enable();
1861 preempt_enable();
1862 device_resume();
1863 printk(KERN_ERR "Driver powerdown failed\n");
1864 return -EBUSY;
1865 }
1866
1867 /* Wait for completion of async requests */
1868 while (!batt_req.complete)
1869 pmu_poll();
1870
1871 /* Giveup the lazy FPU & vec so we don't have to back them
1872 * up from the low level code
1873 */
1874 enable_kernel_fp();
1875
1876#ifdef CONFIG_ALTIVEC
1877 if (cpu_has_feature(CPU_FTR_ALTIVEC))
1878 enable_kernel_altivec();
1879#endif /* CONFIG_ALTIVEC */
1880
1881 return 0;
1882}
1883
1884static int
1885pmac_wakeup_devices(void)
1886{
1887 mdelay(100);
1888
1889#ifdef CONFIG_PMAC_BACKLIGHT
1890 /* Tell backlight code it can use the chip again */
1891 pmu_backlight_set_sleep(0);
1892#endif
1893
1894 /* Power back up system devices (including the PIC) */
1895 device_power_up();
1896
1897 /* Force a poll of ADB interrupts */
1898 adb_int_pending = 1;
1899 via_pmu_interrupt(0, NULL);
1900
1901 /* Restart jiffies & scheduling */
1902 wakeup_decrementer();
1903
1904 /* Re-enable local CPU interrupts */
1905 local_irq_enable();
1906 mdelay(10);
1907 preempt_enable();
1908
1909 /* Call platform functions marked "on wake" */
1910 pmac_pfunc_base_resume();
1911 pmac_pfunc_i2c_resume();
1912
1913 /* Resume devices */
1914 device_resume();
1915
1916 pm_restore_console();
1917
1918 return 0;
1919}
1920
1921#define GRACKLE_PM (1<<7) 1763#define GRACKLE_PM (1<<7)
1922#define GRACKLE_DOZE (1<<5) 1764#define GRACKLE_DOZE (1<<5)
1923#define GRACKLE_NAP (1<<4) 1765#define GRACKLE_NAP (1<<4)
@@ -1928,19 +1770,12 @@ static int powerbook_sleep_grackle(void)
1928 unsigned long save_l2cr; 1770 unsigned long save_l2cr;
1929 unsigned short pmcr1; 1771 unsigned short pmcr1;
1930 struct adb_request req; 1772 struct adb_request req;
1931 int ret;
1932 struct pci_dev *grackle; 1773 struct pci_dev *grackle;
1933 1774
1934 grackle = pci_get_bus_and_slot(0, 0); 1775 grackle = pci_get_bus_and_slot(0, 0);
1935 if (!grackle) 1776 if (!grackle)
1936 return -ENODEV; 1777 return -ENODEV;
1937 1778
1938 ret = pmac_suspend_devices();
1939 if (ret) {
1940 printk(KERN_ERR "Sleep rejected by devices\n");
1941 return ret;
1942 }
1943
1944 /* Turn off various things. Darwin does some retry tests here... */ 1779 /* Turn off various things. Darwin does some retry tests here... */
1945 pmu_request(&req, NULL, 2, PMU_POWER_CTRL0, PMU_POW0_OFF|PMU_POW0_HARD_DRIVE); 1780 pmu_request(&req, NULL, 2, PMU_POWER_CTRL0, PMU_POW0_OFF|PMU_POW0_HARD_DRIVE);
1946 pmu_wait_complete(&req); 1781 pmu_wait_complete(&req);
@@ -2003,8 +1838,6 @@ static int powerbook_sleep_grackle(void)
2003 PMU_POW_ON|PMU_POW_BACKLIGHT|PMU_POW_CHARGER|PMU_POW_IRLED|PMU_POW_MEDIABAY); 1838 PMU_POW_ON|PMU_POW_BACKLIGHT|PMU_POW_CHARGER|PMU_POW_IRLED|PMU_POW_MEDIABAY);
2004 pmu_wait_complete(&req); 1839 pmu_wait_complete(&req);
2005 1840
2006 pmac_wakeup_devices();
2007
2008 return 0; 1841 return 0;
2009} 1842}
2010 1843
@@ -2014,7 +1847,6 @@ powerbook_sleep_Core99(void)
2014 unsigned long save_l2cr; 1847 unsigned long save_l2cr;
2015 unsigned long save_l3cr; 1848 unsigned long save_l3cr;
2016 struct adb_request req; 1849 struct adb_request req;
2017 int ret;
2018 1850
2019 if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) { 1851 if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) {
2020 printk(KERN_ERR "Sleep mode not supported on this machine\n"); 1852 printk(KERN_ERR "Sleep mode not supported on this machine\n");
@@ -2024,12 +1856,6 @@ powerbook_sleep_Core99(void)
2024 if (num_online_cpus() > 1 || cpu_is_offline(0)) 1856 if (num_online_cpus() > 1 || cpu_is_offline(0))
2025 return -EAGAIN; 1857 return -EAGAIN;
2026 1858
2027 ret = pmac_suspend_devices();
2028 if (ret) {
2029 printk(KERN_ERR "Sleep rejected by devices\n");
2030 return ret;
2031 }
2032
2033 /* Stop environment and ADB interrupts */ 1859 /* Stop environment and ADB interrupts */
2034 pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0); 1860 pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0);
2035 pmu_wait_complete(&req); 1861 pmu_wait_complete(&req);
@@ -2100,8 +1926,6 @@ powerbook_sleep_Core99(void)
2100 /* Restore LPJ, cpufreq will adjust the cpu frequency */ 1926 /* Restore LPJ, cpufreq will adjust the cpu frequency */
2101 loops_per_jiffy /= 2; 1927 loops_per_jiffy /= 2;
2102 1928
2103 pmac_wakeup_devices();
2104
2105 return 0; 1929 return 0;
2106} 1930}
2107 1931
@@ -2120,7 +1944,7 @@ static void powerbook_sleep_init_3400(void)
2120 1944
2121static int powerbook_sleep_3400(void) 1945static int powerbook_sleep_3400(void)
2122{ 1946{
2123 int ret, i, x; 1947 int i, x;
2124 unsigned int hid0; 1948 unsigned int hid0;
2125 unsigned long msr; 1949 unsigned long msr;
2126 struct adb_request sleep_req; 1950 struct adb_request sleep_req;
@@ -2130,12 +1954,6 @@ static int powerbook_sleep_3400(void)
2130 return -ENOMEM; 1954 return -ENOMEM;
2131 mem_ctrl_sleep = pb3400_mem_ctrl + PB3400_MEM_CTRL_SLEEP; 1955 mem_ctrl_sleep = pb3400_mem_ctrl + PB3400_MEM_CTRL_SLEEP;
2132 1956
2133 ret = pmac_suspend_devices();
2134 if (ret) {
2135 printk(KERN_ERR "Sleep rejected by devices\n");
2136 return ret;
2137 }
2138
2139 /* Set the memory controller to keep the memory refreshed 1957 /* Set the memory controller to keep the memory refreshed
2140 while we're asleep */ 1958 while we're asleep */
2141 for (i = 0x403f; i >= 0x4000; --i) { 1959 for (i = 0x403f; i >= 0x4000; --i) {
@@ -2173,12 +1991,10 @@ static int powerbook_sleep_3400(void)
2173 out_be32(mem_ctrl_sleep, 0x3f); 1991 out_be32(mem_ctrl_sleep, 0x3f);
2174 pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 0); 1992 pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 0);
2175 1993
2176 pmac_wakeup_devices();
2177
2178 return 0; 1994 return 0;
2179} 1995}
2180 1996
2181#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */ 1997#endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
2182 1998
2183/* 1999/*
2184 * Support for /dev/pmu device 2000 * Support for /dev/pmu device
@@ -2351,6 +2167,129 @@ pmu_release(struct inode *inode, struct file *file)
2351 return 0; 2167 return 0;
2352} 2168}
2353 2169
2170#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
2171/*
2172 * overrides the weak arch_suspend_disable_irqs in kernel/power/main.c
2173 *
2174 * XXX: Once Scott Wood's patch is merged, this needs to use the ppc_md
2175 * hooks that patch adds!
2176 */
2177void arch_suspend_disable_irqs(void)
2178{
2179#ifdef CONFIG_PMAC_BACKLIGHT
2180 /* Tell backlight code not to muck around with the chip anymore */
2181 pmu_backlight_set_sleep(1);
2182#endif
2183
2184 /* Call platform functions marked "on sleep" */
2185 pmac_pfunc_i2c_suspend();
2186 pmac_pfunc_base_suspend();
2187
2188 /* Stop preemption */
2189 preempt_disable();
2190
2191 /* Make sure the decrementer won't interrupt us */
2192 asm volatile("mtdec %0" : : "r" (0x7fffffff));
2193 /* Make sure any pending DEC interrupt occurring while we did
2194 * the above didn't re-enable the DEC */
2195 mb();
2196 asm volatile("mtdec %0" : : "r" (0x7fffffff));
2197
2198 local_irq_disable();
2199}
2200
2201static int powerbook_sleep(suspend_state_t state)
2202{
2203 int error = 0;
2204
2205 /* Wait for completion of async requests */
2206 while (!batt_req.complete)
2207 pmu_poll();
2208
2209 /* Giveup the lazy FPU & vec so we don't have to back them
2210 * up from the low level code
2211 */
2212 enable_kernel_fp();
2213
2214#ifdef CONFIG_ALTIVEC
2215 if (cpu_has_feature(CPU_FTR_ALTIVEC))
2216 enable_kernel_altivec();
2217#endif /* CONFIG_ALTIVEC */
2218
2219 switch (pmu_kind) {
2220 case PMU_OHARE_BASED:
2221 error = powerbook_sleep_3400();
2222 break;
2223 case PMU_HEATHROW_BASED:
2224 case PMU_PADDINGTON_BASED:
2225 error = powerbook_sleep_grackle();
2226 break;
2227 case PMU_KEYLARGO_BASED:
2228 error = powerbook_sleep_Core99();
2229 break;
2230 default:
2231 return -ENOSYS;
2232 }
2233
2234 if (error)
2235 return error;
2236
2237 mdelay(100);
2238
2239#ifdef CONFIG_PMAC_BACKLIGHT
2240 /* Tell backlight code it can use the chip again */
2241 pmu_backlight_set_sleep(0);
2242#endif
2243
2244 return 0;
2245}
2246
2247/*
2248 * overrides the weak arch_suspend_enable_irqs in kernel/power/main.c
2249 *
2250 * XXX: Once Scott Wood's patch is merged, this needs to use the ppc_md
2251 * hooks that patch adds!
2252 */
2253void arch_suspend_enable_irqs(void)
2254{
2255 /* Force a poll of ADB interrupts */
2256 adb_int_pending = 1;
2257 via_pmu_interrupt(0, NULL);
2258
2259 /* Restart jiffies & scheduling */
2260 wakeup_decrementer();
2261
2262 /* Re-enable local CPU interrupts */
2263 local_irq_enable();
2264 mdelay(10);
2265 preempt_enable();
2266
2267 /* Call platform functions marked "on wake" */
2268 pmac_pfunc_base_resume();
2269 pmac_pfunc_i2c_resume();
2270}
2271
2272static int pmu_sleep_valid(suspend_state_t state)
2273{
2274 return state == PM_SUSPEND_MEM
2275 && (pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, -1) >= 0);
2276}
2277
2278static struct platform_suspend_ops pmu_pm_ops = {
2279 .enter = powerbook_sleep,
2280 .valid = pmu_sleep_valid,
2281};
2282
2283static int register_pmu_pm_ops(void)
2284{
2285 suspend_set_ops(&pmu_pm_ops);
2286
2287 return 0;
2288}
2289
2290device_initcall(register_pmu_pm_ops);
2291#endif
2292
2354static int 2293static int
2355pmu_ioctl(struct inode * inode, struct file *filp, 2294pmu_ioctl(struct inode * inode, struct file *filp,
2356 u_int cmd, u_long arg) 2295 u_int cmd, u_long arg)
@@ -2359,35 +2298,15 @@ pmu_ioctl(struct inode * inode, struct file *filp,
2359 int error = -EINVAL; 2298 int error = -EINVAL;
2360 2299
2361 switch (cmd) { 2300 switch (cmd) {
2362#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
2363 case PMU_IOC_SLEEP: 2301 case PMU_IOC_SLEEP:
2364 if (!capable(CAP_SYS_ADMIN)) 2302 if (!capable(CAP_SYS_ADMIN))
2365 return -EACCES; 2303 return -EACCES;
2366 if (sleep_in_progress) 2304 return pm_suspend(PM_SUSPEND_MEM);
2367 return -EBUSY;
2368 sleep_in_progress = 1;
2369 switch (pmu_kind) {
2370 case PMU_OHARE_BASED:
2371 error = powerbook_sleep_3400();
2372 break;
2373 case PMU_HEATHROW_BASED:
2374 case PMU_PADDINGTON_BASED:
2375 error = powerbook_sleep_grackle();
2376 break;
2377 case PMU_KEYLARGO_BASED:
2378 error = powerbook_sleep_Core99();
2379 break;
2380 default:
2381 error = -ENOSYS;
2382 }
2383 sleep_in_progress = 0;
2384 break;
2385 case PMU_IOC_CAN_SLEEP: 2305 case PMU_IOC_CAN_SLEEP:
2386 if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) 2306 if (pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, -1) < 0)
2387 return put_user(0, argp); 2307 return put_user(0, argp);
2388 else 2308 else
2389 return put_user(1, argp); 2309 return put_user(1, argp);
2390#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */
2391 2310
2392#ifdef CONFIG_PMAC_BACKLIGHT_LEGACY 2311#ifdef CONFIG_PMAC_BACKLIGHT_LEGACY
2393 /* Compatibility ioctl's for backlight */ 2312 /* Compatibility ioctl's for backlight */
@@ -2395,9 +2314,6 @@ pmu_ioctl(struct inode * inode, struct file *filp,
2395 { 2314 {
2396 int brightness; 2315 int brightness;
2397 2316
2398 if (sleep_in_progress)
2399 return -EBUSY;
2400
2401 brightness = pmac_backlight_get_legacy_brightness(); 2317 brightness = pmac_backlight_get_legacy_brightness();
2402 if (brightness < 0) 2318 if (brightness < 0)
2403 return brightness; 2319 return brightness;
@@ -2409,9 +2325,6 @@ pmu_ioctl(struct inode * inode, struct file *filp,
2409 { 2325 {
2410 int brightness; 2326 int brightness;
2411 2327
2412 if (sleep_in_progress)
2413 return -EBUSY;
2414
2415 error = get_user(brightness, argp); 2328 error = get_user(brightness, argp);
2416 if (error) 2329 if (error)
2417 return error; 2330 return error;
@@ -2536,15 +2449,43 @@ pmu_polled_request(struct adb_request *req)
2536 local_irq_restore(flags); 2449 local_irq_restore(flags);
2537 return 0; 2450 return 0;
2538} 2451}
2539#endif /* DEBUG_SLEEP */
2540 2452
2453/* N.B. This doesn't work on the 3400 */
2454void pmu_blink(int n)
2455{
2456 struct adb_request req;
2541 2457
2542/* FIXME: This is a temporary set of callbacks to enable us 2458 memset(&req, 0, sizeof(req));
2543 * to do suspend-to-disk.
2544 */
2545 2459
2546#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) 2460 for (; n > 0; --n) {
2461 req.nbytes = 4;
2462 req.done = NULL;
2463 req.data[0] = 0xee;
2464 req.data[1] = 4;
2465 req.data[2] = 0;
2466 req.data[3] = 1;
2467 req.reply[0] = ADB_RET_OK;
2468 req.reply_len = 1;
2469 req.reply_expected = 0;
2470 pmu_polled_request(&req);
2471 mdelay(50);
2472 req.nbytes = 4;
2473 req.done = NULL;
2474 req.data[0] = 0xee;
2475 req.data[1] = 4;
2476 req.data[2] = 0;
2477 req.data[3] = 0;
2478 req.reply[0] = ADB_RET_OK;
2479 req.reply_len = 1;
2480 req.reply_expected = 0;
2481 pmu_polled_request(&req);
2482 mdelay(50);
2483 }
2484 mdelay(50);
2485}
2486#endif /* DEBUG_SLEEP */
2547 2487
2488#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
2548int pmu_sys_suspended; 2489int pmu_sys_suspended;
2549 2490
2550static int pmu_sys_suspend(struct sys_device *sysdev, pm_message_t state) 2491static int pmu_sys_suspend(struct sys_device *sysdev, pm_message_t state)
@@ -2578,7 +2519,7 @@ static int pmu_sys_resume(struct sys_device *sysdev)
2578 return 0; 2519 return 0;
2579} 2520}
2580 2521
2581#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */ 2522#endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
2582 2523
2583static struct sysdev_class pmu_sysclass = { 2524static struct sysdev_class pmu_sysclass = {
2584 set_kset_name("pmu"), 2525 set_kset_name("pmu"),
@@ -2589,10 +2530,10 @@ static struct sys_device device_pmu = {
2589}; 2530};
2590 2531
2591static struct sysdev_driver driver_pmu = { 2532static struct sysdev_driver driver_pmu = {
2592#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) 2533#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
2593 .suspend = &pmu_sys_suspend, 2534 .suspend = &pmu_sys_suspend,
2594 .resume = &pmu_sys_resume, 2535 .resume = &pmu_sys_resume,
2595#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */ 2536#endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
2596}; 2537};
2597 2538
2598static int __init init_pmu_sysfs(void) 2539static int __init init_pmu_sysfs(void)
@@ -2627,10 +2568,10 @@ EXPORT_SYMBOL(pmu_wait_complete);
2627EXPORT_SYMBOL(pmu_suspend); 2568EXPORT_SYMBOL(pmu_suspend);
2628EXPORT_SYMBOL(pmu_resume); 2569EXPORT_SYMBOL(pmu_resume);
2629EXPORT_SYMBOL(pmu_unlock); 2570EXPORT_SYMBOL(pmu_unlock);
2630#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) 2571#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
2631EXPORT_SYMBOL(pmu_enable_irled); 2572EXPORT_SYMBOL(pmu_enable_irled);
2632EXPORT_SYMBOL(pmu_battery_count); 2573EXPORT_SYMBOL(pmu_battery_count);
2633EXPORT_SYMBOL(pmu_batteries); 2574EXPORT_SYMBOL(pmu_batteries);
2634EXPORT_SYMBOL(pmu_power_flags); 2575EXPORT_SYMBOL(pmu_power_flags);
2635#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */ 2576#endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
2636 2577