blob: f6745b297caa6da31ca4b7175ebb58d4e0f396e8 [file] [log] [blame]
Soby Mathew9b2de242024-02-27 16:08:42 +00001/*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4 */
5
AlexeiFedorovffef39a2024-10-28 16:35:21 +00006#include <arm_memory.h>
Soby Mathew9b2de242024-02-27 16:08:42 +00007#include <assert.h>
8#include <platform_api.h>
9#include <utils_def.h>
10
AlexeiFedorovffef39a2024-10-28 16:35:21 +000011static struct arm_memory_layout arm_dram;
12static struct arm_memory_layout arm_dev_ncoh;
13static struct arm_memory_layout arm_dev_coh;
Soby Mathew9b2de242024-02-27 16:08:42 +000014
AlexeiFedorovffef39a2024-10-28 16:35:21 +000015struct arm_memory_layout *arm_get_dram_layout(void)
Soby Mathew9b2de242024-02-27 16:08:42 +000016{
17 return &arm_dram;
18}
19
AlexeiFedorovffef39a2024-10-28 16:35:21 +000020struct arm_memory_layout *arm_get_dev_ncoh_layout(void)
21{
22 return &arm_dev_ncoh;
23}
24
25struct arm_memory_layout *arm_get_dev_coh_layout(void)
26{
27 return &arm_dev_coh;
28}
29
AlexeiFedorov037add62024-10-30 15:53:05 +000030static unsigned long granule_addr_to_idx(unsigned long addr,
31 struct arm_memory_layout *memory_ptr)
Soby Mathew9b2de242024-02-27 16:08:42 +000032{
Harry Moulton1c9c7b92024-03-07 16:33:59 +000033 unsigned long r, l = 0UL;
34
AlexeiFedorov037add62024-10-30 15:53:05 +000035 if (!GRANULE_ALIGNED(addr) || (memory_ptr->num_banks == 0UL)) {
Soby Mathew9b2de242024-02-27 16:08:42 +000036 return UINT64_MAX;
37 }
38
AlexeiFedorov037add62024-10-30 15:53:05 +000039 assert(memory_ptr->num_banks <= PLAT_ARM_MAX_MEM_BANKS);
40 r = memory_ptr->num_banks - 1UL;
Soby Mathew9b2de242024-02-27 16:08:42 +000041
Harry Moulton1c9c7b92024-03-07 16:33:59 +000042 /*
43 * Use a binary search rather than a linear one to locate the bank which
44 * the address falls within, then use the start_gran_idx (which is a
AlexeiFedorov037add62024-10-30 15:53:05 +000045 * cumulative idx from previous memory banks) to calculate the required
Harry Moulton1c9c7b92024-03-07 16:33:59 +000046 * granule index.
47 */
48 while (l <= r) {
AlexeiFedorovffef39a2024-10-28 16:35:21 +000049 const struct arm_memory_bank *bank;
Harry Moulton1c9c7b92024-03-07 16:33:59 +000050 unsigned long i;
Soby Mathew9b2de242024-02-27 16:08:42 +000051
Harry Moulton1c9c7b92024-03-07 16:33:59 +000052 i = l + ((r - l) / 2UL);
AlexeiFedorovffef39a2024-10-28 16:35:21 +000053 assert(i < PLAT_ARM_MAX_MEM_BANKS);
Harry Moulton1c9c7b92024-03-07 16:33:59 +000054
AlexeiFedorov037add62024-10-30 15:53:05 +000055 bank = &memory_ptr->bank[i];
Harry Moulton1c9c7b92024-03-07 16:33:59 +000056
57 if (addr < bank->base) {
58 if (i == 0UL) {
59 break;
60 }
61 r = i - 1UL;
62 } else if (addr > (bank->base + bank->size - 1UL)) {
63 l = i + 1UL;
64 } else {
65 return (bank->start_gran_idx +
66 ((addr - bank->base) >> GRANULE_SHIFT));
67 }
68 }
Soby Mathew9b2de242024-02-27 16:08:42 +000069 return UINT64_MAX;
70}
71
AlexeiFedorov037add62024-10-30 15:53:05 +000072unsigned long plat_granule_addr_to_idx(unsigned long addr)
Soby Mathew9b2de242024-02-27 16:08:42 +000073{
AlexeiFedorov037add62024-10-30 15:53:05 +000074 return granule_addr_to_idx(addr, &arm_dram);
75}
76
77unsigned long plat_dev_granule_addr_to_idx(unsigned long addr, enum dev_type *type)
78{
79 unsigned long ret;
80
81 assert(type != NULL);
82
83 /* Check non-coherent device granules */
84 if (arm_dev_ncoh.num_granules != 0UL) {
85 ret = granule_addr_to_idx(addr, &arm_dev_ncoh);
86 if (ret != UINT64_MAX) {
87 *type = DEV_RANGE_NON_COHERENT;
88 return ret;
89 }
90 }
91
92 /* Check coherent device granules */
93 if (arm_dev_coh.num_granules != 0UL) {
94 ret = granule_addr_to_idx(addr, &arm_dev_coh);
95 if (ret != UINT64_MAX) {
96 *type = DEV_RANGE_COHERENT;
97 return ret;
98 }
99 }
100
101 *type = DEV_RANGE_MAX;
102 return UINT64_MAX;
103}
104
105static unsigned long granule_idx_to_addr(unsigned long idx,
106 struct arm_memory_layout *memory_ptr)
107{
Harry Moulton1c9c7b92024-03-07 16:33:59 +0000108 unsigned long r, l = 0UL, addr = 0UL;
Soby Mathew9b2de242024-02-27 16:08:42 +0000109
AlexeiFedorov037add62024-10-30 15:53:05 +0000110 assert(memory_ptr->num_banks != 0UL);
111 assert(idx < memory_ptr->num_granules);
Harry Moulton1c9c7b92024-03-07 16:33:59 +0000112
AlexeiFedorov037add62024-10-30 15:53:05 +0000113 r = memory_ptr->num_banks - 1UL;
Harry Moulton1c9c7b92024-03-07 16:33:59 +0000114
115 /*
116 * Calculate the start and end granule index of each bank using the
AlexeiFedorov037add62024-10-30 15:53:05 +0000117 * start_gran_idx (which is a cumulative idx from previous memory banks)
Harry Moulton1c9c7b92024-03-07 16:33:59 +0000118 * and then check whether the given index falls within it.
119 */
120 while (l <= r) {
AlexeiFedorovffef39a2024-10-28 16:35:21 +0000121 const struct arm_memory_bank *bank;
Harry Moulton1c9c7b92024-03-07 16:33:59 +0000122 unsigned long i;
123 unsigned long idx_start, idx_end;
124
125 i = l + ((r - l) / 2UL);
AlexeiFedorovffef39a2024-10-28 16:35:21 +0000126 assert(i < PLAT_ARM_MAX_MEM_BANKS);
Harry Moulton1c9c7b92024-03-07 16:33:59 +0000127
AlexeiFedorov037add62024-10-30 15:53:05 +0000128 bank = &memory_ptr->bank[i];
Harry Moulton1c9c7b92024-03-07 16:33:59 +0000129
130 idx_start = bank->start_gran_idx;
131 idx_end = idx_start + (bank->size >> GRANULE_SHIFT) - 1UL;
132
133 if (idx < idx_start) {
134 assert(i != 0UL);
135 r = i - 1UL;
136 } else if (idx > idx_end) {
137 l = i + 1UL;
138 } else {
139 addr = bank->base + ((idx - idx_start) << GRANULE_SHIFT);
140 break;
141 }
Soby Mathew9b2de242024-02-27 16:08:42 +0000142 }
Harry Moulton1c9c7b92024-03-07 16:33:59 +0000143 /* Assert that the search was successful */
144 assert(l <= r);
145 return addr;
Soby Mathew9b2de242024-02-27 16:08:42 +0000146}
AlexeiFedorov037add62024-10-30 15:53:05 +0000147
148unsigned long plat_granule_idx_to_addr(unsigned long idx)
149{
150 return granule_idx_to_addr(idx, &arm_dram);
151}
152
153unsigned long plat_dev_granule_idx_to_addr(unsigned long idx, enum dev_type type)
154{
155 (void)type;
156
157 /* No coherent device memory */
158 assert(type == DEV_RANGE_NON_COHERENT);
159
160 return granule_idx_to_addr(idx, &arm_dev_ncoh);
161}
162