1*0d5ec955Stony.xie /* 2*0d5ec955Stony.xie * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3*0d5ec955Stony.xie * 4*0d5ec955Stony.xie * Redistribution and use in source and binary forms, with or without 5*0d5ec955Stony.xie * modification, are permitted provided that the following conditions are met: 6*0d5ec955Stony.xie * 7*0d5ec955Stony.xie * Redistributions of source code must retain the above copyright notice, this 8*0d5ec955Stony.xie * list of conditions and the following disclaimer. 9*0d5ec955Stony.xie * 10*0d5ec955Stony.xie * Redistributions in binary form must reproduce the above copyright notice, 11*0d5ec955Stony.xie * this list of conditions and the following disclaimer in the documentation 12*0d5ec955Stony.xie * and/or other materials provided with the distribution. 13*0d5ec955Stony.xie * 14*0d5ec955Stony.xie * Neither the name of ARM nor the names of its contributors may be used 15*0d5ec955Stony.xie * to endorse or promote products derived from this software without specific 16*0d5ec955Stony.xie * prior written permission. 17*0d5ec955Stony.xie * 18*0d5ec955Stony.xie * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19*0d5ec955Stony.xie * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20*0d5ec955Stony.xie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21*0d5ec955Stony.xie * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22*0d5ec955Stony.xie * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23*0d5ec955Stony.xie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24*0d5ec955Stony.xie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25*0d5ec955Stony.xie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26*0d5ec955Stony.xie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27*0d5ec955Stony.xie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28*0d5ec955Stony.xie * POSSIBILITY OF SUCH DAMAGE. 29*0d5ec955Stony.xie */ 30*0d5ec955Stony.xie 31*0d5ec955Stony.xie #include <arch_helpers.h> 32*0d5ec955Stony.xie #include <console.h> 33*0d5ec955Stony.xie #include <debug.h> 34*0d5ec955Stony.xie #include <delay_timer.h> 35*0d5ec955Stony.xie #include <mmio.h> 36*0d5ec955Stony.xie #include <platform_def.h> 37*0d5ec955Stony.xie #include <plat_private.h> 38*0d5ec955Stony.xie #include <soc.h> 39*0d5ec955Stony.xie #include <string.h> 40*0d5ec955Stony.xie #include "ddr_parameter.h" 41*0d5ec955Stony.xie 42*0d5ec955Stony.xie /* 43*0d5ec955Stony.xie * The miniloader delivers the parameters about ddr usage info from address 44*0d5ec955Stony.xie * 0x02000000 and the data format is defined as below figure. It tells ATF the 45*0d5ec955Stony.xie * areas of ddr that are used by platform, we treat them as non-secure regions 46*0d5ec955Stony.xie * by default. Then we should parse the other part regions and configurate them 47*0d5ec955Stony.xie * as secure regions to avoid illegal access. 48*0d5ec955Stony.xie * 49*0d5ec955Stony.xie * [ddr usage info data format] 50*0d5ec955Stony.xie * 0x02000000 51*0d5ec955Stony.xie * ----------------------------------------------------------------------------- 52*0d5ec955Stony.xie * | <name> | <size> | <description> | 53*0d5ec955Stony.xie * ----------------------------------------------------------------------------- 54*0d5ec955Stony.xie * | count | 4byte | the array numbers of the | 55*0d5ec955Stony.xie * | | | 'addr_array' and 'size_array' | 56*0d5ec955Stony.xie * ----------------------------------------------------------------------------- 57*0d5ec955Stony.xie * | reserved | 4byte | just for 'addr_array' 8byte aligned | 58*0d5ec955Stony.xie * ----------------------------------------------------------------------------- 59*0d5ec955Stony.xie * | addr_array[count] | per 8byte | memory region base address | 60*0d5ec955Stony.xie * ----------------------------------------------------------------------------- 61*0d5ec955Stony.xie * | size_array[count] | per 8byte | memory region size (byte) | 62*0d5ec955Stony.xie * ----------------------------------------------------------------------------- 63*0d5ec955Stony.xie */ 64*0d5ec955Stony.xie 65*0d5ec955Stony.xie /* 66*0d5ec955Stony.xie * function: read parameters info(ns-regions) and try to parse s-regions info 67*0d5ec955Stony.xie * 68*0d5ec955Stony.xie * @addr: head address to the ddr usage struct from miniloader 69*0d5ec955Stony.xie * @max_mb: the max ddr capacity(MB) that the platform support 70*0d5ec955Stony.xie */ 71*0d5ec955Stony.xie struct param_ddr_usage ddr_region_usage_parse(uint64_t addr, uint64_t max_mb) 72*0d5ec955Stony.xie { 73*0d5ec955Stony.xie uint64_t base, top; 74*0d5ec955Stony.xie uint32_t i, addr_offset, size_offset; 75*0d5ec955Stony.xie struct param_ddr_usage p; 76*0d5ec955Stony.xie 77*0d5ec955Stony.xie memset(&p, 0, sizeof(p)); 78*0d5ec955Stony.xie 79*0d5ec955Stony.xie /* read how many blocks of ns-regions, read from offset: 0x0 */ 80*0d5ec955Stony.xie p.ns_nr = mmio_read_32(addr + REGION_NR_OFFSET); 81*0d5ec955Stony.xie if ((p.ns_nr > DDR_REGION_NR_MAX) || (p.ns_nr == 0)) { 82*0d5ec955Stony.xie ERROR("over or zero region, nr=%d, max=%d\n", 83*0d5ec955Stony.xie p.ns_nr, DDR_REGION_NR_MAX); 84*0d5ec955Stony.xie return p; 85*0d5ec955Stony.xie } 86*0d5ec955Stony.xie 87*0d5ec955Stony.xie /* whole ddr regions boundary, it will be used when parse s-regions */ 88*0d5ec955Stony.xie p.boundary = max_mb; 89*0d5ec955Stony.xie 90*0d5ec955Stony.xie /* calculate ns-region base addr and size offset */ 91*0d5ec955Stony.xie addr_offset = REGION_ADDR_OFFSET; 92*0d5ec955Stony.xie size_offset = REGION_ADDR_OFFSET + p.ns_nr * REGION_DATA_PER_BYTES; 93*0d5ec955Stony.xie 94*0d5ec955Stony.xie /* read all ns-regions base and top address */ 95*0d5ec955Stony.xie for (i = 0; i < p.ns_nr; i++) { 96*0d5ec955Stony.xie base = mmio_read_64(addr + addr_offset); 97*0d5ec955Stony.xie top = base + mmio_read_64(addr + size_offset); 98*0d5ec955Stony.xie /* 99*0d5ec955Stony.xie * translate byte to MB and store info, 100*0d5ec955Stony.xie * Miniloader will promise every ns-region is MB aligned. 101*0d5ec955Stony.xie */ 102*0d5ec955Stony.xie p.ns_base[i] = RG_SIZE_MB(base); 103*0d5ec955Stony.xie p.ns_top[i] = RG_SIZE_MB(top); 104*0d5ec955Stony.xie 105*0d5ec955Stony.xie addr_offset += REGION_DATA_PER_BYTES; 106*0d5ec955Stony.xie size_offset += REGION_DATA_PER_BYTES; 107*0d5ec955Stony.xie } 108*0d5ec955Stony.xie 109*0d5ec955Stony.xie /* 110*0d5ec955Stony.xie * a s-region's base starts from previous ns-region's top, and a 111*0d5ec955Stony.xie * s-region's top ends with next ns-region's base. maybe like this: 112*0d5ec955Stony.xie * 113*0d5ec955Stony.xie * case1: ns-regison start from 0MB 114*0d5ec955Stony.xie * ----------------------------------------------- 115*0d5ec955Stony.xie * | ns0 | S0 | ns1 | S1 | ns2 | 116*0d5ec955Stony.xie * 0----------------------------------------------- max_mb 117*0d5ec955Stony.xie * 118*0d5ec955Stony.xie * 119*0d5ec955Stony.xie * case2: ns-regison not start from 0MB 120*0d5ec955Stony.xie * ----------------------------------------------- 121*0d5ec955Stony.xie * | S0 | ns0 | ns1 | ns2 | S1 | 122*0d5ec955Stony.xie * 0----------------------------------------------- max_mb 123*0d5ec955Stony.xie */ 124*0d5ec955Stony.xie 125*0d5ec955Stony.xie /* like above case2 figure, ns-region is not start from 0MB */ 126*0d5ec955Stony.xie if (p.ns_base[0] != 0) { 127*0d5ec955Stony.xie p.s_base[p.s_nr] = 0; 128*0d5ec955Stony.xie p.s_top[p.s_nr] = p.ns_base[0]; 129*0d5ec955Stony.xie p.s_nr++; 130*0d5ec955Stony.xie } 131*0d5ec955Stony.xie 132*0d5ec955Stony.xie /* 133*0d5ec955Stony.xie * notice: if ns-regions not start from 0MB, p.s_nr = 1 now, otherwise 0 134*0d5ec955Stony.xie */ 135*0d5ec955Stony.xie for (i = 0; i < p.ns_nr; i++) { 136*0d5ec955Stony.xie /* 137*0d5ec955Stony.xie * if current ns-regions top covers boundary, 138*0d5ec955Stony.xie * that means s-regions are all parsed yet, so finsh. 139*0d5ec955Stony.xie */ 140*0d5ec955Stony.xie if (p.ns_top[i] == p.boundary) 141*0d5ec955Stony.xie goto out; 142*0d5ec955Stony.xie 143*0d5ec955Stony.xie /* s-region's base starts from previous ns-region's top */ 144*0d5ec955Stony.xie p.s_base[p.s_nr] = p.ns_top[i]; 145*0d5ec955Stony.xie 146*0d5ec955Stony.xie /* s-region's top ends with next ns-region's base */ 147*0d5ec955Stony.xie if (i + 1 < p.ns_nr) 148*0d5ec955Stony.xie p.s_top[p.s_nr] = p.ns_base[i + 1]; 149*0d5ec955Stony.xie else 150*0d5ec955Stony.xie p.s_top[p.s_nr] = p.boundary; 151*0d5ec955Stony.xie p.s_nr++; 152*0d5ec955Stony.xie } 153*0d5ec955Stony.xie out: 154*0d5ec955Stony.xie return p; 155*0d5ec955Stony.xie } 156