mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 10:31:46 +09:00
ANDROID: usb: dwc3: core: Introduce vendor struct to deal with ABI breakage
Adding commits [1]/[2] to DWC3 driver essentially breaks the ABI as it modifies dwc3 structure by adding phy related variables to it. Fix this by moving the newly added variable to a vendor opts structure. Also to not break boot on pixel devices, use the already present phy structure in dwc for single port controllers and first port of multiport controllers. For the other ports, use the phy structures present in vendor dwc. [1]: https://lore.kernel.org/all/20240420044901.884098-3-quic_kriskura@quicinc.com/ [2]: https://lore.kernel.org/all/20240420044901.884098-5-quic_kriskura@quicinc.com/ Bug: 233985973 Change-Id: I76575bcd9a8f6c49077e4200cbda1c684af427c6 Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com>
This commit is contained in:
committed by
Treehugger Robot
parent
9f49b974c8
commit
8ed9a61b54
@@ -39,7 +39,16 @@
|
||||
#include "io.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
/*
|
||||
* For type visibility (http://b/236036821)
|
||||
*/
|
||||
const struct dwc3 *const ANDROID_GKI_struct_dwc3;
|
||||
EXPORT_SYMBOL_GPL(ANDROID_GKI_struct_dwc3);
|
||||
|
||||
#ifndef __GENKSYMS__
|
||||
#include "../host/xhci.h"
|
||||
#endif
|
||||
|
||||
#define DWC3_DEFAULT_AUTOSUSPEND_DELAY 5000 /* ms */
|
||||
|
||||
@@ -107,10 +116,11 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc)
|
||||
|
||||
void dwc3_enable_susphy(struct dwc3 *dwc, bool enable)
|
||||
{
|
||||
struct dwc3_vendor *vdwc = container_of(dwc, struct dwc3_vendor, dwc);
|
||||
u32 reg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dwc->num_usb3_ports; i++) {
|
||||
for (i = 0; i < vdwc->num_usb3_ports; i++) {
|
||||
reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(i));
|
||||
if (enable && !dwc->dis_u3_susphy_quirk)
|
||||
reg |= DWC3_GUSB3PIPECTL_SUSPHY;
|
||||
@@ -120,7 +130,7 @@ void dwc3_enable_susphy(struct dwc3 *dwc, bool enable)
|
||||
dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(i), reg);
|
||||
}
|
||||
|
||||
for (i = 0; i < dwc->num_usb2_ports; i++) {
|
||||
for (i = 0; i < vdwc->num_usb2_ports; i++) {
|
||||
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(i));
|
||||
if (enable && !dwc->dis_u2_susphy_quirk)
|
||||
reg |= DWC3_GUSB2PHYCFG_SUSPHY;
|
||||
@@ -146,6 +156,7 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
|
||||
static void __dwc3_set_mode(struct work_struct *work)
|
||||
{
|
||||
struct dwc3 *dwc = work_to_dwc(work);
|
||||
struct dwc3_vendor *vdwc = container_of(dwc, struct dwc3_vendor, dwc);
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
u32 reg;
|
||||
@@ -228,10 +239,14 @@ static void __dwc3_set_mode(struct work_struct *work)
|
||||
} else {
|
||||
if (dwc->usb2_phy)
|
||||
otg_set_vbus(dwc->usb2_phy->otg, true);
|
||||
for (i = 0; i < dwc->num_usb2_ports; i++)
|
||||
phy_set_mode(dwc->usb2_generic_phy[i], PHY_MODE_USB_HOST);
|
||||
for (i = 0; i < dwc->num_usb3_ports; i++)
|
||||
phy_set_mode(dwc->usb3_generic_phy[i], PHY_MODE_USB_HOST);
|
||||
|
||||
phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
|
||||
for (i = 1; i < vdwc->num_usb2_ports; i++)
|
||||
phy_set_mode(vdwc->usb2_generic_phy[i], PHY_MODE_USB_HOST);
|
||||
phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST);
|
||||
for (i = 1; i < vdwc->num_usb3_ports; i++)
|
||||
phy_set_mode(vdwc->usb3_generic_phy[i], PHY_MODE_USB_HOST);
|
||||
|
||||
if (dwc->dis_split_quirk) {
|
||||
reg = dwc3_readl(dwc->regs, DWC3_GUCTL3);
|
||||
reg |= DWC3_GUCTL3_SPLITDISABLE;
|
||||
@@ -246,8 +261,8 @@ static void __dwc3_set_mode(struct work_struct *work)
|
||||
|
||||
if (dwc->usb2_phy)
|
||||
otg_set_vbus(dwc->usb2_phy->otg, false);
|
||||
phy_set_mode(dwc->usb2_generic_phy[0], PHY_MODE_USB_DEVICE);
|
||||
phy_set_mode(dwc->usb3_generic_phy[0], PHY_MODE_USB_DEVICE);
|
||||
phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE);
|
||||
phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE);
|
||||
|
||||
ret = dwc3_gadget_init(dwc);
|
||||
if (ret)
|
||||
@@ -847,16 +862,17 @@ static int dwc3_hs_phy_setup(struct dwc3 *dwc, int index)
|
||||
*/
|
||||
static int dwc3_phy_setup(struct dwc3 *dwc)
|
||||
{
|
||||
struct dwc3_vendor *vdwc = container_of(dwc, struct dwc3_vendor, dwc);
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < dwc->num_usb3_ports; i++) {
|
||||
for (i = 0; i < vdwc->num_usb3_ports; i++) {
|
||||
ret = dwc3_ss_phy_setup(dwc, i);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < dwc->num_usb2_ports; i++) {
|
||||
for (i = 0; i < vdwc->num_usb2_ports; i++) {
|
||||
ret = dwc3_hs_phy_setup(dwc, i);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -899,6 +915,7 @@ static void dwc3_clk_disable(struct dwc3 *dwc)
|
||||
|
||||
static void dwc3_core_exit(struct dwc3 *dwc)
|
||||
{
|
||||
struct dwc3_vendor *vdwc = container_of(dwc, struct dwc3_vendor, dwc);
|
||||
int i;
|
||||
|
||||
dwc3_event_buffers_cleanup(dwc);
|
||||
@@ -906,18 +923,22 @@ static void dwc3_core_exit(struct dwc3 *dwc)
|
||||
usb_phy_set_suspend(dwc->usb2_phy, 1);
|
||||
usb_phy_set_suspend(dwc->usb3_phy, 1);
|
||||
|
||||
for (i = 0; i < dwc->num_usb2_ports; i++)
|
||||
phy_power_off(dwc->usb2_generic_phy[i]);
|
||||
for (i = 0; i < dwc->num_usb3_ports; i++)
|
||||
phy_power_off(dwc->usb3_generic_phy[i]);
|
||||
phy_power_off(dwc->usb2_generic_phy);
|
||||
for (i = 1; i < vdwc->num_usb2_ports; i++)
|
||||
phy_power_off(vdwc->usb2_generic_phy[i]);
|
||||
phy_power_off(dwc->usb3_generic_phy);
|
||||
for (i = 1; i < vdwc->num_usb3_ports; i++)
|
||||
phy_power_off(vdwc->usb3_generic_phy[i]);
|
||||
|
||||
usb_phy_shutdown(dwc->usb2_phy);
|
||||
usb_phy_shutdown(dwc->usb3_phy);
|
||||
|
||||
for (i = 0; i < dwc->num_usb2_ports; i++)
|
||||
phy_exit(dwc->usb2_generic_phy[i]);
|
||||
for (i = 0; i < dwc->num_usb3_ports; i++)
|
||||
phy_exit(dwc->usb3_generic_phy[i]);
|
||||
phy_exit(dwc->usb2_generic_phy);
|
||||
for (i = 1; i < vdwc->num_usb2_ports; i++)
|
||||
phy_exit(vdwc->usb2_generic_phy[i]);
|
||||
phy_exit(dwc->usb3_generic_phy);
|
||||
for (i = 1; i < vdwc->num_usb3_ports; i++)
|
||||
phy_exit(vdwc->usb3_generic_phy[i]);
|
||||
|
||||
dwc3_clk_disable(dwc);
|
||||
reset_control_assert(dwc->reset);
|
||||
@@ -1150,6 +1171,7 @@ static void dwc3_set_power_down_clk_scale(struct dwc3 *dwc)
|
||||
*/
|
||||
static int dwc3_core_init(struct dwc3 *dwc)
|
||||
{
|
||||
struct dwc3_vendor *vdwc = container_of(dwc, struct dwc3_vendor, dwc);
|
||||
unsigned int hw_mode;
|
||||
u32 reg;
|
||||
int ret;
|
||||
@@ -1189,14 +1211,22 @@ static int dwc3_core_init(struct dwc3 *dwc)
|
||||
usb_phy_init(dwc->usb2_phy);
|
||||
usb_phy_init(dwc->usb3_phy);
|
||||
|
||||
for (i = 0; i < dwc->num_usb2_ports; i++) {
|
||||
ret = phy_init(dwc->usb2_generic_phy[i]);
|
||||
ret = phy_init(dwc->usb2_generic_phy);
|
||||
if (ret < 0)
|
||||
goto err0a;
|
||||
|
||||
for (i = 1; i < vdwc->num_usb2_ports; i++) {
|
||||
ret = phy_init(vdwc->usb2_generic_phy[i]);
|
||||
if (ret < 0)
|
||||
goto exit_usb2_phy;
|
||||
}
|
||||
|
||||
for (i = 0; i < dwc->num_usb3_ports; i++) {
|
||||
ret = phy_init(dwc->usb3_generic_phy[i]);
|
||||
ret = phy_init(dwc->usb3_generic_phy);
|
||||
if (ret < 0)
|
||||
goto exit_usb2_phy;
|
||||
|
||||
for (i = 1; i < vdwc->num_usb3_ports; i++) {
|
||||
ret = phy_init(vdwc->usb3_generic_phy[i]);
|
||||
if (ret < 0)
|
||||
goto exit_usb3_phy;
|
||||
}
|
||||
@@ -1226,14 +1256,22 @@ static int dwc3_core_init(struct dwc3 *dwc)
|
||||
usb_phy_set_suspend(dwc->usb2_phy, 0);
|
||||
usb_phy_set_suspend(dwc->usb3_phy, 0);
|
||||
|
||||
for (i = 0; i < dwc->num_usb2_ports; i++) {
|
||||
ret = phy_power_on(dwc->usb2_generic_phy[i]);
|
||||
ret = phy_power_on(dwc->usb2_generic_phy);
|
||||
if (ret < 0)
|
||||
goto set_suspend_phy;
|
||||
|
||||
for (i = 1; i < vdwc->num_usb2_ports; i++) {
|
||||
ret = phy_power_on(vdwc->usb2_generic_phy[i]);
|
||||
if (ret < 0)
|
||||
goto power_off_usb2_phy;
|
||||
}
|
||||
|
||||
for (i = 0; i < dwc->num_usb3_ports; i++) {
|
||||
ret = phy_power_on(dwc->usb3_generic_phy[i]);
|
||||
ret = phy_power_on(dwc->usb3_generic_phy);
|
||||
if (ret < 0)
|
||||
goto power_off_usb2_phy;
|
||||
|
||||
for (i = 1; i < vdwc->num_usb3_ports; i++) {
|
||||
ret = phy_power_on(vdwc->usb3_generic_phy[i]);
|
||||
if (ret < 0)
|
||||
goto power_off_usb3_phy;
|
||||
}
|
||||
@@ -1377,26 +1415,31 @@ static int dwc3_core_init(struct dwc3 *dwc)
|
||||
* (http://b/233985973)
|
||||
*/
|
||||
power_off_usb3_phy:
|
||||
for (j = i - 1; j >= 0; j--)
|
||||
phy_power_off(dwc->usb3_generic_phy[j]);
|
||||
i = dwc->num_usb2_ports;
|
||||
for (j = i - 1; j > 0; j--)
|
||||
phy_power_off(vdwc->usb3_generic_phy[j]);
|
||||
phy_power_off(dwc->usb3_generic_phy);
|
||||
i = vdwc->num_usb2_ports;
|
||||
|
||||
power_off_usb2_phy:
|
||||
for (j = i - 1; j >= 0; j--)
|
||||
phy_power_off(dwc->usb2_generic_phy[j]);
|
||||
i = dwc->num_usb3_ports;
|
||||
for (j = i - 1; j > 0; j--)
|
||||
phy_power_off(vdwc->usb2_generic_phy[j]);
|
||||
phy_power_off(dwc->usb2_generic_phy);
|
||||
i = vdwc->num_usb3_ports;
|
||||
|
||||
set_suspend_phy:
|
||||
usb_phy_set_suspend(dwc->usb2_phy, 1);
|
||||
usb_phy_set_suspend(dwc->usb3_phy, 1);
|
||||
|
||||
exit_usb3_phy:
|
||||
for (j = i - 1; j >= 0; j--)
|
||||
phy_exit(dwc->usb3_generic_phy[j]);
|
||||
i = dwc->num_usb2_ports;
|
||||
for (j = i - 1; j > 0; j--)
|
||||
phy_exit(vdwc->usb3_generic_phy[j]);
|
||||
phy_exit(dwc->usb3_generic_phy);
|
||||
i = vdwc->num_usb2_ports;
|
||||
|
||||
exit_usb2_phy:
|
||||
for (j = i - 1; j >= 0; j--)
|
||||
phy_exit(dwc->usb2_generic_phy[j]);
|
||||
for (j = i - 1; j > 0; j--)
|
||||
phy_exit(vdwc->usb2_generic_phy[j]);
|
||||
phy_exit(dwc->usb2_generic_phy);
|
||||
|
||||
usb_phy_shutdown(dwc->usb2_phy);
|
||||
usb_phy_shutdown(dwc->usb3_phy);
|
||||
@@ -1410,8 +1453,10 @@ err0:
|
||||
|
||||
static int dwc3_core_get_phy(struct dwc3 *dwc)
|
||||
{
|
||||
struct dwc3_vendor *vdwc = container_of(dwc, struct dwc3_vendor, dwc);
|
||||
struct device *dev = dwc->dev;
|
||||
struct device_node *node = dev->of_node;
|
||||
struct phy *temp_phy = NULL;
|
||||
char phy_name[9];
|
||||
int ret;
|
||||
int i;
|
||||
@@ -1440,38 +1485,48 @@ static int dwc3_core_get_phy(struct dwc3 *dwc)
|
||||
return dev_err_probe(dev, ret, "no usb3 phy configured\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < dwc->num_usb2_ports; i++) {
|
||||
if (dwc->num_usb2_ports == 1)
|
||||
for (i = 0; i < vdwc->num_usb2_ports; i++) {
|
||||
if (vdwc->num_usb2_ports == 1)
|
||||
snprintf(phy_name, sizeof(phy_name), "usb2-phy");
|
||||
else
|
||||
snprintf(phy_name, sizeof(phy_name), "usb2-%d", i);
|
||||
|
||||
dwc->usb2_generic_phy[i] = devm_phy_get(dev, phy_name);
|
||||
if (IS_ERR(dwc->usb2_generic_phy[i])) {
|
||||
ret = PTR_ERR(dwc->usb2_generic_phy[i]);
|
||||
temp_phy = devm_phy_get(dev, phy_name);
|
||||
if (IS_ERR(temp_phy)) {
|
||||
ret = PTR_ERR(temp_phy);
|
||||
if (ret == -ENOSYS || ret == -ENODEV)
|
||||
dwc->usb2_generic_phy[i] = NULL;
|
||||
temp_phy = NULL;
|
||||
else
|
||||
return dev_err_probe(dev, ret, "failed to lookup phy %s\n",
|
||||
phy_name);
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
dwc->usb2_generic_phy = temp_phy;
|
||||
else
|
||||
vdwc->usb2_generic_phy[i] = temp_phy;
|
||||
}
|
||||
|
||||
for (i = 0; i < dwc->num_usb3_ports; i++) {
|
||||
if (dwc->num_usb3_ports == 1)
|
||||
for (i = 0; i < vdwc->num_usb3_ports; i++) {
|
||||
if (vdwc->num_usb3_ports == 1)
|
||||
snprintf(phy_name, sizeof(phy_name), "usb3-phy");
|
||||
else
|
||||
snprintf(phy_name, sizeof(phy_name), "usb3-%d", i);
|
||||
|
||||
dwc->usb3_generic_phy[i] = devm_phy_get(dev, phy_name);
|
||||
if (IS_ERR(dwc->usb3_generic_phy[i])) {
|
||||
ret = PTR_ERR(dwc->usb3_generic_phy[i]);
|
||||
temp_phy = devm_phy_get(dev, phy_name);
|
||||
if (IS_ERR(temp_phy)) {
|
||||
ret = PTR_ERR(temp_phy);
|
||||
if (ret == -ENOSYS || ret == -ENODEV)
|
||||
dwc->usb3_generic_phy[i] = NULL;
|
||||
temp_phy = NULL;
|
||||
else
|
||||
return dev_err_probe(dev, ret, "failed to lookup phy %s\n",
|
||||
phy_name);
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
dwc->usb3_generic_phy = temp_phy;
|
||||
else
|
||||
vdwc->usb3_generic_phy[i] = temp_phy;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1479,6 +1534,7 @@ static int dwc3_core_get_phy(struct dwc3 *dwc)
|
||||
|
||||
static int dwc3_core_init_mode(struct dwc3 *dwc)
|
||||
{
|
||||
struct dwc3_vendor *vdwc = container_of(dwc, struct dwc3_vendor, dwc);
|
||||
struct device *dev = dwc->dev;
|
||||
int ret;
|
||||
int i;
|
||||
@@ -1489,8 +1545,8 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
|
||||
|
||||
if (dwc->usb2_phy)
|
||||
otg_set_vbus(dwc->usb2_phy->otg, false);
|
||||
phy_set_mode(dwc->usb2_generic_phy[0], PHY_MODE_USB_DEVICE);
|
||||
phy_set_mode(dwc->usb3_generic_phy[0], PHY_MODE_USB_DEVICE);
|
||||
phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE);
|
||||
phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE);
|
||||
|
||||
ret = dwc3_gadget_init(dwc);
|
||||
if (ret)
|
||||
@@ -1502,10 +1558,12 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
|
||||
if (dwc->usb2_phy)
|
||||
otg_set_vbus(dwc->usb2_phy->otg, true);
|
||||
|
||||
for (i = 0; i < dwc->num_usb2_ports; i++)
|
||||
phy_set_mode(dwc->usb2_generic_phy[i], PHY_MODE_USB_HOST);
|
||||
for (i = 0; i < dwc->num_usb3_ports; i++)
|
||||
phy_set_mode(dwc->usb3_generic_phy[i], PHY_MODE_USB_HOST);
|
||||
phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
|
||||
for (i = 1; i < vdwc->num_usb2_ports; i++)
|
||||
phy_set_mode(vdwc->usb2_generic_phy[i], PHY_MODE_USB_HOST);
|
||||
phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST);
|
||||
for (i = 1; i < vdwc->num_usb3_ports; i++)
|
||||
phy_set_mode(vdwc->usb3_generic_phy[i], PHY_MODE_USB_HOST);
|
||||
|
||||
ret = dwc3_host_init(dwc);
|
||||
if (ret)
|
||||
@@ -1865,6 +1923,7 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
|
||||
|
||||
static int dwc3_get_num_ports(struct dwc3 *dwc)
|
||||
{
|
||||
struct dwc3_vendor *vdwc = container_of(dwc, struct dwc3_vendor, dwc);
|
||||
void __iomem *base;
|
||||
u8 major_revision;
|
||||
u32 offset;
|
||||
@@ -1891,9 +1950,9 @@ static int dwc3_get_num_ports(struct dwc3 *dwc)
|
||||
|
||||
val = readl(base + offset + 0x08);
|
||||
if (major_revision == 0x03) {
|
||||
dwc->num_usb3_ports += XHCI_EXT_PORT_COUNT(val);
|
||||
vdwc->num_usb3_ports += XHCI_EXT_PORT_COUNT(val);
|
||||
} else if (major_revision <= 0x02) {
|
||||
dwc->num_usb2_ports += XHCI_EXT_PORT_COUNT(val);
|
||||
vdwc->num_usb2_ports += XHCI_EXT_PORT_COUNT(val);
|
||||
} else {
|
||||
dev_warn(dwc->dev, "unrecognized port major revision %d\n",
|
||||
major_revision);
|
||||
@@ -1901,11 +1960,11 @@ static int dwc3_get_num_ports(struct dwc3 *dwc)
|
||||
} while (1);
|
||||
|
||||
dev_dbg(dwc->dev, "hs-ports: %u ss-ports: %u\n",
|
||||
dwc->num_usb2_ports, dwc->num_usb3_ports);
|
||||
vdwc->num_usb2_ports, vdwc->num_usb3_ports);
|
||||
|
||||
iounmap(base);
|
||||
if (dwc->num_usb2_ports > DWC3_USB2_MAX_PORTS ||
|
||||
dwc->num_usb3_ports > DWC3_USB3_MAX_PORTS)
|
||||
if (vdwc->num_usb2_ports > DWC3_USB2_MAX_PORTS ||
|
||||
vdwc->num_usb3_ports > DWC3_USB3_MAX_PORTS)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@@ -1917,16 +1976,18 @@ static int dwc3_probe(struct platform_device *pdev)
|
||||
struct resource *res, dwc_res;
|
||||
unsigned int hw_mode;
|
||||
struct dwc3 *dwc;
|
||||
struct dwc3_vendor *vdwc;
|
||||
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
void __iomem *regs;
|
||||
|
||||
dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL);
|
||||
if (!dwc)
|
||||
vdwc = devm_kzalloc(dev, sizeof(*vdwc), GFP_KERNEL);
|
||||
if (!vdwc)
|
||||
return -ENOMEM;
|
||||
|
||||
dwc = &vdwc->dwc;
|
||||
dwc->dev = dev;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
@@ -2053,8 +2114,8 @@ static int dwc3_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto disable_clks;
|
||||
} else {
|
||||
dwc->num_usb2_ports = 1;
|
||||
dwc->num_usb3_ports = 1;
|
||||
vdwc->num_usb2_ports = 1;
|
||||
vdwc->num_usb3_ports = 1;
|
||||
}
|
||||
|
||||
spin_lock_init(&dwc->lock);
|
||||
@@ -2115,20 +2176,24 @@ err5:
|
||||
usb_phy_set_suspend(dwc->usb2_phy, 1);
|
||||
usb_phy_set_suspend(dwc->usb3_phy, 1);
|
||||
|
||||
for (i = 0; i < dwc->num_usb3_ports; i++)
|
||||
phy_power_off(dwc->usb3_generic_phy[i]);
|
||||
phy_power_off(dwc->usb3_generic_phy);
|
||||
for (i = 1; i < vdwc->num_usb3_ports; i++)
|
||||
phy_power_off(vdwc->usb3_generic_phy[i]);
|
||||
|
||||
for (i = 0; i < dwc->num_usb2_ports; i++)
|
||||
phy_power_off(dwc->usb2_generic_phy[i]);
|
||||
phy_power_off(dwc->usb2_generic_phy);
|
||||
for (i = 1; i < vdwc->num_usb2_ports; i++)
|
||||
phy_power_off(vdwc->usb2_generic_phy[i]);
|
||||
|
||||
usb_phy_shutdown(dwc->usb2_phy);
|
||||
usb_phy_shutdown(dwc->usb3_phy);
|
||||
|
||||
for (i = 0; i < dwc->num_usb3_ports; i++)
|
||||
phy_exit(dwc->usb3_generic_phy[i]);
|
||||
phy_exit(dwc->usb3_generic_phy);
|
||||
for (i = 1; i < vdwc->num_usb3_ports; i++)
|
||||
phy_exit(vdwc->usb3_generic_phy[i]);
|
||||
|
||||
for (i = 0; i < dwc->num_usb2_ports; i++)
|
||||
phy_exit(dwc->usb2_generic_phy[i]);
|
||||
phy_exit(dwc->usb2_generic_phy);
|
||||
for (i = 1; i < vdwc->num_usb2_ports; i++)
|
||||
phy_exit(vdwc->usb2_generic_phy[i]);
|
||||
|
||||
dwc3_ulpi_exit(dwc);
|
||||
|
||||
@@ -2214,6 +2279,7 @@ assert_reset:
|
||||
|
||||
static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
|
||||
{
|
||||
struct dwc3_vendor *vdwc = container_of(dwc, struct dwc3_vendor, dwc);
|
||||
u32 reg;
|
||||
int i;
|
||||
|
||||
@@ -2234,7 +2300,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
|
||||
/* Let controller to suspend HSPHY before PHY driver suspends */
|
||||
if (dwc->dis_u2_susphy_quirk ||
|
||||
dwc->dis_enblslpm_quirk) {
|
||||
for (i = 0; i < dwc->num_usb2_ports; i++) {
|
||||
for (i = 0; i < vdwc->num_usb2_ports; i++) {
|
||||
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(i));
|
||||
reg |= DWC3_GUSB2PHYCFG_ENBLSLPM |
|
||||
DWC3_GUSB2PHYCFG_SUSPHY;
|
||||
@@ -2244,10 +2310,12 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
|
||||
usleep_range(5000, 6000);
|
||||
}
|
||||
|
||||
for (i = 0; i < dwc->num_usb2_ports; i++)
|
||||
phy_pm_runtime_put_sync(dwc->usb2_generic_phy[i]);
|
||||
for (i = 0; i < dwc->num_usb3_ports; i++)
|
||||
phy_pm_runtime_put_sync(dwc->usb3_generic_phy[i]);
|
||||
phy_pm_runtime_put_sync(dwc->usb2_generic_phy);
|
||||
for (i = 1; i < vdwc->num_usb2_ports; i++)
|
||||
phy_pm_runtime_put_sync(vdwc->usb2_generic_phy[i]);
|
||||
phy_pm_runtime_put_sync(dwc->usb3_generic_phy);
|
||||
for (i = 1; i < vdwc->num_usb3_ports; i++)
|
||||
phy_pm_runtime_put_sync(vdwc->usb3_generic_phy[i]);
|
||||
break;
|
||||
case DWC3_GCTL_PRTCAP_OTG:
|
||||
/* do nothing during runtime_suspend */
|
||||
@@ -2272,6 +2340,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
|
||||
|
||||
static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
|
||||
{
|
||||
struct dwc3_vendor *vdwc = container_of(dwc, struct dwc3_vendor, dwc);
|
||||
int ret;
|
||||
u32 reg;
|
||||
int i;
|
||||
@@ -2294,7 +2363,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
|
||||
break;
|
||||
}
|
||||
/* Restore GUSB2PHYCFG bits that were modified in suspend */
|
||||
for (i = 0; i < dwc->num_usb2_ports; i++) {
|
||||
for (i = 0; i < vdwc->num_usb2_ports; i++) {
|
||||
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(i));
|
||||
if (dwc->dis_u2_susphy_quirk)
|
||||
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
|
||||
@@ -2305,10 +2374,12 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
|
||||
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(i), reg);
|
||||
}
|
||||
|
||||
for (i = 0; i < dwc->num_usb2_ports; i++)
|
||||
phy_pm_runtime_get_sync(dwc->usb2_generic_phy[i]);
|
||||
for (i = 0; i < dwc->num_usb3_ports; i++)
|
||||
phy_pm_runtime_get_sync(dwc->usb3_generic_phy[i]);
|
||||
phy_pm_runtime_get_sync(dwc->usb2_generic_phy);
|
||||
for (i = 1; i < vdwc->num_usb2_ports; i++)
|
||||
phy_pm_runtime_get_sync(vdwc->usb2_generic_phy[i]);
|
||||
phy_pm_runtime_get_sync(dwc->usb3_generic_phy);
|
||||
for (i = 1; i < vdwc->num_usb3_ports; i++)
|
||||
phy_pm_runtime_get_sync(vdwc->usb3_generic_phy[i]);
|
||||
break;
|
||||
case DWC3_GCTL_PRTCAP_OTG:
|
||||
/* nothing to do on runtime_resume */
|
||||
@@ -2510,12 +2581,6 @@ static struct platform_driver dwc3_driver = {
|
||||
|
||||
module_platform_driver(dwc3_driver);
|
||||
|
||||
/*
|
||||
* For type visibility (http://b/236036821)
|
||||
*/
|
||||
const struct dwc3 *const ANDROID_GKI_struct_dwc3;
|
||||
EXPORT_SYMBOL_GPL(ANDROID_GKI_struct_dwc3);
|
||||
|
||||
MODULE_ALIAS("platform:dwc3");
|
||||
MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -1048,10 +1048,8 @@ struct dwc3_scratchpad_array {
|
||||
* @usb_psy: pointer to power supply interface.
|
||||
* @usb2_phy: pointer to USB2 PHY
|
||||
* @usb3_phy: pointer to USB3 PHY
|
||||
* @usb2_generic_phy: pointer to array of USB2 PHYs
|
||||
* @usb3_generic_phy: pointer to array of USB3 PHYs
|
||||
* @num_usb2_ports: number of USB2 ports
|
||||
* @num_usb3_ports: number of USB3 ports
|
||||
* @usb2_generic_phy: pointer to USB2 PHY
|
||||
* @usb3_generic_phy: pointer to USB3 PHY
|
||||
* @phys_ready: flag to indicate that PHYs are ready
|
||||
* @ulpi: pointer to ulpi interface
|
||||
* @ulpi_ready: flag to indicate that ULPI is initialized
|
||||
@@ -1188,11 +1186,8 @@ struct dwc3 {
|
||||
struct usb_phy *usb2_phy;
|
||||
struct usb_phy *usb3_phy;
|
||||
|
||||
struct phy *usb2_generic_phy[DWC3_USB2_MAX_PORTS];
|
||||
struct phy *usb3_generic_phy[DWC3_USB3_MAX_PORTS];
|
||||
|
||||
u8 num_usb2_ports;
|
||||
u8 num_usb3_ports;
|
||||
struct phy *usb2_generic_phy;
|
||||
struct phy *usb3_generic_phy;
|
||||
|
||||
bool phys_ready;
|
||||
|
||||
@@ -1377,6 +1372,23 @@ struct dwc3 {
|
||||
ANDROID_KABI_RESERVE(4);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dwc3_vendor - contains parameters without modifying the format of DWC3 core
|
||||
* @dwc: contains dwc3 core reference
|
||||
* @num_usb2_ports: number of USB2 ports
|
||||
* @num_usb3_ports: number of USB3 ports
|
||||
* @usb2_generic_phy: pointer to array of USB2 PHYs
|
||||
* @usb3_generic_phy: pointer to array of USB3 PHYs
|
||||
*/
|
||||
struct dwc3_vendor {
|
||||
struct dwc3 dwc;
|
||||
u8 num_usb2_ports;
|
||||
u8 num_usb3_ports;
|
||||
|
||||
struct phy *usb2_generic_phy[DWC3_USB2_MAX_PORTS];
|
||||
struct phy *usb3_generic_phy[DWC3_USB3_MAX_PORTS];
|
||||
};
|
||||
|
||||
#define INCRX_BURST_MODE 0
|
||||
#define INCRX_UNDEF_LENGTH_BURST_MODE 1
|
||||
|
||||
|
||||
@@ -332,6 +332,7 @@ void dwc3_otg_update(struct dwc3 *dwc, bool ignore_idstatus)
|
||||
int id;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
struct dwc3_vendor *vdwc = container_of(dwc, struct dwc3_vendor, dwc);
|
||||
|
||||
if (dwc->dr_mode != USB_DR_MODE_OTG)
|
||||
return;
|
||||
@@ -387,9 +388,10 @@ void dwc3_otg_update(struct dwc3 *dwc, bool ignore_idstatus)
|
||||
} else {
|
||||
if (dwc->usb2_phy)
|
||||
otg_set_vbus(dwc->usb2_phy->otg, true);
|
||||
for (i = 0; i < dwc->num_usb2_ports; i++) {
|
||||
if (dwc->usb2_generic_phy[i]) {
|
||||
phy_set_mode(dwc->usb2_generic_phy[i],
|
||||
phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
|
||||
for (i = 1; i < vdwc->num_usb2_ports; i++) {
|
||||
if (vdwc->usb2_generic_phy[i]) {
|
||||
phy_set_mode(vdwc->usb2_generic_phy[i],
|
||||
PHY_MODE_USB_HOST);
|
||||
}
|
||||
}
|
||||
@@ -404,8 +406,8 @@ void dwc3_otg_update(struct dwc3 *dwc, bool ignore_idstatus)
|
||||
|
||||
if (dwc->usb2_phy)
|
||||
otg_set_vbus(dwc->usb2_phy->otg, false);
|
||||
if (dwc->usb2_generic_phy[0])
|
||||
phy_set_mode(dwc->usb2_generic_phy[0],
|
||||
if (dwc->usb2_generic_phy)
|
||||
phy_set_mode(dwc->usb2_generic_phy,
|
||||
PHY_MODE_USB_DEVICE);
|
||||
ret = dwc3_gadget_init(dwc);
|
||||
if (ret)
|
||||
|
||||
Reference in New Issue
Block a user