Merge branch '2022-03-10-platform-updates' into next
[platform/kernel/u-boot.git] / arch / arm / mach-mvebu / armada3700 / cpu.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2016 Stefan Roese <sr@denx.de>
4  * Copyright (C) 2020 Marek Behun <marek.behun@nic.cz>
5  */
6
7 #include <common.h>
8 #include <cpu_func.h>
9 #include <dm.h>
10 #include <fdtdec.h>
11 #include <fdt_support.h>
12 #include <init.h>
13 #include <asm/global_data.h>
14 #include <linux/bitops.h>
15 #include <linux/libfdt.h>
16 #include <linux/sizes.h>
17 #include <asm/io.h>
18 #include <asm/system.h>
19 #include <asm/arch/cpu.h>
20 #include <asm/arch/soc.h>
21 #include <asm/armv8/mmu.h>
22 #include <sort.h>
23
24 /* Armada 3700 */
25 #define MVEBU_GPIO_NB_REG_BASE          (MVEBU_REGISTER(0x13800))
26
27 #define MVEBU_TEST_PIN_LATCH_N          (MVEBU_GPIO_NB_REG_BASE + 0x8)
28 #define MVEBU_XTAL_MODE_MASK            BIT(9)
29 #define MVEBU_XTAL_MODE_OFFS            9
30 #define MVEBU_XTAL_CLOCK_25MHZ          0x0
31 #define MVEBU_XTAL_CLOCK_40MHZ          0x1
32
33 #define MVEBU_NB_WARM_RST_REG           (MVEBU_GPIO_NB_REG_BASE + 0x40)
34 #define MVEBU_NB_WARM_RST_MAGIC_NUM     0x1d1e
35
36 /* Armada 3700 CPU Address Decoder registers */
37 #define MVEBU_CPU_DEC_WIN_REG_BASE      (size_t)(MVEBU_REGISTER(0xcf00))
38 #define MVEBU_CPU_DEC_WIN_CTRL(w) \
39         (MVEBU_CPU_DEC_WIN_REG_BASE + ((w) << 4))
40 #define MVEBU_CPU_DEC_WIN_CTRL_EN       BIT(0)
41 #define MVEBU_CPU_DEC_WIN_CTRL_TGT_MASK 0xf
42 #define MVEBU_CPU_DEC_WIN_CTRL_TGT_OFFS 4
43 #define MVEBU_CPU_DEC_WIN_CTRL_TGT_DRAM 0
44 #define MVEBU_CPU_DEC_WIN_CTRL_TGT_PCIE 2
45 #define MVEBU_CPU_DEC_WIN_SIZE(w)       (MVEBU_CPU_DEC_WIN_CTRL(w) + 0x4)
46 #define MVEBU_CPU_DEC_WIN_BASE(w)       (MVEBU_CPU_DEC_WIN_CTRL(w) + 0x8)
47 #define MVEBU_CPU_DEC_WIN_REMAP(w)      (MVEBU_CPU_DEC_WIN_CTRL(w) + 0xc)
48 #define MVEBU_CPU_DEC_WIN_GRANULARITY   16
49 #define MVEBU_CPU_DEC_WINS              5
50 #define MVEBU_CPU_DEC_CCI_BASE          (MVEBU_CPU_DEC_WIN_REG_BASE + 0xe0)
51 #define MVEBU_CPU_DEC_ROM_BASE          (MVEBU_CPU_DEC_WIN_REG_BASE + 0xf4)
52
53 #define MAX_MEM_MAP_REGIONS             (MVEBU_CPU_DEC_WINS + 4)
54
55 #define A3700_PTE_BLOCK_NORMAL \
56         (PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE)
57 #define A3700_PTE_BLOCK_DEVICE \
58         (PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE)
59
60 DECLARE_GLOBAL_DATA_PTR;
61
62 static struct mm_region mvebu_mem_map[MAX_MEM_MAP_REGIONS] = {
63         {
64                 /*
65                  * SRAM, MMIO regions
66                  * Don't remove this, build_mem_map needs it.
67                  */
68                 .phys = SOC_REGS_PHY_BASE,
69                 .virt = SOC_REGS_PHY_BASE,
70                 .size = 0x02000000UL,   /* 32MiB internal registers */
71                 .attrs = A3700_PTE_BLOCK_DEVICE
72         },
73 };
74
75 struct mm_region *mem_map = mvebu_mem_map;
76
77 static int get_cpu_dec_win(int win, u32 *tgt, u32 *base, u32 *size)
78 {
79         u32 reg;
80
81         reg = readl(MVEBU_CPU_DEC_WIN_CTRL(win));
82         if (!(reg & MVEBU_CPU_DEC_WIN_CTRL_EN))
83                 return -1;
84
85         if (tgt) {
86                 reg >>= MVEBU_CPU_DEC_WIN_CTRL_TGT_OFFS;
87                 reg &= MVEBU_CPU_DEC_WIN_CTRL_TGT_MASK;
88                 *tgt = reg;
89         }
90
91         if (base) {
92                 reg = readl(MVEBU_CPU_DEC_WIN_BASE(win));
93                 *base = reg << MVEBU_CPU_DEC_WIN_GRANULARITY;
94         }
95
96         if (size) {
97                 /*
98                  * Window size is encoded as the number of 1s from LSB to MSB,
99                  * followed by 0s. The number of 1s specifies the size in 64 KiB
100                  * granularity.
101                  */
102                 reg = readl(MVEBU_CPU_DEC_WIN_SIZE(win));
103                 *size = ((reg + 1) << MVEBU_CPU_DEC_WIN_GRANULARITY);
104         }
105
106         return 0;
107 }
108
109 /*
110  * Builds mem_map according to CPU Address Decoder settings, which were set by
111  * the TIMH image on the Cortex-M3 secure processor, or by ARM Trusted Firmware
112  */
113 static void build_mem_map(void)
114 {
115         int win, region;
116         u32 reg;
117
118         region = 1;
119
120         /* CCI-400 */
121         reg = readl(MVEBU_CPU_DEC_CCI_BASE);
122         mvebu_mem_map[region].phys = reg << 20;
123         mvebu_mem_map[region].virt = reg << 20;
124         mvebu_mem_map[region].size = SZ_64K;
125         mvebu_mem_map[region].attrs = A3700_PTE_BLOCK_DEVICE;
126         ++region;
127
128         /* AP BootROM */
129         reg = readl(MVEBU_CPU_DEC_ROM_BASE);
130         mvebu_mem_map[region].phys = reg << 20;
131         mvebu_mem_map[region].virt = reg << 20;
132         mvebu_mem_map[region].size = SZ_1M;
133         mvebu_mem_map[region].attrs = A3700_PTE_BLOCK_NORMAL;
134         ++region;
135
136         for (win = 0; win < MVEBU_CPU_DEC_WINS; ++win) {
137                 u32 base, tgt, size;
138                 u64 attrs;
139
140                 /* skip disabled windows */
141                 if (get_cpu_dec_win(win, &tgt, &base, &size))
142                         continue;
143
144                 if (tgt == MVEBU_CPU_DEC_WIN_CTRL_TGT_DRAM)
145                         attrs = A3700_PTE_BLOCK_NORMAL;
146                 else if (tgt == MVEBU_CPU_DEC_WIN_CTRL_TGT_PCIE)
147                         attrs = A3700_PTE_BLOCK_DEVICE;
148                 else
149                         /* skip windows with other targets */
150                         continue;
151
152                 mvebu_mem_map[region].phys = base;
153                 mvebu_mem_map[region].virt = base;
154                 mvebu_mem_map[region].size = size;
155                 mvebu_mem_map[region].attrs = attrs;
156                 ++region;
157         }
158
159         /* add list terminator */
160         mvebu_mem_map[region].size = 0;
161         mvebu_mem_map[region].attrs = 0;
162 }
163
164 void enable_caches(void)
165 {
166         icache_enable();
167         dcache_enable();
168 }
169
170 int a3700_dram_init(void)
171 {
172         int win;
173
174         build_mem_map();
175
176         gd->ram_size = 0;
177         for (win = 0; win < MVEBU_CPU_DEC_WINS; ++win) {
178                 u32 base, tgt, size;
179
180                 /* skip disabled windows */
181                 if (get_cpu_dec_win(win, &tgt, &base, &size))
182                         continue;
183
184                 /* skip non-DRAM windows */
185                 if (tgt != MVEBU_CPU_DEC_WIN_CTRL_TGT_DRAM)
186                         continue;
187
188                 /*
189                  * It is possible that one image was built for boards with
190                  * different RAM sizes, for example 512 MiB and 1 GiB.
191                  * We therefore try to determine the actual RAM size in the
192                  * window with get_ram_size.
193                  */
194                 gd->ram_size += get_ram_size((void *)(size_t)base, size);
195         }
196
197         return 0;
198 }
199
200 struct a3700_dram_window {
201         size_t base, size;
202 };
203
204 static int dram_win_cmp(const void *a, const void *b)
205 {
206         size_t ab, bb;
207
208         ab = ((const struct a3700_dram_window *)a)->base;
209         bb = ((const struct a3700_dram_window *)b)->base;
210
211         if (ab < bb)
212                 return -1;
213         else if (ab > bb)
214                 return 1;
215         else
216                 return 0;
217 }
218
219 int a3700_dram_init_banksize(void)
220 {
221         struct a3700_dram_window dram_wins[MVEBU_CPU_DEC_WINS];
222         int bank, win, ndram_wins;
223         u32 last_end;
224         size_t size;
225
226         ndram_wins = 0;
227         for (win = 0; win < MVEBU_CPU_DEC_WINS; ++win) {
228                 u32 base, tgt, size;
229
230                 /* skip disabled windows */
231                 if (get_cpu_dec_win(win, &tgt, &base, &size))
232                         continue;
233
234                 /* skip non-DRAM windows */
235                 if (tgt != MVEBU_CPU_DEC_WIN_CTRL_TGT_DRAM)
236                         continue;
237
238                 dram_wins[win].base = base;
239                 dram_wins[win].size = size;
240                 ++ndram_wins;
241         }
242
243         qsort(dram_wins, ndram_wins, sizeof(dram_wins[0]), dram_win_cmp);
244
245         bank = 0;
246         last_end = -1;
247
248         for (win = 0; win < ndram_wins; ++win) {
249                 /* again determining actual RAM size as in a3700_dram_init */
250                 size = get_ram_size((void *)dram_wins[win].base,
251                                     dram_wins[win].size);
252
253                 /*
254                  * Check if previous window ends as the current starts. If yes,
255                  * merge these windows into one "bank". This is possible by this
256                  * simple check thanks to mem_map regions being qsorted in
257                  * build_mem_map.
258                  */
259                 if (last_end == dram_wins[win].base) {
260                         gd->bd->bi_dram[bank - 1].size += size;
261                         last_end += size;
262                 } else {
263                         if (bank == CONFIG_NR_DRAM_BANKS) {
264                                 printf("Need more CONFIG_NR_DRAM_BANKS\n");
265                                 return -ENOBUFS;
266                         }
267
268                         gd->bd->bi_dram[bank].start = dram_wins[win].base;
269                         gd->bd->bi_dram[bank].size = size;
270                         last_end = dram_wins[win].base + size;
271                         ++bank;
272                 }
273         }
274
275         /*
276          * If there is more place for DRAM BANKS definitions than needed, fill
277          * the rest with zeros.
278          */
279         for (; bank < CONFIG_NR_DRAM_BANKS; ++bank) {
280                 gd->bd->bi_dram[bank].start = 0;
281                 gd->bd->bi_dram[bank].size = 0;
282         }
283
284         return 0;
285 }
286
287 static u32 find_pcie_window_base(void)
288 {
289         int win;
290
291         for (win = 0; win < MVEBU_CPU_DEC_WINS; ++win) {
292                 u32 base, tgt;
293
294                 /* skip disabled windows */
295                 if (get_cpu_dec_win(win, &tgt, &base, NULL))
296                         continue;
297
298                 if (tgt == MVEBU_CPU_DEC_WIN_CTRL_TGT_PCIE)
299                         return base;
300         }
301
302         return -1;
303 }
304
305 static int fdt_setprop_inplace_u32_partial(void *blob, int node,
306                                            const char *name,
307                                            u32 idx, u32 val)
308 {
309         val = cpu_to_fdt32(val);
310
311         return fdt_setprop_inplace_namelen_partial(blob, node, name,
312                                                    strlen(name),
313                                                    idx * sizeof(u32),
314                                                    &val, sizeof(u32));
315 }
316
317 int a3700_fdt_fix_pcie_regions(void *blob)
318 {
319         int acells, pacells, scells;
320         u32 base, fix_offset;
321         const u32 *ranges;
322         int node, pnode;
323         int ret, i, len;
324
325         base = find_pcie_window_base();
326         if (base == -1)
327                 return -ENOENT;
328
329         node = fdt_node_offset_by_compatible(blob, -1, "marvell,armada-3700-pcie");
330         if (node < 0)
331                 return node;
332
333         ranges = fdt_getprop(blob, node, "ranges", &len);
334         if (!ranges || len % sizeof(u32))
335                 return -ENOENT;
336
337         /*
338          * The "ranges" property is an array of
339          * { <child address> <parent address> <size in child address space> }
340          *
341          * All 3 elements can span a diffent number of cells. Fetch their sizes.
342          */
343         pnode = fdt_parent_offset(blob, node);
344         acells = fdt_address_cells(blob, node);
345         pacells = fdt_address_cells(blob, pnode);
346         scells = fdt_size_cells(blob, node);
347
348         /* Child PCI addresses always use 3 cells */
349         if (acells != 3)
350                 return -ENOENT;
351
352         /* Calculate fixup offset from first child address (in last cell) */
353         fix_offset = base - fdt32_to_cpu(ranges[2]);
354
355         /* If fixup offset is zero then there is nothing to fix */
356         if (!fix_offset)
357                 return 0;
358
359         /*
360          * Fix address (last cell) of each child address and each parent
361          * address
362          */
363         for (i = 0; i < len / sizeof(u32); i += acells + pacells + scells) {
364                 int idx;
365
366                 /* fix child address */
367                 idx = i + acells - 1;
368                 ret = fdt_setprop_inplace_u32_partial(blob, node, "ranges", idx,
369                                                       fdt32_to_cpu(ranges[idx]) +
370                                                       fix_offset);
371                 if (ret)
372                         return ret;
373
374                 /* fix parent address */
375                 idx = i + acells + pacells - 1;
376                 ret = fdt_setprop_inplace_u32_partial(blob, node, "ranges", idx,
377                                                       fdt32_to_cpu(ranges[idx]) +
378                                                       fix_offset);
379                 if (ret)
380                         return ret;
381         }
382
383         return 0;
384 }
385
386 void reset_cpu(void)
387 {
388         /*
389          * Write magic number of 0x1d1e to North Bridge Warm Reset register
390          * to trigger warm reset
391          */
392         writel(MVEBU_NB_WARM_RST_MAGIC_NUM, MVEBU_NB_WARM_RST_REG);
393 }
394
395 /*
396  * get_ref_clk
397  *
398  * return: reference clock in MHz (25 or 40)
399  */
400 u32 get_ref_clk(void)
401 {
402         u32 regval;
403
404         regval = (readl(MVEBU_TEST_PIN_LATCH_N) & MVEBU_XTAL_MODE_MASK) >>
405                 MVEBU_XTAL_MODE_OFFS;
406
407         if (regval == MVEBU_XTAL_CLOCK_25MHZ)
408                 return 25;
409         else
410                 return 40;
411 }