diff options
| author | Nathan Rossi <nathan@nathanrossi.com> | 2016-12-20 19:20:42 +1000 |
|---|---|---|
| committer | Nathan Rossi <nathan@nathanrossi.com> | 2016-12-21 22:05:09 +1000 |
| commit | 3e2319675cf104b2183261aad63acc095f114657 (patch) | |
| tree | 4d0320a88f742036bcf9ca796b1e4867dffef198 | |
| parent | 47f17c451a534cb8a7d7360ea6f97a6c9f6be798 (diff) | |
| download | meta-xilinx-3e2319675cf104b2183261aad63acc095f114657.tar.gz | |
u-boot-xlnx_2016.07: Backport fix for memory corruption
Backport the dram_init* memory corruption fix, this resolves issues with
some configurations where the dram_init function for zynq/zynqmp would
trash non-relocated locations in memory due to the use of static
variables before bss initialization.
Signed-off-by: Nathan Rossi <nathan@nathanrossi.com>
4 files changed, 477 insertions, 0 deletions
diff --git a/recipes-bsp/u-boot/u-boot-xlnx_2016.07.bb b/recipes-bsp/u-boot/u-boot-xlnx_2016.07.bb index 61f1cb79..af33a4cf 100644 --- a/recipes-bsp/u-boot/u-boot-xlnx_2016.07.bb +++ b/recipes-bsp/u-boot/u-boot-xlnx_2016.07.bb | |||
| @@ -7,6 +7,13 @@ SRCREV = "95e11f6eb4bc07bbee12a4217c58146bddac61b2" | |||
| 7 | PV = "v2016.07-xilinx-${XILINX_RELEASE_VERSION}+git${SRCPV}" | 7 | PV = "v2016.07-xilinx-${XILINX_RELEASE_VERSION}+git${SRCPV}" |
| 8 | 8 | ||
| 9 | FILESEXTRAPATHS_prepend := "${THISDIR}/u-boot-xlnx:" | 9 | FILESEXTRAPATHS_prepend := "${THISDIR}/u-boot-xlnx:" |
| 10 | FILESEXTRAPATHS_prepend := "${THISDIR}/u-boot:" | ||
| 11 | |||
| 12 | SRC_URI_append = " \ | ||
| 13 | file://0001-fdt-add-memory-bank-decoding-functions-for-board-set.patch \ | ||
| 14 | file://0002-ARM-zynq-Replace-board-specific-with-generic-memory-.patch \ | ||
| 15 | file://0003-ARM64-zynqmp-Replace-board-specific-with-generic-mem.patch \ | ||
| 16 | " | ||
| 10 | 17 | ||
| 11 | SRC_URI_append_kc705-microblazeel = " file://microblaze-kc705-Convert-microblaze-generic-to-k.patch" | 18 | SRC_URI_append_kc705-microblazeel = " file://microblaze-kc705-Convert-microblaze-generic-to-k.patch" |
| 12 | 19 | ||
diff --git a/recipes-bsp/u-boot/u-boot/0001-fdt-add-memory-bank-decoding-functions-for-board-set.patch b/recipes-bsp/u-boot/u-boot/0001-fdt-add-memory-bank-decoding-functions-for-board-set.patch new file mode 100644 index 00000000..b7d179f8 --- /dev/null +++ b/recipes-bsp/u-boot/u-boot/0001-fdt-add-memory-bank-decoding-functions-for-board-set.patch | |||
| @@ -0,0 +1,144 @@ | |||
| 1 | From 623f60198b38c4fdae596038cd5956e44b6224a4 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Nathan Rossi <nathan@nathanrossi.com> | ||
| 3 | Date: Mon, 19 Dec 2016 00:03:34 +1000 | ||
| 4 | Subject: [PATCH 1/3] fdt: add memory bank decoding functions for board setup | ||
| 5 | |||
| 6 | Add two functions for use by board implementations to decode the memory | ||
| 7 | banks of the /memory node so as to populate the global data with | ||
| 8 | ram_size and board info for memory banks. | ||
| 9 | |||
| 10 | The fdtdec_setup_memory_size() function decodes the first memory bank | ||
| 11 | and sets up the gd->ram_size with the size of the memory bank. This | ||
| 12 | function should be called from the boards dram_init(). | ||
| 13 | |||
| 14 | The fdtdec_setup_memory_banksize() function decode the memory banks | ||
| 15 | (up to the CONFIG_NR_DRAM_BANKS) and populates the base address and size | ||
| 16 | into the gd->bd->bi_dram array of banks. This function should be called | ||
| 17 | from the boards dram_init_banksize(). | ||
| 18 | |||
| 19 | Signed-off-by: Nathan Rossi <nathan@nathanrossi.com> | ||
| 20 | Cc: Simon Glass <sjg@chromium.org> | ||
| 21 | Cc: Michal Simek <monstr@monstr.eu> | ||
| 22 | Reviewed-by: Simon Glass <sjg@chromium.org> | ||
| 23 | Signed-off-by: Michal Simek <michal.simek@xilinx.com> | ||
| 24 | Upstream-Status: Backport | ||
| 25 | --- | ||
| 26 | include/fdtdec.h | 34 ++++++++++++++++++++++++++++++++++ | ||
| 27 | lib/fdtdec.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | ||
| 28 | 2 files changed, 90 insertions(+) | ||
| 29 | |||
| 30 | diff --git a/include/fdtdec.h b/include/fdtdec.h | ||
| 31 | index 27887c8c21..d074478f14 100644 | ||
| 32 | --- a/include/fdtdec.h | ||
| 33 | +++ b/include/fdtdec.h | ||
| 34 | @@ -976,6 +976,40 @@ struct display_timing { | ||
| 35 | */ | ||
| 36 | int fdtdec_decode_display_timing(const void *blob, int node, int index, | ||
| 37 | struct display_timing *config); | ||
| 38 | + | ||
| 39 | +/** | ||
| 40 | + * fdtdec_setup_memory_size() - decode and setup gd->ram_size | ||
| 41 | + * | ||
| 42 | + * Decode the /memory 'reg' property to determine the size of the first memory | ||
| 43 | + * bank, populate the global data with the size of the first bank of memory. | ||
| 44 | + * | ||
| 45 | + * This function should be called from a boards dram_init(). This helper | ||
| 46 | + * function allows for boards to query the device tree for DRAM size instead of | ||
| 47 | + * hard coding the value in the case where the memory size cannot be detected | ||
| 48 | + * automatically. | ||
| 49 | + * | ||
| 50 | + * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or | ||
| 51 | + * invalid | ||
| 52 | + */ | ||
| 53 | +int fdtdec_setup_memory_size(void); | ||
| 54 | + | ||
| 55 | +/** | ||
| 56 | + * fdtdec_setup_memory_banksize() - decode and populate gd->bd->bi_dram | ||
| 57 | + * | ||
| 58 | + * Decode the /memory 'reg' property to determine the address and size of the | ||
| 59 | + * memory banks. Use this data to populate the global data board info with the | ||
| 60 | + * phys address and size of memory banks. | ||
| 61 | + * | ||
| 62 | + * This function should be called from a boards dram_init_banksize(). This | ||
| 63 | + * helper function allows for boards to query the device tree for memory bank | ||
| 64 | + * information instead of hard coding the information in cases where it cannot | ||
| 65 | + * be detected automatically. | ||
| 66 | + * | ||
| 67 | + * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or | ||
| 68 | + * invalid | ||
| 69 | + */ | ||
| 70 | +int fdtdec_setup_memory_banksize(void); | ||
| 71 | + | ||
| 72 | /** | ||
| 73 | * Set up the device tree ready for use | ||
| 74 | */ | ||
| 75 | diff --git a/lib/fdtdec.c b/lib/fdtdec.c | ||
| 76 | index 4e619c49a2..81f47ef2c7 100644 | ||
| 77 | --- a/lib/fdtdec.c | ||
| 78 | +++ b/lib/fdtdec.c | ||
| 79 | @@ -1174,6 +1174,62 @@ int fdtdec_decode_display_timing(const void *blob, int parent, int index, | ||
| 80 | return ret; | ||
| 81 | } | ||
| 82 | |||
| 83 | +int fdtdec_setup_memory_size(void) | ||
| 84 | +{ | ||
| 85 | + int ret, mem; | ||
| 86 | + struct fdt_resource res; | ||
| 87 | + | ||
| 88 | + mem = fdt_path_offset(gd->fdt_blob, "/memory"); | ||
| 89 | + if (mem < 0) { | ||
| 90 | + debug("%s: Missing /memory node\n", __func__); | ||
| 91 | + return -EINVAL; | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + ret = fdt_get_resource(gd->fdt_blob, mem, "reg", 0, &res); | ||
| 95 | + if (ret != 0) { | ||
| 96 | + debug("%s: Unable to decode first memory bank\n", __func__); | ||
| 97 | + return -EINVAL; | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + gd->ram_size = (phys_size_t)(res.end - res.start + 1); | ||
| 101 | + debug("%s: Initial DRAM size %llx\n", __func__, (u64)gd->ram_size); | ||
| 102 | + | ||
| 103 | + return 0; | ||
| 104 | +} | ||
| 105 | + | ||
| 106 | +#if defined(CONFIG_NR_DRAM_BANKS) | ||
| 107 | +int fdtdec_setup_memory_banksize(void) | ||
| 108 | +{ | ||
| 109 | + int bank, ret, mem; | ||
| 110 | + struct fdt_resource res; | ||
| 111 | + | ||
| 112 | + mem = fdt_path_offset(gd->fdt_blob, "/memory"); | ||
| 113 | + if (mem < 0) { | ||
| 114 | + debug("%s: Missing /memory node\n", __func__); | ||
| 115 | + return -EINVAL; | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { | ||
| 119 | + ret = fdt_get_resource(gd->fdt_blob, mem, "reg", bank, &res); | ||
| 120 | + if (ret == -FDT_ERR_NOTFOUND) | ||
| 121 | + break; | ||
| 122 | + if (ret != 0) | ||
| 123 | + return -EINVAL; | ||
| 124 | + | ||
| 125 | + gd->bd->bi_dram[bank].start = (phys_addr_t)res.start; | ||
| 126 | + gd->bd->bi_dram[bank].size = | ||
| 127 | + (phys_size_t)(res.end - res.start + 1); | ||
| 128 | + | ||
| 129 | + debug("%s: DRAM Bank #%d: start = 0x%llx, size = 0x%llx\n", | ||
| 130 | + __func__, bank, | ||
| 131 | + (unsigned long long)gd->bd->bi_dram[bank].start, | ||
| 132 | + (unsigned long long)gd->bd->bi_dram[bank].size); | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + return 0; | ||
| 136 | +} | ||
| 137 | +#endif | ||
| 138 | + | ||
| 139 | int fdtdec_setup(void) | ||
| 140 | { | ||
| 141 | #if CONFIG_IS_ENABLED(OF_CONTROL) | ||
| 142 | -- | ||
| 143 | 2.11.0 | ||
| 144 | |||
diff --git a/recipes-bsp/u-boot/u-boot/0002-ARM-zynq-Replace-board-specific-with-generic-memory-.patch b/recipes-bsp/u-boot/u-boot/0002-ARM-zynq-Replace-board-specific-with-generic-memory-.patch new file mode 100644 index 00000000..41806966 --- /dev/null +++ b/recipes-bsp/u-boot/u-boot/0002-ARM-zynq-Replace-board-specific-with-generic-memory-.patch | |||
| @@ -0,0 +1,170 @@ | |||
| 1 | From de9bf1b591a80ef8fce8cad5c3d5a1139d136a77 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Nathan Rossi <nathan@nathanrossi.com> | ||
| 3 | Date: Mon, 19 Dec 2016 00:03:34 +1000 | ||
| 4 | Subject: [PATCH 2/3] ARM: zynq: Replace board specific with generic memory | ||
| 5 | bank decoding | ||
| 6 | |||
| 7 | The dram_init and dram_init_banksize functions were using a board | ||
| 8 | specific implementation for decoding the memory banks from the fdt. This | ||
| 9 | board specific implementation uses a static variable 'tmp' which makes | ||
| 10 | these functions unsafe for execution from within the board_init_f | ||
| 11 | context. | ||
| 12 | |||
| 13 | This unsafe use of a static variable was causing a specific bug when | ||
| 14 | using the zynq_zybo configuration, U-Boot would generate the following | ||
| 15 | error during image load. This was caused due to dram_init overwriting | ||
| 16 | the relocations for the 'image' variable within the do_bootm function. | ||
| 17 | Out of coincidence the un-initialized memory has a compression type | ||
| 18 | which is the same as the value for the relocation type R_ARM_RELATIVE. | ||
| 19 | |||
| 20 | Uncompressing Invalid Image ... Unimplemented compression type 23 | ||
| 21 | |||
| 22 | It should be noted that this is just one way the issue could surface, | ||
| 23 | other cases my not be observed in normal boot flow. Depending on the | ||
| 24 | size of various sections, and location of relocations within __rel_dyn | ||
| 25 | and the compiler/linker the outcome of this bug can differ greatly. | ||
| 26 | |||
| 27 | This change makes the dram_init* functions use a generic implementation | ||
| 28 | of decoding and populating memory bank and size data. | ||
| 29 | |||
| 30 | Signed-off-by: Nathan Rossi <nathan@nathanrossi.com> | ||
| 31 | Fixes: 758f29d0f8 ("ARM: zynq: Support systems with more memory banks") | ||
| 32 | Cc: Michal Simek <monstr@monstr.eu> | ||
| 33 | Signed-off-by: Michal Simek <michal.simek@xilinx.com> | ||
| 34 | Upstream-Status: Backport | ||
| 35 | --- | ||
| 36 | board/xilinx/zynq/board.c | 112 ++-------------------------------------------- | ||
| 37 | 1 file changed, 3 insertions(+), 109 deletions(-) | ||
| 38 | |||
| 39 | diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c | ||
| 40 | index 2c86940957..5cd9bbf711 100644 | ||
| 41 | --- a/board/xilinx/zynq/board.c | ||
| 42 | +++ b/board/xilinx/zynq/board.c | ||
| 43 | @@ -124,121 +124,15 @@ int zynq_board_read_rom_ethaddr(unsigned char *ethaddr) | ||
| 44 | } | ||
| 45 | |||
| 46 | #if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE) | ||
| 47 | -/* | ||
| 48 | - * fdt_get_reg - Fill buffer by information from DT | ||
| 49 | - */ | ||
| 50 | -static phys_size_t fdt_get_reg(const void *fdt, int nodeoffset, void *buf, | ||
| 51 | - const u32 *cell, int n) | ||
| 52 | -{ | ||
| 53 | - int i = 0, b, banks; | ||
| 54 | - int parent_offset = fdt_parent_offset(fdt, nodeoffset); | ||
| 55 | - int address_cells = fdt_address_cells(fdt, parent_offset); | ||
| 56 | - int size_cells = fdt_size_cells(fdt, parent_offset); | ||
| 57 | - char *p = buf; | ||
| 58 | - u64 val; | ||
| 59 | - u64 vals; | ||
| 60 | - | ||
| 61 | - debug("%s: addr_cells=%x, size_cell=%x, buf=%p, cell=%p\n", | ||
| 62 | - __func__, address_cells, size_cells, buf, cell); | ||
| 63 | - | ||
| 64 | - /* Check memory bank setup */ | ||
| 65 | - banks = n % (address_cells + size_cells); | ||
| 66 | - if (banks) | ||
| 67 | - panic("Incorrect memory setup cells=%d, ac=%d, sc=%d\n", | ||
| 68 | - n, address_cells, size_cells); | ||
| 69 | - | ||
| 70 | - banks = n / (address_cells + size_cells); | ||
| 71 | - | ||
| 72 | - for (b = 0; b < banks; b++) { | ||
| 73 | - debug("%s: Bank #%d:\n", __func__, b); | ||
| 74 | - if (address_cells == 2) { | ||
| 75 | - val = cell[i + 1]; | ||
| 76 | - val <<= 32; | ||
| 77 | - val |= cell[i]; | ||
| 78 | - val = fdt64_to_cpu(val); | ||
| 79 | - debug("%s: addr64=%llx, ptr=%p, cell=%p\n", | ||
| 80 | - __func__, val, p, &cell[i]); | ||
| 81 | - *(phys_addr_t *)p = val; | ||
| 82 | - } else { | ||
| 83 | - debug("%s: addr32=%x, ptr=%p\n", | ||
| 84 | - __func__, fdt32_to_cpu(cell[i]), p); | ||
| 85 | - *(phys_addr_t *)p = fdt32_to_cpu(cell[i]); | ||
| 86 | - } | ||
| 87 | - p += sizeof(phys_addr_t); | ||
| 88 | - i += address_cells; | ||
| 89 | - | ||
| 90 | - debug("%s: pa=%p, i=%x, size=%zu\n", __func__, p, i, | ||
| 91 | - sizeof(phys_addr_t)); | ||
| 92 | - | ||
| 93 | - if (size_cells == 2) { | ||
| 94 | - vals = cell[i + 1]; | ||
| 95 | - vals <<= 32; | ||
| 96 | - vals |= cell[i]; | ||
| 97 | - vals = fdt64_to_cpu(vals); | ||
| 98 | - | ||
| 99 | - debug("%s: size64=%llx, ptr=%p, cell=%p\n", | ||
| 100 | - __func__, vals, p, &cell[i]); | ||
| 101 | - *(phys_size_t *)p = vals; | ||
| 102 | - } else { | ||
| 103 | - debug("%s: size32=%x, ptr=%p\n", | ||
| 104 | - __func__, fdt32_to_cpu(cell[i]), p); | ||
| 105 | - *(phys_size_t *)p = fdt32_to_cpu(cell[i]); | ||
| 106 | - } | ||
| 107 | - p += sizeof(phys_size_t); | ||
| 108 | - i += size_cells; | ||
| 109 | - | ||
| 110 | - debug("%s: ps=%p, i=%x, size=%zu\n", | ||
| 111 | - __func__, p, i, sizeof(phys_size_t)); | ||
| 112 | - } | ||
| 113 | - | ||
| 114 | - /* Return the first address size */ | ||
| 115 | - return *(phys_size_t *)((char *)buf + sizeof(phys_addr_t)); | ||
| 116 | -} | ||
| 117 | - | ||
| 118 | -#define FDT_REG_SIZE sizeof(u32) | ||
| 119 | -/* Temp location for sharing data for storing */ | ||
| 120 | -/* Up to 64-bit address + 64-bit size */ | ||
| 121 | -static u8 tmp[CONFIG_NR_DRAM_BANKS * 16]; | ||
| 122 | - | ||
| 123 | void dram_init_banksize(void) | ||
| 124 | { | ||
| 125 | - int bank; | ||
| 126 | - | ||
| 127 | - memcpy(&gd->bd->bi_dram[0], &tmp, sizeof(tmp)); | ||
| 128 | - | ||
| 129 | - for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { | ||
| 130 | - debug("Bank #%d: start %llx\n", bank, | ||
| 131 | - (unsigned long long)gd->bd->bi_dram[bank].start); | ||
| 132 | - debug("Bank #%d: size %llx\n", bank, | ||
| 133 | - (unsigned long long)gd->bd->bi_dram[bank].size); | ||
| 134 | - } | ||
| 135 | + fdtdec_setup_memory_banksize(); | ||
| 136 | } | ||
| 137 | |||
| 138 | int dram_init(void) | ||
| 139 | { | ||
| 140 | - int node, len; | ||
| 141 | - const void *blob = gd->fdt_blob; | ||
| 142 | - const u32 *cell; | ||
| 143 | - | ||
| 144 | - memset(&tmp, 0, sizeof(tmp)); | ||
| 145 | - | ||
| 146 | - /* find or create "/memory" node. */ | ||
| 147 | - node = fdt_subnode_offset(blob, 0, "memory"); | ||
| 148 | - if (node < 0) { | ||
| 149 | - printf("%s: Can't get memory node\n", __func__); | ||
| 150 | - return node; | ||
| 151 | - } | ||
| 152 | - | ||
| 153 | - /* Get pointer to cells and lenght of it */ | ||
| 154 | - cell = fdt_getprop(blob, node, "reg", &len); | ||
| 155 | - if (!cell) { | ||
| 156 | - printf("%s: Can't get reg property\n", __func__); | ||
| 157 | - return -1; | ||
| 158 | - } | ||
| 159 | - | ||
| 160 | - gd->ram_size = fdt_get_reg(blob, node, &tmp, cell, len / FDT_REG_SIZE); | ||
| 161 | - | ||
| 162 | - debug("%s: Initial DRAM size %llx\n", __func__, (u64)gd->ram_size); | ||
| 163 | + if (fdtdec_setup_memory_size() != 0) | ||
| 164 | + return -EINVAL; | ||
| 165 | |||
| 166 | zynq_ddrc_init(); | ||
| 167 | |||
| 168 | -- | ||
| 169 | 2.11.0 | ||
| 170 | |||
diff --git a/recipes-bsp/u-boot/u-boot/0003-ARM64-zynqmp-Replace-board-specific-with-generic-mem.patch b/recipes-bsp/u-boot/u-boot/0003-ARM64-zynqmp-Replace-board-specific-with-generic-mem.patch new file mode 100644 index 00000000..2e6e9e31 --- /dev/null +++ b/recipes-bsp/u-boot/u-boot/0003-ARM64-zynqmp-Replace-board-specific-with-generic-mem.patch | |||
| @@ -0,0 +1,156 @@ | |||
| 1 | From 950f86ca38325c9ae7874895d2cdbdda5496e712 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Nathan Rossi <nathan@nathanrossi.com> | ||
| 3 | Date: Mon, 19 Dec 2016 00:03:34 +1000 | ||
| 4 | Subject: [PATCH 3/3] ARM64: zynqmp: Replace board specific with generic memory | ||
| 5 | bank decoding | ||
| 6 | |||
| 7 | The dram_init and dram_init_banksize functions were using a board | ||
| 8 | specific implementation for decoding the memory banks from the fdt. This | ||
| 9 | board specific implementation uses a static variable 'tmp' which makes | ||
| 10 | these functions unsafe for execution from within the board_init_f | ||
| 11 | context. | ||
| 12 | |||
| 13 | This change makes the dram_init* functions use a generic implementation | ||
| 14 | of decoding and populating memory bank and size data. | ||
| 15 | |||
| 16 | Signed-off-by: Nathan Rossi <nathan@nathanrossi.com> | ||
| 17 | Fixes: 8d59d7f63b ("ARM64: zynqmp: Read RAM information from DT") | ||
| 18 | Cc: Michal Simek <michal.simek@xilinx.com> | ||
| 19 | Signed-off-by: Michal Simek <michal.simek@xilinx.com> | ||
| 20 | Upstream-Status: Backport | ||
| 21 | --- | ||
| 22 | board/xilinx/zynqmp/zynqmp.c | 112 ++----------------------------------------- | ||
| 23 | 1 file changed, 3 insertions(+), 109 deletions(-) | ||
| 24 | |||
| 25 | diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c | ||
| 26 | index a23c38acd9..4e5871b76a 100644 | ||
| 27 | --- a/board/xilinx/zynqmp/zynqmp.c | ||
| 28 | +++ b/board/xilinx/zynqmp/zynqmp.c | ||
| 29 | @@ -180,121 +180,15 @@ int zynq_board_read_rom_ethaddr(unsigned char *ethaddr) | ||
| 30 | } | ||
| 31 | |||
| 32 | #if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE) | ||
| 33 | -/* | ||
| 34 | - * fdt_get_reg - Fill buffer by information from DT | ||
| 35 | - */ | ||
| 36 | -static phys_size_t fdt_get_reg(const void *fdt, int nodeoffset, void *buf, | ||
| 37 | - const u32 *cell, int n) | ||
| 38 | -{ | ||
| 39 | - int i = 0, b, banks; | ||
| 40 | - int parent_offset = fdt_parent_offset(fdt, nodeoffset); | ||
| 41 | - int address_cells = fdt_address_cells(fdt, parent_offset); | ||
| 42 | - int size_cells = fdt_size_cells(fdt, parent_offset); | ||
| 43 | - char *p = buf; | ||
| 44 | - u64 val; | ||
| 45 | - u64 vals; | ||
| 46 | - | ||
| 47 | - debug("%s: addr_cells=%x, size_cell=%x, buf=%p, cell=%p\n", | ||
| 48 | - __func__, address_cells, size_cells, buf, cell); | ||
| 49 | - | ||
| 50 | - /* Check memory bank setup */ | ||
| 51 | - banks = n % (address_cells + size_cells); | ||
| 52 | - if (banks) | ||
| 53 | - panic("Incorrect memory setup cells=%d, ac=%d, sc=%d\n", | ||
| 54 | - n, address_cells, size_cells); | ||
| 55 | - | ||
| 56 | - banks = n / (address_cells + size_cells); | ||
| 57 | - | ||
| 58 | - for (b = 0; b < banks; b++) { | ||
| 59 | - debug("%s: Bank #%d:\n", __func__, b); | ||
| 60 | - if (address_cells == 2) { | ||
| 61 | - val = cell[i + 1]; | ||
| 62 | - val <<= 32; | ||
| 63 | - val |= cell[i]; | ||
| 64 | - val = fdt64_to_cpu(val); | ||
| 65 | - debug("%s: addr64=%llx, ptr=%p, cell=%p\n", | ||
| 66 | - __func__, val, p, &cell[i]); | ||
| 67 | - *(phys_addr_t *)p = val; | ||
| 68 | - } else { | ||
| 69 | - debug("%s: addr32=%x, ptr=%p\n", | ||
| 70 | - __func__, fdt32_to_cpu(cell[i]), p); | ||
| 71 | - *(phys_addr_t *)p = fdt32_to_cpu(cell[i]); | ||
| 72 | - } | ||
| 73 | - p += sizeof(phys_addr_t); | ||
| 74 | - i += address_cells; | ||
| 75 | - | ||
| 76 | - debug("%s: pa=%p, i=%x, size=%zu\n", __func__, p, i, | ||
| 77 | - sizeof(phys_addr_t)); | ||
| 78 | - | ||
| 79 | - if (size_cells == 2) { | ||
| 80 | - vals = cell[i + 1]; | ||
| 81 | - vals <<= 32; | ||
| 82 | - vals |= cell[i]; | ||
| 83 | - vals = fdt64_to_cpu(vals); | ||
| 84 | - | ||
| 85 | - debug("%s: size64=%llx, ptr=%p, cell=%p\n", | ||
| 86 | - __func__, vals, p, &cell[i]); | ||
| 87 | - *(phys_size_t *)p = vals; | ||
| 88 | - } else { | ||
| 89 | - debug("%s: size32=%x, ptr=%p\n", | ||
| 90 | - __func__, fdt32_to_cpu(cell[i]), p); | ||
| 91 | - *(phys_size_t *)p = fdt32_to_cpu(cell[i]); | ||
| 92 | - } | ||
| 93 | - p += sizeof(phys_size_t); | ||
| 94 | - i += size_cells; | ||
| 95 | - | ||
| 96 | - debug("%s: ps=%p, i=%x, size=%zu\n", | ||
| 97 | - __func__, p, i, sizeof(phys_size_t)); | ||
| 98 | - } | ||
| 99 | - | ||
| 100 | - /* Return the first address size */ | ||
| 101 | - return *(phys_size_t *)((char *)buf + sizeof(phys_addr_t)); | ||
| 102 | -} | ||
| 103 | - | ||
| 104 | -#define FDT_REG_SIZE sizeof(u32) | ||
| 105 | -/* Temp location for sharing data for storing */ | ||
| 106 | -/* Up to 64-bit address + 64-bit size */ | ||
| 107 | -static u8 tmp[CONFIG_NR_DRAM_BANKS * 16]; | ||
| 108 | - | ||
| 109 | void dram_init_banksize(void) | ||
| 110 | { | ||
| 111 | - int bank; | ||
| 112 | - | ||
| 113 | - memcpy(&gd->bd->bi_dram[0], &tmp, sizeof(tmp)); | ||
| 114 | - | ||
| 115 | - for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { | ||
| 116 | - debug("Bank #%d: start %llx\n", bank, | ||
| 117 | - (unsigned long long)gd->bd->bi_dram[bank].start); | ||
| 118 | - debug("Bank #%d: size %llx\n", bank, | ||
| 119 | - (unsigned long long)gd->bd->bi_dram[bank].size); | ||
| 120 | - } | ||
| 121 | + fdtdec_setup_memory_banksize(); | ||
| 122 | } | ||
| 123 | |||
| 124 | int dram_init(void) | ||
| 125 | { | ||
| 126 | - int node, len; | ||
| 127 | - const void *blob = gd->fdt_blob; | ||
| 128 | - const u32 *cell; | ||
| 129 | - | ||
| 130 | - memset(&tmp, 0, sizeof(tmp)); | ||
| 131 | - | ||
| 132 | - /* find or create "/memory" node. */ | ||
| 133 | - node = fdt_subnode_offset(blob, 0, "memory"); | ||
| 134 | - if (node < 0) { | ||
| 135 | - printf("%s: Can't get memory node\n", __func__); | ||
| 136 | - return node; | ||
| 137 | - } | ||
| 138 | - | ||
| 139 | - /* Get pointer to cells and lenght of it */ | ||
| 140 | - cell = fdt_getprop(blob, node, "reg", &len); | ||
| 141 | - if (!cell) { | ||
| 142 | - printf("%s: Can't get reg property\n", __func__); | ||
| 143 | - return -1; | ||
| 144 | - } | ||
| 145 | - | ||
| 146 | - gd->ram_size = fdt_get_reg(blob, node, &tmp, cell, len / FDT_REG_SIZE); | ||
| 147 | - | ||
| 148 | - debug("%s: Initial DRAM size %llx\n", __func__, (u64)gd->ram_size); | ||
| 149 | + if (fdtdec_setup_memory_size() != 0) | ||
| 150 | + return -EINVAL; | ||
| 151 | |||
| 152 | return 0; | ||
| 153 | } | ||
| 154 | -- | ||
| 155 | 2.11.0 | ||
| 156 | |||
