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, &regsp->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 $@ $@.bin; \
+	${OBJCOPY} -S -O binary $@ $@.bin; \
+	echo ${TOOL_MKUBOOTIMAGE} ${MKUBOOTIMAGEARGS_NONE} $@.bin $@.ub; \
+	${TOOL_MKUBOOTIMAGE} ${MKUBOOTIMAGEARGS_NONE} $@.bin $@.ub; \
+	echo ${TOOL_GZIP} -c $@.bin > $@.bin.gz; \
+	${TOOL_GZIP} -c $@.bin > $@.bin.gz; \
+	echo ${TOOL_MKUBOOTIMAGE} ${MKUBOOTIMAGEARGS_GZ} $@.bin.gz $@.gz.ub; \
+	${TOOL_MKUBOOTIMAGE} ${MKUBOOTIMAGEARGS_GZ} $@.bin.gz $@.gz.ub
+
+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"

Reply via email to