+static void i2c_lpc2_start(struct I2c *i2c, uint16_t slave_addr)
+{
+ if (I2C_TEST_START(i2c->flags) == I2C_START_W)
+ {
+ ticks_t start = timer_clock();
+ while (true)
+ {
+ i2c_hw_restart(i2c);
+
+ uint8_t status = HWREG(i2c->hw->base + I2C_STAT_OFF);
+
+ /* Start status ok, set addres and the R/W bit */
+ if ((status == I2C_STAT_SEND) || (status == I2C_STAT_RESEND))
+ HWREG(i2c->hw->base + I2C_DAT_OFF) = slave_addr & ~I2C_READBIT;
+
+ /* Clear the start bit and clear the SI bit */
+ HWREG(i2c->hw->base + I2C_CONCLR_OFF) = BV(I2CON_SIC) | BV(I2CON_STAC);
+
+ if (status == I2C_STAT_SLAW_ACK)
+ break;
+
+ if (status == I2C_STAT_ARB_LOST)
+ {
+ LOG_ERR("Arbitration lost\n");
+ i2c->errors |= I2C_ARB_LOST;
+ i2c_hw_stop(i2c);
+ }
+
+ if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
+ {
+ LOG_ERR("Timeout on I2C START\n");
+ i2c->errors |= I2C_NO_ACK;
+ i2c_hw_stop(i2c);
+ break;
+ }
+ }
+ }
+ else if (I2C_TEST_START(i2c->flags) == I2C_START_R)
+ {
+ i2c_hw_restart(i2c);
+
+ uint8_t status = HWREG(i2c->hw->base + I2C_STAT_OFF);
+
+ /* Start status ok, set addres and the R/W bit */
+ if ((status == I2C_STAT_SEND) || (status == I2C_STAT_RESEND))
+ HWREG(i2c->hw->base + I2C_DAT_OFF) = slave_addr | I2C_READBIT;
+
+ /* Clear the start bit and clear the SI bit */
+ HWREG(i2c->hw->base + I2C_CONCLR_OFF) = BV(I2CON_SIC) | BV(I2CON_STAC);
+
+ WAIT_SI(i2c);
+
+ status = HWREG(i2c->hw->base + I2C_STAT_OFF);
+
+ if (status == I2C_STAT_SLAR_NACK)
+ {
+ LOG_ERR("SLAR NACK:%02x\n", status);
+ i2c->errors |= I2C_NO_ACK;
+ i2c_hw_stop(i2c);
+ }
+
+ if (status == I2C_STAT_ARB_LOST)
+ {
+ LOG_ERR("Arbitration lost\n");
+ i2c->errors |= I2C_ARB_LOST;
+ i2c_hw_stop(i2c);
+ }
+ }
+ else
+ {
+ ASSERT(0);
+ }
+}
+
+static const I2cVT i2c_lpc_vt =
+{
+ .start = i2c_lpc2_start,
+ .get = i2c_lpc2_get,
+ .put = i2c_lpc2_put,
+ .send = i2c_swSend,
+ .recv = i2c_swRecv,
+};
+
+struct I2cHardware i2c_lpc2_hw[] =
+{
+ { /* I2C0 */
+ .base = I2C0_BASE_ADDR,
+ .pconp = BV(PCONP_PCI2C0),
+ .pinsel_port = PINSEL1_OFF,
+ .pinsel = I2C0_PINSEL,
+ .pinsel_mask = I2C0_PINSEL_MASK,
+ .pclksel = PCLKSEL0_OFF,
+ .pclk_mask = I2C0_PCLK_MASK,
+ .pclk_div = I2C0_PCLK_DIV8,
+ },
+ { /* I2C1 */
+ .base = I2C1_BASE_ADDR,
+ .pconp = BV(PCONP_PCI2C1),
+ .pinsel_port = PINSEL0_OFF,
+ .pinsel = I2C1_PINSEL,
+ .pinsel_mask = I2C1_PINSEL_MASK,
+ .pclksel = PCLKSEL1_OFF,
+ .pclk_mask = I2C1_PCLK_MASK,
+ .pclk_div = I2C1_PCLK_DIV8,
+ },
+ { /* I2C2 */
+ .base = I2C2_BASE_ADDR,
+ .pconp = BV(PCONP_PCI2C2),
+ .pinsel_port = PINSEL0_OFF,
+ .pinsel = I2C2_PINSEL,
+ .pinsel_mask = I2C2_PINSEL_MASK,
+ .pclksel = PCLKSEL1_OFF,
+ .pclk_mask = I2C2_PCLK_MASK,
+ .pclk_div = I2C2_PCLK_DIV8,
+ },
+};
+