^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for the OLPC XO-1.75 Embedded Controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * The EC protocol is documented at:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * http://wiki.laptop.org/go/XO_1.75_HOST_to_EC_Protocol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2010 One Laptop per Child Foundation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2018 Lubomir Rintel <lkundrak@v3.sk>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/kfifo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/olpc-ec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/power_supply.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/reboot.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/spi/spi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct ec_cmd_t {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) u8 cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) u8 bytes_returned;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) enum ec_chan_t {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) CHAN_NONE = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) CHAN_SWITCH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) CHAN_CMD_RESP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) CHAN_KEYBOARD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) CHAN_TOUCHPAD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) CHAN_EVENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) CHAN_DEBUG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) CHAN_CMD_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * EC events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define EVENT_AC_CHANGE 1 /* AC plugged/unplugged */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define EVENT_BATTERY_STATUS 2 /* Battery low/full/error/gone */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define EVENT_BATTERY_CRITICAL 3 /* Battery critical voltage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define EVENT_BATTERY_SOC_CHANGE 4 /* 1% SOC Change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define EVENT_BATTERY_ERROR 5 /* Abnormal error, query for cause */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define EVENT_POWER_PRESSED 6 /* Power button was pressed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define EVENT_POWER_PRESS_WAKE 7 /* Woken up with a power button */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define EVENT_TIMED_HOST_WAKE 8 /* Host wake timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define EVENT_OLS_HIGH_LIMIT 9 /* OLS crossed dark threshold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define EVENT_OLS_LOW_LIMIT 10 /* OLS crossed light threshold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * EC commands
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * (from http://dev.laptop.org/git/users/rsmith/ec-1.75/tree/ec_cmd.h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define CMD_GET_API_VERSION 0x08 /* out: u8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define CMD_READ_VOLTAGE 0x10 /* out: u16, *9.76/32, mV */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define CMD_READ_CURRENT 0x11 /* out: s16, *15.625/120, mA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define CMD_READ_ACR 0x12 /* out: s16, *6250/15, uAh */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define CMD_READ_BATT_TEMPERATURE 0x13 /* out: u16, *100/256, deg C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define CMD_READ_AMBIENT_TEMPERATURE 0x14 /* unimplemented, no hardware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define CMD_READ_BATTERY_STATUS 0x15 /* out: u8, bitmask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define CMD_READ_SOC 0x16 /* out: u8, percentage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define CMD_READ_GAUGE_ID 0x17 /* out: u8 * 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define CMD_READ_GAUGE_DATA 0x18 /* in: u8 addr, out: u8 data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define CMD_READ_BOARD_ID 0x19 /* out: u16 (platform id) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define CMD_READ_BATT_ERR_CODE 0x1f /* out: u8, error bitmask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define CMD_SET_DCON_POWER 0x26 /* in: u8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define CMD_RESET_EC 0x28 /* none */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define CMD_READ_BATTERY_TYPE 0x2c /* out: u8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define CMD_SET_AUTOWAK 0x33 /* out: u8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define CMD_SET_EC_WAKEUP_TIMER 0x36 /* in: u32, out: ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define CMD_READ_EXT_SCI_MASK 0x37 /* ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define CMD_WRITE_EXT_SCI_MASK 0x38 /* ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define CMD_CLEAR_EC_WAKEUP_TIMER 0x39 /* none */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define CMD_ENABLE_RUNIN_DISCHARGE 0x3B /* none */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define CMD_DISABLE_RUNIN_DISCHARGE 0x3C /* none */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define CMD_READ_MPPT_ACTIVE 0x3d /* out: u8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define CMD_READ_MPPT_LIMIT 0x3e /* out: u8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define CMD_SET_MPPT_LIMIT 0x3f /* in: u8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define CMD_DISABLE_MPPT 0x40 /* none */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define CMD_ENABLE_MPPT 0x41 /* none */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define CMD_READ_VIN 0x42 /* out: u16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define CMD_EXT_SCI_QUERY 0x43 /* ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define RSP_KEYBOARD_DATA 0x48 /* ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define RSP_TOUCHPAD_DATA 0x49 /* ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define CMD_GET_FW_VERSION 0x4a /* out: u8 * 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define CMD_POWER_CYCLE 0x4b /* none */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define CMD_POWER_OFF 0x4c /* none */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define CMD_RESET_EC_SOFT 0x4d /* none */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define CMD_READ_GAUGE_U16 0x4e /* ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define CMD_ENABLE_MOUSE 0x4f /* ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define CMD_ECHO 0x52 /* in: u8 * 5, out: u8 * 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define CMD_GET_FW_DATE 0x53 /* out: u8 * 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define CMD_GET_FW_USER 0x54 /* out: u8 * 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define CMD_TURN_OFF_POWER 0x55 /* none (same as 0x4c) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define CMD_READ_OLS 0x56 /* out: u16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define CMD_OLS_SMT_LEDON 0x57 /* none */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define CMD_OLS_SMT_LEDOFF 0x58 /* none */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define CMD_START_OLS_ASSY 0x59 /* none */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define CMD_STOP_OLS_ASSY 0x5a /* none */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define CMD_OLS_SMTTEST_STOP 0x5b /* none */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define CMD_READ_VIN_SCALED 0x5c /* out: u16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define CMD_READ_BAT_MIN_W 0x5d /* out: u16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define CMD_READ_BAR_MAX_W 0x5e /* out: u16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define CMD_RESET_BAT_MINMAX_W 0x5f /* none */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define CMD_READ_LOCATION 0x60 /* in: u16 addr, out: u8 data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define CMD_WRITE_LOCATION 0x61 /* in: u16 addr, u8 data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define CMD_KEYBOARD_CMD 0x62 /* in: u8, out: ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define CMD_TOUCHPAD_CMD 0x63 /* in: u8, out: ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define CMD_GET_FW_HASH 0x64 /* out: u8 * 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define CMD_SUSPEND_HINT 0x65 /* in: u8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define CMD_ENABLE_WAKE_TIMER 0x66 /* in: u8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define CMD_SET_WAKE_TIMER 0x67 /* in: 32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define CMD_ENABLE_WAKE_AUTORESET 0x68 /* in: u8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define CMD_OLS_SET_LIMITS 0x69 /* in: u16, u16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define CMD_OLS_GET_LIMITS 0x6a /* out: u16, u16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define CMD_OLS_SET_CEILING 0x6b /* in: u16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define CMD_OLS_GET_CEILING 0x6c /* out: u16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * Accepted EC commands, and how many bytes they return. There are plenty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * of EC commands that are no longer implemented, or are implemented only on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * certain older boards.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static const struct ec_cmd_t olpc_xo175_ec_cmds[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) { CMD_GET_API_VERSION, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) { CMD_READ_VOLTAGE, 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) { CMD_READ_CURRENT, 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) { CMD_READ_ACR, 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) { CMD_READ_BATT_TEMPERATURE, 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) { CMD_READ_BATTERY_STATUS, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) { CMD_READ_SOC, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) { CMD_READ_GAUGE_ID, 8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) { CMD_READ_GAUGE_DATA, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) { CMD_READ_BOARD_ID, 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) { CMD_READ_BATT_ERR_CODE, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) { CMD_SET_DCON_POWER, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) { CMD_RESET_EC, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) { CMD_READ_BATTERY_TYPE, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) { CMD_ENABLE_RUNIN_DISCHARGE, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) { CMD_DISABLE_RUNIN_DISCHARGE, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) { CMD_READ_MPPT_ACTIVE, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) { CMD_READ_MPPT_LIMIT, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) { CMD_SET_MPPT_LIMIT, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) { CMD_DISABLE_MPPT, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) { CMD_ENABLE_MPPT, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) { CMD_READ_VIN, 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) { CMD_GET_FW_VERSION, 16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) { CMD_POWER_CYCLE, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) { CMD_POWER_OFF, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) { CMD_RESET_EC_SOFT, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) { CMD_ECHO, 5 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) { CMD_GET_FW_DATE, 16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) { CMD_GET_FW_USER, 16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) { CMD_TURN_OFF_POWER, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) { CMD_READ_OLS, 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) { CMD_OLS_SMT_LEDON, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) { CMD_OLS_SMT_LEDOFF, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) { CMD_START_OLS_ASSY, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) { CMD_STOP_OLS_ASSY, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) { CMD_OLS_SMTTEST_STOP, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) { CMD_READ_VIN_SCALED, 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) { CMD_READ_BAT_MIN_W, 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) { CMD_READ_BAR_MAX_W, 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) { CMD_RESET_BAT_MINMAX_W, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) { CMD_READ_LOCATION, 1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) { CMD_WRITE_LOCATION, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) { CMD_GET_FW_HASH, 16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) { CMD_SUSPEND_HINT, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) { CMD_ENABLE_WAKE_TIMER, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) { CMD_SET_WAKE_TIMER, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) { CMD_ENABLE_WAKE_AUTORESET, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) { CMD_OLS_SET_LIMITS, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) { CMD_OLS_GET_LIMITS, 4 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) { CMD_OLS_SET_CEILING, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) { CMD_OLS_GET_CEILING, 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) { CMD_READ_EXT_SCI_MASK, 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) { CMD_WRITE_EXT_SCI_MASK, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #define EC_MAX_CMD_DATA_LEN 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) #define EC_MAX_RESP_LEN 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) #define LOG_BUF_SIZE 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) #define PM_WAKEUP_TIME 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) #define EC_ALL_EVENTS GENMASK(15, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) enum ec_state_t {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) CMD_STATE_IDLE = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) CMD_STATE_WAITING_FOR_SWITCH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) CMD_STATE_CMD_IN_TX_FIFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) CMD_STATE_CMD_SENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) CMD_STATE_RESP_RECEIVED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) CMD_STATE_ERROR_RECEIVED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct olpc_xo175_ec_cmd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) u8 command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) u8 nr_args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) u8 data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) u8 args[EC_MAX_CMD_DATA_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) struct olpc_xo175_ec_resp {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) u8 channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) u8 byte;
^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) struct olpc_xo175_ec {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) bool suspended;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* SPI related stuff. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct spi_device *spi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct spi_transfer xfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct spi_message msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct olpc_xo175_ec_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct olpc_xo175_ec_resp resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) } tx_buf, rx_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* GPIO for the CMD signals. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct gpio_desc *gpio_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /* Command handling related state. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) spinlock_t cmd_state_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) int cmd_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) bool cmd_running;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) struct completion cmd_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct olpc_xo175_ec_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) u8 resp_data[EC_MAX_RESP_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int expected_resp_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) int resp_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /* Power button. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct input_dev *pwrbtn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* Debug handling. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) char logbuf[LOG_BUF_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) int logbuf_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static struct platform_device *olpc_ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static int olpc_xo175_ec_resp_len(u8 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) const struct ec_cmd_t *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) for (p = olpc_xo175_ec_cmds; p->cmd; p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (p->cmd == cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return p->bytes_returned;
^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) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static void olpc_xo175_ec_flush_logbuf(struct olpc_xo175_ec *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) dev_dbg(&priv->spi->dev, "got debug string [%*pE]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) priv->logbuf_len, priv->logbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) priv->logbuf_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static void olpc_xo175_ec_complete(void *arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static void olpc_xo175_ec_send_command(struct olpc_xo175_ec *priv, void *cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) size_t cmdlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) memcpy(&priv->tx_buf, cmd, cmdlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) priv->xfer.len = cmdlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) spi_message_init_with_transfers(&priv->msg, &priv->xfer, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) priv->msg.complete = olpc_xo175_ec_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) priv->msg.context = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) ret = spi_async(priv->spi, &priv->msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) dev_err(&priv->spi->dev, "spi_async() failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static void olpc_xo175_ec_read_packet(struct olpc_xo175_ec *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) u8 nonce[] = {0xA5, 0x5A};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) olpc_xo175_ec_send_command(priv, nonce, sizeof(nonce));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static void olpc_xo175_ec_complete(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) struct olpc_xo175_ec *priv = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) struct device *dev = &priv->spi->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) struct power_supply *psy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) u8 channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) u8 byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ret = priv->msg.status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) dev_err(dev, "SPI transfer failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) spin_lock_irqsave(&priv->cmd_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (priv->cmd_running) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) priv->resp_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) priv->cmd_state = CMD_STATE_ERROR_RECEIVED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) complete(&priv->cmd_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) spin_unlock_irqrestore(&priv->cmd_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (ret != -EINTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) olpc_xo175_ec_read_packet(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) channel = priv->rx_buf.resp.channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) byte = priv->rx_buf.resp.byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) switch (channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) case CHAN_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) spin_lock_irqsave(&priv->cmd_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (!priv->cmd_running) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) /* We can safely ignore these */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) dev_err(dev, "spurious FIFO read packet\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) spin_unlock_irqrestore(&priv->cmd_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) priv->cmd_state = CMD_STATE_CMD_SENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (!priv->expected_resp_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) complete(&priv->cmd_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) olpc_xo175_ec_read_packet(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) spin_unlock_irqrestore(&priv->cmd_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) case CHAN_SWITCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) spin_lock_irqsave(&priv->cmd_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (!priv->cmd_running) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /* Just go with the flow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) dev_err(dev, "spurious SWITCH packet\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) memset(&priv->cmd, 0, sizeof(priv->cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) priv->cmd.command = CMD_ECHO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) priv->cmd_state = CMD_STATE_CMD_IN_TX_FIFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) /* Throw command into TxFIFO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) gpiod_set_value_cansleep(priv->gpio_cmd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) olpc_xo175_ec_send_command(priv, &priv->cmd, sizeof(priv->cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) spin_unlock_irqrestore(&priv->cmd_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) case CHAN_CMD_RESP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) spin_lock_irqsave(&priv->cmd_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (!priv->cmd_running) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) dev_err(dev, "spurious response packet\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) } else if (priv->resp_len >= priv->expected_resp_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) dev_err(dev, "too many response packets\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) priv->resp_data[priv->resp_len++] = byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (priv->resp_len == priv->expected_resp_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) priv->cmd_state = CMD_STATE_RESP_RECEIVED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) complete(&priv->cmd_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) spin_unlock_irqrestore(&priv->cmd_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) case CHAN_CMD_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) spin_lock_irqsave(&priv->cmd_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (!priv->cmd_running) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) dev_err(dev, "spurious cmd error packet\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) priv->resp_data[0] = byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) priv->resp_len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) priv->cmd_state = CMD_STATE_ERROR_RECEIVED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) complete(&priv->cmd_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) spin_unlock_irqrestore(&priv->cmd_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) case CHAN_KEYBOARD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) dev_warn(dev, "keyboard is not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) case CHAN_TOUCHPAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) dev_warn(dev, "touchpad is not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) case CHAN_EVENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) dev_dbg(dev, "got event %.2x\n", byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) switch (byte) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) case EVENT_AC_CHANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) psy = power_supply_get_by_name("olpc_ac");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (psy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) power_supply_changed(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) power_supply_put(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) case EVENT_BATTERY_STATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) case EVENT_BATTERY_CRITICAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) case EVENT_BATTERY_SOC_CHANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) case EVENT_BATTERY_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) psy = power_supply_get_by_name("olpc_battery");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (psy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) power_supply_changed(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) power_supply_put(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) case EVENT_POWER_PRESSED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) input_report_key(priv->pwrbtn, KEY_POWER, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) input_sync(priv->pwrbtn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) input_report_key(priv->pwrbtn, KEY_POWER, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) input_sync(priv->pwrbtn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) case EVENT_POWER_PRESS_WAKE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) case EVENT_TIMED_HOST_WAKE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) pm_wakeup_event(priv->pwrbtn->dev.parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) PM_WAKEUP_TIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) dev_dbg(dev, "ignored unknown event %.2x\n", byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) case CHAN_DEBUG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (byte == '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) olpc_xo175_ec_flush_logbuf(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) } else if (isprint(byte)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) priv->logbuf[priv->logbuf_len++] = byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (priv->logbuf_len == LOG_BUF_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) olpc_xo175_ec_flush_logbuf(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) dev_warn(dev, "unknown channel: %d, %.2x\n", channel, byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /* Most non-command packets get the TxFIFO refilled and an ACK. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) olpc_xo175_ec_read_packet(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) * This function is protected with a mutex. We can safely assume that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * there will be only one instance of this function running at a time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) * One of the ways in which we enforce this is by waiting until we get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * all response bytes back from the EC, rather than just the number that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * the caller requests (otherwise, we might start a new command while an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * old command's response bytes are still incoming).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static int olpc_xo175_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *resp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) size_t resp_len, void *ec_cb_arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) struct olpc_xo175_ec *priv = ec_cb_arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct device *dev = &priv->spi->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) size_t nr_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) dev_dbg(dev, "CMD %x, %zd bytes expected\n", cmd, resp_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (inlen > 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) dev_err(dev, "command len %zd too big!\n", resp_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /* Suspending in the middle of an EC command hoses things badly! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (WARN_ON(priv->suspended))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) /* Ensure a valid command and return bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) ret = olpc_xo175_ec_resp_len(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) dev_err_ratelimited(dev, "unknown command 0x%x\n", cmd);
^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) * Assume the best in our callers, and allow unknown commands
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) * through. I'm not the charitable type, but it was beaten
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * into me. Just maintain a minimum standard of sanity.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (resp_len > sizeof(priv->resp_data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) dev_err(dev, "response too big: %zd!\n", resp_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) nr_bytes = resp_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) nr_bytes = (size_t)ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) resp_len = min(resp_len, nr_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) spin_lock_irqsave(&priv->cmd_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) /* Initialize the state machine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) init_completion(&priv->cmd_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) priv->cmd_running = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) priv->cmd_state = CMD_STATE_WAITING_FOR_SWITCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) memset(&priv->cmd, 0, sizeof(priv->cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) priv->cmd.command = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) priv->cmd.nr_args = inlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) priv->cmd.data_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) memcpy(priv->cmd.args, inbuf, inlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) priv->expected_resp_len = nr_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) priv->resp_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) /* Tickle the cmd gpio to get things started */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) gpiod_set_value_cansleep(priv->gpio_cmd, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) spin_unlock_irqrestore(&priv->cmd_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) /* The irq handler should do the rest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (!wait_for_completion_timeout(&priv->cmd_done,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) msecs_to_jiffies(4000))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) dev_err(dev, "EC cmd error: timeout in STATE %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) priv->cmd_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) gpiod_set_value_cansleep(priv->gpio_cmd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) spi_slave_abort(priv->spi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) olpc_xo175_ec_read_packet(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) spin_lock_irqsave(&priv->cmd_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) /* Deal with the results. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (priv->cmd_state == CMD_STATE_ERROR_RECEIVED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) /* EC-provided error is in the single response byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) dev_err(dev, "command 0x%x returned error 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) cmd, priv->resp_data[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) ret = -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) } else if (priv->resp_len != nr_bytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) dev_err(dev, "command 0x%x returned %d bytes, expected %zd bytes\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) cmd, priv->resp_len, nr_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) ret = -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) * We may have 8 bytes in priv->resp, but we only care about
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) * what we've been asked for. If the caller asked for only 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) * bytes, give them that. We've guaranteed that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) * resp_len <= priv->resp_len and priv->resp_len == nr_bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) memcpy(resp, priv->resp_data, resp_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) /* This should already be low, but just in case. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) gpiod_set_value_cansleep(priv->gpio_cmd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) priv->cmd_running = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) spin_unlock_irqrestore(&priv->cmd_state_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) static int olpc_xo175_ec_set_event_mask(unsigned int mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) u8 args[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) args[0] = mask >> 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) args[1] = mask >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) return olpc_ec_cmd(CMD_WRITE_EXT_SCI_MASK, args, 2, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) static void olpc_xo175_ec_power_off(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) olpc_ec_cmd(CMD_POWER_OFF, NULL, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) mdelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) static int __maybe_unused olpc_xo175_ec_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) struct olpc_xo175_ec *priv = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) u8 suspend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) u32 suspend_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) } __packed hintargs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) static unsigned int suspend_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * SOC_SLEEP is not wired to the EC on B3 and earlier boards.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) * This command lets the EC know instead. The suspend count doesn't seem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) * to be used anywhere but in the EC debug output.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) hintargs.suspend = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) hintargs.suspend_count = suspend_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) olpc_ec_cmd(CMD_SUSPEND_HINT, (void *)&hintargs, sizeof(hintargs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * After we've sent the suspend hint, don't allow further EC commands
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * to be run until we've resumed. Userspace tasks should be frozen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * but kernel threads and interrupts could still schedule EC commands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) priv->suspended = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) static int __maybe_unused olpc_xo175_ec_resume_noirq(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) struct olpc_xo175_ec *priv = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) priv->suspended = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static int __maybe_unused olpc_xo175_ec_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) u8 x = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) * The resume hint is only needed if no other commands are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) * being sent during resume. all it does is tell the EC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * the SoC is definitely awake.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) olpc_ec_cmd(CMD_SUSPEND_HINT, &x, 1, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) /* Enable all EC events while we're awake */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) olpc_xo175_ec_set_event_mask(EC_ALL_EVENTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) return 0;
^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) static struct olpc_ec_driver olpc_xo175_ec_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) .ec_cmd = olpc_xo175_ec_cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) static int olpc_xo175_ec_remove(struct spi_device *spi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (pm_power_off == olpc_xo175_ec_power_off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) pm_power_off = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) spi_slave_abort(spi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) platform_device_unregister(olpc_ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) olpc_ec = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) static int olpc_xo175_ec_probe(struct spi_device *spi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) struct olpc_xo175_ec *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (olpc_ec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) dev_err(&spi->dev, "OLPC EC already registered.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) priv->gpio_cmd = devm_gpiod_get(&spi->dev, "cmd", GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (IS_ERR(priv->gpio_cmd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) dev_err(&spi->dev, "failed to get cmd gpio: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) PTR_ERR(priv->gpio_cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) return PTR_ERR(priv->gpio_cmd);
^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) priv->spi = spi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) spin_lock_init(&priv->cmd_state_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) priv->cmd_state = CMD_STATE_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) init_completion(&priv->cmd_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) priv->logbuf_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) /* Set up power button input device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) priv->pwrbtn = devm_input_allocate_device(&spi->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (!priv->pwrbtn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) priv->pwrbtn->name = "Power Button";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) priv->pwrbtn->dev.parent = &spi->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) input_set_capability(priv->pwrbtn, EV_KEY, KEY_POWER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) ret = input_register_device(priv->pwrbtn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) dev_err(&spi->dev, "error registering input device: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) spi_set_drvdata(spi, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) priv->xfer.rx_buf = &priv->rx_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) priv->xfer.tx_buf = &priv->tx_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) olpc_xo175_ec_read_packet(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) olpc_ec_driver_register(&olpc_xo175_ec_driver, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) olpc_ec = platform_device_register_resndata(&spi->dev, "olpc-ec", -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) NULL, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) /* Enable all EC events while we're awake */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) olpc_xo175_ec_set_event_mask(EC_ALL_EVENTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (pm_power_off == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) pm_power_off = olpc_xo175_ec_power_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) dev_info(&spi->dev, "OLPC XO-1.75 Embedded Controller driver\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) static const struct dev_pm_ops olpc_xo175_ec_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(NULL, olpc_xo175_ec_resume_noirq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) SET_RUNTIME_PM_OPS(olpc_xo175_ec_suspend, olpc_xo175_ec_resume, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) static const struct of_device_id olpc_xo175_ec_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) { .compatible = "olpc,xo1.75-ec" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) MODULE_DEVICE_TABLE(of, olpc_xo175_ec_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) static const struct spi_device_id olpc_xo175_ec_id_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) { "xo1.75-ec", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) MODULE_DEVICE_TABLE(spi, olpc_xo175_ec_id_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) static struct spi_driver olpc_xo175_ec_spi_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) .name = "olpc-xo175-ec",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) .of_match_table = olpc_xo175_ec_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) .pm = &olpc_xo175_ec_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) .probe = olpc_xo175_ec_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) .remove = olpc_xo175_ec_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) module_spi_driver(olpc_xo175_ec_spi_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) MODULE_DESCRIPTION("OLPC XO-1.75 Embedded Controller driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>"); /* Functionality */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>"); /* Bugs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) MODULE_LICENSE("GPL");