platsmp.c (ecd740c6f2f092b90b95fa35f757973589eaaca2) | platsmp.c (06cc5c1d4d7313bc864e9aac1d1cbd63d8b9ca4c) |
---|---|
1/* 2 * Copyright (c) 2013 Linaro Ltd. 3 * Copyright (c) 2013 Hisilicon Limited. 4 * Based on arch/arm/mach-vexpress/platsmp.c, Copyright (C) 2002 ARM Ltd. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 */ 10#include <linux/smp.h> 11#include <linux/io.h> 12#include <linux/of_address.h> 13 14#include <asm/cacheflush.h> 15#include <asm/smp_plat.h> 16#include <asm/smp_scu.h> 17 18#include "core.h" 19 | 1/* 2 * Copyright (c) 2013 Linaro Ltd. 3 * Copyright (c) 2013 Hisilicon Limited. 4 * Based on arch/arm/mach-vexpress/platsmp.c, Copyright (C) 2002 ARM Ltd. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 */ 10#include <linux/smp.h> 11#include <linux/io.h> 12#include <linux/of_address.h> 13 14#include <asm/cacheflush.h> 15#include <asm/smp_plat.h> 16#include <asm/smp_scu.h> 17 18#include "core.h" 19 |
20#define HIX5HD2_BOOT_ADDRESS 0xffff0000 21 |
|
20static void __iomem *ctrl_base; 21 22void hi3xxx_set_cpu_jump(int cpu, void *jump_addr) 23{ 24 cpu = cpu_logical_map(cpu); 25 if (!cpu || !ctrl_base) 26 return; 27 writel_relaxed(virt_to_phys(jump_addr), ctrl_base + ((cpu - 1) << 2)); 28} 29 30int hi3xxx_get_cpu_jump(int cpu) 31{ 32 cpu = cpu_logical_map(cpu); 33 if (!cpu || !ctrl_base) 34 return 0; 35 return readl_relaxed(ctrl_base + ((cpu - 1) << 2)); 36} 37 | 22static void __iomem *ctrl_base; 23 24void hi3xxx_set_cpu_jump(int cpu, void *jump_addr) 25{ 26 cpu = cpu_logical_map(cpu); 27 if (!cpu || !ctrl_base) 28 return; 29 writel_relaxed(virt_to_phys(jump_addr), ctrl_base + ((cpu - 1) << 2)); 30} 31 32int hi3xxx_get_cpu_jump(int cpu) 33{ 34 cpu = cpu_logical_map(cpu); 35 if (!cpu || !ctrl_base) 36 return 0; 37 return readl_relaxed(ctrl_base + ((cpu - 1) << 2)); 38} 39 |
38static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus) | 40static void __init hisi_enable_scu_a9(void) |
39{ | 41{ |
40 struct device_node *np = NULL; | |
41 unsigned long base = 0; | 42 unsigned long base = 0; |
42 u32 offset = 0; | |
43 void __iomem *scu_base = NULL; 44 45 if (scu_a9_has_base()) { 46 base = scu_a9_get_base(); 47 scu_base = ioremap(base, SZ_4K); 48 if (!scu_base) { 49 pr_err("ioremap(scu_base) failed\n"); 50 return; 51 } 52 scu_enable(scu_base); 53 iounmap(scu_base); 54 } | 43 void __iomem *scu_base = NULL; 44 45 if (scu_a9_has_base()) { 46 base = scu_a9_get_base(); 47 scu_base = ioremap(base, SZ_4K); 48 if (!scu_base) { 49 pr_err("ioremap(scu_base) failed\n"); 50 return; 51 } 52 scu_enable(scu_base); 53 iounmap(scu_base); 54 } |
55} 56 57static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus) 58{ 59 struct device_node *np = NULL; 60 u32 offset = 0; 61 62 hisi_enable_scu_a9(); |
|
55 if (!ctrl_base) { 56 np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl"); 57 if (!np) { 58 pr_err("failed to find hisilicon,sysctrl node\n"); 59 return; 60 } 61 ctrl_base = of_iomap(np, 0); 62 if (!ctrl_base) { --- 19 unchanged lines hidden (view full) --- 82struct smp_operations hi3xxx_smp_ops __initdata = { 83 .smp_prepare_cpus = hi3xxx_smp_prepare_cpus, 84 .smp_boot_secondary = hi3xxx_boot_secondary, 85#ifdef CONFIG_HOTPLUG_CPU 86 .cpu_die = hi3xxx_cpu_die, 87 .cpu_kill = hi3xxx_cpu_kill, 88#endif 89}; | 63 if (!ctrl_base) { 64 np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl"); 65 if (!np) { 66 pr_err("failed to find hisilicon,sysctrl node\n"); 67 return; 68 } 69 ctrl_base = of_iomap(np, 0); 70 if (!ctrl_base) { --- 19 unchanged lines hidden (view full) --- 90struct smp_operations hi3xxx_smp_ops __initdata = { 91 .smp_prepare_cpus = hi3xxx_smp_prepare_cpus, 92 .smp_boot_secondary = hi3xxx_boot_secondary, 93#ifdef CONFIG_HOTPLUG_CPU 94 .cpu_die = hi3xxx_cpu_die, 95 .cpu_kill = hi3xxx_cpu_kill, 96#endif 97}; |
98 99static void __init hix5hd2_smp_prepare_cpus(unsigned int max_cpus) 100{ 101 hisi_enable_scu_a9(); 102} 103 104void hix5hd2_set_scu_boot_addr(phys_addr_t start_addr, phys_addr_t jump_addr) 105{ 106 void __iomem *virt; 107 108 virt = ioremap(start_addr, PAGE_SIZE); 109 110 writel_relaxed(0xe51ff004, virt); /* ldr pc, [rc, #-4] */ 111 writel_relaxed(jump_addr, virt + 4); /* pc jump phy address */ 112 iounmap(virt); 113} 114 115static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle) 116{ 117 phys_addr_t jumpaddr; 118 119 jumpaddr = virt_to_phys(hix5hd2_secondary_startup); 120 hix5hd2_set_scu_boot_addr(HIX5HD2_BOOT_ADDRESS, jumpaddr); 121 hix5hd2_set_cpu(cpu, true); 122 arch_send_wakeup_ipi_mask(cpumask_of(cpu)); 123 return 0; 124} 125 126 127struct smp_operations hix5hd2_smp_ops __initdata = { 128 .smp_prepare_cpus = hix5hd2_smp_prepare_cpus, 129 .smp_boot_secondary = hix5hd2_boot_secondary, 130#ifdef CONFIG_HOTPLUG_CPU 131 .cpu_die = hix5hd2_cpu_die, 132#endif 133}; |
|