This source file includes following definitions.
- admtemp_match
- admtemp_attach
- admtemp_refresh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
27 #define ADM1021_INT_TEMP 0x00
28 #define ADM1021_EXT_TEMP 0x01
29 #define ADM1021_STATUS 0x02
30 #define ADM1021_STATUS_INVAL 0x7f
31 #define ADM1021_STATUS_NOEXT 0x40
32 #define ADM1021_CONFIG_READ 0x03
33 #define ADM1021_CONFIG_WRITE 0x09
34 #define ADM1021_CONFIG_RUN 0x40
35 #define ADM1021_COMPANY 0xfe
36 #define ADM1021_STEPPING 0xff
37
38
39 #define ADMTEMP_EXT 0
40 #define ADMTEMP_INT 1
41 #define ADMTEMP_NUM_SENSORS 2
42
43 struct admtemp_softc {
44 struct device sc_dev;
45 i2c_tag_t sc_tag;
46 i2c_addr_t sc_addr;
47
48 struct ksensor sc_sensor[ADMTEMP_NUM_SENSORS];
49 struct ksensordev sc_sensordev;
50 int sc_noexternal;
51 };
52
53 int admtemp_match(struct device *, void *, void *);
54 void admtemp_attach(struct device *, struct device *, void *);
55 void admtemp_refresh(void *);
56
57 struct cfattach admtemp_ca = {
58 sizeof(struct admtemp_softc), admtemp_match, admtemp_attach
59 };
60
61 struct cfdriver admtemp_cd = {
62 NULL, "admtemp", DV_DULL
63 };
64
65 int
66 admtemp_match(struct device *parent, void *match, void *aux)
67 {
68 struct i2c_attach_args *ia = aux;
69
70 if (strcmp(ia->ia_name, "adm1021") == 0 ||
71 strcmp(ia->ia_name, "adm1023") == 0 ||
72 strcmp(ia->ia_name, "adm1032") == 0 ||
73 strcmp(ia->ia_name, "g781") == 0 ||
74 strcmp(ia->ia_name, "g781-1") == 0 ||
75 strcmp(ia->ia_name, "gl523sm") == 0 ||
76 strcmp(ia->ia_name, "max1617") == 0 ||
77 strcmp(ia->ia_name, "xeontemp") == 0)
78 return (1);
79 return (0);
80 }
81
82 void
83 admtemp_attach(struct device *parent, struct device *self, void *aux)
84 {
85 struct admtemp_softc *sc = (struct admtemp_softc *)self;
86 struct i2c_attach_args *ia = aux;
87 u_int8_t cmd, data, stat;
88 int xeon = 0, i;
89
90 sc->sc_tag = ia->ia_tag;
91 sc->sc_addr = ia->ia_addr;
92
93 if (strcmp(ia->ia_name, "xeontemp") == 0) {
94 printf(": Xeon");
95 xeon = 1;
96 } else
97 printf(": %s", ia->ia_name);
98
99 iic_acquire_bus(sc->sc_tag, 0);
100 cmd = ADM1021_CONFIG_READ;
101 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
102 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
103 iic_release_bus(sc->sc_tag, 0);
104 printf(", cannot get control register\n");
105 return;
106 }
107 if (data & ADM1021_CONFIG_RUN) {
108 cmd = ADM1021_STATUS;
109 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
110 sc->sc_addr, &cmd, sizeof cmd, &stat, sizeof stat, 0)) {
111 iic_release_bus(sc->sc_tag, 0);
112 printf(", cannot read status register\n");
113 return;
114 }
115 if ((stat & ADM1021_STATUS_INVAL) == ADM1021_STATUS_INVAL) {
116 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
117 sc->sc_addr, &cmd, sizeof cmd, &stat, sizeof stat, 0)) {
118 iic_release_bus(sc->sc_tag, 0);
119 printf(", cannot read status register\n");
120 return;
121 }
122 }
123
124
125 if ((stat & ADM1021_STATUS_INVAL) != ADM1021_STATUS_INVAL &&
126 (stat & ADM1021_STATUS_NOEXT))
127 sc->sc_noexternal = 1;
128
129 data &= ~ADM1021_CONFIG_RUN;
130 cmd = ADM1021_CONFIG_WRITE;
131 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
132 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
133 iic_release_bus(sc->sc_tag, 0);
134 printf(", cannot set control register\n");
135 return;
136 }
137 }
138 iic_release_bus(sc->sc_tag, 0);
139
140
141 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
142 sizeof(sc->sc_sensordev.xname));
143
144 sc->sc_sensor[ADMTEMP_EXT].type = SENSOR_TEMP;
145 strlcpy(sc->sc_sensor[ADMTEMP_EXT].desc,
146 xeon ? "Xeon" : "External",
147 sizeof(sc->sc_sensor[ADMTEMP_EXT].desc));
148
149 sc->sc_sensor[ADMTEMP_INT].type = SENSOR_TEMP;
150 strlcpy(sc->sc_sensor[ADMTEMP_INT].desc,
151 xeon ? "Xeon" : "Internal",
152 sizeof(sc->sc_sensor[ADMTEMP_INT].desc));
153
154 if (sensor_task_register(sc, admtemp_refresh, 5) == NULL) {
155 printf(", unable to register update task\n");
156 return;
157 }
158
159 for (i = 0; i < (sc->sc_noexternal ? 1 : ADMTEMP_NUM_SENSORS); i++)
160 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
161 sensordev_install(&sc->sc_sensordev);
162
163 printf("\n");
164 }
165
166 void
167 admtemp_refresh(void *arg)
168 {
169 struct admtemp_softc *sc = arg;
170 u_int8_t cmd;
171 int8_t sdata;
172
173 iic_acquire_bus(sc->sc_tag, 0);
174
175 if (sc->sc_noexternal == 0) {
176 cmd = ADM1021_EXT_TEMP;
177 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
178 &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0) {
179 if (sdata == 0x7f) {
180 sc->sc_sensor[ADMTEMP_EXT].flags |= SENSOR_FINVALID;
181 } else {
182 sc->sc_sensor[ADMTEMP_EXT].value =
183 273150000 + 1000000 * sdata;
184 sc->sc_sensor[ADMTEMP_EXT].flags &= ~SENSOR_FINVALID;
185 }
186 }
187 } else
188 sc->sc_sensor[ADMTEMP_EXT].flags |= SENSOR_FINVALID;
189
190
191 cmd = ADM1021_INT_TEMP;
192 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
193 &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0) {
194 if (sdata == 0x7f) {
195 sc->sc_sensor[ADMTEMP_INT].flags |= SENSOR_FINVALID;
196 } else {
197 sc->sc_sensor[ADMTEMP_INT].value =
198 273150000 + 1000000 * sdata;
199 sc->sc_sensor[ADMTEMP_INT].flags &= ~SENSOR_FINVALID;
200 }
201 }
202
203 iic_release_bus(sc->sc_tag, 0);
204 }