diff options
-rw-r--r-- | Documentation/devicetree/bindings/regulator/max8973-regulator.txt | 20 | ||||
-rw-r--r-- | drivers/regulator/lp8755.c | 23 | ||||
-rw-r--r-- | drivers/regulator/max14577.c | 128 | ||||
-rw-r--r-- | drivers/regulator/max77693.c | 17 | ||||
-rw-r--r-- | drivers/regulator/max77843.c | 68 | ||||
-rw-r--r-- | drivers/regulator/max8973-regulator.c | 269 | ||||
-rw-r--r-- | include/linux/regulator/max8973-regulator.h | 4 |
7 files changed, 320 insertions, 209 deletions
diff --git a/Documentation/devicetree/bindings/regulator/max8973-regulator.txt b/Documentation/devicetree/bindings/regulator/max8973-regulator.txt index 4f15d8a1bfd0..55efb24e5683 100644 --- a/Documentation/devicetree/bindings/regulator/max8973-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/max8973-regulator.txt @@ -2,12 +2,30 @@ Required properties: -- compatible: must be "maxim,max8973" +- compatible: must be one of following: + "maxim,max8973" + "maxim,max77621". - reg: the i2c slave address of the regulator. It should be 0x1b. Any standard regulator properties can be used to configure the single max8973 DCDC. +Optional properties: + +-maxim,externally-enable: boolean, externally control the regulator output + enable/disable. +-maxim,enable-gpio: GPIO for enable control. If the valid GPIO is provided + then externally enable control will be considered. +-maxim,dvs-gpio: GPIO which is connected to DVS pin of device. +-maxim,dvs-default-state: Default state of GPIO during initialisation. + 1 for HIGH and 0 for LOW. +-maxim,enable-remote-sense: boolean, enable reote sense. +-maxim,enable-falling-slew-rate: boolean, enable falling slew rate. +-maxim,enable-active-discharge: boolean: enable active discharge. +-maxim,enable-frequency-shift: boolean, enable 9% frequency shift. +-maxim,enable-bias-control: boolean, enable bias control. By enabling this + startup delay can be reduce to 20us from 220us. + Example: max8973@1b { diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c index 4a415d4ee463..d6773da925ba 100644 --- a/drivers/regulator/lp8755.c +++ b/drivers/regulator/lp8755.c @@ -419,20 +419,16 @@ static int lp8755_int_config(struct lp8755_chip *pchip) } ret = lp8755_read(pchip, 0x0F, ®val); - if (ret < 0) - goto err_i2c; - pchip->irqmask = regval; - ret = request_threaded_irq(pchip->irq, NULL, lp8755_irq_handler, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "lp8755-irq", pchip); - if (ret) + if (ret < 0) { + dev_err(pchip->dev, "i2c acceess error %s\n", __func__); return ret; + } - return ret; - -err_i2c: - dev_err(pchip->dev, "i2c acceess error %s\n", __func__); - return ret; + pchip->irqmask = regval; + return devm_request_threaded_irq(pchip->dev, pchip->irq, NULL, + lp8755_irq_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "lp8755-irq", pchip); } static const struct regmap_config lp8755_regmap = { @@ -514,9 +510,6 @@ static int lp8755_remove(struct i2c_client *client) for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) lp8755_write(pchip, icnt, 0x00); - if (pchip->irq != 0) - free_irq(pchip->irq, pchip); - return 0; } diff --git a/drivers/regulator/max14577.c b/drivers/regulator/max14577.c index b3678d289619..b2daa6641417 100644 --- a/drivers/regulator/max14577.c +++ b/drivers/regulator/max14577.c @@ -100,31 +100,34 @@ static struct regulator_ops max14577_charger_ops = { .set_current_limit = max14577_reg_set_current_limit, }; +#define MAX14577_SAFEOUT_REG { \ + .name = "SAFEOUT", \ + .of_match = of_match_ptr("SAFEOUT"), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = MAX14577_SAFEOUT, \ + .ops = &max14577_safeout_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .n_voltages = 1, \ + .min_uV = MAX14577_REGULATOR_SAFEOUT_VOLTAGE, \ + .enable_reg = MAX14577_REG_CONTROL2, \ + .enable_mask = CTRL2_SFOUTORD_MASK, \ +} +#define MAX14577_CHARGER_REG { \ + .name = "CHARGER", \ + .of_match = of_match_ptr("CHARGER"), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = MAX14577_CHARGER, \ + .ops = &max14577_charger_ops, \ + .type = REGULATOR_CURRENT, \ + .owner = THIS_MODULE, \ + .enable_reg = MAX14577_CHG_REG_CHG_CTRL2, \ + .enable_mask = CHGCTRL2_MBCHOSTEN_MASK, \ +} + static const struct regulator_desc max14577_supported_regulators[] = { - [MAX14577_SAFEOUT] = { - .name = "SAFEOUT", - .of_match = of_match_ptr("SAFEOUT"), - .regulators_node = of_match_ptr("regulators"), - .id = MAX14577_SAFEOUT, - .ops = &max14577_safeout_ops, - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - .n_voltages = 1, - .min_uV = MAX14577_REGULATOR_SAFEOUT_VOLTAGE, - .enable_reg = MAX14577_REG_CONTROL2, - .enable_mask = CTRL2_SFOUTORD_MASK, - }, - [MAX14577_CHARGER] = { - .name = "CHARGER", - .of_match = of_match_ptr("CHARGER"), - .regulators_node = of_match_ptr("regulators"), - .id = MAX14577_CHARGER, - .ops = &max14577_charger_ops, - .type = REGULATOR_CURRENT, - .owner = THIS_MODULE, - .enable_reg = MAX14577_CHG_REG_CHG_CTRL2, - .enable_mask = CHGCTRL2_MBCHOSTEN_MASK, - }, + [MAX14577_SAFEOUT] = MAX14577_SAFEOUT_REG, + [MAX14577_CHARGER] = MAX14577_CHARGER_REG, }; static struct regulator_ops max77836_ldo_ops = { @@ -138,63 +141,28 @@ static struct regulator_ops max77836_ldo_ops = { /* TODO: add .set_suspend_mode */ }; +#define MAX77836_LDO_REG(num) { \ + .name = "LDO" # num, \ + .of_match = of_match_ptr("LDO" # num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = MAX77836_LDO ## num, \ + .ops = &max77836_ldo_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .n_voltages = MAX77836_REGULATOR_LDO_VOLTAGE_STEPS_NUM, \ + .min_uV = MAX77836_REGULATOR_LDO_VOLTAGE_MIN, \ + .uV_step = MAX77836_REGULATOR_LDO_VOLTAGE_STEP, \ + .enable_reg = MAX77836_LDO_REG_CNFG1_LDO ## num, \ + .enable_mask = MAX77836_CNFG1_LDO_PWRMD_MASK, \ + .vsel_reg = MAX77836_LDO_REG_CNFG1_LDO ## num, \ + .vsel_mask = MAX77836_CNFG1_LDO_TV_MASK, \ +} + static const struct regulator_desc max77836_supported_regulators[] = { - [MAX14577_SAFEOUT] = { - .name = "SAFEOUT", - .of_match = of_match_ptr("SAFEOUT"), - .regulators_node = of_match_ptr("regulators"), - .id = MAX14577_SAFEOUT, - .ops = &max14577_safeout_ops, - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - .n_voltages = 1, - .min_uV = MAX14577_REGULATOR_SAFEOUT_VOLTAGE, - .enable_reg = MAX14577_REG_CONTROL2, - .enable_mask = CTRL2_SFOUTORD_MASK, - }, - [MAX14577_CHARGER] = { - .name = "CHARGER", - .of_match = of_match_ptr("CHARGER"), - .regulators_node = of_match_ptr("regulators"), - .id = MAX14577_CHARGER, - .ops = &max14577_charger_ops, - .type = REGULATOR_CURRENT, - .owner = THIS_MODULE, - .enable_reg = MAX14577_CHG_REG_CHG_CTRL2, - .enable_mask = CHGCTRL2_MBCHOSTEN_MASK, - }, - [MAX77836_LDO1] = { - .name = "LDO1", - .of_match = of_match_ptr("LDO1"), - .regulators_node = of_match_ptr("regulators"), - .id = MAX77836_LDO1, - .ops = &max77836_ldo_ops, - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - .n_voltages = MAX77836_REGULATOR_LDO_VOLTAGE_STEPS_NUM, - .min_uV = MAX77836_REGULATOR_LDO_VOLTAGE_MIN, - .uV_step = MAX77836_REGULATOR_LDO_VOLTAGE_STEP, - .enable_reg = MAX77836_LDO_REG_CNFG1_LDO1, - .enable_mask = MAX77836_CNFG1_LDO_PWRMD_MASK, - .vsel_reg = MAX77836_LDO_REG_CNFG1_LDO1, - .vsel_mask = MAX77836_CNFG1_LDO_TV_MASK, - }, - [MAX77836_LDO2] = { - .name = "LDO2", - .of_match = of_match_ptr("LDO2"), - .regulators_node = of_match_ptr("regulators"), - .id = MAX77836_LDO2, - .ops = &max77836_ldo_ops, - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - .n_voltages = MAX77836_REGULATOR_LDO_VOLTAGE_STEPS_NUM, - .min_uV = MAX77836_REGULATOR_LDO_VOLTAGE_MIN, - .uV_step = MAX77836_REGULATOR_LDO_VOLTAGE_STEP, - .enable_reg = MAX77836_LDO_REG_CNFG1_LDO2, - .enable_mask = MAX77836_CNFG1_LDO_PWRMD_MASK, - .vsel_reg = MAX77836_LDO_REG_CNFG1_LDO2, - .vsel_mask = MAX77836_CNFG1_LDO_TV_MASK, - }, + [MAX14577_SAFEOUT] = MAX14577_SAFEOUT_REG, + [MAX14577_CHARGER] = MAX14577_CHARGER_REG, + [MAX77836_LDO1] = MAX77836_LDO_REG(1), + [MAX77836_LDO2] = MAX77836_LDO_REG(2), }; #ifdef CONFIG_OF diff --git a/drivers/regulator/max77693.c b/drivers/regulator/max77693.c index 9665a488e2f1..38722c8311a5 100644 --- a/drivers/regulator/max77693.c +++ b/drivers/regulator/max77693.c @@ -35,20 +35,6 @@ #define CHGIN_ILIM_STEP_20mA 20000 -/* CHARGER regulator ops */ -/* CHARGER regulator uses two bits for enabling */ -static int max77693_chg_is_enabled(struct regulator_dev *rdev) -{ - int ret; - unsigned int val; - - ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); - if (ret) - return ret; - - return (val & rdev->desc->enable_mask) == rdev->desc->enable_mask; -} - /* * CHARGER regulator - Min : 20mA, Max : 2580mA, step : 20mA * 0x00, 0x01, 0x2, 0x03 = 60 mA @@ -118,7 +104,7 @@ static struct regulator_ops max77693_safeout_ops = { }; static struct regulator_ops max77693_charger_ops = { - .is_enabled = max77693_chg_is_enabled, + .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .get_current_limit = max77693_chg_get_current_limit, @@ -155,6 +141,7 @@ static const struct regulator_desc regulators[] = { .enable_reg = MAX77693_CHG_REG_CHG_CNFG_00, .enable_mask = CHG_CNFG_00_CHG_MASK | CHG_CNFG_00_BUCK_MASK, + .enable_val = CHG_CNFG_00_CHG_MASK | CHG_CNFG_00_BUCK_MASK, }, }; diff --git a/drivers/regulator/max77843.c b/drivers/regulator/max77843.c index c132ef527cdd..f4fd0d3cfa6e 100644 --- a/drivers/regulator/max77843.c +++ b/drivers/regulator/max77843.c @@ -33,21 +33,6 @@ static const unsigned int max77843_safeout_voltage_table[] = { 3300000, }; -static int max77843_reg_is_enabled(struct regulator_dev *rdev) -{ - struct regmap *regmap = rdev->regmap; - int ret; - unsigned int reg; - - ret = regmap_read(regmap, rdev->desc->enable_reg, ®); - if (ret) { - dev_err(&rdev->dev, "Fialed to read charger register\n"); - return ret; - } - - return (reg & rdev->desc->enable_mask) == rdev->desc->enable_mask; -} - static int max77843_reg_get_current_limit(struct regulator_dev *rdev) { struct regmap *regmap = rdev->regmap; @@ -96,7 +81,7 @@ static int max77843_reg_set_current_limit(struct regulator_dev *rdev, } static struct regulator_ops max77843_charger_ops = { - .is_enabled = max77843_reg_is_enabled, + .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .get_current_limit = max77843_reg_get_current_limit, @@ -112,37 +97,25 @@ static struct regulator_ops max77843_regulator_ops = { .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] = { - .name = "SAFEOUT1", - .id = MAX77843_SAFEOUT1, - .ops = &max77843_regulator_ops, - .of_match = of_match_ptr("SAFEOUT1"), - .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_ENSAFEOUT1, - .vsel_reg = MAX77843_SYS_REG_SAFEOUTCTRL, - .vsel_mask = MAX77843_REG_SAFEOUTCTRL_SAFEOUT1_MASK, - }, - [MAX77843_SAFEOUT2] = { - .name = "SAFEOUT2", - .id = MAX77843_SAFEOUT2, - .ops = &max77843_regulator_ops, - .of_match = of_match_ptr("SAFEOUT2"), - .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_ENSAFEOUT2, - .vsel_reg = MAX77843_SYS_REG_SAFEOUTCTRL, - .vsel_mask = MAX77843_REG_SAFEOUTCTRL_SAFEOUT2_MASK, - }, + [MAX77843_SAFEOUT1] = MAX77843_SAFEOUT(1), + [MAX77843_SAFEOUT2] = MAX77843_SAFEOUT(2), [MAX77843_CHARGER] = { .name = "CHARGER", .id = MAX77843_CHARGER, @@ -152,7 +125,8 @@ static const struct regulator_desc max77843_supported_regulators[] = { .type = REGULATOR_CURRENT, .owner = THIS_MODULE, .enable_reg = MAX77843_CHG_REG_CHG_CNFG_00, - .enable_mask = MAX77843_CHG_MASK, + .enable_mask = MAX77843_CHG_MASK | MAX77843_CHG_BUCK_MASK, + .enable_val = MAX77843_CHG_MASK | MAX77843_CHG_BUCK_MASK, }, }; diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c index c3d55c2db593..6f2bdad8b4d8 100644 --- a/drivers/regulator/max8973-regulator.c +++ b/drivers/regulator/max8973-regulator.c @@ -27,12 +27,14 @@ #include <linux/init.h> #include <linux/err.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/max8973-regulator.h> #include <linux/regulator/of_regulator.h> #include <linux/gpio.h> +#include <linux/of_gpio.h> #include <linux/i2c.h> #include <linux/slab.h> #include <linux/regmap.h> @@ -66,6 +68,7 @@ #define MAX8973_RAMP_25mV_PER_US 0x1 #define MAX8973_RAMP_50mV_PER_US 0x2 #define MAX8973_RAMP_200mV_PER_US 0x3 +#define MAX8973_RAMP_MASK 0x3 /* MAX8973_CONTROL2 */ #define MAX8973_WDTMR_ENABLE BIT(6) @@ -89,19 +92,25 @@ #define MAX8973_VOLATGE_STEP 6250 #define MAX8973_BUCK_N_VOLTAGE 0x80 +enum device_id { + MAX8973, + MAX77621 +}; + /* Maxim 8973 chip information */ struct max8973_chip { struct device *dev; struct regulator_desc desc; struct regmap *regmap; bool enable_external_control; + int enable_gpio; int dvs_gpio; int lru_index[MAX8973_MAX_VOUT_REG]; int curr_vout_val[MAX8973_MAX_VOUT_REG]; int curr_vout_reg; int curr_gpio_val; - bool valid_dvs_gpio; struct regulator_ops ops; + enum device_id id; }; /* @@ -174,7 +183,7 @@ static int max8973_dcdc_set_voltage_sel(struct regulator_dev *rdev, * If gpios are available to select the VOUT register then least * recently used register for new configuration. */ - if (max->valid_dvs_gpio) + if (gpio_is_valid(max->dvs_gpio)) found = find_voltage_set_register(max, vsel, &vout_reg, &gpio_val); @@ -191,7 +200,7 @@ static int max8973_dcdc_set_voltage_sel(struct regulator_dev *rdev, } /* Select proper VOUT register vio gpios */ - if (max->valid_dvs_gpio) { + if (gpio_is_valid(max->dvs_gpio)) { gpio_set_value_cansleep(max->dvs_gpio, gpio_val & 0x1); max->curr_gpio_val = gpio_val; } @@ -242,12 +251,45 @@ static unsigned int max8973_dcdc_get_mode(struct regulator_dev *rdev) REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; } +static int max8973_set_ramp_delay(struct regulator_dev *rdev, + int ramp_delay) +{ + struct max8973_chip *max = rdev_get_drvdata(rdev); + unsigned int control; + int ret; + int ret_val; + + /* Set ramp delay */ + if (ramp_delay < 25000) { + control = MAX8973_RAMP_12mV_PER_US; + ret_val = 12000; + } else if (ramp_delay < 50000) { + control = MAX8973_RAMP_25mV_PER_US; + ret_val = 25000; + } else if (ramp_delay < 200000) { + control = MAX8973_RAMP_50mV_PER_US; + ret_val = 50000; + } else { + control = MAX8973_RAMP_200mV_PER_US; + ret_val = 200000; + } + + ret = regmap_update_bits(max->regmap, MAX8973_CONTROL1, + MAX8973_RAMP_MASK, control); + if (ret < 0) + dev_err(max->dev, "register %d update failed, %d", + MAX8973_CONTROL1, ret); + return ret; +} + static const struct regulator_ops max8973_dcdc_ops = { .get_voltage_sel = max8973_dcdc_get_voltage_sel, .set_voltage_sel = max8973_dcdc_set_voltage_sel, .list_voltage = regulator_list_voltage_linear, .set_mode = max8973_dcdc_set_mode, .get_mode = max8973_dcdc_get_mode, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_ramp_delay = max8973_set_ramp_delay, }; static int max8973_init_dcdc(struct max8973_chip *max, @@ -256,6 +298,29 @@ static int max8973_init_dcdc(struct max8973_chip *max, int ret; uint8_t control1 = 0; uint8_t control2 = 0; + unsigned int data; + + ret = regmap_read(max->regmap, MAX8973_CONTROL1, &data); + if (ret < 0) { + dev_err(max->dev, "register %d read failed, err = %d", + MAX8973_CONTROL1, ret); + return ret; + } + control1 = data & MAX8973_RAMP_MASK; + switch (control1) { + case MAX8973_RAMP_12mV_PER_US: + max->desc.ramp_delay = 12000; + break; + case MAX8973_RAMP_25mV_PER_US: + max->desc.ramp_delay = 25000; + break; + case MAX8973_RAMP_50mV_PER_US: + max->desc.ramp_delay = 50000; + break; + case MAX8973_RAMP_200mV_PER_US: + max->desc.ramp_delay = 200000; + break; + } if (pdata->control_flags & MAX8973_CONTROL_REMOTE_SENSE_ENABLE) control1 |= MAX8973_SNS_ENABLE; @@ -266,28 +331,16 @@ static int max8973_init_dcdc(struct max8973_chip *max, if (pdata->control_flags & MAX8973_CONTROL_OUTPUT_ACTIVE_DISCH_ENABLE) control1 |= MAX8973_AD_ENABLE; - if (pdata->control_flags & MAX8973_CONTROL_BIAS_ENABLE) + if (pdata->control_flags & MAX8973_CONTROL_BIAS_ENABLE) { control1 |= MAX8973_BIAS_ENABLE; + max->desc.enable_time = 20; + } else { + max->desc.enable_time = 240; + } if (pdata->control_flags & MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE) control1 |= MAX8973_FREQSHIFT_9PER; - /* Set ramp delay */ - if (pdata->reg_init_data && - pdata->reg_init_data->constraints.ramp_delay) { - if (pdata->reg_init_data->constraints.ramp_delay < 25000) - control1 |= MAX8973_RAMP_12mV_PER_US; - else if (pdata->reg_init_data->constraints.ramp_delay < 50000) - control1 |= MAX8973_RAMP_25mV_PER_US; - else if (pdata->reg_init_data->constraints.ramp_delay < 200000) - control1 |= MAX8973_RAMP_50mV_PER_US; - else - control1 |= MAX8973_RAMP_200mV_PER_US; - } else { - control1 |= MAX8973_RAMP_12mV_PER_US; - max->desc.ramp_delay = 12500; - } - if (!(pdata->control_flags & MAX8973_CONTROL_PULL_DOWN_ENABLE)) control2 |= MAX8973_DISCH_ENBABLE; @@ -344,7 +397,7 @@ static int max8973_init_dcdc(struct max8973_chip *max, } /* If external control is enabled then disable EN bit */ - if (max->enable_external_control) { + if (max->enable_external_control && (max->id == MAX8973)) { ret = regmap_update_bits(max->regmap, MAX8973_VOUT, MAX8973_VOUT_ENABLE, 0); if (ret < 0) @@ -361,22 +414,82 @@ static const struct regmap_config max8973_regmap_config = { .cache_type = REGCACHE_RBTREE, }; +static struct max8973_regulator_platform_data *max8973_parse_dt( + struct device *dev) +{ + struct max8973_regulator_platform_data *pdata; + struct device_node *np = dev->of_node; + int ret; + u32 pval; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + + pdata->enable_ext_control = of_property_read_bool(np, + "maxim,externally-enable"); + pdata->enable_gpio = of_get_named_gpio(np, "maxim,enable-gpio", 0); + pdata->dvs_gpio = of_get_named_gpio(np, "maxim,dvs-gpio", 0); + + ret = of_property_read_u32(np, "maxim,dvs-default-state", &pval); + if (!ret) + pdata->dvs_def_state = pval; + + if (of_property_read_bool(np, "maxim,enable-remote-sense")) + pdata->control_flags |= MAX8973_CONTROL_REMOTE_SENSE_ENABLE; + + if (of_property_read_bool(np, "maxim,enable-falling-slew-rate")) + pdata->control_flags |= + MAX8973_CONTROL_FALLING_SLEW_RATE_ENABLE; + + if (of_property_read_bool(np, "maxim,enable-active-discharge")) + pdata->control_flags |= + MAX8973_CONTROL_OUTPUT_ACTIVE_DISCH_ENABLE; + + if (of_property_read_bool(np, "maxim,enable-frequency-shift")) + pdata->control_flags |= MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE; + + if (of_property_read_bool(np, "maxim,enable-bias-control")) + pdata->control_flags |= MAX8973_BIAS_ENABLE; + + return pdata; +} + +static const struct of_device_id of_max8973_match_tbl[] = { + { .compatible = "maxim,max8973", .data = (void *)MAX8973, }, + { .compatible = "maxim,max77621", .data = (void *)MAX77621, }, + { }, +}; +MODULE_DEVICE_TABLE(of, of_max8973_match_tbl); + static int max8973_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct max8973_regulator_platform_data *pdata; + struct regulator_init_data *ridata; struct regulator_config config = { }; struct regulator_dev *rdev; struct max8973_chip *max; + bool pdata_from_dt = false; + unsigned int chip_id; int ret; pdata = dev_get_platdata(&client->dev); - if (!pdata && !client->dev.of_node) { + if (!pdata && client->dev.of_node) { + pdata = max8973_parse_dt(&client->dev); + pdata_from_dt = true; + } + + if (!pdata) { dev_err(&client->dev, "No Platform data"); return -EIO; } + if ((pdata->dvs_gpio == -EPROBE_DEFER) || + (pdata->enable_gpio == -EPROBE_DEFER)) + return -EPROBE_DEFER; + max = devm_kzalloc(&client->dev, sizeof(*max), GFP_KERNEL); if (!max) return -ENOMEM; @@ -388,6 +501,27 @@ static int max8973_probe(struct i2c_client *client, return ret; } + if (client->dev.of_node) { + const struct of_device_id *match; + + match = of_match_device(of_match_ptr(of_max8973_match_tbl), + &client->dev); + if (!match) + return -ENODATA; + max->id = (u32)((uintptr_t)match->data); + } else { + max->id = id->driver_data; + } + + ret = regmap_read(max->regmap, MAX8973_CHIPID1, &chip_id); + if (ret < 0) { + dev_err(&client->dev, "register CHIPID1 read failed, %d", ret); + return ret; + } + + dev_info(&client->dev, "CHIP-ID OTP: 0x%02x ID_M: 0x%02x\n", + (chip_id >> 4) & 0xF, (chip_id >> 1) & 0x7); + i2c_set_clientdata(client, max); max->ops = max8973_dcdc_ops; max->dev = &client->dev; @@ -400,23 +534,14 @@ static int max8973_probe(struct i2c_client *client, max->desc.uV_step = MAX8973_VOLATGE_STEP; max->desc.n_voltages = MAX8973_BUCK_N_VOLTAGE; - if (!pdata || !pdata->enable_ext_control) { - max->desc.enable_reg = MAX8973_VOUT; - max->desc.enable_mask = MAX8973_VOUT_ENABLE; - max->ops.enable = regulator_enable_regmap; - max->ops.disable = regulator_disable_regmap; - max->ops.is_enabled = regulator_is_enabled_regmap; - } + max->dvs_gpio = (pdata->dvs_gpio) ? pdata->dvs_gpio : -EINVAL; + max->enable_gpio = (pdata->enable_gpio) ? pdata->enable_gpio : -EINVAL; + max->enable_external_control = pdata->enable_ext_control; + max->curr_gpio_val = pdata->dvs_def_state; + max->curr_vout_reg = MAX8973_VOUT + pdata->dvs_def_state; - if (pdata) { - max->dvs_gpio = pdata->dvs_gpio; - max->enable_external_control = pdata->enable_ext_control; - max->curr_gpio_val = pdata->dvs_def_state; - max->curr_vout_reg = MAX8973_VOUT + pdata->dvs_def_state; - } else { - max->dvs_gpio = -EINVAL; - max->curr_vout_reg = MAX8973_VOUT; - } + if (gpio_is_valid(max->enable_gpio)) + max->enable_external_control = true; max->lru_index[0] = max->curr_vout_reg; @@ -434,7 +559,6 @@ static int max8973_probe(struct i2c_client *client, max->dvs_gpio, ret); return ret; } - max->valid_dvs_gpio = true; /* * Initialize the lru index with vout_reg id @@ -444,22 +568,64 @@ 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 { - max->valid_dvs_gpio = false; } - if (pdata) { - ret = max8973_init_dcdc(max, pdata); - if (ret < 0) { - dev_err(max->dev, "Max8973 Init failed, err = %d\n", ret); - return ret; + if (pdata_from_dt) + pdata->reg_init_data = of_get_regulator_init_data(&client->dev, + client->dev.of_node, &max->desc); + + ridata = pdata->reg_init_data; + switch (max->id) { + case MAX8973: + if (!pdata->enable_ext_control) { + max->desc.enable_reg = MAX8973_VOUT; + max->desc.enable_mask = MAX8973_VOUT_ENABLE; + max->ops.enable = regulator_enable_regmap; + max->ops.disable = regulator_disable_regmap; + max->ops.is_enabled = regulator_is_enabled_regmap; + break; + } + + if (gpio_is_valid(max->enable_gpio)) { + config.ena_gpio_flags = GPIOF_OUT_INIT_LOW; + if (ridata && (ridata->constraints.always_on || + ridata->constraints.boot_on)) + config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH; + config.ena_gpio = max->enable_gpio; } + break; + + case MAX77621: + if (gpio_is_valid(max->enable_gpio)) { + ret = devm_gpio_request_one(&client->dev, + max->enable_gpio, GPIOF_OUT_INIT_HIGH, + "max8973-en-gpio"); + if (ret) { + dev_err(&client->dev, + "gpio_request for gpio %d failed: %d\n", + max->enable_gpio, ret); + return ret; + } + } + + max->desc.enable_reg = MAX8973_VOUT; + max->desc.enable_mask = MAX8973_VOUT_ENABLE; + max->ops.enable = regulator_enable_regmap; + max->ops.disable = regulator_disable_regmap; + max->ops.is_enabled = regulator_is_enabled_regmap; + break; + default: + break; + } + + ret = max8973_init_dcdc(max, pdata); + if (ret < 0) { + dev_err(max->dev, "Max8973 Init failed, err = %d\n", ret); + return ret; } config.dev = &client->dev; - config.init_data = pdata ? pdata->reg_init_data : - of_get_regulator_init_data(&client->dev, client->dev.of_node, - &max->desc); + config.init_data = pdata->reg_init_data; config.driver_data = max; config.of_node = client->dev.of_node; config.regmap = max->regmap; @@ -476,15 +642,16 @@ static int max8973_probe(struct i2c_client *client, } static const struct i2c_device_id max8973_id[] = { - {.name = "max8973",}, + {.name = "max8973", .driver_data = MAX8973}, + {.name = "max77621", .driver_data = MAX77621}, {}, }; - MODULE_DEVICE_TABLE(i2c, max8973_id); static struct i2c_driver max8973_i2c_driver = { .driver = { .name = "max8973", + .of_match_table = of_max8973_match_tbl, .owner = THIS_MODULE, }, .probe = max8973_probe, diff --git a/include/linux/regulator/max8973-regulator.h b/include/linux/regulator/max8973-regulator.h index f8acc052e353..f6a8a16a0d4d 100644 --- a/include/linux/regulator/max8973-regulator.h +++ b/include/linux/regulator/max8973-regulator.h @@ -58,6 +58,9 @@ * control signal from EN input pin. If it is false then * voltage output will be enabled/disabled through EN bit of * device register. + * @enable_gpio: Enable GPIO. If EN pin is controlled through GPIO from host + * then GPIO number can be provided. If no GPIO controlled then + * it should be -1. * @dvs_gpio: GPIO for dvs. It should be -1 if this is tied with fixed logic. * @dvs_def_state: Default state of dvs. 1 if it is high else 0. */ @@ -65,6 +68,7 @@ struct max8973_regulator_platform_data { struct regulator_init_data *reg_init_data; unsigned long control_flags; bool enable_ext_control; + int enable_gpio; int dvs_gpio; unsigned dvs_def_state:1; }; |