diff options
author | Ting Shen <phoenixshen@google.com> | 2019-12-16 17:44:57 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-01-17 12:31:42 +0000 |
commit | 45427c38df049e4506bf42e17d1ccfd303e1380c (patch) | |
tree | d0ceab265367bcfb1e9ebc2d47222749710fe127 /chip | |
parent | 166c22d05730de961b894d954116439d6ff219e7 (diff) | |
download | chrome-ec-45427c38df049e4506bf42e17d1ccfd303e1380c.tar.gz |
i2c: Support changing I2C bus speed at runtime
Add a i2c_set_freq function and let chip drivers add their underlying
implementation.
Also implemented on stm32f0.
BUG=b:143677811,b:78189419
TEST=1) make
2) On kodama, call i2c_set_freq(1, 100) during init.
verify the bus is configured to 100kbps in kodama rev 1
BRANCH=kukui
Change-Id: Iebb5baacf098b3e5649a4bd8ca14acf097d39693
Signed-off-by: Ting Shen <phoenixshen@google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1969245
Reviewed-by: Matthew Blecker <matthewb@chromium.org>
Reviewed-by: Jett Rink <jettrink@chromium.org>
Commit-Queue: Ting Shen <phoenixshen@chromium.org>
Tested-by: Ting Shen <phoenixshen@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r-- | chip/host/build.mk | 5 | ||||
-rw-r--r-- | chip/host/i2c.c | 21 | ||||
-rw-r--r-- | chip/stm32/i2c-stm32f0.c | 47 | ||||
-rw-r--r-- | chip/stm32/i2c-stm32f0.h | 15 |
4 files changed, 58 insertions, 30 deletions
diff --git a/chip/host/build.mk b/chip/host/build.mk index f57fe85502..9d77937776 100644 --- a/chip/host/build.mk +++ b/chip/host/build.mk @@ -8,8 +8,9 @@ CORE:=host -chip-y=system.o gpio.o uart.o persistence.o flash.o lpc.o reboot.o i2c.o \ +chip-y=system.o gpio.o uart.o persistence.o flash.o lpc.o reboot.o \ clock.o spi_master.o trng.o + ifndef CONFIG_KEYBOARD_NOT_RAW chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o endif @@ -21,6 +22,8 @@ dirs-y += chip/g/dcrypto endif dirs-y += chip/host/dcrypto +chip-$(CONFIG_I2C)+= i2c.o + chip-$(CONFIG_DCRYPTO)+= dcrypto/aes.o chip-$(CONFIG_DCRYPTO)+= dcrypto/app_cipher.o chip-$(CONFIG_DCRYPTO)+= dcrypto/app_key.o diff --git a/chip/host/i2c.c b/chip/host/i2c.c index 5b863c1d41..f474c38ef1 100644 --- a/chip/host/i2c.c +++ b/chip/host/i2c.c @@ -7,6 +7,7 @@ #include "hooks.h" #include "i2c.h" +#include "i2c_private.h" #include "link_defs.h" #include "test_util.h" @@ -95,6 +96,26 @@ int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, return EC_ERROR_UNKNOWN; } +int chip_i2c_set_freq(int port, enum i2c_freq freq) +{ + return EC_ERROR_UNIMPLEMENTED; +} + +enum i2c_freq chip_i2c_get_freq(int port) +{ + switch (i2c_ports[port].kbps) { + case 1000: + return I2C_FREQ_1000KHZ; + case 400: + return I2C_FREQ_400KHZ; + case 100: + return I2C_FREQ_100KHZ; + } + + /* fallback to 100k */ + return I2C_FREQ_100KHZ; +} + int i2c_raw_get_scl(int port) { return 1; diff --git a/chip/stm32/i2c-stm32f0.c b/chip/stm32/i2c-stm32f0.c index 21cfe3e684..f722de2b54 100644 --- a/chip/stm32/i2c-stm32f0.c +++ b/chip/stm32/i2c-stm32f0.c @@ -12,7 +12,7 @@ #include "host_command.h" #include "hwtimer.h" #include "i2c.h" -#include "i2c-stm32f0.h" +#include "i2c_private.h" #include "registers.h" #include "system.h" #include "task.h" @@ -113,22 +113,39 @@ static const uint32_t timingr_regs[I2C_CLK_SRC_COUNT][I2C_FREQ_COUNT] = { }, }; -static void i2c_set_freq_port(const struct i2c_port_t *p, - enum stm32_i2c_clk_src src, - enum i2c_freq freq) +int chip_i2c_set_freq(int port, enum i2c_freq freq) { - int port = p->port; - const uint32_t *regs = timingr_regs[src]; + enum stm32_i2c_clk_src src = I2C_CLK_SRC_48MHZ; + +#if defined(CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS) && \ + defined(CONFIG_LOW_POWER_IDLE) && \ + (I2C_PORT_EC == STM32_I2C1_PORT) + if (port == STM32_I2C1_PORT) { + /* + * Use HSI (8MHz) for i2c clock. This allows smooth wakeup + * from STOP mode since HSI is only clock running immediately + * upon exit from STOP mode. + */ + src = I2C_CLK_SRC_8MHZ; + } +#endif /* Disable port */ STM32_I2C_CR1(port) = 0; STM32_I2C_CR2(port) = 0; /* Set clock frequency */ - STM32_I2C_TIMINGR(port) = regs[freq]; + STM32_I2C_TIMINGR(port) = timingr_regs[src][freq]; /* Enable port */ STM32_I2C_CR1(port) = STM32_I2C_CR1_PE; pdata[port].freq = freq; + + return EC_SUCCESS; +} + +enum i2c_freq chip_i2c_get_freq(int port) +{ + return pdata[port].freq; } /** @@ -136,10 +153,10 @@ static void i2c_set_freq_port(const struct i2c_port_t *p, * * @param p the I2c port */ -void stm32f0_i2c_init_port(const struct i2c_port_t *p) +static int i2c_init_port(const struct i2c_port_t *p) { int port = p->port; - enum stm32_i2c_clk_src src = I2C_CLK_SRC_48MHZ; + int ret = EC_SUCCESS; enum i2c_freq freq; /* Enable clocks to I2C modules if necessary */ @@ -148,15 +165,14 @@ void stm32f0_i2c_init_port(const struct i2c_port_t *p) if (port == STM32_I2C1_PORT) { #if defined(CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS) && \ -defined(CONFIG_LOW_POWER_IDLE) && \ -(I2C_PORT_EC == STM32_I2C1_PORT) + defined(CONFIG_LOW_POWER_IDLE) && \ + (I2C_PORT_EC == STM32_I2C1_PORT) /* * Use HSI (8MHz) for i2c clock. This allows smooth wakeup * from STOP mode since HSI is only clock running immediately * upon exit from STOP mode. */ STM32_RCC_CFGR3 &= ~0x10; - src = I2C_CLK_SRC_8MHZ; #else /* Use SYSCLK for i2c clock. */ STM32_RCC_CFGR3 |= 0x10; @@ -180,13 +196,16 @@ defined(CONFIG_LOW_POWER_IDLE) && \ default: /* unknown speed, defaults to 100kBps */ CPRINTS("I2C bad speed %d kBps", p->kbps); freq = I2C_FREQ_100KHZ; + ret = EC_ERROR_INVAL; } /* Set up initial bus frequencies */ - i2c_set_freq_port(p, src, freq); + chip_i2c_set_freq(p->port, freq); /* Set up default timeout */ i2c_set_timeout(port, 0); + + return ret; } /*****************************************************************************/ @@ -604,7 +623,7 @@ void i2c_init(void) int i; for (i = 0; i < i2c_ports_used; i++, p++) - stm32f0_i2c_init_port(p); + i2c_init_port(p); #ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR_FLAGS STM32_I2C_CR1(I2C_PORT_EC) |= STM32_I2C_CR1_RXIE | STM32_I2C_CR1_ERRIE diff --git a/chip/stm32/i2c-stm32f0.h b/chip/stm32/i2c-stm32f0.h deleted file mode 100644 index 8e694759e9..0000000000 --- a/chip/stm32/i2c-stm32f0.h +++ /dev/null @@ -1,15 +0,0 @@ -/* 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. - */ -#ifndef __CROS_EC_I2C_STM32F0_H -#define __CROS_EC_I2C_STM32F0_H - -/** - * Initialize on the specified I2C port. - * - * @param p the I2c port - */ -void stm32f0_i2c_init_port(const struct i2c_port_t *p); - -#endif |