diff --git a/drivers/i2c/i2c_ene_kb1200.c b/drivers/i2c/i2c_ene_kb1200.c index 359f99793e4..e6853d38c7c 100644 --- a/drivers/i2c/i2c_ene_kb1200.c +++ b/drivers/i2c/i2c_ene_kb1200.c @@ -12,13 +12,20 @@ #include #include +#include +LOG_MODULE_REGISTER(i2c_ene, CONFIG_I2C_LOG_LEVEL); + +#include "i2c-priv.h" + struct i2c_kb1200_config { struct fsmbm_regs *fsmbm; + uint32_t clock_freq; const struct pinctrl_dev_config *pcfg; }; struct i2c_kb1200_data { - struct k_sem mutex; + struct k_sem lock; + struct k_sem wait; volatile uint8_t *msg_buf; volatile uint32_t msg_len; volatile uint8_t msg_flags; @@ -39,6 +46,7 @@ static void i2c_kb1200_isr(const struct device *dev) uint32_t remain = data->msg_len - data->index; uint32_t send_bytes = remain > FSMBM_BUFFER_SIZE ? FSMBM_BUFFER_SIZE : remain; + memcpy((void *)&config->fsmbm->FSMBMDAT[0], (void *)&data->msg_buf[data->index], send_bytes); data->index += send_bytes; @@ -52,7 +60,7 @@ static void i2c_kb1200_isr(const struct device *dev) } else if (config->fsmbm->FSMBMPF & FSMBM_COMPLETE_EVENT) { /* complete */ if (((config->fsmbm->FSMBMSTS & FSMBM_STS_MASK) == FSMBM_SMBUS_BUSY) && - ((config->fsmbm->FSMBMFRT & ___STOP) == ___NONE)) { + ((config->fsmbm->FSMBMFRT & FRT_STOP) == FRT_NONE)) { /* while packet finish without STOP, the error message is * FSMBM_SMBUS_BUSY */ @@ -61,10 +69,12 @@ static void i2c_kb1200_isr(const struct device *dev) data->err_code = config->fsmbm->FSMBMSTS & FSMBM_STS_MASK; } data->state = STATE_COMPLETE; + k_sem_give(&data->wait); config->fsmbm->FSMBMPF = FSMBM_COMPLETE_EVENT; } else { data->err_code = config->fsmbm->FSMBMSTS & FSMBM_STS_MASK; data->state = STATE_COMPLETE; + k_sem_give(&data->wait); } } else if (data->state == STATE_RECEIVING) { uint32_t remain = data->msg_len - data->index; @@ -89,7 +99,7 @@ static void i2c_kb1200_isr(const struct device *dev) } else if (config->fsmbm->FSMBMPF & FSMBM_COMPLETE_EVENT) { /* complete */ if (((config->fsmbm->FSMBMSTS & FSMBM_STS_MASK) == FSMBM_SMBUS_BUSY) && - ((config->fsmbm->FSMBMFRT & ___STOP) == ___NONE)) { + ((config->fsmbm->FSMBMFRT & FRT_STOP) == FRT_NONE)) { /* while packet finish without STOP, the error message is * FSMBM_SMBUS_BUSY */ @@ -98,13 +108,16 @@ static void i2c_kb1200_isr(const struct device *dev) data->err_code = config->fsmbm->FSMBMSTS & FSMBM_STS_MASK; } data->state = STATE_COMPLETE; + k_sem_give(&data->wait); config->fsmbm->FSMBMPF = FSMBM_COMPLETE_EVENT; } else { data->err_code = config->fsmbm->FSMBMSTS & FSMBM_STS_MASK; data->state = STATE_COMPLETE; + k_sem_give(&data->wait); } } else if (data->state == STATE_COMPLETE) { config->fsmbm->FSMBMPF = (FSMBM_COMPLETE_EVENT | FSMBM_BLOCK_FINISH_EVENT); + k_sem_give(&data->wait); } } @@ -112,14 +125,16 @@ static int i2c_kb1200_poll_write(const struct device *dev, struct i2c_msg msg, u { const struct i2c_kb1200_config *config = dev->config; struct i2c_kb1200_data *data = dev->data; - uint8_t send_bytes; + uint32_t send_bytes; + int ret; + k_sem_reset(&data->wait); if (msg.flags & I2C_MSG_STOP) { /* No CMD, No CNT, No PEC, with STOP*/ - config->fsmbm->FSMBMFRT = ___STOP; + config->fsmbm->FSMBMFRT = FRT_STOP; } else { /* No CMD, No CNT, No PEC, no STOP*/ - config->fsmbm->FSMBMFRT = ___NONE; + config->fsmbm->FSMBMFRT = FRT_NONE; } data->msg_len = msg.len; data->msg_buf = msg.buf; @@ -135,7 +150,7 @@ static int i2c_kb1200_poll_write(const struct device *dev, struct i2c_msg msg, u data->state = STATE_SENDING; config->fsmbm->FSMBMCMD = 0; - config->fsmbm->FSMBMADR = (addr & ~BIT(0)) | FSMBM_WRITE; + config->fsmbm->FSMBMADR = (addr << 1) | FSMBM_WRITE; config->fsmbm->FSMBMPF = (FSMBM_COMPLETE_EVENT | FSMBM_BLOCK_FINISH_EVENT); /* If data over bufferSize increase 1 to force continue transmit */ if (msg.len >= (FSMBM_BUFFER_SIZE + 1)) { @@ -145,15 +160,19 @@ static int i2c_kb1200_poll_write(const struct device *dev, struct i2c_msg msg, u } config->fsmbm->FSMBMIE = (FSMBM_COMPLETE_EVENT | FSMBM_BLOCK_FINISH_EVENT); config->fsmbm->FSMBMPRTC_P = FLEXIBLE_PROTOCOL; - while (data->state != STATE_COMPLETE) { - ; + + /* Wait until ISR or timeout */ + ret = k_sem_take(&data->wait, K_MSEC(FSMBM_MAX_TIMEOUT)); + if (ret == -EAGAIN) { + data->err_code |= FSMBM_SDA_TIMEOUT; } data->state = STATE_IDLE; - if (data->err_code != 0) { + if (data->err_code) { /* reset HW */ config->fsmbm->FSMBMCFG |= FSMBM_HW_RESET; return data->err_code; } + return 0; } @@ -161,13 +180,18 @@ static int i2c_kb1200_poll_read(const struct device *dev, struct i2c_msg msg, ui { const struct i2c_kb1200_config *config = dev->config; struct i2c_kb1200_data *data = dev->data; + int ret; + k_sem_reset(&data->wait); + if ((msg.flags & I2C_MSG_RESTART) && !(msg.flags & I2C_MSG_STOP)) { + LOG_ERR("ENE i2c format not support."); + } if (msg.flags & I2C_MSG_STOP) { /* No CMD, No CNT, No PEC, with STOP*/ - config->fsmbm->FSMBMFRT = ___STOP; + config->fsmbm->FSMBMFRT = FRT_STOP; } else { /* No CMD, No CNT, No PEC, no STOP*/ - config->fsmbm->FSMBMFRT = ___NONE; + config->fsmbm->FSMBMFRT = FRT_NONE; } data->msg_len = msg.len; data->msg_buf = msg.buf; @@ -178,7 +202,7 @@ static int i2c_kb1200_poll_read(const struct device *dev, struct i2c_msg msg, ui data->state = STATE_RECEIVING; config->fsmbm->FSMBMCMD = 0; - config->fsmbm->FSMBMADR = (addr & ~BIT(0)) | FSMBM_READ; + config->fsmbm->FSMBMADR = (addr << 1) | FSMBM_READ; config->fsmbm->FSMBMPF = (FSMBM_COMPLETE_EVENT | FSMBM_BLOCK_FINISH_EVENT); /* If data over bufferSize increase 1 to force continue receive */ if (msg.len >= (FSMBM_BUFFER_SIZE + 1)) { @@ -188,15 +212,20 @@ static int i2c_kb1200_poll_read(const struct device *dev, struct i2c_msg msg, ui } config->fsmbm->FSMBMIE = (FSMBM_COMPLETE_EVENT | FSMBM_BLOCK_FINISH_EVENT); config->fsmbm->FSMBMPRTC_P = FLEXIBLE_PROTOCOL; - while (data->state != STATE_COMPLETE) { - ; + + /* Wait until ISR or timeout */ + ret = k_sem_take(&data->wait, K_MSEC(FSMBM_MAX_TIMEOUT)); + if (ret == -EAGAIN) { + data->err_code |= FSMBM_SDA_TIMEOUT; } data->state = STATE_IDLE; - if (data->err_code != 0) { + + if (data->err_code) { /* reset HW */ config->fsmbm->FSMBMCFG |= FSMBM_HW_RESET; return data->err_code; } + return 0; } @@ -204,6 +233,7 @@ static int i2c_kb1200_poll_read(const struct device *dev, struct i2c_msg msg, ui static int i2c_kb1200_configure(const struct device *dev, uint32_t dev_config) { const struct i2c_kb1200_config *config = dev->config; + uint32_t speed; if (!(dev_config & I2C_MODE_CONTROLLER)) { return -ENOTSUP; @@ -213,7 +243,7 @@ static int i2c_kb1200_configure(const struct device *dev, uint32_t dev_config) return -ENOTSUP; } - uint32_t speed = I2C_SPEED_GET(dev_config); + speed = I2C_SPEED_GET(dev_config); switch (speed) { case I2C_SPEED_STANDARD: @@ -242,7 +272,7 @@ static int i2c_kb1200_get_config(const struct device *dev, uint32_t *dev_config) const struct i2c_kb1200_config *config = dev->config; if ((config->fsmbm->FSMBMCFG & FSMBM_FUNCTION_ENABLE) == 0x00) { - printk("Cannot find i2c controller on 0x%p!\n", config->fsmbm); + LOG_ERR("Cannot find i2c controller on 0x%p!", config->fsmbm); return -EIO; } @@ -251,6 +281,8 @@ static int i2c_kb1200_get_config(const struct device *dev, uint32_t *dev_config) *dev_config = I2C_MODE_CONTROLLER | I2C_SPEED_SET(I2C_SPEED_STANDARD); break; case FSMBM_CLK_400K: + case FSMBM_CLK_500K: + case FSMBM_CLK_666K: *dev_config = I2C_MODE_CONTROLLER | I2C_SPEED_SET(I2C_SPEED_FAST); break; case FSMBM_CLK_1M: @@ -267,27 +299,27 @@ static int i2c_kb1200_transfer(const struct device *dev, struct i2c_msg *msgs, u uint16_t addr) { struct i2c_kb1200_data *data = dev->data; - int ret; + int ret = 0; - /* get the mutex */ - k_sem_take(&data->mutex, K_FOREVER); + /* lock */ + k_sem_take(&data->lock, K_FOREVER); for (int i = 0U; i < num_msgs; i++) { if ((msgs[i].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) { ret = i2c_kb1200_poll_write(dev, msgs[i], addr); if (ret) { - printk("%s Write error: 0x%X\n", dev->name, ret); + ret = -EIO; break; } } else { ret = i2c_kb1200_poll_read(dev, msgs[i], addr); if (ret) { - printk("%s Read error: 0x%X\n", dev->name, ret); + ret = -EIO; break; } } } - /* release the mutex */ - k_sem_give(&data->mutex); + /* release the lock */ + k_sem_give(&data->lock); return ret; } @@ -332,14 +364,23 @@ static int i2c_kb1200_init(const struct device *dev) int ret; const struct i2c_kb1200_config *config = dev->config; struct i2c_kb1200_data *data = dev->data; + uint32_t bitrate_cfg; ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); if (ret != 0) { return ret; } - /* init mutex */ - k_sem_init(&data->mutex, 1, 1); + bitrate_cfg = i2c_map_dt_bitrate(config->clock_freq); + if (!bitrate_cfg) { + return -EINVAL; + } + + i2c_kb1200_configure(dev, bitrate_cfg | I2C_MODE_CONTROLLER); + + k_sem_init(&data->wait, 0, 1); + /* init lock */ + k_sem_init(&data->lock, 1, 1); kb1200_fsmbm_irq_init(); return 0; @@ -350,10 +391,11 @@ static int i2c_kb1200_init(const struct device *dev) static struct i2c_kb1200_data i2c_kb1200_data_##inst; \ static const struct i2c_kb1200_config i2c_kb1200_config_##inst = { \ .fsmbm = (struct fsmbm_regs *)DT_INST_REG_ADDR(inst), \ + .clock_freq = DT_INST_PROP(inst, clock_frequency), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ }; \ I2C_DEVICE_DT_INST_DEFINE(inst, &i2c_kb1200_init, NULL, &i2c_kb1200_data_##inst, \ - &i2c_kb1200_config_##inst, PRE_KERNEL_1, \ - CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &i2c_kb1200_api); + &i2c_kb1200_config_##inst, PRE_KERNEL_1, \ + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &i2c_kb1200_api); DT_INST_FOREACH_STATUS_OKAY(I2C_KB1200_DEVICE) diff --git a/soc/ene/kb1200/reg/fsmbm.h b/soc/ene/kb1200/reg/fsmbm.h index 33f96ae0c0e..129fbae71b4 100644 --- a/soc/ene/kb1200/reg/fsmbm.h +++ b/soc/ene/kb1200/reg/fsmbm.h @@ -58,28 +58,27 @@ struct fsmbm_regs { #define FSMBM_SMBUS_BUSY 0x1A #define FSMBM_STOP_FAIL 0x1E #define FSMBM_PEC_ERROR 0x1F -/* Packet Form */ -#define ___NONE 0x00 -#define ___STOP 0x01 -#define __PEC_ 0x02 -#define __PEC_STOP 0x03 -#define _CNT__ 0x04 -#define _CNT__STOP 0x05 -#define _CNT_PEC_ 0x06 -#define _CNT_PEC_STOP 0x07 -#define CMD___ 0x08 -#define CMD___STOP 0x09 -#define CMD__PEC_ 0x0A -#define CMD__PEC_STOP 0x0B -#define CMD_CNT__ 0x0C -#define CMD_CNT__STOP 0x0D -#define CMD_CNT_PEC_ 0x0E -#define CMD_CNT_PEC_STOP 0x0F +#define FSMBM_SDA_TIMEOUT 0x80 +#define FSMBM_MAX_TIMEOUT 200 /* Unit: ms */ + +/* Packet Form */ +#define FRT_NONE 0x00 +#define FRT_STOP 0x01 +#define FRT_PEC 0x02 +#define FRT_CNT 0x04 +#define FRT_CMD 0x08 +#define FRT_PEC_STOP (FRT_PEC | FRT_STOP) +#define FRT_CNT_STOP (FRT_CNT | FRT_STOP) +#define FRT_CNT_PEC (FRT_CNT | FRT_PEC) +#define FRT_CNT_PEC_STOP (FRT_CNT | FRT_PEC | FRT_STOP) +#define FRT_CMD_STOP (FRT_CMD | FRT_STOP) +#define FRT_CMD_PEC (FRT_CMD | FRT_PEC) +#define FRT_CMD_PEC_STOP (FRT_CMD | FRT_PEC | FRT_STOP) +#define FRT_CMD_CNT (FRT_CMD | FRT_CNT) +#define FRT_CMD_CNT_STOP (FRT_CMD | FRT_CNT | FRT_STOP) +#define FRT_CMD_CNT_PEC (FRT_CMD | FRT_CNT | FRT_PEC) +#define FRT_CMD_CNT_PEC_STOP (FRT_CMD | FRT_CNT | FRT_PEC | FRT_STOP) -#define FLEXIBLE_CMD 0x08 -#define FLEXIBLE_CNT 0x04 -#define FLEXIBLE_PEC 0x02 -#define FLEXIBLE_STOP 0x01 /* HW */ #define FSMBM_BUFFER_SIZE 0x20 #define FSMBM_MAXCNT 0xFF @@ -109,6 +108,7 @@ struct fsmbm_regs { #define FSMBM_CLK_10K 0x6363 /* Other(non 50% Duty Cycle) */ #define FSMBM_CLK_400K 0x0102 +#define FSMBM_CLK_666K 0x0001 #define FSMBM_COMPLETE_EVENT 0x01 #define FSMBM_HOST_NOTIFY_EVENT 0x02