Module Name:    src
Committed By:   reinoud
Date:           Fri Jun  6 14:28:58 UTC 2014

Modified Files:
        src/sys/arch/arm/samsung: exynos4_loc.c exynos5_loc.c exynos_usb.c
            exynos_var.h

Log Message:
Revisit Exynos USB system implementing usb2phy support for Exynos4.


To generate a diff of this commit:
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/arm/samsung/exynos4_loc.c
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/samsung/exynos5_loc.c
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/samsung/exynos_usb.c
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/arm/samsung/exynos_var.h

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/exynos4_loc.c
diff -u src/sys/arch/arm/samsung/exynos4_loc.c:1.7 src/sys/arch/arm/samsung/exynos4_loc.c:1.8
--- src/sys/arch/arm/samsung/exynos4_loc.c:1.7	Wed May 21 13:02:46 2014
+++ src/sys/arch/arm/samsung/exynos4_loc.c	Fri Jun  6 14:28:58 2014
@@ -304,14 +304,21 @@ const struct exyo_locinfo exynos4_i2c_lo
 
 /* usb locators */
 const struct exyo_usb_locinfo exynos4_usb_locinfo = {
+	.uloc_pmuregs_offset	= EXYNOS4_PMU_OFFSET,
+	.uloc_sysregs_offset	= 0,
+
 	.uloc_ehci_offset	= EXYNOS4_USBHOST0_OFFSET,
 	.uloc_ohci_offset	= EXYNOS4_USBHOST1_OFFSET,
-	.uloc_usbhost_irq	= IRQ_UHOST,
 	.uloc_usbotg_offset	= EXYNOS4_USBOTG1_OFFSET,
+	.uloc_usb2phy_offset	= EXYNOS4_USBOTG1_OFFSET,
+
+	.uloc_usbhost_irq	= IRQ_UHOST,
 	.uloc_usbotg_irq	= IRQ_HSOTG,
-	.uloc_usb3_ctrl		= 0,		/* no usbctl */
-	.uloc_usb3_linkoffset	= 0,		/* no usb3   */
-	.uloc_usb3_slots	= 0,		/* no usb3   */
-	.uloc_usb3_irq		= 0,		/* no usb3   */
+	.uloc_usb3_irq		= 0,		/* no usb3 */
+
+	.uloc_usb3_xhci0_offset	= 0,		/* no usb3 */
+	.uloc_usb3_xhci1_offset	= 0,		/* no usb3 */
+	.uloc_usb3_phy0_offset	= 0,		/* no usb3 */
+	.uloc_usb3_phy1_offset	= 0,		/* no usb3 */
 };
 

Index: src/sys/arch/arm/samsung/exynos5_loc.c
diff -u src/sys/arch/arm/samsung/exynos5_loc.c:1.5 src/sys/arch/arm/samsung/exynos5_loc.c:1.6
--- src/sys/arch/arm/samsung/exynos5_loc.c:1.5	Wed May 21 13:02:46 2014
+++ src/sys/arch/arm/samsung/exynos5_loc.c	Fri Jun  6 14:28:58 2014
@@ -239,14 +239,21 @@ const struct exyo_locinfo exynos5_i2c_lo
 
 /* usb locators */
 const struct exyo_usb_locinfo exynos5_usb_locinfo = {
+	.uloc_pmuregs_offset	= EXYNOS5_ALIVE_OFFSET,
+	.uloc_sysregs_offset	= EXYNOS5_SYSREG_OFFSET,
+
 	.uloc_ehci_offset	= EXYNOS5_USB2_HOST_EHCI_OFFSET,
 	.uloc_ohci_offset	= EXYNOS5_USB2_HOST_OHCI_OFFSET,
-	.uloc_usbhost_irq	= IRQ_USB_HOST20,
 	.uloc_usbotg_offset	= EXYNOS5_USB2_DEVICE_LINK_OFFSET,
+	.uloc_usb2phy_offset	= EXYNOS5_USB2_DEVICE_LINK_OFFSET,
+
+	.uloc_usbhost_irq	= IRQ_USB_HOST20,
 	.uloc_usbotg_irq	= IRQ_USBOTG,
-	.uloc_usb3_ctrl		= EXYNOS5_USB3_DEVICE_CTRL_OFFSET,
-	.uloc_usb3_linkoffset	= EXYNOS5_USB3_DEVICE_LINK_OFFSET00,
-	.uloc_usb3_slots	= 16,
 	.uloc_usb3_irq		= IRQ_USB_DRD30,
+
+	.uloc_usb3_xhci0_offset	= EXYNOS5_USB3_XHCI0_OFFSET,
+	.uloc_usb3_xhci1_offset	= EXYNOS5_USB3_XHCI1_OFFSET,
+	.uloc_usb3_phy0_offset	= EXYNOS5_USB3_PHY0_OFFSET,
+	.uloc_usb3_phy1_offset	= EXYNOS5_USB3_PHY1_OFFSET,
 };
 

