Module Name:    src
Committed By:   reinoud
Date:           Sun Sep 21 15:22:40 UTC 2014

Modified Files:
        src/sys/arch/arm/samsung: exynos_usb.c

Log Message:
Fix Exynos5 SoC OHCI hang

Redo the Exynos 5410 USB phy initialisation following uboot


To generate a diff of this commit:
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/arm/samsung/exynos_usb.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/samsung/exynos_usb.c
diff -u src/sys/arch/arm/samsung/exynos_usb.c:1.9 src/sys/arch/arm/samsung/exynos_usb.c:1.10
--- src/sys/arch/arm/samsung/exynos_usb.c:1.9	Tue Sep  9 21:26:47 2014
+++ src/sys/arch/arm/samsung/exynos_usb.c	Sun Sep 21 15:22:40 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: exynos_usb.c,v 1.9 2014/09/09 21:26:47 reinoud Exp $	*/
+/*	$NetBSD: exynos_usb.c,v 1.10 2014/09/21 15:22:40 reinoud Exp $	*/
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: exynos_usb.c,v 1.9 2014/09/09 21:26:47 reinoud Exp $");
+__KERNEL_RCSID(1, "$NetBSD: exynos_usb.c,v 1.10 2014/09/21 15:22:40 reinoud Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -223,11 +223,20 @@ exynos_usb_attach(device_t parent, devic
 
 	/*
 	 * Disable interrupts
+	 *
+	 * To prevent OHCI lockups on Exynos5 SoCs, we first have to read the
+	 * address before we set it; this is most likely a bug in the SoC
 	 */
 #if NOHCI > 0
+	int regval;
+
+	regval = bus_space_read_1(sc->sc_bst, sc->sc_ohci_bsh,
+		OHCI_INTERRUPT_DISABLE);
+	regval = OHCI_ALL_INTRS;
 	bus_space_write_4(sc->sc_bst, sc->sc_ohci_bsh,
-	    OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS);
+	    OHCI_INTERRUPT_DISABLE, regval);
 #endif
+
 #if NEHCI > 0
 	bus_size_t caplength = bus_space_read_1(sc->sc_bst,
 	    sc->sc_ehci_bsh, EHCI_CAPLENGTH);
