From nobody Sat Feb 7 17:20:54 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6D7A0C001DC for ; Mon, 31 Jul 2023 16:29:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233435AbjGaQ3q (ORCPT ); Mon, 31 Jul 2023 12:29:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33044 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233416AbjGaQ3V (ORCPT ); Mon, 31 Jul 2023 12:29:21 -0400 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4D33719AE for ; Mon, 31 Jul 2023 09:28:57 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-583c49018c6so54750787b3.0 for ; Mon, 31 Jul 2023 09:28:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1690820935; x=1691425735; h=cc:to:from:subject:message-id:mime-version:date:from:to:cc:subject :date:message-id:reply-to; bh=LRo3hsVN444y0TtHMhMGsvOxbkL/I2oYGwECX+0Byew=; b=P8GE0hx+sl8QGUPGi3dWOPM26glgmmBwSyQfJ0jfzMszA6lbWEO6eqUChY8bWmonYJ d4xzq63NJmQVBJhYArUf2sRoqTk65UdxGyJF8J+EfSvo9tiA/hqM0uDfkcQcQQsOpmlC tW0SR+JIfyeBfa9ROWPCmefQraKyFl2qUcYNThvpa0kAfJ881A3cRbchHmkML4c9eafo BuDHUw+8UBE+ZzoNPwMl1bC5b/t9EbClPS21GWGXBqOZnuIekyrd/Yk62s0gp2Nhngve KUMI1JqXIAsyTH/p8gPsi3LJMUSdVq+IZ5XNkZ79eMJMYMe+EkNeBrZTNEM57b601Pvg HsLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1690820935; x=1691425735; h=cc:to:from:subject:message-id:mime-version:date:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=LRo3hsVN444y0TtHMhMGsvOxbkL/I2oYGwECX+0Byew=; b=bn6dicaKltAXwBr4flzAz0iA/Ea/Bdt2sUPfyepUJwMWBK2GHX53s3IXxeUsi7DRuV 2yR3g+ootY5zst880HPc8GinnkLrS5pFuDj/vjzOeQwR8XXa8pVNukcGGo2Yl3NXKZGb 34g+3RDUcLwUtSh3TV0UOfhzf4v5hADegYk7Hj2M2mG6N5xL6bW6qM5w6Nv5J3Kb6tXp 7zryNrENl2lJ+golV7s29HMN82EqF23ZdLh8BtmfwVcCvCepal60PeEm5c6AGzo0LDrf m1ZxydUB5XKMfPkvkCkrZy5cAFZv6zg1Jsg7LzGnU182H8z8xMjoHjpmtaryjxHuPk3e VenQ== X-Gm-Message-State: ABy/qLauDXAtIVv+f9DW8CH9xEIMD+PbNxqwC7zEPGHkSC6h+sqDwUeg Dx6mUge9IPKsIc+6edZZAAfuXh8FyazP X-Google-Smtp-Source: APBJJlHwDw8hHfctSTvG20cp1AfKZnIF/LJ8pK7D4h5+AmnTyceO45s+QGfH5TcfIihmEGJ60WxSukBwNQNo X-Received: from kyletso-p620lin01.ntc.corp.google.com ([2401:fa00:fc:202:ba23:5591:d70e:c541]) (user=kyletso job=sendgmr) by 2002:a81:ac58:0:b0:579:e07c:2798 with SMTP id z24-20020a81ac58000000b00579e07c2798mr70972ywj.2.1690820524611; Mon, 31 Jul 2023 09:22:04 -0700 (PDT) Date: Tue, 1 Aug 2023 00:21:59 +0800 Mime-Version: 1.0 X-Mailer: git-send-email 2.41.0.487.g6d72f3e995-goog Message-ID: <20230731162159.19483-1-kyletso@google.com> Subject: [PATCH] usb: typec: tcpm: Refactor the PPS APDO selection From: Kyle Tso To: linux@roeck-us.net, heikki.krogerus@linux.intel.com, gregkh@linuxfoundation.org Cc: badhri@google.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, Kyle Tso Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In current design of the PPS APDO selection, TCPM power supply only accepts the requested voltage which is inside the range of the selected PPS profile. To extend the flexibility and usability, remove the checks about the voltage range in current profile. And try to search all PPS APDOs of the Source that fit the requested voltage. Also remove some redundant checks in tcpm_pd_build_pps_request. Signed-off-by: Kyle Tso Acked-by: Heikki Krogerus Reviewed-by: Guenter Roeck --- drivers/usb/typec/tcpm/tcpm.c | 122 ++++++---------------------------- 1 file changed, 21 insertions(+), 101 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 829d75ebab42..9c496b8302b4 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -3253,23 +3253,12 @@ static int tcpm_pd_select_pdo(struct tcpm_port *por= t, int *sink_pdo, return ret; } =20 -#define min_pps_apdo_current(x, y) \ - min(pdo_pps_apdo_max_current(x), pdo_pps_apdo_max_current(y)) - static unsigned int tcpm_pd_select_pps_apdo(struct tcpm_port *port) { - unsigned int i, j, max_mw =3D 0, max_mv =3D 0; - unsigned int min_src_mv, max_src_mv, src_ma, src_mw; - unsigned int min_snk_mv, max_snk_mv; - unsigned int max_op_mv; - u32 pdo, src, snk; - unsigned int src_pdo =3D 0, snk_pdo =3D 0; + unsigned int i, src_ma, max_temp_mw =3D 0, max_op_ma, op_mw; + unsigned int src_pdo =3D 0; + u32 pdo, src; =20 - /* - * Select the source PPS APDO providing the most power while staying - * within the board's limits. We skip the first PDO as this is always - * 5V 3A. - */ for (i =3D 1; i < port->nr_source_caps; ++i) { pdo =3D port->source_caps[i]; =20 @@ -3280,54 +3269,17 @@ static unsigned int tcpm_pd_select_pps_apdo(struct = tcpm_port *port) continue; } =20 - min_src_mv =3D pdo_pps_apdo_min_voltage(pdo); - max_src_mv =3D pdo_pps_apdo_max_voltage(pdo); - src_ma =3D pdo_pps_apdo_max_current(pdo); - src_mw =3D (src_ma * max_src_mv) / 1000; - - /* - * Now search through the sink PDOs to find a matching - * PPS APDO. Again skip the first sink PDO as this will - * always be 5V 3A. - */ - for (j =3D 1; j < port->nr_snk_pdo; j++) { - pdo =3D port->snk_pdo[j]; - - switch (pdo_type(pdo)) { - case PDO_TYPE_APDO: - if (pdo_apdo_type(pdo) !=3D APDO_TYPE_PPS) { - tcpm_log(port, - "Not PPS APDO (sink), ignoring"); - continue; - } - - min_snk_mv =3D - pdo_pps_apdo_min_voltage(pdo); - max_snk_mv =3D - pdo_pps_apdo_max_voltage(pdo); - break; - default: - tcpm_log(port, - "Not APDO type (sink), ignoring"); - continue; - } + if (port->pps_data.req_out_volt > pdo_pps_apdo_max_voltage(pdo) || + port->pps_data.req_out_volt < pdo_pps_apdo_min_voltage(pdo)) + continue; =20 - if (min_src_mv <=3D max_snk_mv && - max_src_mv >=3D min_snk_mv) { - max_op_mv =3D min(max_src_mv, max_snk_mv); - src_mw =3D (max_op_mv * src_ma) / 1000; - /* Prefer higher voltages if available */ - if ((src_mw =3D=3D max_mw && - max_op_mv > max_mv) || - src_mw > max_mw) { - src_pdo =3D i; - snk_pdo =3D j; - max_mw =3D src_mw; - max_mv =3D max_op_mv; - } - } + src_ma =3D pdo_pps_apdo_max_current(pdo); + max_op_ma =3D min(src_ma, port->pps_data.req_op_curr); + op_mw =3D max_op_ma * port->pps_data.req_out_volt / 1000; + if (op_mw > max_temp_mw) { + src_pdo =3D i; + max_temp_mw =3D op_mw; } - break; default: tcpm_log(port, "Not APDO type (source), ignoring"); @@ -3337,16 +3289,10 @@ static unsigned int tcpm_pd_select_pps_apdo(struct = tcpm_port *port) =20 if (src_pdo) { src =3D port->source_caps[src_pdo]; - snk =3D port->snk_pdo[snk_pdo]; - - port->pps_data.req_min_volt =3D max(pdo_pps_apdo_min_voltage(src), - pdo_pps_apdo_min_voltage(snk)); - port->pps_data.req_max_volt =3D min(pdo_pps_apdo_max_voltage(src), - pdo_pps_apdo_max_voltage(snk)); - port->pps_data.req_max_curr =3D min_pps_apdo_current(src, snk); - port->pps_data.req_out_volt =3D min(port->pps_data.req_max_volt, - max(port->pps_data.req_min_volt, - port->pps_data.req_out_volt)); + + port->pps_data.req_min_volt =3D pdo_pps_apdo_min_voltage(src); + port->pps_data.req_max_volt =3D pdo_pps_apdo_max_voltage(src); + port->pps_data.req_max_curr =3D pdo_pps_apdo_max_current(src); port->pps_data.req_op_curr =3D min(port->pps_data.req_max_curr, port->pps_data.req_op_curr); } @@ -3464,32 +3410,16 @@ static int tcpm_pd_send_request(struct tcpm_port *p= ort) static int tcpm_pd_build_pps_request(struct tcpm_port *port, u32 *rdo) { unsigned int out_mv, op_ma, op_mw, max_mv, max_ma, flags; - enum pd_pdo_type type; unsigned int src_pdo_index; - u32 pdo; =20 src_pdo_index =3D tcpm_pd_select_pps_apdo(port); if (!src_pdo_index) return -EOPNOTSUPP; =20 - pdo =3D port->source_caps[src_pdo_index]; - type =3D pdo_type(pdo); - - switch (type) { - case PDO_TYPE_APDO: - if (pdo_apdo_type(pdo) !=3D APDO_TYPE_PPS) { - tcpm_log(port, "Invalid APDO selected!"); - return -EINVAL; - } - max_mv =3D port->pps_data.req_max_volt; - max_ma =3D port->pps_data.req_max_curr; - out_mv =3D port->pps_data.req_out_volt; - op_ma =3D port->pps_data.req_op_curr; - break; - default: - tcpm_log(port, "Invalid PDO selected!"); - return -EINVAL; - } + max_mv =3D port->pps_data.req_max_volt; + max_ma =3D port->pps_data.req_max_curr; + out_mv =3D port->pps_data.req_out_volt; + op_ma =3D port->pps_data.req_op_curr; =20 flags =3D RDO_USB_COMM | RDO_NO_SUSPEND; =20 @@ -5882,12 +5812,6 @@ static int tcpm_pps_set_out_volt(struct tcpm_port *p= ort, u16 req_out_volt) goto port_unlock; } =20 - if (req_out_volt < port->pps_data.min_volt || - req_out_volt > port->pps_data.max_volt) { - ret =3D -EINVAL; - goto port_unlock; - } - target_mw =3D (port->current_limit * req_out_volt) / 1000; if (target_mw < port->operating_snk_mw) { ret =3D -EINVAL; @@ -6440,11 +6364,7 @@ static int tcpm_psy_set_prop(struct power_supply *ps= y, ret =3D tcpm_psy_set_online(port, val); break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: - if (val->intval < port->pps_data.min_volt * 1000 || - val->intval > port->pps_data.max_volt * 1000) - ret =3D -EINVAL; - else - ret =3D tcpm_pps_set_out_volt(port, val->intval / 1000); + ret =3D tcpm_pps_set_out_volt(port, val->intval / 1000); break; case POWER_SUPPLY_PROP_CURRENT_NOW: if (val->intval > port->pps_data.max_curr * 1000) --=20 2.41.0.487.g6d72f3e995-goog