linux/arch/arm/mach-imx/src.c
<<
>>
Prefs
   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);
 239