diff --git a/drivers/i2c/i2c_ll_stm32.c b/drivers/i2c/i2c_ll_stm32.c index 552acfb6ab2e..616c89b3dcbd 100644 --- a/drivers/i2c/i2c_ll_stm32.c +++ b/drivers/i2c/i2c_ll_stm32.c @@ -94,9 +94,13 @@ int i2c_stm32_runtime_configure(const struct device *dev, uint32_t config) #endif LL_I2C_Disable(i2c); - LL_I2C_SetMode(i2c, LL_I2C_MODE_I2C); + i2c_stm32_set_smbus_mode(dev, data->mode); ret = stm32_i2c_configure_timing(dev, i2c_clock); + if (data->smbalert_active) { + LL_I2C_Enable(i2c); + } + #ifdef CONFIG_PM_DEVICE_RUNTIME ret = clock_control_off(clk, (clock_control_subsys_t)&cfg->pclken[0]); if (ret < 0) { @@ -365,6 +369,7 @@ static int i2c_stm32_init(const struct device *dev) #endif data->is_configured = false; + data->mode = I2CSTM32MODE_I2C; /* * initialize mutex used when multiple transfers @@ -441,6 +446,70 @@ static int i2c_stm32_pm_action(const struct device *dev, enum pm_device_action a #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) +{ + struct i2c_stm32_data *data = dev->data; + + data->smbalert_cb_func = func; + data->smbalert_cb_dev = cb_dev; +} +#endif /* CONFIG_SMBUS_STM32_SMBALERT */ + +void i2c_stm32_set_smbus_mode(const struct device *dev, enum i2c_stm32_mode mode) +{ + const struct i2c_stm32_config *cfg = dev->config; + struct i2c_stm32_data *data = dev->data; + I2C_TypeDef *i2c = cfg->i2c; + + data->mode = mode; + + switch (mode) { + case I2CSTM32MODE_I2C: + LL_I2C_SetMode(i2c, LL_I2C_MODE_I2C); + return; +#ifdef CONFIG_SMBUS_STM32 + case I2CSTM32MODE_SMBUSHOST: + LL_I2C_SetMode(i2c, LL_I2C_MODE_SMBUS_HOST); + return; + case I2CSTM32MODE_SMBUSDEVICE: + LL_I2C_SetMode(i2c, LL_I2C_MODE_SMBUS_DEVICE); + return; + case I2CSTM32MODE_SMBUSDEVICEARP: + LL_I2C_SetMode(i2c, LL_I2C_MODE_SMBUS_DEVICE_ARP); + return; +#endif + default: + LOG_ERR("%s: invalid mode %i", dev->name, mode); + return; + } +} + +#ifdef CONFIG_SMBUS_STM32 +void i2c_stm32_smbalert_enable(const struct device *dev) +{ + struct i2c_stm32_data *data = dev->data; + const struct i2c_stm32_config *cfg = dev->config; + + data->smbalert_active = true; + LL_I2C_EnableSMBusAlert(cfg->i2c); + LL_I2C_EnableIT_ERR(cfg->i2c); + LL_I2C_Enable(cfg->i2c); +} + +void i2c_stm32_smbalert_disable(const struct device *dev) +{ + struct i2c_stm32_data *data = dev->data; + const struct i2c_stm32_config *cfg = dev->config; + + data->smbalert_active = false; + LL_I2C_DisableSMBusAlert(cfg->i2c); + LL_I2C_DisableIT_ERR(cfg->i2c); + LL_I2C_Disable(cfg->i2c); +} +#endif /* CONFIG_SMBUS_STM32 */ + /* Macros for I2C instance declaration */ #ifdef CONFIG_I2C_STM32_INTERRUPT diff --git a/drivers/i2c/i2c_ll_stm32.h b/drivers/i2c/i2c_ll_stm32.h index c77b687038d7..0a9dc1be350a 100644 --- a/drivers/i2c/i2c_ll_stm32.h +++ b/drivers/i2c/i2c_ll_stm32.h @@ -9,6 +9,8 @@ #ifndef ZEPHYR_DRIVERS_I2C_I2C_LL_STM32_H_ #define ZEPHYR_DRIVERS_I2C_I2C_LL_STM32_H_ +#include + #ifdef CONFIG_I2C_STM32_BUS_RECOVERY #include #endif /* CONFIG_I2C_STM32_BUS_RECOVERY */ @@ -79,6 +81,12 @@ struct i2c_stm32_data { bool slave_attached; #endif bool is_configured; + bool smbalert_active; + enum i2c_stm32_mode mode; +#ifdef CONFIG_SMBUS_STM32_SMBALERT + i2c_stm32_smbalert_cb_func_t smbalert_cb_func; + const struct device *smbalert_cb_dev; +#endif }; int32_t stm32_i2c_transaction(const struct device *dev, diff --git a/drivers/i2c/i2c_ll_stm32_v1.c b/drivers/i2c/i2c_ll_stm32_v1.c index d0a0131858fe..4730cc155985 100644 --- a/drivers/i2c/i2c_ll_stm32_v1.c +++ b/drivers/i2c/i2c_ll_stm32_v1.c @@ -48,13 +48,17 @@ static void stm32_i2c_generate_start_condition(I2C_TypeDef *i2c) static void stm32_i2c_disable_transfer_interrupts(const struct device *dev) { const struct i2c_stm32_config *cfg = dev->config; + struct i2c_stm32_data *data = dev->data; I2C_TypeDef *i2c = cfg->i2c; LL_I2C_DisableIT_TX(i2c); LL_I2C_DisableIT_RX(i2c); LL_I2C_DisableIT_EVT(i2c); LL_I2C_DisableIT_BUF(i2c); - LL_I2C_DisableIT_ERR(i2c); + + if (!data->smbalert_active) { + LL_I2C_DisableIT_ERR(i2c); + } } static void stm32_i2c_enable_transfer_interrupts(const struct device *dev) @@ -118,6 +122,7 @@ static void stm32_i2c_reset(const struct device *dev) static void stm32_i2c_master_finish(const struct device *dev) { const struct i2c_stm32_config *cfg = dev->config; + struct i2c_stm32_data *data = dev->data; I2C_TypeDef *i2c = cfg->i2c; #ifdef CONFIG_I2C_STM32_INTERRUPT @@ -125,16 +130,17 @@ static void stm32_i2c_master_finish(const struct device *dev) #endif #if defined(CONFIG_I2C_TARGET) - struct i2c_stm32_data *data = dev->data; data->master_active = false; - if (!data->slave_attached) { + if (!data->slave_attached && !data->smbalert_active) { LL_I2C_Disable(i2c); } else { stm32_i2c_enable_transfer_interrupts(dev); LL_I2C_AcknowledgeNextData(i2c, LL_I2C_ACK); } #else - LL_I2C_Disable(i2c); + if (!data->smbalert_active) { + LL_I2C_Disable(i2c); + } #endif } @@ -538,7 +544,9 @@ int i2c_stm32_target_unregister(const struct device *dev, struct i2c_target_conf LL_I2C_ClearFlag_STOP(i2c); LL_I2C_ClearFlag_ADDR(i2c); - LL_I2C_Disable(i2c); + if (!data->smbalert_active) { + LL_I2C_Disable(i2c); + } data->slave_attached = false; @@ -608,6 +616,16 @@ void stm32_i2c_error_isr(void *arg) data->current.is_err = 1U; goto end; } + +#if defined(CONFIG_SMBUS_STM32_SMBALERT) + if (LL_I2C_IsActiveSMBusFlag_ALERT(i2c)) { + LL_I2C_ClearSMBusFlag_ALERT(i2c); + if (data->smbalert_cb_func != NULL) { + data->smbalert_cb_func(data->smbalert_cb_dev); + } + goto end; + } +#endif return; end: stm32_i2c_master_mode_end(dev); diff --git a/drivers/i2c/i2c_ll_stm32_v2.c b/drivers/i2c/i2c_ll_stm32_v2.c index 8292b2f6738f..a685ebebeb78 100644 --- a/drivers/i2c/i2c_ll_stm32_v2.c +++ b/drivers/i2c/i2c_ll_stm32_v2.c @@ -74,6 +74,7 @@ static inline void msg_init(const struct device *dev, struct i2c_msg *msg, static void stm32_i2c_disable_transfer_interrupts(const struct device *dev) { const struct i2c_stm32_config *cfg = dev->config; + struct i2c_stm32_data *data = dev->data; I2C_TypeDef *i2c = cfg->i2c; LL_I2C_DisableIT_TX(i2c); @@ -81,7 +82,10 @@ static void stm32_i2c_disable_transfer_interrupts(const struct device *dev) LL_I2C_DisableIT_STOP(i2c); LL_I2C_DisableIT_NACK(i2c); LL_I2C_DisableIT_TC(i2c); - LL_I2C_DisableIT_ERR(i2c); + + if (!data->smbalert_active) { + LL_I2C_DisableIT_ERR(i2c); + } } static void stm32_i2c_enable_transfer_interrupts(const struct device *dev) @@ -109,11 +113,13 @@ static void stm32_i2c_master_mode_end(const struct device *dev) #if defined(CONFIG_I2C_TARGET) data->master_active = false; - if (!data->slave_attached) { + if (!data->slave_attached && !data->smbalert_active) { LL_I2C_Disable(i2c); } #else - LL_I2C_Disable(i2c); + if (!data->smbalert_active) { + LL_I2C_Disable(i2c); + } #endif k_sem_give(&data->device_sync_sem); } @@ -330,7 +336,9 @@ int i2c_stm32_target_unregister(const struct device *dev, LL_I2C_ClearFlag_STOP(i2c); LL_I2C_ClearFlag_ADDR(i2c); - LL_I2C_Disable(i2c); + if (!data->smbalert_active) { + LL_I2C_Disable(i2c); + } #if defined(CONFIG_PM_DEVICE_RUNTIME) if (pm_device_wakeup_is_capable(dev)) { @@ -437,6 +445,16 @@ static int stm32_i2c_error(const struct device *dev) goto end; } +#if defined(CONFIG_SMBUS_STM32_SMBALERT) + if (LL_I2C_IsActiveSMBusFlag_ALERT(i2c)) { + LL_I2C_ClearSMBusFlag_ALERT(i2c); + if (data->smbalert_cb_func != NULL) { + data->smbalert_cb_func(data->smbalert_cb_dev); + } + goto end; + } +#endif + return 0; end: stm32_i2c_master_mode_end(dev); diff --git a/drivers/smbus/CMakeLists.txt b/drivers/smbus/CMakeLists.txt index 13a260681f05..b7677a9bf6f4 100644 --- a/drivers/smbus/CMakeLists.txt +++ b/drivers/smbus/CMakeLists.txt @@ -4,7 +4,10 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/smbus.h) zephyr_library() +zephyr_library_sources(smbus_utils.c) + zephyr_library_sources_ifdef(CONFIG_SMBUS_SHELL smbus_shell.c) zephyr_library_sources_ifdef(CONFIG_SMBUS_INTEL_PCH intel_pch_smbus.c) +zephyr_library_sources_ifdef(CONFIG_SMBUS_STM32 smbus_stm32.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE smbus_handlers.c) diff --git a/drivers/smbus/Kconfig b/drivers/smbus/Kconfig index 88eff8b0030b..74efaae29f17 100644 --- a/drivers/smbus/Kconfig +++ b/drivers/smbus/Kconfig @@ -77,4 +77,22 @@ config SMBUS_INTEL_PCH_SMBALERT endif # SMBUS_INTEL_PCH +config SMBUS_STM32 + bool "STM32 SMBus driver" + default y + depends on DT_HAS_ST_STM32_SMBUS_ENABLED + depends on I2C_STM32 + help + Enable STM32 SMBus driver. + +if SMBUS_STM32 + +config SMBUS_STM32_SMBALERT + bool "SMBus STM32 SMBALERT signal support" + default y + help + Support SMBALERT signal from peripheral devices. + +endif # SMBUS_STM32 + endif # SMBUS diff --git a/drivers/smbus/intel_pch_smbus.c b/drivers/smbus/intel_pch_smbus.c index e40fc3d0cb65..9452efecf224 100644 --- a/drivers/smbus/intel_pch_smbus.c +++ b/drivers/smbus/intel_pch_smbus.c @@ -143,33 +143,7 @@ static void smbalert_work(struct k_work *work) smb_alert_work); const struct device *dev = data->dev; - /** - * There might be several peripheral devices and the he highest - * priority (lowest address) device wins arbitration, we need to - * read them all. - * - * The format of the transaction is: - * - * 0 1 2 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |S| Alert Addr |R|A| Address |X|N|P| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - do { - uint8_t addr; - int ret; - - ret = smbus_byte_read(dev, SMBUS_ADDRESS_ARA, &addr); - if (ret < 0) { - LOG_DBG("Cannot read peripheral address (anymore)"); - return; - } - - LOG_DBG("Read addr 0x%02x, ret %d", addr, ret); - - smbus_fire_callbacks(&data->smbalert_cbs, dev, addr); - } while (true); + smbus_loop_alert_devices(dev, &data->smbalert_cbs); } static int pch_smbus_smbalert_set_sb(const struct device *dev, diff --git a/drivers/smbus/smbus_stm32.c b/drivers/smbus/smbus_stm32.c new file mode 100644 index 000000000000..56636cc84bff --- /dev/null +++ b/drivers/smbus/smbus_stm32.c @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2023 SILA Embedded Solutions GmbH + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "smbus_utils.h" + +LOG_MODULE_REGISTER(stm32_smbus, CONFIG_SMBUS_LOG_LEVEL); + +struct smbus_stm32_config { + const struct pinctrl_dev_config *pcfg; + const struct device *i2c_dev; +}; + +struct smbus_stm32_data { + uint32_t config; + const struct device *dev; +#ifdef CONFIG_SMBUS_STM32_SMBALERT + sys_slist_t smbalert_callbacks; + struct k_work smbalert_work; +#endif /* CONFIG_SMBUS_STM32_SMBALERT */ +}; + +#ifdef CONFIG_SMBUS_STM32_SMBALERT +static void smbus_stm32_smbalert_isr(const struct device *dev) +{ + struct smbus_stm32_data *data = dev->data; + + k_work_submit(&data->smbalert_work); +} + +static void smbus_stm32_smbalert_work(struct k_work *work) +{ + struct smbus_stm32_data *data = CONTAINER_OF(work, struct smbus_stm32_data, smbalert_work); + const struct device *dev = data->dev; + + LOG_DBG("%s: got SMB alert", dev->name); + + smbus_loop_alert_devices(dev, &data->smbalert_callbacks); +} + +static int smbus_stm32_smbalert_set_cb(const struct device *dev, struct smbus_callback *cb) +{ + struct smbus_stm32_data *data = dev->data; + + return smbus_callback_set(&data->smbalert_callbacks, cb); +} + +static int smbus_stm32_smbalert_remove_cb(const struct device *dev, struct smbus_callback *cb) +{ + struct smbus_stm32_data *data = dev->data; + + return smbus_callback_remove(&data->smbalert_callbacks, cb); +} +#endif /* CONFIG_SMBUS_STM32_SMBALERT */ + +static int smbus_stm32_init(const struct device *dev) +{ + const struct smbus_stm32_config *config = dev->config; + struct smbus_stm32_data *data = dev->data; + int result; + + data->dev = dev; + + if (!device_is_ready(config->i2c_dev)) { + LOG_ERR("%s: I2C device is not ready", dev->name); + return -ENODEV; + } + + result = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (result < 0) { + LOG_ERR("%s: pinctrl setup failed (%d)", dev->name, result); + return result; + } + +#ifdef CONFIG_SMBUS_STM32_SMBALERT + k_work_init(&data->smbalert_work, smbus_stm32_smbalert_work); + + i2c_stm32_smbalert_set_callback(config->i2c_dev, smbus_stm32_smbalert_isr, dev); +#endif /* CONFIG_SMBUS_STM32_SMBALERT */ + + return 0; +} + +static int smbus_stm32_configure(const struct device *dev, uint32_t config_value) +{ + const struct smbus_stm32_config *config = dev->config; + struct smbus_stm32_data *data = dev->data; + + if (config_value & SMBUS_MODE_PEC) { + LOG_ERR("%s: not implemented", dev->name); + return -EINVAL; + } + + if (config_value & SMBUS_MODE_HOST_NOTIFY) { + LOG_ERR("%s: not available", dev->name); + return -EINVAL; + } + + if (config_value & SMBUS_MODE_CONTROLLER) { + LOG_DBG("%s: configuring SMB in host mode", dev->name); + i2c_stm32_set_smbus_mode(config->i2c_dev, I2CSTM32MODE_SMBUSHOST); + } else { + LOG_DBG("%s: configuring SMB in device mode", dev->name); + i2c_stm32_set_smbus_mode(config->i2c_dev, I2CSTM32MODE_SMBUSDEVICE); + } + + if (config_value & SMBUS_MODE_SMBALERT) { + LOG_DBG("%s: activating SMB alert", dev->name); + i2c_stm32_smbalert_enable(config->i2c_dev); + } else { + LOG_DBG("%s: deactivating SMB alert", dev->name); + i2c_stm32_smbalert_disable(config->i2c_dev); + } + + data->config = config_value; + return 0; +} + +static int smbus_stm32_get_config(const struct device *dev, uint32_t *config) +{ + struct smbus_stm32_data *data = dev->data; + *config = data->config; + return 0; +} + +static int smbus_stm32_quick(const struct device *dev, uint16_t periph_addr, + enum smbus_direction rw) +{ + const struct smbus_stm32_config *config = dev->config; + + switch (rw) { + case SMBUS_MSG_WRITE: + return i2c_write(config->i2c_dev, NULL, 0, periph_addr); + case SMBUS_MSG_READ: + return i2c_read(config->i2c_dev, NULL, 0, periph_addr); + default: + LOG_ERR("%s: invalid smbus direction %i", dev->name, rw); + return -EINVAL; + } +} + +static int smbus_stm32_byte_write(const struct device *dev, uint16_t periph_addr, uint8_t command) +{ + const struct smbus_stm32_config *config = dev->config; + + return i2c_write(config->i2c_dev, &command, sizeof(command), periph_addr); +} + +static int smbus_stm32_byte_read(const struct device *dev, uint16_t periph_addr, uint8_t *byte) +{ + const struct smbus_stm32_config *config = dev->config; + + return i2c_read(config->i2c_dev, byte, sizeof(*byte), periph_addr); +} + +static int smbus_stm32_byte_data_write(const struct device *dev, uint16_t periph_addr, + uint8_t command, uint8_t byte) +{ + const struct smbus_stm32_config *config = dev->config; + uint8_t buffer[] = { + command, + byte, + }; + + return i2c_write(config->i2c_dev, buffer, ARRAY_SIZE(buffer), periph_addr); +} + +static int smbus_stm32_byte_data_read(const struct device *dev, uint16_t periph_addr, + uint8_t command, uint8_t *byte) +{ + const struct smbus_stm32_config *config = dev->config; + + return i2c_write_read(config->i2c_dev, periph_addr, &command, sizeof(command), byte, + sizeof(*byte)); +} + +static int smbus_stm32_word_data_write(const struct device *dev, uint16_t periph_addr, + uint8_t command, uint16_t word) +{ + const struct smbus_stm32_config *config = dev->config; + uint8_t buffer[sizeof(command) + sizeof(word)]; + + buffer[0] = command; + sys_put_le16(word, buffer + 1); + + return i2c_write(config->i2c_dev, buffer, ARRAY_SIZE(buffer), periph_addr); +} + +static int smbus_stm32_word_data_read(const struct device *dev, uint16_t periph_addr, + uint8_t command, uint16_t *word) +{ + const struct smbus_stm32_config *config = dev->config; + int result; + + result = i2c_write_read(config->i2c_dev, periph_addr, &command, sizeof(command), word, + sizeof(*word)); + *word = sys_le16_to_cpu(*word); + + return result; +} + +static int smbus_stm32_pcall(const struct device *dev, uint16_t periph_addr, uint8_t command, + uint16_t send_word, uint16_t *recv_word) +{ + const struct smbus_stm32_config *config = dev->config; + uint8_t buffer[sizeof(command) + sizeof(send_word)]; + int result; + + buffer[0] = command; + sys_put_le16(send_word, buffer + 1); + + result = i2c_write_read(config->i2c_dev, periph_addr, buffer, ARRAY_SIZE(buffer), recv_word, + sizeof(*recv_word)); + *recv_word = sys_le16_to_cpu(*recv_word); + + return result; +} + +static int smbus_stm32_block_write(const struct device *dev, uint16_t periph_addr, uint8_t command, + uint8_t count, uint8_t *buf) +{ + const struct smbus_stm32_config *config = dev->config; + struct i2c_msg messages[] = { + { + .buf = &command, + .len = sizeof(command), + .flags = 0, + }, + { + .buf = buf, + .len = count, + .flags = 0, + }, + }; + + return i2c_transfer(config->i2c_dev, messages, ARRAY_SIZE(messages), periph_addr); +} + +static const struct smbus_driver_api smbus_stm32_api = { + .configure = smbus_stm32_configure, + .get_config = smbus_stm32_get_config, + .smbus_quick = smbus_stm32_quick, + .smbus_byte_write = smbus_stm32_byte_write, + .smbus_byte_read = smbus_stm32_byte_read, + .smbus_byte_data_write = smbus_stm32_byte_data_write, + .smbus_byte_data_read = smbus_stm32_byte_data_read, + .smbus_word_data_write = smbus_stm32_word_data_write, + .smbus_word_data_read = smbus_stm32_word_data_read, + .smbus_pcall = smbus_stm32_pcall, + .smbus_block_write = smbus_stm32_block_write, +#ifdef CONFIG_SMBUS_STM32_SMBALERT + .smbus_smbalert_set_cb = smbus_stm32_smbalert_set_cb, + .smbus_smbalert_remove_cb = smbus_stm32_smbalert_remove_cb, +#else + .smbus_smbalert_set_cb = NULL, + .smbus_smbalert_remove_cb = NULL, +#endif /* CONFIG_SMBUS_STM32_SMBALERT */ + .smbus_block_read = NULL, + .smbus_block_pcall = NULL, + .smbus_host_notify_set_cb = NULL, + .smbus_host_notify_remove_cb = NULL, +}; + +#define DT_DRV_COMPAT st_stm32_smbus + +#define SMBUS_STM32_DEVICE_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + static struct smbus_stm32_config smbus_stm32_config_##n = { \ + .i2c_dev = DEVICE_DT_GET(DT_INST_PROP(n, i2c)), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + }; \ + \ + static struct smbus_stm32_data smbus_stm32_data_##n; \ + \ + SMBUS_DEVICE_DT_INST_DEFINE(n, smbus_stm32_init, NULL, &smbus_stm32_data_##n, \ + &smbus_stm32_config_##n, POST_KERNEL, \ + CONFIG_SMBUS_INIT_PRIORITY, &smbus_stm32_api); + +DT_INST_FOREACH_STATUS_OKAY(SMBUS_STM32_DEVICE_INIT) diff --git a/drivers/smbus/smbus_utils.c b/drivers/smbus/smbus_utils.c new file mode 100644 index 000000000000..5ff3076da9e1 --- /dev/null +++ b/drivers/smbus/smbus_utils.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022 Intel Corporation + * Copyright (c) 2023 SILA Embedded Solutions GmbH + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "smbus_utils.h" + +#include + +LOG_MODULE_REGISTER(smbus_utils, CONFIG_SMBUS_LOG_LEVEL); + +void smbus_loop_alert_devices(const struct device *dev, sys_slist_t *callbacks) +{ + int result; + uint8_t address; + + /** + * There might be several peripheral devices which could have triggered the alert and + * the one with the highest priority (lowest address) device wins the arbitration. In + * any case, we will have to loop through all of them. + * + * The format of the transaction is: + * + * 0 1 2 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |S| Alert Addr |R|A| Address |X|N|P| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + while (true) { + result = smbus_byte_read(dev, SMBUS_ADDRESS_ARA, &address); + if (result != 0) { + LOG_DBG("%s: no more peripheral devices left which triggered an alert", + dev->name); + return; + } + + LOG_DBG("%s: address 0x%02X triggered an alert", dev->name, address); + + smbus_fire_callbacks(callbacks, dev, address); + } +} diff --git a/drivers/smbus/smbus_utils.h b/drivers/smbus/smbus_utils.h index 0158d2c5a521..a4f7ecd0c729 100644 --- a/drivers/smbus/smbus_utils.h +++ b/drivers/smbus/smbus_utils.h @@ -7,6 +7,11 @@ #ifndef ZEPHYR_DRIVERS_SMBUS_SMBUS_UTILS_H_ #define ZEPHYR_DRIVERS_SMBUS_SMBUS_UTILS_H_ +#include +#include +#include +#include + /** * @brief Generic function to insert a callback to a callback list * @@ -91,5 +96,15 @@ static inline void smbus_init_callback(struct smbus_callback *callback, callback->addr = addr; } +/** + * @brief Helper for handling an SMB alert + * + * This loops through all devices which triggered the SMB alert and + * fires the callbacks. + * + * @param dev SMBus device + * @param callbacks list of SMB alert callbacks + */ +void smbus_loop_alert_devices(const struct device *dev, sys_slist_t *callbacks); #endif /* ZEPHYR_DRIVERS_SMBUS_SMBUS_UTILS_H_ */ diff --git a/dts/arm/st/c0/stm32c0.dtsi b/dts/arm/st/c0/stm32c0.dtsi index ef71f835ba2a..fd37b14b5f93 100644 --- a/dts/arm/st/c0/stm32c0.dtsi +++ b/dts/arm/st/c0/stm32c0.dtsi @@ -343,6 +343,14 @@ io-channels = <&adc1 10>; status = "disabled"; }; + + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c1>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm/st/f0/stm32f0.dtsi b/dts/arm/st/f0/stm32f0.dtsi index 3a7e5dac8ce3..0371ac75ac6e 100644 --- a/dts/arm/st/f0/stm32f0.dtsi +++ b/dts/arm/st/f0/stm32f0.dtsi @@ -364,6 +364,14 @@ io-channels = <&adc1 17>; status = "disabled"; }; + + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c1>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm/st/f0/stm32f030X8.dtsi b/dts/arm/st/f0/stm32f030X8.dtsi index 775b3b3ebe42..9044da82c0ad 100644 --- a/dts/arm/st/f0/stm32f030X8.dtsi +++ b/dts/arm/st/f0/stm32f030X8.dtsi @@ -77,4 +77,12 @@ }; }; }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/f0/stm32f051.dtsi b/dts/arm/st/f0/stm32f051.dtsi index 45165c31e2b3..51d23418207d 100644 --- a/dts/arm/st/f0/stm32f051.dtsi +++ b/dts/arm/st/f0/stm32f051.dtsi @@ -77,4 +77,12 @@ #io-channel-cells = <1>; }; }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/f0/stm32f070Xb.dtsi b/dts/arm/st/f0/stm32f070Xb.dtsi index 665945738a82..6962a67ba109 100644 --- a/dts/arm/st/f0/stm32f070Xb.dtsi +++ b/dts/arm/st/f0/stm32f070Xb.dtsi @@ -87,4 +87,12 @@ status = "disabled"; }; }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/f1/stm32f1.dtsi b/dts/arm/st/f1/stm32f1.dtsi index d3eb976b5663..dc9f140370ec 100644 --- a/dts/arm/st/f1/stm32f1.dtsi +++ b/dts/arm/st/f1/stm32f1.dtsi @@ -362,6 +362,22 @@ v25 = <1430>; ntc; }; + + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c1>; + status = "disabled"; + }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm/st/f2/stm32f2.dtsi b/dts/arm/st/f2/stm32f2.dtsi index 7cef6f2428a5..9c9137569198 100644 --- a/dts/arm/st/f2/stm32f2.dtsi +++ b/dts/arm/st/f2/stm32f2.dtsi @@ -713,6 +713,30 @@ compatible = "usb-nop-xceiv"; #phy-cells = <0>; }; + + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c1>; + status = "disabled"; + }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; + + smbus3: smbus3 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c3>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm/st/f3/stm32f3.dtsi b/dts/arm/st/f3/stm32f3.dtsi index 5f5099a90d68..e4a64b243042 100644 --- a/dts/arm/st/f3/stm32f3.dtsi +++ b/dts/arm/st/f3/stm32f3.dtsi @@ -463,6 +463,14 @@ compatible = "usb-nop-xceiv"; #phy-cells = <0>; }; + + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c1>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm/st/f3/stm32f302.dtsi b/dts/arm/st/f3/stm32f302.dtsi index 59f4b2f70776..5d2c40be20b1 100644 --- a/dts/arm/st/f3/stm32f302.dtsi +++ b/dts/arm/st/f3/stm32f302.dtsi @@ -117,4 +117,20 @@ st,adc-sequencer = ; }; }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; + + smbus3: smbus3 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c3>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/f3/stm32f302Xc.dtsi b/dts/arm/st/f3/stm32f302Xc.dtsi index 4c1de5611ee2..8d30e7d31d18 100644 --- a/dts/arm/st/f3/stm32f302Xc.dtsi +++ b/dts/arm/st/f3/stm32f302Xc.dtsi @@ -49,3 +49,4 @@ }; /delete-node/ &i2c3; +/delete-node/ &smbus3; diff --git a/dts/arm/st/f3/stm32f303.dtsi b/dts/arm/st/f3/stm32f303.dtsi index 01e5d4233df1..5fa8d11b150d 100644 --- a/dts/arm/st/f3/stm32f303.dtsi +++ b/dts/arm/st/f3/stm32f303.dtsi @@ -172,4 +172,12 @@ st,adc-sequencer = ; }; }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/f3/stm32f373.dtsi b/dts/arm/st/f3/stm32f373.dtsi index 9c42331c36e1..73c4de1eafac 100644 --- a/dts/arm/st/f3/stm32f373.dtsi +++ b/dts/arm/st/f3/stm32f373.dtsi @@ -212,4 +212,12 @@ vbat: vbat { io-channels = <&adc1 18>; }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/f4/stm32f4.dtsi b/dts/arm/st/f4/stm32f4.dtsi index 4a03abd609b8..010868a00f2a 100644 --- a/dts/arm/st/f4/stm32f4.dtsi +++ b/dts/arm/st/f4/stm32f4.dtsi @@ -599,6 +599,30 @@ compatible = "usb-nop-xceiv"; #phy-cells = <0>; }; + + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c1>; + status = "disabled"; + }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; + + smbus3: smbus3 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c3>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm/st/f7/stm32f7.dtsi b/dts/arm/st/f7/stm32f7.dtsi index f2d336d7b6d4..cfd98d4bb4d7 100644 --- a/dts/arm/st/f7/stm32f7.dtsi +++ b/dts/arm/st/f7/stm32f7.dtsi @@ -882,6 +882,30 @@ compatible = "usb-nop-xceiv"; #phy-cells = <0>; }; + + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; + + smbus3: smbus3 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c3>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm/st/f7/stm32f745.dtsi b/dts/arm/st/f7/stm32f745.dtsi index d63ddd881baa..b4e7b55a948d 100644 --- a/dts/arm/st/f7/stm32f745.dtsi +++ b/dts/arm/st/f7/stm32f745.dtsi @@ -88,4 +88,12 @@ status = "disabled"; }; }; + + smbus4: smbus4 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c4>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/f7/stm32f765.dtsi b/dts/arm/st/f7/stm32f765.dtsi index fccf74e73558..642a7a755211 100644 --- a/dts/arm/st/f7/stm32f765.dtsi +++ b/dts/arm/st/f7/stm32f765.dtsi @@ -91,4 +91,12 @@ }; }; + + smbus4: smbus4 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c4>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/g0/stm32g0.dtsi b/dts/arm/st/g0/stm32g0.dtsi index 5f37fc667dbf..bfa023d027d3 100644 --- a/dts/arm/st/g0/stm32g0.dtsi +++ b/dts/arm/st/g0/stm32g0.dtsi @@ -460,6 +460,22 @@ io-channels = <&adc1 14>; status = "disabled"; }; + + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c1>; + status = "disabled"; + }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm/st/g0/stm32g0b0.dtsi b/dts/arm/st/g0/stm32g0b0.dtsi index f9c26bb0ddea..861c70f2d5b9 100644 --- a/dts/arm/st/g0/stm32g0b0.dtsi +++ b/dts/arm/st/g0/stm32g0b0.dtsi @@ -110,4 +110,12 @@ compatible = "usb-nop-xceiv"; #phy-cells = <0>; }; + + smbus3: smbus3 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c3>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/g0/stm32g0b1.dtsi b/dts/arm/st/g0/stm32g0b1.dtsi index b99063d67b8c..ead49eb06052 100644 --- a/dts/arm/st/g0/stm32g0b1.dtsi +++ b/dts/arm/st/g0/stm32g0b1.dtsi @@ -143,4 +143,12 @@ compatible = "usb-nop-xceiv"; #phy-cells = <0>; }; + + smbus3: smbus3 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c3>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/g4/stm32g4.dtsi b/dts/arm/st/g4/stm32g4.dtsi index 4cc6c26fc029..1b6632f694f4 100644 --- a/dts/arm/st/g4/stm32g4.dtsi +++ b/dts/arm/st/g4/stm32g4.dtsi @@ -691,6 +691,30 @@ compatible = "usb-nop-xceiv"; #phy-cells = <0>; }; + + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c1>; + status = "disabled"; + }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; + + smbus3: smbus3 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c3>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm/st/g4/stm32g473.dtsi b/dts/arm/st/g4/stm32g473.dtsi index 97565c33e732..930e16397950 100644 --- a/dts/arm/st/g4/stm32g473.dtsi +++ b/dts/arm/st/g4/stm32g473.dtsi @@ -108,4 +108,12 @@ status = "disabled"; }; }; + + smbus4: smbus4 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c4>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/h5/stm32h5.dtsi b/dts/arm/st/h5/stm32h5.dtsi index 43266cfbe2c9..310b3384f602 100644 --- a/dts/arm/st/h5/stm32h5.dtsi +++ b/dts/arm/st/h5/stm32h5.dtsi @@ -536,6 +536,22 @@ compatible = "usb-nop-xceiv"; #phy-cells = <0>; }; + + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c1>; + status = "disabled"; + }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm/st/h5/stm32h562.dtsi b/dts/arm/st/h5/stm32h562.dtsi index 66ed8d3d927a..f7cd14f72135 100644 --- a/dts/arm/st/h5/stm32h562.dtsi +++ b/dts/arm/st/h5/stm32h562.dtsi @@ -308,4 +308,20 @@ status = "disabled"; }; }; + + smbus3: smbus3 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c3>; + status = "disabled"; + }; + + smbus4: smbus4 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c4>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/h7/stm32h7.dtsi b/dts/arm/st/h7/stm32h7.dtsi index ecbe8f419a60..9dcd13531323 100644 --- a/dts/arm/st/h7/stm32h7.dtsi +++ b/dts/arm/st/h7/stm32h7.dtsi @@ -1036,6 +1036,38 @@ vrefint-cal-mv = <3300>; status = "disabled"; }; + + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c1>; + status = "disabled"; + }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; + + smbus3: smbus3 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c3>; + status = "disabled"; + }; + + smbus4: smbus4 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c4>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm/st/l0/stm32l0.dtsi b/dts/arm/st/l0/stm32l0.dtsi index b05dbff210df..7bb62de1f22f 100644 --- a/dts/arm/st/l0/stm32l0.dtsi +++ b/dts/arm/st/l0/stm32l0.dtsi @@ -351,6 +351,14 @@ io-channels = <&adc1 17>; status = "disabled"; }; + + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c1>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm/st/l0/stm32l051.dtsi b/dts/arm/st/l0/stm32l051.dtsi index e6209dc531bb..9c5bfa1b0284 100644 --- a/dts/arm/st/l0/stm32l051.dtsi +++ b/dts/arm/st/l0/stm32l051.dtsi @@ -73,4 +73,12 @@ reg = <0x08080000 DT_SIZE_K(2)>; }; }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/l0/stm32l071.dtsi b/dts/arm/st/l0/stm32l071.dtsi index 56d88c5bd51a..95a8fdc84249 100644 --- a/dts/arm/st/l0/stm32l071.dtsi +++ b/dts/arm/st/l0/stm32l071.dtsi @@ -161,4 +161,20 @@ reg = <0x08080000 DT_SIZE_K(6)>; }; }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; + + smbus3: smbus3 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c3>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/l1/stm32l1.dtsi b/dts/arm/st/l1/stm32l1.dtsi index 2f08501a2c10..53dbd64492d2 100644 --- a/dts/arm/st/l1/stm32l1.dtsi +++ b/dts/arm/st/l1/stm32l1.dtsi @@ -482,6 +482,22 @@ io-channels = <&adc1 17>; status = "disabled"; }; + + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c1>; + status = "disabled"; + }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm/st/l4/stm32l4.dtsi b/dts/arm/st/l4/stm32l4.dtsi index f2b8c1a2ff67..7dcabdf877cd 100644 --- a/dts/arm/st/l4/stm32l4.dtsi +++ b/dts/arm/st/l4/stm32l4.dtsi @@ -493,6 +493,22 @@ io-channels = <&adc1 18>; status = "disabled"; }; + + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c1>; + status = "disabled"; + }; + + smbus3: smbus3 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c3>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm/st/l4/stm32l412.dtsi b/dts/arm/st/l4/stm32l412.dtsi index f516ccdc57cb..152340889fdf 100644 --- a/dts/arm/st/l4/stm32l412.dtsi +++ b/dts/arm/st/l4/stm32l412.dtsi @@ -74,4 +74,12 @@ compatible = "usb-nop-xceiv"; #phy-cells = <0>; }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/l4/stm32l431.dtsi b/dts/arm/st/l4/stm32l431.dtsi index 9a9892a0f4d0..7fb1d7b4bd4e 100644 --- a/dts/arm/st/l4/stm32l431.dtsi +++ b/dts/arm/st/l4/stm32l431.dtsi @@ -129,4 +129,12 @@ status = "disabled"; }; }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/l4/stm32l433.dtsi b/dts/arm/st/l4/stm32l433.dtsi index c754097bec98..c0e1f0e18bee 100644 --- a/dts/arm/st/l4/stm32l433.dtsi +++ b/dts/arm/st/l4/stm32l433.dtsi @@ -68,4 +68,12 @@ status = "disabled"; }; }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/l4/stm32l451.dtsi b/dts/arm/st/l4/stm32l451.dtsi index b566db4336ad..c22e4ef0820a 100644 --- a/dts/arm/st/l4/stm32l451.dtsi +++ b/dts/arm/st/l4/stm32l451.dtsi @@ -162,4 +162,20 @@ }; }; }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; + + smbus4: smbus4 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c4>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/l4/stm32l471.dtsi b/dts/arm/st/l4/stm32l471.dtsi index c1f5b5978a08..53a7fe28f02c 100644 --- a/dts/arm/st/l4/stm32l471.dtsi +++ b/dts/arm/st/l4/stm32l471.dtsi @@ -274,4 +274,12 @@ die_temp: dietemp { ts-cal2-temp = <110>; }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/l4/stm32l496.dtsi b/dts/arm/st/l4/stm32l496.dtsi index c11eba47796d..4bba5f13ecce 100644 --- a/dts/arm/st/l4/stm32l496.dtsi +++ b/dts/arm/st/l4/stm32l496.dtsi @@ -82,4 +82,12 @@ die_temp: dietemp { ts-cal2-temp = <130>; }; + + smbus4: smbus4 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c4>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/l4/stm32l4p5.dtsi b/dts/arm/st/l4/stm32l4p5.dtsi index 03973dcf077d..648fa936a5fa 100644 --- a/dts/arm/st/l4/stm32l4p5.dtsi +++ b/dts/arm/st/l4/stm32l4p5.dtsi @@ -398,4 +398,20 @@ compatible = "usb-nop-xceiv"; #phy-cells = <0>; }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; + + smbus4: smbus4 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c4>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/l5/stm32l5.dtsi b/dts/arm/st/l5/stm32l5.dtsi index 3886de376316..f9c37b33cd8c 100644 --- a/dts/arm/st/l5/stm32l5.dtsi +++ b/dts/arm/st/l5/stm32l5.dtsi @@ -734,6 +734,22 @@ #phy-cells = <0>; }; + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c1>; + status = "disabled"; + }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; + }; &nvic { diff --git a/dts/arm/st/mp1/stm32mp157.dtsi b/dts/arm/st/mp1/stm32mp157.dtsi index 1877301b9f25..2eec4faa4da3 100644 --- a/dts/arm/st/mp1/stm32mp157.dtsi +++ b/dts/arm/st/mp1/stm32mp157.dtsi @@ -398,6 +398,14 @@ status = "disabled"; }; }; + + smbus5: smbus5 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c5>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm/st/u5/stm32u5.dtsi b/dts/arm/st/u5/stm32u5.dtsi index 7bfe52780b2b..b97e509c8315 100644 --- a/dts/arm/st/u5/stm32u5.dtsi +++ b/dts/arm/st/u5/stm32u5.dtsi @@ -883,6 +883,38 @@ io-channels = <&adc4 14>; status = "disabled"; }; + + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c1>; + status = "disabled"; + }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; + + smbus3: smbus3 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c3>; + status = "disabled"; + }; + + smbus4: smbus4 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c4>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm/st/u5/stm32u595.dtsi b/dts/arm/st/u5/stm32u595.dtsi index db489205f953..3bc16eb120e8 100644 --- a/dts/arm/st/u5/stm32u595.dtsi +++ b/dts/arm/st/u5/stm32u595.dtsi @@ -97,4 +97,20 @@ st,adc-sequencer = ; }; }; + + smbus5: smbus5 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c5>; + status = "disabled"; + }; + + smbus6: smbus6 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c6>; + status = "disabled"; + }; }; diff --git a/dts/arm/st/wb/stm32wb.dtsi b/dts/arm/st/wb/stm32wb.dtsi index f6a1c785b868..d76f2f243f74 100644 --- a/dts/arm/st/wb/stm32wb.dtsi +++ b/dts/arm/st/wb/stm32wb.dtsi @@ -547,6 +547,22 @@ clocks = <&rcc STM32_CLOCK_BUS_AHB3 0x00100000>, <&rcc STM32_SRC_LSE RFWKP_SEL(1)>; }; + + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c1>; + status = "disabled"; + }; + + smbus3: smbus3 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c3>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm/st/wba/stm32wba.dtsi b/dts/arm/st/wba/stm32wba.dtsi index 5e0f67625ee2..d9d718a9898c 100644 --- a/dts/arm/st/wba/stm32wba.dtsi +++ b/dts/arm/st/wba/stm32wba.dtsi @@ -451,6 +451,22 @@ status = "disabled"; }; }; + + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c1>; + status = "disabled"; + }; + + smbus3: smbus3 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c3>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/arm/st/wl/stm32wl.dtsi b/dts/arm/st/wl/stm32wl.dtsi index feeb013af6e3..3dc4b3fcc3f3 100644 --- a/dts/arm/st/wl/stm32wl.dtsi +++ b/dts/arm/st/wl/stm32wl.dtsi @@ -523,6 +523,30 @@ io-channels = <&adc1 14>; status = "disabled"; }; + + smbus1: smbus1 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c1>; + status = "disabled"; + }; + + smbus2: smbus2 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c2>; + status = "disabled"; + }; + + smbus3: smbus3 { + compatible = "st,stm32-smbus"; + #address-cells = <1>; + #size-cells = <0>; + i2c = <&i2c3>; + status = "disabled"; + }; }; &nvic { diff --git a/dts/bindings/smbus/st,stm32-smbus.yaml b/dts/bindings/smbus/st,stm32-smbus.yaml new file mode 100644 index 000000000000..2c93189c178d --- /dev/null +++ b/dts/bindings/smbus/st,stm32-smbus.yaml @@ -0,0 +1,14 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: STM32 SMBus controller + +compatible: "st,stm32-smbus" + +include: [smbus-controller.yaml, pinctrl-device.yaml] + +properties: + i2c: + type: phandle + required: true + description: I2C device which maps to the same address diff --git a/include/zephyr/drivers/i2c/stm32.h b/include/zephyr/drivers/i2c/stm32.h new file mode 100644 index 000000000000..ac943d74664b --- /dev/null +++ b/include/zephyr/drivers/i2c/stm32.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 SILA Embedded Solutions GmbH + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_I2C_STM32_H_ +#define ZEPHYR_INCLUDE_DRIVERS_I2C_STM32_H_ + +#include + +enum i2c_stm32_mode { + I2CSTM32MODE_I2C, + I2CSTM32MODE_SMBUSHOST, + I2CSTM32MODE_SMBUSDEVICE, + I2CSTM32MODE_SMBUSDEVICEARP, +}; + +void i2c_stm32_set_smbus_mode(const struct device *dev, enum i2c_stm32_mode mode); + +#ifdef CONFIG_SMBUS_STM32_SMBALERT +typedef void (*i2c_stm32_smbalert_cb_func_t)(const struct device *dev); + +void i2c_stm32_smbalert_set_callback(const struct device *dev, i2c_stm32_smbalert_cb_func_t func, + const struct device *cb_dev); +void i2c_stm32_smbalert_enable(const struct device *dev); +void i2c_stm32_smbalert_disable(const struct device *dev); +#endif /* CONFIG_SMBUS_STM32_SMBALERT */ + +#endif /* ZEPHYR_INCLUDE_DRIVERS_I2C_STM32_H_ */ diff --git a/include/zephyr/drivers/smbus.h b/include/zephyr/drivers/smbus.h index c4995febb7b6..c0348c367f14 100644 --- a/include/zephyr/drivers/smbus.h +++ b/include/zephyr/drivers/smbus.h @@ -19,6 +19,8 @@ * @{ */ +#include +#include #include #include diff --git a/tests/drivers/smbus/smbus_emul/prj.conf b/tests/drivers/smbus/smbus_emul/prj.conf index 996a530cd41b..99e5c1f89d52 100644 --- a/tests/drivers/smbus/smbus_emul/prj.conf +++ b/tests/drivers/smbus/smbus_emul/prj.conf @@ -1,3 +1,5 @@ CONFIG_ZTEST=y CONFIG_LOG=y CONFIG_ENTROPY_GENERATOR=y +CONFIG_SMBUS=y +CONFIG_SMBUS_LOG_LEVEL_DBG=y diff --git a/tests/drivers/smbus/smbus_emul/src/smbus.c b/tests/drivers/smbus/smbus_emul/src/smbus.c index 1d2a3b5200e0..d42a22d1a23f 100644 --- a/tests/drivers/smbus/smbus_emul/src/smbus.c +++ b/tests/drivers/smbus/smbus_emul/src/smbus.c @@ -14,8 +14,6 @@ #include "emul.h" -#define CONFIG_SMBUS_LOG_LEVEL LOG_LEVEL_DBG - #define PERIPH_ADDR 0x10 static uint8_t mock_sys_in8(io_port_t port)