From 3119525203149fc11ce9f48131afdf9795d7a4ea Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 28 Feb 2014 11:01:48 +0100 Subject: regulator: s2mps11: Don't store registered regulators in state container Regulators registered by devm_regulator_register() do not have to be stored in state container because they are never dereferenced later. The array of regulator_dev can be safely removed from state container. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/regulator/s2mps11.c') diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index cd0b9e35a56d..3647d590b962 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -28,8 +28,6 @@ #define S2MPS11_REGULATOR_CNT ARRAY_SIZE(regulators) struct s2mps11_info { - struct regulator_dev *rdev[S2MPS11_REGULATOR_MAX]; - int ramp_delay2; int ramp_delay34; int ramp_delay5; @@ -439,6 +437,8 @@ common_reg: config.regmap = iodev->regmap_pmic; config.driver_data = s2mps11; for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) { + struct regulator_dev *regulator; + if (!reg_np) { config.init_data = pdata->regulators[i].initdata; config.of_node = pdata->regulators[i].reg_node; @@ -447,10 +447,10 @@ common_reg: config.of_node = rdata[i].of_node; } - s2mps11->rdev[i] = devm_regulator_register(&pdev->dev, + regulator = devm_regulator_register(&pdev->dev, ®ulators[i], &config); - if (IS_ERR(s2mps11->rdev[i])) { - ret = PTR_ERR(s2mps11->rdev[i]); + if (IS_ERR(regulator)) { + ret = PTR_ERR(regulator); dev_err(&pdev->dev, "regulator init failed for %d\n", i); return ret; -- cgit v1.2.3-59-g8ed1b From 219ef031de434591bb6c85d22701ce8b23c4b1a4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 28 Feb 2014 11:01:49 +0100 Subject: regulator: s2mps11: Constify regulator_desc array Constify the regulator_desc 'regulators' array. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/regulator/s2mps11.c') diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 3647d590b962..189038aecbf5 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -343,7 +343,7 @@ static struct regulator_ops s2mps11_buck_ops = { .enable_mask = S2MPS11_ENABLE_MASK \ } -static struct regulator_desc regulators[] = { +static const struct regulator_desc regulators[] = { regulator_desc_ldo2(1), regulator_desc_ldo1(2), regulator_desc_ldo1(3), -- cgit v1.2.3-59-g8ed1b From 3e80f95bfc5f490bda4785cb672490f7012a40d0 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 28 Feb 2014 11:01:50 +0100 Subject: regulator: s2mps11: Copy supported regulators from initconst Add __initconst to 'regulator_desc' array with supported regulators. During probe choose how many and which regulators will be supported according to device ID. Then copy the 'regulator_desc' array to allocated memory so the regulator core can use it. Additionally allocate array of of_regulator_match() dynamically (based on number of regulators) instead of allocation on the stack. This is needed for supporting different devices in s2mps11 driver and actually prepares the regulator driver for supporting the S2MPS14 device. Code for supporting the S2MPS14 device will add its own array of 'regulator_desc' (also marked as __initconst). This way memory footprint of the driver will be reduced (approximately 'regulators_desc' array for S2MPS11 occupies 5 kB on 32-bit ARM, for S2MPS14 will occupy 3 kB). Signed-off-by: Krzysztof Kozlowski Signed-off-by: Chanwoo Choi Cc: Yadwinder Singh Brar Reviewed-by: Yadwinder Singh Brar Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 75 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 13 deletions(-) (limited to 'drivers/regulator/s2mps11.c') diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 189038aecbf5..ca66fc56fa58 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -25,9 +25,8 @@ #include #include -#define S2MPS11_REGULATOR_CNT ARRAY_SIZE(regulators) - struct s2mps11_info { + unsigned int rdev_num; int ramp_delay2; int ramp_delay34; int ramp_delay5; @@ -343,7 +342,7 @@ static struct regulator_ops s2mps11_buck_ops = { .enable_mask = S2MPS11_ENABLE_MASK \ } -static const struct regulator_desc regulators[] = { +static const struct regulator_desc s2mps11_regulators[] __initconst = { regulator_desc_ldo2(1), regulator_desc_ldo1(2), regulator_desc_ldo1(3), @@ -394,21 +393,62 @@ static const struct regulator_desc regulators[] = { regulator_desc_buck10, }; +/* + * Allocates memory under 'regulators' pointer and copies there array + * of regulator_desc for given device. + * + * Returns number of regulators or negative ERRNO on error. + */ +static int __init +s2mps11_pmic_init_regulators_desc(struct platform_device *pdev, + struct regulator_desc **regulators) +{ + const struct regulator_desc *regulators_init; + enum sec_device_type dev_type; + int rdev_num; + + dev_type = platform_get_device_id(pdev)->driver_data; + switch (dev_type) { + case S2MPS11X: + rdev_num = ARRAY_SIZE(s2mps11_regulators); + regulators_init = s2mps11_regulators; + break; + default: + dev_err(&pdev->dev, "Invalid device type: %u\n", dev_type); + return -EINVAL; + }; + + *regulators = devm_kzalloc(&pdev->dev, + sizeof(**regulators) * rdev_num, GFP_KERNEL); + if (!*regulators) + return -ENOMEM; + + memcpy(*regulators, regulators_init, sizeof(**regulators) * rdev_num); + + return rdev_num; +} + static int s2mps11_pmic_probe(struct platform_device *pdev) { struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); - struct sec_platform_data *pdata = dev_get_platdata(iodev->dev); - struct of_regulator_match rdata[S2MPS11_REGULATOR_MAX]; + struct sec_platform_data *pdata = iodev->pdata; + struct of_regulator_match *rdata = NULL; struct device_node *reg_np = NULL; struct regulator_config config = { }; struct s2mps11_info *s2mps11; - int i, ret; + int i, ret = 0; + struct regulator_desc *regulators = NULL; + int rdev_num; s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info), GFP_KERNEL); if (!s2mps11) return -ENOMEM; + rdev_num = s2mps11_pmic_init_regulators_desc(pdev, ®ulators); + if (rdev_num < 0) + return rdev_num; + if (!iodev->dev->of_node) { if (pdata) { goto common_reg; @@ -419,24 +459,30 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) } } - for (i = 0; i < S2MPS11_REGULATOR_CNT; i++) + rdata = kzalloc(sizeof(*rdata) * rdev_num, GFP_KERNEL); + if (!rdata) + return -ENOMEM; + + for (i = 0; i < rdev_num; i++) rdata[i].name = regulators[i].name; reg_np = of_find_node_by_name(iodev->dev->of_node, "regulators"); if (!reg_np) { dev_err(&pdev->dev, "could not find regulators sub-node\n"); - return -EINVAL; + ret = -EINVAL; + goto out; } - of_regulator_match(&pdev->dev, reg_np, rdata, S2MPS11_REGULATOR_MAX); + of_regulator_match(&pdev->dev, reg_np, rdata, rdev_num); common_reg: platform_set_drvdata(pdev, s2mps11); + s2mps11->rdev_num = rdev_num; config.dev = &pdev->dev; config.regmap = iodev->regmap_pmic; config.driver_data = s2mps11; - for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) { + for (i = 0; i < rdev_num; i++) { struct regulator_dev *regulator; if (!reg_np) { @@ -453,15 +499,18 @@ common_reg: ret = PTR_ERR(regulator); dev_err(&pdev->dev, "regulator init failed for %d\n", i); - return ret; + goto out; } } - return 0; +out: + kfree(rdata); + + return ret; } static const struct platform_device_id s2mps11_pmic_id[] = { - { "s2mps11-pmic", 0}, + { "s2mps11-pmic", S2MPS11X}, { }, }; MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id); -- cgit v1.2.3-59-g8ed1b From 0f4cc282951a76011db1da6787b3d2acc63238ca Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 3 Mar 2014 16:53:51 +0100 Subject: regulator: s2mps11: Fix section mismatch Remove __initconst from regulator_desc array because this array is used during probe and s2mps11_pmic_probe() is not in __init section. However still select the number of supported regulators according to device ID so the driver will be ready for adding support for S2MPS14 device. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 63 ++++++++++++--------------------------------- 1 file changed, 17 insertions(+), 46 deletions(-) (limited to 'drivers/regulator/s2mps11.c') diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index ca66fc56fa58..ca876de72eae 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -342,7 +342,7 @@ static struct regulator_ops s2mps11_buck_ops = { .enable_mask = S2MPS11_ENABLE_MASK \ } -static const struct regulator_desc s2mps11_regulators[] __initconst = { +static const struct regulator_desc s2mps11_regulators[] = { regulator_desc_ldo2(1), regulator_desc_ldo1(2), regulator_desc_ldo1(3), @@ -393,41 +393,6 @@ static const struct regulator_desc s2mps11_regulators[] __initconst = { regulator_desc_buck10, }; -/* - * Allocates memory under 'regulators' pointer and copies there array - * of regulator_desc for given device. - * - * Returns number of regulators or negative ERRNO on error. - */ -static int __init -s2mps11_pmic_init_regulators_desc(struct platform_device *pdev, - struct regulator_desc **regulators) -{ - const struct regulator_desc *regulators_init; - enum sec_device_type dev_type; - int rdev_num; - - dev_type = platform_get_device_id(pdev)->driver_data; - switch (dev_type) { - case S2MPS11X: - rdev_num = ARRAY_SIZE(s2mps11_regulators); - regulators_init = s2mps11_regulators; - break; - default: - dev_err(&pdev->dev, "Invalid device type: %u\n", dev_type); - return -EINVAL; - }; - - *regulators = devm_kzalloc(&pdev->dev, - sizeof(**regulators) * rdev_num, GFP_KERNEL); - if (!*regulators) - return -ENOMEM; - - memcpy(*regulators, regulators_init, sizeof(**regulators) * rdev_num); - - return rdev_num; -} - static int s2mps11_pmic_probe(struct platform_device *pdev) { struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); @@ -437,17 +402,24 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) struct regulator_config config = { }; struct s2mps11_info *s2mps11; int i, ret = 0; - struct regulator_desc *regulators = NULL; - int rdev_num; + const struct regulator_desc *regulators; + enum sec_device_type dev_type; s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info), GFP_KERNEL); if (!s2mps11) return -ENOMEM; - rdev_num = s2mps11_pmic_init_regulators_desc(pdev, ®ulators); - if (rdev_num < 0) - return rdev_num; + dev_type = platform_get_device_id(pdev)->driver_data; + switch (dev_type) { + case S2MPS11X: + s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators); + regulators = s2mps11_regulators; + break; + default: + dev_err(&pdev->dev, "Invalid device type: %u\n", dev_type); + return -EINVAL; + }; if (!iodev->dev->of_node) { if (pdata) { @@ -459,11 +431,11 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) } } - rdata = kzalloc(sizeof(*rdata) * rdev_num, GFP_KERNEL); + rdata = kzalloc(sizeof(*rdata) * s2mps11->rdev_num, GFP_KERNEL); if (!rdata) return -ENOMEM; - for (i = 0; i < rdev_num; i++) + for (i = 0; i < s2mps11->rdev_num; i++) rdata[i].name = regulators[i].name; reg_np = of_find_node_by_name(iodev->dev->of_node, "regulators"); @@ -473,16 +445,15 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) goto out; } - of_regulator_match(&pdev->dev, reg_np, rdata, rdev_num); + of_regulator_match(&pdev->dev, reg_np, rdata, s2mps11->rdev_num); common_reg: platform_set_drvdata(pdev, s2mps11); - s2mps11->rdev_num = rdev_num; config.dev = &pdev->dev; config.regmap = iodev->regmap_pmic; config.driver_data = s2mps11; - for (i = 0; i < rdev_num; i++) { + for (i = 0; i < s2mps11->rdev_num; i++) { struct regulator_dev *regulator; if (!reg_np) { -- cgit v1.2.3-59-g8ed1b From 15f77300c9eedb095c8f4097628af51e8e14de30 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 7 Mar 2014 11:10:50 +0100 Subject: regulator: s2mps11: Add support for S2MPS14 regulators Add support for S2MPS14 PMIC regulators to s2mps11 driver. The S2MPS14 has fewer BUCK-s and LDO-s than S2MPS11. It also does not support controlling the BUCK ramp delay. Signed-off-by: Krzysztof Kozlowski Cc: Mark Brown Cc: Liam Girdwood Reviewed-by: Yadwinder Singh Brar Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 9 +- drivers/regulator/s2mps11.c | 252 +++++++++++++++++++++++++++++++++----------- 2 files changed, 196 insertions(+), 65 deletions(-) (limited to 'drivers/regulator/s2mps11.c') diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 8f8e6710bb45..69e6bf755e00 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -424,12 +424,13 @@ config REGULATOR_S2MPA01 via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs. config REGULATOR_S2MPS11 - tristate "Samsung S2MPS11 voltage regulator" + tristate "Samsung S2MPS11/S2MPS14 voltage regulator" depends on MFD_SEC_CORE help - This driver supports a Samsung S2MPS11 voltage output regulator - via I2C bus. S2MPS11 is comprised of high efficient Buck converters - including Dual-Phase Buck converter, Buck-Boost converter, various LDOs. + This driver supports a Samsung S2MPS11/S2MPS14 voltage output + regulator via I2C bus. The chip is comprised of high efficient Buck + converters including Dual-Phase Buck converter, Buck-Boost converter, + various LDOs. config REGULATOR_S5M8767 tristate "Samsung S5M8767A voltage regulator" diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index ca876de72eae..65697b1a26c0 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -1,13 +1,18 @@ /* * s2mps11.c * - * Copyright (c) 2012 Samsung Electronics Co., Ltd + * Copyright (c) 2012-2014 Samsung Electronics Co., Ltd * http://www.samsung.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. + * 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 in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * */ @@ -24,6 +29,7 @@ #include #include #include +#include struct s2mps11_info { unsigned int rdev_num; @@ -233,7 +239,7 @@ static struct regulator_ops s2mps11_buck_ops = { .set_ramp_delay = s2mps11_set_ramp_delay, }; -#define regulator_desc_ldo1(num) { \ +#define regulator_desc_s2mps11_ldo1(num) { \ .name = "LDO"#num, \ .id = S2MPS11_LDO##num, \ .ops = &s2mps11_ldo_ops, \ @@ -247,7 +253,7 @@ static struct regulator_ops s2mps11_buck_ops = { .enable_reg = S2MPS11_REG_L1CTRL + num - 1, \ .enable_mask = S2MPS11_ENABLE_MASK \ } -#define regulator_desc_ldo2(num) { \ +#define regulator_desc_s2mps11_ldo2(num) { \ .name = "LDO"#num, \ .id = S2MPS11_LDO##num, \ .ops = &s2mps11_ldo_ops, \ @@ -262,7 +268,7 @@ static struct regulator_ops s2mps11_buck_ops = { .enable_mask = S2MPS11_ENABLE_MASK \ } -#define regulator_desc_buck1_4(num) { \ +#define regulator_desc_s2mps11_buck1_4(num) { \ .name = "BUCK"#num, \ .id = S2MPS11_BUCK##num, \ .ops = &s2mps11_buck_ops, \ @@ -278,7 +284,7 @@ static struct regulator_ops s2mps11_buck_ops = { .enable_mask = S2MPS11_ENABLE_MASK \ } -#define regulator_desc_buck5 { \ +#define regulator_desc_s2mps11_buck5 { \ .name = "BUCK5", \ .id = S2MPS11_BUCK5, \ .ops = &s2mps11_buck_ops, \ @@ -294,7 +300,7 @@ static struct regulator_ops s2mps11_buck_ops = { .enable_mask = S2MPS11_ENABLE_MASK \ } -#define regulator_desc_buck6_8(num) { \ +#define regulator_desc_s2mps11_buck6_8(num) { \ .name = "BUCK"#num, \ .id = S2MPS11_BUCK##num, \ .ops = &s2mps11_buck_ops, \ @@ -310,7 +316,7 @@ static struct regulator_ops s2mps11_buck_ops = { .enable_mask = S2MPS11_ENABLE_MASK \ } -#define regulator_desc_buck9 { \ +#define regulator_desc_s2mps11_buck9 { \ .name = "BUCK9", \ .id = S2MPS11_BUCK9, \ .ops = &s2mps11_buck_ops, \ @@ -326,7 +332,7 @@ static struct regulator_ops s2mps11_buck_ops = { .enable_mask = S2MPS11_ENABLE_MASK \ } -#define regulator_desc_buck10 { \ +#define regulator_desc_s2mps11_buck10 { \ .name = "BUCK10", \ .id = S2MPS11_BUCK10, \ .ops = &s2mps11_buck_ops, \ @@ -343,54 +349,173 @@ static struct regulator_ops s2mps11_buck_ops = { } static const struct regulator_desc s2mps11_regulators[] = { - regulator_desc_ldo2(1), - regulator_desc_ldo1(2), - regulator_desc_ldo1(3), - regulator_desc_ldo1(4), - regulator_desc_ldo1(5), - regulator_desc_ldo2(6), - regulator_desc_ldo1(7), - regulator_desc_ldo1(8), - regulator_desc_ldo1(9), - regulator_desc_ldo1(10), - regulator_desc_ldo2(11), - regulator_desc_ldo1(12), - regulator_desc_ldo1(13), - regulator_desc_ldo1(14), - regulator_desc_ldo1(15), - regulator_desc_ldo1(16), - regulator_desc_ldo1(17), - regulator_desc_ldo1(18), - regulator_desc_ldo1(19), - regulator_desc_ldo1(20), - regulator_desc_ldo1(21), - regulator_desc_ldo2(22), - regulator_desc_ldo2(23), - regulator_desc_ldo1(24), - regulator_desc_ldo1(25), - regulator_desc_ldo1(26), - regulator_desc_ldo2(27), - regulator_desc_ldo1(28), - regulator_desc_ldo1(29), - regulator_desc_ldo1(30), - regulator_desc_ldo1(31), - regulator_desc_ldo1(32), - regulator_desc_ldo1(33), - regulator_desc_ldo1(34), - regulator_desc_ldo1(35), - regulator_desc_ldo1(36), - regulator_desc_ldo1(37), - regulator_desc_ldo1(38), - regulator_desc_buck1_4(1), - regulator_desc_buck1_4(2), - regulator_desc_buck1_4(3), - regulator_desc_buck1_4(4), - regulator_desc_buck5, - regulator_desc_buck6_8(6), - regulator_desc_buck6_8(7), - regulator_desc_buck6_8(8), - regulator_desc_buck9, - regulator_desc_buck10, + regulator_desc_s2mps11_ldo2(1), + regulator_desc_s2mps11_ldo1(2), + regulator_desc_s2mps11_ldo1(3), + regulator_desc_s2mps11_ldo1(4), + regulator_desc_s2mps11_ldo1(5), + regulator_desc_s2mps11_ldo2(6), + regulator_desc_s2mps11_ldo1(7), + regulator_desc_s2mps11_ldo1(8), + regulator_desc_s2mps11_ldo1(9), + regulator_desc_s2mps11_ldo1(10), + regulator_desc_s2mps11_ldo2(11), + regulator_desc_s2mps11_ldo1(12), + regulator_desc_s2mps11_ldo1(13), + regulator_desc_s2mps11_ldo1(14), + regulator_desc_s2mps11_ldo1(15), + regulator_desc_s2mps11_ldo1(16), + regulator_desc_s2mps11_ldo1(17), + regulator_desc_s2mps11_ldo1(18), + regulator_desc_s2mps11_ldo1(19), + regulator_desc_s2mps11_ldo1(20), + regulator_desc_s2mps11_ldo1(21), + regulator_desc_s2mps11_ldo2(22), + regulator_desc_s2mps11_ldo2(23), + regulator_desc_s2mps11_ldo1(24), + regulator_desc_s2mps11_ldo1(25), + regulator_desc_s2mps11_ldo1(26), + regulator_desc_s2mps11_ldo2(27), + regulator_desc_s2mps11_ldo1(28), + regulator_desc_s2mps11_ldo1(29), + regulator_desc_s2mps11_ldo1(30), + regulator_desc_s2mps11_ldo1(31), + regulator_desc_s2mps11_ldo1(32), + regulator_desc_s2mps11_ldo1(33), + regulator_desc_s2mps11_ldo1(34), + regulator_desc_s2mps11_ldo1(35), + regulator_desc_s2mps11_ldo1(36), + regulator_desc_s2mps11_ldo1(37), + regulator_desc_s2mps11_ldo1(38), + regulator_desc_s2mps11_buck1_4(1), + regulator_desc_s2mps11_buck1_4(2), + regulator_desc_s2mps11_buck1_4(3), + regulator_desc_s2mps11_buck1_4(4), + regulator_desc_s2mps11_buck5, + regulator_desc_s2mps11_buck6_8(6), + regulator_desc_s2mps11_buck6_8(7), + regulator_desc_s2mps11_buck6_8(8), + regulator_desc_s2mps11_buck9, + regulator_desc_s2mps11_buck10, +}; + +static struct regulator_ops s2mps14_reg_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .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, + .set_voltage_time_sel = regulator_set_voltage_time_sel, +}; + +#define regulator_desc_s2mps14_ldo1(num) { \ + .name = "LDO"#num, \ + .id = S2MPS14_LDO##num, \ + .ops = &s2mps14_reg_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = S2MPS14_LDO_MIN_800MV, \ + .uV_step = S2MPS14_LDO_STEP_25MV, \ + .n_voltages = S2MPS14_LDO_N_VOLTAGES, \ + .vsel_reg = S2MPS14_REG_L1CTRL + num - 1, \ + .vsel_mask = S2MPS14_LDO_VSEL_MASK, \ + .enable_reg = S2MPS14_REG_L1CTRL + num - 1, \ + .enable_mask = S2MPS14_ENABLE_MASK \ +} +#define regulator_desc_s2mps14_ldo2(num) { \ + .name = "LDO"#num, \ + .id = S2MPS14_LDO##num, \ + .ops = &s2mps14_reg_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = S2MPS14_LDO_MIN_1800MV, \ + .uV_step = S2MPS14_LDO_STEP_25MV, \ + .n_voltages = S2MPS14_LDO_N_VOLTAGES, \ + .vsel_reg = S2MPS14_REG_L1CTRL + num - 1, \ + .vsel_mask = S2MPS14_LDO_VSEL_MASK, \ + .enable_reg = S2MPS14_REG_L1CTRL + num - 1, \ + .enable_mask = S2MPS14_ENABLE_MASK \ +} +#define regulator_desc_s2mps14_ldo3(num) { \ + .name = "LDO"#num, \ + .id = S2MPS14_LDO##num, \ + .ops = &s2mps14_reg_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = S2MPS14_LDO_MIN_800MV, \ + .uV_step = S2MPS14_LDO_STEP_12_5MV, \ + .n_voltages = S2MPS14_LDO_N_VOLTAGES, \ + .vsel_reg = S2MPS14_REG_L1CTRL + num - 1, \ + .vsel_mask = S2MPS14_LDO_VSEL_MASK, \ + .enable_reg = S2MPS14_REG_L1CTRL + num - 1, \ + .enable_mask = S2MPS14_ENABLE_MASK \ +} +#define regulator_desc_s2mps14_buck1235(num) { \ + .name = "BUCK"#num, \ + .id = S2MPS14_BUCK##num, \ + .ops = &s2mps14_reg_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = S2MPS14_BUCK1235_MIN_600MV, \ + .uV_step = S2MPS14_BUCK1235_STEP_6_25MV, \ + .n_voltages = S2MPS14_BUCK_N_VOLTAGES, \ + .linear_min_sel = S2MPS14_BUCK1235_START_SEL, \ + .ramp_delay = S2MPS14_BUCK_RAMP_DELAY, \ + .vsel_reg = S2MPS14_REG_B1CTRL2 + (num - 1) * 2, \ + .vsel_mask = S2MPS14_BUCK_VSEL_MASK, \ + .enable_reg = S2MPS14_REG_B1CTRL1 + (num - 1) * 2, \ + .enable_mask = S2MPS14_ENABLE_MASK \ +} +#define regulator_desc_s2mps14_buck4(num) { \ + .name = "BUCK"#num, \ + .id = S2MPS14_BUCK##num, \ + .ops = &s2mps14_reg_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = S2MPS14_BUCK4_MIN_1400MV, \ + .uV_step = S2MPS14_BUCK4_STEP_12_5MV, \ + .n_voltages = S2MPS14_BUCK_N_VOLTAGES, \ + .linear_min_sel = S2MPS14_BUCK4_START_SEL, \ + .ramp_delay = S2MPS14_BUCK_RAMP_DELAY, \ + .vsel_reg = S2MPS14_REG_B1CTRL2 + (num - 1) * 2, \ + .vsel_mask = S2MPS14_BUCK_VSEL_MASK, \ + .enable_reg = S2MPS14_REG_B1CTRL1 + (num - 1) * 2, \ + .enable_mask = S2MPS14_ENABLE_MASK \ +} + +static const struct regulator_desc s2mps14_regulators[] = { + regulator_desc_s2mps14_ldo3(1), + regulator_desc_s2mps14_ldo3(2), + regulator_desc_s2mps14_ldo1(3), + regulator_desc_s2mps14_ldo1(4), + regulator_desc_s2mps14_ldo3(5), + regulator_desc_s2mps14_ldo3(6), + regulator_desc_s2mps14_ldo1(7), + regulator_desc_s2mps14_ldo2(8), + regulator_desc_s2mps14_ldo3(9), + regulator_desc_s2mps14_ldo3(10), + regulator_desc_s2mps14_ldo1(11), + regulator_desc_s2mps14_ldo2(12), + regulator_desc_s2mps14_ldo2(13), + regulator_desc_s2mps14_ldo2(14), + regulator_desc_s2mps14_ldo2(15), + regulator_desc_s2mps14_ldo2(16), + regulator_desc_s2mps14_ldo2(17), + regulator_desc_s2mps14_ldo2(18), + regulator_desc_s2mps14_ldo1(19), + regulator_desc_s2mps14_ldo1(20), + regulator_desc_s2mps14_ldo1(21), + regulator_desc_s2mps14_ldo3(22), + regulator_desc_s2mps14_ldo1(23), + regulator_desc_s2mps14_ldo2(24), + regulator_desc_s2mps14_ldo2(25), + regulator_desc_s2mps14_buck1235(1), + regulator_desc_s2mps14_buck1235(2), + regulator_desc_s2mps14_buck1235(3), + regulator_desc_s2mps14_buck4(4), + regulator_desc_s2mps14_buck1235(5), }; static int s2mps11_pmic_probe(struct platform_device *pdev) @@ -416,6 +541,10 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators); regulators = s2mps11_regulators; break; + case S2MPS14X: + s2mps11->rdev_num = ARRAY_SIZE(s2mps14_regulators); + regulators = s2mps14_regulators; + break; default: dev_err(&pdev->dev, "Invalid device type: %u\n", dev_type); return -EINVAL; @@ -482,6 +611,7 @@ out: static const struct platform_device_id s2mps11_pmic_id[] = { { "s2mps11-pmic", S2MPS11X}, + { "s2mps14-pmic", S2MPS14X}, { }, }; MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id); @@ -509,5 +639,5 @@ module_exit(s2mps11_pmic_exit); /* Module information */ MODULE_AUTHOR("Sangbeom Kim "); -MODULE_DESCRIPTION("SAMSUNG S2MPS11 Regulator Driver"); +MODULE_DESCRIPTION("SAMSUNG S2MPS11/S2MPS14 Regulator Driver"); MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From 05be09bb5ec8d12051515087a1983745dc93d906 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 7 Mar 2014 11:10:51 +0100 Subject: regulator: s2mps11: Add set_suspend_disable for S2MPS14 S2MPS14 regulators support suspend mode where their status is controlled by PWREN coming from SoC. This patch implements the set_suspend_disable for S2MPS14 regulators. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 51 ++++++++++++++++++++++++++++++++++++- include/linux/mfd/samsung/s2mps14.h | 2 ++ 2 files changed, 52 insertions(+), 1 deletion(-) (limited to 'drivers/regulator/s2mps11.c') diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 65697b1a26c0..cdd8d4066121 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -39,6 +39,11 @@ struct s2mps11_info { int ramp_delay16; int ramp_delay7810; int ramp_delay9; + /* + * One bit for each S2MPS14 regulator whether the suspend mode + * was enabled. + */ + unsigned int s2mps14_suspend_state:30; }; static int get_ramp_delay(int ramp_delay) @@ -399,15 +404,59 @@ static const struct regulator_desc s2mps11_regulators[] = { regulator_desc_s2mps11_buck10, }; +static int s2mps14_regulator_enable(struct regulator_dev *rdev) +{ + struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); + unsigned int val; + + if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev))) + val = S2MPS14_ENABLE_SUSPEND; + else + val = rdev->desc->enable_mask; + + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, val); +} + +static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev) +{ + int ret; + unsigned int val; + struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); + + /* LDO3 should be always on and does not support suspend mode */ + if (rdev_get_id(rdev) == S2MPS14_LDO3) + return 0; + + ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); + if (ret < 0) + return ret; + + s2mps11->s2mps14_suspend_state |= (1 << rdev_get_id(rdev)); + /* + * Don't enable suspend mode if regulator is already disabled because + * this would effectively for a short time turn on the regulator after + * resuming. + * However we still want to toggle the suspend_state bit for regulator + * in case if it got enabled before suspending the system. + */ + if (!(val & rdev->desc->enable_mask)) + return 0; + + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, S2MPS14_ENABLE_SUSPEND); +} + static struct regulator_ops s2mps14_reg_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .is_enabled = regulator_is_enabled_regmap, - .enable = regulator_enable_regmap, + .enable = s2mps14_regulator_enable, .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_suspend_disable = s2mps14_regulator_set_suspend_disable, }; #define regulator_desc_s2mps14_ldo1(num) { \ diff --git a/include/linux/mfd/samsung/s2mps14.h b/include/linux/mfd/samsung/s2mps14.h index ec1e0857ddde..4b449b8ac548 100644 --- a/include/linux/mfd/samsung/s2mps14.h +++ b/include/linux/mfd/samsung/s2mps14.h @@ -146,6 +146,8 @@ enum s2mps14_regulators { #define S2MPS14_BUCK_VSEL_MASK 0xFF #define S2MPS14_ENABLE_MASK (0x03 << S2MPS14_ENABLE_SHIFT) #define S2MPS14_ENABLE_SHIFT 6 +/* On/Off controlled by PWREN */ +#define S2MPS14_ENABLE_SUSPEND (0x01 << S2MPS14_ENABLE_SHIFT) #define S2MPS14_LDO_N_VOLTAGES (S2MPS14_LDO_VSEL_MASK + 1) #define S2MPS14_BUCK_N_VOLTAGES (S2MPS14_BUCK_VSEL_MASK + 1) -- cgit v1.2.3-59-g8ed1b From 14256f734ecce8dfb8fdce0e138d18f3fadf882e Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 4 Mar 2014 11:16:57 +0530 Subject: regulator: s2mps11: Use of_get_child_by_name of_find_node_by_name walks the allnodes list, and can thus walk outside of the parent node. Use of_get_child_by_name instead. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/regulator/s2mps11.c') diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index cdd8d4066121..906d764e98a8 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -616,7 +616,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) for (i = 0; i < s2mps11->rdev_num; i++) rdata[i].name = regulators[i].name; - reg_np = of_find_node_by_name(iodev->dev->of_node, "regulators"); + reg_np = of_get_child_by_name(iodev->dev->of_node, "regulators"); if (!reg_np) { dev_err(&pdev->dev, "could not find regulators sub-node\n"); ret = -EINVAL; -- cgit v1.2.3-59-g8ed1b From 991acaf629cb12774beb4662e6b3045504680779 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 4 Mar 2014 11:16:58 +0530 Subject: regulator: s2mps11: Add missing of_node_put Add of_node_put to decrement the ref count. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/regulator/s2mps11.c') diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 906d764e98a8..1f6fd4c45006 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -624,6 +624,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) } of_regulator_match(&pdev->dev, reg_np, rdata, s2mps11->rdev_num); + of_node_put(reg_np); common_reg: platform_set_drvdata(pdev, s2mps11); -- cgit v1.2.3-59-g8ed1b