Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/samsung Revisit Exynos USB system implementing ...



details:   https://anonhg.NetBSD.org/src/rev/2088accf9ab0
branches:  trunk
changeset: 796505:2088accf9ab0
user:      reinoud <reinoud%NetBSD.org@localhost>
date:      Fri Jun 06 14:28:58 2014 +0000

description:
Revisit Exynos USB system implementing usb2phy support for Exynos4.

diffstat:

 sys/arch/arm/samsung/exynos4_loc.c |   17 ++-
 sys/arch/arm/samsung/exynos5_loc.c |   15 ++-
 sys/arch/arm/samsung/exynos_usb.c  |  172 +++++++++++++++++++++++++++++++++---
 sys/arch/arm/samsung/exynos_var.h  |   19 +++-
 4 files changed, 192 insertions(+), 31 deletions(-)

diffs (truncated from 376 to 300 lines):

diff -r c43b1dd60cd6 -r 2088accf9ab0 sys/arch/arm/samsung/exynos4_loc.c
--- a/sys/arch/arm/samsung/exynos4_loc.c        Fri Jun 06 14:25:19 2014 +0000
+++ b/sys/arch/arm/samsung/exynos4_loc.c        Fri Jun 06 14:28:58 2014 +0000
@@ -304,14 +304,21 @@
 
 /* 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_usbotg_offset     = EXYNOS4_USBOTG1_OFFSET,
+       .uloc_usb2phy_offset    = EXYNOS4_USBOTG1_OFFSET,
+
        .uloc_usbhost_irq       = IRQ_UHOST,
-       .uloc_usbotg_offset     = EXYNOS4_USBOTG1_OFFSET,
        .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 */
 };
 
diff -r c43b1dd60cd6 -r 2088accf9ab0 sys/arch/arm/samsung/exynos5_loc.c
--- a/sys/arch/arm/samsung/exynos5_loc.c        Fri Jun 06 14:25:19 2014 +0000
+++ b/sys/arch/arm/samsung/exynos5_loc.c        Fri Jun 06 14:28:58 2014 +0000
@@ -239,14 +239,21 @@
 
 /* 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_usbotg_offset     = EXYNOS5_USB2_DEVICE_LINK_OFFSET,
+       .uloc_usb2phy_offset    = EXYNOS5_USB2_DEVICE_LINK_OFFSET,
+
        .uloc_usbhost_irq       = IRQ_USB_HOST20,
-       .uloc_usbotg_offset     = EXYNOS5_USB2_DEVICE_LINK_OFFSET,
        .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,
 };
 
diff -r c43b1dd60cd6 -r 2088accf9ab0 sys/arch/arm/samsung/exynos_usb.c
--- a/sys/arch/arm/samsung/exynos_usb.c Fri Jun 06 14:25:19 2014 +0000
+++ b/sys/arch/arm/samsung/exynos_usb.c Fri Jun 06 14:28:58 2014 +0000
@@ -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 @@
 #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 @@
 
        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 @@
        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 @@
        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 @@
        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 @@
            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 @@
        };
        sc->sc_ehci_dev = config_found(self, &usb_ehci, NULL);
 #endif
+
+       /* TBD: USB3 xhci0 / xhci1 attachments */
 }
 
 
@@ -257,15 +293,11 @@
        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 @@
        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 @@
 #endif
 
 
+/*
+ * USB Phy init
+ */
+
 static void
-exynos_usb_init(struct exynos_usb_softc *sc)
+exynos_usb2_set_isolation(struct exynos_usb_softc *sc, bool on)
 {
-       /* TBD */
+       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 */



Home | Main Index | Thread Index | Old Index