Line data Source code
1 : /* $OpenBSD: adm1031.c,v 1.8 2007/06/24 05:34:35 dlg Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2005 Theo de Raadt
5 : *
6 : * Permission to use, copy, modify, and distribute this software for any
7 : * purpose with or without fee is hereby granted, provided that the above
8 : * copyright notice and this permission notice appear in all copies.
9 : *
10 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 : */
18 :
19 : #include <sys/param.h>
20 : #include <sys/systm.h>
21 : #include <sys/device.h>
22 : #include <sys/sensors.h>
23 :
24 : #include <dev/i2c/i2cvar.h>
25 :
26 : /* adm 1031 registers */
27 : #define ADM1031_INT_TEMP 0x0a
28 : #define ADM1031_EXT_TEMP 0x0b
29 : #define ADM1031_EXT2_TEMP 0x0c
30 : #define ADM1031_FAN 0x08
31 : #define ADM1031_FANC 0x20
32 : #define ADM1031_FAN2 0x09
33 : #define ADM1031_FAN2C 0x21
34 : #define ADM1024_FANC_VAL(x) (x >> 6)
35 :
36 : /* Sensors */
37 : #define ADMTT_INT 0
38 : #define ADMTT_EXT 1
39 : #define ADMTT_EXT2 2
40 : #define ADMTT_FAN 3
41 : #define ADMTT_FAN2 4
42 : #define ADMTT_NUM_SENSORS 5
43 :
44 : struct admtt_softc {
45 : struct device sc_dev;
46 : i2c_tag_t sc_tag;
47 : i2c_addr_t sc_addr;
48 : int sc_fanmul;
49 :
50 : struct ksensor sc_sensor[ADMTT_NUM_SENSORS];
51 : struct ksensordev sc_sensordev;
52 : };
53 :
54 : int admtt_match(struct device *, void *, void *);
55 : void admtt_attach(struct device *, struct device *, void *);
56 : void admtt_refresh(void *);
57 :
58 : struct cfattach admtt_ca = {
59 : sizeof(struct admtt_softc), admtt_match, admtt_attach
60 : };
61 :
62 : struct cfdriver admtt_cd = {
63 : NULL, "admtt", DV_DULL
64 : };
65 :
66 : int
67 0 : admtt_match(struct device *parent, void *match, void *aux)
68 : {
69 0 : struct i2c_attach_args *ia = aux;
70 :
71 0 : if (strcmp(ia->ia_name, "adm1031") == 0)
72 0 : return (1);
73 0 : return (0);
74 0 : }
75 :
76 : void
77 0 : admtt_attach(struct device *parent, struct device *self, void *aux)
78 : {
79 0 : struct admtt_softc *sc = (struct admtt_softc *)self;
80 0 : struct i2c_attach_args *ia = aux;
81 0 : u_int8_t cmd, data;
82 : int i;
83 :
84 0 : sc->sc_tag = ia->ia_tag;
85 0 : sc->sc_addr = ia->ia_addr;
86 :
87 0 : cmd = ADM1031_FANC;
88 0 : if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
89 0 : sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
90 0 : printf(", unable to read fan setting\n");
91 0 : return;
92 : }
93 0 : sc->sc_fanmul = 11250/8 * (1 << ADM1024_FANC_VAL(data)) * 60;
94 :
95 : /* Initialize sensor data. */
96 0 : strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
97 : sizeof(sc->sc_sensordev.xname));
98 :
99 0 : sc->sc_sensor[ADMTT_INT].type = SENSOR_TEMP;
100 0 : strlcpy(sc->sc_sensor[ADMTT_INT].desc, "Internal",
101 : sizeof(sc->sc_sensor[ADMTT_INT].desc));
102 :
103 0 : sc->sc_sensor[ADMTT_EXT].type = SENSOR_TEMP;
104 0 : strlcpy(sc->sc_sensor[ADMTT_EXT].desc, "External",
105 : sizeof(sc->sc_sensor[ADMTT_EXT].desc));
106 :
107 0 : sc->sc_sensor[ADMTT_EXT2].type = SENSOR_TEMP;
108 0 : strlcpy(sc->sc_sensor[ADMTT_EXT2].desc, "External",
109 : sizeof(sc->sc_sensor[ADMTT_EXT2].desc));
110 :
111 0 : sc->sc_sensor[ADMTT_FAN].type = SENSOR_FANRPM;
112 :
113 0 : sc->sc_sensor[ADMTT_FAN2].type = SENSOR_FANRPM;
114 :
115 0 : if (sensor_task_register(sc, admtt_refresh, 5) == NULL) {
116 0 : printf(", unable to register update task\n");
117 0 : return;
118 : }
119 :
120 0 : for (i = 0; i < ADMTT_NUM_SENSORS; i++)
121 0 : sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
122 0 : sensordev_install(&sc->sc_sensordev);
123 :
124 0 : printf("\n");
125 0 : }
126 :
127 : void
128 0 : admtt_refresh(void *arg)
129 : {
130 0 : struct admtt_softc *sc = arg;
131 0 : u_int8_t cmd, data;
132 :
133 0 : iic_acquire_bus(sc->sc_tag, 0);
134 :
135 0 : cmd = ADM1031_INT_TEMP;
136 0 : if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
137 0 : sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
138 0 : sc->sc_sensor[ADMTT_INT].value = 273150000 + 1000000 * data;
139 :
140 0 : cmd = ADM1031_EXT_TEMP;
141 0 : if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
142 0 : sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
143 0 : sc->sc_sensor[ADMTT_EXT].value = 273150000 + 1000000 * data;
144 :
145 0 : cmd = ADM1031_EXT2_TEMP;
146 0 : if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
147 0 : sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
148 0 : sc->sc_sensor[ADMTT_EXT2].value = 273150000 + 1000000 * data;
149 :
150 0 : cmd = ADM1031_FAN;
151 0 : if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
152 0 : sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) {
153 0 : if (data == 0)
154 0 : sc->sc_sensor[ADMTT_FAN].flags |= SENSOR_FINVALID;
155 : else {
156 0 : sc->sc_sensor[ADMTT_FAN].value =
157 0 : sc->sc_fanmul / (2 * (int)data);
158 0 : sc->sc_sensor[ADMTT_FAN].flags &= ~SENSOR_FINVALID;
159 : }
160 : }
161 :
162 0 : cmd = ADM1031_FAN2;
163 0 : if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
164 0 : sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) {
165 0 : if (data == 0)
166 0 : sc->sc_sensor[ADMTT_FAN2].flags |= SENSOR_FINVALID;
167 : else {
168 0 : sc->sc_sensor[ADMTT_FAN2].value =
169 0 : sc->sc_fanmul / (2 * (int)data);
170 0 : sc->sc_sensor[ADMTT_FAN2].flags &= ~SENSOR_FINVALID;
171 : }
172 : }
173 :
174 0 : iic_release_bus(sc->sc_tag, 0);
175 0 : }
|