driver: i2c: infineon: Adding XMC4 I2C driver

- This includes the driver, test app, and sample app
- Only the boards\arm\xmc47_relax_kit board is supported for now

Signed-off-by: Bill Waters <bill.waters@infineon.com>
This commit is contained in:
Bill Waters 2023-07-10 10:25:26 -07:00 committed by Carles Cufí
commit 541482ff20
13 changed files with 745 additions and 12 deletions

View file

@ -9,6 +9,7 @@ supported:
- adc - adc
- dma - dma
- gpio - gpio
- i2c
- spi - spi
- uart - uart
ram: 352 ram: 352

View file

@ -46,6 +46,7 @@ zephyr_library_sources_ifdef(CONFIG_I2C_TCA954X i2c_tca954x.c)
zephyr_library_sources_ifdef(CONFIG_I2C_XEC_V2 i2c_mchp_xec_v2.c) zephyr_library_sources_ifdef(CONFIG_I2C_XEC_V2 i2c_mchp_xec_v2.c)
zephyr_library_sources_ifdef(CONFIG_I2C_GD32 i2c_gd32.c) zephyr_library_sources_ifdef(CONFIG_I2C_GD32 i2c_gd32.c)
zephyr_library_sources_ifdef(CONFIG_I2C_INFINEON_CAT1 i2c_ifx_cat1.c) zephyr_library_sources_ifdef(CONFIG_I2C_INFINEON_CAT1 i2c_ifx_cat1.c)
zephyr_library_sources_ifdef(CONFIG_I2C_INFINEON_XMC4 i2c_ifx_xmc4.c)
zephyr_library_sources_ifdef(CONFIG_I2C_ANDES_ATCIIC100 i2c_andes_atciic100.c) zephyr_library_sources_ifdef(CONFIG_I2C_ANDES_ATCIIC100 i2c_andes_atciic100.c)
zephyr_library_sources_ifdef(CONFIG_I2C_SC18IM704 i2c_sc18im704.c) zephyr_library_sources_ifdef(CONFIG_I2C_SC18IM704 i2c_sc18im704.c)
zephyr_library_sources_ifdef(CONFIG_I2C_SMARTBOND i2c_smartbond.c) zephyr_library_sources_ifdef(CONFIG_I2C_SMARTBOND i2c_smartbond.c)

View file

@ -70,6 +70,7 @@ source "drivers/i2c/Kconfig.rcar"
source "drivers/i2c/Kconfig.tca954x" source "drivers/i2c/Kconfig.tca954x"
source "drivers/i2c/Kconfig.gd32" source "drivers/i2c/Kconfig.gd32"
source "drivers/i2c/Kconfig.ifx_cat1" source "drivers/i2c/Kconfig.ifx_cat1"
source "drivers/i2c/Kconfig.ifx_xmc4"
source "drivers/i2c/Kconfig.andes_atciic100" source "drivers/i2c/Kconfig.andes_atciic100"
source "drivers/i2c/Kconfig.sc18im704" source "drivers/i2c/Kconfig.sc18im704"
source "drivers/i2c/Kconfig.smartbond" source "drivers/i2c/Kconfig.smartbond"

View file

@ -0,0 +1,25 @@
# Infineon XMC4 I2C configuration options
# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or
# an affiliate of Cypress Semiconductor Corporation
#
# SPDX-License-Identifier: Apache-2.0
menuconfig I2C_INFINEON_XMC4
bool "Infineon XMC4 I2C driver"
default y
depends on DT_HAS_INFINEON_XMC4_I2C_ENABLED
help
This option enables the I2C driver for Infineon XMC4 family.
if I2C_INFINEON_XMC4
config I2C_INFINEON_XMC4_TARGET_BUF
int "I2C Target data buffer length"
depends on I2C_INFINEON_XMC4
range 1 1024
default 64
help
Buffer to receive data as an I2C Target.
endif # I2C_INFINEON_XMC4

465
drivers/i2c/i2c_ifx_xmc4.c Normal file
View file

