clk: fixed-rate: Enable DM_FLAG_PRE_RELOC flag
[platform/kernel/u-boot.git] / board / broadcom / bcmns3 / ns3.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2020 Broadcom.
4  *
5  */
6
7 #include <common.h>
8 #include <fdt_support.h>
9 #include <asm/io.h>
10 #include <asm/gic-v3.h>
11 #include <asm/system.h>
12 #include <asm/armv8/mmu.h>
13 #include <asm/arch-bcmns3/bl33_info.h>
14 #include <dt-bindings/memory/bcm-ns3-mc.h>
15
16 /* Default reset-level = 3 and strap-val = 0 */
17 #define L3_RESET        30
18
19 #define BANK_OFFSET(bank)      ((u64)BCM_NS3_DDR_INFO_BASE + 8 + ((bank) * 16))
20
21 /*
22  * ns3_dram_bank - DDR bank details
23  *
24  * @start: DDR bank start address
25  * @len: DDR bank length
26  */
27 struct ns3_dram_bank {
28         u64 start[BCM_NS3_MAX_NR_BANKS];
29         u64 len[BCM_NS3_MAX_NR_BANKS];
30 };
31
32 /*
33  * ns3_dram_hdr - DDR header info
34  *
35  * @sig: DDR info signature
36  * @bank: DDR bank details
37  */
38 struct ns3_dram_hdr {
39         u32 sig;
40         struct ns3_dram_bank bank;
41 };
42
43 static struct mm_region ns3_mem_map[] = {
44         {
45                 .virt = 0x0UL,
46                 .phys = 0x0UL,
47                 .size = 0x80000000UL,
48                 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
49                          PTE_BLOCK_NON_SHARE |
50                          PTE_BLOCK_PXN | PTE_BLOCK_UXN
51         }, {
52                 .virt = BCM_NS3_MEM_START,
53                 .phys = BCM_NS3_MEM_START,
54                 .size = BCM_NS3_MEM_LEN,
55                 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
56                          PTE_BLOCK_INNER_SHARE
57         }, {
58                 .virt = BCM_NS3_BANK_1_MEM_START,
59                 .phys = BCM_NS3_BANK_1_MEM_START,
60                 .size = BCM_NS3_BANK_1_MEM_LEN,
61                 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
62                          PTE_BLOCK_INNER_SHARE
63         }, {
64                 /* List terminator */
65                 0,
66         }
67 };
68
69 struct mm_region *mem_map = ns3_mem_map;
70
71 DECLARE_GLOBAL_DATA_PTR;
72
73 /*
74  * Force the bl33_info to the data-section, as .bss will not be valid
75  * when save_boot_params is invoked.
76  */
77 struct bl33_info *bl33_info __section(".data");
78
79 /*
80  * Run modulo 256 checksum calculation and return the calculated checksum
81  */
82 static u8 checksum_calc(u8 *p, unsigned int len)
83 {
84         unsigned int i;
85         u8 chksum = 0;
86
87         for (i = 0; i < len; i++)
88                 chksum += p[i];
89
90         return chksum;
91 }
92
93 /*
94  * This function parses the memory layout information from a reserved area in
95  * DDR, and then fix up the FDT before passing it to Linux.
96  *
97  * In the case of error, do nothing and the default memory layout in DT will
98  * be used
99  */
100 static int mem_info_parse_fixup(void *fdt)
101 {
102         struct ns3_dram_hdr hdr;
103         u32 *p32, i, nr_banks;
104         u64 *p64;
105
106         /* validate signature */
107         p32 = (u32 *)BCM_NS3_DDR_INFO_BASE;
108         hdr.sig = *p32;
109         if (hdr.sig != BCM_NS3_DDR_INFO_SIG) {
110                 printf("DDR info signature 0x%x invalid\n", hdr.sig);
111                 return -EINVAL;
112         }
113
114         /* run checksum test to validate data  */
115         if (checksum_calc((u8 *)p32, BCM_NS3_DDR_INFO_LEN) != 0) {
116                 printf("Checksum on DDR info failed\n");
117                 return -EINVAL;
118         }
119
120         /* parse information for each bank */
121         nr_banks = 0;
122         for (i = 0; i < BCM_NS3_MAX_NR_BANKS; i++) {
123                 /* skip banks with a length of zero */
124                 p64 = (u64 *)BANK_OFFSET(i);
125                 if (*(p64 + 1) == 0)
126                         continue;
127
128                 hdr.bank.start[i] = *p64;
129                 hdr.bank.len[i] = *(p64 + 1);
130
131                 printf("mem[%u] 0x%llx - 0x%llx\n", i, hdr.bank.start[i],
132                        hdr.bank.start[i] + hdr.bank.len[i] - 1);
133                 nr_banks++;
134         }
135
136         if (!nr_banks) {
137                 printf("No DDR banks detected\n");
138                 return -ENOMEM;
139         }
140
141         return fdt_fixup_memory_banks(fdt, hdr.bank.start, hdr.bank.len,
142                                       nr_banks);
143 }
144
145 int board_init(void)
146 {
147         /* Setup memory using "memory" node from DTB */
148         if (fdtdec_setup_mem_size_base() != 0)
149                 return -EINVAL;
150         fdtdec_setup_memory_banksize();
151
152         if (bl33_info->version != BL33_INFO_VERSION)
153                 printf("*** warning: ATF BL31 and U-Boot not in sync! ***\n");
154
155         return 0;
156 }
157
158 int board_late_init(void)
159 {
160         return 0;
161 }
162
163 int dram_init(void)
164 {
165         /*
166          * Mark ram base as the last 16MB of 2GB DDR, which is 0xFF00_0000.
167          * So that relocation happens with in the last 16MB memory.
168          */
169         gd->ram_base = (phys_size_t)(BCM_NS3_MEM_END - SZ_16M);
170         gd->ram_size = (unsigned long)SZ_16M;
171
172         return 0;
173 }
174
175 int dram_init_banksize(void)
176 {
177         gd->bd->bi_dram[0].start = (BCM_NS3_MEM_END - SZ_16M);
178         gd->bd->bi_dram[0].size = SZ_16M;
179
180         return 0;
181 }
182
183 /* Limit RAM used by U-Boot to the DDR first bank End region */
184 ulong board_get_usable_ram_top(ulong total_size)
185 {
186         return BCM_NS3_MEM_END;
187 }
188
189 void reset_cpu(ulong level)
190 {
191         u32 reset_level, strap_val;
192
193         /* Default reset type is L3 reset */
194         if (!level) {
195                 /*
196                  * Encoding: U-Boot reset command expects decimal argument,
197                  * Boot strap val: Bits[3:0]
198                  * reset level: Bits[7:4]
199                  */
200                 strap_val = L3_RESET % 10;
201                 level = L3_RESET / 10;
202                 reset_level = level % 10;
203                 psci_system_reset2(reset_level, strap_val);
204         } else {
205                 /* U-Boot cmd "reset" with any arg will trigger L1 reset */
206                 psci_system_reset();
207         }
208 }
209
210 #ifdef CONFIG_OF_BOARD_SETUP
211 int ft_board_setup(void *fdt, struct bd_info *bd)
212 {
213         gic_lpi_tables_init();
214
215         return mem_info_parse_fixup(fdt);
216 }
217 #endif /* CONFIG_OF_BOARD_SETUP */