Module Name: src
Committed By: jmcneill
Date: Tue May 28 21:56:04 UTC 2019
Modified Files:
src/sys/arch/arm/sunxi: files.sunxi
Added Files:
src/sys/arch/arm/sunxi: sun9i_a80_usbclk.c sun9i_a80_usbphy.c
Log Message:
Add A80 USB support.
To generate a diff of this commit:
cvs rdiff -u -r1.63 -r1.64 src/sys/arch/arm/sunxi/files.sunxi
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/sunxi/sun9i_a80_usbclk.c \
src/sys/arch/arm/sunxi/sun9i_a80_usbphy.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/sunxi/files.sunxi
diff -u src/sys/arch/arm/sunxi/files.sunxi:1.63 src/sys/arch/arm/sunxi/files.sunxi:1.64
--- src/sys/arch/arm/sunxi/files.sunxi:1.63 Mon May 27 21:12:54 2019
+++ src/sys/arch/arm/sunxi/files.sunxi Tue May 28 21:56:04 2019
@@ -1,4 +1,4 @@
-# $NetBSD: files.sunxi,v 1.63 2019/05/27 21:12:54 jmcneill Exp $
+# $NetBSD: files.sunxi,v 1.64 2019/05/28 21:56:04 jmcneill Exp $
#
# Configuration info for Allwinner sunxi family SoCs
#
@@ -97,6 +97,11 @@ device sun9immcclk
attach sun9immcclk at fdt with sunxi_a80_mmcclk
file arch/arm/sunxi/sun9i_a80_mmcclk.c sunxi_a80_mmcclk
+# USB HCI clocks (A80)
+device sun9iusbclk
+attach sun9iusbclk at fdt with sunxi_a80_usbclk
+file arch/arm/sunxi/sun9i_a80_usbclk.c sunxi_a80_usbclk
+
# CPUS clock driver (A80)
device sun9icpusclk
attach sun9icpusclk at fdt with sunxi_a80_cpusclk
@@ -150,6 +155,10 @@ device sunxiusb3phy
attach sunxiusb3phy at fdt with sunxi_usb3phy
file arch/arm/sunxi/sunxi_usb3phy.c sunxi_usb3phy
+device sun9iusbphy
+attach sun9iusbphy at fdt with sunxi_a80_usbphy
+file arch/arm/sunxi/sun9i_a80_usbphy.c sunxi_a80_usbphy
+
# EHCI
attach ehci at fdt with ehci_fdt
file dev/fdt/ehci_fdt.c ehci_fdt
Added files:
Index: src/sys/arch/arm/sunxi/sun9i_a80_usbclk.c
diff -u /dev/null src/sys/arch/arm/sunxi/sun9i_a80_usbclk.c:1.1
--- /dev/null Tue May 28 21:56:04 2019
+++ src/sys/arch/arm/sunxi/sun9i_a80_usbclk.c Tue May 28 21:56:03 2019
@@ -0,0 +1,147 @@
+/* $NetBSD: sun9i_a80_usbclk.c,v 1.1 2019/05/28 21:56:03 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2017 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 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 <sys/cdefs.h>
+
+__KERNEL_RCSID(1, "$NetBSD: sun9i_a80_usbclk.c,v 1.1 2019/05/28 21:56:03 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <arm/sunxi/sunxi_ccu.h>
+
+enum {
+ CLK_BUS_HCI0 = 0,
+ CLK_USB_OHCI0,
+ CLK_BUS_HCI1,
+ CLK_BUS_HCI2,
+ CLK_USB_OHCI2,
+ CLK_USB0_PHY,
+ CLK_USB1_HSIC,
+ CLK_USB1_PHY,
+ CLK_USB2_HSIC,
+ CLK_USB2_PHY,
+ CLK_USB_HSIC
+};
+
+enum {
+ RST_USB0_HCI = 0,
+ RST_USB1_HCI,
+ RST_USB2_HCI,
+ RST_USB0_PHY,
+ RST_USB1_HSIC,
+ RST_USB1_PHY,
+ RST_USB2_HSIC,
+ RST_USB2_PHY
+};
+
+#define HCI_SCR 0x00
+#define HCI_PCR 0x04
+
+static int sun9i_a80_usbclk_match(device_t, cfdata_t, void *);
+static void sun9i_a80_usbclk_attach(device_t, device_t, void *);
+
+static const char * compatible[] = {
+ "allwinner,sun9i-a80-usb-clks",
+ NULL
+};
+
+CFATTACH_DECL_NEW(sunxi_a80_usbclk, sizeof(struct sunxi_ccu_softc),
+ sun9i_a80_usbclk_match, sun9i_a80_usbclk_attach, NULL, NULL);
+
+static struct sunxi_ccu_reset sun9i_a80_usbclk_resets[] = {
+ SUNXI_CCU_RESET(RST_USB0_HCI, HCI_SCR, 17),
+ SUNXI_CCU_RESET(RST_USB1_HCI, HCI_SCR, 18),
+ SUNXI_CCU_RESET(RST_USB2_HCI, HCI_SCR, 19),
+ SUNXI_CCU_RESET(RST_USB0_PHY, HCI_PCR, 17),
+
+ SUNXI_CCU_RESET(RST_USB1_HSIC, HCI_PCR, 18),
+ SUNXI_CCU_RESET(RST_USB1_PHY, HCI_PCR, 19),
+ SUNXI_CCU_RESET(RST_USB2_HSIC, HCI_PCR, 20),
+ SUNXI_CCU_RESET(RST_USB2_PHY, HCI_PCR, 21),
+};
+
+static struct sunxi_ccu_clk sun9i_a80_usbclk_clks[] = {
+ SUNXI_CCU_GATE(CLK_BUS_HCI0, "bus-hci0", "bus", HCI_SCR, 1),
+ SUNXI_CCU_GATE(CLK_USB_OHCI0, "usb-ohci0", "hosc", HCI_SCR, 2),
+ SUNXI_CCU_GATE(CLK_BUS_HCI1, "bus-hci1", "bus", HCI_SCR, 3),
+ SUNXI_CCU_GATE(CLK_BUS_HCI2, "bus-hci2", "bus", HCI_SCR, 5),
+ SUNXI_CCU_GATE(CLK_USB_OHCI2, "usb-ohci2", "hosc", HCI_SCR, 6),
+
+ SUNXI_CCU_GATE(CLK_USB0_PHY, "usb0-phy", "hosc", HCI_PCR, 1),
+ SUNXI_CCU_GATE(CLK_USB1_HSIC, "usb1-hsic", "hosc", HCI_PCR, 2),
+ SUNXI_CCU_GATE(CLK_USB1_PHY, "usb1-phy", "hosc", HCI_PCR, 3),
+ SUNXI_CCU_GATE(CLK_USB2_HSIC, "usb2-hsic", "hosc", HCI_PCR, 4),
+ SUNXI_CCU_GATE(CLK_USB2_PHY, "usb2-phy", "hosc", HCI_PCR, 5),
+ SUNXI_CCU_GATE(CLK_USB_HSIC, "usb-hsic", "hosc", HCI_PCR, 10),
+};
+
+static int
+sun9i_a80_usbclk_match(device_t parent, cfdata_t cf, void *aux)
+{
+ struct fdt_attach_args * const faa = aux;
+
+ return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+sun9i_a80_usbclk_attach(device_t parent, device_t self, void *aux)
+{
+ struct sunxi_ccu_softc * const sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ struct clk *clk;
+
+ sc->sc_dev = self;
+ sc->sc_phandle = faa->faa_phandle;
+ sc->sc_bst = faa->faa_bst;
+
+ sc->sc_resets = sun9i_a80_usbclk_resets;
+ sc->sc_nresets = __arraycount(sun9i_a80_usbclk_resets);
+
+ sc->sc_clks = sun9i_a80_usbclk_clks;
+ sc->sc_nclks = __arraycount(sun9i_a80_usbclk_clks);
+
+ clk = fdtbus_clock_get(phandle, "bus");
+ if (clk == NULL || clk_enable(clk) != 0) {
+ aprint_error(": couldn't enable clock\n");
+ return;
+ }
+
+ if (sunxi_ccu_attach(sc) != 0)
+ return;
+
+ aprint_naive("\n");
+ aprint_normal(": A80 USB HCI clocks\n");
+
+ sunxi_ccu_print(sc);
+}
Index: src/sys/arch/arm/sunxi/sun9i_a80_usbphy.c
diff -u /dev/null src/sys/arch/arm/sunxi/sun9i_a80_usbphy.c:1.1
--- /dev/null Tue May 28 21:56:04 2019
+++ src/sys/arch/arm/sunxi/sun9i_a80_usbphy.c Tue May 28 21:56:04 2019
@@ -0,0 +1,214 @@
+/* $NetBSD: sun9i_a80_usbphy.c,v 1.1 2019/05/28 21:56:04 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2019 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: sun9i_a80_usbphy.c,v 1.1 2019/05/28 21:56: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/time.h>
+
+#include <dev/fdt/fdtvar.h>
+
+/* PMU registers */
+#define PMU_CFG 0x00
+#define EHCI_HS_FORCE __BIT(20)
+#define HSIC_CONNECT_DET __BIT(17)
+#define HSIC_CONNECT_INT __BIT(16)
+#define AHB_INCR16 __BIT(11)
+#define AHB_INCR8 __BIT(10)
+#define AHB_INCR4 __BIT(9)
+#define AHB_INCRX_ALIGN __BIT(8)
+#define HSIC __BIT(1)
+#define ULPI_BYPASS __BIT(0)
+
+static int sun9i_usbphy_match(device_t, cfdata_t, void *);
+static void sun9i_usbphy_attach(device_t, device_t, void *);
+
+static const char * compatible[] = {
+ "allwinner,sun9i-a80-usb-phy",
+ NULL
+};
+
+struct sun9i_usbphy_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+
+ struct clk *sc_clk_phy;
+ struct clk *sc_clk_hsic;
+ struct fdtbus_reset *sc_rst;
+
+ struct fdtbus_regulator *sc_supply;
+};
+
+#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(sunxi_a80_usbphy, sizeof(struct sun9i_usbphy_softc),
+ sun9i_usbphy_match, sun9i_usbphy_attach, NULL, NULL);
+
+static void *
+sun9i_usbphy_acquire(device_t dev, const void *data, size_t len)
+{
+ struct sun9i_usbphy_softc * const sc = device_private(dev);
+
+ return sc;
+}
+
+static void
+sun9i_usbphy_release(device_t dev, void *priv)
+{
+}
+
+static int
+sun9i_usbphy_enable(device_t dev, void *priv, bool enable)
+{
+ struct sun9i_usbphy_softc * const sc = device_private(dev);
+ uint32_t passby_mask;
+ uint32_t val;
+ int error;
+
+ passby_mask = ULPI_BYPASS|AHB_INCR16|AHB_INCR8|AHB_INCR4|AHB_INCRX_ALIGN;
+ if (sc->sc_clk_hsic != NULL)
+ passby_mask |= HSIC|EHCI_HS_FORCE|HSIC_CONNECT_DET|HSIC_CONNECT_INT;
+
+ /* Enable/disable passby */
+ if (enable) {
+ error = clk_enable(sc->sc_clk_phy);
+ if (error != 0)
+ return error;
+
+ if (sc->sc_clk_hsic != NULL) {
+ error = clk_enable(sc->sc_clk_hsic);
+ if (error != 0)
+ return error;
+ }
+
+ error = fdtbus_reset_deassert(sc->sc_rst);
+ if (error != 0)
+ return error;
+
+ val = PHY_READ(sc, PMU_CFG);
+ val |= passby_mask;
+ PHY_WRITE(sc, PMU_CFG, val);
+ } else {
+ val = PHY_READ(sc, PMU_CFG);
+ val &= ~passby_mask;
+ PHY_WRITE(sc, PMU_CFG, val);
+
+ error = fdtbus_reset_assert(sc->sc_rst);
+ if (error != 0)
+ return error;
+
+ if (sc->sc_clk_hsic != NULL) {
+ error = clk_disable(sc->sc_clk_hsic);
+ if (error != 0)
+ return error;
+ }
+
+ error = clk_disable(sc->sc_clk_phy);
+ if (error != 0)
+ return error;
+ }
+
+ return 0;
+}
+
+const struct fdtbus_phy_controller_func sun9i_usbphy_funcs = {
+ .acquire = sun9i_usbphy_acquire,
+ .release = sun9i_usbphy_release,
+ .enable = sun9i_usbphy_enable,
+};
+
+static int
+sun9i_usbphy_match(device_t parent, cfdata_t cf, void *aux)
+{
+ struct fdt_attach_args * const faa = aux;
+
+ return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+sun9i_usbphy_attach(device_t parent, device_t self, void *aux)
+{
+ struct sun9i_usbphy_softc * const sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ const char *phy_type;
+ bus_addr_t addr;
+ bus_size_t size;
+
+ sc->sc_dev = self;
+ sc->sc_bst = faa->faa_bst;
+
+ if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get registers\n");
+ return;
+ }
+ if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
+ aprint_error(": couldn't map registers\n");
+ return;
+ }
+
+ phy_type = fdtbus_get_string(phandle, "phy_type");
+ if (phy_type && strcmp(phy_type, "hsic") == 0) {
+ sc->sc_clk_phy = fdtbus_clock_get(phandle, "hsic_480M");
+ sc->sc_clk_hsic = fdtbus_clock_get(phandle, "hsic_12M");
+ sc->sc_rst = fdtbus_reset_get(phandle, "hsic");
+
+ if (sc->sc_clk_phy == NULL || sc->sc_clk_hsic == NULL || sc->sc_rst == NULL) {
+ aprint_error(": couldn't get hsic resources\n");
+ return;
+ }
+ } else {
+ sc->sc_clk_phy = fdtbus_clock_get(phandle, "phy");
+ sc->sc_rst = fdtbus_reset_get(phandle, "phy");
+ if (sc->sc_clk_phy == NULL || sc->sc_rst == NULL) {
+ aprint_error(": couldn't get phy resources\n");
+ return;
+ }
+ }
+
+ aprint_naive("\n");
+ aprint_normal(": USB PHY\n");
+
+ sc->sc_supply = fdtbus_regulator_acquire(phandle, "phy-supply");
+ if (sc->sc_supply != NULL) {
+ if (fdtbus_regulator_enable(sc->sc_supply) != 0)
+ aprint_error_dev(self, "WARNING: couldn't enable power supply\n");
+ }
+
+ fdtbus_register_phy_controller(self, phandle, &sun9i_usbphy_funcs);
+}