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/of.h>
  10#include <linux/of_address.h>
  11#include <linux/reset-controller.h>
  12#include <linux/smp.h>
  13#include <asm/smp_plat.h>
  14#include "common.h"
  15
  16#define SRC_SCR                         0x000
  17#define SRC_GPR1                        0x020
  18#define BP_SRC_SCR_WARM_RESET_ENABLE    0
  19#define BP_SRC_SCR_SW_GPU_RST           1
  20#define BP_SRC_SCR_SW_VPU_RST           2
  21#define BP_SRC_SCR_SW_IPU1_RST          3
  22#define BP_SRC_SCR_SW_OPEN_VG_RST       4
  23#define BP_SRC_SCR_SW_IPU2_RST          12
  24#define BP_SRC_SCR_CORE1_RST            14
  25#define BP_SRC_SCR_CORE1_ENABLE         22
  26
  27static void __iomem *src_base;
  28static DEFINE_SPINLOCK(scr_lock);
  29
  30static const int sw_reset_bits[5] = {
  31        BP_SRC_SCR_SW_GPU_RST,
  32        BP_SRC_SCR_SW_VPU_RST,
  33        BP_SRC_SCR_SW_IPU1_RST,
  34        BP_SRC_SCR_SW_OPEN_VG_RST,
  35        BP_SRC_SCR_SW_IPU2_RST
  36};
  37
  38static int imx_src_reset_module(struct reset_controller_dev *rcdev,
  39                unsigned long sw_reset_idx)
  40{
  41        unsigned long timeout;
  42        unsigned long flags;
  43        int bit;
  44        u32 val;
  45
  46        if (sw_reset_idx >= ARRAY_SIZE(sw_reset_bits))
  47                return -EINVAL;
  48
  49        bit = 1 << sw_reset_bits[sw_reset_idx];
  50
  51        spin_lock_irqsave(&scr_lock, flags);
  52        val = readl_relaxed(src_base + SRC_SCR);
  53        val |= bit;
  54        writel_relaxed(val, src_base + SRC_SCR);
  55        spin_unlock_irqrestore(&scr_lock, flags);
  56
  57        timeout = jiffies + msecs_to_jiffies(1000);
  58        while (readl(src_base + SRC_SCR) & bit) {
  59                if (time_after(jiffies, timeout))
  60                        return -ETIME;
  61                cpu_relax();
  62        }
  63
  64        return 0;
  65}
  66
  67static const struct reset_control_ops imx_src_ops = {
  68        .reset = imx_src_reset_module,
  69};
  70
  71static struct reset_controller_dev imx_reset_controller = {
  72        .ops = &imx_src_ops,
  73        .nr_resets = ARRAY_SIZE(sw_reset_bits),
  74};
  75
  76void imx_enable_cpu(int cpu, bool enable)
  77{
  78        u32 mask, val;
  79
  80        cpu = cpu_logical_map(cpu);
  81        mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
  82        spin_lock(&scr_lock);
  83        val = readl_relaxed(src_base + SRC_SCR);
  84        val = enable ? val | mask : val & ~mask;
  85        val |= 1 << (BP_SRC_SCR_CORE1_RST + cpu - 1);
  86        writel_relaxed(val, src_base + SRC_SCR);
  87        spin_unlock(&scr_lock);
  88}
  89
  90void imx_set_cpu_jump(int cpu, void *jump_addr)
  91{
  92        cpu = cpu_logical_map(cpu);
  93        writel_relaxed(__pa_symbol(jump_addr),
  94                       src_base + SRC_GPR1 + cpu * 8);
  95}
  96
  97u32 imx_get_cpu_arg(int cpu)
  98{
  99        cpu = cpu_logical_map(cpu);
 100        return readl_relaxed(src_base + SRC_GPR1 + cpu * 8 + 4);
 101}
 102
 103void imx_set_cpu_arg(int cpu, u32 arg)
 104{
 105        cpu = cpu_logical_map(cpu);
 106        writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4);
 107}
 108
 109void __init imx_src_init(void)
 110{
 111        struct device_node *np;
 112        u32 val;
 113
 114        np = of_find_compatible_node(NULL, NULL, "fsl,imx51-src");
 115        if (!np)
 116                return;
 117        src_base = of_iomap(np, 0);
 118        WARN_ON(!src_base);
 119
 120        imx_reset_controller.of_node = np;
 121        if (IS_ENABLED(CONFIG_RESET_CONTROLLER))
 122                reset_controller_register(&imx_reset_controller);
 123
 124        /*
 125         * force warm reset sources to generate cold reset
 126         * for a more reliable restart
 127         */
 128        spin_lock(&scr_lock);
 129        val = readl_relaxed(src_base + SRC_SCR);
 130        val &= ~(1 << BP_SRC_SCR_WARM_RESET_ENABLE);
 131        writel_relaxed(val, src_base + SRC_SCR);
 132        spin_unlock(&scr_lock);
 133}
 134