From 827e06683409ebd8f1f7b0a8da9bc5c17d4dfefa Mon Sep 17 00:00:00 2001
From: David Heidelberger <david.heidelberger@ixit.cz>
Date: Sun, 10 Nov 2013 21:46:42 +0100
Subject: [PATCH] pxa270: pocket loox c550 support agaist 3.8 v5

---
 arch/arm/Kconfig                              |   1 -
 arch/arm/mach-pxa/Kconfig                     |   8 +
 arch/arm/mach-pxa/Makefile                    |   1 +
 arch/arm/mach-pxa/Makefile.boot               |   5 +
 arch/arm/mach-pxa/include/mach/loox550-gpio.h |  96 ++++++
 arch/arm/mach-pxa/include/mach/loox550.h      |  30 ++
 arch/arm/mach-pxa/include/mach/loox5xx_leds.h |  27 ++
 arch/arm/mach-pxa/include/mach/map.h          |  36 +++
 arch/arm/mach-pxa/include/mach/pxa-pm_ll.h    |   6 +
 arch/arm/mach-pxa/include/mach/pxa2xx-regs.h  |  13 +
 arch/arm/mach-pxa/loox550/Kconfig             |  45 +++
 arch/arm/mach-pxa/loox550/Makefile            |  10 +
 arch/arm/mach-pxa/loox550/loox550-cpld.h      | 163 ++++++++++
 arch/arm/mach-pxa/loox550/loox550.c           | 351 +++++++++++++++++++++
 arch/arm/mach-pxa/loox550/loox550_battery.c   | 190 ++++++++++++
 arch/arm/mach-pxa/loox550/loox550_cpld.c      | 427 ++++++++++++++++++++++++++
 arch/arm/mach-pxa/loox550/loox550_flash.c     |  54 ++++
 arch/arm/mach-pxa/loox550/loox550_flash_old.c |  87 ++++++
 arch/arm/mach-pxa/loox550/loox550_pm.c        | 322 +++++++++++++++++++
 arch/arm/mach-pxa/loox550/loox5xx_leds.c      | 379 +++++++++++++++++++++++
 arch/arm/mach-pxa/loox550/looxn560_pm.c       | 106 +++++++
 arch/arm/tools/mach-types                     |   1 +
 drivers/video/backlight/Makefile              |   2 +
 drivers/video/backlight/loox550_bl.c          | 162 ++++++++++
 drivers/video/backlight/loox550_lcd.c         | 167 ++++++++++
 25 files changed, 2688 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-pxa/include/mach/loox550-gpio.h
 create mode 100644 arch/arm/mach-pxa/include/mach/loox550.h
 create mode 100644 arch/arm/mach-pxa/include/mach/loox5xx_leds.h
 create mode 100644 arch/arm/mach-pxa/include/mach/map.h
 create mode 100644 arch/arm/mach-pxa/include/mach/pxa-pm_ll.h
 create mode 100644 arch/arm/mach-pxa/loox550/Kconfig
 create mode 100644 arch/arm/mach-pxa/loox550/Makefile
 create mode 100644 arch/arm/mach-pxa/loox550/loox550-cpld.h
 create mode 100644 arch/arm/mach-pxa/loox550/loox550.c
 create mode 100644 arch/arm/mach-pxa/loox550/loox550_battery.c
 create mode 100644 arch/arm/mach-pxa/loox550/loox550_cpld.c
 create mode 100644 arch/arm/mach-pxa/loox550/loox550_flash.c
 create mode 100644 arch/arm/mach-pxa/loox550/loox550_flash_old.c
 create mode 100644 arch/arm/mach-pxa/loox550/loox550_pm.c
 create mode 100644 arch/arm/mach-pxa/loox550/loox5xx_leds.c
 create mode 100644 arch/arm/mach-pxa/loox550/looxn560_pm.c
 create mode 100644 drivers/video/backlight/loox550_bl.c
 create mode 100644 drivers/video/backlight/loox550_lcd.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 67874b8..fec7c18 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -661,7 +661,6 @@ config ARCH_PXA
 	select ARCH_MTD_XIP
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_CPU_SUSPEND if PM
-	select AUTO_ZRELADDR
 	select CLKDEV_LOOKUP
 	select CLKSRC_MMIO
 	select GENERIC_CLOCKEVENTS
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 86eec41..08be68e 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -343,6 +343,13 @@ config MACH_MP900C
 	bool "Nec Mobilepro 900/c"
 	select PXA25x
 
+config MACH_LOOX550
+        bool "Fujitsu-Siemens PocketLoox 550 PDA device"
+        select PXA27x
+        select HTC_EGPIO
+	select IWMMXT
+        select PXA_SUSPEND_SAVE_EXTRA_REGS
+
 config ARCH_PXA_PALM
 	bool "PXA based Palm PDAs"
 	select HAVE_PWM
@@ -696,4 +703,5 @@ config PXA_HAVE_ISA_IRQS
 config PXA310_ULPI
 	bool
 
+source "arch/arm/mach-pxa/loox550/Kconfig"
 endif
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 12c5005..44dd92d 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_MACH_SAAR)		+= saar.o
 # 3rd Party Dev Platforms
 obj-$(CONFIG_ARCH_PXA_IDP)	+= idp.o
 obj-$(CONFIG_ARCH_VIPER)	+= viper.o
+obj-$(CONFIG_MACH_LOOX550)      += loox550/
 obj-$(CONFIG_MACH_ARCOM_ZEUS)	+= zeus.o
 obj-$(CONFIG_MACH_BALLOON3)	+= balloon3.o
 obj-$(CONFIG_MACH_CSB726)	+= csb726.o
diff --git a/arch/arm/mach-pxa/Makefile.boot b/arch/arm/mach-pxa/Makefile.boot
index 2c1ae92..96ac9d6 100644
--- a/arch/arm/mach-pxa/Makefile.boot
+++ b/arch/arm/mach-pxa/Makefile.boot
@@ -1,2 +1,7 @@
    zreladdr-y	+= 0xa0008000
 
+ifeq ($(CONFIG_MACH_LOOX550),y)
+   zreladdr-y   :=      $(CONFIG_PHYS_OFFSET)+0x8000
+endif
+
+
diff --git a/arch/arm/mach-pxa/include/mach/loox550-gpio.h b/arch/arm/mach-pxa/include/mach/loox550-gpio.h
new file mode 100644
index 0000000..3466b3f
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/loox550-gpio.h
@@ -0,0 +1,96 @@
+/*
+ * mach/loox550-gpio.h
+ * 
+ * Loox 550 GPIO list
+ * Reused the hx4700-gpio.h file as a template.
+ *
+ * History:
+ */
+
+/*
+ * !!! ATTENTION !!!
+ *
+ * Following GPIOs definitions are taken from another PDA header (hx4700).
+ * We should check them all, to make sure that they aren't misused.
+ * My suggestion is to mark all GPIOs that we are sure or unsure with some comment
+ * so if you are sure of some GPIO, please add some comment after its definition!
+ *
+ * THANKS!
+ * Tomasz Figa <tom3q@staszic.waw.pl>
+ *
+ * Note (18.08.2008):	tom3q:	I have marked all the GPIOs we are sure with their directions and descriptions
+ *				if you find the meaning of some GPIO, please mark it following the scheme:
+ 				// DIR - sure - description
+ 				All the GPIOs marked as UNKNOWN are just unknown... (Don't look at their name)
+ */
+
+#ifndef _LOOX550_GPIO_H_
+#define _LOOX550_GPIO_H_
+
+// CPLD
+#define LOOX5XX_EGPIO_BASE                      PXA_NR_BUILTIN_GPIO
+
+#define LOOX5XX_EGPIO_LED_1                     (LOOX5XX_EGPIO_BASE + 1*16 + 0)
+#define LOOX5XX_EGPIO_LED_2                     (LOOX5XX_EGPIO_BASE + 1*16 + 1)
+#define LOOX5XX_EGPIO_LED_3                     (LOOX5XX_EGPIO_BASE + 1*16 + 2)
+
+#define LOOX5XX_EGPIO_LED_4                     (LOOX5XX_EGPIO_BASE + 2*16 + 0)
+#define LOOX5XX_EGPIO_LED_5                     (LOOX5XX_EGPIO_BASE + 2*16 + 1)
+#define LOOX5XX_EGPIO_LED_6                     (LOOX5XX_EGPIO_BASE + 2*16 + 2)
+
+#define LOOX5XX_EGPIO_LED_7                     (LOOX5XX_EGPIO_BASE + 3*16 + 0)
+
+/*
+ * GPIOs operating as Application-Specific GPIO
+ */
+
+#define GPIO_NR_LOOXC550_KEYPWR                 0
+
+#define GPIO_NR_LOOXC550_BATTCOVER              4
+
+#define GPIO_NR_LOOXC550_AC_IN_N                9
+
+#define GPIO_NR_LOOXC550_BATTERY_FULL_N         11 //virstud
+
+#define GPIO_NR_LOOXC550_USB_DETECT_N           13
+
+#define GPIO_NR_LOOXC550_SD_RO                  15
+
+#define GPIO_NR_LOOXC550_BT_RESET1              22
+
+#define GPIO_NR_LOOXC550_GPS_PWRON              53
+
+#define GPIO_NR_LOOXC550_USB_PULLUP             57
+
+#define GPIO_NR_LOOXC550_SD_DETECT              78
+
+#define GPIO_NR_LOOXC550_GPS_IR_MUX             81
+
+#define GPIO_NR_LOOXC550_HP_JACK                93
+#define GPIO_NR_LOOXC550_TOUCHPANEL_IRQ_N       94
+
+#define GPIO_NR_LOOXC550_KP_MKIN3               97
+#define GPIO_NR_LOOXC550_KP_MKIN4               98
+#define GPIO_NR_LOOXC550_CHARGE_EN_N            99
+
+
+#define GPIO_NR_LOOXC550_KP_MKIN0               100
+#define GPIO_NR_LOOXC550_KP_MKIN1               101
+#define GPIO_NR_LOOXC550_KP_MKIN2               102
+#define GPIO_NR_LOOXC550_KP_MKOUT0              103
+#define GPIO_NR_LOOXC550_KP_MKOUT1              104
+
+#define GPIO_NR_LOOXC550_USB_CHARGE_RATE_N      107
+#define GPIO_NR_LOOXC550_SD_POWER               108
+
+#define GPIO_NR_LOOXC550_KP_MKIN0_MD            (GPIO_NR_LOOXC550_KP_MKIN0 | GPIO_ALT_FN_1_IN)
+#define GPIO_NR_LOOXC550_KP_MKIN1_MD            (GPIO_NR_LOOXC550_KP_MKIN1 | GPIO_ALT_FN_1_IN)
+#define GPIO_NR_LOOXC550_KP_MKIN2_MD            (GPIO_NR_LOOXC550_KP_MKIN2 | GPIO_ALT_FN_1_IN)
+#define GPIO_NR_LOOXC550_KP_MKIN3_MD            (GPIO_NR_LOOXC550_KP_MKIN3 | GPIO_ALT_FN_3_IN)
+#define GPIO_NR_LOOXC550_KP_MKIN4_MD            (GPIO_NR_LOOXC550_KP_MKIN4 | GPIO_ALT_FN_3_IN)
+
+#define GPIO_NR_LOOXC550_KP_MKOUT0_MD           (GPIO_NR_LOOXC550_KP_MKOUT0 | GPIO_ALT_FN_2_OUT)
+#define GPIO_NR_LOOXC550_KP_MKOUT1_MD           (GPIO_NR_LOOXC550_KP_MKOUT1 | GPIO_ALT_FN_2_OUT)
+
+
+#endif /* _LOOX550_GPIO_H */
diff --git a/arch/arm/mach-pxa/include/mach/loox550.h b/arch/arm/mach-pxa/include/mach/loox550.h
new file mode 100644
index 0000000..1e99b6b
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/loox550.h
@@ -0,0 +1,30 @@
+/*
+ * include/asm/arm/arch-pxa/loox720.h
+ */
+
+#ifndef _LOOX720_H_
+#define _LOOX720_H_
+
+/* Loox 720 general header
+ */
+
+struct loox720_bt_funcs {
+        void (*configure) ( int state );
+};
+
+#endif /* _LOOX720_H_ */
+
+/*
+ * Loox 720 Leds
+ */
+
+#define LOOX720_LED_LEFT 0
+#define LOOX720_LED_RIGHT 1
+#define LOOX720_LED_COLOR_A 1
+#define LOOX720_LED_COLOR_B 2
+#define LOOX720_LED_COLOR_C 3
+#define LOOX720_LED_BLINK 4
+#define LOOX720_LED_BLINK_ALT 12
+
+extern void loox720_enable_led(int led, int mode);
+extern void loox720_disable_led(int led, int mode);
diff --git a/arch/arm/mach-pxa/include/mach/loox5xx_leds.h b/arch/arm/mach-pxa/include/mach/loox5xx_leds.h
new file mode 100644
index 0000000..99e07bb
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/loox5xx_leds.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Leds support for Fujitsu-Siemens Loox 5xx PDAs
+ *
+ * Evgeny Chukreev <akshaal@akshaal.info>   http://www.akshaal.info
+ *
+ */
+
+#ifndef _LOOX5XX_LEDS_H_
+#define _LOOX5XX_LEDS_H_
+
+#define LOOX5XX_LED_KEYBOARD        1
+#define LOOX5XX_LED_LEFT_GREEN      2
+#define LOOX5XX_LED_LEFT_BLUE       4
+#define LOOX5XX_LED_LEFT_ORANGE     8
+#define LOOX5XX_LED_RIGHT_GREEN     16
+
+// These functions are for leds having two states
+extern void loox5xx_enable_leds (u32 leds);
+extern void loox5xx_disable_leds (u32 leds);
+
+// Power led has three states
+extern void loox5xx_enable_power_led (void);
+extern void loox5xx_disable_power_led (void);
+extern void loox5xx_blink_power_led (void);
+
+#endif /* _LOOX720_H_ */
diff --git a/arch/arm/mach-pxa/include/mach/map.h b/arch/arm/mach-pxa/include/mach/map.h
new file mode 100644
index 0000000..7ef3c83
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/map.h
@@ -0,0 +1,36 @@
+/*
+ *  linux/include/asm-arm/map.h
+ *
+ *  Copyright (C) 1999-2000 Russell King
+ *
+ * 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.
+ *
+ *  Page table mapping constructs and function prototypes
+ */
+#include <asm/io.h>
+
+struct map_desc {
+	unsigned long virtual;
+	unsigned long pfn;
+	unsigned long length;
+	unsigned int type;
+};
+
+/* types 0-3 are defined in asm/io.h */
+#define MT_CACHECLEAN		4
+#define MT_MINICLEAN		5
+#define MT_LOW_VECTORS		6
+#define MT_HIGH_VECTORS		7
+#define MT_MEMORY		8
+#define MT_ROM			9
+
+#define MT_NONSHARED_DEVICE	MT_DEVICE_NONSHARED
+#define MT_IXP2000_DEVICE	MT_DEVICE_IXP2000
+
+#ifdef CONFIG_MMU
+extern void iotable_init(struct map_desc *, int);
+#else
+#define iotable_init(map,num)	do { } while (0)
+#endif
diff --git a/arch/arm/mach-pxa/include/mach/pxa-pm_ll.h b/arch/arm/mach-pxa/include/mach/pxa-pm_ll.h
new file mode 100644
index 0000000..638ed2f
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/pxa-pm_ll.h
@@ -0,0 +1,6 @@
+struct pxa_ll_pm_ops {
+	void (*suspend)(unsigned long);
+	void (*resume)(void);
+};
+
+extern struct pxa_ll_pm_ops *pxa_pm_set_ll_ops(struct pxa_ll_pm_ops *new_ops);
diff --git a/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h b/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h
index ee6ced1..028d055 100644
--- a/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h
+++ b/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h
@@ -74,6 +74,19 @@
 #define PCMD30	__REG(0x40F00080 + 30 * 4)
 #define PCMD31	__REG(0x40F00080 + 31 * 4)
 
