summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortim <tim2.lin@ite.corp-partner.google.com>2019-03-28 14:08:15 +0800
committerchrome-bot <chrome-bot@chromium.org>2019-03-30 20:59:39 -0700
commit6a7c59affa6aba2af814a45f6f49908d22e2fa04 (patch)
tree92e5c77dda843e1e1eae9eabafdb2650d23870fa
parent101ef9c869d483307eb9325ec82a97f606e9caca (diff)
downloadchrome-ec-6a7c59affa6aba2af814a45f6f49908d22e2fa04.tar.gz
it83xx/i2cs: add i2c slave function
The I2C function of IT8320 is used as the slave. The slave channel A can support 16-byte FIFO for read and write data. The enhanced I2C channel D, E and F can support read and write 256-byte data by DMA mode. When master transmits data to slave, the interrupt signal will generate, and the data will be saved to buffer. BUG=none BRANCH=none TEST=none Change-Id: I167215352119ec11dfd96eb1f33abc1e2111dead Signed-off-by: tim <tim2.lin@ite.corp-partner.google.com> Reviewed-on: https://chromium-review.googlesource.com/1488273 Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com> Tested-by: Tim2 Lin <tim2.lin@ite.corp-partner.google.com> Reviewed-by: Jett Rink <jettrink@chromium.org> Reviewed-by: Vijay P Hiremath <vijay.p.hiremath@intel.com>
-rw-r--r--chip/it83xx/build.mk3
-rw-r--r--chip/it83xx/config_chip.h1
-rw-r--r--chip/it83xx/i2c.c6
-rw-r--r--chip/it83xx/i2c_slave.c320
-rw-r--r--chip/it83xx/intc.c30
-rw-r--r--chip/it83xx/intc.h3
-rw-r--r--chip/it83xx/registers.h46
-rw-r--r--core/nds32/ec.lds.S11
-rw-r--r--include/i2c_slave.h21
9 files changed, 427 insertions, 14 deletions
diff --git a/chip/it83xx/build.mk b/chip/it83xx/build.mk
index 365a993113..5ce2bc8397 100644
--- a/chip/it83xx/build.mk
+++ b/chip/it83xx/build.mk
@@ -24,4 +24,5 @@ chip-$(CONFIG_HOSTCMD_ESPI)+=espi.o
chip-$(CONFIG_SPI_MASTER)+=spi_master.o
chip-$(CONFIG_PECI)+=peci.o
chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o
-chip-$(CONFIG_I2C)+=i2c.o
+chip-$(CONFIG_I2C_MASTER)+=i2c.o
+chip-$(CONFIG_I2C_SLAVE)+=i2c_slave.o
diff --git a/chip/it83xx/config_chip.h b/chip/it83xx/config_chip.h
index 2e71fb3ef6..d0edfe6eb9 100644
--- a/chip/it83xx/config_chip.h
+++ b/chip/it83xx/config_chip.h
@@ -27,6 +27,7 @@
* There are three i2c enhanced ports.
*/
#define I2C_STANDARD_PORT_COUNT 3
+#define I2C_ENHANCED_PORT_COUNT 3
/****************************************************************************/
/* Memory mapping */
diff --git a/chip/it83xx/i2c.c b/chip/it83xx/i2c.c
index 56f805b9f6..48d13d5fdd 100644
--- a/chip/it83xx/i2c.c
+++ b/chip/it83xx/i2c.c
@@ -18,12 +18,6 @@
#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args)
-/*
- * The count number of the counter for 25 ms register.
- * The 25 ms register is calculated by (count number *1.024 kHz).
- */
-#define I2C_CLK_LOW_TIMEOUT 255 /* ~=249 ms */
-
/* Default maximum time we allow for an I2C transfer */
#define I2C_TIMEOUT_DEFAULT_US (100 * MSEC)
diff --git a/chip/it83xx/i2c_slave.c b/chip/it83xx/i2c_slave.c
new file mode 100644
index 0000000000..066ea6334a
--- /dev/null
+++ b/chip/it83xx/i2c_slave.c
@@ -0,0 +1,320 @@
+/* Copyright 2019 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.
+ */
+
+/* I2C module for Chrome EC */
+
+#include "clock.h"
+#include "compile_time_macros.h"
+#include "console.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "i2c_slave.h"
+#include "registers.h"
+#include <stddef.h>
+#include <string.h>
+#include "task.h"
+
+/* Console output macros */
+#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args)
+
+/* The size must be a power of 2 */
+#define I2C_MAX_BUFFER_SIZE 0x100
+#define I2C_SIZE_MASK (I2C_MAX_BUFFER_SIZE - 1)
+
+#define I2C_READ_MAXFIFO_DATA 16
+#define I2C_ENHANCED_CH_INTERVAL 0x80
+
+/* Store master to slave data of channel D, E, F by DMA */
+static uint8_t in_data[I2C_ENHANCED_PORT_COUNT][I2C_MAX_BUFFER_SIZE]
+ __attribute__((section(".h2ram.pool.i2cslv")));
+/* Store slave to master data of channel D, E, F by DMA */
+static uint8_t out_data[I2C_ENHANCED_PORT_COUNT][I2C_MAX_BUFFER_SIZE]
+ __attribute__((section(".h2ram.pool.i2cslv")));
+/* Store read and write data of channel A by FIFO mode */
+static uint8_t pbuffer[I2C_MAX_BUFFER_SIZE];
+
+static uint32_t w_index;
+static uint32_t r_index;
+static int wr_done[I2C_ENHANCED_PORT_COUNT];
+
+void buffer_index_reset(void)
+{
+ /* Reset write buffer index */
+ w_index = 0;
+ /* Reset read buffer index */
+ r_index = 0;
+}
+
+/* Data structure to define I2C slave control configuration. */
+struct i2c_slv_ctrl_t {
+ int irq; /* slave irq */
+ /* offset from base 0x00F03500 register; -1 means unused. */
+ int offset;
+ enum clock_gate_offsets clock_gate;
+ int dma_index;
+};
+
+/* I2C slave control */
+const struct i2c_slv_ctrl_t i2c_slv_ctrl[] = {
+ [IT83XX_I2C_CH_A] = {.irq = IT83XX_IRQ_SMB_A, .offset = -1,
+ .clock_gate = CGC_OFFSET_SMBA, .dma_index = -1},
+ [IT83XX_I2C_CH_D] = {.irq = IT83XX_IRQ_SMB_D, .offset = 0x180,
+ .clock_gate = CGC_OFFSET_SMBD, .dma_index = 0},
+ [IT83XX_I2C_CH_E] = {.irq = IT83XX_IRQ_SMB_E, .offset = 0x0,
+ .clock_gate = CGC_OFFSET_SMBE, .dma_index = 1},
+ [IT83XX_I2C_CH_F] = {.irq = IT83XX_IRQ_SMB_F, .offset = 0x80,
+ .clock_gate = CGC_OFFSET_SMBF, .dma_index = 2},
+};
+
+void i2c_slave_read_write_data(int port)
+{
+ int slv_status, i;
+
+ /* I2C slave channel A FIFO mode */
+ if (port < I2C_STANDARD_PORT_COUNT) {
+ int count;
+
+ slv_status = IT83XX_SMB_SLSTA;
+
+ /* bit0-4 : FIFO byte count */
+ count = IT83XX_SMB_SFFSTA & 0x1F;
+
+ /* Slave data register is waiting for read or write. */
+ if (slv_status & IT83XX_SMB_SDS) {
+ /* Master to read data */
+ if (slv_status & IT83XX_SMB_RCS) {
+ for (i = 0; i < I2C_READ_MAXFIFO_DATA; i++)
+ /* Return buffer data to master */
+ IT83XX_SMB_SLDA =
+ pbuffer[(i + r_index) & I2C_SIZE_MASK];
+
+ /* Index to next 16 bytes of read buffer */
+ r_index += I2C_READ_MAXFIFO_DATA;
+ }
+ /* Master to write data */
+ else {
+ /* FIFO Full */
+ if (IT83XX_SMB_SFFSTA & IT83XX_SMB_SFFFULL) {
+ for (i = 0; i < count; i++)
+ /* Get data from master to buffer */
+ pbuffer[(w_index + i) &
+ I2C_SIZE_MASK] = IT83XX_SMB_SLDA;
+ }
+
+ /* Index to next byte of write buffer */
+ w_index += count;
+ }
+ }
+ /* Stop condition, indicate stop condition detected. */
+ if (slv_status & IT83XX_SMB_SPDS) {
+ /* Read data less 16 bytes status */
+ if (slv_status & IT83XX_SMB_RCS) {
+ /* Disable FIFO mode to clear left count */
+ IT83XX_SMB_SFFCTL &= ~IT83XX_SMB_SAFE;
+
+ /* Slave A FIFO Enable */
+ IT83XX_SMB_SFFCTL |= IT83XX_SMB_SAFE;
+ }
+ /* Master to write data */
+ else {
+ for (i = 0; i < count; i++)
+ /* Get data from master to buffer */
+ pbuffer[(i + w_index) &
+ I2C_SIZE_MASK] = IT83XX_SMB_SLDA;
+ }
+
+ /* Reset read and write buffer index */
+ buffer_index_reset();
+ }
+ /* Slave time status, timeout status occurs. */
+ if (slv_status & IT83XX_SMB_STS) {
+ /* Reset read and write buffer index */
+ buffer_index_reset();
+ }
+
+ /* Write clear the slave status */
+ IT83XX_SMB_SLSTA = slv_status;
+ }
+ /* Enhanced I2C slave channel D, E, F DMA mode */
+ else {
+ int ch, idx;
+
+ /* Get enhanced i2c channel */
+ ch = i2c_slv_ctrl[port].offset / I2C_ENHANCED_CH_INTERVAL;
+
+ idx = i2c_slv_ctrl[port].dma_index;
+
+ /* Interrupt pending */
+ if (IT83XX_I2C_STR(ch) & IT83XX_I2C_INTPEND) {
+
+ slv_status = IT83XX_I2C_IRQ_ST(ch);
+
+ /* Master to read data */
+ if (slv_status & IT83XX_I2C_IDR_CLR) {
+ /*
+ * TODO(b:129360157): Return buffer data by
+ * "out_data" array.
+ * Ex: Write data to buffer from 0x00 to 0xFF
+ */
+ for (i = 0; i < I2C_MAX_BUFFER_SIZE; i++)
+ out_data[idx][i] = i;
+ }
+ /* Master to write data */
+ if (slv_status & IT83XX_I2C_IDW_CLR) {
+ /* Master to write data finish flag */
+ wr_done[idx] = 1;
+ }
+ /* Slave finish */
+ if (slv_status & IT83XX_I2C_P_CLR) {
+ if (wr_done[idx]) {
+ /*
+ * TODO(b:129360157): Handle master write
+ * data by "in_data" array.
+ */
+ CPRINTS("WData: %.*h\n",
+ I2C_MAX_BUFFER_SIZE, in_data[idx]);
+ wr_done[idx] = 0;
+ }
+ }
+
+ /* Write clear the slave status */
+ IT83XX_I2C_IRQ_ST(ch) = slv_status;
+ }
+
+ /* Hardware reset */
+ IT83XX_I2C_CTR(ch) |= IT83XX_I2C_HALT;
+ }
+}
+
+void i2c_slv_interrupt(int port)
+{
+ /* Slave to read and write fifo data */
+ i2c_slave_read_write_data(port);
+
+ /* Clear the interrupt status */
+ task_clear_pending_irq(i2c_slv_ctrl[port].irq);
+}
+
+void i2c_slave_enable(int port, uint8_t slv_addr)
+{
+
+ clock_enable_peripheral(i2c_slv_ctrl[port].clock_gate, 0, 0);
+
+ /* I2C slave channel A FIFO mode */
+ if (port < I2C_STANDARD_PORT_COUNT) {
+
+ /* This field defines the SMCLK0/1/2 clock/data low timeout. */
+ IT83XX_SMB_25MS = I2C_CLK_LOW_TIMEOUT;
+
+ /* bit0 : Slave A FIFO Enable */
+ IT83XX_SMB_SFFCTL |= IT83XX_SMB_SAFE;
+
+ /*
+ * bit1 : Slave interrupt enable.
+ * bit2 : SMCLK/SMDAT will be released if timeout.
+ * bit3 : Slave detect STOP condition interrupt enable.
+ */
+ IT83XX_SMB_SICR = 0x0E;
+
+ /* Slave address 1 */
+ IT83XX_SMB_RESLADR = slv_addr;
+
+ /* Write clear all slave status */
+ IT83XX_SMB_SLSTA = 0xE7;
+
+ /* bit5 : Enable the SMBus slave device */
+ IT83XX_SMB_HOCTL2(port) |= IT83XX_SMB_SLVEN;
+ }
+ /* Enhanced I2C slave channel D, E, F DMA mode */
+ else {
+ int ch, idx;
+
+ /* Get enhanced i2c channel */
+ ch = i2c_slv_ctrl[port].offset / I2C_ENHANCED_CH_INTERVAL;
+
+ idx = i2c_slv_ctrl[port].dma_index;
+
+ switch (port) {
+ case IT83XX_I2C_CH_D:
+ /* Enable I2C D channel */
+ IT83XX_GPIO_GRC2 |= (1 << 5);
+ break;
+ case IT83XX_I2C_CH_E:
+ /* Enable I2C E channel */
+ IT83XX_GCTRL_PMER1 |= (1 << 0);
+ break;
+ case IT83XX_I2C_CH_F:
+ /* Enable I2C F channel */
+ IT83XX_GCTRL_PMER1 |= (1 << 1);
+ break;
+ }
+
+ /* Software reset */
+ IT83XX_I2C_DHTR(ch) |= (1 << 7);
+ IT83XX_I2C_DHTR(ch) &= ~(1 << 7);
+
+ /* This field defines the SMCLK3/4/5 clock/data low timeout. */
+ IT83XX_I2C_TOR(ch) = I2C_CLK_LOW_TIMEOUT;
+
+ /* Bit stretching */
+ IT83XX_I2C_TOS(ch) |= IT83XX_I2C_CLK_STR;
+
+ /* Slave address(8-bit)*/
+ IT83XX_I2C_IDR(ch) = slv_addr << 1;
+
+ /* I2C interrupt enable and set acknowledge */
+ IT83XX_I2C_CTR(ch) = IT83XX_I2C_HALT |
+ IT83XX_I2C_INTEN | IT83XX_I2C_ACK;
+
+ /*
+ * bit3 : Slave ID write flag
+ * bit2 : Slave ID read flag
+ * bit1 : Slave received data flag
+ * bit0 : Slave finish
+ */
+ IT83XX_I2C_IRQ_ST(ch) = 0xFF;
+
+ /* Clear read and write data buffer of DMA */
+ memset(in_data[idx], 0, I2C_MAX_BUFFER_SIZE);
+ memset(out_data[idx], 0, I2C_MAX_BUFFER_SIZE);
+
+ /* DMA write target address register */
+ IT83XX_I2C_RAMHA(ch) = ((uint32_t)in_data[idx] >> 8) & 0x0F;
+ IT83XX_I2C_RAMLA(ch) = (uint32_t)in_data[idx] & 0xFF;
+
+ /* DMA read target address register */
+ IT83XX_I2C_RAMHA2(ch) = ((uint32_t)out_data[idx] >> 8) & 0x0F;
+ IT83XX_I2C_RAMLA2(ch) = (uint32_t)out_data[idx] & 0xFF;
+
+ /* I2C module enable and command queue mode */
+ IT83XX_I2C_CTR1(ch) = IT83XX_I2C_COMQ_EN |
+ IT83XX_I2C_MDL_EN;
+ }
+}
+
+static void i2c_slave_init(void)
+{
+ int i, p;
+
+ /* DLM 52k~56k size select enable */
+ IT83XX_GCTRL_MCCR2 |= (1 << 4);
+
+ /* Enable I2C Slave function */
+ for (i = 0; i < i2c_slvs_used; i++) {
+
+ /* I2c slave port mapping. */
+ p = i2c_slv_ports[i].port;
+
+ /* To enable slave ch[x] */
+ i2c_slave_enable(p, i2c_slv_ports[i].slave_adr);
+
+ /* Clear the interrupt status */
+ task_clear_pending_irq(i2c_slv_ctrl[p].irq);
+
+ /* enable i2c interrupt */
+ task_enable_irq(i2c_slv_ctrl[p].irq);
+ }
+}
+DECLARE_HOOK(HOOK_INIT, i2c_slave_init, HOOK_PRIO_INIT_I2C + 1);
diff --git a/chip/it83xx/intc.c b/chip/it83xx/intc.c
index 79d738e93c..033a65d87b 100644
--- a/chip/it83xx/intc.c
+++ b/chip/it83xx/intc.c
@@ -219,9 +219,14 @@ void intc_cpu_int_group_6(void)
int intc_group_6 = intc_get_ec_int();
switch (intc_group_6) {
-#ifdef CONFIG_I2C
+#if defined(CONFIG_I2C_MASTER) || defined(CONFIG_I2C_SLAVE)
case IT83XX_IRQ_SMB_A:
- i2c_interrupt(IT83XX_I2C_CH_A);
+#ifdef CONFIG_I2C_SLAVE
+ if (IT83XX_SMB_SFFCTL & IT83XX_SMB_SAFE)
+ i2c_slv_interrupt(IT83XX_I2C_CH_A);
+ else
+#endif
+ i2c_interrupt(IT83XX_I2C_CH_A);
break;
case IT83XX_IRQ_SMB_B:
@@ -233,15 +238,30 @@ void intc_cpu_int_group_6(void)
break;
case IT83XX_IRQ_SMB_D:
- i2c_interrupt(IT83XX_I2C_CH_D);
+#ifdef CONFIG_I2C_SLAVE
+ if (!(IT83XX_I2C_CTR(3) & IT83XX_I2C_MODE))
+ i2c_slv_interrupt(IT83XX_I2C_CH_D);
+ else
+#endif
+ i2c_interrupt(IT83XX_I2C_CH_D);
break;
case IT83XX_IRQ_SMB_E:
- i2c_interrupt(IT83XX_I2C_CH_E);
+#ifdef CONFIG_I2C_SLAVE
+ if (!(IT83XX_I2C_CTR(0) & IT83XX_I2C_MODE))
+ i2c_slv_interrupt(IT83XX_I2C_CH_E);
+ else
+#endif
+ i2c_interrupt(IT83XX_I2C_CH_E);
break;
case IT83XX_IRQ_SMB_F:
- i2c_interrupt(IT83XX_I2C_CH_F);
+#ifdef CONFIG_I2C_SLAVE
+ if (!(IT83XX_I2C_CTR(1) & IT83XX_I2C_MODE))
+ i2c_slv_interrupt(IT83XX_I2C_CH_F);
+ else
+#endif
+ i2c_interrupt(IT83XX_I2C_CH_F);
break;
#endif
default:
diff --git a/chip/it83xx/intc.h b/chip/it83xx/intc.h
index 2655f64b45..3a05e3d5a3 100644
--- a/chip/it83xx/intc.h
+++ b/chip/it83xx/intc.h
@@ -18,6 +18,9 @@ void lpcrst_interrupt(enum gpio_signal signal);
void peci_interrupt(void);
void adc_interrupt(void);
void i2c_interrupt(int port);
+#ifdef CONFIG_I2C_SLAVE
+void i2c_slv_interrupt(int port);
+#endif
void clock_sleep_mode_wakeup_isr(void);
int clock_ec_wake_from_sleep(void);
void __enter_hibernate(uint32_t seconds, uint32_t microseconds);
diff --git a/chip/it83xx/registers.h b/chip/it83xx/registers.h
index 6414ec9d16..aff0b7cea0 100644
--- a/chip/it83xx/registers.h
+++ b/chip/it83xx/registers.h
@@ -1065,6 +1065,12 @@ REG8(IT83XX_PMC_BASE + (ch > LPC_PM2 ? 5 : 8) + (ch << 4))
#define IT83XX_PECI_AWFCSV REG8(IT83XX_PECI_BASE+0x0D)
#define IT83XX_PECI_PADCTLR REG8(IT83XX_PECI_BASE+0x0E)
+/*
+ * The count number of the counter for 25 ms register.
+ * The 25 ms register is calculated by (count number *1.024 kHz).
+ */
+#define I2C_CLK_LOW_TIMEOUT 255 /* ~=249 ms */
+
/* SMBus/I2C Interface (SMB/I2C) */
#define IT83XX_SMB_BASE 0x00F01C00
@@ -1091,6 +1097,21 @@ REG8(IT83XX_PMC_BASE + (ch > LPC_PM2 ? 5 : 8) + (ch << 4))
#define IT83XX_SMB_PECERC(ch) REG8(IT83XX_SMB_BASE+0x47+(ch << 6))
#define IT83XX_SMB_SMBPCTL(ch) REG8(IT83XX_SMB_BASE+0x4A+(ch << 6))
#define IT83XX_SMB_HOCTL2(ch) REG8(IT83XX_SMB_BASE+0x50+(ch << 6))
+#define IT83XX_SMB_SLVEN (1 << 5)
+#define IT83XX_SMB_RESLADR REG8(IT83XX_SMB_BASE+0x48)
+#define IT83XX_SMB_SLDA REG8(IT83XX_SMB_BASE+0x49)
+#define IT83XX_SMB_SLSTA REG8(IT83XX_SMB_BASE+0x4B)
+#define IT83XX_SMB_SPDS (1 << 5)
+#define IT83XX_SMB_RCS (1 << 3)
+#define IT83XX_SMB_STS (1 << 2)
+#define IT83XX_SMB_SDS (1 << 1)
+#define IT83XX_SMB_SICR REG8(IT83XX_SMB_BASE+0x4C)
+#define IT83XX_SMB_RESLADR2 REG8(IT83XX_SMB_BASE+0x51)
+#define IT83XX_SMB_ENADDR2 (1 << 7)
+#define IT83XX_SMB_SFFCTL REG8(IT83XX_SMB_BASE+0x55)
+#define IT83XX_SMB_SAFE (1 << 0)
+#define IT83XX_SMB_SFFSTA REG8(IT83XX_SMB_BASE+0x56)
+#define IT83XX_SMB_SFFFULL (1 << 6)
/* BRAM */
#define IT83XX_BRAM_BASE 0x00F02200
@@ -1159,11 +1180,36 @@ enum bram_indices {
#define IT83XX_I2C_PSR(ch) REG8(IT83XX_I2C_BASE+0x01+(ch << 7))
#define IT83XX_I2C_HSPR(ch) REG8(IT83XX_I2C_BASE+0x02+(ch << 7))
#define IT83XX_I2C_STR(ch) REG8(IT83XX_I2C_BASE+0x03+(ch << 7))
+#define IT83XX_I2C_BB (1 << 5)
+#define IT83XX_I2C_TIME_OUT (1 << 3)
+#define IT83XX_I2C_RW (1 << 2)
+#define IT83XX_I2C_INTPEND (1 << 1)
#define IT83XX_I2C_DHTR(ch) REG8(IT83XX_I2C_BASE+0x04+(ch << 7))
#define IT83XX_I2C_TOR(ch) REG8(IT83XX_I2C_BASE+0x05+(ch << 7))
#define IT83XX_I2C_DTR(ch) REG8(IT83XX_I2C_BASE+0x08+(ch << 7))
#define IT83XX_I2C_CTR(ch) REG8(IT83XX_I2C_BASE+0x09+(ch << 7))
+#define IT83XX_I2C_INTEN (1 << 6)
+#define IT83XX_I2C_MODE (1 << 5)
+#define IT83XX_I2C_STARST (1 << 4)
+#define IT83XX_I2C_ACK (1 << 3)
+#define IT83XX_I2C_HALT (1 << 0)
#define IT83XX_I2C_CTR1(ch) REG8(IT83XX_I2C_BASE+0x0A+(ch << 7))
+#define IT83XX_I2C_COMQ_EN (1 << 7)
+#define IT83XX_I2C_MDL_EN (1 << 1)
+#define IT83XX_I2C_BYTE_CNT_L(ch) REG8(IT83XX_I2C_BASE+0x0C+(ch << 7))
+#define IT83XX_I2C_IRQ_ST(ch) REG8(IT83XX_I2C_BASE+0x0D+(ch << 7))
+#define IT83XX_I2C_IDW_CLR (1 << 3)
+#define IT83XX_I2C_IDR_CLR (1 << 2)
+#define IT83XX_I2C_SLVDATAFLG (1 << 1)
+#define IT83XX_I2C_P_CLR (1 << 0)
+#define IT83XX_I2C_IDR(ch) REG8(IT83XX_I2C_BASE+0x06+(ch << 7))
+#define IT83XX_I2C_TOS(ch) REG8(IT83XX_I2C_BASE+0x07+(ch << 7))
+#define IT83XX_I2C_CLK_STR (1 << 7)
+#define IT83XX_I2C_IDR2(ch) REG8(IT83XX_I2C_BASE+0x1F+(ch << 7))
+#define IT83XX_I2C_RAMHA(ch) REG8(IT83XX_I2C_BASE+0x23+(ch << 7))
+#define IT83XX_I2C_RAMLA(ch) REG8(IT83XX_I2C_BASE+0x24+(ch << 7))
+#define IT83XX_I2C_RAMHA2(ch) REG8(IT83XX_I2C_BASE+0x2B+(ch << 7))
+#define IT83XX_I2C_RAMLA2(ch) REG8(IT83XX_I2C_BASE+0x2C+(ch << 7))
enum i2c_channels {
IT83XX_I2C_CH_A, /* GPIO.B3/B4 */
diff --git a/core/nds32/ec.lds.S b/core/nds32/ec.lds.S
index 659270c5b4..bb115ed8df 100644
--- a/core/nds32/ec.lds.S
+++ b/core/nds32/ec.lds.S
@@ -21,7 +21,7 @@ MEMORY
{
FLASH (rx) : ORIGIN = FW_OFF(SECTION), LENGTH = FW_SIZE(SECTION)
IRAM (rw) : ORIGIN = CONFIG_RAM_BASE, LENGTH = CONFIG_RAM_SIZE
-#ifdef CONFIG_HOSTCMD_X86
+#if defined(CONFIG_HOSTCMD_X86) || defined(CONFIG_I2C_SLAVE)
H2RAM (rw) : ORIGIN = CONFIG_H2RAM_BASE, LENGTH = CONFIG_H2RAM_SIZE
#endif
}
@@ -237,14 +237,21 @@ SECTIONS
__image_size = LOADADDR(.data) + SIZEOF(.data) - FW_OFF(SECTION);
-#ifdef CONFIG_HOSTCMD_X86
+#if defined(CONFIG_HOSTCMD_X86) || defined(CONFIG_I2C_SLAVE)
.h2ram (NOLOAD) : {
. += CONFIG_H2RAM_HOST_LPC_IO_BASE;
*(.h2ram.pool.hostcmd)
. = ALIGN(256);
*(.h2ram.pool.acpiec)
+#ifdef CONFIG_I2C_SLAVE
+ . = ALIGN(256);
+ *(.h2ram.pool.i2cslv)
+#endif
+ __h2ram_end = .;
} > H2RAM
#endif
+ ASSERT((__h2ram_end) <= (CONFIG_H2RAM_BASE + CONFIG_H2RAM_SIZE),
+ "Not enough space for h2ram section.")
#if !(defined(SECTION_IS_RO) && defined(CONFIG_FLASH))
/DISCARD/ : {
diff --git a/include/i2c_slave.h b/include/i2c_slave.h
new file mode 100644
index 0000000000..3145d4679b
--- /dev/null
+++ b/include/i2c_slave.h
@@ -0,0 +1,21 @@
+/* Copyright 2019 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.
+ */
+
+/* I2C slave interface for Chrome EC */
+
+#ifndef __CROS_EC_I2CSLV_H
+#define __CROS_EC_I2CSLV_H
+
+/* Data structure to define I2C slave port configuration. */
+struct i2c_slv_port_t {
+ const char *name; /* Port name */
+ int port; /* Port */
+ uint8_t slave_adr; /* slave address(7-bit without R/W) */
+};
+
+extern const struct i2c_slv_port_t i2c_slv_ports[];
+extern const unsigned int i2c_slvs_used;
+
+#endif /* __CROS_EC_I2CSLV_H */