1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2007, 2008 Rui Paulo <rpaulo@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 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. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 30 #define ASMC_MAXFANS 6 31 #define ASMC_MAXVAL 32 /* Maximum SMC value size */ 32 #define ASMC_KEYLEN 4 /* SMC key name length */ 33 #define ASMC_TYPELEN 4 /* SMC type string length */ 34 #define ASMC_MAX_SENSORS 64 /* Max sensors per type */ 35 36 /* Maximum number of auto-detected temperature sensors */ 37 #define ASMC_TEMP_MAX 80 38 39 struct asmc_softc { 40 device_t sc_dev; 41 struct mtx sc_mtx; 42 int sc_nfan; 43 int sc_nkeys; 44 int16_t sms_rest_x; 45 int16_t sms_rest_y; 46 int16_t sms_rest_z; 47 struct sysctl_oid *sc_fan_tree[ASMC_MAXFANS+1]; 48 struct sysctl_oid *sc_temp_tree; 49 struct sysctl_oid *sc_sms_tree; 50 struct sysctl_oid *sc_light_tree; 51 int sc_rid_port; 52 int sc_rid_irq; 53 struct resource *sc_ioport; 54 struct resource *sc_irq; 55 void *sc_cookie; 56 /* MMIO backend (T2 Macs) */ 57 int sc_rid_mem; 58 struct resource *sc_iomem; 59 bool sc_is_mmio; 60 int sc_is_t2; /* T2 fan float + per-fan manual */ 61 int sc_sms_intrtype; 62 struct taskqueue *sc_sms_tq; 63 struct task sc_sms_task; 64 uint8_t sc_sms_intr_works; 65 struct cdev *sc_kbd_bkl; 66 uint32_t sc_kbd_bkl_level; 67 #ifdef ASMC_DEBUG 68 /* Raw key access */ 69 struct sysctl_oid *sc_raw_tree; 70 char sc_rawkey[ASMC_KEYLEN + 1]; 71 uint8_t sc_rawval[ASMC_MAXVAL]; 72 uint8_t sc_rawlen; 73 char sc_rawtype[ASMC_TYPELEN + 1]; 74 #endif 75 /* Voltage/Current/Power/Light sensors */ 76 char *sc_voltage_sensors[ASMC_MAX_SENSORS]; 77 int sc_voltage_count; 78 char *sc_current_sensors[ASMC_MAX_SENSORS]; 79 int sc_current_count; 80 char *sc_power_sensors[ASMC_MAX_SENSORS]; 81 int sc_power_count; 82 char *sc_light_sensors[ASMC_MAX_SENSORS]; 83 int sc_light_count; 84 /* Auto-detected temperature sensors */ 85 char *sc_temp_sensors[ASMC_TEMP_MAX]; 86 int sc_temp_count; 87 /* Auto-detected capabilities */ 88 int sc_has_sms; 89 int sc_has_light; 90 int sc_light_len; /* ASMC_LIGHT_{SHORT,LONG}LEN */ 91 int sc_has_safespeed; 92 int sc_has_alsl; /* ALSL interrupt source */ 93 }; 94 95 /* 96 * Data port. 97 */ 98 #define ASMC_DATAPORT_READ(sc) bus_read_1(sc->sc_ioport, 0x00) 99 #define ASMC_DATAPORT_WRITE(sc, val) \ 100 bus_write_1(sc->sc_ioport, 0x00, val) 101 #define ASMC_STATUS_MASK 0x0f 102 103 /* 104 * Command port. 105 */ 106 #define ASMC_CMDPORT_READ(sc) bus_read_1(sc->sc_ioport, 0x04) 107 #define ASMC_CMDPORT_WRITE(sc, val) \ 108 bus_write_1(sc->sc_ioport, 0x04, val) 109 #define ASMC_CMDREAD 0x10 110 #define ASMC_CMDWRITE 0x11 111 #define ASMC_CMDGETBYINDEX 0x12 112 #define ASMC_CMDGETINFO 0x13 113 114 #define ASMC_STATUS_AWAIT_DATA 0x04 115 #define ASMC_STATUS_DATA_READY 0x05 116 117 #define ASMC_KEYINFO_RESPLEN 6 /* getinfo: 1 len + 4 type + 1 attr */ 118 #define ASMC_MAXRETRIES 10 119 120 /* 121 * Interrupt port. 122 */ 123 #define ASMC_INTPORT_READ(sc) bus_read_1(sc->sc_ioport, 0x1f) 124 125 /* Number of keys */ 126 #define ASMC_NKEYS "#KEY" /* RO; 4 bytes */ 127 128 /* Query the ASMC revision */ 129 #define ASMC_KEY_REV "REV " /* RO: 6 bytes */ 130 131 /* 132 * Fan control via SMC. 133 */ 134 #define ASMC_KEY_FANCOUNT "FNum" /* RO; 1 byte */ 135 #define ASMC_KEY_FANMANUAL "FS! " /* RW; 2 bytes */ 136 #define ASMC_KEY_FANID "F%dID" /* RO; 16 bytes */ 137 #define ASMC_KEY_FANSPEED "F%dAc" /* RO; 2 bytes */ 138 #define ASMC_KEY_FANMINSPEED "F%dMn" /* RW; 2 bytes */ 139 #define ASMC_KEY_FANMAXSPEED "F%dMx" /* RO; 2 bytes */ 140 #define ASMC_KEY_FANSAFESPEED "F%dSf" /* RO; 2 bytes */ 141 #define ASMC_KEY_FANTARGETSPEED "F%dTg" /* RW; 2 bytes */ 142 143 /* 144 * Sudden Motion Sensor (SMS). 145 */ 146 #define ASMC_SMS_INIT1 0xe0 147 #define ASMC_SMS_INIT2 0xf8 148 #define ASMC_KEY_SMS "MOCN" /* RW; 2 bytes */ 149 #define ASMC_KEY_SMS_X "MO_X" /* RO; 2 bytes */ 150 #define ASMC_KEY_SMS_Y "MO_Y" /* RO; 2 bytes */ 151 #define ASMC_KEY_SMS_Z "MO_Z" /* RO; 2 bytes */ 152 #define ASMC_KEY_SMS_LOW "MOLT" /* RW; 2 bytes */ 153 #define ASMC_KEY_SMS_HIGH "MOHT" /* RW; 2 bytes */ 154 #define ASMC_KEY_SMS_LOW_INT "MOLD" /* RW; 1 byte */ 155 #define ASMC_KEY_SMS_HIGH_INT "MOHD" /* RW; 1 byte */ 156 #define ASMC_KEY_SMS_FLAG "MSDW" /* RW; 1 byte */ 157 #define ASMC_SMS_INTFF 0x60 /* Free fall Interrupt */ 158 #define ASMC_SMS_INTHA 0x6f /* High Acceleration Interrupt */ 159 #define ASMC_SMS_INTSH 0x80 /* Shock Interrupt */ 160 161 /* 162 * Light Sensor. 163 */ 164 #define ASMC_ALSL_INT2A 0x2a /* Ambient Light related Interrupt */ 165 166 /* 167 * Keyboard backlight. 168 */ 169 #define ASMC_LIGHT_SHORTLEN 6 /* ALV0 short format */ 170 #define ASMC_LIGHT_LONGLEN 10 /* ALV0 long format (10-byte) */ 171 #define ASMC_KEY_LIGHTLEFT "ALV0" /* RO; 6 or 10 bytes */ 172 #define ASMC_KEY_LIGHTRIGHT "ALV1" /* RO; 6 bytes */ 173 #define ASMC_KEY_LIGHTVALUE "LKSB" /* WO; 2 bytes */ 174 #define ASMC_KEY_LIGHTSRC "ALSL" /* RO; ambient light source */ 175 #define ASMC_KEY_FANSAFESPEED0 "F0Sf" /* RO; 2 bytes */ 176 177 /* 178 * Sleep Indicator LED (SIL). 179 * 180 * MSLD controls the duty cycle of the front-panel sleep indicator LED. 181 * 0x00 = LED at idle brightness, 0xff = LED fully off. 182 * MSLS is the SIL state latch — must be written to 0x01 before MSLD 183 * can re-enable the LED after it has been turned off. 184 * 185 * Protocol: OFF = write MSLD 0xff 186 * ON = write MSLS 0x01, then write MSLD 0x01 187 * 188 * Present on all Intel Macs with a sleep indicator (laptops + Mac Mini). 189 */ 190 #define ASMC_KEY_MSLD "MSLD" /* RW; 1 byte, SIL duty */ 191 #define ASMC_KEY_MSLS "MSLS" /* RW; 1 byte, SIL state latch */ 192 193 /* 194 * Auto power-on after AC power loss (AUPO). 195 * When set, the machine boots automatically when AC power is restored 196 * after an unclean power loss. This is NOT Wake-on-LAN. 197 */ 198 #define ASMC_KEY_AUPO "AUPO" /* RW; 1 byte */ 199 200 /* 201 * Interrupt keys. 202 */ 203 #define ASMC_KEY_INTOK "NTOK" /* WO; 1 byte */ 204 205 /* 206 * System State Machine / diagnostics keys. 207 * 208 * MSSD - Mac System Shutdown cause (last shutdown reason code) 209 * MSSP - Mac System SleeP cause (last sleep reason code) 210 * MSAL - Mac System ALarm (thermal subsystem status bitmap) 211 * MSPS - Mac System Power State (current power state index) 212 * CLKT - CLocK Time (seconds since midnight, SMC RTC) 213 * MSTS - Mac System sTate/Status (SSM state; 0 = S0 awake) 214 */ 215 #define ASMC_KEY_CLKT "CLKT" /* RO; 4 bytes ui32 BE */ 216 #define ASMC_KEY_MSSD "MSSD" /* RO; 1 byte si8 */ 217 #define ASMC_KEY_MSSP "MSSP" /* RO; 1 byte si8 */ 218 #define ASMC_KEY_MSAL "MSAL" /* RO; 1 byte hex_ */ 219 #define ASMC_KEY_MSPS "MSPS" /* RO; 1 or 2 bytes hex_ */ 220 #define ASMC_KEY_MSTS "MSTS" /* RO; 1 byte ui8 */ 221 222 #define ASMC_MSAL_TSS 0x01 /* TSS running */ 223 #define ASMC_MSAL_THERM_VALID 0x02 /* thermal calibration valid */ 224 #define ASMC_MSAL_CALIB_VALID 0x08 /* I/P calibration valid */ 225 #define ASMC_MSAL_PROCHOT 0x40 /* Prochot enabled */ 226 #define ASMC_MSAL_PLIMITS 0x80 /* plimits enabled */ 227 228 /* 229 * Board identity keys. 230 * 231 * RPlt - board platform identifier (e.g. "Mac-XXXX") 232 * RGEN - security chip generation (3 = T2) 233 */ 234 #define ASMC_KEY_RPLT "RPlt" /* RO; 8 bytes ch8* */ 235 #define ASMC_KEY_RGEN "RGEN" /* RO; 1 byte ui8 */ 236 #define ASMC_RPLT_MAXLEN 8 /* RPlt key data length */ 237 238 /* 239 * Shutdown/sleep cause codes (MSSD/MSSP values). 240 * 241 * Positive values indicate normal operation; negative values indicate 242 * fault conditions. 243 * Sources: Apple SMC firmware, VirtualSMC docs, macOS 244 * pmset/powermetrics output. 245 */ 246 struct asmc_cause { 247 int8_t code; 248 const char *desc; /* shutdown description */ 249 const char *sleep_desc; /* sleep description, or NULL if same */ 250 }; 251 252 #define ASMC_CAUSE_BUFLEN 48 /* "-128 (temperature-overlimit-timeout)\0" */ 253 254 static const struct asmc_cause asmc_cause_table[] = { 255 { 5, "good-shutdown", "good-sleep" }, 256 { 3, "power-button", NULL }, 257 { 2, "low-battery-sleep", NULL }, 258 { 1, "overtemp-sleep", NULL }, 259 { 0, "initial", NULL }, 260 { -1, "health-check", NULL }, 261 { -2, "power-supply", NULL }, 262 { -3, "temperature-multisleep", NULL }, 263 { -4, "sensor-fan", NULL }, 264 { -30, "temperature-overlimit-timeout",NULL }, 265 { -40, "pswr-smrst", NULL }, /* power supply watchdog reset */ 266 { -50, "unmapped", NULL }, 267 { -60, "low-battery", NULL }, 268 { -61, "ninja-shutdown", NULL }, /* sudden unexpected power loss */ 269 { -62, "ninja-restart", NULL }, 270 { -70, "palm-rest-temperature", NULL }, 271 { -71, "sodimm-temperature", NULL }, 272 { -72, "heatpipe-temperature", NULL }, 273 { -74, "battery-temperature", NULL }, 274 { -75, "adapter-timeout", NULL }, 275 { -77, "manual-temperature", NULL }, 276 { -78, "adapter-current", NULL }, 277 { -79, "battery-current", NULL }, 278 { -82, "skin-temperature", NULL }, 279 { -83, "skin-temperature-sensors", NULL }, 280 { -84, "backup-temperature", NULL }, 281 { -86, "cpu-proximity-temperature", NULL }, 282 { -95, "cpu-temperature", NULL }, 283 { -100, "power-supply-temperature", NULL }, 284 { -101, "lcd-temperature", NULL }, 285 { -102, "rsm-power-fail", NULL }, 286 { -103, "battery-cuv", NULL }, /* cell under-voltage */ 287 { -127, "pmu-forced-shutdown", NULL }, 288 { -128, "unknown", NULL }, 289 }; 290