diff options
Diffstat (limited to 'src/soc/intel')
-rw-r--r-- | src/soc/intel/common/lpss_i2c.c | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/src/soc/intel/common/lpss_i2c.c b/src/soc/intel/common/lpss_i2c.c index 0c8fec44b5..76c3d14d70 100644 --- a/src/soc/intel/common/lpss_i2c.c +++ b/src/soc/intel/common/lpss_i2c.c @@ -58,6 +58,19 @@ struct lpss_i2c_regs { uint32_t rx_level; uint32_t sda_hold; uint32_t tx_abort_source; + uint32_t slv_data_nak_only; + uint32_t dma_cr; + uint32_t dma_tdlr; + uint32_t dma_rdlr; + uint32_t sda_setup; + uint32_t ack_general_call; + uint32_t enable_status; + uint32_t fs_spklen; + uint32_t hs_spklen; + uint32_t clr_restart_det; + uint32_t comp_param1; + uint32_t comp_version; + uint32_t comp_type; } __attribute__((packed)); /* Use a ~4ms timeout for various operations */ @@ -153,7 +166,7 @@ static int lpss_i2c_disable(struct lpss_i2c_regs *regs) /* Wait for enable bit to clear */ stopwatch_init_usecs_expire(&sw, LPSS_I2C_TIMEOUT_US); - while (read32(®s->enable) & ENABLE_CONTROLLER) + while (read32(®s->enable_status) & ENABLE_CONTROLLER) if (stopwatch_expired(&sw)) return -1; } @@ -232,6 +245,7 @@ int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count) struct stopwatch sw; struct lpss_i2c_regs *regs; size_t byte; + int ret = -1; if (count <= 0 || !segments) return -1; @@ -242,14 +256,11 @@ int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count) return -1; } - if (!(read32(®s->enable) & ENABLE_CONTROLLER)) { - printk(BIOS_ERR, "I2C bus %u not initialized\n", bus); - return -1; - } + lpss_i2c_enable(regs); if (lpss_i2c_wait_for_bus_idle(regs)) { printk(BIOS_ERR, "I2C timeout waiting for bus %u idle\n", bus); - return -1; + goto out; } /* Process each segment */ @@ -269,7 +280,7 @@ int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count) printk(BIOS_ERR, "I2C %s failed: bus %u " "addr 0x%02x\n", segments->read ? "read" : "write", bus, segments->chip); - return -1; + goto out; } } segments++; @@ -280,7 +291,7 @@ int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count) while (!(read32(®s->raw_intr_stat) & INTR_STAT_STOP_DET)) { if (stopwatch_expired(&sw)) { printk(BIOS_ERR, "I2C stop bit not received\n"); - return -1; + goto out; } } @@ -290,7 +301,7 @@ int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count) /* Wait for the bus to go idle */ if (lpss_i2c_wait_for_bus_idle(regs)) { printk(BIOS_ERR, "I2C timeout waiting for bus %u idle\n", bus); - return -1; + goto out; } /* Flush the RX FIFO in case it is not empty */ @@ -298,12 +309,17 @@ int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count) while (read32(®s->status) & STATUS_RX_FIFO_NOT_EMPTY) { if (stopwatch_expired(&sw)) { printk(BIOS_ERR, "I2C timeout flushing RX FIFO\n"); - return -1; + goto out; } read32(®s->cmd_data); } - return 0; + ret = 0; + +out: + read32(®s->clear_intr); + lpss_i2c_disable(regs); + return ret; } /* @@ -519,8 +535,6 @@ int lpss_i2c_init(unsigned bus, enum i2c_speed speed) /* Enable stop detection interrupt */ write32(®s->intr_mask, INTR_STAT_STOP_DET); - lpss_i2c_enable(regs); - printk(BIOS_INFO, "LPSS I2C bus %u at 0x%p (%u KHz)\n", bus, regs, (speed ? : I2C_SPEED_FAST) / KHz); |