summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
authorTing Shen <phoenixshen@google.com>2019-12-16 17:44:57 +0800
committerCommit Bot <commit-bot@chromium.org>2020-01-17 12:31:42 +0000
commit45427c38df049e4506bf42e17d1ccfd303e1380c (patch)
treed0ceab265367bcfb1e9ebc2d47222749710fe127 /chip
parent166c22d05730de961b894d954116439d6ff219e7 (diff)
downloadchrome-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.mk5
-rw-r--r--chip/host/i2c.c21
-rw-r--r--chip/stm32/i2c-stm32f0.c47
-rw-r--r--chip/stm32/i2c-stm32f0.h15
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