xref: /rk3399_rockchip-uboot/drivers/power/pmic/pmic_rk801.c (revision b3317784154ac42522f6d3f9ab17aa2bd2c25028)
12690619bSJoseph Chen /*
22690619bSJoseph Chen  * (C) Copyright 2024 Rockchip Electronics Co., Ltd.
32690619bSJoseph Chen  *
42690619bSJoseph Chen  * SPDX-License-Identifier:     GPL-2.0+
52690619bSJoseph Chen  */
62690619bSJoseph Chen 
72690619bSJoseph Chen #include <common.h>
82690619bSJoseph Chen #include <dm.h>
92690619bSJoseph Chen #include <errno.h>
102690619bSJoseph Chen #include <irq-generic.h>
112690619bSJoseph Chen #include <power/rk801_pmic.h>
122690619bSJoseph Chen #include <power/pmic.h>
132690619bSJoseph Chen 
142690619bSJoseph Chen DECLARE_GLOBAL_DATA_PTR;
152690619bSJoseph Chen 
162690619bSJoseph Chen #if CONFIG_IS_ENABLED(IRQ)
172690619bSJoseph Chen static const struct virq_reg rk801_irqs[] = {
182690619bSJoseph Chen 	[RK801_IRQ_PWRON_FALL] = {
192690619bSJoseph Chen 		.mask = RK801_IRQ_PWRON_FALL_MSK,
202690619bSJoseph Chen 		.reg_offset = 0,
212690619bSJoseph Chen 	},
222690619bSJoseph Chen 	[RK801_IRQ_PWRON_RISE] = {
232690619bSJoseph Chen 		.mask = RK801_IRQ_PWRON_RISE_MSK,
242690619bSJoseph Chen 		.reg_offset = 0,
252690619bSJoseph Chen 	},
262690619bSJoseph Chen };
272690619bSJoseph Chen 
282690619bSJoseph Chen static struct virq_chip rk801_irq_chip = {
292690619bSJoseph Chen 	.status_base    = RK801_INT_STS0_REG,
302690619bSJoseph Chen 	.mask_base	= RK801_INT_STS0_REG,
312690619bSJoseph Chen 	.num_regs	= 1,
322690619bSJoseph Chen 	.read		= pmic_reg_read,
332690619bSJoseph Chen 	.write		= pmic_reg_write,
342690619bSJoseph Chen 	.irqs		= rk801_irqs,
352690619bSJoseph Chen 	.num_irqs	= ARRAY_SIZE(rk801_irqs),
362690619bSJoseph Chen };
372690619bSJoseph Chen #endif
382690619bSJoseph Chen 
392690619bSJoseph Chen static struct reg_data rk801_init_reg[] = {
402690619bSJoseph Chen 	{ RK801_SLEEP_CFG_REG, RK801_NONE_FUN, RK801_SLEEP_FUN_MSK },
412b3603a8SJoseph Chen 	{ RK801_SYS_CFG2_REG, RK801_RST_RESTART_REG, RK801_RST_MSK },
422690619bSJoseph Chen 	{ RK801_INT_CONFIG_REG, RK801_INT_ACT_L, RK801_INT_POL_MSK },
432690619bSJoseph Chen 	{ RK801_POWER_FPWM_EN_REG, RK801_PLDO_HRDEC_EN, RK801_PLDO_HRDEC_EN },
442690619bSJoseph Chen 	{ RK801_BUCK_DEBUG5_REG, 0x54, 0xff },
452690619bSJoseph Chen 	{ RK801_CON_BACK1_REG, 0x18, 0xff },
462690619bSJoseph Chen };
472690619bSJoseph Chen 
482690619bSJoseph Chen static const struct pmic_child_info pmic_children_info[] = {
492690619bSJoseph Chen 	{ .prefix = "DCDC", .driver = "rk801_buck"},
502690619bSJoseph Chen 	{ .prefix = "LDO", .driver = "rk801_ldo"},
512690619bSJoseph Chen 	{ .prefix = "SWITCH", .driver = "rk801_switch"},
522690619bSJoseph Chen 	{ },
532690619bSJoseph Chen };
542690619bSJoseph Chen 
552690619bSJoseph Chen static const struct pmic_child_info power_key_info[] = {
562690619bSJoseph Chen 	{ .prefix = "pwrkey", .driver = "rk8xx_pwrkey"},
572690619bSJoseph Chen 	{ },
582690619bSJoseph Chen };
592690619bSJoseph Chen 
rk801_reg_count(struct udevice * dev)602690619bSJoseph Chen static int rk801_reg_count(struct udevice *dev)
612690619bSJoseph Chen {
622690619bSJoseph Chen 	return RK801_SYS_CFG3_OTP_REG + 1;
632690619bSJoseph Chen }
642690619bSJoseph Chen 
rk801_write(struct udevice * dev,uint reg,const uint8_t * buff,int len)652690619bSJoseph Chen static int rk801_write(struct udevice *dev, uint reg, const uint8_t *buff, int len)
662690619bSJoseph Chen {
672690619bSJoseph Chen 	int ret;
682690619bSJoseph Chen 
692690619bSJoseph Chen 	ret = dm_i2c_write(dev, reg, buff, len);
702690619bSJoseph Chen 	if (ret) {
712690619bSJoseph Chen 		printf("rk801: write reg 0x%02x failed, ret=%d\n", reg, ret);
722690619bSJoseph Chen 		return ret;
732690619bSJoseph Chen 	}
742690619bSJoseph Chen 
752690619bSJoseph Chen 	return 0;
762690619bSJoseph Chen }
772690619bSJoseph Chen 
rk801_read(struct udevice * dev,uint reg,uint8_t * buff,int len)782690619bSJoseph Chen static int rk801_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
792690619bSJoseph Chen {
802690619bSJoseph Chen 	int ret;
812690619bSJoseph Chen 
822690619bSJoseph Chen 	ret = dm_i2c_read(dev, reg, buff, len);
832690619bSJoseph Chen 	if (ret) {
842690619bSJoseph Chen 		printf("rk801: read reg 0x%02x failed, ret=%d\n", reg, ret);
852690619bSJoseph Chen 		return ret;
862690619bSJoseph Chen 	}
872690619bSJoseph Chen 
882690619bSJoseph Chen 	return 0;
892690619bSJoseph Chen }
902690619bSJoseph Chen 
rk801_shutdown(struct udevice * dev)912690619bSJoseph Chen static int rk801_shutdown(struct udevice *dev)
922690619bSJoseph Chen {
932690619bSJoseph Chen 	int ret;
942690619bSJoseph Chen 	u8 val;
952690619bSJoseph Chen 
962690619bSJoseph Chen 	ret = rk801_read(dev, RK801_SYS_CFG2_REG, &val, 1);
972690619bSJoseph Chen 	if (ret)
982690619bSJoseph Chen 		return ret;
992690619bSJoseph Chen 
1002690619bSJoseph Chen 	val |= DEV_OFF;
1012690619bSJoseph Chen 
1022690619bSJoseph Chen 	return rk801_write(dev, RK801_SYS_CFG2_REG, &val, 1);
1032690619bSJoseph Chen }
1042690619bSJoseph Chen 
1052690619bSJoseph Chen #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
rk801_bind(struct udevice * dev)1062690619bSJoseph Chen static int rk801_bind(struct udevice *dev)
1072690619bSJoseph Chen {
1082690619bSJoseph Chen 	ofnode regulators_node;
1092690619bSJoseph Chen 	int children;
1102690619bSJoseph Chen 
1112690619bSJoseph Chen 	regulators_node = dev_read_subnode(dev, "regulators");
1122690619bSJoseph Chen 	if (!ofnode_valid(regulators_node))
1132690619bSJoseph Chen 		return -ENXIO;
1142690619bSJoseph Chen 
1152690619bSJoseph Chen 	children = pmic_bind_children(dev, regulators_node, pmic_children_info);
1162690619bSJoseph Chen 	if (!children)
1172690619bSJoseph Chen 		debug("%s: %s - no child found\n", __func__, dev->name);
1182690619bSJoseph Chen 
1192690619bSJoseph Chen 	children = pmic_bind_children(dev, dev->node, power_key_info);
1202690619bSJoseph Chen 	if (!children)
1212690619bSJoseph Chen 		debug("%s: %s - no child found\n", __func__, dev->name);
1222690619bSJoseph Chen 
1232690619bSJoseph Chen 	return 0;
1242690619bSJoseph Chen }
1252690619bSJoseph Chen #endif
1262690619bSJoseph Chen 
rk801_ofdata_to_platdata(struct udevice * dev)1272690619bSJoseph Chen static int rk801_ofdata_to_platdata(struct udevice *dev)
1282690619bSJoseph Chen {
1292690619bSJoseph Chen #if CONFIG_IS_ENABLED(IRQ)
1302690619bSJoseph Chen 	struct rk801_priv *priv = dev_get_priv(dev);
1312690619bSJoseph Chen 	u32 interrupt, phandle;
1322690619bSJoseph Chen 	int ret;
1332690619bSJoseph Chen 
1342690619bSJoseph Chen 	phandle = dev_read_u32_default(dev, "interrupt-parent", -ENODATA);
1352690619bSJoseph Chen 	if (phandle == -ENODATA) {
1362690619bSJoseph Chen 		printf("Read 'interrupt-parent' failed, ret=%d\n", phandle);
1372690619bSJoseph Chen 		return phandle;
1382690619bSJoseph Chen 	}
1392690619bSJoseph Chen 
1402690619bSJoseph Chen 	ret = dev_read_u32_array(dev, "interrupts", &interrupt, 1);
1412690619bSJoseph Chen 	if (ret) {
1422690619bSJoseph Chen 		printf("Read 'interrupts' failed, ret=%d\n", ret);
1432690619bSJoseph Chen 		return ret;
1442690619bSJoseph Chen 	}
1452690619bSJoseph Chen 
1462690619bSJoseph Chen 	priv->irq = phandle_gpio_to_irq(phandle, interrupt);
1472690619bSJoseph Chen 	if (priv->irq < 0) {
1482690619bSJoseph Chen 		printf("priv to request rk801 irq, ret=%d\n", priv->irq);
1492690619bSJoseph Chen 		return priv->irq;
1502690619bSJoseph Chen 	}
1512690619bSJoseph Chen #endif
1522690619bSJoseph Chen 
1532690619bSJoseph Chen 	return 0;
1542690619bSJoseph Chen }
1552690619bSJoseph Chen 
rk801_probe(struct udevice * dev)1562690619bSJoseph Chen static int rk801_probe(struct udevice *dev)
1572690619bSJoseph Chen {
1582690619bSJoseph Chen 	struct rk801_priv *priv = dev_get_priv(dev);
1592690619bSJoseph Chen 	uint8_t msb, lsb, on, off;
160*b3317784SJoseph Chen 	u32 pmic_id;
1612690619bSJoseph Chen 	int i, ret;
1622690619bSJoseph Chen 
1632690619bSJoseph Chen 	ret = rk801_read(dev, RK801_ID_MSB, &msb, 1);
1642690619bSJoseph Chen 	if (ret)
1652690619bSJoseph Chen 		return ret;
1662690619bSJoseph Chen 
1672690619bSJoseph Chen 	ret = rk801_read(dev, RK801_ID_LSB, &lsb, 1);
1682690619bSJoseph Chen 	if (ret)
1692690619bSJoseph Chen 		return ret;
1702690619bSJoseph Chen 
171*b3317784SJoseph Chen 	pmic_id = (msb << 8) | lsb;
172*b3317784SJoseph Chen 	priv->variant = pmic_id & RK8XX_ID_MSK;
17305cdba35SJoseph Chen 	priv->req_pwrctrl_dvs = (lsb & 0x0f) < 3;
1742690619bSJoseph Chen 	if (priv->req_pwrctrl_dvs) {
1755e8035f6SJoseph Chen 		/* GPIOD_IS_OUT: output inactive */
1762690619bSJoseph Chen 		ret = gpio_request_by_name(dev, "pwrctrl-gpios", 0,
1772690619bSJoseph Chen 					   &priv->pwrctrl_gpio, GPIOD_IS_OUT);
1782690619bSJoseph Chen 		if (ret) {
179*b3317784SJoseph Chen 			printf("rk801: failed to get pwrctrl-gpio, ret=%d\n", ret);
1802690619bSJoseph Chen 			return ret;
1812690619bSJoseph Chen 		}
1822690619bSJoseph Chen 	}
1832690619bSJoseph Chen 
184*b3317784SJoseph Chen 	rk801_read(dev, RK801_ON_SOURCE_REG, &on, 1);
185*b3317784SJoseph Chen 	rk801_read(dev, RK801_OFF_SOURCE_REG, &off, 1);
186*b3317784SJoseph Chen 
187*b3317784SJoseph Chen 	printf("PMIC:  RK%x (on=0x%02x, off=0x%02x, req_dvs: %d, act: %s)\n",
188*b3317784SJoseph Chen 	       pmic_id, on, off, priv->req_pwrctrl_dvs,
189*b3317784SJoseph Chen 	       priv->pwrctrl_gpio.flags & GPIOD_ACTIVE_LOW ? "low" : "high");
190*b3317784SJoseph Chen 
1912690619bSJoseph Chen 	for (i = 0; i < ARRAY_SIZE(rk801_init_reg); i++) {
1922690619bSJoseph Chen 		ret = pmic_clrsetbits(dev,
1932690619bSJoseph Chen 				      rk801_init_reg[i].reg,
1942690619bSJoseph Chen 				      rk801_init_reg[i].mask,
1952690619bSJoseph Chen 				      rk801_init_reg[i].val);
1962690619bSJoseph Chen 		if (ret < 0) {
1972690619bSJoseph Chen 			printf("rk801: set reg 0x%x failed, ret=%d\n",
1982690619bSJoseph Chen 			       rk801_init_reg[i].reg, ret);
1992690619bSJoseph Chen 		}
2002690619bSJoseph Chen 	}
2012690619bSJoseph Chen 
2022690619bSJoseph Chen #if CONFIG_IS_ENABLED(IRQ)
2032690619bSJoseph Chen 	priv->irq_chip = &rk801_irq_chip;
2042690619bSJoseph Chen 	ret = virq_add_chip(dev, priv->irq_chip, priv->irq);
2052690619bSJoseph Chen 	if (ret) {
2062690619bSJoseph Chen 		printf("rk801: failed to add irqchip(irq=%d), ret=%d\n",
2072690619bSJoseph Chen 		       priv->irq, ret);
2082690619bSJoseph Chen 		return ret;
2092690619bSJoseph Chen 	}
2102690619bSJoseph Chen #endif
2112690619bSJoseph Chen 	return 0;
2122690619bSJoseph Chen }
2132690619bSJoseph Chen 
2142690619bSJoseph Chen static struct dm_pmic_ops rk801_ops = {
2152690619bSJoseph Chen 	.reg_count = rk801_reg_count,
2162690619bSJoseph Chen 	.read = rk801_read,
2172690619bSJoseph Chen 	.write = rk801_write,
2182690619bSJoseph Chen 	.shutdown = rk801_shutdown,
2192690619bSJoseph Chen };
2202690619bSJoseph Chen 
2212690619bSJoseph Chen static const struct udevice_id rk801_ids[] = {
2222690619bSJoseph Chen 	{ .compatible = "rockchip,rk801" },
223d76fd971SJoseph Chen 	{ }
2242690619bSJoseph Chen };
2252690619bSJoseph Chen 
2262690619bSJoseph Chen U_BOOT_DRIVER(pmic_rk801) = {
2272690619bSJoseph Chen 	.name = "rk801 pmic",
2282690619bSJoseph Chen 	.id = UCLASS_PMIC,
2292690619bSJoseph Chen 	.of_match = rk801_ids,
2302690619bSJoseph Chen #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
2312690619bSJoseph Chen 	.bind = rk801_bind,
2322690619bSJoseph Chen #endif
2332690619bSJoseph Chen 	.ofdata_to_platdata = rk801_ofdata_to_platdata,
2342690619bSJoseph Chen 	.priv_auto_alloc_size = sizeof(struct rk801_priv),
2352690619bSJoseph Chen 	.probe = rk801_probe,
2362690619bSJoseph Chen 	.ops = &rk801_ops,
2372690619bSJoseph Chen };
2382690619bSJoseph Chen 
239