diff options
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/Kconfig | 25 | ||||
-rw-r--r-- | drivers/i2c/Makefile | 4 | ||||
-rw-r--r-- | drivers/i2c/mtk_i2c.c | 45 | ||||
-rw-r--r-- | drivers/i2c/mvtwsi.c | 42 |
4 files changed, 103 insertions, 13 deletions
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 5e81698143a..4f42200f392 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -231,6 +231,15 @@ config SYS_I2C_DW controller is used in various SoCs, e.g. the ST SPEAr, Altera SoCFPGA, Synopsys ARC700 and some Intel x86 SoCs. +config SYS_I2C_DW_PCI + bool "Designware PCI I2C Controller" + depends on SYS_I2C_DW && PCI && ACPIGEN + default y + help + Say yes here to select the Designware PCI I2C Host Controller. + This PCI I2C controller is the base on Desigware I2C host + controller. + config SYS_I2C_AST2600 bool "AST2600 I2C Controller" depends on DM_I2C && ARCH_ASPEED @@ -363,7 +372,7 @@ config SYS_MXC_I2C1_SPEED config SYS_MXC_I2C1_SLAVE hex "I2C1 Slave" - default 0 + default 0x0 help MXC I2C1 Slave endif @@ -378,7 +387,7 @@ config SYS_MXC_I2C2_SPEED config SYS_MXC_I2C2_SLAVE hex "I2C2 Slave" - default 0 + default 0x0 help MXC I2C2 Slave endif @@ -392,7 +401,7 @@ config SYS_MXC_I2C3_SPEED config SYS_MXC_I2C3_SLAVE hex "I2C3 Slave" - default 0 + default 0x0 help MXC I2C3 Slave endif @@ -406,7 +415,7 @@ config SYS_MXC_I2C4_SPEED config SYS_MXC_I2C4_SLAVE hex "I2C4 Slave" - default 0 + default 0x0 help MXC I2C4 Slave endif @@ -420,7 +429,7 @@ config SYS_MXC_I2C5_SPEED config SYS_MXC_I2C5_SLAVE hex "I2C5 Slave" - default 0 + default 0x0 help MXC I2C5 Slave endif @@ -434,7 +443,7 @@ config SYS_MXC_I2C6_SPEED config SYS_MXC_I2C6_SLAVE hex "I2C6 Slave" - default 0 + default 0x0 help MXC I2C6 Slave endif @@ -448,7 +457,7 @@ config SYS_MXC_I2C7_SPEED config SYS_MXC_I2C7_SLAVE hex "I2C7 Slave" - default 0 + default 0x0 help MXC I2C7 Slave endif @@ -462,7 +471,7 @@ config SYS_MXC_I2C8_SPEED config SYS_MXC_I2C8_SLAVE hex "I2C8 Slave" - default 0 + default 0x0 help MXC I2C8 Slave endif diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 99545df2e55..d5b85f398db 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -18,9 +18,7 @@ obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o obj-$(CONFIG_SYS_I2C_CA) += i2c-cortina.o obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o -ifdef CONFIG_PCI -obj-$(CONFIG_SYS_I2C_DW) += designware_i2c_pci.o -endif +obj-$(CONFIG_SYS_I2C_DW_PCI) += designware_i2c_pci.o obj-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o obj-$(CONFIG_SYS_I2C_IHS) += ihs_i2c.o obj-$(CONFIG_SYS_I2C_INTEL) += intel_i2c.o diff --git a/drivers/i2c/mtk_i2c.c b/drivers/i2c/mtk_i2c.c index 5528bcd7cce..2f331d3216a 100644 --- a/drivers/i2c/mtk_i2c.c +++ b/drivers/i2c/mtk_i2c.c @@ -183,9 +183,36 @@ static const uint mt_i2c_regs_v2[] = { [REG_DCM_EN] = 0xf88, }; +static const uint mt_i2c_regs_v3[] = { + [REG_PORT] = 0x0, + [REG_INTR_MASK] = 0x8, + [REG_INTR_STAT] = 0xc, + [REG_CONTROL] = 0x10, + [REG_TRANSFER_LEN] = 0x14, + [REG_TRANSAC_LEN] = 0x18, + [REG_DELAY_LEN] = 0x1c, + [REG_TIMING] = 0x20, + [REG_START] = 0x24, + [REG_EXT_CONF] = 0x28, + [REG_LTIMING] = 0x2c, + [REG_HS] = 0x30, + [REG_IO_CONFIG] = 0x34, + [REG_FIFO_ADDR_CLR] = 0x38, + [REG_TRANSFER_LEN_AUX] = 0x44, + [REG_CLOCK_DIV] = 0x48, + [REG_SOFTRESET] = 0x50, + [REG_SLAVE_ADDR] = 0x94, + [REG_DEBUGSTAT] = 0xe4, + [REG_DEBUGCTRL] = 0xe8, + [REG_FIFO_STAT] = 0xf4, + [REG_FIFO_THRESH] = 0xf8, + [REG_DCM_EN] = 0xf88, +}; + struct mtk_i2c_soc_data { const uint *regs; uint dma_sync: 1; + uint ltiming_adjust: 1; }; struct mtk_i2c_priv { @@ -401,6 +428,10 @@ static int mtk_i2c_set_speed(struct udevice *dev, uint speed) (sample_cnt << HS_SAMPLE_OFFSET) | (step_cnt << HS_STEP_OFFSET); i2c_writel(priv, REG_HS, high_speed_reg); + if (priv->soc_data->ltiming_adjust) { + timing_reg = (sample_cnt << 12) | (step_cnt << 9); + i2c_writel(priv, REG_LTIMING, timing_reg); + } } else { ret = mtk_i2c_calculate_speed(clk_src, priv->speed, &step_cnt, &sample_cnt); @@ -412,7 +443,12 @@ static int mtk_i2c_set_speed(struct udevice *dev, uint speed) high_speed_reg = I2C_TIME_CLR_VALUE; i2c_writel(priv, REG_TIMING, timing_reg); i2c_writel(priv, REG_HS, high_speed_reg); + if (priv->soc_data->ltiming_adjust) { + timing_reg = (sample_cnt << 6) | step_cnt; + i2c_writel(priv, REG_LTIMING, timing_reg); + } } + exit: if (mtk_i2c_clk_disable(priv)) return log_msg_ret("set_speed disable clk", -1); @@ -725,7 +761,6 @@ static int mtk_i2c_probe(struct udevice *dev) return log_msg_ret("probe enable clk", -1); mtk_i2c_init_hw(priv); - if (mtk_i2c_clk_disable(priv)) return log_msg_ret("probe disable clk", -1); @@ -750,31 +785,37 @@ static int mtk_i2c_deblock(struct udevice *dev) static const struct mtk_i2c_soc_data mt76xx_soc_data = { .regs = mt_i2c_regs_v1, .dma_sync = 0, + .ltiming_adjust = 0, }; static const struct mtk_i2c_soc_data mt7981_soc_data = { - .regs = mt_i2c_regs_v1, + .regs = mt_i2c_regs_v3, .dma_sync = 1, + .ltiming_adjust = 1, }; static const struct mtk_i2c_soc_data mt7986_soc_data = { .regs = mt_i2c_regs_v1, .dma_sync = 1, + .ltiming_adjust = 0, }; static const struct mtk_i2c_soc_data mt8183_soc_data = { .regs = mt_i2c_regs_v2, .dma_sync = 1, + .ltiming_adjust = 0, }; static const struct mtk_i2c_soc_data mt8518_soc_data = { .regs = mt_i2c_regs_v1, .dma_sync = 0, + .ltiming_adjust = 0, }; static const struct mtk_i2c_soc_data mt8512_soc_data = { .regs = mt_i2c_regs_v1, .dma_sync = 1, + .ltiming_adjust = 0, }; static const struct dm_i2c_ops mtk_i2c_ops = { diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c index 93bbc6916e5..14cdb0f6635 100644 --- a/drivers/i2c/mvtwsi.c +++ b/drivers/i2c/mvtwsi.c @@ -142,6 +142,8 @@ enum mvtwsi_ctrl_register_fields { * code. */ enum mvstwsi_status_values { + /* Protocol violation on bus; this is a terminal state */ + MVTWSI_BUS_ERROR = 0x00, /* START condition transmitted */ MVTWSI_STATUS_START = 0x08, /* Repeated START condition transmitted */ @@ -526,6 +528,36 @@ static void __twsi_i2c_init(struct mvtwsi_registers *twsi, int speed, } /* + * __twsi_i2c_reinit() - Reset and reinitialize the I2C controller. + * + * This function should be called to get the MVTWSI controller out of the + * "bus error" state. It saves and restores the baud and address registers. + * + * @twsi: The MVTWSI register structure to use. + * @tick: The duration of a clock cycle at the current I2C speed. + */ +static void __twsi_i2c_reinit(struct mvtwsi_registers *twsi, uint tick) +{ + uint baud; + uint slaveadd; + + /* Save baud, address registers */ + baud = readl(&twsi->baudrate); + slaveadd = readl(&twsi->slave_address); + + /* Reset controller */ + twsi_reset(twsi); + + /* Restore baud, address registers */ + writel(baud, &twsi->baudrate); + writel(slaveadd, &twsi->slave_address); + writel(0, &twsi->xtnd_slave_addr); + + /* Assert STOP, but don't care for the result */ + (void) twsi_stop(twsi, tick); +} + +/* * i2c_begin() - Start a I2C transaction. * * Begin a I2C transaction with a given expected start status and chip address. @@ -621,6 +653,11 @@ static int __twsi_i2c_read(struct mvtwsi_registers *twsi, uchar chip, int stop_status; int expected_start = MVTWSI_STATUS_START; + /* Check for (and clear) a bus error from a previous failed transaction + * or another master on the same bus */ + if (readl(&twsi->status) == MVTWSI_BUS_ERROR) + __twsi_i2c_reinit(twsi, tick); + if (alen > 0) { /* Begin i2c write to send the address bytes */ status = i2c_begin(twsi, expected_start, (chip << 1), tick); @@ -668,6 +705,11 @@ static int __twsi_i2c_write(struct mvtwsi_registers *twsi, uchar chip, { int status, stop_status; + /* Check for (and clear) a bus error from a previous failed transaction + * or another master on the same bus */ + if (readl(&twsi->status) == MVTWSI_BUS_ERROR) + __twsi_i2c_reinit(twsi, tick); + /* Begin i2c write to send first the address bytes, then the * data bytes */ status = i2c_begin(twsi, MVTWSI_STATUS_START, (chip << 1), tick); |