Lines Matching +full:i2c +full:- +full:r1p10
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2019-2020 Thomas Skibo <thomasskibo@yahoo.com>
28 /* Cadence / Zynq i2c driver.
30 * Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
31 * (v1.12.2) July 1, 2018. Xilinx doc UG585. I2C Controller is documented
75 {"cdns,i2c-r1p10", HWTYPE_CDNS_R1P10},
77 {"cdns,i2c-r1p14", HWTYPE_CDNS_R1P14},
104 #define I2C_SC_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
105 #define I2C_SC_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
107 mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->dev), NULL, MTX_DEF)
108 #define I2C_SC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx)
109 #define I2C_SC_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
111 #define RD2(sc, off) (bus_read_2((sc)->mem_res, (off)))
112 #define WR2(sc, off, val) (bus_write_2((sc)->mem_res, (off), (val)))
113 #define RD1(sc, off) (bus_read_1((sc)->mem_res, (off)))
114 #define WR1(sc, off, val) (bus_write_1((sc)->mem_res, (off), (val)))
116 /* Cadence I2C controller device registers. */
141 #define CDNC_I2C_ADDR 0x0008 /* i2c address register. */
142 #define CDNC_I2C_DATA 0x000C /* i2c data register. */
157 #define CDNC_I2C_TIME_OUT 0x001C /* Time-out register. */
183 * The i2c controller has a two-stage clock divider to create in cdnc_i2c_set_freq()
191 div_b = sc->ref_clock_freq / (22 * sc->i2c_clock_freq * in cdnc_i2c_set_freq()
195 clk_out = sc->ref_clock_freq / (22 * (div_a + 1) * in cdnc_i2c_set_freq()
197 err = clk_out > sc->i2c_clock_freq ? in cdnc_i2c_set_freq()
198 clk_out - sc->i2c_clock_freq : in cdnc_i2c_set_freq()
199 sc->i2c_clock_freq - clk_out; in cdnc_i2c_set_freq()
208 device_printf(sc->dev, "cannot configure clock divider.\n"); in cdnc_i2c_set_freq()
212 clk_out = sc->ref_clock_freq / (22 * (best_div_a + 1) * in cdnc_i2c_set_freq()
216 sc->ref_clock_freq, sc->i2c_clock_freq); in cdnc_i2c_set_freq()
217 DPRINTF("%s: div_a=%d div_b=%d real-freq=%d\n", __func__, best_div_a, in cdnc_i2c_set_freq()
220 sc->cfg_reg_shadow &= ~(CDNC_I2C_CR_DIV_A_MASK | in cdnc_i2c_set_freq()
222 sc->cfg_reg_shadow |= CDNC_I2C_CR_DIV_A(best_div_a) | in cdnc_i2c_set_freq()
224 WR2(sc, CDNC_I2C_CR, sc->cfg_reg_shadow); in cdnc_i2c_set_freq()
226 sc->i2c_clk_real_freq = clk_out; in cdnc_i2c_set_freq()
237 sc->cfg_reg_shadow = 0; in cdnc_i2c_init_hw()
239 sc->hold = 0; in cdnc_i2c_init_hw()
245 /* Max out bogus time-out register. */ in cdnc_i2c_init_hw()
261 sc->cfg_reg_shadow &= CDNC_I2C_CR_DIV_A_MASK | CDNC_I2C_CR_DIV_B_MASK; in cdnc_i2c_errs()
262 WR2(sc, CDNC_I2C_CR, sc->cfg_reg_shadow | CDNC_I2C_CR_CLR_FIFO); in cdnc_i2c_errs()
263 sc->hold = 0; in cdnc_i2c_errs()
290 sc->i2c_clock_freq = IICBUS_GET_FREQUENCY(sc->iicbus, speed); in cdnc_i2c_reset()
307 sc->interrupts++; in cdnc_i2c_intr()
316 sc->timeout_ints++; in cdnc_i2c_intr()
318 sc->istat |= status; in cdnc_i2c_intr()
330 uint16_t flags = msg->flags; in cdnc_i2c_xfer_rd()
331 uint16_t len = msg->len; in cdnc_i2c_xfer_rd()
338 if (sc->hwtype == HWTYPE_CDNS_R1P10 && (flags & IIC_M_NOSTOP)) in cdnc_i2c_xfer_rd()
345 sc->cfg_reg_shadow &= CDNC_I2C_CR_DIV_A_MASK | CDNC_I2C_CR_DIV_B_MASK; in cdnc_i2c_xfer_rd()
346 sc->cfg_reg_shadow |= CDNC_I2C_CR_HOLD | CDNC_I2C_CR_ACKEN | in cdnc_i2c_xfer_rd()
348 WR2(sc, CDNC_I2C_CR, sc->cfg_reg_shadow | CDNC_I2C_CR_CLR_FIFO); in cdnc_i2c_xfer_rd()
349 sc->hold = 1; in cdnc_i2c_xfer_rd()
352 nbytes = MIN(CDNC_I2C_FIFO_SIZE - 2, len); in cdnc_i2c_xfer_rd()
358 sc->cfg_reg_shadow &= ~CDNC_I2C_CR_HOLD; in cdnc_i2c_xfer_rd()
359 WR2(sc, CDNC_I2C_CR, sc->cfg_reg_shadow); in cdnc_i2c_xfer_rd()
360 sc->hold = 0; in cdnc_i2c_xfer_rd()
365 WR2(sc, CDNC_I2C_ADDR, msg->slave >> 1); in cdnc_i2c_xfer_rd()
376 error = mtx_sleep(sc, &sc->sc_mtx, 0, "cdi2c", hz); in cdnc_i2c_xfer_rd()
384 else if (sc->istat & CDNC_I2C_ISR_ERRS) in cdnc_i2c_xfer_rd()
385 error = cdnc_i2c_errs(sc, sc->istat); in cdnc_i2c_xfer_rd()
386 sc->istat = 0; in cdnc_i2c_xfer_rd()
392 while (nbytes-- > 0) { in cdnc_i2c_xfer_rd()
398 msg->buf[idx++] = RD2(sc, CDNC_I2C_DATA); in cdnc_i2c_xfer_rd()
399 len--; in cdnc_i2c_xfer_rd()
410 uint16_t flags = msg->flags; in cdnc_i2c_xfer_wr()
411 uint16_t len = msg->len; in cdnc_i2c_xfer_wr()
419 sc->cfg_reg_shadow &= CDNC_I2C_CR_DIV_A_MASK | CDNC_I2C_CR_DIV_B_MASK; in cdnc_i2c_xfer_wr()
420 sc->cfg_reg_shadow |= CDNC_I2C_CR_HOLD | CDNC_I2C_CR_ACKEN | in cdnc_i2c_xfer_wr()
422 WR2(sc, CDNC_I2C_CR, sc->cfg_reg_shadow | CDNC_I2C_CR_CLR_FIFO); in cdnc_i2c_xfer_wr()
423 sc->hold = 1; in cdnc_i2c_xfer_wr()
427 nbytes = MIN(len, CDNC_I2C_FIFO_SIZE - in cdnc_i2c_xfer_wr()
428 RD1(sc, CDNC_I2C_TRANS_SIZE) - 1); in cdnc_i2c_xfer_wr()
429 len -= nbytes; in cdnc_i2c_xfer_wr()
430 while (nbytes-- > 0) in cdnc_i2c_xfer_wr()
431 WR2(sc, CDNC_I2C_DATA, msg->buf[idx++]); in cdnc_i2c_xfer_wr()
436 sc->cfg_reg_shadow &= ~CDNC_I2C_CR_HOLD; in cdnc_i2c_xfer_wr()
437 WR2(sc, CDNC_I2C_CR, sc->cfg_reg_shadow); in cdnc_i2c_xfer_wr()
438 sc->hold = 0; in cdnc_i2c_xfer_wr()
443 WR2(sc, CDNC_I2C_ADDR, msg->slave >> 1); in cdnc_i2c_xfer_wr()
451 error = mtx_sleep(sc, &sc->sc_mtx, 0, "cdi2c", hz); in cdnc_i2c_xfer_wr()
459 else if (sc->istat & CDNC_I2C_ISR_ERRS) in cdnc_i2c_xfer_wr()
460 error = cdnc_i2c_errs(sc, sc->istat); in cdnc_i2c_xfer_wr()
461 sc->istat = 0; in cdnc_i2c_xfer_wr()
481 __func__, i, sc->hold, msgs[i].slave, msgs[i].flags, in cdnc_i2c_transfer()
484 if (!sc->hold && (msgs[i].flags & IIC_M_NOSTART)) in cdnc_i2c_transfer()
514 &sc->i2c_clk_real_freq, 0, "i2c clock real frequency"); in cdnc_i2c_add_sysctls()
517 &sc->interrupts, 0, "interrupt calls"); in cdnc_i2c_add_sysctls()
519 &sc->timeout_ints, 0, "hardware timeout interrupts"); in cdnc_i2c_add_sysctls()
530 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) in cdnc_i2c_probe()
533 device_set_desc(dev, "Cadence I2C Controller"); in cdnc_i2c_probe()
551 sc->dev = dev; in cdnc_i2c_attach()
552 sc->hwtype = ofw_bus_search_compatible(dev, compat_data)->ocd_data; in cdnc_i2c_attach()
556 /* Get ref-clock and i2c-clock properties. */ in cdnc_i2c_attach()
558 if (OF_getprop(node, "ref-clock", &cell, sizeof(cell)) > 0) in cdnc_i2c_attach()
559 sc->ref_clock_freq = fdt32_to_cpu(cell); in cdnc_i2c_attach()
560 else if (clk_get_by_ofw_index(dev, node, 0, &sc->ref_clk) == 0) { in cdnc_i2c_attach()
561 if ((err = clk_enable(sc->ref_clk)) != 0) in cdnc_i2c_attach()
564 else if ((err = clk_get_freq(sc->ref_clk, &freq)) != 0) in cdnc_i2c_attach()
568 sc->ref_clock_freq = freq; in cdnc_i2c_attach()
571 device_printf(dev, "must have ref-clock property\n"); in cdnc_i2c_attach()
574 if (OF_getprop(node, "clock-frequency", &cell, sizeof(cell)) > 0) in cdnc_i2c_attach()
575 sc->i2c_clock_freq = fdt32_to_cpu(cell); in cdnc_i2c_attach()
577 sc->i2c_clock_freq = CDNC_I2C_DEFAULT_I2C_CLOCK; in cdnc_i2c_attach()
581 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, in cdnc_i2c_attach()
583 if (sc->mem_res == NULL) { in cdnc_i2c_attach()
591 sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, in cdnc_i2c_attach()
593 if (sc->irq_res == NULL) { in cdnc_i2c_attach()
600 err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, in cdnc_i2c_attach()
601 NULL, cdnc_i2c_intr, sc, &sc->intrhandle); in cdnc_i2c_attach()
615 sc->iicbus = device_add_child(dev, "iicbus", DEVICE_UNIT_ANY); in cdnc_i2c_attach()
631 if (sc->ref_clk != NULL) { in cdnc_i2c_detach()
632 clk_release(sc->ref_clk); in cdnc_i2c_detach()
633 sc->ref_clk = NULL; in cdnc_i2c_detach()
637 if (sc->mem_res != NULL) { in cdnc_i2c_detach()
638 sc->cfg_reg_shadow = 0; in cdnc_i2c_detach()
647 if (sc->irq_res != NULL) { in cdnc_i2c_detach()
648 if (sc->intrhandle) in cdnc_i2c_detach()
649 bus_teardown_intr(dev, sc->irq_res, sc->intrhandle); in cdnc_i2c_detach()
651 rman_get_rid(sc->irq_res), sc->irq_res); in cdnc_i2c_detach()
652 sc->irq_res = NULL; in cdnc_i2c_detach()
656 if (sc->mem_res != NULL) { in cdnc_i2c_detach()
658 rman_get_rid(sc->mem_res), sc->mem_res); in cdnc_i2c_detach()
659 sc->mem_res = NULL; in cdnc_i2c_detach()