1 /*- 2 * Copyright (c) 2009 Nathan Whitehorn 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 21 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include <sys/param.h> 32 #include <sys/bus.h> 33 #include <sys/systm.h> 34 #include <sys/module.h> 35 #include <sys/conf.h> 36 #include <sys/cpu.h> 37 #include <sys/clock.h> 38 #include <sys/ctype.h> 39 #include <sys/kernel.h> 40 #include <sys/kthread.h> 41 #include <sys/reboot.h> 42 #include <sys/rman.h> 43 #include <sys/sysctl.h> 44 #include <sys/unistd.h> 45 46 #include <machine/bus.h> 47 #include <machine/intr_machdep.h> 48 #include <machine/md_var.h> 49 50 #include <dev/iicbus/iicbus.h> 51 #include <dev/iicbus/iiconf.h> 52 #include <dev/led/led.h> 53 #include <dev/ofw/openfirm.h> 54 #include <dev/ofw/ofw_bus.h> 55 #include <dev/ofw/ofw_bus_subr.h> 56 #include <powerpc/powermac/macgpiovar.h> 57 58 #include "clock_if.h" 59 #include "iicbus_if.h" 60 61 struct smu_cmd { 62 volatile uint8_t cmd; 63 uint8_t len; 64 uint8_t data[254]; 65 66 STAILQ_ENTRY(smu_cmd) cmd_q; 67 }; 68 69 STAILQ_HEAD(smu_cmdq, smu_cmd); 70 71 struct smu_fan { 72 cell_t reg; 73 cell_t min_rpm; 74 cell_t max_rpm; 75 cell_t unmanaged_rpm; 76 char location[32]; 77 78 int old_style; 79 int setpoint; 80 }; 81 82 struct smu_sensor { 83 cell_t reg; 84 char location[32]; 85 enum { 86 SMU_CURRENT_SENSOR, 87 SMU_VOLTAGE_SENSOR, 88 SMU_POWER_SENSOR, 89 SMU_TEMP_SENSOR 90 } type; 91 }; 92 93 struct smu_softc { 94 device_t sc_dev; 95 struct mtx sc_mtx; 96 97 struct resource *sc_memr; 98 int sc_memrid; 99 100 bus_dma_tag_t sc_dmatag; 101 bus_space_tag_t sc_bt; 102 bus_space_handle_t sc_mailbox; 103 104 struct smu_cmd *sc_cmd, *sc_cur_cmd; 105 bus_addr_t sc_cmd_phys; 106 bus_dmamap_t sc_cmd_dmamap; 107 struct smu_cmdq sc_cmdq; 108 109 struct smu_fan *sc_fans; 110 int sc_nfans; 111 struct smu_sensor *sc_sensors; 112 int sc_nsensors; 113 114 int sc_doorbellirqid; 115 struct resource *sc_doorbellirq; 116 void *sc_doorbellirqcookie; 117 118 struct proc *sc_fanmgt_proc; 119 time_t sc_lastuserchange; 120 121 /* Calibration data */ 122 uint16_t sc_cpu_diode_scale; 123 int16_t sc_cpu_diode_offset; 124 125 uint16_t sc_cpu_volt_scale; 126 int16_t sc_cpu_volt_offset; 127 uint16_t sc_cpu_curr_scale; 128 int16_t sc_cpu_curr_offset; 129 130 uint16_t sc_slots_pow_scale; 131 int16_t sc_slots_pow_offset; 132 133 /* Thermal management parameters */ 134 int sc_target_temp; /* Default 55 C */ 135 int sc_critical_temp; /* Default 90 C */ 136 137 struct cdev *sc_leddev; 138 }; 139 140 /* regular bus attachment functions */ 141 142 static int smu_probe(device_t); 143 static int smu_attach(device_t); 144 static const struct ofw_bus_devinfo * 145 smu_get_devinfo(device_t bus, device_t dev); 146 147 /* cpufreq notification hooks */ 148 149 static void smu_cpufreq_pre_change(device_t, const struct cf_level *level); 150 static void smu_cpufreq_post_change(device_t, const struct cf_level *level); 151 152 /* clock interface */ 153 static int smu_gettime(device_t dev, struct timespec *ts); 154 static int smu_settime(device_t dev, struct timespec *ts); 155 156 /* utility functions */ 157 static int smu_run_cmd(device_t dev, struct smu_cmd *cmd, int wait); 158 static int smu_get_datablock(device_t dev, int8_t id, uint8_t *buf, 159 size_t len); 160 static void smu_attach_i2c(device_t dev, phandle_t i2croot); 161 static void smu_attach_fans(device_t dev, phandle_t fanroot); 162 static void smu_attach_sensors(device_t dev, phandle_t sensroot); 163 static void smu_fan_management_proc(void *xdev); 164 static void smu_manage_fans(device_t smu); 165 static void smu_set_sleepled(void *xdev, int onoff); 166 static int smu_server_mode(SYSCTL_HANDLER_ARGS); 167 static void smu_doorbell_intr(void *xdev); 168 169 /* where to find the doorbell GPIO */ 170 171 static device_t smu_doorbell = NULL; 172 173 static device_method_t smu_methods[] = { 174 /* Device interface */ 175 DEVMETHOD(device_probe, smu_probe), 176 DEVMETHOD(device_attach, smu_attach), 177 178 /* Clock interface */ 179 DEVMETHOD(clock_gettime, smu_gettime), 180 DEVMETHOD(clock_settime, smu_settime), 181 182 /* ofw_bus interface */ 183 DEVMETHOD(bus_child_pnpinfo_str,ofw_bus_gen_child_pnpinfo_str), 184 DEVMETHOD(ofw_bus_get_devinfo, smu_get_devinfo), 185 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), 186 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), 187 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), 188 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), 189 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), 190 191 { 0, 0 }, 192 }; 193 194 static driver_t smu_driver = { 195 "smu", 196 smu_methods, 197 sizeof(struct smu_softc) 198 }; 199 200 static devclass_t smu_devclass; 201 202 DRIVER_MODULE(smu, nexus, smu_driver, smu_devclass, 0, 0); 203 MALLOC_DEFINE(M_SMU, "smu", "SMU Sensor Information"); 204 205 #define SMU_MAILBOX 0x8000860c 206 #define SMU_FANMGT_INTERVAL 1000 /* ms */ 207 208 /* Command types */ 209 #define SMU_ADC 0xd8 210 #define SMU_FAN 0x4a 211 #define SMU_I2C 0x9a 212 #define SMU_I2C_SIMPLE 0x00 213 #define SMU_I2C_NORMAL 0x01 214 #define SMU_I2C_COMBINED 0x02 215 #define SMU_MISC 0xee 216 #define SMU_MISC_GET_DATA 0x02 217 #define SMU_MISC_LED_CTRL 0x04 218 #define SMU_POWER 0xaa 219 #define SMU_POWER_EVENTS 0x8f 220 #define SMU_PWR_GET_POWERUP 0x00 221 #define SMU_PWR_SET_POWERUP 0x01 222 #define SMU_PWR_CLR_POWERUP 0x02 223 #define SMU_RTC 0x8e 224 #define SMU_RTC_GET 0x81 225 #define SMU_RTC_SET 0x80 226 227 /* Power event types */ 228 #define SMU_WAKEUP_KEYPRESS 0x01 229 #define SMU_WAKEUP_AC_INSERT 0x02 230 #define SMU_WAKEUP_AC_CHANGE 0x04 231 #define SMU_WAKEUP_RING 0x10 232 233 /* Data blocks */ 234 #define SMU_CPUTEMP_CAL 0x18 235 #define SMU_CPUVOLT_CAL 0x21 236 #define SMU_SLOTPW_CAL 0x78 237 238 /* Partitions */ 239 #define SMU_PARTITION 0x3e 240 #define SMU_PARTITION_LATEST 0x01 241 #define SMU_PARTITION_BASE 0x02 242 #define SMU_PARTITION_UPDATE 0x03 243 244 static int 245 smu_probe(device_t dev) 246 { 247 const char *name = ofw_bus_get_name(dev); 248 249 if (strcmp(name, "smu") != 0) 250 return (ENXIO); 251 252 device_set_desc(dev, "Apple System Management Unit"); 253 return (0); 254 } 255 256 static void 257 smu_phys_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) 258 { 259 struct smu_softc *sc = xsc; 260 261 sc->sc_cmd_phys = segs[0].ds_addr; 262 } 263 264 static int 265 smu_attach(device_t dev) 266 { 267 struct smu_softc *sc; 268 phandle_t node, child; 269 uint8_t data[12]; 270 271 sc = device_get_softc(dev); 272 273 mtx_init(&sc->sc_mtx, "smu", NULL, MTX_DEF); 274 sc->sc_cur_cmd = NULL; 275 sc->sc_doorbellirqid = -1; 276 277 /* 278 * Map the mailbox area. This should be determined from firmware, 279 * but I have not found a simple way to do that. 280 */ 281 bus_dma_tag_create(NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT, 282 BUS_SPACE_MAXADDR, NULL, NULL, PAGE_SIZE, 1, PAGE_SIZE, 0, NULL, 283 NULL, &(sc->sc_dmatag)); 284 sc->sc_bt = &bs_le_tag; 285 bus_space_map(sc->sc_bt, SMU_MAILBOX, 4, 0, &sc->sc_mailbox); 286 287 /* 288 * Allocate the command buffer. This can be anywhere in the low 4 GB 289 * of memory. 290 */ 291 bus_dmamem_alloc(sc->sc_dmatag, (void **)&sc->sc_cmd, BUS_DMA_WAITOK | 292 BUS_DMA_ZERO, &sc->sc_cmd_dmamap); 293 bus_dmamap_load(sc->sc_dmatag, sc->sc_cmd_dmamap, 294 sc->sc_cmd, PAGE_SIZE, smu_phys_callback, sc, 0); 295 STAILQ_INIT(&sc->sc_cmdq); 296 297 /* 298 * Set up handlers to change CPU voltage when CPU frequency is changed. 299 */ 300 EVENTHANDLER_REGISTER(cpufreq_pre_change, smu_cpufreq_pre_change, dev, 301 EVENTHANDLER_PRI_ANY); 302 EVENTHANDLER_REGISTER(cpufreq_post_change, smu_cpufreq_post_change, dev, 303 EVENTHANDLER_PRI_ANY); 304 305 /* 306 * Detect and attach child devices. 307 */ 308 node = ofw_bus_get_node(dev); 309 for (child = OF_child(node); child != 0; child = OF_peer(child)) { 310 char name[32]; 311 memset(name, 0, sizeof(name)); 312 OF_getprop(child, "name", name, sizeof(name)); 313 314 if (strncmp(name, "rpm-fans", 9) == 0 || 315 strncmp(name, "fans", 5) == 0) 316 smu_attach_fans(dev, child); 317 318 if (strncmp(name, "sensors", 8) == 0) 319 smu_attach_sensors(dev, child); 320 321 if (strncmp(name, "smu-i2c-control", 15) == 0) 322 smu_attach_i2c(dev, child); 323 } 324 325 /* Some SMUs have the I2C children directly under the bus. */ 326 smu_attach_i2c(dev, node); 327 328 /* 329 * Collect calibration constants. 330 */ 331 smu_get_datablock(dev, SMU_CPUTEMP_CAL, data, sizeof(data)); 332 sc->sc_cpu_diode_scale = (data[4] << 8) + data[5]; 333 sc->sc_cpu_diode_offset = (data[6] << 8) + data[7]; 334 335 smu_get_datablock(dev, SMU_CPUVOLT_CAL, data, sizeof(data)); 336 sc->sc_cpu_volt_scale = (data[4] << 8) + data[5]; 337 sc->sc_cpu_volt_offset = (data[6] << 8) + data[7]; 338 sc->sc_cpu_curr_scale = (data[8] << 8) + data[9]; 339 sc->sc_cpu_curr_offset = (data[10] << 8) + data[11]; 340 341 smu_get_datablock(dev, SMU_SLOTPW_CAL, data, sizeof(data)); 342 sc->sc_slots_pow_scale = (data[4] << 8) + data[5]; 343 sc->sc_slots_pow_offset = (data[6] << 8) + data[7]; 344 345 /* 346 * Set up simple-minded thermal management. 347 */ 348 sc->sc_target_temp = 55; 349 sc->sc_critical_temp = 90; 350 351 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), 352 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 353 "target_temp", CTLTYPE_INT | CTLFLAG_RW, &sc->sc_target_temp, 354 sizeof(int), "Target temperature (C)"); 355 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), 356 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 357 "critical_temp", CTLTYPE_INT | CTLFLAG_RW, 358 &sc->sc_critical_temp, sizeof(int), "Critical temperature (C)"); 359 360 kproc_create(smu_fan_management_proc, dev, &sc->sc_fanmgt_proc, 361 RFHIGHPID, 0, "smu_thermal"); 362 363 /* 364 * Set up LED interface 365 */ 366 sc->sc_leddev = led_create(smu_set_sleepled, dev, "sleepled"); 367 368 /* 369 * Reset on power loss behavior 370 */ 371 372 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 373 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 374 "server_mode", CTLTYPE_INT | CTLFLAG_RW, dev, 0, 375 smu_server_mode, "I", "Enable reboot after power failure"); 376 377 /* 378 * Set up doorbell interrupt. 379 */ 380 sc->sc_doorbellirqid = 0; 381 sc->sc_doorbellirq = bus_alloc_resource_any(smu_doorbell, SYS_RES_IRQ, 382 &sc->sc_doorbellirqid, RF_ACTIVE); 383 bus_setup_intr(smu_doorbell, sc->sc_doorbellirq, 384 INTR_TYPE_MISC | INTR_MPSAFE, NULL, smu_doorbell_intr, dev, 385 &sc->sc_doorbellirqcookie); 386 powerpc_config_intr(rman_get_start(sc->sc_doorbellirq), 387 INTR_TRIGGER_EDGE, INTR_POLARITY_LOW); 388 389 /* 390 * Connect RTC interface. 391 */ 392 clock_register(dev, 1000); 393 394 return (bus_generic_attach(dev)); 395 } 396 397 static const struct ofw_bus_devinfo * 398 smu_get_devinfo(device_t bus, device_t dev) 399 { 400 401 return (device_get_ivars(dev)); 402 } 403 404 static void 405 smu_send_cmd(device_t dev, struct smu_cmd *cmd) 406 { 407 struct smu_softc *sc; 408 409 sc = device_get_softc(dev); 410 411 mtx_assert(&sc->sc_mtx, MA_OWNED); 412 413 powerpc_pow_enabled = 0; /* SMU cannot work if we go to NAP */ 414 sc->sc_cur_cmd = cmd; 415 416 /* Copy the command to the mailbox */ 417 sc->sc_cmd->cmd = cmd->cmd; 418 sc->sc_cmd->len = cmd->len; 419 memcpy(sc->sc_cmd->data, cmd->data, sizeof(cmd->data)); 420 bus_dmamap_sync(sc->sc_dmatag, sc->sc_cmd_dmamap, BUS_DMASYNC_PREWRITE); 421 bus_space_write_4(sc->sc_bt, sc->sc_mailbox, 0, sc->sc_cmd_phys); 422 423 /* Flush the cacheline it is in -- SMU bypasses the cache */ 424 __asm __volatile("sync; dcbf 0,%0; sync" :: "r"(sc->sc_cmd): "memory"); 425 426 /* Ring SMU doorbell */ 427 macgpio_write(smu_doorbell, GPIO_DDR_OUTPUT); 428 } 429 430 static void 431 smu_doorbell_intr(void *xdev) 432 { 433 device_t smu; 434 struct smu_softc *sc; 435 int doorbell_ack; 436 437 smu = xdev; 438 doorbell_ack = macgpio_read(smu_doorbell); 439 sc = device_get_softc(smu); 440 441 if (doorbell_ack != (GPIO_DDR_OUTPUT | GPIO_LEVEL_RO | GPIO_DATA)) 442 return; 443 444 mtx_lock(&sc->sc_mtx); 445 446 if (sc->sc_cur_cmd == NULL) /* spurious */ 447 goto done; 448 449 /* Check result. First invalidate the cache again... */ 450 __asm __volatile("dcbf 0,%0; sync" :: "r"(sc->sc_cmd) : "memory"); 451 452 bus_dmamap_sync(sc->sc_dmatag, sc->sc_cmd_dmamap, BUS_DMASYNC_POSTREAD); 453 454 sc->sc_cur_cmd->cmd = sc->sc_cmd->cmd; 455 sc->sc_cur_cmd->len = sc->sc_cmd->len; 456 memcpy(sc->sc_cur_cmd->data, sc->sc_cmd->data, 457 sizeof(sc->sc_cmd->data)); 458 wakeup(sc->sc_cur_cmd); 459 sc->sc_cur_cmd = NULL; 460 powerpc_pow_enabled = 1; 461 462 done: 463 /* Queue next command if one is pending */ 464 if (STAILQ_FIRST(&sc->sc_cmdq) != NULL) { 465 sc->sc_cur_cmd = STAILQ_FIRST(&sc->sc_cmdq); 466 STAILQ_REMOVE_HEAD(&sc->sc_cmdq, cmd_q); 467 smu_send_cmd(smu, sc->sc_cur_cmd); 468 } 469 470 mtx_unlock(&sc->sc_mtx); 471 } 472 473 static int 474 smu_run_cmd(device_t dev, struct smu_cmd *cmd, int wait) 475 { 476 struct smu_softc *sc; 477 uint8_t cmd_code; 478 int error; 479 480 sc = device_get_softc(dev); 481 cmd_code = cmd->cmd; 482 483 mtx_lock(&sc->sc_mtx); 484 if (sc->sc_cur_cmd != NULL) { 485 STAILQ_INSERT_TAIL(&sc->sc_cmdq, cmd, cmd_q); 486 } else 487 smu_send_cmd(dev, cmd); 488 mtx_unlock(&sc->sc_mtx); 489 490 if (!wait) 491 return (0); 492 493 if (sc->sc_doorbellirqid < 0) { 494 /* Poll if the IRQ has not been set up yet */ 495 do { 496 DELAY(50); 497 smu_doorbell_intr(dev); 498 } while (sc->sc_cur_cmd != NULL); 499 } else { 500 /* smu_doorbell_intr will wake us when the command is ACK'ed */ 501 error = tsleep(cmd, 0, "smu", 800 * hz / 1000); 502 if (error != 0) 503 smu_doorbell_intr(dev); /* One last chance */ 504 505 if (error != 0) { 506 mtx_lock(&sc->sc_mtx); 507 if (cmd->cmd == cmd_code) { /* Never processed */ 508 /* Abort this command if we timed out */ 509 if (sc->sc_cur_cmd == cmd) 510 sc->sc_cur_cmd = NULL; 511 else 512 STAILQ_REMOVE(&sc->sc_cmdq, cmd, smu_cmd, 513 cmd_q); 514 mtx_unlock(&sc->sc_mtx); 515 return (error); 516 } 517 error = 0; 518 mtx_unlock(&sc->sc_mtx); 519 } 520 } 521 522 /* SMU acks the command by inverting the command bits */ 523 if (cmd->cmd == ((~cmd_code) & 0xff)) 524 error = 0; 525 else 526 error = EIO; 527 528 return (error); 529 } 530 531 static int 532 smu_get_datablock(device_t dev, int8_t id, uint8_t *buf, size_t len) 533 { 534 struct smu_cmd cmd; 535 uint8_t addr[4]; 536 537 cmd.cmd = SMU_PARTITION; 538 cmd.len = 2; 539 cmd.data[0] = SMU_PARTITION_LATEST; 540 cmd.data[1] = id; 541 542 smu_run_cmd(dev, &cmd, 1); 543 544 addr[0] = addr[1] = 0; 545 addr[2] = cmd.data[0]; 546 addr[3] = cmd.data[1]; 547 548 cmd.cmd = SMU_MISC; 549 cmd.len = 7; 550 cmd.data[0] = SMU_MISC_GET_DATA; 551 cmd.data[1] = sizeof(addr); 552 memcpy(&cmd.data[2], addr, sizeof(addr)); 553 cmd.data[6] = len; 554 555 smu_run_cmd(dev, &cmd, 1); 556 memcpy(buf, cmd.data, len); 557 return (0); 558 } 559 560 static void 561 smu_slew_cpu_voltage(device_t dev, int to) 562 { 563 struct smu_cmd cmd; 564 565 cmd.cmd = SMU_POWER; 566 cmd.len = 8; 567 cmd.data[0] = 'V'; 568 cmd.data[1] = 'S'; 569 cmd.data[2] = 'L'; 570 cmd.data[3] = 'E'; 571 cmd.data[4] = 'W'; 572 cmd.data[5] = 0xff; 573 cmd.data[6] = 1; 574 cmd.data[7] = to; 575 576 smu_run_cmd(dev, &cmd, 1); 577 } 578 579 static void 580 smu_cpufreq_pre_change(device_t dev, const struct cf_level *level) 581 { 582 /* 583 * Make sure the CPU voltage is raised before we raise 584 * the clock. 585 */ 586 587 if (level->rel_set[0].freq == 10000 /* max */) 588 smu_slew_cpu_voltage(dev, 0); 589 } 590 591 static void 592 smu_cpufreq_post_change(device_t dev, const struct cf_level *level) 593 { 594 /* We are safe to reduce CPU voltage after a downward transition */ 595 596 if (level->rel_set[0].freq < 10000 /* max */) 597 smu_slew_cpu_voltage(dev, 1); /* XXX: 1/4 voltage for 970MP? */ 598 } 599 600 /* Routines for probing the SMU doorbell GPIO */ 601 static int doorbell_probe(device_t dev); 602 static int doorbell_attach(device_t dev); 603 604 static device_method_t doorbell_methods[] = { 605 /* Device interface */ 606 DEVMETHOD(device_probe, doorbell_probe), 607 DEVMETHOD(device_attach, doorbell_attach), 608 { 0, 0 }, 609 }; 610 611 static driver_t doorbell_driver = { 612 "smudoorbell", 613 doorbell_methods, 614 0 615 }; 616 617 static devclass_t doorbell_devclass; 618 619 DRIVER_MODULE(smudoorbell, macgpio, doorbell_driver, doorbell_devclass, 0, 0); 620 621 static int 622 doorbell_probe(device_t dev) 623 { 624 const char *name = ofw_bus_get_name(dev); 625 626 if (strcmp(name, "smu-doorbell") != 0) 627 return (ENXIO); 628 629 device_set_desc(dev, "SMU Doorbell GPIO"); 630 device_quiet(dev); 631 return (0); 632 } 633 634 static int 635 doorbell_attach(device_t dev) 636 { 637 smu_doorbell = dev; 638 return (0); 639 } 640 641 /* 642 * Sensor and fan management 643 */ 644 645 static int 646 smu_fan_set_rpm(device_t smu, struct smu_fan *fan, int rpm) 647 { 648 struct smu_cmd cmd; 649 int error; 650 651 cmd.cmd = SMU_FAN; 652 error = EIO; 653 654 /* Clamp to allowed range */ 655 rpm = max(fan->min_rpm, rpm); 656 rpm = min(fan->max_rpm, rpm); 657 658 /* 659 * Apple has two fan control mechanisms. We can't distinguish 660 * them except by seeing if the new one fails. If the new one 661 * fails, use the old one. 662 */ 663 664 if (!fan->old_style) { 665 cmd.len = 4; 666 cmd.data[0] = 0x30; 667 cmd.data[1] = fan->reg; 668 cmd.data[2] = (rpm >> 8) & 0xff; 669 cmd.data[3] = rpm & 0xff; 670 671 error = smu_run_cmd(smu, &cmd, 1); 672 if (error) 673 fan->old_style = 1; 674 } 675 676 if (fan->old_style) { 677 cmd.len = 14; 678 cmd.data[0] = 0; 679 cmd.data[1] = 1 << fan->reg; 680 cmd.data[2 + 2*fan->reg] = (rpm >> 8) & 0xff; 681 cmd.data[3 + 2*fan->reg] = rpm & 0xff; 682 error = smu_run_cmd(smu, &cmd, 1); 683 } 684 685 if (error == 0) 686 fan->setpoint = rpm; 687 688 return (error); 689 } 690 691 static int 692 smu_fan_read_rpm(device_t smu, struct smu_fan *fan) 693 { 694 struct smu_cmd cmd; 695 int rpm, error; 696 697 if (!fan->old_style) { 698 cmd.cmd = SMU_FAN; 699 cmd.len = 2; 700 cmd.data[0] = 0x31; 701 cmd.data[1] = fan->reg; 702 703 error = smu_run_cmd(smu, &cmd, 1); 704 if (error) 705 fan->old_style = 1; 706 707 rpm = (cmd.data[0] << 8) | cmd.data[1]; 708 } 709 710 if (fan->old_style) { 711 cmd.cmd = SMU_FAN; 712 cmd.len = 1; 713 cmd.data[0] = 1; 714 715 error = smu_run_cmd(smu, &cmd, 1); 716 if (error) 717 return (error); 718 719 rpm = (cmd.data[fan->reg*2+1] << 8) | cmd.data[fan->reg*2+2]; 720 } 721 722 return (rpm); 723 } 724 725 static int 726 smu_fanrpm_sysctl(SYSCTL_HANDLER_ARGS) 727 { 728 device_t smu; 729 struct smu_softc *sc; 730 struct smu_fan *fan; 731 int rpm, error; 732 733 smu = arg1; 734 sc = device_get_softc(smu); 735 fan = &sc->sc_fans[arg2]; 736 737 rpm = smu_fan_read_rpm(smu, fan); 738 if (rpm < 0) 739 return (rpm); 740 741 error = sysctl_handle_int(oidp, &rpm, 0, req); 742 743 if (error || !req->newptr) 744 return (error); 745 746 sc->sc_lastuserchange = time_uptime; 747 748 return (smu_fan_set_rpm(smu, fan, rpm)); 749 } 750 751 static void 752 smu_attach_fans(device_t dev, phandle_t fanroot) 753 { 754 struct smu_fan *fan; 755 struct smu_softc *sc; 756 struct sysctl_oid *oid, *fanroot_oid; 757 struct sysctl_ctx_list *ctx; 758 phandle_t child; 759 char type[32], sysctl_name[32]; 760 int i; 761 762 sc = device_get_softc(dev); 763 sc->sc_nfans = 0; 764 765 for (child = OF_child(fanroot); child != 0; child = OF_peer(child)) 766 sc->sc_nfans++; 767 768 if (sc->sc_nfans == 0) { 769 device_printf(dev, "WARNING: No fans detected!\n"); 770 return; 771 } 772 773 sc->sc_fans = malloc(sc->sc_nfans * sizeof(struct smu_fan), M_SMU, 774 M_WAITOK | M_ZERO); 775 776 fan = sc->sc_fans; 777 sc->sc_nfans = 0; 778 779 ctx = device_get_sysctl_ctx(dev); 780 fanroot_oid = SYSCTL_ADD_NODE(ctx, 781 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "fans", 782 CTLFLAG_RD, 0, "SMU Fan Information"); 783 784 for (child = OF_child(fanroot); child != 0; child = OF_peer(child)) { 785 OF_getprop(child, "device_type", type, sizeof(type)); 786 if (strcmp(type, "fan-rpm-control") != 0) 787 continue; 788 789 fan->old_style = 0; 790 OF_getprop(child, "reg", &fan->reg, sizeof(cell_t)); 791 OF_getprop(child, "min-value", &fan->min_rpm, sizeof(cell_t)); 792 OF_getprop(child, "max-value", &fan->max_rpm, sizeof(cell_t)); 793 794 if (OF_getprop(child, "unmanaged-value", &fan->unmanaged_rpm, 795 sizeof(cell_t)) != sizeof(cell_t)) 796 fan->unmanaged_rpm = fan->max_rpm; 797 798 fan->setpoint = smu_fan_read_rpm(dev, fan); 799 800 OF_getprop(child, "location", fan->location, 801 sizeof(fan->location)); 802 803 /* Add sysctls */ 804 for (i = 0; i < strlen(fan->location); i++) { 805 sysctl_name[i] = tolower(fan->location[i]); 806 if (isspace(sysctl_name[i])) 807 sysctl_name[i] = '_'; 808 } 809 sysctl_name[i] = 0; 810 811 oid = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(fanroot_oid), 812 OID_AUTO, sysctl_name, CTLFLAG_RD, 0, "Fan Information"); 813 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "minrpm", 814 CTLTYPE_INT | CTLFLAG_RD, &fan->min_rpm, sizeof(cell_t), 815 "Minimum allowed RPM"); 816 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "maxrpm", 817 CTLTYPE_INT | CTLFLAG_RD, &fan->max_rpm, sizeof(cell_t), 818 "Maximum allowed RPM"); 819 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "rpm", 820 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, 821 sc->sc_nfans, smu_fanrpm_sysctl, "I", "Fan RPM"); 822 823 fan++; 824 sc->sc_nfans++; 825 } 826 } 827 828 static int 829 smu_sensor_read(device_t smu, struct smu_sensor *sens, int *val) 830 { 831 struct smu_cmd cmd; 832 struct smu_softc *sc; 833 int64_t value; 834 int error; 835 836 cmd.cmd = SMU_ADC; 837 cmd.len = 1; 838 cmd.data[0] = sens->reg; 839 error = 0; 840 841 error = smu_run_cmd(smu, &cmd, 1); 842 if (error != 0) 843 return (error); 844 845 sc = device_get_softc(smu); 846 value = (cmd.data[0] << 8) | cmd.data[1]; 847 848 switch (sens->type) { 849 case SMU_TEMP_SENSOR: 850 value *= sc->sc_cpu_diode_scale; 851 value >>= 3; 852 value += ((int64_t)sc->sc_cpu_diode_offset) << 9; 853 value <<= 1; 854 855 /* Convert from 16.16 fixed point degC into integer C. */ 856 value >>= 16; 857 break; 858 case SMU_VOLTAGE_SENSOR: 859 value *= sc->sc_cpu_volt_scale; 860 value += sc->sc_cpu_volt_offset; 861 value <<= 4; 862 863 /* Convert from 16.16 fixed point V into mV. */ 864 value *= 15625; 865 value /= 1024; 866 value /= 1000; 867 break; 868 case SMU_CURRENT_SENSOR: 869 value *= sc->sc_cpu_curr_scale; 870 value += sc->sc_cpu_curr_offset; 871 value <<= 4; 872 873 /* Convert from 16.16 fixed point A into mA. */ 874 value *= 15625; 875 value /= 1024; 876 value /= 1000; 877 break; 878 case SMU_POWER_SENSOR: 879 value *= sc->sc_slots_pow_scale; 880 value += sc->sc_slots_pow_offset; 881 value <<= 4; 882 883 /* Convert from 16.16 fixed point W into mW. */ 884 value *= 15625; 885 value /= 1024; 886 value /= 1000; 887 break; 888 } 889 890 *val = value; 891 return (0); 892 } 893 894 static int 895 smu_sensor_sysctl(SYSCTL_HANDLER_ARGS) 896 { 897 device_t smu; 898 struct smu_softc *sc; 899 struct smu_sensor *sens; 900 int value, error; 901 902 smu = arg1; 903 sc = device_get_softc(smu); 904 sens = &sc->sc_sensors[arg2]; 905 906 error = smu_sensor_read(smu, sens, &value); 907 if (error != 0) 908 return (error); 909 910 error = sysctl_handle_int(oidp, &value, 0, req); 911 912 return (error); 913 } 914 915 static void 916 smu_attach_sensors(device_t dev, phandle_t sensroot) 917 { 918 struct smu_sensor *sens; 919 struct smu_softc *sc; 920 struct sysctl_oid *sensroot_oid; 921 struct sysctl_ctx_list *ctx; 922 phandle_t child; 923 char type[32]; 924 int i; 925 926 sc = device_get_softc(dev); 927 sc->sc_nsensors = 0; 928 929 for (child = OF_child(sensroot); child != 0; child = OF_peer(child)) 930 sc->sc_nsensors++; 931 932 if (sc->sc_nsensors == 0) { 933 device_printf(dev, "WARNING: No sensors detected!\n"); 934 return; 935 } 936 937 sc->sc_sensors = malloc(sc->sc_nsensors * sizeof(struct smu_sensor), 938 M_SMU, M_WAITOK | M_ZERO); 939 940 sens = sc->sc_sensors; 941 sc->sc_nsensors = 0; 942 943 ctx = device_get_sysctl_ctx(dev); 944 sensroot_oid = SYSCTL_ADD_NODE(ctx, 945 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "sensors", 946 CTLFLAG_RD, 0, "SMU Sensor Information"); 947 948 for (child = OF_child(sensroot); child != 0; child = OF_peer(child)) { 949 char sysctl_name[40], sysctl_desc[40]; 950 const char *units; 951 952 OF_getprop(child, "device_type", type, sizeof(type)); 953 954 if (strcmp(type, "current-sensor") == 0) { 955 sens->type = SMU_CURRENT_SENSOR; 956 units = "mA"; 957 } else if (strcmp(type, "temp-sensor") == 0) { 958 sens->type = SMU_TEMP_SENSOR; 959 units = "C"; 960 } else if (strcmp(type, "voltage-sensor") == 0) { 961 sens->type = SMU_VOLTAGE_SENSOR; 962 units = "mV"; 963 } else if (strcmp(type, "power-sensor") == 0) { 964 sens->type = SMU_POWER_SENSOR; 965 units = "mW"; 966 } else { 967 continue; 968 } 969 970 OF_getprop(child, "reg", &sens->reg, sizeof(cell_t)); 971 OF_getprop(child, "location", sens->location, 972 sizeof(sens->location)); 973 974 for (i = 0; i < strlen(sens->location); i++) { 975 sysctl_name[i] = tolower(sens->location[i]); 976 if (isspace(sysctl_name[i])) 977 sysctl_name[i] = '_'; 978 } 979 sysctl_name[i] = 0; 980 981 sprintf(sysctl_desc,"%s (%s)", sens->location, units); 982 983 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(sensroot_oid), OID_AUTO, 984 sysctl_name, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 985 dev, sc->sc_nsensors, smu_sensor_sysctl, "I", sysctl_desc); 986 987 sens++; 988 sc->sc_nsensors++; 989 } 990 } 991 992 static void 993 smu_fan_management_proc(void *xdev) 994 { 995 device_t smu = xdev; 996 997 while(1) { 998 smu_manage_fans(smu); 999 pause("smu", SMU_FANMGT_INTERVAL * hz / 1000); 1000 } 1001 } 1002 1003 static void 1004 smu_manage_fans(device_t smu) 1005 { 1006 struct smu_softc *sc; 1007 int i, maxtemp, temp, factor, error; 1008 1009 sc = device_get_softc(smu); 1010 1011 maxtemp = 0; 1012 for (i = 0; i < sc->sc_nsensors; i++) { 1013 if (sc->sc_sensors[i].type != SMU_TEMP_SENSOR) 1014 continue; 1015 1016 error = smu_sensor_read(smu, &sc->sc_sensors[i], &temp); 1017 if (error == 0 && temp > maxtemp) 1018 maxtemp = temp; 1019 } 1020 1021 if (maxtemp > sc->sc_critical_temp) { 1022 device_printf(smu, "WARNING: Current system temperature (%d C) " 1023 "exceeds critical temperature (%d C)! Shutting down!\n", 1024 maxtemp, sc->sc_critical_temp); 1025 shutdown_nice(RB_POWEROFF); 1026 } 1027 1028 if (maxtemp - sc->sc_target_temp > 20) 1029 device_printf(smu, "WARNING: Current system temperature (%d C) " 1030 "more than 20 degrees over target temperature (%d C)!\n", 1031 maxtemp, sc->sc_target_temp); 1032 1033 if (time_uptime - sc->sc_lastuserchange < 3) { 1034 /* 1035 * If we have heard from a user process in the last 3 seconds, 1036 * go away. 1037 */ 1038 1039 return; 1040 } 1041 1042 if (maxtemp < 10) { /* Bail if no good sensors */ 1043 for (i = 0; i < sc->sc_nfans; i++) 1044 smu_fan_set_rpm(smu, &sc->sc_fans[i], 1045 sc->sc_fans[i].unmanaged_rpm); 1046 return; 1047 } 1048 1049 if (maxtemp - sc->sc_target_temp > 4) 1050 factor = 110; 1051 else if (maxtemp - sc->sc_target_temp > 1) 1052 factor = 105; 1053 else if (sc->sc_target_temp - maxtemp > 4) 1054 factor = 90; 1055 else if (sc->sc_target_temp - maxtemp > 1) 1056 factor = 95; 1057 else 1058 factor = 100; 1059 1060 for (i = 0; i < sc->sc_nfans; i++) 1061 smu_fan_set_rpm(smu, &sc->sc_fans[i], 1062 (sc->sc_fans[i].setpoint * factor) / 100); 1063 } 1064 1065 static void 1066 smu_set_sleepled(void *xdev, int onoff) 1067 { 1068 static struct smu_cmd cmd; 1069 device_t smu = xdev; 1070 1071 cmd.cmd = SMU_MISC; 1072 cmd.len = 3; 1073 cmd.data[0] = SMU_MISC_LED_CTRL; 1074 cmd.data[1] = 0; 1075 cmd.data[2] = onoff; 1076 1077 smu_run_cmd(smu, &cmd, 0); 1078 } 1079 1080 static int 1081 smu_server_mode(SYSCTL_HANDLER_ARGS) 1082 { 1083 struct smu_cmd cmd; 1084 u_int server_mode; 1085 device_t smu = arg1; 1086 int error; 1087 1088 cmd.cmd = SMU_POWER_EVENTS; 1089 cmd.len = 1; 1090 cmd.data[0] = SMU_PWR_GET_POWERUP; 1091 1092 error = smu_run_cmd(smu, &cmd, 1); 1093 1094 if (error) 1095 return (error); 1096 1097 server_mode = (cmd.data[1] & SMU_WAKEUP_AC_INSERT) ? 1 : 0; 1098 1099 error = sysctl_handle_int(oidp, &server_mode, 0, req); 1100 1101 if (error || !req->newptr) 1102 return (error); 1103 1104 if (server_mode == 1) 1105 cmd.data[0] = SMU_PWR_SET_POWERUP; 1106 else if (server_mode == 0) 1107 cmd.data[0] = SMU_PWR_CLR_POWERUP; 1108 else 1109 return (EINVAL); 1110 1111 cmd.len = 3; 1112 cmd.data[1] = 0; 1113 cmd.data[2] = SMU_WAKEUP_AC_INSERT; 1114 1115 return (smu_run_cmd(smu, &cmd, 1)); 1116 } 1117 1118 static int 1119 smu_gettime(device_t dev, struct timespec *ts) 1120 { 1121 struct smu_cmd cmd; 1122 struct clocktime ct; 1123 1124 cmd.cmd = SMU_RTC; 1125 cmd.len = 1; 1126 cmd.data[0] = SMU_RTC_GET; 1127 1128 if (smu_run_cmd(dev, &cmd, 1) != 0) 1129 return (ENXIO); 1130 1131 ct.nsec = 0; 1132 ct.sec = bcd2bin(cmd.data[0]); 1133 ct.min = bcd2bin(cmd.data[1]); 1134 ct.hour = bcd2bin(cmd.data[2]); 1135 ct.dow = bcd2bin(cmd.data[3]); 1136 ct.day = bcd2bin(cmd.data[4]); 1137 ct.mon = bcd2bin(cmd.data[5]); 1138 ct.year = bcd2bin(cmd.data[6]) + 2000; 1139 1140 return (clock_ct_to_ts(&ct, ts)); 1141 } 1142 1143 static int 1144 smu_settime(device_t dev, struct timespec *ts) 1145 { 1146 struct smu_cmd cmd; 1147 struct clocktime ct; 1148 1149 cmd.cmd = SMU_RTC; 1150 cmd.len = 8; 1151 cmd.data[0] = SMU_RTC_SET; 1152 1153 clock_ts_to_ct(ts, &ct); 1154 1155 cmd.data[1] = bin2bcd(ct.sec); 1156 cmd.data[2] = bin2bcd(ct.min); 1157 cmd.data[3] = bin2bcd(ct.hour); 1158 cmd.data[4] = bin2bcd(ct.dow); 1159 cmd.data[5] = bin2bcd(ct.day); 1160 cmd.data[6] = bin2bcd(ct.mon); 1161 cmd.data[7] = bin2bcd(ct.year - 2000); 1162 1163 return (smu_run_cmd(dev, &cmd, 1)); 1164 } 1165 1166 /* SMU I2C Interface */ 1167 1168 static int smuiic_probe(device_t dev); 1169 static int smuiic_attach(device_t dev); 1170 static int smuiic_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs); 1171 static phandle_t smuiic_get_node(device_t bus, device_t dev); 1172 1173 static device_method_t smuiic_methods[] = { 1174 /* device interface */ 1175 DEVMETHOD(device_probe, smuiic_probe), 1176 DEVMETHOD(device_attach, smuiic_attach), 1177 1178 /* iicbus interface */ 1179 DEVMETHOD(iicbus_callback, iicbus_null_callback), 1180 DEVMETHOD(iicbus_transfer, smuiic_transfer), 1181 1182 /* ofw_bus interface */ 1183 DEVMETHOD(ofw_bus_get_node, smuiic_get_node), 1184 1185 { 0, 0 } 1186 }; 1187 1188 struct smuiic_softc { 1189 struct mtx sc_mtx; 1190 volatile int sc_iic_inuse; 1191 int sc_busno; 1192 }; 1193 1194 static driver_t smuiic_driver = { 1195 "iichb", 1196 smuiic_methods, 1197 sizeof(struct smuiic_softc) 1198 }; 1199 static devclass_t smuiic_devclass; 1200 1201 DRIVER_MODULE(smuiic, smu, smuiic_driver, smuiic_devclass, 0, 0); 1202 1203 static void 1204 smu_attach_i2c(device_t smu, phandle_t i2croot) 1205 { 1206 phandle_t child; 1207 device_t cdev; 1208 struct ofw_bus_devinfo *dinfo; 1209 char name[32]; 1210 1211 for (child = OF_child(i2croot); child != 0; child = OF_peer(child)) { 1212 if (OF_getprop(child, "name", name, sizeof(name)) <= 0) 1213 continue; 1214 1215 if (strcmp(name, "i2c-bus") != 0 && strcmp(name, "i2c") != 0) 1216 continue; 1217 1218 dinfo = malloc(sizeof(struct ofw_bus_devinfo), M_SMU, 1219 M_WAITOK | M_ZERO); 1220 if (ofw_bus_gen_setup_devinfo(dinfo, child) != 0) { 1221 free(dinfo, M_SMU); 1222 continue; 1223 } 1224 1225 cdev = device_add_child(smu, NULL, -1); 1226 if (cdev == NULL) { 1227 device_printf(smu, "<%s>: device_add_child failed\n", 1228 dinfo->obd_name); 1229 ofw_bus_gen_destroy_devinfo(dinfo); 1230 free(dinfo, M_SMU); 1231 continue; 1232 } 1233 device_set_ivars(cdev, dinfo); 1234 } 1235 } 1236 1237 static int 1238 smuiic_probe(device_t dev) 1239 { 1240 const char *name; 1241 1242 name = ofw_bus_get_name(dev); 1243 if (name == NULL) 1244 return (ENXIO); 1245 1246 if (strcmp(name, "i2c-bus") == 0 || strcmp(name, "i2c") == 0) { 1247 device_set_desc(dev, "SMU I2C controller"); 1248 return (0); 1249 } 1250 1251 return (ENXIO); 1252 } 1253 1254 static int 1255 smuiic_attach(device_t dev) 1256 { 1257 struct smuiic_softc *sc = device_get_softc(dev); 1258 mtx_init(&sc->sc_mtx, "smuiic", NULL, MTX_DEF); 1259 sc->sc_iic_inuse = 0; 1260 1261 /* Get our bus number */ 1262 OF_getprop(ofw_bus_get_node(dev), "reg", &sc->sc_busno, 1263 sizeof(sc->sc_busno)); 1264 1265 /* Add the IIC bus layer */ 1266 device_add_child(dev, "iicbus", -1); 1267 1268 return (bus_generic_attach(dev)); 1269 } 1270 1271 static int 1272 smuiic_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) 1273 { 1274 struct smuiic_softc *sc = device_get_softc(dev); 1275 struct smu_cmd cmd; 1276 int i, j, error; 1277 1278 mtx_lock(&sc->sc_mtx); 1279 while (sc->sc_iic_inuse) 1280 mtx_sleep(sc, &sc->sc_mtx, 0, "smuiic", 100); 1281 1282 sc->sc_iic_inuse = 1; 1283 error = 0; 1284 1285 for (i = 0; i < nmsgs; i++) { 1286 cmd.cmd = SMU_I2C; 1287 cmd.data[0] = sc->sc_busno; 1288 if (msgs[i].flags & IIC_M_NOSTOP) 1289 cmd.data[1] = SMU_I2C_COMBINED; 1290 else 1291 cmd.data[1] = SMU_I2C_SIMPLE; 1292 1293 cmd.data[2] = msgs[i].slave; 1294 if (msgs[i].flags & IIC_M_RD) 1295 cmd.data[2] |= 1; 1296 1297 if (msgs[i].flags & IIC_M_NOSTOP) { 1298 KASSERT(msgs[i].len < 4, 1299 ("oversize I2C combined message")); 1300 1301 cmd.data[3] = min(msgs[i].len, 3); 1302 memcpy(&cmd.data[4], msgs[i].buf, min(msgs[i].len, 3)); 1303 i++; /* Advance to next part of message */ 1304 } else { 1305 cmd.data[3] = 0; 1306 memset(&cmd.data[4], 0, 3); 1307 } 1308 1309 cmd.data[7] = msgs[i].slave; 1310 if (msgs[i].flags & IIC_M_RD) 1311 cmd.data[7] |= 1; 1312 1313 cmd.data[8] = msgs[i].len; 1314 if (msgs[i].flags & IIC_M_RD) { 1315 memset(&cmd.data[9], 0xff, msgs[i].len); 1316 cmd.len = 9; 1317 } else { 1318 memcpy(&cmd.data[9], msgs[i].buf, msgs[i].len); 1319 cmd.len = 9 + msgs[i].len; 1320 } 1321 1322 mtx_unlock(&sc->sc_mtx); 1323 smu_run_cmd(device_get_parent(dev), &cmd, 1); 1324 mtx_lock(&sc->sc_mtx); 1325 1326 for (j = 0; j < 10; j++) { 1327 cmd.cmd = SMU_I2C; 1328 cmd.len = 1; 1329 cmd.data[0] = 0; 1330 memset(&cmd.data[1], 0xff, msgs[i].len); 1331 1332 mtx_unlock(&sc->sc_mtx); 1333 smu_run_cmd(device_get_parent(dev), &cmd, 1); 1334 mtx_lock(&sc->sc_mtx); 1335 1336 if (!(cmd.data[0] & 0x80)) 1337 break; 1338 1339 mtx_sleep(sc, &sc->sc_mtx, 0, "smuiic", 10); 1340 } 1341 1342 if (cmd.data[0] & 0x80) { 1343 error = EIO; 1344 msgs[i].len = 0; 1345 goto exit; 1346 } 1347 memcpy(msgs[i].buf, &cmd.data[1], msgs[i].len); 1348 msgs[i].len = cmd.len - 1; 1349 } 1350 1351 exit: 1352 sc->sc_iic_inuse = 0; 1353 mtx_unlock(&sc->sc_mtx); 1354 wakeup(sc); 1355 return (error); 1356 } 1357 1358 static phandle_t 1359 smuiic_get_node(device_t bus, device_t dev) 1360 { 1361 1362 return (ofw_bus_get_node(bus)); 1363 } 1364 1365