1a2847172SGrzegorz Jaszczyk /*
2a2847172SGrzegorz Jaszczyk * Copyright (C) 2018 Marvell International Ltd.
3a2847172SGrzegorz Jaszczyk *
4a2847172SGrzegorz Jaszczyk * SPDX-License-Identifier: BSD-3-Clause
5a2847172SGrzegorz Jaszczyk * https://spdx.org/licenses
6a2847172SGrzegorz Jaszczyk */
7a2847172SGrzegorz Jaszczyk
8a2847172SGrzegorz Jaszczyk #include <platform_def.h>
9a2847172SGrzegorz Jaszczyk
10a2847172SGrzegorz Jaszczyk #include <common/debug.h>
11a2847172SGrzegorz Jaszczyk #include <lib/mmio.h>
12a2847172SGrzegorz Jaszczyk
13a2847172SGrzegorz Jaszczyk #include <ddr_info.h>
14a2847172SGrzegorz Jaszczyk
15a2847172SGrzegorz Jaszczyk #define DRAM_CH0_MMAP_LOW_REG(iface, cs, base) \
16a2847172SGrzegorz Jaszczyk (base + DRAM_CH0_MMAP_LOW_OFFSET + (iface) * 0x10000 + (cs) * 0x8)
17a2847172SGrzegorz Jaszczyk #define DRAM_CH0_MMAP_HIGH_REG(iface, cs, base) \
18a2847172SGrzegorz Jaszczyk (DRAM_CH0_MMAP_LOW_REG(iface, cs, base) + 4)
19a2847172SGrzegorz Jaszczyk #define DRAM_CS_VALID_ENABLED_MASK 0x1
20a2847172SGrzegorz Jaszczyk #define DRAM_AREA_LENGTH_OFFS 16
21a2847172SGrzegorz Jaszczyk #define DRAM_AREA_LENGTH_MASK (0x1f << DRAM_AREA_LENGTH_OFFS)
22a2847172SGrzegorz Jaszczyk #define DRAM_START_ADDRESS_L_OFFS 23
23a2847172SGrzegorz Jaszczyk #define DRAM_START_ADDRESS_L_MASK \
24a2847172SGrzegorz Jaszczyk (0x1ff << DRAM_START_ADDRESS_L_OFFS)
25a2847172SGrzegorz Jaszczyk #define DRAM_START_ADDR_HTOL_OFFS 32
26a2847172SGrzegorz Jaszczyk
27a2847172SGrzegorz Jaszczyk #define DRAM_MAX_CS_NUM 2
28a2847172SGrzegorz Jaszczyk
29a2847172SGrzegorz Jaszczyk #define DRAM_CS_ENABLED(iface, cs, base) \
30a2847172SGrzegorz Jaszczyk (mmio_read_32(DRAM_CH0_MMAP_LOW_REG(iface, cs, base)) & \
31a2847172SGrzegorz Jaszczyk DRAM_CS_VALID_ENABLED_MASK)
32a2847172SGrzegorz Jaszczyk #define GET_DRAM_REGION_SIZE_CODE(iface, cs, base) \
33a2847172SGrzegorz Jaszczyk (mmio_read_32(DRAM_CH0_MMAP_LOW_REG(iface, cs, base)) & \
34a2847172SGrzegorz Jaszczyk DRAM_AREA_LENGTH_MASK) >> DRAM_AREA_LENGTH_OFFS
35a2847172SGrzegorz Jaszczyk
36a2847172SGrzegorz Jaszczyk /* Mapping between DDR area length and real DDR size is specific and looks like
37*1b491eeaSElyes Haouas * below:
38a2847172SGrzegorz Jaszczyk * 0 => 384 MB
39a2847172SGrzegorz Jaszczyk * 1 => 768 MB
40a2847172SGrzegorz Jaszczyk * 2 => 1536 MB
41a2847172SGrzegorz Jaszczyk * 3 => 3 GB
42a2847172SGrzegorz Jaszczyk * 4 => 6 GB
43a2847172SGrzegorz Jaszczyk *
44a2847172SGrzegorz Jaszczyk * 7 => 8 MB
45a2847172SGrzegorz Jaszczyk * 8 => 16 MB
46a2847172SGrzegorz Jaszczyk * 9 => 32 MB
47a2847172SGrzegorz Jaszczyk * 10 => 64 MB
48a2847172SGrzegorz Jaszczyk * 11 => 128 MB
49a2847172SGrzegorz Jaszczyk * 12 => 256 MB
50a2847172SGrzegorz Jaszczyk * 13 => 512 MB
51a2847172SGrzegorz Jaszczyk * 14 => 1 GB
52a2847172SGrzegorz Jaszczyk * 15 => 2 GB
53a2847172SGrzegorz Jaszczyk * 16 => 4 GB
54a2847172SGrzegorz Jaszczyk * 17 => 8 GB
55a2847172SGrzegorz Jaszczyk * 18 => 16 GB
56a2847172SGrzegorz Jaszczyk * 19 => 32 GB
57a2847172SGrzegorz Jaszczyk * 20 => 64 GB
58a2847172SGrzegorz Jaszczyk * 21 => 128 GB
59a2847172SGrzegorz Jaszczyk * 22 => 256 GB
60a2847172SGrzegorz Jaszczyk * 23 => 512 GB
61a2847172SGrzegorz Jaszczyk * 24 => 1 TB
62a2847172SGrzegorz Jaszczyk * 25 => 2 TB
63a2847172SGrzegorz Jaszczyk * 26 => 4 TB
64a2847172SGrzegorz Jaszczyk *
65a2847172SGrzegorz Jaszczyk * to calculate real size we need to use two different formulas:
66a2847172SGrzegorz Jaszczyk * -- GET_DRAM_REGION_SIZE_ODD for values 0-4 (DRAM_REGION_SIZE_ODD)
67a2847172SGrzegorz Jaszczyk * -- GET_DRAM_REGION_SIZE_EVEN for values 7-26 (DRAM_REGION_SIZE_EVEN)
68a2847172SGrzegorz Jaszczyk * using mentioned formulas we cover whole mapping between "Area length" value
69a2847172SGrzegorz Jaszczyk * and real size (see above mapping).
70a2847172SGrzegorz Jaszczyk */
71a2847172SGrzegorz Jaszczyk #define DRAM_REGION_SIZE_EVEN(C) (((C) >= 7) && ((C) <= 26))
72a2847172SGrzegorz Jaszczyk #define GET_DRAM_REGION_SIZE_EVEN(C) ((uint64_t)1 << ((C) + 16))
73a2847172SGrzegorz Jaszczyk #define DRAM_REGION_SIZE_ODD(C) ((C) <= 4)
74a2847172SGrzegorz Jaszczyk #define GET_DRAM_REGION_SIZE_ODD(C) ((uint64_t)0x18000000 << (C))
75a2847172SGrzegorz Jaszczyk
76a2847172SGrzegorz Jaszczyk
mvebu_get_dram_size(uint64_t ap_base_addr)77a2847172SGrzegorz Jaszczyk uint64_t mvebu_get_dram_size(uint64_t ap_base_addr)
78a2847172SGrzegorz Jaszczyk {
79a2847172SGrzegorz Jaszczyk uint64_t mem_size = 0;
80a2847172SGrzegorz Jaszczyk uint8_t region_code;
81a2847172SGrzegorz Jaszczyk uint8_t cs, iface;
82a2847172SGrzegorz Jaszczyk
83a2847172SGrzegorz Jaszczyk for (iface = 0; iface < DRAM_MAX_IFACE; iface++) {
84a2847172SGrzegorz Jaszczyk for (cs = 0; cs < DRAM_MAX_CS_NUM; cs++) {
85a2847172SGrzegorz Jaszczyk
86a2847172SGrzegorz Jaszczyk /* Exit loop on first disabled DRAM CS */
87a2847172SGrzegorz Jaszczyk if (!DRAM_CS_ENABLED(iface, cs, ap_base_addr))
88a2847172SGrzegorz Jaszczyk break;
89a2847172SGrzegorz Jaszczyk
90a2847172SGrzegorz Jaszczyk /* Decode area length for current CS
91a2847172SGrzegorz Jaszczyk * from register value
92a2847172SGrzegorz Jaszczyk */
93a2847172SGrzegorz Jaszczyk region_code =
94a2847172SGrzegorz Jaszczyk GET_DRAM_REGION_SIZE_CODE(iface, cs,
95a2847172SGrzegorz Jaszczyk ap_base_addr);
96a2847172SGrzegorz Jaszczyk
97a2847172SGrzegorz Jaszczyk if (DRAM_REGION_SIZE_EVEN(region_code)) {
98a2847172SGrzegorz Jaszczyk mem_size +=
99a2847172SGrzegorz Jaszczyk GET_DRAM_REGION_SIZE_EVEN(region_code);
100a2847172SGrzegorz Jaszczyk } else if (DRAM_REGION_SIZE_ODD(region_code)) {
101a2847172SGrzegorz Jaszczyk mem_size +=
102a2847172SGrzegorz Jaszczyk GET_DRAM_REGION_SIZE_ODD(region_code);
103a2847172SGrzegorz Jaszczyk } else {
104a2847172SGrzegorz Jaszczyk WARN("%s: Invalid mem region (0x%x) CS#%d\n",
105a2847172SGrzegorz Jaszczyk __func__, region_code, cs);
106a2847172SGrzegorz Jaszczyk return 0;
107a2847172SGrzegorz Jaszczyk }
108a2847172SGrzegorz Jaszczyk }
109a2847172SGrzegorz Jaszczyk }
110a2847172SGrzegorz Jaszczyk
111a2847172SGrzegorz Jaszczyk return mem_size;
112a2847172SGrzegorz Jaszczyk }
113