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