Skip to content

Commit 06cc5c1

Browse files
windyanolofj
authored andcommitted
ARM: hisi: enable hix5hd2 SoC
Enable support for the Hisilicon HiX5HD2 SoC. This HiX5HD2 SoC series support both single and dual Cortex-A9 cores. Add ARCH_HIX5HD2 to distinguish HiX5HD2 from Hi3xxx. They are different in implementation such as SMP, IPs integarted and earlycon configure. Signed-off-by: Haifeng Yan <[email protected]> Signed-off-by: Jiancheng Xue <[email protected]> Signed-off-by: Haojian Zhuang <[email protected]> Acked-by: Wei Xu <[email protected]> Signed-off-by: Olof Johansson <[email protected]>
1 parent 7685b12 commit 06cc5c1

File tree

8 files changed

+161
-6
lines changed

8 files changed

+161
-6
lines changed

Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ Example:
3131
reboot-offset = <0x4>;
3232
};
3333

34+
-----------------------------------------------------------------------
35+
Hisilicon CPU controller
36+
37+
Required properties:
38+
- compatible : "hisilicon,cpuctrl"
39+
- reg : Register address and size
40+
41+
The clock registers and power registers of secondary cores are defined
42+
in CPU controller, especially in HIX5HD2 SoC.
43+
44+
-----------------------------------------------------------------------
3445
PCTRL: Peripheral misc control register
3546

3647
Required Properties:

arch/arm/mach-hisi/Kconfig

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,24 @@ if ARCH_HISI
1010
menu "Hisilicon platform type"
1111

1212
config ARCH_HI3xxx
13-
bool "Hisilicon Hi36xx/Hi37xx family" if ARCH_MULTI_V7
13+
bool "Hisilicon Hi36xx family" if ARCH_MULTI_V7
1414
select CACHE_L2X0
1515
select HAVE_ARM_SCU if SMP
1616
select HAVE_ARM_TWD if SMP
1717
select PINCTRL
1818
select PINCTRL_SINGLE
1919
help
20-
Support for Hisilicon Hi36xx/Hi37xx processor family
20+
Support for Hisilicon Hi36xx SoC family
2121

22+
config ARCH_HIX5HD2
23+
bool "Hisilicon X5HD2 family" if ARCH_MULTI_V7
24+
select CACHE_L2X0
25+
select HAVE_ARM_SCU if SMP
26+
select HAVE_ARM_TWD if SMP
27+
select PINCTRL
28+
select PINCTRL_SINGLE
29+
help
30+
Support for Hisilicon HIX5HD2 SoC family
2231
endmenu
2332

2433
endif

arch/arm/mach-hisi/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
#
44

55
obj-y += hisilicon.o
6-
obj-$(CONFIG_SMP) += platsmp.o hotplug.o
6+
obj-$(CONFIG_SMP) += platsmp.o hotplug.o headsmp.o

arch/arm/mach-hisi/core.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,9 @@ extern void hi3xxx_cpu_die(unsigned int cpu);
1212
extern int hi3xxx_cpu_kill(unsigned int cpu);
1313
extern void hi3xxx_set_cpu(int cpu, bool enable);
1414

15+
extern void hix5hd2_secondary_startup(void);
16+
extern struct smp_operations hix5hd2_smp_ops;
17+
extern void hix5hd2_set_cpu(int cpu, bool enable);
18+
extern void hix5hd2_cpu_die(unsigned int cpu);
19+
1520
#endif

arch/arm/mach-hisi/headsmp.S

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* Copyright (c) 2014 Hisilicon Limited.
3+
* Copyright (c) 2014 Linaro Ltd.
4+
*
5+
* This program is free software; you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License version 2 as
7+
* published by the Free Software Foundation.
8+
*/
9+
#include <linux/linkage.h>
10+
#include <linux/init.h>
11+
12+
__CPUINIT
13+
14+
ENTRY(hix5hd2_secondary_startup)
15+
bl v7_invalidate_l1
16+
b secondary_startup

arch/arm/mach-hisi/hisilicon.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,15 @@ DT_MACHINE_START(HI3620, "Hisilicon Hi3620 (Flattened Device Tree)")
8888
.smp = smp_ops(hi3xxx_smp_ops),
8989
.restart = hi3xxx_restart,
9090
MACHINE_END
91+
92+
static const char *hix5hd2_compat[] __initconst = {
93+
"hisilicon,hix5hd2",
94+
NULL,
95+
};
96+
97+
DT_MACHINE_START(HIX5HD2_DT, "Hisilicon HIX5HD2 (Flattened Device Tree)")
98+
.dt_compat = hix5hd2_compat,
99+
.init_late = hi3xxx_init_late,
100+
.smp = smp_ops(hix5hd2_smp_ops),
101+
.restart = hi3xxx_restart,
102+
MACHINE_END

arch/arm/mach-hisi/hotplug.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@
5757
#define CPU0_NEON_SRST_REQ_EN (1 << 4)
5858
#define CPU0_SRST_REQ_EN (1 << 0)
5959

