1 1.1 macallan /*- 2 1.1 macallan * Copyright (c) 2013 Phileas Fogg 3 1.1 macallan * All rights reserved. 4 1.1 macallan * 5 1.1 macallan * Redistribution and use in source and binary forms, with or without 6 1.1 macallan * modification, are permitted provided that the following conditions 7 1.1 macallan * are met: 8 1.1 macallan * 1. Redistributions of source code must retain the above copyright 9 1.1 macallan * notice, this list of conditions and the following disclaimer. 10 1.1 macallan * 2. Redistributions in binary form must reproduce the above copyright 11 1.1 macallan * notice, this list of conditions and the following disclaimer in the 12 1.1 macallan * documentation and/or other materials provided with the distribution. 13 1.1 macallan * 14 1.1 macallan * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 15 1.1 macallan * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16 1.1 macallan * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 1.1 macallan * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 18 1.1 macallan * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 1.1 macallan * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 1.1 macallan * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 1.1 macallan * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 1.1 macallan * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 1.1 macallan * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 1.1 macallan * POSSIBILITY OF SUCH DAMAGE. 25 1.1 macallan */ 26 1.1 macallan 27 1.1 macallan #include <sys/param.h> 28 1.1 macallan #include <sys/systm.h> 29 1.1 macallan #include <sys/kernel.h> 30 1.1 macallan #include <sys/malloc.h> 31 1.1 macallan #include <sys/device.h> 32 1.1 macallan #include <sys/proc.h> 33 1.1 macallan #include <sys/mutex.h> 34 1.1 macallan #include <sys/time.h> 35 1.1 macallan #include <sys/reboot.h> 36 1.1 macallan #include <sys/sysctl.h> 37 1.2 macallan #include <sys/kthread.h> 38 1.1 macallan 39 1.1 macallan #include <machine/autoconf.h> 40 1.1 macallan 41 1.1 macallan #include <dev/ofw/openfirm.h> 42 1.1 macallan #include <dev/i2c/i2cvar.h> 43 1.1 macallan #include <dev/clock_subr.h> 44 1.1 macallan #include <dev/sysmon/sysmonvar.h> 45 1.1 macallan #include <dev/sysmon/sysmon_taskq.h> 46 1.1 macallan 47 1.1 macallan #include <macppc/dev/obiovar.h> 48 1.1 macallan #include <macppc/dev/smuvar.h> 49 1.15 macallan #include <macppc/dev/fancontrolvar.h> 50 1.1 macallan 51 1.1 macallan #include "opt_smu.h" 52 1.1 macallan 53 1.1 macallan struct smu_softc; 54 1.1 macallan 55 1.1 macallan struct smu_cmd { 56 1.1 macallan u_char cmd; 57 1.1 macallan u_char len; 58 1.1 macallan u_char data[254]; 59 1.1 macallan }; 60 1.1 macallan 61 1.1 macallan struct smu_fan { 62 1.1 macallan struct smu_softc* sc; 63 1.1 macallan 64 1.1 macallan char location[32]; 65 1.1 macallan int reg; 66 1.1 macallan int zone; 67 1.1 macallan int rpm_ctl; 68 1.1 macallan int min_rpm; 69 1.1 macallan int max_rpm; 70 1.1 macallan int default_rpm; 71 1.15 macallan int wanted_rpm; 72 1.1 macallan int current_rpm; 73 1.15 macallan int fault; 74 1.1 macallan time_t last_update; 75 1.1 macallan }; 76 1.1 macallan 77 1.1 macallan struct smu_iicbus { 78 1.1 macallan struct smu_softc* sc; 79 1.1 macallan 80 1.1 macallan int reg; 81 1.1 macallan struct i2c_controller i2c; 82 1.1 macallan }; 83 1.1 macallan 84 1.1 macallan #define SMU_MAX_FANS 8 85 1.1 macallan #define SMU_MAX_IICBUS 3 86 1.12 macallan #define SMU_MAX_SME_SENSORS (SMU_MAX_FANS + 8) 87 1.1 macallan 88 1.2 macallan 89 1.15 macallan #define SMU_ZONE_CPU 0 90 1.15 macallan #define SMU_ZONE_CASE 1 91 1.15 macallan #define SMU_ZONE_DRIVEBAY 2 92 1.15 macallan #define SMU_ZONES 3 93 1.2 macallan 94 1.2 macallan #define C_TO_uK(n) (n * 1000000 + 273150000) 95 1.2 macallan 96 1.1 macallan struct smu_softc { 97 1.1 macallan device_t sc_dev; 98 1.1 macallan int sc_node; 99 1.1 macallan struct sysctlnode *sc_sysctl_me; 100 1.1 macallan 101 1.1 macallan kmutex_t sc_cmd_lock; 102 1.2 macallan kmutex_t sc_msg_lock; 103 1.1 macallan struct smu_cmd *sc_cmd; 104 1.1 macallan paddr_t sc_cmd_paddr; 105 1.1 macallan int sc_dbell_mbox; 106 1.1 macallan int sc_dbell_gpio; 107 1.1 macallan 108 1.1 macallan int sc_num_fans; 109 1.1 macallan struct smu_fan sc_fans[SMU_MAX_FANS]; 110 1.1 macallan 111 1.1 macallan int sc_num_iicbus; 112 1.1 macallan struct smu_iicbus sc_iicbus[SMU_MAX_IICBUS]; 113 1.1 macallan 114 1.1 macallan struct todr_chip_handle sc_todr; 115 1.1 macallan 116 1.1 macallan struct sysmon_envsys *sc_sme; 117 1.1 macallan envsys_data_t sc_sme_sensors[SMU_MAX_SME_SENSORS]; 118 1.12 macallan uint32_t cpu_m; 119 1.12 macallan int32_t cpu_b; 120 1.2 macallan 121 1.15 macallan fancontrol_zone_t sc_zones[SMU_ZONES]; 122 1.2 macallan lwp_t *sc_thread; 123 1.2 macallan bool sc_dying; 124 1.1 macallan }; 125 1.1 macallan 126 1.1 macallan #define SMU_CMD_FAN 0x4a 127 1.1 macallan #define SMU_CMD_RTC 0x8e 128 1.1 macallan #define SMU_CMD_I2C 0x9a 129 1.1 macallan #define SMU_CMD_POWER 0xaa 130 1.12 macallan #define SMU_CMD_ADC 0xd8 131 1.5 macallan #define SMU_MISC 0xee 132 1.5 macallan #define SMU_MISC_GET_DATA 0x02 133 1.5 macallan #define SMU_MISC_LED_CTRL 0x04 134 1.5 macallan 135 1.5 macallan #define SMU_CPUTEMP_CAL 0x18 136 1.5 macallan #define SMU_CPUVOLT_CAL 0x21 137 1.5 macallan #define SMU_SLOTPW_CAL 0x78 138 1.5 macallan 139 1.5 macallan #define SMU_PARTITION 0x3e 140 1.5 macallan #define SMU_PARTITION_LATEST 0x01 141 1.5 macallan #define SMU_PARTITION_BASE 0x02 142 1.5 macallan #define SMU_PARTITION_UPDATE 0x03 143 1.1 macallan 144 1.1 macallan #ifdef SMU_DEBUG 145 1.1 macallan #define DPRINTF printf 146 1.1 macallan #else 147 1.1 macallan #define DPRINTF while (0) printf 148 1.1 macallan #endif 149 1.1 macallan 150 1.1 macallan static int smu_match(device_t, struct cfdata *, void *); 151 1.1 macallan static void smu_attach(device_t, device_t, void *); 152 1.1 macallan static int smu_setup_doorbell(struct smu_softc *); 153 1.1 macallan static void smu_setup_fans(struct smu_softc *); 154 1.1 macallan static void smu_setup_iicbus(struct smu_softc *); 155 1.1 macallan static void smu_setup_sme(struct smu_softc *); 156 1.1 macallan static int smu_iicbus_print(void *, const char *); 157 1.1 macallan static void smu_sme_refresh(struct sysmon_envsys *, envsys_data_t *); 158 1.1 macallan static int smu_do_cmd(struct smu_softc *, struct smu_cmd *, int); 159 1.1 macallan static int smu_dbell_gpio_intr(void *); 160 1.1 macallan static int smu_todr_gettime_ymdhms(todr_chip_handle_t, struct clock_ymdhms *); 161 1.1 macallan static int smu_todr_settime_ymdhms(todr_chip_handle_t, struct clock_ymdhms *); 162 1.1 macallan static int smu_fan_update_rpm(struct smu_fan *); 163 1.12 macallan static int smu_read_adc(struct smu_softc *, int); 164 1.12 macallan 165 1.1 macallan static int smu_iicbus_exec(void *, i2c_op_t, i2c_addr_t, const void *, 166 1.1 macallan size_t, void *, size_t, int); 167 1.1 macallan 168 1.2 macallan static void smu_setup_zones(struct smu_softc *); 169 1.2 macallan static void smu_adjust(void *); 170 1.15 macallan 171 1.2 macallan static bool is_cpu_sensor(const envsys_data_t *); 172 1.2 macallan static bool is_drive_sensor(const envsys_data_t *); 173 1.2 macallan static bool is_slots_sensor(const envsys_data_t *); 174 1.15 macallan static int smu_fan_get_rpm(void *, int); 175 1.15 macallan static int smu_fan_set_rpm(void *, int, int); 176 1.2 macallan 177 1.5 macallan int smu_get_datablock(int, uint8_t *, size_t); 178 1.5 macallan 179 1.1 macallan CFATTACH_DECL_NEW(smu, sizeof(struct smu_softc), 180 1.1 macallan smu_match, smu_attach, NULL, NULL); 181 1.1 macallan 182 1.1 macallan static struct smu_softc *smu0 = NULL; 183 1.1 macallan 184 1.1 macallan static int 185 1.1 macallan smu_match(device_t parent, struct cfdata *cf, void *aux) 186 1.1 macallan { 187 1.1 macallan struct confargs *ca = aux; 188 1.1 macallan 189 1.1 macallan if (strcmp(ca->ca_name, "smu") == 0) 190 1.1 macallan return 5; 191 1.1 macallan 192 1.1 macallan return 0; 193 1.1 macallan } 194 1.1 macallan 195 1.1 macallan static void 196 1.1 macallan smu_attach(device_t parent, device_t self, void *aux) 197 1.1 macallan { 198 1.1 macallan struct confargs *ca = aux; 199 1.1 macallan struct smu_softc *sc = device_private(self); 200 1.12 macallan uint16_t data[4]; 201 1.1 macallan 202 1.1 macallan sc->sc_dev = self; 203 1.1 macallan sc->sc_node = ca->ca_node; 204 1.1 macallan 205 1.5 macallan if (smu0 == NULL) 206 1.5 macallan smu0 = sc; 207 1.5 macallan 208 1.1 macallan sysctl_createv(NULL, 0, NULL, (void *) &sc->sc_sysctl_me, 209 1.1 macallan CTLFLAG_READWRITE, 210 1.1 macallan CTLTYPE_NODE, device_xname(sc->sc_dev), NULL, 211 1.1 macallan NULL, 0, NULL, 0, 212 1.1 macallan CTL_MACHDEP, CTL_CREATE, CTL_EOL); 213 1.1 macallan 214 1.1 macallan if (smu_setup_doorbell(sc) != 0) { 215 1.1 macallan aprint_normal(": unable to set up doorbell\n"); 216 1.1 macallan return; 217 1.1 macallan } 218 1.1 macallan 219 1.9 rin aprint_normal("\n"); 220 1.9 rin 221 1.1 macallan smu_setup_fans(sc); 222 1.1 macallan smu_setup_iicbus(sc); 223 1.1 macallan 224 1.1 macallan sc->sc_todr.todr_gettime_ymdhms = smu_todr_gettime_ymdhms; 225 1.1 macallan sc->sc_todr.todr_settime_ymdhms = smu_todr_settime_ymdhms; 226 1.17 thorpej sc->sc_todr.todr_dev = self; 227 1.1 macallan todr_attach(&sc->sc_todr); 228 1.1 macallan 229 1.12 macallan /* calibration data */ 230 1.12 macallan memset(data, 0, 8); 231 1.12 macallan smu_get_datablock(SMU_CPUTEMP_CAL, (void *)data, 8); 232 1.12 macallan DPRINTF("data %04x %04x %04x %04x\n", data[0], data[1], data[2], data[3]); 233 1.12 macallan sc->cpu_m = data[2]; 234 1.12 macallan sc->cpu_b = (int16_t)data[3]; 235 1.12 macallan 236 1.1 macallan smu_setup_sme(sc); 237 1.1 macallan 238 1.2 macallan smu_setup_zones(sc); 239 1.1 macallan } 240 1.1 macallan 241 1.1 macallan static int 242 1.1 macallan smu_setup_doorbell(struct smu_softc *sc) 243 1.1 macallan { 244 1.1 macallan int node, parent, reg[4], gpio_base, irq; 245 1.1 macallan 246 1.1 macallan mutex_init(&sc->sc_cmd_lock, MUTEX_DEFAULT, IPL_NONE); 247 1.7 chs sc->sc_cmd = malloc(4096, M_DEVBUF, M_WAITOK); 248 1.1 macallan sc->sc_cmd_paddr = vtophys((vaddr_t) sc->sc_cmd); 249 1.1 macallan 250 1.1 macallan DPRINTF("%s: cmd vaddr 0x%x paddr 0x%x\n", 251 1.1 macallan __func__, (unsigned int) sc->sc_cmd, 252 1.1 macallan (unsigned int) sc->sc_cmd_paddr); 253 1.1 macallan 254 1.1 macallan if (OF_getprop(sc->sc_node, "platform-doorbell-buff", 255 1.1 macallan &node, sizeof(node)) <= 0) 256 1.1 macallan return -1; 257 1.1 macallan 258 1.1 macallan if (OF_getprop(node, "platform-do-doorbell-buff", 259 1.1 macallan reg, sizeof(reg)) < sizeof(reg)) 260 1.1 macallan return -1; 261 1.1 macallan 262 1.1 macallan sc->sc_dbell_mbox = reg[3]; 263 1.1 macallan 264 1.1 macallan if (OF_getprop(sc->sc_node, "platform-doorbell-ack", 265 1.1 macallan &node, sizeof(node)) <= 0) 266 1.1 macallan return -1; 267 1.1 macallan 268 1.1 macallan parent = OF_parent(node); 269 1.1 macallan if (parent == 0) 270 1.1 macallan return -1; 271 1.1 macallan 272 1.1 macallan if (OF_getprop(parent, "reg", &gpio_base, sizeof(gpio_base)) <= 0) 273 1.1 macallan return -1; 274 1.1 macallan 275 1.1 macallan if (OF_getprop(node, "reg", reg, sizeof(reg)) <= 0) 276 1.1 macallan return -1; 277 1.1 macallan 278 1.1 macallan if (OF_getprop(node, "interrupts", &irq, sizeof(irq)) <= 0) 279 1.1 macallan return -1; 280 1.1 macallan 281 1.1 macallan sc->sc_dbell_gpio = gpio_base + reg[0]; 282 1.1 macallan 283 1.1 macallan aprint_normal(" mbox 0x%x gpio 0x%x irq %d", 284 1.1 macallan sc->sc_dbell_mbox, sc->sc_dbell_gpio, irq); 285 1.1 macallan 286 1.11 rin intr_establish_xname(irq, IST_EDGE_FALLING, IPL_TTY, 287 1.11 rin smu_dbell_gpio_intr, sc, device_xname(sc->sc_dev)); 288 1.1 macallan 289 1.1 macallan return 0; 290 1.1 macallan } 291 1.1 macallan 292 1.1 macallan static void 293 1.1 macallan smu_setup_fans(struct smu_softc *sc) 294 1.1 macallan { 295 1.1 macallan struct smu_fan *fan; 296 1.15 macallan char type[32]; 297 1.15 macallan int node, i; 298 1.10 macallan const char *fans[] = { "fans", "rpm-fans", 0 }; 299 1.10 macallan int n = 0; 300 1.10 macallan 301 1.10 macallan while (fans[n][0] != 0) { 302 1.10 macallan node = of_getnode_byname(sc->sc_node, fans[n]); 303 1.10 macallan for (node = OF_child(node); 304 1.10 macallan (node != 0) && (sc->sc_num_fans < SMU_MAX_FANS); 305 1.10 macallan node = OF_peer(node)) { 306 1.10 macallan fan = &sc->sc_fans[sc->sc_num_fans]; 307 1.10 macallan fan->sc = sc; 308 1.10 macallan 309 1.10 macallan memset(fan->location, 0, sizeof(fan->location)); 310 1.10 macallan OF_getprop(node, "location", fan->location, 311 1.10 macallan sizeof(fan->location)); 312 1.10 macallan 313 1.10 macallan if (OF_getprop(node, "reg", &fan->reg, 314 1.10 macallan sizeof(fan->reg)) <= 0) 315 1.10 macallan continue; 316 1.10 macallan 317 1.10 macallan if (OF_getprop(node, "zone", &fan->zone , 318 1.10 macallan sizeof(fan->zone)) <= 0) 319 1.10 macallan continue; 320 1.10 macallan 321 1.10 macallan memset(type, 0, sizeof(type)); 322 1.10 macallan OF_getprop(node, "device_type", type, sizeof(type)); 323 1.10 macallan if (strcmp(type, "fan-rpm-control") == 0) 324 1.10 macallan fan->rpm_ctl = 1; 325 1.10 macallan else 326 1.10 macallan fan->rpm_ctl = 0; 327 1.10 macallan 328 1.10 macallan if (OF_getprop(node, "min-value", &fan->min_rpm, 329 1.10 macallan sizeof(fan->min_rpm)) <= 0) 330 1.10 macallan fan->min_rpm = 0; 331 1.10 macallan 332 1.10 macallan if (OF_getprop(node, "max-value", &fan->max_rpm, 333 1.10 macallan sizeof(fan->max_rpm)) <= 0) 334 1.10 macallan fan->max_rpm = 0xffff; 335 1.10 macallan 336 1.10 macallan if (OF_getprop(node, "unmanage-value", &fan->default_rpm, 337 1.10 macallan sizeof(fan->default_rpm)) <= 0) 338 1.10 macallan fan->default_rpm = fan->max_rpm; 339 1.10 macallan 340 1.10 macallan DPRINTF("fan: location %s reg %x zone %d rpm_ctl %d " 341 1.10 macallan "min_rpm %d max_rpm %d default_rpm %d\n", 342 1.10 macallan fan->location, fan->reg, fan->zone, fan->rpm_ctl, 343 1.10 macallan fan->min_rpm, fan->max_rpm, fan->default_rpm); 344 1.1 macallan 345 1.15 macallan fan->wanted_rpm = fan->default_rpm; 346 1.15 macallan fan->fault = 0; 347 1.10 macallan sc->sc_num_fans++; 348 1.10 macallan } 349 1.10 macallan n++; 350 1.1 macallan } 351 1.1 macallan 352 1.1 macallan for (i = 0; i < sc->sc_num_fans; i++) { 353 1.1 macallan fan = &sc->sc_fans[i]; 354 1.15 macallan smu_fan_set_rpm(sc, i, fan->default_rpm); 355 1.15 macallan smu_fan_update_rpm(fan); 356 1.1 macallan } 357 1.1 macallan } 358 1.1 macallan 359 1.1 macallan static void 360 1.1 macallan smu_setup_iicbus(struct smu_softc *sc) 361 1.1 macallan { 362 1.1 macallan struct smu_iicbus *iicbus; 363 1.1 macallan struct i2c_controller *i2c; 364 1.1 macallan struct smu_iicbus_confargs ca; 365 1.1 macallan int node; 366 1.1 macallan char name[32]; 367 1.1 macallan 368 1.16 thorpej devhandle_t selfh = device_handle(sc->sc_dev); 369 1.1 macallan node = of_getnode_byname(sc->sc_node, "smu-i2c-control"); 370 1.10 macallan if (node == 0) node = sc->sc_node; 371 1.1 macallan for (node = OF_child(node); 372 1.1 macallan (node != 0) && (sc->sc_num_iicbus < SMU_MAX_IICBUS); 373 1.1 macallan node = OF_peer(node)) { 374 1.1 macallan memset(name, 0, sizeof(name)); 375 1.1 macallan OF_getprop(node, "name", name, sizeof(name)); 376 1.10 macallan if ((strcmp(name, "i2c-bus") != 0) && 377 1.10 macallan (strcmp(name, "i2c") != 0)) 378 1.1 macallan continue; 379 1.1 macallan 380 1.1 macallan iicbus = &sc->sc_iicbus[sc->sc_num_iicbus]; 381 1.1 macallan iicbus->sc = sc; 382 1.1 macallan i2c = &iicbus->i2c; 383 1.1 macallan 384 1.1 macallan if (OF_getprop(node, "reg", &iicbus->reg, sizeof(iicbus->reg)) <= 0) 385 1.1 macallan continue; 386 1.1 macallan 387 1.1 macallan DPRINTF("iicbus: reg %x\n", iicbus->reg); 388 1.1 macallan 389 1.8 thorpej iic_tag_init(i2c); 390 1.1 macallan i2c->ic_cookie = iicbus; 391 1.1 macallan i2c->ic_exec = smu_iicbus_exec; 392 1.1 macallan 393 1.1 macallan ca.ca_name = name; 394 1.1 macallan ca.ca_node = node; 395 1.1 macallan ca.ca_tag = i2c; 396 1.13 thorpej config_found(sc->sc_dev, &ca, smu_iicbus_print, 397 1.16 thorpej CFARGS(.devhandle = devhandle_from_of(selfh, node))); 398 1.1 macallan 399 1.1 macallan sc->sc_num_iicbus++; 400 1.1 macallan } 401 1.1 macallan } 402 1.1 macallan 403 1.1 macallan static void 404 1.1 macallan smu_setup_sme(struct smu_softc *sc) 405 1.1 macallan { 406 1.1 macallan struct smu_fan *fan; 407 1.1 macallan envsys_data_t *sme_sensor; 408 1.12 macallan int i, sensors, child, reg; 409 1.12 macallan char loc[32], type[32]; 410 1.1 macallan 411 1.1 macallan sc->sc_sme = sysmon_envsys_create(); 412 1.1 macallan 413 1.1 macallan for (i = 0; i < sc->sc_num_fans; i++) { 414 1.1 macallan sme_sensor = &sc->sc_sme_sensors[i]; 415 1.1 macallan fan = &sc->sc_fans[i]; 416 1.1 macallan 417 1.1 macallan sme_sensor->units = ENVSYS_SFANRPM; 418 1.1 macallan sme_sensor->state = ENVSYS_SINVALID; 419 1.1 macallan snprintf(sme_sensor->desc, sizeof(sme_sensor->desc), 420 1.1 macallan "%s", fan->location); 421 1.1 macallan 422 1.1 macallan if (sysmon_envsys_sensor_attach(sc->sc_sme, sme_sensor)) { 423 1.1 macallan sysmon_envsys_destroy(sc->sc_sme); 424 1.1 macallan return; 425 1.1 macallan } 426 1.1 macallan } 427 1.12 macallan sensors = OF_finddevice("/smu/sensors"); 428 1.12 macallan child = OF_child(sensors); 429 1.12 macallan while (child != 0) { 430 1.12 macallan sme_sensor = &sc->sc_sme_sensors[i]; 431 1.12 macallan if (OF_getprop(child, "location", loc, 32) == 0) goto next; 432 1.12 macallan if (OF_getprop(child, "device_type", type, 32) == 0) goto next; 433 1.12 macallan if (OF_getprop(child, "reg", ®, 4) == 0) goto next; 434 1.12 macallan if (strcmp(type, "temp-sensor") == 0) { 435 1.12 macallan sme_sensor->units = ENVSYS_STEMP; 436 1.12 macallan sme_sensor->state = ENVSYS_SINVALID; 437 1.12 macallan strncpy(sme_sensor->desc, loc, sizeof(sme_sensor->desc)); 438 1.12 macallan sme_sensor->private = reg; 439 1.12 macallan sysmon_envsys_sensor_attach(sc->sc_sme, sme_sensor); 440 1.12 macallan i++; 441 1.12 macallan printf("%s: %s@%x\n", loc, type, reg); 442 1.12 macallan } 443 1.12 macallan next: 444 1.12 macallan child = OF_peer(child); 445 1.12 macallan } 446 1.12 macallan 447 1.1 macallan sc->sc_sme->sme_name = device_xname(sc->sc_dev); 448 1.1 macallan sc->sc_sme->sme_cookie = sc; 449 1.1 macallan sc->sc_sme->sme_refresh = smu_sme_refresh; 450 1.1 macallan 451 1.1 macallan if (sysmon_envsys_register(sc->sc_sme)) { 452 1.1 macallan aprint_error_dev(sc->sc_dev, 453 1.1 macallan "unable to register with sysmon\n"); 454 1.1 macallan sysmon_envsys_destroy(sc->sc_sme); 455 1.1 macallan } 456 1.1 macallan } 457 1.1 macallan 458 1.1 macallan static int 459 1.1 macallan smu_iicbus_print(void *aux, const char *smu) 460 1.1 macallan { 461 1.1 macallan struct smu_iicbus_confargs *ca = aux; 462 1.1 macallan 463 1.1 macallan if (smu) 464 1.1 macallan aprint_normal("%s at %s", ca->ca_name, smu); 465 1.1 macallan 466 1.1 macallan return UNCONF; 467 1.1 macallan } 468 1.1 macallan 469 1.1 macallan static void 470 1.1 macallan smu_sme_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 471 1.1 macallan { 472 1.1 macallan struct smu_softc *sc = sme->sme_cookie; 473 1.1 macallan int which = edata->sensor; 474 1.1 macallan int ret; 475 1.1 macallan 476 1.1 macallan edata->state = ENVSYS_SINVALID; 477 1.1 macallan 478 1.1 macallan if (which < sc->sc_num_fans) { 479 1.1 macallan 480 1.15 macallan ret = smu_fan_get_rpm(sc, which); 481 1.15 macallan if (ret != -1) { 482 1.15 macallan sc->sc_fans[which].current_rpm = ret; 483 1.15 macallan edata->value_cur = ret; 484 1.1 macallan edata->state = ENVSYS_SVALID; 485 1.1 macallan } 486 1.12 macallan } else if (edata->private > 0) { 487 1.12 macallan /* this works only for the CPU diode */ 488 1.12 macallan int64_t r = smu_read_adc(sc, edata->private); 489 1.12 macallan if (r != -1) { 490 1.12 macallan r = r * sc->cpu_m; 491 1.12 macallan r >>= 3; 492 1.12 macallan r += (int64_t)sc->cpu_b << 9; 493 1.12 macallan r <<= 1; 494 1.12 macallan r *= 15625; 495 1.12 macallan r /= 1024; 496 1.12 macallan edata->value_cur = r + 273150000; 497 1.12 macallan edata->state = ENVSYS_SVALID; 498 1.12 macallan } 499 1.1 macallan } 500 1.1 macallan } 501 1.1 macallan 502 1.1 macallan static int 503 1.1 macallan smu_do_cmd(struct smu_softc *sc, struct smu_cmd *cmd, int timo) 504 1.1 macallan { 505 1.2 macallan int gpio, ret, bail; 506 1.1 macallan u_char ack; 507 1.1 macallan 508 1.1 macallan mutex_enter(&sc->sc_cmd_lock); 509 1.1 macallan 510 1.1 macallan DPRINTF("%s: cmd %02x len %02x\n", __func__, cmd->cmd, cmd->len); 511 1.1 macallan DPRINTF("%s: data %02x %02x %02x %02x %02x %02x %02x %02x\n", __func__, 512 1.1 macallan cmd->data[0], cmd->data[1], cmd->data[2], cmd->data[3], 513 1.1 macallan cmd->data[4], cmd->data[5], cmd->data[6], cmd->data[7]); 514 1.1 macallan 515 1.1 macallan sc->sc_cmd->cmd = cmd->cmd; 516 1.1 macallan sc->sc_cmd->len = cmd->len; 517 1.1 macallan memcpy(sc->sc_cmd->data, cmd->data, cmd->len); 518 1.1 macallan 519 1.1 macallan __asm volatile ("dcbf 0,%0; sync" :: "r"(sc->sc_cmd) : "memory"); 520 1.1 macallan 521 1.1 macallan obio_write_4(sc->sc_dbell_mbox, sc->sc_cmd_paddr); 522 1.1 macallan obio_write_1(sc->sc_dbell_gpio, 0x04); 523 1.1 macallan 524 1.2 macallan bail = 0; 525 1.2 macallan 526 1.2 macallan gpio = obio_read_1(sc->sc_dbell_gpio); 527 1.2 macallan 528 1.2 macallan while (((gpio & 0x07) != 0x07) && (bail < timo)) { 529 1.2 macallan ret = tsleep(sc->sc_cmd, PWAIT, "smu_cmd", mstohz(10)); 530 1.1 macallan if (ret != 0) { 531 1.2 macallan bail++; 532 1.1 macallan } 533 1.1 macallan gpio = obio_read_1(sc->sc_dbell_gpio); 534 1.2 macallan } 535 1.1 macallan 536 1.2 macallan if ((gpio & 0x07) != 0x07) { 537 1.2 macallan mutex_exit(&sc->sc_cmd_lock); 538 1.2 macallan return EWOULDBLOCK; 539 1.2 macallan } 540 1.2 macallan 541 1.1 macallan __asm volatile ("dcbf 0,%0; sync" :: "r"(sc->sc_cmd) : "memory"); 542 1.1 macallan 543 1.1 macallan ack = (~cmd->cmd) & 0xff; 544 1.1 macallan if (sc->sc_cmd->cmd != ack) { 545 1.1 macallan DPRINTF("%s: invalid ack, got %x expected %x\n", 546 1.1 macallan __func__, sc->sc_cmd->cmd, ack); 547 1.1 macallan mutex_exit(&sc->sc_cmd_lock); 548 1.1 macallan return EIO; 549 1.1 macallan } 550 1.1 macallan 551 1.1 macallan cmd->cmd = sc->sc_cmd->cmd; 552 1.1 macallan cmd->len = sc->sc_cmd->len; 553 1.1 macallan memcpy(cmd->data, sc->sc_cmd->data, sc->sc_cmd->len); 554 1.1 macallan 555 1.1 macallan mutex_exit(&sc->sc_cmd_lock); 556 1.1 macallan 557 1.1 macallan return 0; 558 1.1 macallan } 559 1.1 macallan 560 1.1 macallan 561 1.1 macallan static int 562 1.1 macallan smu_dbell_gpio_intr(void *arg) 563 1.1 macallan { 564 1.1 macallan struct smu_softc *sc = arg; 565 1.1 macallan 566 1.1 macallan DPRINTF("%s\n", __func__); 567 1.1 macallan 568 1.1 macallan wakeup(sc->sc_cmd); 569 1.1 macallan 570 1.1 macallan return 1; 571 1.1 macallan } 572 1.1 macallan 573 1.1 macallan void 574 1.1 macallan smu_poweroff(void) 575 1.1 macallan { 576 1.1 macallan struct smu_cmd cmd; 577 1.1 macallan 578 1.1 macallan if (smu0 == NULL) 579 1.1 macallan return; 580 1.1 macallan 581 1.1 macallan cmd.cmd = SMU_CMD_POWER; 582 1.1 macallan strcpy(cmd.data, "SHUTDOWN"); 583 1.1 macallan cmd.len = strlen(cmd.data) + 1; 584 1.1 macallan smu_do_cmd(smu0, &cmd, 800); 585 1.1 macallan 586 1.1 macallan for (;;); 587 1.1 macallan } 588 1.1 macallan 589 1.1 macallan void 590 1.1 macallan smu_restart(void) 591 1.1 macallan { 592 1.1 macallan struct smu_cmd cmd; 593 1.1 macallan 594 1.1 macallan if (smu0 == NULL) 595 1.1 macallan return; 596 1.1 macallan 597 1.1 macallan cmd.cmd = SMU_CMD_POWER; 598 1.1 macallan strcpy(cmd.data, "RESTART"); 599 1.1 macallan cmd.len = strlen(cmd.data) + 1; 600 1.1 macallan smu_do_cmd(smu0, &cmd, 800); 601 1.1 macallan 602 1.1 macallan for (;;); 603 1.1 macallan } 604 1.1 macallan 605 1.1 macallan static int 606 1.1 macallan smu_todr_gettime_ymdhms(todr_chip_handle_t tch, struct clock_ymdhms *dt) 607 1.1 macallan { 608 1.17 thorpej struct smu_softc *sc = device_private(tch->todr_dev); 609 1.1 macallan struct smu_cmd cmd; 610 1.1 macallan int ret; 611 1.1 macallan 612 1.1 macallan cmd.cmd = SMU_CMD_RTC; 613 1.1 macallan cmd.len = 1; 614 1.1 macallan cmd.data[0] = 0x81; 615 1.1 macallan 616 1.1 macallan ret = smu_do_cmd(sc, &cmd, 800); 617 1.1 macallan if (ret != 0) 618 1.1 macallan return ret; 619 1.1 macallan 620 1.1 macallan dt->dt_sec = bcdtobin(cmd.data[0]); 621 1.1 macallan dt->dt_min = bcdtobin(cmd.data[1]); 622 1.1 macallan dt->dt_hour = bcdtobin(cmd.data[2]); 623 1.1 macallan dt->dt_wday = bcdtobin(cmd.data[3]); 624 1.1 macallan dt->dt_day = bcdtobin(cmd.data[4]); 625 1.1 macallan dt->dt_mon = bcdtobin(cmd.data[5]); 626 1.1 macallan dt->dt_year = bcdtobin(cmd.data[6]) + 2000; 627 1.1 macallan 628 1.1 macallan return 0; 629 1.1 macallan } 630 1.1 macallan 631 1.1 macallan static int 632 1.1 macallan smu_todr_settime_ymdhms(todr_chip_handle_t tch, struct clock_ymdhms *dt) 633 1.1 macallan { 634 1.17 thorpej struct smu_softc *sc = device_private(tch->todr_dev); 635 1.1 macallan struct smu_cmd cmd; 636 1.1 macallan 637 1.1 macallan cmd.cmd = SMU_CMD_RTC; 638 1.1 macallan cmd.len = 8; 639 1.1 macallan cmd.data[0] = 0x80; 640 1.1 macallan cmd.data[1] = bintobcd(dt->dt_sec); 641 1.1 macallan cmd.data[2] = bintobcd(dt->dt_min); 642 1.1 macallan cmd.data[3] = bintobcd(dt->dt_hour); 643 1.1 macallan cmd.data[4] = bintobcd(dt->dt_wday); 644 1.1 macallan cmd.data[5] = bintobcd(dt->dt_day); 645 1.1 macallan cmd.data[6] = bintobcd(dt->dt_mon); 646 1.1 macallan cmd.data[7] = bintobcd(dt->dt_year - 2000); 647 1.1 macallan 648 1.1 macallan return smu_do_cmd(sc, &cmd, 800); 649 1.1 macallan } 650 1.1 macallan 651 1.1 macallan static int 652 1.1 macallan smu_fan_update_rpm(struct smu_fan *fan) 653 1.1 macallan { 654 1.1 macallan struct smu_softc *sc = fan->sc; 655 1.1 macallan struct smu_cmd cmd; 656 1.15 macallan int ret, diff; 657 1.1 macallan 658 1.1 macallan cmd.cmd = SMU_CMD_FAN; 659 1.1 macallan cmd.len = 2; 660 1.1 macallan cmd.data[0] = 0x31; 661 1.1 macallan cmd.data[1] = fan->reg; 662 1.1 macallan 663 1.1 macallan ret = smu_do_cmd(sc, &cmd, 800); 664 1.1 macallan if (ret == 0) { 665 1.1 macallan fan->last_update = time_uptime; 666 1.1 macallan fan->current_rpm = (cmd.data[0] << 8) | cmd.data[1]; 667 1.1 macallan } else { 668 1.1 macallan cmd.cmd = SMU_CMD_FAN; 669 1.1 macallan cmd.len = 1; 670 1.1 macallan cmd.data[0] = 0x01; 671 1.1 macallan 672 1.1 macallan ret = smu_do_cmd(sc, &cmd, 800); 673 1.1 macallan if (ret == 0) { 674 1.1 macallan fan->last_update = time_uptime; 675 1.1 macallan fan->current_rpm = (cmd.data[1 + fan->reg * 2] << 8) | 676 1.1 macallan cmd.data[2 + fan->reg * 2]; 677 1.1 macallan } 678 1.1 macallan } 679 1.15 macallan diff = abs(fan->current_rpm - fan->wanted_rpm); 680 1.15 macallan if (diff > fan->max_rpm >> 3) { 681 1.15 macallan fan->fault++; 682 1.15 macallan } else fan->fault = 0; 683 1.1 macallan return ret; 684 1.1 macallan } 685 1.1 macallan 686 1.1 macallan static int 687 1.15 macallan smu_fan_get_rpm(void *cookie, int which) 688 1.1 macallan { 689 1.15 macallan struct smu_softc *sc = cookie; 690 1.15 macallan struct smu_fan *fan = &sc->sc_fans[which]; 691 1.1 macallan int ret; 692 1.4 sevan ret = 0; 693 1.1 macallan 694 1.1 macallan if (time_uptime - fan->last_update > 1) { 695 1.1 macallan ret = smu_fan_update_rpm(fan); 696 1.1 macallan if (ret != 0) 697 1.15 macallan return -1; 698 1.1 macallan } 699 1.1 macallan 700 1.15 macallan return fan->current_rpm; 701 1.1 macallan } 702 1.1 macallan 703 1.1 macallan static int 704 1.15 macallan smu_fan_set_rpm(void *cookie, int which, int rpm) 705 1.1 macallan { 706 1.15 macallan struct smu_softc *sc = cookie; 707 1.15 macallan struct smu_fan *fan = &sc->sc_fans[which]; 708 1.1 macallan struct smu_cmd cmd; 709 1.1 macallan int ret; 710 1.1 macallan 711 1.1 macallan DPRINTF("%s: fan %s rpm %d\n", __func__, fan->location, rpm); 712 1.1 macallan 713 1.6 riastrad rpm = uimax(fan->min_rpm, rpm); 714 1.6 riastrad rpm = uimin(fan->max_rpm, rpm); 715 1.1 macallan 716 1.15 macallan fan->wanted_rpm = rpm; 717 1.15 macallan 718 1.1 macallan cmd.cmd = SMU_CMD_FAN; 719 1.1 macallan cmd.len = 4; 720 1.1 macallan cmd.data[0] = 0x30; 721 1.1 macallan cmd.data[1] = fan->reg; 722 1.1 macallan cmd.data[2] = (rpm >> 8) & 0xff; 723 1.1 macallan cmd.data[3] = rpm & 0xff; 724 1.1 macallan 725 1.1 macallan ret = smu_do_cmd(sc, &cmd, 800); 726 1.1 macallan if (ret != 0) { 727 1.1 macallan cmd.cmd = SMU_CMD_FAN; 728 1.1 macallan cmd.len = 14; 729 1.1 macallan cmd.data[0] = fan->rpm_ctl ? 0x00 : 0x10; 730 1.1 macallan cmd.data[1] = 1 << fan->reg; 731 1.1 macallan cmd.data[2] = cmd.data[2 + fan->reg * 2] = (rpm >> 8) & 0xff; 732 1.1 macallan cmd.data[3] = cmd.data[3 + fan->reg * 2] = rpm & 0xff; 733 1.1 macallan 734 1.1 macallan ret = smu_do_cmd(sc, &cmd, 800); 735 1.1 macallan } 736 1.1 macallan 737 1.1 macallan return ret; 738 1.1 macallan } 739 1.1 macallan 740 1.1 macallan static int 741 1.12 macallan smu_read_adc(struct smu_softc *sc, int id) 742 1.12 macallan { 743 1.12 macallan struct smu_cmd cmd; 744 1.12 macallan int ret; 745 1.12 macallan 746 1.12 macallan cmd.cmd = SMU_CMD_ADC; 747 1.12 macallan cmd.len = 1; 748 1.12 macallan cmd.data[0] = id; 749 1.12 macallan 750 1.12 macallan ret = smu_do_cmd(sc, &cmd, 800); 751 1.12 macallan if (ret == 0) { 752 1.12 macallan return cmd.data[0] << 8 | cmd.data[1]; 753 1.12 macallan } 754 1.12 macallan return -1; 755 1.12 macallan } 756 1.12 macallan 757 1.12 macallan static int 758 1.1 macallan smu_iicbus_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *send, 759 1.1 macallan size_t send_len, void *recv, size_t recv_len, int flags) 760 1.1 macallan { 761 1.1 macallan struct smu_iicbus *iicbus = cookie; 762 1.1 macallan struct smu_softc *sc = iicbus->sc; 763 1.1 macallan struct smu_cmd cmd; 764 1.1 macallan int retries, ret; 765 1.1 macallan 766 1.1 macallan DPRINTF("%s: op %x addr %x send_len %d recv_len %d\n", 767 1.1 macallan __func__, op, addr, send_len, recv_len); 768 1.1 macallan 769 1.1 macallan cmd.cmd = SMU_CMD_I2C; 770 1.1 macallan cmd.len = 9 + recv_len; 771 1.1 macallan cmd.data[0] = iicbus->reg; 772 1.1 macallan cmd.data[1] = I2C_OP_READ_P(op) ? 0x02 : 0x00; 773 1.5 macallan cmd.data[2] = addr << 1; 774 1.1 macallan cmd.data[3] = send_len; 775 1.1 macallan memcpy(&cmd.data[4], send, send_len); 776 1.5 macallan cmd.data[7] = addr << 1; 777 1.1 macallan if (I2C_OP_READ_P(op)) 778 1.1 macallan cmd.data[7] |= 0x01; 779 1.1 macallan cmd.data[8] = recv_len; 780 1.1 macallan memcpy(&cmd.data[9], recv, recv_len); 781 1.1 macallan 782 1.1 macallan ret = smu_do_cmd(sc, &cmd, 800); 783 1.1 macallan if (ret != 0) 784 1.1 macallan return (ret); 785 1.1 macallan 786 1.1 macallan for (retries = 0; retries < 10; retries++) { 787 1.1 macallan cmd.cmd = SMU_CMD_I2C; 788 1.1 macallan cmd.len = 1; 789 1.1 macallan cmd.data[0] = 0x00; 790 1.1 macallan memset(&cmd.data[1], 0xff, recv_len); 791 1.1 macallan 792 1.1 macallan ret = smu_do_cmd(sc, &cmd, 800); 793 1.1 macallan 794 1.1 macallan DPRINTF("%s: cmd data[0] %x\n", __func__, cmd.data[0]); 795 1.1 macallan 796 1.1 macallan if (ret == 0 && (cmd.data[0] & 0x80) == 0) 797 1.1 macallan break; 798 1.1 macallan 799 1.1 macallan DELAY(10000); 800 1.1 macallan } 801 1.1 macallan 802 1.1 macallan if (cmd.data[0] & 0x80) 803 1.1 macallan return EIO; 804 1.1 macallan 805 1.1 macallan if (I2C_OP_READ_P(op)) 806 1.1 macallan memcpy(recv, &cmd.data[1], recv_len); 807 1.1 macallan 808 1.1 macallan return 0; 809 1.1 macallan } 810 1.1 macallan 811 1.1 macallan SYSCTL_SETUP(smu_sysctl_setup, "SMU sysctl subtree setup") 812 1.1 macallan { 813 1.1 macallan sysctl_createv(NULL, 0, NULL, NULL, 814 1.1 macallan CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL, 815 1.1 macallan NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL); 816 1.1 macallan } 817 1.2 macallan 818 1.2 macallan static void 819 1.2 macallan smu_setup_zones(struct smu_softc *sc) 820 1.2 macallan { 821 1.2 macallan struct smu_fan *f; 822 1.15 macallan fancontrol_zone_t *z; 823 1.2 macallan int i; 824 1.2 macallan 825 1.15 macallan /* init zones */ 826 1.15 macallan sc->sc_zones[SMU_ZONE_CPU].name = "CPUs"; 827 1.15 macallan sc->sc_zones[SMU_ZONE_CPU].filter = is_cpu_sensor; 828 1.15 macallan sc->sc_zones[SMU_ZONE_CPU].cookie = sc; 829 1.15 macallan sc->sc_zones[SMU_ZONE_CPU].get_rpm = smu_fan_get_rpm; 830 1.15 macallan sc->sc_zones[SMU_ZONE_CPU].set_rpm = smu_fan_set_rpm; 831 1.15 macallan sc->sc_zones[SMU_ZONE_CPU].Tmin = 45; 832 1.15 macallan sc->sc_zones[SMU_ZONE_CPU].Tmax = 80; 833 1.15 macallan sc->sc_zones[SMU_ZONE_CPU].nfans = 0; 834 1.15 macallan sc->sc_zones[SMU_ZONE_CASE].name = "Slots"; 835 1.15 macallan sc->sc_zones[SMU_ZONE_CASE].filter = is_slots_sensor; 836 1.15 macallan sc->sc_zones[SMU_ZONE_CASE].cookie = sc; 837 1.15 macallan sc->sc_zones[SMU_ZONE_CASE].Tmin = 50; 838 1.15 macallan sc->sc_zones[SMU_ZONE_CASE].Tmax = 75; 839 1.15 macallan sc->sc_zones[SMU_ZONE_CASE].nfans = 0; 840 1.15 macallan sc->sc_zones[SMU_ZONE_CASE].get_rpm = smu_fan_get_rpm; 841 1.15 macallan sc->sc_zones[SMU_ZONE_CASE].set_rpm = smu_fan_set_rpm; 842 1.15 macallan sc->sc_zones[SMU_ZONE_DRIVEBAY].name = "Drivebays"; 843 1.15 macallan sc->sc_zones[SMU_ZONE_DRIVEBAY].filter = is_drive_sensor; 844 1.15 macallan sc->sc_zones[SMU_ZONE_DRIVEBAY].cookie = sc; 845 1.15 macallan sc->sc_zones[SMU_ZONE_DRIVEBAY].get_rpm = smu_fan_get_rpm; 846 1.15 macallan sc->sc_zones[SMU_ZONE_DRIVEBAY].set_rpm = smu_fan_set_rpm; 847 1.15 macallan sc->sc_zones[SMU_ZONE_DRIVEBAY].Tmin = 30; 848 1.15 macallan sc->sc_zones[SMU_ZONE_DRIVEBAY].Tmax = 50; 849 1.15 macallan sc->sc_zones[SMU_ZONE_DRIVEBAY].nfans = 0; 850 1.15 macallan 851 1.2 macallan /* find CPU fans */ 852 1.15 macallan z = &sc->sc_zones[SMU_ZONE_CPU]; 853 1.2 macallan for (i = 0; i < SMU_MAX_FANS; i++) { 854 1.2 macallan f = &sc->sc_fans[i]; 855 1.10 macallan if ((strstr(f->location, "CPU") != NULL) || 856 1.10 macallan (strstr(f->location, "System") != NULL)) { 857 1.15 macallan z->fans[z->nfans].num = i; 858 1.15 macallan z->fans[z->nfans].min_rpm = f->min_rpm; 859 1.15 macallan z->fans[z->nfans].max_rpm = f->max_rpm; 860 1.15 macallan z->fans[z->nfans].name = f->location; 861 1.2 macallan z->nfans++; 862 1.2 macallan } 863 1.2 macallan } 864 1.9 rin aprint_normal_dev(sc->sc_dev, 865 1.9 rin "using %d fans for CPU zone\n", z->nfans); 866 1.2 macallan 867 1.15 macallan z = &sc->sc_zones[SMU_ZONE_DRIVEBAY]; 868 1.2 macallan for (i = 0; i < SMU_MAX_FANS; i++) { 869 1.2 macallan f = &sc->sc_fans[i]; 870 1.10 macallan if ((strstr(f->location, "DRIVE") != NULL) || 871 1.10 macallan (strstr(f->location, "Drive") != NULL)) { 872 1.15 macallan z->fans[z->nfans].num = i; 873 1.15 macallan z->fans[z->nfans].min_rpm = f->min_rpm; 874 1.15 macallan z->fans[z->nfans].max_rpm = f->max_rpm; 875 1.15 macallan z->fans[z->nfans].name = f->location; 876 1.2 macallan z->nfans++; 877 1.2 macallan } 878 1.2 macallan } 879 1.9 rin aprint_normal_dev(sc->sc_dev, 880 1.9 rin "using %d fans for drive bay zone\n", z->nfans); 881 1.2 macallan 882 1.15 macallan z = &sc->sc_zones[SMU_ZONE_CASE]; 883 1.2 macallan for (i = 0; i < SMU_MAX_FANS; i++) { 884 1.2 macallan f = &sc->sc_fans[i]; 885 1.2 macallan if ((strstr(f->location, "BACKSIDE") != NULL) || 886 1.2 macallan (strstr(f->location, "SLOTS") != NULL)) { 887 1.15 macallan z->fans[z->nfans].num = i; 888 1.15 macallan z->fans[z->nfans].min_rpm = f->min_rpm; 889 1.15 macallan z->fans[z->nfans].max_rpm = f->max_rpm; 890 1.15 macallan z->fans[z->nfans].name = f->location; 891 1.2 macallan z->nfans++; 892 1.2 macallan } 893 1.2 macallan } 894 1.9 rin aprint_normal_dev(sc->sc_dev, 895 1.9 rin "using %d fans for expansion slots zone\n", z->nfans); 896 1.15 macallan 897 1.15 macallan /* setup sysctls for our zones etc. */ 898 1.15 macallan for (i = 0; i < SMU_ZONES; i++) { 899 1.15 macallan fancontrol_init_zone(&sc->sc_zones[i], sc->sc_sysctl_me); 900 1.15 macallan } 901 1.2 macallan 902 1.2 macallan sc->sc_dying = false; 903 1.2 macallan kthread_create(PRI_NONE, 0, curcpu(), smu_adjust, sc, &sc->sc_thread, 904 1.2 macallan "fan control"); 905 1.2 macallan } 906 1.2 macallan 907 1.2 macallan static void 908 1.2 macallan smu_adjust(void *cookie) 909 1.2 macallan { 910 1.2 macallan struct smu_softc *sc = cookie; 911 1.2 macallan int i; 912 1.2 macallan 913 1.2 macallan while (!sc->sc_dying) { 914 1.2 macallan for (i = 0; i < SMU_ZONES; i++) 915 1.15 macallan if (sc->sc_zones[i].nfans > 0) 916 1.15 macallan fancontrol_adjust_zone(&sc->sc_zones[i]); 917 1.15 macallan kpause("fanctrl", true, mstohz(2000), NULL); 918 1.2 macallan } 919 1.2 macallan kthread_exit(0); 920 1.2 macallan } 921 1.2 macallan 922 1.2 macallan static bool is_cpu_sensor(const envsys_data_t *edata) 923 1.2 macallan { 924 1.2 macallan if (edata->units != ENVSYS_STEMP) 925 1.2 macallan return false; 926 1.10 macallan if (strstr(edata->desc, "CPU") != NULL) 927 1.2 macallan return TRUE; 928 1.2 macallan return false; 929 1.2 macallan } 930 1.2 macallan 931 1.2 macallan static bool is_drive_sensor(const envsys_data_t *edata) 932 1.2 macallan { 933 1.2 macallan if (edata->units != ENVSYS_STEMP) 934 1.2 macallan return false; 935 1.10 macallan if (strstr(edata->desc, "DRIVE") != NULL) 936 1.10 macallan return TRUE; 937 1.10 macallan if (strstr(edata->desc, "drive") != NULL) 938 1.2 macallan return TRUE; 939 1.2 macallan return false; 940 1.2 macallan } 941 1.2 macallan 942 1.2 macallan static bool is_slots_sensor(const envsys_data_t *edata) 943 1.2 macallan { 944 1.2 macallan if (edata->units != ENVSYS_STEMP) 945 1.2 macallan return false; 946 1.2 macallan if (strstr(edata->desc, "BACKSIDE") != NULL) 947 1.2 macallan return TRUE; 948 1.2 macallan if (strstr(edata->desc, "INLET") != NULL) 949 1.2 macallan return TRUE; 950 1.10 macallan if (strstr(edata->desc, "DIODE") != NULL) 951 1.10 macallan return TRUE; 952 1.10 macallan if (strstr(edata->desc, "TUNNEL") != NULL) 953 1.10 macallan return TRUE; 954 1.2 macallan return false; 955 1.2 macallan } 956 1.5 macallan 957 1.5 macallan int 958 1.5 macallan smu_get_datablock(int id, uint8_t *buf, size_t len) 959 1.5 macallan { 960 1.5 macallan struct smu_cmd cmd; 961 1.5 macallan 962 1.5 macallan cmd.cmd = SMU_PARTITION; 963 1.5 macallan cmd.len = 2; 964 1.5 macallan cmd.data[0] = SMU_PARTITION_LATEST; 965 1.5 macallan cmd.data[1] = id; 966 1.5 macallan smu_do_cmd(smu0, &cmd, 100); 967 1.5 macallan 968 1.5 macallan cmd.data[4] = cmd.data[0]; 969 1.5 macallan cmd.data[5] = cmd.data[1]; 970 1.5 macallan 971 1.5 macallan cmd.cmd = SMU_MISC; 972 1.5 macallan cmd.len = 7; 973 1.5 macallan cmd.data[0] = SMU_MISC_GET_DATA; 974 1.5 macallan cmd.data[1] = 4; 975 1.5 macallan cmd.data[2] = 0; 976 1.5 macallan cmd.data[3] = 0; 977 1.5 macallan cmd.data[6] = len; 978 1.5 macallan smu_do_cmd(smu0, &cmd, 100); 979 1.5 macallan 980 1.5 macallan memcpy(buf, cmd.data, len); 981 1.5 macallan return 0; 982 1.5 macallan } 983