xref: /openbsd-src/sys/dev/fdt/rkpmic.c (revision b99ef4df7fac99f3475b694d6cd4990521c99ae6)
1 /*	$OpenBSD: rkpmic.c,v 1.7 2020/11/12 10:47:07 patrick Exp $	*/
2 /*
3  * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/device.h>
21 #include <sys/malloc.h>
22 
23 #include <dev/ofw/openfirm.h>
24 #include <dev/ofw/ofw_regulator.h>
25 #include <dev/ofw/fdt.h>
26 
27 #include <dev/i2c/i2cvar.h>
28 
29 #include <dev/clock_subr.h>
30 
31 extern todr_chip_handle_t todr_handle;
32 
33 #define RK808_SECONDS		0x00
34 #define RK808_MINUTES		0x01
35 #define RK808_HOURS		0x02
36 #define RK808_DAYS		0x03
37 #define RK808_MONTHS		0x04
38 #define RK808_YEARS		0x05
39 #define RK808_WEEKS		0x06
40 #define RK808_RTC_CTRL		0x10
41 #define  RK808_RTC_CTRL_STOP_RTC	0x01
42 #define RK808_RTC_STATUS	0x11
43 #define  RK808_RTC_STATUS_POWER_UP	0x80
44 
45 #define RK808_NRTC_REGS	7
46 
47 struct rkpmic_regdata {
48 	const char *name;
49 	uint8_t reg, mask;
50 	uint32_t base, delta;
51 };
52 
53 struct rkpmic_regdata rk805_regdata[] = {
54 	{ "DCDC_REG1", 0x2f, 0x3f, 712500, 12500 },
55 	{ "DCDC_REG2", 0x33, 0x3f, 712500, 12500 },
56 	{ "DCDC_REG4", 0x38, 0x1f, 800000, 100000 },
57 	{ "LDO_REG1", 0x3b, 0x1f, 800000, 100000 },
58 	{ "LDO_REG2", 0x3d, 0x1f, 800000, 100000 },
59 	{ "LDO_REG3", 0x3f, 0x1f, 800000, 100000 },
60 	{ }
61 };
62 
63 struct rkpmic_regdata rk808_regdata[] = {
64 	{ "DCDC_REG1", 0x2f, 0x3f, 712500, 12500 },
65 	{ "DCDC_REG2", 0x33, 0x3f, 712500, 12500 },
66 	{ "DCDC_REG4", 0x38, 0x0f, 1800000, 100000 },
67 	{ "LDO_REG1", 0x3b, 0x1f, 1800000, 100000 },
68 	{ "LDO_REG2", 0x3d, 0x1f, 1800000, 100000 },
69 	{ "LDO_REG3", 0x3f, 0x0f, 800000, 100000 },
70 	{ "LDO_REG4", 0x41, 0x1f, 1800000, 100000 },
71 	{ "LDO_REG5", 0x43, 0x1f, 1800000, 100000 },
72 	{ "LDO_REG6", 0x45, 0x1f, 800000, 100000 },
73 	{ "LDO_REG7", 0x47, 0x1f, 800000, 100000 },
74 	{ "LDO_REG8", 0x49, 0x1f, 1800000, 100000 },
75 	{ }
76 };
77 
78 struct rkpmic_softc {
79 	struct device sc_dev;
80 	i2c_tag_t sc_tag;
81 	i2c_addr_t sc_addr;
82 
83 	struct todr_chip_handle sc_todr;
84 	struct rkpmic_regdata *sc_regdata;
85 };
86 
87 int	rkpmic_match(struct device *, void *, void *);
88 void	rkpmic_attach(struct device *, struct device *, void *);
89 
90 struct cfattach rkpmic_ca = {
91 	sizeof(struct rkpmic_softc), rkpmic_match, rkpmic_attach
92 };
93 
94 struct cfdriver rkpmic_cd = {
95 	NULL, "rkpmic", DV_DULL
96 };
97 
98 void	rkpmic_attach_regulator(struct rkpmic_softc *, int);
99 uint8_t	rkpmic_reg_read(struct rkpmic_softc *, int);
100 void	rkpmic_reg_write(struct rkpmic_softc *, int, uint8_t);
101 int	rkpmic_clock_read(struct rkpmic_softc *, struct clock_ymdhms *);
102 int	rkpmic_clock_write(struct rkpmic_softc *, struct clock_ymdhms *);
103 int	rkpmic_gettime(struct todr_chip_handle *, struct timeval *);
104 int	rkpmic_settime(struct todr_chip_handle *, struct timeval *);
105 
106 int
107 rkpmic_match(struct device *parent, void *match, void *aux)
108 {
109 	struct i2c_attach_args *ia = aux;
110 
111 	return (strcmp(ia->ia_name, "rockchip,rk805") == 0 ||
112 	    strcmp(ia->ia_name, "rockchip,rk808") == 0);
113 }
114 
115 void
116 rkpmic_attach(struct device *parent, struct device *self, void *aux)
117 {
118 	struct rkpmic_softc *sc = (struct rkpmic_softc *)self;
119 	struct i2c_attach_args *ia = aux;
120 	int node = *(int *)ia->ia_cookie;
121 	const char *chip;
122 
123 	sc->sc_tag = ia->ia_tag;
124 	sc->sc_addr = ia->ia_addr;
125 
126 	sc->sc_todr.cookie = sc;
127 	sc->sc_todr.todr_gettime = rkpmic_gettime;
128 	sc->sc_todr.todr_settime = rkpmic_settime;
129 	if (todr_handle == NULL)
130 		todr_handle = &sc->sc_todr;
131 
132 	if (OF_is_compatible(node, "rockchip,rk805")) {
133 		chip = "RK805";
134 		sc->sc_regdata = rk805_regdata;
135 	} else {
136 		chip = "RK808";
137 		sc->sc_regdata = rk808_regdata;
138 	}
139 	printf(": %s\n", chip);
140 
141 	node = OF_getnodebyname(node, "regulators");
142 	if (node == 0)
143 		return;
144 	for (node = OF_child(node); node; node = OF_peer(node))
145 		rkpmic_attach_regulator(sc, node);
146 }
147 
148 struct rkpmic_regulator {
149 	struct rkpmic_softc *rr_sc;
150 
151 	uint8_t rr_reg, rr_mask;
152 	uint32_t rr_base, rr_delta;
153 
154 	struct regulator_device rr_rd;
155 };
156 
157 uint32_t rkpmic_get_voltage(void *);
158 int	rkpmic_set_voltage(void *, uint32_t);
159 
160 void
161 rkpmic_attach_regulator(struct rkpmic_softc *sc, int node)
162 {
163 	struct rkpmic_regulator *rr;
164 	char name[32];
165 	int i;
166 
167 	name[0] = 0;
168 	OF_getprop(node, "name", name, sizeof(name));
169 	name[sizeof(name) - 1] = 0;
170 	for (i = 0; sc->sc_regdata[i].name; i++) {
171 		if (strcmp(sc->sc_regdata[i].name, name) == 0)
172 			break;
173 	}
174 	if (sc->sc_regdata[i].name == NULL)
175 		return;
176 
177 	rr = malloc(sizeof(*rr), M_DEVBUF, M_WAITOK | M_ZERO);
178 	rr->rr_sc = sc;
179 
180 	rr->rr_reg = sc->sc_regdata[i].reg;
181 	rr->rr_mask = sc->sc_regdata[i].mask;
182 	rr->rr_base = sc->sc_regdata[i].base;
183 	rr->rr_delta = sc->sc_regdata[i].delta;
184 
185 	rr->rr_rd.rd_node = node;
186 	rr->rr_rd.rd_cookie = rr;
187 	rr->rr_rd.rd_get_voltage = rkpmic_get_voltage;
188 	rr->rr_rd.rd_set_voltage = rkpmic_set_voltage;
189 	regulator_register(&rr->rr_rd);
190 }
191 
192 uint32_t
193 rkpmic_get_voltage(void *cookie)
194 {
195 	struct rkpmic_regulator *rr = cookie;
196 	uint8_t vsel;
197 
198 	vsel = rkpmic_reg_read(rr->rr_sc, rr->rr_reg);
199 	return rr->rr_base + (vsel & rr->rr_mask) * rr->rr_delta;
200 }
201 
202 int
203 rkpmic_set_voltage(void *cookie, uint32_t voltage)
204 {
205 	struct rkpmic_regulator *rr = cookie;
206 	uint32_t vmin = rr->rr_base;
207 	uint32_t vmax = vmin + rr->rr_mask * rr->rr_delta;
208 	uint8_t vsel;
209 
210 	if (voltage < vmin || voltage > vmax)
211 		return EINVAL;
212 
213 	vsel = rkpmic_reg_read(rr->rr_sc, rr->rr_reg);
214 	vsel &= ~rr->rr_mask;
215 	vsel |= (voltage - rr->rr_base) / rr->rr_delta;
216 	rkpmic_reg_write(rr->rr_sc, rr->rr_reg, vsel);
217 
218 	return 0;
219 }
220 
221 int
222 rkpmic_gettime(struct todr_chip_handle *handle, struct timeval *tv)
223 {
224 	struct rkpmic_softc *sc = handle->cookie;
225 	struct clock_ymdhms dt;
226 	time_t secs;
227 	int error;
228 
229 	error = rkpmic_clock_read(sc, &dt);
230 	if (error)
231 		return error;
232 
233 	if (dt.dt_sec > 59 || dt.dt_min > 59 || dt.dt_hour > 23 ||
234 	    dt.dt_day > 31 || dt.dt_day == 0 ||
235 	    dt.dt_mon > 12 || dt.dt_mon == 0 ||
236 	    dt.dt_year < POSIX_BASE_YEAR)
237 		return EINVAL;
238 
239 	/*
240 	 * The RTC thinks November has 31 days.  Match what Linux does
241 	 * and undo the damage by considering the calenders to be in
242 	 * sync on January 1st 2016.
243 	 */
244 	secs = clock_ymdhms_to_secs(&dt);
245 	secs += (dt.dt_year - 2016 + (dt.dt_mon == 12 ? 1 : 0)) * 86400;
246 
247 	tv->tv_sec = secs;
248 	tv->tv_usec = 0;
249 	return 0;
250 }
251 
252 int
253 rkpmic_settime(struct todr_chip_handle *handle, struct timeval *tv)
254 {
255 	struct rkpmic_softc *sc = handle->cookie;
256 	struct clock_ymdhms dt;
257 	time_t secs;
258 
259 	/*
260 	 * Take care of the November 31st braindamage here as well.
261 	 * Don't try to be clever, just do the conversion in two
262 	 * steps, first taking care of November 31 in previous years,
263 	 * and then taking care of days in December of the current
264 	 * year.  Decmber 1st turns into November 31st!
265 	 */
266 	secs = tv->tv_sec;
267 	clock_secs_to_ymdhms(secs, &dt);
268 	secs -= (dt.dt_year - 2016) * 86400;
269 	clock_secs_to_ymdhms(secs, &dt);
270 	if (dt.dt_mon == 12) {
271 		dt.dt_day--;
272 		if (dt.dt_day == 0) {
273 			dt.dt_mon = 11;
274 			dt.dt_day = 31;
275 		}
276 	}
277 
278 	return rkpmic_clock_write(sc, &dt);
279 }
280 
281 uint8_t
282 rkpmic_reg_read(struct rkpmic_softc *sc, int reg)
283 {
284 	uint8_t cmd = reg;
285 	uint8_t val;
286 	int error;
287 
288 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
289 	error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
290 	    &cmd, sizeof cmd, &val, sizeof val, I2C_F_POLL);
291 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
292 
293 	if (error) {
294 		printf("%s: can't read register 0x%02x\n",
295 		    sc->sc_dev.dv_xname, reg);
296 		val = 0xff;
297 	}
298 
299 	return val;
300 }
301 
302 void
303 rkpmic_reg_write(struct rkpmic_softc *sc, int reg, uint8_t val)
304 {
305 	uint8_t cmd = reg;
306 	int error;
307 
308 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
309 	error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
310 	    &cmd, sizeof cmd, &val, sizeof val, I2C_F_POLL);
311 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
312 
313 	if (error) {
314 		printf("%s: can't write register 0x%02x\n",
315 		    sc->sc_dev.dv_xname, reg);
316 	}
317 }
318 
319 int
320 rkpmic_clock_read(struct rkpmic_softc *sc, struct clock_ymdhms *dt)
321 {
322 	uint8_t regs[RK808_NRTC_REGS];
323 	uint8_t cmd = RK808_SECONDS;
324 	uint8_t status;
325 	int error;
326 
327 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
328 	error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
329 	    &cmd, sizeof(cmd), regs, RK808_NRTC_REGS, I2C_F_POLL);
330 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
331 
332 	if (error) {
333 		printf("%s: can't read RTC\n", sc->sc_dev.dv_xname);
334 		return error;
335 	}
336 
337 	/*
338 	 * Convert the RK808's register values into something useable.
339 	 */
340 	dt->dt_sec = FROMBCD(regs[0]);
341 	dt->dt_min = FROMBCD(regs[1]);
342 	dt->dt_hour = FROMBCD(regs[2]);
343 	dt->dt_day = FROMBCD(regs[3]);
344 	dt->dt_mon = FROMBCD(regs[4]);
345 	dt->dt_year = FROMBCD(regs[5]) + 2000;
346 
347 	/* Consider the time to be invalid if the POWER_UP bit is set. */
348 	status = rkpmic_reg_read(sc, RK808_RTC_STATUS);
349 	if (status & RK808_RTC_STATUS_POWER_UP)
350 		return EINVAL;
351 
352 	return 0;
353 }
354 
355 int
356 rkpmic_clock_write(struct rkpmic_softc *sc, struct clock_ymdhms *dt)
357 {
358 	uint8_t regs[RK808_NRTC_REGS];
359 	uint8_t cmd = RK808_SECONDS;
360 	int error;
361 
362 	/*
363 	 * Convert our time representation into something the RK808
364 	 * can understand.
365 	 */
366 	regs[0] = TOBCD(dt->dt_sec);
367 	regs[1] = TOBCD(dt->dt_min);
368 	regs[2] = TOBCD(dt->dt_hour);
369 	regs[3] = TOBCD(dt->dt_day);
370 	regs[4] = TOBCD(dt->dt_mon);
371 	regs[5] = TOBCD(dt->dt_year - 2000);
372 	regs[6] = TOBCD(dt->dt_wday);
373 
374 	/* Stop RTC such that we can write to it. */
375 	rkpmic_reg_write(sc, RK808_RTC_CTRL, RK808_RTC_CTRL_STOP_RTC);
376 
377 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
378 	error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
379 	    &cmd, sizeof(cmd), regs, RK808_NRTC_REGS, I2C_F_POLL);
380 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
381 
382 	/* Restart RTC. */
383 	rkpmic_reg_write(sc, RK808_RTC_CTRL, 0);
384 
385 	if (error) {
386 		printf("%s: can't write RTC\n", sc->sc_dev.dv_xname);
387 		return error;
388 	}
389 
390 	/* Clear POWER_UP bit to indicate the time is now valid. */
391 	rkpmic_reg_write(sc, RK808_RTC_STATUS, RK808_RTC_STATUS_POWER_UP);
392 
393 	return 0;
394 }
395