1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2020 - Cortina Access Inc.
4  *
5  */
6 #include <common.h>
7 #include <init.h>
8 #include <malloc.h>
9 #include <errno.h>
10 #include <netdev.h>
11 #include <asm/global_data.h>
12 #include <asm/io.h>
13 #include <linux/bitops.h>
14 #include <linux/compiler.h>
15 #include <configs/presidio_asic.h>
16 #include <linux/psci.h>
17 #include <asm/psci.h>
18 #include <cpu_func.h>
19 #include <asm/armv8/mmu.h>
20 
21 DECLARE_GLOBAL_DATA_PTR;
22 
23 #define CA_PERIPH_BASE                  0xE0000000UL
24 #define CA_PERIPH_SIZE                  0x20000000UL
25 #define CA_GLOBAL_BASE                  0xf4320000
26 #define CA_GLOBAL_JTAG_ID               0xf4320000
27 #define CA_GLOBAL_BLOCK_RESET           0xf4320004
28 #define CA_GLOBAL_BLOCK_RESET_RESET_DMA BIT(16)
29 #define CA_DMA_SEC_SSP_BAUDRATE_CTRL    0xf7001b94
30 #define CA_DMA_SEC_SSP_ID               0xf7001b80
31 
print_cpuinfo(void)32 int print_cpuinfo(void)
33 {
34 	printf("CPU:   Cortina Presidio G3\n");
35 	return 0;
36 }
37 
38 static struct mm_region presidio_mem_map[] = {
39 	{
40 	.virt = DDR_BASE,
41 	.phys = DDR_BASE,
42 	.size = PHYS_SDRAM_1_SIZE,
43 	.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
44 		 PTE_BLOCK_OUTER_SHARE
45 	},
46 	{
47 	.virt = CA_PERIPH_BASE,
48 	.phys = CA_PERIPH_BASE,
49 	.size = CA_PERIPH_SIZE,
50 	.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
51 		 PTE_BLOCK_NON_SHARE
52 	},
53 	{
54 	/* List terminator */
55 	0,
56 	}
57 };
58 
59 struct mm_region *mem_map = presidio_mem_map;
60 
invoke_psci_fn_smc(u64 function_id,u64 arg0,u64 arg1,u64 arg2)61 static noinline int invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1,
62 				       u64 arg2)
63 {
64 	asm volatile("mov x0, %0\n"
65 		    "mov x1, %1\n"
66 		    "mov x2, %2\n"
67 		    "mov x3, %3\n"
68 		    "smc	#0\n"
69 		    : "+r" (function_id)
70 		    : "r" (arg0), "r" (arg1), "r" (arg2)
71 		    );
72 
73 	return function_id;
74 }
75 
board_early_init_r(void)76 int board_early_init_r(void)
77 {
78 	dcache_disable();
79 	return 0;
80 }
81 
board_init(void)82 int board_init(void)
83 {
84 	unsigned int reg_data, jtag_id;
85 
86 	/* Enable timer */
87 	writel(1, CONFIG_SYS_TIMER_BASE);
88 
89 	/* Enable snoop in CCI400 slave port#4 */
90 	writel(3, 0xF5595000);
91 
92 	jtag_id = readl(CA_GLOBAL_JTAG_ID);
93 
94 	/* If this is HGU variant then do not use
95 	 * the Saturn daughter card ref. clk
96 	 */
97 	if (jtag_id == 0x1010D8F3) {
98 		reg_data = readl(0xF3100064);
99 		/* change multifunc. REF CLK pin to
100 		 * a simple GPIO pin
101 		 */
102 		reg_data |= (1 << 1);
103 		writel(reg_data, 0xf3100064);
104 	}
105 
106 	return 0;
107 }
108 
dram_init(void)109 int dram_init(void)
110 {
111 	unsigned int ddr_size;
112 
113 	ddr_size = readl(0x111100c);
114 	gd->ram_size = ddr_size * 0x100000;
115 	return 0;
116 }
117 
reset_cpu(void)118 void reset_cpu(void)
119 {
120 	invoke_psci_fn_smc(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
121 }
122 
123 #ifdef CONFIG_LAST_STAGE_INIT
last_stage_init(void)124 int last_stage_init(void)
125 {
126 	u32 val;
127 
128 	val = readl(CA_GLOBAL_BLOCK_RESET);
129 	val &= ~CA_GLOBAL_BLOCK_RESET_RESET_DMA;
130 	writel(val, CA_GLOBAL_BLOCK_RESET);
131 
132 	/* reduce output pclk ~3.7Hz to save power consumption */
133 	writel(0x000000FF, CA_DMA_SEC_SSP_BAUDRATE_CTRL);
134 
135 	return 0;
136 }
137 #endif
138