]> git.sur5r.net Git - u-boot/blob - drivers/cpu/bmips_cpu.c
Merge git://git.denx.de/u-boot-mips
[u-boot] / drivers / cpu / bmips_cpu.c
1 /*
2  * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
3  *
4  * Derived from linux/arch/mips/bcm63xx/cpu.c:
5  *      Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
6  *      Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
9  */
10
11 #include <common.h>
12 #include <cpu.h>
13 #include <dm.h>
14 #include <errno.h>
15 #include <asm/io.h>
16
17 DECLARE_GLOBAL_DATA_PTR;
18
19 #define REV_CHIPID_SHIFT                16
20 #define REV_CHIPID_MASK                 (0xffff << REV_CHIPID_SHIFT)
21 #define REV_LONG_CHIPID_SHIFT           12
22 #define REV_LONG_CHIPID_MASK            (0xfffff << REV_LONG_CHIPID_SHIFT)
23 #define REV_REVID_SHIFT                 0
24 #define REV_REVID_MASK                  (0xff << REV_REVID_SHIFT)
25
26 #define REG_BCM6328_OTP                 0x62c
27 #define BCM6328_TP1_DISABLED            BIT(9)
28
29 #define REG_BCM6318_STRAP_OVRDBUS       0x900
30 #define OVRDBUS_6318_FREQ_SHIFT         23
31 #define OVRDBUS_6318_FREQ_MASK          (0x3 << OVRDBUS_6318_FREQ_SHIFT)
32
33 #define REG_BCM6328_MISC_STRAPBUS       0x1a40
34 #define STRAPBUS_6328_FCVO_SHIFT        7
35 #define STRAPBUS_6328_FCVO_MASK         (0x1f << STRAPBUS_6328_FCVO_SHIFT)
36
37 #define REG_BCM6348_PERF_MIPSPLLCFG     0x34
38 #define MIPSPLLCFG_6348_M1CPU_SHIFT     6
39 #define MIPSPLLCFG_6348_M1CPU_MASK      (0x7 << MIPSPLLCFG_6348_M1CPU_SHIFT)
40 #define MIPSPLLCFG_6348_N2_SHIFT        15
41 #define MIPSPLLCFG_6348_N2_MASK         (0x1F << MIPSPLLCFG_6348_N2_SHIFT)
42 #define MIPSPLLCFG_6348_N1_SHIFT        20
43 #define MIPSPLLCFG_6348_N1_MASK         (0x7 << MIPSPLLCFG_6348_N1_SHIFT)
44
45 #define REG_BCM6358_DDR_DMIPSPLLCFG     0x12b8
46 #define DMIPSPLLCFG_6358_M1_SHIFT       0
47 #define DMIPSPLLCFG_6358_M1_MASK        (0xff << DMIPSPLLCFG_6358_M1_SHIFT)
48 #define DMIPSPLLCFG_6358_N1_SHIFT       23
49 #define DMIPSPLLCFG_6358_N1_MASK        (0x3f << DMIPSPLLCFG_6358_N1_SHIFT)
50 #define DMIPSPLLCFG_6358_N2_SHIFT       29
51 #define DMIPSPLLCFG_6358_N2_MASK        (0x7 << DMIPSPLLCFG_6358_N2_SHIFT)
52
53 #define REG_BCM6368_DDR_DMIPSPLLCFG     0x12a0
54 #define DMIPSPLLCFG_6368_P1_SHIFT       0
55 #define DMIPSPLLCFG_6368_P1_MASK        (0xf << DMIPSPLLCFG_6368_P1_SHIFT)
56 #define DMIPSPLLCFG_6368_P2_SHIFT       4
57 #define DMIPSPLLCFG_6368_P2_MASK        (0xf << DMIPSPLLCFG_6368_P2_SHIFT)
58 #define DMIPSPLLCFG_6368_NDIV_SHIFT     16
59 #define DMIPSPLLCFG_6368_NDIV_MASK      (0x1ff << DMIPSPLLCFG_6368_NDIV_SHIFT)
60 #define REG_BCM6368_DDR_DMIPSPLLDIV     0x12a4
61 #define DMIPSPLLDIV_6368_MDIV_SHIFT     0
62 #define DMIPSPLLDIV_6368_MDIV_MASK      (0xff << DMIPSPLLDIV_6368_MDIV_SHIFT)
63
64 #define REG_BCM63268_MISC_STRAPBUS      0x1814
65 #define STRAPBUS_63268_FCVO_SHIFT       21
66 #define STRAPBUS_63268_FCVO_MASK        (0xf << STRAPBUS_63268_FCVO_SHIFT)
67
68 struct bmips_cpu_priv;
69
70 struct bmips_cpu_hw {
71         int (*get_cpu_desc)(struct bmips_cpu_priv *priv, char *buf, int size);
72         ulong (*get_cpu_freq)(struct bmips_cpu_priv *);
73         int (*get_cpu_count)(struct bmips_cpu_priv *);
74 };
75
76 struct bmips_cpu_priv {
77         void __iomem *regs;
78         const struct bmips_cpu_hw *hw;
79 };
80
81 /* Specific CPU Ops */
82 static int bmips_short_cpu_desc(struct bmips_cpu_priv *priv, char *buf,
83                                 int size)
84 {
85         unsigned short cpu_id;
86         unsigned char cpu_rev;
87         u32 val;
88
89         val = readl_be(priv->regs);
90         cpu_id = (val & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT;
91         cpu_rev = (val & REV_REVID_MASK) >> REV_REVID_SHIFT;
92
93         snprintf(buf, size, "BCM%04X%02X", cpu_id, cpu_rev);
94
95         return 0;
96 }
97
98 static int bmips_long_cpu_desc(struct bmips_cpu_priv *priv, char *buf,
99                                 int size)
100 {
101         unsigned int cpu_id;
102         unsigned char cpu_rev;
103         u32 val;
104
105         val = readl_be(priv->regs);
106         cpu_id = (val & REV_LONG_CHIPID_MASK) >> REV_LONG_CHIPID_SHIFT;
107         cpu_rev = (val & REV_REVID_MASK) >> REV_REVID_SHIFT;
108
109         snprintf(buf, size, "BCM%05X%02X", cpu_id, cpu_rev);
110
111         return 0;
112 }
113
114 static ulong bcm3380_get_cpu_freq(struct bmips_cpu_priv *priv)
115 {
116         return 333000000;
117 }
118
119 static ulong bcm6318_get_cpu_freq(struct bmips_cpu_priv *priv)
120 {
121         unsigned int mips_pll_fcvo;
122
123         mips_pll_fcvo = readl_be(priv->regs + REG_BCM6318_STRAP_OVRDBUS);
124         mips_pll_fcvo = (mips_pll_fcvo & OVRDBUS_6318_FREQ_MASK)
125                         >> OVRDBUS_6318_FREQ_SHIFT;
126
127         switch (mips_pll_fcvo) {
128         case 0:
129                 return 166000000;
130         case 1:
131                 return 400000000;
132         case 2:
133                 return 250000000;
134         case 3:
135                 return 333000000;
136         default:
137                 return 0;
138         }
139 }
140
141 static ulong bcm6328_get_cpu_freq(struct bmips_cpu_priv *priv)
142 {
143         unsigned int mips_pll_fcvo;
144
145         mips_pll_fcvo = readl_be(priv->regs + REG_BCM6328_MISC_STRAPBUS);
146         mips_pll_fcvo = (mips_pll_fcvo & STRAPBUS_6328_FCVO_MASK)
147                         >> STRAPBUS_6328_FCVO_SHIFT;
148
149         switch (mips_pll_fcvo) {
150         case 0x12:
151         case 0x14:
152         case 0x19:
153                 return 160000000;
154         case 0x1c:
155                 return 192000000;
156         case 0x13:
157         case 0x15:
158                 return 200000000;
159         case 0x1a:
160                 return 384000000;
161         case 0x16:
162                 return 400000000;
163         default:
164                 return 320000000;
165         }
166 }
167
168 static ulong bcm6338_get_cpu_freq(struct bmips_cpu_priv *priv)
169 {
170         return 240000000;
171 }
172
173 static ulong bcm6348_get_cpu_freq(struct bmips_cpu_priv *priv)
174 {
175         unsigned int tmp, n1, n2, m1;
176
177         tmp = readl_be(priv->regs + REG_BCM6348_PERF_MIPSPLLCFG);
178         n1 = (tmp & MIPSPLLCFG_6348_N1_MASK) >> MIPSPLLCFG_6348_N1_SHIFT;
179         n2 = (tmp & MIPSPLLCFG_6348_N2_MASK) >> MIPSPLLCFG_6348_N2_SHIFT;
180         m1 = (tmp & MIPSPLLCFG_6348_M1CPU_MASK) >> MIPSPLLCFG_6348_M1CPU_SHIFT;
181
182         return (16 * 1000000 * (n1 + 1) * (n2 + 2)) / (m1 + 1);
183 }
184
185 static ulong bcm6358_get_cpu_freq(struct bmips_cpu_priv *priv)
186 {
187         unsigned int tmp, n1, n2, m1;
188
189         tmp = readl_be(priv->regs + REG_BCM6358_DDR_DMIPSPLLCFG);
190         n1 = (tmp & DMIPSPLLCFG_6358_N1_MASK) >> DMIPSPLLCFG_6358_N1_SHIFT;
191         n2 = (tmp & DMIPSPLLCFG_6358_N2_MASK) >> DMIPSPLLCFG_6358_N2_SHIFT;
192         m1 = (tmp & DMIPSPLLCFG_6358_M1_MASK) >> DMIPSPLLCFG_6358_M1_SHIFT;
193
194         return (16 * 1000000 * n1 * n2) / m1;
195 }
196
197 static ulong bcm6368_get_cpu_freq(struct bmips_cpu_priv *priv)
198 {
199         unsigned int tmp, p1, p2, ndiv, m1;
200
201         tmp = readl_be(priv->regs + REG_BCM6368_DDR_DMIPSPLLCFG);
202         p1 = (tmp & DMIPSPLLCFG_6368_P1_MASK) >> DMIPSPLLCFG_6368_P1_SHIFT;
203         p2 = (tmp & DMIPSPLLCFG_6368_P2_MASK) >> DMIPSPLLCFG_6368_P2_SHIFT;
204         ndiv = (tmp & DMIPSPLLCFG_6368_NDIV_MASK) >>
205                DMIPSPLLCFG_6368_NDIV_SHIFT;
206
207         tmp = readl_be(priv->regs + REG_BCM6368_DDR_DMIPSPLLDIV);
208         m1 = (tmp & DMIPSPLLDIV_6368_MDIV_MASK) >> DMIPSPLLDIV_6368_MDIV_SHIFT;
209
210         return (((64 * 1000000) / p1) * p2 * ndiv) / m1;
211 }
212
213 static ulong bcm63268_get_cpu_freq(struct bmips_cpu_priv *priv)
214 {
215         unsigned int mips_pll_fcvo;
216
217         mips_pll_fcvo = readl_be(priv->regs + REG_BCM63268_MISC_STRAPBUS);
218         mips_pll_fcvo = (mips_pll_fcvo & STRAPBUS_63268_FCVO_MASK)
219                         >> STRAPBUS_63268_FCVO_SHIFT;
220
221         switch (mips_pll_fcvo) {
222         case 0x3:
223         case 0xe:
224                 return 320000000;
225         case 0xa:
226                 return 333000000;
227         case 0x2:
228         case 0xb:
229         case 0xf:
230                 return 400000000;
231         default:
232                 return 0;
233         }
234 }
235
236 static int bcm6328_get_cpu_count(struct bmips_cpu_priv *priv)
237 {
238         u32 val = readl_be(priv->regs + REG_BCM6328_OTP);
239
240         if (val & BCM6328_TP1_DISABLED)
241                 return 1;
242         else
243                 return 2;
244 }
245
246 static int bcm6345_get_cpu_count(struct bmips_cpu_priv *priv)
247 {
248         return 1;
249 }
250
251 static int bcm6358_get_cpu_count(struct bmips_cpu_priv *priv)
252 {
253         return 2;
254 }
255
256 static const struct bmips_cpu_hw bmips_cpu_bcm3380 = {
257         .get_cpu_desc = bmips_short_cpu_desc,
258         .get_cpu_freq = bcm3380_get_cpu_freq,
259         .get_cpu_count = bcm6358_get_cpu_count,
260 };
261
262 static const struct bmips_cpu_hw bmips_cpu_bcm6318 = {
263         .get_cpu_desc = bmips_short_cpu_desc,
264         .get_cpu_freq = bcm6318_get_cpu_freq,
265         .get_cpu_count = bcm6345_get_cpu_count,
266 };
267
268 static const struct bmips_cpu_hw bmips_cpu_bcm6328 = {
269         .get_cpu_desc = bmips_long_cpu_desc,
270         .get_cpu_freq = bcm6328_get_cpu_freq,
271         .get_cpu_count = bcm6328_get_cpu_count,
272 };
273
274 static const struct bmips_cpu_hw bmips_cpu_bcm6338 = {
275         .get_cpu_desc = bmips_short_cpu_desc,
276         .get_cpu_freq = bcm6338_get_cpu_freq,
277         .get_cpu_count = bcm6345_get_cpu_count,
278 };
279
280 static const struct bmips_cpu_hw bmips_cpu_bcm6348 = {
281         .get_cpu_desc = bmips_short_cpu_desc,
282         .get_cpu_freq = bcm6348_get_cpu_freq,
283         .get_cpu_count = bcm6345_get_cpu_count,
284 };
285
286 static const struct bmips_cpu_hw bmips_cpu_bcm6358 = {
287         .get_cpu_desc = bmips_short_cpu_desc,
288         .get_cpu_freq = bcm6358_get_cpu_freq,
289         .get_cpu_count = bcm6358_get_cpu_count,
290 };
291
292 static const struct bmips_cpu_hw bmips_cpu_bcm6368 = {
293         .get_cpu_desc = bmips_short_cpu_desc,
294         .get_cpu_freq = bcm6368_get_cpu_freq,
295         .get_cpu_count = bcm6358_get_cpu_count,
296 };
297
298 static const struct bmips_cpu_hw bmips_cpu_bcm63268 = {
299         .get_cpu_desc = bmips_long_cpu_desc,
300         .get_cpu_freq = bcm63268_get_cpu_freq,
301         .get_cpu_count = bcm6358_get_cpu_count,
302 };
303
304 /* Generic CPU Ops */
305 static int bmips_cpu_get_desc(struct udevice *dev, char *buf, int size)
306 {
307         struct bmips_cpu_priv *priv = dev_get_priv(dev);
308         const struct bmips_cpu_hw *hw = priv->hw;
309
310         return hw->get_cpu_desc(priv, buf, size);
311 }
312
313 static int bmips_cpu_get_info(struct udevice *dev, struct cpu_info *info)
314 {
315         struct bmips_cpu_priv *priv = dev_get_priv(dev);
316         const struct bmips_cpu_hw *hw = priv->hw;
317
318         info->cpu_freq = hw->get_cpu_freq(priv);
319         info->features = BIT(CPU_FEAT_L1_CACHE);
320         info->features |= BIT(CPU_FEAT_MMU);
321         info->features |= BIT(CPU_FEAT_DEVICE_ID);
322
323         return 0;
324 }
325
326 static int bmips_cpu_get_count(struct udevice *dev)
327 {
328         struct bmips_cpu_priv *priv = dev_get_priv(dev);
329         const struct bmips_cpu_hw *hw = priv->hw;
330
331         return hw->get_cpu_count(priv);
332 }
333
334 static int bmips_cpu_get_vendor(struct udevice *dev, char *buf, int size)
335 {
336         snprintf(buf, size, "Broadcom");
337
338         return 0;
339 }
340
341 static const struct cpu_ops bmips_cpu_ops = {
342         .get_desc = bmips_cpu_get_desc,
343         .get_info = bmips_cpu_get_info,
344         .get_count = bmips_cpu_get_count,
345         .get_vendor = bmips_cpu_get_vendor,
346 };
347
348 /* BMIPS CPU driver */
349 int bmips_cpu_bind(struct udevice *dev)
350 {
351         struct cpu_platdata *plat = dev_get_parent_platdata(dev);
352
353         plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
354                 "reg", -1);
355         plat->device_id = read_c0_prid();
356
357         return 0;
358 }
359
360 int bmips_cpu_probe(struct udevice *dev)
361 {
362         struct bmips_cpu_priv *priv = dev_get_priv(dev);
363         const struct bmips_cpu_hw *hw =
364                 (const struct bmips_cpu_hw *)dev_get_driver_data(dev);
365         fdt_addr_t addr;
366         fdt_size_t size;
367
368         addr = devfdt_get_addr_size_index(dev_get_parent(dev), 0, &size);
369         if (addr == FDT_ADDR_T_NONE)
370                 return -EINVAL;
371
372         priv->regs = ioremap(addr, size);
373         priv->hw = hw;
374
375         return 0;
376 }
377
378 static const struct udevice_id bmips_cpu_ids[] = {
379         {
380                 .compatible = "brcm,bcm3380-cpu",
381                 .data = (ulong)&bmips_cpu_bcm3380,
382         }, {
383                 .compatible = "brcm,bcm6318-cpu",
384                 .data = (ulong)&bmips_cpu_bcm6318,
385         }, {
386                 .compatible = "brcm,bcm6328-cpu",
387                 .data = (ulong)&bmips_cpu_bcm6328,
388         }, {
389                 .compatible = "brcm,bcm6338-cpu",
390                 .data = (ulong)&bmips_cpu_bcm6338,
391         }, {
392                 .compatible = "brcm,bcm6348-cpu",
393                 .data = (ulong)&bmips_cpu_bcm6348,
394         }, {
395                 .compatible = "brcm,bcm6358-cpu",
396                 .data = (ulong)&bmips_cpu_bcm6358,
397         }, {
398                 .compatible = "brcm,bcm6368-cpu",
399                 .data = (ulong)&bmips_cpu_bcm6368,
400         }, {
401                 .compatible = "brcm,bcm63268-cpu",
402                 .data = (ulong)&bmips_cpu_bcm63268,
403         },
404         { /* sentinel */ }
405 };
406
407 U_BOOT_DRIVER(bmips_cpu_drv) = {
408         .name = "bmips_cpu",
409         .id = UCLASS_CPU,
410         .of_match = bmips_cpu_ids,
411         .bind = bmips_cpu_bind,
412         .probe = bmips_cpu_probe,
413         .priv_auto_alloc_size = sizeof(struct bmips_cpu_priv),
414         .ops = &bmips_cpu_ops,
415         .flags = DM_FLAG_PRE_RELOC,
416 };
417
418 #ifdef CONFIG_DISPLAY_CPUINFO
419 int print_cpuinfo(void)
420 {
421         struct cpu_info cpu;
422         struct udevice *dev;
423         int err;
424         char desc[100];
425
426         err = uclass_get_device(UCLASS_CPU, 0, &dev);
427         if (err)
428                 return 0;
429
430         err = cpu_get_info(dev, &cpu);
431         if (err)
432                 return 0;
433
434         err = cpu_get_desc(dev, desc, sizeof(desc));
435         if (err)
436                 return 0;
437
438         printf("Chip ID: %s, MIPS: ", desc);
439         print_freq(cpu.cpu_freq, "\n");
440
441         return 0;
442 }
443 #endif