Index: src/sys/arch/arm/samsung/exynos_usb.c
diff -u src/sys/arch/arm/samsung/exynos_usb.c:1.4 src/sys/arch/arm/samsung/exynos_usb.c:1.5
--- src/sys/arch/arm/samsung/exynos_usb.c:1.4	Wed May 21 13:02:46 2014
+++ src/sys/arch/arm/samsung/exynos_usb.c	Fri Jun  6 14:28:58 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: exynos_usb.c,v 1.4 2014/05/21 13:02:46 reinoud Exp $	*/
+/*	$NetBSD: exynos_usb.c,v 1.5 2014/06/06 14:28:58 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.4 2014/05/21 13:02:46 reinoud Exp $");
+__KERNEL_RCSID(1, "$NetBSD: exynos_usb.c,v 1.5 2014/06/06 14:28:58 reinoud Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -46,6 +46,7 @@ __KERNEL_RCSID(1, "$NetBSD: exynos_usb.c
 #include <sys/proc.h>
 #include <sys/queue.h>
 #include <sys/kmem.h>
+#include <sys/gpio.h>
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
@@ -77,6 +78,10 @@ struct exynos_usb_softc {
 
 	bus_space_handle_t sc_ehci_bsh;
 	bus_space_handle_t sc_ohci_bsh;
+	bus_space_handle_t sc_usb2phy_bsh;
+
+	bus_space_handle_t sc_pmuregs_bsh;
+	bus_space_handle_t sc_sysregs_bsh;
 
 	device_t	 sc_ohci_dev;
 	device_t	 sc_ehci_dev;
@@ -88,8 +93,15 @@ struct exynos_usb_attach_args {
 	const char *name;
 };
 
+static struct exynos_gpio_pinset uhost_pwr_pinset = {
+	.pinset_group = "ETC6",
+	.pinset_func  = 0,
+	.pinset_mask  = __BIT(5) | __BIT(6),
+};
+
+
 static int exynos_usb_intr(void *arg);
-static void exynos_usb_init(struct exynos_usb_softc *sc);
+static void exynos_usb_phy_init(struct exynos_usb_softc *sc);
 
 
 static int	exynos_usb_match(device_t, cfdata_t, void *);
@@ -116,6 +128,8 @@ exynos_usb_attach(device_t parent, devic
 	struct exynos_usb_softc * const sc = &exynos_usb_sc;
 	struct exyo_attach_args *exyoaa = (struct exyo_attach_args *) aux;
 	struct exyo_locators *loc = &exyoaa->exyo_loc;
+	struct exynos_gpio_pindata XuhostOVERCUR;
+	struct exynos_gpio_pindata XuhostPWREN;
 
 	/* no locators expected */
 	KASSERT(loc->loc_offset == 0);
