10d5ec955Stony.xie /* 20d5ec955Stony.xie * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 30d5ec955Stony.xie * 4*c3e70be1Sdp-arm * SPDX-License-Identifier: BSD-3-Clause 50d5ec955Stony.xie */ 60d5ec955Stony.xie 70d5ec955Stony.xie #include <arch_helpers.h> 80d5ec955Stony.xie #include <console.h> 90d5ec955Stony.xie #include <debug.h> 100d5ec955Stony.xie #include <delay_timer.h> 110d5ec955Stony.xie #include <mmio.h> 120d5ec955Stony.xie #include <platform_def.h> 130d5ec955Stony.xie #include <plat_private.h> 140d5ec955Stony.xie #include <soc.h> 150d5ec955Stony.xie #include <string.h> 160d5ec955Stony.xie #include "ddr_parameter.h" 170d5ec955Stony.xie 180d5ec955Stony.xie /* 190d5ec955Stony.xie * The miniloader delivers the parameters about ddr usage info from address 200d5ec955Stony.xie * 0x02000000 and the data format is defined as below figure. It tells ATF the 210d5ec955Stony.xie * areas of ddr that are used by platform, we treat them as non-secure regions 220d5ec955Stony.xie * by default. Then we should parse the other part regions and configurate them 230d5ec955Stony.xie * as secure regions to avoid illegal access. 240d5ec955Stony.xie * 250d5ec955Stony.xie * [ddr usage info data format] 260d5ec955Stony.xie * 0x02000000 270d5ec955Stony.xie * ----------------------------------------------------------------------------- 280d5ec955Stony.xie * | <name> | <size> | <description> | 290d5ec955Stony.xie * ----------------------------------------------------------------------------- 300d5ec955Stony.xie * | count | 4byte | the array numbers of the | 310d5ec955Stony.xie * | | | 'addr_array' and 'size_array' | 320d5ec955Stony.xie * ----------------------------------------------------------------------------- 330d5ec955Stony.xie * | reserved | 4byte | just for 'addr_array' 8byte aligned | 340d5ec955Stony.xie * ----------------------------------------------------------------------------- 350d5ec955Stony.xie * | addr_array[count] | per 8byte | memory region base address | 360d5ec955Stony.xie * ----------------------------------------------------------------------------- 370d5ec955Stony.xie * | size_array[count] | per 8byte | memory region size (byte) | 380d5ec955Stony.xie * ----------------------------------------------------------------------------- 390d5ec955Stony.xie */ 400d5ec955Stony.xie 410d5ec955Stony.xie /* 420d5ec955Stony.xie * function: read parameters info(ns-regions) and try to parse s-regions info 430d5ec955Stony.xie * 440d5ec955Stony.xie * @addr: head address to the ddr usage struct from miniloader 450d5ec955Stony.xie * @max_mb: the max ddr capacity(MB) that the platform support 460d5ec955Stony.xie */ 470d5ec955Stony.xie struct param_ddr_usage ddr_region_usage_parse(uint64_t addr, uint64_t max_mb) 480d5ec955Stony.xie { 490d5ec955Stony.xie uint64_t base, top; 500d5ec955Stony.xie uint32_t i, addr_offset, size_offset; 510d5ec955Stony.xie struct param_ddr_usage p; 520d5ec955Stony.xie 530d5ec955Stony.xie memset(&p, 0, sizeof(p)); 540d5ec955Stony.xie 550d5ec955Stony.xie /* read how many blocks of ns-regions, read from offset: 0x0 */ 560d5ec955Stony.xie p.ns_nr = mmio_read_32(addr + REGION_NR_OFFSET); 570d5ec955Stony.xie if ((p.ns_nr > DDR_REGION_NR_MAX) || (p.ns_nr == 0)) { 580d5ec955Stony.xie ERROR("over or zero region, nr=%d, max=%d\n", 590d5ec955Stony.xie p.ns_nr, DDR_REGION_NR_MAX); 600d5ec955Stony.xie return p; 610d5ec955Stony.xie } 620d5ec955Stony.xie 630d5ec955Stony.xie /* whole ddr regions boundary, it will be used when parse s-regions */ 640d5ec955Stony.xie p.boundary = max_mb; 650d5ec955Stony.xie 660d5ec955Stony.xie /* calculate ns-region base addr and size offset */ 670d5ec955Stony.xie addr_offset = REGION_ADDR_OFFSET; 680d5ec955Stony.xie size_offset = REGION_ADDR_OFFSET + p.ns_nr * REGION_DATA_PER_BYTES; 690d5ec955Stony.xie 700d5ec955Stony.xie /* read all ns-regions base and top address */ 710d5ec955Stony.xie for (i = 0; i < p.ns_nr; i++) { 720d5ec955Stony.xie base = mmio_read_64(addr + addr_offset); 730d5ec955Stony.xie top = base + mmio_read_64(addr + size_offset); 740d5ec955Stony.xie /* 750d5ec955Stony.xie * translate byte to MB and store info, 760d5ec955Stony.xie * Miniloader will promise every ns-region is MB aligned. 770d5ec955Stony.xie */ 780d5ec955Stony.xie p.ns_base[i] = RG_SIZE_MB(base); 790d5ec955Stony.xie p.ns_top[i] = RG_SIZE_MB(top); 800d5ec955Stony.xie 810d5ec955Stony.xie addr_offset += REGION_DATA_PER_BYTES; 820d5ec955Stony.xie size_offset += REGION_DATA_PER_BYTES; 830d5ec955Stony.xie } 840d5ec955Stony.xie 850d5ec955Stony.xie /* 860d5ec955Stony.xie * a s-region's base starts from previous ns-region's top, and a 870d5ec955Stony.xie * s-region's top ends with next ns-region's base. maybe like this: 880d5ec955Stony.xie * 890d5ec955Stony.xie * case1: ns-regison start from 0MB 900d5ec955Stony.xie * ----------------------------------------------- 910d5ec955Stony.xie * | ns0 | S0 | ns1 | S1 | ns2 | 920d5ec955Stony.xie * 0----------------------------------------------- max_mb 930d5ec955Stony.xie * 940d5ec955Stony.xie * 950d5ec955Stony.xie * case2: ns-regison not start from 0MB 960d5ec955Stony.xie * ----------------------------------------------- 970d5ec955Stony.xie * | S0 | ns0 | ns1 | ns2 | S1 | 980d5ec955Stony.xie * 0----------------------------------------------- max_mb 990d5ec955Stony.xie */ 1000d5ec955Stony.xie 1010d5ec955Stony.xie /* like above case2 figure, ns-region is not start from 0MB */ 1020d5ec955Stony.xie if (p.ns_base[0] != 0) { 1030d5ec955Stony.xie p.s_base[p.s_nr] = 0; 1040d5ec955Stony.xie p.s_top[p.s_nr] = p.ns_base[0]; 1050d5ec955Stony.xie p.s_nr++; 1060d5ec955Stony.xie } 1070d5ec955Stony.xie 1080d5ec955Stony.xie /* 1090d5ec955Stony.xie * notice: if ns-regions not start from 0MB, p.s_nr = 1 now, otherwise 0 1100d5ec955Stony.xie */ 1110d5ec955Stony.xie for (i = 0; i < p.ns_nr; i++) { 1120d5ec955Stony.xie /* 1130d5ec955Stony.xie * if current ns-regions top covers boundary, 1140d5ec955Stony.xie * that means s-regions are all parsed yet, so finsh. 1150d5ec955Stony.xie */ 1160d5ec955Stony.xie if (p.ns_top[i] == p.boundary) 1170d5ec955Stony.xie goto out; 1180d5ec955Stony.xie 1190d5ec955Stony.xie /* s-region's base starts from previous ns-region's top */ 1200d5ec955Stony.xie p.s_base[p.s_nr] = p.ns_top[i]; 1210d5ec955Stony.xie 1220d5ec955Stony.xie /* s-region's top ends with next ns-region's base */ 1230d5ec955Stony.xie if (i + 1 < p.ns_nr) 1240d5ec955Stony.xie p.s_top[p.s_nr] = p.ns_base[i + 1]; 1250d5ec955Stony.xie else 1260d5ec955Stony.xie p.s_top[p.s_nr] = p.boundary; 1270d5ec955Stony.xie p.s_nr++; 1280d5ec955Stony.xie } 1290d5ec955Stony.xie out: 1300d5ec955Stony.xie return p; 1310d5ec955Stony.xie } 132