diff --git a/drivers/i2c/CMakeLists.txt b/drivers/i2c/CMakeLists.txt index 67ca17fd252..fd7192e8c6d 100644 --- a/drivers/i2c/CMakeLists.txt +++ b/drivers/i2c/CMakeLists.txt @@ -67,10 +67,12 @@ zephyr_library_sources_ifdef(CONFIG_I2C_SEDI i2c_sedi.c) zephyr_library_sources_ifdef(CONFIG_I2C_SIFIVE i2c_sifive.c) zephyr_library_sources_ifdef(CONFIG_I2C_SMARTBOND i2c_smartbond.c) zephyr_library_sources_ifdef(CONFIG_I2C_STM32_V1 + i2c_ll_stm32_common.c i2c_ll_stm32_v1.c i2c_ll_stm32.c ) zephyr_library_sources_ifdef(CONFIG_I2C_STM32_V2 + i2c_ll_stm32_common.c i2c_ll_stm32_v2.c i2c_ll_stm32.c ) diff --git a/drivers/i2c/i2c_ll_stm32.c b/drivers/i2c/i2c_ll_stm32.c index 47ea370e562..63e21236ddb 100644 --- a/drivers/i2c/i2c_ll_stm32.c +++ b/drivers/i2c/i2c_ll_stm32.c @@ -329,59 +329,6 @@ static DEVICE_API(i2c, api_funcs) = { #endif }; -#ifdef CONFIG_PM_DEVICE - -static int i2c_stm32_suspend(const struct device *dev) -{ - int ret; - const struct i2c_stm32_config *cfg = dev->config; - const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); - - /* Disable device clock. */ - ret = clock_control_off(clk, (clock_control_subsys_t)&cfg->pclken[0]); - if (ret < 0) { - LOG_ERR("failure disabling I2C clock"); - return ret; - } - - /* Move pins to sleep state */ - ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_SLEEP); - if (ret == -ENOENT) { - /* Warn but don't block suspend */ - LOG_WRN("I2C pinctrl sleep state not available "); - } else if (ret < 0) { - return ret; - } - - return 0; -} - -#endif - -static int i2c_stm32_activate(const struct device *dev) -{ - int ret; - const struct i2c_stm32_config *cfg = dev->config; - const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); - - /* Move pins to active/default state */ - ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); - if (ret < 0) { - LOG_ERR("I2C pinctrl setup failed (%d)", ret); - return ret; - } - - /* Enable device clock. */ - if (clock_control_on(clk, - (clock_control_subsys_t) &cfg->pclken[0]) != 0) { - LOG_ERR("i2c: failure enabling clock"); - return -EIO; - } - - return 0; -} - - static int i2c_stm32_init(const struct device *dev) { const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); @@ -450,28 +397,6 @@ static int i2c_stm32_init(const struct device *dev) return 0; } -#ifdef CONFIG_PM_DEVICE - -static int i2c_stm32_pm_action(const struct device *dev, enum pm_device_action action) -{ - int err; - - switch (action) { - case PM_DEVICE_ACTION_RESUME: - err = i2c_stm32_activate(dev); - break; - case PM_DEVICE_ACTION_SUSPEND: - err = i2c_stm32_suspend(dev); - break; - default: - return -ENOTSUP; - } - - return err; -} - -#endif - #ifdef CONFIG_SMBUS_STM32_SMBALERT void i2c_stm32_smbalert_set_callback(const struct device *dev, i2c_stm32_smbalert_cb_func_t func, const struct device *cb_dev) @@ -540,51 +465,6 @@ void i2c_stm32_smbalert_disable(const struct device *dev) /* Macros for I2C instance declaration */ -#ifdef CONFIG_I2C_STM32_INTERRUPT - -#ifdef CONFIG_I2C_STM32_COMBINED_INTERRUPT -#define I2C_STM32_IRQ_CONNECT_AND_ENABLE(index) \ - do { \ - IRQ_CONNECT(DT_INST_IRQN(index), \ - DT_INST_IRQ(index, priority), \ - i2c_stm32_combined_isr, \ - DEVICE_DT_INST_GET(index), 0); \ - irq_enable(DT_INST_IRQN(index)); \ - } while (false) -#else -#define I2C_STM32_IRQ_CONNECT_AND_ENABLE(index) \ - do { \ - IRQ_CONNECT(DT_INST_IRQ_BY_NAME(index, event, irq), \ - DT_INST_IRQ_BY_NAME(index, event, priority),\ - i2c_stm32_event_isr, \ - DEVICE_DT_INST_GET(index), 0); \ - irq_enable(DT_INST_IRQ_BY_NAME(index, event, irq)); \ - \ - IRQ_CONNECT(DT_INST_IRQ_BY_NAME(index, error, irq), \ - DT_INST_IRQ_BY_NAME(index, error, priority),\ - i2c_stm32_error_isr, \ - DEVICE_DT_INST_GET(index), 0); \ - irq_enable(DT_INST_IRQ_BY_NAME(index, error, irq)); \ - } while (false) -#endif /* CONFIG_I2C_STM32_COMBINED_INTERRUPT */ - -#define I2C_STM32_IRQ_HANDLER_DECL(index) \ -static void i2c_stm32_irq_config_func_##index(const struct device *dev) -#define I2C_STM32_IRQ_HANDLER_FUNCTION(index) \ - .irq_config_func = i2c_stm32_irq_config_func_##index, -#define I2C_STM32_IRQ_HANDLER(index) \ -static void i2c_stm32_irq_config_func_##index(const struct device *dev) \ -{ \ - I2C_STM32_IRQ_CONNECT_AND_ENABLE(index); \ -} -#else - -#define I2C_STM32_IRQ_HANDLER_DECL(index) -#define I2C_STM32_IRQ_HANDLER_FUNCTION(index) -#define I2C_STM32_IRQ_HANDLER(index) - -#endif /* CONFIG_I2C_STM32_INTERRUPT */ - #ifdef CONFIG_I2C_STM32_V2_DMA #define I2C_DMA_INIT(index, dir) \ diff --git a/drivers/i2c/i2c_ll_stm32.h b/drivers/i2c/i2c_ll_stm32.h index 14d713fb9bb..ec4eaea09c6 100644 --- a/drivers/i2c/i2c_ll_stm32.h +++ b/drivers/i2c/i2c_ll_stm32.h @@ -10,6 +10,11 @@ #define ZEPHYR_DRIVERS_I2C_I2C_LL_STM32_H_ #include +#include +#include +#include +#include +#include #ifdef CONFIG_I2C_STM32_BUS_RECOVERY #include @@ -117,15 +122,65 @@ int i2c_stm32_transaction(const struct device *dev, int i2c_stm32_configure_timing(const struct device *dev, uint32_t clk); int i2c_stm32_runtime_configure(const struct device *dev, uint32_t config); -void i2c_stm32_event_isr(void *arg); -void i2c_stm32_error_isr(void *arg); -#ifdef CONFIG_I2C_STM32_COMBINED_INTERRUPT -void i2c_stm32_combined_isr(void *arg); -#endif /* CONFIG_I2C_STM32_COMBINED_INTERRUPT */ - #ifdef CONFIG_I2C_TARGET int i2c_stm32_target_register(const struct device *dev, struct i2c_target_config *config); int i2c_stm32_target_unregister(const struct device *dev, struct i2c_target_config *config); #endif /* CONFIG_I2C_TARGET */ +int i2c_stm32_activate(const struct device *dev); + +#ifdef CONFIG_PM_DEVICE +int i2c_stm32_pm_action(const struct device *dev, enum pm_device_action action); +int i2c_stm32_suspend(const struct device *dev); +#endif /* CONFIG_PM_DEVICE */ + +int i2c_stm32_error(const struct device *dev); +void i2c_stm32_event(const struct device *dev); + +#ifdef CONFIG_I2C_STM32_INTERRUPT +#ifdef CONFIG_I2C_STM32_COMBINED_INTERRUPT +void i2c_stm32_combined_isr(void *arg); +#define I2C_STM32_IRQ_CONNECT_AND_ENABLE(index) \ + do { \ + IRQ_CONNECT(DT_INST_IRQN(index), \ + DT_INST_IRQ(index, priority), \ + i2c_stm32_combined_isr, \ + DEVICE_DT_INST_GET(index), 0); \ + irq_enable(DT_INST_IRQN(index)); \ + } while (false) +#else /* CONFIG_I2C_STM32_COMBINED_INTERRUPT */ +void i2c_stm32_event_isr(void *arg); +void i2c_stm32_error_isr(void *arg); +#define I2C_STM32_IRQ_CONNECT_AND_ENABLE(index) \ + do { \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(index, event, irq), \ + DT_INST_IRQ_BY_NAME(index, event, priority), \ + i2c_stm32_event_isr, \ + DEVICE_DT_INST_GET(index), 0); \ + irq_enable(DT_INST_IRQ_BY_NAME(index, event, irq)); \ + \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(index, error, irq), \ + DT_INST_IRQ_BY_NAME(index, error, priority), \ + i2c_stm32_error_isr, \ + DEVICE_DT_INST_GET(index), 0); \ + irq_enable(DT_INST_IRQ_BY_NAME(index, error, irq)); \ + } while (false) +#endif /* CONFIG_I2C_STM32_COMBINED_INTERRUPT */ + +#define I2C_STM32_IRQ_HANDLER_DECL(index) \ +static void i2c_stm32_irq_config_func_##index(const struct device *dev) +#define I2C_STM32_IRQ_HANDLER_FUNCTION(index) \ + .irq_config_func = i2c_stm32_irq_config_func_##index, +#define I2C_STM32_IRQ_HANDLER(index) \ +static void i2c_stm32_irq_config_func_##index(const struct device *dev) \ +{ \ + I2C_STM32_IRQ_CONNECT_AND_ENABLE(index); \ +} + +#else /* CONFIG_I2C_STM32_INTERRUPT */ +#define STM32_I2C_IRQ_HANDLER_DECL(index) +#define STM32_I2C_IRQ_HANDLER_FUNCTION(index) +#define STM32_I2C_IRQ_HANDLER(index) +#endif /* CONFIG_I2C_STM32_INTERRUPT */ + #endif /* ZEPHYR_DRIVERS_I2C_I2C_LL_STM32_H_ */ diff --git a/drivers/i2c/i2c_ll_stm32_common.c b/drivers/i2c/i2c_ll_stm32_common.c new file mode 100644 index 00000000000..e94ae5ec252 --- /dev/null +++ b/drivers/i2c/i2c_ll_stm32_common.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2016 BayLibre, SAS + * Copyright (c) 2017 Linaro Ltd + * Copyright (c) 2024 Intel Corporation + * Copyright (c) 2025 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL +#include +LOG_MODULE_REGISTER(i2c_ll_stm32_common); + +#include "i2c_ll_stm32.h" + +#ifdef CONFIG_I2C_STM32_COMBINED_INTERRUPT +void i2c_stm32_combined_isr(void *arg) +{ + const struct device *dev = (const struct device *) arg; + + if (i2c_stm32_error(dev)) { + return; + } + i2c_stm32_event(dev); +} +#else +void i2c_stm32_event_isr(void *arg) +{ + const struct device *dev = (const struct device *) arg; + + i2c_stm32_event(dev); +} + +void i2c_stm32_error_isr(void *arg) +{ + const struct device *dev = (const struct device *) arg; + + (void)i2c_stm32_error(dev); +} +#endif + +int i2c_stm32_activate(const struct device *dev) +{ + int ret; + const struct i2c_stm32_config *cfg = dev->config; + const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); + + /* Move pins to active/default state */ + ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + LOG_ERR("I2C pinctrl setup failed (%d)", ret); + return ret; + } + + /* Enable device clock. */ + if (clock_control_on(clk, + (clock_control_subsys_t) &cfg->pclken[0]) != 0) { + LOG_ERR("i2c: failure enabling clock"); + return -EIO; + } + + return 0; +} + +#ifdef CONFIG_PM_DEVICE +int i2c_stm32_suspend(const struct device *dev) +{ + int ret; + const struct i2c_stm32_config *cfg = dev->config; + const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); + + /* Disable device clock. */ + ret = clock_control_off(clk, (clock_control_subsys_t)&cfg->pclken[0]); + if (ret < 0) { + LOG_ERR("failure disabling I2C clock"); + return ret; + } + + /* Move pins to sleep state */ + ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_SLEEP); + if (ret == -ENOENT) { + /* Warn but don't block suspend */ + LOG_WRN("I2C pinctrl sleep state not available "); + } else if (ret < 0) { + return ret; + } + + return 0; +} + +int i2c_stm32_pm_action(const struct device *dev, enum pm_device_action action) +{ + int err; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + err = i2c_stm32_activate(dev); + break; + case PM_DEVICE_ACTION_SUSPEND: + err = i2c_stm32_suspend(dev); + break; + default: + return -ENOTSUP; + } + + return err; +} +#endif diff --git a/drivers/i2c/i2c_ll_stm32_v1.c b/drivers/i2c/i2c_ll_stm32_v1.c index 6c1fc37c5a5..59e93f74133 100644 --- a/drivers/i2c/i2c_ll_stm32_v1.c +++ b/drivers/i2c/i2c_ll_stm32_v1.c @@ -564,9 +564,8 @@ int i2c_stm32_target_unregister(const struct device *dev, struct i2c_target_conf } #endif /* defined(CONFIG_I2C_TARGET) */ -void i2c_stm32_event_isr(void *arg) +void i2c_stm32_event(const struct device *dev) { - const struct device *dev = (const struct device *)arg; const struct i2c_stm32_config *cfg = dev->config; struct i2c_stm32_data *data = dev->data; I2C_TypeDef *i2c = cfg->i2c; @@ -593,9 +592,8 @@ void i2c_stm32_event_isr(void *arg) } } -void i2c_stm32_error_isr(void *arg) +int i2c_stm32_error(const struct device *dev) { - const struct device *dev = (const struct device *)arg; const struct i2c_stm32_config *cfg = dev->config; struct i2c_stm32_data *data = dev->data; I2C_TypeDef *i2c = cfg->i2c; @@ -603,7 +601,7 @@ void i2c_stm32_error_isr(void *arg) #if defined(CONFIG_I2C_TARGET) if (data->slave_attached && !data->master_active) { /* No need for a slave error function right now. */ - return; + return 0; } #endif @@ -634,9 +632,10 @@ void i2c_stm32_error_isr(void *arg) goto end; } #endif - return; + return 0; end: i2c_stm32_master_mode_end(dev); + return -EIO; } static int32_t i2c_stm32_msg_write(const struct device *dev, struct i2c_msg *msg, diff --git a/drivers/i2c/i2c_ll_stm32_v2.c b/drivers/i2c/i2c_ll_stm32_v2.c index aeb4064df60..ee820272215 100644 --- a/drivers/i2c/i2c_ll_stm32_v2.c +++ b/drivers/i2c/i2c_ll_stm32_v2.c @@ -544,7 +544,7 @@ int i2c_stm32_target_unregister(const struct device *dev, #endif /* defined(CONFIG_I2C_TARGET) */ -static void i2c_stm32_event(const struct device *dev) +void i2c_stm32_event(const struct device *dev) { const struct i2c_stm32_config *cfg = dev->config; struct i2c_stm32_data *data = dev->data; @@ -618,7 +618,7 @@ end: i2c_stm32_master_mode_end(dev); } -static int i2c_stm32_error(const struct device *dev) +int i2c_stm32_error(const struct device *dev) { const struct i2c_stm32_config *cfg = dev->config; struct i2c_stm32_data *data = dev->data; @@ -659,33 +659,6 @@ end: return -EIO; } -#ifdef CONFIG_I2C_STM32_COMBINED_INTERRUPT -void i2c_stm32_combined_isr(void *arg) -{ - const struct device *dev = (const struct device *) arg; - - if (i2c_stm32_error(dev)) { - return; - } - i2c_stm32_event(dev); -} -#else - -void i2c_stm32_event_isr(void *arg) -{ - const struct device *dev = (const struct device *) arg; - - i2c_stm32_event(dev); -} - -void i2c_stm32_error_isr(void *arg) -{ - const struct device *dev = (const struct device *) arg; - - i2c_stm32_error(dev); -} -#endif - #if defined(CONFIG_DCACHE) && defined(CONFIG_I2C_STM32_V2_DMA) static bool buf_in_nocache(uintptr_t buf, size_t len_bytes) {