Module Name: src
Committed By: hkenken
Date: Wed Jul 24 13:12:34 UTC 2019
Added Files:
src/sys/arch/arm/imx: imx6_gpcreg.h
src/sys/arch/arm/imx/fdt: files.imx6 if_enet_imx.c imx6_ahcisata.c
imx6_clk.c imx6_com.c imx6_gpc.c imx6_gpio.c imx6_iomux.c
imx6_pcie.c imx6_platform.c imx6_platform.h imx6_sdhc.c imx6_usb.c
imx6_usbphy.c
src/sys/arch/evbarm/conf: IMX files.imx mk.imx std.imx
Log Message:
Add support for device tree.
+ CCM (clk)
+ COM (uart)
+ GPIO
+ IOMUX (pin control)
+ PCIe
+ SDHC
+ USB Host
+ USB phy
To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/imx/imx6_gpcreg.h
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/imx/fdt/files.imx6 \
src/sys/arch/arm/imx/fdt/if_enet_imx.c \
src/sys/arch/arm/imx/fdt/imx6_ahcisata.c \
src/sys/arch/arm/imx/fdt/imx6_clk.c src/sys/arch/arm/imx/fdt/imx6_com.c \
src/sys/arch/arm/imx/fdt/imx6_gpc.c src/sys/arch/arm/imx/fdt/imx6_gpio.c \
src/sys/arch/arm/imx/fdt/imx6_iomux.c \
src/sys/arch/arm/imx/fdt/imx6_pcie.c \
src/sys/arch/arm/imx/fdt/imx6_platform.c \
src/sys/arch/arm/imx/fdt/imx6_platform.h \
src/sys/arch/arm/imx/fdt/imx6_sdhc.c src/sys/arch/arm/imx/fdt/imx6_usb.c \
src/sys/arch/arm/imx/fdt/imx6_usbphy.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/evbarm/conf/IMX \
src/sys/arch/evbarm/conf/files.imx src/sys/arch/evbarm/conf/mk.imx \
src/sys/arch/evbarm/conf/std.imx
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Added files:
Index: src/sys/arch/arm/imx/imx6_gpcreg.h
diff -u /dev/null src/sys/arch/arm/imx/imx6_gpcreg.h:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/arm/imx/imx6_gpcreg.h Wed Jul 24 13:12:33 2019
@@ -0,0 +1,41 @@
+/* $NetBSD: imx6_gpcreg.h,v 1.1 2019/07/24 13:12:33 hkenken Exp $ */
+/*-
+ * Copyright (c) 2019 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * 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.
+ */
+#ifndef _ARM_IMX_IMX6_GPCREG_H_
+#define _ARM_IMX_IMX6_GPCREG_H_
+
+#define GPC_CNTR 0x00000000
+#define GPC_PGR 0x00000004
+#define GPC_IMR1 0x00000008
+#define GPC_IMR2 0x0000000C
+#define GPC_IMR3 0x00000010
+#define GPC_IMR4 0x00000014
+#define GPC_ISR1 0x00000018
+#define GPC_ISR2 0x0000001C
+#define GPC_ISR3 0x00000020
+#define GPC_ISR4 0x00000024
+
+#endif /* _ARM_IMX_IMX6_GPCREG_H_ */
Index: src/sys/arch/arm/imx/fdt/files.imx6
diff -u /dev/null src/sys/arch/arm/imx/fdt/files.imx6:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/arm/imx/fdt/files.imx6 Wed Jul 24 13:12:33 2019
@@ -0,0 +1,80 @@
+# $NetBSD: files.imx6,v 1.1 2019/07/24 13:12:33 hkenken Exp $
+#
+# Configuration info for the Freescale i.MX6
+#
+
+file arch/arm/arm32/arm32_boot.c
+file arch/arm/arm32/arm32_kvminit.c
+file arch/arm/arm32/arm32_reboot.c
+file arch/arm/arm32/irq_dispatch.S
+file arch/arm/arm32/armv7_generic_space.c
+file arch/arm/arm/arm_generic_dma.c
+file arch/arm/arm/bus_space_a4x.S
+
+file arch/arm/imx/fdt/imx6_platform.c soc_imx
+
+# SOC parameters
+defflag opt_soc.h SOC_IMX
+defflag opt_soc.h SOC_IMX6QDL: SOC_IMX
+
+# Clock
+device imxccm : clk
+attach imxccm at fdt
+file arch/arm/imx/imx6_ccm.c imxccm
+file arch/arm/imx/fdt/imx6_clk.c imxccm
+
+# GPC
+device imxgpc
+attach imxgpc at fdt
+file arch/arm/imx/fdt/imx6_gpc.c imxgpc
+
+# IOMUX
+device imxiomux
+attach imxiomux at fdt
+file arch/arm/imx/fdt/imx6_iomux.c imxiomux
+
+# GPIO controller
+device imxgpio: gpiobus
+attach imxgpio at fdt
+file arch/arm/imx/imxgpio.c imxgpio
+file arch/arm/imx/fdt/imx6_gpio.c imxgpio
+
+# UART
+device imxuart { } : bus_space_generic
+attach imxuart at fdt with imx6_com
+file arch/arm/imx/imxuart.c imxuart needs-flag
+file arch/arm/imx/fdt/imx6_com.c imx6_com needs-flag
+defflag opt_imxuart.h IMXUARTCONSOLE
+
+# FEC
+device enet: ether, ifnet, arp, mii, bus_dma_generic
+attach enet at fdt
+file arch/arm/imx/if_enet.c enet
+file arch/arm/imx/fdt/if_enet_imx.c enet
+
+# SATA
+attach ahcisata at fdt with imx6_ahcisata
+file arch/arm/imx/fdt/imx6_ahcisata.c imx6_ahcisata
+
+# USB Controller
+device imxusbc { [unit=-1], [irq=-1] } : bus_dma_generic
+attach imxusbc at fdt with imxusbc_fdt
+file arch/arm/imx/fdt/imx6_usb.c imxusbc_fdt
+
+attach ehci at imxusbc with imxehci
+file arch/arm/imx/imxusb.c imxehci
+
+# USB PHY
+device imxusbphy
+attach imxusbphy at fdt
+file arch/arm/imx/fdt/imx6_usbphy.c imxusbphy
+
+# SDMMC
+attach sdhc at fdt with imx6_sdhc
+file arch/arm/imx/fdt/imx6_sdhc.c imx6_sdhc
+
+# PCIe
+device imxpcie: pcibus
+attach imxpcie at fdt with imxpcie_fdt
+file arch/arm/imx/imxpcie.c imxpcie
+file arch/arm/imx/fdt/imx6_pcie.c imxpcie_fdt
Index: src/sys/arch/arm/imx/fdt/if_enet_imx.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/if_enet_imx.c:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/arm/imx/fdt/if_enet_imx.c Wed Jul 24 13:12:33 2019
@@ -0,0 +1,173 @@
+/* $NetBSD: if_enet_imx.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $ */
+/*-
+ * Copyright (c) 2019 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * 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(0, "$NetBSD: if_enet_imx.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $");
+
+#include "opt_fdt.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+
+#include <arm/imx/imx6var.h>
+#include <arm/imx/imx6_reg.h>
+#include <arm/imx/if_enetreg.h>
+#include <arm/imx/if_enetvar.h>
+
+#include <dev/fdt/fdtvar.h>
+
+static const char * const compatible[] = {
+ "fsl,imx6q-fec",
+ NULL
+};
+
+static int enet_init_clocks(struct enet_softc *);
+static void enet_phy_reset(const int);
+
+int
+enet_match(device_t parent, cfdata_t cf, void *aux)
+{
+ struct fdt_attach_args * const faa = aux;
+
+ return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+void
+enet_attach(device_t parent, device_t self, void *aux)
+{
+ struct enet_softc *sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ bus_space_tag_t bst = faa->faa_bst;
+ bus_space_handle_t bsh;
+ bus_addr_t addr;
+ bus_size_t size;
+ int error;
+
+ if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get enet registers\n");
+ return;
+ }
+
+ error = bus_space_map(bst, addr, size, 0, &bsh);
+ if (error) {
+ aprint_error(": couldn't map enet registers: %d\n", error);
+ return;
+ }
+
+ sc->sc_clk_enet = fdtbus_clock_get(phandle, "ahb");
+ if (sc->sc_clk_enet == NULL) {
+ aprint_error(": couldn't get clock ahb\n");
+ goto failure;
+ }
+ sc->sc_clk_enet_ref= fdtbus_clock_get(phandle, "ptp");
+ if (sc->sc_clk_enet_ref == NULL) {
+ aprint_error(": couldn't get clock ptp\n");
+ goto failure;
+ }
+
+ aprint_naive("\n");
+ aprint_normal(": Gigabit Ethernet Controller\n");
+
+ enet_phy_reset(phandle);
+
+ sc->sc_dev = self;
+ sc->sc_iot = bst;
+ sc->sc_ioh = bsh;
+ sc->sc_dmat = faa->faa_dmat;
+
+ sc->sc_imxtype = 6; /* i.MX6 */
+ sc->sc_rgmii = 1;
+
+ char intrstr[128];
+ if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
+ aprint_error_dev(self, "failed to decode interrupt\n");
+ goto failure;
+ }
+ sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_NET, 0,
+ enet_intr, sc);
+ if (sc->sc_ih == NULL) {
+ aprint_error_dev(self, "failed to establish interrupt on %s\n",
+ intrstr);
+ goto failure;
+ }
+ aprint_normal_dev(self, "interrupting on %s\n", intrstr);
+
+ enet_init_clocks(sc);
+ sc->sc_pllclock = clk_get_rate(sc->sc_clk_enet);
+
+ if (enet_attach_common(self) != 0)
+ goto failure;
+
+ return;
+
+failure:
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, size);
+ return;
+}
+
+static int
+enet_init_clocks(struct enet_softc *sc)
+{
+ int error;
+
+ error = clk_enable(sc->sc_clk_enet);
+ if (error) {
+ aprint_error_dev(sc->sc_dev, "couldn't enable enet: %d\n", error);
+ return error;
+ }
+ error = clk_enable(sc->sc_clk_enet_ref);
+ if (error) {
+ aprint_error_dev(sc->sc_dev, "couldn't enable enet_ref: %d\n", error);
+ return error;
+ }
+
+ return 0;
+}
+
+static void
+enet_phy_reset(const int phandle)
+{
+ struct fdtbus_gpio_pin *reset;
+ int error;
+
+ reset = fdtbus_gpio_acquire(phandle, "phy-reset-gpios", GPIO_PIN_OUTPUT);
+ if (reset == NULL)
+ return;
+
+ u_int msec;
+ error = of_getprop_uint32(phandle, "phy-reset-duration", &msec);
+ if (error)
+ msec = 1;
+
+ /* Reset */
+ fdtbus_gpio_write(reset, 1);
+ delay(msec * 1000);
+ fdtbus_gpio_write(reset, 0);
+
+ fdtbus_gpio_release(reset);
+}
Index: src/sys/arch/arm/imx/fdt/imx6_ahcisata.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx6_ahcisata.c:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/arm/imx/fdt/imx6_ahcisata.c Wed Jul 24 13:12:33 2019
@@ -0,0 +1,480 @@
+/* $NetBSD: imx6_ahcisata.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $ */
+/*-
+ * Copyright (c) 2019 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * 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(0, "$NetBSD: imx6_ahcisata.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+
+#include <dev/ata/atavar.h>
+#include <dev/ic/ahcisatavar.h>
+
+#include <arm/imx/imx6_reg.h>
+#include <arm/imx/imx6var.h>
+#include <arm/imx/imx6_ahcisatareg.h>
+#include <arm/imx/imx6_iomuxreg.h>
+#include <arm/imx/imx6_ccmreg.h>
+#include <arm/imx/imx6_ccmvar.h>
+
+#include <dev/fdt/fdtvar.h>
+
+static int imx6_ahcisata_match(device_t, cfdata_t, void *);
+static void imx6_ahcisata_attach(device_t, device_t, void *);
+
+struct imx6_ahcisata_softc {
+ struct ahci_softc sc;
+
+ device_t sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ bus_space_handle_t sc_gpr_ioh;
+ void *sc_ih;
+
+ u_int sc_tx_level;
+ u_int sc_tx_boost;
+ u_int sc_tx_atten;
+ u_int sc_rx_eq;
+ u_int sc_ss;
+
+ struct clk *sc_clk_sata;
+ struct clk *sc_clk_sata_ref;
+ struct clk *sc_clk_ahb;
+};
+
+static int imx6_ahcisata_init(struct imx6_ahcisata_softc *);
+static int imx6_ahcisata_phy_ctrl(struct imx6_ahcisata_softc *, uint32_t, int);
+static int imx6_ahcisata_phy_addr(struct imx6_ahcisata_softc *, uint32_t);
+static int imx6_ahcisata_phy_write(struct imx6_ahcisata_softc *, uint32_t, uint16_t);
+static int imx6_ahcisata_phy_read(struct imx6_ahcisata_softc *, uint32_t);
+static int imx6_ahcisata_init_clocks(struct imx6_ahcisata_softc *);
+
+CFATTACH_DECL_NEW(imx6_ahcisata, sizeof(struct imx6_ahcisata_softc),
+ imx6_ahcisata_match, imx6_ahcisata_attach, NULL, NULL);
+
+static int
+imx6_ahcisata_match(device_t parent, cfdata_t cf, void *aux)
+{
+ const char * const compatible[] = { "fsl,imx6q-ahci", NULL };
+ struct fdt_attach_args * const faa = aux;
+
+ return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+imx6_ahcisata_attach(device_t parent, device_t self, void *aux)
+{
+ struct imx6_ahcisata_softc * const sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ bus_addr_t ahci_addr;
+ bus_size_t ahci_size;
+ bus_addr_t addr;
+ bus_size_t size;
+ char intrstr[128];
+ int error;
+
+ if (fdtbus_get_reg(phandle, 0, &ahci_addr, &ahci_size) != 0) {
+ aprint_error(": couldn't get ahci registers\n");
+ return;
+ }
+
+ if (of_getprop_uint32(phandle, "fsl,transmit-level-mV", &sc->sc_tx_level) != 0)
+ sc->sc_tx_level = 1104;
+ if (of_getprop_uint32(phandle, "fsl,transmit-boost-mdB", &sc->sc_tx_boost) != 0)
+ sc->sc_tx_boost = 3330;
+ if (of_getprop_uint32(phandle, "fsl,transmit-atten-16ths", &sc->sc_tx_atten) != 0)
+ sc->sc_tx_atten = 9;
+ if (of_getprop_uint32(phandle, "fsl,receive-eq-mdB", &sc->sc_rx_eq) != 0)
+ sc->sc_rx_eq = 3000;
+ if (of_getprop_bool(phandle, "fsl,no-spread-spectrum") == false)
+ sc->sc_ss = 1;
+
+ sc->sc_clk_sata = fdtbus_clock_get(phandle, "sata");
+ if (sc->sc_clk_sata == NULL) {
+ aprint_error(": couldn't get clock sata\n");
+ return;
+ }
+ sc->sc_clk_sata_ref = fdtbus_clock_get(phandle, "sata_ref");
+ if (sc->sc_clk_sata_ref == NULL) {
+ aprint_error(": couldn't get clock sata_ref\n");
+ return;
+ }
+ sc->sc_clk_ahb = fdtbus_clock_get(phandle, "ahb");
+ if (sc->sc_clk_ahb == NULL) {
+ aprint_error(": couldn't get clock ahb\n");
+ return;
+ }
+
+ aprint_naive("\n");
+ aprint_normal(": AHCI Controller\n");
+
+ aprint_debug_dev(self, "tx level %d [mV]\n", sc->sc_tx_level);
+ aprint_debug_dev(self, "tx boost %d [mdB]\n", sc->sc_tx_boost);
+ aprint_debug_dev(self, "tx atten %d [16ths]\n", sc->sc_tx_atten);
+ aprint_debug_dev(self, "rx eq %d [mdB]\n", sc->sc_rx_eq);
+ aprint_debug_dev(self, "ss %d\n", sc->sc_ss);
+
+ sc->sc_dev = self;
+
+ sc->sc.sc_atac.atac_dev = self;
+ sc->sc.sc_ahci_ports = 1;
+ sc->sc.sc_dmat = faa->faa_dmat;
+ sc->sc.sc_ahcit = faa->faa_bst;
+ sc->sc.sc_ahcis = ahci_size;
+ error = bus_space_map(sc->sc.sc_ahcit, ahci_addr, ahci_size, 0,
+ &sc->sc.sc_ahcih);
+ if (error) {
+ aprint_error(": couldn't map ahci registers: %d\n", error);
+ return;
+ }
+
+ sc->sc_iot = sc->sc.sc_ahcit;
+ sc->sc_ioh = sc->sc.sc_ahcih;
+
+ const int gpr_phandle = OF_finddevice("/soc/aips-bus/iomuxc-gpr");
+ fdtbus_get_reg(gpr_phandle, 0, &addr, &size);
+ if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_gpr_ioh)) {
+ aprint_error_dev(self, "Cannot map registers\n");
+ return;
+ }
+
+ if (imx6_ahcisata_init_clocks(sc) != 0) {
+ aprint_error_dev(self, "couldn't init clocks\n");
+ return;
+ }
+
+ if (imx6_ahcisata_init(sc) != 0) {
+ aprint_error_dev(self, "couldn't init ahci\n");
+ return;
+ }
+
+ if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
+ aprint_error_dev(self, "failed to decode interrupt\n");
+ return;
+ }
+
+ sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_BIO, 0,
+ ahci_intr, &sc->sc);
+ if (sc->sc_ih == NULL) {
+ aprint_error_dev(self, "failed to establish interrupt on %s\n",
+ intrstr);
+ return;
+ }
+ aprint_normal_dev(self, "interrupting on %s\n", intrstr);
+
+ ahci_attach(&sc->sc);
+}
+
+static int
+imx6_ahcisata_phy_ctrl(struct imx6_ahcisata_softc *sc, uint32_t bitmask, int on)
+{
+ uint32_t v;
+ int timeout;
+
+ v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR);
+ if (on)
+ v |= bitmask;
+ else
+ v &= ~bitmask;
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR, v);
+
+ for (timeout = 5000; timeout > 0; --timeout) {
+ v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYSR);
+ if (!!(v & SATA_P0PHYSR_CR_ACK) == !!on)
+ break;
+ delay(100);
+ }
+
+ if (timeout > 0)
+ return 0;
+
+ return -1;
+}
+
+static int
+imx6_ahcisata_phy_addr(struct imx6_ahcisata_softc *sc, uint32_t addr)
+{
+ delay(100);
+
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR, addr);
+
+ if (imx6_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_ADDR, 1) != 0)
+ return -1;
+ if (imx6_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_ADDR, 0) != 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+imx6_ahcisata_phy_write(struct imx6_ahcisata_softc *sc, uint32_t addr,
+ uint16_t data)
+{
+ if (imx6_ahcisata_phy_addr(sc, addr) != 0)
+ return -1;
+
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR, data);
+
+ if (imx6_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_DATA, 1) != 0)
+ return -1;
+ if (imx6_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_DATA, 0) != 0)
+ return -1;
+
+ if ((addr == SATA_PHY_CLOCK_RESET) && data) {
+ /* we can't check ACK after RESET */
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR,
+ data | SATA_P0PHYCR_CR_WRITE);
+ return 0;
+ }
+
+ if (imx6_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_WRITE, 1) != 0)
+ return -1;
+ if (imx6_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_WRITE, 0) != 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+imx6_ahcisata_phy_read(struct imx6_ahcisata_softc *sc, uint32_t addr)
+{
+ uint32_t v;
+
+ if (imx6_ahcisata_phy_addr(sc, addr) != 0)
+ return -1;
+
+ if (imx6_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_READ, 1) != 0)
+ return -1;
+
+ v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYSR);
+
+ if (imx6_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_READ, 0) != 0)
+ return -1;
+
+ return SATA_P0PHYSR_CR_DATA_OUT(v);
+}
+
+const static int tx_level[] = {
+ 937,
+ 947,
+ 957,
+ 966,
+ 976,
+ 986,
+ 996,
+ 1005,
+ 1015,
+ 1025,
+ 1035,
+ 1045,
+ 1054,
+ 1064,
+ 1074,
+ 1084,
+ 1094,
+ 1104,
+ 1113,
+ 1123,
+ 1133,
+ 1143,
+ 1152,
+ 1162,
+ 1172,
+ 1182,
+ 1191,
+ 1201,
+ 1211,
+ 1221,
+ 1230,
+ 1240,
+};
+
+const static int tx_boots[] = {
+ 0,
+ 370,
+ 740,
+ 1110,
+ 1480,
+ 1850,
+ 2220,
+ 2590,
+ 2960,
+ 3330,
+ 3700,
+ 4070,
+ 4440,
+ 4810,
+ 5280,
+ 5750,
+};
+
+const static int tx_atten[] = {
+ 16,
+ 14,
+ 12,
+ 10,
+ 9,
+ 8,
+};
+
+const static int rx_eq[] = {
+ 500,
+ 1000,
+ 1500,
+ 2000,
+ 2500,
+ 3000,
+ 3500,
+ 4000,
+};
+
+static int
+imx6_ahcisata_search_regval(const int *values, int count, int val)
+{
+ for (int i = 0; i < count; i++)
+ if (values[i] == val)
+ return i;
+
+ return -1;
+}
+
+static int
+imx6_ahcisata_init(struct imx6_ahcisata_softc *sc)
+{
+ uint32_t v;
+ int timeout;
+ int pllstat;
+
+ v = bus_space_read_4(sc->sc_iot, sc->sc_gpr_ioh, IOMUX_GPR13);
+ /* clear */
+ v &= ~(IOMUX_GPR13_SATA_PHY_8 |
+ IOMUX_GPR13_SATA_PHY_7 |
+ IOMUX_GPR13_SATA_PHY_6 |
+ IOMUX_GPR13_SATA_SPEED |
+ IOMUX_GPR13_SATA_PHY_5 |
+ IOMUX_GPR13_SATA_PHY_4 |
+ IOMUX_GPR13_SATA_PHY_3 |
+ IOMUX_GPR13_SATA_PHY_2 |
+ IOMUX_GPR13_SATA_PHY_1 |
+ IOMUX_GPR13_SATA_PHY_0);
+ /* setting */
+ struct {
+ const int *array;
+ int count;
+ int val;
+ int def_val;
+ int mask;
+ } gpr13_sata_phy_settings[] = {
+ { tx_level, __arraycount(tx_level), sc->sc_tx_level,
+ 0x11, IOMUX_GPR13_SATA_PHY_2 },
+ { tx_boots, __arraycount(tx_boots), sc->sc_tx_boost,
+ 0x09, IOMUX_GPR13_SATA_PHY_3 },
+ { tx_atten, __arraycount(tx_atten), sc->sc_tx_atten,
+ 0x04, IOMUX_GPR13_SATA_PHY_4 },
+ { rx_eq, __arraycount(rx_eq), sc->sc_rx_eq,
+ 0x05, IOMUX_GPR13_SATA_PHY_8 }
+ };
+ for (int i = 0; i < __arraycount(gpr13_sata_phy_settings); i++) {
+ int val;
+ val = imx6_ahcisata_search_regval(
+ gpr13_sata_phy_settings[i].array,
+ gpr13_sata_phy_settings[i].count,
+ gpr13_sata_phy_settings[i].val);
+ if (val == -1)
+ val = gpr13_sata_phy_settings[i].def_val;
+ v |= __SHIFTIN(val, gpr13_sata_phy_settings[i].mask);
+ }
+ v |= __SHIFTIN(sc->sc_ss, IOMUX_GPR13_SATA_PHY_5);
+ v |= __SHIFTIN(0x12, IOMUX_GPR13_SATA_PHY_7); /* Rx SATA2m */
+ v |= __SHIFTIN(3, IOMUX_GPR13_SATA_PHY_6); /* Rx DPLL mode */
+ v |= __SHIFTIN(1, IOMUX_GPR13_SATA_SPEED); /* 3.0GHz */
+ v |= __SHIFTIN(1, IOMUX_GPR13_SATA_PHY_1); /* PLL clock enable */
+ bus_space_write_4(sc->sc_iot, sc->sc_gpr_ioh, IOMUX_GPR13, v);
+
+ /* phy reset */
+ if (imx6_ahcisata_phy_write(sc, SATA_PHY_CLOCK_RESET,
+ SATA_PHY_CLOCK_RESET_RST) < 0) {
+ aprint_error_dev(sc->sc_dev, "cannot reset PHY\n");
+ return -1;
+ }
+
+ for (timeout = 50; timeout > 0; --timeout) {
+ delay(100);
+ pllstat = imx6_ahcisata_phy_read(sc, SATA_PHY_LANE0_OUT_STAT);
+ if (pllstat < 0) {
+ aprint_error_dev(sc->sc_dev,
+ "cannot read LANE0 status\n");
+ break;
+ }
+ if (pllstat & SATA_PHY_LANE0_OUT_STAT_RX_PLL_STATE)
+ break;
+ }
+ if (timeout <= 0)
+ return -1;
+
+ /* Support Staggered Spin-up */
+ v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_CAP);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_CAP, v | SATA_CAP_SSS);
+
+ /* Ports Implmented. must set 1 */
+ v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_PI);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_PI, v | SATA_PI_PI);
+
+ /* set 1ms-timer = AHB clock / 1000 */
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_TIMER1MS,
+ clk_get_rate(sc->sc_clk_ahb) / 1000);
+
+ return 0;
+}
+
+static int
+imx6_ahcisata_init_clocks(struct imx6_ahcisata_softc *sc)
+{
+ int error;
+
+ error = clk_enable(sc->sc_clk_sata);
+ if (error) {
+ aprint_error_dev(sc->sc_dev, "couldn't enable sata: %d\n", error);
+ return error;
+ }
+ error = clk_enable(sc->sc_clk_sata_ref);
+ if (error) {
+ aprint_error_dev(sc->sc_dev, "couldn't enable sata-ref: %d\n", error);
+ return error;
+ }
+ error = clk_enable(sc->sc_clk_ahb);
+ if (error) {
+ aprint_error_dev(sc->sc_dev, "couldn't enable anb: %d\n", error);
+ return error;
+ }
+
+ return 0;
+}
Index: src/sys/arch/arm/imx/fdt/imx6_clk.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx6_clk.c:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/arm/imx/fdt/imx6_clk.c Wed Jul 24 13:12:33 2019
@@ -0,0 +1,141 @@
+/* $NetBSD: imx6_clk.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $ */
+/*-
+ * Copyright (c) 2019 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * 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(0, "$NetBSD: imx6_clk.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $");
+
+#include "opt_fdt.h"
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/sysctl.h>
+#include <sys/cpufreq.h>
+#include <sys/malloc.h>
+#include <sys/kmem.h>
+#include <sys/param.h>
+
+#include <arm/imx/imx6_ccmvar.h>
+
+#include <dev/clk/clk_backend.h>
+#include <dev/fdt/fdtvar.h>
+
+static struct clk *imx6_clk_decode(device_t, int, const void *, size_t);
+
+static const struct fdtbus_clock_controller_func imx6_ccm_fdtclock_funcs = {
+ .decode = imx6_clk_decode
+};
+
+static struct clk *
+imx6_clk_decode(device_t dev, int cc_phandle, const void *data, size_t len)
+{
+ struct clk *clk;
+
+ /* #clock-cells should be 1 */
+ if (len != 4)
+ return NULL;
+
+ const u_int clock_id = be32dec(data);
+
+ clk = imx6_get_clock_by_id(clock_id);
+ if (clk)
+ return clk;
+
+ return NULL;
+}
+
+static void
+imx6_clk_fixed_from_fdt(const char *name)
+{
+ struct imx6_clk *iclk = (struct imx6_clk *)imx6_get_clock(name);
+
+ KASSERT(iclk != NULL);
+
+ char *path = kmem_asprintf("/clocks/%s", name);
+ int phandle = OF_finddevice(path);
+ kmem_free(path, strlen(path) + 1);
+
+ if (of_getprop_uint32(phandle, "clock-frequency", &iclk->clk.fixed.rate) != 0)
+ iclk->clk.fixed.rate = 0;
+}
+
+static int imxccm_match(device_t, cfdata_t, void *);
+static void imxccm_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(imxccm, sizeof(struct imxccm_softc),
+ imxccm_match, imxccm_attach, NULL, NULL);
+
+static int
+imxccm_match(device_t parent, cfdata_t cfdata, void *aux)
+{
+ const char * const compatible[] = { "fsl,imx6q-ccm", NULL };
+ struct fdt_attach_args * const faa = aux;
+
+ return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+imxccm_attach(device_t parent, device_t self, void *aux)
+{
+ struct imxccm_softc * const sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+ bus_addr_t addr;
+ bus_size_t size;
+
+ if (fdtbus_get_reg(faa->faa_phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get registers\n");
+ return;
+ }
+
+ sc->sc_dev = self;
+ sc->sc_iot = faa->faa_bst;
+
+ if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh)) {
+ aprint_error(": can't map ccm registers\n");
+ return;
+ }
+
+ int phandle = OF_finddevice("/soc/aips-bus/anatop");
+ fdtbus_get_reg(phandle, 0, &addr, &size);
+
+ if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh_analog)) {
+ aprint_error(": can't map anatop registers\n");
+ return;
+ }
+
+ imxccm_attach_common(self);
+
+ imx6_clk_fixed_from_fdt("ckil");
+ imx6_clk_fixed_from_fdt("ckih");
+ imx6_clk_fixed_from_fdt("osc");
+ imx6_clk_fixed_from_fdt("anaclk1");
+ imx6_clk_fixed_from_fdt("anaclk2");
+
+ fdtbus_register_clock_controller(self, faa->faa_phandle,
+ &imx6_ccm_fdtclock_funcs);
+}
+
Index: src/sys/arch/arm/imx/fdt/imx6_com.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx6_com.c:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/arm/imx/fdt/imx6_com.c Wed Jul 24 13:12:33 2019
@@ -0,0 +1,148 @@
+/* $NetBSD: imx6_com.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $ */
+/*-
+ * Copyright (c) 2019 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * 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(0, "$NetBSD: imx6_com.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $");
+
+#include "opt_fdt.h"
+#include "opt_imxuart.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <arm/imx/imx6_reg.h>
+#include <arm/imx/imx6var.h>
+#include <arm/imx/imxuartreg.h>
+#include <arm/imx/imxuartvar.h>
+
+static int imx6_com_match(device_t, struct cfdata *, void *);
+static void imx6_com_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(imx6_com, sizeof(struct imxuart_softc),
+ imx6_com_match, imx6_com_attach, NULL, NULL);
+
+static const char * const compatible[] = {
+ "fsl,imx6q-uart",
+ NULL
+};
+
+static int
+imx6_com_match(device_t parent, struct cfdata *cf, void *aux)
+{
+ struct fdt_attach_args * const faa = aux;
+
+ return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+imx6_com_attach(device_t parent, device_t self, void *aux)
+{
+ struct imxuart_softc *sc = device_private(self);
+ struct imxuart_regs *regsp = &sc->sc_regs;
+ struct fdt_attach_args *faa = aux;
+ const int phandle = faa->faa_phandle;
+ bus_space_tag_t bst = faa->faa_bst;
+ bus_space_handle_t bsh;
+ char intrstr[128];
+ bus_addr_t addr;
+ bus_size_t size;
+
+ if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get registers\n");
+ return;
+ }
+
+ if (bus_space_map(bst, addr, size, 0, &bsh) != 0) {
+ aprint_error(": couldn't map registers\n");
+ return;
+ }
+
+ sc->sc_dev = self;
+ regsp->ur_iot = bst;
+ regsp->ur_iobase = addr;
+ regsp->ur_ioh = bsh;
+
+ if (imxuart_is_console(regsp->ur_iot, regsp->ur_iobase, ®sp->ur_ioh))
+ aprint_normal(" (console)");
+
+ aprint_normal("\n");
+
+ if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
+ aprint_error_dev(self, "failed to decode interrupt\n");
+ return;
+ }
+
+ sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_SERIAL,
+ FDT_INTR_MPSAFE, imxuintr, sc);
+ if (sc->sc_ih == NULL)
+ aprint_error_dev(self, "failed to establish interrupt\n");
+
+ aprint_normal_dev(self, "interrupting on %s\n", intrstr);
+
+ imxuart_attach_subr(sc);
+
+}
+
+/*
+ * Console support
+ */
+
+static int
+imx6_com_console_match(int phandle)
+{
+ return of_match_compatible(phandle, compatible);
+}
+
+static void
+imx6_com_console_consinit(struct fdt_attach_args *faa, u_int uart_freq)
+{
+ const int phandle = faa->faa_phandle;
+ bus_space_tag_t bst = faa->faa_bst;
+ bus_addr_t addr;
+ bus_size_t size;
+ tcflag_t flags;
+ int speed;
+
+ fdtbus_get_reg(phandle, 0, &addr, &size);
+ speed = fdtbus_get_stdout_speed();
+ if (speed < 0)
+ speed = 115200; /* default */
+ flags = fdtbus_get_stdout_flags();
+
+ imxuart_set_frequency(uart_freq, 2);
+ if (imxuart_cnattach(bst, addr, speed, flags) != 0)
+ panic("cannot attach console UART");
+}
+
+static const struct fdt_console imx6_com_console = {
+ .match = imx6_com_console_match,
+ .consinit = imx6_com_console_consinit,
+};
+
+FDT_CONSOLE(imx6_com, &imx6_com_console);
Index: src/sys/arch/arm/imx/fdt/imx6_gpc.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx6_gpc.c:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/arm/imx/fdt/imx6_gpc.c Wed Jul 24 13:12:33 2019
@@ -0,0 +1,158 @@
+/* $NetBSD: imx6_gpc.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $ */
+/*-
+ * Copyright (c) 2019 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * 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(0, "$NetBSD: imx6_gpc.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $");
+
+#include "opt_fdt.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+
+#include <arm/imx/imx6var.h>
+#include <arm/imx/imx6_reg.h>
+#include <arm/imx/imx6_gpcreg.h>
+
+#include <arm/cortex/gic_intr.h>
+
+#include <dev/fdt/fdtvar.h>
+
+struct imxgpc_softc {
+ device_t sc_dev;
+
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+};
+
+static int imxgpc_match(device_t, struct cfdata *, void *);
+static void imxgpc_attach(device_t, device_t, void *);
+
+static void *imxgpc_establish(device_t, u_int *, int, int,
+ int (*)(void *), void *);
+static void imxgpc_disestablish(device_t, void *);
+static bool imxgpc_intrstr(device_t, u_int *, char *, size_t);
+
+struct fdtbus_interrupt_controller_func imxgpc_funcs = {
+ .establish = imxgpc_establish,
+ .disestablish = imxgpc_disestablish,
+ .intrstr = imxgpc_intrstr
+};
+
+CFATTACH_DECL_NEW(imxgpc, sizeof(struct imxgpc_softc),
+ imxgpc_match, imxgpc_attach, NULL, NULL);
+
+static int
+imxgpc_match(device_t parent, cfdata_t cf, void *aux)
+{
+ const char * const compatible[] = { "fsl,imx6q-gpc", NULL };
+ struct fdt_attach_args * const faa = aux;
+
+ return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+imxgpc_attach(device_t parent, device_t self, void *aux)
+{
+ struct imxgpc_softc * const sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ bus_addr_t gpc_addr;
+ bus_size_t gpc_size;
+ int error;
+
+ if (fdtbus_get_reg(phandle, 0, &gpc_addr, &gpc_size) != 0) {
+ aprint_error(": couldn't get gpc registers\n");
+ return;
+ }
+
+ sc->sc_dev = self;
+ sc->sc_iot = faa->faa_bst;
+
+ error = bus_space_map(sc->sc_iot, gpc_addr, gpc_size, 0,
+ &sc->sc_ioh);
+ if (error) {
+ aprint_error(": couldn't map gpc registers: %d\n", error);
+ return;
+ }
+
+ error = fdtbus_register_interrupt_controller(self, faa->faa_phandle,
+ &imxgpc_funcs);
+ if (error) {
+ aprint_error(": couldn't register with fdtbus: %d\n", error);
+ return;
+ }
+
+ aprint_naive("\n");
+ aprint_normal(": General Power Controller\n");
+
+ return;
+}
+
+static void *
+imxgpc_establish(device_t dev, u_int *specifier, int ipl, int flags,
+ int (*func)(void *), void *arg)
+{
+ /* 1st cell is the interrupt type; 0 is SPI, 1 is PPI */
+ /* 2nd cell is the interrupt number */
+ /* 3rd cell is flags */
+
+ const u_int type = be32toh(specifier[0]);
+ const u_int intr = be32toh(specifier[1]);
+ const u_int irq = type == 0 ? IRQ_SPI(intr) : IRQ_PPI(intr);
+ const u_int trig = be32toh(specifier[2]) & 0xf;
+ const u_int level = (trig & 0x3) ? IST_EDGE : IST_LEVEL;
+
+ const u_int mpsafe = (flags & FDT_INTR_MPSAFE) ? IST_MPSAFE : 0;
+
+ aprint_debug_dev(dev, "intr establish irq %d, level %d\n", irq, level);
+ return intr_establish(irq, ipl, level | mpsafe, func, arg);
+}
+
+static void
+imxgpc_disestablish(device_t dev, void *ih)
+{
+ intr_disestablish(ih);
+}
+
+static bool
+imxgpc_intrstr(device_t dev, u_int *specifier, char *buf, size_t buflen)
+{
+ /* 1st cell is the interrupt type; 0 is SPI, 1 is PPI */
+ /* 2nd cell is the interrupt number */
+ /* 3rd cell is flags */
+
+ if (!specifier)
+ return false;
+
+ const u_int type = be32toh(specifier[0]);
+ const u_int intr = be32toh(specifier[1]);
+ const u_int irq = type == 0 ? IRQ_SPI(intr) : IRQ_PPI(intr);
+
+ snprintf(buf, buflen, "irq %d", irq);
+
+ return true;
+}
Index: src/sys/arch/arm/imx/fdt/imx6_gpio.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx6_gpio.c:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/arm/imx/fdt/imx6_gpio.c Wed Jul 24 13:12:33 2019
@@ -0,0 +1,274 @@
+/* $NetBSD: imx6_gpio.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $ */
+/*-
+ * Copyright (c) 2019 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * 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(0, "$NetBSD: imx6_gpio.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $");
+
+#include "opt_fdt.h"
+#include "gpio.h"
+
+#define _INTR_PRIVATE
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/kmem.h>
+#include <sys/gpio.h>
+
+#include <dev/gpio/gpiovar.h>
+
+#include <arm/pic/picvar.h>
+#include <arm/imx/imx6_reg.h>
+
+#include <arm/imx/imxgpioreg.h>
+#include <arm/imx/imxgpiovar.h>
+
+#include <dev/fdt/fdtvar.h>
+
+static void *imx6_gpio_fdt_acquire(device_t, const void *, size_t, int);
+static void imx6_gpio_fdt_release(device_t, void *);
+static int imx6_gpio_fdt_read(device_t, void *, bool);
+static void imx6_gpio_fdt_write(device_t, void *, int, bool);
+
+static void *imxgpio_establish(device_t, u_int *, int, int,
+ int (*)(void *), void *);
+static void imxgpio_disestablish(device_t, void *);
+static bool imxgpio_intrstr(device_t, u_int *, char *, size_t);
+
+static struct fdtbus_interrupt_controller_func imxgpio_funcs = {
+ .establish = imxgpio_establish,
+ .disestablish = imxgpio_disestablish,
+ .intrstr = imxgpio_intrstr
+};
+
+static struct fdtbus_gpio_controller_func imx6_gpio_funcs = {
+ .acquire = imx6_gpio_fdt_acquire,
+ .release = imx6_gpio_fdt_release,
+ .read = imx6_gpio_fdt_read,
+ .write = imx6_gpio_fdt_write
+};
+
+const int imxgpio_ngroups = GPIO_NGROUPS;
+
+int
+imxgpio_match(device_t parent, cfdata_t cf, void *aux)
+{
+ const char * const compatible[] = {
+ "fsl,imx6q-gpio",
+ NULL
+ };
+ struct fdt_attach_args * const faa = aux;
+
+ return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+void
+imxgpio_attach(device_t parent, device_t self, void *aux)
+{
+ struct imxgpio_softc * const sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+ char intrstr[128];
+ const int phandle = faa->faa_phandle;
+ bus_space_handle_t ioh;
+ bus_addr_t addr;
+ bus_size_t size;
+ int error;
+
+ if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get registers\n");
+ return;
+ }
+
+ error = bus_space_map(faa->faa_bst, addr, size, 0, &ioh);
+ if (error) {
+ aprint_error(": couldn't map %#llx: %d", (uint64_t)addr, error);
+ return;
+ }
+
+ aprint_naive("\n");
+ aprint_normal(": GPIO (%s)\n", fdtbus_get_string(phandle, "name"));
+
+ sc->gpio_memt = faa->faa_bst;
+ sc->gpio_memh = ioh;
+ sc->gpio_unit = (addr - IMX6_AIPS1_BASE - AIPS1_GPIO1_BASE) / 0x4000;
+ sc->gpio_irqbase = PIC_MAXSOURCES + sc->gpio_unit * GPIO_NPINS;
+
+ if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
+ aprint_error_dev(self, "failed to decode interrupt\n");
+ return;
+ }
+ sc->gpio_is = fdtbus_intr_establish(phandle, 0, IPL_HIGH, 0,
+ pic_handle_intr, &sc->gpio_pic);
+ if (sc->gpio_is == NULL) {
+ aprint_error_dev(self, "couldn't establish interrupt on %s\n",
+ intrstr);
+ return;
+ }
+ aprint_normal_dev(self, "interrupting on %s\n", intrstr);
+
+ if (!fdtbus_intr_str(phandle, 1, intrstr, sizeof(intrstr))) {
+ aprint_error_dev(self, "failed to decode interrupt\n");
+ return;
+ }
+ sc->gpio_is_high = fdtbus_intr_establish(phandle, 1, IPL_HIGH, 0,
+ pic_handle_intr, &sc->gpio_pic);
+ if (sc->gpio_is_high == NULL) {
+ aprint_error_dev(self, "couldn't establish interrupt on %s\n",
+ intrstr);
+ return;
+ }
+ aprint_normal_dev(self, "interrupting on %s\n", intrstr);
+
+ fdtbus_register_gpio_controller(self, phandle, &imx6_gpio_funcs);
+
+ error = fdtbus_register_interrupt_controller(self, phandle,
+ &imxgpio_funcs);
+ if (error) {
+ aprint_error(": couldn't register with fdtbus: %d\n", error);
+ return;
+ }
+
+ imxgpio_attach_common(self);
+}
+
+static void *
+imx6_gpio_fdt_acquire(device_t dev, const void *data, size_t len, int flags)
+{
+ struct imxgpio_softc * const sc = device_private(dev);
+ struct imxgpio_pin *gpin;
+ const u_int *gpio = data;
+
+ if (len != 12)
+ return NULL;
+
+ const u_int pin = be32toh(gpio[1]);
+ const bool actlo = be32toh(gpio[2]) & 1;
+
+ gpin = kmem_zalloc(sizeof(*gpin), KM_SLEEP);
+ gpin->pin_no = pin;
+ gpin->pin_flags = flags;
+ gpin->pin_actlo = actlo;
+
+ imxgpio_pin_ctl(sc, gpin->pin_no, gpin->pin_flags);
+
+ return gpin;
+}
+
+static void
+imx6_gpio_fdt_release(device_t dev, void *priv)
+{
+ struct imxgpio_softc * const sc = device_private(dev);
+ struct imxgpio_pin *gpin = priv;
+
+ imxgpio_pin_ctl(sc, gpin->pin_no, GPIO_PIN_INPUT);
+ kmem_free(gpin, sizeof(*gpin));
+}
+
+static int
+imx6_gpio_fdt_read(device_t dev, void *priv, bool raw)
+{
+ struct imxgpio_softc * const sc = device_private(dev);
+ struct imxgpio_pin *gpin = priv;
+ int val;
+
+ val = imxgpio_pin_read(sc, gpin->pin_no);
+
+ if (!raw && gpin->pin_actlo)
+ val = !val;
+
+ return val;
+}
+
+static void
+imx6_gpio_fdt_write(device_t dev, void *priv, int val, bool raw)
+{
+ struct imxgpio_softc * const sc = device_private(dev);
+ struct imxgpio_pin *gpin = priv;
+
+ if (!raw && gpin->pin_actlo)
+ val = !val;
+
+ imxgpio_pin_write(sc, gpin->pin_no, val);
+}
+
+static void *
+imxgpio_establish(device_t dev, u_int *specifier, int ipl, int flags,
+ int (*func)(void *), void *arg)
+{
+ struct imxgpio_softc * const sc = device_private(dev);
+
+ /* 1st cell is the interrupt number */
+ /* 2nd cell is flags */
+
+ const u_int intr = be32toh(specifier[0]);
+ const u_int trig = be32toh(specifier[1]) & 0xf;
+ u_int level;
+
+ if ((trig & 0x1) && (trig & 0x2))
+ level = IST_EDGE_BOTH;
+ else if (trig & 0x1)
+ level = IST_EDGE_RISING;
+ else if (trig & 0x2)
+ level = IST_EDGE_FALLING;
+ else if (trig & 0x4)
+ level = IST_LEVEL_HIGH;
+ else
+ level = IST_LEVEL_LOW;
+
+ const u_int mpsafe = (flags & FDT_INTR_MPSAFE) ? IST_MPSAFE : 0;
+
+ aprint_debug_dev(dev, "intr establish irq %d, level %d\n",
+ sc->gpio_irqbase + intr, level);
+ return intr_establish(sc->gpio_irqbase + intr, ipl, level | mpsafe, func, arg);
+}
+
+static void
+imxgpio_disestablish(device_t dev, void *ih)
+{
+ intr_disestablish(ih);
+}
+
+static bool
+imxgpio_intrstr(device_t dev, u_int *specifier, char *buf, size_t buflen)
+{
+ struct imxgpio_softc * const sc = device_private(dev);
+
+ /* 1st cell is the interrupt number */
+ /* 2nd cell is flags */
+
+ if (!specifier)
+ return false;
+
+ const u_int intr = be32toh(specifier[0]);
+
+ snprintf(buf, buflen, "irq %d (gpio%d %d)",
+ sc->gpio_irqbase + intr, sc->gpio_unit, intr);
+
+ return true;
+}
Index: src/sys/arch/arm/imx/fdt/imx6_iomux.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx6_iomux.c:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/arm/imx/fdt/imx6_iomux.c Wed Jul 24 13:12:33 2019
@@ -0,0 +1,178 @@
+/* $NetBSD: imx6_iomux.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $ */
+/*-
+ * Copyright (c) 2019 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * 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(0, "$NetBSD: imx6_iomux.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $");
+
+#include "opt_fdt.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+
+#include <arm/imx/imx6var.h>
+#include <arm/imx/imx6_reg.h>
+#include <arm/imx/imx6_iomuxreg.h>
+
+#include <dev/fdt/fdtvar.h>
+
+struct imxiomux_softc {
+ device_t sc_dev;
+
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+
+ int sc_phandle;
+};
+
+#define CONFIG_NO_PAD_CTL __BIT(31)
+#define CONFIG_SION __BIT(30)
+
+static int
+imx6_pinctrl_set_config(device_t dev, const void *data, size_t len)
+{
+ struct imxiomux_softc * const sc = device_private(dev);
+ int pins_len;
+ uint32_t reg;
+
+ if (len != 4)
+ return -1;
+
+ const int phandle = fdtbus_get_phandle_from_native(be32dec(data));
+ const u_int *pins = fdtbus_get_prop(phandle, "fsl,pins", &pins_len);
+
+ aprint_debug_dev(sc->sc_dev, "name %s\n", fdtbus_get_string(phandle, "name"));
+ while (pins_len >= 24) {
+ u_int mux_reg = be32toh(pins[0]);
+ u_int conf_reg = be32toh(pins[1]);
+ u_int input_reg = be32toh(pins[2]);
+ u_int mux_mode = be32toh(pins[3]);
+ u_int input_val = be32toh(pins[4]);
+ u_int config = be32toh(pins[5]);
+
+ if (config & CONFIG_SION)
+ mux_mode |= IOMUX_CONFIG_SION;
+ config &= ~CONFIG_SION;
+
+ reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, mux_reg);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, mux_reg, mux_mode);
+ aprint_debug_dev(sc->sc_dev,
+ "mux offset 0x%08x, val 0x%08x -> 0x%08x\n",
+ mux_reg, reg, mux_mode);
+
+ if (!(config & CONFIG_NO_PAD_CTL)) {
+ reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, conf_reg);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, conf_reg, config);
+ aprint_debug_dev(sc->sc_dev,
+ "config offset 0x%08x, val 0x%08x -> 0x%08x\n",
+ conf_reg, reg, config);
+ }
+
+ if (__SHIFTOUT(input_val, __BITS(31, 24)) == 0xff) {
+ uint8_t sel = __SHIFTOUT(input_val, __BITS(7, 0));
+ uint8_t width = __SHIFTOUT(input_val, __BITS(15, 8));
+ uint8_t shift = __SHIFTOUT(input_val, __BITS(23, 16));
+ uint32_t mask = __BITS(shift + (width - 1), shift);
+
+ reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, input_reg);
+ reg &= ~mask;
+ reg |= __SHIFTIN(sel, mask);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, input_reg, reg);
+ aprint_debug_dev(sc->sc_dev,
+ "+input offset 0x%08x, val 0x%08x\n",
+ input_reg, reg);
+ } else if (input_reg != 0) {
+ reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, input_reg);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, input_reg, input_val);
+ aprint_debug_dev(sc->sc_dev,
+ "input offset 0x%08x, val 0x%08x -> 0x%08x\n",
+ input_reg, reg, input_val);
+ }
+
+ pins_len -= 24;
+ pins += 6;
+ }
+
+ return 0;
+}
+
+static struct fdtbus_pinctrl_controller_func imx6_pinctrl_funcs = {
+ .set_config = imx6_pinctrl_set_config,
+};
+
+static int imxiomux_match(device_t, struct cfdata *, void *);
+static void imxiomux_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(imxiomux, sizeof(struct imxiomux_softc),
+ imxiomux_match, imxiomux_attach, NULL, NULL);
+
+static int
+imxiomux_match(device_t parent, cfdata_t cf, void *aux)
+{
+ const char * const compatible[] = { "fsl,imx6q-iomuxc", NULL };
+ struct fdt_attach_args * const faa = aux;
+
+ return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+imxiomux_attach(device_t parent, device_t self, void *aux)
+{
+ struct imxiomux_softc * const sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ bus_addr_t addr;
+ bus_size_t size;
+ int error;
+
+ if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get iomux registers\n");
+ return;
+ }
+
+ sc->sc_dev = self;
+ sc->sc_iot = faa->faa_bst;
+
+ error = bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh);
+ if (error) {
+ aprint_error(": couldn't map iomux registers: %d\n", error);
+ return;
+ }
+
+ aprint_naive("\n");
+ aprint_normal(": IOMUX Controller\n");
+
+ for (int child = OF_child(phandle); child; child = OF_peer(child)) {
+ for (int sub = OF_child(child); sub; sub = OF_peer(sub)) {
+ if (!of_hasprop(sub, "fsl,pins"))
+ continue;
+ fdtbus_register_pinctrl_config(self, sub, &imx6_pinctrl_funcs);
+ }
+ }
+
+ fdtbus_pinctrl_configure();
+}
+
Index: src/sys/arch/arm/imx/fdt/imx6_pcie.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx6_pcie.c:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/arm/imx/fdt/imx6_pcie.c Wed Jul 24 13:12:33 2019
@@ -0,0 +1,248 @@
+/* $NetBSD: imx6_pcie.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $ */
+/*-
+ * Copyright (c) 2019 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * 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(0, "$NetBSD: imx6_pcie.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $");
+
+#include "opt_pci.h"
+#include "opt_fdt.h"
+
+#include "pci.h"
+#include "imxgpio.h"
+#include "locators.h"
+
+#define _INTR_PRIVATE
+
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/extent.h>
+#include <sys/queue.h>
+#include <sys/mutex.h>
+#include <sys/kmem.h>
+#include <sys/gpio.h>
+
+#include <machine/frame.h>
+#include <arm/cpufunc.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pciconf.h>
+
+#include <arm/imx/imxpcievar.h>
+#include <arm/imx/imxgpioreg.h>
+#include <arm/imx/imxgpiovar.h>
+#include <arm/imx/imx6var.h>
+#include <arm/imx/imx6_reg.h>
+#include <arm/imx/imx6_iomuxreg.h>
+#include <arm/imx/imx6_ccmreg.h>
+#include <arm/imx/imx6_ccmvar.h>
+
+struct imxpcie_fdt_softc {
+ struct imxpcie_softc sc_imxpcie;
+
+ struct fdtbus_gpio_pin *sc_pin_reset;
+};
+
+static int imx6_pcie_match(device_t, cfdata_t, void *);
+static void imx6_pcie_attach(device_t, device_t, void *);
+
+static void imx6_pcie_configure(void *);
+static uint32_t imx6_pcie_gpr_read(void *, uint32_t);
+static void imx6_pcie_gpr_write(void *, uint32_t, uint32_t);
+static void imx6_pcie_reset(void *);
+
+#define IMX6_PCIE_MEM_BASE 0x01000000
+#define IMX6_PCIE_MEM_SIZE 0x00f00000 /* 15MB */
+#define IMX6_PCIE_ROOT_BASE 0x01f00000
+#define IMX6_PCIE_ROOT_SIZE 0x00080000 /* 512KB */
+#define IMX6_PCIE_IO_BASE 0x01f80000
+#define IMX6_PCIE_IO_SIZE 0x00010000 /* 64KB */
+
+CFATTACH_DECL_NEW(imxpcie_fdt, sizeof(struct imxpcie_fdt_softc),
+ imx6_pcie_match, imx6_pcie_attach, NULL, NULL);
+
+static const char * const compatible[] = {
+ "fsl,imx6q-pcie",
+ NULL
+};
+
+static int
+imx6_pcie_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
+imx6_pcie_attach(device_t parent, device_t self, void *aux)
+{
+ struct imxpcie_fdt_softc * const ifsc = device_private(self);
+ struct imxpcie_softc * const sc = &ifsc->sc_imxpcie;
+ struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ bus_space_tag_t bst = faa->faa_bst;
+ char intrstr[128];
+ bus_addr_t addr;
+ bus_size_t size;
+
+ aprint_naive("\n");
+ aprint_normal(": PCI Express Controller\n");
+
+ sc->sc_dev = self;
+ sc->sc_iot = bst;
+ sc->sc_dmat = faa->faa_dmat;
+ sc->sc_cookie = ifsc;
+ sc->sc_pci_netbsd_configure = imx6_pcie_configure;
+ sc->sc_gpr_read = imx6_pcie_gpr_read;
+ sc->sc_gpr_write = imx6_pcie_gpr_write;
+ sc->sc_reset = imx6_pcie_reset;
+
+ if (fdtbus_get_reg_byname(phandle, "dbi", &addr, &size) != 0) {
+ aprint_error(": couldn't get registers\n");
+ return;
+ }
+ if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh)) {
+ aprint_error_dev(self, "Cannot map registers\n");
+ return;
+ }
+ if (fdtbus_get_reg_byname(phandle, "config", &addr, &size) != 0) {
+ aprint_error(": couldn't get registers\n");
+ return;
+ }
+ sc->sc_root_addr = addr;
+ sc->sc_root_size = size;
+
+ const int gpr_phandle = OF_finddevice("/soc/aips-bus/iomuxc-gpr");
+ fdtbus_get_reg(gpr_phandle, 0, &addr, &size);
+ if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_gpr_ioh)) {
+ aprint_error_dev(self, "Cannot map registers\n");
+ return;
+ }
+
+ ifsc->sc_pin_reset = fdtbus_gpio_acquire(phandle, "reset-gpio",
+ GPIO_PIN_OUTPUT);
+ if (!ifsc->sc_pin_reset) {
+ aprint_error(": couldn't acquire reset gpio\n");
+ return;
+ }
+
+ sc->sc_clk_pcie_axi = fdtbus_clock_get(phandle, "pcie");
+ if (sc->sc_clk_pcie_axi == NULL) {
+ aprint_error(": couldn't get clock pcie_axi\n");
+ return;
+ }
+ sc->sc_clk_lvds1_gate = fdtbus_clock_get(phandle, "pcie_bus");
+ if (sc->sc_clk_lvds1_gate == NULL) {
+ aprint_error(": couldn't get clock lvds1_gate\n");
+ return;
+ }
+ sc->sc_clk_pcie_ref = fdtbus_clock_get(phandle, "pcie_phy");
+ if (sc->sc_clk_pcie_ref == NULL) {
+ aprint_error(": couldn't get clock pcie_ref\n");
+ return;
+ }
+
+ TAILQ_INIT(&sc->sc_intrs);
+ mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
+
+ if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
+ aprint_error_dev(self, "failed to decode interrupt\n");
+ return;
+ }
+
+ sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_VM, 0, imxpcie_intr, sc);
+ if (sc->sc_ih == NULL) {
+ aprint_error_dev(self, "failed to establish interrupt on %s\n",
+ intrstr);
+ return;
+ }
+ aprint_normal_dev(self, "interrupting on %s\n", intrstr);
+
+ imxpcie_attach_common(sc);
+}
+
+static void
+imx6_pcie_configure(void *cookie)
+{
+ struct imxpcie_fdt_softc * const ifsc = cookie;
+ struct imxpcie_softc * const sc = &ifsc->sc_imxpcie;
+
+#ifdef PCI_NETBSD_CONFIGURE
+ struct extent *ioext, *memext;
+ int error;
+
+ ioext = extent_create("pciio", IMX6_PCIE_IO_BASE,
+ IMX6_PCIE_IO_BASE + IMX6_PCIE_IO_SIZE - 1,
+ NULL, 0, EX_NOWAIT);
+ memext = extent_create("pcimem", IMX6_PCIE_MEM_BASE,
+ IMX6_PCIE_MEM_BASE + IMX6_PCIE_MEM_SIZE - 1,
+ NULL, 0, EX_NOWAIT);
+
+ error = pci_configure_bus(&sc->sc_pc, ioext, memext, NULL, 0,
+ arm_dcache_align);
+
+ extent_destroy(ioext);
+ extent_destroy(memext);
+
+ if (error) {
+ aprint_error_dev(sc->sc_dev, "configuration failed (%d)\n",
+ error);
+ }
+#endif
+}
+
+static uint32_t
+imx6_pcie_gpr_read(void *cookie, uint32_t reg)
+{
+ struct imxpcie_fdt_softc * const ifsc = cookie;
+ struct imxpcie_softc * const sc = &ifsc->sc_imxpcie;
+ return bus_space_read_4(sc->sc_iot, sc->sc_gpr_ioh, reg);
+}
+
+static void
+imx6_pcie_gpr_write(void *cookie, uint32_t reg, uint32_t val)
+{
+ struct imxpcie_fdt_softc * const ifsc = cookie;
+ struct imxpcie_softc * const sc = &ifsc->sc_imxpcie;
+ bus_space_write_4(sc->sc_iot, sc->sc_gpr_ioh, reg, val);
+}
+
+static void
+imx6_pcie_reset(void *cookie)
+{
+ struct imxpcie_fdt_softc * const ifsc = cookie;
+
+ fdtbus_gpio_write(ifsc->sc_pin_reset, 1);
+ delay(20 * 1000);
+ fdtbus_gpio_write(ifsc->sc_pin_reset, 0);
+}
Index: src/sys/arch/arm/imx/fdt/imx6_platform.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx6_platform.c:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/arm/imx/fdt/imx6_platform.c Wed Jul 24 13:12:33 2019
@@ -0,0 +1,200 @@
+/* $NetBSD: imx6_platform.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $ */
+/*-
+ * Copyright (c) 2019 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * 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(0, "$NetBSD: imx6_platform.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $");
+
+#include "opt_soc.h"
+#include "arml2cc.h"
+#include "opt_multiprocessor.h"
+#include "opt_fdt.h"
+#include "opt_fdt_arm.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/device.h>
+#include <sys/termios.h>
+
+#include <dev/fdt/fdtvar.h>
+#include <arm/fdt/arm_fdtvar.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <arm/arm32/machdep.h>
+
+#include <machine/bootconfig.h>
+#include <arm/cpufunc.h>
+
+#include <arm/cortex/a9tmr_var.h>
+#include <arm/cortex/scu_reg.h>
+#include <arm/cortex/gic_reg.h>
+#include <arm/cortex/pl310_var.h>
+
+#include <arm/imx/imx6_reg.h>
+#include <arm/imx/imx6_srcreg.h>
+#include <arm/imx/imxuartreg.h>
+
+#include <arm/imx/fdt/imx6_platform.h>
+
+#include <libfdt.h>
+
+#define IMX_REF_FREQ 80000000
+
+#ifdef VERBOSE_INIT_ARM
+#define VPRINTF(...) printf(__VA_ARGS__)
+#else
+#define VPRINTF(...) __nothing
+#endif
+
+extern struct bus_space armv7_generic_bs_tag;
+extern struct bus_space armv7_generic_a4x_bs_tag;
+extern struct arm32_bus_dma_tag arm_generic_dma_tag;
+
+static const struct pmap_devmap *
+imx_platform_devmap(void)
+{
+ static const struct pmap_devmap devmap[] = {
+ DEVMAP_ENTRY(KERNEL_IO_IOREG_VBASE, IMX6_IOREG_PBASE, IMX6_IOREG_SIZE),
+ DEVMAP_ENTRY(KERNEL_IO_ARMCORE_VBASE, IMX6_ARMCORE_PBASE, IMX6_ARMCORE_SIZE),
+ DEVMAP_ENTRY_END
+};
+
+ return devmap;
+}
+
+static void
+imx_platform_init_attach_args(struct fdt_attach_args *faa)
+{
+ faa->faa_bst = &armv7_generic_bs_tag;
+ faa->faa_a4x_bst = &armv7_generic_a4x_bs_tag;
+ faa->faa_dmat = &arm_generic_dma_tag;
+}
+
+void imx_platform_early_putchar(char);
+
+void
+imx_platform_early_putchar(char c)
+{
+#ifdef CONSADDR
+#define CONSADDR_VA ((CONSADDR - IMX6_IOREG_PBASE) + KERNEL_IO_IOREG_VBASE)
+
+ volatile uint32_t *uartaddr = cpu_earlydevice_va_p() ?
+ (volatile uint32_t *)CONSADDR_VA :
+ (volatile uint32_t *)CONSADDR;
+
+ while ((le32toh(uartaddr[(IMX_USR2/4)]) & IMX_USR2_TXDC) == 0)
+ ;
+
+ uartaddr[(IMX_UTXD/4)] = htole32(c);
+#endif
+}
+
+static void
+imx_platform_device_register(device_t self, void *aux)
+{
+}
+
+static u_int
+imx_platform_uart_freq(void)
+{
+ return IMX_REF_FREQ;
+}
+
+static void
+imx_platform_bootstrap(void)
+{
+#if NARML2CC > 0
+ bus_space_tag_t bst = &armv7_generic_bs_tag;
+ bus_space_handle_t bsh;
+ if (bus_space_map(bst, IMX6_ARMCORE_PBASE, IMX6_ARMCORE_SIZE, 0, &bsh))
+ panic("couldn't map armcore registers");
+ arml2cc_init(bst, bsh, ARMCORE_L2C_BASE);
+ bus_space_unmap(bst, bsh, IMX6_ARMCORE_SIZE);
+#endif
+
+ arm_fdt_cpu_bootstrap();
+}
+
+static int
+imx_platform_mpstart(void)
+{
+#if defined(MULTIPROCESSOR)
+ bus_space_tag_t bst = &armv7_generic_bs_tag;
+ bus_space_handle_t bsh;
+
+ if (bus_space_map(bst, IMX6_ARMCORE_PBASE, IMX6_ARMCORE_SIZE, 0, &bsh) != 0)
+ panic("couldn't map armcore registers");
+
+ /* Enable Snoop Control Unit */
+ bus_space_write_4(bst, bsh, SCU_INV_ALL_REG, 0xff);
+ bus_space_write_4(bst, bsh, SCU_CTL,
+ bus_space_read_4(bst, bsh, SCU_CTL) | SCU_CTL_SCU_ENA);
+
+ bus_space_unmap(bst, bsh, AIPS1_SRC_SIZE);
+
+ if (bus_space_map(bst, IMX6_AIPS1_BASE + AIPS1_SRC_BASE, AIPS1_SRC_SIZE, 0, &bsh) != 0)
+ panic("couldn't map SRC");
+
+
+ uint32_t srcctl = bus_space_read_4(bst, bsh, SRC_SCR);
+ const paddr_t mpstart = KERN_VTOPHYS((vaddr_t)cpu_mpstart);
+
+ srcctl &= ~(SRC_SCR_CORE1_ENABLE | SRC_SCR_CORE2_ENABLE |
+ SRC_SCR_CORE3_ENABLE);
+ bus_space_write_4(bst, bsh, SRC_SCR, srcctl);
+
+ for (int i = 1; i < arm_cpu_max; i++) {
+ bus_space_write_4(bst, bsh, SRC_GPRN_ENTRY(i), mpstart);
+ srcctl |= SRC_SCR_COREN_RST(i);
+ srcctl |= SRC_SCR_COREN_ENABLE(i);
+ }
+ bus_space_write_4(bst, bsh, SRC_SCR, srcctl);
+
+ bus_space_unmap(bst, bsh, AIPS1_SRC_SIZE);
+
+ return arm_fdt_cpu_mpstart();
+#endif
+}
+
+static void
+imx6_platform_reset(void)
+{
+}
+
+const struct arm_platform imx6_platform = {
+ .ap_devmap = imx_platform_devmap,
+ .ap_bootstrap = imx_platform_bootstrap,
+ .ap_init_attach_args = imx_platform_init_attach_args,
+ .ap_device_register = imx_platform_device_register,
+ .ap_reset = imx6_platform_reset,
+ .ap_delay = a9tmr_delay,
+ .ap_uart_freq = imx_platform_uart_freq,
+ .ap_mpstart = imx_platform_mpstart,
+};
+
+ARM_PLATFORM(imx6, "fsl,imx6q", &imx6_platform);
+
Index: src/sys/arch/arm/imx/fdt/imx6_platform.h
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx6_platform.h:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/arm/imx/fdt/imx6_platform.h Wed Jul 24 13:12:33 2019
@@ -0,0 +1,35 @@
+/* $NetBSD: imx6_platform.h,v 1.1 2019/07/24 13:12:33 hkenken Exp $ */
+/*-
+ * Copyright (c) 2019 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * 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.
+ */
+#ifndef _ARM_IMX_FDT_IMX6_PLATFORM_H
+#define _ARM_IMX_FDT_IMX6_PLATFORM_H
+
+#include <arch/evbarm/fdt/platform.h>
+
+#define KERNEL_IO_IOREG_VBASE KERNEL_IO_VBASE
+#define KERNEL_IO_ARMCORE_VBASE (KERNEL_IO_IOREG_VBASE + IMX6_IOREG_SIZE)
+
+#endif /* _ARM_IMX_FDT_IMX6_PLATFORM_H */
Index: src/sys/arch/arm/imx/fdt/imx6_sdhc.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx6_sdhc.c:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/arm/imx/fdt/imx6_sdhc.c Wed Jul 24 13:12:33 2019
@@ -0,0 +1,191 @@
+/* $NetBSD: imx6_sdhc.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $ */
+/*-
+ * Copyright (c) 2019 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * 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(0, "$NetBSD: imx6_sdhc.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $");
+
+#include "opt_fdt.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/gpio.h>
+
+#include <dev/sdmmc/sdhcreg.h>
+#include <dev/sdmmc/sdhcvar.h>
+#include <dev/sdmmc/sdmmcvar.h>
+
+#include <arm/imx/imx6_reg.h>
+#include <arm/imx/imx6var.h>
+
+#include <dev/fdt/fdtvar.h>
+
+static int imx6_sdhc_match(device_t, cfdata_t, void *);
+static void imx6_sdhc_attach(device_t, device_t, void *);
+
+static int imx6_sdhc_card_detect(struct sdhc_softc *);
+
+struct imx6_sdhc_softc {
+ struct sdhc_softc sc_sdhc;
+
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ bus_size_t sc_bsz;
+
+ struct sdhc_host *sc_host;
+ void *sc_ih;
+
+ struct clk *sc_clk_per;
+
+ struct fdtbus_gpio_pin *sc_pin_cd;
+};
+
+CFATTACH_DECL_NEW(imx6_sdhc, sizeof(struct imx6_sdhc_softc),
+ imx6_sdhc_match, imx6_sdhc_attach, NULL, NULL);
+
+static const char * const compatible[] = {
+ "fsl,imx6q-usdhc",
+ NULL
+};
+
+static int
+imx6_sdhc_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
+imx6_sdhc_attach(device_t parent, device_t self, void *aux)
+{
+ struct imx6_sdhc_softc * const sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+ char intrstr[128];
+ bus_addr_t addr;
+ bus_size_t size;
+ u_int bus_width;
+ int error;
+
+ if (fdtbus_get_reg(faa->faa_phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get registers\n");
+ return;
+ }
+
+ if (of_getprop_uint32(faa->faa_phandle, "bus-width", &bus_width))
+ bus_width = 4;
+
+ sc->sc_clk_per = fdtbus_clock_get(faa->faa_phandle, "per");
+ if (sc->sc_clk_per == NULL) {
+ aprint_error(": couldn't get clock\n");
+ return;
+ }
+
+ sc->sc_sdhc.sc_dev = self;
+ sc->sc_sdhc.sc_dmat = faa->faa_dmat;
+
+ sc->sc_sdhc.sc_clkbase = clk_get_rate(sc->sc_clk_per) / 1000;
+ sc->sc_sdhc.sc_flags =
+ SDHC_FLAG_USE_DMA |
+ SDHC_FLAG_NO_PWR0 |
+ SDHC_FLAG_HAVE_DVS |
+ SDHC_FLAG_32BIT_ACCESS |
+ SDHC_FLAG_8BIT_MODE |
+ SDHC_FLAG_USE_ADMA2 |
+ SDHC_FLAG_USDHC;
+
+ if (bus_width == 8) {
+ sc->sc_sdhc.sc_flags |= SDHC_FLAG_8BIT_MODE;
+ }
+ sc->sc_sdhc.sc_host = &sc->sc_host;
+
+ sc->sc_bst = faa->faa_bst;
+ 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);
+ return;
+ }
+ sc->sc_bsz = size;
+
+ sc->sc_pin_cd = fdtbus_gpio_acquire(faa->faa_phandle,
+ "cd-gpios", GPIO_PIN_INPUT);
+
+ if (sc->sc_pin_cd) {
+ sc->sc_sdhc.sc_vendor_card_detect = imx6_sdhc_card_detect;
+ sc->sc_sdhc.sc_flags |= SDHC_FLAG_POLL_CARD_DET;
+ }
+
+ error = clk_enable(sc->sc_clk_per);
+ if (error) {
+ aprint_error(": couldn't enable clock: %d\n", error);
+ return;
+ }
+
+ aprint_naive("\n");
+ aprint_normal(": SDMMC (%u kHz)\n", sc->sc_sdhc.sc_clkbase);
+
+ if (sc->sc_sdhc.sc_clkbase == 0) {
+ aprint_error_dev(self, "couldn't determine frequency\n");
+ return;
+ }
+
+ if (!fdtbus_intr_str(faa->faa_phandle, 0, intrstr, sizeof(intrstr))) {
+ aprint_error_dev(self, "failed to decode interrupt\n");
+ return;
+ }
+
+ sc->sc_ih = fdtbus_intr_establish(faa->faa_phandle, 0, IPL_SDMMC, 0,
+ sdhc_intr, &sc->sc_sdhc);
+ if (sc->sc_ih == NULL) {
+ aprint_error_dev(self, "couldn't establish interrupt on %s\n",
+ intrstr);
+ return;
+ }
+ aprint_normal_dev(self, "interrupting on %s\n", intrstr);
+
+ error = sdhc_host_found(&sc->sc_sdhc, sc->sc_bst, sc->sc_bsh, sc->sc_bsz);
+ if (error) {
+ aprint_error_dev(self, "couldn't initialize host, error = %d\n",
+ error);
+ fdtbus_intr_disestablish(faa->faa_phandle, sc->sc_ih);
+ sc->sc_ih = NULL;
+ return;
+ }
+}
+
+static int
+imx6_sdhc_card_detect(struct sdhc_softc *ssc)
+{
+ struct imx6_sdhc_softc *sc = device_private(ssc->sc_dev);
+
+ KASSERT(sc->sc_pin_cd != NULL);
+
+ return fdtbus_gpio_read(sc->sc_pin_cd);
+}
+
Index: src/sys/arch/arm/imx/fdt/imx6_usb.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx6_usb.c:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/arm/imx/fdt/imx6_usb.c Wed Jul 24 13:12:33 2019
@@ -0,0 +1,277 @@
+/* $NetBSD: imx6_usb.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $ */
+/*-
+ * Copyright (c) 2019 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * 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(0, "$NetBSD: imx6_usb.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $");
+
+#include "opt_fdt.h"
+
+#include <locators.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/bus.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/imx/imx6var.h>
+#include <arm/imx/imx6_reg.h>
+#include <arm/imx/imx6_usbreg.h>
+#include <arm/imx/imxusbvar.h>
+
+#include <dev/fdt/fdtvar.h>
+
+struct imxusbc_fdt_softc {
+ struct imxusbc_softc sc_imxusbc; /* Must be first */
+
+ int sc_phandle;
+};
+
+static int imx6_usb_match(device_t, struct cfdata *, void *);
+static void imx6_usb_attach(device_t, device_t, void *);
+static int imx6_usb_init_clocks(struct imxusbc_softc *);
+static void imx6_usb_init(struct imxehci_softc *);
+static void init_otg(struct imxehci_softc *);
+static void init_h1(struct imxehci_softc *);
+static int imxusbc_print(void *, const char *);
+static void *imx6_usb_intr_establish(struct imxehci_softc *);
+
+/* attach structures */
+CFATTACH_DECL_NEW(imxusbc_fdt, sizeof(struct imxusbc_fdt_softc),
+ imx6_usb_match, imx6_usb_attach, NULL, NULL);
+
+static const char * const compatible[] = {
+ "fsl,imx6q-usb",
+ NULL
+};
+
+static int
+imx6_usb_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
+imx6_usb_attach(device_t parent, device_t self, void *aux)
+{
+ struct imxusbc_fdt_softc *ifsc = device_private(self);
+ struct imxusbc_softc *sc = &ifsc->sc_imxusbc;
+ struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ bus_space_tag_t bst = faa->faa_bst;
+ bus_space_handle_t bsh;
+ bus_addr_t addr;
+ bus_size_t size;
+ int error;
+
+ aprint_naive("\n");
+ aprint_normal("\n");
+
+ ifsc->sc_phandle = phandle;
+
+ if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get imxusbc registers\n");
+ return;
+ }
+
+ error = bus_space_map(bst, addr, size, 0, &bsh);
+ if (error) {
+ aprint_error(": couldn't map %#llx: %d", (uint64_t)addr, error);
+ return;
+ }
+
+ sc->sc_clk = fdtbus_clock_get_index(phandle, 0);
+ if (sc->sc_clk == NULL) {
+ aprint_error(": couldn't get clock\n");
+ return;
+ }
+
+ sc->sc_init_md_hook = imx6_usb_init;
+ sc->sc_intr_establish_md_hook = imx6_usb_intr_establish;
+ sc->sc_setup_md_hook = NULL;
+
+ sc->sc_dev = self;
+ sc->sc_iot = bst;
+ sc->sc_ioh = bsh;
+ sc->sc_ehci_size = size;
+ sc->sc_ehci_offset = 0;
+
+ struct fdt_phandle_data data;
+ error = fdtbus_get_phandle_with_data(phandle, "fsl,usbmisc",
+ "#index-cells", 0, &data);
+ if (error) {
+ aprint_error(": couldn't get usbmisc property\n");
+ return;
+ }
+ int unit = be32toh(data.values[0]);
+
+ if (fdtbus_get_reg(data.phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get usbmisc registers\n");
+ return;
+ }
+ error = bus_space_map(bst, addr, size, 0, &bsh);
+ if (error) {
+ aprint_error(": couldn't map usbmisc registers: %d\n", error);
+ return;
+ }
+ sc->sc_ioh_usbnc = bsh;
+
+ if (imx6_usb_init_clocks(sc) != 0) {
+ aprint_error_dev(self, "couldn't init clocks\n");
+ return;
+ }
+
+ /* attach OTG/EHCI host controllers */
+ struct imxusbc_attach_args iaa;
+ iaa.aa_iot = sc->sc_iot;
+ iaa.aa_ioh = sc->sc_ioh;
+ iaa.aa_dmat = faa->faa_dmat;
+ iaa.aa_unit = unit;
+ iaa.aa_irq = IMXUSBCCF_IRQ_DEFAULT;
+ config_found_sm_loc(self, "imxusbc", NULL, &iaa, imxusbc_print, NULL);
+
+ return;
+}
+
+static int
+imxusbc_print(void *aux, const char *name __unused)
+{
+ struct imxusbc_attach_args *iaa;
+
+ iaa = (struct imxusbc_attach_args *)aux;
+
+ aprint_normal(" unit %d intr %d", iaa->aa_unit, iaa->aa_irq);
+ return UNCONF;
+}
+
+
+static int
+imx6_usb_init_clocks(struct imxusbc_softc *sc)
+{
+ int error;
+
+ error = clk_enable(sc->sc_clk);
+ if (error) {
+ aprint_error_dev(sc->sc_dev, "couldn't enable: %d\n", error);
+ return error;
+ }
+
+ return 0;
+}
+
+static void
+imx6_usb_init(struct imxehci_softc *sc)
+{
+ switch (sc->sc_unit) {
+ case 0: /* OTG controller */
+ init_otg(sc);
+ break;
+ case 1: /* EHCI Host 1 */
+ init_h1(sc);
+ break;
+ case 2: /* EHCI Host 2 */
+ case 3: /* EHCI Host 3 */
+ default:
+ aprint_error_dev(sc->sc_dev, "unit %d not supported\n",
+ sc->sc_unit);
+ }
+}
+
+static void
+init_otg(struct imxehci_softc *sc)
+{
+ struct imxusbc_softc *usbc = sc->sc_usbc;
+ uint32_t v;
+
+ sc->sc_iftype = IMXUSBC_IF_UTMI_WIDE;
+
+ imxehci_reset(sc);
+
+ v = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh_usbnc, USBNC_USB_OTG_CTRL);
+ v |= USBNC_USB_OTG_CTRL_WKUP_VBUS_EN;
+ v |= USBNC_USB_OTG_CTRL_OVER_CUR_DIS;
+ v |= USBNC_USB_OTG_CTRL_PWR_POL;
+ v &= ~USBNC_USB_OTG_CTRL_UTMI_ON_CLOCK;
+ bus_space_write_4(usbc->sc_iot, usbc->sc_ioh_usbnc, USBNC_USB_OTG_CTRL, v);
+}
+
+static void
+init_h1(struct imxehci_softc *sc)
+{
+ struct imxusbc_softc *usbc = sc->sc_usbc;
+ uint32_t v;
+
+ sc->sc_iftype = IMXUSBC_IF_UTMI_WIDE;
+
+ v = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh_usbnc, USBNC_USB_UH1_CTRL);
+ v |= USBNC_USB_UH1_CTRL_OVER_CUR_POL;
+ v |= USBNC_USB_UH1_CTRL_OVER_CUR_DIS;
+ bus_space_write_4(usbc->sc_iot, usbc->sc_ioh_usbnc, USBNC_USB_UH1_CTRL, v);
+
+ /* do reset */
+ imxehci_reset(sc);
+
+ /* set mode */
+ v = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh, USBC_UH1_USBMODE);
+ v &= ~USBC_UH_USBMODE_CM;
+ v |= __SHIFTIN(USBC_UH_USBMODE_CM, USBC_UH_USBMODE_CM_HOST_CONTROLLER);
+ bus_space_write_4(usbc->sc_iot, usbc->sc_ioh, USBC_UH1_USBMODE, v);
+}
+
+static void *
+imx6_usb_intr_establish(struct imxehci_softc *sc)
+{
+ struct imxusbc_fdt_softc *ifsc = (struct imxusbc_fdt_softc *)sc->sc_usbc;
+ ehci_softc_t *hsc = &sc->sc_hsc;
+ void *ih;
+
+ char intrstr[128];
+ if (!fdtbus_intr_str(ifsc->sc_phandle, 0, intrstr, sizeof(intrstr))) {
+ aprint_error_dev(sc->sc_dev, "failed to decode interrupt\n");
+ return NULL;
+ }
+ ih = fdtbus_intr_establish(ifsc->sc_phandle, 0, IPL_USB, 0, ehci_intr, hsc);
+ if (ih == NULL) {
+ aprint_error_dev(sc->sc_dev, "failed to establish interrupt on %s\n",
+ intrstr);
+ return NULL;
+ }
+ aprint_normal_dev(sc->sc_dev, "interrupting on %s\n", intrstr);
+
+ return ih;
+}
Index: src/sys/arch/arm/imx/fdt/imx6_usbphy.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx6_usbphy.c:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/arm/imx/fdt/imx6_usbphy.c Wed Jul 24 13:12:33 2019
@@ -0,0 +1,163 @@
+/* $NetBSD: imx6_usbphy.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $ */
+/*-
+ * Copyright (c) 2019 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * 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: imx6_usbphy.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $");
+
+#include "opt_fdt.h"
+
+#include "locators.h"
+#include "ohci.h"
+#include "ehci.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+
+#include <arm/imx/imx6var.h>
+#include <arm/imx/imx6_reg.h>
+#include <arm/imx/imx6_usbphyreg.h>
+
+#include <dev/fdt/fdtvar.h>
+
+struct imx6_usbphy_softc {
+ device_t sc_dev;
+
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+
+ struct clk *sc_clk;
+};
+
+static int imx6_usbphy_match(device_t, cfdata_t, void *);
+static void imx6_usbphy_attach(device_t, device_t, void *);
+
+static int imx6_usbphy_init_clocks(device_t);
+static int imx6_usbphy_enable(device_t, void *, bool);
+
+CFATTACH_DECL_NEW(imxusbphy, sizeof(struct imx6_usbphy_softc),
+ imx6_usbphy_match, imx6_usbphy_attach, NULL, NULL);
+
+static const char * const compatible[] = {
+ "fsl,imx6q-usbphy",
+ NULL
+};
+
+static int
+imx6_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
+imx6_usbphy_attach(device_t parent, device_t self, void *aux)
+{
+ struct imx6_usbphy_softc *sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ bus_space_tag_t bst = faa->faa_bst;
+ bus_space_handle_t bsh;
+ bus_addr_t addr;
+ bus_size_t size;
+ int error;
+
+ if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get iomux registers\n");
+ return;
+ }
+
+ error = bus_space_map(bst, addr, size, 0, &bsh);
+ if (error) {
+ aprint_error(": couldn't map %#llx: %d", (uint64_t)addr, error);
+ return;
+ }
+
+ sc->sc_clk = fdtbus_clock_get_index(phandle, 0);
+ if (sc->sc_clk == NULL) {
+ aprint_error(": couldn't get clock\n");
+ return;
+ }
+
+ sc->sc_dev = self;
+ sc->sc_iot = bst;
+ sc->sc_ioh = bsh;
+
+ aprint_naive("\n");
+ aprint_normal(": USB PHY\n");
+
+ imx6_usbphy_init_clocks(self);
+ imx6_usbphy_enable(self, NULL, true);
+}
+
+static int
+imx6_usbphy_init_clocks(device_t dev)
+{
+ struct imx6_usbphy_softc * const sc = device_private(dev);
+ int error;
+
+ error = clk_enable(sc->sc_clk);
+ if (error) {
+ aprint_error_dev(sc->sc_dev, "couldn't enable: %d\n", error);
+ return error;
+ }
+
+ return 0;
+}
+
+#define USBPHY_READ(sc, reg) \
+ bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))
+#define USBPHY_WRITE(sc, reg, val) \
+ bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
+
+static int
+imx6_usbphy_enable(device_t dev, void *priv, bool enable)
+{
+ struct imx6_usbphy_softc * const sc = device_private(dev);
+
+ /* USBPHY enable */
+ USBPHY_WRITE(sc, USBPHY_CTRL, USBPHY_CTRL_CLKGATE);
+
+ /* do reset */
+ USBPHY_WRITE(sc, USBPHY_CTRL_SET, USBPHY_CTRL_SFTRST);
+ delay(100);
+
+ /* clear reset, and run clocks */
+ USBPHY_WRITE(sc, USBPHY_CTRL_CLR,
+ USBPHY_CTRL_SFTRST | USBPHY_CTRL_CLKGATE);
+ delay(100);
+
+ /* power on */
+ USBPHY_WRITE(sc, USBPHY_PWD, 0);
+
+ /* UTMI+Level2, Level3 */
+ USBPHY_WRITE(sc, USBPHY_CTRL_SET,
+ USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3);
+
+ return 0;
+}
+
Index: src/sys/arch/evbarm/conf/IMX
diff -u /dev/null src/sys/arch/evbarm/conf/IMX:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/evbarm/conf/IMX Wed Jul 24 13:12:34 2019
@@ -0,0 +1,134 @@
+#
+# $NetBSD: IMX,v 1.1 2019/07/24 13:12:34 hkenken Exp $
+#
+# NXP(Freescale) I.MX family SoCs
+#
+
+include "arch/evbarm/conf/std.imx"
+include "arch/evbarm/conf/files.imx"
+include "arch/evbarm/conf/GENERIC.common"
+
+makeoptions DTSGNUARCH="arm"
+makeoptions DTSSUBDIR="fsl"
+makeoptions DTS="
+ imx6q-hummingboard.dts
+ imx6dl-hummingboard.dts
+ imx6q-hummingboard2.dts
+ imx6dl-hummingboard2.dts
+"
+
+options MULTIPROCESSOR
+
+options CPU_CORTEXA9
+
+options SOC_IMX6Q
+options SOC_IMX6DL
+options SOC_IMX6QDL
+
+pseudo-device openfirm # /dev/openfirm
+
+#options DIAGNOSTIC # internal consistency checks
+#options DEBUG
+#options LOCKDEBUG
+#options PMAP_DEBUG # Enable pmap_debug_level code
+#options IPKDB # remote kernel debugging
+#options VERBOSE_INIT_ARM # verbose bootstrapping messages
+# CONSADDR is required for early init messages from VERBOSE_INIT_ARM.
+options CONSADDR=0x02020000
+options EARLYCONS=imx
+options BOOT_ARGS="\"verbose debug\""
+
+makeoptions DEBUG="-g" # compile full symbol table
+makeoptions COPY_SYMTAB=1
+
+config netbsd root on ? type ?
+
+# Device tree support
+armfdt0 at root
+simplebus* at fdt? pass 0
+
+# CPUs
+cpus* at fdt? pass 0
+cpu* at fdt? pass 0
+
+# Timer
+a9tmr* at fdt? pass 2 # A9 Global Timer
+arma9tmr0 at a9tmr?
+
+# Interrupt controller
+gic* at fdt? pass 1 # ARM Generic Interrupt Controller
+armgic0 at gic?
+
+l2cc* at fdt? pass 1 # ARM Cortex A9 L2 Cache Controller
+arml2cc* at l2cc?
+
+# Clock
+fclock* at fdt? pass 1
+ffclock* at fdt? pass 1
+fregulator* at fdt? pass 5
+gregulator* at fdt? pass 4
+imxccm* at fdt? pass 1 # i.MX6 ccm
+
+# IOMUX
+imxiomux* at fdt? pass 2
+
+# GPC
+imxgpc* at fdt? pass 2
+
+# GPIO
+imxgpio* at fdt? pass 3
+gpio* at gpiobus?
+
+# UART
+imxuart* at fdt?
+options IMXUARTCONSOLE
+
+# Network Interfaces
+enet* at fdt? # FEC
+
+# MII/PHY support
+atphy* at mii? phy ? # Attansic/Atheros PHYs
+ukphy* at mii? phy ? # generic unknown PHYs
+
+# SATA
+ahcisata* at fdt? # SATA
+atabus* at ahcisata? channel ?
+wd* at atabus? drive ?
+
+# ATAPI bus support
+atapibus* at atapi?
+
+# ATAPI devices
+# flags have the same meaning as for IDE drives.
+cd* at atapibus? drive ? flags 0x0000 # ATAPI CD-ROM drives
+sd* at atapibus? drive ? flags 0x0000 # ATAPI disk drives
+st* at atapibus? drive ? flags 0x0000 # ATAPI tape drives
+uk* at atapibus? drive ? flags 0x0000 # ATAPI unknown
+
+# SDMMC
+sdhc* at fdt? # SDMMC
+sdmmc* at sdhc?
+ld* at sdmmc?
+
+# USB
+imxusbphy* at fdt?
+imxusbc* at fdt?
+ehci* at imxusbc?
+usb* at ehci?
+
+# USB device drivers
+include "dev/usb/usbdevices.config"
+
+midi* at midibus?
+
+# PCIe
+imxpcie* at fdt?
+#options PCIVERBOSE
+#options PCI_CONFIG_DUMP
+
+pci* at imxpcie?
+ppb* at pci? dev ? function ?
+pci* at ppb?
+
+cinclude "arch/evbarm/conf/IMX.local"
+
Index: src/sys/arch/evbarm/conf/files.imx
diff -u /dev/null src/sys/arch/evbarm/conf/files.imx:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/evbarm/conf/files.imx Wed Jul 24 13:12:34 2019
@@ -0,0 +1,12 @@
+# $NetBSD: files.imx,v 1.1 2019/07/24 13:12:34 hkenken Exp $
+#
+# NXP(Freescale) i.MX configuration info
+#
+
+include "arch/arm/pic/files.pic"
+include "arch/arm/cortex/files.cortex"
+
+include "arch/evbarm/conf/files.fdt"
+
+include "arch/arm/imx/fdt/files.imx6"
+
Index: src/sys/arch/evbarm/conf/mk.imx
diff -u /dev/null src/sys/arch/evbarm/conf/mk.imx:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/evbarm/conf/mk.imx Wed Jul 24 13:12:34 2019
@@ -0,0 +1,34 @@
+# $NetBSD: mk.imx,v 1.1 2019/07/24 13:12:34 hkenken Exp $
+
+.if !empty(MACHINE_ARCH:M*eb)
+EXTRA_LINKFLAGS+= --be8
+.endif
+
+ENTRYPOINT= generic_start
+
+SYSTEM_FIRST_OBJ= armv6_start.o
+SYSTEM_FIRST_SFILE= ${ARM}/arm/armv6_start.S
+
+_OSRELEASE!= ${HOST_SH} $S/conf/osrelease.sh
+
+MKUBOOTIMAGEARGS= -A arm -T kernel -O linux
+MKUBOOTIMAGEARGS+= -e 0
+MKUBOOTIMAGEARGS+= -n "NetBSD/${BOARDTYPE:U${MACHINE_ARCH}} ${_OSRELEASE}"
+MKUBOOTIMAGEARGS+= -a $(KERNEL_BASE_PHYS) -e $(KERNEL_BASE_PHYS)
+MKUBOOTIMAGEARGS_NONE= ${MKUBOOTIMAGEARGS} -C none
+MKUBOOTIMAGEARGS_GZ= ${MKUBOOTIMAGEARGS} -C gz
+
+SYSTEM_LD_TAIL_EXTRA+=; \
+ echo ${OBJCOPY} -S -O binary $@ [email protected]; \
+ ${OBJCOPY} -S -O binary $@ [email protected]; \
+ echo ${TOOL_MKUBOOTIMAGE} ${MKUBOOTIMAGEARGS_NONE} [email protected] [email protected]; \
+ ${TOOL_MKUBOOTIMAGE} ${MKUBOOTIMAGEARGS_NONE} [email protected] [email protected]; \
+ echo ${TOOL_GZIP} -c [email protected] > [email protected]; \
+ ${TOOL_GZIP} -c [email protected] > [email protected]; \
+ echo ${TOOL_MKUBOOTIMAGE} ${MKUBOOTIMAGEARGS_GZ} [email protected] [email protected]; \
+ ${TOOL_MKUBOOTIMAGE} ${MKUBOOTIMAGEARGS_GZ} [email protected] [email protected]
+
+EXTRA_KERNELS+= ${KERNELS:@.KERNEL.@${.KERNEL.}.bin@}
+EXTRA_KERNELS+= ${KERNELS:@.KERNEL.@${.KERNEL.}.ub@}
+EXTRA_KERNELS+= ${KERNELS:@.KERNEL.@${.KERNEL.}.bin.gz@}
+EXTRA_KERNELS+= ${KERNELS:@.KERNEL.@${.KERNEL.}.gz.ub@}
Index: src/sys/arch/evbarm/conf/std.imx
diff -u /dev/null src/sys/arch/evbarm/conf/std.imx:1.1
--- /dev/null Wed Jul 24 13:12:34 2019
+++ src/sys/arch/evbarm/conf/std.imx Wed Jul 24 13:12:34 2019
@@ -0,0 +1,32 @@
+# $NetBSD: std.imx,v 1.1 2019/07/24 13:12:34 hkenken Exp $
+#
+
+machine evbarm arm
+include "arch/arm/conf/std.arm" # arch standard options
+include "arch/evbarm/conf/std.evbarm"
+
+# Architecture opions
+options ARM_GENERIC_TODR
+options ARM_HAS_VBAR
+options ARM_INTR_IMPL="<arch/arm/fdt/fdt_intr.h>"
+options DRAM_BLOCKS=256
+options EVBARM_BOARDTYPE="evbarm"
+options FDT # Flattened Device Tree support
+options FPU_VFP
+options MODULAR
+options MODULAR_DEFAULT_AUTOLOAD
+options PCI_NETBSD_CONFIGURE
+options TPIDRPRW_IS_CURCPU
+options __BUS_SPACE_HAS_STREAM_METHODS
+options __HAVE_CPU_COUNTER
+options __HAVE_CPU_UAREA_ALLOC_IDLELWP
+options __HAVE_GENERIC_START
+options __HAVE_GENERIC_CPU_INITCLOCKS
+options __HAVE_FAST_SOFTINTS # should be in types.h
+options __HAVE_PCI_CONF_HOOK
+#options __HAVE_PCI_MSI_MSIX
+
+makeoptions BOARDMKFRAG="${THISARM}/conf/mk.imx"
+
+makeoptions KERNEL_BASE_PHYS="0x18000000"
+makeoptions KERNEL_BASE_VIRT="0x80000000"