1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 24c58063dSHeiko Stuebner /* 34c58063dSHeiko Stuebner * Rockchip Generic Register Files setup 44c58063dSHeiko Stuebner * 54c58063dSHeiko Stuebner * Copyright (c) 2016 Heiko Stuebner <heiko@sntech.de> 64c58063dSHeiko Stuebner */ 74c58063dSHeiko Stuebner 84c58063dSHeiko Stuebner #include <linux/err.h> 94c58063dSHeiko Stuebner #include <linux/mfd/syscon.h> 100e7ed4ddSRob Herring #include <linux/of.h> 114c58063dSHeiko Stuebner #include <linux/platform_device.h> 124c58063dSHeiko Stuebner #include <linux/regmap.h> 134c58063dSHeiko Stuebner 144c58063dSHeiko Stuebner #define HIWORD_UPDATE(val, mask, shift) \ 154c58063dSHeiko Stuebner ((val) << (shift) | (mask) << ((shift) + 16)) 164c58063dSHeiko Stuebner 174c58063dSHeiko Stuebner struct rockchip_grf_value { 184c58063dSHeiko Stuebner const char *desc; 194c58063dSHeiko Stuebner u32 reg; 204c58063dSHeiko Stuebner u32 val; 214c58063dSHeiko Stuebner }; 224c58063dSHeiko Stuebner 234c58063dSHeiko Stuebner struct rockchip_grf_info { 244c58063dSHeiko Stuebner const struct rockchip_grf_value *values; 254c58063dSHeiko Stuebner int num_values; 264c58063dSHeiko Stuebner }; 274c58063dSHeiko Stuebner 284c58063dSHeiko Stuebner #define RK3036_GRF_SOC_CON0 0x140 294c58063dSHeiko Stuebner 304c58063dSHeiko Stuebner static const struct rockchip_grf_value rk3036_defaults[] __initconst = { 314c58063dSHeiko Stuebner /* 324c58063dSHeiko Stuebner * Disable auto jtag/sdmmc switching that causes issues with the 334c58063dSHeiko Stuebner * clock-framework and the mmc controllers making them unreliable. 344c58063dSHeiko Stuebner */ 354c58063dSHeiko Stuebner { "jtag switching", RK3036_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 11) }, 364c58063dSHeiko Stuebner }; 374c58063dSHeiko Stuebner 384c58063dSHeiko Stuebner static const struct rockchip_grf_info rk3036_grf __initconst = { 394c58063dSHeiko Stuebner .values = rk3036_defaults, 404c58063dSHeiko Stuebner .num_values = ARRAY_SIZE(rk3036_defaults), 414c58063dSHeiko Stuebner }; 424c58063dSHeiko Stuebner 436e61c891SXiao Yao #define RK3128_GRF_SOC_CON0 0x140 447bd76f40SAlex Bee #define RK3128_GRF_SOC_CON1 0x144 456e61c891SXiao Yao 466e61c891SXiao Yao static const struct rockchip_grf_value rk3128_defaults[] __initconst = { 476e61c891SXiao Yao { "jtag switching", RK3128_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 8) }, 487bd76f40SAlex Bee { "vpu main clock", RK3128_GRF_SOC_CON1, HIWORD_UPDATE(0, 1, 10) }, 496e61c891SXiao Yao }; 506e61c891SXiao Yao 516e61c891SXiao Yao static const struct rockchip_grf_info rk3128_grf __initconst = { 526e61c891SXiao Yao .values = rk3128_defaults, 536e61c891SXiao Yao .num_values = ARRAY_SIZE(rk3128_defaults), 546e61c891SXiao Yao }; 556e61c891SXiao Yao 56e17ee5f0SShawn Lin #define RK3228_GRF_SOC_CON6 0x418 57e17ee5f0SShawn Lin 58e17ee5f0SShawn Lin static const struct rockchip_grf_value rk3228_defaults[] __initconst = { 59e17ee5f0SShawn Lin { "jtag switching", RK3228_GRF_SOC_CON6, HIWORD_UPDATE(0, 1, 8) }, 60e17ee5f0SShawn Lin }; 61e17ee5f0SShawn Lin 62e17ee5f0SShawn Lin static const struct rockchip_grf_info rk3228_grf __initconst = { 63e17ee5f0SShawn Lin .values = rk3228_defaults, 64e17ee5f0SShawn Lin .num_values = ARRAY_SIZE(rk3228_defaults), 65e17ee5f0SShawn Lin }; 66e17ee5f0SShawn Lin 674c58063dSHeiko Stuebner #define RK3288_GRF_SOC_CON0 0x244 68bbdc00a7SDouglas Anderson #define RK3288_GRF_SOC_CON2 0x24c 694c58063dSHeiko Stuebner 704c58063dSHeiko Stuebner static const struct rockchip_grf_value rk3288_defaults[] __initconst = { 714c58063dSHeiko Stuebner { "jtag switching", RK3288_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 12) }, 72bbdc00a7SDouglas Anderson { "pwm select", RK3288_GRF_SOC_CON2, HIWORD_UPDATE(1, 1, 0) }, 734c58063dSHeiko Stuebner }; 744c58063dSHeiko Stuebner 754c58063dSHeiko Stuebner static const struct rockchip_grf_info rk3288_grf __initconst = { 764c58063dSHeiko Stuebner .values = rk3288_defaults, 774c58063dSHeiko Stuebner .num_values = ARRAY_SIZE(rk3288_defaults), 784c58063dSHeiko Stuebner }; 794c58063dSHeiko Stuebner 80887758c3SShawn Lin #define RK3328_GRF_SOC_CON4 0x410 81887758c3SShawn Lin 82887758c3SShawn Lin static const struct rockchip_grf_value rk3328_defaults[] __initconst = { 83887758c3SShawn Lin { "jtag switching", RK3328_GRF_SOC_CON4, HIWORD_UPDATE(0, 1, 12) }, 84887758c3SShawn Lin }; 85887758c3SShawn Lin 86887758c3SShawn Lin static const struct rockchip_grf_info rk3328_grf __initconst = { 87887758c3SShawn Lin .values = rk3328_defaults, 88887758c3SShawn Lin .num_values = ARRAY_SIZE(rk3328_defaults), 89887758c3SShawn Lin }; 90887758c3SShawn Lin 914c58063dSHeiko Stuebner #define RK3368_GRF_SOC_CON15 0x43c 924c58063dSHeiko Stuebner 934c58063dSHeiko Stuebner static const struct rockchip_grf_value rk3368_defaults[] __initconst = { 944c58063dSHeiko Stuebner { "jtag switching", RK3368_GRF_SOC_CON15, HIWORD_UPDATE(0, 1, 13) }, 954c58063dSHeiko Stuebner }; 964c58063dSHeiko Stuebner 974c58063dSHeiko Stuebner static const struct rockchip_grf_info rk3368_grf __initconst = { 984c58063dSHeiko Stuebner .values = rk3368_defaults, 994c58063dSHeiko Stuebner .num_values = ARRAY_SIZE(rk3368_defaults), 1004c58063dSHeiko Stuebner }; 1014c58063dSHeiko Stuebner 1024c58063dSHeiko Stuebner #define RK3399_GRF_SOC_CON7 0xe21c 1034c58063dSHeiko Stuebner 1044c58063dSHeiko Stuebner static const struct rockchip_grf_value rk3399_defaults[] __initconst = { 1054c58063dSHeiko Stuebner { "jtag switching", RK3399_GRF_SOC_CON7, HIWORD_UPDATE(0, 1, 12) }, 1064c58063dSHeiko Stuebner }; 1074c58063dSHeiko Stuebner 1084c58063dSHeiko Stuebner static const struct rockchip_grf_info rk3399_grf __initconst = { 1094c58063dSHeiko Stuebner .values = rk3399_defaults, 1104c58063dSHeiko Stuebner .num_values = ARRAY_SIZE(rk3399_defaults), 1114c58063dSHeiko Stuebner }; 1124c58063dSHeiko Stuebner 1135c0bb711SPeter Geis #define RK3566_GRF_USB3OTG0_CON1 0x0104 1145c0bb711SPeter Geis 1155c0bb711SPeter Geis static const struct rockchip_grf_value rk3566_defaults[] __initconst = { 1165c0bb711SPeter Geis { "usb3otg port switch", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(0, 1, 12) }, 1175c0bb711SPeter Geis { "usb3otg clock switch", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(1, 1, 7) }, 1185c0bb711SPeter Geis { "usb3otg disable usb3", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(1, 1, 0) }, 1195c0bb711SPeter Geis }; 1205c0bb711SPeter Geis 1215c0bb711SPeter Geis static const struct rockchip_grf_info rk3566_pipegrf __initconst = { 1225c0bb711SPeter Geis .values = rk3566_defaults, 1235c0bb711SPeter Geis .num_values = ARRAY_SIZE(rk3566_defaults), 1245c0bb711SPeter Geis }; 1255c0bb711SPeter Geis 126*e1aaecacSDetlev Casanova #define RK3576_SYSGRF_SOC_CON1 0x0004 127*e1aaecacSDetlev Casanova 128*e1aaecacSDetlev Casanova static const struct rockchip_grf_value rk3576_defaults_sys_grf[] __initconst = { 129*e1aaecacSDetlev Casanova { "i3c0 weakpull", RK3576_SYSGRF_SOC_CON1, HIWORD_UPDATE(3, 3, 6) }, 130*e1aaecacSDetlev Casanova { "i3c1 weakpull", RK3576_SYSGRF_SOC_CON1, HIWORD_UPDATE(3, 3, 8) }, 131*e1aaecacSDetlev Casanova }; 132*e1aaecacSDetlev Casanova 133*e1aaecacSDetlev Casanova static const struct rockchip_grf_info rk3576_sysgrf __initconst = { 134*e1aaecacSDetlev Casanova .values = rk3576_defaults_sys_grf, 135*e1aaecacSDetlev Casanova .num_values = ARRAY_SIZE(rk3576_defaults_sys_grf), 136*e1aaecacSDetlev Casanova }; 137*e1aaecacSDetlev Casanova 138*e1aaecacSDetlev Casanova #define RK3576_IOCGRF_MISC_CON 0x04F0 139*e1aaecacSDetlev Casanova 140*e1aaecacSDetlev Casanova static const struct rockchip_grf_value rk3576_defaults_ioc_grf[] __initconst = { 141*e1aaecacSDetlev Casanova { "jtag switching", RK3576_IOCGRF_MISC_CON, HIWORD_UPDATE(0, 1, 1) }, 142*e1aaecacSDetlev Casanova }; 143*e1aaecacSDetlev Casanova 144*e1aaecacSDetlev Casanova static const struct rockchip_grf_info rk3576_iocgrf __initconst = { 145*e1aaecacSDetlev Casanova .values = rk3576_defaults_ioc_grf, 146*e1aaecacSDetlev Casanova .num_values = ARRAY_SIZE(rk3576_defaults_ioc_grf), 147*e1aaecacSDetlev Casanova }; 148*e1aaecacSDetlev Casanova 1496f6878ecSOndrej Jirman #define RK3588_GRF_SOC_CON6 0x0318 1506f6878ecSOndrej Jirman 1516f6878ecSOndrej Jirman static const struct rockchip_grf_value rk3588_defaults[] __initconst = { 1526f6878ecSOndrej Jirman { "jtag switching", RK3588_GRF_SOC_CON6, HIWORD_UPDATE(0, 1, 14) }, 1536f6878ecSOndrej Jirman }; 1546f6878ecSOndrej Jirman 1556f6878ecSOndrej Jirman static const struct rockchip_grf_info rk3588_sysgrf __initconst = { 1566f6878ecSOndrej Jirman .values = rk3588_defaults, 1576f6878ecSOndrej Jirman .num_values = ARRAY_SIZE(rk3588_defaults), 1586f6878ecSOndrej Jirman }; 1596f6878ecSOndrej Jirman 1604c58063dSHeiko Stuebner static const struct of_device_id rockchip_grf_dt_match[] __initconst = { 1614c58063dSHeiko Stuebner { 1624c58063dSHeiko Stuebner .compatible = "rockchip,rk3036-grf", 1634c58063dSHeiko Stuebner .data = (void *)&rk3036_grf, 1644c58063dSHeiko Stuebner }, { 1656e61c891SXiao Yao .compatible = "rockchip,rk3128-grf", 1666e61c891SXiao Yao .data = (void *)&rk3128_grf, 1676e61c891SXiao Yao }, { 168e17ee5f0SShawn Lin .compatible = "rockchip,rk3228-grf", 169e17ee5f0SShawn Lin .data = (void *)&rk3228_grf, 170e17ee5f0SShawn Lin }, { 1714c58063dSHeiko Stuebner .compatible = "rockchip,rk3288-grf", 1724c58063dSHeiko Stuebner .data = (void *)&rk3288_grf, 1734c58063dSHeiko Stuebner }, { 174887758c3SShawn Lin .compatible = "rockchip,rk3328-grf", 175887758c3SShawn Lin .data = (void *)&rk3328_grf, 176887758c3SShawn Lin }, { 1774c58063dSHeiko Stuebner .compatible = "rockchip,rk3368-grf", 1784c58063dSHeiko Stuebner .data = (void *)&rk3368_grf, 1794c58063dSHeiko Stuebner }, { 1804c58063dSHeiko Stuebner .compatible = "rockchip,rk3399-grf", 1814c58063dSHeiko Stuebner .data = (void *)&rk3399_grf, 1825c0bb711SPeter Geis }, { 1835c0bb711SPeter Geis .compatible = "rockchip,rk3566-pipe-grf", 1845c0bb711SPeter Geis .data = (void *)&rk3566_pipegrf, 1856f6878ecSOndrej Jirman }, { 186*e1aaecacSDetlev Casanova .compatible = "rockchip,rk3576-sys-grf", 187*e1aaecacSDetlev Casanova .data = (void *)&rk3576_sysgrf, 188*e1aaecacSDetlev Casanova }, { 189*e1aaecacSDetlev Casanova .compatible = "rockchip,rk3576-ioc-grf", 190*e1aaecacSDetlev Casanova .data = (void *)&rk3576_iocgrf, 191*e1aaecacSDetlev Casanova }, { 1926f6878ecSOndrej Jirman .compatible = "rockchip,rk3588-sys-grf", 1936f6878ecSOndrej Jirman .data = (void *)&rk3588_sysgrf, 1944c58063dSHeiko Stuebner }, 1954c58063dSHeiko Stuebner { /* sentinel */ }, 1964c58063dSHeiko Stuebner }; 1974c58063dSHeiko Stuebner 1984c58063dSHeiko Stuebner static int __init rockchip_grf_init(void) 1994c58063dSHeiko Stuebner { 2004c58063dSHeiko Stuebner const struct rockchip_grf_info *grf_info; 2014c58063dSHeiko Stuebner const struct of_device_id *match; 2024c58063dSHeiko Stuebner struct device_node *np; 2034c58063dSHeiko Stuebner struct regmap *grf; 2044c58063dSHeiko Stuebner int ret, i; 2054c58063dSHeiko Stuebner 2064c58063dSHeiko Stuebner np = of_find_matching_node_and_match(NULL, rockchip_grf_dt_match, 2074c58063dSHeiko Stuebner &match); 2084c58063dSHeiko Stuebner if (!np) 2094c58063dSHeiko Stuebner return -ENODEV; 2104c58063dSHeiko Stuebner if (!match || !match->data) { 2114c58063dSHeiko Stuebner pr_err("%s: missing grf data\n", __func__); 2129b59588dSMiaoqian Lin of_node_put(np); 2134c58063dSHeiko Stuebner return -EINVAL; 2144c58063dSHeiko Stuebner } 2154c58063dSHeiko Stuebner 2164c58063dSHeiko Stuebner grf_info = match->data; 2174c58063dSHeiko Stuebner 2184c58063dSHeiko Stuebner grf = syscon_node_to_regmap(np); 2199b59588dSMiaoqian Lin of_node_put(np); 2204c58063dSHeiko Stuebner if (IS_ERR(grf)) { 2214c58063dSHeiko Stuebner pr_err("%s: could not get grf syscon\n", __func__); 2224c58063dSHeiko Stuebner return PTR_ERR(grf); 2234c58063dSHeiko Stuebner } 2244c58063dSHeiko Stuebner 2254c58063dSHeiko Stuebner for (i = 0; i < grf_info->num_values; i++) { 2264c58063dSHeiko Stuebner const struct rockchip_grf_value *val = &grf_info->values[i]; 2274c58063dSHeiko Stuebner 2284c58063dSHeiko Stuebner pr_debug("%s: adjusting %s in %#6x to %#10x\n", __func__, 2294c58063dSHeiko Stuebner val->desc, val->reg, val->val); 2304c58063dSHeiko Stuebner ret = regmap_write(grf, val->reg, val->val); 2314c58063dSHeiko Stuebner if (ret < 0) 2324c58063dSHeiko Stuebner pr_err("%s: write to %#6x failed with %d\n", 2334c58063dSHeiko Stuebner __func__, val->reg, ret); 2344c58063dSHeiko Stuebner } 2354c58063dSHeiko Stuebner 2364c58063dSHeiko Stuebner return 0; 2374c58063dSHeiko Stuebner } 2384c58063dSHeiko Stuebner postcore_initcall(rockchip_grf_init); 239