@@ -145,10 +159,32 @@ exynos_usb_attach(device_t parent, devic
 	bus_space_subregion(sc->sc_bst, exyoaa->exyo_core_bsh,
 		sc->sc_locinfo->uloc_ohci_offset, EXYNOS_BLOCK_SIZE,
 		&sc->sc_ohci_bsh);
+	bus_space_subregion(sc->sc_bst, exyoaa->exyo_core_bsh,
+		sc->sc_locinfo->uloc_usb2phy_offset, EXYNOS_BLOCK_SIZE,
+		&sc->sc_usb2phy_bsh);
+
+	bus_space_subregion(sc->sc_bst, exyoaa->exyo_core_bsh,
+		sc->sc_locinfo->uloc_pmuregs_offset, EXYNOS_BLOCK_SIZE,
+		&sc->sc_pmuregs_bsh);
+
+	if (sc->sc_locinfo->uloc_sysregs_offset)
+		bus_space_subregion(sc->sc_bst, exyoaa->exyo_core_bsh,
+			sc->sc_locinfo->uloc_sysregs_offset, EXYNOS_BLOCK_SIZE,
+			&sc->sc_sysregs_bsh);
 
 	aprint_naive("\n");
 	aprint_normal("\n");
 
+	/* power up USB subsystem XXX PWREN not working yet */
+	exynos_gpio_pinset_acquire(&uhost_pwr_pinset);
+	exynos_gpio_pinset_to_pindata(&uhost_pwr_pinset, 5, &XuhostPWREN);
+	exynos_gpio_pinset_to_pindata(&uhost_pwr_pinset, 6, &XuhostOVERCUR);
+
+	/* enable power and set Xuhost OVERCUR to inactive by pulling it up */
+	exynos_gpio_pindata_ctl(&XuhostPWREN, GPIO_PIN_PULLUP);
+	exynos_gpio_pindata_ctl(&XuhostOVERCUR, GPIO_PIN_PULLUP);
+	DELAY(80000);
+
 	/*
 	 * Disable interrupts
 	 */
@@ -163,10 +199,8 @@ exynos_usb_attach(device_t parent, devic
 	    caplength + EHCI_USBINTR, 0);
 #endif
 
-	/*
-	 * Init USB subsystem
-	 */
-	exynos_usb_init(sc);
+	/* init USB phys */
+	exynos_usb_phy_init(sc);
 
 	/* claim shared interrupt for OHCI/EHCI */
 	sc->sc_intrh = intr_establish(sc->sc_locinfo->uloc_usbhost_irq,
@@ -195,6 +229,8 @@ exynos_usb_attach(device_t parent, devic
 	};
 	sc->sc_ehci_dev = config_found(self, &usb_ehci, NULL);
 #endif
+
+	/* TBD: USB3 xhci0 / xhci1 attachments */
 }
 
 
@@ -257,15 +293,11 @@ exynos_ohci_attach(device_t parent, devi
 	sc->sc_bus.dmatag = usbsc->sc_dmat;
 	sc->sc_bus.hci_private = sc;
 
-//sc->sc_bus.use_polling=1;
-
 	strlcpy(sc->sc_vendor, "exynos", sizeof(sc->sc_vendor));
 
 	aprint_naive(": OHCI USB controller\n");
 	aprint_normal(": OHCI USB controller\n");
 
-	/* enable things ? extra settings? TBD */
-
 	/* attach */
 	r = ohci_init(sc);
 	if (r != USBD_NORMAL_COMPLETION) {
@@ -318,15 +350,11 @@ exynos_ehci_attach(device_t parent, devi
 	if (usbsc->sc_ohci_dev != NULL)
 		sc->sc_comps[sc->sc_ncomp++] = usbsc->sc_ohci_dev;
 
-//sc->sc_bus.use_polling=1;
-
 	strlcpy(sc->sc_vendor, "exynos", sizeof(sc->sc_vendor));
 
 	aprint_naive(": EHCI USB controller\n");
 	aprint_normal(": EHCI USB controller\n");
 
-	/* enable things ? extra settings? TBD */
-
 	/* attach */
 	r = ehci_init(sc);
 	if (r != USBD_NORMAL_COMPLETION) {
@@ -341,9 +369,119 @@ exynos_ehci_attach(device_t parent, devi
 #endif
 
 
+/*
+ * USB Phy init
+ */
+
+static void
+exynos_usb2_set_isolation(struct exynos_usb_softc *sc, bool on)
+{
+	int val;
+
+	val = on ? PMU_PHY_DISABLE : PMU_PHY_ENABLE;
+	if (IS_EXYNOS4X12_P()) {
+		bus_space_write_4(sc->sc_bst, sc->sc_pmuregs_bsh,
+			EXYNOS_PMU_USB_PHY_CTRL, val);
+		bus_space_write_4(sc->sc_bst, sc->sc_pmuregs_bsh,
+			EXYNOS_PMU_USB_HSIC_1_PHY_CTRL, val);
+		bus_space_write_4(sc->sc_bst, sc->sc_pmuregs_bsh,
+			EXYNOS_PMU_USB_HSIC_2_PHY_CTRL, val);
+	} else {
+		bus_space_write_4(sc->sc_bst, sc->sc_pmuregs_bsh,
+			EXYNOS_PMU_USBDEV_PHY_CTRL, val);
+		bus_space_write_4(sc->sc_bst, sc->sc_pmuregs_bsh,
+			EXYNOS_PMU_USBHOST_PHY_CTRL, val);
+	}
+}
+
+
+#ifdef EXYNOS4
+static void
+exynos4_usb2phy_enable(struct exynos_usb_softc *sc)
+{
+	uint32_t phypwr, rstcon, clkreg;
+
+	/* disable phy isolation */
+	exynos_usb2_set_isolation(sc, false);
+
+	/* write clock value */
+	clkreg = 5;	/* 24 Mhz */
+	bus_space_write_4(sc->sc_bst, sc->sc_usb2phy_bsh,
+		USB_PHYCLK, clkreg);
+
+	/* set device and host to normal */
+	phypwr = bus_space_read_4(sc->sc_bst, sc->sc_usb2phy_bsh,
+		USB_PHYPWR);
+
+	/* set to normal of device */
+	phypwr &= ~PHYPWR_NORMAL_MASK_PHY0;
+	bus_space_write_4(sc->sc_bst, sc->sc_usb2phy_bsh,
+		USB_PHYPWR, phypwr);
+
+	if (IS_EXYNOS4X12_P()) {
+		/* set to normal of host */
+		phypwr = bus_space_read_4(sc->sc_bst, sc->sc_usb2phy_bsh,
+			USB_PHYPWR);
+		phypwr &= ~(PHYPWR_NORMAL_MASK_HSIC0 |
+			    PHYPWR_NORMAL_MASK_HSIC1 |
+			    PHYPWR_NORMAL_MASK_PHY1);
+		bus_space_write_4(sc->sc_bst, sc->sc_usb2phy_bsh,
+			USB_PHYPWR, phypwr);
+	}
+
+	/* reset both phy and link of device */
+	rstcon = bus_space_read_4(sc->sc_bst, sc->sc_usb2phy_bsh,
+		USB_RSTCON);
+	rstcon |= RSTCON_DEVPHY_SWRST;
+	bus_space_write_4(sc->sc_bst, sc->sc_usb2phy_bsh,
+		USB_RSTCON, rstcon);
+	DELAY(10000);
+	rstcon &= ~RSTCON_DEVPHY_SWRST;
+	bus_space_write_4(sc->sc_bst, sc->sc_usb2phy_bsh,
+		USB_RSTCON, rstcon);
+
+	if (IS_EXYNOS4X12_P()) {
+		/* reset both phy and link of host */
+		rstcon = bus_space_read_4(sc->sc_bst, sc->sc_usb2phy_bsh,
+			USB_RSTCON);
+		rstcon |= RSTCON_HOSTPHY_SWRST | RSTCON_HOSTPHYLINK_SWRST;
+		bus_space_write_4(sc->sc_bst, sc->sc_usb2phy_bsh,
+			USB_RSTCON, rstcon);
+		DELAY(10000);
+		rstcon &= ~(RSTCON_HOSTPHY_SWRST | RSTCON_HOSTPHYLINK_SWRST);
+		bus_space_write_4(sc->sc_bst, sc->sc_usb2phy_bsh,
+			USB_RSTCON, rstcon);
+	}
+
+	/* wait for everything to be initialized */
+	DELAY(80000);
+}
+#endif
+
+
+#ifdef EXYNOS5
+static void
+exynos5_usb2phy_enable(struct exynos_usb_softc *sc)
+{
+	/* disable phy isolation */
+	exynos_usb2_set_isolation(sc, false);
+
+	aprint_error_dev(sc->sc_self, "%s not implemented\n", __func__);
+}
+#endif
+
+
 static void
-exynos_usb_init(struct exynos_usb_softc *sc)
+exynos_usb_phy_init(struct exynos_usb_softc *sc)
 {
-	/* TBD */
+#ifdef EXYNOS4
+	if (IS_EXYNOS4_P())
+		exynos4_usb2phy_enable(sc);
+#endif
+#ifdef EXYNOS5
+	if (IS_EXYNOS5_P())
+		exynos5_usb2phy_enable(sc);
+	/* TBD: USB3 phy init */
+#endif
 }
 

Index: src/sys/arch/arm/samsung/exynos_var.h
diff -u src/sys/arch/arm/samsung/exynos_var.h:1.10 src/sys/arch/arm/samsung/exynos_var.h:1.11
--- src/sys/arch/arm/samsung/exynos_var.h:1.10	Wed May 21 13:02:46 2014
+++ src/sys/arch/arm/samsung/exynos_var.h	Fri Jun  6 14:28:58 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: exynos_var.h,v 1.10 2014/05/21 13:02:46 reinoud Exp $ */
+/* $NetBSD: exynos_var.h,v 1.11 2014/06/06 14:28:58 reinoud Exp $ */
 /*-
  * Copyright (c) 2013, 2014 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -57,6 +57,8 @@ extern uint32_t exynos_pop_id;
 #define IS_EXYNOS4412_R0_P() \
 			((EXYNOS_PRODUCT_ID(exynos_soc_id) == 0xe4412) && \
 			 (EXYNOS_PRODUCT_REV(exynos_soc_id) == 0))
+#define IS_EXYNOS4X12_P()	((EXYNOS_PRODUCT_ID(exynos_soc_id) & 0xff0ff) \
+			== 0xe4012)
 
 #define IS_EXYNOS4_P()	(EXYNOS_PRODUCT_FAMILY(exynos_soc_id) == EXYNOS4_PRODUCT_FAMILY)
 
@@ -80,15 +82,22 @@ struct exyo_locators {
 
 
 struct exyo_usb_locinfo {
+	bus_size_t	uloc_pmuregs_offset;
+	bus_size_t	uloc_sysregs_offset;
+
 	bus_size_t	uloc_ehci_offset;
 	bus_size_t	uloc_ohci_offset;
-	int		uloc_usbhost_irq;
 	bus_size_t	uloc_usbotg_offset;
+	bus_size_t	uloc_usb2phy_offset;
+
+	int		uloc_usbhost_irq;
 	int		uloc_usbotg_irq;
-	bus_size_t	uloc_usb3_ctrl;
-	bus_size_t	uloc_usb3_linkoffset;
-	int		uloc_usb3_slots;
 	int		uloc_usb3_irq;
+
+	bus_size_t	uloc_usb3_xhci0_offset;
+	bus_size_t	uloc_usb3_xhci1_offset;
+	bus_size_t	uloc_usb3_phy0_offset;
+	bus_size_t	uloc_usb3_phy1_offset;
 };
 
 

Reply via email to