Lines Matching refs:margining
517 static int margining_modify_error_counter(struct tb_margining *margining, in margining_modify_error_counter() argument
521 struct tb_port *port = margining->port; in margining_modify_error_counter()
531 return usb4_port_sw_margin(port, margining->target, margining->index, in margining_modify_error_counter()
535 static bool supports_software(const struct tb_margining *margining) in supports_software() argument
537 if (margining->gen < 4) in supports_software()
538 return margining->caps[0] & USB4_MARGIN_CAP_0_MODES_SW; in supports_software()
539 return margining->caps[2] & USB4_MARGIN_CAP_2_MODES_SW; in supports_software()
542 static bool supports_hardware(const struct tb_margining *margining) in supports_hardware() argument
544 if (margining->gen < 4) in supports_hardware()
545 return margining->caps[0] & USB4_MARGIN_CAP_0_MODES_HW; in supports_hardware()
546 return margining->caps[2] & USB4_MARGIN_CAP_2_MODES_HW; in supports_hardware()
549 static bool all_lanes(const struct tb_margining *margining) in all_lanes() argument
551 return margining->caps[0] & USB4_MARGIN_CAP_0_ALL_LANES; in all_lanes()
555 independent_voltage_margins(const struct tb_margining *margining) in independent_voltage_margins() argument
557 if (margining->gen < 4) { in independent_voltage_margins()
558 switch (FIELD_GET(USB4_MARGIN_CAP_0_VOLTAGE_INDP_MASK, margining->caps[0])) { in independent_voltage_margins()
567 switch (FIELD_GET(USB4_MARGIN_CAP_2_VOLTAGE_INDP_MASK, margining->caps[2])) { in independent_voltage_margins()
577 static bool supports_time(const struct tb_margining *margining) in supports_time() argument
579 if (margining->gen < 4) in supports_time()
580 return margining->caps[0] & USB4_MARGIN_CAP_0_TIME; in supports_time()
581 return margining->caps[2] & USB4_MARGIN_CAP_2_TIME; in supports_time()
586 independent_time_margins(const struct tb_margining *margining) in independent_time_margins() argument
588 if (margining->gen < 4) { in independent_time_margins()
589 switch (FIELD_GET(USB4_MARGIN_CAP_1_TIME_INDP_MASK, margining->caps[1])) { in independent_time_margins()
598 switch (FIELD_GET(USB4_MARGIN_CAP_2_TIME_INDP_MASK, margining->caps[2])) { in independent_time_margins()
609 supports_optional_voltage_offset_range(const struct tb_margining *margining) in supports_optional_voltage_offset_range() argument
611 return margining->caps[0] & USB4_MARGIN_CAP_0_OPT_VOLTAGE_SUPPORT; in supports_optional_voltage_offset_range()
619 struct tb_margining *margining = s->private; in margining_ber_level_write() local
620 struct tb *tb = margining->port->sw->tb; in margining_ber_level_write()
628 if (margining->software) { in margining_ber_level_write()
645 if (val < margining->min_ber_level || in margining_ber_level_write()
646 val > margining->max_ber_level) { in margining_ber_level_write()
651 margining->ber_level = val; in margining_ber_level_write()
671 const struct tb_margining *margining = s->private; in margining_ber_level_show() local
673 if (margining->software) in margining_ber_level_show()
675 ber_level_show(s, margining->ber_level); in margining_ber_level_show()
682 struct tb_margining *margining = s->private; in margining_caps_show() local
683 struct tb *tb = margining->port->sw->tb; in margining_caps_show()
690 for (int i = 0; i < ARRAY_SIZE(margining->caps); i++) in margining_caps_show()
691 seq_printf(s, "0x%08x\n", margining->caps[i]); in margining_caps_show()
694 supports_software(margining) ? "yes" : "no"); in margining_caps_show()
695 if (supports_hardware(margining)) { in margining_caps_show()
698 ber_level_show(s, margining->min_ber_level); in margining_caps_show()
700 ber_level_show(s, margining->max_ber_level); in margining_caps_show()
706 str_yes_no(all_lanes(margining))); in margining_caps_show()
708 margining->voltage_steps); in margining_caps_show()
710 margining->max_voltage_offset); in margining_caps_show()
712 str_yes_no(supports_optional_voltage_offset_range(margining))); in margining_caps_show()
713 if (supports_optional_voltage_offset_range(margining)) { in margining_caps_show()
715 margining->voltage_steps_optional_range); in margining_caps_show()
717 margining->max_voltage_offset_optional_range); in margining_caps_show()
720 switch (independent_voltage_margins(margining)) { in margining_caps_show()
737 tb_port_warn(margining->port, in margining_caps_show()
743 if (supports_time(margining)) { in margining_caps_show()
746 str_yes_no(margining->caps[1] & USB4_MARGIN_CAP_1_TIME_DESTR)); in margining_caps_show()
748 switch (independent_time_margins(margining)) { in margining_caps_show()
765 tb_port_warn(margining->port, in margining_caps_show()
772 margining->time_steps); in margining_caps_show()
774 margining->max_time_offset); in margining_caps_show()
812 struct tb_margining *margining = s->private; in margining_lanes_write() local
813 struct tb_port *port = margining->port; in margining_lanes_write()
837 if (lane == USB4_MARGINING_LANE_ALL && !all_lanes(margining)) in margining_lanes_write()
843 if (lane == USB4_MARGINING_LANE_RX2 && !margining->asym_rx) in margining_lanes_write()
846 margining->lanes = lane; in margining_lanes_write()
854 struct tb_margining *margining = s->private; in margining_lanes_show() local
855 struct tb_port *port = margining->port; in margining_lanes_show()
861 !all_lanes(margining)) in margining_lanes_show()
864 !margining->asym_rx) in margining_lanes_show()
870 if (lane_names[i].lane == margining->lanes) in margining_lanes_show()
888 struct tb_margining *margining = s->private; in margining_voltage_time_offset_write() local
889 struct tb *tb = margining->port->sw->tb; in margining_voltage_time_offset_write()
899 if (!margining->software) in margining_voltage_time_offset_write()
902 if (margining->time) in margining_voltage_time_offset_write()
903 max_margin = margining->time_steps; in margining_voltage_time_offset_write()
905 if (margining->optional_voltage_offset_range) in margining_voltage_time_offset_write()
906 max_margin = margining->voltage_steps_optional_range; in margining_voltage_time_offset_write()
908 max_margin = margining->voltage_steps; in margining_voltage_time_offset_write()
910 margining->voltage_time_offset = clamp(val, 0, max_margin); in margining_voltage_time_offset_write()
919 const struct tb_margining *margining = s->private; in margining_voltage_time_offset_show() local
920 struct tb *tb = margining->port->sw->tb; in margining_voltage_time_offset_show()
923 if (!margining->software) in margining_voltage_time_offset_show()
926 seq_printf(s, "%d\n", margining->voltage_time_offset); in margining_voltage_time_offset_show()
939 struct tb_margining *margining = s->private; in margining_error_counter_write() local
940 struct tb *tb = margining->port->sw->tb; in margining_error_counter_write()
961 if (!margining->software) in margining_error_counter_write()
964 margining->error_counter = error_counter; in margining_error_counter_write()
972 const struct tb_margining *margining = s->private; in margining_error_counter_show() local
973 struct tb *tb = margining->port->sw->tb; in margining_error_counter_show()
976 if (!margining->software) in margining_error_counter_show()
979 switch (margining->error_counter) { in margining_error_counter_show()
1004 struct tb_margining *margining = s->private; in margining_dwell_time_write() local
1005 struct tb *tb = margining->port->sw->tb; in margining_dwell_time_write()
1014 if (!margining->software) in margining_dwell_time_write()
1017 margining->dwell_time = clamp(val, MIN_DWELL_TIME, MAX_DWELL_TIME); in margining_dwell_time_write()
1025 struct tb_margining *margining = s->private; in margining_dwell_time_show() local
1026 struct tb *tb = margining->port->sw->tb; in margining_dwell_time_show()
1029 if (!margining->software) in margining_dwell_time_show()
1032 seq_printf(s, "%d\n", margining->dwell_time); in margining_dwell_time_show()
1044 struct tb_margining *margining = s->private; in margining_optional_voltage_offset_write() local
1045 struct tb *tb = margining->port->sw->tb; in margining_optional_voltage_offset_write()
1054 margining->optional_voltage_offset_range = val; in margining_optional_voltage_offset_write()
1063 struct tb_margining *margining = s->private; in margining_optional_voltage_offset_show() local
1064 struct tb *tb = margining->port->sw->tb; in margining_optional_voltage_offset_show()
1067 seq_printf(s, "%u\n", margining->optional_voltage_offset_range); in margining_optional_voltage_offset_show()
1079 struct tb_margining *margining = s->private; in margining_mode_write() local
1080 struct tb *tb = margining->port->sw->tb; in margining_mode_write()
1096 if (supports_software(margining)) in margining_mode_write()
1097 margining->software = true; in margining_mode_write()
1101 if (supports_hardware(margining)) in margining_mode_write()
1102 margining->software = false; in margining_mode_write()
1118 struct tb_margining *margining = s->private; in margining_mode_show() local
1119 struct tb *tb = margining->port->sw->tb; in margining_mode_show()
1125 if (supports_software(margining)) { in margining_mode_show()
1126 if (margining->software) in margining_mode_show()
1132 if (supports_hardware(margining)) { in margining_mode_show()
1133 if (margining->software) in margining_mode_show()
1146 static int margining_run_sw(struct tb_margining *margining, in margining_run_sw() argument
1149 u32 nsamples = margining->dwell_time / DWELL_SAMPLE_INTERVAL; in margining_run_sw()
1152 ret = usb4_port_sw_margin(margining->port, margining->target, margining->index, in margining_run_sw()
1153 params, margining->results); in margining_run_sw()
1160 ret = usb4_port_sw_margin_errors(margining->port, margining->target, in margining_run_sw()
1161 margining->index, &margining->results[1]); in margining_run_sw()
1165 if (margining->lanes == USB4_MARGINING_LANE_RX0) in margining_run_sw()
1167 margining->results[1]); in margining_run_sw()
1168 else if (margining->lanes == USB4_MARGINING_LANE_RX1) in margining_run_sw()
1170 margining->results[1]); in margining_run_sw()
1171 else if (margining->lanes == USB4_MARGINING_LANE_RX2) in margining_run_sw()
1173 margining->results[1]); in margining_run_sw()
1174 else if (margining->lanes == USB4_MARGINING_LANE_ALL) in margining_run_sw()
1175 errors = margining->results[1]; in margining_run_sw()
1189 margining_modify_error_counter(margining, margining->lanes, in margining_run_sw()
1194 static int validate_margining(struct tb_margining *margining) in validate_margining() argument
1202 if (margining->lanes == USB4_MARGINING_LANE_RX2) { in validate_margining()
1205 ret = tb_port_get_link_width(margining->port); in validate_margining()
1209 tb_port_warn(margining->port, "link is %s expected %s", in validate_margining()
1221 struct tb_margining *margining = data; in margining_run_write() local
1222 struct tb_port *port = margining->port; in margining_run_write()
1223 struct device *dev = margining->dev; in margining_run_write()
1239 ret = validate_margining(margining); in margining_run_write()
1264 memset(margining->results, 0, sizeof(margining->results)); in margining_run_write()
1266 if (margining->software) { in margining_run_write()
1269 .lanes = margining->lanes, in margining_run_write()
1270 .time = margining->time, in margining_run_write()
1271 .voltage_time_offset = margining->voltage_time_offset, in margining_run_write()
1272 .right_high = margining->right_high, in margining_run_write()
1273 .upper_eye = margining->upper_eye, in margining_run_write()
1274 .optional_voltage_offset_range = margining->optional_voltage_offset_range, in margining_run_write()
1279 margining->time ? "time" : "voltage", dev_name(dev), in margining_run_write()
1280 margining->lanes); in margining_run_write()
1282 ret = margining_run_sw(margining, ¶ms); in margining_run_write()
1285 .ber_level = margining->ber_level, in margining_run_write()
1286 .lanes = margining->lanes, in margining_run_write()
1287 .time = margining->time, in margining_run_write()
1288 .right_high = margining->right_high, in margining_run_write()
1289 .upper_eye = margining->upper_eye, in margining_run_write()
1290 .optional_voltage_offset_range = margining->optional_voltage_offset_range, in margining_run_write()
1295 margining->time ? "time" : "voltage", dev_name(dev), in margining_run_write()
1296 margining->lanes); in margining_run_write()
1298 ret = usb4_port_hw_margin(port, margining->target, margining->index, ¶ms, in margining_run_write()
1299 margining->results, ARRAY_SIZE(margining->results)); in margining_run_write()
1320 struct tb_margining *margining = s->private; in margining_results_write() local
1321 struct tb *tb = margining->port->sw->tb; in margining_results_write()
1327 memset(margining->results, 0, sizeof(margining->results)); in margining_results_write()
1329 if (margining->software) { in margining_results_write()
1331 margining_modify_error_counter(margining, in margining_results_write()
1341 const struct tb_margining *margining, u8 val) in voltage_margin_show() argument
1346 voltage = tmp * margining->max_voltage_offset / margining->voltage_steps; in voltage_margin_show()
1351 if (margining->optional_voltage_offset_range) in voltage_margin_show()
1356 const struct tb_margining *margining, u8 val) in time_margin_show() argument
1361 interval = tmp * margining->max_time_offset / margining->time_steps; in time_margin_show()
1387 const struct tb_margining *margining, in margining_hw_result_format() argument
1392 if (margining->time) { in margining_hw_result_format()
1393 val = margining_hw_result_val(margining->results, lane, true); in margining_hw_result_format()
1395 time_margin_show(s, margining, val); in margining_hw_result_format()
1396 val = margining_hw_result_val(margining->results, lane, false); in margining_hw_result_format()
1398 time_margin_show(s, margining, val); in margining_hw_result_format()
1400 val = margining_hw_result_val(margining->results, lane, true); in margining_hw_result_format()
1402 voltage_margin_show(s, margining, val); in margining_hw_result_format()
1403 val = margining_hw_result_val(margining->results, lane, false); in margining_hw_result_format()
1405 voltage_margin_show(s, margining, val); in margining_hw_result_format()
1411 struct tb_margining *margining = s->private; in margining_results_show() local
1412 struct tb *tb = margining->port->sw->tb; in margining_results_show()
1418 seq_printf(s, "0x%08x\n", margining->results[0]); in margining_results_show()
1420 if (!margining->software) { in margining_results_show()
1421 for (int i = 1; i < ARRAY_SIZE(margining->results); i++) in margining_results_show()
1422 seq_printf(s, "0x%08x\n", margining->results[i]); in margining_results_show()
1424 if (margining->lanes == USB4_MARGINING_LANE_ALL) { in margining_results_show()
1425 margining_hw_result_format(s, margining, in margining_results_show()
1427 margining_hw_result_format(s, margining, in margining_results_show()
1429 if (margining->asym_rx) in margining_results_show()
1430 margining_hw_result_format(s, margining, in margining_results_show()
1433 margining_hw_result_format(s, margining, in margining_results_show()
1434 margining->lanes); in margining_results_show()
1439 seq_printf(s, "0x%08x\n", margining->results[1]); in margining_results_show()
1441 result = FIELD_GET(USB4_MARGIN_SW_LANES_MASK, margining->results[0]); in margining_results_show()
1445 margining->results[1]); in margining_results_show()
1451 margining->results[1]); in margining_results_show()
1454 if (margining->asym_rx && in margining_results_show()
1458 margining->results[1]); in margining_results_show()
1473 struct tb_margining *margining = s->private; in margining_test_write() local
1474 struct tb *tb = margining->port->sw->tb; in margining_test_write()
1489 if (!strcmp(buf, "time") && supports_time(margining)) in margining_test_write()
1490 margining->time = true; in margining_test_write()
1492 margining->time = false; in margining_test_write()
1505 struct tb_margining *margining = s->private; in margining_test_show() local
1506 struct tb *tb = margining->port->sw->tb; in margining_test_show()
1511 if (supports_time(margining)) { in margining_test_show()
1512 if (margining->time) in margining_test_show()
1530 struct tb_margining *margining = s->private; in margining_margin_write() local
1531 struct tb *tb = margining->port->sw->tb; in margining_margin_write()
1546 if (margining->time) { in margining_margin_write()
1548 margining->right_high = false; in margining_margin_write()
1550 margining->right_high = true; in margining_margin_write()
1555 margining->right_high = false; in margining_margin_write()
1557 margining->right_high = true; in margining_margin_write()
1571 struct tb_margining *margining = s->private; in margining_margin_show() local
1572 struct tb *tb = margining->port->sw->tb; in margining_margin_show()
1577 if (margining->time) { in margining_margin_show()
1578 if (margining->right_high) in margining_margin_show()
1583 if (margining->right_high) in margining_margin_show()
1613 usb4->margining->upper_eye = false; in margining_eye_write()
1615 usb4->margining->upper_eye = true; in margining_eye_write()
1631 if (usb4->margining->upper_eye) in margining_eye_show()
1648 struct tb_margining *margining; in margining_alloc() local
1659 margining = kzalloc(sizeof(*margining), GFP_KERNEL); in margining_alloc()
1660 if (!margining) in margining_alloc()
1663 margining->port = port; in margining_alloc()
1664 margining->target = target; in margining_alloc()
1665 margining->index = index; in margining_alloc()
1666 margining->dev = dev; in margining_alloc()
1667 margining->gen = ret; in margining_alloc()
1668 margining->asym_rx = tb_port_width_supported(port, TB_LINK_WIDTH_ASYM_RX); in margining_alloc()
1670 ret = usb4_port_margining_caps(port, target, index, margining->caps, in margining_alloc()
1671 ARRAY_SIZE(margining->caps)); in margining_alloc()
1673 kfree(margining); in margining_alloc()
1678 if (supports_software(margining)) in margining_alloc()
1679 margining->software = true; in margining_alloc()
1681 if (margining->gen < 4) { in margining_alloc()
1682 val = FIELD_GET(USB4_MARGIN_CAP_0_VOLTAGE_STEPS_MASK, margining->caps[0]); in margining_alloc()
1683 margining->voltage_steps = val; in margining_alloc()
1684 val = FIELD_GET(USB4_MARGIN_CAP_0_MAX_VOLTAGE_OFFSET_MASK, margining->caps[0]); in margining_alloc()
1685 margining->max_voltage_offset = 74 + val * 2; in margining_alloc()
1687 val = FIELD_GET(USB4_MARGIN_CAP_2_VOLTAGE_STEPS_MASK, margining->caps[2]); in margining_alloc()
1688 margining->voltage_steps = val; in margining_alloc()
1689 val = FIELD_GET(USB4_MARGIN_CAP_2_MAX_VOLTAGE_OFFSET_MASK, margining->caps[2]); in margining_alloc()
1690 margining->max_voltage_offset = 74 + val * 2; in margining_alloc()
1693 if (supports_optional_voltage_offset_range(margining)) { in margining_alloc()
1695 margining->caps[0]); in margining_alloc()
1696 margining->voltage_steps_optional_range = val; in margining_alloc()
1698 margining->caps[1]); in margining_alloc()
1699 margining->max_voltage_offset_optional_range = 74 + val * 2; in margining_alloc()
1702 if (supports_time(margining)) { in margining_alloc()
1703 val = FIELD_GET(USB4_MARGIN_CAP_1_TIME_STEPS_MASK, margining->caps[1]); in margining_alloc()
1704 margining->time_steps = val; in margining_alloc()
1705 val = FIELD_GET(USB4_MARGIN_CAP_1_TIME_OFFSET_MASK, margining->caps[1]); in margining_alloc()
1710 margining->max_time_offset = 200 + 10 * val; in margining_alloc()
1714 if (supports_hardware(margining)) { in margining_alloc()
1715 val = FIELD_GET(USB4_MARGIN_CAP_1_MIN_BER_MASK, margining->caps[1]); in margining_alloc()
1716 margining->min_ber_level = val; in margining_alloc()
1717 val = FIELD_GET(USB4_MARGIN_CAP_1_MAX_BER_MASK, margining->caps[1]); in margining_alloc()
1718 margining->max_ber_level = val; in margining_alloc()
1721 margining->ber_level = margining->min_ber_level; in margining_alloc()
1723 debugfs_create_file("ber_level_contour", 0400, dir, margining, in margining_alloc()
1726 debugfs_create_file("caps", 0400, dir, margining, &margining_caps_fops); in margining_alloc()
1727 debugfs_create_file("lanes", 0600, dir, margining, &margining_lanes_fops); in margining_alloc()
1728 debugfs_create_file("mode", 0600, dir, margining, &margining_mode_fops); in margining_alloc()
1729 debugfs_create_file("run", 0600, dir, margining, &margining_run_fops); in margining_alloc()
1730 debugfs_create_file("results", 0600, dir, margining, in margining_alloc()
1732 debugfs_create_file("test", 0600, dir, margining, &margining_test_fops); in margining_alloc()
1733 if (independent_voltage_margins(margining) == USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_HL || in margining_alloc()
1734 (supports_time(margining) && in margining_alloc()
1735 independent_time_margins(margining) == USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_LR)) in margining_alloc()
1736 debugfs_create_file("margin", 0600, dir, margining, &margining_margin_fops); in margining_alloc()
1738 margining->error_counter = USB4_MARGIN_SW_ERROR_COUNTER_CLEAR; in margining_alloc()
1739 margining->dwell_time = MIN_DWELL_TIME; in margining_alloc()
1741 if (supports_optional_voltage_offset_range(margining)) in margining_alloc()
1742 debugfs_create_file("optional_voltage_offset", DEBUGFS_MODE, dir, margining, in margining_alloc()
1745 if (supports_software(margining)) { in margining_alloc()
1746 debugfs_create_file("voltage_time_offset", DEBUGFS_MODE, dir, margining, in margining_alloc()
1748 debugfs_create_file("error_counter", DEBUGFS_MODE, dir, margining, in margining_alloc()
1750 debugfs_create_file("dwell_time", DEBUGFS_MODE, dir, margining, in margining_alloc()
1754 if (margining->gen >= 4) in margining_alloc()
1757 return margining; in margining_alloc()
1770 port->usb4->margining = margining_alloc(port, &port->usb4->dev, in margining_port_init()
1788 kfree(port->usb4->margining); in margining_port_remove()
1789 port->usb4->margining = NULL; in margining_port_remove()
1849 rt->margining = margining_alloc(rt->port, &rt->dev, in margining_retimer_init()
1856 kfree(rt->margining); in margining_retimer_remove()
1857 rt->margining = NULL; in margining_retimer_remove()