1*eb7eaf8dSmpi /* $OpenBSD: environ.c,v 1.2 2021/10/24 17:05:03 mpi Exp $ */
2df5a06c9Skettenis
3df5a06c9Skettenis /*
4df5a06c9Skettenis * Copyright (c) 2008 Mark Kettenis
5df5a06c9Skettenis *
6df5a06c9Skettenis * Permission to use, copy, modify, and distribute this software for any
7df5a06c9Skettenis * purpose with or without fee is hereby granted, provided that the above
8df5a06c9Skettenis * copyright notice and this permission notice appear in all copies.
9df5a06c9Skettenis *
10df5a06c9Skettenis * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11df5a06c9Skettenis * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12df5a06c9Skettenis * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13df5a06c9Skettenis * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14df5a06c9Skettenis * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15df5a06c9Skettenis * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16df5a06c9Skettenis * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17df5a06c9Skettenis */
18df5a06c9Skettenis
19df5a06c9Skettenis /*
20df5a06c9Skettenis * Driver for environment device on Enterprise 3000/4000/5000/6000
21df5a06c9Skettenis * and Enterprise 3500/4500/5500/6500.
22df5a06c9Skettenis */
23df5a06c9Skettenis
24df5a06c9Skettenis #include <sys/param.h>
25df5a06c9Skettenis #include <sys/device.h>
26df5a06c9Skettenis #include <sys/kernel.h>
27df5a06c9Skettenis #include <sys/sensors.h>
28df5a06c9Skettenis #include <sys/systm.h>
29df5a06c9Skettenis
30df5a06c9Skettenis #include <machine/bus.h>
31df5a06c9Skettenis #include <machine/autoconf.h>
32df5a06c9Skettenis
33df5a06c9Skettenis #include <sparc64/dev/fhcvar.h>
34df5a06c9Skettenis
35df5a06c9Skettenis struct environ_softc {
36df5a06c9Skettenis struct device sc_dv;
37df5a06c9Skettenis bus_space_tag_t sc_iot;
38df5a06c9Skettenis bus_space_handle_t sc_ioh;
39df5a06c9Skettenis
40df5a06c9Skettenis struct ksensor sc_sensor;
41df5a06c9Skettenis struct ksensordev sc_sensordev;
42df5a06c9Skettenis };
43df5a06c9Skettenis
44df5a06c9Skettenis int environ_match(struct device *, void *, void *);
45df5a06c9Skettenis void environ_attach(struct device *, struct device *, void *);
46df5a06c9Skettenis void environ_refresh(void *);
47df5a06c9Skettenis
48*eb7eaf8dSmpi const struct cfattach environ_ca = {
49df5a06c9Skettenis sizeof(struct environ_softc), environ_match, environ_attach
50df5a06c9Skettenis };
51df5a06c9Skettenis
52df5a06c9Skettenis struct cfdriver environ_cd = {
53df5a06c9Skettenis NULL, "environ", DV_DULL
54df5a06c9Skettenis };
55df5a06c9Skettenis
56df5a06c9Skettenis int
environ_match(struct device * parent,void * cf,void * aux)57df5a06c9Skettenis environ_match(struct device *parent, void *cf, void *aux)
58df5a06c9Skettenis {
59df5a06c9Skettenis struct fhc_attach_args *fa = aux;
60df5a06c9Skettenis
61df5a06c9Skettenis if (strcmp("environment", fa->fa_name) == 0)
62df5a06c9Skettenis return (1);
63df5a06c9Skettenis return (0);
64df5a06c9Skettenis }
65df5a06c9Skettenis
66df5a06c9Skettenis void
environ_attach(struct device * parent,struct device * self,void * aux)67df5a06c9Skettenis environ_attach(struct device *parent, struct device *self, void *aux)
68df5a06c9Skettenis {
69df5a06c9Skettenis struct environ_softc *sc = (void *)self;
70df5a06c9Skettenis struct fhc_attach_args *fa = aux;
71df5a06c9Skettenis
72df5a06c9Skettenis sc->sc_iot = fa->fa_bustag;
73df5a06c9Skettenis if (fhc_bus_map(sc->sc_iot, fa->fa_reg[0].fbr_slot,
74df5a06c9Skettenis fa->fa_reg[0].fbr_offset, fa->fa_reg[0].fbr_size, 0,
75df5a06c9Skettenis &sc->sc_ioh)) {
76df5a06c9Skettenis printf(": can't map registers\n");
77df5a06c9Skettenis return;
78df5a06c9Skettenis }
79df5a06c9Skettenis
80df5a06c9Skettenis /* First reading allegedly gives garbage. */
81df5a06c9Skettenis bus_space_read_1(sc->sc_iot, sc->sc_ioh, 0);
82df5a06c9Skettenis delay(30);
83df5a06c9Skettenis
84df5a06c9Skettenis /* Initialize sensor data. */
85df5a06c9Skettenis strlcpy(sc->sc_sensordev.xname, sc->sc_dv.dv_xname,
86df5a06c9Skettenis sizeof(sc->sc_sensordev.xname));
87df5a06c9Skettenis sc->sc_sensor.type = SENSOR_TEMP;
88df5a06c9Skettenis
89df5a06c9Skettenis sensor_attach(&sc->sc_sensordev, &sc->sc_sensor);
90df5a06c9Skettenis
91df5a06c9Skettenis if (sensor_task_register(sc, environ_refresh, 5) == NULL) {
92df5a06c9Skettenis printf(": unable to register update task\n");
93df5a06c9Skettenis return;
94df5a06c9Skettenis }
95df5a06c9Skettenis
96df5a06c9Skettenis sensordev_install(&sc->sc_sensordev);
97df5a06c9Skettenis
98df5a06c9Skettenis printf("\n");
99df5a06c9Skettenis }
100df5a06c9Skettenis
101df5a06c9Skettenis /*
102df5a06c9Skettenis * Calibration table for 2nd generation CPU boards.
103df5a06c9Skettenis */
104df5a06c9Skettenis int8_t environ_cpu2_temp[] = {
105df5a06c9Skettenis -17, -16, -15, -14, -13, -12, -11, -10,
106df5a06c9Skettenis -9, -8, -7, -6, -5, -4, -3, -2,
107df5a06c9Skettenis -1, 0, 1, 2, 3, 4, 5, 6,
108df5a06c9Skettenis 7, 8, 9, 10, 11, 12, 13, 13,
109df5a06c9Skettenis 14, 15, 16, 16, 17, 18, 18, 19,
110df5a06c9Skettenis 20, 20, 21, 22, 22, 23, 24, 24,
111df5a06c9Skettenis 25, 25, 26, 26, 27, 27, 28, 28,
112df5a06c9Skettenis 29, 30, 30, 31, 31, 32, 32, 33,
113df5a06c9Skettenis 33, 34, 34, 35, 35, 36, 36, 37,
114df5a06c9Skettenis 37, 37, 38, 38, 39, 39, 40, 40,
115df5a06c9Skettenis 41, 41, 42, 42, 43, 43, 43, 44,
116df5a06c9Skettenis 44, 45, 45, 46, 46, 46, 47, 47,
117df5a06c9Skettenis 48, 48, 49, 49, 50, 50, 50, 51,
118df5a06c9Skettenis 51, 52, 52, 53, 53, 53, 54, 54,
119df5a06c9Skettenis 55, 55, 56, 56, 56, 57, 57, 58,
120df5a06c9Skettenis 58, 59, 59, 59, 60, 60, 61, 61,
121df5a06c9Skettenis 62, 62, 63, 63, 63, 64, 64, 65,
122df5a06c9Skettenis 65, 66, 66, 67, 67, 68, 68, 68,
123df5a06c9Skettenis 69, 69, 70, 70, 71, 71, 72, 72,
124df5a06c9Skettenis 73, 73, 74, 74, 75, 75, 76, 76,
125df5a06c9Skettenis 77, 77, 78, 78, 79, 79, 80, 80,
126df5a06c9Skettenis 81, 81, 82, 83, 83, 84, 84, 85,
127df5a06c9Skettenis 85, 86, 87, 87, 88, 88, 89, 90,
128df5a06c9Skettenis 90, 91, 92, 92, 93, 94, 94, 95,
129df5a06c9Skettenis 96, 96, 97, 98, 99, 99, 100, 101,
130df5a06c9Skettenis 102, 103, 103, 104, 105, 106, 107, 108,
131df5a06c9Skettenis 109, 110
132df5a06c9Skettenis };
133df5a06c9Skettenis
134df5a06c9Skettenis void
environ_refresh(void * arg)135df5a06c9Skettenis environ_refresh(void *arg)
136df5a06c9Skettenis {
137df5a06c9Skettenis struct environ_softc *sc = arg;
138df5a06c9Skettenis u_int8_t val;
139df5a06c9Skettenis int8_t temp;
140df5a06c9Skettenis
141df5a06c9Skettenis val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 0);
142df5a06c9Skettenis
143df5a06c9Skettenis if (val == 0xff) {
144df5a06c9Skettenis sc->sc_sensor.flags |= SENSOR_FINVALID;
145df5a06c9Skettenis return;
146df5a06c9Skettenis }
147df5a06c9Skettenis
148df5a06c9Skettenis if (val < sizeof(environ_cpu2_temp))
149df5a06c9Skettenis temp = environ_cpu2_temp[val];
150df5a06c9Skettenis else
151df5a06c9Skettenis temp = 110;
152df5a06c9Skettenis
153df5a06c9Skettenis sc->sc_sensor.value = val * 1000000 + 273150000;
154df5a06c9Skettenis sc->sc_sensor.flags &= ~SENSOR_FINVALID;
155df5a06c9Skettenis }
156