2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2009 Nathan Whitehorn
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/param.h>
32 #include <sys/eventhandler.h>
33 #include <sys/systm.h>
34 #include <sys/module.h>
37 #include <sys/clock.h>
38 #include <sys/ctype.h>
39 #include <sys/kernel.h>
40 #include <sys/kthread.h>
42 #include <sys/mutex.h>
43 #include <sys/reboot.h>
45 #include <sys/sysctl.h>
46 #include <sys/unistd.h>
48 #include <machine/bus.h>
49 #include <machine/intr_machdep.h>
50 #include <machine/md_var.h>
52 #include <dev/iicbus/iicbus.h>
53 #include <dev/iicbus/iiconf.h>
54 #include <dev/led/led.h>
55 #include <dev/ofw/openfirm.h>
56 #include <dev/ofw/ofw_bus.h>
57 #include <dev/ofw/ofw_bus_subr.h>
58 #include <powerpc/powermac/macgpiovar.h>
59 #include <powerpc/powermac/powermac_thermal.h>
62 #include "iicbus_if.h"
69 STAILQ_ENTRY(smu_cmd
) cmd_q
;
72 STAILQ_HEAD(smu_cmdq
, smu_cmd
);
88 /* We can read the PWM and the RPM from a PWM controlled fan.
89 * Offer both values via sysctl.
92 SMU_PWM_SYSCTL_PWM
= 1 << 8,
93 SMU_PWM_SYSCTL_RPM
= 2 << 8
97 struct pmac_therm therm
;
113 struct resource
*sc_memr
;
117 bus_dma_tag_t sc_dmatag
;
118 bus_space_tag_t sc_bt
;
119 bus_space_handle_t sc_mailbox
;
121 struct smu_cmd
*sc_cmd
, *sc_cur_cmd
;
122 bus_addr_t sc_cmd_phys
;
123 bus_dmamap_t sc_cmd_dmamap
;
124 struct smu_cmdq sc_cmdq
;
126 struct smu_fan
*sc_fans
;
129 struct smu_sensor
*sc_sensors
;
132 int sc_doorbellirqid
;
133 struct resource
*sc_doorbellirq
;
134 void *sc_doorbellirqcookie
;
136 struct proc
*sc_fanmgt_proc
;
137 time_t sc_lastuserchange
;
139 /* Calibration data */
140 uint16_t sc_cpu_diode_scale
;
141 int16_t sc_cpu_diode_offset
;
143 uint16_t sc_cpu_volt_scale
;
144 int16_t sc_cpu_volt_offset
;
145 uint16_t sc_cpu_curr_scale
;
146 int16_t sc_cpu_curr_offset
;
148 uint16_t sc_slots_pow_scale
;
149 int16_t sc_slots_pow_offset
;
151 struct cdev
*sc_leddev
;
154 /* regular bus attachment functions */
156 static int smu_probe(device_t
);
157 static int smu_attach(device_t
);
158 static const struct ofw_bus_devinfo
*
159 smu_get_devinfo(device_t bus
, device_t dev
);
161 /* cpufreq notification hooks */
163 static void smu_cpufreq_pre_change(device_t
, const struct cf_level
*level
);
164 static void smu_cpufreq_post_change(device_t
, const struct cf_level
*level
);
166 /* clock interface */
167 static int smu_gettime(device_t dev
, struct timespec
*ts
);
168 static int smu_settime(device_t dev
, struct timespec
*ts
);
170 /* utility functions */
171 static int smu_run_cmd(device_t dev
, struct smu_cmd
*cmd
, int wait
);
172 static int smu_get_datablock(device_t dev
, int8_t id
, uint8_t *buf
,
174 static void smu_attach_i2c(device_t dev
, phandle_t i2croot
);
175 static void smu_attach_fans(device_t dev
, phandle_t fanroot
);
176 static void smu_attach_sensors(device_t dev
, phandle_t sensroot
);
177 static void smu_set_sleepled(void *xdev
, int onoff
);
178 static int smu_server_mode(SYSCTL_HANDLER_ARGS
);
179 static void smu_doorbell_intr(void *xdev
);
180 static void smu_shutdown(void *xdev
, int howto
);
182 /* where to find the doorbell GPIO */
184 static device_t smu_doorbell
= NULL
;
186 static device_method_t smu_methods
[] = {
187 /* Device interface */
188 DEVMETHOD(device_probe
, smu_probe
),
189 DEVMETHOD(device_attach
, smu_attach
),
191 /* Clock interface */
192 DEVMETHOD(clock_gettime
, smu_gettime
),
193 DEVMETHOD(clock_settime
, smu_settime
),
195 /* ofw_bus interface */
196 DEVMETHOD(bus_child_pnpinfo
, ofw_bus_gen_child_pnpinfo
),
197 DEVMETHOD(ofw_bus_get_devinfo
, smu_get_devinfo
),
198 DEVMETHOD(ofw_bus_get_compat
, ofw_bus_gen_get_compat
),
199 DEVMETHOD(ofw_bus_get_model
, ofw_bus_gen_get_model
),
200 DEVMETHOD(ofw_bus_get_name
, ofw_bus_gen_get_name
),
201 DEVMETHOD(ofw_bus_get_node
, ofw_bus_gen_get_node
),
202 DEVMETHOD(ofw_bus_get_type
, ofw_bus_gen_get_type
),
207 static driver_t smu_driver
= {
210 sizeof(struct smu_softc
)
213 DRIVER_MODULE(smu
, ofwbus
, smu_driver
, 0, 0);
214 static MALLOC_DEFINE(M_SMU
, "smu", "SMU Sensor Information");
216 #define SMU_MAILBOX 0x8000860c
217 #define SMU_FANMGT_INTERVAL 1000 /* ms */
222 #define SMU_RPM_STATUS 0x01
223 #define SMU_RPM_SETPOINT 0x02
224 #define SMU_PWM_STATUS 0x11
225 #define SMU_PWM_SETPOINT 0x12
227 #define SMU_I2C_SIMPLE 0x00
228 #define SMU_I2C_NORMAL 0x01
229 #define SMU_I2C_COMBINED 0x02
230 #define SMU_MISC 0xee
231 #define SMU_MISC_GET_DATA 0x02
232 #define SMU_MISC_LED_CTRL 0x04
233 #define SMU_POWER 0xaa
234 #define SMU_POWER_EVENTS 0x8f
235 #define SMU_PWR_GET_POWERUP 0x00
236 #define SMU_PWR_SET_POWERUP 0x01
237 #define SMU_PWR_CLR_POWERUP 0x02
239 #define SMU_RTC_GET 0x81
240 #define SMU_RTC_SET 0x80
242 /* Power event types */
243 #define SMU_WAKEUP_KEYPRESS 0x01
244 #define SMU_WAKEUP_AC_INSERT 0x02
245 #define SMU_WAKEUP_AC_CHANGE 0x04
246 #define SMU_WAKEUP_RING 0x10
249 #define SMU_CPUTEMP_CAL 0x18
250 #define SMU_CPUVOLT_CAL 0x21
251 #define SMU_SLOTPW_CAL 0x78
254 #define SMU_PARTITION 0x3e
255 #define SMU_PARTITION_LATEST 0x01
256 #define SMU_PARTITION_BASE 0x02
257 #define SMU_PARTITION_UPDATE 0x03
260 smu_probe(device_t dev
)
262 const char *name
= ofw_bus_get_name(dev
);
264 if (strcmp(name
, "smu") != 0)
267 device_set_desc(dev
, "Apple System Management Unit");
272 smu_phys_callback(void *xsc
, bus_dma_segment_t
*segs
, int nsegs
, int error
)
274 struct smu_softc
*sc
= xsc
;
276 sc
->sc_cmd_phys
= segs
[0].ds_addr
;
280 smu_attach(device_t dev
)
282 struct smu_softc
*sc
;
283 phandle_t node
, child
;
286 sc
= device_get_softc(dev
);
288 mtx_init(&sc
->sc_mtx
, "smu", NULL
, MTX_DEF
);
289 sc
->sc_cur_cmd
= NULL
;
290 sc
->sc_doorbellirqid
= -1;
293 if (OF_finddevice("/u3") != -1)
297 * Map the mailbox area. This should be determined from firmware,
298 * but I have not found a simple way to do that.
300 bus_dma_tag_create(NULL
, 16, 0, BUS_SPACE_MAXADDR_32BIT
,
301 BUS_SPACE_MAXADDR
, NULL
, NULL
, PAGE_SIZE
, 1, PAGE_SIZE
, 0, NULL
,
302 NULL
, &(sc
->sc_dmatag
));
303 sc
->sc_bt
= &bs_le_tag
;
304 bus_space_map(sc
->sc_bt
, SMU_MAILBOX
, 4, 0, &sc
->sc_mailbox
);
307 * Allocate the command buffer. This can be anywhere in the low 4 GB
310 bus_dmamem_alloc(sc
->sc_dmatag
, (void **)&sc
->sc_cmd
, BUS_DMA_WAITOK
|
311 BUS_DMA_ZERO
, &sc
->sc_cmd_dmamap
);
312 bus_dmamap_load(sc
->sc_dmatag
, sc
->sc_cmd_dmamap
,
313 sc
->sc_cmd
, PAGE_SIZE
, smu_phys_callback
, sc
, 0);
314 STAILQ_INIT(&sc
->sc_cmdq
);
317 * Set up handlers to change CPU voltage when CPU frequency is changed.
319 EVENTHANDLER_REGISTER(cpufreq_pre_change
, smu_cpufreq_pre_change
, dev
,
320 EVENTHANDLER_PRI_ANY
);
321 EVENTHANDLER_REGISTER(cpufreq_post_change
, smu_cpufreq_post_change
, dev
,
322 EVENTHANDLER_PRI_ANY
);
324 node
= ofw_bus_get_node(dev
);
326 /* Some SMUs have RPM and PWM controlled fans which do not sit
327 * under the same node. So we have to attach them separately.
329 smu_attach_fans(dev
, node
);
332 * Now detect and attach the other child devices.
334 for (child
= OF_child(node
); child
!= 0; child
= OF_peer(child
)) {
336 memset(name
, 0, sizeof(name
));
337 OF_getprop(child
, "name", name
, sizeof(name
));
339 if (strncmp(name
, "sensors", 8) == 0)
340 smu_attach_sensors(dev
, child
);
342 if (strncmp(name
, "smu-i2c-control", 15) == 0)
343 smu_attach_i2c(dev
, child
);
346 /* Some SMUs have the I2C children directly under the bus. */
347 smu_attach_i2c(dev
, node
);
350 * Collect calibration constants.
352 smu_get_datablock(dev
, SMU_CPUTEMP_CAL
, data
, sizeof(data
));
353 sc
->sc_cpu_diode_scale
= (data
[4] << 8) + data
[5];
354 sc
->sc_cpu_diode_offset
= (data
[6] << 8) + data
[7];
356 smu_get_datablock(dev
, SMU_CPUVOLT_CAL
, data
, sizeof(data
));
357 sc
->sc_cpu_volt_scale
= (data
[4] << 8) + data
[5];
358 sc
->sc_cpu_volt_offset
= (data
[6] << 8) + data
[7];
359 sc
->sc_cpu_curr_scale
= (data
[8] << 8) + data
[9];
360 sc
->sc_cpu_curr_offset
= (data
[10] << 8) + data
[11];
362 smu_get_datablock(dev
, SMU_SLOTPW_CAL
, data
, sizeof(data
));
363 sc
->sc_slots_pow_scale
= (data
[4] << 8) + data
[5];
364 sc
->sc_slots_pow_offset
= (data
[6] << 8) + data
[7];
367 * Set up LED interface
369 sc
->sc_leddev
= led_create(smu_set_sleepled
, dev
, "sleepled");
372 * Reset on power loss behavior
375 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev
),
376 SYSCTL_CHILDREN(device_get_sysctl_tree(dev
)), OID_AUTO
,
377 "server_mode", CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_NEEDGIANT
, dev
,
378 0, smu_server_mode
, "I", "Enable reboot after power failure");
381 * Set up doorbell interrupt.
383 sc
->sc_doorbellirqid
= 0;
384 sc
->sc_doorbellirq
= bus_alloc_resource_any(smu_doorbell
, SYS_RES_IRQ
,
385 &sc
->sc_doorbellirqid
, RF_ACTIVE
);
386 bus_setup_intr(smu_doorbell
, sc
->sc_doorbellirq
,
387 INTR_TYPE_MISC
| INTR_MPSAFE
, NULL
, smu_doorbell_intr
, dev
,
388 &sc
->sc_doorbellirqcookie
);
389 powerpc_config_intr(rman_get_start(sc
->sc_doorbellirq
),
390 INTR_TRIGGER_EDGE
, INTR_POLARITY_LOW
);
393 * Connect RTC interface.
395 clock_register(dev
, 1000);
398 * Learn about shutdown events
400 EVENTHANDLER_REGISTER(shutdown_final
, smu_shutdown
, dev
,
403 bus_attach_children(dev
);
407 static const struct ofw_bus_devinfo
*
408 smu_get_devinfo(device_t bus
, device_t dev
)
411 return (device_get_ivars(dev
));
415 smu_send_cmd(device_t dev
, struct smu_cmd
*cmd
)
417 struct smu_softc
*sc
;
419 sc
= device_get_softc(dev
);
421 mtx_assert(&sc
->sc_mtx
, MA_OWNED
);
424 powerpc_pow_enabled
= 0; /* SMU cannot work if we go to NAP */
426 sc
->sc_cur_cmd
= cmd
;
428 /* Copy the command to the mailbox */
429 sc
->sc_cmd
->cmd
= cmd
->cmd
;
430 sc
->sc_cmd
->len
= cmd
->len
;
431 memcpy(sc
->sc_cmd
->data
, cmd
->data
, sizeof(cmd
->data
));
432 bus_dmamap_sync(sc
->sc_dmatag
, sc
->sc_cmd_dmamap
, BUS_DMASYNC_PREWRITE
);
433 bus_space_write_4(sc
->sc_bt
, sc
->sc_mailbox
, 0, sc
->sc_cmd_phys
);
435 /* Flush the cacheline it is in -- SMU bypasses the cache */
436 __asm
__volatile("sync; dcbf 0,%0; sync" :: "r"(sc
->sc_cmd
): "memory");
438 /* Ring SMU doorbell */
439 macgpio_write(smu_doorbell
, GPIO_DDR_OUTPUT
);
443 smu_doorbell_intr(void *xdev
)
446 struct smu_softc
*sc
;
450 doorbell_ack
= macgpio_read(smu_doorbell
);
451 sc
= device_get_softc(smu
);
453 if (doorbell_ack
!= (GPIO_DDR_OUTPUT
| GPIO_LEVEL_RO
| GPIO_DATA
))
456 mtx_lock(&sc
->sc_mtx
);
458 if (sc
->sc_cur_cmd
== NULL
) /* spurious */
461 /* Check result. First invalidate the cache again... */
462 __asm
__volatile("dcbf 0,%0; sync" :: "r"(sc
->sc_cmd
) : "memory");
464 bus_dmamap_sync(sc
->sc_dmatag
, sc
->sc_cmd_dmamap
, BUS_DMASYNC_POSTREAD
);
466 sc
->sc_cur_cmd
->cmd
= sc
->sc_cmd
->cmd
;
467 sc
->sc_cur_cmd
->len
= sc
->sc_cmd
->len
;
468 memcpy(sc
->sc_cur_cmd
->data
, sc
->sc_cmd
->data
,
469 sizeof(sc
->sc_cmd
->data
));
470 wakeup(sc
->sc_cur_cmd
);
471 sc
->sc_cur_cmd
= NULL
;
473 powerpc_pow_enabled
= 1;
476 /* Queue next command if one is pending */
477 if (STAILQ_FIRST(&sc
->sc_cmdq
) != NULL
) {
478 sc
->sc_cur_cmd
= STAILQ_FIRST(&sc
->sc_cmdq
);
479 STAILQ_REMOVE_HEAD(&sc
->sc_cmdq
, cmd_q
);
480 smu_send_cmd(smu
, sc
->sc_cur_cmd
);
483 mtx_unlock(&sc
->sc_mtx
);
487 smu_run_cmd(device_t dev
, struct smu_cmd
*cmd
, int wait
)
489 struct smu_softc
*sc
;
493 sc
= device_get_softc(dev
);
496 mtx_lock(&sc
->sc_mtx
);
497 if (sc
->sc_cur_cmd
!= NULL
) {
498 STAILQ_INSERT_TAIL(&sc
->sc_cmdq
, cmd
, cmd_q
);
500 smu_send_cmd(dev
, cmd
);
501 mtx_unlock(&sc
->sc_mtx
);
506 if (sc
->sc_doorbellirqid
< 0) {
507 /* Poll if the IRQ has not been set up yet */
510 smu_doorbell_intr(dev
);
511 } while (sc
->sc_cur_cmd
!= NULL
);
513 /* smu_doorbell_intr will wake us when the command is ACK'ed */
514 error
= tsleep(cmd
, 0, "smu", 800 * hz
/ 1000);
516 smu_doorbell_intr(dev
); /* One last chance */
519 mtx_lock(&sc
->sc_mtx
);
520 if (cmd
->cmd
== cmd_code
) { /* Never processed */
521 /* Abort this command if we timed out */
522 if (sc
->sc_cur_cmd
== cmd
)
523 sc
->sc_cur_cmd
= NULL
;
525 STAILQ_REMOVE(&sc
->sc_cmdq
, cmd
, smu_cmd
,
527 mtx_unlock(&sc
->sc_mtx
);
531 mtx_unlock(&sc
->sc_mtx
);
535 /* SMU acks the command by inverting the command bits */
536 if (cmd
->cmd
== ((~cmd_code
) & 0xff))
545 smu_get_datablock(device_t dev
, int8_t id
, uint8_t *buf
, size_t len
)
550 cmd
.cmd
= SMU_PARTITION
;
552 cmd
.data
[0] = SMU_PARTITION_LATEST
;
555 smu_run_cmd(dev
, &cmd
, 1);
557 addr
[0] = addr
[1] = 0;
558 addr
[2] = cmd
.data
[0];
559 addr
[3] = cmd
.data
[1];
563 cmd
.data
[0] = SMU_MISC_GET_DATA
;
564 cmd
.data
[1] = sizeof(addr
);
565 memcpy(&cmd
.data
[2], addr
, sizeof(addr
));
568 smu_run_cmd(dev
, &cmd
, 1);
569 memcpy(buf
, cmd
.data
, len
);
574 smu_slew_cpu_voltage(device_t dev
, int to
)
589 smu_run_cmd(dev
, &cmd
, 1);
593 smu_cpufreq_pre_change(device_t dev
, const struct cf_level
*level
)
596 * Make sure the CPU voltage is raised before we raise
600 if (level
->rel_set
[0].freq
== 10000 /* max */)
601 smu_slew_cpu_voltage(dev
, 0);
605 smu_cpufreq_post_change(device_t dev
, const struct cf_level
*level
)
607 /* We are safe to reduce CPU voltage after a downward transition */
609 if (level
->rel_set
[0].freq
< 10000 /* max */)
610 smu_slew_cpu_voltage(dev
, 1); /* XXX: 1/4 voltage for 970MP? */
613 /* Routines for probing the SMU doorbell GPIO */
614 static int doorbell_probe(device_t dev
);
615 static int doorbell_attach(device_t dev
);
617 static device_method_t doorbell_methods
[] = {
618 /* Device interface */
619 DEVMETHOD(device_probe
, doorbell_probe
),
620 DEVMETHOD(device_attach
, doorbell_attach
),
624 static driver_t doorbell_driver
= {
630 EARLY_DRIVER_MODULE(smudoorbell
, macgpio
, doorbell_driver
, 0, 0,
631 BUS_PASS_SUPPORTDEV
);
634 doorbell_probe(device_t dev
)
636 const char *name
= ofw_bus_get_name(dev
);
638 if (strcmp(name
, "smu-doorbell") != 0)
641 device_set_desc(dev
, "SMU Doorbell GPIO");
647 doorbell_attach(device_t dev
)
654 * Sensor and fan management
658 smu_fan_check_old_style(struct smu_fan
*fan
)
660 device_t smu
= fan
->dev
;
661 struct smu_softc
*sc
= device_get_softc(smu
);
665 if (sc
->old_style_fans
!= -1)
666 return (sc
->old_style_fans
);
669 * Apple has two fan control mechanisms. We can't distinguish
670 * them except by seeing if the new one fails. If the new one
671 * fails, use the old one.
677 cmd
.data
[1] = fan
->reg
;
680 error
= smu_run_cmd(smu
, &cmd
, 1);
681 } while (error
== EWOULDBLOCK
);
683 sc
->old_style_fans
= (error
!= 0);
685 return (sc
->old_style_fans
);
689 smu_fan_set_rpm(struct smu_fan
*fan
, int rpm
)
691 device_t smu
= fan
->dev
;
698 /* Clamp to allowed range */
699 rpm
= max(fan
->fan
.min_rpm
, rpm
);
700 rpm
= min(fan
->fan
.max_rpm
, rpm
);
702 smu_fan_check_old_style(fan
);
704 if (!fan
->old_style
) {
707 cmd
.data
[1] = fan
->reg
;
708 cmd
.data
[2] = (rpm
>> 8) & 0xff;
709 cmd
.data
[3] = rpm
& 0xff;
711 error
= smu_run_cmd(smu
, &cmd
, 1);
712 if (error
&& error
!= EWOULDBLOCK
)
716 cmd
.data
[0] = 0x00; /* RPM fan. */
717 cmd
.data
[1] = 1 << fan
->reg
;
718 cmd
.data
[2 + 2*fan
->reg
] = (rpm
>> 8) & 0xff;
719 cmd
.data
[3 + 2*fan
->reg
] = rpm
& 0xff;
720 error
= smu_run_cmd(smu
, &cmd
, 1);
730 smu_fan_read_rpm(struct smu_fan
*fan
)
732 device_t smu
= fan
->dev
;
736 smu_fan_check_old_style(fan
);
738 if (!fan
->old_style
) {
742 cmd
.data
[1] = fan
->reg
;
744 error
= smu_run_cmd(smu
, &cmd
, 1);
745 if (error
&& error
!= EWOULDBLOCK
)
748 rpm
= (cmd
.data
[0] << 8) | cmd
.data
[1];
751 if (fan
->old_style
) {
754 cmd
.data
[0] = SMU_RPM_STATUS
;
756 error
= smu_run_cmd(smu
, &cmd
, 1);
760 rpm
= (cmd
.data
[fan
->reg
*2+1] << 8) | cmd
.data
[fan
->reg
*2+2];
766 smu_fan_set_pwm(struct smu_fan
*fan
, int pwm
)
768 device_t smu
= fan
->dev
;
775 /* Clamp to allowed range */
776 pwm
= max(fan
->fan
.min_rpm
, pwm
);
777 pwm
= min(fan
->fan
.max_rpm
, pwm
);
780 * Apple has two fan control mechanisms. We can't distinguish
781 * them except by seeing if the new one fails. If the new one
782 * fails, use the old one.
785 if (!fan
->old_style
) {
788 cmd
.data
[1] = fan
->reg
;
789 cmd
.data
[2] = (pwm
>> 8) & 0xff;
790 cmd
.data
[3] = pwm
& 0xff;
792 error
= smu_run_cmd(smu
, &cmd
, 1);
793 if (error
&& error
!= EWOULDBLOCK
)
797 if (fan
->old_style
) {
799 cmd
.data
[0] = 0x10; /* PWM fan. */
800 cmd
.data
[1] = 1 << fan
->reg
;
801 cmd
.data
[2 + 2*fan
->reg
] = (pwm
>> 8) & 0xff;
802 cmd
.data
[3 + 2*fan
->reg
] = pwm
& 0xff;
803 error
= smu_run_cmd(smu
, &cmd
, 1);
813 smu_fan_read_pwm(struct smu_fan
*fan
, int *pwm
, int *rpm
)
815 device_t smu
= fan
->dev
;
819 if (!fan
->old_style
) {
823 cmd
.data
[1] = fan
->reg
;
825 error
= smu_run_cmd(smu
, &cmd
, 1);
826 if (error
&& error
!= EWOULDBLOCK
)
829 *rpm
= (cmd
.data
[0] << 8) | cmd
.data
[1];
832 if (fan
->old_style
) {
835 cmd
.data
[0] = SMU_PWM_STATUS
;
837 error
= smu_run_cmd(smu
, &cmd
, 1);
841 *rpm
= (cmd
.data
[fan
->reg
*2+1] << 8) | cmd
.data
[fan
->reg
*2+2];
843 if (fan
->old_style
) {
846 cmd
.data
[0] = SMU_PWM_SETPOINT
;
847 cmd
.data
[1] = 1 << fan
->reg
;
849 error
= smu_run_cmd(smu
, &cmd
, 1);
853 *pwm
= cmd
.data
[fan
->reg
*2+2];
859 smu_fanrpm_sysctl(SYSCTL_HANDLER_ARGS
)
862 struct smu_softc
*sc
;
864 int pwm
= 0, rpm
, error
= 0;
867 sc
= device_get_softc(smu
);
868 fan
= &sc
->sc_fans
[arg2
& 0xff];
870 if (fan
->type
== SMU_FAN_RPM
) {
871 rpm
= smu_fan_read_rpm(fan
);
875 error
= sysctl_handle_int(oidp
, &rpm
, 0, req
);
877 error
= smu_fan_read_pwm(fan
, &pwm
, &rpm
);
881 switch (arg2
& 0xff00) {
882 case SMU_PWM_SYSCTL_PWM
:
883 error
= sysctl_handle_int(oidp
, &pwm
, 0, req
);
885 case SMU_PWM_SYSCTL_RPM
:
886 error
= sysctl_handle_int(oidp
, &rpm
, 0, req
);
889 /* This should never happen */
893 /* We can only read the RPM from a PWM controlled fan, so return. */
894 if ((arg2
& 0xff00) == SMU_PWM_SYSCTL_RPM
)
897 if (error
|| !req
->newptr
)
900 sc
->sc_lastuserchange
= time_uptime
;
902 if (fan
->type
== SMU_FAN_RPM
)
903 return (smu_fan_set_rpm(fan
, rpm
));
905 return (smu_fan_set_pwm(fan
, pwm
));
909 smu_fill_fan_prop(device_t dev
, phandle_t child
, int id
)
912 struct smu_softc
*sc
;
915 sc
= device_get_softc(dev
);
916 fan
= &sc
->sc_fans
[id
];
918 OF_getprop(child
, "device_type", type
, sizeof(type
));
919 /* We have either RPM or PWM controlled fans. */
920 if (strcmp(type
, "fan-rpm-control") == 0)
921 fan
->type
= SMU_FAN_RPM
;
923 fan
->type
= SMU_FAN_PWM
;
927 OF_getprop(child
, "reg", &fan
->reg
,
929 OF_getprop(child
, "min-value", &fan
->fan
.min_rpm
,
931 OF_getprop(child
, "max-value", &fan
->fan
.max_rpm
,
933 OF_getprop(child
, "zone", &fan
->fan
.zone
,
936 if (OF_getprop(child
, "unmanaged-value",
937 &fan
->fan
.default_rpm
,
938 sizeof(int)) != sizeof(int))
939 fan
->fan
.default_rpm
= fan
->fan
.max_rpm
;
941 OF_getprop(child
, "location", fan
->fan
.name
,
942 sizeof(fan
->fan
.name
));
944 if (fan
->type
== SMU_FAN_RPM
)
945 fan
->setpoint
= smu_fan_read_rpm(fan
);
947 smu_fan_read_pwm(fan
, &fan
->setpoint
, &fan
->rpm
);
950 /* On the first call count the number of fans. In the second call,
951 * after allocating the fan struct, fill the properties of the fans.
954 smu_count_fans(device_t dev
)
956 struct smu_softc
*sc
;
957 phandle_t child
, node
, root
;
960 node
= ofw_bus_get_node(dev
);
961 sc
= device_get_softc(dev
);
963 /* First find the fanroots and count the number of fans. */
964 for (root
= OF_child(node
); root
!= 0; root
= OF_peer(root
)) {
966 memset(name
, 0, sizeof(name
));
967 OF_getprop(root
, "name", name
, sizeof(name
));
968 if (strncmp(name
, "rpm-fans", 9) == 0 ||
969 strncmp(name
, "pwm-fans", 9) == 0 ||
970 strncmp(name
, "fans", 5) == 0)
971 for (child
= OF_child(root
); child
!= 0;
972 child
= OF_peer(child
)) {
974 /* When allocated, fill the fan properties. */
975 if (sc
->sc_fans
!= NULL
) {
976 smu_fill_fan_prop(dev
, child
,
982 device_printf(dev
, "WARNING: No fans detected!\n");
989 smu_attach_fans(device_t dev
, phandle_t fanroot
)
992 struct smu_softc
*sc
;
993 struct sysctl_oid
*oid
, *fanroot_oid
;
994 struct sysctl_ctx_list
*ctx
;
995 char sysctl_name
[32];
998 sc
= device_get_softc(dev
);
1000 /* Get the number of fans. */
1001 sc
->sc_nfans
= smu_count_fans(dev
);
1002 if (sc
->sc_nfans
== 0)
1005 /* Now we're able to allocate memory for the fans struct. */
1006 sc
->sc_fans
= malloc(sc
->sc_nfans
* sizeof(struct smu_fan
), M_SMU
,
1009 /* Now fill in the properties. */
1010 smu_count_fans(dev
);
1012 /* Register fans with pmac_thermal */
1013 for (i
= 0; i
< sc
->sc_nfans
; i
++)
1014 pmac_thermal_fan_register(&sc
->sc_fans
[i
].fan
);
1016 ctx
= device_get_sysctl_ctx(dev
);
1017 fanroot_oid
= SYSCTL_ADD_NODE(ctx
,
1018 SYSCTL_CHILDREN(device_get_sysctl_tree(dev
)), OID_AUTO
, "fans",
1019 CTLFLAG_RD
| CTLFLAG_MPSAFE
, 0, "SMU Fan Information");
1022 for (i
= 0; i
< sc
->sc_nfans
; i
++) {
1023 fan
= &sc
->sc_fans
[i
];
1024 for (j
= 0; j
< strlen(fan
->fan
.name
); j
++) {
1025 sysctl_name
[j
] = tolower(fan
->fan
.name
[j
]);
1026 if (isspace(sysctl_name
[j
]))
1027 sysctl_name
[j
] = '_';
1030 if (fan
->type
== SMU_FAN_RPM
) {
1031 oid
= SYSCTL_ADD_NODE(ctx
,
1032 SYSCTL_CHILDREN(fanroot_oid
), OID_AUTO
,
1033 sysctl_name
, CTLFLAG_RD
| CTLFLAG_MPSAFE
, 0,
1035 SYSCTL_ADD_INT(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
1036 "minrpm", CTLFLAG_RD
,
1037 &fan
->fan
.min_rpm
, 0,
1038 "Minimum allowed RPM");
1039 SYSCTL_ADD_INT(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
1040 "maxrpm", CTLFLAG_RD
,
1041 &fan
->fan
.max_rpm
, 0,
1042 "Maximum allowed RPM");
1043 SYSCTL_ADD_PROC(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
1044 "rpm",CTLTYPE_INT
| CTLFLAG_RW
|
1045 CTLFLAG_MPSAFE
, dev
, i
,
1046 smu_fanrpm_sysctl
, "I", "Fan RPM");
1048 fan
->fan
.read
= (int (*)(struct pmac_fan
*))smu_fan_read_rpm
;
1049 fan
->fan
.set
= (int (*)(struct pmac_fan
*, int))smu_fan_set_rpm
;
1052 oid
= SYSCTL_ADD_NODE(ctx
,
1053 SYSCTL_CHILDREN(fanroot_oid
), OID_AUTO
,
1054 sysctl_name
, CTLFLAG_RD
| CTLFLAG_MPSAFE
, 0,
1056 SYSCTL_ADD_INT(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
1057 "minpwm", CTLFLAG_RD
,
1058 &fan
->fan
.min_rpm
, 0,
1059 "Minimum allowed PWM in %");
1060 SYSCTL_ADD_INT(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
1061 "maxpwm", CTLFLAG_RD
,
1062 &fan
->fan
.max_rpm
, 0,
1063 "Maximum allowed PWM in %");
1064 SYSCTL_ADD_PROC(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
1065 "pwm",CTLTYPE_INT
| CTLFLAG_RW
|
1066 CTLFLAG_MPSAFE
, dev
,
1067 SMU_PWM_SYSCTL_PWM
| i
,
1068 smu_fanrpm_sysctl
, "I", "Fan PWM in %");
1069 SYSCTL_ADD_PROC(ctx
, SYSCTL_CHILDREN(oid
), OID_AUTO
,
1070 "rpm",CTLTYPE_INT
| CTLFLAG_RD
|
1071 CTLFLAG_MPSAFE
, dev
,
1072 SMU_PWM_SYSCTL_RPM
| i
,
1073 smu_fanrpm_sysctl
, "I", "Fan RPM");
1074 fan
->fan
.read
= NULL
;
1075 fan
->fan
.set
= (int (*)(struct pmac_fan
*, int))smu_fan_set_pwm
;
1078 device_printf(dev
, "Fan: %s type: %d\n",
1079 fan
->fan
.name
, fan
->type
);
1084 smu_sensor_read(struct smu_sensor
*sens
)
1086 device_t smu
= sens
->dev
;
1088 struct smu_softc
*sc
;
1094 cmd
.data
[0] = sens
->reg
;
1097 error
= smu_run_cmd(smu
, &cmd
, 1);
1101 sc
= device_get_softc(smu
);
1102 value
= (cmd
.data
[0] << 8) | cmd
.data
[1];
1104 switch (sens
->type
) {
1105 case SMU_TEMP_SENSOR
:
1106 value
*= sc
->sc_cpu_diode_scale
;
1108 value
+= ((int64_t)sc
->sc_cpu_diode_offset
) << 9;
1111 /* Convert from 16.16 fixed point degC into integer 0.1 K. */
1112 value
= 10*(value
>> 16) + ((10*(value
& 0xffff)) >> 16) + 2731;
1114 case SMU_VOLTAGE_SENSOR
:
1115 value
*= sc
->sc_cpu_volt_scale
;
1116 value
+= sc
->sc_cpu_volt_offset
;
1119 /* Convert from 16.16 fixed point V into mV. */
1124 case SMU_CURRENT_SENSOR
:
1125 value
*= sc
->sc_cpu_curr_scale
;
1126 value
+= sc
->sc_cpu_curr_offset
;
1129 /* Convert from 16.16 fixed point A into mA. */
1134 case SMU_POWER_SENSOR
:
1135 value
*= sc
->sc_slots_pow_scale
;
1136 value
+= sc
->sc_slots_pow_offset
;
1139 /* Convert from 16.16 fixed point W into mW. */
1150 smu_sensor_sysctl(SYSCTL_HANDLER_ARGS
)
1153 struct smu_softc
*sc
;
1154 struct smu_sensor
*sens
;
1158 sc
= device_get_softc(smu
);
1159 sens
= &sc
->sc_sensors
[arg2
];
1161 value
= smu_sensor_read(sens
);
1165 error
= sysctl_handle_int(oidp
, &value
, 0, req
);
1171 smu_attach_sensors(device_t dev
, phandle_t sensroot
)
1173 struct smu_sensor
*sens
;
1174 struct smu_softc
*sc
;
1175 struct sysctl_oid
*sensroot_oid
;
1176 struct sysctl_ctx_list
*ctx
;
1181 sc
= device_get_softc(dev
);
1182 sc
->sc_nsensors
= 0;
1184 for (child
= OF_child(sensroot
); child
!= 0; child
= OF_peer(child
))
1187 if (sc
->sc_nsensors
== 0) {
1188 device_printf(dev
, "WARNING: No sensors detected!\n");
1192 sc
->sc_sensors
= malloc(sc
->sc_nsensors
* sizeof(struct smu_sensor
),
1193 M_SMU
, M_WAITOK
| M_ZERO
);
1195 sens
= sc
->sc_sensors
;
1196 sc
->sc_nsensors
= 0;
1198 ctx
= device_get_sysctl_ctx(dev
);
1199 sensroot_oid
= SYSCTL_ADD_NODE(ctx
,
1200 SYSCTL_CHILDREN(device_get_sysctl_tree(dev
)), OID_AUTO
, "sensors",
1201 CTLFLAG_RD
| CTLFLAG_MPSAFE
, 0, "SMU Sensor Information");
1203 for (child
= OF_child(sensroot
); child
!= 0; child
= OF_peer(child
)) {
1204 char sysctl_name
[40], sysctl_desc
[40];
1208 OF_getprop(child
, "device_type", type
, sizeof(type
));
1210 if (strcmp(type
, "current-sensor") == 0) {
1211 sens
->type
= SMU_CURRENT_SENSOR
;
1213 } else if (strcmp(type
, "temp-sensor") == 0) {
1214 sens
->type
= SMU_TEMP_SENSOR
;
1216 } else if (strcmp(type
, "voltage-sensor") == 0) {
1217 sens
->type
= SMU_VOLTAGE_SENSOR
;
1219 } else if (strcmp(type
, "power-sensor") == 0) {
1220 sens
->type
= SMU_POWER_SENSOR
;
1226 OF_getprop(child
, "reg", &sens
->reg
, sizeof(cell_t
));
1227 OF_getprop(child
, "zone", &sens
->therm
.zone
, sizeof(int));
1228 OF_getprop(child
, "location", sens
->therm
.name
,
1229 sizeof(sens
->therm
.name
));
1231 for (i
= 0; i
< strlen(sens
->therm
.name
); i
++) {
1232 sysctl_name
[i
] = tolower(sens
->therm
.name
[i
]);
1233 if (isspace(sysctl_name
[i
]))
1234 sysctl_name
[i
] = '_';
1238 sprintf(sysctl_desc
,"%s (%s)", sens
->therm
.name
, units
);
1240 SYSCTL_ADD_PROC(ctx
, SYSCTL_CHILDREN(sensroot_oid
), OID_AUTO
,
1241 sysctl_name
, CTLTYPE_INT
| CTLFLAG_RD
| CTLFLAG_MPSAFE
,
1242 dev
, sc
->sc_nsensors
, smu_sensor_sysctl
,
1243 (sens
->type
== SMU_TEMP_SENSOR
) ? "IK" : "I", sysctl_desc
);
1245 if (sens
->type
== SMU_TEMP_SENSOR
) {
1246 /* Make up some numbers */
1247 sens
->therm
.target_temp
= 500 + 2731; /* 50 C */
1248 sens
->therm
.max_temp
= 900 + 2731; /* 90 C */
1251 (int (*)(struct pmac_therm
*))smu_sensor_read
;
1252 pmac_thermal_sensor_register(&sens
->therm
);
1261 smu_set_sleepled(void *xdev
, int onoff
)
1263 static struct smu_cmd cmd
;
1264 device_t smu
= xdev
;
1268 cmd
.data
[0] = SMU_MISC_LED_CTRL
;
1270 cmd
.data
[2] = onoff
;
1272 smu_run_cmd(smu
, &cmd
, 0);
1276 smu_server_mode(SYSCTL_HANDLER_ARGS
)
1280 device_t smu
= arg1
;
1283 cmd
.cmd
= SMU_POWER_EVENTS
;
1285 cmd
.data
[0] = SMU_PWR_GET_POWERUP
;
1287 error
= smu_run_cmd(smu
, &cmd
, 1);
1292 server_mode
= (cmd
.data
[1] & SMU_WAKEUP_AC_INSERT
) ? 1 : 0;
1294 error
= sysctl_handle_int(oidp
, &server_mode
, 0, req
);
1296 if (error
|| !req
->newptr
)
1299 if (server_mode
== 1)
1300 cmd
.data
[0] = SMU_PWR_SET_POWERUP
;
1301 else if (server_mode
== 0)
1302 cmd
.data
[0] = SMU_PWR_CLR_POWERUP
;
1308 cmd
.data
[2] = SMU_WAKEUP_AC_INSERT
;
1310 return (smu_run_cmd(smu
, &cmd
, 1));
1314 smu_shutdown(void *xdev
, int howto
)
1316 device_t smu
= xdev
;
1319 cmd
.cmd
= SMU_POWER
;
1320 if ((howto
& RB_POWEROFF
) != 0)
1321 strcpy(cmd
.data
, "SHUTDOWN");
1322 else if ((howto
& RB_HALT
) == 0)
1323 strcpy(cmd
.data
, "RESTART");
1327 cmd
.len
= strlen(cmd
.data
);
1329 smu_run_cmd(smu
, &cmd
, 1);
1335 smu_gettime(device_t dev
, struct timespec
*ts
)
1338 struct clocktime ct
;
1342 cmd
.data
[0] = SMU_RTC_GET
;
1344 if (smu_run_cmd(dev
, &cmd
, 1) != 0)
1348 ct
.sec
= bcd2bin(cmd
.data
[0]);
1349 ct
.min
= bcd2bin(cmd
.data
[1]);
1350 ct
.hour
= bcd2bin(cmd
.data
[2]);
1351 ct
.dow
= bcd2bin(cmd
.data
[3]);
1352 ct
.day
= bcd2bin(cmd
.data
[4]);
1353 ct
.mon
= bcd2bin(cmd
.data
[5]);
1354 ct
.year
= bcd2bin(cmd
.data
[6]) + 2000;
1356 return (clock_ct_to_ts(&ct
, ts
));
1360 smu_settime(device_t dev
, struct timespec
*ts
)
1362 static struct smu_cmd cmd
;
1363 struct clocktime ct
;
1367 cmd
.data
[0] = SMU_RTC_SET
;
1369 clock_ts_to_ct(ts
, &ct
);
1371 cmd
.data
[1] = bin2bcd(ct
.sec
);
1372 cmd
.data
[2] = bin2bcd(ct
.min
);
1373 cmd
.data
[3] = bin2bcd(ct
.hour
);
1374 cmd
.data
[4] = bin2bcd(ct
.dow
);
1375 cmd
.data
[5] = bin2bcd(ct
.day
);
1376 cmd
.data
[6] = bin2bcd(ct
.mon
);
1377 cmd
.data
[7] = bin2bcd(ct
.year
- 2000);
1379 return (smu_run_cmd(dev
, &cmd
, 0));
1382 /* SMU I2C Interface */
1384 static int smuiic_probe(device_t dev
);
1385 static int smuiic_attach(device_t dev
);
1386 static int smuiic_transfer(device_t dev
, struct iic_msg
*msgs
, uint32_t nmsgs
);
1387 static phandle_t
smuiic_get_node(device_t bus
, device_t dev
);
1389 static device_method_t smuiic_methods
[] = {
1390 /* device interface */
1391 DEVMETHOD(device_probe
, smuiic_probe
),
1392 DEVMETHOD(device_attach
, smuiic_attach
),
1394 /* iicbus interface */
1395 DEVMETHOD(iicbus_callback
, iicbus_null_callback
),
1396 DEVMETHOD(iicbus_transfer
, smuiic_transfer
),
1398 /* ofw_bus interface */
1399 DEVMETHOD(ofw_bus_get_node
, smuiic_get_node
),
1403 struct smuiic_softc
{
1405 volatile int sc_iic_inuse
;
1409 static driver_t smuiic_driver
= {
1412 sizeof(struct smuiic_softc
)
1415 DRIVER_MODULE(smuiic
, smu
, smuiic_driver
, 0, 0);
1418 smu_attach_i2c(device_t smu
, phandle_t i2croot
)
1422 struct ofw_bus_devinfo
*dinfo
;
1425 for (child
= OF_child(i2croot
); child
!= 0; child
= OF_peer(child
)) {
1426 if (OF_getprop(child
, "name", name
, sizeof(name
)) <= 0)
1429 if (strcmp(name
, "i2c-bus") != 0 && strcmp(name
, "i2c") != 0)
1432 dinfo
= malloc(sizeof(struct ofw_bus_devinfo
), M_SMU
,
1434 if (ofw_bus_gen_setup_devinfo(dinfo
, child
) != 0) {
1439 cdev
= device_add_child(smu
, NULL
, DEVICE_UNIT_ANY
);
1441 device_printf(smu
, "<%s>: device_add_child failed\n",
1443 ofw_bus_gen_destroy_devinfo(dinfo
);
1447 device_set_ivars(cdev
, dinfo
);
1452 smuiic_probe(device_t dev
)
1456 name
= ofw_bus_get_name(dev
);
1460 if (strcmp(name
, "i2c-bus") == 0 || strcmp(name
, "i2c") == 0) {
1461 device_set_desc(dev
, "SMU I2C controller");
1469 smuiic_attach(device_t dev
)
1471 struct smuiic_softc
*sc
= device_get_softc(dev
);
1472 mtx_init(&sc
->sc_mtx
, "smuiic", NULL
, MTX_DEF
);
1473 sc
->sc_iic_inuse
= 0;
1475 /* Get our bus number */
1476 OF_getprop(ofw_bus_get_node(dev
), "reg", &sc
->sc_busno
,
1477 sizeof(sc
->sc_busno
));
1479 /* Add the IIC bus layer */
1480 device_add_child(dev
, "iicbus", DEVICE_UNIT_ANY
);
1482 bus_attach_children(dev
);
1487 smuiic_transfer(device_t dev
, struct iic_msg
*msgs
, uint32_t nmsgs
)
1489 struct smuiic_softc
*sc
= device_get_softc(dev
);
1493 mtx_lock(&sc
->sc_mtx
);
1494 while (sc
->sc_iic_inuse
)
1495 mtx_sleep(sc
, &sc
->sc_mtx
, 0, "smuiic", 100);
1497 sc
->sc_iic_inuse
= 1;
1500 for (i
= 0; i
< nmsgs
; i
++) {
1502 cmd
.data
[0] = sc
->sc_busno
;
1503 if (msgs
[i
].flags
& IIC_M_NOSTOP
)
1504 cmd
.data
[1] = SMU_I2C_COMBINED
;
1506 cmd
.data
[1] = SMU_I2C_SIMPLE
;
1508 cmd
.data
[2] = msgs
[i
].slave
;
1509 if (msgs
[i
].flags
& IIC_M_RD
)
1512 if (msgs
[i
].flags
& IIC_M_NOSTOP
) {
1513 KASSERT(msgs
[i
].len
< 4,
1514 ("oversize I2C combined message"));
1516 cmd
.data
[3] = min(msgs
[i
].len
, 3);
1517 memcpy(&cmd
.data
[4], msgs
[i
].buf
, min(msgs
[i
].len
, 3));
1518 i
++; /* Advance to next part of message */
1521 memset(&cmd
.data
[4], 0, 3);
1524 cmd
.data
[7] = msgs
[i
].slave
;
1525 if (msgs
[i
].flags
& IIC_M_RD
)
1528 cmd
.data
[8] = msgs
[i
].len
;
1529 if (msgs
[i
].flags
& IIC_M_RD
) {
1530 memset(&cmd
.data
[9], 0xff, msgs
[i
].len
);
1533 memcpy(&cmd
.data
[9], msgs
[i
].buf
, msgs
[i
].len
);
1534 cmd
.len
= 9 + msgs
[i
].len
;
1537 mtx_unlock(&sc
->sc_mtx
);
1538 smu_run_cmd(device_get_parent(dev
), &cmd
, 1);
1539 mtx_lock(&sc
->sc_mtx
);
1541 for (j
= 0; j
< 10; j
++) {
1545 memset(&cmd
.data
[1], 0xff, msgs
[i
].len
);
1547 mtx_unlock(&sc
->sc_mtx
);
1548 smu_run_cmd(device_get_parent(dev
), &cmd
, 1);
1549 mtx_lock(&sc
->sc_mtx
);
1551 if (!(cmd
.data
[0] & 0x80))
1554 mtx_sleep(sc
, &sc
->sc_mtx
, 0, "smuiic", 10);
1557 if (cmd
.data
[0] & 0x80) {
1562 memcpy(msgs
[i
].buf
, &cmd
.data
[1], msgs
[i
].len
);
1563 msgs
[i
].len
= cmd
.len
- 1;
1567 sc
->sc_iic_inuse
= 0;
1568 mtx_unlock(&sc
->sc_mtx
);
1574 smuiic_get_node(device_t bus
, device_t dev
)
1577 return (ofw_bus_get_node(bus
));