Lines Matching +full:i2c +full:- +full:transfer +full:- +full:timeout +full:- +full:us
38 * Intel fourth generation mobile cpus integrated I2C device.
79 * lines are taken from I2C specifications.
147 * 0 - Try read clock registers from ACPI and fallback to p.1.
148 * 1 - Calculate values based on controller type (IC clock rate).
149 * 2 - Use values inherited from DragonflyBSD driver (old behavior).
150 * 3 - Keep clock registers intact.
157 * Low-level inline support functions
162 bus_write_4(sc->regs_res, reg, value); in reg_write()
163 bus_barrier(sc->regs_res, reg, 4, BUS_SPACE_BARRIER_WRITE); in reg_write()
171 bus_barrier(sc->regs_res, reg, 4, BUS_SPACE_BARRIER_READ); in reg_read()
172 value = bus_read_4(sc->regs_res, reg); in reg_read()
179 if (sc->intr_mask != val) { in ig4iic_set_intr_mask()
181 sc->intr_mask = val; in ig4iic_set_intr_mask()
200 /* User-requested abort. Not really a error */ in intrstat2iic()
256 for (retry = 100; retry > 0; --retry) { in set_controller()
268 * Wait up to 25ms for the requested interrupt using a 25uS polling loop.
275 int txlvl = -1; in wait_intr()
290 * reset the timeout if we see a change in the transmit in wait_intr()
313 mtx_lock_spin(&sc->io_lock); in wait_intr()
315 msleep_spin(sc, &sc->io_lock, "i2cwait", in wait_intr()
318 mtx_unlock_spin(&sc->io_lock); in wait_intr()
333 * This operation does not issue anything to the I2C bus but sets
344 if (sc->slave_valid && sc->last_slave == slave && in set_slave_addr()
345 sc->use_10bit == use_10bit) { in set_slave_addr()
348 sc->use_10bit = use_10bit; in set_slave_addr()
362 if (sc->use_10bit) { in set_slave_addr()
369 sc->slave_valid = true; in set_slave_addr()
370 sc->last_slave = slave; in set_slave_addr()
384 * and I2C bus STOP condition. in ig4iic_xfer_start()
421 * Amount of unread data before next burst to get better I2C bus utilization.
423 * Intel-recommended value is 16 for DMA transfers with 64-byte depth FIFOs.
442 burst = sc->cfg.txfifo_depth - in ig4iic_read()
449 burst = sc->cfg.txfifo_depth - in ig4iic_read()
453 burst = MIN(burst, sc->cfg.rxfifo_depth - in ig4iic_read()
454 (requested - received)); in ig4iic_read()
460 if (stop && requested == len - 1) in ig4iic_read()
467 if (requested != len && requested - received > IG4_FIFO_LOWAT) in ig4iic_read()
470 while (received < requested - lowat) { in ig4iic_read()
471 burst = MIN(requested - received, in ig4iic_read()
474 while (burst--) in ig4iic_read()
479 requested - received - lowat - 1); in ig4iic_read()
503 burst = sc->cfg.txfifo_depth - in ig4iic_write()
510 if (stop && sent == len - 1) in ig4iic_write()
516 if (len - sent <= sc->cfg.txfifo_depth) in ig4iic_write()
517 lowat = sc->cfg.txfifo_depth - (len - sent); in ig4iic_write()
543 * The hardware interface imposes limits on allowed I2C messages. in ig4iic_transfer()
552 * of the transfer direction happens, so it's impossible to have in ig4iic_transfer()
566 if (i == nmsgs - 1 && (msgs[i].flags & IIC_M_NOSTOP) != 0) { in ig4iic_transfer()
577 (msgs[i - 1].flags & IIC_M_NOSTOP) == 0) { in ig4iic_transfer()
581 if ((msgs[i - 1].flags & IIC_M_NOSTOP) != 0 && in ig4iic_transfer()
582 msgs[i].slave != msgs[i - 1].slave) { in ig4iic_transfer()
588 (msgs[i - 1].flags & IIC_M_RD)) { in ig4iic_transfer()
602 allocated = sx_xlocked(&sc->call_lock) != 0; in ig4iic_transfer()
604 sx_xlock(&sc->call_lock); in ig4iic_transfer()
606 /* Debugging - dump registers. */ in ig4iic_transfer()
627 if (!sc->slave_valid || in ig4iic_transfer()
628 (msgs[i].slave >> 1) != sc->last_slave) { in ig4iic_transfer()
647 /* Wait for error or stop condition occurred on the I2C bus */ in ig4iic_transfer()
657 * both FIFOs. Do a controller soft reset if transfer in ig4iic_transfer()
662 device_printf(sc->dev, "Failed to abort " in ig4iic_transfer()
663 "transfer. Do the controller reset.\n"); in ig4iic_transfer()
683 sx_unlock(&sc->call_lock); in ig4iic_transfer()
693 allocated = sx_xlocked(&sc->call_lock) != 0; in ig4iic_reset()
695 sx_xlock(&sc->call_lock); in ig4iic_reset()
699 *oldaddr = sc->last_slave << 1; in ig4iic_reset()
702 sc->slave_valid = false; in ig4iic_reset()
705 sx_unlock(&sc->call_lock); in ig4iic_reset()
721 if (sx_try_xlock(&sc->call_lock) == 0) in ig4iic_callback()
724 sx_xlock(&sc->call_lock); in ig4iic_callback()
728 sx_unlock(&sc->call_lock); in ig4iic_callback()
775 sda_fall_time = hw->sda_fall_time == 0 ? tf_max : hw->sda_fall_time; in ig4iic_clk_params()
777 ((hw->ic_clock_rate * (thigh + sda_fall_time) + 500) / 1000 - 3); in ig4iic_clk_params()
779 scl_fall_time = hw->scl_fall_time == 0 ? tf_max : hw->scl_fall_time; in ig4iic_clk_params()
781 ((hw->ic_clock_rate * (tlow + scl_fall_time) + 500) / 1000 - 1); in ig4iic_clk_params()
787 if (hw->sda_hold_time != 0) in ig4iic_clk_params()
789 ((hw->ic_clock_rate * hw->sda_hold_time + 500) / 1000); in ig4iic_clk_params()
812 if (obj->Type == ACPI_TYPE_PACKAGE && obj->Package.Count == 3) { in ig4iic_acpi_params()
813 elems = obj->Package.Elements; in ig4iic_acpi_params()
835 sc->cfg.version = reg_read(sc, IG4_REG_COMP_VER); in ig4iic_get_config()
836 sc->cfg.bus_speed = reg_read(sc, IG4_REG_CTL) & IG4_CTL_SPEED_MASK; in ig4iic_get_config()
837 sc->cfg.ss_scl_hcnt = in ig4iic_get_config()
839 sc->cfg.ss_scl_lcnt = in ig4iic_get_config()
841 sc->cfg.fs_scl_hcnt = in ig4iic_get_config()
843 sc->cfg.fs_scl_lcnt = in ig4iic_get_config()
845 sc->cfg.ss_sda_hold = sc->cfg.fs_sda_hold = in ig4iic_get_config()
848 if (sc->cfg.bus_speed != IG4_CTL_SPEED_STD) in ig4iic_get_config()
849 sc->cfg.bus_speed = IG4_CTL_SPEED_FAST; in ig4iic_get_config()
852 if (sc->version == IG4_HASWELL || sc->version == IG4_ATOM) { in ig4iic_get_config()
855 sc->cfg.txfifo_depth = IG4_PARAM1_TXFIFO_DEPTH(v); in ig4iic_get_config()
857 sc->cfg.rxfifo_depth = IG4_PARAM1_RXFIFO_DEPTH(v); in ig4iic_get_config()
860 /* Override hardware config with IC_clock-based counter values */ in ig4iic_get_config()
861 if (ig4_timings < 2 && sc->version < nitems(ig4iic_hw)) { in ig4iic_get_config()
862 hw = &ig4iic_hw[sc->version]; in ig4iic_get_config()
863 sc->cfg.bus_speed = IG4_CTL_SPEED_FAST; in ig4iic_get_config()
864 ig4iic_clk_params(hw, IG4_CTL_SPEED_STD, &sc->cfg.ss_scl_hcnt, in ig4iic_get_config()
865 &sc->cfg.ss_scl_lcnt, &sc->cfg.ss_sda_hold); in ig4iic_get_config()
866 ig4iic_clk_params(hw, IG4_CTL_SPEED_FAST, &sc->cfg.fs_scl_hcnt, in ig4iic_get_config()
867 &sc->cfg.fs_scl_lcnt, &sc->cfg.fs_sda_hold); in ig4iic_get_config()
868 if (hw->txfifo_depth != 0) in ig4iic_get_config()
869 sc->cfg.txfifo_depth = hw->txfifo_depth; in ig4iic_get_config()
870 if (hw->rxfifo_depth != 0) in ig4iic_get_config()
871 sc->cfg.rxfifo_depth = hw->rxfifo_depth; in ig4iic_get_config()
881 sc->cfg.bus_speed = IG4_CTL_SPEED_STD; in ig4iic_get_config()
882 sc->cfg.ss_scl_hcnt = sc->cfg.fs_scl_hcnt = 100; in ig4iic_get_config()
883 sc->cfg.ss_scl_lcnt = sc->cfg.fs_scl_lcnt = 125; in ig4iic_get_config()
884 if (sc->version == IG4_SKYLAKE) in ig4iic_get_config()
885 sc->cfg.ss_sda_hold = sc->cfg.fs_sda_hold = 28; in ig4iic_get_config()
890 if (ig4_timings == 0 && (handle = acpi_get_handle(sc->dev)) != NULL) { in ig4iic_get_config()
891 ig4iic_acpi_params(handle, "SSCN", &sc->cfg.ss_scl_hcnt, in ig4iic_get_config()
892 &sc->cfg.ss_scl_lcnt, &sc->cfg.ss_sda_hold); in ig4iic_get_config()
893 ig4iic_acpi_params(handle, "FMCN", &sc->cfg.fs_scl_hcnt, in ig4iic_get_config()
894 &sc->cfg.fs_scl_lcnt, &sc->cfg.fs_sda_hold); in ig4iic_get_config()
899 device_printf(sc->dev, "Controller parameters:\n"); in ig4iic_get_config()
901 sc->cfg.bus_speed == IG4_CTL_SPEED_STD ? "Std" : "Fast"); in ig4iic_get_config()
904 sc->cfg.ss_scl_hcnt, sc->cfg.ss_scl_lcnt, in ig4iic_get_config()
905 sc->cfg.ss_sda_hold); in ig4iic_get_config()
907 sc->cfg.fs_scl_hcnt, sc->cfg.fs_scl_lcnt, in ig4iic_get_config()
908 sc->cfg.fs_sda_hold); in ig4iic_get_config()
918 if (IG4_HAS_ADDREGS(sc->version) && (v & IG4_RESTORE_REQUIRED)) { in ig4iic_set_config()
925 if ((sc->version == IG4_HASWELL || sc->version == IG4_ATOM) && reset) { in ig4iic_set_config()
928 } else if (IG4_HAS_ADDREGS(sc->version) && reset) { in ig4iic_set_config()
933 if (sc->version == IG4_ATOM) in ig4iic_set_config()
936 if (sc->version == IG4_HASWELL || sc->version == IG4_ATOM) { in ig4iic_set_config()
943 if (sc->version == IG4_HASWELL && in ig4iic_set_config()
951 if (sc->version == IG4_HASWELL) { in ig4iic_set_config()
954 } else if (IG4_HAS_ADDREGS(sc->version)) { in ig4iic_set_config()
959 if (sc->version == IG4_HASWELL || sc->version == IG4_ATOM) { in ig4iic_set_config()
966 device_printf(sc->dev, "controller error during attach-1\n"); in ig4iic_set_config()
972 sc->intr_mask = 0; in ig4iic_set_config()
974 reg_write(sc, IG4_REG_SS_SCL_HCNT, sc->cfg.ss_scl_hcnt); in ig4iic_set_config()
975 reg_write(sc, IG4_REG_SS_SCL_LCNT, sc->cfg.ss_scl_lcnt); in ig4iic_set_config()
976 reg_write(sc, IG4_REG_FS_SCL_HCNT, sc->cfg.fs_scl_hcnt); in ig4iic_set_config()
977 reg_write(sc, IG4_REG_FS_SCL_LCNT, sc->cfg.fs_scl_lcnt); in ig4iic_set_config()
979 (sc->cfg.bus_speed & IG4_CTL_SPEED_MASK) == IG4_CTL_SPEED_STD ? in ig4iic_set_config()
980 sc->cfg.ss_sda_hold : sc->cfg.fs_sda_hold); in ig4iic_set_config()
989 (sc->cfg.bus_speed & IG4_CTL_SPEED_MASK)); in ig4iic_set_config()
991 /* Force setting of the target address on the next transfer */ in ig4iic_set_config()
992 sc->slave_valid = false; in ig4iic_set_config()
1007 if (sc->cfg.txfifo_depth == 0) { in ig4iic_get_fifo()
1010 sc->cfg.txfifo_depth = in ig4iic_get_fifo()
1014 if (sc->cfg.rxfifo_depth == 0) { in ig4iic_get_fifo()
1017 sc->cfg.rxfifo_depth = in ig4iic_get_fifo()
1023 sc->cfg.rxfifo_depth, sc->cfg.txfifo_depth); in ig4iic_get_fifo()
1035 mtx_init(&sc->io_lock, "IG4 I/O lock", NULL, MTX_SPIN); in ig4iic_attach()
1036 sx_init(&sc->call_lock, "IG4 call lock"); in ig4iic_attach()
1040 error = ig4iic_set_config(sc, IG4_HAS_ADDREGS(sc->version)); in ig4iic_attach()
1045 sc->iicbus = device_add_child(sc->dev, "iicbus", DEVICE_UNIT_ANY); in ig4iic_attach()
1046 if (sc->iicbus == NULL) { in ig4iic_attach()
1047 device_printf(sc->dev, "iicbus driver not found\n"); in ig4iic_attach()
1053 device_printf(sc->dev, "controller error during attach-2\n"); in ig4iic_attach()
1058 device_printf(sc->dev, "controller error during attach-3\n"); in ig4iic_attach()
1062 error = bus_setup_intr(sc->dev, sc->intr_res, INTR_TYPE_MISC | INTR_MPSAFE, in ig4iic_attach()
1063 ig4iic_intr, NULL, sc, &sc->intr_handle); in ig4iic_attach()
1065 device_printf(sc->dev, in ig4iic_attach()
1069 bus_attach_children(sc->dev); in ig4iic_attach()
1080 error = bus_generic_detach(sc->dev); in ig4iic_detach()
1083 if (sc->intr_handle) in ig4iic_detach()
1084 bus_teardown_intr(sc->dev, sc->intr_res, sc->intr_handle); in ig4iic_detach()
1086 sx_xlock(&sc->call_lock); in ig4iic_detach()
1088 sc->iicbus = NULL; in ig4iic_detach()
1089 sc->intr_handle = NULL; in ig4iic_detach()
1093 sx_xunlock(&sc->call_lock); in ig4iic_detach()
1095 mtx_destroy(&sc->io_lock); in ig4iic_detach()
1096 sx_destroy(&sc->call_lock); in ig4iic_detach()
1107 error = bus_generic_suspend(sc->dev); in ig4iic_suspend()
1109 sx_xlock(&sc->call_lock); in ig4iic_suspend()
1111 if (IG4_HAS_ADDREGS(sc->version)) { in ig4iic_suspend()
1117 * Controller can become dysfunctional if I2C lines are pulled in ig4iic_suspend()
1118 * down when suspend procedure turns off power to I2C device. in ig4iic_suspend()
1123 sx_xunlock(&sc->call_lock); in ig4iic_suspend()
1132 sx_xlock(&sc->call_lock); in ig4iic_resume()
1133 if (ig4iic_set_config(sc, IG4_HAS_ADDREGS(sc->version))) in ig4iic_resume()
1134 device_printf(sc->dev, "controller error during resume\n"); in ig4iic_resume()
1135 sx_xunlock(&sc->call_lock); in ig4iic_resume()
1137 error = bus_generic_resume(sc->dev); in ig4iic_resume()
1151 mtx_lock_spin(&sc->io_lock); in ig4iic_intr()
1153 if (sc->intr_mask != 0 && reg_read(sc, IG4_REG_INTR_STAT) != 0) { in ig4iic_intr()
1159 mtx_unlock_spin(&sc->io_lock); in ig4iic_intr()
1165 device_printf(sc->dev, " %-23s %08x\n", #reg, reg_read(sc, reg))
1170 device_printf(sc->dev, "ig4iic register dump:\n"); in ig4iic_dump()
1196 if (sc->version == IG4_ATOM) { in ig4iic_dump()
1200 if (sc->version == IG4_HASWELL || sc->version == IG4_ATOM) { in ig4iic_dump()
1203 } else if (sc->version == IG4_SKYLAKE) { in ig4iic_dump()
1206 if (sc->version == IG4_HASWELL) { in ig4iic_dump()
1209 } else if (IG4_HAS_ADDREGS(sc->version)) { in ig4iic_dump()