static int bcmpmu_i2c_try_write(struct bcmpmu59xxx *bcmpmu, u32 reg, u8 value) { int err = 0; int tries = PWRMGR_I2C_RDWR_MAX_TRIES; u8 temp = 0; u8 check_fifo = DEC_REG_FLAG(reg) & 1; if (DEC_REG_ADD(reg) >= PMU_REG_MAX) return -ENODEV; while (tries--) { if (check_fifo && (last_trans == I2C_TRANS_WRITE)) { err = pwr_mgr_pmu_reg_read((u8) DEC_REG_ADD(PMU_REG_I2CCTRL1), bcmpmu_get_slaveid(bcmpmu, PMU_REG_I2CCTRL1), &temp); if (err == 0) { if (!(temp & I2CCTRL1_FIFOFULL_MASK)) { err = pwr_mgr_pmu_reg_write ((u8) DEC_REG_ADD(reg), bcmpmu_get_slaveid(bcmpmu, reg), value); if (err == 0) { last_trans = I2C_TRANS_WRITE; break; } } } udelay(PWRMGR_I2C_RETRY_DELAY_US); } else { err = pwr_mgr_pmu_reg_write((u8) DEC_REG_ADD(reg), bcmpmu_get_slaveid(bcmpmu, reg), value); if (err == 0) { last_trans = I2C_TRANS_WRITE; break; } } } if (tries <= 0) { err = -EAGAIN; pr_pmui2c(ERROR, "ERR: I2C SW SEQ Write MAX Tries\n"); } if (!err) bcmpmu_i2c_log(i2c_log_buf_v, 0, bcmpmu_get_slaveid(bcmpmu, reg), DEC_REG_ADD(reg), value); else bcmpmu_i2c_log(i2c_log_buf_v, (char)err, bcmpmu_get_slaveid(bcmpmu, reg), DEC_REG_ADD(reg), value); return err; }
/** * function must be called with i2c_mutex locked */ static int i2c_try_read_write(struct bcmpmu *bcmpmu, int trans_type, u8 reg_addr, u8 slave_id, u8 *value) { struct bcmpmu_reg_map map; struct bcmpmu_i2c *acc = (struct bcmpmu_i2c *)bcmpmu->accinfo; int err = 0; int tries = PWRMGR_I2C_RDWR_MAX_TRIES; u8 clientaddr; u8 temp; pr_debug("%s: trans %d addr %x, slave %x\n", __func__, trans_type, reg_addr, slave_id); if (trans_type == I2C_TRANS_READ) map = bcmpmu->regmap[PMU_REG_BUS_STATUS_READ_FIFO]; else map = bcmpmu->regmap[PMU_REG_BUS_STATUS_WRITE_FIFO]; if ((map.addr == 0) && (map.mask == 0)) { err = -ENXIO; goto err_out; } if (map.map == 0) clientaddr = acc->i2c_client->addr; else clientaddr = acc->i2c_client1->addr; switch (trans_type) { case I2C_TRANS_READ: while (tries--) { /** * Read the FIFORDBLOCK Bit of PMU before * initiating an read transaction if the last * trasaction was i2c write. This bit is set by * the * PMU when its busy finishing previous write * operation (if this bit is ignored there is a * chance of reading a stale data of the * register !!) */ if (last_i2c_trans == I2C_TRANS_WRITE) { err = pwr_mgr_pmu_reg_read(map.addr, clientaddr, &temp); if (err == 0) { if ((temp & map.mask) == bcmpmu->pmu_rev) { /** * OK: Now we can try * to read the register */ err = pwr_mgr_pmu_reg_read(reg_addr, slave_id, value); if (err == 0) { last_i2c_trans = I2C_TRANS_READ; break; } } } } else { err = pwr_mgr_pmu_reg_read(reg_addr, slave_id, value); if (err == 0) { last_i2c_trans = I2C_TRANS_READ; break; } } udelay(PWRMGR_I2C_RETRY_DELAY_US); } if (tries <= 0) { pr_info("ERROR: I2C SW SEQ Max Tries\n"); err = -EAGAIN; break; } break; case I2C_TRANS_WRITE: while (tries--) { if (last_i2c_trans == I2C_TRANS_WRITE) { err = pwr_mgr_pmu_reg_read(map.addr, clientaddr, &temp); if (err == 0) { if (!(temp & map.mask)) { err = pwr_mgr_pmu_reg_write( reg_addr, slave_id, *value); if (err == 0) { last_i2c_trans = I2C_TRANS_WRITE; break; } } } udelay(PWRMGR_I2C_RETRY_DELAY_US); } else { err = pwr_mgr_pmu_reg_write(reg_addr, slave_id, *value); if (err == 0) { last_i2c_trans = I2C_TRANS_WRITE; break; } } } if (tries <= 0) { err = -EAGAIN; pr_info("ERROR: I2C SW SEQ Write MAX Tries\n"); break; } break; default: err = -EINVAL; break; } err_out: return err; }