aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-bcm
diff options
context:
space:
mode:
authorKevin Hilman <khilman@linaro.org>2015-06-25 00:32:13 -0400
committerKevin Hilman <khilman@linaro.org>2015-06-25 00:32:13 -0400
commit03fa626774a30145bdb97ce1bc909a0cfd419ce6 (patch)
treea0d66f91d4a983b94f6d74b7b03b5c9e00697499 /arch/arm/mach-bcm
parent8d2977bf36bf6fc66d0c8e64263711cc2f0c1e4b (diff)
parent2879e43f09122f8b3ef5456e3d7e48716b086e60 (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/Kconfig2
-rw-r--r--arch/arm/mach-bcm/Makefile7
-rw-r--r--arch/arm/mach-bcm/bcm63xx_headsmp.S23
-rw-r--r--arch/arm/mach-bcm/bcm63xx_pmb.c221
-rw-r--r--arch/arm/mach-bcm/bcm63xx_smp.c169
-rw-r--r--arch/arm/mach-bcm/bcm63xx_smp.h9
-rw-r--r--arch/arm/mach-bcm/bcm_5301x.c9
-rw-r--r--arch/arm/mach-bcm/board_bcm2835.c91
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
38obj-$(CONFIG_ARCH_BCM_5301X) += bcm_5301x.o 38obj-$(CONFIG_ARCH_BCM_5301X) += bcm_5301x.o
39 39
40# BCM63XXx 40# BCM63XXx
41obj-$(CONFIG_ARCH_BCM_63XX) := bcm63xx.o 41ifeq ($(CONFIG_ARCH_BCM_63XX),y)
42CFLAGS_bcm63xx_headsmp.o += -march=armv7-a
43obj-y += bcm63xx.o
44obj-$(CONFIG_SMP) += bcm63xx_smp.o bcm63xx_headsmp.o \
45 bcm63xx_pmb.o
46endif
42 47
43ifeq ($(CONFIG_ARCH_BRCMSTB),y) 48ifeq ($(CONFIG_ARCH_BRCMSTB),y)
44CFLAGS_platsmp-brcmstb.o += -march=armv7-a 49CFLAGS_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
13ENTRY(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
23ENDPROC(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 */
64static 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 */
88static DEFINE_SPINLOCK(pmb_lock);
89
90static 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
130int 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);
217out:
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 */
36static 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
100static const struct of_device_id bcm63138_bootlut_ids[] = {
101 { .compatible = "brcm,bcm63138-bootlut", },
102 { /* sentinel */ },
103};
104
105#define BOOTLUT_RESET_VECT 0x20
106
107static 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;
147out:
148 iounmap(bootlut_base);
149
150 return ret;
151}
152
153static 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
164struct smp_operations bcm63138_smp_ops __initdata = {
165 .smp_prepare_cpus = bcm63138_smp_prepare_cpus,
166 .smp_boot_secondary = bcm63138_smp_boot_secondary,
167};
168
169CPU_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
4struct device_node;
5
6extern void bcm63138_secondary_startup(void);
7extern 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;
18static int bcm5301x_abort_handler(unsigned long addr, unsigned int fsr, 18static 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
38static 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 */
44static 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
55static 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 */
78static 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
96static 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
103static void __init bcm2835_map_io(void)
104{
105 iotable_init(&io_map, 1);
106}
107
108static void __init bcm2835_init(void) 24static 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
131DT_MACHINE_START(BCM2835, "BCM2835") 43DT_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
137MACHINE_END 46MACHINE_END