mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
BACKPORT: usb: dwc3: core: Access XHCI address space temporarily to read port info
All DWC3 Multi Port controllers that exist today only support host mode. Temporarily map XHCI address space for host-only controllers and parse XHCI Extended Capabilities registers to read number of usb2 ports and usb3 ports present on multiport controller. Each USB Port is at least HS capable. The port info for usb2 and usb3 phy are identified as num_usb2_ports and num_usb3_ports and these are used as iterators for phy operations and for modifying GUSB2PHYCFG/ GUSB3PIPECTL registers accordingly. Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com> Reviewed-by: Bjorn Andersson <quic_bjorande@quicinc.com> Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Reviewed-by: Johan Hovold <johan+linaro@kernel.org> Tested-by: Johan Hovold <johan+linaro@kernel.org> Link: https://lore.kernel.org/r/20240420044901.884098-3-quic_kriskura@quicinc.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Bug: 233985973 Change-Id: I918ec194e477bde071e7d11e8610a893594bfdf6 (cherry picked from commit 921e109c6200741499ad0136e41cca9d16431c92) [Krishna: Resolved conflicts during backport] Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com>
This commit is contained in:
committed by
Treehugger Robot
parent
38859a233e
commit
28c74caaf3
@@ -39,6 +39,7 @@
|
|||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "../host/xhci.h"
|
||||||
|
|
||||||
#define DWC3_DEFAULT_AUTOSUSPEND_DELAY 5000 /* ms */
|
#define DWC3_DEFAULT_AUTOSUSPEND_DELAY 5000 /* ms */
|
||||||
|
|
||||||
@@ -1773,10 +1774,56 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
|
|||||||
return edev;
|
return edev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dwc3_get_num_ports(struct dwc3 *dwc)
|
||||||
|
{
|
||||||
|
void __iomem *base;
|
||||||
|
u8 major_revision;
|
||||||
|
u32 offset;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remap xHCI address space to access XHCI ext cap regs since it is
|
||||||
|
* needed to get information on number of ports present.
|
||||||
|
*/
|
||||||
|
base = ioremap(dwc->xhci_resources[0].start,
|
||||||
|
resource_size(&dwc->xhci_resources[0]));
|
||||||
|
if (!base)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
do {
|
||||||
|
offset = xhci_find_next_ext_cap(base, offset,
|
||||||
|
XHCI_EXT_CAPS_PROTOCOL);
|
||||||
|
if (!offset)
|
||||||
|
break;
|
||||||
|
|
||||||
|
val = readl(base + offset);
|
||||||
|
major_revision = XHCI_EXT_PORT_MAJOR(val);
|
||||||
|
|
||||||
|
val = readl(base + offset + 0x08);
|
||||||
|
if (major_revision == 0x03) {
|
||||||
|
dwc->num_usb3_ports += XHCI_EXT_PORT_COUNT(val);
|
||||||
|
} else if (major_revision <= 0x02) {
|
||||||
|
dwc->num_usb2_ports += XHCI_EXT_PORT_COUNT(val);
|
||||||
|
} else {
|
||||||
|
dev_warn(dwc->dev, "unrecognized port major revision %d\n",
|
||||||
|
major_revision);
|
||||||
|
}
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
dev_dbg(dwc->dev, "hs-ports: %u ss-ports: %u\n",
|
||||||
|
dwc->num_usb2_ports, dwc->num_usb3_ports);
|
||||||
|
|
||||||
|
iounmap(base);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int dwc3_probe(struct platform_device *pdev)
|
static int dwc3_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct resource *res, dwc_res;
|
struct resource *res, dwc_res;
|
||||||
|
unsigned int hw_mode;
|
||||||
struct dwc3 *dwc;
|
struct dwc3 *dwc;
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
@@ -1903,6 +1950,20 @@ static int dwc3_probe(struct platform_device *pdev)
|
|||||||
goto disable_clks;
|
goto disable_clks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Currently only DWC3 controllers that are host-only capable
|
||||||
|
* can have more than one port.
|
||||||
|
*/
|
||||||
|
hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
|
||||||
|
if (hw_mode == DWC3_GHWPARAMS0_MODE_HOST) {
|
||||||
|
ret = dwc3_get_num_ports(dwc);
|
||||||
|
if (ret)
|
||||||
|
goto disable_clks;
|
||||||
|
} else {
|
||||||
|
dwc->num_usb2_ports = 1;
|
||||||
|
dwc->num_usb3_ports = 1;
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock_init(&dwc->lock);
|
spin_lock_init(&dwc->lock);
|
||||||
mutex_init(&dwc->mutex);
|
mutex_init(&dwc->mutex);
|
||||||
|
|
||||||
|
|||||||
@@ -1043,6 +1043,8 @@ struct dwc3_scratchpad_array {
|
|||||||
* @usb3_phy: pointer to USB3 PHY
|
* @usb3_phy: pointer to USB3 PHY
|
||||||
* @usb2_generic_phy: pointer to USB2 PHY
|
* @usb2_generic_phy: pointer to USB2 PHY
|
||||||
* @usb3_generic_phy: pointer to USB3 PHY
|
* @usb3_generic_phy: pointer to USB3 PHY
|
||||||
|
* @num_usb2_ports: number of USB2 ports
|
||||||
|
* @num_usb3_ports: number of USB3 ports
|
||||||
* @phys_ready: flag to indicate that PHYs are ready
|
* @phys_ready: flag to indicate that PHYs are ready
|
||||||
* @ulpi: pointer to ulpi interface
|
* @ulpi: pointer to ulpi interface
|
||||||
* @ulpi_ready: flag to indicate that ULPI is initialized
|
* @ulpi_ready: flag to indicate that ULPI is initialized
|
||||||
@@ -1182,6 +1184,9 @@ struct dwc3 {
|
|||||||
struct phy *usb2_generic_phy;
|
struct phy *usb2_generic_phy;
|
||||||
struct phy *usb3_generic_phy;
|
struct phy *usb3_generic_phy;
|
||||||
|
|
||||||
|
u8 num_usb2_ports;
|
||||||
|
u8 num_usb3_ports;
|
||||||
|
|
||||||
bool phys_ready;
|
bool phys_ready;
|
||||||
|
|
||||||
struct ulpi *ulpi;
|
struct ulpi *ulpi;
|
||||||
|
|||||||
Reference in New Issue
Block a user