src.c (5964B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright 2011 Freescale Semiconductor, Inc. 4 * Copyright 2011 Linaro Ltd. 5 */ 6 7#include <linux/init.h> 8#include <linux/io.h> 9#include <linux/iopoll.h> 10#include <linux/of.h> 11#include <linux/of_address.h> 12#include <linux/platform_device.h> 13#include <linux/reset-controller.h> 14#include <linux/smp.h> 15#include <asm/smp_plat.h> 16#include "common.h" 17#include "hardware.h" 18 19#define SRC_SCR 0x000 20#define SRC_GPR1_V1 0x020 21#define SRC_GPR1_V2 0x074 22#define SRC_GPR1(gpr_v2) ((gpr_v2) ? SRC_GPR1_V2 : SRC_GPR1_V1) 23#define BP_SRC_SCR_WARM_RESET_ENABLE 0 24#define BP_SRC_SCR_SW_GPU_RST 1 25#define BP_SRC_SCR_SW_VPU_RST 2 26#define BP_SRC_SCR_SW_IPU1_RST 3 27#define BP_SRC_SCR_SW_OPEN_VG_RST 4 28#define BP_SRC_SCR_SW_IPU2_RST 12 29#define BP_SRC_SCR_CORE1_RST 14 30#define BP_SRC_SCR_CORE1_ENABLE 22 31/* below is for i.MX7D */ 32#define SRC_A7RCR1 0x008 33#define BP_SRC_A7RCR1_A7_CORE1_ENABLE 1 34#define GPC_CPU_PGC_SW_PUP_REQ 0xf0 35#define GPC_CPU_PGC_SW_PDN_REQ 0xfc 36#define GPC_PGC_C1 0x840 37#define BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7 0x2 38 39static void __iomem *src_base; 40static DEFINE_SPINLOCK(scr_lock); 41static bool gpr_v2; 42static void __iomem *gpc_base; 43 44static const int sw_reset_bits[5] = { 45 BP_SRC_SCR_SW_GPU_RST, 46 BP_SRC_SCR_SW_VPU_RST, 47 BP_SRC_SCR_SW_IPU1_RST, 48 BP_SRC_SCR_SW_OPEN_VG_RST, 49 BP_SRC_SCR_SW_IPU2_RST 50}; 51 52static int imx_src_reset_module(struct reset_controller_dev *rcdev, 53 unsigned long sw_reset_idx) 54{ 55 unsigned long timeout; 56 unsigned long flags; 57 int bit; 58 u32 val; 59 60 if (sw_reset_idx >= ARRAY_SIZE(sw_reset_bits)) 61 return -EINVAL; 62 63 bit = 1 << sw_reset_bits[sw_reset_idx]; 64 65 spin_lock_irqsave(&scr_lock, flags); 66 val = readl_relaxed(src_base + SRC_SCR); 67 val |= bit; 68 writel_relaxed(val, src_base + SRC_SCR); 69 spin_unlock_irqrestore(&scr_lock, flags); 70 71 timeout = jiffies + msecs_to_jiffies(1000); 72 while (readl(src_base + SRC_SCR) & bit) { 73 if (time_after(jiffies, timeout)) 74 return -ETIME; 75 cpu_relax(); 76 } 77 78 return 0; 79} 80 81static const struct reset_control_ops imx_src_ops = { 82 .reset = imx_src_reset_module, 83}; 84 85static void imx_gpcv2_set_m_core_pgc(bool enable, u32 offset) 86{ 87 writel_relaxed(enable, gpc_base + offset); 88} 89 90/* 91 * The motivation for bringing up the second i.MX7D core inside the kernel 92 * is that legacy vendor bootloaders usually do not implement PSCI support. 93 * This is a significant blocker for systems in the field that are running old 94 * bootloader versions to upgrade to a modern mainline kernel version, as only 95 * one CPU of the i.MX7D would be brought up. 96 * Bring up the second i.MX7D core inside the kernel to make the migration 97 * path to mainline kernel easier for the existing iMX7D users. 98 */ 99void imx_gpcv2_set_core1_pdn_pup_by_software(bool pdn) 100{ 101 u32 reg = pdn ? GPC_CPU_PGC_SW_PDN_REQ : GPC_CPU_PGC_SW_PUP_REQ; 102 u32 val, pup; 103 int ret; 104 105 imx_gpcv2_set_m_core_pgc(true, GPC_PGC_C1); 106 val = readl_relaxed(gpc_base + reg); 107 val |= BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7; 108 writel_relaxed(val, gpc_base + reg); 109 110 ret = readl_relaxed_poll_timeout_atomic(gpc_base + reg, pup, 111 !(pup & BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7), 112 5, 1000000); 113 if (ret < 0) { 114 pr_err("i.MX7D: CORE1_A7 power up timeout\n"); 115 val &= ~BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7; 116 writel_relaxed(val, gpc_base + reg); 117 } 118 119 imx_gpcv2_set_m_core_pgc(false, GPC_PGC_C1); 120} 121 122void imx_enable_cpu(int cpu, bool enable) 123{ 124 u32 mask, val; 125 126 cpu = cpu_logical_map(cpu); 127 spin_lock(&scr_lock); 128 if (gpr_v2) { 129 if (enable) 130 imx_gpcv2_set_core1_pdn_pup_by_software(false); 131 132 mask = 1 << (BP_SRC_A7RCR1_A7_CORE1_ENABLE + cpu - 1); 133 val = readl_relaxed(src_base + SRC_A7RCR1); 134 val = enable ? val | mask : val & ~mask; 135 writel_relaxed(val, src_base + SRC_A7RCR1); 136 } else { 137 mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1); 138 val = readl_relaxed(src_base + SRC_SCR); 139 val = enable ? val | mask : val & ~mask; 140 val |= 1 << (BP_SRC_SCR_CORE1_RST + cpu - 1); 141 writel_relaxed(val, src_base + SRC_SCR); 142 } 143 spin_unlock(&scr_lock); 144} 145 146void imx_set_cpu_jump(int cpu, void *jump_addr) 147{ 148 cpu = cpu_logical_map(cpu); 149 writel_relaxed(__pa_symbol(jump_addr), 150 src_base + SRC_GPR1(gpr_v2) + cpu * 8); 151} 152 153u32 imx_get_cpu_arg(int cpu) 154{ 155 cpu = cpu_logical_map(cpu); 156 return readl_relaxed(src_base + SRC_GPR1(gpr_v2) + cpu * 8 + 4); 157} 158 159void imx_set_cpu_arg(int cpu, u32 arg) 160{ 161 cpu = cpu_logical_map(cpu); 162 writel_relaxed(arg, src_base + SRC_GPR1(gpr_v2) + cpu * 8 + 4); 163} 164 165void __init imx_src_init(void) 166{ 167 struct device_node *np; 168 u32 val; 169 170 np = of_find_compatible_node(NULL, NULL, "fsl,imx51-src"); 171 if (!np) 172 return; 173 src_base = of_iomap(np, 0); 174 WARN_ON(!src_base); 175 176 /* 177 * force warm reset sources to generate cold reset 178 * for a more reliable restart 179 */ 180 spin_lock(&scr_lock); 181 val = readl_relaxed(src_base + SRC_SCR); 182 val &= ~(1 << BP_SRC_SCR_WARM_RESET_ENABLE); 183 writel_relaxed(val, src_base + SRC_SCR); 184 spin_unlock(&scr_lock); 185} 186 187void __init imx7_src_init(void) 188{ 189 struct device_node *np; 190 191 gpr_v2 = true; 192 193 np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-src"); 194 if (!np) 195 return; 196 197 src_base = of_iomap(np, 0); 198 if (!src_base) 199 return; 200 201 np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-gpc"); 202 if (!np) 203 return; 204 205 gpc_base = of_iomap(np, 0); 206 if (!gpc_base) 207 return; 208} 209 210static const struct of_device_id imx_src_dt_ids[] = { 211 { .compatible = "fsl,imx51-src" }, 212 { /* sentinel */ } 213}; 214 215static int imx_src_probe(struct platform_device *pdev) 216{ 217 struct reset_controller_dev *rcdev; 218 219 rcdev = devm_kzalloc(&pdev->dev, sizeof(*rcdev), GFP_KERNEL); 220 if (!rcdev) 221 return -ENOMEM; 222 223 rcdev->ops = &imx_src_ops; 224 rcdev->dev = &pdev->dev; 225 rcdev->of_node = pdev->dev.of_node; 226 rcdev->nr_resets = ARRAY_SIZE(sw_reset_bits); 227 228 return devm_reset_controller_register(&pdev->dev, rcdev); 229} 230 231static struct platform_driver imx_src_driver = { 232 .driver = { 233 .name = "imx-src", 234 .of_match_table = imx_src_dt_ids, 235 }, 236 .probe = imx_src_probe, 237}; 238builtin_platform_driver(imx_src_driver);