1 /* 2 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <arch_helpers.h> 8 #include <console.h> 9 #include <debug.h> 10 #include <delay_timer.h> 11 #include <mmio.h> 12 #include <plat_private.h> 13 #include <platform_def.h> 14 #include <soc.h> 15 #include <string.h> 16 #include "ddr_parameter.h" 17 18 /* 19 * The miniloader delivers the parameters about ddr usage info from address 20 * 0x02000000 and the data format is defined as below figure. It tells ATF the 21 * areas of ddr that are used by platform, we treat them as non-secure regions 22 * by default. Then we should parse the other part regions and configurate them 23 * as secure regions to avoid illegal access. 24 * 25 * [ddr usage info data format] 26 * 0x02000000 27 * ----------------------------------------------------------------------------- 28 * | <name> | <size> | <description> | 29 * ----------------------------------------------------------------------------- 30 * | count | 4byte | the array numbers of the | 31 * | | | 'addr_array' and 'size_array' | 32 * ----------------------------------------------------------------------------- 33 * | reserved | 4byte | just for 'addr_array' 8byte aligned | 34 * ----------------------------------------------------------------------------- 35 * | addr_array[count] | per 8byte | memory region base address | 36 * ----------------------------------------------------------------------------- 37 * | size_array[count] | per 8byte | memory region size (byte) | 38 * ----------------------------------------------------------------------------- 39 */ 40 41 /* 42 * function: read parameters info(ns-regions) and try to parse s-regions info 43 * 44 * @addr: head address to the ddr usage struct from miniloader 45 * @max_mb: the max ddr capacity(MB) that the platform support 46 */ 47 struct param_ddr_usage ddr_region_usage_parse(uint64_t addr, uint64_t max_mb) 48 { 49 uint64_t base, top; 50 uint32_t i, addr_offset, size_offset; 51 struct param_ddr_usage p; 52 53 memset(&p, 0, sizeof(p)); 54 55 /* read how many blocks of ns-regions, read from offset: 0x0 */ 56 p.ns_nr = mmio_read_32(addr + REGION_NR_OFFSET); 57 if ((p.ns_nr > DDR_REGION_NR_MAX) || (p.ns_nr == 0)) { 58 ERROR("over or zero region, nr=%d, max=%d\n", 59 p.ns_nr, DDR_REGION_NR_MAX); 60 return p; 61 } 62 63 /* whole ddr regions boundary, it will be used when parse s-regions */ 64 p.boundary = max_mb; 65 66 /* calculate ns-region base addr and size offset */ 67 addr_offset = REGION_ADDR_OFFSET; 68 size_offset = REGION_ADDR_OFFSET + p.ns_nr * REGION_DATA_PER_BYTES; 69 70 /* read all ns-regions base and top address */ 71 for (i = 0; i < p.ns_nr; i++) { 72 base = mmio_read_64(addr + addr_offset); 73 top = base + mmio_read_64(addr + size_offset); 74 /* 75 * translate byte to MB and store info, 76 * Miniloader will promise every ns-region is MB aligned. 77 */ 78 p.ns_base[i] = RG_SIZE_MB(base); 79 p.ns_top[i] = RG_SIZE_MB(top); 80 81 addr_offset += REGION_DATA_PER_BYTES; 82 size_offset += REGION_DATA_PER_BYTES; 83 } 84 85 /* 86 * a s-region's base starts from previous ns-region's top, and a 87 * s-region's top ends with next ns-region's base. maybe like this: 88 * 89 * case1: ns-regison start from 0MB 90 * ----------------------------------------------- 91 * | ns0 | S0 | ns1 | S1 | ns2 | 92 * 0----------------------------------------------- max_mb 93 * 94 * 95 * case2: ns-regison not start from 0MB 96 * ----------------------------------------------- 97 * | S0 | ns0 | ns1 | ns2 | S1 | 98 * 0----------------------------------------------- max_mb 99 */ 100 101 /* like above case2 figure, ns-region is not start from 0MB */ 102 if (p.ns_base[0] != 0) { 103 p.s_base[p.s_nr] = 0; 104 p.s_top[p.s_nr] = p.ns_base[0]; 105 p.s_nr++; 106 } 107 108 /* 109 * notice: if ns-regions not start from 0MB, p.s_nr = 1 now, otherwise 0 110 */ 111 for (i = 0; i < p.ns_nr; i++) { 112 /* 113 * if current ns-regions top covers boundary, 114 * that means s-regions are all parsed yet, so finsh. 115 */ 116 if (p.ns_top[i] == p.boundary) 117 goto out; 118 119 /* s-region's base starts from previous ns-region's top */ 120 p.s_base[p.s_nr] = p.ns_top[i]; 121 122 /* s-region's top ends with next ns-region's base */ 123 if (i + 1 < p.ns_nr) 124 p.s_top[p.s_nr] = p.ns_base[i + 1]; 125 else 126 p.s_top[p.s_nr] = p.boundary; 127 p.s_nr++; 128 } 129 out: 130 return p; 131 } 132