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