summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2015-10-29 10:47:21 -0700
committerChromeOS bot <3su6n15k.default@developer.gserviceaccount.com>2015-11-03 18:08:08 +0000
commit764c5ce9c2ade0f6228815139e8a560d193e5016 (patch)
tree924dcd99de2982fb2fe2fcc6a5b5811e9db62e6a
parent0f250d89b91db41b9045053e8e1417a99fd6dfeb (diff)
downloadchrome-ec-764c5ce9c2ade0f6228815139e8a560d193e5016.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> (cherry picked from commit 813e56e10af48dc010dc629cb6d0c37efcb995dd) Signed-off-by: Gwendal Grignou <gwendal@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/309964
-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 */