From f74521ca578f38daa3e800efde7fdb2ac3ba76ef Mon Sep 17 00:00:00 2001 From: MyungJoo Ham Date: Mon, 8 May 2017 05:45:44 +0000 Subject: [PATCH 1/8] regulator: max8997/8966: fix charger cv voltage set bug When min charger-CV is <= 4.0V and max charger-CV is >= 4.0V, we can use 4.00V as CV (register value = 0x1).` The original code had a typo that wrote ">=" (max_uV >= 4000000), which should've been "<", which is not necessary anyway as mentioned by Dan Carpenter. Reported-By: Dan Carpenter Signed-off-by: MyungJoo Ham Reviewed-by: Bartlomiej Zolnierkiewicz Reviewed-by: Chanwoo Choi Signed-off-by: Mark Brown --- drivers/regulator/max8997-regulator.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/max8997-regulator.c b/drivers/regulator/max8997-regulator.c index efabc0ea0e96..559b9ac45404 100644 --- a/drivers/regulator/max8997-regulator.c +++ b/drivers/regulator/max8997-regulator.c @@ -428,12 +428,9 @@ static int max8997_set_voltage_charger_cv(struct regulator_dev *rdev, if (max_uV < 4000000 || min_uV > 4350000) return -EINVAL; - if (min_uV <= 4000000) { - if (max_uV >= 4000000) - return -EINVAL; - else - val = 0x1; - } else if (min_uV <= 4200000 && max_uV >= 4200000) + if (min_uV <= 4000000) + val = 0x1; + else if (min_uV <= 4200000 && max_uV >= 4200000) val = 0x0; else { lb = (min_uV - 4000001) / 20000 + 2; From 96e4f5232c8cdb64cb18721ea0871c849346cbf5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 4 May 2017 22:10:51 +0200 Subject: [PATCH 2/8] regulator: palmas: Drop unnecessary static Drop static on a local variable, when the variable is initialized before any use, on every possible execution path through the function. The semantic patch that fixes this problem is as follows: (http://coccinelle.lip6.fr/) // @bad exists@ position p; identifier x; type T; @@ static T x@p; ... x = <+...x...+> @@ identifier x; expression e; type T; position p != bad.p; @@ -static T x@p; ... when != x when strict ?x = e; // There is no reduction in code size in this case, but the change does reduce the size of the bss segment, containing uninitialized static data. before: text data bss dec hex filename 12882 3480 8 16370 3ff2 drivers/regulator/palmas-regulator.o after: text data bss dec hex filename 12882 3480 0 16362 3fea drivers/regulator/palmas-regulator.o Signed-off-by: Julia Lawall Signed-off-by: Mark Brown --- drivers/regulator/palmas-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 31ae5ee3a80d..34d4a62283d7 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -1491,7 +1491,7 @@ static int palmas_dt_to_pdata(struct device *dev, } for (idx = 0; idx < ddata->max_reg; idx++) { - static struct of_regulator_match *match; + struct of_regulator_match *match; struct palmas_reg_init *rinit; struct device_node *np; From 80aec6f536e68d2a0483e5d1d67ea4572937cf43 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 10 May 2017 09:30:20 +0100 Subject: [PATCH 3/8] regulator: lp8755: fix spelling mistake "acceess" -> "access" Trivial fix to spelling mistake in dev_err messages. Signed-off-by: Colin Ian King Signed-off-by: Mark Brown --- drivers/regulator/lp8755.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c index db34e1da75ef..244822bb63cd 100644 --- a/drivers/regulator/lp8755.c +++ b/drivers/regulator/lp8755.c @@ -99,7 +99,7 @@ static int lp8755_buck_enable_time(struct regulator_dev *rdev) ret = lp8755_read(pchip, 0x12 + id, ®val); if (ret < 0) { - dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + dev_err(pchip->dev, "i2c access error %s\n", __func__); return ret; } return (regval & 0xff) * 100; @@ -144,7 +144,7 @@ static int lp8755_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) goto err_i2c; return ret; err_i2c: - dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + dev_err(pchip->dev, "i2c access error %s\n", __func__); return ret; } @@ -175,7 +175,7 @@ static unsigned int lp8755_buck_get_mode(struct regulator_dev *rdev) return REGULATOR_MODE_NORMAL; err_i2c: - dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + dev_err(pchip->dev, "i2c access error %s\n", __func__); return 0; } @@ -223,7 +223,7 @@ static int lp8755_buck_set_ramp(struct regulator_dev *rdev, int ramp) goto err_i2c; return ret; err_i2c: - dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + dev_err(pchip->dev, "i2c access error %s\n", __func__); return ret; } @@ -295,7 +295,7 @@ static int lp8755_init_data(struct lp8755_chip *pchip) return ret; out_i2c_error: - dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + dev_err(pchip->dev, "i2c access error %s\n", __func__); return ret; } @@ -404,7 +404,7 @@ static irqreturn_t lp8755_irq_handler(int irq, void *data) return IRQ_HANDLED; err_i2c: - dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + dev_err(pchip->dev, "i2c access error %s\n", __func__); return IRQ_NONE; } @@ -420,7 +420,7 @@ static int lp8755_int_config(struct lp8755_chip *pchip) ret = lp8755_read(pchip, 0x0F, ®val); if (ret < 0) { - dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + dev_err(pchip->dev, "i2c access error %s\n", __func__); return ret; } From f0168a9bfdfd6058c78207616348fed3cd52e739 Mon Sep 17 00:00:00 2001 From: Keerthy Date: Tue, 23 May 2017 17:46:55 +0530 Subject: [PATCH 4/8] regulator: lp87565: Add support for lp87565 PMIC regulators The regulators set consists of 4 BUCKs. The output voltages are configurable and are meant to supply power to the main processor and other components. The ramp delay is configurable for all BUCKs. The BUCKs can be configured in single phase or multiphase modes. Signed-off-by: Keerthy Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 8 + drivers/regulator/Makefile | 1 + drivers/regulator/lp87565-regulator.c | 237 ++++++++++++++++++++++++++ 3 files changed, 246 insertions(+) create mode 100644 drivers/regulator/lp87565-regulator.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 48db87d6dfef..7c34ff8a5884 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -365,6 +365,14 @@ config REGULATOR_LP8755 chip contains six step-down DC/DC converters which can support 9 mode multiphase configuration. +config REGULATOR_LP87565 + tristate "TI LP87565 Power regulators" + depends on MFD_TI_LP87565 && OF + help + This driver supports LP87565 voltage regulator chips. LP87565 + provides four step-down converters. It supports software based + voltage control for different voltage domains + config REGULATOR_LP8788 tristate "TI LP8788 Power Regulators" depends on MFD_LP8788 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index dc3503fb3e30..fee6b8cb80a8 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o obj-$(CONFIG_REGULATOR_LP873X) += lp873x-regulator.o +obj-$(CONFIG_REGULATOR_LP87565) += lp87565-regulator.o obj-$(CONFIG_REGULATOR_LP8788) += lp8788-buck.o obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o obj-$(CONFIG_REGULATOR_LP8755) += lp8755.o diff --git a/drivers/regulator/lp87565-regulator.c b/drivers/regulator/lp87565-regulator.c new file mode 100644 index 000000000000..71e762292529 --- /dev/null +++ b/drivers/regulator/lp87565-regulator.c @@ -0,0 +1,237 @@ +/* + * Regulator driver for LP87565 PMIC + * + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.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 +#include +#include + +#include + +#define LP87565_REGULATOR(_name, _id, _of, _ops, _n, _vr, _vm, _er, _em, \ + _delay, _lr, _cr) \ + [_id] = { \ + .desc = { \ + .name = _name, \ + .supply_name = _of "-in", \ + .id = _id, \ + .of_match = of_match_ptr(_of), \ + .regulators_node = of_match_ptr("regulators"),\ + .ops = &_ops, \ + .n_voltages = _n, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .vsel_reg = _vr, \ + .vsel_mask = _vm, \ + .enable_reg = _er, \ + .enable_mask = _em, \ + .ramp_delay = _delay, \ + .linear_ranges = _lr, \ + .n_linear_ranges = ARRAY_SIZE(_lr), \ + }, \ + .ctrl2_reg = _cr, \ + } + +struct lp87565_regulator { + struct regulator_desc desc; + unsigned int ctrl2_reg; +}; + +static const struct lp87565_regulator regulators[]; + +static const struct regulator_linear_range buck0_1_2_3_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0x0, 0x17, 10000), + REGULATOR_LINEAR_RANGE(735000, 0x18, 0x9d, 5000), + REGULATOR_LINEAR_RANGE(1420000, 0x9e, 0xff, 20000), +}; + +static unsigned int lp87565_buck_ramp_delay[] = { + 30000, 15000, 10000, 7500, 3800, 1900, 940, 470 +}; + +/* LP87565 BUCK current limit */ +static const unsigned int lp87565_buck_uA[] = { + 1500000, 2000000, 2500000, 3000000, 3500000, 4000000, 4500000, 5000000, +}; + +static int lp87565_buck_set_ramp_delay(struct regulator_dev *rdev, + int ramp_delay) +{ + int id = rdev_get_id(rdev); + struct lp87565 *lp87565 = rdev_get_drvdata(rdev); + unsigned int reg; + int ret; + + if (ramp_delay <= 470) + reg = 7; + else if (ramp_delay <= 940) + reg = 6; + else if (ramp_delay <= 1900) + reg = 5; + else if (ramp_delay <= 3800) + reg = 4; + else if (ramp_delay <= 7500) + reg = 3; + else if (ramp_delay <= 10000) + reg = 2; + else if (ramp_delay <= 15000) + reg = 1; + else + reg = 0; + + ret = regmap_update_bits(lp87565->regmap, regulators[id].ctrl2_reg, + LP87565_BUCK_CTRL_2_SLEW_RATE, + reg << __ffs(LP87565_BUCK_CTRL_2_SLEW_RATE)); + if (ret) { + dev_err(lp87565->dev, "SLEW RATE write failed: %d\n", ret); + return ret; + } + + rdev->constraints->ramp_delay = lp87565_buck_ramp_delay[reg]; + + return 0; +} + +static int lp87565_buck_set_current_limit(struct regulator_dev *rdev, + int min_uA, int max_uA) +{ + int id = rdev_get_id(rdev); + struct lp87565 *lp87565 = rdev_get_drvdata(rdev); + int i; + + for (i = ARRAY_SIZE(lp87565_buck_uA) - 1; i >= 0; i--) { + if (lp87565_buck_uA[i] >= min_uA && + lp87565_buck_uA[i] <= max_uA) + return regmap_update_bits(lp87565->regmap, + regulators[id].ctrl2_reg, + LP87565_BUCK_CTRL_2_ILIM, + i << __ffs(LP87565_BUCK_CTRL_2_ILIM)); + } + + return -EINVAL; +} + +static int lp87565_buck_get_current_limit(struct regulator_dev *rdev) +{ + int id = rdev_get_id(rdev); + struct lp87565 *lp87565 = rdev_get_drvdata(rdev); + int ret; + unsigned int val; + + ret = regmap_read(lp87565->regmap, regulators[id].ctrl2_reg, &val); + if (ret) + return ret; + + val = (val & LP87565_BUCK_CTRL_2_ILIM) >> + __ffs(LP87565_BUCK_CTRL_2_ILIM); + + return (val < ARRAY_SIZE(lp87565_buck_uA)) ? + lp87565_buck_uA[val] : -EINVAL; +} + +/* Operations permitted on BUCK0, BUCK1 */ +static struct regulator_ops lp87565_buck_ops = { + .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, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_ramp_delay = lp87565_buck_set_ramp_delay, + .set_current_limit = lp87565_buck_set_current_limit, + .get_current_limit = lp87565_buck_get_current_limit, +}; + +static const struct lp87565_regulator regulators[] = { + LP87565_REGULATOR("BUCK0", LP87565_BUCK_0, "buck0", lp87565_buck_ops, + 256, LP87565_REG_BUCK0_VOUT, LP87565_BUCK_VSET, + LP87565_REG_BUCK0_CTRL_1, + LP87565_BUCK_CTRL_1_EN, 3800, + buck0_1_2_3_ranges, LP87565_REG_BUCK0_CTRL_2), + LP87565_REGULATOR("BUCK1", LP87565_BUCK_1, "buck1", lp87565_buck_ops, + 256, LP87565_REG_BUCK1_VOUT, LP87565_BUCK_VSET, + LP87565_REG_BUCK1_CTRL_1, + LP87565_BUCK_CTRL_1_EN, 3800, + buck0_1_2_3_ranges, LP87565_REG_BUCK1_CTRL_2), + LP87565_REGULATOR("BUCK2", LP87565_BUCK_2, "buck2", lp87565_buck_ops, + 256, LP87565_REG_BUCK2_VOUT, LP87565_BUCK_VSET, + LP87565_REG_BUCK2_CTRL_1, + LP87565_BUCK_CTRL_1_EN, 3800, + buck0_1_2_3_ranges, LP87565_REG_BUCK2_CTRL_2), + LP87565_REGULATOR("BUCK3", LP87565_BUCK_3, "buck3", lp87565_buck_ops, + 256, LP87565_REG_BUCK3_VOUT, LP87565_BUCK_VSET, + LP87565_REG_BUCK3_CTRL_1, + LP87565_BUCK_CTRL_1_EN, 3800, + buck0_1_2_3_ranges, LP87565_REG_BUCK3_CTRL_2), + LP87565_REGULATOR("BUCK10", LP87565_BUCK_10, "buck10", lp87565_buck_ops, + 256, LP87565_REG_BUCK0_VOUT, LP87565_BUCK_VSET, + LP87565_REG_BUCK0_CTRL_1, + LP87565_BUCK_CTRL_1_EN, 3800, + buck0_1_2_3_ranges, LP87565_REG_BUCK0_CTRL_2), + LP87565_REGULATOR("BUCK23", LP87565_BUCK_23, "buck23", lp87565_buck_ops, + 256, LP87565_REG_BUCK2_VOUT, LP87565_BUCK_VSET, + LP87565_REG_BUCK2_CTRL_1, + LP87565_BUCK_CTRL_1_EN, 3800, + buck0_1_2_3_ranges, LP87565_REG_BUCK2_CTRL_2), +}; + +static int lp87565_regulator_probe(struct platform_device *pdev) +{ + struct lp87565 *lp87565 = dev_get_drvdata(pdev->dev.parent); + struct regulator_config config = { }; + struct regulator_dev *rdev; + int i, min_idx = LP87565_BUCK_1, max_idx = LP87565_BUCK_3; + + platform_set_drvdata(pdev, lp87565); + + config.dev = &pdev->dev; + config.dev->of_node = lp87565->dev->of_node; + config.driver_data = lp87565; + config.regmap = lp87565->regmap; + + if (lp87565->dev_type == LP87565_DEVICE_TYPE_LP87565_Q1) { + min_idx = LP87565_BUCK_10; + max_idx = LP87565_BUCK_23; + } + + for (i = min_idx; i <= max_idx; i++) { + rdev = devm_regulator_register(&pdev->dev, ®ulators[i].desc, + &config); + if (IS_ERR(rdev)) { + dev_err(lp87565->dev, "failed to register %s regulator\n", + pdev->name); + return PTR_ERR(rdev); + } + } + + return 0; +} + +static const struct platform_device_id lp87565_regulator_id_table[] = { + { "lp87565-regulator", }, + { "lp87565-q1-regulator", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, lp87565_regulator_id_table); + +static struct platform_driver lp87565_regulator_driver = { + .driver = { + .name = "lp87565-pmic", + }, + .probe = lp87565_regulator_probe, + .id_table = lp87565_regulator_id_table, +}; +module_platform_driver(lp87565_regulator_driver); + +MODULE_AUTHOR("J Keerthy "); +MODULE_DESCRIPTION("LP87565 voltage regulator driver"); +MODULE_LICENSE("GPL v2"); From 5c7024ae7e6787541dd737ba1eba828d5fc74d58 Mon Sep 17 00:00:00 2001 From: Wang Xiaoyin Date: Wed, 7 Jun 2017 15:06:03 +0800 Subject: [PATCH 5/8] regulator: hi6421v530: add driver for hi6421v530 voltage regulator add the driver for hi6421v530 voltage regulator Signed-off-by: Wang Xiaoyin Signed-off-by: Guodong Xu Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 10 ++ drivers/regulator/Makefile | 1 + drivers/regulator/hi6421v530-regulator.c | 207 +++++++++++++++++++++++ 3 files changed, 218 insertions(+) create mode 100644 drivers/regulator/hi6421v530-regulator.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 48db87d6dfef..78cd8d84a2cb 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -296,6 +296,16 @@ 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_HI6421V530 + tristate "HiSilicon Hi6421v530 PMIC voltage regulator support" + depends on MFD_HI6421_PMIC && OF + help + This driver provides support for the voltage regulators on + HiSilicon Hi6421v530 PMU / Codec IC. + Hi6421v530 is a multi-function device which, on regulator part, + provides 5 general purpose LDOs, and 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 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index dc3503fb3e30..36e2b750b188 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -38,6 +38,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_HI6421V530) += hi6421v530-regulator.o obj-$(CONFIG_REGULATOR_HI655X) += hi655x-regulator.o obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o diff --git a/drivers/regulator/hi6421v530-regulator.c b/drivers/regulator/hi6421v530-regulator.c new file mode 100644 index 000000000000..46bbba96307f --- /dev/null +++ b/drivers/regulator/hi6421v530-regulator.c @@ -0,0 +1,207 @@ +/* + * Device driver for regulators in Hi6421V530 IC + * + * Copyright (c) <2017> HiSilicon Technologies Co., Ltd. + * http://www.hisilicon.com + * Copyright (c) <2017> Linaro Ltd. + * http://www.linaro.org + * + * Author: Wang Xiaoyin + * Guodong Xu + * + * 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 +#include +#include +#include +#include +#include + +/* + * struct hi6421v530_regulator_info - hi6421v530 regulator information + * @desc: regulator description + * @mode_mask: ECO mode bitmask of LDOs; for BUCKs, this masks sleep + * @eco_microamp: eco mode load upper limit (in uA), valid for LDOs only + */ +struct hi6421v530_regulator_info { + struct regulator_desc rdesc; + u8 mode_mask; + u32 eco_microamp; +}; + +/* HI6421v530 regulators */ +enum hi6421v530_regulator_id { + HI6421V530_LDO3, + HI6421V530_LDO9, + HI6421V530_LDO11, + HI6421V530_LDO15, + HI6421V530_LDO16, +}; + +static const unsigned int ldo_3_voltages[] = { + 1800000, 1825000, 1850000, 1875000, + 1900000, 1925000, 1950000, 1975000, + 2000000, 2025000, 2050000, 2075000, + 2100000, 2125000, 2150000, 2200000, +}; + +static const unsigned int ldo_9_11_voltages[] = { + 1750000, 1800000, 1825000, 2800000, + 2850000, 2950000, 3000000, 3300000, +}; + +static const unsigned int ldo_15_16_voltages[] = { + 1750000, 1800000, 2400000, 2600000, + 2700000, 2850000, 2950000, 3000000, +}; + +static const struct regulator_ops hi6421v530_ldo_ops; + +#define HI6421V530_LDO_ENABLE_TIME (350) + +/* + * _id - LDO id name string + * v_table - voltage table + * vreg - voltage select register + * vmask - voltage select mask + * ereg - enable register + * emask - enable mask + * odelay - off/on delay time in uS + * ecomask - eco mode mask + * ecoamp - eco mode load uppler limit in uA + */ +#define HI6421V530_LDO(_ID, v_table, vreg, vmask, ereg, emask, \ + odelay, ecomask, ecoamp) { \ + .rdesc = { \ + .name = #_ID, \ + .of_match = of_match_ptr(#_ID), \ + .regulators_node = of_match_ptr("regulators"), \ + .ops = &hi6421v530_ldo_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = HI6421V530_##_ID, \ + .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(v_table), \ + .volt_table = v_table, \ + .vsel_reg = HI6421_REG_TO_BUS_ADDR(vreg), \ + .vsel_mask = vmask, \ + .enable_reg = HI6421_REG_TO_BUS_ADDR(ereg), \ + .enable_mask = emask, \ + .enable_time = HI6421V530_LDO_ENABLE_TIME, \ + .off_on_delay = odelay, \ + }, \ + .mode_mask = ecomask, \ + .eco_microamp = ecoamp, \ +} + +/* HI6421V530 regulator information */ + +static struct hi6421v530_regulator_info hi6421v530_regulator_info[] = { + HI6421V530_LDO(LDO3, ldo_3_voltages, 0x061, 0xf, 0x060, 0x2, + 20000, 0x6, 8000), + HI6421V530_LDO(LDO9, ldo_9_11_voltages, 0x06b, 0x7, 0x06a, 0x2, + 40000, 0x6, 8000), + HI6421V530_LDO(LDO11, ldo_9_11_voltages, 0x06f, 0x7, 0x06e, 0x2, + 40000, 0x6, 8000), + HI6421V530_LDO(LDO15, ldo_15_16_voltages, 0x077, 0x7, 0x076, 0x2, + 40000, 0x6, 8000), + HI6421V530_LDO(LDO16, ldo_15_16_voltages, 0x079, 0x7, 0x078, 0x2, + 40000, 0x6, 8000), +}; + +static unsigned int hi6421v530_regulator_ldo_get_mode( + struct regulator_dev *rdev) +{ + struct hi6421v530_regulator_info *info; + unsigned int reg_val; + + info = rdev_get_drvdata(rdev); + regmap_read(rdev->regmap, rdev->desc->enable_reg, ®_val); + + if (reg_val & (info->mode_mask)) + return REGULATOR_MODE_IDLE; + + return REGULATOR_MODE_NORMAL; +} + +static int hi6421v530_regulator_ldo_set_mode(struct regulator_dev *rdev, + unsigned int mode) +{ + struct hi6421v530_regulator_info *info; + unsigned int new_mode; + + info = rdev_get_drvdata(rdev); + switch (mode) { + case REGULATOR_MODE_NORMAL: + new_mode = 0; + break; + case REGULATOR_MODE_IDLE: + new_mode = info->mode_mask; + break; + default: + return -EINVAL; + } + + regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + info->mode_mask, new_mode); + + return 0; +} + + +static const struct regulator_ops hi6421v530_ldo_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .list_voltage = regulator_list_voltage_table, + .map_voltage = regulator_map_voltage_ascend, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_mode = hi6421v530_regulator_ldo_get_mode, + .set_mode = hi6421v530_regulator_ldo_set_mode, +}; + +static int hi6421v530_regulator_probe(struct platform_device *pdev) +{ + struct hi6421_pmic *pmic; + struct regulator_dev *rdev; + struct regulator_config config = { }; + unsigned int i; + + pmic = dev_get_drvdata(pdev->dev.parent); + if (!pmic) { + dev_err(&pdev->dev, "no pmic in the regulator parent node\n"); + return -ENODEV; + } + + for (i = 0; i < ARRAY_SIZE(hi6421v530_regulator_info); i++) { + config.dev = pdev->dev.parent; + config.regmap = pmic->regmap; + config.driver_data = &hi6421v530_regulator_info[i]; + + rdev = devm_regulator_register(&pdev->dev, + &hi6421v530_regulator_info[i].rdesc, + &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "failed to register regulator %s\n", + hi6421v530_regulator_info[i].rdesc.name); + return PTR_ERR(rdev); + } + } + return 0; +} + +static struct platform_driver hi6421v530_regulator_driver = { + .driver = { + .name = "hi6421v530-regulator", + }, + .probe = hi6421v530_regulator_probe, +}; +module_platform_driver(hi6421v530_regulator_driver); + +MODULE_AUTHOR("Wang Xiaoyin "); +MODULE_DESCRIPTION("Hi6421v530 regulator driver"); +MODULE_LICENSE("GPL v2"); From 580331d04982eb0d96085d57c04d7f69cc05b7d1 Mon Sep 17 00:00:00 2001 From: Keerthy Date: Tue, 6 Jun 2017 14:35:02 +0530 Subject: [PATCH 6/8] regulator: lp87565: Fix the GPL header Fix the GPL header to reflect GPL v2 Signed-off-by: Keerthy Signed-off-by: Mark Brown --- drivers/regulator/lp87565-regulator.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/regulator/lp87565-regulator.c b/drivers/regulator/lp87565-regulator.c index 71e762292529..6d92c3fe39a3 100644 --- a/drivers/regulator/lp87565-regulator.c +++ b/drivers/regulator/lp87565-regulator.c @@ -5,8 +5,7 @@ * * 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. + * Free Software Foundation version 2. */ #include From ded7b2aeefaff4e9d52a935e13ff1f1970b7cfda Mon Sep 17 00:00:00 2001 From: Guodong Xu Date: Wed, 14 Jun 2017 23:11:06 +0800 Subject: [PATCH 7/8] regulator: hi6421v530: Describe consumed platform device The hi6421v530-regulator driver consumes a similarly named platform device. Adding that to the module device table, allows modprobe to locate this driver once the device is created. Signed-off-by: Guodong Xu Signed-off-by: Mark Brown --- drivers/regulator/hi6421v530-regulator.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/regulator/hi6421v530-regulator.c b/drivers/regulator/hi6421v530-regulator.c index 46bbba96307f..c09bc71538a5 100644 --- a/drivers/regulator/hi6421v530-regulator.c +++ b/drivers/regulator/hi6421v530-regulator.c @@ -194,7 +194,14 @@ static int hi6421v530_regulator_probe(struct platform_device *pdev) return 0; } +static const struct platform_device_id hi6421v530_regulator_table[] = { + { .name = "hi6421v530-regulator" }, + {}, +}; +MODULE_DEVICE_TABLE(platform, hi6421v530_regulator_table); + static struct platform_driver hi6421v530_regulator_driver = { + .id_table = hi6421v530_regulator_table, .driver = { .name = "hi6421v530-regulator", }, From 42f1ea48efd99394a4790e8ab956f1fb8e0a931e Mon Sep 17 00:00:00 2001 From: Keerthy Date: Tue, 20 Jun 2017 09:06:55 +0530 Subject: [PATCH 8/8] regulator: lp87565: Fix the initial voltage range The latest documentation reveals that initial voltage range that is supported is starting from 0.6V for all the PMICs belonging to lp87565 family. Fix the same. Signed-off-by: Keerthy Fixes: f0168a9bf ("regulator: lp87565: Add support for lp87565 PMIC regulators") Signed-off-by: Mark Brown --- drivers/regulator/lp87565-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/lp87565-regulator.c b/drivers/regulator/lp87565-regulator.c index 6d92c3fe39a3..cfdbe294fb6a 100644 --- a/drivers/regulator/lp87565-regulator.c +++ b/drivers/regulator/lp87565-regulator.c @@ -46,7 +46,7 @@ struct lp87565_regulator { static const struct lp87565_regulator regulators[]; static const struct regulator_linear_range buck0_1_2_3_ranges[] = { - REGULATOR_LINEAR_RANGE(500000, 0x0, 0x17, 10000), + REGULATOR_LINEAR_RANGE(600000, 0xA, 0x17, 10000), REGULATOR_LINEAR_RANGE(735000, 0x18, 0x9d, 5000), REGULATOR_LINEAR_RANGE(1420000, 0x9e, 0xff, 20000), };