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; };