mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-15 15:04:27 +08:00
fcaf20360a
Based on 1 normalized pattern(s): the code contained herein is licensed under the gnu general public license you may obtain a copy of the gnu general public license version 2 or later at the following locations http www opensource org licenses gpl license html http www gnu org copyleft gpl html extracted by the scancode license scanner the SPDX license identifier GPL-2.0-or-later has been chosen to replace the boilerplate/reference in 161 file(s). Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Richard Fontana <rfontana@redhat.com> Reviewed-by: Allison Randal <allison@lohutok.net> Reviewed-by: Kate Stewart <kstewart@linuxfoundation.org> Cc: linux-spdx@vger.kernel.org Link: https://lkml.kernel.org/r/20190527070033.383790741@linutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
137 lines
3.1 KiB
C
137 lines
3.1 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Copyright 2011 Freescale Semiconductor, Inc.
|
|
* Copyright 2011 Linaro Ltd.
|
|
*/
|
|
|
|
#include <linux/init.h>
|
|
#include <linux/io.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/reset-controller.h>
|
|
#include <linux/smp.h>
|
|
#include <asm/smp_plat.h>
|
|
#include "common.h"
|
|
|
|
#define SRC_SCR 0x000
|
|
#define SRC_GPR1 0x020
|
|
#define BP_SRC_SCR_WARM_RESET_ENABLE 0
|
|
#define BP_SRC_SCR_SW_GPU_RST 1
|
|
#define BP_SRC_SCR_SW_VPU_RST 2
|
|
#define BP_SRC_SCR_SW_IPU1_RST 3
|
|
#define BP_SRC_SCR_SW_OPEN_VG_RST 4
|
|
#define BP_SRC_SCR_SW_IPU2_RST 12
|
|
#define BP_SRC_SCR_CORE1_RST 14
|
|
#define BP_SRC_SCR_CORE1_ENABLE 22
|
|
|
|
static void __iomem *src_base;
|
|
static DEFINE_SPINLOCK(scr_lock);
|
|
|
|
static const int sw_reset_bits[5] = {
|
|
BP_SRC_SCR_SW_GPU_RST,
|
|
BP_SRC_SCR_SW_VPU_RST,
|
|
BP_SRC_SCR_SW_IPU1_RST,
|
|
BP_SRC_SCR_SW_OPEN_VG_RST,
|
|
BP_SRC_SCR_SW_IPU2_RST
|
|
};
|
|
|
|
static int imx_src_reset_module(struct reset_controller_dev *rcdev,
|
|
unsigned long sw_reset_idx)
|
|
{
|
|
unsigned long timeout;
|
|
unsigned long flags;
|
|
int bit;
|
|
u32 val;
|
|
|
|
if (!src_base)
|
|
return -ENODEV;
|
|
|
|
if (sw_reset_idx >= ARRAY_SIZE(sw_reset_bits))
|
|
return -EINVAL;
|
|
|
|
bit = 1 << sw_reset_bits[sw_reset_idx];
|
|
|
|
spin_lock_irqsave(&scr_lock, flags);
|
|
val = readl_relaxed(src_base + SRC_SCR);
|
|
val |= bit;
|
|
writel_relaxed(val, src_base + SRC_SCR);
|
|
spin_unlock_irqrestore(&scr_lock, flags);
|
|
|
|
timeout = jiffies + msecs_to_jiffies(1000);
|
|
while (readl(src_base + SRC_SCR) & bit) {
|
|
if (time_after(jiffies, timeout))
|
|
return -ETIME;
|
|
cpu_relax();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct reset_control_ops imx_src_ops = {
|
|
.reset = imx_src_reset_module,
|
|
};
|
|
|
|
static struct reset_controller_dev imx_reset_controller = {
|
|
.ops = &imx_src_ops,
|
|
.nr_resets = ARRAY_SIZE(sw_reset_bits),
|
|
};
|
|
|
|
void imx_enable_cpu(int cpu, bool enable)
|
|
{
|
|
u32 mask, val;
|
|
|
|
cpu = cpu_logical_map(cpu);
|
|
mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
|
|
spin_lock(&scr_lock);
|
|
val = readl_relaxed(src_base + SRC_SCR);
|
|
val = enable ? val | mask : val & ~mask;
|
|
val |= 1 << (BP_SRC_SCR_CORE1_RST + cpu - 1);
|
|
writel_relaxed(val, src_base + SRC_SCR);
|
|
spin_unlock(&scr_lock);
|
|
}
|
|
|
|
void imx_set_cpu_jump(int cpu, void *jump_addr)
|
|
{
|
|
cpu = cpu_logical_map(cpu);
|
|
writel_relaxed(__pa_symbol(jump_addr),
|
|
src_base + SRC_GPR1 + cpu * 8);
|
|
}
|
|
|
|
u32 imx_get_cpu_arg(int cpu)
|
|
{
|
|
cpu = cpu_logical_map(cpu);
|
|
return readl_relaxed(src_base + SRC_GPR1 + cpu * 8 + 4);
|
|
}
|
|
|
|
void imx_set_cpu_arg(int cpu, u32 arg)
|
|
{
|
|
cpu = cpu_logical_map(cpu);
|
|
writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4);
|
|
}
|
|
|
|
void __init imx_src_init(void)
|
|
{
|
|
struct device_node *np;
|
|
u32 val;
|
|
|
|
np = of_find_compatible_node(NULL, NULL, "fsl,imx51-src");
|
|
if (!np)
|
|
return;
|
|
src_base = of_iomap(np, 0);
|
|
WARN_ON(!src_base);
|
|
|
|
imx_reset_controller.of_node = np;
|
|
if (IS_ENABLED(CONFIG_RESET_CONTROLLER))
|
|
reset_controller_register(&imx_reset_controller);
|
|
|
|
/*
|
|
* force warm reset sources to generate cold reset
|
|
* for a more reliable restart
|
|
*/
|
|
spin_lock(&scr_lock);
|
|
val = readl_relaxed(src_base + SRC_SCR);
|
|
val &= ~(1 << BP_SRC_SCR_WARM_RESET_ENABLE);
|
|
writel_relaxed(val, src_base + SRC_SCR);
|
|
spin_unlock(&scr_lock);
|
|
}
|