Module Name: src Committed By: jmcneill Date: Fri Nov 12 22:02:08 UTC 2021
Modified Files: src/sys/arch/arm/rockchip: files.rockchip rk3328_cru.c rk3399_cru.c rk_cru.h rk_cru_composite.c rk_cru_pll.c rk_gmac.c rk_i2c.c rk_platform.c src/sys/arch/evbarm/conf: GENERIC files.generic Added Files: src/sys/arch/arm/rockchip: rk3066_smp.c rk3288_cru.c rk3288_cru.h rk3288_iomux.c rk3288_platform.h rk3288_usb.c Log Message: arm: rockchip: Add support for RK3288 SoC. The Rockchip RK3288 is a quad core Cortex-A17 SoC. To generate a diff of this commit: cvs rdiff -u -r1.24 -r1.25 src/sys/arch/arm/rockchip/files.rockchip cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/rockchip/rk3066_smp.c \ src/sys/arch/arm/rockchip/rk3288_cru.c \ src/sys/arch/arm/rockchip/rk3288_cru.h \ src/sys/arch/arm/rockchip/rk3288_iomux.c \ src/sys/arch/arm/rockchip/rk3288_platform.h \ src/sys/arch/arm/rockchip/rk3288_usb.c cvs rdiff -u -r1.8 -r1.9 src/sys/arch/arm/rockchip/rk3328_cru.c cvs rdiff -u -r1.22 -r1.23 src/sys/arch/arm/rockchip/rk3399_cru.c cvs rdiff -u -r1.7 -r1.8 src/sys/arch/arm/rockchip/rk_cru.h cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/rockchip/rk_cru_composite.c cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/rockchip/rk_cru_pll.c cvs rdiff -u -r1.20 -r1.21 src/sys/arch/arm/rockchip/rk_gmac.c cvs rdiff -u -r1.10 -r1.11 src/sys/arch/arm/rockchip/rk_i2c.c cvs rdiff -u -r1.14 -r1.15 src/sys/arch/arm/rockchip/rk_platform.c cvs rdiff -u -r1.100 -r1.101 src/sys/arch/evbarm/conf/GENERIC cvs rdiff -u -r1.11 -r1.12 src/sys/arch/evbarm/conf/files.generic 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.24 src/sys/arch/arm/rockchip/files.rockchip:1.25 --- src/sys/arch/arm/rockchip/files.rockchip:1.24 Sun May 17 19:57:25 2020 +++ src/sys/arch/arm/rockchip/files.rockchip Fri Nov 12 22:02:08 2021 @@ -1,4 +1,4 @@ -# $NetBSD: files.rockchip,v 1.24 2020/05/17 19:57:25 riastradh Exp $ +# $NetBSD: files.rockchip,v 1.25 2021/11/12 22:02:08 jmcneill Exp $ # # Configuration info for Rockchip family SoCs # @@ -6,6 +6,8 @@ file arch/arm/rockchip/rk_platform.c soc_rockchip +file arch/arm/rockchip/rk3066_smp.c soc_rk3288 + # Clock and reset unit (CRU) device rkcru: rk_cru file arch/arm/rockchip/rk_cru.c rk_cru @@ -15,6 +17,14 @@ file arch/arm/rockchip/rk_cru_gate.c rk file arch/arm/rockchip/rk_cru_mux.c rk_cru file arch/arm/rockchip/rk_cru_pll.c rk_cru +ifdef arm + +# RK3288 clock and reset unit +attach rkcru at fdt with rk3288_cru +file arch/arm/rockchip/rk3288_cru.c rk3288_cru & soc_rk3288 + +else + # RK3328 clock and reset unit attach rkcru at fdt with rk3328_cru file arch/arm/rockchip/rk3328_cru.c rk3328_cru & soc_rk3328 @@ -25,13 +35,25 @@ file arch/arm/rockchip/rk3399_cru.c rk3 attach rkcru at fdt with rk3399_pmucru file arch/arm/rockchip/rk3399_pmucru.c rk3399_pmucru & soc_rk3399 +endif + # IOMUX control device rkiomux { } + +ifdef arm + +attach rkiomux at fdt with rk3288_iomux +file arch/arm/rockchip/rk3288_iomux.c rk3288_iomux & soc_rk3288 + +else + 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 +endif + # GPIO device rkgpio: gpiobus attach rkgpio at rkiomux with rk_gpio @@ -54,6 +76,12 @@ device rkusbphy attach rkusbphy at rkusb with rk_usbphy file arch/arm/rockchip/rk_usb.c rk_usb | rk_usbphy +device rk3288usb { } +attach rk3288usb at fdt with rk3288_usb +device rk3288usbphy +attach rk3288usbphy at rk3288usb with rk3288_usbphy +file arch/arm/rockchip/rk3288_usb.c rk3288_usb | rk3288_usbphy + # GMAC attach awge at fdt with rk_gmac file arch/arm/rockchip/rk_gmac.c rk_gmac @@ -119,5 +147,6 @@ file arch/arm/rockchip/rk_v1crypto.c rk # SOC parameters defflag opt_soc.h SOC_ROCKCHIP +defflag opt_soc.h SOC_RK3288: 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.8 src/sys/arch/arm/rockchip/rk3328_cru.c:1.9 --- src/sys/arch/arm/rockchip/rk3328_cru.c:1.8 Sat May 15 08:46:00 2021 +++ src/sys/arch/arm/rockchip/rk3328_cru.c Fri Nov 12 22:02:08 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: rk3328_cru.c,v 1.8 2021/05/15 08:46:00 mrg Exp $ */ +/* $NetBSD: rk3328_cru.c,v 1.9 2021/11/12 22:02:08 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.8 2021/05/15 08:46:00 mrg Exp $"); +__KERNEL_RCSID(1, "$NetBSD: rk3328_cru.c,v 1.9 2021/11/12 22:02:08 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -501,6 +501,7 @@ rk3328_cru_attach(device_t parent, devic sc->sc_clks = rk3328_cru_clks; sc->sc_nclks = __arraycount(rk3328_cru_clks); + sc->sc_grf_soc_status = 0x0480; sc->sc_softrst_base = SOFTRST_CON(0); if (rk_cru_attach(sc) != 0) Index: src/sys/arch/arm/rockchip/rk3399_cru.c diff -u src/sys/arch/arm/rockchip/rk3399_cru.c:1.22 src/sys/arch/arm/rockchip/rk3399_cru.c:1.23 --- src/sys/arch/arm/rockchip/rk3399_cru.c:1.22 Thu May 20 01:07:24 2021 +++ src/sys/arch/arm/rockchip/rk3399_cru.c Fri Nov 12 22:02:08 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: rk3399_cru.c,v 1.22 2021/05/20 01:07:24 msaitoh Exp $ */ +/* $NetBSD: rk3399_cru.c,v 1.23 2021/11/12 22:02:08 jmcneill Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -28,7 +28,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: rk3399_cru.c,v 1.22 2021/05/20 01:07:24 msaitoh Exp $"); +__KERNEL_RCSID(1, "$NetBSD: rk3399_cru.c,v 1.23 2021/11/12 22:02:08 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -1126,6 +1126,7 @@ rk3399_cru_attach(device_t parent, devic sc->sc_clks = rk3399_cru_clks; sc->sc_nclks = __arraycount(rk3399_cru_clks); + sc->sc_grf_soc_status = 0x0480; sc->sc_softrst_base = SOFTRST_CON(0); if (rk_cru_attach(sc) != 0) Index: src/sys/arch/arm/rockchip/rk_cru.h diff -u src/sys/arch/arm/rockchip/rk_cru.h:1.7 src/sys/arch/arm/rockchip/rk_cru.h:1.8 --- src/sys/arch/arm/rockchip/rk_cru.h:1.7 Sat Nov 16 13:23:13 2019 +++ src/sys/arch/arm/rockchip/rk_cru.h Fri Nov 12 22:02:08 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: rk_cru.h,v 1.7 2019/11/16 13:23:13 jmcneill Exp $ */ +/* $NetBSD: rk_cru.h,v 1.8 2021/11/12 22:02:08 jmcneill Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -80,6 +80,8 @@ struct rk_cru_pll { u_int nrates; const char **parents; u_int nparents; + u_int flags; +#define RK_PLL_RK3288 0x01 }; u_int rk_cru_pll_get_rate(struct rk_cru_softc *, struct rk_cru_clk *); @@ -100,6 +102,27 @@ const char *rk_cru_pll_get_parent(struct .u.pll.lock_mask = (_lock_mask), \ .u.pll.rates = (_rates), \ .u.pll.nrates = __arraycount(_rates), \ + .u.pll.flags = 0, \ + .get_rate = rk_cru_pll_get_rate, \ + .set_rate = rk_cru_pll_set_rate, \ + .get_parent = rk_cru_pll_get_parent, \ + } + +#define RK3288_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), \ + .u.pll.flags = RK_PLL_RK3288, \ .get_rate = rk_cru_pll_get_rate, \ .set_rate = rk_cru_pll_set_rate, \ .get_parent = rk_cru_pll_get_parent, \ @@ -207,6 +230,7 @@ struct rk_cru_composite { #define RK_COMPOSITE_ROUND_DOWN 0x01 #define RK_COMPOSITE_SET_RATE_PARENT 0x02 #define RK_COMPOSITE_FRACDIV 0x04 +#define RK_COMPOSITE_POW2 0x08 }; int rk_cru_composite_enable(struct rk_cru_softc *, struct rk_cru_clk *, int); @@ -367,6 +391,7 @@ struct rk_cru_softc { struct rk_cru_clk *sc_clks; u_int sc_nclks; + bus_size_t sc_grf_soc_status; /* for PLL lock */ bus_size_t sc_softrst_base; }; Index: src/sys/arch/arm/rockchip/rk_cru_composite.c diff -u src/sys/arch/arm/rockchip/rk_cru_composite.c:1.6 src/sys/arch/arm/rockchip/rk_cru_composite.c:1.7 --- src/sys/arch/arm/rockchip/rk_cru_composite.c:1.6 Thu May 20 01:41:55 2021 +++ src/sys/arch/arm/rockchip/rk_cru_composite.c Fri Nov 12 22:02:08 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: rk_cru_composite.c,v 1.6 2021/05/20 01:41:55 msaitoh Exp $ */ +/* $NetBSD: rk_cru_composite.c,v 1.7 2021/11/12 22:02:08 jmcneill Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rk_cru_composite.c,v 1.6 2021/05/20 01:41:55 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rk_cru_composite.c,v 1.7 2021/11/12 22:02:08 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -83,9 +83,14 @@ rk_cru_composite_get_rate(struct rk_cru_ return (u_int)((uint64_t)prate * num / den); } else { const uint32_t val = CRU_READ(sc, composite->muxdiv_reg); - const u_int div = (composite->div_mask != 0) - ? __SHIFTOUT(val, composite->div_mask) + 1 : 1; + u_int div; + if (composite->flags & RK_COMPOSITE_POW2) { + div = 1U << __SHIFTOUT(val, composite->div_mask); + } else { + div = (composite->div_mask != 0) + ? __SHIFTOUT(val, composite->div_mask) + 1 : 1; + } return prate / div; } } @@ -149,6 +154,10 @@ rk_cru_composite_set_rate(struct rk_cru_ return rk_cru_composite_set_rate_frac(sc, clk, rate); } + if (composite->flags & RK_COMPOSITE_POW2) { + return ENXIO; /* TODO */ + } + best_div = 0; best_mux = 0; best_diff = INT_MAX; Index: src/sys/arch/arm/rockchip/rk_cru_pll.c diff -u src/sys/arch/arm/rockchip/rk_cru_pll.c:1.4 src/sys/arch/arm/rockchip/rk_cru_pll.c:1.5 --- src/sys/arch/arm/rockchip/rk_cru_pll.c:1.4 Sun Aug 12 16:48:05 2018 +++ src/sys/arch/arm/rockchip/rk_cru_pll.c Fri Nov 12 22:02:08 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: rk_cru_pll.c,v 1.4 2018/08/12 16:48:05 jmcneill Exp $ */ +/* $NetBSD: rk_cru_pll.c,v 1.5 2021/11/12 22:02:08 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.4 2018/08/12 16:48:05 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rk_cru_pll.c,v 1.5 2021/11/12 22:02:08 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -57,9 +57,20 @@ __KERNEL_RCSID(0, "$NetBSD: rk_cru_pll.c #define PLL_DACPD __BIT(24) #define PLL_FRACDIV __BITS(23,0) +#define PLL_CON3 0x0c + #define PLL_WRITE_MASK 0xffff0000 /* for CON0 and CON1 */ -#define GRF_SOC_STATUS0 0x0480 +/* RK3288 CON0 */ +#define RK3288_CLKR __BITS(13,8) +#define RK3288_CLKOD __BITS(3,0) +/* RK3288 CON1 */ +#define RK3288_LOCK __BIT(31) +#define RK3288_CLKF __BITS(12,0) +/* RK3288 CON2 */ +#define RK3288_BWADJ __BITS(11,0) +/* RK3288 CON3 */ +#define RK3288_BYPASS __BIT(0) u_int rk_cru_pll_get_rate(struct rk_cru_softc *sc, @@ -83,24 +94,39 @@ rk_cru_pll_get_rate(struct rk_cru_softc 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); + + if ((pll->flags & RK_PLL_RK3288) != 0) { + if ((con3 & RK3288_BYPASS) != 0) { + return fref; + } + + const u_int nr = __SHIFTOUT(con0, RK3288_CLKR) + 1; + const u_int no = __SHIFTOUT(con0, RK3288_CLKOD) + 1; + const u_int nf = __SHIFTOUT(con1, RK3288_CLKF) + 1; + + const uint64_t tmp = (uint64_t)fref * nf / nr / no; - const u_int postdiv1 = __SHIFTOUT(con0, PLL_POSTDIV1); - const u_int fbdiv = __SHIFTOUT(con0, PLL_FBDIV); - const u_int dsmpd = __SHIFTOUT(con1, PLL_DSMPD); - const u_int refdiv = __SHIFTOUT(con1, PLL_REFDIV); - const u_int postdiv2 = __SHIFTOUT(con1, PLL_POSTDIV2); - const u_int fracdiv = __SHIFTOUT(con2, PLL_FRACDIV); - - if (dsmpd == 1) { - /* integer mode */ - foutvco = fref / refdiv * fbdiv; + return (u_int)tmp; } else { - /* fractional mode */ - foutvco = fref / refdiv * fbdiv + ((fref * fracdiv) >> 24); - } - foutpostdiv = foutvco / postdiv1 / postdiv2; + const u_int postdiv1 = __SHIFTOUT(con0, PLL_POSTDIV1); + const u_int fbdiv = __SHIFTOUT(con0, PLL_FBDIV); + const u_int dsmpd = __SHIFTOUT(con1, PLL_DSMPD); + const u_int refdiv = __SHIFTOUT(con1, PLL_REFDIV); + const u_int postdiv2 = __SHIFTOUT(con1, PLL_POSTDIV2); + const u_int fracdiv = __SHIFTOUT(con2, PLL_FRACDIV); + + 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; + return foutpostdiv; + } } int @@ -125,6 +151,8 @@ rk_cru_pll_set_rate(struct rk_cru_softc if (pll_rate == NULL) return EINVAL; + KASSERT((pll->flags & RK_PLL_RK3288) == 0); /* XXX TODO */ + CRU_WRITE(sc, pll->con_base + PLL_CON0, __SHIFTIN(pll_rate->postdiv1, PLL_POSTDIV1) | __SHIFTIN(pll_rate->fbdiv, PLL_FBDIV) | @@ -148,7 +176,7 @@ rk_cru_pll_set_rate(struct rk_cru_softc syscon_lock(sc->sc_grf); for (retry = 1000; retry > 0; retry--) { - if (syscon_read_4(sc->sc_grf, GRF_SOC_STATUS0) & pll->lock_mask) + if (syscon_read_4(sc->sc_grf, sc->sc_grf_soc_status) & pll->lock_mask) break; delay(1); } Index: src/sys/arch/arm/rockchip/rk_gmac.c diff -u src/sys/arch/arm/rockchip/rk_gmac.c:1.20 src/sys/arch/arm/rockchip/rk_gmac.c:1.21 --- src/sys/arch/arm/rockchip/rk_gmac.c:1.20 Sun Nov 7 19:21:33 2021 +++ src/sys/arch/arm/rockchip/rk_gmac.c Fri Nov 12 22:02:08 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: rk_gmac.c,v 1.20 2021/11/07 19:21:33 jmcneill Exp $ */ +/* $NetBSD: rk_gmac.c,v 1.21 2021/11/12 22:02:08 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.20 2021/11/07 19:21:33 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rk_gmac.c,v 1.21 2021/11/12 22:02:08 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -54,11 +54,13 @@ __KERNEL_RCSID(0, "$NetBSD: rk_gmac.c,v #define RK_GMAC_RXDLY_DEFAULT 0x10 enum rk_gmac_type { - GMAC_RK3328 = 1, + GMAC_RK3288 = 1, + GMAC_RK3328, GMAC_RK3399 }; static const struct device_compatible_entry compat_data[] = { + { .compat = "rockchip,rk3288-gmac", .value = GMAC_RK3288 }, { .compat = "rockchip,rk3328-gmac", .value = GMAC_RK3328 }, { .compat = "rockchip,rk3399-gmac", .value = GMAC_RK3399 }, DEVICE_COMPAT_EOL @@ -71,6 +73,98 @@ struct rk_gmac_softc { }; /* + * RK3288 specific + */ + +#define RK3288_GRF_SOC_CON1 0x0248 +#define RK3288_GRF_SOC_CON1_RMII_MODE __BIT(14) +#define RK3288_GRF_SOC_CON1_GMAC_CLK_SEL __BITS(13,12) +#define RK3288_GRF_SOC_CON1_GMAC_CLK_SEL_125M 0 +#define RK3288_GRF_SOC_CON1_GMAC_CLK_SEL_2_5M 2 +#define RK3288_GRF_SOC_CON1_GMAC_CLK_SEL_25M 3 +#define RK3288_GRF_SOC_CON1_RMII_CLK_SEL __BIT(11) +#define RK3288_GRF_SOC_CON1_RMII_CLK_SEL_25M 1 +#define RK3288_GRF_SOC_CON1_RMII_CLK_SEL_2_5M 0 +#define RK3288_GRF_SOC_CON1_GMAC_SPEED __BIT(10) +#define RK3288_GRF_SOC_CON1_GMAC_SPEED_10M 0 +#define RK3288_GRF_SOC_CON1_GMAC_SPEED_100M 1 +#define RK3288_GRF_SOC_CON1_GMAC_FLOWCTRL __BIT(9) +#define RK3288_GRF_SOC_CON1_GMAC_PHY_INTF_SEL __BITS(8,6) +#define RK3288_GRF_SOC_CON1_GMAC_PHY_INTF_SEL_RGMII 1 +#define RK3288_GRF_SOC_CON1_GMAC_PHY_INTF_SEL_RMII 4 + +#define RK3288_GRF_SOC_CON3 0x0250 +#define RK3288_GRF_SOC_CON3_RXCLK_DLY_ENA_GMAC __BIT(15) +#define RK3288_GRF_SOC_CON3_TXCLK_DLY_ENA_GMAC __BIT(14) +#define RK3288_GRF_SOC_CON3_CLK_RX_DL_CFG_GMAC __BITS(13,7) +#define RK3288_GRF_SOC_CON3_CLK_TX_DL_CFG_GMAC __BITS(6,0) + +static void +rk3288_gmac_set_mode_rgmii(struct dwc_gmac_softc *sc, u_int tx_delay, u_int rx_delay, bool set_delay) +{ + struct rk_gmac_softc * const rk_sc = (struct rk_gmac_softc *)sc; + uint32_t write_mask, write_val; + + syscon_lock(rk_sc->sc_syscon); + + write_mask = (RK3288_GRF_SOC_CON1_RMII_MODE | + RK3288_GRF_SOC_CON1_GMAC_PHY_INTF_SEL) << 16; + write_val = __SHIFTIN(RK3288_GRF_SOC_CON1_GMAC_PHY_INTF_SEL_RGMII, + RK3288_GRF_SOC_CON1_GMAC_PHY_INTF_SEL); + syscon_write_4(rk_sc->sc_syscon, RK3288_GRF_SOC_CON1, + write_mask | write_val); + + if (set_delay) { + write_mask = (RK3288_GRF_SOC_CON3_RXCLK_DLY_ENA_GMAC | + RK3288_GRF_SOC_CON3_TXCLK_DLY_ENA_GMAC | + RK3288_GRF_SOC_CON3_CLK_RX_DL_CFG_GMAC | + RK3288_GRF_SOC_CON3_CLK_TX_DL_CFG_GMAC) << 16; + write_val = 0; + if (tx_delay) { + write_mask |= RK3288_GRF_SOC_CON3_TXCLK_DLY_ENA_GMAC | + __SHIFTIN(tx_delay, + RK3288_GRF_SOC_CON3_CLK_TX_DL_CFG_GMAC); + } + if (rx_delay) { + write_mask |= RK3288_GRF_SOC_CON3_RXCLK_DLY_ENA_GMAC | + __SHIFTIN(rx_delay, + RK3288_GRF_SOC_CON3_CLK_RX_DL_CFG_GMAC); + } + syscon_write_4(rk_sc->sc_syscon, RK3288_GRF_SOC_CON3, + write_mask | write_val); + } + + syscon_unlock(rk_sc->sc_syscon); +} + +static void +rk3288_gmac_set_speed_rgmii(struct dwc_gmac_softc *sc, int speed) +{ + struct rk_gmac_softc * const rk_sc = (struct rk_gmac_softc *)sc; + uint32_t write_mask, write_val; + + syscon_lock(rk_sc->sc_syscon); + + write_mask = (RK3288_GRF_SOC_CON1_GMAC_CLK_SEL) << 16; + switch (speed) { + case IFM_10_T: + write_val = RK3288_GRF_SOC_CON1_GMAC_CLK_SEL_2_5M; + break; + case IFM_100_TX: + write_val = RK3288_GRF_SOC_CON1_GMAC_CLK_SEL_25M; + break; + case IFM_1000_T: + default: + write_val = RK3288_GRF_SOC_CON1_GMAC_CLK_SEL_125M; + break; + } + syscon_write_4(rk_sc->sc_syscon, RK3288_GRF_SOC_CON1, + write_mask | write_val); + + syscon_unlock(rk_sc->sc_syscon); +} + +/* * RK3328 specific */ @@ -415,6 +509,17 @@ rk_gmac_attach(device_t parent, device_t } switch (rk_sc->sc_type) { + case GMAC_RK3288: + if (strncmp(phy_mode, "rgmii", 5) == 0) { + rk3288_gmac_set_mode_rgmii(sc, tx_delay, rx_delay, + set_delay); + + sc->sc_set_speed = rk3288_gmac_set_speed_rgmii; + } else { + aprint_error(": unsupported phy-mode '%s'\n", phy_mode); + return; + } + break; case GMAC_RK3328: if (strncmp(phy_mode, "rgmii", 5) == 0) { rk3328_gmac_set_mode_rgmii(sc, tx_delay, rx_delay, Index: src/sys/arch/arm/rockchip/rk_i2c.c diff -u src/sys/arch/arm/rockchip/rk_i2c.c:1.10 src/sys/arch/arm/rockchip/rk_i2c.c:1.11 --- src/sys/arch/arm/rockchip/rk_i2c.c:1.10 Wed Jan 27 03:10:19 2021 +++ src/sys/arch/arm/rockchip/rk_i2c.c Fri Nov 12 22:02:08 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: rk_i2c.c,v 1.10 2021/01/27 03:10:19 thorpej Exp $ */ +/* $NetBSD: rk_i2c.c,v 1.11 2021/11/12 22:02:08 jmcneill Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -28,7 +28,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rk_i2c.c,v 1.10 2021/01/27 03:10:19 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rk_i2c.c,v 1.11 2021/11/12 22:02:08 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -100,8 +100,14 @@ __KERNEL_RCSID(0, "$NetBSD: rk_i2c.c,v 1 #define RKI2C_TXDATA(n) (0x100 + (n) * 4) #define RKI2C_RXDATA(n) (0x200 + (n) * 4) +/* Compat data flags */ +#define RKI2C_HAS_PCLK __BIT(0) + static const struct device_compatible_entry compat_data[] = { - { .compat = "rockchip,rk3399-i2c" }, +#if notyet + { .compat = "rockchip,rk3288-i2c", .value = 0 }, +#endif + { .compat = "rockchip,rk3399-i2c", .value = RKI2C_HAS_PCLK }, DEVICE_COMPAT_EOL }; @@ -377,22 +383,27 @@ rk_i2c_attach(device_t parent, device_t const int phandle = faa->faa_phandle; bus_addr_t addr; bus_size_t size; + u_int flags; if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { aprint_error(": couldn't get registers\n"); return; } + flags = of_compatible_lookup(phandle, compat_data)->value; + sc->sc_sclk = fdtbus_clock_get(phandle, "i2c"); if (sc->sc_sclk == NULL || clk_enable(sc->sc_sclk) != 0) { aprint_error(": couldn't enable sclk\n"); return; } - sc->sc_pclk = fdtbus_clock_get(phandle, "pclk"); - if (sc->sc_pclk == NULL || clk_enable(sc->sc_pclk) != 0) { - aprint_error(": couldn't enable pclk\n"); - return; + if (ISSET(flags, RKI2C_HAS_PCLK)) { + sc->sc_pclk = fdtbus_clock_get(phandle, "pclk"); + if (sc->sc_pclk == NULL || clk_enable(sc->sc_pclk) != 0) { + aprint_error(": couldn't enable pclk\n"); + return; + } } if (of_getprop_uint32(phandle, "clock-frequency", &sc->sc_clkfreq)) Index: src/sys/arch/arm/rockchip/rk_platform.c diff -u src/sys/arch/arm/rockchip/rk_platform.c:1.14 src/sys/arch/arm/rockchip/rk_platform.c:1.15 --- src/sys/arch/arm/rockchip/rk_platform.c:1.14 Fri Sep 3 01:23:33 2021 +++ src/sys/arch/arm/rockchip/rk_platform.c Fri Nov 12 22:02:08 2021 @@ -1,7 +1,7 @@ -/* $NetBSD: rk_platform.c,v 1.14 2021/09/03 01:23:33 mrg Exp $ */ +/* $NetBSD: rk_platform.c,v 1.15 2021/11/12 22:02:08 jmcneill Exp $ */ /*- - * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> + * Copyright (c) 2018,2021 Jared McNeill <jmcne...@invisible.ca> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,7 +31,7 @@ #include "opt_console.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rk_platform.c,v 1.14 2021/09/03 01:23:33 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rk_platform.c,v 1.15 2021/11/12 22:02:08 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -101,6 +101,95 @@ rk_platform_bootstrap(void) } } +#ifdef SOC_RK3288 + +#define RK3288_WDT_BASE 0xff800000 +#define RK3288_WDT_SIZE 0x10000 + +#define RK3288_WDT_CR 0x0000 +#define RK3288_WDT_CR_WDT_EN __BIT(0) +#define RK3288_WDT_TORR 0x0004 +#define RK3288_WDT_CRR 0x000c +#define RK3288_WDT_MAGIC 0x76 + +static bus_space_handle_t rk3288_wdt_bsh; + +#include <arm/rockchip/rk3288_platform.h> + +static const struct pmap_devmap * +rk3288_platform_devmap(void) +{ + static const struct pmap_devmap devmap[] = { + DEVMAP_ENTRY(RK3288_CORE_VBASE, + RK3288_CORE_PBASE, + RK3288_CORE_SIZE), + DEVMAP_ENTRY_END + }; + + return devmap; +} + +void rk3288_platform_early_putchar(char); + +void __noasan +rk3288_platform_early_putchar(char c) +{ +#ifdef CONSADDR +#define CONSADDR_VA ((CONSADDR - RK3288_CORE_PBASE) + RK3288_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 void +rk3288_platform_bootstrap(void) +{ + bus_space_tag_t bst = &arm_generic_bs_tag; + + rk_platform_bootstrap(); + bus_space_map(bst, RK3288_WDT_BASE, RK3288_WDT_SIZE, 0, &rk3288_wdt_bsh); +} + +static void +rk3288_platform_reset(void) +{ + bus_space_tag_t bst = &arm_generic_bs_tag; + + bus_space_write_4(bst, rk3288_wdt_bsh, RK3288_WDT_TORR, 0); + bus_space_write_4(bst, rk3288_wdt_bsh, RK3288_WDT_CRR, RK3288_WDT_MAGIC); + for (;;) { + bus_space_write_4(bst, rk3288_wdt_bsh, RK3288_WDT_CR, RK3288_WDT_CR_WDT_EN); + } +} + +static u_int +rk3288_platform_uart_freq(void) +{ + return RK3288_UART_FREQ; +} + +static const struct arm_platform rk3288_platform = { + .ap_devmap = rk3288_platform_devmap, + .ap_bootstrap = rk3288_platform_bootstrap, + .ap_init_attach_args = rk_platform_init_attach_args, + .ap_device_register = rk_platform_device_register, + .ap_reset = rk3288_platform_reset, + .ap_delay = gtmr_delay, + .ap_uart_freq = rk3288_platform_uart_freq, + .ap_mpstart = arm_fdt_cpu_mpstart, +}; + +ARM_PLATFORM(rk3288, "rockchip,rk3288", &rk3288_platform); +#endif /* SOC_RK3288 */ + + #ifdef SOC_RK3328 #include <arm/rockchip/rk3328_platform.h> Index: src/sys/arch/evbarm/conf/GENERIC diff -u src/sys/arch/evbarm/conf/GENERIC:1.100 src/sys/arch/evbarm/conf/GENERIC:1.101 --- src/sys/arch/evbarm/conf/GENERIC:1.100 Thu Aug 26 17:08:34 2021 +++ src/sys/arch/evbarm/conf/GENERIC Fri Nov 12 22:02:08 2021 @@ -1,5 +1,5 @@ # -# $NetBSD: GENERIC,v 1.100 2021/08/26 17:08:34 thorpej Exp $ +# $NetBSD: GENERIC,v 1.101 2021/11/12 22:02:08 jmcneill Exp $ # # GENERIC ARM (aarch32) kernel # @@ -19,6 +19,7 @@ options SOC_IMX6QDL options SOC_IMX7D options SOC_MESON8B options SOC_OMAP3 +options SOC_RK3288 options SOC_SUN4I_A10 options SOC_SUN5I_A13 options SOC_SUN6I_A31 @@ -79,6 +80,7 @@ options MSGBUFSIZE=32768 #options EARLYCONS=vexpress, CONSADDR=0x1c090000 #options EARLYCONS=virt, CONSADDR=0x09000000 #options EARLYCONS=zynq, CONSADDR=0xe0001000 +#options EARLYCONS=rk3288, CONSADDR=0xff690000 # Kernel Undefined Behavior Sanitizer (kUBSan). Use UBSAN_ALWAYS_FATAL # if you want panics instead of warnings. @@ -134,6 +136,7 @@ meson8bclkc* at fdt? pass 2 # Amlogic mesonresets* at fdt? pass 2 # Amlogic Meson misc. clock resets omap3cm* at fdt? pass 1 # TI OMAP3 CM omap3prm* at fdt? pass 1 # TI OMAP3 PRM +rkcru* at fdt? pass 2 # Rockchip RK3288 CRU sun4ia10ccu* at fdt? pass 2 # Allwinner A10/A20 CCU sun5ia13ccu* at fdt? pass 2 # Allwinner A13 CCU sun6ia31ccu* at fdt? pass 2 # Allwinner A31 CCU @@ -258,6 +261,7 @@ imxgpio* at fdt? pass 3 # i.MX GPIO mesonpinctrl* at fdt? pass 2 # Amlogic Meson GPIO plgpio* at fdt? # ARM PrimeCell GPIO sunxigpio* at fdt? pass 3 # Allwinner GPIO +rkgpio* at rkiomux? # Rockchip GPIO tegragpio* at fdt? pass 2 # NVIDIA Tegra GPIO tigpio* at fdt? pass 2 # TI GPIO gpio* at gpiobus? @@ -265,6 +269,7 @@ gpio* at gpiobus? # IOMUX / MPIO / Pinmux pinctrl* at fdt? pass 2 # Generic pinctrl driver imxiomux* at fdt? pass 2 # i.MX IOMUX +rkiomux* at fdt? pass 3 # Rockchip IOMUX tegrapinmux* at fdt? # NVIDIA Tegra MPIO # PWM controller @@ -349,6 +354,7 @@ options I2C_MAX_ADDR=0xfff bsciic* at fdt? # Broadcom BCM283x Serial Control exyoi2c* at fdt? # Samsung Exynos I2C imxi2c* at fdt? pass 4 # i.MX I2C +rkiic* at fdt? pass 4 # Rockchip I2C sunxirsb* at fdt? pass 4 # Allwinner RSB sunxitwi* at fdt? # Allwinner TWI tegrai2c* at fdt? pass 4 # NVIDIA Tegra I2C @@ -370,6 +376,7 @@ em3027rtc* at iic? max77620pmic* at iic? pcaiicmux* at iic? # PCA954x / PCA984x I2C switch / mux pcf8563rtc* at iic? # PCF8563 RTC +rkpmic* at iic? # Rockchip Power Management IC seeprom* at iic? # AT24Cxx Serial EEPROM sy8106a* at iic? # Silergy SY81061 regulator tcakp* at iic? # TI TCA8418 Keypad Scan IC @@ -549,6 +556,8 @@ exusbphy* at fdt? pass 9 # Samsung Exy exusbdrdphy* at fdt? pass 9 # Samsung Exynos USB3 DRD PHY imxusbphy* at fdt? pass 9 # i.MX USB PHY mesonusbphy* at fdt? pass 9 # Amlogic Meson USB2 PHY +rk3288usb* at fdt? pass 9 # Rockchip USB PHY +rk3288usbphy* at rk3288usb? sun9iusbphy* at fdt? pass 9 # Allwinner A80 USB PHY sunxiusbphy* at fdt? pass 9 # Allwinner USB PHY sunxiusb3phy* at fdt? pass 9 # Allwinner USB3 PHY Index: src/sys/arch/evbarm/conf/files.generic diff -u src/sys/arch/evbarm/conf/files.generic:1.11 src/sys/arch/evbarm/conf/files.generic:1.12 --- src/sys/arch/evbarm/conf/files.generic:1.11 Wed Dec 23 14:42:38 2020 +++ src/sys/arch/evbarm/conf/files.generic Fri Nov 12 22:02:08 2021 @@ -1,4 +1,4 @@ -# $NetBSD: files.generic,v 1.11 2020/12/23 14:42:38 skrll Exp $ +# $NetBSD: files.generic,v 1.12 2021/11/12 22:02:08 jmcneill Exp $ # # A generic (aarch32) kernel configuration info # @@ -22,6 +22,7 @@ include "arch/arm/amlogic/files.meson" include "arch/arm/broadcom/files.bcm2835" include "arch/arm/nvidia/files.tegra" include "arch/arm/nxp/files.imx" +include "arch/arm/rockchip/files.rockchip" include "arch/arm/samsung/files.exynos" include "arch/arm/sunxi/files.sunxi" include "arch/arm/ti/files.ti" Added files: Index: src/sys/arch/arm/rockchip/rk3066_smp.c diff -u /dev/null src/sys/arch/arm/rockchip/rk3066_smp.c:1.1 --- /dev/null Fri Nov 12 22:02:08 2021 +++ src/sys/arch/arm/rockchip/rk3066_smp.c Fri Nov 12 22:02:08 2021 @@ -0,0 +1,166 @@ +/* $NetBSD: rk3066_smp.c,v 1.1 2021/11/12 22:02:08 jmcneill Exp $ */ + +/*- + * Copyright (c) 2021 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 "opt_soc.h" +#include "opt_multiprocessor.h" + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: rk3066_smp.c,v 1.1 2021/11/12 22:02:08 jmcneill Exp $"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/cpu.h> +#include <sys/device.h> + +#include <dev/fdt/fdtvar.h> +#include <arm/fdt/arm_fdtvar.h> + +#include <uvm/uvm_extern.h> + +#define PMU_PWRDN_CON 0x0008 +#define PMU_PWRDN_ST 0x000c + +#define SRAM_ENTRY_PA 0x0008 +#define SRAM_DOORBELL 0x0004 +#define SRAM_DOORBELL_MAGIC 0xdeadbeaf + +extern struct bus_space arm_generic_bs_tag; + +static uint32_t +rk3066_mpstart_pa(void) +{ + bool ok __diagused; + paddr_t pa; + + ok = pmap_extract(pmap_kernel(), (vaddr_t)cpu_mpstart, &pa); + KASSERT(ok); + + return (uint32_t)pa; +} + +static int +rk3066_map(int phandle, bus_space_tag_t bst, bus_space_handle_t *pbsh, + bus_size_t *psize) +{ + bus_addr_t addr; + int error; + + error = fdtbus_get_reg(phandle, 0, &addr, psize); + if (error != 0) { + return error; + } + + return bus_space_map(bst, addr, *psize, 0, pbsh); +} + +static int +rk3066_smp_enable(int cpus_phandle, u_int cpuno) +{ + bus_space_tag_t bst = &arm_generic_bs_tag; + bus_space_handle_t bsh_sram, bsh_pmu; + bus_size_t sz_sram, sz_pmu; + uint32_t val; + int error; + + const int sram_phandle = + of_find_bycompat(OF_peer(0), "rockchip,rk3066-smp-sram"); + if (sram_phandle == -1) { + printf("%s: missing rockchip,rk3066-smp-sram node\n", + __func__); + return ENXIO; + } + + const int pmu_phandle = fdtbus_get_phandle(cpus_phandle, + "rockchip,pmu"); + if (pmu_phandle == -1) { + printf("%s: missing rockchip,pmu xref\n", __func__); + return ENXIO; + } + + error = rk3066_map(sram_phandle, bst, &bsh_sram, &sz_sram); + if (error != 0) { + return error; + } + + error = rk3066_map(pmu_phandle, bst, &bsh_pmu, &sz_pmu); + if (error != 0) { + bus_space_unmap(bst, bsh_pmu, sz_pmu); + return error; + } + + /* Enable the A17 core's power domain */ + val = bus_space_read_4(bst, bsh_pmu, PMU_PWRDN_CON); + val &= ~__BIT(cpuno); + bus_space_write_4(bst, bsh_pmu, PMU_PWRDN_CON, val); + + /* Wait for the A17 core to power on */ + do { + val = bus_space_read_4(bst, bsh_pmu, PMU_PWRDN_ST); + } while ((val & __BIT(cpuno)) != 0); + + delay(2000); + + /* Set wake vector */ + bus_space_write_4(bst, bsh_sram, SRAM_ENTRY_PA, rk3066_mpstart_pa()); + /* Notify boot rom that we are ready to start */ + bus_space_write_4(bst, bsh_sram, SRAM_DOORBELL, SRAM_DOORBELL_MAGIC); + dsb(); + sev(); + + bus_space_unmap(bst, bsh_pmu, sz_pmu); + bus_space_unmap(bst, bsh_sram, sz_sram); + + return 0; +} + +static int +cpu_enable_rk3066(int phandle) +{ + static uint32_t enabled; + uint64_t mpidr; + int error = 0; + + fdtbus_get_reg64(phandle, 0, &mpidr, NULL); + + const u_int cpuno = __SHIFTOUT(mpidr, MPIDR_AFF0); + const bool is_enabled = enabled & __BIT(cpuno); + + if (!is_enabled) { + error = rk3066_smp_enable(OF_parent(phandle), cpuno); + if (error == 0) { + enabled |= __BIT(cpuno); + } + } else { + printf("WARNING: CPU enable called more than once for CPU %u\n", + cpuno); + } + + return error; +} + +ARM_CPU_METHOD(rk3066, "rockchip,rk3066-smp", cpu_enable_rk3066); Index: src/sys/arch/arm/rockchip/rk3288_cru.c diff -u /dev/null src/sys/arch/arm/rockchip/rk3288_cru.c:1.1 --- /dev/null Fri Nov 12 22:02:08 2021 +++ src/sys/arch/arm/rockchip/rk3288_cru.c Fri Nov 12 22:02:08 2021 @@ -0,0 +1,309 @@ +/* $NetBSD: rk3288_cru.c,v 1.1 2021/11/12 22:02:08 jmcneill Exp $ */ + +/*- + * Copyright (c) 2021 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: rk3288_cru.c,v 1.1 2021/11/12 22:02:08 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/rk3288_cru.h> + +#define PLL_CON(n) (0x0000 + (n) * 4) +#define MODE_CON 0x0050 +#define CLKSEL_CON(n) (0x0060 + (n) * 4) +#define CLKGATE_CON(n) (0x0160 + (n) * 4) +#define SOFTRST_CON(n) (0x01b8 + (n) * 4) + +#define GRF_SOC_CON4 0x0410 +#define GRF_MAC_CON1 0x0904 + +static int rk3288_cru_match(device_t, cfdata_t, void *); +static void rk3288_cru_attach(device_t, device_t, void *); + +static const struct device_compatible_entry compat_data[] = { + { .compat = "rockchip,rk3288-cru" }, + DEVICE_COMPAT_EOL +}; + +CFATTACH_DECL_NEW(rk3288_cru, sizeof(struct rk_cru_softc), + rk3288_cru_match, rk3288_cru_attach, NULL, NULL); + +static const char * pll_parents[] = { "xin24m" }; +static const char * aclk_cpu_src_parents[] = { "cpll_aclk_cpu", "gpll_aclk_cpu" }; +static const char * uart0_parents[] = { "clk_uart0_div", "clk_uart0_frac", "xin24m" }; +static const char * uart1_parents[] = { "clk_uart1_div", "clk_uart1_frac", "xin24m" }; +static const char * uart2_parents[] = { "clk_uart2_div", "clk_uart2_frac", "xin24m" }; +static const char * uart3_parents[] = { "clk_uart3_div", "clk_uart3_frac", "xin24m" }; +static const char * uart4_parents[] = { "clk_uart4_div", "clk_uart4_frac", "xin24m" }; +static const char * mmc_parents[] = { "cpll", "gpll", "xin24m", "xin24m" }; +static const char * mac_parents[] = { "mac_pll_src", "ext_gmac" }; +static const char * mux_2plls_parents[] = { "cpll", "gpll" }; +static const char * mux_npll_cpll_gpll_parents[] = { "npll", "cpll", "gpll" }; +static const char * mux_3plls_usb_parents[] = { "cpll", "gpll", "usbphy480m_src", "npll" }; + +static struct rk_cru_pll_rate rk3288_pll_rates[] = { + /* TODO */ +}; + +static struct rk_cru_clk rk3288_cru_clks[] = { + RK3288_PLL(RK3288_PLL_CPLL, "cpll", pll_parents, + PLL_CON(8), /* con_base */ + MODE_CON, /* mode_reg */ + __BIT(8), /* mode_mask */ + __BIT(2), /* lock_mask */ + rk3288_pll_rates), + RK3288_PLL(RK3288_PLL_GPLL, "gpll", pll_parents, + PLL_CON(12), /* con_base */ + MODE_CON, /* mode_reg */ + __BIT(12), /* mode_mask */ + __BIT(3), /* lock_mask */ + rk3288_pll_rates), + RK3288_PLL(RK3288_PLL_NPLL, "npll", pll_parents, + PLL_CON(16), /* con_base */ + MODE_CON, /* mode_reg */ + __BIT(14), /* mode_mask */ + __BIT(4), /* lock_mask */ + rk3288_pll_rates), + + RK_COMPOSITE_NOGATE(0, "aclk_cpu_src", aclk_cpu_src_parents, + CLKSEL_CON(1), /* muxdiv_reg */ + __BIT(15), /* mux_mask */ + __BITS(7,3), /* div_mask */ + 0), + RK_COMPOSITE_NOMUX(RK3288_PCLK_CPU, "pclk_cpu", "aclk_cpu_pre", + CLKSEL_CON(1), /* div_reg */ + __BITS(14,12), /* div_mask */ + CLKGATE_CON(0), /* gate_reg */ + __BIT(5), /* gate_mask */ + 0), + RK_COMPOSITE_NOMUX(RK3288_HCLK_PERI, "hclk_peri", "aclk_peri_src", + CLKSEL_CON(10), /* div_reg */ + __BITS(9,8), /* div_mask */ + CLKGATE_CON(2), /* gate_reg */ + __BIT(2), /* gate_mask */ + RK_COMPOSITE_POW2), + RK_COMPOSITE(0, "aclk_peri_src", mux_2plls_parents, + CLKSEL_CON(10), /* muxdiv_reg */ + __BIT(15), /* mux_mask */ + __BITS(4,0), /* div_mask */ + CLKGATE_CON(2), /* gate_reg */ + __BIT(0), /* gate_mask */ + 0), + RK_COMPOSITE_NOMUX(0, "pclk_pd_pmu", "gpll", + CLKSEL_CON(33), /* div_reg */ + __BITS(4,0), /* div_mask */ + CLKGATE_CON(5), /* gate_reg */ + __BIT(8), /* gate_mask */ + 0), + RK_COMPOSITE_NOMUX(RK3288_PCLK_PERI, "pclk_peri", "aclk_peri_src", + CLKSEL_CON(10), /* div_reg */ + __BITS(13,12), /* div_mask */ + CLKGATE_CON(2), /* gate_reg */ + __BIT(3), /* gate_mask */ + 0), + + /* UARTs */ + RK_COMPOSITE(0, "clk_uart0_div", mux_3plls_usb_parents, + CLKSEL_CON(13), /* muxdiv_reg */ + __BITS(14,13), /* mux_mask */ + __BITS(6,0), /* div_mask */ + CLKGATE_CON(1), /* gate_reg */ + __BIT(8), /* gate_mask */ + 0), + /* XXX TODO: CRU_CLKGATE1_CON bit 9 (clk_uart0_frac_src_gate_en) */ + RK_COMPOSITE_FRAC(0, "clk_uart0_frac", "clk_uart0_div", + CLKSEL_CON(17), /* fracdiv_reg */ + 0), + RK_COMPOSITE_NOMUX(0, "clk_uart1_div", "uart_src", + CLKSEL_CON(14), /* div_reg */ + __BITS(6,0), /* div_mask */ + CLKGATE_CON(1), /* gate_reg */ + __BIT(10), /* gate_mask */ + 0), + /* XXX TODO: CRU_CLKGATE1_CON bit 11 (clk_uart1_frac_src_gate_en) */ + RK_COMPOSITE_FRAC(0, "clk_uart1_frac", "clk_uart1_div", + CLKSEL_CON(18), /* fracdiv_reg */ + 0), + RK_COMPOSITE_NOMUX(0, "clk_uart2_div", "uart_src", + CLKSEL_CON(15), /* div_reg */ + __BITS(6,0), /* div_mask */ + CLKGATE_CON(1), /* gate_reg */ + __BIT(12), /* gate_mask */ + 0), + /* XXX TODO: CRU_CLKGATE1_CON bit 13 (clk_uart2_frac_src_gate_en) */ + RK_COMPOSITE_FRAC(0, "clk_uart2_frac", "clk_uart2_div", + CLKSEL_CON(19), /* fracdiv_reg */ + 0), + RK_COMPOSITE_NOMUX(0, "clk_uart3_div", "uart_src", + CLKSEL_CON(16), /* div_reg */ + __BITS(6,0), /* div_mask */ + CLKGATE_CON(1), /* gate_reg */ + __BIT(14), /* gate_mask */ + 0), + /* XXX TODO: CRU_CLKGATE1_CON bit 15 (clk_uart3_frac_src_gate_en) */ + RK_COMPOSITE_FRAC(0, "clk_uart3_frac", "clk_uart3_div", + CLKSEL_CON(20), /* fracdiv_reg */ + 0), + RK_COMPOSITE_NOMUX(0, "clk_uart4_div", "uart_src", + CLKSEL_CON(3), /* div_reg */ + __BITS(6,0), /* div_mask */ + CLKGATE_CON(2), /* gate_reg */ + __BIT(12), /* gate_mask */ + 0), + /* XXX TODO: CRU_CLKGATE2_CON bit 13 (clk_uart4_frac_src_gate_en) */ + RK_COMPOSITE_FRAC(0, "clk_uart4_frac", "clk_uart4_div", + CLKSEL_CON(7), /* fracdiv_reg */ + 0), + + /* SD/eMMC/SDIO */ + RK_COMPOSITE(RK3288_SCLK_SDMMC, "sclk_sdmmc", mmc_parents, + CLKSEL_CON(11), /* muxdiv_reg */ + __BITS(7,6), /* mux_mask */ + __BITS(5,0), /* div_mask */ + CLKGATE_CON(13), /* gate_reg */ + __BIT(0), /* gate_mask */ + 0), + RK_COMPOSITE(RK3288_SCLK_SDIO0, "sclk_sdio0", mmc_parents, + CLKSEL_CON(12), /* muxdiv_reg */ + __BITS(7,6), /* mux_mask */ + __BITS(5,0), /* div_mask */ + CLKGATE_CON(13), /* gate_reg */ + __BIT(1), /* gate_mask */ + 0), + RK_COMPOSITE(RK3288_SCLK_SDIO1, "sclk_sdio1", mmc_parents, + CLKSEL_CON(34), /* muxdiv_reg */ + __BITS(15,14), /* mux_mask */ + __BITS(13,8), /* div_mask */ + CLKGATE_CON(13), /* gate_reg */ + __BIT(2), /* gate_mask */ + 0), + RK_COMPOSITE(RK3288_SCLK_EMMC, "sclk_emmc", mmc_parents, + CLKSEL_CON(12), /* muxdiv_reg */ + __BITS(15,14), /* mux_mask */ + __BITS(13,8), /* div_mask */ + CLKGATE_CON(13), /* gate_reg */ + __BIT(3), /* gate_mask */ + 0), + + /* MAC */ + RK_COMPOSITE(0, "mac_pll_src", mux_npll_cpll_gpll_parents, + CLKSEL_CON(21), /* muxdiv_reg */ + __BITS(1,0), /* mux_mask */ + __BITS(12,8), /* div_mask */ + CLKGATE_CON(2), /* gate_reg */ + __BIT(5), /* gate_mask */ + 0), + + RK_DIV(0, "aclk_cpu_pre", "aclk_cpu_src", CLKSEL_CON(1), __BITS(3,0), 0), + RK_DIV(0, "clk_24m", "xin24m", CLKSEL_CON(2), __BITS(12,8), 0), + RK_DIV(0, "pclk_pd_alive", "gpll", CLKSEL_CON(33), __BITS(12,8), 0), + + RK_MUX(RK3288_SCLK_UART0, "sclk_uart0", uart0_parents, CLKSEL_CON(13), __BITS(9,8)), + RK_MUX(RK3288_SCLK_UART1, "sclk_uart1", uart1_parents, CLKSEL_CON(14), __BITS(9,8)), + RK_MUX(RK3288_SCLK_UART2, "sclk_uart2", uart2_parents, CLKSEL_CON(15), __BITS(9,8)), + RK_MUX(RK3288_SCLK_UART3, "sclk_uart3", uart3_parents, CLKSEL_CON(16), __BITS(9,8)), + RK_MUX(RK3288_SCLK_UART4, "sclk_uart4", uart4_parents, CLKSEL_CON(3), __BITS(9,8)), + RK_MUX(0, "uart_src", mux_2plls_parents, CLKSEL_CON(15), __BIT(15)), + RK_MUX(RK3288_SCLK_MAC, "mac_clk", mac_parents, CLKSEL_CON(21), __BIT(4)), + + RK_GATE(0, "gpll_aclk_cpu", "gpll", CLKGATE_CON(0), 10), + RK_GATE(0, "cpll_aclk_cpu", "cpll", CLKGATE_CON(0), 11), + RK_GATE(RK3288_ACLK_PERI, "aclk_peri", "aclk_peri_src", CLKGATE_CON(2), 1), + RK_GATE(RK3288_SCLK_MAC_RX, "sclk_mac_rx", "mac_clk", CLKGATE_CON(5), 0), + RK_GATE(RK3288_SCLK_MAC_TX, "sclk_mac_tx", "mac_clk", CLKGATE_CON(5), 1), + RK_GATE(RK3288_SCLK_MACREF, "sclk_macref", "mac_clk", CLKGATE_CON(5), 2), + RK_GATE(RK3288_SCLK_MACREF_OUT, "sclk_macref_out", "mac_clk", CLKGATE_CON(5), 3), + RK_GATE(RK3288_PCLK_I2C1, "pclk_i2c1", "pclk_peri", CLKGATE_CON(6), 13), + RK_GATE(RK3288_PCLK_I2C3, "pclk_i2c3", "pclk_peri", CLKGATE_CON(6), 14), + RK_GATE(RK3288_PCLK_I2C4, "pclk_i2c4", "pclk_peri", CLKGATE_CON(6), 15), + RK_GATE(RK3288_PCLK_I2C5, "pclk_i2c5", "pclk_peri", CLKGATE_CON(7), 0), + RK_GATE(RK3288_HCLK_USBHOST0, "hclk_host0", "hclk_peri", CLKGATE_CON(7), 6), + RK_GATE(RK3288_HCLK_USBHOST1, "hclk_host1", "hclk_peri", CLKGATE_CON(7), 7), + RK_GATE(RK3288_HCLK_HSIC, "hclk_hsic", "hclk_peri", CLKGATE_CON(7), 8), + RK_GATE(RK3288_PCLK_GMAC, "pclk_gmac", "pclk_peri", CLKGATE_CON(8), 1), + RK_GATE(RK3288_HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", CLKGATE_CON(8), 3), + RK_GATE(RK3288_HCLK_SDIO0, "hclk_sdio0", "hclk_peri", CLKGATE_CON(8), 4), + RK_GATE(RK3288_HCLK_SDIO1, "hclk_sdio1", "hclk_peri", CLKGATE_CON(8), 5), + RK_GATE(RK3288_ACLK_GMAC, "aclk_gmac", "aclk_peri", CLKGATE_CON(8), 0), + RK_GATE(RK3288_HCLK_EMMC, "hclk_emmc", "hclk_peri", CLKGATE_CON(8), 6), + RK_GATE(RK3288_PCLK_I2C0, "pclk_i2c0", "pclk_cpu", CLKGATE_CON(10), 2), + RK_GATE(RK3288_PCLK_I2C2, "pclk_i2c2", "pclk_cpu", CLKGATE_CON(10), 3), + RK_GATE(RK3288_PCLK_UART2, "pclk_uart2", "pclk_cpu", CLKGATE_CON(11), 9), + RK_GATE(RK3288_SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLKGATE_CON(13), 4), + RK_GATE(RK3288_SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLKGATE_CON(13), 5), + RK_GATE(RK3288_SCLK_OTGPHY2, "sclk_otgphy2", "xin24m", CLKGATE_CON(13), 6), + RK_GATE(RK3288_PCLK_GPIO1, "pclk_gpio1", "pclk_pd_alive", CLKGATE_CON(14), 1), + RK_GATE(RK3288_PCLK_GPIO2, "pclk_gpio2", "pclk_pd_alive", CLKGATE_CON(14), 2), + RK_GATE(RK3288_PCLK_GPIO3, "pclk_gpio3", "pclk_pd_alive", CLKGATE_CON(14), 3), + RK_GATE(RK3288_PCLK_GPIO4, "pclk_gpio4", "pclk_pd_alive", CLKGATE_CON(14), 4), + RK_GATE(RK3288_PCLK_GPIO5, "pclk_gpio5", "pclk_pd_alive", CLKGATE_CON(14), 5), + RK_GATE(RK3288_PCLK_GPIO6, "pclk_gpio6", "pclk_pd_alive", CLKGATE_CON(14), 6), + RK_GATE(RK3288_PCLK_GPIO7, "pclk_gpio7", "pclk_pd_alive", CLKGATE_CON(14), 7), + RK_GATE(RK3288_PCLK_GPIO8, "pclk_gpio8", "pclk_pd_alive", CLKGATE_CON(14), 8), + RK_GATE(RK3288_PCLK_GPIO0, "pclk_gpio0", "pclk_pd_pmu", CLKGATE_CON(17), 4), +}; + +static int +rk3288_cru_match(device_t parent, cfdata_t cf, void *aux) +{ + struct fdt_attach_args * const faa = aux; + + return of_compatible_match(faa->faa_phandle, compat_data); +} + +static void +rk3288_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 = rk3288_cru_clks; + sc->sc_nclks = __arraycount(rk3288_cru_clks); + + sc->sc_grf_soc_status = 0x0284; + sc->sc_softrst_base = SOFTRST_CON(0); + + if (rk_cru_attach(sc) != 0) + return; + + aprint_naive("\n"); + aprint_normal(": RK3288 CRU\n"); + + rk_cru_print(sc); +} Index: src/sys/arch/arm/rockchip/rk3288_cru.h diff -u /dev/null src/sys/arch/arm/rockchip/rk3288_cru.h:1.1 --- /dev/null Fri Nov 12 22:02:08 2021 +++ src/sys/arch/arm/rockchip/rk3288_cru.h Fri Nov 12 22:02:08 2021 @@ -0,0 +1,209 @@ +/* $NetBSD: rk3288_cru.h,v 1.1 2021/11/12 22:02:08 jmcneill Exp $ */ + +/*- + * Copyright (c) 2021 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 _RK3328_CRU_H +#define _RK3328_CRU_H + +#define RK3288_PLL_APLL 1 +#define RK3288_PLL_DPLL 2 +#define RK3288_PLL_CPLL 3 +#define RK3288_PLL_GPLL 4 +#define RK3288_PLL_NPLL 5 +#define RK3288_ARMCLK 6 +#define RK3288_SCLK_GPU 64 +#define RK3288_SCLK_SPI0 65 +#define RK3288_SCLK_SPI1 66 +#define RK3288_SCLK_SPI2 67 +#define RK3288_SCLK_SDMMC 68 +#define RK3288_SCLK_SDIO0 69 +#define RK3288_SCLK_SDIO1 70 +#define RK3288_SCLK_EMMC 71 +#define RK3288_SCLK_TSADC 72 +#define RK3288_SCLK_SARADC 73 +#define RK3288_SCLK_PS2C 74 +#define RK3288_SCLK_NANDC0 75 +#define RK3288_SCLK_NANDC1 76 +#define RK3288_SCLK_UART0 77 +#define RK3288_SCLK_UART1 78 +#define RK3288_SCLK_UART2 79 +#define RK3288_SCLK_UART3 80 +#define RK3288_SCLK_UART4 81 +#define RK3288_SCLK_I2S0 82 +#define RK3288_SCLK_SPDIF 83 +#define RK3288_SCLK_SPDIF8CH 84 +#define RK3288_SCLK_TIMER0 85 +#define RK3288_SCLK_TIMER1 86 +#define RK3288_SCLK_TIMER2 87 +#define RK3288_SCLK_TIMER3 88 +#define RK3288_SCLK_TIMER4 89 +#define RK3288_SCLK_TIMER5 90 +#define RK3288_SCLK_TIMER6 91 +#define RK3288_SCLK_HSADC 92 +#define RK3288_SCLK_OTGPHY0 93 +#define RK3288_SCLK_OTGPHY1 94 +#define RK3288_SCLK_OTGPHY2 95 +#define RK3288_SCLK_OTG_ADP 96 +#define RK3288_SCLK_HSICPHY480M 97 +#define RK3288_SCLK_HSICPHY12M 98 +#define RK3288_SCLK_MACREF 99 +#define RK3288_SCLK_LCDC_PWM0 100 +#define RK3288_SCLK_LCDC_PWM1 101 +#define RK3288_SCLK_MAC_RX 102 +#define RK3288_SCLK_MAC_TX 103 +#define RK3288_SCLK_EDP_24M 104 +#define RK3288_SCLK_EDP 105 +#define RK3288_SCLK_RGA 106 +#define RK3288_SCLK_ISP 107 +#define RK3288_SCLK_ISP_JPE 108 +#define RK3288_SCLK_HDMI_HDCP 109 +#define RK3288_SCLK_HDMI_CEC 110 +#define RK3288_SCLK_HEVC_CABAC 111 +#define RK3288_SCLK_HEVC_CORE 112 +#define RK3288_SCLK_I2S0_OUT 113 +#define RK3288_SCLK_SDMMC_DRV 114 +#define RK3288_SCLK_SDIO0_DRV 115 +#define RK3288_SCLK_SDIO1_DRV 116 +#define RK3288_SCLK_EMMC_DRV 117 +#define RK3288_SCLK_SDMMC_SAMPLE 118 +#define RK3288_SCLK_SDIO0_SAMPLE 119 +#define RK3288_SCLK_SDIO1_SAMPLE 120 +#define RK3288_SCLK_EMMC_SAMPLE 121 +#define RK3288_SCLK_USBPHY480M_SRC 122 +#define RK3288_SCLK_PVTM_CORE 123 +#define RK3288_SCLK_PVTM_GPU 124 +#define RK3288_SCLK_CRYPTO 125 +#define RK3288_SCLK_MIPIDSI_24M 126 +#define RK3288_SCLK_VIP_OUT 127 +#define RK3288_SCLK_MAC 151 +#define RK3288_SCLK_MACREF_OUT 152 +#define RK3288_DCLK_VOP0 190 +#define RK3288_DCLK_VOP1 191 +#define RK3288_ACLK_GPU 192 +#define RK3288_ACLK_DMAC1 193 +#define RK3288_ACLK_DMAC2 194 +#define RK3288_ACLK_MMU 195 +#define RK3288_ACLK_GMAC 196 +#define RK3288_ACLK_VOP0 197 +#define RK3288_ACLK_VOP1 198 +#define RK3288_ACLK_CRYPTO 199 +#define RK3288_ACLK_RGA 200 +#define RK3288_ACLK_RGA_NIU 201 +#define RK3288_ACLK_IEP 202 +#define RK3288_ACLK_VIO0_NIU 203 +#define RK3288_ACLK_VIP 204 +#define RK3288_ACLK_ISP 205 +#define RK3288_ACLK_VIO1_NIU 206 +#define RK3288_ACLK_HEVC 207 +#define RK3288_ACLK_VCODEC 208 +#define RK3288_ACLK_CPU 209 +#define RK3288_ACLK_PERI 210 +#define RK3288_PCLK_GPIO0 320 +#define RK3288_PCLK_GPIO1 321 +#define RK3288_PCLK_GPIO2 322 +#define RK3288_PCLK_GPIO3 323 +#define RK3288_PCLK_GPIO4 324 +#define RK3288_PCLK_GPIO5 325 +#define RK3288_PCLK_GPIO6 326 +#define RK3288_PCLK_GPIO7 327 +#define RK3288_PCLK_GPIO8 328 +#define RK3288_PCLK_GRF 329 +#define RK3288_PCLK_SGRF 330 +#define RK3288_PCLK_PMU 331 +#define RK3288_PCLK_I2C0 332 +#define RK3288_PCLK_I2C1 333 +#define RK3288_PCLK_I2C2 334 +#define RK3288_PCLK_I2C3 335 +#define RK3288_PCLK_I2C4 336 +#define RK3288_PCLK_I2C5 337 +#define RK3288_PCLK_SPI0 338 +#define RK3288_PCLK_SPI1 339 +#define RK3288_PCLK_SPI2 340 +#define RK3288_PCLK_UART0 341 +#define RK3288_PCLK_UART1 342 +#define RK3288_PCLK_UART2 343 +#define RK3288_PCLK_UART3 344 +#define RK3288_PCLK_UART4 345 +#define RK3288_PCLK_TSADC 346 +#define RK3288_PCLK_SARADC 347 +#define RK3288_PCLK_SIM 348 +#define RK3288_PCLK_GMAC 349 +#define RK3288_PCLK_PWM 350 +#define RK3288_PCLK_RKPWM 351 +#define RK3288_PCLK_PS2C 352 +#define RK3288_PCLK_TIMER 353 +#define RK3288_PCLK_TZPC 354 +#define RK3288_PCLK_EDP_CTRL 355 +#define RK3288_PCLK_MIPI_DSI0 356 +#define RK3288_PCLK_MIPI_DSI1 357 +#define RK3288_PCLK_MIPI_CSI 358 +#define RK3288_PCLK_LVDS_PHY 359 +#define RK3288_PCLK_HDMI_CTRL 360 +#define RK3288_PCLK_VIO2_H2P 361 +#define RK3288_PCLK_CPU 362 +#define RK3288_PCLK_PERI 363 +#define RK3288_PCLK_DDRUPCTL0 364 +#define RK3288_PCLK_PUBL0 365 +#define RK3288_PCLK_DDRUPCTL1 366 +#define RK3288_PCLK_PUBL1 367 +#define RK3288_PCLK_WDT 368 +#define RK3288_PCLK_EFUSE256 369 +#define RK3288_PCLK_EFUSE1024 370 +#define RK3288_PCLK_ISP_IN 371 +#define RK3288_HCLK_GPS 448 +#define RK3288_HCLK_OTG0 449 +#define RK3288_HCLK_USBHOST0 450 +#define RK3288_HCLK_USBHOST1 451 +#define RK3288_HCLK_HSIC 452 +#define RK3288_HCLK_NANDC0 453 +#define RK3288_HCLK_NANDC1 454 +#define RK3288_HCLK_TSP 455 +#define RK3288_HCLK_SDMMC 456 +#define RK3288_HCLK_SDIO0 457 +#define RK3288_HCLK_SDIO1 458 +#define RK3288_HCLK_EMMC 459 +#define RK3288_HCLK_HSADC 460 +#define RK3288_HCLK_CRYPTO 461 +#define RK3288_HCLK_I2S0 462 +#define RK3288_HCLK_SPDIF 463 +#define RK3288_HCLK_SPDIF8CH 464 +#define RK3288_HCLK_VOP0 465 +#define RK3288_HCLK_VOP1 466 +#define RK3288_HCLK_ROM 467 +#define RK3288_HCLK_IEP 468 +#define RK3288_HCLK_ISP 469 +#define RK3288_HCLK_RGA 470 +#define RK3288_HCLK_VIO_AHB_ARBI 471 +#define RK3288_HCLK_VIO_NIU 472 +#define RK3288_HCLK_VIP 473 +#define RK3288_HCLK_VIO2_H2P 474 +#define RK3288_HCLK_HEVC 475 +#define RK3288_HCLK_VCODEC 476 +#define RK3288_HCLK_CPU 477 +#define RK3288_HCLK_PERI 478 + +#endif /* !_RK3328_CRU_H */ Index: src/sys/arch/arm/rockchip/rk3288_iomux.c diff -u /dev/null src/sys/arch/arm/rockchip/rk3288_iomux.c:1.1 --- /dev/null Fri Nov 12 22:02:08 2021 +++ src/sys/arch/arm/rockchip/rk3288_iomux.c Fri Nov 12 22:02:08 2021 @@ -0,0 +1,367 @@ +/* $NetBSD: rk3288_iomux.c,v 1.1 2021/11/12 22:02:08 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: rk3288_iomux.c,v 1.1 2021/11/12 22:02:08 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 GPIO_P_CTL_Z 0 +#define GPIO_P_CTL_PULLUP 1 +#define GPIO_P_CTL_PULLDOWN 2 +#define GPIO_P_CTL_MASK 0x3U + +#define GPIO_E_CTL_2MA 0 +#define GPIO_E_CTL_4MA 1 +#define GPIO_E_CTL_8MA 2 +#define GPIO_E_CTL_12MA 3 +#define GPIO_E_CTL_MASK 0x3U + +static const struct device_compatible_entry compat_data[] = { + { .compat = "rockchip,rk3288-pinctrl" }, + DEVICE_COMPAT_EOL +}; + +struct rk3288_iomux_softc { + device_t sc_dev; + struct syscon *sc_grf; + struct syscon *sc_pmu; +}; + +struct rk3288_iomux_reg { + struct syscon *syscon; + int mux_reg; + uint32_t mux_bit; + int pull_reg; + uint32_t pull_bit; + int drv_reg; + uint32_t drv_bit; + uint32_t flags; +#define IOMUX_NOROUTE __BIT(0) +#define IOMUX_4BIT __BIT(1) +}; + +#define LOCK(reg) \ + syscon_lock((reg)->syscon) +#define UNLOCK(reg) \ + syscon_unlock((reg)->syscon) +#define RD4(reg, off) \ + syscon_read_4((reg)->syscon, (off)) +#define WR4(reg, off, val) \ + syscon_write_4((reg)->syscon, (off), (val)) + +static int rk3288_iomux_match(device_t, cfdata_t, void *); +static void rk3288_iomux_attach(device_t, device_t, void *); + +CFATTACH_DECL_NEW(rk3288_iomux, sizeof(struct rk3288_iomux_softc), + rk3288_iomux_match, rk3288_iomux_attach, NULL, NULL); + +#define NBANKS 9 +#define NPINSPERBANK 32 + +static uint32_t rk3288_iomux_flags[NBANKS][NPINSPERBANK / 8] = { + [0] = { 0, 0, 0, IOMUX_NOROUTE }, + [1] = { IOMUX_NOROUTE, IOMUX_NOROUTE, IOMUX_NOROUTE, 0 }, + [2] = { 0, 0, 0, IOMUX_NOROUTE }, + [3] = { 0, 0, 0, IOMUX_4BIT }, + [4] = { IOMUX_4BIT, IOMUX_4BIT, 0, 0 }, + [5] = { IOMUX_NOROUTE, 0, 0, IOMUX_NOROUTE }, + [6] = { 0, 0, 0, IOMUX_NOROUTE }, + [7] = { 0, 0, IOMUX_4BIT, IOMUX_NOROUTE }, + [8] = { 0, 0, IOMUX_NOROUTE, IOMUX_NOROUTE } +}; + +static int rk3288_iomux_offset[NBANKS][NPINSPERBANK / 8] = { + /* PMU offsets */ + [0] = { 0x84, 0x88, 0x8c, -1 }, + /* GRF offsets */ + [1] = { -1, -1, -1, 0x0c }, + [2] = { 0x10, 0x14, 0x18, -1 }, + [3] = { 0x20, 0x24, 0x28, 0x2c }, + [4] = { 0x34, 0x3c, 0x44, 0x48 }, + [5] = { -1, 0x50, 0x54, -1 }, + [6] = { 0x5c, 0x60, 0x64, -1 }, + [7] = { 0x6c, 0x70, 0x74, -1 }, + [8] = { 0x80, 0x84, -1, -1 }, +}; + +static bool +rk3288_iomux_get_reg(struct rk3288_iomux_softc *sc, u_int bank, u_int idx, + struct rk3288_iomux_reg *reg) +{ + if (bank >= NBANKS || idx >= NPINSPERBANK) { + return false; + } + + if (bank == 0) { + reg->syscon = sc->sc_pmu; + reg->pull_reg = 0x64 + (idx / 8) * 4; + reg->pull_bit = idx % 8 * 2; + reg->drv_reg = 0x70 + (idx / 8) * 4; + reg->drv_bit = idx % 8 * 2; + } else { + reg->syscon = sc->sc_grf; + reg->pull_reg = 0x130 + (bank * 0x10) + (idx / 8) * 4; + reg->pull_bit = idx % 8 * 2; + reg->drv_reg = 0x1b0 + (bank * 0x10) + (idx / 8) * 4; + reg->drv_bit = idx % 8 * 2; + } + reg->flags = rk3288_iomux_flags[bank][idx / 8]; + reg->mux_reg = rk3288_iomux_offset[bank][idx / 8]; + if (reg->mux_reg != -1) { + if ((reg->flags & IOMUX_4BIT) == 0) { + reg->mux_bit = idx % 8 * 2; + } else { + reg->mux_bit = idx % 4 * 4; + if ((idx % 8) >= 4) { + reg->mux_reg += 0x4; + } + } + } + + return true; +} + +static void +rk3288_iomux_set_bias(struct rk3288_iomux_softc *sc, struct rk3288_iomux_reg *reg, + int bias) +{ + uint32_t val; + u_int p; + + switch (bias) { + case 0: + p = GPIO_P_CTL_Z; + break; + case GPIO_PIN_PULLUP: + p = GPIO_P_CTL_PULLUP; + break; + case GPIO_PIN_PULLDOWN: + p = GPIO_P_CTL_PULLDOWN; + break; + default: + return; + } + + val = GPIO_P_CTL_MASK << (reg->pull_bit + 16); + val |= p << reg->pull_bit; + +#ifdef RK3288_IOMUX_DEBUG + const uint32_t oval = RD4(reg, reg->pull_reg); + printf("%s: wr %#x -> %#x (%#x)\n", __func__, + oval & (GPIO_P_CTL_MASK << reg->pull_bit), + val & 0xffff, + GPIO_P_CTL_MASK << reg->pull_bit); +#endif + + WR4(reg, reg->pull_reg, val); +} + +static void +rk3288_iomux_set_drive_strength(struct rk3288_iomux_softc *sc, + struct rk3288_iomux_reg *reg, int drv) +{ + uint32_t val; + u_int e; + + switch (drv) { + case 2: + e = GPIO_E_CTL_2MA; + break; + case 4: + e = GPIO_E_CTL_4MA; + break; + case 8: + e = GPIO_E_CTL_8MA; + break; + case 12: + e = GPIO_E_CTL_12MA; + break; + default: + return; + } + + val = GPIO_E_CTL_MASK << (reg->drv_bit + 16); + val |= e << reg->drv_bit; + WR4(reg, reg->drv_reg, val); +} + +static void +rk3288_iomux_set_mux(struct rk3288_iomux_softc *sc, + struct rk3288_iomux_reg *reg, u_int mux) +{ + uint32_t val; + + KASSERT(reg->mux_reg != -1); + + val = ((reg->flags & IOMUX_4BIT) ? 0xf : 0x3) << (reg->mux_bit + 16); + val |= mux << reg->mux_bit; + + WR4(reg, reg->mux_reg, val); +} + +static void +rk3288_iomux_config(struct rk3288_iomux_softc *sc, struct rk3288_iomux_reg *reg, + u_int mux, const int phandle) +{ + int bias, drv; + + bias = fdtbus_pinctrl_parse_bias(phandle, NULL); + drv = fdtbus_pinctrl_parse_drive_strength(phandle); + +#ifdef RK3288_IOMUX_DEBUG + printf(" -> %s mux %#x/%d, pull %#x/%d, drv %#x/%d, flags %#x\n", + reg->syscon == sc->sc_pmu ? "pmu" : "grf", + reg->mux_reg, reg->mux_bit, + reg->pull_reg, reg->pull_bit, + reg->drv_reg, reg->drv_bit, + reg->flags); + printf(" bias %d drv %d mux %u\n", bias, drv, mux); +#endif + + /* XXX + * ASUS Tinkerboard goes nuts if we update any PMU bias fields. + * Skip them until we figure out why. + */ + if (reg->syscon == sc->sc_pmu) { + bias = -1; + } + + LOCK(reg); + + if (bias != -1) { + rk3288_iomux_set_bias(sc, reg, bias); + } + if (drv != -1) { + rk3288_iomux_set_drive_strength(sc, reg, drv); + } + if ((reg->flags & IOMUX_NOROUTE) == 0) { + rk3288_iomux_set_mux(sc, reg, mux); + } + + UNLOCK(reg); +} + +static int +rk3288_iomux_pinctrl_set_config(device_t dev, const void *data, size_t len) +{ + struct rk3288_iomux_softc * const sc = device_private(dev); + int pins_len = 0; + + 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 rk3288_iomux_reg regdef = {}; + + if (rk3288_iomux_get_reg(sc, bank, idx, ®def)) { +#ifdef RK3288_IOMUX_DEBUG + printf(" -> gpio%u P%c%u (%u)\n", bank, 'A' + (idx / 8), idx % 8, idx); +#endif + rk3288_iomux_config(sc, ®def, mux, cfg); + } else { + aprint_error_dev(dev, "unsupported iomux bank %u idx %u\n", + bank, mux); + } + + pins_len -= 16; + pins += 4; + } + + return 0; +} + +static struct fdtbus_pinctrl_controller_func rk3288_iomux_pinctrl_funcs = { + .set_config = rk3288_iomux_pinctrl_set_config, +}; + +static int +rk3288_iomux_match(device_t parent, cfdata_t cf, void *aux) +{ + struct fdt_attach_args * const faa = aux; + + return of_compatible_match(faa->faa_phandle, compat_data); +} + +static void +rk3288_iomux_attach(device_t parent, device_t self, void *aux) +{ + struct rk3288_iomux_softc * const sc = device_private(self); + struct fdt_attach_args * const faa = aux; + const int phandle = faa->faa_phandle; + + sc->sc_dev = self; + sc->sc_grf = fdtbus_syscon_acquire(phandle, "rockchip,grf"); + if (sc->sc_grf == NULL) { + aprint_error(": couldn't acquire grf syscon\n"); + return; + } + sc->sc_pmu = fdtbus_syscon_acquire(phandle, "rockchip,pmu"); + if (sc->sc_pmu == NULL) { + aprint_error(": couldn't acquire pmu syscon\n"); + return; + } + + aprint_naive("\n"); + aprint_normal(": RK3288 IOMUX control\n"); + + for (int child = OF_child(phandle); child; child = OF_peer(child)) { + for (int sub = OF_child(child); sub; sub = OF_peer(sub)) { + if (!of_hasprop(sub, "rockchip,pins")) + continue; + fdtbus_register_pinctrl_config(self, sub, &rk3288_iomux_pinctrl_funcs); + } + } + + for (int 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, CFARGS_NONE); + } +} Index: src/sys/arch/arm/rockchip/rk3288_platform.h diff -u /dev/null src/sys/arch/arm/rockchip/rk3288_platform.h:1.1 --- /dev/null Fri Nov 12 22:02:08 2021 +++ src/sys/arch/arm/rockchip/rk3288_platform.h Fri Nov 12 22:02:08 2021 @@ -0,0 +1,40 @@ +/* $NetBSD: rk3288_platform.h,v 1.1 2021/11/12 22:02:08 jmcneill Exp $ */ + +/*- + * Copyright (c) 2021 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_RK3288_PLATFORM_H +#define _ARM_RK3288_PLATFORM_H + +#include <arch/evbarm/fdt/platform.h> + +#define RK3288_CORE_VBASE KERNEL_IO_VBASE +#define RK3288_CORE_PBASE 0xff000000 +#define RK3288_CORE_SIZE 0x01000000 + +#define RK3288_UART_FREQ 24000000 + +#endif /* _ARM_RK3288_PLATFORM_H */ Index: src/sys/arch/arm/rockchip/rk3288_usb.c diff -u /dev/null src/sys/arch/arm/rockchip/rk3288_usb.c:1.1 --- /dev/null Fri Nov 12 22:02:08 2021 +++ src/sys/arch/arm/rockchip/rk3288_usb.c Fri Nov 12 22:02:08 2021 @@ -0,0 +1,183 @@ +/* $NetBSD: rk3288_usb.c,v 1.1 2021/11/12 22:02:08 jmcneill Exp $ */ + +/*- + * Copyright (c) 2021 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``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 FOUNDATION OR CONTRIBUTORS + * 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: rk3288_usb.c,v 1.1 2021/11/12 22:02:08 jmcneill Exp $"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/device.h> +#include <sys/intr.h> +#include <sys/systm.h> +#include <sys/time.h> +#include <sys/kmem.h> + +#include <dev/fdt/fdtvar.h> +#include <dev/fdt/syscon.h> + +#define GRF_UOCn_CON0_SIDDQ __BIT(13) + +static int rk3288_usb_match(device_t, cfdata_t, void *); +static void rk3288_usb_attach(device_t, device_t, void *); + +static const struct device_compatible_entry compat_data[] = { + { .compat = "rockchip,rk3288-usb-phy" }, + DEVICE_COMPAT_EOL +}; + +CFATTACH_DECL_NEW(rk3288_usb, 0, + rk3288_usb_match, rk3288_usb_attach, NULL, NULL); + +static int +rk3288_usb_match(device_t parent, cfdata_t cf, void *aux) +{ + struct fdt_attach_args * const faa = aux; + + return of_compatible_match(faa->faa_phandle, compat_data); +} + +static void +rk3288_usb_attach(device_t parent, device_t self, void *aux) +{ + struct fdt_attach_args * const faa = aux; + const int phandle = faa->faa_phandle; + int child; + + aprint_naive("\n"); + aprint_normal(": USB PHY\n"); + + for (child = OF_child(phandle); child; child = OF_peer(child)) { + if (!fdtbus_status_okay(child)) + continue; + + 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, CFARGS_NONE); + } +} + +/* + * USB PHY + */ + +static int rk3288_usbphy_match(device_t, cfdata_t, void *); +static void rk3288_usbphy_attach(device_t, device_t, void *); + +struct rk3288_usbphy_softc { + device_t sc_dev; + int sc_phandle; + struct syscon *sc_syscon; + bus_addr_t sc_reg; +}; + +CFATTACH_DECL_NEW(rk3288_usbphy, sizeof(struct rk3288_usbphy_softc), + rk3288_usbphy_match, rk3288_usbphy_attach, NULL, NULL); + +static void * +rk3288_usbphy_acquire(device_t dev, const void *data, size_t len) +{ + struct rk3288_usbphy_softc * const sc = device_private(dev); + + if (len != 0) + return NULL; + + return sc; +} + +static void +rk3288_usbphy_release(device_t dev, void *priv) +{ +} + +static int +rk3288_usbphy_enable(device_t dev, void *priv, bool enable) +{ + struct rk3288_usbphy_softc * const sc = device_private(dev); + uint32_t write_mask, write_val; + + write_mask = GRF_UOCn_CON0_SIDDQ << 16; + write_val = enable ? 0 : GRF_UOCn_CON0_SIDDQ; + + syscon_lock(sc->sc_syscon); + syscon_write_4(sc->sc_syscon, sc->sc_reg, write_mask | write_val); + syscon_unlock(sc->sc_syscon); + + return 0; +} + +const struct fdtbus_phy_controller_func rk3288_usbphy_funcs = { + .acquire = rk3288_usbphy_acquire, + .release = rk3288_usbphy_release, + .enable = rk3288_usbphy_enable, +}; + +static int +rk3288_usbphy_match(device_t parent, cfdata_t cf, void *aux) +{ + return 1; +} + +static void +rk3288_usbphy_attach(device_t parent, device_t self, void *aux) +{ + struct rk3288_usbphy_softc * const sc = device_private(self); + struct fdt_attach_args * const faa = aux; + const int phandle = faa->faa_phandle; + struct fdtbus_reset *rst; + + sc->sc_dev = self; + sc->sc_phandle = phandle; + sc->sc_syscon = fdtbus_syscon_lookup(OF_parent(OF_parent(phandle))); + if (sc->sc_syscon == NULL) { + aprint_error(": couldn't find syscon\n"); + return; + } + if (fdtbus_get_reg(phandle, 0, &sc->sc_reg, NULL) != 0) { + aprint_error(": couldn't find registers\n"); + return; + } + + rst = fdtbus_reset_get(phandle, "phy-reset"); + if (rst == NULL || fdtbus_reset_deassert(rst) != 0) { + aprint_error(": couldn't de-assert reset\n"); + return; + } + if (fdtbus_clock_enable(phandle, "phyclk", true) != 0) { + aprint_error(": couildn't enable clock\n"); + return; + } + + aprint_naive("\n"); + aprint_normal(": USB port\n"); + + fdtbus_register_phy_controller(self, phandle, &rk3288_usbphy_funcs); +}