Module Name:    src
Committed By:   jmcneill
Date:           Mon Feb 25 19:30:17 UTC 2019

Modified Files:
        src/sys/arch/arm/amlogic: files.meson meson8b_clkc.c meson_clk.c
            meson_clk.h meson_clk_div.c meson_clk_gate.c meson_clk_mpll.c
            meson_clk_mux.c meson_clk_pll.c meson_dwmac.c meson_pinctrl.c
            meson_pinctrl.h meson_platform.c meson_resets.c meson_usbphy.c
        src/sys/arch/evbarm/conf: GENERIC GENERIC64 files.generic64
        src/sys/external/gpl2/dts/dist/arch/arm64/boot/dts/amlogic:
            meson-gxbb.dtsi
Added Files:
        src/sys/arch/arm/amlogic: mesongx_mmc.c mesongxbb_aoclkc.c
            mesongxbb_aoclkc.h mesongxbb_clkc.c mesongxbb_clkc.h
            mesongxbb_pinctrl.c

Log Message:
Add support for Amlogic S905 (Meson GXBB) SoCs.


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/amlogic/files.meson \
    src/sys/arch/arm/amlogic/meson_platform.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/amlogic/meson8b_clkc.c \
    src/sys/arch/arm/amlogic/meson_clk.h \
    src/sys/arch/arm/amlogic/meson_clk_div.c \
    src/sys/arch/arm/amlogic/meson_dwmac.c \
    src/sys/arch/arm/amlogic/meson_pinctrl.c
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/amlogic/meson_clk.c \
    src/sys/arch/arm/amlogic/meson_clk_gate.c \
    src/sys/arch/arm/amlogic/meson_clk_mpll.c \
    src/sys/arch/arm/amlogic/meson_clk_mux.c \
    src/sys/arch/arm/amlogic/meson_clk_pll.c \
    src/sys/arch/arm/amlogic/meson_pinctrl.h \
    src/sys/arch/arm/amlogic/meson_resets.c \
    src/sys/arch/arm/amlogic/meson_usbphy.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/amlogic/mesongx_mmc.c \
    src/sys/arch/arm/amlogic/mesongxbb_aoclkc.c \
    src/sys/arch/arm/amlogic/mesongxbb_aoclkc.h \
    src/sys/arch/arm/amlogic/mesongxbb_clkc.c \
    src/sys/arch/arm/amlogic/mesongxbb_clkc.h \
    src/sys/arch/arm/amlogic/mesongxbb_pinctrl.c
cvs rdiff -u -r1.22 -r1.23 src/sys/arch/evbarm/conf/GENERIC
cvs rdiff -u -r1.79 -r1.80 src/sys/arch/evbarm/conf/GENERIC64
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/evbarm/conf/files.generic64
cvs rdiff -u -r1.1.1.7 -r1.2 \
    src/sys/external/gpl2/dts/dist/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/amlogic/files.meson
diff -u src/sys/arch/arm/amlogic/files.meson:1.4 src/sys/arch/arm/amlogic/files.meson:1.5
--- src/sys/arch/arm/amlogic/files.meson:1.4	Sun Jan 20 17:58:22 2019
+++ src/sys/arch/arm/amlogic/files.meson	Mon Feb 25 19:30:17 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: files.meson,v 1.4 2019/01/20 17:58:22 jmcneill Exp $
+#	$NetBSD: files.meson,v 1.5 2019/02/25 19:30:17 jmcneill Exp $
 #
 # Configuration info for Amlogic Meson family SoCs
 #
@@ -22,6 +22,16 @@ device	meson8bclkc: meson_clk
 attach	meson8bclkc at fdt with meson8b_clkc
 file	arch/arm/amlogic/meson8b_clkc.c		meson8b_clkc
 
+# Meson GXBB clock controller
+device	gxbbclkc: meson_clk
+attach	gxbbclkc at fdt with mesongxbb_clkc
+file	arch/arm/amlogic/mesongxbb_clkc.c	mesongxbb_clkc
+
+# Meson GXBB AO clock controller
+device	gxbbaoclkc: meson_clk
+attach	gxbbaoclkc at fdt with mesongxbb_aoclkc
+file	arch/arm/amlogic/mesongxbb_aoclkc.c	mesongxbb_aoclkc
+
 # Meson reset controller
 device	mesonresets
 attach	mesonresets at fdt with meson_resets
@@ -33,7 +43,8 @@ attach	mesonuart at fdt with meson_uart
 file	arch/arm/amlogic/meson_uart.c		meson_uart
 
 # Framebuffer console
-attach	genfb at fdt with meson_genfb
+device	mesonfb
+attach	mesonfb at fdt with meson_genfb
 file	arch/arm/amlogic/meson_genfb.c		meson_genfb & soc_meson
 
 # GPIO
@@ -41,17 +52,23 @@ device	mesonpinctrl: gpiobus
 attach	mesonpinctrl at fdt with meson_pinctrl
 file	arch/arm/amlogic/meson_pinctrl.c	meson_pinctrl
 file	arch/arm/amlogic/meson8b_pinctrl.c	meson_pinctrl & soc_meson8b
+file	arch/arm/amlogic/mesongxbb_pinctrl.c	meson_pinctrl & soc_mesongxbb
 
-# SDHC
+# Meson8b SDHC
 device	mesonsdhc: sdmmcbus
 attach	mesonsdhc at fdt with meson_sdhc
 file	arch/arm/amlogic/meson_sdhc.c		meson_sdhc
 
-# SDIO
+# Meson8b SDIO
 device	mesonsdio: sdmmcbus
 attach	mesonsdio at fdt with meson_sdio
 file	arch/arm/amlogic/meson_sdio.c		meson_sdio
 
+# Meson GX MMC
+device	mesongxmmc: sdmmcbus
+attach	mesongxmmc at fdt with mesongx_mmc
+file	arch/arm/amlogic/mesongx_mmc.c		mesongx_mmc 
+
 # USB PHY
 device	mesonusbphy
 attach	mesonusbphy at fdt with meson_usbphy
@@ -79,3 +96,4 @@ file	arch/arm/amlogic/meson_wdt.c		meson
 # SOC parameters
 defflag	opt_soc.h			SOC_MESON
 defflag	opt_soc.h			SOC_MESON8B: SOC_MESON
+defflag	opt_soc.h			SOC_MESONGXBB: SOC_MESON
Index: src/sys/arch/arm/amlogic/meson_platform.c
diff -u src/sys/arch/arm/amlogic/meson_platform.c:1.4 src/sys/arch/arm/amlogic/meson_platform.c:1.5
--- src/sys/arch/arm/amlogic/meson_platform.c:1.4	Thu Jan 31 13:06:10 2019
+++ src/sys/arch/arm/amlogic/meson_platform.c	Mon Feb 25 19:30:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: meson_platform.c,v 1.4 2019/01/31 13:06:10 skrll Exp $ */
+/* $NetBSD: meson_platform.c,v 1.5 2019/02/25 19:30:17 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2019 Jared McNeill <jmcne...@invisible.ca>
@@ -33,7 +33,7 @@
 #include "arml2cc.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: meson_platform.c,v 1.4 2019/01/31 13:06:10 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: meson_platform.c,v 1.5 2019/02/25 19:30:17 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -50,6 +50,7 @@ __KERNEL_RCSID(0, "$NetBSD: meson_platfo
 #include <arm/cpufunc.h>
 
 #include <arm/cortex/a9tmr_var.h>
+#include <arm/cortex/gtmr_var.h>
 #include <arm/cortex/pl310_var.h>
 #include <arm/cortex/scu_reg.h>
 
@@ -64,7 +65,7 @@ __KERNEL_RCSID(0, "$NetBSD: meson_platfo
 
 #define	MESON_CORE_APB3_VBASE	KERNEL_IO_VBASE
 #define	MESON_CORE_APB3_PBASE	0xc0000000
-#define	MESON_CORE_APB3_SIZE	0x01300000
+#define	MESON_CORE_APB3_SIZE	0x01400000
 
 #define MESON_CBUS_OFFSET	0x01100000
 
@@ -84,8 +85,8 @@ __KERNEL_RCSID(0, "$NetBSD: meson_platfo
 #define MESON8B_ARM_SCU_BASE	0x00100000
 
 #define MESON8B_AOBUS_VBASE	(MESON8B_ARM_VBASE + MESON8B_ARM_SIZE)
-#define	MESON8B_AOBUS_PBASE	0xc8100000
-#define MESON8B_AOBUS_SIZE	0x00100000
+#define	MESON8B_AOBUS_PBASE	0xc8000000
+#define MESON8B_AOBUS_SIZE	0x00200000
 
 #define MESON_AOBUS_PWR_CTRL0_REG	0xe0
 #define MESON_AOBUS_PWR_CTRL1_REG	0xe4
@@ -96,7 +97,7 @@ __KERNEL_RCSID(0, "$NetBSD: meson_platfo
 
 #define MESON8B_SRAM_VBASE	(MESON8B_AOBUS_VBASE + MESON8B_AOBUS_SIZE)
 #define MESON8B_SRAM_PBASE	0xd9000000
-#define MESON8B_SRAM_SIZE	0x00010000	/* 0x10000 rounded up */
+#define MESON8B_SRAM_SIZE	0x00200000	/* 0x10000 rounded up */
 
 #define MESON8B_SRAM_CPUCONF_OFFSET		0x1ff80
 #define MESON8B_SRAM_CPUCONF_CTRL_REG		0x00
@@ -183,7 +184,7 @@ meson_platform_device_register(device_t 
 		}
 	}
 
