summaryrefslogtreecommitdiff
path: root/chip/it83xx
diff options
context:
space:
mode:
authorDino Li <dino.li@ite.com.tw>2016-01-25 15:01:18 +0800
committerchrome-bot <chrome-bot@chromium.org>2016-01-26 23:59:47 -0800
commit72ad2608470a58ad2f82c076229feddfcbc2a6a2 (patch)
tree52fcbe32d8d8fec4423620818a3b05be4a780756 /chip/it83xx
parent74e81bf9daba09b989a4e9e3153e7db5e6c4e730 (diff)
downloadchrome-ec-72ad2608470a58ad2f82c076229feddfcbc2a6a2.tar.gz
chip: it83xx: update ec2i module
1. The previous EC2I module does not meet section '7.17.5 EC2I Programming Guide'. We need to correct it to prevent conflict with H2RAM (LPC I/O cycles 800h ~ 9ffh) which cause LPC keeps long wait states. NOTE: If EC is using EC2I internal bus to access PNPCFG registers while host accessing EC ram through H2RAM interface at the same time, the symptom will appear. 2. Remove 'CONFIG_IT83XX_PNPCFG_HOST_ACCESS'. We don't allow the host access PNPCFG registers. Signed-off-by: Dino Li <dino.li@ite.com.tw> BRANCH=none BUG=none TEST=1. To use console command 'rwreg' to r/w PNPCFG registers and there is no error code return. 2. To create a stress test for this change. - EC use 'ec2i_read()' and 'ec2i_write()' to access PNPCFG registers per-10ms. - run ectool 'version' command per-100ms. Before the change was made, LPC will keep in long wait states immediately. After the change, we run the test of ectool 'version' command over 20000 times. Change-Id: I84e86fc17ef624d4a60a1a051bc301ebdf56a3da Reviewed-on: https://chromium-review.googlesource.com/323563 Commit-Ready: Dino Li <dino.li@ite.com.tw> Tested-by: Dino Li <dino.li@ite.com.tw> Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'chip/it83xx')
-rw-r--r--chip/it83xx/ec2i.c231
1 files changed, 112 insertions, 119 deletions
diff --git a/chip/it83xx/ec2i.c b/chip/it83xx/ec2i.c
index 05266bec1b..cb8f5d3365 100644
--- a/chip/it83xx/ec2i.c
+++ b/chip/it83xx/ec2i.c
@@ -5,154 +5,147 @@
/* EC2I control module for IT83xx. */
-#include "hooks.h"
+#include "common.h"
#include "ec2i_chip.h"
+#include "hooks.h"
#include "registers.h"
+#include "task.h"
#include "timer.h"
-#define EC2I_ACCESS_TIME_USEC 15
-
-static int ec2i_check_status_bit(uint8_t status_bit)
+/* EC2I access index/data port */
+enum ec2i_access {
+ /* index port */
+ EC2I_ACCESS_INDEX = 0,
+ /* data port */
+ EC2I_ACCESS_DATA = 1,
+};
+
+enum ec2i_status_mask {
+ /* 1: EC read-access is still processing. */
+ EC2I_STATUS_CRIB = (1 << 1),
+ /* 1: EC write-access is still processing with IHD register. */
+ EC2I_STATUS_CWIB = (1 << 2),
+ EC2I_STATUS_ALL = (EC2I_STATUS_CRIB | EC2I_STATUS_CWIB),
+};
+
+static int ec2i_wait_status_bit_cleared(enum ec2i_status_mask mask)
{
- int num;
-
- for (num = 0; num < 10; num++) {
- udelay(EC2I_ACCESS_TIME_USEC);
-
- if (!(IT83XX_EC2I_IBCTL & status_bit))
- return 0;
- }
+ /* delay ~15.25us */
+ IT83XX_GCTRL_WNCKR = 0;
- /* Timeout */
- return -1;
+ return (IT83XX_EC2I_IBCTL & mask);
}
-static void ec2i_ec_access_enable(void)
+static enum ec2i_message ec2i_write_pnpcfg(enum ec2i_access sel, uint8_t data)
{
- /*
- * bit0: Host access to the PNPCFG registers is disabled.
- * bit1: Host access to the BRAM registers is disabled.
- */
- IT83XX_EC2I_LSIOHA |= 0x03;
-
- /* bit0: EC to I-Bus access enabled. */
- IT83XX_EC2I_IBCTL |= 0x01;
-
- /*
- * Make sure that both CRIB and CWIB bits in IBCTL register
- * are cleared.
- * bit1: CRIB
- * bit2: CWIB
- */
- if (ec2i_check_status_bit(0x06))
- IT83XX_EC2I_IBCTL &= ~0x02;
-
- /* Enable EC access to the PNPCFG registers */
- IT83XX_EC2I_IBMAE |= 0x01;
-}
+ int rv = EC_ERROR_UNKNOWN;
-static void ec2i_ec_access_disable(void)
-{
- /* Disable EC access to the PNPCFG registers. */
- IT83XX_EC2I_IBMAE &= ~0x01;
-
- /* Diable EC to I-Bus access. */
- IT83XX_EC2I_IBCTL &= ~0x01;
+ /* bit1 : VCC power on */
+ if (IT83XX_SWUC_SWCTL1 & (1 << 1)) {
+ /*
+ * Wait that both CRIB and CWIB bits in IBCTL register
+ * are cleared.
+ */
+ rv = ec2i_wait_status_bit_cleared(EC2I_STATUS_ALL);
+ if (!rv) {
+ /* Set indirect host I/O offset. */
+ IT83XX_EC2I_IHIOA = sel;
+ /* Write the data to IHD register */
+ IT83XX_EC2I_IHD = data;
+ /* Enable EC access to the PNPCFG registers */
+ IT83XX_EC2I_IBMAE |= (1 << 0);
+ /* bit0: EC to I-Bus access enabled. */
+ IT83XX_EC2I_IBCTL |= (1 << 0);
+ /* Wait the CWIB bit in IBCTL cleared. */
+ rv = ec2i_wait_status_bit_cleared(EC2I_STATUS_CWIB);
+ /* Disable EC access to the PNPCFG registers. */
+ IT83XX_EC2I_IBMAE &= ~(1 << 0);
+ /* Disable EC to I-Bus access. */
+ IT83XX_EC2I_IBCTL &= ~(1 << 0);
+ }
+ }
-#ifdef CONFIG_IT83XX_PNPCFG_HOST_ACCESS
- /* Enable host access */
- IT83XX_EC2I_LSIOHA &= ~0x03;
-#else
- /* Host access is disabled */
- IT83XX_EC2I_LSIOHA &= ~0x02;
-#endif
+ return rv ? EC2I_WRITE_ERROR : EC2I_WRITE_SUCCESS;
}
-/* EC2I write */
-enum ec2i_message ec2i_write(enum host_pnpcfg_index index, uint8_t data)
+static enum ec2i_message ec2i_read_pnpcfg(enum ec2i_access sel)
{
- /* bit1 : VCC power on */
- if (IT83XX_SWUC_SWCTL1 & 0x02) {
- /* Enable EC2I EC access */
- ec2i_ec_access_enable();
-
- /* Set indirect host I/O offset. (index port) */
- IT83XX_EC2I_IHIOA = 0;
- IT83XX_EC2I_IHD = index;
-
- /* Read the CWIB bit in IBCTL until it returns 0. */
- if (ec2i_check_status_bit(0x04)) {
- ec2i_ec_access_disable();
- return EC2I_WRITE_ERROR;
- }
+ int rv = EC_ERROR_UNKNOWN;
+ uint8_t ihd = 0;
- /* Set indirect host I/O offset. (data port) */
- IT83XX_EC2I_IHIOA = 1;
- IT83XX_EC2I_IHD = data;
-
- /* Read the CWIB bit in IBCTL until it returns 0. */
- if (ec2i_check_status_bit(0x04)) {
- ec2i_ec_access_disable();
- return EC2I_WRITE_ERROR;
+ /* bit1 : VCC power on */
+ if (IT83XX_SWUC_SWCTL1 & (1 << 1)) {
+ /*
+ * Wait that both CRIB and CWIB bits in IBCTL register
+ * are cleared.
+ */
+ rv = ec2i_wait_status_bit_cleared(EC2I_STATUS_ALL);
+ if (!rv) {
+ /* Set indirect host I/O offset. */
+ IT83XX_EC2I_IHIOA = sel;
+ /* Enable EC access to the PNPCFG registers */
+ IT83XX_EC2I_IBMAE |= (1 << 0);
+ /* bit1: a read-action */
+ IT83XX_EC2I_IBCTL |= (1 << 1);
+ /* bit0: EC to I-Bus access enabled. */
+ IT83XX_EC2I_IBCTL |= (1 << 0);
+ /* Wait the CRIB bit in IBCTL cleared. */
+ rv = ec2i_wait_status_bit_cleared(EC2I_STATUS_CRIB);
+ /* Read the data from IHD register */
+ ihd = IT83XX_EC2I_IHD;
+ /* Disable EC access to the PNPCFG registers. */
+ IT83XX_EC2I_IBMAE &= ~(1 << 0);
+ /* Disable EC to I-Bus access. */
+ IT83XX_EC2I_IBCTL &= ~(1 << 0);
}
-
- /* Disable EC2I EC access */
- ec2i_ec_access_disable();
-
- return EC2I_WRITE_SUCCESS;
- } else {
- return EC2I_WRITE_ERROR;
}
+
+ return rv ? EC2I_READ_ERROR : (EC2I_READ_SUCCESS + ihd);
}
/* EC2I read */
enum ec2i_message ec2i_read(enum host_pnpcfg_index index)
{
- uint8_t data;
-
- /* bit1 : VCC power on */
- if (IT83XX_SWUC_SWCTL1 & 0x02) {
- /* Enable EC2I EC access */
- ec2i_ec_access_enable();
-
- /* Set indirect host I/O offset. (index port) */
- IT83XX_EC2I_IHIOA = 0;
- IT83XX_EC2I_IHD = index;
-
- /* Read the CWIB bit in IBCTL until it returns 0. */
- if (ec2i_check_status_bit(0x04)) {
- ec2i_ec_access_disable();
- return EC2I_READ_ERROR;
- }
-
- /* Set indirect host I/O offset. (data port) */
- IT83XX_EC2I_IHIOA = 1;
-
- /* This access is a read-action */
- IT83XX_EC2I_IBCTL |= 0x02;
-
- /* Read the CRIB bit in IBCTL until it returns 0. */
- if (ec2i_check_status_bit(0x02)) {
- ec2i_ec_access_disable();
- return EC2I_READ_ERROR;
- }
-
- /* Read the data from IHD register */
- data = IT83XX_EC2I_IHD;
-
- /* Disable EC2I EC access */
- ec2i_ec_access_disable();
+ enum ec2i_message ret = EC2I_READ_ERROR;
+ uint32_t int_mask = get_int_mask();
+
+ /* critical section with interrupts off */
+ interrupt_disable();
+ /* Set index */
+ if (ec2i_write_pnpcfg(EC2I_ACCESS_INDEX, index) == EC2I_WRITE_SUCCESS)
+ /* read data port */
+ ret = ec2i_read_pnpcfg(EC2I_ACCESS_DATA);
+ /* restore interrupts */
+ set_int_mask(int_mask);
+
+ return ret;
+}
- return EC2I_READ_SUCCESS + data;
- } else {
- return EC2I_READ_ERROR;
- }
+/* EC2I write */
+enum ec2i_message ec2i_write(enum host_pnpcfg_index index, uint8_t data)
+{
+ enum ec2i_message ret = EC2I_WRITE_ERROR;
+ uint32_t int_mask = get_int_mask();
+
+ /* critical section with interrupts off */
+ interrupt_disable();
+ /* Set index */
+ if (ec2i_write_pnpcfg(EC2I_ACCESS_INDEX, index) == EC2I_WRITE_SUCCESS)
+ /* Set data */
+ ret = ec2i_write_pnpcfg(EC2I_ACCESS_DATA, data);
+ /* restore interrupts */
+ set_int_mask(int_mask);
+
+ return ret;
}
static void pnpcfg_init(void)
{
int table;
+ /* Host access is disabled */
+ IT83XX_EC2I_LSIOHA |= 0x3;
+
for (table = 0x00; table < EC2I_SETTING_COUNT; table++) {
if (ec2i_write(pnpcfg_settings[table].index_port,
pnpcfg_settings[table].data_port) == EC2I_WRITE_ERROR)