/* * Copyright (c) 2021 IoT.bzh * * SPDX-License-Identifier: Apache-2.0 */ #define DT_DRV_COMPAT renesas_rcar_i2c #include #include #include #include #include #include #include #include LOG_MODULE_REGISTER(i2c_rcar); #include "i2c-priv.h" typedef void (*init_func_t)(const struct device *dev); struct i2c_rcar_cfg { uint32_t reg_addr; init_func_t init_func; const struct device *clock_dev; struct rcar_cpg_clk mod_clk; uint32_t bitrate; }; struct i2c_rcar_data { uint8_t status_mask; struct k_sem int_sem; }; /* Registers */ #define RCAR_I2C_ICSCR 0x00 /* Slave Control Register */ #define RCAR_I2C_ICMCR 0x04 /* Master Control Register */ #define RCAR_I2C_ICSIER 0x10 /* Slave IRQ Enable */ #define RCAR_I2C_ICMIER 0x14 /* Master IRQ Enable */ #define RCAR_I2C_ICSSR 0x08 /* Slave Status */ #define RCAR_I2C_ICMSR 0x0c /* Master Status */ #define RCAR_I2C_ICCCR 0x18 /* Clock Control Register */ #define RCAR_I2C_ICSAR 0x1c /* Slave Address Register */ #define RCAR_I2C_ICMAR 0x20 /* Master Address Register */ #define RCAR_I2C_ICRXD_ICTXD 0x24 /* Receive Transmit Data Register */ #define RCAR_I2C_ICFBSCR 0x38 /* First Bit Setup Cycle (Gen3).*/ #define RCAR_I2C_ICFBSCR_TCYC17 0x0f /* 17*Tcyc */ #define RCAR_I2C_ICMCR_MDBS BIT(7) /* Master Data Buffer Select */ #define RCAR_I2C_ICMCR_FSCL BIT(6) /* Forced SCL */ #define RCAR_I2C_ICMCR_FSDA BIT(5) /* Forced SDA */ #define RCAR_I2C_ICMCR_OBPC BIT(4) /* Override Bus Pin Control */ #define RCAR_I2C_ICMCR_MIE BIT(3) /* Master Interface Enable */ #define RCAR_I2C_ICMCR_TSBE BIT(2) /* Start Byte Transmission Enable */ #define RCAR_I2C_ICMCR_FSB BIT(1) /* Forced Stop onto the Bus */ #define RCAR_I2C_ICMCR_ESG BIT(0) /* Enable Start Generation */ #define RCAR_I2C_ICMCR_MASTER (RCAR_I2C_ICMCR_MDBS | RCAR_I2C_ICMCR_MIE) /* Bits to manage ICMIER and ICMSR registers */ #define RCAR_I2C_MNR BIT(6) /* Master Nack Received */ #define RCAR_I2C_MAL BIT(5) /* Master Arbitration lost */ #define RCAR_I2C_MST BIT(4) /* Master Stop Transmitted */ #define RCAR_I2C_MDE BIT(3) /* Master Data Empty */ #define RCAR_I2C_MDT BIT(2) /* Master Data Transmitted */ #define RCAR_I2C_MDR BIT(1) /* Master Data Received */ #define RCAR_I2C_MAT BIT(0) /* Master Address Transmitted */ /* Recommended bitrate settings from official documentation */ #define RCAR_I2C_ICCCR_CDF_100_KHZ 6 #define RCAR_I2C_ICCCR_CDF_400_KHZ 6 #define RCAR_I2C_ICCCR_SCGD_100_KHZ 21 #define RCAR_I2C_ICCCR_SCGD_400_KHZ 3 #define MAX_WAIT_US 100 static uint32_t i2c_rcar_read(const struct i2c_rcar_cfg *config, uint32_t offs) { return sys_read32(config->reg_addr + offs); } static void i2c_rcar_write(const struct i2c_rcar_cfg *config, uint32_t offs, uint32_t value) { sys_write32(value, config->reg_addr + offs); } static void i2c_rcar_isr(const struct device *dev) { const struct i2c_rcar_cfg *config = dev->config; struct i2c_rcar_data *data = dev->data; if (((i2c_rcar_read(config, RCAR_I2C_ICMSR)) & data->status_mask) == data->status_mask) { k_sem_give(&data->int_sem); i2c_rcar_write(config, RCAR_I2C_ICMIER, 0); } } static int i2c_rcar_wait_for_state(const struct device *dev, uint8_t mask) { const struct i2c_rcar_cfg *config = dev->config; struct i2c_rcar_data *data = dev->data; data->status_mask = mask; /* Reset interrupts semaphore */ k_sem_reset(&data->int_sem); /* Enable interrupts */ i2c_rcar_write(config, RCAR_I2C_ICMIER, mask); /* Wait for the interrupts */ return k_sem_take(&data->int_sem, K_USEC(MAX_WAIT_US)); } static int i2c_rcar_finish(const struct device *dev) { const struct i2c_rcar_cfg *config = dev->config; int ret; /* Enable STOP generation */ i2c_rcar_write(config, RCAR_I2C_ICMCR, RCAR_I2C_ICMCR_MASTER | RCAR_I2C_ICMCR_FSB); i2c_rcar_write(config, RCAR_I2C_ICMSR, 0); /* Wait for STOP to be transmitted */ ret = i2c_rcar_wait_for_state(dev, RCAR_I2C_MST); i2c_rcar_write(config, RCAR_I2C_ICMSR, 0); /* Disable STOP generation */ i2c_rcar_write(config, RCAR_I2C_ICMCR, RCAR_I2C_ICMCR_MASTER); return ret; } static int i2c_rcar_set_addr(const struct device *dev, uint8_t chip, uint8_t read) { const struct i2c_rcar_cfg *config = dev->config; /* Set slave address & transfer mode */ i2c_rcar_write(config, RCAR_I2C_ICMAR, (chip << 1) | read); /* Reset */ i2c_rcar_write(config, RCAR_I2C_ICMCR, RCAR_I2C_ICMCR_MASTER | RCAR_I2C_ICMCR_ESG); /* Clear Status */ i2c_rcar_write(config, RCAR_I2C_ICMSR, 0); /* Wait for address & transfer mode to be transmitted */ if (read != 0) { return i2c_rcar_wait_for_state(dev, RCAR_I2C_MAT | RCAR_I2C_MDR); } else { return i2c_rcar_wait_for_state(dev, RCAR_I2C_MAT | RCAR_I2C_MDE); } } static int i2c_rcar_transfer_msg(const struct device *dev, struct i2c_msg *msg) { const struct i2c_rcar_cfg *config = dev->config; uint32_t i, reg; int ret = 0; if ((msg->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) { /* Reading as master */ i2c_rcar_write(config, RCAR_I2C_ICMCR, RCAR_I2C_ICMCR_MASTER); for (i = 0; i < msg->len; i++) { if (msg->len - 1 == i) { i2c_rcar_write(config, RCAR_I2C_ICMCR, RCAR_I2C_ICMCR_MASTER | RCAR_I2C_ICMCR_FSB); } /* Start data reception */ reg = i2c_rcar_read(config, RCAR_I2C_ICMSR); reg &= ~RCAR_I2C_MDR; i2c_rcar_write(config, RCAR_I2C_ICMSR, reg); /* Wait for data to be received */ ret = i2c_rcar_wait_for_state(dev, RCAR_I2C_MDR); if (ret != 0) { return ret; } msg->buf[i] = i2c_rcar_read(config, RCAR_I2C_ICRXD_ICTXD) & 0xff; } } else { /* Writing as master */ for (i = 0; i < msg->len; i++) { i2c_rcar_write(config, RCAR_I2C_ICRXD_ICTXD, msg->buf[i]); i2c_rcar_write(config, RCAR_I2C_ICMCR, RCAR_I2C_ICMCR_MASTER); /* Start data transmission */ reg = i2c_rcar_read(config, RCAR_I2C_ICMSR); reg &= ~RCAR_I2C_MDE; i2c_rcar_write(config, RCAR_I2C_ICMSR, reg); /* Wait for all data to be transmitted */ ret = i2c_rcar_wait_for_state(dev, RCAR_I2C_MDE); if (ret != 0) { return ret; } } } return ret; } static int i2c_rcar_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, uint16_t addr) { const struct i2c_rcar_cfg *config = dev->config; uint16_t timeout = 0; int ret; if (!num_msgs) { return 0; } /* Wait for the bus to be available */ while ((i2c_rcar_read(config, RCAR_I2C_ICMCR) & RCAR_I2C_ICMCR_FSDA) && (timeout < 10)) { k_busy_wait(USEC_PER_MSEC); timeout++; } if (timeout == 10) { return -EIO; } do { /* We are not supporting 10-bit addressing */ if ((msgs->flags & I2C_MSG_ADDR_10_BITS) == I2C_MSG_ADDR_10_BITS) { return -ENOTSUP; } /* Send slave address */ if (i2c_rcar_set_addr(dev, addr, !!(msgs->flags & I2C_MSG_READ))) { return -EIO; /* No ACK received */ } /* Transfer data */ if (msgs->len) { ret = i2c_rcar_transfer_msg(dev, msgs); if (ret != 0) { return ret; } } /* Finish the transfer */ if ((msgs->flags & I2C_MSG_STOP) == I2C_MSG_STOP) { ret = i2c_rcar_finish(dev); if (ret != 0) { return ret; } } /* Next message */ msgs++; num_msgs--; } while (num_msgs); /* Complete without error */ return 0; } static int i2c_rcar_configure(const struct device *dev, uint32_t dev_config) { const struct i2c_rcar_cfg *config = dev->config; uint8_t cdf, scgd; /* We only support Master mode */ if ((dev_config & I2C_MODE_CONTROLLER) != I2C_MODE_CONTROLLER) { return -ENOTSUP; } /* We are not supporting 10-bit addressing */ if ((dev_config & I2C_ADDR_10_BITS) == I2C_ADDR_10_BITS) { return -ENOTSUP; } switch (I2C_SPEED_GET(dev_config)) { case I2C_SPEED_STANDARD: /* Use recommended value for 100 kHz bus */ cdf = RCAR_I2C_ICCCR_CDF_100_KHZ; scgd = RCAR_I2C_ICCCR_SCGD_100_KHZ; break; case I2C_SPEED_FAST: /* Use recommended value for 400 kHz bus */ cdf = RCAR_I2C_ICCCR_CDF_400_KHZ; scgd = RCAR_I2C_ICCCR_SCGD_400_KHZ; break; default: return -ENOTSUP; } /* Setting ICCCR to recommended value */ i2c_rcar_write(config, RCAR_I2C_ICCCR, (scgd << 3) | cdf); /* Reset slave mode */ i2c_rcar_write(config, RCAR_I2C_ICSIER, 0); i2c_rcar_write(config, RCAR_I2C_ICSAR, 0); i2c_rcar_write(config, RCAR_I2C_ICSCR, 0); i2c_rcar_write(config, RCAR_I2C_ICSSR, 0); /* Reset master mode */ i2c_rcar_write(config, RCAR_I2C_ICMIER, 0); i2c_rcar_write(config, RCAR_I2C_ICMCR, 0); i2c_rcar_write(config, RCAR_I2C_ICMSR, 0); i2c_rcar_write(config, RCAR_I2C_ICMAR, 0); return 0; } static int i2c_rcar_init(const struct device *dev) { const struct i2c_rcar_cfg *config = dev->config; struct i2c_rcar_data *data = dev->data; uint32_t bitrate_cfg; int ret; k_sem_init(&data->int_sem, 0, 1); if (!device_is_ready(config->clock_dev)) { return -ENODEV; } ret = clock_control_on(config->clock_dev, (clock_control_subsys_t)&config->mod_clk); if (ret != 0) { return ret; } bitrate_cfg = i2c_map_dt_bitrate(config->bitrate); ret = i2c_rcar_configure(dev, I2C_MODE_CONTROLLER | bitrate_cfg); if (ret != 0) { return ret; } config->init_func(dev); return 0; } static const struct i2c_driver_api i2c_rcar_driver_api = { .configure = i2c_rcar_configure, .transfer = i2c_rcar_transfer, #ifdef CONFIG_I2C_RTIO .iodev_submit = i2c_iodev_submit_fallback, #endif }; /* Device Instantiation */ #define I2C_RCAR_INIT(n) \ static void i2c_rcar_##n##_init(const struct device *dev); \ static const struct i2c_rcar_cfg i2c_rcar_cfg_##n = { \ .reg_addr = DT_INST_REG_ADDR(n), \ .init_func = i2c_rcar_##n##_init, \ .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ .bitrate = DT_INST_PROP(n, clock_frequency), \ .mod_clk.module = \ DT_INST_CLOCKS_CELL_BY_IDX(n, 0, module), \ .mod_clk.domain = \ DT_INST_CLOCKS_CELL_BY_IDX(n, 0, domain), \ }; \ \ static struct i2c_rcar_data i2c_rcar_data_##n; \ \ I2C_DEVICE_DT_INST_DEFINE(n, \ i2c_rcar_init, \ NULL, \ &i2c_rcar_data_##n, \ &i2c_rcar_cfg_##n, \ POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \ &i2c_rcar_driver_api \ ); \ static void i2c_rcar_##n##_init(const struct device *dev) \ { \ IRQ_CONNECT(DT_INST_IRQN(n), \ 0, \ i2c_rcar_isr, \ DEVICE_DT_INST_GET(n), 0); \ \ irq_enable(DT_INST_IRQN(n)); \ } DT_INST_FOREACH_STATUS_OKAY(I2C_RCAR_INIT)