Skip to content

Commit

Permalink
Merge remote-tracking branches 'regulator/topic/discharge', 'regulato…
Browse files Browse the repository at this point in the history
…r/topic/fan53555', 'regulator/topic/gpio', 'regulator/topic/hi655x' and 'regulator/topic/lp872x' into regulator-next
  • Loading branch information
Mark Brown committed Mar 13, 2016
6 parents 92aa18f + 354794d + ab7cad3 + 0258382 + 4618119 + 7e6213f commit d1f8302
Show file tree
Hide file tree
Showing 15 changed files with 402 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
Hisilicon Hi655x Voltage regulators

Note:
The Hi655x regulator control is managed by Hi655x PMIC.
So the node of this regulator must be child node of Hi655x
PMIC node.

The driver uses the regulator core framework, so please also
take the bindings of regulator.txt for reference.

The valid names for regulators are:

LDO2_2V8 LDO7_SDIO LDO10_2V85 LDO13_1V8 LDO14_2V8
LDO15_1V8 LDO17_2V5 LDO19_3V0 LDO21_1V8 LDO22_1V2

Example:
pmic: pmic@f8000000 {
compatible = "hisilicon,hi655x-pmic";
...
regulators {
ldo2: LDO2@a21 {
regulator-name = "LDO2_2V8";
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <3200000>;
regulator-enable-ramp-delay = <120>;
};
...
}
}
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/regulator/lp872x.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Optional properties:
- ti,dvs-gpio: GPIO specifier for external DVS pin control of LP872x devices.
- ti,dvs-vsel: DVS selector. 0 = SEL_V1, 1 = SEL_V2.
- ti,dvs-state: initial DVS pin state. 0 = DVS_LOW, 1 = DVS_HIGH.
- enable-gpios: GPIO specifier for EN pin control of LP872x devices.

Sub nodes for regulator_init_data
LP8720 has maximum 6 nodes. (child name: ldo1 ~ 5 and buck)
Expand Down
5 changes: 5 additions & 0 deletions Documentation/devicetree/bindings/regulator/regulator.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ Optional properties:
any consumer request.
- regulator-pull-down: Enable pull down resistor when the regulator is disabled.
- regulator-over-current-protection: Enable over current protection.
- regulator-active-discharge: tristate, enable/disable active discharge of
regulators. The values are:
0: Disable active discharge.
1: Enable active discharge.
Absence of this property will leave configuration to default.

Deprecated properties:
- regulator-compatible: If a regulator chip contains multiple
Expand Down
8 changes: 8 additions & 0 deletions drivers/regulator/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,14 @@ config REGULATOR_HI6421
21 general purpose LDOs, 3 dedicated LDOs, and 5 BUCKs. All
of them come with support to either ECO (idle) or sleep mode.

config REGULATOR_HI655X
tristate "Hisilicon HI655X PMIC regulators support"
depends on ARCH_HISI || COMPILE_TEST
depends on MFD_HI655X_PMIC && OF
help
This driver provides support for the voltage regulators of the
Hisilicon Hi655x PMIC device.

config REGULATOR_ISL9305
tristate "Intersil ISL9305 regulator"
depends on I2C
Expand Down
1 change: 1 addition & 0 deletions drivers/regulator/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o
obj-$(CONFIG_REGULATOR_HI655X) += hi655x-regulator.o
obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o
obj-$(CONFIG_REGULATOR_LM363X) += lm363x-regulator.o
Expand Down
11 changes: 11 additions & 0 deletions drivers/regulator/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1139,6 +1139,17 @@ static int set_machine_constraints(struct regulator_dev *rdev,
}
}

if (rdev->constraints->active_discharge && ops->set_active_discharge) {
bool ad_state = (rdev->constraints->active_discharge ==
REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false;

ret = ops->set_active_discharge(rdev, ad_state);
if (ret < 0) {
rdev_err(rdev, "failed to set active discharge\n");
return ret;
}
}

print_constraints(rdev);
return 0;
}
Expand Down
18 changes: 18 additions & 0 deletions drivers/regulator/fan53555.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,22 @@ static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV)
return 0;
}

static int fan53555_set_suspend_enable(struct regulator_dev *rdev)
{
struct fan53555_device_info *di = rdev_get_drvdata(rdev);

return regmap_update_bits(di->regmap, di->sleep_reg,
VSEL_BUCK_EN, VSEL_BUCK_EN);
}

static int fan53555_set_suspend_disable(struct regulator_dev *rdev)
{
struct fan53555_device_info *di = rdev_get_drvdata(rdev);

return regmap_update_bits(di->regmap, di->sleep_reg,
VSEL_BUCK_EN, 0);
}

