Module Name: src Committed By: jmcneill Date: Sun Aug 12 16:48:05 UTC 2018
Modified Files: src/sys/arch/arm/rockchip: files.rockchip rk3328_cru.c rk_cru.c rk_cru.h rk_cru_pll.c rk_gmac.c rk_platform.c rk_usb.c Added Files: src/sys/arch/arm/rockchip: rk3328_iomux.c rk3399_cru.c rk3399_cru.h rk3399_iomux.c rk3399_platform.h rk3399_pmucru.c rk3399_pmucru.h Removed Files: src/sys/arch/arm/rockchip: rk_iomux.c Log Message: Add support for Rockchip RK3399 SoC. To generate a diff of this commit: cvs rdiff -u -r1.14 -r1.15 src/sys/arch/arm/rockchip/files.rockchip cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/rockchip/rk3328_cru.c \ src/sys/arch/arm/rockchip/rk_cru_pll.c src/sys/arch/arm/rockchip/rk_usb.c cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/rockchip/rk3328_iomux.c \ src/sys/arch/arm/rockchip/rk3399_cru.c \ src/sys/arch/arm/rockchip/rk3399_cru.h \ src/sys/arch/arm/rockchip/rk3399_iomux.c \ src/sys/arch/arm/rockchip/rk3399_platform.h \ src/sys/arch/arm/rockchip/rk3399_pmucru.c \ src/sys/arch/arm/rockchip/rk3399_pmucru.h cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/rockchip/rk_cru.c cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/rockchip/rk_cru.h \ src/sys/arch/arm/rockchip/rk_platform.c cvs rdiff -u -r1.7 -r1.8 src/sys/arch/arm/rockchip/rk_gmac.c cvs rdiff -u -r1.3 -r0 src/sys/arch/arm/rockchip/rk_iomux.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/rockchip/files.rockchip diff -u src/sys/arch/arm/rockchip/files.rockchip:1.14 src/sys/arch/arm/rockchip/files.rockchip:1.15 --- src/sys/arch/arm/rockchip/files.rockchip:1.14 Sun Jul 1 18:16:58 2018 +++ src/sys/arch/arm/rockchip/files.rockchip Sun Aug 12 16:48:04 2018 @@ -1,4 +1,4 @@ -# $NetBSD: files.rockchip,v 1.14 2018/07/01 18:16:58 jmcneill Exp $ +# $NetBSD: files.rockchip,v 1.15 2018/08/12 16:48:04 jmcneill Exp $ # # Configuration info for Rockchip family SoCs # @@ -19,10 +19,18 @@ file arch/arm/rockchip/rk_cru_pll.c rk_ attach rkcru at fdt with rk3328_cru file arch/arm/rockchip/rk3328_cru.c rk3328_cru & soc_rk3328 +# RK3399 clock and reset unit +attach rkcru at fdt with rk3399_cru +file arch/arm/rockchip/rk3399_cru.c rk3399_cru & soc_rk3399 +attach rkcru at fdt with rk3399_pmucru +file arch/arm/rockchip/rk3399_pmucru.c rk3399_pmucru & soc_rk3399 + # IOMUX control device rkiomux { } -attach rkiomux at fdt with rk_iomux -file arch/arm/rockchip/rk_iomux.c rk_iomux +attach rkiomux at fdt with rk3328_iomux +file arch/arm/rockchip/rk3328_iomux.c rk3328_iomux & soc_rk3328 +attach rkiomux at fdt with rk3399_iomux +file arch/arm/rockchip/rk3399_iomux.c rk3399_iomux & soc_rk3399 # GPIO device rkgpio: gpiobus @@ -48,3 +56,4 @@ file arch/arm/rockchip/rk_gmac.c rk_gma # SOC parameters defflag opt_soc.h SOC_ROCKCHIP defflag opt_soc.h SOC_RK3328: SOC_ROCKCHIP +defflag opt_soc.h SOC_RK3399: SOC_ROCKCHIP Index: src/sys/arch/arm/rockchip/rk3328_cru.c diff -u src/sys/arch/arm/rockchip/rk3328_cru.c:1.3 src/sys/arch/arm/rockchip/rk3328_cru.c:1.4 --- src/sys/arch/arm/rockchip/rk3328_cru.c:1.3 Sun Jul 1 18:15:19 2018 +++ src/sys/arch/arm/rockchip/rk3328_cru.c Sun Aug 12 16:48:04 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: rk3328_cru.c,v 1.3 2018/07/01 18:15:19 jmcneill Exp $ */ +/* $NetBSD: rk3328_cru.c,v 1.4 2018/08/12 16:48:04 jmcneill Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -28,7 +28,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: rk3328_cru.c,v 1.3 2018/07/01 18:15:19 jmcneill Exp $"); +__KERNEL_RCSID(1, "$NetBSD: rk3328_cru.c,v 1.4 2018/08/12 16:48:04 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -44,6 +44,7 @@ __KERNEL_RCSID(1, "$NetBSD: rk3328_cru.c #define MISC_CON 0x0084 #define CLKSEL_CON(n) (0x0100 + (n) * 4) #define CLKGATE_CON(n) (0x0200 + (n) * 4) +#define SOFTRST_CON(n) (0x0300 + (n) * 4) #define GRF_SOC_CON4 0x0410 #define GRF_MAC_CON1 0x0904 @@ -131,6 +132,7 @@ static const struct rk_cru_arm_rate armc RK_ARM_RATE( 96000000, 1), }; +static const char * pll_parents[] = { "xin24m" }; static const char * armclk_parents[] = { "apll", "gpll", "dpll", "npll" }; static const char * aclk_bus_pre_parents[] = { "cpll", "gpll", "hdmiphy" }; static const char * hclk_bus_pre_parents[] = { "aclk_bus_pre" }; @@ -151,31 +153,31 @@ static const char * comp_uart_parents[] static const char * pclk_gmac_parents[] = { "aclk_gmac" }; static struct rk_cru_clk rk3328_cru_clks[] = { - RK_PLL(RK3328_PLL_APLL, "apll", "xin24m", + RK_PLL(RK3328_PLL_APLL, "apll", pll_parents, PLL_CON(0), /* con_base */ 0x80, /* mode_reg */ __BIT(0), /* mode_mask */ __BIT(4), /* lock_mask */ pll_frac_rates), - RK_PLL(RK3328_PLL_DPLL, "dpll", "xin24m", + RK_PLL(RK3328_PLL_DPLL, "dpll", pll_parents, PLL_CON(8), /* con_base */ 0x80, /* mode_reg */ __BIT(4), /* mode_mask */ __BIT(3), /* lock_mask */ pll_norates), - RK_PLL(RK3328_PLL_CPLL, "cpll", "xin24m", + RK_PLL(RK3328_PLL_CPLL, "cpll", pll_parents, PLL_CON(16), /* con_base */ 0x80, /* mode_reg */ __BIT(8), /* mode_mask */ __BIT(2), /* lock_mask */ pll_rates), - RK_PLL(RK3328_PLL_GPLL, "gpll", "xin24m", + RK_PLL(RK3328_PLL_GPLL, "gpll", pll_parents, PLL_CON(24), /* con_base */ 0x80, /* mode_reg */ __BIT(12), /* mode_mask */ __BIT(1), /* lock_mask */ pll_frac_rates), - RK_PLL(RK3328_PLL_NPLL, "npll", "xin24m", + RK_PLL(RK3328_PLL_NPLL, "npll", pll_parents, PLL_CON(40), /* con_base */ 0x80, /* mode_reg */ __BIT(1), /* mode_mask */ @@ -398,6 +400,8 @@ rk3328_cru_attach(device_t parent, devic sc->sc_clks = rk3328_cru_clks; sc->sc_nclks = __arraycount(rk3328_cru_clks); + sc->sc_softrst_base = SOFTRST_CON(0); + if (rk_cru_attach(sc) != 0) return; Index: src/sys/arch/arm/rockchip/rk_cru_pll.c diff -u src/sys/arch/arm/rockchip/rk_cru_pll.c:1.3 src/sys/arch/arm/rockchip/rk_cru_pll.c:1.4 --- src/sys/arch/arm/rockchip/rk_cru_pll.c:1.3 Sat Jun 30 17:54:07 2018 +++ src/sys/arch/arm/rockchip/rk_cru_pll.c Sun Aug 12 16:48:05 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: rk_cru_pll.c,v 1.3 2018/06/30 17:54:07 jmcneill Exp $ */ +/* $NetBSD: rk_cru_pll.c,v 1.4 2018/08/12 16:48:05 jmcneill Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rk_cru_pll.c,v 1.3 2018/06/30 17:54:07 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rk_cru_pll.c,v 1.4 2018/08/12 16:48:05 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -169,5 +169,5 @@ rk_cru_pll_get_parent(struct rk_cru_soft KASSERT(clk->type == RK_CRU_PLL); - return pll->parent; + return pll->parents[0]; } Index: src/sys/arch/arm/rockchip/rk_usb.c diff -u src/sys/arch/arm/rockchip/rk_usb.c:1.3 src/sys/arch/arm/rockchip/rk_usb.c:1.4 --- src/sys/arch/arm/rockchip/rk_usb.c:1.3 Sat Jun 30 18:07:32 2018 +++ src/sys/arch/arm/rockchip/rk_usb.c Sun Aug 12 16:48:05 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: rk_usb.c,v 1.3 2018/06/30 18:07:32 jmcneill Exp $ */ +/* $NetBSD: rk_usb.c,v 1.4 2018/08/12 16:48:05 jmcneill Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -28,7 +28,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rk_usb.c,v 1.3 2018/06/30 18:07:32 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rk_usb.c,v 1.4 2018/08/12 16:48:05 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -46,17 +46,31 @@ __KERNEL_RCSID(0, "$NetBSD: rk_usb.c,v 1 static int rk_usb_match(device_t, cfdata_t, void *); static void rk_usb_attach(device_t, device_t, void *); -#define CON0_REG 0x100 -#define CON1_REG 0x104 -#define CON2_REG 0x108 -#define USBPHY_COMMONONN __BIT(4) +#define RK3328_CON0_REG 0x100 +#define RK3328_CON1_REG 0x104 +#define RK3328_CON2_REG 0x108 +#define RK3328_USBPHY_COMMONONN __BIT(4) + +#define RK3399_GRF_USB20_PHY0_CON0_REG 0x0e450 +#define RK3399_GRF_USB20_PHY1_CON0_REG 0x0e460 +#define RK3399_USBPHY_COMMONONN __BIT(4) +#define RK3399_GRF_USB20_PHY0_CON1_REG 0x0e454 +#define RK3399_GRF_USB20_PHY1_CON1_REG 0x0e464 +#define RK3399_GRF_USB20_PHY0_CON2_REG 0x0e458 +#define RK3399_GRF_USB20_PHY1_CON2_REG 0x0e468 +#define RK3399_USBPHY_SUSPEND_N __BIT(1) +#define RK3399_USBPHY_UTMI_SEL __BIT(0) + +#define RK3399_PHY_NO(_sc) ((_sc)->sc_reg == 0xe450 ? 0 : 1) enum rk_usb_type { USB_RK3328 = 1, + USB_RK3399, }; static const struct of_compat_data compat_data[] = { { "rockchip,rk3328-usb2phy", USB_RK3328 }, + { "rockchip,rk3399-usb2phy", USB_RK3399 }, { NULL } }; @@ -71,6 +85,8 @@ struct rk_usb_softc { struct clk_domain sc_clkdom; struct rk_usb_clk sc_usbclk; + + bus_addr_t sc_reg; }; CFATTACH_DECL_NEW(rk_usb, sizeof(struct rk_usb_softc), @@ -102,12 +118,27 @@ static int rk_usb_clk_enable(void *priv, struct clk *clk) { struct rk_usb_softc * const sc = priv; + uint32_t reg, write_mask, write_val; - const uint32_t write_mask = USBPHY_COMMONONN << 16; - const uint32_t write_val = 0; + switch (sc->sc_type) { + case USB_RK3328: + reg = RK3328_CON2_REG; + write_mask = RK3328_USBPHY_COMMONONN << 16; + write_val = 0; + break; + case USB_RK3399: + reg = RK3399_PHY_NO(sc) == 0 ? + RK3399_GRF_USB20_PHY0_CON0_REG : + RK3399_GRF_USB20_PHY1_CON0_REG; + write_mask = RK3399_USBPHY_COMMONONN << 16; + write_val = 0; + break; + default: + return ENXIO; + } syscon_lock(sc->sc_syscon); - syscon_write_4(sc->sc_syscon, CON2_REG, write_mask | write_val); + syscon_write_4(sc->sc_syscon, reg, write_mask | write_val); syscon_unlock(sc->sc_syscon); return 0; @@ -117,12 +148,27 @@ static int rk_usb_clk_disable(void *priv, struct clk *clk) { struct rk_usb_softc * const sc = priv; + uint32_t reg, write_mask, write_val; - const uint32_t write_mask = USBPHY_COMMONONN << 16; - const uint32_t write_val = USBPHY_COMMONONN; + switch (sc->sc_type) { + case USB_RK3328: + reg = RK3328_CON2_REG; + write_mask = RK3328_USBPHY_COMMONONN << 16; + write_val = RK3328_USBPHY_COMMONONN; + break; + case USB_RK3399: + reg = RK3399_PHY_NO(sc) == 0 ? + RK3399_GRF_USB20_PHY0_CON0_REG : + RK3399_GRF_USB20_PHY1_CON0_REG; + write_mask = RK3399_USBPHY_COMMONONN << 16; + write_val = RK3399_USBPHY_COMMONONN; + break; + default: + return ENXIO; + } syscon_lock(sc->sc_syscon); - syscon_write_4(sc->sc_syscon, CON2_REG, write_mask | write_val); + syscon_write_4(sc->sc_syscon, reg, write_mask | write_val); syscon_unlock(sc->sc_syscon); return 0; @@ -165,8 +211,22 @@ rk_usb_attach(device_t parent, device_t struct rk_usb_softc * const sc = device_private(self); struct fdt_attach_args * const faa = aux; const int phandle = faa->faa_phandle; + struct clk *clk; int child; + /* Cache the base address of this PHY so we know which instance we are */ + if (fdtbus_get_reg(phandle, 0, &sc->sc_reg, NULL) != 0) { + aprint_error(": couldn't get registers\n"); + return; + } + + clk = fdtbus_clock_get(phandle, "phyclk"); +KASSERT(clk != NULL); + if (clk && clk_enable(clk) != 0) { + aprint_error(": couldn't enable phy clock\n"); + return; + } + sc->sc_dev = self; sc->sc_type = of_search_compatible(phandle, compat_data)->data; sc->sc_syscon = fdtbus_syscon_lookup(OF_parent(phandle)); @@ -214,6 +274,7 @@ static void rk_usbphy_attach(device_t, d struct rk_usbphy_softc { device_t sc_dev; int sc_phandle; + struct fdtbus_regulator *sc_supply; }; CFATTACH_DECL_NEW(rk_usbphy, sizeof(struct rk_usbphy_softc), @@ -238,13 +299,37 @@ rk_usbphy_release(device_t dev, void *pr static int rk_usbphy_otg_enable(device_t dev, void *priv, bool enable) { + struct rk_usbphy_softc * const sc = device_private(dev); struct rk_usb_softc * const usb_sc = device_private(device_parent(dev)); + uint32_t reg, write_mask, write_val; + int error; - const uint32_t write_mask = 0x1ffU << 16; - const uint32_t write_val = enable ? 0 : 0x1d1; + switch (usb_sc->sc_type) { + case USB_RK3328: + reg = RK3328_CON0_REG; + write_mask = 0x1ffU << 16; + write_val = enable ? 0 : 0x1d1; + break; + case USB_RK3399: + reg = RK3399_PHY_NO(usb_sc) == 0 ? + RK3399_GRF_USB20_PHY0_CON1_REG : + RK3399_GRF_USB20_PHY1_CON1_REG; + write_mask = (RK3399_USBPHY_SUSPEND_N|RK3399_USBPHY_UTMI_SEL) << 16; + write_val = RK3399_USBPHY_UTMI_SEL; + break; + default: + return ENXIO; + } + + if (sc->sc_supply) { + error = enable ? fdtbus_regulator_enable(sc->sc_supply) : + fdtbus_regulator_disable(sc->sc_supply); + if (error != 0) + return error; + } syscon_lock(usb_sc->sc_syscon); - syscon_write_4(usb_sc->sc_syscon, CON0_REG, write_mask | write_val); + syscon_write_4(usb_sc->sc_syscon, reg, write_mask | write_val); syscon_unlock(usb_sc->sc_syscon); return 0; @@ -253,13 +338,37 @@ rk_usbphy_otg_enable(device_t dev, void static int rk_usbphy_host_enable(device_t dev, void *priv, bool enable) { + struct rk_usbphy_softc * const sc = device_private(dev); struct rk_usb_softc * const usb_sc = device_private(device_parent(dev)); + uint32_t reg, write_mask, write_val; + int error; - const uint32_t write_mask = 0x1ffU << 16; - const uint32_t write_val = enable ? 0 : 0x1d1; + switch (usb_sc->sc_type) { + case USB_RK3328: + reg = RK3328_CON1_REG; + write_mask = 0x1ffU << 16; + write_val = enable ? 0 : 0x1d1; + break; + case USB_RK3399: + reg = RK3399_PHY_NO(usb_sc) == 0 ? + RK3399_GRF_USB20_PHY0_CON2_REG : + RK3399_GRF_USB20_PHY1_CON2_REG; + write_mask = (RK3399_USBPHY_SUSPEND_N|RK3399_USBPHY_UTMI_SEL) << 16; + write_val = RK3399_USBPHY_UTMI_SEL; + break; + default: + return ENXIO; + } + + if (sc->sc_supply) { + error = enable ? fdtbus_regulator_enable(sc->sc_supply) : + fdtbus_regulator_disable(sc->sc_supply); + if (error != 0) + return error; + } syscon_lock(usb_sc->sc_syscon); - syscon_write_4(usb_sc->sc_syscon, CON1_REG, write_mask | write_val); + syscon_write_4(usb_sc->sc_syscon, reg, write_mask | write_val); syscon_unlock(usb_sc->sc_syscon); return 0; @@ -300,6 +409,13 @@ rk_usbphy_attach(device_t parent, device sc->sc_dev = self; sc->sc_phandle = phandle; + if (of_hasprop(phandle, "phy-supply")) { + sc->sc_supply = fdtbus_regulator_acquire(phandle, "phy-supply"); + if (sc->sc_supply == NULL) { + aprint_error(": couldn't acquire regulator\n"); + return; + } + } aprint_naive("\n"); Index: src/sys/arch/arm/rockchip/rk_cru.c diff -u src/sys/arch/arm/rockchip/rk_cru.c:1.4 src/sys/arch/arm/rockchip/rk_cru.c:1.5 --- src/sys/arch/arm/rockchip/rk_cru.c:1.4 Sat Jun 30 17:54:07 2018 +++ src/sys/arch/arm/rockchip/rk_cru.c Sun Aug 12 16:48:05 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: rk_cru.c,v 1.4 2018/06/30 17:54:07 jmcneill Exp $ */ +/* $NetBSD: rk_cru.c,v 1.5 2018/08/12 16:48:05 jmcneill Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -30,7 +30,7 @@ #include "opt_fdt_arm.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rk_cru.c,v 1.4 2018/06/30 17:54:07 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rk_cru.c,v 1.5 2018/08/12 16:48:05 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -43,8 +43,6 @@ __KERNEL_RCSID(0, "$NetBSD: rk_cru.c,v 1 #include <arm/rockchip/rk_cru.h> -#define CRU_SOFTRST_CON0 0x0300 - static void * rk_cru_reset_acquire(device_t dev, const void *data, size_t len) { @@ -64,7 +62,7 @@ rk_cru_reset_assert(device_t dev, void * { struct rk_cru_softc * const sc = device_private(dev); const uintptr_t reset_id = (uintptr_t)priv; - const bus_size_t reg = CRU_SOFTRST_CON0 + (reset_id / 16) * 4; + const bus_size_t reg = sc->sc_softrst_base + (reset_id / 16) * 4; const u_int shift = reset_id % 16; CRU_WRITE(sc, reg, (1 << (shift + 16)) | (1 << shift)); @@ -77,7 +75,7 @@ rk_cru_reset_deassert(device_t dev, void { struct rk_cru_softc * const sc = device_private(dev); const uintptr_t reset_id = (uintptr_t)priv; - const bus_size_t reg = CRU_SOFTRST_CON0 + (reset_id / 16) * 4; + const bus_size_t reg = sc->sc_softrst_base + (reset_id / 16) * 4; const u_int shift = reset_id % 16; CRU_WRITE(sc, reg, (1 << (shift + 16)) | (0 << shift)); @@ -357,13 +355,13 @@ rk_cru_print(struct rk_cru_softc *sc) default: type = "???"; break; } - aprint_debug_dev(sc->sc_dev, + aprint_normal_dev(sc->sc_dev, "%3d %-14s %2s %-14s %-7s ", clk->id, clk->base.name, clkp_parent ? "<-" : "", clkp_parent ? clkp_parent->name : "", type); - aprint_debug("%10d Hz\n", clk_get_rate(&clk->base)); + aprint_normal("%10d Hz\n", clk_get_rate(&clk->base)); } } Index: src/sys/arch/arm/rockchip/rk_cru.h diff -u src/sys/arch/arm/rockchip/rk_cru.h:1.2 src/sys/arch/arm/rockchip/rk_cru.h:1.3 --- src/sys/arch/arm/rockchip/rk_cru.h:1.2 Sat Jun 30 17:54:07 2018 +++ src/sys/arch/arm/rockchip/rk_cru.h Sun Aug 12 16:48:05 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: rk_cru.h,v 1.2 2018/06/30 17:54:07 jmcneill Exp $ */ +/* $NetBSD: rk_cru.h,v 1.3 2018/08/12 16:48:05 jmcneill Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -78,20 +78,22 @@ struct rk_cru_pll { uint32_t lock_mask; const struct rk_cru_pll_rate *rates; u_int nrates; - const char *parent; + const char **parents; + u_int nparents; }; u_int rk_cru_pll_get_rate(struct rk_cru_softc *, struct rk_cru_clk *); int rk_cru_pll_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int); const char *rk_cru_pll_get_parent(struct rk_cru_softc *, struct rk_cru_clk *); -#define RK_PLL(_id, _name, _parent, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \ +#define RK_PLL(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \ { \ .id = (_id), \ .type = RK_CRU_PLL, \ .base.name = (_name), \ .base.flags = 0, \ - .u.pll.parent = (_parent), \ + .u.pll.parents = (_parents), \ + .u.pll.nparents = __arraycount(_parents), \ .u.pll.con_base = (_con_base), \ .u.pll.mode_reg = (_mode_reg), \ .u.pll.mode_mask = (_mode_mask), \ @@ -195,6 +197,15 @@ int rk_cru_composite_set_parent(struct r .set_parent = rk_cru_composite_set_parent, \ } +#define RK_COMPOSITE_NOMUX(_id, _name, _parent, _div_reg, _div_mask, _gate_reg, _gate_mask, _flags) \ + RK_COMPOSITE(_id, _name, (const char *[]){ _parent }, _div_reg, 0, _div_mask, _gate_reg, _gate_mask, _flags) + +#define RK_COMPOSITE_NOGATE(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _flags) \ + RK_COMPOSITE(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, 0, 0, _flags) + +#define RK_DIV(_id, _name, _parent, _div_reg, _div_mask, _flags) \ + RK_COMPOSITE(_id, _name, (const char *[]){ _parent }, _div_reg, 0, _div_mask, 0, 0, _flags) + /* Gate clocks */ struct rk_cru_gate { @@ -300,6 +311,8 @@ struct rk_cru_softc { struct rk_cru_clk *sc_clks; u_int sc_nclks; + + bus_size_t sc_softrst_base; }; int rk_cru_attach(struct rk_cru_softc *); Index: src/sys/arch/arm/rockchip/rk_platform.c diff -u src/sys/arch/arm/rockchip/rk_platform.c:1.2 src/sys/arch/arm/rockchip/rk_platform.c:1.3 --- src/sys/arch/arm/rockchip/rk_platform.c:1.2 Sun Aug 5 14:02:35 2018 +++ src/sys/arch/arm/rockchip/rk_platform.c Sun Aug 12 16:48:05 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: rk_platform.c,v 1.2 2018/08/05 14:02:35 skrll Exp $ */ +/* $NetBSD: rk_platform.c,v 1.3 2018/08/12 16:48:05 jmcneill Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -31,7 +31,7 @@ #include "opt_fdt_arm.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rk_platform.c,v 1.2 2018/08/05 14:02:35 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rk_platform.c,v 1.3 2018/08/12 16:48:05 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -158,3 +158,61 @@ static const struct arm_platform rk3328_ ARM_PLATFORM(rk3328, "rockchip,rk3328", &rk3328_platform); #endif /* SOC_RK3328 */ + + +#ifdef SOC_RK3399 + +#include <arm/rockchip/rk3399_platform.h> + +static const struct pmap_devmap * +rk3399_platform_devmap(void) +{ + static const struct pmap_devmap devmap[] = { + DEVMAP_ENTRY(RK3399_CORE_VBASE, + RK3399_CORE_PBASE, + RK3399_CORE_SIZE), + DEVMAP_ENTRY_END + }; + + return devmap; +} + +void rk3399_platform_early_putchar(char); + +void +rk3399_platform_early_putchar(char c) +{ +#ifdef CONSADDR +#define CONSADDR_VA ((CONSADDR - RK3399_CORE_PBASE) + RK3399_CORE_VBASE) + volatile uint32_t *uartaddr = cpu_earlydevice_va_p() ? + (volatile uint32_t *)CONSADDR_VA : + (volatile uint32_t *)CONSADDR; + + while ((le32toh(uartaddr[com_lsr]) & LSR_TXRDY) == 0) + ; + + uartaddr[com_data] = htole32(c); +#undef CONSADDR_VA +#endif +} + +static u_int +rk3399_platform_uart_freq(void) +{ + return RK3399_UART_FREQ; +} + +static const struct arm_platform rk3399_platform = { + .ap_devmap = rk3399_platform_devmap, + .ap_bootstrap = rk_platform_bootstrap, + .ap_init_attach_args = rk_platform_init_attach_args, + .ap_early_putchar = rk3399_platform_early_putchar, + .ap_device_register = rk_platform_device_register, + .ap_reset = psci_fdt_reset, + .ap_delay = gtmr_delay, + .ap_uart_freq = rk3399_platform_uart_freq, +}; + +ARM_PLATFORM(rk3399, "rockchip,rk3399", &rk3399_platform); + +#endif /* SOC_RK3399 */ Index: src/sys/arch/arm/rockchip/rk_gmac.c diff -u src/sys/arch/arm/rockchip/rk_gmac.c:1.7 src/sys/arch/arm/rockchip/rk_gmac.c:1.8 --- src/sys/arch/arm/rockchip/rk_gmac.c:1.7 Mon Jul 16 23:11:47 2018 +++ src/sys/arch/arm/rockchip/rk_gmac.c Sun Aug 12 16:48:05 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: rk_gmac.c,v 1.7 2018/07/16 23:11:47 christos Exp $ */ +/* $NetBSD: rk_gmac.c,v 1.8 2018/08/12 16:48:05 jmcneill Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -28,7 +28,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rk_gmac.c,v 1.7 2018/07/16 23:11:47 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rk_gmac.c,v 1.8 2018/08/12 16:48:05 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -49,6 +49,30 @@ __KERNEL_RCSID(0, "$NetBSD: rk_gmac.c,v #include <dev/fdt/fdtvar.h> #include <dev/fdt/syscon.h> +#define RK_GMAC_TXDLY_DEFAULT 0x30 +#define RK_GMAC_RXDLY_DEFAULT 0x10 + +enum rk_gmac_type { + GMAC_RK3328 = 1, + GMAC_RK3399 +}; + +static const struct of_compat_data compat_data[] = { + { "rockchip,rk3328-gmac", GMAC_RK3328 }, + { "rockchip,rk3399-gmac", GMAC_RK3399 }, + { NULL } +}; + +struct rk_gmac_softc { + struct dwc_gmac_softc sc_base; + struct syscon *sc_syscon; + enum rk_gmac_type sc_type; +}; + +/* + * RK3328 specific + */ + #define RK3328_GRF_MAC_CON0 0x0900 #define RK3328_GRF_MAC_CON0_RXDLY __BITS(13,7) #define RK3328_GRF_MAC_CON0_TXDLY __BITS(6,0) @@ -64,56 +88,6 @@ __KERNEL_RCSID(0, "$NetBSD: rk_gmac.c,v #define RK3328_GRF_MAC_CON1_RXDLY_EN __BIT(1) #define RK3328_GRF_MAC_CON1_TXDLY_EN __BIT(0) -#define RK_GMAC_TXDLY_DEFAULT 0x30 -#define RK_GMAC_RXDLY_DEFAULT 0x10 - -static const char * compatible[] = { - "rockchip,rk3328-gmac", - NULL -}; - -struct rk_gmac_softc { - struct dwc_gmac_softc sc_base; - struct syscon *sc_syscon; -}; - -static int -rk_gmac_reset(const int phandle) -{ - struct fdtbus_gpio_pin *pin_reset; - const u_int *reset_delay_us; - bool reset_active_low; - int len; - - if (!of_hasprop(phandle, "snps,reset-gpio")) - return 0; - - pin_reset = fdtbus_gpio_acquire(phandle, "snps,reset-gpio", GPIO_PIN_OUTPUT); - if (pin_reset == NULL) - return ENOENT; - - reset_delay_us = fdtbus_get_prop(phandle, "snps,reset-delays-us", &len); - if (reset_delay_us == NULL || len != 12) - return ENXIO; - - reset_active_low = of_hasprop(phandle, "snps,reset-active-low"); - - fdtbus_gpio_write_raw(pin_reset, reset_active_low ? 1 : 0); - delay(be32toh(reset_delay_us[0])); - fdtbus_gpio_write_raw(pin_reset, reset_active_low ? 0 : 1); - delay(be32toh(reset_delay_us[1])); - fdtbus_gpio_write_raw(pin_reset, reset_active_low ? 1 : 0); - delay(be32toh(reset_delay_us[2])); - - return 0; -} - -static int -rk_gmac_intr(void *arg) -{ - return dwc_gmac_intr(arg); -} - static void rk3328_gmac_set_mode_rgmii(struct dwc_gmac_softc *sc, u_int tx_delay, u_int rx_delay) { @@ -167,6 +141,112 @@ rk3328_gmac_set_speed_rgmii(struct dwc_g syscon_unlock(rk_sc->sc_syscon); } +/* + * RK3399 specific + */ + +#define RK3399_GRF_SOC_CON5 0x0c214 +#define RK3399_GRF_SOC_CON5_GMAC_PHY_INTF_SEL __BITS(11,9) +#define RK3399_GRF_SOC_CON5_GMAC_FLOWCTRL __BIT(8) +#define RK3399_GRF_SOC_CON5_GMAC_SPEED __BIT(7) +#define RK3399_GRF_SOC_CON5_RMII_MODE __BIT(6) +#define RK3399_GRF_SOC_CON5_GMAC_CLK_SEL __BITS(5,4) +#define RK3399_GRF_SOC_CON5_GMAC_CLK_SEL_125M 0 +#define RK3399_GRF_SOC_CON5_GMAC_CLK_SEL_25M 1 +#define RK3399_GRF_SOC_CON5_GMAC_CLK_SEL_2_5M 2 +#define RK3399_GRF_SOC_CON5_RMII_CLK_SEL __BIT(3) +#define RK3399_GRF_SOC_CON6 0x0c218 +#define RK3399_GRF_SOC_CON6_GMAC_RXCLK_DLY_ENA __BIT(15) +#define RK3399_GRF_SOC_CON6_GMAC_CLK_RX_DL_CFG __BITS(14,8) +#define RK3399_GRF_SOC_CON6_GMAC_TXCLK_DLY_ENA __BIT(7) +#define RK3399_GRF_SOC_CON6_GMAC_CLK_TX_DL_CFG __BITS(6,0) + +static void +rk3399_gmac_set_mode_rgmii(struct dwc_gmac_softc *sc, u_int tx_delay, u_int rx_delay) +{ + struct rk_gmac_softc * const rk_sc = (struct rk_gmac_softc *)sc; + + const uint32_t con5_mask = + (RK3399_GRF_SOC_CON5_RMII_MODE | RK3399_GRF_SOC_CON5_GMAC_PHY_INTF_SEL) << 16; + const uint32_t con5 = __SHIFTIN(1, RK3399_GRF_SOC_CON5_GMAC_PHY_INTF_SEL); + + const uint32_t con6_mask = + (RK3399_GRF_SOC_CON6_GMAC_CLK_RX_DL_CFG | RK3399_GRF_SOC_CON6_GMAC_CLK_TX_DL_CFG) << 16; + const uint32_t con6 = + __SHIFTIN(rx_delay, RK3399_GRF_SOC_CON6_GMAC_CLK_RX_DL_CFG) | + __SHIFTIN(tx_delay, RK3399_GRF_SOC_CON6_GMAC_CLK_TX_DL_CFG); + + syscon_lock(rk_sc->sc_syscon); + syscon_write_4(rk_sc->sc_syscon, RK3399_GRF_SOC_CON5, con5 | con5_mask); + syscon_write_4(rk_sc->sc_syscon, RK3399_GRF_SOC_CON6, con6 | con6_mask); + syscon_unlock(rk_sc->sc_syscon); +} + +static void +rk3399_gmac_set_speed_rgmii(struct dwc_gmac_softc *sc, int speed) +{ + struct rk_gmac_softc * const rk_sc = (struct rk_gmac_softc *)sc; + u_int clksel; + + switch (speed) { + case IFM_10_T: + clksel = RK3399_GRF_SOC_CON5_GMAC_CLK_SEL_2_5M; + break; + case IFM_100_TX: + clksel = RK3399_GRF_SOC_CON5_GMAC_CLK_SEL_25M; + break; + default: + clksel = RK3399_GRF_SOC_CON5_GMAC_CLK_SEL_125M; + break; + } + + const uint32_t con5_mask = + RK3399_GRF_SOC_CON5_GMAC_CLK_SEL << 16; + const uint32_t con5 = + __SHIFTIN(clksel, RK3399_GRF_SOC_CON5_GMAC_CLK_SEL); + + syscon_lock(rk_sc->sc_syscon); + syscon_write_4(rk_sc->sc_syscon, RK3399_GRF_SOC_CON5, con5 | con5_mask); + syscon_unlock(rk_sc->sc_syscon); +} + +static int +rk_gmac_reset(const int phandle) +{ + struct fdtbus_gpio_pin *pin_reset; + const u_int *reset_delay_us; + bool reset_active_low; + int len; + + if (!of_hasprop(phandle, "snps,reset-gpio")) + return 0; + + pin_reset = fdtbus_gpio_acquire(phandle, "snps,reset-gpio", GPIO_PIN_OUTPUT); + if (pin_reset == NULL) + return ENOENT; + + reset_delay_us = fdtbus_get_prop(phandle, "snps,reset-delays-us", &len); + if (reset_delay_us == NULL || len != 12) + return ENXIO; + + reset_active_low = of_hasprop(phandle, "snps,reset-active-low"); + + fdtbus_gpio_write_raw(pin_reset, reset_active_low ? 1 : 0); + delay(be32toh(reset_delay_us[0])); + fdtbus_gpio_write_raw(pin_reset, reset_active_low ? 0 : 1); + delay(be32toh(reset_delay_us[1])); + fdtbus_gpio_write_raw(pin_reset, reset_active_low ? 1 : 0); + delay(be32toh(reset_delay_us[2])); + + return 0; +} + +static int +rk_gmac_intr(void *arg) +{ + return dwc_gmac_intr(arg); +} + static int rk_gmac_setup_clocks(int phandle) { @@ -234,7 +314,7 @@ rk_gmac_match(device_t parent, cfdata_t { struct fdt_attach_args * const faa = aux; - return of_match_compatible(faa->faa_phandle, compatible); + return of_match_compat_data(faa->faa_phandle, compat_data); } static void @@ -255,6 +335,8 @@ rk_gmac_attach(device_t parent, device_t return; } + rk_sc->sc_type = of_search_compatible(phandle, compat_data)->data; + rk_sc->sc_syscon = fdtbus_syscon_acquire(phandle, "rockchip,grf"); if (rk_sc->sc_syscon == NULL) { aprint_error(": couldn't get grf syscon\n"); @@ -300,13 +382,27 @@ rk_gmac_attach(device_t parent, device_t return; } - if (strcmp(phy_mode, "rgmii") == 0) { - rk3328_gmac_set_mode_rgmii(sc, tx_delay, rx_delay); - - sc->sc_set_speed = rk3328_gmac_set_speed_rgmii; - } else { - aprint_error(": unsupported phy-mode '%s'\n", phy_mode); - return; + switch (rk_sc->sc_type) { + case GMAC_RK3328: + if (strcmp(phy_mode, "rgmii") == 0) { + rk3328_gmac_set_mode_rgmii(sc, tx_delay, rx_delay); + + sc->sc_set_speed = rk3328_gmac_set_speed_rgmii; + } else { + aprint_error(": unsupported phy-mode '%s'\n", phy_mode); + return; + } + break; + case GMAC_RK3399: + if (strcmp(phy_mode, "rgmii") == 0) { + rk3399_gmac_set_mode_rgmii(sc, tx_delay, rx_delay); + + sc->sc_set_speed = rk3399_gmac_set_speed_rgmii; + } else { + aprint_error(": unsupported phy-mode '%s'\n", phy_mode); + return; + } + break; } aprint_naive("\n"); Added files: Index: src/sys/arch/arm/rockchip/rk3328_iomux.c diff -u /dev/null src/sys/arch/arm/rockchip/rk3328_iomux.c:1.1 --- /dev/null Sun Aug 12 16:48:05 2018 +++ src/sys/arch/arm/rockchip/rk3328_iomux.c Sun Aug 12 16:48:04 2018 @@ -0,0 +1,314 @@ +/* $NetBSD: rk3328_iomux.c,v 1.1 2018/08/12 16:48:04 jmcneill Exp $ */ + +/*- + * Copyright (c) 2018 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: rk3328_iomux.c,v 1.1 2018/08/12 16:48:04 jmcneill Exp $"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/device.h> +#include <sys/intr.h> +#include <sys/systm.h> +#include <sys/mutex.h> +#include <sys/kmem.h> +#include <sys/lwp.h> + +#include <dev/fdt/fdtvar.h> +#include <dev/fdt/syscon.h> + +#define GRF_GPIO_P_REG(_bank, _idx) (0x0100 + (_bank) * 0x10 + ((_idx) >> 3) * 4) +#define GRF_GPIO_P_CTL(_idx) (0x3 << (((_idx) & 7) * 2)) +#define GRF_GPIO_P_CTL_Z 0 +#define GRF_GPIO_P_CTL_PULLUP 1 +#define GRF_GPIO_P_CTL_PULLDOWN 2 +#define GRF_GPIO_P_CTL_REPEATER 3 +#define GRF_GPIO_P_CTL_MASK 0x3 +#define GRF_GPIO_P_WRITE_EN(_idx) (0x3 << (((_idx) & 7) * 2 + 16)) + +#define GRF_GPIO_E_REG(_bank, _idx) (0x0200 + (_bank) * 0x10 + ((_idx) >> 3) * 4) +#define GRF_GPIO_E_CTL(_idx) (0x3 << (((_idx) & 7) * 2)) +#define GRF_GPIO_E_CTL_2MA 0 +#define GRF_GPIO_E_CTL_4MA 1 +#define GRF_GPIO_E_CTL_8MA 2 +#define GRF_GPIO_E_CTL_12MA 3 +#define GRF_GPIO_E_CTL_MASK 0x3 +#define GRF_GPIO_E_WRITE_EN(_idx) (0x3 << (((_idx) & 7) * 2 + 16)) + +struct rk3328_iomux { + bus_size_t base; + u_int type; +#define RK3328_IOMUX_TYPE_3BIT 0x01 +}; + +struct rk3328_iomux_bank { + struct rk3328_iomux iomux[4]; +}; + +static const struct rk3328_iomux_bank rk3328_iomux_banks[] = { + [0] = { + .iomux = { + [0] = { .base = 0x0000 }, + [1] = { .base = 0x0004 }, + [2] = { .base = 0x0008 }, + [3] = { .base = 0x000c }, + }, + }, + [1] = { + .iomux = { + [0] = { .base = 0x0010 }, + [1] = { .base = 0x0014 }, + [2] = { .base = 0x0018 }, + [3] = { .base = 0x001c }, + } + }, + [2] = { + .iomux = { + [0] = { .base = 0x0020 }, + [1] = { .base = 0x0024, .type = RK3328_IOMUX_TYPE_3BIT }, + [2] = { .base = 0x002c, .type = RK3328_IOMUX_TYPE_3BIT }, + [3] = { .base = 0x0034 }, + }, + }, + [3] = { + .iomux = { + [0] = { .base = 0x0038, .type = RK3328_IOMUX_TYPE_3BIT }, + [1] = { .base = 0x0040, .type = RK3328_IOMUX_TYPE_3BIT }, + [2] = { .base = 0x0048 }, + [3] = { .base = 0x004c }, + }, + }, +}; + +struct rk3328_iomux_conf { + const struct rk3328_iomux_bank *banks; + u_int nbanks; +}; + +static const struct rk3328_iomux_conf rk3328_iomux_conf = { + .banks = rk3328_iomux_banks, + .nbanks = __arraycount(rk3328_iomux_banks), +}; + +static const struct of_compat_data compat_data[] = { + { "rockchip,rk3328-pinctrl", (uintptr_t)&rk3328_iomux_conf }, + { NULL } +}; + +struct rk3328_iomux_softc { + device_t sc_dev; + struct syscon *sc_syscon; + + const struct rk3328_iomux_conf *sc_conf; +}; + +#define LOCK(sc) \ + syscon_lock((sc)->sc_syscon) +#define UNLOCK(sc) \ + syscon_unlock((sc)->sc_syscon) +#define RD4(sc, reg) \ + syscon_read_4((sc)->sc_syscon, (reg)) +#define WR4(sc, reg, val) \ + syscon_write_4((sc)->sc_syscon, (reg), (val)) + +static int rk3328_iomux_match(device_t, cfdata_t, void *); +static void rk3328_iomux_attach(device_t, device_t, void *); + +CFATTACH_DECL_NEW(rk3328_iomux, sizeof(struct rk3328_iomux_softc), + rk3328_iomux_match, rk3328_iomux_attach, NULL, NULL); + +static void +rk3328_iomux_calc_iomux_reg(struct rk3328_iomux_softc *sc, u_int bank, u_int pin, bus_size_t *reg, uint32_t *mask) +{ + const struct rk3328_iomux_bank *banks = sc->sc_conf->banks; + + KASSERT(bank < sc->sc_conf->nbanks); + + *reg = banks[bank].iomux[pin / 8].base; + if (banks[bank].iomux[pin / 8].type & RK3328_IOMUX_TYPE_3BIT) { + if ((pin % 8) >= 5) + *reg += 0x04; + const u_int bit = (pin % 8 % 5) * 3; + *mask = 7 << bit; + } else { + const u_int bit = (pin % 8) * 2; + *mask = 3 << bit; + } +} + +static void +rk3328_iomux_set_bias(struct rk3328_iomux_softc *sc, u_int bank, u_int idx, u_int bias) +{ + WR4(sc, GRF_GPIO_P_REG(bank, idx), + __SHIFTIN(GRF_GPIO_P_CTL_MASK, GRF_GPIO_P_WRITE_EN(idx)) | + __SHIFTIN(bias, GRF_GPIO_P_CTL(idx))); +} + +static void +rk3328_iomux_set_drive_strength(struct rk3328_iomux_softc *sc, u_int bank, u_int idx, u_int drv) +{ + WR4(sc, GRF_GPIO_E_REG(bank, idx), + __SHIFTIN(GRF_GPIO_E_CTL_MASK, GRF_GPIO_E_WRITE_EN(idx)) | + __SHIFTIN(drv, GRF_GPIO_E_CTL(idx))); +} + +static void +rk3328_iomux_set_mux(struct rk3328_iomux_softc *sc, u_int bank, u_int idx, u_int mux) +{ + bus_size_t reg; + uint32_t mask; + + rk3328_iomux_calc_iomux_reg(sc, bank, idx, ®, &mask); + + WR4(sc, reg, (mask << 16) | __SHIFTIN(mux, mask)); +} + +static int +rk3328_iomux_config(struct rk3328_iomux_softc *sc, const int phandle, u_int bank, u_int idx, u_int mux) +{ + u_int drv; + + if (of_hasprop(phandle, "bias-disable")) + rk3328_iomux_set_bias(sc, bank, idx, GRF_GPIO_P_CTL_Z); + else if (of_hasprop(phandle, "bias-pull-up")) + rk3328_iomux_set_bias(sc, bank, idx, GRF_GPIO_P_CTL_PULLUP); + else if (of_hasprop(phandle, "bias-pull-down")) + rk3328_iomux_set_bias(sc, bank, idx, GRF_GPIO_P_CTL_PULLDOWN); + + if (of_getprop_uint32(phandle, "drive-strength", &drv) == 0) { + switch (drv) { + case 2: + rk3328_iomux_set_drive_strength(sc, bank, idx, GRF_GPIO_E_CTL_2MA); + break; + case 4: + rk3328_iomux_set_drive_strength(sc, bank, idx, GRF_GPIO_E_CTL_4MA); + break; + case 8: + rk3328_iomux_set_drive_strength(sc, bank, idx, GRF_GPIO_E_CTL_8MA); + break; + case 12: + rk3328_iomux_set_drive_strength(sc, bank, idx, GRF_GPIO_E_CTL_12MA); + break; + default: + aprint_error_dev(sc->sc_dev, "unsupported drive-strength %u\n", drv); + return EINVAL; + } + } + +#if notyet + if (of_hasprop(phandle, "input-enable")) + rk3328_iomux_set_direction(sc, bank, idx, GPIO_PIN_INPUT, -1); + else if (of_hasprop(phandle, "output-high")) + rk3328_iomux_set_direction(sc, bank, idx, GPIO_PIN_OUTPUT, GPIO_PIN_HIGH); + else if (of_hasprop(phandle, "output-low")) + rk3328_iomux_set_direction(sc, bank, idx, GPIO_PIN_OUTPUT, GPIO_PIN_LOW); +#endif + + rk3328_iomux_set_mux(sc, bank, idx, mux); + + return 0; +} + +static int +rk3328_iomux_pinctrl_set_config(device_t dev, const void *data, size_t len) +{ + struct rk3328_iomux_softc * const sc = device_private(dev); + int pins_len; + + if (len != 4) + return -1; + + const int phandle = fdtbus_get_phandle_from_native(be32dec(data)); + const u_int *pins = fdtbus_get_prop(phandle, "rockchip,pins", &pins_len); + + while (pins_len >= 16) { + const u_int bank = be32toh(pins[0]); + const u_int idx = be32toh(pins[1]); + const u_int mux = be32toh(pins[2]); + const int cfg = fdtbus_get_phandle_from_native(be32toh(pins[3])); + + LOCK(sc); + rk3328_iomux_config(sc, cfg, bank, idx, mux); + UNLOCK(sc); + + pins_len -= 16; + pins += 4; + } + + return 0; +} + +static struct fdtbus_pinctrl_controller_func rk3328_iomux_pinctrl_funcs = { + .set_config = rk3328_iomux_pinctrl_set_config, +}; + +static int +rk3328_iomux_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 +rk3328_iomux_attach(device_t parent, device_t self, void *aux) +{ + struct rk3328_iomux_softc * const sc = device_private(self); + struct fdt_attach_args * const faa = aux; + const int phandle = faa->faa_phandle; + int child, sub; + + sc->sc_dev = self; + sc->sc_syscon = fdtbus_syscon_acquire(phandle, "rockchip,grf"); + if (sc->sc_syscon == NULL) { + aprint_error(": couldn't acquire grf syscon\n"); + return; + } + sc->sc_conf = (void *)of_search_compatible(phandle, compat_data)->data; + + aprint_naive("\n"); + aprint_normal(": RK3328 IOMUX control\n"); + + for (child = OF_child(phandle); child; child = OF_peer(child)) { + for (sub = OF_child(child); sub; sub = OF_peer(sub)) { + if (!of_hasprop(sub, "rockchip,pins")) + continue; + fdtbus_register_pinctrl_config(self, sub, &rk3328_iomux_pinctrl_funcs); + } + } + + fdtbus_pinctrl_configure(); + + for (child = OF_child(phandle); child; child = OF_peer(child)) { + struct fdt_attach_args cfaa = *faa; + cfaa.faa_phandle = child; + cfaa.faa_name = fdtbus_get_string(child, "name"); + cfaa.faa_quiet = false; + + config_found(self, &cfaa, NULL); + } +} Index: src/sys/arch/arm/rockchip/rk3399_cru.c diff -u /dev/null src/sys/arch/arm/rockchip/rk3399_cru.c:1.1 --- /dev/null Sun Aug 12 16:48:05 2018 +++ src/sys/arch/arm/rockchip/rk3399_cru.c Sun Aug 12 16:48:05 2018 @@ -0,0 +1,636 @@ +/* $NetBSD: rk3399_cru.c,v 1.1 2018/08/12 16:48:05 jmcneill Exp $ */ + +/*- + * Copyright (c) 2018 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: rk3399_cru.c,v 1.1 2018/08/12 16:48:05 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/rockchip/rk_cru.h> +#include <arm/rockchip/rk3399_cru.h> + +#define PLL_CON(n) (0x0000 + (n) * 4) +#define CLKSEL_CON(n) (0x0100 + (n) * 4) +#define CLKGATE_CON(n) (0x0300 + (n) * 4) +#define SOFTRST_CON(n) (0x0400 + (n) * 4) + +static int rk3399_cru_match(device_t, cfdata_t, void *); +static void rk3399_cru_attach(device_t, device_t, void *); + +static const char * const compatible[] = { + "rockchip,rk3399-cru", + NULL +}; + +CFATTACH_DECL_NEW(rk3399_cru, sizeof(struct rk_cru_softc), + rk3399_cru_match, rk3399_cru_attach, NULL, NULL); + +static const struct rk_cru_pll_rate pll_rates[] = { + RK_PLL_RATE(2208000000, 1, 92, 1, 1, 1, 0), + RK_PLL_RATE(2184000000, 1, 91, 1, 1, 1, 0), + RK_PLL_RATE(2160000000, 1, 90, 1, 1, 1, 0), + RK_PLL_RATE(2136000000, 1, 89, 1, 1, 1, 0), + RK_PLL_RATE(2112000000, 1, 88, 1, 1, 1, 0), + RK_PLL_RATE(2088000000, 1, 87, 1, 1, 1, 0), + RK_PLL_RATE(2064000000, 1, 86, 1, 1, 1, 0), + RK_PLL_RATE(2040000000, 1, 85, 1, 1, 1, 0), + RK_PLL_RATE(2016000000, 1, 84, 1, 1, 1, 0), + RK_PLL_RATE(1992000000, 1, 83, 1, 1, 1, 0), + RK_PLL_RATE(1968000000, 1, 82, 1, 1, 1, 0), + RK_PLL_RATE(1944000000, 1, 81, 1, 1, 1, 0), + RK_PLL_RATE(1920000000, 1, 80, 1, 1, 1, 0), + RK_PLL_RATE(1896000000, 1, 79, 1, 1, 1, 0), + RK_PLL_RATE(1872000000, 1, 78, 1, 1, 1, 0), + RK_PLL_RATE(1848000000, 1, 77, 1, 1, 1, 0), + RK_PLL_RATE(1824000000, 1, 76, 1, 1, 1, 0), + RK_PLL_RATE(1800000000, 1, 75, 1, 1, 1, 0), + RK_PLL_RATE(1776000000, 1, 74, 1, 1, 1, 0), + RK_PLL_RATE(1752000000, 1, 73, 1, 1, 1, 0), + RK_PLL_RATE(1728000000, 1, 72, 1, 1, 1, 0), + RK_PLL_RATE(1704000000, 1, 71, 1, 1, 1, 0), + RK_PLL_RATE(1680000000, 1, 70, 1, 1, 1, 0), + RK_PLL_RATE(1656000000, 1, 69, 1, 1, 1, 0), + RK_PLL_RATE(1632000000, 1, 68, 1, 1, 1, 0), + RK_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0), + RK_PLL_RATE(1600000000, 3, 200, 1, 1, 1, 0), + RK_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0), + RK_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0), + RK_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0), + RK_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0), + RK_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0), + RK_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0), + RK_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0), + RK_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0), + RK_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0), + RK_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0), + RK_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0), + RK_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0), + RK_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0), + RK_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0), + RK_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0), + RK_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0), + RK_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0), + RK_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0), + RK_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0), + RK_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0), + RK_PLL_RATE(1000000000, 1, 125, 3, 1, 1, 0), + RK_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0), + RK_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0), + RK_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0), + RK_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0), + RK_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0), + RK_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0), + RK_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0), + RK_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0), + RK_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0), + RK_PLL_RATE( 800000000, 1, 100, 3, 1, 1, 0), + RK_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0), + RK_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0), + RK_PLL_RATE( 676000000, 3, 169, 2, 1, 1, 0), + RK_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0), + RK_PLL_RATE( 594000000, 1, 99, 4, 1, 1, 0), + RK_PLL_RATE( 533250000, 8, 711, 4, 1, 1, 0), + RK_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0), + RK_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0), + RK_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0), + RK_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0), + RK_PLL_RATE( 297000000, 1, 99, 4, 2, 1, 0), + RK_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0), + RK_PLL_RATE( 148500000, 1, 99, 4, 4, 1, 0), + RK_PLL_RATE( 106500000, 1, 71, 4, 4, 1, 0), + RK_PLL_RATE( 96000000, 1, 64, 4, 4, 1, 0), + RK_PLL_RATE( 74250000, 2, 99, 4, 4, 1, 0), + RK_PLL_RATE( 65000000, 1, 65, 6, 4, 1, 0), + RK_PLL_RATE( 54000000, 1, 54, 6, 4, 1, 0), + RK_PLL_RATE( 27000000, 1, 27, 6, 4, 1, 0), +}; + +static const struct rk_cru_pll_rate pll_norates[] = { +}; + +#define PLL_CON0 0x00 +#define PLL_FBDIV __BITS(11,0) + +#define PLL_CON1 0x04 +#define PLL_POSTDIV2 __BITS(14,12) +#define PLL_POSTDIV1 __BITS(10,8) +#define PLL_REFDIV __BITS(5,0) + +#define PLL_CON2 0x08 +#define PLL_LOCK __BIT(31) +#define PLL_FRACDIV __BITS(23,0) + +#define PLL_CON3 0x0c +#define PLL_WORK_MODE __BITS(9,8) +#define PLL_WORK_MODE_SLOW 0 +#define PLL_WORK_MODE_NORMAL 1 +#define PLL_WORK_MODE_DEEP_SLOW 2 +#define PLL_DSMPD __BIT(3) + +#define PLL_WRITE_MASK 0xffff0000 + +static u_int +rk3399_cru_pll_get_rate(struct rk_cru_softc *sc, + struct rk_cru_clk *clk) +{ + struct rk_cru_pll *pll = &clk->u.pll; + struct clk *clkp, *clkp_parent; + u_int foutvco, foutpostdiv; + + KASSERT(clk->type == RK_CRU_PLL); + + clkp = &clk->base; + clkp_parent = clk_get_parent(clkp); + if (clkp_parent == NULL) + return 0; + + const u_int fref = clk_get_rate(clkp_parent); + if (fref == 0) + return 0; + + const uint32_t con0 = CRU_READ(sc, pll->con_base + PLL_CON0); + const uint32_t con1 = CRU_READ(sc, pll->con_base + PLL_CON1); + const uint32_t con2 = CRU_READ(sc, pll->con_base + PLL_CON2); + const uint32_t con3 = CRU_READ(sc, pll->con_base + PLL_CON3); + + const u_int fbdiv = __SHIFTOUT(con0, PLL_FBDIV); + const u_int postdiv2 = __SHIFTOUT(con1, PLL_POSTDIV2); + const u_int postdiv1 = __SHIFTOUT(con1, PLL_POSTDIV1); + const u_int refdiv = __SHIFTOUT(con1, PLL_REFDIV); + const u_int fracdiv = __SHIFTOUT(con2, PLL_FRACDIV); + const u_int dsmpd = __SHIFTOUT(con3, PLL_DSMPD); + + if (dsmpd == 1) { + /* integer mode */ + foutvco = fref / refdiv * fbdiv; + } else { + /* fractional mode */ + foutvco = fref / refdiv * fbdiv + ((fref * fracdiv) >> 24); + } + foutpostdiv = foutvco / postdiv1 / postdiv2; + + return foutpostdiv; +} + +static int +rk3399_cru_pll_set_rate(struct rk_cru_softc *sc, + struct rk_cru_clk *clk, u_int rate) +{ + struct rk_cru_pll *pll = &clk->u.pll; + const struct rk_cru_pll_rate *pll_rate = NULL; + uint32_t val; + int retry; + + KASSERT(clk->type == RK_CRU_PLL); + + if (pll->rates == NULL || rate == 0) + return EIO; + + for (int i = 0; i < pll->nrates; i++) + if (pll->rates[i].rate == rate) { + pll_rate = &pll->rates[i]; + break; + } + if (pll_rate == NULL) + return EINVAL; + + val = __SHIFTIN(PLL_WORK_MODE_SLOW, PLL_WORK_MODE) | (PLL_WORK_MODE << 16); + CRU_WRITE(sc, pll->con_base + PLL_CON3, val); + + CRU_WRITE(sc, pll->con_base + PLL_CON0, + __SHIFTIN(pll_rate->fbdiv, PLL_FBDIV) | + PLL_WRITE_MASK); + + CRU_WRITE(sc, pll->con_base + PLL_CON1, + __SHIFTIN(pll_rate->postdiv2, PLL_POSTDIV2) | + __SHIFTIN(pll_rate->postdiv1, PLL_POSTDIV1) | + __SHIFTIN(pll_rate->refdiv, PLL_REFDIV) | + PLL_WRITE_MASK); + + val = CRU_READ(sc, pll->con_base + PLL_CON2); + val &= ~PLL_FRACDIV; + val |= __SHIFTIN(pll_rate->fracdiv, PLL_FRACDIV); + CRU_WRITE(sc, pll->con_base + PLL_CON2, val); + + val = __SHIFTIN(pll_rate->dsmpd, PLL_DSMPD) | (PLL_DSMPD << 16); + CRU_WRITE(sc, pll->con_base + PLL_CON3, val); + + /* Set PLL work mode to normal */ + const uint32_t write_mask = pll->mode_mask << 16; + const uint32_t write_val = pll->mode_mask; + CRU_WRITE(sc, pll->mode_reg, write_mask | write_val); + + for (retry = 1000; retry > 0; retry--) { + if (CRU_READ(sc, pll->con_base + PLL_CON2) & pll->lock_mask) + break; + delay(1); + } + + if (retry == 0) + device_printf(sc->sc_dev, "WARNING: %s failed to lock\n", + clk->base.name); + + val = __SHIFTIN(PLL_WORK_MODE_NORMAL, PLL_WORK_MODE) | (PLL_WORK_MODE << 16); + CRU_WRITE(sc, pll->con_base + PLL_CON3, val); + + return 0; +} + +#define RK3399_PLL(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \ + { \ + .id = (_id), \ + .type = RK_CRU_PLL, \ + .base.name = (_name), \ + .base.flags = 0, \ + .u.pll.parents = (_parents), \ + .u.pll.nparents = __arraycount(_parents), \ + .u.pll.con_base = (_con_base), \ + .u.pll.mode_reg = (_mode_reg), \ + .u.pll.mode_mask = (_mode_mask), \ + .u.pll.lock_mask = (_lock_mask), \ + .u.pll.rates = (_rates), \ + .u.pll.nrates = __arraycount(_rates), \ + .get_rate = rk3399_cru_pll_get_rate, \ + .set_rate = rk3399_cru_pll_set_rate, \ + .get_parent = rk_cru_pll_get_parent, \ + } + +static const char * pll_parents[] = { "xin24m", "xin32k" }; +static const char * mux_pll_src_cpll_gpll_parents[] = { "cpll", "gpll" }; +static const char * mux_pll_src_cpll_gpll_npll_parents[] = { "cpll", "gpll", "npll" }; +static const char * mux_pll_src_cpll_gpll_upll_parents[] = { "cpll", "gpll", "upll" }; +static const char * mux_pll_src_cpll_gpll_npll_ppll_upll_24m_parents[] = { "cpll", "gpll", "npll", "ppll", "upll", "xin24m" }; +static const char * mux_aclk_perilp0_parents[] = { "cpll_aclk_perilp0_src", "gpll_aclk_perilp0_src" }; +static const char * mux_hclk_perilp1_parents[] = { "cpll_hclk_perilp1_src", "gpll_hclk_perilp1_src" }; +static const char * mux_aclk_perihp_parents[] = { "cpll_aclk_perihp_src", "gpll_aclk_perihp_src" }; +static const char * mux_aclk_cci_parents[] = { "cpll_aclk_cci_src", "gpll_aclk_cci_src", "npll_aclk_cci_src", "vpll_aclk_cci_src" }; +static const char * mux_uart0_parents[] = { "clk_uart0_div", "clk_uart0_frac", "xin24m" }; +static const char * mux_uart1_parents[] = { "clk_uart1_div", "clk_uart1_frac", "xin24m" }; +static const char * mux_uart2_parents[] = { "clk_uart2_div", "clk_uart2_frac", "xin24m" }; +static const char * mux_uart3_parents[] = { "clk_uart3_div", "clk_uart3_frac", "xin24m" }; +static const char * mux_rmii_parents[] = { "clk_gmac", "clkin_gmac" }; +static const char * mux_aclk_gmac_parents[] = { "cpll_aclk_gmac_src", "gpll_aclk_gmac_src" }; + +static struct rk_cru_clk rk3399_cru_clks[] = { + RK3399_PLL(RK3399_PLL_APLLL, "lpll", pll_parents, + PLL_CON(0), /* con_base */ + PLL_CON(3), /* mode_reg */ + __BIT(8), /* mode_mask */ + __BIT(31), /* lock_mask */ + pll_rates), + RK3399_PLL(RK3399_PLL_APLLB, "bpll", pll_parents, + PLL_CON(8), /* con_base */ + PLL_CON(11), /* mode_reg */ + __BIT(8), /* mode_mask */ + __BIT(31), /* lock_mask */ + pll_rates), + RK3399_PLL(RK3399_PLL_DPLL, "dpll", pll_parents, + PLL_CON(16), /* con_base */ + PLL_CON(19), /* mode_reg */ + __BIT(8), /* mode_mask */ + __BIT(31), /* lock_mask */ + pll_norates), + RK3399_PLL(RK3399_PLL_CPLL, "cpll", pll_parents, + PLL_CON(24), /* con_base */ + PLL_CON(27), /* mode_reg */ + __BIT(8), /* mode_mask */ + __BIT(31), /* lock_mask */ + pll_rates), + RK3399_PLL(RK3399_PLL_GPLL, "gpll", pll_parents, + PLL_CON(32), /* con_base */ + PLL_CON(35), /* mode_reg */ + __BIT(8), /* mode_mask */ + __BIT(31), /* lock_mask */ + pll_rates), + RK3399_PLL(RK3399_PLL_NPLL, "npll", pll_parents, + PLL_CON(40), /* con_base */ + PLL_CON(43), /* mode_reg */ + __BIT(8), /* mode_mask */ + __BIT(31), /* lock_mask */ + pll_rates), + RK3399_PLL(RK3399_PLL_VPLL, "vpll", pll_parents, + PLL_CON(43), /* con_base */ + PLL_CON(51), /* mode_reg */ + __BIT(8), /* mode_mask */ + __BIT(31), /* lock_mask */ + pll_rates), + + /* + * perilp0 + */ + RK_GATE(0, "gpll_aclk_perilp0_src", "gpll", CLKGATE_CON(7), 0), + RK_GATE(0, "cpll_aclk_perilp0_src", "cpll", CLKGATE_CON(7), 1), + RK_COMPOSITE(RK3399_ACLK_PERILP0, "aclk_perilp0", mux_aclk_perilp0_parents, + CLKSEL_CON(23), /* muxdiv_reg */ + __BIT(7), /* mux_mask */ + __BITS(4,0), /* div_mask */ + CLKGATE_CON(7), /* gate_reg */ + __BIT(2), /* gate_mask */ + 0), + RK_COMPOSITE_NOMUX(RK3399_HCLK_PERILP0, "hclk_perilp0", "aclk_perilp0", + CLKSEL_CON(23), /* div_reg */ + __BITS(10,8), /* div_mask */ + CLKGATE_CON(7), /* gate_reg */ + __BIT(3), /* gate_mask */ + 0), + RK_COMPOSITE_NOMUX(RK3399_PCLK_PERILP0, "pclk_perilp0", "aclk_perilp0", + CLKSEL_CON(23), /* div_reg */ + __BITS(14,12), /* div_mask */ + CLKGATE_CON(7), /* gate_reg */ + __BIT(4), /* gate_mask */ + 0), + + /* + * perilp1 + */ + RK_GATE(0, "gpll_hclk_perilp1_src", "gpll", CLKGATE_CON(8), 0), + RK_GATE(0, "cpll_hclk_perilp1_src", "cpll", CLKGATE_CON(8), 1), + RK_COMPOSITE_NOGATE(RK3399_HCLK_PERILP1, "hclk_perilp1", mux_hclk_perilp1_parents, + CLKSEL_CON(25), /* muxdiv_reg */ + __BITS(10,8), /* mux_mask */ + __BITS(4,0), /* div_mask */ + 0), + RK_COMPOSITE_NOMUX(RK3399_PCLK_PERILP1, "pclk_perilp1", "hclk_perilp1", + CLKSEL_CON(25), /* div_reg */ + __BITS(10,8), /* div_mask */ + CLKGATE_CON(8), /* gate_reg */ + __BIT(2), /* gate_mask */ + 0), + + /* + * perihp + */ + RK_GATE(0, "gpll_aclk_perihp_src", "gpll", CLKGATE_CON(5), 0), + RK_GATE(0, "cpll_aclk_perihp_src", "cpll", CLKGATE_CON(5), 1), + RK_COMPOSITE(RK3399_ACLK_PERIHP, "aclk_perihp", mux_aclk_perihp_parents, + CLKSEL_CON(14), /* muxdiv_reg */ + __BIT(7), /* mux_mask */ + __BITS(4,0), /* div_mask */ + CLKGATE_CON(5), /* gate_reg */ + __BIT(2), /* gate_mask */ + 0), + RK_COMPOSITE_NOMUX(RK3399_HCLK_PERIHP, "hclk_perihp", "aclk_perihp", + CLKSEL_CON(14), /* div_reg */ + __BITS(10,8), /* div_mask */ + CLKGATE_CON(5), /* gate_reg */ + __BIT(3), /* gate_mask */ + 0), + RK_COMPOSITE_NOMUX(RK3399_PCLK_PERIHP, "pclk_perihp", "aclk_perihp", + CLKSEL_CON(14), /* div_reg */ + __BITS(14,12), /* div_mask */ + CLKGATE_CON(5), /* gate_reg */ + __BIT(4), /* gate_mask */ + 0), + + /* + * CCI + */ + RK_GATE(0, "cpll_aclk_cci_src", "cpll", CLKGATE_CON(2), 0), + RK_GATE(0, "gpll_aclk_cci_src", "gpll", CLKGATE_CON(2), 1), + RK_GATE(0, "npll_aclk_cci_src", "npll", CLKGATE_CON(2), 2), + RK_GATE(0, "vpll_aclk_cci_src", "vpll", CLKGATE_CON(2), 3), + RK_COMPOSITE(0, "aclk_cci_pre", mux_aclk_cci_parents, + CLKSEL_CON(5), /* muxdiv_reg */ + __BITS(7,6), /* mux_mask */ + __BITS(4,0), /* div_mask */ + CLKGATE_CON(2), /* gate_reg */ + __BIT(4), /* gate_mask */ + 0), + RK_GATE(RK3399_ACLK_CCI, "aclk_cci", "aclk_cci_pre", CLKGATE_CON(15), 2), + + /* + * GIC + */ + RK_COMPOSITE(RK3399_ACLK_GIC_PRE, "aclk_gic_pre", mux_pll_src_cpll_gpll_parents, + CLKSEL_CON(56), /* muxdiv_reg */ + __BIT(15), /* mux_mask */ + __BITS(12,8), /* div_mask */ + CLKGATE_CON(12), /* gate_reg */ + __BIT(12), /* gate_mask */ + 0), + + /* + * DDR + */ + RK_COMPOSITE(RK3399_PCLK_DDR, "pclk_ddr", mux_pll_src_cpll_gpll_parents, + CLKSEL_CON(6), /* muxdiv_reg */ + __BIT(15), /* mux_mask */ + __BITS(12,8), /* div_mask */ + CLKGATE_CON(3), /* gate_reg */ + __BIT(4), /* gate_mask */ + 0), + + /* + * alive + */ + RK_DIV(RK3399_PCLK_ALIVE, "pclk_alive", "gpll", CLKSEL_CON(57), __BITS(4,0), 0), + + /* + * GPIO + */ + RK_GATE(RK3399_PCLK_GPIO2, "pclk_gpio2", "pclk_alive", CLKGATE_CON(31), 3), + RK_GATE(RK3399_PCLK_GPIO3, "pclk_gpio3", "pclk_alive", CLKGATE_CON(31), 4), + RK_GATE(RK3399_PCLK_GPIO4, "pclk_gpio4", "pclk_alive", CLKGATE_CON(31), 5), + + /* + * UART + */ + RK_MUX(0, "clk_uart0_src", mux_pll_src_cpll_gpll_upll_parents, CLKSEL_CON(33), __BITS(13,12)), + RK_MUX(0, "clk_uart_src", mux_pll_src_cpll_gpll_parents, CLKSEL_CON(33), __BIT(15)), + RK_COMPOSITE_NOMUX(0, "clk_uart0_div", "clk_uart0_src", + CLKSEL_CON(33), /* div_reg */ + __BITS(6,0), /* div_mask */ + CLKGATE_CON(9), /* gate_reg */ + __BIT(0), /* gate_mask */ + 0), + RK_COMPOSITE_NOMUX(0, "clk_uart1_div", "clk_uart_src", + CLKSEL_CON(34), /* div_reg */ + __BITS(6,0), /* div_mask */ + CLKGATE_CON(9), /* gate_reg */ + __BIT(2), /* gate_mask */ + 0), + RK_COMPOSITE_NOMUX(0, "clk_uart2_div", "clk_uart_src", + CLKSEL_CON(35), /* div_reg */ + __BITS(6,0), /* div_mask */ + CLKGATE_CON(9), /* gate_reg */ + __BIT(4), /* gate_mask */ + 0), + RK_COMPOSITE_NOMUX(0, "clk_uart3_div", "clk_uart_src", + CLKSEL_CON(36), /* div_reg */ + __BITS(6,0), /* div_mask */ + CLKGATE_CON(9), /* gate_reg */ + __BIT(6), /* gate_mask */ + 0), + RK_MUX(RK3399_SCLK_UART0, "clk_uart0", mux_uart0_parents, CLKSEL_CON(33), __BITS(9,8)), + RK_MUX(RK3399_SCLK_UART1, "clk_uart1", mux_uart1_parents, CLKSEL_CON(34), __BITS(9,8)), + RK_MUX(RK3399_SCLK_UART2, "clk_uart2", mux_uart2_parents, CLKSEL_CON(35), __BITS(9,8)), + RK_MUX(RK3399_SCLK_UART3, "clk_uart3", mux_uart3_parents, CLKSEL_CON(36), __BITS(9,8)), + RK_GATE(RK3399_PCLK_UART0, "pclk_uart0", "pclk_perilp1", CLKGATE_CON(22), 0), + RK_GATE(RK3399_PCLK_UART1, "pclk_uart1", "pclk_perilp1", CLKGATE_CON(22), 1), + RK_GATE(RK3399_PCLK_UART2, "pclk_uart2", "pclk_perilp1", CLKGATE_CON(22), 2), + RK_GATE(RK3399_PCLK_UART3, "pclk_uart3", "pclk_perilp1", CLKGATE_CON(22), 3), + + /* + * SDMMC/SDIO + */ + RK_COMPOSITE(RK3399_HCLK_SD, "hclk_sd", mux_pll_src_cpll_gpll_parents, + CLKSEL_CON(13), /* muxdiv_reg */ + __BIT(15), /* mux_mask */ + __BITS(12,8), /* div_mask */ + CLKGATE_CON(12), /* gate_reg */ + __BIT(13), /* gate_mask */ + 0), + RK_COMPOSITE(RK3399_SCLK_SDIO, "clk_sdio", mux_pll_src_cpll_gpll_npll_ppll_upll_24m_parents, + CLKSEL_CON(15), /* muxdiv_reg */ + __BITS(10,8), /* mux_mask */ + __BITS(6,0), /* div_mask */ + CLKGATE_CON(6), /* gate_reg */ + __BIT(0), /* gate_mask */ + 0), + RK_COMPOSITE(RK3399_SCLK_SDMMC, "clk_sdmmc", mux_pll_src_cpll_gpll_npll_ppll_upll_24m_parents, + CLKSEL_CON(16), /* muxdiv_reg */ + __BITS(10,8), /* mux_mask */ + __BITS(6,0), /* div_mask */ + CLKGATE_CON(6), /* gate_reg */ + __BIT(1), /* gate_mask */ + 0), + RK_GATE(RK3399_HCLK_SDMMC, "hclk_sdmmc", "hclk_sd", CLKGATE_CON(33), 8), + RK_GATE(RK3399_HCLK_SDIO, "hclk_sdio", "pclk_perilp1", CLKGATE_CON(34), 4), + + /* + * GMAC + */ + RK_COMPOSITE(RK3399_SCLK_MAC, "clk_gmac", mux_pll_src_cpll_gpll_npll_parents, + CLKSEL_CON(20), /* muxdiv_reg */ + __BITS(15,14), /* mux_mask */ + __BITS(12,8), /* div_mask */ + CLKGATE_CON(5), /* gate_reg */ + __BIT(5), /* gate_mask */ + 0), + RK_MUX(RK3399_SCLK_RMII_SRC, "clk_rmii_src", mux_rmii_parents, CLKSEL_CON(19), __BIT(4)), + RK_GATE(RK3399_SCLK_MACREF_OUT, "clk_mac_refout", "clk_rmii_src", CLKGATE_CON(5), 6), + RK_GATE(RK3399_SCLK_MACREF, "clk_mac_ref", "clk_rmii_src", CLKGATE_CON(5), 7), + RK_GATE(RK3399_SCLK_MAC_RX, "clk_rmii_rx", "clk_rmii_src", CLKGATE_CON(5), 8), + RK_GATE(RK3399_SCLK_MAC_TX, "clk_rmii_tx", "clk_rmii_src", CLKGATE_CON(5), 9), + RK_GATE(0, "gpll_aclk_gmac_src", "gpll", CLKGATE_CON(6), 8), + RK_GATE(0, "cpll_aclk_gmac_src", "cpll", CLKGATE_CON(6), 9), + RK_COMPOSITE(0, "aclk_gmac_pre", mux_aclk_gmac_parents, + CLKSEL_CON(20), /* muxdiv_reg */ + __BIT(17), /* mux_mask */ + __BITS(4,0), /* div_mask */ + CLKGATE_CON(6), /* gate_reg */ + __BIT(10), /* gate_mask */ + 0), + RK_GATE(RK3399_ACLK_GMAC, "aclk_gmac", "aclk_gmac_pre", CLKGATE_CON(32), 0), + RK_COMPOSITE_NOMUX(0, "pclk_gmac_pre", "aclk_gmac_pre", + CLKSEL_CON(19), /* div_reg */ + __BITS(10,8), /* div_mask */ + CLKGATE_CON(6), /* gate_reg */ + __BIT(11), /* gate_mask */ + 0), + RK_GATE(RK3399_PCLK_GMAC, "pclk_gmac", "pclk_gmac_pre", CLKGATE_CON(32), 2), + + /* + * USB2 + */ + RK_GATE(RK3399_HCLK_HOST0, "hclk_host0", "hclk_perihp", CLKGATE_CON(20), 5), + RK_GATE(RK3399_HCLK_HOST0_ARB, "hclk_host0_arb", "hclk_perihp", CLKGATE_CON(20), 6), + RK_GATE(RK3399_HCLK_HOST1, "hclk_host1", "hclk_perihp", CLKGATE_CON(20), 7), + RK_GATE(RK3399_HCLK_HOST1_ARB, "hclk_host1_arb", "hclk_perihp", CLKGATE_CON(20), 8), + RK_GATE(RK3399_SCLK_USB2PHY0_REF, "clk_usb2phy0_ref", "xin24m", CLKGATE_CON(6), 5), + RK_GATE(RK3399_SCLK_USB2PHY1_REF, "clk_usb2phy1_ref", "xin24m", CLKGATE_CON(6), 6), + + /* + * USB3 + */ + RK_GATE(RK3399_SCLK_USB3OTG0_REF, "clk_usb3otg0_ref", "xin24m", CLKGATE_CON(12), 1), + RK_GATE(RK3399_SCLK_USB3OTG1_REF, "clk_usb3otg1_ref", "xin24m", CLKGATE_CON(12), 2), + RK_COMPOSITE(RK3399_SCLK_USB3OTG0_SUSPEND, "clk_usb3otg0_suspend", pll_parents, + CLKSEL_CON(40), /* muxdiv_reg */ + __BIT(15), /* mux_mask */ + __BITS(9,0), /* div_mask */ + CLKGATE_CON(12), /* gate_reg */ + __BIT(3), /* gate_mask */ + 0), + RK_COMPOSITE(RK3399_SCLK_USB3OTG1_SUSPEND, "clk_usb3otg1_suspend", pll_parents, + CLKSEL_CON(41), /* muxdiv_reg */ + __BIT(15), /* mux_mask */ + __BITS(9,0), /* div_mask */ + CLKGATE_CON(12), /* gate_reg */ + __BIT(4), /* gate_mask */ + 0), + RK_COMPOSITE(RK3399_ACLK_USB3, "aclk_usb3", mux_pll_src_cpll_gpll_npll_parents, + CLKSEL_CON(39), /* muxdiv_reg */ + __BITS(7,6), /* mux_mask */ + __BITS(4,0), /* div_mask */ + CLKGATE_CON(12), /* gate_reg */ + __BIT(0), /* gate_mask */ + 0), + RK_GATE(RK3399_ACLK_USB3OTG0, "aclk_usb3otg0", "aclk_usb3", CLKGATE_CON(30), 1), + RK_GATE(RK3399_ACLK_USB3OTG1, "aclk_usb3otg1", "aclk_usb3", CLKGATE_CON(30), 2), + RK_GATE(RK3399_ACLK_USB3_RKSOC_AXI_PERF, "aclk_usb3_rksoc_axi_perf", "aclk_usb3", CLKGATE_CON(30), 3), + RK_GATE(RK3399_ACLK_USB3_GRF, "aclk_usb3_grf", "aclk_usb3", CLKGATE_CON(30), 4), +}; + +static int +rk3399_cru_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 +rk3399_cru_attach(device_t parent, device_t self, void *aux) +{ + struct rk_cru_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_bst = faa->faa_bst; + + sc->sc_clks = rk3399_cru_clks; + sc->sc_nclks = __arraycount(rk3399_cru_clks); + + sc->sc_softrst_base = SOFTRST_CON(0); + + if (rk_cru_attach(sc) != 0) + return; + + aprint_naive("\n"); + aprint_normal(": RK3399 CRU\n"); + + rk_cru_print(sc); +} Index: src/sys/arch/arm/rockchip/rk3399_cru.h diff -u /dev/null src/sys/arch/arm/rockchip/rk3399_cru.h:1.1 --- /dev/null Sun Aug 12 16:48:05 2018 +++ src/sys/arch/arm/rockchip/rk3399_cru.h Sun Aug 12 16:48:05 2018 @@ -0,0 +1,353 @@ +/* $NetBSD: rk3399_cru.h,v 1.1 2018/08/12 16:48:05 jmcneill Exp $ */ + +/*- + * Copyright (c) 2018 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 _RK3399_CRU_H +#define _RK3399_CRU_H + +/* + * Clocks + */ + +#define RK3399_PLL_APLLL 1 +#define RK3399_PLL_APLLB 2 +#define RK3399_PLL_DPLL 3 +#define RK3399_PLL_CPLL 4 +#define RK3399_PLL_GPLL 5 +#define RK3399_PLL_NPLL 6 +#define RK3399_PLL_VPLL 7 +#define RK3399_ARMCLKL 8 +#define RK3399_ARMCLKB 9 +#define RK3399_SCLK_I2C1 65 +#define RK3399_SCLK_I2C2 66 +#define RK3399_SCLK_I2C3 67 +#define RK3399_SCLK_I2C5 68 +#define RK3399_SCLK_I2C6 69 +#define RK3399_SCLK_I2C7 70 +#define RK3399_SCLK_SPI0 71 +#define RK3399_SCLK_SPI1 72 +#define RK3399_SCLK_SPI2 73 +#define RK3399_SCLK_SPI4 74 +#define RK3399_SCLK_SPI5 75 +#define RK3399_SCLK_SDMMC 76 +#define RK3399_SCLK_SDIO 77 +#define RK3399_SCLK_EMMC 78 +#define RK3399_SCLK_TSADC 79 +#define RK3399_SCLK_SARADC 80 +#define RK3399_SCLK_UART0 81 +#define RK3399_SCLK_UART1 82 +#define RK3399_SCLK_UART2 83 +#define RK3399_SCLK_UART3 84 +#define RK3399_SCLK_SPDIF_8CH 85 +#define RK3399_SCLK_I2S0_8CH 86 +#define RK3399_SCLK_I2S1_8CH 87 +#define RK3399_SCLK_I2S2_8CH 88 +#define RK3399_SCLK_I2S_8CH_OUT 89 +#define RK3399_SCLK_TIMER00 90 +#define RK3399_SCLK_TIMER01 91 +#define RK3399_SCLK_TIMER02 92 +#define RK3399_SCLK_TIMER03 93 +#define RK3399_SCLK_TIMER04 94 +#define RK3399_SCLK_TIMER05 95 +#define RK3399_SCLK_TIMER06 96 +#define RK3399_SCLK_TIMER07 97 +#define RK3399_SCLK_TIMER08 98 +#define RK3399_SCLK_TIMER09 99 +#define RK3399_SCLK_TIMER10 100 +#define RK3399_SCLK_TIMER11 101 +#define RK3399_SCLK_MACREF 102 +#define RK3399_SCLK_MAC_RX 103 +#define RK3399_SCLK_MAC_TX 104 +#define RK3399_SCLK_MAC 105 +#define RK3399_SCLK_MACREF_OUT 106 +#define RK3399_SCLK_VOP0_PWM 107 +#define RK3399_SCLK_VOP1_PWM 108 +#define RK3399_SCLK_RGA_CORE 109 +#define RK3399_SCLK_ISP0 110 +#define RK3399_SCLK_ISP1 111 +#define RK3399_SCLK_HDMI_CEC 112 +#define RK3399_SCLK_HDMI_SFR 113 +#define RK3399_SCLK_DP_CORE 114 +#define RK3399_SCLK_PVTM_CORE_L 115 +#define RK3399_SCLK_PVTM_CORE_B 116 +#define RK3399_SCLK_PVTM_GPU 117 +#define RK3399_SCLK_PVTM_DDR 118 +#define RK3399_SCLK_MIPIDPHY_REF 119 +#define RK3399_SCLK_MIPIDPHY_CFG 120 +#define RK3399_SCLK_HSICPHY 121 +#define RK3399_SCLK_USBPHY480M 122 +#define RK3399_SCLK_USB2PHY0_REF 123 +#define RK3399_SCLK_USB2PHY1_REF 124 +#define RK3399_SCLK_UPHY0_TCPDPHY_REF 125 +#define RK3399_SCLK_UPHY0_TCPDCORE 126 +#define RK3399_SCLK_UPHY1_TCPDPHY_REF 127 +#define RK3399_SCLK_UPHY1_TCPDCORE 128 +#define RK3399_SCLK_USB3OTG0_REF 129 +#define RK3399_SCLK_USB3OTG1_REF 130 +#define RK3399_SCLK_USB3OTG0_SUSPEND 131 +#define RK3399_SCLK_USB3OTG1_SUSPEND 132 +#define RK3399_SCLK_CRYPTO0 133 +#define RK3399_SCLK_CRYPTO1 134 +#define RK3399_SCLK_CCI_TRACE 135 +#define RK3399_SCLK_CS 136 +#define RK3399_SCLK_CIF_OUT 137 +#define RK3399_SCLK_PCIEPHY_REF 138 +#define RK3399_SCLK_PCIE_CORE 139 +#define RK3399_SCLK_M0_PERILP 140 +#define RK3399_SCLK_M0_PERILP_DEC 141 +#define RK3399_SCLK_CM0S 142 +#define RK3399_SCLK_DBG_NOC 143 +#define RK3399_SCLK_DBG_PD_CORE_B 144 +#define RK3399_SCLK_DBG_PD_CORE_L 145 +#define RK3399_SCLK_DFIMON0_TIMER 146 +#define RK3399_SCLK_DFIMON1_TIMER 147 +#define RK3399_SCLK_INTMEM0 148 +#define RK3399_SCLK_INTMEM1 149 +#define RK3399_SCLK_INTMEM2 150 +#define RK3399_SCLK_INTMEM3 151 +#define RK3399_SCLK_INTMEM4 152 +#define RK3399_SCLK_INTMEM5 153 +#define RK3399_SCLK_SDMMC_DRV 154 +#define RK3399_SCLK_SDMMC_SAMPLE 155 +#define RK3399_SCLK_SDIO_DRV 156 +#define RK3399_SCLK_SDIO_SAMPLE 157 +#define RK3399_SCLK_VDU_CORE 158 +#define RK3399_SCLK_VDU_CA 159 +#define RK3399_SCLK_PCIE_PM 160 +#define RK3399_SCLK_SPDIF_REC_DPTX 161 +#define RK3399_SCLK_DPHY_PLL 162 +#define RK3399_SCLK_DPHY_TX0_CFG 163 +#define RK3399_SCLK_DPHY_TX1RX1_CFG 164 +#define RK3399_SCLK_DPHY_RX0_CFG 165 +#define RK3399_SCLK_RMII_SRC 166 +#define RK3399_SCLK_PCIEPHY_REF100M 167 +#define RK3399_SCLK_DDRC 168 +#define RK3399_SCLK_TESTCLKOUT1 169 +#define RK3399_SCLK_TESTCLKOUT2 170 +#define RK3399_DCLK_VOP0 180 +#define RK3399_DCLK_VOP1 181 +#define RK3399_DCLK_VOP0_DIV 182 +#define RK3399_DCLK_VOP1_DIV 183 +#define RK3399_DCLK_M0_PERILP 184 +#define RK3399_DCLK_VOP0_FRAC 185 +#define RK3399_DCLK_VOP1_FRAC 186 +#define RK3399_FCLK_CM0S 190 +#define RK3399_ACLK_PERIHP 192 +#define RK3399_ACLK_PERIHP_NOC 193 +#define RK3399_ACLK_PERILP0 194 +#define RK3399_ACLK_PERILP0_NOC 195 +#define RK3399_ACLK_PERF_PCIE 196 +#define RK3399_ACLK_PCIE 197 +#define RK3399_ACLK_INTMEM 198 +#define RK3399_ACLK_TZMA 199 +#define RK3399_ACLK_DCF 200 +#define RK3399_ACLK_CCI 201 +#define RK3399_ACLK_CCI_NOC0 202 +#define RK3399_ACLK_CCI_NOC1 203 +#define RK3399_ACLK_CCI_GRF 204 +#define RK3399_ACLK_CENTER 205 +#define RK3399_ACLK_CENTER_MAIN_NOC 206 +#define RK3399_ACLK_CENTER_PERI_NOC 207 +#define RK3399_ACLK_GPU 208 +#define RK3399_ACLK_PERF_GPU 209 +#define RK3399_ACLK_GPU_GRF 210 +#define RK3399_ACLK_DMAC0_PERILP 211 +#define RK3399_ACLK_DMAC1_PERILP 212 +#define RK3399_ACLK_GMAC 213 +#define RK3399_ACLK_GMAC_NOC 214 +#define RK3399_ACLK_PERF_GMAC 215 +#define RK3399_ACLK_VOP0_NOC 216 +#define RK3399_ACLK_VOP0 217 +#define RK3399_ACLK_VOP1_NOC 218 +#define RK3399_ACLK_VOP1 219 +#define RK3399_ACLK_RGA 220 +#define RK3399_ACLK_RGA_NOC 221 +#define RK3399_ACLK_HDCP 222 +#define RK3399_ACLK_HDCP_NOC 223 +#define RK3399_ACLK_HDCP22 224 +#define RK3399_ACLK_IEP 225 +#define RK3399_ACLK_IEP_NOC 226 +#define RK3399_ACLK_VIO 227 +#define RK3399_ACLK_VIO_NOC 228 +#define RK3399_ACLK_ISP0 229 +#define RK3399_ACLK_ISP1 230 +#define RK3399_ACLK_ISP0_NOC 231 +#define RK3399_ACLK_ISP1_NOC 232 +#define RK3399_ACLK_ISP0_WRAPPER 233 +#define RK3399_ACLK_ISP1_WRAPPER 234 +#define RK3399_ACLK_VCODEC 235 +#define RK3399_ACLK_VCODEC_NOC 236 +#define RK3399_ACLK_VDU 237 +#define RK3399_ACLK_VDU_NOC 238 +#define RK3399_ACLK_PERI 239 +#define RK3399_ACLK_EMMC 240 +#define RK3399_ACLK_EMMC_CORE 241 +#define RK3399_ACLK_EMMC_NOC 242 +#define RK3399_ACLK_EMMC_GRF 243 +#define RK3399_ACLK_USB3 244 +#define RK3399_ACLK_USB3_NOC 245 +#define RK3399_ACLK_USB3OTG0 246 +#define RK3399_ACLK_USB3OTG1 247 +#define RK3399_ACLK_USB3_RKSOC_AXI_PERF 248 +#define RK3399_ACLK_USB3_GRF 249 +#define RK3399_ACLK_GIC 250 +#define RK3399_ACLK_GIC_NOC 251 +#define RK3399_ACLK_GIC_ADB400_CORE_L_2_GIC 252 +#define RK3399_ACLK_GIC_ADB400_CORE_B_2_GIC 253 +#define RK3399_ACLK_GIC_ADB400_GIC_2_CORE_L 254 +#define RK3399_ACLK_GIC_ADB400_GIC_2_CORE_B 255 +#define RK3399_ACLK_CORE_ADB400_CORE_L_2_CCI500 256 +#define RK3399_ACLK_CORE_ADB400_CORE_B_2_CCI500 257 +#define RK3399_ACLK_ADB400M_PD_CORE_L 258 +#define RK3399_ACLK_ADB400M_PD_CORE_B 259 +#define RK3399_ACLK_PERF_CORE_L 260 +#define RK3399_ACLK_PERF_CORE_B 261 +#define RK3399_ACLK_GIC_PRE 262 +#define RK3399_ACLK_VOP0_PRE 263 +#define RK3399_ACLK_VOP1_PRE 264 +#define RK3399_PCLK_PERIHP 320 +#define RK3399_PCLK_PERIHP_NOC 321 +#define RK3399_PCLK_PERILP0 322 +#define RK3399_PCLK_PERILP1 323 +#define RK3399_PCLK_PERILP1_NOC 324 +#define RK3399_PCLK_PERILP_SGRF 325 +#define RK3399_PCLK_PERIHP_GRF 326 +#define RK3399_PCLK_PCIE 327 +#define RK3399_PCLK_SGRF 328 +#define RK3399_PCLK_INTR_ARB 329 +#define RK3399_PCLK_CENTER_MAIN_NOC 330 +#define RK3399_PCLK_CIC 331 +#define RK3399_PCLK_COREDBG_B 332 +#define RK3399_PCLK_COREDBG_L 333 +#define RK3399_PCLK_DBG_CXCS_PD_CORE_B 334 +#define RK3399_PCLK_DCF 335 +#define RK3399_PCLK_GPIO2 336 +#define RK3399_PCLK_GPIO3 337 +#define RK3399_PCLK_GPIO4 338 +#define RK3399_PCLK_GRF 339 +#define RK3399_PCLK_HSICPHY 340 +#define RK3399_PCLK_I2C1 341 +#define RK3399_PCLK_I2C2 342 +#define RK3399_PCLK_I2C3 343 +#define RK3399_PCLK_I2C5 344 +#define RK3399_PCLK_I2C6 345 +#define RK3399_PCLK_I2C7 346 +#define RK3399_PCLK_SPI0 347 +#define RK3399_PCLK_SPI1 348 +#define RK3399_PCLK_SPI2 349 +#define RK3399_PCLK_SPI4 350 +#define RK3399_PCLK_SPI5 351 +#define RK3399_PCLK_UART0 352 +#define RK3399_PCLK_UART1 353 +#define RK3399_PCLK_UART2 354 +#define RK3399_PCLK_UART3 355 +#define RK3399_PCLK_TSADC 356 +#define RK3399_PCLK_SARADC 357 +#define RK3399_PCLK_GMAC 358 +#define RK3399_PCLK_GMAC_NOC 359 +#define RK3399_PCLK_TIMER0 360 +#define RK3399_PCLK_TIMER1 361 +#define RK3399_PCLK_EDP 362 +#define RK3399_PCLK_EDP_NOC 363 +#define RK3399_PCLK_EDP_CTRL 364 +#define RK3399_PCLK_VIO 365 +#define RK3399_PCLK_VIO_NOC 366 +#define RK3399_PCLK_VIO_GRF 367 +#define RK3399_PCLK_MIPI_DSI0 368 +#define RK3399_PCLK_MIPI_DSI1 369 +#define RK3399_PCLK_HDCP 370 +#define RK3399_PCLK_HDCP_NOC 371 +#define RK3399_PCLK_HDMI_CTRL 372 +#define RK3399_PCLK_DP_CTRL 373 +#define RK3399_PCLK_HDCP22 374 +#define RK3399_PCLK_GASKET 375 +#define RK3399_PCLK_DDR 376 +#define RK3399_PCLK_DDR_MON 377 +#define RK3399_PCLK_DDR_SGRF 378 +#define RK3399_PCLK_ISP1_WRAPPER 379 +#define RK3399_PCLK_WDT 380 +#define RK3399_PCLK_EFUSE1024NS 381 +#define RK3399_PCLK_EFUSE1024S 382 +#define RK3399_PCLK_PMU_INTR_ARB 383 +#define RK3399_PCLK_MAILBOX0 384 +#define RK3399_PCLK_USBPHY_MUX_G 385 +#define RK3399_PCLK_UPHY0_TCPHY_G 386 +#define RK3399_PCLK_UPHY0_TCPD_G 387 +#define RK3399_PCLK_UPHY1_TCPHY_G 388 +#define RK3399_PCLK_UPHY1_TCPD_G 389 +#define RK3399_PCLK_ALIVE 390 +#define RK3399_HCLK_PERIHP 448 +#define RK3399_HCLK_PERILP0 449 +#define RK3399_HCLK_PERILP1 450 +#define RK3399_HCLK_PERILP0_NOC 451 +#define RK3399_HCLK_PERILP1_NOC 452 +#define RK3399_HCLK_M0_PERILP 453 +#define RK3399_HCLK_M0_PERILP_NOC 454 +#define RK3399_HCLK_AHB1TOM 455 +#define RK3399_HCLK_HOST0 456 +#define RK3399_HCLK_HOST0_ARB 457 +#define RK3399_HCLK_HOST1 458 +#define RK3399_HCLK_HOST1_ARB 459 +#define RK3399_HCLK_HSIC 460 +#define RK3399_HCLK_SD 461 +#define RK3399_HCLK_SDMMC 462 +#define RK3399_HCLK_SDMMC_NOC 463 +#define RK3399_HCLK_M_CRYPTO0 464 +#define RK3399_HCLK_M_CRYPTO1 465 +#define RK3399_HCLK_S_CRYPTO0 466 +#define RK3399_HCLK_S_CRYPTO1 467 +#define RK3399_HCLK_I2S0_8CH 468 +#define RK3399_HCLK_I2S1_8CH 469 +#define RK3399_HCLK_I2S2_8CH 470 +#define RK3399_HCLK_SPDIF 471 +#define RK3399_HCLK_VOP0_NOC 472 +#define RK3399_HCLK_VOP0 473 +#define RK3399_HCLK_VOP1_NOC 474 +#define RK3399_HCLK_VOP1 475 +#define RK3399_HCLK_ROM 476 +#define RK3399_HCLK_IEP 477 +#define RK3399_HCLK_IEP_NOC 478 +#define RK3399_HCLK_ISP0 479 +#define RK3399_HCLK_ISP1 480 +#define RK3399_HCLK_ISP0_NOC 481 +#define RK3399_HCLK_ISP1_NOC 482 +#define RK3399_HCLK_ISP0_WRAPPER 483 +#define RK3399_HCLK_ISP1_WRAPPER 484 +#define RK3399_HCLK_RGA 485 +#define RK3399_HCLK_RGA_NOC 486 +#define RK3399_HCLK_HDCP 487 +#define RK3399_HCLK_HDCP_NOC 488 +#define RK3399_HCLK_HDCP22 489 +#define RK3399_HCLK_VCODEC 490 +#define RK3399_HCLK_VCODEC_NOC 491 +#define RK3399_HCLK_VDU 492 +#define RK3399_HCLK_VDU_NOC 493 +#define RK3399_HCLK_SDIO 494 +#define RK3399_HCLK_SDIO_NOC 495 +#define RK3399_HCLK_SDIOAUDIO_NOC 496 + +#endif /* !_RK3399_CRU_H */ Index: src/sys/arch/arm/rockchip/rk3399_iomux.c diff -u /dev/null src/sys/arch/arm/rockchip/rk3399_iomux.c:1.1 --- /dev/null Sun Aug 12 16:48:05 2018 +++ src/sys/arch/arm/rockchip/rk3399_iomux.c Sun Aug 12 16:48:05 2018 @@ -0,0 +1,464 @@ +/* $NetBSD: rk3399_iomux.c,v 1.1 2018/08/12 16:48:05 jmcneill Exp $ */ + +/*- + * Copyright (c) 2018 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. + */ + +//#define RK3399_IOMUX_DEBUG + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: rk3399_iomux.c,v 1.1 2018/08/12 16:48:05 jmcneill Exp $"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/device.h> +#include <sys/intr.h> +#include <sys/systm.h> +#include <sys/mutex.h> +#include <sys/kmem.h> +#include <sys/gpio.h> +#include <sys/lwp.h> + +#include <dev/fdt/fdtvar.h> +#include <dev/fdt/syscon.h> + +/* PU/PD control */ +#define GRF_GPIO_P_CTL(_idx) (0x3 << (((_idx) & 7) * 2)) +#define GRF_GPIO_P_WRITE_EN(_idx) (0x3 << (((_idx) & 7) * 2 + 16)) +/* Different bias value mapping for GRF and PMU registers */ +#define GRF_GPIO_P_CTL_Z 0 +#define GRF_GPIO_P_CTL_PULLDOWN 1 +#define GRF_GPIO_P_CTL_Z_ALT 2 +#define GRF_GPIO_P_CTL_PULLUP 3 +#define PMU_GPIO_P_CTL_Z 0 +#define PMU_GPIO_P_CTL_PULLUP 1 +#define PMU_GPIO_P_CTL_PULLDOWN 2 +#define PMU_GPIO_P_CTL_RESERVED 3 + +/* Drive strength control */ +/* Different drive strength value mapping for GRF and PMU registers */ +#define GRF_GPIO_E_CTL_2MA 0 +#define GRF_GPIO_E_CTL_4MA 1 +#define GRF_GPIO_E_CTL_8MA 2 +#define GRF_GPIO_E_CTL_12MA 3 +#define PMU_GPIO_E_CTL_5MA 0 +#define PMU_GPIO_E_CTL_10MA 1 +#define PMU_GPIO_E_CTL_15MA 2 +#define PMU_GPIO_E_CTL_20MA 3 + +enum rk3399_drv_type { + RK3399_DRV_TYPE_IO_DEFAULT, + RK3399_DRV_TYPE_IO_1V8_3V0, + RK3399_DRV_TYPE_IO_1V8, + RK3399_DRV_TYPE_IO_1V8_3V0_AUTO, + RK3399_DRV_TYPE_IO_3V3, +}; + +static int rk3399_drv_strength[5][9] = { + [RK3399_DRV_TYPE_IO_DEFAULT] = { 2, 4, 8, 12, -1 }, + [RK3399_DRV_TYPE_IO_1V8_3V0] = { 3, 6, 9, 12, -1 }, + [RK3399_DRV_TYPE_IO_1V8] = { 5, 10, 15, 20, -1 }, + [RK3399_DRV_TYPE_IO_1V8_3V0_AUTO] = { 4, 6, 8, 10, 12, 14, 16, 18, -1 }, + [RK3399_DRV_TYPE_IO_3V3] = { 4, 7, 10, 13, 16, 19, 22, 26, -1 }, +}; + +struct rk3399_iomux { + enum rk3399_drv_type drv_type; +}; + +struct rk3399_iomux_bank { + struct rk3399_iomux iomux[5]; + u_int regs; +#define RK_IOMUX_REGS_GRF 0 +#define RK_IOMUX_REGS_PMU 1 +}; + +static const struct rk3399_iomux_bank rk3399_iomux_banks[] = { + [0] = { + .regs = RK_IOMUX_REGS_PMU, + .iomux = { + [0] = { .drv_type = RK3399_DRV_TYPE_IO_1V8 }, + [1] = { .drv_type = RK3399_DRV_TYPE_IO_1V8 }, + [2] = { .drv_type = RK3399_DRV_TYPE_IO_DEFAULT }, + [3] = { .drv_type = RK3399_DRV_TYPE_IO_DEFAULT }, + }, + }, + [1] = { + .regs = RK_IOMUX_REGS_PMU, + .iomux = { + [0] = { .drv_type = RK3399_DRV_TYPE_IO_1V8_3V0 }, + [1] = { .drv_type = RK3399_DRV_TYPE_IO_1V8_3V0 }, + [2] = { .drv_type = RK3399_DRV_TYPE_IO_1V8_3V0 }, + [3] = { .drv_type = RK3399_DRV_TYPE_IO_1V8_3V0 }, + } + }, + [2] = { + .regs = RK_IOMUX_REGS_GRF, + .iomux = { + [0] = { .drv_type = RK3399_DRV_TYPE_IO_1V8_3V0 }, + [1] = { .drv_type = RK3399_DRV_TYPE_IO_1V8_3V0 }, + [2] = { .drv_type = RK3399_DRV_TYPE_IO_1V8 }, + [3] = { .drv_type = RK3399_DRV_TYPE_IO_1V8 }, + }, + }, + [3] = { + .regs = RK_IOMUX_REGS_GRF, + .iomux = { + [0] = { .drv_type = RK3399_DRV_TYPE_IO_3V3 }, + [1] = { .drv_type = RK3399_DRV_TYPE_IO_3V3 }, + [2] = { .drv_type = RK3399_DRV_TYPE_IO_3V3 }, + [3] = { .drv_type = RK3399_DRV_TYPE_IO_1V8_3V0 }, + }, + }, + [4] = { + .regs = RK_IOMUX_REGS_GRF, + .iomux = { + [0] = { .drv_type = RK3399_DRV_TYPE_IO_1V8_3V0 }, + [1] = { .drv_type = RK3399_DRV_TYPE_IO_1V8_3V0_AUTO }, + [2] = { .drv_type = RK3399_DRV_TYPE_IO_1V8_3V0 }, + [3] = { .drv_type = RK3399_DRV_TYPE_IO_1V8_3V0 }, + }, + }, +}; + +#define RK3399_IOMUX_BANK_IS_PMU(_bank) (rk3399_iomux_banks[(_bank)].regs == RK_IOMUX_REGS_PMU) + +struct rk3399_iomux_conf { + const struct rk3399_iomux_bank *banks; + u_int nbanks; +}; + +static const struct rk3399_iomux_conf rk3399_iomux_conf = { + .banks = rk3399_iomux_banks, + .nbanks = __arraycount(rk3399_iomux_banks), +}; + +static const struct of_compat_data compat_data[] = { + { "rockchip,rk3399-pinctrl", (uintptr_t)&rk3399_iomux_conf }, + { NULL } +}; + +struct rk3399_iomux_softc { + device_t sc_dev; + struct syscon *sc_syscon[2]; + + const struct rk3399_iomux_conf *sc_conf; +}; + +#define LOCK(syscon) \ + syscon_lock(syscon) +#define UNLOCK(syscon) \ + syscon_unlock(syscon) +#define RD4(syscon, reg) \ + syscon_read_4(syscon, (reg)) +#define WR4(syscon, reg, val) \ + syscon_write_4(syscon, (reg), (val)) + +static int rk3399_iomux_match(device_t, cfdata_t, void *); +static void rk3399_iomux_attach(device_t, device_t, void *); + +CFATTACH_DECL_NEW(rk3399_iomux, sizeof(struct rk3399_iomux_softc), + rk3399_iomux_match, rk3399_iomux_attach, NULL, NULL); + +static void +rk3399_iomux_set_bias(struct rk3399_iomux_softc *sc, u_int bank, u_int idx, int flags) +{ + const struct rk3399_iomux_bank *banks = sc->sc_conf->banks; + bus_size_t reg; + u_int bias; + + KASSERT(bank < sc->sc_conf->nbanks); + + struct syscon * const syscon = sc->sc_syscon[banks[bank].regs]; + if (RK3399_IOMUX_BANK_IS_PMU(bank)) { + reg = 0x00040 + (0x10 * bank); + } else { + reg = 0x0e040 + (0x10 * (bank - 2)); + } + reg += 0x4 * (idx / 8); + + if (flags == GPIO_PIN_PULLUP) { + bias = RK3399_IOMUX_BANK_IS_PMU(bank) ? PMU_GPIO_P_CTL_PULLUP : GRF_GPIO_P_CTL_PULLUP; + } else if (flags == GPIO_PIN_PULLDOWN) { + bias = RK3399_IOMUX_BANK_IS_PMU(bank) ? PMU_GPIO_P_CTL_PULLDOWN : GRF_GPIO_P_CTL_PULLDOWN; + } else { + bias = RK3399_IOMUX_BANK_IS_PMU(bank) ? PMU_GPIO_P_CTL_Z : GRF_GPIO_P_CTL_Z; + } + + const uint32_t bias_val = __SHIFTIN(bias, GRF_GPIO_P_CTL(idx)); + const uint32_t bias_mask = GRF_GPIO_P_WRITE_EN(idx); + +#ifdef RK3399_IOMUX_DEBUG + printf("%s: bank %d idx %d flags %#x: %08x -> ", __func__, bank, idx, flags, RD4(syscon, reg)); +#endif + WR4(syscon, reg, bias_val | bias_mask); +#ifdef RK3399_IOMUX_DEBUG + printf("%08x (reg %#lx)\n", RD4(syscon, reg), reg); +#endif +} + +static int +rk3399_iomux_map_drive_strength(struct rk3399_iomux_softc *sc, enum rk3399_drv_type drv_type, u_int val) +{ + for (int n = 0; rk3399_drv_strength[drv_type][n] != -1; n++) + if (rk3399_drv_strength[drv_type][n] == val) + return n; + return -1; +} + +static int +rk3399_iomux_set_drive_strength(struct rk3399_iomux_softc *sc, u_int bank, u_int idx, u_int val) +{ + const struct rk3399_iomux_bank *banks = sc->sc_conf->banks; + uint32_t drv_mask, drv_val; + bus_size_t reg; + + KASSERT(bank < sc->sc_conf->nbanks); + + if (idx >= 32) + return EINVAL; + + const int drv = rk3399_iomux_map_drive_strength(sc, banks[bank].iomux[idx / 8].drv_type, val); + if (drv == -1) + return EINVAL; + + struct syscon * const syscon = sc->sc_syscon[banks[bank].regs]; + switch (bank) { + case 0: + case 1: + reg = 0x00040 + (0x10 * bank) + 0x4 * (idx / 4); + drv_mask = 0x3 << ((idx & 7) * 2); + break; + case 2: + reg = 0x0e100 + 0x4 * (idx / 4); + drv_mask = 0x3 << ((idx & 7) * 2); + break; + case 3: + switch (idx / 8) { + case 0: + case 1: + case 2: + reg = 0x0e110 + 0x8 * (idx / 4); + drv_mask = 0x7 << ((idx & 7) * 3); + break; + case 3: + reg = 0x0e128; + drv_mask = 0x3 << ((idx & 7) * 2); + break; + default: + return EINVAL; + } + break; + case 4: + switch (idx / 8) { + case 0: + reg = 0x0e12c; + drv_mask = 0x3 << ((idx & 7) * 2); + break; + case 1: + reg = 0x0e130; + drv_mask = 0x7 << ((idx & 7) * 3); + break; + case 2: + reg = 0x0e138; + drv_mask = 0x3 << ((idx & 7) * 2); + break; + case 3: + reg = 0x0e13c; + drv_mask = 0x3 << ((idx & 7) * 2); + break; + default: + return EINVAL; + } + break; + default: + return EINVAL; + } + drv_val = __SHIFTIN(val, drv_mask); + + while (drv_mask) { + const uint32_t write_val = drv_val & 0xffff; + const uint32_t write_mask = (drv_mask & 0xffff) << 16; + if (write_mask) { +#ifdef RK3399_IOMUX_DEBUG + printf("%s: bank %d idx %d val %d: %08x -> ", __func__, bank, idx, val, RD4(syscon, reg)); +#endif + WR4(syscon, reg, write_val | write_mask); +#ifdef RK3399_IOMUX_DEBUG + printf("%08x (reg %#lx)\n", RD4(syscon, reg), reg); +#endif + } + reg += 0x4; + drv_val >>= 16; + drv_mask >>= 16; + } + + return 0; +} + +static void +rk3399_iomux_set_mux(struct rk3399_iomux_softc *sc, u_int bank, u_int idx, u_int mux) +{ + const struct rk3399_iomux_bank *banks = sc->sc_conf->banks; + bus_size_t reg; + uint32_t mask; + + KASSERT(bank < sc->sc_conf->nbanks); + + struct syscon * const syscon = sc->sc_syscon[banks[bank].regs]; + if (RK3399_IOMUX_BANK_IS_PMU(bank)) { + reg = 0x00000 + (0x10 * bank); + } else { + reg = 0x0e000 + (0x10 * (bank - 2)); + } + reg += 0x4 * (idx / 4); + mask = 3 << ((idx & 7) * 2); + +#ifdef RK3399_IOMUX_DEBUG + printf("%s: bank %d idx %d mux %#x: %08x -> ", __func__, bank, idx, mux, RD4(syscon, reg)); +#endif + WR4(syscon, reg, (mask << 16) | __SHIFTIN(mux, mask)); +#ifdef RK3399_IOMUX_DEBUG + printf("%08x (reg %#lx)\n", RD4(syscon, reg), reg); +#endif +} + +static int +rk3399_iomux_config(struct rk3399_iomux_softc *sc, const int phandle, u_int bank, u_int idx, u_int mux) +{ + u_int drv; + + if (of_hasprop(phandle, "bias-disable")) + rk3399_iomux_set_bias(sc, bank, idx, 0); + else if (of_hasprop(phandle, "bias-pull-up")) + rk3399_iomux_set_bias(sc, bank, idx, GPIO_PIN_PULLUP); + else if (of_hasprop(phandle, "bias-pull-down")) + rk3399_iomux_set_bias(sc, bank, idx, GPIO_PIN_PULLDOWN); + + if (of_getprop_uint32(phandle, "drive-strength", &drv) == 0) { + if (rk3399_iomux_set_drive_strength(sc, bank, idx, drv) != 0) + return EINVAL; + } + +#if notyet + if (of_hasprop(phandle, "input-enable")) + rk3399_iomux_set_direction(sc, bank, idx, GPIO_PIN_INPUT, -1); + else if (of_hasprop(phandle, "output-high")) + rk3399_iomux_set_direction(sc, bank, idx, GPIO_PIN_OUTPUT, GPIO_PIN_HIGH); + else if (of_hasprop(phandle, "output-low")) + rk3399_iomux_set_direction(sc, bank, idx, GPIO_PIN_OUTPUT, GPIO_PIN_LOW); +#endif + + rk3399_iomux_set_mux(sc, bank, idx, mux); + + return 0; +} + +static int +rk3399_iomux_pinctrl_set_config(device_t dev, const void *data, size_t len) +{ + struct rk3399_iomux_softc * const sc = device_private(dev); + const struct rk3399_iomux_bank *banks = sc->sc_conf->banks; + int pins_len; + + if (len != 4) + return -1; + + const int phandle = fdtbus_get_phandle_from_native(be32dec(data)); + const u_int *pins = fdtbus_get_prop(phandle, "rockchip,pins", &pins_len); + + while (pins_len >= 16) { + const u_int bank = be32toh(pins[0]); + const u_int idx = be32toh(pins[1]); + const u_int mux = be32toh(pins[2]); + const int cfg = fdtbus_get_phandle_from_native(be32toh(pins[3])); + + struct syscon * const syscon = sc->sc_syscon[banks[bank].regs]; + LOCK(syscon); + rk3399_iomux_config(sc, cfg, bank, idx, mux); + UNLOCK(syscon); + + pins_len -= 16; + pins += 4; + } + + return 0; +} + +static struct fdtbus_pinctrl_controller_func rk3399_iomux_pinctrl_funcs = { + .set_config = rk3399_iomux_pinctrl_set_config, +}; + +static int +rk3399_iomux_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 +rk3399_iomux_attach(device_t parent, device_t self, void *aux) +{ + struct rk3399_iomux_softc * const sc = device_private(self); + struct fdt_attach_args * const faa = aux; + const int phandle = faa->faa_phandle; + int child, sub; + + sc->sc_dev = self; + sc->sc_syscon[RK_IOMUX_REGS_GRF] = fdtbus_syscon_acquire(phandle, "rockchip,grf"); + if (sc->sc_syscon[RK_IOMUX_REGS_GRF] == NULL) { + aprint_error(": couldn't acquire grf syscon\n"); + return; + } + sc->sc_syscon[RK_IOMUX_REGS_PMU] = fdtbus_syscon_acquire(phandle, "rockchip,pmu"); + if (sc->sc_syscon[RK_IOMUX_REGS_PMU] == NULL) { + aprint_error(": couldn't acquire pmu syscon\n"); + return; + } + sc->sc_conf = (void *)of_search_compatible(phandle, compat_data)->data; + + aprint_naive("\n"); + aprint_normal(": RK3399 IOMUX control\n"); + + for (child = OF_child(phandle); child; child = OF_peer(child)) { + for (sub = OF_child(child); sub; sub = OF_peer(sub)) { + if (!of_hasprop(sub, "rockchip,pins")) + continue; + fdtbus_register_pinctrl_config(self, sub, &rk3399_iomux_pinctrl_funcs); + } + } + + fdtbus_pinctrl_configure(); + + for (child = OF_child(phandle); child; child = OF_peer(child)) { + struct fdt_attach_args cfaa = *faa; + cfaa.faa_phandle = child; + cfaa.faa_name = fdtbus_get_string(child, "name"); + cfaa.faa_quiet = false; + + config_found(self, &cfaa, NULL); + } +} Index: src/sys/arch/arm/rockchip/rk3399_platform.h diff -u /dev/null src/sys/arch/arm/rockchip/rk3399_platform.h:1.1 --- /dev/null Sun Aug 12 16:48:05 2018 +++ src/sys/arch/arm/rockchip/rk3399_platform.h Sun Aug 12 16:48:05 2018 @@ -0,0 +1,40 @@ +/* $NetBSD: rk3399_platform.h,v 1.1 2018/08/12 16:48:05 jmcneill Exp $ */ + +/*- + * Copyright (c) 2018 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 _ARM_RK3399_PLATFORM_H +#define _ARM_RK3399_PLATFORM_H + +#include <arch/evbarm/fdt/platform.h> + +#define RK3399_CORE_VBASE KERNEL_IO_VBASE +#define RK3399_CORE_PBASE 0xf8000000 +#define RK3399_CORE_SIZE 0x08000000 + +#define RK3399_UART_FREQ 24000000 + +#endif /* _ARM_RK3399_PLATFORM_H */ Index: src/sys/arch/arm/rockchip/rk3399_pmucru.c diff -u /dev/null src/sys/arch/arm/rockchip/rk3399_pmucru.c:1.1 --- /dev/null Sun Aug 12 16:48:05 2018 +++ src/sys/arch/arm/rockchip/rk3399_pmucru.c Sun Aug 12 16:48:05 2018 @@ -0,0 +1,333 @@ +/* $NetBSD: rk3399_pmucru.c,v 1.1 2018/08/12 16:48:05 jmcneill Exp $ */ + +/*- + * Copyright (c) 2018 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: rk3399_pmucru.c,v 1.1 2018/08/12 16:48:05 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/rockchip/rk_cru.h> +#include <arm/rockchip/rk3399_pmucru.h> + +#define PLL_CON(n) (0x0000 + (n) * 4) +#define CLKSEL_CON(n) (0x0080 + (n) * 4) +#define CLKGATE_CON(n) (0x0100 + (n) * 4) +#define SOFTRST_CON(n) (0x0110 + (n) * 4) + +static int rk3399_pmucru_match(device_t, cfdata_t, void *); +static void rk3399_pmucru_attach(device_t, device_t, void *); + +static const char * const compatible[] = { + "rockchip,rk3399-pmucru", + NULL +}; + +CFATTACH_DECL_NEW(rk3399_pmucru, sizeof(struct rk_cru_softc), + rk3399_pmucru_match, rk3399_pmucru_attach, NULL, NULL); + +static const struct rk_cru_pll_rate pll_rates[] = { + RK_PLL_RATE(2208000000, 1, 92, 1, 1, 1, 0), + RK_PLL_RATE(2184000000, 1, 91, 1, 1, 1, 0), + RK_PLL_RATE(2160000000, 1, 90, 1, 1, 1, 0), + RK_PLL_RATE(2136000000, 1, 89, 1, 1, 1, 0), + RK_PLL_RATE(2112000000, 1, 88, 1, 1, 1, 0), + RK_PLL_RATE(2088000000, 1, 87, 1, 1, 1, 0), + RK_PLL_RATE(2064000000, 1, 86, 1, 1, 1, 0), + RK_PLL_RATE(2040000000, 1, 85, 1, 1, 1, 0), + RK_PLL_RATE(2016000000, 1, 84, 1, 1, 1, 0), + RK_PLL_RATE(1992000000, 1, 83, 1, 1, 1, 0), + RK_PLL_RATE(1968000000, 1, 82, 1, 1, 1, 0), + RK_PLL_RATE(1944000000, 1, 81, 1, 1, 1, 0), + RK_PLL_RATE(1920000000, 1, 80, 1, 1, 1, 0), + RK_PLL_RATE(1896000000, 1, 79, 1, 1, 1, 0), + RK_PLL_RATE(1872000000, 1, 78, 1, 1, 1, 0), + RK_PLL_RATE(1848000000, 1, 77, 1, 1, 1, 0), + RK_PLL_RATE(1824000000, 1, 76, 1, 1, 1, 0), + RK_PLL_RATE(1800000000, 1, 75, 1, 1, 1, 0), + RK_PLL_RATE(1776000000, 1, 74, 1, 1, 1, 0), + RK_PLL_RATE(1752000000, 1, 73, 1, 1, 1, 0), + RK_PLL_RATE(1728000000, 1, 72, 1, 1, 1, 0), + RK_PLL_RATE(1704000000, 1, 71, 1, 1, 1, 0), + RK_PLL_RATE(1680000000, 1, 70, 1, 1, 1, 0), + RK_PLL_RATE(1656000000, 1, 69, 1, 1, 1, 0), + RK_PLL_RATE(1632000000, 1, 68, 1, 1, 1, 0), + RK_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0), + RK_PLL_RATE(1600000000, 3, 200, 1, 1, 1, 0), + RK_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0), + RK_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0), + RK_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0), + RK_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0), + RK_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0), + RK_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0), + RK_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0), + RK_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0), + RK_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0), + RK_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0), + RK_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0), + RK_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0), + RK_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0), + RK_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0), + RK_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0), + RK_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0), + RK_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0), + RK_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0), + RK_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0), + RK_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0), + RK_PLL_RATE(1000000000, 1, 125, 3, 1, 1, 0), + RK_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0), + RK_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0), + RK_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0), + RK_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0), + RK_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0), + RK_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0), + RK_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0), + RK_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0), + RK_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0), + RK_PLL_RATE( 800000000, 1, 100, 3, 1, 1, 0), + RK_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0), + RK_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0), + RK_PLL_RATE( 676000000, 3, 169, 2, 1, 1, 0), + RK_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0), + RK_PLL_RATE( 594000000, 1, 99, 4, 1, 1, 0), + RK_PLL_RATE( 533250000, 8, 711, 4, 1, 1, 0), + RK_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0), + RK_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0), + RK_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0), + RK_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0), + RK_PLL_RATE( 297000000, 1, 99, 4, 2, 1, 0), + RK_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0), + RK_PLL_RATE( 148500000, 1, 99, 4, 4, 1, 0), + RK_PLL_RATE( 106500000, 1, 71, 4, 4, 1, 0), + RK_PLL_RATE( 96000000, 1, 64, 4, 4, 1, 0), + RK_PLL_RATE( 74250000, 2, 99, 4, 4, 1, 0), + RK_PLL_RATE( 65000000, 1, 65, 6, 4, 1, 0), + RK_PLL_RATE( 54000000, 1, 54, 6, 4, 1, 0), + RK_PLL_RATE( 27000000, 1, 27, 6, 4, 1, 0), +}; + +#define PLL_CON0 0x00 +#define PLL_FBDIV __BITS(11,0) + +#define PLL_CON1 0x04 +#define PLL_POSTDIV2 __BITS(14,12) +#define PLL_POSTDIV1 __BITS(10,8) +#define PLL_REFDIV __BITS(5,0) + +#define PLL_CON2 0x08 +#define PLL_LOCK __BIT(31) +#define PLL_FRACDIV __BITS(23,0) + +#define PLL_CON3 0x0c +#define PLL_WORK_MODE __BITS(9,8) +#define PLL_WORK_MODE_SLOW 0 +#define PLL_WORK_MODE_NORMAL 1 +#define PLL_WORK_MODE_DEEP_SLOW 2 +#define PLL_DSMPD __BIT(3) + +#define PLL_WRITE_MASK 0xffff0000 + +static u_int +rk3399_pmucru_pll_get_rate(struct rk_cru_softc *sc, + struct rk_cru_clk *clk) +{ + struct rk_cru_pll *pll = &clk->u.pll; + struct clk *clkp, *clkp_parent; + u_int foutvco, foutpostdiv; + + KASSERT(clk->type == RK_CRU_PLL); + + clkp = &clk->base; + clkp_parent = clk_get_parent(clkp); + if (clkp_parent == NULL) + return 0; + + const u_int fref = clk_get_rate(clkp_parent); + if (fref == 0) + return 0; + + const uint32_t con0 = CRU_READ(sc, pll->con_base + PLL_CON0); + const uint32_t con1 = CRU_READ(sc, pll->con_base + PLL_CON1); + const uint32_t con2 = CRU_READ(sc, pll->con_base + PLL_CON2); + const uint32_t con3 = CRU_READ(sc, pll->con_base + PLL_CON3); + + const u_int fbdiv = __SHIFTOUT(con0, PLL_FBDIV); + const u_int postdiv2 = __SHIFTOUT(con1, PLL_POSTDIV2); + const u_int postdiv1 = __SHIFTOUT(con1, PLL_POSTDIV1); + const u_int refdiv = __SHIFTOUT(con1, PLL_REFDIV); + const u_int fracdiv = __SHIFTOUT(con2, PLL_FRACDIV); + const u_int dsmpd = __SHIFTOUT(con3, PLL_DSMPD); + + if (dsmpd == 1) { + /* integer mode */ + foutvco = fref / refdiv * fbdiv; + } else { + /* fractional mode */ + foutvco = fref / refdiv * fbdiv + ((fref * fracdiv) >> 24); + } + foutpostdiv = foutvco / postdiv1 / postdiv2; + + return foutpostdiv; +} + +static int +rk3399_pmucru_pll_set_rate(struct rk_cru_softc *sc, + struct rk_cru_clk *clk, u_int rate) +{ + struct rk_cru_pll *pll = &clk->u.pll; + const struct rk_cru_pll_rate *pll_rate = NULL; + uint32_t val; + int retry; + + KASSERT(clk->type == RK_CRU_PLL); + + if (pll->rates == NULL || rate == 0) + return EIO; + + for (int i = 0; i < pll->nrates; i++) + if (pll->rates[i].rate == rate) { + pll_rate = &pll->rates[i]; + break; + } + if (pll_rate == NULL) + return EINVAL; + + val = __SHIFTIN(PLL_WORK_MODE_SLOW, PLL_WORK_MODE) | (PLL_WORK_MODE << 16); + CRU_WRITE(sc, pll->con_base + PLL_CON3, val); + + CRU_WRITE(sc, pll->con_base + PLL_CON0, + __SHIFTIN(pll_rate->fbdiv, PLL_FBDIV) | + PLL_WRITE_MASK); + + CRU_WRITE(sc, pll->con_base + PLL_CON1, + __SHIFTIN(pll_rate->postdiv2, PLL_POSTDIV2) | + __SHIFTIN(pll_rate->postdiv1, PLL_POSTDIV1) | + __SHIFTIN(pll_rate->refdiv, PLL_REFDIV) | + PLL_WRITE_MASK); + + val = CRU_READ(sc, pll->con_base + PLL_CON2); + val &= ~PLL_FRACDIV; + val |= __SHIFTIN(pll_rate->fracdiv, PLL_FRACDIV); + CRU_WRITE(sc, pll->con_base + PLL_CON2, val); + + val = __SHIFTIN(pll_rate->dsmpd, PLL_DSMPD) | (PLL_DSMPD << 16); + CRU_WRITE(sc, pll->con_base + PLL_CON3, val); + + /* Set PLL work mode to normal */ + const uint32_t write_mask = pll->mode_mask << 16; + const uint32_t write_val = pll->mode_mask; + CRU_WRITE(sc, pll->mode_reg, write_mask | write_val); + + for (retry = 1000; retry > 0; retry--) { + if (CRU_READ(sc, pll->con_base + PLL_CON2) & pll->lock_mask) + break; + delay(1); + } + + if (retry == 0) + device_printf(sc->sc_dev, "WARNING: %s failed to lock\n", + clk->base.name); + + val = __SHIFTIN(PLL_WORK_MODE_NORMAL, PLL_WORK_MODE) | (PLL_WORK_MODE << 16); + CRU_WRITE(sc, pll->con_base + PLL_CON3, val); + + return 0; +} + +#define RK3399_PLL(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \ + { \ + .id = (_id), \ + .type = RK_CRU_PLL, \ + .base.name = (_name), \ + .base.flags = 0, \ + .u.pll.parents = (_parents), \ + .u.pll.nparents = __arraycount(_parents), \ + .u.pll.con_base = (_con_base), \ + .u.pll.mode_reg = (_mode_reg), \ + .u.pll.mode_mask = (_mode_mask), \ + .u.pll.lock_mask = (_lock_mask), \ + .u.pll.rates = (_rates), \ + .u.pll.nrates = __arraycount(_rates), \ + .get_rate = rk3399_pmucru_pll_get_rate, \ + .set_rate = rk3399_pmucru_pll_set_rate, \ + .get_parent = rk_cru_pll_get_parent, \ + } + +static const char * pll_parents[] = { "xin24m", "xin32k" }; + +static struct rk_cru_clk rk3399_pmucru_clks[] = { + RK3399_PLL(RK3399_PLL_PPLL, "ppll", pll_parents, + PLL_CON(0), /* con_base */ + PLL_CON(3), /* mode_reg */ + __BIT(8), /* mode_mask */ + __BIT(31), /* lock_mask */ + pll_rates), + + RK_DIV(RK3399_PCLK_SRC_PMU, "pclk_pmu_src", "ppll", CLKSEL_CON(0), __BITS(4,0), 0), + + RK_GATE(RK3399_PCLK_PMU, "pclk_pmu", "pclk_pmu_src", CLKGATE_CON(1), 0), + RK_GATE(RK3399_PCLK_GPIO0_PMU, "pclk_gpio0_pmu", "pclk_pmu_src", CLKGATE_CON(1), 3), + RK_GATE(RK3399_PCLK_GPIO1_PMU, "pclk_gpio1_pmu", "pclk_pmu_src", CLKGATE_CON(1), 4), +}; + +static int +rk3399_pmucru_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 +rk3399_pmucru_attach(device_t parent, device_t self, void *aux) +{ + struct rk_cru_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_bst = faa->faa_bst; + + sc->sc_clks = rk3399_pmucru_clks; + sc->sc_nclks = __arraycount(rk3399_pmucru_clks); + + sc->sc_softrst_base = SOFTRST_CON(0); + + if (rk_cru_attach(sc) != 0) + return; + + aprint_naive("\n"); + aprint_normal(": RK3399 PMU CRU\n"); + + rk_cru_print(sc); +} Index: src/sys/arch/arm/rockchip/rk3399_pmucru.h diff -u /dev/null src/sys/arch/arm/rockchip/rk3399_pmucru.h:1.1 --- /dev/null Sun Aug 12 16:48:05 2018 +++ src/sys/arch/arm/rockchip/rk3399_pmucru.h Sun Aug 12 16:48:05 2018 @@ -0,0 +1,72 @@ +/* $NetBSD: rk3399_pmucru.h,v 1.1 2018/08/12 16:48:05 jmcneill Exp $ */ + +/*- + * Copyright (c) 2018 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 _RK3399_PMUCRU_H +#define _RK3399_PMUCRU_H + +/* + * Clocks + */ + +#define RK3399_PLL_PPLL 1 +#define RK3399_SCLK_32K_SUSPEND_PMU 2 +#define RK3399_SCLK_SPI3_PMU 3 +#define RK3399_SCLK_TIMER12_PMU 4 +#define RK3399_SCLK_TIMER13_PMU 5 +#define RK3399_SCLK_UART4_PMU 6 +#define RK3399_SCLK_PVTM_PMU 7 +#define RK3399_SCLK_WIFI_PMU 8 +#define RK3399_SCLK_I2C0_PMU 9 +#define RK3399_SCLK_I2C4_PMU 10 +#define RK3399_SCLK_I2C8_PMU 11 +#define RK3399_PCLK_SRC_PMU 19 +#define RK3399_PCLK_PMU 20 +#define RK3399_PCLK_PMUGRF_PMU 21 +#define RK3399_PCLK_INTMEM1_PMU 22 +#define RK3399_PCLK_GPIO0_PMU 23 +#define RK3399_PCLK_GPIO1_PMU 24 +#define RK3399_PCLK_SGRF_PMU 25 +#define RK3399_PCLK_NOC_PMU 26 +#define RK3399_PCLK_I2C0_PMU 27 +#define RK3399_PCLK_I2C4_PMU 28 +#define RK3399_PCLK_I2C8_PMU 29 +#define RK3399_PCLK_RKPWM_PMU 30 +#define RK3399_PCLK_SPI3_PMU 31 +#define RK3399_PCLK_TIMER_PMU 32 +#define RK3399_PCLK_MAILBOX_PMU 33 +#define RK3399_PCLK_UART4_PMU 34 +#define RK3399_PCLK_WDT_M0_PMU 35 +#define RK3399_FCLK_CM0S_SRC_PMU 44 +#define RK3399_FCLK_CM0S_PMU 45 +#define RK3399_SCLK_CM0S_PMU 46 +#define RK3399_HCLK_CM0S_PMU 47 +#define RK3399_DCLK_CM0S_PMU 48 +#define RK3399_PCLK_INTR_ARB_PMU 49 +#define RK3399_HCLK_NOC_PMU 50 + +#endif /* !_RK3399_PMUCRU_H */