Module Name: src
Committed By: jmcneill
Date: Tue Jul 3 16:09:04 UTC 2018
Modified Files:
src/sys/arch/arm/samsung: exynos_ehci.c exynos_ohci.c exynos_usbphy.c
files.exynos
Added Files:
src/sys/arch/arm/samsung: exynos_usbdrdphy.c
Removed Files:
src/sys/arch/arm/samsung: exynos_usb3.c
Log Message:
Add support for Samsung Exynos USB.
To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/samsung/exynos_ehci.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/samsung/exynos_ohci.c
cvs rdiff -u -r1.1 -r0 src/sys/arch/arm/samsung/exynos_usb3.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/samsung/exynos_usbdrdphy.c
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/samsung/exynos_usbphy.c
cvs rdiff -u -r1.27 -r1.28 src/sys/arch/arm/samsung/files.exynos
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_ehci.c
diff -u src/sys/arch/arm/samsung/exynos_ehci.c:1.3 src/sys/arch/arm/samsung/exynos_ehci.c:1.4
--- src/sys/arch/arm/samsung/exynos_ehci.c:1.3 Mon Apr 9 16:21:09 2018
+++ src/sys/arch/arm/samsung/exynos_ehci.c Tue Jul 3 16:09:04 2018
@@ -1,12 +1,9 @@
-/* $NetBSD: exynos_ehci.c,v 1.3 2018/04/09 16:21:09 jakllsch Exp $ */
+/* $NetBSD: exynos_ehci.c,v 1.4 2018/07/03 16:09:04 jmcneill Exp $ */
/*-
- * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * Copyright (c) 2015-2018 Jared McNeill <[email protected]>
* All rights reserved.
*
- * This code is derived from software contributed to The NetBSD Foundation
- * by Reinoud Zandijk.
- *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -16,107 +13,132 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
-#include "locators.h"
-#include "ohci.h"
-#include "ehci.h"
-
#include <sys/cdefs.h>
-
-__KERNEL_RCSID(1, "$NetBSD: exynos_ehci.c,v 1.3 2018/04/09 16:21:09 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: exynos_ehci.c,v 1.4 2018/07/03 16:09:04 jmcneill Exp $");
#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/intr.h>
#include <sys/bus.h>
#include <sys/device.h>
-#include <sys/proc.h>
-#include <sys/queue.h>
-#include <sys/kmem.h>
-#include <sys/gpio.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdivar.h>
#include <dev/usb/usb_mem.h>
-
#include <dev/usb/ehcireg.h>
#include <dev/usb/ehcivar.h>
-#include <arm/samsung/exynos_reg.h>
-#include <arm/samsung/exynos_var.h>
-
#include <dev/fdt/fdtvar.h>
static int exynos_ehci_match(device_t, cfdata_t, void *);
static void exynos_ehci_attach(device_t, device_t, void *);
-CFATTACH_DECL_NEW(exynos_ehci, sizeof(struct ehci_softc),
- exynos_ehci_match, exynos_ehci_attach, NULL, NULL);
-
+CFATTACH_DECL2_NEW(exynos_ehci, sizeof(struct ehci_softc),
+ exynos_ehci_match, exynos_ehci_attach, NULL,
+ ehci_activate, NULL, ehci_childdet);
static int
exynos_ehci_match(device_t parent, cfdata_t cf, void *aux)
{
- const char * const compatible[] = { "samsung,exynos5-ehci",
- NULL };
+ const char * const compatible[] = {
+ "samsung,exynos4210-ehci",
+ NULL
+ };
struct fdt_attach_args * const faa = aux;
+
return of_match_compatible(faa->faa_phandle, compatible);
}
-
static void
exynos_ehci_attach(device_t parent, device_t self, void *aux)
{
- struct ehci_softc *sc = device_private(self);
+ struct ehci_softc * const sc = device_private(self);
struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ struct fdtbus_phy *phy;
+ struct clk *clk;
+ char intrstr[128];
bus_addr_t addr;
bus_size_t size;
- int error;
+ int error, child;
+ void *ih;
- if (fdtbus_get_reg(faa->faa_phandle, 0, &addr, &size) != 0) {
+ if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
aprint_error(": couldn't get registers\n");
return;
}
+ /* Enable clocks */
+ clk = fdtbus_clock_get(phandle, "usbhost");
+ if (clk == NULL || clk_enable(clk) != 0) {
+ aprint_error(": couldn't enable clock\n");
+ return;
+ }
+
+ /* Enable phys for each port */
+ for (child = OF_child(phandle); child; child = OF_peer(child)) {
+ phy = fdtbus_phy_get_index(child, 0);
+ if (phy && fdtbus_phy_enable(phy, true) != 0)
+ aprint_error(": couldn't enable phy for %s\n",
+ fdtbus_get_string(child, "name"));
+ }
+
sc->sc_dev = self;
- sc->iot = faa->faa_bst;
- sc->sc_size = size;
- sc->sc_bus.ub_dmatag = faa->faa_dmat;
sc->sc_bus.ub_hcpriv = sc;
+ sc->sc_bus.ub_dmatag = faa->faa_dmat;
sc->sc_bus.ub_revision = USBREV_2_0;
- sc->sc_ncomp = 0;
-
- error = bus_space_map(sc->iot, addr, size, 0, &sc->ioh);
- if (error) {
- aprint_error(": couldn't map %#llx: %d",
- (uint64_t)addr, error);
+ if (of_hasprop(phandle, "has-transaction-translator"))
+ sc->sc_flags |= EHCIF_ETTF;
+ else
+ sc->sc_ncomp = 1;
+ sc->sc_size = size;
+ sc->iot = faa->faa_bst;
+ if (bus_space_map(sc->iot, addr, size, 0, &sc->ioh) != 0) {
+ aprint_error(": couldn't map registers\n");
return;
}
+ aprint_naive("\n");
+ aprint_normal(": Exynos EHCI\n");
+
+ /* Disable interrupts */
+ sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH);
+ EOWRITE4(sc, EHCI_USBINTR, 0);
+
+ if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
+ aprint_error_dev(self, "failed to decode interrupt\n");
+ return;
+ }
- aprint_naive(": EHCI USB controller\n");
- aprint_normal(": EHCI NOT IMPLEMENTED\n");
+ ih = fdtbus_intr_establish(phandle, 0, IPL_USB, FDT_INTR_MPSAFE,
+ ehci_intr, sc);
+ if (ih == NULL) {
+ aprint_error_dev(self, "couldn't establish interrupt on %s\n",
+ intrstr);
+ return;
+ }
+ aprint_normal_dev(self, "interrupting on %s\n", intrstr);
- /* attach */
error = ehci_init(sc);
if (error) {
aprint_error_dev(self, "init failed, error = %d\n", error);
- /* disable : TBD */
return;
}
+
sc->sc_child = config_found(self, &sc->sc_bus, usbctlprint);
}
Index: src/sys/arch/arm/samsung/exynos_ohci.c
diff -u src/sys/arch/arm/samsung/exynos_ohci.c:1.2 src/sys/arch/arm/samsung/exynos_ohci.c:1.3
--- src/sys/arch/arm/samsung/exynos_ohci.c:1.2 Sat Apr 23 10:15:28 2016
+++ src/sys/arch/arm/samsung/exynos_ohci.c Tue Jul 3 16:09:04 2018
@@ -1,12 +1,9 @@
-/* $NetBSD: exynos_ohci.c,v 1.2 2016/04/23 10:15:28 skrll Exp $ */
+/* $NetBSD: exynos_ohci.c,v 1.3 2018/07/03 16:09:04 jmcneill Exp $ */
/*-
- * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * Copyright (c) 2015-2018 Jared McNeill <[email protected]>
* All rights reserved.
*
- * This code is derived from software contributed to The NetBSD Foundation
- * by Reinoud Zandijk.
- *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -16,105 +13,128 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
-#include "locators.h"
-#include "ohci.h"
-#include "ehci.h"
-
#include <sys/cdefs.h>
-
-__KERNEL_RCSID(1, "$NetBSD: exynos_ohci.c,v 1.2 2016/04/23 10:15:28 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: exynos_ohci.c,v 1.3 2018/07/03 16:09:04 jmcneill Exp $");
#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/intr.h>
#include <sys/bus.h>
#include <sys/device.h>
-#include <sys/proc.h>
-#include <sys/queue.h>
-#include <sys/kmem.h>
-#include <sys/gpio.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdivar.h>
#include <dev/usb/usb_mem.h>
-
#include <dev/usb/ohcireg.h>
#include <dev/usb/ohcivar.h>
-#include <arm/samsung/exynos_reg.h>
-#include <arm/samsung/exynos_var.h>
-
#include <dev/fdt/fdtvar.h>
static int exynos_ohci_match(device_t, cfdata_t, void *);
static void exynos_ohci_attach(device_t, device_t, void *);
-CFATTACH_DECL_NEW(exynos_ohci, sizeof(struct ohci_softc),
- exynos_ohci_match, exynos_ohci_attach, NULL, NULL);
-
+CFATTACH_DECL2_NEW(exynos_ohci, sizeof(struct ohci_softc),
+ exynos_ohci_match, exynos_ohci_attach, NULL,
+ ohci_activate, NULL, ohci_childdet);
static int
exynos_ohci_match(device_t parent, cfdata_t cf, void *aux)
{
- const char * const compatible[] = { "samsung,exynos5-ohci",
- NULL };
+ const char * const compatible[] = {
+ "samsung,exynos4210-ohci",
+ NULL
+ };
struct fdt_attach_args * const faa = aux;
+
return of_match_compatible(faa->faa_phandle, compatible);
}
-
static void
exynos_ohci_attach(device_t parent, device_t self, void *aux)
{
- struct ohci_softc *sc = device_private(self);
+ struct ohci_softc * const sc = device_private(self);
struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ struct fdtbus_phy *phy;
+ struct clk *clk;
+ char intrstr[128];
bus_addr_t addr;
bus_size_t size;
- int error;
+ int error, child;
+ void *ih;
- if (fdtbus_get_reg(faa->faa_phandle, 0, &addr, &size) != 0) {
+ if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
aprint_error(": couldn't get registers\n");
return;
}
+ /* Enable clocks */
+ clk = fdtbus_clock_get(phandle, "usbhost");
+ if (clk == NULL || clk_enable(clk) != 0) {
+ aprint_error(": couldn't enable clock\n");
+ return;
+ }
+
+ /* Enable phys for each port */
+ for (child = OF_child(phandle); child; child = OF_peer(child)) {
+ phy = fdtbus_phy_get_index(child, 0);
+ if (phy && fdtbus_phy_enable(phy, true) != 0)
+ aprint_error(": couldn't enable phy for %s\n",
+ fdtbus_get_string(child, "name"));
+ }
+
sc->sc_dev = self;
- sc->iot = faa->faa_bst;
- sc->sc_size = size;
- sc->sc_bus.ub_dmatag = faa->faa_dmat;
sc->sc_bus.ub_hcpriv = sc;
+ sc->sc_bus.ub_dmatag = faa->faa_dmat;
+ sc->sc_flags = 0;
+ sc->sc_size = size;
+ sc->iot = faa->faa_bst;
+ if (bus_space_map(sc->iot, addr, size, 0, &sc->ioh) != 0) {
+ aprint_error(": couldn't map registers\n");
+ return;
+ }
- error = bus_space_map(sc->iot, addr, size, 0, &sc->ioh);
- if (error) {
- aprint_error(": couldn't map %#llx: %d",
- (uint64_t)addr, error);
+ aprint_naive("\n");
+ aprint_normal(": Exynos OHCI\n");
+
+ /* Disable interrupts */
+ bus_space_write_4(sc->iot, sc->ioh, OHCI_INTERRUPT_DISABLE,
+ OHCI_ALL_INTRS);
+
+ if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
+ aprint_error_dev(self, "failed to decode interrupt\n");
return;
}
- aprint_naive(": OHCI USB controller\n");
- aprint_normal(": OHCI NOT IMPLEMENTED\n");
+ ih = fdtbus_intr_establish(phandle, 0, IPL_USB, FDT_INTR_MPSAFE,
+ ohci_intr, sc);
+ if (ih == NULL) {
+ aprint_error_dev(self, "couldn't establish interrupt on %s\n",
+ intrstr);
+ return;
+ }
+ aprint_normal_dev(self, "interrupting on %s\n", intrstr);
- /* attach */
error = ohci_init(sc);
if (error) {
aprint_error_dev(self, "init failed, error = %d\n", error);
- /* disable : TBD */
return;
}
+
sc->sc_child = config_found(self, &sc->sc_bus, usbctlprint);
}
-
Index: src/sys/arch/arm/samsung/exynos_usbphy.c
diff -u src/sys/arch/arm/samsung/exynos_usbphy.c:1.1 src/sys/arch/arm/samsung/exynos_usbphy.c:1.2
--- src/sys/arch/arm/samsung/exynos_usbphy.c:1.1 Sun Dec 27 02:54:12 2015
+++ src/sys/arch/arm/samsung/exynos_usbphy.c Tue Jul 3 16:09:04 2018
@@ -1,12 +1,9 @@
-/* $NetBSD: exynos_usbphy.c,v 1.1 2015/12/27 02:54:12 marty Exp $ */
+/* $NetBSD: exynos_usbphy.c,v 1.2 2018/07/03 16:09:04 jmcneill Exp $ */
/*-
- * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * Copyright (c) 2018 Jared McNeill <[email protected]>
* All rights reserved.
*
- * This code is derived from software contributed to The NetBSD Foundation
- * by Reinoud Zandijk.
- *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -29,81 +26,268 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include "locators.h"
-#include "ohci.h"
-#include "ehci.h"
-
#include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: exynos_usbphy.c,v 1.1 2015/12/27 02:54:12 marty Exp $");
+__KERNEL_RCSID(0, "$NetBSD: exynos_usbphy.c,v 1.2 2018/07/03 16:09:04 jmcneill Exp $");
#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/intr.h>
#include <sys/bus.h>
#include <sys/device.h>
-#include <sys/proc.h>
-#include <sys/queue.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
#include <sys/kmem.h>
-#include <sys/gpio.h>
-#include <dev/usb/usb.h>
-#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdivar.h>
-#include <dev/usb/usb_mem.h>
+#include <dev/fdt/fdtvar.h>
+#include <dev/fdt/syscon.h>
#include <arm/samsung/exynos_reg.h>
-#include <arm/samsung/exynos_var.h>
+#include <arm/samsung/exynos5_reg.h>
-#include <dev/fdt/fdtvar.h>
+/*
+ * System Registers
+ */
+#define USB20PHY_CFG 0x230
+#define USB20PHY_CFG_HOST_LINK_EN __BIT(0)
+
+/*
+ * PMU Registers
+ */
+#define USBHOST_PHY_CTRL 0x708
+#define USBHOST_PHY_CTRL_EN __BIT(0)
+
+enum {
+ PHY_ID_DEVICE = 0,
+ PHY_ID_HOST,
+ PHY_ID_HSIC0,
+ PHY_ID_HSIC1,
+ NPHY_ID
+};
+
+static int exynos_usbphy_match(device_t, cfdata_t, void *);
+static void exynos_usbphy_attach(device_t, device_t, void *);
+
+static const struct of_compat_data compat_data[] = {
+ { "samsung,exynos5250-usb2-phy", 0 },
+ { NULL }
+};
+
+struct exynos_usbphy_softc;
+
+struct exynos_usbphy {
+ struct exynos_usbphy_softc *phy_sc;
+ u_int phy_index;
+};
struct exynos_usbphy_softc {
- device_t sc_dev;
- bus_space_tag_t sc_bst;
- bus_space_handle_t sc_bsh;
+ device_t sc_dev;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ int sc_phandle;
+
+ struct syscon *sc_sysreg;
+ struct syscon *sc_pmureg;
+
+ u_int sc_refcnt;
+
+ struct exynos_usbphy *sc_phy;
+ u_int sc_nphy;
+
+ struct fdtbus_gpio_pin *sc_gpio_id_det;
+ struct fdtbus_gpio_pin *sc_gpio_vbus_det;
};
-static int exynos_usbphy_match(device_t, cfdata_t, void *);
-static void exynos_usbphy_attach(device_t, device_t, void *);
+#define PHY_READ(sc, reg) \
+ bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
+#define PHY_WRITE(sc, reg, val) \
+ bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
CFATTACH_DECL_NEW(exynos_usbphy, sizeof(struct exynos_usbphy_softc),
- exynos_usbphy_match, exynos_usbphy_attach, NULL, NULL);
+ exynos_usbphy_match, exynos_usbphy_attach, NULL, NULL);
+
+static void *
+exynos_usbphy_acquire(device_t dev, const void *data, size_t len)
+{
+ struct exynos_usbphy_softc * const sc = device_private(dev);
+
+ if (len != 4)
+ return NULL;
+
+ const u_int index = be32dec(data);
+ if (index >= sc->sc_nphy)
+ return NULL;
+
+ return &sc->sc_phy[index];
+}
+
+static void
+exynos_usbphy_release(device_t dev, void *priv)
+{
+}
+
+static int
+exynos_usbphy_enable(device_t dev, void *priv, bool enable)
+{
+ struct exynos_usbphy * const phy = priv;
+ struct exynos_usbphy_softc * const sc = phy->phy_sc;
+ bool do_common;
+ uint32_t val;
+
+ if (enable) {
+ sc->sc_refcnt++;
+ } else {
+ KASSERT(sc->sc_refcnt > 0);
+ sc->sc_refcnt--;
+ }
+ do_common = sc->sc_refcnt == enable;
+
+ if (do_common) {
+ syscon_lock(sc->sc_sysreg);
+ val = syscon_read_4(sc->sc_sysreg, USB20PHY_CFG);
+ if (enable)
+ val |= USB20PHY_CFG_HOST_LINK_EN;
+ else
+ val &= ~USB20PHY_CFG_HOST_LINK_EN;
+ syscon_write_4(sc->sc_sysreg, USB20PHY_CFG, val);
+ syscon_unlock(sc->sc_sysreg);
+
+ syscon_lock(sc->sc_pmureg);
+ val = syscon_read_4(sc->sc_pmureg, USBHOST_PHY_CTRL);
+ if (enable)
+ val |= USBHOST_PHY_CTRL_EN;
+ else
+ val &= ~USBHOST_PHY_CTRL_EN;
+ syscon_write_4(sc->sc_pmureg, USBHOST_PHY_CTRL, val);
+ syscon_unlock(sc->sc_pmureg);
+
+ if (enable) {
+ val = PHY_READ(sc, USB_PHY_HOST_CTRL0);
+ val &= ~HOST_CTRL0_COMMONON_N;
+ val &= ~HOST_CTRL0_PHY_SWRST;
+ val &= ~HOST_CTRL0_PHY_SWRST_ALL;
+ val &= ~HOST_CTRL0_SIDDQ;
+ val &= ~HOST_CTRL0_FORCESUSPEND;
+ val &= ~HOST_CTRL0_FORCESLEEP;
+ val &= ~HOST_CTRL0_FSEL_MASK;
+ val |= __SHIFTIN(FSEL_CLKSEL_24M, HOST_CTRL0_FSEL_MASK);
+ val |= HOST_CTRL0_LINK_SWRST;
+ val |= HOST_CTRL0_UTMI_SWRST;
+ PHY_WRITE(sc, USB_PHY_HOST_CTRL0, val);
+
+ delay(10000);
+
+ val &= ~HOST_CTRL0_LINK_SWRST;
+ val &= ~HOST_CTRL0_UTMI_SWRST;
+ PHY_WRITE(sc, USB_PHY_HOST_CTRL0, val);
+
+ delay(10000);
+ }
+ }
+
+ switch (phy->phy_index) {
+ case PHY_ID_HSIC0:
+ case PHY_ID_HSIC1:
+ if (enable) {
+ const bus_size_t reg = phy->phy_index == PHY_ID_HSIC0 ?
+ USB_PHY_HSIC_CTRL1 : USB_PHY_HSIC_CTRL2;
+
+ val = HSIC_CTRL_PHY_SWRST;
+ val |= __SHIFTIN(HSIC_CTRL_REFCLKDIV_12, HSIC_CTRL_REFCLKDIV_MASK);
+ val |= __SHIFTIN(HSIC_CTRL_REFCLKSEL_DEFAULT, HSIC_CTRL_REFCLKSEL_MASK);
+ PHY_WRITE(sc, reg, val);
+
+ delay(10000);
+
+ val &= ~HSIC_CTRL_PHY_SWRST;
+ PHY_WRITE(sc, reg, val);
+
+ delay(10000);
+ }
+ break;
+ }
+
+ if (do_common) {
+ if (enable) {
+ val = PHY_READ(sc, USB_PHY_HOST_EHCICTRL);
+ val |= HOST_EHCICTRL_ENA_INCRXALIGN;
+ val |= HOST_EHCICTRL_ENA_INCR4;
+ val |= HOST_EHCICTRL_ENA_INCR8;
+ val |= HOST_EHCICTRL_ENA_INCR16;
+ PHY_WRITE(sc, USB_PHY_HOST_EHCICTRL, val);
+ }
+ }
+
+ return 0;
+}
+const struct fdtbus_phy_controller_func exynos_usbphy_funcs = {
+ .acquire = exynos_usbphy_acquire,
+ .release = exynos_usbphy_release,
+ .enable = exynos_usbphy_enable,
+};
static int
exynos_usbphy_match(device_t parent, cfdata_t cf, void *aux)
{
- const char * const compatible[] = { "samsung,exynos5-usb2phy",
- NULL };
struct fdt_attach_args * const faa = aux;
- return of_match_compatible(faa->faa_phandle, compatible);
-}
+ return of_match_compat_data(faa->faa_phandle, compat_data);
+}
static void
exynos_usbphy_attach(device_t parent, device_t self, void *aux)
{
- struct exynos_usbphy_softc *sc = device_private(self);
+ struct exynos_usbphy_softc * const sc = device_private(self);
struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ struct clk *clk;
bus_addr_t addr;
bus_size_t size;
- int error;
+ u_int n;
- if (fdtbus_get_reg(faa->faa_phandle, 0, &addr, &size) != 0) {
- aprint_error(": couldn't get registers\n");
+ if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get phy registers\n");
return;
}
sc->sc_dev = self;
+ sc->sc_phandle = phandle;
sc->sc_bst = faa->faa_bst;
+ if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
+ aprint_error(": couldn't map phy registers\n");
+ return;
+ }
+ sc->sc_nphy = NPHY_ID;
+ sc->sc_phy = kmem_alloc(sizeof(*sc->sc_phy) * sc->sc_nphy, KM_SLEEP);
+ for (n = 0; n < sc->sc_nphy; n++) {
+ sc->sc_phy[n].phy_sc = sc;
+ sc->sc_phy[n].phy_index = n;
+ }
- error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh);
- if (error) {
- aprint_error(": couldn't map %#llx: %d",
- (uint64_t)addr, error);
+ sc->sc_sysreg = fdtbus_syscon_acquire(phandle, "samsung,sysreg-phandle");
+ if (sc->sc_sysreg == NULL) {
+ aprint_error(": couldn't acquire sysreg syscon\n");
return;
}
+ sc->sc_pmureg = fdtbus_syscon_acquire(phandle, "samsung,pmureg-phandle");
+ if (sc->sc_pmureg == NULL) {
+ aprint_error(": couldn't acquire pmureg syscon\n");
+ return;
+ }
+
+ /* Enable clocks */
+ clk = fdtbus_clock_get(phandle, "phy");
+ if (clk == NULL || clk_enable(clk) != 0) {
+ aprint_error(": couldn't enable phy clock\n");
+ return;
+ }
+ clk = fdtbus_clock_get(phandle, "ref");
+ if (clk == NULL || clk_enable(clk) != 0) {
+ aprint_error(": couldn't enable ref clock\n");
+ return;
+ }
+
+ aprint_naive("\n");
+ aprint_normal(": USB2 PHY\n");
- aprint_normal(": USB 2 PHY NOT IMPLEMENTED\n");
+ fdtbus_register_phy_controller(self, phandle, &exynos_usbphy_funcs);
}
Index: src/sys/arch/arm/samsung/files.exynos
diff -u src/sys/arch/arm/samsung/files.exynos:1.27 src/sys/arch/arm/samsung/files.exynos:1.28
--- src/sys/arch/arm/samsung/files.exynos:1.27 Mon Jul 2 12:53:51 2018
+++ src/sys/arch/arm/samsung/files.exynos Tue Jul 3 16:09:04 2018
@@ -1,4 +1,4 @@
-# $NetBSD: files.exynos,v 1.27 2018/07/02 12:53:51 jmcneill Exp $
+# $NetBSD: files.exynos,v 1.28 2018/07/03 16:09:04 jmcneill Exp $
#
# Configuration info for Samsung Exynos SoC ARM Peripherals
#
@@ -79,25 +79,24 @@ attach exyopctl at fdt with exynos_pinc
file arch/arm/samsung/exynos_pinctrl.c exynos_pinctrl needs-flag
file arch/arm/samsung/exynos_gpio.c exynos_pinctrl needs-flag
-# USB2 phy
-device exyousbphy
-attach exyousbphy at fdt with exynos_usbphy
+# USB2 PHY
+device exusbphy
+attach exusbphy at fdt with exynos_usbphy
file arch/arm/samsung/exynos_usbphy.c exynos_usbphy
+# USB DRD PHY
+device exusbdrdphy
+attach exusbdrdphy at fdt with exynos_usbdrdphy
+file arch/arm/samsung/exynos_usbdrdphy.c exynos_usbdrdphy
+
# USB2 Host Controller (OHCI)
attach ohci at fdt with exynos_ohci
file arch/arm/samsung/exynos_ohci.c exynos_ohci
-#USB 2 Host Controller (EHCI)
+# USB 2 Host Controller (EHCI)
attach ehci at fdt with exynos_ehci
file arch/arm/samsung/exynos_ehci.c exynos_ehci
-# USB3 Host Controller (xHCI)
-device exyousb : fdtbus
-attach exyousb at fdt with exynos_usb
-attach xhci at fdt
-file arch/arm/samsung/exynos_usb3.c exynos_usb
-
# SD/MMC Host Controller
attach dwcmmc at fdt with exynos_dwcmmc
file arch/arm/samsung/exynos_dwcmmc.c exynos_dwcmmc
Added files:
Index: src/sys/arch/arm/samsung/exynos_usbdrdphy.c
diff -u /dev/null src/sys/arch/arm/samsung/exynos_usbdrdphy.c:1.1
--- /dev/null Tue Jul 3 16:09:04 2018
+++ src/sys/arch/arm/samsung/exynos_usbdrdphy.c Tue Jul 3 16:09:04 2018
@@ -0,0 +1,288 @@
+/* $NetBSD: exynos_usbdrdphy.c,v 1.1 2018/07/03 16:09:04 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2018 Jared McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+__KERNEL_RCSID(0, "$NetBSD: exynos_usbdrdphy.c,v 1.1 2018/07/03 16:09:04 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/kmem.h>
+
+#include <dev/fdt/fdtvar.h>
+#include <dev/fdt/syscon.h>
+
+/*
+ * PHY Registers
+ */
+#define PHY_LINK_SYSTEM 0x04
+#define PHY_LINK_SYSTEM_XHCI_VERCTL __BIT(27)
+#define PHY_LINK_SYSTEM_FLADJ __BITS(6,1)
+#define PHY_UTMI 0x08
+#define PHY_UTMI_OTGDISABLE __BIT(6)
+#define PHY_CLK_RST 0x10
+#define PHY_CLK_RST_SSC_REFCLKSEL __BITS(30,23)
+#define PHY_CLK_RST_SSC_EN __BIT(20)
+#define PHY_CLK_RST_REF_SSP_EN __BIT(19)
+#define PHY_CLK_RST_MPLL_MULT __BITS(17,11)
+#define PHY_CLK_RST_MPLL_MULT_24M 0x68
+#define PHY_CLK_RST_FSEL __BITS(10,5)
+#define PHY_CLK_RST_FSEL_24M 0x2a
+#define PHY_CLK_RST_RETENABLEN __BIT(4)
+#define PHY_CLK_RST_REFCLKSEL __BITS(3,2)
+#define PHY_CLK_RST_REFCLKSEL_EXT 3
+#define PHY_CLK_RST_PORTRESET __BIT(1)
+#define PHY_CLK_RST_COMMONONN __BIT(0)
+#define PHY_REG0 0x14
+#define PHY_PARAM0 0x1c
+#define PHY_PARAM0_REF_USE_PAD __BIT(31)
+#define PHY_PARAM0_REF_LOSLEVEL __BITS(30,26)
+#define PHY_PARAM1 0x20
+#define PHY_PARAM1_TXDEEMPH __BITS(4,0)
+#define PHY_TEST 0x28
+#define PHY_TEST_POWERDOWN_SSP __BIT(3)
+#define PHY_TEST_POWERDOWN_HSP __BIT(2)
+#define PHY_BATCHG 0x30
+#define PHY_BATCHG_UTMI_CLKSEL __BIT(2)
+#define PHY_RESUME 0x34
+
+/*
+ * PMU Registers
+ */
+#define USBDRD_PHY_CTRL(n) (0x704 + (n) * 4)
+#define USBDRD_PHY_CTRL_EN __BIT(0)
+
+static int exynos_usbdrdphy_match(device_t, cfdata_t, void *);
+static void exynos_usbdrdphy_attach(device_t, device_t, void *);
+
+enum {
+ PHY_ID_UTMI_PLUS = 0,
+ PHY_ID_PIPE3,
+ NPHY_ID
+};
+
+static const struct of_compat_data compat_data[] = {
+ { "samsung,exynos5420-usbdrd-phy", 0 },
+ { NULL }
+};
+
+struct exynos_usbdrdphy_softc;
+
+struct exynos_usbdrdphy {
+ struct exynos_usbdrdphy_softc *phy_sc;
+ u_int phy_index;
+};
+
+struct exynos_usbdrdphy_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ int sc_phandle;
+ struct syscon *sc_pmureg;
+
+ struct exynos_usbdrdphy *sc_phy;
+ u_int sc_nphy;
+
+ struct fdtbus_gpio_pin *sc_gpio_id_det;
+ struct fdtbus_gpio_pin *sc_gpio_vbus_det;
+};
+
+#define PHY_READ(sc, reg) \
+ bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
+#define PHY_WRITE(sc, reg, val) \
+ bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+
+CFATTACH_DECL_NEW(exynos_usbdrdphy, sizeof(struct exynos_usbdrdphy_softc),
+ exynos_usbdrdphy_match, exynos_usbdrdphy_attach, NULL, NULL);
+
+static void *
+exynos_usbdrdphy_acquire(device_t dev, const void *data, size_t len)
+{
+ struct exynos_usbdrdphy_softc * const sc = device_private(dev);
+
+ if (len != 4)
+ return NULL;
+
+ const u_int index = be32dec(data);
+ if (index >= sc->sc_nphy)
+ return NULL;
+
+ return &sc->sc_phy[index];
+}
+
+static void
+exynos_usbdrdphy_release(device_t dev, void *priv)
+{
+}
+
+static int
+exynos_usbdrdphy_enable(device_t dev, void *priv, bool enable)
+{
+ struct exynos_usbdrdphy * const phy = priv;
+ struct exynos_usbdrdphy_softc * const sc = phy->phy_sc;
+ uint32_t val;
+
+ syscon_lock(sc->sc_pmureg);
+ val = syscon_read_4(sc->sc_pmureg, USBDRD_PHY_CTRL(phy->phy_index));
+ if (enable)
+ val |= USBDRD_PHY_CTRL_EN;
+ else
+ val &= ~USBDRD_PHY_CTRL_EN;
+ syscon_write_4(sc->sc_pmureg, USBDRD_PHY_CTRL(phy->phy_index), val);
+ syscon_unlock(sc->sc_pmureg);
+
+ return 0;
+}
+
+const struct fdtbus_phy_controller_func exynos_usbdrdphy_funcs = {
+ .acquire = exynos_usbdrdphy_acquire,
+ .release = exynos_usbdrdphy_release,
+ .enable = exynos_usbdrdphy_enable,
+};
+
+static void
+exynos_usbdrdphy_init(struct exynos_usbdrdphy_softc *sc)
+{
+ uint32_t val;
+
+ PHY_WRITE(sc, PHY_REG0, 0);
+
+ val = PHY_READ(sc, PHY_PARAM0);
+ val &= ~PHY_PARAM0_REF_USE_PAD;
+ val &= ~PHY_PARAM0_REF_LOSLEVEL;
+ val |= __SHIFTIN(9, PHY_PARAM0_REF_LOSLEVEL);
+ PHY_WRITE(sc, PHY_PARAM0, val);
+
+ PHY_WRITE(sc, PHY_RESUME, 0);
+
+ val = PHY_READ(sc, PHY_LINK_SYSTEM);
+ val |= PHY_LINK_SYSTEM_XHCI_VERCTL;
+ val &= ~PHY_LINK_SYSTEM_FLADJ;
+ val |= __SHIFTIN(0x20, PHY_LINK_SYSTEM_FLADJ);
+ PHY_WRITE(sc, PHY_LINK_SYSTEM, val);
+
+ val = PHY_READ(sc, PHY_PARAM1);
+ val &= ~PHY_PARAM1_TXDEEMPH;
+ val |= __SHIFTIN(0x1c, PHY_PARAM1_TXDEEMPH);
+ PHY_WRITE(sc, PHY_PARAM1, val);
+
+ val = PHY_READ(sc, PHY_BATCHG);
+ val |= PHY_BATCHG_UTMI_CLKSEL;
+ PHY_WRITE(sc, PHY_BATCHG, val);
+
+ val = PHY_READ(sc, PHY_TEST);
+ val &= ~PHY_TEST_POWERDOWN_SSP;
+ val &= ~PHY_TEST_POWERDOWN_HSP;
+ PHY_WRITE(sc, PHY_TEST, val);
+
+ PHY_WRITE(sc, PHY_UTMI, PHY_UTMI_OTGDISABLE);
+
+ val = __SHIFTIN(PHY_CLK_RST_REFCLKSEL_EXT, PHY_CLK_RST_REFCLKSEL);
+ val |= __SHIFTIN(PHY_CLK_RST_FSEL_24M, PHY_CLK_RST_FSEL);
+ val |= __SHIFTIN(PHY_CLK_RST_MPLL_MULT_24M, PHY_CLK_RST_MPLL_MULT);
+ val |= __SHIFTIN(0x88, PHY_CLK_RST_SSC_REFCLKSEL);
+ val |= PHY_CLK_RST_PORTRESET;
+ val |= PHY_CLK_RST_RETENABLEN;
+ val |= PHY_CLK_RST_REF_SSP_EN;
+ val |= PHY_CLK_RST_SSC_EN;
+ val |= PHY_CLK_RST_COMMONONN;
+ PHY_WRITE(sc, PHY_CLK_RST, val);
+
+ delay(50000);
+
+ val &= ~PHY_CLK_RST_PORTRESET;
+ PHY_WRITE(sc, PHY_CLK_RST, val);
+}
+
+static int
+exynos_usbdrdphy_match(device_t parent, cfdata_t cf, void *aux)
+{
+ struct fdt_attach_args * const faa = aux;
+
+ return of_match_compat_data(faa->faa_phandle, compat_data);
+}
+
+static void
+exynos_usbdrdphy_attach(device_t parent, device_t self, void *aux)
+{
+ struct exynos_usbdrdphy_softc * const sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ struct clk *clk;
+ bus_addr_t addr;
+ bus_size_t size;
+ u_int n;
+
+ if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get phy registers\n");
+ return;
+ }
+
+ sc->sc_dev = self;
+ sc->sc_phandle = phandle;
+ sc->sc_bst = faa->faa_bst;
+ if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
+ aprint_error(": couldn't map phy registers\n");
+ return;
+ }
+
+ sc->sc_nphy = NPHY_ID;
+ sc->sc_phy = kmem_alloc(sizeof(*sc->sc_phy) * sc->sc_nphy, KM_SLEEP);
+ for (n = 0; n < sc->sc_nphy; n++) {
+ sc->sc_phy[n].phy_sc = sc;
+ sc->sc_phy[n].phy_index = n;
+ }
+
+ sc->sc_pmureg = fdtbus_syscon_acquire(phandle, "samsung,pmu-syscon");
+ if (sc->sc_pmureg == NULL) {
+ aprint_error(": couldn't acquire pmureg syscon\n");
+ return;
+ }
+
+ /* Enable clocks */
+ clk = fdtbus_clock_get(phandle, "phy");
+ if (clk == NULL || clk_enable(clk) != 0) {
+ aprint_error(": couldn't enable phy clock\n");
+ return;
+ }
+ clk = fdtbus_clock_get(phandle, "ref");
+ if (clk == NULL || clk_enable(clk) != 0) {
+ aprint_error(": couldn't enable ref clock\n");
+ return;
+ }
+
+ aprint_naive("\n");
+ aprint_normal(": USB DRD PHY\n");
+
+ exynos_usbdrdphy_init(sc);
+
+ fdtbus_register_phy_controller(self, phandle, &exynos_usbdrdphy_funcs);
+}