Add support for transfer of more than 256 byte in STM32 v1 and v2 RTIO drivers. Signed-off-by: Etienne Carriere <etienne.carriere@st.com>
205 lines
6.2 KiB
C
205 lines
6.2 KiB
C
/*
|
|
* 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 <zephyr/drivers/i2c/stm32.h>
|
|
#include <zephyr/kernel.h>
|
|
#include <zephyr/devicetree.h>
|
|
#include <zephyr/pm/device.h>
|
|
#include <zephyr/pm/device_runtime.h>
|
|
#include <zephyr/logging/log.h>
|
|
|
|
#ifdef CONFIG_I2C_STM32_BUS_RECOVERY
|
|
#include <zephyr/drivers/gpio.h>
|
|
#endif /* CONFIG_I2C_STM32_BUS_RECOVERY */
|
|
|
|
#include <zephyr/drivers/dma.h>
|
|
|
|
typedef void (*irq_config_func_t)(const struct device *port);
|
|
|
|
#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;
|
|
#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;
|
|
#ifdef CONFIG_I2C_TARGET
|
|
bool master_active;
|
|
struct i2c_target_config *slave_cfg;
|
|
#ifdef CONFIG_I2C_STM32_V2
|
|
struct i2c_target_config *slave2_cfg;
|
|
#endif /* CONFIG_I2C_STM32_V2 */
|
|
bool slave_attached;
|
|
#endif /* CONFIG_I2C_TARGET */
|
|
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_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);
|
|
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 */
|
|
#endif /* CONFIG_I2C_RTIO */
|
|
|
|
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_ */
|