60+
#define HIX5HD2_PERI_CRG20 0x50
61+
#define CRG20_CPU1_RESET (1 << 17)
62+
63+
#define HIX5HD2_PERI_PMC0 0x1000
64+
#define PMC0_CPU1_WAIT_MTCOMS_ACK (1 << 8)
65+
#define PMC0_CPU1_PMC_ENABLE (1 << 7)
66+
#define PMC0_CPU1_POWERDOWN (1 << 3)
67+
6068
enum {
6169
HI3620_CTRL,
6270
ERROR_CTRL,
@@ -157,6 +165,50 @@ void hi3xxx_set_cpu(int cpu, bool enable)
157165
set_cpu_hi3620(cpu, enable);
158166
}
159167

168+
static bool hix5hd2_hotplug_init(void)
169+
{
170+
struct device_node *np;
171+
172+
np = of_find_compatible_node(NULL, NULL, "hisilicon,cpuctrl");
173+
if (np) {
174+
ctrl_base = of_iomap(np, 0);
175+
return true;
176+
}
177+
return false;
178+
}
179+
180+
void hix5hd2_set_cpu(int cpu, bool enable)
181+
{
182+
u32 val = 0;
183+
184+
if (!ctrl_base)
185+
if (!hix5hd2_hotplug_init())
186+
BUG();
187+
188+
if (enable) {
189+
/* power on cpu1 */
190+
val = readl_relaxed(ctrl_base + HIX5HD2_PERI_PMC0);
191+
val &= ~(PMC0_CPU1_WAIT_MTCOMS_ACK | PMC0_CPU1_POWERDOWN);
192+
val |= PMC0_CPU1_PMC_ENABLE;
193+
writel_relaxed(val, ctrl_base + HIX5HD2_PERI_PMC0);
194+
/* unreset */
195+
val = readl_relaxed(ctrl_base + HIX5HD2_PERI_CRG20);
196+
val &= ~CRG20_CPU1_RESET;
197+
writel_relaxed(val, ctrl_base + HIX5HD2_PERI_CRG20);
198+
} else {
199+
/* power down cpu1 */
200+
val = readl_relaxed(ctrl_base + HIX5HD2_PERI_PMC0);
201+
val |= PMC0_CPU1_PMC_ENABLE | PMC0_CPU1_POWERDOWN;
202+
val &= ~PMC0_CPU1_WAIT_MTCOMS_ACK;
203+
writel_relaxed(val, ctrl_base + HIX5HD2_PERI_PMC0);
204+
205+
/* reset */
206+
val = readl_relaxed(ctrl_base + HIX5HD2_PERI_CRG20);
207+
val |= CRG20_CPU1_RESET;
208+
writel_relaxed(val, ctrl_base + HIX5HD2_PERI_CRG20);
209+
}
210+
}
211+
160212
static inline void cpu_enter_lowpower(void)
161213
{
162214
unsigned int v;
@@ -199,4 +251,10 @@ int hi3xxx_cpu_kill(unsigned int cpu)
199251
hi3xxx_set_cpu(cpu, false);
200252
return 1;
201253
}
254+
255+
void hix5hd2_cpu_die(unsigned int cpu)
256+
{
257+
flush_cache_all();
258+
hix5hd2_set_cpu(cpu, false);
259+
}
202260
#endif

arch/arm/mach-hisi/platsmp.c

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
#include "core.h"
1919

20+
#define HIX5HD2_BOOT_ADDRESS 0xffff0000
21+
2022
static void __iomem *ctrl_base;
2123

2224
void hi3xxx_set_cpu_jump(int cpu, void *jump_addr)
@@ -35,11 +37,9 @@ int hi3xxx_get_cpu_jump(int cpu)
3537
return readl_relaxed(ctrl_base + ((cpu - 1) << 2));
3638
}
3739

38-
static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus)
40+
static void __init hisi_enable_scu_a9(void)
3941
{
40-
struct device_node *np = NULL;
4142
unsigned long base = 0;
42-
u32 offset = 0;
4343
void __iomem *scu_base = NULL;
4444

4545
if (scu_a9_has_base()) {
@@ -52,6 +52,14 @@ static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus)
5252
scu_enable(scu_base);
5353
iounmap(scu_base);
5454
}
55+
}
56+
57+
static 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();
5563
if (!ctrl_base) {
5664
np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
5765
if (!np) {
@@ -87,3 +95,39 @@ struct smp_operations hi3xxx_smp_ops __initdata = {
8795
.cpu_kill = hi3xxx_cpu_kill,
8896
#endif
8997
};
98+
99+
static void __init hix5hd2_smp_prepare_cpus(unsigned int max_cpus)
100+
{
101+
hisi_enable_scu_a9();
102+
}
103+
104+
void 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+
115+
static 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+
127+
struct 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+
};

0 commit comments

Comments
 (0)