From 7f5f7be3e5df92ec2e9447b3d5d0b8ddeb96c9a0 Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Tue, 3 Jul 2012 14:45:59 -0700 Subject: Add memory-mapped data support for I2C and SPI protocols And fix returning memory-mapped string length on LPC as well. BUG=chrome-os-partner:11090 TEST=manual from EC, 'hostevent set 0x40000' from host, 'ectool eventget' --> should print 0x40000 Signed-off-by: Randall Spangler Change-Id: I9edbd0a1468b5d4160ce67c471332226e51fa868 Reviewed-on: https://gerrit.chromium.org/gerrit/26719 Reviewed-by: Simon Glass --- chip/lm4/lpc.c | 2 +- chip/lm4/power_button.c | 4 ++-- chip/lm4/pwm.c | 10 ++++---- common/charge_state.c | 40 ++++++++++++++----------------- common/host_command.c | 40 ++++++++++++++++++++++++++++++- common/temp_sensor.c | 11 ++++----- include/ec_commands.h | 16 +++++++++++++ include/host_command.h | 11 +++++++++ util/comm-host.h | 5 ++++ util/comm-i2c.c | 64 +++++++++++++++++++++++++++++++++++++++---------- util/comm-lpc.c | 4 ++-- util/ectool.c | 30 ++++++++--------------- 12 files changed, 165 insertions(+), 72 deletions(-) diff --git a/chip/lm4/lpc.c b/chip/lm4/lpc.c index fdf491563b..26fcb39931 100644 --- a/chip/lm4/lpc.c +++ b/chip/lm4/lpc.c @@ -227,7 +227,7 @@ void lpc_comx_put_char(int c) */ static void update_host_event_status(void) { uint32_t *mapped_raw_events = - (uint32_t *)(lpc_get_memmap_range() + EC_MEMMAP_HOST_EVENTS); + (uint32_t *)host_get_memmap(EC_MEMMAP_HOST_EVENTS); int need_sci = 0; int need_smi = 0; diff --git a/chip/lm4/power_button.c b/chip/lm4/power_button.c index cf458f9601..5bb7510c33 100644 --- a/chip/lm4/power_button.c +++ b/chip/lm4/power_button.c @@ -515,7 +515,7 @@ void power_button_task(void) static int power_button_init(void) { /* Set up memory-mapped switch positions */ - memmap_switches = lpc_get_memmap_range() + EC_MEMMAP_SWITCHES; + memmap_switches = host_get_memmap(EC_MEMMAP_SWITCHES); *memmap_switches = 0; if (get_lid_open()) { debounced_lid_open = 1; @@ -633,7 +633,7 @@ DECLARE_CONSOLE_COMMAND(lidclose, command_lidclose, static int command_mmapinfo(int argc, char **argv) { - uint8_t *memmap_switches = lpc_get_memmap_range() + EC_MEMMAP_SWITCHES; + uint8_t *memmap_switches = host_get_memmap(EC_MEMMAP_SWITCHES); uint8_t val = *memmap_switches; int i; const char *explanation[] = { diff --git a/chip/lm4/pwm.c b/chip/lm4/pwm.c index 511410c6c2..950dd02268 100644 --- a/chip/lm4/pwm.c +++ b/chip/lm4/pwm.c @@ -5,13 +5,12 @@ /* PWM control module for Chrome EC */ -#include "board.h" +#include "common.h" #include "console.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" #include "lpc.h" -#include "ec_commands.h" #include "pwm.h" #include "registers.h" #include "task.h" @@ -103,11 +102,10 @@ int pwm_set_keyboard_backlight(int percent) return EC_SUCCESS; } -static void update_lpc_mapped_memory(void) +static void update_mapped_memory(void) { int i, r; - uint16_t *mapped = (uint16_t *)(lpc_get_memmap_range() + - EC_MEMMAP_FAN); + uint16_t *mapped = (uint16_t *)host_get_memmap(EC_MEMMAP_FAN); for (i = 0; i < 4; ++i) mapped[i] = 0xffff; @@ -140,7 +138,7 @@ void pwm_task(void) { while (1) { check_fan_failure(); - update_lpc_mapped_memory(); + update_mapped_memory(); usleep(1000000); } } diff --git a/common/charge_state.c b/common/charge_state.c index 338e2f873e..128a1db293 100644 --- a/common/charge_state.c +++ b/common/charge_state.c @@ -8,14 +8,14 @@ #include "battery.h" #include "battery_pack.h" -#include "board.h" #include "charge_state.h" #include "charger.h" #include "chipset.h" +#include "common.h" #include "console.h" #include "gpio.h" +#include "host_command.h" #include "lpc.h" -#include "ec_commands.h" #include "power_button.h" #include "power_led.h" #include "printf.h" @@ -41,37 +41,34 @@ static void update_battery_info(void) int batt_serial; /* Design Capacity of Full */ - battery_design_capacity((int *)(lpc_get_memmap_range() + - EC_MEMMAP_BATT_DCAP)); + battery_design_capacity((int *)host_get_memmap(EC_MEMMAP_BATT_DCAP)); /* Design Voltage */ - battery_design_voltage((int *)(lpc_get_memmap_range() + - EC_MEMMAP_BATT_DVLT)); + battery_design_voltage((int *)host_get_memmap(EC_MEMMAP_BATT_DVLT)); /* Last Full Charge Capacity */ - battery_full_charge_capacity((int *)(lpc_get_memmap_range() + - EC_MEMMAP_BATT_LFCC)); + battery_full_charge_capacity( + (int *)host_get_memmap(EC_MEMMAP_BATT_LFCC)); /* Cycle Count */ - battery_cycle_count((int *)(lpc_get_memmap_range() + - EC_MEMMAP_BATT_CCNT)); + battery_cycle_count((int *)host_get_memmap(EC_MEMMAP_BATT_CCNT)); /* Battery Manufacturer string */ - batt_str = (char *)(lpc_get_memmap_range() + EC_MEMMAP_BATT_MFGR); + batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MFGR); memset(batt_str, 0, EC_MEMMAP_TEXT_MAX); battery_manufacturer_name(batt_str, EC_MEMMAP_TEXT_MAX); /* Battery Model string */ - batt_str = (char *)(lpc_get_memmap_range() + EC_MEMMAP_BATT_MODEL); + batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_MODEL); memset(batt_str, 0, EC_MEMMAP_TEXT_MAX); battery_device_name(batt_str, EC_MEMMAP_TEXT_MAX); /* Battery Type string */ - batt_str = (char *)(lpc_get_memmap_range() + EC_MEMMAP_BATT_TYPE); + batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_TYPE); battery_device_chemistry(batt_str, EC_MEMMAP_TEXT_MAX); /* Smart battery serial number is 16 bits */ - batt_str = (char *)(lpc_get_memmap_range() + EC_MEMMAP_BATT_SERIAL); + batt_str = (char *)host_get_memmap(EC_MEMMAP_BATT_SERIAL); memset(batt_str, 0, EC_MEMMAP_TEXT_MAX); if (battery_serial_number(&batt_serial) == 0) snprintf(batt_str, EC_MEMMAP_TEXT_MAX, "%04X", batt_serial); @@ -474,14 +471,13 @@ void charge_state_machine_task(void) ctx.charger = charger_get_info(); /* Setup LPC direct memmap */ - ctx.memmap_batt_volt = (uint32_t *)(lpc_get_memmap_range() + - EC_MEMMAP_BATT_VOLT); - ctx.memmap_batt_rate = (uint32_t *)(lpc_get_memmap_range() + - EC_MEMMAP_BATT_RATE); - ctx.memmap_batt_cap = (uint32_t *)(lpc_get_memmap_range() + - EC_MEMMAP_BATT_CAP); - ctx.memmap_batt_flags = (uint8_t *)(lpc_get_memmap_range() + - EC_MEMMAP_BATT_FLAG); + ctx.memmap_batt_volt = + (uint32_t *)host_get_memmap(EC_MEMMAP_BATT_VOLT); + ctx.memmap_batt_rate = + (uint32_t *)host_get_memmap(EC_MEMMAP_BATT_RATE); + ctx.memmap_batt_cap = + (uint32_t *)host_get_memmap(EC_MEMMAP_BATT_CAP); + ctx.memmap_batt_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG); while (1) { diff --git a/common/host_command.c b/common/host_command.c index cc7de1e473..3647e50cda 100644 --- a/common/host_command.c +++ b/common/host_command.c @@ -23,6 +23,18 @@ static int host_command[2]; +#ifndef CONFIG_LPC +static uint8_t host_memmap[EC_MEMMAP_SIZE]; +#endif + +uint8_t *host_get_memmap(int offset) +{ +#ifdef CONFIG_LPC + return lpc_get_memmap_range() + offset; +#else + return host_memmap + offset; +#endif +} void host_command_received(int slot, int command) { @@ -93,6 +105,32 @@ static int host_command_read_test(uint8_t *data, int *resp_size) } DECLARE_HOST_COMMAND(EC_CMD_READ_TEST, host_command_read_test); +#ifndef CONFIG_LPC +/* + * Host command to read memory map is not needed on LPC, because LPC can + * directly map the data to the host's memory space. + */ +static int host_command_read_memmap(uint8_t *data, int *resp_size) +{ + struct ec_params_read_memmap *p = (struct ec_params_read_memmap *)data; + struct ec_response_read_memmap *r = + (struct ec_response_read_memmap *)data; + + /* Copy params out of data before we overwrite it with output */ + uint8_t offset = p->offset; + uint8_t size = p->size; + + if (size > sizeof(r->data) || offset > EC_MEMMAP_SIZE || + offset + size > EC_MEMMAP_SIZE) + return EC_RES_INVALID_PARAM; + + memcpy(r->data, host_get_memmap(offset), size); + + *resp_size = size; + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_READ_MEMMAP, host_command_read_memmap); +#endif #ifdef CONFIG_LPC /* ACPI query event handler. Note that the returned value is NOT actually @@ -114,7 +152,7 @@ static int host_command_acpi_query_event(uint8_t *data, int *resp_size) return 0; } DECLARE_HOST_COMMAND(EC_CMD_ACPI_QUERY_EVENT, host_command_acpi_query_event); -#endif +#endif /* CONFIG_LPC */ /* Finds a command by command number. Returns the command structure, or NULL if diff --git a/common/temp_sensor.c b/common/temp_sensor.c index 0cfcade505..257b1a372b 100644 --- a/common/temp_sensor.c +++ b/common/temp_sensor.c @@ -5,14 +5,13 @@ /* Temperature sensor module for Chrome EC */ -#include "board.h" #include "chip_temp_sensor.h" #include "chipset.h" +#include "common.h" #include "console.h" #include "gpio.h" #include "i2c.h" -#include "lpc.h" -#include "ec_commands.h" +#include "host_command.h" #include "peci.h" #include "task.h" #include "temp_sensor.h" @@ -74,10 +73,10 @@ static void poll_fast_sensors(void) } -static void update_lpc_mapped_memory(void) +static void update_mapped_memory(void) { int i, t; - uint8_t *mapped = lpc_get_memmap_range() + EC_MEMMAP_TEMP_SENSOR; + uint8_t *mapped = host_get_memmap(EC_MEMMAP_TEMP_SENSOR); memset(mapped, 0xff, 16); @@ -104,7 +103,7 @@ void temp_sensor_task(void) poll_fast_sensors(); } poll_slow_sensors(); - update_lpc_mapped_memory(); + update_mapped_memory(); } } diff --git a/include/ec_commands.h b/include/ec_commands.h index 719d5c1908..e4499302d9 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -257,6 +257,22 @@ struct ec_params_board_version { uint16_t board_version; /* A monotonously incrementing number. */ } __packed; +/* + * Read memory-mapped data. + * + * This is an alternate interface to memory-mapped data for bus protocols + * which don't support direct-mapped memory - I2C, SPI, etc. + */ +#define EC_CMD_READ_MEMMAP 0x07 + +struct ec_params_read_memmap { + uint8_t offset; /* Offset in memmap (EC_MEMMAP_*) */ + uint8_t size; /* Size to read in bytes */ +} __packed; + +struct ec_response_read_memmap { + uint32_t data[EC_PARAM_SIZE]; +} __packed; /*****************************************************************************/ /* Flash commands */ diff --git a/include/host_command.h b/include/host_command.h index 69facb6268..296ac26d8c 100644 --- a/include/host_command.h +++ b/include/host_command.h @@ -21,6 +21,17 @@ struct host_command { int (*handler)(uint8_t *data, int *response_size); }; +/** + * Return a pointer to the memory-mapped buffer. + * + * This buffer is EC_MEMMAP_SIZE bytes long, is writable at any time, and the + * host can read it at any time. + * + * @param offset Offset within the range to return + * @return pointer to the buffer at that offset + */ +uint8_t *host_get_memmap(int offset); + /** * Process a host command and return its response * diff --git a/util/comm-host.h b/util/comm-host.h index b3790b4717..7a3f856bf9 100644 --- a/util/comm-host.h +++ b/util/comm-host.h @@ -29,6 +29,11 @@ int ec_command(int command, const void *indata, int insize, uint8_t read_mapped_mem8(uint8_t offset); uint16_t read_mapped_mem16(uint8_t offset); uint32_t read_mapped_mem32(uint8_t offset); +/* + * Read a memory-mapped string at the specified offset and store into buf, + * which must be at least size EC_MEMMAP_TEXT_MAX. Returns the length of + * the copied string, not counting the terminating '\0', or <0 if error. + */ int read_mapped_string(uint8_t offset, char *buf); #endif /* COMM_HOST_H */ diff --git a/util/comm-i2c.c b/util/comm-i2c.c index 47241d392e..5020db3ecf 100644 --- a/util/comm-i2c.c +++ b/util/comm-i2c.c @@ -186,30 +186,70 @@ done: return ret; } - uint8_t read_mapped_mem8(uint8_t offset) { - /* Not implemented */ - return 0xff; -} + struct ec_params_read_memmap p; + uint8_t val; + + p.offset = offset; + p.size = sizeof(val); + if (ec_command(EC_CMD_READ_MEMMAP, &p, sizeof(p), + &val, sizeof(val)) < 0) + return 0xff; + + return val; +} uint16_t read_mapped_mem16(uint8_t offset) { - /* Not implemented */ - return 0xffff; -} + struct ec_params_read_memmap p; + uint16_t val; + + p.offset = offset; + p.size = sizeof(val); + if (ec_command(EC_CMD_READ_MEMMAP, &p, sizeof(p), + &val, sizeof(val)) < 0) + return 0xffff; + + return val; +} uint32_t read_mapped_mem32(uint8_t offset) { - /* Not implemented */ - return 0xffffffff; -} + struct ec_params_read_memmap p; + uint32_t val; + p.offset = offset; + p.size = sizeof(val); + + if (ec_command(EC_CMD_READ_MEMMAP, &p, sizeof(p), + &val, sizeof(val)) < 0) + return 0xffffffff; + + return val; +} int read_mapped_string(uint8_t offset, char *buf) { - strncpy(buf, "NOT IMPLEMENTED", EC_MEMMAP_TEXT_MAX); - return sizeof("NOT IMPLEMENTED"); + struct ec_params_read_memmap p; + int c; + + p.offset = offset; + p.size = EC_MEMMAP_TEXT_MAX; + + if (ec_command(EC_CMD_READ_MEMMAP, &p, sizeof(p), + buf, EC_MEMMAP_TEXT_MAX) < 0) { + *buf = 0; + return -1; + } + + for (c = 0; c < EC_MEMMAP_TEXT_MAX; c++) { + if (buf[c] == 0) + return c; + } + + buf[EC_MEMMAP_TEXT_MAX - 1] = 0; + return EC_MEMMAP_TEXT_MAX - 1; } diff --git a/util/comm-lpc.c b/util/comm-lpc.c index 31e2cdb3a2..d91a8a2cc6 100644 --- a/util/comm-lpc.c +++ b/util/comm-lpc.c @@ -157,6 +157,6 @@ int read_mapped_string(uint8_t offset, char *buf) return c; } - buf[EC_MEMMAP_TEXT_MAX-1] = 0; - return EC_MEMMAP_TEXT_MAX; + buf[EC_MEMMAP_TEXT_MAX - 1] = 0; + return EC_MEMMAP_TEXT_MAX - 1; } diff --git a/util/ectool.c b/util/ectool.c index 2cb80bedf1..2b1078323b 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -1487,32 +1487,22 @@ int cmd_battery(int argc, char *argv[]) printf("Battery info:\n"); rv = read_mapped_string(EC_MEMMAP_BATT_MFGR, batt_text); - if (rv) { - if (!is_string_printable(batt_text)) - goto cmd_error; - printf(" OEM name: %s\n", batt_text); - } + if (rv < 0 || !is_string_printable(batt_text)) + goto cmd_error; + printf(" OEM name: %s\n", batt_text); rv = read_mapped_string(EC_MEMMAP_BATT_MODEL, batt_text); - if (rv) { - if (!is_string_printable(batt_text)) - goto cmd_error; - printf(" Model number: %s\n", batt_text); - } + if (rv < 0 || !is_string_printable(batt_text)) + goto cmd_error; + printf(" Model number: %s\n", batt_text); rv = read_mapped_string(EC_MEMMAP_BATT_TYPE, batt_text); - if (rv) { - if (!is_string_printable(batt_text)) - goto cmd_error; - printf(" Chemistry : %s\n", batt_text); - } + if (rv < 0 || !is_string_printable(batt_text)) + goto cmd_error; + printf(" Chemistry : %s\n", batt_text); rv = read_mapped_string(EC_MEMMAP_BATT_SERIAL, batt_text); - if (rv) { - if (!is_string_printable(batt_text)) - goto cmd_error; - printf(" Serial number: %s\n", batt_text); - } + printf(" Serial number: %s\n", batt_text); val = read_mapped_mem32(EC_MEMMAP_BATT_DCAP); if (!is_battery_range(val)) -- cgit v1.2.1