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

USB: ehci-mxc: Setup portsc register prior to accessing OTG viewport

In order to read/write to the i.MX OTG viewport register it is necessary to setup
the PORTSCx register first.

By default i.MX OTG port is configured for USB serial PHY. In order to use a ULPI PHY
the PORTSCx register needs to be configured properly.

commit 724c852 (USB: ehci/mxc: compile fix) placed the PORTSC setup after the OTG
viewport is accessed and this causes ULPI read/write to fail.

Revert the PORTSC setup order.

Tested on a MX31PDK board with a ISP1504 transceiver:

ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
mxc-ehci mxc-ehci.0: initializing i.MX USB Controller
ULPI transceiver vendor/product ID 0x04cc/0x1504
Found NXP ISP1504 ULPI transceiver.
ULPI integrity check: passed.

Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Fabio Estevam and committed by
Greg Kroah-Hartman
0247a7bc 2c8245c4

+14 -12
+14 -12
drivers/usb/host/ehci-mxc.c
··· 36 36 static int ehci_mxc_setup(struct usb_hcd *hcd) 37 37 { 38 38 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 39 - struct device *dev = hcd->self.controller; 40 - struct mxc_usbh_platform_data *pdata = dev_get_platdata(dev); 41 39 int retval; 42 40 43 - /* EHCI registers start at offset 0x100 */ 44 - ehci->caps = hcd->regs + 0x100; 45 - ehci->regs = hcd->regs + 0x100 + 46 - HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); 47 41 dbg_hcs_params(ehci, "reset"); 48 42 dbg_hcc_params(ehci, "reset"); 49 43 ··· 58 64 ehci->sbrn = 0x20; 59 65 60 66 ehci_reset(ehci); 61 - 62 - /* set up the PORTSCx register */ 63 - ehci_writel(ehci, pdata->portsc, &ehci->regs->port_status[0]); 64 - 65 - /* is this really needed? */ 66 - msleep(10); 67 67 68 68 ehci_port_power(ehci, 0); 69 69 return 0; ··· 116 128 int irq, ret; 117 129 struct ehci_mxc_priv *priv; 118 130 struct device *dev = &pdev->dev; 131 + struct ehci_hcd *ehci; 119 132 120 133 dev_info(&pdev->dev, "initializing i.MX USB Controller\n"); 121 134 ··· 192 203 ret = mxc_initialize_usb_hw(pdev->id, pdata->flags); 193 204 if (ret < 0) 194 205 goto err_init; 206 + 207 + ehci = hcd_to_ehci(hcd); 208 + 209 + /* EHCI registers start at offset 0x100 */ 210 + ehci->caps = hcd->regs + 0x100; 211 + ehci->regs = hcd->regs + 0x100 + 212 + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); 213 + 214 + /* set up the PORTSCx register */ 215 + ehci_writel(ehci, pdata->portsc, &ehci->regs->port_status[0]); 216 + 217 + /* is this really needed? */ 218 + msleep(10); 195 219 196 220 /* Initialize the transceiver */ 197 221 if (pdata->otg) {