Commit a627506a authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'regulator/topic/da9211',...

Merge remote-tracking branches 'regulator/topic/da9211', 'regulator/topic/getreg', 'regulator/topic/gpio' and 'regulator/topic/lp872x' into regulator-next
...@@ -180,3 +180,38 @@ int regulator_unregister_notifier(struct regulator *regulator, ...@@ -180,3 +180,38 @@ int regulator_unregister_notifier(struct regulator *regulator,
Regulators use the kernel notifier framework to send event to their interested Regulators use the kernel notifier framework to send event to their interested
consumers. consumers.
7. Regulator Direct Register Access
===================================
Some kinds of power management hardware or firmware are designed such that
they need to do low-level hardware access to regulators, with no involvement
from the kernel. Examples of such devices are:
- clocksource with a voltage-controlled oscillator and control logic to change
the supply voltage over I2C to achieve a desired output clock rate
- thermal management firmware that can issue an arbitrary I2C transaction to
perform system poweroff during overtemperature conditions
To set up such a device/firmware, various parameters like I2C address of the
regulator, addresses of various regulator registers etc. need to be configured
to it. The regulator framework provides the following helpers for querying
these details.
Bus-specific details, like I2C addresses or transfer rates are handled by the
regmap framework. To get the regulator's regmap (if supported), use :-
struct regmap *regulator_get_regmap(struct regulator *regulator);
To obtain the hardware register offset and bitmask for the regulator's voltage
selector register, use :-
int regulator_get_hardware_vsel_register(struct regulator *regulator,
unsigned *vsel_reg,
unsigned *vsel_mask);
To convert a regulator framework voltage selector code (used by
regulator_list_voltage) to a hardware-specific voltage selector that can be
directly written to the voltage selector register, use :-
int regulator_list_hardware_vsel(struct regulator *regulator,
unsigned selector);
...@@ -198,6 +198,16 @@ config REGULATOR_DA9210 ...@@ -198,6 +198,16 @@ config REGULATOR_DA9210
converter 12A DC-DC Buck controlled through an I2C converter 12A DC-DC Buck controlled through an I2C
interface. interface.
config REGULATOR_DA9211
tristate "Dialog Semiconductor DA9211/DA9212 regulator"
depends on I2C
select REGMAP_I2C
help
Say y here to support for the Dialog Semiconductor DA9211/DA9212.
The DA9211/DA9212 is a multi-phase synchronous step down
converter 12A DC-DC Buck controlled through an I2C
interface.
config REGULATOR_DBX500_PRCMU config REGULATOR_DBX500_PRCMU
bool bool
......
...@@ -27,6 +27,7 @@ obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o ...@@ -27,6 +27,7 @@ obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o
obj-$(CONFIG_REGULATOR_DA9063) += da9063-regulator.o obj-$(CONFIG_REGULATOR_DA9063) += da9063-regulator.o
obj-$(CONFIG_REGULATOR_DA9210) += da9210-regulator.o obj-$(CONFIG_REGULATOR_DA9210) += da9210-regulator.o
obj-$(CONFIG_REGULATOR_DA9211) += da9211-regulator.o
obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/suspend.h> #include <linux/suspend.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/regulator/of_regulator.h> #include <linux/regulator/of_regulator.h>
...@@ -77,7 +78,7 @@ struct regulator_map { ...@@ -77,7 +78,7 @@ struct regulator_map {
*/ */
struct regulator_enable_gpio { struct regulator_enable_gpio {
struct list_head list; struct list_head list;
int gpio; struct gpio_desc *gpiod;
u32 enable_count; /* a number of enabled shared GPIO */ u32 enable_count; /* a number of enabled shared GPIO */
u32 request_count; /* a number of requested shared GPIO */ u32 request_count; /* a number of requested shared GPIO */
unsigned int ena_gpio_invert:1; unsigned int ena_gpio_invert:1;
...@@ -1662,10 +1663,13 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev, ...@@ -1662,10 +1663,13 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev,
const struct regulator_config *config) const struct regulator_config *config)
{ {
struct regulator_enable_gpio *pin; struct regulator_enable_gpio *pin;
struct gpio_desc *gpiod;
int ret; int ret;
gpiod = gpio_to_desc(config->ena_gpio);
list_for_each_entry(pin, &regulator_ena_gpio_list, list) { list_for_each_entry(pin, &regulator_ena_gpio_list, list) {
if (pin->gpio == config->ena_gpio) { if (pin->gpiod == gpiod) {
rdev_dbg(rdev, "GPIO %d is already used\n", rdev_dbg(rdev, "GPIO %d is already used\n",
config->ena_gpio); config->ena_gpio);
goto update_ena_gpio_to_rdev; goto update_ena_gpio_to_rdev;
...@@ -1684,7 +1688,7 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev, ...@@ -1684,7 +1688,7 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev,
return -ENOMEM; return -ENOMEM;
} }
pin->gpio = config->ena_gpio; pin->gpiod = gpiod;
pin->ena_gpio_invert = config->ena_gpio_invert; pin->ena_gpio_invert = config->ena_gpio_invert;
list_add(&pin->list, &regulator_ena_gpio_list); list_add(&pin->list, &regulator_ena_gpio_list);
...@@ -1703,10 +1707,10 @@ static void regulator_ena_gpio_free(struct regulator_dev *rdev) ...@@ -1703,10 +1707,10 @@ static void regulator_ena_gpio_free(struct regulator_dev *rdev)
/* Free the GPIO only in case of no use */ /* Free the GPIO only in case of no use */
list_for_each_entry_safe(pin, n, &regulator_ena_gpio_list, list) { list_for_each_entry_safe(pin, n, &regulator_ena_gpio_list, list) {
if (pin->gpio == rdev->ena_pin->gpio) { if (pin->gpiod == rdev->ena_pin->gpiod) {
if (pin->request_count <= 1) { if (pin->request_count <= 1) {
pin->request_count = 0; pin->request_count = 0;
gpio_free(pin->gpio); gpiod_put(pin->gpiod);
list_del(&pin->list); list_del(&pin->list);
kfree(pin); kfree(pin);
} else { } else {
...@@ -1734,8 +1738,8 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) ...@@ -1734,8 +1738,8 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
if (enable) { if (enable) {
/* Enable GPIO at initial use */ /* Enable GPIO at initial use */
if (pin->enable_count == 0) if (pin->enable_count == 0)
gpio_set_value_cansleep(pin->gpio, gpiod_set_value_cansleep(pin->gpiod,
!pin->ena_gpio_invert); !pin->ena_gpio_invert);
pin->enable_count++; pin->enable_count++;
} else { } else {
...@@ -1746,8 +1750,8 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) ...@@ -1746,8 +1750,8 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
/* Disable GPIO if not used */ /* Disable GPIO if not used */
if (pin->enable_count <= 1) { if (pin->enable_count <= 1) {
gpio_set_value_cansleep(pin->gpio, gpiod_set_value_cansleep(pin->gpiod,
pin->ena_gpio_invert); pin->ena_gpio_invert);
pin->enable_count = 0; pin->enable_count = 0;
} }
} }
...@@ -2234,6 +2238,77 @@ int regulator_list_voltage(struct regulator *regulator, unsigned selector) ...@@ -2234,6 +2238,77 @@ int regulator_list_voltage(struct regulator *regulator, unsigned selector)
} }
EXPORT_SYMBOL_GPL(regulator_list_voltage); EXPORT_SYMBOL_GPL(regulator_list_voltage);
/**
* regulator_get_regmap - get the regulator's register map
* @regulator: regulator source
*
* Returns the register map for the given regulator, or an ERR_PTR value
* if the regulator doesn't use regmap.
*/
struct regmap *regulator_get_regmap(struct regulator *regulator)
{
struct regmap *map = regulator->rdev->regmap;
return map ? map : ERR_PTR(-EOPNOTSUPP);
}
/**
* regulator_get_hardware_vsel_register - get the HW voltage selector register
* @regulator: regulator source
* @vsel_reg: voltage selector register, output parameter
* @vsel_mask: mask for voltage selector bitfield, output parameter
*
* Returns the hardware register offset and bitmask used for setting the
* regulator voltage. This might be useful when configuring voltage-scaling
* hardware or firmware that can make I2C requests behind the kernel's back,
* for example.
*
* On success, the output parameters @vsel_reg and @vsel_mask are filled in
* and 0 is returned, otherwise a negative errno is returned.
*/
int regulator_get_hardware_vsel_register(struct regulator *regulator,
unsigned *vsel_reg,
unsigned *vsel_mask)
{
struct regulator_dev *rdev = regulator->rdev;
struct regulator_ops *ops = rdev->desc->ops;
if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap)
return -EOPNOTSUPP;
*vsel_reg = rdev->desc->vsel_reg;
*vsel_mask = rdev->desc->vsel_mask;
return 0;
}
EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register);
/**
* regulator_list_hardware_vsel - get the HW-specific register value for a selector
* @regulator: regulator source
* @selector: identify voltage to list
*
* Converts the selector to a hardware-specific voltage selector that can be
* directly written to the regulator registers. The address of the voltage
* register can be determined by calling @regulator_get_hardware_vsel_register.
*
* On error a negative errno is returned.
*/
int regulator_list_hardware_vsel(struct regulator *regulator,
unsigned selector)
{
struct regulator_dev *rdev = regulator->rdev;
struct regulator_ops *ops = rdev->desc->ops;
if (selector >= rdev->desc->n_voltages)
return -EINVAL;
if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap)
return -EOPNOTSUPP;
return selector;
}
EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel);
/** /**
* regulator_get_linear_step - return the voltage step size between VSEL values * regulator_get_linear_step - return the voltage step size between VSEL values
* @regulator: regulator source * @regulator: regulator source
......
/*
* da9211-regulator.c - Regulator device driver for DA9211
* Copyright (C) 2014 Dialog Semiconductor Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*/
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regmap.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/regulator/da9211.h>
#include "da9211-regulator.h"
#define DA9211_BUCK_MODE_SLEEP 1
#define DA9211_BUCK_MODE_SYNC 2
#define DA9211_BUCK_MODE_AUTO 3
/* DA9211 REGULATOR IDs */
#define DA9211_ID_BUCKA 0
#define DA9211_ID_BUCKB 1
struct da9211 {
struct device *dev;
struct regmap *regmap;
struct da9211_pdata *pdata;
struct regulator_dev *rdev[DA9211_MAX_REGULATORS];
int num_regulator;
int chip_irq;
};
static const struct regmap_range_cfg da9211_regmap_range[] = {
{
.selector_reg = DA9211_REG_PAGE_CON,
.selector_mask = DA9211_REG_PAGE_MASK,
.selector_shift = DA9211_REG_PAGE_SHIFT,
.window_start = 0,
.window_len = 256,
.range_min = 0,
.range_max = 2*256,
},
};
static const struct regmap_config da9211_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 2 * 256,
.ranges = da9211_regmap_range,
.num_ranges = ARRAY_SIZE(da9211_regmap_range),
};
/* Default limits measured in millivolts and milliamps */
#define DA9211_MIN_MV 300
#define DA9211_MAX_MV 1570
#define DA9211_STEP_MV 10
/* Current limits for buck (uA) indices corresponds with register values */
static const int da9211_current_limits[] = {
2000000, 2200000, 2400000, 2600000, 2800000, 3000000, 3200000, 3400000,
3600000, 3800000, 4000000, 4200000, 4400000, 4600000, 4800000, 5000000
};
static unsigned int da9211_buck_get_mode(struct regulator_dev *rdev)
{
int id = rdev_get_id(rdev);
struct da9211 *chip = rdev_get_drvdata(rdev);
unsigned int data;
int ret, mode = 0;
ret = regmap_read(chip->regmap, DA9211_REG_BUCKA_CONF+id, &data);
if (ret < 0)
return ret;
switch (data & 0x03) {
case DA9211_BUCK_MODE_SYNC:
mode = REGULATOR_MODE_FAST;
break;
case DA9211_BUCK_MODE_AUTO:
mode = REGULATOR_MODE_NORMAL;
break;
case DA9211_BUCK_MODE_SLEEP:
mode = REGULATOR_MODE_STANDBY;
break;
}
return mode;
}
static int da9211_buck_set_mode(struct regulator_dev *rdev,
unsigned int mode)
{
int id = rdev_get_id(rdev);
struct da9211 *chip = rdev_get_drvdata(rdev);
int val = 0;
switch (mode) {
case REGULATOR_MODE_FAST:
val = DA9211_BUCK_MODE_SYNC;
break;
case REGULATOR_MODE_NORMAL:
val = DA9211_BUCK_MODE_AUTO;
break;
case REGULATOR_MODE_STANDBY:
val = DA9211_BUCK_MODE_SLEEP;
break;
}
return regmap_update_bits(chip->regmap, DA9211_REG_BUCKA_CONF+id,
0x03, val);
}
static int da9211_set_current_limit(struct regulator_dev *rdev, int min,
int max)
{
int id = rdev_get_id(rdev);
struct da9211 *chip = rdev_get_drvdata(rdev);
int i;
/* search for closest to maximum */
for (i = ARRAY_SIZE(da9211_current_limits)-1; i >= 0; i--) {
if (min <= da9211_current_limits[i] &&
max >= da9211_current_limits[i]) {
return regmap_update_bits(chip->regmap,
DA9211_REG_BUCK_ILIM,
(0x0F << id*4), (i << id*4));
}
}
return -EINVAL;
}
static int da9211_get_current_limit(struct regulator_dev *rdev)
{
int id = rdev_get_id(rdev);
struct da9211 *chip = rdev_get_drvdata(rdev);
unsigned int data;
int ret;
ret = regmap_read(chip->regmap, DA9211_REG_BUCK_ILIM, &data);
if (ret < 0)
return ret;
/* select one of 16 values: 0000 (2000mA) to 1111 (5000mA) */
data = (data >> id*4) & 0x0F;
return da9211_current_limits[data];
}
static struct regulator_ops da9211_buck_ops = {
.get_mode = da9211_buck_get_mode,
.set_mode = da9211_buck_set_mode,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
.set_current_limit = da9211_set_current_limit,
.get_current_limit = da9211_get_current_limit,
};
#define DA9211_BUCK(_id) \
{\
.name = #_id,\
.ops = &da9211_buck_ops,\
.type = REGULATOR_VOLTAGE,\
.id = DA9211_ID_##_id,\
.n_voltages = (DA9211_MAX_MV - DA9211_MIN_MV) / DA9211_STEP_MV + 1,\
.min_uV = (DA9211_MIN_MV * 1000),\
.uV_step = (DA9211_STEP_MV * 1000),\
.enable_reg = DA9211_REG_BUCKA_CONT + DA9211_ID_##_id,\
.enable_mask = DA9211_BUCKA_EN,\
.vsel_reg = DA9211_REG_VBUCKA_A + DA9211_ID_##_id * 2,\
.vsel_mask = DA9211_VBUCK_MASK,\
.owner = THIS_MODULE,\
}
static struct regulator_desc da9211_regulators[] = {
DA9211_BUCK(BUCKA),
DA9211_BUCK(BUCKB),
};
static irqreturn_t da9211_irq_handler(int irq, void *data)
{
struct da9211 *chip = data;
int reg_val, err, ret = IRQ_NONE;
err = regmap_read(chip->regmap, DA9211_REG_EVENT_B, &reg_val);
if (err < 0)
goto error_i2c;
if (reg_val & DA9211_E_OV_CURR_A) {
regulator_notifier_call_chain(chip->rdev[0],
REGULATOR_EVENT_OVER_CURRENT,
rdev_get_drvdata(chip->rdev[0]));
err = regmap_write(chip->regmap, DA9211_REG_EVENT_B,
DA9211_E_OV_CURR_A);
if (err < 0)
goto error_i2c;
ret = IRQ_HANDLED;
}
if (reg_val & DA9211_E_OV_CURR_B) {
regulator_notifier_call_chain(chip->rdev[1],
REGULATOR_EVENT_OVER_CURRENT,
rdev_get_drvdata(chip->rdev[1]));
err = regmap_write(chip->regmap, DA9211_REG_EVENT_B,
DA9211_E_OV_CURR_B);
if (err < 0)
goto error_i2c;
ret = IRQ_HANDLED;
}
return ret;
error_i2c:
dev_err(chip->dev, "I2C error : %d\n", err);
return IRQ_NONE;
}
static int da9211_regulator_init(struct da9211 *chip)
{
struct regulator_config config = { };
int i, ret;
unsigned int data;
ret = regmap_read(chip->regmap, DA9211_REG_CONFIG_E, &data);
if (ret < 0) {
dev_err(chip->dev, "Failed to read CONTROL_E reg: %d\n", ret);
return ret;
}
data &= DA9211_SLAVE_SEL;
/* If configuration for 1/2 bucks is different between platform data
* and the register, driver should exit.
*/
if ((chip->pdata->num_buck == 2 && data == 0x40)
|| (chip->pdata->num_buck == 1 && data == 0x00)) {
if (data == 0)
chip->num_regulator = 1;
else
chip->num_regulator = 2;
} else {
dev_err(chip->dev, "Configuration is mismatched\n");
return -EINVAL;
}
for (i = 0; i < chip->num_regulator; i++) {
if (chip->pdata)
config.init_data =
&(chip->pdata->init_data[i]);
config.dev = chip->dev;
config.driver_data = chip;
config.regmap = chip->regmap;
chip->rdev[i] = devm_regulator_register(chip->dev,
&da9211_regulators[i], &config);
if (IS_ERR(chip->rdev[i])) {
dev_err(chip->dev,
"Failed to register DA9211 regulator\n");
return PTR_ERR(chip->rdev[i]);
}
if (chip->chip_irq != 0) {
ret = regmap_update_bits(chip->regmap,
DA9211_REG_MASK_B, DA9211_M_OV_CURR_A << i, 1);
if (ret < 0) {
dev_err(chip->dev,
"Failed to update mask reg: %d\n", ret);
return ret;
}
}
}
return 0;
}
/*
* I2C driver interface functions
*/
static int da9211_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct da9211 *chip;
int error, ret;
chip = devm_kzalloc(&i2c->dev, sizeof(struct da9211), GFP_KERNEL);
chip->dev = &i2c->dev;
chip->regmap = devm_regmap_init_i2c(i2c, &da9211_regmap_config);
if (IS_ERR(chip->regmap)) {
error = PTR_ERR(chip->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
error);
return error;
}
i2c_set_clientdata(i2c, chip);
chip->pdata = i2c->dev.platform_data;
if (!chip->pdata) {
dev_err(&i2c->dev, "No platform init data supplied\n");
return -ENODEV;
}
chip->chip_irq = i2c->irq;
if (chip->chip_irq != 0) {
ret = devm_request_threaded_irq(chip->dev, chip->chip_irq, NULL,
da9211_irq_handler,
IRQF_TRIGGER_LOW|IRQF_ONESHOT,
"da9211", chip);
if (ret != 0) {
dev_err(chip->dev, "Failed to request IRQ: %d\n",
chip->chip_irq);
return ret;
}
} else {
dev_warn(chip->dev, "No IRQ configured\n");
}
ret = da9211_regulator_init(chip);
if (ret < 0)
dev_err(&i2c->dev, "Failed to initialize regulator: %d\n", ret);
return ret;
}
static const struct i2c_device_id da9211_i2c_id[] = {
{"da9211", 0},
{},
};
MODULE_DEVICE_TABLE(i2c, da9211_i2c_id);
static struct i2c_driver da9211_regulator_driver = {
.driver = {
.name = "da9211",
.owner = THIS_MODULE,
},
.probe = da9211_i2c_probe,
.id_table = da9211_i2c_id,
};
module_i2c_driver(da9211_regulator_driver);
MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>");
MODULE_DESCRIPTION("Regulator device driver for Dialog DA9211");
MODULE_LICENSE("GPL v2");
/*
* da9211-regulator.h - Regulator definitions for DA9211
* Copyright (C) 2014 Dialog Semiconductor Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*/
#ifndef __DA9211_REGISTERS_H__
#define __DA9211_REGISTERS_H__
/* Page selection */
#define DA9211_REG_PAGE_CON 0x00
/* System Control and Event Registers */
#define DA9211_REG_STATUS_A 0x50
#define DA9211_REG_STATUS_B 0x51
#define DA9211_REG_EVENT_A 0x52
#define DA9211_REG_EVENT_B 0x53
#define DA9211_REG_MASK_A 0x54
#define DA9211_REG_MASK_B 0x55
#define DA9211_REG_CONTROL_A 0x56
/* GPIO Control Registers */
#define DA9211_REG_GPIO_0_1 0x58
#define DA9211_REG_GPIO_2_3 0x59
#define DA9211_REG_GPIO_4 0x5A
/* Regulator Registers */
#define DA9211_REG_BUCKA_CONT 0x5D
#define DA9211_REG_BUCKB_CONT 0x5E
#define DA9211_REG_BUCK_ILIM 0xD0
#define DA9211_REG_BUCKA_CONF 0xD1
#define DA9211_REG_BUCKB_CONF 0xD2
#define DA9211_REG_BUCK_CONF 0xD3
#define DA9211_REG_VBACKA_MAX 0xD5
#define DA9211_REG_VBACKB_MAX 0xD6
#define DA9211_REG_VBUCKA_A 0xD7
#define DA9211_REG_VBUCKA_B 0xD8
#define DA9211_REG_VBUCKB_A 0xD9
#define DA9211_REG_VBUCKB_B 0xDA
/* I2C Interface Settings */
#define DA9211_REG_INTERFACE 0x105
/* BUCK Phase Selection*/
#define DA9211_REG_CONFIG_E 0x147
/*
* Registers bits
*/
/* DA9211_REG_PAGE_CON (addr=0x00) */
#define DA9211_REG_PAGE_SHIFT 1
#define DA9211_REG_PAGE_MASK 0x02
/* On I2C registers 0x00 - 0xFF */
#define DA9211_REG_PAGE0 0
/* On I2C registers 0x100 - 0x1FF */
#define DA9211_REG_PAGE2 2
#define DA9211_PAGE_WRITE_MODE 0x00
#define DA9211_REPEAT_WRITE_MODE 0x40
#define DA9211_PAGE_REVERT 0x80
/* DA9211_REG_STATUS_A (addr=0x50) */
#define DA9211_GPI0 0x01
#define DA9211_GPI1 0x02
#define DA9211_GPI2 0x04
#define DA9211_GPI3 0x08
#define DA9211_GPI4 0x10
/* DA9211_REG_EVENT_A (addr=0x52) */
#define DA9211_E_GPI0 0x01
#define DA9211_E_GPI1 0x02
#define DA9211_E_GPI2 0x04
#define DA9211_E_GPI3 0x08
#define DA9211_E_GPI4 0x10
#define DA9211_E_UVLO_IO 0x40
/* DA9211_REG_EVENT_B (addr=0x53) */
#define DA9211_E_PWRGOOD_A 0x01
#define DA9211_E_PWRGOOD_B 0x02
#define DA9211_E_TEMP_WARN 0x04
#define DA9211_E_TEMP_CRIT 0x08
#define DA9211_E_OV_CURR_A 0x10
#define DA9211_E_OV_CURR_B 0x20
/* DA9211_REG_MASK_A (addr=0x54) */
#define DA9211_M_GPI0 0x01
#define DA9211_M_GPI1 0x02
#define DA9211_M_GPI2 0x04
#define DA9211_M_GPI3 0x08
#define DA9211_M_GPI4 0x10
#define DA9211_M_UVLO_IO 0x40
/* DA9211_REG_MASK_B (addr=0x55) */
#define DA9211_M_PWRGOOD_A 0x01
#define DA9211_M_PWRGOOD_B 0x02
#define DA9211_M_TEMP_WARN 0x04
#define DA9211_M_TEMP_CRIT 0x08
#define DA9211_M_OV_CURR_A 0x10
#define DA9211_M_OV_CURR_B 0x20
/* DA9211_REG_CONTROL_A (addr=0x56) */
#define DA9211_DEBOUNCING_SHIFT 0
#define DA9211_DEBOUNCING_MASK 0x07
#define DA9211_SLEW_RATE_SHIFT 3
#define DA9211_SLEW_RATE_A_MASK 0x18
#define DA9211_SLEW_RATE_B_SHIFT 5
#define DA9211_SLEW_RATE_B_MASK 0x60
#define DA9211_V_LOCK 0x80
/* DA9211_REG_GPIO_0_1 (addr=0x58) */
#define DA9211_GPIO0_PIN_SHIFT 0
#define DA9211_GPIO0_PIN_MASK 0x03
#define DA9211_GPIO0_PIN_GPI 0x00
#define DA9211_GPIO0_PIN_GPO_OD 0x02
#define DA9211_GPIO0_PIN_GPO 0x03
#define DA9211_GPIO0_TYPE 0x04
#define DA9211_GPIO0_TYPE_GPI 0x00
#define DA9211_GPIO0_TYPE_GPO 0x04
#define DA9211_GPIO0_MODE 0x08
#define DA9211_GPIO1_PIN_SHIFT 4
#define DA9211_GPIO1_PIN_MASK 0x30
#define DA9211_GPIO1_PIN_GPI 0x00
#define DA9211_GPIO1_PIN_VERROR 0x10
#define DA9211_GPIO1_PIN_GPO_OD 0x20
#define DA9211_GPIO1_PIN_GPO 0x30
#define DA9211_GPIO1_TYPE_SHIFT 0x40
#define DA9211_GPIO1_TYPE_GPI 0x00
#define DA9211_GPIO1_TYPE_GPO 0x40
#define DA9211_GPIO1_MODE 0x80
/* DA9211_REG_GPIO_2_3 (addr=0x59) */
#define DA9211_GPIO2_PIN_SHIFT 0
#define DA9211_GPIO2_PIN_MASK 0x03
#define DA9211_GPIO2_PIN_GPI 0x00
#define DA9211_GPIO5_PIN_BUCK_CLK 0x10
#define DA9211_GPIO2_PIN_GPO_OD 0x02
#define DA9211_GPIO2_PIN_GPO 0x03
#define DA9211_GPIO2_TYPE 0x04
#define DA9211_GPIO2_TYPE_GPI 0x00
#define DA9211_GPIO2_TYPE_GPO 0x04
#define DA9211_GPIO2_MODE 0x08
#define DA9211_GPIO3_PIN_SHIFT 4
#define DA9211_GPIO3_PIN_MASK 0x30
#define DA9211_GPIO3_PIN_GPI 0x00
#define DA9211_GPIO3_PIN_IERROR 0x10
#define DA9211_GPIO3_PIN_GPO_OD 0x20
#define DA9211_GPIO3_PIN_GPO 0x30
#define DA9211_GPIO3_TYPE_SHIFT 0x40
#define DA9211_GPIO3_TYPE_GPI 0x00
#define DA9211_GPIO3_TYPE_GPO 0x40
#define DA9211_GPIO3_MODE 0x80
/* DA9211_REG_GPIO_4 (addr=0x5A) */
#define DA9211_GPIO4_PIN_SHIFT 0
#define DA9211_GPIO4_PIN_MASK 0x03
#define DA9211_GPIO4_PIN_GPI 0x00
#define DA9211_GPIO4_PIN_GPO_OD 0x02
#define DA9211_GPIO4_PIN_GPO 0x03
#define DA9211_GPIO4_TYPE 0x04
#define DA9211_GPIO4_TYPE_GPI 0x00
#define DA9211_GPIO4_TYPE_GPO 0x04
#define DA9211_GPIO4_MODE 0x08
/* DA9211_REG_BUCKA_CONT (addr=0x5D) */
#define DA9211_BUCKA_EN 0x01
#define DA9211_BUCKA_GPI_SHIFT 1
#define DA9211_BUCKA_GPI_MASK 0x06
#define DA9211_BUCKA_GPI_OFF 0x00
#define DA9211_BUCKA_GPI_GPIO0 0x02
#define DA9211_BUCKA_GPI_GPIO1 0x04
#define DA9211_BUCKA_GPI_GPIO3 0x06
#define DA9211_BUCKA_PD_DIS 0x08
#define DA9211_VBUCKA_SEL 0x10
#define DA9211_VBUCKA_SEL_A 0x00
#define DA9211_VBUCKA_SEL_B 0x10
#define DA9211_VBUCKA_GPI_SHIFT 5
#define DA9211_VBUCKA_GPI_MASK 0x60
#define DA9211_VBUCKA_GPI_OFF 0x00
#define DA9211_VBUCKA_GPI_GPIO1 0x20
#define DA9211_VBUCKA_GPI_GPIO2 0x40
#define DA9211_VBUCKA_GPI_GPIO4 0x60
/* DA9211_REG_BUCKB_CONT (addr=0x5E) */
#define DA9211_BUCKB_EN 0x01
#define DA9211_BUCKB_GPI_SHIFT 1
#define DA9211_BUCKB_GPI_MASK 0x06
#define DA9211_BUCKB_GPI_OFF 0x00
#define DA9211_BUCKB_GPI_GPIO0 0x02
#define DA9211_BUCKB_GPI_GPIO1 0x04
#define DA9211_BUCKB_GPI_GPIO3 0x06
#define DA9211_BUCKB_PD_DIS 0x08
#define DA9211_VBUCKB_SEL 0x10
#define DA9211_VBUCKB_SEL_A 0x00
#define DA9211_VBUCKB_SEL_B 0x10
#define DA9211_VBUCKB_GPI_SHIFT 5
#define DA9211_VBUCKB_GPI_MASK 0x60
#define DA9211_VBUCKB_GPI_OFF 0x00
#define DA9211_VBUCKB_GPI_GPIO1 0x20
#define DA9211_VBUCKB_GPI_GPIO2 0x40
#define DA9211_VBUCKB_GPI_GPIO4 0x60
/* DA9211_REG_BUCK_ILIM (addr=0xD0) */
#define DA9211_BUCKA_ILIM_SHIFT 0
#define DA9211_BUCKA_ILIM_MASK 0x0F
#define DA9211_BUCKB_ILIM_SHIFT 4
#define DA9211_BUCKB_ILIM_MASK 0xF0
/* DA9211_REG_BUCKA_CONF (addr=0xD1) */
#define DA9211_BUCKA_MODE_SHIFT 0
#define DA9211_BUCKA_MODE_MASK 0x03
#define DA9211_BUCKA_MODE_MANUAL 0x00
#define DA9211_BUCKA_MODE_SLEEP 0x01
#define DA9211_BUCKA_MODE_SYNC 0x02
#define DA9211_BUCKA_MODE_AUTO 0x03
#define DA9211_BUCKA_UP_CTRL_SHIFT 2
#define DA9211_BUCKA_UP_CTRL_MASK 0x1C
#define DA9211_BUCKA_DOWN_CTRL_SHIFT 5
#define DA9211_BUCKA_DOWN_CTRL_MASK 0xE0
/* DA9211_REG_BUCKB_CONF (addr=0xD2) */
#define DA9211_BUCKB_MODE_SHIFT 0
#define DA9211_BUCKB_MODE_MASK 0x03
#define DA9211_BUCKB_MODE_MANUAL 0x00
#define DA9211_BUCKB_MODE_SLEEP 0x01
#define DA9211_BUCKB_MODE_SYNC 0x02
#define DA9211_BUCKB_MODE_AUTO 0x03
#define DA9211_BUCKB_UP_CTRL_SHIFT 2
#define DA9211_BUCKB_UP_CTRL_MASK 0x1C
#define DA9211_BUCKB_DOWN_CTRL_SHIFT 5
#define DA9211_BUCKB_DOWN_CTRL_MASK 0xE0
/* DA9211_REG_BUCK_CONF (addr=0xD3) */
#define DA9211_PHASE_SEL_A_SHIFT 0
#define DA9211_PHASE_SEL_A_MASK 0x03
#define DA9211_PHASE_SEL_B_SHIFT 2
#define DA9211_PHASE_SEL_B_MASK 0x04
#define DA9211_PH_SH_EN_A_SHIFT 3
#define DA9211_PH_SH_EN_A_MASK 0x08
#define DA9211_PH_SH_EN_B_SHIFT 4
#define DA9211_PH_SH_EN_B_MASK 0x10
/* DA9211_REG_VBUCKA_MAX (addr=0xD5) */
#define DA9211_VBUCKA_BASE_SHIFT 0
#define DA9211_VBUCKA_BASE_MASK 0x7F
/* DA9211_REG_VBUCKB_MAX (addr=0xD6) */
#define DA9211_VBUCKB_BASE_SHIFT 0
#define DA9211_VBUCKB_BASE_MASK 0x7F
/* DA9211_REG_VBUCKA/B_A/B (addr=0xD7/0xD8/0xD9/0xDA) */
#define DA9211_VBUCK_SHIFT 0
#define DA9211_VBUCK_MASK 0x7F
#define DA9211_VBUCK_BIAS 0
#define DA9211_BUCK_SL 0x80
/* DA9211_REG_INTERFACE (addr=0x105) */
#define DA9211_IF_BASE_ADDR_SHIFT 4
#define DA9211_IF_BASE_ADDR_MASK 0xF0
/* DA9211_REG_CONFIG_E (addr=0x147) */
#define DA9211_SLAVE_SEL 0x40
#endif /* __DA9211_REGISTERS_H__ */
...@@ -845,7 +845,6 @@ static struct lp872x_platform_data ...@@ -845,7 +845,6 @@ static struct lp872x_platform_data
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct lp872x_platform_data *pdata; struct lp872x_platform_data *pdata;
struct of_regulator_match *match; struct of_regulator_match *match;
struct regulator_init_data *d;
int num_matches; int num_matches;
int count; int count;
int i; int i;
...@@ -892,14 +891,6 @@ static struct lp872x_platform_data ...@@ -892,14 +891,6 @@ static struct lp872x_platform_data
pdata->regulator_data[i].id = pdata->regulator_data[i].id =
(enum lp872x_regulator_id)match[i].driver_data; (enum lp872x_regulator_id)match[i].driver_data;
pdata->regulator_data[i].init_data = match[i].init_data; pdata->regulator_data[i].init_data = match[i].init_data;
/* Operation mode configuration for buck/buck1/buck2 */
if (strncmp(match[i].name, "buck", 4))
continue;
d = pdata->regulator_data[i].init_data;
d->constraints.valid_modes_mask |= LP872X_VALID_OPMODE;
d->constraints.valid_ops_mask |= REGULATOR_CHANGE_MODE;
} }
out: out:
return pdata; return pdata;
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
struct device; struct device;
struct notifier_block; struct notifier_block;
struct regmap;
/* /*
* Regulator operating modes. * Regulator operating modes.
...@@ -215,6 +216,13 @@ int regulator_set_optimum_mode(struct regulator *regulator, int load_uA); ...@@ -215,6 +216,13 @@ int regulator_set_optimum_mode(struct regulator *regulator, int load_uA);
int regulator_allow_bypass(struct regulator *regulator, bool allow); int regulator_allow_bypass(struct regulator *regulator, bool allow);
struct regmap *regulator_get_regmap(struct regulator *regulator);
int regulator_get_hardware_vsel_register(struct regulator *regulator,
unsigned *vsel_reg,
unsigned *vsel_mask);
int regulator_list_hardware_vsel(struct regulator *regulator,
unsigned selector);
/* regulator notifier block */ /* regulator notifier block */
int regulator_register_notifier(struct regulator *regulator, int regulator_register_notifier(struct regulator *regulator,
struct notifier_block *nb); struct notifier_block *nb);
...@@ -457,6 +465,24 @@ static inline int regulator_allow_bypass(struct regulator *regulator, ...@@ -457,6 +465,24 @@ static inline int regulator_allow_bypass(struct regulator *regulator,
return 0; return 0;
} }
static inline struct regmap *regulator_get_regmap(struct regulator *regulator)
{
return ERR_PTR(-EOPNOTSUPP);
}
static inline int regulator_get_hardware_vsel_register(struct regulator *regulator,
unsigned *vsel_reg,
unsigned *vsel_mask)
{
return -EOPNOTSUPP;
}
static inline int regulator_list_hardware_vsel(struct regulator *regulator,
unsigned selector)
{
return -EOPNOTSUPP;
}
static inline int regulator_register_notifier(struct regulator *regulator, static inline int regulator_register_notifier(struct regulator *regulator,
struct notifier_block *nb) struct notifier_block *nb)
{ {
......
/*
* da9211.h - Regulator device driver for DA9211
* Copyright (C) 2014 Dialog Semiconductor Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*/
#ifndef __LINUX_REGULATOR_DA9211_H
#define __LINUX_REGULATOR_DA9211_H
#include <linux/regulator/machine.h>
#define DA9211_MAX_REGULATORS 2
struct da9211_pdata {
/*
* Number of buck
* 1 : 4 phase 1 buck
* 2 : 2 phase 2 buck
*/
int num_buck;
struct regulator_init_data *init_data;
};
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment