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"; }; ðmac { @@ -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), +};