Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: chipidea: imx: turn off vbus comparator when suspend

As we use bvalid for vbus wakeup source, to save power when
suspend, turn off the vbus comparator for imx7d and imx8mm.

Below is this bit description from RM of iMX8MM
"VBUS Valid Comparator Enable:

This signal controls the USB OTG PHY VBUS Valid comparator which
indicates whether the voltage on the USB_OTG*_VBUS pin is below
the VBUS Valid threshold. The VBUS Valid threshold is nominally
4.75V on this USB PHY. The VBUS Valid threshold can be adjusted
using the USBNC_OTGn_PHY_CFG1[OTGTUNE0] bit field. Status of the
VBUS Valid comparator, when it is enabled, is reported on the
USBNC_OTGn_PHY_STATUS[VBUS_VLD] bit.
When OTGDISABLE0 (USBNC_USB_OTGx_PHY_CFG2[10])is set to 1'b0 and
DRVVBUS0 is set to 1'b1, the Bandgap circuitry and VBUS Valid
comparator are powered, even in Suspend or Sleep mode.
DRVVBUS0 should be reset to 1'b0 when the internal VBUS Valid comparator
is not required, to reduce quiescent current in Suspend or Sleep mode.
- 0 The VBUS Valid comparator is disabled
- 1 The VBUS Valid comparator is enabled"

Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
Acked-by: Peter Chen <peter.chen@kernel.org>
Message-ID: <20230517081907.3410465-2-xu.yang_2@nxp.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Xu Yang and committed by
Greg Kroah-Hartman
0ac37fbd 41e2f976

+35
+35
drivers/usb/chipidea/usbmisc_imx.c
··· 151 151 int (*charger_detection)(struct imx_usbmisc_data *data); 152 152 /* It's called when system resume from usb power lost */ 153 153 int (*power_lost_check)(struct imx_usbmisc_data *data); 154 + void (*vbus_comparator_on)(struct imx_usbmisc_data *data, bool on); 154 155 }; 155 156 156 157 struct imx_usbmisc { ··· 875 874 return ret; 876 875 } 877 876 877 + static void usbmisc_imx7d_vbus_comparator_on(struct imx_usbmisc_data *data, 878 + bool on) 879 + { 880 + unsigned long flags; 881 + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 882 + u32 val; 883 + 884 + if (data->hsic) 885 + return; 886 + 887 + spin_lock_irqsave(&usbmisc->lock, flags); 888 + /* 889 + * Disable VBUS valid comparator when in suspend mode, 890 + * when OTG is disabled and DRVVBUS0 is asserted case 891 + * the Bandgap circuitry and VBUS Valid comparator are 892 + * still powered, even in Suspend or Sleep mode. 893 + */ 894 + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 895 + if (on) 896 + val |= MX7D_USB_OTG_PHY_CFG2_DRVVBUS0; 897 + else 898 + val &= ~MX7D_USB_OTG_PHY_CFG2_DRVVBUS0; 899 + 900 + writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 901 + spin_unlock_irqrestore(&usbmisc->lock, flags); 902 + } 903 + 878 904 static int usbmisc_imx7ulp_init(struct imx_usbmisc_data *data) 879 905 { 880 906 struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); ··· 1045 1017 .set_wakeup = usbmisc_imx7d_set_wakeup, 1046 1018 .charger_detection = imx7d_charger_detection, 1047 1019 .power_lost_check = usbmisc_imx7d_power_lost_check, 1020 + .vbus_comparator_on = usbmisc_imx7d_vbus_comparator_on, 1048 1021 }; 1049 1022 1050 1023 static const struct usbmisc_ops imx7ulp_usbmisc_ops = { ··· 1160 1131 1161 1132 usbmisc = dev_get_drvdata(data->dev); 1162 1133 1134 + if (usbmisc->ops->vbus_comparator_on) 1135 + usbmisc->ops->vbus_comparator_on(data, false); 1136 + 1163 1137 if (wakeup && usbmisc->ops->set_wakeup) 1164 1138 ret = usbmisc->ops->set_wakeup(data, true); 1165 1139 if (ret) { ··· 1215 1183 dev_err(data->dev, "set_wakeup failed, ret=%d\n", ret); 1216 1184 goto hsic_set_clk_fail; 1217 1185 } 1186 + 1187 + if (usbmisc->ops->vbus_comparator_on) 1188 + usbmisc->ops->vbus_comparator_on(data, true); 1218 1189 1219 1190 return 0; 1220 1191