diff options
Diffstat (limited to 'drivers/macintosh/via-pmu.c')
-rw-r--r-- | drivers/macintosh/via-pmu.c | 664 |
1 files changed, 175 insertions, 489 deletions
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index ac420b17e16f..ebec663d5d37 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> |
@@ -33,7 +31,6 @@ | |||
33 | #include <linux/adb.h> | 31 | #include <linux/adb.h> |
34 | #include <linux/pmu.h> | 32 | #include <linux/pmu.h> |
35 | #include <linux/cuda.h> | 33 | #include <linux/cuda.h> |
36 | #include <linux/smp_lock.h> | ||
37 | #include <linux/module.h> | 34 | #include <linux/module.h> |
38 | #include <linux/spinlock.h> | 35 | #include <linux/spinlock.h> |
39 | #include <linux/pm.h> | 36 | #include <linux/pm.h> |
@@ -65,9 +62,7 @@ | |||
65 | #include "via-pmu-event.h" | 62 | #include "via-pmu-event.h" |
66 | 63 | ||
67 | /* Some compile options */ | 64 | /* Some compile options */ |
68 | #undef SUSPEND_USES_PMU | 65 | #undef DEBUG_SLEEP |
69 | #define DEBUG_SLEEP | ||
70 | #undef HACKED_PCI_SAVE | ||
71 | 66 | ||
72 | /* Misc minor number allocated for /dev/pmu */ | 67 | /* Misc minor number allocated for /dev/pmu */ |
73 | #define PMU_MINOR 154 | 68 | #define PMU_MINOR 154 |
@@ -152,12 +147,9 @@ static spinlock_t pmu_lock; | |||
152 | static u8 pmu_intr_mask; | 147 | static u8 pmu_intr_mask; |
153 | static int pmu_version; | 148 | static int pmu_version; |
154 | static int drop_interrupts; | 149 | static int drop_interrupts; |
155 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) | 150 | #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32) |
156 | static int option_lid_wakeup = 1; | 151 | static int option_lid_wakeup = 1; |
157 | #endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */ | 152 | #endif /* CONFIG_SUSPEND && CONFIG_PPC32 */ |
158 | #if (defined(CONFIG_PM_SLEEP)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT_LEGACY) | ||
159 | static int sleep_in_progress; | ||
160 | #endif | ||
161 | static unsigned long async_req_locks; | 153 | static unsigned long async_req_locks; |
162 | static unsigned int pmu_irq_stats[11]; | 154 | static unsigned int pmu_irq_stats[11]; |
163 | 155 | ||
@@ -177,7 +169,6 @@ static struct proc_dir_entry *proc_pmu_batt[PMU_MAX_BATTERIES]; | |||
177 | 169 | ||
178 | int __fake_sleep; | 170 | int __fake_sleep; |
179 | int asleep; | 171 | int asleep; |
180 | BLOCKING_NOTIFIER_HEAD(sleep_notifier_list); | ||
181 | 172 | ||
182 | #ifdef CONFIG_ADB | 173 | #ifdef CONFIG_ADB |
183 | static int adb_dev_map; | 174 | static int adb_dev_map; |
@@ -224,7 +215,7 @@ extern void enable_kernel_fp(void); | |||
224 | 215 | ||
225 | #ifdef DEBUG_SLEEP | 216 | #ifdef DEBUG_SLEEP |
226 | int pmu_polled_request(struct adb_request *req); | 217 | int pmu_polled_request(struct adb_request *req); |
227 | int pmu_wink(struct adb_request *req); | 218 | void pmu_blink(int n); |
228 | #endif | 219 | #endif |
229 | 220 | ||
230 | /* | 221 | /* |
@@ -875,7 +866,7 @@ proc_read_options(char *page, char **start, off_t off, | |||
875 | { | 866 | { |
876 | char *p = page; | 867 | char *p = page; |
877 | 868 | ||
878 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) | 869 | #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32) |
879 | if (pmu_kind == PMU_KEYLARGO_BASED && | 870 | if (pmu_kind == PMU_KEYLARGO_BASED && |
880 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0) | 871 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0) |
881 | p += sprintf(p, "lid_wakeup=%d\n", option_lid_wakeup); | 872 | p += sprintf(p, "lid_wakeup=%d\n", option_lid_wakeup); |
@@ -916,7 +907,7 @@ proc_write_options(struct file *file, const char __user *buffer, | |||
916 | *(val++) = 0; | 907 | *(val++) = 0; |
917 | while(*val == ' ') | 908 | while(*val == ' ') |
918 | val++; | 909 | val++; |
919 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) | 910 | #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32) |
920 | if (pmu_kind == PMU_KEYLARGO_BASED && | 911 | if (pmu_kind == PMU_KEYLARGO_BASED && |
921 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0) | 912 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0) |
922 | if (!strcmp(label, "lid_wakeup")) | 913 | if (!strcmp(label, "lid_wakeup")) |
@@ -1256,9 +1247,7 @@ void | |||
1256 | pmu_suspend(void) | 1247 | pmu_suspend(void) |
1257 | { | 1248 | { |
1258 | unsigned long flags; | 1249 | unsigned long flags; |
1259 | #ifdef SUSPEND_USES_PMU | 1250 | |
1260 | struct adb_request *req; | ||
1261 | #endif | ||
1262 | if (!via) | 1251 | if (!via) |
1263 | return; | 1252 | return; |
1264 | 1253 | ||
@@ -1276,17 +1265,10 @@ pmu_suspend(void) | |||
1276 | via_pmu_interrupt(0, NULL); | 1265 | via_pmu_interrupt(0, NULL); |
1277 | spin_lock_irqsave(&pmu_lock, flags); | 1266 | spin_lock_irqsave(&pmu_lock, flags); |
1278 | if (!adb_int_pending && pmu_state == idle && !req_awaiting_reply) { | 1267 | if (!adb_int_pending && pmu_state == idle && !req_awaiting_reply) { |
1279 | #ifdef SUSPEND_USES_PMU | ||
1280 | pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0); | ||
1281 | spin_unlock_irqrestore(&pmu_lock, flags); | ||
1282 | while(!req.complete) | ||
1283 | pmu_poll(); | ||
1284 | #else /* SUSPEND_USES_PMU */ | ||
1285 | if (gpio_irq >= 0) | 1268 | if (gpio_irq >= 0) |
1286 | disable_irq_nosync(gpio_irq); | 1269 | disable_irq_nosync(gpio_irq); |
1287 | out_8(&via[IER], CB1_INT | IER_CLR); | 1270 | out_8(&via[IER], CB1_INT | IER_CLR); |
1288 | spin_unlock_irqrestore(&pmu_lock, flags); | 1271 | spin_unlock_irqrestore(&pmu_lock, flags); |
1289 | #endif /* SUSPEND_USES_PMU */ | ||
1290 | break; | 1272 | break; |
1291 | } | 1273 | } |
1292 | } while (1); | 1274 | } while (1); |
@@ -1307,18 +1289,11 @@ pmu_resume(void) | |||
1307 | return; | 1289 | return; |
1308 | } | 1290 | } |
1309 | adb_int_pending = 1; | 1291 | adb_int_pending = 1; |
1310 | #ifdef SUSPEND_USES_PMU | ||
1311 | pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask); | ||
1312 | spin_unlock_irqrestore(&pmu_lock, flags); | ||
1313 | while(!req.complete) | ||
1314 | pmu_poll(); | ||
1315 | #else /* SUSPEND_USES_PMU */ | ||
1316 | if (gpio_irq >= 0) | 1292 | if (gpio_irq >= 0) |
1317 | enable_irq(gpio_irq); | 1293 | enable_irq(gpio_irq); |
1318 | out_8(&via[IER], CB1_INT | IER_SET); | 1294 | out_8(&via[IER], CB1_INT | IER_SET); |
1319 | spin_unlock_irqrestore(&pmu_lock, flags); | 1295 | spin_unlock_irqrestore(&pmu_lock, flags); |
1320 | pmu_poll(); | 1296 | pmu_poll(); |
1321 | #endif /* SUSPEND_USES_PMU */ | ||
1322 | } | 1297 | } |
1323 | 1298 | ||
1324 | /* Interrupt data could be the result data from an ADB cmd */ | 1299 | /* Interrupt data could be the result data from an ADB cmd */ |
@@ -1738,228 +1713,7 @@ pmu_present(void) | |||
1738 | return via != 0; | 1713 | return via != 0; |
1739 | } | 1714 | } |
1740 | 1715 | ||
1741 | #ifdef CONFIG_PM_SLEEP | 1716 | #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32) |
1742 | |||
1743 | static LIST_HEAD(sleep_notifiers); | ||
1744 | |||
1745 | int | ||
1746 | pmu_register_sleep_notifier(struct pmu_sleep_notifier *n) | ||
1747 | { | ||
1748 | struct list_head *list; | ||
1749 | struct pmu_sleep_notifier *notifier; | ||
1750 | |||
1751 | for (list = sleep_notifiers.next; list != &sleep_notifiers; | ||
1752 | list = list->next) { | ||
1753 | notifier = list_entry(list, struct pmu_sleep_notifier, list); | ||
1754 | if (n->priority > notifier->priority) | ||
1755 | break; | ||
1756 | } | ||
1757 | __list_add(&n->list, list->prev, list); | ||
1758 | return 0; | ||
1759 | } | ||
1760 | EXPORT_SYMBOL(pmu_register_sleep_notifier); | ||
1761 | |||
1762 | int | ||
1763 | pmu_unregister_sleep_notifier(struct pmu_sleep_notifier* n) | ||
1764 | { | ||
1765 | if (n->list.next == 0) | ||
1766 | return -ENOENT; | ||
1767 | list_del(&n->list); | ||
1768 | n->list.next = NULL; | ||
1769 | return 0; | ||
1770 | } | ||
1771 | EXPORT_SYMBOL(pmu_unregister_sleep_notifier); | ||
1772 | #endif /* CONFIG_PM_SLEEP */ | ||
1773 | |||
1774 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) | ||
1775 | |||
1776 | /* Sleep is broadcast last-to-first */ | ||
1777 | static void broadcast_sleep(int when) | ||
1778 | { | ||
1779 | struct list_head *list; | ||
1780 | struct pmu_sleep_notifier *notifier; | ||
1781 | |||
1782 | for (list = sleep_notifiers.prev; list != &sleep_notifiers; | ||
1783 | list = list->prev) { | ||
1784 | notifier = list_entry(list, struct pmu_sleep_notifier, list); | ||
1785 | notifier->notifier_call(notifier, when); | ||
1786 | } | ||
1787 | } | ||
1788 | |||
1789 | /* Wake is broadcast first-to-last */ | ||
1790 | static void broadcast_wake(void) | ||
1791 | { | ||
1792 | struct list_head *list; | ||
1793 | struct pmu_sleep_notifier *notifier; | ||
1794 | |||
1795 | for (list = sleep_notifiers.next; list != &sleep_notifiers; | ||
1796 | list = list->next) { | ||
1797 | notifier = list_entry(list, struct pmu_sleep_notifier, list); | ||
1798 | notifier->notifier_call(notifier, PBOOK_WAKE); | ||
1799 | } | ||
1800 | } | ||
1801 | |||
1802 | /* | ||
1803 | * This struct is used to store config register values for | ||
1804 | * PCI devices which may get powered off when we sleep. | ||
1805 | */ | ||
1806 | static struct pci_save { | ||
1807 | #ifndef HACKED_PCI_SAVE | ||
1808 | u16 command; | ||
1809 | u16 cache_lat; | ||
1810 | u16 intr; | ||
1811 | u32 rom_address; | ||
1812 | #else | ||
1813 | u32 config[16]; | ||
1814 | #endif | ||
1815 | } *pbook_pci_saves; | ||
1816 | static int pbook_npci_saves; | ||
1817 | |||
1818 | static void | ||
1819 | pbook_alloc_pci_save(void) | ||
1820 | { | ||
1821 | int npci; | ||
1822 | struct pci_dev *pd = NULL; | ||
1823 | |||
1824 | npci = 0; | ||
1825 | while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) { | ||
1826 | ++npci; | ||
1827 | } | ||
1828 | if (npci == 0) | ||
1829 | return; | ||
1830 | pbook_pci_saves = (struct pci_save *) | ||
1831 | kmalloc(npci * sizeof(struct pci_save), GFP_KERNEL); | ||
1832 | pbook_npci_saves = npci; | ||
1833 | } | ||
1834 | |||
1835 | static void | ||
1836 | pbook_free_pci_save(void) | ||
1837 | { | ||
1838 | if (pbook_pci_saves == NULL) | ||
1839 | return; | ||
1840 | kfree(pbook_pci_saves); | ||
1841 | pbook_pci_saves = NULL; | ||
1842 | pbook_npci_saves = 0; | ||
1843 | } | ||
1844 | |||
1845 | static void | ||
1846 | pbook_pci_save(void) | ||
1847 | { | ||
1848 | struct pci_save *ps = pbook_pci_saves; | ||
1849 | struct pci_dev *pd = NULL; | ||
1850 | int npci = pbook_npci_saves; | ||
1851 | |||
1852 | if (ps == NULL) | ||
1853 | return; | ||
1854 | |||
1855 | while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) { | ||
1856 | if (npci-- == 0) { | ||
1857 | pci_dev_put(pd); | ||
1858 | return; | ||
1859 | } | ||
1860 | #ifndef HACKED_PCI_SAVE | ||
1861 | pci_read_config_word(pd, PCI_COMMAND, &ps->command); | ||
1862 | pci_read_config_word(pd, PCI_CACHE_LINE_SIZE, &ps->cache_lat); | ||
1863 | pci_read_config_word(pd, PCI_INTERRUPT_LINE, &ps->intr); | ||
1864 | pci_read_config_dword(pd, PCI_ROM_ADDRESS, &ps->rom_address); | ||
1865 | #else | ||
1866 | int i; | ||
1867 | for (i=1;i<16;i++) | ||
1868 | pci_read_config_dword(pd, i<<4, &ps->config[i]); | ||
1869 | #endif | ||
1870 | ++ps; | ||
1871 | } | ||
1872 | } | ||
1873 | |||
1874 | /* For this to work, we must take care of a few things: If gmac was enabled | ||
1875 | * during boot, it will be in the pci dev list. If it's disabled at this point | ||
1876 | * (and it will probably be), then you can't access it's config space. | ||
1877 | */ | ||
1878 | static void | ||
1879 | pbook_pci_restore(void) | ||
1880 | { | ||
1881 | u16 cmd; | ||
1882 | struct pci_save *ps = pbook_pci_saves - 1; | ||
1883 | struct pci_dev *pd = NULL; | ||
1884 | int npci = pbook_npci_saves; | ||
1885 | int j; | ||
1886 | |||
1887 | while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) { | ||
1888 | #ifdef HACKED_PCI_SAVE | ||
1889 | int i; | ||
1890 | if (npci-- == 0) { | ||
1891 | pci_dev_put(pd); | ||
1892 | return; | ||
1893 | } | ||
1894 | ps++; | ||
1895 | for (i=2;i<16;i++) | ||
1896 | pci_write_config_dword(pd, i<<4, ps->config[i]); | ||
1897 | pci_write_config_dword(pd, 4, ps->config[1]); | ||
1898 | #else | ||
1899 | if (npci-- == 0) | ||
1900 | return; | ||
1901 | ps++; | ||
1902 | if (ps->command == 0) | ||
1903 | continue; | ||
1904 | pci_read_config_word(pd, PCI_COMMAND, &cmd); | ||
1905 | if ((ps->command & ~cmd) == 0) | ||
1906 | continue; | ||
1907 | switch (pd->hdr_type) { | ||
1908 | case PCI_HEADER_TYPE_NORMAL: | ||
1909 | for (j = 0; j < 6; ++j) | ||
1910 | pci_write_config_dword(pd, | ||
1911 | PCI_BASE_ADDRESS_0 + j*4, | ||
1912 | pd->resource[j].start); | ||
1913 | pci_write_config_dword(pd, PCI_ROM_ADDRESS, | ||
1914 | ps->rom_address); | ||
1915 | pci_write_config_word(pd, PCI_CACHE_LINE_SIZE, | ||
1916 | ps->cache_lat); | ||
1917 | pci_write_config_word(pd, PCI_INTERRUPT_LINE, | ||
1918 | ps->intr); | ||
1919 | pci_write_config_word(pd, PCI_COMMAND, ps->command); | ||
1920 | break; | ||
1921 | } | ||
1922 | #endif | ||
1923 | } | ||
1924 | } | ||
1925 | |||
1926 | #ifdef DEBUG_SLEEP | ||
1927 | /* N.B. This doesn't work on the 3400 */ | ||
1928 | void | ||
1929 | pmu_blink(int n) | ||
1930 | { | ||
1931 | struct adb_request req; | ||
1932 | |||
1933 | memset(&req, 0, sizeof(req)); | ||
1934 | |||
1935 | for (; n > 0; --n) { | ||
1936 | req.nbytes = 4; | ||
1937 | req.done = NULL; | ||
1938 | req.data[0] = 0xee; | ||
1939 | req.data[1] = 4; | ||
1940 | req.data[2] = 0; | ||
1941 | req.data[3] = 1; | ||
1942 | req.reply[0] = ADB_RET_OK; | ||
1943 | req.reply_len = 1; | ||
1944 | req.reply_expected = 0; | ||
1945 | pmu_polled_request(&req); | ||
1946 | mdelay(50); | ||
1947 | req.nbytes = 4; | ||
1948 | req.done = NULL; | ||
1949 | req.data[0] = 0xee; | ||
1950 | req.data[1] = 4; | ||
1951 | req.data[2] = 0; | ||
1952 | req.data[3] = 0; | ||
1953 | req.reply[0] = ADB_RET_OK; | ||
1954 | req.reply_len = 1; | ||
1955 | req.reply_expected = 0; | ||
1956 | pmu_polled_request(&req); | ||
1957 | mdelay(50); | ||
1958 | } | ||
1959 | mdelay(50); | ||
1960 | } | ||
1961 | #endif | ||
1962 | |||
1963 | /* | 1717 | /* |
1964 | * Put the powerbook to sleep. | 1718 | * Put the powerbook to sleep. |
1965 | */ | 1719 | */ |
@@ -1994,134 +1748,6 @@ restore_via_state(void) | |||
1994 | out_8(&via[IER], IER_SET | SR_INT | CB1_INT); | 1748 | out_8(&via[IER], IER_SET | SR_INT | CB1_INT); |
1995 | } | 1749 | } |
1996 | 1750 | ||
1997 | extern void pmu_backlight_set_sleep(int sleep); | ||
1998 | |||
1999 | static int | ||
2000 | pmac_suspend_devices(void) | ||
2001 | { | ||
2002 | int ret; | ||
2003 | |||
2004 | pm_prepare_console(); | ||
2005 | |||
2006 | /* Notify old-style device drivers */ | ||
2007 | broadcast_sleep(PBOOK_SLEEP_REQUEST); | ||
2008 | |||
2009 | /* Sync the disks. */ | ||
2010 | /* XXX It would be nice to have some way to ensure that | ||
2011 | * nobody is dirtying any new buffers while we wait. That | ||
2012 | * could be achieved using the refrigerator for processes | ||
2013 | * that swsusp uses | ||
2014 | */ | ||
2015 | sys_sync(); | ||
2016 | |||
2017 | broadcast_sleep(PBOOK_SLEEP_NOW); | ||
2018 | |||
2019 | /* Send suspend call to devices, hold the device core's dpm_sem */ | ||
2020 | ret = device_suspend(PMSG_SUSPEND); | ||
2021 | if (ret) { | ||
2022 | broadcast_wake(); | ||
2023 | printk(KERN_ERR "Driver sleep failed\n"); | ||
2024 | return -EBUSY; | ||
2025 | } | ||
2026 | |||
2027 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
2028 | /* Tell backlight code not to muck around with the chip anymore */ | ||
2029 | pmu_backlight_set_sleep(1); | ||
2030 | #endif | ||
2031 | |||
2032 | /* Call platform functions marked "on sleep" */ | ||
2033 | pmac_pfunc_i2c_suspend(); | ||
2034 | pmac_pfunc_base_suspend(); | ||
2035 | |||
2036 | /* Stop preemption */ | ||
2037 | preempt_disable(); | ||
2038 | |||
2039 | /* Make sure the decrementer won't interrupt us */ | ||
2040 | asm volatile("mtdec %0" : : "r" (0x7fffffff)); | ||
2041 | /* Make sure any pending DEC interrupt occurring while we did | ||
2042 | * the above didn't re-enable the DEC */ | ||
2043 | mb(); | ||
2044 | asm volatile("mtdec %0" : : "r" (0x7fffffff)); | ||
2045 | |||
2046 | /* We can now disable MSR_EE. This code of course works properly only | ||
2047 | * on UP machines... For SMP, if we ever implement sleep, we'll have to | ||
2048 | * stop the "other" CPUs way before we do all that stuff. | ||
2049 | */ | ||
2050 | local_irq_disable(); | ||
2051 | |||
2052 | /* Broadcast power down irq | ||
2053 | * This isn't that useful in most cases (only directly wired devices can | ||
2054 | * use this but still... This will take care of sysdev's as well, so | ||
2055 | * we exit from here with local irqs disabled and PIC off. | ||
2056 | */ | ||
2057 | ret = device_power_down(PMSG_SUSPEND); | ||
2058 | if (ret) { | ||
2059 | wakeup_decrementer(); | ||
2060 | local_irq_enable(); | ||
2061 | preempt_enable(); | ||
2062 | device_resume(); | ||
2063 | broadcast_wake(); | ||
2064 | printk(KERN_ERR "Driver powerdown failed\n"); | ||
2065 | return -EBUSY; | ||
2066 | } | ||
2067 | |||
2068 | /* Wait for completion of async requests */ | ||
2069 | while (!batt_req.complete) | ||
2070 | pmu_poll(); | ||
2071 | |||
2072 | /* Giveup the lazy FPU & vec so we don't have to back them | ||
2073 | * up from the low level code | ||
2074 | */ | ||
2075 | enable_kernel_fp(); | ||
2076 | |||
2077 | #ifdef CONFIG_ALTIVEC | ||
2078 | if (cpu_has_feature(CPU_FTR_ALTIVEC)) | ||
2079 | enable_kernel_altivec(); | ||
2080 | #endif /* CONFIG_ALTIVEC */ | ||
2081 | |||
2082 | return 0; | ||
2083 | } | ||
2084 | |||
2085 | static int | ||
2086 | pmac_wakeup_devices(void) | ||
2087 | { | ||
2088 | mdelay(100); | ||
2089 | |||
2090 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
2091 | /* Tell backlight code it can use the chip again */ | ||
2092 | pmu_backlight_set_sleep(0); | ||
2093 | #endif | ||
2094 | |||
2095 | /* Power back up system devices (including the PIC) */ | ||
2096 | device_power_up(); | ||
2097 | |||
2098 | /* Force a poll of ADB interrupts */ | ||
2099 | adb_int_pending = 1; | ||
2100 | via_pmu_interrupt(0, NULL); | ||
2101 | |||
2102 | /* Restart jiffies & scheduling */ | ||
2103 | wakeup_decrementer(); | ||
2104 | |||
2105 | /* Re-enable local CPU interrupts */ | ||
2106 | local_irq_enable(); | ||
2107 | mdelay(10); | ||
2108 | preempt_enable(); | ||
2109 | |||
2110 | /* Call platform functions marked "on wake" */ | ||
2111 | pmac_pfunc_base_resume(); | ||
2112 | pmac_pfunc_i2c_resume(); | ||
2113 | |||
2114 | /* Resume devices */ | ||
2115 | device_resume(); | ||
2116 | |||
2117 | /* Notify old style drivers */ | ||
2118 | broadcast_wake(); | ||
2119 | |||
2120 | pm_restore_console(); | ||
2121 | |||
2122 | return 0; | ||
2123 | } | ||
2124 | |||
2125 | #define GRACKLE_PM (1<<7) | 1751 | #define GRACKLE_PM (1<<7) |
2126 | #define GRACKLE_DOZE (1<<5) | 1752 | #define GRACKLE_DOZE (1<<5) |
2127 | #define GRACKLE_NAP (1<<4) | 1753 | #define GRACKLE_NAP (1<<4) |
@@ -2132,19 +1758,12 @@ static int powerbook_sleep_grackle(void) | |||
2132 | unsigned long save_l2cr; | 1758 | unsigned long save_l2cr; |
2133 | unsigned short pmcr1; | 1759 | unsigned short pmcr1; |
2134 | struct adb_request req; | 1760 | struct adb_request req; |
2135 | int ret; | ||
2136 | struct pci_dev *grackle; | 1761 | struct pci_dev *grackle; |
2137 | 1762 | ||
2138 | grackle = pci_get_bus_and_slot(0, 0); | 1763 | grackle = pci_get_bus_and_slot(0, 0); |
2139 | if (!grackle) | 1764 | if (!grackle) |
2140 | return -ENODEV; | 1765 | return -ENODEV; |
2141 | 1766 | ||
2142 | ret = pmac_suspend_devices(); | ||
2143 | if (ret) { | ||
2144 | printk(KERN_ERR "Sleep rejected by devices\n"); | ||
2145 | return ret; | ||
2146 | } | ||
2147 | |||
2148 | /* Turn off various things. Darwin does some retry tests here... */ | 1767 | /* Turn off various things. Darwin does some retry tests here... */ |
2149 | pmu_request(&req, NULL, 2, PMU_POWER_CTRL0, PMU_POW0_OFF|PMU_POW0_HARD_DRIVE); | 1768 | pmu_request(&req, NULL, 2, PMU_POWER_CTRL0, PMU_POW0_OFF|PMU_POW0_HARD_DRIVE); |
2150 | pmu_wait_complete(&req); | 1769 | pmu_wait_complete(&req); |
@@ -2207,8 +1826,6 @@ static int powerbook_sleep_grackle(void) | |||
2207 | PMU_POW_ON|PMU_POW_BACKLIGHT|PMU_POW_CHARGER|PMU_POW_IRLED|PMU_POW_MEDIABAY); | 1826 | PMU_POW_ON|PMU_POW_BACKLIGHT|PMU_POW_CHARGER|PMU_POW_IRLED|PMU_POW_MEDIABAY); |
2208 | pmu_wait_complete(&req); | 1827 | pmu_wait_complete(&req); |
2209 | 1828 | ||
2210 | pmac_wakeup_devices(); | ||
2211 | |||
2212 | return 0; | 1829 | return 0; |
2213 | } | 1830 | } |
2214 | 1831 | ||
@@ -2218,7 +1835,6 @@ powerbook_sleep_Core99(void) | |||
2218 | unsigned long save_l2cr; | 1835 | unsigned long save_l2cr; |
2219 | unsigned long save_l3cr; | 1836 | unsigned long save_l3cr; |
2220 | struct adb_request req; | 1837 | struct adb_request req; |
2221 | int ret; | ||
2222 | 1838 | ||
2223 | if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) { | 1839 | if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) { |
2224 | printk(KERN_ERR "Sleep mode not supported on this machine\n"); | 1840 | printk(KERN_ERR "Sleep mode not supported on this machine\n"); |
@@ -2228,12 +1844,6 @@ powerbook_sleep_Core99(void) | |||
2228 | if (num_online_cpus() > 1 || cpu_is_offline(0)) | 1844 | if (num_online_cpus() > 1 || cpu_is_offline(0)) |
2229 | return -EAGAIN; | 1845 | return -EAGAIN; |
2230 | 1846 | ||
2231 | ret = pmac_suspend_devices(); | ||
2232 | if (ret) { | ||
2233 | printk(KERN_ERR "Sleep rejected by devices\n"); | ||
2234 | return ret; | ||
2235 | } | ||
2236 | |||
2237 | /* Stop environment and ADB interrupts */ | 1847 | /* Stop environment and ADB interrupts */ |
2238 | pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0); | 1848 | pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0); |
2239 | pmu_wait_complete(&req); | 1849 | pmu_wait_complete(&req); |
@@ -2304,45 +1914,33 @@ powerbook_sleep_Core99(void) | |||
2304 | /* Restore LPJ, cpufreq will adjust the cpu frequency */ | 1914 | /* Restore LPJ, cpufreq will adjust the cpu frequency */ |
2305 | loops_per_jiffy /= 2; | 1915 | loops_per_jiffy /= 2; |
2306 | 1916 | ||
2307 | pmac_wakeup_devices(); | ||
2308 | |||
2309 | return 0; | 1917 | return 0; |
2310 | } | 1918 | } |
2311 | 1919 | ||
2312 | #define PB3400_MEM_CTRL 0xf8000000 | 1920 | #define PB3400_MEM_CTRL 0xf8000000 |
2313 | #define PB3400_MEM_CTRL_SLEEP 0x70 | 1921 | #define PB3400_MEM_CTRL_SLEEP 0x70 |
2314 | 1922 | ||
2315 | static int | 1923 | static void __iomem *pb3400_mem_ctrl; |
2316 | powerbook_sleep_3400(void) | 1924 | |
1925 | static void powerbook_sleep_init_3400(void) | ||
1926 | { | ||
1927 | /* map in the memory controller registers */ | ||
1928 | pb3400_mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100); | ||
1929 | if (pb3400_mem_ctrl == NULL) | ||
1930 | printk(KERN_WARNING "ioremap failed: sleep won't be possible"); | ||
1931 | } | ||
1932 | |||
1933 | static int powerbook_sleep_3400(void) | ||
2317 | { | 1934 | { |
2318 | int ret, i, x; | 1935 | int i, x; |
2319 | unsigned int hid0; | 1936 | unsigned int hid0; |
2320 | unsigned long p; | 1937 | unsigned long msr; |
2321 | struct adb_request sleep_req; | 1938 | struct adb_request sleep_req; |
2322 | void __iomem *mem_ctrl; | ||
2323 | unsigned int __iomem *mem_ctrl_sleep; | 1939 | unsigned int __iomem *mem_ctrl_sleep; |
2324 | 1940 | ||
2325 | /* first map in the memory controller registers */ | 1941 | if (pb3400_mem_ctrl == NULL) |
2326 | mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100); | ||
2327 | if (mem_ctrl == NULL) { | ||
2328 | printk("powerbook_sleep_3400: ioremap failed\n"); | ||
2329 | return -ENOMEM; | 1942 | return -ENOMEM; |
2330 | } | 1943 | mem_ctrl_sleep = pb3400_mem_ctrl + PB3400_MEM_CTRL_SLEEP; |
2331 | mem_ctrl_sleep = mem_ctrl + PB3400_MEM_CTRL_SLEEP; | ||
2332 | |||
2333 | /* Allocate room for PCI save */ | ||
2334 | pbook_alloc_pci_save(); | ||
2335 | |||
2336 | ret = pmac_suspend_devices(); | ||
2337 | if (ret) { | ||
2338 | pbook_free_pci_save(); | ||
2339 | iounmap(mem_ctrl); | ||
2340 | printk(KERN_ERR "Sleep rejected by devices\n"); | ||
2341 | return ret; | ||
2342 | } | ||
2343 | |||
2344 | /* Save the state of PCI config space for some slots */ | ||
2345 | pbook_pci_save(); | ||
2346 | 1944 | ||
2347 | /* Set the memory controller to keep the memory refreshed | 1945 | /* Set the memory controller to keep the memory refreshed |
2348 | while we're asleep */ | 1946 | while we're asleep */ |
@@ -2357,41 +1955,34 @@ powerbook_sleep_3400(void) | |||
2357 | 1955 | ||
2358 | /* Ask the PMU to put us to sleep */ | 1956 | /* Ask the PMU to put us to sleep */ |
2359 | pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T'); | 1957 | pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T'); |
2360 | while (!sleep_req.complete) | 1958 | pmu_wait_complete(&sleep_req); |
2361 | mb(); | 1959 | pmu_unlock(); |
2362 | 1960 | ||
2363 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,1); | 1961 | pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 1); |
2364 | 1962 | ||
2365 | /* displacement-flush the L2 cache - necessary? */ | ||
2366 | for (p = KERNELBASE; p < KERNELBASE + 0x100000; p += 0x1000) | ||
2367 | i = *(volatile int *)p; | ||
2368 | asleep = 1; | 1963 | asleep = 1; |
2369 | 1964 | ||
2370 | /* Put the CPU into sleep mode */ | 1965 | /* Put the CPU into sleep mode */ |
2371 | hid0 = mfspr(SPRN_HID0); | 1966 | hid0 = mfspr(SPRN_HID0); |
2372 | hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP; | 1967 | hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP; |
2373 | mtspr(SPRN_HID0, hid0); | 1968 | mtspr(SPRN_HID0, hid0); |
2374 | mtmsr(mfmsr() | MSR_POW | MSR_EE); | 1969 | local_irq_enable(); |
2375 | udelay(10); | 1970 | msr = mfmsr() | MSR_POW; |
1971 | while (asleep) { | ||
1972 | mb(); | ||
1973 | mtmsr(msr); | ||
1974 | isync(); | ||
1975 | } | ||
1976 | local_irq_disable(); | ||
2376 | 1977 | ||
2377 | /* OK, we're awake again, start restoring things */ | 1978 | /* OK, we're awake again, start restoring things */ |
2378 | out_be32(mem_ctrl_sleep, 0x3f); | 1979 | out_be32(mem_ctrl_sleep, 0x3f); |
2379 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0); | 1980 | pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 0); |
2380 | pbook_pci_restore(); | ||
2381 | pmu_unlock(); | ||
2382 | |||
2383 | /* wait for the PMU interrupt sequence to complete */ | ||
2384 | while (asleep) | ||
2385 | mb(); | ||
2386 | |||
2387 | pmac_wakeup_devices(); | ||
2388 | pbook_free_pci_save(); | ||
2389 | iounmap(mem_ctrl); | ||
2390 | 1981 | ||
2391 | return 0; | 1982 | return 0; |
2392 | } | 1983 | } |
2393 | 1984 | ||
2394 | #endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */ | 1985 | #endif /* CONFIG_SUSPEND && CONFIG_PPC32 */ |
2395 | 1986 | ||
2396 | /* | 1987 | /* |
2397 | * Support for /dev/pmu device | 1988 | * Support for /dev/pmu device |
@@ -2548,7 +2139,6 @@ pmu_release(struct inode *inode, struct file *file) | |||
2548 | struct pmu_private *pp = file->private_data; | 2139 | struct pmu_private *pp = file->private_data; |
2549 | unsigned long flags; | 2140 | unsigned long flags; |
2550 | 2141 | ||
2551 | lock_kernel(); | ||
2552 | if (pp != 0) { | 2142 | if (pp != 0) { |
2553 | file->private_data = NULL; | 2143 | file->private_data = NULL; |
2554 | spin_lock_irqsave(&all_pvt_lock, flags); | 2144 | spin_lock_irqsave(&all_pvt_lock, flags); |
@@ -2562,10 +2152,96 @@ pmu_release(struct inode *inode, struct file *file) | |||
2562 | 2152 | ||
2563 | kfree(pp); | 2153 | kfree(pp); |
2564 | } | 2154 | } |
2565 | unlock_kernel(); | ||
2566 | return 0; | 2155 | return 0; |
2567 | } | 2156 | } |
2568 | 2157 | ||
2158 | #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32) | ||
2159 | static void pmac_suspend_disable_irqs(void) | ||
2160 | { | ||
2161 | /* Call platform functions marked "on sleep" */ | ||
2162 | pmac_pfunc_i2c_suspend(); | ||
2163 | pmac_pfunc_base_suspend(); | ||
2164 | } | ||
2165 | |||
2166 | static int powerbook_sleep(suspend_state_t state) | ||
2167 | { | ||
2168 | int error = 0; | ||
2169 | |||
2170 | /* Wait for completion of async requests */ | ||
2171 | while (!batt_req.complete) | ||
2172 | pmu_poll(); | ||
2173 | |||
2174 | /* Giveup the lazy FPU & vec so we don't have to back them | ||
2175 | * up from the low level code | ||
2176 | */ | ||
2177 | enable_kernel_fp(); | ||
2178 | |||
2179 | #ifdef CONFIG_ALTIVEC | ||
2180 | if (cpu_has_feature(CPU_FTR_ALTIVEC)) | ||
2181 | enable_kernel_altivec(); | ||
2182 | #endif /* CONFIG_ALTIVEC */ | ||
2183 | |||
2184 | switch (pmu_kind) { | ||
2185 | case PMU_OHARE_BASED: | ||
2186 | error = powerbook_sleep_3400(); | ||
2187 | break; | ||
2188 | case PMU_HEATHROW_BASED: | ||
2189 | case PMU_PADDINGTON_BASED: | ||
2190 | error = powerbook_sleep_grackle(); | ||
2191 | break; | ||
2192 | case PMU_KEYLARGO_BASED: | ||
2193 | error = powerbook_sleep_Core99(); | ||
2194 | break; | ||
2195 | default: | ||
2196 | return -ENOSYS; | ||
2197 | } | ||
2198 | |||
2199 | if (error) | ||
2200 | return error; | ||
2201 | |||
2202 | mdelay(100); | ||
2203 | |||
2204 | return 0; | ||
2205 | } | ||
2206 | |||
2207 | static void pmac_suspend_enable_irqs(void) | ||
2208 | { | ||
2209 | /* Force a poll of ADB interrupts */ | ||
2210 | adb_int_pending = 1; | ||
2211 | via_pmu_interrupt(0, NULL); | ||
2212 | |||
2213 | mdelay(10); | ||
2214 | |||
2215 | /* Call platform functions marked "on wake" */ | ||
2216 | pmac_pfunc_base_resume(); | ||
2217 | pmac_pfunc_i2c_resume(); | ||
2218 | } | ||
2219 | |||
2220 | static int pmu_sleep_valid(suspend_state_t state) | ||
2221 | { | ||
2222 | return state == PM_SUSPEND_MEM | ||
2223 | && (pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, -1) >= 0); | ||
2224 | } | ||
2225 | |||
2226 | static struct platform_suspend_ops pmu_pm_ops = { | ||
2227 | .enter = powerbook_sleep, | ||
2228 | .valid = pmu_sleep_valid, | ||
2229 | }; | ||
2230 | |||
2231 | static int register_pmu_pm_ops(void) | ||
2232 | { | ||
2233 | if (pmu_kind == PMU_OHARE_BASED) | ||
2234 | powerbook_sleep_init_3400(); | ||
2235 | ppc_md.suspend_disable_irqs = pmac_suspend_disable_irqs; | ||
2236 | ppc_md.suspend_enable_irqs = pmac_suspend_enable_irqs; | ||
2237 | suspend_set_ops(&pmu_pm_ops); | ||
2238 | |||
2239 | return 0; | ||
2240 | } | ||
2241 | |||
2242 | device_initcall(register_pmu_pm_ops); | ||
2243 | #endif | ||
2244 | |||
2569 | static int | 2245 | static int |
2570 | pmu_ioctl(struct inode * inode, struct file *filp, | 2246 | pmu_ioctl(struct inode * inode, struct file *filp, |
2571 | u_int cmd, u_long arg) | 2247 | u_int cmd, u_long arg) |
@@ -2574,35 +2250,15 @@ pmu_ioctl(struct inode * inode, struct file *filp, | |||
2574 | int error = -EINVAL; | 2250 | int error = -EINVAL; |
2575 | 2251 | ||
2576 | switch (cmd) { | 2252 | switch (cmd) { |
2577 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) | ||
2578 | case PMU_IOC_SLEEP: | 2253 | case PMU_IOC_SLEEP: |
2579 | if (!capable(CAP_SYS_ADMIN)) | 2254 | if (!capable(CAP_SYS_ADMIN)) |
2580 | return -EACCES; | 2255 | return -EACCES; |
2581 | if (sleep_in_progress) | 2256 | return pm_suspend(PM_SUSPEND_MEM); |
2582 | return -EBUSY; | ||
2583 | sleep_in_progress = 1; | ||
2584 | switch (pmu_kind) { | ||
2585 | case PMU_OHARE_BASED: | ||
2586 | error = powerbook_sleep_3400(); | ||
2587 | break; | ||
2588 | case PMU_HEATHROW_BASED: | ||
2589 | case PMU_PADDINGTON_BASED: | ||
2590 | error = powerbook_sleep_grackle(); | ||
2591 | break; | ||
2592 | case PMU_KEYLARGO_BASED: | ||
2593 | error = powerbook_sleep_Core99(); | ||
2594 | break; | ||
2595 | default: | ||
2596 | error = -ENOSYS; | ||
2597 | } | ||
2598 | sleep_in_progress = 0; | ||
2599 | break; | ||
2600 | case PMU_IOC_CAN_SLEEP: | 2257 | case PMU_IOC_CAN_SLEEP: |
2601 | if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) | 2258 | if (pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, -1) < 0) |
2602 | return put_user(0, argp); | 2259 | return put_user(0, argp); |
2603 | else | 2260 | else |
2604 | return put_user(1, argp); | 2261 | return put_user(1, argp); |
2605 | #endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */ | ||
2606 | 2262 | ||
2607 | #ifdef CONFIG_PMAC_BACKLIGHT_LEGACY | 2263 | #ifdef CONFIG_PMAC_BACKLIGHT_LEGACY |
2608 | /* Compatibility ioctl's for backlight */ | 2264 | /* Compatibility ioctl's for backlight */ |
@@ -2610,9 +2266,6 @@ pmu_ioctl(struct inode * inode, struct file *filp, | |||
2610 | { | 2266 | { |
2611 | int brightness; | 2267 | int brightness; |
2612 | 2268 | ||
2613 | if (sleep_in_progress) | ||
2614 | return -EBUSY; | ||
2615 | |||
2616 | brightness = pmac_backlight_get_legacy_brightness(); | 2269 | brightness = pmac_backlight_get_legacy_brightness(); |
2617 | if (brightness < 0) | 2270 | if (brightness < 0) |
2618 | return brightness; | 2271 | return brightness; |
@@ -2624,9 +2277,6 @@ pmu_ioctl(struct inode * inode, struct file *filp, | |||
2624 | { | 2277 | { |
2625 | int brightness; | 2278 | int brightness; |
2626 | 2279 | ||
2627 | if (sleep_in_progress) | ||
2628 | return -EBUSY; | ||
2629 | |||
2630 | error = get_user(brightness, argp); | 2280 | error = get_user(brightness, argp); |
2631 | if (error) | 2281 | if (error) |
2632 | return error; | 2282 | return error; |
@@ -2751,15 +2401,43 @@ pmu_polled_request(struct adb_request *req) | |||
2751 | local_irq_restore(flags); | 2401 | local_irq_restore(flags); |
2752 | return 0; | 2402 | return 0; |
2753 | } | 2403 | } |
2754 | #endif /* DEBUG_SLEEP */ | ||
2755 | 2404 | ||
2405 | /* N.B. This doesn't work on the 3400 */ | ||
2406 | void pmu_blink(int n) | ||
2407 | { | ||
2408 | struct adb_request req; | ||
2756 | 2409 | ||
2757 | /* FIXME: This is a temporary set of callbacks to enable us | 2410 | memset(&req, 0, sizeof(req)); |
2758 | * to do suspend-to-disk. | ||
2759 | */ | ||
2760 | 2411 | ||
2761 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) | 2412 | for (; n > 0; --n) { |
2413 | req.nbytes = 4; | ||
2414 | req.done = NULL; | ||
2415 | req.data[0] = 0xee; | ||
2416 | req.data[1] = 4; | ||
2417 | req.data[2] = 0; | ||
2418 | req.data[3] = 1; | ||
2419 | req.reply[0] = ADB_RET_OK; | ||
2420 | req.reply_len = 1; | ||
2421 | req.reply_expected = 0; | ||
2422 | pmu_polled_request(&req); | ||
2423 | mdelay(50); | ||
2424 | req.nbytes = 4; | ||
2425 | req.done = NULL; | ||
2426 | req.data[0] = 0xee; | ||
2427 | req.data[1] = 4; | ||
2428 | req.data[2] = 0; | ||
2429 | req.data[3] = 0; | ||
2430 | req.reply[0] = ADB_RET_OK; | ||
2431 | req.reply_len = 1; | ||
2432 | req.reply_expected = 0; | ||
2433 | pmu_polled_request(&req); | ||
2434 | mdelay(50); | ||
2435 | } | ||
2436 | mdelay(50); | ||
2437 | } | ||
2438 | #endif /* DEBUG_SLEEP */ | ||
2762 | 2439 | ||
2440 | #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32) | ||
2763 | int pmu_sys_suspended; | 2441 | int pmu_sys_suspended; |
2764 | 2442 | ||
2765 | static int pmu_sys_suspend(struct sys_device *sysdev, pm_message_t state) | 2443 | static int pmu_sys_suspend(struct sys_device *sysdev, pm_message_t state) |
@@ -2767,10 +2445,15 @@ static int pmu_sys_suspend(struct sys_device *sysdev, pm_message_t state) | |||
2767 | if (state.event != PM_EVENT_SUSPEND || pmu_sys_suspended) | 2445 | if (state.event != PM_EVENT_SUSPEND || pmu_sys_suspended) |
2768 | return 0; | 2446 | return 0; |
2769 | 2447 | ||
2770 | /* Suspend PMU event interrupts */ | 2448 | /* Suspend PMU event interrupts */\ |
2771 | pmu_suspend(); | 2449 | pmu_suspend(); |
2772 | |||
2773 | pmu_sys_suspended = 1; | 2450 | pmu_sys_suspended = 1; |
2451 | |||
2452 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
2453 | /* Tell backlight code not to muck around with the chip anymore */ | ||
2454 | pmu_backlight_set_sleep(1); | ||
2455 | #endif | ||
2456 | |||
2774 | return 0; | 2457 | return 0; |
2775 | } | 2458 | } |
2776 | 2459 | ||
@@ -2785,15 +2468,18 @@ static int pmu_sys_resume(struct sys_device *sysdev) | |||
2785 | pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2); | 2468 | pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2); |
2786 | pmu_wait_complete(&req); | 2469 | pmu_wait_complete(&req); |
2787 | 2470 | ||
2471 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
2472 | /* Tell backlight code it can use the chip again */ | ||
2473 | pmu_backlight_set_sleep(0); | ||
2474 | #endif | ||
2788 | /* Resume PMU event interrupts */ | 2475 | /* Resume PMU event interrupts */ |
2789 | pmu_resume(); | 2476 | pmu_resume(); |
2790 | |||
2791 | pmu_sys_suspended = 0; | 2477 | pmu_sys_suspended = 0; |
2792 | 2478 | ||
2793 | return 0; | 2479 | return 0; |
2794 | } | 2480 | } |
2795 | 2481 | ||
2796 | #endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */ | 2482 | #endif /* CONFIG_SUSPEND && CONFIG_PPC32 */ |
2797 | 2483 | ||
2798 | static struct sysdev_class pmu_sysclass = { | 2484 | static struct sysdev_class pmu_sysclass = { |
2799 | .name = "pmu", | 2485 | .name = "pmu", |
@@ -2804,10 +2490,10 @@ static struct sys_device device_pmu = { | |||
2804 | }; | 2490 | }; |
2805 | 2491 | ||
2806 | static struct sysdev_driver driver_pmu = { | 2492 | static struct sysdev_driver driver_pmu = { |
2807 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) | 2493 | #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32) |
2808 | .suspend = &pmu_sys_suspend, | 2494 | .suspend = &pmu_sys_suspend, |
2809 | .resume = &pmu_sys_resume, | 2495 | .resume = &pmu_sys_resume, |
2810 | #endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */ | 2496 | #endif /* CONFIG_SUSPEND && CONFIG_PPC32 */ |
2811 | }; | 2497 | }; |
2812 | 2498 | ||
2813 | static int __init init_pmu_sysfs(void) | 2499 | static int __init init_pmu_sysfs(void) |
@@ -2842,10 +2528,10 @@ EXPORT_SYMBOL(pmu_wait_complete); | |||
2842 | EXPORT_SYMBOL(pmu_suspend); | 2528 | EXPORT_SYMBOL(pmu_suspend); |
2843 | EXPORT_SYMBOL(pmu_resume); | 2529 | EXPORT_SYMBOL(pmu_resume); |
2844 | EXPORT_SYMBOL(pmu_unlock); | 2530 | EXPORT_SYMBOL(pmu_unlock); |
2845 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) | 2531 | #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32) |
2846 | EXPORT_SYMBOL(pmu_enable_irled); | 2532 | EXPORT_SYMBOL(pmu_enable_irled); |
2847 | EXPORT_SYMBOL(pmu_battery_count); | 2533 | EXPORT_SYMBOL(pmu_battery_count); |
2848 | EXPORT_SYMBOL(pmu_batteries); | 2534 | EXPORT_SYMBOL(pmu_batteries); |
2849 | EXPORT_SYMBOL(pmu_power_flags); | 2535 | EXPORT_SYMBOL(pmu_power_flags); |
2850 | #endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */ | 2536 | #endif /* CONFIG_SUSPEND && CONFIG_PPC32 */ |
2851 | 2537 | ||