summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2015-10-29 10:47:21 -0700
committerchrome-bot <chrome-bot@chromium.org>2015-10-30 14:33:29 -0700
commit813e56e10af48dc010dc629cb6d0c37efcb995dd (patch)
tree0fc55e5773da06559f385a84bee488245f013d68
parente4d78afafbf5170d1ceb60f1b0043a70c3449970 (diff)
downloadchrome-ec-813e56e10af48dc010dc629cb6d0c37efcb995dd.tar.gz
stm32f0: i2c: Set timing register values by port clock source
I2C1 may be clocked by HSI or SCLK. I2C2 is always clocked by PCLK. Therefore, apply different timing register values according to the selected clock source for a port. BUG=chrome-os-partner:46188 BRANCH=None TEST=Manual on glados_pd. Verify slave i2c communication is functional. Change-Id: Icd2306d25d5863b0fc3379e46885a227efb23cca Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/309781 Commit-Ready: Gwendal Grignou <gwendal@chromium.org> Tested-by: Shawn N <shawnn@chromium.org> Reviewed-by: Gwendal Grignou <gwendal@chromium.org>
-rw-r--r--chip/stm32/i2c-stm32f0.c76
-rw-r--r--include/i2c.h11
2 files changed, 57 insertions, 30 deletions
diff --git a/chip/stm32/i2c-stm32f0.c b/chip/stm32/i2c-stm32f0.c
index c06f0d2619..565006596f 100644
--- a/chip/stm32/i2c-stm32f0.c
+++ b/chip/stm32/i2c-stm32f0.c
@@ -81,42 +81,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
+/* 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)
+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;
}
@@ -129,12 +126,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)
@@ -144,6 +143,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;
@@ -153,8 +153,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);
/* Set up default timeout */
i2c_set_timeout(port, 0);
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 */