diff --git a/Documentation/power/power_supply_class.txt b/Documentation/power/power_supply_class.txt
index c6cd495..4801654 100644
--- a/Documentation/power/power_supply_class.txt
+++ b/Documentation/power/power_supply_class.txt
@@ -76,6 +76,11 @@ STATUS - this attribute represents operating status (charging, full,
 discharging (i.e. powering a load), etc.). This corresponds to
 BATTERY_STATUS_* values, as defined in battery.h.
 
+CHARGE_TYPE - batteries can typically charge at different rates.
+This defines trickle and fast charges.  For batteries that
+are already charged or discharging, 'n/a' can be displayed (or
+'unknown', if the status is not known).
+
 HEALTH - represents health of the battery, values corresponds to
 POWER_SUPPLY_HEALTH_*, defined in battery.h.
 
diff --git a/MAINTAINERS b/MAINTAINERS
index cf4abdd..c560f04 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6266,6 +6266,24 @@ W:	http://oops.ghostprotocols.net:81/blog
 S:	Maintained
 F:	drivers/net/wireless/wl3501*
 
+WOLFSON PMIC DRIVERS
+P:	Mark Brown
+M:	broonie@opensource.wolfsonmicro.com
+L:	linux-kernel@vger.kernel.org
+T:	git git://opensource.wolfsonmicro.com/linux-2.6-audioplus
+W:	http://opensource.wolfsonmicro.com/node/8
+S:	Supported
+F:	drivers/leds/leds-wm83*.c
+F:	drivers/mfd/wm8*.c
+F:	drivers/power/wm83*.c
+F:	drivers/rtc/rtc-wm83*.c
+F:	drivers/regulator/wm8*.c
+F:	drivers/watchdog/wm83*_wdt.c
+F:	include/linux/mfd/wm8350
+F:	include/linux/mfd/wm8400
+F:	sound/soc/codecs/wm8350.c
+F:	sound/soc/codecs/wm8400.c
+
 WM97XX TOUCHSCREEN DRIVERS
 P:	Mark Brown
 M:	broonie@opensource.wolfsonmicro.com
