summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip/stm32/i2c-stm32f0.c78
-rw-r--r--include/i2c.h11
2 files changed, 58 insertions, 31 deletions
diff --git a/chip/stm32/i2c-stm32f0.c b/chip/stm32/i2c-stm32f0.c
index 14b52770c8..860a0a8c14 100644
--- a/chip/stm32/i2c-stm32f0.c
+++ b/chip/stm32/i2c-stm32f0.c
@@ -68,42 +68,39 @@ static int wait_isr(int port, int mask)
return EC_ERROR_TIMEOUT;
}
-#if defined(CONFIG_HOSTCMD_I2C_SLAVE_ADDR) && \
-defined(CONFIG_LOW_POWER_IDLE) && \
-(I2C_PORT_EC == STM32_I2C1_PORT)
-/* 8MHz i2cclk register settings */
-#define STM32_I2C_TIMINGR_1000MHZ 0x00100306
-#define STM32_I2C_TIMINGR_400MHZ 0x00310309
-#define STM32_I2C_TIMINGR_100MHZ 0x10420f13
-#else
-/* 48MHz i2cclk register settings */
-#define STM32_I2C_TIMINGR_1000MHZ 0x50100103
-#define STM32_I2C_TIMINGR_400MHZ 0x50330309
-#define STM32_I2C_TIMINGR_100MHZ 0xB0421214
-#endif
-
-static void i2c_set_freq_port(const struct i2c_port_t *p)
+/* Supported i2c input clocks */
+enum stm32_i2c_clk_src {
+ I2C_CLK_SRC_48MHZ = 0,
+ I2C_CLK_SRC_8MHZ = 1,
+ I2C_CLK_SRC_COUNT,
+};
+
+/* timingr register values for supported input clks / i2c clk rates */
+static const uint32_t timingr_regs[I2C_CLK_SRC_COUNT][I2C_FREQ_COUNT] = {
+ [I2C_CLK_SRC_48MHZ] = {
+ [I2C_FREQ_1000KHZ] = 0x00100306,
+ [I2C_FREQ_400KHZ] = 0x00310309,
+ [I2C_FREQ_100KHZ] = 0x10420f13,
+ },
+ [I2C_CLK_SRC_8MHZ] = {
+ [I2C_FREQ_1000KHZ] = 0x50100103,
+ [I2C_FREQ_400KHZ] = 0x50330309,
+ [I2C_FREQ_100KHZ] = 0xB0421214,
+ },
+};
+
+static void i2c_set_freq_port(const struct i2c_port_t *p,
+ enum stm32_i2c_clk_src src,
+ enum i2c_freq freq)
{
int port = p->port;
+ const uint32_t *regs = timingr_regs[src];
/* Disable port */
STM32_I2C_CR1(port) = 0;
STM32_I2C_CR2(port) = 0;
/* Set clock frequency */
- switch (p->kbps) {
- case 1000:
- STM32_I2C_TIMINGR(port) = STM32_I2C_TIMINGR_1000MHZ;
- break;
- case 400:
- STM32_I2C_TIMINGR(port) = STM32_I2C_TIMINGR_400MHZ;
- break;
- case 100:
- STM32_I2C_TIMINGR(port) = STM32_I2C_TIMINGR_100MHZ;
- break;
- default: /* unknown speed, defaults to 100kBps */
- CPRINTS("I2C bad speed %d kBps", p->kbps);
- STM32_I2C_TIMINGR(port) = STM32_I2C_TIMINGR_100MHZ;
- }
+ STM32_I2C_TIMINGR(port) = regs[freq];
/* Enable port */
STM32_I2C_CR1(port) = STM32_I2C_CR1_PE;
}
@@ -116,12 +113,14 @@ static void i2c_set_freq_port(const struct i2c_port_t *p)
static void i2c_init_port(const struct i2c_port_t *p)
{
int port = p->port;
+ enum stm32_i2c_clk_src src = I2C_CLK_SRC_48MHZ;
+ enum i2c_freq freq;
/* Enable clocks to I2C modules if necessary */
if (!(STM32_RCC_APB1ENR & (1 << (21 + port))))
STM32_RCC_APB1ENR |= 1 << (21 + port);
- if (port == 0) {
+ if (port == STM32_I2C1_PORT) {
#if defined(CONFIG_HOSTCMD_I2C_SLAVE_ADDR) && \
defined(CONFIG_LOW_POWER_IDLE) && \
(I2C_PORT_EC == STM32_I2C1_PORT)
@@ -131,6 +130,7 @@ defined(CONFIG_LOW_POWER_IDLE) && \
* upon exit from STOP mode.
*/
STM32_RCC_CFGR3 &= ~0x10;
+ src = I2C_CLK_SRC_8MHZ;
#else
/* Use SYSCLK for i2c clock. */
STM32_RCC_CFGR3 |= 0x10;
@@ -140,8 +140,24 @@ defined(CONFIG_LOW_POWER_IDLE) && \
/* Configure GPIOs */
gpio_config_module(MODULE_I2C, 1);
+ /* Set clock frequency */
+ switch (p->kbps) {
+ case 1000:
+ freq = I2C_FREQ_1000KHZ;
+ break;
+ case 400:
+ freq = I2C_FREQ_400KHZ;
+ break;
+ case 100:
+ freq = I2C_FREQ_100KHZ;
+ break;
+ default: /* unknown speed, defaults to 100kBps */
+ CPRINTS("I2C bad speed %d kBps", p->kbps);
+ freq = I2C_FREQ_100KHZ;
+ }
+
/* Set up initial bus frequencies */
- i2c_set_freq_port(p);
+ i2c_set_freq_port(p, src, freq);
}
/*****************************************************************************/
diff --git a/include/i2c.h b/include/i2c.h
index 674dd84e80..fdda5a0187 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -13,6 +13,17 @@
/* Flags for slave address field, in addition to the 8-bit address */
#define I2C_FLAG_BIG_ENDIAN 0x100 /* 16 byte values are MSB-first */
+/*
+ * Supported I2C CLK frequencies.
+ * TODO(crbug.com/549286): Use this enum in i2c_port_t.
+ */
+enum i2c_freq {
+ I2C_FREQ_1000KHZ = 0,
+ I2C_FREQ_400KHZ = 1,
+ I2C_FREQ_100KHZ = 2,
+ I2C_FREQ_COUNT,
+};
+
/* Data structure to define I2C port configuration. */
struct i2c_port_t {
const char *name; /* Port name */