thunderbolt: Consolidate margining parameters into a structure
Consolidate the hardware and software margining parameters into a single structure to reduce the number of parameters passed to the margining functions. Signed-off-by: Rene Sapiens <rene.sapiens@intel.com> Co-developed-by: Aapo Vienamo <aapo.vienamo@linux.intel.com> Signed-off-by: Aapo Vienamo <aapo.vienamo@linux.intel.com> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
This commit is contained in:
committed by
Mika Westerberg
parent
24edc39704
commit
81f848d287
@@ -780,13 +780,20 @@ static int margining_run_write(void *data, u64 val)
|
||||
}
|
||||
|
||||
if (margining->software) {
|
||||
struct usb4_port_margining_params params = {
|
||||
.error_counter = USB4_MARGIN_SW_ERROR_COUNTER_CLEAR,
|
||||
.lanes = margining->lanes,
|
||||
.time = margining->time,
|
||||
.right_high = margining->right_high,
|
||||
};
|
||||
|
||||
tb_port_dbg(port,
|
||||
"running software %s lane margining for %s lanes %u\n",
|
||||
margining->time ? "time" : "voltage", dev_name(dev),
|
||||
margining->lanes);
|
||||
ret = usb4_port_sw_margin(port, margining->target, margining->index,
|
||||
margining->lanes, margining->time, margining->right_high,
|
||||
USB4_MARGIN_SW_COUNTER_CLEAR, &margining->results[0]);
|
||||
|
||||
ret = usb4_port_sw_margin(port, margining->target, margining->index, ¶ms,
|
||||
&margining->results[0]);
|
||||
if (ret)
|
||||
goto out_clx;
|
||||
|
||||
@@ -794,16 +801,23 @@ static int margining_run_write(void *data, u64 val)
|
||||
margining->index,
|
||||
&margining->results[0]);
|
||||
} else {
|
||||
struct usb4_port_margining_params params = {
|
||||
.ber_level = margining->ber_level,
|
||||
.lanes = margining->lanes,
|
||||
.time = margining->time,
|
||||
.right_high = margining->right_high,
|
||||
};
|
||||
|
||||
/* Clear the results */
|
||||
margining->results[0] = 0;
|
||||
margining->results[1] = 0;
|
||||
|
||||
tb_port_dbg(port,
|
||||
"running hardware %s lane margining for %s lanes %u\n",
|
||||
margining->time ? "time" : "voltage", dev_name(dev),
|
||||
margining->lanes);
|
||||
/* Clear the results */
|
||||
margining->results[0] = 0;
|
||||
margining->results[1] = 0;
|
||||
ret = usb4_port_hw_margin(port, margining->target, margining->index,
|
||||
margining->lanes, margining->ber_level,
|
||||
margining->time, margining->right_high,
|
||||
|
||||
ret = usb4_port_hw_margin(port, margining->target, margining->index, ¶ms,
|
||||
margining->results);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,10 +85,5 @@ enum usb4_sb_opcode {
|
||||
#define USB4_MARGIN_SW_TIME BIT(3)
|
||||
#define USB4_MARGIN_SW_RH BIT(4)
|
||||
#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
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1353,14 +1353,44 @@ 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)
|
||||
* @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;
|
||||
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, u32 *results);
|
||||
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);
|
||||
|
||||
|
||||
+21
-25
@@ -1653,31 +1653,29 @@ 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);
|
||||
|
||||
ret = usb4_port_sb_write(port, target, index, USB4_SB_METADATA, &val,
|
||||
sizeof(val));
|
||||
@@ -1698,11 +1696,7 @@ 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
|
||||
@@ -1710,19 +1704,21 @@ int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
|
||||
* 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, 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_SW_TIME;
|
||||
if (right_high)
|
||||
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);
|
||||
|
||||
ret = usb4_port_sb_write(port, target, index, USB4_SB_METADATA, &val,
|
||||
sizeof(val));
|
||||
|
||||
Reference in New Issue
Block a user