w83795g.c revision 1.1.2.3 1 1.1.2.3 bouyer /* $NetBSD: w83795g.c,v 1.1.2.3 2013/10/20 13:36:43 bouyer Exp $ */
2 1.1.2.2 riz
3 1.1.2.2 riz /*
4 1.1.2.2 riz * Copyright (c) 2013 Soren S. Jorvang. All rights reserved.
5 1.1.2.2 riz *
6 1.1.2.2 riz * Redistribution and use in source and binary forms, with or without
7 1.1.2.2 riz * modification, are permitted provided that the following conditions
8 1.1.2.2 riz * are met:
9 1.1.2.2 riz * 1. Redistributions of source code must retain the above copyright
10 1.1.2.2 riz * notice, this list of conditions, and the following disclaimer.
11 1.1.2.2 riz * 2. Redistributions in binary form must reproduce the above copyright
12 1.1.2.2 riz * notice, this list of conditions and the following disclaimer in the
13 1.1.2.2 riz * documentation and/or other materials provided with the distribution.
14 1.1.2.2 riz *
15 1.1.2.2 riz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 1.1.2.2 riz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 1.1.2.2 riz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 1.1.2.2 riz * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 1.1.2.2 riz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 1.1.2.2 riz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 1.1.2.2 riz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 1.1.2.2 riz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 1.1.2.2 riz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 1.1.2.2 riz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 1.1.2.2 riz * SUCH DAMAGE.
26 1.1.2.2 riz */
27 1.1.2.2 riz
28 1.1.2.2 riz #include <sys/cdefs.h>
29 1.1.2.3 bouyer __KERNEL_RCSID(0, "$NetBSD: w83795g.c,v 1.1.2.3 2013/10/20 13:36:43 bouyer Exp $");
30 1.1.2.2 riz
31 1.1.2.2 riz #include <sys/param.h>
32 1.1.2.2 riz #include <sys/systm.h>
33 1.1.2.2 riz #include <sys/device.h>
34 1.1.2.2 riz #include <sys/conf.h>
35 1.1.2.2 riz #include <sys/gpio.h>
36 1.1.2.2 riz #include <sys/wdog.h>
37 1.1.2.2 riz
38 1.1.2.2 riz #include <dev/i2c/i2cvar.h>
39 1.1.2.2 riz #include <dev/gpio/gpiovar.h>
40 1.1.2.2 riz #include <dev/sysmon/sysmonvar.h>
41 1.1.2.2 riz
42 1.1.2.2 riz #include <dev/i2c/w83795greg.h>
43 1.1.2.2 riz
44 1.1.2.2 riz #define NUM_SENSORS 53
45 1.1.2.2 riz static const struct w83795g_sensor {
46 1.1.2.2 riz const char *desc;
47 1.1.2.2 riz enum envsys_units type;
48 1.1.2.2 riz uint8_t en_reg;
49 1.1.2.2 riz uint8_t en_mask;
50 1.1.2.2 riz uint8_t en_bits;
51 1.1.2.2 riz uint8_t msb;
52 1.1.2.2 riz } sensors[NUM_SENSORS] = {
53 1.1.2.2 riz #define _VOLT ENVSYS_SVOLTS_DC
54 1.1.2.2 riz { "VSEN1", _VOLT, W83795G_V_CTRL1, 0x01, 0x01, W83795G_VSEN1 },
55 1.1.2.2 riz { "VSEN2", _VOLT, W83795G_V_CTRL1, 0x02, 0x02, W83795G_VSEN2 },
56 1.1.2.2 riz { "VSEN3", _VOLT, W83795G_V_CTRL1, 0x04, 0x04, W83795G_VSEN3 },
57 1.1.2.2 riz { "VSEN4", _VOLT, W83795G_V_CTRL1, 0x08, 0x08, W83795G_VSEN4 },
58 1.1.2.2 riz { "VSEN5", _VOLT, W83795G_V_CTRL1, 0x10, 0x10, W83795G_VSEN5 },
59 1.1.2.2 riz { "VSEN6", _VOLT, W83795G_V_CTRL1, 0x20, 0x20, W83795G_VSEN6 },
60 1.1.2.2 riz { "VSEN7", _VOLT, W83795G_V_CTRL1, 0x40, 0x40, W83795G_VSEN7 },
61 1.1.2.2 riz { "VSEN8", _VOLT, W83795G_V_CTRL1, 0x80, 0x80, W83795G_VSEN8 },
62 1.1.2.2 riz { "VSEN9", _VOLT, W83795G_V_CTRL2, 0x01, 0x01, W83795G_VSEN9 },
63 1.1.2.2 riz { "VSEN10", _VOLT, W83795G_V_CTRL2, 0x02, 0x02, W83795G_VSEN10 },
64 1.1.2.2 riz { "VSEN11", _VOLT, W83795G_V_CTRL2, 0x04, 0x04, W83795G_VSEN11 },
65 1.1.2.2 riz { "VTT", _VOLT, W83795G_V_CTRL2, 0x08, 0x08, W83795G_VTT },
66 1.1.2.2 riz { "3VDD", _VOLT, W83795G_V_CTRL2, 0x10, 0x10, W83795G_3VDD },
67 1.1.2.2 riz { "3VSB", _VOLT, W83795G_V_CTRL2, 0x20, 0x20, W83795G_3VSB },
68 1.1.2.2 riz { "VBAT", _VOLT, W83795G_V_CTRL2, 0x40, 0x40, W83795G_VBAT },
69 1.1.2.2 riz { "VSEN12", _VOLT, W83795G_T_CTRL1, 0x03, 0x02, W83795G_VSEN12 },
70 1.1.2.2 riz { "VSEN13", _VOLT, W83795G_T_CTRL1, 0x0c, 0x08, W83795G_VSEN13 },
71 1.1.2.2 riz { "VDSEN14", _VOLT, W83795G_T_CTRL2, 0x03, 0x02, W83795G_VDSEN14 },
72 1.1.2.2 riz { "VDSEN15", _VOLT, W83795G_T_CTRL2, 0x0c, 0x08, W83795G_VDSEN15 },
73 1.1.2.2 riz { "VDSEN16", _VOLT, W83795G_T_CTRL2, 0x30, 0x20, W83795G_VDSEN16 },
74 1.1.2.2 riz { "VDSEN17", _VOLT, W83795G_T_CTRL2, 0xc0, 0x80, W83795G_VDSEN17 },
75 1.1.2.2 riz #define _TEMP ENVSYS_STEMP
76 1.1.2.2 riz { "TR5", _TEMP, W83795G_T_CTRL1, 0x03, 0x03, W83795G_TR5 },
77 1.1.2.2 riz { "TR6", _TEMP, W83795G_T_CTRL1, 0x0c, 0x0c, W83795G_TR6 },
78 1.1.2.2 riz { "TD1", _TEMP, W83795G_T_CTRL2, 0x03, 0x01, W83795G_TD1 },
79 1.1.2.2 riz { "TD2", _TEMP, W83795G_T_CTRL2, 0x0c, 0x04, W83795G_TD2 },
80 1.1.2.2 riz { "TD3", _TEMP, W83795G_T_CTRL2, 0x30, 0x10, W83795G_TD3 },
81 1.1.2.2 riz { "TD4", _TEMP, W83795G_T_CTRL2, 0xc0, 0x40, W83795G_TD4 },
82 1.1.2.2 riz { "TR1", _TEMP, W83795G_T_CTRL2, 0x03, 0x03, W83795G_TR1 },
83 1.1.2.2 riz { "TR2", _TEMP, W83795G_T_CTRL2, 0x0c, 0x0c, W83795G_TR2 },
84 1.1.2.2 riz { "TR3", _TEMP, W83795G_T_CTRL2, 0x30, 0x30, W83795G_TR3 },
85 1.1.2.2 riz { "TR4", _TEMP, W83795G_T_CTRL2, 0xc0, 0xc0, W83795G_TR4 },
86 1.1.2.2 riz { "DTS1", _TEMP, W83795G_T_CTRL1, 0x20, 0x20, W83795G_DTS1 },
87 1.1.2.2 riz { "DTS2", _TEMP, W83795G_T_CTRL1, 0x20, 0x20, W83795G_DTS2 },
88 1.1.2.2 riz { "DTS3", _TEMP, W83795G_T_CTRL1, 0x20, 0x20, W83795G_DTS3 },
89 1.1.2.2 riz { "DTS4", _TEMP, W83795G_T_CTRL1, 0x20, 0x20, W83795G_DTS4 },
90 1.1.2.2 riz { "DTS5", _TEMP, W83795G_T_CTRL1, 0x20, 0x20, W83795G_DTS5 },
91 1.1.2.2 riz { "DTS6", _TEMP, W83795G_T_CTRL1, 0x20, 0x20, W83795G_DTS6 },
92 1.1.2.2 riz { "DTS7", _TEMP, W83795G_T_CTRL1, 0x20, 0x20, W83795G_DTS7 },
93 1.1.2.2 riz { "DTS8", _TEMP, W83795G_T_CTRL1, 0x20, 0x20, W83795G_DTS8 },
94 1.1.2.2 riz #define _FAN ENVSYS_SFANRPM
95 1.1.2.2 riz { "FANIN1", _FAN, W83795G_F_CTRL1, 0x01, 0x01, W83795G_FANIN1 },
96 1.1.2.2 riz { "FANIN2", _FAN, W83795G_F_CTRL1, 0x02, 0x02, W83795G_FANIN2 },
97 1.1.2.2 riz { "FANIN3", _FAN, W83795G_F_CTRL1, 0x04, 0x04, W83795G_FANIN3 },
98 1.1.2.2 riz { "FANIN4", _FAN, W83795G_F_CTRL1, 0x08, 0x08, W83795G_FANIN4 },
99 1.1.2.2 riz { "FANIN5", _FAN, W83795G_F_CTRL1, 0x10, 0x10, W83795G_FANIN5 },
100 1.1.2.2 riz { "FANIN6", _FAN, W83795G_F_CTRL1, 0x20, 0x20, W83795G_FANIN6 },
101 1.1.2.2 riz { "FANIN7", _FAN, W83795G_F_CTRL1, 0x40, 0x40, W83795G_FANIN7 },
102 1.1.2.2 riz { "FANIN8", _FAN, W83795G_F_CTRL1, 0x80, 0x80, W83795G_FANIN8 },
103 1.1.2.2 riz { "FANIN9", _FAN, W83795G_F_CTRL2, 0x01, 0x01, W83795G_FANIN9 },
104 1.1.2.2 riz { "FANIN10", _FAN, W83795G_F_CTRL2, 0x02, 0x02, W83795G_FANIN10 },
105 1.1.2.2 riz { "FANIN11", _FAN, W83795G_F_CTRL2, 0x04, 0x04, W83795G_FANIN11 },
106 1.1.2.2 riz { "FANIN12", _FAN, W83795G_F_CTRL2, 0x08, 0x08, W83795G_FANIN12 },
107 1.1.2.2 riz { "FANIN13", _FAN, W83795G_F_CTRL2, 0x10, 0x10, W83795G_FANIN13 },
108 1.1.2.2 riz { "FANIN14", _FAN, W83795G_F_CTRL2, 0x20, 0x20, W83795G_FANIN14 },
109 1.1.2.2 riz };
110 1.1.2.2 riz
111 1.1.2.2 riz struct w83795g_softc {
112 1.1.2.2 riz device_t sc_dev;
113 1.1.2.2 riz i2c_tag_t sc_tag;
114 1.1.2.2 riz i2c_addr_t sc_addr;
115 1.1.2.2 riz struct gpio_chipset_tag sc_gpio_gc;
116 1.1.2.2 riz gpio_pin_t sc_gpio_pins[8];
117 1.1.2.2 riz struct sysmon_envsys *sc_sme;
118 1.1.2.2 riz envsys_data_t sc_sensors[NUM_SENSORS];
119 1.1.2.2 riz struct sysmon_wdog sc_smw;
120 1.1.2.2 riz };
121 1.1.2.2 riz
122 1.1.2.2 riz static int w83795g_match(device_t, cfdata_t, void *);
123 1.1.2.2 riz static void w83795g_attach(device_t, device_t, void *);
124 1.1.2.2 riz
125 1.1.2.2 riz CFATTACH_DECL_NEW(w83795g, sizeof(struct w83795g_softc),
126 1.1.2.2 riz w83795g_match, w83795g_attach, NULL, NULL);
127 1.1.2.2 riz
128 1.1.2.2 riz static void w83795g_refresh(struct sysmon_envsys *, envsys_data_t *);
129 1.1.2.2 riz static void w83795g_get_limits(struct sysmon_envsys *, envsys_data_t *,
130 1.1.2.2 riz sysmon_envsys_lim_t *limits, uint32_t *props);
131 1.1.2.2 riz
132 1.1.2.2 riz static int w83795g_gpio_read(void *, int);
133 1.1.2.2 riz static void w83795g_gpio_write(void *, int, int);
134 1.1.2.2 riz static void w83795g_gpio_ctl(void *, int, int);
135 1.1.2.2 riz
136 1.1.2.2 riz static int w83795g_wdog_setmode(struct sysmon_wdog *);
137 1.1.2.2 riz static int w83795g_wdog_tickle(struct sysmon_wdog *);
138 1.1.2.2 riz
139 1.1.2.2 riz static int
140 1.1.2.2 riz w83795g_match(device_t parent, cfdata_t match, void *aux)
141 1.1.2.2 riz {
142 1.1.2.2 riz struct i2c_attach_args *ia = aux;
143 1.1.2.2 riz uint8_t bank, vend, chip, deva;
144 1.1.2.2 riz
145 1.1.2.2 riz if (ia->ia_addr < I2CADDR_MINADDR || ia->ia_addr > I2CADDR_MAXADDR)
146 1.1.2.2 riz return 0;
147 1.1.2.2 riz
148 1.1.2.2 riz iic_acquire_bus(ia->ia_tag, 0);
149 1.1.2.2 riz iic_smbus_read_byte(ia->ia_tag, ia->ia_addr, W83795G_BANKSEL, &bank, 0);
150 1.1.2.2 riz iic_smbus_read_byte(ia->ia_tag, ia->ia_addr, W83795G_VENDOR, &vend, 0);
151 1.1.2.2 riz iic_smbus_read_byte(ia->ia_tag, ia->ia_addr, W83795G_CHIP, &chip, 0);
152 1.1.2.2 riz iic_smbus_read_byte(ia->ia_tag, ia->ia_addr, W83795G_DEVICEA, &deva, 0);
153 1.1.2.2 riz iic_release_bus(ia->ia_tag, 0);
154 1.1.2.2 riz
155 1.1.2.2 riz if ((bank & BANKSEL_HBACS && vend == VENDOR_NUVOTON_ID_HI) ||
156 1.1.2.2 riz (~bank & BANKSEL_HBACS && vend == VENDOR_NUVOTON_ID_LO))
157 1.1.2.2 riz if (chip == CHIP_W83795G && deva == DEVICEA_A)
158 1.1.2.2 riz return 1;
159 1.1.2.2 riz
160 1.1.2.2 riz return 0;
161 1.1.2.2 riz }
162 1.1.2.2 riz
163 1.1.2.2 riz static void
164 1.1.2.2 riz w83795g_attach(device_t parent, device_t self, void *aux)
165 1.1.2.2 riz {
166 1.1.2.2 riz struct w83795g_softc *sc = device_private(self);
167 1.1.2.2 riz struct i2c_attach_args *ia = aux;
168 1.1.2.2 riz struct gpiobus_attach_args gba;
169 1.1.2.2 riz uint8_t conf, rev, reg, gpiom, en_reg;
170 1.1.2.2 riz int i;
171 1.1.2.2 riz
172 1.1.2.2 riz sc->sc_dev = self;
173 1.1.2.2 riz sc->sc_tag = ia->ia_tag;
174 1.1.2.2 riz sc->sc_addr = ia->ia_addr;
175 1.1.2.2 riz sc->sc_gpio_gc.gp_cookie = sc;
176 1.1.2.2 riz sc->sc_gpio_gc.gp_pin_read = w83795g_gpio_read;
177 1.1.2.2 riz sc->sc_gpio_gc.gp_pin_write = w83795g_gpio_write;
178 1.1.2.2 riz sc->sc_gpio_gc.gp_pin_ctl = w83795g_gpio_ctl;
179 1.1.2.2 riz sc->sc_sme = sysmon_envsys_create();
180 1.1.2.2 riz sc->sc_sme->sme_name = device_xname(self);
181 1.1.2.2 riz sc->sc_sme->sme_cookie = sc;
182 1.1.2.2 riz sc->sc_sme->sme_refresh = w83795g_refresh;
183 1.1.2.2 riz sc->sc_sme->sme_get_limits = w83795g_get_limits;
184 1.1.2.2 riz sc->sc_smw.smw_name = device_xname(self);
185 1.1.2.2 riz sc->sc_smw.smw_cookie = sc;
186 1.1.2.2 riz sc->sc_smw.smw_setmode = w83795g_wdog_setmode;
187 1.1.2.2 riz sc->sc_smw.smw_tickle = w83795g_wdog_tickle;
188 1.1.2.2 riz sc->sc_smw.smw_period = 60;
189 1.1.2.2 riz
190 1.1.2.2 riz iic_acquire_bus(sc->sc_tag, 0);
191 1.1.2.2 riz iic_smbus_write_byte(sc->sc_tag, sc->sc_addr, W83795G_BANKSEL, 0, 0);
192 1.1.2.2 riz iic_smbus_read_byte(sc->sc_tag, sc->sc_addr, W83795G_CONFIG, &conf, 0);
193 1.1.2.2 riz iic_smbus_read_byte(sc->sc_tag, sc->sc_addr, W83795G_DEVICE, &rev, 0);
194 1.1.2.2 riz
195 1.1.2.2 riz aprint_normal(": Nuvaton W83795");
196 1.1.2.2 riz if (conf & CONFIG_CONFIG48)
197 1.1.2.2 riz aprint_normal("ADG");
198 1.1.2.2 riz else
199 1.1.2.2 riz aprint_normal("G");
200 1.1.2.2 riz aprint_verbose(" (rev %c)", rev - DEVICEA_A + 'A');
201 1.1.2.2 riz aprint_normal(" Hardware Monitor\n");
202 1.1.2.2 riz aprint_naive(": Hardware Monitor\n");
203 1.1.2.2 riz
204 1.1.2.2 riz /* Debug dump of all register banks */
205 1.1.2.2 riz for (i = 0; i < 1024; i++) {
206 1.1.2.2 riz if (i % 256 == 0) {
207 1.1.2.2 riz iic_smbus_write_byte(sc->sc_tag, sc->sc_addr,
208 1.1.2.2 riz W83795G_BANKSEL, i / 256, 0);
209 1.1.2.2 riz aprint_debug_dev(self, "register bank %d:\n", i / 256);
210 1.1.2.2 riz }
211 1.1.2.2 riz if (i % 32 == 0)
212 1.1.2.2 riz aprint_debug_dev(self, "%02x ", i % 256);
213 1.1.2.2 riz iic_smbus_read_byte(sc->sc_tag, sc->sc_addr, i % 256, ®, 0);
214 1.1.2.2 riz aprint_debug("%02x", reg);
215 1.1.2.2 riz if (i % 32 == 31)
216 1.1.2.2 riz aprint_debug("\n");
217 1.1.2.2 riz else if (i % 8 == 7)
218 1.1.2.2 riz aprint_debug(" ");
219 1.1.2.2 riz }
220 1.1.2.2 riz
221 1.1.2.2 riz iic_smbus_write_byte(sc->sc_tag, sc->sc_addr, W83795G_BANKSEL, 0, 0);
222 1.1.2.2 riz
223 1.1.2.2 riz for (i = 0; i < NUM_SENSORS; i++) {
224 1.1.2.2 riz iic_smbus_read_byte(sc->sc_tag, sc->sc_addr,
225 1.1.2.2 riz sensors[i].en_reg, &en_reg, 0);
226 1.1.2.2 riz
227 1.1.2.2 riz if ((en_reg & sensors[i].en_mask) != sensors[i].en_bits)
228 1.1.2.2 riz continue;
229 1.1.2.2 riz
230 1.1.2.2 riz strcpy(sc->sc_sensors[i].desc, sensors[i].desc);
231 1.1.2.2 riz sc->sc_sensors[i].units = sensors[i].type;
232 1.1.2.2 riz sc->sc_sensors[i].state = ENVSYS_SINVALID;
233 1.1.2.2 riz sc->sc_sensors[i].flags = ENVSYS_FMONLIMITS;
234 1.1.2.2 riz sc->sc_sensors[i].private = i;
235 1.1.2.2 riz sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensors[i]);
236 1.1.2.2 riz }
237 1.1.2.2 riz
238 1.1.2.2 riz iic_smbus_read_byte(sc->sc_tag, sc->sc_addr, W83795G_GPIO_M, &gpiom, 0);
239 1.1.2.2 riz iic_release_bus(sc->sc_tag, 0);
240 1.1.2.2 riz
241 1.1.2.2 riz if (conf & CONFIG_CONFIG48)
242 1.1.2.2 riz gba.gba_npins = 4;
243 1.1.2.2 riz else
244 1.1.2.2 riz gba.gba_npins = 8;
245 1.1.2.2 riz gba.gba_gc = &sc->sc_gpio_gc;
246 1.1.2.2 riz gba.gba_pins = sc->sc_gpio_pins;
247 1.1.2.2 riz
248 1.1.2.2 riz for (i = 0; i < gba.gba_npins; i++) {
249 1.1.2.2 riz sc->sc_gpio_pins[i].pin_num = i;
250 1.1.2.2 riz sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_OUTPUT | GPIO_PIN_INPUT;
251 1.1.2.2 riz sc->sc_gpio_pins[i].pin_flags = (gpiom & (1 << i)) ?
252 1.1.2.2 riz GPIO_PIN_OUTPUT : GPIO_PIN_INPUT;
253 1.1.2.2 riz sc->sc_gpio_pins[i].pin_state = w83795g_gpio_read(sc, i);
254 1.1.2.2 riz }
255 1.1.2.2 riz
256 1.1.2.2 riz if (sysmon_envsys_register(sc->sc_sme))
257 1.1.2.2 riz aprint_error_dev(self, "unable to register with sysmon\n");
258 1.1.2.2 riz
259 1.1.2.2 riz if (sysmon_wdog_register(&sc->sc_smw) != 0)
260 1.1.2.2 riz aprint_error_dev(self, "couldn't register watchdog\n");
261 1.1.2.2 riz
262 1.1.2.2 riz if (!pmf_device_register(self, NULL, NULL))
263 1.1.2.2 riz aprint_error_dev(self, "couldn't establish power handler\n");
264 1.1.2.2 riz
265 1.1.2.2 riz config_found(self, &gba, gpiobus_print);
266 1.1.2.2 riz }
267 1.1.2.2 riz
268 1.1.2.2 riz static void
269 1.1.2.2 riz w83795g_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
270 1.1.2.2 riz {
271 1.1.2.2 riz struct w83795g_softc *sc = sme->sme_cookie;
272 1.1.2.2 riz const struct w83795g_sensor *sensor = &sensors[edata->private];
273 1.1.2.2 riz uint8_t msb, lsb;
274 1.1.2.2 riz
275 1.1.2.2 riz sensor = &sensors[edata->private];
276 1.1.2.2 riz
277 1.1.2.2 riz iic_acquire_bus(sc->sc_tag, 0);
278 1.1.2.2 riz iic_smbus_write_byte(sc->sc_tag, sc->sc_addr, W83795G_BANKSEL, 0, 0);
279 1.1.2.2 riz iic_smbus_read_byte(sc->sc_tag, sc->sc_addr, sensor->msb, &msb, 0);
280 1.1.2.2 riz iic_smbus_read_byte(sc->sc_tag, sc->sc_addr, W83795G_VR_LSB, &lsb, 0);
281 1.1.2.2 riz iic_release_bus(sc->sc_tag, 0);
282 1.1.2.2 riz
283 1.1.2.2 riz switch (edata->units) {
284 1.1.2.2 riz case ENVSYS_SVOLTS_DC:
285 1.1.2.2 riz if (sensor->msb == W83795G_3VDD ||
286 1.1.2.2 riz sensor->msb == W83795G_3VSB ||
287 1.1.2.2 riz sensor->msb == W83795G_VBAT)
288 1.1.2.2 riz edata->value_cur = (msb << 2 | lsb >> 6) * 6000;
289 1.1.2.2 riz else
290 1.1.2.2 riz edata->value_cur = (msb << 2 | lsb >> 6) * 2000;
291 1.1.2.2 riz break;
292 1.1.2.2 riz case ENVSYS_STEMP:
293 1.1.2.2 riz edata->value_cur = ((int8_t)msb << 2 | lsb >> 6) * 250000 +
294 1.1.2.2 riz 273150000;
295 1.1.2.2 riz break;
296 1.1.2.2 riz case ENVSYS_SFANRPM:
297 1.1.2.2 riz edata->value_cur = 1350000 / (msb << 4 | lsb >> 4);
298 1.1.2.2 riz break;
299 1.1.2.2 riz }
300 1.1.2.2 riz
301 1.1.2.2 riz edata->state = ENVSYS_SVALID;
302 1.1.2.2 riz }
303 1.1.2.2 riz
304 1.1.2.2 riz static void
305 1.1.2.2 riz w83795g_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
306 1.1.2.2 riz sysmon_envsys_lim_t *limits, uint32_t *props)
307 1.1.2.2 riz {
308 1.1.2.2 riz struct w83795g_softc *sc = sme->sme_cookie;
309 1.1.2.2 riz const struct w83795g_sensor *sensor = &sensors[edata->private];
310 1.1.2.2 riz uint8_t index, msb, lsb;
311 1.1.2.2 riz
312 1.1.2.2 riz iic_acquire_bus(sc->sc_tag, 0);
313 1.1.2.2 riz iic_smbus_write_byte(sc->sc_tag, sc->sc_addr, W83795G_BANKSEL, 0, 0);
314 1.1.2.2 riz
315 1.1.2.2 riz switch (edata->units) {
316 1.1.2.2 riz case ENVSYS_SVOLTS_DC:
317 1.1.2.2 riz break;
318 1.1.2.2 riz case ENVSYS_STEMP:
319 1.1.2.2 riz if (sensor->msb == W83795G_TR5)
320 1.1.2.2 riz index = W83795G_TR5CRIT;
321 1.1.2.2 riz else if (sensor->msb == W83795G_TR6)
322 1.1.2.2 riz index = W83795G_TR6CRIT;
323 1.1.2.2 riz else if (sensor->msb >= W83795G_DTS1)
324 1.1.2.2 riz index = W83795G_DTSCRIT;
325 1.1.2.2 riz else
326 1.1.2.2 riz index = W83795G_TD1CRIT +
327 1.1.2.2 riz (sensor->msb - W83795G_TD1) * 4;
328 1.1.2.2 riz iic_smbus_read_byte(sc->sc_tag, sc->sc_addr, index, &msb, 0);
329 1.1.2.2 riz limits->sel_critmax = (int8_t)msb * 1000000 + 273150000;
330 1.1.2.2 riz index += 2;
331 1.1.2.2 riz iic_smbus_read_byte(sc->sc_tag, sc->sc_addr, index++, &msb, 0);
332 1.1.2.2 riz limits->sel_warnmax = (int8_t)msb * 1000000 + 273150000;
333 1.1.2.2 riz *props |= PROP_CRITMAX | PROP_WARNMAX;
334 1.1.2.2 riz break;
335 1.1.2.2 riz case ENVSYS_SFANRPM:
336 1.1.2.2 riz index = W83795G_FAN1HL + (sensor->msb - W83795G_FANIN1) * 2;
337 1.1.2.2 riz iic_smbus_read_byte(sc->sc_tag, sc->sc_addr, index, &msb, 0);
338 1.1.2.2 riz index = W83795G_FHL1LSB + (sensor->msb - W83795G_FANIN1) / 2;
339 1.1.2.2 riz iic_smbus_read_byte(sc->sc_tag, sc->sc_addr, index, &lsb, 0);
340 1.1.2.2 riz if (index % 2)
341 1.1.2.2 riz lsb >> 4;
342 1.1.2.2 riz else
343 1.1.2.2 riz lsb &= 0xf;
344 1.1.2.2 riz limits->sel_warnmin = 1350000 / (msb << 4 | lsb);
345 1.1.2.2 riz *props |= PROP_WARNMIN;
346 1.1.2.2 riz break;
347 1.1.2.2 riz }
348 1.1.2.2 riz
349 1.1.2.2 riz iic_release_bus(sc->sc_tag, 0);
350 1.1.2.2 riz }
351 1.1.2.2 riz
352 1.1.2.2 riz static int
353 1.1.2.2 riz w83795g_gpio_read(void *arg, int pin)
354 1.1.2.2 riz {
355 1.1.2.2 riz struct w83795g_softc *sc = arg;
356 1.1.2.2 riz uint8_t in, out;
357 1.1.2.2 riz
358 1.1.2.2 riz iic_acquire_bus(sc->sc_tag, 0);
359 1.1.2.2 riz iic_smbus_write_byte(sc->sc_tag, sc->sc_addr, W83795G_BANKSEL, 0, 0);
360 1.1.2.2 riz iic_smbus_read_byte(sc->sc_tag, sc->sc_addr, W83795G_GPIO_I, &in, 0);
361 1.1.2.2 riz iic_smbus_read_byte(sc->sc_tag, sc->sc_addr, W83795G_GPIO_O, &out, 0);
362 1.1.2.2 riz iic_release_bus(sc->sc_tag, 0);
363 1.1.2.2 riz
364 1.1.2.2 riz if (sc->sc_gpio_pins[pin].pin_flags == GPIO_PIN_OUTPUT)
365 1.1.2.2 riz in = out;
366 1.1.2.2 riz
367 1.1.2.2 riz return (in & (1 << pin)) ? GPIO_PIN_HIGH : GPIO_PIN_LOW;
368 1.1.2.2 riz }
369 1.1.2.2 riz
370 1.1.2.2 riz static void
371 1.1.2.2 riz w83795g_gpio_write(void *arg, int pin, int value)
372 1.1.2.2 riz {
373 1.1.2.2 riz struct w83795g_softc *sc = arg;
374 1.1.2.2 riz uint8_t out;
375 1.1.2.2 riz
376 1.1.2.2 riz iic_acquire_bus(sc->sc_tag, 0);
377 1.1.2.2 riz iic_smbus_write_byte(sc->sc_tag, sc->sc_addr, W83795G_BANKSEL, 0, 0);
378 1.1.2.2 riz iic_smbus_read_byte(sc->sc_tag, sc->sc_addr, W83795G_GPIO_O, &out, 0);
379 1.1.2.2 riz
380 1.1.2.2 riz if (value == GPIO_PIN_LOW)
381 1.1.2.2 riz out &= ~(1 << pin);
382 1.1.2.2 riz else if (value == GPIO_PIN_HIGH)
383 1.1.2.2 riz out |= (1 << pin);
384 1.1.2.2 riz
385 1.1.2.2 riz iic_smbus_write_byte(sc->sc_tag, sc->sc_addr, W83795G_GPIO_O, out, 0);
386 1.1.2.2 riz iic_release_bus(sc->sc_tag, 0);
387 1.1.2.2 riz }
388 1.1.2.2 riz
389 1.1.2.2 riz static void
390 1.1.2.2 riz w83795g_gpio_ctl(void *arg, int pin, int flags)
391 1.1.2.2 riz {
392 1.1.2.2 riz struct w83795g_softc *sc = arg;
393 1.1.2.2 riz uint8_t mode;
394 1.1.2.2 riz
395 1.1.2.2 riz iic_acquire_bus(sc->sc_tag, 0);
396 1.1.2.2 riz iic_smbus_write_byte(sc->sc_tag, sc->sc_addr, W83795G_BANKSEL, 0, 0);
397 1.1.2.2 riz iic_smbus_read_byte(sc->sc_tag, sc->sc_addr, W83795G_GPIO_M, &mode, 0);
398 1.1.2.2 riz
399 1.1.2.2 riz if (flags & GPIO_PIN_INPUT)
400 1.1.2.2 riz mode &= ~(1 << pin);
401 1.1.2.2 riz if (flags & GPIO_PIN_OUTPUT)
402 1.1.2.2 riz mode |= (1 << pin);
403 1.1.2.2 riz
404 1.1.2.2 riz iic_smbus_write_byte(sc->sc_tag, sc->sc_addr, W83795G_GPIO_M, mode, 0);
405 1.1.2.2 riz iic_release_bus(sc->sc_tag, 0);
406 1.1.2.2 riz }
407 1.1.2.2 riz
408 1.1.2.2 riz static int
409 1.1.2.2 riz w83795g_wdog_setmode(struct sysmon_wdog *smw)
410 1.1.2.2 riz {
411 1.1.2.2 riz struct w83795g_softc *sc = smw->smw_cookie;
412 1.1.2.2 riz
413 1.1.2.2 riz /*
414 1.1.2.2 riz * This device also supports a "hard" watchdog mode, which survives
415 1.1.2.2 riz * across reboots, but making use of that would require sysmon_wdog
416 1.1.2.2 riz * to have a way of querying the watchdog state at startup.
417 1.1.2.2 riz */
418 1.1.2.2 riz
419 1.1.2.2 riz iic_acquire_bus(sc->sc_tag, 0);
420 1.1.2.2 riz iic_smbus_write_byte(sc->sc_tag, sc->sc_addr, W83795G_BANKSEL, 0, 0);
421 1.1.2.2 riz iic_smbus_write_byte(sc->sc_tag, sc->sc_addr, W83795G_WDT_ENA,
422 1.1.2.2 riz WDT_ENA_ENWDT | WDT_ENA_SOFT, 0);
423 1.1.2.2 riz if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED)
424 1.1.2.2 riz iic_smbus_write_byte(sc->sc_tag, sc->sc_addr, W83795G_WDTLOCK,
425 1.1.2.2 riz WDTLOCK_DISABLE_SOFT, 0);
426 1.1.2.2 riz else
427 1.1.2.2 riz iic_smbus_write_byte(sc->sc_tag, sc->sc_addr, W83795G_WDTLOCK,
428 1.1.2.2 riz WDTLOCK_ENABLE_SOFT, 0);
429 1.1.2.2 riz iic_release_bus(sc->sc_tag, 0);
430 1.1.2.2 riz
431 1.1.2.2 riz if (smw->smw_period == WDOG_PERIOD_DEFAULT)
432 1.1.2.2 riz smw->smw_period = 60;
433 1.1.2.2 riz smw->smw_period = roundup(smw->smw_period, 60);
434 1.1.2.2 riz w83795g_wdog_tickle(smw);
435 1.1.2.2 riz
436 1.1.2.2 riz return 0;
437 1.1.2.2 riz }
438 1.1.2.2 riz
439 1.1.2.2 riz static int
440 1.1.2.2 riz w83795g_wdog_tickle(struct sysmon_wdog *smw)
441 1.1.2.2 riz {
442 1.1.2.2 riz struct w83795g_softc *sc = smw->smw_cookie;
443 1.1.2.2 riz
444 1.1.2.2 riz iic_acquire_bus(sc->sc_tag, 0);
445 1.1.2.2 riz iic_smbus_write_byte(sc->sc_tag, sc->sc_addr, W83795G_BANKSEL, 0, 0);
446 1.1.2.2 riz iic_smbus_write_byte(sc->sc_tag, sc->sc_addr, W83795G_WDT_CNT,
447 1.1.2.2 riz smw->smw_period / 60, 0);
448 1.1.2.2 riz iic_release_bus(sc->sc_tag, 0);
449 1.1.2.2 riz
450 1.1.2.2 riz return 0;
451 1.1.2.2 riz }
452