aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/olpc/files-2.6.23/arch/i386/kernel/olpc-pm.c
diff options
context:
space:
mode:
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.c785
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");