summaryrefslogtreecommitdiff
path: root/drivers/regulator
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-06-10 05:30:17 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-06-10 05:30:17 -0300
commitd635711daa98be86d4c7fd01499c34f566b54ccb (patch)
treeaa5cc3760a27c3d57146498cb82fa549547de06c /drivers/regulator
parentc91265cd0efb83778f015b4d4b1129bd2cfd075e (diff)
Linux-libre 4.6.2-gnu
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/Kconfig28
-rw-r--r--drivers/regulator/Makefile9
-rw-r--r--drivers/regulator/act8865-regulator.c8
-rw-r--r--drivers/regulator/act8945a-regulator.c165
-rw-r--r--drivers/regulator/ad5398.c6
-rw-r--r--drivers/regulator/axp20x-regulator.c69
-rw-r--r--drivers/regulator/core.c92
-rw-r--r--drivers/regulator/da9063-regulator.c2
-rw-r--r--drivers/regulator/da9210-regulator.c5
-rw-r--r--drivers/regulator/fan53555.c18
-rw-r--r--drivers/regulator/gpio-regulator.c8
-rw-r--r--drivers/regulator/helpers.c23
-rw-r--r--drivers/regulator/hi655x-regulator.c227
-rw-r--r--drivers/regulator/lp872x.c38
-rw-r--r--drivers/regulator/ltc3589.c15
-rw-r--r--drivers/regulator/max77620-regulator.c813
-rw-r--r--drivers/regulator/max77686-regulator.c (renamed from drivers/regulator/max77686.c)0
-rw-r--r--drivers/regulator/max77802-regulator.c (renamed from drivers/regulator/max77802.c)0
-rw-r--r--drivers/regulator/mt6397-regulator.c15
-rw-r--r--drivers/regulator/of_regulator.c21
-rw-r--r--drivers/regulator/pv88060-regulator.c8
-rw-r--r--drivers/regulator/pv88090-regulator.c8
-rw-r--r--drivers/regulator/pwm-regulator.c29
-rw-r--r--drivers/regulator/s2mps11.c71
-rw-r--r--drivers/regulator/tps65912-regulator.c613
-rw-r--r--drivers/regulator/vexpress-regulator.c (renamed from drivers/regulator/vexpress.c)0
26 files changed, 1660 insertions, 631 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 8155e80dd..c77dc08b1 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -78,6 +78,15 @@ config REGULATOR_ACT8865
This driver controls a active-semi act8865 voltage output
regulator via I2C bus.
+config REGULATOR_ACT8945A
+ tristate "Active-semi ACT8945A voltage regulator"
+ depends on MFD_ACT8945A
+ help
+ This driver controls a active-semi ACT8945A voltage regulator
+ via I2C bus. The ACT8945A features three step-down DC/DC converters
+ and four low-dropout linear regulators, along with a ActivePath
+ battery charger.
+
config REGULATOR_AD5398
tristate "Analog Devices AD5398/AD5821 regulators"
depends on I2C
@@ -261,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
@@ -343,6 +360,15 @@ config REGULATOR_MAX1586
regulator via I2C bus. The provided regulator is suitable
for PXA27x chips to control VCC_CORE and VCC_USIM voltages.
+config REGULATOR_MAX77620
+ tristate "Maxim 77620/MAX20024 voltage regulator"
+ depends on MFD_MAX77620
+ help
+ This driver controls Maxim MAX77620 voltage output regulator
+ via I2C bus. The provided regulator is suitable for Tegra
+ chip to control Step-Down DC-DC and LDOs. Say Y here to
+ enable the regulator driver.
+
config REGULATOR_MAX8649
tristate "Maxim 8649 voltage regulator"
depends on I2C
@@ -762,7 +788,7 @@ config REGULATOR_TPS65910
config REGULATOR_TPS65912
tristate "TI TPS65912 Power regulator"
- depends on (MFD_TPS65912_I2C || MFD_TPS65912_SPI)
+ depends on MFD_TPS65912
help
This driver supports TPS65912 voltage regulator chip.
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 980b1943f..61bfbb9d4 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
obj-$(CONFIG_REGULATOR_AB8500) += ab8500-ext.o ab8500.o
obj-$(CONFIG_REGULATOR_ACT8865) += act8865-regulator.o
+obj-$(CONFIG_REGULATOR_ACT8945A) += act8945a-regulator.o
obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
@@ -34,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
@@ -46,6 +48,7 @@ obj-$(CONFIG_REGULATOR_LP8755) += lp8755.o
obj-$(CONFIG_REGULATOR_LTC3589) += ltc3589.o
obj-$(CONFIG_REGULATOR_MAX14577) += max14577.o
obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
+obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o
obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o
obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
obj-$(CONFIG_REGULATOR_MAX8907) += max8907-regulator.o
@@ -54,9 +57,9 @@ obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o
obj-$(CONFIG_REGULATOR_MAX8973) += max8973-regulator.o
obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o
obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
-obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o
+obj-$(CONFIG_REGULATOR_MAX77686) += max77686-regulator.o
obj-$(CONFIG_REGULATOR_MAX77693) += max77693.o
-obj-$(CONFIG_REGULATOR_MAX77802) += max77802.o
+obj-$(CONFIG_REGULATOR_MAX77802) += max77802-regulator.o
obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
@@ -98,7 +101,7 @@ obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o
obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
-obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress.o
+obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c
index f8d4cd3d1..000d566e3 100644
--- a/drivers/regulator/act8865-regulator.c
+++ b/drivers/regulator/act8865-regulator.c
@@ -218,7 +218,7 @@ static const struct regulator_desc act8600_regulators[] = {
.ops = &act8865_ldo_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = 1,
- .fixed_uV = 1800000,
+ .fixed_uV = 3300000,
.enable_reg = ACT8600_LDO910_CTRL,
.enable_mask = ACT8865_ENA,
.owner = THIS_MODULE,
@@ -369,7 +369,7 @@ static int act8865_pdata_from_dt(struct device *dev,
for (i = 0; i < num_matches; i++) {
regulator->id = i;
regulator->name = matches[i].name;
- regulator->platform_data = matches[i].init_data;
+ regulator->init_data = matches[i].init_data;
of_node[i] = matches[i].of_node;
regulator++;
}
@@ -396,7 +396,7 @@ static struct regulator_init_data
for (i = 0; i < pdata->num_regulators; i++) {
if (pdata->regulators[i].id == id)
- return pdata->regulators[i].platform_data;
+ return pdata->regulators[i].init_data;
}
return NULL;
@@ -415,7 +415,7 @@ static void act8865_power_off(void)
static int act8865_pmic_probe(struct i2c_client *client,
const struct i2c_device_id *i2c_id)
{
- static const struct regulator_desc *regulators;
+ const struct regulator_desc *regulators;
struct act8865_platform_data pdata_of, *pdata;
struct device *dev = &client->dev;
struct device_node **of_node;
diff --git a/drivers/regulator/act8945a-regulator.c b/drivers/regulator/act8945a-regulator.c
new file mode 100644
index 000000000..441864b9f
--- /dev/null
+++ b/drivers/regulator/act8945a-regulator.c
@@ -0,0 +1,165 @@
+/*
+ * Voltage regulation driver for active-semi ACT8945A PMIC
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Wenyou Yang <wenyou.yang@atmel.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/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+/**
+ * ACT8945A Global Register Map.
+ */
+#define ACT8945A_SYS_MODE 0x00
+#define ACT8945A_SYS_CTRL 0x01
+#define ACT8945A_DCDC1_VSET1 0x20
+#define ACT8945A_DCDC1_VSET2 0x21
+#define ACT8945A_DCDC1_CTRL 0x22
+#define ACT8945A_DCDC2_VSET1 0x30
+#define ACT8945A_DCDC2_VSET2 0x31
+#define ACT8945A_DCDC2_CTRL 0x32
+#define ACT8945A_DCDC3_VSET1 0x40
+#define ACT8945A_DCDC3_VSET2 0x41
+#define ACT8945A_DCDC3_CTRL 0x42
+#define ACT8945A_LDO1_VSET 0x50
+#define ACT8945A_LDO1_CTRL 0x51
+#define ACT8945A_LDO2_VSET 0x54
+#define ACT8945A_LDO2_CTRL 0x55
+#define ACT8945A_LDO3_VSET 0x60
+#define ACT8945A_LDO3_CTRL 0x61
+#define ACT8945A_LDO4_VSET 0x64
+#define ACT8945A_LDO4_CTRL 0x65
+
+/**
+ * Field Definitions.
+ */
+#define ACT8945A_ENA 0x80 /* ON - [7] */
+#define ACT8945A_VSEL_MASK 0x3F /* VSET - [5:0] */
+
+/**
+ * ACT8945A Voltage Number
+ */
+#define ACT8945A_VOLTAGE_NUM 64
+
+enum {
+ ACT8945A_ID_DCDC1,
+ ACT8945A_ID_DCDC2,
+ ACT8945A_ID_DCDC3,
+ ACT8945A_ID_LDO1,
+ ACT8945A_ID_LDO2,
+ ACT8945A_ID_LDO3,
+ ACT8945A_ID_LDO4,
+ ACT8945A_REG_NUM,
+};
+
+static const struct regulator_linear_range act8945a_voltage_ranges[] = {
+ REGULATOR_LINEAR_RANGE(600000, 0, 23, 25000),
+ REGULATOR_LINEAR_RANGE(1200000, 24, 47, 50000),
+ REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000),
+};
+
+static struct regulator_ops act8945a_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
+#define ACT89xx_REG(_name, _family, _id, _vsel_reg, _supply) \
+ [_family##_ID_##_id] = { \
+ .name = _name, \
+ .supply_name = _supply, \
+ .of_match = of_match_ptr("REG_"#_id), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .id = _family##_ID_##_id, \
+ .type = REGULATOR_VOLTAGE, \
+ .ops = &act8945a_ops, \
+ .n_voltages = ACT8945A_VOLTAGE_NUM, \
+ .linear_ranges = act8945a_voltage_ranges, \
+ .n_linear_ranges = ARRAY_SIZE(act8945a_voltage_ranges), \
+ .vsel_reg = _family##_##_id##_##_vsel_reg, \
+ .vsel_mask = ACT8945A_VSEL_MASK, \
+ .enable_reg = _family##_##_id##_CTRL, \
+ .enable_mask = ACT8945A_ENA, \
+ .owner = THIS_MODULE, \
+ }
+
+static const struct regulator_desc act8945a_regulators[] = {
+ ACT89xx_REG("DCDC_REG1", ACT8945A, DCDC1, VSET1, "vp1"),
+ ACT89xx_REG("DCDC_REG2", ACT8945A, DCDC2, VSET1, "vp2"),
+ ACT89xx_REG("DCDC_REG3", ACT8945A, DCDC3, VSET1, "vp3"),
+ ACT89xx_REG("LDO_REG1", ACT8945A, LDO1, VSET, "inl45"),
+ ACT89xx_REG("LDO_REG2", ACT8945A, LDO2, VSET, "inl45"),
+ ACT89xx_REG("LDO_REG3", ACT8945A, LDO3, VSET, "inl67"),
+ ACT89xx_REG("LDO_REG4", ACT8945A, LDO4, VSET, "inl67"),
+};
+
+static const struct regulator_desc act8945a_alt_regulators[] = {
+ ACT89xx_REG("DCDC_REG1", ACT8945A, DCDC1, VSET2, "vp1"),
+ ACT89xx_REG("DCDC_REG2", ACT8945A, DCDC2, VSET2, "vp2"),
+ ACT89xx_REG("DCDC_REG3", ACT8945A, DCDC3, VSET2, "vp3"),
+ ACT89xx_REG("LDO_REG1", ACT8945A, LDO1, VSET, "inl45"),
+ ACT89xx_REG("LDO_REG2", ACT8945A, LDO2, VSET, "inl45"),
+ ACT89xx_REG("LDO_REG3", ACT8945A, LDO3, VSET, "inl67"),
+ ACT89xx_REG("LDO_REG4", ACT8945A, LDO4, VSET, "inl67"),
+};
+
+static int act8945a_pmic_probe(struct platform_device *pdev)
+{
+ struct regulator_config config = { };
+ const struct regulator_desc *regulators;
+ struct regulator_dev *rdev;
+ int i, num_regulators;
+ bool voltage_select;
+
+ voltage_select = of_property_read_bool(pdev->dev.parent->of_node,
+ "active-semi,vsel-high");
+
+ if (voltage_select) {
+ regulators = act8945a_alt_regulators;
+ num_regulators = ARRAY_SIZE(act8945a_alt_regulators);
+ } else {
+ regulators = act8945a_regulators;
+ num_regulators = ARRAY_SIZE(act8945a_regulators);
+ }
+
+ config.dev = &pdev->dev;
+ config.dev->of_node = pdev->dev.parent->of_node;
+ for (i = 0; i < num_regulators; i++) {
+ rdev = devm_regulator_register(&pdev->dev, &regulators[i], &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev,
+ "failed to register %s regulator\n",
+ regulators[i].name);
+ return PTR_ERR(rdev);
+ }
+ }
+
+ return 0;
+}
+
+static struct platform_driver act8945a_pmic_driver = {
+ .driver = {
+ .name = "act8945a-regulator",
+ },
+ .probe = act8945a_pmic_probe,
+};
+module_platform_driver(act8945a_pmic_driver);
+
+MODULE_DESCRIPTION("Active-semi ACT8945A voltage regulator driver");
+MODULE_AUTHOR("Wenyou Yang <wenyou.yang@atmel.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c
index ea50a886b..8b0f788a9 100644
--- a/drivers/regulator/ad5398.c
+++ b/drivers/regulator/ad5398.c
@@ -58,10 +58,12 @@ static int ad5398_write_reg(struct i2c_client *client, const unsigned short data
val = cpu_to_be16(data);
ret = i2c_master_send(client, (char *)&val, 2);
- if (ret < 0)
+ if (ret != 2) {
dev_err(&client->dev, "I2C write error\n");
+ return ret < 0 ? ret : -EIO;
+ }
- return ret;
+ return 0;
}
static int ad5398_get_current_limit(struct regulator_dev *rdev)
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index f2e1a39ce..514a5e8fd 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -39,7 +39,7 @@
#define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
_vmask, _ereg, _emask, _enable_val, _disable_val) \
[_family##_##_id] = { \
- .name = #_id, \
+ .name = (_match), \
.supply_name = (_supply), \
.of_match = of_match_ptr(_match), \
.regulators_node = of_match_ptr("regulators"), \
@@ -61,7 +61,7 @@
#define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
_vmask, _ereg, _emask) \
[_family##_##_id] = { \
- .name = #_id, \
+ .name = (_match), \
.supply_name = (_supply), \
.of_match = of_match_ptr(_match), \
.regulators_node = of_match_ptr("regulators"), \
@@ -78,21 +78,15 @@
.ops = &axp20x_ops, \
}
-#define AXP_DESC_SW(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
- _vmask, _ereg, _emask) \
+#define AXP_DESC_SW(_family, _id, _match, _supply, _ereg, _emask) \
[_family##_##_id] = { \
- .name = #_id, \
+ .name = (_match), \
.supply_name = (_supply), \
.of_match = of_match_ptr(_match), \
.regulators_node = of_match_ptr("regulators"), \
.type = REGULATOR_VOLTAGE, \
.id = _family##_##_id, \
- .n_voltages = (((_max) - (_min)) / (_step) + 1), \
.owner = THIS_MODULE, \
- .min_uV = (_min) * 1000, \
- .uV_step = (_step) * 1000, \
- .vsel_reg = (_vreg), \
- .vsel_mask = (_vmask), \
.enable_reg = (_ereg), \
.enable_mask = (_emask), \
.ops = &axp20x_ops_sw, \
@@ -100,7 +94,7 @@
#define AXP_DESC_FIXED(_family, _id, _match, _supply, _volt) \
[_family##_##_id] = { \
- .name = #_id, \
+ .name = (_match), \
.supply_name = (_supply), \
.of_match = of_match_ptr(_match), \
.regulators_node = of_match_ptr("regulators"), \
@@ -112,39 +106,34 @@
.ops = &axp20x_ops_fixed \
}
-#define AXP_DESC_TABLE(_family, _id, _match, _supply, _table, _vreg, _vmask, \
- _ereg, _emask) \
+#define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages, \
+ _vreg, _vmask, _ereg, _emask) \
[_family##_##_id] = { \
- .name = #_id, \
+ .name = (_match), \
.supply_name = (_supply), \
.of_match = of_match_ptr(_match), \
.regulators_node = of_match_ptr("regulators"), \
.type = REGULATOR_VOLTAGE, \
.id = _family##_##_id, \
- .n_voltages = ARRAY_SIZE(_table), \
+ .n_voltages = (_n_voltages), \
.owner = THIS_MODULE, \
.vsel_reg = (_vreg), \
.vsel_mask = (_vmask), \
.enable_reg = (_ereg), \
.enable_mask = (_emask), \
- .volt_table = (_table), \
- .ops = &axp20x_ops_table, \
+ .linear_ranges = (_ranges), \
+ .n_linear_ranges = ARRAY_SIZE(_ranges), \
+ .ops = &axp20x_ops_range, \
}
-static const int axp20x_ldo4_data[] = { 1250000, 1300000, 1400000, 1500000, 1600000,
- 1700000, 1800000, 1900000, 2000000, 2500000,
- 2700000, 2800000, 3000000, 3100000, 3200000,
- 3300000 };
-
static struct regulator_ops axp20x_ops_fixed = {
.list_voltage = regulator_list_voltage_linear,
};
-static struct regulator_ops axp20x_ops_table = {
+static struct regulator_ops axp20x_ops_range = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
- .list_voltage = regulator_list_voltage_table,
- .map_voltage = regulator_map_voltage_ascend,
+ .list_voltage = regulator_list_voltage_linear_range,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -160,13 +149,19 @@ static struct regulator_ops axp20x_ops = {
};
static struct regulator_ops axp20x_ops_sw = {
- .get_voltage_sel = regulator_get_voltage_sel_regmap,
- .list_voltage = regulator_list_voltage_linear,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
};
+static const struct regulator_linear_range axp20x_ldo4_ranges[] = {
+ REGULATOR_LINEAR_RANGE(1250000, 0x0, 0x0, 0),
+ REGULATOR_LINEAR_RANGE(1300000, 0x1, 0x8, 100000),
+ REGULATOR_LINEAR_RANGE(2500000, 0x9, 0x9, 0),
+ REGULATOR_LINEAR_RANGE(2700000, 0xa, 0xb, 100000),
+ REGULATOR_LINEAR_RANGE(3000000, 0xc, 0xf, 100000),
+};
+
static const struct regulator_desc axp20x_regulators[] = {
AXP_DESC(AXP20X, DCDC2, "dcdc2", "vin2", 700, 2275, 25,
AXP20X_DCDC2_V_OUT, 0x3f, AXP20X_PWR_OUT_CTRL, 0x10),
@@ -177,8 +172,9 @@ static const struct regulator_desc axp20x_regulators[] = {
AXP20X_LDO24_V_OUT, 0xf0, AXP20X_PWR_OUT_CTRL, 0x04),
AXP_DESC(AXP20X, LDO3, "ldo3", "ldo3in", 700, 3500, 25,
AXP20X_LDO3_V_OUT, 0x7f, AXP20X_PWR_OUT_CTRL, 0x40),
- AXP_DESC_TABLE(AXP20X, LDO4, "ldo4", "ldo24in", axp20x_ldo4_data,
- AXP20X_LDO24_V_OUT, 0x0f, AXP20X_PWR_OUT_CTRL, 0x08),
+ AXP_DESC_RANGES(AXP20X, LDO4, "ldo4", "ldo24in", axp20x_ldo4_ranges,
+ 16, AXP20X_LDO24_V_OUT, 0x0f, AXP20X_PWR_OUT_CTRL,
+ 0x08),
AXP_DESC_IO(AXP20X, LDO5, "ldo5", "ldo5in", 1800, 3300, 100,
AXP20X_LDO5_V_OUT, 0xf0, AXP20X_GPIO0_CTRL, 0x07,
AXP20X_IO_ENABLED, AXP20X_IO_DISABLED),
@@ -196,8 +192,8 @@ static const struct regulator_desc axp22x_regulators[] = {
AXP_DESC(AXP22X, DCDC5, "dcdc5", "vin5", 1000, 2550, 50,
AXP22X_DCDC5_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(5)),
/* secondary switchable output of DCDC1 */
- AXP_DESC_SW(AXP22X, DC1SW, "dc1sw", NULL, 1600, 3400, 100,
- AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(7)),
+ AXP_DESC_SW(AXP22X, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
+ BIT(7)),
/* LDO regulator internally chained to DCDC5 */
AXP_DESC(AXP22X, DC5LDO, "dc5ldo", NULL, 700, 1400, 100,
AXP22X_DC5LDO_V_OUT, 0x7, AXP22X_PWR_OUT_CTRL1, BIT(0)),
@@ -221,10 +217,14 @@ static const struct regulator_desc axp22x_regulators[] = {
AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
AXP_DESC(AXP22X, ELDO3, "eldo3", "eldoin", 700, 3300, 100,
AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
- AXP_DESC_IO(AXP22X, LDO_IO0, "ldo_io0", "ips", 1800, 3300, 100,
+ /* Note the datasheet only guarantees reliable operation up to
+ * 3.3V, this needs to be enforced via dts provided constraints */
+ AXP_DESC_IO(AXP22X, LDO_IO0, "ldo_io0", "ips", 700, 3800, 100,
AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
- AXP_DESC_IO(AXP22X, LDO_IO1, "ldo_io1", "ips", 1800, 3300, 100,
+ /* Note the datasheet only guarantees reliable operation up to
+ * 3.3V, this needs to be enforced via dts provided constraints */
+ AXP_DESC_IO(AXP22X, LDO_IO1, "ldo_io1", "ips", 700, 3800, 100,
AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000),
@@ -244,6 +244,7 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
step = 75;
break;
case AXP221_ID:
+ case AXP223_ID:
min = 1800;
max = 4050;
def = 3000;
@@ -322,6 +323,7 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work
break;
case AXP221_ID:
+ case AXP223_ID:
if (id < AXP22X_DCDC1 || id > AXP22X_DCDC5)
return -EINVAL;
@@ -360,6 +362,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
nregulators = AXP20X_REG_ID_MAX;
break;
case AXP221_ID:
+ case AXP223_ID:
regulators = axp22x_regulators;
nregulators = AXP22X_REG_ID_MAX;
break;
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 744c9889f..fd0e4e37f 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1057,18 +1057,18 @@ static int set_machine_constraints(struct regulator_dev *rdev,
ret = machine_constraints_voltage(rdev, rdev->constraints);
if (ret != 0)
- goto out;
+ return ret;
ret = machine_constraints_current(rdev, rdev->constraints);
if (ret != 0)
- goto out;
+ return ret;
if (rdev->constraints->ilim_uA && ops->set_input_current_limit) {
ret = ops->set_input_current_limit(rdev,
rdev->constraints->ilim_uA);
if (ret < 0) {
rdev_err(rdev, "failed to set input limit\n");
- goto out;
+ return ret;
}
}
@@ -1077,21 +1077,20 @@ static int set_machine_constraints(struct regulator_dev *rdev,
ret = suspend_prepare(rdev, rdev->constraints->initial_state);
if (ret < 0) {
rdev_err(rdev, "failed to set suspend state\n");
- goto out;
+ return ret;
}
}
if (rdev->constraints->initial_mode) {
if (!ops->set_mode) {
rdev_err(rdev, "no set_mode operation\n");
- ret = -EINVAL;
- goto out;
+ return -EINVAL;
}
ret = ops->set_mode(rdev, rdev->constraints->initial_mode);
if (ret < 0) {
rdev_err(rdev, "failed to set initial mode: %d\n", ret);
- goto out;
+ return ret;
}
}
@@ -1102,7 +1101,7 @@ static int set_machine_constraints(struct regulator_dev *rdev,
ret = _regulator_do_enable(rdev);
if (ret < 0 && ret != -EINVAL) {
rdev_err(rdev, "failed to enable\n");
- goto out;
+ return ret;
}
}
@@ -1111,7 +1110,7 @@ static int set_machine_constraints(struct regulator_dev *rdev,
ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay);
if (ret < 0) {
rdev_err(rdev, "failed to set ramp_delay\n");
- goto out;
+ return ret;
}
}
@@ -1119,7 +1118,7 @@ static int set_machine_constraints(struct regulator_dev *rdev,
ret = ops->set_pull_down(rdev);
if (ret < 0) {
rdev_err(rdev, "failed to set pull down\n");
- goto out;
+ return ret;
}
}
@@ -1127,7 +1126,7 @@ static int set_machine_constraints(struct regulator_dev *rdev,
ret = ops->set_soft_start(rdev);
if (ret < 0) {
rdev_err(rdev, "failed to set soft start\n");
- goto out;
+ return ret;
}
}
@@ -1136,16 +1135,34 @@ static int set_machine_constraints(struct regulator_dev *rdev,
ret = ops->set_over_current_protection(rdev);
if (ret < 0) {
rdev_err(rdev, "failed to set over current protection\n");
- goto out;
+ return ret;
+ }
+ }
+
+ 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;
+ }
+ }
+
+ 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;
-out:
- kfree(rdev->constraints);
- rdev->constraints = NULL;
- return ret;
}
/**
@@ -3823,6 +3840,11 @@ static void rdev_init_debugfs(struct regulator_dev *rdev)
&rdev->bypass_count);
}
+static int regulator_register_resolve_supply(struct device *dev, void *data)
+{
+ return regulator_resolve_supply(dev_to_rdev(dev));
+}
+
/**
* regulator_register - register regulator
* @regulator_desc: regulator to register
@@ -3918,6 +3940,16 @@ regulator_register(const struct regulator_desc *regulator_desc,
goto clean;
}
+ if ((config->ena_gpio || config->ena_gpio_initialized) &&
+ gpio_is_valid(config->ena_gpio)) {
+ ret = regulator_ena_gpio_request(rdev, config);
+ if (ret != 0) {
+ rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
+ config->ena_gpio, ret);
+ goto clean;
+ }
+ }
+
/* register with sysfs */
rdev->dev.class = &regulator_class;
rdev->dev.parent = dev;
@@ -3926,21 +3958,11 @@ regulator_register(const struct regulator_desc *regulator_desc,
ret = device_register(&rdev->dev);
if (ret != 0) {
put_device(&rdev->dev);
- goto clean;
+ goto wash;
}
dev_set_drvdata(&rdev->dev, rdev);
- if ((config->ena_gpio || config->ena_gpio_initialized) &&
- gpio_is_valid(config->ena_gpio)) {
- ret = regulator_ena_gpio_request(rdev, config);
- if (ret != 0) {
- rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
- config->ena_gpio, ret);
- goto wash;
- }
- }
-
/* set regulator constraints */
if (init_data)
constraints = &init_data->constraints;
@@ -3969,8 +3991,11 @@ regulator_register(const struct regulator_desc *regulator_desc,
}
rdev_init_debugfs(rdev);
-out:
mutex_unlock(&regulator_list_mutex);
+
+ /* try to resolve regulators supply since a new one was registered */
+ class_for_each_device(&regulator_class, NULL, NULL,
+ regulator_register_resolve_supply);
kfree(config);
return rdev;
@@ -3979,17 +4004,18 @@ unset_supplies:
scrub:
regulator_ena_gpio_free(rdev);
- kfree(rdev->constraints);
-wash:
device_unregister(&rdev->dev);
/* device core frees rdev */
- rdev = ERR_PTR(ret);
goto out;
+wash:
+ regulator_ena_gpio_free(rdev);
clean:
kfree(rdev);
- rdev = ERR_PTR(ret);
- goto out;
+out:
+ mutex_unlock(&regulator_list_mutex);
+ kfree(config);
+ return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(regulator_register);
diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c
index ed9e7e96f..c6af343f5 100644
--- a/drivers/regulator/da9063-regulator.c
+++ b/drivers/regulator/da9063-regulator.c
@@ -900,4 +900,4 @@ module_exit(da9063_regulator_cleanup);
MODULE_AUTHOR("Krystian Garbaciak <krystian.garbaciak@diasemi.com>");
MODULE_DESCRIPTION("DA9063 regulators driver");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("paltform:" DA9063_DRVNAME_REGULATORS);
+MODULE_ALIAS("platform:" DA9063_DRVNAME_REGULATORS);
diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c
index 8b3cc9f0c..01c0e3709 100644
--- a/drivers/regulator/da9210-regulator.c
+++ b/drivers/regulator/da9210-regulator.c
@@ -132,6 +132,8 @@ static irqreturn_t da9210_irq_handler(int irq, void *data)
if (error < 0)
goto error_i2c;
+ mutex_lock(&chip->rdev->mutex);
+
if (val & DA9210_E_OVCURR) {
regulator_notifier_call_chain(chip->rdev,
REGULATOR_EVENT_OVER_CURRENT,
@@ -155,6 +157,9 @@ static irqreturn_t da9210_irq_handler(int irq, void *data)
NULL);
handled |= DA9210_E_VMAX;
}
+
+ mutex_unlock(&chip->rdev->mutex);
+
if (handled) {
/* Clear handled events */
error = regmap_write(chip->regmap, DA9210_REG_EVENT_B, handled);
diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
index 4940e8287..2cb5cc311 100644
--- a/drivers/regulator/fan53555.c
+++ b/drivers/regulator/fan53555.c
@@ -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);
@@ -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)
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
index 7bba8b747..83e89e5d4 100644
--- a/drivers/regulator/gpio-regulator.c
+++ b/drivers/regulator/gpio-regulator.c
@@ -162,6 +162,8 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np,
of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0);
+ if (config->enable_gpio == -EPROBE_DEFER)
+ return ERR_PTR(-EPROBE_DEFER);
/* Fetch GPIOs. - optional property*/
ret = of_gpio_count(np);
@@ -283,8 +285,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;
}
}
diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
index 3bbb32680..b1e32e748 100644
--- a/drivers/regulator/helpers.c
+++ b/drivers/regulator/helpers.c
@@ -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);
diff --git a/drivers/regulator/hi655x-regulator.c b/drivers/regulator/hi655x-regulator.c
new file mode 100644
index 000000000..aca18466f
--- /dev/null
+++ b/drivers/regulator/hi655x-regulator.c
@@ -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");
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index 19d758486..38992112f 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -15,6 +15,7 @@
#include <linux/regmap.h>
#include <linux/err.h>
#include <linux/gpio.h>
+#include <linux/delay.h>
#include <linux/regulator/lp872x.h>
#include <linux/regulator/driver.h>
#include <linux/platform_device.h>
@@ -738,10 +739,8 @@ static int lp872x_init_dvs(struct lp872x *lp)
goto set_default_dvs_mode;
gpio = dvs->gpio;
- if (!gpio_is_valid(gpio)) {
- dev_warn(lp->dev, "invalid gpio: %d\n", gpio);
+ if (!gpio_is_valid(gpio))
goto set_default_dvs_mode;
- }
pinstate = dvs->init_state;
ret = devm_gpio_request_one(lp->dev, gpio, pinstate, "LP872X DVS");
@@ -759,6 +758,33 @@ set_default_dvs_mode:
default_dvs_mode[lp->chipid]);
}
+static int lp872x_hw_enable(struct lp872x *lp)
+{
+ int ret, gpio;
+
+ if (!lp->pdata)
+ return -EINVAL;
+
+ gpio = lp->pdata->enable_gpio;
+ if (!gpio_is_valid(gpio))
+ return 0;
+
+ /* Always set enable GPIO high. */
+ ret = devm_gpio_request_one(lp->dev, gpio, GPIOF_OUT_INIT_HIGH, "LP872X EN");
+ if (ret) {
+ dev_err(lp->dev, "gpio request err: %d\n", ret);
+ return ret;
+ }
+
+ /* Each chip has a different enable delay. */
+ if (lp->chipid == LP8720)
+ usleep_range(LP8720_ENABLE_DELAY, 1.5 * LP8720_ENABLE_DELAY);
+ else
+ usleep_range(LP8725_ENABLE_DELAY, 1.5 * LP8725_ENABLE_DELAY);
+
+ return 0;
+}
+
static int lp872x_config(struct lp872x *lp)
{
struct lp872x_platform_data *pdata = lp->pdata;
@@ -877,6 +903,8 @@ static struct lp872x_platform_data
of_property_read_u8(np, "ti,dvs-state", &dvs_state);
pdata->dvs->init_state = dvs_state ? DVS_HIGH : DVS_LOW;
+ pdata->enable_gpio = of_get_named_gpio(np, "enable-gpios", 0);
+
if (of_get_child_count(np) == 0)
goto out;
@@ -950,6 +978,10 @@ static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
lp->chipid = id->driver_data;
i2c_set_clientdata(cl, lp);
+ ret = lp872x_hw_enable(lp);
+ if (ret)
+ return ret;
+
ret = lp872x_config(lp);
if (ret)
return ret;
diff --git a/drivers/regulator/ltc3589.c b/drivers/regulator/ltc3589.c
index 972c386b2..47bef328f 100644
--- a/drivers/regulator/ltc3589.c
+++ b/drivers/regulator/ltc3589.c
@@ -520,12 +520,15 @@ static int ltc3589_probe(struct i2c_client *client,
}
}
- ret = devm_request_threaded_irq(dev, client->irq, NULL, ltc3589_isr,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
- client->name, ltc3589);
- if (ret) {
- dev_err(dev, "Failed to request IRQ: %d\n", ret);
- return ret;
+ if (client->irq) {
+ ret = devm_request_threaded_irq(dev, client->irq, NULL,
+ ltc3589_isr,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ client->name, ltc3589);
+ if (ret) {
+ dev_err(dev, "Failed to request IRQ: %d\n", ret);
+ return ret;
+ }
}
return 0;
diff --git a/drivers/regulator/max77620-regulator.c b/drivers/regulator/max77620-regulator.c
new file mode 100644
index 000000000..73a3356a5
--- /dev/null
+++ b/drivers/regulator/max77620-regulator.c
@@ -0,0 +1,813 @@
+/*
+ * Maxim MAX77620 Regulator driver
+ *
+ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Author: Mallikarjun Kasoju <mkasoju@nvidia.com>
+ * Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/mfd/max77620.h>
+#include <linux/module.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>
+
+#define max77620_rails(_name) "max77620-"#_name
+
+/* Power Mode */
+#define MAX77620_POWER_MODE_NORMAL 3
+#define MAX77620_POWER_MODE_LPM 2
+#define MAX77620_POWER_MODE_GLPM 1
+#define MAX77620_POWER_MODE_DISABLE 0
+
+/* SD Slew Rate */
+#define MAX77620_SD_SR_13_75 0
+#define MAX77620_SD_SR_27_5 1
+#define MAX77620_SD_SR_55 2
+#define MAX77620_SD_SR_100 3
+
+enum max77620_regulators {
+ MAX77620_REGULATOR_ID_SD0,
+ MAX77620_REGULATOR_ID_SD1,
+ MAX77620_REGULATOR_ID_SD2,
+ MAX77620_REGULATOR_ID_SD3,
+ MAX77620_REGULATOR_ID_SD4,
+ MAX77620_REGULATOR_ID_LDO0,
+ MAX77620_REGULATOR_ID_LDO1,
+ MAX77620_REGULATOR_ID_LDO2,
+ MAX77620_REGULATOR_ID_LDO3,
+ MAX77620_REGULATOR_ID_LDO4,
+ MAX77620_REGULATOR_ID_LDO5,
+ MAX77620_REGULATOR_ID_LDO6,
+ MAX77620_REGULATOR_ID_LDO7,
+ MAX77620_REGULATOR_ID_LDO8,
+ MAX77620_NUM_REGS,
+};
+
+/* Regulator types */
+enum max77620_regulator_type {
+ MAX77620_REGULATOR_TYPE_SD,
+ MAX77620_REGULATOR_TYPE_LDO_N,
+ MAX77620_REGULATOR_TYPE_LDO_P,
+};
+
+struct max77620_regulator_info {
+ u8 type;
+ u8 fps_addr;
+ u8 volt_addr;
+ u8 cfg_addr;
+ u8 power_mode_mask;
+ u8 power_mode_shift;
+ u8 remote_sense_addr;
+ u8 remote_sense_mask;
+ struct regulator_desc desc;
+};
+
+struct max77620_regulator_pdata {
+ struct regulator_init_data *reg_idata;
+ int active_fps_src;
+ int active_fps_pd_slot;
+ int active_fps_pu_slot;
+ int suspend_fps_src;
+ int suspend_fps_pd_slot;
+ int suspend_fps_pu_slot;
+ int current_mode;
+};
+
+struct max77620_regulator {
+ struct device *dev;
+ struct regmap *rmap;
+ struct max77620_regulator_info *rinfo[MAX77620_NUM_REGS];
+ struct max77620_regulator_pdata reg_pdata[MAX77620_NUM_REGS];
+ int enable_power_mode[MAX77620_NUM_REGS];
+ int current_power_mode[MAX77620_NUM_REGS];
+ int active_fps_src[MAX77620_NUM_REGS];
+};
+
+#define fps_src_name(fps_src) \
+ (fps_src == MAX77620_FPS_SRC_0 ? "FPS_SRC_0" : \
+ fps_src == MAX77620_FPS_SRC_1 ? "FPS_SRC_1" : \
+ fps_src == MAX77620_FPS_SRC_2 ? "FPS_SRC_2" : "FPS_SRC_NONE")
+
+static int max77620_regulator_get_fps_src(struct max77620_regulator *pmic,
+ int id)
+{
+ struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(pmic->rmap, rinfo->fps_addr, &val);
+ if (ret < 0) {
+ dev_err(pmic->dev, "Reg 0x%02x read failed %d\n",
+ rinfo->fps_addr, ret);
+ return ret;
+ }
+
+ return (val & MAX77620_FPS_SRC_MASK) >> MAX77620_FPS_SRC_SHIFT;
+}
+
+static int max77620_regulator_set_fps_src(struct max77620_regulator *pmic,
+ int fps_src, int id)
+{
+ struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+ unsigned int val;
+ int ret;
+
+ switch (fps_src) {
+ case MAX77620_FPS_SRC_0:
+ case MAX77620_FPS_SRC_1:
+ case MAX77620_FPS_SRC_2:
+ case MAX77620_FPS_SRC_NONE:
+ break;
+
+ case MAX77620_FPS_SRC_DEF:
+ ret = regmap_read(pmic->rmap, rinfo->fps_addr, &val);
+ if (ret < 0) {
+ dev_err(pmic->dev, "Reg 0x%02x read failed %d\n",
+ rinfo->fps_addr, ret);
+ return ret;
+ }
+ ret = (val & MAX77620_FPS_SRC_MASK) >> MAX77620_FPS_SRC_SHIFT;
+ pmic->active_fps_src[id] = ret;
+ return 0;
+
+ default:
+ dev_err(pmic->dev, "Invalid FPS %d for regulator %d\n",
+ fps_src, id);
+ return -EINVAL;
+ }
+
+ ret = regmap_update_bits(pmic->rmap, rinfo->fps_addr,
+ MAX77620_FPS_SRC_MASK,
+ fps_src << MAX77620_FPS_SRC_SHIFT);
+ if (ret < 0) {
+ dev_err(pmic->dev, "Reg 0x%02x update failed %d\n",
+ rinfo->fps_addr, ret);
+ return ret;
+ }
+ pmic->active_fps_src[id] = fps_src;
+
+ return 0;
+}
+
+static int max77620_regulator_set_fps_slots(struct max77620_regulator *pmic,
+ int id, bool is_suspend)
+{
+ struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id];
+ struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+ unsigned int val = 0;
+ unsigned int mask = 0;
+ int pu = rpdata->active_fps_pu_slot;
+ int pd = rpdata->active_fps_pd_slot;
+ int ret = 0;
+
+ if (is_suspend) {
+ pu = rpdata->suspend_fps_pu_slot;
+ pd = rpdata->suspend_fps_pd_slot;
+ }
+
+ /* FPS power up period setting */
+ if (pu >= 0) {
+ val |= (pu << MAX77620_FPS_PU_PERIOD_SHIFT);
+ mask |= MAX77620_FPS_PU_PERIOD_MASK;
+ }
+
+ /* FPS power down period setting */
+ if (pd >= 0) {
+ val |= (pd << MAX77620_FPS_PD_PERIOD_SHIFT);
+ mask |= MAX77620_FPS_PD_PERIOD_MASK;
+ }
+
+ if (mask) {
+ ret = regmap_update_bits(pmic->rmap, rinfo->fps_addr,
+ mask, val);
+ if (ret < 0) {
+ dev_err(pmic->dev, "Reg 0x%02x update failed: %d\n",
+ rinfo->fps_addr, ret);
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static int max77620_regulator_set_power_mode(struct max77620_regulator *pmic,
+ int power_mode, int id)
+{
+ struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+ u8 mask = rinfo->power_mode_mask;
+ u8 shift = rinfo->power_mode_shift;
+ u8 addr;
+ int ret;
+
+ switch (rinfo->type) {
+ case MAX77620_REGULATOR_TYPE_SD:
+ addr = rinfo->cfg_addr;
+ break;
+ default:
+ addr = rinfo->volt_addr;
+ break;
+ }
+
+ ret = regmap_update_bits(pmic->rmap, addr, mask, power_mode << shift);
+ if (ret < 0) {
+ dev_err(pmic->dev, "Regulator %d mode set failed: %d\n",
+ id, ret);
+ return ret;
+ }
+ pmic->current_power_mode[id] = power_mode;
+
+ return ret;
+}
+
+static int max77620_regulator_get_power_mode(struct max77620_regulator *pmic,
+ int id)
+{
+ struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+ unsigned int val, addr;
+ u8 mask = rinfo->power_mode_mask;
+ u8 shift = rinfo->power_mode_shift;
+ int ret;
+
+ switch (rinfo->type) {
+ case MAX77620_REGULATOR_TYPE_SD:
+ addr = rinfo->cfg_addr;
+ break;
+ default:
+ addr = rinfo->volt_addr;
+ break;
+ }
+
+ ret = regmap_read(pmic->rmap, addr, &val);
+ if (ret < 0) {
+ dev_err(pmic->dev, "Regulator %d: Reg 0x%02x read failed: %d\n",
+ id, addr, ret);
+ return ret;
+ }
+
+ return (val & mask) >> shift;
+}
+
+static int max77620_read_slew_rate(struct max77620_regulator *pmic, int id)
+{
+ struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+ unsigned int rval;
+ int slew_rate;
+ int ret;
+
+ ret = regmap_read(pmic->rmap, rinfo->cfg_addr, &rval);
+ if (ret < 0) {
+ dev_err(pmic->dev, "Register 0x%02x read failed: %d\n",
+ rinfo->cfg_addr, ret);
+ return ret;
+ }
+
+ switch (rinfo->type) {
+ case MAX77620_REGULATOR_TYPE_SD:
+ slew_rate = (rval >> MAX77620_SD_SR_SHIFT) & 0x3;
+ switch (slew_rate) {
+ case 0:
+ slew_rate = 13750;
+ break;
+ case 1:
+ slew_rate = 27500;
+ break;
+ case 2:
+ slew_rate = 55000;
+ break;
+ case 3:
+ slew_rate = 100000;
+ break;
+ }
+ rinfo->desc.ramp_delay = slew_rate;
+ break;
+ default:
+ slew_rate = rval & 0x1;
+ switch (slew_rate) {
+ case 0:
+ slew_rate = 100000;
+ break;
+ case 1:
+ slew_rate = 5000;
+ break;
+ }
+ rinfo->desc.ramp_delay = slew_rate;
+ break;
+ }
+
+ return 0;
+}
+
+static int max77620_init_pmic(struct max77620_regulator *pmic, int id)
+{
+ struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id];
+ int ret;
+
+ /* Update power mode */
+ ret = max77620_regulator_get_power_mode(pmic, id);
+ if (ret < 0)
+ return ret;
+
+ pmic->current_power_mode[id] = ret;
+ pmic->enable_power_mode[id] = MAX77620_POWER_MODE_NORMAL;
+
+ if (rpdata->active_fps_src == MAX77620_FPS_SRC_DEF) {
+ ret = max77620_regulator_get_fps_src(pmic, id);
+ if (ret < 0)
+ return ret;
+ rpdata->active_fps_src = ret;
+ }
+
+ /* If rails are externally control of FPS then enable it always. */
+ if (rpdata->active_fps_src == MAX77620_FPS_SRC_NONE) {
+ ret = max77620_regulator_set_power_mode(pmic,
+ pmic->enable_power_mode[id], id);
+ if (ret < 0)
+ return ret;
+ } else {
+ if (pmic->current_power_mode[id] !=
+ pmic->enable_power_mode[id]) {
+ ret = max77620_regulator_set_power_mode(pmic,
+ pmic->enable_power_mode[id], id);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ ret = max77620_regulator_set_fps_src(pmic, rpdata->active_fps_src, id);
+ if (ret < 0)
+ return ret;
+
+ ret = max77620_regulator_set_fps_slots(pmic, id, false);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int max77620_regulator_enable(struct regulator_dev *rdev)
+{
+ struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+
+ if (pmic->active_fps_src[id] != MAX77620_FPS_SRC_NONE)
+ return 0;
+
+ return max77620_regulator_set_power_mode(pmic,
+ pmic->enable_power_mode[id], id);
+}
+
+static int max77620_regulator_disable(struct regulator_dev *rdev)
+{
+ struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+
+ if (pmic->active_fps_src[id] != MAX77620_FPS_SRC_NONE)
+ return 0;
+
+ return max77620_regulator_set_power_mode(pmic,
+ MAX77620_POWER_MODE_DISABLE, id);
+}
+
+static int max77620_regulator_is_enabled(struct regulator_dev *rdev)
+{
+ struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+ int ret = 1;
+
+ if (pmic->active_fps_src[id] != MAX77620_FPS_SRC_NONE)
+ return 1;
+
+ ret = max77620_regulator_get_power_mode(pmic, id);
+ if (ret < 0)
+ return ret;
+
+ if (ret != MAX77620_POWER_MODE_DISABLE)
+ return 1;
+
+ return 0;
+}
+
+static int max77620_regulator_set_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+ struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+ struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id];
+ bool fpwm = false;
+ int power_mode;
+ int ret;
+ u8 val;
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ fpwm = true;
+ power_mode = MAX77620_POWER_MODE_NORMAL;
+ break;
+
+ case REGULATOR_MODE_NORMAL:
+ power_mode = MAX77620_POWER_MODE_NORMAL;
+ break;
+
+ case REGULATOR_MODE_IDLE:
+ power_mode = MAX77620_POWER_MODE_LPM;
+ break;
+
+ default:
+ dev_err(pmic->dev, "Regulator %d mode %d is invalid\n",
+ id, mode);
+ return -EINVAL;
+ }
+
+ if (rinfo->type != MAX77620_REGULATOR_TYPE_SD)
+ goto skip_fpwm;
+
+ val = (fpwm) ? MAX77620_SD_FPWM_MASK : 0;
+ ret = regmap_update_bits(pmic->rmap, rinfo->cfg_addr,
+ MAX77620_SD_FPWM_MASK, val);
+ if (ret < 0) {
+ dev_err(pmic->dev, "Reg 0x%02x update failed: %d\n",
+ rinfo->cfg_addr, ret);
+ return ret;
+ }
+ rpdata->current_mode = mode;
+
+skip_fpwm:
+ ret = max77620_regulator_set_power_mode(pmic, power_mode, id);
+ if (ret < 0)
+ return ret;
+
+ pmic->enable_power_mode[id] = power_mode;
+
+ return 0;
+}
+
+static unsigned int max77620_regulator_get_mode(struct regulator_dev *rdev)
+{
+ struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+ struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+ int fpwm = 0;
+ int ret;
+ int pm_mode, reg_mode;
+ unsigned int val;
+
+ ret = max77620_regulator_get_power_mode(pmic, id);
+ if (ret < 0)
+ return 0;
+
+ pm_mode = ret;
+
+ if (rinfo->type == MAX77620_REGULATOR_TYPE_SD) {
+ ret = regmap_read(pmic->rmap, rinfo->cfg_addr, &val);
+ if (ret < 0) {
+ dev_err(pmic->dev, "Reg 0x%02x read failed: %d\n",
+ rinfo->cfg_addr, ret);
+ return ret;
+ }
+ fpwm = !!(val & MAX77620_SD_FPWM_MASK);
+ }
+
+ switch (pm_mode) {
+ case MAX77620_POWER_MODE_NORMAL:
+ case MAX77620_POWER_MODE_DISABLE:
+ if (fpwm)
+ reg_mode = REGULATOR_MODE_FAST;
+ else
+ reg_mode = REGULATOR_MODE_NORMAL;
+ break;
+ case MAX77620_POWER_MODE_LPM:
+ case MAX77620_POWER_MODE_GLPM:
+ reg_mode = REGULATOR_MODE_IDLE;
+ break;
+ default:
+ return 0;
+ }
+
+ return reg_mode;
+}
+
+static int max77620_regulator_set_ramp_delay(struct regulator_dev *rdev,
+ int ramp_delay)
+{
+ struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+ struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+ int ret, val;
+ u8 mask;
+
+ if (rinfo->type == MAX77620_REGULATOR_TYPE_SD) {
+ if (ramp_delay <= 13750)
+ val = 0;
+ else if (ramp_delay <= 27500)
+ val = 1;
+ else if (ramp_delay <= 55000)
+ val = 2;
+ else
+ val = 3;
+ val <<= MAX77620_SD_SR_SHIFT;
+ mask = MAX77620_SD_SR_MASK;
+ } else {
+ if (ramp_delay <= 5000)
+ val = 1;
+ else
+ val = 0;
+ mask = MAX77620_LDO_SLEW_RATE_MASK;
+ }
+
+ ret = regmap_update_bits(pmic->rmap, rinfo->cfg_addr, mask, val);
+ if (ret < 0)
+ dev_err(pmic->dev, "Reg 0x%02x update failed: %d\n",
+ rinfo->cfg_addr, ret);
+
+ return ret;
+}
+
+static int max77620_of_parse_cb(struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regulator_config *config)
+{
+ struct max77620_regulator *pmic = config->driver_data;
+ struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[desc->id];
+ u32 pval;
+ int ret;
+
+ ret = of_property_read_u32(np, "maxim,active-fps-source", &pval);
+ rpdata->active_fps_src = (!ret) ? pval : MAX77620_FPS_SRC_DEF;
+
+ ret = of_property_read_u32(np, "maxim,active-fps-power-up-slot", &pval);
+ rpdata->active_fps_pu_slot = (!ret) ? pval : -1;
+
+ ret = of_property_read_u32(
+ np, "maxim,active-fps-power-down-slot", &pval);
+ rpdata->active_fps_pd_slot = (!ret) ? pval : -1;
+
+ ret = of_property_read_u32(np, "maxim,suspend-fps-source", &pval);
+ rpdata->suspend_fps_src = (!ret) ? pval : -1;
+
+ ret = of_property_read_u32(
+ np, "maxim,suspend-fps-power-up-slot", &pval);
+ rpdata->suspend_fps_pu_slot = (!ret) ? pval : -1;
+
+ ret = of_property_read_u32(
+ np, "maxim,suspend-fps-power-down-slot", &pval);
+ rpdata->suspend_fps_pd_slot = (!ret) ? pval : -1;
+
+ return max77620_init_pmic(pmic, desc->id);
+}
+
+static struct regulator_ops max77620_regulator_ops = {
+ .is_enabled = max77620_regulator_is_enabled,
+ .enable = max77620_regulator_enable,
+ .disable = max77620_regulator_disable,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_mode = max77620_regulator_set_mode,
+ .get_mode = max77620_regulator_get_mode,
+ .set_ramp_delay = max77620_regulator_set_ramp_delay,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .set_active_discharge = regulator_set_active_discharge_regmap,
+};
+
+#define MAX77620_SD_CNF2_ROVS_EN_NONE 0
+#define RAIL_SD(_id, _name, _sname, _volt_mask, _min_uV, _max_uV, \
+ _step_uV, _rs_add, _rs_mask) \
+ [MAX77620_REGULATOR_ID_##_id] = { \
+ .type = MAX77620_REGULATOR_TYPE_SD, \
+ .volt_addr = MAX77620_REG_##_id, \
+ .cfg_addr = MAX77620_REG_##_id##_CFG, \
+ .fps_addr = MAX77620_REG_FPS_##_id, \
+ .remote_sense_addr = _rs_add, \
+ .remote_sense_mask = MAX77620_SD_CNF2_ROVS_EN_##_rs_mask, \
+ .power_mode_mask = MAX77620_SD_POWER_MODE_MASK, \
+ .power_mode_shift = MAX77620_SD_POWER_MODE_SHIFT, \
+ .desc = { \
+ .name = max77620_rails(_name), \
+ .of_match = of_match_ptr(#_name), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .of_parse_cb = max77620_of_parse_cb, \
+ .supply_name = _sname, \
+ .id = MAX77620_REGULATOR_ID_##_id, \
+ .ops = &max77620_regulator_ops, \
+ .n_voltages = ((_max_uV - _min_uV) / _step_uV) + 1, \
+ .min_uV = _min_uV, \
+ .uV_step = _step_uV, \
+ .enable_time = 500, \
+ .vsel_mask = MAX77620_##_volt_mask##_VOLT_MASK, \
+ .vsel_reg = MAX77620_REG_##_id, \
+ .active_discharge_off = 0, \
+ .active_discharge_on = MAX77620_SD_CFG1_ADE_ENABLE, \
+ .active_discharge_mask = MAX77620_SD_CFG1_ADE_MASK, \
+ .active_discharge_reg = MAX77620_REG_##_id##_CFG, \
+ .type = REGULATOR_VOLTAGE, \
+ }, \
+ }
+
+#define RAIL_LDO(_id, _name, _sname, _type, _min_uV, _max_uV, _step_uV) \
+ [MAX77620_REGULATOR_ID_##_id] = { \
+ .type = MAX77620_REGULATOR_TYPE_LDO_##_type, \
+ .volt_addr = MAX77620_REG_##_id##_CFG, \
+ .cfg_addr = MAX77620_REG_##_id##_CFG2, \
+ .fps_addr = MAX77620_REG_FPS_##_id, \
+ .remote_sense_addr = 0xFF, \
+ .power_mode_mask = MAX77620_LDO_POWER_MODE_MASK, \
+ .power_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT, \
+ .desc = { \
+ .name = max77620_rails(_name), \
+ .of_match = of_match_ptr(#_name), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .of_parse_cb = max77620_of_parse_cb, \
+ .supply_name = _sname, \
+ .id = MAX77620_REGULATOR_ID_##_id, \
+ .ops = &max77620_regulator_ops, \
+ .n_voltages = ((_max_uV - _min_uV) / _step_uV) + 1, \
+ .min_uV = _min_uV, \
+ .uV_step = _step_uV, \
+ .enable_time = 500, \
+ .vsel_mask = MAX77620_LDO_VOLT_MASK, \
+ .vsel_reg = MAX77620_REG_##_id##_CFG, \
+ .active_discharge_off = 0, \
+ .active_discharge_on = MAX77620_LDO_CFG2_ADE_ENABLE, \
+ .active_discharge_mask = MAX77620_LDO_CFG2_ADE_MASK, \
+ .active_discharge_reg = MAX77620_REG_##_id##_CFG2, \
+ .type = REGULATOR_VOLTAGE, \
+ }, \
+ }
+
+static struct max77620_regulator_info max77620_regs_info[MAX77620_NUM_REGS] = {
+ RAIL_SD(SD0, sd0, "in-sd0", SD0, 600000, 1400000, 12500, 0x22, SD0),
+ RAIL_SD(SD1, sd1, "in-sd1", SD1, 600000, 1550000, 12500, 0x22, SD1),
+ RAIL_SD(SD2, sd2, "in-sd2", SDX, 600000, 3787500, 12500, 0xFF, NONE),
+ RAIL_SD(SD3, sd3, "in-sd3", SDX, 600000, 3787500, 12500, 0xFF, NONE),
+ RAIL_SD(SD4, sd4, "in-sd4", SDX, 600000, 3787500, 12500, 0xFF, NONE),
+
+ RAIL_LDO(LDO0, ldo0, "in-ldo0-1", N, 800000, 2375000, 25000),
+ RAIL_LDO(LDO1, ldo1, "in-ldo0-1", N, 800000, 2375000, 25000),
+ RAIL_LDO(LDO2, ldo2, "in-ldo2", P, 800000, 3950000, 50000),
+ RAIL_LDO(LDO3, ldo3, "in-ldo3-5", P, 800000, 3950000, 50000),
+ RAIL_LDO(LDO4, ldo4, "in-ldo4-6", P, 800000, 1587500, 12500),
+ RAIL_LDO(LDO5, ldo5, "in-ldo3-5", P, 800000, 3950000, 50000),
+ RAIL_LDO(LDO6, ldo6, "in-ldo4-6", P, 800000, 3950000, 50000),
+ RAIL_LDO(LDO7, ldo7, "in-ldo7-8", N, 800000, 3950000, 50000),
+ RAIL_LDO(LDO8, ldo8, "in-ldo7-8", N, 800000, 3950000, 50000),
+};
+
+static struct max77620_regulator_info max20024_regs_info[MAX77620_NUM_REGS] = {
+ RAIL_SD(SD0, sd0, "in-sd0", SD0, 800000, 1587500, 12500, 0x22, SD0),
+ RAIL_SD(SD1, sd1, "in-sd1", SD1, 600000, 3387500, 12500, 0x22, SD1),
+ RAIL_SD(SD2, sd2, "in-sd2", SDX, 600000, 3787500, 12500, 0xFF, NONE),
+ RAIL_SD(SD3, sd3, "in-sd3", SDX, 600000, 3787500, 12500, 0xFF, NONE),
+ RAIL_SD(SD4, sd4, "in-sd4", SDX, 600000, 3787500, 12500, 0xFF, NONE),
+
+ RAIL_LDO(LDO0, ldo0, "in-ldo0-1", N, 800000, 2375000, 25000),
+ RAIL_LDO(LDO1, ldo1, "in-ldo0-1", N, 800000, 2375000, 25000),
+ RAIL_LDO(LDO2, ldo2, "in-ldo2", P, 800000, 3950000, 50000),
+ RAIL_LDO(LDO3, ldo3, "in-ldo3-5", P, 800000, 3950000, 50000),
+ RAIL_LDO(LDO4, ldo4, "in-ldo4-6", P, 800000, 1587500, 12500),
+ RAIL_LDO(LDO5, ldo5, "in-ldo3-5", P, 800000, 3950000, 50000),
+ RAIL_LDO(LDO6, ldo6, "in-ldo4-6", P, 800000, 3950000, 50000),
+ RAIL_LDO(LDO7, ldo7, "in-ldo7-8", N, 800000, 3950000, 50000),
+ RAIL_LDO(LDO8, ldo8, "in-ldo7-8", N, 800000, 3950000, 50000),
+};
+
+static int max77620_regulator_probe(struct platform_device *pdev)
+{
+ struct max77620_chip *max77620_chip = dev_get_drvdata(pdev->dev.parent);
+ struct max77620_regulator_info *rinfo;
+ struct device *dev = &pdev->dev;
+ struct regulator_config config = { };
+ struct max77620_regulator *pmic;
+ int ret = 0;
+ int id;
+
+ pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
+ if (!pmic)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, pmic);
+ pmic->dev = dev;
+ pmic->rmap = max77620_chip->rmap;
+ if (!dev->of_node)
+ dev->of_node = pdev->dev.parent->of_node;
+
+ switch (max77620_chip->chip_id) {
+ case MAX77620:
+ rinfo = max77620_regs_info;
+ break;
+ default:
+ rinfo = max20024_regs_info;
+ break;
+ }
+
+ config.regmap = pmic->rmap;
+ config.dev = dev;
+ config.driver_data = pmic;
+
+ for (id = 0; id < MAX77620_NUM_REGS; id++) {
+ struct regulator_dev *rdev;
+ struct regulator_desc *rdesc;
+
+ if ((max77620_chip->chip_id == MAX77620) &&
+ (id == MAX77620_REGULATOR_ID_SD4))
+ continue;
+
+ rdesc = &rinfo[id].desc;
+ pmic->rinfo[id] = &max77620_regs_info[id];
+ pmic->enable_power_mode[id] = MAX77620_POWER_MODE_NORMAL;
+
+ ret = max77620_read_slew_rate(pmic, id);
+ if (ret < 0)
+ return ret;
+
+ rdev = devm_regulator_register(dev, rdesc, &config);
+ if (IS_ERR(rdev)) {
+ ret = PTR_ERR(rdev);
+ dev_err(dev, "Regulator registration %s failed: %d\n",
+ rdesc->name, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int max77620_regulator_suspend(struct device *dev)
+{
+ struct max77620_regulator *pmic = dev_get_drvdata(dev);
+ struct max77620_regulator_pdata *reg_pdata;
+ int id;
+
+ for (id = 0; id < MAX77620_NUM_REGS; id++) {
+ reg_pdata = &pmic->reg_pdata[id];
+
+ max77620_regulator_set_fps_slots(pmic, id, true);
+ if (reg_pdata->suspend_fps_src < 0)
+ continue;
+
+ max77620_regulator_set_fps_src(pmic, reg_pdata->suspend_fps_src,
+ id);
+ }
+
+ return 0;
+}
+
+static int max77620_regulator_resume(struct device *dev)
+{
+ struct max77620_regulator *pmic = dev_get_drvdata(dev);
+ struct max77620_regulator_pdata *reg_pdata;
+ int id;
+
+ for (id = 0; id < MAX77620_NUM_REGS; id++) {
+ reg_pdata = &pmic->reg_pdata[id];
+
+ max77620_regulator_set_fps_slots(pmic, id, false);
+ if (reg_pdata->active_fps_src < 0)
+ continue;
+ max77620_regulator_set_fps_src(pmic, reg_pdata->active_fps_src,
+ id);
+ }
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops max77620_regulator_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(max77620_regulator_suspend,
+ max77620_regulator_resume)
+};
+
+static const struct platform_device_id max77620_regulator_devtype[] = {
+ { .name = "max77620-pmic", },
+ { .name = "max20024-pmic", },
+ {},
+};
+MODULE_DEVICE_TABLE(platform, max77620_regulator_devtype);
+
+static struct platform_driver max77620_regulator_driver = {
+ .probe = max77620_regulator_probe,
+ .id_table = max77620_regulator_devtype,
+ .driver = {
+ .name = "max77620-pmic",
+ .pm = &max77620_regulator_pm_ops,
+ },
+};
+
+module_platform_driver(max77620_regulator_driver);
+
+MODULE_DESCRIPTION("MAX77620/MAX20024 regulator driver");
+MODULE_AUTHOR("Mallikarjun Kasoju <mkasoju@nvidia.com>");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686-regulator.c
index 17ccf365a..17ccf365a 100644
--- a/drivers/regulator/max77686.c
+++ b/drivers/regulator/max77686-regulator.c
diff --git a/drivers/regulator/max77802.c b/drivers/regulator/max77802-regulator.c
index c07ee13bd..c07ee13bd 100644
--- a/drivers/regulator/max77802.c
+++ b/drivers/regulator/max77802-regulator.c
diff --git a/drivers/regulator/mt6397-regulator.c b/drivers/regulator/mt6397-regulator.c
index a5b2f4762..17a5b6c2d 100644
--- a/drivers/regulator/mt6397-regulator.c
+++ b/drivers/regulator/mt6397-regulator.c
@@ -317,11 +317,25 @@ static int mt6397_regulator_probe(struct platform_device *pdev)
return 0;
}
+static const struct platform_device_id mt6397_platform_ids[] = {
+ {"mt6397-regulator", 0},
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(platform, mt6397_platform_ids);
+
+static const struct of_device_id mt6397_of_match[] = {
+ { .compatible = "mediatek,mt6397-regulator", },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mt6397_of_match);
+
static struct platform_driver mt6397_regulator_driver = {
.driver = {
.name = "mt6397-regulator",
+ .of_match_table = of_match_ptr(mt6397_of_match),
},
.probe = mt6397_regulator_probe,
+ .id_table = mt6397_platform_ids,
};
module_platform_driver(mt6397_regulator_driver);
@@ -329,4 +343,3 @@ module_platform_driver(mt6397_regulator_driver);
MODULE_AUTHOR("Flora Fu <flora.fu@mediatek.com>");
MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6397 PMIC");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:mt6397-regulator");
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 499e437c7..6b0aa80b2 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -28,7 +28,6 @@ static void of_get_regulation_constraints(struct device_node *np,
struct regulator_init_data **init_data,
const struct regulator_desc *desc)
{
- const __be32 *min_uV, *max_uV;
struct regulation_constraints *constraints = &(*init_data)->constraints;
struct regulator_state *suspend_state;
struct device_node *suspend_np;
@@ -37,18 +36,18 @@ static void of_get_regulation_constraints(struct device_node *np,
constraints->name = of_get_property(np, "regulator-name", NULL);
- min_uV = of_get_property(np, "regulator-min-microvolt", NULL);
- if (min_uV)
- constraints->min_uV = be32_to_cpu(*min_uV);
- max_uV = of_get_property(np, "regulator-max-microvolt", NULL);
- if (max_uV)
- constraints->max_uV = be32_to_cpu(*max_uV);
+ if (!of_property_read_u32(np, "regulator-min-microvolt", &pval))
+ constraints->min_uV = pval;
+
+ if (!of_property_read_u32(np, "regulator-max-microvolt", &pval))
+ constraints->max_uV = pval;
/* Voltage change possible? */
if (constraints->min_uV != constraints->max_uV)
constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE;
/* Only one voltage? Then make sure it's set. */
- if (min_uV && max_uV && constraints->min_uV == constraints->max_uV)
+ if (constraints->min_uV && constraints->max_uV &&
+ constraints->min_uV == constraints->max_uV)
constraints->apply_uV = true;
if (!of_property_read_u32(np, "regulator-microvolt-offset", &pval))
@@ -93,6 +92,12 @@ static void of_get_regulation_constraints(struct device_node *np,
constraints->soft_start = of_property_read_bool(np,
"regulator-soft-start");
+ ret = of_property_read_u32(np, "regulator-active-discharge", &pval);
+ if (!ret) {
+ constraints->active_discharge =
+ (pval) ? REGULATOR_ACTIVE_DISCHARGE_ENABLE :
+ REGULATOR_ACTIVE_DISCHARGE_DISABLE;
+ }
if (!of_property_read_u32(np, "regulator-initial-mode", &pval)) {
if (desc && desc->of_map_mode) {
diff --git a/drivers/regulator/pv88060-regulator.c b/drivers/regulator/pv88060-regulator.c
index 094376c8d..c448b727f 100644
--- a/drivers/regulator/pv88060-regulator.c
+++ b/drivers/regulator/pv88060-regulator.c
@@ -285,8 +285,8 @@ static irqreturn_t pv88060_irq_handler(int irq, void *data)
}
}
- err = regmap_update_bits(chip->regmap, PV88060_REG_EVENT_A,
- PV88060_E_VDD_FLT, PV88060_E_VDD_FLT);
+ err = regmap_write(chip->regmap, PV88060_REG_EVENT_A,
+ PV88060_E_VDD_FLT);
if (err < 0)
goto error_i2c;
@@ -302,8 +302,8 @@ static irqreturn_t pv88060_irq_handler(int irq, void *data)
}
}
- err = regmap_update_bits(chip->regmap, PV88060_REG_EVENT_A,
- PV88060_E_OVER_TEMP, PV88060_E_OVER_TEMP);
+ err = regmap_write(chip->regmap, PV88060_REG_EVENT_A,
+ PV88060_E_OVER_TEMP);
if (err < 0)
goto error_i2c;
diff --git a/drivers/regulator/pv88090-regulator.c b/drivers/regulator/pv88090-regulator.c
index ac15f31b5..0057c6740 100644
--- a/drivers/regulator/pv88090-regulator.c
+++ b/drivers/regulator/pv88090-regulator.c
@@ -283,8 +283,8 @@ static irqreturn_t pv88090_irq_handler(int irq, void *data)
}
}
- err = regmap_update_bits(chip->regmap, PV88090_REG_EVENT_A,
- PV88090_E_VDD_FLT, PV88090_E_VDD_FLT);
+ err = regmap_write(chip->regmap, PV88090_REG_EVENT_A,
+ PV88090_E_VDD_FLT);
if (err < 0)
goto error_i2c;
@@ -300,8 +300,8 @@ static irqreturn_t pv88090_irq_handler(int irq, void *data)
}
}
- err = regmap_update_bits(chip->regmap, PV88090_REG_EVENT_A,
- PV88090_E_OVER_TEMP, PV88090_E_OVER_TEMP);
+ err = regmap_write(chip->regmap, PV88090_REG_EVENT_A,
+ PV88090_E_OVER_TEMP);
if (err < 0)
goto error_i2c;
diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c
index 3aca067b9..4689d62f4 100644
--- a/drivers/regulator/pwm-regulator.c
+++ b/drivers/regulator/pwm-regulator.c
@@ -27,6 +27,13 @@ struct pwm_regulator_data {
/* Voltage table */
struct pwm_voltages *duty_cycle_table;
+
+ /* regulator descriptor */
+ struct regulator_desc desc;
+
+ /* Regulator ops */
+ struct regulator_ops ops;
+
int state;
/* Continuous voltage */
@@ -115,7 +122,7 @@ static int pwm_voltage_to_duty_cycle_percentage(struct regulator_dev *rdev, int
int max_uV = rdev->constraints->max_uV;
int diff = max_uV - min_uV;
- return 100 - (((req_uV * 100) - (min_uV * 100)) / diff);
+ return ((req_uV * 100) - (min_uV * 100)) / diff;
}
static int pwm_regulator_get_voltage(struct regulator_dev *rdev)
@@ -212,8 +219,10 @@ static int pwm_regulator_init_table(struct platform_device *pdev,
}
drvdata->duty_cycle_table = duty_cycle_table;
- pwm_regulator_desc.ops = &pwm_regulator_voltage_table_ops;
- pwm_regulator_desc.n_voltages = length / sizeof(*duty_cycle_table);
+ memcpy(&drvdata->ops, &pwm_regulator_voltage_table_ops,
+ sizeof(drvdata->ops));
+ drvdata->desc.ops = &drvdata->ops;
+ drvdata->desc.n_voltages = length / sizeof(*duty_cycle_table);
return 0;
}
@@ -221,8 +230,10 @@ static int pwm_regulator_init_table(struct platform_device *pdev,
static int pwm_regulator_init_continuous(struct platform_device *pdev,
struct pwm_regulator_data *drvdata)
{
- pwm_regulator_desc.ops = &pwm_regulator_voltage_continuous_ops;
- pwm_regulator_desc.continuous_voltage_range = true;
+ memcpy(&drvdata->ops, &pwm_regulator_voltage_continuous_ops,
+ sizeof(drvdata->ops));
+ drvdata->desc.ops = &drvdata->ops;
+ drvdata->desc.continuous_voltage_range = true;
return 0;
}
@@ -245,6 +256,8 @@ static int pwm_regulator_probe(struct platform_device *pdev)
if (!drvdata)
return -ENOMEM;
+ memcpy(&drvdata->desc, &pwm_regulator_desc, sizeof(drvdata->desc));
+
if (of_find_property(np, "voltage-table", NULL))
ret = pwm_regulator_init_table(pdev, drvdata);
else
@@ -253,7 +266,7 @@ static int pwm_regulator_probe(struct platform_device *pdev)
return ret;
init_data = of_get_regulator_init_data(&pdev->dev, np,
- &pwm_regulator_desc);
+ &drvdata->desc);
if (!init_data)
return -ENOMEM;
@@ -269,10 +282,10 @@ static int pwm_regulator_probe(struct platform_device *pdev)
}
regulator = devm_regulator_register(&pdev->dev,
- &pwm_regulator_desc, &config);
+ &drvdata->desc, &config);
if (IS_ERR(regulator)) {
dev_err(&pdev->dev, "Failed to register regulator %s\n",
- pwm_regulator_desc.name);
+ drvdata->desc.name);
return PTR_ERR(regulator);
}
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 3242ffc0c..6dfa3502e 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -38,7 +38,6 @@
/* The highest number of possible regulators for supported devices. */
#define S2MPS_REGULATOR_MAX S2MPS13_REGULATOR_MAX
struct s2mps11_info {
- unsigned int rdev_num;
int ramp_delay2;
int ramp_delay34;
int ramp_delay5;
@@ -54,7 +53,10 @@ struct s2mps11_info {
*/
DECLARE_BITMAP(suspend_state, S2MPS_REGULATOR_MAX);
- /* Array of size rdev_num with GPIO-s for external sleep control */
+ /*
+ * Array (size: number of regulators) with GPIO-s for external
+ * sleep control.
+ */
int *ext_control_gpio;
};
@@ -306,7 +308,7 @@ static struct regulator_ops s2mps11_buck_ops = {
.enable_mask = S2MPS11_ENABLE_MASK \
}
-#define regulator_desc_s2mps11_buck6_10(num, min, step) { \
+#define regulator_desc_s2mps11_buck67810(num, min, step) { \
.name = "BUCK"#num, \
.id = S2MPS11_BUCK##num, \
.ops = &s2mps11_buck_ops, \
@@ -322,6 +324,22 @@ static struct regulator_ops s2mps11_buck_ops = {
.enable_mask = S2MPS11_ENABLE_MASK \
}
+#define regulator_desc_s2mps11_buck9 { \
+ .name = "BUCK9", \
+ .id = S2MPS11_BUCK9, \
+ .ops = &s2mps11_buck_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = MIN_3000_MV, \
+ .uV_step = STEP_25_MV, \
+ .n_voltages = S2MPS11_BUCK9_N_VOLTAGES, \
+ .ramp_delay = S2MPS11_RAMP_DELAY, \
+ .vsel_reg = S2MPS11_REG_B9CTRL2, \
+ .vsel_mask = S2MPS11_BUCK9_VSEL_MASK, \
+ .enable_reg = S2MPS11_REG_B9CTRL1, \
+ .enable_mask = S2MPS11_ENABLE_MASK \
+}
+
static const struct regulator_desc s2mps11_regulators[] = {
regulator_desc_s2mps11_ldo(1, STEP_25_MV),
regulator_desc_s2mps11_ldo(2, STEP_50_MV),
@@ -366,11 +384,11 @@ static const struct regulator_desc s2mps11_regulators[] = {
regulator_desc_s2mps11_buck1_4(3),
regulator_desc_s2mps11_buck1_4(4),
regulator_desc_s2mps11_buck5,
- regulator_desc_s2mps11_buck6_10(6, MIN_600_MV, STEP_6_25_MV),
- regulator_desc_s2mps11_buck6_10(7, MIN_600_MV, STEP_6_25_MV),
- regulator_desc_s2mps11_buck6_10(8, MIN_600_MV, STEP_6_25_MV),
- regulator_desc_s2mps11_buck6_10(9, MIN_3000_MV, STEP_25_MV),
- regulator_desc_s2mps11_buck6_10(10, MIN_750_MV, STEP_12_5_MV),
+ regulator_desc_s2mps11_buck67810(6, MIN_600_MV, STEP_6_25_MV),
+ regulator_desc_s2mps11_buck67810(7, MIN_600_MV, STEP_6_25_MV),
+ regulator_desc_s2mps11_buck67810(8, MIN_600_MV, STEP_6_25_MV),
+ regulator_desc_s2mps11_buck9,
+ regulator_desc_s2mps11_buck67810(10, MIN_750_MV, STEP_12_5_MV),
};
static struct regulator_ops s2mps14_reg_ops;
@@ -819,7 +837,8 @@ static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev,
}
static int s2mps11_pmic_dt_parse(struct platform_device *pdev,
- struct of_regulator_match *rdata, struct s2mps11_info *s2mps11)
+ struct of_regulator_match *rdata, struct s2mps11_info *s2mps11,
+ unsigned int rdev_num)
{
struct device_node *reg_np;
@@ -829,7 +848,7 @@ static int s2mps11_pmic_dt_parse(struct platform_device *pdev,
return -EINVAL;
}
- of_regulator_match(&pdev->dev, reg_np, rdata, s2mps11->rdev_num);
+ of_regulator_match(&pdev->dev, reg_np, rdata, rdev_num);
if (s2mps11->dev_type == S2MPS14X)
s2mps14_pmic_dt_parse_ext_control_gpio(pdev, rdata, s2mps11);
@@ -1077,6 +1096,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
struct of_regulator_match *rdata = NULL;
struct regulator_config config = { };
struct s2mps11_info *s2mps11;
+ unsigned int rdev_num = 0;
int i, ret = 0;
const struct regulator_desc *regulators;
@@ -1088,28 +1108,29 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
s2mps11->dev_type = platform_get_device_id(pdev)->driver_data;
switch (s2mps11->dev_type) {
case S2MPS11X:
- s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators);
+ rdev_num = ARRAY_SIZE(s2mps11_regulators);
regulators = s2mps11_regulators;
- BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num);
+ BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mps11_regulators));
break;
case S2MPS13X:
- s2mps11->rdev_num = ARRAY_SIZE(s2mps13_regulators);
+ rdev_num = ARRAY_SIZE(s2mps13_regulators);
regulators = s2mps13_regulators;
- BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num);
+ BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mps13_regulators));
break;
case S2MPS14X:
- s2mps11->rdev_num = ARRAY_SIZE(s2mps14_regulators);
+ rdev_num = ARRAY_SIZE(s2mps14_regulators);
regulators = s2mps14_regulators;
- BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num);
+ BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mps14_regulators));
break;
case S2MPS15X:
- s2mps11->rdev_num = ARRAY_SIZE(s2mps15_regulators);
+ rdev_num = ARRAY_SIZE(s2mps15_regulators);
regulators = s2mps15_regulators;
+ BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mps15_regulators));
break;
case S2MPU02:
- s2mps11->rdev_num = ARRAY_SIZE(s2mpu02_regulators);
+ rdev_num = ARRAY_SIZE(s2mpu02_regulators);
regulators = s2mpu02_regulators;
- BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num);
+ BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mpu02_regulators));
break;
default:
dev_err(&pdev->dev, "Invalid device type: %u\n",
@@ -1118,7 +1139,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
}
s2mps11->ext_control_gpio = devm_kmalloc(&pdev->dev,
- sizeof(*s2mps11->ext_control_gpio) * s2mps11->rdev_num,
+ sizeof(*s2mps11->ext_control_gpio) * rdev_num,
GFP_KERNEL);
if (!s2mps11->ext_control_gpio)
return -ENOMEM;
@@ -1126,7 +1147,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
* 0 is a valid GPIO so initialize all GPIO-s to negative value
* to indicate that external control won't be used for this regulator.
*/
- for (i = 0; i < s2mps11->rdev_num; i++)
+ for (i = 0; i < rdev_num; i++)
s2mps11->ext_control_gpio[i] = -EINVAL;
if (!iodev->dev->of_node) {
@@ -1140,14 +1161,14 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
}
}
- rdata = kzalloc(sizeof(*rdata) * s2mps11->rdev_num, GFP_KERNEL);
+ rdata = kzalloc(sizeof(*rdata) * rdev_num, GFP_KERNEL);
if (!rdata)
return -ENOMEM;
- for (i = 0; i < s2mps11->rdev_num; i++)
+ for (i = 0; i < rdev_num; i++)
rdata[i].name = regulators[i].name;
- ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11);
+ ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11, rdev_num);
if (ret)
goto out;
@@ -1159,7 +1180,7 @@ common_reg:
config.driver_data = s2mps11;
config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
config.ena_gpio_initialized = true;
- for (i = 0; i < s2mps11->rdev_num; i++) {
+ for (i = 0; i < rdev_num; i++) {
struct regulator_dev *regulator;
if (pdata) {
diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c
index 9503d5481..a4921a70d 100644
--- a/drivers/regulator/tps65912-regulator.c
+++ b/drivers/regulator/tps65912-regulator.c
@@ -1,541 +1,168 @@
/*
- * tps65912.c -- TI tps65912
+ * Regulator driver for TI TPS65912x PMICs
*
- * Copyright 2011 Texas Instruments Inc.
+ * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
+ * Andrew F. Davis <afd@ti.com>
*
- * Author: Margarita Olaya Cabrera <magi@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 version 2 as
+ * published by the Free Software Foundation.
*
- * 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 "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether expressed or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License version 2 for more details.
*
- * This driver is based on wm8350 implementation.
+ * Based on the TPS65218 driver and the previous TPS65912 driver by
+ * Margarita Olaya Cabrera <magi@slimlogic.co.uk>
*/
-#include <linux/kernel.h>
#include <linux/module.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/slab.h>
-#include <linux/gpio.h>
-#include <linux/mfd/tps65912.h>
-
-/* DCDC's */
-#define TPS65912_REG_DCDC1 0
-#define TPS65912_REG_DCDC2 1
-#define TPS65912_REG_DCDC3 2
-#define TPS65912_REG_DCDC4 3
-
-/* LDOs */
-#define TPS65912_REG_LDO1 4
-#define TPS65912_REG_LDO2 5
-#define TPS65912_REG_LDO3 6
-#define TPS65912_REG_LDO4 7
-#define TPS65912_REG_LDO5 8
-#define TPS65912_REG_LDO6 9
-#define TPS65912_REG_LDO7 10
-#define TPS65912_REG_LDO8 11
-#define TPS65912_REG_LDO9 12
-#define TPS65912_REG_LDO10 13
-
-/* Number of step-down converters available */
-#define TPS65912_NUM_DCDC 4
-
-/* Number of LDO voltage regulators available */
-#define TPS65912_NUM_LDO 10
-/* Number of total regulators available */
-#define TPS65912_NUM_REGULATOR (TPS65912_NUM_DCDC + TPS65912_NUM_LDO)
-
-#define TPS65912_REG_ENABLED 0x80
-#define OP_SELREG_MASK 0x40
-#define OP_SELREG_SHIFT 6
-
-struct tps_info {
- const char *name;
-};
+#include <linux/mfd/tps65912.h>
-static struct tps_info tps65912_regs[] = {
- {
- .name = "DCDC1",
- },
- {
- .name = "DCDC2",
- },
- {
- .name = "DCDC3",
- },
- {
- .name = "DCDC4",
- },
- {
- .name = "LDO1",
- },
- {
- .name = "LDO2",
- },
- {
- .name = "LDO3",
- },
- {
- .name = "LDO4",
- },
- {
- .name = "LDO5",
- },
- {
- .name = "LDO6",
- },
- {
- .name = "LDO7",
- },
- {
- .name = "LDO8",
- },
- {
- .name = "LDO9",
- },
- {
- .name = "LDO10",
- },
-};
+enum tps65912_regulators { DCDC1, DCDC2, DCDC3, DCDC4, LDO1, LDO2, LDO3,
+ LDO4, LDO5, LDO6, LDO7, LDO8, LDO9, LDO10 };
+
+#define TPS65912_REGULATOR(_name, _id, _of_match, _ops, _vr, _er, _lr) \
+ [_id] = { \
+ .name = _name, \
+ .of_match = _of_match, \
+ .regulators_node = "regulators", \
+ .id = _id, \
+ .ops = &_ops, \
+ .n_voltages = 64, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .vsel_reg = _vr, \
+ .vsel_mask = 0x3f, \
+ .enable_reg = _er, \
+ .enable_mask = BIT(7), \
+ .volt_table = NULL, \
+ .linear_ranges = _lr, \
+ .n_linear_ranges = ARRAY_SIZE(_lr), \
+ }
-struct tps65912_reg {
- struct regulator_desc desc[TPS65912_NUM_REGULATOR];
- struct tps65912 *mfd;
- struct regulator_dev *rdev[TPS65912_NUM_REGULATOR];
- struct tps_info *info[TPS65912_NUM_REGULATOR];
- /* for read/write access */
- struct mutex io_lock;
- int mode;
- int (*get_ctrl_reg)(int);
- int dcdc_range[TPS65912_NUM_DCDC];
- int pwm_mode_reg;
- int eco_reg;
+static const struct regulator_linear_range tps65912_dcdc_ranges[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0x0, 0x3f, 50000),
};
static const struct regulator_linear_range tps65912_ldo_ranges[] = {
- REGULATOR_LINEAR_RANGE(800000, 0, 32, 25000),
- REGULATOR_LINEAR_RANGE(1650000, 33, 60, 50000),
- REGULATOR_LINEAR_RANGE(3100000, 61, 63, 100000),
+ REGULATOR_LINEAR_RANGE(800000, 0x0, 0x20, 25000),
+ REGULATOR_LINEAR_RANGE(1650000, 0x21, 0x3c, 50000),
+ REGULATOR_LINEAR_RANGE(3100000, 0x3d, 0x3f, 100000),
};
-static int tps65912_get_range(struct tps65912_reg *pmic, int id)
-{
- struct tps65912 *mfd = pmic->mfd;
- int range;
-
- switch (id) {
- case TPS65912_REG_DCDC1:
- range = tps65912_reg_read(mfd, TPS65912_DCDC1_LIMIT);
- break;
- case TPS65912_REG_DCDC2:
- range = tps65912_reg_read(mfd, TPS65912_DCDC2_LIMIT);
- break;
- case TPS65912_REG_DCDC3:
- range = tps65912_reg_read(mfd, TPS65912_DCDC3_LIMIT);
- break;
- case TPS65912_REG_DCDC4:
- range = tps65912_reg_read(mfd, TPS65912_DCDC4_LIMIT);
- break;
- default:
- return 0;
- }
-
- if (range >= 0)
- range = (range & DCDC_LIMIT_RANGE_MASK)
- >> DCDC_LIMIT_RANGE_SHIFT;
-
- pmic->dcdc_range[id] = range;
- return range;
-}
-
-static unsigned long tps65912_vsel_to_uv_range0(u8 vsel)
-{
- unsigned long uv;
-
- uv = ((vsel * 12500) + 500000);
- return uv;
-}
-
-static unsigned long tps65912_vsel_to_uv_range1(u8 vsel)
-{
- unsigned long uv;
-
- uv = ((vsel * 12500) + 700000);
- return uv;
-}
-
-static unsigned long tps65912_vsel_to_uv_range2(u8 vsel)
-{
- unsigned long uv;
-
- uv = ((vsel * 25000) + 500000);
- return uv;
-}
-
-static unsigned long tps65912_vsel_to_uv_range3(u8 vsel)
-{
- unsigned long uv;
-
- if (vsel == 0x3f)
- uv = 3800000;
- else
- uv = ((vsel * 50000) + 500000);
-
- return uv;
-}
-
-static int tps65912_get_ctrl_register(int id)
-{
- if (id >= TPS65912_REG_DCDC1 && id <= TPS65912_REG_LDO4)
- return id * 3 + TPS65912_DCDC1_AVS;
- else if (id >= TPS65912_REG_LDO5 && id <= TPS65912_REG_LDO10)
- return id - TPS65912_REG_LDO5 + TPS65912_LDO5;
- else
- return -EINVAL;
-}
-
-static int tps65912_get_sel_register(struct tps65912_reg *pmic, int id)
-{
- struct tps65912 *mfd = pmic->mfd;
- int opvsel;
- u8 reg = 0;
-
- if (id >= TPS65912_REG_DCDC1 && id <= TPS65912_REG_LDO4) {
- opvsel = tps65912_reg_read(mfd, id * 3 + TPS65912_DCDC1_OP);
- if (opvsel & OP_SELREG_MASK)
- reg = id * 3 + TPS65912_DCDC1_AVS;
- else
- reg = id * 3 + TPS65912_DCDC1_OP;
- } else if (id >= TPS65912_REG_LDO5 && id <= TPS65912_REG_LDO10) {
- reg = id - TPS65912_REG_LDO5 + TPS65912_LDO5;
- } else {
- return -EINVAL;
- }
-
- return reg;
-}
-
-static int tps65912_get_mode_regiters(struct tps65912_reg *pmic, int id)
-{
- switch (id) {
- case TPS65912_REG_DCDC1:
- pmic->pwm_mode_reg = TPS65912_DCDC1_CTRL;
- pmic->eco_reg = TPS65912_DCDC1_AVS;
- break;
- case TPS65912_REG_DCDC2:
- pmic->pwm_mode_reg = TPS65912_DCDC2_CTRL;
- pmic->eco_reg = TPS65912_DCDC2_AVS;
- break;
- case TPS65912_REG_DCDC3:
- pmic->pwm_mode_reg = TPS65912_DCDC3_CTRL;
- pmic->eco_reg = TPS65912_DCDC3_AVS;
- break;
- case TPS65912_REG_DCDC4:
- pmic->pwm_mode_reg = TPS65912_DCDC4_CTRL;
- pmic->eco_reg = TPS65912_DCDC4_AVS;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int tps65912_reg_is_enabled(struct regulator_dev *dev)
-{
- struct tps65912_reg *pmic = rdev_get_drvdata(dev);
- struct tps65912 *mfd = pmic->mfd;
- int reg, value, id = rdev_get_id(dev);
-
- if (id < TPS65912_REG_DCDC1 || id > TPS65912_REG_LDO10)
- return -EINVAL;
-
- reg = pmic->get_ctrl_reg(id);
- if (reg < 0)
- return reg;
-
- value = tps65912_reg_read(mfd, reg);
- if (value < 0)
- return value;
-
- return value & TPS65912_REG_ENABLED;
-}
-
-static int tps65912_reg_enable(struct regulator_dev *dev)
-{
- struct tps65912_reg *pmic = rdev_get_drvdata(dev);
- struct tps65912 *mfd = pmic->mfd;
- int id = rdev_get_id(dev);
- int reg;
-
- if (id < TPS65912_REG_DCDC1 || id > TPS65912_REG_LDO10)
- return -EINVAL;
-
- reg = pmic->get_ctrl_reg(id);
- if (reg < 0)
- return reg;
-
- return tps65912_set_bits(mfd, reg, TPS65912_REG_ENABLED);
-}
-
-static int tps65912_reg_disable(struct regulator_dev *dev)
-{
- struct tps65912_reg *pmic = rdev_get_drvdata(dev);
- struct tps65912 *mfd = pmic->mfd;
- int id = rdev_get_id(dev), reg;
-
- reg = pmic->get_ctrl_reg(id);
- if (reg < 0)
- return reg;
-
- return tps65912_clear_bits(mfd, reg, TPS65912_REG_ENABLED);
-}
-
-static int tps65912_set_mode(struct regulator_dev *dev, unsigned int mode)
-{
- struct tps65912_reg *pmic = rdev_get_drvdata(dev);
- struct tps65912 *mfd = pmic->mfd;
- int pwm_mode, eco, id = rdev_get_id(dev);
-
- tps65912_get_mode_regiters(pmic, id);
-
- pwm_mode = tps65912_reg_read(mfd, pmic->pwm_mode_reg);
- eco = tps65912_reg_read(mfd, pmic->eco_reg);
-
- pwm_mode &= DCDCCTRL_DCDC_MODE_MASK;
- eco &= DCDC_AVS_ECO_MASK;
-
- switch (mode) {
- case REGULATOR_MODE_FAST:
- /* Verify if mode alredy set */
- if (pwm_mode && !eco)
- break;
- tps65912_set_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK);
- tps65912_clear_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK);
- break;
- case REGULATOR_MODE_NORMAL:
- case REGULATOR_MODE_IDLE:
- if (!pwm_mode && !eco)
- break;
- tps65912_clear_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK);
- tps65912_clear_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK);
- break;
- case REGULATOR_MODE_STANDBY:
- if (!pwm_mode && eco)
- break;
- tps65912_clear_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK);
- tps65912_set_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK);
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static unsigned int tps65912_get_mode(struct regulator_dev *dev)
-{
- struct tps65912_reg *pmic = rdev_get_drvdata(dev);
- struct tps65912 *mfd = pmic->mfd;
- int pwm_mode, eco, mode = 0, id = rdev_get_id(dev);
-
- tps65912_get_mode_regiters(pmic, id);
-
- pwm_mode = tps65912_reg_read(mfd, pmic->pwm_mode_reg);
- eco = tps65912_reg_read(mfd, pmic->eco_reg);
-
- pwm_mode &= DCDCCTRL_DCDC_MODE_MASK;
- eco &= DCDC_AVS_ECO_MASK;
-
- if (pwm_mode && !eco)
- mode = REGULATOR_MODE_FAST;
- else if (!pwm_mode && !eco)
- mode = REGULATOR_MODE_NORMAL;
- else if (!pwm_mode && eco)
- mode = REGULATOR_MODE_STANDBY;
-
- return mode;
-}
-
-static int tps65912_list_voltage(struct regulator_dev *dev, unsigned selector)
-{
- struct tps65912_reg *pmic = rdev_get_drvdata(dev);
- int range, voltage = 0, id = rdev_get_id(dev);
-
- if (id > TPS65912_REG_DCDC4)
- return -EINVAL;
-
- range = pmic->dcdc_range[id];
-
- switch (range) {
- case 0:
- /* 0.5 - 1.2875V in 12.5mV steps */
- voltage = tps65912_vsel_to_uv_range0(selector);
- break;
- case 1:
- /* 0.7 - 1.4875V in 12.5mV steps */
- voltage = tps65912_vsel_to_uv_range1(selector);
- break;
- case 2:
- /* 0.5 - 2.075V in 25mV steps */
- voltage = tps65912_vsel_to_uv_range2(selector);
- break;
- case 3:
- /* 0.5 - 3.8V in 50mV steps */
- voltage = tps65912_vsel_to_uv_range3(selector);
- break;
- }
- return voltage;
-}
-
-static int tps65912_get_voltage_sel(struct regulator_dev *dev)
-{
- struct tps65912_reg *pmic = rdev_get_drvdata(dev);
- struct tps65912 *mfd = pmic->mfd;
- int id = rdev_get_id(dev);
- int reg, vsel;
-
- reg = tps65912_get_sel_register(pmic, id);
- if (reg < 0)
- return reg;
-
- vsel = tps65912_reg_read(mfd, reg);
- vsel &= 0x3F;
-
- return vsel;
-}
-
-static int tps65912_set_voltage_sel(struct regulator_dev *dev,
- unsigned selector)
-{
- struct tps65912_reg *pmic = rdev_get_drvdata(dev);
- struct tps65912 *mfd = pmic->mfd;
- int id = rdev_get_id(dev);
- int value;
- u8 reg;
-
- reg = tps65912_get_sel_register(pmic, id);
- value = tps65912_reg_read(mfd, reg);
- value &= 0xC0;
- return tps65912_reg_write(mfd, reg, selector | value);
-}
-
/* Operations permitted on DCDCx */
static struct regulator_ops tps65912_ops_dcdc = {
- .is_enabled = tps65912_reg_is_enabled,
- .enable = tps65912_reg_enable,
- .disable = tps65912_reg_disable,
- .set_mode = tps65912_set_mode,
- .get_mode = tps65912_get_mode,
- .get_voltage_sel = tps65912_get_voltage_sel,
- .set_voltage_sel = tps65912_set_voltage_sel,
- .list_voltage = tps65912_list_voltage,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
};
/* Operations permitted on LDOx */
static struct regulator_ops tps65912_ops_ldo = {
- .is_enabled = tps65912_reg_is_enabled,
- .enable = tps65912_reg_enable,
- .disable = tps65912_reg_disable,
- .get_voltage_sel = tps65912_get_voltage_sel,
- .set_voltage_sel = tps65912_set_voltage_sel,
- .list_voltage = regulator_list_voltage_linear_range,
- .map_voltage = regulator_map_voltage_linear_range,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+};
+
+static const struct regulator_desc regulators[] = {
+ TPS65912_REGULATOR("DCDC1", DCDC1, "dcdc1", tps65912_ops_dcdc,
+ TPS65912_DCDC1_OP, TPS65912_DCDC1_CTRL,
+ tps65912_dcdc_ranges),
+ TPS65912_REGULATOR("DCDC2", DCDC2, "dcdc2", tps65912_ops_dcdc,
+ TPS65912_DCDC2_OP, TPS65912_DCDC2_CTRL,
+ tps65912_dcdc_ranges),
+ TPS65912_REGULATOR("DCDC3", DCDC3, "dcdc3", tps65912_ops_dcdc,
+ TPS65912_DCDC3_OP, TPS65912_DCDC3_CTRL,
+ tps65912_dcdc_ranges),
+ TPS65912_REGULATOR("DCDC4", DCDC4, "dcdc4", tps65912_ops_dcdc,
+ TPS65912_DCDC4_OP, TPS65912_DCDC4_CTRL,
+ tps65912_dcdc_ranges),
+ TPS65912_REGULATOR("LDO1", LDO1, "ldo1", tps65912_ops_ldo,
+ TPS65912_LDO1_OP, TPS65912_LDO1_AVS,
+ tps65912_ldo_ranges),
+ TPS65912_REGULATOR("LDO2", LDO2, "ldo2", tps65912_ops_ldo,
+ TPS65912_LDO2_OP, TPS65912_LDO2_AVS,
+ tps65912_ldo_ranges),
+ TPS65912_REGULATOR("LDO3", LDO3, "ldo3", tps65912_ops_ldo,
+ TPS65912_LDO3_OP, TPS65912_LDO3_AVS,
+ tps65912_ldo_ranges),
+ TPS65912_REGULATOR("LDO4", LDO4, "ldo4", tps65912_ops_ldo,
+ TPS65912_LDO4_OP, TPS65912_LDO4_AVS,
+ tps65912_ldo_ranges),
+ TPS65912_REGULATOR("LDO5", LDO5, "ldo5", tps65912_ops_ldo,
+ TPS65912_LDO5, TPS65912_LDO5,
+ tps65912_ldo_ranges),
+ TPS65912_REGULATOR("LDO6", LDO6, "ldo6", tps65912_ops_ldo,
+ TPS65912_LDO6, TPS65912_LDO6,
+ tps65912_ldo_ranges),
+ TPS65912_REGULATOR("LDO7", LDO7, "ldo7", tps65912_ops_ldo,
+ TPS65912_LDO7, TPS65912_LDO7,
+ tps65912_ldo_ranges),
+ TPS65912_REGULATOR("LDO8", LDO8, "ldo8", tps65912_ops_ldo,
+ TPS65912_LDO8, TPS65912_LDO8,
+ tps65912_ldo_ranges),
+ TPS65912_REGULATOR("LDO9", LDO9, "ldo9", tps65912_ops_ldo,
+ TPS65912_LDO9, TPS65912_LDO9,
+ tps65912_ldo_ranges),
+ TPS65912_REGULATOR("LDO10", LDO10, "ldo10", tps65912_ops_ldo,
+ TPS65912_LDO10, TPS65912_LDO10,
+ tps65912_ldo_ranges),
};
-static int tps65912_probe(struct platform_device *pdev)
+static int tps65912_regulator_probe(struct platform_device *pdev)
{
- struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
+ struct tps65912 *tps = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = { };
- struct tps_info *info;
- struct regulator_init_data *reg_data;
struct regulator_dev *rdev;
- struct tps65912_reg *pmic;
- struct tps65912_board *pmic_plat_data;
int i;
- pmic_plat_data = dev_get_platdata(tps65912->dev);
- if (!pmic_plat_data)
- return -EINVAL;
+ platform_set_drvdata(pdev, tps);
- reg_data = pmic_plat_data->tps65912_pmic_init_data;
+ config.dev = &pdev->dev;
+ config.driver_data = tps;
+ config.dev->of_node = tps->dev->of_node;
+ config.regmap = tps->regmap;
- pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
- if (!pmic)
- return -ENOMEM;
-
- mutex_init(&pmic->io_lock);
- pmic->mfd = tps65912;
- platform_set_drvdata(pdev, pmic);
-
- pmic->get_ctrl_reg = &tps65912_get_ctrl_register;
- info = tps65912_regs;
-
- for (i = 0; i < TPS65912_NUM_REGULATOR; i++, info++, reg_data++) {
- int range = 0;
- /* Register the regulators */
- pmic->info[i] = info;
-
- pmic->desc[i].name = info->name;
- pmic->desc[i].id = i;
- pmic->desc[i].n_voltages = 64;
- if (i > TPS65912_REG_DCDC4) {
- pmic->desc[i].ops = &tps65912_ops_ldo;
- pmic->desc[i].linear_ranges = tps65912_ldo_ranges;
- pmic->desc[i].n_linear_ranges =
- ARRAY_SIZE(tps65912_ldo_ranges);
- } else {
- pmic->desc[i].ops = &tps65912_ops_dcdc;
- }
- pmic->desc[i].type = REGULATOR_VOLTAGE;
- pmic->desc[i].owner = THIS_MODULE;
- range = tps65912_get_range(pmic, i);
-
- config.dev = tps65912->dev;
- config.init_data = reg_data;
- config.driver_data = pmic;
-
- rdev = devm_regulator_register(&pdev->dev, &pmic->desc[i],
+ for (i = 0; i < ARRAY_SIZE(regulators); i++) {
+ rdev = devm_regulator_register(&pdev->dev, &regulators[i],
&config);
if (IS_ERR(rdev)) {
- dev_err(tps65912->dev,
- "failed to register %s regulator\n",
+ dev_err(tps->dev, "failed to register %s regulator\n",
pdev->name);
return PTR_ERR(rdev);
}
-
- /* Save regulator for cleanup */
- pmic->rdev[i] = rdev;
}
+
return 0;
}
-static struct platform_driver tps65912_driver = {
+static const struct platform_device_id tps65912_regulator_id_table[] = {
+ { "tps65912-regulator", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, tps65912_regulator_id_table);
+
+static struct platform_driver tps65912_regulator_driver = {
.driver = {
- .name = "tps65912-pmic",
+ .name = "tps65912-regulator",
},
- .probe = tps65912_probe,
+ .probe = tps65912_regulator_probe,
+ .id_table = tps65912_regulator_id_table,
};
+module_platform_driver(tps65912_regulator_driver);
-static int __init tps65912_init(void)
-{
- return platform_driver_register(&tps65912_driver);
-}
-subsys_initcall(tps65912_init);
-
-static void __exit tps65912_cleanup(void)
-{
- platform_driver_unregister(&tps65912_driver);
-}
-module_exit(tps65912_cleanup);
-
-MODULE_AUTHOR("Margarita Olaya Cabrera <magi@slimlogic.co.uk>");
+MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>");
MODULE_DESCRIPTION("TPS65912 voltage regulator driver");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:tps65912-pmic");
diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress-regulator.c
index c810cbbd4..c810cbbd4 100644
--- a/drivers/regulator/vexpress.c
+++ b/drivers/regulator/vexpress-regulator.c