1 /* 2 * Copyright (C) 2016 Stefan Roese <sr@denx.de> 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <fdtdec.h> 10 #include <libfdt.h> 11 #include <asm/io.h> 12 #include <asm/system.h> 13 #include <asm/arch/cpu.h> 14 #include <asm/arch/soc.h> 15 #include <asm/armv8/mmu.h> 16 17 DECLARE_GLOBAL_DATA_PTR; 18 19 /* 20 * Not all memory is mapped in the MMU. So we need to restrict the 21 * memory size so that U-Boot does not try to access it. Also, the 22 * internal registers are located at 0xf000.0000 - 0xffff.ffff. 23 * Currently only 2GiB are mapped for system memory. This is what 24 * we pass to the U-Boot subsystem here. 25 */ 26 #define USABLE_RAM_SIZE 0x80000000 27 28 ulong board_get_usable_ram_top(ulong total_size) 29 { 30 if (gd->ram_size > USABLE_RAM_SIZE) 31 return USABLE_RAM_SIZE; 32 33 return gd->ram_size; 34 } 35 36 /* 37 * On ARMv8, MBus is not configured in U-Boot. To enable compilation 38 * of the already implemented drivers, lets add a dummy version of 39 * this function so that linking does not fail. 40 */ 41 const struct mbus_dram_target_info *mvebu_mbus_dram_info(void) 42 { 43 return NULL; 44 } 45 46 /* DRAM init code ... */ 47 48 static const void *get_memory_reg_prop(const void *fdt, int *lenp) 49 { 50 int offset; 51 52 offset = fdt_path_offset(fdt, "/memory"); 53 if (offset < 0) 54 return NULL; 55 56 return fdt_getprop(fdt, offset, "reg", lenp); 57 } 58 59 int dram_init(void) 60 { 61 const void *fdt = gd->fdt_blob; 62 const fdt32_t *val; 63 int ac, sc, len; 64 65 ac = fdt_address_cells(fdt, 0); 66 sc = fdt_size_cells(fdt, 0); 67 if (ac < 0 || sc < 1 || sc > 2) { 68 printf("invalid address/size cells\n"); 69 return -EINVAL; 70 } 71 72 val = get_memory_reg_prop(fdt, &len); 73 if (len / sizeof(*val) < ac + sc) 74 return -EINVAL; 75 76 val += ac; 77 78 gd->ram_size = fdtdec_get_number(val, sc); 79 80 debug("DRAM size = %08lx\n", (unsigned long)gd->ram_size); 81 82 return 0; 83 } 84 85 int dram_init_banksize(void) 86 { 87 const void *fdt = gd->fdt_blob; 88 const fdt32_t *val; 89 int ac, sc, cells, len, i; 90 91 val = get_memory_reg_prop(fdt, &len); 92 if (len < 0) 93 return -ENXIO; 94 95 ac = fdt_address_cells(fdt, 0); 96 sc = fdt_size_cells(fdt, 0); 97 if (ac < 1 || ac > 2 || sc < 1 || sc > 2) { 98 printf("invalid address/size cells\n"); 99 return -ENXIO; 100 } 101 102 cells = ac + sc; 103 104 len /= sizeof(*val); 105 106 for (i = 0; i < CONFIG_NR_DRAM_BANKS && len >= cells; 107 i++, len -= cells) { 108 gd->bd->bi_dram[i].start = fdtdec_get_number(val, ac); 109 val += ac; 110 gd->bd->bi_dram[i].size = fdtdec_get_number(val, sc); 111 val += sc; 112 113 debug("DRAM bank %d: start = %08lx, size = %08lx\n", 114 i, (unsigned long)gd->bd->bi_dram[i].start, 115 (unsigned long)gd->bd->bi_dram[i].size); 116 } 117 118 return 0; 119 } 120 121 int arch_cpu_init(void) 122 { 123 /* Nothing to do (yet) */ 124 return 0; 125 } 126 127 int arch_early_init_r(void) 128 { 129 struct udevice *dev; 130 int ret; 131 int i; 132 133 /* 134 * Loop over all MISC uclass drivers to call the comphy code 135 * and init all CP110 devices enabled in the DT 136 */ 137 i = 0; 138 while (1) { 139 /* Call the comphy code via the MISC uclass driver */ 140 ret = uclass_get_device(UCLASS_MISC, i++, &dev); 141 142 /* We're done, once no further CP110 device is found */ 143 if (ret) 144 break; 145 } 146 147 /* Cause the SATA device to do its early init */ 148 uclass_first_device(UCLASS_AHCI, &dev); 149 150 return 0; 151 } 152