Lines Matching refs:margining

518 static int margining_modify_error_counter(struct tb_margining *margining,  in margining_modify_error_counter()  argument
522 struct tb_port *port = margining->port; in margining_modify_error_counter()
532 return usb4_port_sw_margin(port, margining->target, margining->index, in margining_modify_error_counter()
536 static bool supports_software(const struct tb_margining *margining) in supports_software() argument
538 if (margining->gen < 4) in supports_software()
539 return margining->caps[0] & USB4_MARGIN_CAP_0_MODES_SW; in supports_software()
540 return margining->caps[2] & USB4_MARGIN_CAP_2_MODES_SW; in supports_software()
543 static bool supports_hardware(const struct tb_margining *margining) in supports_hardware() argument
545 if (margining->gen < 4) in supports_hardware()
546 return margining->caps[0] & USB4_MARGIN_CAP_0_MODES_HW; in supports_hardware()
547 return margining->caps[2] & USB4_MARGIN_CAP_2_MODES_HW; in supports_hardware()
550 static bool all_lanes(const struct tb_margining *margining) in all_lanes() argument
552 return margining->caps[0] & USB4_MARGIN_CAP_0_ALL_LANES; in all_lanes()
556 independent_voltage_margins(const struct tb_margining *margining) in independent_voltage_margins() argument
558 if (margining->gen < 4) { in independent_voltage_margins()
559 switch (FIELD_GET(USB4_MARGIN_CAP_0_VOLTAGE_INDP_MASK, margining->caps[0])) { in independent_voltage_margins()
568 switch (FIELD_GET(USB4_MARGIN_CAP_2_VOLTAGE_INDP_MASK, margining->caps[2])) { in independent_voltage_margins()
578 static bool supports_time(const struct tb_margining *margining) in supports_time() argument
580 if (margining->gen < 4) in supports_time()
581 return margining->caps[0] & USB4_MARGIN_CAP_0_TIME; in supports_time()
582 return margining->caps[2] & USB4_MARGIN_CAP_2_TIME; in supports_time()
587 independent_time_margins(const struct tb_margining *margining) in independent_time_margins() argument
589 if (margining->gen < 4) { in independent_time_margins()
590 switch (FIELD_GET(USB4_MARGIN_CAP_1_TIME_INDP_MASK, margining->caps[1])) { in independent_time_margins()
599 switch (FIELD_GET(USB4_MARGIN_CAP_2_TIME_INDP_MASK, margining->caps[2])) { in independent_time_margins()
610 supports_optional_voltage_offset_range(const struct tb_margining *margining) in supports_optional_voltage_offset_range() argument
612 return margining->caps[0] & USB4_MARGIN_CAP_0_OPT_VOLTAGE_SUPPORT; in supports_optional_voltage_offset_range()
620 struct tb_margining *margining = s->private; in margining_ber_level_write() local
621 struct tb *tb = margining->port->sw->tb; in margining_ber_level_write()
629 if (margining->software) { in margining_ber_level_write()
646 if (val < margining->min_ber_level || in margining_ber_level_write()
647 val > margining->max_ber_level) { in margining_ber_level_write()
652 margining->ber_level = val; in margining_ber_level_write()
672 const struct tb_margining *margining = s->private; in margining_ber_level_show() local
674 if (margining->software) in margining_ber_level_show()
676 ber_level_show(s, margining->ber_level); in margining_ber_level_show()
683 struct tb_margining *margining = s->private; in margining_caps_show() local
684 struct tb *tb = margining->port->sw->tb; in margining_caps_show()
691 for (int i = 0; i < ARRAY_SIZE(margining->caps); i++) in margining_caps_show()
692 seq_printf(s, "0x%08x\n", margining->caps[i]); in margining_caps_show()
695 str_yes_no(supports_software(margining))); in margining_caps_show()
696 if (supports_hardware(margining)) { in margining_caps_show()
699 ber_level_show(s, margining->min_ber_level); in margining_caps_show()
701 ber_level_show(s, margining->max_ber_level); in margining_caps_show()
707 str_yes_no(all_lanes(margining))); in margining_caps_show()
709 margining->voltage_steps); in margining_caps_show()
711 margining->max_voltage_offset); in margining_caps_show()
713 str_yes_no(supports_optional_voltage_offset_range(margining))); in margining_caps_show()
714 if (supports_optional_voltage_offset_range(margining)) { in margining_caps_show()
716 margining->voltage_steps_optional_range); in margining_caps_show()
718 margining->max_voltage_offset_optional_range); in margining_caps_show()
721 switch (independent_voltage_margins(margining)) { in margining_caps_show()
738 tb_port_warn(margining->port, in margining_caps_show()
744 if (supports_time(margining)) { in margining_caps_show()
747 str_yes_no(margining->caps[1] & USB4_MARGIN_CAP_1_TIME_DESTR)); in margining_caps_show()
749 switch (independent_time_margins(margining)) { in margining_caps_show()
766 tb_port_warn(margining->port, in margining_caps_show()
773 margining->time_steps); in margining_caps_show()
775 margining->max_time_offset); in margining_caps_show()
813 struct tb_margining *margining = s->private; in margining_lanes_write() local
814 struct tb_port *port = margining->port; in margining_lanes_write()
838 if (lane == USB4_MARGINING_LANE_ALL && !all_lanes(margining)) in margining_lanes_write()
844 if (lane == USB4_MARGINING_LANE_RX2 && !margining->asym_rx) in margining_lanes_write()
847 margining->lanes = lane; in margining_lanes_write()
855 struct tb_margining *margining = s->private; in margining_lanes_show() local
856 struct tb_port *port = margining->port; in margining_lanes_show()
862 !all_lanes(margining)) in margining_lanes_show()
865 !margining->asym_rx) in margining_lanes_show()
871 if (lane_names[i].lane == margining->lanes) in margining_lanes_show()
889 struct tb_margining *margining = s->private; in margining_voltage_time_offset_write() local
890 struct tb *tb = margining->port->sw->tb; in margining_voltage_time_offset_write()
900 if (!margining->software) in margining_voltage_time_offset_write()
903 if (margining->time) in margining_voltage_time_offset_write()
904 max_margin = margining->time_steps; in margining_voltage_time_offset_write()
906 if (margining->optional_voltage_offset_range) in margining_voltage_time_offset_write()
907 max_margin = margining->voltage_steps_optional_range; in margining_voltage_time_offset_write()
909 max_margin = margining->voltage_steps; in margining_voltage_time_offset_write()
911 margining->voltage_time_offset = clamp(val, 0, max_margin); in margining_voltage_time_offset_write()
920 const struct tb_margining *margining = s->private; in margining_voltage_time_offset_show() local
921 struct tb *tb = margining->port->sw->tb; in margining_voltage_time_offset_show()
924 if (!margining->software) in margining_voltage_time_offset_show()
927 seq_printf(s, "%d\n", margining->voltage_time_offset); in margining_voltage_time_offset_show()
940 struct tb_margining *margining = s->private; in margining_error_counter_write() local
941 struct tb *tb = margining->port->sw->tb; in margining_error_counter_write()
962 if (!margining->software) in margining_error_counter_write()
965 margining->error_counter = error_counter; in margining_error_counter_write()
973 const struct tb_margining *margining = s->private; in margining_error_counter_show() local
974 struct tb *tb = margining->port->sw->tb; in margining_error_counter_show()
977 if (!margining->software) in margining_error_counter_show()
980 switch (margining->error_counter) { in margining_error_counter_show()
1005 struct tb_margining *margining = s->private; in margining_dwell_time_write() local
1006 struct tb *tb = margining->port->sw->tb; in margining_dwell_time_write()
1015 if (!margining->software) in margining_dwell_time_write()
1018 margining->dwell_time = clamp(val, MIN_DWELL_TIME, MAX_DWELL_TIME); in margining_dwell_time_write()
1026 struct tb_margining *margining = s->private; in margining_dwell_time_show() local
1027 struct tb *tb = margining->port->sw->tb; in margining_dwell_time_show()
1030 if (!margining->software) in margining_dwell_time_show()
1033 seq_printf(s, "%d\n", margining->dwell_time); in margining_dwell_time_show()
1045 struct tb_margining *margining = s->private; in margining_optional_voltage_offset_write() local
1046 struct tb *tb = margining->port->sw->tb; in margining_optional_voltage_offset_write()
1055 margining->optional_voltage_offset_range = val; in margining_optional_voltage_offset_write()
1064 struct tb_margining *margining = s->private; in margining_optional_voltage_offset_show() local
1065 struct tb *tb = margining->port->sw->tb; in margining_optional_voltage_offset_show()
1068 seq_printf(s, "%u\n", margining->optional_voltage_offset_range); in margining_optional_voltage_offset_show()
1080 struct tb_margining *margining = s->private; in margining_mode_write() local
1081 struct tb *tb = margining->port->sw->tb; in margining_mode_write()
1097 if (supports_software(margining)) in margining_mode_write()
1098 margining->software = true; in margining_mode_write()
1102 if (supports_hardware(margining)) in margining_mode_write()
1103 margining->software = false; in margining_mode_write()
1119 struct tb_margining *margining = s->private; in margining_mode_show() local
1120 struct tb *tb = margining->port->sw->tb; in margining_mode_show()
1126 if (supports_software(margining)) { in margining_mode_show()
1127 if (margining->software) in margining_mode_show()
1133 if (supports_hardware(margining)) { in margining_mode_show()
1134 if (margining->software) in margining_mode_show()
1147 static int margining_run_sw(struct tb_margining *margining, in margining_run_sw() argument
1150 u32 nsamples = margining->dwell_time / DWELL_SAMPLE_INTERVAL; in margining_run_sw()
1153 ret = usb4_port_sw_margin(margining->port, margining->target, margining->index, in margining_run_sw()
1154 params, margining->results); in margining_run_sw()
1161 ret = usb4_port_sw_margin_errors(margining->port, margining->target, in margining_run_sw()
1162 margining->index, &margining->results[1]); in margining_run_sw()
1166 if (margining->lanes == USB4_MARGINING_LANE_RX0) in margining_run_sw()
1168 margining->results[1]); in margining_run_sw()
1169 else if (margining->lanes == USB4_MARGINING_LANE_RX1) in margining_run_sw()
1171 margining->results[1]); in margining_run_sw()
1172 else if (margining->lanes == USB4_MARGINING_LANE_RX2) in margining_run_sw()
1174 margining->results[1]); in margining_run_sw()
1175 else if (margining->lanes == USB4_MARGINING_LANE_ALL) in margining_run_sw()
1176 errors = margining->results[1]; in margining_run_sw()
1190 margining_modify_error_counter(margining, margining->lanes, in margining_run_sw()
1195 static int validate_margining(struct tb_margining *margining) in validate_margining() argument
1203 if (margining->lanes == USB4_MARGINING_LANE_RX2) { in validate_margining()
1206 ret = tb_port_get_link_width(margining->port); in validate_margining()
1210 tb_port_warn(margining->port, "link is %s expected %s", in validate_margining()
1222 struct tb_margining *margining = data; in margining_run_write() local
1223 struct tb_port *port = margining->port; in margining_run_write()
1224 struct device *dev = margining->dev; in margining_run_write()
1240 ret = validate_margining(margining); in margining_run_write()
1265 memset(margining->results, 0, sizeof(margining->results)); in margining_run_write()
1267 if (margining->software) { in margining_run_write()
1270 .lanes = margining->lanes, in margining_run_write()
1271 .time = margining->time, in margining_run_write()
1272 .voltage_time_offset = margining->voltage_time_offset, in margining_run_write()
1273 .right_high = margining->right_high, in margining_run_write()
1274 .upper_eye = margining->upper_eye, in margining_run_write()
1275 .optional_voltage_offset_range = margining->optional_voltage_offset_range, in margining_run_write()
1280 margining->time ? "time" : "voltage", dev_name(dev), in margining_run_write()
1281 margining->lanes); in margining_run_write()
1283 ret = margining_run_sw(margining, &params); in margining_run_write()
1286 .ber_level = margining->ber_level, in margining_run_write()
1287 .lanes = margining->lanes, in margining_run_write()
1288 .time = margining->time, in margining_run_write()
1289 .right_high = margining->right_high, in margining_run_write()
1290 .upper_eye = margining->upper_eye, in margining_run_write()
1291 .optional_voltage_offset_range = margining->optional_voltage_offset_range, in margining_run_write()
1296 margining->time ? "time" : "voltage", dev_name(dev), in margining_run_write()
1297 margining->lanes); in margining_run_write()
1299 ret = usb4_port_hw_margin(port, margining->target, margining->index, &params, in margining_run_write()
1300 margining->results, ARRAY_SIZE(margining->results)); in margining_run_write()
1321 struct tb_margining *margining = s->private; in margining_results_write() local
1322 struct tb *tb = margining->port->sw->tb; in margining_results_write()
1328 memset(margining->results, 0, sizeof(margining->results)); in margining_results_write()
1330 if (margining->software) { in margining_results_write()
1332 margining_modify_error_counter(margining, in margining_results_write()
1342 const struct tb_margining *margining, u8 val) in voltage_margin_show() argument
1347 voltage = tmp * margining->max_voltage_offset / margining->voltage_steps; in voltage_margin_show()
1352 if (margining->optional_voltage_offset_range) in voltage_margin_show()
1357 const struct tb_margining *margining, u8 val) in time_margin_show() argument
1362 interval = tmp * margining->max_time_offset / margining->time_steps; in time_margin_show()
1388 const struct tb_margining *margining, in margining_hw_result_format() argument
1393 if (margining->time) { in margining_hw_result_format()
1394 val = margining_hw_result_val(margining->results, lane, true); in margining_hw_result_format()
1396 time_margin_show(s, margining, val); in margining_hw_result_format()
1397 val = margining_hw_result_val(margining->results, lane, false); in margining_hw_result_format()
1399 time_margin_show(s, margining, val); in margining_hw_result_format()
1401 val = margining_hw_result_val(margining->results, lane, true); in margining_hw_result_format()
1403 voltage_margin_show(s, margining, val); in margining_hw_result_format()
1404 val = margining_hw_result_val(margining->results, lane, false); in margining_hw_result_format()
1406 voltage_margin_show(s, margining, val); in margining_hw_result_format()
1412 struct tb_margining *margining = s->private; in margining_results_show() local
1413 struct tb *tb = margining->port->sw->tb; in margining_results_show()
1419 seq_printf(s, "0x%08x\n", margining->results[0]); in margining_results_show()
1421 if (!margining->software) { in margining_results_show()
1422 for (int i = 1; i < ARRAY_SIZE(margining->results); i++) in margining_results_show()
1423 seq_printf(s, "0x%08x\n", margining->results[i]); in margining_results_show()
1425 if (margining->lanes == USB4_MARGINING_LANE_ALL) { in margining_results_show()
1426 margining_hw_result_format(s, margining, in margining_results_show()
1428 margining_hw_result_format(s, margining, in margining_results_show()
1430 if (margining->asym_rx) in margining_results_show()
1431 margining_hw_result_format(s, margining, in margining_results_show()
1434 margining_hw_result_format(s, margining, in margining_results_show()
1435 margining->lanes); in margining_results_show()
1440 seq_printf(s, "0x%08x\n", margining->results[1]); in margining_results_show()
1442 result = FIELD_GET(USB4_MARGIN_SW_LANES_MASK, margining->results[0]); in margining_results_show()
1446 margining->results[1]); in margining_results_show()
1452 margining->results[1]); in margining_results_show()
1455 if (margining->asym_rx && in margining_results_show()
1459 margining->results[1]); in margining_results_show()
1474 struct tb_margining *margining = s->private; in margining_test_write() local
1475 struct tb *tb = margining->port->sw->tb; in margining_test_write()
1490 if (!strcmp(buf, "time") && supports_time(margining)) in margining_test_write()
1491 margining->time = true; in margining_test_write()
1493 margining->time = false; in margining_test_write()
1506 struct tb_margining *margining = s->private; in margining_test_show() local
1507 struct tb *tb = margining->port->sw->tb; in margining_test_show()
1512 if (supports_time(margining)) { in margining_test_show()
1513 if (margining->time) in margining_test_show()
1531 struct tb_margining *margining = s->private; in margining_margin_write() local
1532 struct tb *tb = margining->port->sw->tb; in margining_margin_write()
1547 if (margining->time) { in margining_margin_write()
1549 margining->right_high = false; in margining_margin_write()
1551 margining->right_high = true; in margining_margin_write()
1556 margining->right_high = false; in margining_margin_write()
1558 margining->right_high = true; in margining_margin_write()
1572 struct tb_margining *margining = s->private; in margining_margin_show() local
1573 struct tb *tb = margining->port->sw->tb; in margining_margin_show()
1578 if (margining->time) { in margining_margin_show()
1579 if (margining->right_high) in margining_margin_show()
1584 if (margining->right_high) in margining_margin_show()
1614 usb4->margining->upper_eye = false; in margining_eye_write()
1616 usb4->margining->upper_eye = true; in margining_eye_write()
1632 if (usb4->margining->upper_eye) in margining_eye_show()
1649 struct tb_margining *margining; in margining_alloc() local
1660 margining = kzalloc_obj(*margining); in margining_alloc()
1661 if (!margining) in margining_alloc()
1664 margining->port = port; in margining_alloc()
1665 margining->target = target; in margining_alloc()
1666 margining->index = index; in margining_alloc()
1667 margining->dev = dev; in margining_alloc()
1668 margining->gen = ret; in margining_alloc()
1669 margining->asym_rx = tb_port_width_supported(port, TB_LINK_WIDTH_ASYM_RX); in margining_alloc()
1671 ret = usb4_port_margining_caps(port, target, index, margining->caps, in margining_alloc()
1672 ARRAY_SIZE(margining->caps)); in margining_alloc()
1674 kfree(margining); in margining_alloc()
1679 if (supports_software(margining)) in margining_alloc()
1680 margining->software = true; in margining_alloc()
1682 if (margining->gen < 4) { in margining_alloc()
1683 val = FIELD_GET(USB4_MARGIN_CAP_0_VOLTAGE_STEPS_MASK, margining->caps[0]); in margining_alloc()
1684 margining->voltage_steps = val; in margining_alloc()
1685 val = FIELD_GET(USB4_MARGIN_CAP_0_MAX_VOLTAGE_OFFSET_MASK, margining->caps[0]); in margining_alloc()
1686 margining->max_voltage_offset = 74 + val * 2; in margining_alloc()
1688 val = FIELD_GET(USB4_MARGIN_CAP_2_VOLTAGE_STEPS_MASK, margining->caps[2]); in margining_alloc()
1689 margining->voltage_steps = val; in margining_alloc()
1690 val = FIELD_GET(USB4_MARGIN_CAP_2_MAX_VOLTAGE_OFFSET_MASK, margining->caps[2]); in margining_alloc()
1691 margining->max_voltage_offset = 74 + val * 2; in margining_alloc()
1694 if (supports_optional_voltage_offset_range(margining)) { in margining_alloc()
1696 margining->caps[0]); in margining_alloc()
1697 margining->voltage_steps_optional_range = val; in margining_alloc()
1699 margining->caps[1]); in margining_alloc()
1700 margining->max_voltage_offset_optional_range = 74 + val * 2; in margining_alloc()
1703 if (supports_time(margining)) { in margining_alloc()
1704 val = FIELD_GET(USB4_MARGIN_CAP_1_TIME_STEPS_MASK, margining->caps[1]); in margining_alloc()
1705 margining->time_steps = val; in margining_alloc()
1706 val = FIELD_GET(USB4_MARGIN_CAP_1_TIME_OFFSET_MASK, margining->caps[1]); in margining_alloc()
1711 margining->max_time_offset = 200 + 10 * val; in margining_alloc()
1715 if (supports_hardware(margining)) { in margining_alloc()
1716 val = FIELD_GET(USB4_MARGIN_CAP_1_MIN_BER_MASK, margining->caps[1]); in margining_alloc()
1717 margining->min_ber_level = val; in margining_alloc()
1718 val = FIELD_GET(USB4_MARGIN_CAP_1_MAX_BER_MASK, margining->caps[1]); in margining_alloc()
1719 margining->max_ber_level = val; in margining_alloc()
1722 margining->ber_level = margining->min_ber_level; in margining_alloc()
1724 debugfs_create_file("ber_level_contour", 0400, dir, margining, in margining_alloc()
1727 debugfs_create_file("caps", 0400, dir, margining, &margining_caps_fops); in margining_alloc()
1728 debugfs_create_file("lanes", 0600, dir, margining, &margining_lanes_fops); in margining_alloc()
1729 debugfs_create_file("mode", 0600, dir, margining, &margining_mode_fops); in margining_alloc()
1730 debugfs_create_file("run", 0600, dir, margining, &margining_run_fops); in margining_alloc()
1731 debugfs_create_file("results", 0600, dir, margining, in margining_alloc()
1733 debugfs_create_file("test", 0600, dir, margining, &margining_test_fops); in margining_alloc()
1734 if (independent_voltage_margins(margining) == USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_HL || in margining_alloc()
1735 (supports_time(margining) && in margining_alloc()
1736 independent_time_margins(margining) == USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_LR)) in margining_alloc()
1737 debugfs_create_file("margin", 0600, dir, margining, &margining_margin_fops); in margining_alloc()
1739 margining->error_counter = USB4_MARGIN_SW_ERROR_COUNTER_CLEAR; in margining_alloc()
1740 margining->dwell_time = MIN_DWELL_TIME; in margining_alloc()
1742 if (supports_optional_voltage_offset_range(margining)) in margining_alloc()
1743 debugfs_create_file("optional_voltage_offset", DEBUGFS_MODE, dir, margining, in margining_alloc()
1746 if (supports_software(margining)) { in margining_alloc()
1747 debugfs_create_file("voltage_time_offset", DEBUGFS_MODE, dir, margining, in margining_alloc()
1749 debugfs_create_file("error_counter", DEBUGFS_MODE, dir, margining, in margining_alloc()
1751 debugfs_create_file("dwell_time", DEBUGFS_MODE, dir, margining, in margining_alloc()
1755 if (margining->gen >= 4) in margining_alloc()
1758 return margining; in margining_alloc()
1771 port->usb4->margining = margining_alloc(port, &port->usb4->dev, in margining_port_init()
1789 kfree(port->usb4->margining); in margining_port_remove()
1790 port->usb4->margining = NULL; in margining_port_remove()
1850 rt->margining = margining_alloc(rt->port, &rt->dev, in margining_retimer_init()
1857 kfree(rt->margining); in margining_retimer_remove()
1858 rt->margining = NULL; in margining_retimer_remove()