diff options
author | Kevin Hilman <khilman@linaro.org> | 2015-06-25 00:32:13 -0400 |
---|---|---|
committer | Kevin Hilman <khilman@linaro.org> | 2015-06-25 00:32:13 -0400 |
commit | 03fa626774a30145bdb97ce1bc909a0cfd419ce6 (patch) | |
tree | a0d66f91d4a983b94f6d74b7b03b5c9e00697499 /arch/arm/mach-bcm | |
parent | 8d2977bf36bf6fc66d0c8e64263711cc2f0c1e4b (diff) | |
parent | 2879e43f09122f8b3ef5456e3d7e48716b086e60 (diff) |
Merge tag 'armsoc-soc' into test-merge
ARM: SoC: platform support for v4.2
Our SoC branch usually contains expanded support for new SoCs and
other core platform code. Some highlights from this round:
- sunxi: SMP support for A23 SoC
- socpga: big-endian support
- pxa: conversion to common clock framework
- bcm: SMP support for BCM63138
- imx: support new I.MX7D SoC
- zte: basic support for ZX296702 SoC
Conflicts:
arch/arm/mach-socfpga/core.h
Trivial remove/remove conflict with our cleanup branch.
Resolution: remove both sides
# gpg: Signature made Wed Jun 24 21:32:12 2015 PDT using RSA key ID D3FBC665
# gpg: Good signature from "Kevin Hilman <khilman@deeprootsystems.com>"
# gpg: aka "Kevin Hilman <khilman@linaro.org>"
# gpg: aka "Kevin Hilman <khilman@kernel.org>"
# Conflicts:
# arch/arm/mach-socfpga/core.h
Diffstat (limited to 'arch/arm/mach-bcm')
-rw-r--r-- | arch/arm/mach-bcm/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm/mach-bcm/Makefile | 7 | ||||
-rw-r--r-- | arch/arm/mach-bcm/bcm63xx_headsmp.S | 23 | ||||
-rw-r--r-- | arch/arm/mach-bcm/bcm63xx_pmb.c | 221 | ||||
-rw-r--r-- | arch/arm/mach-bcm/bcm63xx_smp.c | 169 | ||||
-rw-r--r-- | arch/arm/mach-bcm/bcm63xx_smp.h | 9 | ||||
-rw-r--r-- | arch/arm/mach-bcm/bcm_5301x.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-bcm/board_bcm2835.c | 91 |
8 files changed, 435 insertions, 96 deletions
diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index 8b11f44bb36e..e9184feffc4e 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig | |||
@@ -19,6 +19,7 @@ config ARCH_BCM_IPROC | |||
19 | select ARCH_REQUIRE_GPIOLIB | 19 | select ARCH_REQUIRE_GPIOLIB |
20 | select ARM_AMBA | 20 | select ARM_AMBA |
21 | select PINCTRL | 21 | select PINCTRL |
22 | select MTD_NAND_BRCMNAND | ||
22 | help | 23 | help |
23 | This enables support for systems based on Broadcom IPROC architected SoCs. | 24 | This enables support for systems based on Broadcom IPROC architected SoCs. |
24 | The IPROC complex contains one or more ARM CPUs along with common | 25 | The IPROC complex contains one or more ARM CPUs along with common |
@@ -144,6 +145,7 @@ config ARCH_BRCMSTB | |||
144 | select BRCMSTB_GISB_ARB | 145 | select BRCMSTB_GISB_ARB |
145 | select BRCMSTB_L2_IRQ | 146 | select BRCMSTB_L2_IRQ |
146 | select BCM7120_L2_IRQ | 147 | select BCM7120_L2_IRQ |
148 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
147 | help | 149 | help |
148 | Say Y if you intend to run the kernel on a Broadcom ARM-based STB | 150 | Say Y if you intend to run the kernel on a Broadcom ARM-based STB |
149 | chipset. | 151 | chipset. |
diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile index 54d274da7ccb..4fb0da458e91 100644 --- a/arch/arm/mach-bcm/Makefile +++ b/arch/arm/mach-bcm/Makefile | |||
@@ -38,7 +38,12 @@ obj-$(CONFIG_ARCH_BCM2835) += board_bcm2835.o | |||
38 | obj-$(CONFIG_ARCH_BCM_5301X) += bcm_5301x.o | 38 | obj-$(CONFIG_ARCH_BCM_5301X) += bcm_5301x.o |
39 | 39 | ||
40 | # BCM63XXx | 40 | # BCM63XXx |
41 | obj-$(CONFIG_ARCH_BCM_63XX) := bcm63xx.o | 41 | ifeq ($(CONFIG_ARCH_BCM_63XX),y) |
42 | CFLAGS_bcm63xx_headsmp.o += -march=armv7-a | ||
43 | obj-y += bcm63xx.o | ||
44 | obj-$(CONFIG_SMP) += bcm63xx_smp.o bcm63xx_headsmp.o \ | ||
45 | bcm63xx_pmb.o | ||
46 | endif | ||
42 | 47 | ||
43 | ifeq ($(CONFIG_ARCH_BRCMSTB),y) | 48 | ifeq ($(CONFIG_ARCH_BRCMSTB),y) |
44 | CFLAGS_platsmp-brcmstb.o += -march=armv7-a | 49 | CFLAGS_platsmp-brcmstb.o += -march=armv7-a |
diff --git a/arch/arm/mach-bcm/bcm63xx_headsmp.S b/arch/arm/mach-bcm/bcm63xx_headsmp.S new file mode 100644 index 000000000000..c7af397c7f14 --- /dev/null +++ b/arch/arm/mach-bcm/bcm63xx_headsmp.S | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015, Broadcom Corporation | ||
3 | * All Rights Reserved | ||
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 | #include <asm/assembler.h> | ||
12 | |||
13 | ENTRY(bcm63138_secondary_startup) | ||
14 | ARM_BE8(setend be) | ||
15 | /* | ||
16 | * L1 cache does have unpredictable contents at power-up clean its | ||
17 | * contents without flushing | ||
18 | */ | ||
19 | bl v7_invalidate_l1 | ||
20 | nop | ||
21 | |||
22 | b secondary_startup | ||
23 | ENDPROC(bcm63138_secondary_startup) | ||
diff --git a/arch/arm/mach-bcm/bcm63xx_pmb.c b/arch/arm/mach-bcm/bcm63xx_pmb.c new file mode 100644 index 000000000000..de061ec5a479 --- /dev/null +++ b/arch/arm/mach-bcm/bcm63xx_pmb.c | |||
@@ -0,0 +1,221 @@ | |||
1 | /* | ||
2 | * Broadcom BCM63138 PMB initialization for secondary CPU(s) | ||
3 | * | ||
4 | * Copyright (C) 2015 Broadcom Corporation | ||
5 | * Author: Florian Fainelli <f.fainelli@gmail.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/spinlock.h> | ||
15 | #include <linux/reset/bcm63xx_pmb.h> | ||
16 | #include <linux/of.h> | ||
17 | #include <linux/of_address.h> | ||
18 | |||
19 | #include "bcm63xx_smp.h" | ||
20 | |||
21 | /* ARM Control register definitions */ | ||
22 | #define CORE_PWR_CTRL_SHIFT 0 | ||
23 | #define CORE_PWR_CTRL_MASK 0x3 | ||
24 | #define PLL_PWR_ON BIT(8) | ||
25 | #define PLL_LDO_PWR_ON BIT(9) | ||
26 | #define PLL_CLAMP_ON BIT(10) | ||
27 | #define CPU_RESET_N(x) BIT(13 + (x)) | ||
28 | #define NEON_RESET_N BIT(15) | ||
29 | #define PWR_CTRL_STATUS_SHIFT 28 | ||
30 | #define PWR_CTRL_STATUS_MASK 0x3 | ||
31 | #define PWR_DOWN_SHIFT 30 | ||
32 | #define PWR_DOWN_MASK 0x3 | ||
33 | |||
34 | /* CPU Power control register definitions */ | ||
35 | #define MEM_PWR_OK BIT(0) | ||
36 | #define MEM_PWR_ON BIT(1) | ||
37 | #define MEM_CLAMP_ON BIT(2) | ||
38 | #define MEM_PWR_OK_STATUS BIT(4) | ||
39 | #define MEM_PWR_ON_STATUS BIT(5) | ||
40 | #define MEM_PDA_SHIFT 8 | ||
41 | #define MEM_PDA_MASK 0xf | ||
42 | #define MEM_PDA_CPU_MASK 0x1 | ||
43 | #define MEM_PDA_NEON_MASK 0xf | ||
44 | #define CLAMP_ON BIT(15) | ||
45 | #define PWR_OK_SHIFT 16 | ||
46 | #define PWR_OK_MASK 0xf | ||
47 | #define PWR_ON_SHIFT 20 | ||
48 | #define PWR_CPU_MASK 0x03 | ||
49 | #define PWR_NEON_MASK 0x01 | ||
50 | #define PWR_ON_MASK 0xf | ||
51 | #define PWR_OK_STATUS_SHIFT 24 | ||
52 | #define PWR_OK_STATUS_MASK 0xf | ||
53 | #define PWR_ON_STATUS_SHIFT 28 | ||
54 | #define PWR_ON_STATUS_MASK 0xf | ||
55 | |||
56 | #define ARM_CONTROL 0x30 | ||
57 | #define ARM_PWR_CONTROL_BASE 0x34 | ||
58 | #define ARM_PWR_CONTROL(x) (ARM_PWR_CONTROL_BASE + (x) * 0x4) | ||
59 | #define ARM_NEON_L2 0x3c | ||
60 | |||
61 | /* Perform a value write, then spin until the value shifted by | ||
62 | * shift is seen, masked with mask and is different from cond. | ||
63 | */ | ||
64 | static int bpcm_wr_rd_mask(void __iomem *master, | ||
65 | unsigned int addr, u32 off, u32 *val, | ||
66 | u32 shift, u32 mask, u32 cond) | ||
67 | { | ||
68 | int ret; | ||
69 | |||
70 | ret = bpcm_wr(master, addr, off, *val); | ||
71 | if (ret) | ||
72 | return ret; | ||
73 | |||
74 | do { | ||
75 | ret = bpcm_rd(master, addr, off, val); | ||
76 | if (ret) | ||
77 | return ret; | ||
78 | |||
79 | cpu_relax(); | ||
80 | } while (((*val >> shift) & mask) != cond); | ||
81 | |||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | /* Global lock to serialize accesses to the PMB registers while we | ||
86 | * are bringing up the secondary CPU | ||
87 | */ | ||
88 | static DEFINE_SPINLOCK(pmb_lock); | ||
89 | |||
90 | static int bcm63xx_pmb_get_resources(struct device_node *dn, | ||
91 | void __iomem **base, | ||
92 | unsigned int *cpu, | ||
93 | unsigned int *addr) | ||
94 | { | ||
95 | struct device_node *pmb_dn; | ||
96 | struct of_phandle_args args; | ||
97 | int ret; | ||
98 | |||
99 | ret = of_property_read_u32(dn, "reg", cpu); | ||
100 | if (ret) { | ||
101 | pr_err("CPU is missing a reg node\n"); | ||
102 | return ret; | ||
103 | } | ||
104 | |||
105 | ret = of_parse_phandle_with_args(dn, "resets", "#reset-cells", | ||
106 | 0, &args); | ||
107 | if (ret) { | ||
108 | pr_err("CPU is missing a resets phandle\n"); | ||
109 | return ret; | ||
110 | } | ||
111 | |||
112 | pmb_dn = args.np; | ||
113 | if (args.args_count != 2) { | ||
114 | pr_err("reset-controller does not conform to reset-cells\n"); | ||
115 | return -EINVAL; | ||
116 | } | ||
117 | |||
118 | *base = of_iomap(args.np, 0); | ||
119 | if (!*base) { | ||
120 | pr_err("failed remapping PMB register\n"); | ||
121 | return -ENOMEM; | ||
122 | } | ||
123 | |||
124 | /* We do not need the number of zones */ | ||
125 | *addr = args.args[0]; | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | int bcm63xx_pmb_power_on_cpu(struct device_node *dn) | ||
131 | { | ||
132 | void __iomem *base; | ||
133 | unsigned int cpu, addr; | ||
134 | unsigned long flags; | ||
135 | u32 val, ctrl; | ||
136 | int ret; | ||
137 | |||
138 | ret = bcm63xx_pmb_get_resources(dn, &base, &cpu, &addr); | ||
139 | if (ret) | ||
140 | return ret; | ||
141 | |||
142 | /* We would not know how to enable a third and greater CPU */ | ||
143 | WARN_ON(cpu > 1); | ||
144 | |||
145 | spin_lock_irqsave(&pmb_lock, flags); | ||
146 | |||
147 | /* Check if the CPU is already on and save the ARM_CONTROL register | ||
148 | * value since we will use it later for CPU de-assert once done with | ||
149 | * the CPU-specific power sequence | ||
150 | */ | ||
151 | ret = bpcm_rd(base, addr, ARM_CONTROL, &ctrl); | ||
152 | if (ret) | ||
153 | goto out; | ||
154 | |||
155 | if (ctrl & CPU_RESET_N(cpu)) { | ||
156 | pr_info("PMB: CPU%d is already powered on\n", cpu); | ||
157 | ret = 0; | ||
158 | goto out; | ||
159 | } | ||
160 | |||
161 | /* Power on PLL */ | ||
162 | ret = bpcm_rd(base, addr, ARM_PWR_CONTROL(cpu), &val); | ||
163 | if (ret) | ||
164 | goto out; | ||
165 | |||
166 | val |= (PWR_CPU_MASK << PWR_ON_SHIFT); | ||
167 | |||
168 | ret = bpcm_wr_rd_mask(base, addr, ARM_PWR_CONTROL(cpu), &val, | ||
169 | PWR_ON_STATUS_SHIFT, PWR_CPU_MASK, PWR_CPU_MASK); | ||
170 | if (ret) | ||
171 | goto out; | ||
172 | |||
173 | val |= (PWR_CPU_MASK << PWR_OK_SHIFT); | ||
174 | |||
175 | ret = bpcm_wr_rd_mask(base, addr, ARM_PWR_CONTROL(cpu), &val, | ||
176 | PWR_OK_STATUS_SHIFT, PWR_CPU_MASK, PWR_CPU_MASK); | ||
177 | if (ret) | ||
178 | goto out; | ||
179 | |||
180 | val &= ~CLAMP_ON; | ||
181 | |||
182 | ret = bpcm_wr(base, addr, ARM_PWR_CONTROL(cpu), val); | ||
183 | if (ret) | ||
184 | goto out; | ||
185 | |||
186 | /* Power on CPU<N> RAM */ | ||
187 | val &= ~(MEM_PDA_MASK << MEM_PDA_SHIFT); | ||
188 | |||
189 | ret = bpcm_wr(base, addr, ARM_PWR_CONTROL(cpu), val); | ||
190 | if (ret) | ||
191 | goto out; | ||
192 | |||
193 | val |= MEM_PWR_ON; | ||
194 | |||
195 | ret = bpcm_wr_rd_mask(base, addr, ARM_PWR_CONTROL(cpu), &val, | ||
196 | 0, MEM_PWR_ON_STATUS, MEM_PWR_ON_STATUS); | ||
197 | if (ret) | ||
198 | goto out; | ||
199 | |||
200 | val |= MEM_PWR_OK; | ||
201 | |||
202 | ret = bpcm_wr_rd_mask(base, addr, ARM_PWR_CONTROL(cpu), &val, | ||
203 | 0, MEM_PWR_OK_STATUS, MEM_PWR_OK_STATUS); | ||
204 | if (ret) | ||
205 | goto out; | ||
206 | |||
207 | val &= ~MEM_CLAMP_ON; | ||
208 | |||
209 | ret = bpcm_wr(base, addr, ARM_PWR_CONTROL(cpu), val); | ||
210 | if (ret) | ||
211 | goto out; | ||
212 | |||
213 | /* De-assert CPU reset */ | ||
214 | ctrl |= CPU_RESET_N(cpu); | ||
215 | |||
216 | ret = bpcm_wr(base, addr, ARM_CONTROL, ctrl); | ||
217 | out: | ||
218 | spin_unlock_irqrestore(&pmb_lock, flags); | ||
219 | iounmap(base); | ||
220 | return ret; | ||
221 | } | ||
diff --git a/arch/arm/mach-bcm/bcm63xx_smp.c b/arch/arm/mach-bcm/bcm63xx_smp.c new file mode 100644 index 000000000000..3f014f18cea5 --- /dev/null +++ b/arch/arm/mach-bcm/bcm63xx_smp.c | |||
@@ -0,0 +1,169 @@ | |||
1 | /* | ||
2 | * Broadcom BCM63138 DSL SoCs SMP support code | ||
3 | * | ||
4 | * Copyright (C) 2015, Broadcom Corporation | ||
5 | * | ||
6 | * Licensed under the terms of the GPLv2 | ||
7 | */ | ||
8 | |||
9 | #include <linux/delay.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/smp.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/of.h> | ||
14 | #include <linux/of_address.h> | ||
15 | |||
16 | #include <asm/cacheflush.h> | ||
17 | #include <asm/smp_scu.h> | ||
18 | #include <asm/smp_plat.h> | ||
19 | #include <asm/vfp.h> | ||
20 | |||
21 | #include "bcm63xx_smp.h" | ||
22 | |||
23 | /* Size of mapped Cortex A9 SCU address space */ | ||
24 | #define CORTEX_A9_SCU_SIZE 0x58 | ||
25 | |||
26 | /* | ||
27 | * Enable the Cortex A9 Snoop Control Unit | ||
28 | * | ||
29 | * By the time this is called we already know there are multiple | ||
30 | * cores present. We assume we're running on a Cortex A9 processor, | ||
31 | * so any trouble getting the base address register or getting the | ||
32 | * SCU base is a problem. | ||
33 | * | ||
34 | * Return 0 if successful or an error code otherwise. | ||
35 | */ | ||
36 | static int __init scu_a9_enable(void) | ||
37 | { | ||
38 | unsigned long config_base; | ||
39 | void __iomem *scu_base; | ||
40 | unsigned int i, ncores; | ||
41 | |||
42 | if (!scu_a9_has_base()) { | ||
43 | pr_err("no configuration base address register!\n"); | ||
44 | return -ENXIO; | ||
45 | } | ||
46 | |||
47 | /* Config base address register value is zero for uniprocessor */ | ||
48 | config_base = scu_a9_get_base(); | ||
49 | if (!config_base) { | ||
50 | pr_err("hardware reports only one core\n"); | ||
51 | return -ENOENT; | ||
52 | } | ||
53 | |||
54 | scu_base = ioremap((phys_addr_t)config_base, CORTEX_A9_SCU_SIZE); | ||
55 | if (!scu_base) { | ||
56 | pr_err("failed to remap config base (%lu/%u) for SCU\n", | ||
57 | config_base, CORTEX_A9_SCU_SIZE); | ||
58 | return -ENOMEM; | ||
59 | } | ||
60 | |||
61 | scu_enable(scu_base); | ||
62 | |||
63 | ncores = scu_base ? scu_get_core_count(scu_base) : 1; | ||
64 | |||
65 | if (ncores > nr_cpu_ids) { | ||
66 | pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", | ||
67 | ncores, nr_cpu_ids); | ||
68 | ncores = nr_cpu_ids; | ||
69 | } | ||
70 | |||
71 | /* The BCM63138 SoC has two Cortex-A9 CPUs, CPU0 features a complete | ||
72 | * and fully functional VFP unit that can be used, but CPU1 does not. | ||
73 | * Since we will not be able to trap kernel-mode NEON to force | ||
74 | * migration to CPU0, just do not advertise VFP support at all. | ||
75 | * | ||
76 | * This will make vfp_init bail out and do not attempt to use VFP at | ||
77 | * all, for kernel-mode NEON, we do not want to introduce any | ||
78 | * conditionals in hot-paths, so we just restrict the system to UP. | ||
79 | */ | ||
80 | #ifdef CONFIG_VFP | ||
81 | if (ncores > 1) { | ||
82 | pr_warn("SMP: secondary CPUs lack VFP unit, disabling VFP\n"); | ||
83 | vfp_disable(); | ||
84 | |||
85 | #ifdef CONFIG_KERNEL_MODE_NEON | ||
86 | WARN(1, "SMP: kernel-mode NEON enabled, restricting to UP\n"); | ||
87 | ncores = 1; | ||
88 | #endif | ||
89 | } | ||
90 | #endif | ||
91 | |||
92 | for (i = 0; i < ncores; i++) | ||
93 | set_cpu_possible(i, true); | ||
94 | |||
95 | iounmap(scu_base); /* That's the last we'll need of this */ | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static const struct of_device_id bcm63138_bootlut_ids[] = { | ||
101 | { .compatible = "brcm,bcm63138-bootlut", }, | ||
102 | { /* sentinel */ }, | ||
103 | }; | ||
104 | |||
105 | #define BOOTLUT_RESET_VECT 0x20 | ||
106 | |||
107 | static int bcm63138_smp_boot_secondary(unsigned int cpu, | ||
108 | struct task_struct *idle) | ||
109 | { | ||
110 | void __iomem *bootlut_base; | ||
111 | struct device_node *dn; | ||
112 | int ret = 0; | ||
113 | u32 val; | ||
114 | |||
115 | dn = of_find_matching_node(NULL, bcm63138_bootlut_ids); | ||
116 | if (!dn) { | ||
117 | pr_err("SMP: unable to find bcm63138 boot LUT node\n"); | ||
118 | return -ENODEV; | ||
119 | } | ||
120 | |||
121 | bootlut_base = of_iomap(dn, 0); | ||
122 | of_node_put(dn); | ||
123 | |||
124 | if (!bootlut_base) { | ||
125 | pr_err("SMP: unable to remap boot LUT base register\n"); | ||
126 | return -ENOMEM; | ||
127 | } | ||
128 | |||
129 | /* Locate the secondary CPU node */ | ||
130 | dn = of_get_cpu_node(cpu_logical_map(cpu), NULL); | ||
131 | if (!dn) { | ||
132 | pr_err("SMP: failed to locate secondary CPU%d node\n", cpu); | ||
133 | ret = -ENODEV; | ||
134 | goto out; | ||
135 | } | ||
136 | |||
137 | /* Write the secondary init routine to the BootLUT reset vector */ | ||
138 | val = virt_to_phys(bcm63138_secondary_startup); | ||
139 | writel_relaxed(val, bootlut_base + BOOTLUT_RESET_VECT); | ||
140 | |||
141 | /* Power up the core, will jump straight to its reset vector when we | ||
142 | * return | ||
143 | */ | ||
144 | ret = bcm63xx_pmb_power_on_cpu(dn); | ||
145 | if (ret) | ||
146 | goto out; | ||
147 | out: | ||
148 | iounmap(bootlut_base); | ||
149 | |||
150 | return ret; | ||
151 | } | ||
152 | |||
153 | static void __init bcm63138_smp_prepare_cpus(unsigned int max_cpus) | ||
154 | { | ||
155 | int ret; | ||
156 | |||
157 | ret = scu_a9_enable(); | ||
158 | if (ret) { | ||
159 | pr_warn("SMP: Cortex-A9 SCU setup failed\n"); | ||
160 | return; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | struct smp_operations bcm63138_smp_ops __initdata = { | ||
165 | .smp_prepare_cpus = bcm63138_smp_prepare_cpus, | ||
166 | .smp_boot_secondary = bcm63138_smp_boot_secondary, | ||
167 | }; | ||
168 | |||
169 | CPU_METHOD_OF_DECLARE(bcm63138_smp, "brcm,bcm63138", &bcm63138_smp_ops); | ||
diff --git a/arch/arm/mach-bcm/bcm63xx_smp.h b/arch/arm/mach-bcm/bcm63xx_smp.h new file mode 100644 index 000000000000..50b76044536e --- /dev/null +++ b/arch/arm/mach-bcm/bcm63xx_smp.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef __BCM63XX_SMP_H | ||
2 | #define __BCM63XX_SMP_H | ||
3 | |||
4 | struct device_node; | ||
5 | |||
6 | extern void bcm63138_secondary_startup(void); | ||
7 | extern int bcm63xx_pmb_power_on_cpu(struct device_node *dn); | ||
8 | |||
9 | #endif /* __BCM63XX_SMP_H */ | ||
diff --git a/arch/arm/mach-bcm/bcm_5301x.c b/arch/arm/mach-bcm/bcm_5301x.c index e9bcbdbce555..7aef92720eb4 100644 --- a/arch/arm/mach-bcm/bcm_5301x.c +++ b/arch/arm/mach-bcm/bcm_5301x.c | |||
@@ -18,15 +18,16 @@ static bool first_fault = true; | |||
18 | static int bcm5301x_abort_handler(unsigned long addr, unsigned int fsr, | 18 | static int bcm5301x_abort_handler(unsigned long addr, unsigned int fsr, |
19 | struct pt_regs *regs) | 19 | struct pt_regs *regs) |
20 | { | 20 | { |
21 | if (fsr == 0x1c06 && first_fault) { | 21 | if ((fsr == 0x1406 || fsr == 0x1c06) && first_fault) { |
22 | first_fault = false; | 22 | first_fault = false; |
23 | 23 | ||
24 | /* | 24 | /* |
25 | * These faults with code 0x1c06 happens for no good reason, | 25 | * These faults with codes 0x1406 (BCM4709) or 0x1c06 happens |
26 | * possibly left over from the CFE boot loader. | 26 | * for no good reason, possibly left over from the CFE boot |
27 | * loader. | ||
27 | */ | 28 | */ |
28 | pr_warn("External imprecise Data abort at addr=%#lx, fsr=%#x ignored.\n", | 29 | pr_warn("External imprecise Data abort at addr=%#lx, fsr=%#x ignored.\n", |
29 | addr, fsr); | 30 | addr, fsr); |
30 | 31 | ||
31 | /* Returning non-zero causes fault display and panic */ | 32 | /* Returning non-zero causes fault display and panic */ |
32 | return 0; | 33 | return 0; |
diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c index 70f2f3925f0e..0f7b9eac3d15 100644 --- a/arch/arm/mach-bcm/board_bcm2835.c +++ b/arch/arm/mach-bcm/board_bcm2835.c | |||
@@ -12,7 +12,6 @@ | |||
12 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/init.h> | 15 | #include <linux/init.h> |
17 | #include <linux/irqchip.h> | 16 | #include <linux/irqchip.h> |
18 | #include <linux/of_address.h> | 17 | #include <linux/of_address.h> |
@@ -22,97 +21,10 @@ | |||
22 | #include <asm/mach/arch.h> | 21 | #include <asm/mach/arch.h> |
23 | #include <asm/mach/map.h> | 22 | #include <asm/mach/map.h> |
24 | 23 | ||
25 | #define PM_RSTC 0x1c | ||
26 | #define PM_RSTS 0x20 | ||
27 | #define PM_WDOG 0x24 | ||
28 | |||
29 | #define PM_PASSWORD 0x5a000000 | ||
30 | #define PM_RSTC_WRCFG_MASK 0x00000030 | ||
31 | #define PM_RSTC_WRCFG_FULL_RESET 0x00000020 | ||
32 | #define PM_RSTS_HADWRH_SET 0x00000040 | ||
33 | |||
34 | #define BCM2835_PERIPH_PHYS 0x20000000 | ||
35 | #define BCM2835_PERIPH_VIRT 0xf0000000 | ||
36 | #define BCM2835_PERIPH_SIZE SZ_16M | ||
37 | |||
38 | static void __iomem *wdt_regs; | ||
39 | |||
40 | /* | ||
41 | * The machine restart method can be called from an atomic context so we won't | ||
42 | * be able to ioremap the regs then. | ||
43 | */ | ||
44 | static void bcm2835_setup_restart(void) | ||
45 | { | ||
46 | struct device_node *np = of_find_compatible_node(NULL, NULL, | ||
47 | "brcm,bcm2835-pm-wdt"); | ||
48 | if (WARN(!np, "unable to setup watchdog restart")) | ||
49 | return; | ||
50 | |||
51 | wdt_regs = of_iomap(np, 0); | ||
52 | WARN(!wdt_regs, "failed to remap watchdog regs"); | ||
53 | } | ||
54 | |||
55 | static void bcm2835_restart(enum reboot_mode mode, const char *cmd) | ||
56 | { | ||
57 | u32 val; | ||
58 | |||
59 | if (!wdt_regs) | ||
60 | return; | ||
61 | |||
62 | /* use a timeout of 10 ticks (~150us) */ | ||
63 | writel_relaxed(10 | PM_PASSWORD, wdt_regs + PM_WDOG); | ||
64 | val = readl_relaxed(wdt_regs + PM_RSTC); | ||
65 | val &= ~PM_RSTC_WRCFG_MASK; | ||
66 | val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET; | ||
67 | writel_relaxed(val, wdt_regs + PM_RSTC); | ||
68 | |||
69 | /* No sleeping, possibly atomic. */ | ||
70 | mdelay(1); | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * We can't really power off, but if we do the normal reset scheme, and | ||
75 | * indicate to bootcode.bin not to reboot, then most of the chip will be | ||
76 | * powered off. | ||
77 | */ | ||
78 | static void bcm2835_power_off(void) | ||
79 | { | ||
80 | u32 val; | ||
81 | |||
82 | /* | ||
83 | * We set the watchdog hard reset bit here to distinguish this reset | ||
84 | * from the normal (full) reset. bootcode.bin will not reboot after a | ||
85 | * hard reset. | ||
86 | */ | ||
87 | val = readl_relaxed(wdt_regs + PM_RSTS); | ||
88 | val &= ~PM_RSTC_WRCFG_MASK; | ||
89 | val |= PM_PASSWORD | PM_RSTS_HADWRH_SET; | ||
90 | writel_relaxed(val, wdt_regs + PM_RSTS); | ||
91 | |||
92 | /* Continue with normal reset mechanism */ | ||
93 | bcm2835_restart(REBOOT_HARD, ""); | ||
94 | } | ||
95 | |||
96 | static struct map_desc io_map __initdata = { | ||
97 | .virtual = BCM2835_PERIPH_VIRT, | ||
98 | .pfn = __phys_to_pfn(BCM2835_PERIPH_PHYS), | ||
99 | .length = BCM2835_PERIPH_SIZE, | ||
100 | .type = MT_DEVICE | ||
101 | }; | ||
102 | |||
103 | static void __init bcm2835_map_io(void) | ||
104 | { | ||
105 | iotable_init(&io_map, 1); | ||
106 | } | ||
107 | |||
108 | static void __init bcm2835_init(void) | 24 | static void __init bcm2835_init(void) |
109 | { | 25 | { |
110 | int ret; | 26 | int ret; |
111 | 27 | ||
112 | bcm2835_setup_restart(); | ||
113 | if (wdt_regs) | ||
114 | pm_power_off = bcm2835_power_off; | ||
115 | |||
116 | bcm2835_init_clocks(); | 28 | bcm2835_init_clocks(); |
117 | 29 | ||
118 | ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, | 30 | ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, |
@@ -129,9 +41,6 @@ static const char * const bcm2835_compat[] = { | |||
129 | }; | 41 | }; |
130 | 42 | ||
131 | DT_MACHINE_START(BCM2835, "BCM2835") | 43 | DT_MACHINE_START(BCM2835, "BCM2835") |
132 | .map_io = bcm2835_map_io, | ||
133 | .init_irq = irqchip_init, | ||
134 | .init_machine = bcm2835_init, | 44 | .init_machine = bcm2835_init, |
135 | .restart = bcm2835_restart, | ||
136 | .dt_compat = bcm2835_compat | 45 | .dt_compat = bcm2835_compat |
137 | MACHINE_END | 46 | MACHINE_END |