xref: /openbsd-src/sys/arch/sparc64/dev/clkbrd.c (revision eb7eaf8de3ff431d305450f61b441e5460c82246)
1 /*	$OpenBSD: clkbrd.c,v 1.7 2021/10/24 17:05:03 mpi Exp $	*/
2 
3 /*
4  * Copyright (c) 2004 Jason L. Wright (jason@thought.net)
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
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/conf.h>
31 #include <sys/device.h>
32 #include <sys/kernel.h>
33 #include <sys/malloc.h>
34 #include <sys/sensors.h>
35 #include <sys/systm.h>
36 #include <sys/timeout.h>
37 
38 #include <machine/bus.h>
39 #include <machine/autoconf.h>
40 #include <machine/openfirm.h>
41 
42 #include <sparc64/dev/fhcvar.h>
43 #include <sparc64/dev/clkbrdreg.h>
44 #include <sparc64/dev/clkbrdvar.h>
45 
46 int clkbrd_match(struct device *, void *, void *);
47 void clkbrd_attach(struct device *, struct device *, void *);
48 void clkbrd_led_blink(void *, int);
49 void clkbrd_refresh(void *);
50 
51 const struct cfattach clkbrd_ca = {
52 	sizeof(struct clkbrd_softc), clkbrd_match, clkbrd_attach
53 };
54 
55 struct cfdriver clkbrd_cd = {
56 	NULL, "clkbrd", DV_DULL
57 };
58 
59 int
clkbrd_match(struct device * parent,void * match,void * aux)60 clkbrd_match(struct device *parent, void *match, void *aux)
61 {
62 	struct fhc_attach_args *fa = aux;
63 
64 	if (strcmp(fa->fa_name, "clock-board") == 0)
65 		return (1);
66 	return (0);
67 }
68 
69 void
clkbrd_attach(struct device * parent,struct device * self,void * aux)70 clkbrd_attach(struct device *parent, struct device *self, void *aux)
71 {
72 	struct clkbrd_softc *sc = (struct clkbrd_softc *)self;
73 	struct fhc_attach_args *fa = aux;
74 	int slots;
75 	u_int8_t r;
76 
77 	sc->sc_bt = fa->fa_bustag;
78 
79 	if (fa->fa_nreg < 2) {
80 		printf(": no registers\n");
81 		return;
82 	}
83 
84 	if (fhc_bus_map(sc->sc_bt, fa->fa_reg[1].fbr_slot,
85 	    fa->fa_reg[1].fbr_offset, fa->fa_reg[1].fbr_size, 0,
86 	    &sc->sc_creg)) {
87 		printf(": can't map ctrl regs\n");
88 		return;
89 	}
90 
91 	if (fa->fa_nreg > 2) {
92 		if (fhc_bus_map(sc->sc_bt, fa->fa_reg[2].fbr_slot,
93 		    fa->fa_reg[2].fbr_offset, fa->fa_reg[2].fbr_size, 0,
94 		    &sc->sc_vreg)) {
95 			printf(": can't map vreg\n");
96 			return;
97 		}
98 		sc->sc_has_vreg = 1;
99 	}
100 
101 	slots = 4;
102 	r = bus_space_read_1(sc->sc_bt, sc->sc_creg, CLK_STS1);
103 	switch (r & 0xc0) {
104 	case 0x40:
105 		slots = 16;
106 		break;
107 	case 0xc0:
108 		slots = 8;
109 		break;
110 	case 0x80:
111 		if (sc->sc_has_vreg) {
112 			r = bus_space_read_1(sc->sc_bt, sc->sc_vreg, 0);
113 			if (r != 0 && (r & 0x80) == 0)
114 					slots = 5;
115 		}
116 	}
117 
118 	sc->sc_blink.bl_func = clkbrd_led_blink;
119 	sc->sc_blink.bl_arg = sc;
120 	blink_led_register(&sc->sc_blink);
121 
122 	/* Initialize sensor data. */
123 	strlcpy(sc->sc_sensordev.xname, sc->sc_dv.dv_xname,
124 	    sizeof(sc->sc_sensordev.xname));
125 	sc->sc_sensor.type = SENSOR_TEMP;
126 
127 	sensor_attach(&sc->sc_sensordev, &sc->sc_sensor);
128 
129 	if (sensor_task_register(sc, clkbrd_refresh, 5) == NULL) {
130 		printf(": unable to register update task\n");
131 		return;
132 	}
133 
134 	sensordev_install(&sc->sc_sensordev);
135 
136 	printf(": %d slots\n", slots);
137 }
138 
139 void
clkbrd_led_blink(void * vsc,int on)140 clkbrd_led_blink(void *vsc, int on)
141 {
142 	struct clkbrd_softc *sc = vsc;
143 	int s;
144 	u_int8_t r;
145 
146 	s = splhigh();
147 	r = bus_space_read_1(sc->sc_bt, sc->sc_creg, CLK_CTRL);
148 	if (on)
149 		r |= CLK_CTRL_RLED;
150 	else
151 		r &= ~CLK_CTRL_RLED;
152 	bus_space_write_1(sc->sc_bt, sc->sc_creg, CLK_CTRL, r);
153 	bus_space_read_1(sc->sc_bt, sc->sc_creg, CLK_CTRL);
154 	splx(s);
155 }
156 
157 /*
158  * Calibration table for temperature sensor.
159  */
160 int8_t clkbrd_temp[] = {
161 	 0,  0,  0,  0,  0,  0,  0,  0,
162 	 0,  0,  0,  0,  1,  2,  4,  5,
163 	 7,  8, 10, 11, 12, 13, 14, 15,
164 	17, 18, 19, 20, 21, 22, 23, 24,
165 	24, 25, 26, 27, 28, 29, 29, 30,
166 	31, 32, 32, 33, 34, 35, 35, 36,
167 	37, 38, 38, 39, 40, 40, 41, 42,
168 	42, 43, 44, 44, 45, 46, 46, 47,
169 	48, 48, 49, 50, 50, 51, 52, 52,
170 	53, 54, 54, 55, 56, 57, 57, 58,
171 	59, 59, 60, 60, 61, 62, 63, 63,
172 	64, 65, 65, 66, 67, 68, 68, 69,
173 	70, 70, 71, 72, 73, 74, 74, 75,
174 	76, 77, 78, 78, 79, 80, 81, 82
175 };
176 
177 const int8_t clkbrd_temp_warn = 60;
178 const int8_t clkbrd_temp_crit = 68;
179 
180 void
clkbrd_refresh(void * arg)181 clkbrd_refresh(void *arg)
182 {
183 	struct clkbrd_softc *sc = arg;
184 	u_int8_t val;
185 	int8_t temp;
186 
187 	val = bus_space_read_1(sc->sc_bt, sc->sc_creg, CLK_TEMP);
188 	if (val == 0xff) {
189 		sc->sc_sensor.flags |= SENSOR_FINVALID;
190 		return;
191 	}
192 
193 	if (val < sizeof(clkbrd_temp))
194 		temp = clkbrd_temp[val];
195 	else
196 		temp = clkbrd_temp[sizeof(clkbrd_temp) - 1];
197 
198 	sc->sc_sensor.value = val * 1000000 + 273150000;
199 	sc->sc_sensor.flags &= ~SENSOR_FINVALID;
200 	sc->sc_sensor.status = SENSOR_S_OK;
201 	if (temp >= clkbrd_temp_warn)
202 		sc->sc_sensor.status = SENSOR_S_WARN;
203 	if (temp >= clkbrd_temp_crit)
204 		sc->sc_sensor.status = SENSOR_S_CRIT;
205 }
206