Commit 0f7d6ece authored by Laxman Dewangan's avatar Laxman Dewangan Committed by Mark Brown

regulator: max8973: add support for MAX77621

Maxim MAX77621 device is high-efficiency, three-phase,
DC-DC step-down switching regulator delivers peak
output currents up to 16A. This device is extension of
MAX8973 and compatible with the register definition.

The MAX77621 has the SHUTDOWN pin which is EN pin on the
MAX8973. On MAX77621, the SHUTDOWN pin (active low) reset
device register to its POR/OTP value. The voltage output
is enabled when SHUTDONW pin is HIGH and EN bit on VOUT
register is HIGH.

For MAX8973, VOUT is enabled when EN bit or EN pin is high.

Add support of the MAX77621 device on max8973 regulator driver
with following changes:
- Make sure SHUTDOWN pin is set HIGH through GPIO calls if
  GPIO from AP connected to SHUTDOWN pin provided.
- Enable/disable the rail through register access only.
Signed-off-by: default avatarLaxman Dewangan <ldewangan@nvidia.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 3064c1f3
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
Required properties: 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. - reg: the i2c slave address of the regulator. It should be 0x1b.
Any standard regulator properties can be used to configure the single max8973 Any standard regulator properties can be used to configure the single max8973
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
...@@ -91,6 +92,11 @@ ...@@ -91,6 +92,11 @@
#define MAX8973_VOLATGE_STEP 6250 #define MAX8973_VOLATGE_STEP 6250
#define MAX8973_BUCK_N_VOLTAGE 0x80 #define MAX8973_BUCK_N_VOLTAGE 0x80
enum device_id {
MAX8973,
MAX77621
};
/* Maxim 8973 chip information */ /* Maxim 8973 chip information */
struct max8973_chip { struct max8973_chip {
struct device *dev; struct device *dev;
...@@ -104,6 +110,7 @@ struct max8973_chip { ...@@ -104,6 +110,7 @@ struct max8973_chip {
int curr_vout_reg; int curr_vout_reg;
int curr_gpio_val; int curr_gpio_val;
struct regulator_ops ops; struct regulator_ops ops;
enum device_id id;
}; };
/* /*
...@@ -390,7 +397,7 @@ static int max8973_init_dcdc(struct max8973_chip *max, ...@@ -390,7 +397,7 @@ static int max8973_init_dcdc(struct max8973_chip *max,
} }
/* If external control is enabled then disable EN bit */ /* 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, ret = regmap_update_bits(max->regmap, MAX8973_VOUT,
MAX8973_VOUT_ENABLE, 0); MAX8973_VOUT_ENABLE, 0);
if (ret < 0) if (ret < 0)
...@@ -448,6 +455,13 @@ static struct max8973_regulator_platform_data *max8973_parse_dt( ...@@ -448,6 +455,13 @@ static struct max8973_regulator_platform_data *max8973_parse_dt(
return pdata; 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, static int max8973_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -457,6 +471,7 @@ static int max8973_probe(struct i2c_client *client, ...@@ -457,6 +471,7 @@ static int max8973_probe(struct i2c_client *client,
struct regulator_dev *rdev; struct regulator_dev *rdev;
struct max8973_chip *max; struct max8973_chip *max;
bool pdata_from_dt = false; bool pdata_from_dt = false;
unsigned int chip_id;
int ret; int ret;
pdata = dev_get_platdata(&client->dev); pdata = dev_get_platdata(&client->dev);
...@@ -486,6 +501,27 @@ static int max8973_probe(struct i2c_client *client, ...@@ -486,6 +501,27 @@ static int max8973_probe(struct i2c_client *client,
return ret; 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); i2c_set_clientdata(client, max);
max->ops = max8973_dcdc_ops; max->ops = max8973_dcdc_ops;
max->dev = &client->dev; max->dev = &client->dev;
...@@ -507,14 +543,6 @@ static int max8973_probe(struct i2c_client *client, ...@@ -507,14 +543,6 @@ static int max8973_probe(struct i2c_client *client,
if (gpio_is_valid(max->enable_gpio)) if (gpio_is_valid(max->enable_gpio))
max->enable_external_control = true; max->enable_external_control = true;
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;
}
max->lru_index[0] = max->curr_vout_reg; max->lru_index[0] = max->curr_vout_reg;
if (gpio_is_valid(max->dvs_gpio)) { if (gpio_is_valid(max->dvs_gpio)) {
...@@ -546,6 +574,50 @@ static int max8973_probe(struct i2c_client *client, ...@@ -546,6 +574,50 @@ static int max8973_probe(struct i2c_client *client,
pdata->reg_init_data = of_get_regulator_init_data(&client->dev, pdata->reg_init_data = of_get_regulator_init_data(&client->dev,
client->dev.of_node, &max->desc); 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); ret = max8973_init_dcdc(max, pdata);
if (ret < 0) { if (ret < 0) {
dev_err(max->dev, "Max8973 Init failed, err = %d\n", ret); dev_err(max->dev, "Max8973 Init failed, err = %d\n", ret);
...@@ -558,15 +630,6 @@ static int max8973_probe(struct i2c_client *client, ...@@ -558,15 +630,6 @@ static int max8973_probe(struct i2c_client *client,
config.of_node = client->dev.of_node; config.of_node = client->dev.of_node;
config.regmap = max->regmap; config.regmap = max->regmap;
if (gpio_is_valid(max->enable_gpio)) {
ridata = pdata->reg_init_data;
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;
}
/* Register the regulators */ /* Register the regulators */
rdev = devm_regulator_register(&client->dev, &max->desc, &config); rdev = devm_regulator_register(&client->dev, &max->desc, &config);
if (IS_ERR(rdev)) { if (IS_ERR(rdev)) {
...@@ -579,15 +642,16 @@ static int max8973_probe(struct i2c_client *client, ...@@ -579,15 +642,16 @@ static int max8973_probe(struct i2c_client *client,
} }
static const struct i2c_device_id max8973_id[] = { 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); MODULE_DEVICE_TABLE(i2c, max8973_id);
static struct i2c_driver max8973_i2c_driver = { static struct i2c_driver max8973_i2c_driver = {
.driver = { .driver = {
.name = "max8973", .name = "max8973",
.of_match_table = of_max8973_match_tbl,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = max8973_probe, .probe = max8973_probe,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment