xref: /openbsd-src/sys/dev/fdt/rkpmic.c (revision ae3cb403620ab940fbaabb3055fac045a63d56b7)
1 /*	$OpenBSD: rkpmic.c,v 1.3 2017/11/18 20:29:51 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 rk808_regdata[] = {
54 	{ "DCDC_REG1", 0x2f, 0x3f, 712500, 12500 },
55 	{ "DCDC_REG2", 0x33, 0x3f, 712500, 12500 },
56 	{ "DCDC_REG4", 0x38, 0x0f, 1800000, 100000 },
57 	{ "LDO_REG1", 0x3b, 0x1f, 1800000, 100000 },
58 	{ "LDO_REG2", 0x3d, 0x1f, 1800000, 100000 },
59 	{ "LDO_REG3", 0x3f, 0x0f, 800000, 100000 },
60 	{ "LDO_REG4", 0x41, 0x1f, 1800000, 100000 },
61 	{ "LDO_REG5", 0x43, 0x1f, 1800000, 100000 },
62 	{ "LDO_REG6", 0x45, 0x1f, 800000, 100000 },
63 	{ "LDO_REG7", 0x47, 0x1f, 800000, 100000 },
64 	{ "LDO_REG8", 0x49, 0x1f, 1800000, 100000 },
65 };
66 
67 struct rkpmic_softc {
68 	struct device sc_dev;
69 	i2c_tag_t sc_tag;
70 	i2c_addr_t sc_addr;
71 
72 	struct todr_chip_handle sc_todr;
73 };
74 
75 int	rkpmic_match(struct device *, void *, void *);
76 void	rkpmic_attach(struct device *, struct device *, void *);
77 
78 struct cfattach rkpmic_ca = {
79 	sizeof(struct rkpmic_softc), rkpmic_match, rkpmic_attach
80 };
81 
82 struct cfdriver rkpmic_cd = {
83 	NULL, "rkpmic", DV_DULL
84 };
85 
86 void	rkpmic_attach_regulator(struct rkpmic_softc *, int);
87 uint8_t	rkpmic_reg_read(struct rkpmic_softc *, int);
88 void	rkpmic_reg_write(struct rkpmic_softc *, int, uint8_t);
89 int	rkpmic_clock_read(struct rkpmic_softc *, struct clock_ymdhms *);
90 int	rkpmic_clock_write(struct rkpmic_softc *, struct clock_ymdhms *);
91 int	rkpmic_gettime(struct todr_chip_handle *, struct timeval *);
92 int	rkpmic_settime(struct todr_chip_handle *, struct timeval *);
93 
94 int
95 rkpmic_match(struct device *parent, void *match, void *aux)
96 {
97 	struct i2c_attach_args *ia = aux;
98 	int node = *(int *)ia->ia_cookie;
99 
100 	return (OF_is_compatible(node, "rockchip,rk808"));
101 }
102 
103 void
104 rkpmic_attach(struct device *parent, struct device *self, void *aux)
105 {
106 	struct rkpmic_softc *sc = (struct rkpmic_softc *)self;
107 	struct i2c_attach_args *ia = aux;
108 	int node = *(int *)ia->ia_cookie;
109 
110 	sc->sc_tag = ia->ia_tag;
111 	sc->sc_addr = ia->ia_addr;
112 
113 	printf("\n");
114 
115 	sc->sc_todr.cookie = sc;
116 	sc->sc_todr.todr_gettime = rkpmic_gettime;
117 	sc->sc_todr.todr_settime = rkpmic_settime;
118 	todr_handle = &sc->sc_todr;
119 
120 	node = OF_getnodebyname(node, "regulators");
121 	if (node == 0)
122 		return;
123 	for (node = OF_child(node); node; node = OF_peer(node))
124 		rkpmic_attach_regulator(sc, node);
125 }
126 
127 struct rkpmic_regulator {
128 	struct rkpmic_softc *rr_sc;
129 
130 	uint8_t rr_reg, rr_mask;
131 	uint32_t rr_base, rr_delta;
132 
133 	struct regulator_device rr_rd;
134 };
135 
136 uint32_t rkpmic_get_voltage(void *);
137 
138 void
139 rkpmic_attach_regulator(struct rkpmic_softc *sc, int node)
140 {
141 	struct rkpmic_regulator *rr;
142 	char name[32];
143 	int i;
144 
145 	name[0] = 0;
146 	OF_getprop(node, "name", name, sizeof(name));
147 	name[sizeof(name) - 1] = 0;
148 	for (i = 0; i < nitems(rk808_regdata); i++) {
149 		if (strcmp(rk808_regdata[i].name, name) == 0)
150 			break;
151 	}
152 	if (i == nitems(rk808_regdata))
153 		return;
154 
155 	rr = malloc(sizeof(*rr), M_DEVBUF, M_WAITOK | M_ZERO);
156 	rr->rr_sc = sc;
157 
158 	rr->rr_reg = rk808_regdata[i].reg;
159 	rr->rr_mask = rk808_regdata[i].mask;
160 	rr->rr_base = rk808_regdata[i].base;
161 	rr->rr_delta = rk808_regdata[i].delta;
162 
163 	rr->rr_rd.rd_node = node;
164 	rr->rr_rd.rd_cookie = rr;
165 	rr->rr_rd.rd_get_voltage = rkpmic_get_voltage;
166 	regulator_register(&rr->rr_rd);
167 }
168 
169 uint32_t
170 rkpmic_get_voltage(void *cookie)
171 {
172 	struct rkpmic_regulator *rr = cookie;
173 	uint8_t value;
174 
175 	value = rkpmic_reg_read(rr->rr_sc, rr->rr_reg);
176 	return rr->rr_base + (value & rr->rr_mask) * rr->rr_delta;
177 }
178 
179 int
180 rkpmic_gettime(struct todr_chip_handle *handle, struct timeval *tv)
181 {
182 	struct rkpmic_softc *sc = handle->cookie;
183 	struct clock_ymdhms dt;
184 	time_t secs;
185 	int error;
186 
187 	error = rkpmic_clock_read(sc, &dt);
188 	if (error)
189 		return error;
190 
191 	if (dt.dt_sec > 59 || dt.dt_min > 59 || dt.dt_hour > 23 ||
192 	    dt.dt_day > 31 || dt.dt_day == 0 ||
193 	    dt.dt_mon > 12 || dt.dt_mon == 0 ||
194 	    dt.dt_year < POSIX_BASE_YEAR)
195 		return EINVAL;
196 
197 	/*
198 	 * The RTC thinks November has 31 days.  Match what Linux does
199 	 * and undo the damage by considering the calenders to be in
200 	 * sync on January 1st 2016.
201 	 */
202 	secs = clock_ymdhms_to_secs(&dt);
203 	secs += (dt.dt_year - 2016 + (dt.dt_mon == 12 ? 1 : 0)) * 86400;
204 
205 	tv->tv_sec = secs;
206 	tv->tv_usec = 0;
207 	return 0;
208 }
209 
210 int
211 rkpmic_settime(struct todr_chip_handle *handle, struct timeval *tv)
212 {
213 	struct rkpmic_softc *sc = handle->cookie;
214 	struct clock_ymdhms dt;
215 	time_t secs;
216 
217 	/*
218 	 * Take care of the November 31st braindamage here as well.
219 	 * Don't try to be clever, just do the conversion in two
220 	 * steps, first taking care of November 31 in previous years,
221 	 * and then taking care of days in December of the current
222 	 * year.  Decmber 1st turns into November 31st!
223 	 */
224 	secs = tv->tv_sec;
225 	clock_secs_to_ymdhms(secs, &dt);
226 	secs -= (dt.dt_year - 2016) * 86400;
227 	clock_secs_to_ymdhms(secs, &dt);
228 	if (dt.dt_mon == 12) {
229 		dt.dt_day--;
230 		if (dt.dt_day == 0) {
231 			dt.dt_mon = 11;
232 			dt.dt_day = 31;
233 		}
234 	}
235 
236 	return rkpmic_clock_write(sc, &dt);
237 }
238 
239 uint8_t
240 rkpmic_reg_read(struct rkpmic_softc *sc, int reg)
241 {
242 	uint8_t cmd = reg;
243 	uint8_t val;
244 	int error;
245 
246 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
247 	error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
248 	    &cmd, sizeof cmd, &val, sizeof val, I2C_F_POLL);
249 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
250 
251 	if (error) {
252 		printf("%s: can't read register 0x%02x\n",
253 		    sc->sc_dev.dv_xname, reg);
254 		val = 0xff;
255 	}
256 
257 	return val;
258 }
259 
260 void
261 rkpmic_reg_write(struct rkpmic_softc *sc, int reg, uint8_t val)
262 {
263 	uint8_t cmd = reg;
264 	int error;
265 
266 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
267 	error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
268 	    &cmd, sizeof cmd, &val, sizeof val, I2C_F_POLL);
269 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
270 
271 	if (error) {
272 		printf("%s: can't write register 0x%02x\n",
273 		    sc->sc_dev.dv_xname, reg);
274 	}
275 }
276 
277 int
278 rkpmic_clock_read(struct rkpmic_softc *sc, struct clock_ymdhms *dt)
279 {
280 	uint8_t regs[RK808_NRTC_REGS];
281 	uint8_t cmd = RK808_SECONDS;
282 	uint8_t status;
283 	int error;
284 
285 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
286 	error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
287 	    &cmd, sizeof(cmd), regs, RK808_NRTC_REGS, I2C_F_POLL);
288 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
289 
290 	if (error) {
291 		printf("%s: can't read RTC\n", sc->sc_dev.dv_xname);
292 		return error;
293 	}
294 
295 	/*
296 	 * Convert the RK808's register values into something useable.
297 	 */
298 	dt->dt_sec = FROMBCD(regs[0]);
299 	dt->dt_min = FROMBCD(regs[1]);
300 	dt->dt_hour = FROMBCD(regs[2]);
301 	dt->dt_day = FROMBCD(regs[3]);
302 	dt->dt_mon = FROMBCD(regs[4]);
303 	dt->dt_year = FROMBCD(regs[5]) + 2000;
304 
305 	/* Consider the time to be invalid if the POWER_UP bit is set. */
306 	status = rkpmic_reg_read(sc, RK808_RTC_STATUS);
307 	if (status & RK808_RTC_STATUS_POWER_UP)
308 		return EINVAL;
309 
310 	return 0;
311 }
312 
313 int
314 rkpmic_clock_write(struct rkpmic_softc *sc, struct clock_ymdhms *dt)
315 {
316 	uint8_t regs[RK808_NRTC_REGS];
317 	uint8_t cmd = RK808_SECONDS;
318 	int error;
319 
320 	/*
321 	 * Convert our time representation into something the RK808
322 	 * can understand.
323 	 */
324 	regs[0] = TOBCD(dt->dt_sec);
325 	regs[1] = TOBCD(dt->dt_min);
326 	regs[2] = TOBCD(dt->dt_hour);
327 	regs[3] = TOBCD(dt->dt_day);
328 	regs[4] = TOBCD(dt->dt_mon);
329 	regs[5] = TOBCD(dt->dt_year - 2000);
330 	regs[6] = TOBCD(dt->dt_wday);
331 
332 	/* Stop RTC such that we can write to it. */
333 	rkpmic_reg_write(sc, RK808_RTC_CTRL, RK808_RTC_CTRL_STOP_RTC);
334 
335 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
336 	error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
337 	    &cmd, sizeof(cmd), regs, RK808_NRTC_REGS, I2C_F_POLL);
338 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
339 
340 	/* Restart RTC. */
341 	rkpmic_reg_write(sc, RK808_RTC_CTRL, 0);
342 
343 	if (error) {
344 		printf("%s: can't write RTC\n", sc->sc_dev.dv_xname);
345 		return error;
346 	}
347 
348 	/* Clear POWER_UP bit to indicate the time is now valid. */
349 	rkpmic_reg_write(sc, RK808_RTC_STATUS, RK808_RTC_STATUS_POWER_UP);
350 
351 	return 0;
352 }
353