vserver 1.9.5.x5
[linux-2.6.git] / drivers / macintosh / via-pmu.c
index 9f4147e..019f4c4 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/device.h>
 #include <linux/suspend.h>
 #include <linux/syscalls.h>
+#include <linux/cpu.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
@@ -72,7 +73,7 @@
 /* How many iterations between battery polls */
 #define BATTERY_POLLING_COUNT  2
 
-static volatile unsigned char *via;
+static volatile unsigned char __iomem *via;
 
 /* VIA registers - spaced 0x200 bytes apart */
 #define RS             0x200           /* skip between registers */
@@ -141,7 +142,7 @@ static struct device_node *vias;
 static int pmu_kind = PMU_UNKNOWN;
 static int pmu_fully_inited = 0;
 static int pmu_has_adb;
-static unsigned char *gpio_reg = NULL;
+static unsigned char __iomem *gpio_reg = NULL;
 static int gpio_irq = -1;
 static int gpio_irq_enabled = -1;
 static volatile int pmu_suspended = 0;
@@ -152,9 +153,8 @@ static int drop_interrupts;
 #ifdef CONFIG_PMAC_PBOOK
 static int option_lid_wakeup = 1;
 static int sleep_in_progress;
-static int can_sleep;
-static unsigned long async_req_locks;
 #endif /* CONFIG_PMAC_PBOOK */
+static unsigned long async_req_locks;
 static unsigned int pmu_irq_stats[11];
 
 static struct proc_dir_entry *proc_pmu_root;
@@ -352,7 +352,7 @@ find_via_pmu(void)
        } else
                pmu_kind = PMU_UNKNOWN;
 
-       via = (volatile unsigned char *) ioremap(vias->addrs->address, 0x2000);
+       via = ioremap(vias->addrs->address, 0x2000);
        
        out_8(&via[IER], IER_CLR | 0x7f);       /* disable all intrs */
        out_8(&via[IFR], 0x7f);                 /* clear IFR */
@@ -406,8 +406,6 @@ static int __init via_pmu_start(void)
        bright_req_2.complete = 1;
 #ifdef CONFIG_PMAC_PBOOK
        batt_req.complete = 1;
