#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>
/* 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 */
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;
#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;
} 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 */
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",
}
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;
}
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)
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 */
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);
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 */
pmac_suspend_devices(void)
{
int ret;
-
+
pm_prepare_console();
/* Notify old-style device drivers & userland */
/* 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
/* 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);
/* Re-enable local CPU interrupts */
local_irq_enable();
- pmu_blink(1);
+ mdelay(100);
preempt_enable();
/* 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 */
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);
(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 */
* 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)
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)
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();
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);
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();
};
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)
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
#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)
}
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();
}
static inline int __pmac
-polled_recv_byte(volatile unsigned char *via)
+polled_recv_byte(volatile unsigned char __iomem *via)
{
int x;
{
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];