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 (!src_base)
  47                return -ENODEV;
  48
  49        if (sw_reset_idx >= ARRAY_SIZE(sw_reset_bits))
  50                return -EINVAL;
  51
  52        bit = 1 << sw_reset_bits[sw_reset_idx];
  53
  54        spin_lock_irqsave(&scr_lock, flags);
  55        val = readl_relaxed(src_base + SRC_SCR);
  56        val |= bit;
  57        writel_relaxed(val, src_base + SRC_SCR);
  58        spin_unlock_irqrestore(&scr_lock, flags);
  59
  60        timeout = jiffies + msecs_to_jiffies(1000);
  61        while (readl(src_base + SRC_SCR) & bit) {
  62                if (time_after(jiffies, timeout))
  63                        return -ETIME;
  64                cpu_relax();
  65        }
  66
  67        return 0;
  68}
  69
  70static const struct reset_control_ops imx_src_ops = {
  71        .reset = imx_src_reset_module,
  72};
  73
  74static struct reset_controller_dev imx_reset_controller = {
  75        .ops = &imx_src_ops,
  76        .nr_resets = ARRAY_SIZE(sw_reset_bits),
  77};
  78
  79void imx_enable_cpu(int cpu, bool enable)
  80{
  81        u32 mask, val;
  82
  83        cpu = cpu_logical_map(cpu);
  84        mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
  85        spin_lock(&scr_lock);
  86        val = readl_relaxed(src_base + SRC_SCR);
  87        val = enable ? val | mask : val & ~mask;
  88        val |= 1 << (BP_SRC_SCR_CORE1_RST + cpu - 1);
  89        writel_relaxed(val, src_base + SRC_SCR);
  90        spin_unlock(&scr_lock);
  91}
  92
  93void imx_set_cpu_jump(int cpu, void *jump_addr)
  94{
  95        cpu = cpu_logical_map(cpu);
  96        writel_relaxed(__pa_symbol(jump_addr),
  97                       src_base + SRC_GPR1 + cpu * 8);
  98}
  99
 100u32 imx_get_cpu_arg(int cpu)
 101{
 102        cpu = cpu_logical_map(cpu);
 103        return readl_relaxed(src_base + SRC_GPR1 + cpu * 8 + 4);
 104}
 105
 106void imx_set_cpu_arg(int cpu, u32 arg)
 107{
 108        cpu = cpu_logical_map(cpu);
 109        writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4);
 110}
 111
 112void __init imx_src_init(void)
 113{
 114        struct device_node *np;
 115        u32 val;
 116
 117        np = of_find_compatible_node(NULL, NULL, "fsl,imx51-src");
 118        if (!np)
 119                return;
 120        src_base = of_iomap(np, 0);
 121        WARN_ON(!src_base);
 122
 123        imx_reset_controller.of_node = np;
 124        if (IS_ENABLED(CONFIG_RESET_CONTROLLER))
 125                reset_controller_register(&imx_reset_controller);
 126
 127        /*
 128         * force warm reset sources to generate cold reset
 129         * for a more reliable restart
 130         */
 131        spin_lock(&scr_lock);
 132        val = readl_relaxed(src_base + SRC_SCR);
 133        val &= ~(1 << BP_SRC_SCR_WARM_RESET_ENABLE);
 134        writel_relaxed(val, src_base + SRC_SCR);
 135        spin_unlock(&scr_lock);
 136}
 137