aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/macintosh/via-pmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/macintosh/via-pmu.c')
-rw-r--r--drivers/macintosh/via-pmu.c172
1 files changed, 36 insertions, 136 deletions
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 6df3f3503e5b..0e233185ad14 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -202,6 +202,12 @@ static int proc_read_options(char *page, char **start, off_t off,
202static int proc_write_options(struct file *file, const char __user *buffer, 202static int proc_write_options(struct file *file, const char __user *buffer,
203 unsigned long count, void *data); 203 unsigned long count, void *data);
204 204
205#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
206static void powerbook_sleep_init_3400(void);
207#else
208#define powerbook_sleep_init_3400() do { } while (0)
209#endif
210
205#ifdef CONFIG_ADB 211#ifdef CONFIG_ADB
206struct adb_driver via_pmu_driver = { 212struct adb_driver via_pmu_driver = {
207 "PMU", 213 "PMU",
@@ -449,6 +455,10 @@ static int __init via_pmu_start(void)
449 pmu_poll(); 455 pmu_poll();
450 } while (pmu_state != idle); 456 } while (pmu_state != idle);
451 457
458 /* Do allocations and ioremaps that will be needed for sleep */
459 if (pmu_kind == PMU_OHARE_BASED)
460 powerbook_sleep_init_3400();
461
452 return 0; 462 return 0;
453} 463}
454 464
@@ -1719,108 +1729,6 @@ pmu_present(void)
1719} 1729}
1720 1730
1721#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) 1731#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
1722/*
1723 * This struct is used to store config register values for
1724 * PCI devices which may get powered off when we sleep.
1725 */
1726static struct pci_save {
1727 u16 command;
1728 u16 cache_lat;
1729 u16 intr;
1730 u32 rom_address;
1731} *pbook_pci_saves;
1732static int pbook_npci_saves;
1733
1734static void
1735pbook_alloc_pci_save(void)
1736{
1737 int npci;
1738 struct pci_dev *pd = NULL;
1739
1740 npci = 0;
1741 while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
1742 ++npci;
1743 }
1744 if (npci == 0)
1745 return;
1746 pbook_pci_saves = (struct pci_save *)
1747 kmalloc(npci * sizeof(struct pci_save), GFP_KERNEL);
1748 pbook_npci_saves = npci;
1749}
1750
1751static void
1752pbook_free_pci_save(void)
1753{
1754 if (pbook_pci_saves == NULL)
1755 return;
1756 kfree(pbook_pci_saves);
1757 pbook_pci_saves = NULL;
1758 pbook_npci_saves = 0;
1759}
1760
1761static void
1762pbook_pci_save(void)
1763{
1764 struct pci_save *ps = pbook_pci_saves;
1765 struct pci_dev *pd = NULL;
1766 int npci = pbook_npci_saves;
1767
1768 if (ps == NULL)
1769 return;
1770
1771 while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
1772 if (npci-- == 0) {
1773 pci_dev_put(pd);
1774 return;
1775 }
1776 pci_read_config_word(pd, PCI_COMMAND, &ps->command);
1777 pci_read_config_word(pd, PCI_CACHE_LINE_SIZE, &ps->cache_lat);
1778 pci_read_config_word(pd, PCI_INTERRUPT_LINE, &ps->intr);
1779 pci_read_config_dword(pd, PCI_ROM_ADDRESS, &ps->rom_address);
1780 ++ps;
1781 }
1782}
1783
1784/* For this to work, we must take care of a few things: If gmac was enabled
1785 * during boot, it will be in the pci dev list. If it's disabled at this point
1786 * (and it will probably be), then you can't access it's config space.
1787 */
1788static void
1789pbook_pci_restore(void)
1790{
1791 u16 cmd;
1792 struct pci_save *ps = pbook_pci_saves - 1;
1793 struct pci_dev *pd = NULL;
1794 int npci = pbook_npci_saves;
1795 int j;
1796
1797 while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
1798 if (npci-- == 0)
1799 return;
1800 ps++;
1801 if (ps->command == 0)
1802 continue;
1803 pci_read_config_word(pd, PCI_COMMAND, &cmd);
1804 if ((ps->command & ~cmd) == 0)
1805 continue;
1806 switch (pd->hdr_type) {
1807 case PCI_HEADER_TYPE_NORMAL:
1808 for (j = 0; j < 6; ++j)
1809 pci_write_config_dword(pd,
1810 PCI_BASE_ADDRESS_0 + j*4,
1811 pd->resource[j].start);
1812 pci_write_config_dword(pd, PCI_ROM_ADDRESS,
1813 ps->rom_address);
1814 pci_write_config_word(pd, PCI_CACHE_LINE_SIZE,
1815 ps->cache_lat);
1816 pci_write_config_word(pd, PCI_INTERRUPT_LINE,
1817 ps->intr);
1818 pci_write_config_word(pd, PCI_COMMAND, ps->command);
1819 break;
1820 }
1821 }
1822}
1823
1824#ifdef DEBUG_SLEEP 1732#ifdef DEBUG_SLEEP
1825/* N.B. This doesn't work on the 3400 */ 1733/* N.B. This doesn't work on the 3400 */
1826void 1734void
@@ -2200,37 +2108,34 @@ powerbook_sleep_Core99(void)
2200#define PB3400_MEM_CTRL 0xf8000000 2108#define PB3400_MEM_CTRL 0xf8000000
2201#define PB3400_MEM_CTRL_SLEEP 0x70 2109#define PB3400_MEM_CTRL_SLEEP 0x70
2202 2110
2203static int 2111static void __iomem *pb3400_mem_ctrl;
2204powerbook_sleep_3400(void) 2112
2113static void powerbook_sleep_init_3400(void)
2114{
2115 /* map in the memory controller registers */
2116 pb3400_mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100);
2117 if (pb3400_mem_ctrl == NULL)
2118 printk(KERN_WARNING "ioremap failed: sleep won't be possible");
2119}
2120
2121static int powerbook_sleep_3400(void)
2205{ 2122{
2206 int ret, i, x; 2123 int ret, i, x;
2207 unsigned int hid0; 2124 unsigned int hid0;
2208 unsigned long p; 2125 unsigned long msr;
2209 struct adb_request sleep_req; 2126 struct adb_request sleep_req;
2210 void __iomem *mem_ctrl;
2211 unsigned int __iomem *mem_ctrl_sleep; 2127 unsigned int __iomem *mem_ctrl_sleep;
2212 2128
2213 /* first map in the memory controller registers */ 2129 if (pb3400_mem_ctrl == NULL)
2214 mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100);
2215 if (mem_ctrl == NULL) {
2216 printk("powerbook_sleep_3400: ioremap failed\n");
2217 return -ENOMEM; 2130 return -ENOMEM;
2218 } 2131 mem_ctrl_sleep = pb3400_mem_ctrl + PB3400_MEM_CTRL_SLEEP;
2219 mem_ctrl_sleep = mem_ctrl + PB3400_MEM_CTRL_SLEEP;
2220
2221 /* Allocate room for PCI save */
2222 pbook_alloc_pci_save();
2223 2132
2224 ret = pmac_suspend_devices(); 2133 ret = pmac_suspend_devices();
2225 if (ret) { 2134 if (ret) {
2226 pbook_free_pci_save();
2227 printk(KERN_ERR "Sleep rejected by devices\n"); 2135 printk(KERN_ERR "Sleep rejected by devices\n");
2228 return ret; 2136 return ret;
2229 } 2137 }
2230 2138
2231 /* Save the state of PCI config space for some slots */
2232 pbook_pci_save();
2233
2234 /* Set the memory controller to keep the memory refreshed 2139 /* Set the memory controller to keep the memory refreshed
2235 while we're asleep */ 2140 while we're asleep */
2236 for (i = 0x403f; i >= 0x4000; --i) { 2141 for (i = 0x403f; i >= 0x4000; --i) {
@@ -2244,36 +2149,31 @@ powerbook_sleep_3400(void)
2244 2149
2245 /* Ask the PMU to put us to sleep */ 2150 /* Ask the PMU to put us to sleep */
2246 pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T'); 2151 pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
2247 while (!sleep_req.complete) 2152 pmu_wait_complete(&sleep_req);
2248 mb(); 2153 pmu_unlock();
2249 2154
2250 pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,1); 2155 pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 1);
2251 2156
2252 /* displacement-flush the L2 cache - necessary? */
2253 for (p = KERNELBASE; p < KERNELBASE + 0x100000; p += 0x1000)
2254 i = *(volatile int *)p;
2255 asleep = 1; 2157 asleep = 1;
2256 2158
2257 /* Put the CPU into sleep mode */ 2159 /* Put the CPU into sleep mode */
2258 hid0 = mfspr(SPRN_HID0); 2160 hid0 = mfspr(SPRN_HID0);
2259 hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP; 2161 hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP;
2260 mtspr(SPRN_HID0, hid0); 2162 mtspr(SPRN_HID0, hid0);
2261 mtmsr(mfmsr() | MSR_POW | MSR_EE); 2163 local_irq_enable();
2262 udelay(10); 2164 msr = mfmsr() | MSR_POW;
2165 while (asleep) {
2166 mb();
2167 mtmsr(msr);
2168 isync();
2169 }
2170 local_irq_disable();
2263 2171
2264 /* OK, we're awake again, start restoring things */ 2172 /* OK, we're awake again, start restoring things */
2265 out_be32(mem_ctrl_sleep, 0x3f); 2173 out_be32(mem_ctrl_sleep, 0x3f);
2266 pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0); 2174 pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 0);
2267 pbook_pci_restore();
2268 pmu_unlock();
2269
2270 /* wait for the PMU interrupt sequence to complete */
2271 while (asleep)
2272 mb();
2273 2175
2274 pmac_wakeup_devices(); 2176 pmac_wakeup_devices();
2275 pbook_free_pci_save();
2276 iounmap(mem_ctrl);
2277 2177
2278 return 0; 2178 return 0;
2279} 2179}