1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Broadcom BCM63138 PMB initialization for secondary CPU(s)
5 * Copyright (C) 2015 Broadcom Corporation
6 * Author: Florian Fainelli <f.fainelli@gmail.com>
8 #include <linux/kernel.h>
10 #include <linux/spinlock.h>
11 #include <linux/reset/bcm63xx_pmb.h>
13 #include <linux/of_address.h>
15 #include "bcm63xx_smp.h"
17 /* ARM Control register definitions */
18 #define CORE_PWR_CTRL_SHIFT 0
19 #define CORE_PWR_CTRL_MASK 0x3
20 #define PLL_PWR_ON BIT(8)
21 #define PLL_LDO_PWR_ON BIT(9)
22 #define PLL_CLAMP_ON BIT(10)
23 #define CPU_RESET_N(x) BIT(13 + (x))
24 #define NEON_RESET_N BIT(15)
25 #define PWR_CTRL_STATUS_SHIFT 28
26 #define PWR_CTRL_STATUS_MASK 0x3
27 #define PWR_DOWN_SHIFT 30
28 #define PWR_DOWN_MASK 0x3
30 /* CPU Power control register definitions */
31 #define MEM_PWR_OK BIT(0)
32 #define MEM_PWR_ON BIT(1)
33 #define MEM_CLAMP_ON BIT(2)
34 #define MEM_PWR_OK_STATUS BIT(4)
35 #define MEM_PWR_ON_STATUS BIT(5)
36 #define MEM_PDA_SHIFT 8
37 #define MEM_PDA_MASK 0xf
38 #define MEM_PDA_CPU_MASK 0x1
39 #define MEM_PDA_NEON_MASK 0xf
40 #define CLAMP_ON BIT(15)
41 #define PWR_OK_SHIFT 16
42 #define PWR_OK_MASK 0xf
43 #define PWR_ON_SHIFT 20
44 #define PWR_CPU_MASK 0x03
45 #define PWR_NEON_MASK 0x01
46 #define PWR_ON_MASK 0xf
47 #define PWR_OK_STATUS_SHIFT 24
48 #define PWR_OK_STATUS_MASK 0xf
49 #define PWR_ON_STATUS_SHIFT 28
50 #define PWR_ON_STATUS_MASK 0xf
52 #define ARM_CONTROL 0x30
53 #define ARM_PWR_CONTROL_BASE 0x34
54 #define ARM_PWR_CONTROL(x) (ARM_PWR_CONTROL_BASE + (x) * 0x4)
55 #define ARM_NEON_L2 0x3c
57 /* Perform a value write, then spin until the value shifted by
58 * shift is seen, masked with mask and is different from cond.
60 static int bpcm_wr_rd_mask(void __iomem
*master
,
61 unsigned int addr
, u32 off
, u32
*val
,
62 u32 shift
, u32 mask
, u32 cond
)
66 ret
= bpcm_wr(master
, addr
, off
, *val
);
71 ret
= bpcm_rd(master
, addr
, off
, val
);
76 } while (((*val
>> shift
) & mask
) != cond
);
81 /* Global lock to serialize accesses to the PMB registers while we
82 * are bringing up the secondary CPU
84 static DEFINE_SPINLOCK(pmb_lock
);
86 static int bcm63xx_pmb_get_resources(struct device_node
*dn
,
91 struct of_phandle_args args
;
94 ret
= of_property_read_u32(dn
, "reg", cpu
);
96 pr_err("CPU is missing a reg node\n");
100 ret
= of_parse_phandle_with_args(dn
, "resets", "#reset-cells",
103 pr_err("CPU is missing a resets phandle\n");
107 if (args
.args_count
!= 2) {
108 pr_err("reset-controller does not conform to reset-cells\n");
112 *base
= of_iomap(args
.np
, 0);
114 pr_err("failed remapping PMB register\n");
118 /* We do not need the number of zones */
119 *addr
= args
.args
[0];
124 int bcm63xx_pmb_power_on_cpu(struct device_node
*dn
)
127 unsigned int cpu
, addr
;
132 ret
= bcm63xx_pmb_get_resources(dn
, &base
, &cpu
, &addr
);
136 /* We would not know how to enable a third and greater CPU */
139 spin_lock_irqsave(&pmb_lock
, flags
);
141 /* Check if the CPU is already on and save the ARM_CONTROL register
142 * value since we will use it later for CPU de-assert once done with
143 * the CPU-specific power sequence
145 ret
= bpcm_rd(base
, addr
, ARM_CONTROL
, &ctrl
);
149 if (ctrl
& CPU_RESET_N(cpu
)) {
150 pr_info("PMB: CPU%d is already powered on\n", cpu
);
156 ret
= bpcm_rd(base
, addr
, ARM_PWR_CONTROL(cpu
), &val
);
160 val
|= (PWR_CPU_MASK
<< PWR_ON_SHIFT
);
162 ret
= bpcm_wr_rd_mask(base
, addr
, ARM_PWR_CONTROL(cpu
), &val
,
163 PWR_ON_STATUS_SHIFT
, PWR_CPU_MASK
, PWR_CPU_MASK
);
167 val
|= (PWR_CPU_MASK
<< PWR_OK_SHIFT
);
169 ret
= bpcm_wr_rd_mask(base
, addr
, ARM_PWR_CONTROL(cpu
), &val
,
170 PWR_OK_STATUS_SHIFT
, PWR_CPU_MASK
, PWR_CPU_MASK
);
176 ret
= bpcm_wr(base
, addr
, ARM_PWR_CONTROL(cpu
), val
);
180 /* Power on CPU<N> RAM */
181 val
&= ~(MEM_PDA_MASK
<< MEM_PDA_SHIFT
);
183 ret
= bpcm_wr(base
, addr
, ARM_PWR_CONTROL(cpu
), val
);
189 ret
= bpcm_wr_rd_mask(base
, addr
, ARM_PWR_CONTROL(cpu
), &val
,
190 0, MEM_PWR_ON_STATUS
, MEM_PWR_ON_STATUS
);
196 ret
= bpcm_wr_rd_mask(base
, addr
, ARM_PWR_CONTROL(cpu
), &val
,
197 0, MEM_PWR_OK_STATUS
, MEM_PWR_OK_STATUS
);
201 val
&= ~MEM_CLAMP_ON
;
203 ret
= bpcm_wr(base
, addr
, ARM_PWR_CONTROL(cpu
), val
);
207 /* De-assert CPU reset */
208 ctrl
|= CPU_RESET_N(cpu
);
210 ret
= bpcm_wr(base
, addr
, ARM_CONTROL
, ctrl
);
212 spin_unlock_irqrestore(&pmb_lock
, flags
);