mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
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:
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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>");
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user