Merge branch 'for-rmk' of git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6 into devel
diff --git a/MAINTAINERS b/MAINTAINERS
index 581fedc..1ab1b7f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -680,6 +680,13 @@
 L:	linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:	Maintained
 
+ARM/H4700 (HP IPAQ HX4700) MACHINE SUPPORT
+P:	Philipp Zabel
+M:	philipp.zabel@gmail.com
+S:	Maintained
+F:	arch/arm/mach-pxa/hx4700.c
+F:	arch/arm/mach-pxa/include/mach/hx4700.h
+
 ARM/HP JORNADA 7XX MACHINE SUPPORT
 P:	Kristoffer Ericson
 M:	kristoffer.ericson@gmail.com
@@ -4627,7 +4634,7 @@
 
 PXA2xx/PXA3xx SUPPORT
 P:	Eric Miao
-M:	eric.miao@marvell.com
+M:	eric.y.miao@gmail.com
 P:	Russell King
 M:	linux@arm.linux.org.uk
 L:	linux-arm-kernel@lists.arm.linux.org.uk	(subscribers-only)
@@ -4641,19 +4648,19 @@
 
 PXA168 SUPPORT
 P:	Eric Miao
-M:	eric.miao@marvell.com
+M:	eric.y.miao@gmail.com
 P:	Jason Chagas
 M:	jason.chagas@marvell.com
 L:	linux-arm-kernel@lists.arm.linux.org.uk	(subscribers-only)
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git
-S:	Supported
+S:	Maintained
 
 PXA910 SUPPORT
 P:	Eric Miao
-M:	eric.miao@marvell.com
+M:	eric.y.miao@gmail.com
 L:	linux-arm-kernel@lists.arm.linux.org.uk	(subscribers-only)
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git
-S:	Supported
+S:	Maintained
 
 PXA MMCI DRIVER
 S:	Orphan
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index 08f2786..4efbb9d 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -35,10 +35,6 @@
 config SHARP_PARAM
 	bool
 
-config SHARPSL_PM
-	bool
-	select APM_EMULATION
-
 config SHARP_SCOOP
 	bool
 
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 7cb7961..76be7ff 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -12,7 +12,6 @@
 obj-$(CONFIG_TIMER_ACORN)	+= time-acorn.o
 obj-$(CONFIG_SHARP_LOCOMO)	+= locomo.o
 obj-$(CONFIG_SHARP_PARAM)	+= sharpsl_param.o
-obj-$(CONFIG_SHARPSL_PM)	+= sharpsl_pm.o
 obj-$(CONFIG_SHARP_SCOOP)	+= scoop.o
 obj-$(CONFIG_ARCH_IXP2000)	+= uengine.o
 obj-$(CONFIG_ARCH_IXP23XX)	+= uengine.o
diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c
deleted file mode 100644
index 140f1d7..0000000
--- a/arch/arm/common/sharpsl_pm.c
+++ /dev/null
@@ -1,859 +0,0 @@
-/*
- * Battery and Power Management code for the Sharp SL-C7xx and SL-Cxx00
- * series of PDAs
- *
- * Copyright (c) 2004-2005 Richard Purdie
- *
- * Based on code written by Sharp for 2.4 kernels
- *
- * 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.
- *
- */
-
-#undef DEBUG
-
-#include <linux/module.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/apm_bios.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/leds.h>
-#include <linux/apm-emulation.h>
-#include <linux/suspend.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <mach/pm.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/regs-rtc.h>
-#include <mach/sharpsl.h>
-#include <asm/hardware/sharpsl_pm.h>
-
-/*
- * Constants
- */
-#define SHARPSL_CHARGE_ON_TIME_INTERVAL        (msecs_to_jiffies(1*60*1000))  /* 1 min */
-#define SHARPSL_CHARGE_FINISH_TIME             (msecs_to_jiffies(10*60*1000)) /* 10 min */
-#define SHARPSL_BATCHK_TIME                    (msecs_to_jiffies(15*1000))    /* 15 sec */
-#define SHARPSL_BATCHK_TIME_SUSPEND            (60*10)                        /* 10 min */
-
-#define SHARPSL_WAIT_CO_TIME                   15  /* 15 sec */
-#define SHARPSL_WAIT_DISCHARGE_ON              100 /* 100 msec */
-#define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP   10  /* 10 msec */
-#define SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT   10  /* 10 msec */
-#define SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN   10  /* 10 msec */
-#define SHARPSL_CHARGE_WAIT_TIME               15  /* 15 msec */
-#define SHARPSL_CHARGE_CO_CHECK_TIME           5   /* 5 msec */
-#define SHARPSL_CHARGE_RETRY_CNT               1   /* eqv. 10 min */
-
-/*
- * Prototypes
- */
-#ifdef CONFIG_PM
-static int sharpsl_off_charge_battery(void);
-static int sharpsl_check_battery_voltage(void);
-static int sharpsl_fatal_check(void);
-#endif
-static int sharpsl_check_battery_temp(void);
-static int sharpsl_ac_check(void);
-static int sharpsl_average_value(int ad);
-static void sharpsl_average_clear(void);
-static void sharpsl_charge_toggle(struct work_struct *private_);
-static void sharpsl_battery_thread(struct work_struct *private_);
-
-
-/*
- * Variables
- */
-struct sharpsl_pm_status sharpsl_pm;
-DECLARE_DELAYED_WORK(toggle_charger, sharpsl_charge_toggle);
-DECLARE_DELAYED_WORK(sharpsl_bat, sharpsl_battery_thread);
-DEFINE_LED_TRIGGER(sharpsl_charge_led_trigger);
-
-
-static int get_percentage(int voltage)
-{
-	int i = sharpsl_pm.machinfo->bat_levels - 1;
-	int bl_status = sharpsl_pm.machinfo->backlight_get_status ? sharpsl_pm.machinfo->backlight_get_status() : 0;
-	struct battery_thresh *thresh;
-
-	if (sharpsl_pm.charge_mode == CHRG_ON)
-		thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_acin_bl : sharpsl_pm.machinfo->bat_levels_acin;
-	else
-		thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_noac_bl : sharpsl_pm.machinfo->bat_levels_noac;
-
-	while (i > 0 && (voltage > thresh[i].voltage))
-		i--;
-
-	return thresh[i].percentage;
-}
-
-static int get_apm_status(int voltage)
-{
-	int low_thresh, high_thresh;
-
-	if (sharpsl_pm.charge_mode == CHRG_ON) {
-		high_thresh = sharpsl_pm.machinfo->status_high_acin;
-		low_thresh = sharpsl_pm.machinfo->status_low_acin;
-	} else {
-		high_thresh = sharpsl_pm.machinfo->status_high_noac;
-		low_thresh = sharpsl_pm.machinfo->status_low_noac;
-	}
-
-	if (voltage >= high_thresh)
-		return APM_BATTERY_STATUS_HIGH;
-	if (voltage >= low_thresh)
-		return APM_BATTERY_STATUS_LOW;
-	return APM_BATTERY_STATUS_CRITICAL;
-}
-
-void sharpsl_battery_kick(void)
-{
-	schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(125));
-}
-EXPORT_SYMBOL(sharpsl_battery_kick);
-
-
-static void sharpsl_battery_thread(struct work_struct *private_)
-{
-	int voltage, percent, apm_status, i = 0;
-
-	if (!sharpsl_pm.machinfo)
-		return;
-
-	sharpsl_pm.battstat.ac_status = (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN) ? APM_AC_ONLINE : APM_AC_OFFLINE);
-
-	/* Corgi cannot confirm when battery fully charged so periodically kick! */
-	if (!sharpsl_pm.machinfo->batfull_irq && (sharpsl_pm.charge_mode == CHRG_ON)
-			&& time_after(jiffies, sharpsl_pm.charge_start_time +  SHARPSL_CHARGE_ON_TIME_INTERVAL))
-		schedule_delayed_work(&toggle_charger, 0);
-
-	while(1) {
-		voltage = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
-
-		if (voltage > 0) break;
-		if (i++ > 5) {
-			voltage = sharpsl_pm.machinfo->bat_levels_noac[0].voltage;
-			dev_warn(sharpsl_pm.dev, "Warning: Cannot read main battery!\n");
-			break;
-		}
-	}
-
-	voltage = sharpsl_average_value(voltage);
-	apm_status = get_apm_status(voltage);
-	percent = get_percentage(voltage);
-
-	/* At low battery voltages, the voltage has a tendency to start
-           creeping back up so we try to avoid this here */
-	if ((sharpsl_pm.battstat.ac_status == APM_AC_ONLINE) || (apm_status == APM_BATTERY_STATUS_HIGH) ||  percent <= sharpsl_pm.battstat.mainbat_percent) {
-		sharpsl_pm.battstat.mainbat_voltage = voltage;
-		sharpsl_pm.battstat.mainbat_status = apm_status;
-		sharpsl_pm.battstat.mainbat_percent = percent;
-	}
-
-	dev_dbg(sharpsl_pm.dev, "Battery: voltage: %d, status: %d, percentage: %d, time: %ld\n", voltage,
-			sharpsl_pm.battstat.mainbat_status, sharpsl_pm.battstat.mainbat_percent, jiffies);
-
-#ifdef CONFIG_BACKLIGHT_CORGI
-	/* If battery is low. limit backlight intensity to save power. */
-	if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE)
-			&& ((sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_LOW) ||
-			(sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL))) {
-		if (!(sharpsl_pm.flags & SHARPSL_BL_LIMIT)) {
-			sharpsl_pm.machinfo->backlight_limit(1);
-			sharpsl_pm.flags |= SHARPSL_BL_LIMIT;
-		}
-	} else if (sharpsl_pm.flags & SHARPSL_BL_LIMIT) {
-		sharpsl_pm.machinfo->backlight_limit(0);
-		sharpsl_pm.flags &= ~SHARPSL_BL_LIMIT;
-	}
-#endif
-
-	/* Suspend if critical battery level */
-	if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE)
-			&& (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL)
-			&& !(sharpsl_pm.flags & SHARPSL_APM_QUEUED)) {
-		sharpsl_pm.flags |= SHARPSL_APM_QUEUED;
-		dev_err(sharpsl_pm.dev, "Fatal Off\n");
-		apm_queue_event(APM_CRITICAL_SUSPEND);
-	}
-
-	schedule_delayed_work(&sharpsl_bat, SHARPSL_BATCHK_TIME);
-}
-
-void sharpsl_pm_led(int val)
-{
-	if (val == SHARPSL_LED_ERROR) {
-		dev_err(sharpsl_pm.dev, "Charging Error!\n");
-	} else if (val == SHARPSL_LED_ON) {
-		dev_dbg(sharpsl_pm.dev, "Charge LED On\n");
-		led_trigger_event(sharpsl_charge_led_trigger, LED_FULL);
-	} else {
-		dev_dbg(sharpsl_pm.dev, "Charge LED Off\n");
-		led_trigger_event(sharpsl_charge_led_trigger, LED_OFF);
-	}
-}
-
-static void sharpsl_charge_on(void)
-{
-	dev_dbg(sharpsl_pm.dev, "Turning Charger On\n");
-
-	sharpsl_pm.full_count = 0;
-	sharpsl_pm.charge_mode = CHRG_ON;
-	schedule_delayed_work(&toggle_charger, msecs_to_jiffies(250));
-	schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(500));
-}
-
-static void sharpsl_charge_off(void)
-{
-	dev_dbg(sharpsl_pm.dev, "Turning Charger Off\n");
-
-	sharpsl_pm.machinfo->charge(0);
-	sharpsl_pm_led(SHARPSL_LED_OFF);
-	sharpsl_pm.charge_mode = CHRG_OFF;
-
-	schedule_delayed_work(&sharpsl_bat, 0);
-}
-
-static void sharpsl_charge_error(void)
-{
-	sharpsl_pm_led(SHARPSL_LED_ERROR);
-	sharpsl_pm.machinfo->charge(0);
-	sharpsl_pm.charge_mode = CHRG_ERROR;
-}
-
-static void sharpsl_charge_toggle(struct work_struct *private_)
-{
-	dev_dbg(sharpsl_pm.dev, "Toogling Charger at time: %lx\n", jiffies);
-
-	if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
-		sharpsl_charge_off();
-		return;
-	} else if ((sharpsl_check_battery_temp() < 0) || (sharpsl_ac_check() < 0)) {
-		sharpsl_charge_error();
-		return;
-	}
-
-	sharpsl_pm_led(SHARPSL_LED_ON);
-	sharpsl_pm.machinfo->charge(0);
-	mdelay(SHARPSL_CHARGE_WAIT_TIME);
-	sharpsl_pm.machinfo->charge(1);
-
-	sharpsl_pm.charge_start_time = jiffies;
-}
-
-static void sharpsl_ac_timer(unsigned long data)
-{
-	int acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN);
-
-	dev_dbg(sharpsl_pm.dev, "AC Status: %d\n",acin);
-
-	sharpsl_average_clear();
-	if (acin && (sharpsl_pm.charge_mode != CHRG_ON))
-		sharpsl_charge_on();
-	else if (sharpsl_pm.charge_mode == CHRG_ON)
-		sharpsl_charge_off();
-
-	schedule_delayed_work(&sharpsl_bat, 0);
-}
-
-
-irqreturn_t sharpsl_ac_isr(int irq, void *dev_id)
-{
-	/* Delay the event slightly to debounce */
-	/* Must be a smaller delay than the chrg_full_isr below */
-	mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250));
-
-	return IRQ_HANDLED;
-}
-
-static void sharpsl_chrg_full_timer(unsigned long data)
-{
-	dev_dbg(sharpsl_pm.dev, "Charge Full at time: %lx\n", jiffies);
-
-	sharpsl_pm.full_count++;
-
-	if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
-		dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n");
-		if (sharpsl_pm.charge_mode == CHRG_ON)
-			sharpsl_charge_off();
-	} else if (sharpsl_pm.full_count < 2) {
-		dev_dbg(sharpsl_pm.dev, "Charge Full: Count too low\n");
-		schedule_delayed_work(&toggle_charger, 0);
-	} else if (time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_FINISH_TIME)) {
-		dev_dbg(sharpsl_pm.dev, "Charge Full: Interrupt generated too slowly - retry.\n");
-		schedule_delayed_work(&toggle_charger, 0);
-	} else {
-		sharpsl_charge_off();
-		sharpsl_pm.charge_mode = CHRG_DONE;
-		dev_dbg(sharpsl_pm.dev, "Charge Full: Charging Finished\n");
-	}
-}
-
-/* Charging Finished Interrupt (Not present on Corgi) */
-/* Can trigger at the same time as an AC status change so
-   delay until after that has been processed */
-irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id)
-{
-	if (sharpsl_pm.flags & SHARPSL_SUSPENDED)
-		return IRQ_HANDLED;
-
-	/* delay until after any ac interrupt */
-	mod_timer(&sharpsl_pm.chrg_full_timer, jiffies + msecs_to_jiffies(500));
-
-	return IRQ_HANDLED;
-}
-
-irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id)
-{
-	int is_fatal = 0;
-
-	if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) {
-		dev_err(sharpsl_pm.dev, "Battery now Unlocked! Suspending.\n");
-		is_fatal = 1;
-	}
-
-	if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_FATAL)) {
-		dev_err(sharpsl_pm.dev, "Fatal Batt Error! Suspending.\n");
-		is_fatal = 1;
-	}
-
-	if (!(sharpsl_pm.flags & SHARPSL_APM_QUEUED) && is_fatal) {
-		sharpsl_pm.flags |= SHARPSL_APM_QUEUED;
-		apm_queue_event(APM_CRITICAL_SUSPEND);
-	}
-
-	return IRQ_HANDLED;
-}
-
-/*
- * Maintain an average of the last 10 readings
- */
-#define SHARPSL_CNV_VALUE_NUM    10
-static int sharpsl_ad_index;
-
-static void sharpsl_average_clear(void)
-{
-	sharpsl_ad_index = 0;
-}
-
-static int sharpsl_average_value(int ad)
-{
-	int i, ad_val = 0;
-	static int sharpsl_ad[SHARPSL_CNV_VALUE_NUM+1];
-
-	if (sharpsl_pm.battstat.mainbat_status != APM_BATTERY_STATUS_HIGH) {
-		sharpsl_ad_index = 0;
-		return ad;
-	}
-
-	sharpsl_ad[sharpsl_ad_index] = ad;
-	sharpsl_ad_index++;
-	if (sharpsl_ad_index >= SHARPSL_CNV_VALUE_NUM) {
-		for (i=0; i < (SHARPSL_CNV_VALUE_NUM-1); i++)
-			sharpsl_ad[i] = sharpsl_ad[i+1];
-		sharpsl_ad_index = SHARPSL_CNV_VALUE_NUM - 1;
-	}
-	for (i=0; i < sharpsl_ad_index; i++)
-		ad_val += sharpsl_ad[i];
-
-	return (ad_val / sharpsl_ad_index);
-}
-
-/*
- * Take an array of 5 integers, remove the maximum and minimum values
- * and return the average.
- */
-static int get_select_val(int *val)
-{
-	int i, j, k, temp, sum = 0;
-
-	/* Find MAX val */
-	temp = val[0];
-	j=0;
-	for (i=1; i<5; i++) {
-		if (temp < val[i]) {
-			temp = val[i];
-			j = i;
-		}
-	}
-
-	/* Find MIN val */
-	temp = val[4];
-	k=4;
-	for (i=3; i>=0; i--) {
-		if (temp > val[i]) {
-			temp = val[i];
-			k = i;
-		}
-	}
-
-	for (i=0; i<5; i++)
-		if (i != j && i != k )
-			sum += val[i];
-
-	dev_dbg(sharpsl_pm.dev, "Average: %d from values: %d, %d, %d, %d, %d\n", sum/3, val[0], val[1], val[2], val[3], val[4]);
-
-	return (sum/3);
-}
-
-static int sharpsl_check_battery_temp(void)
-{
-	int val, i, buff[5];
-
-	/* Check battery temperature */
-	for (i=0; i<5; i++) {
-		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP);
-		sharpsl_pm.machinfo->measure_temp(1);
-		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP);
-		buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_TEMP);
-		sharpsl_pm.machinfo->measure_temp(0);
-	}
-
-	val = get_select_val(buff);
-
-	dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val);
-	if (val > sharpsl_pm.machinfo->charge_on_temp) {
-		printk(KERN_WARNING "Not charging: temperature out of limits.\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int sharpsl_check_battery_voltage(void)
-{
-	int val, i, buff[5];
-
-	/* disable charge, enable discharge */
-	sharpsl_pm.machinfo->charge(0);
-	sharpsl_pm.machinfo->discharge(1);
-	mdelay(SHARPSL_WAIT_DISCHARGE_ON);
-
-	if (sharpsl_pm.machinfo->discharge1)
-		sharpsl_pm.machinfo->discharge1(1);
-
-	/* Check battery voltage */
-	for (i=0; i<5; i++) {
-		buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
-		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT);
-	}
-
-	if (sharpsl_pm.machinfo->discharge1)
-		sharpsl_pm.machinfo->discharge1(0);
-
-	sharpsl_pm.machinfo->discharge(0);
-
-	val = get_select_val(buff);
-	dev_dbg(sharpsl_pm.dev, "Battery Voltage: %d\n", val);
-
-	if (val < sharpsl_pm.machinfo->charge_on_volt)
-		return -1;
-
-	return 0;
-}
-#endif
-
-static int sharpsl_ac_check(void)
-{
-	int temp, i, buff[5];
-
-	for (i=0; i<5; i++) {
-		buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_ACIN_VOLT);
-		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN);
-	}
-
-	temp = get_select_val(buff);
-	dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp);
-
-	if ((temp > sharpsl_pm.machinfo->charge_acin_high) || (temp < sharpsl_pm.machinfo->charge_acin_low)) {
-		dev_err(sharpsl_pm.dev, "Error: AC check failed.\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int sharpsl_pm_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	sharpsl_pm.flags |= SHARPSL_SUSPENDED;
-	flush_scheduled_work();
-
-	if (sharpsl_pm.charge_mode == CHRG_ON)
-		sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG;
-	else
-		sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG;
-
-	return 0;
-}
-
-static int sharpsl_pm_resume(struct platform_device *pdev)
-{
-	/* Clear the reset source indicators as they break the bootloader upon reboot */
-	RCSR = 0x0f;
-	sharpsl_average_clear();
-	sharpsl_pm.flags &= ~SHARPSL_APM_QUEUED;
-	sharpsl_pm.flags &= ~SHARPSL_SUSPENDED;
-
-	return 0;
-}
-
-static void corgi_goto_sleep(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state)
-{
-	dev_dbg(sharpsl_pm.dev, "Time is: %08x\n",RCNR);
-
-	dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n",sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG);
-	/* not charging and AC-IN! */
-
-	if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN))) {
-		dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n");
-		sharpsl_pm.charge_mode = CHRG_OFF;
-		sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG;
-		sharpsl_off_charge_battery();
-	}
-
-	sharpsl_pm.machinfo->presuspend();
-
-	PEDR = 0xffffffff; /* clear it */
-
-	sharpsl_pm.flags &= ~SHARPSL_ALARM_ACTIVE;
-	if ((sharpsl_pm.charge_mode == CHRG_ON) && ((alarm_enable && ((alarm_time - RCNR) > (SHARPSL_BATCHK_TIME_SUSPEND + 30))) || !alarm_enable)) {
-		RTSR &= RTSR_ALE;
-		RTAR = RCNR + SHARPSL_BATCHK_TIME_SUSPEND;
-		dev_dbg(sharpsl_pm.dev, "Charging alarm at: %08x\n",RTAR);
-		sharpsl_pm.flags |= SHARPSL_ALARM_ACTIVE;
-	} else if (alarm_enable) {
-		RTSR &= RTSR_ALE;
-		RTAR = alarm_time;
-		dev_dbg(sharpsl_pm.dev, "User alarm at: %08x\n",RTAR);
-	} else {
-		dev_dbg(sharpsl_pm.dev, "No alarms set.\n");
-	}
-
-	pxa_pm_enter(state);
-
-	sharpsl_pm.machinfo->postsuspend();
-
-	dev_dbg(sharpsl_pm.dev, "Corgi woken up from suspend: %08x\n",PEDR);
-}
-
-static int corgi_enter_suspend(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state)
-{
-	if (!sharpsl_pm.machinfo->should_wakeup(!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE) && alarm_enable) )
-	{
-		if (!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE)) {
-			dev_dbg(sharpsl_pm.dev, "No user triggered wakeup events and not charging. Strange. Suspend.\n");
-			corgi_goto_sleep(alarm_time, alarm_enable, state);
-			return 1;
-		}
-		if(sharpsl_off_charge_battery()) {
-			dev_dbg(sharpsl_pm.dev, "Charging. Suspend...\n");
-			corgi_goto_sleep(alarm_time, alarm_enable, state);
-			return 1;
-		}
-		dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n");
-	}
-
-	if ((!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) || (sharpsl_fatal_check() < 0) )
-	{
-		dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n");
-		corgi_goto_sleep(alarm_time, alarm_enable, state);
-		return 1;
-	}
-
-	return 0;
-}
-
-static int corgi_pxa_pm_enter(suspend_state_t state)
-{
-	unsigned long alarm_time = RTAR;
-	unsigned int alarm_status = ((RTSR & RTSR_ALE) != 0);
-
-	dev_dbg(sharpsl_pm.dev, "SharpSL suspending for first time.\n");
-
-	corgi_goto_sleep(alarm_time, alarm_status, state);
-
-	while (corgi_enter_suspend(alarm_time,alarm_status,state))
-		{}
-
-	if (sharpsl_pm.machinfo->earlyresume)
-		sharpsl_pm.machinfo->earlyresume();
-
-	dev_dbg(sharpsl_pm.dev, "SharpSL resuming...\n");
-
-	return 0;
-}
-
-/*
- * Check for fatal battery errors
- * Fatal returns -1
- */
-static int sharpsl_fatal_check(void)
-{
-	int buff[5], temp, i, acin;
-
-	dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n");
-
-	/* Check AC-Adapter */
-	acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN);
-
-	if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) {
-		sharpsl_pm.machinfo->charge(0);
-		udelay(100);
-		sharpsl_pm.machinfo->discharge(1);	/* enable discharge */
-		mdelay(SHARPSL_WAIT_DISCHARGE_ON);
-	}
-
-	if (sharpsl_pm.machinfo->discharge1)
-		sharpsl_pm.machinfo->discharge1(1);
-
-	/* Check battery : check inserting battery ? */
-	for (i=0; i<5; i++) {
-		buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
-		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT);
-	}
-
-	if (sharpsl_pm.machinfo->discharge1)
-		sharpsl_pm.machinfo->discharge1(0);
-
-	if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) {
-		udelay(100);
-		sharpsl_pm.machinfo->charge(1);
-		sharpsl_pm.machinfo->discharge(0);
-	}
-
-	temp = get_select_val(buff);
-	dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %ld\n", acin, temp, sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT));
-
-	if ((acin && (temp < sharpsl_pm.machinfo->fatal_acin_volt)) ||
-			(!acin && (temp < sharpsl_pm.machinfo->fatal_noacin_volt)))
-		return -1;
-	return 0;
-}
-
-static int sharpsl_off_charge_error(void)
-{
-	dev_err(sharpsl_pm.dev, "Offline Charger: Error occurred.\n");
-	sharpsl_pm.machinfo->charge(0);
-	sharpsl_pm_led(SHARPSL_LED_ERROR);
-	sharpsl_pm.charge_mode = CHRG_ERROR;
-	return 1;
-}
-
-/*
- * Charging Control while suspended
- * Return 1 - go straight to sleep
- * Return 0 - sleep or wakeup depending on other factors
- */
-static int sharpsl_off_charge_battery(void)
-{
-	int time;
-
-	dev_dbg(sharpsl_pm.dev, "Charge Mode: %d\n", sharpsl_pm.charge_mode);
-
-	if (sharpsl_pm.charge_mode == CHRG_OFF) {
-		dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n");
-
-		/* AC Check */
-		if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery_temp() < 0))
-			return sharpsl_off_charge_error();
-
-		/* Start Charging */
-		sharpsl_pm_led(SHARPSL_LED_ON);
-		sharpsl_pm.machinfo->charge(0);
-		mdelay(SHARPSL_CHARGE_WAIT_TIME);
-		sharpsl_pm.machinfo->charge(1);
-
-		sharpsl_pm.charge_mode = CHRG_ON;
-		sharpsl_pm.full_count = 0;
-
-		return 1;
-	} else if (sharpsl_pm.charge_mode != CHRG_ON) {
-		return 1;
-	}
-
-	if (sharpsl_pm.full_count == 0) {
-		int time;
-
-		dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n");
-
-		if ((sharpsl_check_battery_temp() < 0) || (sharpsl_check_battery_voltage() < 0))
-			return sharpsl_off_charge_error();
-
-		sharpsl_pm.machinfo->charge(0);
-		mdelay(SHARPSL_CHARGE_WAIT_TIME);
-		sharpsl_pm.machinfo->charge(1);
-		sharpsl_pm.charge_mode = CHRG_ON;
-
-		mdelay(SHARPSL_CHARGE_CO_CHECK_TIME);
-
-		time = RCNR;
-		while(1) {
-			/* Check if any wakeup event had occurred */
-			if (sharpsl_pm.machinfo->charger_wakeup() != 0)
-				return 0;
-			/* Check for timeout */
-			if ((RCNR - time) > SHARPSL_WAIT_CO_TIME)
-				return 1;
-			if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) {
-				dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occurred. Retrying to check\n");
-	   			sharpsl_pm.full_count++;
-				sharpsl_pm.machinfo->charge(0);
-				mdelay(SHARPSL_CHARGE_WAIT_TIME);
-				sharpsl_pm.machinfo->charge(1);
-				return 1;
-			}
-		}
-	}
-
-	dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 3\n");
-
-	mdelay(SHARPSL_CHARGE_CO_CHECK_TIME);
-
-	time = RCNR;
-	while(1) {
-		/* Check if any wakeup event had occurred */
-		if (sharpsl_pm.machinfo->charger_wakeup() != 0)
-			return 0;
-		/* Check for timeout */
-		if ((RCNR-time) > SHARPSL_WAIT_CO_TIME) {
-			if (sharpsl_pm.full_count > SHARPSL_CHARGE_RETRY_CNT) {
-				dev_dbg(sharpsl_pm.dev, "Offline Charger: Not charged sufficiently. Retrying.\n");
-				sharpsl_pm.full_count = 0;
-			}
-			sharpsl_pm.full_count++;
-			return 1;
-		}
-		if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) {
-			dev_dbg(sharpsl_pm.dev, "Offline Charger: Charging complete.\n");
-			sharpsl_pm_led(SHARPSL_LED_OFF);
-			sharpsl_pm.machinfo->charge(0);
-			sharpsl_pm.charge_mode = CHRG_DONE;
-			return 1;
-		}
-	}
-}
-#else
-#define sharpsl_pm_suspend	NULL
-#define sharpsl_pm_resume	NULL
-#endif
-
-static ssize_t battery_percentage_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%d\n",sharpsl_pm.battstat.mainbat_percent);
-}
-
-static ssize_t battery_voltage_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%d\n",sharpsl_pm.battstat.mainbat_voltage);
-}
-
-static DEVICE_ATTR(battery_percentage, 0444, battery_percentage_show, NULL);
-static DEVICE_ATTR(battery_voltage, 0444, battery_voltage_show, NULL);
-
-extern void (*apm_get_power_status)(struct apm_power_info *);
-
-static void sharpsl_apm_get_power_status(struct apm_power_info *info)
-{
-	info->ac_line_status = sharpsl_pm.battstat.ac_status;
-
-	if (sharpsl_pm.charge_mode == CHRG_ON)
-		info->battery_status = APM_BATTERY_STATUS_CHARGING;
-	else
-		info->battery_status = sharpsl_pm.battstat.mainbat_status;
-
-	info->battery_flag = (1 << info->battery_status);
-	info->battery_life = sharpsl_pm.battstat.mainbat_percent;
-}
-
-#ifdef CONFIG_PM
-static struct platform_suspend_ops sharpsl_pm_ops = {
-	.enter		= corgi_pxa_pm_enter,
-	.valid		= suspend_valid_only_mem,
-};
-#endif
-
-static int __init sharpsl_pm_probe(struct platform_device *pdev)
-{
-	int ret;
-
-	if (!pdev->dev.platform_data)
-		return -EINVAL;
-
-	sharpsl_pm.dev = &pdev->dev;
-	sharpsl_pm.machinfo = pdev->dev.platform_data;
-	sharpsl_pm.charge_mode = CHRG_OFF;
-	sharpsl_pm.flags = 0;
-
-	init_timer(&sharpsl_pm.ac_timer);
-	sharpsl_pm.ac_timer.function = sharpsl_ac_timer;
-
-	init_timer(&sharpsl_pm.chrg_full_timer);
-	sharpsl_pm.chrg_full_timer.function = sharpsl_chrg_full_timer;
-
-	led_trigger_register_simple("sharpsl-charge", &sharpsl_charge_led_trigger);
-
-	sharpsl_pm.machinfo->init();
-
-	ret = device_create_file(&pdev->dev, &dev_attr_battery_percentage);
-	ret |= device_create_file(&pdev->dev, &dev_attr_battery_voltage);
-	if (ret != 0)
-		dev_warn(&pdev->dev, "Failed to register attributes (%d)\n", ret);
-
-	apm_get_power_status = sharpsl_apm_get_power_status;
-
-#ifdef CONFIG_PM
-	suspend_set_ops(&sharpsl_pm_ops);
-#endif
-
-	mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250));
-
-	return 0;
-}
-
-static int sharpsl_pm_remove(struct platform_device *pdev)
-{
-	suspend_set_ops(NULL);
-
-	device_remove_file(&pdev->dev, &dev_attr_battery_percentage);
-	device_remove_file(&pdev->dev, &dev_attr_battery_voltage);
-
-	led_trigger_unregister_simple(sharpsl_charge_led_trigger);
-
-	sharpsl_pm.machinfo->exit();
-
-	del_timer_sync(&sharpsl_pm.chrg_full_timer);
-	del_timer_sync(&sharpsl_pm.ac_timer);
-
-	return 0;
-}
-
-static struct platform_driver sharpsl_pm_driver = {
-	.probe		= sharpsl_pm_probe,
-	.remove		= sharpsl_pm_remove,
-	.suspend	= sharpsl_pm_suspend,
-	.resume		= sharpsl_pm_resume,
-	.driver		= {
-		.name		= "sharpsl-pm",
-	},
-};
-
-static int __devinit sharpsl_pm_init(void)
-{
-	return platform_driver_register(&sharpsl_pm_driver);
-}
-
-static void sharpsl_pm_exit(void)
-{
- 	platform_driver_unregister(&sharpsl_pm_driver);
-}
-
-late_initcall(sharpsl_pm_init);
-module_exit(sharpsl_pm_exit);
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index 227da08..d18d21b 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc3
-# Tue Aug 19 11:26:54 2008
+# Linux kernel version: 2.6.30-rc8
+# Thu Jun  4 09:53:21 2009
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -22,8 +22,6 @@
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
-CONFIG_ZONE_DMA=y
 CONFIG_ARCH_MTD_XIP=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_VECTORS_BASE=0xffff0000
@@ -44,15 +42,24 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=18
-# CONFIG_CGROUPS is not set
 CONFIG_GROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 # CONFIG_RT_GROUP_SCHED is not set
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
@@ -61,31 +68,37 @@
 # CONFIG_IPC_NS is not set
 # CONFIG_USER_NS is not set
 # CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 # CONFIG_EMBEDDED is not set
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
+CONFIG_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
@@ -93,19 +106,13 @@
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
 CONFIG_HAVE_CLK=y
-CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
 # CONFIG_MODULE_FORCE_LOAD is not set
@@ -113,11 +120,8 @@
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -133,7 +137,7 @@
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
+CONFIG_FREEZER=y
 
 #
 # System Type
@@ -143,10 +147,10 @@
 # CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_VERSATILE is not set
 # CONFIG_ARCH_AT91 is not set
-# CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_GEMINI is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
 # CONFIG_ARCH_NETX is not set
 # CONFIG_ARCH_H720X is not set
@@ -167,14 +171,17 @@
 # CONFIG_ARCH_ORION5X is not set
 # CONFIG_ARCH_PNX4008 is not set
 CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_MMP is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
 # CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_MSM7X00A is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
 
 #
 # Intel PXA2xx/PXA3xx Implementations
@@ -187,16 +194,24 @@
 # CONFIG_CPU_PXA310 is not set
 # CONFIG_CPU_PXA320 is not set
 # CONFIG_CPU_PXA930 is not set
+# CONFIG_CPU_PXA935 is not set
 # CONFIG_ARCH_GUMSTIX is not set
+# CONFIG_MACH_INTELMOTE2 is not set
 # CONFIG_ARCH_LUBBOCK is not set
 # CONFIG_MACH_LOGICPD_PXA270 is not set
 # CONFIG_MACH_MAINSTONE is not set
+# CONFIG_MACH_MP900C is not set
 # CONFIG_ARCH_PXA_IDP is not set
 # CONFIG_PXA_SHARPSL is not set
+# CONFIG_ARCH_VIPER is not set
 # CONFIG_ARCH_PXA_ESERIES is not set
-# CONFIG_MACH_TRIZEPS4 is not set
+# CONFIG_TRIZEPS_PXA is not set
+# CONFIG_MACH_H5000 is not set
 # CONFIG_MACH_EM_X270 is not set
+# CONFIG_MACH_EXEDA is not set
 # CONFIG_MACH_COLIBRI is not set
+# CONFIG_MACH_COLIBRI300 is not set
+# CONFIG_MACH_COLIBRI320 is not set
 # CONFIG_MACH_ZYLONITE is not set
 # CONFIG_MACH_LITTLETON is not set
 # CONFIG_MACH_TAVOREVB is not set
@@ -204,19 +219,15 @@
 # CONFIG_MACH_ARMCORE is not set
 CONFIG_MACH_CM_X300=y
 # CONFIG_MACH_MAGICIAN is not set
+# CONFIG_MACH_HIMALAYA is not set
+# CONFIG_MACH_MIOA701 is not set
 # CONFIG_MACH_PCM027 is not set
 # CONFIG_ARCH_PXA_PALM is not set
+# CONFIG_MACH_CSB726 is not set
 # CONFIG_PXA_EZX is not set
 CONFIG_PXA3xx=y
 # CONFIG_PXA_PWM is not set
-
-#
-# Boot options
-#
-
-#
-# Power management
-#
+CONFIG_PLAT_PXA=y
 
 #
 # Processor Type
@@ -241,6 +252,7 @@
 CONFIG_OUTER_CACHE=y
 CONFIG_CACHE_XSC3L2=y
 CONFIG_IWMMXT=y
+CONFIG_COMMON_CLKDEV=y
 
 #
 # Bus support
@@ -256,25 +268,33 @@
 CONFIG_NO_HZ=y
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
 # CONFIG_PREEMPT is not set
 CONFIG_HZ=100
 CONFIG_AEABI=y
 CONFIG_OABI_COMPAT=y
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+# CONFIG_ARCH_HAS_HOLES_MEMORYMODEL is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HIGHMEM=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -287,7 +307,7 @@
 # CONFIG_KEXEC is not set
 
 #
-# CPU Frequency scaling
+# CPU Power Management
 #
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_TABLE=y
@@ -304,6 +324,7 @@
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 # CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
 # CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+# CONFIG_CPU_IDLE is not set
 
 #
 # Floating point emulation
@@ -320,6 +341,8 @@
 # Userspace binary formats
 #
 CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
 # CONFIG_BINFMT_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 
@@ -376,6 +399,7 @@
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
@@ -385,7 +409,9 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
@@ -407,8 +433,7 @@
 #
 # Bluetooth device drivers
 #
-CONFIG_BT_HCIUSB=m
-CONFIG_BT_HCIUSB_SCO=y
+# CONFIG_BT_HCIBTUSB is not set
 # CONFIG_BT_HCIBTSDIO is not set
 # CONFIG_BT_HCIUART is not set
 # CONFIG_BT_HCIBCM203X is not set
@@ -416,19 +441,15 @@
 # CONFIG_BT_HCIBFUSB is not set
 # CONFIG_BT_HCIVHCI is not set
 # CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+CONFIG_WIRELESS=y
 # CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
+# CONFIG_LIB80211_DEBUG is not set
 # CONFIG_MAC80211 is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -453,6 +474,7 @@
 # CONFIG_MTD_DEBUG is not set
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 # CONFIG_MTD_CMDLINE_PARTS is not set
 # CONFIG_MTD_AFS_PARTS is not set
@@ -494,7 +516,6 @@
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_SHARP_SL is not set
 # CONFIG_MTD_PLATRAM is not set
 
 #
@@ -516,16 +537,23 @@
 # CONFIG_MTD_NAND_ECC_SMC is not set
 # CONFIG_MTD_NAND_MUSEUM_IDS is not set
 # CONFIG_MTD_NAND_H1900 is not set
+# CONFIG_MTD_NAND_GPIO is not set
 CONFIG_MTD_NAND_IDS=y
 # CONFIG_MTD_NAND_DISKONCHIP is not set
 # CONFIG_MTD_NAND_SHARPSL is not set
 CONFIG_MTD_NAND_PXA3xx=y
+# CONFIG_MTD_NAND_PXA3xx_BUILTIN is not set
 # CONFIG_MTD_NAND_NANDSIM is not set
 # CONFIG_MTD_NAND_PLATFORM is not set
 # CONFIG_MTD_ALAUDA is not set
 # CONFIG_MTD_ONENAND is not set
 
 #
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
@@ -585,11 +613,15 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -604,11 +636,17 @@
 CONFIG_DM9000=y
 CONFIG_DM9000_DEBUGLEVEL=0
 CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_ETHOC is not set
 # CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
 # CONFIG_IBM_NEW_EMAC_ZMII is not set
 # CONFIG_IBM_NEW_EMAC_RGMII is not set
 # CONFIG_IBM_NEW_EMAC_TAH is not set
 # CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
@@ -624,10 +662,13 @@
 # CONFIG_LIBERTAS_DEBUG is not set
 # CONFIG_USB_ZD1201 is not set
 # CONFIG_USB_NET_RNDIS_WLAN is not set
-# CONFIG_IWLWIFI_LEDS is not set
 # CONFIG_HOSTAP is not set
 
 #
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -677,18 +718,21 @@
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
 # CONFIG_TOUCHSCREEN_MTOUCH is not set
 # CONFIG_TOUCHSCREEN_INEXIO is not set
 # CONFIG_TOUCHSCREEN_MK712 is not set
 # CONFIG_TOUCHSCREEN_PENMOUNT is not set
 # CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
 # CONFIG_TOUCHSCREEN_TOUCHWIN is not set
-# CONFIG_TOUCHSCREEN_UCB1400 is not set
 # CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
 # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
 # CONFIG_INPUT_MISC is not set
 
 #
@@ -721,10 +765,10 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_HW_RANDOM is not set
-# CONFIG_NVRAM is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
@@ -763,12 +807,8 @@
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-# CONFIG_EEPROM_AT24 is not set
-# CONFIG_EEPROM_LEGACY is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
 # CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
@@ -782,6 +822,10 @@
 # CONFIG_GPIO_SYSFS is not set
 
 #
+# Memory mapped GPIO expanders:
+#
+
+#
 # I2C GPIO expanders:
 #
 # CONFIG_GPIO_MAX732X is not set
@@ -798,12 +842,14 @@
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
 # Sonics Silicon Backplane
 #
-CONFIG_SSB_POSSIBLE=y
 # CONFIG_SSB is not set
 
 #
@@ -811,12 +857,19 @@
 #
 # CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
 # CONFIG_HTC_EGPIO is not set
 # CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_MFD_T7L66XB is not set
 # CONFIG_MFD_TC6387XB is not set
 # CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
 
 #
 # Multimedia devices
@@ -842,6 +895,7 @@
 CONFIG_FB=y
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
@@ -862,12 +916,15 @@
 #
 # CONFIG_FB_S1D13XXX is not set
 CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_OVERLAY is not set
 # CONFIG_FB_PXA_SMARTPANEL is not set
 # CONFIG_FB_PXA_PARAMETERS is not set
 # CONFIG_FB_MBX is not set
 # CONFIG_FB_W100 is not set
-# CONFIG_FB_AM200EPD is not set
 # CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -899,9 +956,11 @@
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
 CONFIG_SOUND=m
+# CONFIG_SOUND_OSS_CORE is not set
 CONFIG_SND=m
 CONFIG_SND_TIMER=m
 CONFIG_SND_PCM=m
+CONFIG_SND_JACK=y
 # CONFIG_SND_SEQUENCER is not set
 # CONFIG_SND_MIXER_OSS is not set
 # CONFIG_SND_PCM_OSS is not set
@@ -916,12 +975,15 @@
 # CONFIG_SND_SERIAL_U16550 is not set
 # CONFIG_SND_MPU401 is not set
 CONFIG_SND_ARM=y
+CONFIG_SND_PXA2XX_LIB=m
 # CONFIG_SND_PXA2XX_AC97 is not set
 CONFIG_SND_USB=y
 # CONFIG_SND_USB_AUDIO is not set
 # CONFIG_SND_USB_CAIAQ is not set
 CONFIG_SND_SOC=m
 CONFIG_SND_PXA2XX_SOC=m
+CONFIG_SND_SOC_I2C_AND_SPI=m
+# CONFIG_SND_SOC_ALL_CODECS is not set
 # CONFIG_SOUND_PRIME is not set
 CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
@@ -932,9 +994,39 @@
 # USB Input Devices
 #
 CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
+# CONFIG_HID_PID is not set
 # CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
+CONFIG_HID_EZKEY=y
+CONFIG_HID_KYE=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+CONFIG_HID_TOPSEED=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -952,11 +1044,14 @@
 # CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
 CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
 
 #
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
@@ -965,6 +1060,7 @@
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_SL811_HCD is not set
 # CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
 # CONFIG_USB_MUSB_HDRC is not set
 
 #
@@ -973,20 +1069,20 @@
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 # CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
 #
 
 #
-# may also be needed; see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
 #
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
 # CONFIG_USB_STORAGE_USBAT is not set
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_SDDR55 is not set
@@ -994,7 +1090,6 @@
 # CONFIG_USB_STORAGE_ALAUDA is not set
 # CONFIG_USB_STORAGE_ONETOUCH is not set
 # CONFIG_USB_STORAGE_KARMA is not set
-# CONFIG_USB_STORAGE_SIERRA is not set
 # CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
 # CONFIG_USB_LIBUSUAL is not set
 
@@ -1015,6 +1110,7 @@
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
 # CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
@@ -1022,7 +1118,6 @@
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
@@ -1031,13 +1126,20 @@
 # CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 # CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
 CONFIG_MMC=m
 # CONFIG_MMC_DEBUG is not set
 # CONFIG_MMC_UNSAFE_RESUME is not set
 
 #
-# MMC/SD Card Drivers
+# MMC/SD/SDIO Card Drivers
 #
 CONFIG_MMC_BLOCK=m
 CONFIG_MMC_BLOCK_BOUNCE=y
@@ -1045,10 +1147,12 @@
 # CONFIG_MMC_TEST is not set
 
 #
-# MMC/SD Host Controller Drivers
+# MMC/SD/SDIO Host Controller Drivers
 #
 CONFIG_MMC_PXA=m
 # CONFIG_MMC_SDHCI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 
@@ -1057,7 +1161,10 @@
 #
 # CONFIG_LEDS_PCA9532 is not set
 CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP5521 is not set
 # CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_BD2802 is not set
 
 #
 # LED Triggers
@@ -1065,7 +1172,13 @@
 CONFIG_LEDS_TRIGGERS=y
 # CONFIG_LEDS_TRIGGER_TIMER is not set
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
 # CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
 CONFIG_RTC_LIB=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
@@ -1096,6 +1209,7 @@
 # CONFIG_RTC_DRV_M41T80 is not set
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
 
 #
 # SPI RTC drivers
@@ -1105,28 +1219,27 @@
 # Platform RTC drivers
 #
 # CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
 # CONFIG_RTC_DRV_DS1511 is not set
 # CONFIG_RTC_DRV_DS1553 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
 # CONFIG_RTC_DRV_STK17TA8 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
 # CONFIG_RTC_DRV_M48T59 is not set
-# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+CONFIG_RTC_DRV_V3020=y
 
 #
 # on-CPU RTC drivers
 #
 CONFIG_RTC_DRV_SA1100=y
+# CONFIG_RTC_DRV_PXA is not set
 # CONFIG_DMADEVICES is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
 # CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
@@ -1135,15 +1248,18 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1153,6 +1269,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1173,15 +1294,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -1201,6 +1320,7 @@
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
@@ -1209,6 +1329,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -1313,6 +1434,7 @@
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
 # CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -1329,6 +1451,7 @@
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_VM is not set
@@ -1336,22 +1459,38 @@
 CONFIG_DEBUG_MEMORY_INIT=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
-CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_NOTIFIERS is not set
 # CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
 # CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
 CONFIG_DEBUG_USER=y
 # CONFIG_DEBUG_ERRORS is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
@@ -1363,17 +1502,28 @@
 #
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
 CONFIG_CRYPTO=y
 
 #
 # Crypto core or helper
 #
+# CONFIG_CRYPTO_FIPS is not set
 CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
 CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
 CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
 # CONFIG_CRYPTO_CRYPTD is not set
 # CONFIG_CRYPTO_AUTHENC is not set
 # CONFIG_CRYPTO_TEST is not set
@@ -1442,15 +1592,21 @@
 # Compression
 #
 # CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
 # CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 CONFIG_CRC_T10DIF=y
@@ -1460,7 +1616,10 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/magician_defconfig b/arch/arm/configs/magician_defconfig
index f56837f..957fd5f 100644
--- a/arch/arm/configs/magician_defconfig
+++ b/arch/arm/configs/magician_defconfig
@@ -190,6 +190,7 @@
 # CONFIG_MACH_SAAR is not set
 # CONFIG_MACH_ARMCORE is not set
 # CONFIG_MACH_CM_X300 is not set
+CONFIG_MACH_H4700=y
 CONFIG_MACH_MAGICIAN=y
 # CONFIG_MACH_MIOA701 is not set
 # CONFIG_MACH_PCM027 is not set
@@ -828,7 +829,7 @@
 #
 # CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
-# CONFIG_MFD_ASIC3 is not set
+CONFIG_MFD_ASIC3=y
 CONFIG_HTC_EGPIO=y
 CONFIG_HTC_PASIC3=y
 # CONFIG_TPS65010 is not set
@@ -891,7 +892,7 @@
 # CONFIG_FB_PXA_SMARTPANEL is not set
 # CONFIG_FB_PXA_PARAMETERS is not set
 # CONFIG_FB_MBX is not set
-# CONFIG_FB_W100 is not set
+CONFIG_FB_W100=y
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FB_METRONOME is not set
 # CONFIG_FB_MB862XX is not set
diff --git a/arch/arm/mach-mmp/include/mach/irqs.h b/arch/arm/mach-mmp/include/mach/irqs.h
index e83e45e..16295cf 100644
--- a/arch/arm/mach-mmp/include/mach/irqs.h
+++ b/arch/arm/mach-mmp/include/mach/irqs.h
@@ -52,6 +52,7 @@
 /*
  * Interrupt numbers for PXA910
  */
+#define IRQ_PXA910_NONE			(-1)
 #define IRQ_PXA910_AIRQ			0
 #define IRQ_PXA910_SSP3			1
 #define IRQ_PXA910_SSP2			2
diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
index 2e91464..3b216bf 100644
--- a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
@@ -253,6 +253,10 @@
 #define GPIO58_LCD_PCLK_WR	MFP_CFG(GPIO58, AF1)
 #define GPIO85_LCD_VSYNC	MFP_CFG(GPIO85, AF1)
 
+/* I2C */
+#define GPIO105_CI2C_SDA	MFP_CFG(GPIO105, AF1)
+#define GPIO106_CI2C_SCL	MFP_CFG(GPIO106, AF1)
+
 /* I2S */
 #define GPIO113_I2S_MCLK	MFP_CFG(GPIO113,AF6)
 #define GPIO114_I2S_FRM		MFP_CFG(GPIO114,AF1)
@@ -260,4 +264,27 @@
 #define GPIO116_I2S_RXD		MFP_CFG(GPIO116,AF2)
 #define GPIO117_I2S_TXD		MFP_CFG(GPIO117,AF2)
 
+/* PWM */
+#define GPIO96_PWM3_OUT		MFP_CFG(GPIO96, AF1)
+#define GPIO97_PWM2_OUT		MFP_CFG(GPIO97, AF1)
+#define GPIO98_PWM1_OUT		MFP_CFG(GPIO98, AF1)
+#define GPIO104_PWM4_OUT	MFP_CFG(GPIO104, AF1)
+#define GPIO106_PWM2_OUT	MFP_CFG(GPIO106, AF2)
+#define GPIO74_PWM4_OUT		MFP_CFG(GPIO74, AF2)
+#define GPIO75_PWM3_OUT		MFP_CFG(GPIO75, AF2)
+#define GPIO76_PWM2_OUT		MFP_CFG(GPIO76, AF2)
+#define GPIO77_PWM1_OUT		MFP_CFG(GPIO77, AF2)
+#define GPIO82_PWM4_OUT		MFP_CFG(GPIO82, AF2)
+#define GPIO83_PWM3_OUT		MFP_CFG(GPIO83, AF2)
+#define GPIO84_PWM2_OUT		MFP_CFG(GPIO84, AF2)
+#define GPIO85_PWM1_OUT		MFP_CFG(GPIO85, AF2)
+#define GPIO84_PWM1_OUT		MFP_CFG(GPIO84, AF4)
+#define GPIO122_PWM3_OUT	MFP_CFG(GPIO122, AF3)
+#define GPIO123_PWM1_OUT	MFP_CFG(GPIO123, AF1)
+#define GPIO124_PWM2_OUT	MFP_CFG(GPIO124, AF1)
+#define GPIO125_PWM3_OUT	MFP_CFG(GPIO125, AF1)
+#define GPIO126_PWM4_OUT	MFP_CFG(GPIO126, AF1)
+#define GPIO86_PWM1_OUT		MFP_CFG(GPIO86, AF2)
+#define GPIO86_PWM2_OUT		MFP_CFG(GPIO86, AF3)
+
 #endif /* __ASM_MACH_MFP_PXA168_H */
diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa910.h b/arch/arm/mach-mmp/include/mach/mfp-pxa910.h
index d97de36..bf1189f 100644
--- a/arch/arm/mach-mmp/include/mach/mfp-pxa910.h
+++ b/arch/arm/mach-mmp/include/mach/mfp-pxa910.h
@@ -159,4 +159,12 @@
 #define MMC1_CD_MMC1_CD		MFP_CFG_DRV(MMC1_CD, AF0, MEDIUM)
 #define MMC1_WP_MMC1_WP		MFP_CFG_DRV(MMC1_WP, AF0, MEDIUM)
 
+/* PWM */
+#define GPIO27 PWM3 AF2		MFP_CFG(GPIO27, AF2)
+#define GPIO51_PWM2_OUT		MFP_CFG(GPIO51, AF2)
+#define GPIO117_PWM1_OUT	MFP_CFG(GPIO117, AF2)
+#define GPIO118_PWM2_OUT	MFP_CFG(GPIO118, AF2)
+#define GPIO119_PWM3_OUT	MFP_CFG(GPIO119, AF2)
+#define GPIO120_PWM4_OUT	MFP_CFG(GPIO120, AF2)
+
 #endif /* __ASM_MACH MFP_PXA910_H */
diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h
index ef0a8a2..6bf1f0e 100644
--- a/arch/arm/mach-mmp/include/mach/pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/pxa168.h
@@ -1,10 +1,18 @@
 #ifndef __ASM_MACH_PXA168_H
 #define __ASM_MACH_PXA168_H
 
+#include <linux/i2c.h>
 #include <mach/devices.h>
+#include <plat/i2c.h>
 
 extern struct pxa_device_desc pxa168_device_uart1;
 extern struct pxa_device_desc pxa168_device_uart2;
+extern struct pxa_device_desc pxa168_device_twsi0;
+extern struct pxa_device_desc pxa168_device_twsi1;
+extern struct pxa_device_desc pxa168_device_pwm1;
+extern struct pxa_device_desc pxa168_device_pwm2;
+extern struct pxa_device_desc pxa168_device_pwm3;
+extern struct pxa_device_desc pxa168_device_pwm4;
 
 static inline int pxa168_add_uart(int id)
 {
@@ -20,4 +28,40 @@
 
 	return pxa_register_device(d, NULL, 0);
 }
+
+static inline int pxa168_add_twsi(int id, struct i2c_pxa_platform_data *data,
+				  struct i2c_board_info *info, unsigned size)
+{
+	struct pxa_device_desc *d = NULL;
+	int ret;
+
+	switch (id) {
+	case 0: d = &pxa168_device_twsi0; break;
+	case 1: d = &pxa168_device_twsi1; break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = i2c_register_board_info(id, info, size);
+	if (ret)
+		return ret;
+
+	return pxa_register_device(d, data, sizeof(*data));
+}
+
+static inline int pxa168_add_pwm(int id)
+{
+	struct pxa_device_desc *d = NULL;
+
+	switch (id) {
+	case 1: d = &pxa168_device_pwm1; break;
+	case 2: d = &pxa168_device_pwm2; break;
+	case 3: d = &pxa168_device_pwm3; break;
+	case 4: d = &pxa168_device_pwm4; break;
+	default:
+		return -EINVAL;
+	}
+
+	return pxa_register_device(d, NULL, 0);
+}
 #endif /* __ASM_MACH_PXA168_H */
diff --git a/arch/arm/mach-mmp/include/mach/pxa910.h b/arch/arm/mach-mmp/include/mach/pxa910.h
index b7aeaf5..6ae1ed7 100644
--- a/arch/arm/mach-mmp/include/mach/pxa910.h
+++ b/arch/arm/mach-mmp/include/mach/pxa910.h
@@ -1,10 +1,18 @@
 #ifndef __ASM_MACH_PXA910_H
 #define __ASM_MACH_PXA910_H
 
+#include <linux/i2c.h>
 #include <mach/devices.h>
+#include <plat/i2c.h>
 
 extern struct pxa_device_desc pxa910_device_uart1;
 extern struct pxa_device_desc pxa910_device_uart2;
+extern struct pxa_device_desc pxa910_device_twsi0;
+extern struct pxa_device_desc pxa910_device_twsi1;
+extern struct pxa_device_desc pxa910_device_pwm1;
+extern struct pxa_device_desc pxa910_device_pwm2;
+extern struct pxa_device_desc pxa910_device_pwm3;
+extern struct pxa_device_desc pxa910_device_pwm4;
 
 static inline int pxa910_add_uart(int id)
 {
@@ -20,4 +28,40 @@
 
 	return pxa_register_device(d, NULL, 0);
 }
+
+static inline int pxa910_add_twsi(int id, struct i2c_pxa_platform_data *data,
+				  struct i2c_board_info *info, unsigned size)
+{
+	struct pxa_device_desc *d = NULL;
+	int ret;
+
+	switch (id) {
+	case 0: d = &pxa910_device_twsi0; break;
+	case 1: d = &pxa910_device_twsi1; break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = i2c_register_board_info(id, info, size);
+	if (ret)
+		return ret;
+
+	return pxa_register_device(d, data, sizeof(*data));
+}
+
+static inline int pxa910_add_pwm(int id)
+{
+	struct pxa_device_desc *d = NULL;
+
+	switch (id) {
+	case 1: d = &pxa910_device_pwm1; break;
+	case 2: d = &pxa910_device_pwm2; break;
+	case 3: d = &pxa910_device_pwm3; break;
+	case 4: d = &pxa910_device_pwm4; break;
+	default:
+		return -EINVAL;
+	}
+
+	return pxa_register_device(d, NULL, 0);
+}
 #endif /* __ASM_MACH_PXA910_H */
diff --git a/arch/arm/mach-mmp/include/mach/regs-apbc.h b/arch/arm/mach-mmp/include/mach/regs-apbc.h
index c6b8c9d..98ccbee 100644
--- a/arch/arm/mach-mmp/include/mach/regs-apbc.h
+++ b/arch/arm/mach-mmp/include/mach/regs-apbc.h
@@ -22,8 +22,10 @@
 #define APBC_PXA168_UART1	APBC_REG(0x000)
 #define APBC_PXA168_UART2	APBC_REG(0x004)
 #define APBC_PXA168_GPIO	APBC_REG(0x008)
-#define APBC_PXA168_PWM0	APBC_REG(0x00c)
-#define APBC_PXA168_PWM1	APBC_REG(0x010)
+#define APBC_PXA168_PWM1	APBC_REG(0x00c)
+#define APBC_PXA168_PWM2	APBC_REG(0x010)
+#define APBC_PXA168_PWM3	APBC_REG(0x014)
+#define APBC_PXA168_PWM4	APBC_REG(0x018)
 #define APBC_PXA168_SSP1	APBC_REG(0x01c)
 #define APBC_PXA168_SSP2	APBC_REG(0x020)
 #define APBC_PXA168_RTC		APBC_REG(0x028)
@@ -48,10 +50,10 @@
 #define APBC_PXA910_UART0	APBC_REG(0x000)
 #define APBC_PXA910_UART1	APBC_REG(0x004)
 #define APBC_PXA910_GPIO	APBC_REG(0x008)
-#define APBC_PXA910_PWM0	APBC_REG(0x00c)
-#define APBC_PXA910_PWM1	APBC_REG(0x010)
-#define APBC_PXA910_PWM2	APBC_REG(0x014)
-#define APBC_PXA910_PWM3	APBC_REG(0x018)
+#define APBC_PXA910_PWM1	APBC_REG(0x00c)
+#define APBC_PXA910_PWM2	APBC_REG(0x010)
+#define APBC_PXA910_PWM3	APBC_REG(0x014)
+#define APBC_PXA910_PWM4	APBC_REG(0x018)
 #define APBC_PXA910_SSP1	APBC_REG(0x01c)
 #define APBC_PXA910_SSP2	APBC_REG(0x020)
 #define APBC_PXA910_IPC		APBC_REG(0x024)
diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index ae92446..71b1ae3 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -65,11 +65,23 @@
 /* APB peripheral clocks */
 static APBC_CLK(uart1, PXA168_UART1, 1, 14745600);
 static APBC_CLK(uart2, PXA168_UART2, 1, 14745600);
+static APBC_CLK(twsi0, PXA168_TWSI0, 1, 33000000);
+static APBC_CLK(twsi1, PXA168_TWSI1, 1, 33000000);
+static APBC_CLK(pwm1, PXA168_PWM1, 1, 13000000);
+static APBC_CLK(pwm2, PXA168_PWM2, 1, 13000000);
+static APBC_CLK(pwm3, PXA168_PWM3, 1, 13000000);
+static APBC_CLK(pwm4, PXA168_PWM4, 1, 13000000);
 
 /* device and clock bindings */
 static struct clk_lookup pxa168_clkregs[] = {
 	INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
 	INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL),
+	INIT_CLKREG(&clk_twsi0, "pxa2xx-i2c.0", NULL),
+	INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.1", NULL),
+	INIT_CLKREG(&clk_pwm1, "pxa168-pwm.0", NULL),
+	INIT_CLKREG(&clk_pwm2, "pxa168-pwm.1", NULL),
+	INIT_CLKREG(&clk_pwm3, "pxa168-pwm.2", NULL),
+	INIT_CLKREG(&clk_pwm4, "pxa168-pwm.3", NULL),
 };
 
 static int __init pxa168_init(void)
@@ -109,3 +121,9 @@
 /* on-chip devices */
 PXA168_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4017000, 0x30, 21, 22);
 PXA168_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4018000, 0x30, 23, 24);
+PXA168_DEVICE(twsi0, "pxa2xx-i2c", 0, TWSI0, 0xd4011000, 0x28);
+PXA168_DEVICE(twsi1, "pxa2xx-i2c", 1, TWSI1, 0xd4025000, 0x28);
+PXA168_DEVICE(pwm1, "pxa168-pwm", 0, NONE, 0xd401a000, 0x10);
+PXA168_DEVICE(pwm2, "pxa168-pwm", 1, NONE, 0xd401a400, 0x10);
+PXA168_DEVICE(pwm3, "pxa168-pwm", 2, NONE, 0xd401a800, 0x10);
+PXA168_DEVICE(pwm4, "pxa168-pwm", 3, NONE, 0xd401ac00, 0x10);
diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c
index 453f8f7..5882ca6 100644
--- a/arch/arm/mach-mmp/pxa910.c
+++ b/arch/arm/mach-mmp/pxa910.c
@@ -103,11 +103,23 @@
 /* APB peripheral clocks */
 static APBC_CLK(uart1, PXA910_UART0, 1, 14745600);
 static APBC_CLK(uart2, PXA910_UART1, 1, 14745600);
+static APBC_CLK(twsi0, PXA168_TWSI0, 1, 33000000);
+static APBC_CLK(twsi1, PXA168_TWSI1, 1, 33000000);
+static APBC_CLK(pwm1, PXA910_PWM1, 1, 13000000);
+static APBC_CLK(pwm2, PXA910_PWM2, 1, 13000000);
+static APBC_CLK(pwm3, PXA910_PWM3, 1, 13000000);
+static APBC_CLK(pwm4, PXA910_PWM4, 1, 13000000);
 
 /* device and clock bindings */
 static struct clk_lookup pxa910_clkregs[] = {
 	INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
 	INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL),
+	INIT_CLKREG(&clk_twsi0, "pxa2xx-i2c.0", NULL),
+	INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.1", NULL),
+	INIT_CLKREG(&clk_pwm1, "pxa910-pwm.0", NULL),
+	INIT_CLKREG(&clk_pwm2, "pxa910-pwm.1", NULL),
+	INIT_CLKREG(&clk_pwm3, "pxa910-pwm.2", NULL),
+	INIT_CLKREG(&clk_pwm4, "pxa910-pwm.3", NULL),
 };
 
 static int __init pxa910_init(void)
@@ -156,3 +168,9 @@
  */
 PXA910_DEVICE(uart1, "pxa2xx-uart", 0, UART2, 0xd4017000, 0x30, 21, 22);
 PXA910_DEVICE(uart2, "pxa2xx-uart", 1, UART3, 0xd4018000, 0x30, 23, 24);
+PXA910_DEVICE(twsi0, "pxa2xx-i2c", 0, TWSI0, 0xd4011000, 0x28);
+PXA910_DEVICE(twsi1, "pxa2xx-i2c", 1, TWSI1, 0xd4025000, 0x28);
+PXA910_DEVICE(pwm1, "pxa910-pwm", 0, NONE, 0xd401a000, 0x10);
+PXA910_DEVICE(pwm2, "pxa910-pwm", 1, NONE, 0xd401a400, 0x10);
+PXA910_DEVICE(pwm3, "pxa910-pwm", 2, NONE, 0xd401a800, 0x10);
+PXA910_DEVICE(pwm4, "pxa910-pwm", 3, NONE, 0xd401ac00, 0x10);
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 17d3fbd..f4533f8 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -51,6 +51,12 @@
 	select IWMMXT
 	select PXA_HAVE_BOARD_IRQS
 
+config MACH_STARGATE2
+	bool "Intel Stargate 2 Platform"
+	select PXA27x
+	select IWMMXT
+	select PXA_HAVE_BOARD_IRQS
+
 config ARCH_LUBBOCK
 	bool "Intel DBPXA250 Development Platform"
 	select PXA25x
@@ -88,6 +94,10 @@
 	  SL-C3000 (Spitz), SL-C3100 (Borzoi) or SL-C6000x (Tosa)
 	  handheld computer.
 
+config SHARPSL_PM
+	bool
+	select APM_EMULATION
+
 config CORGI_SSP_DEPRECATED
 	bool
 	select PXA_SSP
@@ -280,6 +290,7 @@
 	select PXA3xx
 	select PXA_SSP
 	select HAVE_PWM
+	select PXA_HAVE_BOARD_IRQS
 
 config MACH_LITTLETON
 	bool "PXA3xx Form Factor Platform (aka Littleton)"
@@ -308,6 +319,14 @@
 	select PXA3xx
 	select CPU_PXA300
 
+config MACH_H4700
+	bool "HP iPAQ hx4700"
+	select PXA27x
+	select IWMMXT
+	select PXA_SSP
+	select HAVE_PWM
+	select PXA_HAVE_BOARD_IRQS
+
 config MACH_MAGICIAN
 	bool "Enable HTC Magician Support"
 	select PXA27x
@@ -505,12 +524,6 @@
 	help
 	  Enable support for PXA2xx SSP ports
 
-config PXA_PWM
-	tristate
-	default BACKLIGHT_PWM
-	help
-	  Enable support for PXA2xx/PXA3xx PWM controllers
-
 config TOSA_BT
 	tristate "Control the state of built-in bluetooth chip on Sharp SL-6000"
 	depends on MACH_TOSA
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 682dbf4..d18ffef 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -15,7 +15,6 @@
 
 # Generic drivers that other drivers may depend upon
 obj-$(CONFIG_PXA_SSP)		+= ssp.o
-obj-$(CONFIG_PXA_PWM)		+= pwm.o
 
 # SoC-specific code
 obj-$(CONFIG_PXA25x)		+= mfp-pxa2xx.o pxa2xx.o pxa25x.o
@@ -47,6 +46,7 @@
 obj-$(CONFIG_MACH_PCM990_BASEBOARD)	+= pcm990-baseboard.o
 obj-$(CONFIG_MACH_TOSA)		+= tosa.o
 obj-$(CONFIG_MACH_EM_X270)	+= em-x270.o
+obj-$(CONFIG_MACH_H4700)	+= hx4700.o
 obj-$(CONFIG_MACH_MAGICIAN)	+= magician.o
 obj-$(CONFIG_MACH_HIMALAYA)	+= himalaya.o
 obj-$(CONFIG_MACH_MIOA701)	+= mioa701.o mioa701_bootresume.o
@@ -78,6 +78,7 @@
 obj-$(CONFIG_PXA_EZX)           += ezx.o
 
 obj-$(CONFIG_MACH_INTELMOTE2)   += imote2.o
+obj-$(CONFIG_MACH_STARGATE2)	+= stargate2.o
 obj-$(CONFIG_MACH_CSB726)	+= csb726.o
 obj-$(CONFIG_CSB726_CSB701)	+= csb701.o
 
diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c
index 34576ba..1d2cec2 100644
--- a/arch/arm/mach-pxa/cm-x270.c
+++ b/arch/arm/mach-pxa/cm-x270.c
@@ -335,6 +335,10 @@
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(cmx270_pin_config));
 
+#ifdef CONFIG_PM
+	pxa27x_set_pwrmode(PWRMODE_DEEPSLEEP);
+#endif
+
 	cmx270_init_rtc();
 	cmx270_init_mmc();
 	cmx270_init_ohci();
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index a9f48b1..465da26 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -21,18 +21,20 @@
 #include <linux/gpio.h>
 #include <linux/dm9000.h>
 #include <linux/leds.h>
+#include <linux/rtc-v3020.h>
 
 #include <linux/i2c.h>
 #include <linux/i2c/pca953x.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+#include <asm/setup.h>
 
 #include <mach/pxa300.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/ohci.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/pxa3xx_nand.h>
 
 #include <asm/mach/map.h>
@@ -46,6 +48,11 @@
 
 #define	CM_X300_MMC2_IRQ	IRQ_GPIO(GPIO82_MMC2_IRQ)
 
+#define GPIO95_RTC_CS		(95)
+#define GPIO96_RTC_WR		(96)
+#define GPIO97_RTC_RD		(97)
+#define GPIO98_RTC_IO		(98)
+
 static mfp_cfg_t cm_x300_mfp_cfg[] __initdata = {
 	/* LCD */
 	GPIO54_LCD_LDD_0,
@@ -135,6 +142,12 @@
 	GPIO85_GPIO,			/* MMC WP */
 	GPIO99_GPIO,			/* Ethernet IRQ */
 
+	/* RTC GPIOs */
+	GPIO95_GPIO,			/* RTC CS */
+	GPIO96_GPIO,			/* RTC WR */
+	GPIO97_GPIO,			/* RTC RD */
+	GPIO98_GPIO,			/* RTC IO */
+
 	/* Standard I2C */
 	GPIO21_I2C_SCL,
 	GPIO22_I2C_SDA,
@@ -265,6 +278,7 @@
 
 static struct pxa3xx_nand_platform_data cm_x300_nand_info = {
 	.enable_arbiter	= 1,
+	.keep_config	= 1,
 	.parts		= cm_x300_nand_partitions,
 	.nr_parts	= ARRAY_SIZE(cm_x300_nand_partitions),
 };
@@ -441,6 +455,31 @@
 static inline void cm_x300_init_i2c(void) {}
 #endif
 
+#if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE)
+struct v3020_platform_data cm_x300_v3020_pdata = {
+	.use_gpio	= 1,
+	.gpio_cs	= GPIO95_RTC_CS,
+	.gpio_wr	= GPIO96_RTC_WR,
+	.gpio_rd	= GPIO97_RTC_RD,
+	.gpio_io	= GPIO98_RTC_IO,
+};
+
+static struct platform_device cm_x300_rtc_device = {
+	.name		= "v3020",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &cm_x300_v3020_pdata,
+	}
+};
+
+static void __init cm_x300_init_rtc(void)
+{
+	platform_device_register(&cm_x300_rtc_device);
+}
+#else
+static inline void cm_x300_init_rtc(void) {}
+#endif
+
 static void __init cm_x300_init(void)
 {
 	/* board-processor specific GPIO initialization */
@@ -453,6 +492,19 @@
 	cm_x300_init_nand();
 	cm_x300_init_leds();
 	cm_x300_init_i2c();
+	cm_x300_init_rtc();
+}
+
+static void __init cm_x300_fixup(struct machine_desc *mdesc, struct tag *tags,
+				 char **cmdline, struct meminfo *mi)
+{
+	mi->nr_banks = 2;
+	mi->bank[0].start = 0xa0000000;
+	mi->bank[0].node = 0;
+	mi->bank[0].size = (64*1024*1024);
+	mi->bank[1].start = 0xc0000000;
+	mi->bank[1].node = 0;
+	mi->bank[1].size = (64*1024*1024);
 }
 
 MACHINE_START(CM_X300, "CM-X300 module")
@@ -463,4 +515,5 @@
 	.init_irq	= pxa3xx_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= cm_x300_init,
+	.fixup		= cm_x300_fixup,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 930e364..962dda2 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -42,7 +42,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/pxa25x.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/irda.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
@@ -445,13 +445,8 @@
 	.wait_for_sync		= corgi_wait_for_hsync,
 };
 
-static void corgi_ads7846_cs(u32 command)
-{
-	gpio_set_value(CORGI_GPIO_ADS7846_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
 static struct pxa2xx_spi_chip corgi_ads7846_chip = {
-	.cs_control	= corgi_ads7846_cs,
+	.gpio_cs	= CORGI_GPIO_ADS7846_CS,
 };
 
 static void corgi_bl_kick_battery(void)
@@ -475,22 +470,12 @@
 	.kick_battery		= corgi_bl_kick_battery,
 };
 
-static void corgi_lcdcon_cs(u32 command)
-{
-	gpio_set_value(CORGI_GPIO_LCDCON_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
 static struct pxa2xx_spi_chip corgi_lcdcon_chip = {
-	.cs_control	= corgi_lcdcon_cs,
+	.gpio_cs	= CORGI_GPIO_LCDCON_CS,
 };
 
-static void corgi_max1111_cs(u32 command)
-{
-	gpio_set_value(CORGI_GPIO_MAX1111_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
 static struct pxa2xx_spi_chip corgi_max1111_chip = {
-	.cs_control	= corgi_max1111_cs,
+	.gpio_cs	= CORGI_GPIO_MAX1111_CS,
 };
 
 static struct spi_board_info corgi_spi_devices[] = {
@@ -520,32 +505,8 @@
 
 static void __init corgi_init_spi(void)
 {
-	int err;
-
-	err = gpio_request(CORGI_GPIO_ADS7846_CS, "ADS7846_CS");
-	if (err)
-		return;
-
-	err = gpio_request(CORGI_GPIO_LCDCON_CS, "LCDCON_CS");
-	if (err)
-		goto err_free_1;
-
-	err = gpio_request(CORGI_GPIO_MAX1111_CS, "MAX1111_CS");
-	if (err)
-		goto err_free_2;
-
-	gpio_direction_output(CORGI_GPIO_ADS7846_CS, 1);
-	gpio_direction_output(CORGI_GPIO_LCDCON_CS, 1);
-	gpio_direction_output(CORGI_GPIO_MAX1111_CS, 1);
-
 	pxa2xx_set_spi_info(1, &corgi_spi_info);
 	spi_register_board_info(ARRAY_AND_SIZE(corgi_spi_devices));
-	return;
-
-err_free_2:
-	gpio_free(CORGI_GPIO_LCDCON_CS);
-err_free_1:
-	gpio_free(CORGI_GPIO_ADS7846_CS);
 }
 #else
 static inline void corgi_init_spi(void) {}
diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c
index 7f04b3a..a093282 100644
--- a/arch/arm/mach-pxa/corgi_pm.c
+++ b/arch/arm/mach-pxa/corgi_pm.c
@@ -41,7 +41,6 @@
 	pxa_gpio_mode(CORGI_GPIO_CHRG_ON | GPIO_OUT);
 	pxa_gpio_mode(CORGI_GPIO_CHRG_UKN | GPIO_OUT);
 	pxa_gpio_mode(CORGI_GPIO_KEY_INT | GPIO_IN);
-	sharpsl_pm_pxa_init();
 }
 
 static void corgi_measure_temp(int on)
@@ -191,7 +190,7 @@
 
 static struct sharpsl_charger_machinfo corgi_pm_machinfo = {
 	.init            = corgi_charger_init,
-	.exit            = sharpsl_pm_pxa_remove,
+	.exit            = NULL,
 	.gpio_batlock    = CORGI_GPIO_BAT_COVER,
 	.gpio_acin       = CORGI_GPIO_AC_IN,
 	.gpio_batfull    = CORGI_GPIO_CHRG_FULL,
diff --git a/arch/arm/mach-pxa/cpufreq-pxa2xx.c b/arch/arm/mach-pxa/cpufreq-pxa2xx.c
index 083a1d8..3a8ee22 100644
--- a/arch/arm/mach-pxa/cpufreq-pxa2xx.c
+++ b/arch/arm/mach-pxa/cpufreq-pxa2xx.c
@@ -36,6 +36,8 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/cpufreq.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
 
 #include <mach/pxa2xx-regs.h>
 
@@ -47,6 +49,8 @@
 #define freq_debug  0
 #endif
 
+static struct regulator *vcc_core;
+
 static unsigned int pxa27x_maxfreq;
 module_param(pxa27x_maxfreq, uint, 0);
 MODULE_PARM_DESC(pxa27x_maxfreq, "Set the pxa27x maxfreq in MHz"
@@ -58,6 +62,8 @@
 	unsigned int cccr;
 	unsigned int div2;
 	unsigned int cclkcfg;
+	int vmin;
+	int vmax;
 } pxa_freqs_t;
 
 /* Define the refresh period in mSec for the SDRAM and the number of rows */
@@ -82,24 +88,24 @@
 
 static pxa_freqs_t pxa255_run_freqs[] =
 {
-	/* CPU   MEMBUS  CCCR  DIV2 CCLKCFG	   run  turbo PXbus SDRAM */
-	{ 99500,  99500, 0x121, 1,  CCLKCFG},	/*  99,   99,   50,   50  */
-	{132700, 132700, 0x123, 1,  CCLKCFG},	/* 133,  133,   66,   66  */
-	{199100,  99500, 0x141, 0,  CCLKCFG},	/* 199,  199,   99,   99  */
-	{265400, 132700, 0x143, 1,  CCLKCFG},	/* 265,  265,  133,   66  */
-	{331800, 165900, 0x145, 1,  CCLKCFG},	/* 331,  331,  166,   83  */
-	{398100,  99500, 0x161, 0,  CCLKCFG},	/* 398,  398,  196,   99  */
+	/* CPU   MEMBUS  CCCR  DIV2 CCLKCFG	           run  turbo PXbus SDRAM */
+	{ 99500,  99500, 0x121, 1,  CCLKCFG, -1, -1},	/*  99,   99,   50,   50  */
+	{132700, 132700, 0x123, 1,  CCLKCFG, -1, -1},	/* 133,  133,   66,   66  */
+	{199100,  99500, 0x141, 0,  CCLKCFG, -1, -1},	/* 199,  199,   99,   99  */
+	{265400, 132700, 0x143, 1,  CCLKCFG, -1, -1},	/* 265,  265,  133,   66  */
+	{331800, 165900, 0x145, 1,  CCLKCFG, -1, -1},	/* 331,  331,  166,   83  */
+	{398100,  99500, 0x161, 0,  CCLKCFG, -1, -1},	/* 398,  398,  196,   99  */
 };
 
 /* Use the turbo mode frequencies for the CPUFREQ_POLICY_POWERSAVE policy */
 static pxa_freqs_t pxa255_turbo_freqs[] =
 {
 	/* CPU   MEMBUS  CCCR  DIV2 CCLKCFG	   run  turbo PXbus SDRAM */
-	{ 99500, 99500,  0x121, 1,  CCLKCFG},	/*  99,   99,   50,   50  */
-	{199100, 99500,  0x221, 0,  CCLKCFG},	/*  99,  199,   50,   99  */
-	{298500, 99500,  0x321, 0,  CCLKCFG},	/*  99,  287,   50,   99  */
-	{298600, 99500,  0x1c1, 0,  CCLKCFG},	/* 199,  287,   99,   99  */
-	{398100, 99500,  0x241, 0,  CCLKCFG},	/* 199,  398,   99,   99  */
+	{ 99500, 99500,  0x121, 1,  CCLKCFG, -1, -1},	/*  99,   99,   50,   50  */
+	{199100, 99500,  0x221, 0,  CCLKCFG, -1, -1},	/*  99,  199,   50,   99  */
+	{298500, 99500,  0x321, 0,  CCLKCFG, -1, -1},	/*  99,  287,   50,   99  */
+	{298600, 99500,  0x1c1, 0,  CCLKCFG, -1, -1},	/* 199,  287,   99,   99  */
+	{398100, 99500,  0x241, 0,  CCLKCFG, -1, -1},	/* 199,  398,   99,   99  */
 };
 
 #define NUM_PXA25x_RUN_FREQS ARRAY_SIZE(pxa255_run_freqs)
@@ -148,13 +154,13 @@
    ((T)  ? CCLKCFG_TURBO : 0))
 
 static pxa_freqs_t pxa27x_freqs[] = {
-	{104000, 104000, PXA27x_CCCR(1,	 8, 2), 0, CCLKCFG2(1, 0, 1)},
-	{156000, 104000, PXA27x_CCCR(1,	 8, 6), 0, CCLKCFG2(1, 1, 1)},
-	{208000, 208000, PXA27x_CCCR(0, 16, 2), 1, CCLKCFG2(0, 0, 1)},
-	{312000, 208000, PXA27x_CCCR(1, 16, 3), 1, CCLKCFG2(1, 0, 1)},
-	{416000, 208000, PXA27x_CCCR(1, 16, 4), 1, CCLKCFG2(1, 0, 1)},
-	{520000, 208000, PXA27x_CCCR(1, 16, 5), 1, CCLKCFG2(1, 0, 1)},
-	{624000, 208000, PXA27x_CCCR(1, 16, 6), 1, CCLKCFG2(1, 0, 1)}
+	{104000, 104000, PXA27x_CCCR(1,	 8, 2), 0, CCLKCFG2(1, 0, 1),  900000, 1705000 },
+	{156000, 104000, PXA27x_CCCR(1,	 8, 6), 0, CCLKCFG2(1, 1, 1), 1000000, 1705000 },
+	{208000, 208000, PXA27x_CCCR(0, 16, 2), 1, CCLKCFG2(0, 0, 1), 1180000, 1705000 },
+	{312000, 208000, PXA27x_CCCR(1, 16, 3), 1, CCLKCFG2(1, 0, 1), 1250000, 1705000 },
+	{416000, 208000, PXA27x_CCCR(1, 16, 4), 1, CCLKCFG2(1, 0, 1), 1350000, 1705000 },
+	{520000, 208000, PXA27x_CCCR(1, 16, 5), 1, CCLKCFG2(1, 0, 1), 1450000, 1705000 },
+	{624000, 208000, PXA27x_CCCR(1, 16, 6), 1, CCLKCFG2(1, 0, 1), 1550000, 1705000 }
 };
 
 #define NUM_PXA27x_FREQS ARRAY_SIZE(pxa27x_freqs)
@@ -163,6 +169,47 @@
 
 extern unsigned get_clk_frequency_khz(int info);
 
+#ifdef CONFIG_REGULATOR
+
+static int pxa_cpufreq_change_voltage(pxa_freqs_t *pxa_freq)
+{
+	int ret = 0;
+	int vmin, vmax;
+
+	if (!cpu_is_pxa27x())
+		return 0;
+
+	vmin = pxa_freq->vmin;
+	vmax = pxa_freq->vmax;
+	if ((vmin == -1) || (vmax == -1))
+		return 0;
+
+	ret = regulator_set_voltage(vcc_core, vmin, vmax);
+	if (ret)
+		pr_err("cpufreq: Failed to set vcc_core in [%dmV..%dmV]\n",
+		       vmin, vmax);
+	return ret;
+}
+
+static __init void pxa_cpufreq_init_voltages(void)
+{
+	vcc_core = regulator_get(NULL, "vcc_core");
+	if (IS_ERR(vcc_core)) {
+		pr_info("cpufreq: Didn't find vcc_core regulator\n");
+		vcc_core = NULL;
+	} else {
+		pr_info("cpufreq: Found vcc_core regulator\n");
+	}
+}
+#else
+static int pxa_cpufreq_change_voltage(pxa_freqs_t *pxa_freq)
+{
+	return 0;
+}
+
+static __init void pxa_cpufreq_init_voltages(void) { }
+#endif
+
 static void find_freq_tables(struct cpufreq_frequency_table **freq_table,
 			     pxa_freqs_t **pxa_freqs)
 {
@@ -251,6 +298,7 @@
 	unsigned long flags;
 	unsigned int new_freq_cpu, new_freq_mem;
 	unsigned int unused, preset_mdrefr, postset_mdrefr, cclkcfg;
+	int ret = 0;
 
 	/* Get the current policy */
 	find_freq_tables(&pxa_freqs_table, &pxa_freq_settings);
@@ -273,6 +321,10 @@
 			 freqs.new / 1000, (pxa_freq_settings[idx].div2) ?
 			 (new_freq_mem / 2000) : (new_freq_mem / 1000));
 
+	if (vcc_core && freqs.new > freqs.old)
+		ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]);
+	if (ret)
+		return ret;
 	/*
 	 * Tell everyone what we're about to do...
 	 * you should add a notify client with any platform specific
@@ -335,6 +387,18 @@
 	 */
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
+	/*
+	 * Even if voltage setting fails, we don't report it, as the frequency
+	 * change succeeded. The voltage reduction is not a critical failure,
+	 * only power savings will suffer from this.
+	 *
+	 * Note: if the voltage change fails, and a return value is returned, a
+	 * bug is triggered (seems a deadlock). Should anybody find out where,
+	 * the "return 0" should become a "return ret".
+	 */
+	if (vcc_core && freqs.new < freqs.old)
+		ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]);
+
 	return 0;
 }
 
@@ -349,6 +413,8 @@
 	if (cpu_is_pxa27x())
 		pxa27x_guess_max_freq();
 
+	pxa_cpufreq_init_voltages();
+
 	init_sdram_rows();
 
 	/* set default policy and cpuinfo */
diff --git a/arch/arm/mach-pxa/csb726.c b/arch/arm/mach-pxa/csb726.c
index 2b289f8..7d3e1b4 100644
--- a/arch/arm/mach-pxa/csb726.c
+++ b/arch/arm/mach-pxa/csb726.c
@@ -16,15 +16,17 @@
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/partitions.h>
 #include <linux/sm501.h>
+#include <linux/smsc911x.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/csb726.h>
 #include <mach/mfp-pxa27x.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/ohci.h>
 #include <mach/pxa2xx-regs.h>
+#include <mach/audio.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -275,15 +277,26 @@
 	{
 		.start	= CSB726_IRQ_LAN,
 		.end	= CSB726_IRQ_LAN,
-		.flags	= IORESOURCE_IRQ,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
 	},
 };
 
+struct smsc911x_platform_config csb726_lan_config = {
+	.irq_type	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
+	.flags		= SMSC911X_USE_32BIT,
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+};
+
+
 static struct platform_device csb726_lan = {
-	.name		= "smc911x",
+	.name		= "smsc911x",
 	.id		= -1,
 	.num_resources	= ARRAY_SIZE(csb726_lan_resources),
 	.resource	= csb726_lan_resources,
+	.dev		= {
+		.platform_data	= &csb726_lan_config,
+	},
 };
 
 static struct platform_device *devices[] __initdata = {
@@ -303,6 +316,7 @@
 	pxa27x_set_i2c_power_info(NULL);
 	pxa_set_mci_info(&csb726_mci);
 	pxa_set_ohci_info(&csb726_ohci_platform_data);
+	pxa_set_ac97_info(NULL);
 
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index d245e59c..d3c3b7b 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -8,7 +8,7 @@
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/irda.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/ohci.h>
 #include <mach/pxa27x_keypad.h>
 #include <mach/pxa2xx_spi.h>
@@ -287,7 +287,7 @@
 };
 
 struct platform_device pxa3xx_device_i2c_power = {
-	.name		= "pxa2xx-i2c",
+	.name		= "pxa3xx-pwri2c",
 	.id		= 1,
 	.resource	= pxa3xx_resources_i2c_power,
 	.num_resources	= ARRAY_SIZE(pxa3xx_resources_i2c_power),
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index bc0f73f..243e080 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -28,6 +28,8 @@
 #include <linux/spi/libertas_spi.h>
 #include <linux/power_supply.h>
 #include <linux/apm-emulation.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
 
 #include <media/soc_camera.h>
 
@@ -41,7 +43,7 @@
 #include <mach/ohci.h>
 #include <mach/mmc.h>
 #include <mach/pxa27x_keypad.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/camera.h>
 #include <mach/pxa2xx_spi.h>
 
@@ -52,23 +54,31 @@
 #define GPIO13_MMC_CD		(13)
 #define GPIO95_MMC_WP		(95)
 #define GPIO56_NAND_RB		(56)
+#define GPIO93_CAM_RESET	(93)
+#define GPIO16_USB_HUB_RESET	(16)
 
 /* eXeda specific GPIOs */
 #define GPIO114_MMC_CD		(114)
 #define GPIO20_NAND_RB		(20)
 #define GPIO38_SD_PWEN		(38)
+#define GPIO37_WLAN_RST		(37)
+#define GPIO95_TOUCHPAD_INT	(95)
+#define GPIO130_CAM_RESET	(130)
+#define GPIO10_USB_HUB_RESET	(10)
 
 /* common  GPIOs */
 #define GPIO11_NAND_CS		(11)
-#define GPIO93_CAM_RESET	(93)
 #define GPIO41_ETHIRQ		(41)
 #define EM_X270_ETHIRQ		IRQ_GPIO(GPIO41_ETHIRQ)
 #define GPIO115_WLAN_PWEN	(115)
 #define GPIO19_WLAN_STRAP	(19)
+#define GPIO9_USB_VBUS_EN	(9)
 
 static int mmc_cd;
 static int nand_rb;
 static int dm9000_flags;
+static int cam_reset;
+static int usb_hub_reset;
 
 static unsigned long common_pin_config[] = {
 	/* AC'97 */
@@ -180,7 +190,6 @@
 
 	/* power controls */
 	GPIO20_GPIO	| MFP_LPM_DRIVE_LOW,	/* GPRS_PWEN */
-	GPIO93_GPIO	| MFP_LPM_DRIVE_LOW,	/* Camera reset */
 	GPIO115_GPIO	| MFP_LPM_DRIVE_LOW,	/* WLAN_PWEN */
 
 	/* NAND controls */
@@ -191,14 +200,18 @@
 };
 
 static unsigned long em_x270_pin_config[] = {
-	GPIO13_GPIO,	/* MMC card detect */
-	GPIO56_GPIO,	/* NAND Ready/Busy */
-	GPIO95_GPIO,	/* MMC Write protect */
+	GPIO13_GPIO,				/* MMC card detect */
+	GPIO16_GPIO,				/* USB hub reset */
+	GPIO56_GPIO,				/* NAND Ready/Busy */
+	GPIO93_GPIO	| MFP_LPM_DRIVE_LOW,	/* Camera reset */
+	GPIO95_GPIO,				/* MMC Write protect */
 };
 
 static unsigned long exeda_pin_config[] = {
+	GPIO10_GPIO,				/* USB hub reset */
 	GPIO20_GPIO,				/* NAND Ready/Busy */
 	GPIO38_GPIO	| MFP_LPM_DRIVE_LOW,	/* SD slot power */
+	GPIO95_GPIO,				/* touchpad IRQ */
 	GPIO114_GPIO,				/* MMC card detect */
 };
 
@@ -464,18 +477,79 @@
 
 /* PXA27x OHCI controller setup */
 #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static struct regulator *em_x270_usb_ldo;
+
+static int em_x270_usb_hub_init(void)
+{
+	int err;
+
+	em_x270_usb_ldo = regulator_get(NULL, "vcc usb");
+	if (IS_ERR(em_x270_usb_ldo))
+		return PTR_ERR(em_x270_usb_ldo);
+
+	err = gpio_request(GPIO9_USB_VBUS_EN, "vbus en");
+	if (err)
+		goto err_free_usb_ldo;
+
+	err = gpio_request(usb_hub_reset, "hub rst");
+	if (err)
+		goto err_free_vbus_gpio;
+
+	/* USB Hub power-on and reset */
+	gpio_direction_output(usb_hub_reset, 0);
+	regulator_enable(em_x270_usb_ldo);
+	gpio_set_value(usb_hub_reset, 1);
+	gpio_set_value(usb_hub_reset, 0);
+	regulator_disable(em_x270_usb_ldo);
+	regulator_enable(em_x270_usb_ldo);
+	gpio_set_value(usb_hub_reset, 1);
+
+	/* enable VBUS */
+	gpio_direction_output(GPIO9_USB_VBUS_EN, 1);
+
+	return 0;
+
+err_free_vbus_gpio:
+	gpio_free(GPIO9_USB_VBUS_EN);
+err_free_usb_ldo:
+	regulator_put(em_x270_usb_ldo);
+
+	return err;
+}
+
 static int em_x270_ohci_init(struct device *dev)
 {
+	int err;
+
+	/* we don't want to entirely disable USB if the HUB init failed */
+	err = em_x270_usb_hub_init();
+	if (err)
+		pr_err("USB Hub initialization failed: %d\n", err);
+
 	/* enable port 2 transiever */
 	UP2OCR = UP2OCR_HXS | UP2OCR_HXOE;
 
 	return 0;
 }
 
+static void em_x270_ohci_exit(struct device *dev)
+{
+	gpio_free(usb_hub_reset);
+	gpio_free(GPIO9_USB_VBUS_EN);
+
+	if (!IS_ERR(em_x270_usb_ldo)) {
+		if (regulator_is_enabled(em_x270_usb_ldo))
+			regulator_disable(em_x270_usb_ldo);
+
+		regulator_put(em_x270_usb_ldo);
+	}
+}
+
 static struct pxaohci_platform_data em_x270_ohci_platform_data = {
 	.port_mode	= PMM_PERPORT_MODE,
 	.flags		= ENABLE_PORT1 | ENABLE_PORT2 | POWER_CONTROL_LOW,
 	.init		= em_x270_ohci_init,
+	.exit		= em_x270_ohci_exit,
 };
 
 static void __init em_x270_init_ohci(void)
@@ -677,26 +751,52 @@
 	if (err)
 		return err;
 
+	err = gpio_request(GPIO19_WLAN_STRAP, "WLAN STRAP");
+	if (err)
+		goto err_free_pwen;
+
+	if (machine_is_exeda()) {
+		err = gpio_request(GPIO37_WLAN_RST, "WLAN RST");
+		if (err)
+			goto err_free_strap;
+
+		gpio_direction_output(GPIO37_WLAN_RST, 1);
+		msleep(100);
+	}
+
 	gpio_direction_output(GPIO19_WLAN_STRAP, 1);
-	mdelay(100);
+	msleep(100);
 
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(em_x270_libertas_pin_config));
 
 	gpio_direction_output(GPIO115_WLAN_PWEN, 0);
-	mdelay(100);
+	msleep(100);
 	gpio_set_value(GPIO115_WLAN_PWEN, 1);
-	mdelay(100);
+	msleep(100);
 
 	spi->bits_per_word = 16;
 	spi_setup(spi);
 
 	return 0;
+
+err_free_strap:
+	gpio_free(GPIO19_WLAN_STRAP);
+err_free_pwen:
+	gpio_free(GPIO115_WLAN_PWEN);
+
+	return err;
 }
 
 static int em_x270_libertas_teardown(struct spi_device *spi)
 {
 	gpio_set_value(GPIO115_WLAN_PWEN, 0);
 	gpio_free(GPIO115_WLAN_PWEN);
+	gpio_free(GPIO19_WLAN_STRAP);
+
+	if (machine_is_exeda()) {
+		gpio_set_value(GPIO37_WLAN_RST, 0);
+		gpio_free(GPIO37_WLAN_RST);
+	}
 
 	return 0;
 }
@@ -863,26 +963,26 @@
 {
 	int ret;
 
-	ret = gpio_request(GPIO93_CAM_RESET, "camera reset");
+	ret = gpio_request(cam_reset, "camera reset");
 	if (ret)
 		return ret;
 
-	gpio_direction_output(GPIO93_CAM_RESET, 0);
+	gpio_direction_output(cam_reset, 0);
 
 	em_x270_camera_ldo = regulator_get(NULL, "vcc cam");
 	if (em_x270_camera_ldo == NULL) {
-		gpio_free(GPIO93_CAM_RESET);
+		gpio_free(cam_reset);
 		return -ENODEV;
 	}
 
 	ret = regulator_enable(em_x270_camera_ldo);
 	if (ret) {
 		regulator_put(em_x270_camera_ldo);
-		gpio_free(GPIO93_CAM_RESET);
+		gpio_free(cam_reset);
 		return ret;
 	}
 
-	gpio_set_value(GPIO93_CAM_RESET, 1);
+	gpio_set_value(cam_reset, 1);
 
 	return 0;
 }
@@ -902,7 +1002,7 @@
 	if (on == is_on)
 		return 0;
 
-	gpio_set_value(GPIO93_CAM_RESET, !on);
+	gpio_set_value(cam_reset, !on);
 
 	if (on)
 		ret = regulator_enable(em_x270_camera_ldo);
@@ -912,7 +1012,7 @@
 	if (ret)
 		return ret;
 
-	gpio_set_value(GPIO93_CAM_RESET, on);
+	gpio_set_value(cam_reset, on);
 
 	return 0;
 }
@@ -929,13 +1029,8 @@
 	},
 };
 
-static struct i2c_pxa_platform_data em_x270_i2c_info = {
-	.fast_mode = 1,
-};
-
 static void  __init em_x270_init_camera(void)
 {
-	pxa_set_i2c_info(&em_x270_i2c_info);
 	i2c_register_board_info(0, ARRAY_AND_SIZE(em_x270_i2c_cam_info));
 	pxa_set_camera_info(&em_x270_camera_platform_data);
 }
@@ -985,7 +1080,7 @@
 };
 
 struct power_supply_info em_x270_psy_info = {
-	.name = "LP555597P6H-FPS",
+	.name = "battery",
 	.technology = POWER_SUPPLY_TECHNOLOGY_LIPO,
 	.voltage_max_design = 4200000,
 	.voltage_min_design = 3000000,
@@ -1069,6 +1164,29 @@
 	i2c_register_board_info(1, &em_x270_i2c_pmic_info, 1);
 }
 
+static struct pca953x_platform_data exeda_gpio_ext_pdata = {
+	.gpio_base = 128,
+};
+
+static struct i2c_board_info exeda_i2c_info[] = {
+	{
+		I2C_BOARD_INFO("pca9555", 0x21),
+		.platform_data = &exeda_gpio_ext_pdata,
+	},
+};
+
+static struct i2c_pxa_platform_data em_x270_i2c_info = {
+	.fast_mode = 1,
+};
+
+static void __init em_x270_init_i2c(void)
+{
+	pxa_set_i2c_info(&em_x270_i2c_info);
+
+	if (machine_is_exeda())
+		i2c_register_board_info(0, ARRAY_AND_SIZE(exeda_i2c_info));
+}
+
 static void __init em_x270_module_init(void)
 {
 	pr_info("%s\n", __func__);
@@ -1077,6 +1195,8 @@
 	mmc_cd = GPIO13_MMC_CD;
 	nand_rb = GPIO56_NAND_RB;
 	dm9000_flags = DM9000_PLATF_32BITONLY;
+	cam_reset = GPIO93_CAM_RESET;
+	usb_hub_reset = GPIO16_USB_HUB_RESET;
 }
 
 static void __init em_x270_exeda_init(void)
@@ -1087,12 +1207,18 @@
 	mmc_cd = GPIO114_MMC_CD;
 	nand_rb = GPIO20_NAND_RB;
 	dm9000_flags = DM9000_PLATF_16BITONLY;
+	cam_reset = GPIO130_CAM_RESET;
+	usb_hub_reset = GPIO10_USB_HUB_RESET;
 }
 
 static void __init em_x270_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(common_pin_config));
 
+#ifdef CONFIG_PM
+	pxa27x_set_pwrmode(PWRMODE_DEEPSLEEP);
+#endif
+
 	if (machine_is_em_x270())
 		em_x270_module_init();
 	else if (machine_is_exeda())
@@ -1111,8 +1237,9 @@
 	em_x270_init_keypad();
 	em_x270_init_gpio_keys();
 	em_x270_init_ac97();
-	em_x270_init_camera();
 	em_x270_init_spi();
+	em_x270_init_i2c();
+	em_x270_init_camera();
 }
 
 MACHINE_START(EM_X270, "Compulab EM-X270")
diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c
index 7db966d..588b265 100644
--- a/arch/arm/mach-pxa/ezx.c
+++ b/arch/arm/mach-pxa/ezx.c
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/pwm_backlight.h>
 #include <linux/input.h>
+#include <linux/gpio_keys.h>
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -25,13 +26,19 @@
 #include <mach/pxa27x.h>
 #include <mach/pxafb.h>
 #include <mach/ohci.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/hardware.h>
 #include <mach/pxa27x_keypad.h>
 
 #include "devices.h"
 #include "generic.h"
 
+#define GPIO12_A780_FLIP_LID 		12
+#define GPIO15_A1200_FLIP_LID 		15
+#define GPIO15_A910_FLIP_LID 		15
+#define GPIO12_E680_LOCK_SWITCH 	12
+#define GPIO15_E6_LOCK_SWITCH 		15
+
 static struct platform_pwm_backlight_data ezx_backlight_data = {
 	.pwm_id		= 0,
 	.max_brightness	= 1023,
@@ -88,7 +95,7 @@
 	.lcd_conn	= LCD_COLOR_TFT_18BPP,
 };
 
-static struct platform_device *devices[] __initdata = {
+static struct platform_device *ezx_devices[] __initdata = {
 	&ezx_backlight_device,
 };
 
@@ -651,6 +658,35 @@
 #endif /* CONFIG_MACH_EZX_E2 */
 
 #ifdef CONFIG_MACH_EZX_A780
+/* gpio_keys */
+static struct gpio_keys_button a780_buttons[] = {
+	[0] = {
+		.code       = SW_LID,
+		.gpio       = GPIO12_A780_FLIP_LID,
+		.active_low = 0,
+		.desc       = "A780 flip lid",
+		.type       = EV_SW,
+		.wakeup     = 1,
+	},
+};
+
+static struct gpio_keys_platform_data a780_gpio_keys_platform_data = {
+	.buttons  = a780_buttons,
+	.nbuttons = ARRAY_SIZE(a780_buttons),
+};
+
+static struct platform_device a780_gpio_keys = {
+	.name = "gpio-keys",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &a780_gpio_keys_platform_data,
+	},
+};
+
+static struct platform_device *a780_devices[] __initdata = {
+	&a780_gpio_keys,
+};
+
 static void __init a780_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config));
@@ -663,7 +699,8 @@
 
 	pxa_set_keypad_info(&a780_keypad_platform_data);
 
-	platform_add_devices(devices, ARRAY_SIZE(devices));
+	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
+	platform_add_devices(ARRAY_AND_SIZE(a780_devices));
 }
 
 MACHINE_START(EZX_A780, "Motorola EZX A780")
@@ -678,10 +715,39 @@
 #endif
 
 #ifdef CONFIG_MACH_EZX_E680
+/* gpio_keys */
+static struct gpio_keys_button e680_buttons[] = {
+	[0] = {
+		.code       = KEY_SCREENLOCK,
+		.gpio       = GPIO12_E680_LOCK_SWITCH,
+		.active_low = 0,
+		.desc       = "E680 lock switch",
+		.type       = EV_KEY,
+		.wakeup     = 1,
+	},
+};
+
+static struct gpio_keys_platform_data e680_gpio_keys_platform_data = {
+	.buttons  = e680_buttons,
+	.nbuttons = ARRAY_SIZE(e680_buttons),
+};
+
+static struct platform_device e680_gpio_keys = {
+	.name = "gpio-keys",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &e680_gpio_keys_platform_data,
+	},
+};
+
 static struct i2c_board_info __initdata e680_i2c_board_info[] = {
 	{ I2C_BOARD_INFO("tea5767", 0x81) },
 };
 
+static struct platform_device *e680_devices[] __initdata = {
+	&e680_gpio_keys,
+};
+
 static void __init e680_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config));
@@ -695,7 +761,8 @@
 
 	pxa_set_keypad_info(&e680_keypad_platform_data);
 
-	platform_add_devices(devices, ARRAY_SIZE(devices));
+	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
+	platform_add_devices(ARRAY_AND_SIZE(e680_devices));
 }
 
 MACHINE_START(EZX_E680, "Motorola EZX E680")
@@ -710,10 +777,39 @@
 #endif
 
 #ifdef CONFIG_MACH_EZX_A1200
+/* gpio_keys */
+static struct gpio_keys_button a1200_buttons[] = {
+	[0] = {
+		.code       = SW_LID,
+		.gpio       = GPIO15_A1200_FLIP_LID,
+		.active_low = 0,
+		.desc       = "A1200 flip lid",
+		.type       = EV_SW,
+		.wakeup     = 1,
+	},
+};
+
+static struct gpio_keys_platform_data a1200_gpio_keys_platform_data = {
+	.buttons  = a1200_buttons,
+	.nbuttons = ARRAY_SIZE(a1200_buttons),
+};
+
+static struct platform_device a1200_gpio_keys = {
+	.name = "gpio-keys",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &a1200_gpio_keys_platform_data,
+	},
+};
+
 static struct i2c_board_info __initdata a1200_i2c_board_info[] = {
 	{ I2C_BOARD_INFO("tea5767", 0x81) },
 };
 
+static struct platform_device *a1200_devices[] __initdata = {
+	&a1200_gpio_keys,
+};
+
 static void __init a1200_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config));
@@ -727,7 +823,8 @@
 
 	pxa_set_keypad_info(&a1200_keypad_platform_data);
 
-	platform_add_devices(devices, ARRAY_SIZE(devices));
+	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
+	platform_add_devices(ARRAY_AND_SIZE(a1200_devices));
 }
 
 MACHINE_START(EZX_A1200, "Motorola EZX A1200")
@@ -742,6 +839,35 @@
 #endif
 
 #ifdef CONFIG_MACH_EZX_A910
+/* gpio_keys */
+static struct gpio_keys_button a910_buttons[] = {
+	[0] = {
+		.code       = SW_LID,
+		.gpio       = GPIO15_A910_FLIP_LID,
+		.active_low = 0,
+		.desc       = "A910 flip lid",
+		.type       = EV_SW,
+		.wakeup     = 1,
+	},
+};
+
+static struct gpio_keys_platform_data a910_gpio_keys_platform_data = {
+	.buttons  = a910_buttons,
+	.nbuttons = ARRAY_SIZE(a910_buttons),
+};
+
+static struct platform_device a910_gpio_keys = {
+	.name = "gpio-keys",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &a910_gpio_keys_platform_data,
+	},
+};
+
+static struct platform_device *a910_devices[] __initdata = {
+	&a910_gpio_keys,
+};
+
 static void __init a910_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config));
@@ -754,7 +880,8 @@
 
 	pxa_set_keypad_info(&a910_keypad_platform_data);
 
-	platform_add_devices(devices, ARRAY_SIZE(devices));
+	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
+	platform_add_devices(ARRAY_AND_SIZE(a910_devices));
 }
 
 MACHINE_START(EZX_A910, "Motorola EZX A910")
@@ -769,10 +896,39 @@
 #endif
 
 #ifdef CONFIG_MACH_EZX_E6
+/* gpio_keys */
+static struct gpio_keys_button e6_buttons[] = {
+	[0] = {
+		.code       = KEY_SCREENLOCK,
+		.gpio       = GPIO15_E6_LOCK_SWITCH,
+		.active_low = 0,
+		.desc       = "E6 lock switch",
+		.type       = EV_KEY,
+		.wakeup     = 1,
+	},
+};
+
+static struct gpio_keys_platform_data e6_gpio_keys_platform_data = {
+	.buttons  = e6_buttons,
+	.nbuttons = ARRAY_SIZE(e6_buttons),
+};
+
+static struct platform_device e6_gpio_keys = {
+	.name = "gpio-keys",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &e6_gpio_keys_platform_data,
+	},
+};
+
 static struct i2c_board_info __initdata e6_i2c_board_info[] = {
 	{ I2C_BOARD_INFO("tea5767", 0x81) },
 };
 
+static struct platform_device *e6_devices[] __initdata = {
+	&e6_gpio_keys,
+};
+
 static void __init e6_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config));
@@ -786,7 +942,8 @@
 
 	pxa_set_keypad_info(&e6_keypad_platform_data);
 
-	platform_add_devices(devices, ARRAY_SIZE(devices));
+	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
+	platform_add_devices(ARRAY_AND_SIZE(e6_devices));
 }
 
 MACHINE_START(EZX_E6, "Motorola EZX E6")
@@ -805,6 +962,9 @@
 	{ I2C_BOARD_INFO("tea5767", 0x81) },
 };
 
+static struct platform_device *e2_devices[] __initdata = {
+};
+
 static void __init e2_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config));
@@ -818,7 +978,8 @@
 
 	pxa_set_keypad_info(&e2_keypad_platform_data);
 
-	platform_add_devices(devices, ARRAY_SIZE(devices));
+	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
+	platform_add_devices(ARRAY_AND_SIZE(e2_devices));
 }
 
 MACHINE_START(EZX_E2, "Motorola EZX E2")
diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c
new file mode 100644
index 0000000..7fff467
--- /dev/null
+++ b/arch/arm/mach-pxa/hx4700.c
@@ -0,0 +1,851 @@
+/*
+ * Support for HP iPAQ hx4700 PDAs.
+ *
+ * Copyright (c) 2008-2009 Philipp Zabel
+ *
+ * Based on code:
+ *    Copyright (c) 2004 Hewlett-Packard Company.
+ *    Copyright (c) 2005 SDG Systems, LLC
+ *    Copyright (c) 2006 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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/lcd.h>
+#include <linux/mfd/htc-egpio.h>
+#include <linux/mfd/asic3.h>
+#include <linux/mtd/physmap.h>
+#include <linux/pda_power.h>
+#include <linux/pwm_backlight.h>
+#include <linux/regulator/bq24022.h>
+#include <linux/regulator/machine.h>
+#include <linux/spi/ads7846.h>
+#include <linux/spi/spi.h>
+#include <linux/usb/gpio_vbus.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/pxa27x.h>
+#include <mach/hx4700.h>
+#include <plat/i2c.h>
+#include <mach/irda.h>
+#include <mach/pxa2xx_spi.h>
+
+#include <video/w100fb.h>
+
+#include "devices.h"
+#include "generic.h"
+
+/* Physical address space information */
+
+#define ATI_W3220_PHYS  PXA_CS2_PHYS /* ATI Imageon 3220 Graphics */
+#define ASIC3_PHYS      PXA_CS3_PHYS
+#define ASIC3_SD_PHYS   (PXA_CS3_PHYS + 0x02000000)
+
+static unsigned long hx4700_pin_config[] __initdata = {
+
+	/* SDRAM and Static Memory I/O Signals */
+	GPIO20_nSDCS_2,
+	GPIO21_nSDCS_3,
+	GPIO15_nCS_1,
+	GPIO78_nCS_2,   /* W3220 */
+	GPIO79_nCS_3,   /* ASIC3 */
+	GPIO80_nCS_4,
+	GPIO33_nCS_5,	/* EGPIO, WLAN */
+
+	/* PC CARD */
+	GPIO48_nPOE,
+	GPIO49_nPWE,
+	GPIO50_nPIOR,
+	GPIO51_nPIOW,
+	GPIO54_nPCE_2,
+	GPIO55_nPREG,
+	GPIO56_nPWAIT,
+	GPIO57_nIOIS16,
+	GPIO85_nPCE_1,
+	GPIO104_PSKTSEL,
+
+	/* I2C */
+	GPIO117_I2C_SCL,
+	GPIO118_I2C_SDA,
+
+	/* FFUART (RS-232) */
+	GPIO34_FFUART_RXD,
+	GPIO35_FFUART_CTS,
+	GPIO36_FFUART_DCD,
+	GPIO37_FFUART_DSR,
+	GPIO38_FFUART_RI,
+	GPIO39_FFUART_TXD,
+	GPIO40_FFUART_DTR,
+	GPIO41_FFUART_RTS,
+
+	/* BTUART */
+	GPIO42_BTUART_RXD,
+	GPIO43_BTUART_TXD,
+	GPIO44_BTUART_CTS,
+	GPIO45_BTUART_RTS,
+
+	/* PWM 1 (Backlight) */
+	GPIO17_PWM1_OUT,
+
+	/* I2S */
+	GPIO28_I2S_BITCLK_OUT,
+	GPIO29_I2S_SDATA_IN,
+	GPIO30_I2S_SDATA_OUT,
+	GPIO31_I2S_SYNC,
+	GPIO113_I2S_SYSCLK,
+
+	/* SSP 1 (NavPoint) */
+	GPIO23_SSP1_SCLK,
+	GPIO24_SSP1_SFRM,
+	GPIO25_SSP1_TXD,
+	GPIO26_SSP1_RXD,
+
+	/* SSP 2 (TSC2046) */
+	GPIO19_SSP2_SCLK,
+	GPIO86_SSP2_RXD,
+	GPIO87_SSP2_TXD,
+	GPIO88_GPIO,
+
+	/* HX4700 specific input GPIOs */
+	GPIO12_GPIO,	/* ASIC3_IRQ */
+	GPIO13_GPIO,	/* W3220_IRQ */
+	GPIO14_GPIO,	/* nWLAN_IRQ */
+
+	GPIO10_GPIO,	/* GSM_IRQ */
+	GPIO13_GPIO,	/* CPLD_IRQ */
+	GPIO107_GPIO,	/* DS1WM_IRQ */
+	GPIO108_GPIO,	/* GSM_READY */
+	GPIO58_GPIO,	/* TSC2046_nPENIRQ */
+	GPIO66_GPIO,	/* nSDIO_IRQ */
+};
+
+#define HX4700_GPIO_IN(num, _desc) \
+	{ .gpio = (num), .dir = 0, .desc = (_desc) }
+#define HX4700_GPIO_OUT(num, _init, _desc) \
+	{ .gpio = (num), .dir = 1, .init = (_init), .desc = (_desc) }
+struct gpio_ress {
+	unsigned gpio : 8;
+	unsigned dir : 1;
+	unsigned init : 1;
+	char *desc;
+};
+
+static int hx4700_gpio_request(struct gpio_ress *gpios, int size)
+{
+	int i, rc = 0;
+	int gpio;
+	int dir;
+
+	for (i = 0; (!rc) && (i < size); i++) {
+		gpio = gpios[i].gpio;
+		dir = gpios[i].dir;
+		rc = gpio_request(gpio, gpios[i].desc);
+		if (rc) {
+			pr_err("Error requesting GPIO %d(%s) : %d\n",
+			       gpio, gpios[i].desc, rc);
+			continue;
+		}
+		if (dir)
+			gpio_direction_output(gpio, gpios[i].init);
+		else
+			gpio_direction_input(gpio);
+	}
+	while ((rc) && (--i >= 0))
+		gpio_free(gpios[i].gpio);
+	return rc;
+}
+
+/*
+ * IRDA
+ */
+
+static void irda_transceiver_mode(struct device *dev, int mode)
+{
+	gpio_set_value(GPIO105_HX4700_nIR_ON, mode & IR_OFF);
+}
+
+static struct pxaficp_platform_data ficp_info = {
+	.transceiver_cap  = IR_SIRMODE | IR_OFF,
+	.transceiver_mode = irda_transceiver_mode,
+};
+
+/*
+ * GPIO Keys
+ */
+
+#define INIT_KEY(_code, _gpio, _active_low, _desc)	\
+	{						\
+		.code       = KEY_##_code,		\
+		.gpio       = _gpio,			\
+		.active_low = _active_low,		\
+		.desc       = _desc,			\
+		.type       = EV_KEY,			\
+		.wakeup     = 1,			\
+	}
+
+static struct gpio_keys_button gpio_keys_buttons[] = {
+	INIT_KEY(POWER,       GPIO0_HX4700_nKEY_POWER,   1, "Power button"),
+	INIT_KEY(MAIL,        GPIO94_HX4700_KEY_MAIL,    0, "Mail button"),
+	INIT_KEY(ADDRESSBOOK, GPIO99_HX4700_KEY_CONTACTS,0, "Contacts button"),
+	INIT_KEY(RECORD,      GPIOD6_nKEY_RECORD,        1, "Record button"),
+	INIT_KEY(CALENDAR,    GPIOD1_nKEY_CALENDAR,      1, "Calendar button"),
+	INIT_KEY(HOMEPAGE,    GPIOD3_nKEY_HOME,          1, "Home button"),
+};
+
+static struct gpio_keys_platform_data gpio_keys_data = {
+	.buttons = gpio_keys_buttons,
+	.nbuttons = ARRAY_SIZE(gpio_keys_buttons),
+};
+
+static struct platform_device gpio_keys = {
+	.name = "gpio-keys",
+	.dev  = {
+		.platform_data = &gpio_keys_data,
+	},
+	.id   = -1,
+};
+
+/*
+ * ASIC3
+ */
+
+static u16 asic3_gpio_config[] = {
+	/* ASIC3 GPIO banks A and B along with some of C and D
+	   implement the buffering for the CF slot. */
+	ASIC3_CONFIG_GPIO(0, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(1, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(2, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(3, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(4, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(5, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(6, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(7, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(8, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(9, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(10, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(11, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(12, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(13, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(14, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(15, 1, 1, 0),
+
+	ASIC3_CONFIG_GPIO(16, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(17, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(18, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(19, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(20, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(21, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(22, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(23, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(24, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(25, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(26, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(27, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(28, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(29, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(30, 1, 1, 0),
+	ASIC3_CONFIG_GPIO(31, 1, 1, 0),
+
+	/* GPIOC - CF, LEDs, SD */
+	ASIC3_GPIOC0_LED0,		/* red */
+	ASIC3_GPIOC1_LED1,		/* green */
+	ASIC3_GPIOC2_LED2,		/* blue */
+	ASIC3_GPIOC4_CF_nCD,
+	ASIC3_GPIOC5_nCIOW,
+	ASIC3_GPIOC6_nCIOR,
+	ASIC3_GPIOC7_nPCE_1,
+	ASIC3_GPIOC8_nPCE_2,
+	ASIC3_GPIOC9_nPOE,
+	ASIC3_GPIOC10_nPWE,
+	ASIC3_GPIOC11_PSKTSEL,
+	ASIC3_GPIOC12_nPREG,
+	ASIC3_GPIOC13_nPWAIT,
+	ASIC3_GPIOC14_nPIOIS16,
+	ASIC3_GPIOC15_nPIOR,
+
+	/* GPIOD: input GPIOs, CF */
+	ASIC3_GPIOD11_nCIOIS16,
+	ASIC3_GPIOD12_nCWAIT,
+	ASIC3_GPIOD15_nPIOW,
+};
+
+static struct resource asic3_resources[] = {
+	/* GPIO part */
+	[0] = {
+		.start	= ASIC3_PHYS,
+		.end	= ASIC3_PHYS + ASIC3_MAP_SIZE_16BIT - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gpio_to_irq(GPIO12_HX4700_ASIC3_IRQ),
+		.end	= gpio_to_irq(GPIO12_HX4700_ASIC3_IRQ),
+		.flags	= IORESOURCE_IRQ,
+	},
+	/* SD part */
+	[2] = {
+		.start	= ASIC3_SD_PHYS,
+		.end	= ASIC3_SD_PHYS + ASIC3_MAP_SIZE_16BIT - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[3] = {
+		.start	= gpio_to_irq(GPIO66_HX4700_ASIC3_nSDIO_IRQ),
+		.end	= gpio_to_irq(GPIO66_HX4700_ASIC3_nSDIO_IRQ),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct asic3_platform_data asic3_platform_data = {
+	.gpio_config     = asic3_gpio_config,
+	.gpio_config_num = ARRAY_SIZE(asic3_gpio_config),
+	.irq_base        = IRQ_BOARD_START,
+	.gpio_base       = HX4700_ASIC3_GPIO_BASE,
+};
+
+static struct platform_device asic3 = {
+	.name          = "asic3",
+	.id            = -1,
+	.resource      = asic3_resources,
+	.num_resources = ARRAY_SIZE(asic3_resources),
+	.dev = {
+		.platform_data = &asic3_platform_data,
+	},
+};
+
+/*
+ * EGPIO
+ */
+
+static struct resource egpio_resources[] = {
+	[0] = {
+		.start = PXA_CS5_PHYS,
+		.end   = PXA_CS5_PHYS + 0x4 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static struct htc_egpio_chip egpio_chips[] = {
+	[0] = {
+		.reg_start = 0,
+		.gpio_base = HX4700_EGPIO_BASE,
+		.num_gpios = 8,
+		.direction = HTC_EGPIO_OUTPUT,
+	},
+};
+
+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 egpio = {
+	.name          = "htc-egpio",
+	.id            = -1,
+	.resource      = egpio_resources,
+	.num_resources = ARRAY_SIZE(egpio_resources),
+	.dev = {
+		.platform_data = &egpio_info,
+	},
+};
+
+/*
+ * LCD - Sony display connected to ATI Imageon w3220
+ */
+
+static int lcd_power;
+
+static void sony_lcd_init(void)
+{
+	gpio_set_value(GPIO84_HX4700_LCD_SQN, 1);
+	gpio_set_value(GPIO110_HX4700_LCD_LVDD_3V3_ON, 0);
+	gpio_set_value(GPIO111_HX4700_LCD_AVDD_3V3_ON, 0);
+	gpio_set_value(GPIO70_HX4700_LCD_SLIN1, 0);
+	gpio_set_value(GPIO62_HX4700_LCD_nRESET, 0);
+	mdelay(10);
+	gpio_set_value(GPIO59_HX4700_LCD_PC1, 0);
+	gpio_set_value(GPIO110_HX4700_LCD_LVDD_3V3_ON, 0);
+	mdelay(20);
+
+	gpio_set_value(GPIO110_HX4700_LCD_LVDD_3V3_ON, 1);
+	mdelay(5);
+	gpio_set_value(GPIO111_HX4700_LCD_AVDD_3V3_ON, 1);
+
+	/* FIXME: init w3220 registers here */
+
+	mdelay(5);
+	gpio_set_value(GPIO70_HX4700_LCD_SLIN1, 1);
+	mdelay(10);
+	gpio_set_value(GPIO62_HX4700_LCD_nRESET, 1);
+	mdelay(10);
+	gpio_set_value(GPIO59_HX4700_LCD_PC1, 1);
+	mdelay(10);
+	gpio_set_value(GPIO112_HX4700_LCD_N2V7_7V3_ON, 1);
+}
+
+static void sony_lcd_off(void)
+{
+	gpio_set_value(GPIO59_HX4700_LCD_PC1, 0);
+	gpio_set_value(GPIO62_HX4700_LCD_nRESET, 0);
+	mdelay(10);
+	gpio_set_value(GPIO112_HX4700_LCD_N2V7_7V3_ON, 0);
+	mdelay(10);
+	gpio_set_value(GPIO111_HX4700_LCD_AVDD_3V3_ON, 0);
+	mdelay(10);
+	gpio_set_value(GPIO110_HX4700_LCD_LVDD_3V3_ON, 0);
+}
+
+static int hx4700_lcd_set_power(struct lcd_device *ldev, int level)
+{
+	switch (level) {
+	case FB_BLANK_UNBLANK:
+		sony_lcd_init();
+		break;
+	case FB_BLANK_NORMAL:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_POWERDOWN:
+		sony_lcd_off();
+		break;
+	}
+	lcd_power = level;
+	return 0;
+}
+
+static int hx4700_lcd_get_power(struct lcd_device *lm)
+{
+	return lcd_power;
+}
+
+static struct lcd_ops hx4700_lcd_ops = {
+	.get_power = hx4700_lcd_get_power,
+	.set_power = hx4700_lcd_set_power,
+};
+
+static struct lcd_device *hx4700_lcd_device;
+
+#ifdef CONFIG_PM
+static void w3220_lcd_suspend(struct w100fb_par *wfb)
+{
+	sony_lcd_off();
+}
+
+static void w3220_lcd_resume(struct w100fb_par *wfb)
+{
+	sony_lcd_init();
+}
+#else
+#define w3220_lcd_resume	NULL
+#define w3220_lcd_suspend	NULL
+#endif
+
+static struct w100_tg_info w3220_tg_info = {
+	.suspend	= w3220_lcd_suspend,
+	.resume		= w3220_lcd_resume,
+};
+
+/*  				 W3220_VGA		QVGA */
+static struct w100_gen_regs w3220_regs = {
+	.lcd_format =        0x00000003,
+	.lcdd_cntl1 =        0x00000000,
+	.lcdd_cntl2 =        0x0003ffff,
+	.genlcd_cntl1 =      0x00abf003,	/* 0x00fff003 */
+	.genlcd_cntl2 =      0x00000003,
+	.genlcd_cntl3 =      0x000102aa,
+};
+
+static struct w100_mode w3220_modes[] = {
+{
+	.xres 		= 480,
+	.yres 		= 640,
+	.left_margin 	= 15,
+	.right_margin 	= 16,
+	.upper_margin 	= 8,
+	.lower_margin 	= 7,
+	.crtc_ss	= 0x00000000,
+	.crtc_ls	= 0xa1ff01f9,	/* 0x21ff01f9 */
+	.crtc_gs	= 0xc0000000,	/* 0x40000000 */
+	.crtc_vpos_gs	= 0x0000028f,
+	.crtc_ps1_active = 0x00000000,	/* 0x41060010 */
+	.crtc_rev	= 0,
+	.crtc_dclk	= 0x80000000,
+	.crtc_gclk	= 0x040a0104,
+	.crtc_goe	= 0,
+	.pll_freq 	= 95,
+	.pixclk_divider = 4,
+	.pixclk_divider_rotated = 4,
+	.pixclk_src     = CLK_SRC_PLL,
+	.sysclk_divider = 0,
+	.sysclk_src     = CLK_SRC_PLL,
+},
+{
+	.xres 		= 240,
+	.yres 		= 320,
+	.left_margin 	= 9,
+	.right_margin 	= 8,
+	.upper_margin 	= 5,
+	.lower_margin 	= 4,
+	.crtc_ss	= 0x80150014,
+	.crtc_ls        = 0xa0fb00f7,
+	.crtc_gs	= 0xc0080007,
+	.crtc_vpos_gs	= 0x00080007,
+	.crtc_rev	= 0x0000000a,
+	.crtc_dclk	= 0x81700030,
+	.crtc_gclk	= 0x8015010f,
+	.crtc_goe	= 0x00000000,
+	.pll_freq 	= 95,
+	.pixclk_divider = 4,
+	.pixclk_divider_rotated = 4,
+	.pixclk_src     = CLK_SRC_PLL,
+	.sysclk_divider = 0,
+	.sysclk_src     = CLK_SRC_PLL,
+},
+};
+
+struct w100_mem_info w3220_mem_info = {
+	.ext_cntl        = 0x09640011,
+	.sdram_mode_reg  = 0x00600021,
+	.ext_timing_cntl = 0x1a001545,	/* 0x15001545 */
+	.io_cntl         = 0x7ddd7333,
+	.size            = 0x1fffff,
+};
+
+struct w100_bm_mem_info w3220_bm_mem_info = {
+	.ext_mem_bw = 0x50413e01,
+	.offset = 0,
+	.ext_timing_ctl = 0x00043f7f,
+	.ext_cntl = 0x00000010,
+	.mode_reg = 0x00250000,
+	.io_cntl = 0x0fff0000,
+	.config = 0x08301480,
+};
+
+static struct w100_gpio_regs w3220_gpio_info = {
+	.init_data1 = 0xdfe00100,	/* GPIO_DATA */
+	.gpio_dir1  = 0xffff0000,	/* GPIO_CNTL1 */
+	.gpio_oe1   = 0x00000000,	/* GPIO_CNTL2 */
+	.init_data2 = 0x00000000,	/* GPIO_DATA2 */
+	.gpio_dir2  = 0x00000000,	/* GPIO_CNTL3 */
+	.gpio_oe2   = 0x00000000,	/* GPIO_CNTL4 */
+};
+
+static struct w100fb_mach_info w3220_info = {
+	.tg        = &w3220_tg_info,
+	.mem       = &w3220_mem_info,
+	.bm_mem    = &w3220_bm_mem_info,
+	.gpio      = &w3220_gpio_info,
+	.regs      = &w3220_regs,
+	.modelist  = w3220_modes,
+	.num_modes = 2,
+	.xtal_freq = 16000000,
+};
+
+static struct resource w3220_resources[] = {
+	[0] = {
+		.start	= ATI_W3220_PHYS,
+		.end	= ATI_W3220_PHYS + 0x00ffffff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device w3220 = {
+	.name	= "w100fb",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &w3220_info,
+	},
+	.num_resources = ARRAY_SIZE(w3220_resources),
+	.resource      = w3220_resources,
+};
+
+/*
+ * Backlight
+ */
+
+static struct platform_pwm_backlight_data backlight_data = {
+	.pwm_id         = 1,
+	.max_brightness = 200,
+	.dft_brightness = 100,
+	.pwm_period_ns  = 30923,
+};
+
+static struct platform_device backlight = {
+	.name = "pwm-backlight",
+	.id   = -1,
+	.dev  = {
+		.parent        = &pxa27x_device_pwm1.dev,
+		.platform_data = &backlight_data,
+	},
+};
+
+/*
+ * USB "Transceiver"
+ */
+
+static struct gpio_vbus_mach_info gpio_vbus_info = {
+	.gpio_pullup        = GPIO76_HX4700_USBC_PUEN,
+	.gpio_vbus          = GPIOD14_nUSBC_DETECT,
+	.gpio_vbus_inverted = 1,
+};
+
+static struct platform_device gpio_vbus = {
+	.name          = "gpio-vbus",
+	.id            = -1,
+	.dev = {
+		.platform_data = &gpio_vbus_info,
+	},
+};
+
+/*
+ * Touchscreen - TSC2046 connected to SSP2
+ */
+
+static const struct ads7846_platform_data tsc2046_info = {
+	.model            = 7846,
+	.vref_delay_usecs = 100,
+	.pressure_max     = 512,
+	.debounce_max     = 10,
+	.debounce_tol     = 3,
+	.debounce_rep     = 1,
+	.gpio_pendown     = GPIO58_HX4700_TSC2046_nPENIRQ,
+};
+
+static struct pxa2xx_spi_chip tsc2046_chip = {
+	.tx_threshold = 1,
+	.rx_threshold = 2,
+	.timeout      = 64,
+	.gpio_cs      = GPIO88_HX4700_TSC2046_CS,
+};
+
+static struct spi_board_info tsc2046_board_info[] __initdata = {
+	{
+		.modalias        = "ads7846",
+		.bus_num         = 2,
+		.max_speed_hz    = 2600000, /* 100 kHz sample rate */
+		.irq             = gpio_to_irq(GPIO58_HX4700_TSC2046_nPENIRQ),
+		.platform_data   = &tsc2046_info,
+		.controller_data = &tsc2046_chip,
+	},
+};
+
+static struct pxa2xx_spi_master pxa_ssp2_master_info = {
+	.num_chipselect = 1,
+	.clock_enable   = CKEN_SSP2,
+	.enable_dma     = 1,
+};
+
+/*
+ * External power
+ */
+
+static int power_supply_init(struct device *dev)
+{
+	return gpio_request(GPIOD9_nAC_IN, "AC charger detect");
+}
+
+static int hx4700_is_ac_online(void)
+{
+	return !gpio_get_value(GPIOD9_nAC_IN);
+}
+
+static void power_supply_exit(struct device *dev)
+{
+	gpio_free(GPIOD9_nAC_IN);
+}
+
+static char *hx4700_supplicants[] = {
+	"ds2760-battery.0", "backup-battery"
+};
+
+static struct pda_power_pdata power_supply_info = {
+	.init            = power_supply_init,
+	.is_ac_online    = hx4700_is_ac_online,
+	.exit            = power_supply_exit,
+	.supplied_to     = hx4700_supplicants,
+	.num_supplicants = ARRAY_SIZE(hx4700_supplicants),
+};
+
+static struct resource power_supply_resources[] = {
+	[0] = {
+		.name  = "ac",
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE |
+		         IORESOURCE_IRQ_LOWEDGE,
+		.start = gpio_to_irq(GPIOD9_nAC_IN),
+		.end   = gpio_to_irq(GPIOD9_nAC_IN),
+	},
+	[1] = {
+		.name  = "usb",
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE |
+		         IORESOURCE_IRQ_LOWEDGE,
+		.start = gpio_to_irq(GPIOD14_nUSBC_DETECT),
+		.end   = gpio_to_irq(GPIOD14_nUSBC_DETECT),
+	},
+};
+
+static struct platform_device power_supply = {
+	.name = "pda-power",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &power_supply_info,
+	},
+	.resource      = power_supply_resources,
+	.num_resources = ARRAY_SIZE(power_supply_resources),
+};
+
+/*
+ * Battery charger
+ */
+
+static struct regulator_consumer_supply bq24022_consumers[] = {
+	{
+		.dev = &gpio_vbus.dev,
+		.supply = "vbus_draw",
+	},
+	{
+		.dev = &power_supply.dev,
+		.supply = "ac_draw",
+	},
+};
+
+static struct regulator_init_data bq24022_init_data = {
+	.constraints = {
+		.max_uA         = 500000,
+		.valid_ops_mask = REGULATOR_CHANGE_CURRENT,
+	},
+	.num_consumer_supplies  = ARRAY_SIZE(bq24022_consumers),
+	.consumer_supplies      = bq24022_consumers,
+};
+
+static struct bq24022_mach_info bq24022_info = {
+	.gpio_nce   = GPIO72_HX4700_BQ24022_nCHARGE_EN,
+	.gpio_iset2 = GPIO96_HX4700_BQ24022_ISET2,
+	.init_data  = &bq24022_init_data,
+};
+
+static struct platform_device bq24022 = {
+	.name = "bq24022",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &bq24022_info,
+	},
+};
+
+/*
+ * StrataFlash
+ */
+
+static void hx4700_set_vpp(struct map_info *map, int vpp)
+{
+	gpio_set_value(GPIO91_HX4700_FLASH_VPEN, vpp);
+}
+
+static struct resource strataflash_resource = {
+	.start = PXA_CS0_PHYS,
+	.end   = PXA_CS0_PHYS + SZ_128M - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct physmap_flash_data strataflash_data = {
+	.width = 4,
+	.set_vpp = hx4700_set_vpp,
+};
+
+static struct platform_device strataflash = {
+	.name          = "physmap-flash",
+	.id            = -1,
+	.resource      = &strataflash_resource,
+	.num_resources = 1,
+	.dev = {
+		.platform_data = &strataflash_data,
+	},
+};
+
+/*
+ * PCMCIA
+ */
+
+static struct platform_device pcmcia = {
+	.name = "hx4700-pcmcia",
+	.dev  = {
+		.parent = &asic3.dev,
+	},
+};
+
+/*
+ * Platform devices
+ */
+
+static struct platform_device *devices[] __initdata = {
+	&asic3,
+	&gpio_keys,
+	&backlight,
+	&w3220,
+	&egpio,
+	&bq24022,
+	&gpio_vbus,
+	&power_supply,
+	&strataflash,
+	&pcmcia,
+};
+
+static struct gpio_ress global_gpios[] = {
+	HX4700_GPIO_IN(GPIO12_HX4700_ASIC3_IRQ, "ASIC3_IRQ"),
+	HX4700_GPIO_IN(GPIO13_HX4700_W3220_IRQ, "W3220_IRQ"),
+	HX4700_GPIO_IN(GPIO14_HX4700_nWLAN_IRQ, "WLAN_IRQ"),
+	HX4700_GPIO_OUT(GPIO59_HX4700_LCD_PC1,          1, "LCD_PC1"),
+	HX4700_GPIO_OUT(GPIO62_HX4700_LCD_nRESET,       1, "LCD_RESET"),
+	HX4700_GPIO_OUT(GPIO70_HX4700_LCD_SLIN1,        1, "LCD_SLIN1"),
+	HX4700_GPIO_OUT(GPIO84_HX4700_LCD_SQN,          1, "LCD_SQN"),
+	HX4700_GPIO_OUT(GPIO110_HX4700_LCD_LVDD_3V3_ON, 1, "LCD_LVDD"),
+	HX4700_GPIO_OUT(GPIO111_HX4700_LCD_AVDD_3V3_ON, 1, "LCD_AVDD"),
+	HX4700_GPIO_OUT(GPIO32_HX4700_RS232_ON,         1, "RS232_ON"),
+	HX4700_GPIO_OUT(GPIO71_HX4700_ASIC3_nRESET,     1, "ASIC3_nRESET"),
+	HX4700_GPIO_OUT(GPIO82_HX4700_EUART_RESET,      1, "EUART_RESET"),
+	HX4700_GPIO_OUT(GPIO105_HX4700_nIR_ON,          1, "nIR_EN"),
+};
+
+static void __init hx4700_init(void)
+{
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(hx4700_pin_config));
+	hx4700_gpio_request(ARRAY_AND_SIZE(global_gpios));
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	pxa_set_ficp_info(&ficp_info);
+	pxa27x_set_i2c_power_info(NULL);
+	pxa_set_i2c_info(NULL);
+	pxa2xx_set_spi_info(2, &pxa_ssp2_master_info);
+	spi_register_board_info(ARRAY_AND_SIZE(tsc2046_board_info));
+
+	hx4700_lcd_device = lcd_device_register("w100fb", NULL,
+					(void *)&w3220_info, &hx4700_lcd_ops);
+
+	gpio_set_value(GPIO71_HX4700_ASIC3_nRESET, 0);
+	mdelay(10);
+	gpio_set_value(GPIO71_HX4700_ASIC3_nRESET, 1);
+	mdelay(10);
+}
+
+MACHINE_START(H4700, "HP iPAQ HX4700")
+	.phys_io      = 0x40000000,
+	.io_pg_offst  = (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.boot_params  = 0xa0000100,
+	.map_io       = pxa_map_io,
+	.init_irq     = pxa27x_init_irq,
+	.init_machine = hx4700_init,
+	.timer        = &pxa_timer,
+MACHINE_END
diff --git a/arch/arm/mach-pxa/imote2.c b/arch/arm/mach-pxa/imote2.c
index 2121309..be7be72 100644
--- a/arch/arm/mach-pxa/imote2.c
+++ b/arch/arm/mach-pxa/imote2.c
@@ -22,6 +22,7 @@
 #include <linux/spi/spi.h>
 #include <linux/i2c.h>
 #include <linux/mfd/da903x.h>
+#include <linux/sht15.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -29,7 +30,7 @@
 #include <asm/mach/flash.h>
 
 #include <mach/pxa27x.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/udc.h>
 #include <mach/mmc.h>
 #include <mach/pxa2xx_spi.h>
@@ -102,6 +103,10 @@
 	GPIO96_GPIO,	/* accelerometer interrupt */
 	GPIO99_GPIO,	/* ADC interrupt */
 
+	/* SHT15 */
+	GPIO100_GPIO,
+	GPIO98_GPIO,
+
 	/* Connector pins specified as gpios */
 	GPIO94_GPIO, /* large basic connector pin 14 */
 	GPIO10_GPIO, /* large basic connector pin 23 */
@@ -112,6 +117,26 @@
 	GPIO105_GPIO, /* blue led */
 };
 
+static struct sht15_platform_data platform_data_sht15 = {
+	.gpio_data =  100,
+	.gpio_sck  =  98,
+};
+
+static struct platform_device sht15 = {
+	.name = "sht15",
+	.id = -1,
+	.dev = {
+		.platform_data = &platform_data_sht15,
+	},
+};
+
+static struct regulator_consumer_supply imote2_sensor_3_con[] = {
+	{
+		.dev = &sht15.dev,
+		.supply = "vcc",
+	},
+};
+
 static struct gpio_led imote2_led_pins[] = {
 	{
 		.name       =  "imote2:red",
@@ -257,6 +282,8 @@
 			.min_uV = 2800000,
 			.max_uV = 3000000,
 		},
+		.num_consumer_supplies = ARRAY_SIZE(imote2_sensor_3_con),
+		.consumer_supplies = imote2_sensor_3_con,
 	},
 	[vcc_pxa_pll] = { /* 1.17V - 1.43V, default 1.3V*/
 		.constraints = {
@@ -432,6 +459,9 @@
 		.type = "tmp175",
 		.addr = 0x4A,
 		.irq = IRQ_GPIO(96),
+	}, { /* IMB400 Multimedia board */
+		.type = "wm8940",
+		.addr = 0x1A,
 	},
 };
 
@@ -456,25 +486,12 @@
 	.num_chipselect = 1,
 };
 
-/* Patch posted by Eric Miao <eric.miao@marvell.com> will remove
- * the need for these functions.
- */
-static void spi1control(u32 command)
-{
-	gpio_set_value(24, command & PXA2XX_CS_ASSERT ? 0 : 1);
-};
-
-static void spi3control(u32 command)
-{
-	gpio_set_value(39, command & PXA2XX_CS_ASSERT ? 0 : 1);
-};
-
 static struct pxa2xx_spi_chip staccel_chip_info = {
 	.tx_threshold = 8,
 	.rx_threshold = 8,
 	.dma_burst_size = 8,
 	.timeout = 235,
-	.cs_control = spi1control,
+	.gpio_cs = 24,
 };
 
 static struct pxa2xx_spi_chip cc2420_info = {
@@ -482,7 +499,7 @@
 	.rx_threshold = 8,
 	.dma_burst_size = 8,
 	.timeout = 235,
-	.cs_control = spi3control,
+	.gpio_cs = 39,
 };
 
 static struct spi_board_info spi_board_info[] __initdata = {
@@ -521,6 +538,7 @@
 static struct platform_device *imote2_devices[] = {
 	&imote2_flash_device,
 	&imote2_leds,
+	&sht15,
 };
 
 static struct i2c_pxa_platform_data i2c_pwr_pdata = {
@@ -538,8 +556,6 @@
 	/* SPI chip select directions - all other directions should
 	 * be handled by drivers.*/
 	gpio_direction_output(37, 0);
-	gpio_direction_output(24, 0);
-	gpio_direction_output(39, 0);
 
 	platform_add_devices(imote2_devices, ARRAY_SIZE(imote2_devices));
 
diff --git a/arch/arm/mach-pxa/include/mach/hx4700.h b/arch/arm/mach-pxa/include/mach/hx4700.h
new file mode 100644
index 0000000..9eaeed1
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/hx4700.h
@@ -0,0 +1,131 @@
+/*
+ * GPIO and IRQ definitions for HP iPAQ hx4700
+ *
+ * Copyright (c) 2008 Philipp Zabel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _HX4700_H_
+#define _HX4700_H_
+
+#include <linux/gpio.h>
+#include <linux/mfd/asic3.h>
+
+#define HX4700_ASIC3_GPIO_BASE	NR_BUILTIN_GPIO
+#define HX4700_EGPIO_BASE	(HX4700_ASIC3_GPIO_BASE + ASIC3_NUM_GPIOS)
+
+/*
+ * PXA GPIOs
+ */
+
+#define GPIO0_HX4700_nKEY_POWER			0
+#define GPIO12_HX4700_ASIC3_IRQ			12
+#define GPIO13_HX4700_W3220_IRQ			13
+#define GPIO14_HX4700_nWLAN_IRQ			14
+#define GPIO18_HX4700_RDY			18
+#define GPIO22_HX4700_LCD_RL			22
+#define GPIO27_HX4700_CODEC_ON			27
+#define GPIO32_HX4700_RS232_ON			32
+#define GPIO52_HX4700_CPU_nBATT_FAULT		52
+#define GPIO58_HX4700_TSC2046_nPENIRQ		58
+#define GPIO59_HX4700_LCD_PC1			59
+#define GPIO60_HX4700_CF_RNB			60
+#define GPIO61_HX4700_W3220_nRESET		61
+#define GPIO62_HX4700_LCD_nRESET		62
+#define GPIO63_HX4700_CPU_SS_nRESET		63
+#define GPIO65_HX4700_TSC2046_PEN_PU		65
+#define GPIO66_HX4700_ASIC3_nSDIO_IRQ		66
+#define GPIO67_HX4700_EUART_PS			67
+#define GPIO70_HX4700_LCD_SLIN1			70
+#define GPIO71_HX4700_ASIC3_nRESET		71
+#define GPIO72_HX4700_BQ24022_nCHARGE_EN	72
+#define GPIO73_HX4700_LCD_UD_1			73
+#define GPIO75_HX4700_EARPHONE_nDET		75
+#define GPIO76_HX4700_USBC_PUEN			76
+#define GPIO81_HX4700_CPU_GP_nRESET		81
+#define GPIO82_HX4700_EUART_RESET		82
+#define GPIO83_HX4700_WLAN_nRESET		83
+#define GPIO84_HX4700_LCD_SQN			84
+#define GPIO85_HX4700_nPCE1			85
+#define GPIO88_HX4700_TSC2046_CS		88
+#define GPIO91_HX4700_FLASH_VPEN		91
+#define GPIO92_HX4700_HP_DRIVER			92
+#define GPIO93_HX4700_EUART_INT			93
+#define GPIO94_HX4700_KEY_MAIL			94
+#define GPIO95_HX4700_BATT_OFF			95
+#define GPIO96_HX4700_BQ24022_ISET2		96
+#define GPIO97_HX4700_nBL_DETECT		97
+#define GPIO99_HX4700_KEY_CONTACTS		99
+#define GPIO100_HX4700_AUTO_SENSE		100 /* BL auto brightness */
+#define GPIO102_HX4700_SYNAPTICS_POWER_ON	102
+#define GPIO103_HX4700_SYNAPTICS_INT		103
+#define GPIO105_HX4700_nIR_ON			105
+#define GPIO106_HX4700_CPU_BT_nRESET		106
+#define GPIO107_HX4700_SPK_nSD			107
+#define GPIO109_HX4700_CODEC_nPDN		109
+#define GPIO110_HX4700_LCD_LVDD_3V3_ON		110
+#define GPIO111_HX4700_LCD_AVDD_3V3_ON		111
+#define GPIO112_HX4700_LCD_N2V7_7V3_ON		112
+#define GPIO114_HX4700_CF_RESET			114
+#define GPIO116_HX4700_CPU_HW_nRESET		116
+
+/*
+ * ASIC3 GPIOs
+ */
+
+#define GPIOC_BASE		(HX4700_ASIC3_GPIO_BASE + 32)
+#define GPIOD_BASE		(HX4700_ASIC3_GPIO_BASE + 48)
+
+#define GPIOC0_LED_RED		(GPIOC_BASE + 0)
+#define GPIOC1_LED_GREEN	(GPIOC_BASE + 1)
+#define GPIOC2_LED_BLUE		(GPIOC_BASE + 2)
+#define GPIOC3_nSD_CS		(GPIOC_BASE + 3)
+#define GPIOC4_CF_nCD		(GPIOC_BASE + 4)	/* Input */
+#define GPIOC5_nCIOW		(GPIOC_BASE + 5)	/* Output, to CF */
+#define GPIOC6_nCIOR		(GPIOC_BASE + 6)	/* Output, to CF */
+#define GPIOC7_nPCE1		(GPIOC_BASE + 7)	/* Input, from CPU */
+#define GPIOC8_nPCE2		(GPIOC_BASE + 8)	/* Input, from CPU */
+#define GPIOC9_nPOE		(GPIOC_BASE + 9)	/* Input, from CPU */
+#define GPIOC10_CF_nPWE		(GPIOC_BASE + 10)	/* Input */
+#define GPIOC11_PSKTSEL		(GPIOC_BASE + 11)	/* Input, from CPU */
+#define GPIOC12_nPREG		(GPIOC_BASE + 12)	/* Input, from CPU */
+#define GPIOC13_nPWAIT		(GPIOC_BASE + 13)	/* Output, to CPU */
+#define GPIOC14_nPIOIS16	(GPIOC_BASE + 14)	/* Output, to CPU */
+#define GPIOC15_nPIOR		(GPIOC_BASE + 15)	/* Input, from CPU */
+
+#define GPIOD0_CPU_SS_INT	(GPIOD_BASE + 0)	/* Input */
+#define GPIOD1_nKEY_CALENDAR	(GPIOD_BASE + 1)
+#define GPIOD2_BLUETOOTH_WAKEUP	(GPIOD_BASE + 2)
+#define GPIOD3_nKEY_HOME	(GPIOD_BASE + 3)
+#define GPIOD4_CF_nCD		(GPIOD_BASE + 4)	/* Input, from CF */
+#define GPIOD5_nPIO		(GPIOD_BASE + 5)	/* Input */
+#define GPIOD6_nKEY_RECORD	(GPIOD_BASE + 6)
+#define GPIOD7_nSDIO_DETECT	(GPIOD_BASE + 7)
+#define GPIOD8_COM_DCD		(GPIOD_BASE + 8)	/* Input */
+#define GPIOD9_nAC_IN		(GPIOD_BASE + 9)
+#define GPIOD10_nSDIO_IRQ	(GPIOD_BASE + 10)	/* Input */
+#define GPIOD11_nCIOIS16	(GPIOD_BASE + 11)	/* Input, from CF */
+#define GPIOD12_nCWAIT		(GPIOD_BASE + 12)	/* Input, from CF */
+#define GPIOD13_CF_RNB		(GPIOD_BASE + 13)	/* Input */
+#define GPIOD14_nUSBC_DETECT	(GPIOD_BASE + 14)
+#define GPIOD15_nPIOW		(GPIOD_BASE + 15)	/* Input, from CPU */
+
+/*
+ * EGPIOs
+ */
+
+#define EGPIO0_VCC_3V3_EN	(HX4700_EGPIO_BASE + 0)	/* WLAN support chip */
+#define EGPIO1_WL_VREG_EN	(HX4700_EGPIO_BASE + 1)	/* WLAN power */
+#define EGPIO2_VCC_2V1_WL_EN	(HX4700_EGPIO_BASE + 2)	/* unused */
+#define EGPIO3_SS_PWR_ON	(HX4700_EGPIO_BASE + 3)	/* smart slot power */
+#define EGPIO4_CF_3V3_ON	(HX4700_EGPIO_BASE + 4)	/* CF 3.3V enable */
+#define EGPIO5_BT_3V3_ON	(HX4700_EGPIO_BASE + 5)	/* BT 3.3V enable */
+#define EGPIO6_WL1V8_EN		(HX4700_EGPIO_BASE + 6)	/* WLAN 1.8V enable */
+#define EGPIO7_VCC_3V3_WL_EN	(HX4700_EGPIO_BASE + 7)	/* WLAN 3.3V enable */
+#define EGPIO8_USB_3V3_ON	(HX4700_EGPIO_BASE + 8)	/* unused */
+
+#endif /* _HX4700_H_ */
diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h
index 32bb4a2..6a1d959 100644
--- a/arch/arm/mach-pxa/include/mach/irqs.h
+++ b/arch/arm/mach-pxa/include/mach/irqs.h
@@ -91,13 +91,23 @@
 #define IRQ_TO_GPIO(i)	(((i) < IRQ_GPIO(2)) ? ((i) - IRQ_GPIO0) : IRQ_TO_GPIO_2_x(i))
 
 /*
- * The next 16 interrupts are for board specific purposes.  Since
+ * The following interrupts are for board specific purposes. Since
  * the kernel can only run on one machine at a time, we can re-use
- * these.  If you need more, increase IRQ_BOARD_END, but keep it
- * within sensible limits.
+ * these.  There will be 16 IRQs by default.  If it is not enough,
+ * IRQ_BOARD_END is allowed be customized for each board, but keep
+ * the numbers within sensible limits and in descending order, so
+ * when multiple config options are selected, the maximum will be
+ * used.
  */
 #define IRQ_BOARD_START		(PXA_GPIO_IRQ_BASE + PXA_GPIO_IRQ_NUM)
+
+#if defined(CONFIG_MACH_H4700)
+#define IRQ_BOARD_END		(IRQ_BOARD_START + 70)
+#elif defined(CONFIG_MACH_ZYLONITE)
+#define IRQ_BOARD_END		(IRQ_BOARD_START + 32)
+#else
 #define IRQ_BOARD_END		(IRQ_BOARD_START + 16)
+#endif
 
 #define IRQ_SA1111_START	(IRQ_BOARD_END)
 #define IRQ_GPAIN0		(IRQ_BOARD_END + 0)
@@ -188,8 +198,6 @@
 #define NR_IRQS			(IRQ_LOCOMO_SPI_TEND + 1)
 #elif defined(CONFIG_PXA_HAVE_BOARD_IRQS)
 #define NR_IRQS			(IRQ_BOARD_END)
-#elif defined(CONFIG_MACH_ZYLONITE)
-#define NR_IRQS			(IRQ_BOARD_START + 32)
 #else
 #define NR_IRQS			(IRQ_BOARD_START)
 #endif
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa320.h b/arch/arm/mach-pxa/include/mach/mfp-pxa320.h
index 07897e6..3ce4682 100644
--- a/arch/arm/mach-pxa/include/mach/mfp-pxa320.h
+++ b/arch/arm/mach-pxa/include/mach/mfp-pxa320.h
@@ -283,6 +283,9 @@
 #define GPIO41_UART1_TXD	MFP_CFG_LPM(GPIO41, AF4, FLOAT)
 #define GPIO42_UART1_RXD	MFP_CFG_LPM(GPIO42, AF4, FLOAT)
 #define GPIO42_UART1_TXD	MFP_CFG_LPM(GPIO42, AF2, FLOAT)
+#define GPIO75_UART1_RXD	MFP_CFG_LPM(GPIO75, AF1, FLOAT)
+#define GPIO76_UART1_RXD	MFP_CFG_LPM(GPIO76, AF3, FLOAT)
+#define GPIO76_UART1_TXD	MFP_CFG_LPM(GPIO76, AF1, FLOAT)
 #define GPIO97_UART1_RXD	MFP_CFG_LPM(GPIO97, AF1, FLOAT)
 #define GPIO97_UART1_TXD	MFP_CFG_LPM(GPIO97, AF6, FLOAT)
 #define GPIO98_UART1_RXD	MFP_CFG_LPM(GPIO98, AF6, FLOAT)
@@ -291,6 +294,9 @@
 #define GPIO43_UART1_RTS	MFP_CFG_LPM(GPIO43, AF4, FLOAT)
 #define GPIO48_UART1_CTS	MFP_CFG_LPM(GPIO48, AF4, FLOAT)
 #define GPIO48_UART1_RTS	MFP_CFG_LPM(GPIO48, AF2, FLOAT)
+#define GPIO77_UART1_CTS	MFP_CFG_LPM(GPIO77, AF1, FLOAT)
+#define GPIO82_UART1_RTS	MFP_CFG_LPM(GPIO82, AF1, FLOAT)
+#define GPIO82_UART1_CTS	MFP_CFG_LPM(GPIO82, AF3, FLOAT)
 #define GPIO99_UART1_CTS	MFP_CFG_LPM(GPIO99, AF1, FLOAT)
 #define GPIO99_UART1_RTS	MFP_CFG_LPM(GPIO99, AF6, FLOAT)
 #define GPIO104_UART1_CTS	MFP_CFG_LPM(GPIO104, AF6, FLOAT)
@@ -299,13 +305,18 @@
 #define GPIO45_UART1_DSR	MFP_CFG_LPM(GPIO45, AF2, FLOAT)
 #define GPIO47_UART1_DTR	MFP_CFG_LPM(GPIO47, AF2, FLOAT)
 #define GPIO47_UART1_DSR	MFP_CFG_LPM(GPIO47, AF4, FLOAT)
+#define GPIO79_UART1_DSR	MFP_CFG_LPM(GPIO79, AF1, FLOAT)
+#define GPIO81_UART1_DTR	MFP_CFG_LPM(GPIO81, AF1, FLOAT)
+#define GPIO81_UART1_DSR	MFP_CFG_LPM(GPIO81, AF3, FLOAT)
 #define GPIO101_UART1_DTR	MFP_CFG_LPM(GPIO101, AF6, FLOAT)
 #define GPIO101_UART1_DSR	MFP_CFG_LPM(GPIO101, AF1, FLOAT)
 #define GPIO103_UART1_DTR	MFP_CFG_LPM(GPIO103, AF1, FLOAT)
 #define GPIO103_UART1_DSR	MFP_CFG_LPM(GPIO103, AF6, FLOAT)
 #define GPIO44_UART1_DCD	MFP_CFG_LPM(GPIO44, AF2, FLOAT)
+#define GPIO78_UART1_DCD	MFP_CFG_LPM(GPIO78, AF1, FLOAT)
 #define GPIO100_UART1_DCD	MFP_CFG_LPM(GPIO100, AF1, FLOAT)
 #define GPIO46_UART1_RI		MFP_CFG_LPM(GPIO46, AF2, FLOAT)
+#define GPIO80_UART1_RI		MFP_CFG_LPM(GPIO80, AF1, FLOAT)
 #define GPIO102_UART1_RI	MFP_CFG_LPM(GPIO102, AF1, FLOAT)
 
 /* UART2 */
@@ -438,6 +449,9 @@
 
 #define GPIO2_RDY		MFP_CFG(GPIO2, AF1)
 #define GPIO5_NPIOR		MFP_CFG(GPIO5, AF3)
+#define GPIO6_NPIOW		MFP_CFG(GPIO6, AF3)
+#define GPIO7_NPIOS16		MFP_CFG(GPIO7, AF3)
+#define GPIO8_NPWAIT		MFP_CFG(GPIO8, AF3)
 
 #define GPIO11_PWM0_OUT		MFP_CFG(GPIO11, AF1)
 #define GPIO12_PWM1_OUT		MFP_CFG(GPIO12, AF1)
diff --git a/arch/arm/mach-pxa/include/mach/pm.h b/arch/arm/mach-pxa/include/mach/pm.h
index a6eeef8..fd8360c 100644
--- a/arch/arm/mach-pxa/include/mach/pm.h
+++ b/arch/arm/mach-pxa/include/mach/pm.h
@@ -27,6 +27,8 @@
 extern void pxa_cpu_resume(void);
 
 extern int pxa_pm_enter(suspend_state_t state);
+extern int pxa_pm_prepare(void);
+extern void pxa_pm_finish(void);
 
 /* NOTE: this is for PM debugging on Lubbock,  it's really a big
  * ugly, but let's keep the crap minimum here, instead of direct
diff --git a/arch/arm/mach-pxa/include/mach/pxa27x.h b/arch/arm/mach-pxa/include/mach/pxa27x.h
index 6876e16..0b70269 100644
--- a/arch/arm/mach-pxa/include/mach/pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/pxa27x.h
@@ -16,4 +16,7 @@
 #define ARB_DMA_PARK		(1<<25)	   /* Be parked with DMA when idle */
 #define ARB_CORE_PARK		(1<<24)	   /* Be parked with core when idle */
 #define ARB_LOCK_FLAG		(1<<23)	   /* Only Locking masters gain access to the bus */
+
+extern int __init pxa27x_set_pwrmode(unsigned int mode);
+
 #endif /* __MACH_PXA27x_H */
diff --git a/arch/arm/include/asm/hardware/sharpsl_pm.h b/arch/arm/mach-pxa/include/mach/sharpsl_pm.h
similarity index 93%
rename from arch/arm/include/asm/hardware/sharpsl_pm.h
rename to arch/arm/mach-pxa/include/mach/sharpsl_pm.h
index 2d00db2..1920dc6 100644
--- a/arch/arm/include/asm/hardware/sharpsl_pm.h
+++ b/arch/arm/mach-pxa/include/mach/sharpsl_pm.h
@@ -8,8 +8,8 @@
  * published by the Free Software Foundation.
  *
  */
-
-#include <linux/interrupt.h>
+#ifndef _MACH_SHARPSL_PM
+#define _MACH_SHARPSL_PM
 
 struct sharpsl_charger_machinfo {
 	void (*init)(void);
@@ -100,7 +100,5 @@
 
 void sharpsl_battery_kick(void);
 void sharpsl_pm_led(int val);
-irqreturn_t sharpsl_ac_isr(int irq, void *dev_id);
-irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id);
-irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id);
 
+#endif
diff --git a/arch/arm/mach-pxa/include/mach/uncompress.h b/arch/arm/mach-pxa/include/mach/uncompress.h
index 5706cea..b547494 100644
--- a/arch/arm/mach-pxa/include/mach/uncompress.h
+++ b/arch/arm/mach-pxa/include/mach/uncompress.h
@@ -36,7 +36,8 @@
 static inline void arch_decomp_setup(void)
 {
 	if (machine_is_littleton() || machine_is_intelmote2()
-			|| machine_is_csb726())
+	    || machine_is_csb726() || machine_is_stargate2()
+	    || machine_is_cm_x300())
 		UART = STUART;
 }
 
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index c872b9f..55b3788 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -42,14 +42,17 @@
 #include <mach/pxa300.h>
 #include <mach/pxafb.h>
 #include <mach/ssp.h>
+#include <mach/mmc.h>
 #include <mach/pxa2xx_spi.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/pxa27x_keypad.h>
 #include <mach/pxa3xx_nand.h>
 #include <mach/littleton.h>
 
 #include "generic.h"
 
+#define GPIO_MMC1_CARD_DETECT	mfp_to_gpio(MFP_PIN_GPIO15)
+
 /* Littleton MFP configurations */
 static mfp_cfg_t littleton_mfp_cfg[] __initdata = {
 	/* LCD */
@@ -98,6 +101,15 @@
 	GPIO123_KP_MKOUT_2,
 	GPIO124_KP_MKOUT_3,
 	GPIO125_KP_MKOUT_4,
+
+	/* MMC1 */
+	GPIO3_MMC1_DAT0,
+	GPIO4_MMC1_DAT1,
+	GPIO5_MMC1_DAT2,
+	GPIO6_MMC1_DAT3,
+	GPIO7_MMC1_CLK,
+	GPIO8_MMC1_CMD,
+	GPIO15_GPIO, /* card detect */
 };
 
 static struct resource smc91x_resources[] = {
@@ -179,15 +191,10 @@
 	.num_chipselect		= 1,
 };
 
-static void littleton_tdo24m_cs(u32 cmd)
-{
-	gpio_set_value(LITTLETON_GPIO_LCD_CS, !(cmd == PXA2XX_CS_ASSERT));
-}
-
 static struct pxa2xx_spi_chip littleton_tdo24m_chip = {
 	.rx_threshold	= 1,
 	.tx_threshold	= 1,
-	.cs_control	= littleton_tdo24m_cs,
+	.gpio_cs	= LITTLETON_GPIO_LCD_CS,
 };
 
 static struct spi_board_info littleton_spi_devices[] __initdata = {
@@ -202,16 +209,6 @@
 
 static void __init littleton_init_spi(void)
 {
-	int err;
-
-	err = gpio_request(LITTLETON_GPIO_LCD_CS, "LCD_CS");
-	if (err) {
-		pr_warning("failed to request GPIO for LCS CS\n");
-		return;
-	}
-
-	gpio_direction_output(LITTLETON_GPIO_LCD_CS, 1);
-
 	pxa2xx_set_spi_info(2, &littleton_spi_info);
 	spi_register_board_info(ARRAY_AND_SIZE(littleton_spi_devices));
 }
@@ -267,6 +264,56 @@
 static inline void littleton_init_keypad(void) {}
 #endif
 
+#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
+static int littleton_mci_init(struct device *dev,
+			      irq_handler_t littleton_detect_int, void *data)
+{
+	int err, gpio_cd = GPIO_MMC1_CARD_DETECT;
+
+	err = gpio_request(gpio_cd, "mmc card detect");
+	if (err)
+		goto err_request_cd;
+
+	gpio_direction_input(gpio_cd);
+
+	err = request_irq(gpio_to_irq(gpio_cd), littleton_detect_int,
+			  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+			  "mmc card detect", data);
+	if (err) {
+		dev_err(dev, "failed to request card detect IRQ\n");
+		goto err_request_irq;
+	}
+	return 0;
+
+err_request_irq:
+	gpio_free(gpio_cd);
+err_request_cd:
+	return err;
+}
+
+static void littleton_mci_exit(struct device *dev, void *data)
+{
+	int gpio_cd = GPIO_MMC1_CARD_DETECT;
+
+	free_irq(gpio_to_irq(gpio_cd), data);
+	gpio_free(gpio_cd);
+}
+
+static struct pxamci_platform_data littleton_mci_platform_data = {
+	.detect_delay	= 20,
+	.ocr_mask	= MMC_VDD_32_33 | MMC_VDD_33_34,
+	.init 		= littleton_mci_init,
+	.exit		= littleton_mci_exit,
+};
+
+static void __init littleton_init_mmc(void)
+{
+	pxa_set_mci_info(&littleton_mci_platform_data);
+}
+#else
+static inline void littleton_init_mmc(void) {}
+#endif
+
 #if defined(CONFIG_MTD_NAND_PXA3xx) || defined(CONFIG_MTD_NAND_PXA3xx_MODULE)
 static struct mtd_partition littleton_nand_partitions[] = {
 	[0] = {
@@ -407,6 +454,7 @@
 
 	littleton_init_spi();
 	littleton_init_i2c();
+	littleton_init_mmc();
 	littleton_init_lcd();
 	littleton_init_keypad();
 	littleton_init_nand();
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index c899bbd..ca39669 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -36,7 +36,7 @@
 #include <mach/pxa27x.h>
 #include <mach/magician.h>
 #include <mach/pxafb.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
@@ -745,6 +745,14 @@
 };
 
 /*
+ * I2C
+ */
+
+static struct i2c_pxa_platform_data i2c_info = {
+	.fast_mode = 1,
+};
+
+/*
  * Platform devices
  */
 
@@ -771,7 +779,7 @@
 
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(magician_pin_config));
 
-	platform_add_devices(devices, ARRAY_SIZE(devices));
+	platform_add_devices(ARRAY_AND_SIZE(devices));
 
 	err = gpio_request(GPIO83_MAGICIAN_nIR_EN, "nIR_EN");
 	if (!err) {
@@ -779,7 +787,7 @@
 		pxa_set_ficp_info(&magician_ficp_info);
 	}
 	pxa27x_set_i2c_power_info(NULL);
-	pxa_set_i2c_info(NULL);
+	pxa_set_i2c_info(&i2c_info);
 	pxa_set_mci_info(&magician_mci_info);
 	pxa_set_ohci_info(&magician_ohci_info);
 
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index a6c8429..f4dabf0 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -46,7 +46,7 @@
 #include <mach/mainstone.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index ff8052c..4dc8c2e 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -48,7 +48,7 @@
 #include <mach/mmc.h>
 #include <mach/udc.h>
 #include <mach/pxa27x-udc.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/camera.h>
 #include <mach/audio.h>
 #include <media/soc_camera.h>
@@ -798,7 +798,7 @@
 	arm_machine_restart('s', cmd);
 }
 
-struct gpio_ress global_gpios[] = {
+static struct gpio_ress global_gpios[] = {
 	MIO_GPIO_OUT(GPIO9_CHARGE_EN, 1, "Charger enable"),
 	MIO_GPIO_OUT(GPIO18_POWEROFF, 0, "Power Off"),
 	MIO_GPIO_OUT(GPIO87_LCD_POWER, 0, "LCD Power")
diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c
index 2e65f05..ed70f28 100644
--- a/arch/arm/mach-pxa/palmld.c
+++ b/arch/arm/mach-pxa/palmld.c
@@ -532,30 +532,18 @@
 /******************************************************************************
  * Power management - standby
  ******************************************************************************/
-#ifdef CONFIG_PM
-static u32 *addr __initdata;
-static u32 resume[3] __initdata = {
-	0xe3a00101,	/* mov	r0,	#0x40000000 */
-	0xe380060f,	/* orr	r0, r0, #0x00f00000 */
-	0xe590f008,	/* ldr	pc, [r0, #0x08] */
-};
-
-static int __init palmld_pm_init(void)
+static void __init palmld_pm_init(void)
 {
-	int i;
+	static u32 resume[] = {
+		0xe3a00101,	/* mov	r0,	#0x40000000 */
+		0xe380060f,	/* orr	r0, r0, #0x00f00000 */
+		0xe590f008,	/* ldr	pc, [r0, #0x08] */
+	};
 
-	/* this is where the bootloader jumps */
-	addr = phys_to_virt(PALMLD_STR_BASE);
-
-	for (i = 0; i < 3; i++)
-		addr[i] = resume[i];
-
-	return 0;
+	/* copy the bootloader */
+	memcpy(phys_to_virt(PALMLD_STR_BASE), resume, sizeof(resume));
 }
 
-device_initcall(palmld_pm_init);
-#endif
-
 /******************************************************************************
  * Machine init
  ******************************************************************************/
@@ -595,6 +583,7 @@
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(palmld_pin_config));
 
+	palmld_pm_init();
 	set_pxa_fb_info(&palmld_lcd_screen);
 	pxa_set_mci_info(&palmld_mci_platform_data);
 	pxa_set_ac97_info(&palmld_ac97_pdata);
diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c
index 05bf979..aae64a1 100644
--- a/arch/arm/mach-pxa/palmt5.c
+++ b/arch/arm/mach-pxa/palmt5.c
@@ -26,6 +26,7 @@
 #include <linux/gpio.h>
 #include <linux/wm97xx_batt.h>
 #include <linux/power_supply.h>
+#include <linux/usb/gpio_vbus.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -343,11 +344,18 @@
 /******************************************************************************
  * UDC
  ******************************************************************************/
-static struct pxa2xx_udc_mach_info palmt5_udc_info __initdata = {
+static struct gpio_vbus_mach_info palmt5_udc_info = {
 	.gpio_vbus		= GPIO_NR_PALMT5_USB_DETECT_N,
 	.gpio_vbus_inverted	= 1,
 	.gpio_pullup		= GPIO_NR_PALMT5_USB_PULLUP,
-	.gpio_pullup_inverted	= 0,
+};
+
+static struct platform_device palmt5_gpio_vbus = {
+	.name	= "gpio-vbus",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &palmt5_udc_info,
+	},
 };
 
 /******************************************************************************
@@ -466,30 +474,18 @@
 /******************************************************************************
  * Power management - standby
  ******************************************************************************/
-#ifdef CONFIG_PM
-static u32 *addr __initdata;
-static u32 resume[3] __initdata = {
-	0xe3a00101,	/* mov	r0,	#0x40000000 */
-	0xe380060f,	/* orr	r0, r0, #0x00f00000 */
-	0xe590f008,	/* ldr	pc, [r0, #0x08] */
-};
-
-static int __init palmt5_pm_init(void)
+static void __init palmt5_pm_init(void)
 {
-	int i;
+	static u32 resume[] = {
+		0xe3a00101,	/* mov	r0,	#0x40000000 */
+		0xe380060f,	/* orr	r0, r0, #0x00f00000 */
+		0xe590f008,	/* ldr	pc, [r0, #0x08] */
+	};
 
-	/* this is where the bootloader jumps */
-	addr = phys_to_virt(PALMT5_STR_BASE);
-
-	for (i = 0; i < 3; i++)
-		addr[i] = resume[i];
-
-	return 0;
+	/* copy the bootloader */
+	memcpy(phys_to_virt(PALMT5_STR_BASE), resume, sizeof(resume));
 }
 
-device_initcall(palmt5_pm_init);
-#endif
-
 /******************************************************************************
  * Machine init
  ******************************************************************************/
@@ -500,6 +496,7 @@
 	&palmt5_backlight,
 	&power_supply,
 	&palmt5_asoc,
+	&palmt5_gpio_vbus,
 };
 
 /* setup udc GPIOs initial state */
@@ -515,14 +512,15 @@
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(palmt5_pin_config));
 
+	palmt5_pm_init();
 	set_pxa_fb_info(&palmt5_lcd_screen);
 	pxa_set_mci_info(&palmt5_mci_platform_data);
 	palmt5_udc_init();
 	pxa_set_ac97_info(&palmt5_ac97_pdata);
-	pxa_set_udc_info(&palmt5_udc_info);
 	pxa_set_ficp_info(&palmt5_ficp_platform_data);
 	pxa_set_keypad_info(&palmt5_keypad_platform_data);
 	wm97xx_bat_set_pdata(&wm97xx_batt_pdata);
+
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
diff --git a/arch/arm/mach-pxa/palmte2.c b/arch/arm/mach-pxa/palmte2.c
index 43fcf2e..d823b09 100644
--- a/arch/arm/mach-pxa/palmte2.c
+++ b/arch/arm/mach-pxa/palmte2.c
@@ -25,6 +25,7 @@
 #include <linux/gpio.h>
 #include <linux/wm97xx_batt.h>
 #include <linux/power_supply.h>
+#include <linux/usb/gpio_vbus.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -37,6 +38,7 @@
 #include <mach/mfp-pxa25x.h>
 #include <mach/irda.h>
 #include <mach/udc.h>
+#include <mach/palmasoc.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -107,6 +109,7 @@
 	GPIO1_RST,	/* reset */
 	GPIO4_GPIO,	/* Hotsync button */
 	GPIO9_GPIO,	/* power detect */
+	GPIO15_GPIO,	/* earphone detect */
 	GPIO37_GPIO,	/* LCD power */
 	GPIO56_GPIO,	/* Backlight power */
 };
@@ -318,11 +321,18 @@
 /******************************************************************************
  * UDC
  ******************************************************************************/
-static struct pxa2xx_udc_mach_info palmte2_udc_info __initdata = {
+static struct gpio_vbus_mach_info palmte2_udc_info = {
 	.gpio_vbus		= GPIO_NR_PALMTE2_USB_DETECT_N,
 	.gpio_vbus_inverted	= 1,
 	.gpio_pullup		= GPIO_NR_PALMTE2_USB_PULLUP,
-	.gpio_pullup_inverted	= 0,
+};
+
+static struct platform_device palmte2_gpio_vbus = {
+	.name	= "gpio-vbus",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &palmte2_udc_info,
+	},
 };
 
 /******************************************************************************
@@ -395,6 +405,21 @@
 };
 
 /******************************************************************************
+ * aSoC audio
+ ******************************************************************************/
+static struct palm27x_asoc_info palmte2_asoc_pdata = {
+	.jack_gpio	= GPIO_NR_PALMTE2_EARPHONE_DETECT,
+};
+
+static struct platform_device palmte2_asoc = {
+	.name = "palm27x-asoc",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &palmte2_asoc_pdata,
+	},
+};
+
+/******************************************************************************
  * Framebuffer
  ******************************************************************************/
 static struct pxafb_mode_info palmte2_lcd_modes[] = {
@@ -429,6 +454,8 @@
 #endif
 	&palmte2_backlight,
 	&power_supply,
+	&palmte2_asoc,
+	&palmte2_gpio_vbus,
 };
 
 /* setup udc GPIOs initial state */
@@ -447,7 +474,6 @@
 	set_pxa_fb_info(&palmte2_lcd_screen);
 	pxa_set_mci_info(&palmte2_mci_platform_data);
 	palmte2_udc_init();
-	pxa_set_udc_info(&palmte2_udc_info);
 	pxa_set_ac97_info(NULL);
 	pxa_set_ficp_info(&palmte2_ficp_platform_data);
 	wm97xx_bat_set_pdata(&wm97xx_batt_pdata);
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
index e99a893..6c15d84 100644
--- a/arch/arm/mach-pxa/palmtx.c
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -27,6 +27,7 @@
 #include <linux/gpio.h>
 #include <linux/wm97xx_batt.h>
 #include <linux/power_supply.h>
+#include <linux/usb/gpio_vbus.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -359,11 +360,18 @@
 /******************************************************************************
  * UDC
  ******************************************************************************/
-static struct pxa2xx_udc_mach_info palmtx_udc_info __initdata = {
+static struct gpio_vbus_mach_info palmtx_udc_info = {
 	.gpio_vbus		= GPIO_NR_PALMTX_USB_DETECT_N,
 	.gpio_vbus_inverted	= 1,
 	.gpio_pullup		= GPIO_NR_PALMTX_USB_PULLUP,
-	.gpio_pullup_inverted	= 0,
+};
+
+static struct platform_device palmtx_gpio_vbus = {
+	.name	= "gpio-vbus",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &palmtx_udc_info,
+	},
 };
 
 /******************************************************************************
@@ -483,30 +491,18 @@
 /******************************************************************************
  * Power management - standby
  ******************************************************************************/
-#ifdef CONFIG_PM
-static u32 *addr __initdata;
-static u32 resume[3] __initdata = {
-	0xe3a00101,	/* mov	r0,	#0x40000000 */
-	0xe380060f,	/* orr	r0, r0, #0x00f00000 */
-	0xe590f008,	/* ldr	pc, [r0, #0x08] */
-};
-
-static int __init palmtx_pm_init(void)
+static void __init palmtx_pm_init(void)
 {
-	int i;
+	static u32 resume[] = {
+		0xe3a00101,	/* mov	r0,	#0x40000000 */
+		0xe380060f,	/* orr	r0, r0, #0x00f00000 */
+		0xe590f008,	/* ldr	pc, [r0, #0x08] */
+	};
 
-	/* this is where the bootloader jumps */
-	addr = phys_to_virt(PALMTX_STR_BASE);
-
-	for (i = 0; i < 3; i++)
-		addr[i] = resume[i];
-
-	return 0;
+	/* copy the bootloader */
+	memcpy(phys_to_virt(PALMTX_STR_BASE), resume, sizeof(resume));
 }
 
-device_initcall(palmtx_pm_init);
-#endif
-
 /******************************************************************************
  * Machine init
  ******************************************************************************/
@@ -517,6 +513,7 @@
 	&palmtx_backlight,
 	&power_supply,
 	&palmtx_asoc,
+	&palmtx_gpio_vbus,
 };
 
 static struct map_desc palmtx_io_desc[] __initdata = {
@@ -548,11 +545,11 @@
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(palmtx_pin_config));
 
+	palmtx_pm_init();
 	set_pxa_fb_info(&palmtx_lcd_screen);
 	pxa_set_mci_info(&palmtx_mci_platform_data);
 	palmtx_udc_init();
 	pxa_set_ac97_info(&palmtx_ac97_pdata);
-	pxa_set_udc_info(&palmtx_udc_info);
 	pxa_set_ficp_info(&palmtx_ficp_platform_data);
 	pxa_set_keypad_info(&palmtx_keypad_platform_data);
 	wm97xx_bat_set_pdata(&wm97xx_batt_pdata);
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index 6c12b5a..095521e 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -28,7 +28,7 @@
 #include <media/soc_camera.h>
 
 #include <asm/gpio.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/camera.h>
 #include <asm/mach/map.h>
 #include <mach/pxa27x.h>
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
index 884b174..7693355 100644
--- a/arch/arm/mach-pxa/pm.c
+++ b/arch/arm/mach-pxa/pm.c
@@ -79,7 +79,7 @@
 	return -EINVAL;
 }
 
-static int pxa_pm_prepare(void)
+int pxa_pm_prepare(void)
 {
 	int ret = 0;
 
@@ -89,7 +89,7 @@
 	return ret;
 }
 
-static void pxa_pm_finish(void)
+void pxa_pm_finish(void)
 {
 	if (pxa_cpu_pm_fns && pxa_cpu_pm_fns->finish)
 		pxa_cpu_pm_fns->finish();
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 036bbde..ac431ed 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -39,7 +39,7 @@
 #include <mach/pxa25x.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/irda.h>
 #include <mach/poodle.h>
 #include <mach/pxafb.h>
@@ -214,13 +214,8 @@
 	.gpio_pendown		= POODLE_GPIO_TP_INT,
 };
 
-static void ads7846_cs(u32 command)
-{
-	gpio_set_value(POODLE_GPIO_TP_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
 static struct pxa2xx_spi_chip poodle_ads7846_chip = {
-	.cs_control		= ads7846_cs,
+	.gpio_cs		= POODLE_GPIO_TP_CS,
 };
 
 static struct spi_board_info poodle_spi_devices[] = {
@@ -236,14 +231,6 @@
 
 static void __init poodle_init_spi(void)
 {
-	int err;
-
-	err = gpio_request(POODLE_GPIO_TP_CS, "ADS7846_CS");
-	if (err)
-		return;
-
-	gpio_direction_output(POODLE_GPIO_TP_CS, 1);
-
 	pxa2xx_set_spi_info(1, &poodle_spi_info);
 	spi_register_board_info(ARRAY_AND_SIZE(poodle_spi_devices));
 }
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index a425ec7..ec68cc1 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -27,7 +27,7 @@
 #include <mach/ohci.h>
 #include <mach/pm.h>
 #include <mach/dma.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -204,6 +204,23 @@
 #define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]
 
 /*
+ * allow platforms to override default PWRMODE setting used for PM_SUSPEND_MEM
+ */
+static unsigned int pwrmode = PWRMODE_SLEEP;
+
+int __init pxa27x_set_pwrmode(unsigned int mode)
+{
+	switch (mode) {
+	case PWRMODE_SLEEP:
+	case PWRMODE_DEEPSLEEP:
+		pwrmode = mode;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+/*
  * List of global PXA peripheral registers to preserve.
  * More ones like CP and general purpose register values are preserved
  * with the stack pointer in sleep.S.
@@ -254,7 +271,7 @@
 		pxa_cpu_standby();
 		break;
 	case PM_SUSPEND_MEM:
-		pxa27x_cpu_suspend(PWRMODE_SLEEP);
+		pxa27x_cpu_suspend(pwrmode);
 		break;
 	}
 }
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index b02d454..6f678d9 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -30,7 +30,7 @@
 #include <mach/pm.h>
 #include <mach/dma.h>
 #include <mach/ssp.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -552,7 +552,7 @@
 }
 
 static struct platform_device *devices[] __initdata = {
-/*	&pxa_device_udc,	The UDC driver is PXA25x only */
+	&pxa27x_device_udc,
 	&pxa_device_ffuart,
 	&pxa_device_btuart,
 	&pxa_device_stuart,
diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c
index ff82399..8241a63 100644
--- a/arch/arm/mach-pxa/saar.c
+++ b/arch/arm/mach-pxa/saar.c
@@ -27,7 +27,7 @@
 #include <asm/mach/arch.h>
 
 #include <mach/pxa930.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/pxafb.h>
 
 #include "devices.h"
diff --git a/arch/arm/mach-pxa/sharpsl.h b/arch/arm/mach-pxa/sharpsl.h
index 047909a..55259f4 100644
--- a/arch/arm/mach-pxa/sharpsl.h
+++ b/arch/arm/mach-pxa/sharpsl.h
@@ -7,7 +7,7 @@
  *
  */
 
-#include <asm/hardware/sharpsl_pm.h>
+#include <mach/sharpsl_pm.h>
 
 /*
  * SharpSL SSP Driver
@@ -44,8 +44,6 @@
 
 extern struct battery_thresh spitz_battery_levels_acin[];
 extern struct battery_thresh spitz_battery_levels_noac[];
-void sharpsl_pm_pxa_init(void);
-void sharpsl_pm_pxa_remove(void);
 int sharpsl_pm_pxa_read_max1111(int channel);
 
 
diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c
index 16b4ec6..2546c06 100644
--- a/arch/arm/mach-pxa/sharpsl_pm.c
+++ b/arch/arm/mach-pxa/sharpsl_pm.c
@@ -15,20 +15,69 @@
 #undef DEBUG
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/apm-emulation.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/leds.h>
+#include <linux/suspend.h>
+#include <linux/gpio.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <mach/pm.h>
+#include <mach/pxa2xx-regs.h>
 #include <mach/pxa2xx-gpio.h>
+#include <mach/regs-rtc.h>
 #include <mach/sharpsl.h>
+#include <mach/sharpsl_pm.h>
+
 #include "sharpsl.h"
 
+/*
+ * Constants
+ */
+#define SHARPSL_CHARGE_ON_TIME_INTERVAL        (msecs_to_jiffies(1*60*1000))  /* 1 min */
+#define SHARPSL_CHARGE_FINISH_TIME             (msecs_to_jiffies(10*60*1000)) /* 10 min */
+#define SHARPSL_BATCHK_TIME                    (msecs_to_jiffies(15*1000))    /* 15 sec */
+#define SHARPSL_BATCHK_TIME_SUSPEND            (60*10)                        /* 10 min */
+
+#define SHARPSL_WAIT_CO_TIME                   15  /* 15 sec */
+#define SHARPSL_WAIT_DISCHARGE_ON              100 /* 100 msec */
+#define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP   10  /* 10 msec */
+#define SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT   10  /* 10 msec */
+#define SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN   10  /* 10 msec */
+#define SHARPSL_CHARGE_WAIT_TIME               15  /* 15 msec */
+#define SHARPSL_CHARGE_CO_CHECK_TIME           5   /* 5 msec */
+#define SHARPSL_CHARGE_RETRY_CNT               1   /* eqv. 10 min */
+
+/*
+ * Prototypes
+ */
+#ifdef CONFIG_PM
+static int sharpsl_off_charge_battery(void);
+static int sharpsl_check_battery_voltage(void);
+static int sharpsl_fatal_check(void);
+#endif
+static int sharpsl_check_battery_temp(void);
+static int sharpsl_ac_check(void);
+static int sharpsl_average_value(int ad);
+static void sharpsl_average_clear(void);
+static void sharpsl_charge_toggle(struct work_struct *private_);
+static void sharpsl_battery_thread(struct work_struct *private_);
+
+
+/*
+ * Variables
+ */
+struct sharpsl_pm_status sharpsl_pm;
+static DECLARE_DELAYED_WORK(toggle_charger, sharpsl_charge_toggle);
+static DECLARE_DELAYED_WORK(sharpsl_bat, sharpsl_battery_thread);
+DEFINE_LED_TRIGGER(sharpsl_charge_led_trigger);
+
+
+
 struct battery_thresh spitz_battery_levels_acin[] = {
 	{ 213, 100},
 	{ 212,  98},
@@ -144,42 +193,789 @@
 #endif
 }
 
-void sharpsl_pm_pxa_init(void)
+static int get_percentage(int voltage)
 {
-	pxa_gpio_mode(sharpsl_pm.machinfo->gpio_acin | GPIO_IN);
-	pxa_gpio_mode(sharpsl_pm.machinfo->gpio_batfull | GPIO_IN);
-	pxa_gpio_mode(sharpsl_pm.machinfo->gpio_batlock | GPIO_IN);
+	int i = sharpsl_pm.machinfo->bat_levels - 1;
+	int bl_status = sharpsl_pm.machinfo->backlight_get_status ? sharpsl_pm.machinfo->backlight_get_status() : 0;
+	struct battery_thresh *thresh;
+
+	if (sharpsl_pm.charge_mode == CHRG_ON)
+		thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_acin_bl : sharpsl_pm.machinfo->bat_levels_acin;
+	else
+		thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_noac_bl : sharpsl_pm.machinfo->bat_levels_noac;
+
+	while (i > 0 && (voltage > thresh[i].voltage))
+		i--;
+
+	return thresh[i].percentage;
+}
+
+static int get_apm_status(int voltage)
+{
+	int low_thresh, high_thresh;
+
+	if (sharpsl_pm.charge_mode == CHRG_ON) {
+		high_thresh = sharpsl_pm.machinfo->status_high_acin;
+		low_thresh = sharpsl_pm.machinfo->status_low_acin;
+	} else {
+		high_thresh = sharpsl_pm.machinfo->status_high_noac;
+		low_thresh = sharpsl_pm.machinfo->status_low_noac;
+	}
+
+	if (voltage >= high_thresh)
+		return APM_BATTERY_STATUS_HIGH;
+	if (voltage >= low_thresh)
+		return APM_BATTERY_STATUS_LOW;
+	return APM_BATTERY_STATUS_CRITICAL;
+}
+
+void sharpsl_battery_kick(void)
+{
+	schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(125));
+}
+EXPORT_SYMBOL(sharpsl_battery_kick);
+
+
+static void sharpsl_battery_thread(struct work_struct *private_)
+{
+	int voltage, percent, apm_status, i = 0;
+
+	if (!sharpsl_pm.machinfo)
+		return;
+
+	sharpsl_pm.battstat.ac_status = (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN) ? APM_AC_ONLINE : APM_AC_OFFLINE);
+
+	/* Corgi cannot confirm when battery fully charged so periodically kick! */
+	if (!sharpsl_pm.machinfo->batfull_irq && (sharpsl_pm.charge_mode == CHRG_ON)
+			&& time_after(jiffies, sharpsl_pm.charge_start_time +  SHARPSL_CHARGE_ON_TIME_INTERVAL))
+		schedule_delayed_work(&toggle_charger, 0);
+
+	while(1) {
+		voltage = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
+
+		if (voltage > 0) break;
+		if (i++ > 5) {
+			voltage = sharpsl_pm.machinfo->bat_levels_noac[0].voltage;
+			dev_warn(sharpsl_pm.dev, "Warning: Cannot read main battery!\n");
+			break;
+		}
+	}
+
+	voltage = sharpsl_average_value(voltage);
+	apm_status = get_apm_status(voltage);
+	percent = get_percentage(voltage);
+
+	/* At low battery voltages, the voltage has a tendency to start
+           creeping back up so we try to avoid this here */
+	if ((sharpsl_pm.battstat.ac_status == APM_AC_ONLINE) || (apm_status == APM_BATTERY_STATUS_HIGH) ||  percent <= sharpsl_pm.battstat.mainbat_percent) {
+		sharpsl_pm.battstat.mainbat_voltage = voltage;
+		sharpsl_pm.battstat.mainbat_status = apm_status;
+		sharpsl_pm.battstat.mainbat_percent = percent;
+	}
+
+	dev_dbg(sharpsl_pm.dev, "Battery: voltage: %d, status: %d, percentage: %d, time: %ld\n", voltage,
+			sharpsl_pm.battstat.mainbat_status, sharpsl_pm.battstat.mainbat_percent, jiffies);
+
+#ifdef CONFIG_BACKLIGHT_CORGI
+	/* If battery is low. limit backlight intensity to save power. */
+	if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE)
+			&& ((sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_LOW) ||
+			(sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL))) {
+		if (!(sharpsl_pm.flags & SHARPSL_BL_LIMIT)) {
+			sharpsl_pm.machinfo->backlight_limit(1);
+			sharpsl_pm.flags |= SHARPSL_BL_LIMIT;
+		}
+	} else if (sharpsl_pm.flags & SHARPSL_BL_LIMIT) {
+		sharpsl_pm.machinfo->backlight_limit(0);
+		sharpsl_pm.flags &= ~SHARPSL_BL_LIMIT;
+	}
+#endif
+
+	/* Suspend if critical battery level */
+	if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE)
+			&& (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL)
+			&& !(sharpsl_pm.flags & SHARPSL_APM_QUEUED)) {
+		sharpsl_pm.flags |= SHARPSL_APM_QUEUED;
+		dev_err(sharpsl_pm.dev, "Fatal Off\n");
+		apm_queue_event(APM_CRITICAL_SUSPEND);
+	}
+
+	schedule_delayed_work(&sharpsl_bat, SHARPSL_BATCHK_TIME);
+}
+
+void sharpsl_pm_led(int val)
+{
+	if (val == SHARPSL_LED_ERROR) {
+		dev_err(sharpsl_pm.dev, "Charging Error!\n");
+	} else if (val == SHARPSL_LED_ON) {
+		dev_dbg(sharpsl_pm.dev, "Charge LED On\n");
+		led_trigger_event(sharpsl_charge_led_trigger, LED_FULL);
+	} else {
+		dev_dbg(sharpsl_pm.dev, "Charge LED Off\n");
+		led_trigger_event(sharpsl_charge_led_trigger, LED_OFF);
+	}
+}
+
+static void sharpsl_charge_on(void)
+{
+	dev_dbg(sharpsl_pm.dev, "Turning Charger On\n");
+
+	sharpsl_pm.full_count = 0;
+	sharpsl_pm.charge_mode = CHRG_ON;
+	schedule_delayed_work(&toggle_charger, msecs_to_jiffies(250));
+	schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(500));
+}
+
+static void sharpsl_charge_off(void)
+{
+	dev_dbg(sharpsl_pm.dev, "Turning Charger Off\n");
+
+	sharpsl_pm.machinfo->charge(0);
+	sharpsl_pm_led(SHARPSL_LED_OFF);
+	sharpsl_pm.charge_mode = CHRG_OFF;
+
+	schedule_delayed_work(&sharpsl_bat, 0);
+}
+
+static void sharpsl_charge_error(void)
+{
+	sharpsl_pm_led(SHARPSL_LED_ERROR);
+	sharpsl_pm.machinfo->charge(0);
+	sharpsl_pm.charge_mode = CHRG_ERROR;
+}
+
+static void sharpsl_charge_toggle(struct work_struct *private_)
+{
+	dev_dbg(sharpsl_pm.dev, "Toogling Charger at time: %lx\n", jiffies);
+
+	if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
+		sharpsl_charge_off();
+		return;
+	} else if ((sharpsl_check_battery_temp() < 0) || (sharpsl_ac_check() < 0)) {
+		sharpsl_charge_error();
+		return;
+	}
+
+	sharpsl_pm_led(SHARPSL_LED_ON);
+	sharpsl_pm.machinfo->charge(0);
+	mdelay(SHARPSL_CHARGE_WAIT_TIME);
+	sharpsl_pm.machinfo->charge(1);
+
+	sharpsl_pm.charge_start_time = jiffies;
+}
+
+static void sharpsl_ac_timer(unsigned long data)
+{
+	int acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN);
+
+	dev_dbg(sharpsl_pm.dev, "AC Status: %d\n",acin);
+
+	sharpsl_average_clear();
+	if (acin && (sharpsl_pm.charge_mode != CHRG_ON))
+		sharpsl_charge_on();
+	else if (sharpsl_pm.charge_mode == CHRG_ON)
+		sharpsl_charge_off();
+
+	schedule_delayed_work(&sharpsl_bat, 0);
+}
+
+
+static irqreturn_t sharpsl_ac_isr(int irq, void *dev_id)
+{
+	/* Delay the event slightly to debounce */
+	/* Must be a smaller delay than the chrg_full_isr below */
+	mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250));
+
+	return IRQ_HANDLED;
+}
+
+static void sharpsl_chrg_full_timer(unsigned long data)
+{
+	dev_dbg(sharpsl_pm.dev, "Charge Full at time: %lx\n", jiffies);
+
+	sharpsl_pm.full_count++;
+
+	if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
+		dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n");
+		if (sharpsl_pm.charge_mode == CHRG_ON)
+			sharpsl_charge_off();
+	} else if (sharpsl_pm.full_count < 2) {
+		dev_dbg(sharpsl_pm.dev, "Charge Full: Count too low\n");
+		schedule_delayed_work(&toggle_charger, 0);
+	} else if (time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_FINISH_TIME)) {
+		dev_dbg(sharpsl_pm.dev, "Charge Full: Interrupt generated too slowly - retry.\n");
+		schedule_delayed_work(&toggle_charger, 0);
+	} else {
+		sharpsl_charge_off();
+		sharpsl_pm.charge_mode = CHRG_DONE;
+		dev_dbg(sharpsl_pm.dev, "Charge Full: Charging Finished\n");
+	}
+}
+
+/* Charging Finished Interrupt (Not present on Corgi) */
+/* Can trigger at the same time as an AC status change so
+   delay until after that has been processed */
+static irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id)
+{
+	if (sharpsl_pm.flags & SHARPSL_SUSPENDED)
+		return IRQ_HANDLED;
+
+	/* delay until after any ac interrupt */
+	mod_timer(&sharpsl_pm.chrg_full_timer, jiffies + msecs_to_jiffies(500));
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id)
+{
+	int is_fatal = 0;
+
+	if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) {
+		dev_err(sharpsl_pm.dev, "Battery now Unlocked! Suspending.\n");
+		is_fatal = 1;
+	}
+
+	if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_FATAL)) {
+		dev_err(sharpsl_pm.dev, "Fatal Batt Error! Suspending.\n");
+		is_fatal = 1;
+	}
+
+	if (!(sharpsl_pm.flags & SHARPSL_APM_QUEUED) && is_fatal) {
+		sharpsl_pm.flags |= SHARPSL_APM_QUEUED;
+		apm_queue_event(APM_CRITICAL_SUSPEND);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Maintain an average of the last 10 readings
+ */
+#define SHARPSL_CNV_VALUE_NUM    10
+static int sharpsl_ad_index;
+
+static void sharpsl_average_clear(void)
+{
+	sharpsl_ad_index = 0;
+}
+
+static int sharpsl_average_value(int ad)
+{
+	int i, ad_val = 0;
+	static int sharpsl_ad[SHARPSL_CNV_VALUE_NUM+1];
+
+	if (sharpsl_pm.battstat.mainbat_status != APM_BATTERY_STATUS_HIGH) {
+		sharpsl_ad_index = 0;
+		return ad;
+	}
+
+	sharpsl_ad[sharpsl_ad_index] = ad;
+	sharpsl_ad_index++;
+	if (sharpsl_ad_index >= SHARPSL_CNV_VALUE_NUM) {
+		for (i=0; i < (SHARPSL_CNV_VALUE_NUM-1); i++)
+			sharpsl_ad[i] = sharpsl_ad[i+1];
+		sharpsl_ad_index = SHARPSL_CNV_VALUE_NUM - 1;
+	}
+	for (i=0; i < sharpsl_ad_index; i++)
+		ad_val += sharpsl_ad[i];
+
+	return (ad_val / sharpsl_ad_index);
+}
+
+/*
+ * Take an array of 5 integers, remove the maximum and minimum values
+ * and return the average.
+ */
+static int get_select_val(int *val)
+{
+	int i, j, k, temp, sum = 0;
+
+	/* Find MAX val */
+	temp = val[0];
+	j=0;
+	for (i=1; i<5; i++) {
+		if (temp < val[i]) {
+			temp = val[i];
+			j = i;
+		}
+	}
+
+	/* Find MIN val */
+	temp = val[4];
+	k=4;
+	for (i=3; i>=0; i--) {
+		if (temp > val[i]) {
+			temp = val[i];
+			k = i;
+		}
+	}
+
+	for (i=0; i<5; i++)
+		if (i != j && i != k )
+			sum += val[i];
+
+	dev_dbg(sharpsl_pm.dev, "Average: %d from values: %d, %d, %d, %d, %d\n", sum/3, val[0], val[1], val[2], val[3], val[4]);
+
+	return (sum/3);
+}
+
+static int sharpsl_check_battery_temp(void)
+{
+	int val, i, buff[5];
+
+	/* Check battery temperature */
+	for (i=0; i<5; i++) {
+		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP);
+		sharpsl_pm.machinfo->measure_temp(1);
+		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP);
+		buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_TEMP);
+		sharpsl_pm.machinfo->measure_temp(0);
+	}
+
+	val = get_select_val(buff);
+
+	dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val);
+	if (val > sharpsl_pm.machinfo->charge_on_temp) {
+		printk(KERN_WARNING "Not charging: temperature out of limits.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int sharpsl_check_battery_voltage(void)
+{
+	int val, i, buff[5];
+
+	/* disable charge, enable discharge */
+	sharpsl_pm.machinfo->charge(0);
+	sharpsl_pm.machinfo->discharge(1);
+	mdelay(SHARPSL_WAIT_DISCHARGE_ON);
+
+	if (sharpsl_pm.machinfo->discharge1)
+		sharpsl_pm.machinfo->discharge1(1);
+
+	/* Check battery voltage */
+	for (i=0; i<5; i++) {
+		buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
+		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT);
+	}
+
+	if (sharpsl_pm.machinfo->discharge1)
+		sharpsl_pm.machinfo->discharge1(0);
+
+	sharpsl_pm.machinfo->discharge(0);
+
+	val = get_select_val(buff);
+	dev_dbg(sharpsl_pm.dev, "Battery Voltage: %d\n", val);
+
+	if (val < sharpsl_pm.machinfo->charge_on_volt)
+		return -1;
+
+	return 0;
+}
+#endif
+
+static int sharpsl_ac_check(void)
+{
+	int temp, i, buff[5];
+
+	for (i=0; i<5; i++) {
+		buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_ACIN_VOLT);
+		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN);
+	}
+
+	temp = get_select_val(buff);
+	dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp);
+
+	if ((temp > sharpsl_pm.machinfo->charge_acin_high) || (temp < sharpsl_pm.machinfo->charge_acin_low)) {
+		dev_err(sharpsl_pm.dev, "Error: AC check failed.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int sharpsl_pm_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	sharpsl_pm.flags |= SHARPSL_SUSPENDED;
+	flush_scheduled_work();
+
+	if (sharpsl_pm.charge_mode == CHRG_ON)
+		sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG;
+	else
+		sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG;
+
+	return 0;
+}
+
+static int sharpsl_pm_resume(struct platform_device *pdev)
+{
+	/* Clear the reset source indicators as they break the bootloader upon reboot */
+	RCSR = 0x0f;
+	sharpsl_average_clear();
+	sharpsl_pm.flags &= ~SHARPSL_APM_QUEUED;
+	sharpsl_pm.flags &= ~SHARPSL_SUSPENDED;
+
+	return 0;
+}
+
+static void corgi_goto_sleep(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state)
+{
+	dev_dbg(sharpsl_pm.dev, "Time is: %08x\n",RCNR);
+
+	dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n",sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG);
+	/* not charging and AC-IN! */
+
+	if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN))) {
+		dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n");
+		sharpsl_pm.charge_mode = CHRG_OFF;
+		sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG;
+		sharpsl_off_charge_battery();
+	}
+
+	sharpsl_pm.machinfo->presuspend();
+
+	PEDR = 0xffffffff; /* clear it */
+
+	sharpsl_pm.flags &= ~SHARPSL_ALARM_ACTIVE;
+	if ((sharpsl_pm.charge_mode == CHRG_ON) && ((alarm_enable && ((alarm_time - RCNR) > (SHARPSL_BATCHK_TIME_SUSPEND + 30))) || !alarm_enable)) {
+		RTSR &= RTSR_ALE;
+		RTAR = RCNR + SHARPSL_BATCHK_TIME_SUSPEND;
+		dev_dbg(sharpsl_pm.dev, "Charging alarm at: %08x\n",RTAR);
+		sharpsl_pm.flags |= SHARPSL_ALARM_ACTIVE;
+	} else if (alarm_enable) {
+		RTSR &= RTSR_ALE;
+		RTAR = alarm_time;
+		dev_dbg(sharpsl_pm.dev, "User alarm at: %08x\n",RTAR);
+	} else {
+		dev_dbg(sharpsl_pm.dev, "No alarms set.\n");
+	}
+
+	pxa_pm_enter(state);
+
+	sharpsl_pm.machinfo->postsuspend();
+
+	dev_dbg(sharpsl_pm.dev, "Corgi woken up from suspend: %08x\n",PEDR);
+}
+
+static int corgi_enter_suspend(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state)
+{
+	if (!sharpsl_pm.machinfo->should_wakeup(!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE) && alarm_enable) )
+	{
+		if (!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE)) {
+			dev_dbg(sharpsl_pm.dev, "No user triggered wakeup events and not charging. Strange. Suspend.\n");
+			corgi_goto_sleep(alarm_time, alarm_enable, state);
+			return 1;
+		}
+		if(sharpsl_off_charge_battery()) {
+			dev_dbg(sharpsl_pm.dev, "Charging. Suspend...\n");
+			corgi_goto_sleep(alarm_time, alarm_enable, state);
+			return 1;
+		}
+		dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n");
+	}
+
+	if ((!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) || (sharpsl_fatal_check() < 0) )
+	{
+		dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n");
+		corgi_goto_sleep(alarm_time, alarm_enable, state);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int corgi_pxa_pm_enter(suspend_state_t state)
+{
+	unsigned long alarm_time = RTAR;
+	unsigned int alarm_status = ((RTSR & RTSR_ALE) != 0);
+
+	dev_dbg(sharpsl_pm.dev, "SharpSL suspending for first time.\n");
+
+	corgi_goto_sleep(alarm_time, alarm_status, state);
+
+	while (corgi_enter_suspend(alarm_time,alarm_status,state))
+		{}
+
+	if (sharpsl_pm.machinfo->earlyresume)
+		sharpsl_pm.machinfo->earlyresume();
+
+	dev_dbg(sharpsl_pm.dev, "SharpSL resuming...\n");
+
+	return 0;
+}
+
+/*
+ * Check for fatal battery errors
+ * Fatal returns -1
+ */
+static int sharpsl_fatal_check(void)
+{
+	int buff[5], temp, i, acin;
+
+	dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n");
+
+	/* Check AC-Adapter */
+	acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN);
+
+	if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) {
+		sharpsl_pm.machinfo->charge(0);
+		udelay(100);
+		sharpsl_pm.machinfo->discharge(1);	/* enable discharge */
+		mdelay(SHARPSL_WAIT_DISCHARGE_ON);
+	}
+
+	if (sharpsl_pm.machinfo->discharge1)
+		sharpsl_pm.machinfo->discharge1(1);
+
+	/* Check battery : check inserting battery ? */
+	for (i=0; i<5; i++) {
+		buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
+		mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT);
+	}
+
+	if (sharpsl_pm.machinfo->discharge1)
+		sharpsl_pm.machinfo->discharge1(0);
+
+	if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) {
+		udelay(100);
+		sharpsl_pm.machinfo->charge(1);
+		sharpsl_pm.machinfo->discharge(0);
+	}
+
+	temp = get_select_val(buff);
+	dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %ld\n", acin, temp, sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT));
+
+	if ((acin && (temp < sharpsl_pm.machinfo->fatal_acin_volt)) ||
+			(!acin && (temp < sharpsl_pm.machinfo->fatal_noacin_volt)))
+		return -1;
+	return 0;
+}
+
+static int sharpsl_off_charge_error(void)
+{
+	dev_err(sharpsl_pm.dev, "Offline Charger: Error occurred.\n");
+	sharpsl_pm.machinfo->charge(0);
+	sharpsl_pm_led(SHARPSL_LED_ERROR);
+	sharpsl_pm.charge_mode = CHRG_ERROR;
+	return 1;
+}
+
+/*
+ * Charging Control while suspended
+ * Return 1 - go straight to sleep
+ * Return 0 - sleep or wakeup depending on other factors
+ */
+static int sharpsl_off_charge_battery(void)
+{
+	int time;
+
+	dev_dbg(sharpsl_pm.dev, "Charge Mode: %d\n", sharpsl_pm.charge_mode);
+
+	if (sharpsl_pm.charge_mode == CHRG_OFF) {
+		dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n");
+
+		/* AC Check */
+		if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery_temp() < 0))
+			return sharpsl_off_charge_error();
+
+		/* Start Charging */
+		sharpsl_pm_led(SHARPSL_LED_ON);
+		sharpsl_pm.machinfo->charge(0);
+		mdelay(SHARPSL_CHARGE_WAIT_TIME);
+		sharpsl_pm.machinfo->charge(1);
+
+		sharpsl_pm.charge_mode = CHRG_ON;
+		sharpsl_pm.full_count = 0;
+
+		return 1;
+	} else if (sharpsl_pm.charge_mode != CHRG_ON) {
+		return 1;
+	}
+
+	if (sharpsl_pm.full_count == 0) {
+		int time;
+
+		dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n");
+
+		if ((sharpsl_check_battery_temp() < 0) || (sharpsl_check_battery_voltage() < 0))
+			return sharpsl_off_charge_error();
+
+		sharpsl_pm.machinfo->charge(0);
+		mdelay(SHARPSL_CHARGE_WAIT_TIME);
+		sharpsl_pm.machinfo->charge(1);
+		sharpsl_pm.charge_mode = CHRG_ON;
+
+		mdelay(SHARPSL_CHARGE_CO_CHECK_TIME);
+
+		time = RCNR;
+		while(1) {
+			/* Check if any wakeup event had occurred */
+			if (sharpsl_pm.machinfo->charger_wakeup() != 0)
+				return 0;
+			/* Check for timeout */
+			if ((RCNR - time) > SHARPSL_WAIT_CO_TIME)
+				return 1;
+			if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) {
+				dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occurred. Retrying to check\n");
+				sharpsl_pm.full_count++;
+				sharpsl_pm.machinfo->charge(0);
+				mdelay(SHARPSL_CHARGE_WAIT_TIME);
+				sharpsl_pm.machinfo->charge(1);
+				return 1;
+			}
+		}
+	}
+
+	dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 3\n");
+
+	mdelay(SHARPSL_CHARGE_CO_CHECK_TIME);
+
+	time = RCNR;
+	while(1) {
+		/* Check if any wakeup event had occurred */
+		if (sharpsl_pm.machinfo->charger_wakeup() != 0)
+			return 0;
+		/* Check for timeout */
+		if ((RCNR-time) > SHARPSL_WAIT_CO_TIME) {
+			if (sharpsl_pm.full_count > SHARPSL_CHARGE_RETRY_CNT) {
+				dev_dbg(sharpsl_pm.dev, "Offline Charger: Not charged sufficiently. Retrying.\n");
+				sharpsl_pm.full_count = 0;
+			}
+			sharpsl_pm.full_count++;
+			return 1;
+		}
+		if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) {
+			dev_dbg(sharpsl_pm.dev, "Offline Charger: Charging complete.\n");
+			sharpsl_pm_led(SHARPSL_LED_OFF);
+			sharpsl_pm.machinfo->charge(0);
+			sharpsl_pm.charge_mode = CHRG_DONE;
+			return 1;
+		}
+	}
+}
+#else
+#define sharpsl_pm_suspend	NULL
+#define sharpsl_pm_resume	NULL
+#endif
+
+static ssize_t battery_percentage_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n",sharpsl_pm.battstat.mainbat_percent);
+}
+
+static ssize_t battery_voltage_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n",sharpsl_pm.battstat.mainbat_voltage);
+}
+
+static DEVICE_ATTR(battery_percentage, 0444, battery_percentage_show, NULL);
+static DEVICE_ATTR(battery_voltage, 0444, battery_voltage_show, NULL);
+
+extern void (*apm_get_power_status)(struct apm_power_info *);
+
+static void sharpsl_apm_get_power_status(struct apm_power_info *info)
+{
+	info->ac_line_status = sharpsl_pm.battstat.ac_status;
+
+	if (sharpsl_pm.charge_mode == CHRG_ON)
+		info->battery_status = APM_BATTERY_STATUS_CHARGING;
+	else
+		info->battery_status = sharpsl_pm.battstat.mainbat_status;
+
+	info->battery_flag = (1 << info->battery_status);
+	info->battery_life = sharpsl_pm.battstat.mainbat_percent;
+}
+
+#ifdef CONFIG_PM
+static struct platform_suspend_ops sharpsl_pm_ops = {
+	.prepare	= pxa_pm_prepare,
+	.finish		= pxa_pm_finish,
+	.enter		= corgi_pxa_pm_enter,
+	.valid		= suspend_valid_only_mem,
+};
+#endif
+
+static int __init sharpsl_pm_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	if (!pdev->dev.platform_data)
+		return -EINVAL;
+
+	sharpsl_pm.dev = &pdev->dev;
+	sharpsl_pm.machinfo = pdev->dev.platform_data;
+	sharpsl_pm.charge_mode = CHRG_OFF;
+	sharpsl_pm.flags = 0;
+
+	init_timer(&sharpsl_pm.ac_timer);
+	sharpsl_pm.ac_timer.function = sharpsl_ac_timer;
+
+	init_timer(&sharpsl_pm.chrg_full_timer);
+	sharpsl_pm.chrg_full_timer.function = sharpsl_chrg_full_timer;
+
+	led_trigger_register_simple("sharpsl-charge", &sharpsl_charge_led_trigger);
+
+	sharpsl_pm.machinfo->init();
+
+	gpio_request(sharpsl_pm.machinfo->gpio_acin, "AC IN");
+	gpio_direction_input(sharpsl_pm.machinfo->gpio_acin);
+	gpio_request(sharpsl_pm.machinfo->gpio_batfull, "Battery Full");
+	gpio_direction_input(sharpsl_pm.machinfo->gpio_batfull);
+	gpio_request(sharpsl_pm.machinfo->gpio_batlock, "Battery Lock");
+	gpio_direction_input(sharpsl_pm.machinfo->gpio_batlock);
 
 	/* Register interrupt handlers */
-	if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, IRQF_DISABLED, "AC Input Detect", sharpsl_ac_isr)) {
+	if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "AC Input Detect", sharpsl_ac_isr)) {
 		dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin));
 	}
-	else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin),IRQ_TYPE_EDGE_BOTH);
 
-	if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED, "Battery Cover", sharpsl_fatal_isr)) {
+	if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Battery Cover", sharpsl_fatal_isr)) {
 		dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock));
 	}
-	else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock),IRQ_TYPE_EDGE_FALLING);
 
 	if (sharpsl_pm.machinfo->gpio_fatal) {
-		if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED, "Fatal Battery", sharpsl_fatal_isr)) {
+		if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Fatal Battery", sharpsl_fatal_isr)) {
 			dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal));
 		}
-		else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal),IRQ_TYPE_EDGE_FALLING);
 	}
 
 	if (sharpsl_pm.machinfo->batfull_irq)
 	{
 		/* Register interrupt handler. */
-		if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, IRQF_DISABLED, "CO", sharpsl_chrg_full_isr)) {
+		if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING, "CO", sharpsl_chrg_full_isr)) {
 			dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull));
 		}
-		else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQ_TYPE_EDGE_RISING);
 	}
+
+	ret = device_create_file(&pdev->dev, &dev_attr_battery_percentage);
+	ret |= device_create_file(&pdev->dev, &dev_attr_battery_voltage);
+	if (ret != 0)
+		dev_warn(&pdev->dev, "Failed to register attributes (%d)\n", ret);
+
+	apm_get_power_status = sharpsl_apm_get_power_status;
+
+#ifdef CONFIG_PM
+	suspend_set_ops(&sharpsl_pm_ops);
+#endif
+
+	mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250));
+
+	return 0;
 }
 
-void sharpsl_pm_pxa_remove(void)
+static int sharpsl_pm_remove(struct platform_device *pdev)
 {
+	suspend_set_ops(NULL);
+
+	device_remove_file(&pdev->dev, &dev_attr_battery_percentage);
+	device_remove_file(&pdev->dev, &dev_attr_battery_voltage);
+
+	led_trigger_unregister_simple(sharpsl_charge_led_trigger);
+
 	free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr);
 	free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr);
 
@@ -188,4 +984,39 @@
 
 	if (sharpsl_pm.machinfo->batfull_irq)
 		free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr);
+
+	gpio_free(sharpsl_pm.machinfo->gpio_batlock);
+	gpio_free(sharpsl_pm.machinfo->gpio_batfull);
+	gpio_free(sharpsl_pm.machinfo->gpio_acin);
+
+	if (sharpsl_pm.machinfo->exit)
+		sharpsl_pm.machinfo->exit();
+
+	del_timer_sync(&sharpsl_pm.chrg_full_timer);
+	del_timer_sync(&sharpsl_pm.ac_timer);
+
+	return 0;
 }
+
+static struct platform_driver sharpsl_pm_driver = {
+	.probe		= sharpsl_pm_probe,
+	.remove		= sharpsl_pm_remove,
+	.suspend	= sharpsl_pm_suspend,
+	.resume		= sharpsl_pm_resume,
+	.driver		= {
+		.name		= "sharpsl-pm",
+	},
+};
+
+static int __devinit sharpsl_pm_init(void)
+{
+	return platform_driver_register(&sharpsl_pm_driver);
+}
+
+static void sharpsl_pm_exit(void)
+{
+	platform_driver_unregister(&sharpsl_pm_driver);
+}
+
+late_initcall(sharpsl_pm_init);
+module_exit(sharpsl_pm_exit);
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 5a45fe3..dda310f 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -13,19 +13,11 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
-#include <linux/major.h>
-#include <linux/fs.h>
-#include <linux/interrupt.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
-#include <linux/mmc/host.h>
 #include <linux/mtd/physmap.h>
-#include <linux/pm.h>
-#include <linux/backlight.h>
-#include <linux/io.h>
 #include <linux/i2c.h>
 #include <linux/i2c/pca953x.h>
 #include <linux/spi/spi.h>
@@ -34,31 +26,22 @@
 #include <linux/mtd/sharpsl.h>
 
 #include <asm/setup.h>
-#include <asm/memory.h>
 #include <asm/mach-types.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-
 #include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
+#include <asm/mach/sharpsl_param.h>
+#include <asm/hardware/scoop.h>
+
 
 #include <mach/pxa27x.h>
 #include <mach/pxa27x-udc.h>
 #include <mach/reset.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/irda.h>
 #include <mach/mmc.h>
 #include <mach/ohci.h>
-#include <mach/udc.h>
 #include <mach/pxafb.h>
 #include <mach/pxa2xx_spi.h>
 #include <mach/spitz.h>
-#include <mach/sharpsl.h>
-
-#include <asm/mach/sharpsl_param.h>
-#include <asm/hardware/scoop.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -317,13 +300,8 @@
 	.wait_for_sync		= spitz_wait_for_hsync,
 };
 
-static void spitz_ads7846_cs(u32 command)
-{
-	gpio_set_value(SPITZ_GPIO_ADS7846_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
 static struct pxa2xx_spi_chip spitz_ads7846_chip = {
-	.cs_control		= spitz_ads7846_cs,
+	.gpio_cs		= SPITZ_GPIO_ADS7846_CS,
 };
 
 static void spitz_bl_kick_battery(void)
@@ -347,22 +325,12 @@
 	.kick_battery		= spitz_bl_kick_battery,
 };
 
-static void spitz_lcdcon_cs(u32 command)
-{
-	gpio_set_value(SPITZ_GPIO_LCDCON_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
 static struct pxa2xx_spi_chip spitz_lcdcon_chip = {
-	.cs_control	= spitz_lcdcon_cs,
+	.gpio_cs	= SPITZ_GPIO_LCDCON_CS,
 };
 
-static void spitz_max1111_cs(u32 command)
-{
-	gpio_set_value(SPITZ_GPIO_MAX1111_CS, !(command == PXA2XX_CS_ASSERT));
-}
-
 static struct pxa2xx_spi_chip spitz_max1111_chip = {
-	.cs_control	= spitz_max1111_cs,
+	.gpio_cs	= SPITZ_GPIO_MAX1111_CS,
 };
 
 static struct spi_board_info spitz_spi_devices[] = {
@@ -392,30 +360,6 @@
 
 static void __init spitz_init_spi(void)
 {
-	int err;
-
-	err = gpio_request(SPITZ_GPIO_ADS7846_CS, "ADS7846_CS");
-	if (err)
-		return;
-
-	err = gpio_request(SPITZ_GPIO_LCDCON_CS, "LCDCON_CS");
-	if (err)
-		goto err_free_1;
-
-	err = gpio_request(SPITZ_GPIO_MAX1111_CS, "MAX1111_CS");
-	if (err)
-		goto err_free_2;
-
-	err = gpio_direction_output(SPITZ_GPIO_ADS7846_CS, 1);
-	if (err)
-		goto err_free_3;
-	err = gpio_direction_output(SPITZ_GPIO_LCDCON_CS, 1);
-	if (err)
-		goto err_free_3;
-	err = gpio_direction_output(SPITZ_GPIO_MAX1111_CS, 1);
-	if (err)
-		goto err_free_3;
-
 	if (machine_is_akita()) {
 		spitz_lcdcon_info.gpio_backlight_cont = AKITA_GPIO_BACKLIGHT_CONT;
 		spitz_lcdcon_info.gpio_backlight_on = AKITA_GPIO_BACKLIGHT_ON;
@@ -423,14 +367,6 @@
 
 	pxa2xx_set_spi_info(2, &spitz_spi_info);
 	spi_register_board_info(ARRAY_AND_SIZE(spitz_spi_devices));
-	return;
-
-err_free_3:
-	gpio_free(SPITZ_GPIO_MAX1111_CS);
-err_free_2:
-	gpio_free(SPITZ_GPIO_LCDCON_CS);
-err_free_1:
-	gpio_free(SPITZ_GPIO_ADS7846_CS);
 }
 #else
 static inline void spitz_init_spi(void) {}
diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c
index 2e44905..724ffb0 100644
--- a/arch/arm/mach-pxa/spitz_pm.c
+++ b/arch/arm/mach-pxa/spitz_pm.c
@@ -41,7 +41,6 @@
 {
 	pxa_gpio_mode(SPITZ_GPIO_KEY_INT | GPIO_IN);
 	pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN);
-	sharpsl_pm_pxa_init();
 }
 
 static void spitz_measure_temp(int on)
@@ -182,7 +181,7 @@
 
 struct sharpsl_charger_machinfo spitz_pm_machinfo = {
 	.init             = spitz_charger_init,
-	.exit             = sharpsl_pm_pxa_remove,
+	.exit             = NULL,
 	.gpio_batlock     = SPITZ_GPIO_BAT_COVER,
 	.gpio_acin        = SPITZ_GPIO_AC_IN,
 	.gpio_batfull     = SPITZ_GPIO_CHRG_FULL,
diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c
new file mode 100644
index 0000000..3b205b6
--- /dev/null
+++ b/arch/arm/mach-pxa/stargate2.c
@@ -0,0 +1,796 @@
+/*
+ *  linux/arch/arm/mach-pxa/stargate2.c
+ *
+ *  Author:	Ed C. Epp
+ *  Created:	Nov 05, 2002
+ *  Copyright:	Intel Corp.
+ *
+ *  Modified 2009:  Jonathan Cameron <jic23@cam.ac.uk>
+ *
+ *  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/device.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/bitops.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/machine.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/mtd/partitions.h>
+
+#include <linux/i2c/pcf857x.h>
+#include <linux/i2c/at24.h>
+#include <linux/smc91x.h>
+#include <linux/gpio.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/flash.h>
+
+#include <mach/pxa27x.h>
+#include <plat/i2c.h>
+#include <mach/mmc.h>
+#include <mach/udc.h>
+#include <mach/pxa2xx_spi.h>
+#include <mach/pxa27x-udc.h>
+
+#include <linux/spi/spi.h>
+#include <linux/mfd/da903x.h>
+#include <linux/sht15.h>
+
+#include "devices.h"
+#include "generic.h"
+
+/* Bluetooth */
+#define SG2_BT_RESET		81
+
+/* SD */
+#define SG2_GPIO_nSD_DETECT	90
+#define SG2_SD_POWER_ENABLE	89
+
+static unsigned long stargate2_pin_config[] __initdata = {
+
+	GPIO15_nCS_1, /* SRAM */
+	/* SMC91x */
+	GPIO80_nCS_4,
+	GPIO40_GPIO, /*cable detect?*/
+	/* Device Identification for wakeup*/
+	GPIO102_GPIO,
+
+	/* Button */
+	GPIO91_GPIO | WAKEUP_ON_LEVEL_HIGH,
+
+	/* DA9030 */
+	GPIO1_GPIO,
+
+	/* Compact Flash */
+	GPIO79_PSKTSEL,
+	GPIO48_nPOE,
+	GPIO49_nPWE,
+	GPIO50_nPIOR,
+	GPIO51_nPIOW,
+	GPIO85_nPCE_1,
+	GPIO54_nPCE_2,
+	GPIO55_nPREG,
+	GPIO56_nPWAIT,
+	GPIO57_nIOIS16,
+	GPIO120_GPIO, /* Buff ctrl */
+	GPIO108_GPIO, /* Power ctrl */
+	GPIO82_GPIO, /* Reset */
+	GPIO53_GPIO, /* SG2_S0_GPIO_DETECT */
+
+	/* MMC */
+	GPIO32_MMC_CLK,
+	GPIO112_MMC_CMD,
+	GPIO92_MMC_DAT_0,
+	GPIO109_MMC_DAT_1,
+	GPIO110_MMC_DAT_2,
+	GPIO111_MMC_DAT_3,
+	GPIO90_GPIO, /* nSD detect */
+	GPIO89_GPIO, /* SD_POWER_ENABLE */
+
+	/* Bluetooth */
+	GPIO81_GPIO, /* reset */
+
+	/* cc2420 802.15.4 radio */
+	GPIO22_GPIO,		/* CC_RSTN  (out)*/
+	GPIO114_GPIO,		/* CC_FIFO (in) */
+	GPIO116_GPIO, 		/* CC_CCA (in) */
+	GPIO0_GPIO,		/* CC_FIFOP (in) */
+	GPIO16_GPIO,		/* CCSFD (in) */
+	GPIO39_GPIO,		/* CSn (out) */
+
+	/* I2C */
+	GPIO117_I2C_SCL,
+	GPIO118_I2C_SDA,
+
+	/* SSP 3 - 802.15.4 radio */
+	GPIO39_GPIO, /* chip select */
+	GPIO34_SSP3_SCLK,
+	GPIO35_SSP3_TXD,
+	GPIO41_SSP3_RXD,
+
+	/* SSP 2 */
+	GPIO11_SSP2_RXD,
+	GPIO38_SSP2_TXD,
+	GPIO36_SSP2_SCLK,
+	GPIO37_GPIO, /* chip select */
+
+	/* SSP 1 */
+	GPIO26_SSP1_RXD,
+	GPIO25_SSP1_TXD,
+	GPIO23_SSP1_SCLK,
+	GPIO24_GPIO, /* chip select */
+
+	/* BTUART */
+	GPIO42_BTUART_RXD,
+	GPIO43_BTUART_TXD,
+	GPIO44_BTUART_CTS,
+	GPIO45_BTUART_RTS,
+
+	/* STUART */
+	GPIO46_STUART_RXD,
+	GPIO47_STUART_TXD,
+
+	/* Basic sensor board */
+	GPIO96_GPIO,	/* accelerometer interrupt */
+	GPIO99_GPIO,	/* ADC interrupt */
+
+	/* Connector pins specified as gpios */
+	GPIO94_GPIO, /* large basic connector pin 14 */
+	GPIO10_GPIO, /* large basic connector pin 23 */
+
+	/* SHT15 */
+	GPIO100_GPIO,
+	GPIO98_GPIO,
+};
+
+/**
+ * stargate2_reset_bluetooth() reset the bluecore to ensure consistent state
+ **/
+static int stargate2_reset_bluetooth(void)
+{
+	int err;
+	err = gpio_request(SG2_BT_RESET, "SG2_BT_RESET");
+	if (err) {
+		printk(KERN_ERR "Could not get gpio for bluetooth reset \n");
+		return err;
+	}
+	gpio_direction_output(SG2_BT_RESET, 1);
+	mdelay(5);
+	/* now reset it - 5 msec minimum */
+	gpio_set_value(SG2_BT_RESET, 0);
+	mdelay(10);
+	gpio_set_value(SG2_BT_RESET, 1);
+	gpio_free(SG2_BT_RESET);
+	return 0;
+}
+
+static struct led_info stargate2_leds[] = {
+	{
+		.name = "sg2:red",
+		.flags = DA9030_LED_RATE_ON,
+	}, {
+		.name = "sg2:blue",
+		.flags = DA9030_LED_RATE_ON,
+	}, {
+		.name = "sg2:green",
+		.flags = DA9030_LED_RATE_ON,
+	},
+};
+
+static struct sht15_platform_data platform_data_sht15 = {
+	.gpio_data =  100,
+	.gpio_sck  =  98,
+};
+
+static struct platform_device sht15 = {
+	.name = "sht15",
+	.id = -1,
+	.dev = {
+		.platform_data = &platform_data_sht15,
+	},
+};
+
+static struct regulator_consumer_supply stargate2_sensor_3_con[] = {
+	{
+		.dev = &sht15.dev,
+		.supply = "vcc",
+	},
+};
+
+enum stargate2_ldos{
+	vcc_vref,
+	vcc_cc2420,
+	/* a mote connector? */
+	vcc_mica,
+	/* the CSR bluecore chip */
+	vcc_bt,
+	/* The two voltages available to sensor boards */
+	vcc_sensor_1_8,
+	vcc_sensor_3,
+	/* directly connected to the pxa27x */
+	vcc_sram_ext,
+	vcc_pxa_pll,
+	vcc_pxa_usim, /* Reference voltage for certain gpios */
+	vcc_pxa_mem,
+	vcc_pxa_flash,
+	vcc_pxa_core, /*Dc-Dc buck not yet supported */
+	vcc_lcd,
+	vcc_bb,
+	vcc_bbio, /*not sure!*/
+	vcc_io, /* cc2420 802.15.4 radio and pxa vcc_io ?*/
+};
+
+/* The values of the various regulator constraints are obviously dependent
+ * on exactly what is wired to each ldo.  Unfortunately this information is
+ * not generally available.  More information has been requested from Xbow.
+ */
+static struct regulator_init_data stargate2_ldo_init_data[] = {
+	[vcc_bbio] = {
+		.constraints = { /* board default 1.8V */
+			.name = "vcc_bbio",
+			.min_uV = 1800000,
+			.max_uV = 1800000,
+		},
+	},
+	[vcc_bb] = {
+		.constraints = { /* board default 2.8V */
+			.name = "vcc_bb",
+			.min_uV = 2700000,
+			.max_uV = 3000000,
+		},
+	},
+	[vcc_pxa_flash] = {
+		.constraints = {/* default is 1.8V */
+			.name = "vcc_pxa_flash",
+			.min_uV = 1800000,
+			.max_uV = 1800000,
+		},
+	},
+	[vcc_cc2420] = { /* also vcc_io */
+		.constraints = {
+			/* board default is 2.8V */
+			.name = "vcc_cc2420",
+			.min_uV = 2700000,
+			.max_uV = 3300000,
+		},
+	},
+	[vcc_vref] = { /* Reference for what? */
+		.constraints = { /* default 1.8V */
+			.name = "vcc_vref",
+			.min_uV = 1800000,
+			.max_uV = 1800000,
+		},
+	},
+	[vcc_sram_ext] = {
+		.constraints = { /* default 2.8V */
+			.name = "vcc_sram_ext",
+			.min_uV = 2800000,
+			.max_uV = 2800000,
+		},
+	},
+	[vcc_mica] = {
+		.constraints = { /* default 2.8V */
+			.name = "vcc_mica",
+			.min_uV = 2800000,
+			.max_uV = 2800000,
+		},
+	},
+	[vcc_bt] = {
+		.constraints = { /* default 2.8V */
+			.name = "vcc_bt",
+			.min_uV = 2800000,
+			.max_uV = 2800000,
+		},
+	},
+	[vcc_lcd] = {
+		.constraints = { /* default 2.8V */
+			.name = "vcc_lcd",
+			.min_uV = 2700000,
+			.max_uV = 3300000,
+		},
+	},
+	[vcc_io] = { /* Same or higher than everything
+			  * bar vccbat and vccusb */
+		.constraints = { /* default 2.8V */
+			.name = "vcc_io",
+			.min_uV = 2692000,
+			.max_uV = 3300000,
+		},
+	},
+	[vcc_sensor_1_8] = {
+		.constraints = { /* default 1.8V */
+			.name = "vcc_sensor_1_8",
+			.min_uV = 1800000,
+			.max_uV = 1800000,
+		},
+	},
+	[vcc_sensor_3] = { /* curiously default 2.8V */
+		.constraints = {
+			.name = "vcc_sensor_3",
+			.min_uV = 2800000,
+			.max_uV = 3000000,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(stargate2_sensor_3_con),
+		.consumer_supplies = stargate2_sensor_3_con,
+	},
+	[vcc_pxa_pll] = { /* 1.17V - 1.43V, default 1.3V*/
+		.constraints = {
+			.name = "vcc_pxa_pll",
+			.min_uV = 1170000,
+			.max_uV = 1430000,
+		},
+	},
+	[vcc_pxa_usim] = {
+		.constraints = { /* default 1.8V */
+			.name = "vcc_pxa_usim",
+			.min_uV = 1710000,
+			.max_uV = 2160000,
+		},
+	},
+	[vcc_pxa_mem] = {
+		.constraints = { /* default 1.8V */
+			.name = "vcc_pxa_mem",
+			.min_uV = 1800000,
+			.max_uV = 1800000,
+		},
+	},
+};
+
+static struct da903x_subdev_info stargate2_da9030_subdevs[] = {
+	{
+		.name = "da903x-led",
+		.id = DA9030_ID_LED_2,
+		.platform_data = &stargate2_leds[0],
+	}, {
+		.name = "da903x-led",
+		.id = DA9030_ID_LED_3,
+		.platform_data = &stargate2_leds[2],
+	}, {
+		.name = "da903x-led",
+		.id = DA9030_ID_LED_4,
+		.platform_data = &stargate2_leds[1],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO2,
+		.platform_data = &stargate2_ldo_init_data[vcc_bbio],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO3,
+		.platform_data = &stargate2_ldo_init_data[vcc_bb],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO4,
+		.platform_data = &stargate2_ldo_init_data[vcc_pxa_flash],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO5,
+		.platform_data = &stargate2_ldo_init_data[vcc_cc2420],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO6,
+		.platform_data = &stargate2_ldo_init_data[vcc_vref],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO7,
+		.platform_data = &stargate2_ldo_init_data[vcc_sram_ext],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO8,
+		.platform_data = &stargate2_ldo_init_data[vcc_mica],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO9,
+		.platform_data = &stargate2_ldo_init_data[vcc_bt],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO10,
+		.platform_data = &stargate2_ldo_init_data[vcc_sensor_1_8],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO11,
+		.platform_data = &stargate2_ldo_init_data[vcc_sensor_3],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO12,
+		.platform_data = &stargate2_ldo_init_data[vcc_lcd],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO15,
+		.platform_data = &stargate2_ldo_init_data[vcc_pxa_pll],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO17,
+		.platform_data = &stargate2_ldo_init_data[vcc_pxa_usim],
+	}, {
+		.name = "da903x-regulator", /*pxa vcc i/o and cc2420 vcc i/o */
+		.id = DA9030_ID_LDO18,
+		.platform_data = &stargate2_ldo_init_data[vcc_io],
+	}, {
+		.name = "da903x-regulator",
+		.id = DA9030_ID_LDO19,
+		.platform_data = &stargate2_ldo_init_data[vcc_pxa_mem],
+	},
+};
+
+static struct da903x_platform_data stargate2_da9030_pdata = {
+	.num_subdevs = ARRAY_SIZE(stargate2_da9030_subdevs),
+	.subdevs = stargate2_da9030_subdevs,
+};
+
+static struct resource smc91x_resources[] = {
+	[0] = {
+		.name = "smc91x-regs",
+		.start = (PXA_CS4_PHYS + 0x300),
+		.end = (PXA_CS4_PHYS + 0xfffff),
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_GPIO(40),
+		.end = IRQ_GPIO(40),
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	}
+};
+
+static struct smc91x_platdata stargate2_smc91x_info = {
+	.flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT
+	| SMC91X_NOWAIT | SMC91X_USE_DMA,
+};
+
+static struct platform_device smc91x_device = {
+	.name = "smc91x",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(smc91x_resources),
+	.resource = smc91x_resources,
+	.dev = {
+		.platform_data = &stargate2_smc91x_info,
+	},
+};
+
+
+
+static struct pxamci_platform_data stargate2_mci_platform_data;
+
+/*
+ * The card detect interrupt isn't debounced so we delay it by 250ms
+ * to give the card a chance to fully insert / eject.
+ */
+static int stargate2_mci_init(struct device *dev,
+			      irq_handler_t stargate2_detect_int,
+			      void *data)
+{
+	int err;
+
+	err = gpio_request(SG2_SD_POWER_ENABLE, "SG2_sd_power_enable");
+	if (err) {
+		printk(KERN_ERR "Can't get the gpio for SD power control");
+		goto return_err;
+	}
+	gpio_direction_output(SG2_SD_POWER_ENABLE, 0);
+
+	err = gpio_request(SG2_GPIO_nSD_DETECT, "SG2_sd_detect");
+	if (err) {
+		printk(KERN_ERR "Can't get the sd detect gpio");
+		goto free_power_en;
+	}
+	gpio_direction_input(SG2_GPIO_nSD_DETECT);
+	/* Delay to allow for full insertion */
+	stargate2_mci_platform_data.detect_delay = msecs_to_jiffies(250);
+
+	err = request_irq(IRQ_GPIO(SG2_GPIO_nSD_DETECT),
+			  stargate2_detect_int,
+			  IRQ_TYPE_EDGE_BOTH,
+			  "MMC card detect",
+			  data);
+	if (err) {
+		printk(KERN_ERR "can't request MMC card detect IRQ\n");
+		goto free_nsd_detect;
+	}
+	return 0;
+
+ free_nsd_detect:
+	gpio_free(SG2_GPIO_nSD_DETECT);
+ free_power_en:
+	gpio_free(SG2_SD_POWER_ENABLE);
+ return_err:
+	return err;
+}
+
+/**
+ * stargate2_mci_setpower() - set state of mmc power supply
+ *
+ * Very simple control. Either it is on or off and is controlled by
+ * a gpio pin */
+static void stargate2_mci_setpower(struct device *dev, unsigned int vdd)
+{
+	gpio_set_value(SG2_SD_POWER_ENABLE, !!vdd);
+}
+
+static void stargate2_mci_exit(struct device *dev, void *data)
+{
+	free_irq(IRQ_GPIO(SG2_GPIO_nSD_DETECT), data);
+	gpio_free(SG2_SD_POWER_ENABLE);
+	gpio_free(SG2_GPIO_nSD_DETECT);
+}
+
+static struct pxamci_platform_data stargate2_mci_platform_data = {
+	.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
+	.init = stargate2_mci_init,
+	.setpower = stargate2_mci_setpower,
+	.exit = stargate2_mci_exit,
+};
+
+static struct mtd_partition stargate2flash_partitions[] = {
+	{
+		.name = "Bootloader",
+		.size = 0x00040000,
+		.offset = 0,
+		.mask_flags = 0,
+	}, {
+		.name = "Kernel",
+		.size = 0x00200000,
+		.offset = 0x00040000,
+		.mask_flags = 0
+	}, {
+		.name = "Filesystem",
+		.size = 0x01DC0000,
+		.offset = 0x00240000,
+		.mask_flags = 0
+	},
+};
+
+static struct resource flash_resources = {
+	.start = PXA_CS0_PHYS,
+	.end = PXA_CS0_PHYS + SZ_32M - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct flash_platform_data stargate2_flash_data = {
+	.map_name = "cfi_probe",
+	.parts = stargate2flash_partitions,
+	.nr_parts = ARRAY_SIZE(stargate2flash_partitions),
+	.name = "PXA27xOnChipROM",
+	.width = 2,
+};
+
+static struct platform_device stargate2_flash_device = {
+	.name = "pxa2xx-flash",
+	.id = 0,
+	.dev = {
+		.platform_data = &stargate2_flash_data,
+	},
+	.resource = &flash_resources,
+	.num_resources = 1,
+};
+
+/*
+ * SRAM - The Stargate 2 has 32MB of SRAM.
+ *
+ * Here it is made available as an MTD. This will then
+ * typically have a cifs filesystem created on it to provide
+ * fast temporary storage.
+ */
+static struct resource sram_resources = {
+	.start = PXA_CS1_PHYS,
+	.end = PXA_CS1_PHYS + SZ_32M-1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platdata_mtd_ram stargate2_sram_pdata = {
+	.mapname = "Stargate2 SRAM",
+	.bankwidth = 2,
+};
+
+static struct platform_device stargate2_sram = {
+	.name = "mtd-ram",
+	.id = 0,
+	.resource = &sram_resources,
+	.num_resources = 1,
+	.dev = {
+		.platform_data = &stargate2_sram_pdata,
+	},
+};
+
+static struct pcf857x_platform_data platform_data_pcf857x = {
+	.gpio_base = 128,
+	.n_latch = 0,
+	.setup = NULL,
+	.teardown = NULL,
+	.context = NULL,
+};
+
+static struct at24_platform_data pca9500_eeprom_pdata = {
+	.byte_len = 256,
+	.page_size = 4,
+};
+
+
+static struct i2c_board_info __initdata stargate2_i2c_board_info[] = {
+	/* Techically this a pca9500 - but it's compatible with the 8574
+	 * for gpio expansion and the 24c02 for eeprom access.
+	 */
+	{
+		.type = "pcf8574",
+		.addr =  0x27,
+		.platform_data = &platform_data_pcf857x,
+	}, {
+		.type = "24c02",
+		.addr = 0x57,
+		.platform_data = &pca9500_eeprom_pdata,
+	}, {
+		.type = "max1238",
+		.addr = 0x35,
+	}, { /* ITS400 Sensor board only */
+		.type = "max1363",
+		.addr = 0x34,
+		/* Through a nand gate - Also beware, on V2 sensor board the
+		 * pull up resistors are missing.
+		 */
+		.irq = IRQ_GPIO(99),
+	}, { /* ITS400 Sensor board only */
+		.type = "tsl2561",
+		.addr = 0x49,
+		/* Through a nand gate - Also beware, on V2 sensor board the
+		 * pull up resistors are missing.
+		 */
+		.irq = IRQ_GPIO(99),
+	}, { /* ITS400 Sensor board only */
+		.type = "tmp175",
+		.addr = 0x4A,
+		.irq = IRQ_GPIO(96),
+	},
+};
+
+static struct i2c_board_info __initdata stargate2_pwr_i2c_board_info[] = {
+	{
+		.type = "da9030",
+		.addr = 0x49,
+		.platform_data = &stargate2_da9030_pdata,
+		.irq = gpio_to_irq(1),
+	},
+};
+
+static struct pxa2xx_spi_master pxa_ssp_master_0_info = {
+	.num_chipselect = 1,
+};
+
+static struct pxa2xx_spi_master pxa_ssp_master_1_info = {
+	.num_chipselect = 1,
+};
+
+static struct pxa2xx_spi_master pxa_ssp_master_2_info = {
+	.num_chipselect = 1,
+};
+
+/* An upcoming kernel change will scrap SFRM usage so these
+ * drivers have been moved to use gpio's via cs_control */
+static struct pxa2xx_spi_chip staccel_chip_info = {
+	.tx_threshold = 8,
+	.rx_threshold = 8,
+	.dma_burst_size = 8,
+	.timeout = 235,
+	.gpio_cs = 24,
+};
+
+static struct pxa2xx_spi_chip cc2420_info = {
+	.tx_threshold = 8,
+	.rx_threshold = 8,
+	.dma_burst_size = 8,
+	.timeout = 235,
+	.gpio_cs = 39,
+};
+
+static struct spi_board_info spi_board_info[] __initdata = {
+	{
+		.modalias = "lis3l02dq",
+		.max_speed_hz = 8000000,/* 8MHz max spi frequency at 3V */
+		.bus_num = 1,
+		.chip_select = 0,
+		.controller_data = &staccel_chip_info,
+		.irq = IRQ_GPIO(96),
+	}, {
+		.modalias = "cc2420",
+		.max_speed_hz = 6500000,
+		.bus_num = 3,
+		.chip_select = 0,
+		.controller_data = &cc2420_info,
+	},
+};
+
+static void sg2_udc_command(int cmd)
+{
+	switch (cmd) {
+	case PXA2XX_UDC_CMD_CONNECT:
+		UP2OCR |=  UP2OCR_HXOE  | UP2OCR_DPPUE | UP2OCR_DPPUBE;
+		break;
+	case PXA2XX_UDC_CMD_DISCONNECT:
+		UP2OCR &= ~(UP2OCR_HXOE  | UP2OCR_DPPUE | UP2OCR_DPPUBE);
+		break;
+	}
+}
+
+/* Board doesn't support cable detection - so always lie and say
+ * something is there.
+ */
+static int sg2_udc_detect(void)
+{
+	return 1;
+}
+
+static struct pxa2xx_udc_mach_info stargate2_udc_info __initdata = {
+	.udc_is_connected	= sg2_udc_detect,
+	.udc_command		= sg2_udc_command,
+};
+
+static struct platform_device *stargate2_devices[] = {
+	&stargate2_flash_device,
+	&stargate2_sram,
+	&smc91x_device,
+	&sht15,
+};
+
+static struct i2c_pxa_platform_data i2c_pwr_pdata = {
+	.fast_mode = 1,
+};
+
+static struct i2c_pxa_platform_data i2c_pdata = {
+	.fast_mode = 1,
+};
+
+static void __init stargate2_init(void)
+{
+	/* This is probably a board specific hack as this must be set
+	   prior to connecting the MFP stuff up. */
+	MECR &= ~MECR_NOS;
+
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(stargate2_pin_config));
+
+	/* spi chip selects */
+	gpio_direction_output(37, 0);
+	gpio_direction_output(24, 0);
+	gpio_direction_output(39, 0);
+
+	platform_add_devices(ARRAY_AND_SIZE(stargate2_devices));
+
+	pxa2xx_set_spi_info(1, &pxa_ssp_master_0_info);
+	pxa2xx_set_spi_info(2, &pxa_ssp_master_1_info);
+	pxa2xx_set_spi_info(3, &pxa_ssp_master_2_info);
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+
+	i2c_register_board_info(0, ARRAY_AND_SIZE(stargate2_i2c_board_info));
+	i2c_register_board_info(1,
+				ARRAY_AND_SIZE(stargate2_pwr_i2c_board_info));
+	pxa27x_set_i2c_power_info(&i2c_pwr_pdata);
+	pxa_set_i2c_info(&i2c_pdata);
+
+	pxa_set_mci_info(&stargate2_mci_platform_data);
+
+	pxa_set_udc_info(&stargate2_udc_info);
+
+	stargate2_reset_bluetooth();
+}
+
+MACHINE_START(STARGATE2, "Stargate 2")
+	.phys_io = 0x40000000,
+	.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.map_io = pxa_map_io,
+	.init_irq = pxa27x_init_irq,
+	.timer = &pxa_timer,
+	.init_machine = stargate2_init,
+	.boot_params = 0xA0000100,
+MACHINE_END
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index a0bd46e..168267a 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -40,7 +40,7 @@
 #include <mach/pxa25x.h>
 #include <mach/reset.h>
 #include <mach/irda.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
 #include <mach/tosa_bt.h>
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index f79c9cb..825f540 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -47,7 +47,7 @@
 #include <mach/mmc.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 
 #include "generic.h"
 #include "devices.h"
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index dd031cc..d33c232 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -45,7 +45,7 @@
 #include <mach/pxa25x.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/regs-uart.h>
 #include <mach/viper.h>
 
diff --git a/arch/arm/mach-pxa/zylonite_pxa300.c b/arch/arm/mach-pxa/zylonite_pxa300.c
index c256c57..cefd1c0 100644
--- a/arch/arm/mach-pxa/zylonite_pxa300.c
+++ b/arch/arm/mach-pxa/zylonite_pxa300.c
@@ -21,7 +21,7 @@
 #include <linux/gpio.h>
 
 #include <mach/pxa300.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
 #include <mach/zylonite.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-sa1100/collie_pm.c b/arch/arm/mach-sa1100/collie_pm.c
deleted file mode 100644
index 444f266..0000000
--- a/arch/arm/mach-sa1100/collie_pm.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Based on spitz_pm.c and sharp code.
- *
- * Copyright (C) 2001  SHARP
- * Copyright 2005 Pavel Machek <pavel@suse.cz>
- *
- * Distribute under GPLv2.
- *
- * Li-ion batteries are angry beasts, and they like to explode. This driver is not finished,
- * and sometimes charges them when it should not. If it makes angry lithium to come your way...
- * ...well, you have been warned.
- *
- * Actually, this should be quite safe, it seems sharp leaves charger enabled by default,
- * and my collie did not explode (yet).
- */
-
-#include <linux/module.h>
-#include <linux/stat.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <asm/hardware/scoop.h>
-#include <mach/dma.h>
-#include <mach/collie.h>
-#include <asm/mach/sharpsl_param.h>
-#include <asm/hardware/sharpsl_pm.h>
-
-#include "../drivers/mfd/ucb1x00.h"
-
-static struct ucb1x00 *ucb;
-static int ad_revise;
-
-#define ADCtoPower(x)	       ((330 * x * 2) / 1024)
-
-static void collie_charger_init(void)
-{
-	int err;
-
-	if (sharpsl_param.adadj != -1)
-		ad_revise = sharpsl_param.adadj;
-
-	/* Register interrupt handler. */
-	if ((err = request_irq(COLLIE_IRQ_GPIO_AC_IN, sharpsl_ac_isr, IRQF_DISABLED,
-			       "ACIN", sharpsl_ac_isr))) {
-		printk("Could not get irq %d.\n", COLLIE_IRQ_GPIO_AC_IN);
-		return;
-	}
-	if ((err = request_irq(COLLIE_IRQ_GPIO_CO, sharpsl_chrg_full_isr, IRQF_DISABLED,
-			       "CO", sharpsl_chrg_full_isr))) {
-		free_irq(COLLIE_IRQ_GPIO_AC_IN, sharpsl_ac_isr);
-		printk("Could not get irq %d.\n", COLLIE_IRQ_GPIO_CO);
-		return;
-	}
-
-	gpio_request(COLLIE_GPIO_CHARGE_ON, "charge on");
-	gpio_direction_output(COLLIE_GPIO_CHARGE_ON, 1);
-
-	ucb1x00_io_set_dir(ucb, 0, COLLIE_TC35143_GPIO_MBAT_ON | COLLIE_TC35143_GPIO_TMP_ON |
-			           COLLIE_TC35143_GPIO_BBAT_ON);
-	return;
-}
-
-static void collie_measure_temp(int on)
-{
-	if (on)
-		ucb1x00_io_write(ucb, COLLIE_TC35143_GPIO_TMP_ON, 0);
-	else
-		ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_TMP_ON);
-}
-
-static void collie_charge(int on)
-{
-	/* Zaurus seems to contain LTC1731; it should know when to
-	 * stop charging itself, so setting charge on should be
-	 * relatively harmless (as long as it is not done too often).
-	 */
-	gpio_set_value(COLLIE_GPIO_CHARGE_ON, on);
-}
-
-static void collie_discharge(int on)
-{
-}
-
-static void collie_discharge1(int on)
-{
-}
-
-static void collie_presuspend(void)
-{
-}
-
-static void collie_postsuspend(void)
-{
-}
-
-static int collie_should_wakeup(unsigned int resume_on_alarm)
-{
-	return 0;
-}
-
-static unsigned long collie_charger_wakeup(void)
-{
-	return 0;
-}
-
-int collie_read_backup_battery(void)
-{
-	int voltage;
-
-	ucb1x00_adc_enable(ucb);
-
-	ucb1x00_io_write(ucb, COLLIE_TC35143_GPIO_BBAT_ON, 0);
-	voltage = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD1, UCB_SYNC);
-
-	ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_BBAT_ON);
-	ucb1x00_adc_disable(ucb);
-
-	printk("Backup battery = %d(%d)\n", ADCtoPower(voltage), voltage);
-
-	return ADCtoPower(voltage);
-}
-
-int collie_read_main_battery(void)
-{
-	int voltage, voltage_rev, voltage_volts;
-
-	ucb1x00_adc_enable(ucb);
-	ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_BBAT_ON);
-	ucb1x00_io_write(ucb, COLLIE_TC35143_GPIO_MBAT_ON, 0);
-
-	mdelay(1);
-	voltage = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD1, UCB_SYNC);
-
-	ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_MBAT_ON);
-	ucb1x00_adc_disable(ucb);
-
-	voltage_rev = voltage + ((ad_revise * voltage) / 652);
-	voltage_volts = ADCtoPower(voltage_rev);
-
-	printk("Main battery = %d(%d)\n", voltage_volts, voltage);
-
-	if (voltage != -1)
-		return voltage_volts;
-	else
-		return voltage;
-}
-
-int collie_read_temp(void)
-{
-	int voltage;
-
-	/* According to Sharp, temp must be > 973, main battery must be < 465,
-	   FIXME: sharpsl_pm.c has both conditions negated? FIXME: values
-	   are way out of range? */
-
-	ucb1x00_adc_enable(ucb);
-	ucb1x00_io_write(ucb, COLLIE_TC35143_GPIO_TMP_ON, 0);
-	/* >1010 = battery removed, 460 = 22C ?, higher = lower temp ? */
-	voltage = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD0, UCB_SYNC);
-	ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_TMP_ON);
-	ucb1x00_adc_disable(ucb);
-
-	printk("Battery temp = %d\n", voltage);
-	return voltage;
-}
-
-static unsigned long read_devdata(int which)
-{
-	switch (which) {
-	case SHARPSL_BATT_VOLT:
-		return collie_read_main_battery();
-	case SHARPSL_BATT_TEMP:
-		return collie_read_temp();
-	case SHARPSL_ACIN_VOLT:
-		return 500;
-	case SHARPSL_STATUS_ACIN: {
-		int ret = GPLR & COLLIE_GPIO_AC_IN;
-		printk("AC status = %d\n", ret);
-		return ret;
-	}
-	case SHARPSL_STATUS_FATAL: {
-		int ret = GPLR & COLLIE_GPIO_MAIN_BAT_LOW;
-		printk("Fatal bat = %d\n", ret);
-		return ret;
-	}
-	default:
-		return ~0;
-	}
-}
-
-struct battery_thresh collie_battery_levels_acin[] = {
-	{ 420, 100},
-	{ 417,  95},
-	{ 415,  90},
-	{ 413,  80},
-	{ 411,  75},
-	{ 408,  70},
-	{ 406,  60},
-	{ 403,  50},
-	{ 398,  40},
-	{ 391,  25},
-	{  10,   5},
-	{   0,   0},
-};
-
-struct battery_thresh collie_battery_levels[] = {
-	{ 394, 100},
-	{ 390,  95},
-	{ 380,  90},
-	{ 370,  80},
-	{ 368,  75},	/* From sharp code: battery high with frontlight */
-	{ 366,  70},	/* 60..90 -- fake values invented by me for testing */
-	{ 364,  60},
-	{ 362,  50},
-	{ 360,  40},
-	{ 358,  25},	/* From sharp code: battery low with frontlight */
-	{ 356,   5},	/* From sharp code: battery verylow with frontlight */
-	{   0,   0},
-};
-
-struct sharpsl_charger_machinfo collie_pm_machinfo = {
-	.init             = collie_charger_init,
-	.read_devdata	  = read_devdata,
-	.discharge        = collie_discharge,
-	.discharge1       = collie_discharge1,
-	.charge           = collie_charge,
-	.measure_temp     = collie_measure_temp,
-	.presuspend       = collie_presuspend,
-	.postsuspend      = collie_postsuspend,
-	.charger_wakeup   = collie_charger_wakeup,
-	.should_wakeup    = collie_should_wakeup,
-	.bat_levels       = 12,
-	.bat_levels_noac  = collie_battery_levels,
-	.bat_levels_acin  = collie_battery_levels_acin,
-	.status_high_acin = 368,
-	.status_low_acin  = 358,
-	.status_high_noac = 368,
-	.status_low_noac  = 358,
-	.charge_on_volt	  = 350,	/* spitz uses 2.90V, but lets play it safe. */
-	.charge_on_temp   = 550,
-	.charge_acin_high = 550,	/* collie does not seem to have sensor for this, anyway */
-	.charge_acin_low  = 450,	/* ignored, too */
-	.fatal_acin_volt  = 356,
-	.fatal_noacin_volt = 356,
-
-	.batfull_irq = 1,		/* We do not want periodical charge restarts */
-};
-
-static int __init collie_pm_ucb_add(struct ucb1x00_dev *pdev)
-{
-	sharpsl_pm.machinfo = &collie_pm_machinfo;
-	ucb = pdev->ucb;
-	return 0;
-}
-
-static struct ucb1x00_driver collie_pm_ucb_driver = {
-	.add	= collie_pm_ucb_add,
-};
-
-static struct platform_device *collie_pm_device;
-
-static int __init collie_pm_init(void)
-{
-	int ret;
-
-	collie_pm_device = platform_device_alloc("sharpsl-pm", -1);
-	if (!collie_pm_device)
-		return -ENOMEM;
-
-	collie_pm_device->dev.platform_data = &collie_pm_machinfo;
-	ret = platform_device_add(collie_pm_device);
-
-	if (ret)
-		platform_device_put(collie_pm_device);
-
-	if (!ret)
-		ret = ucb1x00_register_driver(&collie_pm_ucb_driver);
-
-	return ret;
-}
-
-static void __exit collie_pm_exit(void)
-{
-	ucb1x00_unregister_driver(&collie_pm_ucb_driver);
-	platform_device_unregister(collie_pm_device);
-}
-
-module_init(collie_pm_init);
-module_exit(collie_pm_exit);
diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile
index 8f2c4c7..0264bfb 100644
--- a/arch/arm/plat-pxa/Makefile
+++ b/arch/arm/plat-pxa/Makefile
@@ -7,3 +7,5 @@
 obj-$(CONFIG_GENERIC_GPIO)	+= gpio.o
 obj-$(CONFIG_PXA3xx)		+= mfp.o
 obj-$(CONFIG_ARCH_MMP)		+= mfp.o
+
+obj-$(CONFIG_HAVE_PWM)		+= pwm.o
diff --git a/arch/arm/mach-pxa/include/mach/i2c.h b/arch/arm/plat-pxa/include/plat/i2c.h
similarity index 100%
rename from arch/arm/mach-pxa/include/mach/i2c.h
rename to arch/arm/plat-pxa/include/plat/i2c.h
diff --git a/arch/arm/mach-pxa/pwm.c b/arch/arm/plat-pxa/pwm.c
similarity index 77%
rename from arch/arm/mach-pxa/pwm.c
rename to arch/arm/plat-pxa/pwm.c
index fcdd374..a9eabdc 100644
--- a/arch/arm/mach-pxa/pwm.c
+++ b/arch/arm/plat-pxa/pwm.c
@@ -21,6 +21,19 @@
 
 #include <asm/div64.h>
 
+#define HAS_SECONDARY_PWM	0x10
+#define PWM_ID_BASE(d)		((d) & 0xf)
+
+static const struct platform_device_id pwm_id_table[] = {
+	/*   PWM    has_secondary_pwm? */
+	{ "pxa25x-pwm", 0 },
+	{ "pxa27x-pwm", 0 | HAS_SECONDARY_PWM },
+	{ "pxa168-pwm", 1 },
+	{ "pxa910-pwm", 1 },
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, pwm_id_table);
+
 /* PWM registers and bits definitions */
 #define PWMCR		(0x00)
 #define PWMDCR		(0x04)
@@ -31,7 +44,8 @@
 
 struct pwm_device {
 	struct list_head	node;
-	struct platform_device *pdev;
+	struct pwm_device	*secondary;
+	struct platform_device	*pdev;
 
 	const char	*label;
 	struct clk	*clk;
@@ -159,17 +173,17 @@
 	mutex_unlock(&pwm_lock);
 }
 
-static struct pwm_device *pwm_probe(struct platform_device *pdev,
-		unsigned int pwm_id, struct pwm_device *parent_pwm)
+static int __devinit pwm_probe(struct platform_device *pdev)
 {
-	struct pwm_device *pwm;
+	struct platform_device_id *id = platform_get_device_id(pdev);
+	struct pwm_device *pwm, *secondary = NULL;
 	struct resource *r;
 	int ret = 0;
 
 	pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
 	if (pwm == NULL) {
 		dev_err(&pdev->dev, "failed to allocate memory\n");
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	pwm->clk = clk_get(&pdev->dev, NULL);
@@ -180,16 +194,9 @@
 	pwm->clk_enabled = 0;
 
 	pwm->use_count = 0;
-	pwm->pwm_id = pwm_id;
+	pwm->pwm_id = PWM_ID_BASE(id->driver_data) + pdev->id;
 	pwm->pdev = pdev;
 
-	if (parent_pwm != NULL) {
-		/* registers for the second PWM has offset of 0x10 */
-		pwm->mmio_base = parent_pwm->mmio_base + 0x10;
-		__add_pwm(pwm);
-		return pwm;
-	}
-
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (r == NULL) {
 		dev_err(&pdev->dev, "no memory resource defined\n");
@@ -211,9 +218,27 @@
 		goto err_free_mem;
 	}
 
+	if (id->driver_data & HAS_SECONDARY_PWM) {
+		secondary = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
+		if (secondary == NULL) {
+			ret = -ENOMEM;
+			goto err_free_mem;
+		}
+
+		*secondary = *pwm;
+		pwm->secondary = secondary;
+
+		/* registers for the second PWM has offset of 0x10 */
+		secondary->mmio_base = pwm->mmio_base + 0x10;
+		secondary->pwm_id = pdev->id + 2;
+	}
+
 	__add_pwm(pwm);
+	if (secondary)
+		__add_pwm(secondary);
+
 	platform_set_drvdata(pdev, pwm);
-	return pwm;
+	return 0;
 
 err_free_mem:
 	release_mem_region(r->start, r->end - r->start + 1);
@@ -221,32 +246,7 @@
 	clk_put(pwm->clk);
 err_free:
 	kfree(pwm);
-	return ERR_PTR(ret);
-}
-
-static int __devinit pxa25x_pwm_probe(struct platform_device *pdev)
-{
-	struct pwm_device *pwm = pwm_probe(pdev, pdev->id, NULL);
-
-	if (IS_ERR(pwm))
-		return PTR_ERR(pwm);
-
-	return 0;
-}
-
-static int __devinit pxa27x_pwm_probe(struct platform_device *pdev)
-{
-	struct pwm_device *pwm;
-
-	pwm = pwm_probe(pdev, pdev->id, NULL);
-	if (IS_ERR(pwm))
-		return PTR_ERR(pwm);
-
-	pwm = pwm_probe(pdev, pdev->id + 2, pwm);
-	if (IS_ERR(pwm))
-		return PTR_ERR(pwm);
-
-	return 0;
+	return ret;
 }
 
 static int __devexit pwm_remove(struct platform_device *pdev)
@@ -259,6 +259,12 @@
 		return -ENODEV;
 
 	mutex_lock(&pwm_lock);
+
+	if (pwm->secondary) {
+		list_del(&pwm->secondary->node);
+		kfree(pwm->secondary);
+	}
+
 	list_del(&pwm->node);
 	mutex_unlock(&pwm_lock);
 
@@ -272,46 +278,25 @@
 	return 0;
 }
 
-static struct platform_driver pxa25x_pwm_driver = {
+static struct platform_driver pwm_driver = {
 	.driver		= {
 		.name	= "pxa25x-pwm",
+		.owner	= THIS_MODULE,
 	},
-	.probe		= pxa25x_pwm_probe,
+	.probe		= pwm_probe,
 	.remove		= __devexit_p(pwm_remove),
-};
-
-static struct platform_driver pxa27x_pwm_driver = {
-	.driver		= {
-		.name	= "pxa27x-pwm",
-	},
-	.probe		= pxa27x_pwm_probe,
-	.remove		= __devexit_p(pwm_remove),
+	.id_table	= pwm_id_table,
 };
 
 static int __init pwm_init(void)
 {
-	int ret = 0;
-
-	ret = platform_driver_register(&pxa25x_pwm_driver);
-	if (ret) {
-		printk(KERN_ERR "failed to register pxa25x_pwm_driver\n");
-		return ret;
-	}
-
-	ret = platform_driver_register(&pxa27x_pwm_driver);
-	if (ret) {
-		printk(KERN_ERR "failed to register pxa27x_pwm_driver\n");
-		return ret;
-	}
-
-	return ret;
+	return platform_driver_register(&pwm_driver);
 }
 arch_initcall(pwm_init);
 
 static void __exit pwm_exit(void)
 {
-	platform_driver_unregister(&pxa25x_pwm_driver);
-	platform_driver_unregister(&pxa27x_pwm_driver);
+	platform_driver_unregister(&pwm_driver);
 }
 module_exit(pwm_exit);
 
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index acc7143..035a6c7 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -34,10 +34,24 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 
-#include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>
+
+/*
+ * I2C register offsets will be shifted 0 or 1 bit left, depending on
+ * different SoCs
+ */
+#define REG_SHIFT_0	(0 << 0)
+#define REG_SHIFT_1	(1 << 0)
+#define REG_SHIFT(d)	((d) & 0x1)
+
+static const struct platform_device_id i2c_pxa_id_table[] = {
+	{ "pxa2xx-i2c",		REG_SHIFT_1 },
+	{ "pxa3xx-pwri2c",	REG_SHIFT_0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
 
 /*
  * I2C registers and bit definitions
@@ -985,6 +999,7 @@
 	struct pxa_i2c *i2c;
 	struct resource *res;
 	struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
+	struct platform_device_id *id = platform_get_device_id(dev);
 	int ret;
 	int irq;
 
@@ -1028,7 +1043,7 @@
 		ret = -EIO;
 		goto eremap;
 	}
-	i2c->reg_shift = (cpu_is_pxa3xx() && (dev->id == 1)) ? 0 : 1;
+	i2c->reg_shift = REG_SHIFT(id->driver_data);
 
 	i2c->iobase = res->start;
 	i2c->iosize = res_len(res);
@@ -1150,6 +1165,7 @@
 		.name	= "pxa2xx-i2c",
 		.owner	= THIS_MODULE,
 	},
+	.id_table	= i2c_pxa_id_table,
 };
 
 static int __init i2c_adap_pxa_init(void)
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 329f890..f1f773b 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -45,7 +45,8 @@
     defined(CONFIG_MACH_ZYLONITE) ||\
     defined(CONFIG_MACH_LITTLETON) ||\
     defined(CONFIG_MACH_ZYLONITE2) ||\
-    defined(CONFIG_ARCH_VIPER)
+    defined(CONFIG_ARCH_VIPER) ||\
+    defined(CONFIG_MACH_STARGATE2)
 
 #include <asm/mach-types.h>
 
@@ -73,7 +74,7 @@
 /* We actually can't write halfwords properly if not word aligned */
 static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 {
-	if (machine_is_mainstone() && reg & 2) {
+	if ((machine_is_mainstone() || machine_is_stargate2()) && reg & 2) {
 		unsigned int v = val << 16;
 		v |= readl(ioaddr + (reg & ~2)) & 0xffff;
 		writel(v, ioaddr + (reg & ~2));
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 2764735..fbf965b 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -217,7 +217,7 @@
 	depends on ARM && ARCH_PXA && PCMCIA
 	depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \
 		    || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \
-		    || ARCH_VIPER || ARCH_PXA_ESERIES)
+		    || ARCH_VIPER || ARCH_PXA_ESERIES || MACH_STARGATE2)
 	help
 	  Say Y here to include support for the PXA2xx PCMCIA controller
 
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index bbac463..047394d 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -73,5 +73,6 @@
 pxa2xx-obj-$(CONFIG_MACH_PALMTX)		+= pxa2xx_palmtx.o
 pxa2xx-obj-$(CONFIG_MACH_PALMLD)		+= pxa2xx_palmld.o
 pxa2xx-obj-$(CONFIG_MACH_E740)			+= pxa2xx_e740.o
+pxa2xx-obj-$(CONFIG_MACH_STARGATE2)		+= pxa2xx_stargate2.o
 
 obj-$(CONFIG_PCMCIA_PXA2XX)			+= pxa2xx_core.o $(pxa2xx-obj-y)
diff --git a/drivers/pcmcia/pxa2xx_stargate2.c b/drivers/pcmcia/pxa2xx_stargate2.c
new file mode 100644
index 0000000..490749e
--- /dev/null
+++ b/drivers/pcmcia/pxa2xx_stargate2.c
@@ -0,0 +1,174 @@
+/*
+ * linux/drivers/pcmcia/pxa2xx_stargate2.c
+ *
+ * Stargate 2 PCMCIA specific routines.
+ *
+ * Created:	December 6, 2005
+ * Author:	Ed C. Epp
+ * Copyright:	Intel Corp 2005
+ *              Jonathan Cameron <jic23@cam.ac.uk> 2009
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include "soc_common.h"
+
+#define SG2_S0_BUFF_CTL		120
+#define SG2_S0_POWER_CTL	108
+#define SG2_S0_GPIO_RESET	82
+#define SG2_S0_GPIO_DETECT	53
+#define SG2_S0_GPIO_READY	81
+
+static struct pcmcia_irqs irqs[] = {
+	{ 0, IRQ_GPIO(SG2_S0_GPIO_DETECT), "PCMCIA0 CD" },
+};
+
+static int sg2_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+	skt->irq = IRQ_GPIO(SG2_S0_GPIO_READY);
+	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+}
+
+static void sg2_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+}
+
+static void sg2_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+				    struct pcmcia_state *state)
+{
+	state->detect = !gpio_get_value(SG2_S0_GPIO_DETECT);
+	state->ready  = !!gpio_get_value(SG2_S0_GPIO_READY);
+	state->bvd1   = 0; /* not available - battery detect on card */
+	state->bvd2   = 0; /* not available */
+	state->vs_3v  = 1; /* not available - voltage detect for card */
+	state->vs_Xv  = 0; /* not available */
+	state->wrprot = 0; /* not available - write protect */
+}
+
+static int sg2_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+				       const socket_state_t *state)
+{
+	/* Enable card power */
+	switch (state->Vcc) {
+	case 0:
+		/* sets power ctl register high */
+		gpio_set_value(SG2_S0_POWER_CTL, 1);
+		break;
+	case 33:
+	case 50:
+		/* sets power control register low (clear) */
+		gpio_set_value(SG2_S0_POWER_CTL, 0);
+		msleep(100);
+		break;
+	default:
+		pr_err("%s(): bad Vcc %u\n",
+		       __func__, state->Vcc);
+		return -1;
+	}
+
+	/* reset */
+	gpio_set_value(SG2_S0_GPIO_RESET, !!(state->flags & SS_RESET));
+
+	return 0;
+}
+
+static void sg2_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+	soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+}
+
+static void sg2_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+	soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+}
+
+static struct pcmcia_low_level sg2_pcmcia_ops __initdata = {
+	.owner			= THIS_MODULE,
+	.hw_init		= sg2_pcmcia_hw_init,
+	.hw_shutdown		= sg2_pcmcia_hw_shutdown,
+	.socket_state		= sg2_pcmcia_socket_state,
+	.configure_socket	= sg2_pcmcia_configure_socket,
+	.socket_init		= sg2_pcmcia_socket_init,
+	.socket_suspend		= sg2_pcmcia_socket_suspend,
+	.nr			= 1,
+};
+
+static struct platform_device *sg2_pcmcia_device;
+
+static int __init sg2_pcmcia_init(void)
+{
+	int ret;
+
+	if (!machine_is_stargate2())
+		return -ENODEV;
+
+	sg2_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
+	if (!sg2_pcmcia_device)
+		return -ENOMEM;
+
+	ret = gpio_request(SG2_S0_BUFF_CTL, "SG2 CF buff ctl");
+	if (ret)
+		goto error_put_platform_device;
+	ret = gpio_request(SG2_S0_POWER_CTL, "SG2 CF power ctl");
+	if (ret)
+		goto error_free_gpio_buff_ctl;
+	ret = gpio_request(SG2_S0_GPIO_RESET, "SG2 CF reset");
+	if (ret)
+		goto error_free_gpio_power_ctl;
+	/* Set gpio directions */
+	gpio_direction_output(SG2_S0_BUFF_CTL, 0);
+	gpio_direction_output(SG2_S0_POWER_CTL, 1);
+	gpio_direction_output(SG2_S0_GPIO_RESET, 1);
+
+	ret = platform_device_add_data(sg2_pcmcia_device,
+				       &sg2_pcmcia_ops,
+				       sizeof(sg2_pcmcia_ops));
+	if (ret)
+		goto error_free_gpio_reset;
+
+	ret = platform_device_add(sg2_pcmcia_device);
+	if (ret)
+		goto error_free_gpio_reset;
+
+	return 0;
+error_free_gpio_reset:
+	gpio_free(SG2_S0_GPIO_RESET);
+error_free_gpio_power_ctl:
+	gpio_free(SG2_S0_POWER_CTL);
+error_free_gpio_buff_ctl:
+	gpio_free(SG2_S0_BUFF_CTL);
+error_put_platform_device:
+	platform_device_put(sg2_pcmcia_device);
+
+	return ret;
+}
+
+static void __exit sg2_pcmcia_exit(void)
+{
+	platform_device_unregister(sg2_pcmcia_device);
+	gpio_free(SG2_S0_BUFF_CTL);
+	gpio_free(SG2_S0_POWER_CTL);
+	gpio_free(SG2_S0_GPIO_RESET);
+}
+
+fs_initcall(sg2_pcmcia_init);
+module_exit(sg2_pcmcia_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-pcmcia");
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 8083d86..b6c0239 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1759,6 +1759,16 @@
 	  Say Y here if you want to support the built-in frame buffer of
 	  the Motorola 68328 CPU family.
 
+config FB_PXA168
+	tristate "PXA168/910 LCD framebuffer support"
+	depends on FB && (CPU_PXA168 || CPU_PXA910)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Frame buffer driver for the built-in LCD controller in the Marvell
+	  MMP processor.
+
 config FB_PXA
 	tristate "PXA LCD framebuffer support"
 	depends on FB && ARCH_PXA
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index d8d0be5..01a819f 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -97,6 +97,7 @@
 obj-$(CONFIG_FB_CIRRUS)		  += cirrusfb.o
 obj-$(CONFIG_FB_ASILIANT)	  += asiliantfb.o
 obj-$(CONFIG_FB_PXA)		  += pxafb.o
+obj-$(CONFIG_FB_PXA168)		  += pxa168fb.o
 obj-$(CONFIG_FB_W100)		  += w100fb.o
 obj-$(CONFIG_FB_TMIO)		  += tmiofb.o
 obj-$(CONFIG_FB_AU1100)		  += au1100fb.o
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
new file mode 100644
index 0000000..84d8327
--- /dev/null
+++ b/drivers/video/pxa168fb.c
@@ -0,0 +1,803 @@
+/*
+ * linux/drivers/video/pxa168fb.c -- Marvell PXA168 LCD Controller
+ *
+ *  Copyright (C) 2008 Marvell International Ltd.
+ *  All rights reserved.
+ *
+ *  2009-02-16  adapted from original version for PXA168/910
+ *              Jun Nie <njun@marvell.com>
+ *
+ * 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/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/uaccess.h>
+#include <video/pxa168fb.h>
+
+#include "pxa168fb.h"
+
+#define DEFAULT_REFRESH		60	/* Hz */
+
+static int determine_best_pix_fmt(struct fb_var_screeninfo *var)
+{
+	/*
+	 * Pseudocolor mode?
+	 */
+	if (var->bits_per_pixel == 8)
+		return PIX_FMT_PSEUDOCOLOR;
+
+	/*
+	 * Check for 565/1555.
+	 */
+	if (var->bits_per_pixel == 16 && var->red.length <= 5 &&
+	    var->green.length <= 6 && var->blue.length <= 5) {
+		if (var->transp.length == 0) {
+			if (var->red.offset >= var->blue.offset)
+				return PIX_FMT_RGB565;
+			else
+				return PIX_FMT_BGR565;
+		}
+
+		if (var->transp.length == 1 && var->green.length <= 5) {
+			if (var->red.offset >= var->blue.offset)
+				return PIX_FMT_RGB1555;
+			else
+				return PIX_FMT_BGR1555;
+		}
+
+		/* fall through */
+	}
+
+	/*
+	 * Check for 888/A888.
+	 */
+	if (var->bits_per_pixel <= 32 && var->red.length <= 8 &&
+	    var->green.length <= 8 && var->blue.length <= 8) {
+		if (var->bits_per_pixel == 24 && var->transp.length == 0) {
+			if (var->red.offset >= var->blue.offset)
+				return PIX_FMT_RGB888PACK;
+			else
+				return PIX_FMT_BGR888PACK;
+		}
+
+		if (var->bits_per_pixel == 32 && var->transp.length == 8) {
+			if (var->red.offset >= var->blue.offset)
+				return PIX_FMT_RGBA888;
+			else
+				return PIX_FMT_BGRA888;
+		} else {
+			if (var->red.offset >= var->blue.offset)
+				return PIX_FMT_RGB888UNPACK;
+			else
+				return PIX_FMT_BGR888UNPACK;
+		}
+
+		/* fall through */
+	}
+
+	return -EINVAL;
+}
+
+static void set_pix_fmt(struct fb_var_screeninfo *var, int pix_fmt)
+{
+	switch (pix_fmt) {
+	case PIX_FMT_RGB565:
+		var->bits_per_pixel = 16;
+		var->red.offset = 11;    var->red.length = 5;
+		var->green.offset = 5;   var->green.length = 6;
+		var->blue.offset = 0;    var->blue.length = 5;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIX_FMT_BGR565:
+		var->bits_per_pixel = 16;
+		var->red.offset = 0;     var->red.length = 5;
+		var->green.offset = 5;   var->green.length = 6;
+		var->blue.offset = 11;   var->blue.length = 5;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIX_FMT_RGB1555:
+		var->bits_per_pixel = 16;
+		var->red.offset = 10;    var->red.length = 5;
+		var->green.offset = 5;   var->green.length = 5;
+		var->blue.offset = 0;    var->blue.length = 5;
+		var->transp.offset = 15; var->transp.length = 1;
+		break;
+	case PIX_FMT_BGR1555:
+		var->bits_per_pixel = 16;
+		var->red.offset = 0;     var->red.length = 5;
+		var->green.offset = 5;   var->green.length = 5;
+		var->blue.offset = 10;   var->blue.length = 5;
+		var->transp.offset = 15; var->transp.length = 1;
+		break;
+	case PIX_FMT_RGB888PACK:
+		var->bits_per_pixel = 24;
+		var->red.offset = 16;    var->red.length = 8;
+		var->green.offset = 8;   var->green.length = 8;
+		var->blue.offset = 0;    var->blue.length = 8;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIX_FMT_BGR888PACK:
+		var->bits_per_pixel = 24;
+		var->red.offset = 0;     var->red.length = 8;
+		var->green.offset = 8;   var->green.length = 8;
+		var->blue.offset = 16;   var->blue.length = 8;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	case PIX_FMT_RGBA888:
+		var->bits_per_pixel = 32;
+		var->red.offset = 16;    var->red.length = 8;
+		var->green.offset = 8;   var->green.length = 8;
+		var->blue.offset = 0;    var->blue.length = 8;
+		var->transp.offset = 24; var->transp.length = 8;
+		break;
+	case PIX_FMT_BGRA888:
+		var->bits_per_pixel = 32;
+		var->red.offset = 0;     var->red.length = 8;
+		var->green.offset = 8;   var->green.length = 8;
+		var->blue.offset = 16;   var->blue.length = 8;
+		var->transp.offset = 24; var->transp.length = 8;
+		break;
+	case PIX_FMT_PSEUDOCOLOR:
+		var->bits_per_pixel = 8;
+		var->red.offset = 0;     var->red.length = 8;
+		var->green.offset = 0;   var->green.length = 8;
+		var->blue.offset = 0;    var->blue.length = 8;
+		var->transp.offset = 0;  var->transp.length = 0;
+		break;
+	}
+}
+
+static void set_mode(struct pxa168fb_info *fbi, struct fb_var_screeninfo *var,
+		     struct fb_videomode *mode, int pix_fmt, int ystretch)
+{
+	struct fb_info *info = fbi->info;
+
+	set_pix_fmt(var, pix_fmt);
+
+	var->xres = mode->xres;
+	var->yres = mode->yres;
+	var->xres_virtual = max(var->xres, var->xres_virtual);
+	if (ystretch)
+		var->yres_virtual = info->fix.smem_len /
+			(var->xres_virtual * (var->bits_per_pixel >> 3));
+	else
+		var->yres_virtual = max(var->yres, var->yres_virtual);
+	var->grayscale = 0;
+	var->accel_flags = FB_ACCEL_NONE;
+	var->pixclock = mode->pixclock;
+	var->left_margin = mode->left_margin;
+	var->right_margin = mode->right_margin;
+	var->upper_margin = mode->upper_margin;
+	var->lower_margin = mode->lower_margin;
+	var->hsync_len = mode->hsync_len;
+	var->vsync_len = mode->vsync_len;
+	var->sync = mode->sync;
+	var->vmode = FB_VMODE_NONINTERLACED;
+	var->rotate = FB_ROTATE_UR;
+}
+
+static int pxa168fb_check_var(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	struct pxa168fb_info *fbi = info->par;
+	int pix_fmt;
+
+	/*
+	 * Determine which pixel format we're going to use.
+	 */
+	pix_fmt = determine_best_pix_fmt(var);
+	if (pix_fmt < 0)
+		return pix_fmt;
+	set_pix_fmt(var, pix_fmt);
+	fbi->pix_fmt = pix_fmt;
+
+	/*
+	 * Basic geometry sanity checks.
+	 */
+	if (var->xoffset + var->xres > var->xres_virtual)
+		return -EINVAL;
+	if (var->yoffset + var->yres > var->yres_virtual)
+		return -EINVAL;
+	if (var->xres + var->right_margin +
+	    var->hsync_len + var->left_margin > 2048)
+		return -EINVAL;
+	if (var->yres + var->lower_margin +
+	    var->vsync_len + var->upper_margin > 2048)
+		return -EINVAL;
+
+	/*
+	 * Check size of framebuffer.
+	 */
+	if (var->xres_virtual * var->yres_virtual *
+	    (var->bits_per_pixel >> 3) > info->fix.smem_len)
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * The hardware clock divider has an integer and a fractional
+ * stage:
+ *
+ *	clk2 = clk_in / integer_divider
+ *	clk_out = clk2 * (1 - (fractional_divider >> 12))
+ *
+ * Calculate integer and fractional divider for given clk_in
+ * and clk_out.
+ */
+static void set_clock_divider(struct pxa168fb_info *fbi,
+			      const struct fb_videomode *m)
+{
+	int divider_int;
+	int needed_pixclk;
+	u64 div_result;
+	u32 x = 0;
+
+	/*
+	 * Notice: The field pixclock is used by linux fb
+	 * is in pixel second. E.g. struct fb_videomode &
+	 * struct fb_var_screeninfo
+	 */
+
+	/*
+	 * Check input values.
+	 */
+	if (!m || !m->pixclock || !m->refresh) {
+		dev_err(fbi->dev, "Input refresh or pixclock is wrong.\n");
+		return;
+	}
+
+	/*
+	 * Using PLL/AXI clock.
+	 */
+	x = 0x80000000;
+
+	/*
+	 * Calc divider according to refresh rate.
+	 */
+	div_result = 1000000000000ll;
+	do_div(div_result, m->pixclock);
+	needed_pixclk = (u32)div_result;
+
+	divider_int = clk_get_rate(fbi->clk) / needed_pixclk;
+
+	/* check whether divisor is too small. */
+	if (divider_int < 2) {
+		dev_warn(fbi->dev, "Warning: clock source is too slow."
+				"Try smaller resolution\n");
+		divider_int = 2;
+	}
+
+	/*
+	 * Set setting to reg.
+	 */
+	x |= divider_int;
+	writel(x, fbi->reg_base + LCD_CFG_SCLK_DIV);
+}
+
+static void set_dma_control0(struct pxa168fb_info *fbi)
+{
+	u32 x;
+
+	/*
+	 * Set bit to enable graphics DMA.
+	 */
+	x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0);
+	x |= fbi->active ? 0x00000100 : 0;
+	fbi->active = 0;
+
+	/*
+	 * If we are in a pseudo-color mode, we need to enable
+	 * palette lookup.
+	 */
+	if (fbi->pix_fmt == PIX_FMT_PSEUDOCOLOR)
+		x |= 0x10000000;
+
+	/*
+	 * Configure hardware pixel format.
+	 */
+	x &= ~(0xF << 16);
+	x |= (fbi->pix_fmt >> 1) << 16;
+
+	/*
+	 * Check red and blue pixel swap.
+	 * 1. source data swap
+	 * 2. panel output data swap
+	 */
+	x &= ~(1 << 12);
+	x |= ((fbi->pix_fmt & 1) ^ (fbi->panel_rbswap)) << 12;
+
+	writel(x, fbi->reg_base + LCD_SPU_DMA_CTRL0);
+}
+
+static void set_dma_control1(struct pxa168fb_info *fbi, int sync)
+{
+	u32 x;
+
+	/*
+	 * Configure default bits: vsync triggers DMA, gated clock
+	 * enable, power save enable, configure alpha registers to
+	 * display 100% graphics, and set pixel command.
+	 */
+	x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL1);
+	x |= 0x2032ff81;
+
+	/*
+	 * We trigger DMA on the falling edge of vsync if vsync is
+	 * active low, or on the rising edge if vsync is active high.
+	 */
+	if (!(sync & FB_SYNC_VERT_HIGH_ACT))
+		x |= 0x08000000;
+
+	writel(x, fbi->reg_base + LCD_SPU_DMA_CTRL1);
+}
+
+static void set_graphics_start(struct fb_info *info, int xoffset, int yoffset)
+{
+	struct pxa168fb_info *fbi = info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	int pixel_offset;
+	unsigned long addr;
+
+	pixel_offset = (yoffset * var->xres_virtual) + xoffset;
+
+	addr = fbi->fb_start_dma + (pixel_offset * (var->bits_per_pixel >> 3));
+	writel(addr, fbi->reg_base + LCD_CFG_GRA_START_ADDR0);
+}
+
+static void set_dumb_panel_control(struct fb_info *info)
+{
+	struct pxa168fb_info *fbi = info->par;
+	struct pxa168fb_mach_info *mi = fbi->dev->platform_data;
+	u32 x;
+
+	/*
+	 * Preserve enable flag.
+	 */
+	x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL) & 0x00000001;
+
+	x |= (fbi->is_blanked ? 0x7 : mi->dumb_mode) << 28;
+	x |= mi->gpio_output_data << 20;
+	x |= mi->gpio_output_mask << 12;
+	x |= mi->panel_rgb_reverse_lanes ? 0x00000080 : 0;
+	x |= mi->invert_composite_blank ? 0x00000040 : 0;
+	x |= (info->var.sync & FB_SYNC_COMP_HIGH_ACT) ? 0x00000020 : 0;
+	x |= mi->invert_pix_val_ena ? 0x00000010 : 0;
+	x |= (info->var.sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x00000008;
+	x |= (info->var.sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x00000004;
+	x |= mi->invert_pixclock ? 0x00000002 : 0;
+
+	writel(x, fbi->reg_base + LCD_SPU_DUMB_CTRL);
+}
+
+static void set_dumb_screen_dimensions(struct fb_info *info)
+{
+	struct pxa168fb_info *fbi = info->par;
+	struct fb_var_screeninfo *v = &info->var;
+	int x;
+	int y;
+
+	x = v->xres + v->right_margin + v->hsync_len + v->left_margin;
+	y = v->yres + v->lower_margin + v->vsync_len + v->upper_margin;
+
+	writel((y << 16) | x, fbi->reg_base + LCD_SPUT_V_H_TOTAL);
+}
+
+static int pxa168fb_set_par(struct fb_info *info)
+{
+	struct pxa168fb_info *fbi = info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	struct fb_videomode mode;
+	u32 x;
+	struct pxa168fb_mach_info *mi;
+
+	mi = fbi->dev->platform_data;
+
+	/*
+	 * Set additional mode info.
+	 */
+	if (fbi->pix_fmt == PIX_FMT_PSEUDOCOLOR)
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	else
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+	info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
+	info->fix.ypanstep = var->yres;
+
+	/*
+	 * Disable panel output while we setup the display.
+	 */
+	x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL);
+	writel(x & ~1, fbi->reg_base + LCD_SPU_DUMB_CTRL);
+
+	/*
+	 * Configure global panel parameters.
+	 */
+	writel((var->yres << 16) | var->xres,
+		fbi->reg_base + LCD_SPU_V_H_ACTIVE);
+
+	/*
+	 * convet var to video mode
+	 */
+	fb_var_to_videomode(&mode, &info->var);
+
+	/* Calculate clock divisor. */
+	set_clock_divider(fbi, &mode);
+
+	/* Configure dma ctrl regs. */
+	set_dma_control0(fbi);
+	set_dma_control1(fbi, info->var.sync);
+
+	/*
+	 * Configure graphics DMA parameters.
+	 */
+	x = readl(fbi->reg_base + LCD_CFG_GRA_PITCH);
+	x = (x & ~0xFFFF) | ((var->xres_virtual * var->bits_per_pixel) >> 3);
+	writel(x, fbi->reg_base + LCD_CFG_GRA_PITCH);
+	writel((var->yres << 16) | var->xres,
+		fbi->reg_base + LCD_SPU_GRA_HPXL_VLN);
+	writel((var->yres << 16) | var->xres,
+		fbi->reg_base + LCD_SPU_GZM_HPXL_VLN);
+
+	/*
+	 * Configure dumb panel ctrl regs & timings.
+	 */
+	set_dumb_panel_control(info);
+	set_dumb_screen_dimensions(info);
+
+	writel((var->left_margin << 16) | var->right_margin,
+			fbi->reg_base + LCD_SPU_H_PORCH);
+	writel((var->upper_margin << 16) | var->lower_margin,
+			fbi->reg_base + LCD_SPU_V_PORCH);
+
+	/*
+	 * Re-enable panel output.
+	 */
+	x = readl(fbi->reg_base + LCD_SPU_DUMB_CTRL);
+	writel(x | 1, fbi->reg_base + LCD_SPU_DUMB_CTRL);
+
+	return 0;
+}
+
+static unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
+{
+	return ((chan & 0xffff) >> (16 - bf->length)) << bf->offset;
+}
+
+static u32 to_rgb(u16 red, u16 green, u16 blue)
+{
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	return (red << 16) | (green << 8) | blue;
+}
+
+static int
+pxa168fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
+		 unsigned int blue, unsigned int trans, struct fb_info *info)
+{
+	struct pxa168fb_info *fbi = info->par;
+	u32 val;
+
+	if (info->var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green +
+					7471 * blue) >> 16;
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 16) {
+		val =  chan_to_field(red,   &info->var.red);
+		val |= chan_to_field(green, &info->var.green);
+		val |= chan_to_field(blue , &info->var.blue);
+		fbi->pseudo_palette[regno] = val;
+	}
+
+	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR && regno < 256) {
+		val = to_rgb(red, green, blue);
+		writel(val, fbi->reg_base + LCD_SPU_SRAM_WRDAT);
+		writel(0x8300 | regno, fbi->reg_base + LCD_SPU_SRAM_CTRL);
+	}
+
+	return 0;
+}
+
+static int pxa168fb_blank(int blank, struct fb_info *info)
+{
+	struct pxa168fb_info *fbi = info->par;
+
+	fbi->is_blanked = (blank == FB_BLANK_UNBLANK) ? 0 : 1;
+	set_dumb_panel_control(info);
+
+	return 0;
+}
+
+static int pxa168fb_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	set_graphics_start(info, var->xoffset, var->yoffset);
+
+	return 0;
+}
+
+static irqreturn_t pxa168fb_handle_irq(int irq, void *dev_id)
+{
+	struct pxa168fb_info *fbi = dev_id;
+	u32 isr = readl(fbi->reg_base + SPU_IRQ_ISR);
+
+	if ((isr & GRA_FRAME_IRQ0_ENA_MASK)) {
+
+		writel(isr & (~GRA_FRAME_IRQ0_ENA_MASK),
+			fbi->reg_base + SPU_IRQ_ISR);
+
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+static struct fb_ops pxa168fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= pxa168fb_check_var,
+	.fb_set_par	= pxa168fb_set_par,
+	.fb_setcolreg	= pxa168fb_setcolreg,
+	.fb_blank	= pxa168fb_blank,
+	.fb_pan_display	= pxa168fb_pan_display,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static int __init pxa168fb_init_mode(struct fb_info *info,
+			      struct pxa168fb_mach_info *mi)
+{
+	struct pxa168fb_info *fbi = info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	int ret = 0;
+	u32 total_w, total_h, refresh;
+	u64 div_result;
+	const struct fb_videomode *m;
+
+	/*
+	 * Set default value
+	 */
+	refresh = DEFAULT_REFRESH;
+
+	/* try to find best video mode. */
+	m = fb_find_best_mode(&info->var, &info->modelist);
+	if (m)
+		fb_videomode_to_var(&info->var, m);
+
+	/* Init settings. */
+	var->xres_virtual = var->xres;
+	var->yres_virtual = info->fix.smem_len /
+		(var->xres_virtual * (var->bits_per_pixel >> 3));
+	dev_dbg(fbi->dev, "pxa168fb: find best mode: res = %dx%d\n",
+				var->xres, var->yres);
+
+	/* correct pixclock. */
+	total_w = var->xres + var->left_margin + var->right_margin +
+		  var->hsync_len;
+	total_h = var->yres + var->upper_margin + var->lower_margin +
+		  var->vsync_len;
+
+	div_result = 1000000000000ll;
+	do_div(div_result, total_w * total_h * refresh);
+	var->pixclock = (u32)div_result;
+
+	return ret;
+}
+
+static int __init pxa168fb_probe(struct platform_device *pdev)
+{
+	struct pxa168fb_mach_info *mi;
+	struct fb_info *info = 0;
+	struct pxa168fb_info *fbi = 0;
+	struct resource *res;
+	struct clk *clk;
+	int irq, ret;
+
+	mi = pdev->dev.platform_data;
+	if (mi == NULL) {
+		dev_err(&pdev->dev, "no platform data defined\n");
+		return -EINVAL;
+	}
+
+	clk = clk_get(&pdev->dev, "LCDCLK");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "unable to get LCDCLK");
+		return PTR_ERR(clk);
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no IO memory defined\n");
+		return -ENOENT;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no IRQ defined\n");
+		return -ENOENT;
+	}
+
+	info = framebuffer_alloc(sizeof(struct pxa168fb_info), &pdev->dev);
+	if (info == NULL) {
+		clk_put(clk);
+		return -ENOMEM;
+	}
+
+	/* Initialize private data */
+	fbi = info->par;
+	fbi->info = info;
+	fbi->clk = clk;
+	fbi->dev = info->dev = &pdev->dev;
+	fbi->panel_rbswap = mi->panel_rbswap;
+	fbi->is_blanked = 0;
+	fbi->active = mi->active;
+
+	/*
+	 * Initialise static fb parameters.
+	 */
+	info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK |
+		      FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
+	info->node = -1;
+	strlcpy(info->fix.id, mi->id, 16);
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.type_aux = 0;
+	info->fix.xpanstep = 0;
+	info->fix.ypanstep = 0;
+	info->fix.ywrapstep = 0;
+	info->fix.mmio_start = res->start;
+	info->fix.mmio_len = res->end - res->start + 1;
+	info->fix.accel = FB_ACCEL_NONE;
+	info->fbops = &pxa168fb_ops;
+	info->pseudo_palette = fbi->pseudo_palette;
+
+	/*
+	 * Map LCD controller registers.
+	 */
+	fbi->reg_base = ioremap_nocache(res->start, res->end - res->start);
+	if (fbi->reg_base == NULL) {
+		ret = -ENOMEM;
+		goto failed;
+	}
+
+	/*
+	 * Allocate framebuffer memory.
+	 */
+	info->fix.smem_len = PAGE_ALIGN(DEFAULT_FB_SIZE);
+
+	info->screen_base = dma_alloc_writecombine(fbi->dev, info->fix.smem_len,
+						&fbi->fb_start_dma, GFP_KERNEL);
+	if (info->screen_base == NULL) {
+		ret = -ENOMEM;
+		goto failed;
+	}
+
+	info->fix.smem_start = (unsigned long)fbi->fb_start_dma;
+
+	/*
+	 * Set video mode according to platform data.
+	 */
+	set_mode(fbi, &info->var, mi->modes, mi->pix_fmt, 1);
+
+	fb_videomode_to_modelist(mi->modes, mi->num_modes, &info->modelist);
+
+	/*
+	 * init video mode data.
+	 */
+	pxa168fb_init_mode(info, mi);
+
+	ret = pxa168fb_check_var(&info->var, info);
+	if (ret)
+		goto failed_free_fbmem;
+
+	/*
+	 * Fill in sane defaults.
+	 */
+	ret = pxa168fb_check_var(&info->var, info);
+	if (ret)
+		goto failed;
+
+	/*
+	 * enable controller clock
+	 */
+	clk_enable(fbi->clk);
+
+	pxa168fb_set_par(info);
+
+	/*
+	 * Configure default register values.
+	 */
+	writel(0, fbi->reg_base + LCD_SPU_BLANKCOLOR);
+	writel(mi->io_pin_allocation_mode, fbi->reg_base + SPU_IOPAD_CONTROL);
+	writel(0, fbi->reg_base + LCD_CFG_GRA_START_ADDR1);
+	writel(0, fbi->reg_base + LCD_SPU_GRA_OVSA_HPXL_VLN);
+	writel(0, fbi->reg_base + LCD_SPU_SRAM_PARA0);
+	writel(CFG_CSB_256x32(0x1)|CFG_CSB_256x24(0x1)|CFG_CSB_256x8(0x1),
+		fbi->reg_base + LCD_SPU_SRAM_PARA1);
+
+	/*
+	 * Allocate color map.
+	 */
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		ret = -ENOMEM;
+		goto failed_free_clk;
+	}
+
+	/*
+	 * Register irq handler.
+	 */
+	ret = request_irq(irq, pxa168fb_handle_irq, IRQF_SHARED,
+					info->fix.id, fbi);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "unable to request IRQ\n");
+		ret = -ENXIO;
+		goto failed_free_cmap;
+	}
+
+	/*
+	 * Enable GFX interrupt
+	 */
+	writel(GRA_FRAME_IRQ0_ENA(0x1), fbi->reg_base + SPU_IRQ_ENA);
+
+	/*
+	 * Register framebuffer.
+	 */
+	ret = register_framebuffer(info);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to register pxa168-fb: %d\n", ret);
+		ret = -ENXIO;
+		goto failed_free_irq;
+	}
+
+	platform_set_drvdata(pdev, fbi);
+	return 0;
+
+failed_free_irq:
+	free_irq(irq, fbi);
+failed_free_cmap:
+	fb_dealloc_cmap(&info->cmap);
+failed_free_clk:
+	clk_disable(fbi->clk);
+failed_free_fbmem:
+	dma_free_coherent(fbi->dev, info->fix.smem_len,
+			info->screen_base, fbi->fb_start_dma);
+failed:
+	kfree(info);
+	clk_put(clk);
+
+	dev_err(&pdev->dev, "frame buffer device init failed with %d\n", ret);
+	return ret;
+}
+
+static struct platform_driver pxa168fb_driver = {
+	.driver		= {
+		.name	= "pxa168-fb",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= pxa168fb_probe,
+};
+
+static int __devinit pxa168fb_init(void)
+{
+	return platform_driver_register(&pxa168fb_driver);
+}
+module_init(pxa168fb_init);
+
+MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> "
+	      "Green Wan <gwan@marvell.com>");
+MODULE_DESCRIPTION("Framebuffer driver for PXA168/910");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/pxa168fb.h b/drivers/video/pxa168fb.h
new file mode 100644
index 0000000..eee0927
--- /dev/null
+++ b/drivers/video/pxa168fb.h
@@ -0,0 +1,558 @@
+#ifndef __PXA168FB_H__
+#define __PXA168FB_H__
+
+/* ------------< LCD register >------------ */
+/* Video Frame 0&1 start address registers */
+#define	LCD_SPU_DMA_START_ADDR_Y0		0x00C0
+#define	LCD_SPU_DMA_START_ADDR_U0		0x00C4
+#define	LCD_SPU_DMA_START_ADDR_V0		0x00C8
+#define LCD_CFG_DMA_START_ADDR_0		0x00CC /* Cmd address */
+#define	LCD_SPU_DMA_START_ADDR_Y1		0x00D0
+#define	LCD_SPU_DMA_START_ADDR_U1		0x00D4
+#define	LCD_SPU_DMA_START_ADDR_V1		0x00D8
+#define LCD_CFG_DMA_START_ADDR_1		0x00DC /* Cmd address */
+
+/* YC & UV Pitch */
+#define LCD_SPU_DMA_PITCH_YC			0x00E0
+#define     SPU_DMA_PITCH_C(c)			((c) << 16)
+#define     SPU_DMA_PITCH_Y(y)			(y)
+#define LCD_SPU_DMA_PITCH_UV			0x00E4
+#define     SPU_DMA_PITCH_V(v)			((v) << 16)
+#define     SPU_DMA_PITCH_U(u)			(u)
+
+/* Video Starting Point on Screen Register */
+#define LCD_SPUT_DMA_OVSA_HPXL_VLN		0x00E8
+#define     CFG_DMA_OVSA_VLN(y)			((y) << 16) /* 0~0xfff */
+#define     CFG_DMA_OVSA_HPXL(x)		(x)     /* 0~0xfff */
+
+/* Video Size Register */
+#define LCD_SPU_DMA_HPXL_VLN			0x00EC
+#define     CFG_DMA_VLN(y)			((y) << 16)
+#define     CFG_DMA_HPXL(x)			(x)
+
+/* Video Size After zooming Register */
+#define LCD_SPU_DZM_HPXL_VLN			0x00F0
+#define     CFG_DZM_VLN(y)			((y) << 16)
+#define     CFG_DZM_HPXL(x)			(x)
+
+/* Graphic Frame 0&1 Starting Address Register */
+#define LCD_CFG_GRA_START_ADDR0			0x00F4
+#define LCD_CFG_GRA_START_ADDR1			0x00F8
+
+/* Graphic Frame Pitch */
+#define LCD_CFG_GRA_PITCH			0x00FC
+
+/* Graphic Starting Point on Screen Register */
+#define LCD_SPU_GRA_OVSA_HPXL_VLN		0x0100
+#define     CFG_GRA_OVSA_VLN(y)			((y) << 16)
+#define     CFG_GRA_OVSA_HPXL(x)		(x)
+
+/* Graphic Size Register */
+#define LCD_SPU_GRA_HPXL_VLN			0x0104
+#define     CFG_GRA_VLN(y)			((y) << 16)
+#define     CFG_GRA_HPXL(x)			(x)
+
+/* Graphic Size after Zooming Register */
+#define LCD_SPU_GZM_HPXL_VLN			0x0108
+#define     CFG_GZM_VLN(y)			((y) << 16)
+#define     CFG_GZM_HPXL(x)			(x)
+
+/* HW Cursor Starting Point on Screen Register */
+#define LCD_SPU_HWC_OVSA_HPXL_VLN		0x010C
+#define     CFG_HWC_OVSA_VLN(y)			((y) << 16)
+#define     CFG_HWC_OVSA_HPXL(x)		(x)
+
+/* HW Cursor Size */
+#define LCD_SPU_HWC_HPXL_VLN			0x0110
+#define     CFG_HWC_VLN(y)			((y) << 16)
+#define     CFG_HWC_HPXL(x)			(x)
+
+/* Total Screen Size Register */
+#define LCD_SPUT_V_H_TOTAL			0x0114
+#define     CFG_V_TOTAL(y)			((y) << 16)
+#define     CFG_H_TOTAL(x)			(x)
+
+/* Total Screen Active Size Register */
+#define LCD_SPU_V_H_ACTIVE			0x0118
+#define     CFG_V_ACTIVE(y)			((y) << 16)
+#define     CFG_H_ACTIVE(x)			(x)
+
+/* Screen H&V Porch Register */
+#define LCD_SPU_H_PORCH				0x011C
+#define     CFG_H_BACK_PORCH(b)			((b) << 16)
+#define     CFG_H_FRONT_PORCH(f)		(f)
+#define LCD_SPU_V_PORCH				0x0120
+#define     CFG_V_BACK_PORCH(b)			((b) << 16)
+#define     CFG_V_FRONT_PORCH(f)		(f)
+
+/* Screen Blank Color Register */
+#define LCD_SPU_BLANKCOLOR			0x0124
+#define     CFG_BLANKCOLOR_MASK			0x00FFFFFF
+#define     CFG_BLANKCOLOR_R_MASK		0x000000FF
+#define     CFG_BLANKCOLOR_G_MASK		0x0000FF00
+#define     CFG_BLANKCOLOR_B_MASK		0x00FF0000
+
+/* HW Cursor Color 1&2 Register */
+#define LCD_SPU_ALPHA_COLOR1			0x0128
+#define     CFG_HWC_COLOR1			0x00FFFFFF
+#define     CFG_HWC_COLOR1_R(red)		((red) << 16)
+#define     CFG_HWC_COLOR1_G(green)		((green) << 8)
+#define     CFG_HWC_COLOR1_B(blue)		(blue)
+#define     CFG_HWC_COLOR1_R_MASK		0x000000FF
+#define     CFG_HWC_COLOR1_G_MASK		0x0000FF00
+#define     CFG_HWC_COLOR1_B_MASK		0x00FF0000
+#define LCD_SPU_ALPHA_COLOR2			0x012C
+#define     CFG_HWC_COLOR2			0x00FFFFFF
+#define     CFG_HWC_COLOR2_R_MASK		0x000000FF
+#define     CFG_HWC_COLOR2_G_MASK		0x0000FF00
+#define     CFG_HWC_COLOR2_B_MASK		0x00FF0000
+
+/* Video YUV Color Key Control */
+#define LCD_SPU_COLORKEY_Y			0x0130
+#define     CFG_CKEY_Y2(y2)			((y2) << 24)
+#define     CFG_CKEY_Y2_MASK			0xFF000000
+#define     CFG_CKEY_Y1(y1)			((y1) << 16)
+#define     CFG_CKEY_Y1_MASK			0x00FF0000
+#define     CFG_CKEY_Y(y)			((y) << 8)
+#define     CFG_CKEY_Y_MASK			0x0000FF00
+#define     CFG_ALPHA_Y(y)			(y)
+#define     CFG_ALPHA_Y_MASK			0x000000FF
+#define LCD_SPU_COLORKEY_U			0x0134
+#define     CFG_CKEY_U2(u2)			((u2) << 24)
+#define     CFG_CKEY_U2_MASK			0xFF000000
+#define     CFG_CKEY_U1(u1)			((u1) << 16)
+#define     CFG_CKEY_U1_MASK			0x00FF0000
+#define     CFG_CKEY_U(u)			((u) << 8)
+#define     CFG_CKEY_U_MASK			0x0000FF00
+#define     CFG_ALPHA_U(u)			(u)
+#define     CFG_ALPHA_U_MASK			0x000000FF
+#define LCD_SPU_COLORKEY_V			0x0138
+#define     CFG_CKEY_V2(v2)			((v2) << 24)
+#define     CFG_CKEY_V2_MASK			0xFF000000
+#define     CFG_CKEY_V1(v1)			((v1) << 16)
+#define     CFG_CKEY_V1_MASK			0x00FF0000
+#define     CFG_CKEY_V(v)			((v) << 8)
+#define     CFG_CKEY_V_MASK			0x0000FF00
+#define     CFG_ALPHA_V(v)			(v)
+#define     CFG_ALPHA_V_MASK			0x000000FF
+
+/* SPI Read Data Register */
+#define LCD_SPU_SPI_RXDATA			0x0140
+
+/* Smart Panel Read Data Register */
+#define LCD_SPU_ISA_RSDATA			0x0144
+#define     ISA_RXDATA_16BIT_1_DATA_MASK	0x000000FF
+#define     ISA_RXDATA_16BIT_2_DATA_MASK	0x0000FF00
+#define     ISA_RXDATA_16BIT_3_DATA_MASK	0x00FF0000
+#define     ISA_RXDATA_16BIT_4_DATA_MASK	0xFF000000
+#define     ISA_RXDATA_32BIT_1_DATA_MASK	0x00FFFFFF
+
+/* HWC SRAM Read Data Register */
+#define LCD_SPU_HWC_RDDAT			0x0158
+
+/* Gamma Table SRAM Read Data Register */
+#define LCD_SPU_GAMMA_RDDAT			0x015c
+#define     CFG_GAMMA_RDDAT_MASK		0x000000FF
+
+/* Palette Table SRAM Read Data Register */
+#define LCD_SPU_PALETTE_RDDAT			0x0160
+#define     CFG_PALETTE_RDDAT_MASK		0x00FFFFFF
+
+/* I/O Pads Input Read Only Register */
+#define LCD_SPU_IOPAD_IN			0x0178
+#define     CFG_IOPAD_IN_MASK			0x0FFFFFFF
+
+/* Reserved Read Only Registers */
+#define LCD_CFG_RDREG5F				0x017C
+#define     IRE_FRAME_CNT_MASK			0x000000C0
+#define     IPE_FRAME_CNT_MASK			0x00000030
+#define     GRA_FRAME_CNT_MASK			0x0000000C  /* Graphic */
+#define     DMA_FRAME_CNT_MASK			0x00000003  /* Video */
+
+/* SPI Control Register. */
+#define LCD_SPU_SPI_CTRL			0x0180
+#define     CFG_SCLKCNT(div)			((div) << 24)  /* 0xFF~0x2 */
+#define     CFG_SCLKCNT_MASK			0xFF000000
+#define     CFG_RXBITS(rx)			((rx) << 16)   /* 0x1F~0x1 */
+#define     CFG_RXBITS_MASK			0x00FF0000
+#define     CFG_TXBITS(tx)			((tx) << 8)    /* 0x1F~0x1 */
+#define     CFG_TXBITS_MASK			0x0000FF00
+#define     CFG_CLKINV(clk)			((clk) << 7)
+#define     CFG_CLKINV_MASK			0x00000080
+#define     CFG_KEEPXFER(transfer)		((transfer) << 6)
+#define     CFG_KEEPXFER_MASK			0x00000040
+#define     CFG_RXBITSTO0(rx)			((rx) << 5)
+#define     CFG_RXBITSTO0_MASK			0x00000020
+#define     CFG_TXBITSTO0(tx)			((tx) << 4)
+#define     CFG_TXBITSTO0_MASK			0x00000010
+#define     CFG_SPI_ENA(spi)			((spi) << 3)
+#define     CFG_SPI_ENA_MASK			0x00000008
+#define     CFG_SPI_SEL(spi)			((spi) << 2)
+#define     CFG_SPI_SEL_MASK			0x00000004
+#define     CFG_SPI_3W4WB(wire)			((wire) << 1)
+#define     CFG_SPI_3W4WB_MASK			0x00000002
+#define     CFG_SPI_START(start)		(start)
+#define     CFG_SPI_START_MASK			0x00000001
+
+/* SPI Tx Data Register */
+#define LCD_SPU_SPI_TXDATA			0x0184
+
+/*
+   1. Smart Pannel 8-bit Bus Control Register.
+   2. AHB Slave Path Data Port Register
+*/
+#define LCD_SPU_SMPN_CTRL			0x0188
+
+/* DMA Control 0 Register */
+#define LCD_SPU_DMA_CTRL0			0x0190
+#define     CFG_NOBLENDING(nb)			((nb) << 31)
+#define     CFG_NOBLENDING_MASK			0x80000000
+#define     CFG_GAMMA_ENA(gn)			((gn) << 30)
+#define     CFG_GAMMA_ENA_MASK			0x40000000
+#define     CFG_CBSH_ENA(cn)			((cn) << 29)
+#define     CFG_CBSH_ENA_MASK			0x20000000
+#define     CFG_PALETTE_ENA(pn)			((pn) << 28)
+#define     CFG_PALETTE_ENA_MASK		0x10000000
+#define     CFG_ARBFAST_ENA(an)			((an) << 27)
+#define     CFG_ARBFAST_ENA_MASK		0x08000000
+#define     CFG_HWC_1BITMOD(mode)		((mode) << 26)
+#define     CFG_HWC_1BITMOD_MASK		0x04000000
+#define     CFG_HWC_1BITENA(mn)			((mn) << 25)
+#define     CFG_HWC_1BITENA_MASK		0x02000000
+#define     CFG_HWC_ENA(cn)		        ((cn) << 24)
+#define     CFG_HWC_ENA_MASK			0x01000000
+#define     CFG_DMAFORMAT(dmaformat)		((dmaformat) << 20)
+#define     CFG_DMAFORMAT_MASK			0x00F00000
+#define     CFG_GRAFORMAT(graformat)		((graformat) << 16)
+#define     CFG_GRAFORMAT_MASK			0x000F0000
+/* for graphic part */
+#define     CFG_GRA_FTOGGLE(toggle)		((toggle) << 15)
+#define     CFG_GRA_FTOGGLE_MASK		0x00008000
+#define     CFG_GRA_HSMOOTH(smooth)		((smooth) << 14)
+#define     CFG_GRA_HSMOOTH_MASK		0x00004000
+#define     CFG_GRA_TSTMODE(test)		((test) << 13)
+#define     CFG_GRA_TSTMODE_MASK		0x00002000
+#define     CFG_GRA_SWAPRB(swap)		((swap) << 12)
+#define     CFG_GRA_SWAPRB_MASK			0x00001000
+#define     CFG_GRA_SWAPUV(swap)		((swap) << 11)
+#define     CFG_GRA_SWAPUV_MASK			0x00000800
+#define     CFG_GRA_SWAPYU(swap)		((swap) << 10)
+#define     CFG_GRA_SWAPYU_MASK			0x00000400
+#define     CFG_YUV2RGB_GRA(cvrt)		((cvrt) << 9)
+#define     CFG_YUV2RGB_GRA_MASK		0x00000200
+#define     CFG_GRA_ENA(gra)			((gra) << 8)
+#define     CFG_GRA_ENA_MASK			0x00000100
+/* for video part */
+#define     CFG_DMA_FTOGGLE(toggle)		((toggle) << 7)
+#define     CFG_DMA_FTOGGLE_MASK		0x00000080
+#define     CFG_DMA_HSMOOTH(smooth)		((smooth) << 6)
+#define     CFG_DMA_HSMOOTH_MASK		0x00000040
+#define     CFG_DMA_TSTMODE(test)		((test) << 5)
+#define     CFG_DMA_TSTMODE_MASK		0x00000020
+#define     CFG_DMA_SWAPRB(swap)		((swap) << 4)
+#define     CFG_DMA_SWAPRB_MASK			0x00000010
+#define     CFG_DMA_SWAPUV(swap)		((swap) << 3)
+#define     CFG_DMA_SWAPUV_MASK			0x00000008
+#define     CFG_DMA_SWAPYU(swap)		((swap) << 2)
+#define     CFG_DMA_SWAPYU_MASK			0x00000004
+#define     CFG_DMA_SWAP_MASK			0x0000001C
+#define     CFG_YUV2RGB_DMA(cvrt)		((cvrt) << 1)
+#define     CFG_YUV2RGB_DMA_MASK		0x00000002
+#define     CFG_DMA_ENA(video)			(video)
+#define     CFG_DMA_ENA_MASK			0x00000001
+
+/* DMA Control 1 Register */
+#define LCD_SPU_DMA_CTRL1			0x0194
+#define     CFG_FRAME_TRIG(trig)		((trig) << 31)
+#define     CFG_FRAME_TRIG_MASK			0x80000000
+#define     CFG_VSYNC_TRIG(trig)		((trig) << 28)
+#define     CFG_VSYNC_TRIG_MASK			0x70000000
+#define     CFG_VSYNC_INV(inv)			((inv) << 27)
+#define     CFG_VSYNC_INV_MASK			0x08000000
+#define     CFG_COLOR_KEY_MODE(cmode)		((cmode) << 24)
+#define     CFG_COLOR_KEY_MASK			0x07000000
+#define     CFG_CARRY(carry)			((carry) << 23)
+#define     CFG_CARRY_MASK			0x00800000
+#define     CFG_LNBUF_ENA(lnbuf)		((lnbuf) << 22)
+#define     CFG_LNBUF_ENA_MASK			0x00400000
+#define     CFG_GATED_ENA(gated)		((gated) << 21)
+#define     CFG_GATED_ENA_MASK			0x00200000
+#define     CFG_PWRDN_ENA(power)		((power) << 20)
+#define     CFG_PWRDN_ENA_MASK			0x00100000
+#define     CFG_DSCALE(dscale)			((dscale) << 18)
+#define     CFG_DSCALE_MASK			0x000C0000
+#define     CFG_ALPHA_MODE(amode)		((amode) << 16)
+#define     CFG_ALPHA_MODE_MASK			0x00030000
+#define     CFG_ALPHA(alpha)			((alpha) << 8)
+#define     CFG_ALPHA_MASK			0x0000FF00
+#define     CFG_PXLCMD(pxlcmd)			(pxlcmd)
+#define     CFG_PXLCMD_MASK			0x000000FF
+
+/* SRAM Control Register */
+#define LCD_SPU_SRAM_CTRL			0x0198
+#define     CFG_SRAM_INIT_WR_RD(mode)		((mode) << 14)
+#define     CFG_SRAM_INIT_WR_RD_MASK		0x0000C000
+#define     CFG_SRAM_ADDR_LCDID(id)		((id) << 8)
+#define     CFG_SRAM_ADDR_LCDID_MASK		0x00000F00
+#define     CFG_SRAM_ADDR(addr)			(addr)
+#define     CFG_SRAM_ADDR_MASK			0x000000FF
+
+/* SRAM Write Data Register */
+#define LCD_SPU_SRAM_WRDAT			0x019C
+
+/* SRAM RTC/WTC Control Register */
+#define LCD_SPU_SRAM_PARA0			0x01A0
+
+/* SRAM Power Down Control Register */
+#define LCD_SPU_SRAM_PARA1			0x01A4
+#define     CFG_CSB_256x32(hwc)			((hwc) << 15)	/* HWC */
+#define     CFG_CSB_256x32_MASK			0x00008000
+#define     CFG_CSB_256x24(palette)		((palette) << 14)	/* Palette */
+#define     CFG_CSB_256x24_MASK			0x00004000
+#define     CFG_CSB_256x8(gamma)		((gamma) << 13)	/* Gamma */
+#define     CFG_CSB_256x8_MASK			0x00002000
+#define     CFG_PDWN256x32(pdwn)		((pdwn) << 7)	/* HWC */
+#define     CFG_PDWN256x32_MASK			0x00000080
+#define     CFG_PDWN256x24(pdwn)		((pdwn) << 6)	/* Palette */
+#define     CFG_PDWN256x24_MASK			0x00000040
+#define     CFG_PDWN256x8(pdwn)			((pdwn) << 5)	/* Gamma */
+#define     CFG_PDWN256x8_MASK			0x00000020
+#define     CFG_PDWN32x32(pdwn)			((pdwn) << 3)
+#define     CFG_PDWN32x32_MASK			0x00000008
+#define     CFG_PDWN16x66(pdwn)			((pdwn) << 2)
+#define     CFG_PDWN16x66_MASK			0x00000004
+#define     CFG_PDWN32x66(pdwn)			((pdwn) << 1)
+#define     CFG_PDWN32x66_MASK			0x00000002
+#define     CFG_PDWN64x66(pdwn)			(pdwn)
+#define     CFG_PDWN64x66_MASK			0x00000001
+
+/* Smart or Dumb Panel Clock Divider */
+#define LCD_CFG_SCLK_DIV			0x01A8
+#define     SCLK_SOURCE_SELECT(src)		((src) << 31)
+#define     SCLK_SOURCE_SELECT_MASK		0x80000000
+#define     CLK_FRACDIV(frac)			((frac) << 16)
+#define     CLK_FRACDIV_MASK			0x0FFF0000
+#define     CLK_INT_DIV(div)			(div)
+#define     CLK_INT_DIV_MASK			0x0000FFFF
+
+/* Video Contrast Register */
+#define LCD_SPU_CONTRAST			0x01AC
+#define     CFG_BRIGHTNESS(bright)		((bright) << 16)
+#define     CFG_BRIGHTNESS_MASK			0xFFFF0000
+#define     CFG_CONTRAST(contrast)		(contrast)
+#define     CFG_CONTRAST_MASK			0x0000FFFF
+
+/* Video Saturation Register */
+#define LCD_SPU_SATURATION			0x01B0
+#define     CFG_C_MULTS(mult)			((mult) << 16)
+#define     CFG_C_MULTS_MASK			0xFFFF0000
+#define     CFG_SATURATION(sat)			(sat)
+#define     CFG_SATURATION_MASK			0x0000FFFF
+
+/* Video Hue Adjust Register */
+#define LCD_SPU_CBSH_HUE			0x01B4
+#define     CFG_SIN0(sin0)			((sin0) << 16)
+#define     CFG_SIN0_MASK			0xFFFF0000
+#define     CFG_COS0(con0)			(con0)
+#define     CFG_COS0_MASK			0x0000FFFF
+
+/* Dump LCD Panel Control Register */
+#define LCD_SPU_DUMB_CTRL			0x01B8
+#define     CFG_DUMBMODE(mode)			((mode) << 28)
+#define     CFG_DUMBMODE_MASK			0xF0000000
+#define     CFG_LCDGPIO_O(data)			((data) << 20)
+#define     CFG_LCDGPIO_O_MASK			0x0FF00000
+#define     CFG_LCDGPIO_ENA(gpio)		((gpio) << 12)
+#define     CFG_LCDGPIO_ENA_MASK		0x000FF000
+#define     CFG_BIAS_OUT(bias)			((bias) << 8)
+#define     CFG_BIAS_OUT_MASK			0x00000100
+#define     CFG_REVERSE_RGB(rRGB)		((rRGB) << 7)
+#define     CFG_REVERSE_RGB_MASK		0x00000080
+#define     CFG_INV_COMPBLANK(blank)		((blank) << 6)
+#define     CFG_INV_COMPBLANK_MASK		0x00000040
+#define     CFG_INV_COMPSYNC(sync)		((sync) << 5)
+#define     CFG_INV_COMPSYNC_MASK		0x00000020
+#define     CFG_INV_HENA(hena)			((hena) << 4)
+#define     CFG_INV_HENA_MASK			0x00000010
+#define     CFG_INV_VSYNC(vsync)		((vsync) << 3)
+#define     CFG_INV_VSYNC_MASK			0x00000008
+#define     CFG_INV_HSYNC(hsync)		((hsync) << 2)
+#define     CFG_INV_HSYNC_MASK			0x00000004
+#define     CFG_INV_PCLK(pclk)			((pclk) << 1)
+#define     CFG_INV_PCLK_MASK			0x00000002
+#define     CFG_DUMB_ENA(dumb)			(dumb)
+#define     CFG_DUMB_ENA_MASK			0x00000001
+
+/* LCD I/O Pads Control Register */
+#define SPU_IOPAD_CONTROL			0x01BC
+#define     CFG_GRA_VM_ENA(vm)			((vm) << 15)        /* gfx */
+#define     CFG_GRA_VM_ENA_MASK			0x00008000
+#define     CFG_DMA_VM_ENA(vm)			((vm) << 13)	/* video */
+#define     CFG_DMA_VM_ENA_MASK			0x00002000
+#define     CFG_CMD_VM_ENA(vm)			((vm) << 13)
+#define     CFG_CMD_VM_ENA_MASK			0x00000800
+#define     CFG_CSC(csc)			((csc) << 8)	/* csc */
+#define     CFG_CSC_MASK			0x00000300
+#define     CFG_AXICTRL(axi)			((axi) << 4)
+#define     CFG_AXICTRL_MASK			0x000000F0
+#define     CFG_IOPADMODE(iopad)		(iopad)
+#define     CFG_IOPADMODE_MASK			0x0000000F
+
+/* LCD Interrupt Control Register */
+#define SPU_IRQ_ENA				0x01C0
+#define     DMA_FRAME_IRQ0_ENA(irq)		((irq) << 31)
+#define     DMA_FRAME_IRQ0_ENA_MASK		0x80000000
+#define     DMA_FRAME_IRQ1_ENA(irq)		((irq) << 30)
+#define     DMA_FRAME_IRQ1_ENA_MASK		0x40000000
+#define     DMA_FF_UNDERFLOW_ENA(ff)		((ff) << 29)
+#define     DMA_FF_UNDERFLOW_ENA_MASK		0x20000000
+#define     GRA_FRAME_IRQ0_ENA(irq)		((irq) << 27)
+#define     GRA_FRAME_IRQ0_ENA_MASK		0x08000000
+#define     GRA_FRAME_IRQ1_ENA(irq)		((irq) << 26)
+#define     GRA_FRAME_IRQ1_ENA_MASK		0x04000000
+#define     GRA_FF_UNDERFLOW_ENA(ff)		((ff) << 25)
+#define     GRA_FF_UNDERFLOW_ENA_MASK		0x02000000
+#define     VSYNC_IRQ_ENA(vsync_irq)		((vsync_irq) << 23)
+#define     VSYNC_IRQ_ENA_MASK			0x00800000
+#define     DUMB_FRAMEDONE_ENA(fdone)		((fdone) << 22)
+#define     DUMB_FRAMEDONE_ENA_MASK		0x00400000
+#define     TWC_FRAMEDONE_ENA(fdone)		((fdone) << 21)
+#define     TWC_FRAMEDONE_ENA_MASK		0x00200000
+#define     HWC_FRAMEDONE_ENA(fdone)		((fdone) << 20)
+#define     HWC_FRAMEDONE_ENA_MASK		0x00100000
+#define     SLV_IRQ_ENA(irq)			((irq) << 19)
+#define     SLV_IRQ_ENA_MASK			0x00080000
+#define     SPI_IRQ_ENA(irq)			((irq) << 18)
+#define     SPI_IRQ_ENA_MASK			0x00040000
+#define     PWRDN_IRQ_ENA(irq)			((irq) << 17)
+#define     PWRDN_IRQ_ENA_MASK			0x00020000
+#define     ERR_IRQ_ENA(irq)			((irq) << 16)
+#define     ERR_IRQ_ENA_MASK			0x00010000
+#define     CLEAN_SPU_IRQ_ISR(irq)		(irq)
+#define     CLEAN_SPU_IRQ_ISR_MASK		0x0000FFFF
+
+/* LCD Interrupt Status Register */
+#define SPU_IRQ_ISR				0x01C4
+#define     DMA_FRAME_IRQ0(irq)			((irq) << 31)
+#define     DMA_FRAME_IRQ0_MASK			0x80000000
+#define     DMA_FRAME_IRQ1(irq)			((irq) << 30)
+#define     DMA_FRAME_IRQ1_MASK			0x40000000
+#define     DMA_FF_UNDERFLOW(ff)		((ff) << 29)
+#define     DMA_FF_UNDERFLOW_MASK		0x20000000
+#define     GRA_FRAME_IRQ0(irq)			((irq) << 27)
+#define     GRA_FRAME_IRQ0_MASK			0x08000000
+#define     GRA_FRAME_IRQ1(irq)			((irq) << 26)
+#define     GRA_FRAME_IRQ1_MASK			0x04000000
+#define     GRA_FF_UNDERFLOW(ff)		((ff) << 25)
+#define     GRA_FF_UNDERFLOW_MASK		0x02000000
+#define     VSYNC_IRQ(vsync_irq)		((vsync_irq) << 23)
+#define     VSYNC_IRQ_MASK			0x00800000
+#define     DUMB_FRAMEDONE(fdone)		((fdone) << 22)
+#define     DUMB_FRAMEDONE_MASK			0x00400000
+#define     TWC_FRAMEDONE(fdone)		((fdone) << 21)
+#define     TWC_FRAMEDONE_MASK			0x00200000
+#define     HWC_FRAMEDONE(fdone)		((fdone) << 20)
+#define     HWC_FRAMEDONE_MASK			0x00100000
+#define     SLV_IRQ(irq)			((irq) << 19)
+#define     SLV_IRQ_MASK			0x00080000
+#define     SPI_IRQ(irq)			((irq) << 18)
+#define     SPI_IRQ_MASK			0x00040000
+#define     PWRDN_IRQ(irq)			((irq) << 17)
+#define     PWRDN_IRQ_MASK			0x00020000
+#define     ERR_IRQ(irq)			((irq) << 16)
+#define     ERR_IRQ_MASK			0x00010000
+/* read-only */
+#define     DMA_FRAME_IRQ0_LEVEL_MASK		0x00008000
+#define     DMA_FRAME_IRQ1_LEVEL_MASK		0x00004000
+#define     DMA_FRAME_CNT_ISR_MASK		0x00003000
+#define     GRA_FRAME_IRQ0_LEVEL_MASK		0x00000800
+#define     GRA_FRAME_IRQ1_LEVEL_MASK		0x00000400
+#define     GRA_FRAME_CNT_ISR_MASK		0x00000300
+#define     VSYNC_IRQ_LEVEL_MASK		0x00000080
+#define     DUMB_FRAMEDONE_LEVEL_MASK		0x00000040
+#define     TWC_FRAMEDONE_LEVEL_MASK		0x00000020
+#define     HWC_FRAMEDONE_LEVEL_MASK		0x00000010
+#define     SLV_FF_EMPTY_MASK			0x00000008
+#define     DMA_FF_ALLEMPTY_MASK		0x00000004
+#define     GRA_FF_ALLEMPTY_MASK		0x00000002
+#define     PWRDN_IRQ_LEVEL_MASK		0x00000001
+
+
+/*
+ * defined Video Memory Color format for DMA control 0 register
+ * DMA0 bit[23:20]
+ */
+#define VMODE_RGB565		0x0
+#define VMODE_RGB1555		0x1
+#define VMODE_RGB888PACKED	0x2
+#define VMODE_RGB888UNPACKED	0x3
+#define VMODE_RGBA888		0x4
+#define VMODE_YUV422PACKED	0x5
+#define VMODE_YUV422PLANAR	0x6
+#define VMODE_YUV420PLANAR	0x7
+#define VMODE_SMPNCMD		0x8
+#define VMODE_PALETTE4BIT	0x9
+#define VMODE_PALETTE8BIT	0xa
+#define VMODE_RESERVED		0xb
+
+/*
+ * defined Graphic Memory Color format for DMA control 0 register
+ * DMA0 bit[19:16]
+ */
+#define GMODE_RGB565		0x0
+#define GMODE_RGB1555		0x1
+#define GMODE_RGB888PACKED	0x2
+#define GMODE_RGB888UNPACKED	0x3
+#define GMODE_RGBA888		0x4
+#define GMODE_YUV422PACKED	0x5
+#define GMODE_YUV422PLANAR	0x6
+#define GMODE_YUV420PLANAR	0x7
+#define GMODE_SMPNCMD		0x8
+#define GMODE_PALETTE4BIT	0x9
+#define GMODE_PALETTE8BIT	0xa
+#define GMODE_RESERVED		0xb
+
+/*
+ * define for DMA control 1 register
+ */
+#define DMA1_FRAME_TRIG		31 /* bit location */
+#define DMA1_VSYNC_MODE		28
+#define DMA1_VSYNC_INV		27
+#define DMA1_CKEY		24
+#define DMA1_CARRY		23
+#define DMA1_LNBUF_ENA		22
+#define DMA1_GATED_ENA		21
+#define DMA1_PWRDN_ENA		20
+#define DMA1_DSCALE		18
+#define DMA1_ALPHA_MODE		16
+#define DMA1_ALPHA		08
+#define DMA1_PXLCMD		00
+
+/*
+ * defined for Configure Dumb Mode
+ * DUMB LCD Panel bit[31:28]
+ */
+#define DUMB16_RGB565_0		0x0
+#define DUMB16_RGB565_1		0x1
+#define DUMB18_RGB666_0		0x2
+#define DUMB18_RGB666_1		0x3
+#define DUMB12_RGB444_0		0x4
+#define DUMB12_RGB444_1		0x5
+#define DUMB24_RGB888_0		0x6
+#define DUMB_BLANK		0x7
+
+/*
+ * defined for Configure I/O Pin Allocation Mode
+ * LCD LCD I/O Pads control register bit[3:0]
+ */
+#define IOPAD_DUMB24		0x0
+#define IOPAD_DUMB18SPI		0x1
+#define IOPAD_DUMB18GPIO	0x2
+#define IOPAD_DUMB16SPI		0x3
+#define IOPAD_DUMB16GPIO	0x4
+#define IOPAD_DUMB12		0x5
+#define IOPAD_SMART18SPI	0x6
+#define IOPAD_SMART16SPI	0x7
+#define IOPAD_SMART8BOTH	0x8
+
+#endif /* __PXA168FB_H__ */
diff --git a/include/video/pxa168fb.h b/include/video/pxa168fb.h
new file mode 100644
index 0000000..b5cc72f
--- /dev/null
+++ b/include/video/pxa168fb.h
@@ -0,0 +1,127 @@
+/*
+ * linux/arch/arm/mach-mmp/include/mach/pxa168fb.h
+ *
+ *  Copyright (C) 2009 Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_MACH_PXA168FB_H
+#define __ASM_MACH_PXA168FB_H
+
+#include <linux/fb.h>
+#include <linux/interrupt.h>
+
+/* Dumb interface */
+#define PIN_MODE_DUMB_24		0
+#define PIN_MODE_DUMB_18_SPI		1
+#define PIN_MODE_DUMB_18_GPIO		2
+#define PIN_MODE_DUMB_16_SPI		3
+#define PIN_MODE_DUMB_16_GPIO		4
+#define PIN_MODE_DUMB_12_SPI_GPIO	5
+#define PIN_MODE_SMART_18_SPI		6
+#define PIN_MODE_SMART_16_SPI		7
+#define PIN_MODE_SMART_8_SPI_GPIO	8
+
+/* Dumb interface pin allocation */
+#define DUMB_MODE_RGB565		0
+#define DUMB_MODE_RGB565_UPPER		1
+#define DUMB_MODE_RGB666		2
+#define DUMB_MODE_RGB666_UPPER		3
+#define DUMB_MODE_RGB444		4
+#define DUMB_MODE_RGB444_UPPER		5
+#define DUMB_MODE_RGB888		6
+
+/* default fb buffer size WVGA-32bits */
+#define DEFAULT_FB_SIZE	(800 * 480 * 4)
+
+/*
+ * Buffer pixel format
+ * bit0 is for rb swap.
+ * bit12 is for Y UorV swap
+ */
+#define PIX_FMT_RGB565		0
+#define PIX_FMT_BGR565		1
+#define PIX_FMT_RGB1555		2
+#define PIX_FMT_BGR1555		3
+#define PIX_FMT_RGB888PACK	4
+#define PIX_FMT_BGR888PACK	5
+#define PIX_FMT_RGB888UNPACK	6
+#define PIX_FMT_BGR888UNPACK	7
+#define PIX_FMT_RGBA888		8
+#define PIX_FMT_BGRA888		9
+#define PIX_FMT_YUV422PACK	10
+#define PIX_FMT_YVU422PACK	11
+#define PIX_FMT_YUV422PLANAR	12
+#define PIX_FMT_YVU422PLANAR	13
+#define PIX_FMT_YUV420PLANAR	14
+#define PIX_FMT_YVU420PLANAR	15
+#define PIX_FMT_PSEUDOCOLOR	20
+#define PIX_FMT_UYVY422PACK	(0x1000|PIX_FMT_YUV422PACK)
+
+/*
+ * PXA LCD controller private state.
+ */
+struct pxa168fb_info {
+	struct device		*dev;
+	struct clk		*clk;
+	struct fb_info		*info;
+
+	void __iomem		*reg_base;
+	dma_addr_t		fb_start_dma;
+	u32			pseudo_palette[16];
+
+	int			pix_fmt;
+	unsigned		is_blanked:1;
+	unsigned		panel_rbswap:1;
+	unsigned		active:1;
+};
+
+/*
+ * PXA fb machine information
+ */
+struct pxa168fb_mach_info {
+	char	id[16];
+
+	int		num_modes;
+	struct fb_videomode *modes;
+
+	/*
+	 * Pix_fmt
+	 */
+	unsigned	pix_fmt;
+
+	/*
+	 * I/O pin allocation.
+	 */
+	unsigned	io_pin_allocation_mode:4;
+
+	/*
+	 * Dumb panel -- assignment of R/G/B component info to the 24
+	 * available external data lanes.
+	 */
+	unsigned	dumb_mode:4;
+	unsigned	panel_rgb_reverse_lanes:1;
+
+	/*
+	 * Dumb panel -- GPIO output data.
+	 */
+	unsigned	gpio_output_mask:8;
+	unsigned	gpio_output_data:8;
+
+	/*
+	 * Dumb panel -- configurable output signal polarity.
+	 */
+	unsigned	invert_composite_blank:1;
+	unsigned	invert_pix_val_ena:1;
+	unsigned	invert_pixclock:1;
+	unsigned	invert_vsync:1;
+	unsigned	invert_hsync:1;
+	unsigned	panel_rbswap:1;
+	unsigned	active:1;
+	unsigned	enable_lcd:1;
+};
+
+#endif /* __ASM_MACH_PXA168FB_H */
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index ad8a10f..96b2699 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -98,13 +98,14 @@
 	  CompuLab EM-x270.
 
 config SND_PXA2XX_SOC_PALM27X
-	bool "SoC Audio support for Palm T|X, T5 and LifeDrive"
-	depends on SND_PXA2XX_SOC && (MACH_PALMLD || MACH_PALMTX || MACH_PALMT5)
+	bool "SoC Audio support for Palm T|X, T5, E2 and LifeDrive"
+	depends on SND_PXA2XX_SOC && (MACH_PALMLD || MACH_PALMTX || \
+			MACH_PALMT5 || MACH_PALMTE2)
 	select SND_PXA2XX_SOC_AC97
 	select SND_SOC_WM9712
 	help
 	  Say Y if you want to add support for SoC audio on
-	  Palm T|X, T5 or LifeDrive handheld computer.
+	  Palm T|X, T5, E2 or LifeDrive handheld computer.
 
 config SND_SOC_ZYLONITE
 	tristate "SoC Audio support for Marvell Zylonite"
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
index 44fcc4e..e6102fd 100644
--- a/sound/soc/pxa/palm27x.c
+++ b/sound/soc/pxa/palm27x.c
@@ -205,7 +205,7 @@
 	int ret;
 
 	if (!(machine_is_palmtx() || machine_is_palmt5() ||
-		machine_is_palmld()))
+		machine_is_palmld() || machine_is_palmte2()))
 		return -ENODEV;
 
 	if (pdev->dev.platform_data)