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