|
From: <mar...@us...> - 2007-03-19 20:32:34
|
Revision: 924
http://svn.sourceforge.net/hackndev/?rev=924&view=rev
Author: marex_z71
Date: 2007-03-19 13:19:05 -0700 (Mon, 19 Mar 2007)
Log Message:
-----------
PalmLD: Battery driver and TESTING new powermanagement !!! USE AT YOUR 0WN RISK, IT CAN HANG YOUR DEVICE !!!
Modified Paths:
--------------
linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/Kconfig
linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/Makefile
linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld.c
linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld_ide.c
linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld_pm.c
linux4palm/linux/trunk/include/asm-arm/arch-pxa/palmld-gpio.h
Added Paths:
-----------
linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld_battery.c
linux4palm/linux/trunk/include/asm-arm/arch-pxa/palmld-init.h
Removed Paths:
-------------
linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld_ac97.c
Modified: linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/Kconfig
===================================================================
--- linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/Kconfig 2007-03-18 19:56:23 UTC (rev 923)
+++ linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/Kconfig 2007-03-19 20:19:05 UTC (rev 924)
@@ -21,3 +21,20 @@
config PALMLD_IDE
tristate "Palm LifeDrive IDE driver"
depends on MACH_XSCALE_PALMLD
+
+config PALMLD_BATTERY
+ tristate "Palm LifeDrive Battery support"
+ select TOUCHSCREEN_WM97XX
+ depends on MACH_XSCALE_PALMLD
+ default m
+ help
+ Enable support for PalmOne LifeDrive battery to APM.
+ ATM use it only as module, otherwise it hangs.
+
+config PALMLD_PM
+ tristate "Palm LifeDrive Power Management support"
+ depends on MACH_XSCALE_PALMLD
+ default y if MACH_XSCALE_PALMLD
+ help
+ Enable support for suspend/resume the PalmOne LifeDrive PDA.
+
\ No newline at end of file
Modified: linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/Makefile
===================================================================
--- linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/Makefile 2007-03-18 19:56:23 UTC (rev 923)
+++ linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/Makefile 2007-03-19 20:19:05 UTC (rev 924)
@@ -6,5 +6,6 @@
obj-$(CONFIG_PALMLD_PCMCIA) += palmld_pcmcia.o
obj-$(CONFIG_PALMLD_USB) += palmld_usb.o
obj-$(CONFIG_PALMLD_IDE) += palmld_ide.o
-obj-$(CONFIG_PM) += palmld_pm.o
+obj-$(CONFIG_PALMLD_PM) += palmld_pm.o
+obj-$(CONFIG_PALMLD_BATTERY) += palmld_battery.o
Modified: linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld.c
===================================================================
--- linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld.c 2007-03-18 19:56:23 UTC (rev 923)
+++ linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld.c 2007-03-19 20:19:05 UTC (rev 924)
@@ -234,6 +234,18 @@
};
+/********************
+ * Power Management *
+ ********************/
+
+struct platform_device palmld_pm = {
+ .name = "palmld-pm",
+ .id = -1,
+ .dev = {
+ .platform_data = NULL,
+ },
+};
+
/*********************************************************
* IDE
*********************************************************/
@@ -246,7 +258,7 @@
static struct platform_device *devices[] __initdata = {
&palmld_kbd, &palmld_ac97, &palmld_ide, &palmld_backlight,
- &palmldled_device,
+ &palmldled_device, &palmld_pm,
};
/*********************************************************
@@ -325,13 +337,6 @@
static void __init palmld_init(void)
{
-
-
-#ifdef CONFIG_PM
- extern struct pxa_ll_pm_ops palmld_ll_pm_ops;
- pxa_pm_set_ll_ops(&palmld_ll_pm_ops);
-#endif
-
set_pxa_fb_info( &palmld_lcd_screen );
pxa_set_mci_info( &palmld_mci_platform_data );
platform_add_devices( devices, ARRAY_SIZE(devices) );
Deleted: linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld_ac97.c
===================================================================
--- linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld_ac97.c 2007-03-18 19:56:23 UTC (rev 923)
+++ linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld_ac97.c 2007-03-19 20:19:05 UTC (rev 924)
@@ -1,544 +0,0 @@
-/*
- * linux/arch/arm/mach-pxa/palmld/palmld-ts.c
- *
- * Touchscreen/battery driver for Palm LifeDrive's WM9712 AC97 codec.
- *
- * Author: Alex Osborne <bob...@gm...>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/input.h>
-#include <linux/device.h>
-#include <linux/workqueue.h>
-#include <linux/battery.h>
-
-#include <asm/delay.h>
-#include <asm/arch/hardware.h>
-#include <asm/arch/pxa-regs.h>
-#include <asm/arch/irqs.h>
-#include <asm/arch/palmld-gpio.h>
-#include <asm/arch/palmld-ac97.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <sound/driver.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/initval.h>
-#include <sound/ac97_codec.h>
-
-
-#define palmld_ac97_WORK_QUEUE_NAME "palmld_ac97.c"
-
-#define GET_GPIO(gpio) \
- (GPLR(gpio) & GPIO_bit(gpio))
-
-#define X_AXIS_MAX 3630
-#define X_AXIS_MIN 200
-#define Y_AXIS_MAX 3880
-#define Y_AXIS_MIN 160
-#define PRESSURE_MIN 0
-#define PRESSURE_MAX 300
-
-#define GPIO_DEBUG
-
-static spinlock_t palmld_ac97_lock = SPIN_LOCK_UNLOCKED;
-
-static struct workqueue_struct *palmld_ac97_workqueue;
-static struct work_struct palmld_ac97_irq_task;
-struct input_dev *palmld_ac97_input;
-struct device *palmld_ac97_dev;
-
-static u64 battery_update_jiffies_64 = 0;
-static int battery_voltage;
-
-DECLARE_MUTEX(battery_update_mutex);
-
-/*
- * ac97 codec
- */
-
-void wm97xx_gpio_func(ac97_t *ac97, int gpio, int func)
-{
- int GEn;
- GEn = ac97->bus->ops->read(ac97, 0x56);
- if(func)
- GEn |= gpio;
- else
- GEn &= ~gpio;
- ac97->bus->ops->write(ac97, 0x56, GEn);
-}
-
-void wm97xx_gpio_mode(ac97_t *ac97, int gpio, int config, int polarity,
- int sticky, int wakeup)
-{
- int GCn, GPn, GSn, GWn;
- GCn = ac97->bus->ops->read(ac97, 0x4c);
- GPn = ac97->bus->ops->read(ac97, 0x4e);
- GSn = ac97->bus->ops->read(ac97, 0x50);
- GWn = ac97->bus->ops->read(ac97, 0x52);
-
- if(config)
- GCn |= gpio;
- else
- GCn &= ~gpio;
-
- if(polarity)
- GPn |= gpio;
- else
- GPn &= ~gpio;
-
- if(sticky)
- GSn |= gpio;
- else
- GSn &= ~gpio;
-
- if(wakeup)
- GWn |= gpio;
- else
- GWn &= ~gpio;
-
- ac97->bus->ops->write(ac97, 0x4c, GCn);
- ac97->bus->ops->write(ac97, 0x4e, GPn);
- ac97->bus->ops->write(ac97, 0x50, GSn);
- ac97->bus->ops->write(ac97, 0x52, GWn);
-}
-
-void wm97xx_set_digitiser_power(struct device *dev, int value)
-{
- ac97_t *ac97 = dev->platform_data;
- u16 d2;
-
- d2 = ac97->bus->ops->read(ac97, AC97_WM97XX_DIGITISER2);
- d2 |= value;
- ac97->bus->ops->write(ac97, AC97_WM97XX_DIGITISER2, d2);
-}
-
-/*
- * This is a hack that waits until the ac97 bus is free. I was unable to find
- * a more appropriate way of doing this, but it seems to work. If we don't use
- * this, then the driver will eventually conflict with another driver's use
- * of AC97 (probably audio) and will lockup.
- */
-void wait_for_ac97(void)
-{
- int timeout=1000;
-
- while (CAR & CAR_CAIP) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ/100);
- set_current_state(TASK_RUNNING);
- if(!timeout--) {
- printk("palmld_ac97_pendown: CAR_CAIP timeout\n");
- return;
- }
- }
- CAR &= ~CAR_CAIP;
-
-}
-
-static int palmld_ac97_take_reading(struct device *dev, int adcsel)
-{
- ac97_t *ac97 = dev->platform_data;
- int timeout=100;
- u16 r76, r7a;
-
- r76 = ac97->bus->ops->read(ac97, 0x76);
- r76 &= ~WM97XX_ADCSEL_MASK; /* clear ADCSEL */
- r76 |= adcsel; /* set ADCSEL */
- r76 &= ~(1<<11); /* COO = 0 (single measurement) */
- r76 &= ~(1<<10); /* CTC = 0 (polling mode) */
- r76 |= (1<<15); /* start reading */
- ac97->bus->ops->write(ac97, 0x76, r76);
-
- do {
- if(!(timeout--)) {
- printk("palmld_ac97_pendown: timed out waiting for poll to complete.\n");
- return 0;
- }
- //udelay(1);
- r76 = ac97->bus->ops->read(ac97, 0x76);
- } while(!(r76 & (1<<15)));
- printk("Poll complete loops=%d\n", 100-timeout);
-
- r7a = ac97->bus->ops->read(ac97, 0x7a);
- return r7a;
-}
-
-
-
-/*
- * battery
- */
-
-void update_data(int force)
-{
- u16 reading;
-
- if(!force && (battery_update_jiffies_64 + HZ > jiffies_64)) {
- return;
- }
-
- if(down_trylock(&battery_update_mutex)) {
- return;
- }
-
-
- spin_lock(&palmld_ac97_lock);
- wait_for_ac97();
-
- #ifdef GPIO_DEBUG
- ac97_t *ac97 = palmld_ac97_dev->platform_data;
-
- // invert and univert the gpio a few times while watching
- // the PXA's gpios to see if we can spot a connection ;)
- printk("%x %x %x\n", GPLR0, GPLR1, GPLR2);
-
- reading = ac97->bus->ops->read(ac97, 0x58);
- ac97->bus->ops->write(ac97, 0x58, reading | 1);
- udelay(10);
- printk("%x %x %x %x\n", GPLR0, GPLR1, GPLR2, GPLR3);
-
- reading = ac97->bus->ops->read(ac97, 0x58);
- ac97->bus->ops->write(ac97, 0x58, reading & (~1));
- udelay(10);
- printk("%x %x %x %x\n", GPLR0, GPLR1, GPLR2, GPLR3);
-
-
- #else
- wm97xx_set_digitiser_power(palmld_ac97_dev, WM97XX_PRP_DET_DIG);
- reading = palmld_ac97_take_reading(palmld_ac97_dev, WM97XX_ADCSEL_BMON);
- wm97xx_set_digitiser_power(palmld_ac97_dev, WM97XX_PRP_DET);
-
- #endif
-
- spin_unlock(&palmld_ac97_lock);
- battery_voltage = reading & 0xfff;
- printk("Battery: %d\n", battery_voltage);
-
- battery_update_jiffies_64 = jiffies_64;
- up(&battery_update_mutex);
-}
-
-int get_min_voltage(struct battery *b)
-{
- return 0;
-}
-int get_min_charge(struct battery *b)
-{
- return 0;
-}
-int get_max_voltage(struct battery *b)
-{
- return 4750; /* mV */
-}
-int get_max_charge(struct battery *b)
-{
- return 1;
-}
-int get_voltage(struct battery *b)
-{
- update_data(0);
- return battery_voltage;
-}
-int get_charge(struct battery *b)
-{
- return 0;
-}
-int get_status(struct battery *b)
-{
- return 0; //power_status == POWER_NONE? 0: 1;
-}
-
-static struct battery palmld_battery = {
- .name = "palmld-ac97",
- .id = "battery0",
- .get_min_voltage = get_min_voltage,
- .get_min_current = NULL,
- .get_min_charge = get_min_charge,
- .get_max_voltage = get_max_voltage,
- .get_max_current = NULL,
- .get_max_charge = get_max_charge,
- .get_temp = NULL,
- .get_voltage = get_voltage,
- .get_current = NULL,
- .get_charge = get_charge,
- .get_status = get_status,
-};
-
-static void
-battery_class_release(struct class_device *dev)
-{
-}
-
-static void
-battery_class_class_release(struct class *class)
-{
-}
-
-
-/*
- * touchscreen
- */
-
-static void palmld_ac97_pendown(struct device *dev)
-{
- ac97_t *ac97 = dev->platform_data;
- int xread, yread, pressure;
- int pendown=0, valid_coords=0;
-
-
-
- /*
- * shut off the pen detect interrupt until pen goes up, otherwise the WM9712
- * will keep on interrupting us and we'll never be able to get any work
- * done.
- */
- spin_lock(&palmld_ac97_lock);
- wait_for_ac97();
- wm97xx_gpio_mode(ac97, WM97XX_GPIO_13, WM97XX_GPIO_IN,
- WM97XX_GPIO_POL_HIGH, WM97XX_GPIO_NOTSTICKY, WM97XX_GPIO_NOWAKE);
- spin_unlock(&palmld_ac97_lock);
-
-
- /* take readings until the pen goes up */
- do {
- spin_lock(&palmld_ac97_lock);
- wait_for_ac97();
-
- /* power up digitiser */
- wm97xx_set_digitiser_power(dev, WM97XX_PRP_DET_DIG);
-
- /* take readings */
- xread = palmld_ac97_take_reading(dev, WM97XX_ADCSEL_X);
- yread = palmld_ac97_take_reading(dev, WM97XX_ADCSEL_Y);
- pressure = palmld_ac97_take_reading(dev, WM97XX_ADCSEL_PRES);
-
- /* power down digitiser to conserve power */
- wm97xx_set_digitiser_power(dev, WM97XX_PRP_DET);
-
- printk("(%d,%d) = %d\n", xread&0xfff, yread&0xfff, pressure&0xfff);
-
- pendown = pressure & (1<<15);
- valid_coords = (xread & 0xfff) && (yread & 0xfff) && (pressure & 0xfff);
-
- /*
- * with light pressure reading is exteremely inaccurate so only report
- * it when there is heavy pressure
- */
- if( (!pendown) || (pressure & 0xfff) < 100 ) {
-
- /* valid coordinates? */
- if(valid_coords) {
- input_report_abs(palmld_ac97_input, ABS_X, xread & 0xfff);
- input_report_abs(palmld_ac97_input, ABS_Y, yread & 0xfff);
- input_report_abs(palmld_ac97_input, ABS_PRESSURE, pressure & 0xfff);
- }
-
- if(valid_coords || !pendown) {
- input_report_key(palmld_ac97_input, BTN_TOUCH, pendown);
- }
- input_sync(palmld_ac97_input);
- }
-
- spin_unlock(&palmld_ac97_lock);
-
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ/100);
- set_current_state(TASK_RUNNING);
- } while(pressure & (1<<15));
-
- /* re-enable pen detect interrupt */
- spin_lock(&palmld_ac97_lock);
- wait_for_ac97();
- wm97xx_gpio_mode(ac97, WM97XX_GPIO_13, WM97XX_GPIO_IN,
- WM97XX_GPIO_POL_HIGH, WM97XX_GPIO_STICKY, WM97XX_GPIO_WAKE);
- spin_unlock(&palmld_ac97_lock);
-
- printk("exit\n");
-}
-
-static void palmld_ac97_irq_work(void *data)
-{
- int change = 0;
- struct device *dev = data;
- ac97_t *ac97 = dev->platform_data;
- u16 levels;
-
-
- //while(GET_GPIO(27)) { /* while interrupt still there */
-
- spin_lock(&palmld_ac97_lock);
- wait_for_ac97();
- levels = ac97->bus->ops->read(ac97, 0x54);
- spin_unlock(&palmld_ac97_lock);
-
- printk("int %x\n", levels);
-
-
- if(levels & WM97XX_GPIO_13) {
- printk("Pen down detected %x\n", levels);
- levels &= ~WM97XX_GPIO_13;
- //wm9712_initiate_measurement(ac97);
- palmld_ac97_pendown(dev);
- change++;
- }
-
- spin_lock(&palmld_ac97_lock);
- wait_for_ac97();
- ac97->bus->ops->write(ac97, 0x54, levels);
- spin_unlock(&palmld_ac97_lock);
- //}
-
-
-}
-
-static irqreturn_t palmld_ac97_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
-{
- /*
- * we can't use ac97 from within the interrupt handler, so schedule a task
- * to do the actual handling.
- */
- queue_work(palmld_ac97_workqueue, &palmld_ac97_irq_task);
-
- return IRQ_HANDLED;
-}
-
-static int __init palmld_ac97_probe(struct device *dev)
-{
- int err;
- ac97_t *ac97 = dev->platform_data;
- u16 d2;
-
- if(!machine_is_xscale_palmld())
- return -ENODEV;
- printk("palmld_ac97_probe\n");
-
- /* for use by bettery level monitor */
- palmld_ac97_dev = dev;
-
- /* setup work queue */
- palmld_ac97_workqueue = create_workqueue(palmld_ac97_WORK_QUEUE_NAME);
- INIT_WORK(&palmld_ac97_irq_task, palmld_ac97_irq_work, dev);
-
-
- set_irq_type(IRQ_GPIO_PALMLD_WM9712_IRQ, IRQT_RISING);
- err = request_irq(IRQ_GPIO_PALMLD_WM9712_IRQ, palmld_ac97_irq_handler,
- SA_INTERRUPT, "WM9712 IRQ", dev);
-
- if(err) {
- printk(KERN_ERR "palmld_ac97_probe: cannot request pen down IRQ\n");
- return -1;
- }
-
- spin_lock(&palmld_ac97_lock);
-
- printk("x\n");
-
- /* reset levels */
- ac97->bus->ops->write(ac97, 0x54, 0);
- printk("y\n");
-
- /* disable digitiser to save power, enable pen-down detect */
- d2 = ac97->bus->ops->read(ac97, AC97_WM97XX_DIGITISER2);
- d2 |= WM97XX_PRP_DET;
- ac97->bus->ops->write(ac97, AC97_WM97XX_DIGITISER2, d2);
-
-
- /* enable interrupts on codec's gpio 2 (connected to cpu gpio 27) */
- wm97xx_gpio_mode(ac97, WM97XX_GPIO_2, WM97XX_GPIO_IN,
- WM97XX_GPIO_POL_HIGH, WM97XX_GPIO_NOTSTICKY, WM97XX_GPIO_NOWAKE);
- wm97xx_gpio_func(ac97, WM97XX_GPIO_2, 0);
-
- /* enable pen detect interrupt */
- wm97xx_gpio_mode(ac97, WM97XX_GPIO_13, WM97XX_GPIO_IN,
- WM97XX_GPIO_POL_HIGH, WM97XX_GPIO_STICKY, WM97XX_GPIO_WAKE);
-
- /* enable ada detect interrupt */
- /*
- wm97xx_gpio_mode(ac97, WM97XX_GPIO_12, WM97XX_GPIO_IN,
- WM97XX_GPIO_POL_HIGH, WM97XX_GPIO_NOTSTICKY, WM97XX_GPIO_NOWAKE);
- */
-
- /* turn off irq gpio inverting */
- ac97->bus->ops->write(ac97, 0x58, ac97->bus->ops->read(ac97, 0x58)&~1);
-
-
- /* turn on the digitiser and pen down detector */
- d2 = ac97->bus->ops->read(ac97, AC97_WM97XX_DIGITISER2);
- d2 |= WM97XX_PRP_DETW;
- ac97->bus->ops->write(ac97, AC97_WM97XX_DIGITISER2, d2);
- printk("probe\n");
-
- spin_unlock(&palmld_ac97_lock);
-
- /* setup the input device */
- palmld_ac97_input = input_allocate_device();
- palmld_ac97_input->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- palmld_ac97_input->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
- input_set_abs_params(palmld_ac97_input, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
- input_set_abs_params(palmld_ac97_input, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
- input_set_abs_params(palmld_ac97_input, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0);
-
- palmld_ac97_input->name = "Palm LifeDrive touchscreen";
- palmld_ac97_input->dev = dev;
- palmld_ac97_input->id.bustype = BUS_HOST;
- input_register_device(palmld_ac97_input);
-
- /* register battery */
- if(battery_class_register(&palmld_battery)) {
- printk(KERN_ERR "palmld_ac97_probe: Could not register battery "
- "class\n");
- } else {
- palmld_battery.class_dev.class->release = battery_class_release;
- palmld_battery.class_dev.class->class_release = battery_class_class_release;
- }
-
- return 0;
-}
-
-static int __exit palmld_ac97_remove (struct device *dev)
-{
- ac97_t *ac97 = dev->platform_data;
- printk("x: %x\n", ac97->bus->ops->read(ac97, AC97_WM97XX_DIGITISER2));
- input_unregister_device(palmld_ac97_input);
- free_irq(IRQ_GPIO_PALMLD_WM9712_IRQ, dev);
- return 0;
-}
-
-static struct device_driver palmld_ac97_driver = {
- .name = "WM9711,WM9712",
- .bus = &ac97_bus_type,
- .probe = palmld_ac97_probe,
- .remove = palmld_ac97_remove,
-#ifdef CONFIG_PM
- .suspend = NULL,
- .resume = NULL,
-#endif
-};
-
-static int __init palmld_ac97_init(void)
-{
- if(!machine_is_xscale_palmld())
- return -ENODEV;
-
-
- return driver_register(&palmld_ac97_driver);
-}
-
-static void __exit palmld_ac97_exit(void)
-{
- driver_unregister(&palmld_ac97_driver);
-}
-
-module_init(palmld_ac97_init);
-module_exit(palmld_ac97_exit);
-
-MODULE_AUTHOR ("Alex Osborne <bob...@gm...>");
-MODULE_DESCRIPTION ("WM9712 AC97 codec support for Palm LifeDrive");
-MODULE_LICENSE ("GPL");
Added: linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld_battery.c
===================================================================
--- linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld_battery.c (rev 0)
+++ linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld_battery.c 2007-03-19 20:19:05 UTC (rev 924)
@@ -0,0 +1,236 @@
+/************************************************************************
+ * linux/arch/arm/mach-pxa/palmld/palmld_battery.c *
+ * *
+ * Touchscreen/battery driver for WM9712 AC97 codec *
+ * Authros: Jan Herman <2h...@se...> *
+ * Sergey Lapin <sl...@ha...> *
+ * Changes for PalmLD: Marek Vasut <mar...@gm...> *
+ * *
+ ************************************************************************/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/battery.h>
+
+#include <asm/apm.h>
+#include <asm/delay.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/irqs.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <linux/wm97xx.h>
+#include <asm/arch/palmld-gpio.h>
+#include <asm/arch/palmld-init.h>
+
+
+struct palmld_battery_dev
+{
+ struct wm97xx * wm;
+ int battery_registered;
+ int current_voltage;
+ int previous_voltage;
+ u32 last_battery_update;
+};
+
+struct palmld_battery_dev bat;
+
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
+/* original APM hook */
+static void (*apm_get_power_status_orig)(struct apm_power_info *info);
+#endif
+
+int palmld_battery_min_voltage(struct battery *b)
+{
+ return PALMLD_BAT_MIN_VOLTAGE;
+}
+
+
+int palmld_battery_max_voltage(struct battery *b)
+{
+ return PALMLD_BAT_MAX_VOLTAGE; /* mV */
+}
+
+/*
+ This formula is based on battery life of my battery 1100mAh. Original battery in Zire72 is Li-On 920mAh
+ V_batt = ADCSEL_BMON * 1,889 + 767,8 [mV]
+*/
+
+int palmld_battery_get_voltage(struct battery *b)
+{
+ if (bat.battery_registered){
+ bat.previous_voltage = bat.current_voltage;
+ bat.current_voltage = wm97xx_read_aux_adc(bat.wm, WM97XX_AUX_ID3);
+ bat.last_battery_update = jiffies;
+ return bat.current_voltage * 1889/1000 + 7678/10;
+ }
+ else{
+ printk("palmld_battery: cannot get voltage -> battery driver unregistered\n");
+ return 0;
+ }
+}
+
+
+int palmld_battery_get_status(struct battery *b)
+{
+ int ac_connected = GET_PALMLD_GPIO(POWER_DETECT);
+ int usb_connected = !GET_PALMLD_GPIO(USB_DETECT);
+
+ if (bat.current_voltage <= 0)
+ return BATTERY_STATUS_UNKNOWN;
+
+ if (ac_connected || usb_connected){
+ if ( ( bat.current_voltage > bat.previous_voltage ) || (bat.current_voltage <= PALMLD_BAT_MAX_VOLTAGE) )
+ return BATTERY_STATUS_CHARGING;
+ return BATTERY_STATUS_NOT_CHARGING;
+ }
+ else
+ return BATTERY_STATUS_DISCHARGING;
+}
+
+struct battery palmld_battery = {
+ .name = "palmld_battery",
+ .id = "battery0",
+ .get_min_voltage = palmld_battery_min_voltage,
+ .get_max_voltage = palmld_battery_max_voltage,
+ .get_voltage = palmld_battery_get_voltage,
+ .get_status = palmld_battery_get_status,
+};
+
+static int palmld_wm97xx_probe(struct device *dev)
+{
+ struct wm97xx *wm = dev->driver_data;
+ bat.wm = wm;
+ return 0;
+}
+
+static int palmld_wm97xx_remove(struct device *dev)
+{
+ return 0;
+}
+
+static void
+palmld_wm97xx_shutdown(struct device *dev)
+{
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
+ apm_get_power_status = apm_get_power_status_orig;
+#endif
+}
+
+static int
+palmld_wm97xx_suspend(struct device *dev, pm_message_t state)
+{
+ return 0;
+}
+
+static int
+palmld_wm97xx_resume(struct device *dev)
+{
+ return 0;
+}
+
+
+static struct device_driver palmld_wm97xx_driver = {
+ .name = "wm97xx-touchscreen",
+ .bus = &wm97xx_bus_type,
+ .owner = THIS_MODULE,
+ .probe = palmld_wm97xx_probe,
+ .remove = palmld_wm97xx_remove,
+ .suspend = palmld_wm97xx_suspend,
+ .resume = palmld_wm97xx_resume,
+ .shutdown = palmld_wm97xx_shutdown
+};
+
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
+
+/* APM status query callback implementation */
+static void palmld_apm_get_power_status(struct apm_power_info *info)
+{
+ int min, max, curr, percent;
+
+ curr = palmld_battery_get_voltage(&palmld_battery);
+ min = palmld_battery_min_voltage(&palmld_battery);
+ max = palmld_battery_max_voltage(&palmld_battery);
+
+ curr = curr - min;
+ if (curr < 0) curr = 0;
+ max = max - min;
+
+ percent = curr*100/max;
+
+ info->battery_life = percent;
+
+ info->ac_line_status = (GET_PALMLD_GPIO(POWER_DETECT)
+ ? APM_AC_ONLINE : APM_AC_OFFLINE);
+
+ if (info->ac_line_status) {
+ info->battery_status = APM_BATTERY_STATUS_CHARGING;
+ } else {
+ if (percent > 50)
+ info->battery_status = APM_BATTERY_STATUS_HIGH;
+ else if (percent < 5)
+ info->battery_status = APM_BATTERY_STATUS_CRITICAL;
+ else
+ info->battery_status = APM_BATTERY_STATUS_LOW;
+ }
+
+ info->time = percent * PALMLD_MAX_LIFE_MINS/100;
+ info->units = APM_UNITS_MINS;
+}
+#endif
+static int __init palmld_wm97xx_init(void)
+{
+#ifndef MODULE
+ int ret;
+#endif
+
+ /* register battery to APM layer */
+ bat.battery_registered = 0;
+
+ if(battery_class_register(&palmld_battery)) {
+ printk(KERN_ERR "palmld_ac97_probe: could not register battery class\n");
+ }
+ else {
+ bat.battery_registered = 1;
+ printk("Battery registered\n");
+ }
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
+ apm_get_power_status_orig = apm_get_power_status;
+ apm_get_power_status = palmld_apm_get_power_status;
+#endif
+#ifndef MODULE
+ /* If we're in kernel, we could accidentally be run before wm97xx
+ and thus have panic */
+ if((ret = bus_register(&wm97xx_bus_type)) < 0)
+ return ret;
+#endif
+ return driver_register(&palmld_wm97xx_driver);
+}
+
+static void __exit palmld_wm97xx_exit(void)
+{
+/* TODO - recover APM callback to original state */
+ battery_class_unregister(&palmld_battery);
+ driver_unregister(&palmld_wm97xx_driver);
+}
+
+module_init(palmld_wm97xx_init);
+module_exit(palmld_wm97xx_exit);
+
+/* Module information */
+MODULE_AUTHOR("Sergey Lapin <sl...@ha...> Jan Herman <2h...@se...>");
+MODULE_DESCRIPTION("wm97xx battery driver");
+MODULE_LICENSE("GPL");
Modified: linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld_ide.c
===================================================================
--- linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld_ide.c 2007-03-18 19:56:23 UTC (rev 923)
+++ linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld_ide.c 2007-03-19 20:19:05 UTC (rev 924)
@@ -67,6 +67,8 @@
.bus = &platform_bus_type,
.probe = palmld_ide_probe,
.remove = palmld_ide_remove,
+ .suspend= NULL,
+ .resume = NULL,
};
static int __init palmld_ide_init(void)
Modified: linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld_pm.c
===================================================================
--- linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld_pm.c 2007-03-18 19:56:23 UTC (rev 923)
+++ linux4palm/linux/trunk/arch/arm/mach-pxa/palmld/palmld_pm.c 2007-03-19 20:19:05 UTC (rev 924)
@@ -1,87 +1,185 @@
+/************************************************************************
+ * PalmOne LifeDrive suspend/resume support *
+ * *
+ * Author: Jan Herman <2h...@se...> *
+ * Sergey Lapin <sla...@gm...> *
+ * Modification for Palm LifeDrive: Marek Vasut <mar...@gm...> *
+ * *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License version 2 as *
+ * published by the Free Software Foundation. *
+ * *
+ ************************************************************************/
+
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/pm.h>
+#include <linux/fb.h>
+#include <linux/platform_device.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/arch/pm.h>
#include <asm/arch/pxa-pm_ll.h>
#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
-static u32 *addr_a0200000;
-static u32 *addr_a0200004;
-static u32 *addr_a0200008;
-static u32 save_a0200000;
-static u32 save_a0200004;
-static u32 save_a0200008;
+#include <asm/arch/palmld-gpio.h>
+#include <asm/arch/pxa27x_keyboard.h>
-static void palmld_pxa_ll_pm_suspend(unsigned long resume_addr)
+#define KPASMKP(col) (col/2==0 ? KPASMKP0 : col/2==1 ? KPASMKP1 : col/2==2 ? KPASMKP2 : KPASMKP3)
+#define KPASMKPx_MKC(row, col) (1 << (row + 16*(col%2)))
+
+struct pm_save_data
{
+ int brightness;
+ u32 rcnr;
+};
- /* wake up on */
- PWER |= PWER_GPIO12;
- //PFER |= PWER_RTC;
- PRER |= PWER_GPIO12;
-
- /* USB, in theory this can even wake us from deep sleep */
- PWER |= PWER_GPIO3;
- PFER |= PWER_GPIO3;
- PRER |= PWER_GPIO3;
-
- /* disable GPIO reset, palm bootloader will hang us */
- //PCFR |= PCFR_GPR_EN | PCFR_OPDE;
- PCFR &= PCFR_GPR_EN;
-
- /* as set by POS */
- /*PGSR0 = 0x00020000;
- PGSR1 = 0x00000000;
- PGSR2 = 0x01004000;
- PGSR3 = 0x00421380;
-
- PGSR2 |= (1<<30);
- PGSR3 |= (1<<7) | (1<<8) | (1<<9);
+static struct pm_save_data pm_save_data;
- PSLR = 0xff400000;
- */
- //PKWR |= GPIO_bit(0) | GPIO_bit(12) | GPIO_bit(3) | (1<<17);
- //PKSR = 0xffffffff; // clear
+#ifdef CONFIG_PM
+static int palmld_suspend(struct device *dev, pm_message_t state)
+{
+ /* Wake-Up on RTC event, etc. */
+ PWER |= PWER_RTC | PWER_WEP1;
+ /* Wake-Up on powerbutton */
+ PWER |= PWER_GPIO12;
+ PRER |= PWER_GPIO12;
- /*
- addr_a0200000 = phys_to_virt(0xa0200000);
- addr_a0200004 = phys_to_virt(0xa0200004);
- addr_a0200008 = phys_to_virt(0xa0200008);
+ /* USB, in theory this can even wake us from deep sleep */
+// PWER |= PWER_GPIO3;
+// PFER |= PWER_GPIO3;
+// PRER |= PWER_GPIO3;
- save_a0200000 = *addr_a0200000;
- save_a0200004 = *addr_a0200004;
- save_a0200008 = *addr_a0200008;
- */
- /*
- c: e3a00121 mov r0, #1073741832 ; 0x40000008
- 10: e280060f add r0, r0, #15728640 ; 0xf00000
- 14: e590f000 ldr pc, [r0]
- */
-
- /*
- *addr_a0200000 = 0xe3a00121; // mov r0, #0x40000008
- *addr_a0200004 = 0xe280060f; // add r0, r0, #0xf00000
- *addr_a0200008 = 0xe590f000; // ldr pc, [r0]
- */
+ /* Wakeup by keyboard :) */
+// PKWR = 0xe0001;
- PSPR = 0; /* should cause Palm bootloader to allow us to reboot */
+ /* Enabled Deep-Sleep mode */
+ PCFR |= PCFR_DS;
+
+ /* Low power mode */
+ PCFR |= PCFR_OPDE;
+
+
+ /* 3.6.8.1 */
+ while(!(OSCC & OSCC_OOK))
+ {}
+
+ /* disable GPIO reset, palm bootloader will hang us */
+ //PCFR |= PCFR_GPR_EN | PCFR_OPDE;
+ PCFR &= PCFR_GPR_EN;
+
+ return 0;
+}
+
+static int palmld_resume(struct device *dev)
+{
+ /* Disabled Deep-Sleep mode ?? */
+ PCFR &= PCFR_DS;
+
+ /* Re-enable GPIO reset */
+ PCFR |= PCFR_GPR_EN; /* !! DO NOT REMOVE !! THIS IS NECCESARY FOR ENABLE PALM RESET !! */
+
+
+ /* Here are all of special to resume PalmOne LifeDrive */
+
+ /* Turn on LCD power */
+// SET_PALMZ72_GPIO(LCD_POWER,1);
+ /* Turn on USB power */
+// SET_PALMZ72_GPIO(USB_POWER,1);
+
+ return 0;
+}
+#else
+#define palmld_suspend NULL
+#define palmld_resume NULL
+#endif
+
+static void palmld_pxa_ll_pm_suspend(unsigned long resume_addr)
+{
+ /* For future */
return;
}
static void palmld_pxa_ll_pm_resume(void)
{
- /*
- *addr_a0200000 = save_a0200000;
- *addr_a0200004 = save_a0200004;
- *addr_a0200008 = save_a0200008;
- */
-
- /* re-enable GPIO reset */
- PCFR |= PCFR_GPR_EN;
+ /* For future */
}
struct pxa_ll_pm_ops palmld_ll_pm_ops = {
- .suspend = palmld_pxa_ll_pm_suspend,
- .resume = palmld_pxa_ll_pm_resume,
+ .suspend = palmld_pxa_ll_pm_suspend,
+ .resume = palmld_pxa_ll_pm_resume,
};
+
+static int (*pxa_pm_enter_orig)(suspend_state_t state);
+
+static int lifedrive_enter_suspend(suspend_state_t state)
+{
+ /* Here we should implement wakeup conditions
+ If we have none, just return 1 to continue
+ sleeping */
+ int data = 0;
+
+ /* Do not suspend on active keypress */
+ pxa_pm_enter_orig(state);
+
+ printk(KERN_NOTICE "Returning from sleep due to GPIOs 100-102 or 13\n");
+ printk(KERN_NOTICE "RCNR = %u pm_save_data.rcnr = %u\n", RCNR, pm_save_data.rcnr);
+ printk(KERN_NOTICE "Keys pressed: %d\n", data);
+ pm_save_data.rcnr = 0;
+ return 0;
+}
+static int lifedrive_pxa_pm_enter(suspend_state_t state)
+{
+ pm_save_data.rcnr = 0;
+ pxa_pm_enter_orig(state);
+ while (lifedrive_enter_suspend(state))
+ {}
+ return 0;
+}
+
+
+static struct pm_ops lifedrive_pm_ops = {
+ .pm_disk_mode = PM_DISK_FIRMWARE,
+ .prepare = pxa_pm_prepare,
+ .enter = lifedrive_pxa_pm_enter,
+ .finish = pxa_pm_finish,
+};
+
+extern struct pm_ops pxa_pm_ops;
+
+static int palmld_pm_probe(struct device *dev)
+{
+ printk(KERN_NOTICE "PalmOne LifeDrive power management driver registered\n");
+ return 0;
+}
+
+struct device_driver palmld_pm_driver = {
+ .name = "palmld-pm",
+ .bus = &platform_bus_type,
+ .probe = palmld_pm_probe,
+ .suspend = palmld_suspend,
+ .resume = palmld_resume,
+};
+
+static int __init palmld_pm_init(void)
+{
+pxa_pm_enter_orig=pxa_pm_ops.enter;
+ pxa_pm_ops.enter = pxa_pm_enter_orig;
+ return driver_register(&palmld_pm_driver);
+}
+
+static void __exit palmld_pm_exit(void)
+{
+ pxa_pm_ops.enter = pxa_pm_enter_orig;
+ driver_unregister(&palmld_pm_driver);
+}
+
+module_init(palmld_pm_init);
+module_exit(palmld_pm_exit);
+
+MODULE_AUTHOR("Jan Herman <2h...@se...>, Sergey Lapin <sla...@gm...>");
+MODULE_DESCRIPTION("PalmOne LifeDrive power management driver");
+MODULE_LICENSE("GPL");
Modified: linux4palm/linux/trunk/include/asm-arm/arch-pxa/palmld-gpio.h
===================================================================
--- linux4palm/linux/trunk/include/asm-arm/arch-pxa/palmld-gpio.h 2007-03-18 19:56:23 UTC (rev 923)
+++ linux4palm/linux/trunk/include/asm-arm/arch-pxa/palmld-gpio.h 2007-03-19 20:19:05 UTC (rev 924)
@@ -41,6 +41,8 @@
#define GPIO_NR_PALMLD_ORANGE_LED 94
#define GPIO_NR_PALMLD_IDE_IRQ 95
+#define GPIO_NR_PALMLD_LCD_POWER 96
+
#define GPIO_NR_PALMLD_KP_MKIN3 97 /* rotate-display, center, left */
#define GPIO_NR_PALMLD_IDE_RESET 98
Added: linux4palm/linux/trunk/include/asm-arm/arch-pxa/palmld-init.h
===================================================================
--- linux4palm/linux/trunk/include/asm-arm/arch-pxa/palmld-init.h (rev 0)
+++ linux4palm/linux/trunk/include/asm-arm/arch-pxa/palmld-init.h 2007-03-19 20:19:05 UTC (rev 924)
@@ -0,0 +1,34 @@
+/*
+ * palmld-init.h
+ *
+ * Init values for PalmOne LifeDrive Handheld Computer
+ *
+ * Author: Marek Vasut <mar...@gm...>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *
+ *
+ */
+
+#ifndef _INCLUDE_PALMLD_INIT_H_
+
+#define _INCLUDE_PALMLD_INIT_H_
+
+
+// BATTERY
+
+#define PALMLD_BAT_MAX_VOLTAGE 4000 // 4.00V current voltage at max charge as from PalmOS
+#define PALMLD_BAT_MIN_VOLTAGE 3600 // 3.60V critical voltage as from Zlauncher
+#define PALMLD_BAT_MAX_CURRENT 0 // unknokn
+#define PALMLD_BAT_MIN_CURRENT 0 // unknown
+#define PALMLD_BAT_MAX_CHARGE 1 // unknown
+#define PALMLD_BAT_MIN_CHARGE 1 // unknown
+#define PALMLD_BAT_MEASURE_DELAY (HZ * 1)
+#define PALMLD_MAX_LIFE_MINS 240 // my LifeDrive on-life in minutes
+
+
+#endif
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|