emcfanctlutil.c revision 1.1 1 1.1 brad /* $NetBSD: emcfanctlutil.c,v 1.1 2025/03/11 13:56:48 brad Exp $ */
2 1.1 brad
3 1.1 brad /*
4 1.1 brad * Copyright (c) 2025 Brad Spencer <brad (at) anduin.eldar.org>
5 1.1 brad *
6 1.1 brad * Permission to use, copy, modify, and distribute this software for any
7 1.1 brad * purpose with or without fee is hereby granted, provided that the above
8 1.1 brad * copyright notice and this permission notice appear in all copies.
9 1.1 brad *
10 1.1 brad * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 1.1 brad * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 1.1 brad * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 1.1 brad * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 1.1 brad * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 1.1 brad * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 1.1 brad * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 1.1 brad */
18 1.1 brad
19 1.1 brad #ifdef __RCSID
20 1.1 brad __RCSID("$NetBSD: emcfanctlutil.c,v 1.1 2025/03/11 13:56:48 brad Exp $");
21 1.1 brad #endif
22 1.1 brad
23 1.1 brad #include <inttypes.h>
24 1.1 brad #include <stdbool.h>
25 1.1 brad #include <stdio.h>
26 1.1 brad #include <stdlib.h>
27 1.1 brad #include <unistd.h>
28 1.1 brad #include <err.h>
29 1.1 brad #include <fcntl.h>
30 1.1 brad #include <string.h>
31 1.1 brad #include <limits.h>
32 1.1 brad #include <errno.h>
33 1.1 brad
34 1.1 brad #include <dev/i2c/emcfanreg.h>
35 1.1 brad #include <dev/i2c/emcfaninfo.h>
36 1.1 brad
37 1.1 brad #define EXTERN
38 1.1 brad #include "emcfanctl.h"
39 1.1 brad #include "emcfanctlconst.h"
40 1.1 brad #include "emcfanctlutil.h"
41 1.1 brad
42 1.1 brad int
43 1.1 brad emcfan_read_register(int fd, uint8_t reg, uint8_t *res, bool debug)
44 1.1 brad {
45 1.1 brad int err;
46 1.1 brad
47 1.1 brad err = lseek(fd, reg, SEEK_SET);
48 1.1 brad if (err != -1) {
49 1.1 brad err = read(fd, res, 1);
50 1.1 brad if (err == -1)
51 1.1 brad err = errno;
52 1.1 brad else
53 1.1 brad err = 0;
54 1.1 brad } else {
55 1.1 brad err = errno;
56 1.1 brad }
57 1.1 brad
58 1.1 brad if (debug)
59 1.1 brad fprintf(stderr,"emcfan_read_register: reg=0x%02X, res=0x%02x, return err: %d\n",reg, *res, err);
60 1.1 brad
61 1.1 brad return err;
62 1.1 brad }
63 1.1 brad
64 1.1 brad int
65 1.1 brad emcfan_write_register(int fd, uint8_t reg, uint8_t value, bool debug)
66 1.1 brad {
67 1.1 brad int err;
68 1.1 brad
69 1.1 brad err = lseek(fd, reg, SEEK_SET);
70 1.1 brad if (err != -1) {
71 1.1 brad err = write(fd, &value, 1);
72 1.1 brad if (err == -1)
73 1.1 brad err = errno;
74 1.1 brad else
75 1.1 brad err = 0;
76 1.1 brad } else {
77 1.1 brad err = errno;
78 1.1 brad }
79 1.1 brad
80 1.1 brad if (debug)
81 1.1 brad fprintf(stderr,"emcfan_write_register: reg=0x%02X, value=0x%02X, return err: %d\n",reg, value, err);
82 1.1 brad
83 1.1 brad return err;
84 1.1 brad }
85 1.1 brad
86 1.1 brad int
87 1.1 brad emcfan_rmw_register(int fd, uint8_t reg, uint8_t value,
88 1.1 brad const struct emcfan_bits_translate translation[],
89 1.1 brad long unsigned int translation_size,
90 1.1 brad int tindex,
91 1.1 brad bool debug)
92 1.1 brad {
93 1.1 brad int err = 0;
94 1.1 brad uint8_t current, oldcurrent;
95 1.1 brad
96 1.1 brad err = emcfan_read_register(fd, reg, &oldcurrent, debug);
97 1.1 brad if (err != 0)
98 1.1 brad return(err);
99 1.1 brad
100 1.1 brad
101 1.1 brad current = oldcurrent & ~translation[tindex].clear_mask;
102 1.1 brad current = current | translation[tindex].bit_mask;
103 1.1 brad
104 1.1 brad if (debug)
105 1.1 brad fprintf(stderr,"tindex=%d, clear_mask=0x%02X 0x%02X, value=%d (0x%02X), bit_mask=0x%02X 0x%02X, oldcurrent=%d (0x%02X), new current=%d (0x%02X)\n",tindex,
106 1.1 brad translation[tindex].clear_mask,
107 1.1 brad (uint8_t)~translation[tindex].clear_mask,
108 1.1 brad value,value,
109 1.1 brad translation[tindex].bit_mask,
110 1.1 brad (uint8_t)~translation[tindex].bit_mask,
111 1.1 brad oldcurrent,oldcurrent,current,current);
112 1.1 brad
113 1.1 brad err = emcfan_write_register(fd, reg, current, debug);
114 1.1 brad
115 1.1 brad return(err);
116 1.1 brad }
117 1.1 brad
118 1.1 brad char *
119 1.1 brad emcfan_product_to_name(uint8_t product_id)
120 1.1 brad {
121 1.1 brad for(long unsigned int i = 0;i < __arraycount(emcfan_chip_infos); i++)
122 1.1 brad if (product_id == emcfan_chip_infos[i].product_id)
123 1.1 brad return(__UNCONST(emcfan_chip_infos[i].name));
124 1.1 brad return(NULL);
125 1.1 brad }
126 1.1 brad
127 1.1 brad void
128 1.1 brad emcfan_family_to_name(int family, char *name, int len)
129 1.1 brad {
130 1.1 brad switch(family) {
131 1.1 brad case EMCFAN_FAMILY_210X:
132 1.1 brad snprintf(name, len, "%s", "EMC210x");
133 1.1 brad break;
134 1.1 brad case EMCFAN_FAMILY_230X:
135 1.1 brad snprintf(name, len, "%s", "EMC230x");
136 1.1 brad break;
137 1.1 brad case EMCFAN_FAMILY_UNKNOWN:
138 1.1 brad default:
139 1.1 brad snprintf(name, len, "%s", "UNKNOWN");
140 1.1 brad break;
141 1.1 brad }
142 1.1 brad
143 1.1 brad return;
144 1.1 brad }
145 1.1 brad
146 1.1 brad int
147 1.1 brad emcfan_find_info(uint8_t product)
148 1.1 brad {
149 1.1 brad for(long unsigned int i = 0;i < __arraycount(emcfan_chip_infos); i++)
150 1.1 brad if (product == emcfan_chip_infos[i].product_id)
151 1.1 brad return(i);
152 1.1 brad
153 1.1 brad return(-1);
154 1.1 brad }
155 1.1 brad
156 1.1 brad bool
157 1.1 brad emcfan_reg_is_real(int iindex, uint8_t reg)
158 1.1 brad {
159 1.1 brad int segment;
160 1.1 brad uint64_t index;
161 1.1 brad
162 1.1 brad segment = reg / 64;
163 1.1 brad index = reg % 64;
164 1.1 brad
165 1.1 brad return(emcfan_chip_infos[iindex].register_void[segment] & ((uint64_t)1 << index));
166 1.1 brad }
167 1.1 brad
168 1.1 brad static int
169 1.1 brad emcfan_hunt_by_name(const struct emcfan_registers the_registers[], long unsigned int the_registers_size, char *the_name)
170 1.1 brad {
171 1.1 brad int r = -1;
172 1.1 brad
173 1.1 brad for(long unsigned int i = 0;i < the_registers_size;i++) {
174 1.1 brad if (strcmp(the_name, the_registers[i].name) == 0) {
175 1.1 brad r = the_registers[i].reg;
176 1.1 brad break;
177 1.1 brad }
178 1.1 brad }
179 1.1 brad
180 1.1 brad return(r);
181 1.1 brad }
182 1.1 brad
183 1.1 brad int
184 1.1 brad emcfan_reg_by_name(uint8_t product_id, int product_family, char *name)
185 1.1 brad {
186 1.1 brad int r = -1;
187 1.1 brad
188 1.1 brad switch(product_family) {
189 1.1 brad case EMCFAN_FAMILY_210X:
190 1.1 brad switch(product_id) {
191 1.1 brad case EMCFAN_PRODUCT_2101:
192 1.1 brad case EMCFAN_PRODUCT_2101R:
193 1.1 brad r = emcfan_hunt_by_name(emcfanctl_2101_registers,__arraycount(emcfanctl_2101_registers),name);
194 1.1 brad break;
195 1.1 brad case EMCFAN_PRODUCT_2103_1:
196 1.1 brad r = emcfan_hunt_by_name(emcfanctl_2103_1_registers,__arraycount(emcfanctl_2103_1_registers),name);
197 1.1 brad break;
198 1.1 brad case EMCFAN_PRODUCT_2103_24:
199 1.1 brad r = emcfan_hunt_by_name(emcfanctl_2103_24_registers,__arraycount(emcfanctl_2103_24_registers),name);
200 1.1 brad break;
201 1.1 brad case EMCFAN_PRODUCT_2104:
202 1.1 brad r = emcfan_hunt_by_name(emcfanctl_2104_registers,__arraycount(emcfanctl_2104_registers),name);
203 1.1 brad break;
204 1.1 brad case EMCFAN_PRODUCT_2106:
205 1.1 brad r = emcfan_hunt_by_name(emcfanctl_2106_registers,__arraycount(emcfanctl_2106_registers),name);
206 1.1 brad break;
207 1.1 brad default:
208 1.1 brad printf("UNSUPPORTED YET %d\n",product_id);
209 1.1 brad exit(99);
210 1.1 brad break;
211 1.1 brad };
212 1.1 brad break;
213 1.1 brad case EMCFAN_FAMILY_230X:
214 1.1 brad r = emcfan_hunt_by_name(emcfanctl_230x_registers,__arraycount(emcfanctl_230x_registers),name);
215 1.1 brad break;
216 1.1 brad };
217 1.1 brad
218 1.1 brad return(r);
219 1.1 brad }
220 1.1 brad
221 1.1 brad static const char *
222 1.1 brad emcfan_hunt_by_reg(const struct emcfan_registers the_registers[], long unsigned int the_registers_size, uint8_t the_reg)
223 1.1 brad {
224 1.1 brad const char *r = NULL;
225 1.1 brad
226 1.1 brad for(long unsigned int i = 0;i < the_registers_size;i++) {
227 1.1 brad if (the_reg == the_registers[i].reg) {
228 1.1 brad r = the_registers[i].name;
229 1.1 brad break;
230 1.1 brad }
231 1.1 brad }
232 1.1 brad
233 1.1 brad return(r);
234 1.1 brad }
235 1.1 brad
236 1.1 brad const char *
237 1.1 brad emcfan_regname_by_reg(uint8_t product_id, int product_family, uint8_t reg)
238 1.1 brad {
239 1.1 brad const char *r = NULL;
240 1.1 brad
241 1.1 brad switch(product_family) {
242 1.1 brad case EMCFAN_FAMILY_210X:
243 1.1 brad switch(product_id) {
244 1.1 brad case EMCFAN_PRODUCT_2101:
245 1.1 brad case EMCFAN_PRODUCT_2101R:
246 1.1 brad r = emcfan_hunt_by_reg(emcfanctl_2101_registers,__arraycount(emcfanctl_2101_registers),reg);
247 1.1 brad break;
248 1.1 brad case EMCFAN_PRODUCT_2103_1:
249 1.1 brad r = emcfan_hunt_by_reg(emcfanctl_2103_1_registers,__arraycount(emcfanctl_2103_1_registers),reg);
250 1.1 brad break;
251 1.1 brad case EMCFAN_PRODUCT_2103_24:
252 1.1 brad r = emcfan_hunt_by_reg(emcfanctl_2103_24_registers,__arraycount(emcfanctl_2103_24_registers),reg);
253 1.1 brad break;
254 1.1 brad case EMCFAN_PRODUCT_2104:
255 1.1 brad r = emcfan_hunt_by_reg(emcfanctl_2104_registers,__arraycount(emcfanctl_2104_registers),reg);
256 1.1 brad break;
257 1.1 brad case EMCFAN_PRODUCT_2106:
258 1.1 brad r = emcfan_hunt_by_reg(emcfanctl_2106_registers,__arraycount(emcfanctl_2106_registers),reg);
259 1.1 brad break;
260 1.1 brad default:
261 1.1 brad printf("UNSUPPORTED YET %d\n",product_id);
262 1.1 brad exit(99);
263 1.1 brad break;
264 1.1 brad };
265 1.1 brad break;
266 1.1 brad case EMCFAN_FAMILY_230X:
267 1.1 brad r = emcfan_hunt_by_reg(emcfanctl_230x_registers,__arraycount(emcfanctl_230x_registers),reg);
268 1.1 brad break;
269 1.1 brad };
270 1.1 brad
271 1.1 brad return(r);
272 1.1 brad }
273 1.1 brad
274 1.1 brad int
275 1.1 brad find_translated_blob_by_bits_instance(const struct emcfan_bits_translate translation[],
276 1.1 brad long unsigned int translation_size,
277 1.1 brad uint8_t bits, int instance)
278 1.1 brad {
279 1.1 brad int r = -10191;
280 1.1 brad uint8_t clear_mask;
281 1.1 brad uint8_t b;
282 1.1 brad
283 1.1 brad for(long unsigned int i = 0;i < translation_size;i++) {
284 1.1 brad if (instance == translation[i].instance) {
285 1.1 brad clear_mask = translation[i].clear_mask;
286 1.1 brad b = bits & clear_mask;
287 1.1 brad if (b == translation[i].bit_mask) {
288 1.1 brad r = i;
289 1.1 brad break;
290 1.1 brad }
291 1.1 brad }
292 1.1 brad
293 1.1 brad }
294 1.1 brad
295 1.1 brad return(r);
296 1.1 brad }
297 1.1 brad
298 1.1 brad int
299 1.1 brad find_translated_bits_by_hint_instance(const struct emcfan_bits_translate translation[],
300 1.1 brad long unsigned int translation_size,
301 1.1 brad int human_value, int instance)
302 1.1 brad {
303 1.1 brad int r = -10191;
304 1.1 brad
305 1.1 brad for(long unsigned int i = 0;i < translation_size;i++) {
306 1.1 brad if (instance == translation[i].instance &&
307 1.1 brad human_value == translation[i].human_int) {
308 1.1 brad r = i;
309 1.1 brad break;
310 1.1 brad }
311 1.1 brad }
312 1.1 brad
313 1.1 brad return(r);
314 1.1 brad }
315 1.1 brad
316 1.1 brad int
317 1.1 brad find_translated_bits_by_hint(const struct emcfan_bits_translate translation[],
318 1.1 brad long unsigned int translation_size,
319 1.1 brad int human_value)
320 1.1 brad {
321 1.1 brad int r = -10191;
322 1.1 brad
323 1.1 brad for(long unsigned int i = 0;i < translation_size;i++) {
324 1.1 brad if (human_value == translation[i].human_int) {
325 1.1 brad r = i;
326 1.1 brad break;
327 1.1 brad }
328 1.1 brad }
329 1.1 brad
330 1.1 brad return(r);
331 1.1 brad }
332 1.1 brad
333 1.1 brad int
334 1.1 brad find_translated_bits_by_str(const struct emcfan_bits_translate translation[],
335 1.1 brad long unsigned int translation_size,
336 1.1 brad char *human_str)
337 1.1 brad {
338 1.1 brad int r = -10191;
339 1.1 brad
340 1.1 brad for(long unsigned int i = 0;i < translation_size;i++) {
341 1.1 brad if (strcmp(human_str,translation[i].human_str) == 0) {
342 1.1 brad r = i;
343 1.1 brad break;
344 1.1 brad }
345 1.1 brad }
346 1.1 brad
347 1.1 brad return(r);
348 1.1 brad }
349 1.1 brad
350 1.1 brad int
351 1.1 brad find_translated_bits_by_str_instance(const struct emcfan_bits_translate translation[],
352 1.1 brad long unsigned int translation_size,
353 1.1 brad char *human_str, int instance)
354 1.1 brad {
355 1.1 brad int r = -10191;
356 1.1 brad
357 1.1 brad for(long unsigned int i = 0;i < translation_size;i++) {
358 1.1 brad if (instance == translation[i].instance &&
359 1.1 brad strcmp(human_str,translation[i].human_str) == 0) {
360 1.1 brad r = i;
361 1.1 brad break;
362 1.1 brad }
363 1.1 brad }
364 1.1 brad
365 1.1 brad return(r);
366 1.1 brad }
367 1.1 brad
368 1.1 brad int
369 1.1 brad find_human_int(const struct emcfan_bits_translate translation[],
370 1.1 brad long unsigned int translation_size,
371 1.1 brad uint8_t bits)
372 1.1 brad {
373 1.1 brad int r = -10191;
374 1.1 brad
375 1.1 brad for(long unsigned int i = 0;i < translation_size;i++) {
376 1.1 brad if (bits == translation[i].bit_mask) {
377 1.1 brad r = translation[i].human_int;
378 1.1 brad break;
379 1.1 brad }
380 1.1 brad }
381 1.1 brad
382 1.1 brad return(r);
383 1.1 brad }
384 1.1 brad
385 1.1 brad char *
386 1.1 brad find_human_str(const struct emcfan_bits_translate translation[],
387 1.1 brad long unsigned int translation_size,
388 1.1 brad uint8_t bits)
389 1.1 brad {
390 1.1 brad char *r = NULL;
391 1.1 brad
392 1.1 brad for(long unsigned int i = 0;i < translation_size;i++) {
393 1.1 brad if (bits == translation[i].bit_mask) {
394 1.1 brad r = __UNCONST(translation[i].human_str);
395 1.1 brad break;
396 1.1 brad }
397 1.1 brad }
398 1.1 brad
399 1.1 brad return(r);
400 1.1 brad }
401