diff options
Diffstat (limited to 'target/linux/olpc/files-2.6.23/arch/i386/kernel/olpc-pm.c')
-rw-r--r-- | target/linux/olpc/files-2.6.23/arch/i386/kernel/olpc-pm.c | 785 |
1 files changed, 0 insertions, 785 deletions
diff --git a/target/linux/olpc/files-2.6.23/arch/i386/kernel/olpc-pm.c b/target/linux/olpc/files-2.6.23/arch/i386/kernel/olpc-pm.c deleted file mode 100644 index 93149f1c38..0000000000 --- a/target/linux/olpc/files-2.6.23/arch/i386/kernel/olpc-pm.c +++ /dev/null @@ -1,785 +0,0 @@ -/* olpc-pm.c - * © 2006 Red Hat, Inc. - * Portions also copyright 2006 Advanced Micro Devices, Inc. - * GPLv2 - */ - -#include <linux/kernel.h> -#include <linux/interrupt.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/input.h> -#include <linux/suspend.h> -#include <linux/bootmem.h> -#include <linux/platform_device.h> -#include <linux/rtc.h> -#include <linux/mc146818rtc.h> -#include <asm/io.h> - -#include <asm/olpc.h> - -/* A few words about accessing the ACPI and PM registers. Long story short, - byte and word accesses of the ACPI and PM registers is broken. The only - way to do it really correctly is to use dword accesses, which we do - throughout this code. For more details, please consult Eratta 17 and 18 - here: - - http://www.amd.com/files/connectivitysolutions/geode/geode_gx/34472D_CS5536_B1_specupdate.pdf -*/ - -#define PM_IRQ 3 - -#define CS5536_PM_PWRBTN (1 << 8) -#define CS5536_PM_RTC (1 << 10) - -#define GPIO_WAKEUP_EC (1 << 31) -#define GPIO_WAKEUP_LID (1 << 30) - -#define PM_MODE_NORMAL 0 -#define PM_MODE_TEST 1 -#define PM_MODE_MAX 2 - -/* These, and the battery EC commands, should be in an olpc.h. */ -#define EC_WRITE_SCI_MASK 0x1b -#define EC_READ_SCI_MASK 0x1c - -extern void do_olpc_suspend_lowlevel(void); - -static struct { - unsigned long address; - unsigned short segment; -} ofw_bios_entry = { 0, __KERNEL_CS }; - -static int olpc_pm_mode = PM_MODE_NORMAL; -static unsigned long acpi_base; -static unsigned long pms_base; -static int sci_irq; -static int olpc_lid_flag; - -static struct input_dev *pm_inputdev; -static struct input_dev *lid_inputdev; -static struct input_dev *ebook_inputdev; -static struct pm_ops olpc_pm_ops; - -static int gpio_wake_events = 0; -static int ebook_state = -1; -static u16 olpc_wakeup_mask = 0; - -struct platform_device olpc_powerbutton_dev = { - .name = "powerbutton", - .id = -1, -}; - -struct platform_device olpc_lid_dev = { - .name = "lid", - .id = -1, -}; - -static void __init init_ebook_state(void) -{ - if (olpc_ec_cmd(0x2a, NULL, 0, (unsigned char *) &ebook_state, 1)) { - printk(KERN_WARNING "olpc-pm: failed to get EBOOK state!\n"); - ebook_state = 0; - } - ebook_state &= 1; - - /* the input layer needs to know what value to default to as well */ - input_report_switch(ebook_inputdev, SW_TABLET_MODE, ebook_state); - input_sync(ebook_inputdev); -} - -static void (*battery_callback)(unsigned long); -static DEFINE_SPINLOCK(battery_callback_lock); - -/* propagate_events is non-NULL if run from workqueue, - NULL when called at init time to flush SCI queue */ -static void process_sci_queue(struct work_struct *propagate_events) -{ - unsigned char data = 0; - unsigned char battery_events = 0; - int ret; - - do { - ret = olpc_ec_cmd(0x84, NULL, 0, &data, 1); - if (!ret) { - printk(KERN_DEBUG "olpc-pm: SCI 0x%x received\n", - data); - - switch (data) { - case EC_SCI_SRC_EMPTY: - case EC_SCI_SRC_GAME: - case EC_SCI_SRC_WLAN: - /* we ignore these for now */ - break; - case EC_SCI_SRC_BATERR: - printk(KERN_ERR "olpc-pm: Battery Management System detected an error! Remove turnip from battery slot.\n"); - case EC_SCI_SRC_BATSOC: - case EC_SCI_SRC_BATTERY: - case EC_SCI_SRC_ACPWR: - battery_events |= data; - break; - case EC_SCI_SRC_EBOOK: - ebook_state = !ebook_state; - if (propagate_events) { - input_report_switch(ebook_inputdev, - SW_TABLET_MODE, ebook_state); - input_sync(ebook_inputdev); - } - break; - default: - printk(KERN_ERR "olpc-pm: Unknown SCI event 0x%x occurred!\n", data); - } - } - } while (data && !ret); - - if (battery_events && battery_callback && propagate_events) { - void (*cbk)(unsigned long); - - /* Older EC versions didn't distinguish between AC and battery - events */ - if (olpc_platform_info.ecver < 0x45) - battery_events = EC_SCI_SRC_BATTERY | EC_SCI_SRC_ACPWR; - - spin_lock(&battery_callback_lock); - cbk = battery_callback; - spin_unlock(&battery_callback_lock); - - cbk(battery_events); - } - - if (ret) - printk(KERN_WARNING "Failed to clear SCI queue!\n"); -} - -static DECLARE_WORK(sci_work, process_sci_queue); - -void olpc_register_battery_callback(void (*f)(unsigned long)) -{ - spin_lock(&battery_callback_lock); - battery_callback = f; - spin_unlock(&battery_callback_lock); -} -EXPORT_SYMBOL_GPL(olpc_register_battery_callback); - -void olpc_deregister_battery_callback(void) -{ - spin_lock(&battery_callback_lock); - battery_callback = NULL; - spin_unlock(&battery_callback_lock); - cancel_work_sync(&sci_work); -} -EXPORT_SYMBOL_GPL(olpc_deregister_battery_callback); - - -static int olpc_pm_interrupt(int irq, void *id) -{ - uint32_t sts, gpe = 0; - - sts = inl(acpi_base + PM1_STS); - outl(sts | 0xFFFF, acpi_base + PM1_STS); - - if (olpc_get_rev() >= OLPC_REV_B2) { - gpe = inl(acpi_base + PM_GPE0_STS); - outl(0xFFFFFFFF, acpi_base + PM_GPE0_STS); - } - - if (sts & CS5536_PM_PWRBTN) { - input_report_key(pm_inputdev, KEY_POWER, 1); - input_sync(pm_inputdev); - printk(KERN_DEBUG "olpm-pm: PM_PWRBTN event received\n"); - /* Do we need to delay this (and hence schedule_work)? */ - input_report_key(pm_inputdev, KEY_POWER, 0); - input_sync(pm_inputdev); - } - - if (gpe & GPIO_WAKEUP_EC) { - geode_gpio_clear(OLPC_GPIO_ECSCI, GPIO_NEGATIVE_EDGE_STS); - schedule_work(&sci_work); - } - - if (gpe & GPIO_WAKEUP_LID) { - /* Disable events */ - geode_gpio_clear(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE); - - /* Clear the edge */ - - if (olpc_lid_flag) - geode_gpio_clear(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_EN); - else - geode_gpio_clear(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_EN); - - /* Clear the status too */ - geode_gpio_set(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_STS); - geode_gpio_set(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_STS); - - /* The line is high when the LID is open, but SW_LID - * should be high when the LID is closed, so we pass the old - * value of olpc_lid_flag - */ - - input_report_switch(lid_inputdev, SW_LID, olpc_lid_flag); - input_sync(lid_inputdev); - - /* Swap the status */ - olpc_lid_flag = !olpc_lid_flag; - - if (olpc_lid_flag) - geode_gpio_set(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_EN); - else - geode_gpio_set(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_EN); - - /* re-enable the event */ - geode_gpio_set(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE); - } - - return IRQ_HANDLED; -} - -/* - * For now, only support STR. We also don't support suspending on - * B1s, due to difficulties with the cafe FPGA. - */ -static int olpc_pm_state_valid(suspend_state_t pm_state) -{ - if (pm_state == PM_SUSPEND_MEM && olpc_rev_after(OLPC_REV_B1)) - return 1; - - return 0; -} - -/* This is a catchall function for operations that just don't belong - * anywhere else. Later we will evaluate if these belong in the - * individual device drivers or the firmware. - * If you add something to this function, please explain yourself with - * a comment. - */ - -extern void gxfb_flatpanel_control(int state); - -static u32 gpio_wakeup[2]; -static u64 irq_sources[4]; -static u64 mfgpt_irq_msr, mfgpt_nr_msr; - -void olpc_fixup_wakeup(void) -{ - u32 base = geode_gpio_base(); - int i; - - /* This clears any pending events from the status register - - * the firmware also does this, but its possible that it tries - * it too early before the key has a chance to debounce - */ - - outl((CS5536_PM_PWRBTN << 16) | 0xFFFF, acpi_base + PM1_STS); - - /* Enable the flatpanel sequencing as early as possible, because - it takes ~64ms to resume. This probably belongs in the firmware */ - - //gxfb_flatpanel_control(1); - - /* Restore the interrupt sources */ - wrmsrl(MSR_PIC_YSEL_LOW, irq_sources[0]); - wrmsrl(MSR_PIC_ZSEL_LOW, irq_sources[1]); - wrmsrl(MSR_PIC_YSEL_HIGH, irq_sources[2]); - wrmsrl(MSR_PIC_ZSEL_HIGH, irq_sources[3]); - - /* Restore the X and Y sources for GPIO */ - outl(gpio_wakeup[0], base + GPIO_MAP_X); - outl(gpio_wakeup[1], base + GPIO_MAP_Y); - - /* Resture the MFGPT MSRs */ - wrmsrl(MFGPT_IRQ_MSR, mfgpt_irq_msr); - wrmsrl(MFGPT_NR_MSR, mfgpt_nr_msr); - - for (i=0;i<2;i++) { - /* tell the wireless module to restart USB communication */ - olpc_ec_cmd(0x24, NULL, 0, NULL, 0); - } -} - -void olpc_fixup_sleep(void) -{ - u32 base = geode_gpio_base(); - int i; - - /* Save the X and Y sources for GPIO */ - gpio_wakeup[0] = inl(base + GPIO_MAP_X); - gpio_wakeup[1] = inl(base + GPIO_MAP_Y); - - /* Save the Y and Z unrestricted sources */ - - rdmsrl(MSR_PIC_YSEL_LOW, irq_sources[0]); - rdmsrl(MSR_PIC_ZSEL_LOW, irq_sources[1]); - rdmsrl(MSR_PIC_YSEL_HIGH, irq_sources[2]); - rdmsrl(MSR_PIC_ZSEL_HIGH, irq_sources[3]); - - /* Turn off the MFGPT timers on the way down */ - - for(i = 0; i < 8; i++) { - u32 val = geode_mfgpt_read(i, MFGPT_REG_SETUP); - - if (val & MFGPT_SETUP_SETUP) { - val &= ~MFGPT_SETUP_CNTEN; - geode_mfgpt_write(i, MFGPT_REG_SETUP, val); - } - } - - /* Save the MFGPT MSRs */ - rdmsrl(MFGPT_IRQ_MSR, mfgpt_irq_msr); - rdmsrl(MFGPT_NR_MSR, mfgpt_nr_msr); - - if (device_may_wakeup(&olpc_powerbutton_dev.dev)) - olpc_wakeup_mask |= CS5536_PM_PWRBTN; - else - olpc_wakeup_mask &= ~(CS5536_PM_PWRBTN); - - if (device_may_wakeup(&olpc_lid_dev.dev)) { - geode_gpio_set(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE); - gpio_wake_events |= GPIO_WAKEUP_LID; - } else { - geode_gpio_clear(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE); - gpio_wake_events &= ~(GPIO_WAKEUP_LID); - } -} - -static int olpc_pm_enter(suspend_state_t pm_state) -{ - /* Only STR is supported */ - if (pm_state != PM_SUSPEND_MEM) - return -EINVAL; - - olpc_fixup_sleep(); - - /* Set the GPIO wakeup bits */ - outl(gpio_wake_events, acpi_base + PM_GPE0_EN); - outl(0xFFFFFFFF, acpi_base + PM_GPE0_STS); - - /* Save CPU state */ - do_olpc_suspend_lowlevel(); - - olpc_fixup_wakeup(); - - /* Restore the SCI wakeup events */ - outl(gpio_wake_events, acpi_base + PM_GPE0_EN); - - return 0; -} - -int asmlinkage olpc_do_sleep(u8 sleep_state) -{ - void *pgd_addr = __va(read_cr3()); - printk(KERN_ERR "olpc_do_sleep!\n"); /* this needs to remain here so - * that gcc doesn't optimize - * away our __va! */ - /* FIXME: Set the SCI bits we want to wake up on here */ - - /* FIXME: Set any other SCI events that we might want here */ - - outl((olpc_wakeup_mask << 16) | 0xFFFF, acpi_base + PM1_STS); - - /* If we are in test mode, then just return (simulate a successful - suspend/resume). Otherwise, if we are doing the real thing, - then go for the gusto */ - - if (olpc_pm_mode != PM_MODE_TEST) { - __asm__ __volatile__("movl %0,%%eax" : : "r" (pgd_addr)); - __asm__("call *(%%edi); cld" - : : "D" (&ofw_bios_entry)); - } - - return 0; -} - -/* This code will slowly disappear as we fixup the issues in the BIOS */ - -static void __init olpc_fixup_bios(void) -{ - unsigned long hi, lo; - - if (olpc_has_vsa()) { - /* The VSA aggressively sets up the ACPI and PM register for - * trapping - its not enough to force these values in the BIOS - - * they seem to be changed during PCI init as well. - */ - - /* Change the PM registers to decode to the DD */ - - rdmsr(0x510100e2, lo, hi); - hi |= 0x80000000; - wrmsr(0x510100e2, lo, hi); - - /* Change the ACPI registers to decode to the DD */ - - rdmsr(0x510100e3, lo, hi); - hi |= 0x80000000; - wrmsr(0x510100e3, lo, hi); - } - - /* GPIO24 controls WORK_AUX */ - - geode_gpio_set(OLPC_GPIO_WORKAUX, GPIO_OUTPUT_ENABLE); - geode_gpio_set(OLPC_GPIO_WORKAUX, GPIO_OUTPUT_AUX1); - - if (olpc_get_rev() >= OLPC_REV_B2) { - /* GPIO10 is connected to the thermal alarm */ - geode_gpio_set(OLPC_GPIO_THRM_ALRM, GPIO_INPUT_ENABLE); - geode_gpio_set(OLPC_GPIO_THRM_ALRM, GPIO_INPUT_AUX1); - - /* Set up to get LID events */ - geode_gpio_set(OLPC_GPIO_LID, GPIO_INPUT_ENABLE); - - /* Clear edge detection and event enable for now */ - geode_gpio_clear(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE); - geode_gpio_clear(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_EN); - geode_gpio_clear(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_EN); - - geode_gpio_set(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_STS); - geode_gpio_set(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_STS); - - /* Set the LID to cause an PME event on group 6 */ - geode_gpio_event_pme(OLPC_GPIO_LID, 6); - - /* Set PME group 6 to fire the SCI interrupt */ - geode_gpio_set_irq(6, sci_irq); - } - - geode_gpio_set(OLPC_GPIO_ECSCI, GPIO_INPUT_ENABLE); - - /* Clear pending events */ - - geode_gpio_set(OLPC_GPIO_ECSCI, GPIO_NEGATIVE_EDGE_STS); - geode_gpio_set(OLPC_GPIO_ECSCI, GPIO_POSITIVE_EDGE_STS); - - //geode_gpio_set(OLPC_GPIO_ECSCI, GPIO_NEGATIVE_EDGE_EN); - geode_gpio_set(OLPC_GPIO_ECSCI, GPIO_EVENTS_ENABLE); - - /* Set the SCI to cause a PME event on group 7 */ - geode_gpio_event_pme(OLPC_GPIO_ECSCI, 7); - - /* And have group 6 also fire the SCI interrupt */ - geode_gpio_set_irq(7, sci_irq); -} - -/* This provides a control file for setting up testing of the - power management system. For now, there is just one setting: - "test" which means that we don't actually enter the power - off routine. -*/ - -static const char * const pm_states[] = { - [PM_MODE_NORMAL] = "normal", - [PM_MODE_TEST] = "test", -}; - -extern struct mutex pm_mutex; -extern struct kset power_subsys; - -static ssize_t control_show(struct kset *s, char *buf) -{ - return sprintf(buf, "%s\n", pm_states[olpc_pm_mode]); -} - -static ssize_t control_store(struct kset *s, const char *buf, size_t n) -{ - int i, len; - char *p; - - p = memchr(buf, '\n', n); - len = p ? p - buf : n; - - /* Grab the mutex */ - mutex_lock(&pm_mutex); - - for(i = 0; i < PM_MODE_MAX; i++) { - if (!strncmp(buf, pm_states[i], len)) { - olpc_pm_mode = i; - break; - } - } - - mutex_unlock(&pm_mutex); - - return (i == PM_MODE_MAX) ? -EINVAL : n; -} - -static struct subsys_attribute control_attr = { - .attr = { - .name = "olpc-pm", - .mode = 0644, - }, - .show = control_show, - .store = control_store, -}; - -static struct attribute * olpc_attributes[] = { - &control_attr.attr, - NULL -}; - -static struct attribute_group olpc_attrs = { - .attrs = olpc_attributes, -}; - -static int __init alloc_inputdevs(void) -{ - int ret = -ENOMEM; - - pm_inputdev = input_allocate_device(); - if (!pm_inputdev) - goto err; - - pm_inputdev->name = "OLPC PM"; - pm_inputdev->phys = "olpc_pm/input0"; - set_bit(EV_KEY, pm_inputdev->evbit); - set_bit(KEY_POWER, pm_inputdev->keybit); - - ret = input_register_device(pm_inputdev); - if (ret) { - printk(KERN_ERR "olpc-pm: failed to register PM input device: %d\n", ret); - goto err; - } - - lid_inputdev = input_allocate_device(); - if (!lid_inputdev) - goto err; - - lid_inputdev->name = "OLPC lid switch"; - lid_inputdev->phys = "olpc_pm/input1"; - set_bit(EV_SW, lid_inputdev->evbit); - set_bit(SW_LID, lid_inputdev->swbit); - - ret = input_register_device(lid_inputdev); - if (ret) { - printk(KERN_ERR "olpc-pm: failed to register lid input device: %d\n", ret); - goto err; - } - - ebook_inputdev = input_allocate_device(); - if (!ebook_inputdev) - goto err; - - ebook_inputdev->name = "OLPC ebook switch"; - ebook_inputdev->phys = "olpc_pm/input2"; - set_bit(EV_SW, ebook_inputdev->evbit); - set_bit(SW_TABLET_MODE, ebook_inputdev->swbit); - - ret = input_register_device(ebook_inputdev); - if (ret) { - printk(KERN_ERR "olpc-pm: failed to register ebook input device: %d\n", ret); - goto err; - } - - return ret; -err: - if (ebook_inputdev) { - input_unregister_device(ebook_inputdev); - ebook_inputdev = NULL; - } - if (lid_inputdev) { - input_unregister_device(lid_inputdev); - lid_inputdev = NULL; - } - if (pm_inputdev) { - input_unregister_device(pm_inputdev); - pm_inputdev = NULL; - } - - return ret; -} - -static int __init olpc_pm_init(void) -{ - uint32_t lo, hi; - int ret; - uint8_t ec_byte; - - if (!machine_is_olpc()) - return -ENODEV; - - acpi_base = geode_acpi_base(); - pms_base = geode_pms_base(); - - if (!acpi_base || !pms_base) - return -ENODEV; - - ret = alloc_inputdevs(); - if (ret) - return ret; - - rdmsr(0x51400020, lo, hi); - sci_irq = (lo >> 20) & 15; - - if (sci_irq) { - printk(KERN_INFO "SCI is mapped to IRQ %d\n", sci_irq); - } else { - /* Zero doesn't mean zero -- it means masked */ - printk(KERN_INFO "SCI unmapped. Mapping to IRQ 3\n"); - sci_irq = 3; - lo |= 0x00300000; - wrmsrl(0x51400020, lo); - } - - olpc_fixup_bios(); - - lo = inl(pms_base + PM_FSD); - - /* Lock, enable failsafe, 4 seconds */ - outl(0xc001f400, pms_base + PM_FSD); - - /* Here we set up the SCI events we're interested in during - * real-time. We have no sleep button, and the RTC doesn't make - * sense, so set up the power button - */ - - outl(inl(acpi_base) | ((CS5536_PM_PWRBTN) << 16), acpi_base); - - if (olpc_get_rev() >= OLPC_REV_B2) { - gpio_wake_events |= GPIO_WAKEUP_LID; - - /* Get the current value of the GPIO, and set up the edges */ - olpc_lid_flag = geode_gpio_isset(OLPC_GPIO_LID, GPIO_READ_BACK); - - /* Watch for the opposite edge */ - - if (olpc_lid_flag) - geode_gpio_set(OLPC_GPIO_LID, GPIO_NEGATIVE_EDGE_EN); - else - geode_gpio_set(OLPC_GPIO_LID, GPIO_POSITIVE_EDGE_EN); - - /* Enable the event */ - geode_gpio_set(OLPC_GPIO_LID, GPIO_EVENTS_ENABLE); - } - - /* Set up the mask for wakeups the EC will generate SCIs on */ - - ret = olpc_ec_cmd(EC_READ_SCI_MASK, NULL, 0, &ec_byte, 1); - if (ret) - printk(KERN_ERR "Error getting the EC SCI mask: %d\n", ret); - - /* Disable battery 1% charge wakeups */ - ec_byte &= ~EC_SCI_SRC_BATSOC; - - ret = olpc_ec_cmd(EC_WRITE_SCI_MASK, &ec_byte, 1, NULL, 0); - if (ret) - printk(KERN_ERR "Error setting the EC SCI mask: %d\n", ret); - - /* Set up the EC SCI */ - - gpio_wake_events |= GPIO_WAKEUP_EC; - - outl(gpio_wake_events, acpi_base + PM_GPE0_EN); - outl(0xFFFFFFFF, acpi_base + PM_GPE0_STS); - - /* Select level triggered in PIC */ - - if (sci_irq < 8) { - lo = inb(0x4d0); - lo |= 1 << sci_irq; - outb(lo, 0x4d0); - } else { - lo = inb(0x4d1); - lo |= 1 << (sci_irq - 8); - outb(lo, 0x4d1); - } - /* Clear pending interrupt */ - outl(inl(acpi_base) | 0xFFFF, acpi_base); - process_sci_queue(0); /* we just want to flush the queue here */ - init_ebook_state(); - - /* Enable the interrupt */ - - ret = request_irq(sci_irq, &olpc_pm_interrupt, 0, "SCI", &acpi_base); - - if (ret) { - printk(KERN_ERR "Error registering SCI: %d\n", ret); - return ret; - } - - ofw_bios_entry.address = 0xF0000 + PAGE_OFFSET; - pm_set_ops(&olpc_pm_ops); - - sysfs_create_group(&power_subsys.kobj, &olpc_attrs); - - return 0; -} - - -#if defined (CONFIG_RTC_DRV_CMOS) || defined (CONFIG_RTC_DRV_CMOS_MODULE) -struct resource rtc_platform_resource[2] = { - { - .flags = IORESOURCE_IO, - .start = RTC_PORT(0), - .end = RTC_PORT(0) + RTC_IO_EXTENT - }, - { - .flags = IORESOURCE_IRQ, - .start = 8, - .end = 8, - }, -}; - - -static void rtc_wake_on(struct device *dev) -{ - olpc_wakeup_mask |= CS5536_PM_RTC; -} - -static void rtc_wake_off(struct device *dev) -{ - olpc_wakeup_mask &= ~(CS5536_PM_RTC); -} - -static struct cmos_rtc_board_info rtc_info = { - .rtc_day_alarm = 0, - .rtc_mon_alarm = 0, - .rtc_century = 0, - .wake_on = rtc_wake_on, - .wake_off = rtc_wake_off, -}; - -struct platform_device olpc_rtc_device = { - .name = "rtc_cmos", - .id = -1, - .num_resources = ARRAY_SIZE(rtc_platform_resource), - .dev.platform_data = &rtc_info, - .resource = rtc_platform_resource, -}; - -static int __init olpc_platform_init(void) -{ - (void)platform_device_register(&olpc_rtc_device); - device_init_wakeup(&olpc_rtc_device.dev, 1); - - (void)platform_device_register(&olpc_powerbutton_dev); - device_init_wakeup(&olpc_powerbutton_dev.dev, 1); - - (void)platform_device_register(&olpc_lid_dev); - device_init_wakeup(&olpc_lid_dev.dev, 1); - - return 0; -} -arch_initcall(olpc_platform_init); -#endif /* CONFIG_RTC_DRV_CMOS */ - -static void olpc_pm_exit(void) -{ - /* Clear any pending events, and disable them */ - outl(0xFFFF, acpi_base+2); - - free_irq(sci_irq, &acpi_base); - input_unregister_device(pm_inputdev); - input_unregister_device(lid_inputdev); - input_unregister_device(ebook_inputdev); -} - -static struct pm_ops olpc_pm_ops = { - .valid = olpc_pm_state_valid, - .enter = olpc_pm_enter, -}; - -module_init(olpc_pm_init); -module_exit(olpc_pm_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); -MODULE_DESCRIPTION("AMD Geode power management for OLPC CL1"); |