diff options
Diffstat (limited to 'common/ec_ec_comm_slave.c')
-rw-r--r-- | common/ec_ec_comm_slave.c | 327 |
1 files changed, 0 insertions, 327 deletions
diff --git a/common/ec_ec_comm_slave.c b/common/ec_ec_comm_slave.c deleted file mode 100644 index 339f0f0490..0000000000 --- a/common/ec_ec_comm_slave.c +++ /dev/null @@ -1,327 +0,0 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * EC-EC communication, task and functions for slave. - */ - -#include "common.h" -#include "battery.h" -#include "charge_state_v2.h" -#include "console.h" -#include "crc8.h" -#include "ec_commands.h" -#include "ec_ec_comm_slave.h" -#include "extpower.h" -#include "hwtimer.h" -#include "hooks.h" -#include "queue.h" -#include "queue_policies.h" -#include "system.h" -#include "task.h" -#include "util.h" - -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) - -/* Print extra debugging information */ -#undef EXTRA_DEBUG - -/* Set if the master allows the slave to charge the battery. */ -static int charging_allowed; - -/* - * Our command parameter buffer must be big enough to fit any command - * parameter, and crc byte. - */ -#define LARGEST_PARAMS_SIZE 8 - -BUILD_ASSERT(LARGEST_PARAMS_SIZE >= - sizeof(struct ec_params_battery_static_info)); -BUILD_ASSERT(LARGEST_PARAMS_SIZE >= - sizeof(struct ec_params_battery_dynamic_info)); -BUILD_ASSERT(LARGEST_PARAMS_SIZE >= - sizeof(struct ec_params_charger_control)); - -#define COMMAND_BUFFER_PARAMS_SIZE (LARGEST_PARAMS_SIZE + 1) - -/* - * Maximum time needed to read a full command, commands are at most 17 bytes, so - * should not take more than 2ms to be sent at 115200 bps. - */ -#define COMMAND_TIMEOUT_US (5 * MSEC) - - -void ec_ec_comm_slave_written(struct consumer const *consumer, size_t count) -{ - task_wake(TASK_ID_ECCOMM); -} - -/* - * Discard all data from the input queue. - * - * Note that we always sleep for 1ms after clearing the queue, to make sure - * that we give enough time for the next byte to arrive. - */ -static void discard_queue(void) -{ - do { - queue_advance_head(&ec_ec_comm_slave_input, - queue_count(&ec_ec_comm_slave_input)); - usleep(1 * MSEC); - } while (queue_count(&ec_ec_comm_slave_input) > 0); -} - -/* Write response to master. */ -static void write_response(uint16_t res, int seq, const void *data, int len) -{ - struct ec_host_response4 header; - uint8_t crc; - - header.fields0 = - 4 | /* version */ - EC_PACKET4_0_IS_RESPONSE_MASK | /* is_response */ - (seq << EC_PACKET4_0_SEQ_NUM_SHIFT); /* seq_num */ - /* Set data_crc_present if there is data */ - header.fields1 = (len > 0) ? EC_PACKET4_1_DATA_CRC_PRESENT_MASK : 0; - header.result = res; - header.data_len = len; - header.reserved = 0; - header.header_crc = - crc8((uint8_t *)&header, sizeof(header)-1); - QUEUE_ADD_UNITS(&ec_ec_comm_slave_output, - (uint8_t *)&header, sizeof(header)); - - if (len > 0) { - QUEUE_ADD_UNITS(&ec_ec_comm_slave_output, data, len); - crc = crc8(data, len); - QUEUE_ADD_UNITS(&ec_ec_comm_slave_output, &crc, sizeof(crc)); - } -} - -/* - * Read len bytes into buffer. Waiting up to COMMAND_TIMEOUT_US after start. - * - * Returns EC_SUCCESS or EC_ERROR_TIMEOUT. - */ -static int read_data(void *buffer, size_t len, uint32_t start) -{ - uint32_t delta; - - while (queue_count(&ec_ec_comm_slave_input) < len) { - delta = __hw_clock_source_read() - start; - if (delta >= COMMAND_TIMEOUT_US) - return EC_ERROR_TIMEOUT; - - /* Every incoming byte wakes the task. */ - task_wait_event(COMMAND_TIMEOUT_US - delta); - } - - /* Fetch header */ - QUEUE_REMOVE_UNITS(&ec_ec_comm_slave_input, buffer, len); - - return EC_SUCCESS; -} - -static void handle_cmd_reboot_ec( - const struct ec_params_reboot_ec *params, - int data_len, int seq) -{ - int ret = EC_RES_SUCCESS; - - if (data_len != sizeof(*params)) { - ret = EC_RES_INVALID_COMMAND; - goto out; - } - - /* Only handle hibernate */ - if (params->cmd != EC_REBOOT_HIBERNATE) { - ret = EC_RES_INVALID_PARAM; - goto out; - } - - CPRINTS("Hibernating..."); - - system_hibernate(0, 0); - /* We should not be able to write back the response. */ - -out: - write_response(ret, seq, NULL, 0); -} - -#ifdef CONFIG_EC_EC_COMM_BATTERY -static void handle_cmd_charger_control( - const struct ec_params_charger_control *params, - int data_len, int seq) -{ - int ret = EC_RES_SUCCESS; - int prev_charging_allowed = charging_allowed; - - if (data_len != sizeof(*params)) { - ret = EC_RES_INVALID_COMMAND; - goto out; - } - - if (params->max_current >= 0) { - charge_set_output_current_limit(0, 0); - charge_set_input_current_limit( - MIN(MAX_CURRENT_MA, params->max_current), 0); - charging_allowed = params->allow_charging; - } else { - if (-params->max_current > MAX_OTG_CURRENT_MA || - params->otg_voltage > MAX_OTG_VOLTAGE_MV) { - ret = EC_RES_INVALID_PARAM; - goto out; - } - - /* Reset input current to minimum. */ - charge_set_input_current_limit(CONFIG_CHARGER_INPUT_CURRENT, 0); - /* Setup and enable "OTG". */ - charge_set_output_current_limit(-params->max_current, - params->otg_voltage); - charging_allowed = 0; - } - - if (prev_charging_allowed != charging_allowed) - hook_notify(HOOK_AC_CHANGE); - -out: - write_response(ret, seq, NULL, 0); -} - -/* - * On dual-battery slave, we use the charging allowed signal from master to - * indicate whether external power is present. - * - * In most cases, this actually matches the external power status of the master - * (slave battery charging when AC is connected, or discharging when slave - * battery still has enough capacity), with one exception: when we do master to - * slave battery charging (in this case the "external" power is the master). - */ -int extpower_is_present(void) -{ - return charging_allowed; -} -#endif - -void ec_ec_comm_slave_task(void *u) -{ - struct ec_host_request4 header; - /* - * If CONFIG_HOSTCMD_ALIGNED is set, it is important that params is - * aligned on a 32-bit boundary. - */ - uint8_t __aligned(4) params[COMMAND_BUFFER_PARAMS_SIZE]; - unsigned int len, seq = 0, hascrc, cmdver; - uint32_t start; - - while (1) { - task_wait_event(-1); - - if (queue_count(&ec_ec_comm_slave_input) == 0) - continue; - - /* We got some data, start timeout counter. */ - start = __hw_clock_source_read(); - - /* Wait for whole header to be available and read it. */ - if (read_data(&header, sizeof(header), start)) { - CPRINTS("%s timeout (header)", __func__); - goto discard; - } - -#ifdef EXTRA_DEBUG - CPRINTS("%s f0=%02x f1=%02x cmd=%02x, length=%d", __func__, - header.fields0, header.fields1, - header.command, header.data_len); -#endif - - /* Ignore response (we wrote that ourselves) */ - if (header.fields0 & EC_PACKET4_0_IS_RESPONSE_MASK) - goto discard; - - /* Validate version and crc. */ - if ((header.fields0 & EC_PACKET4_0_STRUCT_VERSION_MASK) != 4 || - header.header_crc != - crc8((uint8_t *)&header, sizeof(header)-1)) { - CPRINTS("%s header/crc error", __func__); - goto discard; - } - - len = header.data_len; - hascrc = header.fields1 & EC_PACKET4_1_DATA_CRC_PRESENT_MASK; - if (hascrc) - len += 1; - - /* - * Ignore commands that are too long to fit in our buffer. - */ - if (len > sizeof(params)) { - CPRINTS("%s len error (%d)", __func__, len); - /* Discard the data first, then write error back. */ - discard_queue(); - write_response(EC_RES_OVERFLOW, seq, NULL, 0); - goto discard; - } - - seq = (header.fields0 & EC_PACKET4_0_SEQ_NUM_MASK) >> - EC_PACKET4_0_SEQ_NUM_SHIFT; - - cmdver = header.fields1 & EC_PACKET4_1_COMMAND_VERSION_MASK; - - /* Wait for the rest of the data to be available and read it. */ - if (read_data(params, len, start)) { - CPRINTS("%s timeout (data)", __func__); - goto discard; - } - - /* Check data CRC */ - if (hascrc && params[len-1] != crc8(params, len-1)) { - CPRINTS("%s data crc error", __func__); - write_response(EC_RES_INVALID_CHECKSUM, seq, NULL, 0); - goto discard; - } - - /* For now, all commands have version 0. */ - if (cmdver != 0) { - CPRINTS("%s bad command version", __func__); - write_response(EC_RES_INVALID_VERSION, seq, NULL, 0); - continue; - } - - switch (header.command) { -#ifdef CONFIG_EC_EC_COMM_BATTERY - case EC_CMD_BATTERY_GET_STATIC: - /* Note that we ignore the battery index parameter. */ - write_response(EC_RES_SUCCESS, seq, - &battery_static[BATT_IDX_MAIN], - sizeof(battery_static[BATT_IDX_MAIN])); - break; - case EC_CMD_BATTERY_GET_DYNAMIC: - /* Note that we ignore the battery index parameter. */ - write_response(EC_RES_SUCCESS, seq, - &battery_dynamic[BATT_IDX_MAIN], - sizeof(battery_dynamic[BATT_IDX_MAIN])); - break; - case EC_CMD_CHARGER_CONTROL: - handle_cmd_charger_control((void *)params, - header.data_len, seq); - break; -#endif - case EC_CMD_REBOOT_EC: - handle_cmd_reboot_ec((void *)params, - header.data_len, seq); - break; - default: - write_response(EC_RES_INVALID_COMMAND, seq, - NULL, 0); - } - - continue; -discard: - /* - * Some error occurred: discard all data in the queue. - */ - discard_queue(); - } -} |