/** * pch_i2c_writebytes() - write data to I2C bus in normal mode * @i2c_adap: Pointer to the struct i2c_adapter. * @last: specifies whether last message or not. * In the case of compound mode it will be 1 for last message, * otherwise 0. * @first: specifies whether first message or not. * 1 for first message otherwise 0. */ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, u32 last, u32 first) { struct i2c_algo_pch_data *adap = i2c_adap->algo_data; u8 *buf; u32 length; u32 addr; u32 addr_2_msb; u32 addr_8_lsb; s32 wrcount; s32 rtn; void __iomem *p = adap->pch_base_address; length = msgs->len; buf = msgs->buf; addr = msgs->addr; /* enable master tx */ pch_setbit(adap->pch_base_address, PCH_I2CCTL, I2C_TX_MODE); pch_dbg(adap, "I2CCTL = %x msgs->len = %d\n", ioread32(p + PCH_I2CCTL), length); if (first) { if (pch_i2c_wait_for_bus_idle(adap, BUS_IDLE_TIMEOUT) == -ETIME) return -ETIME; } if (msgs->flags & I2C_M_TEN) { addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7) & 0x06; iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR); if (first) pch_i2c_start(adap); rtn = pch_i2c_wait_for_xfer_complete(adap); if (rtn == 0) { if (pch_i2c_getack(adap)) { pch_dbg(adap, "Receive NACK for slave address" "setting\n"); return -EIO; } addr_8_lsb = (addr & I2C_ADDR_MSK); iowrite32(addr_8_lsb, p + PCH_I2CDR); } else if (rtn == -EIO) { /* Arbitration Lost */ pch_err(adap, "Lost Arbitration\n"); pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT); pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT); pch_i2c_init(adap); return -EAGAIN; } else { /* wait-event timeout */ pch_i2c_stop(adap); return -ETIME; } } else {
/** * pch_i2c_stop() - generate stop condition in normal mode. * @adap: Pointer to struct i2c_algo_pch_data. */ static void pch_i2c_stop(struct i2c_algo_pch_data *adap) { void __iomem *p = adap->pch_base_address; pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL)); /* clear the start bit */ pch_clrbit(adap->pch_base_address, PCH_I2CCTL, PCH_START); }
static int pch_i2c_wait_for_check_xfer(struct i2c_algo_pch_data *adap) { long ret; ret = wait_event_timeout(pch_event, (adap->pch_event_flag != 0), msecs_to_jiffies(1000)); if (!ret) { pch_err(adap, "%s:wait-event timeout\n", __func__); adap->pch_event_flag = 0; pch_i2c_stop(adap); pch_i2c_init(adap); return -ETIMEDOUT; } if (adap->pch_event_flag & I2C_ERROR_MASK) { pch_err(adap, "Lost Arbitration\n"); adap->pch_event_flag = 0; pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT); pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT); pch_i2c_init(adap); return -EAGAIN; } adap->pch_event_flag = 0; if (pch_i2c_getack(adap)) { pch_dbg(adap, "Receive NACK for slave address" "setting\n"); return -EIO; } return 0; }
/** * pch_i2c_wait_for_bus_idle() - check the status of bus. * @adap: Pointer to struct i2c_algo_pch_data. * @timeout: waiting time counter (ms). */ static s32 pch_i2c_wait_for_bus_idle(struct i2c_algo_pch_data *adap, s32 timeout) { void __iomem *p = adap->pch_base_address; int schedule = 0; unsigned long end = jiffies + msecs_to_jiffies(timeout); while (ioread32(p + PCH_I2CSR) & I2CMBB_BIT) { if (time_after(jiffies, end)) { pch_dbg(adap, "I2CSR = %x\n", ioread32(p + PCH_I2CSR)); pch_err(adap, "%s: Timeout Error.return%d\n", __func__, -ETIME); pch_i2c_init(adap); return -ETIME; } if (!schedule) /* Retry after some usecs */ udelay(5); else /* Wait a bit more without consuming CPU */ usleep_range(20, 1000); schedule = 1; } return 0; }
/** * pch_i2c_init() - hardware initialization of I2C module * @adap: Pointer to struct i2c_algo_pch_data. */ static void pch_i2c_init(struct i2c_algo_pch_data *adap) { void __iomem *p = adap->pch_base_address; u32 pch_i2cbc; u32 pch_i2ctmr; u32 reg_value; /* reset I2C controller */ iowrite32(0x01, p + PCH_I2CSRST); msleep(20); iowrite32(0x0, p + PCH_I2CSRST); /* Initialize I2C registers */ iowrite32(0x21, p + PCH_I2CNF); pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_I2CCTL_I2CMEN); if (pch_i2c_speed != 400) pch_i2c_speed = 100; reg_value = PCH_I2CCTL_I2CMEN; if (pch_i2c_speed == FAST_MODE_CLK) { reg_value |= FAST_MODE_EN; pch_dbg(adap, "Fast mode enabled\n"); } if (pch_clk > PCH_MAX_CLK) pch_clk = 62500; pch_i2cbc = (pch_clk + (pch_i2c_speed * 4)) / pch_i2c_speed * 8; /* Set transfer speed in I2CBC */ iowrite32(pch_i2cbc, p + PCH_I2CBC); pch_i2ctmr = (pch_clk) / 8; iowrite32(pch_i2ctmr, p + PCH_I2CTMR); reg_value |= NORMAL_INTR_ENBL; /* Enable interrupts in normal mode */ iowrite32(reg_value, p + PCH_I2CCTL); pch_dbg(adap, "I2CCTL=%x pch_i2cbc=%x pch_i2ctmr=%x Enable interrupts\n", ioread32(p + PCH_I2CCTL), pch_i2cbc, pch_i2ctmr); init_waitqueue_head(&pch_event); }
/** * pch_i2c_writebytes() - write data to I2C bus in normal mode * @i2c_adap: Pointer to the struct i2c_adapter. * @last: specifies whether last message or not. * In the case of compound mode it will be 1 for last message, * otherwise 0. * @first: specifies whether first message or not. * 1 for first message otherwise 0. */ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, u32 last, u32 first) { struct i2c_algo_pch_data *adap = i2c_adap->algo_data; u8 *buf; u32 length; u32 addr; u32 addr_2_msb; u32 addr_8_lsb; s32 wrcount; void __iomem *p = adap->pch_base_address; length = msgs->len; buf = msgs->buf; addr = msgs->addr; /* enable master tx */ pch_setbit(adap->pch_base_address, PCH_I2CCTL, I2C_TX_MODE); pch_dbg(adap, "I2CCTL = %x msgs->len = %d\n", ioread32(p + PCH_I2CCTL), length); if (first) { if (pch_i2c_wait_for_bus_idle(adap, BUS_IDLE_TIMEOUT) == -ETIME) return -ETIME; } if (msgs->flags & I2C_M_TEN) { addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7); iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR); if (first) pch_i2c_start(adap); if (pch_i2c_wait_for_xfer_complete(adap) == 0 && pch_i2c_getack(adap) == 0) { addr_8_lsb = (addr & I2C_ADDR_MSK); iowrite32(addr_8_lsb, p + PCH_I2CDR); } else { pch_i2c_stop(adap); return -ETIME; } } else {
/** * pch_i2c_wait_for_bus_idle() - check the status of bus. * @adap: Pointer to struct i2c_algo_pch_data. * @timeout: waiting time counter (us). */ static s32 pch_i2c_wait_for_bus_idle(struct i2c_algo_pch_data *adap, s32 timeout) { void __iomem *p = adap->pch_base_address; /* MAX timeout value is timeout*1000*1000nsec */ ktime_t ns_val = ktime_add_ns(ktime_get(), timeout*1000*1000); do { if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0) break; msleep(20); } while (ktime_lt(ktime_get(), ns_val)); pch_dbg(adap, "I2CSR = %x\n", ioread32(p + PCH_I2CSR)); if (timeout == 0) { pch_err(adap, "%s: Timeout Error.return%d\n", __func__, -ETIME); return -ETIME; } return 0; }
/** * pch_i2c_repstart() - generate repeated start condition in normal mode * @adap: Pointer to struct i2c_algo_pch_data. */ static void pch_i2c_repstart(struct i2c_algo_pch_data *adap) { void __iomem *p = adap->pch_base_address; pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL)); pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_REPSTART); }