@ -0,0 +1,465 @@
/*
* Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or
* an affiliate of Cypress Semiconductor Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @brief I2C driver for Infineon XMC MCU family.
*/
#define DT_DRV_COMPAT infineon_xmc4_i2c
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/pinctrl.h>
#include <xmc_i2c.h>
#include <xmc_usic.h>
#define USIC_IRQ_MIN 84
#define IRQS_PER_USIC 6
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(i2c_infineon_xmc4, CONFIG_I2C_LOG_LEVEL);
#define I2C_XMC_EVENTS_MASK ( \
XMC_I2C_CH_EVENT_RECEIVE_START | \
XMC_I2C_CH_EVENT_DATA_LOST | \
XMC_I2C_CH_EVENT_TRANSMIT_SHIFT | \
XMC_I2C_CH_EVENT_TRANSMIT_BUFFER | \
XMC_I2C_CH_EVENT_STANDARD_RECEIVE | \
XMC_I2C_CH_EVENT_ALTERNATIVE_RECEIVE | \
XMC_I2C_CH_EVENT_BAUD_RATE_GENERATOR | \
XMC_I2C_CH_EVENT_START_CONDITION_RECEIVED | \
XMC_I2C_CH_EVENT_REPEATED_START_CONDITION_RECEIVED | \
XMC_I2C_CH_EVENT_STOP_CONDITION_RECEIVED | \
XMC_I2C_CH_EVENT_NACK | \
XMC_I2C_CH_EVENT_ARBITRATION_LOST | \
XMC_I2C_CH_EVENT_SLAVE_READ_REQUEST | \
XMC_I2C_CH_EVENT_ERROR | \
XMC_I2C_CH_EVENT_ACK)
#define I2C_XMC_STATUS_FLAG_ERROR_MASK ( \
XMC_I2C_CH_STATUS_FLAG_WRONG_TDF_CODE_FOUND | \
XMC_I2C_CH_STATUS_FLAG_NACK_RECEIVED | \
XMC_I2C_CH_STATUS_FLAG_ARBITRATION_LOST | \
XMC_I2C_CH_STATUS_FLAG_ERROR | \
XMC_I2C_CH_STATUS_FLAG_DATA_LOST_INDICATION)
/* I2C speed */
#define XMC4_I2C_SPEED_STANDARD (100000UL)
#define XMC4_I2C_SPEED_FAST (400000UL)
/* Data structure */
struct ifx_xmc4_i2c_data {
XMC_I2C_CH_CONFIG_t cfg;
struct k_sem operation_sem;
struct k_sem target_sem;
struct i2c_target_config *p_target_config;
uint32_t dev_config;
uint8_t target_wr_byte;
uint8_t target_wr_buffer[CONFIG_I2C_INFINEON_XMC4_TARGET_BUF];
bool ignore_slave_select;
};
/* Device config structure */
struct ifx_xmc4_i2c_config {
XMC_USIC_CH_t *i2c;
const struct pinctrl_dev_config *pcfg;
uint8_t scl_src;
uint8_t sda_src;
uint32_t master_frequency;
void (*irq_config_func)(const struct device *dev);
};
static int ifx_xmc4_i2c_configure(const struct device *dev, uint32_t dev_config)
{
struct ifx_xmc4_i2c_data *data = dev->data;
const struct ifx_xmc4_i2c_config *config = dev->config;
if (dev_config != 0) {
switch (I2C_SPEED_GET(dev_config)) {
case I2C_SPEED_STANDARD:
data->cfg.baudrate = XMC4_I2C_SPEED_STANDARD;
break;
case I2C_SPEED_FAST:
data->cfg.baudrate = XMC4_I2C_SPEED_FAST;
break;
default:
LOG_ERR("Unsupported speed");
return -ERANGE;
}
/* This is deprecated and could be ignored in the future */
if (dev_config & I2C_ADDR_10_BITS) {
LOG_ERR("Use I2C_MSG_ADDR_10_BITS instead of I2C_ADDR_10_BITS");
return -EIO;
}
}
data->dev_config = dev_config;
/* Acquire semaphore (block I2C operation for another thread) */
if (k_sem_take(&data->operation_sem, K_FOREVER)) {
return -EIO;
}
/* Configure the I2C resource */
data->cfg.normal_divider_mode = false;
XMC_I2C_CH_Init(config->i2c, &data->cfg);
XMC_I2C_CH_SetInputSource(config->i2c, XMC_I2C_CH_INPUT_SCL, config->scl_src);
XMC_I2C_CH_SetInputSource(config->i2c, XMC_I2C_CH_INPUT_SDA, config->sda_src);
if (data->dev_config & I2C_MODE_CONTROLLER) {
XMC_USIC_CH_SetFractionalDivider(config->i2c,
XMC_USIC_CH_BRG_CLOCK_DIVIDER_MODE_FRACTIONAL,
1023U);
} else {
config->irq_config_func(dev);
}
XMC_I2C_CH_Start(config->i2c);
/* Release semaphore */
k_sem_give(&data->operation_sem);
return 0;
}
static int ifx_xmc4_i2c_get_config(const struct device *dev, uint32_t *dev_config)
{
struct ifx_xmc4_i2c_data *data = dev->data;
uint32_t config;
switch (data->cfg.baudrate) {
case XMC4_I2C_SPEED_STANDARD:
config = I2C_SPEED_SET(I2C_SPEED_STANDARD);
break;
case XMC4_I2C_SPEED_FAST:
config = I2C_SPEED_SET(I2C_SPEED_FAST);
break;
default:
LOG_ERR("Unsupported speed");
return -ERANGE;
}
if (data->dev_config & I2C_MODE_CONTROLLER) {
config |= I2C_MODE_CONTROLLER;
}
/* Return current configuration */
*dev_config = config;
return 0;
}
static int ifx_xmc4_i2c_msg_validate(struct i2c_msg *msg, uint8_t num_msgs)
{
for (uint32_t i = 0u; i < num_msgs; i++) {
if ((I2C_MSG_ADDR_10_BITS & msg[i].flags) || (msg[i].buf == NULL)) {
return -EINVAL;
}
}
return 0;
}
static int ifx_xmc4_i2c_transfer(const struct device *dev, struct i2c_msg *msg, uint8_t num_msgs,
uint16_t addr)
{
struct ifx_xmc4_i2c_data *data = dev->data;
const struct ifx_xmc4_i2c_config *config = dev->config;
XMC_I2C_CH_CMD_t cmd_type;
if (!num_msgs) {
return 0;
}
/* Acquire semaphore (block I2C transfer for another thread) */
if (k_sem_take(&data->operation_sem, K_FOREVER)) {
return -EIO;
}
/* This function checks if msg.buf is not NULL and if target address is not 10 bit. */
if (ifx_xmc4_i2c_msg_validate(msg, num_msgs) != 0) {
k_sem_give(&data->operation_sem);
return -EINVAL;
}
for (uint32_t msg_index = 0u; msg_index < num_msgs; msg_index++) {
XMC_I2C_CH_ClearStatusFlag(config->i2c, 0xFFFFFFFF);
if ((msg_index == 0) || (msg[msg_index].flags & I2C_MSG_RESTART)) {
/* Send START conditon */
cmd_type = ((msg[msg_index].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) ?
XMC_I2C_CH_CMD_READ : XMC_I2C_CH_CMD_WRITE;
if (msg[msg_index].flags & I2C_MSG_RESTART) {
XMC_I2C_CH_MasterRepeatedStart(config->i2c, addr << 1, cmd_type);
} else {
XMC_I2C_CH_MasterStart(config->i2c, addr << 1, cmd_type);
}
/* Wait for acknowledge */
while ((XMC_I2C_CH_GetStatusFlag(config->i2c) &
XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U) {
/* wait for ACK from slave */
if (XMC_I2C_CH_GetStatusFlag(config->i2c) &
I2C_XMC_STATUS_FLAG_ERROR_MASK) {
k_sem_give(&data->operation_sem);
return -EIO;
}
}
XMC_I2C_CH_ClearStatusFlag(config->i2c,
XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
}
for (uint32_t buf_index = 0u; buf_index < msg[msg_index].len; buf_index++) {
if (cmd_type == XMC_I2C_CH_CMD_WRITE) {
/* Transmit next command from I2C master to I2C slave */
XMC_I2C_CH_MasterTransmit(config->i2c,
msg[msg_index].buf[buf_index]);
/* Wait for acknowledge */
while ((XMC_I2C_CH_GetStatusFlag(config->i2c) &
XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U) {
/* wait for ACK from slave */
if (XMC_I2C_CH_GetStatusFlag(config->i2c) &
I2C_XMC_STATUS_FLAG_ERROR_MASK) {
k_sem_give(&data->operation_sem);
return -EIO;
}
}
XMC_I2C_CH_ClearStatusFlag(config->i2c,
XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
/* Wait until TX FIFO is empty */
while (!XMC_USIC_CH_TXFIFO_IsEmpty(config->i2c)) {
/* wait until all data is sent by HW */
if (XMC_I2C_CH_GetStatusFlag(config->i2c) &
I2C_XMC_STATUS_FLAG_ERROR_MASK) {
k_sem_give(&data->operation_sem);
return -EIO;
}
}
} else {
if (buf_index == (msg[msg_index].len - 1)) {
XMC_I2C_CH_MasterReceiveNack(config->i2c);
} else {
XMC_I2C_CH_MasterReceiveAck(config->i2c);
}
while ((XMC_I2C_CH_GetStatusFlag(config->i2c) &
(XMC_I2C_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION |
XMC_I2C_CH_STATUS_FLAG_RECEIVE_INDICATION)) == 0U) {
/* wait for data byte from slave */
if (XMC_I2C_CH_GetStatusFlag(config->i2c) &
I2C_XMC_STATUS_FLAG_ERROR_MASK) {
k_sem_give(&data->operation_sem);
return -EIO;
}
}
XMC_I2C_CH_ClearStatusFlag(config->i2c,
XMC_I2C_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION |
XMC_I2C_CH_STATUS_FLAG_RECEIVE_INDICATION);
msg[msg_index].buf[buf_index] =
XMC_I2C_CH_GetReceivedData(config->i2c);
}
}
/* Send STOP conditon */
if (msg[msg_index].flags & I2C_MSG_STOP) {
XMC_I2C_CH_MasterStop(config->i2c);
}
}
/* Release semaphore (After I2C transfer is complete) */
k_sem_give(&data->operation_sem);
return 0;
}
static int ifx_xmc4_i2c_init(const struct device *dev)
{
struct ifx_xmc4_i2c_data *data = dev->data;
const struct ifx_xmc4_i2c_config *config = dev->config;
int ret;
/* Configure semaphores */
ret = k_sem_init(&data->operation_sem, 1, 1);
if (ret) {
return ret;
}
ret = k_sem_init(&data->target_sem, 1, 1);
if (ret) {
return ret;
}
/* Configure dt provided device signals when available */
ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
if (ret < 0) {
return ret;
}
return 0;
}
static int ifx_xmc4_i2c_target_register(const struct device *dev, struct i2c_target_config *cfg)
{
struct ifx_xmc4_i2c_data *data = (struct ifx_xmc4_i2c_data *)dev->data;
if (!cfg ||
!cfg->callbacks->read_requested ||
!cfg->callbacks->read_processed ||
!cfg->callbacks->write_requested ||
!cfg->callbacks->write_received ||
!cfg->callbacks->stop) {
return -EINVAL;
}
if (cfg->flags & I2C_TARGET_FLAGS_ADDR_10_BITS) {
return -ENOTSUP;
}
/* Acquire semaphore (block I2C operation for another thread) */
if (k_sem_take(&data->target_sem, K_FOREVER)) {
return -EIO;
}
data->p_target_config = cfg;
data->cfg.address = cfg->address << 1;
if (ifx_xmc4_i2c_configure(dev, I2C_SPEED_SET(I2C_SPEED_STANDARD)) != 0) {
/* Release semaphore */
k_sem_give(&data->target_sem);
return -EIO;
}
k_sem_give(&data->target_sem);
return 0;
}
static int ifx_xmc4_i2c_target_unregister(const struct device *dev, struct i2c_target_config *cfg)
{
struct ifx_xmc4_i2c_data *data = (struct ifx_xmc4_i2c_data *)dev->data;
const struct ifx_xmc4_i2c_config *config = dev->config;
/* Acquire semaphore (block I2C operation for another thread) */
if (k_sem_take(&data->operation_sem, K_FOREVER)) {
return -EIO;
}
data->p_target_config = NULL;
XMC_I2C_CH_DisableEvent(config->i2c, I2C_XMC_EVENTS_MASK);
/* Release semaphore */
k_sem_give(&data->operation_sem);
return 0;
}
static void i2c_xmc4_isr(const struct device *dev)
{
struct ifx_xmc4_i2c_data *data = dev->data;
const struct ifx_xmc4_i2c_config *config = dev->config;
const struct i2c_target_callbacks *callbacks = data->p_target_config->callbacks;
uint32_t status = XMC_I2C_CH_GetStatusFlag(config->i2c);
while (status) {
XMC_I2C_CH_ClearStatusFlag(config->i2c, status);
if (status & XMC_I2C_CH_STATUS_FLAG_STOP_CONDITION_RECEIVED) {
/* Flush the TX buffer */
XMC_USIC_CH_SetTransmitBufferStatus(config->i2c,
XMC_USIC_CH_TBUF_STATUS_SET_IDLE);
callbacks->stop(data->p_target_config);
break;
}
if (!data->ignore_slave_select && (status & XMC_I2C_CH_STATUS_FLAG_SLAVE_SELECT)) {
data->ignore_slave_select = true;
/* Start a slave read */
if (status & XMC_I2C_CH_STATUS_FLAG_SLAVE_READ_REQUESTED) {
callbacks->read_requested(data->p_target_config,
&data->target_wr_byte);
XMC_I2C_CH_SlaveTransmit(config->i2c, data->target_wr_byte);
} else {
callbacks->write_requested(data->p_target_config);
}
}
/* Continue a slave read */
if (status & XMC_I2C_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION) {
callbacks->read_processed(data->p_target_config, &data->target_wr_byte);
XMC_I2C_CH_SlaveTransmit(config->i2c, data->target_wr_byte);
}
/* Start/Continue a slave write */
if (status & (XMC_I2C_CH_STATUS_FLAG_RECEIVE_INDICATION |
XMC_I2C_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION)) {
callbacks->write_received(data->p_target_config,
XMC_I2C_CH_GetReceivedData(config->i2c));
}
if ((status & XMC_I2C_CH_STATUS_FLAG_START_CONDITION_RECEIVED) ||
(status & XMC_I2C_CH_STATUS_FLAG_REPEATED_START_CONDITION_RECEIVED)) {
data->ignore_slave_select = false;
}
status = XMC_I2C_CH_GetStatusFlag(config->i2c);
}
}
/* I2C API structure */
static const struct i2c_driver_api i2c_xmc4_driver_api = {
.configure = ifx_xmc4_i2c_configure,
.transfer = ifx_xmc4_i2c_transfer,
.get_config = ifx_xmc4_i2c_get_config,
.target_register = ifx_xmc4_i2c_target_register,
.target_unregister = ifx_xmc4_i2c_target_unregister};
/* Macros for I2C instance declaration */
#define XMC4_IRQ_HANDLER_INIT(index) \
static void i2c_xmc4_irq_setup_##index(const struct device *dev) \
{ \
const struct ifx_xmc4_i2c_config *config = dev->config; \
uint8_t irq_num = DT_INST_IRQN(index); \
uint8_t service_request = (irq_num - USIC_IRQ_MIN) % IRQS_PER_USIC; \
\
XMC_I2C_CH_SelectInterruptNodePointer(config->i2c, \
XMC_I2C_CH_INTERRUPT_NODE_POINTER_RECEIVE, service_request); \
XMC_I2C_CH_SelectInterruptNodePointer(config->i2c, \
XMC_I2C_CH_INTERRUPT_NODE_POINTER_ALTERNATE_RECEIVE, service_request); \
\
XMC_I2C_CH_EnableEvent(config->i2c, I2C_XMC_EVENTS_MASK); \
\
IRQ_CONNECT(DT_INST_IRQN(index), DT_INST_IRQ(index, priority), i2c_xmc4_isr, \
DEVICE_DT_INST_GET(index), 0); \
\
irq_enable(irq_num); \
}
#define XMC4_IRQ_HANDLER_STRUCT_INIT(index) .irq_config_func = i2c_xmc4_irq_setup_##index
#define INFINEON_XMC4_I2C_INIT(n) \
PINCTRL_DT_INST_DEFINE(n); \
XMC4_IRQ_HANDLER_INIT(n) \
\
static struct ifx_xmc4_i2c_data ifx_xmc4_i2c_data##n; \
\
static const struct ifx_xmc4_i2c_config i2c_xmc4_cfg_##n = { \
.i2c = (XMC_USIC_CH_t *)DT_INST_REG_ADDR(n), \
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
.scl_src = DT_INST_ENUM_IDX(n, scl_src), \
.sda_src = DT_INST_ENUM_IDX(n, sda_src), \
.master_frequency = DT_INST_PROP_OR(n, clock_frequency, XMC4_I2C_SPEED_STANDARD), \
XMC4_IRQ_HANDLER_STRUCT_INIT(n) \
}; \
\
I2C_DEVICE_DT_INST_DEFINE(n, ifx_xmc4_i2c_init, NULL, &ifx_xmc4_i2c_data##n, \
&i2c_xmc4_cfg_##n, POST_KERNEL, \
CONFIG_I2C_INIT_PRIORITY, &i2c_xmc4_driver_api);
DT_INST_FOREACH_STATUS_OKAY(INFINEON_XMC4_I2C_INIT)

View file

@ -593,4 +593,125 @@
pinmux = <XMC4XXX_PINMUX_SET(6, 6, 0)>; pinmux = <XMC4XXX_PINMUX_SET(6, 6, 0)>;
hwctrl = "periph2"; hwctrl = "periph2";
}; };
/omit-if-no-ref/ i2c_controller_scl_p0_8_u0c0: i2c_controller_scl_p0_8_u0c0 {
pinmux = <XMC4XXX_PINMUX_SET(0, 8, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_scl_p1_1_u0c0: i2c_controller_scl_p1_1_u0c0 {
pinmux = <XMC4XXX_PINMUX_SET(1, 1, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_scl_p2_4_u0c1: i2c_controller_scl_p2_4_u0c1 {
pinmux = <XMC4XXX_PINMUX_SET(2, 4, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_scl_p3_0_u0c1: i2c_controller_scl_p3_0_u0c1 {
pinmux = <XMC4XXX_PINMUX_SET(3, 0, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_scl_p6_2_u0c1: i2c_controller_scl_p6_2_u0c1 {
pinmux = <XMC4XXX_PINMUX_SET(6, 2, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_scl_p0_11_u1c0: i2c_controller_scl_p0_11_u1c0 {
pinmux = <XMC4XXX_PINMUX_SET(0, 11, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_scl_p5_8_u1c0: i2c_controller_scl_p5_8_u1c0 {
pinmux = <XMC4XXX_PINMUX_SET(5, 8, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_scl_p0_10_u1c1: i2c_controller_scl_p0_10_u1c1 {
pinmux = <XMC4XXX_PINMUX_SET(0, 10, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_scl_p0_13_u1c1: i2c_controller_scl_p0_13_u1c1 {
pinmux = <XMC4XXX_PINMUX_SET(0, 13, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_scl_p5_2_u2c0: i2c_controller_scl_p5_2_u2c0 {
pinmux = <XMC4XXX_PINMUX_SET(5, 2, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_scl_p3_6_u2c1: i2c_controller_scl_p3_6_u2c1 {
pinmux = <XMC4XXX_PINMUX_SET(3, 6, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_sda_p1_5_u0c0: i2c_controller_sda_p1_5_u0c0 {
pinmux = <XMC4XXX_PINMUX_SET(1, 5, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_sda_p2_5_u0c1: i2c_controller_sda_p2_5_u0c1 {
pinmux = <XMC4XXX_PINMUX_SET(2, 5, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_sda_p3_13_u0c1: i2c_controller_sda_p3_13_u0c1 {
pinmux = <XMC4XXX_PINMUX_SET(3, 13, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_sda_p0_5_u1c0: i2c_controller_sda_p0_5_u1c0 {
pinmux = <XMC4XXX_PINMUX_SET(0, 5, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_sda_p2_14_u1c0: i2c_controller_sda_p2_14_u1c0 {
pinmux = <XMC4XXX_PINMUX_SET(2, 14, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_sda_p3_15_u1c1: i2c_controller_sda_p3_15_u1c1 {
pinmux = <XMC4XXX_PINMUX_SET(3, 15, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_sda_p4_2_u1c1: i2c_controller_sda_p4_2_u1c1 {
pinmux = <XMC4XXX_PINMUX_SET(4, 2, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_sda_p5_0_u2c0: i2c_controller_sda_p5_0_u2c0 {
pinmux = <XMC4XXX_PINMUX_SET(5, 0, 0x1A)>;
};
/omit-if-no-ref/ i2c_controller_sda_p3_5_u2c1: i2c_controller_sda_p3_5_u2c1 {
pinmux = <XMC4XXX_PINMUX_SET(3, 5, 0x1A)>;
};
/omit-if-no-ref/ i2c_target_scl_p0_8_u0c0: i2c_target_scl_p0_8_u0c0 {
pinmux = <XMC4XXX_PINMUX_SET(0, 8, 0x19)>;
};
/omit-if-no-ref/ i2c_target_scl_p1_1_u0c0: i2c_target_scl_p1_1_u0c0 {
pinmux = <XMC4XXX_PINMUX_SET(1, 1, 0x19)>;
};
/omit-if-no-ref/ i2c_target_scl_p2_4_u0c1: i2c_target_scl_p2_4_u0c1 {
pinmux = <XMC4XXX_PINMUX_SET(2, 4, 0x19)>;
};
/omit-if-no-ref/ i2c_target_scl_p3_0_u0c1: i2c_target_scl_p3_0_u0c1 {
pinmux = <XMC4XXX_PINMUX_SET(3, 0, 0x19)>;
};
/omit-if-no-ref/ i2c_target_scl_p6_2_u0c1: i2c_target_scl_p6_2_u0c1 {
pinmux = <XMC4XXX_PINMUX_SET(6, 2, 0x19)>;
};
/omit-if-no-ref/ i2c_target_scl_p0_11_u1c0: i2c_target_scl_p0_11_u1c0 {
pinmux = <XMC4XXX_PINMUX_SET(0, 11, 0x19)>;
};
/omit-if-no-ref/ i2c_target_scl_p5_8_u1c0: i2c_target_scl_p5_8_u1c0 {
pinmux = <XMC4XXX_PINMUX_SET(5, 8, 0x19)>;
};
/omit-if-no-ref/ i2c_target_scl_p0_10_u1c1: i2c_target_scl_p0_10_u1c1 {
pinmux = <XMC4XXX_PINMUX_SET(0, 10, 0x19)>;
};
/omit-if-no-ref/ i2c_target_scl_p0_13_u1c1: i2c_target_scl_p0_13_u1c1 {
pinmux = <XMC4XXX_PINMUX_SET(0, 13, 0x19)>;
};
/omit-if-no-ref/ i2c_target_scl_p5_2_u2c0: i2c_target_scl_p5_2_u2c0 {
pinmux = <XMC4XXX_PINMUX_SET(5, 2, 0x19)>;
};
/omit-if-no-ref/ i2c_target_scl_p3_6_u2c1: i2c_target_scl_p3_6_u2c1 {
pinmux = <XMC4XXX_PINMUX_SET(3, 6, 0x19)>;
};
/omit-if-no-ref/ i2c_target_sda_p1_5_u0c0: i2c_target_sda_p1_5_u0c0 {
pinmux = <XMC4XXX_PINMUX_SET(1, 5, 0x19)>;
};
/omit-if-no-ref/ i2c_target_sda_p2_5_u0c1: i2c_target_sda_p2_5_u0c1 {
pinmux = <XMC4XXX_PINMUX_SET(2, 5, 0x19)>;
};
/omit-if-no-ref/ i2c_target_sda_p3_13_u0c1: i2c_target_sda_p3_13_u0c1 {
pinmux = <XMC4XXX_PINMUX_SET(3, 13, 0x19)>;
};
/omit-if-no-ref/ i2c_target_sda_p0_5_u1c0: i2c_target_sda_p0_5_u1c0 {
pinmux = <XMC4XXX_PINMUX_SET(0, 5, 0x19)>;
};
/omit-if-no-ref/ i2c_target_sda_p2_14_u1c0: i2c_target_sda_p2_14_u1c0 {
pinmux = <XMC4XXX_PINMUX_SET(2, 14, 0x19)>;
};
/omit-if-no-ref/ i2c_target_sda_p3_15_u1c1: i2c_target_sda_p3_15_u1c1 {
pinmux = <XMC4XXX_PINMUX_SET(3, 15, 0x19)>;
};
/omit-if-no-ref/ i2c_target_sda_p4_2_u1c1: i2c_target_sda_p4_2_u1c1 {
pinmux = <XMC4XXX_PINMUX_SET(4, 2, 0x19)>;
};
/omit-if-no-ref/ i2c_target_sda_p5_0_u2c0: i2c_target_sda_p5_0_u2c0 {
pinmux = <XMC4XXX_PINMUX_SET(5, 0, 0x19)>;
};
/omit-if-no-ref/ i2c_target_sda_p3_5_u2c1: i2c_target_sda_p3_5_u2c1 {
pinmux = <XMC4XXX_PINMUX_SET(3, 5, 0x19)>;
};
}; };

View file

@ -21,10 +21,10 @@ properties:
pinctrl-0: pinctrl-0:
description: | description: |
PORT pin configuration for SCL, SDA signals. PORT pin configuration for SCL, SDA signals.
We expect that the phandles will reference pinctrl nodes.These We expect that the phandles will reference pinctrl nodes. These
nodes will have a nodelabel that matches the Infineon SoC Pinctrl nodes will have a nodelabel that matches the Infineon SoC Pinctrl
defines and have following defines and have following
format: p<port>_<pin><peripheral inst>_<signal>. format: p<port>_<pin>_<peripheral inst>_<signal>.
Examples: Examples:
pinctrl-0 = <&p6_0_scb3_i2c_scl &p6_1_scb3_i2c_sda>; pinctrl-0 = <&p6_0_scb3_i2c_scl &p6_1_scb3_i2c_sda>;

View file

@ -0,0 +1,77 @@
# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or
# an affiliate of Cypress Semiconductor Corporation
#
# SPDX-License-Identifier: Apache-2.0
description: Infineon XMC4 I2C
compatible: "infineon,xmc4-i2c"
include: [i2c-controller.yaml, pinctrl-device.yaml]
properties:
reg:
type: array
required: true
scl-src:
description: |
Connects the I2C clock line (USIC DX0 input) to a specific GPIO pin.
The USIC DX0 input is a multiplexer which connects to different GPIO pins.
Refer to the XMC4XXX reference manual for the GPIO pin/mux mappings.
type: string
required: true
enum:
- "DX0A"
- "DX0B"
- "DX0C"
- "DX0D"
- "DX0E"
- "DX0F"
- "DX0G"
sda-src:
description: |
Connects the I2C data line (USIC DX0 input) to a specific GPIO pin.
The USIC DX0 input is a multiplexer which connects to different GPIO pins.
Refer to the XMC4XXX reference manual for the GPIO pin/mux mappings.
type: string
required: true
enum:
- "DX0A"
- "DX0B"
- "DX0C"
- "DX0D"
- "DX0E"
- "DX0F"
- "DX0G"
interrupts:
type: array
required: true
description: |
IRQ number and priority to use for interrupt driven by I2C.
Each USIC must use a certain interrupt range:
USIC0 = [84, 89]
USIC1 = [90, 95]
USIC2 = [96, 101]
pinctrl-0:
description: |
PORT pin configuration for SCL, SDA signals.
We expect that the phandles will reference pinctrl nodes. These
nodes will have a nodelabel that matches the Infineon SoC Pinctrl
defines and have following
format: <signal>_p<port>_<pin>_<peripheral inst>
Examples:
pinctrl-0 = <&i2c_scl_p5_2_u2c0 &i2c_sda_p5_0_u2c0>;
required: true
pinctrl-names:
required: true
clock-frequency:
type: int
description: |
Frequency that the I2C bus runs

View file

@ -16,33 +16,33 @@
#define XMC4XXX_PIN_MASK 0xf #define XMC4XXX_PIN_MASK 0xf
#define XMC4XXX_ALT_POS 8 #define XMC4XXX_ALT_POS 8
#define XMC4XXX_ALT_MASK 0xf #define XMC4XXX_ALT_MASK 0x1f
#define XMC4XXX_PULL_DOWN_POS 12 #define XMC4XXX_PULL_DOWN_POS 13
#define XMC4XXX_PULL_DOWN_MASK 0x1 #define XMC4XXX_PULL_DOWN_MASK 0x1
#define XMC4XXX_PULL_UP_POS 13 #define XMC4XXX_PULL_UP_POS 14
#define XMC4XXX_PULL_UP_MASK 0x1 #define XMC4XXX_PULL_UP_MASK 0x1
#define XMC4XXX_PUSH_PULL_POS 14 #define XMC4XXX_PUSH_PULL_POS 15
#define XMC4XXX_PUSH_PULL_MASK 0x1 #define XMC4XXX_PUSH_PULL_MASK 0x1
#define XMC4XXX_OPEN_DRAIN_POS 15 #define XMC4XXX_OPEN_DRAIN_POS 16
#define XMC4XXX_OPEN_DRAIN_MASK 0x1 #define XMC4XXX_OPEN_DRAIN_MASK 0x1
#define XMC4XXX_OUT_HIGH_POS 16 #define XMC4XXX_OUT_HIGH_POS 17
#define XMC4XXX_OUT_HIGH_MASK 0x1 #define XMC4XXX_OUT_HIGH_MASK 0x1
#define XMC4XXX_OUT_LOW_POS 17 #define XMC4XXX_OUT_LOW_POS 18
#define XMC4XXX_OUT_LOW_MASK 0x1 #define XMC4XXX_OUT_LOW_MASK 0x1
#define XMC4XXX_INV_INPUT_POS 18 #define XMC4XXX_INV_INPUT_POS 19
#define XMC4XXX_INV_INPUT_MASK 0x1 #define XMC4XXX_INV_INPUT_MASK 0x1
#define XMC4XXX_DRIVE_POS 19 #define XMC4XXX_DRIVE_POS 20
#define XMC4XXX_DRIVE_MASK 0x7 #define XMC4XXX_DRIVE_MASK 0x7
#define XMC4XXX_HWCTRL_POS 22 #define XMC4XXX_HWCTRL_POS 23
#define XMC4XXX_HWCTRL_MASK 0x3 #define XMC4XXX_HWCTRL_MASK 0x3
/* Setters and getters */ /* Setters and getters */

View file

@ -40,4 +40,9 @@ config HAS_XMCLIB_SPI
help help
Enable XMCLIB SPI Enable XMCLIB SPI
config HAS_XMCLIB_I2C
bool
help
Enable XMCLIB I2C
endif # HAS_XMCLIB endif # HAS_XMCLIB

View file

@ -18,5 +18,6 @@ config SOC_SERIES_XMC_4XXX
select HAS_XMCLIB_VADC select HAS_XMCLIB_VADC
select HAS_XMCLIB_DMA select HAS_XMCLIB_DMA
select HAS_XMCLIB_SPI select HAS_XMCLIB_SPI
select HAS_XMCLIB_I2C
help help
Enable support for XMC 4xxx MCU series Enable support for XMC 4xxx MCU series

View file

@ -0,0 +1 @@
CONFIG_I2C_INFINEON_XMC4_TARGET_BUF=128

View file

@ -0,0 +1,35 @@
/*
* Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or
* an affiliate of Cypress Semiconductor Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
/ {
aliases {
i2c-0 = &usic0ch1;
};
};
&i2c_controller_scl_p6_2_u0c1 {
drive-strength = "strong-sharp-edge";
hwctrl = "disabled";
};
&i2c_controller_sda_p3_13_u0c1 {
drive-strength = "strong-soft-edge";
hwctrl = "disabled";
};
&usic0ch1 {
compatible = "infineon,xmc4-i2c";
pinctrl-0 = <&i2c_controller_scl_p6_2_u0c1 &i2c_controller_sda_p3_13_u0c1>;
pinctrl-names = "default";
scl-src = "DX0C";
sda-src = "DX0D";
interrupts = <86 1>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
};