18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Rockchip Generic Register Files setup 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2016 Heiko Stuebner <heiko@sntech.de> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/err.h> 98c2ecf20Sopenharmony_ci#include <linux/mfd/syscon.h> 108c2ecf20Sopenharmony_ci#include <linux/of_device.h> 118c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 128c2ecf20Sopenharmony_ci#include <linux/regmap.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define HIWORD_UPDATE(val, mask, shift) \ 158c2ecf20Sopenharmony_ci ((val) << (shift) | (mask) << ((shift) + 16)) 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistruct rockchip_grf_value { 188c2ecf20Sopenharmony_ci const char *desc; 198c2ecf20Sopenharmony_ci u32 reg; 208c2ecf20Sopenharmony_ci u32 val; 218c2ecf20Sopenharmony_ci}; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistruct rockchip_grf_info { 248c2ecf20Sopenharmony_ci const struct rockchip_grf_value *values; 258c2ecf20Sopenharmony_ci int num_values; 268c2ecf20Sopenharmony_ci}; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define RK3036_GRF_SOC_CON0 0x140 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistatic const struct rockchip_grf_value rk3036_defaults[] __initconst = { 318c2ecf20Sopenharmony_ci /* 328c2ecf20Sopenharmony_ci * Disable auto jtag/sdmmc switching that causes issues with the 338c2ecf20Sopenharmony_ci * clock-framework and the mmc controllers making them unreliable. 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_ci { "jtag switching", RK3036_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 11) }, 368c2ecf20Sopenharmony_ci}; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic const struct rockchip_grf_info rk3036_grf __initconst = { 398c2ecf20Sopenharmony_ci .values = rk3036_defaults, 408c2ecf20Sopenharmony_ci .num_values = ARRAY_SIZE(rk3036_defaults), 418c2ecf20Sopenharmony_ci}; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#define RK3128_GRF_SOC_CON0 0x140 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic const struct rockchip_grf_value rk3128_defaults[] __initconst = { 468c2ecf20Sopenharmony_ci { "jtag switching", RK3128_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 8) }, 478c2ecf20Sopenharmony_ci}; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic const struct rockchip_grf_info rk3128_grf __initconst = { 508c2ecf20Sopenharmony_ci .values = rk3128_defaults, 518c2ecf20Sopenharmony_ci .num_values = ARRAY_SIZE(rk3128_defaults), 528c2ecf20Sopenharmony_ci}; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#define RK3228_GRF_SOC_CON6 0x418 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic const struct rockchip_grf_value rk3228_defaults[] __initconst = { 578c2ecf20Sopenharmony_ci { "jtag switching", RK3228_GRF_SOC_CON6, HIWORD_UPDATE(0, 1, 8) }, 588c2ecf20Sopenharmony_ci}; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistatic const struct rockchip_grf_info rk3228_grf __initconst = { 618c2ecf20Sopenharmony_ci .values = rk3228_defaults, 628c2ecf20Sopenharmony_ci .num_values = ARRAY_SIZE(rk3228_defaults), 638c2ecf20Sopenharmony_ci}; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci#define RK3288_GRF_SOC_CON0 0x244 668c2ecf20Sopenharmony_ci#define RK3288_GRF_SOC_CON2 0x24c 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic const struct rockchip_grf_value rk3288_defaults[] __initconst = { 698c2ecf20Sopenharmony_ci { "jtag switching", RK3288_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 12) }, 708c2ecf20Sopenharmony_ci { "pwm select", RK3288_GRF_SOC_CON2, HIWORD_UPDATE(1, 1, 0) }, 718c2ecf20Sopenharmony_ci}; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic const struct rockchip_grf_info rk3288_grf __initconst = { 748c2ecf20Sopenharmony_ci .values = rk3288_defaults, 758c2ecf20Sopenharmony_ci .num_values = ARRAY_SIZE(rk3288_defaults), 768c2ecf20Sopenharmony_ci}; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci#define RK3328_GRF_SOC_CON4 0x410 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic const struct rockchip_grf_value rk3328_defaults[] __initconst = { 818c2ecf20Sopenharmony_ci { "jtag switching", RK3328_GRF_SOC_CON4, HIWORD_UPDATE(0, 1, 12) }, 828c2ecf20Sopenharmony_ci}; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic const struct rockchip_grf_info rk3328_grf __initconst = { 858c2ecf20Sopenharmony_ci .values = rk3328_defaults, 868c2ecf20Sopenharmony_ci .num_values = ARRAY_SIZE(rk3328_defaults), 878c2ecf20Sopenharmony_ci}; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci#define RK3368_GRF_SOC_CON15 0x43c 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic const struct rockchip_grf_value rk3368_defaults[] __initconst = { 928c2ecf20Sopenharmony_ci { "jtag switching", RK3368_GRF_SOC_CON15, HIWORD_UPDATE(0, 1, 13) }, 938c2ecf20Sopenharmony_ci}; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic const struct rockchip_grf_info rk3368_grf __initconst = { 968c2ecf20Sopenharmony_ci .values = rk3368_defaults, 978c2ecf20Sopenharmony_ci .num_values = ARRAY_SIZE(rk3368_defaults), 988c2ecf20Sopenharmony_ci}; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci#define RK3399_GRF_SOC_CON7 0xe21c 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic const struct rockchip_grf_value rk3399_defaults[] __initconst = { 1038c2ecf20Sopenharmony_ci { "jtag switching", RK3399_GRF_SOC_CON7, HIWORD_UPDATE(0, 1, 12) }, 1048c2ecf20Sopenharmony_ci}; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cistatic const struct rockchip_grf_info rk3399_grf __initconst = { 1078c2ecf20Sopenharmony_ci .values = rk3399_defaults, 1088c2ecf20Sopenharmony_ci .num_values = ARRAY_SIZE(rk3399_defaults), 1098c2ecf20Sopenharmony_ci}; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic const struct of_device_id rockchip_grf_dt_match[] __initconst = { 1128c2ecf20Sopenharmony_ci { 1138c2ecf20Sopenharmony_ci .compatible = "rockchip,rk3036-grf", 1148c2ecf20Sopenharmony_ci .data = (void *)&rk3036_grf, 1158c2ecf20Sopenharmony_ci }, { 1168c2ecf20Sopenharmony_ci .compatible = "rockchip,rk3128-grf", 1178c2ecf20Sopenharmony_ci .data = (void *)&rk3128_grf, 1188c2ecf20Sopenharmony_ci }, { 1198c2ecf20Sopenharmony_ci .compatible = "rockchip,rk3228-grf", 1208c2ecf20Sopenharmony_ci .data = (void *)&rk3228_grf, 1218c2ecf20Sopenharmony_ci }, { 1228c2ecf20Sopenharmony_ci .compatible = "rockchip,rk3288-grf", 1238c2ecf20Sopenharmony_ci .data = (void *)&rk3288_grf, 1248c2ecf20Sopenharmony_ci }, { 1258c2ecf20Sopenharmony_ci .compatible = "rockchip,rk3328-grf", 1268c2ecf20Sopenharmony_ci .data = (void *)&rk3328_grf, 1278c2ecf20Sopenharmony_ci }, { 1288c2ecf20Sopenharmony_ci .compatible = "rockchip,rk3368-grf", 1298c2ecf20Sopenharmony_ci .data = (void *)&rk3368_grf, 1308c2ecf20Sopenharmony_ci }, { 1318c2ecf20Sopenharmony_ci .compatible = "rockchip,rk3399-grf", 1328c2ecf20Sopenharmony_ci .data = (void *)&rk3399_grf, 1338c2ecf20Sopenharmony_ci }, 1348c2ecf20Sopenharmony_ci { /* sentinel */ }, 1358c2ecf20Sopenharmony_ci}; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_cistatic int __init rockchip_grf_init(void) 1388c2ecf20Sopenharmony_ci{ 1398c2ecf20Sopenharmony_ci const struct rockchip_grf_info *grf_info; 1408c2ecf20Sopenharmony_ci const struct of_device_id *match; 1418c2ecf20Sopenharmony_ci struct device_node *np; 1428c2ecf20Sopenharmony_ci struct regmap *grf; 1438c2ecf20Sopenharmony_ci int ret, i; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci np = of_find_matching_node_and_match(NULL, rockchip_grf_dt_match, 1468c2ecf20Sopenharmony_ci &match); 1478c2ecf20Sopenharmony_ci if (!np) 1488c2ecf20Sopenharmony_ci return -ENODEV; 1498c2ecf20Sopenharmony_ci if (!match || !match->data) { 1508c2ecf20Sopenharmony_ci pr_err("%s: missing grf data\n", __func__); 1518c2ecf20Sopenharmony_ci of_node_put(np); 1528c2ecf20Sopenharmony_ci return -EINVAL; 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci grf_info = match->data; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci grf = syscon_node_to_regmap(np); 1588c2ecf20Sopenharmony_ci of_node_put(np); 1598c2ecf20Sopenharmony_ci if (IS_ERR(grf)) { 1608c2ecf20Sopenharmony_ci pr_err("%s: could not get grf syscon\n", __func__); 1618c2ecf20Sopenharmony_ci return PTR_ERR(grf); 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci for (i = 0; i < grf_info->num_values; i++) { 1658c2ecf20Sopenharmony_ci const struct rockchip_grf_value *val = &grf_info->values[i]; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci pr_debug("%s: adjusting %s in %#6x to %#10x\n", __func__, 1688c2ecf20Sopenharmony_ci val->desc, val->reg, val->val); 1698c2ecf20Sopenharmony_ci ret = regmap_write(grf, val->reg, val->val); 1708c2ecf20Sopenharmony_ci if (ret < 0) 1718c2ecf20Sopenharmony_ci pr_err("%s: write to %#6x failed with %d\n", 1728c2ecf20Sopenharmony_ci __func__, val->reg, ret); 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci return 0; 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_cipostcore_initcall(rockchip_grf_init); 178