linux/arch/arm/mach-imx/src.c
<<
>>
Prefs
   1/*
   2 * Copyright 2011 Freescale Semiconductor, Inc.
   3 * Copyright 2011 Linaro Ltd.
   4 *
   5 * The code contained herein is licensed under the GNU General Public
   6 * License. You may obtain a copy of the GNU General Public License
   7 * Version 2 or later at the following locations:
   8 *
   9 * http://www.opensource.org/licenses/gpl-license.html
  10 * http://www.gnu.org/copyleft/gpl.html
  11 */
  12
  13#include <linux/init.h>
  14#include <linux/io.h>
  15#include <linux/of.h>
  16#include <linux/of_address.h>
  17#include <linux/reset-controller.h>
  18#include <linux/smp.h>
  19#include <asm/smp_plat.h>
  20#include "common.h"
  21
  22#define SRC_SCR                         0x000
  23#define SRC_GPR1                        0x020
  24#define BP_SRC_SCR_WARM_RESET_ENABLE    0
  25#define BP_SRC_SCR_SW_GPU_RST           1
  26#define BP_SRC_SCR_SW_VPU_RST           2
  27#define BP_SRC_SCR_SW_IPU1_RST          3
  28#define BP_SRC_SCR_SW_OPEN_VG_RST       4
  29#define BP_SRC_SCR_SW_IPU2_RST          12
  30#define BP_SRC_SCR_CORE1_RST            14
  31#define BP_SRC_SCR_CORE1_ENABLE         22
  32
  33static void __iomem *src_base;
  34static DEFINE_SPINLOCK(scr_lock);
  35
  36static const int sw_reset_bits[5] = {
  37        BP_SRC_SCR_SW_GPU_RST,
  38        BP_SRC_SCR_SW_VPU_RST,
  39        BP_SRC_SCR_SW_IPU1_RST,
  40        BP_SRC_SCR_SW_OPEN_VG_RST,
  41        BP_SRC_SCR_SW_IPU2_RST
  42};
  43
  44static int imx_src_reset_module(struct reset_controller_dev *rcdev,
  45                unsigned long sw_reset_idx)
  46{
  47        unsigned long timeout;
  48        unsigned long flags;
  49        int bit;
  50        u32 val;
  51
  52        if (!src_base)
  53                return -ENODEV;
  54
  55        if (sw_reset_idx >= ARRAY_SIZE(sw_reset_bits))
  56                return -EINVAL;
  57
  58        bit = 1 << sw_reset_bits[sw_reset_idx];
  59
  60        spin_lock_irqsave(&scr_lock, flags);
  61        val = readl_relaxed(src_base + SRC_SCR);
  62        val |= bit;
  63        writel_relaxed(val, src_base + SRC_SCR);
  64        spin_unlock_irqrestore(&scr_lock, flags);
  65
  66        timeout = jiffies + msecs_to_jiffies(1000);
  67        while (readl(src_base + SRC_SCR) & bit) {
  68                if (time_after(jiffies, timeout))
  69                        return -ETIME;
  70                cpu_relax();
  71        }
  72
  73        return 0;
  74}
  75
  76static struct reset_control_ops imx_src_ops = {
  77        .reset = imx_src_reset_module,
  78};
  79
  80static struct reset_controller_dev imx_reset_controller = {
  81        .ops = &imx_src_ops,
  82        .nr_resets = ARRAY_SIZE(sw_reset_bits),
  83};
  84
  85void imx_enable_cpu(int cpu, bool enable)
  86{
  87        u32 mask, val;
  88
  89        cpu = cpu_logical_map(cpu);
  90        mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
  91        spin_lock(&scr_lock);
  92        val = readl_relaxed(src_base + SRC_SCR);
  93        val = enable ? val | mask : val & ~mask;
  94        writel_relaxed(val, src_base + SRC_SCR);
  95        spin_unlock(&scr_lock);
  96}
  97
  98void imx_set_cpu_jump(int cpu, void *jump_addr)
  99{
 100        cpu = cpu_logical_map(cpu);
 101        writel_relaxed(virt_to_phys(jump_addr),
 102                       src_base + SRC_GPR1 + cpu * 8);
 103}
 104
 105u32 imx_get_cpu_arg(int cpu)
 106{
 107        cpu = cpu_logical_map(cpu);
 108        return readl_relaxed(src_base + SRC_GPR1 + cpu * 8 + 4);
 109}
 110
 111void imx_set_cpu_arg(int cpu, u32 arg)
 112{
 113        cpu = cpu_logical_map(cpu);
 114        writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4);
 115}
 116
 117void imx_src_prepare_restart(void)
 118{
 119        u32 val;
 120
 121        /* clear enable bits of secondary cores */
 122        spin_lock(&scr_lock);
 123        val = readl_relaxed(src_base + SRC_SCR);
 124        val &= ~(0x7 << BP_SRC_SCR_CORE1_ENABLE);
 125        writel_relaxed(val, src_base + SRC_SCR);
 126        spin_unlock(&scr_lock);
 127
 128        /* clear persistent entry register of primary core */
 129        writel_relaxed(0, src_base + SRC_GPR1);
 130}
 131
 132void __init imx_src_init(void)
 133{
 134        struct device_node *np;
 135        u32 val;
 136
 137        np = of_find_compatible_node(NULL, NULL, "fsl,imx51-src");
 138        if (!np)
 139                return;
 140        src_base = of_iomap(np, 0);
 141        WARN_ON(!src_base);
 142
 143        imx_reset_controller.of_node = np;
 144        if (IS_ENABLED(CONFIG_RESET_CONTROLLER))
 145                reset_controller_register(&imx_reset_controller);
 146
 147        /*
 148         * force warm reset sources to generate cold reset
 149         * for a more reliable restart
 150         */
 151        spin_lock(&scr_lock);
 152        val = readl_relaxed(src_base + SRC_SCR);
 153        val &= ~(1 << BP_SRC_SCR_WARM_RESET_ENABLE);
 154        writel_relaxed(val, src_base + SRC_SCR);
 155        spin_unlock(&scr_lock);
 156}
 157