Commit 81f848d2 authored by Rene Sapiens's avatar Rene Sapiens Committed by Mika Westerberg

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: default avatarRene Sapiens <rene.sapiens@intel.com>
Co-developed-by: default avatarAapo Vienamo <aapo.vienamo@linux.intel.com>
Signed-off-by: default avatarAapo Vienamo <aapo.vienamo@linux.intel.com>
Signed-off-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
parent 24edc397
...@@ -780,13 +780,20 @@ static int margining_run_write(void *data, u64 val) ...@@ -780,13 +780,20 @@ static int margining_run_write(void *data, u64 val)
} }
if (margining->software) { 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, tb_port_dbg(port,
"running software %s lane margining for %s lanes %u\n", "running software %s lane margining for %s lanes %u\n",
margining->time ? "time" : "voltage", dev_name(dev), margining->time ? "time" : "voltage", dev_name(dev),
margining->lanes); margining->lanes);
ret = usb4_port_sw_margin(port, margining->target, margining->index,
margining->lanes, margining->time, margining->right_high, ret = usb4_port_sw_margin(port, margining->target, margining->index, &params,
USB4_MARGIN_SW_COUNTER_CLEAR, &margining->results[0]); &margining->results[0]);
if (ret) if (ret)
goto out_clx; goto out_clx;
...@@ -794,16 +801,23 @@ static int margining_run_write(void *data, u64 val) ...@@ -794,16 +801,23 @@ static int margining_run_write(void *data, u64 val)
margining->index, margining->index,
&margining->results[0]); &margining->results[0]);
} else { } 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, tb_port_dbg(port,
"running hardware %s lane margining for %s lanes %u\n", "running hardware %s lane margining for %s lanes %u\n",
margining->time ? "time" : "voltage", dev_name(dev), margining->time ? "time" : "voltage", dev_name(dev),
margining->lanes); margining->lanes);
/* Clear the results */
margining->results[0] = 0; ret = usb4_port_hw_margin(port, margining->target, margining->index, &params,
margining->results[1] = 0;
ret = usb4_port_hw_margin(port, margining->target, margining->index,
margining->lanes, margining->ber_level,
margining->time, margining->right_high,
margining->results); margining->results);
} }
......
...@@ -85,10 +85,5 @@ enum usb4_sb_opcode { ...@@ -85,10 +85,5 @@ enum usb4_sb_opcode {
#define USB4_MARGIN_SW_TIME BIT(3) #define USB4_MARGIN_SW_TIME BIT(3)
#define USB4_MARGIN_SW_RH BIT(4) #define USB4_MARGIN_SW_RH BIT(4)
#define USB4_MARGIN_SW_COUNTER_MASK GENMASK(14, 13) #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 #endif
...@@ -1353,14 +1353,44 @@ int usb4_port_sb_read(struct tb_port *port, enum usb4_sb_target target, u8 index ...@@ -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, int usb4_port_sb_write(struct tb_port *port, enum usb4_sb_target target,
u8 index, u8 reg, const void *buf, u8 size); 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, int usb4_port_margining_caps(struct tb_port *port, enum usb4_sb_target target,
u8 index, u32 *caps); u8 index, u32 *caps);
int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target, int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
u8 index, unsigned int lanes, unsigned int ber_level, u8 index, const struct usb4_port_margining_params *params,
bool timing, bool right_high, u32 *results); u32 *results);
int usb4_port_sw_margin(struct tb_port *port, enum usb4_sb_target target, int usb4_port_sw_margin(struct tb_port *port, enum usb4_sb_target target,
u8 index, unsigned int lanes, bool timing, u8 index, const struct usb4_port_margining_params *params,
bool right_high, u32 counter, u32 *results); u32 *results);
int usb4_port_sw_margin_errors(struct tb_port *port, enum usb4_sb_target target, int usb4_port_sw_margin_errors(struct tb_port *port, enum usb4_sb_target target,
u8 index, u32 *errors); u8 index, u32 *errors);
......
...@@ -1653,31 +1653,29 @@ int usb4_port_margining_caps(struct tb_port *port, enum usb4_sb_target target, ...@@ -1653,31 +1653,29 @@ int usb4_port_margining_caps(struct tb_port *port, enum usb4_sb_target target,
* @port: USB4 port * @port: USB4 port
* @target: Sideband target * @target: Sideband target
* @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER * @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER
* @lanes: Which lanes to run (must match the port capabilities). Can be * @params: Parameters for USB4 hardware margining
* %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
* @results: Array with at least two elements to hold the results * @results: Array with at least two elements to hold the results
* *
* Runs hardware lane margining on USB4 port and returns the result in * Runs hardware lane margining on USB4 port and returns the result in
* @results. * @results.
*/ */
int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target, int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
u8 index, unsigned int lanes, unsigned int ber_level, u8 index, const struct usb4_port_margining_params *params,
bool timing, bool right_high, u32 *results) u32 *results)
{ {
u32 val; u32 val;
int ret; int ret;
val = lanes; if (WARN_ON_ONCE(!params))
if (timing) return -EINVAL;
val = params->lanes;
if (params->time)
val |= USB4_MARGIN_HW_TIME; val |= USB4_MARGIN_HW_TIME;
if (right_high) if (params->right_high)
val |= USB4_MARGIN_HW_RH; val |= USB4_MARGIN_HW_RH;
if (ber_level) if (params->ber_level)
val |= (ber_level << USB4_MARGIN_HW_BER_SHIFT) & val |= FIELD_PREP(USB4_MARGIN_HW_BER_MASK, params->ber_level);
USB4_MARGIN_HW_BER_MASK;
ret = usb4_port_sb_write(port, target, index, USB4_SB_METADATA, &val, ret = usb4_port_sb_write(port, target, index, USB4_SB_METADATA, &val,
sizeof(val)); sizeof(val));
...@@ -1698,11 +1696,7 @@ int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target, ...@@ -1698,11 +1696,7 @@ int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
* @port: USB4 port * @port: USB4 port
* @target: Sideband target * @target: Sideband target
* @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER * @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER
* @lanes: Which lanes to run (must match the port capabilities). Can be * @params: Parameters for USB4 software margining
* %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
* @results: Data word for the operation completion data * @results: Data word for the operation completion data
* *
* Runs software lane margining on USB4 port. Read back the error * 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, ...@@ -1710,19 +1704,21 @@ int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
* success and negative errno otherwise. * success and negative errno otherwise.
*/ */
int usb4_port_sw_margin(struct tb_port *port, enum usb4_sb_target target, int usb4_port_sw_margin(struct tb_port *port, enum usb4_sb_target target,
u8 index, unsigned int lanes, bool timing, u8 index, const struct usb4_port_margining_params *params,
bool right_high, u32 counter, u32 *results) u32 *results)
{ {
u32 val; u32 val;
int ret; int ret;
val = lanes; if (WARN_ON_ONCE(!params))
if (timing) return -EINVAL;
val = params->lanes;
if (params->time)
val |= USB4_MARGIN_SW_TIME; val |= USB4_MARGIN_SW_TIME;
if (right_high) if (params->right_high)
val |= USB4_MARGIN_SW_RH; val |= USB4_MARGIN_SW_RH;
val |= (counter << USB4_MARGIN_SW_COUNTER_SHIFT) & val |= FIELD_PREP(USB4_MARGIN_SW_COUNTER_MASK, params->error_counter);
USB4_MARGIN_SW_COUNTER_MASK;
ret = usb4_port_sb_write(port, target, index, USB4_SB_METADATA, &val, ret = usb4_port_sb_write(port, target, index, USB4_SB_METADATA, &val,
sizeof(val)); sizeof(val));
......
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