From f98fb1fc9e1bc410fcba2c5a843a67f2e4ca30a6 Mon Sep 17 00:00:00 2001 From: Rohith Kollalsi Date: Fri, 22 Jan 2021 23:41:39 +0530 Subject: [PATCH] usb: dwc3: Set current accordingly based on type of charger detection For ADSP based charger detection set the current for all charger types as it will again be handled on ADSP side. Other wise set current only for SDP charger which is usb based charger. For NON ADSP based charger detection if 'iio-channel-names' is passed in the device tree, charger detection is done through iio channel or else it is done by power_supply_get_property. Change-Id: I17e65448459318ad26b7a2c36742296afa5f0adf Signed-off-by: Rohith Kollalsi --- drivers/usb/dwc3/dwc3-msm.c | 78 ++++++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 15 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index f578fbed9d24..20d9afbe8956 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #include @@ -184,6 +184,12 @@ enum dbm_reg { DBM_DATA_FIFO_SIZE_EN, }; +enum charger_detection_type { + REMOTE_PROC, + IIO, + PSY, +}; + struct dbm_reg_data { u32 offset; unsigned int ep_mult; @@ -478,6 +484,7 @@ struct dwc3_msm { struct mutex suspend_resume_mutex; enum usb_device_speed override_usb_speed; + enum charger_detection_type apsd_source; u32 *gsi_reg; int gsi_reg_offset_cnt; @@ -4496,6 +4503,14 @@ static int dwc3_msm_probe(struct platform_device *pdev) } } + /* Check charger detection type to obtain charger type */ + if (of_get_property(mdwc->dev->of_node, "io-channel-names", NULL)) + mdwc->apsd_source = IIO; + else if (of_get_property(mdwc->dev->of_node, "usb-role-switch", NULL)) + mdwc->apsd_source = REMOTE_PROC; + else + mdwc->apsd_source = PSY; + if (of_property_read_bool(node, "extcon")) { ret = dwc3_msm_extcon_register(mdwc); if (ret) @@ -5010,21 +5025,43 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on) static int get_chg_type(struct dwc3_msm *mdwc) { - int ret, value; + int ret, value = 0; + union power_supply_propval pval = {0}; - if (!mdwc->chg_type) { - mdwc->chg_type = devm_iio_channel_get(mdwc->dev, "chg_type"); - if (IS_ERR_OR_NULL(mdwc->chg_type)) { - dev_dbg(mdwc->dev, "unable to get iio channel\n"); - mdwc->chg_type = NULL; - return -ENODEV; + switch (mdwc->apsd_source) { + case IIO: + if (!mdwc->chg_type) { + mdwc->chg_type = devm_iio_channel_get(mdwc->dev, + "chg_type"); + if (IS_ERR_OR_NULL(mdwc->chg_type)) { + dev_dbg(mdwc->dev, + "unable to get iio channel\n"); + mdwc->chg_type = NULL; + return -ENODEV; + } } - } - ret = iio_read_channel_processed(mdwc->chg_type, &value); - if (ret < 0) { - dev_err(mdwc->dev, "failed to get charger type\n"); - return ret; + ret = iio_read_channel_processed(mdwc->chg_type, &value); + if (ret < 0) { + dev_err(mdwc->dev, "failed to get charger type\n"); + return ret; + } + break; + case PSY: + if (!mdwc->usb_psy) { + mdwc->usb_psy = power_supply_get_by_name("usb"); + if (!mdwc->usb_psy) { + dev_err(mdwc->dev, "Could not get usb psy\n"); + return -ENODEV; + } + } + + power_supply_get_property(mdwc->usb_psy, + POWER_SUPPLY_PROP_USB_TYPE, &pval); + value = pval.intval; + break; + default: + return -EINVAL; } return value; @@ -5064,12 +5101,23 @@ static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned int mA) goto set_prop; } + /* Do not set current multiple times */ + if (mdwc->max_power == mA) + return 0; + /* * Set the valid current only when the device * is connected to a Standard Downstream Port. + * For ADSP based charger detection set current + * for all charger types. For psy based charger + * detection power_supply_usb_type enum is + * returned from pmic while for iio based charger + * detection power_supply_type enum is returned. */ - if (mdwc->max_power == mA || (chg_type != -ENODEV - && chg_type != POWER_SUPPLY_TYPE_USB)) + if (mdwc->apsd_source == PSY && chg_type != POWER_SUPPLY_USB_TYPE_SDP) + return 0; + + if (mdwc->apsd_source == IIO && chg_type != POWER_SUPPLY_TYPE_USB) return 0; /* Set max current limit in uA */