1 From 0377ad93031d3e51c2afe44231241185f684b6af Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
3 Date: Fri, 5 Mar 2021 15:14:32 +0100
4 Subject: [PATCH 1/2] mips: bmips: automatically detect CPU frequency
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
9 Some BCM63xx SoCs support multiple CPU frequencies depending on HW config.
11 Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
13 arch/mips/bmips/setup.c | 198 ++++++++++++++++++++++++++++++++++++++--
14 1 file changed, 191 insertions(+), 7 deletions(-)
16 --- a/arch/mips/bmips/setup.c
17 +++ b/arch/mips/bmips/setup.c
20 #define RELO_NORMAL_VEC BIT(18)
22 +#define REG_BCM6318_SOB ((void __iomem *)CKSEG1ADDR(0x10000900))
23 +#define BCM6318_FREQ_SHIFT 23
24 +#define BCM6318_FREQ_MASK (0x3 << BCM6318_FREQ_SHIFT)
26 #define REG_BCM6328_OTP ((void __iomem *)CKSEG1ADDR(0x1000062c))
27 #define BCM6328_TP1_DISABLED BIT(9)
28 +#define REG_BCM6328_MISC_SB ((void __iomem *)CKSEG1ADDR(0x10001a40))
29 +#define BCM6328_FCVO_SHIFT 7
30 +#define BCM6328_FCVO_MASK (0x1f << BCM6328_FCVO_SHIFT)
32 +#define REG_BCM6358_DDR_PLLC ((void __iomem *)0xfffe12b8)
33 +#define BCM6358_PLLC_M1_SHIFT 0
34 +#define BCM6358_PLLC_M1_MASK (0xff << BCM6358_PLLC_M1_SHIFT)
35 +#define BCM6358_PLLC_N1_SHIFT 23
36 +#define BCM6358_PLLC_N1_MASK (0x3f << BCM6358_PLLC_N1_SHIFT)
37 +#define BCM6358_PLLC_N2_SHIFT 29
38 +#define BCM6358_PLLC_N2_MASK (0x7 << BCM6358_PLLC_N2_SHIFT)
40 +#define REG_BCM6362_MISC_SB ((void __iomem *)CKSEG1ADDR(0x10001814))
41 +#define BCM6362_FCVO_SHIFT 1
42 +#define BCM6362_FCVO_MASK (0x1f << BCM6362_FCVO_SHIFT)
44 +#define REG_BCM6368_DDR_PLLC ((void __iomem *)CKSEG1ADDR(0x100012a0))
45 +#define BCM6368_PLLC_P1_SHIFT 0
46 +#define BCM6368_PLLC_P1_MASK (0xf << BCM6368_PLLC_P1_SHIFT)
47 +#define BCM6368_PLLC_P2_SHIFT 4
48 +#define BCM6368_PLLC_P2_MASK (0xf << BCM6368_PLLC_P2_SHIFT)
49 +#define BCM6368_PLLC_NDIV_SHIFT 16
50 +#define BCM6368_PLLC_NDIV_MASK (0x1ff << BCM6368_PLLC_NDIV_SHIFT)
51 +#define REG_BCM6368_DDR_PLLD ((void __iomem *)CKSEG1ADDR(0x100012a4))
52 +#define BCM6368_PLLD_MDIV_SHIFT 0
53 +#define BCM6368_PLLD_MDIV_MASK (0xff << BCM6368_PLLD_MDIV_SHIFT)
55 +#define REG_BCM63268_MISC_SB ((void __iomem *)CKSEG1ADDR(0x10001814))
56 +#define BCM63268_FCVO_SHIFT 21
57 +#define BCM63268_FCVO_MASK (0xf << BCM63268_FCVO_SHIFT)
59 extern bool bmips_rac_flush_disable;
61 static const unsigned long kbase = VMLINUX_LOAD_ADDRESS & 0xfff00000;
63 +struct bmips_cpufreq {
64 + const char *compatible;
65 + u32 (*cpu_freq)(void);
69 const char *compatible;
70 void (*quirk_fn)(void);
71 @@ -142,17 +181,161 @@ const char *get_system_type(void)
72 return "Generic BMIPS kernel";
75 +static u32 bcm6318_cpufreq(void)
77 + u32 val = __raw_readl(REG_BCM6318_SOB);
79 + switch ((val & BCM6318_FREQ_MASK) >> BCM6318_FREQ_SHIFT) {
93 +static u32 bcm6328_cpufreq(void)
95 + u32 val = __raw_readl(REG_BCM6328_MISC_SB);
97 + switch ((val & BCM6328_FCVO_MASK) >> BCM6328_FCVO_SHIFT) {
116 +static u32 bcm6358_cpufreq(void)
118 + u32 val, n1, n2, m1;
120 + val = __raw_readl(REG_BCM6358_DDR_PLLC);
121 + n1 = (val & BCM6358_PLLC_N1_MASK) >> BCM6358_PLLC_N1_SHIFT;
122 + n2 = (val & BCM6358_PLLC_N2_MASK) >> BCM6358_PLLC_N2_SHIFT;
123 + m1 = (val & BCM6358_PLLC_M1_MASK) >> BCM6358_PLLC_M1_SHIFT;
125 + return (16 * 1000000 * n1 * n2) / m1;
128 +static u32 bcm6362_cpufreq(void)
130 + u32 val = __raw_readl(REG_BCM6362_MISC_SB);
132 + switch ((val & BCM6362_FCVO_MASK) >> BCM6362_FCVO_SHIFT) {
162 +static u32 bcm6368_cpufreq(void)
164 + u32 val, p1, p2, ndiv, m1;
166 + val = __raw_readl(REG_BCM6368_DDR_PLLC);
167 + p1 = (val & BCM6368_PLLC_P1_MASK) >> BCM6368_PLLC_P1_SHIFT;
168 + p2 = (val & BCM6368_PLLC_P2_MASK) >> BCM6368_PLLC_P2_SHIFT;
169 + ndiv = (val & BCM6368_PLLC_NDIV_MASK) >>
170 + BCM6368_PLLC_NDIV_SHIFT;
172 + val = __raw_readl(REG_BCM6368_DDR_PLLD);
173 + m1 = (val & BCM6368_PLLD_MDIV_MASK) >> BCM6368_PLLD_MDIV_SHIFT;
175 + return (((64 * 1000000) / p1) * p2 * ndiv) / m1;
178 +static u32 bcm63268_cpufreq(void)
180 + u32 val = __raw_readl(REG_BCM63268_MISC_SB);
182 + switch ((val & BCM63268_FCVO_MASK) >> BCM63268_FCVO_SHIFT) {
197 +static const struct bmips_cpufreq bmips_cpufreq_list[] = {
198 + { "brcm,bcm6318", &bcm6318_cpufreq },
199 + { "brcm,bcm6328", &bcm6328_cpufreq },
200 + { "brcm,bcm6358", &bcm6358_cpufreq },
201 + { "brcm,bcm6362", &bcm6362_cpufreq },
202 + { "brcm,bcm6368", &bcm6368_cpufreq },
203 + { "brcm,bcm63268", &bcm63268_cpufreq },
207 void __init plat_time_init(void)
209 + const struct bmips_cpufreq *cf;
210 struct device_node *np;
214 - np = of_find_node_by_name(NULL, "cpus");
216 - panic("missing 'cpus' DT node");
217 - if (of_property_read_u32(np, "mips-hpt-frequency", &freq) < 0)
218 - panic("missing 'mips-hpt-frequency' property");
220 + for (cf = bmips_cpufreq_list; cf->cpu_freq; cf++) {
221 + if (of_flat_dt_is_compatible(of_get_flat_dt_root(),
223 + freq = cf->cpu_freq() / 2;
224 + printk("%s detected @ %u MHz\n", cf->compatible, freq / 500000);
230 + np = of_find_node_by_name(NULL, "cpus");
232 + panic("missing 'cpus' DT node");
233 + if (of_property_read_u32(np, "mips-hpt-frequency", &freq) < 0)
234 + panic("missing 'mips-hpt-frequency' property");
238 mips_hpt_frequency = freq;