-       if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
-               can_sleep = 1;
 #endif
 
        if (request_irq(vias->intrs[0].line, via_pmu_interrupt, 0, "VIA-PMU",
@@ -418,7 +416,7 @@ static int __init via_pmu_start(void)
        }
 
        if (pmu_kind == PMU_KEYLARGO_BASED && gpio_irq != -1) {
-               if (request_irq(gpio_irq, gpio1_interrupt, 0, "GPIO1/ADB", (void *)0))
+               if (request_irq(gpio_irq, gpio1_interrupt, 0, "GPIO1 ADB", (void *)0))
                        printk(KERN_ERR "pmu: can't get irq %d (GPIO1)\n", gpio_irq);
                gpio_irq_enabled = 1;
        }
@@ -885,7 +883,8 @@ proc_read_options(char *page, char **start, off_t off,
        char *p = page;
 
 #ifdef CONFIG_PMAC_PBOOK
-       if (pmu_kind == PMU_KEYLARGO_BASED && can_sleep)
+       if (pmu_kind == PMU_KEYLARGO_BASED &&
+           pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
                p += sprintf(p, "lid_wakeup=%d\n", option_lid_wakeup);
 #endif /* CONFIG_PMAC_PBOOK */
        if (pmu_kind == PMU_KEYLARGO_BASED)
@@ -925,7 +924,8 @@ proc_write_options(struct file *file, const char __user *buffer,
        while(*val == ' ')
                val++;
 #ifdef CONFIG_PMAC_PBOOK
-       if (pmu_kind == PMU_KEYLARGO_BASED && can_sleep)
+       if (pmu_kind == PMU_KEYLARGO_BASED &&
+           pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
                if (!strcmp(label, "lid_wakeup"))
                        option_lid_wakeup = ((*val) == '1');
 #endif /* CONFIG_PMAC_PBOOK */
@@ -1164,7 +1164,7 @@ wait_for_ack(void)
 static inline void
 send_byte(int x)
 {
-       volatile unsigned char *v = via;
+       volatile unsigned char __iomem *v = via;
 
        out_8(&v[ACR], in_8(&v[ACR]) | SR_OUT | SR_EXT);
        out_8(&v[SR], x);
@@ -1175,7 +1175,7 @@ send_byte(int x)
 static inline void
 recv_byte(void)
 {
-       volatile unsigned char *v = via;
+       volatile unsigned char __iomem *v = via;
 
        out_8(&v[ACR], (in_8(&v[ACR]) & ~SR_OUT) | SR_EXT);
        in_8(&v[SR]);           /* resets SR */
@@ -2313,7 +2313,7 @@ static int __pmac
 pmac_suspend_devices(void)
 {
        int ret;
-       
+
        pm_prepare_console();
        
        /* Notify old-style device drivers & userland */
@@ -2341,13 +2341,13 @@ pmac_suspend_devices(void)
        /* Send suspend call to devices, hold the device core's dpm_sem */
        ret = device_suspend(PM_SUSPEND_MEM);
        if (ret) {
-               printk(KERN_ERR "Driver sleep failed\n");
                broadcast_wake();
+               printk(KERN_ERR "Driver sleep failed\n");
                return -EBUSY;
        }
-       
+
        preempt_disable();
-       
+
        /* Make sure the decrementer won't interrupt us */
        asm volatile("mtdec %0" : : "r" (0x7fffffff));
        /* Make sure any pending DEC interrupt occurring while we did
@@ -2404,8 +2404,6 @@ pmac_wakeup_devices(void)
        /* Power back up system devices (including the PIC) */
        device_power_up();
 
-       pmu_blink(1);
-
        /* Force a poll of ADB interrupts */
        adb_int_pending = 1;
        via_pmu_interrupt(0, NULL, NULL);
@@ -2416,7 +2414,7 @@ pmac_wakeup_devices(void)
        /* Re-enable local CPU interrupts */
        local_irq_enable();
 
-       pmu_blink(1);
+       mdelay(100);
 
        preempt_enable();
 
@@ -2464,8 +2462,6 @@ powerbook_sleep_grackle(void)
 
        /* For 750, save backside cache setting and disable it */
        save_l2cr = _get_L2CR();        /* (returns -1 if not available) */
-       if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
-               _set_L2CR(save_l2cr & 0x7fffffff);
 
        if (!__fake_sleep) {
                /* Ask the PMU to put us to sleep */
@@ -2530,17 +2526,22 @@ powerbook_sleep_Core99(void)
        struct adb_request req;
        int ret;
        
-       if (!can_sleep) {
+       if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) {
                printk(KERN_ERR "Sleep mode not supported on this machine\n");
                return -ENOSYS;
        }
-       
+
+       if (num_online_cpus() > 1 || cpu_is_offline(0))
+               return -EAGAIN;
+
        ret = pmac_suspend_devices();
        if (ret) {
                printk(KERN_ERR "Sleep rejected by devices\n");
                return ret;
        }
-       
+
+       printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1));
+
        /* Tell PMU what events will wake us up */
        pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_CLR_WAKEUP_EVENTS,
                0xff, 0xff);
@@ -2550,16 +2551,9 @@ powerbook_sleep_Core99(void)
                (option_lid_wakeup ? PMU_PWR_WAKEUP_LID_OPEN : 0));
        pmu_wait_complete(&req);
 
-       /* Save & disable L2 and L3 caches*/
+       /* Save the state of the L2 and L3 caches */
        save_l3cr = _get_L3CR();        /* (returns -1 if not available) */
        save_l2cr = _get_L2CR();        /* (returns -1 if not available) */
-       if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0)
-               _set_L3CR(save_l3cr & 0x7fffffff);
-       if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
-               _set_L2CR(save_l2cr & 0x7fffffff);
-
-       /* Save the state of PCI config space for some slots */
-       //pbook_pci_save();
 
        if (!__fake_sleep) {
                /* Ask the PMU to put us to sleep */
@@ -2574,7 +2568,7 @@ powerbook_sleep_Core99(void)
         * talk to the PMU after this, so I moved it to _after_ sending the
         * sleep command to it. Still need to be checked.
         */
-       pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,1);
+       pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 1);
 
        /* Call low-level ASM sleep handler */
        if (__fake_sleep)
@@ -2583,18 +2577,13 @@ powerbook_sleep_Core99(void)
                low_sleep_handler();
 
        /* Restore Apple core ASICs state */
-       pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0);
+       pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 0);
 
        /* Restore VIA */
        restore_via_state();
 
-       /* Restore PCI config space. This should be overridable by PCI device
-        * drivers as some of them may need special restore code. That's yet
-        * another issue that should be handled by the common code properly,
-        * maybe one day ?
-        */
-       /* Don't restore PCI for now, it crashes. Maybe unnecessary on pbook */
-       //pbook_pci_restore();
+       /* Restore video */
+       pmac_call_early_video_resume();
 
        /* Restore L2 cache */
        if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
@@ -2613,7 +2602,7 @@ powerbook_sleep_Core99(void)
        pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
        pmu_wait_complete(&req);
 
-       pmu_blink(1);
+       printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1));
 
        pmac_wakeup_devices();
 
