diff --git a/boards/renesas/rzg3s_smarc/doc/index.rst b/boards/renesas/rzg3s_smarc/doc/index.rst index 09bcec22e75d..af340fa804c1 100644 --- a/boards/renesas/rzg3s_smarc/doc/index.rst +++ b/boards/renesas/rzg3s_smarc/doc/index.rst @@ -65,6 +65,8 @@ and the following hardware features: +-----------+------------+-------------------------------------+ | GPIO | on-chip | gpio | +-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-------------------------------------+ | UART | on-chip | serial | +-----------+------------+-------------------------------------+ | GTM | on-chip | counter | diff --git a/boards/renesas/rzg3s_smarc/rzg3s_smarc_r9a08g045s33gbg_cm33.yaml b/boards/renesas/rzg3s_smarc/rzg3s_smarc_r9a08g045s33gbg_cm33.yaml index 1d4a4eeeae13..a13e03a51437 100644 --- a/boards/renesas/rzg3s_smarc/rzg3s_smarc_r9a08g045s33gbg_cm33.yaml +++ b/boards/renesas/rzg3s_smarc/rzg3s_smarc_r9a08g045s33gbg_cm33.yaml @@ -7,6 +7,7 @@ toolchain: - gnuarmemb supported: - uart + - i2c - gpio - counter - pwm diff --git a/drivers/i2c/CMakeLists.txt b/drivers/i2c/CMakeLists.txt index 6419417db1c8..5c1e25211954 100644 --- a/drivers/i2c/CMakeLists.txt +++ b/drivers/i2c/CMakeLists.txt @@ -52,6 +52,7 @@ zephyr_library_sources_ifdef(CONFIG_I2C_NXP_II2C i2c_nxp_ii2c.c) zephyr_library_sources_ifdef(CONFIG_I2C_OMAP i2c_omap.c) zephyr_library_sources_ifdef(CONFIG_I2C_RCAR i2c_rcar.c) zephyr_library_sources_ifdef(CONFIG_I2C_RENESAS_RA_IIC i2c_renesas_ra_iic.c) +zephyr_library_sources_ifdef(CONFIG_I2C_RENESAS_RZ_RIIC i2c_renesas_rz_riic.c) zephyr_library_sources_ifdef(CONFIG_I2C_RV32M1_LPI2C i2c_rv32m1_lpi2c.c) zephyr_library_sources_ifdef(CONFIG_I2C_SAM0 i2c_sam0.c) zephyr_library_sources_ifdef(CONFIG_I2C_SAM_TWI i2c_sam_twi.c) diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index c1180acf51d6..aa8d83e9e6f8 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -143,6 +143,7 @@ source "drivers/i2c/Kconfig.numaker" source "drivers/i2c/Kconfig.omap" source "drivers/i2c/Kconfig.rcar" source "drivers/i2c/Kconfig.renesas_ra" +source "drivers/i2c/Kconfig.renesas_rz" source "drivers/i2c/Kconfig.sam0" source "drivers/i2c/Kconfig.sam_twihs" source "drivers/i2c/Kconfig.sbcon" diff --git a/drivers/i2c/Kconfig.renesas_rz b/drivers/i2c/Kconfig.renesas_rz new file mode 100644 index 000000000000..16ebd19c54ec --- /dev/null +++ b/drivers/i2c/Kconfig.renesas_rz @@ -0,0 +1,10 @@ +# Copyright (c) 2024 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +config I2C_RENESAS_RZ_RIIC + bool "Renesas RZ I2C RIIC Master" + default y + depends on DT_HAS_RENESAS_RZ_RIIC_ENABLED + select USE_RZ_FSP_RIIC_MASTER + help + Enable Renesas RZ I2C RIIC Driver. diff --git a/drivers/i2c/i2c_renesas_rz_riic.c b/drivers/i2c/i2c_renesas_rz_riic.c new file mode 100644 index 000000000000..8a43561ef590 --- /dev/null +++ b/drivers/i2c/i2c_renesas_rz_riic.c @@ -0,0 +1,539 @@ +/* + * Copyright (c) 2024 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_rz_riic + +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(renesas_rz_riic); + +typedef void (*init_func_t)(const struct device *dev); + +struct i2c_rz_riic_config { + const struct pinctrl_dev_config *pin_config; + i2c_master_cfg_t *fsp_cfg; + riic_master_extended_cfg_t *riic_master_ext_cfg; + const i2c_master_api_t *fsp_api; + double rise_time_s; + double fall_time_s; + double duty_cycle_percent; +}; + +struct i2c_rz_riic_data { + i2c_master_ctrl_t *fsp_ctrl; + struct k_mutex bus_mutex; + struct k_sem complete_sem; + i2c_master_event_t event; + uint32_t dev_config; +}; + +/* IIC master clock setting calculation function. */ +static void calc_riic_master_clock_setting(const struct device *dev, const uint32_t fsp_i2c_rate, + iic_master_clock_settings_t *clk_cfg); + +/* FSP interruption handlers. */ +void riic_master_rxi_isr(void); +void riic_master_txi_isr(void); +void riic_master_tei_isr(void); +void riic_master_naki_isr(void); +void riic_master_sti_isr(void); +void riic_master_spi_isr(void); +void riic_master_ali_isr(void); +void riic_master_tmoi_isr(void); + +struct rz_riic_master_bitrate { + uint32_t bitrate; + uint32_t duty; + uint32_t divider; + uint32_t brl; + uint32_t brh; + double duty_error_percent; +}; + +static int i2c_rz_riic_configure(const struct device *dev, uint32_t dev_config) +{ + const struct i2c_rz_riic_config *config = dev->config; + struct i2c_rz_riic_data *data = dev->data; + + if (!(dev_config & I2C_MODE_CONTROLLER)) { + LOG_ERR("Only I2C Master mode supported."); + return -EIO; + } + + switch (I2C_SPEED_GET(dev_config)) { + case I2C_SPEED_STANDARD: + config->fsp_cfg->rate = I2C_MASTER_RATE_STANDARD; + break; + case I2C_SPEED_FAST: + config->fsp_cfg->rate = I2C_MASTER_RATE_FAST; + break; + case I2C_SPEED_FAST_PLUS: + config->fsp_cfg->rate = I2C_MASTER_RATE_FASTPLUS; + break; + default: + LOG_ERR("%s: Invalid I2C speed rate flag: %d", __func__, I2C_SPEED_GET(dev_config)); + return -EIO; + } + + /* Recalc clock setting after updating config. */ + calc_riic_master_clock_setting(dev, config->fsp_cfg->rate, + &config->riic_master_ext_cfg->clock_settings); + + config->fsp_api->close(data->fsp_ctrl); + config->fsp_api->open(data->fsp_ctrl, config->fsp_cfg); + + /* save current devconfig. */ + data->dev_config = dev_config; + + return 0; +} + +static int i2c_rz_riic_get_config(const struct device *dev, uint32_t *dev_config) +{ + struct i2c_rz_riic_data *data = (struct i2c_rz_riic_data *const)dev->data; + *dev_config = data->dev_config; + + return 0; +} + +#define OPERATION(msg) (((struct i2c_msg *)msg)->flags & I2C_MSG_RW_MASK) + +static int i2c_rz_riic_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, + uint16_t addr) +{ + const struct i2c_rz_riic_config *config = dev->config; + struct i2c_rz_riic_data *data = (struct i2c_rz_riic_data *const)dev->data; + struct i2c_msg *current, *next; + fsp_err_t err = FSP_SUCCESS; + int ret = 0; + + if (!num_msgs) { + return 0; + } + + /* Check for validity of all messages before transfer */ + current = msgs; + + /* + * Set I2C_MSG_RESTART flag on first message in order to send start + * condition + */ + current->flags |= I2C_MSG_RESTART; + + for (int i = 1; i <= num_msgs; i++) { + if (i < num_msgs) { + next = current + 1; + + /* + * Restart condition between messages + * of different directions is required + */ + if (OPERATION(current) != OPERATION(next)) { + if (!(next->flags & I2C_MSG_RESTART)) { + LOG_ERR("%s: Restart condition between messages of " + "different directions is required." + "Current/Total: [%d/%d]", + __func__, i, num_msgs); + ret = -EIO; + break; + } + } + + /* Stop condition is only allowed on last message */ + if (current->flags & I2C_MSG_STOP) { + LOG_ERR("%s: Invalid stop flag. Stop condition is only allowed on " + "last message. " + "Current/Total: [%d/%d]", + __func__, i, num_msgs); + ret = -EIO; + break; + } + } else { + current->flags |= I2C_MSG_STOP; + } + + current++; + } + + if (ret) { + return ret; + } + + k_mutex_lock(&data->bus_mutex, K_FOREVER); + + /* Set destination address with configured address mode before sending msg. */ + + i2c_master_addr_mode_t addr_mode = 0; + + if (I2C_MSG_ADDR_10_BITS & data->dev_config) { + addr_mode = I2C_MASTER_ADDR_MODE_10BIT; + } else { + addr_mode = I2C_MASTER_ADDR_MODE_7BIT; + } + + config->fsp_api->slaveAddressSet(data->fsp_ctrl, addr, addr_mode); + + /* Process input `msgs`. */ + + current = msgs; + + while (num_msgs > 0) { + if (num_msgs > 1) { + next = current + 1; + } else { + next = NULL; + } + + if (current->flags & I2C_MSG_READ) { + err = config->fsp_api->read(data->fsp_ctrl, current->buf, current->len, + next != NULL && + (next->flags & I2C_MSG_RESTART)); + } else { + err = config->fsp_api->write(data->fsp_ctrl, current->buf, current->len, + next != NULL && + (next->flags & I2C_MSG_RESTART)); + } + + if (err != FSP_SUCCESS) { + switch (err) { + case FSP_ERR_IN_USE: + LOG_ERR("%s: Bus busy condition. Another transfer was in progress.", + __func__); + break; + default: + /* Should not reach here. */ + LOG_ERR("%s: Unknown error. FSP_ERR=%d\n", __func__, err); + break; + } + + ret = -EIO; + goto RELEASE_BUS; + } + + /* Wait for callback to return. */ + k_sem_take(&data->complete_sem, K_FOREVER); + + /* Handle event msg from callback. */ + switch (data->event) { + case I2C_MASTER_EVENT_ABORTED: + LOG_ERR("%s: %s failed.", __func__, + (current->flags & I2C_MSG_READ) ? "Read" : "Write"); + ret = -EIO; + goto RELEASE_BUS; + case I2C_MASTER_EVENT_RX_COMPLETE: + break; + case I2C_MASTER_EVENT_TX_COMPLETE: + break; + default: + break; + } + + current++; + num_msgs--; + } + +RELEASE_BUS: + k_mutex_unlock(&data->bus_mutex); + + return ret; +} + +static void i2c_rz_riic_callback(i2c_master_callback_args_t *p_args) +{ + const struct device *dev = p_args->p_context; + struct i2c_rz_riic_data *data = dev->data; + + data->event = p_args->event; + + k_sem_give(&data->complete_sem); +} + +static int i2c_rz_riic_init(const struct device *dev) +{ + const struct i2c_rz_riic_config *config = dev->config; + struct i2c_rz_riic_data *data = dev->data; + fsp_err_t err = FSP_SUCCESS; + int ret = 0; + + /* Configure dt provided device signals when available */ + if (!config->pin_config) { + ret = pinctrl_apply_state(config->pin_config, PINCTRL_STATE_DEFAULT); + + if (ret < 0) { + LOG_ERR("%s: pinctrl config failed.", __func__); + return ret; + } + } + + k_mutex_init(&data->bus_mutex); + k_sem_init(&data->complete_sem, 0, 1); + + switch (config->fsp_cfg->rate) { + case I2C_MASTER_RATE_STANDARD: + case I2C_MASTER_RATE_FAST: + case I2C_MASTER_RATE_FASTPLUS: + calc_riic_master_clock_setting(dev, config->fsp_cfg->rate, + &config->riic_master_ext_cfg->clock_settings); + config->riic_master_ext_cfg->timeout_mode = IIC_MASTER_TIMEOUT_MODE_SHORT; + config->riic_master_ext_cfg->timeout_scl_low = IIC_MASTER_TIMEOUT_SCL_LOW_ENABLED; + break; + default: + LOG_ERR("%s: Invalid I2C speed rate: %d", __func__, config->fsp_cfg->rate); + return -ENOTSUP; + } + + err = config->fsp_api->open(data->fsp_ctrl, config->fsp_cfg); + + if (err != FSP_SUCCESS) { + LOG_ERR("I2C initialization failed"); + return -EIO; + } + + return 0; +} + +static void calc_riic_master_bitrate(const struct i2c_rz_riic_config *config, + uint32_t total_brl_brh, uint32_t brh, uint32_t divider, + struct rz_riic_master_bitrate *result) +{ + const uint32_t noise_filter_stages = config->riic_master_ext_cfg->noise_filter_stage; + const double rise_time_s = config->rise_time_s; + const double fall_time_s = config->fall_time_s; + const double requested_duty = config->duty_cycle_percent; + const uint32_t peripheral_clock = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_P0CLK); + uint32_t constant_add = 0; + + /* A constant is added to BRL and BRH in all formulas. This constand is 3 + nf when CKS == + * 0, or 2 + nf when CKS != 0. + */ + if (divider == 0) { + constant_add = 3 + noise_filter_stages; + } else { + /* All dividers other than 0 use an addition of 2 + noise_filter_stages. */ + constant_add = 2 + noise_filter_stages; + } + + /* Converts all divided numbers to double to avoid data loss. */ + double divided_p0 = (peripheral_clock >> divider); + + result->bitrate = + 1 / ((total_brl_brh + 2 * constant_add) / divided_p0 + rise_time_s + fall_time_s); + result->duty = + 100 * + ((rise_time_s + ((brh + constant_add) / divided_p0)) / + (rise_time_s + fall_time_s + ((total_brl_brh + 2 * constant_add)) / divided_p0)); + result->divider = divider; + result->brh = brh; + result->brl = total_brl_brh - brh; + result->duty_error_percent = + (result->duty > requested_duty ? (result->duty - requested_duty) + : (requested_duty - result->duty)) / + requested_duty; +} + +static void calc_riic_master_clock_setting(const struct device *dev, const uint32_t fsp_i2c_rate, + iic_master_clock_settings_t *clk_cfg) +{ + const struct i2c_rz_riic_config *config = dev->config; + const uint32_t noise_filter_stages = config->riic_master_ext_cfg->noise_filter_stage; + const double rise_time_s = config->rise_time_s; + const double fall_time_s = config->fall_time_s; + const uint32_t requested_duty = config->duty_cycle_percent; + const uint32_t peripheral_clock = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_P0CLK); + + uint32_t requested_bitrate = 0; + + switch (fsp_i2c_rate) { + case I2C_MASTER_RATE_STANDARD: + case I2C_MASTER_RATE_FAST: + case I2C_MASTER_RATE_FASTPLUS: + requested_bitrate = fsp_i2c_rate; + break; + default: + LOG_ERR("%s: Invalid I2C speed rate: %d", __func__, fsp_i2c_rate); + return; + } + + /* Start with maximum possible bitrate. */ + uint32_t min_brh = noise_filter_stages + 1; + uint32_t min_brl_brh = 2 * min_brh; + struct rz_riic_master_bitrate bitrate = {}; + + calc_riic_master_bitrate(config, min_brl_brh, min_brh, 0, &bitrate); + + /* Start with the smallest divider because it gives the most resolution. */ + uint32_t constant_add = 3 + noise_filter_stages; + + for (int temp_divider = 0; temp_divider <= 7; ++temp_divider) { + if (1 == temp_divider) { + /* All dividers other than 0 use an addition of 2 + noise_filter_stages. */ + constant_add = 2 + noise_filter_stages; + } + + /* If the requested bitrate cannot be achieved with this divider, continue. */ + double divided_p0 = (peripheral_clock >> temp_divider); + uint32_t total_brl_brh = + ceil(((1 / (double)requested_bitrate) - (rise_time_s + fall_time_s)) * + divided_p0 - + (2 * constant_add)); + + if ((total_brl_brh > 62) || (total_brl_brh < min_brl_brh)) { + continue; + } + + uint32_t temp_brh = total_brl_brh * requested_duty / 100; + + if (temp_brh < min_brh) { + temp_brh = min_brh; + } + + /* Calculate the actual bitrate and duty cycle. */ + struct rz_riic_master_bitrate temp_bitrate = {}; + + calc_riic_master_bitrate(config, total_brl_brh, temp_brh, temp_divider, + &temp_bitrate); + + /* Adjust duty cycle down if it helps. */ + struct rz_riic_master_bitrate test_bitrate = temp_bitrate; + + while (test_bitrate.duty > requested_duty) { + temp_brh -= 1; + + if ((temp_brh < min_brh) || ((total_brl_brh - temp_brh) > 31)) { + break; + } + + struct rz_riic_master_bitrate new_bitrate = {}; + + calc_riic_master_bitrate(config, total_brl_brh, temp_brh, temp_divider, + &new_bitrate); + + if (new_bitrate.duty_error_percent < temp_bitrate.duty_error_percent) { + temp_bitrate = new_bitrate; + } else { + break; + } + } + + /* Adjust duty cycle up if it helps. */ + while (test_bitrate.duty < requested_duty) { + ++temp_brh; + + if ((temp_brh > total_brl_brh) || (temp_brh > 31) || + ((total_brl_brh - temp_brh) < min_brh)) { + break; + } + + struct rz_riic_master_bitrate new_bitrate = {}; + + calc_riic_master_bitrate(config, total_brl_brh, temp_brh, temp_divider, + &new_bitrate); + + if (new_bitrate.duty_error_percent < temp_bitrate.duty_error_percent) { + temp_bitrate = new_bitrate; + } else { + break; + } + } + + if ((temp_bitrate.brh < 32) && (temp_bitrate.brl < 32)) { + /* Valid setting found. */ + bitrate = temp_bitrate; + break; + } + } + + clk_cfg->brl_value = bitrate.brl; + clk_cfg->brh_value = bitrate.brh; + clk_cfg->cks_value = bitrate.divider; +} + +static DEVICE_API(i2c, i2c_rz_riic_driver_api) = { + .configure = i2c_rz_riic_configure, + .get_config = i2c_rz_riic_get_config, + .transfer = i2c_rz_riic_transfer, +}; + +#define I2C_RZG_IRQ_CONNECT(index, irq_name, isr) \ + do { \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(index, irq_name, irq), \ + DT_INST_IRQ_BY_NAME(index, irq_name, priority), isr, \ + DEVICE_DT_INST_GET(index), 0); \ + irq_enable(DT_INST_IRQ_BY_NAME(index, irq_name, irq)); \ + } while (0) + +#define I2C_RZG_CONFIG_FUNC(index) \ + I2C_RZG_IRQ_CONNECT(index, rxi, riic_master_rxi_isr); \ + I2C_RZG_IRQ_CONNECT(index, txi, riic_master_txi_isr); \ + I2C_RZG_IRQ_CONNECT(index, tei, riic_master_tei_isr); \ + I2C_RZG_IRQ_CONNECT(index, naki, riic_master_naki_isr); \ + I2C_RZG_IRQ_CONNECT(index, sti, riic_master_sti_isr); \ + I2C_RZG_IRQ_CONNECT(index, spi, riic_master_spi_isr); \ + I2C_RZG_IRQ_CONNECT(index, ali, riic_master_ali_isr); \ + I2C_RZG_IRQ_CONNECT(index, tmoi, riic_master_tmoi_isr); + +#define I2C_RZG_RIIC_INIT(index) \ + static const double RZG_RIIC_MASTER_DIV_TIME_NS = 1000000000; \ + \ + static riic_master_extended_cfg_t g_i2c_master##index##_extend = { \ + .noise_filter_stage = DT_INST_PROP(index, noise_filter_stages), \ + .naki_irq = DT_INST_IRQ_BY_NAME(index, naki, irq), \ + .sti_irq = DT_INST_IRQ_BY_NAME(index, sti, irq), \ + .spi_irq = DT_INST_IRQ_BY_NAME(index, spi, irq), \ + .ali_irq = DT_INST_IRQ_BY_NAME(index, ali, irq), \ + .tmoi_irq = DT_INST_IRQ_BY_NAME(index, tmoi, irq), \ + }; \ + \ + static i2c_master_cfg_t g_i2c_master##index##_cfg = { \ + .channel = DT_INST_PROP(index, channel), \ + .rate = DT_INST_PROP(index, clock_frequency), \ + .slave = 0x00, \ + .addr_mode = I2C_MASTER_ADDR_MODE_7BIT, \ + .p_transfer_tx = NULL, \ + .p_transfer_rx = NULL, \ + .p_callback = i2c_rz_riic_callback, \ + .p_context = DEVICE_DT_GET(DT_DRV_INST(index)), \ + .rxi_irq = DT_INST_IRQ_BY_NAME(index, rxi, irq), \ + .txi_irq = DT_INST_IRQ_BY_NAME(index, txi, irq), \ + .tei_irq = DT_INST_IRQ_BY_NAME(index, tei, irq), \ + .ipl = DT_INST_IRQ_BY_NAME(index, rxi, priority), \ + .p_extend = &g_i2c_master##index##_extend, \ + }; \ + \ + PINCTRL_DT_INST_DEFINE(index); \ + \ + static struct i2c_rz_riic_config i2c_rz_riic_config_##index = { \ + .pin_config = PINCTRL_DT_INST_DEV_CONFIG_GET(index), \ + .fsp_cfg = &g_i2c_master##index##_cfg, \ + .riic_master_ext_cfg = &g_i2c_master##index##_extend, \ + .fsp_api = &g_i2c_master_on_iic, \ + .rise_time_s = DT_INST_PROP(index, rise_time_ns) / RZG_RIIC_MASTER_DIV_TIME_NS, \ + .fall_time_s = DT_INST_PROP(index, fall_time_ns) / RZG_RIIC_MASTER_DIV_TIME_NS, \ + .duty_cycle_percent = DT_INST_PROP(index, duty_cycle_percent), \ + }; \ + \ + static iic_master_instance_ctrl_t g_i2c_master##index##_ctrl; \ + \ + static struct i2c_rz_riic_data i2c_rz_riic_data_##index = { \ + .fsp_ctrl = (i2c_master_ctrl_t *)&g_i2c_master##index##_ctrl, \ + }; \ + \ + static int i2c_rz_riic_init_##index(const struct device *dev) \ + { \ + I2C_RZG_CONFIG_FUNC(index) \ + return i2c_rz_riic_init(dev); \ + }; \ + \ + I2C_DEVICE_DT_INST_DEFINE(index, i2c_rz_riic_init_##index, NULL, \ + &i2c_rz_riic_data_##index, &i2c_rz_riic_config_##index, \ + PRE_KERNEL_2, CONFIG_I2C_INIT_PRIORITY, \ + &i2c_rz_riic_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(I2C_RZG_RIIC_INIT) diff --git a/dts/arm/renesas/rz/rzg/r9a08g045.dtsi b/dts/arm/renesas/rz/rzg/r9a08g045.dtsi index 14614b4d22c1..78430453c3be 100644 --- a/dts/arm/renesas/rz/rzg/r9a08g045.dtsi +++ b/dts/arm/renesas/rz/rzg/r9a08g045.dtsi @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -433,6 +434,55 @@ status = "disabled"; }; + i2c0: i2c@40090000 { + compatible = "renesas,rz-riic"; + channel = <0>; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40090000 0x15>; + interrupts = <257 1>, <258 1>, <259 1>, <260 1>, + <261 1>, <262 1>, <263 1>, <264 1>; + interrupt-names = "tei", "naki", "spi", "sti", "ali", "tmoi", "rxi", "txi"; + status = "disabled"; + }; + i2c1: i2c@40090400 { + compatible = "renesas,rz-riic"; + channel = <1>; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40090400 0x15>; + interrupts = <265 1>, <266 1>, <267 1>, <268 1>, + <269 1>, <270 1>, <271 1>, <272 1>; + interrupt-names = "tei", "naki", "spi", "sti", "ali", "tmoi", "rxi", "txi"; + status = "disabled"; + }; + i2c2: i2c@40090800 { + compatible = "renesas,rz-riic"; + channel = <2>; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40090800 0x15>; + interrupts = <273 1>, <274 1>, <275 1>, <276 1>, + <277 1>, <278 1>, <279 1>, <280 1>; + interrupt-names = "tei", "naki", "spi", "sti", "ali", "tmoi", "rxi", "txi"; + status = "disabled"; + }; + i2c3: i2c@40090c00 { + compatible = "renesas,rz-riic"; + channel = <3>; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40090c00 0x15>; + interrupts = <281 1>, <282 1>, <283 1>, <284 1>, + <285 1>, <286 1>, <287 1>, <288 1>; + interrupt-names = "tei", "naki", "spi", "sti", "ali", "tmoi", "rxi", "txi"; + status = "disabled"; + }; + gtm0: gtm@42801000 { compatible = "renesas,rz-gtm"; reg = <0x42801000 0x30>; diff --git a/dts/bindings/i2c/renesas,rz-riic.yaml b/dts/bindings/i2c/renesas,rz-riic.yaml new file mode 100644 index 000000000000..42b7fdc5d96b --- /dev/null +++ b/dts/bindings/i2c/renesas,rz-riic.yaml @@ -0,0 +1,44 @@ +# Copyright (c) 2024 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RZ/G3S I2C controller + +compatible: "renesas,rz-riic" + +include: [i2c-controller.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + channel: + required: true + type: int + + interrupts: + required: true + + rise-time-ns: + type: int + default: 120 + description: | + Number of nanoseconds the SCL signal takes to rise; t(r) in the I2C specification. + + fall-time-ns: + type: int + default: 120 + description: | + Number of nanoseconds the SCL signal takes to fall; t(f) in the I2C specification. + + duty-cycle-percent: + type: int + default: 50 + + noise-filter-stages: + type: int + default: 1 + enum: + - 1 + - 2 + - 3 + - 4 diff --git a/modules/Kconfig.renesas_fsp b/modules/Kconfig.renesas_fsp index 6b35466490b3..6db624701728 100644 --- a/modules/Kconfig.renesas_fsp +++ b/modules/Kconfig.renesas_fsp @@ -168,6 +168,11 @@ config USE_RZ_FSP_SCIF_UART help Enable RZ FSP SCIF UART driver +config USE_RZ_FSP_RIIC_MASTER + bool + help + Enable RZ FSP RIIC MASTER driver + config USE_RZ_FSP_GTM bool help diff --git a/tests/drivers/i2c/i2c_api/boards/rzg3s_smarc_r9a08g045s33gbg_cm33.conf b/tests/drivers/i2c/i2c_api/boards/rzg3s_smarc_r9a08g045s33gbg_cm33.conf new file mode 100644 index 000000000000..83547b4fe725 --- /dev/null +++ b/tests/drivers/i2c/i2c_api/boards/rzg3s_smarc_r9a08g045s33gbg_cm33.conf @@ -0,0 +1 @@ +CONFIG_SENSOR_GY271_QMC=y diff --git a/tests/drivers/i2c/i2c_api/boards/rzg3s_smarc_r9a08g045s33gbg_cm33.overlay b/tests/drivers/i2c/i2c_api/boards/rzg3s_smarc_r9a08g045s33gbg_cm33.overlay new file mode 100644 index 000000000000..65163d4b5283 --- /dev/null +++ b/tests/drivers/i2c/i2c_api/boards/rzg3s_smarc_r9a08g045s33gbg_cm33.overlay @@ -0,0 +1,9 @@ +/ { + aliases { + i2c-0 = &i2c0; + }; +}; + +&i2c0 { + status = "okay"; +};