]> code.ossystems Code Review - openembedded-core.git/commitdiff
linux-rp: Add HTC Universal support.
authorSamuel Ortiz <sameo@openedhand.com>
Thu, 23 Aug 2007 13:25:56 +0000 (13:25 +0000)
committerSamuel Ortiz <sameo@openedhand.com>
Thu, 23 Aug 2007 13:25:56 +0000 (13:25 +0000)
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@2545 311d38ba-8fff-0310-9ca6-ca027cbcb966

meta/packages/linux/linux-rp-2.6.22/defconfig-htcuniversal
meta/packages/linux/linux-rp-2.6.22/htcuni.patch
meta/packages/linux/linux-rp-2.6.22/pda-power.patch [new file with mode: 0644]
meta/packages/linux/linux-rp_2.6.22.bb

index 87cc5c081eb4c3924a53dd6b5d3778db2ef5c096..0df4c6a10bde004ad0460b3d13ca9a470673a0e1 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.22
-# Thu Jul 19 00:38:46 2007
+# Thu Aug 23 14:47:39 2007
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -160,6 +160,10 @@ CONFIG_ARCH_PXA=y
 # CONFIG_MACH_TRIZEPS4 is not set
 # CONFIG_MACH_HX2750 is not set
 CONFIG_MACH_HTCUNIVERSAL=y
+
+#
+# HTC Universal support
+#
 CONFIG_HTCUNIVERSAL_CORE=y
 CONFIG_HTCUNIVERSAL_UDC=y
 CONFIG_HTCUNIVERSAL_POWER=y
@@ -232,7 +236,7 @@ CONFIG_ALIGNMENT_TRAP=y
 #
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,115200n8 console=tty1 noinitrd root=/dev/mtdblock2 rootfstype=jffs2   dyntick=enable quiet"
+CONFIG_CMDLINE="console=ttyS0,115200n8 console=tty1 noinitrd root=/dev/mtdblock2 rootfstype=jffs2   dyntick=enable debug"
 # CONFIG_XIP_KERNEL is not set
 CONFIG_KEXEC=y
 
@@ -762,6 +766,12 @@ CONFIG_W1_MASTER_DS1WM=y
 # CONFIG_W1_SLAVE_THERM is not set
 # CONFIG_W1_SLAVE_SMEM is not set
 # CONFIG_W1_SLAVE_DS2433 is not set
+CONFIG_W1_SLAVE_DS2760=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+CONFIG_PDA_POWER=y
+CONFIG_APM_POWER=y
+CONFIG_BATTERY_DS2760=y
 # CONFIG_HWMON is not set
 
 #
@@ -773,6 +783,7 @@ CONFIG_W1_MASTER_DS1WM=y
 #
 # CONFIG_MFD_SM501 is not set
 CONFIG_HTC_ASIC3=y
+CONFIG_HTC_ASIC3_DS1WM=y
 
 #
 # Multi-Function Devices
@@ -880,13 +891,13 @@ CONFIG_SOUND=y
 #
 # Advanced Linux Sound Architecture
 #
-CONFIG_SND=m
-CONFIG_SND_TIMER=m
-CONFIG_SND_PCM=m
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
 # CONFIG_SND_SEQUENCER is not set
 CONFIG_SND_OSSEMUL=y
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
 CONFIG_SND_PCM_OSS_PLUGINS=y
 # CONFIG_SND_DYNAMIC_MINORS is not set
 CONFIG_SND_SUPPORT_OLD_API=y
@@ -1089,6 +1100,7 @@ CONFIG_RAMFS=y
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
index 6958129ca1f58d66a8519062ff9041bb5887976c..a83c7afa3430ea26f78c1bdedbad5b4dbcee5704 100644 (file)
@@ -1,10 +1,10 @@
 ---
- arch/arm/mach-pxa/Kconfig                                |    2 
+ arch/arm/mach-pxa/Kconfig                                |   89 +
  arch/arm/mach-pxa/Makefile                               |    1 
  arch/arm/mach-pxa/corgi.c                                |    3 
- arch/arm/mach-pxa/htcuniversal/Kconfig                   |   80 
+ arch/arm/mach-pxa/generic.c                              |   12 
  arch/arm/mach-pxa/htcuniversal/Makefile                  |   19 
- arch/arm/mach-pxa/htcuniversal/htcuniversal.c            |  470 +++++
+ arch/arm/mach-pxa/htcuniversal/htcuniversal.c            |  468 +++++
  arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.c     |  917 +++++++++++
  arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.h     |   65 
  arch/arm/mach-pxa/htcuniversal/htcuniversal_asic3_leds.c |  143 +
  drivers/leds/Kconfig                                     |    7 
  drivers/leds/Makefile                                    |    1 
  drivers/leds/leds-asic3.c                                |  189 ++
- drivers/mfd/Kconfig                                      |    3 
+ drivers/mfd/Kconfig                                      |   10 
  drivers/mfd/Makefile                                     |    2 
  drivers/mfd/asic3_base.c                                 | 1208 +++++++++++++++
  drivers/mfd/soc-core.c                                   |  106 +
  drivers/mfd/soc-core.h                                   |   30 
- drivers/mmc/host/Kconfig                                 |    8 
+ drivers/mmc/host/Kconfig                                 |    6 
  drivers/mmc/host/Makefile                                |    2 
  drivers/mmc/host/asic3_mmc.c                             |  900 +++++++++++
  drivers/mmc/host/asic3_mmc.h                             |   25 
+ drivers/serial/pxa.c                                     |   22 
  drivers/video/backlight/Kconfig                          |    2 
  drivers/video/backlight/corgi_bl.c                       |    4 
+ drivers/w1/slaves/Kconfig                                |   11 
+ drivers/w1/slaves/Makefile                               |    2 
+ drivers/w1/slaves/w1_ds2760.c                            |  213 ++
+ drivers/w1/slaves/w1_ds2760.h                            |   50 
+ drivers/w1/w1_family.h                                   |    1 
  include/asm-arm/arch-pxa/clock.h                         |   27 
  include/asm-arm/arch-pxa/htcuniversal-asic.h             |  213 ++
  include/asm-arm/arch-pxa/htcuniversal-gpio.h             |  220 ++
@@ -48,6 +54,7 @@
  include/asm-arm/arch-pxa/irqs.h                          |    2 
  include/asm-arm/arch-pxa/pxa-pm_ll.h                     |    6 
  include/asm-arm/arch-pxa/pxa-regs.h                      |    2 
+ include/asm-arm/arch-pxa/serial.h                        |   78 
  include/asm-arm/arch-pxa/sharpsl.h                       |    6 
  include/asm-arm/hardware/asic3_keys.h                    |   18 
  include/asm-arm/hardware/asic3_leds.h                    |   34 
  include/linux/pda_power.h                                |   31 
  include/linux/soc/asic3_base.h                           |  104 +
  include/linux/soc/tmio_mmc.h                             |   17 
- 60 files changed, 7410 insertions(+), 16 deletions(-)
+ 67 files changed, 7808 insertions(+), 17 deletions(-)
 
-Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/Kconfig
-===================================================================
---- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/Kconfig        2007-07-27 16:10:40.000000000 +0100
-@@ -0,0 +1,80 @@
-+menuconfig MACH_HTCUNIVERSAL
-+      bool "HTC Universal"
-+      select PXA27x
-+      select BOARD_IRQ_MAP_BIG
-+      help
-+              Say Y here if you intend to run this kernel on a
-+              HTC Universal. Currently there is only basic support
-+              for this PDA.
-+
-+config HTCUNIVERSAL_CORE
-+        tristate "HTC Universal core"
-+        depends on MACH_HTCUNIVERSAL
-+        help
-+          This selection enables HTC Universal core support.
-+
-+config HTCUNIVERSAL_UDC
-+        bool "USB Device Controller support"
-+        depends on MACH_HTCUNIVERSAL && HTC_ASIC3 && USB_PXA27X
-+        help
-+          Enables HTC Universal specific USB detection
-+
-+config HTCUNIVERSAL_POWER
-+        tristate "HTC Universal power"
-+        depends on MACH_HTCUNIVERSAL && HTC_ASIC3
-+        help
-+          This selection enables HTC Universal power monitoring
-+                  hardware support (through ASIC3).
-+
-+config HTCUNIVERSAL_BACKLIGHT
-+      bool "HTC Universal Backlight"
-+      depends on MACH_HTCUNIVERSAL && HTC_ASIC3 && BACKLIGHT_CLASS_DEVICE
-+      help
-+        This driver provides support for changing power and brightness
-+        on HTC Universal LCD backlight.
-+
-+config HTCUNIVERSAL_LCD
-+      tristate "HTC Universal LCD"
-+      depends on MACH_HTCUNIVERSAL && HTC_ASIC3 && LCD_CLASS_DEVICE
-+      help
-+        This driver provides support for changing power and brightness
-+        on HTC Universal LCD display.
-+
-+config HTCUNIVERSAL_TS2
-+      tristate "HTC Universal Touchscreen (old)"
-+      depends on MACH_HTCUNIVERSAL && HTC_ASIC3
-+      help
-+        Enable support for the HTC Universal Touchscreen Panel.
-+
-+config HTCUNIVERSAL_BUTTONS
-+        tristate "HTC Universal buttons support"
-+        depends on MACH_HTCUNIVERSAL && HTC_ASIC3
-+
-+config HTCUNIVERSAL_BLUETOOTH
-+      tristate "HTC Universal Bluetooth"
-+      depends on MACH_HTCUNIVERSAL && HTCUNIVERSAL_CORE && HTC_ASIC3
-+      help
-+        Enables support for the TI BRF6150 Bluetooth Module
-+        in the HTC Universal.
-+
-+config HTCUNIVERSAL_ASIC3_LEDS
-+      tristate "HTC Universal ASIC3 LED support"
-+      select LEDS_ASIC3
-+      depends on MACH_HTCUNIVERSAL && HTCUNIVERSAL_CORE && HTC_ASIC3
-+      ---help---
-+      Support for right (colors red+green+(amber)) and left (green+blue) led
-+      Off/on hook keys LED backlight
-+      Keyboard backlight
-+      Vibra
-+      Flashlight
-+
-+config HTCUNIVERSAL_PHONE
-+      tristate "HTC Universal Phone"
-+      depends on MACH_HTCUNIVERSAL && HTCUNIVERSAL_CORE && HTC_ASIC3
-+      help
-+        Enables support for the Qualcomm MSM6520 Phone Module
-+        in the HTC Universal.
-+
-+config HTCUNIVERSAL_AK4641
-+      depends on SND && I2C
-+      tristate
 Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/Makefile
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/Makefile       2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/Makefile       2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,19 @@
 +#
 +# Makefile for HTC Universal
@@ -164,8 +86,8 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/Makefile
 +obj-$(CONFIG_HTCUNIVERSAL_BACKLIGHT)  += htcuniversal_bl.o
 +obj-$(CONFIG_HTCUNIVERSAL_TS2)                += htcuniversal_ts2.o
 +obj-$(CONFIG_HTCUNIVERSAL_BUTTONS)    += htcuniversal_buttons.o
-+#obj-$(CONFIG_HTCUNIVERSAL_BLUETOOTH) += htcuniversal_bt.o
-+#obj-$(CONFIG_HTCUNIVERSAL_PHONE)     += htcuniversal_phone.o
++obj-$(CONFIG_HTCUNIVERSAL_BLUETOOTH)  += htcuniversal_bt.o
++obj-$(CONFIG_HTCUNIVERSAL_PHONE)      += htcuniversal_phone.o
 +obj-$(CONFIG_HTCUNIVERSAL_ASIC3_LEDS) += htcuniversal_asic3_leds.o
 +obj-$(CONFIG_HTCUNIVERSAL_UDC)                += htcuniversal_udc.o
 +
@@ -173,8 +95,8 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/Makefile
 Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal.c 2007-07-27 16:10:40.000000000 +0100
-@@ -0,0 +1,470 @@
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal.c 2007-08-23 13:09:22.000000000 +0200
+@@ -0,0 +1,468 @@
 +/*
 + * Hardware definitions for HTC Universal
 + *
@@ -203,7 +125,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal.c
 +
 +#include <asm/arch/bitfield.h>
 +#include <asm/arch/pxa-regs.h>
-+//#include <asm/arch/serial.h>
++#include <asm/arch/serial.h>
 +#include <asm/arch/pxa27x_keyboard.h>
 +#include <asm/arch/pxafb.h>
 +#include <asm/arch/irda.h>
@@ -591,13 +513,12 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal.c
 +      pxa_init_irq();
 +}
 +
-+//FIXME
-+//static struct platform_pxa_serial_funcs htcuniversal_pxa_bt_funcs = {
-+//    .configure = htcuniversal_bt_configure,
-+//};
-+//static struct platform_pxa_serial_funcs htcuniversal_pxa_phone_funcs = {
-+//    .configure = htcuniversal_phone_configure,
-+//};
++static struct platform_pxa_serial_funcs htcuniversal_pxa_bt_funcs = {
++      .configure = htcuniversal_bt_configure,
++};
++static struct platform_pxa_serial_funcs htcuniversal_pxa_phone_funcs = {
++      .configure = htcuniversal_phone_configure,
++};
 +
 +/* USB OHCI */
 +
@@ -620,9 +541,8 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal.c
 +{
 +      pxa_map_io();
 +
-+// FIXME
-+//    pxa_set_btuart_info(&htcuniversal_pxa_bt_funcs);
-+//    pxa_set_ffuart_info(&htcuniversal_pxa_phone_funcs);
++      pxa_set_btuart_info(&htcuniversal_pxa_bt_funcs);
++      pxa_set_ffuart_info(&htcuniversal_pxa_phone_funcs);
 +}
 +
 +static void __init htcuniversal_init(void)
@@ -648,7 +568,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal.c
 Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.c  2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.c  2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,917 @@
 +/*
 + * Audio support for codec Asahi Kasei AK4641
@@ -1570,7 +1490,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.c
 Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.h  2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.h  2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,65 @@
 +/*
 + * Audio support for codec Asahi Kasei AK4641
@@ -1640,7 +1560,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ak4641.h
 Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_asic3_leds.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_asic3_leds.c      2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_asic3_leds.c      2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,143 @@
 +/*
 + * LEDs support for the HP iPaq hx4700
@@ -1788,7 +1708,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_asic3_leds.c
 Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bl.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bl.c      2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bl.c      2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,61 @@
 +/*
 + * Use consistent with the GNU GPL is permitted,
@@ -1854,7 +1774,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bl.c
 Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.c      2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.c      2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,135 @@
 +/* Bluetooth interface driver for TI BRF6150 on HX4700
 + *
@@ -1870,7 +1790,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.c
 +#include <linux/soc/asic3_base.h>
 +
 +#include <asm/hardware.h>
-+//#include <asm/arch/serial.h>
++#include <asm/arch/serial.h>
 +#include <asm/hardware/ipaq-asic3.h>
 +#include <asm/arch/htcuniversal-gpio.h>
 +#include <asm/arch/htcuniversal-asic.h>
@@ -1994,7 +1914,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.c
 Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.h      2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.h      2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,17 @@
 +/*
 + * Bluetooth support file for calling bluetooth configuration functions
@@ -2016,7 +1936,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_bt.h
 Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_buttons.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_buttons.c 2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_buttons.c 2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,87 @@
 +/*
 + * Buttons driver for HTC Universal
@@ -2108,7 +2028,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_buttons.c
 Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_core.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_core.c    2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_core.c    2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,226 @@
 +/* Core Hardware driver for Hx4700 (Serial, ASIC3, EGPIOs)
 + *
@@ -2339,7 +2259,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_core.c
 Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_lcd.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_lcd.c     2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_lcd.c     2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,212 @@
 +/*
 + * Use consistent with the GNU GPL is permitted,
@@ -2556,7 +2476,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_lcd.c
 Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.c   2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.c   2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,167 @@
 +
 +/* Phone interface driver for Qualcomm MSM6250 on HTC Universal
@@ -2728,7 +2648,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.c
 Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.h   2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.h   2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,16 @@
 +/*
 + * Bluetooth support file for calling bluetooth configuration functions
@@ -2749,7 +2669,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_phone.h
 Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_pm.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_pm.c      2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_pm.c      2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,69 @@
 +/*
 + * MyPal 716 power management support for the original HTC IPL in DoC G3
@@ -2823,7 +2743,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_pm.c
 Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_power2.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_power2.c  2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_power2.c  2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,97 @@
 +/*
 + * pda_power driver for HTC Universal
@@ -2925,7 +2845,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_power2.c
 Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ts2.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ts2.c     2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ts2.c     2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,490 @@
 +/* Touch screen driver for the TI something-or-other
 + *
@@ -3420,7 +3340,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_ts2.c
 Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_udc.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_udc.c     2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_udc.c     2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,71 @@
 +
 +/*
@@ -3496,7 +3416,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/htcuniversal_udc.c
 Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/tsc2046_ts.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/tsc2046_ts.h   2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/arch/arm/mach-pxa/htcuniversal/tsc2046_ts.h   2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,20 @@
 +/*
 + * temporary TSC2046 touchscreen hack
@@ -3520,22 +3440,120 @@ Index: linux-2.6.22/arch/arm/mach-pxa/htcuniversal/tsc2046_ts.h
 +#endif
 Index: linux-2.6.22/arch/arm/mach-pxa/Kconfig
 ===================================================================
---- linux-2.6.22.orig/arch/arm/mach-pxa/Kconfig        2007-07-27 16:10:20.000000000 +0100
-+++ linux-2.6.22/arch/arm/mach-pxa/Kconfig     2007-07-27 16:10:40.000000000 +0100
-@@ -46,6 +46,8 @@ config MACH_HX2750
+--- linux-2.6.22.orig/arch/arm/mach-pxa/Kconfig        2007-08-23 13:09:21.000000000 +0200
++++ linux-2.6.22/arch/arm/mach-pxa/Kconfig     2007-08-23 13:09:22.000000000 +0200
+@@ -46,6 +46,14 @@
        help
          This enables support for the HP iPAQ HX2750 handheld.
  
-+source "arch/arm/mach-pxa/htcuniversal/Kconfig"
++config MACH_HTCUNIVERSAL
++      bool "HTC Universal"
++      select PXA27x
++      help
++        Say Y here if you intend to run this kernel on a
++        HTC Universal. Currently there is only basic support
++        for this PDA.
 +
  endchoice
  
  if PXA_SHARPSL
+@@ -80,6 +88,86 @@
+ endif
++if MACH_HTCUNIVERSAL
++
++menu "HTC Universal support"
++
++config HTCUNIVERSAL_CORE
++        tristate "HTC Universal core"
++        depends on MACH_HTCUNIVERSAL
++        help
++          This selection enables HTC Universal core support.
++
++config HTCUNIVERSAL_UDC
++        bool "USB Device Controller support"
++        depends on MACH_HTCUNIVERSAL && HTC_ASIC3 && USB_PXA27X
++        help
++          Enables HTC Universal specific USB detection
++
++config HTCUNIVERSAL_POWER
++        tristate "HTC Universal power"
++        depends on MACH_HTCUNIVERSAL && HTC_ASIC3
++        help
++          This selection enables HTC Universal power monitoring
++                  hardware support (through ASIC3).
++
++config HTCUNIVERSAL_BACKLIGHT
++      bool "HTC Universal Backlight"
++      depends on MACH_HTCUNIVERSAL && HTC_ASIC3 && BACKLIGHT_CLASS_DEVICE
++      help
++        This driver provides support for changing power and brightness
++        on HTC Universal LCD backlight.
++
++config HTCUNIVERSAL_LCD
++      tristate "HTC Universal LCD"
++      depends on MACH_HTCUNIVERSAL && HTC_ASIC3 && LCD_CLASS_DEVICE
++      help
++        This driver provides support for changing power and brightness
++        on HTC Universal LCD display.
++
++config HTCUNIVERSAL_TS2
++      tristate "HTC Universal Touchscreen (old)"
++      depends on MACH_HTCUNIVERSAL && HTC_ASIC3
++      help
++        Enable support for the HTC Universal Touchscreen Panel.
++
++config HTCUNIVERSAL_BUTTONS
++        tristate "HTC Universal buttons support"
++        depends on MACH_HTCUNIVERSAL && HTC_ASIC3
++
++config HTCUNIVERSAL_BLUETOOTH
++      tristate "HTC Universal Bluetooth"
++      depends on MACH_HTCUNIVERSAL && HTCUNIVERSAL_CORE && HTC_ASIC3
++      help
++        Enables support for the TI BRF6150 Bluetooth Module
++        in the HTC Universal.
++
++config HTCUNIVERSAL_ASIC3_LEDS
++      tristate "HTC Universal ASIC3 LED support"
++      select LEDS_ASIC3
++      depends on MACH_HTCUNIVERSAL && HTCUNIVERSAL_CORE && HTC_ASIC3
++      ---help---
++      Support for right (colors red+green+(amber)) and left (green+blue) led
++      Off/on hook keys LED backlight
++      Keyboard backlight
++      Vibra
++      Flashlight
++
++config HTCUNIVERSAL_PHONE
++      tristate "HTC Universal Phone"
++      depends on MACH_HTCUNIVERSAL && HTCUNIVERSAL_CORE && HTC_ASIC3
++      help
++        Enables support for the Qualcomm MSM6520 Phone Module
++        in the HTC Universal.
++
++config HTCUNIVERSAL_AK4641
++      depends on SND && I2C
++      tristate "AK4641 chipset support"
++
++endmenu
++
++endif
++
+ endmenu
+ config MACH_POODLE
+@@ -160,4 +248,3 @@
+       depends on (PXA25x || PXA27x) && INPUT
+ endif
+-
 Index: linux-2.6.22/arch/arm/mach-pxa/Makefile
 ===================================================================
---- linux-2.6.22.orig/arch/arm/mach-pxa/Makefile       2007-07-27 16:10:20.000000000 +0100
-+++ linux-2.6.22/arch/arm/mach-pxa/Makefile    2007-07-27 16:10:40.000000000 +0100
-@@ -19,6 +19,7 @@ obj-$(CONFIG_MACH_AKITA)     += akita-ioexp.
+--- linux-2.6.22.orig/arch/arm/mach-pxa/Makefile       2007-08-23 13:09:21.000000000 +0200
++++ linux-2.6.22/arch/arm/mach-pxa/Makefile    2007-08-23 13:09:22.000000000 +0200
+@@ -19,6 +19,7 @@
  obj-$(CONFIG_MACH_POODLE)     += poodle.o corgi_ssp.o sharpsl_pm.o poodle_pm.o
  obj-$(CONFIG_MACH_TOSA)         += tosa.o
  obj-$(CONFIG_MACH_HX2750)     += hx2750.o hx2750_test.o
@@ -3545,8 +3563,8 @@ Index: linux-2.6.22/arch/arm/mach-pxa/Makefile
  led-y := leds.o
 Index: linux-2.6.22/arch/arm/mach-pxa/pm.c
 ===================================================================
---- linux-2.6.22.orig/arch/arm/mach-pxa/pm.c   2007-07-27 16:10:08.000000000 +0100
-+++ linux-2.6.22/arch/arm/mach-pxa/pm.c        2007-07-27 16:10:40.000000000 +0100
+--- linux-2.6.22.orig/arch/arm/mach-pxa/pm.c   2007-08-23 13:09:20.000000000 +0200
++++ linux-2.6.22/arch/arm/mach-pxa/pm.c        2007-08-23 13:09:22.000000000 +0200
 @@ -22,6 +22,7 @@
  #include <asm/system.h>
  #include <asm/arch/pm.h>
@@ -3555,7 +3573,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/pm.c
  #include <asm/arch/lubbock.h>
  #include <asm/mach/time.h>
  
-@@ -75,12 +76,16 @@ enum {     SLEEP_SAVE_START = 0,
+@@ -75,12 +76,16 @@
  };
  
  
@@ -3572,7 +3590,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/pm.c
  
  #ifdef CONFIG_IWMMXT
        /* force any iWMMXt context to ram **/
