xref: /rk3399_rockchip-uboot/drivers/power/pmic/rk8xx_spi.c (revision 1716a6e7909a59d91392d38267cb4e2f04d404fb)
19361c683Sshengfei Xu /*
29361c683Sshengfei Xu  **Copyright (C) 2021 Rockchip Electronics Co., Ltd
39361c683Sshengfei Xu  *
49361c683Sshengfei Xu  * SPDX-License-Identifier:	GPL-2.0+
59361c683Sshengfei Xu  */
69361c683Sshengfei Xu 
79361c683Sshengfei Xu #include <common.h>
89361c683Sshengfei Xu #include <dm.h>
99361c683Sshengfei Xu #include <errno.h>
109361c683Sshengfei Xu #include <irq-generic.h>
119361c683Sshengfei Xu #include <power/rk8xx_pmic.h>
129361c683Sshengfei Xu #include <power/pmic.h>
139361c683Sshengfei Xu #include <spi.h>
149361c683Sshengfei Xu 
159361c683Sshengfei Xu DECLARE_GLOBAL_DATA_PTR;
169361c683Sshengfei Xu 
174213f3e0Sshengfei Xu #if CONFIG_IS_ENABLED(IRQ)
18ef9c5d10Sshengfei Xu /* RK806 */
194213f3e0Sshengfei Xu static const struct virq_reg rk806_irqs[] = {
204213f3e0Sshengfei Xu 	[RK8XX_IRQ_PWRON_FALL] = {
214213f3e0Sshengfei Xu 		.mask = RK806_IRQ_PWRON_FALL_MSK,
224213f3e0Sshengfei Xu 		.reg_offset = 0,
234213f3e0Sshengfei Xu 	},
244213f3e0Sshengfei Xu 	[RK8XX_IRQ_PWRON_RISE] = {
254213f3e0Sshengfei Xu 		.mask = RK806_IRQ_PWRON_RISE_MSK,
264213f3e0Sshengfei Xu 		.reg_offset = 0,
274213f3e0Sshengfei Xu 	},
284213f3e0Sshengfei Xu };
294213f3e0Sshengfei Xu 
304213f3e0Sshengfei Xu static struct virq_chip rk806_irq_chip = {
314213f3e0Sshengfei Xu 	.status_base		= RK806_INT_STS0,
324213f3e0Sshengfei Xu 	.mask_base		= RK806_INT_MSK0,
334213f3e0Sshengfei Xu 	.num_regs		= 1,
344213f3e0Sshengfei Xu 	.read			= pmic_reg_read,
354213f3e0Sshengfei Xu 	.write			= pmic_reg_write,
364213f3e0Sshengfei Xu 	.irqs			= rk806_irqs,
374213f3e0Sshengfei Xu 	.num_irqs		= ARRAY_SIZE(rk806_irqs),
384213f3e0Sshengfei Xu };
394213f3e0Sshengfei Xu #endif
404213f3e0Sshengfei Xu 
419361c683Sshengfei Xu static const struct pmic_child_info pmic_children_info[] = {
42ef9c5d10Sshengfei Xu 	{ .prefix = "DCDC", .driver = "rk8xx_buck"},
43ef9c5d10Sshengfei Xu 	{ .prefix = "NLDO", .driver = "rk8xx_ldo"},
44ef9c5d10Sshengfei Xu 	{ .prefix = "PLDO", .driver = "rk8xx_pldo"},
459361c683Sshengfei Xu 	{ },
469361c683Sshengfei Xu };
479361c683Sshengfei Xu 
484213f3e0Sshengfei Xu static const struct pmic_child_info power_key_info[] = {
494213f3e0Sshengfei Xu 	{ .prefix = "pwrkey", .driver = "rk8xx_pwrkey"},
504213f3e0Sshengfei Xu 	{ },
514213f3e0Sshengfei Xu };
524213f3e0Sshengfei Xu 
_spi_read(struct udevice * dev,u32 reg,u8 * buffer,int len)539361c683Sshengfei Xu static int _spi_read(struct udevice *dev, u32 reg, u8 *buffer, int len)
549361c683Sshengfei Xu {
559361c683Sshengfei Xu 	struct rk8xx_priv *priv = dev_get_priv(dev);
569361c683Sshengfei Xu 	u8 txbuf[3];
579361c683Sshengfei Xu 	int ret;
589361c683Sshengfei Xu 
599361c683Sshengfei Xu 	if (spi_claim_bus(priv->slave))
609361c683Sshengfei Xu 		return -EBUSY;
619361c683Sshengfei Xu 
629361c683Sshengfei Xu 	txbuf[0] = RK806_CMD_READ;
639361c683Sshengfei Xu 	txbuf[1] = reg;
649361c683Sshengfei Xu 	txbuf[2] = RK806_REG_H;
659361c683Sshengfei Xu 
669361c683Sshengfei Xu 	ret = spi_write_then_read(priv->slave, txbuf, 3, NULL, buffer, 1);
679361c683Sshengfei Xu 	spi_release_bus(priv->slave);
689361c683Sshengfei Xu 
699361c683Sshengfei Xu 	return ret;
709361c683Sshengfei Xu }
719361c683Sshengfei Xu 
_spi_write(struct udevice * dev,uint reg,const u8 * buffer,int len)729361c683Sshengfei Xu static int _spi_write(struct udevice *dev, uint reg, const u8 *buffer, int len)
739361c683Sshengfei Xu {
749361c683Sshengfei Xu 	struct rk8xx_priv *priv = dev_get_priv(dev);
759361c683Sshengfei Xu 	u8 txbuf[4];
769361c683Sshengfei Xu 	int ret;
779361c683Sshengfei Xu 
789361c683Sshengfei Xu 	if (len < 1) {
799361c683Sshengfei Xu 		dev_err(dev, "rk806 write error: len < 1\n");
809361c683Sshengfei Xu 		return -EINVAL;
819361c683Sshengfei Xu 	}
829361c683Sshengfei Xu 
839361c683Sshengfei Xu 	if (spi_claim_bus(priv->slave))
849361c683Sshengfei Xu 		return -EBUSY;
859361c683Sshengfei Xu 
869361c683Sshengfei Xu 	txbuf[0] = RK806_CMD_WRITE;
879361c683Sshengfei Xu 	txbuf[1] = reg;
889361c683Sshengfei Xu 	txbuf[2] = RK806_REG_H;
899361c683Sshengfei Xu 	txbuf[3] = *buffer;
909361c683Sshengfei Xu 
919361c683Sshengfei Xu 	ret = spi_write_then_read(priv->slave, txbuf, 4, NULL, NULL, 0);
929361c683Sshengfei Xu 	spi_release_bus(priv->slave);
939361c683Sshengfei Xu 
949361c683Sshengfei Xu 	return ret;
959361c683Sshengfei Xu }
969361c683Sshengfei Xu 
rk806_spi_read(struct udevice * dev,uint reg,u8 * buffer,int len)979361c683Sshengfei Xu static int rk806_spi_read(struct udevice *dev,
989361c683Sshengfei Xu 			  uint reg,
999361c683Sshengfei Xu 			  u8 *buffer,
1009361c683Sshengfei Xu 			  int len)
1019361c683Sshengfei Xu {
1029361c683Sshengfei Xu 	int ret;
1039361c683Sshengfei Xu 
1049361c683Sshengfei Xu 	ret = _spi_read(dev, reg, buffer, len);
1059361c683Sshengfei Xu 	if (ret)
1069361c683Sshengfei Xu 		dev_err(dev, "rk806 read reg(0x%x) error: %d\n", reg, ret);
1079361c683Sshengfei Xu 
1089361c683Sshengfei Xu 	return ret;
1099361c683Sshengfei Xu }
1109361c683Sshengfei Xu 
rk806_spi_write(struct udevice * dev,uint reg,const u8 * buffer,int len)1119361c683Sshengfei Xu static int rk806_spi_write(struct udevice *dev,
1129361c683Sshengfei Xu 			   uint reg,
1139361c683Sshengfei Xu 			   const u8 *buffer,
1149361c683Sshengfei Xu 			   int len)
1159361c683Sshengfei Xu {
1169361c683Sshengfei Xu 	int ret;
1179361c683Sshengfei Xu 
1189361c683Sshengfei Xu 	ret = _spi_write(dev, reg, buffer, len);
1199361c683Sshengfei Xu 	if (ret)
1209361c683Sshengfei Xu 		dev_err(dev, "rk806 write reg(0x%x) error: %d\n", reg, ret);
1219361c683Sshengfei Xu 
1229361c683Sshengfei Xu 	return ret;
1239361c683Sshengfei Xu }
1249361c683Sshengfei Xu 
rk8xx_spi_reg_count(struct udevice * dev)1259361c683Sshengfei Xu static int rk8xx_spi_reg_count(struct udevice *dev)
1269361c683Sshengfei Xu {
1279361c683Sshengfei Xu 	return 0xff;
1289361c683Sshengfei Xu }
1299361c683Sshengfei Xu 
1309361c683Sshengfei Xu #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
rk8xx_spi_bind(struct udevice * dev)1319361c683Sshengfei Xu static int rk8xx_spi_bind(struct udevice *dev)
1329361c683Sshengfei Xu {
1339361c683Sshengfei Xu 	ofnode regulators_node;
1349361c683Sshengfei Xu 	int children;
1359361c683Sshengfei Xu 
1369361c683Sshengfei Xu 	regulators_node = dev_read_subnode(dev, "regulators");
1379361c683Sshengfei Xu 	if (!ofnode_valid(regulators_node)) {
1389361c683Sshengfei Xu 		debug("%s: %s regulators subnode not found!\n", __func__,
1399361c683Sshengfei Xu 		      dev->name);
1409361c683Sshengfei Xu 		return -ENXIO;
1419361c683Sshengfei Xu 	}
1429361c683Sshengfei Xu 
1439361c683Sshengfei Xu 	children = pmic_bind_children(dev, regulators_node, pmic_children_info);
1449361c683Sshengfei Xu 	if (!children)
1459361c683Sshengfei Xu 		debug("%s: %s - no child found\n", __func__, dev->name);
1469361c683Sshengfei Xu 
1474213f3e0Sshengfei Xu 	children = pmic_bind_children(dev, dev->node, power_key_info);
1484213f3e0Sshengfei Xu 	if (!children)
1494213f3e0Sshengfei Xu 		debug("%s: %s - no child found\n", __func__, dev->name);
1504213f3e0Sshengfei Xu 
1514213f3e0Sshengfei Xu 	return 0;
1524213f3e0Sshengfei Xu }
1534213f3e0Sshengfei Xu #endif
1544213f3e0Sshengfei Xu #if CONFIG_IS_ENABLED(IRQ)
rk8xx_spi_ofdata_to_platdata(struct udevice * dev)1554213f3e0Sshengfei Xu static int rk8xx_spi_ofdata_to_platdata(struct udevice *dev)
1564213f3e0Sshengfei Xu {
1574213f3e0Sshengfei Xu 	struct rk8xx_priv *rk8xx = dev_get_priv(dev);
1584213f3e0Sshengfei Xu 	u32 interrupt, phandle;
1594213f3e0Sshengfei Xu 	int ret;
1604213f3e0Sshengfei Xu 
161467c0e51Sshengfei Xu 	rk8xx->rst_fun = dev_read_u32_default(dev, "pmic-reset-func", 0);
162467c0e51Sshengfei Xu 
1634213f3e0Sshengfei Xu 	phandle = dev_read_u32_default(dev, "interrupt-parent", -ENODATA);
1644213f3e0Sshengfei Xu 	if (phandle == -ENODATA) {
1654213f3e0Sshengfei Xu 		printf("Read 'interrupt-parent' failed, ret=%d\n", phandle);
1664213f3e0Sshengfei Xu 		return phandle;
1674213f3e0Sshengfei Xu 	}
1684213f3e0Sshengfei Xu 
1694213f3e0Sshengfei Xu 	ret = dev_read_u32_array(dev, "interrupts", &interrupt, 1);
1704213f3e0Sshengfei Xu 	if (ret) {
1714213f3e0Sshengfei Xu 		printf("Read 'interrupts' failed, ret=%d\n", ret);
1724213f3e0Sshengfei Xu 		return ret;
1734213f3e0Sshengfei Xu 	}
1744213f3e0Sshengfei Xu 
1754213f3e0Sshengfei Xu 	rk8xx->irq = phandle_gpio_to_irq(phandle, interrupt);
17613b7092aSJoseph Chen 	if (rk8xx->irq < 0 && rk8xx->irq != -EBUSY)
1774213f3e0Sshengfei Xu 		printf("Failed to request rk8xx irq, ret=%d\n", rk8xx->irq);
1784213f3e0Sshengfei Xu 
1794213f3e0Sshengfei Xu 	return 0;
1804213f3e0Sshengfei Xu }
1814213f3e0Sshengfei Xu 
rk8xx_spi_irq_chip_init(struct udevice * dev)1824213f3e0Sshengfei Xu static int rk8xx_spi_irq_chip_init(struct udevice *dev)
1834213f3e0Sshengfei Xu {
1844213f3e0Sshengfei Xu 	struct rk8xx_priv *priv = dev_get_priv(dev);
1854213f3e0Sshengfei Xu 	struct virq_chip *irq_chip = NULL;
1864213f3e0Sshengfei Xu 	u8 value;
1874213f3e0Sshengfei Xu 	int ret;
1884213f3e0Sshengfei Xu 
1894213f3e0Sshengfei Xu 	value = 0xff;
1904213f3e0Sshengfei Xu 	rk806_spi_write(dev, RK806_INT_STS0, &value, 1);
1914213f3e0Sshengfei Xu 	rk806_spi_write(dev, RK806_INT_STS1, &value, 1);
1924213f3e0Sshengfei Xu 	rk806_spi_write(dev, RK806_INT_MSK0, &value, 1);
1934213f3e0Sshengfei Xu 	rk806_spi_write(dev, RK806_INT_MSK1, &value, 1);
1944213f3e0Sshengfei Xu 	value = 0x00;
1954213f3e0Sshengfei Xu 	rk806_spi_write(dev, RK806_GPIO_INT_CONFIG, &value, 1);
1964213f3e0Sshengfei Xu 
1974213f3e0Sshengfei Xu 	irq_chip = &rk806_irq_chip;
1984213f3e0Sshengfei Xu 
1994213f3e0Sshengfei Xu 	if (irq_chip && priv->irq > 0) {
2004213f3e0Sshengfei Xu 		ret = virq_add_chip(dev, irq_chip, priv->irq);
2014213f3e0Sshengfei Xu 		if (ret) {
2024213f3e0Sshengfei Xu 			printf("Failed to add irqchip(irq=%d), ret=%d\n",
2034213f3e0Sshengfei Xu 			       priv->irq, ret);
2044213f3e0Sshengfei Xu 			return ret;
2054213f3e0Sshengfei Xu 		}
2064213f3e0Sshengfei Xu 		priv->irq_chip = irq_chip;
2074213f3e0Sshengfei Xu 	}
2084213f3e0Sshengfei Xu 
2094213f3e0Sshengfei Xu 	return 0;
2104213f3e0Sshengfei Xu }
2114213f3e0Sshengfei Xu #else
rk8xx_spi_ofdata_to_platdata(struct udevice * dev)2124213f3e0Sshengfei Xu static inline int rk8xx_spi_ofdata_to_platdata(struct udevice *dev)
2134213f3e0Sshengfei Xu {
214*1716a6e7SJoseph Chen 	struct rk8xx_priv *rk8xx = dev_get_priv(dev);
215*1716a6e7SJoseph Chen 
216*1716a6e7SJoseph Chen 	rk8xx->rst_fun = dev_read_u32_default(dev, "pmic-reset-func", 0);
217*1716a6e7SJoseph Chen 
2184213f3e0Sshengfei Xu 	return 0;
2194213f3e0Sshengfei Xu }
2204213f3e0Sshengfei Xu 
rk8xx_spi_irq_chip_init(struct udevice * dev)2214213f3e0Sshengfei Xu static inline int rk8xx_spi_irq_chip_init(struct udevice *dev)
2224213f3e0Sshengfei Xu {
2239361c683Sshengfei Xu 	return 0;
2249361c683Sshengfei Xu }
2259361c683Sshengfei Xu #endif
2269361c683Sshengfei Xu 
rk8xx_spi_probe(struct udevice * dev)2279361c683Sshengfei Xu static int rk8xx_spi_probe(struct udevice *dev)
2289361c683Sshengfei Xu {
2299361c683Sshengfei Xu 	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
2309361c683Sshengfei Xu 	struct rk8xx_priv *priv = dev_get_priv(dev);
2319361c683Sshengfei Xu 	struct udevice *spi = dev_get_parent(dev);
2329361c683Sshengfei Xu 	struct spi_slave *slave = NULL;
233df66b0efSshengfei Xu 	u8 on_source, off_source;
234a5a15a14Sshengfei Xu 	u8 msb, lsb, value = 0;
2359361c683Sshengfei Xu 	int ret;
2369361c683Sshengfei Xu 
2379361c683Sshengfei Xu 	if (spi->seq < 0) {
2389361c683Sshengfei Xu 		dev_err(dev, "Failed to configure the spi num\n");
2399361c683Sshengfei Xu 		return -EINVAL;
2409361c683Sshengfei Xu 	}
2419361c683Sshengfei Xu 
2429361c683Sshengfei Xu 	slave = spi_setup_slave(spi->seq, plat->cs, plat->max_hz,
2439361c683Sshengfei Xu 				plat->mode);
2449361c683Sshengfei Xu 	if (!slave)
2459361c683Sshengfei Xu 		return -ENODEV;
2469361c683Sshengfei Xu 	priv->slave = slave;
2479361c683Sshengfei Xu 
2489361c683Sshengfei Xu 	/* read Chip variant */
2499361c683Sshengfei Xu 	ret = rk806_spi_read(dev, RK806_CHIP_NAME, &msb, 1);
2504213f3e0Sshengfei Xu 	if (ret) {
2519361c683Sshengfei Xu 		dev_err(dev, "rk806 name read error: %d\n", ret);
2529361c683Sshengfei Xu 		return ret;
2539361c683Sshengfei Xu 	}
2549361c683Sshengfei Xu 
2559361c683Sshengfei Xu 	ret = rk806_spi_read(dev, RK806_CHIP_VER, &lsb, 1);
2564213f3e0Sshengfei Xu 	if (ret) {
2579361c683Sshengfei Xu 		dev_err(dev, "rk806 version read error: %d\n", ret);
2589361c683Sshengfei Xu 		return ret;
2599361c683Sshengfei Xu 	}
2609361c683Sshengfei Xu 
2619361c683Sshengfei Xu 	priv->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
2629361c683Sshengfei Xu 	printf("spi%d: RK%x%x: %d\n", spi->seq, msb, (lsb >> 4), lsb & 0x0f);
2639361c683Sshengfei Xu 
264df66b0efSshengfei Xu 	rk806_spi_read(dev, RK806_ON_SOURCE, &on_source, 1);
265df66b0efSshengfei Xu 	rk806_spi_read(dev, RK806_OFF_SOURCE, &off_source, 1);
266df66b0efSshengfei Xu 	printf("ON=0x%02x, OFF=0x%02x\n", on_source, off_source);
267df66b0efSshengfei Xu 
268a5a15a14Sshengfei Xu 	ret = rk806_spi_read(dev, RK806_HW_VER, &value, 1);
269a5a15a14Sshengfei Xu 	if (ret)
270a5a15a14Sshengfei Xu 		panic("RK806: read RK806_HW_VER error!\n");
271a5a15a14Sshengfei Xu 	/* dual rk806 dev name: "rk806master@0", "rk806slave@1"
272a5a15a14Sshengfei Xu 	 * single rk806 dev name: " rk806single@0"
273a5a15a14Sshengfei Xu 	 */
274a5a15a14Sshengfei Xu 	if ((!strcmp(dev->name, "rk806master@0")) || (!strcmp(dev->name, "rk806slave@1"))) {
275a5a15a14Sshengfei Xu 		if (value != HW_DUAL_PMIC) {
276a5a15a14Sshengfei Xu 			dev_err(dev, "HW single pmic, the firmware dual pmic(0x%x)!\n", value);
277a5a15a14Sshengfei Xu 			run_command("download", 0);
278a5a15a14Sshengfei Xu 		}
279a5a15a14Sshengfei Xu 	} else {
280a5a15a14Sshengfei Xu 		if (value != HW_SINGLE_PMIC) {
281a5a15a14Sshengfei Xu 			dev_err(dev, "HW dual pmic, the firmware single pmic(0x%x)!\n", value);
282a5a15a14Sshengfei Xu 			run_command("download", 0);
283a5a15a14Sshengfei Xu 		}
284a5a15a14Sshengfei Xu 	}
285a5a15a14Sshengfei Xu 
286ef9c5d10Sshengfei Xu 	if ((lsb & RK806_VERSION_MSK) == RK806_VERSION_AB) {
2874213f3e0Sshengfei Xu 		ret = rk806_spi_read(dev, RK806_SYS_CFG1, &value, 1);
2884213f3e0Sshengfei Xu 		if (ret) {
2894213f3e0Sshengfei Xu 			dev_err(dev, "rk806 RK806_SYS_CFG1 read error: %d\n", ret);
2904213f3e0Sshengfei Xu 			return ret;
2914213f3e0Sshengfei Xu 		}
292ef9c5d10Sshengfei Xu 		value |= RK806_ABNORDET_EN;
2934213f3e0Sshengfei Xu 		rk806_spi_write(dev, RK806_SYS_CFG1, &value, 1);
2944213f3e0Sshengfei Xu 	}
2954213f3e0Sshengfei Xu 
296467c0e51Sshengfei Xu 	if (priv->rst_fun) {
297467c0e51Sshengfei Xu 		rk806_spi_read(dev, RK806_SYS_CFG3, &value, 1);
298ef9c5d10Sshengfei Xu 		value &= RK806_RESET_FUN_CLR;
299467c0e51Sshengfei Xu 		if (priv->rst_fun == RK806_RST_MODE1) {
300467c0e51Sshengfei Xu 			value |= (RK806_RST_MODE1 << 6);
301467c0e51Sshengfei Xu 			rk806_spi_write(dev, RK806_SYS_CFG3, &value, 1);
302467c0e51Sshengfei Xu 		} else if (priv->rst_fun == RK806_RST_MODE2) {
303467c0e51Sshengfei Xu 			value |= (RK806_RST_MODE2 << 6);
304467c0e51Sshengfei Xu 			rk806_spi_write(dev, RK806_SYS_CFG3, &value, 1);
305467c0e51Sshengfei Xu 		}
306467c0e51Sshengfei Xu 	}
307467c0e51Sshengfei Xu 
3084213f3e0Sshengfei Xu 	rk8xx_spi_irq_chip_init(dev);
3094213f3e0Sshengfei Xu 
3104213f3e0Sshengfei Xu 	return 0;
3114213f3e0Sshengfei Xu }
3124213f3e0Sshengfei Xu 
rk8xx_spi_shutdown(struct udevice * dev)3134213f3e0Sshengfei Xu static int rk8xx_spi_shutdown(struct udevice *dev)
3144213f3e0Sshengfei Xu {
3154213f3e0Sshengfei Xu 	u8 dev_off;
3164213f3e0Sshengfei Xu 	int ret = 0;
3174213f3e0Sshengfei Xu 
3184213f3e0Sshengfei Xu 	ret = rk806_spi_read(dev, RK806_SYS_CFG3, &dev_off, 1);
3194213f3e0Sshengfei Xu 	if (ret)
3204213f3e0Sshengfei Xu 		return ret;
3214213f3e0Sshengfei Xu 
3224213f3e0Sshengfei Xu 	dev_off |= RK806_DEV_OFF;
3234213f3e0Sshengfei Xu 	ret = rk806_spi_write(dev, RK806_SYS_CFG3, &dev_off, 1);
3244213f3e0Sshengfei Xu 	if (ret) {
3254213f3e0Sshengfei Xu 		dev_err(dev, "rk806 shutdown error: %d\n", ret);
3264213f3e0Sshengfei Xu 		return ret;
3274213f3e0Sshengfei Xu 	}
3284213f3e0Sshengfei Xu 
3294213f3e0Sshengfei Xu 	while (1)
3304213f3e0Sshengfei Xu 		;
3314213f3e0Sshengfei Xu 
3329361c683Sshengfei Xu 	return 0;
3339361c683Sshengfei Xu }
3349361c683Sshengfei Xu 
rk806_suspend(struct udevice * dev)335df66b0efSshengfei Xu static int rk806_suspend(struct udevice *dev)
336df66b0efSshengfei Xu {
337df66b0efSshengfei Xu 	int ret = 0;
338df66b0efSshengfei Xu 	u8 i, val;
339df66b0efSshengfei Xu 
340df66b0efSshengfei Xu 	ret = rk806_spi_read(dev, RK806_PWRCTRL_CONFIG0, &val, 1);
341df66b0efSshengfei Xu 	if (ret)
342df66b0efSshengfei Xu 		return ret;
343df66b0efSshengfei Xu 	val &= RK806_PWRCTRL_FUN_MSK;
344df66b0efSshengfei Xu 	ret = rk806_spi_write(dev, RK806_PWRCTRL_CONFIG0, &val, 1);
345df66b0efSshengfei Xu 	if (ret)
346df66b0efSshengfei Xu 		return ret;
347df66b0efSshengfei Xu 
348df66b0efSshengfei Xu 	ret = rk806_spi_read(dev, RK806_PWRCTRL_CONFIG1, &val, 1);
349df66b0efSshengfei Xu 	if (ret)
350df66b0efSshengfei Xu 		return ret;
351df66b0efSshengfei Xu 	val &= RK806_PWRCTRL_FUN_MSK;
352df66b0efSshengfei Xu 	ret = rk806_spi_write(dev, RK806_PWRCTRL_CONFIG1, &val, 1);
353df66b0efSshengfei Xu 	if (ret)
354df66b0efSshengfei Xu 		return ret;
355df66b0efSshengfei Xu 
356ef9c5d10Sshengfei Xu 	for (i = RK806_VSEL_CTR_SEL0; i <= RK806_DVS_CTR_SEL4; i++) {
357df66b0efSshengfei Xu 		ret = rk806_spi_read(dev, i, &val, 1);
358df66b0efSshengfei Xu 		if (ret)
359df66b0efSshengfei Xu 			return ret;
360df66b0efSshengfei Xu 		val &= RK806_VSEL_CTRL_MSK;
361df66b0efSshengfei Xu 		ret = rk806_spi_write(dev, i, &val, 1);
362df66b0efSshengfei Xu 		if (ret)
363df66b0efSshengfei Xu 			return ret;
364df66b0efSshengfei Xu 	}
365df66b0efSshengfei Xu 
366df66b0efSshengfei Xu 	ret = rk806_spi_read(dev, RK806_PWRCTRL_CONFIG0, &val, 1);
367df66b0efSshengfei Xu 	if (ret)
368df66b0efSshengfei Xu 		return ret;
369df66b0efSshengfei Xu 	val &= RK806_PWRCTRL_FUN_MSK;
370df66b0efSshengfei Xu 	val |= RK806_ENABLE_PWRCTRL;
371df66b0efSshengfei Xu 	ret = rk806_spi_write(dev, RK806_PWRCTRL_CONFIG0, &val, 1);
372df66b0efSshengfei Xu 	if (ret)
373df66b0efSshengfei Xu 		return ret;
374df66b0efSshengfei Xu 
375df66b0efSshengfei Xu 	for (i = RK806_VSEL_CTR_SEL0; i <= RK806_DVS_CTR_SEL4; i++) {
376df66b0efSshengfei Xu 		ret = rk806_spi_read(dev, i, &val, 1);
377df66b0efSshengfei Xu 		if (ret)
378df66b0efSshengfei Xu 			return ret;
379df66b0efSshengfei Xu 		val &= RK806_VSEL_CTRL_MSK;
380df66b0efSshengfei Xu 		val |= RK806_VSEL_PWRCTRL1;
381df66b0efSshengfei Xu 		ret = rk806_spi_write(dev, i, &val, 1);
382df66b0efSshengfei Xu 		if (ret)
383df66b0efSshengfei Xu 			return ret;
384df66b0efSshengfei Xu 	}
385df66b0efSshengfei Xu 
386df66b0efSshengfei Xu 	return ret;
387df66b0efSshengfei Xu }
388df66b0efSshengfei Xu 
rk806_resume(struct udevice * dev)389df66b0efSshengfei Xu static int rk806_resume(struct udevice *dev)
390df66b0efSshengfei Xu {
391df66b0efSshengfei Xu 	int ret = 0;
392df66b0efSshengfei Xu 	u8 i, val;
393df66b0efSshengfei Xu 
394df66b0efSshengfei Xu 	for (i = RK806_VSEL_CTR_SEL0; i <= RK806_DVS_CTR_SEL4; i++) {
395df66b0efSshengfei Xu 		ret = rk806_spi_read(dev, i, &val, 1);
396df66b0efSshengfei Xu 		if (ret)
397df66b0efSshengfei Xu 			return ret;
398df66b0efSshengfei Xu 		val &= RK806_VSEL_CTRL_MSK;
399df66b0efSshengfei Xu 		ret = rk806_spi_write(dev, i, &val, 1);
400df66b0efSshengfei Xu 		if (ret)
401df66b0efSshengfei Xu 			return ret;
402df66b0efSshengfei Xu 	}
403df66b0efSshengfei Xu 
404df66b0efSshengfei Xu 	ret = rk806_spi_read(dev, RK806_PWRCTRL_CONFIG0, &val, 1);
405df66b0efSshengfei Xu 	if (ret)
406df66b0efSshengfei Xu 		return ret;
407df66b0efSshengfei Xu 	val &= RK806_PWRCTRL_FUN_MSK;
408df66b0efSshengfei Xu 	ret = rk806_spi_write(dev, RK806_PWRCTRL_CONFIG0, &val, 1);
409df66b0efSshengfei Xu 	if (ret)
410df66b0efSshengfei Xu 		return ret;
411df66b0efSshengfei Xu 
412df66b0efSshengfei Xu 	ret = rk806_spi_read(dev, RK806_PWRCTRL_CONFIG1, &val, 1);
413df66b0efSshengfei Xu 	if (ret)
414df66b0efSshengfei Xu 		return ret;
415df66b0efSshengfei Xu 	val &= RK806_PWRCTRL_FUN_MSK;
416df66b0efSshengfei Xu 	ret = rk806_spi_write(dev, RK806_PWRCTRL_CONFIG1, &val, 1);
417df66b0efSshengfei Xu 	if (ret)
418df66b0efSshengfei Xu 		return ret;
419df66b0efSshengfei Xu 
420df66b0efSshengfei Xu 	return ret;
421df66b0efSshengfei Xu }
422df66b0efSshengfei Xu 
4239361c683Sshengfei Xu static struct dm_pmic_ops rk8xx_spi_ops = {
4249361c683Sshengfei Xu 	.reg_count = rk8xx_spi_reg_count,
4259361c683Sshengfei Xu 	.read = rk806_spi_read,
4269361c683Sshengfei Xu 	.write = rk806_spi_write,
4274213f3e0Sshengfei Xu 	.shutdown = rk8xx_spi_shutdown,
428df66b0efSshengfei Xu 	.suspend = rk806_suspend,
429df66b0efSshengfei Xu 	.resume = rk806_resume,
4309361c683Sshengfei Xu };
4319361c683Sshengfei Xu 
4329361c683Sshengfei Xu static const struct udevice_id rk8xx_spi_ids[] = {
4339361c683Sshengfei Xu 	{ .compatible = "rockchip,rk806" },
4349361c683Sshengfei Xu 	{ }
4359361c683Sshengfei Xu };
4369361c683Sshengfei Xu 
4379361c683Sshengfei Xu U_BOOT_DRIVER(pmic_rk8xx_spi) = {
4389361c683Sshengfei Xu 	.name = "rk806-pmic",
4399361c683Sshengfei Xu 	.id = UCLASS_PMIC,
4409361c683Sshengfei Xu 	.of_match = rk8xx_spi_ids,
4419361c683Sshengfei Xu #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
4429361c683Sshengfei Xu 	.bind = rk8xx_spi_bind,
4439361c683Sshengfei Xu #endif
4444213f3e0Sshengfei Xu 	.ofdata_to_platdata = rk8xx_spi_ofdata_to_platdata,
4459361c683Sshengfei Xu 	.priv_auto_alloc_size = sizeof(struct rk8xx_priv),
4469361c683Sshengfei Xu 	.probe = rk8xx_spi_probe,
4479361c683Sshengfei Xu 	.ops = &rk8xx_spi_ops,
4489361c683Sshengfei Xu };
449