diff options
Diffstat (limited to 'drivers/regulator/s2mps11.c')
| -rw-r--r-- | drivers/regulator/s2mps11.c | 473 |
1 files changed, 283 insertions, 190 deletions
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 7726b874e539..04ae9c6150bd 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -1,24 +1,12 @@ -/* - * s2mps11.c - * - * 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 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. - * - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// Copyright (c) 2012-2014 Samsung Electronics Co., Ltd +// http://www.samsung.com #include <linux/bug.h> +#include <linux/cleanup.h> #include <linux/err.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/of.h> @@ -27,13 +15,13 @@ #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> -#include <linux/of_gpio.h> #include <linux/mfd/samsung/core.h> #include <linux/mfd/samsung/s2mps11.h> #include <linux/mfd/samsung/s2mps13.h> #include <linux/mfd/samsung/s2mps14.h> #include <linux/mfd/samsung/s2mps15.h> #include <linux/mfd/samsung/s2mpu02.h> +#include <linux/mfd/samsung/s2mpu05.h> /* The highest number of possible regulators for supported devices. */ #define S2MPS_REGULATOR_MAX S2MPS13_REGULATOR_MAX @@ -48,7 +36,7 @@ struct s2mps11_info { enum sec_device_type dev_type; /* - * One bit for each S2MPS13/S2MPS14/S2MPU02 regulator whether + * One bit for each S2MPS11/S2MPS13/S2MPS14/S2MPU02 regulator whether * the suspend mode was enabled. */ DECLARE_BITMAP(suspend_state, S2MPS_REGULATOR_MAX); @@ -57,7 +45,7 @@ struct s2mps11_info { * Array (size: number of regulators) with GPIO-s for external * sleep control. */ - int *ext_control_gpio; + struct gpio_desc **ext_control_gpiod; }; static int get_ramp_delay(int ramp_delay) @@ -84,10 +72,11 @@ static int s2mps11_regulator_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int new_selector) { struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); + int rdev_id = rdev_get_id(rdev); unsigned int ramp_delay = 0; int old_volt, new_volt; - switch (rdev_get_id(rdev)) { + switch (rdev_id) { case S2MPS11_BUCK2: ramp_delay = s2mps11->ramp_delay2; break; @@ -125,9 +114,10 @@ static int s2mps11_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); unsigned int ramp_val, ramp_shift, ramp_reg = S2MPS11_REG_RAMP_BUCK; unsigned int ramp_enable = 1, enable_shift = 0; + int rdev_id = rdev_get_id(rdev); int ret; - switch (rdev_get_id(rdev)) { + switch (rdev_id) { case S2MPS11_BUCK1: if (ramp_delay > s2mps11->ramp_delay16) s2mps11->ramp_delay16 = ramp_delay; @@ -217,9 +207,8 @@ static int s2mps11_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) goto ramp_disable; /* Ramp delay can be enabled/disabled only for buck[2346] */ - if ((rdev_get_id(rdev) >= S2MPS11_BUCK2 && - rdev_get_id(rdev) <= S2MPS11_BUCK4) || - rdev_get_id(rdev) == S2MPS11_BUCK6) { + if ((rdev_id >= S2MPS11_BUCK2 && rdev_id <= S2MPS11_BUCK4) || + rdev_id == S2MPS11_BUCK6) { ret = regmap_update_bits(rdev->regmap, S2MPS11_REG_RAMP, 1 << enable_shift, 1 << enable_shift); if (ret) { @@ -238,27 +227,136 @@ ramp_disable: 1 << enable_shift, 0); } +static int s2mps11_regulator_enable(struct regulator_dev *rdev) +{ + struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); + int rdev_id = rdev_get_id(rdev); + unsigned int val; + + switch (s2mps11->dev_type) { + case S2MPS11X: + if (test_bit(rdev_id, s2mps11->suspend_state)) + val = S2MPS14_ENABLE_SUSPEND; + else + val = rdev->desc->enable_mask; + break; + case S2MPS13X: + case S2MPS14X: + if (test_bit(rdev_id, s2mps11->suspend_state)) + val = S2MPS14_ENABLE_SUSPEND; + else if (s2mps11->ext_control_gpiod[rdev_id]) + val = S2MPS14_ENABLE_EXT_CONTROL; + else + val = rdev->desc->enable_mask; + break; + case S2MPU02: + if (test_bit(rdev_id, s2mps11->suspend_state)) + val = S2MPU02_ENABLE_SUSPEND; + else + val = rdev->desc->enable_mask; + break; + case S2MPU05: + val = rdev->desc->enable_mask; + break; + default: + return -EINVAL; + } + + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, val); +} + +static int s2mps11_regulator_set_suspend_disable(struct regulator_dev *rdev) +{ + int ret; + unsigned int val, state; + struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); + int rdev_id = rdev_get_id(rdev); + + /* Below LDO should be always on or does not support suspend mode. */ + switch (s2mps11->dev_type) { + case S2MPS11X: + switch (rdev_id) { + case S2MPS11_LDO2: + case S2MPS11_LDO36: + case S2MPS11_LDO37: + case S2MPS11_LDO38: + return 0; + default: + state = S2MPS14_ENABLE_SUSPEND; + break; + } + break; + case S2MPS13X: + case S2MPS14X: + switch (rdev_id) { + case S2MPS14_LDO3: + return 0; + default: + state = S2MPS14_ENABLE_SUSPEND; + break; + } + break; + case S2MPU02: + switch (rdev_id) { + case S2MPU02_LDO13: + case S2MPU02_LDO14: + case S2MPU02_LDO15: + case S2MPU02_LDO17: + case S2MPU02_BUCK7: + state = S2MPU02_DISABLE_SUSPEND; + break; + default: + state = S2MPU02_ENABLE_SUSPEND; + break; + } + break; + default: + return -EINVAL; + } + + ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); + if (ret < 0) + return ret; + + set_bit(rdev_id, s2mps11->suspend_state); + /* + * 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, state); +} + static const struct regulator_ops s2mps11_ldo_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .is_enabled = regulator_is_enabled_regmap, - .enable = regulator_enable_regmap, + .enable = s2mps11_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 = s2mps11_regulator_set_suspend_disable, }; static const struct regulator_ops s2mps11_buck_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .is_enabled = regulator_is_enabled_regmap, - .enable = regulator_enable_regmap, + .enable = s2mps11_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 = s2mps11_regulator_set_voltage_time_sel, .set_ramp_delay = s2mps11_set_ramp_delay, + .set_suspend_disable = s2mps11_regulator_set_suspend_disable, }; #define regulator_desc_s2mps11_ldo(num, step) { \ @@ -283,9 +381,10 @@ static const struct regulator_ops s2mps11_buck_ops = { .ops = &s2mps11_buck_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ - .min_uV = MIN_600_MV, \ + .min_uV = MIN_650_MV, \ .uV_step = STEP_6_25_MV, \ - .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ + .linear_min_sel = 8, \ + .n_voltages = S2MPS11_BUCK12346_N_VOLTAGES, \ .ramp_delay = S2MPS11_RAMP_DELAY, \ .vsel_reg = S2MPS11_REG_B1CTRL2 + (num - 1) * 2, \ .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ @@ -299,9 +398,10 @@ static const struct regulator_ops s2mps11_buck_ops = { .ops = &s2mps11_buck_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ - .min_uV = MIN_600_MV, \ + .min_uV = MIN_650_MV, \ .uV_step = STEP_6_25_MV, \ - .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ + .linear_min_sel = 8, \ + .n_voltages = S2MPS11_BUCK5_N_VOLTAGES, \ .ramp_delay = S2MPS11_RAMP_DELAY, \ .vsel_reg = S2MPS11_REG_B5CTRL2, \ .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ @@ -309,7 +409,7 @@ static const struct regulator_ops s2mps11_buck_ops = { .enable_mask = S2MPS11_ENABLE_MASK \ } -#define regulator_desc_s2mps11_buck67810(num, min, step) { \ +#define regulator_desc_s2mps11_buck67810(num, min, step, min_sel, voltages) { \ .name = "BUCK"#num, \ .id = S2MPS11_BUCK##num, \ .ops = &s2mps11_buck_ops, \ @@ -317,7 +417,8 @@ static const struct regulator_ops s2mps11_buck_ops = { .owner = THIS_MODULE, \ .min_uV = min, \ .uV_step = step, \ - .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ + .linear_min_sel = min_sel, \ + .n_voltages = voltages, \ .ramp_delay = S2MPS11_RAMP_DELAY, \ .vsel_reg = S2MPS11_REG_B6CTRL2 + (num - 6) * 2, \ .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ @@ -376,7 +477,7 @@ static const struct regulator_desc s2mps11_regulators[] = { regulator_desc_s2mps11_ldo(32, STEP_50_MV), regulator_desc_s2mps11_ldo(33, STEP_50_MV), regulator_desc_s2mps11_ldo(34, STEP_50_MV), - regulator_desc_s2mps11_ldo(35, STEP_50_MV), + regulator_desc_s2mps11_ldo(35, STEP_25_MV), regulator_desc_s2mps11_ldo(36, STEP_50_MV), regulator_desc_s2mps11_ldo(37, STEP_50_MV), regulator_desc_s2mps11_ldo(38, STEP_50_MV), @@ -385,11 +486,15 @@ 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_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_buck67810(6, MIN_650_MV, STEP_6_25_MV, 8, + S2MPS11_BUCK12346_N_VOLTAGES), + regulator_desc_s2mps11_buck67810(7, MIN_750_MV, STEP_12_5_MV, 0, + S2MPS11_BUCK7810_N_VOLTAGES), + regulator_desc_s2mps11_buck67810(8, MIN_750_MV, STEP_12_5_MV, 0, + S2MPS11_BUCK7810_N_VOLTAGES), regulator_desc_s2mps11_buck9, - regulator_desc_s2mps11_buck67810(10, MIN_750_MV, STEP_12_5_MV), + regulator_desc_s2mps11_buck67810(10, MIN_750_MV, STEP_12_5_MV, 0, + S2MPS11_BUCK7810_N_VOLTAGES), }; static const struct regulator_ops s2mps14_reg_ops; @@ -514,101 +619,16 @@ static const struct regulator_desc s2mps13_regulators[] = { regulator_desc_s2mps13_buck8_10(10, MIN_500_MV, STEP_6_25_MV, 0x10), }; -static int s2mps14_regulator_enable(struct regulator_dev *rdev) -{ - struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); - unsigned int val; - - switch (s2mps11->dev_type) { - case S2MPS13X: - case S2MPS14X: - if (test_bit(rdev_get_id(rdev), s2mps11->suspend_state)) - val = S2MPS14_ENABLE_SUSPEND; - else if (gpio_is_valid(s2mps11->ext_control_gpio[rdev_get_id(rdev)])) - val = S2MPS14_ENABLE_EXT_CONTROL; - else - val = rdev->desc->enable_mask; - break; - case S2MPU02: - if (test_bit(rdev_get_id(rdev), s2mps11->suspend_state)) - val = S2MPU02_ENABLE_SUSPEND; - else - val = rdev->desc->enable_mask; - break; - default: - return -EINVAL; - } - - 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, state; - struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); - int rdev_id = rdev_get_id(rdev); - - /* Below LDO should be always on or does not support suspend mode. */ - switch (s2mps11->dev_type) { - case S2MPS13X: - case S2MPS14X: - switch (rdev_id) { - case S2MPS14_LDO3: - return 0; - default: - state = S2MPS14_ENABLE_SUSPEND; - break; - } - break; - case S2MPU02: - switch (rdev_id) { - case S2MPU02_LDO13: - case S2MPU02_LDO14: - case S2MPU02_LDO15: - case S2MPU02_LDO17: - case S2MPU02_BUCK7: - state = S2MPU02_DISABLE_SUSPEND; - break; - default: - state = S2MPU02_ENABLE_SUSPEND; - break; - } - break; - default: - return -EINVAL; - } - - ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); - if (ret < 0) - return ret; - - set_bit(rdev_get_id(rdev), s2mps11->suspend_state); - /* - * 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, state); -} - static const 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 = s2mps14_regulator_enable, + .enable = s2mps11_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, + .set_suspend_disable = s2mps11_regulator_set_suspend_disable, }; #define regulator_desc_s2mps14_ldo(num, min, step) { \ @@ -734,37 +754,37 @@ static const struct regulator_ops s2mps15_reg_buck_ops = { } /* voltage range for s2mps15 LDO 3, 5, 15, 16, 18, 20, 23 and 27 */ -static const struct regulator_linear_range s2mps15_ldo_voltage_ranges1[] = { +static const struct linear_range s2mps15_ldo_voltage_ranges1[] = { REGULATOR_LINEAR_RANGE(1000000, 0xc, 0x38, 25000), }; /* voltage range for s2mps15 LDO 2, 6, 14, 17, 19, 21, 24 and 25 */ -static const struct regulator_linear_range s2mps15_ldo_voltage_ranges2[] = { +static const struct linear_range s2mps15_ldo_voltage_ranges2[] = { REGULATOR_LINEAR_RANGE(1800000, 0x0, 0x3f, 25000), }; /* voltage range for s2mps15 LDO 4, 11, 12, 13, 22 and 26 */ -static const struct regulator_linear_range s2mps15_ldo_voltage_ranges3[] = { +static const struct linear_range s2mps15_ldo_voltage_ranges3[] = { REGULATOR_LINEAR_RANGE(700000, 0x0, 0x34, 12500), }; /* voltage range for s2mps15 LDO 7, 8, 9 and 10 */ -static const struct regulator_linear_range s2mps15_ldo_voltage_ranges4[] = { +static const struct linear_range s2mps15_ldo_voltage_ranges4[] = { REGULATOR_LINEAR_RANGE(700000, 0x10, 0x20, 25000), }; /* voltage range for s2mps15 LDO 1 */ -static const struct regulator_linear_range s2mps15_ldo_voltage_ranges5[] = { +static const struct linear_range s2mps15_ldo_voltage_ranges5[] = { REGULATOR_LINEAR_RANGE(500000, 0x0, 0x20, 12500), }; /* voltage range for s2mps15 BUCK 1, 2, 3, 4, 5, 6 and 7 */ -static const struct regulator_linear_range s2mps15_buck_voltage_ranges1[] = { +static const struct linear_range s2mps15_buck_voltage_ranges1[] = { REGULATOR_LINEAR_RANGE(500000, 0x20, 0xc0, 6250), }; /* voltage range for s2mps15 BUCK 8, 9 and 10 */ -static const struct regulator_linear_range s2mps15_buck_voltage_ranges2[] = { +static const struct linear_range s2mps15_buck_voltage_ranges2[] = { REGULATOR_LINEAR_RANGE(1000000, 0x20, 0x78, 12500), }; @@ -818,7 +838,7 @@ static int s2mps14_pmic_enable_ext_control(struct s2mps11_info *s2mps11, static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev, struct of_regulator_match *rdata, struct s2mps11_info *s2mps11) { - int *gpio = s2mps11->ext_control_gpio; + struct gpio_desc **gpio = s2mps11->ext_control_gpiod; unsigned int i; unsigned int valid_regulators[3] = { S2MPS14_LDO10, S2MPS14_LDO11, S2MPS14_LDO12 }; @@ -829,11 +849,22 @@ static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev, if (!rdata[reg].init_data || !rdata[reg].of_node) continue; - gpio[reg] = of_get_named_gpio(rdata[reg].of_node, - "samsung,ext-control-gpios", 0); - if (gpio_is_valid(gpio[reg])) - dev_dbg(&pdev->dev, "Using GPIO %d for ext-control over %d/%s\n", - gpio[reg], reg, rdata[reg].name); + gpio[reg] = devm_fwnode_gpiod_get(&pdev->dev, + of_fwnode_handle(rdata[reg].of_node), + "samsung,ext-control", + GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE, + "s2mps11-regulator"); + if (PTR_ERR(gpio[reg]) == -ENOENT) + gpio[reg] = NULL; + else if (IS_ERR(gpio[reg])) { + dev_err(&pdev->dev, "Failed to get control GPIO for %d/%s\n", + reg, rdata[reg].name); + gpio[reg] = NULL; + continue; + } + if (gpio[reg]) + dev_dbg(&pdev->dev, "Using GPIO for ext-control over %d/%s\n", + reg, rdata[reg].name); } } @@ -861,8 +892,9 @@ static int s2mps11_pmic_dt_parse(struct platform_device *pdev, static int s2mpu02_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) { unsigned int ramp_val, ramp_shift, ramp_reg; + int rdev_id = rdev_get_id(rdev); - switch (rdev_get_id(rdev)) { + switch (rdev_id) { case S2MPU02_BUCK1: ramp_shift = S2MPU02_BUCK1_RAMP_SHIFT; break; @@ -890,24 +922,24 @@ static const struct regulator_ops s2mpu02_ldo_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .is_enabled = regulator_is_enabled_regmap, - .enable = s2mps14_regulator_enable, + .enable = s2mps11_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, + .set_suspend_disable = s2mps11_regulator_set_suspend_disable, }; static const struct regulator_ops s2mpu02_buck_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .is_enabled = regulator_is_enabled_regmap, - .enable = s2mps14_regulator_enable, + .enable = s2mps11_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, + .set_suspend_disable = s2mps11_regulator_set_suspend_disable, .set_ramp_delay = s2mpu02_set_ramp_delay, }; @@ -1090,11 +1122,89 @@ static const struct regulator_desc s2mpu02_regulators[] = { regulator_desc_s2mpu02_buck7(7), }; +#define regulator_desc_s2mpu05_ldo_reg(num, min, step, reg) { \ + .name = "ldo"#num, \ + .id = S2MPU05_LDO##num, \ + .ops = &s2mpu02_ldo_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = min, \ + .uV_step = step, \ + .n_voltages = S2MPU05_LDO_N_VOLTAGES, \ + .vsel_reg = reg, \ + .vsel_mask = S2MPU05_LDO_VSEL_MASK, \ + .enable_reg = reg, \ + .enable_mask = S2MPU05_ENABLE_MASK, \ + .enable_time = S2MPU05_ENABLE_TIME_LDO \ +} + +#define regulator_desc_s2mpu05_ldo(num, reg, min, step) \ + regulator_desc_s2mpu05_ldo_reg(num, min, step, S2MPU05_REG_L##num##reg) + +#define regulator_desc_s2mpu05_ldo1(num, reg) \ + regulator_desc_s2mpu05_ldo(num, reg, S2MPU05_LDO_MIN1, S2MPU05_LDO_STEP1) + +#define regulator_desc_s2mpu05_ldo2(num, reg) \ + regulator_desc_s2mpu05_ldo(num, reg, S2MPU05_LDO_MIN1, S2MPU05_LDO_STEP2) + +#define regulator_desc_s2mpu05_ldo3(num, reg) \ + regulator_desc_s2mpu05_ldo(num, reg, S2MPU05_LDO_MIN2, S2MPU05_LDO_STEP2) + +#define regulator_desc_s2mpu05_ldo4(num, reg) \ + regulator_desc_s2mpu05_ldo(num, reg, S2MPU05_LDO_MIN3, S2MPU05_LDO_STEP2) + +#define regulator_desc_s2mpu05_buck(num, which) { \ + .name = "buck"#num, \ + .id = S2MPU05_BUCK##num, \ + .ops = &s2mpu02_buck_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = S2MPU05_BUCK_MIN##which, \ + .uV_step = S2MPU05_BUCK_STEP##which, \ + .n_voltages = S2MPU05_BUCK_N_VOLTAGES, \ + .vsel_reg = S2MPU05_REG_B##num##CTRL2, \ + .vsel_mask = S2MPU05_BUCK_VSEL_MASK, \ + .enable_reg = S2MPU05_REG_B##num##CTRL1, \ + .enable_mask = S2MPU05_ENABLE_MASK, \ + .enable_time = S2MPU05_ENABLE_TIME_BUCK##num \ +} + +#define regulator_desc_s2mpu05_buck123(num) regulator_desc_s2mpu05_buck(num, 1) +#define regulator_desc_s2mpu05_buck45(num) regulator_desc_s2mpu05_buck(num, 2) + +static const struct regulator_desc s2mpu05_regulators[] = { + regulator_desc_s2mpu05_ldo4(1, CTRL), + regulator_desc_s2mpu05_ldo3(2, CTRL), + regulator_desc_s2mpu05_ldo2(3, CTRL), + regulator_desc_s2mpu05_ldo1(4, CTRL), + regulator_desc_s2mpu05_ldo1(5, CTRL), + regulator_desc_s2mpu05_ldo1(6, CTRL), + regulator_desc_s2mpu05_ldo2(7, CTRL), + regulator_desc_s2mpu05_ldo3(8, CTRL), + regulator_desc_s2mpu05_ldo4(9, CTRL1), + regulator_desc_s2mpu05_ldo4(10, CTRL), + /* LDOs 11-24 are used for CP. They aren't documented. */ + regulator_desc_s2mpu05_ldo2(25, CTRL), + regulator_desc_s2mpu05_ldo3(26, CTRL), + regulator_desc_s2mpu05_ldo2(27, CTRL), + regulator_desc_s2mpu05_ldo3(28, CTRL), + regulator_desc_s2mpu05_ldo3(29, CTRL), + regulator_desc_s2mpu05_ldo2(30, CTRL), + regulator_desc_s2mpu05_ldo3(31, CTRL), + regulator_desc_s2mpu05_ldo3(32, CTRL), + regulator_desc_s2mpu05_ldo3(33, CTRL), + regulator_desc_s2mpu05_ldo3(34, CTRL), + regulator_desc_s2mpu05_ldo3(35, CTRL), + regulator_desc_s2mpu05_buck123(1), + regulator_desc_s2mpu05_buck123(2), + regulator_desc_s2mpu05_buck123(3), + regulator_desc_s2mpu05_buck45(4), + regulator_desc_s2mpu05_buck45(5), +}; + 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 = NULL; - struct of_regulator_match *rdata = NULL; struct regulator_config config = { }; struct s2mps11_info *s2mps11; unsigned int rdev_num = 0; @@ -1133,36 +1243,24 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) regulators = s2mpu02_regulators; BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mpu02_regulators)); break; + case S2MPU05: + rdev_num = ARRAY_SIZE(s2mpu05_regulators); + regulators = s2mpu05_regulators; + BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mpu05_regulators)); + break; default: dev_err(&pdev->dev, "Invalid device type: %u\n", s2mps11->dev_type); return -EINVAL; } - s2mps11->ext_control_gpio = devm_kmalloc(&pdev->dev, - sizeof(*s2mps11->ext_control_gpio) * rdev_num, - GFP_KERNEL); - if (!s2mps11->ext_control_gpio) + s2mps11->ext_control_gpiod = devm_kcalloc(&pdev->dev, rdev_num, + sizeof(*s2mps11->ext_control_gpiod), GFP_KERNEL); + if (!s2mps11->ext_control_gpiod) return -ENOMEM; - /* - * 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 < rdev_num; i++) - s2mps11->ext_control_gpio[i] = -EINVAL; - - if (!iodev->dev->of_node) { - if (iodev->pdata) { - pdata = iodev->pdata; - goto common_reg; - } else { - dev_err(pdev->dev.parent, - "Platform data or DT node not supplied\n"); - return -ENODEV; - } - } - rdata = kzalloc(sizeof(*rdata) * rdev_num, GFP_KERNEL); + struct of_regulator_match *rdata __free(kfree) = + kcalloc(rdev_num, sizeof(*rdata), GFP_KERNEL); if (!rdata) return -ENOMEM; @@ -1171,53 +1269,46 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11, rdev_num); if (ret) - goto out; + return ret; -common_reg: platform_set_drvdata(pdev, s2mps11); config.dev = &pdev->dev; config.regmap = iodev->regmap_pmic; config.driver_data = s2mps11; - config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH; - config.ena_gpio_initialized = true; for (i = 0; i < rdev_num; i++) { struct regulator_dev *regulator; - if (pdata) { - config.init_data = pdata->regulators[i].initdata; - config.of_node = pdata->regulators[i].reg_node; - } else { - config.init_data = rdata[i].init_data; - config.of_node = rdata[i].of_node; - } - config.ena_gpio = s2mps11->ext_control_gpio[i]; - + config.init_data = rdata[i].init_data; + config.of_node = rdata[i].of_node; + config.ena_gpiod = s2mps11->ext_control_gpiod[i]; + /* + * Hand the GPIO descriptor management over to the regulator + * core, remove it from devres management. + */ + if (config.ena_gpiod) + devm_gpiod_unhinge(&pdev->dev, config.ena_gpiod); regulator = devm_regulator_register(&pdev->dev, ®ulators[i], &config); if (IS_ERR(regulator)) { - ret = PTR_ERR(regulator); dev_err(&pdev->dev, "regulator init failed for %d\n", i); - goto out; + return PTR_ERR(regulator); } - if (gpio_is_valid(s2mps11->ext_control_gpio[i])) { + if (config.ena_gpiod) { ret = s2mps14_pmic_enable_ext_control(s2mps11, regulator); if (ret < 0) { dev_err(&pdev->dev, "failed to enable GPIO control over %s: %d\n", regulator->desc->name, ret); - goto out; + return ret; } } } -out: - kfree(rdata); - - return ret; + return 0; } static const struct platform_device_id s2mps11_pmic_id[] = { @@ -1226,6 +1317,7 @@ static const struct platform_device_id s2mps11_pmic_id[] = { { "s2mps14-regulator", S2MPS14X}, { "s2mps15-regulator", S2MPS15X}, { "s2mpu02-regulator", S2MPU02}, + { "s2mpu05-regulator", S2MPU05}, { }, }; MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id); @@ -1233,6 +1325,7 @@ MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id); static struct platform_driver s2mps11_pmic_driver = { .driver = { .name = "s2mps11-pmic", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .probe = s2mps11_pmic_probe, .id_table = s2mps11_pmic_id, @@ -1242,5 +1335,5 @@ module_platform_driver(s2mps11_pmic_driver); /* Module information */ MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>"); -MODULE_DESCRIPTION("SAMSUNG S2MPS11/S2MPS14/S2MPS15/S2MPU02 Regulator Driver"); +MODULE_DESCRIPTION("Samsung S2MPS11/14/15/S2MPU02/05 Regulator Driver"); MODULE_LICENSE("GPL"); |
