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