+/*
+ * Pulse Width Modulator
+ */
+
+#define PWM_CTRL0      __REG(0x40B00000)  /* PWM 0 Control Register */
+#define PWM_PWDUTY0    __REG(0x40B00004)  /* PWM 0 Duty Cycle Register */
+#define PWM_PERVAL0    __REG(0x40B00008)  /* PWM 0 Period Control Register */
+
+#define PWM_CTRL1      __REG(0x40C00000)  /* PWM 1Control Register */
+#define PWM_PWDUTY1    __REG(0x40C00004)  /* PWM 1 Duty Cycle Register */
+#define PWM_PERVAL1    __REG(0x40C00008)  /* PWM 1 Period Control Register */
+
+
 #define PCMD_MBC	(1<<12)
 #define PCMD_DCE	(1<<11)
 #define PCMD_LC	(1<<10)
diff --git a/arch/arm/mach-pxa/loox550/Kconfig b/arch/arm/mach-pxa/loox550/Kconfig
new file mode 100644
index 0000000..f7cbba4
--- /dev/null
+++ b/arch/arm/mach-pxa/loox550/Kconfig
@@ -0,0 +1,45 @@
+menu "Fujitsu-Siemens PocketLoox 550 configuration"
+    depends on MACH_LOOX550
+
+config LOOX550_LCD
+    bool "FSC Loox 550 LCD"
+    select FB
+    select FB_BACKLIGHT
+    select BACKLIGHT_LOOX550
+    select LCD_CLASS_DEVICE
+    depends on MACH_LOOX550
+    help
+        This driver provides support for changing power and brightness
+        on Loox 550 LCD display.
+
+config LOOX550_BATTERY
+    bool "FSC Loox 550 Battery support (say Y!)"
+    depends on MACH_LOOX550
+    default y
+    select POWER_SUPPLY
+    select BATTERY_LOOX550
+    help
+        FSC Loox 550/560 power/battery support. You really should say Y here,
+        to get charging on empty battery, AC/USB charging capabilities etc
+
+
+config LOOX550_BUTTONS
+    bool "FSC Loox 550 Buttons"
+    depends on MACH_LOOX550
+    select INPUT_KEYBOARD
+    select KEYBOARD_GPIO
+    select KEYBOARD_PXA27x
+    help
+        FSC Loox 550 buttons support. Including power button.
+
+config LOOX550_FLASH
+    tristate "FSC Loox 550 Flash ROM"
+    select MTD
+    select MTD_CFI
+    select MTD_PARTITIONS
+    select MTD_CFI_INTELEXT
+    select MTD_PXA2XX
+    depends on MACH_LOOX550
+    help
+        FSC Loox 550 internal flash ROM support.
+endmenu
diff --git a/arch/arm/mach-pxa/loox550/Makefile b/arch/arm/mach-pxa/loox550/Makefile
new file mode 100644
index 0000000..431aefe
--- /dev/null
+++ b/arch/arm/mach-pxa/loox550/Makefile
@@ -0,0 +1,10 @@
+#
+# FS Loox Makefile for the linux kernel.
+#
+obj-$(CONFIG_MACH_LOOX550)	+= loox550.o loox5xx_leds.o
+##obj-$(CONFIG_LOOX550_LCD)	+= loox550_lcd.o
+obj-$(CONFIG_LOOX550_ADS7846)	+= loox550_spi_ads7846.o
+obj-$(CONFIG_LOOX550_BATTERY)	+= loox550_battery.o
+obj-$(CONFIG_LOOX550_FLASH)	+= loox550_flash.o
+#obj-$(CONFIG_PM)                += loox550_pm.o
+#obj-y				+= looxn560_pm.o
diff --git a/arch/arm/mach-pxa/loox550/loox550-cpld.h b/arch/arm/mach-pxa/loox550/loox550-cpld.h
new file mode 100644
index 0000000..3185f3d
--- /dev/null
+++ b/arch/arm/mach-pxa/loox550/loox550-cpld.h
@@ -0,0 +1,163 @@
+/*
+ * mach/loox550-cpld.h
+ *
+ * Authors: 	Piotr Czechowicz 	<p.czechowicz@admitech.pl>
+ *		Tomasz Figa		<tomasz.figa@gmail.com>
+ *		Jan Rinze Peterzon	<janrinze@gmail.com>
+ *
+ * Loox 720 CPLD structure:
+ * 16 registers (16-bit) located at physical address (0x10000000):
+ * reg 1 	- interrupt status
+ * reg 2 	- interrupt mask
+ * reg 3 	- input pins
+ * regs 4-7 	- unknown
+ * regs 8-16 	- output pins
+ *
+ */
+
+#ifndef _LOOX550_CPLD_H_
+#define _LOOX550_CPLD_H_
+
+#include <mach/pxa-regs.h>
+#include <linux/irq.h>
+#define __IRQT_RISEDGE	IRQ_TYPE_EDGE_RISING
+#define IRQT_RISING	(__IRQT_RISEDGE)
+
+
+#define LOOX720_CPLD_PHYS	PXA_CS4_PHYS
+#define LOOX720_CPLD_SIZE	32
+
+/*
+    adapted these methods for 16 bit..
+    Hopefully noone else uses these..
+    a carefull grep showed noone yet does..
+    the names are too generic..
+*/
+
+#define BIT_POS(x)	(x>>4)
+#define BIT_SHIFT(x)	(x&15)
+#define BIT_MSK(x)	(u32)(1<<BIT_SHIFT(x))
+
+/*
+Bitmasks of LED modes in LEDs' cache.
+*/
+
+#define LOOX720_LED1_BLUE		1
+#define LOOX720_LED1_GREEN		2
+#define LOOX720_LED1_BLINK		4
+#define LOOX720_LED1_BLINK2		8
+
+#define LOOX720_LED2_GREEN		16
+#define LOOX720_LED2_RED		32
+#define LOOX720_LED2_ORANGE		48
+#define LOOX720_LED2_BLINK	 	64
+#define LOOX720_LED2_BLINK2	  	128
+
+/*
+Bitmasks of bits in reg #8:
+*/
+
+#define LOOX720_CPLD_LED1_BIT_A 256
+#define LOOX720_CPLD_LED1_BIT_B 512
+#define LOOX720_CPLD_LED1_BIT_C 1024
+#define LOOX720_CPLD_LED1_BIT_D 2048
+#define LOOX720_CPLD_LED1_BLINK 32768
+
+#define LOOX720_CPLD_LED2_BIT_A 16
+#define LOOX720_CPLD_LED2_BIT_B 32
+#define LOOX720_CPLD_LED2_BIT_C 64
+#define LOOX720_CPLD_LED2_BIT_D 128
+#define LOOX720_CPLD_LED2_BLINK 16384
+
+/*
+CPLD output bits numbers
+*/
+
+#define LOOX720_CPLD_LED_BIT_1			132
+#define LOOX720_CPLD_LED_BIT_2			133
+#define LOOX720_CPLD_LED_BIT_3			134
+#define LOOX720_CPLD_LED_BIT_4			135
+#define LOOX720_CPLD_LED_BIT_5			136
+#define LOOX720_CPLD_LED_BIT_6			137
+#define LOOX720_CPLD_LED_BIT_7			138
+#define LOOX720_CPLD_LED_BIT_8			139
+#define LOOX720_CPLD_CF_3V3_BIT			140
+#define LOOX720_CPLD_LED_BIT_9			142
+#define LOOX720_CPLD_LED_BIT_10			143
+#define LOOX720_CPLD_BATTERY_BIT		144
+#define LOOX720_CPLD_USB_PULLUP_BIT		145
+#define LOOX720_CPLD_LCD_CONSOLE_BIT		146 // Blanking: 4rd Unblanking: 2nd
+#define LOOX720_CPLD_LCD_BIT			147 // Blanking: 3rd Unblanking: 3rd
+/*
+
+These looks like a piece of garbage, because wince doesn't use them...
+
+#define LOOX720_CPLD_LED2_EN_1			148
+#define LOOX720_CPLD_LED2_EN_2			149
+#define LOOX720_CPLD_LED2_EN_3			150
+#define LOOX720_CPLD_LED1_EN_1			152
+#define LOOX720_CPLD_LED1_EN_2			153
+*/
+#define LOOX720_CPLD_LCD_COLOR_BIT		160 // Blanking: 2nd Unblanking: 4th
+#define LOOX720_CPLD_LCD_BIT2			161 // Blanking: 5th Unblanking: 1st
+#define LOOX720_CPLD_CF_RESET			162
+#define LOOX720_CPLD_SERIAL_BIT			163
+#define LOOX720_CPLD_VAUX_CTL1			176
+#define LOOX720_CPLD_VAUX_CTL2			177
+#define LOOX720_CPLD_VAUX_CTL3			178	
+#define LOOX720_CPLD_VAUX_CTL4			179
+#define LOOX720_CPLD_BLUETOOTH_POWER		192
+#define LOOX720_CPLD_CF_RESET_N			193 // False...
+#define LOOX720_CPLD_CAMERA_FLASH_BIT		195
+#define LOOX720_CPLD_SOUND_BIT			208
+#define LOOX720_CPLD_SND_AMPLIFIER_BIT		209
+#define LOOX720_CPLD_BLUETOOTH_RADIO    	210
+#define LOOX720_CPLD_WIFI_POWER			211
+#define LOOX720_CPLD_CAMERA_POWER		224
+#define LOOX720_CPLD_SD_BIT			225
+#define LOOX720_CPLD_CAMERA_RESET		226
+#define LOOX720_CPLD_CF_5V_BIT			241
+#define LOOX720_CPLD_BACKLIGHT_BIT		242 // Blanking: 1st Unblanking: 5th
+
+/*
+CPLD input bitmasks definitions
+
+These should be bit positions!!
+
+*/
+
+#define LOOX720_CPLD_CF_DETECT_N		0x04
+#define LOOX720_CPLD_CF_READY			0x10
+#define LOOX720_CPLD_WIFI_READY			0x20
+#define LOOX720_CPLD_WIFI_ENABLED		0x40
+
+extern int loox720_cpld_irq_base;
+
+/*
+CPLD interrupt multiplexer definitions
+*/
+
+#define LOOX720_IRQ_BASE IRQ_BOARD_START
+
+#define LOOX720_CPLD_IRQ(irq) \
+    (LOOX720_CPLD_IRQ_ ## irq) + LOOX720_IRQ_BASE
+
+#define LOOX720_CPLD_IRQ_COUNT 16
+
+#define LOOX720_CPLD_IRQ_WIFI 		5
+#define LOOX720_CPLD_IRQ_CF 		4
+#define LOOX720_CPLD_IRQ_CARD_DETECT 	2
+
+/*
+Function definitions
+*/
+
+extern void loox720_set_leds(int mode);
+extern void loox720_egpio_set_bit(int bit, int val);
+extern u32  loox720_cpld_reg_read(int regno);
+extern void loox720_cpld_reg_write(int regno, u32 value);
+extern void loox720_cpld_write_masked(int regno,u32 mask ,u32 value);
+extern u32 loox720_cpld_reg_test(int regno,u32 mask);
+extern void loox720_cpld_resume(void);
+
+#endif
diff --git a/arch/arm/mach-pxa/loox550/loox550.c b/arch/arm/mach-pxa/loox550/loox550.c
new file mode 100644
index 0000000..9bbc4e0
--- /dev/null
+++ b/arch/arm/mach-pxa/loox550/loox550.c
@@ -0,0 +1,351 @@
+/*
+ *  linux/arch/arm/mach-pxa/looxc550/looxc550.c
+ *
+ *  Hardware definitions for FSC LOOX C550
+ *  
+ *  Copyright (c) 2007 Yurii Zolot'ko
+ *  Copyright (c) 2013 David Heidelberger
+ *
+ *  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/init.h>
+#include <linux/notifier.h>
+#include <linux/lcd.h>
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/spi/pxa2xx_spi.h>
+#include <linux/fb.h>
+#include <linux/gpio_keys.h>
+#include <linux/mfd/htc-egpio.h>
+#include <linux/pda_power.h>
+#include <linux/spi/pxa2xx_spi.h>
+#include <linux/spi/ads7846.h>
+#include <linux/spi/spi.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/keypad-pxa27x.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
+
+#include <mach/pxa27x.h>
+#include <mach/udc.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/loox550-gpio.h>
+#include <mach/mfp-pxa27x.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/serial.h>
+
+#include "../generic.h"
+
+static unsigned long loox720_pin_config[] = {
+ GPIO12_GPIO,
+};
+
+static struct pxafb_mode_info loox550_lcd_mode_info = {
+	.pixclock		= 57692,
+	.bpp			= 16,
+	.xres			= 480,
+	.yres			= 640,
+	.hsync_len		= 8,
+	.left_margin	= 8,
+	.right_margin	= 124,
+	.vsync_len		= 2,
+	.upper_margin	= 3,
+	.lower_margin	= 25,
+	.sync			= 1,
+};
+
+static struct pxafb_mach_info loox550_fb_info =
+{
+	.modes			= &loox550_lcd_mode_info,
+	.num_modes		= 1,
+	.lcd_conn		= LCD_COLOR_TFT_16BPP,
+};
+
+// backlight on/off now is handled by the backlight device
+static struct platform_device loox550_bl_device = {
+	.name		= "loox550-bl",
+	.id		= -1,
+};
+
+// lcd on/off is now handled by the lcd device
+static struct platform_device loox550_lcd_device = {
+	.name		= "loox550-lcd",
+	.id		= -1,
+};
+
+/* LCD END */
+
+
+/********** KEYS ********************/
+
+static unsigned int loox550_matrix_keys[] = {
+	KEY(0, 0, KEY_RECORD),
+	KEY(1, 0, KEY_CALENDAR),
+	KEY(2, 0, KEY_MAIL),
+	KEY(3, 0, KEY_ADDRESSBOOK),
+	KEY(4, 0, KEY_HOMEPAGE),
+	KEY(0, 1, KEY_UP),
+	KEY(1, 1, KEY_DOWN),
+	KEY(2, 1, KEY_RIGHT),
+	KEY(3, 1, KEY_LEFT),
+	KEY(4, 1, KEY_ENTER), 
+};
+
+struct pxa27x_keypad_platform_data loox550_keypad_info = {
+	.matrix_key_rows        = 5,
+	.matrix_key_cols        = 2,
+	.matrix_key_map         = loox550_matrix_keys,
+	.matrix_key_map_size    = ARRAY_SIZE(loox550_matrix_keys),
+};
+
+static struct gpio_keys_button loox550_button_table[] = {
+        {KEY_POWER,      GPIO_NR_LOOXC550_KEYPWR,      0, "Power button"},
+};
+
+static struct gpio_keys_platform_data gpio_keys_data = {
+        .buttons  = loox550_button_table,
+        .nbuttons = ARRAY_SIZE(loox550_button_table),
+};
+
+static struct platform_device gpio_keys = {
+        .name = "gpio-keys",
+        .dev  = {
+                .platform_data = &gpio_keys_data,
+        },
+        .id   = -1,
+};
+
+/**************  MMC/SD ***********/
+
+static struct pxamci_platform_data magician_mci_info = {
+	.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
+	.gpio_card_detect = GPIO_NR_LOOXC550_SD_DETECT,
+	.gpio_card_ro = GPIO_NR_LOOXC550_SD_RO,
+	.gpio_power = GPIO_NR_LOOXC550_SD_POWER,
+};
+
+
+/************** BATTERY + PM **************/
+
+static struct platform_device loox720_battery = {
+        .name = "loox720-battery",
+        .id             = -1,
+};
+
+static struct platform_device loox550_pm = {
+        .name = "loox550-pm",
+        .id             = -1,
+};
+
+
+/*************     UDC     *******************/
+
+static struct pxa2xx_udc_mach_info looxc550_udc_info __initdata = {
+        .gpio_pullup    = GPIO_NR_LOOXC550_USB_PULLUP
+};
+
+/*************     OHCI     ******************/
+
+static struct pxaohci_platform_data n560_ohci_platform_data = {
+	.port_mode      = PMM_PERPORT_MODE,
+	.flags          = ENABLE_PORT_ALL | POWER_SENSE_LOW | NO_OC_PROTECTION,
+//        .power_budget   = 500,  // ???
+};
+
+/*
+ * Flash
+ */
+
+extern struct platform_device loox7xx_flash;
+
+/***************** EGPIOs ********************/
+
+static struct resource egpio_resources[] = {
+       [0] = {
+              .start = PXA_CS4_PHYS,
+              .end   = PXA_CS4_PHYS + 0x2*8,
+              .flags = IORESOURCE_MEM,
+       },
+};
+
+static struct htc_egpio_chip egpio_chips[] = {
+        [0] = {
+                .reg_start = 0,
+                .gpio_base = LOOX5XX_EGPIO_BASE + 16*0,
+                .num_gpios = 16,
+                .direction = HTC_EGPIO_OUTPUT,
+		.initial_values = 0x4,
+        },
+        [1] = {
+                .reg_start = 1,
+                .gpio_base = LOOX5XX_EGPIO_BASE + 16*1,
+                .num_gpios = 16,
+                .direction = HTC_EGPIO_OUTPUT,
+		.initial_values = 0x0,
+        },
+        [2] = {
+                .reg_start = 2,
+                .gpio_base = LOOX5XX_EGPIO_BASE + 16*2,
+                .num_gpios = 16,
+                .direction = HTC_EGPIO_OUTPUT,
+		.initial_values = 0x0,
+        },
+        [3] = {
+                .reg_start = 3,
+                .gpio_base = LOOX5XX_EGPIO_BASE + 16*3,
+                .num_gpios = 16,
+                .direction = HTC_EGPIO_OUTPUT,
+		.initial_values = 0x8,
+        },
+        [4] = {
+                .reg_start = 4,
+                .gpio_base = LOOX5XX_EGPIO_BASE + 16*4,
+                .num_gpios = 16,
+                .direction = HTC_EGPIO_OUTPUT,
+		.initial_values = 0x8,
+        },
+        [5] = {
+                .reg_start = 5,
+                .gpio_base = LOOX5XX_EGPIO_BASE + 16*5,
+                .num_gpios = 16,
+                .direction = HTC_EGPIO_OUTPUT,
+		.initial_values = 0x8,
+        },
+        [6] = {
+                .reg_start = 6,
+                .gpio_base = LOOX5XX_EGPIO_BASE + 16*6,
+                .num_gpios = 16,
+                .direction = HTC_EGPIO_OUTPUT,
+		.initial_values = 0x1,
+        },
+};
+
+
+static struct htc_egpio_platform_data egpio_info = {
+        .reg_width    = 16,
+        .bus_width    = 16,
+        .chip         = egpio_chips,
+        .num_chips    = ARRAY_SIZE(egpio_chips),
+};
+
+static struct platform_device loox5xx_egpio = {
+       .name = "htc-egpio",
+       .id   = -1,
+       .dev  = {
+              .platform_data = &egpio_info,
+       },
+       .resource      = egpio_resources,
+       .num_resources = ARRAY_SIZE(egpio_resources),
+};
+
+/*****************************************************************/
+/* LEDs */
+
+static struct platform_device loox5xx_leds = {
+	.name	    = "loox5xx-leds",
+	.id	    = 1,
+};
+
+/*****************************************************************/
+/* SPI */
+
+/* borrowed from lubbock.c */
+static struct pxa2xx_spi_master pxa_ssp_master_info = {
+        .clock_enable = CKEN_SSP1,
+        .num_chipselect = 1,
+        .enable_dma = 0,
+};
+
+static struct platform_device pxa_ssp = {
+        .name           = "pxa2xx-spi",
+        .id             = 1,
+        .dev = {
+                .platform_data  = &pxa_ssp_master_info,
+        },
+};
+
+//----------------------------------------------------------------------------------------
+
+static struct ads7846_platform_data loox5x0_ads7846_info = {
+	.model				= 7845,
+	.pressure_max		= 4095,
+	.x_max				= 480,
+	.y_max				= 640,
+	.gpio_pendown		= GPIO_NR_LOOXC550_TOUCHPANEL_IRQ_N,
+};
+
+static struct pxa2xx_spi_chip loox5x0_ads7846_chip = {
+	.tx_threshold           = 8,
+	.rx_threshold           = 4,
+	.timeout                = 1000,
+	.enable_loopback        = 0,
+	.dma_burst_size         = 0,
+	.gpio_cs                = -1,
+};
+
+static struct spi_board_info loox_board_info[] __initdata = {
+	{
+		.modalias			= "ads7846",
+		.max_speed_hz		= 200000,
+		.bus_num			= 1,
+		.chip_select		= 0,
+		.platform_data		= &loox5x0_ads7846_info,
+		.controller_data	= &loox5x0_ads7846_chip,
+		.irq				= PXA_GPIO_TO_IRQ(GPIO_NR_LOOXC550_TOUCHPANEL_IRQ_N),
+		.mode				= SPI_MODE_0,
+	},
+};
+
+static struct platform_device *devices[] __initdata = {
+	&pxa_ssp,
+	&loox5xx_egpio,
+	&loox5xx_leds,
+
+	&loox720_battery,
+	&loox550_pm,
+	&loox7xx_flash,
+	&gpio_keys
+};
+
+
+static void __init looxc550_init(void)
+{
+	pxa2xx_mfp_config(loox720_pin_config, ARRAY_SIZE(loox720_pin_config));
+
+	pxa_set_fb_info(NULL, &loox550_fb_info);
+	platform_device_register(&loox550_bl_device);
+	platform_device_register(&loox550_lcd_device);
+
+	pxa_set_mci_info(&magician_mci_info);
+	pxa_set_udc_info(&looxc550_udc_info);
+	pxa_set_ohci_info(&n560_ohci_platform_data);
+	pxa_set_keypad_info(&loox550_keypad_info);
+	
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+      
+	spi_register_board_info(loox_board_info, ARRAY_SIZE(loox_board_info));
+}
+
+MACHINE_START(LOOXN560, "FSC Loox 5xx")
+	.atag_offset    = 0x100,
+	.map_io			= pxa27x_map_io,
+	.init_irq		= pxa27x_init_irq,
+	.handle_irq		= pxa27x_handle_irq,
+	.nr_irqs		= PXA_NR_IRQS,
+	.timer			= &pxa_timer,
+	.init_machine	= looxc550_init,
+	.restart		= pxa_restart,
+MACHINE_END
diff --git a/arch/arm/mach-pxa/loox550/loox550_battery.c b/arch/arm/mach-pxa/loox550/loox550_battery.c
new file mode 100644
index 0000000..bd76bf2
--- /dev/null
+++ b/arch/arm/mach-pxa/loox550/loox550_battery.c
@@ -0,0 +1,190 @@
+/* Battery Charging support for FSC Loox 720
+ *
+ * Authors: Piotr Czechowicz, Tomasz Figa
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/gpio.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <mach/loox550-gpio.h>
+#include <mach/loox5xx_leds.h>
+//include <mach/looxc550.h>
+//include <asm/arch/loox720-cpld.h>
+//include <asm/arch/loox720.h>
+//include <asm/arch/irqs.h>
+
+static unsigned int ac_irq = 0xffffffff;
+static unsigned int battery_irq = 0xffffffff;
+static unsigned int usb_irq = 0xffffffff;
+
+static void update_battery_charging(void)
+{
+	int usb_conn = (gpio_get_value(GPIO_NR_LOOXC550_USB_DETECT_N) == 0);  //yes
+	int ac_conn = (gpio_get_value(GPIO_NR_LOOXC550_AC_IN_N) == 0);  //yes
+
+	if (ac_conn || usb_conn) {
+		int battery_full = gpio_get_value(GPIO_NR_LOOXC550_BATTERY_FULL_N) == 0; //yes ???
+		printk(KERN_INFO "battery: ac: %d; usb: %d; battery_full: %d\n", ac_conn, usb_conn, battery_full);
+//		if (ac_conn)
+//			gpio_set_value(GPIO_NR_LOOX720_USB_CHARGE_N, 1);  //????????
+//		else
+//			gpio_set_value(GPIO_NR_LOOX720_USB_CHARGE_N, 0);  //????????
+		if (battery_full) {
+			gpio_set_value(GPIO_NR_LOOXC550_CHARGE_EN_N, 1);  //yes
+			loox5xx_enable_power_led ();
+		} else {
+			gpio_set_value(GPIO_NR_LOOXC550_CHARGE_EN_N, 0);  //yes
+			loox5xx_blink_power_led ();
+		}
+	} else {
+		printk(KERN_INFO "battery: external power is disconnected.\n");
+		loox5xx_disable_power_led ();
+		gpio_set_value(GPIO_NR_LOOXC550_CHARGE_EN_N, 1);
+	}
+}
+
+static void update_battery_chip(void)
+{
+	int connected = (gpio_get_value(GPIO_NR_LOOXC550_AC_IN_N) == 0) || (gpio_get_value(GPIO_NR_LOOXC550_USB_DETECT_N) == 0);  //yes
+	printk( KERN_INFO "battery: charging controller enabled=%d\n", connected );
+//	loox720_egpio_set_bit(LOOX720_CPLD_BATTERY_BIT, connected);		//?????
+}
+
+static irqreturn_t
+battery_isr(int irq, void *data)
+{
+	int full = gpio_get_value(GPIO_NR_LOOXC550_BATTERY_FULL_N) == 0;  //???
+	printk( KERN_INFO "battery_isr: battery_full=%d\n", full);
+
+	update_battery_charging();
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
+ac_isr(int irq, void *data)
+{
+	int connected;
+
+	if (irq != ac_irq)
+		return IRQ_NONE;
+
+	connected = gpio_get_value(GPIO_NR_LOOXC550_AC_IN_N) == 0;
+	printk( KERN_INFO "ac_isr: connected=%d\n", connected );
+
+	update_battery_charging();
+	update_battery_chip();
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
+usb_isr(int irq, void *data)
+{
+	int connected;
+
+	if (irq != usb_irq)
+		return IRQ_NONE;
+
+	connected = gpio_get_value(GPIO_NR_LOOXC550_USB_DETECT_N) == 0;
+	printk( KERN_INFO "usb_isr: connected=%d\n", connected );
+
+	update_battery_charging();
+	update_battery_chip();
+
+	return IRQ_HANDLED;
+}
+
+static int
+loox720_battery_probe( struct platform_device *pdev )
+{
+	int battery_full, usb_connected, ac_connected;
+
+	printk( KERN_NOTICE "Loox 720 Core Hardware Driver\n" );
+
+	ac_irq = PXA_GPIO_TO_IRQ(GPIO_NR_LOOXC550_AC_IN_N);
+	battery_irq = PXA_GPIO_TO_IRQ(GPIO_NR_LOOXC550_BATTERY_FULL_N);  //?????????
+	usb_irq = PXA_GPIO_TO_IRQ(GPIO_NR_LOOXC550_USB_DETECT_N);
+
+	ac_connected = gpio_get_value(GPIO_NR_LOOXC550_AC_IN_N) == 0;
+	usb_connected = gpio_get_value(GPIO_NR_LOOXC550_USB_DETECT_N) == 0;
+	battery_full = gpio_get_value(GPIO_NR_LOOXC550_BATTERY_FULL_N) == 0;
+
+	printk( KERN_INFO "AC: connected=%d\n", ac_connected );
+	if (request_irq( ac_irq, &ac_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+	                 "Loox 720 AC Detect", NULL ) != 0) {
+		printk( KERN_ERR "Unable to configure AC detect interrupt.\n" );
+		return -ENODEV;
+	}
+
+	printk( KERN_INFO "USB: connected=%d\n", usb_connected );
+	if (request_irq( usb_irq, &usb_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "Loox 720 USB Detect", NULL) != 0) {
+		printk( KERN_ERR "Unable to configure USB detect interrupt.\n" );
+		free_irq( ac_irq, NULL );
+		return -ENODEV;
+	}
+
+	if (request_irq( battery_irq, &battery_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "Loox 720 Battery Full", NULL) != 0) {
+		printk( KERN_ERR "Unable to configure battery-full detect interrupt.\n" );
+		free_irq( ac_irq, NULL );
+		free_irq( usb_irq, NULL );
+		return -ENODEV;
+	}
+
+	update_battery_chip();
+	update_battery_charging();
+
+	return 0;
+}
+
+static int
+loox720_battery_remove( struct platform_device *dev )
+{
+	if (ac_irq != 0xffffffff)
+		free_irq( ac_irq, NULL );
+	if (battery_irq != 0xffffffff)
+		free_irq( battery_irq, NULL );
+	if (usb_irq != 0xffffffff)
+		free_irq( usb_irq, NULL );
+	return 0;
+}
+
+struct platform_driver loox720_battery_driver = {
+	.driver = {
+		.name     = "loox720-battery",
+	},
+	.probe    = loox720_battery_probe,
+	.remove   = loox720_battery_remove,
+};
+
+static int __init
+loox720_battery_init( void )
+{
+	return platform_driver_register( &loox720_battery_driver );
+}
+
+
+static void __exit
+loox720_battery_exit( void )
+{
+	platform_driver_unregister( &loox720_battery_driver );
+}
+
+module_init( loox720_battery_init );
+module_exit( loox720_battery_exit );
+
+MODULE_AUTHOR("Piotr Czechowicz, Tomasz Figa");
+MODULE_DESCRIPTION("Loox 720 Battery Charging Support");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/mach-pxa/loox550/loox550_cpld.c b/arch/arm/mach-pxa/loox550/loox550_cpld.c
new file mode 100644
index 0000000..b8caeed
--- /dev/null
+++ b/arch/arm/mach-pxa/loox550/loox550_cpld.c
@@ -0,0 +1,427 @@
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include <mach/irqs.h>
+#include <mach/loox550-gpio.h>
+#include "loox550-cpld.h"
+
+static u32 reg_cache[16]={
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static volatile u16 *cpld_mem = 0;
+int loox550_cpld_irq_base = -1;
+EXPORT_SYMBOL(loox550_cpld_irq_base);
+
+
+struct loox550_irq_data
+{
+	volatile u32 irq_mask;
+	int irq_base;
+};
+
+struct loox550_irq_data * loox550_cpld_irq_data;
+
+struct cpld_bit
+{
+    int	bit;
+    int value;
+};
+
+static struct cpld_bit loox550_cpld_bits[] = 
+{
+    {
+	.bit   = LOOX550_CPLD_SERIAL_BIT,
+	.value = 1
+    },
+    {
+	.bit   = LOOX550_CPLD_LCD_CONSOLE_BIT,
+	.value = 1
+    },
+    {
+	.bit   = LOOX550_CPLD_LCD_BIT,
+	.value = 1
+    },
+    {
+	.bit   = LOOX550_CPLD_LCD_COLOR_BIT,
+	.value = 1
+    },
+    {
+	.bit   = LOOX550_CPLD_LCD_BIT2,
+	.value = 1
+    },
+    {
+	.bit   = LOOX550_CPLD_BACKLIGHT_BIT,
+	.value = 1
+    },
+// NOTE: WinCE enables it only after plugging an USB cable or AC charger
+/*
+    {	
+	.bit   = LOOX550_CPLD_BATTERY_BIT,
+	.value = 1    
+    },
+*/
+// NOTE: WinCE doesn't use them... tom3q
+/*
+    {
+	.bit   = LOOX550_CPLD_LED1_EN_1,
+	.value = 1
+    },
+    {
+	.bit   = LOOX550_CPLD_LED1_EN_2,
+	.value = 1
+    },
+    {
+	.bit   = LOOX550_CPLD_LED2_EN_1,
+	.value = 1
+    },
+    {
+	.bit   = LOOX550_CPLD_LED2_EN_2,
+	.value = 1
+    },
+    {
+	.bit   = LOOX550_CPLD_LED2_EN_3,
+	.value = 1
+    },
+*/
+// NOTE: WinCE keeps this bit HIGH, and that's why i added it here... tom3q
+    {
+    	.bit	= LOOX550_CPLD_CF_RESET_N,
+    	.value = 1
+    }
+};
+
+u32 loox550_cpld_reg_read(int regno)
+{
+    u32 retval = 0;
+    if(cpld_mem) retval = cpld_mem[regno];
+    return retval;
+}
+EXPORT_SYMBOL(loox550_cpld_reg_read);
+
+/*
+    if we want to know if specific bits are set ..
+    this returns them either from the cache or from the real cpld
+*/
+
+u32 loox550_cpld_reg_test(int regno, u32 mask)
+{
+    u32 retval = 0;
+    if (regno < 4) // the lower 4 are inputs
+    {
+	if (cpld_mem)
+	    retval = cpld_mem[regno] & mask;
+    } else {
+	retval = reg_cache[regno] & mask;
+    }
+    return retval;
+}
+EXPORT_SYMBOL(loox550_cpld_reg_test);
+
+void loox550_cpld_reg_write(int regno, u32 value)
+{
+    if (cpld_mem)
+      cpld_mem[regno] = (u16) value;
+    /*
+       apparently we write from outside the cpld environment
+       this would cause that bits are not updated in the cache..
+       also the change from 32 to 16 bit makes that all code needs
+       to be checked for writes directly to the cpld 
+    */
+    reg_cache[regno] = value;	
+}
+EXPORT_SYMBOL(loox550_cpld_reg_write);
+
+void loox550_cpld_write_masked(int regno, u32 mask, u32 value)
+{
+    u32 new_value = (reg_cache[regno] & ~mask ) | (value & mask) ;
+    /*
+	only the corresponding bits in the mask will be updated
+	to the ones from the input value
+    */
+    if (cpld_mem)
+      cpld_mem[regno] =(u16) new_value;
+    /*
+       apparently we write from outside the cpld environment
+       this would cause that bits are not updated in the cache..
+       also the change from 32 to 16 bit makes that all code needs
+       to be checked for writes directly to the cpld 
+    */
+    reg_cache[regno] = new_value;	
+}
+EXPORT_SYMBOL(loox550_cpld_write_masked);
+
+/*
+    exporting access to the cached bits is an example of very bad progamming..
+    the code remains until Piotr decides that it must go.. 
+    20/09/2007 Jan Rinze Peterzon.
+
+u32 loox550_egpio_cache_get(int regno)
+{
+    if(regno>0)
+        return reg_cache[regno];
+    else
+    	return 0;
+}
+EXPORT_SYMBOL(loox550_egpio_cache_get);
+
+    
+void loox550_egpio_cache_set(int regno, u32 value)
+{
+    if(regno>0)
+	reg_cache[regno] = value;
+}
+EXPORT_SYMBOL(loox550_egpio_cache_set);
+*/
+
+/* 
+    this code is a bit archaic i.m.h.o.
+void loox720_egpio_cache_enable_bits(int pos, u32 bits)
+{
+    reg_cache[pos] |= bits;
+}
+
+void loox550_egpio_cache_clear_bits(int pos, u32 bits)
+{
+    reg_cache[pos] &=~bits;
+}
+
+void loox550_egpio_set_bit(int bit, int val)
+{
+    int pos = BIT_POS(bit);
+    if(bit > 31)
+	{
+	    if (val)
+		loox550_egpio_cache_enable_bits(pos, BIT_MSK(bit));
+	    else
+		loox550_egpio_cache_clear_bits(pos, BIT_MSK(bit));
+	    loox550_cpld_reg_write(pos, reg_cache[pos]);
+	}
+}
+*/
+
+void loox550_egpio_set_bit(int bit, int val)
+{
+    int pos = BIT_POS(bit);
+    /*
+	pos 0 has interrupt bits.
+	there is no harm in writing to them if intended
+	since that will clear those interrupts.
+	But we have chosen not to bother with this..
+	pos 1 has interrupt mask register which seems logical to keep
+	in the cache.
+	
+	we actually should be locking interrupts around this..
+	there may be race-conditions around setting bits..
+	
+    */
+    if(pos > 0)
+    {
+	u32 curr_value = reg_cache[pos];
+	if (val)
+		curr_value |= BIT_MSK(bit);
+	    else
+		curr_value &=~BIT_MSK(bit);
+	    loox550_cpld_reg_write(pos, curr_value);
+	}
+}
+EXPORT_SYMBOL(loox550_egpio_set_bit);
+
+void	loox550_cpld_ack_irq(unsigned int irq)
+{
+	/*
+	    we don't ack irqs.
+	    a possibility would be to clear the specific interrupt.
+	    we tried but it had no good effects.
+	*/
+}
+
+void 	loox550_cpld_mask_irq(unsigned int irq)
+{
+	struct loox550_irq_data * irq_data = get_irq_chip_data(irq);
+	/* masking like this is racy.. */
+	irq_data->irq_mask |= 1 << (irq - irq_data->irq_base);
+	/* 
+	    NOTE:
+	    since the isr only uses the copy we might try and
+	    really disable this irq in the cpld:
+	*/
+        cpld_mem[1] = irq_data->irq_mask;
+}
+
+void	loox550_cpld_unmask_irq(unsigned int irq)
+{
+	struct loox550_irq_data * irq_data = get_irq_chip_data(irq);
+	/* masking like this is racy.. */
+	irq_data->irq_mask &= ~(1 << (irq - irq_data->irq_base));
+	/*
+	    NOTE:
+	    should we bother to clear the irq first?
+	    for the people who like to know how:
+	    
+	    cpld_mem[0] = 1 << (irq - irq_data->irq_base;
+	*/
+	/* 
+	    NOTE:
+	    since the isr only uses the copy we might try and
+	    really disable this irq in the cpld:
+	*/
+	cpld_mem[1] = irq_data->irq_mask;
+}
+
+static struct irq_chip loox550_irq_chip = {
+    .name       = "CPLD",
+    .mask       = loox550_cpld_mask_irq,
+    .mask_ack	= loox550_cpld_mask_irq,
+    .unmask     = loox550_cpld_unmask_irq,
+    .ack	= loox550_cpld_ack_irq,
+};
+
+static /*unsigned int*/ void loox550_cpld_irq_demux(unsigned int irq, struct irq_desc *desc)
+{
+    unsigned int mask;
+    struct irq_desc * proc_desc;
+    unsigned int proc_irq;
+    struct loox550_irq_data * irq_data = desc->handler_data;
+
+    /* the following is racy.. we should add irq disabling around it */
+    desc->chip->mask(irq);
+    mask = (cpld_mem[0] & (~irq_data->irq_mask));
+    cpld_mem[0] = mask;// ack all to be handled irqs
+    if (mask) {
+        proc_irq = irq_data->irq_base;
+        proc_desc = irq_desc + proc_irq;
+        do {
+            if (mask & 1)
+                desc_handle_irq(proc_irq, proc_desc);
+            proc_irq++;
+            proc_desc++;
+            mask >>= 1;
+        } while (mask);
+    }
+    desc->chip->unmask(irq);
+    cpld_mem[1] = 0x3FF;
+    cpld_mem[1] = irq_data->irq_mask;
+}
+void loox550_cpld_resume(void)
+{
+        int i;
+        for(i=8; i<16; i++)
+                cpld_mem[i] = reg_cache[i];
+}
+
+static int __init loox550_cpld_init(void)
+{
+    int i;
+//    if (!machine_is_loox720())
+//	return -ENODEV;
+
+    loox550_cpld_irq_base = IRQ_BOARD_START;
+    printk(KERN_INFO "Loox 550 CPLD Driver\n");
+
+    cpld_mem = (u16*)ioremap_nocache(LOOX550_CPLD_PHYS, LOOX550_CPLD_SIZE);
+    if (!cpld_mem)
+    {
+		printk(KERN_ERR "ioremap failed.\n");
+		return -ENODEV;
+    }
+
+    printk(KERN_INFO "Physical address of CPLD: %08X\nVirtual address of CPLD: %08X\nUsing IRQs from %d to %d on IRQ %d\n",
+		LOOX550_CPLD_PHYS, (u32)cpld_mem, loox550_cpld_irq_base, loox550_cpld_irq_base + LOOX550_CPLD_IRQ_COUNT - 1, IRQ_GPIO(GPIO_NR_LOOX550_CPLD_INT));
+
+    for (i=0;i<ARRAY_SIZE(loox550_cpld_bits);i++)
+    	loox550_egpio_set_bit( loox550_cpld_bits[i].bit, loox550_cpld_bits[i].value);
+
+	
+	if(gpio_request(GPIO_NR_LOOX550_CPLD_INT, "CPLD interrupt") != 0) {
+		if (cpld_mem)
+			iounmap(cpld_mem);
+		printk(KERN_ERR "Failed to request CPLD interrupt GPIO\n");
+		return -ENODEV;
+	}
+
+    loox550_cpld_irq_data = kmalloc(sizeof(struct loox550_irq_data), GFP_KERNEL);
+    if(!loox550_cpld_irq_data)
+    {
+	printk(KERN_ERR "kmalloc failed.\n");
+	if (cpld_mem)
+	    iounmap(cpld_mem);
+	gpio_free(GPIO_NR_LOOX550_CPLD_INT);
+        return -ENOMEM;
+    }
+    
+    loox550_cpld_irq_data->irq_base = loox550_cpld_irq_base;
+    loox550_cpld_irq_data->irq_mask = 0x3FF;
+    
+    cpld_mem[1] = 0x3FF; // Mask all interrupts
+
+    for (i=0; i<LOOX550_CPLD_IRQ_COUNT; i++)
+    {
+    	int irq = i + loox550_cpld_irq_base;
+        set_irq_chip(irq, &loox550_irq_chip);
+	set_irq_chip_data(irq, loox550_cpld_irq_data);
+	set_irq_handler(irq, handle_level_irq);
+    	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+    }
+    
+    set_irq_data(IRQ_GPIO(GPIO_NR_LOOX550_CPLD_INT), loox550_cpld_irq_data);
+    set_irq_type(IRQ_GPIO(GPIO_NR_LOOX550_CPLD_INT), IRQT_RISING);
+    set_irq_chained_handler(IRQ_GPIO(GPIO_NR_LOOX550_CPLD_INT), loox550_cpld_irq_demux);
+    
+    cpld_mem[0] = 0x3FF; // clear interrupts
+    cpld_mem[1] = 0x3FF; // enable all interrupts for CFcard and Wifi
+    return 0;
+}
+
+/*
+NOTE: Do we want the CPLD driver to be unloadable? tom3q
+
+static void __exit loox550_cpld_exit(void)
+{
+    if (cpld_mem)
+    {
+	cpld_mem[1] = 0x03FF; // Mask and all interrupts
+	cpld_mem[0] = 0x03FF; // Clear all interrupts
+    }
+	
+    if (loox550_cpld_irq_base!=-1)
+    {
+        int i;
+        for (i = 0 ; i < LOOX550_CPLD_IRQ_COUNT ; i++)
+    	{
+            int irq = i + loox550_cpld_irq_base;
+            set_irq_handler(irq, NULL);
+	    set_irq_chip_data(irq, NULL);
+            set_irq_chip(irq, NULL);
+	    set_irq_flags(irq, 0);
+	}
+	set_irq_chained_handler(IRQ_GPIO(GPIO_NR_LOOX550_CPLD_INT), NULL);
+	set_irq_data(IRQ_GPIO(GPIO_NR_LOOX550_CPLD_INT), NULL);
+    }
+    if (loox550_cpld_irq_data)
+	kfree(loox550_cpld_irq_data);
+    if (cpld_mem)
+        iounmap(cpld_mem);
+        
+	gpio_free(GPIO_NR_LOOX550_CPLD_INT);
+}
+
+module_init( loox550_cpld_init );
+module_exit( loox550_cpld_exit );
+
+MODULE_AUTHOR("Piotr Czechowicz & Tomasz Figa & Jan Rinze Peterzon");
+MODULE_DESCRIPTION("Loox 550 CPLD driver");
+MODULE_LICENSE("GPL");
+*/
+
+/*
+NOTE: see include/linux/init.h for order of initcalls.
+*/
+subsys_initcall( loox550_cpld_init );
diff --git a/arch/arm/mach-pxa/loox550/loox550_flash.c b/arch/arm/mach-pxa/loox550/loox550_flash.c
new file mode 100644
index 0000000..f45103c
--- /dev/null
+++ b/arch/arm/mach-pxa/loox550/loox550_flash.c
@@ -0,0 +1,54 @@
+/*
+ *
+ * Flash support for Loox 7xx PDAs
+ *
+ * Based on magician.c
+ * Initial version by Dmitriy Geels
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/gpio.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/pxa2xx-regs.h>
+#include <mach/map.h>
+
+/*
+ * StrataFlash
+ */
+
+/*static void magician_set_vpp(struct map_info *map, int vpp)
+{
+        gpio_set_value(EGPIO_MAGICIAN_FLASH_VPP, vpp);
+}
+*/
+#define PXA_CS_SIZE             0x04000000
+
+static struct resource strataflash_resource = {
+        .start = PXA_CS0_PHYS,
+        .end   = PXA_CS0_PHYS + PXA_CS_SIZE - 1,
+        .flags = IORESOURCE_MEM,
+};
+
+static struct physmap_flash_data strataflash_data = {
+        .width = 4,
+//        .set_vpp = magician_set_vpp,
+};
+
+struct platform_device loox7xx_flash = {
+        .name          = "physmap-flash",
+        .id            = -1,
+        .resource      = &strataflash_resource,
+        .num_resources = 1,
+        .dev = {
+                .platform_data = &strataflash_data,
+        },
+};
+
diff --git a/arch/arm/mach-pxa/loox550/loox550_flash_old.c b/arch/arm/mach-pxa/loox550/loox550_flash_old.c
new file mode 100644
index 0000000..75c9de9
--- /dev/null
+++ b/arch/arm/mach-pxa/loox550/loox550_flash_old.c
@@ -0,0 +1,87 @@
+/*
+ *
+ * Flash support for Loox 7xx PDAs
+ *
+ * Based on magician.c
+ * Initial version by Dmitriy Geels
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/gpio.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/arch.h>
+#include <mach/map.h>
+#include <mach/flash.h>
+
+/* StrataFlash */
+/*
+static void loox7xx_set_vpp(struct map_info *map, int vpp)
+{
+	static int old_vpp = 0;
+	if (vpp == old_vpp)
+		return;
+	if (vpp)
+		gpio_set_value(EGPIO_MAGICIAN_FLASH_VPP, 1);
+	else
+		gpio_set_value(EGPIO_MAGICIAN_FLASH_VPP, 0);
+	old_vpp = vpp;
+}
+*/
+#ifdef CONFIG_MTD_PARTITIONS
+static struct mtd_partition wince_partitions[] = {
+	{
+		name:		"bootloader",
+		offset:		MTDPART_OFS_NXTBLK,
+		size:		SZ_256K,
+		mask_flags:	MTD_WRITEABLE,  /* force read-only */
+	},
+	{
+		name:		"winmobile",
+		offset:		MTDPART_OFS_NXTBLK,
+		size:		135 * SZ_256K,
+		mask_flags:	MTD_WRITEABLE,  /* force read-only */
+	},
+	{
+		name:		"looxstore",
+		offset:		MTDPART_OFS_NXTBLK,
+		size:		MTDPART_SIZ_FULL,
+		mask_flags:	MTD_WRITEABLE,  /* force read-only */
+	},
+};
+#endif
+
+static struct resource loox7xx_flash_resource = {
+	.start = PXA_CS0_PHYS,
+	.end   = PXA_CS0_PHYS + SZ_64M - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct flash_platform_data loox7xx_flash_data = {
+	.name		= "loox720-flash",
+	.map_name	= "cfi_probe",
+	.width		= 4,
+	.nr_parts	= ARRAY_SIZE(wince_partitions),
+	.parts		= wince_partitions,
+};
+
+struct platform_device loox7xx_flash = {
+	.name          = "pxa2xx-flash",
+	.id            = -1,
+	.num_resources = 1,
+	.resource      = &loox7xx_flash_resource,
+	.dev = {
+		.platform_data = &loox7xx_flash_data,
+	},
+};
+
+MODULE_AUTHOR("Dmitriy Geels <dmitriy.geels@gmail.com>");
+MODULE_DESCRIPTION("Internal flash driver for HTC Bali");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-pxa/loox550/loox550_pm.c b/arch/arm/mach-pxa/loox550/loox550_pm.c
new file mode 100644
index 0000000..4aacbf7
--- /dev/null
+++ b/arch/arm/mach-pxa/loox550/loox550_pm.c
@@ -0,0 +1,322 @@
+/* Power Management support for FSC Loox 720
+ *
+ * Authors: Tomasz Figa
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/gpio.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <mach/pxa-regs.h>
+#include <mach/pxa2xx-regs.h>
+#include <mach/loox550-gpio.h>
+//include <asm/arch/loox720-cpld.h>
+#include <mach/loox550.h>
+#include <mach/irqs.h>
+#include <mach/pm.h>
+
+//#include <linux/dpm.h>
+//#include <asm/arch/pxa-pm_ll.h>
+
+static u32 save[6];
+
+static int loox720_suspend(struct platform_device *pdev, pm_message_t state)
+{
+printk("loox720_suspend\n");
+	/*
+	 * Note that WEP1 wake up event is used by bootldr to set the
+	 * LEDS when power is applied/removed for charging.
+	 */
+//	PWER = PWER_RTC | PWER_GPIO0 | PWER_GPIO1 | PWER_GPIO9 | PWER_GPIO11 | PWER_GPIO12 | PWER_GPIO13;
+//	PFER = PWER_GPIO0 | PWER_GPIO1 | PWER_GPIO9 | PWER_GPIO11 | PWER_GPIO13;                                // Falling Edge Detect
+//	PRER = PWER_GPIO0 | PWER_GPIO1 | PWER_GPIO9 | PWER_GPIO12 | PWER_GPIO13;                // Rising Edge Detect
+//	PKWR = PWER_GPIO0;
+
+//	PGSR0 = 0x00000004; //0x01308018; // hx4700: 0x080DC01C
+//	PGSR1 = 0x00020002; //0x008F0112; // hx4700: 0x34CF0002
+//	PGSR2 = 0x00030000; //0x0C03C000; // hx4700: 0x0123C18C
+//	PGSR3 = 0x00000480; //0x00000C80; // hx4700: 0x00100202
+
+	/* These next checks are specifically for charging.  We want to enable
+	* it if it is already enabled */
+	/* Check for charge enable, GPIO 72 */
+//      if(GPLR2 & (1 << 8)) {
+	/* Set it */
+//              PGSR2 |= (1U << 8);
+//      } else {
+	/* Clear it */
+//              PGSR2 &= ~(1U << 8);
+//      }
+	/* Check for USB_CHARGE_RATE, GPIO 96 */
+//      if(GPLR3 & (1 << 0)) {
+	/* Set it */
+//              PGSR3 |= (1U << 0);
+//      } else {
+	/* Clear it */
+//              PGSR3 &= ~(1U << 0);
+//      }
+
+//	PCFR = PCFR_GPROD|PCFR_GPR_EN|PCFR_OPDE|PCFR_PI2CEN; /* was 0x1091; */
+//	PCFR = 0x00001031;
+	/* The 2<<2 below turns on the Power Island state preservation
+	 * and counters.  This allows us to wake up bootldr after a
+	 * period of time, and it can set the LEDs correctly based on
+	 * the power state.  The bootldr turns it off when it's
+	 * charged.
+	z        */
+//	PSLR=0xcc400000 | (2 << 2);
+//	PSLR=0xcc400004 | (2 << 2);
+	return 0;
+}
+
+static int loox720_resume(struct platform_device *pdev)
+{
+//	loox720_cpld_resume();
+//	__asm__ volatile ("mrc p14, 0, r3, c6, c0, 0\n"
+//	                  "orr r3, r3, #0x0008\n"
+//	                  "mcr p14, 0, r3, c6, c0, 0\n"
+//                  :::"r3");
+//
+	return 0;
+}
+
+static void test_resume(void) __attribute__((naked));
+static void test_resume(void)
+{
+	// our private resume handler restores the data at 0xA8024000
+	// and then turns over control to the pxa_resume handler
+	asm volatile("mov r0,#0xa8000000 \n");      // base memory
+//	asm volatile("mov r0,#0xa0200000 \n"); //550
+
+	asm volatile("orr r1,r0,#0x24000 \n");              // memory offset
+	asm volatile("ldr r2,[r1,#20] \n");         // r2 is store
+	asm volatile("ldr r3,[r1,#16] \n");         // r3 is our resume
+
+	asm volatile("ldr r0,[r2],#4 \n");          // restore word at 0
+	asm volatile("str r0,[r1],#4 \n");          // ..
+	asm volatile("ldr r0,[r2],#4 \n");          // restore a word at 4
+	asm volatile("str r0,[r1],#4 \n");          // ..
+	asm volatile("ldr r0,[r2],#4 \n");          // restore a word at 8
+	asm volatile("str r0,[r1],#4 \n");          // ..
+	asm volatile("ldr r0,[r2],#4 \n");          // restore a word at 12
+	asm volatile("str r0,[r1],#4 \n");          // ..
+	asm volatile("ldr r0,[r2],#4 \n");          // restore a word at 16
+	asm volatile("str r0,[r1],#4 \n");          // ..
+	asm volatile("ldr r0,[r2],#4 \n");          // restore a word at 20
+	asm volatile("str r0,[r1],#4 \n");          // ..
+	asm volatile("mov r0,#0x10000000 \n");      // CPLD address
+	asm volatile("mov r1,#0xa800 \n");          // blue led
+	asm volatile("orr r1,r1,#0x0C \n");         // ..
+	asm volatile("strh r1,[r0,#16] \n");        // set LEDs
+
+	asm volatile("mov r15,r3 \n");
+	asm volatile("mov r0,r0 \n");
+	asm volatile("mov r0,r0 ");
+}
+
+static void
+loox720_pxa_ll_pm_suspend(unsigned long resume_addr)
+{
+//    register unsigned int R10 asm("r10");
+	int i;
+	u32 csum, tmp;
+	u32 * p;
+
+	tmp =  virt_to_phys(save);
+	if ((tmp>=0xa8024000)&&(tmp<=0xa824036))
+		panic("Resume storage should not be overwritten");
+
+	tmp = virt_to_phys(test_resume);
+
+	if ((tmp>=0xa8024000)&&(tmp<=0xa824036))
+		panic("Resume handler should not be overwritten");
+	/* Make sure that bootloader will not found reset pattern
+	 * by setting special memory places to 0x00 */
+
+	p = phys_to_virt(0xA8025304);
+	if (!p)
+		panic("Tried to put sleep informations into unmapped memory!");
+	if (*p == 0x1A2B3C4D)
+		*p = 0;
+
+	p = phys_to_virt(0xA8025314);
+	if (!p)
+		panic("Tried to put sleep informations into unmapped memory!");
+	if (*p == 0x1A2B3C4D)
+		*p = 0;
+
+	/* Save the first 4 words from 0xa8024000. */
+	p = phys_to_virt(0xA8024000);
+	if (!p)
+		panic("Tried to put sleep informations into unmapped memory!");
+	for (i = 0; i < 6; i++)
+		save[i] = p[i];
+
+	/* Set the first four words at 0xa8024000 to:
+	 * resume address; MMU control; TLB base addr; domain id */
+	p[0] = tmp;//(unsigned int) test_resume;//resume_addr;
+
+asm( "mrc\tp15, 0, %0, c1, c0, 0" : "=r" (tmp) );
+	p[1] = tmp & (~0xFFFF3987);         /* mmu off */
+
+asm( "mrc\tp15, 0, %0, c2, c0, 0" : "=r" (tmp) );
+	p[2] = tmp & 0xFFFFC000;        /* Shouldn't matter, since MMU will be off. */
+
+asm( "mrc\tp15, 0, %0, c3, c0, 0" : "=r" (tmp) );
+	p[3] = tmp;     /* Shouldn't matter, since MMU will be off. */
+	p[4] = resume_addr;
+	p[5] = virt_to_phys(save);
+
+	/* Set PSPR to the checksum the HTC bootloader wants to see. */
+	//pr_debug("loox720_pxa_ll_pm_resume: Saving system state...\n");
+	for (csum = 0, i = 0; i < 54; i++) {
+		tmp = p[i] & 0x1;
+		tmp = tmp << 31;
+		tmp |= tmp >> 1;
+		csum += tmp;
+		//      pr_debug("offset: %2x - value: %8x - checksum: %8x", i*4, p[i], csum);
+	}
+
+	PSPR = csum;
+/* clear the Fastbus bit as for some reason letting it set leads to crash on resume */
+__asm__ volatile ("mrc p14, 0, r3, c6, c0, 0\n"
+                  "bic	r3, r3, #8\n"
+                  "mcr p14, 0, r3, c6, c0, 0\n"
+                 :::"r3");
+}
+
+extern void pxa27x_cpu_pm_restore(unsigned long *sleep_save);
+void loox720_cpu_pm_restore(unsigned long *sleep_save)
+{
+	int i;
+	u32 *p;
+
+	/* Restore the data at 0xa8024000. */
+	for (p = phys_to_virt(0xa8024000), i = 0; i < 5; i++)
+	      p[i] = save[i];
+	
+	pxa27x_cpu_pm_restore(sleep_save);
+
+	/* XXX Do we need to flush the cache? */
+	/*
+	__asm__ volatile ("mrc p14, 0, r3, c6, c0, 0\n"
+	        "orr r3, r3, #0x0008\n"
+	        "mcr p14, 0, r3, c6, c0, 0\n"
+	        :::"r3");
+	        */
+
+}
+
+void loox720_cpu_pm_enter(suspend_state_t state)
+{
+	extern void pxa_cpu_standby(void);
+
+	/* ensure voltage-change sequencer not initiated, which hangs -что то про зарядку..убедимся....блаблабла */
+//	PCFR &= ~PCFR_FVC;
+
+	/* Clear edge-detect status register. */
+//	PEDR = 0xDF12FE1B;
+
+	/* Clear reset status */
+//	RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+
+//	switch (state) {
+//	case PM_SUSPEND_STANDBY:
+//		printk("enter PM_SUSPEND_STANDBY\n");
+//		pxa_cpu_standby();
+//		break;
+//	case PM_SUSPEND_MEM:
+//		/* set resume return address */
+//		printk("enter PM_SUSPEND_MEM\n");
+//		loox720_pxa_ll_pm_suspend(virt_to_phys(pxa_cpu_resume));
+//		pxa27x_cpu_suspend(PWRMODE_SLEEP);
+//		break;
+//	}
+}
+
+static int loox720_cpu_pm_valid(suspend_state_t state)
+{
+	return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY;
+}
+
+extern void pxa27x_cpu_pm_save(unsigned long *sleep_save);
+
+enum {	SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3,
+
+	SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
+	SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U,
+	SLEEP_SAVE_GAFR2_L, SLEEP_SAVE_GAFR2_U,
+	SLEEP_SAVE_GAFR3_L, SLEEP_SAVE_GAFR3_U,
+
+	SLEEP_SAVE_PSTR,
+
+	SLEEP_SAVE_CKEN,
+
+	SLEEP_SAVE_MDREFR,
+	SLEEP_SAVE_PWER, SLEEP_SAVE_PCFR, SLEEP_SAVE_PRER,
+	SLEEP_SAVE_PFER, SLEEP_SAVE_PKWR,
+
+	SLEEP_SAVE_COUNT
+};
+
+static struct pxa_cpu_pm_fns loox720_cpu_pm_fns = {
+	.save_count	= SLEEP_SAVE_COUNT,
+	.save		= pxa27x_cpu_pm_save,
+	.restore	= loox720_cpu_pm_restore,
+	.valid		= loox720_cpu_pm_valid,
+	.enter		= loox720_cpu_pm_enter,
+};
+
+static int
+loox720_pm_probe( struct platform_device *pdev )
+{
+	pxa_cpu_pm_fns = &loox720_cpu_pm_fns;
+	return 0;
+}
+
+static int
+loox720_pm_remove( struct platform_device *dev )
+{
+	return 0;
+}
+
+struct platform_driver loox720_pm_driver = {
+	.driver = {
+		.name     = "loox550-pm",
+	},
+	.probe    = loox720_pm_probe,
+	.remove   = loox720_pm_remove,
+	.suspend  = loox720_suspend,
+	.resume   = loox720_resume,
+};
+
+static int __init
+loox720_pm_init( void )
+{
+	return platform_driver_register( &loox720_pm_driver );
+}
+
+
+static void __exit
+loox720_pm_exit( void )
+{
+	platform_driver_unregister( &loox720_pm_driver );
+}
+
+module_init( loox720_pm_init );
+module_exit( loox720_pm_exit );
+
+MODULE_AUTHOR("Tomasz Figa");
+MODULE_DESCRIPTION("Loox 720 Power Management Support");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/mach-pxa/loox550/loox5xx_leds.c b/arch/arm/mach-pxa/loox550/loox5xx_leds.c
new file mode 100644
index 0000000..97cca36
--- /dev/null
+++ b/arch/arm/mach-pxa/loox550/loox5xx_leds.c
@@ -0,0 +1,379 @@
+/*
+ *
+ * Leds support for Fujitsu-Siemens Loox 5xx PDAs
+ *
+ * Evgeny Chukreev <akshaal@akshaal.info>   http://www.akshaal.info
+ * (C) 2009
+ *
+ * GNU GPL
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+
+#include <asm/gpio.h>
+#include <mach/gpio.h>
+#include <mach/loox550-gpio.h>
+#include <mach/loox5xx_leds.h>
+
+// Leds mode stuff
+DEFINE_SPINLOCK(loox5xx_leds_mode_lock);
+static u32 leds_mode = 0; // If a bit is enabled, then special mode is forced for the bit
+static u32 leds_forced_value = 0; // Only valid for bits enabled in leds_mode
+
+#define MODE_PWR_LED_ANY 0
+#define MODE_PWR_LED_OFF 1
+#define MODE_PWR_LED_ON 2
+#define MODE_PWR_LED_BLINK 3
+
+static u8 leds_pwr_mode = MODE_PWR_LED_ANY;
+
+// Current state
+DEFINE_SPINLOCK(loox5xx_leds_state_lock);
+static u32 leds_state = 0;
+static u8 leds_pwr_state = MODE_PWR_LED_OFF;
+
+// //////////////////////////////////////////////////////////////////////////
+// Leds state modification
+
+// Update keyboard led register
+static inline void update_keyboard_led (void) {
+    gpio_set_value (LOOX5XX_EGPIO_LED_7, leds_state & LOOX5XX_LED_KEYBOARD);
+}
+
+// Update left leds register
+static inline void update_left_leds (void) {
+    // Convert from bit-per-led form to stupid register form
+    // We could have done it with a table but it would mean no less code
+    
+    u32 left_state = leds_state & (  LOOX5XX_LED_LEFT_ORANGE
+		                   | LOOX5XX_LED_LEFT_BLUE
+                	           | LOOX5XX_LED_LEFT_GREEN);
+    
+    u32 regv =
+	(left_state == (  LOOX5XX_LED_LEFT_ORANGE
+	 	        | LOOX5XX_LED_LEFT_BLUE
+  		        | LOOX5XX_LED_LEFT_GREEN)) ? 7 :
+
+	(left_state == (  LOOX5XX_LED_LEFT_ORANGE
+	 	        | LOOX5XX_LED_LEFT_BLUE))  ? 6 :
+
+	(left_state == (  LOOX5XX_LED_LEFT_ORANGE
+  		        | LOOX5XX_LED_LEFT_GREEN)) ? 5 :
+
+	(left_state == (  LOOX5XX_LED_LEFT_BLUE
+  		        | LOOX5XX_LED_LEFT_GREEN)) ? 4 :
+
+	(left_state == LOOX5XX_LED_LEFT_ORANGE)    ? 3 :
+	(left_state == LOOX5XX_LED_LEFT_BLUE)      ? 2 :
+	(left_state == LOOX5XX_LED_LEFT_GREEN)     ? 1 :
+						     0;
+
+    gpio_set_value (LOOX5XX_EGPIO_LED_4, regv & 1);
+    gpio_set_value (LOOX5XX_EGPIO_LED_5, regv & 2);
+    gpio_set_value (LOOX5XX_EGPIO_LED_6, regv & 4);
+}
+
+// Update right leds register
+static inline void update_right_leds (void) {
+    // Convert from bit-per-led form to stupid register form.
+    // Blinking green led has higher precedence than orange led
+    u32 green = leds_state & LOOX5XX_LED_RIGHT_GREEN;
+    
+    u32 regv =
+	(leds_pwr_state == MODE_PWR_LED_BLINK && green) ? 4 :
+	(leds_pwr_state == MODE_PWR_LED_BLINK)          ? 3 :
+	green                                           ? 2 :
+	(leds_pwr_state == MODE_PWR_LED_ON)             ? 1 :
+							  0;
+
+    gpio_set_value (LOOX5XX_EGPIO_LED_1, regv & 1);
+    gpio_set_value (LOOX5XX_EGPIO_LED_2, regv & 2);
+    gpio_set_value (LOOX5XX_EGPIO_LED_3, regv & 4);
+}
+
+// Takes forces state into account and calls update functions for
+// changed registers
+static inline void commit_new_leds_state (u32 new_leds_state) {
+    u32 old_leds_state;
+
+    // Set forced bits on
+    new_leds_state |= leds_mode & leds_forced_value;
+
+    // Clear foced bits off
+    new_leds_state &= (~leds_mode) | leds_forced_value;
+
+    // Return if nothing really changed
+    if (new_leds_state == leds_state) {
+	return;
+    }
+
+    // Change shadow state
+    old_leds_state = leds_state;
+    leds_state = new_leds_state;
+
+    // Update keyboard register if changed
+    if ((old_leds_state & LOOX5XX_LED_KEYBOARD)
+	    != (new_leds_state & LOOX5XX_LED_KEYBOARD))
+    {
+	update_keyboard_led ();
+    }
+
+    // Update reft leds register if changed
+    if ((old_leds_state & (LOOX5XX_LED_LEFT_GREEN
+		           | LOOX5XX_LED_LEFT_BLUE
+			   | LOOX5XX_LED_LEFT_ORANGE))
+	    != (new_leds_state & (LOOX5XX_LED_LEFT_GREEN
+	 	                  | LOOX5XX_LED_LEFT_BLUE
+    		      	          | LOOX5XX_LED_LEFT_ORANGE)))
+    {
+	update_left_leds ();
+    }
+
+    // Update right register if changed
+    if ((old_leds_state & LOOX5XX_LED_RIGHT_GREEN)
+	    != (new_leds_state & LOOX5XX_LED_RIGHT_GREEN))
+    {
+	update_right_leds ();
+    }
+}
+
+// Takes forces state into account and calls update functions for
+// changed registers
+static inline void commit_new_leds_pwr_state (u8 new_pwr_state) {
+    // Applying 'force' mode
+    if (leds_pwr_mode != MODE_PWR_LED_ANY) {
+	new_pwr_state = leds_pwr_mode;
+    }
+
+    if (new_pwr_state == leds_pwr_state) {
+	return;
+    }
+
+    leds_pwr_state = new_pwr_state;
+    update_right_leds ();
+}
+
+// //////////////////////////////////////////////////////////////////////////
+// These functions are for leds having two states
+
+void loox5xx_enable_leds (u32 leds) {
+    spin_lock(&loox5xx_leds_state_lock);
+
+    commit_new_leds_state (leds_state | leds);
+
+    spin_unlock(&loox5xx_leds_state_lock);
+}
+
+void loox5xx_disable_leds (u32 leds) {
+    spin_lock(&loox5xx_leds_state_lock);
+
+    commit_new_leds_state (leds_state & (~leds));
+
+    spin_unlock(&loox5xx_leds_state_lock);
+}
+
+// //////////////////////////////////////////////////////////////////////////
+// Power led has three states
+
+void loox5xx_enable_power_led (void) {
+    spin_lock(&loox5xx_leds_state_lock);
+
+    commit_new_leds_pwr_state (MODE_PWR_LED_ON);
+
+    spin_unlock(&loox5xx_leds_state_lock);
+}
+
+void loox5xx_disable_power_led (void) {
+    spin_lock(&loox5xx_leds_state_lock);
+
+    commit_new_leds_pwr_state (MODE_PWR_LED_OFF);
+
+    spin_unlock(&loox5xx_leds_state_lock);
+}
+
+void loox5xx_blink_power_led (void) {
+    spin_lock(&loox5xx_leds_state_lock);
+
+    commit_new_leds_pwr_state (MODE_PWR_LED_BLINK);
+
+    spin_unlock(&loox5xx_leds_state_lock);
+}
+
+// //////////////////////////////////////////////////////////////////////////
+// Device attributes
+
+struct device_led_attribute {
+    struct device_attribute        device_attr;
+    u32 led;
+};
+
+#define DEVICE_2STATE_LED_ATTR(_name, _led) \
+    struct device_led_attribute dev_led_attr_##_name = \
+       { .device_attr = __ATTR(_name, 0644, show_2state_led_attr, store_2state_led_attr), \
+	 .led = _led, }
+
+// Writes current state of led into the given buffer
+static ssize_t show_2state_led_attr (struct device *dev,
+	   		             struct device_attribute *attr,
+			             char *buf)
+{
+    struct device_led_attribute *led_attr = (struct device_led_attribute *) attr;
+    char *mode;
+
+    spin_lock(&loox5xx_leds_mode_lock);
+    if (leds_mode & led_attr->led) {
+	if (leds_forced_value & led_attr->led) {
+	    mode = "on";
+	} else {
+	    mode = "off";
+	}
+    } else {
+	mode = "any";
+    }
+    spin_unlock(&loox5xx_leds_mode_lock);
+
+    return sprintf(buf, "%s\n", mode);
+}
+
+// Reads new state for led from the given buffer
+static ssize_t store_2state_led_attr (struct device *dev,
+				      struct device_attribute *attr,
+		                      const char *buf,
+				      size_t n)
+{
+    struct device_led_attribute *led_attr = (struct device_led_attribute *) attr;
+
+    spin_lock(&loox5xx_leds_mode_lock);
+    if (!strncmp (buf, "on", 2)) {
+	leds_mode |= led_attr->led;
+	leds_forced_value |= led_attr->led;
+        loox5xx_enable_leds (led_attr->led);
+    } else if (!strncmp (buf, "off", 3)) {
+	leds_mode |= led_attr->led;
+	leds_forced_value &= ~(led_attr->led);
+        loox5xx_disable_leds (led_attr->led);
+    } else if (!strncmp (buf, "any", 3)) {
+	leds_mode &= ~(led_attr->led);
+    }
+    spin_unlock(&loox5xx_leds_mode_lock);
+
+    return n;	    
+}
+
+// Writes current state of power led into the given buffer
+static ssize_t show_right_orange_attr (struct device *dev,
+	   		               struct device_attribute *attr,
+			               char *buf)
+{
+    char *smode;
+    u8 copied_mode;
+
+    spin_lock(&loox5xx_leds_mode_lock);
+    copied_mode = leds_pwr_mode;
+    spin_unlock(&loox5xx_leds_mode_lock);
+
+    smode = copied_mode == MODE_PWR_LED_ANY   ? "any"   :
+	    copied_mode == MODE_PWR_LED_ON    ? "on"    :
+	    copied_mode == MODE_PWR_LED_OFF   ? "off"   :
+	    copied_mode == MODE_PWR_LED_BLINK ? "blink" :
+	    "unknown";
+
+    return sprintf(buf, "%s\n", smode);
+}
+
+// Reads new state for power led from the given buffer
+static ssize_t store_right_orange_attr (struct device *dev,
+				        struct device_attribute *attr,
+		                        const char *buf,
+				        size_t n)
+{
+    spin_lock(&loox5xx_leds_mode_lock);
+    if (!strncmp (buf, "on", 2)) {
+	leds_pwr_mode = MODE_PWR_LED_ON;
+	loox5xx_enable_power_led ();
+    } else if (!strncmp (buf, "off", 3)) {
+	leds_pwr_mode = MODE_PWR_LED_OFF;
+	loox5xx_disable_power_led ();
+    } else if (!strncmp (buf, "blink", 5)) {
+	leds_pwr_mode = MODE_PWR_LED_BLINK;
+	loox5xx_blink_power_led ();
+    } else if (!strncmp (buf, "any", 3)) {
+	leds_pwr_mode = MODE_PWR_LED_ANY;
+    }
+    spin_unlock(&loox5xx_leds_mode_lock);
+
+    return n;	    
+}
+
+// Attributes
+static DEVICE_2STATE_LED_ATTR(keyboard, LOOX5XX_LED_KEYBOARD);
+static DEVICE_2STATE_LED_ATTR(left_green, LOOX5XX_LED_LEFT_GREEN);
+static DEVICE_2STATE_LED_ATTR(left_blue, LOOX5XX_LED_LEFT_BLUE);
+static DEVICE_2STATE_LED_ATTR(left_orange, LOOX5XX_LED_LEFT_ORANGE);
+static DEVICE_2STATE_LED_ATTR(right_green, LOOX5XX_LED_RIGHT_GREEN);
+
+static DEVICE_ATTR(right_orange, 0644, show_right_orange_attr, store_right_orange_attr);
+
+// //////////////////////////////////////////////////////////////////////////
+// Methods required for device drivers
+
+// Called upon driver instance intitialization
+static int loox5xx_leds_probe (struct platform_device *pdev) {
+    int err;
+
+    printk (KERN_NOTICE "Loox 5XX leds driver\n");
+
+    // Register device attributes visible through sysfs
+    err = device_create_file (&pdev->dev, &dev_led_attr_keyboard.device_attr);
+    err |= device_create_file (&pdev->dev, &dev_led_attr_left_green.device_attr);
+    err |= device_create_file (&pdev->dev, &dev_led_attr_left_blue.device_attr);
+    err |= device_create_file (&pdev->dev, &dev_led_attr_left_orange.device_attr);
+    err |= device_create_file (&pdev->dev, &dev_led_attr_right_green.device_attr);
+    err |= device_create_file (&pdev->dev, &dev_attr_right_orange);
+
+    if (err != 0) {
+	printk(KERN_WARNING "loox5xx-leds: failed to register attributes\n");
+    }
+
+    return 0;
+}
+
+// Called upon driver instance removing process
+static int loox5xx_leds_remove (struct platform_device *dev)
+{
+    return 0;
+}
+
+// //////////////////////////////////////////////////////////////////////////
+// Device driver description
+
+// Platform driver structure for loox5xx-leds driver
+static struct platform_driver loox5xx_leds_driver = {
+    .driver = {
+	.name     = "loox5xx-leds",
+    },
+    .probe    = loox5xx_leds_probe,
+    .remove   = loox5xx_leds_remove,
+};
+
+// Init function.. called upon module initialization
+static int __init loox5xx_leds_init (void) {
+    return platform_driver_register (&loox5xx_leds_driver);
+}
+
+// Exit function.. called upon module unload (if ever happens...)
+static void __exit loox5xx_leds_exit (void) {
+    platform_driver_unregister (&loox5xx_leds_driver);
+}
+
+module_init (loox5xx_leds_init);
+module_exit (loox5xx_leds_exit);
+
+MODULE_AUTHOR("Evgeny Chukreev <akshaal@akshaal.info>");
+MODULE_DESCRIPTION("Leds support for Fujitsu-Siemens Loox 5xx PDAs");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-pxa/loox550/looxn560_pm.c b/arch/arm/mach-pxa/loox550/looxn560_pm.c
new file mode 100644
index 0000000..cc852d1
--- /dev/null
+++ b/arch/arm/mach-pxa/loox550/looxn560_pm.c
@@ -0,0 +1,106 @@
+/*
+ * LooxN560 power management support for the original HTC IPL in DoC G4
+ *
+ * Use consistent with the GNU GPL is permitted, provided that this
+ * copyright notice is preserved in its entirety in all copies and
+ * derived works.
+ *
+ * Copyright (C) 2005 Pawel Kolodziejski
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/pm.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/pxa-regs.h>
+#include <mach/pxa-pm_ll.h>
+
+#ifdef CONFIG_PM
+
+static u32 *addr_a0000000;
+static u32 *addr_a0025304;
+static u32 *addr_a0200000;
+static u32 *addr_a0200040;
+
+static u32 *addr_a0201000;
+static u32 *addr_a0201004;
+static u32 *addr_a0201008;
+static u32 *addr_a020100c;
+
+static u32 save_a0000000;
+static u32 save_a0025304;
+static u32 save_a0200000;
+static u32 save_a0200040;
+
+static u32 save_a0201000;
+static u32 save_a0201004;
+static u32 save_a0201008;
+static u32 save_a020100c;
+
+#if 0
+a0025304 warm
+a0025314 cold
+#endif
+
+static void pxa_ll_pm_suspend(unsigned long resume_addr)
+{
+	save_a0201000 = *addr_a0201000;
+	save_a0201004 = *addr_a0201004;
+	save_a0201008 = *addr_a0201008;
+	save_a020100c = *addr_a020100c;
+
+         save_a0025304 = *addr_a0025304;
+//        *addr_a0025304 = 0x0 ; /* != 0x1a2b3c4d */
+
+         save_a0200000 = *addr_a0200000;
+        *addr_a0200000 = 0xea0003fe ; /* b 0x1000 */
+
+         save_a0200040 = *addr_a0200040;
+        *addr_a0200040 = 0x43454345 ; /* "ECEC" */
+
+         save_a0000000 = *addr_a0000000;
+
+	/* jump to PSPR */
+	*addr_a0201000 = 0xe3a00101; // mov r0, #0x40000000
+	*addr_a0201004 = 0xe380060f; // orr r0, r0, #0x0f000000
+	*addr_a0201008 = 0xe3800008; // orr r0, r0, #8
+	*addr_a020100c = 0xe590f000; // ldr pc, [r0]
+}
+
+static void pxa_ll_pm_resume(void)
+{
+	*addr_a0201000 = save_a0201000;
+	*addr_a0201004 = save_a0201004;
+	*addr_a0201008 = save_a0201008;
+	*addr_a020100c = save_a020100c;
+
+	*addr_a0200000 = save_a0200000;
+	*addr_a0200040 = save_a0200040;
+	*addr_a0025304 = save_a0025304;
+	*addr_a0000000 = save_a0000000;
+
+}
+
+static struct pxa_ll_pm_ops n560_ll_pm_ops = {
+	.suspend = pxa_ll_pm_suspend,
+	.resume  = pxa_ll_pm_resume,
+};
+
+void n560_ll_pm_init(void) {
+	addr_a0201000 = phys_to_virt(0xa0201000);
+	addr_a0201004 = phys_to_virt(0xa0201004);
+	addr_a0201008 = phys_to_virt(0xa0201008);
+	addr_a020100c = phys_to_virt(0xa020100c);
+
+	addr_a0000000 = phys_to_virt(0xa0000000);
+	addr_a0025304 = phys_to_virt(0xa0025304);
+	addr_a0200000 = phys_to_virt(0xa0200000);
+	addr_a0200040 = phys_to_virt(0xa0200040);
+
+	pxa_pm_set_ll_ops(&n560_ll_pm_ops);
+}
+#endif /* CONFIG_PM */
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 831e1fd..99d34c8 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -251,6 +251,7 @@ realview_pb11mp		MACH_REALVIEW_PB11MP	REALVIEW_PB11MP		1407
 mx27_3ds		MACH_MX27_3DS		MX27_3DS		1430
 halibut			MACH_HALIBUT		HALIBUT			1439
 trout			MACH_TROUT		TROUT			1440
