blob: a67479496654bd580ed73df0e512d51c37cc2680 [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
6#include <arm_dram.h>
7#include <assert.h>
8#include <platform_api.h>
9#include <utils_def.h>
10
11static struct arm_dram_layout arm_dram;
12
13struct arm_dram_layout *arm_get_dram_layout(void)
14{
15 return &arm_dram;
16}
17
18unsigned long plat_granule_addr_to_idx(unsigned long addr)
19{
Harry Moulton1c9c7b92024-03-07 16:33:59 +000020 const struct arm_dram_layout *dram = &arm_dram;
21 unsigned long r, l = 0UL;
22
Soby Mathew9b2de242024-02-27 16:08:42 +000023 if (!GRANULE_ALIGNED(addr)) {
24 return UINT64_MAX;
25 }
26
Harry Moulton1c9c7b92024-03-07 16:33:59 +000027 assert(dram->num_banks > 0UL);
28 assert(dram->num_banks <= PLAT_ARM_MAX_DRAM_BANKS);
29 r = dram->num_banks - 1UL;
Soby Mathew9b2de242024-02-27 16:08:42 +000030
Harry Moulton1c9c7b92024-03-07 16:33:59 +000031 /*
32 * Use a binary search rather than a linear one to locate the bank which
33 * the address falls within, then use the start_gran_idx (which is a
34 * cumulative idx from previous dram banks) to calculate the required
35 * granule index.
36 */
37 while (l <= r) {
38 const struct arm_dram_bank *bank;
39 unsigned long i;
Soby Mathew9b2de242024-02-27 16:08:42 +000040
Harry Moulton1c9c7b92024-03-07 16:33:59 +000041 i = l + ((r - l) / 2UL);
42 assert(i < PLAT_ARM_MAX_DRAM_BANKS);
43
44 bank = &dram->bank[i];
45
46 if (addr < bank->base) {
47 if (i == 0UL) {
48 break;
49 }
50 r = i - 1UL;
51 } else if (addr > (bank->base + bank->size - 1UL)) {
52 l = i + 1UL;
53 } else {
54 return (bank->start_gran_idx +
55 ((addr - bank->base) >> GRANULE_SHIFT));
56 }
57 }
Soby Mathew9b2de242024-02-27 16:08:42 +000058 return UINT64_MAX;
59}
60
61unsigned long plat_granule_idx_to_addr(unsigned long idx)
62{
Harry Moulton1c9c7b92024-03-07 16:33:59 +000063 const struct arm_dram_layout *dram = &arm_dram;
64 unsigned long r, l = 0UL, addr = 0UL;
Soby Mathew9b2de242024-02-27 16:08:42 +000065
Harry Moulton1c9c7b92024-03-07 16:33:59 +000066 assert(dram->num_banks > 0UL);
67 assert(idx < dram->num_granules);
68
69 r = dram->num_banks - 1UL;
70
71 /*
72 * Calculate the start and end granule index of each bank using the
73 * start_gran_idx (which is a cumulative idx from previous dram banks)
74 * and then check whether the given index falls within it.
75 */
76 while (l <= r) {
77 const struct arm_dram_bank *bank;
78 unsigned long i;
79 unsigned long idx_start, idx_end;
80
81 i = l + ((r - l) / 2UL);
82 assert(i < PLAT_ARM_MAX_DRAM_BANKS);
83
84 bank = &dram->bank[i];
85
86 idx_start = bank->start_gran_idx;
87 idx_end = idx_start + (bank->size >> GRANULE_SHIFT) - 1UL;
88
89 if (idx < idx_start) {
90 assert(i != 0UL);
91 r = i - 1UL;
92 } else if (idx > idx_end) {
93 l = i + 1UL;
94 } else {
95 addr = bank->base + ((idx - idx_start) << GRANULE_SHIFT);
96 break;
97 }
Soby Mathew9b2de242024-02-27 16:08:42 +000098 }
Harry Moulton1c9c7b92024-03-07 16:33:59 +000099 /* Assert that the search was successful */
100 assert(l <= r);
101 return addr;
Soby Mathew9b2de242024-02-27 16:08:42 +0000102}