|
9 | 9 |
|
10 | 10 | #include <linux/platform_device.h>
|
11 | 11 |
|
| 12 | +#include "../host/xhci.h" |
| 13 | + |
12 | 14 | #include "core.h"
|
13 | 15 |
|
| 16 | + |
| 17 | +#define XHCI_HCSPARAMS1 0x4 |
| 18 | +#define XHCI_PORTSC_BASE 0x400 |
| 19 | + |
| 20 | +/* |
| 21 | + * dwc3_power_off_all_roothub_ports - Power off all Root hub ports |
| 22 | + * @dwc3: Pointer to our controller context structure |
| 23 | + */ |
| 24 | +static void dwc3_power_off_all_roothub_ports(struct dwc3 *dwc) |
| 25 | +{ |
| 26 | + int i, port_num; |
| 27 | + u32 reg, op_regs_base, offset; |
| 28 | + void __iomem *xhci_regs; |
| 29 | + |
| 30 | + /* xhci regs is not mapped yet, do it temperary here */ |
| 31 | + if (dwc->xhci_resources[0].start) { |
| 32 | + xhci_regs = ioremap(dwc->xhci_resources[0].start, |
| 33 | + DWC3_XHCI_REGS_END); |
| 34 | + if (IS_ERR(xhci_regs)) { |
| 35 | + dev_err(dwc->dev, "Failed to ioremap xhci_regs\n"); |
| 36 | + return; |
| 37 | + } |
| 38 | + |
| 39 | + op_regs_base = HC_LENGTH(readl(xhci_regs)); |
| 40 | + reg = readl(xhci_regs + XHCI_HCSPARAMS1); |
| 41 | + port_num = HCS_MAX_PORTS(reg); |
| 42 | + |
| 43 | + for (i = 1; i <= port_num; i++) { |
| 44 | + offset = op_regs_base + XHCI_PORTSC_BASE + 0x10*(i-1); |
| 45 | + reg = readl(xhci_regs + offset); |
| 46 | + reg &= ~PORT_POWER; |
| 47 | + writel(reg, xhci_regs + offset); |
| 48 | + } |
| 49 | + |
| 50 | + iounmap(xhci_regs); |
| 51 | + } else |
| 52 | + dev_err(dwc->dev, "xhci base reg invalid\n"); |
| 53 | +} |
| 54 | + |
14 | 55 | static int dwc3_host_get_irq(struct dwc3 *dwc)
|
15 | 56 | {
|
16 | 57 | struct platform_device *dwc3_pdev = to_platform_device(dwc->dev);
|
@@ -50,6 +91,13 @@ int dwc3_host_init(struct dwc3 *dwc)
|
50 | 91 | struct platform_device *dwc3_pdev = to_platform_device(dwc->dev);
|
51 | 92 | int prop_idx = 0;
|
52 | 93 |
|
| 94 | + /* |
| 95 | + * We have to power off all Root hub ports immediately after DWC3 set |
| 96 | + * to host mode to avoid VBUS glitch happen when xhci get reset later. |
| 97 | + */ |
| 98 | + if (dwc->host_vbus_glitches) |
| 99 | + dwc3_power_off_all_roothub_ports(dwc); |
| 100 | + |
53 | 101 | irq = dwc3_host_get_irq(dwc);
|
54 | 102 | if (irq < 0)
|
55 | 103 | return irq;
|
|
0 commit comments