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 const 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        val |= 1 << (BP_SRC_SCR_CORE1_RST + cpu - 1);
  95        writel_relaxed(val, src_base + SRC_SCR);
  96        spin_unlock(&scr_lock);
  97}
  98
  99void imx_set_cpu_jump(int cpu, void *jump_addr)
 100{
 101        cpu = cpu_logical_map(cpu);
 102        writel_relaxed(__pa_symbol(jump_addr),
 103                       src_base + SRC_GPR1 + cpu * 8);
 104}
 105
 106u32 imx_get_cpu_arg(int cpu)
 107{
 108        cpu = cpu_logical_map(cpu);
 109        return readl_relaxed(src_base + SRC_GPR1 + cpu * 8 + 4);
 110}
 111
 112void imx_set_cpu_arg(int cpu, u32 arg)
 113{
 114        cpu = cpu_logical_map(cpu);
 115        writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4);
 116}
 117
 118void __init imx_src_init(void)
 119{
 120        struct device_node *np;
 121        u32 val;
 122
 123        np = of_find_compatible_node(NULL, NULL, "fsl,imx51-src");
 124        if (!np)
 125                return;
 126        src_base = of_iomap(np, 0);
 127        WARN_ON(!src_base);
 128
 129        imx_reset_controller.of_node = np;
 130        if (IS_ENABLED(CONFIG_RESET_CONTROLLER))
 131                reset_controller_register(&imx_reset_controller);
 132
 133        /*
 134         * force warm reset sources to generate cold reset
 135         * for a more reliable restart
 136         */
 137        spin_lock(&scr_lock);
 138        val = readl_relaxed(src_base + SRC_SCR);
 139        val &= ~(1 << BP_SRC_SCR_WARM_RESET_ENABLE);
 140        writel_relaxed(val, src_base + SRC_SCR);
 141        spin_unlock(&scr_lock);
 142}
 143