xref: /openbsd-src/sys/dev/fdt/rkpmic.c (revision 505ee9ea3b177e2387d907a91ca7da069f3f14d8)
1 /*	$OpenBSD: rkpmic.c,v 1.6 2018/07/31 10:09:25 kettenis 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 	int node = *(int *)ia->ia_cookie;
111 
112 	return (OF_is_compatible(node, "rockchip,rk805") ||
113 		OF_is_compatible(node, "rockchip,rk808"));
114 }
115 
116 void
117 rkpmic_attach(struct device *parent, struct device *self, void *aux)
118 {
119 	struct rkpmic_softc *sc = (struct rkpmic_softc *)self;
120 	struct i2c_attach_args *ia = aux;
121 	int node = *(int *)ia->ia_cookie;
122 	const char *chip;
123 
124 	sc->sc_tag = ia->ia_tag;
125 	sc->sc_addr = ia->ia_addr;
126 
127 	sc->sc_todr.cookie = sc;
128 	sc->sc_todr.todr_gettime = rkpmic_gettime;
129 	sc->sc_todr.todr_settime = rkpmic_settime;
130 	if (todr_handle == NULL)
131 		todr_handle = &sc->sc_todr;
132 
133 	if (OF_is_compatible(node, "rockchip,rk805")) {
134 		chip = "RK805";
135 		sc->sc_regdata = rk805_regdata;
136 	} else {
137 		chip = "RK808";
138 		sc->sc_regdata = rk808_regdata;
139 	}
140 	printf(": %s\n", chip);
141 
142 	node = OF_getnodebyname(node, "regulators");
143 	if (node == 0)
144 		return;
145 	for (node = OF_child(node); node; node = OF_peer(node))
146 		rkpmic_attach_regulator(sc, node);
147 }
148 
149 struct rkpmic_regulator {
150 	struct rkpmic_softc *rr_sc;
151 
152 	uint8_t rr_reg, rr_mask;
153 	uint32_t rr_base, rr_delta;
154 
155 	struct regulator_device rr_rd;
156 };
157 
158 uint32_t rkpmic_get_voltage(void *);
159 int	rkpmic_set_voltage(void *, uint32_t);
160 
161 void
162 rkpmic_attach_regulator(struct rkpmic_softc *sc, int node)
163 {
164 	struct rkpmic_regulator *rr;
165 	char name[32];
166 	int i;
167 
168 	name[0] = 0;
169 	OF_getprop(node, "name", name, sizeof(name));
170 	name[sizeof(name) - 1] = 0;
171 	for (i = 0; sc->sc_regdata[i].name; i++) {
172 		if (strcmp(sc->sc_regdata[i].name, name) == 0)
173 			break;
174 	}
175 	if (sc->sc_regdata[i].name == NULL)
176 		return;
177 
178 	rr = malloc(sizeof(*rr), M_DEVBUF, M_WAITOK | M_ZERO);
179 	rr->rr_sc = sc;
180 
181 	rr->rr_reg = sc->sc_regdata[i].reg;
182 	rr->rr_mask = sc->sc_regdata[i].mask;
183 	rr->rr_base = sc->sc_regdata[i].base;
184 	rr->rr_delta = sc->sc_regdata[i].delta;
185 
186 	rr->rr_rd.rd_node = node;
187 	rr->rr_rd.rd_cookie = rr;
188 	rr->rr_rd.rd_get_voltage = rkpmic_get_voltage;
189 	rr->rr_rd.rd_set_voltage = rkpmic_set_voltage;
190 	regulator_register(&rr->rr_rd);
191 }
192 
193 uint32_t
194 rkpmic_get_voltage(void *cookie)
195 {
196 	struct rkpmic_regulator *rr = cookie;
197 	uint8_t vsel;
198 
199 	vsel = rkpmic_reg_read(rr->rr_sc, rr->rr_reg);
200 	return rr->rr_base + (vsel & rr->rr_mask) * rr->rr_delta;
201 }
202 
203 int
204 rkpmic_set_voltage(void *cookie, uint32_t voltage)
205 {
206 	struct rkpmic_regulator *rr = cookie;
207 	uint32_t vmin = rr->rr_base;
208 	uint32_t vmax = vmin + rr->rr_mask * rr->rr_delta;
209 	uint8_t vsel;
210 
211 	if (voltage < vmin || voltage > vmax)
212 		return EINVAL;
213 
214 	vsel = rkpmic_reg_read(rr->rr_sc, rr->rr_reg);
215 	vsel &= ~rr->rr_mask;
216 	vsel |= (voltage - rr->rr_base) / rr->rr_delta;
217 	rkpmic_reg_write(rr->rr_sc, rr->rr_reg, vsel);
218 
219 	return 0;
220 }
221 
222 int
223 rkpmic_gettime(struct todr_chip_handle *handle, struct timeval *tv)
224 {
225 	struct rkpmic_softc *sc = handle->cookie;
226 	struct clock_ymdhms dt;
227 	time_t secs;
228 	int error;
229 
230 	error = rkpmic_clock_read(sc, &dt);
231 	if (error)
232 		return error;
233 
234 	if (dt.dt_sec > 59 || dt.dt_min > 59 || dt.dt_hour > 23 ||
235 	    dt.dt_day > 31 || dt.dt_day == 0 ||
236 	    dt.dt_mon > 12 || dt.dt_mon == 0 ||
237 	    dt.dt_year < POSIX_BASE_YEAR)
238 		return EINVAL;
239 
240 	/*
241 	 * The RTC thinks November has 31 days.  Match what Linux does
242 	 * and undo the damage by considering the calenders to be in
243 	 * sync on January 1st 2016.
244 	 */
245 	secs = clock_ymdhms_to_secs(&dt);
246 	secs += (dt.dt_year - 2016 + (dt.dt_mon == 12 ? 1 : 0)) * 86400;
247 
248 	tv->tv_sec = secs;
249 	tv->tv_usec = 0;
250 	return 0;
251 }
252 
253 int
254 rkpmic_settime(struct todr_chip_handle *handle, struct timeval *tv)
255 {
256 	struct rkpmic_softc *sc = handle->cookie;
257 	struct clock_ymdhms dt;
258 	time_t secs;
259 
260 	/*
261 	 * Take care of the November 31st braindamage here as well.
262 	 * Don't try to be clever, just do the conversion in two
263 	 * steps, first taking care of November 31 in previous years,
264 	 * and then taking care of days in December of the current
265 	 * year.  Decmber 1st turns into November 31st!
266 	 */
267 	secs = tv->tv_sec;
268 	clock_secs_to_ymdhms(secs, &dt);
269 	secs -= (dt.dt_year - 2016) * 86400;
270 	clock_secs_to_ymdhms(secs, &dt);
271 	if (dt.dt_mon == 12) {
272 		dt.dt_day--;
273 		if (dt.dt_day == 0) {
274 			dt.dt_mon = 11;
275 			dt.dt_day = 31;
276 		}
277 	}
278 
279 	return rkpmic_clock_write(sc, &dt);
280 }
281 
282 uint8_t
283 rkpmic_reg_read(struct rkpmic_softc *sc, int reg)
284 {
285 	uint8_t cmd = reg;
286 	uint8_t val;
287 	int error;
288 
289 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
290 	error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
291 	    &cmd, sizeof cmd, &val, sizeof val, I2C_F_POLL);
292 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
293 
294 	if (error) {
295 		printf("%s: can't read register 0x%02x\n",
296 		    sc->sc_dev.dv_xname, reg);
297 		val = 0xff;
298 	}
299 
300 	return val;
301 }
302 
303 void
304 rkpmic_reg_write(struct rkpmic_softc *sc, int reg, uint8_t val)
305 {
306 	uint8_t cmd = reg;
307 	int error;
308 
309 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
310 	error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
311 	    &cmd, sizeof cmd, &val, sizeof val, I2C_F_POLL);
312 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
313 
314 	if (error) {
315 		printf("%s: can't write register 0x%02x\n",
316 		    sc->sc_dev.dv_xname, reg);
317 	}
318 }
319 
320 int
321 rkpmic_clock_read(struct rkpmic_softc *sc, struct clock_ymdhms *dt)
322 {
323 	uint8_t regs[RK808_NRTC_REGS];
324 	uint8_t cmd = RK808_SECONDS;
325 	uint8_t status;
326 	int error;
327 
328 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
329 	error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
330 	    &cmd, sizeof(cmd), regs, RK808_NRTC_REGS, I2C_F_POLL);
331 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
332 
333 	if (error) {
334 		printf("%s: can't read RTC\n", sc->sc_dev.dv_xname);
335 		return error;
336 	}
337 
338 	/*
339 	 * Convert the RK808's register values into something useable.
340 	 */
341 	dt->dt_sec = FROMBCD(regs[0]);
342 	dt->dt_min = FROMBCD(regs[1]);
343 	dt->dt_hour = FROMBCD(regs[2]);
344 	dt->dt_day = FROMBCD(regs[3]);
345 	dt->dt_mon = FROMBCD(regs[4]);
346 	dt->dt_year = FROMBCD(regs[5]) + 2000;
347 
348 	/* Consider the time to be invalid if the POWER_UP bit is set. */
349 	status = rkpmic_reg_read(sc, RK808_RTC_STATUS);
350 	if (status & RK808_RTC_STATUS_POWER_UP)
351 		return EINVAL;
352 
353 	return 0;
354 }
355 
356 int
357 rkpmic_clock_write(struct rkpmic_softc *sc, struct clock_ymdhms *dt)
358 {
359 	uint8_t regs[RK808_NRTC_REGS];
360 	uint8_t cmd = RK808_SECONDS;
361 	int error;
362 
363 	/*
364 	 * Convert our time representation into something the RK808
365 	 * can understand.
366 	 */
367 	regs[0] = TOBCD(dt->dt_sec);
368 	regs[1] = TOBCD(dt->dt_min);
369 	regs[2] = TOBCD(dt->dt_hour);
370 	regs[3] = TOBCD(dt->dt_day);
371 	regs[4] = TOBCD(dt->dt_mon);
372 	regs[5] = TOBCD(dt->dt_year - 2000);
373 	regs[6] = TOBCD(dt->dt_wday);
374 
375 	/* Stop RTC such that we can write to it. */
376 	rkpmic_reg_write(sc, RK808_RTC_CTRL, RK808_RTC_CTRL_STOP_RTC);
377 
378 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
379 	error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
380 	    &cmd, sizeof(cmd), regs, RK808_NRTC_REGS, I2C_F_POLL);
381 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
382 
383 	/* Restart RTC. */
384 	rkpmic_reg_write(sc, RK808_RTC_CTRL, 0);
385 
386 	if (error) {
387 		printf("%s: can't write RTC\n", sc->sc_dev.dv_xname);
388 		return error;
389 	}
390 
391 	/* Clear POWER_UP bit to indicate the time is now valid. */
392 	rkpmic_reg_write(sc, RK808_RTC_STATUS, RK808_RTC_STATUS_POWER_UP);
393 
394 	return 0;
395 }
396