summary refs log tree commit diff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-10-14 12:28:55 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-14 12:28:55 -0700
commitc269bc00fcb876ae3b85f178f1e34601185c8ccc (patch)
treecae61de48c631301984a5e8be345be220adabb82
parent2d51b75370d83535883c66521b03fcd6a1f1f68d (diff)
parentcaf1859199e4360ffa826179bc0e881b0348f3ce (diff)
downloadlinux-c269bc00fcb876ae3b85f178f1e34601185c8ccc.tar.gz
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6: (26 commits)
  mfd: Fix warning in WM8350
  mfd: Add placeholders for WM8350 client devices
  da903x: add regulator support for DA9030/DA9034
  mfd: Add WM8350 subdevice registration helper
  regulator: Add WM8350 regulator support
  mfd: Add WM8350 interrupt support
  mfd: Add initialisation callback for WM8350
  mfd: Add GPIO pin configuration support for WM8350
  mfd: Add I2C control support for WM8350
  mfd: Core support for the WM8350 AudioPlus PMIC
  mfd: Add WM8350 watchdog register definitions
  mfd: Add WM8350 RTC register definitions
  mfd: Add WM8350 comparator register definitions
  mfd: Add WM8350 PMU register definitions
  mfd: Add WM8350 PMIC register definitions
  mfd: Add WM8350 GPIO register definitions
  mfd: Add WM8350 audio register definitions
  regulator: Export regulator name via sysfs
  regulator: Add WM8400 regulator support
  mfd: Core support for the WM8400 AudioPlus HiFi CODEC and PMU
  ...
-rw-r--r--Documentation/ABI/testing/sysfs-class-regulator55
-rw-r--r--Documentation/power/regulator/machine.txt140
-rw-r--r--Documentation/power/regulator/regulator.txt8
-rw-r--r--MAINTAINERS3
-rw-r--r--drivers/mfd/Kconfig38
-rw-r--r--drivers/mfd/Makefile5
-rw-r--r--drivers/mfd/wm8350-core.c1273
-rw-r--r--drivers/mfd/wm8350-gpio.c222
-rw-r--r--drivers/mfd/wm8350-i2c.c120
-rw-r--r--drivers/mfd/wm8350-regmap.c1347
-rw-r--r--drivers/mfd/wm8400-core.c455
-rw-r--r--drivers/regulator/Kconfig24
-rw-r--r--drivers/regulator/Makefile3
-rw-r--r--drivers/regulator/bq24022.c21
-rw-r--r--drivers/regulator/core.c508
-rw-r--r--drivers/regulator/da903x.c513
-rw-r--r--drivers/regulator/wm8350-regulator.c1431
-rw-r--r--drivers/regulator/wm8400-regulator.c368
-rw-r--r--include/linux/mfd/wm8350/audio.h598
-rw-r--r--include/linux/mfd/wm8350/comparator.h167
-rw-r--r--include/linux/mfd/wm8350/core.h631
-rw-r--r--include/linux/mfd/wm8350/gpio.h342
-rw-r--r--include/linux/mfd/wm8350/pmic.h741
-rw-r--r--include/linux/mfd/wm8350/rtc.h266
-rw-r--r--include/linux/mfd/wm8350/supply.h111
-rw-r--r--include/linux/mfd/wm8350/wdt.h28
-rw-r--r--include/linux/mfd/wm8400-audio.h1186
-rw-r--r--include/linux/mfd/wm8400-private.h936
-rw-r--r--include/linux/mfd/wm8400.h40
-rw-r--r--include/linux/regulator/driver.h10
-rw-r--r--include/linux/regulator/machine.h30
31 files changed, 11267 insertions, 353 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-regulator b/Documentation/ABI/testing/sysfs-class-regulator
index 79a4a75b2d2c..3731f6f29bcb 100644
--- a/Documentation/ABI/testing/sysfs-class-regulator
+++ b/Documentation/ABI/testing/sysfs-class-regulator
@@ -1,7 +1,7 @@
 What:		/sys/class/regulator/.../state
 Date:		April 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		state. This holds the regulator output state.
@@ -27,7 +27,7 @@ Description:
 What:		/sys/class/regulator/.../type
 Date:		April 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		type. This holds the regulator type.
@@ -51,7 +51,7 @@ Description:
 What:		/sys/class/regulator/.../microvolts
 Date:		April 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		microvolts. This holds the regulator output voltage setting
@@ -65,7 +65,7 @@ Description:
 What:		/sys/class/regulator/.../microamps
 Date:		April 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		microamps. This holds the regulator output current limit
@@ -79,7 +79,7 @@ Description:
 What:		/sys/class/regulator/.../opmode
 Date:		April 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		opmode. This holds the regulator operating mode setting.
@@ -102,7 +102,7 @@ Description:
 What:		/sys/class/regulator/.../min_microvolts
 Date:		April 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		min_microvolts. This holds the minimum safe working regulator
@@ -116,7 +116,7 @@ Description:
 What:		/sys/class/regulator/.../max_microvolts
 Date:		April 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		max_microvolts. This holds the maximum safe working regulator
@@ -130,7 +130,7 @@ Description:
 What:		/sys/class/regulator/.../min_microamps
 Date:		April 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		min_microamps. This holds the minimum safe working regulator
@@ -145,7 +145,7 @@ Description:
 What:		/sys/class/regulator/.../max_microamps
 Date:		April 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		max_microamps. This holds the maximum safe working regulator
@@ -157,10 +157,23 @@ Description:
 		platform code.
 
 
+What:		/sys/class/regulator/.../name
+Date:		October 2008
+KernelVersion:	2.6.28
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
+Description:
+		Each regulator directory will contain a field called
+		name. This holds a string identifying the regulator for
+		display purposes.
+
+		NOTE: this will be empty if no suitable name is provided
+		by platform or regulator drivers.
+
+
 What:		/sys/class/regulator/.../num_users
 Date:		April 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		num_users. This holds the number of consumer devices that
@@ -170,7 +183,7 @@ Description:
 What:		/sys/class/regulator/.../requested_microamps
 Date:		April 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		requested_microamps. This holds the total requested load
@@ -181,7 +194,7 @@ Description:
 What:		/sys/class/regulator/.../parent
 Date:		April 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Some regulator directories will contain a link called parent.
 		This points to the parent or supply regulator if one exists.
@@ -189,7 +202,7 @@ Description:
 What:		/sys/class/regulator/.../suspend_mem_microvolts
 Date:		May 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		suspend_mem_microvolts. This holds the regulator output
@@ -203,7 +216,7 @@ Description:
 What:		/sys/class/regulator/.../suspend_disk_microvolts
 Date:		May 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		suspend_disk_microvolts. This holds the regulator output
@@ -217,7 +230,7 @@ Description:
 What:		/sys/class/regulator/.../suspend_standby_microvolts
 Date:		May 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		suspend_standby_microvolts. This holds the regulator output
@@ -231,7 +244,7 @@ Description:
 What:		/sys/class/regulator/.../suspend_mem_mode
 Date:		May 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		suspend_mem_mode. This holds the regulator operating mode
@@ -245,7 +258,7 @@ Description:
 What:		/sys/class/regulator/.../suspend_disk_mode
 Date:		May 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		suspend_disk_mode. This holds the regulator operating mode
@@ -258,7 +271,7 @@ Description:
 What:		/sys/class/regulator/.../suspend_standby_mode
 Date:		May 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		suspend_standby_mode. This holds the regulator operating mode
@@ -272,7 +285,7 @@ Description:
 What:		/sys/class/regulator/.../suspend_mem_state
 Date:		May 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		suspend_mem_state. This holds the regulator operating state
@@ -287,7 +300,7 @@ Description:
 What:		/sys/class/regulator/.../suspend_disk_state
 Date:		May 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		suspend_disk_state. This holds the regulator operating state
@@ -302,7 +315,7 @@ Description:
 What:		/sys/class/regulator/.../suspend_standby_state
 Date:		May 2008
 KernelVersion:	2.6.26
-Contact:	Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:	Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
 		Each regulator directory will contain a field called
 		suspend_standby_state. This holds the regulator operating
diff --git a/Documentation/power/regulator/machine.txt b/Documentation/power/regulator/machine.txt
index c9a35665cf70..ce3487d99abe 100644
--- a/Documentation/power/regulator/machine.txt
+++ b/Documentation/power/regulator/machine.txt
@@ -2,17 +2,8 @@ Regulator Machine Driver Interface
 ===================================
 
 The regulator machine driver interface is intended for board/machine specific
-initialisation code to configure the regulator subsystem. Typical things that
-machine drivers would do are :-
+initialisation code to configure the regulator subsystem.
 
- 1. Regulator -> Device mapping.
- 2. Regulator supply configuration.
- 3. Power Domain constraint setting.
-
-
-
-1. Regulator -> device mapping
-==============================
 Consider the following machine :-
 
   Regulator-1 -+-> Regulator-2 --> [Consumer A @ 1.8 - 2.0V]
@@ -21,81 +12,82 @@ Consider the following machine :-
 
 The drivers for consumers A & B must be mapped to the correct regulator in
 order to control their power supply. This mapping can be achieved in machine
-initialisation code by calling :-
+initialisation code by creating a struct regulator_consumer_supply for
+each regulator.
+
+struct regulator_consumer_supply {
+	struct device *dev;	/* consumer */
+	const char *supply;	/* consumer supply - e.g. "vcc" */
+};
 
-int regulator_set_device_supply(const char *regulator, struct device *dev,
-				const char *supply);
+e.g. for the machine above
 
-and is shown with the following code :-
+static struct regulator_consumer_supply regulator1_consumers[] = {
+{
+	.dev	= &platform_consumerB_device.dev,
+	.supply	= "Vcc",
+},};
 
-regulator_set_device_supply("Regulator-1", devB, "Vcc");
-regulator_set_device_supply("Regulator-2", devA, "Vcc");
+static struct regulator_consumer_supply regulator2_consumers[] = {
+{
+	.dev	= &platform_consumerA_device.dev,
+	.supply	= "Vcc",
+},};
 
 This maps Regulator-1 to the 'Vcc' supply for Consumer B and maps Regulator-2
 to the 'Vcc' supply for Consumer A.
 
-
-2. Regulator supply configuration.
-==================================
-Consider the following machine (again) :-
-
-  Regulator-1 -+-> Regulator-2 --> [Consumer A @ 1.8 - 2.0V]
-               |
-               +-> [Consumer B @ 3.3V]
+Constraints can now be registered by defining a struct regulator_init_data
+for each regulator power domain. This structure also maps the consumers
+to their supply regulator :-
+
+static struct regulator_init_data regulator1_data = {
+	.constraints = {
+		.min_uV = 3300000,
+		.max_uV = 3300000,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(regulator1_consumers),
+	.consumer_supplies = regulator1_consumers,
+};
 
 Regulator-1 supplies power to Regulator-2. This relationship must be registered
 with the core so that Regulator-1 is also enabled when Consumer A enables it's
-supply (Regulator-2).
-
-This relationship can be register with the core via :-
-
-int regulator_set_supply(const char *regulator, const char *regulator_supply);
-
-In this example we would use the following code :-
-
-regulator_set_supply("Regulator-2", "Regulator-1");
-
-Relationships can be queried by calling :-
-
-const char *regulator_get_supply(const char *regulator);
-
-
-3. Power Domain constraint setting.
-===================================
-Each power domain within a system has physical constraints on voltage and
-current. This must be defined in software so that the power domain is always
-operated within specifications.
-
-Consider the following machine (again) :-
-
-  Regulator-1 -+-> Regulator-2 --> [Consumer A @ 1.8 - 2.0V]
-               |
-               +-> [Consumer B @ 3.3V]
-
-This gives us two regulators and two power domains:
-
-                   Domain 1: Regulator-2, Consumer B.
-                   Domain 2: Consumer A.
-
-Constraints can be registered by calling :-
-
-int regulator_set_platform_constraints(const char *regulator,
-	struct regulation_constraints *constraints);
-
-The example is defined as follows :-
-
-struct regulation_constraints domain_1 = {
-	.min_uV = 3300000,
-	.max_uV = 3300000,
-	.valid_modes_mask = REGULATOR_MODE_NORMAL,
+supply (Regulator-2). The supply regulator is set by the supply_regulator_dev
+field below:-
+
+static struct regulator_init_data regulator2_data = {
+	.supply_regulator_dev = &platform_regulator1_device.dev,
+	.constraints = {
+		.min_uV = 1800000,
+		.max_uV = 2000000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(regulator2_consumers),
+	.consumer_supplies = regulator2_consumers,
 };
 
-struct regulation_constraints domain_2 = {
-	.min_uV = 1800000,
-	.max_uV = 2000000,
-	.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-	.valid_modes_mask = REGULATOR_MODE_NORMAL,
+Finally the regulator devices must be registered in the usual manner.
+
+static struct platform_device regulator_devices[] = {
+{
+	.name = "regulator",
+	.id = DCDC_1,
+	.dev = {
+		.platform_data = &regulator1_data,
+	},
+},
+{
+	.name = "regulator",
+	.id = DCDC_2,
+	.dev = {
+		.platform_data = &regulator2_data,
+	},
+},
 };
+/* register regulator 1 device */
+platform_device_register(&wm8350_regulator_devices[0]);
 
-regulator_set_platform_constraints("Regulator-1", &domain_1);
-regulator_set_platform_constraints("Regulator-2", &domain_2);
+/* register regulator 2 device */
+platform_device_register(&wm8350_regulator_devices[1]);
diff --git a/Documentation/power/regulator/regulator.txt b/Documentation/power/regulator/regulator.txt
index a69050143592..4200accb9bba 100644
--- a/Documentation/power/regulator/regulator.txt
+++ b/Documentation/power/regulator/regulator.txt
@@ -10,11 +10,11 @@ Registration
 
 Drivers can register a regulator by calling :-
 
-struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
-					  void *reg_data);
+struct regulator_dev *regulator_register(struct device *dev,
+	struct regulator_desc *regulator_desc);
 
-This will register the regulators capabilities and operations the regulator
-core. The core does not touch reg_data (private to regulator driver).
+This will register the regulators capabilities and operations to the regulator
+core.
 
 Regulators can be unregistered by calling :-
 
diff --git a/MAINTAINERS b/MAINTAINERS
index 988b0a852890..5d0b8a23d639 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4520,10 +4520,11 @@ S:	Maintained
 
 VOLTAGE AND CURRENT REGULATOR FRAMEWORK
 P:	Liam Girdwood
-M:	lg@opensource.wolfsonmicro.com
+M:	lrg@slimlogic.co.uk
 P:	Mark Brown
 M:	broonie@opensource.wolfsonmicro.com
 W:	http://opensource.wolfsonmicro.com/node/15
+W:	http://www.slimlogic.co.uk/?page_id=5
 T:	git kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6.git
 S:	Supported
 
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 0dae245c6259..5eff8ad834d6 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -87,6 +87,44 @@ config MFD_TC6393XB
 	help
 	  Support for Toshiba Mobile IO Controller TC6393XB
 
+config MFD_WM8400
+	tristate "Support Wolfson Microelectronics WM8400"
+	help
+	  Support for the Wolfson Microelecronics WM8400 PMIC and audio
+	  CODEC.  This driver adds provides common support for accessing
+	  the device, additional drivers must be enabled in order to use
+	  the functionality of the device.
+
+config MFD_WM8350
+	tristate
+
+config MFD_WM8350_CONFIG_MODE_0
+	bool
+	depends on MFD_WM8350
+
+config MFD_WM8350_CONFIG_MODE_1
+	bool
+	depends on MFD_WM8350
+
+config MFD_WM8350_CONFIG_MODE_2
+	bool
+	depends on MFD_WM8350
+
+config MFD_WM8350_CONFIG_MODE_3
+	bool
+	depends on MFD_WM8350
+
+config MFD_WM8350_I2C
+	tristate "Support Wolfson Microelectronics WM8350 with I2C"
+	select MFD_WM8350
+	depends on I2C
+	help
+	  The WM8350 is an integrated audio and power management
+	  subsystem with watchdog and RTC functionality for embedded
+	  systems.  This option enables core support for the WM8350 with
+	  I2C as the control interface.  Additional options must be
+	  selected to enable support for the functionality of the chip.
+
 endmenu
 
 menu "Multimedia Capabilities Port drivers"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 6abebe364419..759b1fe1c891 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -12,6 +12,11 @@ obj-$(CONFIG_MFD_T7L66XB)	+= t7l66xb.o
 obj-$(CONFIG_MFD_TC6387XB)	+= tc6387xb.o
 obj-$(CONFIG_MFD_TC6393XB)	+= tc6393xb.o
 
+obj-$(CONFIG_MFD_WM8400)	+= wm8400-core.o
+wm8350-objs			:= wm8350-core.o wm8350-regmap.o wm8350-gpio.o
+obj-$(CONFIG_MFD_WM8350)	+= wm8350.o
+obj-$(CONFIG_MFD_WM8350_I2C)	+= wm8350-i2c.o
+
 obj-$(CONFIG_MFD_CORE)		+= mfd-core.o
 
 obj-$(CONFIG_MCP)		+= mcp-core.o
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
new file mode 100644
index 000000000000..25a7a5d08bce
--- /dev/null
+++ b/drivers/mfd/wm8350-core.c
@@ -0,0 +1,1273 @@
+/*
+ * wm8350-core.c  --  Device access for Wolfson WM8350
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood, Mark Brown
+ *
+ *  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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/bug.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/audio.h>
+#include <linux/mfd/wm8350/comparator.h>
+#include <linux/mfd/wm8350/gpio.h>
+#include <linux/mfd/wm8350/pmic.h>
+#include <linux/mfd/wm8350/rtc.h>
+#include <linux/mfd/wm8350/supply.h>
+#include <linux/mfd/wm8350/wdt.h>
+
+#define WM8350_UNLOCK_KEY		0x0013
+#define WM8350_LOCK_KEY			0x0000
+
+#define WM8350_CLOCK_CONTROL_1		0x28
+#define WM8350_AIF_TEST			0x74
+
+/* debug */
+#define WM8350_BUS_DEBUG 0
+#if WM8350_BUS_DEBUG
+#define dump(regs, src) do { \
+	int i_; \
+	u16 *src_ = src; \
+	printk(KERN_DEBUG); \
+	for (i_ = 0; i_ < regs; i_++) \
+		printk(" 0x%4.4x", *src_++); \
+	printk("\n"); \
+} while (0);
+#else
+#define dump(bytes, src)
+#endif
+
+#define WM8350_LOCK_DEBUG 0
+#if WM8350_LOCK_DEBUG
+#define ldbg(format, arg...) printk(format, ## arg)
+#else
+#define ldbg(format, arg...)
+#endif
+
+/*
+ * WM8350 Device IO
+ */
+static DEFINE_MUTEX(io_mutex);
+static DEFINE_MUTEX(reg_lock_mutex);
+static DEFINE_MUTEX(auxadc_mutex);
+
+/* Perform a physical read from the device.
+ */
+static int wm8350_phys_read(struct wm8350 *wm8350, u8 reg, int num_regs,
+			    u16 *dest)
+{
+	int i, ret;
+	int bytes = num_regs * 2;
+
+	dev_dbg(wm8350->dev, "volatile read\n");
+	ret = wm8350->read_dev(wm8350, reg, bytes, (char *)dest);
+
+	for (i = reg; i < reg + num_regs; i++) {
+		/* Cache is CPU endian */
+		dest[i - reg] = be16_to_cpu(dest[i - reg]);
+
+		/* Satisfy non-volatile bits from cache */
+		dest[i - reg] &= wm8350_reg_io_map[i].vol;
+		dest[i - reg] |= wm8350->reg_cache[i];
+
+		/* Mask out non-readable bits */
+		dest[i - reg] &= wm8350_reg_io_map[i].readable;
+	}
+
+	dump(num_regs, dest);
+
+	return ret;
+}
+
+static int wm8350_read(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *dest)
+{
+	int i;
+	int end = reg + num_regs;
+	int ret = 0;
+	int bytes = num_regs * 2;
+
+	if (wm8350->read_dev == NULL)
+		return -ENODEV;
+
+	if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) {
+		dev_err(wm8350->dev, "invalid reg %x\n",
+			reg + num_regs - 1);
+		return -EINVAL;
+	}
+
+	dev_dbg(wm8350->dev,
+		"%s R%d(0x%2.2x) %d regs\n", __func__, reg, reg, num_regs);
+
+#if WM8350_BUS_DEBUG
+	/* we can _safely_ read any register, but warn if read not supported */
+	for (i = reg; i < end; i++) {
+		if (!wm8350_reg_io_map[i].readable)
+			dev_warn(wm8350->dev,
+				"reg R%d is not readable\n", i);
+	}
+#endif
+
+	/* if any volatile registers are required, then read back all */
+	for (i = reg; i < end; i++)
+		if (wm8350_reg_io_map[i].vol)
+			return wm8350_phys_read(wm8350, reg, num_regs, dest);
+
+	/* no volatiles, then cache is good */
+	dev_dbg(wm8350->dev, "cache read\n");
+	memcpy(dest, &wm8350->reg_cache[reg], bytes);
+	dump(num_regs, dest);
+	return ret;
+}
+
+static inline int is_reg_locked(struct wm8350 *wm8350, u8 reg)
+{
+	if (reg == WM8350_SECURITY ||
+	    wm8350->reg_cache[WM8350_SECURITY] == WM8350_UNLOCK_KEY)
+		return 0;
+
+	if ((reg == WM8350_GPIO_CONFIGURATION_I_O) ||
+	    (reg >= WM8350_GPIO_FUNCTION_SELECT_1 &&
+	     reg <= WM8350_GPIO_FUNCTION_SELECT_4) ||
+	    (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 &&
+	     reg <= WM8350_BATTERY_CHARGER_CONTROL_3))
+		return 1;
+	return 0;
+}
+
+static int wm8350_write(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *src)
+{
+	int i;
+	int end = reg + num_regs;
+	int bytes = num_regs * 2;
+
+	if (wm8350->write_dev == NULL)
+		return -ENODEV;
+
+	if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) {
+		dev_err(wm8350->dev, "invalid reg %x\n",
+			reg + num_regs - 1);
+		return -EINVAL;
+	}
+
+	/* it's generally not a good idea to write to RO or locked registers */
+	for (i = reg; i < end; i++) {
+		if (!wm8350_reg_io_map[i].writable) {
+			dev_err(wm8350->dev,
+				"attempted write to read only reg R%d\n", i);
+			return -EINVAL;
+		}
+
+		if (is_reg_locked(wm8350, i)) {
+			dev_err(wm8350->dev,
+			       "attempted write to locked reg R%d\n", i);
+			return -EINVAL;
+		}
+
+		src[i - reg] &= wm8350_reg_io_map[i].writable;
+
+		wm8350->reg_cache[i] =
+			(wm8350->reg_cache[i] & ~wm8350_reg_io_map[i].writable)
+			| src[i - reg];
+
+		src[i - reg] = cpu_to_be16(src[i - reg]);
+	}
+
+	/* Actually write it out */
+	return wm8350->write_dev(wm8350, reg, bytes, (char *)src);
+}
+
+/*
+ * Safe read, modify, write methods
+ */
+int wm8350_clear_bits(struct wm8350 *wm8350, u16 reg, u16 mask)
+{
+	u16 data;
+	int err;
+
+	mutex_lock(&io_mutex);
+	err = wm8350_read(wm8350, reg, 1, &data);
+	if (err) {
+		dev_err(wm8350->dev, "read from reg R%d failed\n", reg);
+		goto out;
+	}
+
+	data &= ~mask;
+	err = wm8350_write(wm8350, reg, 1, &data);
+	if (err)
+		dev_err(wm8350->dev, "write to reg R%d failed\n", reg);
+out:
+	mutex_unlock(&io_mutex);
+	return err;
+}
+EXPORT_SYMBOL_GPL(wm8350_clear_bits);
+
+int wm8350_set_bits(struct wm8350 *wm8350, u16 reg, u16 mask)
+{
+	u16 data;
+	int err;
+
+	mutex_lock(&io_mutex);
+	err = wm8350_read(wm8350, reg, 1, &data);
+	if (err) {
+		dev_err(wm8350->dev, "read from reg R%d failed\n", reg);
+		goto out;
+	}
+
+	data |= mask;
+	err = wm8350_write(wm8350, reg, 1, &data);
+	if (err)
+		dev_err(wm8350->dev, "write to reg R%d failed\n", reg);
+out:
+	mutex_unlock(&io_mutex);
+	return err;
+}
+EXPORT_SYMBOL_GPL(wm8350_set_bits);
+
+u16 wm8350_reg_read(struct wm8350 *wm8350, int reg)
+{
+	u16 data;
+	int err;
+
+	mutex_lock(&io_mutex);
+	err = wm8350_read(wm8350, reg, 1, &data);
+	if (err)
+		dev_err(wm8350->dev, "read from reg R%d failed\n", reg);
+
+	mutex_unlock(&io_mutex);
+	return data;
+}
+EXPORT_SYMBOL_GPL(wm8350_reg_read);
+
+int wm8350_reg_write(struct wm8350 *wm8350, int reg, u16 val)
+{
+	int ret;
+	u16 data = val;
+
+	mutex_lock(&io_mutex);
+	ret = wm8350_write(wm8350, reg, 1, &data);
+	if (ret)
+		dev_err(wm8350->dev, "write to reg R%d failed\n", reg);
+	mutex_unlock(&io_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_reg_write);
+
+int wm8350_block_read(struct wm8350 *wm8350, int start_reg, int regs,
+		      u16 *dest)
+{
+	int err = 0;
+
+	mutex_lock(&io_mutex);
+	err = wm8350_read(wm8350, start_reg, regs, dest);
+	if (err)
+		dev_err(wm8350->dev, "block read starting from R%d failed\n",
+			start_reg);
+	mutex_unlock(&io_mutex);
+	return err;
+}
+EXPORT_SYMBOL_GPL(wm8350_block_read);
+
+int wm8350_block_write(struct wm8350 *wm8350, int start_reg, int regs,
+		       u16 *src)
+{
+	int ret = 0;
+
+	mutex_lock(&io_mutex);
+	ret = wm8350_write(wm8350, start_reg, regs, src);
+	if (ret)
+		dev_err(wm8350->dev, "block write starting at R%d failed\n",
+			start_reg);
+	mutex_unlock(&io_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_block_write);
+
+int wm8350_reg_lock(struct wm8350 *wm8350)
+{
+	u16 key = WM8350_LOCK_KEY;
+	int ret;
+
+	ldbg(__func__);
+	mutex_lock(&io_mutex);
+	ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key);
+	if (ret)
+		dev_err(wm8350->dev, "lock failed\n");
+	mutex_unlock(&io_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_reg_lock);
+
+int wm8350_reg_unlock(struct wm8350 *wm8350)
+{
+	u16 key = WM8350_UNLOCK_KEY;
+	int ret;
+
+	ldbg(__func__);
+	mutex_lock(&io_mutex);
+	ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key);
+	if (ret)
+		dev_err(wm8350->dev, "unlock failed\n");
+	mutex_unlock(&io_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_reg_unlock);
+
+static void wm8350_irq_call_handler(struct wm8350 *wm8350, int irq)
+{
+	mutex_lock(&wm8350->irq_mutex);
+
+	if (wm8350->irq[irq].handler)
+		wm8350->irq[irq].handler(wm8350, irq, wm8350->irq[irq].data);
+	else {
+		dev_err(wm8350->dev, "irq %d nobody cared. now masked.\n",
+			irq);
+		wm8350_mask_irq(wm8350, irq);
+	}
+
+	mutex_unlock(&wm8350->irq_mutex);
+}
+
+/*
+ * wm8350_irq_worker actually handles the interrupts.  Since all
+ * interrupts are clear on read the IRQ line will be reasserted and
+ * the physical IRQ will be handled again if another interrupt is
+ * asserted while we run - in the normal course of events this is a
+ * rare occurrence so we save I2C/SPI reads.
+ */
+static void wm8350_irq_worker(struct work_struct *work)
+{
+	struct wm8350 *wm8350 = container_of(work, struct wm8350, irq_work);
+	u16 level_one, status1, status2, comp;
+
+	/* TODO: Use block reads to improve performance? */
+	level_one = wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS)
+		& ~wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK);
+	status1 = wm8350_reg_read(wm8350, WM8350_INT_STATUS_1)
+		& ~wm8350_reg_read(wm8350, WM8350_INT_STATUS_1_MASK);
+	status2 = wm8350_reg_read(wm8350, WM8350_INT_STATUS_2)
+		& ~wm8350_reg_read(wm8350, WM8350_INT_STATUS_2_MASK);
+	comp = wm8350_reg_read(wm8350, WM8350_COMPARATOR_INT_STATUS)
+		& ~wm8350_reg_read(wm8350, WM8350_COMPARATOR_INT_STATUS_MASK);
+
+	/* over current */
+	if (level_one & WM8350_OC_INT) {
+		u16 oc;
+
+		oc = wm8350_reg_read(wm8350, WM8350_OVER_CURRENT_INT_STATUS);
+		oc &= ~wm8350_reg_read(wm8350,
+				       WM8350_OVER_CURRENT_INT_STATUS_MASK);
+
+		if (oc & WM8350_OC_LS_EINT)	/* limit switch */
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_OC_LS);
+	}
+
+	/* under voltage */
+	if (level_one & WM8350_UV_INT) {
+		u16 uv;
+
+		uv = wm8350_reg_read(wm8350, WM8350_UNDER_VOLTAGE_INT_STATUS);
+		uv &= ~wm8350_reg_read(wm8350,
+				       WM8350_UNDER_VOLTAGE_INT_STATUS_MASK);
+
+		if (uv & WM8350_UV_DC1_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC1);
+		if (uv & WM8350_UV_DC2_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC2);
+		if (uv & WM8350_UV_DC3_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC3);
+		if (uv & WM8350_UV_DC4_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC4);
+		if (uv & WM8350_UV_DC5_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC5);
+		if (uv & WM8350_UV_DC6_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC6);
+		if (uv & WM8350_UV_LDO1_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO1);
+		if (uv & WM8350_UV_LDO2_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO2);
+		if (uv & WM8350_UV_LDO3_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO3);
+		if (uv & WM8350_UV_LDO4_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO4);
+	}
+
+	/* charger, RTC */
+	if (status1) {
+		if (status1 & WM8350_CHG_BAT_HOT_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_CHG_BAT_HOT);
+		if (status1 & WM8350_CHG_BAT_COLD_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_CHG_BAT_COLD);
+		if (status1 & WM8350_CHG_BAT_FAIL_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_CHG_BAT_FAIL);
+		if (status1 & WM8350_CHG_TO_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_CHG_TO);
+		if (status1 & WM8350_CHG_END_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_CHG_END);
+		if (status1 & WM8350_CHG_START_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_CHG_START);
+		if (status1 & WM8350_CHG_FAST_RDY_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_CHG_FAST_RDY);
+		if (status1 & WM8350_CHG_VBATT_LT_3P9_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_CHG_VBATT_LT_3P9);
+		if (status1 & WM8350_CHG_VBATT_LT_3P1_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_CHG_VBATT_LT_3P1);
+		if (status1 & WM8350_CHG_VBATT_LT_2P85_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_CHG_VBATT_LT_2P85);
+		if (status1 & WM8350_RTC_ALM_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_RTC_ALM);
+		if (status1 & WM8350_RTC_SEC_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_RTC_SEC);
+		if (status1 & WM8350_RTC_PER_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_RTC_PER);
+	}
+
+	/* current sink, system, aux adc */
+	if (status2) {
+		if (status2 & WM8350_CS1_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_CS1);
+		if (status2 & WM8350_CS2_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_CS2);
+
+		if (status2 & WM8350_SYS_HYST_COMP_FAIL_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_SYS_HYST_COMP_FAIL);
+		if (status2 & WM8350_SYS_CHIP_GT115_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_SYS_CHIP_GT115);
+		if (status2 & WM8350_SYS_CHIP_GT140_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_SYS_CHIP_GT140);
+		if (status2 & WM8350_SYS_WDOG_TO_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_SYS_WDOG_TO);
+
+		if (status2 & WM8350_AUXADC_DATARDY_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_AUXADC_DATARDY);
+		if (status2 & WM8350_AUXADC_DCOMP4_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_AUXADC_DCOMP4);
+		if (status2 & WM8350_AUXADC_DCOMP3_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_AUXADC_DCOMP3);
+		if (status2 & WM8350_AUXADC_DCOMP2_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_AUXADC_DCOMP2);
+		if (status2 & WM8350_AUXADC_DCOMP1_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_AUXADC_DCOMP1);
+
+		if (status2 & WM8350_USB_LIMIT_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_USB_LIMIT);
+	}
+
+	/* wake, codec, ext */
+	if (comp) {
+		if (comp & WM8350_WKUP_OFF_STATE_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_WKUP_OFF_STATE);
+		if (comp & WM8350_WKUP_HIB_STATE_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_WKUP_HIB_STATE);
+		if (comp & WM8350_WKUP_CONV_FAULT_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_WKUP_CONV_FAULT);
+		if (comp & WM8350_WKUP_WDOG_RST_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_WKUP_WDOG_RST);
+		if (comp & WM8350_WKUP_GP_PWR_ON_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_WKUP_GP_PWR_ON);
+		if (comp & WM8350_WKUP_ONKEY_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_WKUP_ONKEY);
+		if (comp & WM8350_WKUP_GP_WAKEUP_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_WKUP_GP_WAKEUP);
+
+		if (comp & WM8350_CODEC_JCK_DET_L_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_CODEC_JCK_DET_L);
+		if (comp & WM8350_CODEC_JCK_DET_R_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_CODEC_JCK_DET_R);
+		if (comp & WM8350_CODEC_MICSCD_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_CODEC_MICSCD);
+		if (comp & WM8350_CODEC_MICD_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_CODEC_MICD);
+
+		if (comp & WM8350_EXT_USB_FB_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_EXT_USB_FB);
+		if (comp & WM8350_EXT_WALL_FB_EINT)
+			wm8350_irq_call_handler(wm8350,
+						WM8350_IRQ_EXT_WALL_FB);
+		if (comp & WM8350_EXT_BAT_FB_EINT)
+			wm8350_irq_call_handler(wm8350, WM8350_IRQ_EXT_BAT_FB);
+	}
+
+	if (level_one & WM8350_GP_INT) {
+		int i;
+		u16 gpio;
+
+		gpio = wm8350_reg_read(wm8350, WM8350_GPIO_INT_STATUS);
+		gpio &= ~wm8350_reg_read(wm8350,
+					 WM8350_GPIO_INT_STATUS_MASK);
+
+		for (i = 0; i < 12; i++) {
+			if (gpio & (1 << i))
+				wm8350_irq_call_handler(wm8350,
+							WM8350_IRQ_GPIO(i));
+		}
+	}
+
+	enable_irq(wm8350->chip_irq);
+}
+
+static irqreturn_t wm8350_irq(int irq, void *data)
+{
+	struct wm8350 *wm8350 = data;
+
+	disable_irq_nosync(irq);
+	schedule_work(&wm8350->irq_work);
+
+	return IRQ_HANDLED;
+}
+
+int wm8350_register_irq(struct wm8350 *wm8350, int irq,
+			void (*handler) (struct wm8350 *, int, void *),
+			void *data)
+{
+	if (irq < 0 || irq > WM8350_NUM_IRQ || !handler)
+		return -EINVAL;
+
+	if (wm8350->irq[irq].handler)
+		return -EBUSY;
+
+	mutex_lock(&wm8350->irq_mutex);
+	wm8350->irq[irq].handler = handler;
+	wm8350->irq[irq].data = data;
+	mutex_unlock(&wm8350->irq_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_register_irq);
+
+int wm8350_free_irq(struct wm8350 *wm8350, int irq)
+{
+	if (irq < 0 || irq > WM8350_NUM_IRQ)
+		return -EINVAL;
+
+	mutex_lock(&wm8350->irq_mutex);
+	wm8350->irq[irq].handler = NULL;
+	mutex_unlock(&wm8350->irq_mutex);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_free_irq);
+
+int wm8350_mask_irq(struct wm8350 *wm8350, int irq)
+{
+	switch (irq) {
+	case WM8350_IRQ_CHG_BAT_HOT:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+				       WM8350_IM_CHG_BAT_HOT_EINT);
+	case WM8350_IRQ_CHG_BAT_COLD:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+				       WM8350_IM_CHG_BAT_COLD_EINT);
+	case WM8350_IRQ_CHG_BAT_FAIL:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+				       WM8350_IM_CHG_BAT_FAIL_EINT);
+	case WM8350_IRQ_CHG_TO:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+				       WM8350_IM_CHG_TO_EINT);
+	case WM8350_IRQ_CHG_END:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+				       WM8350_IM_CHG_END_EINT);
+	case WM8350_IRQ_CHG_START:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+				       WM8350_IM_CHG_START_EINT);
+	case WM8350_IRQ_CHG_FAST_RDY:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+				       WM8350_IM_CHG_FAST_RDY_EINT);
+	case WM8350_IRQ_RTC_PER:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+				       WM8350_IM_RTC_PER_EINT);
+	case WM8350_IRQ_RTC_SEC:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+				       WM8350_IM_RTC_SEC_EINT);
+	case WM8350_IRQ_RTC_ALM:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+				       WM8350_IM_RTC_ALM_EINT);
+	case WM8350_IRQ_CHG_VBATT_LT_3P9:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+				       WM8350_IM_CHG_VBATT_LT_3P9_EINT);
+	case WM8350_IRQ_CHG_VBATT_LT_3P1:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+				       WM8350_IM_CHG_VBATT_LT_3P1_EINT);
+	case WM8350_IRQ_CHG_VBATT_LT_2P85:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+				       WM8350_IM_CHG_VBATT_LT_2P85_EINT);
+	case WM8350_IRQ_CS1:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+				       WM8350_IM_CS1_EINT);
+	case WM8350_IRQ_CS2:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+				       WM8350_IM_CS2_EINT);
+	case WM8350_IRQ_USB_LIMIT:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+				       WM8350_IM_USB_LIMIT_EINT);
+	case WM8350_IRQ_AUXADC_DATARDY:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+				       WM8350_IM_AUXADC_DATARDY_EINT);
+	case WM8350_IRQ_AUXADC_DCOMP4:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+				       WM8350_IM_AUXADC_DCOMP4_EINT);
+	case WM8350_IRQ_AUXADC_DCOMP3:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+				       WM8350_IM_AUXADC_DCOMP3_EINT);
+	case WM8350_IRQ_AUXADC_DCOMP2:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+				       WM8350_IM_AUXADC_DCOMP2_EINT);
+	case WM8350_IRQ_AUXADC_DCOMP1:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+				       WM8350_IM_AUXADC_DCOMP1_EINT);
+	case WM8350_IRQ_SYS_HYST_COMP_FAIL:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+				       WM8350_IM_SYS_HYST_COMP_FAIL_EINT);
+	case WM8350_IRQ_SYS_CHIP_GT115:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+				       WM8350_IM_SYS_CHIP_GT115_EINT);
+	case WM8350_IRQ_SYS_CHIP_GT140:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+				       WM8350_IM_SYS_CHIP_GT140_EINT);
+	case WM8350_IRQ_SYS_WDOG_TO:
+		return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+				       WM8350_IM_SYS_WDOG_TO_EINT);
+	case WM8350_IRQ_UV_LDO4:
+		return wm8350_set_bits(wm8350,
+				       WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+				       WM8350_IM_UV_LDO4_EINT);
+	case WM8350_IRQ_UV_LDO3:
+		return wm8350_set_bits(wm8350,
+				       WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+				       WM8350_IM_UV_LDO3_EINT);
+	case WM8350_IRQ_UV_LDO2:
+		return wm8350_set_bits(wm8350,
+				       WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+				       WM8350_IM_UV_LDO2_EINT);
+	case WM8350_IRQ_UV_LDO1:
+		return wm8350_set_bits(wm8350,
+				       WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+				       WM8350_IM_UV_LDO1_EINT);
+	case WM8350_IRQ_UV_DC6:
+		return wm8350_set_bits(wm8350,
+				       WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+				       WM8350_IM_UV_DC6_EINT);
+	case WM8350_IRQ_UV_DC5:
+		return wm8350_set_bits(wm8350,
+				       WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+				       WM8350_IM_UV_DC5_EINT);
+	case WM8350_IRQ_UV_DC4:
+		return wm8350_set_bits(wm8350,
+				       WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+				       WM8350_IM_UV_DC4_EINT);
+	case WM8350_IRQ_UV_DC3:
+		return wm8350_set_bits(wm8350,
+				       WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+				       WM8350_IM_UV_DC3_EINT);
+	case WM8350_IRQ_UV_DC2:
+		return wm8350_set_bits(wm8350,
+				       WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+				       WM8350_IM_UV_DC2_EINT);
+	case WM8350_IRQ_UV_DC1:
+		return wm8350_set_bits(wm8350,
+				       WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+				       WM8350_IM_UV_DC1_EINT);
+	case WM8350_IRQ_OC_LS:
+		return wm8350_set_bits(wm8350,
+				       WM8350_OVER_CURRENT_INT_STATUS_MASK,
+				       WM8350_IM_OC_LS_EINT);
+	case WM8350_IRQ_EXT_USB_FB:
+		return wm8350_set_bits(wm8350,
+				       WM8350_COMPARATOR_INT_STATUS_MASK,
+				       WM8350_IM_EXT_USB_FB_EINT);
+	case WM8350_IRQ_EXT_WALL_FB:
+		return wm8350_set_bits(wm8350,
+				       WM8350_COMPARATOR_INT_STATUS_MASK,
+				       WM8350_IM_EXT_WALL_FB_EINT);
+	case WM8350_IRQ_EXT_BAT_FB:
+		return wm8350_set_bits(wm8350,
+				       WM8350_COMPARATOR_INT_STATUS_MASK,
+				       WM8350_IM_EXT_BAT_FB_EINT);
+	case WM8350_IRQ_CODEC_JCK_DET_L:
+		return wm8350_set_bits(wm8350,
+				       WM8350_COMPARATOR_INT_STATUS_MASK,
+				       WM8350_IM_CODEC_JCK_DET_L_EINT);
+	case WM8350_IRQ_CODEC_JCK_DET_R:
+		return wm8350_set_bits(wm8350,
+				       WM8350_COMPARATOR_INT_STATUS_MASK,
+				       WM8350_IM_CODEC_JCK_DET_R_EINT);
+	case WM8350_IRQ_CODEC_MICSCD:
+		return wm8350_set_bits(wm8350,
+				       WM8350_COMPARATOR_INT_STATUS_MASK,
+				       WM8350_IM_CODEC_MICSCD_EINT);
+	case WM8350_IRQ_CODEC_MICD:
+		return wm8350_set_bits(wm8350,
+				       WM8350_COMPARATOR_INT_STATUS_MASK,
+				       WM8350_IM_CODEC_MICD_EINT);
+	case WM8350_IRQ_WKUP_OFF_STATE:
+		return wm8350_set_bits(wm8350,
+				       WM8350_COMPARATOR_INT_STATUS_MASK,
+				       WM8350_IM_WKUP_OFF_STATE_EINT);
+	case WM8350_IRQ_WKUP_HIB_STATE:
+		return wm8350_set_bits(wm8350,
+				       WM8350_COMPARATOR_INT_STATUS_MASK,
+				       WM8350_IM_WKUP_HIB_STATE_EINT);
+	case WM8350_IRQ_WKUP_CONV_FAULT:
+		return wm8350_set_bits(wm8350,
+				       WM8350_COMPARATOR_INT_STATUS_MASK,
+				       WM8350_IM_WKUP_CONV_FAULT_EINT);
+	case WM8350_IRQ_WKUP_WDOG_RST:
+		return wm8350_set_bits(wm8350,
+				       WM8350_COMPARATOR_INT_STATUS_MASK,
+				       WM8350_IM_WKUP_OFF_STATE_EINT);
+	case WM8350_IRQ_WKUP_GP_PWR_ON:
+		return wm8350_set_bits(wm8350,
+				       WM8350_COMPARATOR_INT_STATUS_MASK,
+				       WM8350_IM_WKUP_GP_PWR_ON_EINT);
+	case WM8350_IRQ_WKUP_ONKEY:
+		return wm8350_set_bits(wm8350,
+				       WM8350_COMPARATOR_INT_STATUS_MASK,
+				       WM8350_IM_WKUP_ONKEY_EINT);
+	case WM8350_IRQ_WKUP_GP_WAKEUP:
+		return wm8350_set_bits(wm8350,
+				       WM8350_COMPARATOR_INT_STATUS_MASK,
+				       WM8350_IM_WKUP_GP_WAKEUP_EINT);
+	case WM8350_IRQ_GPIO(0):
+		return wm8350_set_bits(wm8350,
+				       WM8350_GPIO_INT_STATUS_MASK,
+				       WM8350_IM_GP0_EINT);
+	case WM8350_IRQ_GPIO(1):
+		return wm8350_set_bits(wm8350,
+				       WM8350_GPIO_INT_STATUS_MASK,
+				       WM8350_IM_GP1_EINT);
+	case WM8350_IRQ_GPIO(2):
+		return wm8350_set_bits(wm8350,
+				       WM8350_GPIO_INT_STATUS_MASK,
+				       WM8350_IM_GP2_EINT);
+	case WM8350_IRQ_GPIO(3):
+		return wm8350_set_bits(wm8350,
+				       WM8350_GPIO_INT_STATUS_MASK,
+				       WM8350_IM_GP3_EINT);
+	case WM8350_IRQ_GPIO(4):
+		return wm8350_set_bits(wm8350,
+				       WM8350_GPIO_INT_STATUS_MASK,
+				       WM8350_IM_GP4_EINT);
+	case WM8350_IRQ_GPIO(5):
+		return wm8350_set_bits(wm8350,
+				       WM8350_GPIO_INT_STATUS_MASK,
+				       WM8350_IM_GP5_EINT);
+	case WM8350_IRQ_GPIO(6):
+		return wm8350_set_bits(wm8350,
+				       WM8350_GPIO_INT_STATUS_MASK,
+				       WM8350_IM_GP6_EINT);
+	case WM8350_IRQ_GPIO(7):
+		return wm8350_set_bits(wm8350,
+				       WM8350_GPIO_INT_STATUS_MASK,
+				       WM8350_IM_GP7_EINT);
+	case WM8350_IRQ_GPIO(8):
+		return wm8350_set_bits(wm8350,
+				       WM8350_GPIO_INT_STATUS_MASK,
+				       WM8350_IM_GP8_EINT);
+	case WM8350_IRQ_GPIO(9):
+		return wm8350_set_bits(wm8350,
+				       WM8350_GPIO_INT_STATUS_MASK,
+				       WM8350_IM_GP9_EINT);
+	case WM8350_IRQ_GPIO(10):
+		return wm8350_set_bits(wm8350,
+				       WM8350_GPIO_INT_STATUS_MASK,
+				       WM8350_IM_GP10_EINT);
+	case WM8350_IRQ_GPIO(11):
+		return wm8350_set_bits(wm8350,
+				       WM8350_GPIO_INT_STATUS_MASK,
+				       WM8350_IM_GP11_EINT);
+	case WM8350_IRQ_GPIO(12):
+		return wm8350_set_bits(wm8350,
+				       WM8350_GPIO_INT_STATUS_MASK,
+				       WM8350_IM_GP12_EINT);
+	default:
+		dev_warn(wm8350->dev, "Attempting to mask unknown IRQ %d\n",
+			 irq);
+		return -EINVAL;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_mask_irq);
+
+int wm8350_unmask_irq(struct wm8350 *wm8350, int irq)
+{
+	switch (irq) {
+	case WM8350_IRQ_CHG_BAT_HOT:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+					 WM8350_IM_CHG_BAT_HOT_EINT);
+	case WM8350_IRQ_CHG_BAT_COLD:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+					 WM8350_IM_CHG_BAT_COLD_EINT);
+	case WM8350_IRQ_CHG_BAT_FAIL:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+					 WM8350_IM_CHG_BAT_FAIL_EINT);
+	case WM8350_IRQ_CHG_TO:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+					 WM8350_IM_CHG_TO_EINT);
+	case WM8350_IRQ_CHG_END:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+					 WM8350_IM_CHG_END_EINT);
+	case WM8350_IRQ_CHG_START:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+					 WM8350_IM_CHG_START_EINT);
+	case WM8350_IRQ_CHG_FAST_RDY:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+					 WM8350_IM_CHG_FAST_RDY_EINT);
+	case WM8350_IRQ_RTC_PER:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+					 WM8350_IM_RTC_PER_EINT);
+	case WM8350_IRQ_RTC_SEC:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+					 WM8350_IM_RTC_SEC_EINT);
+	case WM8350_IRQ_RTC_ALM:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+					 WM8350_IM_RTC_ALM_EINT);
+	case WM8350_IRQ_CHG_VBATT_LT_3P9:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+					 WM8350_IM_CHG_VBATT_LT_3P9_EINT);
+	case WM8350_IRQ_CHG_VBATT_LT_3P1:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+					 WM8350_IM_CHG_VBATT_LT_3P1_EINT);
+	case WM8350_IRQ_CHG_VBATT_LT_2P85:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+					 WM8350_IM_CHG_VBATT_LT_2P85_EINT);
+	case WM8350_IRQ_CS1:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+					 WM8350_IM_CS1_EINT);
+	case WM8350_IRQ_CS2:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+					 WM8350_IM_CS2_EINT);
+	case WM8350_IRQ_USB_LIMIT:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+					 WM8350_IM_USB_LIMIT_EINT);
+	case WM8350_IRQ_AUXADC_DATARDY:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+					 WM8350_IM_AUXADC_DATARDY_EINT);
+	case WM8350_IRQ_AUXADC_DCOMP4:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+					 WM8350_IM_AUXADC_DCOMP4_EINT);
+	case WM8350_IRQ_AUXADC_DCOMP3:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+					 WM8350_IM_AUXADC_DCOMP3_EINT);
+	case WM8350_IRQ_AUXADC_DCOMP2:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+					 WM8350_IM_AUXADC_DCOMP2_EINT);
+	case WM8350_IRQ_AUXADC_DCOMP1:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+					 WM8350_IM_AUXADC_DCOMP1_EINT);
+	case WM8350_IRQ_SYS_HYST_COMP_FAIL:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+					 WM8350_IM_SYS_HYST_COMP_FAIL_EINT);
+	case WM8350_IRQ_SYS_CHIP_GT115:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+					 WM8350_IM_SYS_CHIP_GT115_EINT);
+	case WM8350_IRQ_SYS_CHIP_GT140:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+					 WM8350_IM_SYS_CHIP_GT140_EINT);
+	case WM8350_IRQ_SYS_WDOG_TO:
+		return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+					 WM8350_IM_SYS_WDOG_TO_EINT);
+	case WM8350_IRQ_UV_LDO4:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+					 WM8350_IM_UV_LDO4_EINT);
+	case WM8350_IRQ_UV_LDO3:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+					 WM8350_IM_UV_LDO3_EINT);
+	case WM8350_IRQ_UV_LDO2:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+					 WM8350_IM_UV_LDO2_EINT);
+	case WM8350_IRQ_UV_LDO1:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+					 WM8350_IM_UV_LDO1_EINT);
+	case WM8350_IRQ_UV_DC6:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+					 WM8350_IM_UV_DC6_EINT);
+	case WM8350_IRQ_UV_DC5:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+					 WM8350_IM_UV_DC5_EINT);
+	case WM8350_IRQ_UV_DC4:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+					 WM8350_IM_UV_DC4_EINT);
+	case WM8350_IRQ_UV_DC3:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+					 WM8350_IM_UV_DC3_EINT);
+	case WM8350_IRQ_UV_DC2:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+					 WM8350_IM_UV_DC2_EINT);
+	case WM8350_IRQ_UV_DC1:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+					 WM8350_IM_UV_DC1_EINT);
+	case WM8350_IRQ_OC_LS:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_OVER_CURRENT_INT_STATUS_MASK,
+					 WM8350_IM_OC_LS_EINT);
+	case WM8350_IRQ_EXT_USB_FB:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_COMPARATOR_INT_STATUS_MASK,
+					 WM8350_IM_EXT_USB_FB_EINT);
+	case WM8350_IRQ_EXT_WALL_FB:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_COMPARATOR_INT_STATUS_MASK,
+					 WM8350_IM_EXT_WALL_FB_EINT);
+	case WM8350_IRQ_EXT_BAT_FB:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_COMPARATOR_INT_STATUS_MASK,
+					 WM8350_IM_EXT_BAT_FB_EINT);
+	case WM8350_IRQ_CODEC_JCK_DET_L:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_COMPARATOR_INT_STATUS_MASK,
+					 WM8350_IM_CODEC_JCK_DET_L_EINT);
+	case WM8350_IRQ_CODEC_JCK_DET_R:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_COMPARATOR_INT_STATUS_MASK,
+					 WM8350_IM_CODEC_JCK_DET_R_EINT);
+	case WM8350_IRQ_CODEC_MICSCD:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_COMPARATOR_INT_STATUS_MASK,
+					 WM8350_IM_CODEC_MICSCD_EINT);
+	case WM8350_IRQ_CODEC_MICD:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_COMPARATOR_INT_STATUS_MASK,
+					 WM8350_IM_CODEC_MICD_EINT);
+	case WM8350_IRQ_WKUP_OFF_STATE:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_COMPARATOR_INT_STATUS_MASK,
+					 WM8350_IM_WKUP_OFF_STATE_EINT);
+	case WM8350_IRQ_WKUP_HIB_STATE:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_COMPARATOR_INT_STATUS_MASK,
+					 WM8350_IM_WKUP_HIB_STATE_EINT);
+	case WM8350_IRQ_WKUP_CONV_FAULT:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_COMPARATOR_INT_STATUS_MASK,
+					 WM8350_IM_WKUP_CONV_FAULT_EINT);
+	case WM8350_IRQ_WKUP_WDOG_RST:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_COMPARATOR_INT_STATUS_MASK,
+					 WM8350_IM_WKUP_OFF_STATE_EINT);
+	case WM8350_IRQ_WKUP_GP_PWR_ON:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_COMPARATOR_INT_STATUS_MASK,
+					 WM8350_IM_WKUP_GP_PWR_ON_EINT);
+	case WM8350_IRQ_WKUP_ONKEY:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_COMPARATOR_INT_STATUS_MASK,
+					 WM8350_IM_WKUP_ONKEY_EINT);
+	case WM8350_IRQ_WKUP_GP_WAKEUP:
+		return wm8350_clear_bits(wm8350,
+					 WM8350_COMPARATOR_INT_STATUS_MASK,
+					 WM8350_IM_WKUP_GP_WAKEUP_EINT);
+	case WM8350_IRQ_GPIO(0):
+		return wm8350_clear_bits(wm8350,
+					 WM8350_GPIO_INT_STATUS_MASK,
+					 WM8350_IM_GP0_EINT);
+	case WM8350_IRQ_GPIO(1):
+		return wm8350_clear_bits(wm8350,
+					 WM8350_GPIO_INT_STATUS_MASK,
+					 WM8350_IM_GP1_EINT);
+	case WM8350_IRQ_GPIO(2):
+		return wm8350_clear_bits(wm8350,
+					 WM8350_GPIO_INT_STATUS_MASK,
+					 WM8350_IM_GP2_EINT);
+	case WM8350_IRQ_GPIO(3):
+		return wm8350_clear_bits(wm8350,
+					 WM8350_GPIO_INT_STATUS_MASK,
+					 WM8350_IM_GP3_EINT);
+	case WM8350_IRQ_GPIO(4):
+		return wm8350_clear_bits(wm8350,
+					 WM8350_GPIO_INT_STATUS_MASK,
+					 WM8350_IM_GP4_EINT);
+	case WM8350_IRQ_GPIO(5):
+		return wm8350_clear_bits(wm8350,
+					 WM8350_GPIO_INT_STATUS_MASK,
+					 WM8350_IM_GP5_EINT);
+	case WM8350_IRQ_GPIO(6):
+		return wm8350_clear_bits(wm8350,
+					 WM8350_GPIO_INT_STATUS_MASK,
+					 WM8350_IM_GP6_EINT);
+	case WM8350_IRQ_GPIO(7):
+		return wm8350_clear_bits(wm8350,
+					 WM8350_GPIO_INT_STATUS_MASK,
+					 WM8350_IM_GP7_EINT);
+	case WM8350_IRQ_GPIO(8):
+		return wm8350_clear_bits(wm8350,
+					 WM8350_GPIO_INT_STATUS_MASK,
+					 WM8350_IM_GP8_EINT);
+	case WM8350_IRQ_GPIO(9):
+		return wm8350_clear_bits(wm8350,
+					 WM8350_GPIO_INT_STATUS_MASK,
+					 WM8350_IM_GP9_EINT);
+	case WM8350_IRQ_GPIO(10):
+		return wm8350_clear_bits(wm8350,
+					 WM8350_GPIO_INT_STATUS_MASK,
+					 WM8350_IM_GP10_EINT);
+	case WM8350_IRQ_GPIO(11):
+		return wm8350_clear_bits(wm8350,
+					 WM8350_GPIO_INT_STATUS_MASK,
+					 WM8350_IM_GP11_EINT);
+	case WM8350_IRQ_GPIO(12):
+		return wm8350_clear_bits(wm8350,
+					 WM8350_GPIO_INT_STATUS_MASK,
+					 WM8350_IM_GP12_EINT);
+	default:
+		dev_warn(wm8350->dev, "Attempting to unmask unknown IRQ %d\n",
+			 irq);
+		return -EINVAL;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_unmask_irq);
+
+/*
+ * Cache is always host endian.
+ */
+static int wm8350_create_cache(struct wm8350 *wm8350, int mode)
+{
+	int i, ret = 0;
+	u16 value;
+	const u16 *reg_map;
+
+	switch (mode) {
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0
+	case 0:
+		reg_map = wm8350_mode0_defaults;
+		break;
+#endif
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1
+	case 1:
+		reg_map = wm8350_mode1_defaults;
+		break;
+#endif
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2
+	case 2:
+		reg_map = wm8350_mode2_defaults;
+		break;
+#endif
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3
+	case 3:
+		reg_map = wm8350_mode3_defaults;
+		break;
+#endif
+	default:
+		dev_err(wm8350->dev, "Configuration mode %d not supported\n",
+			mode);
+		return -EINVAL;
+	}
+
+	wm8350->reg_cache =
+	    kzalloc(sizeof(u16) * (WM8350_MAX_REGISTER + 1), GFP_KERNEL);
+	if (wm8350->reg_cache == NULL)
+		return -ENOMEM;
+
+	/* Read the initial cache state back from the device - this is
+	 * a PMIC so the device many not be in a virgin state and we
+	 * can't rely on the silicon values.
+	 */
+	for (i = 0; i < WM8350_MAX_REGISTER; i++) {
+		/* audio register range */
+		if (wm8350_reg_io_map[i].readable &&
+		    (i < WM8350_CLOCK_CONTROL_1 || i > WM8350_AIF_TEST)) {
+			ret = wm8350->read_dev(wm8350, i, 2, (char *)&value);
+			if (ret < 0) {
+				dev_err(wm8350->dev,
+				       "failed to read initial cache value\n");
+				goto out;
+			}
+			value = be16_to_cpu(value);
+			value &= wm8350_reg_io_map[i].readable;
+			wm8350->reg_cache[i] = value;
+		} else
+			wm8350->reg_cache[i] = reg_map[i];
+	}
+
+out:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_create_cache);
+
+/*
+ * Register a client device.  This is non-fatal since there is no need to
+ * fail the entire device init due to a single platform device failing.
+ */
+static void wm8350_client_dev_register(struct wm8350 *wm8350,
+				       const char *name,
+				       struct platform_device **pdev)
+{
+	int ret;
+
+	*pdev = platform_device_alloc(name, -1);
+	if (pdev == NULL) {
+		dev_err(wm8350->dev, "Failed to allocate %s\n", name);
+		return;
+	}
+
+	(*pdev)->dev.parent = wm8350->dev;
+	platform_set_drvdata(*pdev, wm8350);
+	ret = platform_device_add(*pdev);
+	if (ret != 0) {
+		dev_err(wm8350->dev, "Failed to register %s: %d\n", name, ret);
+		platform_device_put(*pdev);
+		*pdev = NULL;
+	}
+}
+
+int wm8350_device_init(struct wm8350 *wm8350, int irq,
+		       struct wm8350_platform_data *pdata)
+{
+	int ret = -EINVAL;
+	u16 id1, id2, mask, mode;
+
+	/* get WM8350 revision and config mode */
+	wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1);
+	wm8350->read_dev(wm8350, WM8350_ID, sizeof(id2), &id2);
+
+	id1 = be16_to_cpu(id1);
+	id2 = be16_to_cpu(id2);
+
+	if (id1 == 0x6143) {
+		switch ((id2 & WM8350_CHIP_REV_MASK) >> 12) {
+		case WM8350_REV_E:
+			dev_info(wm8350->dev, "Found Rev E device\n");
+			wm8350->rev = WM8350_REV_E;
+			break;
+		case WM8350_REV_F:
+			dev_info(wm8350->dev, "Found Rev F device\n");
+			wm8350->rev = WM8350_REV_F;
+			break;
+		case WM8350_REV_G:
+			dev_info(wm8350->dev, "Found Rev G device\n");
+			wm8350->rev = WM8350_REV_G;
+			break;
+		default:
+			/* For safety we refuse to run on unknown hardware */
+			dev_info(wm8350->dev, "Found unknown rev\n");
+			ret = -ENODEV;
+			goto err;
+		}
+	} else {
+		dev_info(wm8350->dev, "Device with ID %x is not a WM8350\n",
+			 id1);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	mode = id2 & WM8350_CONF_STS_MASK >> 10;
+	mask = id2 & WM8350_CUST_ID_MASK;
+	dev_info(wm8350->dev, "Config mode %d, ROM mask %d\n", mode, mask);
+
+	ret = wm8350_create_cache(wm8350, mode);
+	if (ret < 0) {
+		printk(KERN_ERR "wm8350: failed to create register cache\n");
+		return ret;
+	}
+
+	if (pdata->init) {
+		ret = pdata->init(wm8350);
+		if (ret != 0) {
+			dev_err(wm8350->dev, "Platform init() failed: %d\n",
+				ret);
+			goto err;
+		}
+	}
+
+	mutex_init(&wm8350->irq_mutex);
+	INIT_WORK(&wm8350->irq_work, wm8350_irq_worker);
+	if (irq != NO_IRQ) {
+		ret = request_irq(irq, wm8350_irq, 0,
+				  "wm8350", wm8350);
+		if (ret != 0) {
+			dev_err(wm8350->dev, "Failed to request IRQ: %d\n",
+				ret);
+			goto err;
+		}
+	} else {
+		dev_err(wm8350->dev, "No IRQ configured\n");
+		goto err;
+	}
+	wm8350->chip_irq = irq;
+
+	wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0x0);
+
+	wm8350_client_dev_register(wm8350, "wm8350-codec",
+				   &(wm8350->codec.pdev));
+	wm8350_client_dev_register(wm8350, "wm8350-gpio",
+				   &(wm8350->gpio.pdev));
+	wm8350_client_dev_register(wm8350, "wm8350-power",
+				   &(wm8350->power.pdev));
+	wm8350_client_dev_register(wm8350, "wm8350-rtc", &(wm8350->rtc.pdev));
+	wm8350_client_dev_register(wm8350, "wm8350-wdt", &(wm8350->wdt.pdev));
+
+	return 0;
+
+err:
+	kfree(wm8350->reg_cache);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_device_init);
+
+void wm8350_device_exit(struct wm8350 *wm8350)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(wm8350->pmic.pdev); i++)
+		platform_device_unregister(wm8350->pmic.pdev[i]);
+
+	platform_device_unregister(wm8350->wdt.pdev);
+	platform_device_unregister(wm8350->rtc.pdev);
+	platform_device_unregister(wm8350->power.pdev);
+	platform_device_unregister(wm8350->gpio.pdev);
+	platform_device_unregister(wm8350->codec.pdev);
+
+	free_irq(wm8350->chip_irq, wm8350);
+	flush_work(&wm8350->irq_work);
+	kfree(wm8350->reg_cache);
+}
+EXPORT_SYMBOL_GPL(wm8350_device_exit);
+
+MODULE_DESCRIPTION("WM8350 AudioPlus PMIC core driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/wm8350-gpio.c b/drivers/mfd/wm8350-gpio.c
new file mode 100644
index 000000000000..ebf99bef392f
--- /dev/null
+++ b/drivers/mfd/wm8350-gpio.c
@@ -0,0 +1,222 @@
+/*
+ * wm8350-core.c  --  Device access for Wolfson WM8350
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood
+ *
+ *  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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/gpio.h>
+#include <linux/mfd/wm8350/pmic.h>
+
+static int gpio_set_dir(struct wm8350 *wm8350, int gpio, int dir)
+{
+	int ret;
+
+	wm8350_reg_unlock(wm8350);
+	if (dir == WM8350_GPIO_DIR_OUT)
+		ret = wm8350_clear_bits(wm8350,
+					WM8350_GPIO_CONFIGURATION_I_O,
+					1 << gpio);
+	else
+		ret = wm8350_set_bits(wm8350,
+				      WM8350_GPIO_CONFIGURATION_I_O,
+				      1 << gpio);
+	wm8350_reg_lock(wm8350);
+	return ret;
+}
+
+static int gpio_set_debounce(struct wm8350 *wm8350, int gpio, int db)
+{
+	if (db == WM8350_GPIO_DEBOUNCE_ON)
+		return wm8350_set_bits(wm8350, WM8350_GPIO_DEBOUNCE,
+				       1 << gpio);
+	else
+		return wm8350_clear_bits(wm8350,
+					 WM8350_GPIO_DEBOUNCE, 1 << gpio);
+}
+
+static int gpio_set_func(struct wm8350 *wm8350, int gpio, int func)
+{
+	u16 reg;
+
+	wm8350_reg_unlock(wm8350);
+	switch (gpio) {
+	case 0:
+		reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
+		    & ~WM8350_GP0_FN_MASK;
+		wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
+				 reg | ((func & 0xf) << 0));
+		break;
+	case 1:
+		reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
+		    & ~WM8350_GP1_FN_MASK;
+		wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
+				 reg | ((func & 0xf) << 4));
+		break;
+	case 2:
+		reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
+		    & ~WM8350_GP2_FN_MASK;
+		wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
+				 reg | ((func & 0xf) << 8));
+		break;
+	case 3:
+		reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
+		    & ~WM8350_GP3_FN_MASK;
+		wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
+				 reg | ((func & 0xf) << 12));
+		break;
+	case 4:
+		reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
+		    & ~WM8350_GP4_FN_MASK;
+		wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
+				 reg | ((func & 0xf) << 0));
+		break;
+	case 5:
+		reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
+		    & ~WM8350_GP5_FN_MASK;
+		wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
+				 reg | ((func & 0xf) << 4));
+		break;
+	case 6:
+		reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
+		    & ~WM8350_GP6_FN_MASK;
+		wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
+				 reg | ((func & 0xf) << 8));
+		break;
+	case 7:
+		reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
+		    & ~WM8350_GP7_FN_MASK;
+		wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
+				 reg | ((func & 0xf) << 12));
+		break;
+	case 8:
+		reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
+		    & ~WM8350_GP8_FN_MASK;
+		wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
+				 reg | ((func & 0xf) << 0));
+		break;
+	case 9:
+		reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
+		    & ~WM8350_GP9_FN_MASK;
+		wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
+				 reg | ((func & 0xf) << 4));
+		break;
+	case 10:
+		reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
+		    & ~WM8350_GP10_FN_MASK;
+		wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
+				 reg | ((func & 0xf) << 8));
+		break;
+	case 11:
+		reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
+		    & ~WM8350_GP11_FN_MASK;
+		wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
+				 reg | ((func & 0xf) << 12));
+		break;
+	case 12:
+		reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_4)
+		    & ~WM8350_GP12_FN_MASK;
+		wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_4,
+				 reg | ((func & 0xf) << 0));
+		break;
+	default:
+		wm8350_reg_lock(wm8350);
+		return -EINVAL;
+	}
+
+	wm8350_reg_lock(wm8350);
+	return 0;
+}
+
+static int gpio_set_pull_up(struct wm8350 *wm8350, int gpio, int up)
+{
+	if (up)
+		return wm8350_set_bits(wm8350,
+				       WM8350_GPIO_PIN_PULL_UP_CONTROL,
+				       1 << gpio);
+	else
+		return wm8350_clear_bits(wm8350,
+					 WM8350_GPIO_PIN_PULL_UP_CONTROL,
+					 1 << gpio);
+}
+
+static int gpio_set_pull_down(struct wm8350 *wm8350, int gpio, int down)
+{
+	if (down)
+		return wm8350_set_bits(wm8350,
+				       WM8350_GPIO_PULL_DOWN_CONTROL,
+				       1 << gpio);
+	else
+		return wm8350_clear_bits(wm8350,
+					 WM8350_GPIO_PULL_DOWN_CONTROL,
+					 1 << gpio);
+}
+
+static int gpio_set_polarity(struct wm8350 *wm8350, int gpio, int pol)
+{
+	if (pol == WM8350_GPIO_ACTIVE_HIGH)
+		return wm8350_set_bits(wm8350,
+				       WM8350_GPIO_PIN_POLARITY_TYPE,
+				       1 << gpio);
+	else
+		return wm8350_clear_bits(wm8350,
+					 WM8350_GPIO_PIN_POLARITY_TYPE,
+					 1 << gpio);
+}
+
+static int gpio_set_invert(struct wm8350 *wm8350, int gpio, int invert)
+{
+	if (invert == WM8350_GPIO_INVERT_ON)
+		return wm8350_set_bits(wm8350, WM8350_GPIO_INT_MODE, 1 << gpio);
+	else
+		return wm8350_clear_bits(wm8350,
+					 WM8350_GPIO_INT_MODE, 1 << gpio);
+}
+
+int wm8350_gpio_config(struct wm8350 *wm8350, int gpio, int dir, int func,
+		       int pol, int pull, int invert, int debounce)
+{
+	/* make sure we never pull up and down at the same time */
+	if (pull == WM8350_GPIO_PULL_NONE) {
+		if (gpio_set_pull_up(wm8350, gpio, 0))
+			goto err;
+		if (gpio_set_pull_down(wm8350, gpio, 0))
+			goto err;
+	} else if (pull == WM8350_GPIO_PULL_UP) {
+		if (gpio_set_pull_down(wm8350, gpio, 0))
+			goto err;
+		if (gpio_set_pull_up(wm8350, gpio, 1))
+			goto err;
+	} else if (pull == WM8350_GPIO_PULL_DOWN) {
+		if (gpio_set_pull_up(wm8350, gpio, 0))
+			goto err;
+		if (gpio_set_pull_down(wm8350, gpio, 1))
+			goto err;
+	}
+
+	if (gpio_set_invert(wm8350, gpio, invert))
+		goto err;
+	if (gpio_set_polarity(wm8350, gpio, pol))
+		goto err;
+	if (gpio_set_debounce(wm8350, gpio, debounce))
+		goto err;
+	if (gpio_set_dir(wm8350, gpio, dir))
+		goto err;
+	return gpio_set_func(wm8350, gpio, func);
+
+err:
+	return -EIO;
+}
+EXPORT_SYMBOL_GPL(wm8350_gpio_config);
diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c
new file mode 100644
index 000000000000..8dfe21bb3bd1
--- /dev/null
+++ b/drivers/mfd/wm8350-i2c.c
@@ -0,0 +1,120 @@
+/*
+ * wm8350-i2c.c  --  Generic I2C driver for Wolfson WM8350 PMIC
+ *
+ * This driver defines and configures the WM8350 for the Freescale i.MX32ADS.
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood
+ *         linux@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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/wm8350/core.h>
+
+static int wm8350_i2c_read_device(struct wm8350 *wm8350, char reg,
+				  int bytes, void *dest)
+{
+	int ret;
+
+	ret = i2c_master_send(wm8350->i2c_client, &reg, 1);
+	if (ret < 0)
+		return ret;
+	return i2c_master_recv(wm8350->i2c_client, dest, bytes);
+}
+
+static int wm8350_i2c_write_device(struct wm8350 *wm8350, char reg,
+				   int bytes, void *src)
+{
+	/* we add 1 byte for device register */
+	u8 msg[(WM8350_MAX_REGISTER << 1) + 1];
+
+	if (bytes > ((WM8350_MAX_REGISTER << 1) + 1))
+		return -EINVAL;
+
+	msg[0] = reg;
+	memcpy(&msg[1], src, bytes);
+	return i2c_master_send(wm8350->i2c_client, msg, bytes + 1);
+}
+
+static int wm8350_i2c_probe(struct i2c_client *i2c,
+			    const struct i2c_device_id *id)
+{
+	struct wm8350 *wm8350;
+	int ret = 0;
+
+	wm8350 = kzalloc(sizeof(struct wm8350), GFP_KERNEL);
+	if (wm8350 == NULL) {
+		kfree(i2c);
+		return -ENOMEM;
+	}
+
+	i2c_set_clientdata(i2c, wm8350);
+	wm8350->dev = &i2c->dev;
+	wm8350->i2c_client = i2c;
+	wm8350->read_dev = wm8350_i2c_read_device;
+	wm8350->write_dev = wm8350_i2c_write_device;
+
+	ret = wm8350_device_init(wm8350, i2c->irq, i2c->dev.platform_data);
+	if (ret < 0)
+		goto err;
+
+	return ret;
+
+err:
+	kfree(wm8350);
+	return ret;
+}
+
+static int wm8350_i2c_remove(struct i2c_client *i2c)
+{
+	struct wm8350 *wm8350 = i2c_get_clientdata(i2c);
+
+	wm8350_device_exit(wm8350);
+	kfree(wm8350);
+
+	return 0;
+}
+
+static const struct i2c_device_id wm8350_i2c_id[] = {
+       { "wm8350", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8350_i2c_id);
+
+
+static struct i2c_driver wm8350_i2c_driver = {
+	.driver = {
+		   .name = "wm8350",
+		   .owner = THIS_MODULE,
+	},
+	.probe = wm8350_i2c_probe,
+	.remove = wm8350_i2c_remove,
+	.id_table = wm8350_i2c_id,
+};
+
+static int __init wm8350_i2c_init(void)
+{
+	return i2c_add_driver(&wm8350_i2c_driver);
+}
+/* init early so consumer devices can complete system boot */
+subsys_initcall(wm8350_i2c_init);
+
+static void __exit wm8350_i2c_exit(void)
+{
+	i2c_del_driver(&wm8350_i2c_driver);
+}
+module_exit(wm8350_i2c_exit);
+
+MODULE_DESCRIPTION("I2C support for the WM8350 AudioPlus PMIC");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/wm8350-regmap.c b/drivers/mfd/wm8350-regmap.c
new file mode 100644
index 000000000000..974678db22cd
--- /dev/null
+++ b/drivers/mfd/wm8350-regmap.c
@@ -0,0 +1,1347 @@
+/*
+ * wm8350-regmap.c  --  Wolfson Microelectronics WM8350 register map
+ *
+ * This file splits out the tables describing the defaults and access
+ * status of the WM8350 registers since they are rather large.
+ *
+ * Copyright 2007, 2008 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/mfd/wm8350/core.h>
+
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8350_mode0_defaults[] = {
+	0x17FF,     /* R0   - Reset/ID */
+	0x1000,     /* R1   - ID */
+	0x0000,     /* R2 */
+	0x1002,     /* R3   - System Control 1 */
+	0x0004,     /* R4   - System Control 2 */
+	0x0000,     /* R5   - System Hibernate */
+	0x8A00,     /* R6   - Interface Control */
+	0x0000,     /* R7 */
+	0x8000,     /* R8   - Power mgmt (1) */
+	0x0000,     /* R9   - Power mgmt (2) */
+	0x0000,     /* R10  - Power mgmt (3) */
+	0x2000,     /* R11  - Power mgmt (4) */
+	0x0E00,     /* R12  - Power mgmt (5) */
+	0x0000,     /* R13  - Power mgmt (6) */
+	0x0000,     /* R14  - Power mgmt (7) */
+	0x0000,     /* R15 */
+	0x0000,     /* R16  - RTC Seconds/Minutes */
+	0x0100,     /* R17  - RTC Hours/Day */
+	0x0101,     /* R18  - RTC Date/Month */
+	0x1400,     /* R19  - RTC Year */
+	0x0000,     /* R20  - Alarm Seconds/Minutes */
+	0x0000,     /* R21  - Alarm Hours/Day */
+	0x0000,     /* R22  - Alarm Date/Month */
+	0x0320,     /* R23  - RTC Time Control */
+	0x0000,     /* R24  - System Interrupts */
+	0x0000,     /* R25  - Interrupt Status 1 */
+	0x0000,     /* R26  - Interrupt Status 2 */
+	0x0000,     /* R27  - Power Up Interrupt Status */
+	0x0000,     /* R28  - Under Voltage Interrupt status */
+	0x0000,     /* R29  - Over Current Interrupt status */
+	0x0000,     /* R30  - GPIO Interrupt Status */
+	0x0000,     /* R31  - Comparator Interrupt Status */
+	0x3FFF,     /* R32  - System Interrupts Mask */
+	0x0000,     /* R33  - Interrupt Status 1 Mask */
+	0x0000,     /* R34  - Interrupt Status 2 Mask */
+	0x0000,     /* R35  - Power Up Interrupt Status Mask */
+	0x0000,     /* R36  - Under Voltage Interrupt status Mask */
+	0x0000,     /* R37  - Over Current Interrupt status Mask */
+	0x0000,     /* R38  - GPIO Interrupt Status Mask */
+	0x0000,     /* R39  - Comparator Interrupt Status Mask */
+	0x0040,     /* R40  - Clock Control 1 */
+	0x0000,     /* R41  - Clock Control 2 */
+	0x3B00,     /* R42  - FLL Control 1 */
+	0x7086,     /* R43  - FLL Control 2 */
+	0xC226,     /* R44  - FLL Control 3 */
+	0x0000,     /* R45  - FLL Control 4 */
+	0x0000,     /* R46 */
+	0x0000,     /* R47 */
+	0x0000,     /* R48  - DAC Control */
+	0x0000,     /* R49 */
+	0x00C0,     /* R50  - DAC Digital Volume L */
+	0x00C0,     /* R51  - DAC Digital Volume R */
+	0x0000,     /* R52 */
+	0x0040,     /* R53  - DAC LR Rate */
+	0x0000,     /* R54  - DAC Clock Control */
+	0x0000,     /* R55 */
+	0x0000,     /* R56 */
+	0x0000,     /* R57 */
+	0x4000,     /* R58  - DAC Mute */
+	0x0000,     /* R59  - DAC Mute Volume */
+	0x0000,     /* R60  - DAC Side */
+	0x0000,     /* R61 */
+	0x0000,     /* R62 */
+	0x0000,     /* R63 */
+	0x8000,     /* R64  - ADC Control */
+	0x0000,     /* R65 */
+	0x00C0,     /* R66  - ADC Digital Volume L */
+	0x00C0,     /* R67  - ADC Digital Volume R */
+	0x0000,     /* R68  - ADC Divider */
+	0x0000,     /* R69 */
+	0x0040,     /* R70  - ADC LR Rate */
+	0x0000,     /* R71 */
+	0x0303,     /* R72  - Input Control */
+	0x0000,     /* R73  - IN3 Input Control */
+	0x0000,     /* R74  - Mic Bias Control */
+	0x0000,     /* R75 */
+	0x0000,     /* R76  - Output Control */
+	0x0000,     /* R77  - Jack Detect */
+	0x0000,     /* R78  - Anti Pop Control */
+	0x0000,     /* R79 */
+	0x0040,     /* R80  - Left Input Volume */
+	0x0040,     /* R81  - Right Input Volume */
+	0x0000,     /* R82 */
+	0x0000,     /* R83 */
+	0x0000,     /* R84 */
+	0x0000,     /* R85 */
+	0x0000,     /* R86 */
+	0x0000,     /* R87 */
+	0x0800,     /* R88  - Left Mixer Control */
+	0x1000,     /* R89  - Right Mixer Control */
+	0x0000,     /* R90 */
+	0x0000,     /* R91 */
+	0x0000,     /* R92  - OUT3 Mixer Control */
+	0x0000,     /* R93  - OUT4 Mixer Control */
+	0x0000,     /* R94 */
+	0x0000,     /* R95 */
+	0x0000,     /* R96  - Output Left Mixer Volume */
+	0x0000,     /* R97  - Output Right Mixer Volume */
+	0x0000,     /* R98  - Input Mixer Volume L */
+	0x0000,     /* R99  - Input Mixer Volume R */
+	0x0000,     /* R100 - Input Mixer Volume */
+	0x0000,     /* R101 */
+	0x0000,     /* R102 */
+	0x0000,     /* R103 */
+	0x00E4,     /* R104 - LOUT1 Volume */
+	0x00E4,     /* R105 - ROUT1 Volume */
+	0x00E4,     /* R106 - LOUT2 Volume */
+	0x02E4,     /* R107 - ROUT2 Volume */
+	0x0000,     /* R108 */
+	0x0000,     /* R109 */
+	0x0000,     /* R110 */
+	0x0000,     /* R111 - BEEP Volume */
+	0x0A00,     /* R112 - AI Formating */
+	0x0000,     /* R113 - ADC DAC COMP */
+	0x0020,     /* R114 - AI ADC Control */
+	0x0020,     /* R115 - AI DAC Control */
+	0x0000,     /* R116 - AIF Test */
+	0x0000,     /* R117 */
+	0x0000,     /* R118 */
+	0x0000,     /* R119 */
+	0x0000,     /* R120 */
+	0x0000,     /* R121 */
+	0x0000,     /* R122 */
+	0x0000,     /* R123 */
+	0x0000,     /* R124 */
+	0x0000,     /* R125 */
+	0x0000,     /* R126 */
+	0x0000,     /* R127 */
+	0x1FFF,     /* R128 - GPIO Debounce */
+	0x0000,     /* R129 - GPIO Pin pull up Control */
+	0x03FC,     /* R130 - GPIO Pull down Control */
+	0x0000,     /* R131 - GPIO Interrupt Mode */
+	0x0000,     /* R132 */
+	0x0000,     /* R133 - GPIO Control */
+	0x0FFC,     /* R134 - GPIO Configuration (i/o) */
+	0x0FFC,     /* R135 - GPIO Pin Polarity / Type */
+	0x0000,     /* R136 */
+	0x0000,     /* R137 */
+	0x0000,     /* R138 */
+	0x0000,     /* R139 */
+	0x0013,     /* R140 - GPIO Function Select 1 */
+	0x0000,     /* R141 - GPIO Function Select 2 */
+	0x0000,     /* R142 - GPIO Function Select 3 */
+	0x0003,     /* R143 - GPIO Function Select 4 */
+	0x0000,     /* R144 - Digitiser Control (1) */
+	0x0002,     /* R145 - Digitiser Control (2) */
+	0x0000,     /* R146 */
+	0x0000,     /* R147 */
+	0x0000,     /* R148 */
+	0x0000,     /* R149 */
+	0x0000,     /* R150 */
+	0x0000,     /* R151 */
+	0x7000,     /* R152 - AUX1 Readback */
+	0x7000,     /* R153 - AUX2 Readback */
+	0x7000,     /* R154 - AUX3 Readback */
+	0x7000,     /* R155 - AUX4 Readback */
+	0x0000,     /* R156 - USB Voltage Readback */
+	0x0000,     /* R157 - LINE Voltage Readback */
+	0x0000,     /* R158 - BATT Voltage Readback */
+	0x0000,     /* R159 - Chip Temp Readback */
+	0x0000,     /* R160 */
+	0x0000,     /* R161 */
+	0x0000,     /* R162 */
+	0x0000,     /* R163 - Generic Comparator Control */
+	0x0000,     /* R164 - Generic comparator 1 */
+	0x0000,     /* R165 - Generic comparator 2 */
+	0x0000,     /* R166 - Generic comparator 3 */
+	0x0000,     /* R167 - Generic comparator 4 */
+	0xA00F,     /* R168 - Battery Charger Control 1 */
+	0x0B06,     /* R169 - Battery Charger Control 2 */
+	0x0000,     /* R170 - Battery Charger Control 3 */
+	0x0000,     /* R171 */
+	0x0000,     /* R172 - Current Sink Driver A */
+	0x0000,     /* R173 - CSA Flash control */
+	0x0000,     /* R174 - Current Sink Driver B */
+	0x0000,     /* R175 - CSB Flash control */
+	0x0000,     /* R176 - DCDC/LDO requested */
+	0x002D,     /* R177 - DCDC Active options */
+	0x0000,     /* R178 - DCDC Sleep options */
+	0x0025,     /* R179 - Power-check comparator */
+	0x000E,     /* R180 - DCDC1 Control */
+	0x0000,     /* R181 - DCDC1 Timeouts */
+	0x1006,     /* R182 - DCDC1 Low Power */
+	0x0018,     /* R183 - DCDC2 Control */
+	0x0000,     /* R184 - DCDC2 Timeouts */
+	0x0000,     /* R185 */
+	0x0000,     /* R186 - DCDC3 Control */
+	0x0000,     /* R187 - DCDC3 Timeouts */
+	0x0006,     /* R188 - DCDC3 Low Power */
+	0x0000,     /* R189 - DCDC4 Control */
+	0x0000,     /* R190 - DCDC4 Timeouts */
+	0x0006,     /* R191 - DCDC4 Low Power */
+	0x0008,     /* R192 - DCDC5 Control */
+	0x0000,     /* R193 - DCDC5 Timeouts */
+	0x0000,     /* R194 */
+	0x0000,     /* R195 - DCDC6 Control */
+	0x0000,     /* R196 - DCDC6 Timeouts */
+	0x0006,     /* R197 - DCDC6 Low Power */
+	0x0000,     /* R198 */
+	0x0003,     /* R199 - Limit Switch Control */
+	0x001C,     /* R200 - LDO1 Control */
+	0x0000,     /* R201 - LDO1 Timeouts */
+	0x001C,     /* R202 - LDO1 Low Power */
+	0x001B,     /* R203 - LDO2 Control */
+	0x0000,     /* R204 - LDO2 Timeouts */
+	0x001C,     /* R205 - LDO2 Low Power */
+	0x001B,     /* R206 - LDO3 Control */
+	0x0000,     /* R207 - LDO3 Timeouts */
+	0x001C,     /* R208 - LDO3 Low Power */
+	0x001B,     /* R209 - LDO4 Control */
+	0x0000,     /* R210 - LDO4 Timeouts */
+	0x001C,     /* R211 - LDO4 Low Power */
+	0x0000,     /* R212 */
+	0x0000,     /* R213 */
+	0x0000,     /* R214 */
+	0x0000,     /* R215 - VCC_FAULT Masks */
+	0x001F,     /* R216 - Main Bandgap Control */
+	0x0000,     /* R217 - OSC Control */
+	0x9000,     /* R218 - RTC Tick Control */
+	0x0000,     /* R219 */
+	0x4000,     /* R220 - RAM BIST 1 */
+	0x0000,     /* R221 */
+	0x0000,     /* R222 */
+	0x0000,     /* R223 */
+	0x0000,     /* R224 */
+	0x0000,     /* R225 - DCDC/LDO status */
+	0x0000,     /* R226 */
+	0x0000,     /* R227 */
+	0x0000,     /* R228 */
+	0x0000,     /* R229 */
+	0xE000,     /* R230 - GPIO Pin Status */
+	0x0000,     /* R231 */
+	0x0000,     /* R232 */
+	0x0000,     /* R233 */
+	0x0000,     /* R234 */
+	0x0000,     /* R235 */
+	0x0000,     /* R236 */
+	0x0000,     /* R237 */
+	0x0000,     /* R238 */
+	0x0000,     /* R239 */
+	0x0000,     /* R240 */
+	0x0000,     /* R241 */
+	0x0000,     /* R242 */
+	0x0000,     /* R243 */
+	0x0000,     /* R244 */
+	0x0000,     /* R245 */
+	0x0000,     /* R246 */
+	0x0000,     /* R247 */
+	0x0000,     /* R248 */
+	0x0000,     /* R249 */
+	0x0000,     /* R250 */
+	0x0000,     /* R251 */
+	0x0000,     /* R252 */
+	0x0000,     /* R253 */
+	0x0000,     /* R254 */
+	0x0000,     /* R255 */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8350_mode1_defaults[] = {
+	0x17FF,     /* R0   - Reset/ID */
+	0x1000,     /* R1   - ID */
+	0x0000,     /* R2 */
+	0x1002,     /* R3   - System Control 1 */
+	0x0014,     /* R4   - System Control 2 */
+	0x0000,     /* R5   - System Hibernate */
+	0x8A00,     /* R6   - Interface Control */
+	0x0000,     /* R7 */
+	0x8000,     /* R8   - Power mgmt (1) */
+	0x0000,     /* R9   - Power mgmt (2) */
+	0x0000,     /* R10  - Power mgmt (3) */
+	0x2000,     /* R11  - Power mgmt (4) */
+	0x0E00,     /* R12  - Power mgmt (5) */
+	0x0000,     /* R13  - Power mgmt (6) */
+	0x0000,     /* R14  - Power mgmt (7) */
+	0x0000,     /* R15 */
+	0x0000,     /* R16  - RTC Seconds/Minutes */
+	0x0100,     /* R17  - RTC Hours/Day */
+	0x0101,     /* R18  - RTC Date/Month */
+	0x1400,     /* R19  - RTC Year */
+	0x0000,     /* R20  - Alarm Seconds/Minutes */
+	0x0000,     /* R21  - Alarm Hours/Day */
+	0x0000,     /* R22  - Alarm Date/Month */
+	0x0320,     /* R23  - RTC Time Control */
+	0x0000,     /* R24  - System Interrupts */
+	0x0000,     /* R25  - Interrupt Status 1 */
+	0x0000,     /* R26  - Interrupt Status 2 */
+	0x0000,     /* R27  - Power Up Interrupt Status */
+	0x0000,     /* R28  - Under Voltage Interrupt status */
+	0x0000,     /* R29  - Over Current Interrupt status */
+	0x0000,     /* R30  - GPIO Interrupt Status */
+	0x0000,     /* R31  - Comparator Interrupt Status */
+	0x3FFF,     /* R32  - System Interrupts Mask */
+	0x0000,     /* R33  - Interrupt Status 1 Mask */
+	0x0000,     /* R34  - Interrupt Status 2 Mask */
+	0x0000,     /* R35  - Power Up Interrupt Status Mask */
+	0x0000,     /* R36  - Under Voltage Interrupt status Mask */
+	0x0000,     /* R37  - Over Current Interrupt status Mask */
+	0x0000,     /* R38  - GPIO Interrupt Status Mask */
+	0x0000,     /* R39  - Comparator Interrupt Status Mask */
+	0x0040,     /* R40  - Clock Control 1 */
+	0x0000,     /* R41  - Clock Control 2 */
+	0x3B00,     /* R42  - FLL Control 1 */
+	0x7086,     /* R43  - FLL Control 2 */
+	0xC226,     /* R44  - FLL Control 3 */
+	0x0000,     /* R45  - FLL Control 4 */
+	0x0000,     /* R46 */
+	0x0000,     /* R47 */
+	0x0000,     /* R48  - DAC Control */
+	0x0000,     /* R49 */
+	0x00C0,     /* R50  - DAC Digital Volume L */
+	0x00C0,     /* R51  - DAC Digital Volume R */
+	0x0000,     /* R52 */
+	0x0040,     /* R53  - DAC LR Rate */
+	0x0000,     /* R54  - DAC Clock Control */
+	0x0000,     /* R55 */
+	0x0000,     /* R56 */
+	0x0000,     /* R57 */
+	0x4000,     /* R58  - DAC Mute */
+	0x0000,     /* R59  - DAC Mute Volume */
+	0x0000,     /* R60  - DAC Side */
+	0x0000,     /* R61 */
+	0x0000,     /* R62 */
+	0x0000,     /* R63 */
+	0x8000,     /* R64  - ADC Control */
+	0x0000,     /* R65 */
+	0x00C0,     /* R66  - ADC Digital Volume L */
+	0x00C0,     /* R67  - ADC Digital Volume R */
+	0x0000,     /* R68  - ADC Divider */
+	0x0000,     /* R69 */
+	0x0040,     /* R70  - ADC LR Rate */
+	0x0000,     /* R71 */
+	0x0303,     /* R72  - Input Control */
+	0x0000,     /* R73  - IN3 Input Control */
+	0x0000,     /* R74  - Mic Bias Control */
+	0x0000,     /* R75 */
+	0x0000,     /* R76  - Output Control */
+	0x0000,     /* R77  - Jack Detect */
+	0x0000,     /* R78  - Anti Pop Control */
+	0x0000,     /* R79 */
+	0x0040,     /* R80  - Left Input Volume */
+	0x0040,     /* R81  - Right Input Volume */
+	0x0000,     /* R82 */
+	0x0000,     /* R83 */
+	0x0000,     /* R84 */
+	0x0000,     /* R85 */
+	0x0000,     /* R86 */
+	0x0000,     /* R87 */
+	0x0800,     /* R88  - Left Mixer Control */
+	0x1000,     /* R89  - Right Mixer Control */
+	0x0000,     /* R90 */
+	0x0000,     /* R91 */
+	0x0000,     /* R92  - OUT3 Mixer Control */
+	0x0000,     /* R93  - OUT4 Mixer Control */
+	0x0000,     /* R94 */
+	0x0000,     /* R95 */
+	0x0000,     /* R96  - Output Left Mixer Volume */
+	0x0000,     /* R97  - Output Right Mixer Volume */
+	0x0000,     /* R98  - Input Mixer Volume L */
+	0x0000,     /* R99  - Input Mixer Volume R */
+	0x0000,     /* R100 - Input Mixer Volume */
+	0x0000,     /* R101 */
+	0x0000,     /* R102 */
+	0x0000,     /* R103 */
+	0x00E4,     /* R104 - LOUT1 Volume */
+	0x00E4,     /* R105 - ROUT1 Volume */
+	0x00E4,     /* R106 - LOUT2 Volume */
+	0x02E4,     /* R107 - ROUT2 Volume */
+	0x0000,     /* R108 */
+	0x0000,     /* R109 */
+	0x0000,     /* R110 */
+	0x0000,     /* R111 - BEEP Volume */
+	0x0A00,     /* R112 - AI Formating */
+	0x0000,     /* R113 - ADC DAC COMP */
+	0x0020,     /* R114 - AI ADC Control */
+	0x0020,     /* R115 - AI DAC Control */
+	0x0000,     /* R116 - AIF Test */
+	0x0000,     /* R117 */
+	0x0000,     /* R118 */
+	0x0000,     /* R119 */
+	0x0000,     /* R120 */
+	0x0000,     /* R121 */
+	0x0000,     /* R122 */
+	0x0000,     /* R123 */
+	0x0000,     /* R124 */
+	0x0000,     /* R125 */
+	0x0000,     /* R126 */
+	0x0000,     /* R127 */
+	0x1FFF,     /* R128 - GPIO Debounce */
+	0x0000,     /* R129 - GPIO Pin pull up Control */
+	0x03FC,     /* R130 - GPIO Pull down Control */
+	0x0000,     /* R131 - GPIO Interrupt Mode */
+	0x0000,     /* R132 */
+	0x0000,     /* R133 - GPIO Control */
+	0x00FB,     /* R134 - GPIO Configuration (i/o) */
+	0x04FE,     /* R135 - GPIO Pin Polarity / Type */
+	0x0000,     /* R136 */
+	0x0000,     /* R137 */
+	0x0000,     /* R138 */
+	0x0000,     /* R139 */
+	0x0312,     /* R140 - GPIO Function Select 1 */
+	0x1003,     /* R141 - GPIO Function Select 2 */
+	0x1331,     /* R142 - GPIO Function Select 3 */
+	0x0003,     /* R143 - GPIO Function Select 4 */
+	0x0000,     /* R144 - Digitiser Control (1) */
+	0x0002,     /* R145 - Digitiser Control (2) */
+	0x0000,     /* R146 */
+	0x0000,     /* R147 */
+	0x0000,     /* R148 */
+	0x0000,     /* R149 */
+	0x0000,     /* R150 */
+	0x0000,     /* R151 */
+	0x7000,     /* R152 - AUX1 Readback */
+	0x7000,     /* R153 - AUX2 Readback */
+	0x7000,     /* R154 - AUX3 Readback */
+	0x7000,     /* R155 - AUX4 Readback */
+	0x0000,     /* R156 - USB Voltage Readback */
+	0x0000,     /* R157 - LINE Voltage Readback */
+	0x0000,     /* R158 - BATT Voltage Readback */
+	0x0000,     /* R159 - Chip Temp Readback */
+	0x0000,     /* R160 */
+	0x0000,     /* R161 */
+	0x0000,     /* R162 */
+	0x0000,     /* R163 - Generic Comparator Control */
+	0x0000,     /* R164 - Generic comparator 1 */
+	0x0000,     /* R165 - Generic comparator 2 */
+	0x0000,     /* R166 - Generic comparator 3 */
+	0x0000,     /* R167 - Generic comparator 4 */
+	0xA00F,     /* R168 - Battery Charger Control 1 */
+	0x0B06,     /* R169 - Battery Charger Control 2 */
+	0x0000,     /* R170 - Battery Charger Control 3 */
+	0x0000,     /* R171 */
+	0x0000,     /* R172 - Current Sink Driver A */
+	0x0000,     /* R173 - CSA Flash control */
+	0x0000,     /* R174 - Current Sink Driver B */
+	0x0000,     /* R175 - CSB Flash control */
+	0x0000,     /* R176 - DCDC/LDO requested */
+	0x002D,     /* R177 - DCDC Active options */
+	0x0000,     /* R178 - DCDC Sleep options */
+	0x0025,     /* R179 - Power-check comparator */
+	0x0062,     /* R180 - DCDC1 Control */
+	0x0400,     /* R181 - DCDC1 Timeouts */
+	0x1006,     /* R182 - DCDC1 Low Power */
+	0x0018,     /* R183 - DCDC2 Control */
+	0x0000,     /* R184 - DCDC2 Timeouts */
+	0x0000,     /* R185 */
+	0x0026,     /* R186 - DCDC3 Control */
+	0x0400,     /* R187 - DCDC3 Timeouts */
+	0x0006,     /* R188 - DCDC3 Low Power */
+	0x0062,     /* R189 - DCDC4 Control */
+	0x0400,     /* R190 - DCDC4 Timeouts */
+	0x0006,     /* R191 - DCDC4 Low Power */
+	0x0008,     /* R192 - DCDC5 Control */
+	0x0000,     /* R193 - DCDC5 Timeouts */
+	0x0000,     /* R194 */
+	0x0026,     /* R195 - DCDC6 Control */
+	0x0800,     /* R196 - DCDC6 Timeouts */
+	0x0006,     /* R197 - DCDC6 Low Power */
+	0x0000,     /* R198 */
+	0x0003,     /* R199 - Limit Switch Control */
+	0x0006,     /* R200 - LDO1 Control */
+	0x0400,     /* R201 - LDO1 Timeouts */
+	0x001C,     /* R202 - LDO1 Low Power */
+	0x0006,     /* R203 - LDO2 Control */
+	0x0400,     /* R204 - LDO2 Timeouts */
+	0x001C,     /* R205 - LDO2 Low Power */
+	0x001B,     /* R206 - LDO3 Control */
+	0x0000,     /* R207 - LDO3 Timeouts */
+	0x001C,     /* R208 - LDO3 Low Power */
+	0x001B,     /* R209 - LDO4 Control */
+	0x0000,     /* R210 - LDO4 Timeouts */
+	0x001C,     /* R211 - LDO4 Low Power */
+	0x0000,     /* R212 */
+	0x0000,     /* R213 */
+	0x0000,     /* R214 */
+	0x0000,     /* R215 - VCC_FAULT Masks */
+	0x001F,     /* R216 - Main Bandgap Control */
+	0x0000,     /* R217 - OSC Control */
+	0x9000,     /* R218 - RTC Tick Control */
+	0x0000,     /* R219 */
+	0x4000,     /* R220 - RAM BIST 1 */
+	0x0000,     /* R221 */
+	0x0000,     /* R222 */
+	0x0000,     /* R223 */
+	0x0000,     /* R224 */
+	0x0000,     /* R225 - DCDC/LDO status */
+	0x0000,     /* R226 */
+	0x0000,     /* R227 */
+	0x0000,     /* R228 */
+	0x0000,     /* R229 */
+	0xE000,     /* R230 - GPIO Pin Status */
+	0x0000,     /* R231 */
+	0x0000,     /* R232 */
+	0x0000,     /* R233 */
+	0x0000,     /* R234 */
+	0x0000,     /* R235 */
+	0x0000,     /* R236 */
+	0x0000,     /* R237 */
+	0x0000,     /* R238 */
+	0x0000,     /* R239 */
+	0x0000,     /* R240 */
+	0x0000,     /* R241 */
+	0x0000,     /* R242 */
+	0x0000,     /* R243 */
+	0x0000,     /* R244 */
+	0x0000,     /* R245 */
+	0x0000,     /* R246 */
+	0x0000,     /* R247 */
+	0x0000,     /* R248 */
+	0x0000,     /* R249 */
+	0x0000,     /* R250 */
+	0x0000,     /* R251 */
+	0x0000,     /* R252 */
+	0x0000,     /* R253 */
+	0x0000,     /* R254 */
+	0x0000,     /* R255 */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8350_mode2_defaults[] = {
+	0x17FF,     /* R0   - Reset/ID */
+	0x1000,     /* R1   - ID */
+	0x0000,     /* R2 */
+	0x1002,     /* R3   - System Control 1 */
+	0x0014,     /* R4   - System Control 2 */
+	0x0000,     /* R5   - System Hibernate */
+	0x8A00,     /* R6   - Interface Control */
+	0x0000,     /* R7 */
+	0x8000,     /* R8   - Power mgmt (1) */
+	0x0000,     /* R9   - Power mgmt (2) */
+	0x0000,     /* R10  - Power mgmt (3) */
+	0x2000,     /* R11  - Power mgmt (4) */
+	0x0E00,     /* R12  - Power mgmt (5) */
+	0x0000,     /* R13  - Power mgmt (6) */
+	0x0000,     /* R14  - Power mgmt (7) */
+	0x0000,     /* R15 */
+	0x0000,     /* R16  - RTC Seconds/Minutes */
+	0x0100,     /* R17  - RTC Hours/Day */
+	0x0101,     /* R18  - RTC Date/Month */
+	0x1400,     /* R19  - RTC Year */
+	0x0000,     /* R20  - Alarm Seconds/Minutes */
+	0x0000,     /* R21  - Alarm Hours/Day */
+	0x0000,     /* R22  - Alarm Date/Month */
+	0x0320,     /* R23  - RTC Time Control */
+	0x0000,     /* R24  - System Interrupts */
+	0x0000,     /* R25  - Interrupt Status 1 */
+	0x0000,     /* R26  - Interrupt Status 2 */
+	0x0000,     /* R27  - Power Up Interrupt Status */
+	0x0000,     /* R28  - Under Voltage Interrupt status */
+	0x0000,     /* R29  - Over Current Interrupt status */
+	0x0000,     /* R30  - GPIO Interrupt Status */
+	0x0000,     /* R31  - Comparator Interrupt Status */
+	0x3FFF,     /* R32  - System Interrupts Mask */
+	0x0000,     /* R33  - Interrupt Status 1 Mask */
+	0x0000,     /* R34  - Interrupt Status 2 Mask */
+	0x0000,     /* R35  - Power Up Interrupt Status Mask */
+	0x0000,     /* R36  - Under Voltage Interrupt status Mask */
+	0x0000,     /* R37  - Over Current Interrupt status Mask */
+	0x0000,     /* R38  - GPIO Interrupt Status Mask */
+	0x0000,     /* R39  - Comparator Interrupt Status Mask */
+	0x0040,     /* R40  - Clock Control 1 */
+	0x0000,     /* R41  - Clock Control 2 */
+	0x3B00,     /* R42  - FLL Control 1 */
+	0x7086,     /* R43  - FLL Control 2 */
+	0xC226,     /* R44  - FLL Control 3 */
+	0x0000,     /* R45  - FLL Control 4 */
+	0x0000,     /* R46 */
+	0x0000,     /* R47 */
+	0x0000,     /* R48  - DAC Control */
+	0x0000,     /* R49 */
+	0x00C0,     /* R50  - DAC Digital Volume L */
+	0x00C0,     /* R51  - DAC Digital Volume R */
+	0x0000,     /* R52 */
+	0x0040,     /* R53  - DAC LR Rate */
+	0x0000,     /* R54  - DAC Clock Control */
+	0x0000,     /* R55 */
+	0x0000,     /* R56 */
+	0x0000,     /* R57 */
+	0x4000,     /* R58  - DAC Mute */
+	0x0000,     /* R59  - DAC Mute Volume */
+	0x0000,     /* R60  - DAC Side */
+	0x0000,     /* R61 */
+	0x0000,     /* R62 */
+	0x0000,     /* R63 */
+	0x8000,     /* R64  - ADC Control */
+	0x0000,     /* R65 */
+	0x00C0,     /* R66  - ADC Digital Volume L */
+	0x00C0,     /* R67  - ADC Digital Volume R */
+	0x0000,     /* R68  - ADC Divider */
+	0x0000,     /* R69 */
+	0x0040,     /* R70  - ADC LR Rate */
+	0x0000,     /* R71 */
+	0x0303,     /* R72  - Input Control */
+	0x0000,     /* R73  - IN3 Input Control */
+	0x0000,     /* R74  - Mic Bias Control */
+	0x0000,     /* R75 */
+	0x0000,     /* R76  - Output Control */
+	0x0000,     /* R77  - Jack Detect */
+	0x0000,     /* R78  - Anti Pop Control */
+	0x0000,     /* R79 */
+	0x0040,     /* R80  - Left Input Volume */
+	0x0040,     /* R81  - Right Input Volume */
+	0x0000,     /* R82 */
+	0x0000,     /* R83 */
+	0x0000,     /* R84 */
+	0x0000,     /* R85 */
+	0x0000,     /* R86 */
+	0x0000,     /* R87 */
+	0x0800,     /* R88  - Left Mixer Control */
+	0x1000,     /* R89  - Right Mixer Control */
+	0x0000,     /* R90 */
+	0x0000,     /* R91 */
+	0x0000,     /* R92  - OUT3 Mixer Control */
+	0x0000,     /* R93  - OUT4 Mixer Control */
+	0x0000,     /* R94 */
+	0x0000,     /* R95 */
+	0x0000,     /* R96  - Output Left Mixer Volume */
+	0x0000,     /* R97  - Output Right Mixer Volume */
+	0x0000,     /* R98  - Input Mixer Volume L */
+	0x0000,     /* R99  - Input Mixer Volume R */
+	0x0000,     /* R100 - Input Mixer Volume */
+	0x0000,     /* R101 */
+	0x0000,     /* R102 */
+	0x0000,     /* R103 */
+	0x00E4,     /* R104 - LOUT1 Volume */
+	0x00E4,     /* R105 - ROUT1 Volume */
+	0x00E4,     /* R106 - LOUT2 Volume */
+	0x02E4,     /* R107 - ROUT2 Volume */
+	0x0000,     /* R108 */
+	0x0000,     /* R109 */
+	0x0000,     /* R110 */
+	0x0000,     /* R111 - BEEP Volume */
+	0x0A00,     /* R112 - AI Formating */
+	0x0000,     /* R113 - ADC DAC COMP */
+	0x0020,     /* R114 - AI ADC Control */
+	0x0020,     /* R115 - AI DAC Control */
+	0x0000,     /* R116 - AIF Test */
+	0x0000,     /* R117 */
+	0x0000,     /* R118 */
+	0x0000,     /* R119 */
+	0x0000,     /* R120 */
+	0x0000,     /* R121 */
+	0x0000,     /* R122 */
+	0x0000,     /* R123 */
+	0x0000,     /* R124 */
+	0x0000,     /* R125 */
+	0x0000,     /* R126 */
+	0x0000,     /* R127 */
+	0x1FFF,     /* R128 - GPIO Debounce */
+	0x0000,     /* R129 - GPIO Pin pull up Control */
+	0x03FC,     /* R130 - GPIO Pull down Control */
+	0x0000,     /* R131 - GPIO Interrupt Mode */
+	0x0000,     /* R132 */
+	0x0000,     /* R133 - GPIO Control */
+	0x08FB,     /* R134 - GPIO Configuration (i/o) */
+	0x0CFE,     /* R135 - GPIO Pin Polarity / Type */
+	0x0000,     /* R136 */
+	0x0000,     /* R137 */
+	0x0000,     /* R138 */
+	0x0000,     /* R139 */
+	0x0312,     /* R140 - GPIO Function Select 1 */
+	0x0003,     /* R141 - GPIO Function Select 2 */
+	0x2331,     /* R142 - GPIO Function Select 3 */
+	0x0003,     /* R143 - GPIO Function Select 4 */
+	0x0000,     /* R144 - Digitiser Control (1) */
+	0x0002,     /* R145 - Digitiser Control (2) */
+	0x0000,     /* R146 */
+	0x0000,     /* R147 */
+	0x0000,     /* R148 */
+	0x0000,     /* R149 */
+	0x0000,     /* R150 */
+	0x0000,     /* R151 */
+	0x7000,     /* R152 - AUX1 Readback */
+	0x7000,     /* R153 - AUX2 Readback */
+	0x7000,     /* R154 - AUX3 Readback */
+	0x7000,     /* R155 - AUX4 Readback */
+	0x0000,     /* R156 - USB Voltage Readback */
+	0x0000,     /* R157 - LINE Voltage Readback */
+	0x0000,     /* R158 - BATT Voltage Readback */
+	0x0000,     /* R159 - Chip Temp Readback */
+	0x0000,     /* R160 */
+	0x0000,     /* R161 */
+	0x0000,     /* R162 */
+	0x0000,     /* R163 - Generic Comparator Control */
+	0x0000,     /* R164 - Generic comparator 1 */
+	0x0000,     /* R165 - Generic comparator 2 */
+	0x0000,     /* R166 - Generic comparator 3 */
+	0x0000,     /* R167 - Generic comparator 4 */
+	0xA00F,     /* R168 - Battery Charger Control 1 */
+	0x0B06,     /* R169 - Battery Charger Control 2 */
+	0x0000,     /* R170 - Battery Charger Control 3 */
+	0x0000,     /* R171 */
+	0x0000,     /* R172 - Current Sink Driver A */
+	0x0000,     /* R173 - CSA Flash control */
+	0x0000,     /* R174 - Current Sink Driver B */
+	0x0000,     /* R175 - CSB Flash control */
+	0x0000,     /* R176 - DCDC/LDO requested */
+	0x002D,     /* R177 - DCDC Active options */
+	0x0000,     /* R178 - DCDC Sleep options */
+	0x0025,     /* R179 - Power-check comparator */
+	0x000E,     /* R180 - DCDC1 Control */
+	0x0400,     /* R181 - DCDC1 Timeouts */
+	0x1006,     /* R182 - DCDC1 Low Power */
+	0x0018,     /* R183 - DCDC2 Control */
+	0x0000,     /* R184 - DCDC2 Timeouts */
+	0x0000,     /* R185 */
+	0x002E,     /* R186 - DCDC3 Control */
+	0x0800,     /* R187 - DCDC3 Timeouts */
+	0x0006,     /* R188 - DCDC3 Low Power */
+	0x000E,     /* R189 - DCDC4 Control */
+	0x0800,     /* R190 - DCDC4 Timeouts */
+	0x0006,     /* R191 - DCDC4 Low Power */
+	0x0008,     /* R192 - DCDC5 Control */
+	0x0000,     /* R193 - DCDC5 Timeouts */
+	0x0000,     /* R194 */
+	0x0026,     /* R195 - DCDC6 Control */
+	0x0C00,     /* R196 - DCDC6 Timeouts */
+	0x0006,     /* R197 - DCDC6 Low Power */
+	0x0000,     /* R198 */
+	0x0003,     /* R199 - Limit Switch Control */
+	0x001A,     /* R200 - LDO1 Control */
+	0x0800,     /* R201 - LDO1 Timeouts */
+	0x001C,     /* R202 - LDO1 Low Power */
+	0x0010,     /* R203 - LDO2 Control */
+	0x0800,     /* R204 - LDO2 Timeouts */
+	0x001C,     /* R205 - LDO2 Low Power */
+	0x000A,     /* R206 - LDO3 Control */
+	0x0C00,     /* R207 - LDO3 Timeouts */
+	0x001C,     /* R208 - LDO3 Low Power */
+	0x001A,     /* R209 - LDO4 Control */
+	0x0800,     /* R210 - LDO4 Timeouts */
+	0x001C,     /* R211 - LDO4 Low Power */
+	0x0000,     /* R212 */
+	0x0000,     /* R213 */
+	0x0000,     /* R214 */
+	0x0000,     /* R215 - VCC_FAULT Masks */
+	0x001F,     /* R216 - Main Bandgap Control */
+	0x0000,     /* R217 - OSC Control */
+	0x9000,     /* R218 - RTC Tick Control */
+	0x0000,     /* R219 */
+	0x4000,     /* R220 - RAM BIST 1 */
+	0x0000,     /* R221 */
+	0x0000,     /* R222 */
+	0x0000,     /* R223 */
+	0x0000,     /* R224 */
+	0x0000,     /* R225 - DCDC/LDO status */
+	0x0000,     /* R226 */
+	0x0000,     /* R227 */
+	0x0000,     /* R228 */
+	0x0000,     /* R229 */
+	0xE000,     /* R230 - GPIO Pin Status */
+	0x0000,     /* R231 */
+	0x0000,     /* R232 */
+	0x0000,     /* R233 */
+	0x0000,     /* R234 */
+	0x0000,     /* R235 */
+	0x0000,     /* R236 */
+	0x0000,     /* R237 */
+	0x0000,     /* R238 */
+	0x0000,     /* R239 */
+	0x0000,     /* R240 */
+	0x0000,     /* R241 */
+	0x0000,     /* R242 */
+	0x0000,     /* R243 */
+	0x0000,     /* R244 */
+	0x0000,     /* R245 */
+	0x0000,     /* R246 */
+	0x0000,     /* R247 */
+	0x0000,     /* R248 */
+	0x0000,     /* R249 */
+	0x0000,     /* R250 */
+	0x0000,     /* R251 */
+	0x0000,     /* R252 */
+	0x0000,     /* R253 */
+	0x0000,     /* R254 */
+	0x0000,     /* R255 */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8350_mode3_defaults[] = {
+	0x17FF,     /* R0   - Reset/ID */
+	0x1000,     /* R1   - ID */
+	0x0000,     /* R2 */
+	0x1000,     /* R3   - System Control 1 */
+	0x0004,     /* R4   - System Control 2 */
+	0x0000,     /* R5   - System Hibernate */
+	0x8A00,     /* R6   - Interface Control */
+	0x0000,     /* R7 */
+	0x8000,     /* R8   - Power mgmt (1) */
+	0x0000,     /* R9   - Power mgmt (2) */
+	0x0000,     /* R10  - Power mgmt (3) */
+	0x2000,     /* R11  - Power mgmt (4) */
+	0x0E00,     /* R12  - Power mgmt (5) */
+	0x0000,     /* R13  - Power mgmt (6) */
+	0x0000,     /* R14  - Power mgmt (7) */
+	0x0000,     /* R15 */
+	0x0000,     /* R16  - RTC Seconds/Minutes */
+	0x0100,     /* R17  - RTC Hours/Day */
+	0x0101,     /* R18  - RTC Date/Month */
+	0x1400,     /* R19  - RTC Year */
+	0x0000,     /* R20  - Alarm Seconds/Minutes */
+	0x0000,     /* R21  - Alarm Hours/Day */
+	0x0000,     /* R22  - Alarm Date/Month */
+	0x0320,     /* R23  - RTC Time Control */
+	0x0000,     /* R24  - System Interrupts */
+	0x0000,     /* R25  - Interrupt Status 1 */
+	0x0000,     /* R26  - Interrupt Status 2 */
+	0x0000,     /* R27  - Power Up Interrupt Status */
+	0x0000,     /* R28  - Under Voltage Interrupt status */
+	0x0000,     /* R29  - Over Current Interrupt status */
+	0x0000,     /* R30  - GPIO Interrupt Status */
+	0x0000,     /* R31  - Comparator Interrupt Status */
+	0x3FFF,     /* R32  - System Interrupts Mask */
+	0x0000,     /* R33  - Interrupt Status 1 Mask */
+	0x0000,     /* R34  - Interrupt Status 2 Mask */
+	0x0000,     /* R35  - Power Up Interrupt Status Mask */
+	0x0000,     /* R36  - Under Voltage Interrupt status Mask */
+	0x0000,     /* R37  - Over Current Interrupt status Mask */
+	0x0000,     /* R38  - GPIO Interrupt Status Mask */
+	0x0000,     /* R39  - Comparator Interrupt Status Mask */
+	0x0040,     /* R40  - Clock Control 1 */
+	0x0000,     /* R41  - Clock Control 2 */
+	0x3B00,     /* R42  - FLL Control 1 */
+	0x7086,     /* R43  - FLL Control 2 */
+	0xC226,     /* R44  - FLL Control 3 */
+	0x0000,     /* R45  - FLL Control 4 */
+	0x0000,     /* R46 */
+	0x0000,     /* R47 */
+	0x0000,     /* R48  - DAC Control */
+	0x0000,     /* R49 */
+	0x00C0,     /* R50  - DAC Digital Volume L */
+	0x00C0,     /* R51  - DAC Digital Volume R */
+	0x0000,     /* R52 */
+	0x0040,     /* R53  - DAC LR Rate */
+	0x0000,     /* R54  - DAC Clock Control */
+	0x0000,     /* R55 */
+	0x0000,     /* R56 */
+	0x0000,     /* R57 */
+	0x4000,     /* R58  - DAC Mute */
+	0x0000,     /* R59  - DAC Mute Volume */
+	0x0000,     /* R60  - DAC Side */
+	0x0000,     /* R61 */
+	0x0000,     /* R62 */
+	0x0000,     /* R63 */
+	0x8000,     /* R64  - ADC Control */
+	0x0000,     /* R65 */
+	0x00C0,     /* R66  - ADC Digital Volume L */
+	0x00C0,     /* R67  - ADC Digital Volume R */
+	0x0000,     /* R68  - ADC Divider */
+	0x0000,     /* R69 */
+	0x0040,     /* R70  - ADC LR Rate */
+	0x0000,     /* R71 */
+	0x0303,     /* R72  - Input Control */
+	0x0000,     /* R73  - IN3 Input Control */
+	0x0000,     /* R74  - Mic Bias Control */
+	0x0000,     /* R75 */
+	0x0000,     /* R76  - Output Control */
+	0x0000,     /* R77  - Jack Detect */
+	0x0000,     /* R78  - Anti Pop Control */
+	0x0000,     /* R79 */
+	0x0040,     /* R80  - Left Input Volume */
+	0x0040,     /* R81  - Right Input Volume */
+	0x0000,     /* R82 */
+	0x0000,     /* R83 */
+	0x0000,     /* R84 */
+	0x0000,     /* R85 */
+	0x0000,     /* R86 */
+	0x0000,     /* R87 */
+	0x0800,     /* R88  - Left Mixer Control */
+	0x1000,     /* R89  - Right Mixer Control */
+	0x0000,     /* R90 */
+	0x0000,     /* R91 */
+	0x0000,     /* R92  - OUT3 Mixer Control */
+	0x0000,     /* R93  - OUT4 Mixer Control */
+	0x0000,     /* R94 */
+	0x0000,     /* R95 */
+	0x0000,     /* R96  - Output Left Mixer Volume */
+	0x0000,     /* R97  - Output Right Mixer Volume */
+	0x0000,     /* R98  - Input Mixer Volume L */
+	0x0000,     /* R99  - Input Mixer Volume R */
+	0x0000,     /* R100 - Input Mixer Volume */
+	0x0000,     /* R101 */
+	0x0000,     /* R102 */
+	0x0000,     /* R103 */
+	0x00E4,     /* R104 - LOUT1 Volume */
+	0x00E4,     /* R105 - ROUT1 Volume */
+	0x00E4,     /* R106 - LOUT2 Volume */
+	0x02E4,     /* R107 - ROUT2 Volume */
+	0x0000,     /* R108 */
+	0x0000,     /* R109 */
+	0x0000,     /* R110 */
+	0x0000,     /* R111 - BEEP Volume */
+	0x0A00,     /* R112 - AI Formating */
+	0x0000,     /* R113 - ADC DAC COMP */
+	0x0020,     /* R114 - AI ADC Control */
+	0x0020,     /* R115 - AI DAC Control */
+	0x0000,     /* R116 - AIF Test */
+	0x0000,     /* R117 */
+	0x0000,     /* R118 */
+	0x0000,     /* R119 */
+	0x0000,     /* R120 */
+	0x0000,     /* R121 */
+	0x0000,     /* R122 */
+	0x0000,     /* R123 */
+	0x0000,     /* R124 */
+	0x0000,     /* R125 */
+	0x0000,     /* R126 */
+	0x0000,     /* R127 */
+	0x1FFF,     /* R128 - GPIO Debounce */
+	0x0000,     /* R129 - GPIO Pin pull up Control */
+	0x03FC,     /* R130 - GPIO Pull down Control */
+	0x0000,     /* R131 - GPIO Interrupt Mode */
+	0x0000,     /* R132 */
+	0x0000,     /* R133 - GPIO Control */
+	0x0A7B,     /* R134 - GPIO Configuration (i/o) */
+	0x06FE,     /* R135 - GPIO Pin Polarity / Type */
+	0x0000,     /* R136 */
+	0x0000,     /* R137 */
+	0x0000,     /* R138 */
+	0x0000,     /* R139 */
+	0x1312,     /* R140 - GPIO Function Select 1 */
+	0x1030,     /* R141 - GPIO Function Select 2 */
+	0x2231,     /* R142 - GPIO Function Select 3 */
+	0x0003,     /* R143 - GPIO Function Select 4 */
+	0x0000,     /* R144 - Digitiser Control (1) */
+	0x0002,     /* R145 - Digitiser Control (2) */
+	0x0000,     /* R146 */
+	0x0000,     /* R147 */
+	0x0000,     /* R148 */
+	0x0000,     /* R149 */
+	0x0000,     /* R150 */
+	0x0000,     /* R151 */
+	0x7000,     /* R152 - AUX1 Readback */
+	0x7000,     /* R153 - AUX2 Readback */
+	0x7000,     /* R154 - AUX3 Readback */
+	0x7000,     /* R155 - AUX4 Readback */
+	0x0000,     /* R156 - USB Voltage Readback */
+	0x0000,     /* R157 - LINE Voltage Readback */
+	0x0000,     /* R158 - BATT Voltage Readback */
+	0x0000,     /* R159 - Chip Temp Readback */
+	0x0000,     /* R160 */
+	0x0000,     /* R161 */
+	0x0000,     /* R162 */
+	0x0000,     /* R163 - Generic Comparator Control */
+	0x0000,     /* R164 - Generic comparator 1 */
+	0x0000,     /* R165 - Generic comparator 2 */
+	0x0000,     /* R166 - Generic comparator 3 */
+	0x0000,     /* R167 - Generic comparator 4 */
+	0xA00F,     /* R168 - Battery Charger Control 1 */
+	0x0B06,     /* R169 - Battery Charger Control 2 */
+	0x0000,     /* R170 - Battery Charger Control 3 */
+	0x0000,     /* R171 */
+	0x0000,     /* R172 - Current Sink Driver A */
+	0x0000,     /* R173 - CSA Flash control */
+	0x0000,     /* R174 - Current Sink Driver B */
+	0x0000,     /* R175 - CSB Flash control */
+	0x0000,     /* R176 - DCDC/LDO requested */
+	0x002D,     /* R177 - DCDC Active options */
+	0x0000,     /* R178 - DCDC Sleep options */
+	0x0025,     /* R179 - Power-check comparator */
+	0x000E,     /* R180 - DCDC1 Control */
+	0x0400,     /* R181 - DCDC1 Timeouts */
+	0x1006,     /* R182 - DCDC1 Low Power */
+	0x0018,     /* R183 - DCDC2 Control */
+	0x0000,     /* R184 - DCDC2 Timeouts */
+	0x0000,     /* R185 */
+	0x000E,     /* R186 - DCDC3 Control */
+	0x0400,     /* R187 - DCDC3 Timeouts */
+	0x0006,     /* R188 - DCDC3 Low Power */
+	0x0026,     /* R189 - DCDC4 Control */
+	0x0400,     /* R190 - DCDC4 Timeouts */
+	0x0006,     /* R191 - DCDC4 Low Power */
+	0x0008,     /* R192 - DCDC5 Control */
+	0x0000,     /* R193 - DCDC5 Timeouts */
+	0x0000,     /* R194 */
+	0x0026,     /* R195 - DCDC6 Control */
+	0x0400,     /* R196 - DCDC6 Timeouts */
+	0x0006,     /* R197 - DCDC6 Low Power */
+	0x0000,     /* R198 */
+	0x0003,     /* R199 - Limit Switch Control */
+	0x001C,     /* R200 - LDO1 Control */
+	0x0000,     /* R201 - LDO1 Timeouts */
+	0x001C,     /* R202 - LDO1 Low Power */
+	0x001C,     /* R203 - LDO2 Control */
+	0x0400,     /* R204 - LDO2 Timeouts */
+	0x001C,     /* R205 - LDO2 Low Power */
+	0x001C,     /* R206 - LDO3 Control */
+	0x0400,     /* R207 - LDO3 Timeouts */
+	0x001C,     /* R208 - LDO3 Low Power */
+	0x001F,     /* R209 - LDO4 Control */
+	0x0400,     /* R210 - LDO4 Timeouts */
+	0x001C,     /* R211 - LDO4 Low Power */
+	0x0000,     /* R212 */
+	0x0000,     /* R213 */
+	0x0000,     /* R214 */
+	0x0000,     /* R215 - VCC_FAULT Masks */
+	0x001F,     /* R216 - Main Bandgap Control */
+	0x0000,     /* R217 - OSC Control */
+	0x9000,     /* R218 - RTC Tick Control */
+	0x0000,     /* R219 */
+	0x4000,     /* R220 - RAM BIST 1 */
+	0x0000,     /* R221 */
+	0x0000,     /* R222 */
+	0x0000,     /* R223 */
+	0x0000,     /* R224 */
+	0x0000,     /* R225 - DCDC/LDO status */
+	0x0000,     /* R226 */
+	0x0000,     /* R227 */
+	0x0000,     /* R228 */
+	0x0000,     /* R229 */
+	0xE000,     /* R230 - GPIO Pin Status */
+	0x0000,     /* R231 */
+	0x0000,     /* R232 */
+	0x0000,     /* R233 */
+	0x0000,     /* R234 */
+	0x0000,     /* R235 */
+	0x0000,     /* R236 */
+	0x0000,     /* R237 */
+	0x0000,     /* R238 */
+	0x0000,     /* R239 */
+	0x0000,     /* R240 */
+	0x0000,     /* R241 */
+	0x0000,     /* R242 */
+	0x0000,     /* R243 */
+	0x0000,     /* R244 */
+	0x0000,     /* R245 */
+	0x0000,     /* R246 */
+	0x0000,     /* R247 */
+	0x0000,     /* R248 */
+	0x0000,     /* R249 */
+	0x0000,     /* R250 */
+	0x0000,     /* R251 */
+	0x0000,     /* R252 */
+	0x0000,     /* R253 */
+	0x0000,     /* R254 */
+	0x0000,     /* R255 */
+};
+#endif
+
+/* The register defaults for the config mode used must be compiled in but
+ * due to the impact on kernel size it is possible to disable
+ */
+#ifndef WM8350_HAVE_CONFIG_MODE
+#warning No WM8350 config modes supported - select at least one of the
+#warning MFD_WM8350_CONFIG_MODE_n options from the board driver.
+#endif
+
+/*
+ * Access masks.
+ */
+
+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 */
+	{ 0xBE3B, 0xBE3B, 0x8000 }, /* R3   - System Control 1 */
+	{ 0xFCF7, 0xFCF7, 0xF800 }, /* R4   - System Control 2 */
+	{ 0x80FF, 0x80FF, 0x8000 }, /* R5   - System Hibernate */
+	{ 0xFB0E, 0xFB0E, 0x0000 }, /* R6   - Interface Control */
+	{ 0x0000, 0x0000, 0x0000 }, /* R7 */
+	{ 0xE537, 0xE537, 0xFFFF }, /* R8   - Power mgmt (1) */
+	{ 0x0FF3, 0x0FF3, 0xFFFF }, /* R9   - Power mgmt (2) */
+	{ 0x008F, 0x008F, 0xFFFF }, /* R10  - Power mgmt (3) */
+	{ 0x6D3C, 0x6D3C, 0xFFFF }, /* R11  - Power mgmt (4) */
+	{ 0x1F8F, 0x1F8F, 0xFFFF }, /* R12  - Power mgmt (5) */
+	{ 0x8F3F, 0x8F3F, 0xFFFF }, /* R13  - Power mgmt (6) */
+	{ 0x0003, 0x0003, 0xFFFF }, /* R14  - Power mgmt (7) */
+	{ 0x0000, 0x0000, 0x0000 }, /* R15 */
+	{ 0x7F7F, 0x7F7F, 0xFFFF }, /* R16  - RTC Seconds/Minutes */
+	{ 0x073F, 0x073F, 0xFFFF }, /* R17  - RTC Hours/Day */
+	{ 0x1F3F, 0x1F3F, 0xFFFF }, /* R18  - RTC Date/Month */
+	{ 0x3FFF, 0x00FF, 0xFFFF }, /* R19  - RTC Year */
+	{ 0x7F7F, 0x7F7F, 0x0000 }, /* R20  - Alarm Seconds/Minutes */
+	{ 0x0F3F, 0x0F3F, 0x0000 }, /* R21  - Alarm Hours/Day */
+	{ 0x1F3F, 0x1F3F, 0x0000 }, /* R22  - Alarm Date/Month */
+	{ 0xEF7F, 0xEA7F, 0xFFFF }, /* R23  - RTC Time Control */
+	{ 0x3BFF, 0x0000, 0xFFFF }, /* R24  - System Interrupts */
+	{ 0xFEE7, 0x0000, 0xFFFF }, /* R25  - Interrupt Status 1 */
+	{ 0x35FF, 0x0000, 0xFFFF }, /* R26  - Interrupt Status 2 */
+	{ 0x0F3F, 0x0000, 0xFFFF }, /* R27  - Power Up Interrupt Status */
+	{ 0x0F3F, 0x0000, 0xFFFF }, /* R28  - Under Voltage Interrupt status */
+	{ 0x8000, 0x0000, 0xFFFF }, /* R29  - Over Current Interrupt status */
+	{ 0x1FFF, 0x0000, 0xFFFF }, /* R30  - GPIO Interrupt Status */
+	{ 0xEF7F, 0x0000, 0xFFFF }, /* R31  - Comparator Interrupt Status */
+	{ 0x3FFF, 0x3FFF, 0x0000 }, /* R32  - System Interrupts Mask */
+	{ 0xFEE7, 0xFEE7, 0x0000 }, /* R33  - Interrupt Status 1 Mask */
+	{ 0xF5FF, 0xF5FF, 0x0000 }, /* R34  - Interrupt Status 2 Mask */
+	{ 0x0F3F, 0x0F3F, 0x0000 }, /* R35  - Power Up Interrupt Status Mask */
+	{ 0x0F3F, 0x0F3F, 0x0000 }, /* R36  - Under Voltage Int status Mask */
+	{ 0x8000, 0x8000, 0x0000 }, /* R37  - Over Current Int status Mask */
+	{ 0x1FFF, 0x1FFF, 0x0000 }, /* R38  - GPIO Interrupt Status Mask */
+	{ 0xEF7F, 0xEF7F, 0x0000 }, /* R39  - Comparator IntStatus Mask */
+	{ 0xC9F7, 0xC9F7, 0xFFFF }, /* R40  - Clock Control 1 */
+	{ 0x8001, 0x8001, 0x0000 }, /* R41  - Clock Control 2 */
+	{ 0xFFF7, 0xFFF7, 0xFFFF }, /* R42  - FLL Control 1 */
+	{ 0xFBFF, 0xFBFF, 0x0000 }, /* R43  - FLL Control 2 */
+	{ 0xFFFF, 0xFFFF, 0x0000 }, /* R44  - FLL Control 3 */
+	{ 0x0033, 0x0033, 0x0000 }, /* R45  - FLL Control 4 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R46 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R47 */
+	{ 0x3033, 0x3033, 0x0000 }, /* R48  - DAC Control */
+	{ 0x0000, 0x0000, 0x0000 }, /* R49 */
+	{ 0x81FF, 0x81FF, 0xFFFF }, /* R50  - DAC Digital Volume L */
+	{ 0x81FF, 0x81FF, 0xFFFF }, /* R51  - DAC Digital Volume R */
+	{ 0x0000, 0x0000, 0x0000 }, /* R52 */
+	{ 0x0FFF, 0x0FFF, 0xFFFF }, /* R53  - DAC LR Rate */
+	{ 0x0017, 0x0017, 0x0000 }, /* R54  - DAC Clock Control */
+	{ 0x0000, 0x0000, 0x0000 }, /* R55 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R56 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R57 */
+	{ 0x4000, 0x4000, 0x0000 }, /* R58  - DAC Mute */
+	{ 0x7000, 0x7000, 0x0000 }, /* R59  - DAC Mute Volume */
+	{ 0x3C00, 0x3C00, 0x0000 }, /* R60  - DAC Side */
+	{ 0x0000, 0x0000, 0x0000 }, /* R61 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R62 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R63 */
+	{ 0x8303, 0x8303, 0xFFFF }, /* R64  - ADC Control */
+	{ 0x0000, 0x0000, 0x0000 }, /* R65 */
+	{ 0x81FF, 0x81FF, 0xFFFF }, /* R66  - ADC Digital Volume L */
+	{ 0x81FF, 0x81FF, 0xFFFF }, /* R67  - ADC Digital Volume R */
+	{ 0x0FFF, 0x0FFF, 0x0000 }, /* R68  - ADC Divider */
+	{ 0x0000, 0x0000, 0x0000 }, /* R69 */
+	{ 0x0FFF, 0x0FFF, 0xFFFF }, /* R70  - ADC LR Rate */
+	{ 0x0000, 0x0000, 0x0000 }, /* R71 */
+	{ 0x0707, 0x0707, 0xFFFF }, /* R72  - Input Control */
+	{ 0xC0C0, 0xC0C0, 0xFFFF }, /* R73  - IN3 Input Control */
+	{ 0xC09F, 0xC09F, 0xFFFF }, /* R74  - Mic Bias Control */
+	{ 0x0000, 0x0000, 0x0000 }, /* R75 */
+	{ 0x0F15, 0x0F15, 0xFFFF }, /* R76  - Output Control */
+	{ 0xC000, 0xC000, 0xFFFF }, /* R77  - Jack Detect */
+	{ 0x03FF, 0x03FF, 0x0000 }, /* R78  - Anti Pop Control */
+	{ 0x0000, 0x0000, 0x0000 }, /* R79 */
+	{ 0xE1FC, 0xE1FC, 0x8000 }, /* R80  - Left Input Volume */
+	{ 0xE1FC, 0xE1FC, 0x8000 }, /* R81  - Right Input Volume */
+	{ 0x0000, 0x0000, 0x0000 }, /* R82 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R83 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R84 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R85 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R86 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R87 */
+	{ 0x9807, 0x9807, 0xFFFF }, /* R88  - Left Mixer Control */
+	{ 0x980B, 0x980B, 0xFFFF }, /* R89  - Right Mixer Control */
+	{ 0x0000, 0x0000, 0x0000 }, /* R90 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R91 */
+	{ 0x8909, 0x8909, 0xFFFF }, /* R92  - OUT3 Mixer Control */
+	{ 0x9E07, 0x9E07, 0xFFFF }, /* R93  - OUT4 Mixer Control */
+	{ 0x0000, 0x0000, 0x0000 }, /* R94 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R95 */
+	{ 0x0EEE, 0x0EEE, 0x0000 }, /* R96  - Output Left Mixer Volume */
+	{ 0xE0EE, 0xE0EE, 0x0000 }, /* R97  - Output Right Mixer Volume */
+	{ 0x0E0F, 0x0E0F, 0x0000 }, /* R98  - Input Mixer Volume L */
+	{ 0xE0E1, 0xE0E1, 0x0000 }, /* R99  - Input Mixer Volume R */
+	{ 0x800E, 0x800E, 0x0000 }, /* R100 - Input Mixer Volume */
+	{ 0x0000, 0x0000, 0x0000 }, /* R101 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R102 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R103 */
+	{ 0xE1FC, 0xE1FC, 0xFFFF }, /* R104 - LOUT1 Volume */
+	{ 0xE1FC, 0xE1FC, 0xFFFF }, /* R105 - ROUT1 Volume */
+	{ 0xE1FC, 0xE1FC, 0xFFFF }, /* R106 - LOUT2 Volume */
+	{ 0xE7FC, 0xE7FC, 0xFFFF }, /* R107 - ROUT2 Volume */
+	{ 0x0000, 0x0000, 0x0000 }, /* R108 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R109 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R110 */
+	{ 0x80E0, 0x80E0, 0xFFFF }, /* R111 - BEEP Volume */
+	{ 0xBF00, 0xBF00, 0x0000 }, /* R112 - AI Formating */
+	{ 0x00F1, 0x00F1, 0x0000 }, /* R113 - ADC DAC COMP */
+	{ 0x00F8, 0x00F8, 0x0000 }, /* R114 - AI ADC Control */
+	{ 0x40FB, 0x40FB, 0x0000 }, /* R115 - AI DAC Control */
+	{ 0x7C30, 0x7C30, 0x0000 }, /* R116 - AIF Test */
+	{ 0x0000, 0x0000, 0x0000 }, /* R117 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R118 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R119 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R120 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R121 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R122 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R123 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R124 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R125 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R126 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R127 */
+	{ 0x1FFF, 0x1FFF, 0x0000 }, /* R128 - GPIO Debounce */
+	{ 0x1FFF, 0x1FFF, 0x0000 }, /* R129 - GPIO Pin pull up Control */
+	{ 0x1FFF, 0x1FFF, 0x0000 }, /* R130 - GPIO Pull down Control */
+	{ 0x1FFF, 0x1FFF, 0x0000 }, /* R131 - GPIO Interrupt Mode */
+	{ 0x0000, 0x0000, 0x0000 }, /* R132 */
+	{ 0x00C0, 0x00C0, 0x0000 }, /* R133 - GPIO Control */
+	{ 0x1FFF, 0x1FFF, 0x0000 }, /* R134 - GPIO Configuration (i/o) */
+	{ 0x1FFF, 0x1FFF, 0x0000 }, /* R135 - GPIO Pin Polarity / Type */
+	{ 0x0000, 0x0000, 0x0000 }, /* R136 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R137 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R138 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R139 */
+	{ 0xFFFF, 0xFFFF, 0x0000 }, /* R140 - GPIO Function Select 1 */
+	{ 0xFFFF, 0xFFFF, 0x0000 }, /* R141 - GPIO Function Select 2 */
+	{ 0xFFFF, 0xFFFF, 0x0000 }, /* R142 - GPIO Function Select 3 */
+	{ 0x000F, 0x000F, 0x0000 }, /* R143 - GPIO Function Select 4 */
+	{ 0xF0FF, 0xF0FF, 0xA000 }, /* R144 - Digitiser Control (1) */
+	{ 0x3707, 0x3707, 0x0000 }, /* R145 - Digitiser Control (2) */
+	{ 0x0000, 0x0000, 0x0000 }, /* R146 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R147 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R148 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R149 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R150 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R151 */
+	{ 0x7FFF, 0x7000, 0xFFFF }, /* R152 - AUX1 Readback */
+	{ 0x7FFF, 0x7000, 0xFFFF }, /* R153 - AUX2 Readback */
+	{ 0x7FFF, 0x7000, 0xFFFF }, /* R154 - AUX3 Readback */
+	{ 0x7FFF, 0x7000, 0xFFFF }, /* R155 - AUX4 Readback */
+	{ 0x0FFF, 0x0000, 0xFFFF }, /* R156 - USB Voltage Readback */
+	{ 0x0FFF, 0x0000, 0xFFFF }, /* R157 - LINE Voltage Readback */
+	{ 0x0FFF, 0x0000, 0xFFFF }, /* R158 - BATT Voltage Readback */
+	{ 0x0FFF, 0x0000, 0xFFFF }, /* R159 - Chip Temp Readback */
+	{ 0x0000, 0x0000, 0x0000 }, /* R160 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R161 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R162 */
+	{ 0x000F, 0x000F, 0x0000 }, /* R163 - Generic Comparator Control */
+	{ 0xFFFF, 0xFFFF, 0x0000 }, /* R164 - Generic comparator 1 */
+	{ 0xFFFF, 0xFFFF, 0x0000 }, /* R165 - Generic comparator 2 */
+	{ 0xFFFF, 0xFFFF, 0x0000 }, /* R166 - Generic comparator 3 */
+	{ 0xFFFF, 0xFFFF, 0x0000 }, /* R167 - Generic comparator 4 */
+	{ 0xBFFF, 0xBFFF, 0x8000 }, /* R168 - Battery Charger Control 1 */
+	{ 0xFFFF, 0x4FFF, 0xB000 }, /* R169 - Battery Charger Control 2 */
+	{ 0x007F, 0x007F, 0x0000 }, /* R170 - Battery Charger Control 3 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R171 */
+	{ 0x903F, 0x903F, 0xFFFF }, /* R172 - Current Sink Driver A */
+	{ 0xE333, 0xE333, 0xFFFF }, /* R173 - CSA Flash control */
+	{ 0x903F, 0x903F, 0xFFFF }, /* R174 - Current Sink Driver B */
+	{ 0xE333, 0xE333, 0xFFFF }, /* R175 - CSB Flash control */
+	{ 0x8F3F, 0x8F3F, 0xFFFF }, /* R176 - DCDC/LDO requested */
+	{ 0x332D, 0x332D, 0x0000 }, /* R177 - DCDC Active options */
+	{ 0x002D, 0x002D, 0x0000 }, /* R178 - DCDC Sleep options */
+	{ 0x5177, 0x5177, 0x8000 }, /* R179 - Power-check comparator */
+	{ 0x047F, 0x047F, 0x0000 }, /* R180 - DCDC1 Control */
+	{ 0xFFC0, 0xFFC0, 0x0000 }, /* R181 - DCDC1 Timeouts */
+	{ 0x737F, 0x737F, 0x0000 }, /* R182 - DCDC1 Low Power */
+	{ 0x535B, 0x535B, 0x0000 }, /* R183 - DCDC2 Control */
+	{ 0xFFC0, 0xFFC0, 0x0000 }, /* R184 - DCDC2 Timeouts */
+	{ 0x0000, 0x0000, 0x0000 }, /* R185 */
+	{ 0x047F, 0x047F, 0x0000 }, /* R186 - DCDC3 Control */
+	{ 0xFFC0, 0xFFC0, 0x0000 }, /* R187 - DCDC3 Timeouts */
+	{ 0x737F, 0x737F, 0x0000 }, /* R188 - DCDC3 Low Power */
+	{ 0x047F, 0x047F, 0x0000 }, /* R189 - DCDC4 Control */
+	{ 0xFFC0, 0xFFC0, 0x0000 }, /* R190 - DCDC4 Timeouts */
+	{ 0x737F, 0x737F, 0x0000 }, /* R191 - DCDC4 Low Power */
+	{ 0x535B, 0x535B, 0x0000 }, /* R192 - DCDC5 Control */
+	{ 0xFFC0, 0xFFC0, 0x0000 }, /* R193 - DCDC5 Timeouts */
+	{ 0x0000, 0x0000, 0x0000 }, /* R194 */
+	{ 0x047F, 0x047F, 0x0000 }, /* R195 - DCDC6 Control */
+	{ 0xFFC0, 0xFFC0, 0x0000 }, /* R196 - DCDC6 Timeouts */
+	{ 0x737F, 0x737F, 0x0000 }, /* R197 - DCDC6 Low Power */
+	{ 0x0000, 0x0000, 0x0000 }, /* R198 */
+	{ 0xFFD3, 0xFFD3, 0x0000 }, /* R199 - Limit Switch Control */
+	{ 0x441F, 0x441F, 0x0000 }, /* R200 - LDO1 Control */
+	{ 0xFFC0, 0xFFC0, 0x0000 }, /* R201 - LDO1 Timeouts */
+	{ 0x331F, 0x331F, 0x0000 }, /* R202 - LDO1 Low Power */
+	{ 0x441F, 0x441F, 0x0000 }, /* R203 - LDO2 Control */
+	{ 0xFFC0, 0xFFC0, 0x0000 }, /* R204 - LDO2 Timeouts */
+	{ 0x331F, 0x331F, 0x0000 }, /* R205 - LDO2 Low Power */
+	{ 0x441F, 0x441F, 0x0000 }, /* R206 - LDO3 Control */
+	{ 0xFFC0, 0xFFC0, 0x0000 }, /* R207 - LDO3 Timeouts */
+	{ 0x331F, 0x331F, 0x0000 }, /* R208 - LDO3 Low Power */
+	{ 0x441F, 0x441F, 0x0000 }, /* R209 - LDO4 Control */
+	{ 0xFFC0, 0xFFC0, 0x0000 }, /* R210 - LDO4 Timeouts */
+	{ 0x331F, 0x331F, 0x0000 }, /* R211 - LDO4 Low Power */
+	{ 0x0000, 0x0000, 0x0000 }, /* R212 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R213 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R214 */
+	{ 0x8F3F, 0x8F3F, 0x0000 }, /* R215 - VCC_FAULT Masks */
+	{ 0xFF3F, 0xE03F, 0x0000 }, /* R216 - Main Bandgap Control */
+	{ 0xEF2F, 0xE02F, 0x0000 }, /* R217 - OSC Control */
+	{ 0xF3FF, 0xB3FF, 0xc000 }, /* R218 - RTC Tick Control */
+	{ 0xFFFF, 0xFFFF, 0xFFFF }, /* R219 */
+	{ 0x09FF, 0x01FF, 0x0000 }, /* R220 - RAM BIST 1 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R221 */
+	{ 0xFFFF, 0xFFFF, 0xFFFF }, /* R222 */
+	{ 0xFFFF, 0xFFFF, 0xFFFF }, /* R223 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R224 */
+	{ 0x8F3F, 0x0000, 0xFFFF }, /* R225 - DCDC/LDO status */
+	{ 0x0000, 0x0000, 0x0000 }, /* R226 */
+	{ 0x0000, 0x0000, 0xFFFF }, /* R227 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R228 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R229 */
+	{ 0xFFFF, 0x1FFF, 0xFFFF }, /* R230 - GPIO Pin Status */
+	{ 0xFFFF, 0x1FFF, 0xFFFF }, /* R231 */
+	{ 0xFFFF, 0x1FFF, 0xFFFF }, /* R232 */
+	{ 0xFFFF, 0x1FFF, 0xFFFF }, /* R233 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R234 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R235 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R236 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R237 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R238 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R239 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R240 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R241 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R242 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R243 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R244 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R245 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R246 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R247 */
+	{ 0xFFFF, 0x0010, 0xFFFF }, /* R248 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R249 */
+	{ 0xFFFF, 0x0010, 0xFFFF }, /* R250 */
+	{ 0xFFFF, 0x0010, 0xFFFF }, /* R251 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R252 */
+	{ 0xFFFF, 0x0010, 0xFFFF }, /* R253 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R254 */
+	{ 0x0000, 0x0000, 0x0000 }, /* R255 */
+};
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c
new file mode 100644
index 000000000000..6a0cedb5bb8a
--- /dev/null
+++ b/drivers/mfd/wm8400-core.c
@@ -0,0 +1,455 @@
+/*
+ * Core 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.
+ *
+ */
+
+#include <linux/bug.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/mfd/wm8400-private.h>
+#include <linux/mfd/wm8400-audio.h>
+
+static struct {
+	u16  readable;    /* Mask of readable bits */
+	u16  writable;    /* Mask of writable bits */
+	u16  vol;         /* Mask of volatile bits */
+	int  is_codec;    /* Register controlled by codec reset */
+	u16  default_val; /* Value on reset */
+} reg_data[] = {
+	{ 0xFFFF, 0xFFFF, 0x0000, 0, 0x6172 }, /* R0 */
+	{ 0x7000, 0x0000, 0x8000, 0, 0x0000 }, /* R1 */
+	{ 0xFF17, 0xFF17, 0x0000, 0, 0x0000 }, /* R2 */
+	{ 0xEBF3, 0xEBF3, 0x0000, 1, 0x6000 }, /* R3 */
+	{ 0x3CF3, 0x3CF3, 0x0000, 1, 0x0000 }, /* R4  */
+	{ 0xF1F8, 0xF1F8, 0x0000, 1, 0x4050 }, /* R5  */
+	{ 0xFC1F, 0xFC1F, 0x0000, 1, 0x4000 }, /* R6  */
+	{ 0xDFDE, 0xDFDE, 0x0000, 1, 0x01C8 }, /* R7  */
+	{ 0xFCFC, 0xFCFC, 0x0000, 1, 0x0000 }, /* R8  */
+	{ 0xEFFF, 0xEFFF, 0x0000, 1, 0x0040 }, /* R9  */
+	{ 0xEFFF, 0xEFFF, 0x0000, 1, 0x0040 }, /* R10 */
+	{ 0x27F7, 0x27F7, 0x0000, 1, 0x0004 }, /* R11 */
+	{ 0x01FF, 0x01FF, 0x0000, 1, 0x00C0 }, /* R12 */
+	{ 0x01FF, 0x01FF, 0x0000, 1, 0x00C0 }, /* R13 */
+	{ 0x1FEF, 0x1FEF, 0x0000, 1, 0x0000 }, /* R14 */
+	{ 0x0163, 0x0163, 0x0000, 1, 0x0100 }, /* R15 */
+	{ 0x01FF, 0x01FF, 0x0000, 1, 0x00C0 }, /* R16 */
+	{ 0x01FF, 0x01FF, 0x0000, 1, 0x00C0 }, /* R17 */
+	{ 0x1FFF, 0x0FFF, 0x0000, 1, 0x0000 }, /* R18 */
+	{ 0xFFFF, 0xFFFF, 0x0000, 1, 0x1000 }, /* R19 */
+	{ 0xFFFF, 0xFFFF, 0x0000, 1, 0x1010 }, /* R20 */
+	{ 0xFFFF, 0xFFFF, 0x0000, 1, 0x1010 }, /* R21 */
+	{ 0x0FDD, 0x0FDD, 0x0000, 1, 0x8000 }, /* R22 */
+	{ 0x1FFF, 0x1FFF, 0x0000, 1, 0x0800 }, /* R23 */
+	{ 0x0000, 0x01DF, 0x0000, 1, 0x008B }, /* R24 */
+	{ 0x0000, 0x01DF, 0x0000, 1, 0x008B }, /* R25 */
+	{ 0x0000, 0x01DF, 0x0000, 1, 0x008B }, /* R26 */
+	{ 0x0000, 0x01DF, 0x0000, 1, 0x008B }, /* R27 */
+	{ 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R28 */
+	{ 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R29 */
+	{ 0x0000, 0x0077, 0x0000, 1, 0x0066 }, /* R30 */
+	{ 0x0000, 0x0033, 0x0000, 1, 0x0022 }, /* R31 */
+	{ 0x0000, 0x01FF, 0x0000, 1, 0x0079 }, /* R32 */
+	{ 0x0000, 0x01FF, 0x0000, 1, 0x0079 }, /* R33 */
+	{ 0x0000, 0x0003, 0x0000, 1, 0x0003 }, /* R34 */
+	{ 0x0000, 0x01FF, 0x0000, 1, 0x0003 }, /* R35 */
+	{ 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R36 */
+	{ 0x0000, 0x003F, 0x0000, 1, 0x0100 }, /* R37 */
+	{ 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R38 */
+	{ 0x0000, 0x000F, 0x0000, 0, 0x0000 }, /* R39 */
+	{ 0x0000, 0x00FF, 0x0000, 1, 0x0000 }, /* R40 */
+	{ 0x0000, 0x01B7, 0x0000, 1, 0x0000 }, /* R41 */
+	{ 0x0000, 0x01B7, 0x0000, 1, 0x0000 }, /* R42 */
+	{ 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R43 */
+	{ 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R44 */
+	{ 0x0000, 0x00FD, 0x0000, 1, 0x0000 }, /* R45 */
+	{ 0x0000, 0x00FD, 0x0000, 1, 0x0000 }, /* R46 */
+	{ 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R47 */
+	{ 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R48 */
+	{ 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R49 */
+	{ 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R50 */
+	{ 0x0000, 0x01B3, 0x0000, 1, 0x0180 }, /* R51 */
+	{ 0x0000, 0x0077, 0x0000, 1, 0x0000 }, /* R52 */
+	{ 0x0000, 0x0077, 0x0000, 1, 0x0000 }, /* R53 */
+	{ 0x0000, 0x00FF, 0x0000, 1, 0x0000 }, /* R54 */
+	{ 0x0000, 0x0001, 0x0000, 1, 0x0000 }, /* R55 */
+	{ 0x0000, 0x003F, 0x0000, 1, 0x0000 }, /* R56 */
+	{ 0x0000, 0x004F, 0x0000, 1, 0x0000 }, /* R57 */
+	{ 0x0000, 0x00FD, 0x0000, 1, 0x0000 }, /* R58 */
+	{ 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R59 */
+	{ 0x1FFF, 0x1FFF, 0x0000, 1, 0x0000 }, /* R60 */
+	{ 0xFFFF, 0xFFFF, 0x0000, 1, 0x0000 }, /* R61 */
+	{ 0x03FF, 0x03FF, 0x0000, 1, 0x0000 }, /* R62 */
+	{ 0x007F, 0x007F, 0x0000, 1, 0x0000 }, /* R63 */
+	{ 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R64 */
+	{ 0xDFFF, 0xDFFF, 0x0000, 0, 0x0000 }, /* R65 */
+	{ 0xDFFF, 0xDFFF, 0x0000, 0, 0x0000 }, /* R66 */
+	{ 0xDFFF, 0xDFFF, 0x0000, 0, 0x0000 }, /* R67 */
+	{ 0xDFFF, 0xDFFF, 0x0000, 0, 0x0000 }, /* R68 */
+	{ 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R69 */
+	{ 0xFFFF, 0xFFFF, 0x0000, 0, 0x4400 }, /* R70 */
+	{ 0x23FF, 0x23FF, 0x0000, 0, 0x0000 }, /* R71 */
+	{ 0xFFFF, 0xFFFF, 0x0000, 0, 0x4400 }, /* R72 */
+	{ 0x23FF, 0x23FF, 0x0000, 0, 0x0000 }, /* R73 */
+	{ 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R74 */
+	{ 0x000E, 0x000E, 0x0000, 0, 0x0008 }, /* R75 */
+	{ 0xE00F, 0xE00F, 0x0000, 0, 0x0000 }, /* R76 */
+	{ 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R77 */
+	{ 0x03C0, 0x03C0, 0x0000, 0, 0x02C0 }, /* R78 */
+	{ 0xFFFF, 0x0000, 0xffff, 0, 0x0000 }, /* R79 */
+	{ 0xFFFF, 0xFFFF, 0x0000, 0, 0x0000 }, /* R80 */
+	{ 0xFFFF, 0x0000, 0xffff, 0, 0x0000 }, /* R81 */
+	{ 0x2BFF, 0x0000, 0xffff, 0, 0x0000 }, /* R82 */
+	{ 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R83 */
+	{ 0x80FF, 0x80FF, 0x0000, 0, 0x00ff }, /* R84 */
+};
+
+static int wm8400_read(struct wm8400 *wm8400, u8 reg, int num_regs, u16 *dest)
+{
+	int i, ret = 0;
+
+	BUG_ON(reg + num_regs - 1 > ARRAY_SIZE(wm8400->reg_cache));
+
+	/* If there are any volatile reads then read back the entire block */
+	for (i = reg; i < reg + num_regs; i++)
+		if (reg_data[i].vol) {
+			ret = wm8400->read_dev(wm8400->io_data, reg,
+					       num_regs, dest);
+			if (ret != 0)
+				return ret;
+			for (i = 0; i < num_regs; i++)
+				dest[i] = be16_to_cpu(dest[i]);
+
+			return 0;
+		}
+
+	/* Otherwise use the cache */
+	memcpy(dest, &wm8400->reg_cache[reg], num_regs * sizeof(u16));
+
+	return 0;
+}
+
+static int wm8400_write(struct wm8400 *wm8400, u8 reg, int num_regs,
+			u16 *src)
+{
+	int ret, i;
+
+	BUG_ON(reg + num_regs - 1 > ARRAY_SIZE(wm8400->reg_cache));
+
+	for (i = 0; i < num_regs; i++) {
+		BUG_ON(!reg_data[reg + i].writable);
+		wm8400->reg_cache[reg + i] = src[i];
+		src[i] = cpu_to_be16(src[i]);
+	}
+
+	/* Do the actual I/O */
+	ret = wm8400->write_dev(wm8400->io_data, reg, num_regs, src);
+	if (ret != 0)
+		return -EIO;
+
+	return 0;
+}
+
+/**
+ * wm8400_reg_read - Single register read
+ *
+ * @wm8400: Pointer to wm8400 control structure
+ * @reg:    Register to read
+ *
+ * @return  Read value
+ */
+u16 wm8400_reg_read(struct wm8400 *wm8400, u8 reg)
+{
+	u16 val;
+
+	mutex_lock(&wm8400->io_lock);
+
+	wm8400_read(wm8400, reg, 1, &val);
+
+	mutex_unlock(&wm8400->io_lock);
+
+	return val;
+}
+EXPORT_SYMBOL_GPL(wm8400_reg_read);
+
+int wm8400_block_read(struct wm8400 *wm8400, u8 reg, int count, u16 *data)
+{
+	int ret;
+
+	mutex_lock(&wm8400->io_lock);
+
+	ret = wm8400_read(wm8400, reg, count, data);
+
+	mutex_unlock(&wm8400->io_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wm8400_block_read);
+
+/**
+ * wm8400_set_bits - Bitmask write
+ *
+ * @wm8400: Pointer to wm8400 control structure
+ * @reg:    Register to access
+ * @mask:   Mask of bits to change
+ * @val:    Value to set for masked bits
+ */
+int wm8400_set_bits(struct wm8400 *wm8400, u8 reg, u16 mask, u16 val)
+{
+	u16 tmp;
+	int ret;
+
+	mutex_lock(&wm8400->io_lock);
+
+	ret = wm8400_read(wm8400, reg, 1, &tmp);
+	tmp = (tmp & ~mask) | val;
+	if (ret == 0)
+		ret = wm8400_write(wm8400, reg, 1, &tmp);
+
+	mutex_unlock(&wm8400->io_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wm8400_set_bits);
+
+/**
+ * wm8400_reset_codec_reg_cache - Reset cached codec registers to
+ * their default values.
+ */
+void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400)
+{
+	int i;
+
+	mutex_lock(&wm8400->io_lock);
+
+	/* Reset all codec registers to their initial value */
+	for (i = 0; i < ARRAY_SIZE(wm8400->reg_cache); i++)
+		if (reg_data[i].is_codec)
+			wm8400->reg_cache[i] = reg_data[i].default_val;
+
+	mutex_unlock(&wm8400->io_lock);
+}
+EXPORT_SYMBOL_GPL(wm8400_reset_codec_reg_cache);
+
+/*
+ * wm8400_init - Generic initialisation
+ *
+ * The WM8400 can be configured as either an I2C or SPI device.  Probe
+ * functions for each bus set up the accessors then call into this to
+ * set up the device itself.
+ */
+static int wm8400_init(struct wm8400 *wm8400,
+		       struct wm8400_platform_data *pdata)
+{
+	u16 reg;
+	int ret, i;
+
+	mutex_init(&wm8400->io_lock);
+
+	wm8400->dev->driver_data = wm8400;
+
+	/* Check that this is actually a WM8400 */
+	ret = wm8400->read_dev(wm8400->io_data, WM8400_RESET_ID, 1, &reg);
+	if (ret != 0) {
+		dev_err(wm8400->dev, "Chip ID register read failed\n");
+		return -EIO;
+	}
+	if (be16_to_cpu(reg) != reg_data[WM8400_RESET_ID].default_val) {
+		dev_err(wm8400->dev, "Device is not a WM8400, ID is %x\n",
+			be16_to_cpu(reg));
+		return -ENODEV;
+	}
+
+	/* We don't know what state the hardware is in and since this
+	 * is a PMIC we can't reset it safely so initialise the register
+	 * cache from the hardware.
+	 */
+	ret = wm8400->read_dev(wm8400->io_data, 0,
+			       ARRAY_SIZE(wm8400->reg_cache),
+			       wm8400->reg_cache);
+	if (ret != 0) {
+		dev_err(wm8400->dev, "Register cache read failed\n");
+		return -EIO;
+	}
+	for (i = 0; i < ARRAY_SIZE(wm8400->reg_cache); i++)
+		wm8400->reg_cache[i] = be16_to_cpu(wm8400->reg_cache[i]);
+
+	/* If the codec is in reset use hard coded values */
+	if (!(wm8400->reg_cache[WM8400_POWER_MANAGEMENT_1] & WM8400_CODEC_ENA))
+		for (i = 0; i < ARRAY_SIZE(wm8400->reg_cache); i++)
+			if (reg_data[i].is_codec)
+				wm8400->reg_cache[i] = reg_data[i].default_val;
+
+	ret = wm8400_read(wm8400, WM8400_ID, 1, &reg);
+	if (ret != 0) {
+		dev_err(wm8400->dev, "ID register read failed: %d\n", ret);
+		return ret;
+	}
+	reg = (reg & WM8400_CHIP_REV_MASK) >> WM8400_CHIP_REV_SHIFT;
+	dev_info(wm8400->dev, "WM8400 revision %x\n", reg);
+
+	if (pdata && pdata->platform_init) {
+		ret = pdata->platform_init(wm8400->dev);
+		if (ret != 0)
+			dev_err(wm8400->dev, "Platform init failed: %d\n",
+				ret);
+	} else
+		dev_warn(wm8400->dev, "No platform initialisation supplied\n");
+
+	return ret;
+}
+
+static void wm8400_release(struct wm8400 *wm8400)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(wm8400->regulators); i++)
+		if (wm8400->regulators[i].name)
+			platform_device_unregister(&wm8400->regulators[i]);
+}
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static int wm8400_i2c_read(void *io_data, char reg, int count, u16 *dest)
+{
+	struct i2c_client *i2c = io_data;
+	struct i2c_msg xfer[2];
+	int ret;
+
+	/* Write register */
+	xfer[0].addr = i2c->addr;
+	xfer[0].flags = 0;
+	xfer[0].len = 1;
+	xfer[0].buf = &reg;
+
+	/* Read data */
+	xfer[1].addr = i2c->addr;
+	xfer[1].flags = I2C_M_RD;
+	xfer[1].len = count * sizeof(u16);
+	xfer[1].buf = (u8 *)dest;
+
+	ret = i2c_transfer(i2c->adapter, xfer, 2);
+	if (ret == 2)
+		ret = 0;
+	else if (ret >= 0)
+		ret = -EIO;
+
+	return ret;
+}
+
+static int wm8400_i2c_write(void *io_data, char reg, int count, const u16 *src)
+{
+	struct i2c_client *i2c = io_data;
+	u8 *msg;
+	int ret;
+
+	/* We add 1 byte for device register - ideally I2C would gather. */
+	msg = kmalloc((count * sizeof(u16)) + 1, GFP_KERNEL);
+	if (msg == NULL)
+		return -ENOMEM;
+
+	msg[0] = reg;
+	memcpy(&msg[1], src, count * sizeof(u16));
+
+	ret = i2c_master_send(i2c, msg, (count * sizeof(u16)) + 1);
+
+	if (ret == (count * 2) + 1)
+		ret = 0;
+	else if (ret >= 0)
+		ret = -EIO;
+
+	kfree(msg);
+
+	return ret;
+}
+
+static int wm8400_i2c_probe(struct i2c_client *i2c,
+			    const struct i2c_device_id *id)
+{
+	struct wm8400 *wm8400;
+	int ret;
+
+	wm8400 = kzalloc(sizeof(struct wm8400), GFP_KERNEL);
+	if (wm8400 == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	wm8400->io_data = i2c;
+	wm8400->read_dev = wm8400_i2c_read;
+	wm8400->write_dev = wm8400_i2c_write;
+	wm8400->dev = &i2c->dev;
+	i2c_set_clientdata(i2c, wm8400);
+
+	ret = wm8400_init(wm8400, i2c->dev.platform_data);
+	if (ret != 0)
+		goto struct_err;
+
+	return 0;
+
+struct_err:
+	i2c_set_clientdata(i2c, NULL);
+	kfree(wm8400);
+err:
+	return ret;
+}
+
+static int wm8400_i2c_remove(struct i2c_client *i2c)
+{
+	struct wm8400 *wm8400 = i2c_get_clientdata(i2c);
+
+	wm8400_release(wm8400);
+	i2c_set_clientdata(i2c, NULL);
+	kfree(wm8400);
+
+	return 0;
+}
+
+static const struct i2c_device_id wm8400_i2c_id[] = {
+       { "wm8400", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8400_i2c_id);
+
+static struct i2c_driver wm8400_i2c_driver = {
+	.driver = {
+		.name = "WM8400",
+		.owner = THIS_MODULE,
+	},
+	.probe    = wm8400_i2c_probe,
+	.remove   = wm8400_i2c_remove,
+	.id_table = wm8400_i2c_id,
+};
+#endif
+
+static int __init wm8400_module_init(void)
+{
+	int ret = -ENODEV;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	ret = i2c_add_driver(&wm8400_i2c_driver);
+	if (ret != 0)
+		pr_err("Failed to register I2C driver: %d\n", ret);
+#endif
+
+	return ret;
+}
+module_init(wm8400_module_init);
+
+static void __exit wm8400_module_exit(void)
+{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	i2c_del_driver(&wm8400_i2c_driver);
+#endif
+}
+module_exit(wm8400_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index a656128f1fdd..4dada6ee1119 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -56,4 +56,28 @@ config REGULATOR_BQ24022
 	  charging select between 100 mA and 500 mA charging current
 	  limit.
 
+config REGULATOR_WM8350
+	tristate "Wolfson Microelectroncis WM8350 AudioPlus PMIC"
+	depends on MFD_WM8350
+	select REGULATOR
+	help
+	  This driver provides support for the voltage and current regulators
+          of the WM8350 AudioPlus PMIC.
+
+config REGULATOR_WM8400
+	tristate "Wolfson Microelectroncis WM8400 AudioPlus PMIC"
+	depends on MFD_WM8400
+	select REGULATOR
+	help
+	  This driver provides support for the voltage regulators of the
+	  WM8400 AudioPlus PMIC.
+
+config REGULATOR_DA903X
+	tristate "Support regulators on Dialog Semiconductor DA9030/DA9034 PMIC"
+	depends on PMIC_DA903X
+	select REGULATOR
+	help
+	  Say y here to support the BUCKs and LDOs regulators found on
+	  Dialog Semiconductor DA9030/DA9034 PMIC.
+
 endmenu
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index ac2c64efe65c..254d40c02ee8 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -8,5 +8,8 @@ obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
 obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
 
 obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o
+obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
+obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
+obj-$(CONFIG_REGULATOR_DA903X)	+= da903x.o
 
 ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/bq24022.c b/drivers/regulator/bq24022.c
index 263699d6152d..366565aba865 100644
--- a/drivers/regulator/bq24022.c
+++ b/drivers/regulator/bq24022.c
@@ -18,13 +18,13 @@
 #include <linux/regulator/bq24022.h>
 #include <linux/regulator/driver.h>
 
+
 static int bq24022_set_current_limit(struct regulator_dev *rdev,
 					int min_uA, int max_uA)
 {
-	struct platform_device *pdev = rdev_get_drvdata(rdev);
-	struct bq24022_mach_info *pdata = pdev->dev.platform_data;
+	struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
 
-	dev_dbg(&pdev->dev, "setting current limit to %s mA\n",
+	dev_dbg(rdev_get_dev(rdev), "setting current limit to %s mA\n",
 		max_uA >= 500000 ? "500" : "100");
 
 	/* REVISIT: maybe return error if min_uA != 0 ? */
@@ -34,18 +34,16 @@ static int bq24022_set_current_limit(struct regulator_dev *rdev,
 
 static int bq24022_get_current_limit(struct regulator_dev *rdev)
 {
-	struct platform_device *pdev = rdev_get_drvdata(rdev);
-	struct bq24022_mach_info *pdata = pdev->dev.platform_data;
+	struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
 
 	return gpio_get_value(pdata->gpio_iset2) ? 500000 : 100000;
 }
 
 static int bq24022_enable(struct regulator_dev *rdev)
 {
-	struct platform_device *pdev = rdev_get_drvdata(rdev);
-	struct bq24022_mach_info *pdata = pdev->dev.platform_data;
+	struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
 
-	dev_dbg(&pdev->dev, "enabling charger\n");
+	dev_dbg(rdev_get_dev(rdev), "enabling charger\n");
 
 	gpio_set_value(pdata->gpio_nce, 0);
 	return 0;
@@ -53,10 +51,9 @@ static int bq24022_enable(struct regulator_dev *rdev)
 
 static int bq24022_disable(struct regulator_dev *rdev)
 {
-	struct platform_device *pdev = rdev_get_drvdata(rdev);
-	struct bq24022_mach_info *pdata = pdev->dev.platform_data;
+	struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
 
-	dev_dbg(&pdev->dev, "disabling charger\n");
+	dev_dbg(rdev_get_dev(rdev), "disabling charger\n");
 
 	gpio_set_value(pdata->gpio_nce, 1);
 	return 0;
@@ -108,7 +105,7 @@ static int __init bq24022_probe(struct platform_device *pdev)
 	ret = gpio_direction_output(pdata->gpio_iset2, 0);
 	ret = gpio_direction_output(pdata->gpio_nce, 1);
 
-	bq24022 = regulator_register(&bq24022_desc, pdev);
+	bq24022 = regulator_register(&bq24022_desc, &pdev->dev, pdata);
 	if (IS_ERR(bq24022)) {
 		dev_dbg(&pdev->dev, "couldn't register regulator\n");
 		ret = PTR_ERR(bq24022);
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 9c7986261568..02a774424e8d 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2,8 +2,9 @@
  * core.c  --  Voltage/Current Regulator framework.
  *
  * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ * Copyright 2008 SlimLogic Ltd.
  *
- * Author: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  *
  *  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
@@ -64,14 +65,9 @@ struct regulator_map {
 	struct list_head list;
 	struct device *dev;
 	const char *supply;
-	const char *regulator;
+	struct regulator_dev *regulator;
 };
 
-static inline struct regulator_dev *to_rdev(struct device *d)
-{
-	return container_of(d, struct regulator_dev, dev);
-}
-
 /*
  * struct regulator
  *
@@ -227,7 +223,7 @@ static ssize_t device_requested_uA_show(struct device *dev,
 static ssize_t regulator_uV_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 	ssize_t ret;
 
 	mutex_lock(&rdev->mutex);
@@ -240,15 +236,31 @@ static ssize_t regulator_uV_show(struct device *dev,
 static ssize_t regulator_uA_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev));
 }
 
+static ssize_t regulator_name_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
+	const char *name;
+
+	if (rdev->constraints->name)
+		name = rdev->constraints->name;
+	else if (rdev->desc->name)
+		name = rdev->desc->name;
+	else
+		name = "";
+
+	return sprintf(buf, "%s\n", name);
+}
+
 static ssize_t regulator_opmode_show(struct device *dev,
 				    struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 	int mode = _regulator_get_mode(rdev);
 
 	switch (mode) {
@@ -267,7 +279,7 @@ static ssize_t regulator_opmode_show(struct device *dev,
 static ssize_t regulator_state_show(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 	int state = _regulator_is_enabled(rdev);
 
 	if (state > 0)
@@ -281,7 +293,7 @@ static ssize_t regulator_state_show(struct device *dev,
 static ssize_t regulator_min_uA_show(struct device *dev,
 				    struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 
 	if (!rdev->constraints)
 		return sprintf(buf, "constraint not defined\n");
@@ -292,7 +304,7 @@ static ssize_t regulator_min_uA_show(struct device *dev,
 static ssize_t regulator_max_uA_show(struct device *dev,
 				    struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 
 	if (!rdev->constraints)
 		return sprintf(buf, "constraint not defined\n");
@@ -303,7 +315,7 @@ static ssize_t regulator_max_uA_show(struct device *dev,
 static ssize_t regulator_min_uV_show(struct device *dev,
 				    struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 
 	if (!rdev->constraints)
 		return sprintf(buf, "constraint not defined\n");
@@ -314,7 +326,7 @@ static ssize_t regulator_min_uV_show(struct device *dev,
 static ssize_t regulator_max_uV_show(struct device *dev,
 				    struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 
 	if (!rdev->constraints)
 		return sprintf(buf, "constraint not defined\n");
@@ -325,7 +337,7 @@ static ssize_t regulator_max_uV_show(struct device *dev,
 static ssize_t regulator_total_uA_show(struct device *dev,
 				      struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 	struct regulator *regulator;
 	int uA = 0;
 
@@ -339,14 +351,14 @@ static ssize_t regulator_total_uA_show(struct device *dev,
 static ssize_t regulator_num_users_show(struct device *dev,
 				      struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 	return sprintf(buf, "%d\n", rdev->use_count);
 }
 
 static ssize_t regulator_type_show(struct device *dev,
 				  struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 
 	switch (rdev->desc->type) {
 	case REGULATOR_VOLTAGE:
@@ -360,7 +372,7 @@ static ssize_t regulator_type_show(struct device *dev,
 static ssize_t regulator_suspend_mem_uV_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 
 	if (!rdev->constraints)
 		return sprintf(buf, "not defined\n");
@@ -370,7 +382,7 @@ static ssize_t regulator_suspend_mem_uV_show(struct device *dev,
 static ssize_t regulator_suspend_disk_uV_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 
 	if (!rdev->constraints)
 		return sprintf(buf, "not defined\n");
@@ -380,7 +392,7 @@ static ssize_t regulator_suspend_disk_uV_show(struct device *dev,
 static ssize_t regulator_suspend_standby_uV_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 
 	if (!rdev->constraints)
 		return sprintf(buf, "not defined\n");
@@ -406,7 +418,7 @@ static ssize_t suspend_opmode_show(struct regulator_dev *rdev,
 static ssize_t regulator_suspend_mem_mode_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 
 	if (!rdev->constraints)
 		return sprintf(buf, "not defined\n");
@@ -417,7 +429,7 @@ static ssize_t regulator_suspend_mem_mode_show(struct device *dev,
 static ssize_t regulator_suspend_disk_mode_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 
 	if (!rdev->constraints)
 		return sprintf(buf, "not defined\n");
@@ -428,7 +440,7 @@ static ssize_t regulator_suspend_disk_mode_show(struct device *dev,
 static ssize_t regulator_suspend_standby_mode_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 
 	if (!rdev->constraints)
 		return sprintf(buf, "not defined\n");
@@ -439,7 +451,7 @@ static ssize_t regulator_suspend_standby_mode_show(struct device *dev,
 static ssize_t regulator_suspend_mem_state_show(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 
 	if (!rdev->constraints)
 		return sprintf(buf, "not defined\n");
@@ -453,7 +465,7 @@ static ssize_t regulator_suspend_mem_state_show(struct device *dev,
 static ssize_t regulator_suspend_disk_state_show(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 
 	if (!rdev->constraints)
 		return sprintf(buf, "not defined\n");
@@ -467,7 +479,7 @@ static ssize_t regulator_suspend_disk_state_show(struct device *dev,
 static ssize_t regulator_suspend_standby_state_show(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 
 	if (!rdev->constraints)
 		return sprintf(buf, "not defined\n");
@@ -477,7 +489,9 @@ static ssize_t regulator_suspend_standby_state_show(struct device *dev,
 	else
 		return sprintf(buf, "disabled\n");
 }
+
 static struct device_attribute regulator_dev_attrs[] = {
+	__ATTR(name, 0444, regulator_name_show, NULL),
 	__ATTR(microvolts, 0444, regulator_uV_show, NULL),
 	__ATTR(microamps, 0444, regulator_uA_show, NULL),
 	__ATTR(opmode, 0444, regulator_opmode_show, NULL),
@@ -512,7 +526,7 @@ static struct device_attribute regulator_dev_attrs[] = {
 
 static void regulator_dev_release(struct device *dev)
 {
-	struct regulator_dev *rdev = to_rdev(dev);
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
 	kfree(rdev);
 }
 
@@ -569,8 +583,11 @@ static int suspend_set_state(struct regulator_dev *rdev,
 
 	/* enable & disable are mandatory for suspend control */
 	if (!rdev->desc->ops->set_suspend_enable ||
-		!rdev->desc->ops->set_suspend_disable)
+		!rdev->desc->ops->set_suspend_disable) {
+		printk(KERN_ERR "%s: no way to set suspend state\n",
+			__func__);
 		return -EINVAL;
+	}
 
 	if (rstate->enabled)
 		ret = rdev->desc->ops->set_suspend_enable(rdev);
@@ -656,6 +673,155 @@ static void print_constraints(struct regulator_dev *rdev)
 	printk(KERN_INFO "regulator: %s: %s\n", rdev->desc->name, buf);
 }
 
+/**
+ * set_machine_constraints - sets regulator constraints
+ * @regulator: regulator source
+ *
+ * Allows platform initialisation code to define and constrain
+ * regulator circuits e.g. valid voltage/current ranges, etc.  NOTE:
+ * Constraints *must* be set by platform code in order for some
+ * regulator operations to proceed i.e. set_voltage, set_current_limit,
+ * set_mode.
+ */
+static int set_machine_constraints(struct regulator_dev *rdev,
+	struct regulation_constraints *constraints)
+{
+	int ret = 0;
+	const char *name;
+	struct regulator_ops *ops = rdev->desc->ops;
+
+	if (constraints->name)
+		name = constraints->name;
+	else if (rdev->desc->name)
+		name = rdev->desc->name;
+	else
+		name = "regulator";
+
+	rdev->constraints = constraints;
+
+	/* do we need to apply the constraint voltage */
+	if (rdev->constraints->apply_uV &&
+		rdev->constraints->min_uV == rdev->constraints->max_uV &&
+		ops->set_voltage) {
+		ret = ops->set_voltage(rdev,
+			rdev->constraints->min_uV, rdev->constraints->max_uV);
+			if (ret < 0) {
+				printk(KERN_ERR "%s: failed to apply %duV constraint to %s\n",
+				       __func__,
+				       rdev->constraints->min_uV, name);
+				rdev->constraints = NULL;
+				goto out;
+			}
+	}
+
+	/* are we enabled at boot time by firmware / bootloader */
+	if (rdev->constraints->boot_on)
+		rdev->use_count = 1;
+
+	/* do we need to setup our suspend state */
+	if (constraints->initial_state) {
+		ret = suspend_prepare(rdev, constraints->initial_state);
+		if (ret < 0) {
+			printk(KERN_ERR "%s: failed to set suspend state for %s\n",
+			       __func__, name);
+			rdev->constraints = NULL;
+			goto out;
+		}
+	}
+
+	/* if always_on is set then turn the regulator on if it's not
+	 * already on. */
+	if (constraints->always_on && ops->enable &&
+	    ((ops->is_enabled && !ops->is_enabled(rdev)) ||
+	     (!ops->is_enabled && !constraints->boot_on))) {
+		ret = ops->enable(rdev);
+		if (ret < 0) {
+			printk(KERN_ERR "%s: failed to enable %s\n",
+			       __func__, name);
+			rdev->constraints = NULL;
+			goto out;
+		}
+	}
+
+	print_constraints(rdev);
+out:
+	return ret;
+}
+
+/**
+ * set_supply - set regulator supply regulator
+ * @regulator: regulator name
+ * @supply: supply regulator name
+ *
+ * Called by platform initialisation code to set the supply regulator for this
+ * regulator. This ensures that a regulators supply will also be enabled by the
+ * core if it's child is enabled.
+ */
+static int set_supply(struct regulator_dev *rdev,
+	struct regulator_dev *supply_rdev)
+{
+	int err;
+
+	err = sysfs_create_link(&rdev->dev.kobj, &supply_rdev->dev.kobj,
+				"supply");
+	if (err) {
+		printk(KERN_ERR
+		       "%s: could not add device link %s err %d\n",
+		       __func__, supply_rdev->dev.kobj.name, err);
+		       goto out;
+	}
+	rdev->supply = supply_rdev;
+	list_add(&rdev->slist, &supply_rdev->supply_list);
+out:
+	return err;
+}
+
+/**
+ * set_consumer_device_supply: Bind a regulator to a symbolic supply
+ * @regulator: regulator source
+ * @dev:       device the supply applies to
+ * @supply:    symbolic name for supply
+ *
+ * Allows platform initialisation code to map physical regulator
+ * sources to symbolic names for supplies for use by devices.  Devices
+ * should use these symbolic names to request regulators, avoiding the
+ * need to provide board-specific regulator names as platform data.
+ */
+static int set_consumer_device_supply(struct regulator_dev *rdev,
+	struct device *consumer_dev, const char *supply)
+{
+	struct regulator_map *node;
+
+	if (supply == NULL)
+		return -EINVAL;
+
+	node = kmalloc(sizeof(struct regulator_map), GFP_KERNEL);
+	if (node == NULL)
+		return -ENOMEM;
+
+	node->regulator = rdev;
+	node->dev = consumer_dev;
+	node->supply = supply;
+
+	list_add(&node->list, &regulator_map_list);
+	return 0;
+}
+
+static void unset_consumer_device_supply(struct regulator_dev *rdev,
+	struct device *consumer_dev)
+{
+	struct regulator_map *node, *n;
+
+	list_for_each_entry_safe(node, n, &regulator_map_list, list) {
+		if (rdev == node->regulator &&
+			consumer_dev == node->dev) {
+			list_del(&node->list);
+			kfree(node);
+			return;
+		}
+	}
+}
+
 #define REG_STR_SIZE	32
 
 static struct regulator *create_regulator(struct regulator_dev *rdev,
@@ -746,7 +912,6 @@ struct regulator *regulator_get(struct device *dev, const char *id)
 	struct regulator_dev *rdev;
 	struct regulator_map *map;
 	struct regulator *regulator = ERR_PTR(-ENODEV);
-	const char *supply = id;
 
 	if (id == NULL) {
 		printk(KERN_ERR "regulator: get() with no identifier\n");
@@ -758,15 +923,9 @@ struct regulator *regulator_get(struct device *dev, const char *id)
 	list_for_each_entry(map, &regulator_map_list, list) {
 		if (dev == map->dev &&
 		    strcmp(map->supply, id) == 0) {
-			supply = map->regulator;
-			break;
-		}
-	}
-
-	list_for_each_entry(rdev, &regulator_list, list) {
-		if (strcmp(supply, rdev->desc->name) == 0 &&
-		    try_module_get(rdev->owner))
+			rdev = map->regulator;
 			goto found;
+		}
 	}
 	printk(KERN_ERR "regulator: Unable to get requested regulator: %s\n",
 	       id);
@@ -774,12 +933,16 @@ struct regulator *regulator_get(struct device *dev, const char *id)
 	return regulator;
 
 found:
+	if (!try_module_get(rdev->owner))
+		goto out;
+
 	regulator = create_regulator(rdev, dev, id);
 	if (regulator == NULL) {
 		regulator = ERR_PTR(-ENOMEM);
 		module_put(rdev->owner);
 	}
 
+out:
 	mutex_unlock(&regulator_list_mutex);
 	return regulator;
 }
@@ -1559,11 +1722,12 @@ EXPORT_SYMBOL_GPL(regulator_notifier_call_chain);
  * Returns 0 on success.
  */
 struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
-					  void *reg_data)
+	struct device *dev, void *driver_data)
 {
 	static atomic_t regulator_no = ATOMIC_INIT(0);
 	struct regulator_dev *rdev;
-	int ret;
+	struct regulator_init_data *init_data = dev->platform_data;
+	int ret, i;
 
 	if (regulator_desc == NULL)
 		return ERR_PTR(-EINVAL);
@@ -1575,6 +1739,9 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
 	    !regulator_desc->type == REGULATOR_CURRENT)
 		return ERR_PTR(-EINVAL);
 
+	if (!init_data)
+		return ERR_PTR(-EINVAL);
+
 	rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
 	if (rdev == NULL)
 		return ERR_PTR(-ENOMEM);
@@ -1582,7 +1749,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
 	mutex_lock(&regulator_list_mutex);
 
 	mutex_init(&rdev->mutex);
-	rdev->reg_data = reg_data;
+	rdev->reg_data = driver_data;
 	rdev->owner = regulator_desc->owner;
 	rdev->desc = regulator_desc;
 	INIT_LIST_HEAD(&rdev->consumer_list);
@@ -1591,20 +1758,68 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
 	INIT_LIST_HEAD(&rdev->slist);
 	BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
 
+	/* preform any regulator specific init */
+	if (init_data->regulator_init) {
+		ret = init_data->regulator_init(rdev->reg_data);
+		if (ret < 0) {
+			kfree(rdev);
+			rdev = ERR_PTR(ret);
+			goto out;
+		}
+	}
+
+	/* set regulator constraints */
+	ret = set_machine_constraints(rdev, &init_data->constraints);
+	if (ret < 0) {
+		kfree(rdev);
+		rdev = ERR_PTR(ret);
+		goto out;
+	}
+
+	/* register with sysfs */
 	rdev->dev.class = &regulator_class;
-	device_initialize(&rdev->dev);
+	rdev->dev.parent = dev;
 	snprintf(rdev->dev.bus_id, sizeof(rdev->dev.bus_id),
-		 "regulator_%ld_%s",
-		 (unsigned long)atomic_inc_return(&regulator_no) - 1,
-		 regulator_desc->name);
-
-	ret = device_add(&rdev->dev);
-	if (ret == 0)
-		list_add(&rdev->list, &regulator_list);
-	else {
+		 "regulator.%d", atomic_inc_return(&regulator_no) - 1);
+	ret = device_register(&rdev->dev);
+	if (ret != 0) {
 		kfree(rdev);
 		rdev = ERR_PTR(ret);
+		goto out;
+	}
+
+	dev_set_drvdata(&rdev->dev, rdev);
+
+	/* set supply regulator if it exists */
+	if (init_data->supply_regulator_dev) {
+		ret = set_supply(rdev,
+			dev_get_drvdata(init_data->supply_regulator_dev));
+		if (ret < 0) {
+			device_unregister(&rdev->dev);
+			kfree(rdev);
+			rdev = ERR_PTR(ret);
+			goto out;
+		}
 	}
+
+	/* add consumers devices */
+	for (i = 0; i < init_data->num_consumer_supplies; i++) {
+		ret = set_consumer_device_supply(rdev,
+			init_data->consumer_supplies[i].dev,
+			init_data->consumer_supplies[i].supply);
+		if (ret < 0) {
+			for (--i; i >= 0; i--)
+				unset_consumer_device_supply(rdev,
+					init_data->consumer_supplies[i].dev);
+			device_unregister(&rdev->dev);
+			kfree(rdev);
+			rdev = ERR_PTR(ret);
+			goto out;
+		}
+	}
+
+	list_add(&rdev->list, &regulator_list);
+out:
 	mutex_unlock(&regulator_list_mutex);
 	return rdev;
 }
@@ -1631,187 +1846,6 @@ void regulator_unregister(struct regulator_dev *rdev)
 EXPORT_SYMBOL_GPL(regulator_unregister);
 
 /**
- * regulator_set_supply - set regulator supply regulator
- * @regulator: regulator name
- * @supply: supply regulator name
- *
- * Called by platform initialisation code to set the supply regulator for this
- * regulator. This ensures that a regulators supply will also be enabled by the
- * core if it's child is enabled.
- */
-int regulator_set_supply(const char *regulator, const char *supply)
-{
-	struct regulator_dev *rdev, *supply_rdev;
-	int err;
-
-	if (regulator == NULL || supply == NULL)
-		return -EINVAL;
-
-	mutex_lock(&regulator_list_mutex);
-
-	list_for_each_entry(rdev, &regulator_list, list) {
-		if (!strcmp(rdev->desc->name, regulator))
-			goto found_regulator;
-	}
-	mutex_unlock(&regulator_list_mutex);
-	return -ENODEV;
-
-found_regulator:
-	list_for_each_entry(supply_rdev, &regulator_list, list) {
-		if (!strcmp(supply_rdev->desc->name, supply))
-			goto found_supply;
-	}
-	mutex_unlock(&regulator_list_mutex);
-	return -ENODEV;
-
-found_supply:
-	err = sysfs_create_link(&rdev->dev.kobj, &supply_rdev->dev.kobj,
-				"supply");
-	if (err) {
-		printk(KERN_ERR
-		       "%s: could not add device link %s err %d\n",
-		       __func__, supply_rdev->dev.kobj.name, err);
-		       goto out;
-	}
-	rdev->supply = supply_rdev;
-	list_add(&rdev->slist, &supply_rdev->supply_list);
-out:
-	mutex_unlock(&regulator_list_mutex);
-	return err;
-}
-EXPORT_SYMBOL_GPL(regulator_set_supply);
-
-/**
- * regulator_get_supply - get regulator supply regulator
- * @regulator: regulator name
- *
- * Returns the supply supply regulator name or NULL if no supply regulator
- * exists (i.e the regulator is supplied directly from USB, Line, Battery, etc)
- */
-const char *regulator_get_supply(const char *regulator)
-{
-	struct regulator_dev *rdev;
-
-	if (regulator == NULL)
-		return NULL;
-
-	mutex_lock(&regulator_list_mutex);
-	list_for_each_entry(rdev, &regulator_list, list) {
-		if (!strcmp(rdev->desc->name, regulator))
-			goto found;
-	}
-	mutex_unlock(&regulator_list_mutex);
-	return NULL;
-
-found:
-	mutex_unlock(&regulator_list_mutex);
-	if (rdev->supply)
-		return rdev->supply->desc->name;
-	else
-		return NULL;
-}
-EXPORT_SYMBOL_GPL(regulator_get_supply);
-
-/**
- * regulator_set_machine_constraints - sets regulator constraints
- * @regulator: regulator source
- *
- * Allows platform initialisation code to define and constrain
- * regulator circuits e.g. valid voltage/current ranges, etc.  NOTE:
- * Constraints *must* be set by platform code in order for some
- * regulator operations to proceed i.e. set_voltage, set_current_limit,
- * set_mode.
- */
-int regulator_set_machine_constraints(const char *regulator_name,
-	struct regulation_constraints *constraints)
-{
-	struct regulator_dev *rdev;
-	int ret = 0;
-
-	if (regulator_name == NULL)
-		return -EINVAL;
-
-	mutex_lock(&regulator_list_mutex);
-
-	list_for_each_entry(rdev, &regulator_list, list) {
-		if (!strcmp(regulator_name, rdev->desc->name))
-			goto found;
-	}
-	ret = -ENODEV;
-	goto out;
-
-found:
-	mutex_lock(&rdev->mutex);
-	rdev->constraints = constraints;
-
-	/* do we need to apply the constraint voltage */
-	if (rdev->constraints->apply_uV &&
-		rdev->constraints->min_uV == rdev->constraints->max_uV &&
-		rdev->desc->ops->set_voltage) {
-		ret = rdev->desc->ops->set_voltage(rdev,
-			rdev->constraints->min_uV, rdev->constraints->max_uV);
-			if (ret < 0) {
-				printk(KERN_ERR "%s: failed to apply %duV"
-					" constraint\n", __func__,
-					rdev->constraints->min_uV);
-				rdev->constraints = NULL;
-				goto out;
-			}
-	}
-
-	/* are we enabled at boot time by firmware / bootloader */
-	if (rdev->constraints->boot_on)
-		rdev->use_count = 1;
-
-	/* do we need to setup our suspend state */
-	if (constraints->initial_state)
-		ret = suspend_prepare(rdev, constraints->initial_state);
-
-	print_constraints(rdev);
-	mutex_unlock(&rdev->mutex);
-
-out:
-	mutex_unlock(&regulator_list_mutex);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(regulator_set_machine_constraints);
-
-
-/**
- * regulator_set_device_supply: Bind a regulator to a symbolic supply
- * @regulator: regulator source
- * @dev:       device the supply applies to
- * @supply:    symbolic name for supply
- *
- * Allows platform initialisation code to map physical regulator
- * sources to symbolic names for supplies for use by devices.  Devices
- * should use these symbolic names to request regulators, avoiding the
- * need to provide board-specific regulator names as platform data.
- */
-int regulator_set_device_supply(const char *regulator, struct device *dev,
-				const char *supply)
-{
-	struct regulator_map *node;
-
-	if (regulator == NULL || supply == NULL)
-		return -EINVAL;
-
-	node = kmalloc(sizeof(struct regulator_map), GFP_KERNEL);
-	if (node == NULL)
-		return -ENOMEM;
-
-	node->regulator = regulator;
-	node->dev = dev;
-	node->supply = supply;
-
-	mutex_lock(&regulator_list_mutex);
-	list_add(&node->list, &regulator_map_list);
-	mutex_unlock(&regulator_list_mutex);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(regulator_set_device_supply);
-
-/**
  * regulator_suspend_prepare: prepare regulators for system wide suspend
  * @state: system suspend state
  *
@@ -1893,6 +1927,18 @@ int rdev_get_id(struct regulator_dev *rdev)
 }
 EXPORT_SYMBOL_GPL(rdev_get_id);
 
+struct device *rdev_get_dev(struct regulator_dev *rdev)
+{
+	return &rdev->dev;
+}
+EXPORT_SYMBOL_GPL(rdev_get_dev);
+
+void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data)
+{
+	return reg_init_data->driver_data;
+}
+EXPORT_SYMBOL_GPL(regulator_get_init_drvdata);
+
 static int __init regulator_init(void)
 {
 	printk(KERN_INFO "regulator: core version %s\n", REGULATOR_VERSION);
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c
new file mode 100644
index 000000000000..3688e339db87
--- /dev/null
+++ b/drivers/regulator/da903x.c
@@ -0,0 +1,513 @@
+/*
+ * Regulators driver for Dialog Semiconductor DA903x
+ *
+ * Copyright (C) 2006-2008 Marvell International Ltd.
+ * Copyright (C) 2008 Compulab 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/da903x.h>
+
+/* DA9030 Registers */
+#define DA9030_INVAL		(-1)
+#define DA9030_LDO1011		(0x10)
+#define DA9030_LDO15		(0x11)
+#define DA9030_LDO1416		(0x12)
+#define DA9030_LDO1819		(0x13)
+#define DA9030_LDO17		(0x14)
+#define DA9030_BUCK2DVM1	(0x15)
+#define DA9030_BUCK2DVM2	(0x16)
+#define DA9030_RCTL11		(0x17)
+#define DA9030_RCTL21		(0x18)
+#define DA9030_LDO1		(0x90)
+#define DA9030_LDO23		(0x91)
+#define DA9030_LDO45		(0x92)
+#define DA9030_LDO6		(0x93)
+#define DA9030_LDO78		(0x94)
+#define DA9030_LDO912		(0x95)
+#define DA9030_BUCK		(0x96)
+#define DA9030_RCTL12		(0x97)
+#define DA9030_RCTL22		(0x98)
+#define DA9030_LDO_UNLOCK	(0xa0)
+#define DA9030_LDO_UNLOCK_MASK	(0xe0)
+#define DA9034_OVER1		(0x10)
+
+/* DA9034 Registers */
+#define DA9034_INVAL		(-1)
+#define DA9034_OVER2		(0x11)
+#define DA9034_OVER3		(0x12)
+#define DA9034_LDO643		(0x13)
+#define DA9034_LDO987		(0x14)
+#define DA9034_LDO1110		(0x15)
+#define DA9034_LDO1312		(0x16)
+#define DA9034_LDO1514		(0x17)
+#define DA9034_VCC1		(0x20)
+#define DA9034_ADTV1		(0x23)
+#define DA9034_ADTV2		(0x24)
+#define DA9034_AVRC		(0x25)
+#define DA9034_CDTV1		(0x26)
+#define DA9034_CDTV2		(0x27)
+#define DA9034_CVRC		(0x28)
+#define DA9034_SDTV1		(0x29)
+#define DA9034_SDTV2		(0x2a)
+#define DA9034_SVRC		(0x2b)
+#define DA9034_MDTV1		(0x32)
+#define DA9034_MDTV2		(0x33)
+#define DA9034_MVRC		(0x34)
+
+struct da903x_regulator_info {
+	struct regulator_desc desc;
+
+	int	min_uV;
+	int	max_uV;
+	int	step_uV;
+	int	vol_reg;
+	int	vol_shift;
+	int	vol_nbits;
+	int	update_reg;
+	int	update_bit;
+	int	enable_reg;
+	int	enable_bit;
+};
+
+static inline int check_range(struct da903x_regulator_info *info,
+				int min_uV, int max_uV)
+{
+	if (min_uV < info->min_uV || min_uV > info->max_uV)
+		return -EINVAL;
+
+	return 0;
+}
+
+/* DA9030/DA9034 common operations */
+static int da903x_set_ldo_voltage(struct regulator_dev *rdev,
+				  int min_uV, int max_uV)
+{
+	struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+	struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+	uint8_t val, mask;
+
+	if (check_range(info, min_uV, max_uV)) {
+		pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+		return -EINVAL;
+	}
+
+	val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
+	val <<= info->vol_shift;
+	mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+
+	return da903x_update(da9034_dev, info->vol_reg, val, mask);
+}
+
+static int da903x_get_voltage(struct regulator_dev *rdev)
+{
+	struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+	struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+	uint8_t val, mask;
+	int ret;
+
+	ret = da903x_read(da9034_dev, info->vol_reg, &val);
+	if (ret)
+		return ret;
+
+	mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+	val = (val & mask) >> info->vol_shift;
+
+	return info->min_uV + info->step_uV * val;
+}
+
+static int da903x_enable(struct regulator_dev *rdev)
+{
+	struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+	struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+
+	return da903x_set_bits(da9034_dev, info->enable_reg,
+					1 << info->enable_bit);
+}
+
+static int da903x_disable(struct regulator_dev *rdev)
+{
+	struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+	struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+
+	return da903x_clr_bits(da9034_dev, info->enable_reg,
+					1 << info->enable_bit);
+}
+
+static int da903x_is_enabled(struct regulator_dev *rdev)
+{
+	struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+	struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+	uint8_t reg_val;
+	int ret;
+
+	ret = da903x_read(da9034_dev, info->enable_reg, &reg_val);
+	if (ret)
+		return ret;
+
+	return reg_val & (1 << info->enable_bit);
+}
+
+/* DA9030 specific operations */
+static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev,
+				       int min_uV, int max_uV)
+{
+	struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+	struct device *da903x_dev = rdev_get_dev(rdev)->parent;
+	uint8_t val, mask;
+	int ret;
+
+	if (check_range(info, min_uV, max_uV)) {
+		pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+		return -EINVAL;
+	}
+
+	val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
+	val <<= info->vol_shift;
+	mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+	val |= DA9030_LDO_UNLOCK; /* have to set UNLOCK bits */
+	mask |= DA9030_LDO_UNLOCK_MASK;
+
+	/* write twice */
+	ret = da903x_update(da903x_dev, info->vol_reg, val, mask);
+	if (ret)
+		return ret;
+
+	return da903x_update(da903x_dev, info->vol_reg, val, mask);
+}
+
+static int da9030_set_ldo14_voltage(struct regulator_dev *rdev,
+				  int min_uV, int max_uV)
+{
+	struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+	struct device *da903x_dev = rdev_get_dev(rdev)->parent;
+	uint8_t val, mask;
+	int thresh;
+
+	if (check_range(info, min_uV, max_uV)) {
+		pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+		return -EINVAL;
+	}
+
+	thresh = (info->max_uV + info->min_uV) / 2;
+	if (min_uV < thresh) {
+		val = (thresh - min_uV + info->step_uV - 1) / info->step_uV;
+		val |= 0x4;
+	} else {
+		val = (min_uV - thresh + info->step_uV - 1) / info->step_uV;
+	}
+
+	val <<= info->vol_shift;
+	mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+
+	return da903x_update(da903x_dev, info->vol_reg, val, mask);
+}
+
+static int da9030_get_ldo14_voltage(struct regulator_dev *rdev)
+{
+	struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+	struct device *da903x_dev = rdev_get_dev(rdev)->parent;
+	uint8_t val, mask;
+	int ret;
+
+	ret = da903x_read(da903x_dev, info->vol_reg, &val);
+	if (ret)
+		return ret;
+
+	mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+	val = (val & mask) >> info->vol_shift;
+
+	if (val & 0x4)
+		return info->min_uV + info->step_uV * (3 - (val & ~0x4));
+	else
+		return (info->max_uV + info->min_uV) / 2 +
+			info->step_uV * (val & ~0x4);
+}
+
+/* DA9034 specific operations */
+static int da9034_set_dvc_voltage(struct regulator_dev *rdev,
+				  int min_uV, int max_uV)
+{
+	struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+	struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+	uint8_t val, mask;
+	int ret;
+
+	if (check_range(info, min_uV, max_uV)) {
+		pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+		return -EINVAL;
+	}
+
+	val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
+	val <<= info->vol_shift;
+	mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+
+	ret = da903x_update(da9034_dev, info->vol_reg, val, mask);
+	if (ret)
+		return ret;
+
+	ret = da903x_set_bits(da9034_dev, info->update_reg,
+					1 << info->update_bit);
+	return ret;
+}
+
+static int da9034_set_ldo12_voltage(struct regulator_dev *rdev,
+				    int min_uV, int max_uV)
+{
+	struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+	struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+	uint8_t val, mask;
+
+	if (check_range(info, min_uV, max_uV)) {
+		pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+		return -EINVAL;
+	}
+
+	val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
+	val = (val > 7 || val < 20) ? 8 : val - 12;
+	val <<= info->vol_shift;
+	mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+
+	return da903x_update(da9034_dev, info->vol_reg, val, mask);
+}
+
+static int da9034_get_ldo12_voltage(struct regulator_dev *rdev)
+{
+	struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+	struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+	uint8_t val, mask;
+	int ret;
+
+	ret = da903x_read(da9034_dev, info->vol_reg, &val);
+	if (ret)
+		return ret;
+
+	mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+	val = (val & mask) >> info->vol_shift;
+
+	if (val >= 8)
+		return 2700000 + info->step_uV * (val - 8);
+
+	return info->min_uV + info->step_uV * val;
+}
+
+static struct regulator_ops da903x_regulator_ldo_ops = {
+	.set_voltage	= da903x_set_ldo_voltage,
+	.get_voltage	= da903x_get_voltage,
+	.enable		= da903x_enable,
+	.disable	= da903x_disable,
+	.is_enabled	= da903x_is_enabled,
+};
+
+/* NOTE: this is dedicated for the insane DA9030 LDO14 */
+static struct regulator_ops da9030_regulator_ldo14_ops = {
+	.set_voltage	= da9030_set_ldo14_voltage,
+	.get_voltage	= da9030_get_ldo14_voltage,
+	.enable		= da903x_enable,
+	.disable	= da903x_disable,
+	.is_enabled	= da903x_is_enabled,
+};
+
+/* NOTE: this is dedicated for the DA9030 LDO1 and LDO15 that have locks  */
+static struct regulator_ops da9030_regulator_ldo1_15_ops = {
+	.set_voltage	= da9030_set_ldo1_15_voltage,
+	.get_voltage	= da903x_get_voltage,
+	.enable		= da903x_enable,
+	.disable	= da903x_disable,
+	.is_enabled	= da903x_is_enabled,
+};
+
+static struct regulator_ops da9034_regulator_dvc_ops = {
+	.set_voltage	= da9034_set_dvc_voltage,
+	.get_voltage	= da903x_get_voltage,
+	.enable		= da903x_enable,
+	.disable	= da903x_disable,
+	.is_enabled	= da903x_is_enabled,
+};
+
+/* NOTE: this is dedicated for the insane LDO12 */
+static struct regulator_ops da9034_regulator_ldo12_ops = {
+	.set_voltage	= da9034_set_ldo12_voltage,
+	.get_voltage	= da9034_get_ldo12_voltage,
+	.enable		= da903x_enable,
+	.disable	= da903x_disable,
+	.is_enabled	= da903x_is_enabled,
+};
+
+#define DA903x_LDO(_pmic, _id, min, max, step, vreg, shift, nbits, ereg, ebit)	\
+{									\
+	.desc	= {							\
+		.name	= "LDO" #_id,					\
+		.ops	= &da903x_regulator_ldo_ops,			\
+		.type	= REGULATOR_VOLTAGE,				\
+		.id	= _pmic##_ID_LDO##_id,				\
+		.owner	= THIS_MODULE,					\
+	},								\
+	.min_uV		= (min) * 1000,					\
+	.max_uV		= (max) * 1000,					\
+	.step_uV	= (step) * 1000,				\
+	.vol_reg	= _pmic##_##vreg,				\
+	.vol_shift	= (shift),					\
+	.vol_nbits	= (nbits),					\
+	.enable_reg	= _pmic##_##ereg,				\
+	.enable_bit	= (ebit),					\
+}
+
+#define DA9034_DVC(_id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \
+{									\
+	.desc	= {							\
+		.name	= #_id,						\
+		.ops	= &da9034_regulator_dvc_ops,			\
+		.type	= REGULATOR_VOLTAGE,				\
+		.id	= DA9034_ID_##_id,				\
+		.owner	= THIS_MODULE,					\
+	},								\
+	.min_uV		= (min) * 1000,					\
+	.max_uV		= (max) * 1000,					\
+	.step_uV	= (step) * 1000,				\
+	.vol_reg	= DA9034_##vreg,				\
+	.vol_shift	= (0),						\
+	.vol_nbits	= (nbits),					\
+	.update_reg	= DA9034_##ureg,				\
+	.update_bit	= (ubit),					\
+	.enable_reg	= DA9034_##ereg,				\
+	.enable_bit	= (ebit),					\
+}
+
+#define DA9034_LDO(_id, min, max, step, vreg, shift, nbits, ereg, ebit)	\
+	DA903x_LDO(DA9034, _id, min, max, step, vreg, shift, nbits, ereg, ebit)
+
+#define DA9030_LDO(_id, min, max, step, vreg, shift, nbits, ereg, ebit)	\
+	DA903x_LDO(DA9030, _id, min, max, step, vreg, shift, nbits, ereg, ebit)
+
+static struct da903x_regulator_info da903x_regulator_info[] = {
+	/* DA9030 */
+	DA9030_LDO( 1, 1200, 3200, 100,    LDO1, 0, 5, RCTL12, 1),
+	DA9030_LDO( 2, 1800, 3200, 100,   LDO23, 0, 4, RCTL12, 2),
+	DA9030_LDO( 3, 1800, 3200, 100,   LDO23, 4, 4, RCTL12, 3),
+	DA9030_LDO( 4, 1800, 3200, 100,   LDO45, 0, 4, RCTL12, 4),
+	DA9030_LDO( 5, 1800, 3200, 100,   LDO45, 4, 4, RCTL12, 5),
+	DA9030_LDO( 6, 1800, 3200, 100,    LDO6, 0, 4, RCTL12, 6),
+	DA9030_LDO( 7, 1800, 3200, 100,   LDO78, 0, 4, RCTL12, 7),
+	DA9030_LDO( 8, 1800, 3200, 100,   LDO78, 4, 4, RCTL22, 0),
+	DA9030_LDO( 9, 1800, 3200, 100,  LDO912, 0, 4, RCTL22, 1),
+	DA9030_LDO(10, 1800, 3200, 100, LDO1011, 0, 4, RCTL22, 2),
+	DA9030_LDO(11, 1800, 3200, 100, LDO1011, 4, 4, RCTL22, 3),
+	DA9030_LDO(12, 1800, 3200, 100,  LDO912, 4, 4, RCTL22, 4),
+	DA9030_LDO(14, 2760, 2940,  30, LDO1416, 0, 3, RCTL11, 4),
+	DA9030_LDO(15, 1100, 2650,  50,	  LDO15, 0, 5, RCTL11, 5),
+	DA9030_LDO(16, 1100, 2650,  50, LDO1416, 3, 5, RCTL11, 6),
+	DA9030_LDO(17, 1800, 3200, 100,   LDO17, 0, 4, RCTL11, 7),
+	DA9030_LDO(18, 1800, 3200, 100, LDO1819, 0, 4, RCTL21, 2),
+	DA9030_LDO(19, 1800, 3200, 100, LDO1819, 4, 4, RCTL21, 1),
+	DA9030_LDO(13, 2100, 2100, 0, INVAL, 0, 0, RCTL11, 3), /* fixed @2.1V */
+
+	/* DA9034 */
+	DA9034_DVC(BUCK1, 725, 1500, 25, ADTV1, 5, VCC1, 0, OVER1, 0),
+	DA9034_DVC(BUCK2, 725, 1500, 25, CDTV1, 5, VCC1, 2, OVER1, 1),
+	DA9034_DVC(LDO2,  725, 1500, 25, SDTV1, 5, VCC1, 4, OVER1, 2),
+	DA9034_DVC(LDO1, 1700, 2075, 25, MDTV1, 4, VCC1, 6, OVER3, 4),
+
+	DA9034_LDO( 3, 1800, 3300, 100,  LDO643, 0, 4, OVER3, 5),
+	DA9034_LDO( 4, 1800, 2900,1100,  LDO643, 4, 1, OVER3, 6),
+	DA9034_LDO( 6, 2500, 2850,  50,  LDO643, 5, 3, OVER2, 0),
+	DA9034_LDO( 7, 2700, 3050,  50,  LDO987, 0, 3, OVER2, 1),
+	DA9034_LDO( 8, 2700, 2850,  50,  LDO987, 3, 2, OVER2, 2),
+	DA9034_LDO( 9, 2700, 3050,  50,  LDO987, 5, 3, OVER2, 3),
+	DA9034_LDO(10, 2700, 3050,  50, LDO1110, 0, 3, OVER2, 4),
+	DA9034_LDO(11, 1800, 3300, 100, LDO1110, 4, 4, OVER2, 5),
+	DA9034_LDO(12, 1700, 3050,  50, LDO1312, 0, 4, OVER3, 6),
+	DA9034_LDO(13, 1800, 3300, 100, LDO1312, 4, 4, OVER2, 7),
+	DA9034_LDO(14, 1800, 3300, 100, LDO1514, 0, 4, OVER3, 0),
+	DA9034_LDO(15, 1800, 3300, 100, LDO1514, 4, 4, OVER3, 1),
+	DA9034_LDO(5, 3100, 3100, 0, INVAL, 0, 0, OVER3, 7), /* fixed @3.1V */
+};
+
+static inline struct da903x_regulator_info *find_regulator_info(int id)
+{
+	struct da903x_regulator_info *ri;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(da903x_regulator_info); i++) {
+		ri = &da903x_regulator_info[i];
+		if (ri->desc.id == id)
+			return ri;
+	}
+	return NULL;
+}
+
+static int __devinit da903x_regulator_probe(struct platform_device *pdev)
+{
+	struct da903x_regulator_info *ri = NULL;
+	struct regulator_dev *rdev;
+
+	ri = find_regulator_info(pdev->id);
+	if (ri == NULL) {
+		dev_err(&pdev->dev, "invalid regulator ID specified\n");
+		return -EINVAL;
+	}
+
+	/* Workaround for the weird LDO12 voltage setting */
+	if (ri->desc.id == DA9034_ID_LDO12)
+		ri->desc.ops = &da9034_regulator_ldo12_ops;
+
+	if (ri->desc.id == DA9030_ID_LDO14)
+		ri->desc.ops = &da9030_regulator_ldo14_ops;
+
+	if (ri->desc.id == DA9030_ID_LDO1 || ri->desc.id == DA9030_ID_LDO15)
+		ri->desc.ops = &da9030_regulator_ldo1_15_ops;
+
+	rdev = regulator_register(&ri->desc, pdev->dev.parent, ri);
+	if (IS_ERR(rdev)) {
+		dev_err(&pdev->dev, "failed to register regulator %s\n",
+				ri->desc.name);
+		return PTR_ERR(rdev);
+	}
+
+	platform_set_drvdata(pdev, rdev);
+	return 0;
+}
+
+static int __devexit da903x_regulator_remove(struct platform_device *pdev)
+{
+	struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+	regulator_unregister(rdev);
+	return 0;
+}
+
+static struct platform_driver da903x_regulator_driver = {
+	.driver	= {
+		.name	= "da903x-regulator",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= da903x_regulator_probe,
+	.remove		= da903x_regulator_remove,
+};
+
+static int __init da903x_regulator_init(void)
+{
+	return platform_driver_register(&da903x_regulator_driver);
+}
+module_init(da903x_regulator_init);
+
+static void __exit da903x_regulator_exit(void)
+{
+	platform_driver_unregister(&da903x_regulator_driver);
+}
+module_exit(da903x_regulator_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
+	      "Mike Rapoport <mike@compulab.co.il>");
+MODULE_DESCRIPTION("Regulator Driver for Dialog Semiconductor DA903X PMIC");
+MODULE_ALIAS("platform:da903x-regulator");
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
new file mode 100644
index 000000000000..1f44b17e23b1
--- /dev/null
+++ b/drivers/regulator/wm8350-regulator.c
@@ -0,0 +1,1431 @@
+/*
+ * wm8350.c  --  Voltage and current regulation for the Wolfson WM8350 PMIC
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood
+ *         linux@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.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/pmic.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+/* Microamps */
+static const int isink_cur[] = {
+	4,
+	5,
+	6,
+	7,
+	8,
+	10,
+	11,
+	14,
+	16,
+	19,
+	23,
+	27,
+	32,
+	39,
+	46,
+	54,
+	65,
+	77,
+	92,
+	109,
+	130,
+	154,
+	183,
+	218,
+	259,
+	308,
+	367,
+	436,
+	518,
+	616,
+	733,
+	872,
+	1037,
+	1233,
+	1466,
+	1744,
+	2073,
+	2466,
+	2933,
+	3487,
+	4147,
+	4932,
+	5865,
+	6975,
+	8294,
+	9864,
+	11730,
+	13949,
+	16589,
+	19728,
+	23460,
+	27899,
+	33178,
+	39455,
+	46920,
+	55798,
+	66355,
+	78910,
+	93840,
+	111596,
+	132710,
+	157820,
+	187681,
+	223191
+};
+
+static int get_isink_val(int min_uA, int max_uA, u16 *setting)
+{
+	int i;
+
+	for (i = ARRAY_SIZE(isink_cur) - 1; i >= 0; i--) {
+		if (min_uA <= isink_cur[i] && max_uA >= isink_cur[i]) {
+			*setting = i;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+static inline int wm8350_ldo_val_to_mvolts(unsigned int val)
+{
+	if (val < 16)
+		return (val * 50) + 900;
+	else
+		return ((val - 16) * 100) + 1800;
+
+}
+
+static inline unsigned int wm8350_ldo_mvolts_to_val(int mV)
+{
+	if (mV < 1800)
+		return (mV - 900) / 50;
+	else
+		return ((mV - 1800) / 100) + 16;
+}
+
+static inline int wm8350_dcdc_val_to_mvolts(unsigned int val)
+{
+	return (val * 25) + 850;
+}
+
+static inline unsigned int wm8350_dcdc_mvolts_to_val(int mV)
+{
+	return (mV - 850) / 25;
+}
+
+static int wm8350_isink_set_current(struct regulator_dev *rdev, int min_uA,
+	int max_uA)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int isink = rdev_get_id(rdev);
+	u16 val, setting;
+	int ret;
+
+	ret = get_isink_val(min_uA, max_uA, &setting);
+	if (ret != 0)
+		return ret;
+
+	switch (isink) {
+	case WM8350_ISINK_A:
+		val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_A) &
+		    ~WM8350_CS1_ISEL_MASK;
+		wm8350_reg_write(wm8350, WM8350_CURRENT_SINK_DRIVER_A,
+				 val | setting);
+		break;
+	case WM8350_ISINK_B:
+		val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_B) &
+		    ~WM8350_CS1_ISEL_MASK;
+		wm8350_reg_write(wm8350, WM8350_CURRENT_SINK_DRIVER_B,
+				 val | setting);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int wm8350_isink_get_current(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int isink = rdev_get_id(rdev);
+	u16 val;
+
+	switch (isink) {
+	case WM8350_ISINK_A:
+		val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_A) &
+		    WM8350_CS1_ISEL_MASK;
+		break;
+	case WM8350_ISINK_B:
+		val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_B) &
+		    WM8350_CS1_ISEL_MASK;
+		break;
+	default:
+		return 0;
+	}
+
+	return (isink_cur[val] + 50) / 100;
+}
+
+/* turn on ISINK followed by DCDC */
+static int wm8350_isink_enable(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int isink = rdev_get_id(rdev);
+
+	switch (isink) {
+	case WM8350_ISINK_A:
+		switch (wm8350->pmic.isink_A_dcdc) {
+		case WM8350_DCDC_2:
+		case WM8350_DCDC_5:
+			wm8350_set_bits(wm8350, WM8350_POWER_MGMT_7,
+					WM8350_CS1_ENA);
+			wm8350_set_bits(wm8350, WM8350_CSA_FLASH_CONTROL,
+					WM8350_CS1_DRIVE);
+			wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED,
+					1 << (wm8350->pmic.isink_A_dcdc -
+					      WM8350_DCDC_1));
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case WM8350_ISINK_B:
+		switch (wm8350->pmic.isink_B_dcdc) {
+		case WM8350_DCDC_2:
+		case WM8350_DCDC_5:
+			wm8350_set_bits(wm8350, WM8350_POWER_MGMT_7,
+					WM8350_CS2_ENA);
+			wm8350_set_bits(wm8350, WM8350_CSB_FLASH_CONTROL,
+					WM8350_CS2_DRIVE);
+			wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED,
+					1 << (wm8350->pmic.isink_B_dcdc -
+					      WM8350_DCDC_1));
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int wm8350_isink_disable(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int isink = rdev_get_id(rdev);
+
+	switch (isink) {
+	case WM8350_ISINK_A:
+		switch (wm8350->pmic.isink_A_dcdc) {
+		case WM8350_DCDC_2:
+		case WM8350_DCDC_5:
+			wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED,
+					  1 << (wm8350->pmic.isink_A_dcdc -
+						WM8350_DCDC_1));
+			wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_7,
+					  WM8350_CS1_ENA);
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case WM8350_ISINK_B:
+		switch (wm8350->pmic.isink_B_dcdc) {
+		case WM8350_DCDC_2:
+		case WM8350_DCDC_5:
+			wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED,
+					  1 << (wm8350->pmic.isink_B_dcdc -
+						WM8350_DCDC_1));
+			wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_7,
+					  WM8350_CS2_ENA);
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int wm8350_isink_is_enabled(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int isink = rdev_get_id(rdev);
+
+	switch (isink) {
+	case WM8350_ISINK_A:
+		return wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_A) &
+		    0x8000;
+	case WM8350_ISINK_B:
+		return wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_B) &
+		    0x8000;
+	}
+	return -EINVAL;
+}
+
+int wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode,
+			   u16 trigger, u16 duration, u16 on_ramp, u16 off_ramp,
+			   u16 drive)
+{
+	switch (isink) {
+	case WM8350_ISINK_A:
+		wm8350_reg_write(wm8350, WM8350_CSA_FLASH_CONTROL,
+				 (mode ? WM8350_CS1_FLASH_MODE : 0) |
+				 (trigger ? WM8350_CS1_TRIGSRC : 0) |
+				 duration | on_ramp | off_ramp | drive);
+		break;
+	case WM8350_ISINK_B:
+		wm8350_reg_write(wm8350, WM8350_CSB_FLASH_CONTROL,
+				 (mode ? WM8350_CS2_FLASH_MODE : 0) |
+				 (trigger ? WM8350_CS2_TRIGSRC : 0) |
+				 duration | on_ramp | off_ramp | drive);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_isink_set_flash);
+
+static int wm8350_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV,
+	int max_uV)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int volt_reg, dcdc = rdev_get_id(rdev), mV,
+		min_mV = min_uV / 1000, max_mV = max_uV / 1000;
+	u16 val;
+
+	if (min_mV < 850 || min_mV > 4025)
+		return -EINVAL;
+	if (max_mV < 850 || max_mV > 4025)
+		return -EINVAL;
+
+	/* step size is 25mV */
+	mV = (min_mV - 826) / 25;
+	if (wm8350_dcdc_val_to_mvolts(mV) > max_mV)
+		return -EINVAL;
+	BUG_ON(wm8350_dcdc_val_to_mvolts(mV) < min_mV);
+
+	switch (dcdc) {
+	case WM8350_DCDC_1:
+		volt_reg = WM8350_DCDC1_CONTROL;
+		break;
+	case WM8350_DCDC_3:
+		volt_reg = WM8350_DCDC3_CONTROL;
+		break;
+	case WM8350_DCDC_4:
+		volt_reg = WM8350_DCDC4_CONTROL;
+		break;
+	case WM8350_DCDC_6:
+		volt_reg = WM8350_DCDC6_CONTROL;
+		break;
+	case WM8350_DCDC_2:
+	case WM8350_DCDC_5:
+	default:
+		return -EINVAL;
+	}
+
+	/* all DCDCs have same mV bits */
+	val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
+	wm8350_reg_write(wm8350, volt_reg, val | mV);
+	return 0;
+}
+
+static int wm8350_dcdc_get_voltage(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int volt_reg, dcdc = rdev_get_id(rdev);
+	u16 val;
+
+	switch (dcdc) {
+	case WM8350_DCDC_1:
+		volt_reg = WM8350_DCDC1_CONTROL;
+		break;
+	case WM8350_DCDC_3:
+		volt_reg = WM8350_DCDC3_CONTROL;
+		break;
+	case WM8350_DCDC_4:
+		volt_reg = WM8350_DCDC4_CONTROL;
+		break;
+	case WM8350_DCDC_6:
+		volt_reg = WM8350_DCDC6_CONTROL;
+		break;
+	case WM8350_DCDC_2:
+	case WM8350_DCDC_5:
+	default:
+		return -EINVAL;
+	}
+
+	/* all DCDCs have same mV bits */
+	val = wm8350_reg_read(wm8350, volt_reg) & WM8350_DC1_VSEL_MASK;
+	return wm8350_dcdc_val_to_mvolts(val) * 1000;
+}
+
+static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int volt_reg, mV = uV / 1000, dcdc = rdev_get_id(rdev);
+	u16 val;
+
+	dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, dcdc, mV);
+
+	if (mV && (mV < 850 || mV > 4025)) {
+		dev_err(wm8350->dev,
+			"DCDC%d suspend voltage %d mV out of range\n",
+			dcdc, mV);
+		return -EINVAL;
+	}
+	if (mV == 0)
+		mV = 850;
+
+	switch (dcdc) {
+	case WM8350_DCDC_1:
+		volt_reg = WM8350_DCDC1_LOW_POWER;
+		break;
+	case WM8350_DCDC_3:
+		volt_reg = WM8350_DCDC3_LOW_POWER;
+		break;
+	case WM8350_DCDC_4:
+		volt_reg = WM8350_DCDC4_LOW_POWER;
+		break;
+	case WM8350_DCDC_6:
+		volt_reg = WM8350_DCDC6_LOW_POWER;
+		break;
+	case WM8350_DCDC_2:
+	case WM8350_DCDC_5:
+	default:
+		return -EINVAL;
+	}
+
+	/* all DCDCs have same mV bits */
+	val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
+	wm8350_reg_write(wm8350, volt_reg,
+			 val | wm8350_dcdc_mvolts_to_val(mV));
+	return 0;
+}
+
+static int wm8350_dcdc_set_suspend_enable(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int dcdc = rdev_get_id(rdev);
+	u16 val;
+
+	switch (dcdc) {
+	case WM8350_DCDC_1:
+		val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER)
+			& ~WM8350_DCDC_HIB_MODE_MASK;
+		wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER,
+			wm8350->pmic.dcdc1_hib_mode);
+		break;
+	case WM8350_DCDC_3:
+		val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER)
+			& ~WM8350_DCDC_HIB_MODE_MASK;
+		wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER,
+			wm8350->pmic.dcdc3_hib_mode);
+		break;
+	case WM8350_DCDC_4:
+		val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER)
+			& ~WM8350_DCDC_HIB_MODE_MASK;
+		wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER,
+			wm8350->pmic.dcdc4_hib_mode);
+		break;
+	case WM8350_DCDC_6:
+		val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER)
+			& ~WM8350_DCDC_HIB_MODE_MASK;
+		wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER,
+			wm8350->pmic.dcdc6_hib_mode);
+		break;
+	case WM8350_DCDC_2:
+	case WM8350_DCDC_5:
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int wm8350_dcdc_set_suspend_disable(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int dcdc = rdev_get_id(rdev);
+	u16 val;
+
+	switch (dcdc) {
+	case WM8350_DCDC_1:
+		val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER);
+		wm8350->pmic.dcdc1_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+		wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER,
+			WM8350_DCDC_HIB_MODE_DIS);
+		break;
+	case WM8350_DCDC_3:
+		val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER);
+		wm8350->pmic.dcdc3_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+		wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER,
+			WM8350_DCDC_HIB_MODE_DIS);
+		break;
+	case WM8350_DCDC_4:
+		val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER);
+		wm8350->pmic.dcdc4_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+		wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER,
+			WM8350_DCDC_HIB_MODE_DIS);
+		break;
+	case WM8350_DCDC_6:
+		val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER);
+		wm8350->pmic.dcdc6_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+		wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER,
+			WM8350_DCDC_HIB_MODE_DIS);
+		break;
+	case WM8350_DCDC_2:
+	case WM8350_DCDC_5:
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int wm8350_dcdc25_set_suspend_enable(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int dcdc = rdev_get_id(rdev);
+	u16 val;
+
+	switch (dcdc) {
+	case WM8350_DCDC_2:
+		val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
+		    & ~WM8350_DC2_HIB_MODE_MASK;
+		wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
+				 WM8350_DC2_HIB_MODE_ACTIVE);
+		break;
+	case WM8350_DCDC_5:
+		val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
+		    & ~WM8350_DC2_HIB_MODE_MASK;
+		wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
+				 WM8350_DC5_HIB_MODE_ACTIVE);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int wm8350_dcdc25_set_suspend_disable(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int dcdc = rdev_get_id(rdev);
+	u16 val;
+
+	switch (dcdc) {
+	case WM8350_DCDC_2:
+		val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
+		    & ~WM8350_DC2_HIB_MODE_MASK;
+		wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
+				 WM8350_DC2_HIB_MODE_DISABLE);
+		break;
+	case WM8350_DCDC_5:
+		val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
+		    & ~WM8350_DC2_HIB_MODE_MASK;
+		wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
+				 WM8350_DC2_HIB_MODE_DISABLE);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev,
+	unsigned int mode)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int dcdc = rdev_get_id(rdev);
+	u16 *hib_mode;
+
+	switch (dcdc) {
+	case WM8350_DCDC_1:
+		hib_mode = &wm8350->pmic.dcdc1_hib_mode;
+		break;
+	case WM8350_DCDC_3:
+		hib_mode = &wm8350->pmic.dcdc3_hib_mode;
+		break;
+	case WM8350_DCDC_4:
+		hib_mode = &wm8350->pmic.dcdc4_hib_mode;
+		break;
+	case WM8350_DCDC_6:
+		hib_mode = &wm8350->pmic.dcdc6_hib_mode;
+		break;
+	case WM8350_DCDC_2:
+	case WM8350_DCDC_5:
+	default:
+		return -EINVAL;
+	}
+
+	switch (mode) {
+	case REGULATOR_MODE_NORMAL:
+		*hib_mode = WM8350_DCDC_HIB_MODE_IMAGE;
+		break;
+	case REGULATOR_MODE_IDLE:
+		*hib_mode = WM8350_DCDC_HIB_MODE_STANDBY;
+		break;
+	case REGULATOR_MODE_STANDBY:
+		*hib_mode = WM8350_DCDC_HIB_MODE_LDO_IM;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int volt_reg, mV = uV / 1000, ldo = rdev_get_id(rdev);
+	u16 val;
+
+	dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, ldo, mV);
+
+	if (mV < 900 || mV > 3300) {
+		dev_err(wm8350->dev, "LDO%d voltage %d mV out of range\n",
+			ldo, mV);
+		return -EINVAL;
+	}
+
+	switch (ldo) {
+	case WM8350_LDO_1:
+		volt_reg = WM8350_LDO1_LOW_POWER;
+		break;
+	case WM8350_LDO_2:
+		volt_reg = WM8350_LDO2_LOW_POWER;
+		break;
+	case WM8350_LDO_3:
+		volt_reg = WM8350_LDO3_LOW_POWER;
+		break;
+	case WM8350_LDO_4:
+		volt_reg = WM8350_LDO4_LOW_POWER;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* all LDOs have same mV bits */
+	val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
+	wm8350_reg_write(wm8350, volt_reg,
+			 val | wm8350_ldo_mvolts_to_val(mV));
+	return 0;
+}
+
+static int wm8350_ldo_set_suspend_enable(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int volt_reg, ldo = rdev_get_id(rdev);
+	u16 val;
+
+	switch (ldo) {
+	case WM8350_LDO_1:
+		volt_reg = WM8350_LDO1_LOW_POWER;
+		break;
+	case WM8350_LDO_2:
+		volt_reg = WM8350_LDO2_LOW_POWER;
+		break;
+	case WM8350_LDO_3:
+		volt_reg = WM8350_LDO3_LOW_POWER;
+		break;
+	case WM8350_LDO_4:
+		volt_reg = WM8350_LDO4_LOW_POWER;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* all LDOs have same mV bits */
+	val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_HIB_MODE_MASK;
+	wm8350_reg_write(wm8350, volt_reg, val);
+	return 0;
+}
+
+static int wm8350_ldo_set_suspend_disable(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int volt_reg, ldo = rdev_get_id(rdev);
+	u16 val;
+
+	switch (ldo) {
+	case WM8350_LDO_1:
+		volt_reg = WM8350_LDO1_LOW_POWER;
+		break;
+	case WM8350_LDO_2:
+		volt_reg = WM8350_LDO2_LOW_POWER;
+		break;
+	case WM8350_LDO_3:
+		volt_reg = WM8350_LDO3_LOW_POWER;
+		break;
+	case WM8350_LDO_4:
+		volt_reg = WM8350_LDO4_LOW_POWER;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* all LDOs have same mV bits */
+	val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_HIB_MODE_MASK;
+	wm8350_reg_write(wm8350, volt_reg, WM8350_LDO1_HIB_MODE_DIS);
+	return 0;
+}
+
+static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV,
+	int max_uV)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int volt_reg, ldo = rdev_get_id(rdev), mV, min_mV = min_uV / 1000,
+		max_mV = max_uV / 1000;
+	u16 val;
+
+	if (min_mV < 900 || min_mV > 3300)
+		return -EINVAL;
+	if (max_mV < 900 || max_mV > 3300)
+		return -EINVAL;
+
+	if (min_mV < 1800) {
+		/* step size is 50mV < 1800mV */
+		mV = (min_mV - 851) / 50;
+		if (wm8350_ldo_val_to_mvolts(mV) > max_mV)
+			return -EINVAL;
+		BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
+	} else {
+		/* step size is 100mV > 1800mV */
+		mV = ((min_mV - 1701) / 100) + 16;
+		if (wm8350_ldo_val_to_mvolts(mV) > max_mV)
+			return -EINVAL;
+		BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
+	}
+
+	switch (ldo) {
+	case WM8350_LDO_1:
+		volt_reg = WM8350_LDO1_CONTROL;
+		break;
+	case WM8350_LDO_2:
+		volt_reg = WM8350_LDO2_CONTROL;
+		break;
+	case WM8350_LDO_3:
+		volt_reg = WM8350_LDO3_CONTROL;
+		break;
+	case WM8350_LDO_4:
+		volt_reg = WM8350_LDO4_CONTROL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* all LDOs have same mV bits */
+	val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
+	wm8350_reg_write(wm8350, volt_reg, val | mV);
+	return 0;
+}
+
+static int wm8350_ldo_get_voltage(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int volt_reg, ldo = rdev_get_id(rdev);
+	u16 val;
+
+	switch (ldo) {
+	case WM8350_LDO_1:
+		volt_reg = WM8350_LDO1_CONTROL;
+		break;
+	case WM8350_LDO_2:
+		volt_reg = WM8350_LDO2_CONTROL;
+		break;
+	case WM8350_LDO_3:
+		volt_reg = WM8350_LDO3_CONTROL;
+		break;
+	case WM8350_LDO_4:
+		volt_reg = WM8350_LDO4_CONTROL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* all LDOs have same mV bits */
+	val = wm8350_reg_read(wm8350, volt_reg) & WM8350_LDO1_VSEL_MASK;
+	return wm8350_ldo_val_to_mvolts(val) * 1000;
+}
+
+int wm8350_dcdc_set_slot(struct wm8350 *wm8350, int dcdc, u16 start,
+			 u16 stop, u16 fault)
+{
+	int slot_reg;
+	u16 val;
+
+	dev_dbg(wm8350->dev, "%s %d start %d stop %d\n",
+		__func__, dcdc, start, stop);
+
+	/* slot valid ? */
+	if (start > 15 || stop > 15)
+		return -EINVAL;
+
+	switch (dcdc) {
+	case WM8350_DCDC_1:
+		slot_reg = WM8350_DCDC1_TIMEOUTS;
+		break;
+	case WM8350_DCDC_2:
+		slot_reg = WM8350_DCDC2_TIMEOUTS;
+		break;
+	case WM8350_DCDC_3:
+		slot_reg = WM8350_DCDC3_TIMEOUTS;
+		break;
+	case WM8350_DCDC_4:
+		slot_reg = WM8350_DCDC4_TIMEOUTS;
+		break;
+	case WM8350_DCDC_5:
+		slot_reg = WM8350_DCDC5_TIMEOUTS;
+		break;
+	case WM8350_DCDC_6:
+		slot_reg = WM8350_DCDC6_TIMEOUTS;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	val = wm8350_reg_read(wm8350, slot_reg) &
+	    ~(WM8350_DC1_ENSLOT_MASK | WM8350_DC1_SDSLOT_MASK |
+	      WM8350_DC1_ERRACT_MASK);
+	wm8350_reg_write(wm8350, slot_reg,
+			 val | (start << WM8350_DC1_ENSLOT_SHIFT) |
+			 (stop << WM8350_DC1_SDSLOT_SHIFT) |
+			 (fault << WM8350_DC1_ERRACT_SHIFT));
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_dcdc_set_slot);
+
+int wm8350_ldo_set_slot(struct wm8350 *wm8350, int ldo, u16 start, u16 stop)
+{
+	int slot_reg;
+	u16 val;
+
+	dev_dbg(wm8350->dev, "%s %d start %d stop %d\n",
+		__func__, ldo, start, stop);
+
+	/* slot valid ? */
+	if (start > 15 || stop > 15)
+		return -EINVAL;
+
+	switch (ldo) {
+	case WM8350_LDO_1:
+		slot_reg = WM8350_LDO1_TIMEOUTS;
+		break;
+	case WM8350_LDO_2:
+		slot_reg = WM8350_LDO2_TIMEOUTS;
+		break;
+	case WM8350_LDO_3:
+		slot_reg = WM8350_LDO3_TIMEOUTS;
+		break;
+	case WM8350_LDO_4:
+		slot_reg = WM8350_LDO4_TIMEOUTS;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	val = wm8350_reg_read(wm8350, slot_reg) & ~WM8350_LDO1_SDSLOT_MASK;
+	wm8350_reg_write(wm8350, slot_reg, val | ((start << 10) | (stop << 6)));
+	return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_ldo_set_slot);
+
+int wm8350_dcdc25_set_mode(struct wm8350 *wm8350, int dcdc, u16 mode,
+			   u16 ilim, u16 ramp, u16 feedback)
+{
+	u16 val;
+
+	dev_dbg(wm8350->dev, "%s %d mode: %s %s\n", __func__, dcdc,
+		mode ? "normal" : "boost", ilim ? "low" : "normal");
+
+	switch (dcdc) {
+	case WM8350_DCDC_2:
+		val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
+		    & ~(WM8350_DC2_MODE_MASK | WM8350_DC2_ILIM_MASK |
+			WM8350_DC2_RMP_MASK | WM8350_DC2_FBSRC_MASK);
+		wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
+				 (mode << WM8350_DC2_MODE_SHIFT) |
+				 (ilim << WM8350_DC2_ILIM_SHIFT) |
+				 (ramp << WM8350_DC2_RMP_SHIFT) |
+				 (feedback << WM8350_DC2_FBSRC_SHIFT));
+		break;
+	case WM8350_DCDC_5:
+		val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
+		    & ~(WM8350_DC5_MODE_MASK | WM8350_DC5_ILIM_MASK |
+			WM8350_DC5_RMP_MASK | WM8350_DC5_FBSRC_MASK);
+		wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
+				 (mode << WM8350_DC5_MODE_SHIFT) |
+				 (ilim << WM8350_DC5_ILIM_SHIFT) |
+				 (ramp << WM8350_DC5_RMP_SHIFT) |
+				 (feedback << WM8350_DC5_FBSRC_SHIFT));
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_dcdc25_set_mode);
+
+static int wm8350_dcdc_enable(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int dcdc = rdev_get_id(rdev);
+	u16 shift;
+
+	if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
+		return -EINVAL;
+
+	shift = dcdc - WM8350_DCDC_1;
+	wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
+	return 0;
+}
+
+static int wm8350_dcdc_disable(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int dcdc = rdev_get_id(rdev);
+	u16 shift;
+
+	if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
+		return -EINVAL;
+
+	shift = dcdc - WM8350_DCDC_1;
+	wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
+
+	return 0;
+}
+
+static int wm8350_ldo_enable(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int ldo = rdev_get_id(rdev);
+	u16 shift;
+
+	if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
+		return -EINVAL;
+
+	shift = (ldo - WM8350_LDO_1) + 8;
+	wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
+	return 0;
+}
+
+static int wm8350_ldo_disable(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int ldo = rdev_get_id(rdev);
+	u16 shift;
+
+	if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
+		return -EINVAL;
+
+	shift = (ldo - WM8350_LDO_1) + 8;
+	wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
+	return 0;
+}
+
+static int force_continuous_enable(struct wm8350 *wm8350, int dcdc, int enable)
+{
+	int reg = 0, ret;
+
+	switch (dcdc) {
+	case WM8350_DCDC_1:
+		reg = WM8350_DCDC1_FORCE_PWM;
+		break;
+	case WM8350_DCDC_3:
+		reg = WM8350_DCDC3_FORCE_PWM;
+		break;
+	case WM8350_DCDC_4:
+		reg = WM8350_DCDC4_FORCE_PWM;
+		break;
+	case WM8350_DCDC_6:
+		reg = WM8350_DCDC6_FORCE_PWM;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (enable)
+		ret = wm8350_set_bits(wm8350, reg,
+			WM8350_DCDC1_FORCE_PWM_ENA);
+	else
+		ret = wm8350_clear_bits(wm8350, reg,
+			WM8350_DCDC1_FORCE_PWM_ENA);
+	return ret;
+}
+
+static int wm8350_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int dcdc = rdev_get_id(rdev);
+	u16 val;
+
+	if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
+		return -EINVAL;
+
+	if (dcdc == WM8350_DCDC_2 || dcdc == WM8350_DCDC_5)
+		return -EINVAL;
+
+	val = 1 << (dcdc - WM8350_DCDC_1);
+
+	switch (mode) {
+	case REGULATOR_MODE_FAST:
+		/* force continuous mode */
+		wm8350_set_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val);
+		wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
+		force_continuous_enable(wm8350, dcdc, 1);
+		break;
+	case REGULATOR_MODE_NORMAL:
+		/* active / pulse skipping */
+		wm8350_set_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val);
+		wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
+		force_continuous_enable(wm8350, dcdc, 0);
+		break;
+	case REGULATOR_MODE_IDLE:
+		/* standby mode */
+		force_continuous_enable(wm8350, dcdc, 0);
+		wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
+		wm8350_clear_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val);
+		break;
+	case REGULATOR_MODE_STANDBY:
+		/* LDO mode */
+		force_continuous_enable(wm8350, dcdc, 0);
+		wm8350_set_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
+		break;
+	}
+
+	return 0;
+}
+
+static unsigned int wm8350_dcdc_get_mode(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int dcdc = rdev_get_id(rdev);
+	u16 mask, sleep, active, force;
+	int mode = REGULATOR_MODE_NORMAL;
+
+	if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
+		return -EINVAL;
+
+	if (dcdc == WM8350_DCDC_2 || dcdc == WM8350_DCDC_5)
+		return -EINVAL;
+
+	mask = 1 << (dcdc - WM8350_DCDC_1);
+	active = wm8350_reg_read(wm8350, WM8350_DCDC_ACTIVE_OPTIONS) & mask;
+	sleep = wm8350_reg_read(wm8350, WM8350_DCDC_SLEEP_OPTIONS) & mask;
+	force = wm8350_reg_read(wm8350, WM8350_DCDC1_FORCE_PWM)
+	    & WM8350_DCDC1_FORCE_PWM_ENA;
+	dev_dbg(wm8350->dev, "mask %x active %x sleep %x force %x",
+		mask, active, sleep, force);
+
+	if (active && !sleep) {
+		if (force)
+			mode = REGULATOR_MODE_FAST;
+		else
+			mode = REGULATOR_MODE_NORMAL;
+	} else if (!active && !sleep)
+		mode = REGULATOR_MODE_IDLE;
+	else if (!sleep)
+		mode = REGULATOR_MODE_STANDBY;
+
+	return mode;
+}
+
+static unsigned int wm8350_ldo_get_mode(struct regulator_dev *rdev)
+{
+	return REGULATOR_MODE_NORMAL;
+}
+
+struct wm8350_dcdc_efficiency {
+	int uA_load_min;
+	int uA_load_max;
+	unsigned int mode;
+};
+
+static const struct wm8350_dcdc_efficiency dcdc1_6_efficiency[] = {
+	{0, 10000, REGULATOR_MODE_STANDBY},       /* 0 - 10mA - LDO */
+	{10000, 100000, REGULATOR_MODE_IDLE},     /* 10mA - 100mA - Standby */
+	{100000, 1000000, REGULATOR_MODE_NORMAL}, /* > 100mA - Active */
+	{-1, -1, REGULATOR_MODE_NORMAL},
+};
+
+static const struct wm8350_dcdc_efficiency dcdc3_4_efficiency[] = {
+	{0, 10000, REGULATOR_MODE_STANDBY},      /* 0 - 10mA - LDO */
+	{10000, 100000, REGULATOR_MODE_IDLE},    /* 10mA - 100mA - Standby */
+	{100000, 800000, REGULATOR_MODE_NORMAL}, /* > 100mA - Active */
+	{-1, -1, REGULATOR_MODE_NORMAL},
+};
+
+static unsigned int get_mode(int uA, const struct wm8350_dcdc_efficiency *eff)
+{
+	int i = 0;
+
+	while (eff[i].uA_load_min != -1) {
+		if (uA >= eff[i].uA_load_min && uA <= eff[i].uA_load_max)
+			return eff[i].mode;
+	}
+	return REGULATOR_MODE_NORMAL;
+}
+
+/* Query the regulator for it's most efficient mode @ uV,uA
+ * WM8350 regulator efficiency is pretty similar over
+ * different input and output uV.
+ */
+static unsigned int wm8350_dcdc_get_optimum_mode(struct regulator_dev *rdev,
+						 int input_uV, int output_uV,
+						 int output_uA)
+{
+	int dcdc = rdev_get_id(rdev), mode;
+
+	switch (dcdc) {
+	case WM8350_DCDC_1:
+	case WM8350_DCDC_6:
+		mode = get_mode(output_uA, dcdc1_6_efficiency);
+		break;
+	case WM8350_DCDC_3:
+	case WM8350_DCDC_4:
+		mode = get_mode(output_uA, dcdc3_4_efficiency);
+		break;
+	default:
+		mode = REGULATOR_MODE_NORMAL;
+		break;
+	}
+	return mode;
+}
+
+static int wm8350_dcdc_is_enabled(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int dcdc = rdev_get_id(rdev), shift;
+
+	if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
+		return -EINVAL;
+
+	shift = dcdc - WM8350_DCDC_1;
+	return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED)
+	    & (1 << shift);
+}
+
+static int wm8350_ldo_is_enabled(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int ldo = rdev_get_id(rdev), shift;
+
+	if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
+		return -EINVAL;
+
+	shift = (ldo - WM8350_LDO_1) + 8;
+	return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED)
+	    & (1 << shift);
+}
+
+static struct regulator_ops wm8350_dcdc_ops = {
+	.set_voltage = wm8350_dcdc_set_voltage,
+	.get_voltage = wm8350_dcdc_get_voltage,
+	.enable = wm8350_dcdc_enable,
+	.disable = wm8350_dcdc_disable,
+	.get_mode = wm8350_dcdc_get_mode,
+	.set_mode = wm8350_dcdc_set_mode,
+	.get_optimum_mode = wm8350_dcdc_get_optimum_mode,
+	.is_enabled = wm8350_dcdc_is_enabled,
+	.set_suspend_voltage = wm8350_dcdc_set_suspend_voltage,
+	.set_suspend_enable = wm8350_dcdc_set_suspend_enable,
+	.set_suspend_disable = wm8350_dcdc_set_suspend_disable,
+	.set_suspend_mode = wm8350_dcdc_set_suspend_mode,
+};
+
+static struct regulator_ops wm8350_dcdc2_5_ops = {
+	.enable = wm8350_dcdc_enable,
+	.disable = wm8350_dcdc_disable,
+	.is_enabled = wm8350_dcdc_is_enabled,
+	.set_suspend_enable = wm8350_dcdc25_set_suspend_enable,
+	.set_suspend_disable = wm8350_dcdc25_set_suspend_disable,
+};
+
+static struct regulator_ops wm8350_ldo_ops = {
+	.set_voltage = wm8350_ldo_set_voltage,
+	.get_voltage = wm8350_ldo_get_voltage,
+	.enable = wm8350_ldo_enable,
+	.disable = wm8350_ldo_disable,
+	.is_enabled = wm8350_ldo_is_enabled,
+	.get_mode = wm8350_ldo_get_mode,
+	.set_suspend_voltage = wm8350_ldo_set_suspend_voltage,
+	.set_suspend_enable = wm8350_ldo_set_suspend_enable,
+	.set_suspend_disable = wm8350_ldo_set_suspend_disable,
+};
+
+static struct regulator_ops wm8350_isink_ops = {
+	.set_current_limit = wm8350_isink_set_current,
+	.get_current_limit = wm8350_isink_get_current,
+	.enable = wm8350_isink_enable,
+	.disable = wm8350_isink_disable,
+	.is_enabled = wm8350_isink_is_enabled,
+};
+
+static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
+	{
+		.name = "DCDC1",
+		.id = WM8350_DCDC_1,
+		.ops = &wm8350_dcdc_ops,
+		.irq = WM8350_IRQ_UV_DC1,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "DCDC2",
+		.id = WM8350_DCDC_2,
+		.ops = &wm8350_dcdc2_5_ops,
+		.irq = WM8350_IRQ_UV_DC2,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "DCDC3",
+		.id = WM8350_DCDC_3,
+		.ops = &wm8350_dcdc_ops,
+		.irq = WM8350_IRQ_UV_DC3,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "DCDC4",
+		.id = WM8350_DCDC_4,
+		.ops = &wm8350_dcdc_ops,
+		.irq = WM8350_IRQ_UV_DC4,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "DCDC5",
+		.id = WM8350_DCDC_5,
+		.ops = &wm8350_dcdc2_5_ops,
+		.irq = WM8350_IRQ_UV_DC5,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+	 },
+	{
+		.name = "DCDC6",
+		.id = WM8350_DCDC_6,
+		.ops = &wm8350_dcdc_ops,
+		.irq = WM8350_IRQ_UV_DC6,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "LDO1",
+		.id = WM8350_LDO_1,
+		.ops = &wm8350_ldo_ops,
+		.irq = WM8350_IRQ_UV_LDO1,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "LDO2",
+		.id = WM8350_LDO_2,
+		.ops = &wm8350_ldo_ops,
+		.irq = WM8350_IRQ_UV_LDO2,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "LDO3",
+		.id = WM8350_LDO_3,
+		.ops = &wm8350_ldo_ops,
+		.irq = WM8350_IRQ_UV_LDO3,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "LDO4",
+		.id = WM8350_LDO_4,
+		.ops = &wm8350_ldo_ops,
+		.irq = WM8350_IRQ_UV_LDO4,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "ISINKA",
+		.id = WM8350_ISINK_A,
+		.ops = &wm8350_isink_ops,
+		.irq = WM8350_IRQ_CS1,
+		.type = REGULATOR_CURRENT,
+		.owner = THIS_MODULE,
+	 },
+	{
+		.name = "ISINKB",
+		.id = WM8350_ISINK_B,
+		.ops = &wm8350_isink_ops,
+		.irq = WM8350_IRQ_CS2,
+		.type = REGULATOR_CURRENT,
+		.owner = THIS_MODULE,
+	 },
+};
+
+static void pmic_uv_handler(struct wm8350 *wm8350, int irq, void *data)
+{
+	struct regulator_dev *rdev = (struct regulator_dev *)data;
+
+	if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2)
+		regulator_notifier_call_chain(rdev,
+					      REGULATOR_EVENT_REGULATION_OUT,
+					      wm8350);
+	else
+		regulator_notifier_call_chain(rdev,
+					      REGULATOR_EVENT_UNDER_VOLTAGE,
+					      wm8350);
+}
+
+static int wm8350_regulator_probe(struct platform_device *pdev)
+{
+	struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev);
+	struct regulator_dev *rdev;
+	int ret;
+	u16 val;
+
+	if (pdev->id < WM8350_DCDC_1 || pdev->id > WM8350_ISINK_B)
+		return -ENODEV;
+
+	/* do any regulatior specific init */
+	switch (pdev->id) {
+	case WM8350_DCDC_1:
+		val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER);
+		wm8350->pmic.dcdc1_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+		break;
+	case WM8350_DCDC_3:
+		val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER);
+		wm8350->pmic.dcdc3_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+		break;
+	case WM8350_DCDC_4:
+		val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER);
+		wm8350->pmic.dcdc4_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+		break;
+	case WM8350_DCDC_6:
+		val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER);
+		wm8350->pmic.dcdc6_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+		break;
+	}
+
+
+	/* register regulator */
+	rdev = regulator_register(&wm8350_reg[pdev->id], &pdev->dev,
+				  dev_get_drvdata(&pdev->dev));
+	if (IS_ERR(rdev)) {
+		dev_err(&pdev->dev, "failed to register %s\n",
+			wm8350_reg[pdev->id].name);
+		return PTR_ERR(rdev);
+	}
+
+	/* register regulator IRQ */
+	ret = wm8350_register_irq(wm8350, wm8350_reg[pdev->id].irq,
+				  pmic_uv_handler, rdev);
+	if (ret < 0) {
+		regulator_unregister(rdev);
+		dev_err(&pdev->dev, "failed to register regulator %s IRQ\n",
+			wm8350_reg[pdev->id].name);
+		return ret;
+	}
+
+	wm8350_unmask_irq(wm8350, wm8350_reg[pdev->id].irq);
+
+	return 0;
+}
+
+static int wm8350_regulator_remove(struct platform_device *pdev)
+{
+	struct regulator_dev *rdev = platform_get_drvdata(pdev);
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+
+	wm8350_mask_irq(wm8350, wm8350_reg[pdev->id].irq);
+	wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq);
+
+	regulator_unregister(rdev);
+
+	return 0;
+}
+
+int wm8350_register_regulator(struct wm8350 *wm8350, int reg,
+			      struct regulator_init_data *initdata)
+{
+	struct platform_device *pdev;
+	int ret;
+
+	if (wm8350->pmic.pdev[reg])
+		return -EBUSY;
+
+	pdev = platform_device_alloc("wm8350-regulator", reg);
+	if (!pdev)
+		return -ENOMEM;
+
+	wm8350->pmic.pdev[reg] = pdev;
+
+	initdata->driver_data = wm8350;
+
+	pdev->dev.platform_data = initdata;
+	pdev->dev.parent = wm8350->dev;
+	platform_set_drvdata(pdev, wm8350);
+
+	ret = platform_device_add(pdev);
+
+	if (ret != 0) {
+		dev_err(wm8350->dev, "Failed to register regulator %d: %d\n",
+			reg, ret);
+		platform_device_del(pdev);
+		wm8350->pmic.pdev[reg] = NULL;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_register_regulator);
+
+static struct platform_driver wm8350_regulator_driver = {
+	.probe = wm8350_regulator_probe,
+	.remove = wm8350_regulator_remove,
+	.driver		= {
+		.name	= "wm8350-regulator",
+	},
+};
+
+static int __init wm8350_regulator_init(void)
+{
+	return platform_driver_register(&wm8350_regulator_driver);
+}
+subsys_initcall(wm8350_regulator_init);
+
+static void __exit wm8350_regulator_exit(void)
+{
+	platform_driver_unregister(&wm8350_regulator_driver);
+}
+module_exit(wm8350_regulator_exit);
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood");
+MODULE_DESCRIPTION("WM8350 voltage and current regulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c
new file mode 100644
index 000000000000..48b372e038a8
--- /dev/null
+++ b/drivers/regulator/wm8400-regulator.c
@@ -0,0 +1,368 @@
+/*
+ * Regulator support 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.
+ *
+ */
+
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/regulator/driver.h>
+#include <linux/mfd/wm8400-private.h>
+
+static int wm8400_ldo_is_enabled(struct regulator_dev *dev)
+{
+	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+	u16 val;
+
+	val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev));
+	return (val & WM8400_LDO1_ENA) != 0;
+}
+
+static int wm8400_ldo_enable(struct regulator_dev *dev)
+{
+	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+
+	return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
+			       WM8400_LDO1_ENA, WM8400_LDO1_ENA);
+}
+
+static int wm8400_ldo_disable(struct regulator_dev *dev)
+{
+	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+
+	return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
+			       WM8400_LDO1_ENA, 0);
+}
+
+static int wm8400_ldo_get_voltage(struct regulator_dev *dev)
+{
+	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+	u16 val;
+
+	val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev));
+	val &= WM8400_LDO1_VSEL_MASK;
+
+	if (val < 15)
+		return 900000 + (val * 50000);
+	else
+		return 1600000 + ((val - 14) * 100000);
+}
+
+static int wm8400_ldo_set_voltage(struct regulator_dev *dev,
+				  int min_uV, int max_uV)
+{
+	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+	u16 val;
+
+	if (min_uV < 900000 || min_uV > 3300000)
+		return -EINVAL;
+
+	if (min_uV < 1700000) {
+		/* Steps of 50mV from 900mV;  */
+		val = (min_uV - 850001) / 50000;
+
+		if ((val * 50000) + 900000 > max_uV)
+			return -EINVAL;
+		BUG_ON((val * 50000) + 900000 < min_uV);
+	} else {
+		/* Steps of 100mV from 1700mV */
+		val = ((min_uV - 1600001) / 100000);
+
+		if ((val * 100000) + 1700000 > max_uV)
+			return -EINVAL;
+		BUG_ON((val * 100000) + 1700000 < min_uV);
+
+		val += 0xf;
+	}
+
+	return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
+			       WM8400_LDO1_VSEL_MASK, val);
+}
+
+static struct regulator_ops wm8400_ldo_ops = {
+	.is_enabled = wm8400_ldo_is_enabled,
+	.enable = wm8400_ldo_enable,
+	.disable = wm8400_ldo_disable,
+	.get_voltage = wm8400_ldo_get_voltage,
+	.set_voltage = wm8400_ldo_set_voltage,
+};
+
+static int wm8400_dcdc_is_enabled(struct regulator_dev *dev)
+{
+	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+	u16 val;
+
+	val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset);
+	return (val & WM8400_DC1_ENA) != 0;
+}
+
+static int wm8400_dcdc_enable(struct regulator_dev *dev)
+{
+	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+
+	return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+			       WM8400_DC1_ENA, WM8400_DC1_ENA);
+}
+
+static int wm8400_dcdc_disable(struct regulator_dev *dev)
+{
+	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+
+	return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+			       WM8400_DC1_ENA, 0);
+}
+
+static int wm8400_dcdc_get_voltage(struct regulator_dev *dev)
+{
+	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+	u16 val;
+	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+
+	val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset);
+	val &= WM8400_DC1_VSEL_MASK;
+
+	return 850000 + (25000 * val);
+}
+
+static int wm8400_dcdc_set_voltage(struct regulator_dev *dev,
+				  int min_uV, int max_uV)
+{
+	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+	u16 val;
+	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+
+	if (min_uV < 850000)
+		return -EINVAL;
+
+	val = (min_uV - 825001) / 25000;
+
+	if (850000 + (25000 * val) > max_uV)
+		return -EINVAL;
+	BUG_ON(850000 + (25000 * val) < min_uV);
+
+	return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+			       WM8400_DC1_VSEL_MASK, val);
+}
+
+static unsigned int wm8400_dcdc_get_mode(struct regulator_dev *dev)
+{
+	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+	u16 data[2];
+	int ret;
+
+	ret = wm8400_block_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset, 2,
+				data);
+	if (ret != 0)
+		return 0;
+
+	/* Datasheet: hibernate */
+	if (data[0] & WM8400_DC1_SLEEP)
+		return REGULATOR_MODE_STANDBY;
+
+	/* Datasheet: standby */
+	if (!(data[0] & WM8400_DC1_ACTIVE))
+		return REGULATOR_MODE_IDLE;
+
+	/* Datasheet: active with or without force PWM */
+	if (data[1] & WM8400_DC1_FRC_PWM)
+		return REGULATOR_MODE_FAST;
+	else
+		return REGULATOR_MODE_NORMAL;
+}
+
+static int wm8400_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode)
+{
+	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+	int ret;
+
+	switch (mode) {
+	case REGULATOR_MODE_FAST:
+		/* Datasheet: active with force PWM */
+		ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_2 + offset,
+				      WM8400_DC1_FRC_PWM, WM8400_DC1_FRC_PWM);
+		if (ret != 0)
+			return ret;
+
+		return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+				       WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP,
+				       WM8400_DC1_ACTIVE);
+
+	case REGULATOR_MODE_NORMAL:
+		/* Datasheet: active */
+		ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_2 + offset,
+				      WM8400_DC1_FRC_PWM, 0);
+		if (ret != 0)
+			return ret;
+
+		return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+				       WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP,
+				       WM8400_DC1_ACTIVE);
+
+	case REGULATOR_MODE_IDLE:
+		/* Datasheet: standby */
+		ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+				      WM8400_DC1_ACTIVE, 0);
+		if (ret != 0)
+			return ret;
+		return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+				       WM8400_DC1_SLEEP, 0);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static unsigned int wm8400_dcdc_get_optimum_mode(struct regulator_dev *dev,
+						 int input_uV, int output_uV,
+						 int load_uA)
+{
+	return REGULATOR_MODE_NORMAL;
+}
+
+static struct regulator_ops wm8400_dcdc_ops = {
+	.is_enabled = wm8400_dcdc_is_enabled,
+	.enable = wm8400_dcdc_enable,
+	.disable = wm8400_dcdc_disable,
+	.get_voltage = wm8400_dcdc_get_voltage,
+	.set_voltage = wm8400_dcdc_set_voltage,
+	.get_mode = wm8400_dcdc_get_mode,
+	.set_mode = wm8400_dcdc_set_mode,
+	.get_optimum_mode = wm8400_dcdc_get_optimum_mode,
+};
+
+static struct regulator_desc regulators[] = {
+	{
+		.name = "LDO1",
+		.id = WM8400_LDO1,
+		.ops = &wm8400_ldo_ops,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "LDO2",
+		.id = WM8400_LDO2,
+		.ops = &wm8400_ldo_ops,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "LDO3",
+		.id = WM8400_LDO3,
+		.ops = &wm8400_ldo_ops,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "LDO4",
+		.id = WM8400_LDO4,
+		.ops = &wm8400_ldo_ops,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "DCDC1",
+		.id = WM8400_DCDC1,
+		.ops = &wm8400_dcdc_ops,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "DCDC2",
+		.id = WM8400_DCDC2,
+		.ops = &wm8400_dcdc_ops,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init wm8400_regulator_probe(struct platform_device *pdev)
+{
+	struct regulator_dev *rdev;
+
+	rdev = regulator_register(&regulators[pdev->id], &pdev->dev,
+		pdev->dev.driver_data);
+
+	if (IS_ERR(rdev))
+		return PTR_ERR(rdev);
+
+	return 0;
+}
+
+static int __devexit wm8400_regulator_remove(struct platform_device *pdev)
+{
+	struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+	regulator_unregister(rdev);
+
+	return 0;
+}
+
+static struct platform_driver wm8400_regulator_driver = {
+	.driver = {
+		.name = "wm8400-regulator",
+	},
+	.probe = wm8400_regulator_probe,
+	.remove = __devexit_p(wm8400_regulator_remove),
+};
+
+/**
+ * wm8400_register_regulator - enable software control of a WM8400 regulator
+ *
+ * This function enables software control of a WM8400 regulator via
+ * the regulator API.  It is intended to be called from the
+ * platform_init() callback of the WM8400 MFD driver.
+ *
+ * @param dev      The WM8400 device to operate on.
+ * @param reg      The regulator to control.
+ * @param initdata Regulator initdata for the regulator.
+ */
+int wm8400_register_regulator(struct device *dev, int reg,
+			      struct regulator_init_data *initdata)
+{
+	struct wm8400 *wm8400 = dev->driver_data;
+
+	if (wm8400->regulators[reg].name)
+		return -EBUSY;
+
+	initdata->driver_data = wm8400;
+
+	wm8400->regulators[reg].name = "wm8400-regulator";
+	wm8400->regulators[reg].id = reg;
+	wm8400->regulators[reg].dev.parent = dev;
+	wm8400->regulators[reg].dev.driver_data = wm8400;
+	wm8400->regulators[reg].dev.platform_data = initdata;
+
+	return platform_device_register(&wm8400->regulators[reg]);
+}
+EXPORT_SYMBOL_GPL(wm8400_register_regulator);
+
+static int __init wm8400_regulator_init(void)
+{
+	return platform_driver_register(&wm8400_regulator_driver);
+}
+module_init(wm8400_regulator_init);
+
+static void __exit wm8400_regulator_exit(void)
+{
+	platform_driver_unregister(&wm8400_regulator_driver);
+}
+module_exit(wm8400_regulator_exit);
+
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("WM8400 regulator driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8400-regulator");
diff --git a/include/linux/mfd/wm8350/audio.h b/include/linux/mfd/wm8350/audio.h
new file mode 100644
index 000000000000..217bb22ebb8e
--- /dev/null
+++ b/include/linux/mfd/wm8350/audio.h
@@ -0,0 +1,598 @@
+/*
+ * audio.h  --  Audio Driver for Wolfson WM8350 PMIC
+ *
+ * Copyright 2007 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#ifndef __LINUX_MFD_WM8350_AUDIO_H_
+#define __LINUX_MFD_WM8350_AUDIO_H_
+
+#include <linux/platform_device.h>
+
+#define WM8350_CLOCK_CONTROL_1                  0x28
+#define WM8350_CLOCK_CONTROL_2                  0x29
+#define WM8350_FLL_CONTROL_1                    0x2A
+#define WM8350_FLL_CONTROL_2                    0x2B
+#define WM8350_FLL_CONTROL_3                    0x2C
+#define WM8350_FLL_CONTROL_4                    0x2D
+#define WM8350_DAC_CONTROL                      0x30
+#define WM8350_DAC_DIGITAL_VOLUME_L             0x32
+#define WM8350_DAC_DIGITAL_VOLUME_R             0x33
+#define WM8350_DAC_LR_RATE                      0x35
+#define WM8350_DAC_CLOCK_CONTROL                0x36
+#define WM8350_DAC_MUTE                         0x3A
+#define WM8350_DAC_MUTE_VOLUME                  0x3B
+#define WM8350_DAC_SIDE                         0x3C
+#define WM8350_ADC_CONTROL                      0x40
+#define WM8350_ADC_DIGITAL_VOLUME_L             0x42
+#define WM8350_ADC_DIGITAL_VOLUME_R             0x43
+#define WM8350_ADC_DIVIDER                      0x44
+#define WM8350_ADC_LR_RATE                      0x46
+#define WM8350_INPUT_CONTROL                    0x48
+#define WM8350_IN3_INPUT_CONTROL                0x49
+#define WM8350_MIC_BIAS_CONTROL                 0x4A
+#define WM8350_OUTPUT_CONTROL                   0x4C
+#define WM8350_JACK_DETECT                      0x4D
+#define WM8350_ANTI_POP_CONTROL                 0x4E
+#define WM8350_LEFT_INPUT_VOLUME                0x50
+#define WM8350_RIGHT_INPUT_VOLUME               0x51
+#define WM8350_LEFT_MIXER_CONTROL               0x58
+#define WM8350_RIGHT_MIXER_CONTROL              0x59
+#define WM8350_OUT3_MIXER_CONTROL               0x5C
+#define WM8350_OUT4_MIXER_CONTROL               0x5D
+#define WM8350_OUTPUT_LEFT_MIXER_VOLUME         0x60
+#define WM8350_OUTPUT_RIGHT_MIXER_VOLUME        0x61
+#define WM8350_INPUT_MIXER_VOLUME_L             0x62
+#define WM8350_INPUT_MIXER_VOLUME_R             0x63
+#define WM8350_INPUT_MIXER_VOLUME               0x64
+#define WM8350_LOUT1_VOLUME                     0x68
+#define WM8350_ROUT1_VOLUME                     0x69
+#define WM8350_LOUT2_VOLUME                     0x6A
+#define WM8350_ROUT2_VOLUME                     0x6B
+#define WM8350_BEEP_VOLUME                      0x6F
+#define WM8350_AI_FORMATING                     0x70
+#define WM8350_ADC_DAC_COMP                     0x71
+#define WM8350_AI_ADC_CONTROL                   0x72
+#define WM8350_AI_DAC_CONTROL                   0x73
+#define WM8350_AIF_TEST                         0x74
+#define WM8350_JACK_PIN_STATUS                  0xE7
+
+/* Bit values for R08 (0x08) */
+#define WM8350_CODEC_ISEL_1_5                   0	/* x1.5 */
+#define WM8350_CODEC_ISEL_1_0                   1	/* x1.0 */
+#define WM8350_CODEC_ISEL_0_75                  2	/* x0.75 */
+#define WM8350_CODEC_ISEL_0_5                   3	/* x0.5 */
+
+#define WM8350_VMID_OFF                         0
+#define WM8350_VMID_500K                        1
+#define WM8350_VMID_100K                        2
+#define WM8350_VMID_10K                         3
+
+/*
+ * R40 (0x28) - Clock Control 1
+ */
+#define WM8350_TOCLK_RATE                       0x4000
+#define WM8350_MCLK_SEL                         0x0800
+#define WM8350_MCLK_DIV_MASK                    0x0100
+#define WM8350_BCLK_DIV_MASK                    0x00F0
+#define WM8350_OPCLK_DIV_MASK                   0x0007
+
+/*
+ * R41 (0x29) - Clock Control 2
+ */
+#define WM8350_LRC_ADC_SEL                      0x8000
+#define WM8350_MCLK_DIR                         0x0001
+
+/*
+ * R42 (0x2A) - FLL Control 1
+ */
+#define WM8350_FLL_DITHER_WIDTH_MASK            0x3000
+#define WM8350_FLL_DITHER_HP                    0x0800
+#define WM8350_FLL_OUTDIV_MASK                  0x0700
+#define WM8350_FLL_RSP_RATE_MASK                0x00F0
+#define WM8350_FLL_RATE_MASK                    0x0007
+
+/*
+ * R43 (0x2B) - FLL Control 2
+ */
+#define WM8350_FLL_RATIO_MASK                   0xF800
+#define WM8350_FLL_N_MASK                       0x03FF
+
+/*
+ * R44 (0x2C) - FLL Control 3
+ */
+#define WM8350_FLL_K_MASK                       0xFFFF
+
+/*
+ * R45 (0x2D) - FLL Control 4
+ */
+#define WM8350_FLL_FRAC                         0x0020
+#define WM8350_FLL_SLOW_LOCK_REF                0x0010
+#define WM8350_FLL_CLK_SRC_MASK                 0x0003
+
+/*
+ * R48 (0x30) - DAC Control
+ */
+#define WM8350_DAC_MONO                         0x2000
+#define WM8350_AIF_LRCLKRATE                    0x1000
+#define WM8350_DEEMP_MASK                       0x0030
+#define WM8350_DACL_DATINV                      0x0002
+#define WM8350_DACR_DATINV                      0x0001
+
+/*
+ * R50 (0x32) - DAC Digital Volume L
+ */
+#define WM8350_DAC_VU                           0x0100
+#define WM8350_DACL_VOL_MASK                    0x00FF
+
+/*
+ * R51 (0x33) - DAC Digital Volume R
+ */
+#define WM8350_DAC_VU                           0x0100
+#define WM8350_DACR_VOL_MASK                    0x00FF
+
+/*
+ * R53 (0x35) - DAC LR Rate
+ */
+#define WM8350_DACLRC_ENA                       0x0800
+#define WM8350_DACLRC_RATE_MASK                 0x07FF
+
+/*
+ * R54 (0x36) - DAC Clock Control
+ */
+#define WM8350_DACCLK_POL                       0x0010
+#define WM8350_DAC_CLKDIV_MASK                  0x0007
+
+/*
+ * R58 (0x3A) - DAC Mute
+ */
+#define WM8350_DAC_MUTE_ENA                     0x4000
+
+/*
+ * R59 (0x3B) - DAC Mute Volume
+ */
+#define WM8350_DAC_MUTEMODE                     0x4000
+#define WM8350_DAC_MUTERATE                     0x2000
+#define WM8350_DAC_SB_FILT                      0x1000
+
+/*
+ * R60 (0x3C) - DAC Side
+ */
+#define WM8350_ADC_TO_DACL_MASK                 0x3000
+#define WM8350_ADC_TO_DACR_MASK                 0x0C00
+
+/*
+ * R64 (0x40) - ADC Control
+ */
+#define WM8350_ADC_HPF_CUT_MASK                 0x0300
+#define WM8350_ADCL_DATINV                      0x0002
+#define WM8350_ADCR_DATINV                      0x0001
+
+/*
+ * R66 (0x42) - ADC Digital Volume L
+ */
+#define WM8350_ADC_VU                           0x0100
+#define WM8350_ADCL_VOL_MASK                    0x00FF
+
+/*
+ * R67 (0x43) - ADC Digital Volume R
+ */
+#define WM8350_ADC_VU                           0x0100
+#define WM8350_ADCR_VOL_MASK                    0x00FF
+
+/*
+ * R68 (0x44) - ADC Divider
+ */
+#define WM8350_ADCL_DAC_SVOL_MASK               0x0F00
+#define WM8350_ADCR_DAC_SVOL_MASK               0x00F0
+#define WM8350_ADCCLK_POL                       0x0008
+#define WM8350_ADC_CLKDIV_MASK                  0x0007
+
+/*
+ * R70 (0x46) - ADC LR Rate
+ */
+#define WM8350_ADCLRC_ENA                       0x0800
+#define WM8350_ADCLRC_RATE_MASK                 0x07FF
+
+/*
+ * R72 (0x48) - Input Control
+ */
+#define WM8350_IN2R_ENA                         0x0400
+#define WM8350_IN1RN_ENA                        0x0200
+#define WM8350_IN1RP_ENA                        0x0100
+#define WM8350_IN2L_ENA                         0x0004
+#define WM8350_IN1LN_ENA                        0x0002
+#define WM8350_IN1LP_ENA                        0x0001
+
+/*
+ * R73 (0x49) - IN3 Input Control
+ */
+#define WM8350_IN3R_SHORT                       0x4000
+#define WM8350_IN3L_SHORT                       0x0040
+
+/*
+ * R74 (0x4A) - Mic Bias Control
+ */
+#define WM8350_MICBSEL                          0x4000
+#define WM8350_MCDTHR_MASK                      0x001C
+#define WM8350_MCDSCTHR_MASK                    0x0003
+
+/*
+ * R76 (0x4C) - Output Control
+ */
+#define WM8350_OUT4_VROI                        0x0800
+#define WM8350_OUT3_VROI                        0x0400
+#define WM8350_OUT2_VROI                        0x0200
+#define WM8350_OUT1_VROI                        0x0100
+#define WM8350_OUT2_FB                          0x0004
+#define WM8350_OUT1_FB                          0x0001
+
+/*
+ * R77 (0x4D) - Jack Detect
+ */
+#define WM8350_JDL_ENA                          0x8000
+#define WM8350_JDR_ENA                          0x4000
+
+/*
+ * R78 (0x4E) - Anti Pop Control
+ */
+#define WM8350_ANTI_POP_MASK                    0x0300
+#define WM8350_DIS_OP_LN4_MASK                  0x00C0
+#define WM8350_DIS_OP_LN3_MASK                  0x0030
+#define WM8350_DIS_OP_OUT2_MASK                 0x000C
+#define WM8350_DIS_OP_OUT1_MASK                 0x0003
+
+/*
+ * R80 (0x50) - Left Input Volume
+ */
+#define WM8350_INL_MUTE                         0x4000
+#define WM8350_INL_ZC                           0x2000
+#define WM8350_IN_VU                            0x0100
+#define WM8350_INL_VOL_MASK                     0x00FC
+
+/*
+ * R81 (0x51) - Right Input Volume
+ */
+#define WM8350_INR_MUTE                         0x4000
+#define WM8350_INR_ZC                           0x2000
+#define WM8350_IN_VU                            0x0100
+#define WM8350_INR_VOL_MASK                     0x00FC
+
+/*
+ * R88 (0x58) - Left Mixer Control
+ */
+#define WM8350_DACR_TO_MIXOUTL                  0x1000
+#define WM8350_DACL_TO_MIXOUTL                  0x0800
+#define WM8350_IN3L_TO_MIXOUTL                  0x0004
+#define WM8350_INR_TO_MIXOUTL                   0x0002
+#define WM8350_INL_TO_MIXOUTL                   0x0001
+
+/*
+ * R89 (0x59) - Right Mixer Control
+ */
+#define WM8350_DACR_TO_MIXOUTR                  0x1000
+#define WM8350_DACL_TO_MIXOUTR                  0x0800
+#define WM8350_IN3R_TO_MIXOUTR                  0x0008
+#define WM8350_INR_TO_MIXOUTR                   0x0002
+#define WM8350_INL_TO_MIXOUTR                   0x0001
+
+/*
+ * R92 (0x5C) - OUT3 Mixer Control
+ */
+#define WM8350_DACL_TO_OUT3                     0x0800
+#define WM8350_MIXINL_TO_OUT3                   0x0100
+#define WM8350_OUT4_TO_OUT3                     0x0008
+#define WM8350_MIXOUTL_TO_OUT3                  0x0001
+
+/*
+ * R93 (0x5D) - OUT4 Mixer Control
+ */
+#define WM8350_DACR_TO_OUT4                     0x1000
+#define WM8350_DACL_TO_OUT4                     0x0800
+#define WM8350_OUT4_ATTN                        0x0400
+#define WM8350_MIXINR_TO_OUT4                   0x0200
+#define WM8350_OUT3_TO_OUT4                     0x0004
+#define WM8350_MIXOUTR_TO_OUT4                  0x0002
+#define WM8350_MIXOUTL_TO_OUT4                  0x0001
+
+/*
+ * R96 (0x60) - Output Left Mixer Volume
+ */
+#define WM8350_IN3L_MIXOUTL_VOL_MASK            0x0E00
+#define WM8350_IN3L_MIXOUTL_VOL_SHIFT                9
+#define WM8350_INR_MIXOUTL_VOL_MASK             0x00E0
+#define WM8350_INR_MIXOUTL_VOL_SHIFT                 5
+#define WM8350_INL_MIXOUTL_VOL_MASK             0x000E
+#define WM8350_INL_MIXOUTL_VOL_SHIFT                 1
+
+/* Bit values for R96 (0x60) */
+#define WM8350_IN3L_MIXOUTL_VOL_OFF                  0
+#define WM8350_IN3L_MIXOUTL_VOL_M12DB                1
+#define WM8350_IN3L_MIXOUTL_VOL_M9DB                 2
+#define WM8350_IN3L_MIXOUTL_VOL_M6DB                 3
+#define WM8350_IN3L_MIXOUTL_VOL_M3DB                 4
+#define WM8350_IN3L_MIXOUTL_VOL_0DB                  5
+#define WM8350_IN3L_MIXOUTL_VOL_3DB                  6
+#define WM8350_IN3L_MIXOUTL_VOL_6DB                  7
+
+#define WM8350_INR_MIXOUTL_VOL_OFF                   0
+#define WM8350_INR_MIXOUTL_VOL_M12DB                 1
+#define WM8350_INR_MIXOUTL_VOL_M9DB                  2
+#define WM8350_INR_MIXOUTL_VOL_M6DB                  3
+#define WM8350_INR_MIXOUTL_VOL_M3DB                  4
+#define WM8350_INR_MIXOUTL_VOL_0DB                   5
+#define WM8350_INR_MIXOUTL_VOL_3DB                   6
+#define WM8350_INR_MIXOUTL_VOL_6DB                   7
+
+#define WM8350_INL_MIXOUTL_VOL_OFF                   0
+#define WM8350_INL_MIXOUTL_VOL_M12DB                 1
+#define WM8350_INL_MIXOUTL_VOL_M9DB                  2
+#define WM8350_INL_MIXOUTL_VOL_M6DB                  3
+#define WM8350_INL_MIXOUTL_VOL_M3DB                  4
+#define WM8350_INL_MIXOUTL_VOL_0DB                   5
+#define WM8350_INL_MIXOUTL_VOL_3DB                   6
+#define WM8350_INL_MIXOUTL_VOL_6DB                   7
+
+/*
+ * R97 (0x61) - Output Right Mixer Volume
+ */
+#define WM8350_IN3R_MIXOUTR_VOL_MASK            0xE000
+#define WM8350_IN3R_MIXOUTR_VOL_SHIFT               13
+#define WM8350_INR_MIXOUTR_VOL_MASK             0x00E0
+#define WM8350_INR_MIXOUTR_VOL_SHIFT                 5
+#define WM8350_INL_MIXOUTR_VOL_MASK             0x000E
+#define WM8350_INL_MIXOUTR_VOL_SHIFT                 1
+
+/* Bit values for R96 (0x60) */
+#define WM8350_IN3R_MIXOUTR_VOL_OFF                  0
+#define WM8350_IN3R_MIXOUTR_VOL_M12DB                1
+#define WM8350_IN3R_MIXOUTR_VOL_M9DB                 2
+#define WM8350_IN3R_MIXOUTR_VOL_M6DB                 3
+#define WM8350_IN3R_MIXOUTR_VOL_M3DB                 4
+#define WM8350_IN3R_MIXOUTR_VOL_0DB                  5
+#define WM8350_IN3R_MIXOUTR_VOL_3DB                  6
+#define WM8350_IN3R_MIXOUTR_VOL_6DB                  7
+
+#define WM8350_INR_MIXOUTR_VOL_OFF                   0
+#define WM8350_INR_MIXOUTR_VOL_M12DB                 1
+#define WM8350_INR_MIXOUTR_VOL_M9DB                  2
+#define WM8350_INR_MIXOUTR_VOL_M6DB                  3
+#define WM8350_INR_MIXOUTR_VOL_M3DB                  4
+#define WM8350_INR_MIXOUTR_VOL_0DB                   5
+#define WM8350_INR_MIXOUTR_VOL_3DB                   6
+#define WM8350_INR_MIXOUTR_VOL_6DB                   7
+
+#define WM8350_INL_MIXOUTR_VOL_OFF                   0
+#define WM8350_INL_MIXOUTR_VOL_M12DB                 1
+#define WM8350_INL_MIXOUTR_VOL_M9DB                  2
+#define WM8350_INL_MIXOUTR_VOL_M6DB                  3
+#define WM8350_INL_MIXOUTR_VOL_M3DB                  4
+#define WM8350_INL_MIXOUTR_VOL_0DB                   5
+#define WM8350_INL_MIXOUTR_VOL_3DB                   6
+#define WM8350_INL_MIXOUTR_VOL_6DB                   7
+
+/*
+ * R98 (0x62) - Input Mixer Volume L
+ */
+#define WM8350_IN3L_MIXINL_VOL_MASK             0x0E00
+#define WM8350_IN2L_MIXINL_VOL_MASK             0x000E
+#define WM8350_INL_MIXINL_VOL                   0x0001
+
+/*
+ * R99 (0x63) - Input Mixer Volume R
+ */
+#define WM8350_IN3R_MIXINR_VOL_MASK             0xE000
+#define WM8350_IN2R_MIXINR_VOL_MASK             0x00E0
+#define WM8350_INR_MIXINR_VOL                   0x0001
+
+/*
+ * R100 (0x64) - Input Mixer Volume
+ */
+#define WM8350_OUT4_MIXIN_DST                   0x8000
+#define WM8350_OUT4_MIXIN_VOL_MASK              0x000E
+
+/*
+ * R104 (0x68) - LOUT1 Volume
+ */
+#define WM8350_OUT1L_MUTE                       0x4000
+#define WM8350_OUT1L_ZC                         0x2000
+#define WM8350_OUT1_VU                          0x0100
+#define WM8350_OUT1L_VOL_MASK                   0x00FC
+#define WM8350_OUT1L_VOL_SHIFT                       2
+
+/*
+ * R105 (0x69) - ROUT1 Volume
+ */
+#define WM8350_OUT1R_MUTE                       0x4000
+#define WM8350_OUT1R_ZC                         0x2000
+#define WM8350_OUT1_VU                          0x0100
+#define WM8350_OUT1R_VOL_MASK                   0x00FC
+#define WM8350_OUT1R_VOL_SHIFT                       2
+
+/*
+ * R106 (0x6A) - LOUT2 Volume
+ */
+#define WM8350_OUT2L_MUTE                       0x4000
+#define WM8350_OUT2L_ZC                         0x2000
+#define WM8350_OUT2_VU                          0x0100
+#define WM8350_OUT2L_VOL_MASK                   0x00FC
+
+/*
+ * R107 (0x6B) - ROUT2 Volume
+ */
+#define WM8350_OUT2R_MUTE                       0x4000
+#define WM8350_OUT2R_ZC                         0x2000
+#define WM8350_OUT2R_INV                        0x0400
+#define WM8350_OUT2R_INV_MUTE                   0x0200
+#define WM8350_OUT2_VU                          0x0100
+#define WM8350_OUT2R_VOL_MASK                   0x00FC
+
+/*
+ * R111 (0x6F) - BEEP Volume
+ */
+#define WM8350_IN3R_OUT2R_VOL_MASK              0x00E0
+
+/*
+ * R112 (0x70) - AI Formating
+ */
+#define WM8350_AIF_BCLK_INV                     0x8000
+#define WM8350_AIF_TRI                          0x2000
+#define WM8350_AIF_LRCLK_INV                    0x1000
+#define WM8350_AIF_WL_MASK                      0x0C00
+#define WM8350_AIF_FMT_MASK                     0x0300
+
+/*
+ * R113 (0x71) - ADC DAC COMP
+ */
+#define WM8350_DAC_COMP                         0x0080
+#define WM8350_DAC_COMPMODE                     0x0040
+#define WM8350_ADC_COMP                         0x0020
+#define WM8350_ADC_COMPMODE                     0x0010
+#define WM8350_LOOPBACK                         0x0001
+
+/*
+ * R114 (0x72) - AI ADC Control
+ */
+#define WM8350_AIFADC_PD                        0x0080
+#define WM8350_AIFADCL_SRC                      0x0040
+#define WM8350_AIFADCR_SRC                      0x0020
+#define WM8350_AIFADC_TDM_CHAN                  0x0010
+#define WM8350_AIFADC_TDM                       0x0008
+
+/*
+ * R115 (0x73) - AI DAC Control
+ */
+#define WM8350_BCLK_MSTR                        0x4000
+#define WM8350_AIFDAC_PD                        0x0080
+#define WM8350_DACL_SRC                         0x0040
+#define WM8350_DACR_SRC                         0x0020
+#define WM8350_AIFDAC_TDM_CHAN                  0x0010
+#define WM8350_AIFDAC_TDM                       0x0008
+#define WM8350_DAC_BOOST_MASK                   0x0003
+
+/*
+ * R116 (0x74) - AIF Test
+ */
+#define WM8350_CODEC_BYP                        0x4000
+#define WM8350_AIFADC_WR_TST                    0x2000
+#define WM8350_AIFADC_RD_TST                    0x1000
+#define WM8350_AIFDAC_WR_TST                    0x0800
+#define WM8350_AIFDAC_RD_TST                    0x0400
+#define WM8350_AIFADC_ASYN                      0x0020
+#define WM8350_AIFDAC_ASYN                      0x0010
+
+/*
+ * R231 (0xE7) - Jack Status
+ */
+#define WM8350_JACK_R_LVL                       0x0400
+
+/*
+ * WM8350 Platform setup
+ */
+#define WM8350_S_CURVE_NONE			0x0
+#define WM8350_S_CURVE_FAST			0x1
+#define WM8350_S_CURVE_MEDIUM			0x2
+#define WM8350_S_CURVE_SLOW			0x3
+
+#define WM8350_DISCHARGE_OFF			0x0
+#define WM8350_DISCHARGE_FAST			0x1
+#define WM8350_DISCHARGE_MEDIUM			0x2
+#define WM8350_DISCHARGE_SLOW			0x3
+
+#define WM8350_TIE_OFF_500R			0x0
+#define WM8350_TIE_OFF_30K			0x1
+
+/*
+ * Clock sources & directions
+ */
+#define WM8350_SYSCLK				0
+
+#define WM8350_MCLK_SEL_PLL_MCLK		0
+#define WM8350_MCLK_SEL_PLL_DAC			1
+#define WM8350_MCLK_SEL_PLL_ADC			2
+#define WM8350_MCLK_SEL_PLL_32K			3
+#define WM8350_MCLK_SEL_MCLK			5
+
+#define WM8350_MCLK_DIR_OUT			0
+#define WM8350_MCLK_DIR_IN			1
+
+/* clock divider id's */
+#define WM8350_ADC_CLKDIV			0
+#define WM8350_DAC_CLKDIV			1
+#define WM8350_BCLK_CLKDIV			2
+#define WM8350_OPCLK_CLKDIV			3
+#define WM8350_TO_CLKDIV			4
+#define WM8350_SYS_CLKDIV			5
+#define WM8350_DACLR_CLKDIV			6
+#define WM8350_ADCLR_CLKDIV			7
+
+/* ADC clock dividers */
+#define WM8350_ADCDIV_1				0x0
+#define WM8350_ADCDIV_1_5			0x1
+#define WM8350_ADCDIV_2				0x2
+#define WM8350_ADCDIV_3				0x3
+#define WM8350_ADCDIV_4				0x4
+#define WM8350_ADCDIV_5_5			0x5
+#define WM8350_ADCDIV_6				0x6
+
+/* ADC clock dividers */
+#define WM8350_DACDIV_1				0x0
+#define WM8350_DACDIV_1_5			0x1
+#define WM8350_DACDIV_2				0x2
+#define WM8350_DACDIV_3				0x3
+#define WM8350_DACDIV_4				0x4
+#define WM8350_DACDIV_5_5			0x5
+#define WM8350_DACDIV_6				0x6
+
+/* BCLK clock dividers */
+#define WM8350_BCLK_DIV_1			(0x0 << 4)
+#define WM8350_BCLK_DIV_1_5			(0x1 << 4)
+#define WM8350_BCLK_DIV_2			(0x2 << 4)
+#define WM8350_BCLK_DIV_3			(0x3 << 4)
+#define WM8350_BCLK_DIV_4			(0x4 << 4)
+#define WM8350_BCLK_DIV_5_5			(0x5 << 4)
+#define WM8350_BCLK_DIV_6			(0x6 << 4)
+#define WM8350_BCLK_DIV_8			(0x7 << 4)
+#define WM8350_BCLK_DIV_11			(0x8 << 4)
+#define WM8350_BCLK_DIV_12			(0x9 << 4)
+#define WM8350_BCLK_DIV_16			(0xa << 4)
+#define WM8350_BCLK_DIV_22			(0xb << 4)
+#define WM8350_BCLK_DIV_24			(0xc << 4)
+#define WM8350_BCLK_DIV_32			(0xd << 4)
+#define WM8350_BCLK_DIV_44			(0xe << 4)
+#define WM8350_BCLK_DIV_48			(0xf << 4)
+
+/* Sys (MCLK) clock dividers */
+#define WM8350_MCLK_DIV_1			(0x0 << 8)
+#define WM8350_MCLK_DIV_2			(0x1 << 8)
+
+/* OP clock dividers */
+#define WM8350_OPCLK_DIV_1			0x0
+#define WM8350_OPCLK_DIV_2			0x1
+#define WM8350_OPCLK_DIV_3			0x2
+#define WM8350_OPCLK_DIV_4			0x3
+#define WM8350_OPCLK_DIV_5_5			0x4
+#define WM8350_OPCLK_DIV_6			0x5
+
+/* DAI ID */
+#define WM8350_HIFI_DAI				0
+
+/*
+ * Audio interrupts.
+ */
+#define WM8350_IRQ_CODEC_JCK_DET_L		39
+#define WM8350_IRQ_CODEC_JCK_DET_R		40
+#define WM8350_IRQ_CODEC_MICSCD			41
+#define WM8350_IRQ_CODEC_MICD			42
+
+struct wm8350_codec {
+	struct platform_device *pdev;
+};
+
+#endif
diff --git a/include/linux/mfd/wm8350/comparator.h b/include/linux/mfd/wm8350/comparator.h
new file mode 100644
index 000000000000..053788649452
--- /dev/null
+++ b/include/linux/mfd/wm8350/comparator.h
@@ -0,0 +1,167 @@
+/*
+ * comparator.h  --  Comparator Aux ADC for Wolfson WM8350 PMIC
+ *
+ * Copyright 2007 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#ifndef __LINUX_MFD_WM8350_COMPARATOR_H_
+#define __LINUX_MFD_WM8350_COMPARATOR_H_
+
+/*
+ * Registers
+ */
+
+#define WM8350_DIGITISER_CONTROL_1              0x90
+#define WM8350_DIGITISER_CONTROL_2              0x91
+#define WM8350_AUX1_READBACK                    0x98
+#define WM8350_AUX2_READBACK                    0x99
+#define WM8350_AUX3_READBACK                    0x9A
+#define WM8350_AUX4_READBACK                    0x9B
+#define WM8350_CHIP_TEMP_READBACK               0x9F
+#define WM8350_GENERIC_COMPARATOR_CONTROL       0xA3
+#define WM8350_GENERIC_COMPARATOR_1             0xA4
+#define WM8350_GENERIC_COMPARATOR_2             0xA5
+#define WM8350_GENERIC_COMPARATOR_3             0xA6
+#define WM8350_GENERIC_COMPARATOR_4             0xA7
+
+/*
+ * R144 (0x90) - Digitiser Control (1)
+ */
+#define WM8350_AUXADC_CTC                       0x4000
+#define WM8350_AUXADC_POLL                      0x2000
+#define WM8350_AUXADC_HIB_MODE                  0x1000
+#define WM8350_AUXADC_SEL8                      0x0080
+#define WM8350_AUXADC_SEL7                      0x0040
+#define WM8350_AUXADC_SEL6                      0x0020
+#define WM8350_AUXADC_SEL5                      0x0010
+#define WM8350_AUXADC_SEL4                      0x0008
+#define WM8350_AUXADC_SEL3                      0x0004
+#define WM8350_AUXADC_SEL2                      0x0002
+#define WM8350_AUXADC_SEL1                      0x0001
+
+/*
+ * R145 (0x91) - Digitiser Control (2)
+ */
+#define WM8350_AUXADC_MASKMODE_MASK             0x3000
+#define WM8350_AUXADC_CRATE_MASK                0x0700
+#define WM8350_AUXADC_CAL                       0x0004
+#define WM8350_AUX_RBMODE                       0x0002
+#define WM8350_AUXADC_WAIT                      0x0001
+
+/*
+ * R152 (0x98) - AUX1 Readback
+ */
+#define WM8350_AUXADC_SCALE1_MASK               0x6000
+#define WM8350_AUXADC_REF1                      0x1000
+#define WM8350_AUXADC_DATA1_MASK                0x0FFF
+
+/*
+ * R153 (0x99) - AUX2 Readback
+ */
+#define WM8350_AUXADC_SCALE2_MASK               0x6000
+#define WM8350_AUXADC_REF2                      0x1000
+#define WM8350_AUXADC_DATA2_MASK                0x0FFF
+
+/*
+ * R154 (0x9A) - AUX3 Readback
+ */
+#define WM8350_AUXADC_SCALE3_MASK               0x6000
+#define WM8350_AUXADC_REF3                      0x1000
+#define WM8350_AUXADC_DATA3_MASK                0x0FFF
+
+/*
+ * R155 (0x9B) - AUX4 Readback
+ */
+#define WM8350_AUXADC_SCALE4_MASK               0x6000
+#define WM8350_AUXADC_REF4                      0x1000
+#define WM8350_AUXADC_DATA4_MASK                0x0FFF
+
+/*
+ * R156 (0x9C) - USB Voltage Readback
+ */
+#define WM8350_AUXADC_DATA_USB_MASK             0x0FFF
+
+/*
+ * R157 (0x9D) - LINE Voltage Readback
+ */
+#define WM8350_AUXADC_DATA_LINE_MASK            0x0FFF
+
+/*
+ * R158 (0x9E) - BATT Voltage Readback
+ */
+#define WM8350_AUXADC_DATA_BATT_MASK            0x0FFF
+
+/*
+ * R159 (0x9F) - Chip Temp Readback
+ */
+#define WM8350_AUXADC_DATA_CHIPTEMP_MASK        0x0FFF
+
+/*
+ * R163 (0xA3) - Generic Comparator Control
+ */
+#define WM8350_DCMP4_ENA                        0x0008
+#define WM8350_DCMP3_ENA                        0x0004
+#define WM8350_DCMP2_ENA                        0x0002
+#define WM8350_DCMP1_ENA                        0x0001
+
+/*
+ * R164 (0xA4) - Generic comparator 1
+ */
+#define WM8350_DCMP1_SRCSEL_MASK                0xE000
+#define WM8350_DCMP1_GT                         0x1000
+#define WM8350_DCMP1_THR_MASK                   0x0FFF
+
+/*
+ * R165 (0xA5) - Generic comparator 2
+ */
+#define WM8350_DCMP2_SRCSEL_MASK                0xE000
+#define WM8350_DCMP2_GT                         0x1000
+#define WM8350_DCMP2_THR_MASK                   0x0FFF
+
+/*
+ * R166 (0xA6) - Generic comparator 3
+ */
+#define WM8350_DCMP3_SRCSEL_MASK                0xE000
+#define WM8350_DCMP3_GT                         0x1000
+#define WM8350_DCMP3_THR_MASK                   0x0FFF
+
+/*
+ * R167 (0xA7) - Generic comparator 4
+ */
+#define WM8350_DCMP4_SRCSEL_MASK                0xE000
+#define WM8350_DCMP4_GT                         0x1000
+#define WM8350_DCMP4_THR_MASK                   0x0FFF
+
+/*
+ * Interrupts.
+ */
+#define WM8350_IRQ_AUXADC_DATARDY		16
+#define WM8350_IRQ_AUXADC_DCOMP4		17
+#define WM8350_IRQ_AUXADC_DCOMP3		18
+#define WM8350_IRQ_AUXADC_DCOMP2		19
+#define WM8350_IRQ_AUXADC_DCOMP1		20
+#define WM8350_IRQ_SYS_HYST_COMP_FAIL		21
+#define WM8350_IRQ_SYS_CHIP_GT115		22
+#define WM8350_IRQ_SYS_CHIP_GT140		23
+
+/*
+ * USB/2, LINE & BATT = ((VRTC * 2) / 4095)) * 10e6 uV
+ * Where VRTC = 2.7 V
+ */
+#define WM8350_AUX_COEFF			1319
+
+#define WM8350_AUXADC_AUX1			0
+#define WM8350_AUXADC_AUX2			1
+#define WM8350_AUXADC_AUX3			2
+#define WM8350_AUXADC_AUX4			3
+#define WM8350_AUXADC_USB			4
+#define WM8350_AUXADC_LINE			5
+#define WM8350_AUXADC_BATT			6
+#define WM8350_AUXADC_TEMP			7
+
+#endif
diff --git a/include/linux/mfd/wm8350/core.h b/include/linux/mfd/wm8350/core.h
new file mode 100644
index 000000000000..6ebf97f2a475
--- /dev/null
+++ b/include/linux/mfd/wm8350/core.h
@@ -0,0 +1,631 @@
+/*
+ * core.h  --  Core Driver for Wolfson WM8350 PMIC
+ *
+ * Copyright 2007 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#ifndef __LINUX_MFD_WM8350_CORE_H_
+#define __LINUX_MFD_WM8350_CORE_H_
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+
+#include <linux/mfd/wm8350/audio.h>
+#include <linux/mfd/wm8350/gpio.h>
+#include <linux/mfd/wm8350/pmic.h>
+#include <linux/mfd/wm8350/rtc.h>
+#include <linux/mfd/wm8350/supply.h>
+#include <linux/mfd/wm8350/wdt.h>
+
+/*
+ * Register values.
+ */
+#define WM8350_RESET_ID                         0x00
+#define WM8350_ID                               0x01
+#define WM8350_SYSTEM_CONTROL_1                 0x03
+#define WM8350_SYSTEM_CONTROL_2                 0x04
+#define WM8350_SYSTEM_HIBERNATE                 0x05
+#define WM8350_INTERFACE_CONTROL                0x06
+#define WM8350_POWER_MGMT_1                     0x08
+#define WM8350_POWER_MGMT_2                     0x09
+#define WM8350_POWER_MGMT_3                     0x0A
+#define WM8350_POWER_MGMT_4                     0x0B
+#define WM8350_POWER_MGMT_5                     0x0C
+#define WM8350_POWER_MGMT_6                     0x0D
+#define WM8350_POWER_MGMT_7                     0x0E
+
+#define WM8350_SYSTEM_INTERRUPTS                0x18
+#define WM8350_INT_STATUS_1                     0x19
+#define WM8350_INT_STATUS_2                     0x1A
+#define WM8350_POWER_UP_INT_STATUS              0x1B
+#define WM8350_UNDER_VOLTAGE_INT_STATUS         0x1C
+#define WM8350_OVER_CURRENT_INT_STATUS          0x1D
+#define WM8350_GPIO_INT_STATUS                  0x1E
+#define WM8350_COMPARATOR_INT_STATUS            0x1F
+#define WM8350_SYSTEM_INTERRUPTS_MASK           0x20
+#define WM8350_INT_STATUS_1_MASK                0x21
+#define WM8350_INT_STATUS_2_MASK                0x22
+#define WM8350_POWER_UP_INT_STATUS_MASK         0x23
+#define WM8350_UNDER_VOLTAGE_INT_STATUS_MASK    0x24
+#define WM8350_OVER_CURRENT_INT_STATUS_MASK     0x25
+#define WM8350_GPIO_INT_STATUS_MASK             0x26
+#define WM8350_COMPARATOR_INT_STATUS_MASK       0x27
+
+#define WM8350_MAX_REGISTER                     0xFF
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - Reset/ID
+ */
+#define WM8350_SW_RESET_CHIP_ID_MASK            0xFFFF
+
+/*
+ * R1 (0x01) - ID
+ */
+#define WM8350_CHIP_REV_MASK                    0x7000
+#define WM8350_CONF_STS_MASK                    0x0C00
+#define WM8350_CUST_ID_MASK                     0x00FF
+
+/*
+ * R3 (0x03) - System Control 1
+ */
+#define WM8350_CHIP_ON                          0x8000
+#define WM8350_POWERCYCLE                       0x2000
+#define WM8350_VCC_FAULT_OV                     0x1000
+#define WM8350_REG_RSTB_TIME_MASK               0x0C00
+#define WM8350_BG_SLEEP                         0x0200
+#define WM8350_MEM_VALID                        0x0020
+#define WM8350_CHIP_SET_UP                      0x0010
+#define WM8350_ON_DEB_T                         0x0008
+#define WM8350_ON_POL                           0x0002
+#define WM8350_IRQ_POL                          0x0001
+
+/*
+ * R4 (0x04) - System Control 2
+ */
+#define WM8350_USB_SUSPEND_8MA                  0x8000
+#define WM8350_USB_SUSPEND                      0x4000
+#define WM8350_USB_MSTR                         0x2000
+#define WM8350_USB_MSTR_SRC                     0x1000
+#define WM8350_USB_500MA                        0x0800
+#define WM8350_USB_NOLIM                        0x0400
+
+/*
+ * R5 (0x05) - System Hibernate
+ */
+#define WM8350_HIBERNATE                        0x8000
+#define WM8350_WDOG_HIB_MODE                    0x0080
+#define WM8350_REG_HIB_STARTUP_SEQ              0x0040
+#define WM8350_REG_RESET_HIB_MODE               0x0020
+#define WM8350_RST_HIB_MODE                     0x0010
+#define WM8350_IRQ_HIB_MODE                     0x0008
+#define WM8350_MEMRST_HIB_MODE                  0x0004
+#define WM8350_PCCOMP_HIB_MODE                  0x0002
+#define WM8350_TEMPMON_HIB_MODE                 0x0001
+
+/*
+ * R6 (0x06) - Interface Control
+ */
+#define WM8350_USE_DEV_PINS                     0x8000
+#define WM8350_USE_DEV_PINS_MASK                0x8000
+#define WM8350_USE_DEV_PINS_SHIFT                   15
+#define WM8350_DEV_ADDR_MASK                    0x6000
+#define WM8350_DEV_ADDR_SHIFT                       13
+#define WM8350_CONFIG_DONE                      0x1000
+#define WM8350_CONFIG_DONE_MASK                 0x1000
+#define WM8350_CONFIG_DONE_SHIFT                    12
+#define WM8350_RECONFIG_AT_ON                   0x0800
+#define WM8350_RECONFIG_AT_ON_MASK              0x0800
+#define WM8350_RECONFIG_AT_ON_SHIFT                 11
+#define WM8350_AUTOINC                          0x0200
+#define WM8350_AUTOINC_MASK                     0x0200
+#define WM8350_AUTOINC_SHIFT                         9
+#define WM8350_ARA                              0x0100
+#define WM8350_ARA_MASK                         0x0100
+#define WM8350_ARA_SHIFT                             8
+#define WM8350_SPI_CFG                          0x0008
+#define WM8350_SPI_CFG_MASK                     0x0008
+#define WM8350_SPI_CFG_SHIFT                         3
+#define WM8350_SPI_4WIRE                        0x0004
+#define WM8350_SPI_4WIRE_MASK                   0x0004
+#define WM8350_SPI_4WIRE_SHIFT                       2
+#define WM8350_SPI_3WIRE                        0x0002
+#define WM8350_SPI_3WIRE_MASK                   0x0002
+#define WM8350_SPI_3WIRE_SHIFT                       1
+
+/* Bit values for R06 (0x06) */
+#define WM8350_USE_DEV_PINS_PRIMARY                  0
+#define WM8350_USE_DEV_PINS_DEV                      1
+
+#define WM8350_DEV_ADDR_34                           0
+#define WM8350_DEV_ADDR_36                           1
+#define WM8350_DEV_ADDR_3C                           2
+#define WM8350_DEV_ADDR_3E                           3
+
+#define WM8350_CONFIG_DONE_OFF                       0
+#define WM8350_CONFIG_DONE_DONE                      1
+
+#define WM8350_RECONFIG_AT_ON_OFF                    0
+#define WM8350_RECONFIG_AT_ON_ON                     1
+
+#define WM8350_AUTOINC_OFF                           0
+#define WM8350_AUTOINC_ON                            1
+
+#define WM8350_ARA_OFF                               0
+#define WM8350_ARA_ON                                1
+
+#define WM8350_SPI_CFG_CMOS                          0
+#define WM8350_SPI_CFG_OD                            1
+
+#define WM8350_SPI_4WIRE_3WIRE                       0
+#define WM8350_SPI_4WIRE_4WIRE                       1
+
+#define WM8350_SPI_3WIRE_I2C                         0
+#define WM8350_SPI_3WIRE_SPI                         1
+
+/*
+ * R8 (0x08) - Power mgmt (1)
+ */
+#define WM8350_CODEC_ISEL_MASK                  0xC000
+#define WM8350_VBUFEN                           0x2000
+#define WM8350_OUTPUT_DRAIN_EN                  0x0400
+#define WM8350_MIC_DET_ENA                      0x0100
+#define WM8350_BIASEN                           0x0020
+#define WM8350_MICBEN                           0x0010
+#define WM8350_VMIDEN                           0x0004
+#define WM8350_VMID_MASK                        0x0003
+#define WM8350_VMID_SHIFT                            0
+
+/*
+ * R9 (0x09) - Power mgmt (2)
+ */
+#define WM8350_IN3R_ENA                         0x0800
+#define WM8350_IN3L_ENA                         0x0400
+#define WM8350_INR_ENA                          0x0200
+#define WM8350_INL_ENA                          0x0100
+#define WM8350_MIXINR_ENA                       0x0080
+#define WM8350_MIXINL_ENA                       0x0040
+#define WM8350_OUT4_ENA                         0x0020
+#define WM8350_OUT3_ENA                         0x0010
+#define WM8350_MIXOUTR_ENA                      0x0002
+#define WM8350_MIXOUTL_ENA                      0x0001
+
+/*
+ * R10 (0x0A) - Power mgmt (3)
+ */
+#define WM8350_IN3R_TO_OUT2R                    0x0080
+#define WM8350_OUT2R_ENA                        0x0008
+#define WM8350_OUT2L_ENA                        0x0004
+#define WM8350_OUT1R_ENA                        0x0002
+#define WM8350_OUT1L_ENA                        0x0001
+
+/*
+ * R11 (0x0B) - Power mgmt (4)
+ */
+#define WM8350_SYSCLK_ENA                       0x4000
+#define WM8350_ADC_HPF_ENA                      0x2000
+#define WM8350_FLL_ENA                          0x0800
+#define WM8350_FLL_OSC_ENA                      0x0400
+#define WM8350_TOCLK_ENA                        0x0100
+#define WM8350_DACR_ENA                         0x0020
+#define WM8350_DACL_ENA                         0x0010
+#define WM8350_ADCR_ENA                         0x0008
+#define WM8350_ADCL_ENA                         0x0004
+
+/*
+ * R12 (0x0C) - Power mgmt (5)
+ */
+#define WM8350_CODEC_ENA                        0x1000
+#define WM8350_RTC_TICK_ENA                     0x0800
+#define WM8350_OSC32K_ENA                       0x0400
+#define WM8350_CHG_ENA                          0x0200
+#define WM8350_ACC_DET_ENA                      0x0100
+#define WM8350_AUXADC_ENA                       0x0080
+#define WM8350_DCMP4_ENA                        0x0008
+#define WM8350_DCMP3_ENA                        0x0004
+#define WM8350_DCMP2_ENA                        0x0002
+#define WM8350_DCMP1_ENA                        0x0001
+
+/*
+ * R13 (0x0D) - Power mgmt (6)
+ */
+#define WM8350_LS_ENA                           0x8000
+#define WM8350_LDO4_ENA                         0x0800
+#define WM8350_LDO3_ENA                         0x0400
+#define WM8350_LDO2_ENA                         0x0200
+#define WM8350_LDO1_ENA                         0x0100
+#define WM8350_DC6_ENA                          0x0020
+#define WM8350_DC5_ENA                          0x0010
+#define WM8350_DC4_ENA                          0x0008
+#define WM8350_DC3_ENA                          0x0004
+#define WM8350_DC2_ENA                          0x0002
+#define WM8350_DC1_ENA                          0x0001
+
+/*
+ * R14 (0x0E) - Power mgmt (7)
+ */
+#define WM8350_CS2_ENA                          0x0002
+#define WM8350_CS1_ENA                          0x0001
+
+/*
+ * R24 (0x18) - System Interrupts
+ */
+#define WM8350_OC_INT                           0x2000
+#define WM8350_UV_INT                           0x1000
+#define WM8350_PUTO_INT                         0x0800
+#define WM8350_CS_INT                           0x0200
+#define WM8350_EXT_INT                          0x0100
+#define WM8350_CODEC_INT                        0x0080
+#define WM8350_GP_INT                           0x0040
+#define WM8350_AUXADC_INT                       0x0020
+#define WM8350_RTC_INT                          0x0010
+#define WM8350_SYS_INT                          0x0008
+#define WM8350_CHG_INT                          0x0004
+#define WM8350_USB_INT                          0x0002
+#define WM8350_WKUP_INT                         0x0001
+
+/*
+ * R25 (0x19) - Interrupt Status 1
+ */
+#define WM8350_CHG_BAT_HOT_EINT                 0x8000
+#define WM8350_CHG_BAT_COLD_EINT                0x4000
+#define WM8350_CHG_BAT_FAIL_EINT                0x2000
+#define WM8350_CHG_TO_EINT                      0x1000
+#define WM8350_CHG_END_EINT                     0x0800
+#define WM8350_CHG_START_EINT                   0x0400
+#define WM8350_CHG_FAST_RDY_EINT                0x0200
+#define WM8350_RTC_PER_EINT                     0x0080
+#define WM8350_RTC_SEC_EINT                     0x0040
+#define WM8350_RTC_ALM_EINT                     0x0020
+#define WM8350_CHG_VBATT_LT_3P9_EINT            0x0004
+#define WM8350_CHG_VBATT_LT_3P1_EINT            0x0002
+#define WM8350_CHG_VBATT_LT_2P85_EINT           0x0001
+
+/*
+ * R26 (0x1A) - Interrupt Status 2
+ */
+#define WM8350_CS1_EINT                         0x2000
+#define WM8350_CS2_EINT                         0x1000
+#define WM8350_USB_LIMIT_EINT                   0x0400
+#define WM8350_AUXADC_DATARDY_EINT              0x0100
+#define WM8350_AUXADC_DCOMP4_EINT               0x0080
+#define WM8350_AUXADC_DCOMP3_EINT               0x0040
+#define WM8350_AUXADC_DCOMP2_EINT               0x0020
+#define WM8350_AUXADC_DCOMP1_EINT               0x0010
+#define WM8350_SYS_HYST_COMP_FAIL_EINT          0x0008
+#define WM8350_SYS_CHIP_GT115_EINT              0x0004
+#define WM8350_SYS_CHIP_GT140_EINT              0x0002
+#define WM8350_SYS_WDOG_TO_EINT                 0x0001
+
+/*
+ * R27 (0x1B) - Power Up Interrupt Status
+ */
+#define WM8350_PUTO_LDO4_EINT                   0x0800
+#define WM8350_PUTO_LDO3_EINT                   0x0400
+#define WM8350_PUTO_LDO2_EINT                   0x0200
+#define WM8350_PUTO_LDO1_EINT                   0x0100
+#define WM8350_PUTO_DC6_EINT                    0x0020
+#define WM8350_PUTO_DC5_EINT                    0x0010
+#define WM8350_PUTO_DC4_EINT                    0x0008
+#define WM8350_PUTO_DC3_EINT                    0x0004
+#define WM8350_PUTO_DC2_EINT                    0x0002
+#define WM8350_PUTO_DC1_EINT                    0x0001
+
+/*
+ * R28 (0x1C) - Under Voltage Interrupt status
+ */
+#define WM8350_UV_LDO4_EINT                     0x0800
+#define WM8350_UV_LDO3_EINT                     0x0400
+#define WM8350_UV_LDO2_EINT                     0x0200
+#define WM8350_UV_LDO1_EINT                     0x0100
+#define WM8350_UV_DC6_EINT                      0x0020
+#define WM8350_UV_DC5_EINT                      0x0010
+#define WM8350_UV_DC4_EINT                      0x0008
+#define WM8350_UV_DC3_EINT                      0x0004
+#define WM8350_UV_DC2_EINT                      0x0002
+#define WM8350_UV_DC1_EINT                      0x0001
+
+/*
+ * R29 (0x1D) - Over Current Interrupt status
+ */
+#define WM8350_OC_LS_EINT                       0x8000
+
+/*
+ * R30 (0x1E) - GPIO Interrupt Status
+ */
+#define WM8350_GP12_EINT                        0x1000
+#define WM8350_GP11_EINT                        0x0800
+#define WM8350_GP10_EINT                        0x0400
+#define WM8350_GP9_EINT                         0x0200
+#define WM8350_GP8_EINT                         0x0100
+#define WM8350_GP7_EINT                         0x0080
+#define WM8350_GP6_EINT                         0x0040
+#define WM8350_GP5_EINT                         0x0020
+#define WM8350_GP4_EINT                         0x0010
+#define WM8350_GP3_EINT                         0x0008
+#define WM8350_GP2_EINT                         0x0004
+#define WM8350_GP1_EINT                         0x0002
+#define WM8350_GP0_EINT                         0x0001
+
+/*
+ * R31 (0x1F) - Comparator Interrupt Status
+ */
+#define WM8350_EXT_USB_FB_EINT                  0x8000
+#define WM8350_EXT_WALL_FB_EINT                 0x4000
+#define WM8350_EXT_BAT_FB_EINT                  0x2000
+#define WM8350_CODEC_JCK_DET_L_EINT             0x0800
+#define WM8350_CODEC_JCK_DET_R_EINT             0x0400
+#define WM8350_CODEC_MICSCD_EINT                0x0200
+#define WM8350_CODEC_MICD_EINT                  0x0100
+#define WM8350_WKUP_OFF_STATE_EINT              0x0040
+#define WM8350_WKUP_HIB_STATE_EINT              0x0020
+#define WM8350_WKUP_CONV_FAULT_EINT             0x0010
+#define WM8350_WKUP_WDOG_RST_EINT               0x0008
+#define WM8350_WKUP_GP_PWR_ON_EINT              0x0004
+#define WM8350_WKUP_ONKEY_EINT                  0x0002
+#define WM8350_WKUP_GP_WAKEUP_EINT              0x0001
+
+/*
+ * R32 (0x20) - System Interrupts Mask
+ */
+#define WM8350_IM_OC_INT                        0x2000
+#define WM8350_IM_UV_INT                        0x1000
+#define WM8350_IM_PUTO_INT                      0x0800
+#define WM8350_IM_SPARE_INT                     0x0400
+#define WM8350_IM_CS_INT                        0x0200
+#define WM8350_IM_EXT_INT                       0x0100
+#define WM8350_IM_CODEC_INT                     0x0080
+#define WM8350_IM_GP_INT                        0x0040
+#define WM8350_IM_AUXADC_INT                    0x0020
+#define WM8350_IM_RTC_INT                       0x0010
+#define WM8350_IM_SYS_INT                       0x0008
+#define WM8350_IM_CHG_INT                       0x0004
+#define WM8350_IM_USB_INT                       0x0002
+#define WM8350_IM_WKUP_INT                      0x0001
+
+/*
+ * R33 (0x21) - Interrupt Status 1 Mask
+ */
+#define WM8350_IM_CHG_BAT_HOT_EINT              0x8000
+#define WM8350_IM_CHG_BAT_COLD_EINT             0x4000
+#define WM8350_IM_CHG_BAT_FAIL_EINT             0x2000
+#define WM8350_IM_CHG_TO_EINT                   0x1000
+#define WM8350_IM_CHG_END_EINT                  0x0800
+#define WM8350_IM_CHG_START_EINT                0x0400
+#define WM8350_IM_CHG_FAST_RDY_EINT             0x0200
+#define WM8350_IM_RTC_PER_EINT                  0x0080
+#define WM8350_IM_RTC_SEC_EINT                  0x0040
+#define WM8350_IM_RTC_ALM_EINT                  0x0020
+#define WM8350_IM_CHG_VBATT_LT_3P9_EINT         0x0004
+#define WM8350_IM_CHG_VBATT_LT_3P1_EINT         0x0002
+#define WM8350_IM_CHG_VBATT_LT_2P85_EINT        0x0001
+
+/*
+ * R34 (0x22) - Interrupt Status 2 Mask
+ */
+#define WM8350_IM_SPARE2_EINT                   0x8000
+#define WM8350_IM_SPARE1_EINT                   0x4000
+#define WM8350_IM_CS1_EINT                      0x2000
+#define WM8350_IM_CS2_EINT                      0x1000
+#define WM8350_IM_USB_LIMIT_EINT                0x0400
+#define WM8350_IM_AUXADC_DATARDY_EINT           0x0100
+#define WM8350_IM_AUXADC_DCOMP4_EINT            0x0080
+#define WM8350_IM_AUXADC_DCOMP3_EINT            0x0040
+#define WM8350_IM_AUXADC_DCOMP2_EINT            0x0020
+#define WM8350_IM_AUXADC_DCOMP1_EINT            0x0010
+#define WM8350_IM_SYS_HYST_COMP_FAIL_EINT       0x0008
+#define WM8350_IM_SYS_CHIP_GT115_EINT           0x0004
+#define WM8350_IM_SYS_CHIP_GT140_EINT           0x0002
+#define WM8350_IM_SYS_WDOG_TO_EINT              0x0001
+
+/*
+ * R35 (0x23) - Power Up Interrupt Status Mask
+ */
+#define WM8350_IM_PUTO_LDO4_EINT                0x0800
+#define WM8350_IM_PUTO_LDO3_EINT                0x0400
+#define WM8350_IM_PUTO_LDO2_EINT                0x0200
+#define WM8350_IM_PUTO_LDO1_EINT                0x0100
+#define WM8350_IM_PUTO_DC6_EINT                 0x0020
+#define WM8350_IM_PUTO_DC5_EINT                 0x0010
+#define WM8350_IM_PUTO_DC4_EINT                 0x0008
+#define WM8350_IM_PUTO_DC3_EINT                 0x0004
+#define WM8350_IM_PUTO_DC2_EINT                 0x0002
+#define WM8350_IM_PUTO_DC1_EINT                 0x0001
+
+/*
+ * R36 (0x24) - Under Voltage Interrupt status Mask
+ */
+#define WM8350_IM_UV_LDO4_EINT                  0x0800
+#define WM8350_IM_UV_LDO3_EINT                  0x0400
+#define WM8350_IM_UV_LDO2_EINT                  0x0200
+#define WM8350_IM_UV_LDO1_EINT                  0x0100
+#define WM8350_IM_UV_DC6_EINT                   0x0020
+#define WM8350_IM_UV_DC5_EINT                   0x0010
+#define WM8350_IM_UV_DC4_EINT                   0x0008
+#define WM8350_IM_UV_DC3_EINT                   0x0004
+#define WM8350_IM_UV_DC2_EINT                   0x0002
+#define WM8350_IM_UV_DC1_EINT                   0x0001
+
+/*
+ * R37 (0x25) - Over Current Interrupt status Mask
+ */
+#define WM8350_IM_OC_LS_EINT                    0x8000
+
+/*
+ * R38 (0x26) - GPIO Interrupt Status Mask
+ */
+#define WM8350_IM_GP12_EINT                     0x1000
+#define WM8350_IM_GP11_EINT                     0x0800
+#define WM8350_IM_GP10_EINT                     0x0400
+#define WM8350_IM_GP9_EINT                      0x0200
+#define WM8350_IM_GP8_EINT                      0x0100
+#define WM8350_IM_GP7_EINT                      0x0080
+#define WM8350_IM_GP6_EINT                      0x0040
+#define WM8350_IM_GP5_EINT                      0x0020
+#define WM8350_IM_GP4_EINT                      0x0010
+#define WM8350_IM_GP3_EINT                      0x0008
+#define WM8350_IM_GP2_EINT                      0x0004
+#define WM8350_IM_GP1_EINT                      0x0002
+#define WM8350_IM_GP0_EINT                      0x0001
+
+/*
+ * R39 (0x27) - Comparator Interrupt Status Mask
+ */
+#define WM8350_IM_EXT_USB_FB_EINT               0x8000
+#define WM8350_IM_EXT_WALL_FB_EINT              0x4000
+#define WM8350_IM_EXT_BAT_FB_EINT               0x2000
+#define WM8350_IM_CODEC_JCK_DET_L_EINT          0x0800
+#define WM8350_IM_CODEC_JCK_DET_R_EINT          0x0400
+#define WM8350_IM_CODEC_MICSCD_EINT             0x0200
+#define WM8350_IM_CODEC_MICD_EINT               0x0100
+#define WM8350_IM_WKUP_OFF_STATE_EINT           0x0040
+#define WM8350_IM_WKUP_HIB_STATE_EINT           0x0020
+#define WM8350_IM_WKUP_CONV_FAULT_EINT          0x0010
+#define WM8350_IM_WKUP_WDOG_RST_EINT            0x0008
+#define WM8350_IM_WKUP_GP_PWR_ON_EINT           0x0004
+#define WM8350_IM_WKUP_ONKEY_EINT               0x0002
+#define WM8350_IM_WKUP_GP_WAKEUP_EINT           0x0001
+
+/*
+ * R220 (0xDC) - RAM BIST 1
+ */
+#define WM8350_READ_STATUS                      0x0800
+#define WM8350_TSTRAM_CLK                       0x0100
+#define WM8350_TSTRAM_CLK_ENA                   0x0080
+#define WM8350_STARTSEQ                         0x0040
+#define WM8350_READ_SRC                         0x0020
+#define WM8350_COUNT_DIR                        0x0010
+#define WM8350_TSTRAM_MODE_MASK                 0x000E
+#define WM8350_TSTRAM_ENA                       0x0001
+
+/*
+ * R225 (0xE1) - DCDC/LDO status
+ */
+#define WM8350_LS_STS                           0x8000
+#define WM8350_LDO4_STS                         0x0800
+#define WM8350_LDO3_STS                         0x0400
+#define WM8350_LDO2_STS                         0x0200
+#define WM8350_LDO1_STS                         0x0100
+#define WM8350_DC6_STS                          0x0020
+#define WM8350_DC5_STS                          0x0010
+#define WM8350_DC4_STS                          0x0008
+#define WM8350_DC3_STS                          0x0004
+#define WM8350_DC2_STS                          0x0002
+#define WM8350_DC1_STS                          0x0001
+
+/* WM8350 wake up conditions */
+#define WM8350_IRQ_WKUP_OFF_STATE		43
+#define WM8350_IRQ_WKUP_HIB_STATE		44
+#define WM8350_IRQ_WKUP_CONV_FAULT		45
+#define WM8350_IRQ_WKUP_WDOG_RST		46
+#define WM8350_IRQ_WKUP_GP_PWR_ON		47
+#define WM8350_IRQ_WKUP_ONKEY			48
+#define WM8350_IRQ_WKUP_GP_WAKEUP		49
+
+/* wm8350 chip revisions */
+#define WM8350_REV_E				0x4
+#define WM8350_REV_F				0x5
+#define WM8350_REV_G				0x6
+
+#define WM8350_NUM_IRQ				63
+
+struct wm8350_reg_access {
+	u16 readable;		/* Mask of readable bits */
+	u16 writable;		/* Mask of writable bits */
+	u16 vol;		/* Mask of volatile bits */
+};
+extern const struct wm8350_reg_access wm8350_reg_io_map[];
+extern const u16 wm8350_mode0_defaults[];
+extern const u16 wm8350_mode1_defaults[];
+extern const u16 wm8350_mode2_defaults[];
+extern const u16 wm8350_mode3_defaults[];
+
+struct wm8350;
+
+struct wm8350_irq {
+	void (*handler) (struct wm8350 *, int, void *);
+	void *data;
+};
+
+struct wm8350 {
+	int rev;		/* chip revision */
+
+	struct device *dev;
+
+	/* device IO */
+	union {
+		struct i2c_client *i2c_client;
+		struct spi_device *spi_device;
+	};
+	int (*read_dev)(struct wm8350 *wm8350, char reg, int size, void *dest);
+	int (*write_dev)(struct wm8350 *wm8350, char reg, int size,
+			 void *src);
+	u16 *reg_cache;
+
+	/* Interrupt handling */
+	struct work_struct irq_work;
+	struct mutex irq_mutex; /* IRQ table mutex */
+	struct wm8350_irq irq[WM8350_NUM_IRQ];
+	int chip_irq;
+
+	/* Client devices */
+	struct wm8350_codec codec;
+	struct wm8350_gpio gpio;
+	struct wm8350_pmic pmic;
+	struct wm8350_power power;
+	struct wm8350_rtc rtc;
+	struct wm8350_wdt wdt;
+};
+
+/**
+ * Data to be supplied by the platform to initialise the WM8350.
+ *
+ * @init: Function called during driver initialisation.  Should be
+ *        used by the platform to configure GPIO functions and similar.
+ */
+struct wm8350_platform_data {
+	int (*init)(struct wm8350 *wm8350);
+};
+
+
+/*
+ * WM8350 device initialisation and exit.
+ */
+int wm8350_device_init(struct wm8350 *wm8350, int irq,
+		       struct wm8350_platform_data *pdata);
+void wm8350_device_exit(struct wm8350 *wm8350);
+
+/*
+ * WM8350 device IO
+ */
+int wm8350_clear_bits(struct wm8350 *wm8350, u16 reg, u16 mask);
+int wm8350_set_bits(struct wm8350 *wm8350, u16 reg, u16 mask);
+u16 wm8350_reg_read(struct wm8350 *wm8350, int reg);
+int wm8350_reg_write(struct wm8350 *wm8350, int reg, u16 val);
+int wm8350_reg_lock(struct wm8350 *wm8350);
+int wm8350_reg_unlock(struct wm8350 *wm8350);
+int wm8350_block_read(struct wm8350 *wm8350, int reg, int size, u16 *dest);
+int wm8350_block_write(struct wm8350 *wm8350, int reg, int size, u16 *src);
+
+/*
+ * WM8350 internal interrupts
+ */
+int wm8350_register_irq(struct wm8350 *wm8350, int irq,
+			void (*handler) (struct wm8350 *, int, void *),
+			void *data);
+int wm8350_free_irq(struct wm8350 *wm8350, int irq);
+int wm8350_mask_irq(struct wm8350 *wm8350, int irq);
+int wm8350_unmask_irq(struct wm8350 *wm8350, int irq);
+
+
+#endif
diff --git a/include/linux/mfd/wm8350/gpio.h b/include/linux/mfd/wm8350/gpio.h
new file mode 100644
index 000000000000..ed91e8f5d298
--- /dev/null
+++ b/include/linux/mfd/wm8350/gpio.h
@@ -0,0 +1,342 @@
+/*
+ * gpio.h  --  GPIO Driver for Wolfson WM8350 PMIC
+ *
+ * Copyright 2007 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#ifndef __LINUX_MFD_WM8350_GPIO_H_
+#define __LINUX_MFD_WM8350_GPIO_H_
+
+#include <linux/platform_device.h>
+
+/*
+ * GPIO Registers.
+ */
+#define WM8350_GPIO_DEBOUNCE                    0x80
+#define WM8350_GPIO_PIN_PULL_UP_CONTROL         0x81
+#define WM8350_GPIO_PULL_DOWN_CONTROL           0x82
+#define WM8350_GPIO_INT_MODE                    0x83
+#define WM8350_GPIO_CONTROL                     0x85
+#define WM8350_GPIO_CONFIGURATION_I_O           0x86
+#define WM8350_GPIO_PIN_POLARITY_TYPE           0x87
+#define WM8350_GPIO_FUNCTION_SELECT_1           0x8C
+#define WM8350_GPIO_FUNCTION_SELECT_2           0x8D
+#define WM8350_GPIO_FUNCTION_SELECT_3           0x8E
+#define WM8350_GPIO_FUNCTION_SELECT_4           0x8F
+
+/*
+ * GPIO Functions
+ */
+#define WM8350_GPIO0_GPIO_IN			0x0
+#define WM8350_GPIO0_GPIO_OUT			0x0
+#define WM8350_GPIO0_PWR_ON_IN			0x1
+#define WM8350_GPIO0_PWR_ON_OUT			0x1
+#define WM8350_GPIO0_LDO_EN_IN			0x2
+#define WM8350_GPIO0_VRTC_OUT			0x2
+#define WM8350_GPIO0_LPWR1_IN			0x3
+#define WM8350_GPIO0_POR_B_OUT			0x3
+
+#define WM8350_GPIO1_GPIO_IN			0x0
+#define WM8350_GPIO1_GPIO_OUT			0x0
+#define WM8350_GPIO1_PWR_ON_IN			0x1
+#define WM8350_GPIO1_DO_CONF_OUT		0x1
+#define WM8350_GPIO1_LDO_EN_IN			0x2
+#define WM8350_GPIO1_RESET_OUT			0x2
+#define WM8350_GPIO1_LPWR2_IN			0x3
+#define WM8350_GPIO1_MEMRST_OUT			0x3
+
+#define WM8350_GPIO2_GPIO_IN			0x0
+#define WM8350_GPIO2_GPIO_OUT			0x0
+#define WM8350_GPIO2_PWR_ON_IN			0x1
+#define WM8350_GPIO2_PWR_ON_OUT			0x1
+#define WM8350_GPIO2_WAKE_UP_IN			0x2
+#define WM8350_GPIO2_VRTC_OUT			0x2
+#define WM8350_GPIO2_32KHZ_IN			0x3
+#define WM8350_GPIO2_32KHZ_OUT			0x3
+
+#define WM8350_GPIO3_GPIO_IN			0x0
+#define WM8350_GPIO3_GPIO_OUT			0x0
+#define WM8350_GPIO3_PWR_ON_IN			0x1
+#define WM8350_GPIO3_P_CLK_OUT			0x1
+#define WM8350_GPIO3_LDO_EN_IN			0x2
+#define WM8350_GPIO3_VRTC_OUT			0x2
+#define WM8350_GPIO3_PWR_OFF_IN			0x3
+#define WM8350_GPIO3_32KHZ_OUT			0x3
+
+#define WM8350_GPIO4_GPIO_IN			0x0
+#define WM8350_GPIO4_GPIO_OUT			0x0
+#define WM8350_GPIO4_MR_IN			0x1
+#define WM8350_GPIO4_MEM_RST_OUT		0x1
+#define WM8350_GPIO4_FLASH_IN			0x2
+#define WM8350_GPIO4_ADA_OUT			0x2
+#define WM8350_GPIO4_HIBERNATE_IN		0x3
+#define WM8350_GPIO4_FLASH_OUT			0x3
+#define WM8350_GPIO4_MICDET_OUT			0x4
+#define WM8350_GPIO4_MICSHT_OUT			0x5
+
+#define WM8350_GPIO5_GPIO_IN			0x0
+#define WM8350_GPIO5_GPIO_OUT			0x0
+#define WM8350_GPIO5_LPWR1_IN			0x1
+#define WM8350_GPIO5_P_CLK_OUT			0x1
+#define WM8350_GPIO5_ADCLRCLK_IN		0x2
+#define WM8350_GPIO5_ADCLRCLK_OUT		0x2
+#define WM8350_GPIO5_HIBERNATE_IN		0x3
+#define WM8350_GPIO5_32KHZ_OUT			0x3
+#define WM8350_GPIO5_MICDET_OUT			0x4
+#define WM8350_GPIO5_MICSHT_OUT			0x5
+#define WM8350_GPIO5_ADA_OUT			0x6
+#define WM8350_GPIO5_OPCLK_OUT			0x7
+
+#define WM8350_GPIO6_GPIO_IN			0x0
+#define WM8350_GPIO6_GPIO_OUT			0x0
+#define WM8350_GPIO6_LPWR2_IN			0x1
+#define WM8350_GPIO6_MEMRST_OUT			0x1
+#define WM8350_GPIO6_FLASH_IN			0x2
+#define WM8350_GPIO6_ADA_OUT			0x2
+#define WM8350_GPIO6_HIBERNATE_IN		0x3
+#define WM8350_GPIO6_RTC_OUT			0x3
+#define WM8350_GPIO6_MICDET_OUT			0x4
+#define WM8350_GPIO6_MICSHT_OUT			0x5
+#define WM8350_GPIO6_ADCLRCLKB_OUT		0x6
+#define WM8350_GPIO6_SDOUT_OUT			0x7
+
+#define WM8350_GPIO7_GPIO_IN			0x0
+#define WM8350_GPIO7_GPIO_OUT			0x0
+#define WM8350_GPIO7_LPWR3_IN			0x1
+#define WM8350_GPIO7_P_CLK_OUT			0x1
+#define WM8350_GPIO7_MASK_IN			0x2
+#define WM8350_GPIO7_VCC_FAULT_OUT		0x2
+#define WM8350_GPIO7_HIBERNATE_IN		0x3
+#define WM8350_GPIO7_BATT_FAULT_OUT		0x3
+#define WM8350_GPIO7_MICDET_OUT			0x4
+#define WM8350_GPIO7_MICSHT_OUT			0x5
+#define WM8350_GPIO7_ADA_OUT			0x6
+#define WM8350_GPIO7_CSB_IN			0x7
+
+#define WM8350_GPIO8_GPIO_IN			0x0
+#define WM8350_GPIO8_GPIO_OUT			0x0
+#define WM8350_GPIO8_MR_IN			0x1
+#define WM8350_GPIO8_VCC_FAULT_OUT		0x1
+#define WM8350_GPIO8_ADCBCLK_IN			0x2
+#define WM8350_GPIO8_ADCBCLK_OUT		0x2
+#define WM8350_GPIO8_PWR_OFF_IN			0x3
+#define WM8350_GPIO8_BATT_FAULT_OUT		0x3
+#define WM8350_GPIO8_ALTSCL_IN			0xf
+
+#define WM8350_GPIO9_GPIO_IN			0x0
+#define WM8350_GPIO9_GPIO_OUT			0x0
+#define WM8350_GPIO9_HEARTBEAT_IN		0x1
+#define WM8350_GPIO9_VCC_FAULT_OUT		0x1
+#define WM8350_GPIO9_MASK_IN			0x2
+#define WM8350_GPIO9_LINE_GT_BATT_OUT		0x2
+#define WM8350_GPIO9_PWR_OFF_IN			0x3
+#define WM8350_GPIO9_BATT_FAULT_OUT		0x3
+#define WM8350_GPIO9_ALTSDA_OUT			0xf
+
+#define WM8350_GPIO10_GPIO_IN			0x0
+#define WM8350_GPIO10_GPIO_OUT			0x0
+#define WM8350_GPIO10_ISINKC_OUT		0x1
+#define WM8350_GPIO10_PWR_OFF_IN		0x2
+#define WM8350_GPIO10_LINE_GT_BATT_OUT		0x2
+#define WM8350_GPIO10_CHD_IND_IN		0x3
+
+#define WM8350_GPIO11_GPIO_IN			0x0
+#define WM8350_GPIO11_GPIO_OUT			0x0
+#define WM8350_GPIO11_ISINKD_OUT		0x1
+#define WM8350_GPIO11_WAKEUP_IN			0x2
+#define WM8350_GPIO11_LINE_GT_BATT_OUT		0x2
+#define WM8350_GPIO11_CHD_IND_IN		0x3
+
+#define WM8350_GPIO12_GPIO_IN			0x0
+#define WM8350_GPIO12_GPIO_OUT			0x0
+#define WM8350_GPIO12_ISINKE_OUT		0x1
+#define WM8350_GPIO12_LINE_GT_BATT_OUT		0x2
+#define WM8350_GPIO12_LINE_EN_OUT		0x3
+#define WM8350_GPIO12_32KHZ_OUT			0x4
+
+#define WM8350_GPIO_DIR_IN			0
+#define WM8350_GPIO_DIR_OUT			1
+#define WM8350_GPIO_ACTIVE_LOW			0
+#define WM8350_GPIO_ACTIVE_HIGH			1
+#define WM8350_GPIO_PULL_NONE			0
+#define WM8350_GPIO_PULL_UP			1
+#define WM8350_GPIO_PULL_DOWN			2
+#define WM8350_GPIO_INVERT_OFF			0
+#define WM8350_GPIO_INVERT_ON			1
+#define WM8350_GPIO_DEBOUNCE_OFF		0
+#define WM8350_GPIO_DEBOUNCE_ON			1
+
+/*
+ * R128 (0x80) - GPIO Debounce
+ */
+#define WM8350_GP12_DB                          0x1000
+#define WM8350_GP11_DB                          0x0800
+#define WM8350_GP10_DB                          0x0400
+#define WM8350_GP9_DB                           0x0200
+#define WM8350_GP8_DB                           0x0100
+#define WM8350_GP7_DB                           0x0080
+#define WM8350_GP6_DB                           0x0040
+#define WM8350_GP5_DB                           0x0020
+#define WM8350_GP4_DB                           0x0010
+#define WM8350_GP3_DB                           0x0008
+#define WM8350_GP2_DB                           0x0004
+#define WM8350_GP1_DB                           0x0002
+#define WM8350_GP0_DB                           0x0001
+
+/*
+ * R129 (0x81) - GPIO Pin pull up Control
+ */
+#define WM8350_GP12_PU                          0x1000
+#define WM8350_GP11_PU                          0x0800
+#define WM8350_GP10_PU                          0x0400
+#define WM8350_GP9_PU                           0x0200
+#define WM8350_GP8_PU                           0x0100
+#define WM8350_GP7_PU                           0x0080
+#define WM8350_GP6_PU                           0x0040
+#define WM8350_GP5_PU                           0x0020
+#define WM8350_GP4_PU                           0x0010
+#define WM8350_GP3_PU                           0x0008
+#define WM8350_GP2_PU                           0x0004
+#define WM8350_GP1_PU                           0x0002
+#define WM8350_GP0_PU                           0x0001
+
+/*
+ * R130 (0x82) - GPIO Pull down Control
+ */
+#define WM8350_GP12_PD                          0x1000
+#define WM8350_GP11_PD                          0x0800
+#define WM8350_GP10_PD                          0x0400
+#define WM8350_GP9_PD                           0x0200
+#define WM8350_GP8_PD                           0x0100
+#define WM8350_GP7_PD                           0x0080
+#define WM8350_GP6_PD                           0x0040
+#define WM8350_GP5_PD                           0x0020
+#define WM8350_GP4_PD                           0x0010
+#define WM8350_GP3_PD                           0x0008
+#define WM8350_GP2_PD                           0x0004
+#define WM8350_GP1_PD                           0x0002
+#define WM8350_GP0_PD                           0x0001
+
+/*
+ * R131 (0x83) - GPIO Interrupt Mode
+ */
+#define WM8350_GP12_INTMODE                     0x1000
+#define WM8350_GP11_INTMODE                     0x0800
+#define WM8350_GP10_INTMODE                     0x0400
+#define WM8350_GP9_INTMODE                      0x0200
+#define WM8350_GP8_INTMODE                      0x0100
+#define WM8350_GP7_INTMODE                      0x0080
+#define WM8350_GP6_INTMODE                      0x0040
+#define WM8350_GP5_INTMODE                      0x0020
+#define WM8350_GP4_INTMODE                      0x0010
+#define WM8350_GP3_INTMODE                      0x0008
+#define WM8350_GP2_INTMODE                      0x0004
+#define WM8350_GP1_INTMODE                      0x0002
+#define WM8350_GP0_INTMODE                      0x0001
+
+/*
+ * R133 (0x85) - GPIO Control
+ */
+#define WM8350_GP_DBTIME_MASK                   0x00C0
+
+/*
+ * R134 (0x86) - GPIO Configuration (i/o)
+ */
+#define WM8350_GP12_DIR                         0x1000
+#define WM8350_GP11_DIR                         0x0800
+#define WM8350_GP10_DIR                         0x0400
+#define WM8350_GP9_DIR                          0x0200
+#define WM8350_GP8_DIR                          0x0100
+#define WM8350_GP7_DIR                          0x0080
+#define WM8350_GP6_DIR                          0x0040
+#define WM8350_GP5_DIR                          0x0020
+#define WM8350_GP4_DIR                          0x0010
+#define WM8350_GP3_DIR                          0x0008
+#define WM8350_GP2_DIR                          0x0004
+#define WM8350_GP1_DIR                          0x0002
+#define WM8350_GP0_DIR                          0x0001
+
+/*
+ * R135 (0x87) - GPIO Pin Polarity / Type
+ */
+#define WM8350_GP12_CFG                         0x1000
+#define WM8350_GP11_CFG                         0x0800
+#define WM8350_GP10_CFG                         0x0400
+#define WM8350_GP9_CFG                          0x0200
+#define WM8350_GP8_CFG                          0x0100
+#define WM8350_GP7_CFG                          0x0080
+#define WM8350_GP6_CFG                          0x0040
+#define WM8350_GP5_CFG                          0x0020
+#define WM8350_GP4_CFG                          0x0010
+#define WM8350_GP3_CFG                          0x0008
+#define WM8350_GP2_CFG                          0x0004
+#define WM8350_GP1_CFG                          0x0002
+#define WM8350_GP0_CFG                          0x0001
+
+/*
+ * R140 (0x8C) - GPIO Function Select 1
+ */
+#define WM8350_GP3_FN_MASK                      0xF000
+#define WM8350_GP2_FN_MASK                      0x0F00
+#define WM8350_GP1_FN_MASK                      0x00F0
+#define WM8350_GP0_FN_MASK                      0x000F
+
+/*
+ * R141 (0x8D) - GPIO Function Select 2
+ */
+#define WM8350_GP7_FN_MASK                      0xF000
+#define WM8350_GP6_FN_MASK                      0x0F00
+#define WM8350_GP5_FN_MASK                      0x00F0
+#define WM8350_GP4_FN_MASK                      0x000F
+
+/*
+ * R142 (0x8E) - GPIO Function Select 3
+ */
+#define WM8350_GP11_FN_MASK                     0xF000
+#define WM8350_GP10_FN_MASK                     0x0F00
+#define WM8350_GP9_FN_MASK                      0x00F0
+#define WM8350_GP8_FN_MASK                      0x000F
+
+/*
+ * R143 (0x8F) - GPIO Function Select 4
+ */
+#define WM8350_GP12_FN_MASK                     0x000F
+
+/*
+ * R230 (0xE6) - GPIO Pin Status
+ */
+#define WM8350_GP12_LVL                         0x1000
+#define WM8350_GP11_LVL                         0x0800
+#define WM8350_GP10_LVL                         0x0400
+#define WM8350_GP9_LVL                          0x0200
+#define WM8350_GP8_LVL                          0x0100
+#define WM8350_GP7_LVL                          0x0080
+#define WM8350_GP6_LVL                          0x0040
+#define WM8350_GP5_LVL                          0x0020
+#define WM8350_GP4_LVL                          0x0010
+#define WM8350_GP3_LVL                          0x0008
+#define WM8350_GP2_LVL                          0x0004
+#define WM8350_GP1_LVL                          0x0002
+#define WM8350_GP0_LVL                          0x0001
+
+struct wm8350;
+
+int wm8350_gpio_config(struct wm8350 *wm8350, int gpio, int dir, int func,
+		       int pol, int pull, int invert, int debounce);
+
+struct wm8350_gpio {
+	struct platform_device *pdev;
+};
+
+/*
+ * GPIO Interrupts
+ */
+#define WM8350_IRQ_GPIO(x)                      (50 + x)
+
+#endif
diff --git a/include/linux/mfd/wm8350/pmic.h b/include/linux/mfd/wm8350/pmic.h
new file mode 100644
index 000000000000..69b69e07f62f
--- /dev/null
+++ b/include/linux/mfd/wm8350/pmic.h
@@ -0,0 +1,741 @@
+/*
+ * pmic.h  --  Power Managment Driver for Wolfson WM8350 PMIC
+ *
+ * Copyright 2007 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#ifndef __LINUX_MFD_WM8350_PMIC_H
+#define __LINUX_MFD_WM8350_PMIC_H
+
+/*
+ * Register values.
+ */
+
+#define WM8350_CURRENT_SINK_DRIVER_A            0xAC
+#define WM8350_CSA_FLASH_CONTROL                0xAD
+#define WM8350_CURRENT_SINK_DRIVER_B            0xAE
+#define WM8350_CSB_FLASH_CONTROL                0xAF
+#define WM8350_DCDC_LDO_REQUESTED               0xB0
+#define WM8350_DCDC_ACTIVE_OPTIONS              0xB1
+#define WM8350_DCDC_SLEEP_OPTIONS               0xB2
+#define WM8350_POWER_CHECK_COMPARATOR           0xB3
+#define WM8350_DCDC1_CONTROL                    0xB4
+#define WM8350_DCDC1_TIMEOUTS                   0xB5
+#define WM8350_DCDC1_LOW_POWER                  0xB6
+#define WM8350_DCDC2_CONTROL                    0xB7
+#define WM8350_DCDC2_TIMEOUTS                   0xB8
+#define WM8350_DCDC3_CONTROL                    0xBA
+#define WM8350_DCDC3_TIMEOUTS                   0xBB
+#define WM8350_DCDC3_LOW_POWER                  0xBC
+#define WM8350_DCDC4_CONTROL                    0xBD
+#define WM8350_DCDC4_TIMEOUTS                   0xBE
+#define WM8350_DCDC4_LOW_POWER                  0xBF
+#define WM8350_DCDC5_CONTROL                    0xC0
+#define WM8350_DCDC5_TIMEOUTS                   0xC1
+#define WM8350_DCDC6_CONTROL                    0xC3
+#define WM8350_DCDC6_TIMEOUTS                   0xC4
+#define WM8350_DCDC6_LOW_POWER                  0xC5
+#define WM8350_LIMIT_SWITCH_CONTROL             0xC7
+#define WM8350_LDO1_CONTROL                     0xC8
+#define WM8350_LDO1_TIMEOUTS                    0xC9
+#define WM8350_LDO1_LOW_POWER                   0xCA
+#define WM8350_LDO2_CONTROL                     0xCB
+#define WM8350_LDO2_TIMEOUTS                    0xCC
+#define WM8350_LDO2_LOW_POWER                   0xCD
+#define WM8350_LDO3_CONTROL                     0xCE
+#define WM8350_LDO3_TIMEOUTS                    0xCF
+#define WM8350_LDO3_LOW_POWER                   0xD0
+#define WM8350_LDO4_CONTROL                     0xD1
+#define WM8350_LDO4_TIMEOUTS                    0xD2
+#define WM8350_LDO4_LOW_POWER                   0xD3
+#define WM8350_VCC_FAULT_MASKS                  0xD7
+#define WM8350_MAIN_BANDGAP_CONTROL             0xD8
+#define WM8350_OSC_CONTROL                      0xD9
+#define WM8350_RTC_TICK_CONTROL                 0xDA
+#define WM8350_SECURITY                         0xDB
+#define WM8350_RAM_BIST_1                       0xDC
+#define WM8350_DCDC_LDO_STATUS                  0xE1
+#define WM8350_GPIO_PIN_STATUS                  0xE6
+
+#define WM8350_DCDC1_FORCE_PWM                  0xF8
+#define WM8350_DCDC3_FORCE_PWM                  0xFA
+#define WM8350_DCDC4_FORCE_PWM                  0xFB
+#define WM8350_DCDC6_FORCE_PWM                  0xFD
+
+/*
+ * R172 (0xAC) - Current Sink Driver A
+ */
+#define WM8350_CS1_HIB_MODE                     0x1000
+#define WM8350_CS1_HIB_MODE_MASK                0x1000
+#define WM8350_CS1_HIB_MODE_SHIFT                   12
+#define WM8350_CS1_ISEL_MASK                    0x003F
+#define WM8350_CS1_ISEL_SHIFT                        0
+
+/* Bit values for R172 (0xAC) */
+#define WM8350_CS1_HIB_MODE_DISABLE                  0
+#define WM8350_CS1_HIB_MODE_LEAVE                    1
+
+#define WM8350_CS1_ISEL_220M                      0x3F
+
+/*
+ * R173 (0xAD) - CSA Flash control
+ */
+#define WM8350_CS1_FLASH_MODE                   0x8000
+#define WM8350_CS1_TRIGSRC                      0x4000
+#define WM8350_CS1_DRIVE                        0x2000
+#define WM8350_CS1_FLASH_DUR_MASK               0x0300
+#define WM8350_CS1_OFF_RAMP_MASK                0x0030
+#define WM8350_CS1_ON_RAMP_MASK                 0x0003
+
+/*
+ * R174 (0xAE) - Current Sink Driver B
+ */
+#define WM8350_CS2_HIB_MODE                     0x1000
+#define WM8350_CS2_ISEL_MASK                    0x003F
+
+/*
+ * R175 (0xAF) - CSB Flash control
+ */
+#define WM8350_CS2_FLASH_MODE                   0x8000
+#define WM8350_CS2_TRIGSRC                      0x4000
+#define WM8350_CS2_DRIVE                        0x2000
+#define WM8350_CS2_FLASH_DUR_MASK               0x0300
+#define WM8350_CS2_OFF_RAMP_MASK                0x0030
+#define WM8350_CS2_ON_RAMP_MASK                 0x0003
+
+/*
+ * R176 (0xB0) - DCDC/LDO requested
+ */
+#define WM8350_LS_ENA                           0x8000
+#define WM8350_LDO4_ENA                         0x0800
+#define WM8350_LDO3_ENA                         0x0400
+#define WM8350_LDO2_ENA                         0x0200
+#define WM8350_LDO1_ENA                         0x0100
+#define WM8350_DC6_ENA                          0x0020
+#define WM8350_DC5_ENA                          0x0010
+#define WM8350_DC4_ENA                          0x0008
+#define WM8350_DC3_ENA                          0x0004
+#define WM8350_DC2_ENA                          0x0002
+#define WM8350_DC1_ENA                          0x0001
+
+/*
+ * R177 (0xB1) - DCDC Active options
+ */
+#define WM8350_PUTO_MASK                        0x3000
+#define WM8350_PWRUP_DELAY_MASK                 0x0300
+#define WM8350_DC6_ACTIVE                       0x0020
+#define WM8350_DC4_ACTIVE                       0x0008
+#define WM8350_DC3_ACTIVE                       0x0004
+#define WM8350_DC1_ACTIVE                       0x0001
+
+/*
+ * R178 (0xB2) - DCDC Sleep options
+ */
+#define WM8350_DC6_SLEEP                        0x0020
+#define WM8350_DC4_SLEEP                        0x0008
+#define WM8350_DC3_SLEEP                        0x0004
+#define WM8350_DC1_SLEEP                        0x0001
+
+/*
+ * R179 (0xB3) - Power-check comparator
+ */
+#define WM8350_PCCMP_ERRACT                     0x4000
+#define WM8350_PCCMP_RAIL                       0x0100
+#define WM8350_PCCMP_OFF_THR_MASK               0x0070
+#define WM8350_PCCMP_ON_THR_MASK                0x0007
+
+/*
+ * R180 (0xB4) - DCDC1 Control
+ */
+#define WM8350_DC1_OPFLT                        0x0400
+#define WM8350_DC1_VSEL_MASK                    0x007F
+#define WM8350_DC1_VSEL_SHIFT                        0
+
+/*
+ * R181 (0xB5) - DCDC1 Timeouts
+ */
+#define WM8350_DC1_ERRACT_MASK                  0xC000
+#define WM8350_DC1_ERRACT_SHIFT                     14
+#define WM8350_DC1_ENSLOT_MASK                  0x3C00
+#define WM8350_DC1_ENSLOT_SHIFT                     10
+#define WM8350_DC1_SDSLOT_MASK                  0x03C0
+#define WM8350_DC1_UVTO_MASK                    0x0030
+#define WM8350_DC1_SDSLOT_SHIFT                      6
+
+/* Bit values for R181 (0xB5) */
+#define WM8350_DC1_ERRACT_NONE                       0
+#define WM8350_DC1_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_DC1_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R182 (0xB6) - DCDC1 Low Power
+ */
+#define WM8350_DC1_HIB_MODE_MASK                0x7000
+#define WM8350_DC1_HIB_TRIG_MASK                0x0300
+#define WM8350_DC1_VIMG_MASK                    0x007F
+
+/*
+ * R183 (0xB7) - DCDC2 Control
+ */
+#define WM8350_DC2_MODE                         0x4000
+#define WM8350_DC2_MODE_MASK                    0x4000
+#define WM8350_DC2_MODE_SHIFT                       14
+#define WM8350_DC2_HIB_MODE                     0x1000
+#define WM8350_DC2_HIB_MODE_MASK                0x1000
+#define WM8350_DC2_HIB_MODE_SHIFT                   12
+#define WM8350_DC2_HIB_TRIG_MASK                0x0300
+#define WM8350_DC2_HIB_TRIG_SHIFT                    8
+#define WM8350_DC2_ILIM                         0x0040
+#define WM8350_DC2_ILIM_MASK                    0x0040
+#define WM8350_DC2_ILIM_SHIFT                        6
+#define WM8350_DC2_RMP_MASK                     0x0018
+#define WM8350_DC2_RMP_SHIFT                         3
+#define WM8350_DC2_FBSRC_MASK                   0x0003
+#define WM8350_DC2_FBSRC_SHIFT                       0
+
+/* Bit values for R183 (0xB7) */
+#define WM8350_DC2_MODE_BOOST                        0
+#define WM8350_DC2_MODE_SWITCH                       1
+
+#define WM8350_DC2_HIB_MODE_ACTIVE                   1
+#define WM8350_DC2_HIB_MODE_DISABLE                  0
+
+#define WM8350_DC2_HIB_TRIG_NONE                     0
+#define WM8350_DC2_HIB_TRIG_LPWR1                    1
+#define WM8350_DC2_HIB_TRIG_LPWR2                    2
+#define WM8350_DC2_HIB_TRIG_LPWR3                    3
+
+#define WM8350_DC2_ILIM_HIGH                         0
+#define WM8350_DC2_ILIM_LOW                          1
+
+#define WM8350_DC2_RMP_30V                           0
+#define WM8350_DC2_RMP_20V                           1
+#define WM8350_DC2_RMP_10V                           2
+#define WM8350_DC2_RMP_5V                            3
+
+#define WM8350_DC2_FBSRC_FB2                         0
+#define WM8350_DC2_FBSRC_ISINKA                      1
+#define WM8350_DC2_FBSRC_ISINKB                      2
+#define WM8350_DC2_FBSRC_USB                         3
+
+/*
+ * R184 (0xB8) - DCDC2 Timeouts
+ */
+#define WM8350_DC2_ERRACT_MASK                  0xC000
+#define WM8350_DC2_ERRACT_SHIFT                     14
+#define WM8350_DC2_ENSLOT_MASK                  0x3C00
+#define WM8350_DC2_ENSLOT_SHIFT                     10
+#define WM8350_DC2_SDSLOT_MASK                  0x03C0
+#define WM8350_DC2_UVTO_MASK                    0x0030
+
+/* Bit values for R184 (0xB8) */
+#define WM8350_DC2_ERRACT_NONE                       0
+#define WM8350_DC2_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_DC2_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R186 (0xBA) - DCDC3 Control
+ */
+#define WM8350_DC3_OPFLT                        0x0400
+#define WM8350_DC3_VSEL_MASK                    0x007F
+#define WM8350_DC3_VSEL_SHIFT                        0
+
+/*
+ * R187 (0xBB) - DCDC3 Timeouts
+ */
+#define WM8350_DC3_ERRACT_MASK                  0xC000
+#define WM8350_DC3_ERRACT_SHIFT                     14
+#define WM8350_DC3_ENSLOT_MASK                  0x3C00
+#define WM8350_DC3_ENSLOT_SHIFT                     10
+#define WM8350_DC3_SDSLOT_MASK                  0x03C0
+#define WM8350_DC3_UVTO_MASK                    0x0030
+#define WM8350_DC3_SDSLOT_SHIFT                      6
+
+/* Bit values for R187 (0xBB) */
+#define WM8350_DC3_ERRACT_NONE                       0
+#define WM8350_DC3_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_DC3_ERRACT_SHUTDOWN_SYS               2
+/*
+ * R188 (0xBC) - DCDC3 Low Power
+ */
+#define WM8350_DC3_HIB_MODE_MASK                0x7000
+#define WM8350_DC3_HIB_TRIG_MASK                0x0300
+#define WM8350_DC3_VIMG_MASK                    0x007F
+
+/*
+ * R189 (0xBD) - DCDC4 Control
+ */
+#define WM8350_DC4_OPFLT                        0x0400
+#define WM8350_DC4_VSEL_MASK                    0x007F
+#define WM8350_DC4_VSEL_SHIFT                        0
+
+/*
+ * R190 (0xBE) - DCDC4 Timeouts
+ */
+#define WM8350_DC4_ERRACT_MASK                  0xC000
+#define WM8350_DC4_ERRACT_SHIFT                     14
+#define WM8350_DC4_ENSLOT_MASK                  0x3C00
+#define WM8350_DC4_ENSLOT_SHIFT                     10
+#define WM8350_DC4_SDSLOT_MASK                  0x03C0
+#define WM8350_DC4_UVTO_MASK                    0x0030
+#define WM8350_DC4_SDSLOT_SHIFT                      6
+
+/* Bit values for R190 (0xBE) */
+#define WM8350_DC4_ERRACT_NONE                       0
+#define WM8350_DC4_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_DC4_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R191 (0xBF) - DCDC4 Low Power
+ */
+#define WM8350_DC4_HIB_MODE_MASK                0x7000
+#define WM8350_DC4_HIB_TRIG_MASK                0x0300
+#define WM8350_DC4_VIMG_MASK                    0x007F
+
+/*
+ * R192 (0xC0) - DCDC5 Control
+ */
+#define WM8350_DC5_MODE                         0x4000
+#define WM8350_DC5_MODE_MASK                    0x4000
+#define WM8350_DC5_MODE_SHIFT                       14
+#define WM8350_DC5_HIB_MODE                     0x1000
+#define WM8350_DC5_HIB_MODE_MASK                0x1000
+#define WM8350_DC5_HIB_MODE_SHIFT                   12
+#define WM8350_DC5_HIB_TRIG_MASK                0x0300
+#define WM8350_DC5_HIB_TRIG_SHIFT                    8
+#define WM8350_DC5_ILIM                         0x0040
+#define WM8350_DC5_ILIM_MASK                    0x0040
+#define WM8350_DC5_ILIM_SHIFT                        6
+#define WM8350_DC5_RMP_MASK                     0x0018
+#define WM8350_DC5_RMP_SHIFT                         3
+#define WM8350_DC5_FBSRC_MASK                   0x0003
+#define WM8350_DC5_FBSRC_SHIFT                       0
+
+/* Bit values for R192 (0xC0) */
+#define WM8350_DC5_MODE_BOOST                        0
+#define WM8350_DC5_MODE_SWITCH                       1
+
+#define WM8350_DC5_HIB_MODE_ACTIVE                   1
+#define WM8350_DC5_HIB_MODE_DISABLE                  0
+
+#define WM8350_DC5_HIB_TRIG_NONE                     0
+#define WM8350_DC5_HIB_TRIG_LPWR1                    1
+#define WM8350_DC5_HIB_TRIG_LPWR2                    2
+#define WM8350_DC5_HIB_TRIG_LPWR3                    3
+
+#define WM8350_DC5_ILIM_HIGH                         0
+#define WM8350_DC5_ILIM_LOW                          1
+
+#define WM8350_DC5_RMP_30V                           0
+#define WM8350_DC5_RMP_20V                           1
+#define WM8350_DC5_RMP_10V                           2
+#define WM8350_DC5_RMP_5V                            3
+
+#define WM8350_DC5_FBSRC_FB2                         0
+#define WM8350_DC5_FBSRC_ISINKA                      1
+#define WM8350_DC5_FBSRC_ISINKB                      2
+#define WM8350_DC5_FBSRC_USB                         3
+
+/*
+ * R193 (0xC1) - DCDC5 Timeouts
+ */
+#define WM8350_DC5_ERRACT_MASK                  0xC000
+#define WM8350_DC5_ERRACT_SHIFT                     14
+#define WM8350_DC5_ENSLOT_MASK                  0x3C00
+#define WM8350_DC5_ENSLOT_SHIFT                     10
+#define WM8350_DC5_SDSLOT_MASK                  0x03C0
+#define WM8350_DC5_UVTO_MASK                    0x0030
+#define WM8350_DC5_SDSLOT_SHIFT                      6
+
+/* Bit values for R193 (0xC1) */
+#define WM8350_DC5_ERRACT_NONE                       0
+#define WM8350_DC5_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_DC5_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R195 (0xC3) - DCDC6 Control
+ */
+#define WM8350_DC6_OPFLT                        0x0400
+#define WM8350_DC6_VSEL_MASK                    0x007F
+#define WM8350_DC6_VSEL_SHIFT                        0
+
+/*
+ * R196 (0xC4) - DCDC6 Timeouts
+ */
+#define WM8350_DC6_ERRACT_MASK                  0xC000
+#define WM8350_DC6_ERRACT_SHIFT                     14
+#define WM8350_DC6_ENSLOT_MASK                  0x3C00
+#define WM8350_DC6_ENSLOT_SHIFT                     10
+#define WM8350_DC6_SDSLOT_MASK                  0x03C0
+#define WM8350_DC6_UVTO_MASK                    0x0030
+#define WM8350_DC6_SDSLOT_SHIFT                      6
+
+/* Bit values for R196 (0xC4) */
+#define WM8350_DC6_ERRACT_NONE                       0
+#define WM8350_DC6_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_DC6_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R197 (0xC5) - DCDC6 Low Power
+ */
+#define WM8350_DC6_HIB_MODE_MASK                0x7000
+#define WM8350_DC6_HIB_TRIG_MASK                0x0300
+#define WM8350_DC6_VIMG_MASK                    0x007F
+
+/*
+ * R199 (0xC7) - Limit Switch Control
+ */
+#define WM8350_LS_ERRACT_MASK                   0xC000
+#define WM8350_LS_ERRACT_SHIFT                      14
+#define WM8350_LS_ENSLOT_MASK                   0x3C00
+#define WM8350_LS_ENSLOT_SHIFT                      10
+#define WM8350_LS_SDSLOT_MASK                   0x03C0
+#define WM8350_LS_SDSLOT_SHIFT                       6
+#define WM8350_LS_HIB_MODE                      0x0010
+#define WM8350_LS_HIB_MODE_MASK                 0x0010
+#define WM8350_LS_HIB_MODE_SHIFT                     4
+#define WM8350_LS_HIB_PROT                      0x0002
+#define WM8350_LS_HIB_PROT_MASK                 0x0002
+#define WM8350_LS_HIB_PROT_SHIFT                     1
+#define WM8350_LS_PROT                          0x0001
+#define WM8350_LS_PROT_MASK                     0x0001
+#define WM8350_LS_PROT_SHIFT                         0
+
+/* Bit values for R199 (0xC7) */
+#define WM8350_LS_ERRACT_NONE                       0
+#define WM8350_LS_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_LS_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R200 (0xC8) - LDO1 Control
+ */
+#define WM8350_LDO1_SWI                         0x4000
+#define WM8350_LDO1_OPFLT                       0x0400
+#define WM8350_LDO1_VSEL_MASK                   0x001F
+#define WM8350_LDO1_VSEL_SHIFT                       0
+
+/*
+ * R201 (0xC9) - LDO1 Timeouts
+ */
+#define WM8350_LDO1_ERRACT_MASK                 0xC000
+#define WM8350_LDO1_ERRACT_SHIFT                    14
+#define WM8350_LDO1_ENSLOT_MASK                 0x3C00
+#define WM8350_LDO1_ENSLOT_SHIFT                    10
+#define WM8350_LDO1_SDSLOT_MASK                 0x03C0
+#define WM8350_LDO1_UVTO_MASK                   0x0030
+#define WM8350_LDO1_SDSLOT_SHIFT                     6
+
+/* Bit values for R201 (0xC9) */
+#define WM8350_LDO1_ERRACT_NONE                       0
+#define WM8350_LDO1_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_LDO1_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R202 (0xCA) - LDO1 Low Power
+ */
+#define WM8350_LDO1_HIB_MODE_MASK               0x3000
+#define WM8350_LDO1_HIB_TRIG_MASK               0x0300
+#define WM8350_LDO1_VIMG_MASK                   0x001F
+#define WM8350_LDO1_HIB_MODE_DIS		(0x1 << 12)
+
+
+/*
+ * R203 (0xCB) - LDO2 Control
+ */
+#define WM8350_LDO2_SWI                         0x4000
+#define WM8350_LDO2_OPFLT                       0x0400
+#define WM8350_LDO2_VSEL_MASK                   0x001F
+#define WM8350_LDO2_VSEL_SHIFT                       0
+
+/*
+ * R204 (0xCC) - LDO2 Timeouts
+ */
+#define WM8350_LDO2_ERRACT_MASK                 0xC000
+#define WM8350_LDO2_ERRACT_SHIFT                    14
+#define WM8350_LDO2_ENSLOT_MASK                 0x3C00
+#define WM8350_LDO2_ENSLOT_SHIFT                    10
+#define WM8350_LDO2_SDSLOT_MASK                 0x03C0
+#define WM8350_LDO2_SDSLOT_SHIFT                     6
+
+/* Bit values for R204 (0xCC) */
+#define WM8350_LDO2_ERRACT_NONE                       0
+#define WM8350_LDO2_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_LDO2_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R205 (0xCD) - LDO2 Low Power
+ */
+#define WM8350_LDO2_HIB_MODE_MASK               0x3000
+#define WM8350_LDO2_HIB_TRIG_MASK               0x0300
+#define WM8350_LDO2_VIMG_MASK                   0x001F
+
+/*
+ * R206 (0xCE) - LDO3 Control
+ */
+#define WM8350_LDO3_SWI                         0x4000
+#define WM8350_LDO3_OPFLT                       0x0400
+#define WM8350_LDO3_VSEL_MASK                   0x001F
+#define WM8350_LDO3_VSEL_SHIFT                       0
+
+/*
+ * R207 (0xCF) - LDO3 Timeouts
+ */
+#define WM8350_LDO3_ERRACT_MASK                 0xC000
+#define WM8350_LDO3_ERRACT_SHIFT                    14
+#define WM8350_LDO3_ENSLOT_MASK                 0x3C00
+#define WM8350_LDO3_ENSLOT_SHIFT                    10
+#define WM8350_LDO3_SDSLOT_MASK                 0x03C0
+#define WM8350_LDO3_UVTO_MASK                   0x0030
+#define WM8350_LDO3_SDSLOT_SHIFT                     6
+
+/* Bit values for R207 (0xCF) */
+#define WM8350_LDO3_ERRACT_NONE                       0
+#define WM8350_LDO3_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_LDO3_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R208 (0xD0) - LDO3 Low Power
+ */
+#define WM8350_LDO3_HIB_MODE_MASK               0x3000
+#define WM8350_LDO3_HIB_TRIG_MASK               0x0300
+#define WM8350_LDO3_VIMG_MASK                   0x001F
+
+/*
+ * R209 (0xD1) - LDO4 Control
+ */
+#define WM8350_LDO4_SWI                         0x4000
+#define WM8350_LDO4_OPFLT                       0x0400
+#define WM8350_LDO4_VSEL_MASK                   0x001F
+#define WM8350_LDO4_VSEL_SHIFT                       0
+
+/*
+ * R210 (0xD2) - LDO4 Timeouts
+ */
+#define WM8350_LDO4_ERRACT_MASK                 0xC000
+#define WM8350_LDO4_ERRACT_SHIFT                    14
+#define WM8350_LDO4_ENSLOT_MASK                 0x3C00
+#define WM8350_LDO4_ENSLOT_SHIFT                    10
+#define WM8350_LDO4_SDSLOT_MASK                 0x03C0
+#define WM8350_LDO4_UVTO_MASK                   0x0030
+#define WM8350_LDO4_SDSLOT_SHIFT                     6
+
+/* Bit values for R210 (0xD2) */
+#define WM8350_LDO4_ERRACT_NONE                       0
+#define WM8350_LDO4_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_LDO4_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R211 (0xD3) - LDO4 Low Power
+ */
+#define WM8350_LDO4_HIB_MODE_MASK               0x3000
+#define WM8350_LDO4_HIB_TRIG_MASK               0x0300
+#define WM8350_LDO4_VIMG_MASK                   0x001F
+
+/*
+ * R215 (0xD7) - VCC_FAULT Masks
+ */
+#define WM8350_LS_FAULT                         0x8000
+#define WM8350_LDO4_FAULT                       0x0800
+#define WM8350_LDO3_FAULT                       0x0400
+#define WM8350_LDO2_FAULT                       0x0200
+#define WM8350_LDO1_FAULT                       0x0100
+#define WM8350_DC6_FAULT                        0x0020
+#define WM8350_DC5_FAULT                        0x0010
+#define WM8350_DC4_FAULT                        0x0008
+#define WM8350_DC3_FAULT                        0x0004
+#define WM8350_DC2_FAULT                        0x0002
+#define WM8350_DC1_FAULT                        0x0001
+
+/*
+ * R216 (0xD8) - Main Bandgap Control
+ */
+#define WM8350_MBG_LOAD_FUSES                   0x8000
+#define WM8350_MBG_FUSE_WPREP                   0x4000
+#define WM8350_MBG_FUSE_WRITE                   0x2000
+#define WM8350_MBG_FUSE_TRIM_MASK               0x1F00
+#define WM8350_MBG_TRIM_SRC                     0x0020
+#define WM8350_MBG_USER_TRIM_MASK               0x001F
+
+/*
+ * R217 (0xD9) - OSC Control
+ */
+#define WM8350_OSC_LOAD_FUSES                   0x8000
+#define WM8350_OSC_FUSE_WPREP                   0x4000
+#define WM8350_OSC_FUSE_WRITE                   0x2000
+#define WM8350_OSC_FUSE_TRIM_MASK               0x0F00
+#define WM8350_OSC_TRIM_SRC                     0x0020
+#define WM8350_OSC_USER_TRIM_MASK               0x000F
+
+/*
+ * R248 (0xF8) - DCDC1 Force PWM
+ */
+#define WM8350_DCDC1_FORCE_PWM_ENA              0x0010
+
+/*
+ * R250 (0xFA) - DCDC3 Force PWM
+ */
+#define WM8350_DCDC3_FORCE_PWM_ENA              0x0010
+
+/*
+ * R251 (0xFB) - DCDC4 Force PWM
+ */
+#define WM8350_DCDC4_FORCE_PWM_ENA              0x0010
+
+/*
+ * R253 (0xFD) - DCDC1 Force PWM
+ */
+#define WM8350_DCDC6_FORCE_PWM_ENA              0x0010
+
+/*
+ * DCDC's
+ */
+#define WM8350_DCDC_1				0
+#define WM8350_DCDC_2				1
+#define WM8350_DCDC_3				2
+#define WM8350_DCDC_4				3
+#define WM8350_DCDC_5				4
+#define WM8350_DCDC_6				5
+
+/* DCDC modes */
+#define WM8350_DCDC_ACTIVE_STANDBY		0
+#define WM8350_DCDC_ACTIVE_PULSE		1
+#define WM8350_DCDC_SLEEP_NORMAL		0
+#define WM8350_DCDC_SLEEP_LOW			1
+
+/* DCDC Low power (Hibernate) mode */
+#define WM8350_DCDC_HIB_MODE_CUR		(0 << 12)
+#define WM8350_DCDC_HIB_MODE_IMAGE		(1 << 12)
+#define WM8350_DCDC_HIB_MODE_STANDBY		(2 << 12)
+#define WM8350_DCDC_HIB_MODE_LDO		(4 << 12)
+#define WM8350_DCDC_HIB_MODE_LDO_IM		(5 << 12)
+#define WM8350_DCDC_HIB_MODE_DIS		(7 << 12)
+#define WM8350_DCDC_HIB_MODE_MASK		(7 << 12)
+
+/* DCDC Low Power (Hibernate) signal */
+#define WM8350_DCDC_HIB_SIG_REG			(0 << 8)
+#define WM8350_DCDC_HIB_SIG_LPWR1		(1 << 8)
+#define WM8350_DCDC_HIB_SIG_LPWR2		(2 << 8)
+#define WM8350_DCDC_HIB_SIG_LPWR3		(3 << 8)
+
+/* LDO Low power (Hibernate) mode */
+#define WM8350_LDO_HIB_MODE_IMAGE		(0 << 0)
+#define WM8350_LDO_HIB_MODE_DIS			(1 << 0)
+
+/* LDO Low Power (Hibernate) signal */
+#define WM8350_LDO_HIB_SIG_REG			(0 << 8)
+#define WM8350_LDO_HIB_SIG_LPWR1		(1 << 8)
+#define WM8350_LDO_HIB_SIG_LPWR2		(2 << 8)
+#define WM8350_LDO_HIB_SIG_LPWR3		(3 << 8)
+
+/*
+ * LDOs
+ */
+#define WM8350_LDO_1				6
+#define WM8350_LDO_2				7
+#define WM8350_LDO_3				8
+#define WM8350_LDO_4				9
+
+/*
+ * ISINKs
+ */
+#define WM8350_ISINK_A				10
+#define WM8350_ISINK_B				11
+
+#define WM8350_ISINK_MODE_BOOST			0
+#define WM8350_ISINK_MODE_SWITCH		1
+#define WM8350_ISINK_ILIM_NORMAL		0
+#define WM8350_ISINK_ILIM_LOW			1
+
+#define WM8350_ISINK_FLASH_DISABLE		0
+#define WM8350_ISINK_FLASH_ENABLE		1
+#define WM8350_ISINK_FLASH_TRIG_BIT		0
+#define WM8350_ISINK_FLASH_TRIG_GPIO		1
+#define WM8350_ISINK_FLASH_MODE_EN		(1 << 13)
+#define WM8350_ISINK_FLASH_MODE_DIS		(0 << 13)
+#define WM8350_ISINK_FLASH_DUR_32MS		(0 << 8)
+#define WM8350_ISINK_FLASH_DUR_64MS		(1 << 8)
+#define WM8350_ISINK_FLASH_DUR_96MS		(2 << 8)
+#define WM8350_ISINK_FLASH_DUR_1024MS		(3 << 8)
+#define WM8350_ISINK_FLASH_ON_INSTANT		(0 << 4)
+#define WM8350_ISINK_FLASH_ON_0_25S		(1 << 4)
+#define WM8350_ISINK_FLASH_ON_0_50S		(2 << 4)
+#define WM8350_ISINK_FLASH_ON_1_00S		(3 << 4)
+#define WM8350_ISINK_FLASH_ON_1_95S		(1 << 4)
+#define WM8350_ISINK_FLASH_ON_3_91S		(2 << 4)
+#define WM8350_ISINK_FLASH_ON_7_80S		(3 << 4)
+#define WM8350_ISINK_FLASH_OFF_INSTANT		(0 << 0)
+#define WM8350_ISINK_FLASH_OFF_0_25S		(1 << 0)
+#define WM8350_ISINK_FLASH_OFF_0_50S		(2 << 0)
+#define WM8350_ISINK_FLASH_OFF_1_00S		(3 << 0)
+#define WM8350_ISINK_FLASH_OFF_1_95S		(1 << 0)
+#define WM8350_ISINK_FLASH_OFF_3_91S		(2 << 0)
+#define WM8350_ISINK_FLASH_OFF_7_80S		(3 << 0)
+
+/*
+ * Regulator Interrupts.
+ */
+#define WM8350_IRQ_CS1				13
+#define WM8350_IRQ_CS2				14
+#define WM8350_IRQ_UV_LDO4			25
+#define WM8350_IRQ_UV_LDO3			26
+#define WM8350_IRQ_UV_LDO2			27
+#define WM8350_IRQ_UV_LDO1			28
+#define WM8350_IRQ_UV_DC6			29
+#define WM8350_IRQ_UV_DC5			30
+#define WM8350_IRQ_UV_DC4			31
+#define WM8350_IRQ_UV_DC3			32
+#define WM8350_IRQ_UV_DC2			33
+#define WM8350_IRQ_UV_DC1			34
+#define WM8350_IRQ_OC_LS			35
+
+#define NUM_WM8350_REGULATORS			12
+
+struct wm8350;
+struct platform_device;
+struct regulator_init_data;
+
+struct wm8350_pmic {
+	/* ISINK to DCDC mapping */
+	int isink_A_dcdc;
+	int isink_B_dcdc;
+
+	/* hibernate configs */
+	u16 dcdc1_hib_mode;
+	u16 dcdc3_hib_mode;
+	u16 dcdc4_hib_mode;
+	u16 dcdc6_hib_mode;
+
+	/* regulator devices */
+	struct platform_device *pdev[NUM_WM8350_REGULATORS];
+};
+
+int wm8350_register_regulator(struct wm8350 *wm8350, int reg,
+			      struct regulator_init_data *initdata);
+
+/*
+ * Additional DCDC control not supported via regulator API
+ */
+int wm8350_dcdc_set_slot(struct wm8350 *wm8350, int dcdc, u16 start,
+			 u16 stop, u16 fault);
+int wm8350_dcdc25_set_mode(struct wm8350 *wm8350, int dcdc, u16 mode,
+			   u16 ilim, u16 ramp, u16 feedback);
+
+/*
+ * Additional LDO control not supported via regulator API
+ */
+int wm8350_ldo_set_slot(struct wm8350 *wm8350, int ldo, u16 start, u16 stop);
+
+/*
+ * Additional ISINK control not supported via regulator API
+ */
+int wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode,
+			   u16 trigger, u16 duration, u16 on_ramp,
+			   u16 off_ramp, u16 drive);
+
+#endif
diff --git a/include/linux/mfd/wm8350/rtc.h b/include/linux/mfd/wm8350/rtc.h
new file mode 100644
index 000000000000..dfda69e9f440
--- /dev/null
+++ b/include/linux/mfd/wm8350/rtc.h
@@ -0,0 +1,266 @@
+/*
+ * rtc.h  --  RTC driver for Wolfson WM8350 PMIC
+ *
+ * Copyright 2007 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#ifndef __LINUX_MFD_WM8350_RTC_H
+#define __LINUX_MFD_WM8350_RTC_H
+
+#include <linux/platform_device.h>
+
+/*
+ * Register values.
+ */
+#define WM8350_RTC_SECONDS_MINUTES              0x10
+#define WM8350_RTC_HOURS_DAY                    0x11
+#define WM8350_RTC_DATE_MONTH                   0x12
+#define WM8350_RTC_YEAR                         0x13
+#define WM8350_ALARM_SECONDS_MINUTES            0x14
+#define WM8350_ALARM_HOURS_DAY                  0x15
+#define WM8350_ALARM_DATE_MONTH                 0x16
+#define WM8350_RTC_TIME_CONTROL                 0x17
+
+/*
+ * R16 (0x10) - RTC Seconds/Minutes
+ */
+#define WM8350_RTC_MINS_MASK                    0x7F00
+#define WM8350_RTC_MINS_SHIFT                        8
+#define WM8350_RTC_SECS_MASK                    0x007F
+#define WM8350_RTC_SECS_SHIFT                        0
+
+/*
+ * R17 (0x11) - RTC Hours/Day
+ */
+#define WM8350_RTC_DAY_MASK                     0x0700
+#define WM8350_RTC_DAY_SHIFT                         8
+#define WM8350_RTC_HPM_MASK                     0x0020
+#define WM8350_RTC_HPM_SHIFT                         5
+#define WM8350_RTC_HRS_MASK                     0x001F
+#define WM8350_RTC_HRS_SHIFT                         0
+
+/* Bit values for R21 (0x15) */
+#define WM8350_RTC_DAY_SUN                           1
+#define WM8350_RTC_DAY_MON                           2
+#define WM8350_RTC_DAY_TUE                           3
+#define WM8350_RTC_DAY_WED                           4
+#define WM8350_RTC_DAY_THU                           5
+#define WM8350_RTC_DAY_FRI                           6
+#define WM8350_RTC_DAY_SAT                           7
+
+#define WM8350_RTC_HPM_AM                            0
+#define WM8350_RTC_HPM_PM                            1
+
+/*
+ * R18 (0x12) - RTC Date/Month
+ */
+#define WM8350_RTC_MTH_MASK                     0x1F00
+#define WM8350_RTC_MTH_SHIFT                         8
+#define WM8350_RTC_DATE_MASK                    0x003F
+#define WM8350_RTC_DATE_SHIFT                        0
+
+/* Bit values for R22 (0x16) */
+#define WM8350_RTC_MTH_JAN                           1
+#define WM8350_RTC_MTH_FEB                           2
+#define WM8350_RTC_MTH_MAR                           3
+#define WM8350_RTC_MTH_APR                           4
+#define WM8350_RTC_MTH_MAY                           5
+#define WM8350_RTC_MTH_JUN                           6
+#define WM8350_RTC_MTH_JUL                           7
+#define WM8350_RTC_MTH_AUG                           8
+#define WM8350_RTC_MTH_SEP                           9
+#define WM8350_RTC_MTH_OCT                          10
+#define WM8350_RTC_MTH_NOV                          11
+#define WM8350_RTC_MTH_DEC                          12
+#define WM8350_RTC_MTH_JAN_BCD                    0x01
+#define WM8350_RTC_MTH_FEB_BCD                    0x02
+#define WM8350_RTC_MTH_MAR_BCD                    0x03
+#define WM8350_RTC_MTH_APR_BCD                    0x04
+#define WM8350_RTC_MTH_MAY_BCD                    0x05
+#define WM8350_RTC_MTH_JUN_BCD                    0x06
+#define WM8350_RTC_MTH_JUL_BCD                    0x07
+#define WM8350_RTC_MTH_AUG_BCD                    0x08
+#define WM8350_RTC_MTH_SEP_BCD                    0x09
+#define WM8350_RTC_MTH_OCT_BCD                    0x10
+#define WM8350_RTC_MTH_NOV_BCD                    0x11
+#define WM8350_RTC_MTH_DEC_BCD                    0x12
+
+/*
+ * R19 (0x13) - RTC Year
+ */
+#define WM8350_RTC_YHUNDREDS_MASK               0x3F00
+#define WM8350_RTC_YHUNDREDS_SHIFT                   8
+#define WM8350_RTC_YUNITS_MASK                  0x00FF
+#define WM8350_RTC_YUNITS_SHIFT                      0
+
+/*
+ * R20 (0x14) - Alarm Seconds/Minutes
+ */
+#define WM8350_RTC_ALMMINS_MASK                 0x7F00
+#define WM8350_RTC_ALMMINS_SHIFT                     8
+#define WM8350_RTC_ALMSECS_MASK                 0x007F
+#define WM8350_RTC_ALMSECS_SHIFT                     0
+
+/* Bit values for R20 (0x14) */
+#define WM8350_RTC_ALMMINS_DONT_CARE                -1
+#define WM8350_RTC_ALMSECS_DONT_CARE                -1
+
+/*
+ * R21 (0x15) - Alarm Hours/Day
+ */
+#define WM8350_RTC_ALMDAY_MASK                  0x0F00
+#define WM8350_RTC_ALMDAY_SHIFT                      8
+#define WM8350_RTC_ALMHPM_MASK                  0x0020
+#define WM8350_RTC_ALMHPM_SHIFT                      5
+#define WM8350_RTC_ALMHRS_MASK                  0x001F
+#define WM8350_RTC_ALMHRS_SHIFT                      0
+
+/* Bit values for R21 (0x15) */
+#define WM8350_RTC_ALMDAY_DONT_CARE                 -1
+#define WM8350_RTC_ALMDAY_SUN                        1
+#define WM8350_RTC_ALMDAY_MON                        2
+#define WM8350_RTC_ALMDAY_TUE                        3
+#define WM8350_RTC_ALMDAY_WED                        4
+#define WM8350_RTC_ALMDAY_THU                        5
+#define WM8350_RTC_ALMDAY_FRI                        6
+#define WM8350_RTC_ALMDAY_SAT                        7
+
+#define WM8350_RTC_ALMHPM_AM                         0
+#define WM8350_RTC_ALMHPM_PM                         1
+
+#define WM8350_RTC_ALMHRS_DONT_CARE                 -1
+
+/*
+ * R22 (0x16) - Alarm Date/Month
+ */
+#define WM8350_RTC_ALMMTH_MASK                  0x1F00
+#define WM8350_RTC_ALMMTH_SHIFT                      8
+#define WM8350_RTC_ALMDATE_MASK                 0x003F
+#define WM8350_RTC_ALMDATE_SHIFT                     0
+
+/* Bit values for R22 (0x16) */
+#define WM8350_RTC_ALMDATE_DONT_CARE                -1
+
+#define WM8350_RTC_ALMMTH_DONT_CARE                 -1
+#define WM8350_RTC_ALMMTH_JAN                        1
+#define WM8350_RTC_ALMMTH_FEB                        2
+#define WM8350_RTC_ALMMTH_MAR                        3
+#define WM8350_RTC_ALMMTH_APR                        4
+#define WM8350_RTC_ALMMTH_MAY                        5
+#define WM8350_RTC_ALMMTH_JUN                        6
+#define WM8350_RTC_ALMMTH_JUL                        7
+#define WM8350_RTC_ALMMTH_AUG                        8
+#define WM8350_RTC_ALMMTH_SEP                        9
+#define WM8350_RTC_ALMMTH_OCT                       10
+#define WM8350_RTC_ALMMTH_NOV                       11
+#define WM8350_RTC_ALMMTH_DEC                       12
+#define WM8350_RTC_ALMMTH_JAN_BCD                 0x01
+#define WM8350_RTC_ALMMTH_FEB_BCD                 0x02
+#define WM8350_RTC_ALMMTH_MAR_BCD                 0x03
+#define WM8350_RTC_ALMMTH_APR_BCD                 0x04
+#define WM8350_RTC_ALMMTH_MAY_BCD                 0x05
+#define WM8350_RTC_ALMMTH_JUN_BCD                 0x06
+#define WM8350_RTC_ALMMTH_JUL_BCD                 0x07
+#define WM8350_RTC_ALMMTH_AUG_BCD                 0x08
+#define WM8350_RTC_ALMMTH_SEP_BCD                 0x09
+#define WM8350_RTC_ALMMTH_OCT_BCD                 0x10
+#define WM8350_RTC_ALMMTH_NOV_BCD                 0x11
+#define WM8350_RTC_ALMMTH_DEC_BCD                 0x12
+
+/*
+ * R23 (0x17) - RTC Time Control
+ */
+#define WM8350_RTC_BCD                          0x8000
+#define WM8350_RTC_BCD_MASK                     0x8000
+#define WM8350_RTC_BCD_SHIFT                        15
+#define WM8350_RTC_12HR                         0x4000
+#define WM8350_RTC_12HR_MASK                    0x4000
+#define WM8350_RTC_12HR_SHIFT                       14
+#define WM8350_RTC_DST                          0x2000
+#define WM8350_RTC_DST_MASK                     0x2000
+#define WM8350_RTC_DST_SHIFT                        13
+#define WM8350_RTC_SET                          0x0800
+#define WM8350_RTC_SET_MASK                     0x0800
+#define WM8350_RTC_SET_SHIFT                        11
+#define WM8350_RTC_STS                          0x0400
+#define WM8350_RTC_STS_MASK                     0x0400
+#define WM8350_RTC_STS_SHIFT                        10
+#define WM8350_RTC_ALMSET                       0x0200
+#define WM8350_RTC_ALMSET_MASK                  0x0200
+#define WM8350_RTC_ALMSET_SHIFT                      9
+#define WM8350_RTC_ALMSTS                       0x0100
+#define WM8350_RTC_ALMSTS_MASK                  0x0100
+#define WM8350_RTC_ALMSTS_SHIFT                      8
+#define WM8350_RTC_PINT                         0x0070
+#define WM8350_RTC_PINT_MASK                    0x0070
+#define WM8350_RTC_PINT_SHIFT                        4
+#define WM8350_RTC_DSW                          0x000F
+#define WM8350_RTC_DSW_MASK                     0x000F
+#define WM8350_RTC_DSW_SHIFT                         0
+
+/* Bit values for R23 (0x17) */
+#define WM8350_RTC_BCD_BINARY                        0
+#define WM8350_RTC_BCD_BCD                           1
+
+#define WM8350_RTC_12HR_24HR                         0
+#define WM8350_RTC_12HR_12HR                         1
+
+#define WM8350_RTC_DST_DISABLED                      0
+#define WM8350_RTC_DST_ENABLED                       1
+
+#define WM8350_RTC_SET_RUN                           0
+#define WM8350_RTC_SET_SET                           1
+
+#define WM8350_RTC_STS_RUNNING                       0
+#define WM8350_RTC_STS_STOPPED                       1
+
+#define WM8350_RTC_ALMSET_RUN                        0
+#define WM8350_RTC_ALMSET_SET                        1
+
+#define WM8350_RTC_ALMSTS_RUNNING                    0
+#define WM8350_RTC_ALMSTS_STOPPED                    1
+
+#define WM8350_RTC_PINT_DISABLED                     0
+#define WM8350_RTC_PINT_SECS                         1
+#define WM8350_RTC_PINT_MINS                         2
+#define WM8350_RTC_PINT_HRS                          3
+#define WM8350_RTC_PINT_DAYS                         4
+#define WM8350_RTC_PINT_MTHS                         5
+
+#define WM8350_RTC_DSW_DISABLED                      0
+#define WM8350_RTC_DSW_1HZ                           1
+#define WM8350_RTC_DSW_2HZ                           2
+#define WM8350_RTC_DSW_4HZ                           3
+#define WM8350_RTC_DSW_8HZ                           4
+#define WM8350_RTC_DSW_16HZ                          5
+#define WM8350_RTC_DSW_32HZ                          6
+#define WM8350_RTC_DSW_64HZ                          7
+#define WM8350_RTC_DSW_128HZ                         8
+#define WM8350_RTC_DSW_256HZ                         9
+#define WM8350_RTC_DSW_512HZ                        10
+#define WM8350_RTC_DSW_1024HZ                       11
+
+/*
+ * R218 (0xDA) - RTC Tick Control
+ */
+#define WM8350_RTC_TICKSTS                      0x4000
+#define WM8350_RTC_CLKSRC                       0x2000
+#define WM8350_RTC_TRIM_MASK                    0x03FF
+
+/*
+ * RTC Interrupts.
+ */
+#define WM8350_IRQ_RTC_PER			7
+#define WM8350_IRQ_RTC_SEC			8
+#define WM8350_IRQ_RTC_ALM			9
+
+struct wm8350_rtc {
+	struct platform_device *pdev;
+};
+
+#endif
diff --git a/include/linux/mfd/wm8350/supply.h b/include/linux/mfd/wm8350/supply.h
new file mode 100644
index 000000000000..1c8f3cde79b0
--- /dev/null
+++ b/include/linux/mfd/wm8350/supply.h
@@ -0,0 +1,111 @@
+/*
+ * supply.h  --  Power Supply Driver for Wolfson WM8350 PMIC
+ *
+ * Copyright 2007 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#ifndef __LINUX_MFD_WM8350_SUPPLY_H_
+#define __LINUX_MFD_WM8350_SUPPLY_H_
+
+#include <linux/platform_device.h>
+
+/*
+ * Charger registers
+ */
+#define WM8350_BATTERY_CHARGER_CONTROL_1        0xA8
+#define WM8350_BATTERY_CHARGER_CONTROL_2        0xA9
+#define WM8350_BATTERY_CHARGER_CONTROL_3        0xAA
+
+/*
+ * R168 (0xA8) - Battery Charger Control 1
+ */
+#define WM8350_CHG_ENA_R168                     0x8000
+#define WM8350_CHG_THR                          0x2000
+#define WM8350_CHG_EOC_SEL_MASK                 0x1C00
+#define WM8350_CHG_TRICKLE_TEMP_CHOKE           0x0200
+#define WM8350_CHG_TRICKLE_USB_CHOKE            0x0100
+#define WM8350_CHG_RECOVER_T                    0x0080
+#define WM8350_CHG_END_ACT                      0x0040
+#define WM8350_CHG_FAST                         0x0020
+#define WM8350_CHG_FAST_USB_THROTTLE            0x0010
+#define WM8350_CHG_NTC_MON                      0x0008
+#define WM8350_CHG_BATT_HOT_MON                 0x0004
+#define WM8350_CHG_BATT_COLD_MON                0x0002
+#define WM8350_CHG_CHIP_TEMP_MON                0x0001
+
+/*
+ * R169 (0xA9) - Battery Charger Control 2
+ */
+#define WM8350_CHG_ACTIVE                       0x8000
+#define WM8350_CHG_PAUSE                        0x4000
+#define WM8350_CHG_STS_MASK                     0x3000
+#define WM8350_CHG_TIME_MASK                    0x0F00
+#define WM8350_CHG_MASK_WALL_FB                 0x0080
+#define WM8350_CHG_TRICKLE_SEL                  0x0040
+#define WM8350_CHG_VSEL_MASK                    0x0030
+#define WM8350_CHG_ISEL_MASK                    0x000F
+#define WM8350_CHG_STS_OFF                      0x0000
+#define WM8350_CHG_STS_TRICKLE                  0x1000
+#define WM8350_CHG_STS_FAST                     0x2000
+
+/*
+ * R170 (0xAA) - Battery Charger Control 3
+ */
+#define WM8350_CHG_THROTTLE_T_MASK              0x0060
+#define WM8350_CHG_SMART                        0x0010
+#define WM8350_CHG_TIMER_ADJT_MASK              0x000F
+
+/*
+ * Charger Interrupts
+ */
+#define WM8350_IRQ_CHG_BAT_HOT			0
+#define WM8350_IRQ_CHG_BAT_COLD			1
+#define WM8350_IRQ_CHG_BAT_FAIL			2
+#define WM8350_IRQ_CHG_TO			3
+#define WM8350_IRQ_CHG_END			4
+#define WM8350_IRQ_CHG_START			5
+#define WM8350_IRQ_CHG_FAST_RDY			6
+#define WM8350_IRQ_CHG_VBATT_LT_3P9		10
+#define WM8350_IRQ_CHG_VBATT_LT_3P1		11
+#define WM8350_IRQ_CHG_VBATT_LT_2P85		12
+
+/*
+ * Charger Policy
+ */
+#define WM8350_CHG_TRICKLE_50mA			(0 << 6)
+#define WM8350_CHG_TRICKLE_100mA		(1 << 6)
+#define WM8350_CHG_4_05V			(0 << 4)
+#define WM8350_CHG_4_10V			(1 << 4)
+#define WM8350_CHG_4_15V			(2 << 4)
+#define WM8350_CHG_4_20V			(3 << 4)
+#define WM8350_CHG_FAST_LIMIT_mA(x)		((x / 50) & 0xf)
+#define WM8350_CHG_EOC_mA(x)			(((x - 10) & 0x7) << 10)
+#define WM8350_CHG_TRICKLE_3_1V			(0 << 13)
+#define WM8350_CHG_TRICKLE_3_9V			(1 << 13)
+
+/*
+ * Supply Registers.
+ */
+#define WM8350_USB_VOLTAGE_READBACK             0x9C
+#define WM8350_LINE_VOLTAGE_READBACK            0x9D
+#define WM8350_BATT_VOLTAGE_READBACK            0x9E
+
+/*
+ * Supply Interrupts.
+ */
+#define WM8350_IRQ_USB_LIMIT			15
+#define WM8350_IRQ_EXT_USB_FB			36
+#define WM8350_IRQ_EXT_WALL_FB			37
+#define WM8350_IRQ_EXT_BAT_FB			38
+
+struct wm8350_power {
+	struct platform_device *pdev;
+};
+
+#endif
diff --git a/include/linux/mfd/wm8350/wdt.h b/include/linux/mfd/wm8350/wdt.h
new file mode 100644
index 000000000000..f6135b5e5ef4
--- /dev/null
+++ b/include/linux/mfd/wm8350/wdt.h
@@ -0,0 +1,28 @@
+/*
+ * wdt.h  --  Watchdog Driver for Wolfson WM8350 PMIC
+ *
+ * Copyright 2007, 2008 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#ifndef __LINUX_MFD_WM8350_WDT_H_
+#define __LINUX_MFD_WM8350_WDT_H_
+
+#include <linux/platform_device.h>
+
+#define WM8350_WDOG_HIB_MODE                    0x0080
+#define WM8350_WDOG_DEBUG                       0x0040
+#define WM8350_WDOG_MODE_MASK                   0x0030
+#define WM8350_WDOG_TO_MASK                     0x0007
+
+#define WM8350_IRQ_SYS_WDOG_TO			24
+
+struct wm8350_wdt {
+	struct platform_device *pdev;
+};
+
+#endif
diff --git a/include/linux/mfd/wm8400-audio.h b/include/linux/mfd/wm8400-audio.h
new file mode 100644
index 000000000000..b6640e018046
--- /dev/null
+++ b/include/linux/mfd/wm8400-audio.h
@@ -0,0 +1,1186 @@
+/*
+ * wm8400 private definitions for audio
+ *
+ * Copyright 2008 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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __LINUX_MFD_WM8400_AUDIO_H
+#define __LINUX_MFD_WM8400_AUDIO_H
+
+#include <linux/mfd/wm8400-audio.h>
+
+/*
+ * R2 (0x02) - Power Management (1)
+ */
+#define WM8400_CODEC_ENA                        0x8000  /* CODEC_ENA */
+#define WM8400_CODEC_ENA_MASK                   0x8000  /* CODEC_ENA */
+#define WM8400_CODEC_ENA_SHIFT                      15  /* CODEC_ENA */
+#define WM8400_CODEC_ENA_WIDTH                       1  /* CODEC_ENA */
+#define WM8400_SYSCLK_ENA                       0x4000  /* SYSCLK_ENA */
+#define WM8400_SYSCLK_ENA_MASK                  0x4000  /* SYSCLK_ENA */
+#define WM8400_SYSCLK_ENA_SHIFT                     14  /* SYSCLK_ENA */
+#define WM8400_SYSCLK_ENA_WIDTH                      1  /* SYSCLK_ENA */
+#define WM8400_SPK_MIX_ENA                      0x2000  /* SPK_MIX_ENA */
+#define WM8400_SPK_MIX_ENA_MASK                 0x2000  /* SPK_MIX_ENA */
+#define WM8400_SPK_MIX_ENA_SHIFT                    13  /* SPK_MIX_ENA */
+#define WM8400_SPK_MIX_ENA_WIDTH                     1  /* SPK_MIX_ENA */
+#define WM8400_SPK_ENA                          0x1000  /* SPK_ENA */
+#define WM8400_SPK_ENA_MASK                     0x1000  /* SPK_ENA */
+#define WM8400_SPK_ENA_SHIFT                        12  /* SPK_ENA */
+#define WM8400_SPK_ENA_WIDTH                         1  /* SPK_ENA */
+#define WM8400_OUT3_ENA                         0x0800  /* OUT3_ENA */
+#define WM8400_OUT3_ENA_MASK                    0x0800  /* OUT3_ENA */
+#define WM8400_OUT3_ENA_SHIFT                       11  /* OUT3_ENA */
+#define WM8400_OUT3_ENA_WIDTH                        1  /* OUT3_ENA */
+#define WM8400_OUT4_ENA                         0x0400  /* OUT4_ENA */
+#define WM8400_OUT4_ENA_MASK                    0x0400  /* OUT4_ENA */
+#define WM8400_OUT4_ENA_SHIFT                       10  /* OUT4_ENA */
+#define WM8400_OUT4_ENA_WIDTH                        1  /* OUT4_ENA */
+#define WM8400_LOUT_ENA                         0x0200  /* LOUT_ENA */
+#define WM8400_LOUT_ENA_MASK                    0x0200  /* LOUT_ENA */
+#define WM8400_LOUT_ENA_SHIFT                        9  /* LOUT_ENA */
+#define WM8400_LOUT_ENA_WIDTH                        1  /* LOUT_ENA */
+#define WM8400_ROUT_ENA                         0x0100  /* ROUT_ENA */
+#define WM8400_ROUT_ENA_MASK                    0x0100  /* ROUT_ENA */
+#define WM8400_ROUT_ENA_SHIFT                        8  /* ROUT_ENA */
+#define WM8400_ROUT_ENA_WIDTH                        1  /* ROUT_ENA */
+#define WM8400_MIC1BIAS_ENA                     0x0010  /* MIC1BIAS_ENA */
+#define WM8400_MIC1BIAS_ENA_MASK                0x0010  /* MIC1BIAS_ENA */
+#define WM8400_MIC1BIAS_ENA_SHIFT                    4  /* MIC1BIAS_ENA */
+#define WM8400_MIC1BIAS_ENA_WIDTH                    1  /* MIC1BIAS_ENA */
+#define WM8400_VMID_MODE_MASK                   0x0006  /* VMID_MODE - [2:1] */
+#define WM8400_VMID_MODE_SHIFT                       1  /* VMID_MODE - [2:1] */
+#define WM8400_VMID_MODE_WIDTH                       2  /* VMID_MODE - [2:1] */
+#define WM8400_VREF_ENA                         0x0001  /* VREF_ENA */
+#define WM8400_VREF_ENA_MASK                    0x0001  /* VREF_ENA */
+#define WM8400_VREF_ENA_SHIFT                        0  /* VREF_ENA */
+#define WM8400_VREF_ENA_WIDTH                        1  /* VREF_ENA */
+
+/*
+ * R3 (0x03) - Power Management (2)
+ */
+#define WM8400_FLL_ENA                          0x8000  /* FLL_ENA */
+#define WM8400_FLL_ENA_MASK                     0x8000  /* FLL_ENA */
+#define WM8400_FLL_ENA_SHIFT                        15  /* FLL_ENA */
+#define WM8400_FLL_ENA_WIDTH                         1  /* FLL_ENA */
+#define WM8400_TSHUT_ENA                        0x4000  /* TSHUT_ENA */
+#define WM8400_TSHUT_ENA_MASK                   0x4000  /* TSHUT_ENA */
+#define WM8400_TSHUT_ENA_SHIFT                      14  /* TSHUT_ENA */
+#define WM8400_TSHUT_ENA_WIDTH                       1  /* TSHUT_ENA */
+#define WM8400_TSHUT_OPDIS                      0x2000  /* TSHUT_OPDIS */
+#define WM8400_TSHUT_OPDIS_MASK                 0x2000  /* TSHUT_OPDIS */
+#define WM8400_TSHUT_OPDIS_SHIFT                    13  /* TSHUT_OPDIS */
+#define WM8400_TSHUT_OPDIS_WIDTH                     1  /* TSHUT_OPDIS */
+#define WM8400_OPCLK_ENA                        0x0800  /* OPCLK_ENA */
+#define WM8400_OPCLK_ENA_MASK                   0x0800  /* OPCLK_ENA */
+#define WM8400_OPCLK_ENA_SHIFT                      11  /* OPCLK_ENA */
+#define WM8400_OPCLK_ENA_WIDTH                       1  /* OPCLK_ENA */
+#define WM8400_AINL_ENA                         0x0200  /* AINL_ENA */
+#define WM8400_AINL_ENA_MASK                    0x0200  /* AINL_ENA */
+#define WM8400_AINL_ENA_SHIFT                        9  /* AINL_ENA */
+#define WM8400_AINL_ENA_WIDTH                        1  /* AINL_ENA */
+#define WM8400_AINR_ENA                         0x0100  /* AINR_ENA */
+#define WM8400_AINR_ENA_MASK                    0x0100  /* AINR_ENA */
+#define WM8400_AINR_ENA_SHIFT                        8  /* AINR_ENA */
+#define WM8400_AINR_ENA_WIDTH                        1  /* AINR_ENA */
+#define WM8400_LIN34_ENA                        0x0080  /* LIN34_ENA */
+#define WM8400_LIN34_ENA_MASK                   0x0080  /* LIN34_ENA */
+#define WM8400_LIN34_ENA_SHIFT                       7  /* LIN34_ENA */
+#define WM8400_LIN34_ENA_WIDTH                       1  /* LIN34_ENA */
+#define WM8400_LIN12_ENA                        0x0040  /* LIN12_ENA */
+#define WM8400_LIN12_ENA_MASK                   0x0040  /* LIN12_ENA */
+#define WM8400_LIN12_ENA_SHIFT                       6  /* LIN12_ENA */
+#define WM8400_LIN12_ENA_WIDTH                       1  /* LIN12_ENA */
+#define WM8400_RIN34_ENA                        0x0020  /* RIN34_ENA */
+#define WM8400_RIN34_ENA_MASK                   0x0020  /* RIN34_ENA */
+#define WM8400_RIN34_ENA_SHIFT                       5  /* RIN34_ENA */
+#define WM8400_RIN34_ENA_WIDTH                       1  /* RIN34_ENA */
+#define WM8400_RIN12_ENA                        0x0010  /* RIN12_ENA */
+#define WM8400_RIN12_ENA_MASK                   0x0010  /* RIN12_ENA */
+#define WM8400_RIN12_ENA_SHIFT                       4  /* RIN12_ENA */
+#define WM8400_RIN12_ENA_WIDTH                       1  /* RIN12_ENA */
+#define WM8400_ADCL_ENA                         0x0002  /* ADCL_ENA */
+#define WM8400_ADCL_ENA_MASK                    0x0002  /* ADCL_ENA */
+#define WM8400_ADCL_ENA_SHIFT                        1  /* ADCL_ENA */
+#define WM8400_ADCL_ENA_WIDTH                        1  /* ADCL_ENA */
+#define WM8400_ADCR_ENA                         0x0001  /* ADCR_ENA */
+#define WM8400_ADCR_ENA_MASK                    0x0001  /* ADCR_ENA */
+#define WM8400_ADCR_ENA_SHIFT                        0  /* ADCR_ENA */
+#define WM8400_ADCR_ENA_WIDTH                        1  /* ADCR_ENA */
+
+/*
+ * R4 (0x04) - Power Management (3)
+ */
+#define WM8400_LON_ENA                          0x2000  /* LON_ENA */
+#define WM8400_LON_ENA_MASK                     0x2000  /* LON_ENA */
+#define WM8400_LON_ENA_SHIFT                        13  /* LON_ENA */
+#define WM8400_LON_ENA_WIDTH                         1  /* LON_ENA */
+#define WM8400_LOP_ENA                          0x1000  /* LOP_ENA */
+#define WM8400_LOP_ENA_MASK                     0x1000  /* LOP_ENA */
+#define WM8400_LOP_ENA_SHIFT                        12  /* LOP_ENA */
+#define WM8400_LOP_ENA_WIDTH                         1  /* LOP_ENA */
+#define WM8400_RON_ENA                          0x0800  /* RON_ENA */
+#define WM8400_RON_ENA_MASK                     0x0800  /* RON_ENA */
+#define WM8400_RON_ENA_SHIFT                        11  /* RON_ENA */
+#define WM8400_RON_ENA_WIDTH                         1  /* RON_ENA */
+#define WM8400_ROP_ENA                          0x0400  /* ROP_ENA */
+#define WM8400_ROP_ENA_MASK                     0x0400  /* ROP_ENA */
+#define WM8400_ROP_ENA_SHIFT                        10  /* ROP_ENA */
+#define WM8400_ROP_ENA_WIDTH                         1  /* ROP_ENA */
+#define WM8400_LOPGA_ENA                        0x0080  /* LOPGA_ENA */
+#define WM8400_LOPGA_ENA_MASK                   0x0080  /* LOPGA_ENA */
+#define WM8400_LOPGA_ENA_SHIFT                       7  /* LOPGA_ENA */
+#define WM8400_LOPGA_ENA_WIDTH                       1  /* LOPGA_ENA */
+#define WM8400_ROPGA_ENA                        0x0040  /* ROPGA_ENA */
+#define WM8400_ROPGA_ENA_MASK                   0x0040  /* ROPGA_ENA */
+#define WM8400_ROPGA_ENA_SHIFT                       6  /* ROPGA_ENA */
+#define WM8400_ROPGA_ENA_WIDTH                       1  /* ROPGA_ENA */
+#define WM8400_LOMIX_ENA                        0x0020  /* LOMIX_ENA */
+#define WM8400_LOMIX_ENA_MASK                   0x0020  /* LOMIX_ENA */
+#define WM8400_LOMIX_ENA_SHIFT                       5  /* LOMIX_ENA */
+#define WM8400_LOMIX_ENA_WIDTH                       1  /* LOMIX_ENA */
+#define WM8400_ROMIX_ENA                        0x0010  /* ROMIX_ENA */
+#define WM8400_ROMIX_ENA_MASK                   0x0010  /* ROMIX_ENA */
+#define WM8400_ROMIX_ENA_SHIFT                       4  /* ROMIX_ENA */
+#define WM8400_ROMIX_ENA_WIDTH                       1  /* ROMIX_ENA */
+#define WM8400_DACL_ENA                         0x0002  /* DACL_ENA */
+#define WM8400_DACL_ENA_MASK                    0x0002  /* DACL_ENA */
+#define WM8400_DACL_ENA_SHIFT                        1  /* DACL_ENA */
+#define WM8400_DACL_ENA_WIDTH                        1  /* DACL_ENA */
+#define WM8400_DACR_ENA                         0x0001  /* DACR_ENA */
+#define WM8400_DACR_ENA_MASK                    0x0001  /* DACR_ENA */
+#define WM8400_DACR_ENA_SHIFT                        0  /* DACR_ENA */
+#define WM8400_DACR_ENA_WIDTH                        1  /* DACR_ENA */
+
+/*
+ * R5 (0x05) - Audio Interface (1)
+ */
+#define WM8400_AIFADCL_SRC                      0x8000  /* AIFADCL_SRC */
+#define WM8400_AIFADCL_SRC_MASK                 0x8000  /* AIFADCL_SRC */
+#define WM8400_AIFADCL_SRC_SHIFT                    15  /* AIFADCL_SRC */
+#define WM8400_AIFADCL_SRC_WIDTH                     1  /* AIFADCL_SRC */
+#define WM8400_AIFADCR_SRC                      0x4000  /* AIFADCR_SRC */
+#define WM8400_AIFADCR_SRC_MASK                 0x4000  /* AIFADCR_SRC */
+#define WM8400_AIFADCR_SRC_SHIFT                    14  /* AIFADCR_SRC */
+#define WM8400_AIFADCR_SRC_WIDTH                     1  /* AIFADCR_SRC */
+#define WM8400_AIFADC_TDM                       0x2000  /* AIFADC_TDM */
+#define WM8400_AIFADC_TDM_MASK                  0x2000  /* AIFADC_TDM */
+#define WM8400_AIFADC_TDM_SHIFT                     13  /* AIFADC_TDM */
+#define WM8400_AIFADC_TDM_WIDTH                      1  /* AIFADC_TDM */
+#define WM8400_AIFADC_TDM_CHAN                  0x1000  /* AIFADC_TDM_CHAN */
+#define WM8400_AIFADC_TDM_CHAN_MASK             0x1000  /* AIFADC_TDM_CHAN */
+#define WM8400_AIFADC_TDM_CHAN_SHIFT                12  /* AIFADC_TDM_CHAN */
+#define WM8400_AIFADC_TDM_CHAN_WIDTH                 1  /* AIFADC_TDM_CHAN */
+#define WM8400_AIF_BCLK_INV                     0x0100  /* AIF_BCLK_INV */
+#define WM8400_AIF_BCLK_INV_MASK                0x0100  /* AIF_BCLK_INV */
+#define WM8400_AIF_BCLK_INV_SHIFT                    8  /* AIF_BCLK_INV */
+#define WM8400_AIF_BCLK_INV_WIDTH                    1  /* AIF_BCLK_INV */
+#define WM8400_AIF_LRCLK_INV                    0x0080  /* AIF_LRCLK_INV */
+#define WM8400_AIF_LRCLK_INV_MASK               0x0080  /* AIF_LRCLK_INV */
+#define WM8400_AIF_LRCLK_INV_SHIFT                   7  /* AIF_LRCLK_INV */
+#define WM8400_AIF_LRCLK_INV_WIDTH                   1  /* AIF_LRCLK_INV */
+#define WM8400_AIF_WL_MASK                      0x0060  /* AIF_WL - [6:5] */
+#define WM8400_AIF_WL_SHIFT                          5  /* AIF_WL - [6:5] */
+#define WM8400_AIF_WL_WIDTH                          2  /* AIF_WL - [6:5] */
+#define WM8400_AIF_WL_16BITS			(0 << 5)
+#define WM8400_AIF_WL_20BITS			(1 << 5)
+#define WM8400_AIF_WL_24BITS			(2 << 5)
+#define WM8400_AIF_WL_32BITS			(3 << 5)
+#define WM8400_AIF_FMT_MASK                     0x0018  /* AIF_FMT - [4:3] */
+#define WM8400_AIF_FMT_SHIFT                         3  /* AIF_FMT - [4:3] */
+#define WM8400_AIF_FMT_WIDTH                         2  /* AIF_FMT - [4:3] */
+#define WM8400_AIF_FMT_RIGHTJ			(0 << 3)
+#define WM8400_AIF_FMT_LEFTJ			(1 << 3)
+#define WM8400_AIF_FMT_I2S			(2 << 3)
+#define WM8400_AIF_FMT_DSP			(3 << 3)
+
+/*
+ * R6 (0x06) - Audio Interface (2)
+ */
+#define WM8400_DACL_SRC                         0x8000  /* DACL_SRC */
+#define WM8400_DACL_SRC_MASK                    0x8000  /* DACL_SRC */
+#define WM8400_DACL_SRC_SHIFT                       15  /* DACL_SRC */
+#define WM8400_DACL_SRC_WIDTH                        1  /* DACL_SRC */
+#define WM8400_DACR_SRC                         0x4000  /* DACR_SRC */
+#define WM8400_DACR_SRC_MASK                    0x4000  /* DACR_SRC */
+#define WM8400_DACR_SRC_SHIFT                       14  /* DACR_SRC */
+#define WM8400_DACR_SRC_WIDTH                        1  /* DACR_SRC */
+#define WM8400_AIFDAC_TDM                       0x2000  /* AIFDAC_TDM */
+#define WM8400_AIFDAC_TDM_MASK                  0x2000  /* AIFDAC_TDM */
+#define WM8400_AIFDAC_TDM_SHIFT                     13  /* AIFDAC_TDM */
+#define WM8400_AIFDAC_TDM_WIDTH                      1  /* AIFDAC_TDM */
+#define WM8400_AIFDAC_TDM_CHAN                  0x1000  /* AIFDAC_TDM_CHAN */
+#define WM8400_AIFDAC_TDM_CHAN_MASK             0x1000  /* AIFDAC_TDM_CHAN */
+#define WM8400_AIFDAC_TDM_CHAN_SHIFT                12  /* AIFDAC_TDM_CHAN */
+#define WM8400_AIFDAC_TDM_CHAN_WIDTH                 1  /* AIFDAC_TDM_CHAN */
+#define WM8400_DAC_BOOST_MASK                   0x0C00  /* DAC_BOOST - [11:10] */
+#define WM8400_DAC_BOOST_SHIFT                      10  /* DAC_BOOST - [11:10] */
+#define WM8400_DAC_BOOST_WIDTH                       2  /* DAC_BOOST - [11:10] */
+#define WM8400_DAC_COMP                         0x0010  /* DAC_COMP */
+#define WM8400_DAC_COMP_MASK                    0x0010  /* DAC_COMP */
+#define WM8400_DAC_COMP_SHIFT                        4  /* DAC_COMP */
+#define WM8400_DAC_COMP_WIDTH                        1  /* DAC_COMP */
+#define WM8400_DAC_COMPMODE                     0x0008  /* DAC_COMPMODE */
+#define WM8400_DAC_COMPMODE_MASK                0x0008  /* DAC_COMPMODE */
+#define WM8400_DAC_COMPMODE_SHIFT                    3  /* DAC_COMPMODE */
+#define WM8400_DAC_COMPMODE_WIDTH                    1  /* DAC_COMPMODE */
+#define WM8400_ADC_COMP                         0x0004  /* ADC_COMP */
+#define WM8400_ADC_COMP_MASK                    0x0004  /* ADC_COMP */
+#define WM8400_ADC_COMP_SHIFT                        2  /* ADC_COMP */
+#define WM8400_ADC_COMP_WIDTH                        1  /* ADC_COMP */
+#define WM8400_ADC_COMPMODE                     0x0002  /* ADC_COMPMODE */
+#define WM8400_ADC_COMPMODE_MASK                0x0002  /* ADC_COMPMODE */
+#define WM8400_ADC_COMPMODE_SHIFT                    1  /* ADC_COMPMODE */
+#define WM8400_ADC_COMPMODE_WIDTH                    1  /* ADC_COMPMODE */
+#define WM8400_LOOPBACK                         0x0001  /* LOOPBACK */
+#define WM8400_LOOPBACK_MASK                    0x0001  /* LOOPBACK */
+#define WM8400_LOOPBACK_SHIFT                        0  /* LOOPBACK */
+#define WM8400_LOOPBACK_WIDTH                        1  /* LOOPBACK */
+
+/*
+ * R7 (0x07) - Clocking (1)
+ */
+#define WM8400_TOCLK_RATE                       0x8000  /* TOCLK_RATE */
+#define WM8400_TOCLK_RATE_MASK                  0x8000  /* TOCLK_RATE */
+#define WM8400_TOCLK_RATE_SHIFT                     15  /* TOCLK_RATE */
+#define WM8400_TOCLK_RATE_WIDTH                      1  /* TOCLK_RATE */
+#define WM8400_TOCLK_ENA                        0x4000  /* TOCLK_ENA */
+#define WM8400_TOCLK_ENA_MASK                   0x4000  /* TOCLK_ENA */
+#define WM8400_TOCLK_ENA_SHIFT                      14  /* TOCLK_ENA */
+#define WM8400_TOCLK_ENA_WIDTH                       1  /* TOCLK_ENA */
+#define WM8400_OPCLKDIV_MASK                    0x1E00  /* OPCLKDIV - [12:9] */
+#define WM8400_OPCLKDIV_SHIFT                        9  /* OPCLKDIV - [12:9] */
+#define WM8400_OPCLKDIV_WIDTH                        4  /* OPCLKDIV - [12:9] */
+#define WM8400_DCLKDIV_MASK                     0x01C0  /* DCLKDIV - [8:6] */
+#define WM8400_DCLKDIV_SHIFT                         6  /* DCLKDIV - [8:6] */
+#define WM8400_DCLKDIV_WIDTH                         3  /* DCLKDIV - [8:6] */
+#define WM8400_BCLK_DIV_MASK                    0x001E  /* BCLK_DIV - [4:1] */
+#define WM8400_BCLK_DIV_SHIFT                        1  /* BCLK_DIV - [4:1] */
+#define WM8400_BCLK_DIV_WIDTH                        4  /* BCLK_DIV - [4:1] */
+
+/*
+ * R8 (0x08) - Clocking (2)
+ */
+#define WM8400_MCLK_SRC                         0x8000  /* MCLK_SRC */
+#define WM8400_MCLK_SRC_MASK                    0x8000  /* MCLK_SRC */
+#define WM8400_MCLK_SRC_SHIFT                       15  /* MCLK_SRC */
+#define WM8400_MCLK_SRC_WIDTH                        1  /* MCLK_SRC */
+#define WM8400_SYSCLK_SRC                       0x4000  /* SYSCLK_SRC */
+#define WM8400_SYSCLK_SRC_MASK                  0x4000  /* SYSCLK_SRC */
+#define WM8400_SYSCLK_SRC_SHIFT                     14  /* SYSCLK_SRC */
+#define WM8400_SYSCLK_SRC_WIDTH                      1  /* SYSCLK_SRC */
+#define WM8400_CLK_FORCE                        0x2000  /* CLK_FORCE */
+#define WM8400_CLK_FORCE_MASK                   0x2000  /* CLK_FORCE */
+#define WM8400_CLK_FORCE_SHIFT                      13  /* CLK_FORCE */
+#define WM8400_CLK_FORCE_WIDTH                       1  /* CLK_FORCE */
+#define WM8400_MCLK_DIV_MASK                    0x1800  /* MCLK_DIV - [12:11] */
+#define WM8400_MCLK_DIV_SHIFT                       11  /* MCLK_DIV - [12:11] */
+#define WM8400_MCLK_DIV_WIDTH                        2  /* MCLK_DIV - [12:11] */
+#define WM8400_MCLK_INV                         0x0400  /* MCLK_INV */
+#define WM8400_MCLK_INV_MASK                    0x0400  /* MCLK_INV */
+#define WM8400_MCLK_INV_SHIFT                       10  /* MCLK_INV */
+#define WM8400_MCLK_INV_WIDTH                        1  /* MCLK_INV */
+#define WM8400_ADC_CLKDIV_MASK                  0x00E0  /* ADC_CLKDIV - [7:5] */
+#define WM8400_ADC_CLKDIV_SHIFT                      5  /* ADC_CLKDIV - [7:5] */
+#define WM8400_ADC_CLKDIV_WIDTH                      3  /* ADC_CLKDIV - [7:5] */
+#define WM8400_DAC_CLKDIV_MASK                  0x001C  /* DAC_CLKDIV - [4:2] */
+#define WM8400_DAC_CLKDIV_SHIFT                      2  /* DAC_CLKDIV - [4:2] */
+#define WM8400_DAC_CLKDIV_WIDTH                      3  /* DAC_CLKDIV - [4:2] */
+
+/*
+ * R9 (0x09) - Audio Interface (3)
+ */
+#define WM8400_AIF_MSTR1                        0x8000  /* AIF_MSTR1 */
+#define WM8400_AIF_MSTR1_MASK                   0x8000  /* AIF_MSTR1 */
+#define WM8400_AIF_MSTR1_SHIFT                      15  /* AIF_MSTR1 */
+#define WM8400_AIF_MSTR1_WIDTH                       1  /* AIF_MSTR1 */
+#define WM8400_AIF_MSTR2                        0x4000  /* AIF_MSTR2 */
+#define WM8400_AIF_MSTR2_MASK                   0x4000  /* AIF_MSTR2 */
+#define WM8400_AIF_MSTR2_SHIFT                      14  /* AIF_MSTR2 */
+#define WM8400_AIF_MSTR2_WIDTH                       1  /* AIF_MSTR2 */
+#define WM8400_AIF_SEL                          0x2000  /* AIF_SEL */
+#define WM8400_AIF_SEL_MASK                     0x2000  /* AIF_SEL */
+#define WM8400_AIF_SEL_SHIFT                        13  /* AIF_SEL */
+#define WM8400_AIF_SEL_WIDTH                         1  /* AIF_SEL */
+#define WM8400_ADCLRC_DIR                       0x0800  /* ADCLRC_DIR */
+#define WM8400_ADCLRC_DIR_MASK                  0x0800  /* ADCLRC_DIR */
+#define WM8400_ADCLRC_DIR_SHIFT                     11  /* ADCLRC_DIR */
+#define WM8400_ADCLRC_DIR_WIDTH                      1  /* ADCLRC_DIR */
+#define WM8400_ADCLRC_RATE_MASK                 0x07FF  /* ADCLRC_RATE - [10:0] */
+#define WM8400_ADCLRC_RATE_SHIFT                     0  /* ADCLRC_RATE - [10:0] */
+#define WM8400_ADCLRC_RATE_WIDTH                    11  /* ADCLRC_RATE - [10:0] */
+
+/*
+ * R10 (0x0A) - Audio Interface (4)
+ */
+#define WM8400_ALRCGPIO1                        0x8000  /* ALRCGPIO1 */
+#define WM8400_ALRCGPIO1_MASK                   0x8000  /* ALRCGPIO1 */
+#define WM8400_ALRCGPIO1_SHIFT                      15  /* ALRCGPIO1 */
+#define WM8400_ALRCGPIO1_WIDTH                       1  /* ALRCGPIO1 */
+#define WM8400_ALRCBGPIO6                       0x4000  /* ALRCBGPIO6 */
+#define WM8400_ALRCBGPIO6_MASK                  0x4000  /* ALRCBGPIO6 */
+#define WM8400_ALRCBGPIO6_SHIFT                     14  /* ALRCBGPIO6 */
+#define WM8400_ALRCBGPIO6_WIDTH                      1  /* ALRCBGPIO6 */
+#define WM8400_AIF_TRIS                         0x2000  /* AIF_TRIS */
+#define WM8400_AIF_TRIS_MASK                    0x2000  /* AIF_TRIS */
+#define WM8400_AIF_TRIS_SHIFT                       13  /* AIF_TRIS */
+#define WM8400_AIF_TRIS_WIDTH                        1  /* AIF_TRIS */
+#define WM8400_DACLRC_DIR                       0x0800  /* DACLRC_DIR */
+#define WM8400_DACLRC_DIR_MASK                  0x0800  /* DACLRC_DIR */
+#define WM8400_DACLRC_DIR_SHIFT                     11  /* DACLRC_DIR */
+#define WM8400_DACLRC_DIR_WIDTH                      1  /* DACLRC_DIR */
+#define WM8400_DACLRC_RATE_MASK                 0x07FF  /* DACLRC_RATE - [10:0] */
+#define WM8400_DACLRC_RATE_SHIFT                     0  /* DACLRC_RATE - [10:0] */
+#define WM8400_DACLRC_RATE_WIDTH                    11  /* DACLRC_RATE - [10:0] */
+
+/*
+ * R11 (0x0B) - DAC CTRL
+ */
+#define WM8400_DAC_SDMCLK_RATE                  0x2000  /* DAC_SDMCLK_RATE */
+#define WM8400_DAC_SDMCLK_RATE_MASK             0x2000  /* DAC_SDMCLK_RATE */
+#define WM8400_DAC_SDMCLK_RATE_SHIFT                13  /* DAC_SDMCLK_RATE */
+#define WM8400_DAC_SDMCLK_RATE_WIDTH                 1  /* DAC_SDMCLK_RATE */
+#define WM8400_AIF_LRCLKRATE                    0x0400  /* AIF_LRCLKRATE */
+#define WM8400_AIF_LRCLKRATE_MASK               0x0400  /* AIF_LRCLKRATE */
+#define WM8400_AIF_LRCLKRATE_SHIFT                  10  /* AIF_LRCLKRATE */
+#define WM8400_AIF_LRCLKRATE_WIDTH                   1  /* AIF_LRCLKRATE */
+#define WM8400_DAC_MONO                         0x0200  /* DAC_MONO */
+#define WM8400_DAC_MONO_MASK                    0x0200  /* DAC_MONO */
+#define WM8400_DAC_MONO_SHIFT                        9  /* DAC_MONO */
+#define WM8400_DAC_MONO_WIDTH                        1  /* DAC_MONO */
+#define WM8400_DAC_SB_FILT                      0x0100  /* DAC_SB_FILT */
+#define WM8400_DAC_SB_FILT_MASK                 0x0100  /* DAC_SB_FILT */
+#define WM8400_DAC_SB_FILT_SHIFT                     8  /* DAC_SB_FILT */
+#define WM8400_DAC_SB_FILT_WIDTH                     1  /* DAC_SB_FILT */
+#define WM8400_DAC_MUTERATE                     0x0080  /* DAC_MUTERATE */
+#define WM8400_DAC_MUTERATE_MASK                0x0080  /* DAC_MUTERATE */
+#define WM8400_DAC_MUTERATE_SHIFT                    7  /* DAC_MUTERATE */
+#define WM8400_DAC_MUTERATE_WIDTH                    1  /* DAC_MUTERATE */
+#define WM8400_DAC_MUTEMODE                     0x0040  /* DAC_MUTEMODE */
+#define WM8400_DAC_MUTEMODE_MASK                0x0040  /* DAC_MUTEMODE */
+#define WM8400_DAC_MUTEMODE_SHIFT                    6  /* DAC_MUTEMODE */
+#define WM8400_DAC_MUTEMODE_WIDTH                    1  /* DAC_MUTEMODE */
+#define WM8400_DEEMP_MASK                       0x0030  /* DEEMP - [5:4] */
+#define WM8400_DEEMP_SHIFT                           4  /* DEEMP - [5:4] */
+#define WM8400_DEEMP_WIDTH                           2  /* DEEMP - [5:4] */
+#define WM8400_DAC_MUTE                         0x0004  /* DAC_MUTE */
+#define WM8400_DAC_MUTE_MASK                    0x0004  /* DAC_MUTE */
+#define WM8400_DAC_MUTE_SHIFT                        2  /* DAC_MUTE */
+#define WM8400_DAC_MUTE_WIDTH                        1  /* DAC_MUTE */
+#define WM8400_DACL_DATINV                      0x0002  /* DACL_DATINV */
+#define WM8400_DACL_DATINV_MASK                 0x0002  /* DACL_DATINV */
+#define WM8400_DACL_DATINV_SHIFT                     1  /* DACL_DATINV */
+#define WM8400_DACL_DATINV_WIDTH                     1  /* DACL_DATINV */
+#define WM8400_DACR_DATINV                      0x0001  /* DACR_DATINV */
+#define WM8400_DACR_DATINV_MASK                 0x0001  /* DACR_DATINV */
+#define WM8400_DACR_DATINV_SHIFT                     0  /* DACR_DATINV */
+#define WM8400_DACR_DATINV_WIDTH                     1  /* DACR_DATINV */
+
+/*
+ * R12 (0x0C) - Left DAC Digital Volume
+ */
+#define WM8400_DAC_VU                           0x0100  /* DAC_VU */
+#define WM8400_DAC_VU_MASK                      0x0100  /* DAC_VU */
+#define WM8400_DAC_VU_SHIFT                          8  /* DAC_VU */
+#define WM8400_DAC_VU_WIDTH                          1  /* DAC_VU */
+#define WM8400_DACL_VOL_MASK                    0x00FF  /* DACL_VOL - [7:0] */
+#define WM8400_DACL_VOL_SHIFT                        0  /* DACL_VOL - [7:0] */
+#define WM8400_DACL_VOL_WIDTH                        8  /* DACL_VOL - [7:0] */
+
+/*
+ * R13 (0x0D) - Right DAC Digital Volume
+ */
+#define WM8400_DAC_VU                           0x0100  /* DAC_VU */
+#define WM8400_DAC_VU_MASK                      0x0100  /* DAC_VU */
+#define WM8400_DAC_VU_SHIFT                          8  /* DAC_VU */
+#define WM8400_DAC_VU_WIDTH                          1  /* DAC_VU */
+#define WM8400_DACR_VOL_MASK                    0x00FF  /* DACR_VOL - [7:0] */
+#define WM8400_DACR_VOL_SHIFT                        0  /* DACR_VOL - [7:0] */
+#define WM8400_DACR_VOL_WIDTH                        8  /* DACR_VOL - [7:0] */
+
+/*
+ * R14 (0x0E) - Digital Side Tone
+ */
+#define WM8400_ADCL_DAC_SVOL_MASK               0x1E00  /*   ADCL_DAC_SVOL - [12:9] */
+#define WM8400_ADCL_DAC_SVOL_SHIFT                   9  /*   ADCL_DAC_SVOL - [12:9] */
+#define WM8400_ADCL_DAC_SVOL_WIDTH                   4  /*   ADCL_DAC_SVOL - [12:9] */
+#define WM8400_ADCR_DAC_SVOL_MASK               0x01E0  /* ADCR_DAC_SVOL - [8:5] */
+#define WM8400_ADCR_DAC_SVOL_SHIFT                   5  /* ADCR_DAC_SVOL - [8:5] */
+#define WM8400_ADCR_DAC_SVOL_WIDTH                   4  /* ADCR_DAC_SVOL - [8:5] */
+#define WM8400_ADC_TO_DACL_MASK                 0x000C  /* ADC_TO_DACL - [3:2] */
+#define WM8400_ADC_TO_DACL_SHIFT                     2  /* ADC_TO_DACL - [3:2] */
+#define WM8400_ADC_TO_DACL_WIDTH                     2  /* ADC_TO_DACL - [3:2] */
+#define WM8400_ADC_TO_DACR_MASK                 0x0003  /* ADC_TO_DACR - [1:0] */
+#define WM8400_ADC_TO_DACR_SHIFT                     0  /* ADC_TO_DACR - [1:0] */
+#define WM8400_ADC_TO_DACR_WIDTH                     2  /* ADC_TO_DACR - [1:0] */
+
+/*
+ * R15 (0x0F) - ADC CTRL
+ */
+#define WM8400_ADC_HPF_ENA                      0x0100  /* ADC_HPF_ENA */
+#define WM8400_ADC_HPF_ENA_MASK                 0x0100  /* ADC_HPF_ENA */
+#define WM8400_ADC_HPF_ENA_SHIFT                     8  /* ADC_HPF_ENA */
+#define WM8400_ADC_HPF_ENA_WIDTH                     1  /* ADC_HPF_ENA */
+#define WM8400_ADC_HPF_CUT_MASK                 0x0060  /* ADC_HPF_CUT - [6:5] */
+#define WM8400_ADC_HPF_CUT_SHIFT                     5  /* ADC_HPF_CUT - [6:5] */
+#define WM8400_ADC_HPF_CUT_WIDTH                     2  /* ADC_HPF_CUT - [6:5] */
+#define WM8400_ADCL_DATINV                      0x0002  /* ADCL_DATINV */
+#define WM8400_ADCL_DATINV_MASK                 0x0002  /* ADCL_DATINV */
+#define WM8400_ADCL_DATINV_SHIFT                     1  /* ADCL_DATINV */
+#define WM8400_ADCL_DATINV_WIDTH                     1  /* ADCL_DATINV */
+#define WM8400_ADCR_DATINV                      0x0001  /* ADCR_DATINV */
+#define WM8400_ADCR_DATINV_MASK                 0x0001  /* ADCR_DATINV */
+#define WM8400_ADCR_DATINV_SHIFT                     0  /* ADCR_DATINV */
+#define WM8400_ADCR_DATINV_WIDTH                     1  /* ADCR_DATINV */
+
+/*
+ * R16 (0x10) - Left ADC Digital Volume
+ */
+#define WM8400_ADC_VU                           0x0100  /* ADC_VU */
+#define WM8400_ADC_VU_MASK                      0x0100  /* ADC_VU */
+#define WM8400_ADC_VU_SHIFT                          8  /* ADC_VU */
+#define WM8400_ADC_VU_WIDTH                          1  /* ADC_VU */
+#define WM8400_ADCL_VOL_MASK                    0x00FF  /* ADCL_VOL - [7:0] */
+#define WM8400_ADCL_VOL_SHIFT                        0  /* ADCL_VOL - [7:0] */
+#define WM8400_ADCL_VOL_WIDTH                        8  /* ADCL_VOL - [7:0] */
+
+/*
+ * R17 (0x11) - Right ADC Digital Volume
+ */
+#define WM8400_ADC_VU                           0x0100  /* ADC_VU */
+#define WM8400_ADC_VU_MASK                      0x0100  /* ADC_VU */
+#define WM8400_ADC_VU_SHIFT                          8  /* ADC_VU */
+#define WM8400_ADC_VU_WIDTH                          1  /* ADC_VU */
+#define WM8400_ADCR_VOL_MASK                    0x00FF  /* ADCR_VOL - [7:0] */
+#define WM8400_ADCR_VOL_SHIFT                        0  /* ADCR_VOL - [7:0] */
+#define WM8400_ADCR_VOL_WIDTH                        8  /* ADCR_VOL - [7:0] */
+
+/*
+ * R24 (0x18) - Left Line Input 1&2 Volume
+ */
+#define WM8400_IPVU                             0x0100  /* IPVU */
+#define WM8400_IPVU_MASK                        0x0100  /* IPVU */
+#define WM8400_IPVU_SHIFT                            8  /* IPVU */
+#define WM8400_IPVU_WIDTH                            1  /* IPVU */
+#define WM8400_LI12MUTE                         0x0080  /* LI12MUTE */
+#define WM8400_LI12MUTE_MASK                    0x0080  /* LI12MUTE */
+#define WM8400_LI12MUTE_SHIFT                        7  /* LI12MUTE */
+#define WM8400_LI12MUTE_WIDTH                        1  /* LI12MUTE */
+#define WM8400_LI12ZC                           0x0040  /* LI12ZC */
+#define WM8400_LI12ZC_MASK                      0x0040  /* LI12ZC */
+#define WM8400_LI12ZC_SHIFT                          6  /* LI12ZC */
+#define WM8400_LI12ZC_WIDTH                          1  /* LI12ZC */
+#define WM8400_LIN12VOL_MASK                    0x001F  /* LIN12VOL - [4:0] */
+#define WM8400_LIN12VOL_SHIFT                        0  /* LIN12VOL - [4:0] */
+#define WM8400_LIN12VOL_WIDTH                        5  /* LIN12VOL - [4:0] */
+
+/*
+ * R25 (0x19) - Left Line Input 3&4 Volume
+ */
+#define WM8400_IPVU                             0x0100  /* IPVU */
+#define WM8400_IPVU_MASK                        0x0100  /* IPVU */
+#define WM8400_IPVU_SHIFT                            8  /* IPVU */
+#define WM8400_IPVU_WIDTH                            1  /* IPVU */
+#define WM8400_LI34MUTE                         0x0080  /* LI34MUTE */
+#define WM8400_LI34MUTE_MASK                    0x0080  /* LI34MUTE */
+#define WM8400_LI34MUTE_SHIFT                        7  /* LI34MUTE */
+#define WM8400_LI34MUTE_WIDTH                        1  /* LI34MUTE */
+#define WM8400_LI34ZC                           0x0040  /* LI34ZC */
+#define WM8400_LI34ZC_MASK                      0x0040  /* LI34ZC */
+#define WM8400_LI34ZC_SHIFT                          6  /* LI34ZC */
+#define WM8400_LI34ZC_WIDTH                          1  /* LI34ZC */
+#define WM8400_LIN34VOL_MASK                    0x001F  /* LIN34VOL - [4:0] */
+#define WM8400_LIN34VOL_SHIFT                        0  /* LIN34VOL - [4:0] */
+#define WM8400_LIN34VOL_WIDTH                        5  /* LIN34VOL - [4:0] */
+
+/*
+ * R26 (0x1A) - Right Line Input 1&2 Volume
+ */
+#define WM8400_IPVU                             0x0100  /* IPVU */
+#define WM8400_IPVU_MASK                        0x0100  /* IPVU */
+#define WM8400_IPVU_SHIFT                            8  /* IPVU */
+#define WM8400_IPVU_WIDTH                            1  /* IPVU */
+#define WM8400_RI12MUTE                         0x0080  /* RI12MUTE */
+#define WM8400_RI12MUTE_MASK                    0x0080  /* RI12MUTE */
+#define WM8400_RI12MUTE_SHIFT                        7  /* RI12MUTE */
+#define WM8400_RI12MUTE_WIDTH                        1  /* RI12MUTE */
+#define WM8400_RI12ZC                           0x0040  /* RI12ZC */
+#define WM8400_RI12ZC_MASK                      0x0040  /* RI12ZC */
+#define WM8400_RI12ZC_SHIFT                          6  /* RI12ZC */
+#define WM8400_RI12ZC_WIDTH                          1  /* RI12ZC */
+#define WM8400_RIN12VOL_MASK                    0x001F  /* RIN12VOL - [4:0] */
+#define WM8400_RIN12VOL_SHIFT                        0  /* RIN12VOL - [4:0] */
+#define WM8400_RIN12VOL_WIDTH                        5  /* RIN12VOL - [4:0] */
+
+/*
+ * R27 (0x1B) - Right Line Input 3&4 Volume
+ */
+#define WM8400_IPVU                             0x0100  /* IPVU */
+#define WM8400_IPVU_MASK                        0x0100  /* IPVU */
+#define WM8400_IPVU_SHIFT                            8  /* IPVU */
+#define WM8400_IPVU_WIDTH                            1  /* IPVU */
+#define WM8400_RI34MUTE                         0x0080  /* RI34MUTE */
+#define WM8400_RI34MUTE_MASK                    0x0080  /* RI34MUTE */
+#define WM8400_RI34MUTE_SHIFT                        7  /* RI34MUTE */
+#define WM8400_RI34MUTE_WIDTH                        1  /* RI34MUTE */
+#define WM8400_RI34ZC                           0x0040  /* RI34ZC */
+#define WM8400_RI34ZC_MASK                      0x0040  /* RI34ZC */
+#define WM8400_RI34ZC_SHIFT                          6  /* RI34ZC */
+#define WM8400_RI34ZC_WIDTH                          1  /* RI34ZC */
+#define WM8400_RIN34VOL_MASK                    0x001F  /* RIN34VOL - [4:0] */
+#define WM8400_RIN34VOL_SHIFT                        0  /* RIN34VOL - [4:0] */
+#define WM8400_RIN34VOL_WIDTH                        5  /* RIN34VOL - [4:0] */
+
+/*
+ * R28 (0x1C) - Left Output Volume
+ */
+#define WM8400_OPVU                             0x0100  /* OPVU */
+#define WM8400_OPVU_MASK                        0x0100  /* OPVU */
+#define WM8400_OPVU_SHIFT                            8  /* OPVU */
+#define WM8400_OPVU_WIDTH                            1  /* OPVU */
+#define WM8400_LOZC                             0x0080  /* LOZC */
+#define WM8400_LOZC_MASK                        0x0080  /* LOZC */
+#define WM8400_LOZC_SHIFT                            7  /* LOZC */
+#define WM8400_LOZC_WIDTH                            1  /* LOZC */
+#define WM8400_LOUTVOL_MASK                     0x007F  /* LOUTVOL - [6:0] */
+#define WM8400_LOUTVOL_SHIFT                         0  /* LOUTVOL - [6:0] */
+#define WM8400_LOUTVOL_WIDTH                         7  /* LOUTVOL - [6:0] */
+
+/*
+ * R29 (0x1D) - Right Output Volume
+ */
+#define WM8400_OPVU                             0x0100  /* OPVU */
+#define WM8400_OPVU_MASK                        0x0100  /* OPVU */
+#define WM8400_OPVU_SHIFT                            8  /* OPVU */
+#define WM8400_OPVU_WIDTH                            1  /* OPVU */
+#define WM8400_ROZC                             0x0080  /* ROZC */
+#define WM8400_ROZC_MASK                        0x0080  /* ROZC */
+#define WM8400_ROZC_SHIFT                            7  /* ROZC */
+#define WM8400_ROZC_WIDTH                            1  /* ROZC */
+#define WM8400_ROUTVOL_MASK                     0x007F  /* ROUTVOL - [6:0] */
+#define WM8400_ROUTVOL_SHIFT                         0  /* ROUTVOL - [6:0] */
+#define WM8400_ROUTVOL_WIDTH                         7  /* ROUTVOL - [6:0] */
+
+/*
+ * R30 (0x1E) - Line Outputs Volume
+ */
+#define WM8400_LONMUTE                          0x0040  /* LONMUTE */
+#define WM8400_LONMUTE_MASK                     0x0040  /* LONMUTE */
+#define WM8400_LONMUTE_SHIFT                         6  /* LONMUTE */
+#define WM8400_LONMUTE_WIDTH                         1  /* LONMUTE */
+#define WM8400_LOPMUTE                          0x0020  /* LOPMUTE */
+#define WM8400_LOPMUTE_MASK                     0x0020  /* LOPMUTE */
+#define WM8400_LOPMUTE_SHIFT                         5  /* LOPMUTE */
+#define WM8400_LOPMUTE_WIDTH                         1  /* LOPMUTE */
+#define WM8400_LOATTN                           0x0010  /* LOATTN */
+#define WM8400_LOATTN_MASK                      0x0010  /* LOATTN */
+#define WM8400_LOATTN_SHIFT                          4  /* LOATTN */
+#define WM8400_LOATTN_WIDTH                          1  /* LOATTN */
+#define WM8400_RONMUTE                          0x0004  /* RONMUTE */
+#define WM8400_RONMUTE_MASK                     0x0004  /* RONMUTE */
+#define WM8400_RONMUTE_SHIFT                         2  /* RONMUTE */
+#define WM8400_RONMUTE_WIDTH                         1  /* RONMUTE */
+#define WM8400_ROPMUTE                          0x0002  /* ROPMUTE */
+#define WM8400_ROPMUTE_MASK                     0x0002  /* ROPMUTE */
+#define WM8400_ROPMUTE_SHIFT                         1  /* ROPMUTE */
+#define WM8400_ROPMUTE_WIDTH                         1  /* ROPMUTE */
+#define WM8400_ROATTN                           0x0001  /* ROATTN */
+#define WM8400_ROATTN_MASK                      0x0001  /* ROATTN */
+#define WM8400_ROATTN_SHIFT                          0  /* ROATTN */
+#define WM8400_ROATTN_WIDTH                          1  /* ROATTN */
+
+/*
+ * R31 (0x1F) - Out3/4 Volume
+ */
+#define WM8400_OUT3MUTE                         0x0020  /* OUT3MUTE */
+#define WM8400_OUT3MUTE_MASK                    0x0020  /* OUT3MUTE */
+#define WM8400_OUT3MUTE_SHIFT                        5  /* OUT3MUTE */
+#define WM8400_OUT3MUTE_WIDTH                        1  /* OUT3MUTE */
+#define WM8400_OUT3ATTN                         0x0010  /* OUT3ATTN */
+#define WM8400_OUT3ATTN_MASK                    0x0010  /* OUT3ATTN */
+#define WM8400_OUT3ATTN_SHIFT                        4  /* OUT3ATTN */
+#define WM8400_OUT3ATTN_WIDTH                        1  /* OUT3ATTN */
+#define WM8400_OUT4MUTE                         0x0002  /* OUT4MUTE */
+#define WM8400_OUT4MUTE_MASK                    0x0002  /* OUT4MUTE */
+#define WM8400_OUT4MUTE_SHIFT                        1  /* OUT4MUTE */
+#define WM8400_OUT4MUTE_WIDTH                        1  /* OUT4MUTE */
+#define WM8400_OUT4ATTN                         0x0001  /* OUT4ATTN */
+#define WM8400_OUT4ATTN_MASK                    0x0001  /* OUT4ATTN */
+#define WM8400_OUT4ATTN_SHIFT                        0  /* OUT4ATTN */
+#define WM8400_OUT4ATTN_WIDTH                        1  /* OUT4ATTN */
+
+/*
+ * R32 (0x20) - Left OPGA Volume
+ */
+#define WM8400_OPVU                             0x0100  /* OPVU */
+#define WM8400_OPVU_MASK                        0x0100  /* OPVU */
+#define WM8400_OPVU_SHIFT                            8  /* OPVU */
+#define WM8400_OPVU_WIDTH                            1  /* OPVU */
+#define WM8400_LOPGAZC                          0x0080  /* LOPGAZC */
+#define WM8400_LOPGAZC_MASK                     0x0080  /* LOPGAZC */
+#define WM8400_LOPGAZC_SHIFT                         7  /* LOPGAZC */
+#define WM8400_LOPGAZC_WIDTH                         1  /* LOPGAZC */
+#define WM8400_LOPGAVOL_MASK                    0x007F  /* LOPGAVOL - [6:0] */
+#define WM8400_LOPGAVOL_SHIFT                        0  /* LOPGAVOL - [6:0] */
+#define WM8400_LOPGAVOL_WIDTH                        7  /* LOPGAVOL - [6:0] */
+
+/*
+ * R33 (0x21) - Right OPGA Volume
+ */
+#define WM8400_OPVU                             0x0100  /* OPVU */
+#define WM8400_OPVU_MASK                        0x0100  /* OPVU */
+#define WM8400_OPVU_SHIFT                            8  /* OPVU */
+#define WM8400_OPVU_WIDTH                            1  /* OPVU */
+#define WM8400_ROPGAZC                          0x0080  /* ROPGAZC */
+#define WM8400_ROPGAZC_MASK                     0x0080  /* ROPGAZC */
+#define WM8400_ROPGAZC_SHIFT                         7  /* ROPGAZC */
+#define WM8400_ROPGAZC_WIDTH                         1  /* ROPGAZC */
+#define WM8400_ROPGAVOL_MASK                    0x007F  /* ROPGAVOL - [6:0] */
+#define WM8400_ROPGAVOL_SHIFT                        0  /* ROPGAVOL - [6:0] */
+#define WM8400_ROPGAVOL_WIDTH                        7  /* ROPGAVOL - [6:0] */
+
+/*
+ * R34 (0x22) - Speaker Volume
+ */
+#define WM8400_SPKATTN_MASK                     0x0003  /* SPKATTN - [1:0] */
+#define WM8400_SPKATTN_SHIFT                         0  /* SPKATTN - [1:0] */
+#define WM8400_SPKATTN_WIDTH                         2  /* SPKATTN - [1:0] */
+
+/*
+ * R35 (0x23) - ClassD1
+ */
+#define WM8400_CDMODE                           0x0100  /* CDMODE */
+#define WM8400_CDMODE_MASK                      0x0100  /* CDMODE */
+#define WM8400_CDMODE_SHIFT                          8  /* CDMODE */
+#define WM8400_CDMODE_WIDTH                          1  /* CDMODE */
+#define WM8400_CLASSD_CLK_SEL                   0x0080  /* CLASSD_CLK_SEL */
+#define WM8400_CLASSD_CLK_SEL_MASK              0x0080  /* CLASSD_CLK_SEL */
+#define WM8400_CLASSD_CLK_SEL_SHIFT                  7  /* CLASSD_CLK_SEL */
+#define WM8400_CLASSD_CLK_SEL_WIDTH                  1  /* CLASSD_CLK_SEL */
+#define WM8400_CD_SRCTRL                        0x0040  /* CD_SRCTRL */
+#define WM8400_CD_SRCTRL_MASK                   0x0040  /* CD_SRCTRL */
+#define WM8400_CD_SRCTRL_SHIFT                       6  /* CD_SRCTRL */
+#define WM8400_CD_SRCTRL_WIDTH                       1  /* CD_SRCTRL */
+#define WM8400_SPKNOPOP                         0x0020  /* SPKNOPOP */
+#define WM8400_SPKNOPOP_MASK                    0x0020  /* SPKNOPOP */
+#define WM8400_SPKNOPOP_SHIFT                        5  /* SPKNOPOP */
+#define WM8400_SPKNOPOP_WIDTH                        1  /* SPKNOPOP */
+#define WM8400_DBLERATE                         0x0010  /* DBLERATE */
+#define WM8400_DBLERATE_MASK                    0x0010  /* DBLERATE */
+#define WM8400_DBLERATE_SHIFT                        4  /* DBLERATE */
+#define WM8400_DBLERATE_WIDTH                        1  /* DBLERATE */
+#define WM8400_LOOPTEST                         0x0008  /* LOOPTEST */
+#define WM8400_LOOPTEST_MASK                    0x0008  /* LOOPTEST */
+#define WM8400_LOOPTEST_SHIFT                        3  /* LOOPTEST */
+#define WM8400_LOOPTEST_WIDTH                        1  /* LOOPTEST */
+#define WM8400_HALFABBIAS                       0x0004  /* HALFABBIAS */
+#define WM8400_HALFABBIAS_MASK                  0x0004  /* HALFABBIAS */
+#define WM8400_HALFABBIAS_SHIFT                      2  /* HALFABBIAS */
+#define WM8400_HALFABBIAS_WIDTH                      1  /* HALFABBIAS */
+#define WM8400_TRIDEL_MASK                      0x0003  /* TRIDEL - [1:0] */
+#define WM8400_TRIDEL_SHIFT                          0  /* TRIDEL - [1:0] */
+#define WM8400_TRIDEL_WIDTH                          2  /* TRIDEL - [1:0] */
+
+/*
+ * R37 (0x25) - ClassD3
+ */
+#define WM8400_DCGAIN_MASK                      0x0038  /* DCGAIN - [5:3] */
+#define WM8400_DCGAIN_SHIFT                          3  /* DCGAIN - [5:3] */
+#define WM8400_DCGAIN_WIDTH                          3  /* DCGAIN - [5:3] */
+#define WM8400_ACGAIN_MASK                      0x0007  /* ACGAIN - [2:0] */
+#define WM8400_ACGAIN_SHIFT                          0  /* ACGAIN - [2:0] */
+#define WM8400_ACGAIN_WIDTH                          3  /* ACGAIN - [2:0] */
+
+/*
+ * R39 (0x27) - Input Mixer1
+ */
+#define WM8400_AINLMODE_MASK                    0x000C  /* AINLMODE - [3:2] */
+#define WM8400_AINLMODE_SHIFT                        2  /* AINLMODE - [3:2] */
+#define WM8400_AINLMODE_WIDTH                        2  /* AINLMODE - [3:2] */
+#define WM8400_AINRMODE_MASK                    0x0003  /* AINRMODE - [1:0] */
+#define WM8400_AINRMODE_SHIFT                        0  /* AINRMODE - [1:0] */
+#define WM8400_AINRMODE_WIDTH                        2  /* AINRMODE - [1:0] */
+
+/*
+ * R40 (0x28) - Input Mixer2
+ */
+#define WM8400_LMP4                             0x0080  /* LMP4 */
+#define WM8400_LMP4_MASK                        0x0080  /* LMP4 */
+#define WM8400_LMP4_SHIFT                            7  /* LMP4 */
+#define WM8400_LMP4_WIDTH                            1  /* LMP4 */
+#define WM8400_LMN3                             0x0040  /* LMN3 */
+#define WM8400_LMN3_MASK                        0x0040  /* LMN3 */
+#define WM8400_LMN3_SHIFT                            6  /* LMN3 */
+#define WM8400_LMN3_WIDTH                            1  /* LMN3 */
+#define WM8400_LMP2                             0x0020  /* LMP2 */
+#define WM8400_LMP2_MASK                        0x0020  /* LMP2 */
+#define WM8400_LMP2_SHIFT                            5  /* LMP2 */
+#define WM8400_LMP2_WIDTH                            1  /* LMP2 */
+#define WM8400_LMN1                             0x0010  /* LMN1 */
+#define WM8400_LMN1_MASK                        0x0010  /* LMN1 */
+#define WM8400_LMN1_SHIFT                            4  /* LMN1 */
+#define WM8400_LMN1_WIDTH                            1  /* LMN1 */
+#define WM8400_RMP4                             0x0008  /* RMP4 */
+#define WM8400_RMP4_MASK                        0x0008  /* RMP4 */
+#define WM8400_RMP4_SHIFT                            3  /* RMP4 */
+#define WM8400_RMP4_WIDTH                            1  /* RMP4 */
+#define WM8400_RMN3                             0x0004  /* RMN3 */
+#define WM8400_RMN3_MASK                        0x0004  /* RMN3 */
+#define WM8400_RMN3_SHIFT                            2  /* RMN3 */
+#define WM8400_RMN3_WIDTH                            1  /* RMN3 */
+#define WM8400_RMP2                             0x0002  /* RMP2 */
+#define WM8400_RMP2_MASK                        0x0002  /* RMP2 */
+#define WM8400_RMP2_SHIFT                            1  /* RMP2 */
+#define WM8400_RMP2_WIDTH                            1  /* RMP2 */
+#define WM8400_RMN1                             0x0001  /* RMN1 */
+#define WM8400_RMN1_MASK                        0x0001  /* RMN1 */
+#define WM8400_RMN1_SHIFT                            0  /* RMN1 */
+#define WM8400_RMN1_WIDTH                            1  /* RMN1 */
+
+/*
+ * R41 (0x29) - Input Mixer3
+ */
+#define WM8400_L34MNB                           0x0100  /* L34MNB */
+#define WM8400_L34MNB_MASK                      0x0100  /* L34MNB */
+#define WM8400_L34MNB_SHIFT                          8  /* L34MNB */
+#define WM8400_L34MNB_WIDTH                          1  /* L34MNB */
+#define WM8400_L34MNBST                         0x0080  /* L34MNBST */
+#define WM8400_L34MNBST_MASK                    0x0080  /* L34MNBST */
+#define WM8400_L34MNBST_SHIFT                        7  /* L34MNBST */
+#define WM8400_L34MNBST_WIDTH                        1  /* L34MNBST */
+#define WM8400_L12MNB                           0x0020  /* L12MNB */
+#define WM8400_L12MNB_MASK                      0x0020  /* L12MNB */
+#define WM8400_L12MNB_SHIFT                          5  /* L12MNB */
+#define WM8400_L12MNB_WIDTH                          1  /* L12MNB */
+#define WM8400_L12MNBST                         0x0010  /* L12MNBST */
+#define WM8400_L12MNBST_MASK                    0x0010  /* L12MNBST */
+#define WM8400_L12MNBST_SHIFT                        4  /* L12MNBST */
+#define WM8400_L12MNBST_WIDTH                        1  /* L12MNBST */
+#define WM8400_LDBVOL_MASK                      0x0007  /* LDBVOL - [2:0] */
+#define WM8400_LDBVOL_SHIFT                          0  /* LDBVOL - [2:0] */
+#define WM8400_LDBVOL_WIDTH                          3  /* LDBVOL - [2:0] */
+
+/*
+ * R42 (0x2A) - Input Mixer4
+ */
+#define WM8400_R34MNB                           0x0100  /* R34MNB */
+#define WM8400_R34MNB_MASK                      0x0100  /* R34MNB */
+#define WM8400_R34MNB_SHIFT                          8  /* R34MNB */
+#define WM8400_R34MNB_WIDTH                          1  /* R34MNB */
+#define WM8400_R34MNBST                         0x0080  /* R34MNBST */
+#define WM8400_R34MNBST_MASK                    0x0080  /* R34MNBST */
+#define WM8400_R34MNBST_SHIFT                        7  /* R34MNBST */
+#define WM8400_R34MNBST_WIDTH                        1  /* R34MNBST */
+#define WM8400_R12MNB                           0x0020  /* R12MNB */
+#define WM8400_R12MNB_MASK                      0x0020  /* R12MNB */
+#define WM8400_R12MNB_SHIFT                          5  /* R12MNB */
+#define WM8400_R12MNB_WIDTH                          1  /* R12MNB */
+#define WM8400_R12MNBST                         0x0010  /* R12MNBST */
+#define WM8400_R12MNBST_MASK                    0x0010  /* R12MNBST */
+#define WM8400_R12MNBST_SHIFT                        4  /* R12MNBST */
+#define WM8400_R12MNBST_WIDTH                        1  /* R12MNBST */
+#define WM8400_RDBVOL_MASK                      0x0007  /* RDBVOL - [2:0] */
+#define WM8400_RDBVOL_SHIFT                          0  /* RDBVOL - [2:0] */
+#define WM8400_RDBVOL_WIDTH                          3  /* RDBVOL - [2:0] */
+
+/*
+ * R43 (0x2B) - Input Mixer5
+ */
+#define WM8400_LI2BVOL_MASK                     0x01C0  /* LI2BVOL - [8:6] */
+#define WM8400_LI2BVOL_SHIFT                         6  /* LI2BVOL - [8:6] */
+#define WM8400_LI2BVOL_WIDTH                         3  /* LI2BVOL - [8:6] */
+#define WM8400_LR4BVOL_MASK                     0x0038  /* LR4BVOL - [5:3] */
+#define WM8400_LR4BVOL_SHIFT                         3  /* LR4BVOL - [5:3] */
+#define WM8400_LR4BVOL_WIDTH                         3  /* LR4BVOL - [5:3] */
+#define WM8400_LL4BVOL_MASK                     0x0007  /* LL4BVOL - [2:0] */
+#define WM8400_LL4BVOL_SHIFT                         0  /* LL4BVOL - [2:0] */
+#define WM8400_LL4BVOL_WIDTH                         3  /* LL4BVOL - [2:0] */
+
+/*
+ * R44 (0x2C) - Input Mixer6
+ */
+#define WM8400_RI2BVOL_MASK                     0x01C0  /* RI2BVOL - [8:6] */
+#define WM8400_RI2BVOL_SHIFT                         6  /* RI2BVOL - [8:6] */
+#define WM8400_RI2BVOL_WIDTH                         3  /* RI2BVOL - [8:6] */
+#define WM8400_RL4BVOL_MASK                     0x0038  /* RL4BVOL - [5:3] */
+#define WM8400_RL4BVOL_SHIFT                         3  /* RL4BVOL - [5:3] */
+#define WM8400_RL4BVOL_WIDTH                         3  /* RL4BVOL - [5:3] */
+#define WM8400_RR4BVOL_MASK                     0x0007  /* RR4BVOL - [2:0] */
+#define WM8400_RR4BVOL_SHIFT                         0  /* RR4BVOL - [2:0] */
+#define WM8400_RR4BVOL_WIDTH                         3  /* RR4BVOL - [2:0] */
+
+/*
+ * R45 (0x2D) - Output Mixer1
+ */
+#define WM8400_LRBLO                            0x0080  /* LRBLO */
+#define WM8400_LRBLO_MASK                       0x0080  /* LRBLO */
+#define WM8400_LRBLO_SHIFT                           7  /* LRBLO */
+#define WM8400_LRBLO_WIDTH                           1  /* LRBLO */
+#define WM8400_LLBLO                            0x0040  /* LLBLO */
+#define WM8400_LLBLO_MASK                       0x0040  /* LLBLO */
+#define WM8400_LLBLO_SHIFT                           6  /* LLBLO */
+#define WM8400_LLBLO_WIDTH                           1  /* LLBLO */
+#define WM8400_LRI3LO                           0x0020  /* LRI3LO */
+#define WM8400_LRI3LO_MASK                      0x0020  /* LRI3LO */
+#define WM8400_LRI3LO_SHIFT                          5  /* LRI3LO */
+#define WM8400_LRI3LO_WIDTH                          1  /* LRI3LO */
+#define WM8400_LLI3LO                           0x0010  /* LLI3LO */
+#define WM8400_LLI3LO_MASK                      0x0010  /* LLI3LO */
+#define WM8400_LLI3LO_SHIFT                          4  /* LLI3LO */
+#define WM8400_LLI3LO_WIDTH                          1  /* LLI3LO */
+#define WM8400_LR12LO                           0x0008  /* LR12LO */
+#define WM8400_LR12LO_MASK                      0x0008  /* LR12LO */
+#define WM8400_LR12LO_SHIFT                          3  /* LR12LO */
+#define WM8400_LR12LO_WIDTH                          1  /* LR12LO */
+#define WM8400_LL12LO                           0x0004  /* LL12LO */
+#define WM8400_LL12LO_MASK                      0x0004  /* LL12LO */
+#define WM8400_LL12LO_SHIFT                          2  /* LL12LO */
+#define WM8400_LL12LO_WIDTH                          1  /* LL12LO */
+#define WM8400_LDLO                             0x0001  /* LDLO */
+#define WM8400_LDLO_MASK                        0x0001  /* LDLO */
+#define WM8400_LDLO_SHIFT                            0  /* LDLO */
+#define WM8400_LDLO_WIDTH                            1  /* LDLO */
+
+/*
+ * R46 (0x2E) - Output Mixer2
+ */
+#define WM8400_RLBRO                            0x0080  /* RLBRO */
+#define WM8400_RLBRO_MASK                       0x0080  /* RLBRO */
+#define WM8400_RLBRO_SHIFT                           7  /* RLBRO */
+#define WM8400_RLBRO_WIDTH                           1  /* RLBRO */
+#define WM8400_RRBRO                            0x0040  /* RRBRO */
+#define WM8400_RRBRO_MASK                       0x0040  /* RRBRO */
+#define WM8400_RRBRO_SHIFT                           6  /* RRBRO */
+#define WM8400_RRBRO_WIDTH                           1  /* RRBRO */
+#define WM8400_RLI3RO                           0x0020  /* RLI3RO */
+#define WM8400_RLI3RO_MASK                      0x0020  /* RLI3RO */
+#define WM8400_RLI3RO_SHIFT                          5  /* RLI3RO */
+#define WM8400_RLI3RO_WIDTH                          1  /* RLI3RO */
+#define WM8400_RRI3RO                           0x0010  /* RRI3RO */
+#define WM8400_RRI3RO_MASK                      0x0010  /* RRI3RO */
+#define WM8400_RRI3RO_SHIFT                          4  /* RRI3RO */
+#define WM8400_RRI3RO_WIDTH                          1  /* RRI3RO */
+#define WM8400_RL12RO                           0x0008  /* RL12RO */
+#define WM8400_RL12RO_MASK                      0x0008  /* RL12RO */
+#define WM8400_RL12RO_SHIFT                          3  /* RL12RO */
+#define WM8400_RL12RO_WIDTH                          1  /* RL12RO */
+#define WM8400_RR12RO                           0x0004  /* RR12RO */
+#define WM8400_RR12RO_MASK                      0x0004  /* RR12RO */
+#define WM8400_RR12RO_SHIFT                          2  /* RR12RO */
+#define WM8400_RR12RO_WIDTH                          1  /* RR12RO */
+#define WM8400_RDRO                             0x0001  /* RDRO */
+#define WM8400_RDRO_MASK                        0x0001  /* RDRO */
+#define WM8400_RDRO_SHIFT                            0  /* RDRO */
+#define WM8400_RDRO_WIDTH                            1  /* RDRO */
+
+/*
+ * R47 (0x2F) - Output Mixer3
+ */
+#define WM8400_LLI3LOVOL_MASK                   0x01C0  /* LLI3LOVOL - [8:6] */
+#define WM8400_LLI3LOVOL_SHIFT                       6  /* LLI3LOVOL - [8:6] */
+#define WM8400_LLI3LOVOL_WIDTH                       3  /* LLI3LOVOL - [8:6] */
+#define WM8400_LR12LOVOL_MASK                   0x0038  /* LR12LOVOL - [5:3] */
+#define WM8400_LR12LOVOL_SHIFT                       3  /* LR12LOVOL - [5:3] */
+#define WM8400_LR12LOVOL_WIDTH                       3  /* LR12LOVOL - [5:3] */
+#define WM8400_LL12LOVOL_MASK                   0x0007  /* LL12LOVOL - [2:0] */
+#define WM8400_LL12LOVOL_SHIFT                       0  /* LL12LOVOL - [2:0] */
+#define WM8400_LL12LOVOL_WIDTH                       3  /* LL12LOVOL - [2:0] */
+
+/*
+ * R48 (0x30) - Output Mixer4
+ */
+#define WM8400_RRI3ROVOL_MASK                   0x01C0  /* RRI3ROVOL - [8:6] */
+#define WM8400_RRI3ROVOL_SHIFT                       6  /* RRI3ROVOL - [8:6] */
+#define WM8400_RRI3ROVOL_WIDTH                       3  /* RRI3ROVOL - [8:6] */
+#define WM8400_RL12ROVOL_MASK                   0x0038  /* RL12ROVOL - [5:3] */
+#define WM8400_RL12ROVOL_SHIFT                       3  /* RL12ROVOL - [5:3] */
+#define WM8400_RL12ROVOL_WIDTH                       3  /* RL12ROVOL - [5:3] */
+#define WM8400_RR12ROVOL_MASK                   0x0007  /* RR12ROVOL - [2:0] */
+#define WM8400_RR12ROVOL_SHIFT                       0  /* RR12ROVOL - [2:0] */
+#define WM8400_RR12ROVOL_WIDTH                       3  /* RR12ROVOL - [2:0] */
+
+/*
+ * R49 (0x31) - Output Mixer5
+ */
+#define WM8400_LRI3LOVOL_MASK                   0x01C0  /* LRI3LOVOL - [8:6] */
+#define WM8400_LRI3LOVOL_SHIFT                       6  /* LRI3LOVOL - [8:6] */
+#define WM8400_LRI3LOVOL_WIDTH                       3  /* LRI3LOVOL - [8:6] */
+#define WM8400_LRBLOVOL_MASK                    0x0038  /* LRBLOVOL - [5:3] */
+#define WM8400_LRBLOVOL_SHIFT                        3  /* LRBLOVOL - [5:3] */
+#define WM8400_LRBLOVOL_WIDTH                        3  /* LRBLOVOL - [5:3] */
+#define WM8400_LLBLOVOL_MASK                    0x0007  /* LLBLOVOL - [2:0] */
+#define WM8400_LLBLOVOL_SHIFT                        0  /* LLBLOVOL - [2:0] */
+#define WM8400_LLBLOVOL_WIDTH                        3  /* LLBLOVOL - [2:0] */
+
+/*
+ * R50 (0x32) - Output Mixer6
+ */
+#define WM8400_RLI3ROVOL_MASK                   0x01C0  /* RLI3ROVOL - [8:6] */
+#define WM8400_RLI3ROVOL_SHIFT                       6  /* RLI3ROVOL - [8:6] */
+#define WM8400_RLI3ROVOL_WIDTH                       3  /* RLI3ROVOL - [8:6] */
+#define WM8400_RLBROVOL_MASK                    0x0038  /* RLBROVOL - [5:3] */
+#define WM8400_RLBROVOL_SHIFT                        3  /* RLBROVOL - [5:3] */
+#define WM8400_RLBROVOL_WIDTH                        3  /* RLBROVOL - [5:3] */
+#define WM8400_RRBROVOL_MASK                    0x0007  /* RRBROVOL - [2:0] */
+#define WM8400_RRBROVOL_SHIFT                        0  /* RRBROVOL - [2:0] */
+#define WM8400_RRBROVOL_WIDTH                        3  /* RRBROVOL - [2:0] */
+
+/*
+ * R51 (0x33) - Out3/4 Mixer
+ */
+#define WM8400_VSEL_MASK                        0x0180  /* VSEL - [8:7] */
+#define WM8400_VSEL_SHIFT                            7  /* VSEL - [8:7] */
+#define WM8400_VSEL_WIDTH                            2  /* VSEL - [8:7] */
+#define WM8400_LI4O3                            0x0020  /* LI4O3 */
+#define WM8400_LI4O3_MASK                       0x0020  /* LI4O3 */
+#define WM8400_LI4O3_SHIFT                           5  /* LI4O3 */
+#define WM8400_LI4O3_WIDTH                           1  /* LI4O3 */
+#define WM8400_LPGAO3                           0x0010  /* LPGAO3 */
+#define WM8400_LPGAO3_MASK                      0x0010  /* LPGAO3 */
+#define WM8400_LPGAO3_SHIFT                          4  /* LPGAO3 */
+#define WM8400_LPGAO3_WIDTH                          1  /* LPGAO3 */
+#define WM8400_RI4O4                            0x0002  /* RI4O4 */
+#define WM8400_RI4O4_MASK                       0x0002  /* RI4O4 */
+#define WM8400_RI4O4_SHIFT                           1  /* RI4O4 */
+#define WM8400_RI4O4_WIDTH                           1  /* RI4O4 */
+#define WM8400_RPGAO4                           0x0001  /* RPGAO4 */
+#define WM8400_RPGAO4_MASK                      0x0001  /* RPGAO4 */
+#define WM8400_RPGAO4_SHIFT                          0  /* RPGAO4 */
+#define WM8400_RPGAO4_WIDTH                          1  /* RPGAO4 */
+
+/*
+ * R52 (0x34) - Line Mixer1
+ */
+#define WM8400_LLOPGALON                        0x0040  /* LLOPGALON */
+#define WM8400_LLOPGALON_MASK                   0x0040  /* LLOPGALON */
+#define WM8400_LLOPGALON_SHIFT                       6  /* LLOPGALON */
+#define WM8400_LLOPGALON_WIDTH                       1  /* LLOPGALON */
+#define WM8400_LROPGALON                        0x0020  /* LROPGALON */
+#define WM8400_LROPGALON_MASK                   0x0020  /* LROPGALON */
+#define WM8400_LROPGALON_SHIFT                       5  /* LROPGALON */
+#define WM8400_LROPGALON_WIDTH                       1  /* LROPGALON */
+#define WM8400_LOPLON                           0x0010  /* LOPLON */
+#define WM8400_LOPLON_MASK                      0x0010  /* LOPLON */
+#define WM8400_LOPLON_SHIFT                          4  /* LOPLON */
+#define WM8400_LOPLON_WIDTH                          1  /* LOPLON */
+#define WM8400_LR12LOP                          0x0004  /* LR12LOP */
+#define WM8400_LR12LOP_MASK                     0x0004  /* LR12LOP */
+#define WM8400_LR12LOP_SHIFT                         2  /* LR12LOP */
+#define WM8400_LR12LOP_WIDTH                         1  /* LR12LOP */
+#define WM8400_LL12LOP                          0x0002  /* LL12LOP */
+#define WM8400_LL12LOP_MASK                     0x0002  /* LL12LOP */
+#define WM8400_LL12LOP_SHIFT                         1  /* LL12LOP */
+#define WM8400_LL12LOP_WIDTH                         1  /* LL12LOP */
+#define WM8400_LLOPGALOP                        0x0001  /* LLOPGALOP */
+#define WM8400_LLOPGALOP_MASK                   0x0001  /* LLOPGALOP */
+#define WM8400_LLOPGALOP_SHIFT                       0  /* LLOPGALOP */
+#define WM8400_LLOPGALOP_WIDTH                       1  /* LLOPGALOP */
+
+/*
+ * R53 (0x35) - Line Mixer2
+ */
+#define WM8400_RROPGARON                        0x0040  /* RROPGARON */
+#define WM8400_RROPGARON_MASK                   0x0040  /* RROPGARON */
+#define WM8400_RROPGARON_SHIFT                       6  /* RROPGARON */
+#define WM8400_RROPGARON_WIDTH                       1  /* RROPGARON */
+#define WM8400_RLOPGARON                        0x0020  /* RLOPGARON */
+#define WM8400_RLOPGARON_MASK                   0x0020  /* RLOPGARON */
+#define WM8400_RLOPGARON_SHIFT                       5  /* RLOPGARON */
+#define WM8400_RLOPGARON_WIDTH                       1  /* RLOPGARON */
+#define WM8400_ROPRON                           0x0010  /* ROPRON */
+#define WM8400_ROPRON_MASK                      0x0010  /* ROPRON */
+#define WM8400_ROPRON_SHIFT                          4  /* ROPRON */
+#define WM8400_ROPRON_WIDTH                          1  /* ROPRON */
+#define WM8400_RL12ROP                          0x0004  /* RL12ROP */
+#define WM8400_RL12ROP_MASK                     0x0004  /* RL12ROP */
+#define WM8400_RL12ROP_SHIFT                         2  /* RL12ROP */
+#define WM8400_RL12ROP_WIDTH                         1  /* RL12ROP */
+#define WM8400_RR12ROP                          0x0002  /* RR12ROP */
+#define WM8400_RR12ROP_MASK                     0x0002  /* RR12ROP */
+#define WM8400_RR12ROP_SHIFT                         1  /* RR12ROP */
+#define WM8400_RR12ROP_WIDTH                         1  /* RR12ROP */
+#define WM8400_RROPGAROP                        0x0001  /* RROPGAROP */
+#define WM8400_RROPGAROP_MASK                   0x0001  /* RROPGAROP */
+#define WM8400_RROPGAROP_SHIFT                       0  /* RROPGAROP */
+#define WM8400_RROPGAROP_WIDTH                       1  /* RROPGAROP */
+
+/*
+ * R54 (0x36) - Speaker Mixer
+ */
+#define WM8400_LB2SPK                           0x0080  /* LB2SPK */
+#define WM8400_LB2SPK_MASK                      0x0080  /* LB2SPK */
+#define WM8400_LB2SPK_SHIFT                          7  /* LB2SPK */
+#define WM8400_LB2SPK_WIDTH                          1  /* LB2SPK */
+#define WM8400_RB2SPK                           0x0040  /* RB2SPK */
+#define WM8400_RB2SPK_MASK                      0x0040  /* RB2SPK */
+#define WM8400_RB2SPK_SHIFT                          6  /* RB2SPK */
+#define WM8400_RB2SPK_WIDTH                          1  /* RB2SPK */
+#define WM8400_LI2SPK                           0x0020  /* LI2SPK */
+#define WM8400_LI2SPK_MASK                      0x0020  /* LI2SPK */
+#define WM8400_LI2SPK_SHIFT                          5  /* LI2SPK */
+#define WM8400_LI2SPK_WIDTH                          1  /* LI2SPK */
+#define WM8400_RI2SPK                           0x0010  /* RI2SPK */
+#define WM8400_RI2SPK_MASK                      0x0010  /* RI2SPK */
+#define WM8400_RI2SPK_SHIFT                          4  /* RI2SPK */
+#define WM8400_RI2SPK_WIDTH                          1  /* RI2SPK */
+#define WM8400_LOPGASPK                         0x0008  /* LOPGASPK */
+#define WM8400_LOPGASPK_MASK                    0x0008  /* LOPGASPK */
+#define WM8400_LOPGASPK_SHIFT                        3  /* LOPGASPK */
+#define WM8400_LOPGASPK_WIDTH                        1  /* LOPGASPK */
+#define WM8400_ROPGASPK                         0x0004  /* ROPGASPK */
+#define WM8400_ROPGASPK_MASK                    0x0004  /* ROPGASPK */
+#define WM8400_ROPGASPK_SHIFT                        2  /* ROPGASPK */
+#define WM8400_ROPGASPK_WIDTH                        1  /* ROPGASPK */
+#define WM8400_LDSPK                            0x0002  /* LDSPK */
+#define WM8400_LDSPK_MASK                       0x0002  /* LDSPK */
+#define WM8400_LDSPK_SHIFT                           1  /* LDSPK */
+#define WM8400_LDSPK_WIDTH                           1  /* LDSPK */
+#define WM8400_RDSPK                            0x0001  /* RDSPK */
+#define WM8400_RDSPK_MASK                       0x0001  /* RDSPK */
+#define WM8400_RDSPK_SHIFT                           0  /* RDSPK */
+#define WM8400_RDSPK_WIDTH                           1  /* RDSPK */
+
+/*
+ * R55 (0x37) - Additional Control
+ */
+#define WM8400_VROI                             0x0001  /* VROI */
+#define WM8400_VROI_MASK                        0x0001  /* VROI */
+#define WM8400_VROI_SHIFT                            0  /* VROI */
+#define WM8400_VROI_WIDTH                            1  /* VROI */
+
+/*
+ * R56 (0x38) - AntiPOP1
+ */
+#define WM8400_DIS_LLINE                        0x0020  /* DIS_LLINE */
+#define WM8400_DIS_LLINE_MASK                   0x0020  /* DIS_LLINE */
+#define WM8400_DIS_LLINE_SHIFT                       5  /* DIS_LLINE */
+#define WM8400_DIS_LLINE_WIDTH                       1  /* DIS_LLINE */
+#define WM8400_DIS_RLINE                        0x0010  /* DIS_RLINE */
+#define WM8400_DIS_RLINE_MASK                   0x0010  /* DIS_RLINE */
+#define WM8400_DIS_RLINE_SHIFT                       4  /* DIS_RLINE */
+#define WM8400_DIS_RLINE_WIDTH                       1  /* DIS_RLINE */
+#define WM8400_DIS_OUT3                         0x0008  /* DIS_OUT3 */
+#define WM8400_DIS_OUT3_MASK                    0x0008  /* DIS_OUT3 */
+#define WM8400_DIS_OUT3_SHIFT                        3  /* DIS_OUT3 */
+#define WM8400_DIS_OUT3_WIDTH                        1  /* DIS_OUT3 */
+#define WM8400_DIS_OUT4                         0x0004  /* DIS_OUT4 */
+#define WM8400_DIS_OUT4_MASK                    0x0004  /* DIS_OUT4 */
+#define WM8400_DIS_OUT4_SHIFT                        2  /* DIS_OUT4 */
+#define WM8400_DIS_OUT4_WIDTH                        1  /* DIS_OUT4 */
+#define WM8400_DIS_LOUT                         0x0002  /* DIS_LOUT */
+#define WM8400_DIS_LOUT_MASK                    0x0002  /* DIS_LOUT */
+#define WM8400_DIS_LOUT_SHIFT                        1  /* DIS_LOUT */
+#define WM8400_DIS_LOUT_WIDTH                        1  /* DIS_LOUT */
+#define WM8400_DIS_ROUT                         0x0001  /* DIS_ROUT */
+#define WM8400_DIS_ROUT_MASK                    0x0001  /* DIS_ROUT */
+#define WM8400_DIS_ROUT_SHIFT                        0  /* DIS_ROUT */
+#define WM8400_DIS_ROUT_WIDTH                        1  /* DIS_ROUT */
+
+/*
+ * R57 (0x39) - AntiPOP2
+ */
+#define WM8400_SOFTST                           0x0040  /* SOFTST */
+#define WM8400_SOFTST_MASK                      0x0040  /* SOFTST */
+#define WM8400_SOFTST_SHIFT                          6  /* SOFTST */
+#define WM8400_SOFTST_WIDTH                          1  /* SOFTST */
+#define WM8400_BUFIOEN                          0x0008  /* BUFIOEN */
+#define WM8400_BUFIOEN_MASK                     0x0008  /* BUFIOEN */
+#define WM8400_BUFIOEN_SHIFT                         3  /* BUFIOEN */
+#define WM8400_BUFIOEN_WIDTH                         1  /* BUFIOEN */
+#define WM8400_BUFDCOPEN                        0x0004  /* BUFDCOPEN */
+#define WM8400_BUFDCOPEN_MASK                   0x0004  /* BUFDCOPEN */
+#define WM8400_BUFDCOPEN_SHIFT                       2  /* BUFDCOPEN */
+#define WM8400_BUFDCOPEN_WIDTH                       1  /* BUFDCOPEN */
+#define WM8400_POBCTRL                          0x0002  /* POBCTRL */
+#define WM8400_POBCTRL_MASK                     0x0002  /* POBCTRL */
+#define WM8400_POBCTRL_SHIFT                         1  /* POBCTRL */
+#define WM8400_POBCTRL_WIDTH                         1  /* POBCTRL */
+#define WM8400_VMIDTOG                          0x0001  /* VMIDTOG */
+#define WM8400_VMIDTOG_MASK                     0x0001  /* VMIDTOG */
+#define WM8400_VMIDTOG_SHIFT                         0  /* VMIDTOG */
+#define WM8400_VMIDTOG_WIDTH                         1  /* VMIDTOG */
+
+/*
+ * R58 (0x3A) - MICBIAS
+ */
+#define WM8400_MCDSCTH_MASK                     0x00C0  /* MCDSCTH - [7:6] */
+#define WM8400_MCDSCTH_SHIFT                         6  /* MCDSCTH - [7:6] */
+#define WM8400_MCDSCTH_WIDTH                         2  /* MCDSCTH - [7:6] */
+#define WM8400_MCDTHR_MASK                      0x0038  /* MCDTHR - [5:3] */
+#define WM8400_MCDTHR_SHIFT                          3  /* MCDTHR - [5:3] */
+#define WM8400_MCDTHR_WIDTH                          3  /* MCDTHR - [5:3] */
+#define WM8400_MCD                              0x0004  /* MCD */
+#define WM8400_MCD_MASK                         0x0004  /* MCD */
+#define WM8400_MCD_SHIFT                             2  /* MCD */
+#define WM8400_MCD_WIDTH                             1  /* MCD */
+#define WM8400_MBSEL                            0x0001  /* MBSEL */
+#define WM8400_MBSEL_MASK                       0x0001  /* MBSEL */
+#define WM8400_MBSEL_SHIFT                           0  /* MBSEL */
+#define WM8400_MBSEL_WIDTH                           1  /* MBSEL */
+
+/*
+ * R60 (0x3C) - FLL Control 1
+ */
+#define WM8400_FLL_REF_FREQ                     0x1000  /* FLL_REF_FREQ */
+#define WM8400_FLL_REF_FREQ_MASK                0x1000  /* FLL_REF_FREQ */
+#define WM8400_FLL_REF_FREQ_SHIFT                   12  /* FLL_REF_FREQ */
+#define WM8400_FLL_REF_FREQ_WIDTH                    1  /* FLL_REF_FREQ */
+#define WM8400_FLL_CLK_SRC_MASK                 0x0C00  /* FLL_CLK_SRC - [11:10] */
+#define WM8400_FLL_CLK_SRC_SHIFT                    10  /* FLL_CLK_SRC - [11:10] */
+#define WM8400_FLL_CLK_SRC_WIDTH                     2  /* FLL_CLK_SRC - [11:10] */
+#define WM8400_FLL_FRAC                         0x0200  /* FLL_FRAC */
+#define WM8400_FLL_FRAC_MASK                    0x0200  /* FLL_FRAC */
+#define WM8400_FLL_FRAC_SHIFT                        9  /* FLL_FRAC */
+#define WM8400_FLL_FRAC_WIDTH                        1  /* FLL_FRAC */
+#define WM8400_FLL_OSC_ENA                      0x0100  /* FLL_OSC_ENA */
+#define WM8400_FLL_OSC_ENA_MASK                 0x0100  /* FLL_OSC_ENA */
+#define WM8400_FLL_OSC_ENA_SHIFT                     8  /* FLL_OSC_ENA */
+#define WM8400_FLL_OSC_ENA_WIDTH                     1  /* FLL_OSC_ENA */
+#define WM8400_FLL_CTRL_RATE_MASK               0x00E0  /* FLL_CTRL_RATE - [7:5] */
+#define WM8400_FLL_CTRL_RATE_SHIFT                   5  /* FLL_CTRL_RATE - [7:5] */
+#define WM8400_FLL_CTRL_RATE_WIDTH                   3  /* FLL_CTRL_RATE - [7:5] */
+#define WM8400_FLL_FRATIO_MASK                  0x001F  /* FLL_FRATIO - [4:0] */
+#define WM8400_FLL_FRATIO_SHIFT                      0  /* FLL_FRATIO - [4:0] */
+#define WM8400_FLL_FRATIO_WIDTH                      5  /* FLL_FRATIO - [4:0] */
+
+/*
+ * R61 (0x3D) - FLL Control 2
+ */
+#define WM8400_FLL_K_MASK                       0xFFFF  /* FLL_K - [15:0] */
+#define WM8400_FLL_K_SHIFT                           0  /* FLL_K - [15:0] */
+#define WM8400_FLL_K_WIDTH                          16  /* FLL_K - [15:0] */
+
+/*
+ * R62 (0x3E) - FLL Control 3
+ */
+#define WM8400_FLL_N_MASK                       0x03FF  /* FLL_N - [9:0] */
+#define WM8400_FLL_N_SHIFT                           0  /* FLL_N - [9:0] */
+#define WM8400_FLL_N_WIDTH                          10  /* FLL_N - [9:0] */
+
+/*
+ * R63 (0x3F) - FLL Control 4
+ */
+#define WM8400_FLL_TRK_GAIN_MASK                0x0078  /* FLL_TRK_GAIN - [6:3] */
+#define WM8400_FLL_TRK_GAIN_SHIFT                    3  /* FLL_TRK_GAIN - [6:3] */
+#define WM8400_FLL_TRK_GAIN_WIDTH                    4  /* FLL_TRK_GAIN - [6:3] */
+#define WM8400_FLL_OUTDIV_MASK                  0x0007  /* FLL_OUTDIV - [2:0] */
+#define WM8400_FLL_OUTDIV_SHIFT                      0  /* FLL_OUTDIV - [2:0] */
+#define WM8400_FLL_OUTDIV_WIDTH                      3  /* FLL_OUTDIV - [2:0] */
+
+void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400);
+
+#endif
diff --git a/include/linux/mfd/wm8400-private.h b/include/linux/mfd/wm8400-private.h
new file mode 100644
index 000000000000..2aab4e93a5c9
--- /dev/null
+++ b/include/linux/mfd/wm8400-private.h
@@ -0,0 +1,936 @@
+/*
+ * wm8400 private definitions.
+ *
+ * Copyright 2008 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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __LINUX_MFD_WM8400_PRIV_H
+#define __LINUX_MFD_WM8400_PRIV_H
+
+#include <linux/mfd/wm8400.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+
+#define WM8400_REGISTER_COUNT 0x55
+
+struct wm8400 {
+	struct device *dev;
+
+	int (*read_dev)(void *data, char reg, int count, u16 *dst);
+	int (*write_dev)(void *data, char reg, int count, const u16 *src);
+
+	struct mutex io_lock;
+	void *io_data;
+
+	u16 reg_cache[WM8400_REGISTER_COUNT];
+
+	struct platform_device regulators[6];
+};
+
+/*
+ * Register values.
+ */
+#define WM8400_RESET_ID                         0x00
+#define WM8400_ID                               0x01
+#define WM8400_POWER_MANAGEMENT_1               0x02
+#define WM8400_POWER_MANAGEMENT_2               0x03
+#define WM8400_POWER_MANAGEMENT_3               0x04
+#define WM8400_AUDIO_INTERFACE_1                0x05
+#define WM8400_AUDIO_INTERFACE_2                0x06
+#define WM8400_CLOCKING_1                       0x07
+#define WM8400_CLOCKING_2                       0x08
+#define WM8400_AUDIO_INTERFACE_3                0x09
+#define WM8400_AUDIO_INTERFACE_4                0x0A
+#define WM8400_DAC_CTRL                         0x0B
+#define WM8400_LEFT_DAC_DIGITAL_VOLUME          0x0C
+#define WM8400_RIGHT_DAC_DIGITAL_VOLUME         0x0D
+#define WM8400_DIGITAL_SIDE_TONE                0x0E
+#define WM8400_ADC_CTRL                         0x0F
+#define WM8400_LEFT_ADC_DIGITAL_VOLUME          0x10
+#define WM8400_RIGHT_ADC_DIGITAL_VOLUME         0x11
+#define WM8400_GPIO_CTRL_1                      0x12
+#define WM8400_GPIO1_GPIO2                      0x13
+#define WM8400_GPIO3_GPIO4                      0x14
+#define WM8400_GPIO5_GPIO6                      0x15
+#define WM8400_GPIOCTRL_2                       0x16
+#define WM8400_GPIO_POL                         0x17
+#define WM8400_LEFT_LINE_INPUT_1_2_VOLUME       0x18
+#define WM8400_LEFT_LINE_INPUT_3_4_VOLUME       0x19
+#define WM8400_RIGHT_LINE_INPUT_1_2_VOLUME      0x1A
+#define WM8400_RIGHT_LINE_INPUT_3_4_VOLUME      0x1B
+#define WM8400_LEFT_OUTPUT_VOLUME               0x1C
+#define WM8400_RIGHT_OUTPUT_VOLUME              0x1D
+#define WM8400_LINE_OUTPUTS_VOLUME              0x1E
+#define WM8400_OUT3_4_VOLUME                    0x1F
+#define WM8400_LEFT_OPGA_VOLUME                 0x20
+#define WM8400_RIGHT_OPGA_VOLUME                0x21
+#define WM8400_SPEAKER_VOLUME                   0x22
+#define WM8400_CLASSD1                          0x23
+#define WM8400_CLASSD3                          0x25
+#define WM8400_INPUT_MIXER1                     0x27
+#define WM8400_INPUT_MIXER2                     0x28
+#define WM8400_INPUT_MIXER3                     0x29
+#define WM8400_INPUT_MIXER4                     0x2A
+#define WM8400_INPUT_MIXER5                     0x2B
+#define WM8400_INPUT_MIXER6                     0x2C
+#define WM8400_OUTPUT_MIXER1                    0x2D
+#define WM8400_OUTPUT_MIXER2                    0x2E
+#define WM8400_OUTPUT_MIXER3                    0x2F
+#define WM8400_OUTPUT_MIXER4                    0x30
+#define WM8400_OUTPUT_MIXER5                    0x31
+#define WM8400_OUTPUT_MIXER6                    0x32
+#define WM8400_OUT3_4_MIXER                     0x33
+#define WM8400_LINE_MIXER1                      0x34
+#define WM8400_LINE_MIXER2                      0x35
+#define WM8400_SPEAKER_MIXER                    0x36
+#define WM8400_ADDITIONAL_CONTROL               0x37
+#define WM8400_ANTIPOP1                         0x38
+#define WM8400_ANTIPOP2                         0x39
+#define WM8400_MICBIAS                          0x3A
+#define WM8400_FLL_CONTROL_1                    0x3C
+#define WM8400_FLL_CONTROL_2                    0x3D
+#define WM8400_FLL_CONTROL_3                    0x3E
+#define WM8400_FLL_CONTROL_4                    0x3F
+#define WM8400_LDO1_CONTROL                     0x41
+#define WM8400_LDO2_CONTROL                     0x42
+#define WM8400_LDO3_CONTROL                     0x43
+#define WM8400_LDO4_CONTROL                     0x44
+#define WM8400_DCDC1_CONTROL_1                  0x46
+#define WM8400_DCDC1_CONTROL_2                  0x47
+#define WM8400_DCDC2_CONTROL_1                  0x48
+#define WM8400_DCDC2_CONTROL_2                  0x49
+#define WM8400_INTERFACE                        0x4B
+#define WM8400_PM_GENERAL                       0x4C
+#define WM8400_PM_SHUTDOWN_CONTROL              0x4E
+#define WM8400_INTERRUPT_STATUS_1               0x4F
+#define WM8400_INTERRUPT_STATUS_1_MASK          0x50
+#define WM8400_INTERRUPT_LEVELS                 0x51
+#define WM8400_SHUTDOWN_REASON                  0x52
+#define WM8400_LINE_CIRCUITS                    0x54
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - Reset/ID
+ */
+#define WM8400_SW_RESET_CHIP_ID_MASK            0xFFFF  /* SW_RESET/CHIP_ID - [15:0] */
+#define WM8400_SW_RESET_CHIP_ID_SHIFT                0  /* SW_RESET/CHIP_ID - [15:0] */
+#define WM8400_SW_RESET_CHIP_ID_WIDTH               16  /* SW_RESET/CHIP_ID - [15:0] */
+
+/*
+ * R1 (0x01) - ID
+ */
+#define WM8400_CHIP_REV_MASK                    0x7000  /* CHIP_REV - [14:12] */
+#define WM8400_CHIP_REV_SHIFT                       12  /* CHIP_REV - [14:12] */
+#define WM8400_CHIP_REV_WIDTH                        3  /* CHIP_REV - [14:12] */
+
+/*
+ * R18 (0x12) - GPIO CTRL 1
+ */
+#define WM8400_IRQ                              0x1000  /* IRQ */
+#define WM8400_IRQ_MASK                         0x1000  /* IRQ */
+#define WM8400_IRQ_SHIFT                            12  /* IRQ */
+#define WM8400_IRQ_WIDTH                             1  /* IRQ */
+#define WM8400_TEMPOK                           0x0800  /* TEMPOK */
+#define WM8400_TEMPOK_MASK                      0x0800  /* TEMPOK */
+#define WM8400_TEMPOK_SHIFT                         11  /* TEMPOK */
+#define WM8400_TEMPOK_WIDTH                          1  /* TEMPOK */
+#define WM8400_MIC1SHRT                         0x0400  /* MIC1SHRT */
+#define WM8400_MIC1SHRT_MASK                    0x0400  /* MIC1SHRT */
+#define WM8400_MIC1SHRT_SHIFT                       10  /* MIC1SHRT */
+#define WM8400_MIC1SHRT_WIDTH                        1  /* MIC1SHRT */
+#define WM8400_MIC1DET                          0x0200  /* MIC1DET */
+#define WM8400_MIC1DET_MASK                     0x0200  /* MIC1DET */
+#define WM8400_MIC1DET_SHIFT                         9  /* MIC1DET */
+#define WM8400_MIC1DET_WIDTH                         1  /* MIC1DET */
+#define WM8400_FLL_LCK                          0x0100  /* FLL_LCK */
+#define WM8400_FLL_LCK_MASK                     0x0100  /* FLL_LCK */
+#define WM8400_FLL_LCK_SHIFT                         8  /* FLL_LCK */
+#define WM8400_FLL_LCK_WIDTH                         1  /* FLL_LCK */
+#define WM8400_GPIO_STATUS_MASK                 0x00FF  /* GPIO_STATUS - [7:0] */
+#define WM8400_GPIO_STATUS_SHIFT                     0  /* GPIO_STATUS - [7:0] */
+#define WM8400_GPIO_STATUS_WIDTH                     8  /* GPIO_STATUS - [7:0] */
+
+/*
+ * R19 (0x13) - GPIO1 & GPIO2
+ */
+#define WM8400_GPIO2_DEB_ENA                    0x8000  /* GPIO2_DEB_ENA */
+#define WM8400_GPIO2_DEB_ENA_MASK               0x8000  /* GPIO2_DEB_ENA */
+#define WM8400_GPIO2_DEB_ENA_SHIFT                  15  /* GPIO2_DEB_ENA */
+#define WM8400_GPIO2_DEB_ENA_WIDTH                   1  /* GPIO2_DEB_ENA */
+#define WM8400_GPIO2_IRQ_ENA                    0x4000  /* GPIO2_IRQ_ENA */
+#define WM8400_GPIO2_IRQ_ENA_MASK               0x4000  /* GPIO2_IRQ_ENA */
+#define WM8400_GPIO2_IRQ_ENA_SHIFT                  14  /* GPIO2_IRQ_ENA */
+#define WM8400_GPIO2_IRQ_ENA_WIDTH                   1  /* GPIO2_IRQ_ENA */
+#define WM8400_GPIO2_PU                         0x2000  /* GPIO2_PU */
+#define WM8400_GPIO2_PU_MASK                    0x2000  /* GPIO2_PU */
+#define WM8400_GPIO2_PU_SHIFT                       13  /* GPIO2_PU */
+#define WM8400_GPIO2_PU_WIDTH                        1  /* GPIO2_PU */
+#define WM8400_GPIO2_PD                         0x1000  /* GPIO2_PD */
+#define WM8400_GPIO2_PD_MASK                    0x1000  /* GPIO2_PD */
+#define WM8400_GPIO2_PD_SHIFT                       12  /* GPIO2_PD */
+#define WM8400_GPIO2_PD_WIDTH                        1  /* GPIO2_PD */
+#define WM8400_GPIO2_SEL_MASK                   0x0F00  /* GPIO2_SEL - [11:8] */
+#define WM8400_GPIO2_SEL_SHIFT                       8  /* GPIO2_SEL - [11:8] */
+#define WM8400_GPIO2_SEL_WIDTH                       4  /* GPIO2_SEL - [11:8] */
+#define WM8400_GPIO1_DEB_ENA                    0x0080  /* GPIO1_DEB_ENA */
+#define WM8400_GPIO1_DEB_ENA_MASK               0x0080  /* GPIO1_DEB_ENA */
+#define WM8400_GPIO1_DEB_ENA_SHIFT                   7  /* GPIO1_DEB_ENA */
+#define WM8400_GPIO1_DEB_ENA_WIDTH                   1  /* GPIO1_DEB_ENA */
+#define WM8400_GPIO1_IRQ_ENA                    0x0040  /* GPIO1_IRQ_ENA */
+#define WM8400_GPIO1_IRQ_ENA_MASK               0x0040  /* GPIO1_IRQ_ENA */
+#define WM8400_GPIO1_IRQ_ENA_SHIFT                   6  /* GPIO1_IRQ_ENA */
+#define WM8400_GPIO1_IRQ_ENA_WIDTH                   1  /* GPIO1_IRQ_ENA */
+#define WM8400_GPIO1_PU                         0x0020  /* GPIO1_PU */
+#define WM8400_GPIO1_PU_MASK                    0x0020  /* GPIO1_PU */
+#define WM8400_GPIO1_PU_SHIFT                        5  /* GPIO1_PU */
+#define WM8400_GPIO1_PU_WIDTH                        1  /* GPIO1_PU */
+#define WM8400_GPIO1_PD                         0x0010  /* GPIO1_PD */
+#define WM8400_GPIO1_PD_MASK                    0x0010  /* GPIO1_PD */
+#define WM8400_GPIO1_PD_SHIFT                        4  /* GPIO1_PD */
+#define WM8400_GPIO1_PD_WIDTH                        1  /* GPIO1_PD */
+#define WM8400_GPIO1_SEL_MASK                   0x000F  /* GPIO1_SEL - [3:0] */
+#define WM8400_GPIO1_SEL_SHIFT                       0  /* GPIO1_SEL - [3:0] */
+#define WM8400_GPIO1_SEL_WIDTH                       4  /* GPIO1_SEL - [3:0] */
+
+/*
+ * R20 (0x14) - GPIO3 & GPIO4
+ */
+#define WM8400_GPIO4_DEB_ENA                    0x8000  /* GPIO4_DEB_ENA */
+#define WM8400_GPIO4_DEB_ENA_MASK               0x8000  /* GPIO4_DEB_ENA */
+#define WM8400_GPIO4_DEB_ENA_SHIFT                  15  /* GPIO4_DEB_ENA */
+#define WM8400_GPIO4_DEB_ENA_WIDTH                   1  /* GPIO4_DEB_ENA */
+#define WM8400_GPIO4_IRQ_ENA                    0x4000  /* GPIO4_IRQ_ENA */
+#define WM8400_GPIO4_IRQ_ENA_MASK               0x4000  /* GPIO4_IRQ_ENA */
+#define WM8400_GPIO4_IRQ_ENA_SHIFT                  14  /* GPIO4_IRQ_ENA */
+#define WM8400_GPIO4_IRQ_ENA_WIDTH                   1  /* GPIO4_IRQ_ENA */
+#define WM8400_GPIO4_PU                         0x2000  /* GPIO4_PU */
+#define WM8400_GPIO4_PU_MASK                    0x2000  /* GPIO4_PU */
+#define WM8400_GPIO4_PU_SHIFT                       13  /* GPIO4_PU */
+#define WM8400_GPIO4_PU_WIDTH                        1  /* GPIO4_PU */
+#define WM8400_GPIO4_PD                         0x1000  /* GPIO4_PD */
+#define WM8400_GPIO4_PD_MASK                    0x1000  /* GPIO4_PD */
+#define WM8400_GPIO4_PD_SHIFT                       12  /* GPIO4_PD */
+#define WM8400_GPIO4_PD_WIDTH                        1  /* GPIO4_PD */
+#define WM8400_GPIO4_SEL_MASK                   0x0F00  /* GPIO4_SEL - [11:8] */
+#define WM8400_GPIO4_SEL_SHIFT                       8  /* GPIO4_SEL - [11:8] */
+#define WM8400_GPIO4_SEL_WIDTH                       4  /* GPIO4_SEL - [11:8] */
+#define WM8400_GPIO3_DEB_ENA                    0x0080  /* GPIO3_DEB_ENA */
+#define WM8400_GPIO3_DEB_ENA_MASK               0x0080  /* GPIO3_DEB_ENA */
+#define WM8400_GPIO3_DEB_ENA_SHIFT                   7  /* GPIO3_DEB_ENA */
+#define WM8400_GPIO3_DEB_ENA_WIDTH                   1  /* GPIO3_DEB_ENA */
+#define WM8400_GPIO3_IRQ_ENA                    0x0040  /* GPIO3_IRQ_ENA */
+#define WM8400_GPIO3_IRQ_ENA_MASK               0x0040  /* GPIO3_IRQ_ENA */
+#define WM8400_GPIO3_IRQ_ENA_SHIFT                   6  /* GPIO3_IRQ_ENA */
+#define WM8400_GPIO3_IRQ_ENA_WIDTH                   1  /* GPIO3_IRQ_ENA */
+#define WM8400_GPIO3_PU                         0x0020  /* GPIO3_PU */
+#define WM8400_GPIO3_PU_MASK                    0x0020  /* GPIO3_PU */
+#define WM8400_GPIO3_PU_SHIFT                        5  /* GPIO3_PU */
+#define WM8400_GPIO3_PU_WIDTH                        1  /* GPIO3_PU */
+#define WM8400_GPIO3_PD                         0x0010  /* GPIO3_PD */
+#define WM8400_GPIO3_PD_MASK                    0x0010  /* GPIO3_PD */
+#define WM8400_GPIO3_PD_SHIFT                        4  /* GPIO3_PD */
+#define WM8400_GPIO3_PD_WIDTH                        1  /* GPIO3_PD */
+#define WM8400_GPIO3_SEL_MASK                   0x000F  /* GPIO3_SEL - [3:0] */
+#define WM8400_GPIO3_SEL_SHIFT                       0  /* GPIO3_SEL - [3:0] */
+#define WM8400_GPIO3_SEL_WIDTH                       4  /* GPIO3_SEL - [3:0] */
+
+/*
+ * R21 (0x15) - GPIO5 & GPIO6
+ */
+#define WM8400_GPIO6_DEB_ENA                    0x8000  /* GPIO6_DEB_ENA */
+#define WM8400_GPIO6_DEB_ENA_MASK               0x8000  /* GPIO6_DEB_ENA */
+#define WM8400_GPIO6_DEB_ENA_SHIFT                  15  /* GPIO6_DEB_ENA */
+#define WM8400_GPIO6_DEB_ENA_WIDTH                   1  /* GPIO6_DEB_ENA */
+#define WM8400_GPIO6_IRQ_ENA                    0x4000  /* GPIO6_IRQ_ENA */
+#define WM8400_GPIO6_IRQ_ENA_MASK               0x4000  /* GPIO6_IRQ_ENA */
+#define WM8400_GPIO6_IRQ_ENA_SHIFT                  14  /* GPIO6_IRQ_ENA */
+#define WM8400_GPIO6_IRQ_ENA_WIDTH                   1  /* GPIO6_IRQ_ENA */
+#define WM8400_GPIO6_PU                         0x2000  /* GPIO6_PU */
+#define WM8400_GPIO6_PU_MASK                    0x2000  /* GPIO6_PU */
+#define WM8400_GPIO6_PU_SHIFT                       13  /* GPIO6_PU */
+#define WM8400_GPIO6_PU_WIDTH                        1  /* GPIO6_PU */
+#define WM8400_GPIO6_PD                         0x1000  /* GPIO6_PD */
+#define WM8400_GPIO6_PD_MASK                    0x1000  /* GPIO6_PD */
+#define WM8400_GPIO6_PD_SHIFT                       12  /* GPIO6_PD */
+#define WM8400_GPIO6_PD_WIDTH                        1  /* GPIO6_PD */
+#define WM8400_GPIO6_SEL_MASK                   0x0F00  /* GPIO6_SEL - [11:8] */
+#define WM8400_GPIO6_SEL_SHIFT                       8  /* GPIO6_SEL - [11:8] */
+#define WM8400_GPIO6_SEL_WIDTH                       4  /* GPIO6_SEL - [11:8] */
+#define WM8400_GPIO5_DEB_ENA                    0x0080  /* GPIO5_DEB_ENA */
+#define WM8400_GPIO5_DEB_ENA_MASK               0x0080  /* GPIO5_DEB_ENA */
+#define WM8400_GPIO5_DEB_ENA_SHIFT                   7  /* GPIO5_DEB_ENA */
+#define WM8400_GPIO5_DEB_ENA_WIDTH                   1  /* GPIO5_DEB_ENA */
+#define WM8400_GPIO5_IRQ_ENA                    0x0040  /* GPIO5_IRQ_ENA */
+#define WM8400_GPIO5_IRQ_ENA_MASK               0x0040  /* GPIO5_IRQ_ENA */
+#define WM8400_GPIO5_IRQ_ENA_SHIFT                   6  /* GPIO5_IRQ_ENA */
+#define WM8400_GPIO5_IRQ_ENA_WIDTH                   1  /* GPIO5_IRQ_ENA */
+#define WM8400_GPIO5_PU                         0x0020  /* GPIO5_PU */
+#define WM8400_GPIO5_PU_MASK                    0x0020  /* GPIO5_PU */
+#define WM8400_GPIO5_PU_SHIFT                        5  /* GPIO5_PU */
+#define WM8400_GPIO5_PU_WIDTH                        1  /* GPIO5_PU */
+#define WM8400_GPIO5_PD                         0x0010  /* GPIO5_PD */
+#define WM8400_GPIO5_PD_MASK                    0x0010  /* GPIO5_PD */
+#define WM8400_GPIO5_PD_SHIFT                        4  /* GPIO5_PD */
+#define WM8400_GPIO5_PD_WIDTH                        1  /* GPIO5_PD */
+#define WM8400_GPIO5_SEL_MASK                   0x000F  /* GPIO5_SEL - [3:0] */
+#define WM8400_GPIO5_SEL_SHIFT                       0  /* GPIO5_SEL - [3:0] */
+#define WM8400_GPIO5_SEL_WIDTH                       4  /* GPIO5_SEL - [3:0] */
+
+/*
+ * R22 (0x16) - GPIOCTRL 2
+ */
+#define WM8400_TEMPOK_IRQ_ENA                   0x0800  /* TEMPOK_IRQ_ENA */
+#define WM8400_TEMPOK_IRQ_ENA_MASK              0x0800  /* TEMPOK_IRQ_ENA */
+#define WM8400_TEMPOK_IRQ_ENA_SHIFT                 11  /* TEMPOK_IRQ_ENA */
+#define WM8400_TEMPOK_IRQ_ENA_WIDTH                  1  /* TEMPOK_IRQ_ENA */
+#define WM8400_MIC1SHRT_IRQ_ENA                 0x0400  /* MIC1SHRT_IRQ_ENA */
+#define WM8400_MIC1SHRT_IRQ_ENA_MASK            0x0400  /* MIC1SHRT_IRQ_ENA */
+#define WM8400_MIC1SHRT_IRQ_ENA_SHIFT               10  /* MIC1SHRT_IRQ_ENA */
+#define WM8400_MIC1SHRT_IRQ_ENA_WIDTH                1  /* MIC1SHRT_IRQ_ENA */
+#define WM8400_MIC1DET_IRQ_ENA                  0x0200  /* MIC1DET_IRQ_ENA */
+#define WM8400_MIC1DET_IRQ_ENA_MASK             0x0200  /* MIC1DET_IRQ_ENA */
+#define WM8400_MIC1DET_IRQ_ENA_SHIFT                 9  /* MIC1DET_IRQ_ENA */
+#define WM8400_MIC1DET_IRQ_ENA_WIDTH                 1  /* MIC1DET_IRQ_ENA */
+#define WM8400_FLL_LCK_IRQ_ENA                  0x0100  /* FLL_LCK_IRQ_ENA */
+#define WM8400_FLL_LCK_IRQ_ENA_MASK             0x0100  /* FLL_LCK_IRQ_ENA */
+#define WM8400_FLL_LCK_IRQ_ENA_SHIFT                 8  /* FLL_LCK_IRQ_ENA */
+#define WM8400_FLL_LCK_IRQ_ENA_WIDTH                 1  /* FLL_LCK_IRQ_ENA */
+#define WM8400_GPI8_DEB_ENA                     0x0080  /* GPI8_DEB_ENA */
+#define WM8400_GPI8_DEB_ENA_MASK                0x0080  /* GPI8_DEB_ENA */
+#define WM8400_GPI8_DEB_ENA_SHIFT                    7  /* GPI8_DEB_ENA */
+#define WM8400_GPI8_DEB_ENA_WIDTH                    1  /* GPI8_DEB_ENA */
+#define WM8400_GPI8_IRQ_ENA                     0x0040  /* GPI8_IRQ_ENA */
+#define WM8400_GPI8_IRQ_ENA_MASK                0x0040  /* GPI8_IRQ_ENA */
+#define WM8400_GPI8_IRQ_ENA_SHIFT                    6  /* GPI8_IRQ_ENA */
+#define WM8400_GPI8_IRQ_ENA_WIDTH                    1  /* GPI8_IRQ_ENA */
+#define WM8400_GPI8_ENA                         0x0010  /* GPI8_ENA */
+#define WM8400_GPI8_ENA_MASK                    0x0010  /* GPI8_ENA */
+#define WM8400_GPI8_ENA_SHIFT                        4  /* GPI8_ENA */
+#define WM8400_GPI8_ENA_WIDTH                        1  /* GPI8_ENA */
+#define WM8400_GPI7_DEB_ENA                     0x0008  /* GPI7_DEB_ENA */
+#define WM8400_GPI7_DEB_ENA_MASK                0x0008  /* GPI7_DEB_ENA */
+#define WM8400_GPI7_DEB_ENA_SHIFT                    3  /* GPI7_DEB_ENA */
+#define WM8400_GPI7_DEB_ENA_WIDTH                    1  /* GPI7_DEB_ENA */
+#define WM8400_GPI7_IRQ_ENA                     0x0004  /* GPI7_IRQ_ENA */
+#define WM8400_GPI7_IRQ_ENA_MASK                0x0004  /* GPI7_IRQ_ENA */
+#define WM8400_GPI7_IRQ_ENA_SHIFT                    2  /* GPI7_IRQ_ENA */
+#define WM8400_GPI7_IRQ_ENA_WIDTH                    1  /* GPI7_IRQ_ENA */
+#define WM8400_GPI7_ENA                         0x0001  /* GPI7_ENA */
+#define WM8400_GPI7_ENA_MASK                    0x0001  /* GPI7_ENA */
+#define WM8400_GPI7_ENA_SHIFT                        0  /* GPI7_ENA */
+#define WM8400_GPI7_ENA_WIDTH                        1  /* GPI7_ENA */
+
+/*
+ * R23 (0x17) - GPIO_POL
+ */
+#define WM8400_IRQ_INV                          0x1000  /* IRQ_INV */
+#define WM8400_IRQ_INV_MASK                     0x1000  /* IRQ_INV */
+#define WM8400_IRQ_INV_SHIFT                        12  /* IRQ_INV */
+#define WM8400_IRQ_INV_WIDTH                         1  /* IRQ_INV */
+#define WM8400_TEMPOK_POL                       0x0800  /* TEMPOK_POL */
+#define WM8400_TEMPOK_POL_MASK                  0x0800  /* TEMPOK_POL */
+#define WM8400_TEMPOK_POL_SHIFT                     11  /* TEMPOK_POL */
+#define WM8400_TEMPOK_POL_WIDTH                      1  /* TEMPOK_POL */
+#define WM8400_MIC1SHRT_POL                     0x0400  /* MIC1SHRT_POL */
+#define WM8400_MIC1SHRT_POL_MASK                0x0400  /* MIC1SHRT_POL */
+#define WM8400_MIC1SHRT_POL_SHIFT                   10  /* MIC1SHRT_POL */
+#define WM8400_MIC1SHRT_POL_WIDTH                    1  /* MIC1SHRT_POL */
+#define WM8400_MIC1DET_POL                      0x0200  /* MIC1DET_POL */
+#define WM8400_MIC1DET_POL_MASK                 0x0200  /* MIC1DET_POL */
+#define WM8400_MIC1DET_POL_SHIFT                     9  /* MIC1DET_POL */
+#define WM8400_MIC1DET_POL_WIDTH                     1  /* MIC1DET_POL */
+#define WM8400_FLL_LCK_POL                      0x0100  /* FLL_LCK_POL */
+#define WM8400_FLL_LCK_POL_MASK                 0x0100  /* FLL_LCK_POL */
+#define WM8400_FLL_LCK_POL_SHIFT                     8  /* FLL_LCK_POL */
+#define WM8400_FLL_LCK_POL_WIDTH                     1  /* FLL_LCK_POL */
+#define WM8400_GPIO_POL_MASK                    0x00FF  /* GPIO_POL - [7:0] */
+#define WM8400_GPIO_POL_SHIFT                        0  /* GPIO_POL - [7:0] */
+#define WM8400_GPIO_POL_WIDTH                        8  /* GPIO_POL - [7:0] */
+
+/*
+ * R65 (0x41) - LDO 1 Control
+ */
+#define WM8400_LDO1_ENA                         0x8000  /* LDO1_ENA */
+#define WM8400_LDO1_ENA_MASK                    0x8000  /* LDO1_ENA */
+#define WM8400_LDO1_ENA_SHIFT                       15  /* LDO1_ENA */
+#define WM8400_LDO1_ENA_WIDTH                        1  /* LDO1_ENA */
+#define WM8400_LDO1_SWI                         0x4000  /* LDO1_SWI */
+#define WM8400_LDO1_SWI_MASK                    0x4000  /* LDO1_SWI */
+#define WM8400_LDO1_SWI_SHIFT                       14  /* LDO1_SWI */
+#define WM8400_LDO1_SWI_WIDTH                        1  /* LDO1_SWI */
+#define WM8400_LDO1_OPFLT                       0x1000  /* LDO1_OPFLT */
+#define WM8400_LDO1_OPFLT_MASK                  0x1000  /* LDO1_OPFLT */
+#define WM8400_LDO1_OPFLT_SHIFT                     12  /* LDO1_OPFLT */
+#define WM8400_LDO1_OPFLT_WIDTH                      1  /* LDO1_OPFLT */
+#define WM8400_LDO1_ERRACT                      0x0800  /* LDO1_ERRACT */
+#define WM8400_LDO1_ERRACT_MASK                 0x0800  /* LDO1_ERRACT */
+#define WM8400_LDO1_ERRACT_SHIFT                    11  /* LDO1_ERRACT */
+#define WM8400_LDO1_ERRACT_WIDTH                     1  /* LDO1_ERRACT */
+#define WM8400_LDO1_HIB_MODE                    0x0400  /* LDO1_HIB_MODE */
+#define WM8400_LDO1_HIB_MODE_MASK               0x0400  /* LDO1_HIB_MODE */
+#define WM8400_LDO1_HIB_MODE_SHIFT                  10  /* LDO1_HIB_MODE */
+#define WM8400_LDO1_HIB_MODE_WIDTH                   1  /* LDO1_HIB_MODE */
+#define WM8400_LDO1_VIMG_MASK                   0x03E0  /* LDO1_VIMG - [9:5] */
+#define WM8400_LDO1_VIMG_SHIFT                       5  /* LDO1_VIMG - [9:5] */
+#define WM8400_LDO1_VIMG_WIDTH                       5  /* LDO1_VIMG - [9:5] */
+#define WM8400_LDO1_VSEL_MASK                   0x001F  /* LDO1_VSEL - [4:0] */
+#define WM8400_LDO1_VSEL_SHIFT                       0  /* LDO1_VSEL - [4:0] */
+#define WM8400_LDO1_VSEL_WIDTH                       5  /* LDO1_VSEL - [4:0] */
+
+/*
+ * R66 (0x42) - LDO 2 Control
+ */
+#define WM8400_LDO2_ENA                         0x8000  /* LDO2_ENA */
+#define WM8400_LDO2_ENA_MASK                    0x8000  /* LDO2_ENA */
+#define WM8400_LDO2_ENA_SHIFT                       15  /* LDO2_ENA */
+#define WM8400_LDO2_ENA_WIDTH                        1  /* LDO2_ENA */
+#define WM8400_LDO2_SWI                         0x4000  /* LDO2_SWI */
+#define WM8400_LDO2_SWI_MASK                    0x4000  /* LDO2_SWI */
+#define WM8400_LDO2_SWI_SHIFT                       14  /* LDO2_SWI */
+#define WM8400_LDO2_SWI_WIDTH                        1  /* LDO2_SWI */
+#define WM8400_LDO2_OPFLT                       0x1000  /* LDO2_OPFLT */
+#define WM8400_LDO2_OPFLT_MASK                  0x1000  /* LDO2_OPFLT */
+#define WM8400_LDO2_OPFLT_SHIFT                     12  /* LDO2_OPFLT */
+#define WM8400_LDO2_OPFLT_WIDTH                      1  /* LDO2_OPFLT */
+#define WM8400_LDO2_ERRACT                      0x0800  /* LDO2_ERRACT */
+#define WM8400_LDO2_ERRACT_MASK                 0x0800  /* LDO2_ERRACT */
+#define WM8400_LDO2_ERRACT_SHIFT                    11  /* LDO2_ERRACT */
+#define WM8400_LDO2_ERRACT_WIDTH                     1  /* LDO2_ERRACT */
+#define WM8400_LDO2_HIB_MODE                    0x0400  /* LDO2_HIB_MODE */
+#define WM8400_LDO2_HIB_MODE_MASK               0x0400  /* LDO2_HIB_MODE */
+#define WM8400_LDO2_HIB_MODE_SHIFT                  10  /* LDO2_HIB_MODE */
+#define WM8400_LDO2_HIB_MODE_WIDTH                   1  /* LDO2_HIB_MODE */
+#define WM8400_LDO2_VIMG_MASK                   0x03E0  /* LDO2_VIMG - [9:5] */
+#define WM8400_LDO2_VIMG_SHIFT                       5  /* LDO2_VIMG - [9:5] */
+#define WM8400_LDO2_VIMG_WIDTH                       5  /* LDO2_VIMG - [9:5] */
+#define WM8400_LDO2_VSEL_MASK                   0x001F  /* LDO2_VSEL - [4:0] */
+#define WM8400_LDO2_VSEL_SHIFT                       0  /* LDO2_VSEL - [4:0] */
+#define WM8400_LDO2_VSEL_WIDTH                       5  /* LDO2_VSEL - [4:0] */
+
+/*
+ * R67 (0x43) - LDO 3 Control
+ */
+#define WM8400_LDO3_ENA                         0x8000  /* LDO3_ENA */
+#define WM8400_LDO3_ENA_MASK                    0x8000  /* LDO3_ENA */
+#define WM8400_LDO3_ENA_SHIFT                       15  /* LDO3_ENA */
+#define WM8400_LDO3_ENA_WIDTH                        1  /* LDO3_ENA */
+#define WM8400_LDO3_SWI                         0x4000  /* LDO3_SWI */
+#define WM8400_LDO3_SWI_MASK                    0x4000  /* LDO3_SWI */
+#define WM8400_LDO3_SWI_SHIFT                       14  /* LDO3_SWI */
+#define WM8400_LDO3_SWI_WIDTH                        1  /* LDO3_SWI */
+#define WM8400_LDO3_OPFLT                       0x1000  /* LDO3_OPFLT */
+#define WM8400_LDO3_OPFLT_MASK                  0x1000  /* LDO3_OPFLT */
+#define WM8400_LDO3_OPFLT_SHIFT                     12  /* LDO3_OPFLT */
+#define WM8400_LDO3_OPFLT_WIDTH                      1  /* LDO3_OPFLT */
+#define WM8400_LDO3_ERRACT                      0x0800  /* LDO3_ERRACT */
+#define WM8400_LDO3_ERRACT_MASK                 0x0800  /* LDO3_ERRACT */
+#define WM8400_LDO3_ERRACT_SHIFT                    11  /* LDO3_ERRACT */
+#define WM8400_LDO3_ERRACT_WIDTH                     1  /* LDO3_ERRACT */
+#define WM8400_LDO3_HIB_MODE                    0x0400  /* LDO3_HIB_MODE */
+#define WM8400_LDO3_HIB_MODE_MASK               0x0400  /* LDO3_HIB_MODE */
+#define WM8400_LDO3_HIB_MODE_SHIFT                  10  /* LDO3_HIB_MODE */
+#define WM8400_LDO3_HIB_MODE_WIDTH                   1  /* LDO3_HIB_MODE */
+#define WM8400_LDO3_VIMG_MASK                   0x03E0  /* LDO3_VIMG - [9:5] */
+#define WM8400_LDO3_VIMG_SHIFT                       5  /* LDO3_VIMG - [9:5] */
+#define WM8400_LDO3_VIMG_WIDTH                       5  /* LDO3_VIMG - [9:5] */
+#define WM8400_LDO3_VSEL_MASK                   0x001F  /* LDO3_VSEL - [4:0] */
+#define WM8400_LDO3_VSEL_SHIFT                       0  /* LDO3_VSEL - [4:0] */
+#define WM8400_LDO3_VSEL_WIDTH                       5  /* LDO3_VSEL - [4:0] */
+
+/*
+ * R68 (0x44) - LDO 4 Control
+ */
+#define WM8400_LDO4_ENA                         0x8000  /* LDO4_ENA */
+#define WM8400_LDO4_ENA_MASK                    0x8000  /* LDO4_ENA */
+#define WM8400_LDO4_ENA_SHIFT                       15  /* LDO4_ENA */
+#define WM8400_LDO4_ENA_WIDTH                        1  /* LDO4_ENA */
+#define WM8400_LDO4_SWI                         0x4000  /* LDO4_SWI */
+#define WM8400_LDO4_SWI_MASK                    0x4000  /* LDO4_SWI */
+#define WM8400_LDO4_SWI_SHIFT                       14  /* LDO4_SWI */
+#define WM8400_LDO4_SWI_WIDTH                        1  /* LDO4_SWI */
+#define WM8400_LDO4_OPFLT                       0x1000  /* LDO4_OPFLT */
+#define WM8400_LDO4_OPFLT_MASK                  0x1000  /* LDO4_OPFLT */
+#define WM8400_LDO4_OPFLT_SHIFT                     12  /* LDO4_OPFLT */
+#define WM8400_LDO4_OPFLT_WIDTH                      1  /* LDO4_OPFLT */
+#define WM8400_LDO4_ERRACT                      0x0800  /* LDO4_ERRACT */
+#define WM8400_LDO4_ERRACT_MASK                 0x0800  /* LDO4_ERRACT */
+#define WM8400_LDO4_ERRACT_SHIFT                    11  /* LDO4_ERRACT */
+#define WM8400_LDO4_ERRACT_WIDTH                     1  /* LDO4_ERRACT */
+#define WM8400_LDO4_HIB_MODE                    0x0400  /* LDO4_HIB_MODE */
+#define WM8400_LDO4_HIB_MODE_MASK               0x0400  /* LDO4_HIB_MODE */
+#define WM8400_LDO4_HIB_MODE_SHIFT                  10  /* LDO4_HIB_MODE */
+#define WM8400_LDO4_HIB_MODE_WIDTH                   1  /* LDO4_HIB_MODE */
+#define WM8400_LDO4_VIMG_MASK                   0x03E0  /* LDO4_VIMG - [9:5] */
+#define WM8400_LDO4_VIMG_SHIFT                       5  /* LDO4_VIMG - [9:5] */
+#define WM8400_LDO4_VIMG_WIDTH                       5  /* LDO4_VIMG - [9:5] */
+#define WM8400_LDO4_VSEL_MASK                   0x001F  /* LDO4_VSEL - [4:0] */
+#define WM8400_LDO4_VSEL_SHIFT                       0  /* LDO4_VSEL - [4:0] */
+#define WM8400_LDO4_VSEL_WIDTH                       5  /* LDO4_VSEL - [4:0] */
+
+/*
+ * R70 (0x46) - DCDC1 Control 1
+ */
+#define WM8400_DC1_ENA                          0x8000  /* DC1_ENA */
+#define WM8400_DC1_ENA_MASK                     0x8000  /* DC1_ENA */
+#define WM8400_DC1_ENA_SHIFT                        15  /* DC1_ENA */
+#define WM8400_DC1_ENA_WIDTH                         1  /* DC1_ENA */
+#define WM8400_DC1_ACTIVE                       0x4000  /* DC1_ACTIVE */
+#define WM8400_DC1_ACTIVE_MASK                  0x4000  /* DC1_ACTIVE */
+#define WM8400_DC1_ACTIVE_SHIFT                     14  /* DC1_ACTIVE */
+#define WM8400_DC1_ACTIVE_WIDTH                      1  /* DC1_ACTIVE */
+#define WM8400_DC1_SLEEP                        0x2000  /* DC1_SLEEP */
+#define WM8400_DC1_SLEEP_MASK                   0x2000  /* DC1_SLEEP */
+#define WM8400_DC1_SLEEP_SHIFT                      13  /* DC1_SLEEP */
+#define WM8400_DC1_SLEEP_WIDTH                       1  /* DC1_SLEEP */
+#define WM8400_DC1_OPFLT                        0x1000  /* DC1_OPFLT */
+#define WM8400_DC1_OPFLT_MASK                   0x1000  /* DC1_OPFLT */
+#define WM8400_DC1_OPFLT_SHIFT                      12  /* DC1_OPFLT */
+#define WM8400_DC1_OPFLT_WIDTH                       1  /* DC1_OPFLT */
+#define WM8400_DC1_ERRACT                       0x0800  /* DC1_ERRACT */
+#define WM8400_DC1_ERRACT_MASK                  0x0800  /* DC1_ERRACT */
+#define WM8400_DC1_ERRACT_SHIFT                     11  /* DC1_ERRACT */
+#define WM8400_DC1_ERRACT_WIDTH                      1  /* DC1_ERRACT */
+#define WM8400_DC1_HIB_MODE                     0x0400  /* DC1_HIB_MODE */
+#define WM8400_DC1_HIB_MODE_MASK                0x0400  /* DC1_HIB_MODE */
+#define WM8400_DC1_HIB_MODE_SHIFT                   10  /* DC1_HIB_MODE */
+#define WM8400_DC1_HIB_MODE_WIDTH                    1  /* DC1_HIB_MODE */
+#define WM8400_DC1_SOFTST_MASK                  0x0300  /* DC1_SOFTST - [9:8] */
+#define WM8400_DC1_SOFTST_SHIFT                      8  /* DC1_SOFTST - [9:8] */
+#define WM8400_DC1_SOFTST_WIDTH                      2  /* DC1_SOFTST - [9:8] */
+#define WM8400_DC1_OV_PROT                      0x0080  /* DC1_OV_PROT */
+#define WM8400_DC1_OV_PROT_MASK                 0x0080  /* DC1_OV_PROT */
+#define WM8400_DC1_OV_PROT_SHIFT                     7  /* DC1_OV_PROT */
+#define WM8400_DC1_OV_PROT_WIDTH                     1  /* DC1_OV_PROT */
+#define WM8400_DC1_VSEL_MASK                    0x007F  /* DC1_VSEL - [6:0] */
+#define WM8400_DC1_VSEL_SHIFT                        0  /* DC1_VSEL - [6:0] */
+#define WM8400_DC1_VSEL_WIDTH                        7  /* DC1_VSEL - [6:0] */
+
+/*
+ * R71 (0x47) - DCDC1 Control 2
+ */
+#define WM8400_DC1_FRC_PWM                      0x2000  /* DC1_FRC_PWM */
+#define WM8400_DC1_FRC_PWM_MASK                 0x2000  /* DC1_FRC_PWM */
+#define WM8400_DC1_FRC_PWM_SHIFT                    13  /* DC1_FRC_PWM */
+#define WM8400_DC1_FRC_PWM_WIDTH                     1  /* DC1_FRC_PWM */
+#define WM8400_DC1_STBY_LIM_MASK                0x0300  /* DC1_STBY_LIM - [9:8] */
+#define WM8400_DC1_STBY_LIM_SHIFT                    8  /* DC1_STBY_LIM - [9:8] */
+#define WM8400_DC1_STBY_LIM_WIDTH                    2  /* DC1_STBY_LIM - [9:8] */
+#define WM8400_DC1_ACT_LIM                      0x0080  /* DC1_ACT_LIM */
+#define WM8400_DC1_ACT_LIM_MASK                 0x0080  /* DC1_ACT_LIM */
+#define WM8400_DC1_ACT_LIM_SHIFT                     7  /* DC1_ACT_LIM */
+#define WM8400_DC1_ACT_LIM_WIDTH                     1  /* DC1_ACT_LIM */
+#define WM8400_DC1_VIMG_MASK                    0x007F  /* DC1_VIMG - [6:0] */
+#define WM8400_DC1_VIMG_SHIFT                        0  /* DC1_VIMG - [6:0] */
+#define WM8400_DC1_VIMG_WIDTH                        7  /* DC1_VIMG - [6:0] */
+
+/*
+ * R72 (0x48) - DCDC2 Control 1
+ */
+#define WM8400_DC2_ENA                          0x8000  /* DC2_ENA */
+#define WM8400_DC2_ENA_MASK                     0x8000  /* DC2_ENA */
+#define WM8400_DC2_ENA_SHIFT                        15  /* DC2_ENA */
+#define WM8400_DC2_ENA_WIDTH                         1  /* DC2_ENA */
+#define WM8400_DC2_ACTIVE                       0x4000  /* DC2_ACTIVE */
+#define WM8400_DC2_ACTIVE_MASK                  0x4000  /* DC2_ACTIVE */
+#define WM8400_DC2_ACTIVE_SHIFT                     14  /* DC2_ACTIVE */
+#define WM8400_DC2_ACTIVE_WIDTH                      1  /* DC2_ACTIVE */
+#define WM8400_DC2_SLEEP                        0x2000  /* DC2_SLEEP */
+#define WM8400_DC2_SLEEP_MASK                   0x2000  /* DC2_SLEEP */
+#define WM8400_DC2_SLEEP_SHIFT                      13  /* DC2_SLEEP */
+#define WM8400_DC2_SLEEP_WIDTH                       1  /* DC2_SLEEP */
+#define WM8400_DC2_OPFLT                        0x1000  /* DC2_OPFLT */
+#define WM8400_DC2_OPFLT_MASK                   0x1000  /* DC2_OPFLT */
+#define WM8400_DC2_OPFLT_SHIFT                      12  /* DC2_OPFLT */
+#define WM8400_DC2_OPFLT_WIDTH                       1  /* DC2_OPFLT */
+#define WM8400_DC2_ERRACT                       0x0800  /* DC2_ERRACT */
+#define WM8400_DC2_ERRACT_MASK                  0x0800  /* DC2_ERRACT */
+#define WM8400_DC2_ERRACT_SHIFT                     11  /* DC2_ERRACT */
+#define WM8400_DC2_ERRACT_WIDTH                      1  /* DC2_ERRACT */
+#define WM8400_DC2_HIB_MODE                     0x0400  /* DC2_HIB_MODE */
+#define WM8400_DC2_HIB_MODE_MASK                0x0400  /* DC2_HIB_MODE */
+#define WM8400_DC2_HIB_MODE_SHIFT                   10  /* DC2_HIB_MODE */
+#define WM8400_DC2_HIB_MODE_WIDTH                    1  /* DC2_HIB_MODE */
+#define WM8400_DC2_SOFTST_MASK                  0x0300  /* DC2_SOFTST - [9:8] */
+#define WM8400_DC2_SOFTST_SHIFT                      8  /* DC2_SOFTST - [9:8] */
+#define WM8400_DC2_SOFTST_WIDTH                      2  /* DC2_SOFTST - [9:8] */
+#define WM8400_DC2_OV_PROT                      0x0080  /* DC2_OV_PROT */
+#define WM8400_DC2_OV_PROT_MASK                 0x0080  /* DC2_OV_PROT */
+#define WM8400_DC2_OV_PROT_SHIFT                     7  /* DC2_OV_PROT */
+#define WM8400_DC2_OV_PROT_WIDTH                     1  /* DC2_OV_PROT */
+#define WM8400_DC2_VSEL_MASK                    0x007F  /* DC2_VSEL - [6:0] */
+#define WM8400_DC2_VSEL_SHIFT                        0  /* DC2_VSEL - [6:0] */
+#define WM8400_DC2_VSEL_WIDTH                        7  /* DC2_VSEL - [6:0] */
+
+/*
+ * R73 (0x49) - DCDC2 Control 2
+ */
+#define WM8400_DC2_FRC_PWM                      0x2000  /* DC2_FRC_PWM */
+#define WM8400_DC2_FRC_PWM_MASK                 0x2000  /* DC2_FRC_PWM */
+#define WM8400_DC2_FRC_PWM_SHIFT                    13  /* DC2_FRC_PWM */
+#define WM8400_DC2_FRC_PWM_WIDTH                     1  /* DC2_FRC_PWM */
+#define WM8400_DC2_STBY_LIM_MASK                0x0300  /* DC2_STBY_LIM - [9:8] */
+#define WM8400_DC2_STBY_LIM_SHIFT                    8  /* DC2_STBY_LIM - [9:8] */
+#define WM8400_DC2_STBY_LIM_WIDTH                    2  /* DC2_STBY_LIM - [9:8] */
+#define WM8400_DC2_ACT_LIM                      0x0080  /* DC2_ACT_LIM */
+#define WM8400_DC2_ACT_LIM_MASK                 0x0080  /* DC2_ACT_LIM */
+#define WM8400_DC2_ACT_LIM_SHIFT                     7  /* DC2_ACT_LIM */
+#define WM8400_DC2_ACT_LIM_WIDTH                     1  /* DC2_ACT_LIM */
+#define WM8400_DC2_VIMG_MASK                    0x007F  /* DC2_VIMG - [6:0] */
+#define WM8400_DC2_VIMG_SHIFT                        0  /* DC2_VIMG - [6:0] */
+#define WM8400_DC2_VIMG_WIDTH                        7  /* DC2_VIMG - [6:0] */
+
+/*
+ * R75 (0x4B) - Interface
+ */
+#define WM8400_AUTOINC                          0x0008  /* AUTOINC */
+#define WM8400_AUTOINC_MASK                     0x0008  /* AUTOINC */
+#define WM8400_AUTOINC_SHIFT                         3  /* AUTOINC */
+#define WM8400_AUTOINC_WIDTH                         1  /* AUTOINC */
+#define WM8400_ARA_ENA                          0x0004  /* ARA_ENA */
+#define WM8400_ARA_ENA_MASK                     0x0004  /* ARA_ENA */
+#define WM8400_ARA_ENA_SHIFT                         2  /* ARA_ENA */
+#define WM8400_ARA_ENA_WIDTH                         1  /* ARA_ENA */
+#define WM8400_SPI_CFG                          0x0002  /* SPI_CFG */
+#define WM8400_SPI_CFG_MASK                     0x0002  /* SPI_CFG */
+#define WM8400_SPI_CFG_SHIFT                         1  /* SPI_CFG */
+#define WM8400_SPI_CFG_WIDTH                         1  /* SPI_CFG */
+
+/*
+ * R76 (0x4C) - PM GENERAL
+ */
+#define WM8400_CODEC_SOFTST                     0x8000  /* CODEC_SOFTST */
+#define WM8400_CODEC_SOFTST_MASK                0x8000  /* CODEC_SOFTST */
+#define WM8400_CODEC_SOFTST_SHIFT                   15  /* CODEC_SOFTST */
+#define WM8400_CODEC_SOFTST_WIDTH                    1  /* CODEC_SOFTST */
+#define WM8400_CODEC_SOFTSD                     0x4000  /* CODEC_SOFTSD */
+#define WM8400_CODEC_SOFTSD_MASK                0x4000  /* CODEC_SOFTSD */
+#define WM8400_CODEC_SOFTSD_SHIFT                   14  /* CODEC_SOFTSD */
+#define WM8400_CODEC_SOFTSD_WIDTH                    1  /* CODEC_SOFTSD */
+#define WM8400_CHIP_SOFTSD                      0x2000  /* CHIP_SOFTSD */
+#define WM8400_CHIP_SOFTSD_MASK                 0x2000  /* CHIP_SOFTSD */
+#define WM8400_CHIP_SOFTSD_SHIFT                    13  /* CHIP_SOFTSD */
+#define WM8400_CHIP_SOFTSD_WIDTH                     1  /* CHIP_SOFTSD */
+#define WM8400_DSLEEP1_POL                      0x0008  /* DSLEEP1_POL */
+#define WM8400_DSLEEP1_POL_MASK                 0x0008  /* DSLEEP1_POL */
+#define WM8400_DSLEEP1_POL_SHIFT                     3  /* DSLEEP1_POL */
+#define WM8400_DSLEEP1_POL_WIDTH                     1  /* DSLEEP1_POL */
+#define WM8400_DSLEEP2_POL                      0x0004  /* DSLEEP2_POL */
+#define WM8400_DSLEEP2_POL_MASK                 0x0004  /* DSLEEP2_POL */
+#define WM8400_DSLEEP2_POL_SHIFT                     2  /* DSLEEP2_POL */
+#define WM8400_DSLEEP2_POL_WIDTH                     1  /* DSLEEP2_POL */
+#define WM8400_PWR_STATE_MASK                   0x0003  /* PWR_STATE - [1:0] */
+#define WM8400_PWR_STATE_SHIFT                       0  /* PWR_STATE - [1:0] */
+#define WM8400_PWR_STATE_WIDTH                       2  /* PWR_STATE - [1:0] */
+
+/*
+ * R78 (0x4E) - PM Shutdown Control
+ */
+#define WM8400_CHIP_GT150_ERRACT                0x0200  /* CHIP_GT150_ERRACT */
+#define WM8400_CHIP_GT150_ERRACT_MASK           0x0200  /* CHIP_GT150_ERRACT */
+#define WM8400_CHIP_GT150_ERRACT_SHIFT               9  /* CHIP_GT150_ERRACT */
+#define WM8400_CHIP_GT150_ERRACT_WIDTH               1  /* CHIP_GT150_ERRACT */
+#define WM8400_CHIP_GT115_ERRACT                0x0100  /* CHIP_GT115_ERRACT */
+#define WM8400_CHIP_GT115_ERRACT_MASK           0x0100  /* CHIP_GT115_ERRACT */
+#define WM8400_CHIP_GT115_ERRACT_SHIFT               8  /* CHIP_GT115_ERRACT */
+#define WM8400_CHIP_GT115_ERRACT_WIDTH               1  /* CHIP_GT115_ERRACT */
+#define WM8400_LINE_CMP_ERRACT                  0x0080  /* LINE_CMP_ERRACT */
+#define WM8400_LINE_CMP_ERRACT_MASK             0x0080  /* LINE_CMP_ERRACT */
+#define WM8400_LINE_CMP_ERRACT_SHIFT                 7  /* LINE_CMP_ERRACT */
+#define WM8400_LINE_CMP_ERRACT_WIDTH                 1  /* LINE_CMP_ERRACT */
+#define WM8400_UVLO_ERRACT                      0x0040  /* UVLO_ERRACT */
+#define WM8400_UVLO_ERRACT_MASK                 0x0040  /* UVLO_ERRACT */
+#define WM8400_UVLO_ERRACT_SHIFT                     6  /* UVLO_ERRACT */
+#define WM8400_UVLO_ERRACT_WIDTH                     1  /* UVLO_ERRACT */
+
+/*
+ * R79 (0x4F) - Interrupt Status 1
+ */
+#define WM8400_MICD_CINT                        0x8000  /* MICD_CINT */
+#define WM8400_MICD_CINT_MASK                   0x8000  /* MICD_CINT */
+#define WM8400_MICD_CINT_SHIFT                      15  /* MICD_CINT */
+#define WM8400_MICD_CINT_WIDTH                       1  /* MICD_CINT */
+#define WM8400_MICSCD_CINT                      0x4000  /* MICSCD_CINT */
+#define WM8400_MICSCD_CINT_MASK                 0x4000  /* MICSCD_CINT */
+#define WM8400_MICSCD_CINT_SHIFT                    14  /* MICSCD_CINT */
+#define WM8400_MICSCD_CINT_WIDTH                     1  /* MICSCD_CINT */
+#define WM8400_JDL_CINT                         0x2000  /* JDL_CINT */
+#define WM8400_JDL_CINT_MASK                    0x2000  /* JDL_CINT */
+#define WM8400_JDL_CINT_SHIFT                       13  /* JDL_CINT */
+#define WM8400_JDL_CINT_WIDTH                        1  /* JDL_CINT */
+#define WM8400_JDR_CINT                         0x1000  /* JDR_CINT */
+#define WM8400_JDR_CINT_MASK                    0x1000  /* JDR_CINT */
+#define WM8400_JDR_CINT_SHIFT                       12  /* JDR_CINT */
+#define WM8400_JDR_CINT_WIDTH                        1  /* JDR_CINT */
+#define WM8400_CODEC_SEQ_END_EINT               0x0800  /* CODEC_SEQ_END_EINT */
+#define WM8400_CODEC_SEQ_END_EINT_MASK          0x0800  /* CODEC_SEQ_END_EINT */
+#define WM8400_CODEC_SEQ_END_EINT_SHIFT             11  /* CODEC_SEQ_END_EINT */
+#define WM8400_CODEC_SEQ_END_EINT_WIDTH              1  /* CODEC_SEQ_END_EINT */
+#define WM8400_CDEL_TO_EINT                     0x0400  /* CDEL_TO_EINT */
+#define WM8400_CDEL_TO_EINT_MASK                0x0400  /* CDEL_TO_EINT */
+#define WM8400_CDEL_TO_EINT_SHIFT                   10  /* CDEL_TO_EINT */
+#define WM8400_CDEL_TO_EINT_WIDTH                    1  /* CDEL_TO_EINT */
+#define WM8400_CHIP_GT150_EINT                  0x0200  /* CHIP_GT150_EINT */
+#define WM8400_CHIP_GT150_EINT_MASK             0x0200  /* CHIP_GT150_EINT */
+#define WM8400_CHIP_GT150_EINT_SHIFT                 9  /* CHIP_GT150_EINT */
+#define WM8400_CHIP_GT150_EINT_WIDTH                 1  /* CHIP_GT150_EINT */
+#define WM8400_CHIP_GT115_EINT                  0x0100  /* CHIP_GT115_EINT */
+#define WM8400_CHIP_GT115_EINT_MASK             0x0100  /* CHIP_GT115_EINT */
+#define WM8400_CHIP_GT115_EINT_SHIFT                 8  /* CHIP_GT115_EINT */
+#define WM8400_CHIP_GT115_EINT_WIDTH                 1  /* CHIP_GT115_EINT */
+#define WM8400_LINE_CMP_EINT                    0x0080  /* LINE_CMP_EINT */
+#define WM8400_LINE_CMP_EINT_MASK               0x0080  /* LINE_CMP_EINT */
+#define WM8400_LINE_CMP_EINT_SHIFT                   7  /* LINE_CMP_EINT */
+#define WM8400_LINE_CMP_EINT_WIDTH                   1  /* LINE_CMP_EINT */
+#define WM8400_UVLO_EINT                        0x0040  /* UVLO_EINT */
+#define WM8400_UVLO_EINT_MASK                   0x0040  /* UVLO_EINT */
+#define WM8400_UVLO_EINT_SHIFT                       6  /* UVLO_EINT */
+#define WM8400_UVLO_EINT_WIDTH                       1  /* UVLO_EINT */
+#define WM8400_DC2_UV_EINT                      0x0020  /* DC2_UV_EINT */
+#define WM8400_DC2_UV_EINT_MASK                 0x0020  /* DC2_UV_EINT */
+#define WM8400_DC2_UV_EINT_SHIFT                     5  /* DC2_UV_EINT */
+#define WM8400_DC2_UV_EINT_WIDTH                     1  /* DC2_UV_EINT */
+#define WM8400_DC1_UV_EINT                      0x0010  /* DC1_UV_EINT */
+#define WM8400_DC1_UV_EINT_MASK                 0x0010  /* DC1_UV_EINT */
+#define WM8400_DC1_UV_EINT_SHIFT                     4  /* DC1_UV_EINT */
+#define WM8400_DC1_UV_EINT_WIDTH                     1  /* DC1_UV_EINT */
+#define WM8400_LDO4_UV_EINT                     0x0008  /* LDO4_UV_EINT */
+#define WM8400_LDO4_UV_EINT_MASK                0x0008  /* LDO4_UV_EINT */
+#define WM8400_LDO4_UV_EINT_SHIFT                    3  /* LDO4_UV_EINT */
+#define WM8400_LDO4_UV_EINT_WIDTH                    1  /* LDO4_UV_EINT */
+#define WM8400_LDO3_UV_EINT                     0x0004  /* LDO3_UV_EINT */
+#define WM8400_LDO3_UV_EINT_MASK                0x0004  /* LDO3_UV_EINT */
+#define WM8400_LDO3_UV_EINT_SHIFT                    2  /* LDO3_UV_EINT */
+#define WM8400_LDO3_UV_EINT_WIDTH                    1  /* LDO3_UV_EINT */
+#define WM8400_LDO2_UV_EINT                     0x0002  /* LDO2_UV_EINT */
+#define WM8400_LDO2_UV_EINT_MASK                0x0002  /* LDO2_UV_EINT */
+#define WM8400_LDO2_UV_EINT_SHIFT                    1  /* LDO2_UV_EINT */
+#define WM8400_LDO2_UV_EINT_WIDTH                    1  /* LDO2_UV_EINT */
+#define WM8400_LDO1_UV_EINT                     0x0001  /* LDO1_UV_EINT */
+#define WM8400_LDO1_UV_EINT_MASK                0x0001  /* LDO1_UV_EINT */
+#define WM8400_LDO1_UV_EINT_SHIFT                    0  /* LDO1_UV_EINT */
+#define WM8400_LDO1_UV_EINT_WIDTH                    1  /* LDO1_UV_EINT */
+
+/*
+ * R80 (0x50) - Interrupt Status 1 Mask
+ */
+#define WM8400_IM_MICD_CINT                     0x8000  /* IM_MICD_CINT */
+#define WM8400_IM_MICD_CINT_MASK                0x8000  /* IM_MICD_CINT */
+#define WM8400_IM_MICD_CINT_SHIFT                   15  /* IM_MICD_CINT */
+#define WM8400_IM_MICD_CINT_WIDTH                    1  /* IM_MICD_CINT */
+#define WM8400_IM_MICSCD_CINT                   0x4000  /* IM_MICSCD_CINT */
+#define WM8400_IM_MICSCD_CINT_MASK              0x4000  /* IM_MICSCD_CINT */
+#define WM8400_IM_MICSCD_CINT_SHIFT                 14  /* IM_MICSCD_CINT */
+#define WM8400_IM_MICSCD_CINT_WIDTH                  1  /* IM_MICSCD_CINT */
+#define WM8400_IM_JDL_CINT                      0x2000  /* IM_JDL_CINT */
+#define WM8400_IM_JDL_CINT_MASK                 0x2000  /* IM_JDL_CINT */
+#define WM8400_IM_JDL_CINT_SHIFT                    13  /* IM_JDL_CINT */
+#define WM8400_IM_JDL_CINT_WIDTH                     1  /* IM_JDL_CINT */
+#define WM8400_IM_JDR_CINT                      0x1000  /* IM_JDR_CINT */
+#define WM8400_IM_JDR_CINT_MASK                 0x1000  /* IM_JDR_CINT */
+#define WM8400_IM_JDR_CINT_SHIFT                    12  /* IM_JDR_CINT */
+#define WM8400_IM_JDR_CINT_WIDTH                     1  /* IM_JDR_CINT */
+#define WM8400_IM_CODEC_SEQ_END_EINT            0x0800  /* IM_CODEC_SEQ_END_EINT */
+#define WM8400_IM_CODEC_SEQ_END_EINT_MASK       0x0800  /* IM_CODEC_SEQ_END_EINT */
+#define WM8400_IM_CODEC_SEQ_END_EINT_SHIFT          11  /* IM_CODEC_SEQ_END_EINT */
+#define WM8400_IM_CODEC_SEQ_END_EINT_WIDTH           1  /* IM_CODEC_SEQ_END_EINT */
+#define WM8400_IM_CDEL_TO_EINT                  0x0400  /* IM_CDEL_TO_EINT */
+#define WM8400_IM_CDEL_TO_EINT_MASK             0x0400  /* IM_CDEL_TO_EINT */
+#define WM8400_IM_CDEL_TO_EINT_SHIFT                10  /* IM_CDEL_TO_EINT */
+#define WM8400_IM_CDEL_TO_EINT_WIDTH                 1  /* IM_CDEL_TO_EINT */
+#define WM8400_IM_CHIP_GT150_EINT               0x0200  /* IM_CHIP_GT150_EINT */
+#define WM8400_IM_CHIP_GT150_EINT_MASK          0x0200  /* IM_CHIP_GT150_EINT */
+#define WM8400_IM_CHIP_GT150_EINT_SHIFT              9  /* IM_CHIP_GT150_EINT */
+#define WM8400_IM_CHIP_GT150_EINT_WIDTH              1  /* IM_CHIP_GT150_EINT */
+#define WM8400_IM_CHIP_GT115_EINT               0x0100  /* IM_CHIP_GT115_EINT */
+#define WM8400_IM_CHIP_GT115_EINT_MASK          0x0100  /* IM_CHIP_GT115_EINT */
+#define WM8400_IM_CHIP_GT115_EINT_SHIFT              8  /* IM_CHIP_GT115_EINT */
+#define WM8400_IM_CHIP_GT115_EINT_WIDTH              1  /* IM_CHIP_GT115_EINT */
+#define WM8400_IM_LINE_CMP_EINT                 0x0080  /* IM_LINE_CMP_EINT */
+#define WM8400_IM_LINE_CMP_EINT_MASK            0x0080  /* IM_LINE_CMP_EINT */
+#define WM8400_IM_LINE_CMP_EINT_SHIFT                7  /* IM_LINE_CMP_EINT */
+#define WM8400_IM_LINE_CMP_EINT_WIDTH                1  /* IM_LINE_CMP_EINT */
+#define WM8400_IM_UVLO_EINT                     0x0040  /* IM_UVLO_EINT */
+#define WM8400_IM_UVLO_EINT_MASK                0x0040  /* IM_UVLO_EINT */
+#define WM8400_IM_UVLO_EINT_SHIFT                    6  /* IM_UVLO_EINT */
+#define WM8400_IM_UVLO_EINT_WIDTH                    1  /* IM_UVLO_EINT */
+#define WM8400_IM_DC2_UV_EINT                   0x0020  /* IM_DC2_UV_EINT */
+#define WM8400_IM_DC2_UV_EINT_MASK              0x0020  /* IM_DC2_UV_EINT */
+#define WM8400_IM_DC2_UV_EINT_SHIFT                  5  /* IM_DC2_UV_EINT */
+#define WM8400_IM_DC2_UV_EINT_WIDTH                  1  /* IM_DC2_UV_EINT */
+#define WM8400_IM_DC1_UV_EINT                   0x0010  /* IM_DC1_UV_EINT */
+#define WM8400_IM_DC1_UV_EINT_MASK              0x0010  /* IM_DC1_UV_EINT */
+#define WM8400_IM_DC1_UV_EINT_SHIFT                  4  /* IM_DC1_UV_EINT */
+#define WM8400_IM_DC1_UV_EINT_WIDTH                  1  /* IM_DC1_UV_EINT */
+#define WM8400_IM_LDO4_UV_EINT                  0x0008  /* IM_LDO4_UV_EINT */
+#define WM8400_IM_LDO4_UV_EINT_MASK             0x0008  /* IM_LDO4_UV_EINT */
+#define WM8400_IM_LDO4_UV_EINT_SHIFT                 3  /* IM_LDO4_UV_EINT */
+#define WM8400_IM_LDO4_UV_EINT_WIDTH                 1  /* IM_LDO4_UV_EINT */
+#define WM8400_IM_LDO3_UV_EINT                  0x0004  /* IM_LDO3_UV_EINT */
+#define WM8400_IM_LDO3_UV_EINT_MASK             0x0004  /* IM_LDO3_UV_EINT */
+#define WM8400_IM_LDO3_UV_EINT_SHIFT                 2  /* IM_LDO3_UV_EINT */
+#define WM8400_IM_LDO3_UV_EINT_WIDTH                 1  /* IM_LDO3_UV_EINT */
+#define WM8400_IM_LDO2_UV_EINT                  0x0002  /* IM_LDO2_UV_EINT */
+#define WM8400_IM_LDO2_UV_EINT_MASK             0x0002  /* IM_LDO2_UV_EINT */
+#define WM8400_IM_LDO2_UV_EINT_SHIFT                 1  /* IM_LDO2_UV_EINT */
+#define WM8400_IM_LDO2_UV_EINT_WIDTH                 1  /* IM_LDO2_UV_EINT */
+#define WM8400_IM_LDO1_UV_EINT                  0x0001  /* IM_LDO1_UV_EINT */
+#define WM8400_IM_LDO1_UV_EINT_MASK             0x0001  /* IM_LDO1_UV_EINT */
+#define WM8400_IM_LDO1_UV_EINT_SHIFT                 0  /* IM_LDO1_UV_EINT */
+#define WM8400_IM_LDO1_UV_EINT_WIDTH                 1  /* IM_LDO1_UV_EINT */
+
+/*
+ * R81 (0x51) - Interrupt Levels
+ */
+#define WM8400_MICD_LVL                         0x8000  /* MICD_LVL */
+#define WM8400_MICD_LVL_MASK                    0x8000  /* MICD_LVL */
+#define WM8400_MICD_LVL_SHIFT                       15  /* MICD_LVL */
+#define WM8400_MICD_LVL_WIDTH                        1  /* MICD_LVL */
+#define WM8400_MICSCD_LVL                       0x4000  /* MICSCD_LVL */
+#define WM8400_MICSCD_LVL_MASK                  0x4000  /* MICSCD_LVL */
+#define WM8400_MICSCD_LVL_SHIFT                     14  /* MICSCD_LVL */
+#define WM8400_MICSCD_LVL_WIDTH                      1  /* MICSCD_LVL */
+#define WM8400_JDL_LVL                          0x2000  /* JDL_LVL */
+#define WM8400_JDL_LVL_MASK                     0x2000  /* JDL_LVL */
+#define WM8400_JDL_LVL_SHIFT                        13  /* JDL_LVL */
+#define WM8400_JDL_LVL_WIDTH                         1  /* JDL_LVL */
+#define WM8400_JDR_LVL                          0x1000  /* JDR_LVL */
+#define WM8400_JDR_LVL_MASK                     0x1000  /* JDR_LVL */
+#define WM8400_JDR_LVL_SHIFT                        12  /* JDR_LVL */
+#define WM8400_JDR_LVL_WIDTH                         1  /* JDR_LVL */
+#define WM8400_CODEC_SEQ_END_LVL                0x0800  /* CODEC_SEQ_END_LVL */
+#define WM8400_CODEC_SEQ_END_LVL_MASK           0x0800  /* CODEC_SEQ_END_LVL */
+#define WM8400_CODEC_SEQ_END_LVL_SHIFT              11  /* CODEC_SEQ_END_LVL */
+#define WM8400_CODEC_SEQ_END_LVL_WIDTH               1  /* CODEC_SEQ_END_LVL */
+#define WM8400_CDEL_TO_LVL                      0x0400  /* CDEL_TO_LVL */
+#define WM8400_CDEL_TO_LVL_MASK                 0x0400  /* CDEL_TO_LVL */
+#define WM8400_CDEL_TO_LVL_SHIFT                    10  /* CDEL_TO_LVL */
+#define WM8400_CDEL_TO_LVL_WIDTH                     1  /* CDEL_TO_LVL */
+#define WM8400_CHIP_GT150_LVL                   0x0200  /* CHIP_GT150_LVL */
+#define WM8400_CHIP_GT150_LVL_MASK              0x0200  /* CHIP_GT150_LVL */
+#define WM8400_CHIP_GT150_LVL_SHIFT                  9  /* CHIP_GT150_LVL */
+#define WM8400_CHIP_GT150_LVL_WIDTH                  1  /* CHIP_GT150_LVL */
+#define WM8400_CHIP_GT115_LVL                   0x0100  /* CHIP_GT115_LVL */
+#define WM8400_CHIP_GT115_LVL_MASK              0x0100  /* CHIP_GT115_LVL */
+#define WM8400_CHIP_GT115_LVL_SHIFT                  8  /* CHIP_GT115_LVL */
+#define WM8400_CHIP_GT115_LVL_WIDTH                  1  /* CHIP_GT115_LVL */
+#define WM8400_LINE_CMP_LVL                     0x0080  /* LINE_CMP_LVL */
+#define WM8400_LINE_CMP_LVL_MASK                0x0080  /* LINE_CMP_LVL */
+#define WM8400_LINE_CMP_LVL_SHIFT                    7  /* LINE_CMP_LVL */
+#define WM8400_LINE_CMP_LVL_WIDTH                    1  /* LINE_CMP_LVL */
+#define WM8400_UVLO_LVL                         0x0040  /* UVLO_LVL */
+#define WM8400_UVLO_LVL_MASK                    0x0040  /* UVLO_LVL */
+#define WM8400_UVLO_LVL_SHIFT                        6  /* UVLO_LVL */
+#define WM8400_UVLO_LVL_WIDTH                        1  /* UVLO_LVL */
+#define WM8400_DC2_UV_LVL                       0x0020  /* DC2_UV_LVL */
+#define WM8400_DC2_UV_LVL_MASK                  0x0020  /* DC2_UV_LVL */
+#define WM8400_DC2_UV_LVL_SHIFT                      5  /* DC2_UV_LVL */
+#define WM8400_DC2_UV_LVL_WIDTH                      1  /* DC2_UV_LVL */
+#define WM8400_DC1_UV_LVL                       0x0010  /* DC1_UV_LVL */
+#define WM8400_DC1_UV_LVL_MASK                  0x0010  /* DC1_UV_LVL */
+#define WM8400_DC1_UV_LVL_SHIFT                      4  /* DC1_UV_LVL */
+#define WM8400_DC1_UV_LVL_WIDTH                      1  /* DC1_UV_LVL */
+#define WM8400_LDO4_UV_LVL                      0x0008  /* LDO4_UV_LVL */
+#define WM8400_LDO4_UV_LVL_MASK                 0x0008  /* LDO4_UV_LVL */
+#define WM8400_LDO4_UV_LVL_SHIFT                     3  /* LDO4_UV_LVL */
+#define WM8400_LDO4_UV_LVL_WIDTH                     1  /* LDO4_UV_LVL */
+#define WM8400_LDO3_UV_LVL                      0x0004  /* LDO3_UV_LVL */
+#define WM8400_LDO3_UV_LVL_MASK                 0x0004  /* LDO3_UV_LVL */
+#define WM8400_LDO3_UV_LVL_SHIFT                     2  /* LDO3_UV_LVL */
+#define WM8400_LDO3_UV_LVL_WIDTH                     1  /* LDO3_UV_LVL */
+#define WM8400_LDO2_UV_LVL                      0x0002  /* LDO2_UV_LVL */
+#define WM8400_LDO2_UV_LVL_MASK                 0x0002  /* LDO2_UV_LVL */
+#define WM8400_LDO2_UV_LVL_SHIFT                     1  /* LDO2_UV_LVL */
+#define WM8400_LDO2_UV_LVL_WIDTH                     1  /* LDO2_UV_LVL */
+#define WM8400_LDO1_UV_LVL                      0x0001  /* LDO1_UV_LVL */
+#define WM8400_LDO1_UV_LVL_MASK                 0x0001  /* LDO1_UV_LVL */
+#define WM8400_LDO1_UV_LVL_SHIFT                     0  /* LDO1_UV_LVL */
+#define WM8400_LDO1_UV_LVL_WIDTH                     1  /* LDO1_UV_LVL */
+
+/*
+ * R82 (0x52) - Shutdown Reason
+ */
+#define WM8400_SDR_CHIP_SOFTSD                  0x2000  /* SDR_CHIP_SOFTSD */
+#define WM8400_SDR_CHIP_SOFTSD_MASK             0x2000  /* SDR_CHIP_SOFTSD */
+#define WM8400_SDR_CHIP_SOFTSD_SHIFT                13  /* SDR_CHIP_SOFTSD */
+#define WM8400_SDR_CHIP_SOFTSD_WIDTH                 1  /* SDR_CHIP_SOFTSD */
+#define WM8400_SDR_NPDN                         0x0800  /* SDR_NPDN */
+#define WM8400_SDR_NPDN_MASK                    0x0800  /* SDR_NPDN */
+#define WM8400_SDR_NPDN_SHIFT                       11  /* SDR_NPDN */
+#define WM8400_SDR_NPDN_WIDTH                        1  /* SDR_NPDN */
+#define WM8400_SDR_CHIP_GT150                   0x0200  /* SDR_CHIP_GT150 */
+#define WM8400_SDR_CHIP_GT150_MASK              0x0200  /* SDR_CHIP_GT150 */
+#define WM8400_SDR_CHIP_GT150_SHIFT                  9  /* SDR_CHIP_GT150 */
+#define WM8400_SDR_CHIP_GT150_WIDTH                  1  /* SDR_CHIP_GT150 */
+#define WM8400_SDR_CHIP_GT115                   0x0100  /* SDR_CHIP_GT115 */
+#define WM8400_SDR_CHIP_GT115_MASK              0x0100  /* SDR_CHIP_GT115 */
+#define WM8400_SDR_CHIP_GT115_SHIFT                  8  /* SDR_CHIP_GT115 */
+#define WM8400_SDR_CHIP_GT115_WIDTH                  1  /* SDR_CHIP_GT115 */
+#define WM8400_SDR_LINE_CMP                     0x0080  /* SDR_LINE_CMP */
+#define WM8400_SDR_LINE_CMP_MASK                0x0080  /* SDR_LINE_CMP */
+#define WM8400_SDR_LINE_CMP_SHIFT                    7  /* SDR_LINE_CMP */
+#define WM8400_SDR_LINE_CMP_WIDTH                    1  /* SDR_LINE_CMP */
+#define WM8400_SDR_UVLO                         0x0040  /* SDR_UVLO */
+#define WM8400_SDR_UVLO_MASK                    0x0040  /* SDR_UVLO */
+#define WM8400_SDR_UVLO_SHIFT                        6  /* SDR_UVLO */
+#define WM8400_SDR_UVLO_WIDTH                        1  /* SDR_UVLO */
+#define WM8400_SDR_DC2_UV                       0x0020  /* SDR_DC2_UV */
+#define WM8400_SDR_DC2_UV_MASK                  0x0020  /* SDR_DC2_UV */
+#define WM8400_SDR_DC2_UV_SHIFT                      5  /* SDR_DC2_UV */
+#define WM8400_SDR_DC2_UV_WIDTH                      1  /* SDR_DC2_UV */
+#define WM8400_SDR_DC1_UV                       0x0010  /* SDR_DC1_UV */
+#define WM8400_SDR_DC1_UV_MASK                  0x0010  /* SDR_DC1_UV */
+#define WM8400_SDR_DC1_UV_SHIFT                      4  /* SDR_DC1_UV */
+#define WM8400_SDR_DC1_UV_WIDTH                      1  /* SDR_DC1_UV */
+#define WM8400_SDR_LDO4_UV                      0x0008  /* SDR_LDO4_UV */
+#define WM8400_SDR_LDO4_UV_MASK                 0x0008  /* SDR_LDO4_UV */
+#define WM8400_SDR_LDO4_UV_SHIFT                     3  /* SDR_LDO4_UV */
+#define WM8400_SDR_LDO4_UV_WIDTH                     1  /* SDR_LDO4_UV */
+#define WM8400_SDR_LDO3_UV                      0x0004  /* SDR_LDO3_UV */
+#define WM8400_SDR_LDO3_UV_MASK                 0x0004  /* SDR_LDO3_UV */
+#define WM8400_SDR_LDO3_UV_SHIFT                     2  /* SDR_LDO3_UV */
+#define WM8400_SDR_LDO3_UV_WIDTH                     1  /* SDR_LDO3_UV */
+#define WM8400_SDR_LDO2_UV                      0x0002  /* SDR_LDO2_UV */
+#define WM8400_SDR_LDO2_UV_MASK                 0x0002  /* SDR_LDO2_UV */
+#define WM8400_SDR_LDO2_UV_SHIFT                     1  /* SDR_LDO2_UV */
+#define WM8400_SDR_LDO2_UV_WIDTH                     1  /* SDR_LDO2_UV */
+#define WM8400_SDR_LDO1_UV                      0x0001  /* SDR_LDO1_UV */
+#define WM8400_SDR_LDO1_UV_MASK                 0x0001  /* SDR_LDO1_UV */
+#define WM8400_SDR_LDO1_UV_SHIFT                     0  /* SDR_LDO1_UV */
+#define WM8400_SDR_LDO1_UV_WIDTH                     1  /* SDR_LDO1_UV */
+
+/*
+ * R84 (0x54) - Line Circuits
+ */
+#define WM8400_BG_LINE_COMP                     0x8000  /* BG_LINE_COMP */
+#define WM8400_BG_LINE_COMP_MASK                0x8000  /* BG_LINE_COMP */
+#define WM8400_BG_LINE_COMP_SHIFT                   15  /* BG_LINE_COMP */
+#define WM8400_BG_LINE_COMP_WIDTH                    1  /* BG_LINE_COMP */
+#define WM8400_LINE_CMP_VTHI_MASK               0x00F0  /* LINE_CMP_VTHI - [7:4] */
+#define WM8400_LINE_CMP_VTHI_SHIFT                   4  /* LINE_CMP_VTHI - [7:4] */
+#define WM8400_LINE_CMP_VTHI_WIDTH                   4  /* LINE_CMP_VTHI - [7:4] */
+#define WM8400_LINE_CMP_VTHD_MASK               0x000F  /* LINE_CMP_VTHD - [3:0] */
+#define WM8400_LINE_CMP_VTHD_SHIFT                   0  /* LINE_CMP_VTHD - [3:0] */
+#define WM8400_LINE_CMP_VTHD_WIDTH                   4  /* LINE_CMP_VTHD - [3:0] */
+
+u16 wm8400_reg_read(struct wm8400 *wm8400, u8 reg);
+int wm8400_block_read(struct wm8400 *wm8400, u8 reg, int count, u16 *data);
+int wm8400_set_bits(struct wm8400 *wm8400, u8 reg, u16 mask, u16 val);
+
+#endif
diff --git a/include/linux/mfd/wm8400.h b/include/linux/mfd/wm8400.h
new file mode 100644
index 000000000000..b46b566ac1ac
--- /dev/null
+++ b/include/linux/mfd/wm8400.h
@@ -0,0 +1,40 @@
+/*
+ * wm8400 client interface
+ *
+ * Copyright 2008 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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __LINUX_MFD_WM8400_H
+#define __LINUX_MFD_WM8400_H
+
+#include <linux/regulator/machine.h>
+
+#define WM8400_LDO1  0
+#define WM8400_LDO2  1
+#define WM8400_LDO3  2
+#define WM8400_LDO4  3
+#define WM8400_DCDC1 4
+#define WM8400_DCDC2 5
+
+struct wm8400_platform_data {
+	int (*platform_init)(struct device *dev);
+};
+
+int wm8400_register_regulator(struct device *dev, int reg,
+			      struct regulator_init_data *initdata);
+
+#endif
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 1d712c7172a2..e37d80561985 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -18,8 +18,8 @@
 #include <linux/device.h>
 #include <linux/regulator/consumer.h>
 
-struct regulator_constraints;
 struct regulator_dev;
+struct regulator_init_data;
 
 /**
  * struct regulator_ops - regulator operations.
@@ -51,7 +51,7 @@ struct regulator_ops {
 					  int output_uV, int load_uA);
 
 	/* the operations below are for configuration of regulator state when
-	 * it's parent PMIC enters a global STANBY/HIBERNATE state */
+	 * its parent PMIC enters a global STANDBY/HIBERNATE state */
 
 	/* set regulator suspend voltage */
 	int (*set_suspend_voltage) (struct regulator_dev *, int uV);
@@ -85,15 +85,17 @@ struct regulator_desc {
 	struct module *owner;
 };
 
-
 struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
-					  void *reg_data);
+	struct device *dev, void *driver_data);
 void regulator_unregister(struct regulator_dev *rdev);
 
 int regulator_notifier_call_chain(struct regulator_dev *rdev,
 				  unsigned long event, void *data);
 
 void *rdev_get_drvdata(struct regulator_dev *rdev);
+struct device *rdev_get_dev(struct regulator_dev *rdev);
 int rdev_get_id(struct regulator_dev *rdev);
 
+void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data);
+
 #endif
diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h
index 11e737dbfcf2..c6d69331a81e 100644
--- a/include/linux/regulator/machine.h
+++ b/include/linux/regulator/machine.h
@@ -89,15 +89,33 @@ struct regulation_constraints {
 	unsigned apply_uV:1;	/* apply uV constraint iff min == max */
 };
 
-int regulator_set_supply(const char *regulator, const char *regulator_supply);
+/**
+ * struct regulator_consumer_supply - supply -> device mapping
+ *
+ * This maps a supply name to a device.
+ */
+struct regulator_consumer_supply {
+	struct device *dev;	/* consumer */
+	const char *supply;	/* consumer supply - e.g. "vcc" */
+};
 
-const char *regulator_get_supply(const char *regulator);
+/**
+ * struct regulator_init_data - regulator platform initialisation data.
+ *
+ * Initialisation constraints, our supply and consumers supplies.
+ */
+struct regulator_init_data {
+	struct device *supply_regulator_dev; /* or NULL for LINE */
 
-int regulator_set_machine_constraints(const char *regulator,
-	struct regulation_constraints *constraints);
+	struct regulation_constraints constraints;
 
-int regulator_set_device_supply(const char *regulator, struct device *dev,
-				const char *supply);
+	int num_consumer_supplies;
+	struct regulator_consumer_supply *consumer_supplies;
+
+	/* optional regulator machine specific init */
+	int (*regulator_init)(void *driver_data);
+	void *driver_data;	/* core does not touch this */
+};
 
 int regulator_suspend_prepare(suspend_state_t state);