Commit 761fd871 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'thunderbolt-for-v6.12-rc1' of...

Merge tag 'thunderbolt-for-v6.12-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt into usb-next

Mika writes:

thunderbolt: Changes for v6.12 merge window

This includes following USB4/Thunderbolt changes for the v6.12 merge
window:

  - Improvements for software receiver lane margining
  - Enable support for optional voltage offset range for receiver lane
    margining.

All these have been in linux-next with no reported issues.

* tag 'thunderbolt-for-v6.12-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt:
  thunderbolt: Improve software receiver lane margining
  thunderbolt: Add optional voltage offset range for receiver lane margining
  thunderbolt: Consolidate margining parameters into a structure
  thunderbolt: Add missing usb4_port_sb_read() to usb4_port_sw_margin()
parents f299cd11 10904df3
This diff is collapsed.
......@@ -57,6 +57,9 @@ enum usb4_sb_opcode {
#define USB4_MARGIN_CAP_0_TIME BIT(5)
#define USB4_MARGIN_CAP_0_VOLTAGE_STEPS_MASK GENMASK(12, 6)
#define USB4_MARGIN_CAP_0_MAX_VOLTAGE_OFFSET_MASK GENMASK(18, 13)
#define USB4_MARGIN_CAP_0_OPT_VOLTAGE_SUPPORT BIT(19)
#define USB4_MARGIN_CAP_0_VOLT_STEPS_OPT_MASK GENMASK(26, 20)
#define USB4_MARGIN_CAP_1_MAX_VOLT_OFS_OPT_MASK GENMASK(7, 0)
#define USB4_MARGIN_CAP_1_TIME_DESTR BIT(8)
#define USB4_MARGIN_CAP_1_TIME_INDP_MASK GENMASK(10, 9)
#define USB4_MARGIN_CAP_1_TIME_MIN 0x0
......@@ -72,6 +75,7 @@ enum usb4_sb_opcode {
#define USB4_MARGIN_HW_RH BIT(4)
#define USB4_MARGIN_HW_BER_MASK GENMASK(9, 5)
#define USB4_MARGIN_HW_BER_SHIFT 5
#define USB4_MARGIN_HW_OPT_VOLTAGE BIT(10)
/* Applicable to all margin values */
#define USB4_MARGIN_HW_RES_1_MARGIN_MASK GENMASK(6, 0)
......@@ -82,13 +86,17 @@ enum usb4_sb_opcode {
#define USB4_MARGIN_HW_RES_1_L1_LL_MARGIN_SHIFT 24
/* USB4_SB_OPCODE_RUN_SW_LANE_MARGINING */
#define USB4_MARGIN_SW_LANES_MASK GENMASK(2, 0)
#define USB4_MARGIN_SW_LANE_0 0x0
#define USB4_MARGIN_SW_LANE_1 0x1
#define USB4_MARGIN_SW_ALL_LANES 0x7
#define USB4_MARGIN_SW_TIME BIT(3)
#define USB4_MARGIN_SW_RH BIT(4)
#define USB4_MARGIN_SW_OPT_VOLTAGE BIT(5)
#define USB4_MARGIN_SW_VT_MASK GENMASK(12, 6)
#define USB4_MARGIN_SW_COUNTER_MASK GENMASK(14, 13)
#define USB4_MARGIN_SW_COUNTER_SHIFT 13
#define USB4_MARGIN_SW_COUNTER_NOP 0x0
#define USB4_MARGIN_SW_COUNTER_CLEAR 0x1
#define USB4_MARGIN_SW_COUNTER_START 0x2
#define USB4_MARGIN_SW_COUNTER_STOP 0x3
#define USB4_MARGIN_SW_ERR_COUNTER_LANE_0_MASK GENMASK(3, 0)
#define USB4_MARGIN_SW_ERR_COUNTER_LANE_1_MASK GENMASK(7, 4)
#endif
......@@ -1353,14 +1353,48 @@ int usb4_port_sb_read(struct tb_port *port, enum usb4_sb_target target, u8 index
int usb4_port_sb_write(struct tb_port *port, enum usb4_sb_target target,
u8 index, u8 reg, const void *buf, u8 size);
/**
* enum usb4_margin_sw_error_counter - Software margining error counter operation
* @USB4_MARGIN_SW_ERROR_COUNTER_NOP: No change in counter setup
* @USB4_MARGIN_SW_ERROR_COUNTER_CLEAR: Set the error counter to 0, enable counter
* @USB4_MARGIN_SW_ERROR_COUNTER_START: Start counter, count from last value
* @USB4_MARGIN_SW_ERROR_COUNTER_STOP: Stop counter, do not clear value
*/
enum usb4_margin_sw_error_counter {
USB4_MARGIN_SW_ERROR_COUNTER_NOP,
USB4_MARGIN_SW_ERROR_COUNTER_CLEAR,
USB4_MARGIN_SW_ERROR_COUNTER_START,
USB4_MARGIN_SW_ERROR_COUNTER_STOP,
};
/**
* struct usb4_port_margining_params - USB4 margining parameters
* @error_counter: Error counter operation for software margining
* @ber_level: Current BER level contour value
* @lanes: %0, %1 or %7 (all)
* @voltage_time_offset: Offset for voltage / time for software margining
* @optional_voltage_offset_range: Enable optional extended voltage range
* @right_high: %false if left/low margin test is performed, %true if right/high
* @time: %true if time margining is used instead of voltage
*/
struct usb4_port_margining_params {
enum usb4_margin_sw_error_counter error_counter;
u32 ber_level;
u32 lanes;
u32 voltage_time_offset;
bool optional_voltage_offset_range;
bool right_high;
bool time;
};
int usb4_port_margining_caps(struct tb_port *port, enum usb4_sb_target target,
u8 index, u32 *caps);
int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
u8 index, unsigned int lanes, unsigned int ber_level,
bool timing, bool right_high, u32 *results);
u8 index, const struct usb4_port_margining_params *params,
u32 *results);
int usb4_port_sw_margin(struct tb_port *port, enum usb4_sb_target target,
u8 index, unsigned int lanes, bool timing,
bool right_high, u32 counter);
u8 index, const struct usb4_port_margining_params *params,
u32 *results);
int usb4_port_sw_margin_errors(struct tb_port *port, enum usb4_sb_target target,
u8 index, u32 *errors);
......
......@@ -1653,31 +1653,31 @@ int usb4_port_margining_caps(struct tb_port *port, enum usb4_sb_target target,
* @port: USB4 port
* @target: Sideband target
* @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER
* @lanes: Which lanes to run (must match the port capabilities). Can be
* %0, %1 or %7.
* @ber_level: BER level contour value
* @timing: Perform timing margining instead of voltage
* @right_high: Use Right/high margin instead of left/low
* @params: Parameters for USB4 hardware margining
* @results: Array with at least two elements to hold the results
*
* Runs hardware lane margining on USB4 port and returns the result in
* @results.
*/
int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
u8 index, unsigned int lanes, unsigned int ber_level,
bool timing, bool right_high, u32 *results)
u8 index, const struct usb4_port_margining_params *params,
u32 *results)
{
u32 val;
int ret;
val = lanes;
if (timing)
if (WARN_ON_ONCE(!params))
return -EINVAL;
val = params->lanes;
if (params->time)
val |= USB4_MARGIN_HW_TIME;
if (right_high)
if (params->right_high)
val |= USB4_MARGIN_HW_RH;
if (ber_level)
val |= (ber_level << USB4_MARGIN_HW_BER_SHIFT) &
USB4_MARGIN_HW_BER_MASK;
if (params->ber_level)
val |= FIELD_PREP(USB4_MARGIN_HW_BER_MASK, params->ber_level);
if (params->optional_voltage_offset_range)
val |= USB4_MARGIN_HW_OPT_VOLTAGE;
ret = usb4_port_sb_write(port, target, index, USB4_SB_METADATA, &val,
sizeof(val));
......@@ -1698,38 +1698,46 @@ int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
* @port: USB4 port
* @target: Sideband target
* @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER
* @lanes: Which lanes to run (must match the port capabilities). Can be
* %0, %1 or %7.
* @timing: Perform timing margining instead of voltage
* @right_high: Use Right/high margin instead of left/low
* @counter: What to do with the error counter
* @params: Parameters for USB4 software margining
* @results: Data word for the operation completion data
*
* Runs software lane margining on USB4 port. Read back the error
* counters by calling usb4_port_sw_margin_errors(). Returns %0 in
* success and negative errno otherwise.
*/
int usb4_port_sw_margin(struct tb_port *port, enum usb4_sb_target target,
u8 index, unsigned int lanes, bool timing,
bool right_high, u32 counter)
u8 index, const struct usb4_port_margining_params *params,
u32 *results)
{
u32 val;
int ret;
val = lanes;
if (timing)
if (WARN_ON_ONCE(!params))
return -EINVAL;
val = params->lanes;
if (params->time)
val |= USB4_MARGIN_SW_TIME;
if (right_high)
if (params->optional_voltage_offset_range)
val |= USB4_MARGIN_SW_OPT_VOLTAGE;
if (params->right_high)
val |= USB4_MARGIN_SW_RH;
val |= (counter << USB4_MARGIN_SW_COUNTER_SHIFT) &
USB4_MARGIN_SW_COUNTER_MASK;
val |= FIELD_PREP(USB4_MARGIN_SW_COUNTER_MASK, params->error_counter);
val |= FIELD_PREP(USB4_MARGIN_SW_VT_MASK, params->voltage_time_offset);
ret = usb4_port_sb_write(port, target, index, USB4_SB_METADATA, &val,
sizeof(val));
if (ret)
return ret;
return usb4_port_sb_op(port, target, index,
USB4_SB_OPCODE_RUN_SW_LANE_MARGINING, 2500);
ret = usb4_port_sb_op(port, target, index,
USB4_SB_OPCODE_RUN_SW_LANE_MARGINING, 2500);
if (ret)
return ret;
return usb4_port_sb_read(port, target, index, USB4_SB_DATA, results,
sizeof(*results));
}
/**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment