aboutsummaryrefslogtreecommitdiff
path: root/src/vendorcode/cavium/bdk/libbdk-dram/bdk-dram-size.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/cavium/bdk/libbdk-dram/bdk-dram-size.c')
-rw-r--r--src/vendorcode/cavium/bdk/libbdk-dram/bdk-dram-size.c213
1 files changed, 213 insertions, 0 deletions
diff --git a/src/vendorcode/cavium/bdk/libbdk-dram/bdk-dram-size.c b/src/vendorcode/cavium/bdk/libbdk-dram/bdk-dram-size.c
new file mode 100644
index 0000000000..122afb2a18
--- /dev/null
+++ b/src/vendorcode/cavium/bdk/libbdk-dram/bdk-dram-size.c
@@ -0,0 +1,213 @@
+/***********************license start***********************************
+* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
+* reserved.
+*
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* * Redistributions in binary form must reproduce the above
+* copyright notice, this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided
+* with the distribution.
+*
+* * Neither the name of Cavium Inc. nor the names of
+* its contributors may be used to endorse or promote products
+* derived from this software without specific prior written
+* permission.
+*
+* This Software, including technical data, may be subject to U.S. export
+* control laws, including the U.S. Export Administration Act and its
+* associated regulations, and may be subject to export or import
+* regulations in other countries.
+*
+* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
+* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
+* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
+* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
+* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
+* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
+* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
+* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
+* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+***********************license end**************************************/
+#include <bdk.h>
+
+/**
+ * Return the number of LMC controllers in use
+ *
+ * @param node Node to probe
+ *
+ * @return 2 or 4 depending on the mode
+ */
+int __bdk_dram_get_num_lmc(bdk_node_t node)
+{
+ if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
+ {
+ BDK_CSR_INIT(lmcx_dll_ctl2, node, BDK_LMCX_DLL_CTL2(2)); // sample LMC2
+ return (lmcx_dll_ctl2.s.intf_en) ? 4 : 2;
+ }
+ else if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
+ {
+ BDK_CSR_INIT(lmcx_dll_ctl1, node, BDK_LMCX_DLL_CTL2(1)); // sample LMC1
+ return (lmcx_dll_ctl1.s.intf_en) ? 2 : 1;
+ }
+ else if (CAVIUM_IS_MODEL(CAVIUM_CN81XX))
+ {
+ return 1;
+ }
+ else if (CAVIUM_IS_MODEL(CAVIUM_CN93XX))
+ {
+ BDK_CSR_INIT(lmcx_dll_ctl1, node, BDK_LMCX_DLL_CTL2(2));
+ if (lmcx_dll_ctl1.s.intf_en)
+ return 3;
+ lmcx_dll_ctl1.u = BDK_CSR_READ(node, BDK_LMCX_DLL_CTL2(1));
+ return (lmcx_dll_ctl1.s.intf_en) ? 2 : 1;
+ }
+ bdk_error("__bdk_dram_get_num_lmc() needs update for this chip\n");
+ return 1;
+}
+
+/**
+ * Return whether the node/LMC is in DRESET
+ *
+ * @param node Node to probe
+ * @param node LMC to probe
+ *
+ * @return 1 or 0
+ */
+static int __bdk_dram_is_lmc_in_dreset(bdk_node_t node, int lmc)
+{
+ BDK_CSR_INIT(lmcx_dll_ctl2, node, BDK_LMCX_DLL_CTL2(lmc)); // can always read this
+ return (lmcx_dll_ctl2.s.dreset != 0) ? 1 : 0;
+}
+
+/**
+ * Return a mask of the number of row bits in use
+ *
+ * @param node Node to probe
+ *
+ */
+uint32_t __bdk_dram_get_row_mask(bdk_node_t node, int lmc)
+{
+ // PROTECT!!!
+ if (__bdk_dram_is_lmc_in_dreset(node, lmc)) // check LMCn
+ return 0;
+ BDK_CSR_INIT(lmcx_config, node, BDK_LMCX_CONFIG(lmc)); // sample LMCn
+ int numbits = 14 + lmcx_config.s.pbank_lsb - lmcx_config.s.row_lsb - lmcx_config.s.rank_ena;
+ return ((1ul << numbits) - 1);
+}
+
+/**
+ * Return a mask of the number of column bits in use
+ *
+ * @param node Node to probe
+ *
+ */
+uint32_t __bdk_dram_get_col_mask(bdk_node_t node, int lmc)
+{
+ // PROTECT!!!
+ if (__bdk_dram_is_lmc_in_dreset(node, lmc)) // check LMCn
+ return 0;
+ BDK_CSR_INIT(lmcx_config, node, BDK_LMCX_CONFIG(lmc)); // sample LMCn
+ int numbits = 11 + lmcx_config.s.row_lsb - __bdk_dram_get_num_bank_bits(node, lmc);
+ return ((1ul << numbits) - 1);
+}
+
+/**
+ * Return the number of bank bits in use
+ *
+ * @param node Node to probe
+ *
+ */
+// all DDR3, and DDR4 x16 today, use only 3 bank bits; DDR4 x4 and x8 always have 4 bank bits
+// NOTE: this will change in the future, when DDR4 x16 devices can come with 16 banks!! FIXME!!
+int __bdk_dram_get_num_bank_bits(bdk_node_t node, int lmc)
+{
+ // PROTECT!!!
+ if (__bdk_dram_is_lmc_in_dreset(node, lmc)) // check LMCn
+ return 0;
+ BDK_CSR_INIT(lmcx_config, node, BDK_LMCX_CONFIG(lmc)); // sample LMCn
+ int bank_width = (__bdk_dram_is_ddr4(node, lmc) && (lmcx_config.s.bg2_enable)) ? 4 : 3;
+ return bank_width;
+}
+
+/**
+ * Return whether the node has DDR3 or DDR4 DRAM
+ *
+ * @param node Node to probe
+ *
+ * @return 0 (DDR3) or 1 (DDR4)
+ */
+int __bdk_dram_is_ddr4(bdk_node_t node, int lmc)
+{
+ // PROTECT!!!
+ if (__bdk_dram_is_lmc_in_dreset(node, lmc)) // check LMCn
+ return 0;
+ if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX))
+ return 1;
+ BDK_CSR_INIT(lmcx_ddr_pll_ctl, node, BDK_LMCX_DDR_PLL_CTL(lmc)); // sample LMCn
+ return (lmcx_ddr_pll_ctl.cn83xx.ddr4_mode != 0);
+}
+
+/**
+ * Return whether the node has Registered DIMMs or Unbuffered DIMMs
+ *
+ * @param node Node to probe
+ *
+ * @return 0 (Unbuffered) or 1 (Registered)
+ */
+int __bdk_dram_is_rdimm(bdk_node_t node, int lmc)
+{
+ // PROTECT!!!
+ if (__bdk_dram_is_lmc_in_dreset(node, lmc)) // check LMCn
+ return 0;
+ BDK_CSR_INIT(lmcx_control, node, BDK_LMCX_CONTROL(lmc)); // sample LMCn
+ return (lmcx_control.s.rdimm_ena != 0);
+}
+
+/**
+ * Get the amount of DRAM configured for a node. This is read from the LMC
+ * controller after DRAM is setup.
+ *
+ * @param node Node to query
+ *
+ * @return Size in megabytes
+ */
+uint64_t bdk_dram_get_size_mbytes(int node)
+{
+ if (bdk_is_platform(BDK_PLATFORM_EMULATOR))
+ return 2 << 10; /* 2GB is available on t88 and t81
+ ** some t83 models have 8gb, but it is too long to init */
+ /* Return zero if dram isn't enabled */
+ if (!__bdk_is_dram_enabled(node))
+ return 0;
+
+ uint64_t memsize = 0;
+ const int num_dram_controllers = __bdk_dram_get_num_lmc(node);
+ for (int lmc = 0; lmc < num_dram_controllers; lmc++)
+ {
+ if (bdk_is_platform(BDK_PLATFORM_ASIM))
+ {
+ /* Asim doesn't simulate the rank detection, fake 4GB per controller */
+ memsize += 4ull << 30;
+ }
+ else
+ {
+ // PROTECT!!!
+ if (__bdk_dram_is_lmc_in_dreset(node, lmc)) // check LMCn
+ return 0;
+ BDK_CSR_INIT(lmcx_config, node, BDK_LMCX_CONFIG(lmc));
+ int num_ranks = bdk_pop(lmcx_config.s.init_status);
+ uint64_t rank_size = 1ull << (28 + lmcx_config.s.pbank_lsb - lmcx_config.s.rank_ena);
+ memsize += rank_size * num_ranks;
+ }
+ }
+ return memsize >> 20;
+}
+