• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2015 Google, Inc
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6 
7 #include <common.h>
8 #include <dm.h>
9 #include <errno.h>
10 #include <power/rk8xx_pmic.h>
11 #include <power/pmic.h>
12 
13 static struct reg_data rk817_init_reg[] = {
14 /* enable the under-voltage protection,
15  * the under-voltage protection will shutdown the LDO3 and reset the PMIC
16  */
17 	{ RK817_BUCK4_CMIN, 0x60, 0x60},
18 };
19 
20 static const struct pmic_child_info pmic_children_info[] = {
21 	{ .prefix = "DCDC_REG", .driver = "rk8xx_buck"},
22 	{ .prefix = "LDO_REG", .driver = "rk8xx_ldo"},
23 	{ .prefix = "SWITCH_REG", .driver = "rk8xx_switch"},
24 	{ },
25 };
26 
rk8xx_reg_count(struct udevice * dev)27 static int rk8xx_reg_count(struct udevice *dev)
28 {
29 	return RK808_NUM_OF_REGS;
30 }
31 
rk8xx_write(struct udevice * dev,uint reg,const uint8_t * buff,int len)32 static int rk8xx_write(struct udevice *dev, uint reg, const uint8_t *buff,
33 			  int len)
34 {
35 	int ret;
36 
37 	ret = dm_i2c_write(dev, reg, buff, len);
38 	if (ret) {
39 		debug("write error to device: %p register: %#x!\n", dev, reg);
40 		return ret;
41 	}
42 
43 	return 0;
44 }
45 
rk8xx_read(struct udevice * dev,uint reg,uint8_t * buff,int len)46 static int rk8xx_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
47 {
48 	int ret;
49 
50 	ret = dm_i2c_read(dev, reg, buff, len);
51 	if (ret) {
52 		debug("read error from device: %p register: %#x!\n", dev, reg);
53 		return ret;
54 	}
55 
56 	return 0;
57 }
58 
59 #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
rk8xx_bind(struct udevice * dev)60 static int rk8xx_bind(struct udevice *dev)
61 {
62 	ofnode regulators_node;
63 	int children;
64 
65 	regulators_node = dev_read_subnode(dev, "regulators");
66 	if (!ofnode_valid(regulators_node)) {
67 		debug("%s: %s regulators subnode not found!\n", __func__,
68 		      dev->name);
69 		return -ENXIO;
70 	}
71 
72 	debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
73 
74 	children = pmic_bind_children(dev, regulators_node, pmic_children_info);
75 	if (!children)
76 		debug("%s: %s - no child found\n", __func__, dev->name);
77 
78 	/* Always return success for this device */
79 	return 0;
80 }
81 #endif
82 
rk8xx_probe(struct udevice * dev)83 static int rk8xx_probe(struct udevice *dev)
84 {
85 	struct rk8xx_priv *priv = dev_get_priv(dev);
86 	struct reg_data *init_data = NULL;
87 	int init_data_num = 0;
88 	int ret = 0, i, show_variant;
89 	u8 msb, lsb, id_msb, id_lsb;
90 	u8 on_source = 0, off_source = 0;
91 	u8 power_en0, power_en1, power_en2, power_en3;
92 	u8 value;
93 
94 	/* read Chip variant */
95 	if (device_is_compatible(dev, "rockchip,rk817") ||
96 	    device_is_compatible(dev, "rockchip,rk809")) {
97 		id_msb = RK817_ID_MSB;
98 		id_lsb = RK817_ID_LSB;
99 	} else {
100 		id_msb = ID_MSB;
101 		id_lsb = ID_LSB;
102 	}
103 
104 	ret = rk8xx_read(dev, id_msb, &msb, 1);
105 	if (ret)
106 		return ret;
107 	ret = rk8xx_read(dev, id_lsb, &lsb, 1);
108 	if (ret)
109 		return ret;
110 
111 	priv->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
112 	show_variant = priv->variant;
113 	switch (priv->variant) {
114 	case RK808_ID:
115 		show_variant = 0x808;	/* RK808 hardware ID is 0 */
116 		break;
117 	case RK805_ID:
118 	case RK816_ID:
119 	case RK818_ID:
120 		on_source = RK8XX_ON_SOURCE;
121 		off_source = RK8XX_OFF_SOURCE;
122 		break;
123 	case RK809_ID:
124 	case RK817_ID:
125 		on_source = RK817_ON_SOURCE;
126 		off_source = RK817_OFF_SOURCE;
127 		init_data = rk817_init_reg;
128 		init_data_num = ARRAY_SIZE(rk817_init_reg);
129 		power_en0 = pmic_reg_read(dev, RK817_POWER_EN0);
130 		power_en1 = pmic_reg_read(dev, RK817_POWER_EN1);
131 		power_en2 = pmic_reg_read(dev, RK817_POWER_EN2);
132 		power_en3 = pmic_reg_read(dev, RK817_POWER_EN3);
133 
134 		value = (power_en0 & 0x0f) | ((power_en1 & 0x0f) << 4);
135 		pmic_reg_write(dev, RK817_POWER_EN_SAVE0, value);
136 		value = (power_en2 & 0x0f) | ((power_en3 & 0x0f) << 4);
137 		pmic_reg_write(dev, RK817_POWER_EN_SAVE1, value);
138 		break;
139 	default:
140 		printf("Unknown PMIC: RK%x!!\n", priv->variant);
141 		return -EINVAL;
142 	}
143 
144 	for (i = 0; i < init_data_num; i++) {
145 		ret = pmic_clrsetbits(dev,
146 				      init_data[i].reg,
147 				      init_data[i].mask,
148 				      init_data[i].val);
149 		if (ret < 0) {
150 			printf("%s: i2c set reg 0x%x failed, ret=%d\n",
151 			       __func__, init_data[i].reg, ret);
152 		}
153 
154 		debug("%s: reg[0x%x] = 0x%x\n", __func__, init_data[i].reg,
155 		      pmic_reg_read(dev, init_data[i].reg));
156 	}
157 
158 	printf("PMIC:  RK%x ", show_variant);
159 
160 	if (on_source && off_source)
161 		printf("(on=0x%02x, off=0x%02x)",
162 		       pmic_reg_read(dev, on_source),
163 		       pmic_reg_read(dev, off_source));
164 	printf("\n");
165 
166 	return 0;
167 }
168 
169 static struct dm_pmic_ops rk8xx_ops = {
170 	.reg_count = rk8xx_reg_count,
171 	.read = rk8xx_read,
172 	.write = rk8xx_write,
173 };
174 
175 static const struct udevice_id rk8xx_ids[] = {
176 	{ .compatible = "rockchip,rk805" },
177 	{ .compatible = "rockchip,rk808" },
178 	{ .compatible = "rockchip,rk809" },
179 	{ .compatible = "rockchip,rk816" },
180 	{ .compatible = "rockchip,rk817" },
181 	{ .compatible = "rockchip,rk818" },
182 	{ }
183 };
184 
185 U_BOOT_DRIVER(pmic_rk8xx) = {
186 	.name = "rk8xx pmic",
187 	.id = UCLASS_PMIC,
188 	.of_match = rk8xx_ids,
189 #if CONFIG_IS_ENABLED(PMIC_CHILDREN)
190 	.bind = rk8xx_bind,
191 #endif
192 	.priv_auto_alloc_size   = sizeof(struct rk8xx_priv),
193 	.probe = rk8xx_probe,
194 	.ops = &rk8xx_ops,
195 };
196