[U-Boot] [PATCH v3 7/8] power: pmic: rk817: support rk817 pmic

Kever Yang kever.yang at rock-chips.com
Thu Sep 19 08:42:08 UTC 2019


On 2019/9/19 下午4:09, Elaine Zhang wrote:
> From: Joseph Chen <chenjh at rock-chips.com>
>
> The RK817 is a Power Management IC (PMIC) for multimedia
> and handheld devices. They contains the following components:
>      - Regulators(4*BUCKs, 1* BOOST, 9*LDOs, 1*SWITCH)
>      - RTC
>      - Clocking
>
> Signed-off-by: Joseph Chen <chenjh at rock-chips.com>
> Signed-off-by: Elaine Zhang <zhangqing at rock-chips.com>

Reviewed-by: Kever Yang<kever.yang at rock-chips.com>

Thanks,
- Kever
> ---
>   drivers/power/pmic/rk8xx.c      | 100 +++++++++++++++++++--
>   drivers/power/regulator/rk8xx.c | 189 +++++++++++++++++++++++++++++++++++++++-
>   include/power/rk8xx_pmic.h      |  31 +++++++
>   3 files changed, 308 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c
> index df2056913ced..0ec6cb31d706 100644
> --- a/drivers/power/pmic/rk8xx.c
> +++ b/drivers/power/pmic/rk8xx.c
> @@ -10,6 +10,13 @@
>   #include <power/rk8xx_pmic.h>
>   #include <power/pmic.h>
>   
> +static struct reg_data rk817_init_reg[] = {
> +/* enable the under-voltage protection,
> + * the under-voltage protection will shutdown the LDO3 and reset the PMIC
> + */
> +	{ RK817_BUCK4_CMIN, 0x60, 0x60},
> +};
> +
>   static const struct pmic_child_info pmic_children_info[] = {
>   	{ .prefix = "DCDC_REG", .driver = "rk8xx_buck"},
>   	{ .prefix = "LDO_REG", .driver = "rk8xx_ldo"},
> @@ -52,16 +59,22 @@ static int rk8xx_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
>   static int rk8xx_shutdown(struct udevice *dev)
>   {
>   	struct rk8xx_priv *priv = dev_get_priv(dev);
> -	u8 val, dev_off;
> +	u8 val, dev_off, devctrl_reg;
>   	int ret = 0;
>   
>   	switch (priv->variant) {
>   	case RK808_ID:
> +		devctrl_reg = REG_DEVCTRL;
>   		dev_off = BIT(3);
>   		break;
>   	case RK805_ID:
>   	case RK816_ID:
>   	case RK818_ID:
> +		devctrl_reg = REG_DEVCTRL;
> +		dev_off = BIT(0);
> +		break;
> +	case RK817_ID:
> +		devctrl_reg = RK817_REG_SYS_CFG3;
>   		dev_off = BIT(0);
>   		break;
>   	default:
> @@ -69,18 +82,18 @@ static int rk8xx_shutdown(struct udevice *dev)
>   		return -EINVAL;
>   	}
>   
> -	ret = dm_i2c_read(dev, REG_DEVCTRL, &val, 1);
> +	ret = dm_i2c_read(dev, devctrl_reg, &val, 1);
>   	if (ret) {
>   		printf("read error from device: %p register: %#x!",
> -		       dev, REG_DEVCTRL);
> +		       dev, devctrl_reg);
>   		return ret;
>   	}
>   
>   	val |= dev_off;
> -	ret = dm_i2c_write(dev, REG_DEVCTRL, &val, 1);
> +	ret = dm_i2c_write(dev, devctrl_reg, &val, 1);
>   	if (ret) {
>   		printf("write error to device: %p register: %#x!",
> -		       dev, REG_DEVCTRL);
> +		       dev, devctrl_reg);
>   		return ret;
>   	}
>   
> @@ -114,13 +127,83 @@ static int rk8xx_bind(struct udevice *dev)
>   static int rk8xx_probe(struct udevice *dev)
>   {
>   	struct rk8xx_priv *priv = dev_get_priv(dev);
> -	uint8_t msb, lsb;
> +	struct reg_data *init_data = NULL;
> +	int init_data_num = 0;
> +	int ret = 0, i, show_variant;
> +	u8 msb, lsb, id_msb, id_lsb;
> +	u8 on_source = 0, off_source = 0;
> +	u8 power_en0, power_en1, power_en2, power_en3;
> +	u8 value;
>   
>   	/* read Chip variant */
> -	rk8xx_read(dev, ID_MSB, &msb, 1);
> -	rk8xx_read(dev, ID_LSB, &lsb, 1);
> +	if (device_is_compatible(dev, "rockchip,rk817")) {
> +		id_msb = RK817_ID_MSB;
> +		id_lsb = RK817_ID_LSB;
> +	} else {
> +		id_msb = ID_MSB;
> +		id_lsb = ID_LSB;
> +	}
> +
> +	ret = rk8xx_read(dev, id_msb, &msb, 1);
> +	if (ret)
> +		return ret;
> +	ret = rk8xx_read(dev, id_lsb, &lsb, 1);
> +	if (ret)
> +		return ret;
>   
>   	priv->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
> +	show_variant = priv->variant;
> +	switch (priv->variant) {
> +	case RK808_ID:
> +		show_variant = 0x808;	/* RK808 hardware ID is 0 */
> +		break;
> +	case RK805_ID:
> +	case RK816_ID:
> +	case RK818_ID:
> +		on_source = RK8XX_ON_SOURCE;
> +		off_source = RK8XX_OFF_SOURCE;
> +		break;
> +	case RK817_ID:
> +		on_source = RK817_ON_SOURCE;
> +		off_source = RK817_OFF_SOURCE;
> +		init_data = rk817_init_reg;
> +		init_data_num = ARRAY_SIZE(rk817_init_reg);
> +		power_en0 = pmic_reg_read(dev, RK817_POWER_EN0);
> +		power_en1 = pmic_reg_read(dev, RK817_POWER_EN1);
> +		power_en2 = pmic_reg_read(dev, RK817_POWER_EN2);
> +		power_en3 = pmic_reg_read(dev, RK817_POWER_EN3);
> +
> +		value = (power_en0 & 0x0f) | ((power_en1 & 0x0f) << 4);
> +		pmic_reg_write(dev, RK817_POWER_EN_SAVE0, value);
> +		value = (power_en2 & 0x0f) | ((power_en3 & 0x0f) << 4);
> +		pmic_reg_write(dev, RK817_POWER_EN_SAVE1, value);
> +		break;
> +	default:
> +		printf("Unknown PMIC: RK%x!!\n", priv->variant);
> +		return -EINVAL;
> +	}
> +
> +	for (i = 0; i < init_data_num; i++) {
> +		ret = pmic_clrsetbits(dev,
> +				      init_data[i].reg,
> +				      init_data[i].mask,
> +				      init_data[i].val);
> +		if (ret < 0) {
> +			printf("%s: i2c set reg 0x%x failed, ret=%d\n",
> +			       __func__, init_data[i].reg, ret);
> +		}
> +
> +		debug("%s: reg[0x%x] = 0x%x\n", __func__, init_data[i].reg,
> +		      pmic_reg_read(dev, init_data[i].reg));
> +	}
> +
> +	printf("PMIC:  RK%x ", show_variant);
> +
> +	if (on_source && off_source)
> +		printf("(on=0x%02x, off=0x%02x)",
> +		       pmic_reg_read(dev, on_source),
> +		       pmic_reg_read(dev, off_source));
> +	printf("\n");
>   
>   	return 0;
>   }
> @@ -136,6 +219,7 @@ static const struct udevice_id rk8xx_ids[] = {
>   	{ .compatible = "rockchip,rk805" },
>   	{ .compatible = "rockchip,rk808" },
>   	{ .compatible = "rockchip,rk816" },
> +	{ .compatible = "rockchip,rk817" },
>   	{ .compatible = "rockchip,rk818" },
>   	{ }
>   };
> diff --git a/drivers/power/regulator/rk8xx.c b/drivers/power/regulator/rk8xx.c
> index e9d83635988b..3c4a18b0f0c7 100644
> --- a/drivers/power/regulator/rk8xx.c
> +++ b/drivers/power/regulator/rk8xx.c
> @@ -27,6 +27,21 @@
>   #define RK808_BUCK4_VSEL_MASK	0xf
>   #define RK808_LDO_VSEL_MASK	0x1f
>   
> +/* RK817 BUCK */
> +#define RK817_BUCK_ON_VSEL(n)		(0xbb + 3 * (n - 1))
> +#define RK817_BUCK_SLP_VSEL(n)		(0xbc + 3 * (n - 1))
> +#define RK817_BUCK_VSEL_MASK		0x7f
> +#define RK817_BUCK_CONFIG(i)		(0xba + (i) * 3)
> +
> +/* RK817 LDO */
> +#define RK817_LDO_ON_VSEL(n)		(0xcc + 2 * (n - 1))
> +#define RK817_LDO_SLP_VSEL(n)		(0xcd + 2 * (n - 1))
> +#define RK817_LDO_VSEL_MASK		0x7f
> +
> +/* RK817 ENABLE */
> +#define RK817_POWER_EN(n)		(0xb1 + (n))
> +#define RK817_POWER_SLP_EN(n)		(0xb5 + (n))
> +
>   #define RK818_BUCK_VSEL_MASK		0x3f
>   #define RK818_BUCK4_VSEL_MASK		0x1f
>   #define RK818_LDO_VSEL_MASK		0x1f
> @@ -45,13 +60,19 @@
>   #define RK805_RAMP_RATE_12_5MV_PER_US	(2 << RK805_RAMP_RATE_OFFSET)
>   #define RK805_RAMP_RATE_25MV_PER_US	(3 << RK805_RAMP_RATE_OFFSET)
>   #define RK808_RAMP_RATE_OFFSET		3
> -
>   #define RK808_RAMP_RATE_MASK		(3 << RK808_RAMP_RATE_OFFSET)
>   #define RK808_RAMP_RATE_2MV_PER_US	(0 << RK808_RAMP_RATE_OFFSET)
>   #define RK808_RAMP_RATE_4MV_PER_US	(1 << RK808_RAMP_RATE_OFFSET)
>   #define RK808_RAMP_RATE_6MV_PER_US	(2 << RK808_RAMP_RATE_OFFSET)
>   #define RK808_RAMP_RATE_10MV_PER_US	(3 << RK808_RAMP_RATE_OFFSET)
>   
> +#define RK817_RAMP_RATE_OFFSET		6
> +#define RK817_RAMP_RATE_MASK		(0x3 << RK817_RAMP_RATE_OFFSET)
> +#define RK817_RAMP_RATE_3MV_PER_US	(0x0 << RK817_RAMP_RATE_OFFSET)
> +#define RK817_RAMP_RATE_6_3MV_PER_US	(0x1 << RK817_RAMP_RATE_OFFSET)
> +#define RK817_RAMP_RATE_12_5MV_PER_US	(0x2 << RK817_RAMP_RATE_OFFSET)
> +#define RK817_RAMP_RATE_25MV_PER_US	(0x3 << RK817_RAMP_RATE_OFFSET)
> +
>   struct rk8xx_reg_info {
>   	uint min_uv;
>   	uint step_uv;
> @@ -84,6 +105,25 @@ static const struct rk8xx_reg_info rk816_buck[] = {
>   	{  800000, 100000, REG_BUCK4_ON_VSEL, REG_BUCK4_SLP_VSEL, REG_BUCK4_CONFIG, RK818_BUCK4_VSEL_MASK, },
>   };
>   
> +static const struct rk8xx_reg_info rk817_buck[] = {
> +	/* buck 1 */
> +	{  500000,  12500, RK817_BUCK_ON_VSEL(1), RK817_BUCK_SLP_VSEL(1), RK817_BUCK_CONFIG(1), RK817_BUCK_VSEL_MASK, 0x00, },
> +	{ 1500000, 100000, RK817_BUCK_ON_VSEL(1), RK817_BUCK_SLP_VSEL(1), RK817_BUCK_CONFIG(1), RK817_BUCK_VSEL_MASK, 0x50, },
> +	{ 2400000,	0, RK817_BUCK_ON_VSEL(1), RK817_BUCK_SLP_VSEL(1), RK817_BUCK_CONFIG(1), RK817_BUCK_VSEL_MASK, 0x59, },
> +	/* buck 2 */
> +	{  500000,  12500, RK817_BUCK_ON_VSEL(2), RK817_BUCK_SLP_VSEL(2), RK817_BUCK_CONFIG(2), RK817_BUCK_VSEL_MASK, 0x00, },
> +	{ 1500000, 100000, RK817_BUCK_ON_VSEL(2), RK817_BUCK_SLP_VSEL(2), RK817_BUCK_CONFIG(2), RK817_BUCK_VSEL_MASK, 0x50, },
> +	{ 2400000,	0, RK817_BUCK_ON_VSEL(2), RK817_BUCK_SLP_VSEL(2), RK817_BUCK_CONFIG(2), RK817_BUCK_VSEL_MASK, 0x59, },
> +	/* buck 3 */
> +	{  500000,  12500, RK817_BUCK_ON_VSEL(3), RK817_BUCK_SLP_VSEL(3), RK817_BUCK_CONFIG(3), RK817_BUCK_VSEL_MASK, 0x00, },
> +	{ 1500000, 100000, RK817_BUCK_ON_VSEL(3), RK817_BUCK_SLP_VSEL(3), RK817_BUCK_CONFIG(3), RK817_BUCK_VSEL_MASK, 0x50, },
> +	{ 2400000,	0, RK817_BUCK_ON_VSEL(3), RK817_BUCK_SLP_VSEL(3), RK817_BUCK_CONFIG(3), RK817_BUCK_VSEL_MASK, 0x59, },
> +	/* buck 4 */
> +	{  500000,  12500, RK817_BUCK_ON_VSEL(4), RK817_BUCK_SLP_VSEL(4), RK817_BUCK_CONFIG(4), RK817_BUCK_VSEL_MASK, 0x00, },
> +	{ 1500000, 100000, RK817_BUCK_ON_VSEL(4), RK817_BUCK_SLP_VSEL(4), RK817_BUCK_CONFIG(4), RK817_BUCK_VSEL_MASK, 0x50, },
> +	{ 3400000,	0, RK817_BUCK_ON_VSEL(4), RK817_BUCK_SLP_VSEL(4), RK817_BUCK_CONFIG(4), RK817_BUCK_VSEL_MASK, 0x63, },
> +};
> +
>   static const struct rk8xx_reg_info rk818_buck[] = {
>   	{ 712500,   12500, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK818_BUCK_VSEL_MASK, },
>   	{ 712500,   12500, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK818_BUCK_VSEL_MASK, },
> @@ -112,6 +152,36 @@ static const struct rk8xx_reg_info rk816_ldo[] = {
>   	{ 800000, 100000, REG_LDO6_ON_VSEL, REG_LDO6_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
>   };
>   
> +static const struct rk8xx_reg_info rk817_ldo[] = {
> +	/* ldo1 */
> +	{  600000, 25000, RK817_LDO_ON_VSEL(1), RK817_LDO_SLP_VSEL(1), NA, RK817_LDO_VSEL_MASK, 0x00, },
> +	{ 3400000,     0, RK817_LDO_ON_VSEL(1), RK817_LDO_SLP_VSEL(1), NA, RK817_LDO_VSEL_MASK, 0x70, },
> +	/* ldo2 */
> +	{  600000, 25000, RK817_LDO_ON_VSEL(2), RK817_LDO_SLP_VSEL(2), NA, RK817_LDO_VSEL_MASK, 0x00, },
> +	{ 3400000,     0, RK817_LDO_ON_VSEL(2), RK817_LDO_SLP_VSEL(2), NA, RK817_LDO_VSEL_MASK, 0x70, },
> +	/* ldo3 */
> +	{  600000, 25000, RK817_LDO_ON_VSEL(3), RK817_LDO_SLP_VSEL(3), NA, RK817_LDO_VSEL_MASK, 0x00, },
> +	{ 3400000,     0, RK817_LDO_ON_VSEL(3), RK817_LDO_SLP_VSEL(3), NA, RK817_LDO_VSEL_MASK, 0x70, },
> +	/* ldo4 */
> +	{  600000, 25000, RK817_LDO_ON_VSEL(4), RK817_LDO_SLP_VSEL(4), NA, RK817_LDO_VSEL_MASK, 0x00, },
> +	{ 3400000,     0, RK817_LDO_ON_VSEL(4), RK817_LDO_SLP_VSEL(4), NA, RK817_LDO_VSEL_MASK, 0x70, },
> +	/* ldo5 */
> +	{  600000, 25000, RK817_LDO_ON_VSEL(5), RK817_LDO_SLP_VSEL(5), NA, RK817_LDO_VSEL_MASK, 0x00, },
> +	{ 3400000,     0, RK817_LDO_ON_VSEL(5), RK817_LDO_SLP_VSEL(5), NA, RK817_LDO_VSEL_MASK, 0x70, },
> +	/* ldo6 */
> +	{  600000, 25000, RK817_LDO_ON_VSEL(6), RK817_LDO_SLP_VSEL(6), NA, RK817_LDO_VSEL_MASK, 0x00, },
> +	{ 3400000,     0, RK817_LDO_ON_VSEL(6), RK817_LDO_SLP_VSEL(6), NA, RK817_LDO_VSEL_MASK, 0x70, },
> +	/* ldo7 */
> +	{  600000, 25000, RK817_LDO_ON_VSEL(7), RK817_LDO_SLP_VSEL(7), NA, RK817_LDO_VSEL_MASK, 0x00, },
> +	{ 3400000,     0, RK817_LDO_ON_VSEL(7), RK817_LDO_SLP_VSEL(7), NA, RK817_LDO_VSEL_MASK, 0x70, },
> +	/* ldo8 */
> +	{  600000, 25000, RK817_LDO_ON_VSEL(8), RK817_LDO_SLP_VSEL(8), NA, RK817_LDO_VSEL_MASK, 0x00, },
> +	{ 3400000,     0, RK817_LDO_ON_VSEL(8), RK817_LDO_SLP_VSEL(8), NA, RK817_LDO_VSEL_MASK, 0x70, },
> +	/* ldo9 */
> +	{  600000, 25000, RK817_LDO_ON_VSEL(9), RK817_LDO_SLP_VSEL(9), NA, RK817_LDO_VSEL_MASK, 0x00, },
> +	{ 3400000,     0, RK817_LDO_ON_VSEL(9), RK817_LDO_SLP_VSEL(9), NA, RK817_LDO_VSEL_MASK, 0x70, },
> +};
> +
>   static const struct rk8xx_reg_info rk818_ldo[] = {
>   	{ 1800000, 100000, REG_LDO1_ON_VSEL, REG_LDO1_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
>   	{ 1800000, 100000, REG_LDO2_ON_VSEL, REG_LDO2_SLP_VSEL, NA, RK818_LDO_VSEL_MASK, },
> @@ -152,6 +222,24 @@ static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic,
>   		default:
>   			return &rk816_buck[num + 4];
>   		}
> +
> +	case RK817_ID:
> +		switch (num) {
> +		case 0 ... 2:
> +			if (uvolt < 1500000)
> +				return &rk817_buck[num * 3 + 0];
> +			else if (uvolt < 2400000)
> +				return &rk817_buck[num * 3 + 1];
> +			else
> +				return &rk817_buck[num * 3 + 2];
> +		case 3:
> +			if (uvolt < 1500000)
> +				return &rk817_buck[num * 3 + 0];
> +			else if (uvolt < 3400000)
> +				return &rk817_buck[num * 3 + 1];
> +			else
> +				return &rk817_buck[num * 3 + 2];
> +		}
>   	case RK818_ID:
>   		return &rk818_buck[num];
>   	default:
> @@ -189,7 +277,7 @@ static int _buck_set_value(struct udevice *pmic, int buck, int uvolt)
>   static int _buck_set_enable(struct udevice *pmic, int buck, bool enable)
>   {
>   	uint mask, value, en_reg;
> -	int ret;
> +	int ret = 0;
>   	struct rk8xx_priv *priv = dev_get_priv(pmic);
>   
>   	switch (priv->variant) {
> @@ -220,6 +308,15 @@ static int _buck_set_enable(struct udevice *pmic, int buck, bool enable)
>   		ret = pmic_clrsetbits(pmic, REG_DCDC_EN, mask,
>   				      enable ? mask : 0);
>   		break;
> +	case RK817_ID:
> +		if (buck < 4) {
> +			if (enable)
> +				value = ((1 << buck) | (1 << (buck + 4)));
> +			else
> +				value = ((0 << buck) | (1 << (buck + 4)));
> +			ret = pmic_reg_write(pmic, RK817_POWER_EN(0), value);
> +		}
> +		break;
>   	default:
>   		ret = -EINVAL;
>   	}
> @@ -272,6 +369,12 @@ static int _buck_get_enable(struct udevice *pmic, int buck)
>   		if (ret < 0)
>   			return ret;
>   		break;
> +	case RK817_ID:
> +		if (buck < 4) {
> +			mask = 1 << buck;
> +			ret = pmic_reg_read(pmic, RK817_POWER_EN(0));
> +		}
> +		break;
>   	}
>   
>   	if (ret < 0)
> @@ -282,7 +385,7 @@ static int _buck_get_enable(struct udevice *pmic, int buck)
>   
>   static int _buck_set_suspend_enable(struct udevice *pmic, int buck, bool enable)
>   {
> -	uint mask;
> +	uint mask = 0;
>   	int ret;
>   	struct rk8xx_priv *priv = dev_get_priv(pmic);
>   
> @@ -299,6 +402,12 @@ static int _buck_set_suspend_enable(struct udevice *pmic, int buck, bool enable)
>   		ret = pmic_clrsetbits(pmic, REG_SLEEP_SET_OFF1, mask,
>   				      enable ? 0 : mask);
>   		break;
> +	case RK817_ID:
> +		if (buck < 4)
> +			mask = 1 << buck;
> +		ret = pmic_clrsetbits(pmic, RK817_POWER_SLP_EN(0), mask,
> +				      enable ? mask : 0);
> +		break;
>   	default:
>   		ret = -EINVAL;
>   	}
> @@ -310,7 +419,7 @@ static int _buck_get_suspend_enable(struct udevice *pmic, int buck)
>   {
>   	struct rk8xx_priv *priv = dev_get_priv(pmic);
>   	int ret, val;
> -	uint mask;
> +	uint mask = 0;
>   
>   	switch (priv->variant) {
>   	case RK805_ID:
> @@ -329,6 +438,15 @@ static int _buck_get_suspend_enable(struct udevice *pmic, int buck)
>   			return val;
>   		ret = val & mask ? 0 : 1;
>   		break;
> +	case RK817_ID:
> +		if (buck < 4)
> +			mask = 1 << buck;
> +
> +		val = pmic_reg_read(pmic, RK817_POWER_SLP_EN(0));
> +		if (val < 0)
> +			return val;
> +		ret = val & mask ? 1 : 0;
> +		break;
>   	default:
>   		ret = -EINVAL;
>   	}
> @@ -345,6 +463,11 @@ static const struct rk8xx_reg_info *get_ldo_reg(struct udevice *pmic,
>   	case RK805_ID:
>   	case RK816_ID:
>   		return &rk816_ldo[num];
> +	case RK817_ID:
> +		if (uvolt < 3400000)
> +			return &rk817_ldo[num * 2 + 0];
> +		else
> +			return &rk817_ldo[num * 2 + 1];
>   	case RK818_ID:
>   		return &rk818_ldo[num];
>   	default:
> @@ -376,6 +499,20 @@ static int _ldo_get_enable(struct udevice *pmic, int ldo)
>   		if (ret < 0)
>   			return ret;
>   		break;
> +	case RK817_ID:
> +		if (ldo < 4) {
> +			mask = 1 << ldo;
> +			ret = pmic_reg_read(pmic, RK817_POWER_EN(1));
> +		} else if (ldo < 8) {
> +			mask = 1 << (ldo - 4);
> +			ret = pmic_reg_read(pmic, RK817_POWER_EN(2));
> +		} else if (ldo == 8) {
> +			mask = 1 << 0;
> +			ret = pmic_reg_read(pmic, RK817_POWER_EN(3));
> +		} else {
> +			return false;
> +		}
> +		break;
>   	}
>   
>   	if (ret < 0)
> @@ -413,6 +550,24 @@ static int _ldo_set_enable(struct udevice *pmic, int ldo, bool enable)
>   		ret = pmic_clrsetbits(pmic, REG_LDO_EN, mask,
>   				       enable ? mask : 0);
>   		break;
> +	case RK817_ID:
> +		if (ldo < 4) {
> +			en_reg = RK817_POWER_EN(1);
> +		} else if (ldo < 8) {
> +			ldo -= 4;
> +			en_reg = RK817_POWER_EN(2);
> +		} else if (ldo == 8) {
> +			ldo = 0;	/* BIT 0 */
> +			en_reg = RK817_POWER_EN(3);
> +		} else {
> +			return -EINVAL;
> +		}
> +		if (enable)
> +			value = ((1 << ldo) | (1 << (ldo + 4)));
> +		else
> +			value = ((0 << ldo) | (1 << (ldo + 4)));
> +		ret = pmic_reg_write(pmic, en_reg, value);
> +		break;
>   	}
>   
>   	return ret;
> @@ -437,6 +592,17 @@ static int _ldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable)
>   		ret = pmic_clrsetbits(pmic, REG_SLEEP_SET_OFF2, mask,
>   				      enable ? 0 : mask);
>   		break;
> +	case RK817_ID:
> +		if (ldo == 8) {
> +			mask = 1 << 4;	/* LDO9 */
> +			ret = pmic_clrsetbits(pmic, RK817_POWER_SLP_EN(0), mask,
> +					      enable ? mask : 0);
> +		} else {
> +			mask = 1 << ldo;
> +			ret = pmic_clrsetbits(pmic, RK817_POWER_SLP_EN(1), mask,
> +					      enable ? mask : 0);
> +		}
> +		break;
>   	}
>   
>   	return ret;
> @@ -465,6 +631,21 @@ static int _ldo_get_suspend_enable(struct udevice *pmic, int ldo)
>   			return val;
>   		ret = val & mask ? 0 : 1;
>   		break;
> +	case RK817_ID:
> +		if (ldo == 8) {
> +			mask = 1 << 4;	/* LDO9 */
> +			val = pmic_reg_read(pmic, RK817_POWER_SLP_EN(0));
> +			if (val < 0)
> +				return val;
> +			ret = val & mask ? 1 : 0;
> +		} else {
> +			mask = 1 << ldo;
> +			val = pmic_reg_read(pmic, RK817_POWER_SLP_EN(1));
> +			if (val < 0)
> +				return val;
> +			ret = val & mask ? 1 : 0;
> +		}
> +		break;
>   	}
>   
>   	return ret;
> diff --git a/include/power/rk8xx_pmic.h b/include/power/rk8xx_pmic.h
> index 7784c2a5e473..d93cecedddf7 100644
> --- a/include/power/rk8xx_pmic.h
> +++ b/include/power/rk8xx_pmic.h
> @@ -170,6 +170,10 @@ enum {
>   };
>   
>   enum {
> +	RK817_REG_SYS_CFG3 = 0xf4,
> +};
> +
> +enum {
>   	RK816_REG_DCDC_EN1 = 0x23,
>   	RK816_REG_DCDC_EN2,
>   	RK816_REG_DCDC_SLP_EN,
> @@ -182,11 +186,38 @@ enum {
>   	RK805_ID = 0x8050,
>   	RK808_ID = 0x0000,
>   	RK816_ID = 0x8160,
> +	RK817_ID = 0x8170,
>   	RK818_ID = 0x8180,
>   };
>   
> +enum {
> +	RK817_POWER_EN0 = 0xb1,
> +	RK817_POWER_EN1,
> +	RK817_POWER_EN2,
> +	RK817_POWER_EN3,
> +};
> +
> +#define RK817_POWER_EN_SAVE0	0x99
> +#define RK817_POWER_EN_SAVE1	0xa4
> +
> +#define RK817_ID_MSB	0xed
> +#define RK817_ID_LSB	0xee
>   #define RK8XX_ID_MSK	0xfff0
>   
> +#define RK817_PMIC_SYS_CFG3	0xf4
> +#define RK817_GPIO_INT_CFG	0xfe
> +
> +#define RK8XX_ON_SOURCE		0xae
> +#define RK8XX_OFF_SOURCE	0xaf
> +#define RK817_BUCK4_CMIN	0xc6
> +#define RK817_ON_SOURCE		0xf5
> +#define RK817_OFF_SOURCE	0xf6
> +
> +struct reg_data {
> +	u8 reg;
> +	u8 val;
> +	u8 mask;
> +};
>   struct rk8xx_reg_table {
>   	char *name;
>   	u8 reg_ctl;




More information about the U-Boot mailing list