@@ -6278,6 +6296,24 @@ S:	Supported
 F:	drivers/input/touchscreen/*wm97*
 F:	include/linux/wm97xx.h
 
+WOLFSON MICROELECTRONICS PMIC DRIVERS
+P:	Mark Brown
+M:	broonie@opensource.wolfsonmicro.com
+L:	linux-kernel@vger.kernel.org
+T:	git git://opensource.wolfsonmicro.com/linux-2.6-audioplus
+W:	http://opensource.wolfsonmicro.com/node/8
+S:	Supported
+F:	drivers/leds/leds-wm83*.c
+F:	drivers/mfd/wm8*.c
+F:	drivers/power/wm83*.c
+F:	drivers/rtc/rtc-wm83*.c
+F:	drivers/regulator/wm8*.c
+F:	drivers/watchdog/wm83*_wdt.c
+F:	include/linux/mfd/wm8350/
+F:	include/linux/mfd/wm8400/
+F:	sound/soc/codecs/wm8350.c
+F:	sound/soc/codecs/wm8400.c
+
 X.25 NETWORK LAYER
 P:	Henner Eisen
 M:	eis@baty.hanse.de
diff --git a/Makefile b/Makefile
index 1065154..03373bb 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 30
-EXTRAVERSION = -rc8
+EXTRAVERSION =
 NAME = Man-Eating Seals of Antiquity
 
 # *DOCUMENTATION*
diff --git a/arch/arm/mach-mx3/cpufreq.c b/arch/arm/mach-mx3/cpufreq.c
new file mode 100644
index 0000000..8cebe92
--- /dev/null
+++ b/arch/arm/mach-mx3/cpufreq.c
@@ -0,0 +1,236 @@
+/*
+ * cpufreq.c -- i.MX3x CPUfreq driver.
+ *
+ * Copyright (C) 2007 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood <lg@opensource.wolfsonmicro.com>
+ *
+ * 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/types.h>
+#include <linux/kernel.h>
+#include <linux/cpufreq.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/regulator/regulator.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/arch/clock.h>
+#include <asm/cacheflush.h>
+
+static struct clk *cpu_clk;
+static struct regulator *regulator;
+
+struct mx3_freq_volts {
+	int freq;
+	int uV;
+};
+
+/*
+ * These voltage and frequency settings could be further refined.
+ */
+static const struct mx3_freq_volts freq_uV[] = {
+	{133000 * 1000, 1275 * 1000},
+	{266000 * 1000, 1400 * 1000},
+	{399000 * 1000, 1500 * 1000},
+	{532000 * 1000, 1600 * 1000},
+};
+
+/* does need to be in ascending order for calc_frequency() below */
+static struct cpufreq_frequency_table imx31_freq_table[] = {
+	{0x01, 133000},
+	{0x02, 266000},
+	{0x03, 399000},
+	{0x04, 532000},
+	{0, CPUFREQ_TABLE_END},
+};
+
+static int mx3_verify_speed(struct cpufreq_policy *policy)
+{
+	if (policy->cpu != 0)
+		return -EINVAL;
+
+	return cpufreq_frequency_table_verify(policy, imx31_freq_table);
+}
+
+static unsigned int mx3_get_speed(unsigned int cpu)
+{
+	if (cpu)
+		return 0;
+	return clk_get_rate(cpu_clk) / 1000;
+}
+
+static int calc_frequency(int target, unsigned int relation)
+{
+	int i;
+
+	if (relation == CPUFREQ_RELATION_H) {
+		for (i = ARRAY_SIZE(imx31_freq_table) - 1; i > 0; i--) {
+			if (imx31_freq_table[i].frequency <= target)
+				return imx31_freq_table[i].frequency;
+		}
+	} else if (relation == CPUFREQ_RELATION_L) {
+		for (i = 0; i < ARRAY_SIZE(imx31_freq_table) - 1; i++) {
+			if (imx31_freq_table[i].frequency >= target)
+				return imx31_freq_table[i].frequency;
+		}
+	}
+	printk(KERN_ERR "error no valid cpufreq relation\n");
+	return 532000;
+}
+
+static int mx3_cpu_voltage(struct cpufreq_policy *policy, int freq)
+{
+	int i, ret = -EINVAL, mV_delta;
+
+	for (i = 0; i < ARRAY_SIZE(freq_uV); i++) {
+		if (freq_uV[i].freq == freq)
+			goto found;
+	}
+	printk(KERN_ERR "%s: could not find voltage for freq %d kHz\n",
+		__func__, freq);
+	return ret;
+
+found:
+	mV_delta = (freq_uV[i].uV - regulator_get_voltage(regulator)) / 1000;
+	ret = regulator_set_voltage(regulator, freq_uV[i].uV, freq_uV[i].uV);
+	if (mV_delta < 0)
+		mV_delta *= -1;
+	udelay(mV_delta * 2);	/* wait for voltage change - TODO: tune */
+	return ret;
+}
+
+static int mx3_set_target(struct cpufreq_policy *policy,
+			  unsigned int target_freq, unsigned int relation)
+{
+	struct cpufreq_freqs freqs;
+	long freq;
+	int ret = 0;
+
+	/*
+	 * Some governors do not respects CPU and policy lower limits
+	 * which leads to bad things (division by zero etc), ensure
+	 * that such things do not happen.
+	 */
+	if (target_freq < policy->cpuinfo.min_freq)
+		target_freq = policy->cpuinfo.min_freq;
+
+	if (target_freq < policy->min)
+		target_freq = policy->min;
+
+	freq = calc_frequency(target_freq, relation) * 1000;
+	freqs.old = clk_get_rate(cpu_clk) / 1000;
+	freqs.new = (freq + 500) / 1000;
+	freqs.cpu = 0;
+	freqs.flags = 0;
+
+	if (freqs.old < freqs.new)
+		ret = mx3_cpu_voltage(policy, freq);
+
+	if (ret < 0) {
+		printk(KERN_ERR "cant raise voltage for CPU frequency %ld\n",
+		       freq);
+		return -EIO;
+	}
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	clk_set_rate(cpu_clk, freq);
+
+	if (freqs.old > freqs.new)
+		ret = mx3_cpu_voltage(policy, freq);
+	if (ret < 0) {
+		printk(KERN_ERR "cant lower voltage for CPU frequency %ld\n",
+		       freq);
+	}
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	return 0;
+}
+
+static int __init mx3_cpufreq_driver_init(struct cpufreq_policy *policy)
+{
+	int ret;
+
+	printk(KERN_INFO "i.MX3x CPU frequency driver\n");
+
+	if (policy->cpu != 0)
+		return -EINVAL;
+
+	cpu_clk = clk_get(NULL, "cpu_clk");
+	if (IS_ERR(cpu_clk)) {
+		printk(KERN_ERR "%s: failed to get clock\n", __func__);
+		return PTR_ERR(cpu_clk);
+	}
+
+	regulator = regulator_get(NULL, "cpu_vcc");
+	if (IS_ERR(regulator)) {
+		clk_put(cpu_clk);
+		printk(KERN_ERR "%s: failed to get regulator\n", __func__);
+		return PTR_ERR(regulator);
+	}
+
+	policy->cur = policy->min = policy->max = clk_get_rate(cpu_clk) / 1000;
+	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+	policy->cpuinfo.min_freq = 133000;
+	policy->cpuinfo.max_freq = 532000;
+
+	/* Manual states, that PLL stabilizes in two CLK32 periods */
+	policy->cpuinfo.transition_latency = 10;
+
+	ret = cpufreq_frequency_table_cpuinfo(policy, imx31_freq_table);
+	if (ret < 0) {
+		clk_put(cpu_clk);
+		regulator_put(regulator);
+		printk(KERN_ERR "%s: failed to register i.MX3x CPUfreq\n",
+			__func__);
+		return ret;
+	}
+	cpufreq_frequency_table_get_attr(imx31_freq_table, policy->cpu);
+	return 0;
+}
+
+static int mx3_cpufreq_driver_exit(struct cpufreq_policy *policy)
+{
+	cpufreq_frequency_table_put_attr(policy->cpu);
+
+	/* reset CPU to 532MHz */
+	if (regulator_set_voltage(regulator, 1600 * 1000, 1600 * 1000) == 0)
+		clk_set_rate(cpu_clk, 532000 * 1000);
+
+	clk_put(cpu_clk);
+	regulator_put(regulator);
+	return 0;
+}
+
+static struct cpufreq_driver mx3_driver = {
+	.flags = CPUFREQ_STICKY,
+	.verify = mx3_verify_speed,
+	.target = mx3_set_target,
+	.get = mx3_get_speed,
+	.init = mx3_cpufreq_driver_init,
+	.exit = mx3_cpufreq_driver_exit,
+	.name = "imx3x",
+};
+
+static int __devinit mx3_cpufreq_init(void)
+{
+	return cpufreq_register_driver(&mx3_driver);
+}
+
+static void mx3_cpufreq_exit(void)
+{
+	cpufreq_unregister_driver(&mx3_driver);
+}
+
+module_init(mx3_cpufreq_init);
+module_exit(mx3_cpufreq_exit);
+
+MODULE_AUTHOR("Liam Girdwood <lg@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("CPUfreq driver for i.mx3x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index d73f5f4..c5dd718 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -910,6 +910,16 @@ config SENSORS_W83627EHF
 	  This driver can also be built as a module.  If so, the module
 	  will be called w83627ehf.
 
+config SENSORS_WM8350
+	tristate "Wolfson Microelectronics WM835x"
+	depends on MFD_WM8350
+	help
+	  If you say yes here you get support for the hardware
+	  monitoring features of the WM835x series of PMICs.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called wm8350-hwmon.
+
 config SENSORS_ULTRA45
 	tristate "Sun Ultra45 PIC16F747"
 	depends on SPARC64
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 0ae2698..9851f2f 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -88,6 +88,7 @@ obj-$(CONFIG_SENSORS_VT8231)	+= vt8231.o
 obj-$(CONFIG_SENSORS_W83627EHF)	+= w83627ehf.o
 obj-$(CONFIG_SENSORS_W83L785TS)	+= w83l785ts.o
 obj-$(CONFIG_SENSORS_W83L786NG)	+= w83l786ng.o
+obj-$(CONFIG_SENSORS_WM8350)	+= wm8350-hwmon.o
 
 ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/hwmon/wm8350-hwmon.c b/drivers/hwmon/wm8350-hwmon.c
new file mode 100644
index 0000000..7387620
--- /dev/null
+++ b/drivers/hwmon/wm8350-hwmon.c
@@ -0,0 +1,149 @@
+/*
+ * drivers/hwmon/wm8350-hwmon.c - Wolfson Microelectroncis WM8350 PMIC
+ *                                  hardware monitoring features.
+ *
+ * Copyright (C) 2009 Wolfson Microelectronics plc
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License v2 as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/comparator.h>
+
+static ssize_t show_name(struct device *dev,
+			 struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "wm8350\n");
+}
+
+static const char *input_names[] = {
+	[WM8350_AUXADC_USB]  = "USB" ,
+	[WM8350_AUXADC_LINE] = "Line" ,
+	[WM8350_AUXADC_BATT] = "Battery",
+};
+
+
+static ssize_t show_voltage(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	struct wm8350 *wm8350 = dev_get_drvdata(dev);
+	int channel = to_sensor_dev_attr(attr)->index;
+	int val;
+
+	val = wm8350_read_auxadc(wm8350, channel, 0, 0)
+		* WM8350_AUX_COEFF / 1000;
+
+	return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t show_label(struct device *dev,
+			  struct device_attribute *attr, char *buf)
+{
+	int channel = to_sensor_dev_attr(attr)->index;
+
+	return sprintf(buf, "%s\n", input_names[channel]);
+}
+
+#define WM8350_NAMED_VOLTAGE(id, name) \
+	static SENSOR_DEVICE_ATTR(in##id##_input, S_IRUGO, show_voltage,\
+				  NULL, WM8350_AUXADC_##name);		\
+	static SENSOR_DEVICE_ATTR(in##id##_label, S_IRUGO, show_label,	\
+				  NULL, WM8350_AUXADC_##name)
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+WM8350_NAMED_VOLTAGE(0, USB);
+WM8350_NAMED_VOLTAGE(1, BATT);
+WM8350_NAMED_VOLTAGE(2, LINE);
+
+static struct attribute *wm8350_attributes[] = {
+	&dev_attr_name.attr,
+
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in0_label.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in1_label.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in2_label.dev_attr.attr,
+
+	NULL,
+};
+
+static const struct attribute_group wm8350_attr_group = {
+	.attrs	= wm8350_attributes,
+};
+
+static int __devinit wm8350_hwmon_probe(struct platform_device *pdev)
+{
+	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = sysfs_create_group(&pdev->dev.kobj, &wm8350_attr_group);
+	if (ret)
+		goto err;
+
+	wm8350->hwmon.classdev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(wm8350->hwmon.classdev)) {
+		ret = PTR_ERR(wm8350->hwmon.classdev);
+		goto err_group;
+	}
+
+	return 0;
+
+err_group:
+	sysfs_remove_group(&pdev->dev.kobj, &wm8350_attr_group);
+err:
+	return ret;
+}
+
+static int __devexit wm8350_hwmon_remove(struct platform_device *pdev)
+{
+	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
+
+	hwmon_device_unregister(wm8350->hwmon.classdev);
+	sysfs_remove_group(&pdev->dev.kobj, &wm8350_attr_group);
+
+	return 0;
+}
+
+static struct platform_driver wm8350_hwmon_driver = {
+	.probe = wm8350_hwmon_probe,
+	.remove = __devexit_p(wm8350_hwmon_remove),
+	.driver = {
+		.name = "wm8350-hwmon",
+	},
+};
+
+static int __init wm8350_hwmon_init(void)
+{
+	return platform_driver_register(&wm8350_hwmon_driver);
+}
+module_init(wm8350_hwmon_init);
+
+static void __exit wm8350_hwmon_exit(void)
+{
+	platform_driver_unregister(&wm8350_hwmon_driver);
+}
+module_exit(wm8350_hwmon_exit);
+
+MODULE_AUTHOR("Mark Brown");
+MODULE_DESCRIPTION("WM8350 Hardware Monitoring");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8350-hwmon");
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index ee3927a..8ad8a32 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -152,7 +152,7 @@ config MFD_WM8400
 	depends on I2C
 	help
 	  Support for the Wolfson Microelecronics WM8400 PMIC and audio
-	  CODEC.  This driver adds provides common support for accessing
+	  CODEC.  This driver provides common support for accessing
 	  the device, additional drivers must be enabled in order to use
 	  the functionality of the device.
 
diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c
index 386da15..cb73051 100644
--- a/drivers/mfd/htc-pasic3.c
+++ b/drivers/mfd/htc-pasic3.c
@@ -35,7 +35,7 @@ struct pasic3_data {
  */
 void pasic3_write_register(struct device *dev, u32 reg, u8 val)
 {
-	struct pasic3_data *asic = dev->driver_data;
+	struct pasic3_data *asic = dev_get_drvdata(dev);
 	int bus_shift = asic->bus_shift;
 	void __iomem *addr = asic->mapping + (REG_ADDR << bus_shift);
 	void __iomem *data = asic->mapping + (REG_DATA << bus_shift);
@@ -50,7 +50,7 @@ EXPORT_SYMBOL(pasic3_write_register); /* for leds-pasic3 */
  */
 u8 pasic3_read_register(struct device *dev, u32 reg)
 {
-	struct pasic3_data *asic = dev->driver_data;
+	struct pasic3_data *asic = dev_get_drvdata(dev);
 	int bus_shift = asic->bus_shift;
 	void __iomem *addr = asic->mapping + (REG_ADDR << bus_shift);
 	void __iomem *data = asic->mapping + (REG_DATA << bus_shift);
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index 11a6248..082c197 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -618,7 +618,7 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
 
 		pdev->dev.parent = pcf->dev;
 		pdev->dev.platform_data = &pdata->reg_init_data[i];
-		pdev->dev.driver_data = pcf;
+		dev_set_drvdata(&pdev->dev, pcf);
 		pcf->regulator_pdev[i] = pdev;
 
 		platform_device_add(pdev);
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
index fe24079..9d662a5 100644
--- a/drivers/mfd/wm8350-core.c
+++ b/drivers/mfd/wm8350-core.c
@@ -1472,6 +1472,8 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
 				   &(wm8350->codec.pdev));
 	wm8350_client_dev_register(wm8350, "wm8350-gpio",
 				   &(wm8350->gpio.pdev));
+	wm8350_client_dev_register(wm8350, "wm8350-hwmon",
+				   &(wm8350->hwmon.pdev));
 	wm8350_client_dev_register(wm8350, "wm8350-power",
 				   &(wm8350->power.pdev));
 	wm8350_client_dev_register(wm8350, "wm8350-rtc", &(wm8350->rtc.pdev));
@@ -1498,6 +1500,7 @@ void wm8350_device_exit(struct wm8350 *wm8350)
 	platform_device_unregister(wm8350->wdt.pdev);
 	platform_device_unregister(wm8350->rtc.pdev);
 	platform_device_unregister(wm8350->power.pdev);
+	platform_device_unregister(wm8350->hwmon.pdev);
 	platform_device_unregister(wm8350->gpio.pdev);
 	platform_device_unregister(wm8350->codec.pdev);
 
diff --git a/drivers/mfd/wm8350-regmap.c b/drivers/mfd/wm8350-regmap.c
index 9a4cc95..7ccc1ea 100644
--- a/drivers/mfd/wm8350-regmap.c
+++ b/drivers/mfd/wm8350-regmap.c
@@ -3186,7 +3186,7 @@ const struct wm8350_reg_access wm8350_reg_io_map[] = {
 	/*  read    write volatile */
 	{ 0xFFFF, 0xFFFF, 0xFFFF }, /* R0   - Reset/ID */
 	{ 0x7CFF, 0x0C00, 0x7FFF }, /* R1   - ID */
-	{ 0x0000, 0x0000, 0x0000 }, /* R2 */
+	{ 0x007F, 0x0000, 0x0000 }, /* R2   - ROM Mask ID */
 	{ 0xBE3B, 0xBE3B, 0x8000 }, /* R3   - System Control 1 */
 	{ 0xFEF7, 0xFEF7, 0xF800 }, /* R4   - System Control 2 */
 	{ 0x80FF, 0x80FF, 0x8000 }, /* R5   - System Hibernate */
@@ -3411,7 +3411,7 @@ const struct wm8350_reg_access wm8350_reg_io_map[] = {
 	{ 0x0000, 0x0000, 0x0000 }, /* R224 */
 	{ 0x8F3F, 0x0000, 0xFFFF }, /* R225 - DCDC/LDO status */
 	{ 0x0000, 0x0000, 0xFFFF }, /* R226 - Charger status */
-	{ 0x0000, 0x0000, 0xFFFF }, /* R227 */
+	{ 0x34FE, 0x0000, 0xFFFF }, /* R227 */
 	{ 0x0000, 0x0000, 0x0000 }, /* R228 */
 	{ 0x0000, 0x0000, 0x0000 }, /* R229 */
 	{ 0xFFFF, 0x1FFF, 0xFFFF }, /* R230 - GPIO Pin Status */
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c
index cf30d06..7c21bf7 100644
--- a/drivers/mfd/wm8400-core.c
+++ b/drivers/mfd/wm8400-core.c
@@ -265,7 +265,7 @@ static int wm8400_init(struct wm8400 *wm8400,
 
 	mutex_init(&wm8400->io_lock);
 
-	wm8400->dev->driver_data = wm8400;
+	dev_set_drvdata(wm8400->dev, wm8400);
 
 	/* Check that this is actually a WM8400 */
 	ret = wm8400->read_dev(wm8400->io_data, WM8400_RESET_ID, 1, &reg);
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
index 5fbca26..924d323 100644
--- a/drivers/power/olpc_battery.c
+++ b/drivers/power/olpc_battery.c
@@ -228,6 +228,14 @@ static int olpc_bat_get_property(struct power_supply *psy,
 		if (ret)
 			return ret;
 		break;
+	case POWER_SUPPLY_PROP_CHARGE_TYPE:
+		if (ec_byte & BAT_STAT_TRICKLE)
+			val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+		else if (ec_byte & BAT_STAT_CHARGING)
+			val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
+		else
+			val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
+		break;
 	case POWER_SUPPLY_PROP_PRESENT:
 		val->intval = !!(ec_byte & BAT_STAT_PRESENT);
 		break;
@@ -311,6 +319,7 @@ static int olpc_bat_get_property(struct power_supply *psy,
 
 static enum power_supply_property olpc_bat_props[] = {
 	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_CHARGE_TYPE,
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_HEALTH,
 	POWER_SUPPLY_PROP_TECHNOLOGY,
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index da73591..f8296fc 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -43,6 +43,9 @@ static ssize_t power_supply_show_property(struct device *dev,
 	static char *status_text[] = {
 		"Unknown", "Charging", "Discharging", "Not charging", "Full"
 	};
+	static char *charge_type[] = {
+		"Unknown", "N/A", "Trickle", "Fast"
+	};
 	static char *health_text[] = {
 		"Unknown", "Good", "Overheat", "Dead", "Over voltage",
 		"Unspecified failure", "Cold",
@@ -67,6 +70,8 @@ static ssize_t power_supply_show_property(struct device *dev,
 
 	if (off == POWER_SUPPLY_PROP_STATUS)
 		return sprintf(buf, "%s\n", status_text[value.intval]);
+	else if (off == POWER_SUPPLY_PROP_CHARGE_TYPE)
+		return sprintf(buf, "%s\n", charge_type[value.intval]);
 	else if (off == POWER_SUPPLY_PROP_HEALTH)
 		return sprintf(buf, "%s\n", health_text[value.intval]);
 	else if (off == POWER_SUPPLY_PROP_TECHNOLOGY)
@@ -81,6 +86,7 @@ static ssize_t power_supply_show_property(struct device *dev,
 static struct device_attribute power_supply_attrs[] = {
 	/* Properties of type `int' */
 	POWER_SUPPLY_ATTR(status),
+	POWER_SUPPLY_ATTR(charge_type),
 	POWER_SUPPLY_ATTR(health),
 	POWER_SUPPLY_ATTR(present),
 	POWER_SUPPLY_ATTR(online),
diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c
index 1b16bf3..28b0299 100644
--- a/drivers/power/wm8350_power.c
+++ b/drivers/power/wm8350_power.c
@@ -321,6 +321,24 @@ static int wm8350_bat_check_health(struct wm8350 *wm8350)
 	return POWER_SUPPLY_HEALTH_GOOD;
 }
 
+static int wm8350_bat_get_charge_type(struct wm8350 *wm8350)
+{
+	int state;
+
+	state = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2) &
+	    WM8350_CHG_STS_MASK;
+	switch (state) {
+	case WM8350_CHG_STS_OFF:
+		return POWER_SUPPLY_CHARGE_TYPE_NONE;
+	case WM8350_CHG_STS_TRICKLE:
+		return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+	case WM8350_CHG_STS_FAST:
+		return POWER_SUPPLY_CHARGE_TYPE_FAST;
+	default:
+		return POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
+	}
+}
+
 static int wm8350_bat_get_property(struct power_supply *psy,
 				   enum power_supply_property psp,
 				   union power_supply_propval *val)
@@ -342,6 +360,9 @@ static int wm8350_bat_get_property(struct power_supply *psy,
 	case POWER_SUPPLY_PROP_HEALTH:
 		val->intval = wm8350_bat_check_health(wm8350);
 		break;
+	case POWER_SUPPLY_PROP_CHARGE_TYPE:
+		val->intval = wm8350_bat_get_charge_type(wm8350);
+		break;
 	default:
 		ret = -EINVAL;
 		break;
@@ -355,6 +376,7 @@ static enum power_supply_property wm8350_bat_props[] = {
 	POWER_SUPPLY_PROP_ONLINE,
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_CHARGE_TYPE,
 };
 
 /*********************************************************************
diff --git a/include/linux/mfd/wm8350/core.h b/include/linux/mfd/wm8350/core.h
index 42cca67..969b0b5 100644
--- a/include/linux/mfd/wm8350/core.h
+++ b/include/linux/mfd/wm8350/core.h
@@ -605,6 +605,11 @@ struct wm8350_irq {
 	void *data;
 };
 
+struct wm8350_hwmon {
+	struct platform_device *pdev;
+	struct device *classdev;
+};
+
 struct wm8350 {
 	struct device *dev;
 
@@ -629,6 +634,7 @@ struct wm8350 {
 	/* Client devices */
 	struct wm8350_codec codec;
 	struct wm8350_gpio gpio;
+	struct wm8350_hwmon hwmon;
 	struct wm8350_pmic pmic;
 	struct wm8350_power power;
 	struct wm8350_rtc rtc;
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 594c494..f974c78 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -39,6 +39,13 @@ enum {
 };
 
 enum {
+	POWER_SUPPLY_CHARGE_TYPE_UNKNOWN = 0,
+	POWER_SUPPLY_CHARGE_TYPE_NONE,
+	POWER_SUPPLY_CHARGE_TYPE_TRICKLE,
+	POWER_SUPPLY_CHARGE_TYPE_FAST,
+};
+
+enum {
 	POWER_SUPPLY_HEALTH_UNKNOWN = 0,
 	POWER_SUPPLY_HEALTH_GOOD,
 	POWER_SUPPLY_HEALTH_OVERHEAT,
@@ -61,6 +68,7 @@ enum {
 enum power_supply_property {
 	/* Properties of type `int' */
 	POWER_SUPPLY_PROP_STATUS = 0,
+	POWER_SUPPLY_PROP_CHARGE_TYPE,
 	POWER_SUPPLY_PROP_HEALTH,
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_ONLINE,
diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h
index d11bd92..d088eb4 100644
--- a/sound/soc/codecs/wm8350.h
+++ b/sound/soc/codecs/wm8350.h
@@ -13,6 +13,7 @@
 #define _WM8350_H
 
 #include <sound/soc.h>
+#include <linux/mfd/wm8350/audio.h>
 
 extern struct snd_soc_dai wm8350_dai;
 extern struct snd_soc_codec_device soc_codec_dev_wm8350;
diff --git a/sound/soc/codecs/wm8400-codec.h b/sound/soc/codecs/wm8400-codec.h
new file mode 100644
index 0000000..cadddbe
--- /dev/null
+++ b/sound/soc/codecs/wm8400-codec.h
@@ -0,0 +1,62 @@
+/*
+ * wm8400.h  --  audio driver for WM8400
+ *
+ * Copyright 2008 Wolfson Microelectronics PLC.
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#ifndef _WM8400_CODEC_H
+#define _WM8400_CODEC_H
+
+#define WM8400_MCLK_DIV 0
+#define WM8400_DACCLK_DIV 1
+#define WM8400_ADCCLK_DIV 2
+#define WM8400_BCLK_DIV 3
+
+#define WM8400_MCLK_DIV_1 0x400
+#define WM8400_MCLK_DIV_2 0x800
+
+#define WM8400_DAC_CLKDIV_1    0x00
+#define WM8400_DAC_CLKDIV_1_5  0x04
+#define WM8400_DAC_CLKDIV_2    0x08
+#define WM8400_DAC_CLKDIV_3    0x0c
+#define WM8400_DAC_CLKDIV_4    0x10
+#define WM8400_DAC_CLKDIV_5_5  0x14
+#define WM8400_DAC_CLKDIV_6    0x18
+
+#define WM8400_ADC_CLKDIV_1    0x00
+#define WM8400_ADC_CLKDIV_1_5  0x20
+#define WM8400_ADC_CLKDIV_2    0x40
+#define WM8400_ADC_CLKDIV_3    0x60
+#define WM8400_ADC_CLKDIV_4    0x80
+#define WM8400_ADC_CLKDIV_5_5  0xa0
+#define WM8400_ADC_CLKDIV_6    0xc0
+
+
+#define WM8400_BCLK_DIV_1                       (0x0 << 1)
+#define WM8400_BCLK_DIV_1_5                     (0x1 << 1)
+#define WM8400_BCLK_DIV_2                       (0x2 << 1)
+#define WM8400_BCLK_DIV_3                       (0x3 << 1)
+#define WM8400_BCLK_DIV_4                       (0x4 << 1)
+#define WM8400_BCLK_DIV_5_5                     (0x5 << 1)
+#define WM8400_BCLK_DIV_6                       (0x6 << 1)
+#define WM8400_BCLK_DIV_8                       (0x7 << 1)
+#define WM8400_BCLK_DIV_11                      (0x8 << 1)
+#define WM8400_BCLK_DIV_12                      (0x9 << 1)
+#define WM8400_BCLK_DIV_16                      (0xA << 1)
+#define WM8400_BCLK_DIV_22                      (0xB << 1)
+#define WM8400_BCLK_DIV_24                      (0xC << 1)
+#define WM8400_BCLK_DIV_32                      (0xD << 1)
+#define WM8400_BCLK_DIV_44                      (0xE << 1)
+#define WM8400_BCLK_DIV_48                      (0xF << 1)
+
+extern struct snd_soc_codec_dai wm8400_dai;
+extern struct snd_soc_codec_device soc_codec_dev_wm8400;
+
+#endif
