mfd: rk808: add rk816 support

include sub modules: regulator, rtc, gpio, pwrkey

Change-Id: I5efedb2abe2be5335c467aaa91955cb7b9f56cfb
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
This commit is contained in:
Elaine Zhang
2019-03-15 09:38:20 +08:00
committed by Tao Huang
parent 0276e9624b
commit 00ee69d479
4 changed files with 258 additions and 7 deletions

View File

@@ -1116,14 +1116,14 @@ config MFD_RC5T583
different functionality of the device.
config MFD_RK808
tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power Management Chip"
tristate "Rockchip RK805/RK808/RK809/RK816/RK817/RK818 Power Management Chip"
depends on I2C && OF
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
help
If you say yes here you get support for the RK805, RK808, RK809,
RK817 and RK818 Power Management chips.
RK816, RK817, RK818 Power Management chips.
This driver provides common support for accessing the device
through I2C interface. The device supports multiple sub-devices
including interrupts, RTC, LDO & DCDC regulators, and onkey.

View File

@@ -929,11 +929,11 @@ config REGULATOR_RC5T583
outputs which can be controlled by i2c communication.
config REGULATOR_RK808
tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power regulators"
tristate "Rockchip RK805/RK808/RK809/RK816/RK817/RK818 Power regulators"
depends on MFD_RK808
help
Select this option to enable the power regulator of ROCKCHIP
PMIC RK805,RK809&RK817,RK808 and RK818.
PMIC RK805,RK809&RK817,RK808, RK816 and RK818.
This driver supports the control of different power rails of device
through regulator interface. The device supports multiple DCDC/LDO
outputs which can be controlled by i2c communication.

View File

