^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * drivers/hwmon/applesmc.c - driver for Apple's SMC (accelerometer, temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * sensors, fan control, keyboard backlight control) used in Intel-based Apple
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * computers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2007 Nicolas Boichat <nicolas@boichat.ch>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2010 Henrik Rydberg <rydberg@euromail.se>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Based on hdaps.c driver:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright (C) 2005 Robert Love <rml@novell.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright (C) 2005 Jesper Juhl <jj@chaosbits.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Fan control based on smcFanControl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Copyright (C) 2006 Hendrik Holtmann <holtmann@mac.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/dmi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/hwmon-sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/leds.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/hwmon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/bits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* data port used by Apple SMC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define APPLESMC_DATA_PORT 0x300
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* command/status port used by Apple SMC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define APPLESMC_CMD_PORT 0x304
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define APPLESMC_MAX_DATA_LENGTH 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* Apple SMC status bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define SMC_STATUS_AWAITING_DATA BIT(0) /* SMC has data waiting to be read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define SMC_STATUS_IB_CLOSED BIT(1) /* Will ignore any input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define SMC_STATUS_BUSY BIT(2) /* Command in progress */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* Initial wait is 8us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define APPLESMC_MIN_WAIT 0x0008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define APPLESMC_READ_CMD 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define APPLESMC_WRITE_CMD 0x11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define APPLESMC_GET_KEY_BY_INDEX_CMD 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define APPLESMC_GET_KEY_TYPE_CMD 0x13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define KEY_COUNT_KEY "#KEY" /* r-o ui32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o {alv (6-10 bytes) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6-10 bytes) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define BACKLIGHT_KEY "LKSB" /* w-o {lkb (2 bytes) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define CLAMSHELL_KEY "MSLD" /* r-o ui8 (unused) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define MOTION_SENSOR_X_KEY "MO_X" /* r-o sp78 (2 bytes) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define MOTION_SENSOR_Y_KEY "MO_Y" /* r-o sp78 (2 bytes) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define MOTION_SENSOR_Z_KEY "MO_Z" /* r-o sp78 (2 bytes) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define MOTION_SENSOR_KEY "MOCN" /* r/w ui16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define FANS_COUNT "FNum" /* r-o ui8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define FANS_MANUAL "FS! " /* r-w ui16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define FAN_ID_FMT "F%dID" /* r-o char[16] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define TEMP_SENSOR_TYPE "sp78"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* List of keys used to read/write fan speeds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static const char *const fan_speed_fmt[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) "F%dAc", /* actual speed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) "F%dMn", /* minimum speed (rw) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) "F%dMx", /* maximum speed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) "F%dSf", /* safe speed - not all models */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) "F%dTg", /* target speed (manual: rw) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define INIT_TIMEOUT_MSECS 5000 /* wait up to 5s for device init ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define INIT_WAIT_MSECS 50 /* ... in 50ms increments */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define APPLESMC_POLL_INTERVAL 50 /* msecs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define APPLESMC_INPUT_FUZZ 4 /* input event threshold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define APPLESMC_INPUT_FLAT 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define to_index(attr) (to_sensor_dev_attr(attr)->index & 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define to_option(attr) (to_sensor_dev_attr(attr)->index >> 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* Dynamic device node attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct applesmc_dev_attr {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct sensor_device_attribute sda; /* hwmon attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) char name[32]; /* room for node file name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* Dynamic device node group */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct applesmc_node_group {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) char *format; /* format string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) void *show; /* show function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) void *store; /* store function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int option; /* function argument */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct applesmc_dev_attr *nodes; /* dynamic node array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* AppleSMC entry - cached register information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct applesmc_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) char key[5]; /* four-letter key code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) u8 valid; /* set when entry is successfully read once */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) u8 len; /* bounded by APPLESMC_MAX_DATA_LENGTH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) char type[5]; /* four-letter type code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) u8 flags; /* 0x10: func; 0x40: write; 0x80: read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* Register lookup and registers common to all SMCs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static struct applesmc_registers {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct mutex mutex; /* register read/write mutex */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) unsigned int key_count; /* number of SMC registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) unsigned int fan_count; /* number of fans */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) unsigned int temp_count; /* number of temperature registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) unsigned int temp_begin; /* temperature lower index bound */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) unsigned int temp_end; /* temperature upper index bound */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) unsigned int index_count; /* size of temperature index array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int num_light_sensors; /* number of light sensors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) bool has_accelerometer; /* has motion sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) bool has_key_backlight; /* has keyboard backlight */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) bool init_complete; /* true when fully initialized */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct applesmc_entry *cache; /* cached key entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) const char **index; /* temperature key index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) } smcreg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .mutex = __MUTEX_INITIALIZER(smcreg.mutex),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static const int debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static struct platform_device *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static s16 rest_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static s16 rest_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static u8 backlight_state[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static struct device *hwmon_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static struct input_dev *applesmc_idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * Last index written to key_at_index sysfs file, and value to use for all other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * key_at_index_* sysfs files.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static unsigned int key_at_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static struct workqueue_struct *applesmc_led_wq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * Wait for specific status bits with a mask on the SMC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * Used before all transactions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * This does 10 fast loops of 8us then exponentially backs off for a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * minimum total wait of 262ms. Depending on usleep_range this could
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * run out past 500ms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static int wait_status(u8 val, u8 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) u8 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) int us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) us = APPLESMC_MIN_WAIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) for (i = 0; i < 24 ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) status = inb(APPLESMC_CMD_PORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if ((status & mask) == val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) usleep_range(us, us * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (i > 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) us <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /* send_byte - Write to SMC data port. Callers must hold applesmc_lock. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static int send_byte(u8 cmd, u16 port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) status = wait_status(0, SMC_STATUS_IB_CLOSED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * This needs to be a separate read looking for bit 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * after bit 0x02 falls. If consolidated with the wait above
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * this extra read may not happen if status returns both
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * simultaneously and this would appear to be required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) status = wait_status(SMC_STATUS_BUSY, SMC_STATUS_BUSY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) outb(cmd, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /* send_command - Write a command to the SMC. Callers must hold applesmc_lock. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static int send_command(u8 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ret = wait_status(0, SMC_STATUS_IB_CLOSED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) outb(cmd, APPLESMC_CMD_PORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * Based on logic from the Apple driver. This is issued before any interaction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * If busy is stuck high, issue a read command to reset the SMC state machine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * If busy is stuck high after the command then the SMC is jammed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static int smc_sane(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) ret = wait_status(0, SMC_STATUS_BUSY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) ret = send_command(APPLESMC_READ_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return wait_status(0, SMC_STATUS_BUSY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static int send_argument(const char *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (send_byte(key[i], APPLESMC_DATA_PORT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) u8 status, data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) ret = smc_sane();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (send_command(cmd) || send_argument(key)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) pr_warn("%.4s: read arg fail\n", key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* This has no effect on newer (2012) SMCs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (send_byte(len, APPLESMC_DATA_PORT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) pr_warn("%.4s: read len fail\n", key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (wait_status(SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) pr_warn("%.4s: read data[%d] fail\n", key, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) buffer[i] = inb(APPLESMC_DATA_PORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /* Read the data port until bit0 is cleared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) for (i = 0; i < 16; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) udelay(APPLESMC_MIN_WAIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) status = inb(APPLESMC_CMD_PORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (!(status & SMC_STATUS_AWAITING_DATA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) data = inb(APPLESMC_DATA_PORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) pr_warn("flushed %d bytes, last value is: %d\n", i, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return wait_status(0, SMC_STATUS_BUSY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) ret = smc_sane();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (send_command(cmd) || send_argument(key)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) pr_warn("%s: write arg fail\n", key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (send_byte(len, APPLESMC_DATA_PORT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) pr_warn("%.4s: write len fail\n", key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (send_byte(buffer[i], APPLESMC_DATA_PORT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) pr_warn("%s: write data fail\n", key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return wait_status(0, SMC_STATUS_BUSY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static int read_register_count(unsigned int *count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) __be32 be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) ret = read_smc(APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) *count = be32_to_cpu(be);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) * Serialized I/O
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) * Returns zero on success or a negative error on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * All functions below are concurrency safe - callers should NOT hold lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) static int applesmc_read_entry(const struct applesmc_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) u8 *buf, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (entry->len != len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) mutex_lock(&smcreg.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) ret = read_smc(APPLESMC_READ_CMD, entry->key, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) mutex_unlock(&smcreg.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) static int applesmc_write_entry(const struct applesmc_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) const u8 *buf, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (entry->len != len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) mutex_lock(&smcreg.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) ret = write_smc(APPLESMC_WRITE_CMD, entry->key, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) mutex_unlock(&smcreg.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static const struct applesmc_entry *applesmc_get_entry_by_index(int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) struct applesmc_entry *cache = &smcreg.cache[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) u8 key[4], info[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) __be32 be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (cache->valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) mutex_lock(&smcreg.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (cache->valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) be = cpu_to_be32(index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) ret = read_smc(APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) ret = read_smc(APPLESMC_GET_KEY_TYPE_CMD, key, info, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) memcpy(cache->key, key, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) cache->len = info[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) memcpy(cache->type, &info[1], 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) cache->flags = info[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) cache->valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) mutex_unlock(&smcreg.mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) static int applesmc_get_lower_bound(unsigned int *lo, const char *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) int begin = 0, end = smcreg.key_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) const struct applesmc_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) while (begin != end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) int middle = begin + (end - begin) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) entry = applesmc_get_entry_by_index(middle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (IS_ERR(entry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) *lo = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return PTR_ERR(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (strcmp(entry->key, key) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) begin = middle + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) end = middle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) *lo = begin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static int applesmc_get_upper_bound(unsigned int *hi, const char *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) int begin = 0, end = smcreg.key_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) const struct applesmc_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) while (begin != end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) int middle = begin + (end - begin) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) entry = applesmc_get_entry_by_index(middle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (IS_ERR(entry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) *hi = smcreg.key_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return PTR_ERR(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (strcmp(key, entry->key) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) end = middle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) begin = middle + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) *hi = begin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) static const struct applesmc_entry *applesmc_get_entry_by_key(const char *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) int begin, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) ret = applesmc_get_lower_bound(&begin, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) ret = applesmc_get_upper_bound(&end, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (end - begin != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return applesmc_get_entry_by_index(begin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) static int applesmc_read_key(const char *key, u8 *buffer, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) const struct applesmc_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) entry = applesmc_get_entry_by_key(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (IS_ERR(entry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) return PTR_ERR(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return applesmc_read_entry(entry, buffer, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static int applesmc_write_key(const char *key, const u8 *buffer, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) const struct applesmc_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) entry = applesmc_get_entry_by_key(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (IS_ERR(entry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return PTR_ERR(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return applesmc_write_entry(entry, buffer, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) static int applesmc_has_key(const char *key, bool *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) const struct applesmc_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) entry = applesmc_get_entry_by_key(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (IS_ERR(entry) && PTR_ERR(entry) != -EINVAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) return PTR_ERR(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) *value = !IS_ERR(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * applesmc_read_s16 - Read 16-bit signed big endian register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) static int applesmc_read_s16(const char *key, s16 *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) u8 buffer[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) ret = applesmc_read_key(key, buffer, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) *value = ((s16)buffer[0] << 8) | buffer[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) * applesmc_device_init - initialize the accelerometer. Can sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) static void applesmc_device_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) int total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) u8 buffer[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if (!smcreg.has_accelerometer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (!applesmc_read_key(MOTION_SENSOR_KEY, buffer, 2) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) (buffer[0] != 0x00 || buffer[1] != 0x00))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) buffer[0] = 0xe0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) buffer[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) applesmc_write_key(MOTION_SENSOR_KEY, buffer, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) msleep(INIT_WAIT_MSECS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) pr_warn("failed to init the device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) static int applesmc_init_index(struct applesmc_registers *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) const struct applesmc_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (s->index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) s->index = kcalloc(s->temp_count, sizeof(s->index[0]), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (!s->index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) for (i = s->temp_begin; i < s->temp_end; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) entry = applesmc_get_entry_by_index(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (IS_ERR(entry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (strcmp(entry->type, TEMP_SENSOR_TYPE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) s->index[s->index_count++] = entry->key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) static int applesmc_init_smcreg_try(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) struct applesmc_registers *s = &smcreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) bool left_light_sensor = 0, right_light_sensor = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) unsigned int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) u8 tmp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (s->init_complete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) ret = read_register_count(&count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (s->cache && s->key_count != count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) pr_warn("key count changed from %d to %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) s->key_count, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) kfree(s->cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) s->cache = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) s->key_count = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (!s->cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) s->cache = kcalloc(s->key_count, sizeof(*s->cache), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (!s->cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) ret = applesmc_read_key(FANS_COUNT, tmp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) s->fan_count = tmp[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (s->fan_count > 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) s->fan_count = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) ret = applesmc_get_lower_bound(&s->temp_begin, "T");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) ret = applesmc_get_lower_bound(&s->temp_end, "U");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) s->temp_count = s->temp_end - s->temp_begin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) ret = applesmc_init_index(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) ret = applesmc_has_key(LIGHT_SENSOR_LEFT_KEY, &left_light_sensor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) ret = applesmc_has_key(LIGHT_SENSOR_RIGHT_KEY, &right_light_sensor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) ret = applesmc_has_key(MOTION_SENSOR_KEY, &s->has_accelerometer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) ret = applesmc_has_key(BACKLIGHT_KEY, &s->has_key_backlight);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) s->num_light_sensors = left_light_sensor + right_light_sensor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) s->init_complete = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) pr_info("key=%d fan=%d temp=%d index=%d acc=%d lux=%d kbd=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) s->key_count, s->fan_count, s->temp_count, s->index_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) s->has_accelerometer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) s->num_light_sensors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) s->has_key_backlight);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) static void applesmc_destroy_smcreg(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) kfree(smcreg.index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) smcreg.index = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) kfree(smcreg.cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) smcreg.cache = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) smcreg.init_complete = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) * applesmc_init_smcreg - Initialize register cache.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) * Retries until initialization is successful, or the operation times out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) static int applesmc_init_smcreg(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) int ms, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) for (ms = 0; ms < INIT_TIMEOUT_MSECS; ms += INIT_WAIT_MSECS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) ret = applesmc_init_smcreg_try();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (ms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) pr_info("init_smcreg() took %d ms\n", ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) msleep(INIT_WAIT_MSECS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) applesmc_destroy_smcreg();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) /* Device model stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) static int applesmc_probe(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) ret = applesmc_init_smcreg();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) applesmc_device_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) /* Synchronize device with memorized backlight state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) static int applesmc_pm_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (smcreg.has_key_backlight)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) /* Reinitialize device on resume from hibernation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) static int applesmc_pm_restore(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) applesmc_device_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) return applesmc_pm_resume(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) static const struct dev_pm_ops applesmc_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) .resume = applesmc_pm_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) .restore = applesmc_pm_restore,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) static struct platform_driver applesmc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) .probe = applesmc_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) .name = "applesmc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) .pm = &applesmc_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) * applesmc_calibrate - Set our "resting" values. Callers must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) * hold applesmc_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) static void applesmc_calibrate(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) applesmc_read_s16(MOTION_SENSOR_X_KEY, &rest_x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) applesmc_read_s16(MOTION_SENSOR_Y_KEY, &rest_y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) rest_x = -rest_x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) static void applesmc_idev_poll(struct input_dev *idev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) s16 x, y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (applesmc_read_s16(MOTION_SENSOR_X_KEY, &x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (applesmc_read_s16(MOTION_SENSOR_Y_KEY, &y))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) x = -x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) input_report_abs(idev, ABS_X, x - rest_x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) input_report_abs(idev, ABS_Y, y - rest_y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) input_sync(idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) /* Sysfs Files */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) static ssize_t applesmc_name_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return snprintf(buf, PAGE_SIZE, "applesmc\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) static ssize_t applesmc_position_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) s16 x, y, z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) ret = applesmc_read_s16(MOTION_SENSOR_X_KEY, &x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) ret = applesmc_read_s16(MOTION_SENSOR_Y_KEY, &y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) ret = applesmc_read_s16(MOTION_SENSOR_Z_KEY, &z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) return snprintf(buf, PAGE_SIZE, "(%d,%d,%d)\n", x, y, z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) static ssize_t applesmc_light_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) struct device_attribute *attr, char *sysfsbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) const struct applesmc_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) static int data_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) u8 left = 0, right = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) u8 buffer[10];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if (!data_length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) entry = applesmc_get_entry_by_key(LIGHT_SENSOR_LEFT_KEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if (IS_ERR(entry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return PTR_ERR(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (entry->len > 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) data_length = entry->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) pr_info("light sensor data length set to %d\n", data_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, data_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) /* newer macbooks report a single 10-bit bigendian value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) if (data_length == 10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) left = be16_to_cpu(*(__be16 *)(buffer + 6)) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) left = buffer[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, data_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) right = buffer[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", left, right);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) /* Displays sensor key as label */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) static ssize_t applesmc_show_sensor_label(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) struct device_attribute *devattr, char *sysfsbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) const char *key = smcreg.index[to_index(devattr)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) /* Displays degree Celsius * 1000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) static ssize_t applesmc_show_temperature(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) struct device_attribute *devattr, char *sysfsbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) const char *key = smcreg.index[to_index(devattr)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) s16 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) int temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) ret = applesmc_read_s16(key, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) temp = 250 * (value >> 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) static ssize_t applesmc_show_fan_speed(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) struct device_attribute *attr, char *sysfsbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) unsigned int speed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) char newkey[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) u8 buffer[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) scnprintf(newkey, sizeof(newkey), fan_speed_fmt[to_option(attr)],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) to_index(attr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) ret = applesmc_read_key(newkey, buffer, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) speed = ((buffer[0] << 8 | buffer[1]) >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) static ssize_t applesmc_store_fan_speed(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) const char *sysfsbuf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) unsigned long speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) char newkey[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) u8 buffer[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (kstrtoul(sysfsbuf, 10, &speed) < 0 || speed >= 0x4000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) return -EINVAL; /* Bigger than a 14-bit value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) scnprintf(newkey, sizeof(newkey), fan_speed_fmt[to_option(attr)],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) to_index(attr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) buffer[0] = (speed >> 6) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) buffer[1] = (speed << 2) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) ret = applesmc_write_key(newkey, buffer, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) static ssize_t applesmc_show_fan_manual(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) struct device_attribute *attr, char *sysfsbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) u16 manual = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) u8 buffer[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) ret = applesmc_read_key(FANS_MANUAL, buffer, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", manual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) static ssize_t applesmc_store_fan_manual(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) const char *sysfsbuf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) u8 buffer[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) unsigned long input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (kstrtoul(sysfsbuf, 10, &input) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) ret = applesmc_read_key(FANS_MANUAL, buffer, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) val = (buffer[0] << 8 | buffer[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) if (input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) val = val | (0x01 << to_index(attr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) val = val & ~(0x01 << to_index(attr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) buffer[0] = (val >> 8) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) buffer[1] = val & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) ret = applesmc_write_key(FANS_MANUAL, buffer, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) static ssize_t applesmc_show_fan_position(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) struct device_attribute *attr, char *sysfsbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) char newkey[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) u8 buffer[17];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) scnprintf(newkey, sizeof(newkey), FAN_ID_FMT, to_index(attr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) ret = applesmc_read_key(newkey, buffer, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) buffer[16] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", buffer+4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) static ssize_t applesmc_calibrate_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) struct device_attribute *attr, char *sysfsbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", rest_x, rest_y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) static ssize_t applesmc_calibrate_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) struct device_attribute *attr, const char *sysfsbuf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) applesmc_calibrate();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) static void applesmc_backlight_set(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) static DECLARE_WORK(backlight_work, &applesmc_backlight_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) static void applesmc_brightness_set(struct led_classdev *led_cdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) enum led_brightness value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) backlight_state[0] = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) ret = queue_work(applesmc_led_wq, &backlight_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) if (debug && (!ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) dev_dbg(led_cdev->dev, "work was already on the queue.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) static ssize_t applesmc_key_count_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) struct device_attribute *attr, char *sysfsbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) u8 buffer[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) u32 count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) ret = applesmc_read_key(KEY_COUNT_KEY, buffer, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) count = ((u32)buffer[0]<<24) + ((u32)buffer[1]<<16) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) ((u32)buffer[2]<<8) + buffer[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) static ssize_t applesmc_key_at_index_read_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) struct device_attribute *attr, char *sysfsbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) const struct applesmc_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) entry = applesmc_get_entry_by_index(key_at_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) if (IS_ERR(entry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) return PTR_ERR(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) ret = applesmc_read_entry(entry, sysfsbuf, entry->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) return entry->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) static ssize_t applesmc_key_at_index_data_length_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) struct device_attribute *attr, char *sysfsbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) const struct applesmc_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) entry = applesmc_get_entry_by_index(key_at_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (IS_ERR(entry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) return PTR_ERR(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", entry->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) static ssize_t applesmc_key_at_index_type_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) struct device_attribute *attr, char *sysfsbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) const struct applesmc_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) entry = applesmc_get_entry_by_index(key_at_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) if (IS_ERR(entry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) return PTR_ERR(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) static ssize_t applesmc_key_at_index_name_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) struct device_attribute *attr, char *sysfsbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) const struct applesmc_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) entry = applesmc_get_entry_by_index(key_at_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) if (IS_ERR(entry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) return PTR_ERR(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) static ssize_t applesmc_key_at_index_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) struct device_attribute *attr, char *sysfsbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", key_at_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) static ssize_t applesmc_key_at_index_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) struct device_attribute *attr, const char *sysfsbuf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) unsigned long newkey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) if (kstrtoul(sysfsbuf, 10, &newkey) < 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) || newkey >= smcreg.key_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) key_at_index = newkey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) static struct led_classdev applesmc_backlight = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) .name = "smc::kbd_backlight",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) .default_trigger = "nand-disk",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) .brightness_set = applesmc_brightness_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) static struct applesmc_node_group info_group[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) { "name", applesmc_name_show },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) { "key_count", applesmc_key_count_show },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) { "key_at_index", applesmc_key_at_index_show, applesmc_key_at_index_store },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) { "key_at_index_name", applesmc_key_at_index_name_show },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) { "key_at_index_type", applesmc_key_at_index_type_show },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) { "key_at_index_data_length", applesmc_key_at_index_data_length_show },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) { "key_at_index_data", applesmc_key_at_index_read_show },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) static struct applesmc_node_group accelerometer_group[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) { "position", applesmc_position_show },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) { "calibrate", applesmc_calibrate_show, applesmc_calibrate_store },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) static struct applesmc_node_group light_sensor_group[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) { "light", applesmc_light_show },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) static struct applesmc_node_group fan_group[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) { "fan%d_label", applesmc_show_fan_position },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) { "fan%d_input", applesmc_show_fan_speed, NULL, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) { "fan%d_min", applesmc_show_fan_speed, applesmc_store_fan_speed, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) { "fan%d_max", applesmc_show_fan_speed, NULL, 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) { "fan%d_safe", applesmc_show_fan_speed, NULL, 3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) { "fan%d_output", applesmc_show_fan_speed, applesmc_store_fan_speed, 4 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) { "fan%d_manual", applesmc_show_fan_manual, applesmc_store_fan_manual },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) static struct applesmc_node_group temp_group[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) { "temp%d_label", applesmc_show_sensor_label },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) { "temp%d_input", applesmc_show_temperature },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) /* Module stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) * applesmc_destroy_nodes - remove files and free associated memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) static void applesmc_destroy_nodes(struct applesmc_node_group *groups)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) struct applesmc_node_group *grp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) struct applesmc_dev_attr *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) for (grp = groups; grp->nodes; grp++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) for (node = grp->nodes; node->sda.dev_attr.attr.name; node++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) sysfs_remove_file(&pdev->dev.kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) &node->sda.dev_attr.attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) kfree(grp->nodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) grp->nodes = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) * applesmc_create_nodes - create a two-dimensional group of sysfs files
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) static int applesmc_create_nodes(struct applesmc_node_group *groups, int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) struct applesmc_node_group *grp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) struct applesmc_dev_attr *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) struct attribute *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) for (grp = groups; grp->format; grp++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) grp->nodes = kcalloc(num + 1, sizeof(*node), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if (!grp->nodes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) for (i = 0; i < num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) node = &grp->nodes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) scnprintf(node->name, sizeof(node->name), grp->format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) node->sda.index = (grp->option << 16) | (i & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) node->sda.dev_attr.show = grp->show;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) node->sda.dev_attr.store = grp->store;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) attr = &node->sda.dev_attr.attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) sysfs_attr_init(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) attr->name = node->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) attr->mode = 0444 | (grp->store ? 0200 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) ret = sysfs_create_file(&pdev->dev.kobj, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) attr->name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) applesmc_destroy_nodes(groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) /* Create accelerometer resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) static int applesmc_create_accelerometer(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) if (!smcreg.has_accelerometer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) ret = applesmc_create_nodes(accelerometer_group, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) applesmc_idev = input_allocate_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) if (!applesmc_idev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) goto out_sysfs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) /* initial calibrate for the input device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) applesmc_calibrate();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) /* initialize the input device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) applesmc_idev->name = "applesmc";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) applesmc_idev->id.bustype = BUS_HOST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) applesmc_idev->dev.parent = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) input_set_abs_params(applesmc_idev, ABS_X,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) input_set_abs_params(applesmc_idev, ABS_Y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) ret = input_setup_polling(applesmc_idev, applesmc_idev_poll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) goto out_idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) input_set_poll_interval(applesmc_idev, APPLESMC_POLL_INTERVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) ret = input_register_device(applesmc_idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) goto out_idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) out_idev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) input_free_device(applesmc_idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) out_sysfs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) applesmc_destroy_nodes(accelerometer_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) pr_warn("driver init failed (ret=%d)!\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) /* Release all resources used by the accelerometer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) static void applesmc_release_accelerometer(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) if (!smcreg.has_accelerometer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) input_unregister_device(applesmc_idev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) applesmc_destroy_nodes(accelerometer_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) static int applesmc_create_light_sensor(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) if (!smcreg.num_light_sensors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) return applesmc_create_nodes(light_sensor_group, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) static void applesmc_release_light_sensor(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) if (!smcreg.num_light_sensors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) applesmc_destroy_nodes(light_sensor_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) static int applesmc_create_key_backlight(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) if (!smcreg.has_key_backlight)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) applesmc_led_wq = create_singlethread_workqueue("applesmc-led");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) if (!applesmc_led_wq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) return led_classdev_register(&pdev->dev, &applesmc_backlight);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) static void applesmc_release_key_backlight(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) if (!smcreg.has_key_backlight)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) led_classdev_unregister(&applesmc_backlight);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) destroy_workqueue(applesmc_led_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) static int applesmc_dmi_match(const struct dmi_system_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) * Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) * So we need to put "Apple MacBook Pro" before "Apple MacBook".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) static const struct dmi_system_id applesmc_whitelist[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) { applesmc_dmi_match, "Apple MacBook Air", {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) { applesmc_dmi_match, "Apple MacBook Pro", {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro") },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) { applesmc_dmi_match, "Apple MacBook", {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) DMI_MATCH(DMI_PRODUCT_NAME, "MacBook") },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) { applesmc_dmi_match, "Apple Macmini", {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) DMI_MATCH(DMI_PRODUCT_NAME, "Macmini") },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) { applesmc_dmi_match, "Apple MacPro", {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) { applesmc_dmi_match, "Apple iMac", {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) DMI_MATCH(DMI_PRODUCT_NAME, "iMac") },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) { .ident = NULL }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) static int __init applesmc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) if (!dmi_check_system(applesmc_whitelist)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) pr_warn("supported laptop not found!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) if (!request_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) "applesmc")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) ret = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) ret = platform_driver_register(&applesmc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) goto out_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) pdev = platform_device_register_simple("applesmc", APPLESMC_DATA_PORT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) if (IS_ERR(pdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) ret = PTR_ERR(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) goto out_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) /* create register cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) ret = applesmc_init_smcreg();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) goto out_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) ret = applesmc_create_nodes(info_group, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) goto out_smcreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) ret = applesmc_create_nodes(fan_group, smcreg.fan_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) goto out_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) ret = applesmc_create_nodes(temp_group, smcreg.index_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) goto out_fans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) ret = applesmc_create_accelerometer();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) goto out_temperature;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) ret = applesmc_create_light_sensor();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) goto out_accelerometer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) ret = applesmc_create_key_backlight();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) goto out_light_sysfs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) hwmon_dev = hwmon_device_register(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) if (IS_ERR(hwmon_dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) ret = PTR_ERR(hwmon_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) goto out_light_ledclass;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) out_light_ledclass:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) applesmc_release_key_backlight();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) out_light_sysfs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) applesmc_release_light_sensor();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) out_accelerometer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) applesmc_release_accelerometer();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) out_temperature:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) applesmc_destroy_nodes(temp_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) out_fans:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) applesmc_destroy_nodes(fan_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) out_info:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) applesmc_destroy_nodes(info_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) out_smcreg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) applesmc_destroy_smcreg();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) out_device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) platform_device_unregister(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) out_driver:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) platform_driver_unregister(&applesmc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) out_region:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) pr_warn("driver init failed (ret=%d)!\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) static void __exit applesmc_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) hwmon_device_unregister(hwmon_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) applesmc_release_key_backlight();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) applesmc_release_light_sensor();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) applesmc_release_accelerometer();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) applesmc_destroy_nodes(temp_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) applesmc_destroy_nodes(fan_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) applesmc_destroy_nodes(info_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) applesmc_destroy_smcreg();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) platform_device_unregister(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) platform_driver_unregister(&applesmc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) module_init(applesmc_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) module_exit(applesmc_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) MODULE_AUTHOR("Nicolas Boichat");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) MODULE_DESCRIPTION("Apple SMC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) MODULE_DEVICE_TABLE(dmi, applesmc_whitelist);