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