Lines Matching +full:i2c +full:- +full:retry +full:- +full:count

1 // SPDX-License-Identifier: GPL-2.0+
4 * IP from Cadence (ID T-CS-PE-0007-100, Version R1p10f2)
6 * This file is based on: drivers/i2c/zynq_i2c.c,
7 * with added driver-model support and code cleanup.
16 #include <i2c.h>
22 /* i2c register set */
79 #define CDNS_I2C_TRANSFER_SIZE (CDNS_I2C_TRANSFER_SIZE_MAX - 3)
90 int_status = readl(&cdns_i2c->interrupt_status); in cdns_i2c_debug_status()
92 status = readl(&cdns_i2c->status); in cdns_i2c_debug_status()
121 debug("TS%d ", readl(&cdns_i2c->transfer_size)); in cdns_i2c_debug_status()
146 int_status = readl(&cdns_i2c->interrupt_status); in cdns_i2c_wait()
153 writel(int_status & mask, &cdns_i2c->interrupt_status); in cdns_i2c_wait()
176 return -EINVAL; in cdns_i2c_calc_divs()
178 last_error = -1; in cdns_i2c_calc_divs()
184 div_b--; in cdns_i2c_calc_divs()
191 current_error = ((actual_fscl > fscl) ? (actual_fscl - fscl) : in cdns_i2c_calc_divs()
192 (fscl - actual_fscl)); in cdns_i2c_calc_divs()
219 return -EINVAL; in cdns_i2c_set_bus_speed()
222 ret = cdns_i2c_calc_divs(&speed_p, bus->input_freq, &div_a, &div_b); in cdns_i2c_set_bus_speed()
227 __func__, div_a, div_b, bus->input_freq, speed, speed_p); in cdns_i2c_set_bus_speed()
230 (div_a << CDNS_I2C_CONTROL_DIV_A_SHIFT), &bus->regs->control); in cdns_i2c_set_bus_speed()
232 /* Enable master mode, ack, and 7-bit addressing */ in cdns_i2c_set_bus_speed()
233 setbits_le32(&bus->regs->control, CDNS_I2C_CONTROL_MS | in cdns_i2c_set_bus_speed()
241 return (readl(&regs->interrupt_status) & CDNS_I2C_INTERRUPT_ARBLOST); in is_arbitration_lost()
248 struct cdns_i2c_regs *regs = i2c_bus->regs; in cdns_i2c_write_data()
252 setbits_le32(&regs->control, CDNS_I2C_CONTROL_CLR_FIFO); in cdns_i2c_write_data()
253 clrbits_le32(&regs->control, CDNS_I2C_CONTROL_RW); in cdns_i2c_write_data()
259 setbits_le32(&regs->control, CDNS_I2C_CONTROL_HOLD); in cdns_i2c_write_data()
262 writel(CDNS_I2C_INTERRUPTS_MASK, &regs->interrupt_status); in cdns_i2c_write_data()
264 writel(addr, &regs->address); in cdns_i2c_write_data()
266 while (len-- && !is_arbitration_lost(regs)) { in cdns_i2c_write_data()
267 writel(*(cur_data++), &regs->data); in cdns_i2c_write_data()
268 if (readl(&regs->transfer_size) == CDNS_I2C_FIFO_DEPTH) { in cdns_i2c_write_data()
272 return -EAGAIN; in cdns_i2c_write_data()
276 clrbits_le32(&regs->control, in cdns_i2c_write_data()
278 return -ETIMEDOUT; in cdns_i2c_write_data()
283 return -EAGAIN; in cdns_i2c_write_data()
286 if (!i2c_bus->hold_flag) in cdns_i2c_write_data()
287 clrbits_le32(&regs->control, CDNS_I2C_CONTROL_HOLD); in cdns_i2c_write_data()
294 return -ETIMEDOUT; in cdns_i2c_write_data()
296 return -EAGAIN; in cdns_i2c_write_data()
310 struct cdns_i2c_regs *regs = i2c_bus->regs; in cdns_i2c_read_data()
319 setbits_le32(&regs->control, CDNS_I2C_CONTROL_HOLD); in cdns_i2c_read_data()
321 setbits_le32(&regs->control, CDNS_I2C_CONTROL_CLR_FIFO | in cdns_i2c_read_data()
326 writel(curr_recv_count, &regs->transfer_size); in cdns_i2c_read_data()
328 writel(recv_count, &regs->transfer_size); in cdns_i2c_read_data()
332 writel(addr, &regs->address); in cdns_i2c_read_data()
336 hold_quirk = (i2c_bus->quirks & CDNS_I2C_BROKEN_HOLD_BIT) && updatetx; in cdns_i2c_read_data()
339 while (readl(&regs->status) & CDNS_I2C_STATUS_RXDV) { in cdns_i2c_read_data()
341 !i2c_bus->hold_flag) { in cdns_i2c_read_data()
342 clrbits_le32(&regs->control, in cdns_i2c_read_data()
345 *(cur_data)++ = readl(&regs->data); in cdns_i2c_read_data()
346 recv_count--; in cdns_i2c_read_data()
347 curr_recv_count--; in cdns_i2c_read_data()
355 while (readl(&regs->transfer_size) != in cdns_i2c_read_data()
356 (curr_recv_count - CDNS_I2C_FIFO_DEPTH)) in cdns_i2c_read_data()
362 if ((recv_count - CDNS_I2C_FIFO_DEPTH) > in cdns_i2c_read_data()
365 &regs->transfer_size); in cdns_i2c_read_data()
369 writel(recv_count - CDNS_I2C_FIFO_DEPTH, in cdns_i2c_read_data()
370 &regs->transfer_size); in cdns_i2c_read_data()
374 writel(addr, &regs->address); in cdns_i2c_read_data()
377 &regs->transfer_size); in cdns_i2c_read_data()
380 writel(recv_count, &regs->transfer_size); in cdns_i2c_read_data()
391 return -ETIMEDOUT; in cdns_i2c_read_data()
393 return -EAGAIN; in cdns_i2c_read_data()
403 int count; in cdns_i2c_xfer() local
408 hold_quirk = !!(i2c_bus->quirks & CDNS_I2C_BROKEN_HOLD_BIT); in cdns_i2c_xfer()
418 for (count = 0; (count < nmsgs - 1) && hold_quirk; count++) { in cdns_i2c_xfer()
419 if (msg[count].flags & I2C_M_RD) { in cdns_i2c_xfer()
421 return -EOPNOTSUPP; in cdns_i2c_xfer()
425 i2c_bus->hold_flag = 1; in cdns_i2c_xfer()
426 setbits_le32(&i2c_bus->regs->control, CDNS_I2C_CONTROL_HOLD); in cdns_i2c_xfer()
428 i2c_bus->hold_flag = 0; in cdns_i2c_xfer()
432 for (u8 retry = 0; retry < CDNS_I2C_ARB_LOST_MAX_RETRIES && in cdns_i2c_xfer() local
433 nmsgs > 0; nmsgs--, msg++) { in cdns_i2c_xfer()
434 debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len); in cdns_i2c_xfer()
435 if (msg->flags & I2C_M_RD) { in cdns_i2c_xfer()
436 ret = cdns_i2c_read_data(i2c_bus, msg->addr, msg->buf, in cdns_i2c_xfer()
437 msg->len); in cdns_i2c_xfer()
439 ret = cdns_i2c_write_data(i2c_bus, msg->addr, msg->buf, in cdns_i2c_xfer()
440 msg->len); in cdns_i2c_xfer()
442 if (ret == -EAGAIN) { in cdns_i2c_xfer()
445 retry++; in cdns_i2c_xfer()
447 retry); in cdns_i2c_xfer()
453 return -EREMOTEIO; in cdns_i2c_xfer()
468 i2c_bus->regs = (struct cdns_i2c_regs *)dev_read_addr(dev); in cdns_i2c_ofdata_to_platdata()
469 if (!i2c_bus->regs) in cdns_i2c_ofdata_to_platdata()
470 return -ENOMEM; in cdns_i2c_ofdata_to_platdata()
473 i2c_bus->quirks = pdata->quirks; in cdns_i2c_ofdata_to_platdata()
479 i2c_bus->input_freq = clk_get_rate(&clk); in cdns_i2c_ofdata_to_platdata()
494 { .compatible = "cdns,i2c-r1p10", .data = (ulong)&r1p10_i2c_def },
495 { .compatible = "cdns,i2c-r1p14" },
500 .name = "i2c-cdns",