dbcool.c revision 1.33 1 1.33 pgoyette /* $NetBSD: dbcool.c,v 1.33 2011/08/02 14:06:15 pgoyette Exp $ */
2 1.1 pgoyette
3 1.1 pgoyette /*-
4 1.1 pgoyette * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 1.1 pgoyette * All rights reserved.
6 1.1 pgoyette *
7 1.1 pgoyette * This code is derived from software contributed to The NetBSD Foundation
8 1.1 pgoyette * by Paul Goyette
9 1.1 pgoyette *
10 1.1 pgoyette * Redistribution and use in source and binary forms, with or without
11 1.1 pgoyette * modification, are permitted provided that the following conditions
12 1.1 pgoyette * are met:
13 1.1 pgoyette * 1. Redistributions of source code must retain the above copyright
14 1.1 pgoyette * notice, this list of conditions and the following disclaimer.
15 1.1 pgoyette * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 pgoyette * notice, this list of conditions and the following disclaimer in the
17 1.1 pgoyette * documentation and/or other materials provided with the distribution.
18 1.1 pgoyette *
19 1.1 pgoyette * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 pgoyette * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 pgoyette * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 pgoyette * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 pgoyette * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 pgoyette * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 pgoyette * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 pgoyette * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 pgoyette * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 pgoyette * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 pgoyette * POSSIBILITY OF SUCH DAMAGE.
30 1.1 pgoyette */
31 1.1 pgoyette
32 1.1 pgoyette /*
33 1.1 pgoyette * a driver for the dbCool(tm) family of environmental controllers
34 1.1 pgoyette *
35 1.1 pgoyette * Data sheets for the various supported chips are available at
36 1.1 pgoyette *
37 1.1 pgoyette * http://www.onsemi.com/pub/Collateral/ADM1027-D.PDF
38 1.1 pgoyette * http://www.onsemi.com/pub/Collateral/ADM1030-D.PDF
39 1.1 pgoyette * http://www.onsemi.com/pub/Collateral/ADT7463-D.PDF
40 1.1 pgoyette * http://www.onsemi.com/pub/Collateral/ADT7466.PDF
41 1.1 pgoyette * http://www.onsemi.com/pub/Collateral/ADT7467-D.PDF
42 1.1 pgoyette * http://www.onsemi.com/pub/Collateral/ADT7468-D.PDF
43 1.1 pgoyette * http://www.onsemi.com/pub/Collateral/ADT7473-D.PDF
44 1.1 pgoyette * http://www.onsemi.com/pub/Collateral/ADT7475-D.PDF
45 1.1 pgoyette * http://www.onsemi.com/pub/Collateral/ADT7476-D.PDF
46 1.2 pgoyette * http://www.onsemi.com/pub/Collateral/ADT7490-D.PDF
47 1.27 pgoyette * http://www.smsc.com/media/Downloads_Public/Data_Sheets/6d103s.pdf
48 1.1 pgoyette *
49 1.2 pgoyette * (URLs are correct as of October 5, 2008)
50 1.1 pgoyette */
51 1.1 pgoyette
52 1.1 pgoyette #include <sys/cdefs.h>
53 1.33 pgoyette __KERNEL_RCSID(0, "$NetBSD: dbcool.c,v 1.33 2011/08/02 14:06:15 pgoyette Exp $");
54 1.1 pgoyette
55 1.1 pgoyette #include <sys/param.h>
56 1.1 pgoyette #include <sys/systm.h>
57 1.1 pgoyette #include <sys/kernel.h>
58 1.1 pgoyette #include <sys/device.h>
59 1.1 pgoyette #include <sys/malloc.h>
60 1.1 pgoyette #include <sys/sysctl.h>
61 1.31 jmcneill #include <sys/module.h>
62 1.1 pgoyette
63 1.1 pgoyette #include <dev/i2c/dbcool_var.h>
64 1.1 pgoyette #include <dev/i2c/dbcool_reg.h>
65 1.1 pgoyette
66 1.1 pgoyette /* Config interface */
67 1.1 pgoyette static int dbcool_match(device_t, cfdata_t, void *);
68 1.1 pgoyette static void dbcool_attach(device_t, device_t, void *);
69 1.1 pgoyette static int dbcool_detach(device_t, int);
70 1.1 pgoyette
71 1.1 pgoyette /* Device attributes */
72 1.1 pgoyette static int dbcool_supply_voltage(struct dbcool_softc *);
73 1.2 pgoyette static bool dbcool_islocked(struct dbcool_softc *);
74 1.1 pgoyette
75 1.1 pgoyette /* Sensor read functions */
76 1.1 pgoyette static void dbcool_refresh(struct sysmon_envsys *, envsys_data_t *);
77 1.1 pgoyette static int dbcool_read_rpm(struct dbcool_softc *, uint8_t);
78 1.1 pgoyette static int dbcool_read_temp(struct dbcool_softc *, uint8_t, bool);
79 1.2 pgoyette static int dbcool_read_volt(struct dbcool_softc *, uint8_t, int, bool);
80 1.1 pgoyette
81 1.18 pgoyette /* Sensor get/set limit functions */
82 1.18 pgoyette static void dbcool_get_limits(struct sysmon_envsys *, envsys_data_t *,
83 1.18 pgoyette sysmon_envsys_lim_t *, uint32_t *);
84 1.18 pgoyette static void dbcool_get_temp_limits(struct dbcool_softc *, int,
85 1.18 pgoyette sysmon_envsys_lim_t *, uint32_t *);
86 1.18 pgoyette static void dbcool_get_volt_limits(struct dbcool_softc *, int,
87 1.18 pgoyette sysmon_envsys_lim_t *, uint32_t *);
88 1.18 pgoyette static void dbcool_get_fan_limits(struct dbcool_softc *, int,
89 1.18 pgoyette sysmon_envsys_lim_t *, uint32_t *);
90 1.18 pgoyette
91 1.18 pgoyette static void dbcool_set_limits(struct sysmon_envsys *, envsys_data_t *,
92 1.18 pgoyette sysmon_envsys_lim_t *, uint32_t *);
93 1.18 pgoyette static void dbcool_set_temp_limits(struct dbcool_softc *, int,
94 1.18 pgoyette sysmon_envsys_lim_t *, uint32_t *);
95 1.18 pgoyette static void dbcool_set_volt_limits(struct dbcool_softc *, int,
96 1.18 pgoyette sysmon_envsys_lim_t *, uint32_t *);
97 1.18 pgoyette static void dbcool_set_fan_limits(struct dbcool_softc *, int,
98 1.18 pgoyette sysmon_envsys_lim_t *, uint32_t *);
99 1.18 pgoyette
100 1.1 pgoyette /* SYSCTL Helpers */
101 1.33 pgoyette SYSCTL_SETUP_PROTO(sysctl_dbcoolsetup);
102 1.2 pgoyette static int sysctl_dbcool_temp(SYSCTLFN_PROTO);
103 1.2 pgoyette static int sysctl_adm1030_temp(SYSCTLFN_PROTO);
104 1.1 pgoyette static int sysctl_adm1030_trange(SYSCTLFN_PROTO);
105 1.1 pgoyette static int sysctl_dbcool_duty(SYSCTLFN_PROTO);
106 1.1 pgoyette static int sysctl_dbcool_behavior(SYSCTLFN_PROTO);
107 1.2 pgoyette static int sysctl_dbcool_slope(SYSCTLFN_PROTO);
108 1.1 pgoyette static int sysctl_dbcool_thyst(SYSCTLFN_PROTO);
109 1.1 pgoyette
110 1.2 pgoyette /* Set-up subroutines */
111 1.18 pgoyette static void dbcool_setup_controllers(struct dbcool_softc *);
112 1.18 pgoyette static int dbcool_setup_sensors(struct dbcool_softc *);
113 1.18 pgoyette static int dbcool_attach_sensor(struct dbcool_softc *, int);
114 1.18 pgoyette static int dbcool_attach_temp_control(struct dbcool_softc *, int,
115 1.18 pgoyette struct chip_id *);
116 1.2 pgoyette
117 1.1 pgoyette #ifdef DBCOOL_DEBUG
118 1.1 pgoyette static int sysctl_dbcool_reg_select(SYSCTLFN_PROTO);
119 1.1 pgoyette static int sysctl_dbcool_reg_access(SYSCTLFN_PROTO);
120 1.1 pgoyette #endif /* DBCOOL_DEBUG */
121 1.1 pgoyette
122 1.1 pgoyette /*
123 1.1 pgoyette * Descriptions for SYSCTL entries
124 1.1 pgoyette */
125 1.2 pgoyette struct dbc_sysctl_info {
126 1.1 pgoyette const char *name;
127 1.1 pgoyette const char *desc;
128 1.2 pgoyette bool lockable;
129 1.1 pgoyette int (*helper)(SYSCTLFN_PROTO);
130 1.1 pgoyette };
131 1.1 pgoyette
132 1.2 pgoyette static struct dbc_sysctl_info dbc_sysctl_table[] = {
133 1.2 pgoyette /*
134 1.2 pgoyette * The first several entries must remain in the same order as the
135 1.2 pgoyette * corresponding entries in enum dbc_pwm_params
136 1.2 pgoyette */
137 1.1 pgoyette { "behavior", "operating behavior and temp selector",
138 1.2 pgoyette true, sysctl_dbcool_behavior },
139 1.1 pgoyette { "min_duty", "minimum fan controller PWM duty cycle",
140 1.2 pgoyette true, sysctl_dbcool_duty },
141 1.1 pgoyette { "max_duty", "maximum fan controller PWM duty cycle",
142 1.2 pgoyette true, sysctl_dbcool_duty },
143 1.1 pgoyette { "cur_duty", "current fan controller PWM duty cycle",
144 1.2 pgoyette false, sysctl_dbcool_duty },
145 1.2 pgoyette
146 1.2 pgoyette /*
147 1.2 pgoyette * The rest of these should be in the order in which they
148 1.2 pgoyette * are to be stored in the sysctl tree; the table index is
149 1.2 pgoyette * used as the high-order bits of the sysctl_num to maintain
150 1.2 pgoyette * the sequence.
151 1.2 pgoyette *
152 1.2 pgoyette * If you rearrange the order of these items, be sure to
153 1.2 pgoyette * update the sysctl_index in the XXX_sensor_table[] for
154 1.2 pgoyette * the various chips!
155 1.2 pgoyette */
156 1.2 pgoyette { "Trange", "temp slope/range to reach 100% duty cycle",
157 1.2 pgoyette true, sysctl_dbcool_slope },
158 1.1 pgoyette { "Tmin", "temp at which to start fan controller",
159 1.2 pgoyette true, sysctl_dbcool_temp },
160 1.1 pgoyette { "Ttherm", "temp at which THERM is asserted",
161 1.2 pgoyette true, sysctl_dbcool_temp },
162 1.1 pgoyette { "Thyst", "temp hysteresis for stopping fan controller",
163 1.2 pgoyette true, sysctl_dbcool_thyst },
164 1.1 pgoyette { "Tmin", "temp at which to start fan controller",
165 1.2 pgoyette true, sysctl_adm1030_temp },
166 1.2 pgoyette { "Trange", "temp slope/range to reach 100% duty cycle",
167 1.2 pgoyette true, sysctl_adm1030_trange },
168 1.1 pgoyette };
169 1.1 pgoyette
170 1.1 pgoyette static const char *dbc_sensor_names[] = {
171 1.2 pgoyette "l_temp", "r1_temp", "r2_temp", "Vccp", "Vcc", "fan1",
172 1.4 pgoyette "fan2", "fan3", "fan4", "AIN1", "AIN2", "V2dot5",
173 1.16 pgoyette "V5", "V12", "Vtt", "Imon", "VID"
174 1.2 pgoyette };
175 1.2 pgoyette
176 1.2 pgoyette /*
177 1.2 pgoyette * Following table derived from product data-sheets
178 1.2 pgoyette */
179 1.2 pgoyette static int64_t nominal_voltages[] = {
180 1.2 pgoyette -1, /* Vcc can be either 3.3 or 5.0V
181 1.2 pgoyette at 3/4 scale */
182 1.3 pgoyette 2249939, /* Vccp 2.25V 3/4 scale */
183 1.3 pgoyette 2497436, /* 2.5VIN 2.5V 3/4 scale */
184 1.3 pgoyette 5002466, /* 5VIN 5V 3/4 scale */
185 1.2 pgoyette 12000000, /* 12VIN 12V 3/4 scale */
186 1.3 pgoyette 1690809, /* Vtt, Imon 2.25V full scale */
187 1.3 pgoyette 1689600, /* AIN1, AIN2 2.25V full scale */
188 1.3 pgoyette 0
189 1.2 pgoyette };
190 1.2 pgoyette
191 1.2 pgoyette /*
192 1.2 pgoyette * Sensor-type, { val-reg, hilim-reg, lolim-reg}, name-idx, sysctl-table-idx,
193 1.2 pgoyette * nom-voltage-index
194 1.2 pgoyette */
195 1.2 pgoyette struct dbcool_sensor ADT7490_sensor_table[] = {
196 1.2 pgoyette { DBC_TEMP, { DBCOOL_LOCAL_TEMP,
197 1.2 pgoyette DBCOOL_LOCAL_HIGHLIM,
198 1.2 pgoyette DBCOOL_LOCAL_LOWLIM }, 0, 0, 0 },
199 1.2 pgoyette { DBC_TEMP, { DBCOOL_REMOTE1_TEMP,
200 1.2 pgoyette DBCOOL_REMOTE1_HIGHLIM,
201 1.2 pgoyette DBCOOL_REMOTE1_LOWLIM }, 1, 0, 0 },
202 1.2 pgoyette { DBC_TEMP, { DBCOOL_REMOTE2_TEMP,
203 1.2 pgoyette DBCOOL_REMOTE2_HIGHLIM,
204 1.2 pgoyette DBCOOL_REMOTE2_LOWLIM }, 2, 0, 0 },
205 1.2 pgoyette { DBC_VOLT, { DBCOOL_VCCP,
206 1.2 pgoyette DBCOOL_VCCP_HIGHLIM,
207 1.2 pgoyette DBCOOL_VCCP_LOWLIM }, 3, 0, 1 },
208 1.2 pgoyette { DBC_VOLT, { DBCOOL_VCC,
209 1.2 pgoyette DBCOOL_VCC_HIGHLIM,
210 1.2 pgoyette DBCOOL_VCC_LOWLIM }, 4, 0, 0 },
211 1.2 pgoyette { DBC_VOLT, { DBCOOL_25VIN,
212 1.2 pgoyette DBCOOL_25VIN_HIGHLIM,
213 1.2 pgoyette DBCOOL_25VIN_LOWLIM }, 11, 0, 2 },
214 1.2 pgoyette { DBC_VOLT, { DBCOOL_5VIN,
215 1.2 pgoyette DBCOOL_5VIN_HIGHLIM,
216 1.2 pgoyette DBCOOL_5VIN_LOWLIM }, 12, 0, 3 },
217 1.2 pgoyette { DBC_VOLT, { DBCOOL_12VIN,
218 1.2 pgoyette DBCOOL_12VIN_HIGHLIM,
219 1.2 pgoyette DBCOOL_12VIN_LOWLIM }, 13, 0, 4 },
220 1.2 pgoyette { DBC_VOLT, { DBCOOL_VTT,
221 1.2 pgoyette DBCOOL_VTT_HIGHLIM,
222 1.2 pgoyette DBCOOL_VTT_LOWLIM }, 14, 0, 5 },
223 1.2 pgoyette { DBC_VOLT, { DBCOOL_IMON,
224 1.2 pgoyette DBCOOL_IMON_HIGHLIM,
225 1.2 pgoyette DBCOOL_IMON_LOWLIM }, 15, 0, 5 },
226 1.2 pgoyette { DBC_FAN, { DBCOOL_FAN1_TACH_LSB,
227 1.2 pgoyette DBCOOL_NO_REG,
228 1.2 pgoyette DBCOOL_TACH1_MIN_LSB }, 5, 0, 0 },
229 1.2 pgoyette { DBC_FAN, { DBCOOL_FAN2_TACH_LSB,
230 1.2 pgoyette DBCOOL_NO_REG,
231 1.2 pgoyette DBCOOL_TACH2_MIN_LSB }, 6, 0, 0 },
232 1.2 pgoyette { DBC_FAN, { DBCOOL_FAN3_TACH_LSB,
233 1.2 pgoyette DBCOOL_NO_REG,
234 1.2 pgoyette DBCOOL_TACH3_MIN_LSB }, 7, 0, 0 },
235 1.2 pgoyette { DBC_FAN, { DBCOOL_FAN4_TACH_LSB,
236 1.2 pgoyette DBCOOL_NO_REG,
237 1.2 pgoyette DBCOOL_TACH4_MIN_LSB }, 8, 0, 0 },
238 1.16 pgoyette { DBC_VID, { DBCOOL_VID_REG,
239 1.16 pgoyette DBCOOL_NO_REG,
240 1.16 pgoyette DBCOOL_NO_REG }, 16, 0, 0 },
241 1.2 pgoyette { DBC_CTL, { DBCOOL_LOCAL_TMIN,
242 1.2 pgoyette DBCOOL_NO_REG,
243 1.2 pgoyette DBCOOL_NO_REG }, 0, 5, 0 },
244 1.2 pgoyette { DBC_CTL, { DBCOOL_LOCAL_TTHRESH,
245 1.2 pgoyette DBCOOL_NO_REG,
246 1.2 pgoyette DBCOOL_NO_REG }, 0, 6, 0 },
247 1.2 pgoyette { DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST | 0x80,
248 1.2 pgoyette DBCOOL_NO_REG,
249 1.2 pgoyette DBCOOL_NO_REG }, 0, 7, 0 },
250 1.2 pgoyette { DBC_CTL, { DBCOOL_REMOTE1_TMIN,
251 1.2 pgoyette DBCOOL_NO_REG,
252 1.2 pgoyette DBCOOL_NO_REG }, 1, 5, 0 },
253 1.2 pgoyette { DBC_CTL, { DBCOOL_REMOTE1_TTHRESH,
254 1.2 pgoyette DBCOOL_NO_REG,
255 1.2 pgoyette DBCOOL_NO_REG }, 1, 6, 0 },
256 1.2 pgoyette { DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST,
257 1.2 pgoyette DBCOOL_NO_REG,
258 1.2 pgoyette DBCOOL_NO_REG }, 1, 7, 0 },
259 1.2 pgoyette { DBC_CTL, { DBCOOL_REMOTE2_TMIN,
260 1.2 pgoyette DBCOOL_NO_REG,
261 1.2 pgoyette DBCOOL_NO_REG }, 2, 5, 0 },
262 1.2 pgoyette { DBC_CTL, { DBCOOL_REMOTE2_TTHRESH,
263 1.2 pgoyette DBCOOL_NO_REG,
264 1.2 pgoyette DBCOOL_NO_REG }, 2, 6, 0 },
265 1.2 pgoyette { DBC_CTL, { DBCOOL_R2_TMIN_HYST,
266 1.2 pgoyette DBCOOL_NO_REG,
267 1.2 pgoyette DBCOOL_NO_REG }, 2, 7, 0 },
268 1.2 pgoyette { DBC_EOF, { 0, 0, 0 }, 0, 0, 0 }
269 1.2 pgoyette };
270 1.2 pgoyette
271 1.2 pgoyette struct dbcool_sensor ADT7476_sensor_table[] = {
272 1.2 pgoyette { DBC_TEMP, { DBCOOL_LOCAL_TEMP,
273 1.2 pgoyette DBCOOL_LOCAL_HIGHLIM,
274 1.2 pgoyette DBCOOL_LOCAL_LOWLIM }, 0, 0, 0 },
275 1.2 pgoyette { DBC_TEMP, { DBCOOL_REMOTE1_TEMP,
276 1.2 pgoyette DBCOOL_REMOTE1_HIGHLIM,
277 1.2 pgoyette DBCOOL_REMOTE1_LOWLIM }, 1, 0, 0 },
278 1.2 pgoyette { DBC_TEMP, { DBCOOL_REMOTE2_TEMP,
279 1.2 pgoyette DBCOOL_REMOTE2_HIGHLIM,
280 1.2 pgoyette DBCOOL_REMOTE2_LOWLIM }, 2, 0, 0 },
281 1.2 pgoyette { DBC_VOLT, { DBCOOL_VCCP,
282 1.2 pgoyette DBCOOL_VCCP_HIGHLIM,
283 1.2 pgoyette DBCOOL_VCCP_LOWLIM }, 3, 0, 1 },
284 1.2 pgoyette { DBC_VOLT, { DBCOOL_VCC,
285 1.2 pgoyette DBCOOL_VCC_HIGHLIM,
286 1.2 pgoyette DBCOOL_VCC_LOWLIM }, 4, 0, 0 },
287 1.2 pgoyette { DBC_VOLT, { DBCOOL_25VIN,
288 1.2 pgoyette DBCOOL_25VIN_HIGHLIM,
289 1.2 pgoyette DBCOOL_25VIN_LOWLIM }, 11, 0, 2 },
290 1.2 pgoyette { DBC_VOLT, { DBCOOL_5VIN,
291 1.2 pgoyette DBCOOL_5VIN_HIGHLIM,
292 1.2 pgoyette DBCOOL_5VIN_LOWLIM }, 12, 0, 3 },
293 1.2 pgoyette { DBC_VOLT, { DBCOOL_12VIN,
294 1.2 pgoyette DBCOOL_12VIN_HIGHLIM,
295 1.2 pgoyette DBCOOL_12VIN_LOWLIM }, 13, 0, 4 },
296 1.2 pgoyette { DBC_FAN, { DBCOOL_FAN1_TACH_LSB,
297 1.2 pgoyette DBCOOL_NO_REG,
298 1.2 pgoyette DBCOOL_TACH1_MIN_LSB }, 5, 0, 0 },
299 1.2 pgoyette { DBC_FAN, { DBCOOL_FAN2_TACH_LSB,
300 1.2 pgoyette DBCOOL_NO_REG,
301 1.2 pgoyette DBCOOL_TACH2_MIN_LSB }, 6, 0, 0 },
302 1.2 pgoyette { DBC_FAN, { DBCOOL_FAN3_TACH_LSB,
303 1.2 pgoyette DBCOOL_NO_REG,
304 1.2 pgoyette DBCOOL_TACH3_MIN_LSB }, 7, 0, 0 },
305 1.2 pgoyette { DBC_FAN, { DBCOOL_FAN4_TACH_LSB,
306 1.2 pgoyette DBCOOL_NO_REG,
307 1.2 pgoyette DBCOOL_TACH4_MIN_LSB }, 8, 0, 0 },
308 1.16 pgoyette { DBC_VID, { DBCOOL_VID_REG,
309 1.16 pgoyette DBCOOL_NO_REG,
310 1.16 pgoyette DBCOOL_NO_REG }, 16, 0, 0 },
311 1.2 pgoyette { DBC_CTL, { DBCOOL_LOCAL_TMIN,
312 1.2 pgoyette DBCOOL_NO_REG,
313 1.2 pgoyette DBCOOL_NO_REG }, 0, 5, 0 },
314 1.2 pgoyette { DBC_CTL, { DBCOOL_LOCAL_TTHRESH,
315 1.2 pgoyette DBCOOL_NO_REG,
316 1.2 pgoyette DBCOOL_NO_REG }, 0, 6, 0 },
317 1.2 pgoyette { DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST | 0x80,
318 1.2 pgoyette DBCOOL_NO_REG,
319 1.2 pgoyette DBCOOL_NO_REG }, 0, 7, 0 },
320 1.2 pgoyette { DBC_CTL, { DBCOOL_REMOTE1_TMIN,
321 1.2 pgoyette DBCOOL_NO_REG,
322 1.2 pgoyette DBCOOL_NO_REG }, 1, 5, 0 },
323 1.2 pgoyette { DBC_CTL, { DBCOOL_REMOTE1_TTHRESH,
324 1.2 pgoyette DBCOOL_NO_REG,
325 1.2 pgoyette DBCOOL_NO_REG }, 1, 6, 0 },
326 1.2 pgoyette { DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST,
327 1.2 pgoyette DBCOOL_NO_REG,
328 1.2 pgoyette DBCOOL_NO_REG }, 1, 7, 0 },
329 1.2 pgoyette { DBC_CTL, { DBCOOL_REMOTE2_TMIN,
330 1.2 pgoyette DBCOOL_NO_REG,
331 1.2 pgoyette DBCOOL_NO_REG }, 2, 5, 0 },
332 1.2 pgoyette { DBC_CTL, { DBCOOL_REMOTE2_TTHRESH,
333 1.2 pgoyette DBCOOL_NO_REG,
334 1.2 pgoyette DBCOOL_NO_REG }, 2, 6, 0 },
335 1.2 pgoyette { DBC_CTL, { DBCOOL_R2_TMIN_HYST,
336 1.2 pgoyette DBCOOL_NO_REG,
337 1.2 pgoyette DBCOOL_NO_REG }, 2, 7, 0 },
338 1.2 pgoyette { DBC_EOF, { 0, 0, 0 }, 0, 0, 0 }
339 1.1 pgoyette };
340 1.1 pgoyette
341 1.1 pgoyette struct dbcool_sensor ADT7475_sensor_table[] = {
342 1.1 pgoyette { DBC_TEMP, { DBCOOL_LOCAL_TEMP,
343 1.1 pgoyette DBCOOL_LOCAL_HIGHLIM,
344 1.2 pgoyette DBCOOL_LOCAL_LOWLIM }, 0, 0, 0 },
345 1.1 pgoyette { DBC_TEMP, { DBCOOL_REMOTE1_TEMP,
346 1.1 pgoyette DBCOOL_REMOTE1_HIGHLIM,
347 1.2 pgoyette DBCOOL_REMOTE1_LOWLIM }, 1, 0, 0 },
348 1.1 pgoyette { DBC_TEMP, { DBCOOL_REMOTE2_TEMP,
349 1.1 pgoyette DBCOOL_REMOTE2_HIGHLIM,
350 1.2 pgoyette DBCOOL_REMOTE2_LOWLIM }, 2, 0, 0 },
351 1.2 pgoyette { DBC_VOLT, { DBCOOL_VCCP,
352 1.1 pgoyette DBCOOL_VCCP_HIGHLIM,
353 1.2 pgoyette DBCOOL_VCCP_LOWLIM }, 3, 0, 1 },
354 1.2 pgoyette { DBC_VOLT, { DBCOOL_VCC,
355 1.1 pgoyette DBCOOL_VCC_HIGHLIM,
356 1.2 pgoyette DBCOOL_VCC_LOWLIM }, 4, 0, 0 },
357 1.1 pgoyette { DBC_FAN, { DBCOOL_FAN1_TACH_LSB,
358 1.1 pgoyette DBCOOL_NO_REG,
359 1.2 pgoyette DBCOOL_TACH1_MIN_LSB }, 5, 0, 0 },
360 1.1 pgoyette { DBC_FAN, { DBCOOL_FAN2_TACH_LSB,
361 1.1 pgoyette DBCOOL_NO_REG,
362 1.2 pgoyette DBCOOL_TACH2_MIN_LSB }, 6, 0, 0 },
363 1.1 pgoyette { DBC_FAN, { DBCOOL_FAN3_TACH_LSB,
364 1.1 pgoyette DBCOOL_NO_REG,
365 1.2 pgoyette DBCOOL_TACH3_MIN_LSB }, 7, 0, 0 },
366 1.1 pgoyette { DBC_FAN, { DBCOOL_FAN4_TACH_LSB,
367 1.1 pgoyette DBCOOL_NO_REG,
368 1.2 pgoyette DBCOOL_TACH4_MIN_LSB }, 8, 0, 0 },
369 1.1 pgoyette { DBC_CTL, { DBCOOL_LOCAL_TMIN,
370 1.1 pgoyette DBCOOL_NO_REG,
371 1.2 pgoyette DBCOOL_NO_REG }, 0, 5, 0 },
372 1.1 pgoyette { DBC_CTL, { DBCOOL_LOCAL_TTHRESH,
373 1.1 pgoyette DBCOOL_NO_REG,
374 1.2 pgoyette DBCOOL_NO_REG }, 0, 6, 0 },
375 1.1 pgoyette { DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST | 0x80,
376 1.1 pgoyette DBCOOL_NO_REG,
377 1.2 pgoyette DBCOOL_NO_REG }, 0, 7, 0 },
378 1.1 pgoyette { DBC_CTL, { DBCOOL_REMOTE1_TMIN,
379 1.1 pgoyette DBCOOL_NO_REG,
380 1.2 pgoyette DBCOOL_NO_REG }, 1, 5, 0 },
381 1.1 pgoyette { DBC_CTL, { DBCOOL_REMOTE1_TTHRESH,
382 1.1 pgoyette DBCOOL_NO_REG,
383 1.2 pgoyette DBCOOL_NO_REG }, 1, 6, 0 },
384 1.1 pgoyette { DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST,
385 1.1 pgoyette DBCOOL_NO_REG,
386 1.2 pgoyette DBCOOL_NO_REG }, 1, 7, 0 },
387 1.1 pgoyette { DBC_CTL, { DBCOOL_REMOTE2_TMIN,
388 1.1 pgoyette DBCOOL_NO_REG,
389 1.2 pgoyette DBCOOL_NO_REG }, 2, 5, 0 },
390 1.1 pgoyette { DBC_CTL, { DBCOOL_REMOTE2_TTHRESH,
391 1.1 pgoyette DBCOOL_NO_REG,
392 1.2 pgoyette DBCOOL_NO_REG }, 2, 6, 0 },
393 1.1 pgoyette { DBC_CTL, { DBCOOL_R2_TMIN_HYST,
394 1.1 pgoyette DBCOOL_NO_REG,
395 1.2 pgoyette DBCOOL_NO_REG }, 2, 7, 0 },
396 1.2 pgoyette { DBC_EOF, { 0, 0, 0 }, 0, 0, 0 }
397 1.1 pgoyette };
398 1.1 pgoyette
399 1.1 pgoyette /*
400 1.2 pgoyette * The registers of dbcool_power_control must be in the same order as
401 1.1 pgoyette * in enum dbc_pwm_params
402 1.1 pgoyette */
403 1.1 pgoyette struct dbcool_power_control ADT7475_power_table[] = {
404 1.2 pgoyette { { DBCOOL_PWM1_CTL, DBCOOL_PWM1_MINDUTY,
405 1.2 pgoyette DBCOOL_PWM1_MAXDUTY, DBCOOL_PWM1_CURDUTY },
406 1.1 pgoyette "fan_control_1" },
407 1.2 pgoyette { { DBCOOL_PWM2_CTL, DBCOOL_PWM2_MINDUTY,
408 1.2 pgoyette DBCOOL_PWM2_MAXDUTY, DBCOOL_PWM2_CURDUTY },
409 1.1 pgoyette "fan_control_2" },
410 1.2 pgoyette { { DBCOOL_PWM3_CTL, DBCOOL_PWM3_MINDUTY,
411 1.2 pgoyette DBCOOL_PWM3_MAXDUTY, DBCOOL_PWM3_CURDUTY },
412 1.1 pgoyette "fan_control_3" },
413 1.2 pgoyette { { 0, 0, 0, 0 }, NULL }
414 1.1 pgoyette };
415 1.1 pgoyette
416 1.1 pgoyette struct dbcool_sensor ADT7466_sensor_table[] = {
417 1.1 pgoyette { DBC_TEMP, { DBCOOL_ADT7466_LCL_TEMP_MSB,
418 1.1 pgoyette DBCOOL_ADT7466_LCL_TEMP_HILIM,
419 1.2 pgoyette DBCOOL_ADT7466_LCL_TEMP_LOLIM }, 0, 0, 0 },
420 1.1 pgoyette { DBC_TEMP, { DBCOOL_ADT7466_REM_TEMP_MSB,
421 1.1 pgoyette DBCOOL_ADT7466_REM_TEMP_HILIM,
422 1.2 pgoyette DBCOOL_ADT7466_REM_TEMP_LOLIM }, 1, 0, 0 },
423 1.1 pgoyette { DBC_VOLT, { DBCOOL_ADT7466_VCC,
424 1.1 pgoyette DBCOOL_ADT7466_VCC_HILIM,
425 1.2 pgoyette DBCOOL_ADT7466_VCC_LOLIM }, 4, 0, 0 },
426 1.1 pgoyette { DBC_VOLT, { DBCOOL_ADT7466_AIN1,
427 1.1 pgoyette DBCOOL_ADT7466_AIN1_HILIM,
428 1.2 pgoyette DBCOOL_ADT7466_AIN1_LOLIM }, 9, 0, 6 },
429 1.1 pgoyette { DBC_VOLT, { DBCOOL_ADT7466_AIN2,
430 1.1 pgoyette DBCOOL_ADT7466_AIN2_HILIM,
431 1.2 pgoyette DBCOOL_ADT7466_AIN2_LOLIM }, 10, 0, 6 },
432 1.1 pgoyette { DBC_FAN, { DBCOOL_ADT7466_FANA_LSB,
433 1.1 pgoyette DBCOOL_NO_REG,
434 1.2 pgoyette DBCOOL_ADT7466_FANA_LOLIM_LSB }, 5, 0, 0 },
435 1.1 pgoyette { DBC_FAN, { DBCOOL_ADT7466_FANB_LSB,
436 1.1 pgoyette DBCOOL_NO_REG,
437 1.2 pgoyette DBCOOL_ADT7466_FANB_LOLIM_LSB }, 6, 0, 0 },
438 1.2 pgoyette { DBC_EOF, { 0, 0, 0 }, 0, 0, 0 }
439 1.1 pgoyette };
440 1.1 pgoyette
441 1.1 pgoyette struct dbcool_sensor ADM1027_sensor_table[] = {
442 1.1 pgoyette { DBC_TEMP, { DBCOOL_LOCAL_TEMP,
443 1.1 pgoyette DBCOOL_LOCAL_HIGHLIM,
444 1.2 pgoyette DBCOOL_LOCAL_LOWLIM }, 0, 0, 0 },
445 1.1 pgoyette { DBC_TEMP, { DBCOOL_REMOTE1_TEMP,
446 1.1 pgoyette DBCOOL_REMOTE1_HIGHLIM,
447 1.2 pgoyette DBCOOL_REMOTE1_LOWLIM }, 1, 0, 0 },
448 1.1 pgoyette { DBC_TEMP, { DBCOOL_REMOTE2_TEMP,
449 1.1 pgoyette DBCOOL_REMOTE2_HIGHLIM,
450 1.2 pgoyette DBCOOL_REMOTE2_LOWLIM }, 2, 0, 0 },
451 1.2 pgoyette { DBC_VOLT, { DBCOOL_VCCP,
452 1.1 pgoyette DBCOOL_VCCP_HIGHLIM,
453 1.2 pgoyette DBCOOL_VCCP_LOWLIM }, 3, 0, 1 },
454 1.2 pgoyette { DBC_VOLT, { DBCOOL_VCC,
455 1.1 pgoyette DBCOOL_VCC_HIGHLIM,
456 1.2 pgoyette DBCOOL_VCC_LOWLIM }, 4, 0, 0 },
457 1.1 pgoyette { DBC_VOLT, { DBCOOL_25VIN,
458 1.1 pgoyette DBCOOL_25VIN_HIGHLIM,
459 1.2 pgoyette DBCOOL_25VIN_LOWLIM }, 11, 0, 2 },
460 1.1 pgoyette { DBC_VOLT, { DBCOOL_5VIN,
461 1.1 pgoyette DBCOOL_5VIN_HIGHLIM,
462 1.2 pgoyette DBCOOL_5VIN_LOWLIM }, 12, 0, 3 },
463 1.1 pgoyette { DBC_VOLT, { DBCOOL_12VIN,
464 1.1 pgoyette DBCOOL_12VIN_HIGHLIM,
465 1.2 pgoyette DBCOOL_12VIN_LOWLIM }, 13, 0, 4 },
466 1.1 pgoyette { DBC_FAN, { DBCOOL_FAN1_TACH_LSB,
467 1.1 pgoyette DBCOOL_NO_REG,
468 1.2 pgoyette DBCOOL_TACH1_MIN_LSB }, 5, 0, 0 },
469 1.1 pgoyette { DBC_FAN, { DBCOOL_FAN2_TACH_LSB,
470 1.1 pgoyette DBCOOL_NO_REG,
471 1.2 pgoyette DBCOOL_TACH2_MIN_LSB }, 6, 0, 0 },
472 1.1 pgoyette { DBC_FAN, { DBCOOL_FAN3_TACH_LSB,
473 1.1 pgoyette DBCOOL_NO_REG,
474 1.2 pgoyette DBCOOL_TACH3_MIN_LSB }, 7, 0, 0 },
475 1.1 pgoyette { DBC_FAN, { DBCOOL_FAN4_TACH_LSB,
476 1.1 pgoyette DBCOOL_NO_REG,
477 1.2 pgoyette DBCOOL_TACH4_MIN_LSB }, 8, 0, 0 },
478 1.16 pgoyette { DBC_VID, { DBCOOL_VID_REG,
479 1.16 pgoyette DBCOOL_NO_REG,
480 1.16 pgoyette DBCOOL_NO_REG }, 16, 0, 0 },
481 1.1 pgoyette { DBC_CTL, { DBCOOL_LOCAL_TMIN,
482 1.1 pgoyette DBCOOL_NO_REG,
483 1.2 pgoyette DBCOOL_NO_REG }, 0, 5, 0 },
484 1.1 pgoyette { DBC_CTL, { DBCOOL_LOCAL_TTHRESH,
485 1.1 pgoyette DBCOOL_NO_REG,
486 1.2 pgoyette DBCOOL_NO_REG }, 0, 6, 0 },
487 1.1 pgoyette { DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST | 0x80,
488 1.1 pgoyette DBCOOL_NO_REG,
489 1.2 pgoyette DBCOOL_NO_REG }, 0, 7, 0 },
490 1.1 pgoyette { DBC_CTL, { DBCOOL_REMOTE1_TMIN,
491 1.1 pgoyette DBCOOL_NO_REG,
492 1.2 pgoyette DBCOOL_NO_REG }, 1, 5, 0 },
493 1.1 pgoyette { DBC_CTL, { DBCOOL_REMOTE1_TTHRESH,
494 1.1 pgoyette DBCOOL_NO_REG,
495 1.2 pgoyette DBCOOL_NO_REG }, 1, 6, 0 },
496 1.1 pgoyette { DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST,
497 1.1 pgoyette DBCOOL_NO_REG,
498 1.2 pgoyette DBCOOL_NO_REG }, 1, 7, 0 },
499 1.1 pgoyette { DBC_CTL, { DBCOOL_REMOTE2_TMIN,
500 1.1 pgoyette DBCOOL_NO_REG,
501 1.2 pgoyette DBCOOL_NO_REG }, 2, 5, 0 },
502 1.1 pgoyette { DBC_CTL, { DBCOOL_REMOTE2_TTHRESH,
503 1.1 pgoyette DBCOOL_NO_REG,
504 1.2 pgoyette DBCOOL_NO_REG }, 2, 6, 0 },
505 1.1 pgoyette { DBC_CTL, { DBCOOL_R2_TMIN_HYST,
506 1.1 pgoyette DBCOOL_NO_REG,
507 1.2 pgoyette DBCOOL_NO_REG }, 2, 7, 0 },
508 1.2 pgoyette { DBC_EOF, { 0, 0, 0 }, 0, 0, 0 }
509 1.1 pgoyette };
510 1.1 pgoyette
511 1.1 pgoyette struct dbcool_sensor ADM1030_sensor_table[] = {
512 1.1 pgoyette { DBC_TEMP, { DBCOOL_ADM1030_L_TEMP,
513 1.1 pgoyette DBCOOL_ADM1030_L_HI_LIM,
514 1.2 pgoyette DBCOOL_ADM1030_L_LO_LIM }, 0, 0, 0 },
515 1.1 pgoyette { DBC_TEMP, { DBCOOL_ADM1030_R_TEMP,
516 1.1 pgoyette DBCOOL_ADM1030_R_HI_LIM,
517 1.2 pgoyette DBCOOL_ADM1030_R_LO_LIM }, 1, 0, 0 },
518 1.1 pgoyette { DBC_FAN, { DBCOOL_ADM1030_FAN_TACH,
519 1.1 pgoyette DBCOOL_NO_REG,
520 1.2 pgoyette DBCOOL_ADM1030_FAN_LO_LIM }, 5, 0, 0 },
521 1.1 pgoyette { DBC_CTL, { DBCOOL_ADM1030_L_TMIN,
522 1.1 pgoyette DBCOOL_NO_REG,
523 1.2 pgoyette DBCOOL_NO_REG }, 0, 8, 0 },
524 1.1 pgoyette { DBC_CTL, { DBCOOL_ADM1030_L_TTHRESH,
525 1.1 pgoyette DBCOOL_NO_REG,
526 1.2 pgoyette DBCOOL_NO_REG }, 0, 9, 0 },
527 1.1 pgoyette { DBC_CTL, { DBCOOL_ADM1030_L_TTHRESH,
528 1.1 pgoyette DBCOOL_NO_REG,
529 1.2 pgoyette DBCOOL_NO_REG }, 0, 6, 0 },
530 1.1 pgoyette { DBC_CTL, { DBCOOL_ADM1030_R_TMIN,
531 1.1 pgoyette DBCOOL_NO_REG,
532 1.2 pgoyette DBCOOL_NO_REG }, 1, 8, 0 },
533 1.22 macallan { DBC_CTL, { DBCOOL_ADM1030_R_TTHRESH,
534 1.1 pgoyette DBCOOL_NO_REG,
535 1.2 pgoyette DBCOOL_NO_REG }, 1, 9, 0 },
536 1.1 pgoyette { DBC_CTL, { DBCOOL_ADM1030_R_TTHRESH,
537 1.1 pgoyette DBCOOL_NO_REG,
538 1.2 pgoyette DBCOOL_NO_REG }, 1, 6, 0 },
539 1.2 pgoyette { DBC_EOF, {0, 0, 0 }, 0, 0, 0 }
540 1.1 pgoyette };
541 1.1 pgoyette
542 1.1 pgoyette struct dbcool_power_control ADM1030_power_table[] = {
543 1.2 pgoyette { { DBCOOL_ADM1030_CFG1, DBCOOL_NO_REG, DBCOOL_NO_REG,
544 1.2 pgoyette DBCOOL_ADM1030_FAN_SPEED_CFG },
545 1.2 pgoyette "fan_control_1" },
546 1.2 pgoyette { { 0, 0, 0, 0 }, NULL }
547 1.1 pgoyette };
548 1.1 pgoyette
549 1.22 macallan struct dbcool_sensor ADM1031_sensor_table[] = {
550 1.22 macallan { DBC_TEMP, { DBCOOL_ADM1030_L_TEMP,
551 1.22 macallan DBCOOL_ADM1030_L_HI_LIM,
552 1.22 macallan DBCOOL_ADM1030_L_LO_LIM }, 0, 0, 0 },
553 1.22 macallan { DBC_TEMP, { DBCOOL_ADM1030_R_TEMP,
554 1.22 macallan DBCOOL_ADM1030_R_HI_LIM,
555 1.22 macallan DBCOOL_ADM1030_R_LO_LIM }, 1, 0, 0 },
556 1.22 macallan { DBC_TEMP, { DBCOOL_ADM1031_R2_TEMP,
557 1.22 macallan DBCOOL_ADM1031_R2_HI_LIM,
558 1.22 macallan DBCOOL_ADM1031_R2_LO_LIM }, 2, 0, 0 },
559 1.22 macallan { DBC_FAN, { DBCOOL_ADM1030_FAN_TACH,
560 1.22 macallan DBCOOL_NO_REG,
561 1.22 macallan DBCOOL_ADM1030_FAN_LO_LIM }, 5, 0, 0 },
562 1.22 macallan { DBC_FAN, { DBCOOL_ADM1031_FAN2_TACH,
563 1.22 macallan DBCOOL_NO_REG,
564 1.22 macallan DBCOOL_ADM1031_FAN2_LO_LIM }, 6, 0, 0 },
565 1.22 macallan { DBC_CTL, { DBCOOL_ADM1030_L_TMIN,
566 1.22 macallan DBCOOL_NO_REG,
567 1.22 macallan DBCOOL_NO_REG }, 0, 8, 0 },
568 1.22 macallan { DBC_CTL, { DBCOOL_ADM1030_L_TTHRESH,
569 1.22 macallan DBCOOL_NO_REG,
570 1.22 macallan DBCOOL_NO_REG }, 0, 9, 0 },
571 1.22 macallan { DBC_CTL, { DBCOOL_ADM1030_L_TTHRESH,
572 1.22 macallan DBCOOL_NO_REG,
573 1.22 macallan DBCOOL_NO_REG }, 0, 6, 0 },
574 1.22 macallan { DBC_CTL, { DBCOOL_ADM1030_R_TMIN,
575 1.22 macallan DBCOOL_NO_REG,
576 1.22 macallan DBCOOL_NO_REG }, 1, 8, 0 },
577 1.22 macallan { DBC_CTL, { DBCOOL_ADM1030_R_TTHRESH,
578 1.22 macallan DBCOOL_NO_REG,
579 1.22 macallan DBCOOL_NO_REG }, 1, 9, 0 },
580 1.22 macallan { DBC_CTL, { DBCOOL_ADM1030_R_TTHRESH,
581 1.22 macallan DBCOOL_NO_REG,
582 1.22 macallan DBCOOL_NO_REG }, 1, 6, 0 },
583 1.22 macallan { DBC_CTL, { DBCOOL_ADM1031_R2_TMIN,
584 1.22 macallan DBCOOL_NO_REG,
585 1.22 macallan DBCOOL_NO_REG }, 2, 8, 0 },
586 1.22 macallan { DBC_CTL, { DBCOOL_ADM1031_R2_TTHRESH,
587 1.22 macallan DBCOOL_NO_REG,
588 1.22 macallan DBCOOL_NO_REG }, 2, 9, 0 },
589 1.22 macallan { DBC_CTL, { DBCOOL_ADM1031_R2_TTHRESH,
590 1.22 macallan DBCOOL_NO_REG,
591 1.22 macallan DBCOOL_NO_REG }, 2, 6, 0 },
592 1.22 macallan { DBC_EOF, {0, 0, 0 }, 0, 0, 0 }
593 1.22 macallan };
594 1.22 macallan
595 1.22 macallan struct dbcool_power_control ADM1031_power_table[] = {
596 1.22 macallan { { DBCOOL_ADM1030_CFG1, DBCOOL_NO_REG, DBCOOL_NO_REG,
597 1.22 macallan DBCOOL_ADM1030_FAN_SPEED_CFG },
598 1.22 macallan "fan_control_1" },
599 1.22 macallan { { DBCOOL_ADM1030_CFG1, DBCOOL_NO_REG, DBCOOL_NO_REG,
600 1.22 macallan DBCOOL_ADM1030_FAN_SPEED_CFG },
601 1.22 macallan "fan_control_2" },
602 1.22 macallan { { 0, 0, 0, 0 }, NULL }
603 1.22 macallan };
604 1.27 pgoyette
605 1.27 pgoyette struct dbcool_sensor EMC6D103S_sensor_table[] = {
606 1.27 pgoyette { DBC_TEMP, { DBCOOL_LOCAL_TEMP,
607 1.27 pgoyette DBCOOL_LOCAL_HIGHLIM,
608 1.27 pgoyette DBCOOL_LOCAL_LOWLIM }, 0, 0, 0 },
609 1.27 pgoyette { DBC_TEMP, { DBCOOL_REMOTE1_TEMP,
610 1.27 pgoyette DBCOOL_REMOTE1_HIGHLIM,
611 1.27 pgoyette DBCOOL_REMOTE1_LOWLIM }, 1, 0, 0 },
612 1.27 pgoyette { DBC_TEMP, { DBCOOL_REMOTE2_TEMP,
613 1.27 pgoyette DBCOOL_REMOTE2_HIGHLIM,
614 1.27 pgoyette DBCOOL_REMOTE2_LOWLIM }, 2, 0, 0 },
615 1.27 pgoyette { DBC_VOLT, { DBCOOL_VCCP,
616 1.27 pgoyette DBCOOL_VCCP_HIGHLIM,
617 1.27 pgoyette DBCOOL_VCCP_LOWLIM }, 3, 0, 1 },
618 1.27 pgoyette { DBC_VOLT, { DBCOOL_VCC,
619 1.27 pgoyette DBCOOL_VCC_HIGHLIM,
620 1.27 pgoyette DBCOOL_VCC_LOWLIM }, 4, 0, 0 },
621 1.27 pgoyette { DBC_VOLT, { DBCOOL_25VIN,
622 1.27 pgoyette DBCOOL_25VIN_HIGHLIM,
623 1.27 pgoyette DBCOOL_25VIN_LOWLIM }, 11, 0, 2 },
624 1.27 pgoyette { DBC_VOLT, { DBCOOL_5VIN,
625 1.27 pgoyette DBCOOL_5VIN_HIGHLIM,
626 1.27 pgoyette DBCOOL_5VIN_LOWLIM }, 12, 0, 3 },
627 1.27 pgoyette { DBC_VOLT, { DBCOOL_12VIN,
628 1.27 pgoyette DBCOOL_12VIN_HIGHLIM,
629 1.27 pgoyette DBCOOL_12VIN_LOWLIM }, 13, 0, 4 },
630 1.27 pgoyette { DBC_FAN, { DBCOOL_FAN1_TACH_LSB,
631 1.27 pgoyette DBCOOL_NO_REG,
632 1.27 pgoyette DBCOOL_TACH1_MIN_LSB }, 5, 0, 0 },
633 1.27 pgoyette { DBC_FAN, { DBCOOL_FAN2_TACH_LSB,
634 1.27 pgoyette DBCOOL_NO_REG,
635 1.27 pgoyette DBCOOL_TACH2_MIN_LSB }, 6, 0, 0 },
636 1.27 pgoyette { DBC_FAN, { DBCOOL_FAN3_TACH_LSB,
637 1.27 pgoyette DBCOOL_NO_REG,
638 1.27 pgoyette DBCOOL_TACH3_MIN_LSB }, 7, 0, 0 },
639 1.27 pgoyette { DBC_FAN, { DBCOOL_FAN4_TACH_LSB,
640 1.27 pgoyette DBCOOL_NO_REG,
641 1.27 pgoyette DBCOOL_TACH4_MIN_LSB }, 8, 0, 0 },
642 1.27 pgoyette { DBC_VID, { DBCOOL_VID_REG,
643 1.27 pgoyette DBCOOL_NO_REG,
644 1.27 pgoyette DBCOOL_NO_REG }, 16, 0, 0 },
645 1.27 pgoyette { DBC_CTL, { DBCOOL_LOCAL_TMIN,
646 1.27 pgoyette DBCOOL_NO_REG,
647 1.27 pgoyette DBCOOL_NO_REG }, 0, 5, 0 },
648 1.27 pgoyette { DBC_CTL, { DBCOOL_LOCAL_TTHRESH,
649 1.27 pgoyette DBCOOL_NO_REG,
650 1.27 pgoyette DBCOOL_NO_REG }, 0, 6, 0 },
651 1.27 pgoyette { DBC_CTL, { DBCOOL_REMOTE1_TMIN,
652 1.27 pgoyette DBCOOL_NO_REG,
653 1.27 pgoyette DBCOOL_NO_REG }, 1, 5, 0 },
654 1.27 pgoyette { DBC_CTL, { DBCOOL_REMOTE1_TTHRESH,
655 1.27 pgoyette DBCOOL_NO_REG,
656 1.27 pgoyette DBCOOL_NO_REG }, 1, 6, 0 },
657 1.27 pgoyette { DBC_CTL, { DBCOOL_REMOTE2_TMIN,
658 1.27 pgoyette DBCOOL_NO_REG,
659 1.27 pgoyette DBCOOL_NO_REG }, 2, 5, 0 },
660 1.27 pgoyette { DBC_CTL, { DBCOOL_REMOTE2_TTHRESH,
661 1.27 pgoyette DBCOOL_NO_REG,
662 1.27 pgoyette DBCOOL_NO_REG }, 2, 6, 0 },
663 1.27 pgoyette { DBC_EOF, { 0, 0, 0 }, 0, 0, 0 }
664 1.27 pgoyette };
665 1.27 pgoyette
666 1.1 pgoyette struct chip_id chip_table[] = {
667 1.2 pgoyette { DBCOOL_COMPANYID, ADT7490_DEVICEID, ADT7490_REV_ID,
668 1.16 pgoyette ADT7490_sensor_table, ADT7475_power_table,
669 1.16 pgoyette DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY | DBCFLAG_HAS_PECI,
670 1.2 pgoyette 90000 * 60, "ADT7490" },
671 1.1 pgoyette { DBCOOL_COMPANYID, ADT7476_DEVICEID, 0xff,
672 1.2 pgoyette ADT7476_sensor_table, ADT7475_power_table,
673 1.16 pgoyette DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY,
674 1.1 pgoyette 90000 * 60, "ADT7476" },
675 1.1 pgoyette { DBCOOL_COMPANYID, ADT7475_DEVICEID, 0xff,
676 1.1 pgoyette ADT7475_sensor_table, ADT7475_power_table,
677 1.1 pgoyette DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY | DBCFLAG_HAS_SHDN,
678 1.1 pgoyette 90000 * 60, "ADT7475" },
679 1.2 pgoyette { DBCOOL_COMPANYID, ADT7473_DEVICEID, ADT7473_REV_ID1,
680 1.1 pgoyette ADT7475_sensor_table, ADT7475_power_table,
681 1.1 pgoyette DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY | DBCFLAG_HAS_SHDN,
682 1.8 pgoyette 90000 * 60, "ADT7460/ADT7463" },
683 1.2 pgoyette { DBCOOL_COMPANYID, ADT7473_DEVICEID, ADT7473_REV_ID2,
684 1.1 pgoyette ADT7475_sensor_table, ADT7475_power_table,
685 1.1 pgoyette DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY | DBCFLAG_HAS_SHDN,
686 1.1 pgoyette 90000 * 60, "ADT7463-1" },
687 1.1 pgoyette { DBCOOL_COMPANYID, ADT7468_DEVICEID, 0xff,
688 1.2 pgoyette ADT7476_sensor_table, ADT7475_power_table,
689 1.1 pgoyette DBCFLAG_TEMPOFFSET | DBCFLAG_MULTI_VCC | DBCFLAG_HAS_MAXDUTY |
690 1.16 pgoyette DBCFLAG_4BIT_VER | DBCFLAG_HAS_SHDN,
691 1.2 pgoyette 90000 * 60, "ADT7467/ADT7468" },
692 1.1 pgoyette { DBCOOL_COMPANYID, ADT7466_DEVICEID, 0xff,
693 1.1 pgoyette ADT7466_sensor_table, NULL,
694 1.1 pgoyette DBCFLAG_ADT7466 | DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_SHDN,
695 1.1 pgoyette 82000 * 60, "ADT7466" },
696 1.1 pgoyette { DBCOOL_COMPANYID, ADT7463_DEVICEID, ADT7463_REV_ID1,
697 1.1 pgoyette ADM1027_sensor_table, ADT7475_power_table,
698 1.16 pgoyette DBCFLAG_MULTI_VCC | DBCFLAG_4BIT_VER | DBCFLAG_HAS_SHDN,
699 1.1 pgoyette 90000 * 60, "ADT7463" },
700 1.1 pgoyette { DBCOOL_COMPANYID, ADT7463_DEVICEID, ADT7463_REV_ID2,
701 1.1 pgoyette ADM1027_sensor_table, ADT7475_power_table,
702 1.1 pgoyette DBCFLAG_MULTI_VCC | DBCFLAG_4BIT_VER | DBCFLAG_HAS_SHDN |
703 1.16 pgoyette DBCFLAG_HAS_VID_SEL,
704 1.1 pgoyette 90000 * 60, "ADT7463" },
705 1.1 pgoyette { DBCOOL_COMPANYID, ADM1027_DEVICEID, ADM1027_REV_ID,
706 1.1 pgoyette ADM1027_sensor_table, ADT7475_power_table,
707 1.16 pgoyette DBCFLAG_MULTI_VCC | DBCFLAG_4BIT_VER,
708 1.1 pgoyette 90000 * 60, "ADM1027" },
709 1.1 pgoyette { DBCOOL_COMPANYID, ADM1030_DEVICEID, 0xff,
710 1.1 pgoyette ADM1030_sensor_table, ADM1030_power_table,
711 1.16 pgoyette DBCFLAG_ADM1030 | DBCFLAG_NO_READBYTE,
712 1.1 pgoyette 11250 * 60, "ADM1030" },
713 1.21 macallan { DBCOOL_COMPANYID, ADM1031_DEVICEID, 0xff,
714 1.22 macallan ADM1031_sensor_table, ADM1030_power_table,
715 1.21 macallan DBCFLAG_ADM1030 | DBCFLAG_NO_READBYTE,
716 1.21 macallan 11250 * 60, "ADM1031" },
717 1.27 pgoyette { SMSC_COMPANYID, EMC6D103S_DEVICEID, EMC6D103S_REV_ID,
718 1.27 pgoyette EMC6D103S_sensor_table, ADT7475_power_table,
719 1.27 pgoyette DBCFLAG_4BIT_VER,
720 1.27 pgoyette 90000 * 60, "EMC6D103S" },
721 1.1 pgoyette { 0, 0, 0, NULL, NULL, 0, 0, NULL }
722 1.1 pgoyette };
723 1.1 pgoyette
724 1.1 pgoyette static const char *behavior[] = {
725 1.1 pgoyette "remote1", "local", "remote2", "full-speed",
726 1.1 pgoyette "disabled", "local+remote2","all-temps", "manual"
727 1.1 pgoyette };
728 1.1 pgoyette
729 1.1 pgoyette static char dbcool_cur_behav[16];
730 1.1 pgoyette
731 1.1 pgoyette CFATTACH_DECL_NEW(dbcool, sizeof(struct dbcool_softc),
732 1.1 pgoyette dbcool_match, dbcool_attach, dbcool_detach, NULL);
733 1.1 pgoyette
734 1.1 pgoyette int
735 1.1 pgoyette dbcool_match(device_t parent, cfdata_t cf, void *aux)
736 1.1 pgoyette {
737 1.1 pgoyette struct i2c_attach_args *ia = aux;
738 1.13 christos struct dbcool_chipset dc;
739 1.13 christos dc.dc_tag = ia->ia_tag;
740 1.13 christos dc.dc_addr = ia->ia_addr;
741 1.13 christos dc.dc_chip = NULL;
742 1.13 christos dc.dc_readreg = dbcool_readreg;
743 1.13 christos dc.dc_writereg = dbcool_writereg;
744 1.1 pgoyette
745 1.7 pgoyette /* no probing if we attach to iic, but verify chip id and address */
746 1.7 pgoyette if ((ia->ia_addr & DBCOOL_ADDRMASK) != DBCOOL_ADDR)
747 1.7 pgoyette return 0;
748 1.13 christos if (dbcool_chip_ident(&dc) >= 0)
749 1.1 pgoyette return 1;
750 1.1 pgoyette
751 1.1 pgoyette return 0;
752 1.1 pgoyette }
753 1.1 pgoyette
754 1.1 pgoyette void
755 1.1 pgoyette dbcool_attach(device_t parent, device_t self, void *aux)
756 1.1 pgoyette {
757 1.1 pgoyette struct dbcool_softc *sc = device_private(self);
758 1.1 pgoyette struct i2c_attach_args *args = aux;
759 1.1 pgoyette uint8_t ver;
760 1.1 pgoyette
761 1.13 christos sc->sc_dc.dc_addr = args->ia_addr;
762 1.13 christos sc->sc_dc.dc_tag = args->ia_tag;
763 1.13 christos sc->sc_dc.dc_chip = NULL;
764 1.13 christos sc->sc_dc.dc_readreg = dbcool_readreg;
765 1.13 christos sc->sc_dc.dc_writereg = dbcool_writereg;
766 1.13 christos (void)dbcool_chip_ident(&sc->sc_dc);
767 1.2 pgoyette sc->sc_dev = self;
768 1.1 pgoyette
769 1.1 pgoyette aprint_naive("\n");
770 1.1 pgoyette aprint_normal("\n");
771 1.1 pgoyette
772 1.13 christos ver = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_REVISION_REG);
773 1.13 christos if (sc->sc_dc.dc_chip->flags & DBCFLAG_4BIT_VER)
774 1.27 pgoyette if (sc->sc_dc.dc_chip->company == SMSC_COMPANYID)
775 1.27 pgoyette {
776 1.27 pgoyette aprint_normal_dev(self, "SMSC %s Controller "
777 1.27 pgoyette "(rev 0x%02x, stepping 0x%02x)\n", sc->sc_dc.dc_chip->name,
778 1.27 pgoyette ver >> 4, ver & 0x0f);
779 1.27 pgoyette } else {
780 1.27 pgoyette aprint_normal_dev(self, "%s dBCool(tm) Controller "
781 1.27 pgoyette "(rev 0x%02x, stepping 0x%02x)\n", sc->sc_dc.dc_chip->name,
782 1.27 pgoyette ver >> 4, ver & 0x0f);
783 1.27 pgoyette }
784 1.1 pgoyette else
785 1.1 pgoyette aprint_normal_dev(self, "%s dBCool(tm) Controller "
786 1.13 christos "(rev 0x%04x)\n", sc->sc_dc.dc_chip->name, ver);
787 1.1 pgoyette
788 1.33 pgoyette sc->sc_sysctl_log = NULL;
789 1.33 pgoyette
790 1.33 pgoyette #ifdef _MODULE
791 1.33 pgoyette sysctl_dbcoolsetup(&sc->sc_sysctl_log);
792 1.33 pgoyette #endif
793 1.33 pgoyette
794 1.1 pgoyette dbcool_setup(self);
795 1.1 pgoyette
796 1.1 pgoyette if (!pmf_device_register(self, dbcool_pmf_suspend, dbcool_pmf_resume))
797 1.1 pgoyette aprint_error_dev(self, "couldn't establish power handler\n");
798 1.1 pgoyette }
799 1.1 pgoyette
800 1.1 pgoyette static int
801 1.1 pgoyette dbcool_detach(device_t self, int flags)
802 1.1 pgoyette {
803 1.1 pgoyette struct dbcool_softc *sc = device_private(self);
804 1.1 pgoyette
805 1.31 jmcneill pmf_device_deregister(self);
806 1.31 jmcneill
807 1.1 pgoyette sysmon_envsys_unregister(sc->sc_sme);
808 1.33 pgoyette
809 1.33 pgoyette sysctl_teardown(&sc->sc_sysctl_log);
810 1.33 pgoyette
811 1.1 pgoyette sc->sc_sme = NULL;
812 1.1 pgoyette return 0;
813 1.1 pgoyette }
814 1.1 pgoyette
815 1.1 pgoyette /* On suspend, we save the state of the SHDN bit, then set it */
816 1.15 dyoung bool dbcool_pmf_suspend(device_t dev, const pmf_qual_t *qual)
817 1.1 pgoyette {
818 1.1 pgoyette struct dbcool_softc *sc = device_private(dev);
819 1.1 pgoyette uint8_t reg, bit, cfg;
820 1.1 pgoyette
821 1.13 christos if ((sc->sc_dc.dc_chip->flags && DBCFLAG_HAS_SHDN) == 0)
822 1.1 pgoyette return true;
823 1.1 pgoyette
824 1.13 christos if (sc->sc_dc.dc_chip->flags && DBCFLAG_ADT7466) {
825 1.1 pgoyette reg = DBCOOL_ADT7466_CONFIG2;
826 1.1 pgoyette bit = DBCOOL_ADT7466_CFG2_SHDN;
827 1.1 pgoyette } else {
828 1.1 pgoyette reg = DBCOOL_CONFIG2_REG;
829 1.1 pgoyette bit = DBCOOL_CFG2_SHDN;
830 1.1 pgoyette }
831 1.13 christos cfg = sc->sc_dc.dc_readreg(&sc->sc_dc, reg);
832 1.1 pgoyette sc->sc_suspend = cfg & bit;
833 1.1 pgoyette cfg |= bit;
834 1.13 christos sc->sc_dc.dc_writereg(&sc->sc_dc, reg, cfg);
835 1.1 pgoyette
836 1.1 pgoyette return true;
837 1.1 pgoyette }
838 1.1 pgoyette
839 1.1 pgoyette /* On resume, we restore the previous state of the SHDN bit */
840 1.15 dyoung bool dbcool_pmf_resume(device_t dev, const pmf_qual_t *qual)
841 1.1 pgoyette {
842 1.1 pgoyette struct dbcool_softc *sc = device_private(dev);
843 1.1 pgoyette uint8_t reg, bit, cfg;
844 1.1 pgoyette
845 1.13 christos if ((sc->sc_dc.dc_chip->flags && DBCFLAG_HAS_SHDN) == 0)
846 1.1 pgoyette return true;
847 1.1 pgoyette
848 1.13 christos if (sc->sc_dc.dc_chip->flags && DBCFLAG_ADT7466) {
849 1.1 pgoyette reg = DBCOOL_ADT7466_CONFIG2;
850 1.1 pgoyette bit = DBCOOL_ADT7466_CFG2_SHDN;
851 1.1 pgoyette } else {
852 1.1 pgoyette reg = DBCOOL_CONFIG2_REG;
853 1.1 pgoyette bit = DBCOOL_CFG2_SHDN;
854 1.1 pgoyette }
855 1.13 christos cfg = sc->sc_dc.dc_readreg(&sc->sc_dc, reg);
856 1.1 pgoyette cfg &= ~sc->sc_suspend;
857 1.13 christos sc->sc_dc.dc_writereg(&sc->sc_dc, reg, cfg);
858 1.1 pgoyette
859 1.1 pgoyette return true;
860 1.1 pgoyette
861 1.1 pgoyette }
862 1.1 pgoyette
863 1.1 pgoyette uint8_t
864 1.13 christos dbcool_readreg(struct dbcool_chipset *dc, uint8_t reg)
865 1.1 pgoyette {
866 1.1 pgoyette uint8_t data = 0;
867 1.1 pgoyette
868 1.13 christos if (iic_acquire_bus(dc->dc_tag, 0) != 0)
869 1.11 pgoyette return data;
870 1.1 pgoyette
871 1.16 pgoyette if (dc->dc_chip == NULL || dc->dc_chip->flags & DBCFLAG_NO_READBYTE) {
872 1.10 pgoyette /* ADM1027 doesn't support i2c read_byte protocol */
873 1.13 christos if (iic_smbus_send_byte(dc->dc_tag, dc->dc_addr, reg, 0) != 0)
874 1.10 pgoyette goto bad;
875 1.13 christos (void)iic_smbus_receive_byte(dc->dc_tag, dc->dc_addr, &data, 0);
876 1.10 pgoyette } else
877 1.13 christos (void)iic_smbus_read_byte(dc->dc_tag, dc->dc_addr, reg, &data,
878 1.10 pgoyette 0);
879 1.1 pgoyette
880 1.1 pgoyette bad:
881 1.13 christos iic_release_bus(dc->dc_tag, 0);
882 1.1 pgoyette return data;
883 1.1 pgoyette }
884 1.1 pgoyette
885 1.1 pgoyette void
886 1.13 christos dbcool_writereg(struct dbcool_chipset *dc, uint8_t reg, uint8_t val)
887 1.1 pgoyette {
888 1.13 christos if (iic_acquire_bus(dc->dc_tag, 0) != 0)
889 1.9 pgoyette return;
890 1.1 pgoyette
891 1.13 christos (void)iic_smbus_write_byte(dc->dc_tag, dc->dc_addr, reg, val, 0);
892 1.1 pgoyette
893 1.13 christos iic_release_bus(dc->dc_tag, 0);
894 1.27 pgoyette }
895 1.1 pgoyette
896 1.2 pgoyette static bool
897 1.1 pgoyette dbcool_islocked(struct dbcool_softc *sc)
898 1.1 pgoyette {
899 1.1 pgoyette uint8_t cfg_reg;
900 1.1 pgoyette
901 1.13 christos if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADM1030)
902 1.1 pgoyette return 0;
903 1.1 pgoyette
904 1.13 christos if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADT7466)
905 1.1 pgoyette cfg_reg = DBCOOL_ADT7466_CONFIG1;
906 1.1 pgoyette else
907 1.1 pgoyette cfg_reg = DBCOOL_CONFIG1_REG;
908 1.1 pgoyette
909 1.13 christos if (sc->sc_dc.dc_readreg(&sc->sc_dc, cfg_reg) & DBCOOL_CFG1_LOCK)
910 1.1 pgoyette return 1;
911 1.1 pgoyette else
912 1.1 pgoyette return 0;
913 1.1 pgoyette }
914 1.1 pgoyette
915 1.1 pgoyette static int
916 1.1 pgoyette dbcool_read_temp(struct dbcool_softc *sc, uint8_t reg, bool extres)
917 1.1 pgoyette {
918 1.1 pgoyette uint8_t t1, t2, t3, val, ext = 0;
919 1.1 pgoyette int temp;
920 1.1 pgoyette
921 1.13 christos if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADT7466) {
922 1.1 pgoyette /*
923 1.1 pgoyette * ADT7466 temps are in strange location
924 1.1 pgoyette */
925 1.13 christos ext = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_ADT7466_CONFIG1);
926 1.13 christos val = sc->sc_dc.dc_readreg(&sc->sc_dc, reg);
927 1.1 pgoyette if (extres)
928 1.13 christos ext = sc->sc_dc.dc_readreg(&sc->sc_dc, reg + 1);
929 1.13 christos } else if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADM1030) {
930 1.1 pgoyette /*
931 1.1 pgoyette * ADM1030 temps are in their own special place, too
932 1.1 pgoyette */
933 1.1 pgoyette if (extres) {
934 1.13 christos ext = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_ADM1030_TEMP_EXTRES);
935 1.1 pgoyette if (reg == DBCOOL_ADM1030_L_TEMP)
936 1.1 pgoyette ext >>= 6;
937 1.22 macallan else if (reg == DBCOOL_ADM1031_R2_TEMP)
938 1.22 macallan ext >>= 4;
939 1.1 pgoyette else
940 1.1 pgoyette ext >>= 1;
941 1.1 pgoyette ext &= 0x03;
942 1.1 pgoyette }
943 1.13 christos val = sc->sc_dc.dc_readreg(&sc->sc_dc, reg);
944 1.2 pgoyette } else if (extres) {
945 1.13 christos ext = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_EXTRES2_REG);
946 1.1 pgoyette
947 1.2 pgoyette /* Read all msb regs to unlatch them */
948 1.13 christos t1 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_12VIN);
949 1.13 christos t1 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_REMOTE1_TEMP);
950 1.13 christos t2 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_REMOTE2_TEMP);
951 1.13 christos t3 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_LOCAL_TEMP);
952 1.2 pgoyette switch (reg) {
953 1.2 pgoyette case DBCOOL_REMOTE1_TEMP:
954 1.2 pgoyette val = t1;
955 1.2 pgoyette ext >>= 2;
956 1.2 pgoyette break;
957 1.2 pgoyette case DBCOOL_LOCAL_TEMP:
958 1.2 pgoyette val = t3;
959 1.2 pgoyette ext >>= 4;
960 1.2 pgoyette break;
961 1.2 pgoyette case DBCOOL_REMOTE2_TEMP:
962 1.2 pgoyette val = t2;
963 1.2 pgoyette ext >>= 6;
964 1.2 pgoyette break;
965 1.2 pgoyette default:
966 1.2 pgoyette val = 0;
967 1.2 pgoyette break;
968 1.1 pgoyette }
969 1.2 pgoyette ext &= 0x03;
970 1.1 pgoyette }
971 1.2 pgoyette else
972 1.13 christos val = sc->sc_dc.dc_readreg(&sc->sc_dc, reg);
973 1.1 pgoyette
974 1.1 pgoyette /* Check for invalid temp values */
975 1.2 pgoyette if ((sc->sc_temp_offset == 0 && val == 0x80) ||
976 1.2 pgoyette (sc->sc_temp_offset != 0 && val == 0))
977 1.1 pgoyette return 0;
978 1.1 pgoyette
979 1.1 pgoyette /* If using offset mode, adjust, else treat as signed */
980 1.2 pgoyette if (sc->sc_temp_offset) {
981 1.1 pgoyette temp = val;
982 1.2 pgoyette temp -= sc->sc_temp_offset;
983 1.1 pgoyette } else
984 1.1 pgoyette temp = (int8_t)val;
985 1.1 pgoyette
986 1.1 pgoyette /* Convert degC to uK and include extended precision bits */
987 1.1 pgoyette temp *= 1000000;
988 1.1 pgoyette temp += 250000 * (int)ext;
989 1.1 pgoyette temp += 273150000U;
990 1.1 pgoyette
991 1.1 pgoyette return temp;
992 1.1 pgoyette }
993 1.1 pgoyette
994 1.1 pgoyette static int
995 1.1 pgoyette dbcool_read_rpm(struct dbcool_softc *sc, uint8_t reg)
996 1.1 pgoyette {
997 1.1 pgoyette int rpm;
998 1.1 pgoyette uint8_t rpm_lo, rpm_hi;
999 1.1 pgoyette
1000 1.13 christos rpm_lo = sc->sc_dc.dc_readreg(&sc->sc_dc, reg);
1001 1.13 christos if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADM1030)
1002 1.1 pgoyette rpm_hi = (rpm_lo == 0xff)?0xff:0x0;
1003 1.1 pgoyette else
1004 1.13 christos rpm_hi = sc->sc_dc.dc_readreg(&sc->sc_dc, reg + 1);
1005 1.1 pgoyette
1006 1.1 pgoyette rpm = (rpm_hi << 8) | rpm_lo;
1007 1.1 pgoyette if (rpm == 0xffff)
1008 1.1 pgoyette return 0; /* 0xffff indicates stalled/failed fan */
1009 1.1 pgoyette
1010 1.23 macallan /* don't divide by zero */
1011 1.23 macallan return (rpm == 0)? 0 : (sc->sc_dc.dc_chip->rpm_dividend / rpm);
1012 1.1 pgoyette }
1013 1.1 pgoyette
1014 1.2 pgoyette /* Provide chip's supply voltage, in microvolts */
1015 1.1 pgoyette static int
1016 1.1 pgoyette dbcool_supply_voltage(struct dbcool_softc *sc)
1017 1.1 pgoyette {
1018 1.13 christos if (sc->sc_dc.dc_chip->flags & DBCFLAG_MULTI_VCC) {
1019 1.13 christos if (sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_CONFIG1_REG) & DBCOOL_CFG1_Vcc)
1020 1.2 pgoyette return 5002500;
1021 1.1 pgoyette else
1022 1.2 pgoyette return 3300000;
1023 1.13 christos } else if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADT7466) {
1024 1.13 christos if (sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_ADT7466_CONFIG1) &
1025 1.1 pgoyette DBCOOL_ADT7466_CFG1_Vcc)
1026 1.2 pgoyette return 5000000;
1027 1.1 pgoyette else
1028 1.2 pgoyette return 3300000;
1029 1.1 pgoyette } else
1030 1.2 pgoyette return 3300000;
1031 1.1 pgoyette }
1032 1.1 pgoyette
1033 1.2 pgoyette /*
1034 1.2 pgoyette * Nominal voltages are calculated in microvolts
1035 1.2 pgoyette */
1036 1.1 pgoyette static int
1037 1.2 pgoyette dbcool_read_volt(struct dbcool_softc *sc, uint8_t reg, int nom_idx, bool extres)
1038 1.1 pgoyette {
1039 1.1 pgoyette uint8_t ext = 0, v1, v2, v3, v4, val;
1040 1.2 pgoyette int64_t ret;
1041 1.2 pgoyette int64_t nom;
1042 1.2 pgoyette
1043 1.2 pgoyette nom = nominal_voltages[nom_idx];
1044 1.2 pgoyette if (nom < 0)
1045 1.2 pgoyette nom = sc->sc_supply_voltage;
1046 1.1 pgoyette
1047 1.1 pgoyette /* ADT7466 voltages are in strange locations with only 8-bits */
1048 1.13 christos if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADT7466)
1049 1.13 christos val = sc->sc_dc.dc_readreg(&sc->sc_dc, reg);
1050 1.2 pgoyette else
1051 1.2 pgoyette /*
1052 1.2 pgoyette * It's a "normal" dbCool chip - check for regs that
1053 1.2 pgoyette * share extended resolution bits since we have to
1054 1.2 pgoyette * read all the MSB registers to unlatch them.
1055 1.2 pgoyette */
1056 1.2 pgoyette if (!extres)
1057 1.13 christos val = sc->sc_dc.dc_readreg(&sc->sc_dc, reg);
1058 1.2 pgoyette else if (reg == DBCOOL_12VIN) {
1059 1.13 christos ext = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_EXTRES2_REG) && 0x03;
1060 1.13 christos val = sc->sc_dc.dc_readreg(&sc->sc_dc, reg);
1061 1.2 pgoyette (void)dbcool_read_temp(sc, DBCOOL_LOCAL_TEMP, true);
1062 1.2 pgoyette } else if (reg == DBCOOL_VTT || reg == DBCOOL_IMON) {
1063 1.13 christos ext = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_EXTRES_VTT_IMON);
1064 1.13 christos v1 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_IMON);
1065 1.13 christos v2 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_VTT);
1066 1.2 pgoyette if (reg == DBCOOL_IMON) {
1067 1.2 pgoyette val = v1;
1068 1.2 pgoyette ext >>= 6;
1069 1.2 pgoyette } else
1070 1.2 pgoyette val = v2;
1071 1.2 pgoyette ext >>= 4;
1072 1.2 pgoyette ext &= 0x0f;
1073 1.1 pgoyette } else {
1074 1.13 christos ext = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_EXTRES1_REG);
1075 1.13 christos v1 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_25VIN);
1076 1.13 christos v2 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_VCCP);
1077 1.13 christos v3 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_VCC);
1078 1.13 christos v4 = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_5VIN);
1079 1.1 pgoyette
1080 1.1 pgoyette switch (reg) {
1081 1.1 pgoyette case DBCOOL_25VIN:
1082 1.1 pgoyette val = v1;
1083 1.1 pgoyette break;
1084 1.2 pgoyette case DBCOOL_VCCP:
1085 1.1 pgoyette val = v2;
1086 1.1 pgoyette ext >>= 2;
1087 1.1 pgoyette break;
1088 1.2 pgoyette case DBCOOL_VCC:
1089 1.1 pgoyette val = v3;
1090 1.1 pgoyette ext >>= 4;
1091 1.1 pgoyette break;
1092 1.1 pgoyette case DBCOOL_5VIN:
1093 1.1 pgoyette val = v4;
1094 1.1 pgoyette ext >>= 6;
1095 1.1 pgoyette break;
1096 1.1 pgoyette default:
1097 1.1 pgoyette val = nom = 0;
1098 1.1 pgoyette }
1099 1.1 pgoyette ext &= 0x03;
1100 1.1 pgoyette }
1101 1.1 pgoyette
1102 1.1 pgoyette /*
1103 1.1 pgoyette * Scale the nominal value by the 10-bit fraction
1104 1.2 pgoyette *
1105 1.1 pgoyette * Returned value is in microvolts.
1106 1.1 pgoyette */
1107 1.2 pgoyette ret = val;
1108 1.2 pgoyette ret <<= 2;
1109 1.2 pgoyette ret |= ext;
1110 1.1 pgoyette ret = (ret * nom) / 0x300;
1111 1.1 pgoyette
1112 1.1 pgoyette return ret;
1113 1.1 pgoyette }
1114 1.1 pgoyette
1115 1.1 pgoyette SYSCTL_SETUP(sysctl_dbcoolsetup, "sysctl dBCool subtree setup")
1116 1.1 pgoyette {
1117 1.33 pgoyette sysctl_createv(clog, 0, NULL, NULL,
1118 1.1 pgoyette CTLFLAG_PERMANENT,
1119 1.1 pgoyette CTLTYPE_NODE, "hw", NULL,
1120 1.1 pgoyette NULL, 0, NULL, 0,
1121 1.1 pgoyette CTL_HW, CTL_EOL);
1122 1.1 pgoyette }
1123 1.1 pgoyette
1124 1.1 pgoyette static int
1125 1.2 pgoyette sysctl_dbcool_temp(SYSCTLFN_ARGS)
1126 1.1 pgoyette {
1127 1.1 pgoyette struct sysctlnode node;
1128 1.1 pgoyette struct dbcool_softc *sc;
1129 1.1 pgoyette int reg, error;
1130 1.1 pgoyette uint8_t chipreg;
1131 1.1 pgoyette uint8_t newreg;
1132 1.1 pgoyette
1133 1.1 pgoyette node = *rnode;
1134 1.1 pgoyette sc = (struct dbcool_softc *)node.sysctl_data;
1135 1.2 pgoyette chipreg = node.sysctl_num & 0xff;
1136 1.1 pgoyette
1137 1.1 pgoyette if (sc->sc_temp_offset) {
1138 1.13 christos reg = sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg);
1139 1.1 pgoyette reg -= sc->sc_temp_offset;
1140 1.1 pgoyette } else
1141 1.13 christos reg = (int8_t)sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg);
1142 1.1 pgoyette
1143 1.1 pgoyette node.sysctl_data = ®
1144 1.1 pgoyette error = sysctl_lookup(SYSCTLFN_CALL(&node));
1145 1.1 pgoyette
1146 1.1 pgoyette if (error || newp == NULL)
1147 1.1 pgoyette return error;
1148 1.1 pgoyette
1149 1.1 pgoyette /* We were asked to update the value - sanity check before writing */
1150 1.1 pgoyette if (*(int *)node.sysctl_data < -64 ||
1151 1.1 pgoyette *(int *)node.sysctl_data > 127 + sc->sc_temp_offset)
1152 1.1 pgoyette return EINVAL;
1153 1.1 pgoyette
1154 1.1 pgoyette newreg = *(int *)node.sysctl_data;
1155 1.1 pgoyette newreg += sc->sc_temp_offset;
1156 1.13 christos sc->sc_dc.dc_writereg(&sc->sc_dc, chipreg, newreg);
1157 1.1 pgoyette return 0;
1158 1.1 pgoyette }
1159 1.1 pgoyette
1160 1.1 pgoyette static int
1161 1.2 pgoyette sysctl_adm1030_temp(SYSCTLFN_ARGS)
1162 1.1 pgoyette {
1163 1.1 pgoyette struct sysctlnode node;
1164 1.1 pgoyette struct dbcool_softc *sc;
1165 1.1 pgoyette int reg, error;
1166 1.1 pgoyette uint8_t chipreg, oldreg, newreg;
1167 1.1 pgoyette
1168 1.1 pgoyette node = *rnode;
1169 1.1 pgoyette sc = (struct dbcool_softc *)node.sysctl_data;
1170 1.2 pgoyette chipreg = node.sysctl_num & 0xff;
1171 1.1 pgoyette
1172 1.13 christos oldreg = (int8_t)sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg);
1173 1.1 pgoyette reg = (oldreg >> 1) & ~0x03;
1174 1.1 pgoyette
1175 1.1 pgoyette node.sysctl_data = ®
1176 1.1 pgoyette error = sysctl_lookup(SYSCTLFN_CALL(&node));
1177 1.1 pgoyette
1178 1.1 pgoyette if (error || newp == NULL)
1179 1.1 pgoyette return error;
1180 1.1 pgoyette
1181 1.1 pgoyette /* We were asked to update the value - sanity check before writing */
1182 1.1 pgoyette if (*(int *)node.sysctl_data < 0 || *(int *)node.sysctl_data > 127)
1183 1.1 pgoyette return EINVAL;
1184 1.1 pgoyette
1185 1.1 pgoyette newreg = *(int *)node.sysctl_data;
1186 1.1 pgoyette newreg &= ~0x03;
1187 1.1 pgoyette newreg <<= 1;
1188 1.1 pgoyette newreg |= (oldreg & 0x07);
1189 1.13 christos sc->sc_dc.dc_writereg(&sc->sc_dc, chipreg, newreg);
1190 1.1 pgoyette return 0;
1191 1.1 pgoyette }
1192 1.1 pgoyette
1193 1.1 pgoyette static int
1194 1.1 pgoyette sysctl_adm1030_trange(SYSCTLFN_ARGS)
1195 1.1 pgoyette {
1196 1.1 pgoyette struct sysctlnode node;
1197 1.1 pgoyette struct dbcool_softc *sc;
1198 1.1 pgoyette int reg, error, newval;
1199 1.1 pgoyette uint8_t chipreg, oldreg, newreg;
1200 1.1 pgoyette
1201 1.1 pgoyette node = *rnode;
1202 1.1 pgoyette sc = (struct dbcool_softc *)node.sysctl_data;
1203 1.2 pgoyette chipreg = node.sysctl_num & 0xff;
1204 1.1 pgoyette
1205 1.13 christos oldreg = (int8_t)sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg);
1206 1.1 pgoyette reg = oldreg & 0x07;
1207 1.1 pgoyette
1208 1.1 pgoyette node.sysctl_data = ®
1209 1.1 pgoyette error = sysctl_lookup(SYSCTLFN_CALL(&node));
1210 1.1 pgoyette
1211 1.1 pgoyette if (error || newp == NULL)
1212 1.1 pgoyette return error;
1213 1.1 pgoyette
1214 1.1 pgoyette /* We were asked to update the value - sanity check before writing */
1215 1.1 pgoyette newval = *(int *)node.sysctl_data;
1216 1.1 pgoyette
1217 1.1 pgoyette if (newval == 5)
1218 1.1 pgoyette newreg = 0;
1219 1.1 pgoyette else if (newval == 10)
1220 1.1 pgoyette newreg = 1;
1221 1.1 pgoyette else if (newval == 20)
1222 1.1 pgoyette newreg = 2;
1223 1.1 pgoyette else if (newval == 40)
1224 1.1 pgoyette newreg = 3;
1225 1.1 pgoyette else if (newval == 80)
1226 1.1 pgoyette newreg = 4;
1227 1.1 pgoyette else
1228 1.1 pgoyette return EINVAL;
1229 1.1 pgoyette
1230 1.1 pgoyette newreg |= (oldreg & ~0x07);
1231 1.13 christos sc->sc_dc.dc_writereg(&sc->sc_dc, chipreg, newreg);
1232 1.1 pgoyette return 0;
1233 1.1 pgoyette }
1234 1.1 pgoyette
1235 1.1 pgoyette static int
1236 1.1 pgoyette sysctl_dbcool_duty(SYSCTLFN_ARGS)
1237 1.1 pgoyette {
1238 1.1 pgoyette struct sysctlnode node;
1239 1.1 pgoyette struct dbcool_softc *sc;
1240 1.1 pgoyette int reg, error;
1241 1.1 pgoyette uint8_t chipreg, oldreg, newreg;
1242 1.1 pgoyette
1243 1.1 pgoyette node = *rnode;
1244 1.1 pgoyette sc = (struct dbcool_softc *)node.sysctl_data;
1245 1.2 pgoyette chipreg = node.sysctl_num & 0xff;
1246 1.1 pgoyette
1247 1.13 christos oldreg = sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg);
1248 1.1 pgoyette reg = (uint32_t)oldreg;
1249 1.13 christos if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADM1030)
1250 1.1 pgoyette reg = ((reg & 0x0f) * 100) / 15;
1251 1.1 pgoyette else
1252 1.1 pgoyette reg = (reg * 100) / 255;
1253 1.1 pgoyette node.sysctl_data = ®
1254 1.1 pgoyette error = sysctl_lookup(SYSCTLFN_CALL(&node));
1255 1.1 pgoyette
1256 1.1 pgoyette if (error || newp == NULL)
1257 1.1 pgoyette return error;
1258 1.1 pgoyette
1259 1.1 pgoyette /* We were asked to update the value - sanity check before writing */
1260 1.1 pgoyette if (*(int *)node.sysctl_data < 0 || *(int *)node.sysctl_data > 100)
1261 1.1 pgoyette return EINVAL;
1262 1.1 pgoyette
1263 1.13 christos if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADM1030) {
1264 1.1 pgoyette newreg = *(uint8_t *)(node.sysctl_data) * 15 / 100;
1265 1.1 pgoyette newreg |= oldreg & 0xf0;
1266 1.1 pgoyette } else
1267 1.1 pgoyette newreg = *(uint8_t *)(node.sysctl_data) * 255 / 100;
1268 1.13 christos sc->sc_dc.dc_writereg(&sc->sc_dc, chipreg, newreg);
1269 1.1 pgoyette return 0;
1270 1.1 pgoyette }
1271 1.1 pgoyette
1272 1.1 pgoyette static int
1273 1.1 pgoyette sysctl_dbcool_behavior(SYSCTLFN_ARGS)
1274 1.1 pgoyette {
1275 1.1 pgoyette struct sysctlnode node;
1276 1.1 pgoyette struct dbcool_softc *sc;
1277 1.1 pgoyette int i, reg, error;
1278 1.1 pgoyette uint8_t chipreg, oldreg, newreg;
1279 1.1 pgoyette
1280 1.1 pgoyette node = *rnode;
1281 1.1 pgoyette sc = (struct dbcool_softc *)node.sysctl_data;
1282 1.2 pgoyette chipreg = node.sysctl_num & 0xff;
1283 1.1 pgoyette
1284 1.13 christos oldreg = sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg);
1285 1.2 pgoyette
1286 1.13 christos if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADM1030) {
1287 1.13 christos if ((sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_ADM1030_CFG2) & 1) == 0)
1288 1.1 pgoyette reg = 4;
1289 1.1 pgoyette else if ((oldreg & 0x80) == 0)
1290 1.1 pgoyette reg = 7;
1291 1.1 pgoyette else if ((oldreg & 0x60) == 0)
1292 1.1 pgoyette reg = 4;
1293 1.1 pgoyette else
1294 1.1 pgoyette reg = 6;
1295 1.1 pgoyette } else
1296 1.1 pgoyette reg = (oldreg >> 5) & 0x07;
1297 1.1 pgoyette
1298 1.1 pgoyette strlcpy(dbcool_cur_behav, behavior[reg], sizeof(dbcool_cur_behav));
1299 1.1 pgoyette node.sysctl_data = dbcool_cur_behav;
1300 1.1 pgoyette error = sysctl_lookup(SYSCTLFN_CALL(&node));
1301 1.1 pgoyette
1302 1.1 pgoyette if (error || newp == NULL)
1303 1.1 pgoyette return error;
1304 1.1 pgoyette
1305 1.1 pgoyette /* We were asked to update the value - convert string to value */
1306 1.1 pgoyette newreg = __arraycount(behavior);
1307 1.1 pgoyette for (i = 0; i < __arraycount(behavior); i++)
1308 1.1 pgoyette if (strcmp(node.sysctl_data, behavior[i]) == 0)
1309 1.1 pgoyette break;
1310 1.1 pgoyette if (i >= __arraycount(behavior))
1311 1.1 pgoyette return EINVAL;
1312 1.1 pgoyette
1313 1.13 christos if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADM1030) {
1314 1.1 pgoyette /*
1315 1.1 pgoyette * ADM1030 splits fan controller behavior across two
1316 1.1 pgoyette * registers. We also do not support Auto-Filter mode
1317 1.1 pgoyette * nor do we support Manual-RPM-feedback.
1318 1.1 pgoyette */
1319 1.1 pgoyette if (newreg == 4) {
1320 1.13 christos oldreg = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_ADM1030_CFG2);
1321 1.1 pgoyette oldreg &= ~0x01;
1322 1.13 christos sc->sc_dc.dc_writereg(&sc->sc_dc, DBCOOL_ADM1030_CFG2, oldreg);
1323 1.1 pgoyette } else {
1324 1.1 pgoyette if (newreg == 0)
1325 1.1 pgoyette newreg = 4;
1326 1.1 pgoyette else if (newreg == 6)
1327 1.1 pgoyette newreg = 7;
1328 1.1 pgoyette else if (newreg == 7)
1329 1.1 pgoyette newreg = 0;
1330 1.1 pgoyette else
1331 1.1 pgoyette return EINVAL;
1332 1.1 pgoyette newreg <<= 5;
1333 1.1 pgoyette newreg |= (oldreg & 0x1f);
1334 1.13 christos sc->sc_dc.dc_writereg(&sc->sc_dc, chipreg, newreg);
1335 1.13 christos oldreg = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_ADM1030_CFG2) | 1;
1336 1.13 christos sc->sc_dc.dc_writereg(&sc->sc_dc, DBCOOL_ADM1030_CFG2, oldreg);
1337 1.1 pgoyette }
1338 1.1 pgoyette } else {
1339 1.13 christos newreg = (sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg) & 0x1f) | (i << 5);
1340 1.13 christos sc->sc_dc.dc_writereg(&sc->sc_dc, chipreg, newreg);
1341 1.1 pgoyette }
1342 1.1 pgoyette return 0;
1343 1.1 pgoyette }
1344 1.1 pgoyette
1345 1.1 pgoyette static int
1346 1.2 pgoyette sysctl_dbcool_slope(SYSCTLFN_ARGS)
1347 1.1 pgoyette {
1348 1.1 pgoyette struct sysctlnode node;
1349 1.1 pgoyette struct dbcool_softc *sc;
1350 1.1 pgoyette int reg, error;
1351 1.1 pgoyette uint8_t chipreg;
1352 1.1 pgoyette uint8_t newreg;
1353 1.1 pgoyette
1354 1.1 pgoyette node = *rnode;
1355 1.1 pgoyette sc = (struct dbcool_softc *)node.sysctl_data;
1356 1.2 pgoyette chipreg = node.sysctl_num & 0xff;
1357 1.1 pgoyette
1358 1.13 christos reg = (sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg) >> 4) & 0x0f;
1359 1.1 pgoyette node.sysctl_data = ®
1360 1.1 pgoyette error = sysctl_lookup(SYSCTLFN_CALL(&node));
1361 1.1 pgoyette
1362 1.1 pgoyette if (error || newp == NULL)
1363 1.1 pgoyette return error;
1364 1.1 pgoyette
1365 1.1 pgoyette /* We were asked to update the value - sanity check before writing */
1366 1.1 pgoyette if (*(int *)node.sysctl_data < 0 || *(int *)node.sysctl_data > 0x0f)
1367 1.1 pgoyette return EINVAL;
1368 1.1 pgoyette
1369 1.13 christos newreg = (sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg) & 0x0f) |
1370 1.1 pgoyette (*(int *)node.sysctl_data << 4);
1371 1.13 christos sc->sc_dc.dc_writereg(&sc->sc_dc, chipreg, newreg);
1372 1.1 pgoyette return 0;
1373 1.1 pgoyette }
1374 1.1 pgoyette
1375 1.1 pgoyette static int
1376 1.1 pgoyette sysctl_dbcool_thyst(SYSCTLFN_ARGS)
1377 1.1 pgoyette {
1378 1.1 pgoyette struct sysctlnode node;
1379 1.1 pgoyette struct dbcool_softc *sc;
1380 1.1 pgoyette int reg, error;
1381 1.1 pgoyette uint8_t chipreg;
1382 1.1 pgoyette uint8_t newreg, newhyst;
1383 1.1 pgoyette
1384 1.1 pgoyette node = *rnode;
1385 1.1 pgoyette sc = (struct dbcool_softc *)node.sysctl_data;
1386 1.1 pgoyette chipreg = node.sysctl_num & 0x7f;
1387 1.1 pgoyette
1388 1.1 pgoyette /* retrieve 4-bit value */
1389 1.13 christos newreg = sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg);
1390 1.1 pgoyette if ((node.sysctl_num & 0x80) == 0)
1391 1.1 pgoyette reg = newreg >> 4;
1392 1.1 pgoyette else
1393 1.1 pgoyette reg = newreg;
1394 1.1 pgoyette reg = reg & 0x0f;
1395 1.1 pgoyette
1396 1.1 pgoyette node.sysctl_data = ®
1397 1.1 pgoyette error = sysctl_lookup(SYSCTLFN_CALL(&node));
1398 1.1 pgoyette
1399 1.1 pgoyette if (error || newp == NULL)
1400 1.1 pgoyette return error;
1401 1.1 pgoyette
1402 1.1 pgoyette /* We were asked to update the value - sanity check before writing */
1403 1.1 pgoyette newhyst = *(int *)node.sysctl_data;
1404 1.1 pgoyette if (newhyst > 0x0f)
1405 1.1 pgoyette return EINVAL;
1406 1.1 pgoyette
1407 1.1 pgoyette /* Insert new value into field and update register */
1408 1.1 pgoyette if ((node.sysctl_num & 0x80) == 0) {
1409 1.1 pgoyette newreg &= 0x0f;
1410 1.1 pgoyette newreg |= (newhyst << 4);
1411 1.1 pgoyette } else {
1412 1.1 pgoyette newreg &= 0xf0;
1413 1.1 pgoyette newreg |= newhyst;
1414 1.1 pgoyette }
1415 1.13 christos sc->sc_dc.dc_writereg(&sc->sc_dc, chipreg, newreg);
1416 1.1 pgoyette return 0;
1417 1.1 pgoyette }
1418 1.1 pgoyette
1419 1.1 pgoyette #ifdef DBCOOL_DEBUG
1420 1.1 pgoyette
1421 1.1 pgoyette /*
1422 1.1 pgoyette * These routines can be used for debugging. reg_select is used to
1423 1.1 pgoyette * select any arbitrary register in the device. reg_access is used
1424 1.1 pgoyette * to read (and optionally update) the selected register.
1425 1.1 pgoyette *
1426 1.1 pgoyette * No attempt is made to validate the data passed. If you use these
1427 1.1 pgoyette * routines, you are assumed to know what you're doing!
1428 1.1 pgoyette *
1429 1.1 pgoyette * Caveat user
1430 1.1 pgoyette */
1431 1.1 pgoyette static int
1432 1.1 pgoyette sysctl_dbcool_reg_select(SYSCTLFN_ARGS)
1433 1.1 pgoyette {
1434 1.1 pgoyette struct sysctlnode node;
1435 1.1 pgoyette struct dbcool_softc *sc;
1436 1.1 pgoyette int reg, error;
1437 1.1 pgoyette
1438 1.1 pgoyette node = *rnode;
1439 1.1 pgoyette sc = (struct dbcool_softc *)node.sysctl_data;
1440 1.1 pgoyette
1441 1.1 pgoyette reg = sc->sc_user_reg;
1442 1.1 pgoyette node.sysctl_data = ®
1443 1.1 pgoyette error = sysctl_lookup(SYSCTLFN_CALL(&node));
1444 1.1 pgoyette
1445 1.1 pgoyette if (error || newp == NULL)
1446 1.1 pgoyette return error;
1447 1.1 pgoyette
1448 1.1 pgoyette sc->sc_user_reg = *(int *)node.sysctl_data;
1449 1.1 pgoyette return 0;
1450 1.1 pgoyette }
1451 1.1 pgoyette
1452 1.1 pgoyette static int
1453 1.1 pgoyette sysctl_dbcool_reg_access(SYSCTLFN_ARGS)
1454 1.1 pgoyette {
1455 1.1 pgoyette struct sysctlnode node;
1456 1.1 pgoyette struct dbcool_softc *sc;
1457 1.1 pgoyette int reg, error;
1458 1.1 pgoyette uint8_t chipreg;
1459 1.1 pgoyette uint8_t newreg;
1460 1.1 pgoyette
1461 1.1 pgoyette node = *rnode;
1462 1.1 pgoyette sc = (struct dbcool_softc *)node.sysctl_data;
1463 1.1 pgoyette chipreg = sc->sc_user_reg;
1464 1.1 pgoyette
1465 1.13 christos reg = sc->sc_dc.dc_readreg(&sc->sc_dc, chipreg);
1466 1.1 pgoyette node.sysctl_data = ®
1467 1.1 pgoyette error = sysctl_lookup(SYSCTLFN_CALL(&node));
1468 1.1 pgoyette
1469 1.1 pgoyette if (error || newp == NULL)
1470 1.1 pgoyette return error;
1471 1.1 pgoyette
1472 1.1 pgoyette newreg = *(int *)node.sysctl_data;
1473 1.13 christos sc->sc_dc.dc_writereg(&sc->sc_dc, chipreg, newreg);
1474 1.1 pgoyette return 0;
1475 1.1 pgoyette }
1476 1.1 pgoyette #endif /* DBCOOL_DEBUG */
1477 1.1 pgoyette
1478 1.1 pgoyette /*
1479 1.2 pgoyette * Encode an index number and register number for use as a sysctl_num
1480 1.2 pgoyette * so we can select the correct device register later.
1481 1.1 pgoyette */
1482 1.2 pgoyette #define DBC_PWM_SYSCTL(seq, reg) ((seq << 8) | reg)
1483 1.1 pgoyette
1484 1.1 pgoyette void
1485 1.1 pgoyette dbcool_setup(device_t self)
1486 1.1 pgoyette {
1487 1.1 pgoyette struct dbcool_softc *sc = device_private(self);
1488 1.1 pgoyette const struct sysctlnode *me = NULL;
1489 1.17 pgoyette #ifdef DBCOOL_DEBUG
1490 1.1 pgoyette struct sysctlnode *node = NULL;
1491 1.17 pgoyette #endif
1492 1.1 pgoyette uint8_t cfg_val, cfg_reg;
1493 1.18 pgoyette int ret, error;
1494 1.1 pgoyette
1495 1.1 pgoyette /*
1496 1.1 pgoyette * Some chips are capable of reporting an extended temperature range
1497 1.1 pgoyette * by default. On these models, config register 5 bit 0 can be set
1498 1.1 pgoyette * to 1 for compatability with other chips that report 2s complement.
1499 1.1 pgoyette */
1500 1.13 christos if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADT7466) {
1501 1.13 christos if (sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_ADT7466_CONFIG1) & 0x80)
1502 1.1 pgoyette sc->sc_temp_offset = 64;
1503 1.1 pgoyette else
1504 1.1 pgoyette sc->sc_temp_offset = 0;
1505 1.13 christos } else if (sc->sc_dc.dc_chip->flags & DBCFLAG_TEMPOFFSET) {
1506 1.13 christos if (sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_CONFIG5_REG) &
1507 1.1 pgoyette DBCOOL_CFG5_TWOSCOMP)
1508 1.1 pgoyette sc->sc_temp_offset = 0;
1509 1.1 pgoyette else
1510 1.1 pgoyette sc->sc_temp_offset = 64;
1511 1.1 pgoyette } else
1512 1.1 pgoyette sc->sc_temp_offset = 0;
1513 1.1 pgoyette
1514 1.2 pgoyette /* Determine Vcc for this chip */
1515 1.2 pgoyette sc->sc_supply_voltage = dbcool_supply_voltage(sc);
1516 1.2 pgoyette
1517 1.33 pgoyette ret = sysctl_createv(&sc->sc_sysctl_log, 0, NULL, &me,
1518 1.2 pgoyette CTLFLAG_READWRITE,
1519 1.1 pgoyette CTLTYPE_NODE, device_xname(self), NULL,
1520 1.1 pgoyette NULL, 0, NULL, 0,
1521 1.1 pgoyette CTL_HW, CTL_CREATE, CTL_EOL);
1522 1.18 pgoyette if (ret == 0)
1523 1.18 pgoyette sc->sc_root_sysctl_num = me->sysctl_num;
1524 1.18 pgoyette else
1525 1.18 pgoyette sc->sc_root_sysctl_num = 0;
1526 1.18 pgoyette
1527 1.20 pgoyette aprint_debug_dev(self,
1528 1.20 pgoyette "Supply voltage %"PRId64".%06"PRId64"V, %s temp range\n",
1529 1.19 pgoyette sc->sc_supply_voltage / 1000000,
1530 1.19 pgoyette sc->sc_supply_voltage % 1000000,
1531 1.19 pgoyette sc->sc_temp_offset ? "extended" : "normal");
1532 1.19 pgoyette
1533 1.18 pgoyette /* Create the sensors for this device */
1534 1.18 pgoyette sc->sc_sme = sysmon_envsys_create();
1535 1.18 pgoyette if (dbcool_setup_sensors(sc))
1536 1.18 pgoyette goto out;
1537 1.18 pgoyette
1538 1.18 pgoyette if (sc->sc_root_sysctl_num != 0) {
1539 1.18 pgoyette /* If supported, create sysctl tree for fan PWM controllers */
1540 1.18 pgoyette if (sc->sc_dc.dc_chip->power != NULL)
1541 1.18 pgoyette dbcool_setup_controllers(sc);
1542 1.1 pgoyette
1543 1.1 pgoyette #ifdef DBCOOL_DEBUG
1544 1.33 pgoyette ret = sysctl_createv(&sc->sc_sysctl_log, 0, NULL,
1545 1.18 pgoyette (const struct sysctlnode **)&node,
1546 1.18 pgoyette CTLFLAG_READWRITE, CTLTYPE_INT, "reg_select", NULL,
1547 1.18 pgoyette sysctl_dbcool_reg_select,
1548 1.18 pgoyette 0, sc, sizeof(int),
1549 1.18 pgoyette CTL_HW, me->sysctl_num, CTL_CREATE, CTL_EOL);
1550 1.18 pgoyette if (node != NULL)
1551 1.18 pgoyette node->sysctl_data = sc;
1552 1.1 pgoyette
1553 1.33 pgoyette ret = sysctl_createv(&sc->sc_sysctl_log, 0, NULL,
1554 1.18 pgoyette (const struct sysctlnode **)&node,
1555 1.18 pgoyette CTLFLAG_READWRITE, CTLTYPE_INT, "reg_access", NULL,
1556 1.18 pgoyette sysctl_dbcool_reg_access,
1557 1.18 pgoyette 0, sc, sizeof(int),
1558 1.18 pgoyette CTL_HW, me->sysctl_num, CTL_CREATE, CTL_EOL);
1559 1.18 pgoyette if (node != NULL)
1560 1.18 pgoyette node->sysctl_data = sc;
1561 1.1 pgoyette #endif /* DBCOOL_DEBUG */
1562 1.18 pgoyette }
1563 1.2 pgoyette
1564 1.2 pgoyette /*
1565 1.2 pgoyette * Read and rewrite config register to activate device
1566 1.2 pgoyette */
1567 1.13 christos if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADM1030)
1568 1.2 pgoyette cfg_reg = DBCOOL_ADM1030_CFG1;
1569 1.13 christos else if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADT7466)
1570 1.2 pgoyette cfg_reg = DBCOOL_ADT7466_CONFIG1;
1571 1.2 pgoyette else
1572 1.2 pgoyette cfg_reg = DBCOOL_CONFIG1_REG;
1573 1.13 christos cfg_val = sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_CONFIG1_REG);
1574 1.2 pgoyette if ((cfg_val & DBCOOL_CFG1_START) == 0) {
1575 1.2 pgoyette cfg_val |= DBCOOL_CFG1_START;
1576 1.13 christos sc->sc_dc.dc_writereg(&sc->sc_dc, cfg_reg, cfg_val);
1577 1.2 pgoyette }
1578 1.2 pgoyette if (dbcool_islocked(sc))
1579 1.2 pgoyette aprint_normal_dev(self, "configuration locked\n");
1580 1.2 pgoyette
1581 1.2 pgoyette sc->sc_sme->sme_name = device_xname(self);
1582 1.2 pgoyette sc->sc_sme->sme_cookie = sc;
1583 1.2 pgoyette sc->sc_sme->sme_refresh = dbcool_refresh;
1584 1.18 pgoyette sc->sc_sme->sme_set_limits = dbcool_set_limits;
1585 1.18 pgoyette sc->sc_sme->sme_get_limits = dbcool_get_limits;
1586 1.2 pgoyette
1587 1.2 pgoyette if ((error = sysmon_envsys_register(sc->sc_sme)) != 0) {
1588 1.2 pgoyette aprint_error_dev(self,
1589 1.2 pgoyette "unable to register with sysmon (%d)\n", error);
1590 1.2 pgoyette goto out;
1591 1.2 pgoyette }
1592 1.2 pgoyette
1593 1.2 pgoyette return;
1594 1.2 pgoyette
1595 1.2 pgoyette out:
1596 1.2 pgoyette sysmon_envsys_destroy(sc->sc_sme);
1597 1.2 pgoyette }
1598 1.2 pgoyette
1599 1.2 pgoyette static int
1600 1.18 pgoyette dbcool_setup_sensors(struct dbcool_softc *sc)
1601 1.2 pgoyette {
1602 1.18 pgoyette int i;
1603 1.2 pgoyette int error = 0;
1604 1.18 pgoyette uint8_t vid_reg, vid_val;
1605 1.16 pgoyette struct chip_id *chip = sc->sc_dc.dc_chip;
1606 1.2 pgoyette
1607 1.16 pgoyette for (i=0; chip->table[i].type != DBC_EOF; i++) {
1608 1.18 pgoyette if (i < DBCOOL_MAXSENSORS)
1609 1.18 pgoyette sc->sc_sysctl_num[i] = -1;
1610 1.18 pgoyette else if (chip->table[i].type != DBC_CTL) {
1611 1.2 pgoyette aprint_normal_dev(sc->sc_dev, "chip table too big!\n");
1612 1.1 pgoyette break;
1613 1.1 pgoyette }
1614 1.16 pgoyette switch (chip->table[i].type) {
1615 1.1 pgoyette case DBC_TEMP:
1616 1.1 pgoyette sc->sc_sensor[i].units = ENVSYS_STEMP;
1617 1.30 pgoyette sc->sc_sensor[i].state = ENVSYS_SINVALID;
1618 1.16 pgoyette sc->sc_sensor[i].flags |= ENVSYS_FMONLIMITS;
1619 1.18 pgoyette error = dbcool_attach_sensor(sc, i);
1620 1.1 pgoyette break;
1621 1.1 pgoyette case DBC_VOLT:
1622 1.16 pgoyette /*
1623 1.16 pgoyette * If 12V-In pin has been reconfigured as 6th bit
1624 1.16 pgoyette * of VID code, don't create a 12V-In sensor
1625 1.16 pgoyette */
1626 1.16 pgoyette if ((chip->flags & DBCFLAG_HAS_VID_SEL) &&
1627 1.16 pgoyette (chip->table[i].reg.val_reg == DBCOOL_12VIN) &&
1628 1.16 pgoyette (sc->sc_dc.dc_readreg(&sc->sc_dc, DBCOOL_VID_REG) &
1629 1.16 pgoyette 0x80))
1630 1.16 pgoyette break;
1631 1.16 pgoyette
1632 1.1 pgoyette sc->sc_sensor[i].units = ENVSYS_SVOLTS_DC;
1633 1.30 pgoyette sc->sc_sensor[i].state = ENVSYS_SINVALID;
1634 1.16 pgoyette sc->sc_sensor[i].flags |= ENVSYS_FMONLIMITS;
1635 1.18 pgoyette error = dbcool_attach_sensor(sc, i);
1636 1.1 pgoyette break;
1637 1.1 pgoyette case DBC_FAN:
1638 1.1 pgoyette sc->sc_sensor[i].units = ENVSYS_SFANRPM;
1639 1.30 pgoyette sc->sc_sensor[i].state = ENVSYS_SINVALID;
1640 1.16 pgoyette sc->sc_sensor[i].flags |= ENVSYS_FMONLIMITS;
1641 1.18 pgoyette error = dbcool_attach_sensor(sc, i);
1642 1.1 pgoyette break;
1643 1.16 pgoyette case DBC_VID:
1644 1.16 pgoyette sc->sc_sensor[i].units = ENVSYS_INTEGER;
1645 1.30 pgoyette sc->sc_sensor[i].state = ENVSYS_SINVALID;
1646 1.16 pgoyette sc->sc_sensor[i].flags |= ENVSYS_FMONNOTSUPP;
1647 1.16 pgoyette
1648 1.16 pgoyette /* retrieve 5- or 6-bit value */
1649 1.16 pgoyette vid_reg = chip->table[i].reg.val_reg;
1650 1.16 pgoyette vid_val = sc->sc_dc.dc_readreg(&sc->sc_dc, vid_reg);
1651 1.16 pgoyette if (chip->flags & DBCFLAG_HAS_VID_SEL)
1652 1.16 pgoyette vid_val &= 0x3f;
1653 1.16 pgoyette else
1654 1.16 pgoyette vid_val &= 0x1f;
1655 1.16 pgoyette sc->sc_sensor[i].value_cur = vid_val;
1656 1.16 pgoyette
1657 1.18 pgoyette error = dbcool_attach_sensor(sc, i);
1658 1.16 pgoyette break;
1659 1.1 pgoyette case DBC_CTL:
1660 1.18 pgoyette error = dbcool_attach_temp_control(sc, i, chip);
1661 1.18 pgoyette if (error) {
1662 1.18 pgoyette aprint_error_dev(sc->sc_dev,
1663 1.18 pgoyette "attach index %d failed %d\n",
1664 1.18 pgoyette i, error);
1665 1.18 pgoyette error = 0;
1666 1.1 pgoyette }
1667 1.1 pgoyette break;
1668 1.1 pgoyette default:
1669 1.2 pgoyette aprint_error_dev(sc->sc_dev,
1670 1.2 pgoyette "sensor_table index %d has bad type %d\n",
1671 1.16 pgoyette i, chip->table[i].type);
1672 1.1 pgoyette break;
1673 1.1 pgoyette }
1674 1.2 pgoyette if (error)
1675 1.2 pgoyette break;
1676 1.2 pgoyette }
1677 1.2 pgoyette return error;
1678 1.2 pgoyette }
1679 1.1 pgoyette
1680 1.2 pgoyette static int
1681 1.18 pgoyette dbcool_attach_sensor(struct dbcool_softc *sc, int idx)
1682 1.2 pgoyette {
1683 1.2 pgoyette int name_index;
1684 1.2 pgoyette int error = 0;
1685 1.2 pgoyette
1686 1.13 christos name_index = sc->sc_dc.dc_chip->table[idx].name_index;
1687 1.2 pgoyette strlcpy(sc->sc_sensor[idx].desc, dbc_sensor_names[name_index],
1688 1.2 pgoyette sizeof(sc->sc_sensor[idx].desc));
1689 1.13 christos sc->sc_regs[idx] = &sc->sc_dc.dc_chip->table[idx].reg;
1690 1.13 christos sc->sc_nom_volt[idx] = sc->sc_dc.dc_chip->table[idx].nom_volt_index;
1691 1.2 pgoyette
1692 1.2 pgoyette error = sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[idx]);
1693 1.18 pgoyette return error;
1694 1.18 pgoyette }
1695 1.2 pgoyette
1696 1.18 pgoyette static int
1697 1.18 pgoyette dbcool_attach_temp_control(struct dbcool_softc *sc, int idx,
1698 1.18 pgoyette struct chip_id *chip)
1699 1.18 pgoyette {
1700 1.32 macallan const struct sysctlnode *me2 = NULL, *node;
1701 1.18 pgoyette int j, ret, sysctl_index, rw_flag;
1702 1.18 pgoyette uint8_t sysctl_reg;
1703 1.18 pgoyette char name[SYSCTL_NAMELEN];
1704 1.2 pgoyette
1705 1.18 pgoyette /* Search for the corresponding temp sensor */
1706 1.18 pgoyette for (j = 0; j < idx; j++) {
1707 1.18 pgoyette if (j >= DBCOOL_MAXSENSORS || chip->table[j].type != DBC_TEMP)
1708 1.18 pgoyette continue;
1709 1.18 pgoyette if (chip->table[j].name_index == chip->table[idx].name_index)
1710 1.18 pgoyette break;
1711 1.18 pgoyette }
1712 1.18 pgoyette if (j >= idx) /* Temp sensor not found */
1713 1.18 pgoyette return ENOENT;
1714 1.1 pgoyette
1715 1.18 pgoyette /* create sysctl node for the sensor if not one already there */
1716 1.18 pgoyette if (sc->sc_sysctl_num[j] == -1) {
1717 1.33 pgoyette ret = sysctl_createv(&sc->sc_sysctl_log, 0, NULL, &me2,
1718 1.33 pgoyette CTLFLAG_READWRITE,
1719 1.18 pgoyette CTLTYPE_NODE, sc->sc_sensor[j].desc, NULL,
1720 1.18 pgoyette NULL, 0, NULL, 0,
1721 1.18 pgoyette CTL_HW, sc->sc_root_sysctl_num, CTL_CREATE,
1722 1.18 pgoyette CTL_EOL);
1723 1.18 pgoyette if (me2 != NULL)
1724 1.18 pgoyette sc->sc_sysctl_num[j] = me2->sysctl_num;
1725 1.18 pgoyette else
1726 1.18 pgoyette return ret;
1727 1.18 pgoyette }
1728 1.18 pgoyette /* add sysctl leaf node for this control variable */
1729 1.18 pgoyette sysctl_index = chip->table[idx].sysctl_index;
1730 1.18 pgoyette sysctl_reg = chip->table[idx].reg.val_reg;
1731 1.18 pgoyette strlcpy(name, dbc_sysctl_table[sysctl_index].name, sizeof(name));
1732 1.18 pgoyette if (dbc_sysctl_table[sysctl_index].lockable && dbcool_islocked(sc))
1733 1.18 pgoyette rw_flag = CTLFLAG_READONLY | CTLFLAG_OWNDESC;
1734 1.18 pgoyette else
1735 1.18 pgoyette rw_flag = CTLFLAG_READWRITE | CTLFLAG_OWNDESC;
1736 1.33 pgoyette ret = sysctl_createv(&sc->sc_sysctl_log, 0, NULL, &node, rw_flag,
1737 1.18 pgoyette CTLTYPE_INT, name,
1738 1.25 pgoyette SYSCTL_DESCR(dbc_sysctl_table[sysctl_index].desc),
1739 1.18 pgoyette dbc_sysctl_table[sysctl_index].helper,
1740 1.18 pgoyette 0, sc, sizeof(int),
1741 1.18 pgoyette CTL_HW, sc->sc_root_sysctl_num,
1742 1.18 pgoyette sc->sc_sysctl_num[j],
1743 1.18 pgoyette DBC_PWM_SYSCTL(idx, sysctl_reg), CTL_EOL);
1744 1.2 pgoyette
1745 1.18 pgoyette return ret;
1746 1.2 pgoyette }
1747 1.2 pgoyette
1748 1.2 pgoyette static void
1749 1.18 pgoyette dbcool_setup_controllers(struct dbcool_softc *sc)
1750 1.2 pgoyette {
1751 1.18 pgoyette int i, j, ret, rw_flag;
1752 1.2 pgoyette uint8_t sysctl_reg;
1753 1.18 pgoyette struct chip_id *chip = sc->sc_dc.dc_chip;
1754 1.2 pgoyette const struct sysctlnode *me2 = NULL;
1755 1.32 macallan const struct sysctlnode *node = NULL;
1756 1.2 pgoyette char name[SYSCTL_NAMELEN];
1757 1.1 pgoyette
1758 1.18 pgoyette for (i = 0; chip->power[i].desc != NULL; i++) {
1759 1.2 pgoyette snprintf(name, sizeof(name), "fan_ctl_%d", i);
1760 1.33 pgoyette ret = sysctl_createv(&sc->sc_sysctl_log, 0, NULL, &me2,
1761 1.18 pgoyette CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
1762 1.2 pgoyette CTLTYPE_NODE, name, NULL,
1763 1.2 pgoyette NULL, 0, NULL, 0,
1764 1.18 pgoyette CTL_HW, sc->sc_root_sysctl_num, CTL_CREATE, CTL_EOL);
1765 1.1 pgoyette
1766 1.2 pgoyette for (j = DBC_PWM_BEHAVIOR; j < DBC_PWM_LAST_PARAM; j++) {
1767 1.2 pgoyette if (j == DBC_PWM_MAX_DUTY &&
1768 1.18 pgoyette (chip->flags & DBCFLAG_HAS_MAXDUTY) == 0)
1769 1.2 pgoyette continue;
1770 1.18 pgoyette sysctl_reg = chip->power[i].power_regs[j];
1771 1.2 pgoyette if (sysctl_reg == DBCOOL_NO_REG)
1772 1.2 pgoyette continue;
1773 1.2 pgoyette strlcpy(name, dbc_sysctl_table[j].name, sizeof(name));
1774 1.18 pgoyette if (dbc_sysctl_table[j].lockable && dbcool_islocked(sc))
1775 1.18 pgoyette rw_flag = CTLFLAG_READONLY | CTLFLAG_OWNDESC;
1776 1.18 pgoyette else
1777 1.18 pgoyette rw_flag = CTLFLAG_READWRITE | CTLFLAG_OWNDESC;
1778 1.33 pgoyette ret = sysctl_createv(&sc->sc_sysctl_log, 0, NULL,
1779 1.32 macallan &node, rw_flag,
1780 1.2 pgoyette (j == DBC_PWM_BEHAVIOR)?
1781 1.2 pgoyette CTLTYPE_STRING:CTLTYPE_INT,
1782 1.2 pgoyette name,
1783 1.25 pgoyette SYSCTL_DESCR(dbc_sysctl_table[j].desc),
1784 1.2 pgoyette dbc_sysctl_table[j].helper,
1785 1.2 pgoyette 0, sc,
1786 1.2 pgoyette ( j == DBC_PWM_BEHAVIOR)?
1787 1.2 pgoyette sizeof(dbcool_cur_behav): sizeof(int),
1788 1.18 pgoyette CTL_HW, sc->sc_root_sysctl_num, me2->sysctl_num,
1789 1.2 pgoyette DBC_PWM_SYSCTL(j, sysctl_reg), CTL_EOL);
1790 1.1 pgoyette }
1791 1.1 pgoyette }
1792 1.1 pgoyette }
1793 1.1 pgoyette
1794 1.1 pgoyette static void
1795 1.1 pgoyette dbcool_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
1796 1.1 pgoyette {
1797 1.1 pgoyette struct dbcool_softc *sc=sme->sme_cookie;
1798 1.18 pgoyette int i, nom_volt_idx, cur;
1799 1.1 pgoyette struct reg_list *reg;
1800 1.1 pgoyette
1801 1.1 pgoyette i = edata->sensor;
1802 1.1 pgoyette reg = sc->sc_regs[i];
1803 1.18 pgoyette
1804 1.18 pgoyette edata->state = ENVSYS_SVALID;
1805 1.1 pgoyette switch (edata->units)
1806 1.1 pgoyette {
1807 1.1 pgoyette case ENVSYS_STEMP:
1808 1.1 pgoyette cur = dbcool_read_temp(sc, reg->val_reg, true);
1809 1.1 pgoyette break;
1810 1.1 pgoyette case ENVSYS_SVOLTS_DC:
1811 1.2 pgoyette nom_volt_idx = sc->sc_nom_volt[i];
1812 1.2 pgoyette cur = dbcool_read_volt(sc, reg->val_reg, nom_volt_idx,
1813 1.2 pgoyette true);
1814 1.1 pgoyette break;
1815 1.1 pgoyette case ENVSYS_SFANRPM:
1816 1.1 pgoyette cur = dbcool_read_rpm(sc, reg->val_reg);
1817 1.1 pgoyette break;
1818 1.16 pgoyette case ENVSYS_INTEGER:
1819 1.16 pgoyette return;
1820 1.1 pgoyette default:
1821 1.1 pgoyette edata->state = ENVSYS_SINVALID;
1822 1.1 pgoyette return;
1823 1.1 pgoyette }
1824 1.1 pgoyette
1825 1.18 pgoyette if (cur == 0 && (edata->units != ENVSYS_SFANRPM))
1826 1.1 pgoyette edata->state = ENVSYS_SINVALID;
1827 1.1 pgoyette
1828 1.1 pgoyette /*
1829 1.1 pgoyette * If fan is "stalled" but has no low limit, treat
1830 1.1 pgoyette * it as though the fan is not installed.
1831 1.1 pgoyette */
1832 1.1 pgoyette else if (edata->units == ENVSYS_SFANRPM && cur == 0 &&
1833 1.18 pgoyette !(edata->upropset & (PROP_CRITMIN | PROP_WARNMIN)))
1834 1.1 pgoyette edata->state = ENVSYS_SINVALID;
1835 1.1 pgoyette
1836 1.1 pgoyette edata->value_cur = cur;
1837 1.1 pgoyette }
1838 1.1 pgoyette
1839 1.1 pgoyette int
1840 1.13 christos dbcool_chip_ident(struct dbcool_chipset *dc)
1841 1.1 pgoyette {
1842 1.1 pgoyette /* verify this is a supported dbCool chip */
1843 1.1 pgoyette uint8_t c_id, d_id, r_id;
1844 1.1 pgoyette int i;
1845 1.1 pgoyette
1846 1.13 christos c_id = dc->dc_readreg(dc, DBCOOL_COMPANYID_REG);
1847 1.13 christos d_id = dc->dc_readreg(dc, DBCOOL_DEVICEID_REG);
1848 1.13 christos r_id = dc->dc_readreg(dc, DBCOOL_REVISION_REG);
1849 1.27 pgoyette
1850 1.27 pgoyette /* The EMC6D103S only supports read_byte and since dc->dc_chip is
1851 1.27 pgoyette * NULL when we call dc->dc_readreg above we use
1852 1.28 pgoyette * send_byte/receive_byte which doesn't work.
1853 1.27 pgoyette *
1854 1.27 pgoyette * So if we only get 0's back then try again with dc->dc_chip
1855 1.29 pgoyette * set to the EMC6D103S_DEVICEID and which doesn't have
1856 1.27 pgoyette * DBCFLAG_NO_READBYTE set so read_byte will be used
1857 1.27 pgoyette */
1858 1.27 pgoyette if ((c_id == 0) && (d_id == 0) && (r_id == 0)) {
1859 1.27 pgoyette for (i = 0; chip_table[i].company != 0; i++)
1860 1.27 pgoyette if ((SMSC_COMPANYID == chip_table[i].company) &&
1861 1.27 pgoyette (EMC6D103S_DEVICEID == chip_table[i].device)) {
1862 1.27 pgoyette dc->dc_chip = &chip_table[i];
1863 1.27 pgoyette break;
1864 1.27 pgoyette }
1865 1.27 pgoyette c_id = dc->dc_readreg(dc, DBCOOL_COMPANYID_REG);
1866 1.27 pgoyette d_id = dc->dc_readreg(dc, DBCOOL_DEVICEID_REG);
1867 1.27 pgoyette r_id = dc->dc_readreg(dc, DBCOOL_REVISION_REG);
1868 1.27 pgoyette }
1869 1.27 pgoyette
1870 1.1 pgoyette for (i = 0; chip_table[i].company != 0; i++)
1871 1.1 pgoyette if ((c_id == chip_table[i].company) &&
1872 1.1 pgoyette (d_id == chip_table[i].device ||
1873 1.13 christos chip_table[i].device == 0xff) &&
1874 1.1 pgoyette (r_id == chip_table[i].rev ||
1875 1.13 christos chip_table[i].rev == 0xff)) {
1876 1.13 christos dc->dc_chip = &chip_table[i];
1877 1.1 pgoyette return i;
1878 1.1 pgoyette }
1879 1.1 pgoyette
1880 1.1 pgoyette aprint_verbose("dbcool_chip_ident: addr 0x%02x c_id 0x%02x d_id 0x%02x"
1881 1.13 christos " r_id 0x%02x: No match.\n", dc->dc_addr, c_id, d_id,
1882 1.1 pgoyette r_id);
1883 1.1 pgoyette
1884 1.1 pgoyette return -1;
1885 1.1 pgoyette }
1886 1.18 pgoyette
1887 1.18 pgoyette /*
1888 1.18 pgoyette * Retrieve sensor limits from the chip registers
1889 1.18 pgoyette */
1890 1.18 pgoyette static void
1891 1.18 pgoyette dbcool_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
1892 1.18 pgoyette sysmon_envsys_lim_t *limits, uint32_t *props)
1893 1.18 pgoyette {
1894 1.18 pgoyette int index = edata->sensor;
1895 1.18 pgoyette struct dbcool_softc *sc = sme->sme_cookie;
1896 1.18 pgoyette
1897 1.19 pgoyette *props &= ~(PROP_CRITMIN | PROP_CRITMAX);
1898 1.18 pgoyette switch (edata->units) {
1899 1.18 pgoyette case ENVSYS_STEMP:
1900 1.18 pgoyette dbcool_get_temp_limits(sc, index, limits, props);
1901 1.18 pgoyette break;
1902 1.18 pgoyette case ENVSYS_SVOLTS_DC:
1903 1.18 pgoyette dbcool_get_volt_limits(sc, index, limits, props);
1904 1.18 pgoyette break;
1905 1.18 pgoyette case ENVSYS_SFANRPM:
1906 1.18 pgoyette dbcool_get_fan_limits(sc, index, limits, props);
1907 1.18 pgoyette
1908 1.18 pgoyette /* FALLTHROUGH */
1909 1.18 pgoyette default:
1910 1.18 pgoyette break;
1911 1.18 pgoyette }
1912 1.18 pgoyette *props &= ~PROP_DRIVER_LIMITS;
1913 1.19 pgoyette
1914 1.19 pgoyette /* If both limits provided, make sure they're sane */
1915 1.19 pgoyette if ((*props & PROP_CRITMIN) &&
1916 1.19 pgoyette (*props & PROP_CRITMAX) &&
1917 1.19 pgoyette (limits->sel_critmin >= limits->sel_critmax))
1918 1.19 pgoyette *props &= ~(PROP_CRITMIN | PROP_CRITMAX);
1919 1.24 pgoyette
1920 1.24 pgoyette /*
1921 1.24 pgoyette * If this is the first time through, save these values
1922 1.24 pgoyette * in case user overrides them and then requests a reset.
1923 1.24 pgoyette */
1924 1.24 pgoyette if (sc->sc_defprops[index] == 0) {
1925 1.24 pgoyette sc->sc_defprops[index] = *props | PROP_DRIVER_LIMITS;
1926 1.24 pgoyette sc->sc_deflims[index] = *limits;
1927 1.24 pgoyette }
1928 1.18 pgoyette }
1929 1.18 pgoyette
1930 1.18 pgoyette static void
1931 1.18 pgoyette dbcool_get_temp_limits(struct dbcool_softc *sc, int idx,
1932 1.18 pgoyette sysmon_envsys_lim_t *lims, uint32_t *props)
1933 1.18 pgoyette {
1934 1.18 pgoyette struct reg_list *reg = sc->sc_regs[idx];
1935 1.19 pgoyette uint8_t lo_lim, hi_lim;
1936 1.19 pgoyette
1937 1.19 pgoyette lo_lim = sc->sc_dc.dc_readreg(&sc->sc_dc, reg->lo_lim_reg);
1938 1.19 pgoyette hi_lim = sc->sc_dc.dc_readreg(&sc->sc_dc, reg->hi_lim_reg);
1939 1.18 pgoyette
1940 1.18 pgoyette if (sc->sc_temp_offset) {
1941 1.19 pgoyette if (lo_lim > 0x01) {
1942 1.19 pgoyette lims->sel_critmin = lo_lim - sc->sc_temp_offset;
1943 1.19 pgoyette *props |= PROP_CRITMIN;
1944 1.19 pgoyette }
1945 1.19 pgoyette if (hi_lim != 0xff) {
1946 1.19 pgoyette lims->sel_critmax = hi_lim - sc->sc_temp_offset;
1947 1.19 pgoyette *props |= PROP_CRITMAX;
1948 1.19 pgoyette }
1949 1.19 pgoyette } else {
1950 1.19 pgoyette if (lo_lim != 0x80 && lo_lim != 0x81) {
1951 1.19 pgoyette lims->sel_critmin = (int8_t)lo_lim;
1952 1.19 pgoyette *props |= PROP_CRITMIN;
1953 1.19 pgoyette }
1954 1.18 pgoyette
1955 1.19 pgoyette if (hi_lim != 0x7f) {
1956 1.19 pgoyette lims->sel_critmax = (int8_t)hi_lim;
1957 1.19 pgoyette *props |= PROP_CRITMAX;
1958 1.19 pgoyette }
1959 1.19 pgoyette }
1960 1.18 pgoyette
1961 1.19 pgoyette /* Convert temp limits to microKelvin */
1962 1.19 pgoyette lims->sel_critmin *= 1000000;
1963 1.19 pgoyette lims->sel_critmin += 273150000;
1964 1.19 pgoyette lims->sel_critmax *= 1000000;
1965 1.19 pgoyette lims->sel_critmax += 273150000;
1966 1.18 pgoyette }
1967 1.18 pgoyette
1968 1.18 pgoyette static void
1969 1.18 pgoyette dbcool_get_volt_limits(struct dbcool_softc *sc, int idx,
1970 1.18 pgoyette sysmon_envsys_lim_t *lims, uint32_t *props)
1971 1.18 pgoyette {
1972 1.18 pgoyette struct reg_list *reg = sc->sc_regs[idx];
1973 1.18 pgoyette int64_t limit;
1974 1.18 pgoyette int nom;
1975 1.18 pgoyette
1976 1.18 pgoyette nom = nominal_voltages[sc->sc_dc.dc_chip->table[idx].nom_volt_index];
1977 1.18 pgoyette if (nom < 0)
1978 1.18 pgoyette nom = dbcool_supply_voltage(sc);
1979 1.18 pgoyette nom *= 1000000; /* scale for microvolts */
1980 1.18 pgoyette
1981 1.18 pgoyette limit = sc->sc_dc.dc_readreg(&sc->sc_dc, reg->lo_lim_reg);
1982 1.19 pgoyette if (limit != 0x00 && limit != 0xff) {
1983 1.18 pgoyette limit *= nom;
1984 1.18 pgoyette limit /= 0xc0;
1985 1.18 pgoyette lims->sel_critmin = limit;
1986 1.18 pgoyette *props |= PROP_CRITMIN;
1987 1.18 pgoyette }
1988 1.18 pgoyette limit = sc->sc_dc.dc_readreg(&sc->sc_dc, reg->hi_lim_reg);
1989 1.19 pgoyette if (limit != 0x00 && limit != 0xff) {
1990 1.18 pgoyette limit *= nom;
1991 1.18 pgoyette limit /= 0xc0;
1992 1.18 pgoyette lims->sel_critmax = limit;
1993 1.18 pgoyette *props |= PROP_CRITMAX;
1994 1.18 pgoyette }
1995 1.18 pgoyette }
1996 1.18 pgoyette
1997 1.18 pgoyette static void
1998 1.18 pgoyette dbcool_get_fan_limits(struct dbcool_softc *sc, int idx,
1999 1.18 pgoyette sysmon_envsys_lim_t *lims, uint32_t *props)
2000 1.18 pgoyette {
2001 1.18 pgoyette struct reg_list *reg = sc->sc_regs[idx];
2002 1.18 pgoyette int32_t limit;
2003 1.18 pgoyette
2004 1.18 pgoyette limit = dbcool_read_rpm(sc, reg->lo_lim_reg);
2005 1.18 pgoyette if (limit) {
2006 1.18 pgoyette lims->sel_critmin = limit;
2007 1.18 pgoyette *props |= PROP_CRITMIN;
2008 1.19 pgoyette }
2009 1.18 pgoyette }
2010 1.18 pgoyette
2011 1.18 pgoyette /*
2012 1.18 pgoyette * Update sensor limits in the chip registers
2013 1.18 pgoyette */
2014 1.18 pgoyette static void
2015 1.18 pgoyette dbcool_set_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
2016 1.18 pgoyette sysmon_envsys_lim_t *limits, uint32_t *props)
2017 1.18 pgoyette {
2018 1.18 pgoyette int index = edata->sensor;
2019 1.18 pgoyette struct dbcool_softc *sc = sme->sme_cookie;
2020 1.18 pgoyette
2021 1.24 pgoyette if (limits == NULL) {
2022 1.24 pgoyette limits = &sc->sc_deflims[index];
2023 1.24 pgoyette props = &sc->sc_defprops[index];
2024 1.24 pgoyette }
2025 1.18 pgoyette switch (edata->units) {
2026 1.18 pgoyette case ENVSYS_STEMP:
2027 1.18 pgoyette dbcool_set_temp_limits(sc, index, limits, props);
2028 1.18 pgoyette break;
2029 1.18 pgoyette case ENVSYS_SVOLTS_DC:
2030 1.18 pgoyette dbcool_set_volt_limits(sc, index, limits, props);
2031 1.18 pgoyette break;
2032 1.18 pgoyette case ENVSYS_SFANRPM:
2033 1.18 pgoyette dbcool_set_fan_limits(sc, index, limits, props);
2034 1.18 pgoyette
2035 1.18 pgoyette /* FALLTHROUGH */
2036 1.18 pgoyette default:
2037 1.18 pgoyette break;
2038 1.18 pgoyette }
2039 1.18 pgoyette *props &= ~PROP_DRIVER_LIMITS;
2040 1.18 pgoyette }
2041 1.18 pgoyette
2042 1.18 pgoyette static void
2043 1.18 pgoyette dbcool_set_temp_limits(struct dbcool_softc *sc, int idx,
2044 1.18 pgoyette sysmon_envsys_lim_t *lims, uint32_t *props)
2045 1.18 pgoyette {
2046 1.18 pgoyette struct reg_list *reg = sc->sc_regs[idx];
2047 1.18 pgoyette int32_t limit;
2048 1.18 pgoyette
2049 1.18 pgoyette if (*props & PROP_CRITMIN) {
2050 1.18 pgoyette limit = lims->sel_critmin - 273150000;
2051 1.18 pgoyette limit /= 1000000;
2052 1.19 pgoyette if (sc->sc_temp_offset) {
2053 1.19 pgoyette limit += sc->sc_temp_offset;
2054 1.19 pgoyette if (limit < 0)
2055 1.19 pgoyette limit = 0;
2056 1.19 pgoyette else if (limit > 255)
2057 1.19 pgoyette limit = 255;
2058 1.19 pgoyette } else {
2059 1.19 pgoyette if (limit < -127)
2060 1.19 pgoyette limit = -127;
2061 1.19 pgoyette else if (limit > 127)
2062 1.19 pgoyette limit = 127;
2063 1.19 pgoyette }
2064 1.24 pgoyette sc->sc_dc.dc_writereg(&sc->sc_dc, reg->lo_lim_reg,
2065 1.24 pgoyette (uint8_t)limit);
2066 1.24 pgoyette } else if (*props & PROP_DRIVER_LIMITS) {
2067 1.19 pgoyette if (sc->sc_temp_offset)
2068 1.19 pgoyette limit = 0x00;
2069 1.19 pgoyette else
2070 1.19 pgoyette limit = 0x80;
2071 1.24 pgoyette sc->sc_dc.dc_writereg(&sc->sc_dc, reg->lo_lim_reg,
2072 1.24 pgoyette (uint8_t)limit);
2073 1.24 pgoyette }
2074 1.18 pgoyette
2075 1.18 pgoyette if (*props & PROP_CRITMAX) {
2076 1.18 pgoyette limit = lims->sel_critmax - 273150000;
2077 1.18 pgoyette limit /= 1000000;
2078 1.19 pgoyette if (sc->sc_temp_offset) {
2079 1.19 pgoyette limit += sc->sc_temp_offset;
2080 1.19 pgoyette if (limit < 0)
2081 1.19 pgoyette limit = 0;
2082 1.19 pgoyette else if (limit > 255)
2083 1.19 pgoyette limit = 255;
2084 1.19 pgoyette } else {
2085 1.19 pgoyette if (limit < -127)
2086 1.19 pgoyette limit = -127;
2087 1.19 pgoyette else if (limit > 127)
2088 1.19 pgoyette limit = 127;
2089 1.19 pgoyette }
2090 1.24 pgoyette sc->sc_dc.dc_writereg(&sc->sc_dc, reg->hi_lim_reg,
2091 1.24 pgoyette (uint8_t)limit);
2092 1.24 pgoyette } else if (*props & PROP_DRIVER_LIMITS) {
2093 1.19 pgoyette if (sc->sc_temp_offset)
2094 1.18 pgoyette limit = 0xff;
2095 1.19 pgoyette else
2096 1.19 pgoyette limit = 0x7f;
2097 1.24 pgoyette sc->sc_dc.dc_writereg(&sc->sc_dc, reg->hi_lim_reg,
2098 1.24 pgoyette (uint8_t)limit);
2099 1.24 pgoyette }
2100 1.18 pgoyette }
2101 1.18 pgoyette
2102 1.18 pgoyette static void
2103 1.18 pgoyette dbcool_set_volt_limits(struct dbcool_softc *sc, int idx,
2104 1.18 pgoyette sysmon_envsys_lim_t *lims, uint32_t *props)
2105 1.18 pgoyette {
2106 1.18 pgoyette struct reg_list *reg = sc->sc_regs[idx];
2107 1.18 pgoyette int64_t limit;
2108 1.18 pgoyette int nom;
2109 1.18 pgoyette
2110 1.18 pgoyette nom = nominal_voltages[sc->sc_dc.dc_chip->table[idx].nom_volt_index];
2111 1.18 pgoyette if (nom < 0)
2112 1.18 pgoyette nom = dbcool_supply_voltage(sc);
2113 1.18 pgoyette nom *= 1000000; /* scale for microvolts */
2114 1.18 pgoyette
2115 1.18 pgoyette if (*props & PROP_CRITMIN) {
2116 1.18 pgoyette limit = lims->sel_critmin;
2117 1.18 pgoyette limit *= 0xc0;
2118 1.18 pgoyette limit /= nom;
2119 1.18 pgoyette if (limit > 0xff)
2120 1.18 pgoyette limit = 0xff;
2121 1.18 pgoyette else if (limit < 0)
2122 1.18 pgoyette limit = 0;
2123 1.24 pgoyette sc->sc_dc.dc_writereg(&sc->sc_dc, reg->lo_lim_reg, limit);
2124 1.24 pgoyette } else if (*props & PROP_DRIVER_LIMITS)
2125 1.24 pgoyette sc->sc_dc.dc_writereg(&sc->sc_dc, reg->lo_lim_reg, 0);
2126 1.18 pgoyette
2127 1.18 pgoyette if (*props & PROP_CRITMAX) {
2128 1.18 pgoyette limit = lims->sel_critmax;
2129 1.18 pgoyette limit *= 0xc0;
2130 1.18 pgoyette limit /= nom;
2131 1.18 pgoyette if (limit > 0xff)
2132 1.18 pgoyette limit = 0xff;
2133 1.18 pgoyette else if (limit < 0)
2134 1.18 pgoyette limit = 0;
2135 1.24 pgoyette sc->sc_dc.dc_writereg(&sc->sc_dc, reg->hi_lim_reg, limit);
2136 1.24 pgoyette } else if (*props & PROP_DRIVER_LIMITS)
2137 1.24 pgoyette sc->sc_dc.dc_writereg(&sc->sc_dc, reg->hi_lim_reg, 0xff);
2138 1.18 pgoyette }
2139 1.18 pgoyette
2140 1.18 pgoyette static void
2141 1.18 pgoyette dbcool_set_fan_limits(struct dbcool_softc *sc, int idx,
2142 1.18 pgoyette sysmon_envsys_lim_t *lims, uint32_t *props)
2143 1.18 pgoyette {
2144 1.18 pgoyette struct reg_list *reg = sc->sc_regs[idx];
2145 1.18 pgoyette int32_t limit, dividend;
2146 1.18 pgoyette
2147 1.18 pgoyette if (*props & PROP_CRITMIN) {
2148 1.18 pgoyette limit = lims->sel_critmin;
2149 1.18 pgoyette if (limit == 0)
2150 1.18 pgoyette limit = 0xffff;
2151 1.18 pgoyette else {
2152 1.18 pgoyette if (sc->sc_dc.dc_chip->flags & DBCFLAG_ADM1030)
2153 1.18 pgoyette dividend = 11250 * 60;
2154 1.18 pgoyette else
2155 1.18 pgoyette dividend = 90000 * 60;
2156 1.18 pgoyette limit = limit / dividend;
2157 1.18 pgoyette if (limit > 0xffff)
2158 1.18 pgoyette limit = 0xffff;
2159 1.18 pgoyette }
2160 1.24 pgoyette sc->sc_dc.dc_writereg(&sc->sc_dc, reg->lo_lim_reg,
2161 1.24 pgoyette limit & 0xff);
2162 1.24 pgoyette limit >>= 8;
2163 1.24 pgoyette sc->sc_dc.dc_writereg(&sc->sc_dc, reg->lo_lim_reg + 1,
2164 1.24 pgoyette limit & 0xff);
2165 1.24 pgoyette } else if (*props & PROP_DRIVER_LIMITS) {
2166 1.24 pgoyette sc->sc_dc.dc_writereg(&sc->sc_dc, reg->lo_lim_reg, 0xff);
2167 1.24 pgoyette sc->sc_dc.dc_writereg(&sc->sc_dc, reg->lo_lim_reg + 1, 0xff);
2168 1.24 pgoyette }
2169 1.18 pgoyette }
2170 1.31 jmcneill
2171 1.31 jmcneill MODULE(MODULE_CLASS_DRIVER, dbcool, NULL);
2172 1.31 jmcneill
2173 1.31 jmcneill #ifdef _MODULE
2174 1.31 jmcneill #include "ioconf.c"
2175 1.31 jmcneill #endif
2176 1.31 jmcneill
2177 1.31 jmcneill static int
2178 1.31 jmcneill dbcool_modcmd(modcmd_t cmd, void *opaque)
2179 1.31 jmcneill {
2180 1.31 jmcneill int error = 0;
2181 1.31 jmcneill
2182 1.31 jmcneill switch (cmd) {
2183 1.31 jmcneill case MODULE_CMD_INIT:
2184 1.31 jmcneill #ifdef _MODULE
2185 1.31 jmcneill error = config_init_component(cfdriver_ioconf_dbcool,
2186 1.31 jmcneill cfattach_ioconf_dbcool, cfdata_ioconf_dbcool);
2187 1.31 jmcneill #endif
2188 1.31 jmcneill return error;
2189 1.31 jmcneill case MODULE_CMD_FINI:
2190 1.31 jmcneill #ifdef _MODULE
2191 1.31 jmcneill error = config_fini_component(cfdriver_ioconf_dbcool,
2192 1.31 jmcneill cfattach_ioconf_dbcool, cfdata_ioconf_dbcool);
2193 1.31 jmcneill #endif
2194 1.31 jmcneill return error;
2195 1.31 jmcneill default:
2196 1.31 jmcneill return ENOTTY;
2197 1.31 jmcneill }
2198 1.31 jmcneill }
2199