@@ -504,7 +513,9 @@ exynos4_usb2phy_enable(struct exynos_usb
 static void
 exynos5410_usb2phy_enable(struct exynos_usb_softc *sc)
 {
-	uint32_t phyhost, phyotg, phyhsic, ehcictrl, ohcictrl;
+	uint32_t phyhost; //, phyotg;
+	uint32_t phyhsic1, phyhsic2, hsic_ctrl;
+	uint32_t ehcictrl; //, ohcictrl;
 
 	/* host configuration: */
 	phyhost = bus_space_read_4(sc->sc_bst, sc->sc_usb2phy_bsh,
@@ -518,11 +529,11 @@ exynos5410_usb2phy_enable(struct exynos_
 	phyhost &= ~(HOST_CTRL0_FORCESUSPEND | HOST_CTRL0_FORCESLEEP);
 
 	/* host phy reset */
-	phyhost &= ~(HOST_CTRL0_PHY_SWRST | HOST_CTRL0_SIDDQ);
+	phyhost &= ~(HOST_CTRL0_PHY_SWRST | HOST_CTRL0_PHY_SWRST_ALL |
+		HOST_CTRL0_SIDDQ | HOST_CTRL0_COMMONON_N);
 			
 	/* host link reset */
-	phyhost |= HOST_CTRL0_LINK_SWRST | HOST_CTRL0_UTMI_SWRST |
-		HOST_CTRL0_COMMONON_N;
+	phyhost |= HOST_CTRL0_LINK_SWRST | HOST_CTRL0_UTMI_SWRST;
 
 	/* do the reset */
 	bus_space_write_4(sc->sc_bst, sc->sc_usb2phy_bsh,
@@ -532,6 +543,7 @@ exynos5410_usb2phy_enable(struct exynos_
 	bus_space_write_4(sc->sc_bst, sc->sc_usb2phy_bsh,
 		USB_PHY_HOST_CTRL0, phyhost);
 
+#if 0
 	/* otg configuration: */
 	phyotg = bus_space_read_4(sc->sc_bst, sc->sc_usb2phy_bsh,
 		USB_PHY_OTG_SYS);
@@ -557,23 +569,49 @@ exynos5410_usb2phy_enable(struct exynos_
 		OTG_SYS_PHYLINK_SWRST);
 	bus_space_write_4(sc->sc_bst, sc->sc_usb2phy_bsh,
 		USB_PHY_OTG_SYS, phyotg);
+#endif
 
 	/* HSIC phy configuration: */
-	phyhsic = REFCLKDIV_12 | REFCLKSEL_HSIC_DEFAULT |
-		HSIC_CTRL_PHY_SWRST;
+	hsic_ctrl = HSIC_CTRL_FORCESUSPEND | HSIC_CTRL_FORCESLEEP |
+		HSIC_CTRL_SIDDQ;
+
+	phyhsic1 = bus_space_read_4(sc->sc_bst, sc->sc_usb2phy_bsh,
+		USB_PHY_HSIC_CTRL1);
+	phyhsic2 = bus_space_read_4(sc->sc_bst, sc->sc_usb2phy_bsh,
+		USB_PHY_HSIC_CTRL1);
+
+	phyhsic1 &= ~hsic_ctrl;
+	phyhsic2 &= ~hsic_ctrl;
 
 	bus_space_write_4(sc->sc_bst, sc->sc_usb2phy_bsh,
-		USB_PHY_HSIC_CTRL1, phyhsic);
+		USB_PHY_HSIC_CTRL1, phyhsic1);
 	bus_space_write_4(sc->sc_bst, sc->sc_usb2phy_bsh,
-		USB_PHY_HSIC_CTRL2, phyhsic);
+		USB_PHY_HSIC_CTRL2, phyhsic2);
 	DELAY(10000);
-	phyhsic &= ~HSIC_CTRL_PHY_SWRST;
+
+	hsic_ctrl = REFCLKDIV_12 | REFCLKSEL_HSIC_DEFAULT |
+		HSIC_CTRL_UTMI_SWRST;
+
+	phyhsic1 |= hsic_ctrl;
+	phyhsic2 |= hsic_ctrl;
+
 	bus_space_write_4(sc->sc_bst, sc->sc_usb2phy_bsh,
-		USB_PHY_HSIC_CTRL1, phyhsic);
+		USB_PHY_HSIC_CTRL1, phyhsic1);
 	bus_space_write_4(sc->sc_bst, sc->sc_usb2phy_bsh,
-		USB_PHY_HSIC_CTRL2, phyhsic);
+		USB_PHY_HSIC_CTRL2, phyhsic2);
 
-	DELAY(80000);
+	DELAY(10000);
+
+	hsic_ctrl = HSIC_CTRL_PHY_SWRST | HSIC_CTRL_UTMI_SWRST;
+
+	phyhsic1 &= ~hsic_ctrl;
+	phyhsic2 &= ~hsic_ctrl;
+
+	bus_space_write_4(sc->sc_bst, sc->sc_usb2phy_bsh,
+		USB_PHY_HSIC_CTRL1, phyhsic1);
+	bus_space_write_4(sc->sc_bst, sc->sc_usb2phy_bsh,
+		USB_PHY_HSIC_CTRL2, phyhsic2);
+	DELAY(20000);
 
 	/* enable EHCI DMA burst: */
 	ehcictrl = bus_space_read_4(sc->sc_bst, sc->sc_usb2phy_bsh,
@@ -583,13 +621,6 @@ exynos5410_usb2phy_enable(struct exynos_
 		HOST_EHCICTRL_ENA_INCR16;
 	bus_space_write_4(sc->sc_bst, sc->sc_usb2phy_bsh,
 		USB_PHY_HOST_EHCICTRL, ehcictrl);
-
-	/* suspend OHCI legacy (?) */
-	ohcictrl = bus_space_read_4(sc->sc_bst, sc->sc_usb2phy_bsh,
-		USB_PHY_HOST_OHCICTRL);
-	ohcictrl |= HOST_OHCICTRL_SUSPLGCY;
-	bus_space_write_4(sc->sc_bst, sc->sc_usb2phy_bsh,
-		USB_PHY_HOST_OHCICTRL, ohcictrl);
 	DELAY(10000);
 }
 

Reply via email to