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