From 2cd64ae3d57b80f6d93682b98a59ed4b124cf2ef Mon Sep 17 00:00:00 2001 From: Chris Zhong Date: Wed, 20 Aug 2014 11:36:42 +0800 Subject: regulator: RK808: Add regulator driver for RK808 The regulator module consists of 4 DCDCs, 8 LDOs and 2 switches. The output voltages are configurable and are meant to supply power to the main processor and other components Signed-off-by: Chris Zhong Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 410 ++++++++++++++++++++++++++++++++++++ 1 file changed, 410 insertions(+) create mode 100644 drivers/regulator/rk808-regulator.c (limited to 'drivers/regulator/rk808-regulator.c') diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c new file mode 100644 index 000000000000..94753fd311c1 --- /dev/null +++ b/drivers/regulator/rk808-regulator.c @@ -0,0 +1,410 @@ +/* + * Regulator driver for Rockchip RK808 + * + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * + * Author: Chris Zhong + * Author: Zhang Qing + * + * 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. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* + * Field Definitions. + */ +#define RK808_BUCK_VSEL_MASK 0x3f +#define RK808_BUCK4_VSEL_MASK 0xf +#define RK808_LDO_VSEL_MASK 0x1f + +static const int buck_set_vol_base_addr[] = { + RK808_BUCK1_ON_VSEL_REG, + RK808_BUCK2_ON_VSEL_REG, + RK808_BUCK3_CONFIG_REG, + RK808_BUCK4_ON_VSEL_REG, +}; + +static const int buck_contr_base_addr[] = { + RK808_BUCK1_CONFIG_REG, + RK808_BUCK2_CONFIG_REG, + RK808_BUCK3_CONFIG_REG, + RK808_BUCK4_CONFIG_REG, +}; + +#define rk808_BUCK_SET_VOL_REG(x) (buck_set_vol_base_addr[x]) +#define rk808_BUCK_CONTR_REG(x) (buck_contr_base_addr[x]) +#define rk808_LDO_SET_VOL_REG(x) (ldo_set_vol_base_addr[x]) + +static const int ldo_set_vol_base_addr[] = { + RK808_LDO1_ON_VSEL_REG, + RK808_LDO2_ON_VSEL_REG, + RK808_LDO3_ON_VSEL_REG, + RK808_LDO4_ON_VSEL_REG, + RK808_LDO5_ON_VSEL_REG, + RK808_LDO6_ON_VSEL_REG, + RK808_LDO7_ON_VSEL_REG, + RK808_LDO8_ON_VSEL_REG, +}; + +/* + * rk808 voltage number + */ +static const struct regulator_linear_range rk808_buck_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(700000, 0, 63, 12500), +}; + +static const struct regulator_linear_range rk808_buck4_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(1800000, 0, 15, 100000), +}; + +static const struct regulator_linear_range rk808_ldo_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(1800000, 0, 16, 100000), +}; + +static const struct regulator_linear_range rk808_ldo3_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(800000, 0, 13, 100000), + REGULATOR_LINEAR_RANGE(2500000, 15, 15, 0), +}; + +static const struct regulator_linear_range rk808_ldo6_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(800000, 0, 17, 100000), +}; + +static struct regulator_ops rk808_reg_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, +}; + +static struct regulator_ops rk808_switch_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + +static const struct regulator_desc rk808_reg[] = { + { + .name = "DCDC_REG1", + .id = RK808_ID_DCDC1, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 64, + .linear_ranges = rk808_buck_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_buck_voltage_ranges), + .vsel_reg = RK808_BUCK1_ON_VSEL_REG, + .vsel_mask = RK808_BUCK_VSEL_MASK, + .enable_reg = RK808_DCDC_EN_REG, + .enable_mask = BIT(0), + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG2", + .id = RK808_ID_DCDC2, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 64, + .linear_ranges = rk808_buck_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_buck_voltage_ranges), + .vsel_reg = RK808_BUCK2_ON_VSEL_REG, + .vsel_mask = RK808_BUCK_VSEL_MASK, + .enable_reg = RK808_DCDC_EN_REG, + .enable_mask = BIT(1), + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG3", + .id = RK808_ID_DCDC3, + .ops = &rk808_switch_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 1, + .enable_reg = RK808_DCDC_EN_REG, + .enable_mask = BIT(2), + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG4", + .id = RK808_ID_DCDC4, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 17, + .linear_ranges = rk808_buck4_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_buck4_voltage_ranges), + .vsel_reg = RK808_BUCK4_ON_VSEL_REG, + .vsel_mask = RK808_BUCK4_VSEL_MASK, + .enable_reg = RK808_DCDC_EN_REG, + .enable_mask = BIT(3), + .owner = THIS_MODULE, + }, { + .name = "LDO_REG1", + .id = RK808_ID_LDO1, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 17, + .linear_ranges = rk808_ldo_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges), + .vsel_reg = RK808_LDO1_ON_VSEL_REG, + .vsel_mask = RK808_LDO_VSEL_MASK, + .enable_reg = RK808_LDO_EN_REG, + .enable_mask = BIT(0), + .owner = THIS_MODULE, + }, { + .name = "LDO_REG2", + .id = RK808_ID_LDO2, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 17, + .linear_ranges = rk808_ldo_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges), + .vsel_reg = RK808_LDO2_ON_VSEL_REG, + .vsel_mask = RK808_LDO_VSEL_MASK, + .enable_reg = RK808_LDO_EN_REG, + .enable_mask = BIT(1), + .owner = THIS_MODULE, + }, { + .name = "LDO_REG3", + .id = RK808_ID_LDO3, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 16, + .linear_ranges = rk808_ldo3_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_ldo3_voltage_ranges), + .vsel_reg = RK808_LDO3_ON_VSEL_REG, + .vsel_mask = RK808_BUCK4_VSEL_MASK, + .enable_reg = RK808_LDO_EN_REG, + .enable_mask = BIT(2), + .owner = THIS_MODULE, + }, { + .name = "LDO_REG4", + .id = RK808_ID_LDO4, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 17, + .linear_ranges = rk808_ldo_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges), + .vsel_reg = RK808_LDO4_ON_VSEL_REG, + .vsel_mask = RK808_LDO_VSEL_MASK, + .enable_reg = RK808_LDO_EN_REG, + .enable_mask = BIT(3), + .owner = THIS_MODULE, + }, { + .name = "LDO_REG5", + .id = RK808_ID_LDO5, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 17, + .linear_ranges = rk808_ldo_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges), + .vsel_reg = RK808_LDO5_ON_VSEL_REG, + .vsel_mask = RK808_LDO_VSEL_MASK, + .enable_reg = RK808_LDO_EN_REG, + .enable_mask = BIT(4), + .owner = THIS_MODULE, + }, { + .name = "LDO_REG6", + .id = RK808_ID_LDO6, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 18, + .linear_ranges = rk808_ldo6_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_ldo6_voltage_ranges), + .vsel_reg = RK808_LDO6_ON_VSEL_REG, + .vsel_mask = RK808_LDO_VSEL_MASK, + .enable_reg = RK808_LDO_EN_REG, + .enable_mask = BIT(5), + .owner = THIS_MODULE, + }, { + .name = "LDO_REG7", + .id = RK808_ID_LDO7, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 18, + .linear_ranges = rk808_ldo6_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_ldo6_voltage_ranges), + .vsel_reg = RK808_LDO7_ON_VSEL_REG, + .vsel_mask = RK808_LDO_VSEL_MASK, + .enable_reg = RK808_LDO_EN_REG, + .enable_mask = BIT(6), + .owner = THIS_MODULE, + }, { + .name = "LDO_REG8", + .id = RK808_ID_LDO8, + .ops = &rk808_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 17, + .linear_ranges = rk808_ldo_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges), + .vsel_reg = RK808_LDO8_ON_VSEL_REG, + .vsel_mask = RK808_LDO_VSEL_MASK, + .enable_reg = RK808_LDO_EN_REG, + .enable_mask = BIT(7), + .owner = THIS_MODULE, + }, { + .name = "SWITCH_REG1", + .id = RK808_ID_SWITCH1, + .ops = &rk808_switch_ops, + .type = REGULATOR_VOLTAGE, + .enable_reg = RK808_DCDC_EN_REG, + .enable_mask = BIT(5), + .owner = THIS_MODULE, + }, { + .name = "SWITCH_REG2", + .id = RK808_ID_SWITCH2, + .ops = &rk808_switch_ops, + .type = REGULATOR_VOLTAGE, + .enable_reg = RK808_DCDC_EN_REG, + .enable_mask = BIT(6), + .owner = THIS_MODULE, + }, +}; + +static struct of_regulator_match rk808_reg_matches[] = { + [RK808_ID_DCDC1] = { .name = "DCDC_REG1" }, + [RK808_ID_DCDC2] = { .name = "DCDC_REG2" }, + [RK808_ID_DCDC3] = { .name = "DCDC_REG3" }, + [RK808_ID_DCDC4] = { .name = "DCDC_REG4" }, + [RK808_ID_LDO1] = { .name = "LDO_REG1" }, + [RK808_ID_LDO2] = { .name = "LDO_REG2" }, + [RK808_ID_LDO3] = { .name = "LDO_REG3" }, + [RK808_ID_LDO4] = { .name = "LDO_REG4" }, + [RK808_ID_LDO5] = { .name = "LDO_REG5" }, + [RK808_ID_LDO6] = { .name = "LDO_REG6" }, + [RK808_ID_LDO7] = { .name = "LDO_REG7" }, + [RK808_ID_LDO8] = { .name = "LDO_REG8" }, + [RK808_ID_SWITCH1] = { .name = "SWITCH_REG1" }, + [RK808_ID_SWITCH2] = { .name = "SWITCH_REG2" }, +}; + +static int rk808_regulator_dts(struct rk808 *rk808) +{ + struct rk808_board *pdata = rk808->pdata; + struct device_node *np, *reg_np; + int i, ret; + + np = rk808->dev->of_node; + if (!np) { + dev_err(rk808->dev, "could not find pmic sub-node\n"); + return -ENXIO; + } + + reg_np = of_get_child_by_name(np, "regulators"); + if (!reg_np) + return -ENXIO; + + ret = of_regulator_match(rk808->dev, reg_np, rk808_reg_matches, + RK808_NUM_REGULATORS); + if (ret < 0) { + dev_err(rk808->dev, + "failed to parse regulator data: %d\n", ret); + return ret; + } + + for (i = 0; i < RK808_NUM_REGULATORS; i++) { + if (!rk808_reg_matches[i].init_data || + !rk808_reg_matches[i].of_node) + continue; + + pdata->rk808_init_data[i] = rk808_reg_matches[i].init_data; + pdata->of_node[i] = rk808_reg_matches[i].of_node; + } + + return 0; +} + +static int rk808_regulator_probe(struct platform_device *pdev) +{ + struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); + struct rk808_board *pdata; + struct regulator_config config; + struct regulator_dev *rk808_rdev; + struct regulator_init_data *reg_data; + int i = 0; + int ret = 0; + + dev_dbg(rk808->dev, "%s\n", __func__); + + if (!rk808) { + dev_err(rk808->dev, "%s no rk808\n", __func__); + return -ENODEV; + } + + pdata = rk808->pdata; + if (!pdata) { + dev_warn(rk808->dev, "%s no pdata, create it\n", __func__); + pdata = devm_kzalloc(rk808->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + } + + ret = rk808_regulator_dts(rk808); + if (ret) + return ret; + + rk808->num_regulators = RK808_NUM_REGULATORS; + rk808->rdev = devm_kzalloc(&pdev->dev, RK808_NUM_REGULATORS * + sizeof(struct regulator_dev *), GFP_KERNEL); + if (!rk808->rdev) + return -ENOMEM; + + /* Instantiate the regulators */ + for (i = 0; i < RK808_NUM_REGULATORS; i++) { + reg_data = pdata->rk808_init_data[i]; + if (!reg_data) + continue; + + config.dev = rk808->dev; + config.driver_data = rk808; + config.regmap = rk808->regmap; + + if (rk808->dev->of_node) + config.of_node = pdata->of_node[i]; + + reg_data->supply_regulator = rk808_reg[i].name; + config.init_data = reg_data; + + rk808_rdev = devm_regulator_register(&pdev->dev, + &rk808_reg[i], &config); + if (IS_ERR(rk808_rdev)) { + dev_err(rk808->dev, + "failed to register %d regulator\n", i); + return PTR_ERR(rk808_rdev); + } + rk808->rdev[i] = rk808_rdev; + } + return 0; +} + +static struct platform_driver rk808_regulator_driver = { + .probe = rk808_regulator_probe, + .driver = { + .name = "rk808-regulator", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(rk808_regulator_driver); + +MODULE_DESCRIPTION("regulator driver for the rk808 series PMICs"); +MODULE_AUTHOR("Chris Zhong"); +MODULE_AUTHOR("Zhang Qing"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:rk808-regulator"); -- cgit From 462004f1215ccb77969004a049aa5437f34c9b06 Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Thu, 21 Aug 2014 17:54:55 -0700 Subject: regulator: rk808: Fix uninitialized value The RK808 regulator driver was putting its config on the stack but not initting it. That means that you got a semi-random config. Fix this. Signed-off-by: Doug Anderson Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/regulator/rk808-regulator.c') diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 94753fd311c1..4d5041ceb56a 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -334,7 +334,7 @@ static int rk808_regulator_probe(struct platform_device *pdev) { struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); struct rk808_board *pdata; - struct regulator_config config; + struct regulator_config config = {}; struct regulator_dev *rk808_rdev; struct regulator_init_data *reg_data; int i = 0; -- cgit From d76c333e9fe2d269c54f68747b2311a5657276e5 Mon Sep 17 00:00:00 2001 From: Chris Zhong Date: Mon, 25 Aug 2014 21:37:06 +0800 Subject: regulator: RK808: modify for struct rk808 change The "dev" has been deleted from "struct rk808" in rk808 mfd driver so rk808->dev should be replaced by &client->dev here. Signed-off-by: Chris Zhong Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) (limited to 'drivers/regulator/rk808-regulator.c') diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 4d5041ceb56a..f00d6d89c7f4 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -296,13 +296,14 @@ static struct of_regulator_match rk808_reg_matches[] = { static int rk808_regulator_dts(struct rk808 *rk808) { - struct rk808_board *pdata = rk808->pdata; struct device_node *np, *reg_np; + struct i2c_client *client = rk808->i2c; + struct rk808_board *pdata = rk808->pdata; int i, ret; - np = rk808->dev->of_node; + np = client->dev.of_node; if (!np) { - dev_err(rk808->dev, "could not find pmic sub-node\n"); + dev_err(&client->dev, "could not find pmic sub-node\n"); return -ENXIO; } @@ -310,10 +311,10 @@ static int rk808_regulator_dts(struct rk808 *rk808) if (!reg_np) return -ENXIO; - ret = of_regulator_match(rk808->dev, reg_np, rk808_reg_matches, + ret = of_regulator_match(&client->dev, reg_np, rk808_reg_matches, RK808_NUM_REGULATORS); - if (ret < 0) { - dev_err(rk808->dev, + if (ret < 0) { + dev_err(&client->dev, "failed to parse regulator data: %d\n", ret); return ret; } @@ -333,24 +334,17 @@ static int rk808_regulator_dts(struct rk808 *rk808) static int rk808_regulator_probe(struct platform_device *pdev) { struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); - struct rk808_board *pdata; + struct i2c_client *client = rk808->i2c; + struct rk808_board *pdata = rk808->pdata; struct regulator_config config = {}; struct regulator_dev *rk808_rdev; struct regulator_init_data *reg_data; int i = 0; int ret = 0; - dev_dbg(rk808->dev, "%s\n", __func__); - - if (!rk808) { - dev_err(rk808->dev, "%s no rk808\n", __func__); - return -ENODEV; - } - - pdata = rk808->pdata; if (!pdata) { - dev_warn(rk808->dev, "%s no pdata, create it\n", __func__); - pdata = devm_kzalloc(rk808->dev, sizeof(*pdata), GFP_KERNEL); + dev_warn(&client->dev, "%s no pdata, create it\n", __func__); + pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; } @@ -371,11 +365,11 @@ static int rk808_regulator_probe(struct platform_device *pdev) if (!reg_data) continue; - config.dev = rk808->dev; + config.dev = &client->dev; config.driver_data = rk808; config.regmap = rk808->regmap; - if (rk808->dev->of_node) + if (client->dev.of_node) config.of_node = pdata->of_node[i]; reg_data->supply_regulator = rk808_reg[i].name; @@ -384,7 +378,7 @@ static int rk808_regulator_probe(struct platform_device *pdev) rk808_rdev = devm_regulator_register(&pdev->dev, &rk808_reg[i], &config); if (IS_ERR(rk808_rdev)) { - dev_err(rk808->dev, + dev_err(&client->dev, "failed to register %d regulator\n", i); return PTR_ERR(rk808_rdev); } -- cgit From 2a8d1303c6618f44e7603a4625783d1aff5fef4a Mon Sep 17 00:00:00 2001 From: Chris Zhong Date: Tue, 26 Aug 2014 22:18:57 +0800 Subject: regulator: rk808: remove redundant code remove the redundant code, since pdata has been removed from stuct rk808 Signed-off-by: Chris Zhong Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'drivers/regulator/rk808-regulator.c') diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index f00d6d89c7f4..f42952ead1bd 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -294,11 +294,10 @@ static struct of_regulator_match rk808_reg_matches[] = { [RK808_ID_SWITCH2] = { .name = "SWITCH_REG2" }, }; -static int rk808_regulator_dts(struct rk808 *rk808) +static int rk808_regulator_dts(struct i2c_client *client, + struct rk808_board *pdata) { struct device_node *np, *reg_np; - struct i2c_client *client = rk808->i2c; - struct rk808_board *pdata = rk808->pdata; int i, ret; np = client->dev.of_node; @@ -335,7 +334,7 @@ static int rk808_regulator_probe(struct platform_device *pdev) { struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); struct i2c_client *client = rk808->i2c; - struct rk808_board *pdata = rk808->pdata; + struct rk808_board *pdata = dev_get_platdata(&client->dev); struct regulator_config config = {}; struct regulator_dev *rk808_rdev; struct regulator_init_data *reg_data; @@ -343,22 +342,15 @@ static int rk808_regulator_probe(struct platform_device *pdev) int ret = 0; if (!pdata) { - dev_warn(&client->dev, "%s no pdata, create it\n", __func__); pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; } - ret = rk808_regulator_dts(rk808); + ret = rk808_regulator_dts(client, pdata); if (ret) return ret; - rk808->num_regulators = RK808_NUM_REGULATORS; - rk808->rdev = devm_kzalloc(&pdev->dev, RK808_NUM_REGULATORS * - sizeof(struct regulator_dev *), GFP_KERNEL); - if (!rk808->rdev) - return -ENOMEM; - /* Instantiate the regulators */ for (i = 0; i < RK808_NUM_REGULATORS; i++) { reg_data = pdata->rk808_init_data[i]; @@ -382,7 +374,6 @@ static int rk808_regulator_probe(struct platform_device *pdev) "failed to register %d regulator\n", i); return PTR_ERR(rk808_rdev); } - rk808->rdev[i] = rk808_rdev; } return 0; } -- cgit From c61519fd9abb1b520bcbe2eb21cf161d4d1b9eec Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 28 Aug 2014 21:04:49 +0800 Subject: regulator: rk808: Fix memory leak The memory allocated in rk808_regulator_probe() needs to be freed when the module is unloaded. Thus pass &pdev->dev rather than &client->dev to devm_kzalloc. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/regulator/rk808-regulator.c') diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index f42952ead1bd..0d11df131eba 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -342,7 +342,7 @@ static int rk808_regulator_probe(struct platform_device *pdev) int ret = 0; if (!pdata) { - pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; } -- cgit From 5a82067f013fb4f5083fabf4d28f4d1bbada8734 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 2 Sep 2014 08:47:31 +0800 Subject: regulator: rk808: Fix n_voltages for DCDC4 The min_sel is 0, max_sel is 15, so n_voltages should be 16. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/regulator/rk808-regulator.c') diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 0d11df131eba..0da8867bdf4c 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -146,7 +146,7 @@ static const struct regulator_desc rk808_reg[] = { .id = RK808_ID_DCDC4, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, - .n_voltages = 17, + .n_voltages = 16, .linear_ranges = rk808_buck4_voltage_ranges, .n_linear_ranges = ARRAY_SIZE(rk808_buck4_voltage_ranges), .vsel_reg = RK808_BUCK4_ON_VSEL_REG, -- cgit From b8074eba2a6b5b1b090cf9c53dbccf3bc3e5205a Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Tue, 2 Sep 2014 09:14:28 -0700 Subject: regulator: RK808: Add proper input supplies for rk808 The original RK808 regulator driver didn't setup input supplies properly. Add them. Signed-off-by: Doug Anderson Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers/regulator/rk808-regulator.c') diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 0da8867bdf4c..e3720085b4ce 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -108,6 +108,7 @@ static struct regulator_ops rk808_switch_ops = { static const struct regulator_desc rk808_reg[] = { { .name = "DCDC_REG1", + .supply_name = "vcc1", .id = RK808_ID_DCDC1, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, @@ -121,6 +122,7 @@ static const struct regulator_desc rk808_reg[] = { .owner = THIS_MODULE, }, { .name = "DCDC_REG2", + .supply_name = "vcc2", .id = RK808_ID_DCDC2, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, @@ -134,6 +136,7 @@ static const struct regulator_desc rk808_reg[] = { .owner = THIS_MODULE, }, { .name = "DCDC_REG3", + .supply_name = "vcc3", .id = RK808_ID_DCDC3, .ops = &rk808_switch_ops, .type = REGULATOR_VOLTAGE, @@ -143,6 +146,7 @@ static const struct regulator_desc rk808_reg[] = { .owner = THIS_MODULE, }, { .name = "DCDC_REG4", + .supply_name = "vcc4", .id = RK808_ID_DCDC4, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, @@ -156,6 +160,7 @@ static const struct regulator_desc rk808_reg[] = { .owner = THIS_MODULE, }, { .name = "LDO_REG1", + .supply_name = "vcc6", .id = RK808_ID_LDO1, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, @@ -169,6 +174,7 @@ static const struct regulator_desc rk808_reg[] = { .owner = THIS_MODULE, }, { .name = "LDO_REG2", + .supply_name = "vcc6", .id = RK808_ID_LDO2, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, @@ -182,6 +188,7 @@ static const struct regulator_desc rk808_reg[] = { .owner = THIS_MODULE, }, { .name = "LDO_REG3", + .supply_name = "vcc7", .id = RK808_ID_LDO3, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, @@ -195,6 +202,7 @@ static const struct regulator_desc rk808_reg[] = { .owner = THIS_MODULE, }, { .name = "LDO_REG4", + .supply_name = "vcc9", .id = RK808_ID_LDO4, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, @@ -208,6 +216,7 @@ static const struct regulator_desc rk808_reg[] = { .owner = THIS_MODULE, }, { .name = "LDO_REG5", + .supply_name = "vcc9", .id = RK808_ID_LDO5, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, @@ -221,6 +230,7 @@ static const struct regulator_desc rk808_reg[] = { .owner = THIS_MODULE, }, { .name = "LDO_REG6", + .supply_name = "vcc10", .id = RK808_ID_LDO6, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, @@ -234,6 +244,7 @@ static const struct regulator_desc rk808_reg[] = { .owner = THIS_MODULE, }, { .name = "LDO_REG7", + .supply_name = "vcc7", .id = RK808_ID_LDO7, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, @@ -247,6 +258,7 @@ static const struct regulator_desc rk808_reg[] = { .owner = THIS_MODULE, }, { .name = "LDO_REG8", + .supply_name = "vcc11", .id = RK808_ID_LDO8, .ops = &rk808_reg_ops, .type = REGULATOR_VOLTAGE, @@ -260,6 +272,7 @@ static const struct regulator_desc rk808_reg[] = { .owner = THIS_MODULE, }, { .name = "SWITCH_REG1", + .supply_name = "vcc8", .id = RK808_ID_SWITCH1, .ops = &rk808_switch_ops, .type = REGULATOR_VOLTAGE, @@ -268,6 +281,7 @@ static const struct regulator_desc rk808_reg[] = { .owner = THIS_MODULE, }, { .name = "SWITCH_REG2", + .supply_name = "vcc12", .id = RK808_ID_SWITCH2, .ops = &rk808_switch_ops, .type = REGULATOR_VOLTAGE, @@ -364,7 +378,6 @@ static int rk808_regulator_probe(struct platform_device *pdev) if (client->dev.of_node) config.of_node = pdata->of_node[i]; - reg_data->supply_regulator = rk808_reg[i].name; config.init_data = reg_data; rk808_rdev = devm_regulator_register(&pdev->dev, -- cgit From 571a4010847a8b03c88de6543c5c00878a7e97d3 Mon Sep 17 00:00:00 2001 From: Chris Zhong Date: Wed, 10 Sep 2014 09:18:06 +0800 Subject: regulator: rk808: Remove pdata from the regulator Signed-off-by: Chris Zhong Tested-by: Heiko Stuebner Reviewed-by: Doug Anderson Tested-by: Doug Anderson Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 89 +++++++------------------------------ 1 file changed, 17 insertions(+), 72 deletions(-) (limited to 'drivers/regulator/rk808-regulator.c') diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index e3720085b4ce..d91f2b658080 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -14,24 +14,16 @@ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. - * */ #include -#include #include -#include -#include #include -#include #include #include #include -#include -#include -/* - * Field Definitions. - */ + +/* Field Definitions */ #define RK808_BUCK_VSEL_MASK 0x3f #define RK808_BUCK4_VSEL_MASK 0xf #define RK808_LDO_VSEL_MASK 0x1f @@ -50,10 +42,6 @@ static const int buck_contr_base_addr[] = { RK808_BUCK4_CONFIG_REG, }; -#define rk808_BUCK_SET_VOL_REG(x) (buck_set_vol_base_addr[x]) -#define rk808_BUCK_CONTR_REG(x) (buck_contr_base_addr[x]) -#define rk808_LDO_SET_VOL_REG(x) (ldo_set_vol_base_addr[x]) - static const int ldo_set_vol_base_addr[] = { RK808_LDO1_ON_VSEL_REG, RK808_LDO2_ON_VSEL_REG, @@ -65,9 +53,7 @@ static const int ldo_set_vol_base_addr[] = { RK808_LDO8_ON_VSEL_REG, }; -/* - * rk808 voltage number - */ +/* rk808 voltage number */ static const struct regulator_linear_range rk808_buck_voltage_ranges[] = { REGULATOR_LINEAR_RANGE(700000, 0, 63, 12500), }; @@ -308,77 +294,35 @@ static struct of_regulator_match rk808_reg_matches[] = { [RK808_ID_SWITCH2] = { .name = "SWITCH_REG2" }, }; -static int rk808_regulator_dts(struct i2c_client *client, - struct rk808_board *pdata) -{ - struct device_node *np, *reg_np; - int i, ret; - - np = client->dev.of_node; - if (!np) { - dev_err(&client->dev, "could not find pmic sub-node\n"); - return -ENXIO; - } - - reg_np = of_get_child_by_name(np, "regulators"); - if (!reg_np) - return -ENXIO; - - ret = of_regulator_match(&client->dev, reg_np, rk808_reg_matches, - RK808_NUM_REGULATORS); - if (ret < 0) { - dev_err(&client->dev, - "failed to parse regulator data: %d\n", ret); - return ret; - } - - for (i = 0; i < RK808_NUM_REGULATORS; i++) { - if (!rk808_reg_matches[i].init_data || - !rk808_reg_matches[i].of_node) - continue; - - pdata->rk808_init_data[i] = rk808_reg_matches[i].init_data; - pdata->of_node[i] = rk808_reg_matches[i].of_node; - } - - return 0; -} - static int rk808_regulator_probe(struct platform_device *pdev) { struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); struct i2c_client *client = rk808->i2c; - struct rk808_board *pdata = dev_get_platdata(&client->dev); + struct device_node *reg_np; struct regulator_config config = {}; struct regulator_dev *rk808_rdev; - struct regulator_init_data *reg_data; - int i = 0; - int ret = 0; + int ret, i; - if (!pdata) { - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - } + reg_np = of_get_child_by_name(client->dev.of_node, "regulators"); + if (!reg_np) + return -ENXIO; - ret = rk808_regulator_dts(client, pdata); - if (ret) + ret = of_regulator_match(&client->dev, reg_np, rk808_reg_matches, + RK808_NUM_REGULATORS); + if (ret < 0) return ret; /* Instantiate the regulators */ for (i = 0; i < RK808_NUM_REGULATORS; i++) { - reg_data = pdata->rk808_init_data[i]; - if (!reg_data) + if (!rk808_reg_matches[i].init_data || + !rk808_reg_matches[i].of_node) continue; config.dev = &client->dev; config.driver_data = rk808; config.regmap = rk808->regmap; - - if (client->dev.of_node) - config.of_node = pdata->of_node[i]; - - config.init_data = reg_data; + config.of_node = rk808_reg_matches[i].of_node; + config.init_data = rk808_reg_matches[i].init_data; rk808_rdev = devm_regulator_register(&pdev->dev, &rk808_reg[i], &config); @@ -388,6 +332,7 @@ static int rk808_regulator_probe(struct platform_device *pdev) return PTR_ERR(rk808_rdev); } } + return 0; } @@ -403,6 +348,6 @@ module_platform_driver(rk808_regulator_driver); MODULE_DESCRIPTION("regulator driver for the rk808 series PMICs"); MODULE_AUTHOR("Chris Zhong"); -MODULE_AUTHOR("Zhang Qing"); +MODULE_AUTHOR("Zhang Qing"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:rk808-regulator"); -- cgit From 1f0c01621aa1beb0f6bc205beeada2a4a3178d5a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 11 Sep 2014 18:21:10 +0800 Subject: regulator: rk808: Remove unused variables Also remove non-informative comment. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 26 -------------------------- 1 file changed, 26 deletions(-) (limited to 'drivers/regulator/rk808-regulator.c') diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index d91f2b658080..9557428f39a7 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -28,32 +28,6 @@ #define RK808_BUCK4_VSEL_MASK 0xf #define RK808_LDO_VSEL_MASK 0x1f -static const int buck_set_vol_base_addr[] = { - RK808_BUCK1_ON_VSEL_REG, - RK808_BUCK2_ON_VSEL_REG, - RK808_BUCK3_CONFIG_REG, - RK808_BUCK4_ON_VSEL_REG, -}; - -static const int buck_contr_base_addr[] = { - RK808_BUCK1_CONFIG_REG, - RK808_BUCK2_CONFIG_REG, - RK808_BUCK3_CONFIG_REG, - RK808_BUCK4_CONFIG_REG, -}; - -static const int ldo_set_vol_base_addr[] = { - RK808_LDO1_ON_VSEL_REG, - RK808_LDO2_ON_VSEL_REG, - RK808_LDO3_ON_VSEL_REG, - RK808_LDO4_ON_VSEL_REG, - RK808_LDO5_ON_VSEL_REG, - RK808_LDO6_ON_VSEL_REG, - RK808_LDO7_ON_VSEL_REG, - RK808_LDO8_ON_VSEL_REG, -}; - -/* rk808 voltage number */ static const struct regulator_linear_range rk808_buck_voltage_ranges[] = { REGULATOR_LINEAR_RANGE(700000, 0, 63, 12500), }; -- cgit From 1ed3f8ce8399255c7cca43dde5d3a19b2b7dc287 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 11 Sep 2014 18:22:48 +0800 Subject: regulator: rk808: Fix missing of_node_put 1. Pass &pdev->dev rather than &client->dev to of_regulator_match, the *dev argument is used for devres to ensure devm_of_regulator_put_matches() will be called when unload the module. 2. of_get_child_by_name() returns a node pointer with refcount incremented. Thus add missing of_node_put(reg_np). Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/regulator/rk808-regulator.c') diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 9557428f39a7..07b0eb4adf42 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -281,8 +281,9 @@ static int rk808_regulator_probe(struct platform_device *pdev) if (!reg_np) return -ENXIO; - ret = of_regulator_match(&client->dev, reg_np, rk808_reg_matches, + ret = of_regulator_match(&pdev->dev, reg_np, rk808_reg_matches, RK808_NUM_REGULATORS); + of_node_put(reg_np); if (ret < 0) return ret; -- cgit From 8af252272a0d634b59c4c7fa88200b06695decde Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Tue, 16 Sep 2014 10:22:54 -0700 Subject: regulator: rk808: Add function for ramp delay for buck1/buck2 On rk808 buck1 and buck2 have programmable ramp delays. Let's add a function to allow a client of rk808 to set them. Signed-off-by: Doug Anderson Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 57 +++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) (limited to 'drivers/regulator/rk808-regulator.c') diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 07b0eb4adf42..e305416d7697 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -28,6 +28,21 @@ #define RK808_BUCK4_VSEL_MASK 0xf #define RK808_LDO_VSEL_MASK 0x1f +/* Ramp rate definitions for buck1 / buck2 only */ +#define RK808_RAMP_RATE_OFFSET 3 +#define RK808_RAMP_RATE_MASK (3 << RK808_RAMP_RATE_OFFSET) +#define RK808_RAMP_RATE_2MV_PER_US (0 << RK808_RAMP_RATE_OFFSET) +#define RK808_RAMP_RATE_4MV_PER_US (1 << RK808_RAMP_RATE_OFFSET) +#define RK808_RAMP_RATE_6MV_PER_US (2 << RK808_RAMP_RATE_OFFSET) +#define RK808_RAMP_RATE_10MV_PER_US (3 << RK808_RAMP_RATE_OFFSET) + +static const int rk808_buck_config_regs[] = { + RK808_BUCK1_CONFIG_REG, + RK808_BUCK2_CONFIG_REG, + RK808_BUCK3_CONFIG_REG, + RK808_BUCK4_CONFIG_REG, +}; + static const struct regulator_linear_range rk808_buck_voltage_ranges[] = { REGULATOR_LINEAR_RANGE(700000, 0, 63, 12500), }; @@ -49,6 +64,44 @@ static const struct regulator_linear_range rk808_ldo6_voltage_ranges[] = { REGULATOR_LINEAR_RANGE(800000, 0, 17, 100000), }; +static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) +{ + unsigned int ramp_value = RK808_RAMP_RATE_10MV_PER_US; + unsigned int reg = rk808_buck_config_regs[rdev->desc->id - + RK808_ID_DCDC1]; + + switch (ramp_delay) { + case 1 ... 2000: + ramp_value = RK808_RAMP_RATE_2MV_PER_US; + break; + case 2001 ... 4000: + ramp_value = RK808_RAMP_RATE_4MV_PER_US; + break; + case 4001 ... 6000: + ramp_value = RK808_RAMP_RATE_6MV_PER_US; + break; + case 6001 ... 10000: + break; + default: + pr_warn("%s ramp_delay: %d not supported, setting 10000\n", + rdev->desc->name, ramp_delay); + } + + return regmap_update_bits(rdev->regmap, reg, + RK808_RAMP_RATE_MASK, ramp_value); +} + +static struct regulator_ops rk808_buck1_2_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, + .set_ramp_delay = rk808_set_ramp_delay, +}; + static struct regulator_ops rk808_reg_ops = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, @@ -70,7 +123,7 @@ static const struct regulator_desc rk808_reg[] = { .name = "DCDC_REG1", .supply_name = "vcc1", .id = RK808_ID_DCDC1, - .ops = &rk808_reg_ops, + .ops = &rk808_buck1_2_ops, .type = REGULATOR_VOLTAGE, .n_voltages = 64, .linear_ranges = rk808_buck_voltage_ranges, @@ -84,7 +137,7 @@ static const struct regulator_desc rk808_reg[] = { .name = "DCDC_REG2", .supply_name = "vcc2", .id = RK808_ID_DCDC2, - .ops = &rk808_reg_ops, + .ops = &rk808_buck1_2_ops, .type = REGULATOR_VOLTAGE, .n_voltages = 64, .linear_ranges = rk808_buck_voltage_ranges, -- cgit