diff options
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/Kconfig | 16 | ||||
-rw-r--r-- | drivers/regulator/Makefile | 1 | ||||
-rw-r--r-- | drivers/regulator/lp872x.c | 16 | ||||
-rw-r--r-- | drivers/regulator/ltc3589.c | 3 | ||||
-rw-r--r-- | drivers/regulator/max77693.c | 173 | ||||
-rw-r--r-- | drivers/regulator/max77843.c | 201 | ||||
-rw-r--r-- | drivers/regulator/max8973-regulator.c | 80 |
7 files changed, 246 insertions, 244 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 23496da101de..a7b81f0185b5 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -407,13 +407,13 @@ config REGULATOR_MAX77686 Exynos-4 chips to control VARM and VINT voltages. config REGULATOR_MAX77693 - tristate "Maxim MAX77693 regulator" - depends on MFD_MAX77693 + tristate "Maxim 77693/77843 regulator" + depends on (MFD_MAX77693 || MFD_MAX77843) help - This driver controls a Maxim 77693 regulator via I2C bus. + This driver controls a Maxim 77693/77843 regulators via I2C bus. The regulators include two LDOs, 'SAFEOUT1', 'SAFEOUT2' and one current regulator 'CHARGER'. This is suitable for - Exynos-4x12 chips. + Exynos-4x12 (MAX77693) or Exynos5433 (MAX77843) SoC chips. config REGULATOR_MAX77802 tristate "Maxim 77802 regulator" @@ -424,14 +424,6 @@ config REGULATOR_MAX77802 Exynos5420/Exynos5800 SoCs to control various voltages. It includes support for control of voltage and ramp speed. -config REGULATOR_MAX77843 - tristate "Maxim 77843 regulator" - depends on MFD_MAX77843 - help - This driver controls a Maxim 77843 regulator. - The regulator include two 'SAFEOUT' for USB(Universal Serial Bus) - This is suitable for Exynos5433 SoC chips. - config REGULATOR_MC13XXX_CORE tristate diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 91bf76267404..6429e629dcb6 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -56,7 +56,6 @@ obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o obj-$(CONFIG_REGULATOR_MAX77693) += max77693.o obj-$(CONFIG_REGULATOR_MAX77802) += max77802.o -obj-$(CONFIG_REGULATOR_MAX77843) += max77843.o obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 3de328ab41f3..8702e7384af7 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -849,7 +849,7 @@ static struct lp872x_platform_data pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) - goto out; + return ERR_PTR(-ENOMEM); of_property_read_u8(np, "ti,general-config", &pdata->general_config); if (of_find_property(np, "ti,update-config", NULL)) @@ -857,7 +857,7 @@ static struct lp872x_platform_data pdata->dvs = devm_kzalloc(dev, sizeof(struct lp872x_dvs), GFP_KERNEL); if (!pdata->dvs) - goto out; + return ERR_PTR(-ENOMEM); pdata->dvs->gpio = of_get_named_gpio(np, "ti,dvs-gpio", 0); of_property_read_u8(np, "ti,dvs-vsel", (u8 *)&pdata->dvs->vsel); @@ -903,15 +903,21 @@ static struct lp872x_platform_data static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id) { struct lp872x *lp; + struct lp872x_platform_data *pdata; int ret; const int lp872x_num_regulators[] = { [LP8720] = LP8720_NUM_REGULATORS, [LP8725] = LP8725_NUM_REGULATORS, }; - if (cl->dev.of_node) - cl->dev.platform_data = lp872x_populate_pdata_from_dt(&cl->dev, + if (cl->dev.of_node) { + pdata = lp872x_populate_pdata_from_dt(&cl->dev, (enum lp872x_id)id->driver_data); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + } else { + pdata = dev_get_platdata(&cl->dev); + } lp = devm_kzalloc(&cl->dev, sizeof(struct lp872x), GFP_KERNEL); if (!lp) @@ -927,7 +933,7 @@ static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id) } lp->dev = &cl->dev; - lp->pdata = dev_get_platdata(&cl->dev); + lp->pdata = pdata; lp->chipid = id->driver_data; i2c_set_clientdata(cl, lp); diff --git a/drivers/regulator/ltc3589.c b/drivers/regulator/ltc3589.c index 0ce8e4e0fa73..cc22ac66c8fd 100644 --- a/drivers/regulator/ltc3589.c +++ b/drivers/regulator/ltc3589.c @@ -378,7 +378,7 @@ static bool ltc3589_volatile_reg(struct device *dev, unsigned int reg) return false; } -static struct reg_default ltc3589_reg_defaults[] = { +static const struct reg_default ltc3589_reg_defaults[] = { { LTC3589_SCR1, 0x00 }, { LTC3589_OVEN, 0x00 }, { LTC3589_SCR2, 0x00 }, @@ -552,4 +552,3 @@ module_i2c_driver(ltc3589_driver); MODULE_AUTHOR("Philipp Zabel <p.zabel@pengutronix.de>"); MODULE_DESCRIPTION("Regulator driver for Linear Technology LTC3589(-1,2)"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("i2c:ltc3589"); diff --git a/drivers/regulator/max77693.c b/drivers/regulator/max77693.c index 38722c8311a5..de730fd3f8a5 100644 --- a/drivers/regulator/max77693.c +++ b/drivers/regulator/max77693.c @@ -1,8 +1,9 @@ /* - * max77693.c - Regulator driver for the Maxim 77693 + * max77693.c - Regulator driver for the Maxim 77693 and 77843 * - * Copyright (C) 2013 Samsung Electronics + * Copyright (C) 2013-2015 Samsung Electronics * Jonghwa Lee <jonghwa3.lee@samsung.com> + * Krzysztof Kozlowski <k.kozlowski.k@gmail.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 @@ -29,38 +30,64 @@ #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/mfd/max77693.h> +#include <linux/mfd/max77693-common.h> #include <linux/mfd/max77693-private.h> +#include <linux/mfd/max77843-private.h> #include <linux/regulator/of_regulator.h> #include <linux/regmap.h> -#define CHGIN_ILIM_STEP_20mA 20000 +/* + * ID for MAX77843 regulators. + * There is no need for such for MAX77693. + */ +enum max77843_regulator_type { + MAX77843_SAFEOUT1 = 0, + MAX77843_SAFEOUT2, + MAX77843_CHARGER, + + MAX77843_NUM, +}; + +/* Register differences between chargers: MAX77693 and MAX77843 */ +struct chg_reg_data { + unsigned int linear_reg; + unsigned int linear_mask; + unsigned int uA_step; + unsigned int min_sel; +}; /* - * CHARGER regulator - Min : 20mA, Max : 2580mA, step : 20mA + * MAX77693 CHARGER regulator - Min : 20mA, Max : 2580mA, step : 20mA * 0x00, 0x01, 0x2, 0x03 = 60 mA * 0x04 ~ 0x7E = (60 + (X - 3) * 20) mA + * Actually for MAX77693 the driver manipulates the maximum input current, + * not the fast charge current (output). This should be fixed. + * + * On MAX77843 the calculation formula is the same (except values). + * Fortunately it properly manipulates the fast charge current. */ static int max77693_chg_get_current_limit(struct regulator_dev *rdev) { + const struct chg_reg_data *reg_data = rdev_get_drvdata(rdev); unsigned int chg_min_uA = rdev->constraints->min_uA; unsigned int chg_max_uA = rdev->constraints->max_uA; unsigned int reg, sel; unsigned int val; int ret; - ret = regmap_read(rdev->regmap, MAX77693_CHG_REG_CHG_CNFG_09, ®); + ret = regmap_read(rdev->regmap, reg_data->linear_reg, ®); if (ret < 0) return ret; - sel = reg & CHG_CNFG_09_CHGIN_ILIM_MASK; + sel = reg & reg_data->linear_mask; /* the first four codes for charger current are all 60mA */ - if (sel <= 3) + if (sel <= reg_data->min_sel) sel = 0; else - sel -= 3; + sel -= reg_data->min_sel; - val = chg_min_uA + CHGIN_ILIM_STEP_20mA * sel; + val = chg_min_uA + reg_data->uA_step * sel; if (val > chg_max_uA) return -EINVAL; @@ -70,23 +97,43 @@ static int max77693_chg_get_current_limit(struct regulator_dev *rdev) static int max77693_chg_set_current_limit(struct regulator_dev *rdev, int min_uA, int max_uA) { + const struct chg_reg_data *reg_data = rdev_get_drvdata(rdev); unsigned int chg_min_uA = rdev->constraints->min_uA; int sel = 0; - while (chg_min_uA + CHGIN_ILIM_STEP_20mA * sel < min_uA) + while (chg_min_uA + reg_data->uA_step * sel < min_uA) sel++; - if (chg_min_uA + CHGIN_ILIM_STEP_20mA * sel > max_uA) + if (chg_min_uA + reg_data->uA_step * sel > max_uA) return -EINVAL; /* the first four codes for charger current are all 60mA */ - sel += 3; + sel += reg_data->min_sel; - return regmap_write(rdev->regmap, - MAX77693_CHG_REG_CHG_CNFG_09, sel); + return regmap_write(rdev->regmap, reg_data->linear_reg, sel); } /* end of CHARGER regulator ops */ +/* Returns regmap suitable for given regulator on chosen device */ +static struct regmap *max77693_get_regmap(enum max77693_types type, + struct max77693_dev *max77693, + int reg_id) +{ + if (type == TYPE_MAX77693) + return max77693->regmap; + + /* Else: TYPE_MAX77843 */ + switch (reg_id) { + case MAX77843_SAFEOUT1: + case MAX77843_SAFEOUT2: + return max77693->regmap; + case MAX77843_CHARGER: + return max77693->regmap_chg; + default: + return max77693->regmap; + } +} + static const unsigned int max77693_safeout_table[] = { 4850000, 4900000, @@ -111,7 +158,7 @@ static struct regulator_ops max77693_charger_ops = { .set_current_limit = max77693_chg_set_current_limit, }; -#define regulator_desc_esafeout(_num) { \ +#define max77693_regulator_desc_esafeout(_num) { \ .name = "ESAFEOUT"#_num, \ .id = MAX77693_ESAFEOUT##_num, \ .of_match = of_match_ptr("ESAFEOUT"#_num), \ @@ -127,9 +174,9 @@ static struct regulator_ops max77693_charger_ops = { .enable_mask = SAFEOUT_CTRL_ENSAFEOUT##_num##_MASK , \ } -static const struct regulator_desc regulators[] = { - regulator_desc_esafeout(1), - regulator_desc_esafeout(2), +static const struct regulator_desc max77693_supported_regulators[] = { + max77693_regulator_desc_esafeout(1), + max77693_regulator_desc_esafeout(2), { .name = "CHARGER", .id = MAX77693_CHARGER, @@ -145,18 +192,86 @@ static const struct regulator_desc regulators[] = { }, }; +static const struct chg_reg_data max77693_chg_reg_data = { + .linear_reg = MAX77693_CHG_REG_CHG_CNFG_09, + .linear_mask = CHG_CNFG_09_CHGIN_ILIM_MASK, + .uA_step = 20000, + .min_sel = 3, +}; + +#define max77843_regulator_desc_esafeout(num) { \ + .name = "SAFEOUT" # num, \ + .id = MAX77843_SAFEOUT ## num, \ + .ops = &max77693_safeout_ops, \ + .of_match = of_match_ptr("SAFEOUT" # num), \ + .regulators_node = of_match_ptr("regulators"), \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(max77693_safeout_table), \ + .volt_table = max77693_safeout_table, \ + .enable_reg = MAX77843_SYS_REG_SAFEOUTCTRL, \ + .enable_mask = MAX77843_REG_SAFEOUTCTRL_ENSAFEOUT ## num, \ + .vsel_reg = MAX77843_SYS_REG_SAFEOUTCTRL, \ + .vsel_mask = MAX77843_REG_SAFEOUTCTRL_SAFEOUT ## num ## _MASK, \ +} + +static const struct regulator_desc max77843_supported_regulators[] = { + [MAX77843_SAFEOUT1] = max77843_regulator_desc_esafeout(1), + [MAX77843_SAFEOUT2] = max77843_regulator_desc_esafeout(2), + [MAX77843_CHARGER] = { + .name = "CHARGER", + .id = MAX77843_CHARGER, + .ops = &max77693_charger_ops, + .of_match = of_match_ptr("CHARGER"), + .regulators_node = of_match_ptr("regulators"), + .type = REGULATOR_CURRENT, + .owner = THIS_MODULE, + .enable_reg = MAX77843_CHG_REG_CHG_CNFG_00, + .enable_mask = MAX77843_CHG_MASK, + .enable_val = MAX77843_CHG_MASK, + }, +}; + +static const struct chg_reg_data max77843_chg_reg_data = { + .linear_reg = MAX77843_CHG_REG_CHG_CNFG_02, + .linear_mask = MAX77843_CHG_FAST_CHG_CURRENT_MASK, + .uA_step = MAX77843_CHG_FAST_CHG_CURRENT_STEP, + .min_sel = 2, +}; + static int max77693_pmic_probe(struct platform_device *pdev) { + enum max77693_types type = platform_get_device_id(pdev)->driver_data; struct max77693_dev *iodev = dev_get_drvdata(pdev->dev.parent); + const struct regulator_desc *regulators; + unsigned int regulators_size; int i; struct regulator_config config = { }; config.dev = iodev->dev; - config.regmap = iodev->regmap; - for (i = 0; i < ARRAY_SIZE(regulators); i++) { + switch (type) { + case TYPE_MAX77693: + regulators = max77693_supported_regulators; + regulators_size = ARRAY_SIZE(max77693_supported_regulators); + config.driver_data = (void *)&max77693_chg_reg_data; + break; + case TYPE_MAX77843: + regulators = max77843_supported_regulators; + regulators_size = ARRAY_SIZE(max77843_supported_regulators); + config.driver_data = (void *)&max77843_chg_reg_data; + break; + default: + dev_err(&pdev->dev, "Unsupported device type: %u\n", type); + return -ENODEV; + } + + for (i = 0; i < regulators_size; i++) { struct regulator_dev *rdev; + config.regmap = max77693_get_regmap(type, iodev, + regulators[i].id); + rdev = devm_regulator_register(&pdev->dev, ®ulators[i], &config); if (IS_ERR(rdev)) { @@ -170,7 +285,8 @@ static int max77693_pmic_probe(struct platform_device *pdev) } static const struct platform_device_id max77693_pmic_id[] = { - {"max77693-pmic", 0}, + { "max77693-pmic", TYPE_MAX77693 }, + { "max77843-regulator", TYPE_MAX77843 }, {}, }; @@ -184,8 +300,19 @@ static struct platform_driver max77693_pmic_driver = { .id_table = max77693_pmic_id, }; -module_platform_driver(max77693_pmic_driver); +static int __init max77693_pmic_init(void) +{ + return platform_driver_register(&max77693_pmic_driver); +} +subsys_initcall(max77693_pmic_init); + +static void __exit max77693_pmic_cleanup(void) +{ + platform_driver_unregister(&max77693_pmic_driver); +} +module_exit(max77693_pmic_cleanup); -MODULE_DESCRIPTION("MAXIM MAX77693 regulator driver"); +MODULE_DESCRIPTION("MAXIM 77693/77843 regulator driver"); MODULE_AUTHOR("Jonghwa Lee <jonghwa3.lee@samsung.com>"); +MODULE_AUTHOR("Krzysztof Kozlowski <k.kozlowski.k@gmail.com>"); MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/max77843.c b/drivers/regulator/max77843.c deleted file mode 100644 index f4fd0d3cfa6e..000000000000 --- a/drivers/regulator/max77843.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * max77843.c - Regulator driver for the Maxim MAX77843 - * - * Copyright (C) 2015 Samsung Electronics - * Author: Jaewon Kim <jaewon02.kim@samsung.com> - * Author: Beomho Seo <beomho.seo@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. - */ - -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/regulator/driver.h> -#include <linux/regulator/machine.h> -#include <linux/mfd/max77843-private.h> -#include <linux/regulator/of_regulator.h> - -enum max77843_regulator_type { - MAX77843_SAFEOUT1 = 0, - MAX77843_SAFEOUT2, - MAX77843_CHARGER, - - MAX77843_NUM, -}; - -static const unsigned int max77843_safeout_voltage_table[] = { - 4850000, - 4900000, - 4950000, - 3300000, -}; - -static int max77843_reg_get_current_limit(struct regulator_dev *rdev) -{ - struct regmap *regmap = rdev->regmap; - unsigned int chg_min_uA = rdev->constraints->min_uA; - unsigned int chg_max_uA = rdev->constraints->max_uA; - unsigned int val; - int ret; - unsigned int reg, sel; - - ret = regmap_read(regmap, MAX77843_CHG_REG_CHG_CNFG_02, ®); - if (ret) { - dev_err(&rdev->dev, "Failed to read charger register\n"); - return ret; - } - - sel = reg & MAX77843_CHG_FAST_CHG_CURRENT_MASK; - - if (sel < 0x03) - sel = 0; - else - sel -= 2; - - val = chg_min_uA + MAX77843_CHG_FAST_CHG_CURRENT_STEP * sel; - if (val > chg_max_uA) - return -EINVAL; - - return val; -} - -static int max77843_reg_set_current_limit(struct regulator_dev *rdev, - int min_uA, int max_uA) -{ - struct regmap *regmap = rdev->regmap; - unsigned int chg_min_uA = rdev->constraints->min_uA; - int sel = 0; - - while (chg_min_uA + MAX77843_CHG_FAST_CHG_CURRENT_STEP * sel < min_uA) - sel++; - - if (chg_min_uA + MAX77843_CHG_FAST_CHG_CURRENT_STEP * sel > max_uA) - return -EINVAL; - - sel += 2; - - return regmap_write(regmap, MAX77843_CHG_REG_CHG_CNFG_02, sel); -} - -static struct regulator_ops max77843_charger_ops = { - .is_enabled = regulator_is_enabled_regmap, - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .get_current_limit = max77843_reg_get_current_limit, - .set_current_limit = max77843_reg_set_current_limit, -}; - -static struct regulator_ops max77843_regulator_ops = { - .is_enabled = regulator_is_enabled_regmap, - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .list_voltage = regulator_list_voltage_table, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = regulator_set_voltage_sel_regmap, -}; - -#define MAX77843_SAFEOUT(num) { \ - .name = "SAFEOUT" # num, \ - .id = MAX77843_SAFEOUT ## num, \ - .ops = &max77843_regulator_ops, \ - .of_match = of_match_ptr("SAFEOUT" # num), \ - .regulators_node = of_match_ptr("regulators"), \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .n_voltages = ARRAY_SIZE(max77843_safeout_voltage_table), \ - .volt_table = max77843_safeout_voltage_table, \ - .enable_reg = MAX77843_SYS_REG_SAFEOUTCTRL, \ - .enable_mask = MAX77843_REG_SAFEOUTCTRL_ENSAFEOUT ## num, \ - .vsel_reg = MAX77843_SYS_REG_SAFEOUTCTRL, \ - .vsel_mask = MAX77843_REG_SAFEOUTCTRL_SAFEOUT ## num ## _MASK, \ -} - -static const struct regulator_desc max77843_supported_regulators[] = { - [MAX77843_SAFEOUT1] = MAX77843_SAFEOUT(1), - [MAX77843_SAFEOUT2] = MAX77843_SAFEOUT(2), - [MAX77843_CHARGER] = { - .name = "CHARGER", - .id = MAX77843_CHARGER, - .ops = &max77843_charger_ops, - .of_match = of_match_ptr("CHARGER"), - .regulators_node = of_match_ptr("regulators"), - .type = REGULATOR_CURRENT, - .owner = THIS_MODULE, - .enable_reg = MAX77843_CHG_REG_CHG_CNFG_00, - .enable_mask = MAX77843_CHG_MASK | MAX77843_CHG_BUCK_MASK, - .enable_val = MAX77843_CHG_MASK | MAX77843_CHG_BUCK_MASK, - }, -}; - -static struct regmap *max77843_get_regmap(struct max77843 *max77843, int reg_id) -{ - switch (reg_id) { - case MAX77843_SAFEOUT1: - case MAX77843_SAFEOUT2: - return max77843->regmap; - case MAX77843_CHARGER: - return max77843->regmap_chg; - default: - return max77843->regmap; - } -} - -static int max77843_regulator_probe(struct platform_device *pdev) -{ - struct max77843 *max77843 = dev_get_drvdata(pdev->dev.parent); - struct regulator_config config = {}; - int i; - - config.dev = max77843->dev; - config.driver_data = max77843; - - for (i = 0; i < ARRAY_SIZE(max77843_supported_regulators); i++) { - struct regulator_dev *regulator; - - config.regmap = max77843_get_regmap(max77843, - max77843_supported_regulators[i].id); - - regulator = devm_regulator_register(&pdev->dev, - &max77843_supported_regulators[i], &config); - if (IS_ERR(regulator)) { - dev_err(&pdev->dev, - "Failed to regiser regulator-%d\n", i); - return PTR_ERR(regulator); - } - } - - return 0; -} - -static const struct platform_device_id max77843_regulator_id[] = { - { "max77843-regulator", }, - { /* sentinel */ }, -}; - -static struct platform_driver max77843_regulator_driver = { - .driver = { - .name = "max77843-regulator", - }, - .probe = max77843_regulator_probe, - .id_table = max77843_regulator_id, -}; - -static int __init max77843_regulator_init(void) -{ - return platform_driver_register(&max77843_regulator_driver); -} -subsys_initcall(max77843_regulator_init); - -static void __exit max77843_regulator_exit(void) -{ - platform_driver_unregister(&max77843_regulator_driver); -} -module_exit(max77843_regulator_exit); - -MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>"); -MODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>"); -MODULE_DESCRIPTION("Maxim MAX77843 regulator driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c index e94ddcf97722..8857cc02d9a8 100644 --- a/drivers/regulator/max8973-regulator.c +++ b/drivers/regulator/max8973-regulator.c @@ -75,6 +75,7 @@ #define MAX8973_DISCH_ENBABLE BIT(5) #define MAX8973_FT_ENABLE BIT(4) +#define MAX8973_CKKADV_TRIP_MASK 0xC #define MAX8973_CKKADV_TRIP_DISABLE 0xC #define MAX8973_CKKADV_TRIP_75mV_PER_US 0x0 #define MAX8973_CKKADV_TRIP_150mV_PER_US 0x4 @@ -282,6 +283,55 @@ static int max8973_set_ramp_delay(struct regulator_dev *rdev, return ret; } +static int max8973_set_current_limit(struct regulator_dev *rdev, + int min_ua, int max_ua) +{ + struct max8973_chip *max = rdev_get_drvdata(rdev); + unsigned int val; + int ret; + + if (max_ua <= 9000000) + val = MAX8973_CKKADV_TRIP_75mV_PER_US; + else if (max_ua <= 12000000) + val = MAX8973_CKKADV_TRIP_150mV_PER_US; + else + val = MAX8973_CKKADV_TRIP_DISABLE; + + ret = regmap_update_bits(max->regmap, MAX8973_CONTROL2, + MAX8973_CKKADV_TRIP_MASK, val); + if (ret < 0) { + dev_err(max->dev, "register %d update failed: %d\n", + MAX8973_CONTROL2, ret); + return ret; + } + return 0; +} + +static int max8973_get_current_limit(struct regulator_dev *rdev) +{ + struct max8973_chip *max = rdev_get_drvdata(rdev); + unsigned int control2; + int ret; + + ret = regmap_read(max->regmap, MAX8973_CONTROL2, &control2); + if (ret < 0) { + dev_err(max->dev, "register %d read failed: %d\n", + MAX8973_CONTROL2, ret); + return ret; + } + switch (control2 & MAX8973_CKKADV_TRIP_MASK) { + case MAX8973_CKKADV_TRIP_DISABLE: + return 15000000; + case MAX8973_CKKADV_TRIP_150mV_PER_US: + return 12000000; + case MAX8973_CKKADV_TRIP_75mV_PER_US: + return 9000000; + default: + break; + } + return 9000000; +} + static const struct regulator_ops max8973_dcdc_ops = { .get_voltage_sel = max8973_dcdc_get_voltage_sel, .set_voltage_sel = max8973_dcdc_set_voltage_sel, @@ -421,6 +471,8 @@ static struct max8973_regulator_platform_data *max8973_parse_dt( struct device_node *np = dev->of_node; int ret; u32 pval; + bool etr_enable; + bool etr_sensitivity_high; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) @@ -452,6 +504,23 @@ static struct max8973_regulator_platform_data *max8973_parse_dt( if (of_property_read_bool(np, "maxim,enable-bias-control")) pdata->control_flags |= MAX8973_CONTROL_BIAS_ENABLE; + etr_enable = of_property_read_bool(np, "maxim,enable-etr"); + etr_sensitivity_high = of_property_read_bool(np, + "maxim,enable-high-etr-sensitivity"); + if (etr_sensitivity_high) + etr_enable = true; + + if (etr_enable) { + if (etr_sensitivity_high) + pdata->control_flags |= + MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US; + else + pdata->control_flags |= + MAX8973_CONTROL_CLKADV_TRIP_150mV_PER_US; + } else { + pdata->control_flags |= MAX8973_CONTROL_CLKADV_TRIP_DISABLED; + } + return pdata; } @@ -568,6 +637,15 @@ static int max8973_probe(struct i2c_client *client, max->lru_index[i] = i; max->lru_index[0] = max->curr_vout_reg; max->lru_index[max->curr_vout_reg] = 0; + } else { + /* + * If there is no DVS GPIO, the VOUT register + * address is fixed. + */ + max->ops.set_voltage_sel = regulator_set_voltage_sel_regmap; + max->ops.get_voltage_sel = regulator_get_voltage_sel_regmap; + max->desc.vsel_reg = max->curr_vout_reg; + max->desc.vsel_mask = MAX8973_VOUT_MASK; } if (pdata_from_dt) @@ -613,6 +691,8 @@ static int max8973_probe(struct i2c_client *client, max->ops.enable = regulator_enable_regmap; max->ops.disable = regulator_disable_regmap; max->ops.is_enabled = regulator_is_enabled_regmap; + max->ops.set_current_limit = max8973_set_current_limit; + max->ops.get_current_limit = max8973_get_current_limit; break; default: break; |