1 /* $NetBSD: ug.c,v 1.15 2022/09/25 18:43:32 thorpej Exp $ */
2 
3 /*
4  * Copyright (c) 2007 Mihai Chelaru <kefren@netbsd.ro>
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 AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: ug.c,v 1.15 2022/09/25 18:43:32 thorpej Exp $");
30 
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/proc.h>
35 #include <sys/device.h>
36 #include <sys/errno.h>
37 #include <sys/conf.h>
38 #include <sys/envsys.h>
39 #include <sys/time.h>
40 
41 #include <sys/bus.h>
42 #include <sys/intr.h>
43 
44 #include <dev/isa/isareg.h>
45 #include <dev/isa/isavar.h>
46 
47 #include <dev/sysmon/sysmonvar.h>
48 
49 #include <dev/ic/ugreg.h>
50 #include <dev/ic/ugvar.h>
51 
52 uint8_t ug_ver;
53 
54 /*
55  * Imported from linux driver
56  */
57 
58 static const struct ug2_motherboard_info ug2_mb[] = {
59           { 0x000C, "unknown. Please send-pr(1)", {
60                     { "CPU Core", 0, 0, 10, 1, 0 },
61                     { "DDR", 1, 0, 10, 1, 0 },
62                     { "DDR VTT", 2, 0, 10, 1, 0 },
63                     { "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
64                     { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
65                     { "MCH 2.5V", 5, 0, 20, 1, 0 },
66                     { "ICH 1.05V", 6, 0, 10, 1, 0 },
67                     { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
68                     { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
69                     { "ATX +5V", 9, 0, 30, 1, 0 },
70                     { "+3.3V", 10, 0, 20, 1, 0 },
71                     { "5VSB", 11, 0, 30, 1, 0 },
72                     { "CPU", 24, 1, 1, 1, 0 },
73                     { "System", 25, 1, 1, 1, 0 },
74                     { "PWM", 26, 1, 1, 1, 0 },
75                     { "CPU Fan", 32, 2, 60, 1, 0 },
76                     { "NB Fan", 33, 2, 60, 1, 0 },
77                     { "SYS FAN", 34, 2, 60, 1, 0 },
78                     { "AUX1 Fan", 35, 2, 60, 1, 0 },
79                     { NULL, 0, 0, 0, 0, 0 } }
80           },
81           { 0x000D, "Abit AW8", {
82                     { "CPU Core", 0, 0, 10, 1, 0 },
83                     { "DDR", 1, 0, 10, 1, 0 },
84                     { "DDR VTT", 2, 0, 10, 1, 0 },
85                     { "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
86                     { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
87                     { "MCH 2.5V", 5, 0, 20, 1, 0 },
88                     { "ICH 1.05V", 6, 0, 10, 1, 0 },
89                     { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
90                     { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
91                     { "ATX +5V", 9, 0, 30, 1, 0 },
92                     { "+3.3V", 10, 0, 20, 1, 0 },
93                     { "5VSB", 11, 0, 30, 1, 0 },
94                     { "CPU", 24, 1, 1, 1, 0 },
95                     { "System", 25, 1, 1, 1, 0 },
96                     { "PWM1", 26, 1, 1, 1, 0 },
97                     { "PWM2", 27, 1, 1, 1, 0 },
98                     { "PWM3", 28, 1, 1, 1, 0 },
99                     { "PWM4", 29, 1, 1, 1, 0 },
100                     { "CPU Fan", 32, 2, 60, 1, 0 },
101                     { "NB Fan", 33, 2, 60, 1, 0 },
102                     { "SYS Fan", 34, 2, 60, 1, 0 },
103                     { "AUX1 Fan", 35, 2, 60, 1, 0 },
104                     { "AUX2 Fan", 36, 2, 60, 1, 0 },
105                     { "AUX3 Fan", 37, 2, 60, 1, 0 },
106                     { "AUX4 Fan", 38, 2, 60, 1, 0 },
107                     { "AUX5 Fan", 39, 2, 60, 1, 0 },
108                     { NULL, 0, 0, 0, 0, 0 } }
109           },
110           { 0x000E, "Abit AL8", {
111                     { "CPU Core", 0, 0, 10, 1, 0 },
112                     { "DDR", 1, 0, 10, 1, 0 },
113                     { "DDR VTT", 2, 0, 10, 1, 0 },
114                     { "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
115                     { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
116                     { "MCH 2.5V", 5, 0, 20, 1, 0 },
117                     { "ICH 1.05V", 6, 0, 10, 1, 0 },
118                     { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
119                     { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
120                     { "ATX +5V", 9, 0, 30, 1, 0 },
121                     { "+3.3V", 10, 0, 20, 1, 0 },
122                     { "5VSB", 11, 0, 30, 1, 0 },
123                     { "CPU", 24, 1, 1, 1, 0 },
124                     { "System", 25, 1, 1, 1, 0 },
125                     { "PWM", 26, 1, 1, 1, 0 },
126                     { "CPU Fan", 32, 2, 60, 1, 0 },
127                     { "NB Fan", 33, 2, 60, 1, 0 },
128                     { "SYS Fan", 34, 2, 60, 1, 0 },
129                     { NULL, 0, 0, 0, 0, 0 } }
130           },
131           { 0x000F, "unknown. Please send-pr(1)", {
132                     { "CPU Core", 0, 0, 10, 1, 0 },
133                     { "DDR", 1, 0, 10, 1, 0 },
134                     { "DDR VTT", 2, 0, 10, 1, 0 },
135                     { "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
136                     { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
137                     { "MCH 2.5V", 5, 0, 20, 1, 0 },
138                     { "ICH 1.05V", 6, 0, 10, 1, 0 },
139                     { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
140                     { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
141                     { "ATX +5V", 9, 0, 30, 1, 0 },
142                     { "+3.3V", 10, 0, 20, 1, 0 },
143                     { "5VSB", 11, 0, 30, 1, 0 },
144                     { "CPU", 24, 1, 1, 1, 0 },
145                     { "System", 25, 1, 1, 1, 0 },
146                     { "PWM", 26, 1, 1, 1, 0 },
147                     { "CPU Fan", 32, 2, 60, 1, 0 },
148                     { "NB Fan", 33, 2, 60, 1, 0 },
149                     { "SYS Fan", 34, 2, 60, 1, 0 },
150                     { NULL, 0, 0, 0, 0, 0 } }
151           },
152           { 0x0010, "Abit NI8 SLI GR", {
153                     { "CPU Core", 0, 0, 10, 1, 0 },
154                     { "DDR", 1, 0, 10, 1, 0 },
155                     { "DDR VTT", 2, 0, 10, 1, 0 },
156                     { "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
157                     { "NB 1.4V", 4, 0, 10, 1, 0 },
158                     { "SB 1.5V", 6, 0, 10, 1, 0 },
159                     { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
160                     { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
161                     { "ATX +5V", 9, 0, 30, 1, 0 },
162                     { "+3.3V", 10, 0, 20, 1, 0 },
163                     { "5VSB", 11, 0, 30, 1, 0 },
164                     { "CPU", 24, 1, 1, 1, 0 },
165                     { "SYS", 25, 1, 1, 1, 0 },
166                     { "PWM", 26, 1, 1, 1, 0 },
167                     { "CPU Fan", 32, 2, 60, 1, 0 },
168                     { "NB Fan", 33, 2, 60, 1, 0 },
169                     { "SYS Fan", 34, 2, 60, 1, 0 },
170                     { "AUX1 Fan", 35, 2, 60, 1, 0 },
171                     { "OTES1 Fan", 36, 2, 60, 1, 0 },
172                     { NULL, 0, 0, 0, 0, 0 } }
173           },
174           { 0x0011, "Abit AT8 32X", {
175                     { "CPU Core", 0, 0, 10, 1, 0 },
176                     { "DDR", 1, 0, 20, 1, 0 },
177                     { "DDR VTT", 2, 0, 10, 1, 0 },
178                     { "CPU VDDA 2.5V", 6, 0, 20, 1, 0 },
179                     { "NB 1.8V", 4, 0, 10, 1, 0 },
180                     { "NB 1.8V Dual", 5, 0, 10, 1, 0 },
181                     { "HTV 1.2", 3, 0, 10, 1, 0 },
182                     { "PCIE 1.2V", 12, 0, 10, 1, 0 },
183                     { "NB 1.2V", 13, 0, 10, 1, 0 },
184                     { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
185                     { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
186                     { "ATX +5V", 9, 0, 30, 1, 0 },
187                     { "+3.3V", 10, 0, 20, 1, 0 },
188                     { "5VSB", 11, 0, 30, 1, 0 },
189                     { "CPU", 24, 1, 1, 1, 0 },
190                     { "NB", 25, 1, 1, 1, 0 },
191                     { "System", 26, 1, 1, 1, 0 },
192                     { "PWM", 27, 1, 1, 1, 0 },
193                     { "CPU Fan", 32, 2, 60, 1, 0 },
194                     { "NB Fan", 33, 2, 60, 1, 0 },
195                     { "SYS Fan", 34, 2, 60, 1, 0 },
196                     { "AUX1 Fan", 35, 2, 60, 1, 0 },
197                     { "AUX2 Fan", 36, 2, 60, 1, 0 },
198                     { NULL, 0, 0, 0, 0, 0 } }
199           },
200           { 0x0012, "unknown. Please send-pr(1)", {
201                     { "CPU Core", 0, 0, 10, 1, 0 },
202                     { "DDR", 1, 0, 20, 1, 0 },
203                     { "DDR VTT", 2, 0, 10, 1, 0 },
204                     { "HyperTransport", 3, 0, 10, 1, 0 },
205                     { "CPU VDDA 2.5V", 5, 0, 20, 1, 0 },
206                     { "NB", 4, 0, 10, 1, 0 },
207                     { "SB", 6, 0, 10, 1, 0 },
208                     { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
209                     { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
210                     { "ATX +5V", 9, 0, 30, 1, 0 },
211                     { "+3.3V", 10, 0, 20, 1, 0 },
212                     { "5VSB", 11, 0, 30, 1, 0 },
213                     { "CPU", 24, 1, 1, 1, 0 },
214                     { "SYS", 25, 1, 1, 1, 0 },
215                     { "PWM", 26, 1, 1, 1, 0 },
216                     { "CPU Fan", 32, 2, 60, 1, 0 },
217                     { "NB Fan", 33, 2, 60, 1, 0 },
218                     { "SYS Fan", 34, 2, 60, 1, 0 },
219                     { "AUX1 Fan", 36, 2, 60, 1, 0 },
220                     { NULL, 0, 0, 0, 0, 0 } }
221           },
222           { 0x0013, "unknown. Please send-pr(1)", {
223                     { "CPU Core", 0, 0, 10, 1, 0 },
224                     { "DDR", 1, 0, 10, 1, 0 },
225                     { "DDR VTT", 2, 0, 10, 1, 0 },
226                     { "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
227                     { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
228                     { "MCH 2.5V", 5, 0, 20, 1, 0 },
229                     { "ICH 1.05V", 6, 0, 10, 1, 0 },
230                     { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
231                     { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
232                     { "ATX +5V", 9, 0, 30, 1, 0 },
233                     { "+3.3V", 10, 0, 20, 1, 0 },
234                     { "5VSB", 11, 0, 30, 1, 0 },
235                     { "CPU", 24, 1, 1, 1, 0 },
236                     { "System", 25, 1, 1, 1, 0 },
237                     { "PWM1", 26, 1, 1, 1, 0 },
238                     { "PWM2", 27, 1, 1, 1, 0 },
239                     { "PWM3", 28, 1, 1, 1, 0 },
240                     { "PWM4", 29, 1, 1, 1, 0 },
241                     { "CPU Fan", 32, 2, 60, 1, 0 },
242                     { "NB Fan", 33, 2, 60, 1, 0 },
243                     { "SYS Fan", 34, 2, 60, 1, 0 },
244                     { "AUX1 Fan", 35, 2, 60, 1, 0 },
245                     { "AUX2 Fan", 36, 2, 60, 1, 0 },
246                     { "AUX3 Fan", 37, 2, 60, 1, 0 },
247                     { "AUX4 Fan", 38, 2, 60, 1, 0 },
248                     { NULL, 0, 0, 0, 0, 0 } }
249           },
250           { 0x0014, "Abit AB9 Pro", {
251                     { "CPU Core", 0, 0, 10, 1, 0 },
252                     { "DDR", 1, 0, 10, 1, 0 },
253                     { "DDR VTT", 2, 0, 10, 1, 0 },
254                     { "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
255                     { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
256                     { "MCH 2.5V", 5, 0, 20, 1, 0 },
257                     { "ICH 1.05V", 6, 0, 10, 1, 0 },
258                     { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
259                     { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
260                     { "ATX +5V", 9, 0, 30, 1, 0 },
261                     { "+3.3V", 10, 0, 20, 1, 0 },
262                     { "5VSB", 11, 0, 30, 1, 0 },
263                     { "CPU", 24, 1, 1, 1, 0 },
264                     { "System", 25, 1, 1, 1, 0 },
265                     { "PWM", 26, 1, 1, 1, 0 },
266                     { "CPU Fan", 32, 2, 60, 1, 0 },
267                     { "NB Fan", 33, 2, 60, 1, 0 },
268                     { "SYS Fan", 34, 2, 60, 1, 0 },
269                     { NULL, 0, 0, 0, 0, 0 } }
270           },
271           { 0x0015, "unknown. Please send-pr(1)", {
272                     { "CPU Core", 0, 0, 10, 1, 0 },
273                     { "DDR", 1, 0, 20, 1, 0 },
274                     { "DDR VTT", 2, 0, 10, 1, 0 },
275                     { "HyperTransport", 3, 0, 10, 1, 0 },
276                     { "CPU VDDA 2.5V", 5, 0, 20, 1, 0 },
277                     { "NB", 4, 0, 10, 1, 0 },
278                     { "SB", 6, 0, 10, 1, 0 },
279                     { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
280                     { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
281                     { "ATX +5V", 9, 0, 30, 1, 0 },
282                     { "+3.3V", 10, 0, 20, 1, 0 },
283                     { "5VSB", 11, 0, 30, 1, 0 },
284                     { "CPU", 24, 1, 1, 1, 0 },
285                     { "SYS", 25, 1, 1, 1, 0 },
286                     { "PWM", 26, 1, 1, 1, 0 },
287                     { "CPU Fan", 32, 2, 60, 1, 0 },
288                     { "NB Fan", 33, 2, 60, 1, 0 },
289                     { "SYS Fan", 34, 2, 60, 1, 0 },
290                     { "AUX1 Fan", 33, 2, 60, 1, 0 },
291                     { "AUX2 Fan", 35, 2, 60, 1, 0 },
292                     { "AUX3 Fan", 36, 2, 60, 1, 0 },
293                     { NULL, 0, 0, 0, 0, 0 } }
294           },
295           { 0x0016, "generic", {
296                     { "CPU Core", 0, 0, 10, 1, 0 },
297                     { "DDR", 1, 0, 20, 1, 0 },
298                     { "DDR VTT", 2, 0, 10, 1, 0 },
299                     { "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
300                     { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
301                     { "MCH 2.5V", 5, 0, 20, 1, 0 },
302                     { "ICH 1.05V", 6, 0, 10, 1, 0 },
303                     { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
304                     { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
305                     { "ATX +5V", 9, 0, 30, 1, 0 },
306                     { "+3.3V", 10, 0, 20, 1, 0 },
307                     { "5VSB", 11, 0, 30, 1, 0 },
308                     { "CPU", 24, 1, 1, 1, 0 },
309                     { "System", 25, 1, 1, 1, 0 },
310                     { "PWM", 26, 1, 1, 1, 0 },
311                     { "CPU Fan", 32, 2, 60, 1, 0 },
312                     { "NB Fan", 33, 2, 60, 1, 0 },
313                     { "SYS FAN", 34, 2, 60, 1, 0 },
314                     { "AUX1 Fan", 35, 2, 60, 1, 0 },
315                     { NULL, 0, 0, 0, 0, 0 } }
316           },
317           { 0x0000, NULL, { { NULL, 0, 0, 0, 0, 0 } } }
318 };
319 
320 
321 int
ug_reset(struct ug_softc * sc)322 ug_reset(struct ug_softc *sc)
323 {
324           int cnt = 0;
325 
326           while (bus_space_read_1(sc->sc_iot, sc->sc_ioh, UG_DATA) != 0x08) {
327           /* 8 meaning Voodoo */
328 
329                     if (cnt++ > UG_DELAY_CYCLES)
330                               return 0;
331 
332                     bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_DATA, 0);
333 
334                     /* Wait for 0x09 at Data Port */
335                     if (!ug_waitfor(sc, UG_DATA, 0x09))
336                               return 0;
337 
338                     /* Wait for 0xAC at Cmd Port */
339                     if (!ug_waitfor(sc, UG_CMD, 0xAC))
340                               return 0;
341           }
342 
343           return 1;
344 }
345 
346 uint8_t
ug_read(struct ug_softc * sc,unsigned short sensor)347 ug_read(struct ug_softc *sc, unsigned short sensor)
348 {
349           uint8_t bank, sens, rv;
350 
351           bank = (sensor & 0xFF00) >> 8;
352           sens = sensor & 0x00FF;
353 
354           bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_DATA, bank);
355 
356           /* Wait 8 at Data Port */
357           if (!ug_waitfor(sc, UG_DATA, 8))
358                     return 0;
359 
360           bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_CMD, sens);
361 
362           /* Wait 1 at Data Port */
363           if (!ug_waitfor(sc, UG_DATA, 1))
364                     return 0;
365 
366           /* Finally read the sensor */
367           rv = bus_space_read_1(sc->sc_iot, sc->sc_ioh, UG_CMD);
368 
369           ug_reset(sc);
370 
371           return rv;
372 }
373 
374 int
ug_waitfor(struct ug_softc * sc,uint16_t offset,uint8_t value)375 ug_waitfor(struct ug_softc *sc, uint16_t offset, uint8_t value)
376 {
377           int cnt = 0;
378           while (bus_space_read_1(sc->sc_iot, sc->sc_ioh, offset) != value) {
379                     if (cnt++ > UG_DELAY_CYCLES)
380                               return 0;
381           }
382           return 1;
383 }
384 
385 void
ug_setup_sensors(struct ug_softc * sc)386 ug_setup_sensors(struct ug_softc *sc)
387 {
388           int i;
389 
390           /* Setup Temps */
391           for (i = 0; i < UG_VOLT_MIN; i++)
392                     sc->sc_sensor[i].units = ENVSYS_STEMP;
393 
394 #define COPYDESCR(x, y)                                     \
395           do {                                              \
396                     strlcpy((x), (y), sizeof(x)); \
397           } while (0)
398 
399           COPYDESCR(sc->sc_sensor[0].desc, "CPU Temp");
400           COPYDESCR(sc->sc_sensor[1].desc, "SYS Temp");
401           COPYDESCR(sc->sc_sensor[2].desc, "PWN Temp");
402 
403           /* Right, Now setup U sensors */
404 
405           for (i = UG_VOLT_MIN; i < UG_FAN_MIN; i++) {
406                     sc->sc_sensor[i].units = ENVSYS_SVOLTS_DC;
407                     sc->sc_sensor[i].rfact = UG_RFACT;
408           }
409 
410           COPYDESCR(sc->sc_sensor[3].desc, "HTVdd");
411           COPYDESCR(sc->sc_sensor[4].desc, "VCore");
412           COPYDESCR(sc->sc_sensor[5].desc, "DDRVdd");
413           COPYDESCR(sc->sc_sensor[6].desc, "Vdd3V3");
414           COPYDESCR(sc->sc_sensor[7].desc, "Vdd5V");
415           COPYDESCR(sc->sc_sensor[8].desc, "NBVdd");
416           COPYDESCR(sc->sc_sensor[9].desc, "AGPVdd");
417           COPYDESCR(sc->sc_sensor[10].desc, "DDRVtt");
418           COPYDESCR(sc->sc_sensor[11].desc, "Vdd5VSB");
419           COPYDESCR(sc->sc_sensor[12].desc, "Vdd3VDual");
420           COPYDESCR(sc->sc_sensor[13].desc, "SBVdd");
421 
422           /* Fan sensors */
423           for (i = UG_FAN_MIN; i < UG_NUM_SENSORS; i++)
424                     sc->sc_sensor[i].units = ENVSYS_SFANRPM;
425 
426           COPYDESCR(sc->sc_sensor[14].desc, "CPU Fan");
427           COPYDESCR(sc->sc_sensor[15].desc, "NB Fan");
428           COPYDESCR(sc->sc_sensor[16].desc, "SYS Fan");
429           COPYDESCR(sc->sc_sensor[17].desc, "AUX Fan 1");
430           COPYDESCR(sc->sc_sensor[18].desc, "AUX Fan 2");
431 
432           /* All sensors */
433           for (i = 0; i < UG_NUM_SENSORS; i++)
434                     sc->sc_sensor[i].units = ENVSYS_SINVALID;
435 }
436 
437 void
ug_refresh(struct sysmon_envsys * sme,envsys_data_t * edata)438 ug_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
439 {
440           struct ug_softc *sc = sme->sme_cookie;
441 
442           /* Sensors return C while we need uK */
443 
444           if (edata->sensor < UG_VOLT_MIN - 1) /* CPU and SYS Temps */
445                     edata->value_cur = ug_read(sc, UG_CPUTEMP + edata->sensor)
446                         * 1000000 + 273150000;
447           else if (edata->sensor == 2) /* PWMTEMP */
448                     edata->value_cur = ug_read(sc, UG_PWMTEMP)
449                         * 1000000 + 273150000;
450 
451           /* Voltages */
452 
453 #define VOLT_SENSOR UG_HTV + edata->sensor - UG_VOLT_MIN
454 
455           else
456               if ((edata->sensor >= UG_VOLT_MIN) && (edata->sensor < UG_FAN_MIN)) {
457                     edata->value_cur = ug_read(sc, VOLT_SENSOR);
458                     switch(VOLT_SENSOR) {
459                               case UG_5V:                   /* 6V RFact */
460                               case UG_5VSB:
461                                         edata->value_cur *= UG_RFACT6;
462                                         break;
463                               case UG_3V3:                  /* 4V RFact */
464                               case UG_3VDUAL:
465                                         edata->value_cur *= UG_RFACT4;
466                                         break;
467                               default:            /* 3V RFact */
468                                         edata->value_cur *= UG_RFACT3;
469                                         break;
470                     }
471               } else
472 
473 #undef VOLT_SENSOR
474 
475           /* and Fans */
476           if (edata->sensor >= UG_FAN_MIN)
477                     edata->value_cur = ug_read(sc, UG_CPUFAN +
478                         edata->sensor - UG_FAN_MIN) * UG_RFACT_FAN;
479 }
480 
481 void
ug2_attach(device_t dv)482 ug2_attach(device_t dv)
483 {
484           struct ug_softc *sc = device_private(dv);
485           uint8_t buf[2];
486           int i;
487           const struct ug2_motherboard_info *ai;
488           const struct ug2_sensor_info *si;
489 
490           aprint_normal(": Abit uGuru 2005 system monitor\n");
491 
492           if (ug2_read(sc, UG2_MISC_BANK, UG2_BOARD_ID, 2, buf) != 2) {
493                     aprint_error_dev(dv, "Cannot detect board ID. Using default\n");
494                     buf[0] = UG_MAX_MSB_BOARD;
495                     buf[1] = UG_MAX_LSB_BOARD;
496           }
497 
498           if (buf[0] > UG_MAX_MSB_BOARD || buf[1] > UG_MAX_LSB_BOARD ||
499                     buf[1] < UG_MIN_LSB_BOARD) {
500                     aprint_error_dev(dv, "Invalid board ID(%X,%X). Using default\n",
501                               buf[0], buf[1]);
502                     buf[0] = UG_MAX_MSB_BOARD;
503                     buf[1] = UG_MAX_LSB_BOARD;
504           }
505 
506           ai = &ug2_mb[buf[1] - UG_MIN_LSB_BOARD];
507 
508           aprint_normal_dev(dv, "mainboard %s (%.2X%.2X)\n",
509               ai->name, buf[0], buf[1]);
510 
511           sc->mbsens = (const void *)ai->sensors;
512           sc->sc_sme = sysmon_envsys_create();
513 
514           for (i = 0, si = ai->sensors; si && si->name; si++, i++) {
515                     COPYDESCR(sc->sc_sensor[i].desc, si->name);
516                     sc->sc_sensor[i].rfact = 1;
517                     sc->sc_sensor[i].state = ENVSYS_SVALID;
518                     switch (si->type) {
519                               case UG2_VOLTAGE_SENSOR:
520                                         sc->sc_sensor[i].units = ENVSYS_SVOLTS_DC;
521                                         sc->sc_sensor[i].rfact = UG_RFACT;
522                                         break;
523                               case UG2_TEMP_SENSOR:
524                                         sc->sc_sensor[i].units = ENVSYS_STEMP;
525                                         break;
526                               case UG2_FAN_SENSOR:
527                                         sc->sc_sensor[i].units = ENVSYS_SFANRPM;
528                                         break;
529                               default:
530                                         break;
531                     }
532                     if (sysmon_envsys_sensor_attach(sc->sc_sme,
533                                                             &sc->sc_sensor[i])) {
534                               sysmon_envsys_destroy(sc->sc_sme);
535                               return;
536                     }
537           }
538 #undef COPYDESCR
539 
540           sc->sc_sme->sme_name = device_xname(dv);
541           sc->sc_sme->sme_cookie = sc;
542           sc->sc_sme->sme_refresh = ug2_refresh;
543 
544           if (sysmon_envsys_register(sc->sc_sme)) {
545                     aprint_error_dev(dv, "unable to register with sysmon\n");
546                     sysmon_envsys_destroy(sc->sc_sme);
547           }
548 }
549 
550 void
ug2_refresh(struct sysmon_envsys * sme,envsys_data_t * edata)551 ug2_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
552 {
553           struct ug_softc *sc = sme->sme_cookie;
554           const struct ug2_sensor_info *si =
555               (const struct ug2_sensor_info *)sc->mbsens;
556           int rfact = 1;
557           uint8_t v;
558 
559           si += edata->sensor;
560 
561 #define SENSOR_VALUE (v * si->multiplier * rfact / si->divisor + si->offset)
562 
563           if (ug2_read(sc, UG2_SENSORS_BANK, UG2_VALUES_OFFSET +
564               si->port, 1, &v) == 1) {
565                     switch (si->type) {
566                     case UG2_TEMP_SENSOR:
567                         edata->value_cur = SENSOR_VALUE * 1000000
568                               + 273150000;
569                         break;
570                     case UG2_VOLTAGE_SENSOR:
571                         rfact = UG_RFACT;
572                         edata->value_cur = SENSOR_VALUE;
573                         break;
574                     default:
575                         edata->value_cur = SENSOR_VALUE;
576                         break;
577                     }
578           }
579 #undef SENSOR_VALUE
580 }
581 
582 static int
ug2_wait_ready(bus_space_tag_t iot,bus_space_handle_t ioh)583 ug2_wait_ready(bus_space_tag_t iot, bus_space_handle_t ioh)
584 {
585           int cnt = 0;
586 
587           bus_space_write_1(iot, ioh, UG_DATA, 0x1a);
588           while (bus_space_read_1(iot, ioh, UG_DATA) &
589               UG2_STATUS_BUSY) {
590                     if (cnt++ > UG_DELAY_CYCLES)
591                               return 0;
592           }
593           return 1;
594 }
595 
596 static int
ug2_wait_readable(bus_space_tag_t iot,bus_space_handle_t ioh)597 ug2_wait_readable(bus_space_tag_t iot, bus_space_handle_t ioh)
598 {
599           int cnt = 0;
600 
601           while (!(bus_space_read_1(iot, ioh, UG_DATA) &
602                     UG2_STATUS_READY_FOR_READ)) {
603                     if (cnt++ > UG_DELAY_CYCLES)
604                               return 0;
605           }
606           return 1;
607 }
608 
609 int
ug2_sync(bus_space_tag_t iot,bus_space_handle_t ioh)610 ug2_sync(bus_space_tag_t iot, bus_space_handle_t ioh)
611 {
612           int cnt = 0;
613 
614 #define UG2_WAIT_READY if(ug2_wait_ready(iot, ioh) == 0) return 0;
615 
616           /* Don't sync two times in a row */
617           if (ug_ver != 0) {
618                     ug_ver = 0;
619                     return 1;
620           }
621 
622           UG2_WAIT_READY;
623           bus_space_write_1(iot, ioh, UG_DATA, 0x20);
624           UG2_WAIT_READY;
625           bus_space_write_1(iot, ioh, UG_CMD, 0x10);
626           UG2_WAIT_READY;
627           bus_space_write_1(iot, ioh, UG_CMD, 0x00);
628           UG2_WAIT_READY;
629           if (ug2_wait_readable(iot, ioh) == 0)
630                     return 0;
631           while (bus_space_read_1(iot, ioh, UG_CMD) != 0xAC)
632                     if (cnt++ > UG_DELAY_CYCLES)
633                               return 0;
634           return 1;
635 }
636 
637 int
ug2_read(struct ug_softc * sc,uint8_t bank,uint8_t offset,uint8_t count,uint8_t * ret)638 ug2_read(struct ug_softc *sc, uint8_t bank, uint8_t offset, uint8_t count,
639            uint8_t *ret)
640 {
641           int i;
642           bus_space_tag_t iot = sc->sc_iot;
643           bus_space_handle_t ioh = sc->sc_ioh;
644 
645           if (ug2_sync(iot, ioh) == 0)
646                     return 0;
647 
648           bus_space_write_1(iot, ioh, UG_DATA, 0x1A);
649           UG2_WAIT_READY;
650           bus_space_write_1(iot, ioh, UG_CMD, bank);
651           UG2_WAIT_READY;
652           bus_space_write_1(iot, ioh, UG_CMD, offset);
653           UG2_WAIT_READY;
654           bus_space_write_1(iot, ioh, UG_CMD, count);
655           UG2_WAIT_READY;
656 
657 #undef UG2_WAIT_READY
658 
659           /* Now wait for the results */
660           for (i = 0; i < count; i++) {
661                     if (ug2_wait_readable(sc->sc_iot, sc->sc_ioh) == 0)
662                               break;
663                     ret[i] = bus_space_read_1(sc->sc_iot, sc->sc_ioh, UG_CMD);
664           }
665 
666           return i;
667 }
668