diff options
author | Gerrit <chrome-bot@google.com> | 2012-05-21 09:10:59 -0700 |
---|---|---|
committer | Gerrit Code Review <gerrit@gerrit.golo.chromium.org> | 2012-05-21 09:10:59 -0700 |
commit | 9e2c9b332d8e133ef5ea7ea0814657f42169feed (patch) | |
tree | 9e2635455945f44202098209fcb527b21ffae096 | |
parent | 36107b54d45d9e79c09936a686661f8b83bc8708 (diff) | |
parent | 4c5f1365b50c345ea4f34e353cde31499a9190bd (diff) | |
download | chrome-ec-9e2c9b332d8e133ef5ea7ea0814657f42169feed.tar.gz |
Merge "Use common host command processing for Daisy I2C"
-rw-r--r-- | board/daisy/board.h | 3 | ||||
-rw-r--r-- | board/daisy/ec.tasklist | 3 | ||||
-rw-r--r-- | board/snow/board.h | 3 | ||||
-rw-r--r-- | board/snow/ec.tasklist | 3 | ||||
-rw-r--r-- | chip/stm32/build.mk | 4 | ||||
-rw-r--r-- | chip/stm32/i2c.c | 174 | ||||
-rw-r--r-- | chip/stm32/keyboard_scan.c | 26 | ||||
-rw-r--r-- | common/build.mk | 2 | ||||
-rw-r--r-- | common/host_command.c | 2 | ||||
-rw-r--r-- | common/message.c | 93 | ||||
-rw-r--r-- | include/ec_commands.h | 19 | ||||
-rw-r--r-- | include/keyboard_scan.h | 15 | ||||
-rw-r--r-- | include/message.h | 49 |
13 files changed, 121 insertions, 275 deletions
diff --git a/board/daisy/board.h b/board/daisy/board.h index deb8de1e14..b3a9588a37 100644 --- a/board/daisy/board.h +++ b/board/daisy/board.h @@ -17,6 +17,9 @@ /* support programming on-chip flash */ #define CONFIG_FLASH +/* use I2C for host communication */ +#define CONFIG_I2C + /* By default, enable all console messages except keyboard */ #define CC_DEFAULT (CC_ALL & ~CC_MASK(CC_KEYSCAN)) diff --git a/board/daisy/ec.tasklist b/board/daisy/ec.tasklist index 9a14c9098a..24b151ba87 100644 --- a/board/daisy/ec.tasklist +++ b/board/daisy/ec.tasklist @@ -18,5 +18,4 @@ TASK(KEYSCAN, keyboard_scan_task, NULL) \ TASK(GAIAPOWER, gaia_power_task, NULL) \ TASK(CONSOLE, console_task, NULL) \ - TASK(SPI_WORK, spi_work_task, NULL) \ - TASK(I2C2_WORK, i2c2_work_task, NULL) + TASK(HOSTCMD, host_command_task, NULL) diff --git a/board/snow/board.h b/board/snow/board.h index 7d4a1fd3b5..67156dc0ec 100644 --- a/board/snow/board.h +++ b/board/snow/board.h @@ -14,6 +14,9 @@ /* Use USART1 as console serial port */ #define CONFIG_CONSOLE_UART 1 +/* use I2C for host communication */ +#define CONFIG_I2C + #define USB_CHARGE_PORT_COUNT 0 /* EC drives 13 outputs to keyboard matrix */ diff --git a/board/snow/ec.tasklist b/board/snow/ec.tasklist index 9a14c9098a..24b151ba87 100644 --- a/board/snow/ec.tasklist +++ b/board/snow/ec.tasklist @@ -18,5 +18,4 @@ TASK(KEYSCAN, keyboard_scan_task, NULL) \ TASK(GAIAPOWER, gaia_power_task, NULL) \ TASK(CONSOLE, console_task, NULL) \ - TASK(SPI_WORK, spi_work_task, NULL) \ - TASK(I2C2_WORK, i2c2_work_task, NULL) + TASK(HOSTCMD, host_command_task, NULL) diff --git a/chip/stm32/build.mk b/chip/stm32/build.mk index 03877cf6fe..013569cd75 100644 --- a/chip/stm32/build.mk +++ b/chip/stm32/build.mk @@ -11,8 +11,8 @@ CORE:=cortex-m chip-y=dma.o gpio.o hwtimer.o system.o uart.o chip-y+=jtag-$(CHIP_VARIANT).o clock-$(CHIP_VARIANT).o gpio-$(CHIP_VARIANT).o -chip-$(CONFIG_TASK_SPI_WORK)+=spi.o -chip-$(CONFIG_TASK_I2C2_WORK)+=i2c.o +chip-$(CONFIG_SPI)+=spi.o +chip-$(CONFIG_I2C)+=i2c.o chip-$(CONFIG_TASK_WATCHDOG)+=watchdog.o chip-$(CONFIG_TASK_KEYSCAN)+=keyboard_scan.o chip-$(CONFIG_FLASH)+=flash-$(CHIP_VARIANT).o diff --git a/chip/stm32/i2c.c b/chip/stm32/i2c.c index 8ed60e1fe7..2ccecdba16 100644 --- a/chip/stm32/i2c.c +++ b/chip/stm32/i2c.c @@ -6,12 +6,14 @@ #include "board.h" #include "common.h" #include "console.h" +#include "ec_commands.h" #include "gpio.h" #include "hooks.h" +#include "host_command.h" #include "i2c.h" -#include "message.h" #include "registers.h" #include "task.h" +#include "util.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_I2C, outstr) @@ -30,35 +32,15 @@ #define I2C1 STM32_I2C1_PORT #define I2C2 STM32_I2C2_PORT -static task_id_t task_waiting_on_port[NUM_PORTS]; -static struct mutex port_mutex[NUM_PORTS]; static uint16_t i2c_sr1[NUM_PORTS]; -/* per-transaction counters */ -static unsigned int tx_byte_count; -static unsigned int rx_byte_count; - -/* - * i2c_xmit_mode determines what EC sends when AP initiates a - * read transaction. If AP has not set a transmit mode, then - * default to NOP. - */ -static enum message_cmd_t i2c_xmit_mode[NUM_PORTS] = { CMDC_NOP, CMDC_NOP }; - -/* - * Our output buffers. These must be large enough for our largest message, - * including protocol overhead. - */ -static uint8_t out_msg[32]; +/* buffer for host commands (including error code and checksum) */ +static uint8_t host_buffer[EC_PARAM_SIZE + 2]; +/* current position in host buffer for reception */ +static int rx_index; -static void wait_rx(int port) -{ - /* TODO: Add timeouts and error checking for safety */ - while (!(STM32_I2C_SR1(port) & (1 << 6))) - ; -} static void wait_tx(int port) { @@ -67,71 +49,59 @@ static void wait_tx(int port) ; } -static int i2c_read_raw(int port, void *buf, int len) +static int i2c_write_raw(int port, void *buf, int len) { int i; uint8_t *data = buf; - mutex_lock(&port_mutex[port]); - rx_byte_count = 0; for (i = 0; i < len; i++) { - wait_rx(port); - data[i] = STM32_I2C_DR(port); - rx_byte_count++; + STM32_I2C_DR(port) = data[i]; + wait_tx(port); } - mutex_unlock(&port_mutex[port]); return len; } -static int i2c_write_raw(int port, void *buf, int len) +static void _send_result(int slot, int result, int size) { int i; - uint8_t *data = buf; - - mutex_lock(&port_mutex[port]); - tx_byte_count = 0; - for (i = 0; i < len; i++) { - tx_byte_count++; - STM32_I2C_DR(port) = data[i]; - wait_tx(port); + int len = 1; + uint8_t sum = 0; + + ASSERT(slot == 0); + /* record the error code */ + host_buffer[0] = result; + if (size) { + /* compute checksum */ + for (i = 1; i <= size; i++) + sum += host_buffer[i]; + host_buffer[size + 1] = sum; + len = size + 2; } - mutex_unlock(&port_mutex[port]); - return len; + /* send the answer to the AP */ + i2c_write_raw(I2C2, host_buffer, len); } -void i2c2_work_task(void) +void host_send_result(int slot, int result) { - int msg_len; - uint16_t tmp16; - task_waiting_on_port[1] = task_get_current(); - - while (1) { - task_wait_event(-1); - tmp16 = i2c_sr1[I2C2]; - if (tmp16 & (1 << 6)) { - /* RxNE; AP issued write command */ - i2c_read_raw(I2C2, &i2c_xmit_mode[I2C2], 1); -#ifdef CONFIG_DEBUG - CPRINTF("%s: i2c2_xmit_mode: %02x\n", - __func__, i2c_xmit_mode[I2C2]); -#endif - } else if (tmp16 & (1 << 7)) { - /* RxE; AP is waiting for EC response */ - msg_len = message_process_cmd(i2c_xmit_mode[I2C2], - out_msg, sizeof(out_msg)); - if (msg_len > 0) { - i2c_write_raw(I2C2, out_msg, msg_len); - } else { - CPRINTF("%s: unexpected mode %u\n", - __func__, i2c_xmit_mode[I2C2]); - } + _send_result(slot, result, 0); +} - /* reset EC mode to NOP after transfer is finished */ - i2c_xmit_mode[I2C2] = CMDC_NOP; - } - } +void host_send_response(int slot, const uint8_t *data, int size) +{ + uint8_t *out = host_get_buffer(slot); + + if (data != out) + memcpy(out, data, size); + + _send_result(slot, EC_RES_SUCCESS, size); +} + +uint8_t *host_get_buffer(int slot) +{ + ASSERT(slot == 0); + return host_buffer + 1 /* skip room for error code */; } static void i2c_event_handler(int port) @@ -146,32 +116,35 @@ static void i2c_event_handler(int port) /* cleared by reading SR1 followed by reading SR2 */ STM32_I2C_SR1(port); STM32_I2C_SR2(port); -#ifdef CONFIG_DEBUG - CPRINTF("%s: ADDR\n", __func__); -#endif - } else if (i2c_sr1[port] & (1 << 2)) { - ; -#ifdef CONFIG_DEBUG - CPRINTF("%s: BTF\n", __func__); -#endif } else if (i2c_sr1[port] & (1 << 4)) { /* clear STOPF bit by reading SR1 and then writing CR1 */ STM32_I2C_SR1(port); STM32_I2C_CR1(port) = STM32_I2C_CR1(port); -#ifdef CONFIG_DEBUG - CPRINTF("%s: STOPF\n", __func__); -#endif - } else { - ; -#ifdef CONFIG_DEBUG - CPRINTF("%s: unknown event\n", __func__); -#endif } - /* RxNE or TxE, wake the worker task */ - if (i2c_sr1[port] & ((1 << 6) | (1 << 7))) { - if (port == I2C2) - task_wake(TASK_ID_I2C2_WORK); + /* RxNE event */ + if (i2c_sr1[port] & (1 << 6)) { + if (port == I2C2) { /* AP issued write command */ + if (rx_index >= sizeof(host_buffer) - 1) { + rx_index = 0; + CPRINTF("I2C message too large\n"); + } + host_buffer[rx_index++] = STM32_I2C_DR(I2C2); + } + } + /* TxE event */ + if (i2c_sr1[port] & (1 << 7)) { + if (port == I2C2) { /* AP is waiting for EC response */ + if (rx_index) { + /* we have an available command : execute it */ + host_command_received(0, host_buffer[0]); + /* reset host buffer after end of transfer */ + rx_index = 0; + } else { + /* spurious read : return dummy value */ + STM32_I2C_DR(port) = 0xec; + } + } } } static void i2c2_event_interrupt(void) { i2c_event_handler(I2C2); } @@ -185,13 +158,12 @@ static void i2c_error_handler(int port) if (i2c_sr1[port] & 1 << 10) { /* ACK failed (NACK); expected when AP reads final byte. * Software must clear AF bit. */ - CPRINTF("%s: AF detected\n", __func__); - } - CPRINTF("%s: tx byte count: %u, rx_byte_count: %u\n", - __func__, tx_byte_count, rx_byte_count); - CPRINTF("%s: I2C_SR1(%s): 0x%04x\n", __func__, port, i2c_sr1[port]); - CPRINTF("%s: I2C_SR2(%s): 0x%04x\n", + } else { + CPRINTF("%s: I2C_SR1(%s): 0x%04x\n", + __func__, port, i2c_sr1[port]); + CPRINTF("%s: I2C_SR2(%s): 0x%04x\n", __func__, port, STM32_I2C_SR2(port)); + } #endif STM32_I2C_SR1(port) &= ~0xdf00; @@ -201,8 +173,6 @@ DECLARE_IRQ(STM32_IRQ_I2C2_ER, i2c2_error_interrupt, 2); static int i2c_init2(void) { - int i; - /* enable I2C2 clock */ STM32_RCC_APB1ENR |= 1 << 22; @@ -220,10 +190,6 @@ static int i2c_init2(void) /* clear status */ STM32_I2C_SR1(I2C2) = 0; - /* No tasks are waiting on ports */ - for (i = 0; i < NUM_PORTS; i++) - task_waiting_on_port[i] = TASK_ID_INVALID; - /* enable event and error interrupts */ task_enable_irq(STM32_IRQ_I2C2_EV); task_enable_irq(STM32_IRQ_I2C2_ER); diff --git a/chip/stm32/keyboard_scan.c b/chip/stm32/keyboard_scan.c index 14bb331b1b..2784ae1dc2 100644 --- a/chip/stm32/keyboard_scan.c +++ b/chip/stm32/keyboard_scan.c @@ -13,6 +13,7 @@ #include "board.h" #include "console.h" #include "gpio.h" +#include "host_command.h" #include "keyboard.h" #include "keyboard_scan.h" #include "registers.h" @@ -40,9 +41,6 @@ enum COL_INDEX { /* The keyboard state from the last read */ static uint8_t raw_state[KB_OUTPUTS]; -/* The keyboard state we will return when requested */ -static uint8_t saved_state[KB_OUTPUTS]; - /* Mask with 1 bits only for keys that actually exist */ static const uint8_t *actual_key_mask; @@ -386,9 +384,23 @@ int keyboard_scan_recovery_pressed(void) return 0; } -int keyboard_get_scan(uint8_t **buffp, int max_bytes) +static int keyboard_get_scan(uint8_t *data, int *resp_size) { - kb_fifo_remove(saved_state); - *buffp = saved_state; - return KB_OUTPUTS; + kb_fifo_remove(data); + *resp_size = KB_OUTPUTS; + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_MKBP_STATE, keyboard_get_scan); + +static int keyboard_get_info(uint8_t *data, int *resp_size) +{ + struct ec_response_mkbp_info *r = (struct ec_response_mkbp_info *)data; + + r->rows = 8; + r->cols = KB_OUTPUTS; + + *resp_size = sizeof(struct ec_response_mkbp_info); + return EC_RES_SUCCESS; } +DECLARE_HOST_COMMAND(EC_CMD_MKBP_INFO, keyboard_get_info); diff --git a/common/build.mk b/common/build.mk index 3f8e1258a0..99ce6eaffb 100644 --- a/common/build.mk +++ b/common/build.mk @@ -6,7 +6,7 @@ # Common files build # -common-y=main.o message.o util.o console.o uart_buffering.o +common-y=main.o util.o console.o uart_buffering.o common-y+=memory_commands.o shared_mem.o system_common.o hooks.o common-y+=gpio_commands.o version.o common-$(CONFIG_BATTERY_ATL706486)+=battery_atl706486.o diff --git a/common/host_command.c b/common/host_command.c index 7e1a2f53d6..91fcb3af48 100644 --- a/common/host_command.c +++ b/common/host_command.c @@ -106,6 +106,7 @@ static int host_command_read_test(uint8_t *data, int *resp_size) DECLARE_HOST_COMMAND(EC_CMD_READ_TEST, host_command_read_test); +#ifdef CONFIG_LPC /* ACPI query event handler. Note that the returned value is NOT actually * an EC_RES enum; it's 0 if no event was pending, or the 1-based * index of the lowest bit which was set. */ @@ -126,6 +127,7 @@ static int host_command_acpi_query_event(uint8_t *data, int *resp_size) } DECLARE_HOST_COMMAND(EC_CMD_ACPI_QUERY_EVENT, host_command_acpi_query_event); +#endif /* Finds a command by command number. Returns the command structure, or NULL if diff --git a/common/message.c b/common/message.c deleted file mode 100644 index 76a451b55b..0000000000 --- a/common/message.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * This handles incoming commands and provides responses. - * - * Copyright (c) 2012 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 <--> AP message handling. - */ - -#include "board.h" -#include "message.h" -#include "keyboard_scan.h" -#include "util.h" - -/* EC ID */ -/* (TODO(dhendrix): Define this in board-specific code */ -static const char ec_id[] = "Google Chrome EC"; - -/* Protocol version (least significant byte in lowest byte position) */ -static const uint8_t proto_ver[] = { 1, 0, 0, 0 }; - -/** - * Get the response to a given command - * - * @param cmd Command byte to respond to - * @param buffp Buffer to use for data, or it can be updated to - * point to a new buffer - * @param max_len Number of bytes free at *buffp for the response. - * If the supplied buffer is used, this size must not - * be exceeded. - * @return number of bytes in response (which is in *buffp), or -1 on error - */ -static int message_get_response(int cmd, uint8_t **buffp, int max_len) -{ - /* - * Invalid commands are ignored, just returning a stream of 0xff - * bytes. - */ - switch (cmd) { - case CMDC_PROTO_VER: - *buffp = (uint8_t *)proto_ver; - return sizeof(proto_ver); - case CMDC_NOP: - return 0; - case CMDC_ID: - *buffp = (char *)ec_id; - return sizeof(ec_id) - 1; -#ifdef CONFIG_TASK_KEYSCAN - case CMDC_KEY_STATE: - return keyboard_get_scan(buffp, max_len); -#endif - default: - return -1; - } - - return 0; -} - -int message_process_cmd(int cmd, uint8_t *out_msg, int max_len) -{ - uint8_t *msg; - int msg_len; - int need_copy; - int sum = 0; - int i; - - msg = out_msg; - msg_len = message_get_response(cmd, &msg, max_len - MSG_PROTO_BYTES); - if (msg_len < 0) - return msg_len; - - /* - * We add MSG_PROTO_BYTES bytes of overhead: truncate the reply - * if needed. - */ - if (msg_len + MSG_PROTO_BYTES > max_len) - msg_len = max_len - MSG_PROTO_BYTES; - ASSERT(msg_len >= 0 && msg_len < 0xffff); - need_copy = msg != out_msg; - ASSERT(!need_copy || - msg + msg_len < out_msg || - msg > out_msg + sizeof(out_msg)); - - for (i = 0; i < msg_len; i++) { - if (need_copy) - out_msg[i] = msg[i]; - sum += msg[i]; - } - out_msg[i] = sum; - - return msg_len + MSG_PROTO_BYTES; -} diff --git a/include/ec_commands.h b/include/ec_commands.h index ab0142e81d..d71d75c3d5 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -8,6 +8,25 @@ #ifndef __CROS_EC_COMMANDS_H #define __CROS_EC_COMMANDS_H +/* Protocol overview + * + * request: CMD [ P0 P1 P2 ... Pn S ] + * response: ERR [ P0 P1 P2 ... Pn S ] + * + * where the bytes are defined as follow : + * - CMD is the command code. (defined by EC_CMD_ constants) + * - ERR is the error code. (defined by EC_RES_ constants) + * - Px is the optional payload. + * it is not sent if the error code is not success. + * (defined by ec_params_ and ec_response_ structures) + * - S is the checksum which is the sum of all payload bytes. + * + * On LPC, CMD and ERR are sent/received at EC_LPC_ADDR_KERNEL|USER_CMD + * and the payloads are sent/received at EC_LPC_ADDR_KERNEL|USER_PARAM. + * On I2C, all bytes are sent serially in the same message. + */ + + /* During the development stage, the LPC bus has high error bit rate. * Using checksum can detect the error and trigger re-transmit. * FIXME: remove this after mass production. diff --git a/include/keyboard_scan.h b/include/keyboard_scan.h index 895fdfd2b8..684885c82a 100644 --- a/include/keyboard_scan.h +++ b/include/keyboard_scan.h @@ -16,21 +16,6 @@ int keyboard_scan_init(void); /* Returns non-zero if recovery key was pressed at boot. */ int keyboard_scan_recovery_pressed(void); -/** - * Get the scan data from the keyboard. - * - * This returns the results of the last keyboard scan, by pointing the - * supplied buffer to it, and returning the number of bytes available. - * - * The supplied buffer can be used directly if required, but in that case - * the number of bytes available is limited to 'max_bytes'. - * - * @param buffp Pointer to buffer to contain data - * @param max_bytes Maximum number of bytes available in *buffp - * @return number of bytes available, or -1 for error - */ -int keyboard_get_scan(uint8_t **buffp, int max_bytes); - /* clear any saved keyboard state (empty FIFO, etc) */ void keyboard_clear_state(void); diff --git a/include/message.h b/include/message.h deleted file mode 100644 index 439c6df67e..0000000000 --- a/include/message.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Copyright (c) 2012 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. - */ - -#ifndef __MESSAGE_IF_H -#define __MESSAGE_IF_H - -#include <common.h> - -/* Command interface between EC and AP */ - -enum { - MSG_TRAILER_BYTES = 1, - MSG_PROTO_BYTES = MSG_TRAILER_BYTES, -}; - -/* The command codes that we understand */ -enum message_cmd_t { - /* EC control/status messages */ - CMDC_PROTO_VER = 0x00, /* Protocol version */ - CMDC_NOP, /* No operation / ping */ - CMDC_ID, /* Read EC ID */ - - /* Functional messages */ - CMDC_KEY_STATE = 0x20, /* Read key state */ -}; - - -/** - * Process a command received and return the response - * - * There is no time to compute a reply. The data should be ready - * immediately. This function can be called in interrupt context. - * - * The format of a reply is a sequence of bytes: - * - * <msg bytes> <sum> - * - * The checksum is calculated as the sum of all message bytes - * - * @param cmd Command to process (CMD_...) - * @param buff Pointer to buffer to store reponse - * @param max_len Maximum length of buffer - * @return number of bytes in reply, 0 if none, -1 for unknown command - */ -int message_process_cmd(int cmd, uint8_t *buff, int max_len); - -#endif |