1
2
3
4
5
6
7#include <common.h>
8#include <command.h>
9#include <config.h>
10#include <cpu_func.h>
11#include <env.h>
12#include <image.h>
13#include <init.h>
14#include <irq_func.h>
15#include <log.h>
16#include <asm/cache.h>
17#include <asm/global_data.h>
18#include <linux/bitops.h>
19#include <linux/delay.h>
20#include <linux/printk.h>
21#include <linux/kernel.h>
22#include <linux/io.h>
23#include <asm/arcregs.h>
24#include <fdt_support.h>
25#include <dwmmc.h>
26#include <malloc.h>
27#include <usb.h>
28
29#include "clk-lib.h"
30#include "env-lib.h"
31
32DECLARE_GLOBAL_DATA_PTR;
33
34#define ALL_CPU_MASK GENMASK(NR_CPUS - 1, 0)
35#define MASTER_CPU_ID 0
36#define APERTURE_SHIFT 28
37#define NO_CCM 0x10
38#define SLAVE_CPU_READY 0x12345678
39#define BOOTSTAGE_1 1
40#define BOOTSTAGE_2 2
41#define BOOTSTAGE_3 3
42#define BOOTSTAGE_4 4
43#define BOOTSTAGE_5 5
44
45#define RESET_VECTOR_ADDR 0x0
46
47#define CREG_BASE (ARC_PERIPHERAL_BASE + 0x1000)
48#define CREG_CPU_START (CREG_BASE + 0x400)
49#define CREG_CPU_START_MASK 0xF
50#define CREG_CPU_START_POL BIT(4)
51
52#define CREG_CORE_BOOT_IMAGE GENMASK(5, 4)
53
54#define CREG_CPU_0_ENTRY (CREG_BASE + 0x404)
55
56#define SDIO_BASE (ARC_PERIPHERAL_BASE + 0xA000)
57#define SDIO_UHS_REG_EXT (SDIO_BASE + 0x108)
58#define SDIO_UHS_REG_EXT_DIV_2 (2 << 30)
59
60
61#define arc_read_uncached_32(ptr) \
62({ \
63 unsigned int __ret; \
64 __asm__ __volatile__( \
65 " ld.di %0, [%1] \n" \
66 : "=r"(__ret) \
67 : "r"(ptr)); \
68 __ret; \
69})
70
71#define arc_write_uncached_32(ptr, data)\
72({ \
73 __asm__ __volatile__( \
74 " st.di %0, [%1] \n" \
75 : \
76 : "r"(data), "r"(ptr)); \
77})
78
79struct hsdk_env_core_ctl {
80 u32_env entry[NR_CPUS];
81 u32_env iccm[NR_CPUS];
82 u32_env dccm[NR_CPUS];
83};
84
85struct hsdk_env_common_ctl {
86 bool halt_on_boot;
87 u32_env core_mask;
88 u32_env cpu_freq;
89 u32_env axi_freq;
90 u32_env tun_freq;
91 u32_env nvlim;
92 u32_env icache;
93 u32_env dcache;
94 u32_env csm_location;
95 u32_env l2_cache;
96 u32_env haps_apb;
97};
98
99
100
101
102
103
104
105
106
107struct hsdk_cross_cpu {
108
109 u32 ready_flag;
110
111 u32 stack_ptr;
112
113 s32 status[NR_CPUS];
114
115
116
117
118
119
120
121
122
123 u32 entry[NR_CPUS];
124 u32 iccm[NR_CPUS];
125 u32 dccm[NR_CPUS];
126
127 u32 core_mask;
128 u32 icache;
129 u32 dcache;
130
131 u8 cache_padding[ARCH_DMA_MINALIGN];
132} __aligned(ARCH_DMA_MINALIGN);
133
134
135static u32 slave_stack[256 * NR_CPUS] __aligned(ARCH_DMA_MINALIGN);
136
137static struct hsdk_env_common_ctl env_common = {};
138static struct hsdk_env_core_ctl env_core = {};
139static struct hsdk_cross_cpu cross_cpu_data;
140
141static const struct env_map_common env_map_common[] = {
142 { "core_mask", ENV_HEX, true, 0x1, 0xF, &env_common.core_mask },
143 { "non_volatile_limit", ENV_HEX, true, 0, 0xF, &env_common.nvlim },
144 { "icache_ena", ENV_HEX, true, 0, 1, &env_common.icache },
145 { "dcache_ena", ENV_HEX, true, 0, 1, &env_common.dcache },
146#if defined(CONFIG_BOARD_HSDK_4XD)
147 { "l2_cache_ena", ENV_HEX, true, 0, 1, &env_common.l2_cache },
148 { "csm_location", ENV_HEX, true, 0, NO_CCM, &env_common.csm_location },
149 { "haps_apb_location", ENV_HEX, true, 0, 1, &env_common.haps_apb },
150#endif
151 {}
152};
153
154static const struct env_map_common env_map_clock[] = {
155 { "cpu_freq", ENV_DEC, false, 100, 1000, &env_common.cpu_freq },
156 { "axi_freq", ENV_DEC, false, 200, 800, &env_common.axi_freq },
157 { "tun_freq", ENV_DEC, false, 0, 150, &env_common.tun_freq },
158 {}
159};
160
161static const struct env_map_percpu env_map_core[] = {
162 { "core_iccm", ENV_HEX, true, {NO_CCM, 0, NO_CCM, 0}, {NO_CCM, 0xF, NO_CCM, 0xF}, &env_core.iccm },
163 { "core_dccm", ENV_HEX, true, {NO_CCM, 0, NO_CCM, 0}, {NO_CCM, 0xF, NO_CCM, 0xF}, &env_core.dccm },
164 {}
165};
166
167static const struct env_map_common env_map_mask[] = {
168 { "core_mask", ENV_HEX, false, 0x1, 0xF, &env_common.core_mask },
169 {}
170};
171
172static const struct env_map_percpu env_map_go[] = {
173 { "core_entry", ENV_HEX, true, {0, 0, 0, 0}, {U32_MAX, U32_MAX, U32_MAX, U32_MAX}, &env_core.entry },
174 {}
175};
176
177enum board_type {
178 T_BOARD_NONE,
179 T_BOARD_HSDK,
180 T_BOARD_HSDK_4XD
181};
182
183static inline enum board_type get_board_type_runtime(void)
184{
185 u32 arc_id = read_aux_reg(ARC_AUX_IDENTITY) & 0xFF;
186
187 if (arc_id == 0x52)
188 return T_BOARD_HSDK;
189 else if (arc_id == 0x54)
190 return T_BOARD_HSDK_4XD;
191 else
192 return T_BOARD_NONE;
193}
194
195static inline enum board_type get_board_type_config(void)
196{
197 if (IS_ENABLED(CONFIG_BOARD_HSDK))
198 return T_BOARD_HSDK;
199 else if (IS_ENABLED(CONFIG_BOARD_HSDK_4XD))
200 return T_BOARD_HSDK_4XD;
201 else
202 return T_BOARD_NONE;
203}
204
205static bool is_board_match_runtime(enum board_type type_req)
206{
207 return get_board_type_runtime() == type_req;
208}
209
210static bool is_board_match_config(enum board_type type_req)
211{
212 return get_board_type_config() == type_req;
213}
214
215static const char * board_name(enum board_type type)
216{
217 switch (type) {
218 case T_BOARD_HSDK:
219 return "ARC HS Development Kit";
220 case T_BOARD_HSDK_4XD:
221 return "ARC HS4x/HS4xD Development Kit";
222 default:
223 return "?";
224 }
225}
226
227static bool board_mismatch(void)
228{
229 return get_board_type_config() != get_board_type_runtime();
230}
231
232static void sync_cross_cpu_data(void)
233{
234 u32 value;
235
236 for (u32 i = 0; i < NR_CPUS; i++) {
237 value = env_core.entry[i].val;
238 arc_write_uncached_32(&cross_cpu_data.entry[i], value);
239 }
240
241 for (u32 i = 0; i < NR_CPUS; i++) {
242 value = env_core.iccm[i].val;
243 arc_write_uncached_32(&cross_cpu_data.iccm[i], value);
244 }
245
246 for (u32 i = 0; i < NR_CPUS; i++) {
247 value = env_core.dccm[i].val;
248 arc_write_uncached_32(&cross_cpu_data.dccm[i], value);
249 }
250
251 value = env_common.core_mask.val;
252 arc_write_uncached_32(&cross_cpu_data.core_mask, value);
253
254 value = env_common.icache.val;
255 arc_write_uncached_32(&cross_cpu_data.icache, value);
256
257 value = env_common.dcache.val;
258 arc_write_uncached_32(&cross_cpu_data.dcache, value);
259}
260
261
262static bool is_cpu_used(u32 cpu_id)
263{
264 return !!(env_common.core_mask.val & BIT(cpu_id));
265}
266
267
268static void init_slave_cpu_func(u32 core)
269{
270 u32 val;
271
272
273 val = arc_read_uncached_32(&cross_cpu_data.iccm[core]);
274 if (val != NO_CCM)
275 write_aux_reg(ARC_AUX_ICCM_BASE, val << APERTURE_SHIFT);
276
277
278 val = arc_read_uncached_32(&cross_cpu_data.dccm[core]);
279 if (val != NO_CCM)
280 write_aux_reg(ARC_AUX_DCCM_BASE, val << APERTURE_SHIFT);
281
282 if (arc_read_uncached_32(&cross_cpu_data.icache))
283 icache_enable();
284 else
285 icache_disable();
286
287 if (arc_read_uncached_32(&cross_cpu_data.dcache))
288 dcache_enable();
289 else
290 dcache_disable();
291}
292
293static void init_cluster_nvlim(void)
294{
295 u32 val = env_common.nvlim.val << APERTURE_SHIFT;
296
297 flush_dcache_all();
298 write_aux_reg(ARC_AUX_NON_VOLATILE_LIMIT, val);
299
300 if (is_board_match_runtime(T_BOARD_HSDK))
301 write_aux_reg(AUX_AUX_CACHE_LIMIT, val);
302 flush_n_invalidate_dcache_all();
303}
304
305static void init_cluster_slc(void)
306{
307
308 if (!is_board_match_config(T_BOARD_HSDK_4XD))
309 return;
310
311 if (env_common.l2_cache.val)
312 slc_enable();
313 else
314 slc_disable();
315}
316
317#define CREG_CSM_BASE (CREG_BASE + 0x210)
318
319static void init_cluster_csm(void)
320{
321
322 if (!is_board_match_config(T_BOARD_HSDK_4XD))
323 return;
324
325 if (env_common.csm_location.val == NO_CCM) {
326 write_aux_reg(ARC_AUX_CSM_ENABLE, 0);
327 } else {
328
329
330
331
332
333
334 u32 csm_base = (env_common.csm_location.val * SZ_1K) << 2;
335
336 write_aux_reg(ARC_AUX_CSM_ENABLE, 1);
337 writel(csm_base, (void __iomem *)CREG_CSM_BASE);
338 }
339}
340
341static void init_master_icache(void)
342{
343 if (icache_status()) {
344
345 if (!env_common.icache.val)
346 icache_disable();
347 } else {
348
349 if (env_common.icache.val) {
350 icache_enable();
351
352
353 invalidate_icache_all();
354 }
355 }
356}
357
358static void init_master_dcache(void)
359{
360 if (dcache_status()) {
361
362 if (!env_common.dcache.val)
363 dcache_disable();
364 } else {
365
366 if (env_common.dcache.val)
367 dcache_enable();
368
369
370 }
371}
372
373static int cleanup_before_go(void)
374{
375 disable_interrupts();
376 sync_n_cleanup_cache_all();
377
378 return 0;
379}
380
381void slave_cpu_set_boot_addr(u32 addr)
382{
383
384 writel(addr, (void __iomem *)RESET_VECTOR_ADDR);
385
386
387 sync_n_cleanup_cache_all();
388}
389
390static inline void halt_this_cpu(void)
391{
392 __builtin_arc_flag(1);
393}
394
395static u32 get_masked_cpu_ctart_reg(void)
396{
397 int cmd = readl((void __iomem *)CREG_CPU_START);
398
399
400
401
402
403 cmd &= ~CREG_CPU_START_POL;
404
405 cmd &= ~CREG_CPU_START_MASK;
406
407 return cmd;
408}
409
410static void smp_kick_cpu_x(u32 cpu_id)
411{
412 int cmd;
413
414 if (cpu_id > NR_CPUS)
415 return;
416
417 cmd = get_masked_cpu_ctart_reg();
418 cmd |= (1 << cpu_id);
419 writel(cmd, (void __iomem *)CREG_CPU_START);
420}
421
422static u32 prepare_cpu_ctart_reg(void)
423{
424 return get_masked_cpu_ctart_reg() | env_common.core_mask.val;
425}
426
427
428__attribute__((naked, noreturn, flatten)) noinline void hsdk_core_init_f(void)
429{
430 __asm__ __volatile__(
431 "ld.di r8, [%0]\n"
432 "mov %%sp, r8\n"
433 "mov %%fp, %%sp\n"
434 :
435 : "r" (&cross_cpu_data.stack_ptr));
436
437 invalidate_icache_all();
438
439 arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_1);
440 init_slave_cpu_func(CPU_ID_GET());
441
442 arc_write_uncached_32(&cross_cpu_data.ready_flag, SLAVE_CPU_READY);
443 arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_2);
444
445
446 halt_this_cpu();
447
448
449
450
451
452 __builtin_arc_nop();
453 __builtin_arc_nop();
454 __builtin_arc_nop();
455
456 arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_3);
457
458
459 invalidate_icache_all();
460
461 arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_4);
462
463
464 ((void (*)(void))(arc_read_uncached_32(&cross_cpu_data.entry[CPU_ID_GET()])))();
465
466
467 arc_write_uncached_32(&cross_cpu_data.status[CPU_ID_GET()], BOOTSTAGE_5);
468
469
470 while (true)
471 halt_this_cpu();
472}
473
474static void clear_cross_cpu_data(void)
475{
476 arc_write_uncached_32(&cross_cpu_data.ready_flag, 0);
477 arc_write_uncached_32(&cross_cpu_data.stack_ptr, 0);
478
479 for (u32 i = 0; i < NR_CPUS; i++)
480 arc_write_uncached_32(&cross_cpu_data.status[i], 0);
481}
482
483static noinline void do_init_slave_cpu(u32 cpu_id)
484{
485
486 u32 attempts = 100;
487 u32 stack_ptr = (u32)(slave_stack + (64 * cpu_id));
488
489 if (cpu_id >= NR_CPUS)
490 return;
491
492 arc_write_uncached_32(&cross_cpu_data.ready_flag, 0);
493
494
495 arc_write_uncached_32(&cross_cpu_data.stack_ptr, stack_ptr);
496
497 debug("CPU %u: stack pool base: %p\n", cpu_id, slave_stack);
498 debug("CPU %u: current slave stack base: %x\n", cpu_id, stack_ptr);
499 slave_cpu_set_boot_addr((u32)hsdk_core_init_f);
500
501 smp_kick_cpu_x(cpu_id);
502
503 debug("CPU %u: cross-cpu flag: %x [before timeout]\n", cpu_id,
504 arc_read_uncached_32(&cross_cpu_data.ready_flag));
505
506 while (!arc_read_uncached_32(&cross_cpu_data.ready_flag) && attempts--)
507 mdelay(10);
508
509
510 mdelay(20);
511
512
513
514
515
516 if (!attempts)
517 pr_err("CPU %u is not responding after init!\n", cpu_id);
518
519
520 if (arc_read_uncached_32(&cross_cpu_data.status[cpu_id]) != BOOTSTAGE_2)
521 pr_err("CPU %u status is unexpected: %d\n", cpu_id,
522 arc_read_uncached_32(&cross_cpu_data.status[cpu_id]));
523
524 debug("CPU %u: cross-cpu flag: %x [after timeout]\n", cpu_id,
525 arc_read_uncached_32(&cross_cpu_data.ready_flag));
526 debug("CPU %u: status: %d [after timeout]\n", cpu_id,
527 arc_read_uncached_32(&cross_cpu_data.status[cpu_id]));
528}
529
530static void do_init_slave_cpus(void)
531{
532 clear_cross_cpu_data();
533 sync_cross_cpu_data();
534
535 debug("cross_cpu_data location: %#x\n", (u32)&cross_cpu_data);
536
537 for (u32 i = MASTER_CPU_ID + 1; i < NR_CPUS; i++)
538 if (is_cpu_used(i))
539 do_init_slave_cpu(i);
540}
541
542static void do_init_master_cpu(void)
543{
544
545
546
547
548 init_master_icache();
549 init_master_dcache();
550}
551
552enum hsdk_axi_masters {
553 M_HS_CORE = 0,
554 M_HS_RTT,
555 M_AXI_TUN,
556 M_HDMI_VIDEO,
557 M_HDMI_AUDIO,
558 M_USB_HOST,
559 M_ETHERNET,
560 M_SDIO,
561 M_GPU,
562 M_DMAC_0,
563 M_DMAC_1,
564 M_DVFS
565};
566
567#define UPDATE_VAL 1
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590#define CREG_AXI_M_SLV0(m) ((void __iomem *)(CREG_BASE + 0x020 * (m)))
591#define CREG_AXI_M_SLV1(m) ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x004))
592#define CREG_AXI_M_OFT0(m) ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x008))
593#define CREG_AXI_M_OFT1(m) ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x00C))
594#define CREG_AXI_M_UPDT(m) ((void __iomem *)(CREG_BASE + 0x020 * (m) + 0x014))
595
596#define CREG_AXI_M_HS_CORE_BOOT ((void __iomem *)(CREG_BASE + 0x010))
597
598#define CREG_PAE ((void __iomem *)(CREG_BASE + 0x180))
599#define CREG_PAE_UPDT ((void __iomem *)(CREG_BASE + 0x194))
600
601void init_memory_bridge(void)
602{
603 u32 reg;
604
605
606
607
608
609 reg = readl(CREG_AXI_M_HS_CORE_BOOT) & (~0x3);
610 writel(reg, CREG_AXI_M_HS_CORE_BOOT);
611 writel(0x11111111, CREG_AXI_M_SLV0(M_HS_CORE));
612 writel(0x63111111, CREG_AXI_M_SLV1(M_HS_CORE));
613 writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HS_CORE));
614 writel(0x0E543210, CREG_AXI_M_OFT1(M_HS_CORE));
615 writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HS_CORE));
616
617 writel(0x77777777, CREG_AXI_M_SLV0(M_HS_RTT));
618 writel(0x77777777, CREG_AXI_M_SLV1(M_HS_RTT));
619 writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HS_RTT));
620 writel(0x76543210, CREG_AXI_M_OFT1(M_HS_RTT));
621 writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HS_RTT));
622
623 writel(0x88888888, CREG_AXI_M_SLV0(M_AXI_TUN));
624 writel(0x88888888, CREG_AXI_M_SLV1(M_AXI_TUN));
625 writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_AXI_TUN));
626 writel(0x76543210, CREG_AXI_M_OFT1(M_AXI_TUN));
627 writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_AXI_TUN));
628
629 writel(0x77777777, CREG_AXI_M_SLV0(M_HDMI_VIDEO));
630 writel(0x77777777, CREG_AXI_M_SLV1(M_HDMI_VIDEO));
631 writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HDMI_VIDEO));
632 writel(0x76543210, CREG_AXI_M_OFT1(M_HDMI_VIDEO));
633 writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HDMI_VIDEO));
634
635 writel(0x77777777, CREG_AXI_M_SLV0(M_HDMI_AUDIO));
636 writel(0x77777777, CREG_AXI_M_SLV1(M_HDMI_AUDIO));
637 writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_HDMI_AUDIO));
638 writel(0x76543210, CREG_AXI_M_OFT1(M_HDMI_AUDIO));
639 writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HDMI_AUDIO));
640
641 writel(0x77777777, CREG_AXI_M_SLV0(M_USB_HOST));
642 writel(0x77999999, CREG_AXI_M_SLV1(M_USB_HOST));
643 writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_USB_HOST));
644 writel(0x76DCBA98, CREG_AXI_M_OFT1(M_USB_HOST));
645 writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_USB_HOST));
646
647 writel(0x77777777, CREG_AXI_M_SLV0(M_ETHERNET));
648 writel(0x77999999, CREG_AXI_M_SLV1(M_ETHERNET));
649 writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_ETHERNET));
650 writel(0x76DCBA98, CREG_AXI_M_OFT1(M_ETHERNET));
651 writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_ETHERNET));
652
653 writel(0x77777777, CREG_AXI_M_SLV0(M_SDIO));
654 writel(0x77999999, CREG_AXI_M_SLV1(M_SDIO));
655 writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_SDIO));
656 writel(0x76DCBA98, CREG_AXI_M_OFT1(M_SDIO));
657 writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_SDIO));
658
659 writel(0x77777777, CREG_AXI_M_SLV0(M_GPU));
660 writel(0x77777777, CREG_AXI_M_SLV1(M_GPU));
661 writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_GPU));
662 writel(0x76543210, CREG_AXI_M_OFT1(M_GPU));
663 writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_GPU));
664
665 writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_0));
666 writel(0x77777777, CREG_AXI_M_SLV1(M_DMAC_0));
667 writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_0));
668 writel(0x76543210, CREG_AXI_M_OFT1(M_DMAC_0));
669 writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_0));
670
671 writel(0x77777777, CREG_AXI_M_SLV0(M_DMAC_1));
672 writel(0x77777777, CREG_AXI_M_SLV1(M_DMAC_1));
673 writel(0xFEDCBA98, CREG_AXI_M_OFT0(M_DMAC_1));
674 writel(0x76543210, CREG_AXI_M_OFT1(M_DMAC_1));
675 writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DMAC_1));
676
677 writel(0x00000000, CREG_AXI_M_SLV0(M_DVFS));
678 writel(0x60000000, CREG_AXI_M_SLV1(M_DVFS));
679 writel(0x00000000, CREG_AXI_M_OFT0(M_DVFS));
680 writel(0x00000000, CREG_AXI_M_OFT1(M_DVFS));
681 writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_DVFS));
682
683 writel(0x00000000, CREG_PAE);
684 writel(UPDATE_VAL, CREG_PAE_UPDT);
685}
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711void tweak_memory_bridge_cfg(void)
712{
713
714
715
716
717 if (!is_board_match_config(T_BOARD_HSDK_4XD))
718 return;
719
720 if (env_common.haps_apb.val) {
721 writel(0x61111111, CREG_AXI_M_SLV1(M_HS_CORE));
722 writel(0x06543210, CREG_AXI_M_OFT1(M_HS_CORE));
723 } else {
724 writel(0x63111111, CREG_AXI_M_SLV1(M_HS_CORE));
725 writel(0x0E543210, CREG_AXI_M_OFT1(M_HS_CORE));
726 }
727 writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_HS_CORE));
728
729 writel(0x77779999, CREG_AXI_M_SLV1(M_USB_HOST));
730 writel(0x7654BA98, CREG_AXI_M_OFT1(M_USB_HOST));
731 writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_USB_HOST));
732
733 writel(0x77779999, CREG_AXI_M_SLV1(M_ETHERNET));;
734 writel(0x7654BA98, CREG_AXI_M_OFT1(M_ETHERNET));
735 writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_ETHERNET));
736
737 writel(0x77779999, CREG_AXI_M_SLV1(M_SDIO));
738 writel(0x7654BA98, CREG_AXI_M_OFT1(M_SDIO));
739 writel(UPDATE_VAL, CREG_AXI_M_UPDT(M_SDIO));
740}
741
742static void setup_clocks(void)
743{
744 ulong rate;
745
746
747 if (env_common.cpu_freq.set) {
748 rate = env_common.cpu_freq.val;
749 soc_clk_ctl("cpu-clk", &rate, CLK_ON | CLK_SET | CLK_MHZ);
750 }
751
752
753 if (env_common.tun_freq.set) {
754 rate = env_common.tun_freq.val;
755 if (rate)
756 soc_clk_ctl("tun-clk", &rate, CLK_ON | CLK_SET | CLK_MHZ);
757 else
758 soc_clk_ctl("tun-clk", NULL, CLK_OFF);
759 }
760
761 if (env_common.axi_freq.set) {
762 rate = env_common.axi_freq.val;
763 soc_clk_ctl("axi-clk", &rate, CLK_SET | CLK_ON | CLK_MHZ);
764 }
765}
766
767static void do_init_cluster(void)
768{
769
770
771
772
773
774 init_cluster_nvlim();
775 init_cluster_csm();
776 init_cluster_slc();
777 tweak_memory_bridge_cfg();
778}
779
780static int check_master_cpu_id(void)
781{
782 if (CPU_ID_GET() == MASTER_CPU_ID)
783 return 0;
784
785 pr_err("u-boot runs on non-master cpu with id: %lu\n", CPU_ID_GET());
786
787 return -ENOENT;
788}
789
790static noinline int prepare_cpus(void)
791{
792 int ret;
793
794 ret = check_master_cpu_id();
795 if (ret)
796 return ret;
797
798 ret = envs_process_and_validate(env_map_common, env_map_core, is_cpu_used);
799 if (ret)
800 return ret;
801
802 printf("CPU start mask is %#x\n", env_common.core_mask.val);
803
804 do_init_slave_cpus();
805 do_init_master_cpu();
806 do_init_cluster();
807
808 return 0;
809}
810
811static int hsdk_go_run(u32 cpu_start_reg)
812{
813
814 cleanup_before_go();
815
816 if (env_common.halt_on_boot)
817 halt_this_cpu();
818
819
820
821
822
823 __builtin_arc_nop();
824 __builtin_arc_nop();
825 __builtin_arc_nop();
826
827
828 writel(cpu_start_reg, (void __iomem *)CREG_CPU_START);
829
830 if (is_cpu_used(MASTER_CPU_ID))
831 ((void (*)(void))(env_core.entry[MASTER_CPU_ID].val))();
832 else
833 halt_this_cpu();
834
835 pr_err("u-boot still runs on cpu [%ld]\n", CPU_ID_GET());
836
837
838
839
840
841 while (true)
842 halt_this_cpu();
843
844 return 0;
845}
846
847int board_prep_linux(bootm_headers_t *images)
848{
849 int ret, ofst;
850 char mask[15];
851
852 ret = envs_read_validate_common(env_map_mask);
853 if (ret)
854 return ret;
855
856
857 if (!env_common.core_mask.set) {
858 env_common.core_mask.val = ALL_CPU_MASK;
859 env_common.core_mask.set = true;
860 }
861
862 printf("CPU start mask is %#x\n", env_common.core_mask.val);
863
864 if (!is_cpu_used(MASTER_CPU_ID))
865 pr_err("ERR: try to launch linux with CPU[0] disabled! It doesn't work for ARC.\n");
866
867
868
869
870
871 if (env_common.core_mask.val == ALL_CPU_MASK)
872 return 0;
873
874 if (!CONFIG_IS_ENABLED(OF_LIBFDT) || !images->ft_len) {
875 pr_err("WARN: core_mask setup will work properly only with external DTB!\n");
876 return 0;
877 }
878
879
880 ofst = fdt_path_offset(images->ft_addr, "/");
881 sprintf(mask, "%s%s%s%s",
882 is_cpu_used(0) ? "0," : "",
883 is_cpu_used(1) ? "1," : "",
884 is_cpu_used(2) ? "2," : "",
885 is_cpu_used(3) ? "3," : "");
886 ret = fdt_setprop_string(images->ft_addr, ofst, "possible-cpus", mask);
887
888
889
890
891
892
893 if (ret)
894 pr_err("WARN: failed to patch '/possible-cpus' property, ret=%d\n",
895 ret);
896
897 return 0;
898}
899
900void board_jump_and_run(ulong entry, int zero, int arch, uint params)
901{
902 void (*kernel_entry)(int zero, int arch, uint params);
903 u32 cpu_start_reg;
904
905 kernel_entry = (void (*)(int, int, uint))entry;
906
907
908 cpu_start_reg = prepare_cpu_ctart_reg();
909
910
911 slave_cpu_set_boot_addr(entry);
912
913
914 for (u32 i = 0; i < NR_CPUS; i++) {
915 env_core.entry[i].val = entry;
916 env_core.entry[i].set = true;
917 }
918
919 sync_cross_cpu_data();
920
921
922 writel(cpu_start_reg, (void __iomem *)CREG_CPU_START);
923
924 if (is_cpu_used(0))
925 kernel_entry(zero, arch, params);
926}
927
928static int hsdk_go_prepare_and_run(void)
929{
930
931 u32 reg = prepare_cpu_ctart_reg();
932
933 if (env_common.halt_on_boot)
934 printf("CPU will halt before application start, start application with debugger.\n");
935
936 return hsdk_go_run(reg);
937}
938
939static int do_hsdk_go(struct cmd_tbl *cmdtp, int flag, int argc,
940 char *const argv[])
941{
942 int ret;
943
944 if (board_mismatch()) {
945 printf("ERR: U-boot is not configured for this board!\n");
946 return CMD_RET_FAILURE;
947 }
948
949
950
951
952
953 if (argc > 1) {
954 env_common.halt_on_boot = !strcmp(argv[1], "halt");
955 if (!env_common.halt_on_boot) {
956 pr_err("Unrecognised parameter: \'%s\'\n", argv[1]);
957 return CMD_RET_FAILURE;
958 }
959 }
960
961 ret = check_master_cpu_id();
962 if (ret)
963 return ret;
964
965 ret = envs_process_and_validate(env_map_mask, env_map_go, is_cpu_used);
966 if (ret)
967 return ret;
968
969
970 sync_cross_cpu_data();
971
972 ret = hsdk_go_prepare_and_run();
973
974 return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
975}
976
977U_BOOT_CMD(
978 hsdk_go, 3, 0, do_hsdk_go,
979 "Synopsys HSDK specific command",
980 " - Boot stand-alone application on HSDK\n"
981 "hsdk_go halt - Boot stand-alone application on HSDK, halt CPU just before application run\n"
982);
983
984
985
986
987
988
989
990
991#define INIT_MARKER_REGISTER ((void __iomem *)CREG_CPU_0_ENTRY)
992
993#define INIT_MARKER_PENDING 0
994
995static bool init_marker_get(void)
996{
997 return readl(INIT_MARKER_REGISTER) != INIT_MARKER_PENDING;
998}
999
1000static void init_mark_done(void)
1001{
1002 writel(~INIT_MARKER_PENDING, INIT_MARKER_REGISTER);
1003}
1004
1005static int do_hsdk_init(struct cmd_tbl *cmdtp, int flag, int argc,
1006 char *const argv[])
1007{
1008 int ret;
1009
1010 if (board_mismatch()) {
1011 printf("ERR: U-boot is not configured for this board!\n");
1012 return CMD_RET_FAILURE;
1013 }
1014
1015
1016 if (init_marker_get()) {
1017 printf("HSDK HW is already initialized! Please reset the board if you want to change the configuration.\n");
1018 return CMD_RET_FAILURE;
1019 }
1020
1021 ret = prepare_cpus();
1022 if (!ret)
1023 init_mark_done();
1024
1025 return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
1026}
1027
1028U_BOOT_CMD(
1029 hsdk_init, 1, 0, do_hsdk_init,
1030 "Synopsys HSDK specific command",
1031 "- Init HSDK HW\n"
1032);
1033
1034static int do_hsdk_clock_set(struct cmd_tbl *cmdtp, int flag, int argc,
1035 char *const argv[])
1036{
1037 int ret = 0;
1038
1039
1040 argc--;
1041 argv++;
1042
1043 envs_cleanup_common(env_map_clock);
1044
1045 if (!argc) {
1046 printf("Set clocks to values specified in environment\n");
1047 ret = envs_read_common(env_map_clock);
1048 } else {
1049 printf("Set clocks to values specified in args\n");
1050 ret = args_envs_enumerate(env_map_clock, 2, argc, argv);
1051 }
1052
1053 if (ret)
1054 return CMD_RET_FAILURE;
1055
1056 ret = envs_validate_common(env_map_clock);
1057 if (ret)
1058 return CMD_RET_FAILURE;
1059
1060
1061 setup_clocks();
1062
1063 return CMD_RET_SUCCESS;
1064}
1065
1066static int do_hsdk_clock_get(struct cmd_tbl *cmdtp, int flag, int argc,
1067 char *const argv[])
1068{
1069 ulong rate;
1070
1071 if (soc_clk_ctl("cpu-clk", &rate, CLK_GET | CLK_MHZ))
1072 return CMD_RET_FAILURE;
1073
1074 if (env_set_ulong("cpu_freq", rate))
1075 return CMD_RET_FAILURE;
1076
1077 if (soc_clk_ctl("tun-clk", &rate, CLK_GET | CLK_MHZ))
1078 return CMD_RET_FAILURE;
1079
1080 if (env_set_ulong("tun_freq", rate))
1081 return CMD_RET_FAILURE;
1082
1083 if (soc_clk_ctl("axi-clk", &rate, CLK_GET | CLK_MHZ))
1084 return CMD_RET_FAILURE;
1085
1086 if (env_set_ulong("axi_freq", rate))
1087 return CMD_RET_FAILURE;
1088
1089 printf("Clock values are saved to environment\n");
1090
1091 return CMD_RET_SUCCESS;
1092}
1093
1094static int do_hsdk_clock_print(struct cmd_tbl *cmdtp, int flag, int argc,
1095 char *const argv[])
1096{
1097
1098 soc_clk_ctl("cpu-clk", NULL, CLK_PRINT | CLK_MHZ);
1099 soc_clk_ctl("tun-clk", NULL, CLK_PRINT | CLK_MHZ);
1100 soc_clk_ctl("axi-clk", NULL, CLK_PRINT | CLK_MHZ);
1101 soc_clk_ctl("ddr-clk", NULL, CLK_PRINT | CLK_MHZ);
1102
1103 return CMD_RET_SUCCESS;
1104}
1105
1106static int do_hsdk_clock_print_all(struct cmd_tbl *cmdtp, int flag, int argc,
1107 char *const argv[])
1108{
1109
1110
1111
1112
1113
1114
1115
1116
1117 soc_clk_ctl("cpu-pll", NULL, CLK_PRINT | CLK_MHZ);
1118 soc_clk_ctl("cpu-clk", NULL, CLK_PRINT | CLK_MHZ);
1119 printf("\n");
1120
1121
1122 soc_clk_ctl("sys-pll", NULL, CLK_PRINT | CLK_MHZ);
1123 soc_clk_ctl("apb-clk", NULL, CLK_PRINT | CLK_MHZ);
1124 soc_clk_ctl("axi-clk", NULL, CLK_PRINT | CLK_MHZ);
1125 soc_clk_ctl("eth-clk", NULL, CLK_PRINT | CLK_MHZ);
1126 soc_clk_ctl("usb-clk", NULL, CLK_PRINT | CLK_MHZ);
1127 soc_clk_ctl("sdio-clk", NULL, CLK_PRINT | CLK_MHZ);
1128 if (is_board_match_runtime(T_BOARD_HSDK_4XD))
1129 soc_clk_ctl("hdmi-sys-clk", NULL, CLK_PRINT | CLK_MHZ);
1130 soc_clk_ctl("gfx-core-clk", NULL, CLK_PRINT | CLK_MHZ);
1131 if (is_board_match_runtime(T_BOARD_HSDK)) {
1132 soc_clk_ctl("gfx-dma-clk", NULL, CLK_PRINT | CLK_MHZ);
1133 soc_clk_ctl("gfx-cfg-clk", NULL, CLK_PRINT | CLK_MHZ);
1134 }
1135 soc_clk_ctl("dmac-core-clk", NULL, CLK_PRINT | CLK_MHZ);
1136 soc_clk_ctl("dmac-cfg-clk", NULL, CLK_PRINT | CLK_MHZ);
1137 soc_clk_ctl("sdio-ref-clk", NULL, CLK_PRINT | CLK_MHZ);
1138 soc_clk_ctl("spi-clk", NULL, CLK_PRINT | CLK_MHZ);
1139 soc_clk_ctl("i2c-clk", NULL, CLK_PRINT | CLK_MHZ);
1140
1141 soc_clk_ctl("uart-clk", NULL, CLK_PRINT | CLK_MHZ);
1142 printf("\n");
1143
1144
1145 soc_clk_ctl("ddr-clk", NULL, CLK_PRINT | CLK_MHZ);
1146 printf("\n");
1147
1148
1149 if (is_board_match_runtime(T_BOARD_HSDK_4XD)) {
1150 soc_clk_ctl("hdmi-pll", NULL, CLK_PRINT | CLK_MHZ);
1151 soc_clk_ctl("hdmi-clk", NULL, CLK_PRINT | CLK_MHZ);
1152 printf("\n");
1153 }
1154
1155
1156 soc_clk_ctl("tun-pll", NULL, CLK_PRINT | CLK_MHZ);
1157 soc_clk_ctl("tun-clk", NULL, CLK_PRINT | CLK_MHZ);
1158 soc_clk_ctl("rom-clk", NULL, CLK_PRINT | CLK_MHZ);
1159 soc_clk_ctl("pwm-clk", NULL, CLK_PRINT | CLK_MHZ);
1160 if (is_board_match_runtime(T_BOARD_HSDK_4XD))
1161 soc_clk_ctl("timer-clk", NULL, CLK_PRINT | CLK_MHZ);
1162 printf("\n");
1163
1164 return CMD_RET_SUCCESS;
1165}
1166
1167struct cmd_tbl cmd_hsdk_clock[] = {
1168 U_BOOT_CMD_MKENT(set, 3, 0, do_hsdk_clock_set, "", ""),
1169 U_BOOT_CMD_MKENT(get, 3, 0, do_hsdk_clock_get, "", ""),
1170 U_BOOT_CMD_MKENT(print, 4, 0, do_hsdk_clock_print, "", ""),
1171 U_BOOT_CMD_MKENT(print_all, 4, 0, do_hsdk_clock_print_all, "", ""),
1172};
1173
1174static int do_hsdk_clock(struct cmd_tbl *cmdtp, int flag, int argc,
1175 char *const argv[])
1176{
1177 struct cmd_tbl *c;
1178
1179 if (argc < 2)
1180 return CMD_RET_USAGE;
1181
1182
1183 argc--;
1184 argv++;
1185
1186 c = find_cmd_tbl(argv[0], cmd_hsdk_clock, ARRAY_SIZE(cmd_hsdk_clock));
1187 if (!c)
1188 return CMD_RET_USAGE;
1189
1190 return c->cmd(cmdtp, flag, argc, argv);
1191}
1192
1193U_BOOT_CMD(
1194 hsdk_clock, CONFIG_SYS_MAXARGS, 0, do_hsdk_clock,
1195 "Synopsys HSDK specific clock command",
1196 "set - Set clock to values specified in environment / command line arguments\n"
1197 "hsdk_clock get - Save clock values to environment\n"
1198 "hsdk_clock print - Print main clock values to console\n"
1199 "hsdk_clock print_all - Print all clock values to console\n"
1200);
1201
1202
1203int board_early_init_f(void)
1204{
1205
1206
1207
1208
1209 init_memory_bridge();
1210
1211
1212
1213
1214
1215 writel(SDIO_UHS_REG_EXT_DIV_2, (void __iomem *)SDIO_UHS_REG_EXT);
1216
1217 return 0;
1218}
1219
1220int board_early_init_r(void)
1221{
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236 flush_dcache_all();
1237
1238 printf("Relocation Offset is: %08lx\n", gd->reloc_off);
1239
1240 return 0;
1241}
1242
1243int board_late_init(void)
1244{
1245
1246
1247
1248
1249 do_hsdk_clock_get(NULL, 0, 0, NULL);
1250
1251 return 0;
1252}
1253
1254int checkboard(void)
1255{
1256 u32 reg;
1257
1258 printf("Board: Synopsys %s\n", board_name(get_board_type_runtime()));
1259
1260 if (board_mismatch())
1261 printf("WARN: U-boot is configured NOT for this board but for %s!\n",
1262 board_name(get_board_type_config()));
1263
1264 reg = readl(CREG_AXI_M_HS_CORE_BOOT) & CREG_CORE_BOOT_IMAGE;
1265 printf("U-boot autostart: %s\n", reg ? "enabled" : "disabled");
1266
1267 return 0;
1268};
1269