Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");