1 /* 2 * Copyright 2007,2009-2014 Freescale Semiconductor, Inc. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <command.h> 9 #include <pci.h> 10 #include <asm/processor.h> 11 #include <asm/mmu.h> 12 #include <asm/fsl_pci.h> 13 #include <asm/io.h> 14 #include <libfdt.h> 15 #include <fdt_support.h> 16 #include <netdev.h> 17 #include <fdtdec.h> 18 #include <errno.h> 19 #include <malloc.h> 20 21 DECLARE_GLOBAL_DATA_PTR; 22 23 static void *get_fdt_virt(void) 24 { 25 return (void *)CONFIG_SYS_TMPVIRT; 26 } 27 28 static uint64_t get_fdt_phys(void) 29 { 30 return (uint64_t)(uintptr_t)gd->fdt_blob; 31 } 32 33 static void map_fdt_as(int esel) 34 { 35 u32 mas0, mas1, mas2, mas3, mas7; 36 uint64_t fdt_phys = get_fdt_phys(); 37 unsigned long fdt_phys_tlb = fdt_phys & ~0xffffful; 38 unsigned long fdt_virt_tlb = (ulong)get_fdt_virt() & ~0xffffful; 39 40 mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(esel); 41 mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS | MAS1_TSIZE(BOOKE_PAGESZ_1M); 42 mas2 = FSL_BOOKE_MAS2(fdt_virt_tlb, 0); 43 mas3 = FSL_BOOKE_MAS3(fdt_phys_tlb, 0, MAS3_SW|MAS3_SR); 44 mas7 = FSL_BOOKE_MAS7(fdt_phys_tlb); 45 46 write_tlb(mas0, mas1, mas2, mas3, mas7); 47 } 48 49 uint64_t get_phys_ccsrbar_addr_early(void) 50 { 51 void *fdt = get_fdt_virt(); 52 uint64_t r; 53 54 /* 55 * To be able to read the FDT we need to create a temporary TLB 56 * map for it. 57 */ 58 map_fdt_as(10); 59 r = fdt_get_base_address(fdt, fdt_path_offset(fdt, "/soc")); 60 disable_tlb(10); 61 62 return r; 63 } 64 65 int board_early_init_f(void) 66 { 67 return 0; 68 } 69 70 int checkboard(void) 71 { 72 return 0; 73 } 74 75 static int pci_map_region(void *fdt, int pci_node, int range_id, 76 phys_size_t *ppaddr, pci_addr_t *pvaddr, 77 pci_size_t *psize, ulong *pmap_addr) 78 { 79 uint64_t addr; 80 uint64_t size; 81 ulong map_addr; 82 int r; 83 84 r = fdt_read_range(fdt, pci_node, 0, NULL, &addr, &size); 85 if (r) 86 return r; 87 88 if (ppaddr) 89 *ppaddr = addr; 90 if (psize) 91 *psize = size; 92 93 if (!pmap_addr) 94 return 0; 95 96 map_addr = *pmap_addr; 97 98 /* Align map_addr */ 99 map_addr += size - 1; 100 map_addr &= ~(size - 1); 101 102 if (map_addr + size >= CONFIG_SYS_PCI_MAP_END) 103 return -1; 104 105 /* Map virtual memory for range */ 106 assert(!tlb_map_range(map_addr, addr, size, TLB_MAP_IO)); 107 *pmap_addr = map_addr + size; 108 109 if (pvaddr) 110 *pvaddr = map_addr; 111 112 return 0; 113 } 114 115 void pci_init_board(void) 116 { 117 struct pci_controller *pci_hoses; 118 void *fdt = get_fdt_virt(); 119 int pci_node = -1; 120 int pci_num = 0; 121 int pci_count = 0; 122 ulong map_addr; 123 124 puts("\n"); 125 126 /* Start MMIO and PIO range maps above RAM */ 127 map_addr = CONFIG_SYS_PCI_MAP_START; 128 129 /* Count and allocate PCI buses */ 130 pci_node = fdt_node_offset_by_prop_value(fdt, pci_node, 131 "device_type", "pci", 4); 132 while (pci_node != -FDT_ERR_NOTFOUND) { 133 pci_node = fdt_node_offset_by_prop_value(fdt, pci_node, 134 "device_type", "pci", 4); 135 pci_count++; 136 } 137 138 if (pci_count) { 139 pci_hoses = malloc(sizeof(struct pci_controller) * pci_count); 140 } else { 141 printf("PCI: disabled\n\n"); 142 return; 143 } 144 145 /* Spawn PCI buses based on device tree */ 146 pci_node = fdt_node_offset_by_prop_value(fdt, pci_node, 147 "device_type", "pci", 4); 148 while (pci_node != -FDT_ERR_NOTFOUND) { 149 struct fsl_pci_info pci_info = { }; 150 const fdt32_t *reg; 151 int r; 152 153 reg = fdt_getprop(fdt, pci_node, "reg", NULL); 154 pci_info.regs = fdt_translate_address(fdt, pci_node, reg); 155 156 /* Map MMIO range */ 157 r = pci_map_region(fdt, pci_node, 0, &pci_info.mem_phys, NULL, 158 &pci_info.mem_size, &map_addr); 159 if (r) 160 break; 161 162 /* Map PIO range */ 163 r = pci_map_region(fdt, pci_node, 1, &pci_info.io_phys, NULL, 164 &pci_info.io_size, &map_addr); 165 if (r) 166 break; 167 168 /* 169 * The PCI framework finds virtual addresses for the buses 170 * through our address map, so tell it the physical addresses. 171 */ 172 pci_info.mem_bus = pci_info.mem_phys; 173 pci_info.io_bus = pci_info.io_phys; 174 175 /* Instantiate */ 176 pci_info.pci_num = pci_num + 1; 177 178 fsl_setup_hose(&pci_hoses[pci_num], pci_info.regs); 179 printf("PCI: base address %lx\n", pci_info.regs); 180 181 fsl_pci_init_port(&pci_info, &pci_hoses[pci_num], pci_num); 182 183 /* Jump to next PCI node */ 184 pci_node = fdt_node_offset_by_prop_value(fdt, pci_node, 185 "device_type", "pci", 4); 186 pci_num++; 187 } 188 189 puts("\n"); 190 } 191 192 int last_stage_init(void) 193 { 194 void *fdt = get_fdt_virt(); 195 int len = 0; 196 const uint64_t *prop; 197 int chosen; 198 199 chosen = fdt_path_offset(fdt, "/chosen"); 200 if (chosen < 0) { 201 printf("Couldn't find /chosen node in fdt\n"); 202 return -EIO; 203 } 204 205 /* -kernel boot */ 206 prop = fdt_getprop(fdt, chosen, "qemu,boot-kernel", &len); 207 if (prop && (len >= 8)) 208 setenv_hex("qemu_kernel_addr", *prop); 209 210 /* Give the user a variable for the host fdt */ 211 setenv_hex("fdt_addr_r", (ulong)fdt); 212 213 return 0; 214 } 215 216 static uint64_t get_linear_ram_size(void) 217 { 218 void *fdt = get_fdt_virt(); 219 const void *prop; 220 int memory; 221 int len; 222 223 memory = fdt_path_offset(fdt, "/memory"); 224 prop = fdt_getprop(fdt, memory, "reg", &len); 225 226 if (prop && len >= 16) 227 return *(uint64_t *)(prop+8); 228 229 panic("Couldn't determine RAM size"); 230 } 231 232 int board_eth_init(bd_t *bis) 233 { 234 return pci_eth_init(bis); 235 } 236 237 #if defined(CONFIG_OF_BOARD_SETUP) 238 void ft_board_setup(void *blob, bd_t *bd) 239 { 240 FT_FSL_PCI_SETUP; 241 } 242 #endif 243 244 void print_laws(void) 245 { 246 /* We don't emulate LAWs yet */ 247 } 248 249 phys_size_t fixed_sdram(void) 250 { 251 return get_linear_ram_size(); 252 } 253 254 phys_size_t fsl_ddr_sdram_size(void) 255 { 256 return get_linear_ram_size(); 257 } 258 259 void init_tlbs(void) 260 { 261 phys_size_t ram_size; 262 263 /* 264 * Create a temporary AS=1 map for the fdt 265 * 266 * We use ESEL=0 here to overwrite the previous AS=0 map for ourselves 267 * which was only 4k big. This way we don't have to clear any other maps. 268 */ 269 map_fdt_as(0); 270 271 /* Fetch RAM size from the fdt */ 272 ram_size = get_linear_ram_size(); 273 274 /* And remove our fdt map again */ 275 disable_tlb(0); 276 277 /* Create an internal map of manually created TLB maps */ 278 init_used_tlb_cams(); 279 280 /* Create a dynamic AS=0 CCSRBAR mapping */ 281 assert(!tlb_map_range(CONFIG_SYS_CCSRBAR, CONFIG_SYS_CCSRBAR_PHYS, 282 1024 * 1024, TLB_MAP_IO)); 283 284 /* Create a RAM map that spans all accessible RAM */ 285 setup_ddr_tlbs(ram_size >> 20); 286 287 /* Create a map for the TLB */ 288 assert(!tlb_map_range((ulong)get_fdt_virt(), get_fdt_phys(), 289 1024 * 1024, TLB_MAP_RAM)); 290 } 291 292 void init_laws(void) 293 { 294 /* We don't emulate LAWs yet */ 295 } 296 297 static uint32_t get_cpu_freq(void) 298 { 299 void *fdt = get_fdt_virt(); 300 int cpus_node = fdt_path_offset(fdt, "/cpus"); 301 int cpu_node = fdt_first_subnode(fdt, cpus_node); 302 const char *prop = "clock-frequency"; 303 return fdt_getprop_u32_default_node(fdt, cpu_node, 0, prop, 0); 304 } 305 306 void get_sys_info(sys_info_t *sys_info) 307 { 308 int freq = get_cpu_freq(); 309 310 memset(sys_info, 0, sizeof(sys_info_t)); 311 sys_info->freq_systembus = freq; 312 sys_info->freq_ddrbus = freq; 313 sys_info->freq_processor[0] = freq; 314 } 315 316 int get_clocks (void) 317 { 318 sys_info_t sys_info; 319 320 get_sys_info(&sys_info); 321 322 gd->cpu_clk = sys_info.freq_processor[0]; 323 gd->bus_clk = sys_info.freq_systembus; 324 gd->mem_clk = sys_info.freq_ddrbus; 325 gd->arch.lbc_clk = sys_info.freq_ddrbus; 326 327 return 0; 328 } 329 330 unsigned long get_tbclk (void) 331 { 332 void *fdt = get_fdt_virt(); 333 int cpus_node = fdt_path_offset(fdt, "/cpus"); 334 int cpu_node = fdt_first_subnode(fdt, cpus_node); 335 const char *prop = "timebase-frequency"; 336 return fdt_getprop_u32_default_node(fdt, cpu_node, 0, prop, 0); 337 } 338 339 /******************************************** 340 * get_bus_freq 341 * return system bus freq in Hz 342 *********************************************/ 343 ulong get_bus_freq (ulong dummy) 344 { 345 sys_info_t sys_info; 346 get_sys_info(&sys_info); 347 return sys_info.freq_systembus; 348 } 349