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 <stdio.h>
41 #include <string.h>
42 #include <libbdk-hal/bdk-config.h>
43 #include <libbdk-hal/bdk-l2c.h>
44
45 BDK_REQUIRE_DEFINE(DRAM_CONFIG);
46
47 /**
48 * Lookup a DRAM configuration by name and initialize DRAM using it
49 *
50 * @param node Node to configure
51 * @param ddr_clock_override
52 * If non zero, override the DRAM frequency specified
53 * in the config with this value
54 *
55 * @return Amount of DRAM in MB, or negative on failure
56 */
bdk_dram_config(int node,int ddr_clock_override)57 int bdk_dram_config(int node, int ddr_clock_override)
58 {
59 const dram_config_t *config = libdram_config_load(node);
60 if (!config)
61 {
62 printf("N%d: No DRAM config specified, skipping DRAM init\n", node);
63 return 0;
64 }
65
66 BDK_TRACE(DRAM, "N%d: Starting DRAM init (config=%p, ddr_clock_override=%d)\n", node, config, ddr_clock_override);
67 int mbytes = libdram_config(node, config, ddr_clock_override);
68 BDK_TRACE(DRAM, "N%d: DRAM init returned %d\n", node, mbytes);
69 if (mbytes <= 0)
70 {
71 printf("ERROR: DDR initialization failed\n");
72 return -1;
73 }
74
75 return mbytes;
76 }
77
78 /**
79 * Do all the DRAM Margin tests
80 *
81 * @param node Node to test
82 *
83 * @return Success or Fail
84 */
bdk_dram_margin(int node)85 void bdk_dram_margin(int node)
86 {
87 BDK_TRACE(DRAM, "N%d: Starting DRAM margining\n", node);
88 libdram_margin(node);
89 BDK_TRACE(DRAM, "N%d: Finished DRAM margining.\n", node);
90 return;
91 }
92
93 /**
94 * Return the string of the DRAM configuration info at the specified node.
95 * If the node is not configured, NULL is returned.
96 *
97 * @param node node to retrieve
98 *
99 * @return string or NULL
100 */
bdk_dram_get_info_string(int node)101 const char* bdk_dram_get_info_string(int node)
102 {
103 #define INFO_STRING_LEN 40
104 static char info_string[INFO_STRING_LEN];
105 static const char *info_ptr = info_string;
106
107 snprintf(info_string, INFO_STRING_LEN,
108 " %ld MB, %ld MT/s, %s %s",
109 bdk_dram_get_size_mbytes(node),
110 libdram_get_freq_from_pll(node, 0) / 1000000,
111 (__bdk_dram_is_ddr4(node, 0)) ? "DDR4" : "DDR3",
112 (__bdk_dram_is_rdimm(node, 0)) ? "RDIMM" : "UDIMM");
113
114 return info_ptr;
115 }
116
117
118 /**
119 * Return the highest address currently used by the BDK. This address will
120 * be about 4MB above the top of the BDK to make sure small growths between the
121 * call and its use don't cause corruption. Any call to memory allocation can
122 * change this value.
123 *
124 * @return Size of the BDK in bytes
125 */
bdk_dram_get_top_of_bdk(void)126 uint64_t bdk_dram_get_top_of_bdk(void)
127 {
128 /* Make sure the start address is higher that the BDK's active range.
129 *
130 * As sbrk() returns a node address, mask off the node portion of
131 * the address to make it a physical offset. Doing this simplifies the
132 * address checks and calculations which only work with physical offsets.
133 */
134 /* FIXME(dhendrix): we only care about node 0 */
135 // uint64_t top_of_bdk = (bdk_ptr_to_phys(sbrk(0)) & bdk_build_mask(40));
136 uint64_t top_of_bdk = 0;
137 uint64_t l2_size = bdk_l2c_get_cache_size_bytes(bdk_numa_master());
138 if (top_of_bdk <= l2_size)
139 {
140 /* Early BDK code takes care of the first L2 sized area of memory */
141 top_of_bdk = l2_size;
142 }
143 else
144 {
145 /* Give 4MB of extra so the BDK has room to grow */
146 top_of_bdk += 4 << 20;
147 /* Align it on a 64KB boundary */
148 top_of_bdk >>= 16;
149 top_of_bdk <<= 16;
150 }
151 return top_of_bdk;
152 }
153