Merge tag 'ti-v2021.07-rc1' of https://source.denx.de/u-boot/custodians/u-boot-ti
[pandora-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 <init.h>
12 #include <asm/global_data.h>
13 #include <linux/bitops.h>
14 #include <linux/libfdt.h>
15 #include <asm/io.h>
16 #include <asm/system.h>
17 #include <asm/arch/cpu.h>
18 #include <asm/arch/soc.h>
19 #include <asm/armv8/mmu.h>
20 #include <sort.h>
21
22 /* Armada 3700 */
23 #define MVEBU_GPIO_NB_REG_BASE          (MVEBU_REGISTER(0x13800))
24
25 #define MVEBU_TEST_PIN_LATCH_N          (MVEBU_GPIO_NB_REG_BASE + 0x8)
26 #define MVEBU_XTAL_MODE_MASK            BIT(9)
27 #define MVEBU_XTAL_MODE_OFFS            9
28 #define MVEBU_XTAL_CLOCK_25MHZ          0x0
29 #define MVEBU_XTAL_CLOCK_40MHZ          0x1
30
31 #define MVEBU_NB_WARM_RST_REG           (MVEBU_GPIO_NB_REG_BASE + 0x40)
32 #define MVEBU_NB_WARM_RST_MAGIC_NUM     0x1d1e
33
34 /* Armada 3700 CPU Address Decoder registers */
35 #define MVEBU_CPU_DEC_WIN_REG_BASE      (size_t)(MVEBU_REGISTER(0xcf00))
36 #define MVEBU_CPU_DEC_WIN_CTRL(w) \
37         (MVEBU_CPU_DEC_WIN_REG_BASE + ((w) << 4))
38 #define MVEBU_CPU_DEC_WIN_CTRL_EN       BIT(0)
39 #define MVEBU_CPU_DEC_WIN_CTRL_TGT_MASK 0xf
40 #define MVEBU_CPU_DEC_WIN_CTRL_TGT_OFFS 4
41 #define MVEBU_CPU_DEC_WIN_CTRL_TGT_DRAM 0
42 #define MVEBU_CPU_DEC_WIN_CTRL_TGT_PCIE 2
43 #define MVEBU_CPU_DEC_WIN_SIZE(w)       (MVEBU_CPU_DEC_WIN_CTRL(w) + 0x4)
44 #define MVEBU_CPU_DEC_WIN_BASE(w)       (MVEBU_CPU_DEC_WIN_CTRL(w) + 0x8)
45 #define MVEBU_CPU_DEC_WIN_REMAP(w)      (MVEBU_CPU_DEC_WIN_CTRL(w) + 0xc)
46 #define MVEBU_CPU_DEC_WIN_GRANULARITY   16
47 #define MVEBU_CPU_DEC_WINS              5
48
49 #define MAX_MEM_MAP_REGIONS             (MVEBU_CPU_DEC_WINS + 2)
50
51 #define A3700_PTE_BLOCK_NORMAL \
52         (PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE)
53 #define A3700_PTE_BLOCK_DEVICE \
54         (PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE)
55
56 #define PCIE_PATH                       "/soc/pcie@d0070000"
57
58 DECLARE_GLOBAL_DATA_PTR;
59
60 static struct mm_region mvebu_mem_map[MAX_MEM_MAP_REGIONS] = {
61         {
62                 /*
63                  * SRAM, MMIO regions
64                  * Don't remove this, a3700_build_mem_map needs it.
65                  */
66                 .phys = SOC_REGS_PHY_BASE,
67                 .virt = SOC_REGS_PHY_BASE,
68                 .size = 0x02000000UL,   /* 32MiB internal registers */
69                 .attrs = A3700_PTE_BLOCK_DEVICE
70         },
71 };
72
73 struct mm_region *mem_map = mvebu_mem_map;
74
75 static int get_cpu_dec_win(int win, u32 *tgt, u32 *base, u32 *size)
76 {
77         u32 reg;
78
79         reg = readl(MVEBU_CPU_DEC_WIN_CTRL(win));
80         if (!(reg & MVEBU_CPU_DEC_WIN_CTRL_EN))
81                 return -1;
82
83         if (tgt) {
84                 reg >>= MVEBU_CPU_DEC_WIN_CTRL_TGT_OFFS;
85                 reg &= MVEBU_CPU_DEC_WIN_CTRL_TGT_MASK;
86                 *tgt = reg;
87         }
88
89         if (base) {
90                 reg = readl(MVEBU_CPU_DEC_WIN_BASE(win));
91                 *base = reg << MVEBU_CPU_DEC_WIN_GRANULARITY;
92         }
93
94         if (size) {
95                 /*
96                  * Window size is encoded as the number of 1s from LSB to MSB,
97                  * followed by 0s. The number of 1s specifies the size in 64 KiB
98                  * granularity.
99                  */
100                 reg = readl(MVEBU_CPU_DEC_WIN_SIZE(win));
101                 *size = ((reg + 1) << MVEBU_CPU_DEC_WIN_GRANULARITY);
102         }
103
104         return 0;
105 }
106
107 /*
108  * Builds mem_map according to CPU Address Decoder settings, which were set by
109  * the TIMH image on the Cortex-M3 secure processor, or by ARM Trusted Firmware
110  */
111 static void build_mem_map(void)
112 {
113         int win, region;
114
115         region = 1;
116         for (win = 0; win < MVEBU_CPU_DEC_WINS; ++win) {
117                 u32 base, tgt, size;
118                 u64 attrs;
119
120                 /* skip disabled windows */
121                 if (get_cpu_dec_win(win, &tgt, &base, &size))
122                         continue;
123
124                 if (tgt == MVEBU_CPU_DEC_WIN_CTRL_TGT_DRAM)
125                         attrs = A3700_PTE_BLOCK_NORMAL;
126                 else if (tgt == MVEBU_CPU_DEC_WIN_CTRL_TGT_PCIE)
127                         attrs = A3700_PTE_BLOCK_DEVICE;
128                 else
129                         /* skip windows with other targets */
130                         continue;
131
132                 mvebu_mem_map[region].phys = base;
133                 mvebu_mem_map[region].virt = base;
134                 mvebu_mem_map[region].size = size;
135                 mvebu_mem_map[region].attrs = attrs;
136                 ++region;
137         }
138
139         /* add list terminator */
140         mvebu_mem_map[region].size = 0;
141         mvebu_mem_map[region].attrs = 0;
142 }
143
144 void enable_caches(void)
145 {
146         build_mem_map();
147
148         icache_enable();
149         dcache_enable();
150 }
151
152 int a3700_dram_init(void)
153 {
154         int win;
155
156         gd->ram_size = 0;
157         for (win = 0; win < MVEBU_CPU_DEC_WINS; ++win) {
158                 u32 base, tgt, size;
159
160                 /* skip disabled windows */
161                 if (get_cpu_dec_win(win, &tgt, &base, &size))
162                         continue;
163
164                 /* skip non-DRAM windows */
165                 if (tgt != MVEBU_CPU_DEC_WIN_CTRL_TGT_DRAM)
166                         continue;
167
168                 /*
169                  * It is possible that one image was built for boards with
170                  * different RAM sizes, for example 512 MiB and 1 GiB.
171                  * We therefore try to determine the actual RAM size in the
172                  * window with get_ram_size.
173                  */
174                 gd->ram_size += get_ram_size((void *)(size_t)base, size);
175         }
176
177         return 0;
178 }
179
180 struct a3700_dram_window {
181         size_t base, size;
182 };
183
184 static int dram_win_cmp(const void *a, const void *b)
185 {
186         size_t ab, bb;
187
188         ab = ((const struct a3700_dram_window *)a)->base;
189         bb = ((const struct a3700_dram_window *)b)->base;
190
191         if (ab < bb)
192                 return -1;
193         else if (ab > bb)
194                 return 1;
195         else
196                 return 0;
197 }
198
199 int a3700_dram_init_banksize(void)
200 {
201         struct a3700_dram_window dram_wins[MVEBU_CPU_DEC_WINS];
202         int bank, win, ndram_wins;
203         u32 last_end;
204         size_t size;
205
206         ndram_wins = 0;
207         for (win = 0; win < MVEBU_CPU_DEC_WINS; ++win) {
208                 u32 base, tgt, size;
209
210                 /* skip disabled windows */
211                 if (get_cpu_dec_win(win, &tgt, &base, &size))
212                         continue;
213
214                 /* skip non-DRAM windows */
215                 if (tgt != MVEBU_CPU_DEC_WIN_CTRL_TGT_DRAM)
216                         continue;
217
218                 dram_wins[win].base = base;
219                 dram_wins[win].size = size;
220                 ++ndram_wins;
221         }
222
223         qsort(dram_wins, ndram_wins, sizeof(dram_wins[0]), dram_win_cmp);
224
225         bank = 0;
226         last_end = -1;
227
228         for (win = 0; win < ndram_wins; ++win) {
229                 /* again determining actual RAM size as in a3700_dram_init */
230                 size = get_ram_size((void *)dram_wins[win].base,
231                                     dram_wins[win].size);
232
233                 /*
234                  * Check if previous window ends as the current starts. If yes,
235                  * merge these windows into one "bank". This is possible by this
236                  * simple check thanks to mem_map regions being qsorted in
237                  * build_mem_map.
238                  */
239                 if (last_end == dram_wins[win].base) {
240                         gd->bd->bi_dram[bank - 1].size += size;
241                         last_end += size;
242                 } else {
243                         if (bank == CONFIG_NR_DRAM_BANKS) {
244                                 printf("Need more CONFIG_NR_DRAM_BANKS\n");
245                                 return -ENOBUFS;
246                         }
247
248                         gd->bd->bi_dram[bank].start = dram_wins[win].base;
249                         gd->bd->bi_dram[bank].size = size;
250                         last_end = dram_wins[win].base + size;
251                         ++bank;
252                 }
253         }
254
255         /*
256          * If there is more place for DRAM BANKS definitions than needed, fill
257          * the rest with zeros.
258          */
259         for (; bank < CONFIG_NR_DRAM_BANKS; ++bank) {
260                 gd->bd->bi_dram[bank].start = 0;
261                 gd->bd->bi_dram[bank].size = 0;
262         }
263
264         return 0;
265 }
266
267 static u32 find_pcie_window_base(void)
268 {
269         int win;
270
271         for (win = 0; win < MVEBU_CPU_DEC_WINS; ++win) {
272                 u32 base, tgt;
273
274                 /* skip disabled windows */
275                 if (get_cpu_dec_win(win, &tgt, &base, NULL))
276                         continue;
277
278                 if (tgt == MVEBU_CPU_DEC_WIN_CTRL_TGT_PCIE)
279                         return base;
280         }
281
282         return -1;
283 }
284
285 int a3700_fdt_fix_pcie_regions(void *blob)
286 {
287         u32 new_ranges[14], base;
288         const u32 *ranges;
289         int node, len;
290
291         node = fdt_path_offset(blob, PCIE_PATH);
292         if (node < 0)
293                 return node;
294
295         ranges = fdt_getprop(blob, node, "ranges", &len);
296         if (!ranges)
297                 return -ENOENT;
298
299         if (len != sizeof(new_ranges))
300                 return -EINVAL;
301
302         memcpy(new_ranges, ranges, len);
303
304         base = find_pcie_window_base();
305         if (base == -1)
306                 return -ENOENT;
307
308         new_ranges[2] = cpu_to_fdt32(base);
309         new_ranges[4] = new_ranges[2];
310
311         new_ranges[9] = cpu_to_fdt32(base + 0x1000000);
312         new_ranges[11] = new_ranges[9];
313
314         return fdt_setprop_inplace(blob, node, "ranges", new_ranges, len);
315 }
316
317 void reset_cpu(void)
318 {
319         /*
320          * Write magic number of 0x1d1e to North Bridge Warm Reset register
321          * to trigger warm reset
322          */
323         writel(MVEBU_NB_WARM_RST_MAGIC_NUM, MVEBU_NB_WARM_RST_REG);
324 }
325
326 /*
327  * get_ref_clk
328  *
329  * return: reference clock in MHz (25 or 40)
330  */
331 u32 get_ref_clk(void)
332 {
333         u32 regval;
334
335         regval = (readl(MVEBU_TEST_PIN_LATCH_N) & MVEBU_XTAL_MODE_MASK) >>
336                 MVEBU_XTAL_MODE_OFFS;
337
338         if (regval == MVEBU_XTAL_CLOCK_25MHZ)
339                 return 25;
340         else
341                 return 40;
342 }