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
  ...
This commit is contained in:
Linus Torvalds 2008-10-14 12:28:55 -07:00
commit c269bc00fc
31 changed files with 11267 additions and 353 deletions

View File

@ -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

View File

@ -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.
int regulator_set_device_supply(const char *regulator, struct device *dev,
const char *supply);
struct regulator_consumer_supply {
struct device *dev; /* consumer */
const char *supply; /* consumer supply - e.g. "vcc" */
};
and is shown with the following code :-
e.g. for the machine above
regulator_set_device_supply("Regulator-1", devB, "Vcc");
regulator_set_device_supply("Regulator-2", devA, "Vcc");
static struct regulator_consumer_supply regulator1_consumers[] = {
{
.dev = &platform_consumerB_device.dev,
.supply = "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.
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 :-
2. Regulator supply configuration.
==================================
Consider the following machine (again) :-
Regulator-1 -+-> Regulator-2 --> [Consumer A @ 1.8 - 2.0V]
|
+-> [Consumer B @ 3.3V]
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).
supply (Regulator-2). The supply regulator is set by the supply_regulator_dev
field below:-
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,
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.
regulator_set_platform_constraints("Regulator-1", &domain_1);
regulator_set_platform_constraints("Regulator-2", &domain_2);
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]);
/* register regulator 2 device */
platform_device_register(&wm8350_regulator_devices[1]);

View File

@ -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 :-

View File

@ -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

View File

@ -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"

View File

@ -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

1273
drivers/mfd/wm8350-core.c Normal file

File diff suppressed because it is too large Load Diff

222
drivers/mfd/wm8350-gpio.c Normal file
View File

@ -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);

120
drivers/mfd/wm8350-i2c.c Normal file
View File

@ -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");

1347
drivers/mfd/wm8350-regmap.c Normal file

File diff suppressed because it is too large Load Diff

455
drivers/mfd/wm8400-core.c Normal file
View File

@ -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>");

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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);
rdev->dev.class = &regulator_class;
device_initialize(&rdev->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);
/* 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;
}
}
ret = device_add(&rdev->dev);
if (ret == 0)
list_add(&rdev->list, &regulator_list);
else {
/* 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;
rdev->dev.parent = dev;
snprintf(rdev->dev.bus_id, sizeof(rdev->dev.bus_id),
"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;
}
@ -1630,187 +1845,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);

513
drivers/regulator/da903x.c Normal file
View File

@ -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");

File diff suppressed because it is too large Load Diff

View File

@ -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");

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);