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