This source file includes following definitions.
- fcu_match
- fcu_attach
- fcu_refresh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/device.h>
22 #include <sys/sensors.h>
23
24 #include <dev/i2c/i2cvar.h>
25
26
27 #define FCU_FAN_FAIL 0x0b
28 #define FCU_FAN_ACTIVE 0x0d
29 #define FCU_FANREAD(x) 0x11 + (x)*2
30 #define FCU_FANSET(x) 0x10 + (x)*2
31 #define FCU_PWM_FAIL 0x2b
32 #define FCU_PWM_ACTIVE 0x2d
33 #define FCU_PWMREAD(x) 0x30 + (x)*2
34
35
36 #define FCU_RPM1 0
37 #define FCU_RPM2 1
38 #define FCU_RPM3 2
39 #define FCU_RPM4 3
40 #define FCU_RPM5 4
41 #define FCU_RPM6 5
42 #define FCU_FANS 6
43 #define FCU_PWM1 6
44 #define FCU_PWM2 7
45 #define FCU_PWMS 2
46 #define FCU_NUM_SENSORS 8
47
48 struct fcu_softc {
49 struct device sc_dev;
50 i2c_tag_t sc_tag;
51 i2c_addr_t sc_addr;
52
53 struct ksensor sc_sensor[FCU_NUM_SENSORS];
54 struct ksensordev sc_sensordev;
55 };
56
57 int fcu_match(struct device *, void *, void *);
58 void fcu_attach(struct device *, struct device *, void *);
59
60 void fcu_refresh(void *);
61
62 struct cfattach fcu_ca = {
63 sizeof(struct fcu_softc), fcu_match, fcu_attach
64 };
65
66 struct cfdriver fcu_cd = {
67 NULL, "fcu", DV_DULL
68 };
69
70 int
71 fcu_match(struct device *parent, void *match, void *aux)
72 {
73 struct i2c_attach_args *ia = aux;
74
75 if (strcmp(ia->ia_name, "fcu") == 0)
76 return (1);
77 return (0);
78 }
79
80 void
81 fcu_attach(struct device *parent, struct device *self, void *aux)
82 {
83 struct fcu_softc *sc = (struct fcu_softc *)self;
84 struct i2c_attach_args *ia = aux;
85 int i;
86
87 sc->sc_tag = ia->ia_tag;
88 sc->sc_addr = ia->ia_addr;
89
90
91 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
92 sizeof(sc->sc_sensordev.xname));
93 for (i = 0; i < FCU_FANS; i++)
94 sc->sc_sensor[i].type = SENSOR_FANRPM;
95 for (i = 0; i < FCU_PWMS; i++) {
96 sc->sc_sensor[FCU_PWM1 + i].type = SENSOR_PERCENT;
97 strlcpy(sc->sc_sensor[FCU_PWM1 + i].desc, "PWM",
98 sizeof(sc->sc_sensor[FCU_PWM1 + i].desc));
99 }
100
101 if (sensor_task_register(sc, fcu_refresh, 5) == NULL) {
102 printf(", unable to register update task\n");
103 return;
104 }
105
106 for (i = 0; i < FCU_NUM_SENSORS; i++)
107 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
108 sensordev_install(&sc->sc_sensordev);
109
110 printf("\n");
111 }
112
113 void
114 fcu_refresh(void *arg)
115 {
116 struct fcu_softc *sc = arg;
117 u_int8_t cmd, fail, fan[2], active;
118 int i;
119
120 iic_acquire_bus(sc->sc_tag, 0);
121
122 cmd = FCU_FAN_FAIL;
123 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
124 sc->sc_addr, &cmd, sizeof cmd, &fail, sizeof fail, 0))
125 goto abort;
126 cmd = FCU_FAN_ACTIVE;
127 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
128 sc->sc_addr, &cmd, sizeof cmd, &active, sizeof active, 0))
129 goto abort;
130 fail &= active;
131
132 for (i = 0; i < FCU_FANS; i++) {
133 if (fail & (1 << (i + 1)))
134 sc->sc_sensor[i].flags |= SENSOR_FINVALID;
135 else
136 sc->sc_sensor[i].flags &= ~SENSOR_FINVALID;
137 }
138
139 cmd = FCU_PWM_FAIL;
140 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
141 sc->sc_addr, &cmd, sizeof cmd, &fail, sizeof fail, 0))
142 goto abort;
143 cmd = FCU_PWM_ACTIVE;
144 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
145 sc->sc_addr, &cmd, sizeof cmd, &active, sizeof active, 0))
146 goto abort;
147 fail &= active;
148
149 for (i = 0; i < FCU_PWMS; i++) {
150 if (fail & (1 << (i + 1)))
151 sc->sc_sensor[FCU_PWMS + i].flags |= SENSOR_FINVALID;
152 else
153 sc->sc_sensor[FCU_PWMS + i].flags &= ~SENSOR_FINVALID;
154 }
155
156 for (i = 0; i < FCU_FANS; i++) {
157 cmd = FCU_FANREAD(i + 1);
158 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
159 sc->sc_addr, &cmd, sizeof cmd, &fan, sizeof fan, 0)) {
160 sc->sc_sensor[FCU_RPM1 + i].flags |= SENSOR_FINVALID;
161 continue;
162 }
163 sc->sc_sensor[FCU_RPM1 + i].value = (fan[0] << 5) | (fan[1] >> 3);
164 }
165
166 for (i = 0; i < FCU_PWMS; i++) {
167 cmd = FCU_PWMREAD(i + 1);
168 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
169 sc->sc_addr, &cmd, sizeof cmd, &fan, sizeof fan, 0)) {
170 sc->sc_sensor[FCU_PWM1 + i].flags |= SENSOR_FINVALID;
171 continue;
172 }
173 sc->sc_sensor[FCU_PWM1 + i].value = (fan[0] * 100 * 1000) / 255;
174 }
175
176 abort:
177 iic_release_bus(sc->sc_tag, 0);
178 }