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 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(virt_to_phys(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