-	if (device_is_a(self, "genfb")) {
+	if (device_is_a(self, "mesonfb")) {
 		int scale, depth;
 
 		if (get_bootconf_option(boot_args, "fb.scale",
@@ -312,7 +313,7 @@ meson_platform_reset(void)
 	}
 }
 
-#if defined(MULTIPROCESSOR)
+#if defined(SOC_MESON8B)
 static void
 meson8b_mpinit_delay(u_int n)
 {
@@ -395,13 +396,11 @@ cpu_enable_meson8b(int phandle)
 }
 
 ARM_CPU_METHOD(meson8b, "amlogic,meson8b-smp", cpu_enable_meson8b);
-#endif
 
 static int
-meson_mpstart(void)
+meson8b_mpstart(void)
 {
 	int ret = 0;
-#ifdef MULTIPROCESSOR
 	const bus_addr_t cbar = armreg_cbar_read();
 	bus_space_tag_t bst = &arm_generic_bs_tag;
 
@@ -429,12 +428,9 @@ meson_mpstart(void)
 	armv7_dcache_wbinv_all();
 
 	ret = arm_fdt_cpu_mpstart();
-#endif
 	return ret;
 }
 
-
-#if defined(SOC_MESON8B)
 static const struct arm_platform meson8b_platform = {
 	.ap_devmap = meson_platform_devmap,
 	.ap_bootstrap = meson8b_platform_bootstrap,
@@ -443,8 +439,23 @@ static const struct arm_platform meson8b
 	.ap_reset = meson_platform_reset,
 	.ap_delay = a9tmr_delay,
 	.ap_uart_freq = meson_platform_uart_freq,
-	.ap_mpstart = meson_mpstart,
+	.ap_mpstart = meson8b_mpstart,
 };
 
 ARM_PLATFORM(meson8b, "amlogic,meson8b", &meson8b_platform);
+#endif	/* SOC_MESON8B */
+
+#if defined(SOC_MESONGXBB)
+static const struct arm_platform mesongxbb_platform = {
+	.ap_devmap = meson_platform_devmap,
+	.ap_bootstrap = meson_platform_bootstrap,
+	.ap_init_attach_args = meson_platform_init_attach_args,
+	.ap_device_register = meson_platform_device_register,
+	.ap_reset = meson_platform_reset,
+	.ap_delay = gtmr_delay,
+	.ap_uart_freq = meson_platform_uart_freq,
+	.ap_mpstart = arm_fdt_cpu_mpstart,
+};
+
+ARM_PLATFORM(mesongxbb, "amlogic,meson-gxbb", &mesongxbb_platform);
 #endif

Index: src/sys/arch/arm/amlogic/meson8b_clkc.c
diff -u src/sys/arch/arm/amlogic/meson8b_clkc.c:1.2 src/sys/arch/arm/amlogic/meson8b_clkc.c:1.3
--- src/sys/arch/arm/amlogic/meson8b_clkc.c:1.2	Sun Jan 20 17:28:34 2019
+++ src/sys/arch/arm/amlogic/meson8b_clkc.c	Mon Feb 25 19:30:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: meson8b_clkc.c,v 1.2 2019/01/20 17:28:34 jmcneill Exp $ */
+/* $NetBSD: meson8b_clkc.c,v 1.3 2019/02/25 19:30:17 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2019 Jared McNeill <jmcne...@invisible.ca>
@@ -28,7 +28,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: meson8b_clkc.c,v 1.2 2019/01/20 17:28:34 jmcneill Exp $");
+__KERNEL_RCSID(1, "$NetBSD: meson8b_clkc.c,v 1.3 2019/02/25 19:30:17 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -99,6 +99,7 @@ meson8b_clkc_pll_sys_set_rate(struct mes
     struct meson_clk_clk *clk, u_int rate)
 {
 	struct clk *clkp, *clkp_parent;
+	int error;
 
 	KASSERT(clk->type == MESON_CLK_PLL);
 
@@ -115,6 +116,8 @@ meson8b_clkc_pll_sys_set_rate(struct mes
 	if (parent_rate == 0)
 		return EIO;
 
+	CLK_LOCK(sc);
+
 	uint32_t cntl0 = CLK_READ(sc, HHI_SYS_CPU_CLK_CNTL0);
 	uint32_t cntl = CLK_READ(sc, HHI_SYS_PLL_CNTL);
 
@@ -130,12 +133,18 @@ meson8b_clkc_pll_sys_set_rate(struct mes
 		new_mul *= 2;
 	}
 
-	if ((cntl0 & HHI_SYS_CPU_CLK_CNTL0_CLKSEL) == 0)
-		return EIO;
-	if (__SHIFTOUT(cntl0, HHI_SYS_CPU_CLK_CNTL0_PLLSEL) != 1)
-		return EIO;
-	if (__SHIFTOUT(cntl0, HHI_SYS_CPU_CLK_CNTL0_SOUTSEL) != 0)
-		return EIO;
+	if ((cntl0 & HHI_SYS_CPU_CLK_CNTL0_CLKSEL) == 0) {
+		error = EIO;
+		goto done;
+	}
+	if (__SHIFTOUT(cntl0, HHI_SYS_CPU_CLK_CNTL0_PLLSEL) != 1) {
+		error = EIO;
+		goto done;
+	}
+	if (__SHIFTOUT(cntl0, HHI_SYS_CPU_CLK_CNTL0_SOUTSEL) != 0) {
+		error = EIO;
+		goto done;
+	}
 
 	cntl &= ~HHI_SYS_PLL_CNTL_MUL;
 	cntl |= __SHIFTIN(new_mul, HHI_SYS_PLL_CNTL_MUL);
@@ -159,7 +168,12 @@ meson8b_clkc_pll_sys_set_rate(struct mes
 		CLK_WRITE(sc, HHI_SYS_CPU_CLK_CNTL0, cntl0);
 	} while ((CLK_READ(sc, HHI_SYS_PLL_CNTL) & HHI_SYS_PLL_CNTL_LOCK) == 0);
 
-	return 0;
+	error = 0;
+
+done:
+	CLK_UNLOCK(sc);
+
+	return error;
 }
 
 static struct meson_clk_clk meson8b_clkc_clks[] = {
@@ -319,10 +333,20 @@ meson8b_clkc_attach(device_t parent, dev
 {
 	struct meson_clk_softc * const sc = device_private(self);
 	struct fdt_attach_args * const faa = aux;
+	bus_addr_t addr;
+	bus_size_t size;
 
 	sc->sc_dev = self;
 	sc->sc_phandle = faa->faa_phandle;
 	sc->sc_bst = faa->faa_bst;
+	if (fdtbus_get_reg(sc->sc_phandle, MESON8B_CLKC_REG_INDEX, &addr, &size) != 0) {
+		aprint_error(": couldn't get registers\n");
+		return;
+	}
+	if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
+		aprint_error(": couldn't map registers\n");
+		return;
+	}
 
 	sc->sc_resets = meson8b_clkc_resets;
 	sc->sc_nresets = __arraycount(meson8b_clkc_resets);
@@ -330,8 +354,7 @@ meson8b_clkc_attach(device_t parent, dev
 	sc->sc_clks = meson8b_clkc_clks;
 	sc->sc_nclks = __arraycount(meson8b_clkc_clks);
 
-	if (meson_clk_attach(sc, MESON8B_CLKC_REG_INDEX) != 0)
-		return;
+	meson_clk_attach(sc);
 
 	aprint_naive("\n");
 	aprint_normal(": Meson8b clock controller\n");
Index: src/sys/arch/arm/amlogic/meson_clk.h
diff -u src/sys/arch/arm/amlogic/meson_clk.h:1.2 src/sys/arch/arm/amlogic/meson_clk.h:1.3
--- src/sys/arch/arm/amlogic/meson_clk.h:1.2	Sun Jan 20 17:28:00 2019
+++ src/sys/arch/arm/amlogic/meson_clk.h	Mon Feb 25 19:30:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: meson_clk.h,v 1.2 2019/01/20 17:28:00 jmcneill Exp $ */
+/* $NetBSD: meson_clk.h,v 1.3 2019/02/25 19:30:17 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017-2019 Jared McNeill <jmcne...@invisible.ca>
@@ -30,6 +30,7 @@
 #define _ARM_MESON_CLK_H
 
 #include <dev/clk/clk_backend.h>
+#include <dev/fdt/syscon.h>
 
 struct meson_clk_softc;
 struct meson_clk_clk;
@@ -338,9 +339,12 @@ struct meson_clk_clk {
 struct meson_clk_softc {
 	device_t		sc_dev;
 	int			sc_phandle;
+
 	bus_space_tag_t		sc_bst;
 	bus_space_handle_t	sc_bsh;
 
+	struct syscon		*sc_syscon;
+
 	struct clk_domain	sc_clkdom;
 
 	struct meson_clk_reset *sc_resets;
@@ -350,14 +354,19 @@ struct meson_clk_softc {
 	u_int			sc_nclks;
 };
 
-int	meson_clk_attach(struct meson_clk_softc *, u_int);
+void	meson_clk_attach(struct meson_clk_softc *);
 struct meson_clk_clk *meson_clk_clock_find(struct meson_clk_softc *,
 					   const char *);
 void	meson_clk_print(struct meson_clk_softc *);
 
-#define CLK_READ(sc, reg)	\
-	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
-#define CLK_WRITE(sc, reg, val)	\
-	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+void	meson_clk_lock(struct meson_clk_softc *);
+void	meson_clk_unlock(struct meson_clk_softc *);
+uint32_t meson_clk_read(struct meson_clk_softc *, bus_size_t);
+void	meson_clk_write(struct meson_clk_softc *, bus_size_t, uint32_t);
+
+#define	CLK_LOCK	meson_clk_lock
+#define	CLK_UNLOCK	meson_clk_unlock
+#define	CLK_READ	meson_clk_read
+#define	CLK_WRITE	meson_clk_write
 
 #endif /* _ARM_MESON_CLK_H */
Index: src/sys/arch/arm/amlogic/meson_clk_div.c
diff -u src/sys/arch/arm/amlogic/meson_clk_div.c:1.2 src/sys/arch/arm/amlogic/meson_clk_div.c:1.3
--- src/sys/arch/arm/amlogic/meson_clk_div.c:1.2	Sun Jan 20 17:27:30 2019
+++ src/sys/arch/arm/amlogic/meson_clk_div.c	Mon Feb 25 19:30:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: meson_clk_div.c,v 1.2 2019/01/20 17:27:30 jmcneill Exp $ */
+/* $NetBSD: meson_clk_div.c,v 1.3 2019/02/25 19:30:17 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017-2019 Jared McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: meson_clk_div.c,v 1.2 2019/01/20 17:27:30 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: meson_clk_div.c,v 1.3 2019/02/25 19:30:17 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -56,7 +56,10 @@ meson_clk_div_get_rate(struct meson_clk_
 	if (rate == 0)
 		return 0;
 
+	CLK_LOCK(sc);
 	val = CLK_READ(sc, div->reg);
+	CLK_UNLOCK(sc);
+
 	if (div->div)
 		ratio = __SHIFTOUT(val, div->div);
 	else
@@ -81,7 +84,7 @@ meson_clk_div_set_rate(struct meson_clk_
 	struct clk *clkp, *clkp_parent;
 	int parent_rate;
 	uint32_t val, raw_div;
-	int ratio;
+	int ratio, error;
 
 	KASSERT(clk->type == MESON_CLK_DIV);
 
@@ -96,28 +99,41 @@ meson_clk_div_set_rate(struct meson_clk_
 	if (div->div == 0)
 		return ENXIO;
 
+	CLK_LOCK(sc);
+
 	val = CLK_READ(sc, div->reg);
 
 	parent_rate = clk_get_rate(clkp_parent);
-	if (parent_rate == 0)
-		return (new_rate == 0) ? 0 : ERANGE;
+	if (parent_rate == 0) {
+		error = (new_rate == 0) ? 0 : ERANGE;
+		goto done;
+	}
 
 	ratio = howmany(parent_rate, new_rate);
 	if ((div->flags & MESON_CLK_DIV_POWER_OF_TWO) != 0) {
-		return EINVAL;
+		error = EINVAL;
+		goto done;
 	} else if ((div->flags & MESON_CLK_DIV_CPU_SCALE_TABLE) != 0) {
-		return EINVAL;
+		error = EINVAL;
+		goto done;
 	} else {
 		raw_div = (ratio > 0) ? ratio - 1 : 0;
 	}
-	if (raw_div > __SHIFTOUT_MASK(div->div))
-		return ERANGE;
+	if (raw_div > __SHIFTOUT_MASK(div->div)) {
+		error = ERANGE;
+		goto done;
+	}
 
 	val &= ~div->div;
 	val |= __SHIFTIN(raw_div, div->div);
 	CLK_WRITE(sc, div->reg, val);
 
-	return 0;
+	error = 0;
+
+done:
+	CLK_UNLOCK(sc);
+
+	return error;
 }
 
 const char *
Index: src/sys/arch/arm/amlogic/meson_dwmac.c
diff -u src/sys/arch/arm/amlogic/meson_dwmac.c:1.2 src/sys/arch/arm/amlogic/meson_dwmac.c:1.3
--- src/sys/arch/arm/amlogic/meson_dwmac.c:1.2	Sat Feb 23 17:18:38 2019
+++ src/sys/arch/arm/amlogic/meson_dwmac.c	Mon Feb 25 19:30:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: meson_dwmac.c,v 1.2 2019/02/23 17:18:38 martin Exp $ */
+/* $NetBSD: meson_dwmac.c,v 1.3 2019/02/25 19:30:17 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
@@ -28,7 +28,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(0, "$NetBSD: meson_dwmac.c,v 1.2 2019/02/23 17:18:38 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: meson_dwmac.c,v 1.3 2019/02/25 19:30:17 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -53,13 +53,13 @@ __KERNEL_RCSID(0, "$NetBSD: meson_dwmac.
 
 static const char * compatible[] = {
 	"amlogic,meson8b-dwmac",
+	"amlogic,meson-gx-dwmac",
 	NULL
 };
 
 static int
 meson_dwmac_reset(const int phandle)
 {
-#if notyet
 	struct fdtbus_gpio_pin *pin_reset;
 	const u_int *reset_delay_us;
 	bool reset_active_low;
@@ -83,7 +83,6 @@ meson_dwmac_reset(const int phandle)
 	delay(be32toh(reset_delay_us[1]));
 	fdtbus_gpio_write(pin_reset, val);
 	delay(be32toh(reset_delay_us[2]));
-#endif
 
 	return 0;
 }
Index: src/sys/arch/arm/amlogic/meson_pinctrl.c
diff -u src/sys/arch/arm/amlogic/meson_pinctrl.c:1.2 src/sys/arch/arm/amlogic/meson_pinctrl.c:1.3
--- src/sys/arch/arm/amlogic/meson_pinctrl.c:1.2	Wed Jan 23 04:21:54 2019
+++ src/sys/arch/arm/amlogic/meson_pinctrl.c	Mon Feb 25 19:30:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: meson_pinctrl.c,v 1.2 2019/01/23 04:21:54 thorpej Exp $ */
+/* $NetBSD: meson_pinctrl.c,v 1.3 2019/02/25 19:30:17 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2019 Jared D. McNeill <jmcne...@invisible.ca>
@@ -29,7 +29,7 @@
 #include "opt_soc.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: meson_pinctrl.c,v 1.2 2019/01/23 04:21:54 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: meson_pinctrl.c,v 1.3 2019/02/25 19:30:17 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -76,6 +76,10 @@ static const struct of_compat_data compa
 	{ "amlogic,meson8b-aobus-pinctrl",	(uintptr_t)&meson8b_aobus_pinctrl_config },
 	{ "amlogic,meson8b-cbus-pinctrl",	(uintptr_t)&meson8b_cbus_pinctrl_config },
 #endif
+#ifdef SOC_MESONGXBB
+	{ "amlogic,meson-gxbb-aobus-pinctrl",	(uintptr_t)&mesongxbb_aobus_pinctrl_config },
+	{ "amlogic,meson-gxbb-periphs-pinctrl",	(uintptr_t)&mesongxbb_periphs_pinctrl_config },
+#endif
 	{ NULL, 0 }
 };
 

Index: src/sys/arch/arm/amlogic/meson_clk.c
diff -u src/sys/arch/arm/amlogic/meson_clk.c:1.1 src/sys/arch/arm/amlogic/meson_clk.c:1.2
--- src/sys/arch/arm/amlogic/meson_clk.c:1.1	Sat Jan 19 20:56:03 2019
+++ src/sys/arch/arm/amlogic/meson_clk.c	Mon Feb 25 19:30:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: meson_clk.c,v 1.1 2019/01/19 20:56:03 jmcneill Exp $ */
+/* $NetBSD: meson_clk.c,v 1.2 2019/02/25 19:30:17 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017-2019 Jared McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: meson_clk.c,v 1.1 2019/01/19 20:56:03 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: meson_clk.c,v 1.2 2019/02/25 19:30:17 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -35,6 +35,7 @@ __KERNEL_RCSID(0, "$NetBSD: meson_clk.c,
 #include <sys/device.h>
 
 #include <dev/fdt/fdtvar.h>
+#include <dev/fdt/syscon.h>
 
 #include <dev/clk/clk_backend.h>
 
@@ -72,8 +73,10 @@ meson_clk_reset_assert(device_t dev, voi
 	struct meson_clk_softc * const sc = device_private(dev);
 	struct meson_clk_reset * const reset = priv;
 
+	CLK_LOCK(sc);
 	const uint32_t val = CLK_READ(sc, reset->reg);
 	CLK_WRITE(sc, reset->reg, val | reset->mask);
+	CLK_UNLOCK(sc);
 
 	return 0;
 }
@@ -84,8 +87,10 @@ meson_clk_reset_deassert(device_t dev, v
 	struct meson_clk_softc * const sc = device_private(dev);
 	struct meson_clk_reset * const reset = priv;
 
+	CLK_LOCK(sc);
 	const uint32_t val = CLK_READ(sc, reset->reg);
 	CLK_WRITE(sc, reset->reg, val & ~reset->mask);
+	CLK_UNLOCK(sc);
 
 	return 0;
 }
@@ -298,22 +303,11 @@ meson_clk_clock_find(struct meson_clk_so
 	return NULL;
 }
 
-int
-meson_clk_attach(struct meson_clk_softc *sc, u_int reg_index)
+void
+meson_clk_attach(struct meson_clk_softc *sc)
 {
-	bus_addr_t addr;
-	bus_size_t size;
 	int i;
 
-	if (fdtbus_get_reg(sc->sc_phandle, reg_index, &addr, &size) != 0) {
-		aprint_error(": couldn't get registers\n");
-		return ENXIO;
-	}
-	if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
-		aprint_error(": couldn't map registers\n");
-		return ENXIO;
-	}
-
 	sc->sc_clkdom.name = device_xname(sc->sc_dev);
 	sc->sc_clkdom.funcs = &meson_clk_clock_funcs;
 	sc->sc_clkdom.priv = sc;
@@ -322,13 +316,13 @@ meson_clk_attach(struct meson_clk_softc 
 		clk_attach(&sc->sc_clks[i].base);
 	}
 
-	fdtbus_register_clock_controller(sc->sc_dev, sc->sc_phandle,
-	    &meson_clk_fdtclock_funcs);
-
-	fdtbus_register_reset_controller(sc->sc_dev, sc->sc_phandle,
-	    &meson_clk_fdtreset_funcs);
-
-	return 0;
+	if (sc->sc_nclks > 0)
+		fdtbus_register_clock_controller(sc->sc_dev, sc->sc_phandle,
+		    &meson_clk_fdtclock_funcs);
+
+	if (sc->sc_nresets > 0)
+		fdtbus_register_reset_controller(sc->sc_dev, sc->sc_phandle,
+		    &meson_clk_fdtreset_funcs);
 }
 
 void
@@ -367,3 +361,35 @@ meson_clk_print(struct meson_clk_softc *
 		aprint_debug("%10u Hz\n", clk_get_rate(&clk->base));
 	}
 }
+
+void
+meson_clk_lock(struct meson_clk_softc *sc)
+{
+	if (sc->sc_syscon != NULL)
+		syscon_lock(sc->sc_syscon);
+}
+
+void
+meson_clk_unlock(struct meson_clk_softc *sc)
+{
+	if (sc->sc_syscon != NULL)
+		syscon_unlock(sc->sc_syscon);
+}
+
+uint32_t
+meson_clk_read(struct meson_clk_softc *sc, bus_size_t reg)
+{
+	if (sc->sc_syscon != NULL)
+		return syscon_read_4(sc->sc_syscon, reg);
+	else
+		return bus_space_read_4(sc->sc_bst, sc->sc_bsh, reg);
+}
+
+void
+meson_clk_write(struct meson_clk_softc *sc, bus_size_t reg, uint32_t val)
+{
+	if (sc->sc_syscon != NULL)
+		syscon_write_4(sc->sc_syscon, reg, val);
+	else
+		bus_space_write_4(sc->sc_bst, sc->sc_bsh, reg, val);
+}
Index: src/sys/arch/arm/amlogic/meson_clk_gate.c
diff -u src/sys/arch/arm/amlogic/meson_clk_gate.c:1.1 src/sys/arch/arm/amlogic/meson_clk_gate.c:1.2
--- src/sys/arch/arm/amlogic/meson_clk_gate.c:1.1	Sat Jan 19 20:56:03 2019
+++ src/sys/arch/arm/amlogic/meson_clk_gate.c	Mon Feb 25 19:30:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: meson_clk_gate.c,v 1.1 2019/01/19 20:56:03 jmcneill Exp $ */
+/* $NetBSD: meson_clk_gate.c,v 1.2 2019/02/25 19:30:17 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017-2019 Jared McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: meson_clk_gate.c,v 1.1 2019/01/19 20:56:03 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: meson_clk_gate.c,v 1.2 2019/02/25 19:30:17 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -48,6 +48,8 @@ meson_clk_gate_enable(struct meson_clk_s
 
 	set = (gate->flags & MESON_CLK_GATE_SET_TO_DISABLE) ? !enable : enable;
 
+	CLK_LOCK(sc);
+
 	val = CLK_READ(sc, gate->reg);
 	if (set)
 		val |= gate->mask;
@@ -55,6 +57,8 @@ meson_clk_gate_enable(struct meson_clk_s
 		val &= ~gate->mask;
 	CLK_WRITE(sc, gate->reg, val);
 
+	CLK_UNLOCK(sc);
+
 	return 0;
 }
 
Index: src/sys/arch/arm/amlogic/meson_clk_mpll.c
diff -u src/sys/arch/arm/amlogic/meson_clk_mpll.c:1.1 src/sys/arch/arm/amlogic/meson_clk_mpll.c:1.2
--- src/sys/arch/arm/amlogic/meson_clk_mpll.c:1.1	Sat Jan 19 20:56:03 2019
+++ src/sys/arch/arm/amlogic/meson_clk_mpll.c	Mon Feb 25 19:30:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: meson_clk_mpll.c,v 1.1 2019/01/19 20:56:03 jmcneill Exp $ */
+/* $NetBSD: meson_clk_mpll.c,v 1.2 2019/02/25 19:30:17 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2019 Jared McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: meson_clk_mpll.c,v 1.1 2019/01/19 20:56:03 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: meson_clk_mpll.c,v 1.2 2019/02/25 19:30:17 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -58,12 +58,16 @@ meson_clk_mpll_get_rate(struct meson_clk
 	if (parent_rate == 0)
 		return 0;
 
+	CLK_LOCK(sc);
+
 	val = CLK_READ(sc, mpll->sdm.reg);
 	sdm = __SHIFTOUT(val, mpll->sdm.mask);
 
 	val = CLK_READ(sc, mpll->n2.reg);
 	n2 = __SHIFTOUT(val, mpll->n2.mask);
 
+	CLK_UNLOCK(sc);
+
 	const uint64_t div = (SDM_DEN * n2) + sdm;
 	if (div == 0)
 		return 0;
Index: src/sys/arch/arm/amlogic/meson_clk_mux.c
diff -u src/sys/arch/arm/amlogic/meson_clk_mux.c:1.1 src/sys/arch/arm/amlogic/meson_clk_mux.c:1.2
--- src/sys/arch/arm/amlogic/meson_clk_mux.c:1.1	Sat Jan 19 20:56:03 2019
+++ src/sys/arch/arm/amlogic/meson_clk_mux.c	Mon Feb 25 19:30:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: meson_clk_mux.c,v 1.1 2019/01/19 20:56:03 jmcneill Exp $ */
+/* $NetBSD: meson_clk_mux.c,v 1.2 2019/02/25 19:30:17 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017-2019 Jared McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: meson_clk_mux.c,v 1.1 2019/01/19 20:56:03 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: meson_clk_mux.c,v 1.2 2019/02/25 19:30:17 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -45,7 +45,10 @@ meson_clk_mux_get_parent(struct meson_cl
 
 	KASSERT(clk->type == MESON_CLK_MUX);
 
+	CLK_LOCK(sc);
 	val = CLK_READ(sc, mux->reg);
+	CLK_UNLOCK(sc);
+
 	sel = __SHIFTOUT(val, mux->sel);
 	if (sel >= mux->nparents)
 		return NULL;
Index: src/sys/arch/arm/amlogic/meson_clk_pll.c
diff -u src/sys/arch/arm/amlogic/meson_clk_pll.c:1.1 src/sys/arch/arm/amlogic/meson_clk_pll.c:1.2
--- src/sys/arch/arm/amlogic/meson_clk_pll.c:1.1	Sat Jan 19 20:56:03 2019
+++ src/sys/arch/arm/amlogic/meson_clk_pll.c	Mon Feb 25 19:30:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: meson_clk_pll.c,v 1.1 2019/01/19 20:56:03 jmcneill Exp $ */
+/* $NetBSD: meson_clk_pll.c,v 1.2 2019/02/25 19:30:17 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2019 Jared McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: meson_clk_pll.c,v 1.1 2019/01/19 20:56:03 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: meson_clk_pll.c,v 1.2 2019/02/25 19:30:17 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -57,6 +57,8 @@ meson_clk_pll_get_rate(struct meson_clk_
 	if (parent_rate == 0)
 		return 0;
 
+	CLK_LOCK(sc);
+
 	val = CLK_READ(sc, pll->n.reg);
 	n = __SHIFTOUT(val, pll->n.mask);
 
@@ -70,6 +72,8 @@ meson_clk_pll_get_rate(struct meson_clk_
 		frac = 0;
 	}
 
+	CLK_UNLOCK(sc);
+
 	rate = parent_rate * m;
 	if (frac) {
 		uint64_t frac_rate = parent_rate * frac;
Index: src/sys/arch/arm/amlogic/meson_pinctrl.h
diff -u src/sys/arch/arm/amlogic/meson_pinctrl.h:1.1 src/sys/arch/arm/amlogic/meson_pinctrl.h:1.2
--- src/sys/arch/arm/amlogic/meson_pinctrl.h:1.1	Sat Jan 19 20:56:03 2019
+++ src/sys/arch/arm/amlogic/meson_pinctrl.h	Mon Feb 25 19:30:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: meson_pinctrl.h,v 1.1 2019/01/19 20:56:03 jmcneill Exp $ */
+/* $NetBSD: meson_pinctrl.h,v 1.2 2019/02/25 19:30:17 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2019 Jared McNeill <jmcne...@invisible.ca>
@@ -78,4 +78,9 @@ extern const struct meson_pinctrl_config
 extern const struct meson_pinctrl_config meson8b_cbus_pinctrl_config;
 #endif
 
+#ifdef SOC_MESONGXBB
+extern const struct meson_pinctrl_config mesongxbb_aobus_pinctrl_config;
+extern const struct meson_pinctrl_config mesongxbb_periphs_pinctrl_config;
+#endif
+
 #endif /* !_MESON_PINCTRL_H */
Index: src/sys/arch/arm/amlogic/meson_resets.c
diff -u src/sys/arch/arm/amlogic/meson_resets.c:1.1 src/sys/arch/arm/amlogic/meson_resets.c:1.2
--- src/sys/arch/arm/amlogic/meson_resets.c:1.1	Sat Jan 19 20:56:03 2019
+++ src/sys/arch/arm/amlogic/meson_resets.c	Mon Feb 25 19:30:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: meson_resets.c,v 1.1 2019/01/19 20:56:03 jmcneill Exp $ */
+/* $NetBSD: meson_resets.c,v 1.2 2019/02/25 19:30:17 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017-2019 Jared McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: meson_resets.c,v 1.1 2019/01/19 20:56:03 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: meson_resets.c,v 1.2 2019/02/25 19:30:17 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -45,6 +45,7 @@ __KERNEL_RCSID(0, "$NetBSD: meson_resets
 
 static const char * compatible[] = {
 	"amlogic,meson8b-reset",
+	"amlogic,meson-gxbb-reset",
 	NULL
 };
 
Index: src/sys/arch/arm/amlogic/meson_usbphy.c
diff -u src/sys/arch/arm/amlogic/meson_usbphy.c:1.1 src/sys/arch/arm/amlogic/meson_usbphy.c:1.2
--- src/sys/arch/arm/amlogic/meson_usbphy.c:1.1	Sat Jan 19 20:56:03 2019
+++ src/sys/arch/arm/amlogic/meson_usbphy.c	Mon Feb 25 19:30:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: meson_usbphy.c,v 1.1 2019/01/19 20:56:03 jmcneill Exp $ */
+/* $NetBSD: meson_usbphy.c,v 1.2 2019/02/25 19:30:17 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2019 Jared McNeill <jmcne...@invisible.ca>
@@ -28,7 +28,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(0, "$NetBSD: meson_usbphy.c,v 1.1 2019/01/19 20:56:03 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: meson_usbphy.c,v 1.2 2019/02/25 19:30:17 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -61,6 +61,7 @@ enum meson_usbphy_type {
 
 static const struct of_compat_data compat_data[] = {
 	{ "amlogic,meson8b-usb2-phy",		USBPHY_MESON8B },
+	{ "amlogic,meson-gxbb-usb2-phy",	USBPHY_MESON8B },
 	{ NULL }
 };
 
@@ -115,9 +116,22 @@ static int
 meson_usbphy_enable(device_t dev, void *priv, bool enable)
 {
 	struct meson_usbphy_softc * const sc = device_private(dev);
+	struct fdtbus_regulator *reg;
 	uint32_t val;
+	int error;
 
 	if (enable) {
+		if (of_hasprop(sc->sc_phandle, "phy-supply")) {
+			reg = fdtbus_regulator_acquire(sc->sc_phandle, "phy-supply");
+			if (reg != NULL) {
+				error = fdtbus_regulator_enable(reg);
+				if (error != 0)
+					device_printf(dev, "WARNING: couldn't enable phy-supply: %d\n", error);
+			} else {
+				device_printf(dev, "WARNING: couldn't acquire phy-supply\n");
+			}
+		}
+
 		delay(1000);
 
 		val = PHY_READ(sc, PREI_USB_PHY_CFG_REG);

Index: src/sys/arch/evbarm/conf/GENERIC
diff -u src/sys/arch/evbarm/conf/GENERIC:1.22 src/sys/arch/evbarm/conf/GENERIC:1.23
--- src/sys/arch/evbarm/conf/GENERIC:1.22	Sun Jan 20 17:58:37 2019
+++ src/sys/arch/evbarm/conf/GENERIC	Mon Feb 25 19:30:17 2019
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: GENERIC,v 1.22 2019/01/20 17:58:37 jmcneill Exp $
+#	$NetBSD: GENERIC,v 1.23 2019/02/25 19:30:17 jmcneill Exp $
 #
 #	GENERIC ARM (aarch32) kernel
 #
@@ -549,7 +549,8 @@ hdmicec*	at hdmicecbus?
 #tegradrm*	at fdt?			# NVIDIA Tegra Display
 #tegrafb*	at tegrafbbus?
 genfb*		at fdt?			# Simple Framebuffer
-wsdisplay*	at genfb?
+mesonfb*	at fdt?			# Amlogic Meson Framebuffer
+wsdisplay*	at wsemuldisplaydev?
 sunxidebe*      at fdt? pass 4  # Display Backend
 genfb*          at sunxidebe?
 sunxitcon*      at fdt? pass 4  # LCD LVDS/RGB controller

Index: src/sys/arch/evbarm/conf/GENERIC64
diff -u src/sys/arch/evbarm/conf/GENERIC64:1.79 src/sys/arch/evbarm/conf/GENERIC64:1.80
--- src/sys/arch/evbarm/conf/GENERIC64:1.79	Fri Feb  8 00:19:57 2019
+++ src/sys/arch/evbarm/conf/GENERIC64	Mon Feb 25 19:30:17 2019
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: GENERIC64,v 1.79 2019/02/08 00:19:57 macallan Exp $
+#	$NetBSD: GENERIC64,v 1.80 2019/02/25 19:30:17 jmcneill Exp $
 #
 #	GENERIC ARM (aarch64) kernel
 #
@@ -14,11 +14,22 @@ include	"arch/evbarm/conf/GENERIC.common
 #
 makeoptions 	DTSARCH="arm aarch64"
 makeoptions	DTSGNUARCH="arm arm64"
-makeoptions	DTSSUBDIR="allwinner broadcom nvidia rockchip"
+makeoptions	DTSSUBDIR="allwinner amlogic broadcom nvidia rockchip"
 makeoptions	DTS="
 	bcm2837-rpi-3-b.dts
 	bcm2837-rpi-3-b-plus.dts
 
+	meson-gxbb-nanopi-k2.dts
+	meson-gxbb-nexbox-a95x.dts
+	meson-gxbb-odroidc2.dts
+	meson-gxbb-p200.dts
+	meson-gxbb-p201.dts
+	meson-gxbb-vega-s95-meta.dts
+	meson-gxbb-vega-s95-pro.dts
+	meson-gxbb-vega-s95-telos.dts
+	meson-gxbb-wetek-hub.dts
+	meson-gxbb-wetek-play2.dts
+
 	rk3328-evb.dts
 	rk3328-roc-cc.dts
 	rk3328-rock64.dts
@@ -60,6 +71,7 @@ options 	CPU_CORTEXA53
 options 	CPU_CORTEXA57
 options 	CPU_THUNDERX
 options 	SOC_BCM2837
+options 	SOC_MESONGXBB
 options 	SOC_RK3328
 options 	SOC_RK3399
 options 	SOC_SUN50I_A64
@@ -80,6 +92,7 @@ options 	VERBOSE_INIT_ARM # verbose boot
 options 	INCLUDE_CONFIG_FILE
 # EARLYCONS is required for early init messages from VERBOSE_INIT_ARM.
 #options 	EARLYCONS=bcm2837
+#options 	EARLYCONS=meson, CONSADDR=0xc81004c0
 #options 	EARLYCONS=rk3328, CONSADDR=0xff130000
 #options 	EARLYCONS=rk3399, CONSADDR=0xff1a0000
 #options 	EARLYCONS=sunxi, CONSADDR=0x01c28000
@@ -185,6 +198,9 @@ tegrapmc*	at fdt? pass 4		# NVIDIA Tegra
 # Clock and Reset controller
 bcmcprman*	at fdt? pass 1		# Broadcom BCM283x Clock Manager
 bcmaux*		at fdt? pass 1		# Broadcom BCM283x Aux Periph Clocks
+gxbbaoclkc*	at fdt? pass 2		# Amlogic Meson GXBB AO clock controller
+gxbbclkc*	at fdt? pass 2		# Amlogic Meson GXBB EE clock controller
+mesonresets*	at fdt? pass 2		# Amlogic Meson misc. clock resets
 rkcru*		at fdt? pass 2		# Rockchip RK3328 CRU
 sun8ih3ccu*	at fdt? pass 2		# Allwinner H3/H5 CCU
 sun8ih3rccu*	at fdt? pass 2		# Allwinner H3/H5 CCU (PRCM)
@@ -200,6 +216,7 @@ tegra210car*	at fdt? pass 3		# NVIDIA Te
 
 # GPIO controller
 bcmgpio*	at fdt?			# Broadcom BCM283x GPIO
+mesonpinctrl*	at fdt? pass 2		# Amlogic Meson GPIO
 plgpio*		at fdt?			# ARM PrimeCell PL061 GPIO
 plgpio*		at acpi?
 sunxigpio*	at fdt? pass 3		# Allwinner GPIO
@@ -268,6 +285,7 @@ ukphy*		at mii? phy ?		# generic unknown
 # UART
 com*		at fdt?	pass 4			# UART
 com*		at acpi?
+mesonuart*	at fdt? pass 4			# Amlogic Meson UART
 plcom*		at fdt?	pass 4			# ARM PL011 UART
 plcom*		at acpi?
 puc*		at pci? dev ? function ?	# PCI "universal" comm. cards
@@ -310,6 +328,7 @@ tegrartc*	at fdt?			# NVIDIA Tegra RTC
 
 # SDMMC
 dwcmmc*		at fdt?			# Designware SD/MMC
+mesongxmmc*	at fdt?			# Amlogic Meson GX eMMC/SD/SDIO controller
 mmcpwrseq*	at fdt?			# Simple MMC power sequence provider
 sdhc*		at fdt?			# SD Host Controller Interface
 sdhost*		at fdt?			# Broadcom BCM283x SD Host Interface
@@ -398,6 +417,7 @@ sunxithermal*	at fdt?			# Allwinner ther
 tegrasoctherm*	at fdt?			# NVIDIA Tegra SOC_THERM
 
 # USB
+mesonusbphy*	at fdt? pass 9		# Amlogic Meson USB2 PHY
 rkusb*		at fdt? pass 9		# Rockchip USB PHY
 rkusbphy*	at rkusb?
 sunxiusbphy*	at fdt? pass 9		# Allwinner USB PHY

Index: src/sys/arch/evbarm/conf/files.generic64
diff -u src/sys/arch/evbarm/conf/files.generic64:1.10 src/sys/arch/evbarm/conf/files.generic64:1.11
--- src/sys/arch/evbarm/conf/files.generic64:1.10	Sun Jan 27 02:08:38 2019
+++ src/sys/arch/evbarm/conf/files.generic64	Mon Feb 25 19:30:17 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: files.generic64,v 1.10 2019/01/27 02:08:38 pgoyette Exp $
+#	$NetBSD: files.generic64,v 1.11 2019/02/25 19:30:17 jmcneill Exp $
 #
 # A generic (aarch64) kernel configuration info
 #
@@ -11,6 +11,7 @@ include "arch/evbarm/conf/files.fdt"
 # Add other board files here
 #
 include "arch/arm/acpi/files.acpi"
+include "arch/arm/amlogic/files.meson"
 include "arch/arm/broadcom/files.bcm2835"
 include "arch/arm/cavium/files.thunderx"
 include "arch/arm/nvidia/files.tegra"

Index: src/sys/external/gpl2/dts/dist/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
diff -u src/sys/external/gpl2/dts/dist/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi:1.1.1.7 src/sys/external/gpl2/dts/dist/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi:1.2
--- src/sys/external/gpl2/dts/dist/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi:1.1.1.7	Tue Jan 22 14:57:03 2019
+++ src/sys/external/gpl2/dts/dist/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi	Mon Feb 25 19:30:17 2019
@@ -280,6 +280,8 @@
 
 &clkc_AO {
 	compatible = "amlogic,meson-gxbb-aoclkc", "amlogic,meson-gx-aoclkc";
+	clocks = <&xtal>, <&clkc CLKID_CLK81>;
+	clock-names = "xtal", "mpeg-clk";
 };
 
 &ethmac {
@@ -311,6 +313,8 @@
 	clkc: clock-controller {
 		compatible = "amlogic,gxbb-clkc";
 		#clock-cells = <1>;
+		clocks = <&xtal>;
+		clock-names = "xtal";
 	};
 };
 

Added files:

Index: src/sys/arch/arm/amlogic/mesongx_mmc.c
diff -u /dev/null src/sys/arch/arm/amlogic/mesongx_mmc.c:1.1
--- /dev/null	Mon Feb 25 19:30:17 2019
+++ src/sys/arch/arm/amlogic/mesongx_mmc.c	Mon Feb 25 19:30:17 2019
@@ -0,0 +1,1044 @@
+/* $NetBSD: mesongx_mmc.c,v 1.1 2019/02/25 19:30:17 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2019 Jared McNeill <jmcne...@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: mesongx_mmc.c,v 1.1 2019/02/25 19:30:17 jmcneill 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 <sys/bitops.h>
+#include <sys/gpio.h>
+
+#include <dev/sdmmc/sdmmcvar.h>
+#include <dev/sdmmc/sdmmcchip.h>
+#include <dev/sdmmc/sdmmc_ioreg.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#define	SD_EMMC_CLOCK			0x00
+#define	 CLOCK_CFG_IRQ_SDIO_SLEEP		__BIT(25)
+#define	 CLOCK_CFG_ALWAYS_ON			__BIT(24)
+#define	 CLOCK_CFG_RX_DELAY			__BITS(23,20)
+#define	 CLOCK_CFG_TX_DELAY			__BITS(19,16)
+#define	 CLOCK_CFG_SRAM_PD			__BITS(15,14)
+#define	 CLOCK_CFG_RX_PHASE			__BITS(13,12)
+#define	 CLOCK_CFG_TX_PHASE			__BITS(11,10)
+#define	 CLOCK_CFG_CO_PHASE			__BITS(9,8)
+#define	 CLOCK_CFG_SRC				__BITS(7,6)
+#define	 CLOCK_CFG_DIV				__BITS(5,0)
+#define	SD_EMMC_DELAY			0x04
+#define	SD_EMMC_ADJUST			0x08
+#define	 ADJUST_ADJ_DELAY			__BITS(21,16)
+#define	 ADJUST_CALI_RISE			__BIT(14)
+#define	 ADJUST_ADJ_ENABLE			__BIT(13)
+#define	 ADJUST_CALI_ENABLE			__BIT(12)
+#define	 ADJUST_CALI_SEL			__BITS(11,8)
+#define	SD_EMMC_CALOUT			0x10
+#define	 CALOUT_CALI_SETUP			__BITS(15,8)
+#define	 CALOUT_CALI_VLD			__BIT(7)
+#define	 CALOUT_CALI_IDX			__BITS(5,0)
+#define	SD_EMMC_START			0x40
+#define	 START_DESC_ADDR			__BITS(31,2)
+#define	 START_DESC_BUSY			__BIT(1)
+#define	 START_DESC_INT				__BIT(0)
+#define	SD_EMMC_CFG			0x44
+#define	 CFG_IP_TXD_ADJ				__BITS(31,28)
+#define	 CFG_ERR_ABORT				__BIT(27)
+#define	 CFG_IRQ_DS				__BIT(26)
+#define	 CFG_TXD_RETRY				__BIT(25)
+#define	 CFG_TXD_ADD_ERR			__BIT(24)
+#define	 CFG_AUTO_CLK				__BIT(23)
+#define	 CFG_STOP_CLK				__BIT(22)
+#define	 CFG_CMD_LOW				__BIT(21)
+#define	 CFG_CHK_DS				__BIT(20)
+#define	 CFG_IGNORE_OWNER			__BIT(19)
+#define	 CFG_SDCLK_ALWAYS_ON			__BIT(18)
+#define	 CFG_BLK_GAP_IP				__BIT(17)
+#define	 CFG_OUT_FALL				__BIT(16)
+#define	 CFG_RC_CC				__BITS(15,12)
+#define	 CFG_RESP_TIMEOUT			__BIT(11,8)
+#define	 CFG_BL_LEN				__BITS(7,4)
+#define	 CFG_DC_UGT				__BIT(3)
+#define	 CFG_DDR				__BIT(2)
+#define	 CFG_BUS_WIDTH				__BITS(1,0)
+#define	  CFG_BUS_WIDTH_1			0
+#define	  CFG_BUS_WIDTH_4			1
+#define	  CFG_BUS_WIDTH_8			2
+#define	SD_EMMC_STATUS			0x48
+#define	 STATUS_CORE_BUSY			__BIT(31)
+#define	 STATUS_DESC_BUSY			__BIT(30)
+#define	 STATUS_BUS_FSM				__BIT(29,26)
+#define	 STATUS_DS				__BIT(25)
+#define	 STATUS_CMD_I				__BIT(24)
+#define	 STATUS_DAT_I				__BITS(23,16)
+#define	 STATUS_IRQ_SDIO			__BIT(15)
+#define	 STATUS_RESP_STATUS			__BIT(14)
+#define	 STATUS_END_OF_CHAIN			__BIT(13)
+#define	 STATUS_DESC_TIMEOUT			__BIT(12)
+#define	 STATUS_RESP_TIMEOUT			__BIT(11)
+#define	 STATUS_RESP_ERR			__BIT(10)
+#define	 STATUS_DESC_ERR			__BIT(9)
+#define	 STATUS_TXD_ERR				__BIT(8)
+#define	 STATUS_RXD_ERR				__BITS(7,0)
+#define	 STATUS_TIMEOUT				(STATUS_DESC_TIMEOUT | STATUS_RESP_TIMEOUT)
+#define	 STATUS_ERROR				(STATUS_RESP_ERR | STATUS_DESC_ERR | STATUS_RXD_ERR | STATUS_TXD_ERR)
+#define	SD_EMMC_IRQ_EN			0x4c
+#define	 IRQ_EN_CFG_SECURE			__BIT(16)
+#define	 IRQ_EN_IRQ_SDIO			__BIT(15)
+#define	 IRQ_EN_RESP_STATUS			__BIT(14)
+#define	 IRQ_EN_END_OF_CHAIN			__BIT(13)
+#define	 IRQ_EN_DESC_TIMEOUT			__BIT(12)
+#define	 IRQ_EN_RESP_TIMEOUT			__BIT(11)
+#define	 IRQ_EN_RESP_ERR			__BIT(10)
+#define	 IRQ_EN_DESC_ERR			__BIT(9)
+#define	 IRQ_EN_TXD_ERR				__BIT(8)
+#define	 IRQ_EN_RXD_ERR				__BITS(7,0)
+#define	SD_EMMC_CMD_CFG			0x50
+#define	SD_EMMC_CMD_ARG			0x54
+#define	SD_EMMC_CMD_DAT			0x58
+#define	SD_EMMC_CMD_RSP			0x5c
+#define	SD_EMMC_CMD_RSP1		0x60
+#define	SD_EMMC_CMD_RSP2		0x64
+#define	SD_EMMC_CMD_RSP3		0x68
+
+struct mesongx_mmc_desc {
+	uint32_t		flags;
+#define	MESONGX_MMC_FLAGS_OWNER		__BIT(31)
+#define	MESONGX_MMC_FLAGS_ERROR		__BIT(30)
+#define	MESONGX_MMC_FLAGS_CMD_INDEX	__BITS(29,24)
+#define	MESONGX_MMC_FLAGS_DATA_NUM	__BIT(23)
+#define	MESONGX_MMC_FLAGS_RESP_NUM	__BIT(22)
+#define	MESONGX_MMC_FLAGS_RESP_128	__BIT(21)
+#define	MESONGX_MMC_FLAGS_RESP_NOCRC	__BIT(20)
+#define	MESONGX_MMC_FLAGS_DATA_WR	__BIT(19)
+#define	MESONGX_MMC_FLAGS_DATA_IO	__BIT(18)
+#define	MESONGX_MMC_FLAGS_NO_CMD	__BIT(17)
+#define	MESONGX_MMC_FLAGS_NO_RESP	__BIT(16)
+#define	MESONGX_MMC_FLAGS_TIMEOUT	__BITS(15,12)
+#define	MESONGX_MMC_FLAGS_END_OF_CHAIN	__BIT(11)
+#define	MESONGX_MMC_FLAGS_R1B		__BIT(10)
+#define	MESONGX_MMC_FLAGS_BLOCK_MODE	__BIT(9)
+#define	MESONGX_MMC_FLAGS_LENGTH	__BITS(8,0)
+	uint32_t		arg;
+	uint32_t		data;
+#define	MESONGX_MMC_DATA_BIG_ENDIAN	__BIT(1)
+#define	MESONGX_MMC_DATA_SRAM		__BIT(0)
+	uint32_t		resp;
+#define	MESONGX_MMC_RESP_SRAM		__BIT(0)
+} __packed;
+
+#define MESONGX_MMC_NDESC		256
+
+struct mesongx_mmc_softc;
+
+static int	mesongx_mmc_match(device_t, cfdata_t, void *);
+static void	mesongx_mmc_attach(device_t, device_t, void *);
+static void	mesongx_mmc_attach_i(device_t);
+
+static int	mesongx_mmc_intr(void *);
+static int	mesongx_mmc_dma_setup(struct mesongx_mmc_softc *);
+static int	mesongx_mmc_dmabounce_setup(struct mesongx_mmc_softc *);
+
+static int	mesongx_mmc_host_reset(sdmmc_chipset_handle_t);
+static uint32_t	mesongx_mmc_host_ocr(sdmmc_chipset_handle_t);
+static int	mesongx_mmc_host_maxblklen(sdmmc_chipset_handle_t);
+static int	mesongx_mmc_card_detect(sdmmc_chipset_handle_t);
+static int	mesongx_mmc_write_protect(sdmmc_chipset_handle_t);
+static int	mesongx_mmc_bus_power(sdmmc_chipset_handle_t, uint32_t);
+static int	mesongx_mmc_bus_clock(sdmmc_chipset_handle_t, int, bool);
+static int	mesongx_mmc_bus_width(sdmmc_chipset_handle_t, int);
+static int	mesongx_mmc_bus_rod(sdmmc_chipset_handle_t, int);
+static int	mesongx_mmc_signal_voltage(sdmmc_chipset_handle_t, int);
+static int	mesongx_mmc_execute_tuning(sdmmc_chipset_handle_t, int);
+static void	mesongx_mmc_exec_command(sdmmc_chipset_handle_t,
+				      struct sdmmc_command *);
+static void	mesongx_mmc_card_enable_intr(sdmmc_chipset_handle_t, int);
+static void	mesongx_mmc_card_intr_ack(sdmmc_chipset_handle_t);
+
+static struct sdmmc_chip_functions mesongx_mmc_chip_functions = {
+	.host_reset = mesongx_mmc_host_reset,
+	.host_ocr = mesongx_mmc_host_ocr,
+	.host_maxblklen = mesongx_mmc_host_maxblklen,
+	.card_detect = mesongx_mmc_card_detect,
+	.write_protect = mesongx_mmc_write_protect,
+	.bus_power = mesongx_mmc_bus_power,
+	.bus_clock_ddr = mesongx_mmc_bus_clock,
+	.bus_width = mesongx_mmc_bus_width,
+	.bus_rod = mesongx_mmc_bus_rod,
+	.signal_voltage = mesongx_mmc_signal_voltage,
+	.execute_tuning = mesongx_mmc_execute_tuning,
+	.exec_command = mesongx_mmc_exec_command,
+	.card_enable_intr = mesongx_mmc_card_enable_intr,
+	.card_intr_ack = mesongx_mmc_card_intr_ack,
+};
+
+struct mesongx_mmc_softc {
+	device_t		sc_dev;
+	bus_space_tag_t		sc_bst;
+	bus_space_handle_t	sc_bsh;
+	bus_dma_tag_t		sc_dmat;
+	int			sc_phandle;
+
+	void			*sc_ih;
+	kmutex_t		sc_intr_lock;
+	kcondvar_t		sc_intr_cv;
+
+	device_t		sc_sdmmc_dev;
+	uint32_t		sc_host_ocr;
+
+	struct sdmmc_command	*sc_cmd;
+
+	bus_dma_segment_t	sc_desc_segs[1];
+	int			sc_desc_nsegs;
+	bus_size_t		sc_desc_size;
+	bus_dmamap_t		sc_desc_map;
+	int			sc_desc_ndesc;
+	void			*sc_desc_desc;
+
+	bus_dmamap_t		sc_dmabounce_map;
+	void			*sc_dmabounce_buf;
+	size_t			sc_dmabounce_buflen;
+
+	struct clk		*sc_clk_core;
+	struct clk		*sc_clk_clkin[2];
+
+	struct fdtbus_reset	*sc_rst;
+
+	struct fdtbus_gpio_pin	*sc_gpio_cd;
+	int			sc_gpio_cd_inverted;
+	struct fdtbus_gpio_pin	*sc_gpio_wp;
+	int			sc_gpio_wp_inverted;
+
+	struct fdtbus_regulator	*sc_reg_vmmc;
+	struct fdtbus_regulator	*sc_reg_vqmmc;
+
+	struct fdtbus_mmc_pwrseq *sc_pwrseq;
+
+	u_int			sc_max_frequency;
+	bool			sc_non_removable;
+	bool			sc_broken_cd;
+};
+
+CFATTACH_DECL_NEW(mesongx_mmc, sizeof(struct mesongx_mmc_softc),
+	mesongx_mmc_match, mesongx_mmc_attach, NULL, NULL);
+
+#define MMC_WRITE(sc, reg, val)	\
+	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+#define MMC_READ(sc, reg) \
+	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
+
+static const struct of_compat_data compat_data[] = {
+	{ "amlogic,meson-gx-mmc",	1 },
+	{ "amlogic,meson-gxbb-mmc",	1 },
+	{ NULL }
+};
+
+static int
+mesongx_mmc_match(device_t parent, cfdata_t cf, void *aux)
+{
+	struct fdt_attach_args * const faa = aux;
+
+	return of_match_compat_data(faa->faa_phandle, compat_data);
+}
+
+static void
+mesongx_mmc_attach(device_t parent, device_t self, void *aux)
+{
+	struct mesongx_mmc_softc * const sc = device_private(self);
+	struct fdt_attach_args * const faa = aux;
+	const int phandle = faa->faa_phandle;
+	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;
+	}
+
+	sc->sc_clk_core = fdtbus_clock_get(phandle, "core");
+	sc->sc_clk_clkin[0] = fdtbus_clock_get(phandle, "clkin0");
+	sc->sc_clk_clkin[1] = fdtbus_clock_get(phandle, "clkin1");
+
+	if (sc->sc_clk_core == NULL || sc->sc_clk_clkin[0] == NULL ||
+	    sc->sc_clk_clkin[1] == NULL) {
+		aprint_error(": couldn't get clocks\n");
+		return;
+	}
+
+	sc->sc_rst = fdtbus_reset_get_index(phandle, 0);
+	if (sc->sc_rst == NULL) {
+		aprint_error(": couldn't get reset\n");
+		return;
+	}
+
+	sc->sc_pwrseq = fdtbus_mmc_pwrseq_get(phandle);
+
+	if (clk_enable(sc->sc_clk_core) != 0) {
+		aprint_error(": couldn't enable core clock\n");
+		return;
+	}
+	if (clk_enable(sc->sc_clk_clkin[0]) != 0 ||
+	    clk_enable(sc->sc_clk_clkin[1]) != 0) {
+		aprint_error(": couldn't enable clkin clocks\n");
+		return;
+	}
+
+	if (fdtbus_reset_deassert(sc->sc_rst) != 0) {
+		aprint_error(": couldn't de-assert reset\n");
+		return;
+	}
+
+	sc->sc_dev = self;
+	sc->sc_phandle = phandle;
+	sc->sc_bst = faa->faa_bst;
+	sc->sc_dmat = faa->faa_dmat;
+	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO);
+	cv_init(&sc->sc_intr_cv, "gxmmcirq");
+
+	if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
+		aprint_error(": couldn't map registers\n");
+		return;
+	}
+
+	aprint_naive("\n");
+	aprint_normal(": eMMC/SD/SDIO controller\n");
+
+	sc->sc_reg_vmmc = fdtbus_regulator_acquire(phandle, "vmmc-supply");
+	sc->sc_reg_vqmmc = fdtbus_regulator_acquire(phandle, "vqmmc-supply");
+
+	sc->sc_gpio_cd = fdtbus_gpio_acquire(phandle, "cd-gpios",
+	    GPIO_PIN_INPUT);
+	sc->sc_gpio_wp = fdtbus_gpio_acquire(phandle, "wp-gpios",
+	    GPIO_PIN_INPUT);
+
+	sc->sc_gpio_cd_inverted = of_hasprop(phandle, "cd-inverted") ? 1 : 0;
+	sc->sc_gpio_wp_inverted = of_hasprop(phandle, "wp-inverted") ? 1 : 0;
+
+	sc->sc_non_removable = of_hasprop(phandle, "non-removable");
+	sc->sc_broken_cd = of_hasprop(phandle, "broken-cd");
+
+	if (of_getprop_uint32(phandle, "max-frequency", &sc->sc_max_frequency))
+		sc->sc_max_frequency = 52000000;
+
+	if (mesongx_mmc_dma_setup(sc) != 0 ||
+	    mesongx_mmc_dmabounce_setup(sc) != 0) {
+		aprint_error_dev(self, "failed to setup DMA\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, FDT_INTR_MPSAFE,
+	    mesongx_mmc_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);
+
+	config_interrupts(self, mesongx_mmc_attach_i);
+}
+
+static int
+mesongx_mmc_dma_setup(struct mesongx_mmc_softc *sc)
+{
+	int error;
+
+	sc->sc_desc_ndesc = MESONGX_MMC_NDESC;
+	sc->sc_desc_size = sizeof(struct mesongx_mmc_desc) *
+	    sc->sc_desc_ndesc;
+	error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_desc_size,
+	    sizeof(struct mesongx_mmc_desc),
+	    sc->sc_desc_size, sc->sc_desc_segs, 1,
+	    &sc->sc_desc_nsegs, BUS_DMA_WAITOK);
+	if (error)
+		return error;
+	error = bus_dmamem_map(sc->sc_dmat, sc->sc_desc_segs,
+	    sc->sc_desc_nsegs, sc->sc_desc_size,
+	    &sc->sc_desc_desc, BUS_DMA_WAITOK);
+	if (error)
+		goto free;
+	error = bus_dmamap_create(sc->sc_dmat, sc->sc_desc_size, 1,
+	    sc->sc_desc_size, 0, BUS_DMA_WAITOK, &sc->sc_desc_map);
+	if (error)
+		goto unmap;
+	error = bus_dmamap_load(sc->sc_dmat, sc->sc_desc_map,
+	    sc->sc_desc_desc, sc->sc_desc_size, NULL, BUS_DMA_WAITOK);
+	if (error)
+		goto destroy;
+	return 0;
+
+destroy:
+	bus_dmamap_destroy(sc->sc_dmat, sc->sc_desc_map);
+unmap:
+	bus_dmamem_unmap(sc->sc_dmat, sc->sc_desc_desc, sc->sc_desc_size);
+free:
+	bus_dmamem_free(sc->sc_dmat, sc->sc_desc_segs, sc->sc_desc_nsegs);
+	return error;
+}
+
+static int
+mesongx_mmc_dmabounce_setup(struct mesongx_mmc_softc *sc)
+{
+	bus_dma_segment_t ds[1];
+	int error, rseg;
+
+	sc->sc_dmabounce_buflen = MAXPHYS;
+	error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_dmabounce_buflen, 0,
+	    sc->sc_dmabounce_buflen, ds, 1, &rseg, BUS_DMA_WAITOK);
+	if (error)
+		return error;
+	error = bus_dmamem_map(sc->sc_dmat, ds, 1, sc->sc_dmabounce_buflen,
+	    &sc->sc_dmabounce_buf, BUS_DMA_WAITOK);
+	if (error)
+		goto free;
+	error = bus_dmamap_create(sc->sc_dmat, sc->sc_dmabounce_buflen, 1,
+	    sc->sc_dmabounce_buflen, 0, BUS_DMA_WAITOK, &sc->sc_dmabounce_map);
+	if (error)
+		goto unmap;
+	error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmabounce_map,
+	    sc->sc_dmabounce_buf, sc->sc_dmabounce_buflen, NULL,
+	    BUS_DMA_WAITOK);
+	if (error)
+		goto destroy;
+	return 0;
+
+destroy:
+	bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmabounce_map);
+unmap:
+	bus_dmamem_unmap(sc->sc_dmat, sc->sc_dmabounce_buf,
+	    sc->sc_dmabounce_buflen);
+free:
+	bus_dmamem_free(sc->sc_dmat, ds, rseg);
+	return error;
+}
+
+static int
+mesongx_mmc_set_clock(struct mesongx_mmc_softc *sc, u_int freq, bool ddr)
+{
+	int best_diff, best_sel, best_div, sel, div;
+	uint32_t val;
+
+	if (freq == 0)
+		freq = SDMMC_SDCLK_400K;
+
+	best_diff = INT_MAX;
+	best_sel = 0;
+	best_div = 0;
+
+	const u_int target_rate = (freq * 1000) >> ddr;
+	for (sel = 0; sel <= 1; sel++) {
+		const u_int parent_rate = clk_get_rate(sc->sc_clk_clkin[sel]);
+		for (div = 1; div <= 63; div++) {
+			const u_int rate = parent_rate / div;
+			if (rate > target_rate)
+				continue;
+			const int diff = target_rate - rate;
+			if (diff < best_diff) {
+				best_diff = diff;
+				best_sel = sel;
+				best_div = div;
+			}
+		}
+	}
+
+	if (best_diff == INT_MAX)
+		return ERANGE;
+
+	val = MMC_READ(sc, SD_EMMC_CLOCK);
+	val |= CLOCK_CFG_ALWAYS_ON;
+	val &= ~CLOCK_CFG_RX_PHASE;
+	val |= __SHIFTIN(0, CLOCK_CFG_RX_PHASE);
+	val &= ~CLOCK_CFG_TX_PHASE;
+	val |= __SHIFTIN(2, CLOCK_CFG_TX_PHASE);
+	val &= ~CLOCK_CFG_CO_PHASE;
+	val |= __SHIFTIN(3, CLOCK_CFG_CO_PHASE);
+	val &= ~CLOCK_CFG_SRC;
+	val |= __SHIFTIN(best_sel, CLOCK_CFG_SRC);
+	val &= ~CLOCK_CFG_DIV;
+	val |= __SHIFTIN(best_div, CLOCK_CFG_DIV);
+	MMC_WRITE(sc, SD_EMMC_CLOCK, val);
+
+	return 0;
+}
+
+static void
+mesongx_mmc_attach_i(device_t self)
+{
+	struct mesongx_mmc_softc * const sc = device_private(self);
+	struct sdmmcbus_attach_args saa;
+	uint32_t width;
+
+	if (sc->sc_pwrseq)
+		fdtbus_mmc_pwrseq_pre_power_on(sc->sc_pwrseq);
+
+	mesongx_mmc_bus_clock(sc, SDMMC_SDCLK_400K, false);
+	mesongx_mmc_host_reset(sc);
+	mesongx_mmc_bus_width(sc, 1);
+
+	if (sc->sc_pwrseq)
+		fdtbus_mmc_pwrseq_post_power_on(sc->sc_pwrseq);
+
+	if (of_getprop_uint32(sc->sc_phandle, "bus-width", &width) != 0)
+		width = 4;
+
+	memset(&saa, 0, sizeof(saa));
+	saa.saa_busname = "sdmmc";
+	saa.saa_sct = &mesongx_mmc_chip_functions;
+	saa.saa_sch = sc;
+	saa.saa_dmat = sc->sc_dmat;
+	saa.saa_clkmin = SDMMC_SDCLK_400K;
+	saa.saa_clkmax = sc->sc_max_frequency / 1000;
+	saa.saa_caps = SMC_CAPS_DMA |
+		       SMC_CAPS_MULTI_SEG_DMA;
+
+	sc->sc_host_ocr = MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V;
+
+	if (of_getprop_bool(sc->sc_phandle, "cap-sd-highspeed")) {
+		saa.saa_caps |= SMC_CAPS_SD_HIGHSPEED;
+		sc->sc_host_ocr |= MMC_OCR_HCS;
+	}
+	if (of_getprop_bool(sc->sc_phandle, "cap-mmc-highspeed"))
+		saa.saa_caps |= SMC_CAPS_MMC_HIGHSPEED;
+
+	if (sc->sc_reg_vqmmc != NULL) {
+		if (of_getprop_bool(sc->sc_phandle, "mmc-ddr-1_8v")) {
+			saa.saa_caps |= SMC_CAPS_MMC_DDR52;
+			sc->sc_host_ocr |= MMC_OCR_S18A;
+		}
+		if (of_getprop_bool(sc->sc_phandle, "mmc-hs200-1_8v")) {
+			saa.saa_caps |= SMC_CAPS_MMC_HS200;
+			sc->sc_host_ocr |= MMC_OCR_S18A;
+		}
+	}
+
+	if (width == 4)
+		saa.saa_caps |= SMC_CAPS_4BIT_MODE;
+	if (width == 8)
+		saa.saa_caps |= SMC_CAPS_8BIT_MODE;
+
+	if (sc->sc_gpio_cd)
+		saa.saa_caps |= SMC_CAPS_POLL_CARD_DET;
+
+	sc->sc_sdmmc_dev = config_found(self, &saa, NULL);
+}
+
+static int
+mesongx_mmc_intr(void *priv)
+{
+	struct mesongx_mmc_softc * const sc = priv;
+	struct sdmmc_command *cmd;
+	int rv = 0;
+
+	mutex_enter(&sc->sc_intr_lock);
+
+	const uint32_t irq_en = MMC_READ(sc, SD_EMMC_IRQ_EN);
+	const uint32_t status = MMC_READ(sc, SD_EMMC_STATUS) & irq_en;
+
+	if ((status & STATUS_IRQ_SDIO) != 0) {
+		rv = 1;
+		sdmmc_card_intr(sc->sc_sdmmc_dev);
+	}
+
+	cmd = sc->sc_cmd;
+	if (cmd == NULL) {
+		device_printf(sc->sc_dev, "WARNING: IRQ with no active command, status %#x\n", status);
+		goto done;
+	}
+
+	if ((status & STATUS_TIMEOUT) != 0) {
+		rv = 1;
+		cmd->c_error = ETIMEDOUT;
+		goto done;
+	}
+
+	if ((status & STATUS_ERROR) != 0) {
+		rv = 1;
+		cmd->c_error = EIO;
+		goto done;
+	}
+
+	if ((status & STATUS_END_OF_CHAIN) != 0 && (cmd->c_flags & SCF_ITSDONE) == 0) {
+		rv = 1;
+		if ((cmd->c_flags & SCF_RSP_PRESENT) != 0) {
+			if (cmd->c_flags & SCF_RSP_136) {
+				cmd->c_resp[0] = MMC_READ(sc, SD_EMMC_CMD_RSP);
+				cmd->c_resp[1] = MMC_READ(sc, SD_EMMC_CMD_RSP1);
+				cmd->c_resp[2] = MMC_READ(sc, SD_EMMC_CMD_RSP2);
+				cmd->c_resp[3] = MMC_READ(sc, SD_EMMC_CMD_RSP3);
+				if (cmd->c_flags & SCF_RSP_CRC) {
+					cmd->c_resp[0] = (cmd->c_resp[0] >> 8) |
+					    (cmd->c_resp[1] << 24);
+					cmd->c_resp[1] = (cmd->c_resp[1] >> 8) |
+					    (cmd->c_resp[2] << 24);
+					cmd->c_resp[2] = (cmd->c_resp[2] >> 8) |
+					    (cmd->c_resp[3] << 24);
+					cmd->c_resp[3] = (cmd->c_resp[3] >> 8);
+				}
+			} else {
+				cmd->c_resp[0] = MMC_READ(sc, SD_EMMC_CMD_RSP);
+			}
+		}
+		cmd->c_flags |= SCF_ITSDONE;
+		cmd->c_error = 0;
+		goto done;
+	}
+
+done:
+	if (rv) {
+		cv_broadcast(&sc->sc_intr_cv);
+		MMC_WRITE(sc, SD_EMMC_STATUS, irq_en);
+	}
+
+	mutex_exit(&sc->sc_intr_lock);
+
+	return rv;
+}
+
+static int
+mesongx_mmc_host_reset(sdmmc_chipset_handle_t sch)
+{
+	struct mesongx_mmc_softc * const sc = sch;
+	uint32_t val;
+
+	MMC_WRITE(sc, SD_EMMC_START, 0);
+
+	val = MMC_READ(sc, SD_EMMC_CFG);
+	val &= ~CFG_RC_CC;
+	val |= __SHIFTIN(ilog2(16), CFG_RC_CC);
+	val |= CFG_SDCLK_ALWAYS_ON;
+	MMC_WRITE(sc, SD_EMMC_CFG, val);
+
+	return 0;
+}
+
+static uint32_t
+mesongx_mmc_host_ocr(sdmmc_chipset_handle_t sch)
+{
+	struct mesongx_mmc_softc * const sc = sch;
+
+	return sc->sc_host_ocr;
+}
+
+static int
+mesongx_mmc_host_maxblklen(sdmmc_chipset_handle_t sch)
+{
+	return 512;
+}
+
+static int
+mesongx_mmc_card_detect(sdmmc_chipset_handle_t sch)
+{
+	struct mesongx_mmc_softc * const sc = sch;
+	int val;
+
+	if (sc->sc_non_removable || sc->sc_broken_cd) {
+		/*
+		 * Non-removable or broken card detect flag set in
+		 * DT, assume always present
+		 */
+		return 1;
+	} else if (sc->sc_gpio_cd != NULL) {
+		val = fdtbus_gpio_read(sc->sc_gpio_cd);
+		if (sc->sc_gpio_cd_inverted)
+			val = !val;
+		return val;
+	} else {
+		return 1;
+	}
+}
+
+static int
+mesongx_mmc_write_protect(sdmmc_chipset_handle_t sch)
+{
+	struct mesongx_mmc_softc * const sc = sch;
+	int val;
+
+	if (sc->sc_gpio_wp != NULL) {
+		val = fdtbus_gpio_read(sc->sc_gpio_wp);
+		if (sc->sc_gpio_wp_inverted)
+			val = !val;
+		return val;
+	}
+
+	return 0;
+}
+
+static int
+mesongx_mmc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
+{
+	return 0;
+}
+
+static int
+mesongx_mmc_bus_clock(sdmmc_chipset_handle_t sch, int freq, bool ddr)
+{
+	struct mesongx_mmc_softc * const sc = sch;
+	uint32_t val;
+	int error;
+
+	error = mesongx_mmc_set_clock(sc, freq, ddr);
+	if (error != 0)
+		return error;
+
+	val = MMC_READ(sc, SD_EMMC_CFG);
+	if (ddr)
+		val |= CFG_DDR; 
+	else
+		val &= ~CFG_DDR;
+	MMC_WRITE(sc, SD_EMMC_CFG, val);
+
+	return 0;
+}
+
+static int
+mesongx_mmc_bus_width(sdmmc_chipset_handle_t sch, int width)
+{
+	struct mesongx_mmc_softc *sc = sch;
+	uint32_t val;
+
+	val = MMC_READ(sc, SD_EMMC_CFG);
+	val &= ~CFG_BUS_WIDTH;
+
+	switch (width) {
+	case 1:
+		val |= __SHIFTIN(CFG_BUS_WIDTH_1, CFG_BUS_WIDTH);
+		break;
+	case 4:
+		val |= __SHIFTIN(CFG_BUS_WIDTH_4, CFG_BUS_WIDTH);
+		break;
+	case 8:
+		val |= __SHIFTIN(CFG_BUS_WIDTH_8, CFG_BUS_WIDTH);
+		break;
+	default:
+		return EINVAL;
+	}
+
+	MMC_WRITE(sc, SD_EMMC_CFG, val);
+
+	return 0;
+}
+
+static int
+mesongx_mmc_bus_rod(sdmmc_chipset_handle_t sch, int on)
+{
+	return -1;
+}
+
+static int
+mesongx_mmc_signal_voltage(sdmmc_chipset_handle_t sch, int signal_voltage)
+{
+	struct mesongx_mmc_softc *sc = sch;
+	u_int uvol;
+	int error;
+
+	if (sc->sc_reg_vqmmc == NULL)
+		return 0;
+
+	switch (signal_voltage) {
+	case SDMMC_SIGNAL_VOLTAGE_330:
+		uvol = 3300000;
+		break;
+	case SDMMC_SIGNAL_VOLTAGE_180:
+		uvol = 1800000;
+		break;
+	default:
+		return EINVAL;
+	}
+
+	error = fdtbus_regulator_supports_voltage(sc->sc_reg_vqmmc, uvol, uvol);
+	if (error != 0)
+		return 0;
+
+	error = fdtbus_regulator_set_voltage(sc->sc_reg_vqmmc, uvol, uvol);
+	if (error != 0)
+		return error;
+
+	return fdtbus_regulator_enable(sc->sc_reg_vqmmc);
+}
+
+static int
+mesongx_mmc_execute_tuning(sdmmc_chipset_handle_t sch, int timing)
+{
+	switch (timing) {
+	case SDMMC_TIMING_MMC_HS200:
+		break;
+	default:
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+mesongx_mmc_dma_prepare(struct mesongx_mmc_softc *sc, struct sdmmc_command *cmd, uint32_t cmdflags)
+{
+	struct mesongx_mmc_desc *dma = sc->sc_desc_desc;
+	bus_dmamap_t map = cmd->c_dmamap;
+	u_int xferlen, blen, resid;
+	bus_size_t off;
+	uint32_t flags;
+	int desc, seg;
+
+	if (cmd->c_blklen > 512) {
+		device_printf(sc->sc_dev, "block length %d not supported\n", cmd->c_blklen);
+		return EINVAL;
+	}
+
+	for (seg = 0; seg < map->dm_nsegs; seg++) {
+		if (map->dm_segs[seg].ds_len % cmd->c_blklen != 0) {
+			/* Force DMA bounce for unaligned transfers */
+			map = NULL;
+			break;
+		}
+	}
+
+	if (map == NULL) {
+		map = sc->sc_dmabounce_map;
+		cmd->c_flags |= SCF_NEED_BOUNCE;
+
+		if ((cmd->c_flags & SCF_CMD_READ) != 0) {
+			memset(sc->sc_dmabounce_buf, 0, cmd->c_datalen);
+			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmabounce_map,
+			    0, cmd->c_datalen, BUS_DMASYNC_PREREAD);
+		} else {
+			memcpy(sc->sc_dmabounce_buf, cmd->c_data, cmd->c_datalen);
+			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmabounce_map,
+			    0, cmd->c_datalen, BUS_DMASYNC_PREWRITE);
+		}
+	}
+
+	desc = 0;
+	for (seg = 0; seg < map->dm_nsegs; seg++) {
+		bus_addr_t paddr = map->dm_segs[seg].ds_addr;
+		bus_size_t len = map->dm_segs[seg].ds_len;
+		resid = uimin(len, cmd->c_resid);
+		off = 0;
+		while (resid > 0) {
+			if (desc == sc->sc_desc_ndesc)
+				break;
+
+			flags = cmdflags;
+
+			if (resid >= cmd->c_blklen) {
+				xferlen = (resid / cmd->c_blklen) * cmd->c_blklen;
+				blen = xferlen / cmd->c_blklen;
+				flags |= MESONGX_MMC_FLAGS_BLOCK_MODE;
+			} else {
+				blen = xferlen = resid;
+			}
+			KASSERT(xferlen > 0);
+			KASSERT(blen <= 512);
+
+			flags |= __SHIFTIN(blen % 512, MESONGX_MMC_FLAGS_LENGTH);
+			if (desc > 0)
+				flags |= MESONGX_MMC_FLAGS_NO_CMD;
+			if (cmd->c_resid == xferlen)
+				flags |= MESONGX_MMC_FLAGS_END_OF_CHAIN;
+
+			dma[desc].flags = htole32(flags);
+			dma[desc].arg = htole32(cmd->c_arg);
+			dma[desc].data = htole32(paddr + off);
+			dma[desc].resp = 0;
+
+			cmd->c_resid -= xferlen;
+			resid -= xferlen;
+			off += xferlen;
+
+			if (cmd->c_resid == 0)
+				break;
+
+			++desc;
+		}
+	}
+	if (desc == sc->sc_desc_ndesc) {
+		device_printf(sc->sc_dev,
+		    "not enough descriptors for %d byte transfer (%d segs)!\n",
+		    cmd->c_datalen, map->dm_nsegs);
+		return EIO;
+	}
+
+	bus_dmamap_sync(sc->sc_dmat, sc->sc_desc_map, 0,
+	    sc->sc_desc_size, BUS_DMASYNC_PREWRITE);
+
+	return 0;
+}
+
+static void
+mesongx_mmc_dma_complete(struct mesongx_mmc_softc *sc, struct sdmmc_command *cmd)
+{
+	bus_dmamap_sync(sc->sc_dmat, sc->sc_desc_map, 0,
+	    sc->sc_desc_size, BUS_DMASYNC_POSTWRITE);
+
+	if ((cmd->c_flags & SCF_NEED_BOUNCE) != 0) {
+		if ((cmd->c_flags & SCF_CMD_READ) != 0) {
+			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmabounce_map,
+			    0, cmd->c_datalen, BUS_DMASYNC_POSTREAD);
+			memcpy(cmd->c_data, sc->sc_dmabounce_buf, cmd->c_datalen);
+		} else {
+			bus_dmamap_sync(sc->sc_dmat, sc->sc_dmabounce_map,
+			    0, cmd->c_datalen, BUS_DMASYNC_POSTWRITE);
+		}
+	}
+}
+
+static void
+mesongx_mmc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
+{
+	struct mesongx_mmc_softc *sc = sch;
+	uint32_t cmdflags, val;
+	int error;
+
+	const uint32_t irq_mask = IRQ_EN_RESP_STATUS |
+				  IRQ_EN_END_OF_CHAIN |
+				  IRQ_EN_DESC_TIMEOUT |
+				  IRQ_EN_RESP_TIMEOUT |
+				  IRQ_EN_RESP_ERR |
+				  IRQ_EN_DESC_ERR |
+				  IRQ_EN_TXD_ERR |
+				  IRQ_EN_RXD_ERR;
+
+	mutex_enter(&sc->sc_intr_lock);
+
+	while (sc->sc_cmd != NULL)
+		cv_wait(&sc->sc_intr_cv, &sc->sc_intr_lock);
+	sc->sc_cmd = cmd;
+
+	MMC_WRITE(sc, SD_EMMC_START, 0);
+	MMC_WRITE(sc, SD_EMMC_STATUS, MMC_READ(sc, SD_EMMC_STATUS));
+
+	val = MMC_READ(sc, SD_EMMC_IRQ_EN);
+	MMC_WRITE(sc, SD_EMMC_IRQ_EN, val | irq_mask);
+
+	cmdflags = MESONGX_MMC_FLAGS_OWNER;
+	cmdflags |= __SHIFTIN(12, MESONGX_MMC_FLAGS_TIMEOUT);	/* 2^12 = 4096 ms timeout */
+	cmdflags |= __SHIFTIN(cmd->c_opcode, MESONGX_MMC_FLAGS_CMD_INDEX);
+
+	if ((cmd->c_flags & SCF_RSP_PRESENT) == 0) {
+		cmdflags |= MESONGX_MMC_FLAGS_NO_RESP;
+	} else {
+		cmdflags |= MESONGX_MMC_FLAGS_RESP_NUM;
+		if ((cmd->c_flags & SCF_RSP_136) != 0)
+			cmdflags |= MESONGX_MMC_FLAGS_RESP_128;
+		if ((cmd->c_flags & SCF_RSP_CRC) == 0)
+			cmdflags |= MESONGX_MMC_FLAGS_RESP_NOCRC;
+		if (__SHIFTOUT(cmd->c_flags, SCF_RSP_MASK) == SCF_RSP_R1B)
+			cmdflags |= MESONGX_MMC_FLAGS_R1B;
+	}
+
+	if (cmd->c_datalen > 0) {
+		cmdflags |= MESONGX_MMC_FLAGS_DATA_IO;
+		if ((cmd->c_flags & SCF_CMD_READ) == 0)
+			cmdflags |= MESONGX_MMC_FLAGS_DATA_WR;
+
+		val = MMC_READ(sc, SD_EMMC_CFG);
+		val &= ~CFG_BL_LEN;
+		val |= __SHIFTIN(ilog2(cmd->c_blklen), CFG_BL_LEN);
+		MMC_WRITE(sc, SD_EMMC_CFG, val);
+
+		cmd->c_resid = cmd->c_datalen;
+		cmd->c_error = mesongx_mmc_dma_prepare(sc, cmd, cmdflags);
+		if (cmd->c_error != 0)
+			goto done;
+
+		const bus_addr_t desc_paddr = sc->sc_desc_map->dm_segs[0].ds_addr;
+		MMC_WRITE(sc, SD_EMMC_START, desc_paddr | START_DESC_BUSY);	/* starts transfer */
+	} else {
+		MMC_WRITE(sc, SD_EMMC_CMD_CFG, cmdflags | MESONGX_MMC_FLAGS_END_OF_CHAIN);
+		MMC_WRITE(sc, SD_EMMC_CMD_DAT, 0);
+		MMC_WRITE(sc, SD_EMMC_CMD_ARG, cmd->c_arg);			/* starts transfer */
+	}
+
+	struct bintime timeout = { .sec = 5, .frac = 0 };
+	const struct bintime epsilon = { .sec = 1, .frac = 0 };
+
+	while ((cmd->c_flags & SCF_ITSDONE) == 0 && cmd->c_error == 0) {
+		error = cv_timedwaitbt(&sc->sc_intr_cv, &sc->sc_intr_lock, &timeout, &epsilon);
+		if (error != 0) {	
+			cmd->c_error = error;
+			goto done;
+		}
+	}
+
+	if (cmd->c_error == 0 && cmd->c_datalen > 0)
+		mesongx_mmc_dma_complete(sc, cmd);
+
+done:
+	MMC_WRITE(sc, SD_EMMC_START, 0);
+
+	val = MMC_READ(sc, SD_EMMC_IRQ_EN);
+	MMC_WRITE(sc, SD_EMMC_IRQ_EN, val & ~irq_mask);
+
+	sc->sc_cmd = NULL;
+	cv_broadcast(&sc->sc_intr_cv);
+
+#ifdef MESONGX_MMC_DEBUG
+	if (cmd->c_error != 0) {
+		for (u_int reg = 0x00; reg < 0x100; reg += 0x10) {
+			device_printf(sc->sc_dev, "      %02x: %08x %08x %08x %08x\n", reg,
+			    MMC_READ(sc, reg + 0),
+			    MMC_READ(sc, reg + 4),
+			    MMC_READ(sc, reg + 8),
+			    MMC_READ(sc, reg + 12));
+		}
+	}
+#endif
+
+	mutex_exit(&sc->sc_intr_lock);
+}
+
+static void
+mesongx_mmc_card_enable_intr(sdmmc_chipset_handle_t sch, int enable)
+{
+	struct mesongx_mmc_softc * const sc = sch;
+	uint32_t val;
+
+	mutex_enter(&sc->sc_intr_lock);
+
+	val = MMC_READ(sc, SD_EMMC_IRQ_EN);
+	MMC_WRITE(sc, SD_EMMC_IRQ_EN, val | IRQ_EN_IRQ_SDIO);
+
+	mutex_exit(&sc->sc_intr_lock);
+}
+
+static void
+mesongx_mmc_card_intr_ack(sdmmc_chipset_handle_t sch)
+{
+	struct mesongx_mmc_softc *sc = sch;
+
+	MMC_WRITE(sc, SD_EMMC_STATUS, STATUS_IRQ_SDIO);
+}
Index: src/sys/arch/arm/amlogic/mesongxbb_aoclkc.c
diff -u /dev/null src/sys/arch/arm/amlogic/mesongxbb_aoclkc.c:1.1
--- /dev/null	Mon Feb 25 19:30:17 2019
+++ src/sys/arch/arm/amlogic/mesongxbb_aoclkc.c	Mon Feb 25 19:30:17 2019
@@ -0,0 +1,110 @@
+/* $NetBSD: mesongxbb_aoclkc.c,v 1.1 2019/02/25 19:30:17 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2019 Jared McNeill <jmcne...@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+__KERNEL_RCSID(1, "$NetBSD: mesongxbb_aoclkc.c,v 1.1 2019/02/25 19:30:17 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <arm/amlogic/meson_clk.h>
+#include <arm/amlogic/mesongxbb_aoclkc.h>
+
+#define	AO_RTI_GEN_CTNL_REG0	0x40
+
+#define	GATE_PARENT		"mpeg-clk"
+
+static int mesongxbb_aoclkc_match(device_t, cfdata_t, void *);
+static void mesongxbb_aoclkc_attach(device_t, device_t, void *);
+
+static const char * const compatible[] = {
+	"amlogic,meson-gxbb-aoclkc",
+	NULL
+};
+
+CFATTACH_DECL_NEW(mesongxbb_aoclkc, sizeof(struct meson_clk_softc),
+	mesongxbb_aoclkc_match, mesongxbb_aoclkc_attach, NULL, NULL);
+
+static struct meson_clk_reset mesongxbb_aoclkc_resets[] = {
+	MESON_CLK_RESET(MESONGXBB_RESET_AO_REMOTE, AO_RTI_GEN_CTNL_REG0, 16),
+	MESON_CLK_RESET(MESONGXBB_RESET_AO_UART1, AO_RTI_GEN_CTNL_REG0, 17),
+	MESON_CLK_RESET(MESONGXBB_RESET_AO_I2C_MASTER, AO_RTI_GEN_CTNL_REG0, 18),
+	MESON_CLK_RESET(MESONGXBB_RESET_AO_I2C_SLAVE, AO_RTI_GEN_CTNL_REG0, 19),
+	MESON_CLK_RESET(MESONGXBB_RESET_AO_UART2, AO_RTI_GEN_CTNL_REG0, 22),
+	MESON_CLK_RESET(MESONGXBB_RESET_AO_IR_BLASTER, AO_RTI_GEN_CTNL_REG0, 23),
+};
+
+static struct meson_clk_clk mesongxbb_aoclkc_clks[] = {
+	MESON_CLK_GATE(MESONGXBB_CLOCK_AO_REMOTE, "remote_ao", GATE_PARENT, AO_RTI_GEN_CTNL_REG0, 0),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_AO_I2C_MASTER, "i2c_master_ao", GATE_PARENT, AO_RTI_GEN_CTNL_REG0, 1),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_AO_I2C_SLAVE, "i2c_slave_ao", GATE_PARENT, AO_RTI_GEN_CTNL_REG0, 2),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_AO_UART1, "uart1_ao", GATE_PARENT, AO_RTI_GEN_CTNL_REG0, 3),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_AO_UART2, "uart2_ao", GATE_PARENT, AO_RTI_GEN_CTNL_REG0, 5),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_AO_IR_BLASTER, "ir_blaster_ao", GATE_PARENT, AO_RTI_GEN_CTNL_REG0, 6),
+};
+
+static int
+mesongxbb_aoclkc_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
+mesongxbb_aoclkc_attach(device_t parent, device_t self, void *aux)
+{
+	struct meson_clk_softc * const sc = device_private(self);
+	struct fdt_attach_args * const faa = aux;
+
+	sc->sc_dev = self;
+	sc->sc_phandle = faa->faa_phandle;
+	sc->sc_syscon = fdtbus_syscon_lookup(OF_parent(sc->sc_phandle));
+	if (sc->sc_syscon == NULL) {
+		aprint_error(": couldn't get syscon registers\n");
+		return;
+	}
+
+	sc->sc_resets = mesongxbb_aoclkc_resets;
+	sc->sc_nresets = __arraycount(mesongxbb_aoclkc_resets);
+
+	sc->sc_clks = mesongxbb_aoclkc_clks;
+	sc->sc_nclks = __arraycount(mesongxbb_aoclkc_clks);
+
+	meson_clk_attach(sc);
+
+	aprint_naive("\n");
+	aprint_normal(": Meson GXBB AO clock controller\n");
+
+	meson_clk_print(sc);
+}
Index: src/sys/arch/arm/amlogic/mesongxbb_aoclkc.h
diff -u /dev/null src/sys/arch/arm/amlogic/mesongxbb_aoclkc.h:1.1
--- /dev/null	Mon Feb 25 19:30:17 2019
+++ src/sys/arch/arm/amlogic/mesongxbb_aoclkc.h	Mon Feb 25 19:30:17 2019
@@ -0,0 +1,47 @@
+/* $NetBSD: mesongxbb_aoclkc.h,v 1.1 2019/02/25 19:30:17 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2019 Jared McNeill <jmcne...@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _MESONGXBB_AOCLKC_H
+#define _MESONGXBB_AOCLKC_H
+
+#define	MESONGXBB_RESET_AO_REMOTE	0
+#define	MESONGXBB_RESET_AO_I2C_MASTER	1
+#define	MESONGXBB_RESET_AO_I2C_SLAVE	2
+#define	MESONGXBB_RESET_AO_UART1	3
+#define	MESONGXBB_RESET_AO_UART2	4
+#define	MESONGXBB_RESET_AO_IR_BLASTER	5
+
+#define	MESONGXBB_CLOCK_AO_REMOTE	0
+#define	MESONGXBB_CLOCK_AO_I2C_MASTER	1
+#define	MESONGXBB_CLOCK_AO_I2C_SLAVE	2
+#define	MESONGXBB_CLOCK_AO_UART1	3
+#define	MESONGXBB_CLOCK_AO_UART2	4
+#define	MESONGXBB_CLOCK_AO_IR_BLASTER	5
+#define	MESONGXBB_CLOCK_CEC_32K		6
+
+#endif /* _MESONGXBB_AOCLKC_H */
Index: src/sys/arch/arm/amlogic/mesongxbb_clkc.c
diff -u /dev/null src/sys/arch/arm/amlogic/mesongxbb_clkc.c:1.1
--- /dev/null	Mon Feb 25 19:30:17 2019
+++ src/sys/arch/arm/amlogic/mesongxbb_clkc.c	Mon Feb 25 19:30:17 2019
@@ -0,0 +1,244 @@
+/* $NetBSD: mesongxbb_clkc.c,v 1.1 2019/02/25 19:30:17 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2019 Jared McNeill <jmcne...@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+__KERNEL_RCSID(1, "$NetBSD: mesongxbb_clkc.c,v 1.1 2019/02/25 19:30:17 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <arm/amlogic/meson_clk.h>
+#include <arm/amlogic/mesongxbb_clkc.h>
+
+#define	CBUS_REG(x)	((x) << 2)
+
+#define	HHI_GCLK_MPEG0		CBUS_REG(0x50)
+#define	HHI_GCLK_MPEG1		CBUS_REG(0x51)
+#define	HHI_GCLK_MPEG2		CBUS_REG(0x52)
+#define	HHI_GCLK_OTHER		CBUS_REG(0x54)
+#define	HHI_SYS_CPU_CLK_CNTL1	CBUS_REG(0x57)
+#define	HHI_MPEG_CLK_CNTL	CBUS_REG(0x5d)
+#define	HHI_NAND_CLK_CNTL	CBUS_REG(0x97)
+#define	HHI_SD_EMMC_CLK_CNTL	CBUS_REG(0x99)
+#define	HHI_MPLL_CNTL		CBUS_REG(0xa0)
+#define	HHI_MPLL_CNTL2		CBUS_REG(0xa1)
+#define	HHI_MPLL_CNTL5		CBUS_REG(0xa4)
+#define	HHI_MPLL_CNTL6		CBUS_REG(0xa5)
+#define	HHI_MPLL_CNTL7		CBUS_REG(0xa6)
+#define	HHI_MPLL_CNTL8		CBUS_REG(0xa7)
+#define	HHI_MPLL_CNTL9		CBUS_REG(0xa8)
+#define	HHI_SYS_PLL_CNTL	CBUS_REG(0xc0)
+#define	 HHI_SYS_PLL_CNTL_LOCK	__BIT(31)
+#define	 HHI_SYS_PLL_CNTL_OD	__BITS(17,16)
+#define	 HHI_SYS_PLL_CNTL_DIV	__BITS(14,9)
+#define	 HHI_SYS_PLL_CNTL_MUL	__BITS(8,0)
+
+static int mesongxbb_clkc_match(device_t, cfdata_t, void *);
+static void mesongxbb_clkc_attach(device_t, device_t, void *);
+
+static const char * const compatible[] = {
+	"amlogic,gxbb-clkc",
+	NULL
+};
+
+CFATTACH_DECL_NEW(mesongxbb_clkc, sizeof(struct meson_clk_softc),
+	mesongxbb_clkc_match, mesongxbb_clkc_attach, NULL, NULL);
+
+static const char *mpeg_sel_parents[] = { "xtal", NULL, "fclk_div7", "mpll1", "mpll2", "fclk_div4", "fclk_div3", "fclk_div5" };
+static const char *sd_emmc_clk0_sel_parents[] = { "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7" };
+
+static struct meson_clk_clk mesongxbb_clkc_clks[] = {
+
+	MESON_CLK_PLL(MESONGXBB_CLOCK_SYS_PLL_DCO, "pll_sys_dco", "xtal",
+	    MESON_CLK_PLL_REG(HHI_SYS_PLL_CNTL, __BIT(30)),	/* enable */
+	    MESON_CLK_PLL_REG(HHI_SYS_PLL_CNTL, __BITS(8,0)),	/* m */
+	    MESON_CLK_PLL_REG(HHI_SYS_PLL_CNTL, __BITS(13,9)),	/* n */
+	    MESON_CLK_PLL_REG_INVALID,				/* frac */
+	    MESON_CLK_PLL_REG(HHI_SYS_PLL_CNTL, __BIT(31)),	/* l */
+	    MESON_CLK_PLL_REG(HHI_SYS_PLL_CNTL, __BIT(29)),	/* reset */
+	    0),
+
+	MESON_CLK_DIV(MESONGXBB_CLOCK_SYS_PLL, "sys_pll", "pll_sys_dco",
+	    HHI_SYS_PLL_CNTL,		/* reg */
+	    __BITS(17,16),		/* div */
+	    MESON_CLK_DIV_POWER_OF_TWO | MESON_CLK_DIV_SET_RATE_PARENT),
+
+	MESON_CLK_PLL(MESONGXBB_CLOCK_FIXED_PLL_DCO, "pll_fixed_dco", "xtal",
+	    MESON_CLK_PLL_REG(HHI_MPLL_CNTL, __BIT(30)),	/* enable */
+	    MESON_CLK_PLL_REG(HHI_MPLL_CNTL, __BITS(8,0)),	/* m */
+	    MESON_CLK_PLL_REG(HHI_MPLL_CNTL, __BITS(13,9)),	/* n */
+	    MESON_CLK_PLL_REG(HHI_MPLL_CNTL2, __BITS(11,0)),	/* frac */
+	    MESON_CLK_PLL_REG(HHI_MPLL_CNTL, __BIT(31)),	/* l */
+	    MESON_CLK_PLL_REG(HHI_MPLL_CNTL, __BIT(29)),	/* reset */
+	    0),
+
+	MESON_CLK_DIV(MESONGXBB_CLOCK_FIXED_PLL, "pll_fixed", "pll_fixed_dco",
+	    HHI_MPLL_CNTL,	/* reg */
+	    __BITS(17,16),	/* div */
+	    MESON_CLK_DIV_POWER_OF_TWO),
+
+	MESON_CLK_DIV(MESONGXBB_CLOCK_MPLL_PREDIV, "mpll_prediv", "pll_fixed",
+	    HHI_MPLL_CNTL5,	/* reg */
+	    __BIT(12),		/* div */
+	    0),
+
+	MESON_CLK_MPLL(MESONGXBB_CLOCK_MPLL0_DIV, "mpll0_div", "mpll_prediv",
+	    MESON_CLK_PLL_REG(HHI_MPLL_CNTL7, __BITS(13,0)),	/* sdm */
+	    MESON_CLK_PLL_REG(HHI_MPLL_CNTL7, __BIT(15)),	/* sdm_enable */
+	    MESON_CLK_PLL_REG(HHI_MPLL_CNTL7, __BITS(24,16)),	/* n2 */
+	    MESON_CLK_PLL_REG(HHI_MPLL_CNTL, __BIT(25)),	/* ssen */
+	    0),
+	MESON_CLK_MPLL(MESONGXBB_CLOCK_MPLL1_DIV, "mpll1_div", "mpll_prediv",
+	    MESON_CLK_PLL_REG(HHI_MPLL_CNTL8, __BITS(13,0)),	/* sdm */
+	    MESON_CLK_PLL_REG(HHI_MPLL_CNTL8, __BIT(15)),	/* sdm_enable */
+	    MESON_CLK_PLL_REG(HHI_MPLL_CNTL8, __BITS(24,16)),	/* n2 */
+	    MESON_CLK_PLL_REG_INVALID,				/* ssen */
+	    0),
+	MESON_CLK_MPLL(MESONGXBB_CLOCK_MPLL2_DIV, "mpll2_div", "mpll_prediv",
+	    MESON_CLK_PLL_REG(HHI_MPLL_CNTL8, __BITS(13,0)),	/* sdm */
+	    MESON_CLK_PLL_REG(HHI_MPLL_CNTL8, __BIT(15)),	/* sdm_enable */
+	    MESON_CLK_PLL_REG(HHI_MPLL_CNTL8, __BITS(24,16)),	/* n2 */
+	    MESON_CLK_PLL_REG_INVALID,				/* ssen */
+	    0),
+
+	MESON_CLK_GATE(MESONGXBB_CLOCK_MPLL0, "mpll0", "mpll0_div", HHI_MPLL_CNTL7, 14),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_MPLL1, "mpll1", "mpll1_div", HHI_MPLL_CNTL8, 14),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_MPLL2, "mpll2", "mpll2_div", HHI_MPLL_CNTL9, 14),
+
+	MESON_CLK_FIXED_FACTOR(MESONGXBB_CLOCK_FCLK_DIV2_DIV, "fclk_div2_div", "pll_fixed", 2, 1),
+	MESON_CLK_FIXED_FACTOR(MESONGXBB_CLOCK_FCLK_DIV3_DIV, "fclk_div3_div", "pll_fixed", 3, 1),
+	MESON_CLK_FIXED_FACTOR(MESONGXBB_CLOCK_FCLK_DIV4_DIV, "fclk_div4_div", "pll_fixed", 4, 1),
+	MESON_CLK_FIXED_FACTOR(MESONGXBB_CLOCK_FCLK_DIV5_DIV, "fclk_div5_div", "pll_fixed", 5, 1),
+	MESON_CLK_FIXED_FACTOR(MESONGXBB_CLOCK_FCLK_DIV7_DIV, "fclk_div7_div", "pll_fixed", 7, 1),
+
+	MESON_CLK_GATE(MESONGXBB_CLOCK_FCLK_DIV2, "fclk_div2", "fclk_div2_div", HHI_MPLL_CNTL6, 27),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_FCLK_DIV3, "fclk_div3", "fclk_div3_div", HHI_MPLL_CNTL6, 28),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_FCLK_DIV4, "fclk_div4", "fclk_div4_div", HHI_MPLL_CNTL6, 29),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_FCLK_DIV5, "fclk_div5", "fclk_div5_div", HHI_MPLL_CNTL6, 30),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_FCLK_DIV7, "fclk_div7", "fclk_div7_div", HHI_MPLL_CNTL6, 31),
+	MESON_CLK_MUX(MESONGXBB_CLOCK_MPEG_SEL, "mpeg_sel", mpeg_sel_parents,
+	    HHI_MPEG_CLK_CNTL,	/* reg */
+	    __BITS(14,12),	/* sel */
+	    0),
+
+	MESON_CLK_DIV(MESONGXBB_CLOCK_MPEG_DIV, "mpeg_div", "mpeg_sel",
+	    HHI_MPEG_CLK_CNTL,	/* reg */
+	    __BITS(6,0),	/* div */
+	    0),
+
+	MESON_CLK_MUX(MESONGXBB_CLOCK_SD_EMMC_A_CLK0_SEL, "sd_emmc_a_clk0_sel", sd_emmc_clk0_sel_parents,
+	    HHI_SD_EMMC_CLK_CNTL,	/* reg */
+	    __BITS(11,9),		/* sel */
+	    0),
+	MESON_CLK_MUX(MESONGXBB_CLOCK_SD_EMMC_B_CLK0_SEL, "sd_emmc_b_clk0_sel", sd_emmc_clk0_sel_parents,
+	    HHI_SD_EMMC_CLK_CNTL,	/* reg */
+	    __BITS(27,25),		/* sel */
+	    0),
+	MESON_CLK_MUX(MESONGXBB_CLOCK_SD_EMMC_C_CLK0_SEL, "sd_emmc_c_clk0_sel", sd_emmc_clk0_sel_parents,
+	    HHI_NAND_CLK_CNTL,		/* reg */
+	    __BITS(11,9),		/* sel */
+	    0),
+
+	MESON_CLK_DIV(MESONGXBB_CLOCK_SD_EMMC_A_CLK0_DIV, "sd_emmc_a_clk0_div", "sd_emmc_a_clk0_sel",
+	    HHI_SD_EMMC_CLK_CNTL,	/* reg */
+	    __BITS(6,0),		/* div */
+	    0),
+	MESON_CLK_DIV(MESONGXBB_CLOCK_SD_EMMC_B_CLK0_DIV, "sd_emmc_b_clk0_div", "sd_emmc_b_clk0_sel",
+	    HHI_SD_EMMC_CLK_CNTL,	/* reg */
+	    __BITS(22,16),		/* div */
+	    0),
+	MESON_CLK_DIV(MESONGXBB_CLOCK_SD_EMMC_C_CLK0_DIV, "sd_emmc_c_clk0_div", "sd_emmc_c_clk0_sel",
+	    HHI_NAND_CLK_CNTL,		/* reg */
+	    __BITS(6,0),		/* div */
+	    0),
+
+	MESON_CLK_GATE(MESONGXBB_CLOCK_SD_EMMC_A_CLK0, "sd_emmc_a_clk0", "sd_emmc_a_clk0_div", HHI_SD_EMMC_CLK_CNTL, 7),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_SD_EMMC_B_CLK0, "sd_emmc_b_clk0", "sd_emmc_b_clk0_div", HHI_SD_EMMC_CLK_CNTL, 23),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_SD_EMMC_C_CLK0, "sd_emmc_c_clk0", "sd_emmc_c_clk0_div", HHI_NAND_CLK_CNTL, 7),
+
+	MESON_CLK_GATE(MESONGXBB_CLOCK_CLK81, "clk81", "mpeg_div", HHI_MPEG_CLK_CNTL, 7),
+
+	MESON_CLK_GATE(MESONGXBB_CLOCK_I2C, "i2c", "clk81", HHI_GCLK_MPEG0, 9),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_SAR_ADC, "sar_adc", "clk81", HHI_GCLK_MPEG0, 10),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_RNG0, "rng0", "clk81", HHI_GCLK_MPEG0, 12),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_UART0, "uart0", "clk81", HHI_GCLK_MPEG0, 13),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_SDHC, "sdhc", "clk81", HHI_GCLK_MPEG0, 14),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_SDIO, "sdio", "clk81", HHI_GCLK_MPEG0, 17),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_SD_EMMC_A, "sd_emmc_a", "clk81", HHI_GCLK_MPEG0, 24),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_SD_EMMC_B, "sd_emmc_b", "clk81", HHI_GCLK_MPEG0, 25),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_SD_EMMC_C, "sd_emmc_c", "clk81", HHI_GCLK_MPEG0, 26),
+
+	MESON_CLK_GATE(MESONGXBB_CLOCK_ETH, "eth", "clk81", HHI_GCLK_MPEG1, 3),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_UART1, "uart1", "clk81", HHI_GCLK_MPEG1, 16),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_USB0, "usb0", "clk81", HHI_GCLK_MPEG1, 21),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_USB1, "usb1", "clk81", HHI_GCLK_MPEG1, 22),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_USB, "usb", "clk81", HHI_GCLK_MPEG1, 26),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_EFUSE, "efuse", "clk81", HHI_GCLK_MPEG1, 30),
+
+	MESON_CLK_GATE(MESONGXBB_CLOCK_USB1_DDR_BRIDGE, "usb1_ddr_bridge", "clk81", HHI_GCLK_MPEG2, 8),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_USB0_DDR_BRIDGE, "usb0_ddr_bridge", "clk81", HHI_GCLK_MPEG2, 9),
+	MESON_CLK_GATE(MESONGXBB_CLOCK_UART2, "uart2", "clk81", HHI_GCLK_MPEG2, 15),
+};
+
+static int
+mesongxbb_clkc_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
+mesongxbb_clkc_attach(device_t parent, device_t self, void *aux)
+{
+	struct meson_clk_softc * const sc = device_private(self);
+	struct fdt_attach_args * const faa = aux;
+
+	sc->sc_dev = self;
+	sc->sc_phandle = faa->faa_phandle;
+	sc->sc_syscon = fdtbus_syscon_lookup(OF_parent(sc->sc_phandle));
+	if (sc->sc_syscon == NULL) {
+		aprint_error(": couldn't get syscon registers\n");
+		return;
+	}
+
+	sc->sc_clks = mesongxbb_clkc_clks;
+	sc->sc_nclks = __arraycount(mesongxbb_clkc_clks);
+
+	meson_clk_attach(sc);
+
+	aprint_naive("\n");
+	aprint_normal(": Meson GXBB clock controller\n");
+
+	meson_clk_print(sc);
+}
Index: src/sys/arch/arm/amlogic/mesongxbb_clkc.h
diff -u /dev/null src/sys/arch/arm/amlogic/mesongxbb_clkc.h:1.1
--- /dev/null	Mon Feb 25 19:30:17 2019
+++ src/sys/arch/arm/amlogic/mesongxbb_clkc.h	Mon Feb 25 19:30:17 2019
@@ -0,0 +1,198 @@
+/* $NetBSD: mesongxbb_clkc.h,v 1.1 2019/02/25 19:30:17 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2019 Jared McNeill <jmcne...@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _MESONGXBB_CLKC_H
+#define _MESONGXBB_CLKC_H
+
+#define	MESONGXBB_CLOCK_SYS_PLL				0
+#define	MESONGXBB_CLOCK_HDMI_PLL			2
+#define	MESONGXBB_CLOCK_FIXED_PLL			3
+#define	MESONGXBB_CLOCK_FCLK_DIV2			4
+#define	MESONGXBB_CLOCK_FCLK_DIV3			5
+#define	MESONGXBB_CLOCK_FCLK_DIV4			6
+#define	MESONGXBB_CLOCK_FCLK_DIV5			7
+#define	MESONGXBB_CLOCK_FCLK_DIV7			8
+#define	MESONGXBB_CLOCK_GP0_PLL				9
+#define	MESONGXBB_CLOCK_MPEG_SEL			10
+#define	MESONGXBB_CLOCK_MPEG_DIV			11
+#define	MESONGXBB_CLOCK_CLK81				12
+#define	MESONGXBB_CLOCK_MPLL0				13
+#define	MESONGXBB_CLOCK_MPLL1				14
+#define	MESONGXBB_CLOCK_MPLL2				15
+#define	MESONGXBB_CLOCK_DDR				16
+#define	MESONGXBB_CLOCK_DOS				17
+#define	MESONGXBB_CLOCK_ISA				18
+#define	MESONGXBB_CLOCK_PL301				19
+#define	MESONGXBB_CLOCK_PERIPHS				20
+#define	MESONGXBB_CLOCK_SPICC				21
+#define	MESONGXBB_CLOCK_I2C				22
+#define	MESONGXBB_CLOCK_SAR_ADC				23
+#define	MESONGXBB_CLOCK_SMART_CARD			24
+#define	MESONGXBB_CLOCK_RNG0				25
+#define	MESONGXBB_CLOCK_UART0				26
+#define	MESONGXBB_CLOCK_SDHC				27
+#define	MESONGXBB_CLOCK_STREAM				28
+#define	MESONGXBB_CLOCK_ASYNC_FIFO			29
+#define	MESONGXBB_CLOCK_SDIO				30
+#define	MESONGXBB_CLOCK_ABUF				31
+#define	MESONGXBB_CLOCK_HIU_IFACE			32
+#define	MESONGXBB_CLOCK_ASSIST_MISC			33
+#define	MESONGXBB_CLOCK_SPI				34
+#define	MESONGXBB_CLOCK_I2S_SPDIF			35
+#define	MESONGXBB_CLOCK_ETH				36
+#define	MESONGXBB_CLOCK_DEMUX				37
+#define	MESONGXBB_CLOCK_AIU_GLUE			38
+#define	MESONGXBB_CLOCK_IEC958				39
+#define	MESONGXBB_CLOCK_I2S_OUT				40
+#define	MESONGXBB_CLOCK_AMCLK				41
+#define	MESONGXBB_CLOCK_AIFIFO2				42
+#define	MESONGXBB_CLOCK_MIXER				43
+#define	MESONGXBB_CLOCK_MIXER_IFACE			44
+#define	MESONGXBB_CLOCK_ADC				45
+#define	MESONGXBB_CLOCK_BLKMV				46
+#define	MESONGXBB_CLOCK_AIU				47
+#define	MESONGXBB_CLOCK_UART1				48
+#define	MESONGXBB_CLOCK_G2D				49
+#define	MESONGXBB_CLOCK_USB0				50
+#define	MESONGXBB_CLOCK_USB1				51
+#define	MESONGXBB_CLOCK_RESET				52
+#define	MESONGXBB_CLOCK_NAND				53
+#define	MESONGXBB_CLOCK_DOS_PARSER			54
+#define	MESONGXBB_CLOCK_USB				55
+#define	MESONGXBB_CLOCK_VDIN1				56
+#define	MESONGXBB_CLOCK_AHB_ARB0			57
+#define	MESONGXBB_CLOCK_EFUSE				58
+#define	MESONGXBB_CLOCK_BOOT_ROM			59
+#define	MESONGXBB_CLOCK_AHB_DATA_BUS			60
+#define	MESONGXBB_CLOCK_AHB_CTRL_BUS			61
+#define	MESONGXBB_CLOCK_HDMI_INTR_SYNC			62
+#define	MESONGXBB_CLOCK_HDMI_PCLK			63
+#define	MESONGXBB_CLOCK_USB1_DDR_BRIDGE			64
+#define	MESONGXBB_CLOCK_USB0_DDR_BRIDGE			65
+#define	MESONGXBB_CLOCK_MMC_PCLK			66
+#define	MESONGXBB_CLOCK_DVIN				67
+#define	MESONGXBB_CLOCK_UART2				68
+#define	MESONGXBB_CLOCK_SANA				69
+#define	MESONGXBB_CLOCK_VPU_INTR			70
+#define	MESONGXBB_CLOCK_SEC_AHB_AHB3_BRIDGE		71
+#define	MESONGXBB_CLOCK_CLK81_A53			72
+#define	MESONGXBB_CLOCK_VCLK2_VENCI0			73
+#define	MESONGXBB_CLOCK_VCLK2_VENCI1			74
+#define	MESONGXBB_CLOCK_VCLK2_VENCP0			75
+#define	MESONGXBB_CLOCK_VCLK2_VENCP1			76
+#define	MESONGXBB_CLOCK_GCLK_VENCI_INT0			77
+#define	MESONGXBB_CLOCK_GCLK_VENCI_INT			78
+#define	MESONGXBB_CLOCK_DAC_CLK				79
+#define	MESONGXBB_CLOCK_AOCLK_GATE			80
+#define	MESONGXBB_CLOCK_IEC958_GATE			81
+#define	MESONGXBB_CLOCK_ENC480P				82
+#define	MESONGXBB_CLOCK_RNG1				83
+#define	MESONGXBB_CLOCK_GCLK_VENCI_INT1			84
+#define	MESONGXBB_CLOCK_VCLK2_VENCLMCC			85
+#define	MESONGXBB_CLOCK_VCLK2_VENCL			86
+#define	MESONGXBB_CLOCK_VCLK_OTHER			87
+#define	MESONGXBB_CLOCK_EDP				88
+#define	MESONGXBB_CLOCK_AO_MEDIA_CPU			89
+#define	MESONGXBB_CLOCK_AO_AHB_SRAM			90
+#define	MESONGXBB_CLOCK_AO_AHB_BUS			91
+#define	MESONGXBB_CLOCK_AO_IFACE			92
+#define	MESONGXBB_CLOCK_AO_I2C				93
+#define	MESONGXBB_CLOCK_SD_EMMC_A			94
+#define	MESONGXBB_CLOCK_SD_EMMC_B			95
+#define	MESONGXBB_CLOCK_SD_EMMC_C			96
+#define	MESONGXBB_CLOCK_SAR_ADC_CLK			97
+#define	MESONGXBB_CLOCK_SAR_ADC_SEL			98
+#define	MESONGXBB_CLOCK_SAR_ADC_DIV			99
+#define	MESONGXBB_CLOCK_MALI_0_SEL			100
+#define	MESONGXBB_CLOCK_MALI_0_DIV			101
+#define	MESONGXBB_CLOCK_MALI_0				102
+#define	MESONGXBB_CLOCK_MALI_1_SEL			103
+#define	MESONGXBB_CLOCK_MALI_1_DIV			104
+#define	MESONGXBB_CLOCK_MALI_1				105
+#define	MESONGXBB_CLOCK_MALI				106
+#define	MESONGXBB_CLOCK_CTS_AMCLK			107
+#define	MESONGXBB_CLOCK_CTS_AMCLK_SEL			108
+#define	MESONGXBB_CLOCK_CTS_AMCLK_DIV			109
+#define	MESONGXBB_CLOCK_CTS_MCLK_I958			110
+#define	MESONGXBB_CLOCK_CTS_MCLK_I958_SEL		111
+#define	MESONGXBB_CLOCK_CTS_MCLK_I958_DIV		112
+#define	MESONGXBB_CLOCK_CTS_I958			113
+#define	MESONGXBB_CLOCK_32K_CLK				114
+#define	MESONGXBB_CLOCK_32K_CLK_SEL			115
+#define	MESONGXBB_CLOCK_32K_CLK_DIV			116
+#define	MESONGXBB_CLOCK_SD_EMMC_A_CLK0_SEL		117
+#define	MESONGXBB_CLOCK_SD_EMMC_A_CLK0_DIV		118
+#define	MESONGXBB_CLOCK_SD_EMMC_A_CLK0			119
+#define	MESONGXBB_CLOCK_SD_EMMC_B_CLK0_SEL		120
+#define	MESONGXBB_CLOCK_SD_EMMC_B_CLK0_DIV		121
+#define	MESONGXBB_CLOCK_SD_EMMC_B_CLK0			122
+#define	MESONGXBB_CLOCK_SD_EMMC_C_CLK0_SEL		123
+#define	MESONGXBB_CLOCK_SD_EMMC_C_CLK0_DIV		124
+#define	MESONGXBB_CLOCK_SD_EMMC_C_CLK0			125
+#define	MESONGXBB_CLOCK_VPU_0_SEL			126
+#define	MESONGXBB_CLOCK_VPU_0_DIV			127
+#define	MESONGXBB_CLOCK_VPU_0				128
+#define	MESONGXBB_CLOCK_VPU_1_SEL			129
+#define	MESONGXBB_CLOCK_VPU_1_DIV			130
+#define	MESONGXBB_CLOCK_VPU_1				131
+#define	MESONGXBB_CLOCK_VPU				132
+#define	MESONGXBB_CLOCK_VAPB_0_SEL			133
+#define	MESONGXBB_CLOCK_VAPB_0_DIV			134
+#define	MESONGXBB_CLOCK_VAPB_0				135
+#define	MESONGXBB_CLOCK_VAPB_1_SEL			136
+#define	MESONGXBB_CLOCK_VAPB_1_DIV			137
+#define	MESONGXBB_CLOCK_VAPB_1				138
+#define	MESONGXBB_CLOCK_VAPB_SEL			139
+#define	MESONGXBB_CLOCK_VAPB				140
+#define	MESONGXBB_CLOCK_HDMI_PLL_PRE_MULT		141
+#define	MESONGXBB_CLOCK_MPLL0_DIV			142
+#define	MESONGXBB_CLOCK_MPLL1_DIV			143
+#define	MESONGXBB_CLOCK_MPLL2_DIV			144
+#define	MESONGXBB_CLOCK_MPLL_PREDIV			145
+#define	MESONGXBB_CLOCK_FCLK_DIV2_DIV			146
+#define	MESONGXBB_CLOCK_FCLK_DIV3_DIV			147
+#define	MESONGXBB_CLOCK_FCLK_DIV4_DIV			148
+#define	MESONGXBB_CLOCK_FCLK_DIV5_DIV			149
+#define	MESONGXBB_CLOCK_FCLK_DIV7_DIV			150
+#define	MESONGXBB_CLOCK_VDEC_1_SEL			151
+#define	MESONGXBB_CLOCK_VDEC_1_DIV			152
+#define	MESONGXBB_CLOCK_VDEC_1				153
+#define	MESONGXBB_CLOCK_VDEC_HEVC_SEL			154
+#define	MESONGXBB_CLOCK_VDEC_HEVC_DIV			155
+#define	MESONGXBB_CLOCK_VDEC_HEVC			156
+#define	MESONGXBB_CLOCK_GEN_CLK_SEL			157
+#define	MESONGXBB_CLOCK_GEN_CLK_DIV			158
+#define	MESONGXBB_CLOCK_GEN_CLK				159
+#define	MESONGXBB_CLOCK_FIXED_PLL_DCO			160
+#define	MESONGXBB_CLOCK_HDMI_PLL_DCO			161
+#define	MESONGXBB_CLOCK_HDMI_PLL_OD			162
+#define	MESONGXBB_CLOCK_HDMI_PLL_OD2			163
+#define	MESONGXBB_CLOCK_SYS_PLL_DCO			164
+#define	MESONGXBB_CLOCK_GP0_PLL_DCO			165
+
+#endif /* _MESONGXBB_CLKC_H */
Index: src/sys/arch/arm/amlogic/mesongxbb_pinctrl.c
diff -u /dev/null src/sys/arch/arm/amlogic/mesongxbb_pinctrl.c:1.1
--- /dev/null	Mon Feb 25 19:30:17 2019
+++ src/sys/arch/arm/amlogic/mesongxbb_pinctrl.c	Mon Feb 25 19:30:17 2019
@@ -0,0 +1,519 @@
+/* $NetBSD: mesongxbb_pinctrl.c,v 1.1 2019/02/25 19:30:17 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2019 Jared McNeill <jmcne...@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: mesongxbb_pinctrl.c,v 1.1 2019/02/25 19:30:17 jmcneill Exp $");
+
+#include <sys/param.h>
+
+#include <arm/amlogic/meson_pinctrl.h>
+
+/* CBUS pinmux registers */
+#define	CBUS_REG(n)	((n) << 2)
+#define	REG0		CBUS_REG(0)
+#define	REG1		CBUS_REG(1)
+#define	REG2		CBUS_REG(2)
+#define	REG3		CBUS_REG(3)
+#define	REG4		CBUS_REG(4)
+#define	REG5		CBUS_REG(5)
+#define	REG6		CBUS_REG(6)
+#define	REG7		CBUS_REG(7)
+#define	REG8		CBUS_REG(8)
+#define	REG9		CBUS_REG(9)
+
+/* AO pinmux registers */
+#define	AOREG0		0x00
+#define	AOREG1		0x04
+
+/*
+ * GPIO banks. The values must match those in dt-bindings/gpio/meson-gxbb-gpio.h
+ */
+enum {
+	GPIOZ_0 = 0,
+	GPIOZ_1,
+	GPIOZ_2,
+	GPIOZ_3,
+	GPIOZ_4,
+	GPIOZ_5,
+	GPIOZ_6,
+	GPIOZ_7,
+	GPIOZ_8,
+	GPIOZ_9,
+	GPIOZ_10,
+	GPIOZ_11,
+	GPIOZ_12,
+	GPIOZ_13,
+	GPIOZ_14,
+	GPIOZ_15,
+
+	GPIOH_0 = 16,
+	GPIOH_1,
+	GPIOH_2,
+	GPIOH_3,
+
+	BOOT_0 = 20,
+	BOOT_1,
+	BOOT_2,
+	BOOT_3,
+	BOOT_4,
+	BOOT_5,
+	BOOT_6,
+	BOOT_7,
+	BOOT_8,
+	BOOT_9,
+	BOOT_10,
+	BOOT_11,
+	BOOT_12,
+	BOOT_13,
+	BOOT_14,
+	BOOT_15,
+	BOOT_16,
+	BOOT_17,
+
+	CARD_0 = 38,
+	CARD_1,
+	CARD_2,
+	CARD_3,
+	CARD_4,
+	CARD_5,
+	CARD_6,
+
+	GPIODV_0 = 45,
+	GPIODV_1,
+	GPIODV_2,
+	GPIODV_3,
+	GPIODV_4,
+	GPIODV_5,
+	GPIODV_6,
+	GPIODV_7,
+	GPIODV_8,
+	GPIODV_9,
+	GPIODV_10,
+	GPIODV_11,
+	GPIODV_12,
+	GPIODV_13,
+	GPIODV_14,
+	GPIODV_15,
+	GPIODV_16,
+	GPIODV_17,
+	GPIODV_18,
+	GPIODV_19,
+	GPIODV_20,
+	GPIODV_21,
+	GPIODV_22,
+	GPIODV_23,
+	GPIODV_24,
+	GPIODV_25,
+	GPIODV_26,
+	GPIODV_27,
+	GPIODV_28,
+	GPIODV_29,
+
+	GPIOY_0 = 75,
+	GPIOY_1,
+	GPIOY_2,
+	GPIOY_3,
+	GPIOY_4,
+	GPIOY_5,
+	GPIOY_6,
+	GPIOY_7,
+	GPIOY_8,
+	GPIOY_9,
+	GPIOY_10,
+	GPIOY_11,
+	GPIOY_12,
+	GPIOY_13,
+	GPIOY_14,
+	GPIOY_15,
+	GPIOY_16,
+
+	GPIOX_0 = 92,
+	GPIOX_1,
+	GPIOX_2,
+	GPIOX_3,
+	GPIOX_4,
+	GPIOX_5,
+	GPIOX_6,
+	GPIOX_7,
+	GPIOX_8,
+	GPIOX_9,
+	GPIOX_10,
+	GPIOX_11,
+	GPIOX_12,
+	GPIOX_13,
+	GPIOX_14,
+	GPIOX_15,
+	GPIOX_16,
+	GPIOX_17,
+	GPIOX_18,
+	GPIOX_19,
+	GPIOX_20,
+	GPIOX_21,
+	GPIOX_22,
+
+	GPIOCLK_0 = 115,
+	GPIOCLK_1,
+	GPIOCLK_2,
+	GPIOCLK_3,
+
+	GPIOAO_0 = 0,
+	GPIOAO_1,
+	GPIOAO_2,
+	GPIOAO_3,
+	GPIOAO_4,
+	GPIOAO_5,
+	GPIOAO_6,
+	GPIOAO_7,
+	GPIOAO_8,
+	GPIOAO_9,
+	GPIOAO_10,
+	GPIOAO_11,
+	GPIOAO_12,
+	GPIOAO_13,
+	GPIO_TEST_N,
+};
+
+#define	CBUS_GPIO(_id, _off, _bit)	\
+	[_id] = {							\
+		.id = (_id),						\
+		.name = __STRING(_id),					\
+		.oen = {						\
+			.type = MESON_PINCTRL_REGTYPE_GPIO,		\
+			.reg = CBUS_REG((_off) * 3 + 0),		\
+			.mask = __BIT(_bit)				\
+		},							\
+		.out = {						\
+			.type = MESON_PINCTRL_REGTYPE_GPIO,		\
+			.reg = CBUS_REG((_off) * 3 + 1),		\
+			.mask = __BIT(_bit)				\
+		},							\
+		.in = {							\
+			.type = MESON_PINCTRL_REGTYPE_GPIO,		\
+			.reg = CBUS_REG((_off) * 3 + 2),		\
+			.mask = __BIT(_bit)				\
+		},							\
+		.pupden = {						\
+			.type = MESON_PINCTRL_REGTYPE_PULL_ENABLE,	\
+			.reg = CBUS_REG(_off),				\
+			.mask = __BIT(_bit)				\
+		},							\
+		.pupd = {						\
+			.type = MESON_PINCTRL_REGTYPE_PULL,		\
+			.reg = CBUS_REG(_off),				\
+			.mask = __BIT(_bit)				\
+		},							\
+	}
+
+static const struct meson_pinctrl_gpio mesongxbb_periphs_gpios[] = {
+	/* GPIODV */
+	CBUS_GPIO(GPIODV_0, 0, 0),
+	CBUS_GPIO(GPIODV_1, 0, 1),
+	CBUS_GPIO(GPIODV_2, 0, 2),
+	CBUS_GPIO(GPIODV_3, 0, 3),
+	CBUS_GPIO(GPIODV_4, 0, 4),
+	CBUS_GPIO(GPIODV_5, 0, 5),
+	CBUS_GPIO(GPIODV_6, 0, 6),
+	CBUS_GPIO(GPIODV_7, 0, 7),
+	CBUS_GPIO(GPIODV_8, 0, 8),
+	CBUS_GPIO(GPIODV_9, 0, 9),
+	CBUS_GPIO(GPIODV_10, 0, 10),
+	CBUS_GPIO(GPIODV_11, 0, 11),
+	CBUS_GPIO(GPIODV_12, 0, 12),
+	CBUS_GPIO(GPIODV_13, 0, 13),
+	CBUS_GPIO(GPIODV_14, 0, 14),
+	CBUS_GPIO(GPIODV_15, 0, 15),
+	CBUS_GPIO(GPIODV_16, 0, 16),
+	CBUS_GPIO(GPIODV_17, 0, 17),
+	CBUS_GPIO(GPIODV_18, 0, 18),
+	CBUS_GPIO(GPIODV_19, 0, 19),
+	CBUS_GPIO(GPIODV_20, 0, 20),
+	CBUS_GPIO(GPIODV_21, 0, 21),
+	CBUS_GPIO(GPIODV_22, 0, 22),
+
+	/* GPIOH */
+	CBUS_GPIO(GPIOH_0, 1, 0),
+	CBUS_GPIO(GPIOH_1, 1, 1),
+	CBUS_GPIO(GPIOH_2, 1, 2),
+	CBUS_GPIO(GPIOH_3, 1, 3),
+
+	/* BOOT */
+	CBUS_GPIO(BOOT_0, 2, 0),
+	CBUS_GPIO(BOOT_1, 2, 1),
+	CBUS_GPIO(BOOT_2, 2, 2),
+	CBUS_GPIO(BOOT_3, 2, 3),
+	CBUS_GPIO(BOOT_4, 2, 4),
+	CBUS_GPIO(BOOT_5, 2, 5),
+	CBUS_GPIO(BOOT_6, 2, 6),
+	CBUS_GPIO(BOOT_7, 2, 7),
+	CBUS_GPIO(BOOT_8, 2, 8),
+	CBUS_GPIO(BOOT_9, 2, 9),
+	CBUS_GPIO(BOOT_10, 2, 10),
+	CBUS_GPIO(BOOT_11, 2, 11),
+	CBUS_GPIO(BOOT_12, 2, 12),
+	CBUS_GPIO(BOOT_13, 2, 13),
+	CBUS_GPIO(BOOT_14, 2, 14),
+	CBUS_GPIO(BOOT_15, 2, 15),
+	CBUS_GPIO(BOOT_16, 2, 16),
+	CBUS_GPIO(BOOT_17, 2, 17),
+
+	/* CARD */
+	CBUS_GPIO(CARD_0, 2, 20),
+	CBUS_GPIO(CARD_1, 2, 21),
+	CBUS_GPIO(CARD_2, 2, 22),
+	CBUS_GPIO(CARD_3, 2, 23),
+	CBUS_GPIO(CARD_4, 2, 24),
+	CBUS_GPIO(CARD_5, 2, 25),
+	CBUS_GPIO(CARD_6, 2, 26),
+
+	/* CARD */
+	CBUS_GPIO(GPIOCLK_0, 3, 28),
+	CBUS_GPIO(GPIOCLK_1, 3, 29),
+	CBUS_GPIO(GPIOCLK_2, 3, 30),
+	CBUS_GPIO(GPIOCLK_3, 3, 31),
+
+	/* GPIOX */
+	CBUS_GPIO(GPIOX_0, 4, 0),
+	CBUS_GPIO(GPIOX_1, 4, 1),
+	CBUS_GPIO(GPIOX_2, 4, 2),
+	CBUS_GPIO(GPIOX_3, 4, 3),
+	CBUS_GPIO(GPIOX_4, 4, 4),
+	CBUS_GPIO(GPIOX_5, 4, 5),
+	CBUS_GPIO(GPIOX_6, 4, 6),
+	CBUS_GPIO(GPIOX_7, 4, 7),
+	CBUS_GPIO(GPIOX_8, 4, 8),
+	CBUS_GPIO(GPIOX_9, 4, 9),
+	CBUS_GPIO(GPIOX_10, 4, 10),
+	CBUS_GPIO(GPIOX_11, 4, 11),
+	CBUS_GPIO(GPIOX_12, 4, 12),
+	CBUS_GPIO(GPIOX_13, 4, 13),
+	CBUS_GPIO(GPIOX_14, 4, 14),
+	CBUS_GPIO(GPIOX_15, 4, 15),
+	CBUS_GPIO(GPIOX_16, 4, 16),
+	CBUS_GPIO(GPIOX_17, 4, 17),
+	CBUS_GPIO(GPIOX_18, 4, 18),
+	CBUS_GPIO(GPIOX_19, 4, 19),
+	CBUS_GPIO(GPIOX_20, 4, 20),
+	CBUS_GPIO(GPIOX_21, 4, 21),
+	CBUS_GPIO(GPIOX_22, 4, 22),
+};
+
+#define	AO_GPIO(_id, _bit)						\
+	[_id] = {							\
+		.id = (_id),						\
+		.name = __STRING(_id),					\
+		.oen = {						\
+			.type = MESON_PINCTRL_REGTYPE_GPIO,		\
+			.reg = 0,					\
+			.mask = __BIT(_bit)				\
+		},							\
+		.out = {						\
+			.type = MESON_PINCTRL_REGTYPE_GPIO,		\
+			.reg = 0,					\
+			.mask = __BIT(_bit + 16)			\
+		},							\
+		.in = {							\
+			.type = MESON_PINCTRL_REGTYPE_GPIO,		\
+			.reg = 4,					\
+			.mask = __BIT(_bit)				\
+		},							\
+		.pupden = {						\
+			.type = MESON_PINCTRL_REGTYPE_PULL,		\
+			.reg = 0,					\
+			.mask = __BIT(_bit)				\
+		},							\
+		.pupd = {						\
+			.type = MESON_PINCTRL_REGTYPE_PULL,		\
+			.reg = 0,					\
+			.mask = __BIT(_bit + 16)			\
+		},							\
+	}
+
+static const struct meson_pinctrl_gpio mesongxbb_aobus_gpios[] = {
+	/* GPIOAO */
+	AO_GPIO(GPIOAO_0, 0),
+	AO_GPIO(GPIOAO_1, 1),
+	AO_GPIO(GPIOAO_2, 2),
+	AO_GPIO(GPIOAO_3, 3),
+	AO_GPIO(GPIOAO_4, 4),
+	AO_GPIO(GPIOAO_5, 5),
+	AO_GPIO(GPIOAO_6, 6),
+	AO_GPIO(GPIOAO_7, 7),
+	AO_GPIO(GPIOAO_8, 8),
+	AO_GPIO(GPIOAO_9, 9),
+	AO_GPIO(GPIOAO_10, 10),
+	AO_GPIO(GPIOAO_11, 11),
+	AO_GPIO(GPIOAO_12, 12),
+	AO_GPIO(GPIOAO_13, 13),
+};
+
+static const struct meson_pinctrl_group mesongxbb_periphs_groups[] = {
+	/* GPIOX */
+	{ "sdio_d0",		REG8,	5,	{ GPIOX_0 }, 1 },
+	{ "sdio_d1",		REG8,	4,	{ GPIOX_1 }, 1 },
+	{ "sdio_d2",		REG8,	3,	{ GPIOX_2 }, 1 },
+	{ "sdio_d3",		REG8,	2,	{ GPIOX_3 }, 1 },
+	{ "sdio_cmd",		REG8,	1,	{ GPIOX_4 }, 1 },
+	{ "sdio_clk",		REG8,	0,	{ GPIOX_5 }, 1 },
+	{ "sdio_irq",		REG8,	11,	{ GPIOX_7 }, 1 },
+	{ "uart_tx_a",		REG4,	13,	{ GPIOX_12 }, 1 },
+	{ "uart_rx_a",		REG4,	12,	{ GPIOX_13 }, 1 },
+	{ "uart_cts_a",		REG4,	11,	{ GPIOX_14 }, 1 },
+	{ "uart_rts_a",		REG4,	10,	{ GPIOX_15 }, 1 },
+	{ "pwm_a_x",		REG3,	17,	{ GPIOX_6 }, 1 },
+	{ "pwm_e",		REG2,	30,	{ GPIOX_19 }, 1 },
+	{ "pwm_f_x",		REG3,	18,	{ GPIOX_7 }, 1 },
+
+	/* GPIOY */
+	{ "uart_cts_c",		REG1,	19,	{ GPIOY_11 }, 1 },
+	{ "uart_rts_c",		REG1,	18,	{ GPIOY_12 }, 1 },
+	{ "uart_tx_c",		REG1,	17,	{ GPIOY_13 }, 1 },
+	{ "uart_rx_c",		REG1,	16,	{ GPIOY_14 }, 1 },
+	{ "pwm_a_y",		REG1,	21,	{ GPIOY_16 }, 1 },
+	{ "pwm_f_y",		REG1,	20,	{ GPIOY_15 }, 1 },
+	{ "i2s_out_ch23_y",	REG1,	5,	{ GPIOY_8 }, 1 },
+	{ "i2s_out_ch45_y",	REG1,	6,	{ GPIOY_9 }, 1 },
+	{ "i2s_out_ch67_y",	REG1,	7,	{ GPIOY_10 }, 1 },
+	{ "spdif_out_y",	REG1,	9,	{ GPIOY_12 }, 1 },
+	{ "gen_clk_out",	REG6,	15,	{ GPIOY_15 }, 1 },
+
+	/* GPIOZ */
+	{ "eth_mdio",		REG6,	1,	{ GPIOZ_0 }, 1 },
+	{ "eth_mdc",		REG6,	0,	{ GPIOZ_1 }, 1 },
+	{ "eth_clk_rx_clk",	REG6,	13,	{ GPIOZ_2 }, 1 },
+	{ "eth_rx_dv",		REG6,	12,	{ GPIOZ_3 }, 1 },
+	{ "eth_rxd0",		REG6,	11,	{ GPIOZ_4 }, 1 },
+	{ "eth_rxd1",		REG6,	10,	{ GPIOZ_5 }, 1 },
+	{ "eth_rxd2",		REG6,	9,	{ GPIOZ_6 }, 1 },
+	{ "eth_rxd3",		REG6,	8,	{ GPIOZ_7 }, 1 },
+	{ "eth_rgmii_tx_clk",	REG6,	7,	{ GPIOZ_8 }, 1 },
+	{ "eth_tx_en",		REG6,	6,	{ GPIOZ_9 }, 1 },
+	{ "eth_txd0",		REG6,	5,	{ GPIOZ_10 }, 1 },
+	{ "eth_txd1",		REG6,	4,	{ GPIOZ_11 }, 1 },
+	{ "eth_txd2",		REG6,	3,	{ GPIOZ_12 }, 1 },
+	{ "eth_txd3",		REG6,	2,	{ GPIOZ_13 }, 1 },
+	{ "spi_ss0",		REG5,	26,	{ GPIOZ_7 }, 1 },
+	{ "spi_sclk",		REG5,	27,	{ GPIOZ_6 }, 1 },
+	{ "spi_miso",		REG5,	28,	{ GPIOZ_12 }, 1 },
+	{ "spi_mosi",		REG5,	29,	{ GPIOZ_13 }, 1 },
+
+	/* GPIOH */
+	{ "hdmi_hpd",		REG1,	26,	{ GPIOH_0 }, 1 },
+	{ "hdmi_sda",		REG1,	25,	{ GPIOH_1 }, 1 },
+	{ "hdmi_scl",		REG1,	24,	{ GPIOH_2 }, 1 },
+
+	/* GPIODV */
+	{ "uart_tx_b",		REG2,	29,	{ GPIODV_24 }, 1 },
+	{ "uart_rx_b",		REG2,	28,	{ GPIODV_25 }, 1 },
+	{ "uart_cts_b",		REG2,	27,	{ GPIODV_26 }, 1 },
+	{ "uart_rts_b",		REG2,	26,	{ GPIODV_27 }, 1 },
+	{ "pwm_b",		REG3,	21,	{ GPIODV_29 }, 1 },
+	{ "pwm_d",		REG3,	20,	{ GPIODV_28 }, 1 },
+	{ "i2c_sck_a",		REG7,	27,	{ GPIODV_25 }, 1 },
+	{ "i2c_sda_a",		REG7,	26,	{ GPIODV_24 }, 1 },
+	{ "i2c_sck_b",		REG7,	25,	{ GPIODV_27 }, 1 },
+	{ "i2c_sda_b",		REG7,	24,	{ GPIODV_26 }, 1 },
+	{ "i2c_sck_c",		REG7,	23,	{ GPIODV_29 }, 1 },
+	{ "i2c_sda_c",		REG7,	22,	{ GPIODV_28 }, 1 },
+
+	/* BOOT */
+	{ "emmc_nand_d07",	REG4,	30,	{ BOOT_0, BOOT_1, BOOT_2, BOOT_3, BOOT_4, BOOT_5, BOOT_6, BOOT_7 }, 8 },
+	{ "emmc_clk",		REG4,	18,	{ BOOT_8 }, 1 },
+	{ "emmc_cmd",		REG4,	19,	{ BOOT_10 }, 1 },
+	{ "emmc_ds",		REG4,	31,	{ BOOT_15 }, 1 },
+	{ "nor_d",		REG5,	1,	{ BOOT_11 }, 1 },
+	{ "nor_q",		REG5,	3,	{ BOOT_12 }, 1 },
+	{ "nor_c",		REG5,	2,	{ BOOT_13 }, 1 },
+	{ "nor_cs",		REG5,	0,	{ BOOT_15 }, 1 },
+	{ "nand_ce0",		REG4,	26,	{ BOOT_8 }, 1 },
+	{ "nand_ce1",		REG4,	27,	{ BOOT_9 }, 1 },
+	{ "nand_rb0",		REG4,	25,	{ BOOT_10 }, 1 },
+	{ "nand_ale",		REG4,	24,	{ BOOT_11 }, 1 },
+	{ "nand_cle",		REG4,	23,	{ BOOT_12 }, 1 },
+	{ "nand_wen_clk",	REG4,	22,	{ BOOT_13 }, 1 },
+	{ "nand_ren_wr",	REG4,	21,	{ BOOT_14 }, 1 },
+	{ "nand_dqs",		REG4,	20,	{ BOOT_15 }, 1 },
+
+	/* CARD */
+	{ "sdcard_d1",		REG2,	14,	{ CARD_0 }, 1 },
+	{ "sdcard_d0",		REG2,	15,	{ CARD_1 }, 1 },
+	{ "sdcard_d3",		REG2,	12,	{ CARD_4 }, 1 },
+	{ "sdcard_d2",		REG2,	13,	{ CARD_5 }, 1 },
+	{ "sdcard_cmd",		REG2,	10,	{ CARD_3 }, 1 },
+	{ "sdcard_clk",		REG2,	11,	{ CARD_2 }, 1 },
+};
+
+static const struct meson_pinctrl_group mesongxbb_aobus_groups[] = {
+	/* GPIOAO */
+	{ "uart_tx_ao_b",	AOREG0,	24,	{ GPIOAO_4 }, 1 },
+	{ "uart_rx_ao_b",	AOREG0,	25,	{ GPIOAO_5 }, 1 },
+	{ "uart_tx_ao_a",	AOREG0,	12,	{ GPIOAO_0 }, 1 },
+	{ "uart_rx_ao_a",	AOREG0,	11,	{ GPIOAO_1 }, 1 },
+	{ "uart_cts_ao_a",	AOREG0,	10,	{ GPIOAO_2 }, 1 },
+	{ "uart_rts_ao_a",	AOREG0,	9,	{ GPIOAO_3 }, 1 },
+	{ "uart_cts_ao_b",	AOREG0,	8,	{ GPIOAO_2 }, 1 },
+	{ "uart_rts_ao_b",	AOREG0,	7,	{ GPIOAO_3 }, 1 },
+	{ "i2c_sck_ao",		AOREG0,	6,	{ GPIOAO_4 }, 1 },
+	{ "i2c_sda_ao",		AOREG0,	5,	{ GPIOAO_5 }, 1 },
+	{ "i2c_slave_sck_ao",	AOREG0,	2,	{ GPIOAO_4 }, 1 },
+	{ "i2c_slave_sda_ao",	AOREG0,	1,	{ GPIOAO_5 }, 1 },
+	{ "remote_input_ao",	AOREG0,	0,	{ GPIOAO_7 }, 1 },
+	{ "pwm_ao_a_3",		AOREG0,	22,	{ GPIOAO_3 }, 1 },
+	{ "pwm_ao_a_6",		AOREG0,	18,	{ GPIOAO_6 }, 1 },
+	{ "pwm_ao_a_12",	AOREG0,	17,	{ GPIOAO_12 }, 1 },
+	{ "pwm_ao_b",		AOREG0,	3,	{ GPIOAO_13 }, 1 },
+	{ "i2s_am_clk",		AOREG0,	30,	{ GPIOAO_8 }, 1 },
+	{ "i2s_out_ao_clk",	AOREG0,	29,	{ GPIOAO_9 }, 1 },
+	{ "i2s_out_lr_clk",	AOREG0,	28,	{ GPIOAO_10 }, 1 },
+	{ "i2s_out_ch01_ao",	AOREG0,	27,	{ GPIOAO_11 }, 1 },
+	{ "i2s_out_ch23_ao",	AOREG1,	0,	{ GPIOAO_12 }, 1 },
+	{ "i2s_out_ch45_ao",	AOREG1,	1,	{ GPIOAO_13 }, 1 },
+	{ "spdif_out_ao_6",	AOREG0,	16,	{ GPIOAO_6 }, 1 },
+	{ "spdif_out_ao_13",	AOREG0,	4,	{ GPIOAO_13 }, 1 },
+	{ "ao_cec",		AOREG0,	15,	{ GPIOAO_12 }, 1 },
+	{ "ee_cec",		AOREG0,	14,	{ GPIOAO_12 }, 1 },
+
+	/* TEST_N */
+	{ "i2s_out_ch67_ao",	AOREG1,	2,	{ GPIO_TEST_N }, 1 },
+
+};
+
+const struct meson_pinctrl_config mesongxbb_periphs_pinctrl_config = {
+	.name = "Meson GXBB periphs GPIO",
+	.groups = mesongxbb_periphs_groups,
+	.ngroups = __arraycount(mesongxbb_periphs_groups),
+	.gpios = mesongxbb_periphs_gpios,
+	.ngpios = __arraycount(mesongxbb_periphs_gpios),
+};
+
+const struct meson_pinctrl_config mesongxbb_aobus_pinctrl_config = {
+	.name = "Meson GXBB AO GPIO",
+	.groups = mesongxbb_aobus_groups,
+	.ngroups = __arraycount(mesongxbb_aobus_groups),
+	.gpios = mesongxbb_aobus_gpios,
+	.ngpios = __arraycount(mesongxbb_aobus_gpios),
+};

Reply via email to