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