From 1ff07ae859b5d319ce220e94cf77a3fc6a7aeae4 Mon Sep 17 00:00:00 2001 From: Stoyan Bogdanov Date: Tue, 6 Aug 2024 16:27:15 +0300 Subject: [PATCH 1/4] drivers: i2c: Add support for cc23x0 I2C Add support for I2C to cc23x0 SoC. Only controller mode is implemented. Signed-off-by: Stoyan Bogdanov --- drivers/i2c/CMakeLists.txt | 1 + drivers/i2c/Kconfig | 1 + drivers/i2c/Kconfig.cc23x0 | 11 ++ drivers/i2c/i2c_cc23x0.c | 297 ++++++++++++++++++++++++++++ dts/bindings/i2c/ti,cc23x0-i2c.yaml | 22 +++ 5 files changed, 332 insertions(+) create mode 100644 drivers/i2c/Kconfig.cc23x0 create mode 100644 drivers/i2c/i2c_cc23x0.c create mode 100644 dts/bindings/i2c/ti,cc23x0-i2c.yaml diff --git a/drivers/i2c/CMakeLists.txt b/drivers/i2c/CMakeLists.txt index 6419417db1c8..c3bd3f04c0eb 100644 --- a/drivers/i2c/CMakeLists.txt +++ b/drivers/i2c/CMakeLists.txt @@ -26,6 +26,7 @@ add_subdirectory_ifdef(CONFIG_I2C_TARGET target) zephyr_library_sources_ifdef(CONFIG_I2C_AMBIQ i2c_ambiq.c) zephyr_library_sources_ifdef(CONFIG_I2C_ANDES_ATCIIC100 i2c_andes_atciic100.c) zephyr_library_sources_ifdef(CONFIG_I2C_CC13XX_CC26XX i2c_cc13xx_cc26xx.c) +zephyr_library_sources_ifdef(CONFIG_I2C_CC23X0 i2c_cc23x0.c) zephyr_library_sources_ifdef(CONFIG_I2C_CC32XX i2c_cc32xx.c) zephyr_library_sources_ifdef(CONFIG_I2C_DW i2c_dw.c) zephyr_library_sources_ifdef(CONFIG_I2C_ENE_KB1200 i2c_ene_kb1200.c) diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index c1180acf51d6..e2bed799334f 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -123,6 +123,7 @@ source "drivers/i2c/Kconfig.andes_atciic100" source "drivers/i2c/Kconfig.b91" source "drivers/i2c/Kconfig.bcm_iproc" source "drivers/i2c/Kconfig.cc13xx_cc26xx" +source "drivers/i2c/Kconfig.cc23x0" source "drivers/i2c/Kconfig.dw" source "drivers/i2c/Kconfig.ene" source "drivers/i2c/Kconfig.esp32" diff --git a/drivers/i2c/Kconfig.cc23x0 b/drivers/i2c/Kconfig.cc23x0 new file mode 100644 index 000000000000..19ae4bb4e8aa --- /dev/null +++ b/drivers/i2c/Kconfig.cc23x0 @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Baylibre, SAS +# +# SPDX-License-Identifier: Apache-2.0 + +config I2C_CC23X0 + bool "TI SimpleLink CC23x0 I2C driver" + default y + depends on DT_HAS_TI_CC23X0_I2C_ENABLED + select PINCTRL + help + Enable support for I2C on the TI SimpleLink CC23x0 series. diff --git a/drivers/i2c/i2c_cc23x0.c b/drivers/i2c/i2c_cc23x0.c new file mode 100644 index 000000000000..50668a9cbfe1 --- /dev/null +++ b/drivers/i2c/i2c_cc23x0.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2024 Baylibre, SAS + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_cc23x0_i2c + +#include +#include +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL + +#include + +LOG_MODULE_REGISTER(i2c_cc23x0); + +#include +#include + +#include "i2c-priv.h" + +#define I2C_MASTER_ERR_NONE 0 + +struct i2c_cc23x0_data { + struct k_sem lock; + struct k_sem complete; + volatile uint32_t error; +}; + +struct i2c_cc23x0_config { + uint32_t base; + const struct pinctrl_dev_config *pcfg; +}; + +static int i2c_cc23x0_transmit(const struct device *dev, const uint8_t *buf, uint32_t len, + uint16_t addr) +{ + const struct i2c_cc23x0_config *config = dev->config; + const uint32_t base = config->base; + struct i2c_cc23x0_data *data = dev->data; + + /* Sending address without data is not supported */ + if (len == 0) { + return -EIO; + } + + I2CControllerSetTargetAddr(base, addr, false); + + /* Single transmission */ + if (len == 1) { + I2CControllerPutData(base, *buf); + I2CControllerCommand(base, I2C_CONTROLLER_CMD_SINGLE_SEND); + k_sem_take(&data->complete, K_FOREVER); + return data->error == I2C_MASTER_ERR_NONE ? 0 : -EIO; + } + + /* Burst transmission */ + I2CControllerPutData(base, buf[0]); + I2CControllerCommand(base, I2C_CONTROLLER_CMD_BURST_SEND_START); + k_sem_take(&data->complete, K_FOREVER); + + if (data->error != I2C_MASTER_ERR_NONE) { + goto send_error_stop; + } + + for (int i = 1; i < len - 1; i++) { + I2CControllerPutData(base, buf[i]); + I2CControllerCommand(base, I2C_CONTROLLER_CMD_BURST_SEND_CONT); + k_sem_take(&data->complete, K_FOREVER); + + if (data->error != I2C_MASTER_ERR_NONE) { + goto send_error_stop; + } + } + + I2CControllerPutData(base, buf[len - 1]); + I2CControllerCommand(base, I2C_CONTROLLER_CMD_BURST_SEND_FINISH); + k_sem_take(&data->complete, K_FOREVER); + + if (data->error != I2C_MASTER_ERR_NONE) { + return -EIO; + } + + return 0; + +send_error_stop: + I2CControllerCommand(base, I2C_CONTROLLER_CMD_BURST_SEND_ERROR_STOP); + return -EIO; +} + +static int i2c_cc23x0_receive(const struct device *dev, uint8_t *buf, uint32_t len, uint16_t addr) +{ + const struct i2c_cc23x0_config *config = dev->config; + const uint32_t base = config->base; + struct i2c_cc23x0_data *data = dev->data; + + /* Sending address without data is not supported */ + if (len == 0) { + return -EIO; + } + I2CControllerSetTargetAddr(base, addr, true); + + /* Single receive */ + if (len == 1) { + I2CControllerCommand(base, I2C_CONTROLLER_CMD_SINGLE_RECEIVE); + k_sem_take(&data->complete, K_FOREVER); + + if (data->error != I2C_MASTER_ERR_NONE) { + return -EIO; + } + + *buf = I2CControllerGetData(base); + return 0; + } + + /* Burst receive */ + I2CControllerCommand(base, I2C_CONTROLLER_CMD_BURST_RECEIVE_START); + k_sem_take(&data->complete, K_FOREVER); + + if (data->error != I2C_MASTER_ERR_NONE) { + goto recv_error_stop; + } + + buf[0] = I2CControllerGetData(base); + + for (int i = 1; i < len - 1; i++) { + I2CControllerCommand(base, I2C_CONTROLLER_CMD_BURST_RECEIVE_CONT); + k_sem_take(&data->complete, K_FOREVER); + + if (data->error != I2C_MASTER_ERR_NONE) { + goto recv_error_stop; + } + + buf[i] = I2CControllerGetData(base); + } + + I2CControllerCommand(base, I2C_CONTROLLER_CMD_BURST_RECEIVE_FINISH); + k_sem_take(&data->complete, K_FOREVER); + + if (data->error != I2C_MASTER_ERR_NONE) { + return -EIO; + } + + buf[len - 1] = I2CControllerGetData(base); + + return 0; + +recv_error_stop: + I2CControllerCommand(base, I2C_CONTROLLER_CMD_BURST_RECEIVE_ERROR_STOP); + return -EIO; +} + +static int i2c_cc23x0_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, + uint16_t addr) +{ + struct i2c_cc23x0_data *data = dev->data; + int ret = 0; + + if (num_msgs == 0) { + return 0; + } + + k_sem_take(&data->lock, K_FOREVER); + + for (int i = 0; i < num_msgs; i++) { + /* Not supported by hardware */ + if (msgs[i].flags & I2C_MSG_ADDR_10_BITS) { + ret = -EIO; + break; + } + + if ((msgs[i].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) { + ret = i2c_cc23x0_transmit(dev, msgs[i].buf, msgs[i].len, addr); + } else { + ret = i2c_cc23x0_receive(dev, msgs[i].buf, msgs[i].len, addr); + } + + if (ret) { + break; + } + } + k_sem_give(&data->lock); + + return ret; +} + +#define CPU_FREQ DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency) +static int i2c_cc23x0_configure(const struct device *dev, uint32_t dev_config) +{ + const struct i2c_cc23x0_config *config = dev->config; + bool fast; + + switch (I2C_SPEED_GET(dev_config)) { + case I2C_SPEED_STANDARD: + fast = false; + break; + case I2C_SPEED_FAST: + fast = true; + break; + default: + LOG_ERR("Unsupported speed"); + return -EIO; + } + + /* Support for slave mode has not been implemented */ + if (!(dev_config & I2C_MODE_CONTROLLER)) { + LOG_ERR("Slave mode is not supported"); + return -EIO; + } + + /* This is deprecated and could be ignored in the future */ + if (dev_config & I2C_ADDR_10_BITS) { + LOG_ERR("10-bit addressing mode is not supported"); + return -EIO; + } + + /* Enables and configures I2C master */ + I2CControllerInitExpClk(config->base, fast); + + CLKCTLEnable(CLKCTL_BASE, CLKCTL_I2C0); + + return 0; +} + +static void i2c_cc23x0_isr(const struct device *dev) +{ + const struct i2c_cc23x0_config *config = dev->config; + struct i2c_cc23x0_data *data = dev->data; + const uint32_t base = config->base; + + if (I2CControllerIntStatus(base, true)) { + I2CControllerClearInt(base); + + data->error = I2CControllerError(base); + + k_sem_give(&data->complete); + } +} + +static const struct i2c_driver_api i2c_cc23x0_driver_api = {.configure = i2c_cc23x0_configure, + .transfer = i2c_cc23x0_transfer}; + +#define I2C_CC23X0_INIT_FUNC(id) \ + static int i2c_cc23x0_init##id(const struct device *dev) \ + { \ + const struct i2c_cc23x0_config *config = dev->config; \ + uint32_t cfg; \ + int err; \ + \ + CLKCTLEnable(CLKCTL_BASE, CLKCTL_I2C0); \ + \ + IRQ_CONNECT(DT_INST_IRQN(id), DT_INST_IRQ(id, priority), i2c_cc23x0_isr, \ + DEVICE_DT_INST_GET(id), 0); \ + \ + irq_enable(DT_INST_IRQN(id)); \ + \ + err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); \ + if (err < 0) { \ + LOG_ERR("Failed to configure pinctrl state\n"); \ + return err; \ + } \ + \ + cfg = i2c_map_dt_bitrate(DT_INST_PROP(id, clock_frequency)); \ + err = i2c_cc23x0_configure(dev, cfg | I2C_MODE_CONTROLLER); \ + if (err) { \ + LOG_ERR("Failed to configure\n"); \ + return err; \ + } \ + \ + I2CControllerEnableInt(config->base); \ + return 0; \ + } + +#define CC23X0_I2C(id) \ + I2C_CC23X0_INIT_FUNC(id); \ + PINCTRL_DT_INST_DEFINE(id); \ + \ + static const struct i2c_cc23x0_config i2c_cc23x0_##id##_config = { \ + .base = DT_INST_REG_ADDR(id), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \ + }; \ + \ + static struct i2c_cc23x0_data i2c_cc23x0_##id##_data = { \ + .lock = Z_SEM_INITIALIZER(i2c_cc23x0_##id##_data.lock, 1, 1), \ + .complete = Z_SEM_INITIALIZER(i2c_cc23x0_##id##_data.complete, 0, 1), \ + .error = I2C_MASTER_ERR_NONE}; \ + \ + I2C_DEVICE_DT_INST_DEFINE(id, i2c_cc23x0_init##id, NULL, &i2c_cc23x0_##id##_data, \ + &i2c_cc23x0_##id##_config, POST_KERNEL, \ + CONFIG_I2C_INIT_PRIORITY, &i2c_cc23x0_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(CC23X0_I2C); diff --git a/dts/bindings/i2c/ti,cc23x0-i2c.yaml b/dts/bindings/i2c/ti,cc23x0-i2c.yaml new file mode 100644 index 000000000000..a0fb59d868a1 --- /dev/null +++ b/dts/bindings/i2c/ti,cc23x0-i2c.yaml @@ -0,0 +1,22 @@ +# Copyright (c) 2024 Baylibre, SAS +# +# SPDX-License-Identifier: Apache-2.0 + +description: TI CC23x0 I2C node + +compatible: "ti,cc23x0-i2c" + +include: [i2c-controller.yaml, pinctrl-device.yaml, base.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true From 324da9683d6e3cfc67a1ae693f2a183cbd91212c Mon Sep 17 00:00:00 2001 From: Stoyan Bogdanov Date: Tue, 6 Aug 2024 16:20:56 +0300 Subject: [PATCH 2/4] dts: arm: ti: cc23x0: Add I2C support Add support for I2C to cc23x0 SoC. Signed-off-by: Stoyan Bogdanov --- dts/arm/ti/cc23x0.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dts/arm/ti/cc23x0.dtsi b/dts/arm/ti/cc23x0.dtsi index 6b307980ce3e..e411b88b6039 100644 --- a/dts/arm/ti/cc23x0.dtsi +++ b/dts/arm/ti/cc23x0.dtsi @@ -79,6 +79,15 @@ clocks = <&sysclk>; status = "disabled"; }; + + i2c0: i2c@40038000 { + compatible = "ti,cc23x0-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40038000 0x820>; + interrupts = <12 0>; + status = "disabled"; + }; }; }; From 2861b4ac67a57d56b734ac41d8024f56b3496a1e Mon Sep 17 00:00:00 2001 From: Stoyan Bogdanov Date: Tue, 6 Aug 2024 16:19:03 +0300 Subject: [PATCH 3/4] boards: ti: lp_em_cc2340r5: Add I2C support Enable I2C for TI lp_em_cc2340r5. Signed-off-by: Stoyan Bogdanov --- .../ti/lp_em_cc2340r5/lp_em_cc2340r5-pinctrl.dtsi | 14 ++++++++++++++ boards/ti/lp_em_cc2340r5/lp_em_cc2340r5.dts | 8 ++++++++ 2 files changed, 22 insertions(+) diff --git a/boards/ti/lp_em_cc2340r5/lp_em_cc2340r5-pinctrl.dtsi b/boards/ti/lp_em_cc2340r5/lp_em_cc2340r5-pinctrl.dtsi index 1d929cfa6aca..c5438c9d9b7d 100644 --- a/boards/ti/lp_em_cc2340r5/lp_em_cc2340r5-pinctrl.dtsi +++ b/boards/ti/lp_em_cc2340r5/lp_em_cc2340r5-pinctrl.dtsi @@ -18,4 +18,18 @@ bias-disable; input-enable; }; + + /* I2C0 */ + i2c0_scl_default: i2c0_scl_default { + pinmux = <24 DIO24_I2C0_SCL>; + bias-pull-up; + drive-open-drain; + input-enable; + }; + i2c0_sda_default: i2c0_sda_default { + pinmux = <0 DIO0_I2C0_SDA>; + bias-pull-up; + drive-open-drain; + input-enable; + }; }; diff --git a/boards/ti/lp_em_cc2340r5/lp_em_cc2340r5.dts b/boards/ti/lp_em_cc2340r5/lp_em_cc2340r5.dts index 64d3e1502075..6fc12f601234 100644 --- a/boards/ti/lp_em_cc2340r5/lp_em_cc2340r5.dts +++ b/boards/ti/lp_em_cc2340r5/lp_em_cc2340r5.dts @@ -73,3 +73,11 @@ pinctrl-0 = <&uart0_rx_default &uart0_tx_default>; pinctrl-names = "default"; }; + +&i2c0 { + status = "okay"; + pinctrl-0 = <&i2c0_scl_default + &i2c0_sda_default>; + clock-frequency = <100000>; + pinctrl-names = "default"; +}; From e79aada512e1c66c9be948f0daa38b4dc4c3b664 Mon Sep 17 00:00:00 2001 From: Stoyan Bogdanov Date: Tue, 6 Aug 2024 16:14:46 +0300 Subject: [PATCH 4/4] samples: sensors: bme280: Add lp_em_cc2340r5 overlay Add lp_em_cc2340r5 overlay in bme280 sensors sample. Signed-off-by: Stoyan Bogdanov --- samples/sensor/bme280/boards/lp_em_cc2340r5.overlay | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 samples/sensor/bme280/boards/lp_em_cc2340r5.overlay diff --git a/samples/sensor/bme280/boards/lp_em_cc2340r5.overlay b/samples/sensor/bme280/boards/lp_em_cc2340r5.overlay new file mode 100644 index 000000000000..1a18dcbcfa7a --- /dev/null +++ b/samples/sensor/bme280/boards/lp_em_cc2340r5.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 Baylibre, SAS + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&i2c0 { + bme280@76 { + compatible = "bosch,bme280"; + reg = <0x76>; + status = "okay"; + }; +};