xref: /aosp_15_r20/external/coreboot/src/vendorcode/cavium/bdk/libbdk-dram/bdk-dram-size.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /***********************license start***********************************
2 * Copyright (c) 2003-2017  Cavium Inc. ([email protected]). All rights
3 * reserved.
4 *
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 *   * Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 *
13 *   * Redistributions in binary form must reproduce the above
14 *     copyright notice, this list of conditions and the following
15 *     disclaimer in the documentation and/or other materials provided
16 *     with the distribution.
17 *
18 *   * Neither the name of Cavium Inc. nor the names of
19 *     its contributors may be used to endorse or promote products
20 *     derived from this software without specific prior written
21 *     permission.
22 *
23 * This Software, including technical data, may be subject to U.S. export
24 * control laws, including the U.S. Export Administration Act and its
25 * associated regulations, and may be subject to export or import
26 * regulations in other countries.
27 *
28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29 * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
31 * TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
32 * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
33 * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
34 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
35 * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
36 * QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK
37 * ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38 ***********************license end**************************************/
39 #include <bdk.h>
40 #include <bdk-coreboot.h>
41 #include <libbdk-hal/bdk-utils.h>
42 
43 
44 /**
45  * Return the number of LMC controllers in use
46  *
47  * @param node   Node to probe
48  *
49  * @return 2 or 4 depending on the mode
50  */
__bdk_dram_get_num_lmc(bdk_node_t node)51 int __bdk_dram_get_num_lmc(bdk_node_t node)
52 {
53     if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
54     {
55         BDK_CSR_INIT(lmcx_dll_ctl2, node, BDK_LMCX_DLL_CTL2(2)); // sample LMC2
56         return (lmcx_dll_ctl2.s.intf_en) ? 4 : 2;
57     }
58     else if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
59     {
60         BDK_CSR_INIT(lmcx_dll_ctl1, node, BDK_LMCX_DLL_CTL2(1)); // sample LMC1
61         return (lmcx_dll_ctl1.s.intf_en) ? 2 : 1;
62     }
63     else if (CAVIUM_IS_MODEL(CAVIUM_CN81XX))
64     {
65         return 1;
66     }
67     else if (CAVIUM_IS_MODEL(CAVIUM_CN93XX))
68     {
69         BDK_CSR_INIT(lmcx_dll_ctl1, node, BDK_LMCX_DLL_CTL2(2));
70         if (lmcx_dll_ctl1.s.intf_en)
71             return 3;
72         lmcx_dll_ctl1.u = BDK_CSR_READ(node, BDK_LMCX_DLL_CTL2(1));
73         return (lmcx_dll_ctl1.s.intf_en) ? 2 : 1;
74     }
75     bdk_error("__bdk_dram_get_num_lmc() needs update for this chip\n");
76     return 1;
77 }
78 
79 /**
80  * Return whether the node/LMC is in DRESET
81  *
82  * @param node   Node to probe
83  * @param node   LMC to probe
84  *
85  * @return 1 or 0
86  */
__bdk_dram_is_lmc_in_dreset(bdk_node_t node,int lmc)87 static int __bdk_dram_is_lmc_in_dreset(bdk_node_t node, int lmc)
88 {
89     BDK_CSR_INIT(lmcx_dll_ctl2, node, BDK_LMCX_DLL_CTL2(lmc)); // can always read this
90     return (lmcx_dll_ctl2.s.dreset != 0) ? 1 : 0;
91 }
92 
93 /**
94  * Return a mask of the number of row bits in use
95  *
96  * @param node   Node to probe
97  *
98  */
__bdk_dram_get_row_mask(bdk_node_t node,int lmc)99 uint32_t __bdk_dram_get_row_mask(bdk_node_t node, int lmc)
100 {
101     // PROTECT!!!
102     if (__bdk_dram_is_lmc_in_dreset(node, lmc)) // check LMCn
103         return 0;
104     BDK_CSR_INIT(lmcx_config, node, BDK_LMCX_CONFIG(lmc)); // sample LMCn
105     int numbits = 14 + lmcx_config.s.pbank_lsb - lmcx_config.s.row_lsb - lmcx_config.s.rank_ena;
106     return ((1ul << numbits) - 1);
107 }
108 
109 /**
110  * Return a mask of the number of column bits in use
111  *
112  * @param node   Node to probe
113  *
114  */
__bdk_dram_get_col_mask(bdk_node_t node,int lmc)115 uint32_t __bdk_dram_get_col_mask(bdk_node_t node, int lmc)
116 {
117     // PROTECT!!!
118     if (__bdk_dram_is_lmc_in_dreset(node, lmc)) // check LMCn
119         return 0;
120     BDK_CSR_INIT(lmcx_config, node, BDK_LMCX_CONFIG(lmc)); // sample LMCn
121     int numbits = 11 + lmcx_config.s.row_lsb - __bdk_dram_get_num_bank_bits(node, lmc);
122     return ((1ul << numbits) - 1);
123 }
124 
125 /**
126  * Return the number of bank bits in use
127  *
128  * @param node   Node to probe
129  *
130  */
131 // all DDR3, and DDR4 x16 today, use only 3 bank bits; DDR4 x4 and x8 always have 4 bank bits
132 // NOTE: this will change in the future, when DDR4 x16 devices can come with 16 banks!! FIXME!!
__bdk_dram_get_num_bank_bits(bdk_node_t node,int lmc)133 int __bdk_dram_get_num_bank_bits(bdk_node_t node, int lmc)
134 {
135     // PROTECT!!!
136     if (__bdk_dram_is_lmc_in_dreset(node, lmc)) // check LMCn
137         return 0;
138     BDK_CSR_INIT(lmcx_config, node, BDK_LMCX_CONFIG(lmc)); // sample LMCn
139     int bank_width = (__bdk_dram_is_ddr4(node, lmc) && (lmcx_config.s.bg2_enable)) ? 4 : 3;
140     return bank_width;
141 }
142 
143 /**
144  * Return whether the node has DDR3 or DDR4 DRAM
145  *
146  * @param node   Node to probe
147  *
148  * @return 0 (DDR3) or 1 (DDR4)
149  */
__bdk_dram_is_ddr4(bdk_node_t node,int lmc)150 int __bdk_dram_is_ddr4(bdk_node_t node, int lmc)
151 {
152     // PROTECT!!!
153     if (__bdk_dram_is_lmc_in_dreset(node, lmc)) // check LMCn
154         return 0;
155     if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX))
156         return 1;
157     BDK_CSR_INIT(lmcx_ddr_pll_ctl, node, BDK_LMCX_DDR_PLL_CTL(lmc)); // sample LMCn
158     return (lmcx_ddr_pll_ctl.cn83xx.ddr4_mode != 0);
159 }
160 
161 /**
162  * Return whether the node has Registered DIMMs or Unbuffered DIMMs
163  *
164  * @param node   Node to probe
165  *
166  * @return 0 (Unbuffered) or 1 (Registered)
167  */
__bdk_dram_is_rdimm(bdk_node_t node,int lmc)168 int __bdk_dram_is_rdimm(bdk_node_t node, int lmc)
169 {
170     // PROTECT!!!
171     if (__bdk_dram_is_lmc_in_dreset(node, lmc)) // check LMCn
172         return 0;
173     BDK_CSR_INIT(lmcx_control, node, BDK_LMCX_CONTROL(lmc)); // sample LMCn
174     return (lmcx_control.s.rdimm_ena != 0);
175 }
176 
177 /**
178  * Get the amount of DRAM configured for a node. This is read from the LMC
179  * controller after DRAM is setup.
180  *
181  * @param node   Node to query
182  *
183  * @return Size in megabytes
184  */
bdk_dram_get_size_mbytes(int node)185 uint64_t bdk_dram_get_size_mbytes(int node)
186 {
187     /* Return zero if dram isn't enabled */
188     if (!__bdk_is_dram_enabled(node))
189         return 0;
190 
191     uint64_t memsize = 0;
192     const int num_dram_controllers = __bdk_dram_get_num_lmc(node);
193     for (int lmc = 0; lmc < num_dram_controllers; lmc++)
194     {
195          // PROTECT!!!
196         if (__bdk_dram_is_lmc_in_dreset(node, lmc)) // check LMCn
197             return 0;
198         BDK_CSR_INIT(lmcx_config, node, BDK_LMCX_CONFIG(lmc));
199         int num_ranks = bdk_pop(lmcx_config.s.init_status);
200         uint64_t rank_size = 1ull << (28 + lmcx_config.s.pbank_lsb - lmcx_config.s.rank_ena);
201         memsize += rank_size * num_ranks;
202     }
203     return memsize >> 20;
204 }
205 
206