xref: /rk3399_rockchip-uboot/drivers/power/pmic/rk8xx.c (revision 4e8c225a1d386380171f4be14f3bd22ca85bc0bb)
1 /*
2  * Copyright (C) 2015 Google, Inc
3  * Written by Simon Glass <sjg@chromium.org>
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <common.h>
9 #include <dm.h>
10 #include <errno.h>
11 #include <power/rk8xx_pmic.h>
12 #include <power/pmic.h>
13 
14 DECLARE_GLOBAL_DATA_PTR;
15 
16 static const struct pmic_child_info pmic_children_info[] = {
17 	{ .prefix = "DCDC_REG", .driver = "rk8xx_buck"},
18 	{ .prefix = "LDO_REG", .driver = "rk8xx_ldo"},
19 	{ .prefix = "SWITCH_REG", .driver = "rk8xx_switch"},
20 	{ },
21 };
22 
23 static const struct pmic_child_info power_key_info[] = {
24 	{ .prefix = "pwrkey", .driver = "rk8xx_pwrkey"},
25 	{ },
26 };
27 
28 static const struct pmic_child_info fuel_gauge_info[] = {
29 	{ .prefix = "battery", .driver = "rk818_fg"},
30 	{ .prefix = "battery", .driver = "rk816_fg"},
31 	{ },
32 };
33 
34 static int rk8xx_reg_count(struct udevice *dev)
35 {
36 	return RK808_NUM_OF_REGS;
37 }
38 
39 static int rk8xx_write(struct udevice *dev, uint reg, const uint8_t *buff,
40 			  int len)
41 {
42 	int ret;
43 
44 	ret = dm_i2c_write(dev, reg, buff, len);
45 	if (ret) {
46 		debug("write error to device: %p register: %#x!", dev, reg);
47 		return ret;
48 	}
49 
50 	return 0;
51 }
52 
53 static int rk8xx_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
54 {
55 	int ret;
56 
57 	ret = dm_i2c_read(dev, reg, buff, len);
58 	if (ret) {
59 		debug("read error from device: %p register: %#x!", dev, reg);
60 		return ret;
61 	}
62 
63 	return 0;
64 }
65 
66 static int rk8xx_shutdown(struct udevice *dev)
67 {
68 	struct rk8xx_priv *priv = dev_get_priv(dev);
69 	u8 val, dev_off;
70 	int ret = 0;
71 
72 	switch (priv->variant) {
73 	case RK808_ID:
74 		dev_off = BIT(3);
75 		break;
76 	case RK805_ID:
77 	case RK816_ID:
78 	case RK818_ID:
79 		dev_off = BIT(0);
80 		break;
81 	default:
82 		printf("Unknown PMIC: RK%x\n", priv->variant);
83 		return -EINVAL;
84 	}
85 
86 	ret = dm_i2c_read(dev, REG_DEVCTRL, &val, 1);
87 	if (ret) {
88 		printf("read error from device: %p register: %#x!",
89 		       dev, REG_DEVCTRL);
90 		return ret;
91 	}
92 
93 	val |= dev_off;
94 	ret = dm_i2c_write(dev, REG_DEVCTRL, &val, 1);
95 	if (ret) {
96 		printf("write error to device: %p register: %#x!",
97 		       dev, REG_DEVCTRL);
98 		return ret;
99 	}
100 
101 	return 0;
102 }
103 
104 #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
105 static int rk8xx_bind(struct udevice *dev)
106 {
107 	ofnode regulators_node;
108 	int children;
109 
110 	regulators_node = dev_read_subnode(dev, "regulators");
111 	if (!ofnode_valid(regulators_node)) {
112 		debug("%s: %s regulators subnode not found!", __func__,
113 		      dev->name);
114 		return -ENXIO;
115 	}
116 
117 	debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
118 
119 	children = pmic_bind_children(dev, regulators_node, pmic_children_info);
120 	if (!children)
121 		debug("%s: %s - no child found\n", __func__, dev->name);
122 
123 	children = pmic_bind_children(dev, dev->node, power_key_info);
124 	if (!children)
125 		debug("%s: %s - no child found\n", __func__, dev->name);
126 
127 	children = pmic_bind_children(dev, dev->node, fuel_gauge_info);
128 	if (!children)
129 		debug("%s: %s - no child found\n", __func__, dev->name);
130 
131 	/* Always return success for this device */
132 	return 0;
133 }
134 #endif
135 
136 static int rk8xx_probe(struct udevice *dev)
137 {
138 	struct rk8xx_priv *priv = dev_get_priv(dev);
139 	uint8_t msb, lsb;
140 
141 	/* read Chip variant */
142 	rk8xx_read(dev, ID_MSB, &msb, 1);
143 	rk8xx_read(dev, ID_LSB, &lsb, 1);
144 
145 	priv->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
146 
147 	return 0;
148 }
149 
150 static struct dm_pmic_ops rk8xx_ops = {
151 	.reg_count = rk8xx_reg_count,
152 	.read = rk8xx_read,
153 	.write = rk8xx_write,
154 	.shutdown = rk8xx_shutdown,
155 };
156 
157 static const struct udevice_id rk8xx_ids[] = {
158 	{ .compatible = "rockchip,rk805" },
159 	{ .compatible = "rockchip,rk808" },
160 	{ .compatible = "rockchip,rk816" },
161 	{ .compatible = "rockchip,rk818" },
162 	{ }
163 };
164 
165 U_BOOT_DRIVER(pmic_rk8xx) = {
166 	.name = "rk8xx pmic",
167 	.id = UCLASS_PMIC,
168 	.of_match = rk8xx_ids,
169 #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
170 	.bind = rk8xx_bind,
171 #endif
172 	.priv_auto_alloc_size   = sizeof(struct rk8xx_priv),
173 	.probe = rk8xx_probe,
174 	.ops = &rk8xx_ops,
175 };
176