@@ -2630,8 +2619,8 @@ powerbook_sleep_3400(void)
        unsigned int hid0;
        unsigned long p;
        struct adb_request sleep_req;
-       char *mem_ctrl;
-       unsigned int *mem_ctrl_sleep;
+       void __iomem *mem_ctrl;
+       unsigned int __iomem *mem_ctrl_sleep;
 
        /* first map in the memory controller registers */
        mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100);
@@ -2639,7 +2628,7 @@ powerbook_sleep_3400(void)
                printk("powerbook_sleep_3400: ioremap failed\n");
                return -ENOMEM;
        }
-       mem_ctrl_sleep = (unsigned int *) (mem_ctrl + PB3400_MEM_CTRL_SLEEP);
+       mem_ctrl_sleep = mem_ctrl + PB3400_MEM_CTRL_SLEEP;
 
        /* Allocate room for PCI save */
        pbook_alloc_pci_save();
@@ -2721,7 +2710,7 @@ struct pmu_private {
 };
 
 static LIST_HEAD(all_pmu_pvt);
-static spinlock_t all_pvt_lock __pmacdata = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(all_pvt_lock __pmacdata);
 
 static void __pmac
 pmu_pass_intr(unsigned char *data, int len)
@@ -2909,7 +2898,10 @@ pmu_ioctl(struct inode * inode, struct file *filp,
                sleep_in_progress = 0;
                return error;
        case PMU_IOC_CAN_SLEEP:
-               return put_user((u32)can_sleep, argp);
+               if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0)
+                       return put_user(0, argp);
+               else
+                       return put_user(1, argp);
 
 #ifdef CONFIG_PMAC_BACKLIGHT
        /* Backlight should have its own device or go via
@@ -2977,7 +2969,7 @@ void pmu_device_init(void)
 
 #ifdef DEBUG_SLEEP
 static inline void  __pmac
-polled_handshake(volatile unsigned char *via)
+polled_handshake(volatile unsigned char __iomem *via)
 {
        via[B] &= ~TREQ; eieio();
        while ((via[B] & TACK) != 0)
@@ -2988,7 +2980,7 @@ polled_handshake(volatile unsigned char *via)
 }
 
 static inline void  __pmac
-polled_send_byte(volatile unsigned char *via, int x)
+polled_send_byte(volatile unsigned char __iomem *via, int x)
 {
        via[ACR] |= SR_OUT | SR_EXT; eieio();
        via[SR] = x; eieio();
@@ -2996,7 +2988,7 @@ polled_send_byte(volatile unsigned char *via, int x)
 }
 
 static inline int __pmac
-polled_recv_byte(volatile unsigned char *via)
+polled_recv_byte(volatile unsigned char __iomem *via)
 {
        int x;
 
@@ -3012,7 +3004,7 @@ pmu_polled_request(struct adb_request *req)
 {
        unsigned long flags;
        int i, l, c;
-       volatile unsigned char *v = via;
+       volatile unsigned char __iomem *v = via;
 
        req->complete = 1;
        c = req->data[0];