xref: /netbsd-src/sys/dev/i2c/as3722.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
1 /* $NetBSD: as3722.c,v 1.24 2021/08/07 16:19:11 thorpej Exp $ */
2 
3 /*-
4  * Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "opt_fdt.h"
30 
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: as3722.c,v 1.24 2021/08/07 16:19:11 thorpej Exp $");
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/device.h>
38 #include <sys/conf.h>
39 #include <sys/bus.h>
40 #include <sys/kmem.h>
41 #include <sys/wdog.h>
42 
43 #include <dev/clock_subr.h>
44 
45 #include <dev/sysmon/sysmonvar.h>
46 
47 #include <dev/i2c/i2cvar.h>
48 #include <dev/i2c/as3722.h>
49 
50 #ifdef FDT
51 #include <dev/fdt/fdtvar.h>
52 #endif
53 
54 #define	AS3722_I2C_ADDR			0x40
55 
56 #define AS3722_START_YEAR		2000
57 
58 #define AS3722_SD0_VOLTAGE_REG		0x00
59 
60 #define AS3722_SD4_VOLTAGE_REG		0x04
61 
62 #define AS3722_GPIO0_CTRL_REG		0x08
63 #define AS3722_GPIO0_CTRL_INVERT	__BIT(7)
64 #define AS3722_GPIO0_CTRL_IOSF		__BITS(6,3)
65 #define AS3722_GPIO0_CTRL_IOSF_GPIO	0
66 #define AS3722_GPIO0_CTRL_IOSF_WATCHDOG	9
67 #define AS3722_GPIO0_CTRL_MODE		__BITS(2,0)
68 #define AS3722_GPIO0_CTRL_MODE_PULLDOWN	5
69 
70 #define AS3722_LDO6_VOLTAGE_REG		0x16
71 
72 #define AS3722_RESET_CTRL_REG		0x36
73 #define AS3722_RESET_CTRL_POWER_OFF	__BIT(1)
74 #define AS3722_RESET_CTRL_FORCE_RESET	__BIT(0)
75 
76 #define AS3722_WATCHDOG_CTRL_REG	0x38
77 #define AS3722_WATCHDOG_CTRL_MODE	__BITS(2,1)
78 #define AS3722_WATCHDOG_CTRL_ON		__BIT(0)
79 
80 #define AS3722_WATCHDOG_TIMER_REG	0x46
81 #define AS3722_WATCHDOG_TIMER_TIMER	__BITS(6,0)
82 
83 #define AS3722_WATCHDOG_SIGNAL_REG	0x48
84 #define AS3722_WATCHDOG_SIGNAL_PWM_DIV	__BITS(7,6)
85 #define AS3722_WATCHDOG_SIGNAL_SW_SIG	__BIT(0)
86 
87 #define AS3722_SDCONTROL_REG		0x4d
88 #define AS3722_SDCONTROL_SD4_ENABLE	__BIT(4)
89 
90 #define AS3722_LDOCONTROL0_REG		0x4e
91 
92 #define AS3722_RTC_CONTROL_REG		0x60
93 #define AS3722_RTC_CONTROL_RTC_ON	__BIT(2)
94 
95 #define AS3722_RTC_SECOND_REG		0x61
96 #define AS3722_RTC_MINUTE_REG		0x62
97 #define AS3722_RTC_HOUR_REG		0x63
98 #define AS3722_RTC_DAY_REG		0x64
99 #define AS3722_RTC_MONTH_REG		0x65
100 #define AS3722_RTC_YEAR_REG		0x66
101 #define AS3722_RTC_ACCESS_REG		0x6f
102 
103 #define AS3722_ASIC_ID1_REG		0x90
104 #define AS3722_ASIC_ID2_REG		0x91
105 
106 #define AS3722_FUSE7_REG		0xa7
107 #define AS3722_FUSE7_SD0_V_MINUS_200MV	__BIT(4)
108 
109 struct as3722_softc {
110 	device_t	sc_dev;
111 	i2c_tag_t	sc_i2c;
112 	i2c_addr_t	sc_addr;
113 	int		sc_phandle;
114 	int		sc_flags;
115 #define AS3722_FLAG_SD0_V_MINUS_200MV 0x01
116 
117 	struct sysmon_wdog sc_smw;
118 	struct todr_chip_handle sc_todr;
119 };
120 
121 #ifdef FDT
122 static int	as3722reg_set_voltage_sd0(device_t, u_int, u_int);
123 static int	as3722reg_get_voltage_sd0(device_t, u_int *);
124 static int	as3722reg_set_voltage_sd4(device_t, u_int, u_int);
125 static int	as3722reg_get_voltage_sd4(device_t, u_int *);
126 static int	as3722reg_set_voltage_ldo(device_t, u_int, u_int);
127 static int	as3722reg_get_voltage_ldo(device_t, u_int *);
128 
129 static const struct as3722regdef {
130 	const char	*name;
131 	u_int		vsel_reg;
132 	u_int		vsel_mask;
133 	u_int		enable_reg;
134 	u_int		enable_mask;
135 	int		(*set)(device_t, u_int, u_int);
136 	int		(*get)(device_t, u_int *);
137 } as3722regdefs[] = {
138 	{ .name = "sd0",
139 	  .vsel_reg = AS3722_SD0_VOLTAGE_REG,
140 	  .vsel_mask = 0x7f,
141 	  .set = as3722reg_set_voltage_sd0,
142 	  .get = as3722reg_get_voltage_sd0 },
143 	{ .name = "sd4",
144 	  .vsel_reg = AS3722_SD4_VOLTAGE_REG,
145 	  .vsel_mask = 0x7f,
146 	  .enable_reg = AS3722_SDCONTROL_REG,
147 	  .enable_mask = AS3722_SDCONTROL_SD4_ENABLE,
148 	  .set = as3722reg_set_voltage_sd4,
149 	  .get = as3722reg_get_voltage_sd4 },
150 	{ .name = "ldo6",
151 	  .vsel_reg = AS3722_LDO6_VOLTAGE_REG,
152 	  .vsel_mask = 0x7f,
153 	  .enable_reg = AS3722_LDOCONTROL0_REG,
154 	  .enable_mask = 0x40,
155 	  .set = as3722reg_set_voltage_ldo,
156 	  .get = as3722reg_get_voltage_ldo },
157 };
158 
159 struct as3722reg_softc {
160 	device_t	sc_dev;
161 	int		sc_phandle;
162 	const struct as3722regdef *sc_regdef;
163 };
164 
165 struct as3722reg_attach_args {
166 	const struct as3722regdef *reg_def;
167 	int		reg_phandle;
168 };
169 #endif
170 
171 #define AS3722_WATCHDOG_DEFAULT_PERIOD	10
172 
173 static int	as3722_match(device_t, cfdata_t, void *);
174 static void	as3722_attach(device_t, device_t, void *);
175 
176 static void	as3722_wdt_attach(struct as3722_softc *);
177 static int	as3722_wdt_setmode(struct sysmon_wdog *);
178 static int	as3722_wdt_tickle(struct sysmon_wdog *);
179 
180 static void	as3722_rtc_attach(struct as3722_softc *);
181 static int	as3722_rtc_gettime(todr_chip_handle_t, struct clock_ymdhms *);
182 static int	as3722_rtc_settime(todr_chip_handle_t, struct clock_ymdhms *);
183 
184 #ifdef FDT
185 static void	as3722_regulator_attach(struct as3722_softc *);
186 static int	as3722reg_match(device_t, cfdata_t, void *);
187 static void	as3722reg_attach(device_t, device_t, void *);
188 
189 static int	as3722reg_acquire(device_t);
190 static void	as3722reg_release(device_t);
191 static int	as3722reg_enable(device_t, bool);
192 static int	as3722reg_set_voltage(device_t, u_int, u_int);
193 static int	as3722reg_get_voltage(device_t, u_int *);
194 
195 static struct fdtbus_regulator_controller_func as3722reg_funcs = {
196 	.acquire = as3722reg_acquire,
197 	.release = as3722reg_release,
198 	.enable = as3722reg_enable,
199 	.set_voltage = as3722reg_set_voltage,
200 	.get_voltage = as3722reg_get_voltage,
201 };
202 
203 static void	as3722_power_reset(device_t);
204 static void	as3722_power_poweroff(device_t);
205 
206 static struct fdtbus_power_controller_func as3722power_funcs = {
207 	.reset = as3722_power_reset,
208 	.poweroff = as3722_power_poweroff,
209 };
210 #endif
211 
212 static int	as3722_read(struct as3722_softc *, uint8_t, uint8_t *, int);
213 static int	as3722_write(struct as3722_softc *, uint8_t, uint8_t, int);
214 static int	as3722_set_clear(struct as3722_softc *, uint8_t, uint8_t,
215 				 uint8_t, int);
216 
217 CFATTACH_DECL_NEW(as3722pmic, sizeof(struct as3722_softc),
218     as3722_match, as3722_attach, NULL, NULL);
219 
220 #ifdef FDT
221 CFATTACH_DECL_NEW(as3722reg, sizeof(struct as3722reg_softc),
222     as3722reg_match, as3722reg_attach, NULL, NULL);
223 #endif
224 
225 static const struct device_compatible_entry compat_data[] = {
226 	{ .compat = "ams,as3722" },
227 	DEVICE_COMPAT_EOL
228 };
229 
230 static int
as3722_match(device_t parent,cfdata_t match,void * aux)231 as3722_match(device_t parent, cfdata_t match, void *aux)
232 {
233 	struct i2c_attach_args *ia = aux;
234 	uint8_t reg, id1;
235 	int error, match_result;
236 
237 	if (iic_use_direct_match(ia, match, compat_data, &match_result))
238 		return match_result;
239 
240 	if (ia->ia_addr != AS3722_I2C_ADDR)
241 		return 0;
242 
243 	iic_acquire_bus(ia->ia_tag, 0);
244 	reg = AS3722_ASIC_ID1_REG;
245 	error = iic_exec(ia->ia_tag, I2C_OP_READ_WITH_STOP, ia->ia_addr,
246 	    &reg, 1, &id1, 1, 0);
247 	iic_release_bus(ia->ia_tag, 0);
248 
249 	if (error == 0 && id1 == 0x0c)
250 		return I2C_MATCH_ADDRESS_AND_PROBE;
251 
252 	return 0;
253 }
254 
255 static void
as3722_attach(device_t parent,device_t self,void * aux)256 as3722_attach(device_t parent, device_t self, void *aux)
257 {
258 	struct as3722_softc * const sc = device_private(self);
259 	struct i2c_attach_args *ia = aux;
260 
261 	sc->sc_dev = self;
262 	sc->sc_i2c = ia->ia_tag;
263 	sc->sc_addr = ia->ia_addr;
264 	sc->sc_phandle = ia->ia_cookie;
265 
266 	aprint_naive("\n");
267 	aprint_normal(": AMS AS3722\n");
268 
269 	as3722_wdt_attach(sc);
270 	as3722_rtc_attach(sc);
271 #ifdef FDT
272 	as3722_regulator_attach(sc);
273 
274 	fdtbus_register_power_controller(self, sc->sc_phandle,
275 	    &as3722power_funcs);
276 #endif
277 }
278 
279 static void
as3722_wdt_attach(struct as3722_softc * sc)280 as3722_wdt_attach(struct as3722_softc *sc)
281 {
282 	int error;
283 
284 	iic_acquire_bus(sc->sc_i2c, 0);
285 	error = as3722_write(sc, AS3722_GPIO0_CTRL_REG,
286 	    __SHIFTIN(AS3722_GPIO0_CTRL_IOSF_GPIO,
287 		      AS3722_GPIO0_CTRL_IOSF) |
288 	    __SHIFTIN(AS3722_GPIO0_CTRL_MODE_PULLDOWN,
289 		      AS3722_GPIO0_CTRL_MODE),
290 	    0);
291 	error += as3722_set_clear(sc, AS3722_WATCHDOG_CTRL_REG,
292 	    __SHIFTIN(1, AS3722_WATCHDOG_CTRL_MODE), 0, 0);
293 	iic_release_bus(sc->sc_i2c, 0);
294 
295 	if (error) {
296 		aprint_error_dev(sc->sc_dev, "couldn't setup watchdog\n");
297 		return;
298 	}
299 
300 	sc->sc_smw.smw_name = device_xname(sc->sc_dev);
301 	sc->sc_smw.smw_cookie = sc;
302 	sc->sc_smw.smw_setmode = as3722_wdt_setmode;
303 	sc->sc_smw.smw_tickle = as3722_wdt_tickle;
304 	sc->sc_smw.smw_period = AS3722_WATCHDOG_DEFAULT_PERIOD;
305 
306 	aprint_normal_dev(sc->sc_dev, "default watchdog period is %u seconds\n",
307 	    sc->sc_smw.smw_period);
308 
309 	if (sysmon_wdog_register(&sc->sc_smw) != 0)
310 		aprint_error_dev(sc->sc_dev, "couldn't register with sysmon\n");
311 }
312 
313 static void
as3722_rtc_attach(struct as3722_softc * sc)314 as3722_rtc_attach(struct as3722_softc *sc)
315 {
316 	int error;
317 
318 	iic_acquire_bus(sc->sc_i2c, 0);
319 	error = as3722_set_clear(sc, AS3722_RTC_CONTROL_REG,
320 	    AS3722_RTC_CONTROL_RTC_ON, 0, 0);
321 	iic_release_bus(sc->sc_i2c, 0);
322 
323 	if (error) {
324 		aprint_error_dev(sc->sc_dev, "couldn't setup RTC\n");
325 		return;
326 	}
327 
328 	sc->sc_todr.todr_gettime_ymdhms = as3722_rtc_gettime;
329 	sc->sc_todr.todr_settime_ymdhms = as3722_rtc_settime;
330 	sc->sc_todr.cookie = sc;
331 #ifdef FDT
332 	fdtbus_todr_attach(sc->sc_dev, sc->sc_phandle, &sc->sc_todr);
333 #else
334 	todr_attach(&sc->sc_todr);
335 #endif
336 }
337 
338 static int
as3722_read(struct as3722_softc * sc,uint8_t reg,uint8_t * val,int flags)339 as3722_read(struct as3722_softc *sc, uint8_t reg, uint8_t *val, int flags)
340 {
341 	return iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_addr,
342 	    &reg, 1, val, 1, flags);
343 }
344 
345 static int
as3722_write(struct as3722_softc * sc,uint8_t reg,uint8_t val,int flags)346 as3722_write(struct as3722_softc *sc, uint8_t reg, uint8_t val, int flags)
347 {
348 	uint8_t buf[2] = { reg, val };
349 	return iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
350 	    NULL, 0, buf, 2, flags);
351 }
352 
353 static int
as3722_set_clear(struct as3722_softc * sc,uint8_t reg,uint8_t set,uint8_t clr,int flags)354 as3722_set_clear(struct as3722_softc *sc, uint8_t reg, uint8_t set,
355     uint8_t clr, int flags)
356 {
357 	uint8_t old, new;
358 	int error;
359 
360 	error = as3722_read(sc, reg, &old, flags);
361 	if (error) {
362 		return error;
363 	}
364 	new = set | (old & ~clr);
365 
366 	return as3722_write(sc, reg, new, flags);
367 }
368 
369 static int
as3722_wdt_setmode(struct sysmon_wdog * smw)370 as3722_wdt_setmode(struct sysmon_wdog *smw)
371 {
372 	struct as3722_softc * const sc = smw->smw_cookie;
373 	int error;
374 
375 	const int flags = 0;
376 
377 	if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) {
378 		iic_acquire_bus(sc->sc_i2c, flags);
379 		error = as3722_set_clear(sc, AS3722_WATCHDOG_CTRL_REG,
380 		    0, AS3722_WATCHDOG_CTRL_ON, flags);
381 		iic_release_bus(sc->sc_i2c, flags);
382 		return error;
383 	}
384 
385 	if (smw->smw_period == WDOG_PERIOD_DEFAULT) {
386 		smw->smw_period = AS3722_WATCHDOG_DEFAULT_PERIOD;
387 	}
388 	if (smw->smw_period < 1 || smw->smw_period > 128) {
389 		return EINVAL;
390 	}
391 	sc->sc_smw.smw_period = smw->smw_period;
392 
393 	iic_acquire_bus(sc->sc_i2c, flags);
394 	error = as3722_set_clear(sc, AS3722_WATCHDOG_TIMER_REG,
395 	    __SHIFTIN(sc->sc_smw.smw_period - 1, AS3722_WATCHDOG_TIMER_TIMER),
396 	    AS3722_WATCHDOG_TIMER_TIMER, flags);
397 	if (error == 0) {
398 		error = as3722_set_clear(sc, AS3722_WATCHDOG_CTRL_REG,
399 		    AS3722_WATCHDOG_CTRL_ON, 0, flags);
400 	}
401 	iic_release_bus(sc->sc_i2c, flags);
402 
403 	return error;
404 }
405 
406 static int
as3722_wdt_tickle(struct sysmon_wdog * smw)407 as3722_wdt_tickle(struct sysmon_wdog *smw)
408 {
409 	struct as3722_softc * const sc = smw->smw_cookie;
410 	int error;
411 
412 	const int flags = 0;
413 
414 	iic_acquire_bus(sc->sc_i2c, flags);
415 	error = as3722_set_clear(sc, AS3722_WATCHDOG_SIGNAL_REG,
416 	    AS3722_WATCHDOG_SIGNAL_SW_SIG, 0, flags);
417 	iic_release_bus(sc->sc_i2c, flags);
418 
419 	return error;
420 }
421 
422 static int
as3722_rtc_gettime(todr_chip_handle_t tch,struct clock_ymdhms * dt)423 as3722_rtc_gettime(todr_chip_handle_t tch, struct clock_ymdhms *dt)
424 {
425 	struct as3722_softc * const sc = tch->cookie;
426 	uint8_t buf[6];
427 	int error = 0;
428 
429 	const int flags = 0;
430 
431 	iic_acquire_bus(sc->sc_i2c, flags);
432 	error += as3722_read(sc, AS3722_RTC_SECOND_REG, &buf[0], flags);
433 	error += as3722_read(sc, AS3722_RTC_MINUTE_REG, &buf[1], flags);
434 	error += as3722_read(sc, AS3722_RTC_HOUR_REG, &buf[2], flags);
435 	error += as3722_read(sc, AS3722_RTC_DAY_REG, &buf[3], flags);
436 	error += as3722_read(sc, AS3722_RTC_MONTH_REG, &buf[4], flags);
437 	error += as3722_read(sc, AS3722_RTC_YEAR_REG, &buf[5], flags);
438 	iic_release_bus(sc->sc_i2c, flags);
439 
440 	if (error)
441 		return error;
442 
443 	dt->dt_sec = bcdtobin(buf[0] & 0x7f);
444 	dt->dt_min = bcdtobin(buf[1] & 0x7f);
445 	dt->dt_hour = bcdtobin(buf[2] & 0x3f);
446 	dt->dt_day = bcdtobin(buf[3] & 0x3f);
447 	dt->dt_mon = bcdtobin(buf[4] & 0x1f) - 1;
448 	dt->dt_year = AS3722_START_YEAR + bcdtobin(buf[5] & 0x7f);
449 	dt->dt_wday = 0;
450 
451 	return 0;
452 }
453 
454 static int
as3722_rtc_settime(todr_chip_handle_t tch,struct clock_ymdhms * dt)455 as3722_rtc_settime(todr_chip_handle_t tch, struct clock_ymdhms *dt)
456 {
457 	struct as3722_softc * const sc = tch->cookie;
458 	uint8_t buf[6];
459 	int error = 0;
460 
461 	if (dt->dt_year < AS3722_START_YEAR)
462 		return EINVAL;
463 
464 	buf[0] = bintobcd(dt->dt_sec) & 0x7f;
465 	buf[1] = bintobcd(dt->dt_min) & 0x7f;
466 	buf[2] = bintobcd(dt->dt_hour) & 0x3f;
467 	buf[3] = bintobcd(dt->dt_day) & 0x3f;
468 	buf[4] = bintobcd(dt->dt_mon + 1) & 0x1f;
469 	buf[5] = bintobcd(dt->dt_year - AS3722_START_YEAR) & 0x7f;
470 
471 	const int flags = 0;
472 
473 	iic_acquire_bus(sc->sc_i2c, flags);
474 	error += as3722_write(sc, AS3722_RTC_SECOND_REG, buf[0], flags);
475 	error += as3722_write(sc, AS3722_RTC_MINUTE_REG, buf[1], flags);
476 	error += as3722_write(sc, AS3722_RTC_HOUR_REG, buf[2], flags);
477 	error += as3722_write(sc, AS3722_RTC_DAY_REG, buf[3], flags);
478 	error += as3722_write(sc, AS3722_RTC_MONTH_REG, buf[4], flags);
479 	error += as3722_write(sc, AS3722_RTC_YEAR_REG, buf[5], flags);
480 	iic_release_bus(sc->sc_i2c, flags);
481 
482 	return error;
483 }
484 
485 #ifdef FDT
486 static void
as3722_regulator_attach(struct as3722_softc * sc)487 as3722_regulator_attach(struct as3722_softc *sc)
488 {
489 	struct as3722reg_attach_args raa;
490 	int phandle, child;
491 	int error;
492 	const int flags = 0;
493 	uint8_t tmp;
494 
495 	iic_acquire_bus(sc->sc_i2c, flags);
496 	error = as3722_read(sc, AS3722_FUSE7_REG, &tmp, flags);
497 	iic_release_bus(sc->sc_i2c, flags);
498 	if (error != 0) {
499 		aprint_error_dev(sc->sc_dev, "failed to read Fuse7: %d\n", error);
500 		return;
501 	}
502 
503 	if (tmp & AS3722_FUSE7_SD0_V_MINUS_200MV)
504 		sc->sc_flags |= AS3722_FLAG_SD0_V_MINUS_200MV;
505 
506 	phandle = of_find_firstchild_byname(sc->sc_phandle, "regulators");
507 	if (phandle <= 0)
508 		return;
509 
510 	for (int i = 0; i < __arraycount(as3722regdefs); i++) {
511 		const struct as3722regdef *regdef = &as3722regdefs[i];
512 		child = of_find_firstchild_byname(phandle, regdef->name);
513 		if (child <= 0)
514 			continue;
515 		raa.reg_def = regdef;
516 		raa.reg_phandle = child;
517 		config_found(sc->sc_dev, &raa, NULL, CFARGS_NONE);
518 	}
519 }
520 
521 static int
as3722reg_match(device_t parent,cfdata_t match,void * aux)522 as3722reg_match(device_t parent, cfdata_t match, void *aux)
523 {
524 	return 1;
525 }
526 
527 static void
as3722reg_attach(device_t parent,device_t self,void * aux)528 as3722reg_attach(device_t parent, device_t self, void *aux)
529 {
530 	struct as3722reg_softc *sc = device_private(self);
531 	struct as3722reg_attach_args *raa = aux;
532 	char *name = NULL;
533 	int len;
534 
535 	sc->sc_dev = self;
536 	sc->sc_phandle = raa->reg_phandle;
537 	sc->sc_regdef = raa->reg_def;
538 
539 	fdtbus_register_regulator_controller(self, sc->sc_phandle,
540 	    &as3722reg_funcs);
541 
542 	len = OF_getproplen(sc->sc_phandle, "regulator-name");
543 	if (len > 0) {
544 		name = kmem_zalloc(len, KM_SLEEP);
545 		OF_getprop(sc->sc_phandle, "regulator-name", name, len);
546 	}
547 
548 	aprint_naive("\n");
549 	if (name)
550 		aprint_normal(": %s\n", name);
551 	else
552 		aprint_normal("\n");
553 
554 	if (name)
555 		kmem_free(name, len);
556 }
557 
558 static int
as3722reg_acquire(device_t dev)559 as3722reg_acquire(device_t dev)
560 {
561 	return 0;
562 }
563 
564 static void
as3722reg_release(device_t dev)565 as3722reg_release(device_t dev)
566 {
567 }
568 
569 static int
as3722reg_enable(device_t dev,bool enable)570 as3722reg_enable(device_t dev, bool enable)
571 {
572 	struct as3722reg_softc *sc = device_private(dev);
573 	struct as3722_softc *asc = device_private(device_parent(dev));
574 	const struct as3722regdef *regdef = sc->sc_regdef;
575 	const int flags = 0;
576 	int error;
577 
578 	if (!regdef->enable_mask)
579 		return enable ? 0 : EINVAL;
580 
581 	iic_acquire_bus(asc->sc_i2c, flags);
582 	if (enable)
583 		error = as3722_set_clear(asc, regdef->enable_reg,
584 		    regdef->enable_mask, 0, flags);
585 	else
586 		error = as3722_set_clear(asc, regdef->enable_reg,
587 		    0, regdef->enable_mask, flags);
588 	iic_release_bus(asc->sc_i2c, flags);
589 
590 	return error;
591 }
592 
593 static int
as3722reg_set_voltage_ldo(device_t dev,u_int min_uvol,u_int max_uvol)594 as3722reg_set_voltage_ldo(device_t dev, u_int min_uvol, u_int max_uvol)
595 {
596 	struct as3722reg_softc *sc = device_private(dev);
597 	struct as3722_softc *asc = device_private(device_parent(dev));
598 	const struct as3722regdef *regdef = sc->sc_regdef;
599 	const int flags = 0;
600 	uint8_t set_v = 0x00;
601 	u_int uvol;
602 	int error;
603 
604 	for (uint8_t v = 0x01; v <= 0x24; v++) {
605 		uvol = 800000 + (v * 25000);
606 		if (uvol >= min_uvol && uvol <= max_uvol) {
607 			set_v = v;
608 			goto done;
609 		}
610 	}
611 	for (uint8_t v = 0x40; v <= 0x7f; v++) {
612 		uvol = 1725000 + ((v - 0x40) * 25000);
613 		if (uvol >= min_uvol && uvol <= max_uvol) {
614 			set_v = v;
615 			goto done;
616 		}
617 	}
618 	if (set_v == 0)
619 		return ERANGE;
620 
621 done:
622 	iic_acquire_bus(asc->sc_i2c, flags);
623 	error = as3722_set_clear(asc, regdef->vsel_reg, set_v,
624 	    regdef->vsel_mask, flags);
625 	iic_release_bus(asc->sc_i2c, flags);
626 
627 	return error;
628 }
629 
630 static int
as3722reg_get_voltage_ldo(device_t dev,u_int * puvol)631 as3722reg_get_voltage_ldo(device_t dev, u_int *puvol)
632 {
633 	struct as3722reg_softc *sc = device_private(dev);
634 	struct as3722_softc *asc = device_private(device_parent(dev));
635 	const struct as3722regdef *regdef = sc->sc_regdef;
636 	const int flags = 0;
637 	uint8_t v;
638 	int error;
639 
640 	iic_acquire_bus(asc->sc_i2c, flags);
641 	error = as3722_read(asc, regdef->vsel_reg, &v, flags);
642 	iic_release_bus(asc->sc_i2c, flags);
643 	if (error != 0)
644 		return error;
645 
646 	v &= regdef->vsel_mask;
647 
648 	if (v == 0)
649 		*puvol = 0;	/* LDO off */
650 	else if (v >= 0x01 && v <= 0x24)
651 		*puvol = 800000 + (v * 25000);
652 	else if (v >= 0x40 && v <= 0x7f)
653 		*puvol = 1725000 + ((v - 0x40) * 25000);
654 	else
655 		return EINVAL;
656 
657 	return 0;
658 }
659 
660 static int
as3722reg_set_voltage_sd0(device_t dev,u_int min_uvol,u_int max_uvol)661 as3722reg_set_voltage_sd0(device_t dev, u_int min_uvol, u_int max_uvol)
662 {
663 	struct as3722reg_softc *sc = device_private(dev);
664 	struct as3722_softc *asc = device_private(device_parent(dev));
665 	const struct as3722regdef *regdef = sc->sc_regdef;
666 	const int flags = 0;
667 	uint8_t set_v = 0x00;
668 	u_int uvol;
669 	int error;
670 
671 	if (asc->sc_flags & AS3722_FLAG_SD0_V_MINUS_200MV) {
672 		for (uint8_t v = 0x01; v <= 0x6e; v++) {
673 			uvol = 400000 + (v * 10000);
674 			if (uvol >= min_uvol && uvol <= max_uvol) {
675 				set_v = v;
676 				goto done;
677 			}
678 		}
679 	} else {
680 		for (uint8_t v = 0x01; v <= 0x5a; v++) {
681 			uvol = 600000 + (v * 10000);
682 			if (uvol >= min_uvol && uvol <= max_uvol) {
683 				set_v = v;
684 				goto done;
685 			}
686 		}
687 	}
688 	if (set_v == 0)
689 		return ERANGE;
690 
691 done:
692 	iic_acquire_bus(asc->sc_i2c, flags);
693 	error = as3722_set_clear(asc, regdef->vsel_reg, set_v,
694 	    regdef->vsel_mask, flags);
695 	iic_release_bus(asc->sc_i2c, flags);
696 
697 	return error;
698 }
699 
700 static int
as3722reg_get_voltage_sd0(device_t dev,u_int * puvol)701 as3722reg_get_voltage_sd0(device_t dev, u_int *puvol)
702 {
703 	struct as3722reg_softc *sc = device_private(dev);
704 	struct as3722_softc *asc = device_private(device_parent(dev));
705 	const struct as3722regdef *regdef = sc->sc_regdef;
706 	const int flags = 0;
707 	uint8_t v;
708 	int error;
709 
710 	iic_acquire_bus(asc->sc_i2c, flags);
711 	error = as3722_read(asc, regdef->vsel_reg, &v, flags);
712 	iic_release_bus(asc->sc_i2c, flags);
713 	if (error != 0)
714 		return error;
715 
716 	v &= regdef->vsel_mask;
717 
718 	if (v == 0) {
719 		*puvol = 0;	/* DC/DC powered down */
720 		return 0;
721 	}
722 	if (asc->sc_flags & AS3722_FLAG_SD0_V_MINUS_200MV) {
723 		if (v >= 0x01 && v <= 0x6e) {
724 			*puvol = 400000 + (v * 10000);
725 			return 0;
726 		}
727 	} else {
728 		if (v >= 0x01 && v <= 0x5a) {
729 			*puvol = 600000 + (v * 10000);
730 			return 0;
731 		}
732 	}
733 
734 	return EINVAL;
735 }
736 
737 static int
as3722reg_set_voltage_sd4(device_t dev,u_int min_uvol,u_int max_uvol)738 as3722reg_set_voltage_sd4(device_t dev, u_int min_uvol, u_int max_uvol)
739 {
740 	struct as3722reg_softc *sc = device_private(dev);
741 	struct as3722_softc *asc = device_private(device_parent(dev));
742 	const struct as3722regdef *regdef = sc->sc_regdef;
743 	const int flags = 0;
744 	uint8_t set_v = 0x00;
745 	u_int uvol;
746 	int error;
747 
748 
749 	for (uint8_t v = 0x01; v <= 0x40; v++) {
750 		uvol = 600000 + (v * 12500);
751 		if (uvol >= min_uvol && uvol <= max_uvol) {
752 			set_v = v;
753 			goto done;
754 		}
755 	}
756 	for (uint8_t v = 0x41; v <= 0x70; v++) {
757 		uvol = 1400000 + ((v - 0x40) * 25000);
758 		if (uvol >= min_uvol && uvol <= max_uvol) {
759 			set_v = v;
760 			goto done;
761 		}
762 	}
763 	for (uint8_t v = 0x71; v <= 0x7f; v++) {
764 		uvol = 2600000 + ((v - 0x70) * 50000);
765 		if (uvol >= min_uvol && uvol <= max_uvol) {
766 			set_v = v;
767 			goto done;
768 		}
769 	}
770 	if (set_v == 0)
771 		return ERANGE;
772 
773 done:
774 	iic_acquire_bus(asc->sc_i2c, flags);
775 	error = as3722_set_clear(asc, regdef->vsel_reg, set_v,
776 	    regdef->vsel_mask, flags);
777 	iic_release_bus(asc->sc_i2c, flags);
778 
779 	return error;
780 }
781 
782 static int
as3722reg_get_voltage_sd4(device_t dev,u_int * puvol)783 as3722reg_get_voltage_sd4(device_t dev, u_int *puvol)
784 {
785 	struct as3722reg_softc *sc = device_private(dev);
786 	struct as3722_softc *asc = device_private(device_parent(dev));
787 	const struct as3722regdef *regdef = sc->sc_regdef;
788 	const int flags = 0;
789 	uint8_t v;
790 	int error;
791 
792 	iic_acquire_bus(asc->sc_i2c, flags);
793 	error = as3722_read(asc, regdef->vsel_reg, &v, flags);
794 	iic_release_bus(asc->sc_i2c, flags);
795 	if (error != 0)
796 		return error;
797 
798 	v &= regdef->vsel_mask;
799 
800 	if (v == 0)
801 		*puvol = 0;	/* DC/DC powered down */
802 	else if (v >= 0x01 && v <= 0x40)
803 		*puvol = 600000 + (v * 12500);
804 	else if (v >= 0x41 && v <= 0x70)
805 		*puvol = 1400000 + (v - 0x40) * 25000;
806 	else if (v >= 0x71 && v <= 0x7f)
807 		*puvol = 2600000 + (v - 0x70) * 50000;
808 	else
809 		return EINVAL;
810 
811 	return 0;
812 }
813 
814 static int
as3722reg_set_voltage(device_t dev,u_int min_uvol,u_int max_uvol)815 as3722reg_set_voltage(device_t dev, u_int min_uvol, u_int max_uvol)
816 {
817 	struct as3722reg_softc *sc = device_private(dev);
818 	const struct as3722regdef *regdef = sc->sc_regdef;
819 
820 	return regdef->set(dev, min_uvol, max_uvol);
821 }
822 
823 static int
as3722reg_get_voltage(device_t dev,u_int * puvol)824 as3722reg_get_voltage(device_t dev, u_int *puvol)
825 {
826 	struct as3722reg_softc *sc = device_private(dev);
827 	const struct as3722regdef *regdef = sc->sc_regdef;
828 
829 	return regdef->get(dev, puvol);
830 }
831 
832 static void
as3722_power_reset(device_t dev)833 as3722_power_reset(device_t dev)
834 {
835 	delay(1000000);
836 	as3722_reboot(dev);
837 }
838 
839 static void
as3722_power_poweroff(device_t dev)840 as3722_power_poweroff(device_t dev)
841 {
842 	delay(1000000);
843 	as3722_poweroff(dev);
844 }
845 #endif
846 
847 int
as3722_poweroff(device_t dev)848 as3722_poweroff(device_t dev)
849 {
850 	struct as3722_softc * const sc = device_private(dev);
851 	int error;
852 
853 	error = iic_acquire_bus(sc->sc_i2c, 0);
854 	if (error == 0) {
855 		error = as3722_write(sc, AS3722_RESET_CTRL_REG,
856 		    AS3722_RESET_CTRL_POWER_OFF, 0);
857 		iic_release_bus(sc->sc_i2c, 0);
858 	}
859 	if (error) {
860 		device_printf(dev, "WARNING: unable to power off, error %d\n",
861 		    error);
862 	}
863 
864 	return error;
865 }
866 
867 int
as3722_reboot(device_t dev)868 as3722_reboot(device_t dev)
869 {
870 	struct as3722_softc * const sc = device_private(dev);
871 	int error;
872 
873 	error = iic_acquire_bus(sc->sc_i2c, 0);
874 	if (error == 0) {
875 		error = as3722_write(sc, AS3722_RESET_CTRL_REG,
876 		    AS3722_RESET_CTRL_FORCE_RESET, 0);
877 		iic_release_bus(sc->sc_i2c, 0);
878 	}
879 	if (error) {
880 		device_printf(dev, "WARNING: unable to reboot, error %d\n",
881 		    error);
882 	}
883 
884 	return error;
885 }
886