+looxn560                MACH_LOOXN560           LOOXN560                1454
 tct_hammer		MACH_TCT_HAMMER		TCT_HAMMER		1460
 herald			MACH_HERALD		HERALD			1461
 sim_one			MACH_SIM_ONE		SIM_ONE			1476
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index e7ce729..0cfe50c 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_LCD_ILI9320)	   += ili9320.o
 obj-$(CONFIG_LCD_PLATFORM)	   += platform_lcd.o
 obj-$(CONFIG_LCD_VGG2432A4)	   += vgg2432a4.o
 obj-$(CONFIG_LCD_TDO24M)	   += tdo24m.o
+obj-$(CONFIG_LCD_LOOX550)       += loox550_lcd.o
 obj-$(CONFIG_LCD_TOSA)		   += tosa_lcd.o
 obj-$(CONFIG_LCD_S6E63M0)	+= s6e63m0.o
 obj-$(CONFIG_LCD_LD9040)	+= ld9040.o
@@ -35,6 +36,7 @@ obj-$(CONFIG_BACKLIGHT_DA9052)	+= da9052_bl.o
 obj-$(CONFIG_BACKLIGHT_MAX8925)	+= max8925_bl.o
 obj-$(CONFIG_BACKLIGHT_APPLE)	+= apple_bl.o
 obj-$(CONFIG_BACKLIGHT_TOSA)	+= tosa_bl.o
