Files
E3_boot/drivers/source/i2c/sdrv_i2c_reg.c
2025-11-07 10:05:24 +08:00

343 lines
9.7 KiB
C

/**
* @file sdrv_i2c_reg.c
* @sdrv i2c register api source file.
* relative basic register operation.
* only called by Semidrive i2c driver framework internal.
*
* @Copyright (c) 2022 Semidrive Semiconductor.
* @All rights reserved.
*
**/
#include <reg.h>
#include <udelay/udelay.h>
#include "sdrv_i2c_reg.h"
uint8_t sdrv_i2c_recv_data(paddr_t base)
{
return readl(base + I2C_RXFIFO);
}
void sdrv_i2c_send_data(paddr_t base, uint8_t data)
{
writel(data, base + I2C_TXFIFO);
}
uint32_t sdrv_i2c_get_psr_stat(paddr_t base, uint32_t psr_reg)
{
return readl(base + psr_reg);
}
uint32_t sdrv_i2c_get_wspace(paddr_t base)
{
return (readl(base + I2C_FSR) >> 8) & 0xff;
}
uint32_t sdrv_i2c_get_rspace(paddr_t base)
{
return readl(base + I2C_FSR) & 0xff;
}
uint32_t sdrv_i2c_get_fifo_empty_stat(paddr_t base)
{
return readl(base + I2C_FSR) & (0x1 << 24);
}
void sdrv_i2c_set_watermark(paddr_t base, uint32_t wml)
{
writel(wml, base + I2C_FCR);
}
void sdrv_i2c_clear_fifo(paddr_t base)
{
uint32_t val;
val = readl(base + I2C_FCR);
writel(val | 0x1 << 16, base + I2C_FCR);
}
void sdrv_i2c_set_cmdcsr(paddr_t base, uint32_t cmdcsr_reg, uint32_t val)
{
writel(val, base + cmdcsr_reg);
}
uint32_t sdrv_i2c_get_cmdcsr(paddr_t base, uint32_t cmdcsr_reg)
{
return readl(base + cmdcsr_reg);
}
void sdrv_i2c_clear_int(paddr_t base)
{
writel(~0x0, base + I2C_INTR0);
writel(~0x0, base + I2C_INTR1);
writel(~0x0, base + I2C_INTR2);
writel(~0x0, base + I2C_INTR3);
}
void sdrv_i2c_clear_int_bits(paddr_t base, uint32_t intr_reg, uint32_t bits)
{
writel(bits, base + intr_reg);
}
void sdrv_i2c_disable_int(paddr_t base)
{
sdrv_i2c_unmask_int(base, I2C_INTEN0, 0x0);
sdrv_i2c_unmask_int(base, I2C_INTEN1, 0x0);
sdrv_i2c_unmask_int(base, I2C_INTEN2, 0x0);
sdrv_i2c_unmask_int(base, I2C_INTEN3, 0x0);
}
uint32_t sdrv_i2c_get_int_stat(paddr_t base, uint32_t intr_reg)
{
return readl(base + intr_reg);
}
void sdrv_i2c_unmask_int(paddr_t base, uint32_t inten_reg, uint32_t int_flag)
{
writel(int_flag, base + inten_reg);
}
void sdrv_i2c_set_IO(paddr_t base, uint32_t io_reg, uint32_t val)
{
writel(val, base + io_reg);
}
void sdrv_i2c_set_speed(paddr_t base, uint32_t clk, uint32_t speed_mode)
{
uint32_t val;
uint32_t div = clk / 1000 / 108000;
val = readl(base + I2C_PCR0);
writel((val & ~0xff) | (speed_mode | div << 3), base + I2C_PCR0);
}
void sdrv_i2c_set_nack(paddr_t base)
{
uint32_t val;
val = readl(base + I2C_PCR0);
writel(val | 0x100, base + I2C_PCR0);
}
void sdrv_i2c_set_slvaddr(paddr_t base, uint8_t addr)
{
writel(addr, base + I2C_PCR1);
}
void sdrv_i2c_set_opmode(paddr_t base, uint32_t opmode)
{
uint32_t val;
val = readl(base + I2C_MCR0);
writel((val & ~0xf0) | (opmode << 4), base + I2C_MCR0);
}
uint32_t sdrv_i2c_get_parity_stat(paddr_t base)
{
return readl(base + I2C_PARITY_ERR_INT_STAT) & 0x1;
}
void sdrv_i2c_set_parity_stat(paddr_t base, bool enable)
{
uint32_t val = 0x0;
if (enable)
val = 0x1;
writel(val, base + I2C_PARITY_ERR_INT_STAT_EN);
}
void sdrv_i2c_set_parity_sig(paddr_t base, bool enable)
{
uint32_t val = 0x0;
if (enable)
val = 0x1;
writel(val, base + I2C_PARITY_ERR_INT_SIG_EN);
}
void sdrv_i2c_set_timing(paddr_t base, uint32_t clk, int idx)
{
uint32_t pcr_reg = 0;
uint32_t timscll = 0, timtasclh = 0, timtascll = 0, timtasdal = 0, timdvdat = 0;
uint32_t timscll_h = 0, timtasclh_h = 0, timtascll_h = 0, timtasdal_h = 0, timdvdat_h = 0;
uint32_t timunit = 0, timmext = 0, timsext = 0, timstuck = 0;
uint32_t timsdarxhld = 0, timdatspl = 0, timbuf = 0, timidle = 0;
uint32_t clk_khz = clk / 1000;
uint32_t divs = clk_khz / 108000;
if (divs)
clk_khz /= (divs + 1);
if (idx == 0) {
timscll = CAL_SCLL(5000, clk_khz);
timtasclh = CAL_TA(150, clk_khz);
timtascll = CAL_TA(150, clk_khz);
timtasdal = CAL_TA(150, clk_khz);
timdvdat = CAL_DVDAT(3400, clk_khz);
timunit = CAL_UNIT(6);
timmext = CAL_MEXT(0, clk_khz);
timsext = CAL_SEXT(0, clk_khz);
timstuck = CAL_STUCK(5000, clk_khz);
timsdarxhld = CAL_SDARXHLD(300, clk_khz);
timdatspl = CAL_DATSPL(2);
timbuf = CAL_BUF(5000, clk_khz);
timidle = CAL_IDLE(0, clk_khz);
}
else if (idx == 1) {
timscll = CAL_SCLL(1300, clk_khz);
timtasclh = CAL_TA(150, clk_khz);
timtascll = CAL_TA(150, clk_khz);
timtasdal = CAL_TA(150, clk_khz);
timdvdat = CAL_DVDAT(900, clk_khz);
timunit = CAL_UNIT(6);
timmext = CAL_MEXT(0, clk_khz);
timsext = CAL_SEXT(0, clk_khz);
timstuck = CAL_STUCK(5000, clk_khz);
timsdarxhld = CAL_SDARXHLD(300, clk_khz);
timdatspl = CAL_DATSPL(2);
timbuf = CAL_BUF(5000, clk_khz);
timidle = CAL_IDLE(0, clk_khz);
}
else if (idx == 2) {
timscll = CAL_SCLL(500, clk_khz);
timtasclh = CAL_TA(60, clk_khz);
timtascll = CAL_TA(60, clk_khz);
timtasdal = CAL_TA(60, clk_khz);
timdvdat = CAL_DVDAT(450, clk_khz);
timunit = CAL_UNIT(6);
timmext = CAL_MEXT(0, clk_khz);
timsext = CAL_SEXT(0, clk_khz);
timstuck = CAL_STUCK(5000, clk_khz);
timsdarxhld = CAL_SDARXHLD(120, clk_khz);
timdatspl = CAL_DATSPL(2);
timbuf = CAL_BUF(5000, clk_khz);
timidle = CAL_IDLE(0, clk_khz);
}
else if (idx == 3) {
timscll = CAL_SCLL(1300, clk_khz);
timtasclh = CAL_TA(150, clk_khz);
timtascll = CAL_TA(150, clk_khz);
timtasdal = CAL_TA(150, clk_khz);
timdvdat = CAL_DVDAT(900, clk_khz);
timscll_h = CAL_SCLL(160, clk_khz);
timtasclh_h = CAL_TA(30, clk_khz);
timtascll_h = CAL_TA(30, clk_khz);
timtasdal_h = CAL_TA(30, clk_khz);
timdvdat_h = CAL_DVDAT(40, clk_khz);
timunit = CAL_UNIT(6);
timmext = CAL_MEXT(0, clk_khz);
timsext = CAL_SEXT(0, clk_khz);
timstuck = CAL_STUCK(5000, clk_khz);
timsdarxhld = CAL_SDARXHLD(60, clk_khz);
timdatspl = CAL_DATSPL(2);
timbuf = CAL_BUF(5000, clk_khz);
timidle = CAL_IDLE(0, clk_khz);
}
else if (idx == 4) {
timscll = CAL_SCLL(125, clk_khz);
timtasclh = CAL_TA(25, clk_khz);
timtascll = CAL_TA(25, clk_khz);
timtasdal = CAL_TA(25, clk_khz);
timdvdat = CAL_DVDAT(20, clk_khz);
timunit = CAL_UNIT(6);
timmext = CAL_MEXT(0, clk_khz);
timsext = CAL_SEXT(0, clk_khz);
timstuck = CAL_STUCK(5000, clk_khz);
timsdarxhld = CAL_SDARXHLD(20, clk_khz);
timdatspl = CAL_DATSPL(0);
timbuf = CAL_BUF(5000, clk_khz);
timidle = CAL_IDLE(0, clk_khz);
}
pcr_reg = timscll | (timtasclh << 12) | (timtascll << 16) |
(timtasdal << 20) | (timdvdat << 24);
writel(pcr_reg, base + I2C_PCR2);
pcr_reg = timscll_h | (timtasclh_h << 12) | (timtascll_h << 16) |
(timtasdal_h << 20) | (timdvdat_h << 24);
writel(pcr_reg, base + I2C_PCR3);
pcr_reg = timunit | (timmext << 3) | (timsext << 9) | (timstuck << 16);
writel(pcr_reg, base + I2C_PCR4);
pcr_reg = timsdarxhld | (timdatspl << 6) | (timbuf << 18) | (timidle << 21);
writel(pcr_reg, base + I2C_PCR5);
}
void sdrv_i2c_disable(paddr_t base)
{
uint32_t val;
val = readl(base + I2C_MCR0);
writel(val & ~0x1, base + I2C_MCR0);
}
void sdrv_i2c_enable(paddr_t base)
{
uint32_t val;
val = readl(base + I2C_MCR0);
writel(val | 0x1, base + I2C_MCR0);
}
int sdrv_i2c_reset(paddr_t base)
{
uint32_t val;
uint32_t timeout = 100;
sdrv_i2c_disable(base);
val = readl(base + I2C_MCR0);
writel(val | 0x2, base + I2C_MCR0);
do {
if (!(readl(base + I2C_MCR0) & 0x2)) {
sdrv_i2c_enable(base);
return 0;
}
udelay(1);
} while (timeout--);
return -1;
}
void sdrv_i2c_dump_reg(paddr_t base, uint32_t *reg_val)
{
reg_val[0] = readl(base + I2C_MCR0);
reg_val[1] = readl(base + I2C_INTR0);
reg_val[2] = readl(base + I2C_INTR1);
reg_val[3] = readl(base + I2C_INTR2);
reg_val[4] = readl(base + I2C_INTR3);
reg_val[5] = readl(base + I2C_INTEN0);
reg_val[6] = readl(base + I2C_INTEN1);
reg_val[7] = readl(base + I2C_INTEN2);
reg_val[8] = readl(base + I2C_INTEN3);
reg_val[9] = readl(base + I2C_CMDCSR0);
reg_val[10] = readl(base + I2C_CMDCSR1);
reg_val[11] = readl(base + I2C_CMDCSR2);
reg_val[12] = readl(base + I2C_CMDCSR3);
reg_val[13] = readl(base + I2C_FCR);
reg_val[14] = readl(base + I2C_FSR);
reg_val[15] = readl(base + I2C_DMACR);
reg_val[16] = readl(base + I2C_DMASR);
reg_val[17] = readl(base + I2C_PCR0);
reg_val[18] = readl(base + I2C_PCR1);
reg_val[19] = readl(base + I2C_PCR2);
reg_val[20] = readl(base + I2C_PCR3);
reg_val[21] = readl(base + I2C_PCR4);
reg_val[22] = readl(base + I2C_PCR5);
reg_val[23] = readl(base + I2C_PCR6);
reg_val[24] = readl(base + I2C_PCR7);
reg_val[25] = readl(base + I2C_PCR8);
reg_val[26] = readl(base + I2C_PCR9);
reg_val[27] = readl(base + I2C_PCR10);
reg_val[28] = readl(base + I2C_PCR11);
reg_val[29] = readl(base + I2C_PSR0);
}
void sdrv_i2c_write_reg(paddr_t base, uint32_t reg, uint32_t val)
{
writel(val, base + reg);
}
void sdrv_i2c_read_reg(paddr_t base, uint32_t reg, uint32_t *val)
{
*val = readl(base + reg);
}