regulator: max77812: add max77812 regulator driver
Adding regulator driver for MAX77812 device which is used in t210b01 based platforms for powering cpu,gpu and dram io Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
MAX77812 voltage regulator
|
||||
|
||||
Required properties:
|
||||
- compatible: "maxim,max77812-regulator"
|
||||
- reg: I2C slave address
|
||||
|
||||
Regulators subnode:
|
||||
|
||||
MAX77812 supports four regulators, regulators should be described under
|
||||
regualtors subnode.
|
||||
|
||||
Optional properties:
|
||||
-maxim,ramp-up-slew-rate: to configure slew rate during regulator
|
||||
voltage ramp up time
|
||||
-maxim,ramp-down-slew-rate: to configre slew rate during regulator
|
||||
voltage ramp down time
|
||||
-maxim,soft-start-slew-rate: to configure slew rate during regulator
|
||||
enable time
|
||||
-maxim,shutdown-slew-rate: to configure slew rate during regulator
|
||||
disable time or shutdown time
|
||||
|
||||
Each regulator is defined using the standard binding for regulators.
|
||||
|
||||
Example:
|
||||
|
||||
max77812@1b {
|
||||
compatible = "maxim,max77812-regulator";
|
||||
reg = <0x1b>;
|
||||
|
||||
regulators {
|
||||
m1vout {
|
||||
regulator-name = "mvout1";
|
||||
regulator-min-microvolt = <250000>;
|
||||
regulator-max-microvolt = <1525000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-init-mode = <REGULATOR_MODE_NORMAL>;
|
||||
};
|
||||
|
||||
m2vout {
|
||||
regulator-name = "mvout2";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <250000>;
|
||||
regulator-max-microvolt = <1525000>;
|
||||
regulator-init-mode = <REGULATOR_MODE_NORMAL>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -756,6 +756,15 @@ config REGULATOR_MAX77802
|
||||
Exynos5420/Exynos5800 SoCs to control various voltages.
|
||||
It includes support for control of voltage and ramp speed.
|
||||
|
||||
config REGULATOR_MAX77812
|
||||
tristate "Maxim 77812 Quad-Phase Buck regualtor"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
help
|
||||
MAXIM MAX77812 is a quad-phase, high-current, buck regulator.
|
||||
This driver supports configuration of this device
|
||||
through regulator interface.
|
||||
|
||||
config REGULATOR_MAX77826
|
||||
tristate "Maxim 77826 regulator"
|
||||
depends on I2C
|
||||
|
||||
@@ -90,6 +90,7 @@ obj-$(CONFIG_REGULATOR_MAX20411) += max20411-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX77686) += max77686-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX77693) += max77693-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX77802) += max77802-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX77812) += max77812-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX77826) += max77826-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX77857) += max77857-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
|
||||
|
||||
586
drivers/regulator/max77812-regulator.c
Normal file
586
drivers/regulator/max77812-regulator.c
Normal file
@@ -0,0 +1,586 @@
|
||||
/*
|
||||
* MAXIM max77812 Regulator driver
|
||||
*
|
||||
* Copyright (C) 2017-2020, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Author: Venkat Reddy Talla <vreddytalla@nvidia.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.
|
||||
*
|
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
|
||||
* whether express or implied; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
#define MAX77812_REG_RSET 0x00
|
||||
#define MAX77812_REG_INT_SRC 0x01
|
||||
#define MAX77812_REG_INT_SRC_M 0x02
|
||||
#define MAX77812_REG_TOPSYS_INT 0x03
|
||||
#define MAX77812_REG_TOPSYS_INT_M 0x04
|
||||
#define MAX77812_REG_TOPSYS_STAT 0x05
|
||||
#define MAX77812_REG_EN_CTRL 0x06
|
||||
#define MAX77812_REG_STUP_DLY2 0x07
|
||||
#define MAX77812_REG_STUP_DLY3 0x08
|
||||
#define MAX77812_REG_STUP_DLY4 0x09
|
||||
#define MAX77812_REG_SHDN_DLY1 0x0A
|
||||
#define MAX77812_REG_SHDN_DLY2 0x0B
|
||||
#define MAX77812_REG_SHDN_DLY3 0x0C
|
||||
#define MAX77812_REG_SHDN_DLY4 0x0D
|
||||
#define MAX77812_REG_WDTRSTB_DEB 0x0E
|
||||
#define MAX77812_REG_GPI_FUNC 0x0F
|
||||
#define MAX77812_REG_GPI_DEB1 0x10
|
||||
#define MAX77812_REG_GPI_DEB2 0x11
|
||||
#define MAX77812_REG_GPI_PD_CTRL 0x12
|
||||
#define MAX77812_REG_PROT_CFG 0x13
|
||||
#define MAX77812_REG_VERSION 0x14
|
||||
#define MAX77812_REG_I2C_CFG 0x15
|
||||
#define MAX77812_REG_BUCK_INT 0x20
|
||||
#define MAX77812_REG_BUCK_INT_M 0x21
|
||||
#define MAX77812_REG_BUCK_STAT 0x22
|
||||
#define MAX77812_REG_M1_VOUT 0x23
|
||||
#define MAX77812_REG_M2_VOUT 0x24
|
||||
#define MAX77812_REG_M3_VOUT 0x25
|
||||
#define MAX77812_REG_M4_VOUT 0x26
|
||||
#define MAX77812_REG_M1_VOUT_D 0x27
|
||||
#define MAX77812_REG_M2_VOUT_D 0x28
|
||||
#define MAX77812_REG_M3_VOUT_D 0x29
|
||||
#define MAX77812_REG_M4_VOUT_D 0x2A
|
||||
#define MAX77812_REG_M1_VOUT_S 0x2B
|
||||
#define MAX77812_REG_M2_VOUT_S 0x2C
|
||||
#define MAX77812_REG_M3_VOUT_S 0x2D
|
||||
#define MAX77812_REG_M4_VOUT_S 0x2E
|
||||
#define MAX77812_REG_M1_CFG 0x2F
|
||||
#define MAX77812_REG_M2_CFG 0x30
|
||||
#define MAX77812_REG_M3_CFG 0x31
|
||||
#define MAX77812_REG_M4_CFG 0x32
|
||||
#define MAX77812_REG_GLB_CFG1 0x33
|
||||
#define MAX77812_REG_GLB_CFG2 0x34
|
||||
#define MAX77812_REG_GLB_CFG3 0x35
|
||||
#define MAX77812_REG_GLB_CFG4 0x36
|
||||
#define MAX77812_REG_GLB_CFG5 0x37
|
||||
#define MAX77812_REG_GLB_CFG6 0x38
|
||||
#define MAX77812_REG_GLB_CFG7 0x39
|
||||
#define MAX77812_REG_GLB_CFG8 0x3A
|
||||
#define MAX77812_REG_PROT_ACCESS 0xFD
|
||||
#define MAX77812_REG_MAX 0xFE
|
||||
|
||||
#define MAX77812_REG_EN_CTRL_MASK(n) BIT(n)
|
||||
#define MAX77812_START_SLEW_RATE_MASK 0x07
|
||||
#define MAX77812_SHDN_SLEW_RATE_MASK 0x70
|
||||
#define MAX77812_RAMPUP_SLEW_RATE_MASK 0x07
|
||||
#define MAX77812_RAMPDOWN_SLEW_RATE_MASK 0x70
|
||||
#define MAX77812_SLEW_RATE_SHIFT 4
|
||||
|
||||
#define MAX77812_OP_ACTIVE_DISCHARGE_MASK BIT(7)
|
||||
#define MAX77812_PEAK_CURRENT_LMT_MASK 0x70
|
||||
#define MAX77812_SWITCH_FREQ_MASK 0x0C
|
||||
#define MAX77812_FORCED_PWM_MASK BIT(1)
|
||||
#define MAX77812_SLEW_RATE_CNTRL_MASK BIT(0)
|
||||
#define MAX77812_START_SHD_DELAY_MASK 0x1F
|
||||
#define MAX77812_VERSION_MASK 0x07
|
||||
#define MAX77812_ES2_VERSION 0x04
|
||||
#define MAX77812_QS_VERSION 0x05
|
||||
|
||||
#define MAX77812_VOUT_MASK 0xFF
|
||||
#define MAX77812_VOUT_N_VOLTAGE 0xFF
|
||||
#define MAX77812_VOUT_VMIN 250000
|
||||
#define MAX77812_VOUT_VMAX 1525000
|
||||
#define MAX77812_VOUT_STEP 5000
|
||||
|
||||
#define MAX77812_PHASE4_I2C_ADD 0x30
|
||||
#define MAX77812_PHASE31_I2C_ADD 0x31
|
||||
#define MAX77812_PHASE22_I2C_ADD 0x32
|
||||
#define MAX77812_PHASE211_I2C_ADD 0x33
|
||||
#define MAX77812_PHASE1_I2C_ADD 0x34
|
||||
|
||||
enum {
|
||||
MAX77812_REG_ID_M1,
|
||||
MAX77812_REG_ID_M2,
|
||||
MAX77812_REG_ID_M3,
|
||||
MAX77812_REG_ID_M4,
|
||||
MAX77812_ID_RG_MAX,
|
||||
};
|
||||
|
||||
static unsigned int slew_rate_table[] = {
|
||||
1250, 2500, 5000, 10000, 20000, 40000, 60000,
|
||||
};
|
||||
|
||||
static unsigned int peak_current_limit[] = {
|
||||
3000000, 3600000, 4200000, 4800000, 5400000, 6000000,
|
||||
6000000, 7200000,
|
||||
};
|
||||
|
||||
struct max77812_reg_pdata {
|
||||
int peak_current_limit;
|
||||
int switching_freq;
|
||||
bool disable_active_discharge;
|
||||
bool delay_time_step_select;
|
||||
bool enable_forced_pwm;
|
||||
bool disable_slew_rate_cntrl;
|
||||
};
|
||||
|
||||
struct max77812_regulator {
|
||||
struct device *dev;
|
||||
struct regmap *rmap;
|
||||
struct regulator_desc *rdesc[MAX77812_ID_RG_MAX];
|
||||
struct max77812_reg_pdata reg_pdata[MAX77812_ID_RG_MAX];
|
||||
struct regulator_dev *rdev[MAX77812_ID_RG_MAX];
|
||||
u32 ramp_up_slew_rate;
|
||||
u32 ramp_down_slew_rate;
|
||||
u32 shutdown_slew_rate;
|
||||
u32 softstart_slew_rate;
|
||||
};
|
||||
|
||||
static u8 max77802_slew_rate_to_reg(const unsigned int sr_limits[],
|
||||
u8 cnt, unsigned int slew_rate)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
if (slew_rate <= sr_limits[i])
|
||||
return i;
|
||||
}
|
||||
|
||||
return cnt - 1;
|
||||
}
|
||||
|
||||
static int max77812_reg_init(struct max77812_regulator *max77812)
|
||||
{
|
||||
u8 slew_rate = 0;
|
||||
u8 rampdelay = 0;
|
||||
u8 mask = 0;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
if (max77812->softstart_slew_rate) {
|
||||
slew_rate = max77802_slew_rate_to_reg(slew_rate_table,
|
||||
ARRAY_SIZE(slew_rate_table),
|
||||
max77812->softstart_slew_rate);
|
||||
mask = MAX77812_START_SLEW_RATE_MASK;
|
||||
}
|
||||
|
||||
if (max77812->shutdown_slew_rate) {
|
||||
rampdelay = max77802_slew_rate_to_reg(slew_rate_table,
|
||||
ARRAY_SIZE(slew_rate_table),
|
||||
max77812->shutdown_slew_rate);
|
||||
slew_rate |= (rampdelay << MAX77812_SLEW_RATE_SHIFT);
|
||||
mask |= MAX77812_SHDN_SLEW_RATE_MASK;
|
||||
}
|
||||
|
||||
if (slew_rate && mask) {
|
||||
ret = regmap_update_bits(max77812->rmap,
|
||||
MAX77812_REG_GLB_CFG1,
|
||||
mask, slew_rate);
|
||||
if (ret < 0) {
|
||||
dev_err(max77812->dev,
|
||||
"slew rate cfg1 update failed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
slew_rate = 0;
|
||||
mask = 0;
|
||||
|
||||
if (max77812->ramp_up_slew_rate) {
|
||||
slew_rate = max77802_slew_rate_to_reg(slew_rate_table,
|
||||
ARRAY_SIZE(slew_rate_table),
|
||||
max77812->ramp_up_slew_rate);
|
||||
mask = MAX77812_RAMPUP_SLEW_RATE_MASK;
|
||||
}
|
||||
|
||||
if (max77812->ramp_down_slew_rate) {
|
||||
rampdelay = max77802_slew_rate_to_reg(slew_rate_table,
|
||||
ARRAY_SIZE(slew_rate_table),
|
||||
max77812->ramp_down_slew_rate);
|
||||
slew_rate |= (rampdelay << MAX77812_SLEW_RATE_SHIFT);
|
||||
mask |= MAX77812_RAMPDOWN_SLEW_RATE_MASK;
|
||||
}
|
||||
|
||||
if (slew_rate && mask) {
|
||||
ret = regmap_update_bits(max77812->rmap,
|
||||
MAX77812_REG_GLB_CFG2,
|
||||
mask, slew_rate);
|
||||
if (ret < 0) {
|
||||
dev_err(max77812->dev,
|
||||
"slew rate cfg2 update failed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = regmap_read(max77812->rmap, MAX77812_REG_VERSION, &val);
|
||||
if (ret < 0) {
|
||||
dev_err(max77812->dev, "version reg read failed:%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Bit[2:0] = 100b -> ES2 Bit[2:0] = 101b -> QS version */
|
||||
dev_info(max77812->dev, "MAX77812 Version OTP:0x%02X\n", val);
|
||||
|
||||
if ((val & MAX77812_VERSION_MASK) == MAX77812_ES2_VERSION) {
|
||||
ret = regmap_write(max77812->rmap,
|
||||
MAX77812_REG_PROT_ACCESS, 0x5A);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = regmap_read(max77812->rmap,
|
||||
MAX77812_REG_PROT_ACCESS, &val);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
if (val != 0x5A) {
|
||||
dev_err(max77812->dev, "prot register unlock failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_write(max77812->rmap, MAX77812_REG_GLB_CFG5, 0x3E);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = regmap_write(max77812->rmap, MAX77812_REG_GLB_CFG6, 0x90);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = regmap_write(max77812->rmap, MAX77812_REG_GLB_CFG8, 0x3A);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = regmap_write(max77812->rmap,
|
||||
MAX77812_REG_PROT_ACCESS, 0x0);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = regmap_read(max77812->rmap,
|
||||
MAX77812_REG_PROT_ACCESS, &val);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
if (val) {
|
||||
dev_err(max77812->dev, "protect registers lock failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
dev_err(max77812->dev, "protect register access failed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int max77812_config_init(struct max77812_regulator *max77812, int id)
|
||||
{
|
||||
struct max77812_reg_pdata *rpdata = &max77812->reg_pdata[id];
|
||||
u8 rail_config = 0;
|
||||
u8 mask = 0;
|
||||
u8 curnt_lim;
|
||||
u8 switch_freq;
|
||||
u8 reg_addr = 0;
|
||||
int ret;
|
||||
|
||||
if (rpdata->disable_active_discharge) {
|
||||
rail_config &= ~MAX77812_OP_ACTIVE_DISCHARGE_MASK;
|
||||
mask = MAX77812_OP_ACTIVE_DISCHARGE_MASK;
|
||||
}
|
||||
|
||||
if (rpdata->peak_current_limit > 0) {
|
||||
curnt_lim = max77802_slew_rate_to_reg(peak_current_limit,
|
||||
ARRAY_SIZE(peak_current_limit),
|
||||
rpdata->peak_current_limit);
|
||||
rail_config |= (curnt_lim << 4);
|
||||
mask |= MAX77812_PEAK_CURRENT_LMT_MASK;
|
||||
}
|
||||
|
||||
if (rpdata->switching_freq > 0) {
|
||||
if (rpdata->switching_freq == 2)
|
||||
switch_freq = 0;
|
||||
else if (rpdata->switching_freq == 3)
|
||||
switch_freq = 1;
|
||||
else if (rpdata->switching_freq == 4)
|
||||
switch_freq = 2;
|
||||
else
|
||||
switch_freq = 3;
|
||||
rail_config |= (switch_freq << 2);
|
||||
mask |= MAX77812_SWITCH_FREQ_MASK;
|
||||
}
|
||||
|
||||
if (rpdata->enable_forced_pwm) {
|
||||
rail_config |= MAX77812_FORCED_PWM_MASK;
|
||||
mask |= MAX77812_FORCED_PWM_MASK;
|
||||
}
|
||||
|
||||
if (rpdata->disable_slew_rate_cntrl) {
|
||||
rail_config &= ~MAX77812_SLEW_RATE_CNTRL_MASK;
|
||||
mask |= MAX77812_SLEW_RATE_CNTRL_MASK;
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case MAX77812_REG_ID_M1:
|
||||
reg_addr = MAX77812_REG_M1_CFG;
|
||||
break;
|
||||
case MAX77812_REG_ID_M2:
|
||||
reg_addr = MAX77812_REG_M2_CFG;
|
||||
break;
|
||||
case MAX77812_REG_ID_M3:
|
||||
reg_addr = MAX77812_REG_M3_CFG;
|
||||
break;
|
||||
case MAX77812_REG_ID_M4:
|
||||
reg_addr = MAX77812_REG_M4_CFG;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rail_config && mask) {
|
||||
ret = regmap_update_bits(max77812->rmap,
|
||||
reg_addr, mask, rail_config);
|
||||
if (ret < 0) {
|
||||
dev_err(max77812->dev,
|
||||
"reg config update failed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max77812_of_parse_cb(struct device_node *np,
|
||||
const struct regulator_desc *desc,
|
||||
struct regulator_config *config)
|
||||
{
|
||||
struct max77812_regulator *max77812 = config->driver_data;
|
||||
struct max77812_reg_pdata *rpdata = &max77812->reg_pdata[desc->id];
|
||||
u32 pval;
|
||||
int ret;
|
||||
|
||||
rpdata->disable_active_discharge = of_property_read_bool(np,
|
||||
"maxim,disable-active-discharge");
|
||||
|
||||
ret = of_property_read_u32(np, "maxim,peak-current-limit-ua", &pval);
|
||||
rpdata->peak_current_limit = (!ret) ? pval : -1;
|
||||
|
||||
ret = of_property_read_u32(np, "maxim,switching-frequency", &pval);
|
||||
rpdata->switching_freq = (!ret) ? pval : -1;
|
||||
|
||||
rpdata->enable_forced_pwm = of_property_read_bool(np,
|
||||
"maxim,enable-forced-pwm-mode");
|
||||
|
||||
rpdata->disable_slew_rate_cntrl = of_property_read_bool(np,
|
||||
"maxim,disable-slew-rate-control");
|
||||
|
||||
return max77812_config_init(max77812, desc->id);
|
||||
}
|
||||
|
||||
static struct regulator_ops max77812_regulator_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
};
|
||||
|
||||
#define MAX77812_REGULATOR_DESC(_id, _name, _en_bit) \
|
||||
[MAX77812_REG_ID_##_id] = { \
|
||||
.name = "max77812-"#_name, \
|
||||
.of_match = of_match_ptr(#_name), \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.of_parse_cb = max77812_of_parse_cb, \
|
||||
.supply_name = "vin", \
|
||||
.id = MAX77812_REG_ID_##_id, \
|
||||
.ops = &max77812_regulator_ops, \
|
||||
.n_voltages = MAX77812_VOUT_N_VOLTAGE, \
|
||||
.min_uV = MAX77812_VOUT_VMIN, \
|
||||
.uV_step = MAX77812_VOUT_STEP, \
|
||||
.enable_time = 500, \
|
||||
.vsel_mask = MAX77812_VOUT_MASK, \
|
||||
.vsel_reg = MAX77812_REG_##_id##_VOUT, \
|
||||
.enable_reg = MAX77812_REG_EN_CTRL, \
|
||||
.enable_mask = BIT(_en_bit), \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
}
|
||||
|
||||
static struct regulator_desc max77812_regs_desc[MAX77812_ID_RG_MAX] = {
|
||||
MAX77812_REGULATOR_DESC(M1, m1vout, 0),
|
||||
MAX77812_REGULATOR_DESC(M2, m2vout, 2),
|
||||
MAX77812_REGULATOR_DESC(M3, m3vout, 4),
|
||||
MAX77812_REGULATOR_DESC(M4, m4vout, 6),
|
||||
};
|
||||
|
||||
static int max77812_reg_parse_dt(struct device *dev,
|
||||
struct max77812_regulator *max77812_regs)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
u32 pval;
|
||||
int ret;
|
||||
|
||||
ret = of_property_read_u32(np, "maxim,ramp-up-slew-rate", &pval);
|
||||
if (!ret)
|
||||
max77812_regs->ramp_up_slew_rate = pval;
|
||||
|
||||
ret = of_property_read_u32(np, "maxim,ramp-down-slew-rate", &pval);
|
||||
if (!ret)
|
||||
max77812_regs->ramp_down_slew_rate = pval;
|
||||
else
|
||||
max77812_regs->ramp_down_slew_rate =
|
||||
max77812_regs->ramp_up_slew_rate;
|
||||
|
||||
ret = of_property_read_u32(np, "maxim,soft-start-slew-rate", &pval);
|
||||
if (!ret)
|
||||
max77812_regs->softstart_slew_rate = pval;
|
||||
|
||||
ret = of_property_read_u32(np, "maxim,shutdown-slew-rate", &pval);
|
||||
if (!ret)
|
||||
max77812_regs->shutdown_slew_rate = pval;
|
||||
else
|
||||
max77812_regs->shutdown_slew_rate =
|
||||
max77812_regs->softstart_slew_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct regmap_config max77812_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = MAX77812_REG_MAX - 1,
|
||||
.cache_type = REGCACHE_NONE,
|
||||
};
|
||||
|
||||
static int max77812_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct max77812_reg_pdata *rpdata;
|
||||
struct regulator_config config = { };
|
||||
struct regulator_desc *max77812_rdesc[MAX77812_ID_RG_MAX];
|
||||
struct max77812_regulator *max77812;
|
||||
unsigned short addr = client->addr;
|
||||
int id, max_regs = 0;
|
||||
int ret;
|
||||
|
||||
max77812 = devm_kzalloc(dev, sizeof(*max77812), GFP_KERNEL);
|
||||
if (!max77812)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = max77812_reg_parse_dt(dev, max77812);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Reading data from DT failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
max77812->rmap = devm_regmap_init_i2c(client, &max77812_regmap_config);
|
||||
if (IS_ERR(max77812->rmap)) {
|
||||
ret = PTR_ERR(max77812->rmap);
|
||||
dev_err(dev, "regmap init failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, max77812);
|
||||
max77812->dev = dev;
|
||||
|
||||
ret = max77812_reg_init(max77812);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "max77812 Init failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (addr) {
|
||||
case MAX77812_PHASE4_I2C_ADD:
|
||||
max77812_rdesc[0] = &max77812_regs_desc[MAX77812_REG_ID_M1];
|
||||
max_regs = 1;
|
||||
break;
|
||||
case MAX77812_PHASE31_I2C_ADD:
|
||||
max77812_rdesc[0] = &max77812_regs_desc[MAX77812_REG_ID_M1];
|
||||
max77812_rdesc[1] = &max77812_regs_desc[MAX77812_REG_ID_M4];
|
||||
max_regs = 2;
|
||||
break;
|
||||
case MAX77812_PHASE22_I2C_ADD:
|
||||
max77812_rdesc[0] = &max77812_regs_desc[MAX77812_REG_ID_M1];
|
||||
max77812_rdesc[1] = &max77812_regs_desc[MAX77812_REG_ID_M3];
|
||||
max_regs = 2;
|
||||
break;
|
||||
case MAX77812_PHASE211_I2C_ADD:
|
||||
max77812_rdesc[0] = &max77812_regs_desc[MAX77812_REG_ID_M1];
|
||||
max77812_rdesc[1] = &max77812_regs_desc[MAX77812_REG_ID_M3];
|
||||
max77812_rdesc[2] = &max77812_regs_desc[MAX77812_REG_ID_M4];
|
||||
max_regs = 3;
|
||||
break;
|
||||
case MAX77812_PHASE1_I2C_ADD:
|
||||
max77812_rdesc[0] = &max77812_regs_desc[MAX77812_REG_ID_M1];
|
||||
max77812_rdesc[1] = &max77812_regs_desc[MAX77812_REG_ID_M2];
|
||||
max77812_rdesc[2] = &max77812_regs_desc[MAX77812_REG_ID_M3];
|
||||
max77812_rdesc[3] = &max77812_regs_desc[MAX77812_REG_ID_M4];
|
||||
max_regs = 4;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "I2C address invalid: 0x%02x\n", addr);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
for (id = 0; id < max_regs; ++id) {
|
||||
max77812->rdesc[id] = max77812_rdesc[id];
|
||||
rpdata = &max77812->reg_pdata[id];
|
||||
|
||||
config.regmap = max77812->rmap;
|
||||
config.dev = dev;
|
||||
config.driver_data = max77812;
|
||||
|
||||
max77812->rdev[id] = devm_regulator_register(dev,
|
||||
max77812->rdesc[id], &config);
|
||||
if (IS_ERR(max77812->rdev[id])) {
|
||||
ret = PTR_ERR(max77812->rdev[id]);
|
||||
dev_err(dev, "regulator %s register failed: %d\n",
|
||||
max77812->rdesc[id]->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!max77812->rdev[id]->constraints->enable_time)
|
||||
max77812->rdev[id]->constraints->enable_time =
|
||||
max77812->softstart_slew_rate;
|
||||
|
||||
if (!max77812->rdev[id]->constraints->ramp_delay)
|
||||
max77812->rdev[id]->constraints->ramp_delay =
|
||||
max77812->ramp_up_slew_rate;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id max77812_of_match[] = {
|
||||
{ .compatible = "maxim,max77812-regulator", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, max77812_of_match);
|
||||
|
||||
static const struct i2c_device_id max77812_id[] = {
|
||||
{.name = "max77812",},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct i2c_driver max77812_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "max77812",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = max77812_of_match,
|
||||
},
|
||||
.probe = max77812_probe,
|
||||
.id_table = max77812_id,
|
||||
};
|
||||
module_i2c_driver(max77812_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("max77812 regulator driver");
|
||||
MODULE_AUTHOR("Venkat Reddy Talla <vreddytalla@nvidia.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
Reference in New Issue
Block a user