+obj-$(CONFIG_BACKLIGHT_LOOX550) += loox550_bl.o
 obj-$(CONFIG_BACKLIGHT_SAHARA)	+= kb3886_bl.o
 obj-$(CONFIG_BACKLIGHT_WM831X)	+= wm831x_bl.o
 obj-$(CONFIG_BACKLIGHT_ADP5520)	+= adp5520_bl.o
diff --git a/drivers/video/backlight/loox550_bl.c b/drivers/video/backlight/loox550_bl.c
new file mode 100644
index 0000000..15bb5dd
--- /dev/null
+++ b/drivers/video/backlight/loox550_bl.c
@@ -0,0 +1,162 @@
+/*
+ * backlight driver for Fujitsu-Siemens Loox 720
+ * based on the corgi_bl.c backlight driver by Richard Purdie
+ *
+ * Authors: Harald Radke, Tomasz Figa
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/notifier.h>
+#include <linux/backlight.h>
+#include <linux/err.h>
+
+//include <asm/arch/loox720-gpio.h>
+//include <asm/arch/loox720-cpld.h>
+#include <linux/fb.h>
+#include <asm/mach-types.h>
+#include <linux/platform_device.h>
+#include <mach/pxa2xx-regs.h>
+
+
+#define LOOX720_MAX_INTENSITY 0xc8
+#define LOOX720_DEFAULT_INTENSITY (LOOX720_MAX_INTENSITY / 4)
+
+
+static uint reg_pwduty0,reg_perval0;
+
+/*--------------------------------------------------------------------------------*/
+
+static void loox720_set_bl_intensity(int intensity)
+{
+	if (intensity < 7) intensity = 0;
+
+	PWM_CTRL0 = 1;
+	PWM_PWDUTY0 = intensity;
+	PWM_PERVAL0 = LOOX720_MAX_INTENSITY;
+
+	if (intensity > 0) {
+//		loox720_egpio_set_bit(LOOX720_CPLD_BACKLIGHT_BIT, 1);
+		PWM_CTRL0 = 1;
+	} else {
+//		loox720_egpio_set_bit(LOOX720_CPLD_BACKLIGHT_BIT, 0);
+		PWM_CTRL0 = 0;
+	}
+}
+
+/*---------------------------------------------------------------------------------*/
+
+static int loox720_bl_update_status(struct backlight_device *bd) 
+{
+  int intensity = bd->props.brightness;
+
+	if (bd->props.power != FB_BLANK_UNBLANK)
+		intensity = 0;
+	if (bd->props.fb_blank != FB_BLANK_UNBLANK)
+		intensity = 0;
+	loox720_set_bl_intensity(intensity);
+	return 0;
+}
+
+/*--------------------------------------------------------------------------------*/
+
+static	int loox720_bl_get_brightness(struct backlight_device *bd){
+  return PWM_PWDUTY0 & 0xff;
+}
+
+/*--------------------------------------------------------------------------------*/
+
+static struct backlight_ops loox720_bl_ops = {
+	.update_status = loox720_bl_update_status,
+	.get_brightness = loox720_bl_get_brightness,
+};
+
+#ifdef CONFIG_PM
+/*---------------------------------------------------------------------------------*/
+static int loox720_bl_suspend (struct platform_device *pdev, pm_message_t message)
+{
+	reg_pwduty0 = PWM_PWDUTY0;
+	reg_perval0 = PWM_PERVAL0;
+	PWM_CTRL0 = 0;
+//	loox720_egpio_set_bit(LOOX720_CPLD_BACKLIGHT_BIT, 0);
+	return 0;
+}
+
+/*---------------------------------------------------------------------------------*/
+
+static int loox720_bl_resume (struct platform_device *pdev)
+{
+	PWM_CTRL0 = 1;
+	PWM_PWDUTY0 = reg_pwduty0;
+	PWM_PERVAL0 = reg_perval0;
+//	loox720_egpio_set_bit(LOOX720_CPLD_BACKLIGHT_BIT, 1);
+	return 0;
+}
+
+/*---------------------------------------------------------------------------------*/
+#else
+#define loox720_bl_suspend NULL
+#define loox720_bl_resume NULL
+#endif
+
+static int loox720_bl_probe (struct platform_device *pdev)
+{
+	struct backlight_device *bl_device;
+	struct backlight_properties props;
+	// TODO improve settings
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.max_brightness = LOOX720_MAX_INTENSITY;
+	bl_device = backlight_device_register ("loox550-bl", &pdev->dev, NULL, &loox720_bl_ops, &props);
+	if (IS_ERR (bl_device))
+		return -1;
+	platform_set_drvdata(pdev, bl_device);
+	bl_device->props.power = FB_BLANK_UNBLANK;
+	bl_device->props.brightness = LOOX720_DEFAULT_INTENSITY;
+	backlight_update_status(bl_device);
+	return 0;
+}
+
+/*---------------------------------------------------------------------------------*/
+
+static int loox720_bl_remove (struct platform_device *pdev)
+{
+	struct backlight_device *bd = platform_get_drvdata(pdev);
+	backlight_update_status(bd);
+	backlight_device_unregister(bd);
+	return 0;
+}
+
+/*---------------------------------------------------------------------------------*/
+
+static struct platform_driver loox720_bl_driver = {
+	.probe		= loox720_bl_probe,
+	.remove		= loox720_bl_remove,
+	.suspend	= loox720_bl_suspend,
+	.resume		= loox720_bl_resume,
+	.driver		= {
+		.name	= "loox550-bl",
+	},
+};
+
+static int __init loox720_bl_init(void)
+{
+	return platform_driver_register(&loox720_bl_driver);
+}
+
+
+static void __exit loox720_bl_exit (void)
+{
+	platform_driver_unregister(&loox720_bl_driver);
+}
+
+module_init (loox720_bl_init);
+module_exit (loox720_bl_exit);
+
+MODULE_AUTHOR("Harald Radke, Tomasz Figa");
+MODULE_DESCRIPTION("Loox 718/720 LCD backlight driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/video/backlight/loox550_lcd.c b/drivers/video/backlight/loox550_lcd.c
new file mode 100644
index 0000000..bd37135
--- /dev/null
+++ b/drivers/video/backlight/loox550_lcd.c
@@ -0,0 +1,167 @@
+/*
+ * LCD device driver for Fujitsu-Siemens Loox 720
+ *
+ *
+ * Authors: Harald Radke, Tomasz Figa
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/notifier.h>
+#include <linux/lcd.h>
+#include <linux/err.h>
+
+//include <asm/arch/loox720-gpio.h>
+//include <asm/arch/loox720-cpld.h>
+#include <linux/fb.h>
+#include <mach/pxa2xx-regs.h>
+#include <asm/mach-types.h>
+#include <linux/platform_device.h>
+
+
+
+#define LOOX720_MAX_CONTRAST 255
+#define LOOX720_DEFAULT_CONTRAST 77
+
+static uint reg_perval1,reg_pwduty1;
+static int loox_720_lcd_power_status;
+/*--------------------------------------------------------------------------------*/
+
+static int loox720_lcd_set_contrast(struct lcd_device *lcd, int contrast)
+{
+	PWM_PWDUTY1 = contrast;
+	return 0;
+}
+
+/*--------------------------------------------------------------------------------*/
+
+static	int loox720_lcd_get_contrast(struct lcd_device *lcd){
+	return PWM_PWDUTY1 & 0xff;
+}
+
+/*--------------------------------------------------------------------------------*/
+
+static int loox720_lcd_set_power (struct lcd_device *lcd, int power)
+{
+      loox_720_lcd_power_status = power;
+      if (power == FB_BLANK_UNBLANK) {
+		printk("loox720_lcd_set_power power == FB_BLANK_UNBLANK\n");
+//		loox720_egpio_set_bit(LOOX720_CPLD_LCD_COLOR_BIT, 1);
+//		loox720_egpio_set_bit(LOOX720_CPLD_LCD_CONSOLE_BIT, 1);
+//		loox720_egpio_set_bit(LOOX720_CPLD_LCD_BIT2, 1);
+//		loox720_egpio_set_bit(LOOX720_CPLD_LCD_BIT, 1);
+		PWM_CTRL1 = 1;
+	} else {
+		printk("loox720_lcd_set_power power == FB_BLANK_UNBLANK\n");
+//		loox720_egpio_set_bit(LOOX720_CPLD_LCD_BIT2, 0);
+//		loox720_egpio_set_bit(LOOX720_CPLD_LCD_CONSOLE_BIT, 0);
+//		loox720_egpio_set_bit(LOOX720_CPLD_LCD_BIT, 0);
+//		loox720_egpio_set_bit(LOOX720_CPLD_LCD_COLOR_BIT, 0);
+		PWM_CTRL1 = 0;
+
+	}
+	return 0;
+}
+    
+/*--------------------------------------------------------------------------------*/
+
+static int loox720_lcd_get_power (struct lcd_device *lcd) {
+	return loox_720_lcd_power_status;
+}
+
+/*--------------------------------------------------------------------------------*/
+
+struct lcd_ops loox720_lcd_ops = {
+	.get_power = loox720_lcd_get_power,
+	.set_power = loox720_lcd_set_power,
+	.get_contrast = loox720_lcd_get_contrast,
+        .set_contrast = loox720_lcd_set_contrast,
+};
+
+
+#ifdef CONFIG_PM
+/*---------------------------------------------------------------------------------*/
+static int loox720_lcd_suspend (struct platform_device *pdev, pm_message_t message)
+{
+	struct lcd_device *lcd_device=platform_get_drvdata(pdev);
+	reg_pwduty1 = PWM_PWDUTY1;
+	reg_perval1 = PWM_PERVAL1;
+	lcd_set_power(lcd_device,FB_BLANK_POWERDOWN);
+	return 0;
+}
+
+/*---------------------------------------------------------------------------------*/
+
+static int loox720_lcd_resume (struct platform_device *pdev)
+{
+	struct lcd_device *lcd_device=platform_get_drvdata(pdev);
+	PWM_PWDUTY1 = reg_pwduty1;
+	PWM_PERVAL1 = reg_perval1;
+	lcd_set_power(lcd_device,FB_BLANK_UNBLANK);
+	return 0;
+}
+
+/*---------------------------------------------------------------------------------*/
+#else
+#define loox720_lcd_suspend NULL
+#define loox720_lcd_resume NULL
+#endif
+
+static int loox720_lcd_probe (struct platform_device *pdev)
+{
+	struct lcd_device *lcd_device;
+	
+	lcd_device = lcd_device_register ("loox550-lcd", &pdev->dev, NULL, &loox720_lcd_ops);
+	if (IS_ERR (lcd_device))
+		return -1;
+	platform_set_drvdata(pdev, lcd_device);
+	lcd_device->props.max_contrast = LOOX720_MAX_CONTRAST;
+	lcd_set_power(lcd_device,FB_BLANK_UNBLANK);
+	loox720_lcd_set_contrast(lcd_device,LOOX720_DEFAULT_CONTRAST);
+	return 0;
+}
+
+/*---------------------------------------------------------------------------------*/
+
+static int loox720_lcd_remove (struct platform_device *pdev)
+{
+	struct backlight_device *bd = platform_get_drvdata(pdev);
+	backlight_update_status(bd);
+	backlight_device_unregister(bd);
+	return 0;
+}
+
+/*---------------------------------------------------------------------------------*/
+
+static struct platform_driver loox720_lcd_driver = {
+	.probe		= loox720_lcd_probe,
+	.remove		= loox720_lcd_remove,
+	.suspend	= loox720_lcd_suspend,
+	.resume		= loox720_lcd_resume,
+	.driver		= {
+		.name	= "loox550-lcd",
+	},
+};
+
+static int __init loox720_lcd_init(void)
+{
+	return platform_driver_register(&loox720_lcd_driver);
+}
+
+
+static void __exit loox720_lcd_exit (void)
+{
+	platform_driver_unregister(&loox720_lcd_driver);
+}
+
+module_init (loox720_lcd_init);
+module_exit (loox720_lcd_exit);
+
+MODULE_AUTHOR("Harald Radke, Tomasz Figa");
+MODULE_DESCRIPTION("Loox 718/720 LCD device driver");
+MODULE_LICENSE("GPL");
+
-- 
1.8.4.2

