162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Rockchip Generic Register Files setup 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2016 Heiko Stuebner <heiko@sntech.de> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/err.h> 962306a36Sopenharmony_ci#include <linux/mfd/syscon.h> 1062306a36Sopenharmony_ci#include <linux/of.h> 1162306a36Sopenharmony_ci#include <linux/platform_device.h> 1262306a36Sopenharmony_ci#include <linux/regmap.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define HIWORD_UPDATE(val, mask, shift) \ 1562306a36Sopenharmony_ci ((val) << (shift) | (mask) << ((shift) + 16)) 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistruct rockchip_grf_value { 1862306a36Sopenharmony_ci const char *desc; 1962306a36Sopenharmony_ci u32 reg; 2062306a36Sopenharmony_ci u32 val; 2162306a36Sopenharmony_ci}; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistruct rockchip_grf_info { 2462306a36Sopenharmony_ci const struct rockchip_grf_value *values; 2562306a36Sopenharmony_ci int num_values; 2662306a36Sopenharmony_ci}; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define RK3036_GRF_SOC_CON0 0x140 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic const struct rockchip_grf_value rk3036_defaults[] __initconst = { 3162306a36Sopenharmony_ci /* 3262306a36Sopenharmony_ci * Disable auto jtag/sdmmc switching that causes issues with the 3362306a36Sopenharmony_ci * clock-framework and the mmc controllers making them unreliable. 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_ci { "jtag switching", RK3036_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 11) }, 3662306a36Sopenharmony_ci}; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic const struct rockchip_grf_info rk3036_grf __initconst = { 3962306a36Sopenharmony_ci .values = rk3036_defaults, 4062306a36Sopenharmony_ci .num_values = ARRAY_SIZE(rk3036_defaults), 4162306a36Sopenharmony_ci}; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#define RK3128_GRF_SOC_CON0 0x140 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic const struct rockchip_grf_value rk3128_defaults[] __initconst = { 4662306a36Sopenharmony_ci { "jtag switching", RK3128_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 8) }, 4762306a36Sopenharmony_ci}; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic const struct rockchip_grf_info rk3128_grf __initconst = { 5062306a36Sopenharmony_ci .values = rk3128_defaults, 5162306a36Sopenharmony_ci .num_values = ARRAY_SIZE(rk3128_defaults), 5262306a36Sopenharmony_ci}; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#define RK3228_GRF_SOC_CON6 0x418 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic const struct rockchip_grf_value rk3228_defaults[] __initconst = { 5762306a36Sopenharmony_ci { "jtag switching", RK3228_GRF_SOC_CON6, HIWORD_UPDATE(0, 1, 8) }, 5862306a36Sopenharmony_ci}; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic const struct rockchip_grf_info rk3228_grf __initconst = { 6162306a36Sopenharmony_ci .values = rk3228_defaults, 6262306a36Sopenharmony_ci .num_values = ARRAY_SIZE(rk3228_defaults), 6362306a36Sopenharmony_ci}; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci#define RK3288_GRF_SOC_CON0 0x244 6662306a36Sopenharmony_ci#define RK3288_GRF_SOC_CON2 0x24c 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic const struct rockchip_grf_value rk3288_defaults[] __initconst = { 6962306a36Sopenharmony_ci { "jtag switching", RK3288_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 12) }, 7062306a36Sopenharmony_ci { "pwm select", RK3288_GRF_SOC_CON2, HIWORD_UPDATE(1, 1, 0) }, 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic const struct rockchip_grf_info rk3288_grf __initconst = { 7462306a36Sopenharmony_ci .values = rk3288_defaults, 7562306a36Sopenharmony_ci .num_values = ARRAY_SIZE(rk3288_defaults), 7662306a36Sopenharmony_ci}; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci#define RK3328_GRF_SOC_CON4 0x410 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistatic const struct rockchip_grf_value rk3328_defaults[] __initconst = { 8162306a36Sopenharmony_ci { "jtag switching", RK3328_GRF_SOC_CON4, HIWORD_UPDATE(0, 1, 12) }, 8262306a36Sopenharmony_ci}; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistatic const struct rockchip_grf_info rk3328_grf __initconst = { 8562306a36Sopenharmony_ci .values = rk3328_defaults, 8662306a36Sopenharmony_ci .num_values = ARRAY_SIZE(rk3328_defaults), 8762306a36Sopenharmony_ci}; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci#define RK3368_GRF_SOC_CON15 0x43c 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic const struct rockchip_grf_value rk3368_defaults[] __initconst = { 9262306a36Sopenharmony_ci { "jtag switching", RK3368_GRF_SOC_CON15, HIWORD_UPDATE(0, 1, 13) }, 9362306a36Sopenharmony_ci}; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic const struct rockchip_grf_info rk3368_grf __initconst = { 9662306a36Sopenharmony_ci .values = rk3368_defaults, 9762306a36Sopenharmony_ci .num_values = ARRAY_SIZE(rk3368_defaults), 9862306a36Sopenharmony_ci}; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci#define RK3399_GRF_SOC_CON7 0xe21c 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic const struct rockchip_grf_value rk3399_defaults[] __initconst = { 10362306a36Sopenharmony_ci { "jtag switching", RK3399_GRF_SOC_CON7, HIWORD_UPDATE(0, 1, 12) }, 10462306a36Sopenharmony_ci}; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic const struct rockchip_grf_info rk3399_grf __initconst = { 10762306a36Sopenharmony_ci .values = rk3399_defaults, 10862306a36Sopenharmony_ci .num_values = ARRAY_SIZE(rk3399_defaults), 10962306a36Sopenharmony_ci}; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci#define RK3566_GRF_USB3OTG0_CON1 0x0104 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cistatic const struct rockchip_grf_value rk3566_defaults[] __initconst = { 11462306a36Sopenharmony_ci { "usb3otg port switch", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(0, 1, 12) }, 11562306a36Sopenharmony_ci { "usb3otg clock switch", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(1, 1, 7) }, 11662306a36Sopenharmony_ci { "usb3otg disable usb3", RK3566_GRF_USB3OTG0_CON1, HIWORD_UPDATE(1, 1, 0) }, 11762306a36Sopenharmony_ci}; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic const struct rockchip_grf_info rk3566_pipegrf __initconst = { 12062306a36Sopenharmony_ci .values = rk3566_defaults, 12162306a36Sopenharmony_ci .num_values = ARRAY_SIZE(rk3566_defaults), 12262306a36Sopenharmony_ci}; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci#define RK3588_GRF_SOC_CON6 0x0318 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistatic const struct rockchip_grf_value rk3588_defaults[] __initconst = { 12762306a36Sopenharmony_ci { "jtag switching", RK3588_GRF_SOC_CON6, HIWORD_UPDATE(0, 1, 14) }, 12862306a36Sopenharmony_ci}; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistatic const struct rockchip_grf_info rk3588_sysgrf __initconst = { 13162306a36Sopenharmony_ci .values = rk3588_defaults, 13262306a36Sopenharmony_ci .num_values = ARRAY_SIZE(rk3588_defaults), 13362306a36Sopenharmony_ci}; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic const struct of_device_id rockchip_grf_dt_match[] __initconst = { 13762306a36Sopenharmony_ci { 13862306a36Sopenharmony_ci .compatible = "rockchip,rk3036-grf", 13962306a36Sopenharmony_ci .data = (void *)&rk3036_grf, 14062306a36Sopenharmony_ci }, { 14162306a36Sopenharmony_ci .compatible = "rockchip,rk3128-grf", 14262306a36Sopenharmony_ci .data = (void *)&rk3128_grf, 14362306a36Sopenharmony_ci }, { 14462306a36Sopenharmony_ci .compatible = "rockchip,rk3228-grf", 14562306a36Sopenharmony_ci .data = (void *)&rk3228_grf, 14662306a36Sopenharmony_ci }, { 14762306a36Sopenharmony_ci .compatible = "rockchip,rk3288-grf", 14862306a36Sopenharmony_ci .data = (void *)&rk3288_grf, 14962306a36Sopenharmony_ci }, { 15062306a36Sopenharmony_ci .compatible = "rockchip,rk3328-grf", 15162306a36Sopenharmony_ci .data = (void *)&rk3328_grf, 15262306a36Sopenharmony_ci }, { 15362306a36Sopenharmony_ci .compatible = "rockchip,rk3368-grf", 15462306a36Sopenharmony_ci .data = (void *)&rk3368_grf, 15562306a36Sopenharmony_ci }, { 15662306a36Sopenharmony_ci .compatible = "rockchip,rk3399-grf", 15762306a36Sopenharmony_ci .data = (void *)&rk3399_grf, 15862306a36Sopenharmony_ci }, { 15962306a36Sopenharmony_ci .compatible = "rockchip,rk3566-pipe-grf", 16062306a36Sopenharmony_ci .data = (void *)&rk3566_pipegrf, 16162306a36Sopenharmony_ci }, { 16262306a36Sopenharmony_ci .compatible = "rockchip,rk3588-sys-grf", 16362306a36Sopenharmony_ci .data = (void *)&rk3588_sysgrf, 16462306a36Sopenharmony_ci }, 16562306a36Sopenharmony_ci { /* sentinel */ }, 16662306a36Sopenharmony_ci}; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic int __init rockchip_grf_init(void) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci const struct rockchip_grf_info *grf_info; 17162306a36Sopenharmony_ci const struct of_device_id *match; 17262306a36Sopenharmony_ci struct device_node *np; 17362306a36Sopenharmony_ci struct regmap *grf; 17462306a36Sopenharmony_ci int ret, i; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci np = of_find_matching_node_and_match(NULL, rockchip_grf_dt_match, 17762306a36Sopenharmony_ci &match); 17862306a36Sopenharmony_ci if (!np) 17962306a36Sopenharmony_ci return -ENODEV; 18062306a36Sopenharmony_ci if (!match || !match->data) { 18162306a36Sopenharmony_ci pr_err("%s: missing grf data\n", __func__); 18262306a36Sopenharmony_ci of_node_put(np); 18362306a36Sopenharmony_ci return -EINVAL; 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci grf_info = match->data; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci grf = syscon_node_to_regmap(np); 18962306a36Sopenharmony_ci of_node_put(np); 19062306a36Sopenharmony_ci if (IS_ERR(grf)) { 19162306a36Sopenharmony_ci pr_err("%s: could not get grf syscon\n", __func__); 19262306a36Sopenharmony_ci return PTR_ERR(grf); 19362306a36Sopenharmony_ci } 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci for (i = 0; i < grf_info->num_values; i++) { 19662306a36Sopenharmony_ci const struct rockchip_grf_value *val = &grf_info->values[i]; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci pr_debug("%s: adjusting %s in %#6x to %#10x\n", __func__, 19962306a36Sopenharmony_ci val->desc, val->reg, val->val); 20062306a36Sopenharmony_ci ret = regmap_write(grf, val->reg, val->val); 20162306a36Sopenharmony_ci if (ret < 0) 20262306a36Sopenharmony_ci pr_err("%s: write to %#6x failed with %d\n", 20362306a36Sopenharmony_ci __func__, val->reg, ret); 20462306a36Sopenharmony_ci } 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci return 0; 20762306a36Sopenharmony_ci} 20862306a36Sopenharmony_cipostcore_initcall(rockchip_grf_init); 209