/* * Copyright (c) 2016 BayLibre, SAS * Copyright (c) 2017 Linaro Ltd * * SPDX-License-Identifier: Apache-2.0 * */ #ifndef ZEPHYR_DRIVERS_I2C_I2C_LL_STM32_H_ #define ZEPHYR_DRIVERS_I2C_I2C_LL_STM32_H_ #include #include #include #include #include #include #ifdef CONFIG_I2C_STM32_BUS_RECOVERY #include #endif /* CONFIG_I2C_STM32_BUS_RECOVERY */ #include typedef void (*irq_config_func_t)(const struct device *port); #ifdef CONFIG_I2C_STM32_V2 /* Private I2C_MSG_* flags for STM32 I2C */ #define I2C_MSG_STM32_USE_RELOAD_MODE BIT(7) #endif #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_i2c_v2) /** * @brief structure to convey optional i2c timings settings */ struct i2c_config_timing { /* i2c peripheral clock in Hz */ uint32_t periph_clock; /* i2c bus speed in Hz */ uint32_t i2c_speed; /* I2C_TIMINGR register value of i2c v2 peripheral */ uint32_t timing_setting; }; #endif #ifdef CONFIG_I2C_STM32_V2_DMA struct stream { const struct device *dev_dma; int32_t dma_channel; }; #endif /* CONFIG_I2C_STM32_V2_DMA */ struct i2c_stm32_config { #ifdef CONFIG_I2C_STM32_INTERRUPT irq_config_func_t irq_config_func; #endif #ifdef CONFIG_I2C_STM32_BUS_RECOVERY struct gpio_dt_spec scl; struct gpio_dt_spec sda; #endif /* CONFIG_I2C_STM32_BUS_RECOVERY */ const struct stm32_pclken *pclken; size_t pclk_len; I2C_TypeDef *i2c; uint32_t bitrate; const struct pinctrl_dev_config *pcfg; #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_i2c_v2) const struct i2c_config_timing *timings; size_t n_timings; #endif #ifdef CONFIG_I2C_STM32_V2_DMA struct stream tx_dma; struct stream rx_dma; #endif /* CONFIG_I2C_STM32_V2_DMA */ }; struct i2c_stm32_data { #ifdef CONFIG_I2C_RTIO struct i2c_rtio *ctx; uint32_t dev_config; uint8_t *xfer_buf; size_t xfer_len; uint8_t xfer_flags; #ifdef CONFIG_I2C_STM32_V1 size_t msg_len; uint8_t is_restart; uint16_t slave_address; #else uint8_t burst_flags; uint8_t burst_len; #endif /* CONFIG_I2C_STM32_V1 */ #else /* CONFIG_I2C_RTIO */ #ifdef CONFIG_I2C_STM32_INTERRUPT struct k_sem device_sync_sem; #endif /* CONFIG_I2C_STM32_INTERRUPT */ struct k_sem bus_mutex; uint32_t dev_config; #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_i2c_v2) /* Store the current timing structure set by runtime config */ struct i2c_config_timing current_timing; #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_i2c_v2) */ #ifdef CONFIG_I2C_STM32_V1 uint16_t slave_address; #endif /* CONFIG_I2C_STM32_V1 */ struct { #ifdef CONFIG_I2C_STM32_V1 unsigned int is_restart; unsigned int flags; #endif /* CONFIG_I2C_STM32_V1 */ unsigned int is_write; unsigned int is_arlo; unsigned int is_nack; unsigned int is_err; struct i2c_msg *msg; unsigned int len; uint8_t *buf; } current; 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 /* CONFIG_SMBUS_STM32_SMBALERT */ #ifdef CONFIG_I2C_STM32_V2_DMA struct dma_config dma_tx_cfg; struct dma_config dma_rx_cfg; struct dma_block_config dma_blk_cfg; #endif /* CONFIG_I2C_STM32_V2_DMA */ #endif /* CONFIG_I2C_RTIO */ #ifdef CONFIG_I2C_TARGET bool master_active; bool slave_attached; struct i2c_target_config *slave_cfg; #ifdef CONFIG_I2C_STM32_V2 struct i2c_target_config *slave2_cfg; #endif /* CONFIG_I2C_STM32_V2 */ #endif /* CONFIG_I2C_TARGET */ }; #ifdef CONFIG_I2C_RTIO bool i2c_stm32_start(const struct device *dev); int i2c_stm32_msg_start(const struct device *dev, uint8_t flags, uint8_t *buf, size_t buf_len, uint16_t i2c_addr); #else /* CONFIG_I2C_RTIO */ int i2c_stm32_transaction(const struct device *dev, struct i2c_msg msg, uint8_t *next_msg_flags, uint16_t periph); #endif /* CONFIG_I2C_RTIO */ int i2c_stm32_runtime_configure(const struct device *dev, uint32_t config); #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); int i2c_stm32_configure_timing(const struct device *dev, uint32_t clk); #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 I2C_STM32_IRQ_HANDLER_DECL(index) #define I2C_STM32_IRQ_HANDLER_FUNCTION(index) #define I2C_STM32_IRQ_HANDLER(index) #endif /* CONFIG_I2C_STM32_INTERRUPT */ #endif /* ZEPHYR_DRIVERS_I2C_I2C_LL_STM32_H_ */