On 06 December 2018 03:02, Kyle Tso wrote: > Current matching rules ensure that the voltage range of selected Source > Capability is entirely within the range defined in one of the Sink Capabilities. This > is reasonable but not practical because Sink may not support wide range of > voltage when sinking power while Source could advertise its capabilities in > raletively wider range. For example, a Source PDO advertising 3.3V-11V@3A (9V > Prog of Fixed Nominal Voltage) will not be selected if the Sink requires 5V- > 12V@3A PPS power. However, the Sink could work well if the requested voltage > range in RDOs is 5V-11V@3A. Is there a real world example of a sink requiring the 5V - 12V range? In that scenario could we not add an additional sink capability which allows for this range to be supported, and the current implementation should work just fine? > > To improve the usability, change the matching rules to what listed > below: > a. The Source PDO is selectable if any portion of the voltage range > overlaps one of the Sink PDO's voltage range. > b. The maximum operational voltage will be the lower one between the > selected Source PDO and the matching Sink PDO. > c. The maximum power will be the maximum operational voltage times the > maximum current defined in the selected Source PDO d. Select the Source PDO > with the highest maximum power > > Signed-off-by: Kyle Tso <kyletso@xxxxxxxxxx> > --- > drivers/usb/typec/tcpm/tcpm.c | 29 +++++++++++++++++------------ > 1 file changed, 17 insertions(+), 12 deletions(-) > > diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c > index 3620efee2688..3001df7bd602 100644 > --- a/drivers/usb/typec/tcpm/tcpm.c > +++ b/drivers/usb/typec/tcpm/tcpm.c > @@ -2213,7 +2213,8 @@ static unsigned int tcpm_pd_select_pps_apdo(struct > tcpm_port *port) > unsigned int i, j, max_mw = 0, max_mv = 0; > unsigned int min_src_mv, max_src_mv, src_ma, src_mw; > unsigned int min_snk_mv, max_snk_mv; > - u32 pdo; > + unsigned int max_op_mv; > + u32 pdo, src, snk; > unsigned int src_pdo = 0, snk_pdo = 0; > > /* > @@ -2263,16 +2264,18 @@ static unsigned int tcpm_pd_select_pps_apdo(struct > tcpm_port *port) > continue; > } > > - if (max_src_mv <= max_snk_mv && > - min_src_mv >= min_snk_mv) { > + if (min_src_mv <= max_snk_mv && > + max_src_mv >= min_snk_mv) { > + max_op_mv = min(max_src_mv, > max_snk_mv); > + src_mw = (max_op_mv * src_ma) / 1000; > /* Prefer higher voltages if available */ > if ((src_mw == max_mw && > - min_src_mv > max_mv) || > + max_op_mv > max_mv) || > src_mw > max_mw) { > src_pdo = i; > snk_pdo = j; > max_mw = src_mw; > - max_mv = max_src_mv; > + max_mv = max_op_mv; > } > } > } > @@ -2285,14 +2288,16 @@ static unsigned int tcpm_pd_select_pps_apdo(struct > tcpm_port *port) > } > > if (src_pdo) { > - pdo = port->source_caps[src_pdo]; > - > - port->pps_data.min_volt = pdo_pps_apdo_min_voltage(pdo); > - port->pps_data.max_volt = pdo_pps_apdo_max_voltage(pdo); > - port->pps_data.max_curr = > - min_pps_apdo_current(pdo, port->snk_pdo[snk_pdo]); > + src = port->source_caps[src_pdo]; > + snk = port->snk_pdo[snk_pdo]; > + > + port->pps_data.min_volt = > max(pdo_pps_apdo_min_voltage(src), > + pdo_pps_apdo_min_voltage(snk)); > + port->pps_data.max_volt = > min(pdo_pps_apdo_max_voltage(src), > + pdo_pps_apdo_max_voltage(snk)); > + port->pps_data.max_curr = min_pps_apdo_current(src, snk); > port->pps_data.out_volt = > - min(pdo_pps_apdo_max_voltage(pdo), port- > >pps_data.out_volt); > + min(port->pps_data.max_volt, port- > >pps_data.out_volt); > port->pps_data.op_curr = > min(port->pps_data.max_curr, port->pps_data.op_curr); > } > -- > 2.20.0.rc2.403.gdbc3b29805-goog