/** * @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 #include #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); }