diff options
Diffstat (limited to 'drivers/regulator/max77686.c')
-rw-r--r-- | drivers/regulator/max77686.c | 172 |
1 files changed, 80 insertions, 92 deletions
diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c index ef1af2debbd2..871b96bcd2d0 100644 --- a/drivers/regulator/max77686.c +++ b/drivers/regulator/max77686.c @@ -45,6 +45,23 @@ #define MAX77686_DVS_MINUV 600000 #define MAX77686_DVS_UVSTEP 12500 +/* + * Values used for configuring LDOs and bucks. + * Forcing low power mode: LDO1, 3-5, 9, 13, 17-26 + */ +#define MAX77686_LDO_LOWPOWER 0x1 +/* + * On/off controlled by PWRREQ: + * - LDO2, 6-8, 10-12, 14-16 + * - buck[1234] + */ +#define MAX77686_OFF_PWRREQ 0x1 +/* Low power mode controlled by PWRREQ: All LDOs */ +#define MAX77686_LDO_LOWPOWER_PWRREQ 0x2 +/* Forcing low power mode: buck[234] */ +#define MAX77686_BUCK_LOWPOWER 0x2 +#define MAX77686_NORMAL 0x3 + #define MAX77686_OPMODE_SHIFT 6 #define MAX77686_OPMODE_BUCK234_SHIFT 4 #define MAX77686_OPMODE_MASK 0x3 @@ -65,23 +82,36 @@ enum max77686_ramp_rate { }; struct max77686_data { + /* Array indexed by regulator id */ unsigned int opmode[MAX77686_REGULATORS]; }; -/* Some BUCKS supports Normal[ON/OFF] mode during suspend */ -static int max77686_buck_set_suspend_disable(struct regulator_dev *rdev) +static unsigned int max77686_get_opmode_shift(int id) { - unsigned int val; + switch (id) { + case MAX77686_BUCK1: + case MAX77686_BUCK5 ... MAX77686_BUCK9: + return 0; + case MAX77686_BUCK2 ... MAX77686_BUCK4: + return MAX77686_OPMODE_BUCK234_SHIFT; + default: + /* all LDOs */ + return MAX77686_OPMODE_SHIFT; + } +} + +/* Some BUCKs and LDOs supports Normal[ON/OFF] mode during suspend */ +static int max77686_set_suspend_disable(struct regulator_dev *rdev) +{ + unsigned int val, shift; struct max77686_data *max77686 = rdev_get_drvdata(rdev); int ret, id = rdev_get_id(rdev); - if (id == MAX77686_BUCK1) - val = 0x1; - else - val = 0x1 << MAX77686_OPMODE_BUCK234_SHIFT; + shift = max77686_get_opmode_shift(id); + val = MAX77686_OFF_PWRREQ; ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, - rdev->desc->enable_mask, val); + rdev->desc->enable_mask, val << shift); if (ret) return ret; @@ -103,10 +133,10 @@ static int max77686_set_suspend_mode(struct regulator_dev *rdev, switch (mode) { case REGULATOR_MODE_IDLE: /* ON in LP Mode */ - val = 0x2 << MAX77686_OPMODE_SHIFT; + val = MAX77686_LDO_LOWPOWER_PWRREQ; break; case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ - val = 0x3 << MAX77686_OPMODE_SHIFT; + val = MAX77686_NORMAL; break; default: pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n", @@ -115,7 +145,8 @@ static int max77686_set_suspend_mode(struct regulator_dev *rdev, } ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, - rdev->desc->enable_mask, val); + rdev->desc->enable_mask, + val << MAX77686_OPMODE_SHIFT); if (ret) return ret; @@ -133,13 +164,13 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev, switch (mode) { case REGULATOR_MODE_STANDBY: /* switch off */ - val = 0x1 << MAX77686_OPMODE_SHIFT; + val = MAX77686_OFF_PWRREQ; break; case REGULATOR_MODE_IDLE: /* ON in LP Mode */ - val = 0x2 << MAX77686_OPMODE_SHIFT; + val = MAX77686_LDO_LOWPOWER_PWRREQ; break; case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ - val = 0x3 << MAX77686_OPMODE_SHIFT; + val = MAX77686_NORMAL; break; default: pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n", @@ -148,7 +179,8 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev, } ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, - rdev->desc->enable_mask, val); + rdev->desc->enable_mask, + val << MAX77686_OPMODE_SHIFT); if (ret) return ret; @@ -159,10 +191,17 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev, static int max77686_enable(struct regulator_dev *rdev) { struct max77686_data *max77686 = rdev_get_drvdata(rdev); + unsigned int shift; + int id = rdev_get_id(rdev); + + shift = max77686_get_opmode_shift(id); + + if (max77686->opmode[id] == MAX77686_OFF_PWRREQ) + max77686->opmode[id] = MAX77686_NORMAL; return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, rdev->desc->enable_mask, - max77686->opmode[rdev_get_id(rdev)]); + max77686->opmode[id] << shift); } static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) @@ -212,6 +251,7 @@ static struct regulator_ops max77686_ldo_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_time_sel = regulator_set_voltage_time_sel, .set_suspend_mode = max77686_ldo_set_suspend_mode, + .set_suspend_disable = max77686_set_suspend_disable, }; static struct regulator_ops max77686_buck1_ops = { @@ -223,7 +263,7 @@ static struct regulator_ops max77686_buck1_ops = { .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 = max77686_buck_set_suspend_disable, + .set_suspend_disable = max77686_set_suspend_disable, }; static struct regulator_ops max77686_buck_dvs_ops = { @@ -236,11 +276,13 @@ static struct regulator_ops max77686_buck_dvs_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_time_sel = regulator_set_voltage_time_sel, .set_ramp_delay = max77686_set_ramp_delay, - .set_suspend_disable = max77686_buck_set_suspend_disable, + .set_suspend_disable = max77686_set_suspend_disable, }; #define regulator_desc_ldo(num) { \ .name = "LDO"#num, \ + .of_match = of_match_ptr("LDO"#num), \ + .regulators_node = of_match_ptr("voltage-regulators"), \ .id = MAX77686_LDO##num, \ .ops = &max77686_ops, \ .type = REGULATOR_VOLTAGE, \ @@ -257,6 +299,8 @@ static struct regulator_ops max77686_buck_dvs_ops = { } #define regulator_desc_lpm_ldo(num) { \ .name = "LDO"#num, \ + .of_match = of_match_ptr("LDO"#num), \ + .regulators_node = of_match_ptr("voltage-regulators"), \ .id = MAX77686_LDO##num, \ .ops = &max77686_ldo_ops, \ .type = REGULATOR_VOLTAGE, \ @@ -273,6 +317,8 @@ static struct regulator_ops max77686_buck_dvs_ops = { } #define regulator_desc_ldo_low(num) { \ .name = "LDO"#num, \ + .of_match = of_match_ptr("LDO"#num), \ + .regulators_node = of_match_ptr("voltage-regulators"), \ .id = MAX77686_LDO##num, \ .ops = &max77686_ldo_ops, \ .type = REGULATOR_VOLTAGE, \ @@ -289,6 +335,8 @@ static struct regulator_ops max77686_buck_dvs_ops = { } #define regulator_desc_ldo1_low(num) { \ .name = "LDO"#num, \ + .of_match = of_match_ptr("LDO"#num), \ + .regulators_node = of_match_ptr("voltage-regulators"), \ .id = MAX77686_LDO##num, \ .ops = &max77686_ops, \ .type = REGULATOR_VOLTAGE, \ @@ -305,6 +353,8 @@ static struct regulator_ops max77686_buck_dvs_ops = { } #define regulator_desc_buck(num) { \ .name = "BUCK"#num, \ + .of_match = of_match_ptr("BUCK"#num), \ + .regulators_node = of_match_ptr("voltage-regulators"), \ .id = MAX77686_BUCK##num, \ .ops = &max77686_ops, \ .type = REGULATOR_VOLTAGE, \ @@ -320,6 +370,8 @@ static struct regulator_ops max77686_buck_dvs_ops = { } #define regulator_desc_buck1(num) { \ .name = "BUCK"#num, \ + .of_match = of_match_ptr("BUCK"#num), \ + .regulators_node = of_match_ptr("voltage-regulators"), \ .id = MAX77686_BUCK##num, \ .ops = &max77686_buck1_ops, \ .type = REGULATOR_VOLTAGE, \ @@ -335,6 +387,8 @@ static struct regulator_ops max77686_buck_dvs_ops = { } #define regulator_desc_buck_dvs(num) { \ .name = "BUCK"#num, \ + .of_match = of_match_ptr("BUCK"#num), \ + .regulators_node = of_match_ptr("voltage-regulators"), \ .id = MAX77686_BUCK##num, \ .ops = &max77686_buck_dvs_ops, \ .type = REGULATOR_VOLTAGE, \ @@ -350,7 +404,7 @@ static struct regulator_ops max77686_buck_dvs_ops = { << MAX77686_OPMODE_BUCK234_SHIFT, \ } -static struct regulator_desc regulators[] = { +static const struct regulator_desc regulators[] = { regulator_desc_ldo1_low(1), regulator_desc_ldo_low(2), regulator_desc_ldo(3), @@ -388,103 +442,37 @@ static struct regulator_desc regulators[] = { regulator_desc_buck(9), }; -#ifdef CONFIG_OF -static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev, - struct max77686_platform_data *pdata) -{ - struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); - struct device_node *pmic_np, *regulators_np; - struct max77686_regulator_data *rdata; - struct of_regulator_match rmatch; - unsigned int i; - - pmic_np = iodev->dev->of_node; - regulators_np = of_get_child_by_name(pmic_np, "voltage-regulators"); - if (!regulators_np) { - dev_err(&pdev->dev, "could not find regulators sub-node\n"); - return -EINVAL; - } - - pdata->num_regulators = ARRAY_SIZE(regulators); - rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) * - pdata->num_regulators, GFP_KERNEL); - if (!rdata) { - of_node_put(regulators_np); - return -ENOMEM; - } - - for (i = 0; i < pdata->num_regulators; i++) { - rmatch.name = regulators[i].name; - rmatch.init_data = NULL; - rmatch.of_node = NULL; - of_regulator_match(&pdev->dev, regulators_np, &rmatch, 1); - rdata[i].initdata = rmatch.init_data; - rdata[i].of_node = rmatch.of_node; - } - - pdata->regulators = rdata; - of_node_put(regulators_np); - - return 0; -} -#else -static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev, - struct max77686_platform_data *pdata) -{ - return 0; -} -#endif /* CONFIG_OF */ - static int max77686_pmic_probe(struct platform_device *pdev) { struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); - struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev); struct max77686_data *max77686; - int i, ret = 0; + int i; struct regulator_config config = { }; dev_dbg(&pdev->dev, "%s\n", __func__); - if (!pdata) { - dev_err(&pdev->dev, "no platform data found for regulator\n"); - return -ENODEV; - } - - if (iodev->dev->of_node) { - ret = max77686_pmic_dt_parse_pdata(pdev, pdata); - if (ret) - return ret; - } - - if (pdata->num_regulators != MAX77686_REGULATORS) { - dev_err(&pdev->dev, - "Invalid initial data for regulator's initialiation\n"); - return -EINVAL; - } - max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data), GFP_KERNEL); if (!max77686) return -ENOMEM; - config.dev = &pdev->dev; + config.dev = iodev->dev; config.regmap = iodev->regmap; config.driver_data = max77686; platform_set_drvdata(pdev, max77686); for (i = 0; i < MAX77686_REGULATORS; i++) { struct regulator_dev *rdev; + int id = regulators[i].id; - config.init_data = pdata->regulators[i].initdata; - config.of_node = pdata->regulators[i].of_node; - - max77686->opmode[i] = regulators[i].enable_mask; + max77686->opmode[id] = MAX77686_NORMAL; rdev = devm_regulator_register(&pdev->dev, ®ulators[i], &config); if (IS_ERR(rdev)) { + int ret = PTR_ERR(rdev); dev_err(&pdev->dev, - "regulator init failed for %d\n", i); - return PTR_ERR(rdev); + "regulator init failed for %d: %d\n", i, ret); + return ret; } } |