zephyr/drivers/i2c/i2c_rcar.c

390 lines
11 KiB
C

/*
* Copyright (c) 2021 IoT.bzh
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT renesas_rcar_i2c
#include <errno.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/renesas_cpg_mssr.h>
#include <zephyr/logging/log.h>
#include <zephyr/irq.h>
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)