-@@ -88,6 +93,11 @@ int pxa_pm_enter(suspend_state_t state)
+@@ -88,6 +93,11 @@
                iwmmxt_task_disable(NULL);
  #endif
  
@@ -3584,7 +3602,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/pm.c
        SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2);
        SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
        SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
-@@ -123,6 +133,15 @@ int pxa_pm_enter(suspend_state_t state)
+@@ -123,6 +133,15 @@
        /* Clear sleep reset status */
        RCSR = RCSR_SMR;
  
@@ -3600,7 +3618,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/pm.c
        /* before sleeping, calculate and save a checksum */
        for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
                checksum += sleep_save[i];
-@@ -138,6 +157,9 @@ int pxa_pm_enter(suspend_state_t state)
+@@ -138,6 +157,9 @@
        for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
                checksum += sleep_save[i];
  
@@ -3610,7 +3628,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/pm.c
        /* if invalid, display message and wait for a hardware reset */
        if (checksum != sleep_save[SLEEP_SAVE_CKSUM]) {
  #ifdef CONFIG_ARCH_LUBBOCK
-@@ -179,6 +201,10 @@ int pxa_pm_enter(suspend_state_t state)
+@@ -179,6 +201,10 @@
  
        RESTORE(PSTR);
  
@@ -3621,7 +3639,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/pm.c
  #ifdef DEBUG
        printk(KERN_DEBUG "*** made it back from resume\n");
  #endif
-@@ -188,6 +214,13 @@ int pxa_pm_enter(suspend_state_t state)
+@@ -188,6 +214,13 @@
  
  EXPORT_SYMBOL_GPL(pxa_pm_enter);
  
@@ -3635,7 +3653,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/pm.c
  unsigned long sleep_phys_sp(void *sp)
  {
        return virt_to_phys(sp);
-@@ -219,8 +252,9 @@ static struct pm_ops pxa_pm_ops = {
+@@ -219,8 +252,9 @@
        .prepare        = pxa_pm_prepare,
        .enter          = pxa_pm_enter,
        .finish         = pxa_pm_finish,
@@ -3648,9 +3666,9 @@ Index: linux-2.6.22/arch/arm/mach-pxa/pm.c
  
 Index: linux-2.6.22/drivers/input/keyboard/pxa27x_keyboard.c
 ===================================================================
---- linux-2.6.22.orig/drivers/input/keyboard/pxa27x_keyboard.c 2007-07-09 00:32:17.000000000 +0100
-+++ linux-2.6.22/drivers/input/keyboard/pxa27x_keyboard.c      2007-07-27 16:10:40.000000000 +0100
-@@ -140,7 +140,7 @@ static int pxakbd_resume(struct platform
+--- linux-2.6.22.orig/drivers/input/keyboard/pxa27x_keyboard.c 2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/drivers/input/keyboard/pxa27x_keyboard.c      2007-08-23 13:09:22.000000000 +0200
+@@ -140,7 +140,7 @@
                KPREC = pdata->reg_kprec;
  
                /* Enable unit clock */
@@ -3661,9 +3679,9 @@ Index: linux-2.6.22/drivers/input/keyboard/pxa27x_keyboard.c
        mutex_unlock(&input_dev->mutex);
 Index: linux-2.6.22/drivers/leds/Kconfig
 ===================================================================
---- linux-2.6.22.orig/drivers/leds/Kconfig     2007-07-09 00:32:17.000000000 +0100
-+++ linux-2.6.22/drivers/leds/Kconfig  2007-07-27 16:10:40.000000000 +0100
-@@ -95,6 +95,13 @@ config LEDS_COBALT
+--- linux-2.6.22.orig/drivers/leds/Kconfig     2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/drivers/leds/Kconfig  2007-08-23 13:09:22.000000000 +0200
+@@ -95,6 +95,13 @@
        help
          This option enables support for the front LED on Cobalt Server
  
@@ -3679,9 +3697,9 @@ Index: linux-2.6.22/drivers/leds/Kconfig
  config LEDS_TRIGGERS
 Index: linux-2.6.22/drivers/leds/Makefile
 ===================================================================
---- linux-2.6.22.orig/drivers/leds/Makefile    2007-07-09 00:32:17.000000000 +0100
-+++ linux-2.6.22/drivers/leds/Makefile 2007-07-27 16:10:40.000000000 +0100
-@@ -16,6 +16,7 @@ obj-$(CONFIG_LEDS_NET48XX)           += leds-net4
+--- linux-2.6.22.orig/drivers/leds/Makefile    2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/drivers/leds/Makefile 2007-08-23 13:09:22.000000000 +0200
+@@ -16,6 +16,7 @@
  obj-$(CONFIG_LEDS_WRAP)                       += leds-wrap.o
  obj-$(CONFIG_LEDS_H1940)              += leds-h1940.o
  obj-$(CONFIG_LEDS_COBALT)             += leds-cobalt.o
@@ -3692,7 +3710,7 @@ Index: linux-2.6.22/drivers/leds/Makefile
 Index: linux-2.6.22/drivers/leds/leds-asic3.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/drivers/leds/leds-asic3.c     2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/drivers/leds/leds-asic3.c     2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,189 @@
 +/*
 + * LEDs support for HTC ASIC3 devices.
@@ -3885,22 +3903,29 @@ Index: linux-2.6.22/drivers/leds/leds-asic3.c
 +MODULE_LICENSE("GPL");
 Index: linux-2.6.22/drivers/mfd/Kconfig
 ===================================================================
---- linux-2.6.22.orig/drivers/mfd/Kconfig      2007-07-27 16:10:05.000000000 +0100
-+++ linux-2.6.22/drivers/mfd/Kconfig   2007-07-27 16:10:40.000000000 +0100
-@@ -17,6 +17,9 @@ config MFD_SM501
- endmenu
+--- linux-2.6.22.orig/drivers/mfd/Kconfig      2007-08-23 13:09:19.000000000 +0200
++++ linux-2.6.22/drivers/mfd/Kconfig   2007-08-23 13:09:22.000000000 +0200
+@@ -15,6 +15,16 @@
+         interface. The device may be connected by PCI or local bus with
+         varying functions enabled.
  
 +config HTC_ASIC3
 +        tristate "HTC ASIC3 (iPAQ h1900/h3900/h4000/hx4700/rx3000) support"
 +
- menu "Multimedia Capabilities Port drivers"
-       depends on ARCH_SA1100
++config HTC_ASIC3_DS1WM
++       bool "Support HTC ASIC3 builtin DS1WM block"
++       help
++           Choose Y here if you want to include support for ASIC3's builtin
++           W1 controller. Some devices do not use it, and yet other have
++           separate DS1WM controller. For them, choose N.
++
+ endmenu
  
+ menu "Multimedia Capabilities Port drivers"
 Index: linux-2.6.22/drivers/mfd/Makefile
 ===================================================================
---- linux-2.6.22.orig/drivers/mfd/Makefile     2007-07-27 16:10:05.000000000 +0100
-+++ linux-2.6.22/drivers/mfd/Makefile  2007-07-27 16:10:40.000000000 +0100
+--- linux-2.6.22.orig/drivers/mfd/Makefile     2007-08-23 13:09:19.000000000 +0200
++++ linux-2.6.22/drivers/mfd/Makefile  2007-08-23 13:09:22.000000000 +0200
 @@ -2,6 +2,8 @@
  # Makefile for multifunction miscellaneous devices
  #
@@ -3913,7 +3938,7 @@ Index: linux-2.6.22/drivers/mfd/Makefile
 Index: linux-2.6.22/drivers/mfd/asic3_base.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/drivers/mfd/asic3_base.c      2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/drivers/mfd/asic3_base.c      2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,1208 @@
 +/*
 + * Driver interface to HTC "ASIC3"
@@ -5126,7 +5151,7 @@ Index: linux-2.6.22/drivers/mfd/asic3_base.c
 Index: linux-2.6.22/drivers/mfd/soc-core.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/drivers/mfd/soc-core.c        2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/drivers/mfd/soc-core.c        2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,106 @@
 +/*
 + * drivers/soc/soc-core.c
@@ -5237,7 +5262,7 @@ Index: linux-2.6.22/drivers/mfd/soc-core.c
 Index: linux-2.6.22/drivers/mfd/soc-core.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/drivers/mfd/soc-core.h        2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/drivers/mfd/soc-core.h        2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,30 @@
 +/*
 + * drivers/soc/soc-core.h
@@ -5272,7 +5297,7 @@ Index: linux-2.6.22/drivers/mfd/soc-core.h
 Index: linux-2.6.22/include/asm-arm/arch-pxa/clock.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/include/asm-arm/arch-pxa/clock.h      2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/include/asm-arm/arch-pxa/clock.h      2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,27 @@
 +/*
 + *  linux/include/asm-arm/arch-pxa/clock.h
@@ -5304,7 +5329,7 @@ Index: linux-2.6.22/include/asm-arm/arch-pxa/clock.h
 Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-asic.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-asic.h  2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-asic.h  2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,213 @@
 +/*
 + * include/asm/arm/arch-pxa/htcuniversal-asic.h
@@ -5522,7 +5547,7 @@ Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-asic.h
 Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-gpio.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-gpio.h  2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-gpio.h  2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,220 @@
 +/*
 + * include/asm-arm/arch-pxa/htcuniversal-gpio.h
@@ -5747,7 +5772,7 @@ Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-gpio.h
 Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-init.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-init.h  2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-init.h  2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,14 @@
 +/*
 + * include/asm/arm/arch-pxa/htcuniversal-init.h
@@ -5766,7 +5791,7 @@ Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal-init.h
 Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal.h       2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal.h       2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,3 @@
 +#include <asm/arch/irqs.h>
 +
@@ -5774,7 +5799,7 @@ Index: linux-2.6.22/include/asm-arm/arch-pxa/htcuniversal.h
 Index: linux-2.6.22/include/asm-arm/arch-pxa/pxa-pm_ll.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/include/asm-arm/arch-pxa/pxa-pm_ll.h  2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/include/asm-arm/arch-pxa/pxa-pm_ll.h  2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,6 @@
 +struct pxa_ll_pm_ops {
 +      void (*suspend)(unsigned long);
@@ -5784,9 +5809,9 @@ Index: linux-2.6.22/include/asm-arm/arch-pxa/pxa-pm_ll.h
 +extern struct pxa_ll_pm_ops *pxa_pm_set_ll_ops(struct pxa_ll_pm_ops *new_ops);
 Index: linux-2.6.22/include/asm-arm/arch-pxa/sharpsl.h
 ===================================================================
---- linux-2.6.22.orig/include/asm-arm/arch-pxa/sharpsl.h       2007-07-09 00:32:17.000000000 +0100
-+++ linux-2.6.22/include/asm-arm/arch-pxa/sharpsl.h    2007-07-27 16:10:40.000000000 +0100
-@@ -25,12 +25,6 @@ struct corgits_machinfo {
+--- linux-2.6.22.orig/include/asm-arm/arch-pxa/sharpsl.h       2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/include/asm-arm/arch-pxa/sharpsl.h    2007-08-23 13:09:22.000000000 +0200
+@@ -25,12 +25,6 @@
  /*
   * SharpSL Backlight
   */
@@ -5802,7 +5827,7 @@ Index: linux-2.6.22/include/asm-arm/arch-pxa/sharpsl.h
 Index: linux-2.6.22/include/asm-arm/hardware/asic3_keys.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/include/asm-arm/hardware/asic3_keys.h 2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/include/asm-arm/hardware/asic3_keys.h 2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,18 @@
 +#include <linux/input.h>
 +
@@ -5825,7 +5850,7 @@ Index: linux-2.6.22/include/asm-arm/hardware/asic3_keys.h
 Index: linux-2.6.22/include/asm-arm/hardware/asic3_leds.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/include/asm-arm/hardware/asic3_leds.h 2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/include/asm-arm/hardware/asic3_leds.h 2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,34 @@
 +/*
 + * LEDs support for HTC ASIC3 devices.
@@ -5864,7 +5889,7 @@ Index: linux-2.6.22/include/asm-arm/hardware/asic3_leds.h
 Index: linux-2.6.22/include/asm-arm/hardware/ipaq-asic3.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/include/asm-arm/hardware/ipaq-asic3.h 2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/include/asm-arm/hardware/ipaq-asic3.h 2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,602 @@
 +/*
 + *
@@ -6470,9 +6495,9 @@ Index: linux-2.6.22/include/asm-arm/hardware/ipaq-asic3.h
 +#endif
 Index: linux-2.6.22/include/linux/backlight.h
 ===================================================================
---- linux-2.6.22.orig/include/linux/backlight.h        2007-07-09 00:32:17.000000000 +0100
-+++ linux-2.6.22/include/linux/backlight.h     2007-07-27 16:10:40.000000000 +0100
-@@ -87,4 +87,11 @@ extern void backlight_device_unregister(
+--- linux-2.6.22.orig/include/linux/backlight.h        2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/include/linux/backlight.h     2007-08-23 13:09:22.000000000 +0200
+@@ -87,4 +87,11 @@
  
  #define to_backlight_device(obj) container_of(obj, struct backlight_device, class_dev)
  
@@ -6487,7 +6512,7 @@ Index: linux-2.6.22/include/linux/backlight.h
 Index: linux-2.6.22/include/linux/gpiodev.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/include/linux/gpiodev.h       2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/include/linux/gpiodev.h       2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,44 @@
 +#ifndef __GPIODEV_H
 +#define __GPIODEV_H
@@ -6536,7 +6561,7 @@ Index: linux-2.6.22/include/linux/gpiodev.h
 Index: linux-2.6.22/include/linux/input_pda.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/include/linux/input_pda.h     2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/include/linux/input_pda.h     2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,47 @@
 +#ifndef _INPUT_PDA_H
 +#define _INPUT_PDA_H
@@ -6588,7 +6613,7 @@ Index: linux-2.6.22/include/linux/input_pda.h
 Index: linux-2.6.22/include/linux/pda_power.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/include/linux/pda_power.h     2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/include/linux/pda_power.h     2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,31 @@
 +/*
 + * Common power driver for PDAs and phones with one or two external
@@ -6624,7 +6649,7 @@ Index: linux-2.6.22/include/linux/pda_power.h
 Index: linux-2.6.22/include/linux/soc/asic3_base.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/include/linux/soc/asic3_base.h        2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/include/linux/soc/asic3_base.h        2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,104 @@
 +#include <asm/types.h>
 +#include <linux/gpiodev.h>
@@ -6733,7 +6758,7 @@ Index: linux-2.6.22/include/linux/soc/asic3_base.h
 Index: linux-2.6.22/include/linux/soc/tmio_mmc.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/include/linux/soc/tmio_mmc.h  2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/include/linux/soc/tmio_mmc.h  2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,17 @@
 +#include <linux/platform_device.h>
 +
@@ -6754,8 +6779,8 @@ Index: linux-2.6.22/include/linux/soc/tmio_mmc.h
 +};
 Index: linux-2.6.22/include/asm-arm/arch-pxa/pxa-regs.h
 ===================================================================
---- linux-2.6.22.orig/include/asm-arm/arch-pxa/pxa-regs.h      2007-07-27 16:10:22.000000000 +0100
-+++ linux-2.6.22/include/asm-arm/arch-pxa/pxa-regs.h   2007-07-27 16:10:40.000000000 +0100
+--- linux-2.6.22.orig/include/asm-arm/arch-pxa/pxa-regs.h      2007-08-23 13:09:21.000000000 +0200
++++ linux-2.6.22/include/asm-arm/arch-pxa/pxa-regs.h   2007-08-23 13:09:22.000000000 +0200
 @@ -2063,6 +2063,8 @@
  #define LDCMD_SOFINT  (1 << 22)
  #define LDCMD_EOFINT  (1 << 21)
@@ -6767,14 +6792,12 @@ Index: linux-2.6.22/include/asm-arm/arch-pxa/pxa-regs.h
  #define LCCR5_SOFM2   (1<<1)          /* Start Of Frame Mask for Overlay 2 (channel 2) */
 Index: linux-2.6.22/drivers/mmc/host/Kconfig
 ===================================================================
---- linux-2.6.22.orig/drivers/mmc/host/Kconfig 2007-07-09 00:32:17.000000000 +0100
-+++ linux-2.6.22/drivers/mmc/host/Kconfig      2007-07-27 16:10:40.000000000 +0100
-@@ -99,4 +99,10 @@ config MMC_TIFM_SD
+--- linux-2.6.22.orig/drivers/mmc/host/Kconfig 2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/drivers/mmc/host/Kconfig      2007-08-23 13:09:22.000000000 +0200
+@@ -100,3 +100,9 @@
            To compile this driver as a module, choose M here: the
          module will be called tifm_sd.
--
-+ 
 +config MMC_ASIC3
 +      tristate "HTC ASIC3 SD/MMC support"
 +      depends on MMC && HTC_ASIC3
@@ -6783,9 +6806,9 @@ Index: linux-2.6.22/drivers/mmc/host/Kconfig
 +        in the iPAQ hx4700 and others.
 Index: linux-2.6.22/drivers/mmc/host/Makefile
 ===================================================================
---- linux-2.6.22.orig/drivers/mmc/host/Makefile        2007-07-09 00:32:17.000000000 +0100
-+++ linux-2.6.22/drivers/mmc/host/Makefile     2007-07-27 16:10:40.000000000 +0100
-@@ -15,4 +15,4 @@ obj-$(CONFIG_MMC_AU1X)               += au1xmmc.o
+--- linux-2.6.22.orig/drivers/mmc/host/Makefile        2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/drivers/mmc/host/Makefile     2007-08-23 13:09:22.000000000 +0200
+@@ -15,4 +15,4 @@
  obj-$(CONFIG_MMC_OMAP)                += omap.o
  obj-$(CONFIG_MMC_AT91)                += at91_mci.o
  obj-$(CONFIG_MMC_TIFM_SD)     += tifm_sd.o
@@ -6794,7 +6817,7 @@ Index: linux-2.6.22/drivers/mmc/host/Makefile
 Index: linux-2.6.22/drivers/mmc/host/asic3_mmc.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/drivers/mmc/host/asic3_mmc.c  2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/drivers/mmc/host/asic3_mmc.c  2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,900 @@
 +/* Note that this driver can likely be merged into the tmio driver, so
 + * consider this code temporary.  It works, though.
@@ -7699,7 +7722,7 @@ Index: linux-2.6.22/drivers/mmc/host/asic3_mmc.c
 Index: linux-2.6.22/drivers/mmc/host/asic3_mmc.h
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/drivers/mmc/host/asic3_mmc.h  2007-07-27 16:10:40.000000000 +0100
++++ linux-2.6.22/drivers/mmc/host/asic3_mmc.h  2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,25 @@
 +#ifndef __ASIC3_MMC_H
 +#define __ASIC3_MMC_H
@@ -7728,9 +7751,9 @@ Index: linux-2.6.22/drivers/mmc/host/asic3_mmc.h
 +#endif // __ASIC3_MMC_H
 Index: linux-2.6.22/drivers/input/keyboard/Makefile
 ===================================================================
---- linux-2.6.22.orig/drivers/input/keyboard/Makefile  2007-07-09 00:32:17.000000000 +0100
-+++ linux-2.6.22/drivers/input/keyboard/Makefile       2007-07-27 16:10:41.000000000 +0100
-@@ -21,4 +21,4 @@ obj-$(CONFIG_KEYBOARD_OMAP)          += omap-key
+--- linux-2.6.22.orig/drivers/input/keyboard/Makefile  2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/drivers/input/keyboard/Makefile       2007-08-23 13:09:22.000000000 +0200
+@@ -21,4 +21,4 @@
  obj-$(CONFIG_KEYBOARD_PXA27x)         += pxa27x_keyboard.o
  obj-$(CONFIG_KEYBOARD_AAED2000)               += aaed2000_kbd.o
  obj-$(CONFIG_KEYBOARD_GPIO)           += gpio_keys.o
@@ -7739,7 +7762,7 @@ Index: linux-2.6.22/drivers/input/keyboard/Makefile
 Index: linux-2.6.22/drivers/input/keyboard/asic3_keys.c
 ===================================================================
 --- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22/drivers/input/keyboard/asic3_keys.c   2007-07-27 16:10:41.000000000 +0100
++++ linux-2.6.22/drivers/input/keyboard/asic3_keys.c   2007-08-23 13:09:22.000000000 +0200
 @@ -0,0 +1,131 @@
 +/*
 + * Generic buttons driver for ASIC3 SoC.
@@ -7874,8 +7897,8 @@ Index: linux-2.6.22/drivers/input/keyboard/asic3_keys.c
 +MODULE_LICENSE("GPL");
 Index: linux-2.6.22/include/asm-arm/arch-pxa/irqs.h
 ===================================================================
---- linux-2.6.22.orig/include/asm-arm/arch-pxa/irqs.h  2007-07-09 00:32:17.000000000 +0100
-+++ linux-2.6.22/include/asm-arm/arch-pxa/irqs.h       2007-07-27 16:10:41.000000000 +0100
+--- linux-2.6.22.orig/include/asm-arm/arch-pxa/irqs.h  2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/include/asm-arm/arch-pxa/irqs.h       2007-08-23 13:09:22.000000000 +0200
 @@ -178,6 +178,8 @@
        defined(CONFIG_MACH_LOGICPD_PXA270) || \
        defined(CONFIG_MACH_MAINSTONE)
@@ -7887,9 +7910,9 @@ Index: linux-2.6.22/include/asm-arm/arch-pxa/irqs.h
  #endif
 Index: linux-2.6.22/include/linux/ioport.h
 ===================================================================
---- linux-2.6.22.orig/include/linux/ioport.h   2007-07-09 00:32:17.000000000 +0100
-+++ linux-2.6.22/include/linux/ioport.h        2007-07-27 16:10:41.000000000 +0100
-@@ -56,6 +56,7 @@ struct resource_list {
+--- linux-2.6.22.orig/include/linux/ioport.h   2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/include/linux/ioport.h        2007-08-23 13:09:22.000000000 +0200
+@@ -56,6 +56,7 @@
  #define IORESOURCE_IRQ_HIGHLEVEL      (1<<2)
  #define IORESOURCE_IRQ_LOWLEVEL               (1<<3)
  #define IORESOURCE_IRQ_SHAREABLE      (1<<4)
@@ -7899,9 +7922,9 @@ Index: linux-2.6.22/include/linux/ioport.h
  #define IORESOURCE_DMA_TYPE_MASK      (3<<0)
 Index: linux-2.6.22/drivers/video/backlight/Kconfig
 ===================================================================
---- linux-2.6.22.orig/drivers/video/backlight/Kconfig  2007-07-27 16:10:00.000000000 +0100
-+++ linux-2.6.22/drivers/video/backlight/Kconfig       2007-07-27 16:10:41.000000000 +0100
-@@ -34,7 +34,7 @@ config LCD_CLASS_DEVICE
+--- linux-2.6.22.orig/drivers/video/backlight/Kconfig  2007-08-23 13:09:19.000000000 +0200
++++ linux-2.6.22/drivers/video/backlight/Kconfig       2007-08-23 13:09:22.000000000 +0200
+@@ -34,7 +34,7 @@
  
  config BACKLIGHT_CORGI
        tristate "Sharp Corgi Backlight Driver (SL Series)"
@@ -7912,8 +7935,8 @@ Index: linux-2.6.22/drivers/video/backlight/Kconfig
          If you have a Sharp Zaurus SL-C7xx, SL-Cxx00 or SL-6000x say y to enable the
 Index: linux-2.6.22/drivers/video/backlight/corgi_bl.c
 ===================================================================
---- linux-2.6.22.orig/drivers/video/backlight/corgi_bl.c       2007-07-09 00:32:17.000000000 +0100
-+++ linux-2.6.22/drivers/video/backlight/corgi_bl.c    2007-07-27 16:10:41.000000000 +0100
+--- linux-2.6.22.orig/drivers/video/backlight/corgi_bl.c       2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/drivers/video/backlight/corgi_bl.c    2007-08-23 13:09:22.000000000 +0200
 @@ -24,7 +24,7 @@
  static int corgibl_intensity;
  static struct backlight_properties corgibl_data;
@@ -7923,7 +7946,7 @@ Index: linux-2.6.22/drivers/video/backlight/corgi_bl.c
  
  static unsigned long corgibl_flags;
  #define CORGIBL_SUSPENDED     0x01
-@@ -107,7 +107,7 @@ static struct backlight_ops corgibl_ops 
+@@ -107,7 +107,7 @@
  
  static int corgibl_probe(struct platform_device *pdev)
  {
@@ -7934,8 +7957,8 @@ Index: linux-2.6.22/drivers/video/backlight/corgi_bl.c
        if (!machinfo->limit_mask)
 Index: linux-2.6.22/arch/arm/mach-pxa/corgi.c
 ===================================================================
---- linux-2.6.22.orig/arch/arm/mach-pxa/corgi.c        2007-07-27 16:10:13.000000000 +0100
-+++ linux-2.6.22/arch/arm/mach-pxa/corgi.c     2007-07-27 16:13:54.000000000 +0100
+--- linux-2.6.22.orig/arch/arm/mach-pxa/corgi.c        2007-08-23 13:09:20.000000000 +0200
++++ linux-2.6.22/arch/arm/mach-pxa/corgi.c     2007-08-23 13:09:22.000000000 +0200
 @@ -20,6 +20,7 @@
  #include <linux/interrupt.h>
  #include <linux/mmc/host.h>
@@ -7944,7 +7967,7 @@ Index: linux-2.6.22/arch/arm/mach-pxa/corgi.c
  
  #include <asm/setup.h>
  #include <asm/memory.h>
-@@ -142,7 +143,7 @@ struct corgissp_machinfo corgi_ssp_machi
+@@ -142,7 +143,7 @@
  /*
   * Corgi Backlight Device
   */
@@ -7955,9 +7978,9 @@ Index: linux-2.6.22/arch/arm/mach-pxa/corgi.c
        .limit_mask = 0x0b,
 Index: linux-2.6.22/arch/arm/mach-pxa/spitz.c
 ===================================================================
---- linux-2.6.22.orig/arch/arm/mach-pxa/spitz.c        2007-07-27 16:10:17.000000000 +0100
-+++ linux-2.6.22/arch/arm/mach-pxa/spitz.c     2007-07-27 16:10:41.000000000 +0100
-@@ -221,7 +221,7 @@ struct corgissp_machinfo spitz_ssp_machi
+--- linux-2.6.22.orig/arch/arm/mach-pxa/spitz.c        2007-08-23 13:09:20.000000000 +0200
++++ linux-2.6.22/arch/arm/mach-pxa/spitz.c     2007-08-23 13:09:22.000000000 +0200
+@@ -221,7 +221,7 @@
  /*
   * Spitz Backlight Device
   */
@@ -7966,3 +7989,492 @@ Index: linux-2.6.22/arch/arm/mach-pxa/spitz.c
        .default_intensity = 0x1f,
        .limit_mask = 0x0b,
        .max_intensity = 0x2f,
+Index: linux-2.6.22/arch/arm/mach-pxa/generic.c
+===================================================================
+--- linux-2.6.22.orig/arch/arm/mach-pxa/generic.c      2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/arch/arm/mach-pxa/generic.c   2007-08-23 13:09:22.000000000 +0200
+@@ -345,6 +345,18 @@
+       .id             = 3,
+ };
++void __init pxa_set_ffuart_info(struct platform_pxa_serial_funcs *info)
++{
++      ffuart_device.dev.platform_data = info;
++}
++EXPORT_SYMBOL(pxa_set_ffuart_info);
++
++void __init pxa_set_btuart_info(struct platform_pxa_serial_funcs *info)
++{
++      btuart_device.dev.platform_data = info;
++}
++EXPORT_SYMBOL(pxa_set_btuart_info);
++
+ static struct resource i2c_resources[] = {
+       {
+               .start  = 0x40301680,
+Index: linux-2.6.22/drivers/w1/slaves/Kconfig
+===================================================================
+--- linux-2.6.22.orig/drivers/w1/slaves/Kconfig        2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/drivers/w1/slaves/Kconfig     2007-08-23 13:09:22.000000000 +0200
+@@ -35,4 +35,15 @@
+         Each block has 30 bytes of data and a two byte CRC16.
+         Full block writes are only allowed if the CRC is valid.
++config W1_SLAVE_DS2760
++       tristate "Dallas 2760 battery monitor chip (HP iPAQ & others)"
++       depends on W1
++       help
++         If you enable this you will have the DS2760 battery monitor
++         chip support.
++         The battery monitor chip is used in many batteries/devices
++         as the one who is responsible for charging/discharging/monitoring
++         Li+ batteries.
++         If you are unsure, say N.
++
+ endmenu
+Index: linux-2.6.22/drivers/w1/slaves/Makefile
+===================================================================
+--- linux-2.6.22.orig/drivers/w1/slaves/Makefile       2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/drivers/w1/slaves/Makefile    2007-08-23 13:09:22.000000000 +0200
+@@ -5,4 +5,4 @@
+ obj-$(CONFIG_W1_SLAVE_THERM)  += w1_therm.o
+ obj-$(CONFIG_W1_SLAVE_SMEM)   += w1_smem.o
+ obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o
+-
++obj-$(CONFIG_W1_SLAVE_DS2760)         += w1_ds2760.o
+Index: linux-2.6.22/drivers/w1/w1_family.h
+===================================================================
+--- linux-2.6.22.orig/drivers/w1/w1_family.h   2007-07-09 01:32:17.000000000 +0200
++++ linux-2.6.22/drivers/w1/w1_family.h        2007-08-23 13:09:22.000000000 +0200
+@@ -33,6 +33,7 @@
+ #define W1_THERM_DS1822       0x22
+ #define W1_EEPROM_DS2433      0x23
+ #define W1_THERM_DS18B20      0x28
++#define W1_FAMILY_DS2760        0x30
+ #define MAXNAMELEN            32
+Index: linux-2.6.22/include/asm-arm/arch-pxa/serial.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/asm-arm/arch-pxa/serial.h     2007-08-23 13:09:22.000000000 +0200
+@@ -0,0 +1,78 @@
++/*
++ *  linux/include/asm-arm/arch-pxa/serial.h
++ *
++ * Author:    Nicolas Pitre
++ * Copyright: (C) 2001 MontaVista Software Inc.
++ *
++ * 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 <asm/arch/pxa-regs.h>
++
++#define BAUD_BASE     921600
++
++/* Standard COM flags */
++#define STD_COM_FLAGS (ASYNC_SKIP_TEST)
++
++#define STD_SERIAL_PORT_DEFNS \
++      {       \
++              type:                   PORT_PXA,       \
++              xmit_fifo_size:         64,             \
++              baud_base:              BAUD_BASE,      \
++              iomem_base:             &FFUART,        \
++              iomem_reg_shift:        2,              \
++              io_type:                SERIAL_IO_MEM,  \
++              irq:                    IRQ_FFUART,     \
++              flags:                  STD_COM_FLAGS,  \
++      }, {    \
++              type:                   PORT_PXA,       \
++              xmit_fifo_size:         64,             \
++              baud_base:              BAUD_BASE,      \
++              iomem_base:             &STUART,        \
++              iomem_reg_shift:        2,              \
++              io_type:                SERIAL_IO_MEM,  \
++              irq:                    IRQ_STUART,     \
++              flags:                  STD_COM_FLAGS,  \
++      }, {    \
++              type:                   PORT_PXA,       \
++              xmit_fifo_size:         64,             \
++              baud_base:              BAUD_BASE,      \
++              iomem_base:             &BTUART,        \
++              iomem_reg_shift:        2,              \
++              io_type:                SERIAL_IO_MEM,  \
++              irq:                    IRQ_BTUART,     \
++              flags:                  STD_COM_FLAGS,  \
++      }
++
++#define EXTRA_SERIAL_PORT_DEFNS
++
++struct platform_pxa_serial_funcs {
++
++      /* Initialize whatever is connected to this serial port. */
++      void (*configure)(int state);
++#define PXA_UART_CFG_PRE_STARTUP   0
++#define PXA_UART_CFG_POST_STARTUP  1
++#define PXA_UART_CFG_PRE_SHUTDOWN  2
++#define PXA_UART_CFG_POST_SHUTDOWN 3
++
++      /* Enable or disable the individual transmitter/receiver submodules.
++       * On transceivers without echo cancellation (e.g. SIR)
++       * transmitter always has priority; e.g. if both bits are set,
++       * only the transmitter is enabled. */
++        void (*set_txrx)(int txrx);
++#define PXA_SERIAL_TX 1
++#define PXA_SERIAL_RX 2
++
++      /* Get the current state of tx/rx. */
++      int (*get_txrx)(void);
++
++      int (*suspend)(struct platform_device *dev, pm_message_t state);
++      int (*resume)(struct platform_device *dev);
++};
++
++void pxa_set_ffuart_info(struct platform_pxa_serial_funcs *ffuart_funcs);
++void pxa_set_btuart_info(struct platform_pxa_serial_funcs *btuart_funcs);
++void pxa_set_stuart_info(struct platform_pxa_serial_funcs *stuart_funcs);
++void pxa_set_hwuart_info(struct platform_pxa_serial_funcs *hwuart_funcs);
+Index: linux-2.6.22/drivers/w1/slaves/w1_ds2760.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/w1/slaves/w1_ds2760.c 2007-08-23 13:09:22.000000000 +0200
+@@ -0,0 +1,213 @@
++/*
++ * 1-Wire implementation for the ds2760 chip
++ *
++ * Copyright (c) 2004-2005, Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
++ *
++ * Use consistent with the GNU GPL is permitted,
++ * provided that this copyright notice is
++ * preserved in its entirety in all copies and derived works.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/types.h>
++#include <linux/platform_device.h>
++#include <linux/mutex.h>
++#include <linux/idr.h>
++
++#include "../w1.h"
++#include "../w1_int.h"
++#include "../w1_family.h"
++#include "w1_ds2760.h"
++
++static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count,
++                        int io)
++{
++      struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
++
++      if (!dev)
++              return 0;
++
++      mutex_lock(&sl->master->mutex);
++
++      if (addr > DS2760_DATA_SIZE || addr < 0) {
++              count = 0;
++              goto out;
++      }
++      if (addr + count > DS2760_DATA_SIZE)
++              count = DS2760_DATA_SIZE - addr;
++
++      if (!w1_reset_select_slave(sl)) {
++              if (!io) {
++                      w1_write_8(sl->master, W1_DS2760_READ_DATA);
++                      w1_write_8(sl->master, addr);
++                      count = w1_read_block(sl->master, buf, count);
++              } else {
++                      w1_write_8(sl->master, W1_DS2760_WRITE_DATA);
++                      w1_write_8(sl->master, addr);
++                      w1_write_block(sl->master, buf, count);
++                      /* XXX w1_write_block returns void, not n_written */
++              }
++      }
++
++out:
++      mutex_unlock(&sl->master->mutex);
++
++      return count;
++}
++
++int w1_ds2760_read(struct device *dev, char *buf, int addr, size_t count)
++{
++      return w1_ds2760_io(dev, buf, addr, count, 0);
++}
++
++int w1_ds2760_write(struct device *dev, char *buf, int addr, size_t count)
++{
++      return w1_ds2760_io(dev, buf, addr, count, 1);
++}
++
++static ssize_t w1_ds2760_read_bin(struct kobject *kobj, char *buf, loff_t off,
++                                  size_t count)
++{
++      struct device *dev = container_of(kobj, struct device, kobj);
++      return w1_ds2760_read(dev, buf, off, count);
++}
++
++static struct bin_attribute w1_ds2760_bin_attr = {
++      .attr = {
++              .name = "w1_slave",
++              .mode = S_IRUGO,
++              .owner = THIS_MODULE,
++      },
++      .size = DS2760_DATA_SIZE,
++      .read = w1_ds2760_read_bin,
++};
++
++static DEFINE_IDR(bat_idr);
++static DEFINE_MUTEX(bat_idr_lock);
++
++static int new_bat_id(void)
++{
++      int ret;
++
++      while (1) {
++              int id;
++
++              ret = idr_pre_get(&bat_idr, GFP_KERNEL);
++              if (ret == 0)
++                      return -ENOMEM;
++
++              mutex_lock(&bat_idr_lock);
++              ret = idr_get_new(&bat_idr, NULL, &id);
++              mutex_unlock(&bat_idr_lock);
++
++              if (ret == 0) {
++                      ret = id & MAX_ID_MASK;
++                      break;
++              }
++              else if (ret == -EAGAIN)
++                      continue;
++              else
++                      break;
++      }
++
++      return ret;
++}
++
++static void release_bat_id(int id)
++{
++      mutex_lock(&bat_idr_lock);
++      idr_remove(&bat_idr, id);
++      mutex_unlock(&bat_idr_lock);
++
++      return;
++}
++
++static int w1_ds2760_add_slave(struct w1_slave *sl)
++{
++      int ret;
++      int id;
++      struct platform_device *pdev;
++
++      id = new_bat_id();
++      if (id < 0) {
++              ret = id;
++              goto noid;
++      }
++
++      pdev = platform_device_alloc("ds2760-battery", id);
++      if (!pdev) {
++              ret = -ENOMEM;
++              goto pdev_alloc_failed;
++      }
++      pdev->dev.parent = &sl->dev;
++
++      ret = platform_device_add(pdev);
++      if (ret)
++              goto pdev_add_failed;
++
++      ret = sysfs_create_bin_file(&sl->dev.kobj, &w1_ds2760_bin_attr);
++      if (ret)
++              goto bin_attr_failed;
++
++      dev_set_drvdata(&sl->dev, pdev);
++
++      goto success;
++
++bin_attr_failed:
++pdev_add_failed:
++      platform_device_unregister(pdev);
++pdev_alloc_failed:
++      release_bat_id(id);
++noid:
++success:
++      return ret;
++}
++
++static void w1_ds2760_remove_slave(struct w1_slave *sl)
++{
++      struct platform_device *pdev = dev_get_drvdata(&sl->dev);
++      int id = pdev->id;
++
++      platform_device_unregister(pdev);
++      release_bat_id(id);
++      sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2760_bin_attr);
++
++      return;
++}
++
++static struct w1_family_ops w1_ds2760_fops = {
++      .add_slave    = w1_ds2760_add_slave,
++      .remove_slave = w1_ds2760_remove_slave,
++};
++
++static struct w1_family w1_ds2760_family = {
++      .fid = W1_FAMILY_DS2760,
++      .fops = &w1_ds2760_fops,
++};
++
++static int __init w1_ds2760_init(void)
++{
++      printk(KERN_INFO "1-Wire driver for the DS2760 battery monitor "
++             " chip  - (c) 2004-2005, Szabolcs Gyurko\n");
++      idr_init(&bat_idr);
++      return w1_register_family(&w1_ds2760_family);
++}
++
++static void __exit w1_ds2760_exit(void)
++{
++      w1_unregister_family(&w1_ds2760_family);
++      idr_destroy(&bat_idr);
++}
++
++EXPORT_SYMBOL(w1_ds2760_read);
++EXPORT_SYMBOL(w1_ds2760_write);
++
++module_init(w1_ds2760_init);
++module_exit(w1_ds2760_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>");
++MODULE_DESCRIPTION("1-wire Driver Dallas 2760 battery monitor chip");
+Index: linux-2.6.22/drivers/w1/slaves/w1_ds2760.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/w1/slaves/w1_ds2760.h 2007-08-23 13:09:22.000000000 +0200
+@@ -0,0 +1,50 @@
++/*
++ * 1-Wire implementation for the ds2760 chip
++ *
++ * Copyright (c) 2004-2005, Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
++ *
++ * Use consistent with the GNU GPL is permitted,
++ * provided that this copyright notice is
++ * preserved in its entirety in all copies and derived works.
++ *
++ */
++
++#ifndef __w1_ds2760_h__
++#define __w1_ds2760_h__
++
++/* Known commands to the DS2760 chip */
++#define W1_DS2760_SWAP                      0xAA
++#define W1_DS2760_READ_DATA                 0x69
++#define W1_DS2760_WRITE_DATA                0x6C
++#define W1_DS2760_COPY_DATA                 0x48
++#define W1_DS2760_RECALL_DATA               0xB8
++#define W1_DS2760_LOCK                      0x6A
++
++/* Number of valid register addresses */
++#define DS2760_DATA_SIZE          0x40
++
++#define DS2760_PROTECTION_REG     0x00
++#define DS2760_STATUS_REG         0x01
++#define DS2760_EEPROM_REG         0x07
++#define DS2760_SPECIAL_FEATURE_REG  0x08
++#define DS2760_VOLTAGE_MSB        0x0c
++#define DS2760_VOLTAGE_LSB        0x0d
++#define DS2760_CURRENT_MSB        0x0e
++#define DS2760_CURRENT_LSB        0x0f
++#define DS2760_CURRENT_ACCUM_MSB    0x10
++#define DS2760_CURRENT_ACCUM_LSB    0x11
++#define DS2760_TEMP_MSB                   0x18
++#define DS2760_TEMP_LSB                   0x19
++#define DS2760_EEPROM_BLOCK0      0x20
++#define DS2760_ACTIVE_FULL        0x20
++#define DS2760_EEPROM_BLOCK1      0x30
++#define DS2760_RATED_CAPACITY     0x32
++#define DS2760_CURRENT_OFFSET_BIAS  0x33
++#define DS2760_ACTIVE_EMPTY       0x3b
++
++extern int w1_ds2760_read(struct device *dev, char *buf, int addr,
++                          size_t count);
++extern int w1_ds2760_write(struct device *dev, char *buf, int addr,
++                           size_t count);
++
++#endif /* !__w1_ds2760_h__ */
+Index: linux-2.6.22/drivers/serial/pxa.c
+===================================================================
+--- linux-2.6.22.orig/drivers/serial/pxa.c     2007-08-23 13:21:54.000000000 +0200
++++ linux-2.6.22/drivers/serial/pxa.c  2007-08-23 13:22:54.000000000 +0200
+@@ -46,6 +46,7 @@
+ #include <asm/io.h>
+ #include <asm/hardware.h>
+ #include <asm/irq.h>
++#include <asm/arch/serial.h>
+ #include <asm/arch/pxa-regs.h>
+@@ -59,6 +60,14 @@
+       char                    *name;
+ };
++
++#define IS_METHOD(dev, method) (dev && (dev)->platform_data && ((struct platform_pxa_serial_funcs *)(dev)->platform_data)->method)
++#define METHOD_CALL(dev, method) \
++              ((struct platform_pxa_serial_funcs *)(dev)->platform_data)->method()
++#define SAFE_METHOD_CALL(dev, method, args...) \
++      if (IS_METHOD(dev, method)) \
++              ((struct platform_pxa_serial_funcs *)(dev)->platform_data)->method(args)
++
+ static inline unsigned int serial_in(struct uart_pxa_port *up, int offset)
+ {
+       offset <<= 2;
+@@ -346,6 +355,9 @@
+       unsigned long flags;
+       int retval;
++      /* Perform platform-specific port initialization, if needed. */
++      SAFE_METHOD_CALL(port->dev, configure, PXA_UART_CFG_PRE_STARTUP);
++
+       if (port->line == 3) /* HWUART */
+               up->mcr |= UART_MCR_AFE;
+       else
+@@ -401,6 +413,12 @@
+       (void) serial_in(up, UART_IIR);
+       (void) serial_in(up, UART_MSR);
++      /*
++       * Perform platform-specific port initialization if needed
++       */
++      SAFE_METHOD_CALL(port->dev, configure, PXA_UART_CFG_POST_STARTUP);
++      SAFE_METHOD_CALL(port->dev, set_txrx, PXA_SERIAL_RX);
++
+       return 0;
+ }
+@@ -409,6 +427,8 @@
+       struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+       unsigned long flags;
++      SAFE_METHOD_CALL(port->dev, configure, PXA_UART_CFG_PRE_SHUTDOWN);
++
+       free_irq(up->port.irq, up);
+       /*
+@@ -430,6 +450,8 @@
+                                 UART_FCR_CLEAR_RCVR |
+                                 UART_FCR_CLEAR_XMIT);
+       serial_out(up, UART_FCR, 0);
++
++      SAFE_METHOD_CALL(port->dev, configure, PXA_UART_CFG_POST_SHUTDOWN);
+ }
+ static void
diff --git a/meta/packages/linux/linux-rp-2.6.22/pda-power.patch b/meta/packages/linux/linux-rp-2.6.22/pda-power.patch
new file mode 100644 (file)
index 0000000..face2f4
--- /dev/null
@@ -0,0 +1,3373 @@
+---
+ arch/arm/Kconfig                   |    2 
+ drivers/Kconfig                    |    2 
+ drivers/Makefile                   |    1 
+ drivers/power/Kconfig              |   70 +++++
+ drivers/power/Makefile             |   28 ++
+ drivers/power/adc_battery.c        |  278 +++++++++++++++++++++
+ drivers/power/apm_power.c          |  247 +++++++++++++++++++
+ drivers/power/ds2760_battery.c     |  475 +++++++++++++++++++++++++++++++++++++
+ drivers/power/micro_battery.c      |  257 ++++++++++++++++++++
+ drivers/power/olpc_battery.c       |  302 +++++++++++++++++++++++
+ drivers/power/pda_power.c          |  263 ++++++++++++++++++++
+ drivers/power/pmu_battery.c        |  215 ++++++++++++++++
+ drivers/power/power_supply.h       |   42 +++
+ drivers/power/power_supply_core.c  |  168 +++++++++++++
+ drivers/power/power_supply_leds.c  |  188 ++++++++++++++
+ drivers/power/power_supply_sysfs.c |  289 ++++++++++++++++++++++
+ drivers/power/simpad-battery.c     |  242 ++++++++++++++++++
+ include/linux/power_supply.h       |  175 +++++++++++++
+ 18 files changed, 3244 insertions(+)
+
+Index: linux-2.6.22/drivers/power/adc_battery.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/power/adc_battery.c   2007-08-23 12:26:28.000000000 +0200
+@@ -0,0 +1,278 @@
++/*
++ * Copyright (c) 2007 Paul Sokolovsky
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ */
++
++//#define DEBUG
++
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/pm.h>
++#include <linux/delay.h>
++#include <linux/workqueue.h>
++#include <linux/platform_device.h>
++#include <linux/power_supply.h>
++#include <linux/adc.h>
++#include <linux/adc_battery.h>
++
++#include <asm/irq.h>
++
++#define PIN_NO_VOLT 0
++#define PIN_NO_CURR 1
++#define PIN_NO_TEMP 2
++
++struct battery_adc_priv {
++      struct power_supply batt_cdev;
++
++      struct battery_adc_platform_data *pdata;
++
++      struct adc_request req;
++      struct adc_sense pins[3];
++      struct adc_sense last_good_pins[3];
++
++      struct workqueue_struct *wq;
++      struct delayed_work work;
++};
++
++/*
++ *  Battery properties
++ */
++
++static int adc_battery_get_property(struct power_supply *psy,
++                                    enum power_supply_property psp,
++                                    union power_supply_propval *val)
++{
++      struct battery_adc_priv* drvdata = (struct battery_adc_priv*)psy;
++      int voltage;
++
++      switch (psp) {
++      case POWER_SUPPLY_PROP_STATUS:
++              val->intval = drvdata->pdata->charge_status;
++              break;
++      case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
++              val->intval = drvdata->pdata->battery_info.voltage_max_design;
++              break;
++      case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
++              val->intval = drvdata->pdata->battery_info.voltage_min_design;
++              break;
++      case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
++              val->intval = drvdata->pdata->battery_info.charge_full_design;
++              break;
++      case POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN:
++              val->intval = drvdata->pdata->battery_info.charge_empty_design;
++              break;
++      case POWER_SUPPLY_PROP_VOLTAGE_NOW:
++              val->intval = drvdata->last_good_pins[PIN_NO_VOLT].value * drvdata->pdata->voltage_mult;
++              break;
++      case POWER_SUPPLY_PROP_CURRENT_NOW:
++              val->intval = drvdata->last_good_pins[PIN_NO_CURR].value * drvdata->pdata->current_mult;
++              break;
++      case POWER_SUPPLY_PROP_CHARGE_NOW:
++              /* We do calculations in mX, not uX, because todo it in uX we should use "long long"s,
++               * which is a mess (need to use do_div) when you need divide operation). */
++              voltage = drvdata->last_good_pins[PIN_NO_VOLT].value * drvdata->pdata->voltage_mult;
++              val->intval = ((voltage/1000 - drvdata->pdata->battery_info.voltage_min_design/1000) *
++                   (drvdata->pdata->battery_info.charge_full_design/1000 -
++                    drvdata->pdata->battery_info.charge_empty_design/1000)) /
++                   (drvdata->pdata->battery_info.voltage_max_design/1000 -
++                    drvdata->pdata->battery_info.voltage_min_design/1000);
++              val->intval *= 1000; /* convert final result to uX */
++              break;
++      case POWER_SUPPLY_PROP_TEMP:
++              val->intval = drvdata->last_good_pins[PIN_NO_TEMP].value * drvdata->pdata->temperature_mult / 1000;
++              break;
++      default:
++              return -EINVAL;
++      };
++      return 0;
++}
++
++/*
++ *  Driver body
++ */
++
++static void adc_battery_query(struct battery_adc_priv *drvdata)
++{
++      struct battery_adc_platform_data *pdata = drvdata->pdata;
++      int powered, charging;
++
++      adc_request_sample(&drvdata->req);
++
++      powered = power_supply_am_i_supplied(&drvdata->batt_cdev);
++      charging = pdata->is_charging ? pdata->is_charging() : -1;
++
++      if (powered && charging)
++              pdata->charge_status = POWER_SUPPLY_STATUS_CHARGING;
++      else if (powered && !charging && charging != -1)
++              pdata->charge_status = POWER_SUPPLY_STATUS_FULL;
++      else
++              pdata->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
++
++      /* Throw away invalid samples, this may happen soon after resume for example. */
++      if (drvdata->pins[PIN_NO_VOLT].value > 0) {
++              memcpy(drvdata->last_good_pins, drvdata->pins, sizeof(drvdata->pins));
++#ifdef DEBUG
++              printk("%d %d %d\n", drvdata->pins[PIN_NO_VOLT].value,
++                                   drvdata->pins[PIN_NO_CURR].value,
++                                   drvdata->pins[PIN_NO_TEMP].value);
++#endif
++      }
++}
++
++static void adc_battery_charge_power_changed(struct power_supply *bat)
++{
++      struct battery_adc_priv *drvdata = (struct battery_adc_priv*)bat;
++      cancel_delayed_work(&drvdata->work);
++      queue_delayed_work(drvdata->wq, &drvdata->work, 0);
++}
++
++static void adc_battery_work_func(struct work_struct *work)
++{
++      struct delayed_work *delayed_work = container_of(work, struct delayed_work, work);
++      struct battery_adc_priv *drvdata = container_of(delayed_work, struct battery_adc_priv, work);
++
++      adc_battery_query(drvdata);
++      power_supply_changed(&drvdata->batt_cdev);
++
++      queue_delayed_work(drvdata->wq, &drvdata->work, (5000 * HZ) / 1000);
++}
++
++static int adc_battery_probe(struct platform_device *pdev)
++{
++        int retval;
++      struct battery_adc_platform_data *pdata = pdev->dev.platform_data;
++      struct battery_adc_priv *drvdata;
++      int i, j;
++      enum power_supply_property props[] = {
++              POWER_SUPPLY_PROP_STATUS,
++              POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
++              POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
++              POWER_SUPPLY_PROP_VOLTAGE_NOW,
++              POWER_SUPPLY_PROP_CURRENT_NOW,
++              POWER_SUPPLY_PROP_CHARGE_NOW,
++              POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
++              POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN,
++              POWER_SUPPLY_PROP_TEMP,
++      };
++
++      // Initialize ts data structure.
++      drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
++      if (!drvdata)
++              return -ENOMEM;
++
++      drvdata->batt_cdev.name           = pdata->battery_info.name;
++      drvdata->batt_cdev.use_for_apm    = pdata->battery_info.use_for_apm;
++      drvdata->batt_cdev.num_properties = ARRAY_SIZE(props);
++      drvdata->batt_cdev.get_property   = adc_battery_get_property;
++      drvdata->batt_cdev.external_power_changed =
++                                adc_battery_charge_power_changed;
++
++      if (!pdata->voltage_pin) {
++              drvdata->batt_cdev.num_properties--;
++              props[3] = -1;
++      }
++      if (!pdata->current_pin) {
++              drvdata->batt_cdev.num_properties--;
++              props[4] = -1;
++      }
++      if (!pdata->temperature_pin) {
++              drvdata->batt_cdev.num_properties--;
++              props[8] = -1;
++      }
++
++      drvdata->batt_cdev.properties = kmalloc(
++                      sizeof(*drvdata->batt_cdev.properties) *
++                      drvdata->batt_cdev.num_properties, GFP_KERNEL);
++      if (!drvdata->batt_cdev.properties)
++              return -ENOMEM;
++
++      j = 0;
++      for (i = 0; i < ARRAY_SIZE(props); i++) {
++              if (props[i] == -1)
++                      continue;
++              drvdata->batt_cdev.properties[j++] = props[i];
++      }
++
++      retval = power_supply_register(&pdev->dev, &drvdata->batt_cdev);
++      if (retval) {
++              printk("adc-battery: Error registering battery classdev");
++              return retval;
++      }
++
++      drvdata->req.senses = drvdata->pins;
++      drvdata->req.num_senses = ARRAY_SIZE(drvdata->pins);
++      drvdata->pins[PIN_NO_VOLT].name = pdata->voltage_pin;
++      drvdata->pins[PIN_NO_CURR].name = pdata->current_pin;
++      drvdata->pins[PIN_NO_TEMP].name = pdata->temperature_pin;
++
++      adc_request_register(&drvdata->req);
++
++      /* Here we assume raw values in mV */
++      if (!pdata->voltage_mult)
++              pdata->voltage_mult = 1000;
++      /* Here we assume raw values in mA */
++      if (!pdata->current_mult)
++              pdata->current_mult = 1000;
++      /* Here we assume raw values in 1/10 C */
++      if (!pdata->temperature_mult)
++              pdata->temperature_mult = 1000;
++
++      drvdata->pdata = pdata;
++      pdata->drvdata = drvdata; /* Seems ugly, we need better solution */
++
++      platform_set_drvdata(pdev, drvdata);
++
++        // Load initial values ASAP
++      adc_battery_query(drvdata);
++
++      // Still schedule next sampling soon
++      INIT_DELAYED_WORK(&drvdata->work, adc_battery_work_func);
++      drvdata->wq = create_workqueue(pdev->dev.bus_id);
++      if (!drvdata->wq)
++              return -ESRCH;
++
++      queue_delayed_work(drvdata->wq, &drvdata->work, (5000 * HZ) / 1000);
++
++      return retval;
++}
++
++static int adc_battery_remove(struct platform_device *pdev)
++{
++      struct battery_adc_priv *drvdata = platform_get_drvdata(pdev);
++      cancel_delayed_work(&drvdata->work);
++      destroy_workqueue(drvdata->wq);
++      power_supply_unregister(&drvdata->batt_cdev);
++      adc_request_unregister(&drvdata->req);
++      kfree(drvdata->batt_cdev.properties);
++      return 0;
++}
++
++static struct platform_driver adc_battery_driver = {
++      .driver         = {
++              .name   = "adc-battery",
++      },
++      .probe          = adc_battery_probe,
++      .remove         = adc_battery_remove,
++};
++
++static int __init adc_battery_init(void)
++{
++      return platform_driver_register(&adc_battery_driver);
++}
++
++static void __exit adc_battery_exit(void)
++{
++      platform_driver_unregister(&adc_battery_driver);
++}
++
++module_init(adc_battery_init)
++module_exit(adc_battery_exit)
++
++MODULE_AUTHOR("Paul Sokolovsky");
++MODULE_DESCRIPTION("Battery driver for ADC device");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.22/drivers/power/apm_power.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/power/apm_power.c     2007-08-23 12:13:52.000000000 +0200
+@@ -0,0 +1,247 @@
++/*
++ * Copyright (c) 2007 Anton Vorontsov <cbou@mail.ru>
++ * Copyright (c) 2007 Eugeny Boger <eugenyboger@dgap.mipt.ru>
++ *
++ * Author: Eugeny Boger <eugenyboger@dgap.mipt.ru>
++ *
++ * Use consistent with the GNU GPL is permitted,
++ * provided that this copyright notice is
++ * preserved in its entirety in all copies and derived works.
++ */
++
++#include <linux/module.h>
++#include <linux/power_supply.h>
++#include <linux/apm-emulation.h>
++
++#define PSY_PROP(psy, prop, val) psy->get_property(psy, \
++                         POWER_SUPPLY_PROP_##prop, val)
++
++#define _MPSY_PROP(prop, val) main_battery->get_property(main_battery, \
++                                                         prop, val)
++
++#define MPSY_PROP(prop, val) _MPSY_PROP(POWER_SUPPLY_PROP_##prop, val)
++
++static struct power_supply *main_battery;
++
++static void find_main_battery(void)
++{
++      struct device *dev;
++      struct power_supply *bat, *batm;
++      union power_supply_propval full;
++      int max_charge = 0;
++
++      main_battery = NULL;
++      batm = NULL;
++      list_for_each_entry(dev, &power_supply_class->devices, node) {
++              bat = dev_get_drvdata(dev);
++              /* If none of battery devices cantains 'use_for_apm' flag,
++                 choice one with maximum design charge */
++              if (!PSY_PROP(bat, CHARGE_FULL_DESIGN, &full)) {
++                      if (full.intval > max_charge) {
++                              batm = bat;
++                              max_charge = full.intval;
++                      }
++              }
++
++              if (bat->use_for_apm)
++                      main_battery = bat;
++      }
++      if (!main_battery)
++              main_battery = batm;
++
++      return;
++}
++
++static int calculate_time(int status)
++{
++      union power_supply_propval charge_full, charge_empty;
++      union power_supply_propval charge, I;
++
++      if (MPSY_PROP(CHARGE_FULL, &charge_full)) {
++              /* if battery can't report this property, use design value */
++              if (MPSY_PROP(CHARGE_FULL_DESIGN, &charge_full))
++                      return -1;
++      }
++
++      if (MPSY_PROP(CHARGE_EMPTY, &charge_empty)) {
++              /* if battery can't report this property, use design value */
++              if (MPSY_PROP(CHARGE_EMPTY_DESIGN, &charge_empty))
++                      charge_empty.intval = 0;
++      }
++
++      if (MPSY_PROP(CHARGE_AVG, &charge)) {
++              /* if battery can't report average value, use momentary */
++              if (MPSY_PROP(CHARGE_NOW, &charge))
++                      return -1;
++      }
++
++      if (MPSY_PROP(CURRENT_AVG, &I)) {
++              /* if battery can't report average value, use momentary */
++              if (MPSY_PROP(CURRENT_NOW, &I))
++                      return -1;
++      }
++
++      if (I.intval == 0)
++              return 0;
++      else if (status == POWER_SUPPLY_STATUS_CHARGING)
++              return ((charge.intval - charge_full.intval) * 60L) /
++                     I.intval;
++      else
++              return -((charge.intval - charge_empty.intval) * 60L) /
++                      I.intval;
++}
++
++static int calculate_capacity(int using_charge)
++{
++      enum power_supply_property full_prop, empty_prop;
++      enum power_supply_property full_design_prop, empty_design_prop;
++      enum power_supply_property now_prop, avg_prop;
++      union power_supply_propval empty, full, cur;
++      int ret;
++
++      if (using_charge) {
++              full_prop = POWER_SUPPLY_PROP_CHARGE_FULL;
++              empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
++              full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN;
++              empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN;
++              now_prop = POWER_SUPPLY_PROP_CHARGE_NOW;
++              avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG;
++      }
++      else {
++              full_prop = POWER_SUPPLY_PROP_ENERGY_FULL;
++              empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY;
++              full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN;
++              empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN;
++              now_prop = POWER_SUPPLY_PROP_ENERGY_NOW;
++              avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG;
++      }
++
++      if (_MPSY_PROP(full_prop, &full)) {
++              /* if battery can't report this property, use design value */
++              if (_MPSY_PROP(full_design_prop, &full))
++                      return -1;
++      }
++
++      if (_MPSY_PROP(avg_prop, &cur)) {
++              /* if battery can't report average value, use momentary */
++              if (_MPSY_PROP(now_prop, &cur))
++                      return -1;
++      }
++
++      if (_MPSY_PROP(empty_prop, &empty)) {
++              /* if battery can't report this property, use design value */
++              if (_MPSY_PROP(empty_design_prop, &empty))
++                      empty.intval = 0;
++      }
++
++      if (full.intval - empty.intval)
++              ret =  ((cur.intval - empty.intval) * 100L) /
++                     (full.intval - empty.intval);
++      else
++              return -1;
++
++      if (ret > 100)
++              return 100;
++      else if (ret < 0)
++              return 0;
++
++      return ret;
++}
++
++static void apm_battery_apm_get_power_status(struct apm_power_info *info)
++{
++      union power_supply_propval status;
++      union power_supply_propval capacity, time_to_full, time_to_empty;
++
++      down(&power_supply_class->sem);
++      find_main_battery();
++      if (!main_battery) {
++              up(&power_supply_class->sem);
++              return;
++      }
++
++      /* status */
++
++      if (MPSY_PROP(STATUS, &status))
++              status.intval = POWER_SUPPLY_STATUS_UNKNOWN;
++
++      /* ac line status */
++
++      if ((status.intval == POWER_SUPPLY_STATUS_CHARGING) ||
++          (status.intval == POWER_SUPPLY_STATUS_NOT_CHARGING) ||
++          (status.intval == POWER_SUPPLY_STATUS_FULL))
++              info->ac_line_status = APM_AC_ONLINE;
++      else
++              info->ac_line_status = APM_AC_OFFLINE;
++
++      /* battery life (i.e. capacity, in percents) */
++
++      if (MPSY_PROP(CAPACITY, &capacity) == 0)
++              info->battery_life = capacity.intval;
++      else {
++              /* try calculate using energy */
++              info->battery_life = calculate_capacity(0);
++              /* if failed try calculate using charge instead */
++              if (info->battery_life == -1)
++                      info->battery_life = calculate_capacity(1);
++      }
++
++      /* charging status */
++
++      if (status.intval == POWER_SUPPLY_STATUS_CHARGING)
++              info->battery_status = APM_BATTERY_STATUS_CHARGING;
++      else {
++              if (info->battery_life > 50)
++                      info->battery_status = APM_BATTERY_STATUS_HIGH;
++              else if (info->battery_life > 5)
++                      info->battery_status = APM_BATTERY_STATUS_LOW;
++              else
++                      info->battery_status = APM_BATTERY_STATUS_CRITICAL;
++      }
++      info->battery_flag = info->battery_status;
++
++      /* time */
++
++      info->units = APM_UNITS_MINS;
++
++      if (status.intval == POWER_SUPPLY_STATUS_CHARGING) {
++              if (MPSY_PROP(TIME_TO_FULL_AVG, &time_to_full)) {
++                      if (MPSY_PROP(TIME_TO_FULL_NOW, &time_to_full))
++                              info->time = calculate_time(status.intval);
++                      else
++                              info->time = time_to_full.intval / 60;
++              }
++      }
++      else {
++              if (MPSY_PROP(TIME_TO_EMPTY_AVG, &time_to_empty)) {
++                      if (MPSY_PROP(TIME_TO_EMPTY_NOW, &time_to_empty))
++                              info->time = calculate_time(status.intval);
++                      else
++                              info->time = time_to_empty.intval / 60;
++              }
++      }
++
++      up(&power_supply_class->sem);
++      return;
++}
++
++static int __init apm_battery_init(void)
++{
++      printk(KERN_INFO "APM Battery Driver\n");
++
++      apm_get_power_status = apm_battery_apm_get_power_status;
++      return 0;
++}
++
++static void __exit apm_battery_exit(void)
++{
++      apm_get_power_status = NULL;
++      return;
++}
++
++module_init(apm_battery_init);
++module_exit(apm_battery_exit);
++
++MODULE_AUTHOR("Eugeny Boger <eugenyboger@dgap.mipt.ru>");
++MODULE_DESCRIPTION("APM emulation driver for battery monitoring class");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.22/drivers/power/ds2760_battery.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/power/ds2760_battery.c        2007-08-23 12:13:52.000000000 +0200
+@@ -0,0 +1,475 @@
++/*
++ * Driver for batteries with DS2760 chips inside.
++ *
++ * Copyright (c) 2007 Anton Vorontsov
++ *               2004-2007 Matt Reimer
++ *               2004 Szabolcs Gyurko
++ *
++ * Use consistent with the GNU GPL is permitted,
++ * provided that this copyright notice is
++ * preserved in its entirety in all copies and derived works.
++ *
++ * Author:  Anton Vorontsov <cbou@mail.ru>
++ *          February 2007
++ *
++ *          Matt Reimer <mreimer@vpop.net>
++ *          April 2004, 2005, 2007
++ *
++ *          Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
++ *          September 2004
++ */
++
++#include <linux/module.h>
++#include <linux/param.h>
++#include <linux/jiffies.h>
++#include <linux/workqueue.h>
++#include <linux/pm.h>
++#include <linux/platform_device.h>
++#include <linux/power_supply.h>
++
++#include "../w1/w1.h"
++#include "../w1/slaves/w1_ds2760.h"
++
++struct ds2760_device_info {
++      struct device *dev;
++
++      /* DS2760 data, valid after calling ds2760_battery_read_status() */
++      unsigned long update_time;      /* jiffies when data read */
++      char raw[DS2760_DATA_SIZE];     /* raw DS2760 data */
++      int voltage_raw;                /* units of 4.88 mV */
++      int voltage_uV;                 /* units of uV */
++      int current_raw;                /* units of 0.625 mA */
++      int current_uA;                 /* units of uA */
++      int accum_current_raw;          /* units of 0.25 mAh */
++      int accum_current_uAh;          /* units of uAh */
++      int temp_raw;                   /* units of 0.125 C */
++      int temp_C;                     /* units of 0.1 C */
++      int rated_capacity;             /* units of uAh */
++      int rem_capacity;               /* percentage */
++      int full_active_uAh;            /* units of uAh */
++      int empty_uAh;                  /* units of uAh */
++      int life_sec;                   /* units of seconds */
++      int charge_status;              /* POWER_SUPPLY_STATUS_* */
++
++      int full_counter;
++      struct power_supply bat;
++      struct device *w1_dev;
++      struct workqueue_struct *monitor_wqueue;
++      struct delayed_work monitor_work;
++};
++
++static unsigned int cache_time = 1000;
++module_param(cache_time, uint, 0644);
++MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
++
++/* Some batteries have their rated capacity stored a N * 10 mAh, while
++ * others use an index into this table. */
++static int rated_capacities[] = {
++      0,
++      920,        /* Samsung */
++      920,        /* BYD */
++      920,        /* Lishen */
++      920,        /* NEC */
++      1440,       /* Samsung */
++      1440,       /* BYD */
++      1440,       /* Lishen */
++      1440,       /* NEC */
++      2880,       /* Samsung */
++      2880,       /* BYD */
++      2880,       /* Lishen */
++      2880        /* NEC */
++};
++
++/* array is level at temps 0C, 10C, 20C, 30C, 40C
++ * temp is in Celsius */
++static int battery_interpolate(int array[], int temp)
++{
++      int index, dt;
++
++      if (temp <= 0)
++              return array[0];
++      if (temp >= 40)
++              return array[4];
++
++      index = temp / 10;
++      dt    = temp % 10;
++
++      return array[index] + (((array[index + 1] - array[index]) * dt) / 10);
++}
++
++static int ds2760_battery_read_status(struct ds2760_device_info *di)
++{
++      int ret, i, start, count, scale[5];
++
++      if (di->update_time && time_before(jiffies, di->update_time +
++                                         msecs_to_jiffies(cache_time)))
++              return 0;
++
++      /* The first time we read the entire contents of SRAM/EEPROM,
++       * but after that we just read the interesting bits that change. */
++      if (di->update_time == 0) {
++              start = 0;
++              count = DS2760_DATA_SIZE;
++      }
++      else {
++              start = DS2760_VOLTAGE_MSB;
++              count = DS2760_TEMP_LSB - start + 1;
++      }
++
++      ret = w1_ds2760_read(di->w1_dev, di->raw + start, start, count);
++      if (ret != count) {
++              dev_warn(di->dev, "call to w1_ds2760_read failed (0x%p)\n",
++                       di->w1_dev);
++              return 1;
++      }
++
++      di->update_time = jiffies;
++
++      /* DS2760 reports voltage in units of 4.88mV, but the battery class
++       * reports in units of uV, so convert by multiplying by 4880. */
++      di->voltage_raw = (di->raw[DS2760_VOLTAGE_MSB] << 3) |
++                        (di->raw[DS2760_VOLTAGE_LSB] >> 5);
++      di->voltage_uV = di->voltage_raw * 4880;
++
++      /* DS2760 reports current in signed units of 0.625mA, but the battery
++       * class reports in units of uA, so convert by multiplying by 625. */
++      di->current_raw =
++          (((signed char)di->raw[DS2760_CURRENT_MSB]) << 5) |
++                        (di->raw[DS2760_CURRENT_LSB] >> 3);
++      di->current_uA = di->current_raw * 625;
++
++      /* DS2760 reports accumulated current in signed units of 0.25mAh. */
++      di->accum_current_raw =
++          (((signed char)di->raw[DS2760_CURRENT_ACCUM_MSB]) << 8) |
++                         di->raw[DS2760_CURRENT_ACCUM_LSB];
++      di->accum_current_uAh = di->accum_current_raw * 250;
++
++      /* DS2760 reports temperature in signed units of 0.125C, but the
++       * battery class reports in units of 1/10 C, so we convert by
++       * multiplying by .125 * 10 = 1.25. */
++      di->temp_raw = (((signed char)di->raw[DS2760_TEMP_MSB]) << 3) |
++                                   (di->raw[DS2760_TEMP_LSB] >> 5);
++      di->temp_C = di->temp_raw + (di->temp_raw / 4);
++
++      /* At least some battery monitors (e.g. HP iPAQ) store the battery's
++       * maximum rated capacity. */
++      if (di->raw[DS2760_RATED_CAPACITY] < ARRAY_SIZE(rated_capacities))
++              di->rated_capacity = rated_capacities[
++                      (unsigned int)di->raw[DS2760_RATED_CAPACITY]];
++      else
++              di->rated_capacity = di->raw[DS2760_RATED_CAPACITY] * 10;
++
++      di->rated_capacity *= 1000; /* convert to uAh */
++
++      /* Calculate the full level at the present temperature. */
++      di->full_active_uAh = di->raw[DS2760_ACTIVE_FULL] << 8 |
++                            di->raw[DS2760_ACTIVE_FULL + 1];
++
++      scale[0] = di->raw[DS2760_ACTIVE_FULL] << 8 |
++                 di->raw[DS2760_ACTIVE_FULL + 1];
++      for (i = 1; i < 5; i++)
++              scale[i] = scale[i - 1] + di->raw[DS2760_ACTIVE_FULL + 2 + i];
++
++      di->full_active_uAh = battery_interpolate(scale, di->temp_C / 10);
++      di->full_active_uAh *= 1000; /* convert to uAh */
++
++      /* Calculate the empty level at the present temperature. */
++      scale[4] = di->raw[DS2760_ACTIVE_EMPTY + 4];
++      for (i = 3; i >= 0; i--)
++              scale[i] = scale[i + 1] + di->raw[DS2760_ACTIVE_EMPTY + i];
++
++      di->empty_uAh = battery_interpolate(scale, di->temp_C / 10);
++      di->empty_uAh *= 1000; /* convert to uAh */
++
++      /* From Maxim Application Note 131: remaining capacity =
++       * ((ICA - Empty Value) / (Full Value - Empty Value)) x 100% */
++      di->rem_capacity = ((di->accum_current_uAh - di->empty_uAh) * 100L) /
++                          (di->full_active_uAh - di->empty_uAh);
++
++      if (di->rem_capacity < 0)
++              di->rem_capacity = 0;
++      if (di->rem_capacity > 100)
++              di->rem_capacity = 100;
++
++      if (di->current_uA)
++              di->life_sec = -((di->accum_current_uAh - di->empty_uAh) *
++                               3600L) / di->current_uA;
++      else
++              di->life_sec = 0;
++
++      return 0;
++}
++
++static void ds2760_battery_update_status(struct ds2760_device_info *di)
++{
++      int old_charge_status = di->charge_status;
++
++      ds2760_battery_read_status(di);
++
++      if (di->charge_status == POWER_SUPPLY_STATUS_UNKNOWN)
++              di->full_counter = 0;
++
++      if (power_supply_am_i_supplied(&di->bat)) {
++              if (di->current_uA > 10000) {
++                      di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
++                      di->full_counter = 0;
++              }
++              else if (di->current_uA < -5000) {
++                      if (di->charge_status != POWER_SUPPLY_STATUS_NOT_CHARGING)
++                              dev_notice(di->dev, "not enough power to "
++                                         "charge\n");
++                      di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
++                      di->full_counter = 0;
++              }
++              else if (di->current_uA < 10000 &&
++                          di->charge_status != POWER_SUPPLY_STATUS_FULL) {
++
++                      /* Don't consider the battery to be full unless
++                       * we've seen the current < 10 mA at least two
++                       * consecutive times. */
++
++                      di->full_counter++;
++
++                      if (di->full_counter < 2)
++                              di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
++                      else {
++                              unsigned char acr[2];
++                              int acr_val;
++
++                              /* acr is in units of 0.25 mAh */
++                              acr_val = di->full_active_uAh * 4L / 1000;
++
++                              acr[0] = acr_val >> 8;
++                              acr[1] = acr_val & 0xff;
++
++                              if (w1_ds2760_write(di->w1_dev, acr,
++                                  DS2760_CURRENT_ACCUM_MSB, 2) < 2)
++                                      dev_warn(di->dev,
++                                               "ACR reset failed\n");
++
++                              di->charge_status = POWER_SUPPLY_STATUS_FULL;
++                      }
++              }
++      }
++      else {
++              di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
++              di->full_counter = 0;
++      }
++
++      if (di->charge_status != old_charge_status)
++              power_supply_changed(&di->bat);
++
++      return;
++}
++
++static void ds2760_battery_work(struct work_struct *work)
++{
++      struct ds2760_device_info *di = container_of(work,
++              struct ds2760_device_info, monitor_work.work);
++      const int interval = HZ * 60;
++
++      dev_dbg(di->dev, "%s\n", __FUNCTION__);
++
++      ds2760_battery_update_status(di);
++      queue_delayed_work(di->monitor_wqueue, &di->monitor_work, interval);
++
++      return;
++}
++
++#define to_ds2760_device_info(x) container_of((x), struct ds2760_device_info, \
++                                              bat);
++
++static void ds2760_battery_external_power_changed(struct power_supply *psy)
++{
++      struct ds2760_device_info *di = to_ds2760_device_info(psy);
++
++      dev_dbg(di->dev, "%s\n", __FUNCTION__);
++
++      cancel_delayed_work(&di->monitor_work);
++      queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ/10);
++
++      return;
++}
++
++static int ds2760_battery_get_property(struct power_supply *psy,
++                                       enum power_supply_property psp,
++                                       union power_supply_propval *val)
++{
++      struct ds2760_device_info *di = to_ds2760_device_info(psy);
++
++      switch (psp) {
++      case POWER_SUPPLY_PROP_STATUS:
++              val->intval = di->charge_status;
++              return 0;
++      default:
++              break;
++      }
++
++      ds2760_battery_read_status(di);
++
++      switch (psp) {
++      case POWER_SUPPLY_PROP_VOLTAGE_NOW:
++              val->intval = di->voltage_uV;
++              break;
++      case POWER_SUPPLY_PROP_CURRENT_NOW:
++              val->intval = di->current_uA;
++              break;
++      case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
++              val->intval = di->rated_capacity;
++              break;
++      case POWER_SUPPLY_PROP_CHARGE_FULL:
++              val->intval = di->full_active_uAh;
++              break;
++      case POWER_SUPPLY_PROP_CHARGE_EMPTY:
++              val->intval = di->empty_uAh;
++              break;
++      case POWER_SUPPLY_PROP_CHARGE_NOW:
++              val->intval = di->accum_current_uAh;
++              break;
++      case POWER_SUPPLY_PROP_TEMP:
++              val->intval = di->temp_C;
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++static enum power_supply_property ds2760_battery_props[] = {
++      POWER_SUPPLY_PROP_STATUS,
++      POWER_SUPPLY_PROP_VOLTAGE_NOW,
++      POWER_SUPPLY_PROP_CURRENT_NOW,
++      POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
++      POWER_SUPPLY_PROP_CHARGE_FULL,
++      POWER_SUPPLY_PROP_CHARGE_EMPTY,
++      POWER_SUPPLY_PROP_CHARGE_NOW,
++      POWER_SUPPLY_PROP_TEMP,
++};
++
++static int ds2760_battery_probe(struct platform_device *pdev)
++{
++      int retval = 0;
++      struct ds2760_device_info *di;
++      struct ds2760_platform_data *pdata;
++
++      di = kzalloc(sizeof(*di), GFP_KERNEL);
++      if (!di) {
++              retval = -ENOMEM;
++              goto di_alloc_failed;
++      }
++
++      platform_set_drvdata(pdev, di);
++
++      pdata = pdev->dev.platform_data;
++      di->dev                = &pdev->dev;
++      di->w1_dev             = pdev->dev.parent;
++      di->bat.name           = pdev->dev.bus_id;
++      di->bat.type           = POWER_SUPPLY_TYPE_BATTERY;
++      di->bat.properties     = ds2760_battery_props;
++      di->bat.num_properties = ARRAY_SIZE(ds2760_battery_props);
++      di->bat.get_property   = ds2760_battery_get_property;
++      di->bat.external_power_changed =
++                                ds2760_battery_external_power_changed;
++      di->bat.use_for_apm = 1;
++
++      di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
++
++      retval = power_supply_register(&pdev->dev, &di->bat);
++      if (retval) {
++              dev_err(di->dev, "failed to register battery");
++              goto batt_failed;
++      }
++
++      INIT_DELAYED_WORK(&di->monitor_work, ds2760_battery_work);
++      di->monitor_wqueue = create_singlethread_workqueue(pdev->dev.bus_id);
++      if (!di->monitor_wqueue) {
++              retval = -ESRCH;
++              goto workqueue_failed;
++      }
++      queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 1);
++
++      goto success;
++
++workqueue_failed:
++      power_supply_unregister(&di->bat);
++batt_failed:
++      kfree(di);
++di_alloc_failed:
++success:
++      return retval;
++}
++
++static int ds2760_battery_remove(struct platform_device *pdev)
++{
++      struct ds2760_device_info *di = platform_get_drvdata(pdev);
++
++      cancel_rearming_delayed_workqueue(di->monitor_wqueue,
++                                        &di->monitor_work);
++      destroy_workqueue(di->monitor_wqueue);
++      power_supply_unregister(&di->bat);
++
++      return 0;
++}
++
++#ifdef CONFIG_PM
++
++static int ds2760_battery_suspend(struct platform_device *pdev,
++                                  pm_message_t state)
++{
++      struct ds2760_device_info *di = platform_get_drvdata(pdev);
++
++      di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
++
++      return 0;
++}
++
++static int ds2760_battery_resume(struct platform_device *pdev)
++{
++      struct ds2760_device_info *di = platform_get_drvdata(pdev);
++
++      di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
++      power_supply_changed(&di->bat);
++
++      cancel_delayed_work(&di->monitor_work);
++      queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ);
++
++      return 0;
++}
++
++#else
++
++#define ds2760_battery_suspend NULL
++#define ds2760_battery_resume NULL
++
++#endif /* CONFIG_PM */
++
++static struct platform_driver ds2760_battery_driver = {
++      .driver = {
++              .name = "ds2760-battery",
++      },
++      .probe    = ds2760_battery_probe,
++      .remove   = ds2760_battery_remove,
++      .suspend  = ds2760_battery_suspend,
++      .resume   = ds2760_battery_resume,
++};
++
++static int __init ds2760_battery_init(void)
++{
++      return platform_driver_register(&ds2760_battery_driver);
++}
++
++static void __exit ds2760_battery_exit(void)
++{
++      platform_driver_unregister(&ds2760_battery_driver);
++      return;
++}
++
++module_init(ds2760_battery_init);
++module_exit(ds2760_battery_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, "
++              "Matt Reimer <mreimer@vpop.net>, "
++              "Anton Vorontsov <cbou@mail.ru>");
++MODULE_DESCRIPTION("ds2760 battery driver");
+Index: linux-2.6.22/drivers/power/Kconfig
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/power/Kconfig 2007-08-23 12:13:52.000000000 +0200
+@@ -0,0 +1,70 @@
++menuconfig POWER_SUPPLY
++      tristate "Power supply class support"
++      help
++        Say Y here to enable power supply class support. This allows
++        power supply (batteries, AC, USB) monitoring by userspace
++        via sysfs and uevent (if available) and/or APM kernel interface
++        (if selected below).
++
++if POWER_SUPPLY
++
++config POWER_SUPPLY_DEBUG
++      bool "Power supply debug"
++      help
++        Say Y here to enable debugging messages for power supply class
++        and drivers.
++
++config PDA_POWER
++      tristate "Generic PDA/phone power driver"
++      help
++        Say Y here to enable generic power driver for PDAs and phones with
++        one or two external power supplies (AC/USB) connected to main and
++        backup batteries, and optional builtin charger.
++
++config APM_POWER
++      tristate "APM emulation for class batteries"
++      depends on APM_EMULATION
++      help
++        Say Y here to enable support APM status emulation using
++        battery class devices.
++
++config BATTERY_DS2760
++      tristate "DS2760 battery driver (HP iPAQ & others)"
++      select W1
++      select W1_SLAVE_DS2760
++      help
++        Say Y here to enable support for batteries with ds2760 chip.
++
++config BATTERY_PMU
++      tristate "Apple PMU battery"
++      depends on ADB_PMU
++      help
++        Say Y here to expose battery information on Apple machines
++        through the generic battery class.
++
++config BATTERY_OLPC
++      tristate "One Laptop Per Child battery"
++      depends on X86_32
++      help
++        Say Y to enable support for the battery on the OLPC laptop.
++
++# drivers below are not in battery2-2.6 tree
++
++config ADC_BATTERY
++      tristate "Generic ADC battery driver"
++      depends on ADC && POWER_SUPPLY
++      help
++        Say Y here to enable support for battery monitoring using generic ADC device.
++
++config IPAQ_MICRO_BATTERY
++      tristate "HP iPAQ Micro ASIC battery driver"
++      depends on IPAQ_MICRO && POWER_SUPPLY
++      help
++        Choose this option if you want to monitor battery status on
++        Compaq/HP iPAQ h3100 h3600
++
++config MCP_UCB1x00_SIMPAD_BATTERY
++      tristate "SIMpad Battery Reading Support"
++      depends on MCP_UCB1x00 && POWER_SUPPLY
++
++endif # POWER_SUPPLY
+Index: linux-2.6.22/drivers/power/Makefile
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/power/Makefile        2007-08-23 12:13:52.000000000 +0200
+@@ -0,0 +1,28 @@
++power_supply-objs := power_supply_core.o
++
++ifeq ($(CONFIG_SYSFS),y)
++power_supply-objs += power_supply_sysfs.o
++endif
++
++ifeq ($(CONFIG_LEDS_TRIGGERS),y)
++power_supply-objs += power_supply_leds.o
++endif
++
++ifeq ($(CONFIG_POWER_SUPPLY_DEBUG),y)
++EXTRA_CFLAGS += -DDEBUG
++endif
++
++obj-$(CONFIG_POWER_SUPPLY)         += power_supply.o
++
++obj-$(CONFIG_PDA_POWER)            += pda_power.o
++obj-$(CONFIG_APM_POWER)            += apm_power.o
++
++obj-$(CONFIG_BATTERY_DS2760)       += ds2760_battery.o
++obj-$(CONFIG_BATTERY_PMU)          += pmu_battery.o
++obj-$(CONFIG_BATTERY_OLPC)         += olpc_battery.o
++
++# drivers below are not in battery2-2.6 tree
++
++obj-$(CONFIG_ADC_BATTERY)          += adc_battery.o
++obj-$(CONFIG_IPAQ_MICRO_BATTERY)   += micro_battery.o
++obj-$(CONFIG_MCP_UCB1x00_SIMPAD_BATTERY) += simpad-battery.o
+Index: linux-2.6.22/drivers/power/micro_battery.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/power/micro_battery.c 2007-08-23 12:25:20.000000000 +0200
+@@ -0,0 +1,257 @@
++/*
++ * 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.
++ *
++ * h3600 atmel micro companion support, battery subdevice
++ * based on previous kernel 2.4 version
++ * Author : Alessandro Gardich <gremlin@gremlin.it>
++ *
++ */
++
++
++#include <linux/module.h>
++#include <linux/version.h>
++
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/interrupt.h>
++#include <linux/sched.h>
++#include <linux/pm.h>
++#include <linux/sysctl.h>
++#include <linux/proc_fs.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/power_supply.h>
++#include <linux/platform_device.h>
++#include <linux/timer.h>
++
++#include <asm/arch/hardware.h>
++
++#include <asm/arch/h3600.h>
++#include <asm/arch/SA-1100.h>
++
++#include <asm/hardware/micro.h>
++
++#define BATT_PERIOD 10*HZ
++
++#define H3600_BATT_STATUS_HIGH         0x01
++#define H3600_BATT_STATUS_LOW          0x02
++#define H3600_BATT_STATUS_CRITICAL     0x04
++#define H3600_BATT_STATUS_CHARGING     0x08
++#define H3600_BATT_STATUS_CHARGEMAIN   0x10
++#define H3600_BATT_STATUS_DEAD         0x20 /* Battery will not charge */
++#define H3600_BATT_STATUS_NOTINSTALLED 0x20 /* For expansion pack batteries */
++#define H3600_BATT_STATUS_FULL         0x40 /* Battery fully charged (and connected to AC) */
++#define H3600_BATT_STATUS_NOBATTERY    0x80
++#define H3600_BATT_STATUS_UNKNOWN      0xff
++
++
++//static struct power_supply_dev *micro_battery;
++
++static micro_private_t *p_micro;
++
++struct timer_list batt_timer;
++
++struct {
++      int ac;
++      int update_time;
++      int chemistry;
++      int voltage;
++      int temperature;
++      int flag;
++} micro_battery;
++
++static void micro_battery_receive (int len, unsigned char *data) {
++      if (0) {
++              printk(KERN_ERR "h3600_battery - AC = %02x\n", data[0]);
++              printk(KERN_ERR "h3600_battery - BAT1 chemistry = %02x\n", data[1]);
++              printk(KERN_ERR "h3600_battery - BAT1 voltage = %d %02x%02x\n", (data[3]<<8)+data[2], data[2], data[3]);
++              printk(KERN_ERR "h3600_battery - BAT1 status = %02x\n", data[4]);
++      }
++
++      micro_battery.ac = data[0];
++      micro_battery.chemistry = data[1];
++      micro_battery.voltage = ((((unsigned short)data[3]<<8)+data[2]) * 5000L ) * 1000 / 1024;
++      micro_battery.flag = data[4];
++
++      if (len == 9) {
++              if (0) {
++                      printk(KERN_ERR "h3600_battery - BAT2 chemistry = %02x\n", data[5]);
++                      printk(KERN_ERR "h3600_battery - BAT2 voltage = %d %02x%02x\n", (data[7]<<8)+data[6], data[6], data[7]);
++                      printk(KERN_ERR "h3600_battery - BAT2 status = %02x\n", data[8]);
++              }
++      }
++}
++
++static void micro_temperature_receive (int len, unsigned char *data) {
++      micro_battery.temperature = ((unsigned short)data[1]<<8)+data[0];
++}
++
++void h3600_battery_read_status(unsigned long data) {
++
++      if (++data % 2)
++              h3600_micro_tx_msg(0x09,0,NULL);
++      else
++              h3600_micro_tx_msg(0x06,0,NULL);
++
++      batt_timer.expires += BATT_PERIOD;
++      batt_timer.data = data;
++
++      add_timer(&batt_timer);
++}
++
++int get_capacity(struct power_supply *b) {
++    switch (micro_battery.flag) {
++    case H3600_BATT_STATUS_HIGH :     return 100; break;
++    case H3600_BATT_STATUS_LOW :      return 50; break;
++    case H3600_BATT_STATUS_CRITICAL : return 5; break;
++    default: break;
++    }
++    return 0;
++}
++
++int get_status(struct power_supply *b) {
++
++   if (micro_battery.flag == H3600_BATT_STATUS_UNKNOWN)
++      return POWER_SUPPLY_STATUS_UNKNOWN;
++
++   if (micro_battery.flag & H3600_BATT_STATUS_FULL)
++      return POWER_SUPPLY_STATUS_FULL;
++
++   if ((micro_battery.flag & H3600_BATT_STATUS_CHARGING) ||
++       (micro_battery.flag & H3600_BATT_STATUS_CHARGEMAIN))
++      return POWER_SUPPLY_STATUS_CHARGING;
++
++   return POWER_SUPPLY_STATUS_DISCHARGING;
++}
++
++static int micro_batt_get_property(struct power_supply *b,
++                                   enum power_supply_property psp,
++                                   union power_supply_propval *val)
++{
++      switch (psp) {
++      case POWER_SUPPLY_PROP_STATUS:
++              val->intval = get_status(b);
++              break;
++      case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
++              val->intval = 4700000;
++              break;
++      case POWER_SUPPLY_PROP_CAPACITY:
++              val->intval = get_capacity(b);
++              break;
++      case POWER_SUPPLY_PROP_TEMP:
++              val->intval = micro_battery.temperature;
++              break;
++      case POWER_SUPPLY_PROP_VOLTAGE_NOW:
++              val->intval = micro_battery.voltage;
++              break;
++      default:
++              return -EINVAL;
++      };
++
++      return 0;
++}
++
++static enum power_supply_property micro_batt_props[] = {
++      POWER_SUPPLY_PROP_STATUS,
++      POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
++      POWER_SUPPLY_PROP_CAPACITY,
++      POWER_SUPPLY_PROP_TEMP,
++      POWER_SUPPLY_PROP_VOLTAGE_NOW,
++};
++
++static struct power_supply h3600_battery = {
++      .name               = "main-battery",
++      .properties         = micro_batt_props,
++      .num_properties     = ARRAY_SIZE(micro_batt_props),
++      .get_property       = micro_batt_get_property,
++      .use_for_apm        = 1,
++};
++
++static int micro_batt_probe (struct platform_device *pdev)
++{
++      if (1) printk(KERN_ERR "micro battery probe : begin\n");
++
++      power_supply_register(&pdev->dev, &h3600_battery);
++
++      { /*--- callback ---*/
++              p_micro = platform_get_drvdata(pdev);
++              spin_lock(p_micro->lock);
++              p_micro->h_batt = micro_battery_receive;
++              p_micro->h_temp = micro_temperature_receive;
++              spin_unlock(p_micro->lock);
++      }
++
++      { /*--- timer ---*/
++              init_timer(&batt_timer);
++              batt_timer.expires = jiffies + BATT_PERIOD;
++              batt_timer.data = 0;
++              batt_timer.function = h3600_battery_read_status;
++
++              add_timer(&batt_timer);
++      }
++
++      if (1) printk(KERN_ERR "micro battery probe : end\n");
++      return 0;
++}
++
++static int micro_batt_remove (struct platform_device *pdev)
++{
++      power_supply_unregister(&h3600_battery);
++      { /*--- callback ---*/
++              init_timer(&batt_timer);
++              p_micro->h_batt = NULL;
++              p_micro->h_temp = NULL;
++              spin_unlock(p_micro->lock);
++      }
++      { /*--- timer ---*/
++              del_timer_sync(&batt_timer);
++      }
++        return 0;
++}
++
++static int micro_batt_suspend ( struct platform_device *pdev, pm_message_t state)
++{
++      { /*--- timer ---*/
++              del_timer(&batt_timer);
++      }
++      return 0;
++}
++
++static int micro_batt_resume ( struct platform_device *pdev)
++{
++      { /*--- timer ---*/
++              add_timer(&batt_timer);
++      }
++      return 0;
++}
++
++struct platform_driver micro_batt_device_driver = {
++      .driver  = {
++              .name    = "h3600-micro-battery",
++      },
++      .probe   = micro_batt_probe,
++      .remove  = micro_batt_remove,
++      .suspend = micro_batt_suspend,
++      .resume  = micro_batt_resume,
++};
++
++static int micro_batt_init (void)
++{
++      return platform_driver_register(&micro_batt_device_driver);
++}
++
++static void micro_batt_cleanup (void)
++{
++      platform_driver_unregister (&micro_batt_device_driver);
++}
++
++module_init (micro_batt_init);
++module_exit (micro_batt_cleanup);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("gremlin.it");
++MODULE_DESCRIPTION("driver for iPAQ Atmel micro battery");
++
++
+Index: linux-2.6.22/drivers/power/olpc_battery.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/power/olpc_battery.c  2007-08-23 12:13:52.000000000 +0200
+@@ -0,0 +1,302 @@
++/*
++ * Battery driver for One Laptop Per Child board.
++ *
++ *    Copyright Â© 2006  David Woodhouse <dwmw2@infradead.org>
++ *
++ * 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/module.h>
++#include <linux/err.h>
++#include <linux/platform_device.h>
++#include <linux/power_supply.h>
++#include <linux/jiffies.h>
++#include <linux/sched.h>
++#include <asm/io.h>
++
++#define wBAT_VOLTAGE     0xf900  /* *9.76/32,    mV   */
++#define wBAT_CURRENT     0xf902  /* *15.625/120, mA   */
++#define wBAT_TEMP        0xf906  /* *256/1000,   Â°C  */
++#define wAMB_TEMP        0xf908  /* *256/1000,   Â°C  */
++#define SOC              0xf910  /* percentage        */
++#define sMBAT_STATUS     0xfaa4
++#define sBAT_PRESENT          1
++#define sBAT_FULL             2
++#define sBAT_DESTROY          4  /* what is this exactly? */
++#define sBAT_LOW             32
++#define sBAT_DISCHG          64
++#define sMCHARGE_STATUS  0xfaa5
++#define sBAT_CHARGE           1
++#define sBAT_OVERTEMP         4
++#define sBAT_NiMH             8
++#define sPOWER_FLAG      0xfa40
++#define ADAPTER_IN            1
++
++/*********************************************************************
++ *            EC locking and access
++ *********************************************************************/
++
++static int lock_ec(void)
++{
++      unsigned long timeo = jiffies + HZ / 20;
++
++      while (1) {
++              unsigned char lock = inb(0x6c) & 0x80;
++              if (!lock)
++                      return 0;
++              if (time_after(jiffies, timeo)) {
++                      printk(KERN_ERR "olpc_battery: failed to lock EC for "
++                             "battery access\n");
++                      return 1;
++              }
++              yield();
++      }
++}
++
++static void unlock_ec(void)
++{
++      outb(0xff, 0x6c);
++      return;
++}
++
++static unsigned char read_ec_byte(unsigned short adr)
++{
++      outb(adr >> 8, 0x381);
++      outb(adr, 0x382);
++      return inb(0x383);
++}
++
++static unsigned short read_ec_word(unsigned short adr)
++{
++      return (read_ec_byte(adr) << 8) | read_ec_byte(adr + 1);
++}
++
++/*********************************************************************
++ *            Power
++ *********************************************************************/
++
++static int olpc_ac_get_prop(struct power_supply *psy,
++                            enum power_supply_property psp,
++                            union power_supply_propval *val)
++{
++      int ret = 0;
++
++      if (lock_ec())
++              return -EIO;
++
++      switch (psp) {
++      case POWER_SUPPLY_PROP_ONLINE:
++              if (!(read_ec_byte(sMBAT_STATUS) & sBAT_PRESENT)) {
++                      ret = -ENODEV;
++                      goto out;
++              }
++              val->intval = !!(read_ec_byte(sPOWER_FLAG) & ADAPTER_IN);
++              break;
++      default:
++              ret = -EINVAL;
++              break;
++      }
++out:
++      unlock_ec();
++      return ret;
++}
++
++static enum power_supply_property olpc_ac_props[] = {
++      POWER_SUPPLY_PROP_ONLINE,
++};
++
++static struct power_supply olpc_ac = {
++      .name = "olpc-ac",
++      .type = POWER_SUPPLY_TYPE_MAINS,
++      .properties = olpc_ac_props,
++      .num_properties = ARRAY_SIZE(olpc_ac_props),
++      .get_property = olpc_ac_get_prop,
++};
++
++/*********************************************************************
++ *            Battery properties
++ *********************************************************************/
++
++static int olpc_bat_get_property(struct power_supply *psy,
++                                 enum power_supply_property psp,
++                                 union power_supply_propval *val)
++{
++      int ret = 0;
++
++      if (lock_ec())
++              return -EIO;
++
++      switch (psp) {
++      case POWER_SUPPLY_PROP_STATUS:
++              {
++                      int status = POWER_SUPPLY_STATUS_UNKNOWN;
++
++                      val->intval = read_ec_byte(sMBAT_STATUS);
++
++                      if (!(val->intval & sBAT_PRESENT)) {
++                              ret = -ENODEV;
++                              goto out;
++                      }
++
++                      if (val->intval & sBAT_DISCHG)
++                              status = POWER_SUPPLY_STATUS_DISCHARGING;
++                      else if (val->intval & sBAT_FULL)
++                              status = POWER_SUPPLY_STATUS_FULL;
++
++                      val->intval = read_ec_byte(sMCHARGE_STATUS);
++                      if (val->intval & sBAT_CHARGE)
++                              status = POWER_SUPPLY_STATUS_CHARGING;
++
++                      val->intval = status;
++                      break;
++              }
++      case POWER_SUPPLY_PROP_PRESENT:
++              val->intval = !!(read_ec_byte(sMBAT_STATUS) & sBAT_PRESENT);
++              break;
++      case POWER_SUPPLY_PROP_HEALTH:
++              val->intval = read_ec_byte(sMCHARGE_STATUS);
++              if (val->intval & sBAT_OVERTEMP)
++                      val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
++              else
++                      val->intval = POWER_SUPPLY_HEALTH_GOOD;
++              break;
++      case POWER_SUPPLY_PROP_TECHNOLOGY:
++              val->intval = read_ec_byte(sMCHARGE_STATUS);
++              if (val->intval & sBAT_NiMH)
++                      val->intval = POWER_SUPPLY_TECHNOLOGY_NIMH;
++              else
++                      val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
++              break;
++      case POWER_SUPPLY_PROP_VOLTAGE_AVG:
++              val->intval = read_ec_byte(wBAT_VOLTAGE) * 9760L / 32;
++              break;
++      case POWER_SUPPLY_PROP_CURRENT_AVG:
++              val->intval = read_ec_byte(wBAT_CURRENT) * 15625L / 120;
++              break;
++      case POWER_SUPPLY_PROP_CAPACITY:
++              val->intval = read_ec_byte(SOC);
++              break;
++      case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
++              val->intval = read_ec_byte(sMBAT_STATUS);
++              if (val->intval & sBAT_FULL)
++                      val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
++              else if (val->intval & sBAT_LOW)
++                      val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
++              else
++                      val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
++              break;
++      case POWER_SUPPLY_PROP_TEMP:
++              val->intval = read_ec_byte(wBAT_TEMP) * 256 / 100;
++              break;
++      case POWER_SUPPLY_PROP_TEMP_AMBIENT:
++              val->intval = read_ec_byte(wAMB_TEMP) * 256 / 100;
++              break;
++      default:
++              ret = -EINVAL;
++              break;
++      }
++
++out:
++      unlock_ec();
++      return ret;
++}
++
++static enum power_supply_property olpc_bat_props[] = {
++      POWER_SUPPLY_PROP_STATUS,
++      POWER_SUPPLY_PROP_PRESENT,
++      POWER_SUPPLY_PROP_HEALTH,
++      POWER_SUPPLY_PROP_TECHNOLOGY,
++      POWER_SUPPLY_PROP_VOLTAGE_AVG,
++      POWER_SUPPLY_PROP_CURRENT_AVG,
++      POWER_SUPPLY_PROP_CAPACITY,
++      POWER_SUPPLY_PROP_CAPACITY_LEVEL,
++      POWER_SUPPLY_PROP_TEMP,
++      POWER_SUPPLY_PROP_TEMP_AMBIENT,
++};
++
++/*********************************************************************
++ *            Initialisation
++ *********************************************************************/
++
++static struct platform_device *bat_pdev;
++
++static struct power_supply olpc_bat = {
++      .properties = olpc_bat_props,
++      .num_properties = ARRAY_SIZE(olpc_bat_props),
++      .get_property = olpc_bat_get_property,
++      .use_for_apm = 1,
++};
++
++static int __init olpc_bat_init(void)
++{
++      int ret = 0;
++      unsigned short tmp;
++
++      if (!request_region(0x380, 4, "olpc-battery")) {
++              ret = -EIO;
++              goto region_failed;
++      }
++
++      if (lock_ec()) {
++              ret = -EIO;
++              goto lock_failed;
++      }
++
++      tmp = read_ec_word(0xfe92);
++      unlock_ec();
++
++      if (tmp != 0x380) {
++              /* Doesn't look like OLPC EC */
++              ret = -ENODEV;
++              goto not_olpc_ec;
++      }
++
++      bat_pdev = platform_device_register_simple("olpc-battery", 0, NULL, 0);
++      if (IS_ERR(bat_pdev)) {
++              ret = PTR_ERR(bat_pdev);
++              goto pdev_failed;
++      }
++
++      ret = power_supply_register(&bat_pdev->dev, &olpc_ac);
++      if (ret)
++              goto ac_failed;
++
++      olpc_bat.name = bat_pdev->name;
++
++      ret = power_supply_register(&bat_pdev->dev, &olpc_bat);
++      if (ret)
++              goto battery_failed;
++
++      goto success;
++
++battery_failed:
++      power_supply_unregister(&olpc_ac);
++ac_failed:
++      platform_device_unregister(bat_pdev);
++pdev_failed:
++not_olpc_ec:
++lock_failed:
++      release_region(0x380, 4);
++region_failed:
++success:
++      return ret;
++}
++
++static void __exit olpc_bat_exit(void)
++{
++      power_supply_unregister(&olpc_bat);
++      power_supply_unregister(&olpc_ac);
++      platform_device_unregister(bat_pdev);
++      release_region(0x380, 4);
++      return;
++}
++
++module_init(olpc_bat_init);
++module_exit(olpc_bat_exit);
++
++MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Battery driver for One Laptop Per Child "
++                   "($100 laptop) board.");
+Index: linux-2.6.22/drivers/power/pda_power.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/power/pda_power.c     2007-08-23 12:13:52.000000000 +0200
+@@ -0,0 +1,263 @@
++/*
++ * Common power driver for PDAs and phones with one or two external
++ * power supplies (AC/USB) connected to main and backup batteries,
++ * and optional builtin charger.
++ *
++ * Copyright 2007 Anton Vorontsov <cbou@mail.ru>
++ *
++ * 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/module.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/power_supply.h>
++#include <linux/pda_power.h>
++#include <linux/timer.h>
++#include <linux/jiffies.h>
++
++static inline unsigned int get_irq_flags(struct resource *res)
++{
++      unsigned int flags = IRQF_DISABLED | IRQF_SHARED;
++
++      flags |= res->flags & IRQF_TRIGGER_MASK;
++
++      return flags;
++}
++
++static struct device *dev;
++static struct pda_power_pdata *pdata;
++static struct resource *ac_irq, *usb_irq;
++static struct timer_list charger_timer;
++static struct timer_list supply_timer;
++
++static int pda_power_get_property(struct power_supply *psy,
++                                  enum power_supply_property psp,
++                                  union power_supply_propval *val)
++{
++      switch (psp) {
++      case POWER_SUPPLY_PROP_ONLINE:
++              if (psy->type == POWER_SUPPLY_TYPE_MAINS)
++                      val->intval = pdata->is_ac_online ?
++                                    pdata->is_ac_online() : 0;
++              else
++                      val->intval = pdata->is_usb_online ?
++                                    pdata->is_usb_online() : 0;
++              break;
++      default:
++              return -EINVAL;
++      }
++      return 0;
++}
++
++static enum power_supply_property pda_power_props[] = {
++      POWER_SUPPLY_PROP_ONLINE,
++};
++
++static char *pda_power_supplied_to[] = {
++      "main-battery",
++      "backup-battery",
++};
++
++static struct power_supply pda_power_supplies[] = {
++      {
++              .name = "ac",
++              .type = POWER_SUPPLY_TYPE_MAINS,
++              .supplied_to = pda_power_supplied_to,
++              .num_supplicants = ARRAY_SIZE(pda_power_supplied_to),
++              .properties = pda_power_props,
++              .num_properties = ARRAY_SIZE(pda_power_props),
++              .get_property = pda_power_get_property,
++      },
++      {
++              .name = "usb",
++              .type = POWER_SUPPLY_TYPE_USB,
++              .supplied_to = pda_power_supplied_to,
++              .num_supplicants = ARRAY_SIZE(pda_power_supplied_to),
++              .properties = pda_power_props,
++              .num_properties = ARRAY_SIZE(pda_power_props),
++              .get_property = pda_power_get_property,
++      },
++};
++
++static void update_charger(void)
++{
++      if (!pdata->set_charge)
++              return;
++
++      if (pdata->is_ac_online && pdata->is_ac_online()) {
++              dev_dbg(dev, "charger on (AC)\n");
++              pdata->set_charge(PDA_POWER_CHARGE_AC);
++      }
++      else if (pdata->is_usb_online && pdata->is_usb_online()) {
++              dev_dbg(dev, "charger on (USB)\n");
++              pdata->set_charge(PDA_POWER_CHARGE_USB);
++      }
++      else {
++              dev_dbg(dev, "charger off\n");
++              pdata->set_charge(0);
++      }
++
++      return;
++}
++
++static void supply_timer_func(unsigned long irq)
++{
++      if (ac_irq && irq == ac_irq->start)
++              power_supply_changed(&pda_power_supplies[0]);
++      else if (usb_irq && irq == usb_irq->start)
++              power_supply_changed(&pda_power_supplies[1]);
++      return;
++}
++
++static void charger_timer_func(unsigned long irq)
++{
++      update_charger();
++
++      /* Okay, charger set. Now wait a bit before notifying supplicants,
++       * charge power should stabilize. */
++      supply_timer.data = irq;
++      mod_timer(&supply_timer,
++                jiffies + msecs_to_jiffies(pdata->wait_for_charger));
++      return;
++}
++
++static irqreturn_t power_changed_isr(int irq, void *unused)
++{
++      /* Wait a bit before reading ac/usb line status and setting charger,
++       * because ac/usb status readings may lag from irq. */
++      charger_timer.data = irq;
++      mod_timer(&charger_timer,
++                jiffies + msecs_to_jiffies(pdata->wait_for_status));
++      return IRQ_HANDLED;
++}
++
++static int pda_power_probe(struct platform_device *pdev)
++{
++      int ret = 0;
++
++      dev = &pdev->dev;
++
++      if (pdev->id != -1) {
++              dev_err(dev, "it's meaningless to register several "
++                      "pda_powers, use id = -1\n");
++              ret = -EINVAL;
++              goto wrongid;
++      }
++
++      pdata = pdev->dev.platform_data;
++
++      update_charger();
++
++      if (!pdata->wait_for_status)
++              pdata->wait_for_status = 500;
++
++      if (!pdata->wait_for_charger)
++              pdata->wait_for_charger = 500;
++
++      setup_timer(&charger_timer, charger_timer_func, 0);
++      setup_timer(&supply_timer, supply_timer_func, 0);
++
++      ac_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ac");
++      usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb");
++      if (!ac_irq && !usb_irq) {
++              dev_err(dev, "no ac/usb irq specified\n");
++              ret = -ENODEV;
++              goto noirqs;
++      }
++
++      if (pdata->supplied_to) {
++              pda_power_supplies[0].supplied_to = pdata->supplied_to;
++              pda_power_supplies[1].supplied_to = pdata->supplied_to;
++              pda_power_supplies[0].num_supplicants = pdata->num_supplicants;
++              pda_power_supplies[1].num_supplicants = pdata->num_supplicants;
++      }
++
++      ret = power_supply_register(&pdev->dev, &pda_power_supplies[0]);
++      if (ret) {
++              dev_err(dev, "failed to register %s power supply\n",
++                      pda_power_supplies[0].name);
++              goto supply0_failed;
++      }
++
++      ret = power_supply_register(&pdev->dev, &pda_power_supplies[1]);
++      if (ret) {
++              dev_err(dev, "failed to register %s power supply\n",
++                      pda_power_supplies[1].name);
++              goto supply1_failed;
++      }
++
++      if (ac_irq) {
++              ret = request_irq(ac_irq->start, power_changed_isr,
++                                get_irq_flags(ac_irq), ac_irq->name,
++                                &pda_power_supplies[0]);
++              if (ret) {
++                      dev_err(dev, "request ac irq failed\n");
++                      goto ac_irq_failed;
++              }
++      }
++
++      if (usb_irq) {
++              ret = request_irq(usb_irq->start, power_changed_isr,
++                                get_irq_flags(usb_irq), usb_irq->name,
++                                &pda_power_supplies[1]);
++              if (ret) {
++                      dev_err(dev, "request usb irq failed\n");
++                      goto usb_irq_failed;
++              }
++      }
++
++      goto success;
++
++usb_irq_failed:
++      if (ac_irq)
++              free_irq(ac_irq->start, &pda_power_supplies[0]);
++ac_irq_failed:
++      power_supply_unregister(&pda_power_supplies[1]);
++supply1_failed:
++      power_supply_unregister(&pda_power_supplies[0]);
++supply0_failed:
++noirqs:
++wrongid:
++success:
++      return ret;
++}
++
++static int pda_power_remove(struct platform_device *pdev)
++{
++      if (usb_irq)
++              free_irq(usb_irq->start, &pda_power_supplies[1]);
++      if (ac_irq)
++              free_irq(ac_irq->start, &pda_power_supplies[0]);
++      del_timer_sync(&charger_timer);
++      del_timer_sync(&supply_timer);
++      power_supply_unregister(&pda_power_supplies[1]);
++      power_supply_unregister(&pda_power_supplies[0]);
++      return 0;
++}
++
++static struct platform_driver pda_power_pdrv = {
++      .driver = {
++              .name = "pda-power",
++      },
++      .probe = pda_power_probe,
++      .remove = pda_power_remove,
++};
++
++static int __init pda_power_init(void)
++{
++      return platform_driver_register(&pda_power_pdrv);
++}
++
++static void __exit pda_power_exit(void)
++{
++      platform_driver_unregister(&pda_power_pdrv);
++      return;
++}
++
++module_init(pda_power_init);
++module_exit(pda_power_exit);
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>");
+Index: linux-2.6.22/drivers/power/pmu_battery.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/power/pmu_battery.c   2007-08-23 12:13:52.000000000 +0200
+@@ -0,0 +1,215 @@
++/*
++ * Battery class driver for Apple PMU
++ *
++ *    Copyright Â© 2006  David Woodhouse <dwmw2@infradead.org>
++ *
++ * 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/module.h>
++#include <linux/platform_device.h>
++#include <linux/err.h>
++#include <linux/power_supply.h>
++#include <linux/adb.h>
++#include <linux/pmu.h>
++
++static struct pmu_battery_dev {
++      struct power_supply bat;
++      struct pmu_battery_info *pbi;
++      char name[16];
++      int propval;
++} *pbats[PMU_MAX_BATTERIES];
++
++#define to_pmu_battery_dev(x) container_of(x, struct pmu_battery_dev, bat)
++
++/*********************************************************************
++ *            Power
++ *********************************************************************/
++
++static int pmu_get_ac_prop(struct power_supply *psy,
++                           enum power_supply_property psp,
++                           union power_supply_propval *val)
++{
++      switch (psp) {
++      case POWER_SUPPLY_PROP_ONLINE:
++              val->intval = (!!(pmu_power_flags & PMU_PWR_AC_PRESENT)) ||
++                            (pmu_battery_count == 0);
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++static enum power_supply_property pmu_ac_props[] = {
++      POWER_SUPPLY_PROP_ONLINE,
++};
++
++static struct power_supply pmu_ac = {
++      .name = "pmu-ac",
++      .type = POWER_SUPPLY_TYPE_MAINS,
++      .properties = pmu_ac_props,
++      .num_properties = ARRAY_SIZE(pmu_ac_props),
++      .get_property = pmu_get_ac_prop,
++};
++
++/*********************************************************************
++ *            Battery properties
++ *********************************************************************/
++
++static char *pmu_batt_types[] = {
++      "Smart", "Comet", "Hooper", "Unknown"
++};
++
++static char *pmu_bat_get_model_name(struct pmu_battery_info *pbi)
++{
++      switch (pbi->flags & PMU_BATT_TYPE_MASK) {
++      case PMU_BATT_TYPE_SMART:
++              return pmu_batt_types[0];
++      case PMU_BATT_TYPE_COMET:
++              return pmu_batt_types[1];
++      case PMU_BATT_TYPE_HOOPER:
++              return pmu_batt_types[2];
++      default: break;
++      }
++      return pmu_batt_types[3];
++}
++
++static int pmu_bat_get_property(struct power_supply *psy,
++                                enum power_supply_property psp,
++                                union power_supply_propval *val)
++{
++      struct pmu_battery_dev *pbat = to_pmu_battery_dev(psy);
++      struct pmu_battery_info *pbi = pbat->pbi;
++
++      switch (psp) {
++      case POWER_SUPPLY_PROP_STATUS:
++              if (pbi->flags & PMU_BATT_CHARGING)
++                      val->intval = POWER_SUPPLY_STATUS_CHARGING;
++              else
++                      val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
++              break;
++      case POWER_SUPPLY_PROP_PRESENT:
++              val->intval = !!(pbi->flags & PMU_BATT_PRESENT);
++              break;
++      case POWER_SUPPLY_PROP_MODEL_NAME:
++              val->strval = pmu_bat_get_model_name(pbi);
++              break;
++      case POWER_SUPPLY_PROP_ENERGY_AVG:
++              val->intval = pbi->charge     * 1000; /* mWh -> ÂµWh */
++              break;
++      case POWER_SUPPLY_PROP_ENERGY_FULL:
++              val->intval = pbi->max_charge * 1000; /* mWh -> ÂµWh */
++              break;
++      case POWER_SUPPLY_PROP_CURRENT_AVG:
++              val->intval = pbi->amperage   * 1000; /* mA -> ÂµA */
++              break;
++      case POWER_SUPPLY_PROP_VOLTAGE_AVG:
++              val->intval = pbi->voltage    * 1000; /* mV -> ÂµV */
++              break;
++      case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
++              val->intval = pbi->time_remaining;
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++static enum power_supply_property pmu_bat_props[] = {
++      POWER_SUPPLY_PROP_STATUS,
++      POWER_SUPPLY_PROP_PRESENT,
++      POWER_SUPPLY_PROP_MODEL_NAME,
++      POWER_SUPPLY_PROP_ENERGY_AVG,
++      POWER_SUPPLY_PROP_ENERGY_FULL,
++      POWER_SUPPLY_PROP_CURRENT_AVG,
++      POWER_SUPPLY_PROP_VOLTAGE_AVG,
++      POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
++};
++
++/*********************************************************************
++ *            Initialisation
++ *********************************************************************/
++
++static struct platform_device *bat_pdev;
++
++static int __init pmu_bat_init(void)
++{
++      int ret;
++      int i;
++
++      bat_pdev = platform_device_register_simple("pmu-battery",
++                                                 0, NULL, 0);
++      if (IS_ERR(bat_pdev)) {
++              ret = PTR_ERR(bat_pdev);
++              goto pdev_register_failed;
++      }
++
++      ret = power_supply_register(&bat_pdev->dev, &pmu_ac);
++      if (ret)
++              goto ac_register_failed;
++
++      for (i = 0; i < pmu_battery_count; i++) {
++              struct pmu_battery_dev *pbat = kzalloc(sizeof(*pbat),
++                                                     GFP_KERNEL);
++              if (!pbat)
++                      break;
++
++              sprintf(pbat->name, "PMU battery %d", i);
++              pbat->bat.name = pbat->name;
++              pbat->bat.properties = pmu_bat_props;
++              pbat->bat.num_properties = ARRAY_SIZE(pmu_bat_props);
++              pbat->bat.get_property = pmu_bat_get_property;
++              pbat->pbi = &pmu_batteries[i];
++
++              ret = power_supply_register(&bat_pdev->dev, &pbat->bat);
++              if (ret) {
++                      kfree(pbat);
++                      goto battery_register_failed;
++              }
++              pbats[i] = pbat;
++      }
++
++      goto success;
++
++battery_register_failed:
++      while (i--) {
++              if (!pbats[i])
++                      continue;
++              power_supply_unregister(&pbats[i]->bat);
++              kfree(pbats[i]);
++      }
++      power_supply_unregister(&pmu_ac);
++ac_register_failed:
++      platform_device_unregister(bat_pdev);
++pdev_register_failed:
++success:
++      return ret;
++}
++
++static void __exit pmu_bat_exit(void)
++{
++      int i;
++
++      for (i = 0; i < PMU_MAX_BATTERIES; i++) {
++              if (!pbats[i])
++                      continue;
++              power_supply_unregister(&pbats[i]->bat);
++              kfree(pbats[i]);
++      }
++      power_supply_unregister(&pmu_ac);
++      platform_device_unregister(bat_pdev);
++
++      return;
++}
++
++module_init(pmu_bat_init);
++module_exit(pmu_bat_exit);
++
++MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("PMU battery driver");
+Index: linux-2.6.22/drivers/power/power_supply_core.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/power/power_supply_core.c     2007-08-23 12:13:52.000000000 +0200
+@@ -0,0 +1,168 @@
++/*
++ *  Universal power supply monitor class
++ *
++ *  Copyright (c) 2007  Anton Vorontsov <cbou@mail.ru>
++ *  Copyright (c) 2004  Szabolcs Gyurko
++ *  Copyright (c) 2003  Ian Molton <spyro@f2s.com>
++ *
++ *  Modified: 2004, Oct     Szabolcs Gyurko
++ *
++ *  You may use this code as per GPL version 2
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/err.h>
++#include <linux/power_supply.h>
++#include "power_supply.h"
++
++struct class *power_supply_class;
++
++static void power_supply_changed_work(struct work_struct *work)
++{
++      struct power_supply *psy = container_of(work, struct power_supply,
++                                              changed_work);
++      int i;
++
++      dev_dbg(psy->dev, "%s\n", __FUNCTION__);
++
++      for (i = 0; i < psy->num_supplicants; i++) {
++              struct device *dev;
++
++              down(&power_supply_class->sem);
++              list_for_each_entry(dev, &power_supply_class->devices, node) {
++                      struct power_supply *pst = dev_get_drvdata(dev);
++
++                      if (!strcmp(psy->supplied_to[i], pst->name)) {
++                              if (pst->external_power_changed)
++                                      pst->external_power_changed(pst);
++                      }
++              }
++              up(&power_supply_class->sem);
++      }
++
++      power_supply_update_leds(psy);
++
++      kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE);
++
++      return;
++}
++
++void power_supply_changed(struct power_supply *psy)
++{
++      dev_dbg(psy->dev, "%s\n", __FUNCTION__);
++
++      schedule_work(&psy->changed_work);
++
++      return;
++}
++
++int power_supply_am_i_supplied(struct power_supply *psy)
++{
++      union power_supply_propval ret = {0,};
++      struct device *dev;
++
++      down(&power_supply_class->sem);
++      list_for_each_entry(dev, &power_supply_class->devices, node) {
++              struct power_supply *epsy = dev_get_drvdata(dev);
++              int i;
++
++              for (i = 0; i < epsy->num_supplicants; i++) {
++                      if (!strcmp(epsy->supplied_to[i], psy->name)) {
++                              if (epsy->get_property(epsy,
++                                        POWER_SUPPLY_PROP_ONLINE, &ret))
++                                      continue;
++                              if (ret.intval)
++                                      goto out;
++                      }
++              }
++      }
++out:
++      up(&power_supply_class->sem);
++
++      dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, ret.intval);
++
++      return ret.intval;
++}
++
++int power_supply_register(struct device *parent, struct power_supply *psy)
++{
++      int rc = 0;
++
++      psy->dev = device_create(power_supply_class, parent, 0,
++                               "%s", psy->name);
++      if (IS_ERR(psy->dev)) {
++              rc = PTR_ERR(psy->dev);
++              goto dev_create_failed;
++      }
++
++      dev_set_drvdata(psy->dev, psy);
++
++      INIT_WORK(&psy->changed_work, power_supply_changed_work);
++
++      rc = power_supply_create_attrs(psy);
++      if (rc)
++              goto create_attrs_failed;
++
++      rc = power_supply_create_triggers(psy);
++      if (rc)
++              goto create_triggers_failed;
++
++      power_supply_changed(psy);
++
++      goto success;
++
++create_triggers_failed:
++      power_supply_remove_attrs(psy);
++create_attrs_failed:
++      device_unregister(psy->dev);
++dev_create_failed:
++success:
++      return rc;
++}
++
++void power_supply_unregister(struct power_supply *psy)
++{
++      flush_scheduled_work();
++      power_supply_remove_triggers(psy);
++      power_supply_remove_attrs(psy);
++      device_unregister(psy->dev);
++      return;
++}
++
++static int __init power_supply_class_init(void)
++{
++      power_supply_class = class_create(THIS_MODULE, "power_supply");
++
++      if (IS_ERR(power_supply_class))
++              return PTR_ERR(power_supply_class);
++
++      power_supply_class->dev_uevent = power_supply_uevent;
++
++      return 0;
++}
++
++static void __exit power_supply_class_exit(void)
++{
++      class_destroy(power_supply_class);
++      return;
++}
++
++EXPORT_SYMBOL_GPL(power_supply_changed);
++EXPORT_SYMBOL_GPL(power_supply_am_i_supplied);
++EXPORT_SYMBOL_GPL(power_supply_register);
++EXPORT_SYMBOL_GPL(power_supply_unregister);
++
++/* exported for the APM Power driver, APM emulation */
++EXPORT_SYMBOL_GPL(power_supply_class);
++
++subsys_initcall(power_supply_class_init);
++module_exit(power_supply_class_exit);
++
++MODULE_DESCRIPTION("Universal power supply monitor class");
++MODULE_AUTHOR("Ian Molton <spyro@f2s.com>, "
++              "Szabolcs Gyurko, "
++              "Anton Vorontsov <cbou@mail.ru>");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.22/drivers/power/power_supply.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/power/power_supply.h  2007-08-23 12:13:52.000000000 +0200
+@@ -0,0 +1,42 @@
++/*
++ *  Functions private to power supply class
++ *
++ *  Copyright (c) 2007  Anton Vorontsov <cbou@mail.ru>
++ *  Copyright (c) 2004  Szabolcs Gyurko
++ *  Copyright (c) 2003  Ian Molton <spyro@f2s.com>
++ *
++ *  Modified: 2004, Oct     Szabolcs Gyurko
++ *
++ *  You may use this code as per GPL version 2
++ */
++
++#ifdef CONFIG_SYSFS
++
++extern int power_supply_create_attrs(struct power_supply *psy);
++extern void power_supply_remove_attrs(struct power_supply *psy);
++extern int power_supply_uevent(struct device *dev, char **envp, int num_envp,
++                               char *buffer, int buffer_size);
++
++#else
++
++static inline int power_supply_create_attrs(struct power_supply *psy)
++{ return 0; }
++static inline void power_supply_remove_attrs(struct power_supply *psy) {}
++#define power_supply_uevent NULL
++
++#endif /* CONFIG_SYSFS */
++
++#ifdef CONFIG_LEDS_TRIGGERS
++
++extern void power_supply_update_leds(struct power_supply *psy);
++extern int power_supply_create_triggers(struct power_supply *psy);
++extern void power_supply_remove_triggers(struct power_supply *psy);
++
++#else
++
++static inline void power_supply_update_leds(struct power_supply *psy) {}
++static inline int power_supply_create_triggers(struct power_supply *psy)
++{ return 0; }
++static inline void power_supply_remove_triggers(struct power_supply *psy) {}
++
++#endif /* CONFIG_LEDS_TRIGGERS */
+Index: linux-2.6.22/drivers/power/power_supply_leds.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/power/power_supply_leds.c     2007-08-23 12:13:52.000000000 +0200
+@@ -0,0 +1,188 @@
++/*
++ *  LEDs triggers for power supply class
++ *
++ *  Copyright (c) 2007  Anton Vorontsov <cbou@mail.ru>
++ *  Copyright (c) 2004  Szabolcs Gyurko
++ *  Copyright (c) 2003  Ian Molton <spyro@f2s.com>
++ *
++ *  Modified: 2004, Oct     Szabolcs Gyurko
++ *
++ *  You may use this code as per GPL version 2
++ */
++
++#include <linux/power_supply.h>
++
++/* If we have hwtimer trigger, then use it to blink charging LED */
++
++#if defined(CONFIG_LEDS_TRIGGER_HWTIMER) ||                  \
++               (defined(CONFIG_BATTERY_MODULE) &&            \
++                defined(CONFIG_LEDS_TRIGGER_HWTIMER_MODULE))
++       #define led_trigger_register_charging led_trigger_register_hwtimer
++       #define led_trigger_unregister_charging led_trigger_unregister_hwtimer
++#else
++       #define led_trigger_register_charging led_trigger_register_simple
++       #define led_trigger_unregister_charging led_trigger_unregister_simple
++#endif
++
++/* Battery specific LEDs triggers. */
++
++static void power_supply_update_bat_leds(struct power_supply *psy)
++{
++      union power_supply_propval status;
++
++      if (psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))
++              return;
++
++      dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, status.intval);
++
++      switch(status.intval) {
++      case POWER_SUPPLY_STATUS_FULL:
++              led_trigger_event(psy->charging_full_trig, LED_FULL);
++              led_trigger_event(psy->charging_trig, LED_OFF);
++              led_trigger_event(psy->full_trig, LED_FULL);
++              break;
++      case POWER_SUPPLY_STATUS_CHARGING:
++              led_trigger_event(psy->charging_full_trig, LED_FULL);
++              led_trigger_event(psy->charging_trig, LED_FULL);
++              led_trigger_event(psy->full_trig, LED_OFF);
++              break;
++      default:
++              led_trigger_event(psy->charging_full_trig, LED_OFF);
++              led_trigger_event(psy->charging_trig, LED_OFF);
++              led_trigger_event(psy->full_trig, LED_OFF);
++              break;
++      }
++
++      return;
++}
++
++static int power_supply_create_bat_triggers(struct power_supply *psy)
++{
++      int rc = 0;
++
++      psy->charging_full_trig_name = kmalloc(strlen(psy->name) +
++                                sizeof("-charging-or-full"), GFP_KERNEL);
++      if (!psy->charging_full_trig_name)
++              goto charging_full_failed;
++
++      psy->charging_trig_name = kmalloc(strlen(psy->name) +
++                                        sizeof("-charging"), GFP_KERNEL);
++      if (!psy->charging_trig_name)
++              goto charging_failed;
++
++      psy->full_trig_name = kmalloc(strlen(psy->name) +
++                                    sizeof("-full"), GFP_KERNEL);
++      if (!psy->full_trig_name)
++              goto full_failed;
++
++      strcpy(psy->charging_full_trig_name, psy->name);
++      strcat(psy->charging_full_trig_name, "-charging-or-full");
++      strcpy(psy->charging_trig_name, psy->name);
++      strcat(psy->charging_trig_name, "-charging");
++      strcpy(psy->full_trig_name, psy->name);
++      strcat(psy->full_trig_name, "-full");
++
++      led_trigger_register_simple(psy->charging_full_trig_name,
++                                  &psy->charging_full_trig);
++      led_trigger_register_charging(psy->charging_trig_name,
++                                    &psy->charging_trig);
++      led_trigger_register_simple(psy->full_trig_name,
++                                  &psy->full_trig);
++
++      goto success;
++
++full_failed:
++      kfree(psy->charging_trig_name);
++charging_failed:
++      kfree(psy->charging_full_trig_name);
++charging_full_failed:
++      rc = -ENOMEM;
++success:
++      return rc;
++}
++
++static void power_supply_remove_bat_triggers(struct power_supply *psy)
++{
++      led_trigger_unregister_simple(psy->charging_full_trig);
++      led_trigger_unregister_charging(psy->charging_trig);
++      led_trigger_unregister_simple(psy->full_trig);
++      kfree(psy->full_trig_name);
++      kfree(psy->charging_trig_name);
++      kfree(psy->charging_full_trig_name);
++      return;
++}
++
++/* Generated power specific LEDs triggers. */
++
++static void power_supply_update_gen_leds(struct power_supply *psy)
++{
++      union power_supply_propval online;
++
++      if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &online))
++              return;
++
++      dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, online.intval);
++
++      if (online.intval)
++              led_trigger_event(psy->online_trig, LED_FULL);
++      else
++              led_trigger_event(psy->online_trig, LED_OFF);
++
++      return;
++}
++
++static int power_supply_create_gen_triggers(struct power_supply *psy)
++{
++      int rc = 0;
++
++      psy->online_trig_name = kmalloc(strlen(psy->name) + sizeof("-online"),
++                                      GFP_KERNEL);
++      if (!psy->online_trig_name)
++              goto online_failed;
++
++      strcpy(psy->online_trig_name, psy->name);
++      strcat(psy->online_trig_name, "-online");
++
++      led_trigger_register_simple(psy->online_trig_name, &psy->online_trig);
++
++      goto success;
++
++online_failed:
++      rc = -ENOMEM;
++success:
++      return rc;
++}
++
++static void power_supply_remove_gen_triggers(struct power_supply *psy)
++{
++      led_trigger_unregister_simple(psy->online_trig);
++      kfree(psy->online_trig_name);
++      return;
++}
++
++/* Choice what triggers to create&update. */
++
++void power_supply_update_leds(struct power_supply *psy)
++{
++      if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
++              power_supply_update_bat_leds(psy);
++      else
++              power_supply_update_gen_leds(psy);
++      return;
++}
++
++int power_supply_create_triggers(struct power_supply *psy)
++{
++      if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
++              return power_supply_create_bat_triggers(psy);
++      return power_supply_create_gen_triggers(psy);
++}
++
++void power_supply_remove_triggers(struct power_supply *psy)
++{
++      if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
++              power_supply_remove_bat_triggers(psy);
++      else
++              power_supply_remove_gen_triggers(psy);
++      return;
++}
+Index: linux-2.6.22/drivers/power/power_supply_sysfs.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/power/power_supply_sysfs.c    2007-08-23 12:13:52.000000000 +0200
+@@ -0,0 +1,289 @@
++/*
++ *  Sysfs interface for the universal power supply monitor class
++ *
++ *  Copyright Â©  2007  David Woodhouse <dwmw2@infradead.org>
++ *  Copyright (c) 2007  Anton Vorontsov <cbou@mail.ru>
++ *  Copyright (c) 2004  Szabolcs Gyurko
++ *  Copyright (c) 2003  Ian Molton <spyro@f2s.com>
++ *
++ *  Modified: 2004, Oct     Szabolcs Gyurko
++ *
++ *  You may use this code as per GPL version 2
++ */
++
++#include <linux/ctype.h>
++#include <linux/power_supply.h>
++
++/*
++ * This is because the name "current" breaks the device attr macro.
++ * The "current" word resolvs to "(get_current())" so instead of
++ * "current" "(get_current())" appears in the sysfs.
++ *
++ * The source of this definition is the device.h which calls __ATTR
++ * macro in sysfs.h which calls the __stringify macro.
++ *
++ * Only modification that the name is not tried to be resolved
++ * (as a macro let's say).
++ */
++
++#define POWER_SUPPLY_ATTR(_name)                                        \
++{                                                                       \
++      .attr = { .name = #_name, .mode = 0444, .owner = THIS_MODULE }, \
++      .show = power_supply_show_property,                             \
++      .store = NULL,                                                  \
++}
++
++static struct device_attribute power_supply_attrs[];
++
++static ssize_t power_supply_show_property(struct device *dev,
++                                          struct device_attribute *attr,
++                                          char *buf) {
++      static char *status_text[] = {
++              "Unknown", "Charging", "Discharging", "Not charging", "Full"
++      };
++      static char *health_text[] = {
++              "Unknown", "Good", "Overheat", "Dead"
++      };
++      static char *technology_text[] = {
++              "Unknown", "NiMH", "Li-ion", "Li-poly"
++      };
++      static char *capacity_level_text[] = {
++              "Unknown", "Critical", "Low", "Normal", "High", "Full"
++      };
++      ssize_t ret;
++      struct power_supply *psy = dev_get_drvdata(dev);
++      const ptrdiff_t off = attr - power_supply_attrs;
++      union power_supply_propval value;
++
++      ret = psy->get_property(psy, off, &value);
++
++      if (ret < 0) {
++              dev_err(dev, "driver failed to report `%s' property\n",
++                      attr->attr.name);
++              return ret;
++      }
++
++      if (off == POWER_SUPPLY_PROP_STATUS)
++              return sprintf(buf, "%s\n", status_text[value.intval]);
++      else if (off == POWER_SUPPLY_PROP_HEALTH)
++              return sprintf(buf, "%s\n", health_text[value.intval]);
++      else if (off == POWER_SUPPLY_PROP_TECHNOLOGY)
++              return sprintf(buf, "%s\n", technology_text[value.intval]);
++      else if (off == POWER_SUPPLY_PROP_CAPACITY_LEVEL)
++              return sprintf(buf, "%s\n",
++                             capacity_level_text[value.intval]);
++      else if (off == POWER_SUPPLY_PROP_MODEL_NAME)
++              return sprintf(buf, "%s\n", value.strval);
++
++      return sprintf(buf, "%d\n", value.intval);
++}
++
++/* Must be in the same order as POWER_SUPPLY_PROP_* */
++static struct device_attribute power_supply_attrs[] = {
++      /* Properties of type `int' */
++      POWER_SUPPLY_ATTR(status),
++      POWER_SUPPLY_ATTR(health),
++      POWER_SUPPLY_ATTR(present),
++      POWER_SUPPLY_ATTR(online),
++      POWER_SUPPLY_ATTR(technology),
++      POWER_SUPPLY_ATTR(voltage_max_design),
++      POWER_SUPPLY_ATTR(voltage_min_design),
++      POWER_SUPPLY_ATTR(voltage_now),
++      POWER_SUPPLY_ATTR(voltage_avg),
++      POWER_SUPPLY_ATTR(current_now),
++      POWER_SUPPLY_ATTR(current_avg),
++      POWER_SUPPLY_ATTR(charge_full_design),
++      POWER_SUPPLY_ATTR(charge_empty_design),
++      POWER_SUPPLY_ATTR(charge_full),
++      POWER_SUPPLY_ATTR(charge_empty),
++      POWER_SUPPLY_ATTR(charge_now),
++      POWER_SUPPLY_ATTR(charge_avg),
++      POWER_SUPPLY_ATTR(energy_full_design),
++      POWER_SUPPLY_ATTR(energy_empty_design),
++      POWER_SUPPLY_ATTR(energy_full),
++      POWER_SUPPLY_ATTR(energy_empty),
++      POWER_SUPPLY_ATTR(energy_now),
++      POWER_SUPPLY_ATTR(energy_avg),
++      POWER_SUPPLY_ATTR(capacity),
++      POWER_SUPPLY_ATTR(capacity_level),
++      POWER_SUPPLY_ATTR(temp),
++      POWER_SUPPLY_ATTR(temp_ambient),
++      POWER_SUPPLY_ATTR(time_to_empty_now),
++      POWER_SUPPLY_ATTR(time_to_empty_avg),
++      POWER_SUPPLY_ATTR(time_to_full_now),
++      POWER_SUPPLY_ATTR(time_to_full_avg),
++      /* Properties of type `const char *' */
++      POWER_SUPPLY_ATTR(model_name),
++};
++
++static ssize_t power_supply_show_static_attrs(struct device *dev,
++                                              struct device_attribute *attr,
++                                              char *buf) {
++      static char *type_text[] = { "Battery", "UPS", "Mains", "USB" };
++      struct power_supply *psy = dev_get_drvdata(dev);
++
++      return sprintf(buf, "%s\n", type_text[psy->type]);
++}
++
++static struct device_attribute power_supply_static_attrs[] = {
++      __ATTR(type, 0444, power_supply_show_static_attrs, NULL),
++};
++
++int power_supply_create_attrs(struct power_supply *psy)
++{
++      int rc = 0;
++      int i, j;
++
++      for (i = 0; i < ARRAY_SIZE(power_supply_static_attrs); i++) {
++              rc = device_create_file(psy->dev,
++                          &power_supply_static_attrs[i]);
++              if (rc)
++                      goto statics_failed;
++      }
++
++      for (j = 0; j < psy->num_properties; j++) {
++              rc = device_create_file(psy->dev,
++                          &power_supply_attrs[psy->properties[j]]);
++              if (rc)
++                      goto dynamics_failed;
++      }
++
++      goto succeed;
++
++dynamics_failed:
++      while (j--)
++              device_remove_file(psy->dev,
++                         &power_supply_attrs[psy->properties[j]]);
++statics_failed:
++      while (i--)
++              device_remove_file(psy->dev,
++                         &power_supply_static_attrs[psy->properties[i]]);
++succeed:
++      return rc;
++}
++
++void power_supply_remove_attrs(struct power_supply *psy)
++{
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(power_supply_static_attrs); i++)
++              device_remove_file(psy->dev,
++                          &power_supply_static_attrs[i]);
++
++      for (i = 0; i < psy->num_properties; i++)
++              device_remove_file(psy->dev,
++                          &power_supply_attrs[psy->properties[i]]);
++
++      return;
++}
++
++static char *kstruprdup(const char *str, gfp_t gfp)
++{
++      char *ret, *ustr;
++
++      ustr = ret = kmalloc(strlen(str) + 1, gfp);
++
++      if (!ret)
++              return NULL;
++
++      while (*str)
++              *ustr++ = toupper(*str++);
++
++      *ustr = 0;
++
++      return ret;
++}
++
++int power_supply_uevent(struct device *dev, char **envp, int num_envp,
++                        char *buffer, int buffer_size)
++{
++      struct power_supply *psy = dev_get_drvdata(dev);
++      int i = 0, length = 0, ret = 0, j;
++      char *prop_buf;
++      char *attrname;
++
++      dev_dbg(dev, "uevent\n");
++
++      if (!psy) {
++              dev_dbg(dev, "No power supply yet\n");
++              return ret;
++      }
++
++      dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->name);
++
++      ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
++                           &length, "POWER_SUPPLY_NAME=%s", psy->name);
++      if (ret)
++              return ret;
++
++      prop_buf = (char *)get_zeroed_page(GFP_KERNEL);
++      if (!prop_buf)
++              return -ENOMEM;
++
++      for (j = 0; j < ARRAY_SIZE(power_supply_static_attrs); j++) {
++              struct device_attribute *attr;
++              char *line;
++
++              attr = &power_supply_static_attrs[j];
++
++              ret = power_supply_show_static_attrs(dev, attr, prop_buf);
++              if (ret < 0)
++                      goto out;
++
++              line = strchr(prop_buf, '\n');
++              if (line)
++                      *line = 0;
++
++              attrname = kstruprdup(attr->attr.name, GFP_KERNEL);
++              if (!attrname) {
++                      ret = -ENOMEM;
++                      goto out;
++              }
++
++              dev_dbg(dev, "Static prop %s=%s\n", attrname, prop_buf);
++
++              ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
++                                   &length, "POWER_SUPPLY_%s=%s",
++                                   attrname, prop_buf);
++              kfree(attrname);
++              if (ret)
++                      goto out;
++      }
++
++      dev_dbg(dev, "%zd dynamic props\n", psy->num_properties);
++
++      for (j = 0; j < psy->num_properties; j++) {
++              struct device_attribute *attr;
++              char *line;
++
++              attr = &power_supply_attrs[psy->properties[j]];
++
++              ret = power_supply_show_property(dev, attr, prop_buf);
++              if (ret < 0)
++                      goto out;
++
++              line = strchr(prop_buf, '\n');
++              if (line)
++                      *line = 0;
++
++              attrname = kstruprdup(attr->attr.name, GFP_KERNEL);
++              if (!attrname) {
++                      ret = -ENOMEM;
++                      goto out;
++              }
++
++              dev_dbg(dev, "prop %s=%s\n", attrname, prop_buf);
++
++              ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
++                                   &length, "POWER_SUPPLY_%s=%s",
++                                   attrname, prop_buf);
++              kfree(attrname);
++              if (ret)
++                      goto out;
++      }
++
++out:
++      free_page((unsigned long)prop_buf);
++
++      return ret;
++}
+Index: linux-2.6.22/drivers/power/simpad-battery.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/drivers/power/simpad-battery.c        2007-08-23 12:13:52.000000000 +0200
+@@ -0,0 +1,242 @@
++/*
++ *  linux/drivers/misc/simpad-battery.c
++ *
++ *  Copyright (C) 2005 Holger Hans Peter Freyther
++ *  Copyright (C) 2001 Juergen Messerer
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License.
++ *
++ * Read the Battery Level through the UCB1x00 chip. T-Sinuspad is
++ * unsupported for now.
++ *
++ */
++
++#include <linux/battery.h>
++#include <asm/dma.h>
++#include "ucb1x00.h"
++
++
++/*
++ * Conversion from AD -> mV
++ * 7.5V = 1023   7.3313mV/Digit
++ *
++ * 400 Units == 9.7V
++ * a     = ADC value
++ * 21    = ADC error
++ * 12600 = Divident to get 2*7.3242
++ * 860   = Divider to get 2*7.3242
++ * 170   = Voltagedrop over
++ */
++#define CALIBRATE_BATTERY(a)   ((((a + 21)*12600)/860) + 170)
++
++/*
++ * We have two types of batteries a small and a large one
++ * To get the right value we to distinguish between those two
++ * 450 Units == 15 V
++ */
++#define CALIBRATE_SUPPLY(a)   (((a) * 1500) / 45)
++#define MIN_SUPPLY            12000 /* Less then 12V means no powersupply */
++
++/*
++ * Charging Current
++ * if value is >= 50 then charging is on
++ */
++#define CALIBRATE_CHARGING(a)    (((a)* 1000)/(152/4)))
++
++struct simpad_battery_t {
++      struct battery  battery;
++      struct ucb1x00* ucb;
++
++        /*
++       * Variables for the values to one time support
++       * T-Sinuspad as well
++       */
++      int min_voltage;
++      int min_current;
++      int min_charge;
++
++      int max_voltage;
++      int max_current;
++      int max_charge;
++
++      int min_supply;
++      int charging_led_label;
++      int charging_max_label;
++      int batt_full;
++      int batt_low;
++      int batt_critical;
++      int batt_empty;
++};
++
++static int simpad_get_min_voltage(struct battery* _battery )
++{
++      struct simpad_battery_t* battery = (struct simpad_battery_t*)_battery;
++      return  battery->min_voltage;
++}
++
++static int simpad_get_min_current(struct battery* _battery)
++{
++      struct simpad_battery_t* battery = (struct simpad_battery_t*)_battery;
++      return battery->min_current;
++}
++
++static int simpad_get_min_charge(struct battery* _battery)
++{
++      struct simpad_battery_t* battery = (struct simpad_battery_t*)_battery;
++      return battery->min_charge;
++}
++
++static int simpad_get_max_voltage(struct battery* _battery)
++{
++      struct simpad_battery_t* battery = (struct simpad_battery_t*)_battery;
++      return battery->max_voltage;
++}
++
++static int simpad_get_max_current(struct battery* _battery)
++{
++      struct simpad_battery_t* battery = (struct simpad_battery_t*)_battery;
++      return battery->max_current;
++}
++
++static int simpad_get_max_charge(struct battery* _battery)
++{
++      struct simpad_battery_t* battery = (struct simpad_battery_t*)_battery;
++      return battery->max_charge;
++}
++
++static int simpad_get_temp(struct battery* _battery)
++{
++      return 0;
++}
++
++static int simpad_get_voltage(struct battery* _battery)
++{
++      int val;
++      struct simpad_battery_t* battery = (struct simpad_battery_t*)_battery;
++
++
++      ucb1x00_adc_enable(battery->ucb);
++      val = ucb1x00_adc_read(battery->ucb, UCB_ADC_INP_AD1, UCB_NOSYNC);
++      ucb1x00_adc_disable(battery->ucb);
++
++      return CALIBRATE_BATTERY(val);
++}
++
++static int simpad_get_current(struct battery* _battery)
++{
++      int val;
++      struct simpad_battery_t* battery = (struct simpad_battery_t*)_battery;
++
++      ucb1x00_adc_enable(battery->ucb);
++      val = ucb1x00_adc_read(battery->ucb, UCB_ADC_INP_AD3, UCB_NOSYNC);
++      ucb1x00_adc_disable(battery->ucb);
++
++      return val;
++}
++
++static int simpad_get_charge(struct battery* _battery)
++{
++      int val;
++      struct simpad_battery_t* battery = (struct simpad_battery_t*)_battery;
++
++      ucb1x00_adc_enable(battery->ucb);
++      val = ucb1x00_adc_read(battery->ucb, UCB_ADC_INP_AD2, UCB_NOSYNC);
++      ucb1x00_adc_disable(battery->ucb);
++
++      return CALIBRATE_SUPPLY(val);
++
++}
++
++static int simpad_get_status(struct battery* _battery)
++{
++      struct simpad_battery_t* battery = (struct simpad_battery_t*)(_battery);
++      int vcharger = simpad_get_voltage(_battery);
++      int icharger = simpad_get_current(_battery);
++
++      int status = BATTERY_STATUS_UNKNOWN;
++      if(icharger > battery->charging_led_label)
++              status = BATTERY_STATUS_CHARGING;
++      else if(vcharger > battery->min_supply)
++              status = BATTERY_STATUS_NOT_CHARGING;
++      else
++              status = BATTERY_STATUS_DISCHARGING;
++
++      return status;
++}
++
++static struct simpad_battery_t simpad_battery  = {
++      .battery = {
++              .get_min_voltage = simpad_get_min_voltage,
++              .get_min_current = simpad_get_min_current,
++              .get_min_charge  = simpad_get_min_charge,
++              .get_max_voltage = simpad_get_max_voltage,
++              .get_max_current = simpad_get_max_current,
++              .get_max_charge  = simpad_get_max_charge,
++              .get_temp        = simpad_get_temp,
++              .get_voltage     = simpad_get_voltage,
++              .get_current     = simpad_get_current,
++              .get_charge      = simpad_get_charge,
++              .get_status      = simpad_get_status,
++      },
++      .min_voltage = 0,
++      .min_current = 0,
++      .min_charge  = 0,
++      .max_voltage = 0,
++      .max_current = 0,
++      .max_charge  = 0,
++
++      .min_supply         = 1200,
++      .charging_led_label = 18,
++      .charging_max_label = 265,
++      .batt_full          = 8300,
++      .batt_low           = 7300,
++      .batt_critical      = 6800,
++      .batt_empty         = 6500,
++};
++
++
++
++/*
++ * UCB glue code
++ */
++static int ucb1x00_battery_add(struct class_device *dev)
++{
++      struct ucb1x00 *ucb = classdev_to_ucb1x00(dev);
++      simpad_battery.ucb  = ucb;
++
++      battery_class_register(&simpad_battery.battery);
++
++      return 0;
++}
++
++static void ucb1x00_battery_remove(struct class_device *dev)
++{
++      return battery_class_unregister(&simpad_battery.battery);
++}
++
++
++static struct ucb1x00_class_interface ucb1x00_battery_interface = {
++      .interface   = {
++              .add    = ucb1x00_battery_add,
++              .remove = ucb1x00_battery_remove,
++      },
++};
++
++
++static int __init battery_register(void)
++{
++      return ucb1x00_register_interface(&ucb1x00_battery_interface);
++}
++
++static void __exit battery_unregister(void)
++{
++      ucb1x00_unregister_interface(&ucb1x00_battery_interface);
++}
++
++module_init(battery_register);
++module_exit(battery_unregister);
++
++MODULE_AUTHOR("Holger Hans Peter Freyther");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.22/arch/arm/Kconfig
+===================================================================
+--- linux-2.6.22.orig/arch/arm/Kconfig 2007-08-23 12:17:42.000000000 +0200
++++ linux-2.6.22/arch/arm/Kconfig      2007-08-23 12:22:28.000000000 +0200
+@@ -1016,6 +1016,8 @@
+ source "drivers/w1/Kconfig"
++source "drivers/power/Kconfig"
++
+ source "drivers/hwmon/Kconfig"
+ #source "drivers/l3/Kconfig"
+Index: linux-2.6.22/drivers/Kconfig
+===================================================================
+--- linux-2.6.22.orig/drivers/Kconfig  2007-08-23 12:21:27.000000000 +0200
++++ linux-2.6.22/drivers/Kconfig       2007-08-23 12:22:03.000000000 +0200
+@@ -54,6 +54,8 @@
+ source "drivers/w1/Kconfig"
++source "drivers/power/Kconfig"
++
+ source "drivers/hwmon/Kconfig"
+ source "drivers/mfd/Kconfig"
+Index: linux-2.6.22/drivers/Makefile
+===================================================================
+--- linux-2.6.22.orig/drivers/Makefile 2007-08-23 12:33:58.000000000 +0200
++++ linux-2.6.22/drivers/Makefile      2007-08-23 12:34:34.000000000 +0200
+@@ -61,6 +61,7 @@
+ obj-$(CONFIG_RTC_LIB)         += rtc/
+ obj-y                         += i2c/
+ obj-$(CONFIG_W1)              += w1/
++obj-$(CONFIG_POWER_SUPPLY)    += power/
+ obj-$(CONFIG_HWMON)           += hwmon/
+ obj-$(CONFIG_PHONE)           += telephony/
+ obj-$(CONFIG_MD)              += md/
+Index: linux-2.6.22/include/linux/power_supply.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.22/include/linux/power_supply.h  2007-08-23 12:37:10.000000000 +0200
+@@ -0,0 +1,175 @@
++/*
++ *  Universal power supply monitor class
++ *
++ *  Copyright (c) 2007  Anton Vorontsov <cbou@mail.ru>
++ *  Copyright (c) 2004  Szabolcs Gyurko
++ *  Copyright (c) 2003  Ian Molton <spyro@f2s.com>
++ *
++ *  Modified: 2004, Oct     Szabolcs Gyurko
++ *
++ *  You may use this code as per GPL version 2
++ */
++
++#ifndef __LINUX_POWER_SUPPLY_H__
++#define __LINUX_POWER_SUPPLY_H__
++
++#include <linux/device.h>
++#include <linux/workqueue.h>
++#include <linux/leds.h>
++
++/*
++ * All voltages, currents, charges, energies, time and temperatures in uV,
++ * uA, uAh, uWh, seconds and tenths of degree Celsius unless otherwise
++ * stated. It's driver's job to convert its raw values to units in which
++ * this class operates.
++ */
++
++/*
++ * For systems where the charger determines the maximum battery capacity
++ * the min and max fields should be used to present these values to user
++ * space. Unused/unknown fields will not appear in sysfs.
++ */
++
++enum {
++      POWER_SUPPLY_STATUS_UNKNOWN = 0,
++      POWER_SUPPLY_STATUS_CHARGING,
++      POWER_SUPPLY_STATUS_DISCHARGING,
++      POWER_SUPPLY_STATUS_NOT_CHARGING,
++      POWER_SUPPLY_STATUS_FULL,
++};
++
++enum {
++      POWER_SUPPLY_HEALTH_UNKNOWN = 0,
++      POWER_SUPPLY_HEALTH_GOOD,
++      POWER_SUPPLY_HEALTH_OVERHEAT,
++      POWER_SUPPLY_HEALTH_DEAD,
++};
++
++enum {
++      POWER_SUPPLY_TECHNOLOGY_UNKNOWN = 0,
++      POWER_SUPPLY_TECHNOLOGY_NIMH,
++      POWER_SUPPLY_TECHNOLOGY_LION,
++      POWER_SUPPLY_TECHNOLOGY_LIPO,
++};
++
++enum {
++      POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN = 0,
++      POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL,
++      POWER_SUPPLY_CAPACITY_LEVEL_LOW,
++      POWER_SUPPLY_CAPACITY_LEVEL_NORMAL,
++      POWER_SUPPLY_CAPACITY_LEVEL_HIGH,
++      POWER_SUPPLY_CAPACITY_LEVEL_FULL,
++};
++
++enum power_supply_property {
++      /* Properties of type `int' */
++      POWER_SUPPLY_PROP_STATUS = 0,
++      POWER_SUPPLY_PROP_HEALTH,
++      POWER_SUPPLY_PROP_PRESENT,
++      POWER_SUPPLY_PROP_ONLINE,
++      POWER_SUPPLY_PROP_TECHNOLOGY,
++      POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
++      POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
++      POWER_SUPPLY_PROP_VOLTAGE_NOW,
++      POWER_SUPPLY_PROP_VOLTAGE_AVG,
++      POWER_SUPPLY_PROP_CURRENT_NOW,
++      POWER_SUPPLY_PROP_CURRENT_AVG,
++      POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
++      POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN,
++      POWER_SUPPLY_PROP_CHARGE_FULL,
++      POWER_SUPPLY_PROP_CHARGE_EMPTY,
++      POWER_SUPPLY_PROP_CHARGE_NOW,
++      POWER_SUPPLY_PROP_CHARGE_AVG,
++      POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
++      POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN,
++      POWER_SUPPLY_PROP_ENERGY_FULL,
++      POWER_SUPPLY_PROP_ENERGY_EMPTY,
++      POWER_SUPPLY_PROP_ENERGY_NOW,
++      POWER_SUPPLY_PROP_ENERGY_AVG,
++      POWER_SUPPLY_PROP_CAPACITY, /* in percents! */
++      POWER_SUPPLY_PROP_CAPACITY_LEVEL,
++      POWER_SUPPLY_PROP_TEMP,
++      POWER_SUPPLY_PROP_TEMP_AMBIENT,
++      POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
++      POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
++      POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
++      POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
++      /* Properties of type `const char *' */
++      POWER_SUPPLY_PROP_MODEL_NAME,
++};
++
++enum power_supply_type {
++      POWER_SUPPLY_TYPE_BATTERY = 0,
++      POWER_SUPPLY_TYPE_UPS,
++      POWER_SUPPLY_TYPE_MAINS,
++      POWER_SUPPLY_TYPE_USB,
++};
++
++union power_supply_propval {
++      int intval;
++      const char *strval;
++};
++
++struct power_supply {
++      const char *name;
++      enum power_supply_type type;
++      enum power_supply_property *properties;
++      size_t num_properties;
++
++      char **supplied_to;
++      size_t num_supplicants;
++
++      int (*get_property)(struct power_supply *psy,
++                          enum power_supply_property psp,
++                          union power_supply_propval *val);
++      void (*external_power_changed)(struct power_supply *psy);
++
++      /* For APM emulation, think legacy userspace. */
++      int use_for_apm;
++
++      /* private */
++      struct device *dev;
++      struct work_struct changed_work;
++
++#ifdef CONFIG_LEDS_TRIGGERS
++      struct led_trigger *charging_full_trig;
++      char *charging_full_trig_name;
++      struct led_trigger *charging_trig;
++      char *charging_trig_name;
++      struct led_trigger *full_trig;
++      char *full_trig_name;
++      struct led_trigger *online_trig;
++      char *online_trig_name;
++#endif
++};
++
++/*
++ * This is recommended structure to specify static power supply parameters.
++ * Generic one, parametrizable for different power supplies. Power supply
++ * class itself does not use it, but that's what implementing most platform
++ * drivers, should try reuse for consistency.
++ */
++
++struct power_supply_info {
++      const char *name;
++      int technology;
++      int voltage_max_design;
++      int voltage_min_design;
++      int charge_full_design;
++      int charge_empty_design;
++      int energy_full_design;
++      int energy_empty_design;
++      int use_for_apm;
++};
++
++extern void power_supply_changed(struct power_supply *psy);
++extern int power_supply_am_i_supplied(struct power_supply *psy);
++
++extern int power_supply_register(struct device *parent,
++                                 struct power_supply *psy);
++extern void power_supply_unregister(struct power_supply *psy);
++
++/* For APM emulation, think legacy userspace. */
++extern struct class *power_supply_class;
++
++#endif /* __LINUX_POWER_SUPPLY_H__ */
index 237fd5ec85cb7f038a887a917df65e250004d65d..bd67d677c43f167b8876e0189146e3c7e1c2e6cd 100644 (file)
@@ -51,6 +51,7 @@ SRC_URI = "http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.22.tar.bz2 \
            file://connectplus-remove-ide-HACK.patch;patch=1;status=hack \
            file://squashfs3.0-2.6.15.patch;patch=1;status=external \
            file://vesafb-tng-1.0-rc2-2.6.20-rc2.patch;patch=1;status=external \
+          file://pda-power.patch;patch=1 \
            file://defconfig-c7x0 \
            file://defconfig-hx2000 \
            file://defconfig-collie \