From 7cf225b98a7b899323edeb3ef709da880fa88481 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 23 Apr 2015 21:24:32 +0900 Subject: regulator: Remove unneeded semicolons Remove unneeded semicolons after the switch statement to satisfy coccicheck. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/regulator/of_regulator.c | 2 +- drivers/regulator/s2mps11.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 24e812c48d93..e952439e0d83 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -108,7 +108,7 @@ static void of_get_regulation_constraints(struct device_node *np, case PM_SUSPEND_STANDBY: default: continue; - }; + } suspend_np = of_get_child_by_name(np, regulator_states[i]); if (!suspend_np || !suspend_state) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index ff828117798f..326ffb553371 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -515,7 +515,7 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev) break; default: return -EINVAL; - }; + } return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, rdev->desc->enable_mask, val); @@ -538,7 +538,7 @@ static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev) default: state = S2MPS14_ENABLE_SUSPEND; break; - }; + } break; case S2MPU02: switch (rdev_id) { @@ -552,11 +552,11 @@ static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev) default: state = S2MPU02_ENABLE_SUSPEND; break; - }; + } break; default: return -EINVAL; - }; + } ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); if (ret < 0) @@ -977,7 +977,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) 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) * s2mps11->rdev_num, -- cgit v1.2.3-55-g7522 From 0cfeddbded4ad41dba5faccf3c5ecfe5619ae9eb Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 2 May 2015 00:45:05 +0900 Subject: regulator: 88pm8607: Constify platform_device_id The platform_device_id is not modified by the driver and core uses it as const. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/regulator/88pm8607.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index c3d15427adc7..b100a63ff3b3 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -404,7 +404,7 @@ static int pm8607_regulator_probe(struct platform_device *pdev) return 0; } -static struct platform_device_id pm8607_regulator_driver_ids[] = { +static const struct platform_device_id pm8607_regulator_driver_ids[] = { { .name = "88pm860x-regulator", .driver_data = 0, -- cgit v1.2.3-55-g7522 From 9a6c2febdc7fc9ad2fc8b7a7bdb49ae476f424c1 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 11 May 2015 13:58:07 +0100 Subject: regulator: arizona-ldo1: Add additional supported voltage This patch adds support for the 1.175V mode on the LDO1 regulator on the wm5110. This is need as part of the low power sleep mode operation. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- drivers/regulator/arizona-ldo1.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c index a1d07d347c20..90941632efa9 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c @@ -178,6 +178,16 @@ static const struct regulator_init_data arizona_ldo1_default = { .num_consumer_supplies = 1, }; +static const struct regulator_init_data arizona_ldo1_wm5110 = { + .constraints = { + .min_uV = 1175000, + .max_uV = 1200000, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_VOLTAGE, + }, + .num_consumer_supplies = 1, +}; + static int arizona_ldo1_of_get_pdata(struct arizona *arizona, struct regulator_config *config, const struct regulator_desc *desc) @@ -243,6 +253,11 @@ static int arizona_ldo1_probe(struct platform_device *pdev) desc = &arizona_ldo1_hc; ldo1->init_data = arizona_ldo1_dvfs; break; + case WM5110: + case WM8280: + desc = &arizona_ldo1; + ldo1->init_data = arizona_ldo1_wm5110; + break; default: desc = &arizona_ldo1; ldo1->init_data = arizona_ldo1_default; -- cgit v1.2.3-55-g7522 From 4068e5182ada260d8a09f35db79fc2582e08baec Mon Sep 17 00:00:00 2001 From: S Twiss Date: Tue, 19 May 2015 14:10:30 +0100 Subject: regulator: da9062: DA9062 regulator driver Add BUCK and LDO regulator driver support for DA9062 Signed-off-by: Steve Twiss Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 10 + drivers/regulator/Makefile | 1 + drivers/regulator/da9062-regulator.c | 843 +++++++++++++++++++++++++++++++++++ 3 files changed, 854 insertions(+) create mode 100644 drivers/regulator/da9062-regulator.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index a6f116aa5235..1fd6dc3e8341 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -178,6 +178,16 @@ config REGULATOR_DA9055 This driver can also be built as a module. If so, the module will be called da9055-regulator. +config REGULATOR_DA9062 + tristate "Dialog Semiconductor DA9062 regulators" + depends on MFD_DA9062 + help + Say y here to support the BUCKs and LDOs regulators found on + DA9062 PMICs. + + This driver can also be built as a module. If so, the module + will be called da9062-regulator. + config REGULATOR_DA9063 tristate "Dialog Semiconductor DA9063 regulators" depends on MFD_DA9063 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 2c4da15e1545..12ecb65d1a3a 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o obj-$(CONFIG_REGULATOR_DA903X) += da903x.o obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o +obj-$(CONFIG_REGULATOR_DA9062) += da9062-regulator.o obj-$(CONFIG_REGULATOR_DA9063) += da9063-regulator.o obj-$(CONFIG_REGULATOR_DA9210) += da9210-regulator.o obj-$(CONFIG_REGULATOR_DA9211) += da9211-regulator.o diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c new file mode 100644 index 000000000000..9805b6b0bdef --- /dev/null +++ b/drivers/regulator/da9062-regulator.c @@ -0,0 +1,843 @@ +/* + * da9062-regulator.c - REGULATOR device driver for DA9062 + * Copyright (C) 2015 Dialog Semiconductor Ltd. + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Regulator IDs */ +enum { + DA9062_ID_BUCK1, + DA9062_ID_BUCK2, + DA9062_ID_BUCK3, + DA9062_ID_BUCK4, + DA9062_ID_LDO1, + DA9062_ID_LDO2, + DA9062_ID_LDO3, + DA9062_ID_LDO4, + DA9062_MAX_REGULATORS, +}; + +/* Regulator capabilities and registers description */ +struct da9062_regulator_info { + struct regulator_desc desc; + /* Current limiting */ + unsigned int n_current_limits; + const int *current_limits; + /* Main register fields */ + struct reg_field mode; + struct reg_field suspend; + struct reg_field sleep; + struct reg_field suspend_sleep; + unsigned int suspend_vsel_reg; + struct reg_field ilimit; + /* Event detection bit */ + struct reg_field oc_event; +}; + +/* Single regulator settings */ +struct da9062_regulator { + struct regulator_desc desc; + struct regulator_dev *rdev; + struct da9062 *hw; + const struct da9062_regulator_info *info; + + struct regmap_field *mode; + struct regmap_field *suspend; + struct regmap_field *sleep; + struct regmap_field *suspend_sleep; + struct regmap_field *ilimit; +}; + +/* Encapsulates all information for the regulators driver */ +struct da9062_regulators { + int irq_ldo_lim; + unsigned n_regulators; + /* Array size to be defined during init. Keep at end. */ + struct da9062_regulator regulator[0]; +}; + +/* BUCK modes */ +enum { + BUCK_MODE_MANUAL, /* 0 */ + BUCK_MODE_SLEEP, /* 1 */ + BUCK_MODE_SYNC, /* 2 */ + BUCK_MODE_AUTO /* 3 */ +}; + +/* Regulator operations */ + +/* Current limits array (in uA) BUCK1 and BUCK3. + Entry indexes corresponds to register values. */ +static const int da9062_buck_a_limits[] = { + 500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000, + 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1900000, 2000000 +}; + +/* Current limits array (in uA) for BUCK2. + Entry indexes corresponds to register values. */ +static const int da9062_buck_b_limits[] = { + 1500000, 1600000, 1700000, 1800000, 1900000, 2000000, 2100000, 2200000, + 2300000, 2400000, 2500000, 2600000, 2700000, 2800000, 2900000, 3000000 +}; + +static int da9062_set_current_limit(struct regulator_dev *rdev, + int min_ua, int max_ua) +{ + struct da9062_regulator *regl = rdev_get_drvdata(rdev); + const struct da9062_regulator_info *rinfo = regl->info; + int n, tval; + + for (n = 0; n < rinfo->n_current_limits; n++) { + tval = rinfo->current_limits[n]; + if (tval >= min_ua && tval <= max_ua) + return regmap_field_write(regl->ilimit, n); + } + + return -EINVAL; +} + +static int da9062_get_current_limit(struct regulator_dev *rdev) +{ + struct da9062_regulator *regl = rdev_get_drvdata(rdev); + const struct da9062_regulator_info *rinfo = regl->info; + unsigned int sel; + int ret; + + ret = regmap_field_read(regl->ilimit, &sel); + if (ret < 0) + return ret; + + if (sel >= rinfo->n_current_limits) + sel = rinfo->n_current_limits - 1; + + return rinfo->current_limits[sel]; +} + +static int da9062_buck_set_mode(struct regulator_dev *rdev, unsigned mode) +{ + struct da9062_regulator *regl = rdev_get_drvdata(rdev); + unsigned val; + + switch (mode) { + case REGULATOR_MODE_FAST: + val = BUCK_MODE_SYNC; + break; + case REGULATOR_MODE_NORMAL: + val = BUCK_MODE_AUTO; + break; + case REGULATOR_MODE_STANDBY: + val = BUCK_MODE_SLEEP; + break; + default: + return -EINVAL; + } + + return regmap_field_write(regl->mode, val); +} + +/* + * Bucks use single mode register field for normal operation + * and suspend state. + * There are 3 modes to map to: FAST, NORMAL, and STANDBY. + */ + +static unsigned da9062_buck_get_mode(struct regulator_dev *rdev) +{ + struct da9062_regulator *regl = rdev_get_drvdata(rdev); + struct regmap_field *field; + unsigned int val, mode = 0; + int ret; + + ret = regmap_field_read(regl->mode, &val); + if (ret < 0) + return ret; + + switch (val) { + default: + case BUCK_MODE_MANUAL: + mode = REGULATOR_MODE_FAST | REGULATOR_MODE_STANDBY; + /* Sleep flag bit decides the mode */ + break; + case BUCK_MODE_SLEEP: + return REGULATOR_MODE_STANDBY; + case BUCK_MODE_SYNC: + return REGULATOR_MODE_FAST; + case BUCK_MODE_AUTO: + return REGULATOR_MODE_NORMAL; + } + + /* Detect current regulator state */ + ret = regmap_field_read(regl->suspend, &val); + if (ret < 0) + return 0; + + /* Read regulator mode from proper register, depending on state */ + if (val) + field = regl->suspend_sleep; + else + field = regl->sleep; + + ret = regmap_field_read(field, &val); + if (ret < 0) + return 0; + + if (val) + mode &= REGULATOR_MODE_STANDBY; + else + mode &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_FAST; + + return mode; +} + +/* + * LDOs use sleep flags - one for normal and one for suspend state. + * There are 2 modes to map to: NORMAL and STANDBY (sleep) for each state. + */ + +static int da9062_ldo_set_mode(struct regulator_dev *rdev, unsigned mode) +{ + struct da9062_regulator *regl = rdev_get_drvdata(rdev); + unsigned val; + + switch (mode) { + case REGULATOR_MODE_NORMAL: + val = 0; + break; + case REGULATOR_MODE_STANDBY: + val = 1; + break; + default: + return -EINVAL; + } + + return regmap_field_write(regl->sleep, val); +} + +static unsigned da9062_ldo_get_mode(struct regulator_dev *rdev) +{ + struct da9062_regulator *regl = rdev_get_drvdata(rdev); + struct regmap_field *field; + int ret, val; + + /* Detect current regulator state */ + ret = regmap_field_read(regl->suspend, &val); + if (ret < 0) + return 0; + + /* Read regulator mode from proper register, depending on state */ + if (val) + field = regl->suspend_sleep; + else + field = regl->sleep; + + ret = regmap_field_read(field, &val); + if (ret < 0) + return 0; + + if (val) + return REGULATOR_MODE_STANDBY; + else + return REGULATOR_MODE_NORMAL; +} + +static int da9062_buck_get_status(struct regulator_dev *rdev) +{ + int ret = regulator_is_enabled_regmap(rdev); + + if (ret == 0) { + ret = REGULATOR_STATUS_OFF; + } else if (ret > 0) { + ret = da9062_buck_get_mode(rdev); + if (ret > 0) + ret = regulator_mode_to_status(ret); + else if (ret == 0) + ret = -EIO; + } + + return ret; +} + +static int da9062_ldo_get_status(struct regulator_dev *rdev) +{ + int ret = regulator_is_enabled_regmap(rdev); + + if (ret == 0) { + ret = REGULATOR_STATUS_OFF; + } else if (ret > 0) { + ret = da9062_ldo_get_mode(rdev); + if (ret > 0) + ret = regulator_mode_to_status(ret); + else if (ret == 0) + ret = -EIO; + } + + return ret; +} + +static int da9062_set_suspend_voltage(struct regulator_dev *rdev, int uv) +{ + struct da9062_regulator *regl = rdev_get_drvdata(rdev); + const struct da9062_regulator_info *rinfo = regl->info; + int ret, sel; + + sel = regulator_map_voltage_linear(rdev, uv, uv); + if (sel < 0) + return sel; + + sel <<= ffs(rdev->desc->vsel_mask) - 1; + + ret = regmap_update_bits(regl->hw->regmap, rinfo->suspend_vsel_reg, + rdev->desc->vsel_mask, sel); + + return ret; +} + +static int da9062_suspend_enable(struct regulator_dev *rdev) +{ + struct da9062_regulator *regl = rdev_get_drvdata(rdev); + + return regmap_field_write(regl->suspend, 1); +} + +static int da9062_suspend_disable(struct regulator_dev *rdev) +{ + struct da9062_regulator *regl = rdev_get_drvdata(rdev); + + return regmap_field_write(regl->suspend, 0); +} + +static int da9062_buck_set_suspend_mode(struct regulator_dev *rdev, + unsigned mode) +{ + struct da9062_regulator *regl = rdev_get_drvdata(rdev); + int val; + + switch (mode) { + case REGULATOR_MODE_FAST: + val = BUCK_MODE_SYNC; + break; + case REGULATOR_MODE_NORMAL: + val = BUCK_MODE_AUTO; + break; + case REGULATOR_MODE_STANDBY: + val = BUCK_MODE_SLEEP; + break; + default: + return -EINVAL; + } + + return regmap_field_write(regl->mode, val); +} + +static int da9062_ldo_set_suspend_mode(struct regulator_dev *rdev, + unsigned mode) +{ + struct da9062_regulator *regl = rdev_get_drvdata(rdev); + unsigned val; + + switch (mode) { + case REGULATOR_MODE_NORMAL: + val = 0; + break; + case REGULATOR_MODE_STANDBY: + val = 1; + break; + default: + return -EINVAL; + } + + return regmap_field_write(regl->suspend_sleep, val); +} + +static struct regulator_ops da9062_buck_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_linear, + .set_current_limit = da9062_set_current_limit, + .get_current_limit = da9062_get_current_limit, + .set_mode = da9062_buck_set_mode, + .get_mode = da9062_buck_get_mode, + .get_status = da9062_buck_get_status, + .set_suspend_voltage = da9062_set_suspend_voltage, + .set_suspend_enable = da9062_suspend_enable, + .set_suspend_disable = da9062_suspend_disable, + .set_suspend_mode = da9062_buck_set_suspend_mode, +}; + +static struct regulator_ops da9062_ldo_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_linear, + .set_mode = da9062_ldo_set_mode, + .get_mode = da9062_ldo_get_mode, + .get_status = da9062_ldo_get_status, + .set_suspend_voltage = da9062_set_suspend_voltage, + .set_suspend_enable = da9062_suspend_enable, + .set_suspend_disable = da9062_suspend_disable, + .set_suspend_mode = da9062_ldo_set_suspend_mode, +}; + +/* Regulator information */ +static const struct da9062_regulator_info local_regulator_info[] = { + { + .desc.id = DA9062_ID_BUCK1, + .desc.name = "DA9062 BUCK1", + .desc.of_match = of_match_ptr("buck1"), + .desc.regulators_node = of_match_ptr("regulators"), + .desc.ops = &da9062_buck_ops, + .desc.min_uV = (300) * 1000, + .desc.uV_step = (10) * 1000, + .desc.n_voltages = ((1570) - (300))/(10) + 1, + .current_limits = da9062_buck_a_limits, + .n_current_limits = ARRAY_SIZE(da9062_buck_a_limits), + .desc.enable_reg = DA9062AA_BUCK1_CONT, + .desc.enable_mask = DA9062AA_BUCK1_EN_MASK, + .desc.vsel_reg = DA9062AA_VBUCK1_A, + .desc.vsel_mask = DA9062AA_VBUCK1_A_MASK, + .desc.linear_min_sel = 0, + .sleep = REG_FIELD(DA9062AA_VBUCK1_A, + __builtin_ffs((int)DA9062AA_BUCK1_SL_A_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_BUCK1_SL_A_MASK)) - 1), + .suspend_sleep = REG_FIELD(DA9062AA_VBUCK1_B, + __builtin_ffs((int)DA9062AA_BUCK1_SL_B_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_BUCK1_SL_B_MASK)) - 1), + .suspend_vsel_reg = DA9062AA_VBUCK1_B, + .mode = REG_FIELD(DA9062AA_BUCK1_CFG, + __builtin_ffs((int)DA9062AA_BUCK1_MODE_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_BUCK1_MODE_MASK)) - 1), + .suspend = REG_FIELD(DA9062AA_DVC_1, + __builtin_ffs((int)DA9062AA_VBUCK1_SEL_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_VBUCK1_SEL_MASK)) - 1), + .ilimit = REG_FIELD(DA9062AA_BUCK_ILIM_C, + __builtin_ffs((int)DA9062AA_BUCK1_ILIM_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_BUCK1_ILIM_MASK)) - 1), + }, + { + .desc.id = DA9062_ID_BUCK2, + .desc.name = "DA9062 BUCK2", + .desc.of_match = of_match_ptr("buck2"), + .desc.regulators_node = of_match_ptr("regulators"), + .desc.ops = &da9062_buck_ops, + .desc.min_uV = (300) * 1000, + .desc.uV_step = (10) * 1000, + .desc.n_voltages = ((1570) - (300))/(10) + 1, + .current_limits = da9062_buck_a_limits, + .n_current_limits = ARRAY_SIZE(da9062_buck_a_limits), + .desc.enable_reg = DA9062AA_BUCK2_CONT, + .desc.enable_mask = DA9062AA_BUCK2_EN_MASK, + .desc.vsel_reg = DA9062AA_VBUCK2_A, + .desc.vsel_mask = DA9062AA_VBUCK2_A_MASK, + .desc.linear_min_sel = 0, + .sleep = REG_FIELD(DA9062AA_VBUCK2_A, + __builtin_ffs((int)DA9062AA_BUCK2_SL_A_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_BUCK2_SL_A_MASK)) - 1), + .suspend_sleep = REG_FIELD(DA9062AA_VBUCK2_B, + __builtin_ffs((int)DA9062AA_BUCK2_SL_B_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_BUCK2_SL_B_MASK)) - 1), + .suspend_vsel_reg = DA9062AA_VBUCK2_B, + .mode = REG_FIELD(DA9062AA_BUCK2_CFG, + __builtin_ffs((int)DA9062AA_BUCK2_MODE_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_BUCK2_MODE_MASK)) - 1), + .suspend = REG_FIELD(DA9062AA_DVC_1, + __builtin_ffs((int)DA9062AA_VBUCK2_SEL_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_VBUCK2_SEL_MASK)) - 1), + .ilimit = REG_FIELD(DA9062AA_BUCK_ILIM_C, + __builtin_ffs((int)DA9062AA_BUCK2_ILIM_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_BUCK2_ILIM_MASK)) - 1), + }, + { + .desc.id = DA9062_ID_BUCK3, + .desc.name = "DA9062 BUCK3", + .desc.of_match = of_match_ptr("buck3"), + .desc.regulators_node = of_match_ptr("regulators"), + .desc.ops = &da9062_buck_ops, + .desc.min_uV = (800) * 1000, + .desc.uV_step = (20) * 1000, + .desc.n_voltages = ((3340) - (800))/(20) + 1, + .current_limits = da9062_buck_b_limits, + .n_current_limits = ARRAY_SIZE(da9062_buck_b_limits), + .desc.enable_reg = DA9062AA_BUCK3_CONT, + .desc.enable_mask = DA9062AA_BUCK3_EN_MASK, + .desc.vsel_reg = DA9062AA_VBUCK3_A, + .desc.vsel_mask = DA9062AA_VBUCK3_A_MASK, + .desc.linear_min_sel = 0, + .sleep = REG_FIELD(DA9062AA_VBUCK3_A, + __builtin_ffs((int)DA9062AA_BUCK3_SL_A_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_BUCK3_SL_A_MASK)) - 1), + .suspend_sleep = REG_FIELD(DA9062AA_VBUCK3_B, + __builtin_ffs((int)DA9062AA_BUCK3_SL_B_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_BUCK3_SL_B_MASK)) - 1), + .suspend_vsel_reg = DA9062AA_VBUCK3_B, + .mode = REG_FIELD(DA9062AA_BUCK3_CFG, + __builtin_ffs((int)DA9062AA_BUCK3_MODE_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_BUCK3_MODE_MASK)) - 1), + .suspend = REG_FIELD(DA9062AA_DVC_1, + __builtin_ffs((int)DA9062AA_VBUCK3_SEL_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_VBUCK3_SEL_MASK)) - 1), + .ilimit = REG_FIELD(DA9062AA_BUCK_ILIM_A, + __builtin_ffs((int)DA9062AA_BUCK3_ILIM_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_BUCK3_ILIM_MASK)) - 1), + }, + { + .desc.id = DA9062_ID_BUCK4, + .desc.name = "DA9062 BUCK4", + .desc.of_match = of_match_ptr("buck4"), + .desc.regulators_node = of_match_ptr("regulators"), + .desc.ops = &da9062_buck_ops, + .desc.min_uV = (530) * 1000, + .desc.uV_step = (10) * 1000, + .desc.n_voltages = ((1800) - (530))/(10) + 1, + .current_limits = da9062_buck_a_limits, + .n_current_limits = ARRAY_SIZE(da9062_buck_a_limits), + .desc.enable_reg = DA9062AA_BUCK4_CONT, + .desc.enable_mask = DA9062AA_BUCK4_EN_MASK, + .desc.vsel_reg = DA9062AA_VBUCK4_A, + .desc.vsel_mask = DA9062AA_VBUCK4_A_MASK, + .desc.linear_min_sel = 0, + .sleep = REG_FIELD(DA9062AA_VBUCK4_A, + __builtin_ffs((int)DA9062AA_BUCK4_SL_A_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_BUCK4_SL_A_MASK)) - 1), + .suspend_sleep = REG_FIELD(DA9062AA_VBUCK4_B, + __builtin_ffs((int)DA9062AA_BUCK4_SL_B_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_BUCK4_SL_B_MASK)) - 1), + .suspend_vsel_reg = DA9062AA_VBUCK4_B, + .mode = REG_FIELD(DA9062AA_BUCK4_CFG, + __builtin_ffs((int)DA9062AA_BUCK4_MODE_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_BUCK4_MODE_MASK)) - 1), + .suspend = REG_FIELD(DA9062AA_DVC_1, + __builtin_ffs((int)DA9062AA_VBUCK4_SEL_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_VBUCK4_SEL_MASK)) - 1), + .ilimit = REG_FIELD(DA9062AA_BUCK_ILIM_B, + __builtin_ffs((int)DA9062AA_BUCK4_ILIM_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_BUCK4_ILIM_MASK)) - 1), + }, + { + .desc.id = DA9062_ID_LDO1, + .desc.name = "DA9062 LDO1", + .desc.of_match = of_match_ptr("ldo1"), + .desc.regulators_node = of_match_ptr("regulators"), + .desc.ops = &da9062_ldo_ops, + .desc.min_uV = (900) * 1000, + .desc.uV_step = (50) * 1000, + .desc.n_voltages = ((3600) - (900))/(50) + 1, + .desc.enable_reg = DA9062AA_LDO1_CONT, + .desc.enable_mask = DA9062AA_LDO1_EN_MASK, + .desc.vsel_reg = DA9062AA_VLDO1_A, + .desc.vsel_mask = DA9062AA_VLDO1_A_MASK, + .desc.linear_min_sel = 0, + .sleep = REG_FIELD(DA9062AA_VLDO1_A, + __builtin_ffs((int)DA9062AA_LDO1_SL_A_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_LDO1_SL_A_MASK)) - 1), + .suspend_sleep = REG_FIELD(DA9062AA_VLDO1_B, + __builtin_ffs((int)DA9062AA_LDO1_SL_B_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_LDO1_SL_B_MASK)) - 1), + .suspend_vsel_reg = DA9062AA_VLDO1_B, + .suspend = REG_FIELD(DA9062AA_DVC_1, + __builtin_ffs((int)DA9062AA_VLDO1_SEL_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_VLDO1_SEL_MASK)) - 1), + .oc_event = REG_FIELD(DA9062AA_STATUS_D, + __builtin_ffs((int)DA9062AA_LDO1_ILIM_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_LDO1_ILIM_MASK)) - 1), + }, + { + .desc.id = DA9062_ID_LDO2, + .desc.name = "DA9062 LDO2", + .desc.of_match = of_match_ptr("ldo2"), + .desc.regulators_node = of_match_ptr("regulators"), + .desc.ops = &da9062_ldo_ops, + .desc.min_uV = (900) * 1000, + .desc.uV_step = (50) * 1000, + .desc.n_voltages = ((3600) - (600))/(50) + 1, + .desc.enable_reg = DA9062AA_LDO2_CONT, + .desc.enable_mask = DA9062AA_LDO2_EN_MASK, + .desc.vsel_reg = DA9062AA_VLDO2_A, + .desc.vsel_mask = DA9062AA_VLDO2_A_MASK, + .desc.linear_min_sel = 0, + .sleep = REG_FIELD(DA9062AA_VLDO2_A, + __builtin_ffs((int)DA9062AA_LDO2_SL_A_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_LDO2_SL_A_MASK)) - 1), + .suspend_sleep = REG_FIELD(DA9062AA_VLDO2_B, + __builtin_ffs((int)DA9062AA_LDO2_SL_B_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_LDO2_SL_B_MASK)) - 1), + .suspend_vsel_reg = DA9062AA_VLDO2_B, + .suspend = REG_FIELD(DA9062AA_DVC_1, + __builtin_ffs((int)DA9062AA_VLDO2_SEL_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_VLDO2_SEL_MASK)) - 1), + .oc_event = REG_FIELD(DA9062AA_STATUS_D, + __builtin_ffs((int)DA9062AA_LDO2_ILIM_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_LDO2_ILIM_MASK)) - 1), + }, + { + .desc.id = DA9062_ID_LDO3, + .desc.name = "DA9062 LDO3", + .desc.of_match = of_match_ptr("ldo3"), + .desc.regulators_node = of_match_ptr("regulators"), + .desc.ops = &da9062_ldo_ops, + .desc.min_uV = (900) * 1000, + .desc.uV_step = (50) * 1000, + .desc.n_voltages = ((3600) - (900))/(50) + 1, + .desc.enable_reg = DA9062AA_LDO3_CONT, + .desc.enable_mask = DA9062AA_LDO3_EN_MASK, + .desc.vsel_reg = DA9062AA_VLDO3_A, + .desc.vsel_mask = DA9062AA_VLDO3_A_MASK, + .desc.linear_min_sel = 0, + .sleep = REG_FIELD(DA9062AA_VLDO3_A, + __builtin_ffs((int)DA9062AA_LDO3_SL_A_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_LDO3_SL_A_MASK)) - 1), + .suspend_sleep = REG_FIELD(DA9062AA_VLDO3_B, + __builtin_ffs((int)DA9062AA_LDO3_SL_B_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_LDO3_SL_B_MASK)) - 1), + .suspend_vsel_reg = DA9062AA_VLDO3_B, + .suspend = REG_FIELD(DA9062AA_DVC_1, + __builtin_ffs((int)DA9062AA_VLDO3_SEL_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_VLDO3_SEL_MASK)) - 1), + .oc_event = REG_FIELD(DA9062AA_STATUS_D, + __builtin_ffs((int)DA9062AA_LDO3_ILIM_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_LDO3_ILIM_MASK)) - 1), + }, + { + .desc.id = DA9062_ID_LDO4, + .desc.name = "DA9062 LDO4", + .desc.of_match = of_match_ptr("ldo4"), + .desc.regulators_node = of_match_ptr("regulators"), + .desc.ops = &da9062_ldo_ops, + .desc.min_uV = (900) * 1000, + .desc.uV_step = (50) * 1000, + .desc.n_voltages = ((3600) - (900))/(50) + 1, + .desc.enable_reg = DA9062AA_LDO4_CONT, + .desc.enable_mask = DA9062AA_LDO4_EN_MASK, + .desc.vsel_reg = DA9062AA_VLDO4_A, + .desc.vsel_mask = DA9062AA_VLDO4_A_MASK, + .desc.linear_min_sel = 0, + .sleep = REG_FIELD(DA9062AA_VLDO4_A, + __builtin_ffs((int)DA9062AA_LDO4_SL_A_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_LDO4_SL_A_MASK)) - 1), + .suspend_sleep = REG_FIELD(DA9062AA_VLDO4_B, + __builtin_ffs((int)DA9062AA_LDO4_SL_B_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_LDO4_SL_B_MASK)) - 1), + .suspend_vsel_reg = DA9062AA_VLDO4_B, + .suspend = REG_FIELD(DA9062AA_DVC_1, + __builtin_ffs((int)DA9062AA_VLDO4_SEL_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_VLDO4_SEL_MASK)) - 1), + .oc_event = REG_FIELD(DA9062AA_STATUS_D, + __builtin_ffs((int)DA9062AA_LDO4_ILIM_MASK) - 1, + sizeof(unsigned int) * 8 - + __builtin_clz((DA9062AA_LDO4_ILIM_MASK)) - 1), + }, +}; + +/* Regulator interrupt handlers */ +static irqreturn_t da9062_ldo_lim_event(int irq, void *data) +{ + struct da9062_regulators *regulators = data; + struct da9062 *hw = regulators->regulator[0].hw; + struct da9062_regulator *regl; + int handled = IRQ_NONE; + int bits, i, ret; + + ret = regmap_read(hw->regmap, DA9062AA_STATUS_D, &bits); + if (ret < 0) { + dev_err(hw->dev, + "Failed to read LDO overcurrent indicator\n"); + goto ldo_lim_error; + } + + for (i = regulators->n_regulators - 1; i >= 0; i--) { + regl = ®ulators->regulator[i]; + if (regl->info->oc_event.reg != DA9062AA_STATUS_D) + continue; + + if (BIT(regl->info->oc_event.lsb) & bits) { + regulator_notifier_call_chain(regl->rdev, + REGULATOR_EVENT_OVER_CURRENT, NULL); + handled = IRQ_HANDLED; + } + } + +ldo_lim_error: + return handled; +} + +static int da9062_regulator_probe(struct platform_device *pdev) +{ + struct da9062 *chip = dev_get_drvdata(pdev->dev.parent); + struct of_regulator_match *reg_matches = NULL; + struct da9062_regulators *regulators; + struct da9062_regulator *regl; + struct regulator_config config = { }; + int irq, n, ret; + size_t size; + + /* Allocate memory required by usable regulators */ + size = sizeof(struct da9062_regulators) + + DA9062_MAX_REGULATORS * sizeof(struct da9062_regulator); + regulators = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); + if (!regulators) + return -ENOMEM; + + regulators->n_regulators = DA9062_MAX_REGULATORS; + platform_set_drvdata(pdev, regulators); + + n = 0; + while (n < regulators->n_regulators) { + /* Initialise regulator structure */ + regl = ®ulators->regulator[n]; + regl->hw = chip; + regl->info = &local_regulator_info[n]; + regl->desc = regl->info->desc; + regl->desc.type = REGULATOR_VOLTAGE; + regl->desc.owner = THIS_MODULE; + + if (regl->info->mode.reg) + regl->mode = devm_regmap_field_alloc( + &pdev->dev, + chip->regmap, + regl->info->mode); + if (regl->info->suspend.reg) + regl->suspend = devm_regmap_field_alloc( + &pdev->dev, + chip->regmap, + regl->info->suspend); + if (regl->info->sleep.reg) + regl->sleep = devm_regmap_field_alloc( + &pdev->dev, + chip->regmap, + regl->info->sleep); + if (regl->info->suspend_sleep.reg) + regl->suspend_sleep = devm_regmap_field_alloc( + &pdev->dev, + chip->regmap, + regl->info->suspend_sleep); + if (regl->info->ilimit.reg) + regl->ilimit = devm_regmap_field_alloc( + &pdev->dev, + chip->regmap, + regl->info->ilimit); + + /* Register regulator */ + memset(&config, 0, sizeof(config)); + config.dev = chip->dev; + config.driver_data = regl; + config.regmap = chip->regmap; + + regl->rdev = devm_regulator_register(&pdev->dev, ®l->desc, + &config); + if (IS_ERR(regl->rdev)) { + dev_err(&pdev->dev, + "Failed to register %s regulator\n", + regl->desc.name); + return PTR_ERR(regl->rdev); + } + + n++; + } + + /* LDOs overcurrent event support */ + irq = platform_get_irq_byname(pdev, "LDO_LIM"); + if (irq < 0) { + dev_err(&pdev->dev, "Failed to get IRQ.\n"); + return irq; + } + regulators->irq_ldo_lim = irq; + + ret = devm_request_threaded_irq(&pdev->dev, irq, + NULL, da9062_ldo_lim_event, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "LDO_LIM", regulators); + if (ret) { + dev_warn(&pdev->dev, + "Failed to request LDO_LIM IRQ.\n"); + regulators->irq_ldo_lim = -ENXIO; + } + + return 0; +} + +static struct platform_driver da9062_regulator_driver = { + .driver = { + .name = "da9062-regulators", + .owner = THIS_MODULE, + }, + .probe = da9062_regulator_probe, +}; + +static int __init da9062_regulator_init(void) +{ + return platform_driver_register(&da9062_regulator_driver); +} +subsys_initcall(da9062_regulator_init); + +static void __exit da9062_regulator_cleanup(void) +{ + platform_driver_unregister(&da9062_regulator_driver); +} +module_exit(da9062_regulator_cleanup); + +/* Module information */ +MODULE_AUTHOR("S Twiss "); +MODULE_DESCRIPTION("REGULATOR device driver for Dialog DA9062"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform: da9062-regulators"); -- cgit v1.2.3-55-g7522 From ea6254e5c8e54cc43daea4c13b6c66de18b5295b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 25 May 2015 16:32:38 +0800 Subject: regulator: da9062: Fix modalias Remove extra space between platform prefix and driver name in MODULE_ALIAS. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da9062-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c index 9805b6b0bdef..e572a654b272 100644 --- a/drivers/regulator/da9062-regulator.c +++ b/drivers/regulator/da9062-regulator.c @@ -840,4 +840,4 @@ module_exit(da9062_regulator_cleanup); MODULE_AUTHOR("S Twiss "); MODULE_DESCRIPTION("REGULATOR device driver for Dialog DA9062"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform: da9062-regulators"); +MODULE_ALIAS("platform:da9062-regulators"); -- cgit v1.2.3-55-g7522 From 050d0f2de1d3c2034ebf6d66ba30fe97019002f2 Mon Sep 17 00:00:00 2001 From: S Twiss Date: Mon, 1 Jun 2015 14:00:20 +0100 Subject: regulator: da9062: Remove unused variable build warning Remove the unused variable build warning for reg_matches that appears during the compilation of the DA9062 regulator driver. da9062-regulator.c: In function da9062_regulator_probe: da9062-regulator.c:727:29: warning: unused variable reg_matches Signed-off-by: Steve Twiss Signed-off-by: Mark Brown --- drivers/regulator/da9062-regulator.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c index e572a654b272..dd76da09b3c7 100644 --- a/drivers/regulator/da9062-regulator.c +++ b/drivers/regulator/da9062-regulator.c @@ -724,7 +724,6 @@ ldo_lim_error: static int da9062_regulator_probe(struct platform_device *pdev) { struct da9062 *chip = dev_get_drvdata(pdev->dev.parent); - struct of_regulator_match *reg_matches = NULL; struct da9062_regulators *regulators; struct da9062_regulator *regl; struct regulator_config config = { }; -- cgit v1.2.3-55-g7522