static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct fan53555_device_info *di = rdev_get_drvdata(rdev);
Expand Down Expand Up @@ -192,6 +208,8 @@ static struct regulator_ops fan53555_regulator_ops = {
.set_mode = fan53555_set_mode,
.get_mode = fan53555_get_mode,
.set_ramp_delay = fan53555_set_ramp,
.set_suspend_enable = fan53555_set_suspend_enable,
.set_suspend_disable = fan53555_set_suspend_disable,
};

static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di)
Expand Down
6 changes: 4 additions & 2 deletions drivers/regulator/gpio-regulator.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,10 @@ static int gpio_regulator_probe(struct platform_device *pdev)
drvdata->nr_gpios = config->nr_gpios;
ret = gpio_request_array(drvdata->gpios, drvdata->nr_gpios);
if (ret) {
dev_err(&pdev->dev,
"Could not obtain regulator setting GPIOs: %d\n", ret);
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev,
"Could not obtain regulator setting GPIOs: %d\n",
ret);
goto err_memstate;
}
}
Expand Down
23 changes: 23 additions & 0 deletions drivers/regulator/helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,3 +465,26 @@ int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable)
return 0;
}
EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap);

/**
* regulator_set_active_discharge_regmap - Default set_active_discharge()
* using regmap
*
* @rdev: device to operate on.
* @enable: state to set, 0 to disable and 1 to enable.
*/
int regulator_set_active_discharge_regmap(struct regulator_dev *rdev,
bool enable)
{
unsigned int val;

if (enable)
val = rdev->desc->active_discharge_on;
else
val = rdev->desc->active_discharge_off;

return regmap_update_bits(rdev->regmap,
rdev->desc->active_discharge_reg,
rdev->desc->active_discharge_mask, val);
}
EXPORT_SYMBOL_GPL(regulator_set_active_discharge_regmap);
227 changes: 227 additions & 0 deletions drivers/regulator/hi655x-regulator.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
/*
* Device driver for regulators in Hi655x IC
*
* Copyright (c) 2016 Hisilicon.
*
* Authors:
* Chen Feng <puck.chen@hisilicon.com>
* Fei Wang <w.f@huawei.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/

#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include <linux/mfd/hi655x-pmic.h>

struct hi655x_regulator {
unsigned int disable_reg;
unsigned int status_reg;
unsigned int ctrl_regs;
unsigned int ctrl_mask;
struct regulator_desc rdesc;
};

/* LDO7 & LDO10 */
static const unsigned int ldo7_voltages[] = {
1800000, 1850000, 2850000, 2900000,
3000000, 3100000, 3200000, 3300000,
};

static const unsigned int ldo19_voltages[] = {
1800000, 1850000, 1900000, 1750000,
2800000, 2850000, 2900000, 3000000,
};

static const unsigned int ldo22_voltages[] = {
900000, 1000000, 1050000, 1100000,
1150000, 1175000, 1185000, 1200000,
};

enum hi655x_regulator_id {
HI655X_LDO0,
HI655X_LDO1,
HI655X_LDO2,
HI655X_LDO3,
HI655X_LDO4,
HI655X_LDO5,
HI655X_LDO6,
HI655X_LDO7,
HI655X_LDO8,
HI655X_LDO9,
HI655X_LDO10,
HI655X_LDO11,
HI655X_LDO12,
HI655X_LDO13,
HI655X_LDO14,
HI655X_LDO15,
HI655X_LDO16,
HI655X_LDO17,
HI655X_LDO18,
HI655X_LDO19,
HI655X_LDO20,
HI655X_LDO21,
HI655X_LDO22,
};

static int hi655x_is_enabled(struct regulator_dev *rdev)
{
unsigned int value = 0;

struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);

regmap_read(rdev->regmap, regulator->status_reg, &value);
return (value & BIT(regulator->ctrl_mask));
}

static int hi655x_disable(struct regulator_dev *rdev)
{
int ret = 0;

struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);

ret = regmap_write(rdev->regmap, regulator->disable_reg,
BIT(regulator->ctrl_mask));
return ret;
}

static struct regulator_ops hi655x_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = hi655x_disable,
.is_enabled = hi655x_is_enabled,
.list_voltage = regulator_list_voltage_table,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
};

static struct regulator_ops hi655x_ldo_linear_ops = {
.enable = regulator_enable_regmap,
.disable = hi655x_disable,
.is_enabled = hi655x_is_enabled,
.list_voltage = regulator_list_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
};