@@ -34,6 +34,11 @@
#define RK817_BOOST_VSEL_MASK 0x7
#define RK817_BUCK_VSEL_MASK 0x7f
#define RK816_DCDC_SLP_EN_REG_OFFSET 2
#define RK816_SWITCH_SLP_EN_REG_OFFSET 1
#define RK816_LDO1_4_SLP_EN_REG_OFFSET 1
#define RK816_LDO5_6_SLP_EN_REG_OFFSET 2
#define RK818_BUCK_VSEL_MASK 0x3f
#define RK818_BUCK4_VSEL_MASK 0x1f
#define RK818_LDO_VSEL_MASK 0x1f
@@ -113,6 +118,11 @@
.ops = _ops, \
}
#define RK816_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \
_vmask, _ereg, _emask, _disval, _etime) \
RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \
_vmask, _ereg, _emask, _emask, _disval, _etime, &rk808_reg_ops)
#define RK805_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \
_vmask, _ereg, _emask, _etime) \
RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \
@@ -170,6 +180,17 @@ static const struct linear_range rk808_ldo3_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(2500000, 15, 15, 0),
};
static const struct linear_range rk816_buck_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(712500, 0, 59, 12500), /* 0.7125v - 1.45v */
REGULATOR_LINEAR_RANGE(1800000, 60, 62, 200000),/* 1.8v - 2.2v */
REGULATOR_LINEAR_RANGE(2300000, 63, 63, 0), /* 2.3v - 2.3v */
};
static const struct linear_range rk816_buck4_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(800000, 0, 26, 100000), /* 0.8v - 3.4 */
REGULATOR_LINEAR_RANGE(3500000, 27, 31, 0), /* 3.5v */
};
#define RK809_BUCK5_SEL_CNT (8)
static const struct linear_range rk809_buck5_voltage_ranges[] = {
@@ -287,6 +308,58 @@ static int rk808_buck1_2_i2c_set_voltage_sel(struct regulator_dev *rdev,
return ret;
}
#ifdef CONFIG_CLK_RK312X
extern void rkclk_cpuclk_div_setting(int div);
#else
static inline void rkclk_cpuclk_div_setting(int div) {}
#endif
static int rk816_regulator_set_voltage_sel_regmap(struct regulator_dev *rdev,
unsigned int sel)
{
int ret, real_sel, delay = 100;
int rk816_type;
int id = rdev_get_id(rdev);
regmap_read(rdev->regmap, RK816_CHIP_VER_REG, &rk816_type);
rk816_type &= RK816_CHIP_VERSION_MASK;
sel <<= ffs(rdev->desc->vsel_mask) - 1;
if ((rk816_type != RK816_TYPE_ES2) && (id == 0)) {
if (sel > 23)
rkclk_cpuclk_div_setting(4);
else
rkclk_cpuclk_div_setting(2);
}
do {
ret = regmap_update_bits(rdev->regmap,
rdev->desc->vsel_reg,
rdev->desc->vsel_mask, sel);
if (ret)
return ret;
if (rk816_type == RK816_TYPE_ES2) {
ret = regmap_update_bits(rdev->regmap,
RK816_DCDC_EN_REG2,
RK816_BUCK_DVS_CONFIRM,
RK816_BUCK_DVS_CONFIRM);
if (ret)
return ret;
}
regmap_read(rdev->regmap,
rdev->desc->vsel_reg, &real_sel);
real_sel &= rdev->desc->vsel_mask;
delay--;
} while ((sel != real_sel) && (delay > 0));
if ((rk816_type != RK816_TYPE_ES2) && (id == 0))
rkclk_cpuclk_div_setting(1);
return ret;
}
static int rk808_buck1_2_set_voltage_sel(struct regulator_dev *rdev,
unsigned sel)
{
@@ -366,6 +439,11 @@ static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
RK808_RAMP_RATE_MASK, ramp_value);
}
static int rk8xx_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
{
return rk808_set_ramp_delay(rdev, ramp_delay);
}
/*
* RK817 RK809
*/
@@ -448,9 +526,61 @@ static int rk805_set_suspend_disable(struct regulator_dev *rdev)
0);
}
static int rk816_set_suspend_enable(struct regulator_dev *rdev)
{
unsigned int reg, val;
if (rdev->desc->id <= RK816_ID_DCDC4) {
reg = rdev->desc->enable_reg +
RK816_DCDC_SLP_EN_REG_OFFSET;
val = 1 << rdev->desc->id;
} else if ((rdev->desc->id > RK816_ID_DCDC4) &&
(rdev->desc->id <= RK816_ID_LDO4)) {
reg = rdev->desc->enable_reg -
RK816_LDO1_4_SLP_EN_REG_OFFSET;
val = 1 << (rdev->desc->id - RK816_ID_LDO1);
} else {
reg = rdev->desc->enable_reg -
RK816_LDO5_6_SLP_EN_REG_OFFSET;
val = 1 << (rdev->desc->id - RK816_ID_LDO1);
}
return regmap_update_bits(rdev->regmap, reg,
val,
val);
}
static int rk816_set_suspend_disable(struct regulator_dev *rdev)
{
unsigned int reg, val;
if (rdev->desc->id <= RK816_ID_DCDC4) {
reg = rdev->desc->enable_reg +
RK816_DCDC_SLP_EN_REG_OFFSET;
val = 1 << rdev->desc->id;
} else if ((rdev->desc->id > RK816_ID_DCDC4) &&
(rdev->desc->id <= RK816_ID_LDO4)) {
reg = rdev->desc->enable_reg -
RK816_LDO1_4_SLP_EN_REG_OFFSET;
val = 1 << (rdev->desc->id - RK816_ID_LDO1);
} else {
reg = rdev->desc->enable_reg -
RK816_LDO5_6_SLP_EN_REG_OFFSET;
val = 1 << (rdev->desc->id - RK816_ID_LDO1);
}
return regmap_update_bits(rdev->regmap, reg,
val,
0);
}
static int rk808_set_suspend_enable(struct regulator_dev *rdev)
{
unsigned int reg;
struct rk808 *rk808 = dev_get_drvdata(rdev->dev.parent);
if (rk808->variant == RK816_ID)
return rk816_set_suspend_enable(rdev);
reg = rdev->desc->enable_reg + RK808_SLP_SET_OFF_REG_OFFSET;
@@ -462,6 +592,10 @@ static int rk808_set_suspend_enable(struct regulator_dev *rdev)
static int rk808_set_suspend_disable(struct regulator_dev *rdev)
{
unsigned int reg;
struct rk808 *rk808 = dev_get_drvdata(rdev->dev.parent);
if (rk808->variant == RK816_ID)
return rk816_set_suspend_disable(rdev);
reg = rdev->desc->enable_reg + RK808_SLP_SET_OFF_REG_OFFSET;
@@ -631,6 +765,24 @@ static const struct regulator_ops rk808_buck1_2_ops = {
.set_suspend_disable = rk808_set_suspend_disable,
};
static const struct regulator_ops rk816_buck1_2_ops_ranges = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = rk816_regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.set_mode = rk8xx_set_mode,
.get_mode = rk8xx_get_mode,
.set_suspend_mode = rk8xx_set_suspend_mode,
.set_ramp_delay = rk8xx_set_ramp_delay,
.set_suspend_voltage = rk808_set_suspend_voltage_range,
.set_suspend_enable = rk808_set_suspend_enable,
.set_suspend_disable = rk808_set_suspend_disable,
};
static const struct regulator_ops rk808_reg_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
@@ -892,6 +1044,101 @@ static const struct regulator_desc rk808_reg[] = {
RK808_DCDC_EN_REG, BIT(6)),
};
static const struct regulator_desc rk816_reg[] = {
{
.name = "DCDC_REG1",
.supply_name = "vcc1",
.of_match = of_match_ptr("DCDC_REG1"),
.regulators_node = of_match_ptr("regulators"),
.id = RK816_ID_DCDC1,
.ops = &rk816_buck1_2_ops_ranges,
.type = REGULATOR_VOLTAGE,
.n_voltages = 64,
.linear_ranges = rk816_buck_voltage_ranges,
.n_linear_ranges = ARRAY_SIZE(rk816_buck_voltage_ranges),
.vsel_reg = RK816_BUCK1_ON_VSEL_REG,
.vsel_mask = RK818_BUCK_VSEL_MASK,
.enable_reg = RK816_DCDC_EN_REG1,
.enable_mask = BIT(4) | BIT(0),
.enable_val = BIT(4) | BIT(0),
.disable_val = BIT(4),
.of_map_mode = rk8xx_regulator_of_map_mode,
.owner = THIS_MODULE,
}, {
.name = "DCDC_REG2",
.supply_name = "vcc2",
.of_match = of_match_ptr("DCDC_REG2"),
.regulators_node = of_match_ptr("regulators"),
.id = RK816_ID_DCDC2,
.ops = &rk816_buck1_2_ops_ranges,
.type = REGULATOR_VOLTAGE,
.n_voltages = 64,
.linear_ranges = rk816_buck_voltage_ranges,
.n_linear_ranges = ARRAY_SIZE(rk816_buck_voltage_ranges),
.vsel_reg = RK816_BUCK2_ON_VSEL_REG,
.vsel_mask = RK818_BUCK_VSEL_MASK,
.enable_reg = RK816_DCDC_EN_REG1,
.enable_mask = BIT(5) | BIT(1),
.enable_val = BIT(5) | BIT(1),
.disable_val = BIT(5),
.of_map_mode = rk8xx_regulator_of_map_mode,
.owner = THIS_MODULE,
}, {
.name = "DCDC_REG3",
.supply_name = "vcc3",
.of_match = of_match_ptr("DCDC_REG3"),
.regulators_node = of_match_ptr("regulators"),
.id = RK818_ID_DCDC3,
.ops = &rk808_switch_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = 1,
.enable_reg = RK816_DCDC_EN_REG1,
.enable_mask = BIT(6) | BIT(2),
.enable_val = BIT(6) | BIT(2),
.disable_val = BIT(6),
.of_map_mode = rk8xx_regulator_of_map_mode,
.owner = THIS_MODULE,
}, {
.name = "DCDC_REG4",
.supply_name = "vcc4",
.of_match = of_match_ptr("DCDC_REG4"),
.regulators_node = of_match_ptr("regulators"),
.id = RK816_ID_DCDC4,
.ops = &rk808_reg_ops_ranges,
.type = REGULATOR_VOLTAGE,
.n_voltages = 32,
.linear_ranges = rk816_buck4_voltage_ranges,
.n_linear_ranges = ARRAY_SIZE(rk816_buck4_voltage_ranges),
.vsel_reg = RK816_BUCK4_ON_VSEL_REG,
.vsel_mask = RK818_BUCK4_VSEL_MASK,
.enable_reg = RK816_DCDC_EN_REG1,
.enable_mask = BIT(7) | BIT(3),
.enable_val = BIT(7) | BIT(3),
.disable_val = BIT(7),
.of_map_mode = rk8xx_regulator_of_map_mode,
.owner = THIS_MODULE,
},
RK816_DESC(RK816_ID_LDO1, "LDO_REG1", "vcc5", 800, 3400, 100,
RK816_LDO1_ON_VSEL_REG, RK818_LDO_VSEL_MASK,
RK816_LDO_EN_REG1, ENABLE_MASK(0), DISABLE_VAL(0), 400),
RK816_DESC(RK816_ID_LDO2, "LDO_REG2", "vcc5", 800, 3400, 100,
RK816_LDO2_ON_VSEL_REG, RK818_LDO_VSEL_MASK,
RK816_LDO_EN_REG1, ENABLE_MASK(1), DISABLE_VAL(1), 400),
RK816_DESC(RK816_ID_LDO3, "LDO_REG3", "vcc5", 800, 3400, 100,
RK816_LDO3_ON_VSEL_REG, RK818_LDO_VSEL_MASK,
RK816_LDO_EN_REG1, ENABLE_MASK(2), DISABLE_VAL(2), 400),
RK816_DESC(RK816_ID_LDO4, "LDO_REG4", "vcc6", 800, 3400, 100,
RK816_LDO4_ON_VSEL_REG, RK818_LDO_VSEL_MASK,
RK816_LDO_EN_REG1, ENABLE_MASK(3), DISABLE_VAL(3), 400),
RK816_DESC(RK816_ID_LDO5, "LDO_REG5", "vcc6", 800, 3400, 100,
RK816_LDO5_ON_VSEL_REG, RK818_LDO_VSEL_MASK,
RK816_LDO_EN_REG2, ENABLE_MASK(0), DISABLE_VAL(0), 400),
RK816_DESC(RK816_ID_LDO6, "LDO_REG6", "vcc6", 800, 3400, 100,
RK816_LDO6_ON_VSEL_REG, RK818_LDO_VSEL_MASK,
RK816_LDO_EN_REG2, ENABLE_MASK(1), DISABLE_VAL(1), 400),
};
static const struct regulator_desc rk809_reg[] = {
{
.name = "DCDC_REG1",
@@ -1331,6 +1578,10 @@ static int rk808_regulator_probe(struct platform_device *pdev)
regulators = rk809_reg;
nregulators = RK809_NUM_REGULATORS;
break;
case RK816_ID:
regulators = rk816_reg;
nregulators = RK816_NUM_REGULATORS;
break;
case RK817_ID:
regulators = rk817_reg;
nregulators = RK817_NUM_REGULATORS;
@@ -1372,7 +1623,7 @@ static struct platform_driver rk808_regulator_driver = {
module_platform_driver(rk808_regulator_driver);
MODULE_DESCRIPTION("regulator driver for the RK805/RK808/RK818 series PMICs");
MODULE_DESCRIPTION("regulator driver for the RK805/RK808/RK816/RK818 series PMICs");
MODULE_AUTHOR("Tony xie <tony.xie@rock-chips.com>");
MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");

View File

@@ -375,11 +375,11 @@ config RTC_DRV_MAX77686
will be called rtc-max77686.
config RTC_DRV_RK808
tristate "Rockchip RK805/RK808/RK809/RK817/RK818 RTC"
tristate "Rockchip RK805/RK808/RK809/RK816/RK817/RK818 RTC"
depends on MFD_RK808
help
If you say yes here you will get support for the
RTC of RK805, RK809 and RK817, RK808 and RK818 PMIC.
RTC of RK805, RK809 and RK817, RK808, RK816 and RK818 PMIC.
This driver can also be built as a module. If so, the module
will be called rk808-rtc.