ARC: HSDK-4xD: add CSM configuration support
[platform/kernel/u-boot.git] / board / synopsys / hsdk / hsdk.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2018 Synopsys, Inc. All rights reserved.
4  * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
5  */
6
7 #include <common.h>
8 #include <config.h>
9 #include <cpu_func.h>
10 #include <env.h>
11 #include <init.h>
12 #include <irq_func.h>
13 #include <linux/printk.h>
14 #include <linux/kernel.h>
15 #include <linux/io.h>
16 #include <asm/arcregs.h>
17 #include <fdt_support.h>
18 #include <dwmmc.h>
19 #include <malloc.h>
20 #include <usb.h>
21
22 #include "clk-lib.h"
23 #include "env-lib.h"
24
25 DECLARE_GLOBAL_DATA_PTR;
26
27 #define ALL_CPU_MASK            GENMASK(NR_CPUS - 1, 0)
28 #define MASTER_CPU_ID           0
29 #define APERTURE_SHIFT          28
30 #define NO_CCM                  0x10
31 #define SLAVE_CPU_READY         0x12345678
32 #define BOOTSTAGE_1             1 /* after SP, FP setup, before HW init */
33 #define BOOTSTAGE_2             2 /* after HW init, before self halt */
34 #define BOOTSTAGE_3             3 /* after self halt */
35 #define BOOTSTAGE_4             4 /* before app launch */
36 #define BOOTSTAGE_5             5 /* after app launch, unreachable */
37
38 #define RESET_VECTOR_ADDR       0x0
39
40 #define CREG_BASE               (ARC_PERIPHERAL_BASE + 0x1000)
41 #define CREG_CPU_START          (CREG_BASE + 0x400)
42 #define CREG_CPU_START_MASK     0xF
43 #define CREG_CPU_START_POL      BIT(4)
44
45 #define SDIO_BASE               (ARC_PERIPHERAL_BASE + 0xA000)
46 #define SDIO_UHS_REG_EXT        (SDIO_BASE + 0x108)
47 #define SDIO_UHS_REG_EXT_DIV_2  (2 << 30)
48
49 /* Uncached access macros */
50 #define arc_read_uncached_32(ptr)       \
51 ({                                      \
52         unsigned int __ret;             \
53         __asm__ __volatile__(           \
54         "       ld.di %0, [%1]  \n"     \
55         : "=r"(__ret)                   \
56         : "r"(ptr));                    \
57         __ret;                          \
58 })
59
60 #define arc_write_uncached_32(ptr, data)\
61 ({                                      \
62         __asm__ __volatile__(           \
63         "       st.di %0, [%1]  \n"     \
64         :                               \
65         : "r"(data), "r"(ptr));         \
66 })
67
68 struct hsdk_env_core_ctl {
69         u32_env entry[NR_CPUS];
70         u32_env iccm[NR_CPUS];
71         u32_env dccm[NR_CPUS];
72 };
73
74 struct hsdk_env_common_ctl {
75         bool halt_on_boot;
76         u32_env core_mask;
77         u32_env cpu_freq;
78         u32_env axi_freq;
79         u32_env tun_freq;
80         u32_env nvlim;
81         u32_env icache;
82         u32_env dcache;
83         u32_env csm_location;
84         u32_env l2_cache;
85 };
86
87 /*
88  * Uncached cross-cpu structure. All CPUs must access to this structure fields
89  * only with arc_read_uncached_32() / arc_write_uncached_32() accessors (which
90  * implement ld.di / st.di instructions). Simultaneous cached and uncached
91  * access to this area will lead to data loss.
92  * We flush all data caches in board_early_init_r() as we don't want to have
93  * any dirty line in L1d$ or SL$ in this area.
94  */
95 struct hsdk_cross_cpu {
96         /* slave CPU ready flag */
97         u32 ready_flag;
98         /* address of the area, which can be used for stack by slave CPU */
99         u32 stack_ptr;
100         /* slave CPU status - bootstage number */
101         s32 status[NR_CPUS];
102
103         /*
104          * Slave CPU data - it is copy of corresponding fields in
105          * hsdk_env_core_ctl and hsdk_env_common_ctl structures which are
106          * required for slave CPUs initialization.
107          * This fields can be populated by copying from hsdk_env_core_ctl
108          * and hsdk_env_common_ctl structures with sync_cross_cpu_data()
109          * function.
110          */
111         u32 entry[NR_CPUS];
112         u32 iccm[NR_CPUS];
113         u32 dccm[NR_CPUS];
114
115         u32 core_mask;
116         u32 icache;
117         u32 dcache;
118
119         u8 cache_padding[ARCH_DMA_MINALIGN];
120 } __aligned(ARCH_DMA_MINALIGN);
121
122 /* Place for slave CPUs temporary stack */
123 static u32 slave_stack[256 * NR_CPUS] __aligned(ARCH_DMA_MINALIGN);
124
125 static struct hsdk_env_common_ctl env_common = {};
126 static struct hsdk_env_core_ctl env_core = {};
127 static struct hsdk_cross_cpu cross_cpu_data;
128
129 static const struct env_map_common env_map_common[] = {
130         { "core_mask",  ENV_HEX, true,  0x1, 0xF,       &env_common.core_mask },
131         { "non_volatile_limit", ENV_HEX, true, 0, 0xF,  &env_common.nvlim },
132         { "icache_ena", ENV_HEX, true,  0, 1,           &env_common.icache },
133         { "dcache_ena", ENV_HEX, true,  0, 1,           &env_common.dcache },
134 #if defined(CONFIG_BOARD_HSDK_4XD)
135         { "l2_cache_ena",       ENV_HEX, true,  0, 1,           &env_common.l2_cache },
136         { "csm_location",       ENV_HEX, true,  0, NO_CCM,      &env_common.csm_location },
137 #endif /* CONFIG_BOARD_HSDK_4XD */
138         {}
139 };
140
141 static const struct env_map_common env_map_clock[] = {
142         { "cpu_freq",   ENV_DEC, false, 100, 1000,      &env_common.cpu_freq },
143         { "axi_freq",   ENV_DEC, false, 200, 800,       &env_common.axi_freq },
144         { "tun_freq",   ENV_DEC, false, 0, 150,         &env_common.tun_freq },
145         {}
146 };
147
148 static const struct env_map_percpu env_map_core[] = {
149         { "core_iccm", ENV_HEX, true, {NO_CCM, 0, NO_CCM, 0}, {NO_CCM, 0xF, NO_CCM, 0xF}, &env_core.iccm },
150         { "core_dccm", ENV_HEX, true, {NO_CCM, 0, NO_CCM, 0}, {NO_CCM, 0xF, NO_CCM, 0xF}, &env_core.dccm },
151         {}
152 };
153
154 static const struct env_map_common env_map_mask[] = {
155         { "core_mask",  ENV_HEX, false, 0x1, 0xF,       &env_common.core_mask },
156         {}
157 };
158
159 static const struct env_map_percpu env_map_go[] = {
160         { "core_entry", ENV_HEX, true, {0, 0, 0, 0}, {U32_MAX, U32_MAX, U32_MAX, U32_MAX}, &env_core.entry },
161         {}
162 };
163
164 enum board_type {
165         T_BOARD_NONE,
166         T_BOARD_HSDK,
167         T_BOARD_HSDK_4XD
168 };
169
170 static inline enum board_type get_board_type_runtime(void)
171 {
172         u32 arc_id = read_aux_reg(ARC_AUX_IDENTITY) & 0xFF;
173
174         if (arc_id == 0x52)
175                 return T_BOARD_HSDK;
176         else if (arc_id == 0x54)
177                 return T_BOARD_HSDK_4XD;
178         else
179                 return T_BOARD_NONE;
180 }
181
182 static inline enum board_type get_board_type_config(void)
183 {
184         if (IS_ENABLED(CONFIG_BOARD_HSDK))
185                 return T_BOARD_HSDK;
186         else if (IS_ENABLED(CONFIG_BOARD_HSDK_4XD))
187                 return T_BOARD_HSDK_4XD;
188         else
189                 return T_BOARD_NONE;
190 }
191
192 static bool is_board_match_runtime(enum board_type type_req)
193 {
194         return get_board_type_runtime() == type_req;
195 }
196
197 static bool is_board_match_config(enum board_type type_req)
198 {
199         return get_board_type_config() == type_req;
200 }
201
202 static const char * board_name(enum board_type type)
203 {
204         switch (type) {
205                 case T_BOARD_HSDK:
206                         return "ARC HS Development Kit";
207                 case T_BOARD_HSDK_4XD:
208                         return "ARC HS4x/HS4xD Development Kit";
209                 default:
210                         return "?";
211         }
212 }
213
214 static bool board_mismatch(void)
215 {
216         return get_board_type_config() != get_board_type_runtime();
217 }
218
219 static void sync_cross_cpu_data(void)
220 {
221         u32 value;
222
223         for (u32 i = 0; i < NR_CPUS; i++) {
224                 value = env_core.entry[i].val;
225                 arc_write_uncached_32(&cross_cpu_data.entry[i], value);
226         }
227
228         for (u32 i = 0; i < NR_CPUS; i++) {
229                 value = env_core.iccm[i].val;
230                 arc_write_uncached_32(&cross_cpu_data.iccm[i], value);
231         }
232
233         for (u32 i = 0; i < NR_CPUS; i++) {
234                 value = env_core.dccm[i].val;
235                 arc_write_uncached_32(&cross_cpu_data.dccm[i], value);
236         }
237
238         value = env_common.core_mask.val;
239         arc_write_uncached_32(&cross_cpu_data.core_mask, value);
240
241         value = env_common.icache.val;
242         arc_write_uncached_32(&cross_cpu_data.icache, value);
243
244         value = env_common.dcache.val;
245         arc_write_uncached_32(&cross_cpu_data.dcache, value);
246 }
247
248 /* Can be used only on master CPU */
249 static bool is_cpu_used(u32 cpu_id)
250 {
251         return !!(env_common.core_mask.val & BIT(cpu_id));
252 }
253
254 /* TODO: add ICCM BCR and DCCM BCR runtime check */
255 static void init_slave_cpu_func(u32 core)
256 {
257         u32 val;
258
259         /* Remap ICCM to another memory region if it exists */
260         val = arc_read_uncached_32(&cross_cpu_data.iccm[core]);
261         if (val != NO_CCM)
262                 write_aux_reg(ARC_AUX_ICCM_BASE, val << APERTURE_SHIFT);
263
264         /* Remap DCCM to another memory region if it exists */
265         val = arc_read_uncached_32(&cross_cpu_data.dccm[core]);
266         if (val != NO_CCM)
267                 write_aux_reg(ARC_AUX_DCCM_BASE, val << APERTURE_SHIFT);
268
269         if (arc_read_uncached_32(&cross_cpu_data.icache))
270                 icache_enable();
271         else
272                 icache_disable();
273
274         if (arc_read_uncached_32(&cross_cpu_data.dcache))
275                 dcache_enable();
276         else
277                 dcache_disable();
278 }
279
280 static void init_cluster_nvlim(void)
281 {
282         u32 val = env_common.nvlim.val << APERTURE_SHIFT;
283
284         flush_dcache_all();
285         write_aux_reg(ARC_AUX_NON_VOLATILE_LIMIT, val);
286         /* AUX_AUX_CACHE_LIMIT reg is missing starting from HS48 */
287         if (is_board_match_runtime(T_BOARD_HSDK))
288                 write_aux_reg(AUX_AUX_CACHE_LIMIT, val);
289         flush_n_invalidate_dcache_all();
290 }
291
292 static void init_cluster_slc(void)
293 {
294         /* ARC HS38 doesn't support SLC disabling */
295         if (!is_board_match_config(T_BOARD_HSDK_4XD))
296                 return;
297
298         if (env_common.l2_cache.val)
299                 slc_enable();
300         else
301                 slc_disable();
302 }
303
304 #define CREG_CSM_BASE           (CREG_BASE + 0x210)
305
306 static void init_cluster_csm(void)
307 {
308         /* ARC HS38 in HSDK SoC doesn't include CSM */
309         if (!is_board_match_config(T_BOARD_HSDK_4XD))
310                 return;
311
312         if (env_common.csm_location.val == NO_CCM) {
313                 write_aux_reg(ARC_AUX_CSM_ENABLE, 0);
314         } else {
315                 /*
316                  * CSM base address is 256kByte aligned but we allow to map
317                  * CSM only to aperture start (256MByte aligned)
318                  * The field in CREG_CSM_BASE is in 17:2 bits itself so we need
319                  * to shift it.
320                  */
321                 u32 csm_base = (env_common.csm_location.val * SZ_1K) << 2;
322
323                 write_aux_reg(ARC_AUX_CSM_ENABLE, 1);
324                 writel(csm_base, (void __iomem *)CREG_CSM_BASE);
325         }
326 }
327
328 static void init_master_icache(void)
329 {
330         if (icache_status()) {
331                 /* I$ is enabled - we need to disable it */
332                 if (!env_common.icache.val)
333                         icache_disable();
334         } else {
335                 /* I$ is disabled - we need to enable it */
336                 if (env_common.icache.val) {
337                         icache_enable();
338
339                         /* invalidate I$ right after enable */
340                         invalidate_icache_all();
341                 }
342         }
343 }
344
345 static void init_master_dcache(void)
346 {
347         if (dcache_status()) {
348                 /* D$ is enabled - we need to disable it */
349                 if (!env_common.dcache.val)
350                         dcache_disable();
351         } else {
352                 /* D$ is disabled - we need to enable it */
353                 if (env_common.dcache.val)
354                         dcache_enable();
355
356                 /* TODO: probably we need ti invalidate D$ right after enable */
357         }
358 }
359
360 static int cleanup_before_go(void)
361 {
362         disable_interrupts();
363         sync_n_cleanup_cache_all();
364
365         return 0;
366 }
367
368 void slave_cpu_set_boot_addr(u32 addr)
369 {
370         /* All cores have reset vector pointing to 0 */
371         writel(addr, (void __iomem *)RESET_VECTOR_ADDR);
372
373         /* Make sure other cores see written value in memory */
374         sync_n_cleanup_cache_all();
375 }
376
377 static inline void halt_this_cpu(void)
378 {
379         __builtin_arc_flag(1);
380 }
381
382 static u32 get_masked_cpu_ctart_reg(void)
383 {
384         int cmd = readl((void __iomem *)CREG_CPU_START);
385
386         /*
387          * Quirk for HSDK-4xD - due to HW issues HSDK can use any pulse polarity
388          * and HSDK-4xD require active low polarity of cpu_start pulse.
389          */
390         cmd &= ~CREG_CPU_START_POL;
391
392         cmd &= ~CREG_CPU_START_MASK;
393
394         return cmd;
395 }
396
397 static void smp_kick_cpu_x(u32 cpu_id)
398 {
399         int cmd;
400
401         if (cpu_id > NR_CPUS)
402                 return;
403
404         cmd = get_masked_cpu_ctart_reg();
405         cmd |= (1 << cpu_id);
406         writel(cmd, (void __iomem *)CREG_CPU_START);
407 }
408
409 static u32 prepare_cpu_ctart_reg(void)
410 {
411         return get_masked_cpu_ctart_reg() | env_common.core_mask.val;
412 }
413
414 /* slave CPU entry for configuration */
415 __attribute__((naked, noreturn, flatten)) noinline void hsdk_core_init_f(void)
416 {
417         __asm__ __volatile__(
418                 "ld.di  r8,     [%0]\n"
419                 "mov    %%sp,   r8\n"
420                 "mov    %%fp,   %%sp\n"
421                 : /* no output */
422                 : "r" (&cross_cpu_data.stack_ptr));
423
424         invalidate_icache_all();
425
426         arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_1);
427         init_slave_cpu_func(CPU_ID_GET());
428
429         arc_write_uncached_32(&cross_cpu_data.ready_flag, SLAVE_CPU_READY);
430         arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_2);
431
432         /* Halt the processor until the master kick us again */
433         halt_this_cpu();
434
435         /*
436          * 3 NOPs after FLAG 1 instruction are no longer required for ARCv2
437          * cores but we leave them for gebug purposes.
438          */
439         __builtin_arc_nop();
440         __builtin_arc_nop();
441         __builtin_arc_nop();
442
443         arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_3);
444
445         /* get the updated entry - invalidate i$ */
446         invalidate_icache_all();
447
448         arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_4);
449
450         /* Run our program */
451         ((void (*)(void))(arc_read_uncached_32(&cross_cpu_data.entry[CPU_ID_GET()])))();
452
453         /* This bootstage is unreachable as we don't return from app we launch */
454         arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_5);
455
456         /* Something went terribly wrong */
457         while (true)
458                 halt_this_cpu();
459 }
460
461 static void clear_cross_cpu_data(void)
462 {
463         arc_write_uncached_32(&cross_cpu_data.ready_flag, 0);
464         arc_write_uncached_32(&cross_cpu_data.stack_ptr, 0);
465
466         for (u32 i = 0; i < NR_CPUS; i++)
467                 arc_write_uncached_32(&cross_cpu_data.status[i], 0);
468 }
469
470 static noinline void do_init_slave_cpu(u32 cpu_id)
471 {
472         /* attempts number for check clave CPU ready_flag */
473         u32 attempts = 100;
474         u32 stack_ptr = (u32)(slave_stack + (64 * cpu_id));
475
476         if (cpu_id >= NR_CPUS)
477                 return;
478
479         arc_write_uncached_32(&cross_cpu_data.ready_flag, 0);
480
481         /* Use global unique place for each slave cpu stack */
482         arc_write_uncached_32(&cross_cpu_data.stack_ptr, stack_ptr);
483
484         debug("CPU %u: stack pool base: %p\n", cpu_id, slave_stack);
485         debug("CPU %u: current slave stack base: %x\n", cpu_id, stack_ptr);
486         slave_cpu_set_boot_addr((u32)hsdk_core_init_f);
487
488         smp_kick_cpu_x(cpu_id);
489
490         debug("CPU %u: cross-cpu flag: %x [before timeout]\n", cpu_id,
491               arc_read_uncached_32(&cross_cpu_data.ready_flag));
492
493         while (!arc_read_uncached_32(&cross_cpu_data.ready_flag) && attempts--)
494                 mdelay(10);
495
496         /* Just to be sure that slave cpu is halted after it set ready_flag */
497         mdelay(20);
498
499         /*
500          * Only print error here if we reach timeout as there is no option to
501          * halt slave cpu (or check that slave cpu is halted)
502          */
503         if (!attempts)
504                 pr_err("CPU %u is not responding after init!\n", cpu_id);
505
506         /* Check current stage of slave cpu */
507         if (arc_read_uncached_32(&cross_cpu_data.status[cpu_id]) != BOOTSTAGE_2)
508                 pr_err("CPU %u status is unexpected: %d\n", cpu_id,
509                        arc_read_uncached_32(&cross_cpu_data.status[cpu_id]));
510
511         debug("CPU %u: cross-cpu flag: %x [after timeout]\n", cpu_id,
512               arc_read_uncached_32(&cross_cpu_data.ready_flag));
513         debug("CPU %u: status: %d [after timeout]\n", cpu_id,
514               arc_read_uncached_32(&cross_cpu_data.status[cpu_id]));
515 }
516
517 static void do_init_slave_cpus(void)
518 {
519         clear_cross_cpu_data();
520         sync_cross_cpu_data();
521
522         debug("cross_cpu_data location: %#x\n", (u32)&cross_cpu_data);
523
524         for (u32 i = MASTER_CPU_ID + 1; i < NR_CPUS; i++)
525                 if (is_cpu_used(i))
526                         do_init_slave_cpu(i);
527 }
528
529 static void do_init_master_cpu(void)
530 {
531         /*
532          * Setup master caches even if master isn't used as we want to use
533          * same cache configuration on all running CPUs
534          */
535         init_master_icache();
536         init_master_dcache();
537 }
538
539 enum hsdk_axi_masters {
540         M_HS_CORE = 0,
541         M_HS_RTT,
542         M_AXI_TUN,
543         M_HDMI_VIDEO,
544         M_HDMI_AUDIO,
545         M_USB_HOST,
546         M_ETHERNET,
547         M_SDIO,
548         M_GPU,
549         M_DMAC_0,
550         M_DMAC_1,
551         M_DVFS
552 };
553
554 #define UPDATE_VAL      1
555
556 /*
557  * m    master          AXI_M_m_SLV0    AXI_M_m_SLV1    AXI_M_m_OFFSET0 AXI_M_m_OFFSET1
558  * 0    HS (CBU)        0x11111111      0x63111111      0xFEDCBA98      0x0E543210
559  * 1    HS (RTT)        0x77777777      0x77777777      0xFEDCBA98      0x76543210
560  * 2    AXI Tunnel      0x88888888      0x88888888      0xFEDCBA98      0x76543210
561  * 3    HDMI-VIDEO      0x77777777      0x77777777      0xFEDCBA98      0x76543210
562  * 4    HDMI-ADUIO      0x77777777      0x77777777      0xFEDCBA98      0x76543210
563  * 5    USB-HOST        0x77777777      0x77999999      0xFEDCBA98      0x76DCBA98
564  * 6    ETHERNET        0x77777777      0x77999999      0xFEDCBA98      0x76DCBA98
565  * 7    SDIO            0x77777777      0x77999999      0xFEDCBA98      0x76DCBA98
566  * 8    GPU             0x77777777      0x77777777      0xFEDCBA98      0x76543210
567  * 9    DMAC (port #1)  0x77777777      0x77777777      0xFEDCBA98      0x76543210
568  * 10   DMAC (port #2)  0x77777777      0x77777777      0xFEDCBA98      0x76543210
569  * 11   DVFS            0x00000000      0x60000000      0x00000000      0x00000000
570  *
571  * Please read ARC HS Development IC Specification, section 17.2 for more
572  * information about apertures configuration.
573  * NOTE: we intentionally modify default settings in U-boot. Default settings
574  * are specified in "Table 111 CREG Address Decoder register reset values".
575  */
576
577 #define CREG_AXI_M_SLV0(m)  ((void __iomem *)(CREG_BASE + 0x020 * (m)))
578 #define CREG_AXI_M_SLV1(m)  ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x004))
579 #define CREG_AXI_M_OFT0(m)  ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x008))
580 #define CREG_AXI_M_OFT1(m)  ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x00C))
581 #define CREG_AXI_M_UPDT(m)  ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x014))
582
583 #define CREG_AXI_M_HS_CORE_BOOT ((void __iomem *)(CREG_BASE + 0x010))
584
585 #define CREG_PAE        ((void __iomem *)(CREG_BASE + 0x180))
586 #define CREG_PAE_UPDT   ((void __iomem *)(CREG_BASE + 0x194))
587
588 void init_memory_bridge(void)
589 {
590         u32 reg;
591
592         /*
593          * M_HS_CORE has one unic register - BOOT.
594          * We need to clean boot mirror (BOOT[1:0]) bits in them.
595          */
596         reg = readl(CREG_AXI_M_HS_CORE_BOOT) & (~0x3);
597         writel(reg, CREG_AXI_M_HS_CORE_BOOT);
598         writel(0x11111111, CREG_AXI_M_SLV0(M_HS_CORE));
599         writel(0x63111111, CREG_AXI_M_SLV1(M_HS_CORE));
600         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HS_CORE));
601         writel(0x0E543210, CREG_AXI_M_OFT1(M_HS_CORE));
602         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HS_CORE));
603
604         writel(0x77777777, CREG_AXI_M_SLV0(M_HS_RTT));
605         writel(0x77777777, CREG_AXI_M_SLV1(M_HS_RTT));
606         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HS_RTT));
607         writel(0x76543210, CREG_AXI_M_OFT1(M_HS_RTT));
608         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HS_RTT));
609
610         writel(0x88888888, CREG_AXI_M_SLV0(M_AXI_TUN));
611         writel(0x88888888, CREG_AXI_M_SLV1(M_AXI_TUN));
612         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_AXI_TUN));
613         writel(0x76543210, CREG_AXI_M_OFT1(M_AXI_TUN));
614         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_AXI_TUN));
615
616         writel(0x77777777, CREG_AXI_M_SLV0(M_HDMI_VIDEO));
617         writel(0x77777777, CREG_AXI_M_SLV1(M_HDMI_VIDEO));
618         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HDMI_VIDEO));
619         writel(0x76543210, CREG_AXI_M_OFT1(M_HDMI_VIDEO));
620         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HDMI_VIDEO));
621
622         writel(0x77777777, CREG_AXI_M_SLV0(M_HDMI_AUDIO));
623         writel(0x77777777, CREG_AXI_M_SLV1(M_HDMI_AUDIO));
624         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HDMI_AUDIO));
625         writel(0x76543210, CREG_AXI_M_OFT1(M_HDMI_AUDIO));
626         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HDMI_AUDIO));
627
628         writel(0x77777777, CREG_AXI_M_SLV0(M_USB_HOST));
629         writel(0x77999999, CREG_AXI_M_SLV1(M_USB_HOST));
630         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_USB_HOST));
631         writel(0x76DCBA98, CREG_AXI_M_OFT1(M_USB_HOST));
632         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_USB_HOST));
633
634         writel(0x77777777, CREG_AXI_M_SLV0(M_ETHERNET));
635         writel(0x77999999, CREG_AXI_M_SLV1(M_ETHERNET));
636         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_ETHERNET));
637         writel(0x76DCBA98, CREG_AXI_M_OFT1(M_ETHERNET));
638         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_ETHERNET));
639
640         writel(0x77777777, CREG_AXI_M_SLV0(M_SDIO));
641         writel(0x77999999, CREG_AXI_M_SLV1(M_SDIO));
642         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_SDIO));
643         writel(0x76DCBA98, CREG_AXI_M_OFT1(M_SDIO));
644         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_SDIO));
645
646         writel(0x77777777, CREG_AXI_M_SLV0(M_GPU));
647         writel(0x77777777, CREG_AXI_M_SLV1(M_GPU));
648         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_GPU));
649         writel(0x76543210, CREG_AXI_M_OFT1(M_GPU));
650         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_GPU));
651
652         writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_0));
653         writel(0x77777777, CREG_AXI_M_SLV1(M_DMAC_0));
654         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_0));
655         writel(0x76543210, CREG_AXI_M_OFT1(M_DMAC_0));
656         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_0));
657
658         writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_1));
659         writel(0x77777777, CREG_AXI_M_SLV1(M_DMAC_1));
660         writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_1));
661         writel(0x76543210, CREG_AXI_M_OFT1(M_DMAC_1));
662         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_1));
663
664         writel(0x00000000, CREG_AXI_M_SLV0(M_DVFS));
665         writel(0x60000000, CREG_AXI_M_SLV1(M_DVFS));
666         writel(0x00000000, CREG_AXI_M_OFT0(M_DVFS));
667         writel(0x00000000, CREG_AXI_M_OFT1(M_DVFS));
668         writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DVFS));
669
670         writel(0x00000000, CREG_PAE);
671         writel(UPDATE_VAL, CREG_PAE_UPDT);
672 }
673
674 static void setup_clocks(void)
675 {
676         ulong rate;
677
678         /* Setup CPU clock */
679         if (env_common.cpu_freq.set) {
680                 rate = env_common.cpu_freq.val;
681                 soc_clk_ctl("cpu-clk", &rate, CLK_ON | CLK_SET | CLK_MHZ);
682         }
683
684         /* Setup TUN clock */
685         if (env_common.tun_freq.set) {
686                 rate = env_common.tun_freq.val;
687                 if (rate)
688                         soc_clk_ctl("tun-clk", &rate, CLK_ON | CLK_SET | CLK_MHZ);
689                 else
690                         soc_clk_ctl("tun-clk", NULL, CLK_OFF);
691         }
692
693         if (env_common.axi_freq.set) {
694                 rate = env_common.axi_freq.val;
695                 soc_clk_ctl("axi-clk", &rate, CLK_SET | CLK_ON | CLK_MHZ);
696         }
697 }
698
699 static void do_init_cluster(void)
700 {
701         /*
702          * A multi-core ARC HS configuration always includes only one
703          * ARC_AUX_NON_VOLATILE_LIMIT register, which is shared by all the
704          * cores.
705          */
706         init_cluster_nvlim();
707         init_cluster_csm();
708         init_cluster_slc();
709 }
710
711 static int check_master_cpu_id(void)
712 {
713         if (CPU_ID_GET() == MASTER_CPU_ID)
714                 return 0;
715
716         pr_err("u-boot runs on non-master cpu with id: %lu\n", CPU_ID_GET());
717
718         return -ENOENT;
719 }
720
721 static noinline int prepare_cpus(void)
722 {
723         int ret;
724
725         ret = check_master_cpu_id();
726         if (ret)
727                 return ret;
728
729         ret = envs_process_and_validate(env_map_common, env_map_core, is_cpu_used);
730         if (ret)
731                 return ret;
732
733         printf("CPU start mask is %#x\n", env_common.core_mask.val);
734
735         do_init_slave_cpus();
736         do_init_master_cpu();
737         do_init_cluster();
738
739         return 0;
740 }
741
742 static int hsdk_go_run(u32 cpu_start_reg)
743 {
744         /* Cleanup caches, disable interrupts */
745         cleanup_before_go();
746
747         if (env_common.halt_on_boot)
748                 halt_this_cpu();
749
750         /*
751          * 3 NOPs after FLAG 1 instruction are no longer required for ARCv2
752          * cores but we leave them for gebug purposes.
753          */
754         __builtin_arc_nop();
755         __builtin_arc_nop();
756         __builtin_arc_nop();
757
758         /* Kick chosen slave CPUs */
759         writel(cpu_start_reg, (void __iomem *)CREG_CPU_START);
760
761         if (is_cpu_used(MASTER_CPU_ID))
762                 ((void (*)(void))(env_core.entry[MASTER_CPU_ID].val))();
763         else
764                 halt_this_cpu();
765
766         pr_err("u-boot still runs on cpu [%ld]\n", CPU_ID_GET());
767
768         /*
769          * We will never return after executing our program if master cpu used
770          * otherwise halt master cpu manually.
771          */
772         while (true)
773                 halt_this_cpu();
774
775         return 0;
776 }
777
778 int board_prep_linux(bootm_headers_t *images)
779 {
780         int ret, ofst;
781         char mask[15];
782
783         ret = envs_read_validate_common(env_map_mask);
784         if (ret)
785                 return ret;
786
787         /* Rollback to default values */
788         if (!env_common.core_mask.set) {
789                 env_common.core_mask.val = ALL_CPU_MASK;
790                 env_common.core_mask.set = true;
791         }
792
793         printf("CPU start mask is %#x\n", env_common.core_mask.val);
794
795         if (!is_cpu_used(MASTER_CPU_ID))
796                 pr_err("ERR: try to launch linux with CPU[0] disabled! It doesn't work for ARC.\n");
797
798         /*
799          * If we want to launch linux on all CPUs we don't need to patch
800          * linux DTB as it is default configuration
801          */
802         if (env_common.core_mask.val == ALL_CPU_MASK)
803                 return 0;
804
805         if (!IMAGE_ENABLE_OF_LIBFDT || !images->ft_len) {
806                 pr_err("WARN: core_mask setup will work properly only with external DTB!\n");
807                 return 0;
808         }
809
810         /* patch '/possible-cpus' property according to cpu mask */
811         ofst = fdt_path_offset(images->ft_addr, "/");
812         sprintf(mask, "%s%s%s%s",
813                 is_cpu_used(0) ? "0," : "",
814                 is_cpu_used(1) ? "1," : "",
815                 is_cpu_used(2) ? "2," : "",
816                 is_cpu_used(3) ? "3," : "");
817         ret = fdt_setprop_string(images->ft_addr, ofst, "possible-cpus", mask);
818         /*
819          * If we failed to patch '/possible-cpus' property we don't need break
820          * linux loading process: kernel will handle it but linux will print
821          * warning like "Timeout: CPU1 FAILED to comeup !!!".
822          * So warn here about error, but return 0 like no error had occurred.
823          */
824         if (ret)
825                 pr_err("WARN: failed to patch '/possible-cpus' property, ret=%d\n",
826                        ret);
827
828         return 0;
829 }
830
831 void board_jump_and_run(ulong entry, int zero, int arch, uint params)
832 {
833         void (*kernel_entry)(int zero, int arch, uint params);
834         u32 cpu_start_reg;
835
836         kernel_entry = (void (*)(int, int, uint))entry;
837
838         /* Prepare CREG_CPU_START for kicking chosen CPUs */
839         cpu_start_reg = prepare_cpu_ctart_reg();
840
841         /* In case of run without hsdk_init */
842         slave_cpu_set_boot_addr(entry);
843
844         /* In case of run with hsdk_init */
845         for (u32 i = 0; i < NR_CPUS; i++) {
846                 env_core.entry[i].val = entry;
847                 env_core.entry[i].set = true;
848         }
849         /* sync cross_cpu struct as we updated core-entry variables */
850         sync_cross_cpu_data();
851
852         /* Kick chosen slave CPUs */
853         writel(cpu_start_reg, (void __iomem *)CREG_CPU_START);
854
855         if (is_cpu_used(0))
856                 kernel_entry(zero, arch, params);
857 }
858
859 static int hsdk_go_prepare_and_run(void)
860 {
861         /* Prepare CREG_CPU_START for kicking chosen CPUs */
862         u32 reg = prepare_cpu_ctart_reg();
863
864         if (env_common.halt_on_boot)
865                 printf("CPU will halt before application start, start application with debugger.\n");
866
867         return hsdk_go_run(reg);
868 }
869
870 static int do_hsdk_go(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
871 {
872         int ret;
873
874         if (board_mismatch()) {
875                 printf("ERR: U-boot is not configured for this board!\n");
876                 return CMD_RET_FAILURE;
877         }
878
879         /*
880          * Check for 'halt' parameter. 'halt' = enter halt-mode just before
881          * starting the application; can be used for debug.
882          */
883         if (argc > 1) {
884                 env_common.halt_on_boot = !strcmp(argv[1], "halt");
885                 if (!env_common.halt_on_boot) {
886                         pr_err("Unrecognised parameter: \'%s\'\n", argv[1]);
887                         return CMD_RET_FAILURE;
888                 }
889         }
890
891         ret = check_master_cpu_id();
892         if (ret)
893                 return ret;
894
895         ret = envs_process_and_validate(env_map_mask, env_map_go, is_cpu_used);
896         if (ret)
897                 return ret;
898
899         /* sync cross_cpu struct as we updated core-entry variables */
900         sync_cross_cpu_data();
901
902         ret = hsdk_go_prepare_and_run();
903
904         return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
905 }
906
907 U_BOOT_CMD(
908         hsdk_go, 3, 0, do_hsdk_go,
909         "Synopsys HSDK specific command",
910         "     - Boot stand-alone application on HSDK\n"
911         "hsdk_go halt - Boot stand-alone application on HSDK, halt CPU just before application run\n"
912 );
913
914 static int do_hsdk_init(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
915 {
916         static bool done = false;
917         int ret;
918
919         if (board_mismatch()) {
920                 printf("ERR: U-boot is not configured for this board!\n");
921                 return CMD_RET_FAILURE;
922         }
923
924         /* hsdk_init can be run only once */
925         if (done) {
926                 printf("HSDK HW is already initialized! Please reset the board if you want to change the configuration.\n");
927                 return CMD_RET_FAILURE;
928         }
929
930         ret = prepare_cpus();
931         if (!ret)
932                 done = true;
933
934         return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
935 }
936
937 U_BOOT_CMD(
938         hsdk_init, 1, 0, do_hsdk_init,
939         "Synopsys HSDK specific command",
940         "- Init HSDK HW\n"
941 );
942
943 static int do_hsdk_clock_set(cmd_tbl_t *cmdtp, int flag, int argc,
944                              char *const argv[])
945 {
946         int ret = 0;
947
948         /* Strip off leading subcommand argument */
949         argc--;
950         argv++;
951
952         envs_cleanup_common(env_map_clock);
953
954         if (!argc) {
955                 printf("Set clocks to values specified in environment\n");
956                 ret = envs_read_common(env_map_clock);
957         } else {
958                 printf("Set clocks to values specified in args\n");
959                 ret = args_envs_enumerate(env_map_clock, 2, argc, argv);
960         }
961
962         if (ret)
963                 return CMD_RET_FAILURE;
964
965         ret = envs_validate_common(env_map_clock);
966         if (ret)
967                 return CMD_RET_FAILURE;
968
969         /* Setup clock tree HW */
970         setup_clocks();
971
972         return CMD_RET_SUCCESS;
973 }
974
975 static int do_hsdk_clock_get(cmd_tbl_t *cmdtp, int flag, int argc,
976                              char *const argv[])
977 {
978         ulong rate;
979
980         if (soc_clk_ctl("cpu-clk", &rate, CLK_GET | CLK_MHZ))
981                 return CMD_RET_FAILURE;
982
983         if (env_set_ulong("cpu_freq", rate))
984                 return CMD_RET_FAILURE;
985
986         if (soc_clk_ctl("tun-clk", &rate, CLK_GET | CLK_MHZ))
987                 return CMD_RET_FAILURE;
988
989         if (env_set_ulong("tun_freq", rate))
990                 return CMD_RET_FAILURE;
991
992         if (soc_clk_ctl("axi-clk", &rate, CLK_GET | CLK_MHZ))
993                 return CMD_RET_FAILURE;
994
995         if (env_set_ulong("axi_freq", rate))
996                 return CMD_RET_FAILURE;
997
998         printf("Clock values are saved to environment\n");
999
1000         return CMD_RET_SUCCESS;
1001 }
1002
1003 static int do_hsdk_clock_print(cmd_tbl_t *cmdtp, int flag, int argc,
1004                                char *const argv[])
1005 {
1006         /* Main clocks */
1007         soc_clk_ctl("cpu-clk", NULL, CLK_PRINT | CLK_MHZ);
1008         soc_clk_ctl("tun-clk", NULL, CLK_PRINT | CLK_MHZ);
1009         soc_clk_ctl("axi-clk", NULL, CLK_PRINT | CLK_MHZ);
1010         soc_clk_ctl("ddr-clk", NULL, CLK_PRINT | CLK_MHZ);
1011
1012         return CMD_RET_SUCCESS;
1013 }
1014
1015 static int do_hsdk_clock_print_all(cmd_tbl_t *cmdtp, int flag, int argc,
1016                                    char *const argv[])
1017 {
1018         /*
1019          * NOTE: as of today we don't use some peripherals like HDMI / EBI
1020          * so we don't want to print their clocks ("hdmi-sys-clk", "hdmi-pll",
1021          * "hdmi-clk", "ebi-clk"). Nevertheless their clock subsystems is fully
1022          * functional and we can print their clocks if it is required
1023          */
1024
1025         /* CPU clock domain */
1026         soc_clk_ctl("cpu-pll", NULL, CLK_PRINT | CLK_MHZ);
1027         soc_clk_ctl("cpu-clk", NULL, CLK_PRINT | CLK_MHZ);
1028         printf("\n");
1029
1030         /* SYS clock domain */
1031         soc_clk_ctl("sys-pll", NULL, CLK_PRINT | CLK_MHZ);
1032         soc_clk_ctl("apb-clk", NULL, CLK_PRINT | CLK_MHZ);
1033         soc_clk_ctl("axi-clk", NULL, CLK_PRINT | CLK_MHZ);
1034         soc_clk_ctl("eth-clk", NULL, CLK_PRINT | CLK_MHZ);
1035         soc_clk_ctl("usb-clk", NULL, CLK_PRINT | CLK_MHZ);
1036         soc_clk_ctl("sdio-clk", NULL, CLK_PRINT | CLK_MHZ);
1037         if (is_board_match_runtime(T_BOARD_HSDK_4XD))
1038                 soc_clk_ctl("hdmi-sys-clk", NULL, CLK_PRINT | CLK_MHZ);
1039         soc_clk_ctl("gfx-core-clk", NULL, CLK_PRINT | CLK_MHZ);
1040         if (is_board_match_runtime(T_BOARD_HSDK)) {
1041                 soc_clk_ctl("gfx-dma-clk", NULL, CLK_PRINT | CLK_MHZ);
1042                 soc_clk_ctl("gfx-cfg-clk", NULL, CLK_PRINT | CLK_MHZ);
1043         }
1044         soc_clk_ctl("dmac-core-clk", NULL, CLK_PRINT | CLK_MHZ);
1045         soc_clk_ctl("dmac-cfg-clk", NULL, CLK_PRINT | CLK_MHZ);
1046         soc_clk_ctl("sdio-ref-clk", NULL, CLK_PRINT | CLK_MHZ);
1047         soc_clk_ctl("spi-clk", NULL, CLK_PRINT | CLK_MHZ);
1048         soc_clk_ctl("i2c-clk", NULL, CLK_PRINT | CLK_MHZ);
1049 /*      soc_clk_ctl("ebi-clk", NULL, CLK_PRINT | CLK_MHZ); */
1050         soc_clk_ctl("uart-clk", NULL, CLK_PRINT | CLK_MHZ);
1051         printf("\n");
1052
1053         /* DDR clock domain */
1054         soc_clk_ctl("ddr-clk", NULL, CLK_PRINT | CLK_MHZ);
1055         printf("\n");
1056
1057         /* HDMI clock domain */
1058         if (is_board_match_runtime(T_BOARD_HSDK_4XD)) {
1059                 soc_clk_ctl("hdmi-pll", NULL, CLK_PRINT | CLK_MHZ);
1060                 soc_clk_ctl("hdmi-clk", NULL, CLK_PRINT | CLK_MHZ);
1061                 printf("\n");
1062         }
1063
1064         /* TUN clock domain */
1065         soc_clk_ctl("tun-pll", NULL, CLK_PRINT | CLK_MHZ);
1066         soc_clk_ctl("tun-clk", NULL, CLK_PRINT | CLK_MHZ);
1067         soc_clk_ctl("rom-clk", NULL, CLK_PRINT | CLK_MHZ);
1068         soc_clk_ctl("pwm-clk", NULL, CLK_PRINT | CLK_MHZ);
1069         if (is_board_match_runtime(T_BOARD_HSDK_4XD))
1070                 soc_clk_ctl("timer-clk", NULL, CLK_PRINT | CLK_MHZ);
1071         printf("\n");
1072
1073         return CMD_RET_SUCCESS;
1074 }
1075
1076 cmd_tbl_t cmd_hsdk_clock[] = {
1077         U_BOOT_CMD_MKENT(set, 3, 0, do_hsdk_clock_set, "", ""),
1078         U_BOOT_CMD_MKENT(get, 3, 0, do_hsdk_clock_get, "", ""),
1079         U_BOOT_CMD_MKENT(print, 4, 0, do_hsdk_clock_print, "", ""),
1080         U_BOOT_CMD_MKENT(print_all, 4, 0, do_hsdk_clock_print_all, "", ""),
1081 };
1082
1083 static int do_hsdk_clock(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1084 {
1085         cmd_tbl_t *c;
1086
1087         if (argc < 2)
1088                 return CMD_RET_USAGE;
1089
1090         /* Strip off leading 'hsdk_clock' command argument */
1091         argc--;
1092         argv++;
1093
1094         c = find_cmd_tbl(argv[0], cmd_hsdk_clock, ARRAY_SIZE(cmd_hsdk_clock));
1095         if (!c)
1096                 return CMD_RET_USAGE;
1097
1098         return c->cmd(cmdtp, flag, argc, argv);
1099 }
1100
1101 U_BOOT_CMD(
1102         hsdk_clock, CONFIG_SYS_MAXARGS, 0, do_hsdk_clock,
1103         "Synopsys HSDK specific clock command",
1104         "set   - Set clock to values specified in environment / command line arguments\n"
1105         "hsdk_clock get   - Save clock values to environment\n"
1106         "hsdk_clock print - Print main clock values to console\n"
1107         "hsdk_clock print_all - Print all clock values to console\n"
1108 );
1109
1110 /* init calls */
1111 int board_early_init_f(void)
1112 {
1113         /*
1114          * Setup AXI apertures unconditionally as we want to have DDR
1115          * in 0x00000000 region when we are kicking slave cpus.
1116          */
1117         init_memory_bridge();
1118
1119         /*
1120          * Switch SDIO external ciu clock divider from default div-by-8 to
1121          * minimum possible div-by-2.
1122          */
1123         writel(SDIO_UHS_REG_EXT_DIV_2, (void __iomem *)SDIO_UHS_REG_EXT);
1124
1125         return 0;
1126 }
1127
1128 int board_early_init_r(void)
1129 {
1130         /*
1131          * TODO: Init USB here to be able read environment from USB MSD.
1132          * It can be done with usb_init() call. We can't do it right now
1133          * due to brocken USB IP SW reset and lack of USB IP HW reset in
1134          * linux kernel (if we init USB here we will break USB in linux)
1135          */
1136
1137         /*
1138          * Flush all d$ as we want to use uncached area with st.di / ld.di
1139          * instructions and we don't want to have any dirty line in L1d$ or SL$
1140          * in this area. It is enough to flush all d$ once here as we access to
1141          * uncached area with regular st (non .di) instruction only when we copy
1142          * data during u-boot relocation.
1143          */
1144         flush_dcache_all();
1145
1146         printf("Relocation Offset is: %08lx\n", gd->reloc_off);
1147
1148         return 0;
1149 }
1150
1151 int board_late_init(void)
1152 {
1153         /*
1154          * Populate environment with clock frequency values -
1155          * run hsdk_clock get callback without uboot command run.
1156          */
1157         do_hsdk_clock_get(NULL, 0, 0, NULL);
1158
1159         return 0;
1160 }
1161
1162 int checkboard(void)
1163 {
1164         printf("Board: Synopsys %s\n", board_name(get_board_type_runtime()));
1165
1166         if (board_mismatch())
1167                 printf("WARN: U-boot is configured NOT for this board but for %s!\n",
1168                        board_name(get_board_type_config()));
1169
1170         return 0;
1171 };