#define HI655X_LDO(_ID, vreg, vmask, ereg, dreg, \
sreg, cmask, vtable) { \
.rdesc = { \
.name = #_ID, \
.of_match = of_match_ptr(#_ID), \
.ops = &hi655x_regulator_ops, \
.regulators_node = of_match_ptr("regulators"), \
.type = REGULATOR_VOLTAGE, \
.id = HI655X_##_ID, \
.owner = THIS_MODULE, \
.n_voltages = ARRAY_SIZE(vtable), \
.volt_table = vtable, \
.vsel_reg = HI655X_BUS_ADDR(vreg), \
.vsel_mask = vmask, \
.enable_reg = HI655X_BUS_ADDR(ereg), \
.enable_mask = BIT(cmask), \
}, \
.disable_reg = HI655X_BUS_ADDR(dreg), \
.status_reg = HI655X_BUS_ADDR(sreg), \
.ctrl_mask = cmask, \
}

#define HI655X_LDO_LINEAR(_ID, vreg, vmask, ereg, dreg, \
sreg, cmask, minv, nvolt, vstep) { \
.rdesc = { \
.name = #_ID, \
.of_match = of_match_ptr(#_ID), \
.ops = &hi655x_ldo_linear_ops, \
.regulators_node = of_match_ptr("regulators"), \
.type = REGULATOR_VOLTAGE, \
.id = HI655X_##_ID, \
.owner = THIS_MODULE, \
.min_uV = minv, \
.n_voltages = nvolt, \
.uV_step = vstep, \
.vsel_reg = HI655X_BUS_ADDR(vreg), \
.vsel_mask = vmask, \
.enable_reg = HI655X_BUS_ADDR(ereg), \
.enable_mask = BIT(cmask), \
}, \
.disable_reg = HI655X_BUS_ADDR(dreg), \
.status_reg = HI655X_BUS_ADDR(sreg), \
.ctrl_mask = cmask, \
}

static struct hi655x_regulator regulators[] = {
HI655X_LDO_LINEAR(LDO2, 0x72, 0x07, 0x29, 0x2a, 0x2b, 0x01,
2500000, 8, 100000),
HI655X_LDO(LDO7, 0x78, 0x07, 0x29, 0x2a, 0x2b, 0x06, ldo7_voltages),
HI655X_LDO(LDO10, 0x78, 0x07, 0x29, 0x2a, 0x2b, 0x01, ldo7_voltages),
HI655X_LDO_LINEAR(LDO13, 0x7e, 0x07, 0x2c, 0x2d, 0x2e, 0x04,
1600000, 8, 50000),
HI655X_LDO_LINEAR(LDO14, 0x7f, 0x07, 0x2c, 0x2d, 0x2e, 0x05,
2500000, 8, 100000),
HI655X_LDO_LINEAR(LDO15, 0x80, 0x07, 0x2c, 0x2d, 0x2e, 0x06,
1600000, 8, 50000),
HI655X_LDO_LINEAR(LDO17, 0x82, 0x07, 0x2f, 0x30, 0x31, 0x00,
2500000, 8, 100000),
HI655X_LDO(LDO19, 0x84, 0x07, 0x2f, 0x30, 0x31, 0x02, ldo19_voltages),
HI655X_LDO_LINEAR(LDO21, 0x86, 0x07, 0x2f, 0x30, 0x31, 0x04,
1650000, 8, 50000),
HI655X_LDO(LDO22, 0x87, 0x07, 0x2f, 0x30, 0x31, 0x05, ldo22_voltages),
};

static int hi655x_regulator_probe(struct platform_device *pdev)
{
unsigned int i;
struct hi655x_regulator *regulator;
struct hi655x_pmic *pmic;
struct regulator_config config = { };
struct regulator_dev *rdev;

pmic = dev_get_drvdata(pdev->dev.parent);
if (!pmic) {
dev_err(&pdev->dev, "no pmic in the regulator parent node\n");
return -ENODEV;
}

regulator = devm_kzalloc(&pdev->dev, sizeof(*regulator), GFP_KERNEL);
if (!regulator)
return -ENOMEM;

platform_set_drvdata(pdev, regulator);

config.dev = pdev->dev.parent;
config.regmap = pmic->regmap;
config.driver_data = regulator;
for (i = 0; i < ARRAY_SIZE(regulators); i++) {
rdev = devm_regulator_register(&pdev->dev,
&regulators[i].rdesc,
&config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
regulator->rdesc.name);
return PTR_ERR(rdev);
}
}
return 0;
}

static struct platform_driver hi655x_regulator_driver = {
.driver = {
.name = "hi655x-regulator",
},
.probe = hi655x_regulator_probe,
};
module_platform_driver(hi655x_regulator_driver);

MODULE_AUTHOR("Chen Feng <puck.chen@hisilicon.com>");
MODULE_DESCRIPTION("Hisilicon Hi655x regulator driver");
MODULE_LICENSE("GPL v2");
Loading

0 comments on commit d1f8302

Please sign in to comment.