/***********************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**************************************/ #ifndef __LIBDRAM_CONFIG_H__ #define __LIBDRAM_CONFIG_H__ #include #define DDR_CFG_T_MAX_DIMMS 2 /* ThunderX supports a max of two DIMMs per LMC */ /* Structure that provides DIMM information, either in the form of an SPD TWSI address, or a pointer to an array that contains SPD data. One of the two fields must be valid. Note that these fields historically were dimension 2, left over from CN38XX/CN58XX. These chips supported a 128 bit wide LMC, requiring two DIMMs. All other chips use a 64bit wide LMC with multiple LMCs. All Thunder chips use one DIMM for 64bits, so we no longer use an index */ typedef struct { uint16_t spd_addr; /* TWSI address of SPD, 0 if not used */ const uint8_t *spd_ptr; /* pointer to SPD data array, NULL if not used */ } dimm_config_t; typedef struct { uint8_t odt_ena; /* FIX: dqx_ctl for Octeon 3 DDR4 */ uint64_t odt_mask; /* FIX: wodt_mask for Octeon 3 */ bdk_lmcx_modereg_params1_t odt_mask1; bdk_lmcx_modereg_params2_t odt_mask2; /* FIX: needed for DDR4 */ uint8_t qs_dic; /* FIX: rodt_ctl for Octeon 3 */ uint64_t rodt_ctl; /* FIX: rodt_mask for Octeon 3 */ } dimm_odt_config_t; /* The parameters below make up the custom_lmc_config data structure. This structure is used to customize the way that the LMC DRAM Controller is configured for a particular board design. The HRM describes LMC Read Leveling which supports automatic selection of per byte-lane delays. When measuring the read delays the LMC configuration software sweeps through a range of settings for LMC0_COMP_CTL2[RODT_CTL], the Octeon II on-die-termination resistance and LMC0_MODEREG_PARAMS1[RTT_NOM_XX], the DRAM on-die-termination resistance. The minimum and maximum parameters for rtt_nom_idx and rodt_ctl listed below determine the ranges of ODT settings used for the measurements. Note that for rtt_nom an index is used into a sorted table rather than the direct csr setting in order to optimize the sweep. .min_rtt_nom_idx: 1=120ohms, 2=60ohms, 3=40ohms, 4=30ohms, 5=20ohms .max_rtt_nom_idx: 1=120ohms, 2=60ohms, 3=40ohms, 4=30ohms, 5=20ohms .min_rodt_ctl: 1=20ohms, 2=30ohms, 3=40ohms, 4=60ohms, 5=120ohms .max_rodt_ctl: 1=20ohms, 2=30ohms, 3=40ohms, 4=60ohms, 5=120ohms The settings below control the Octeon II drive strength for the CK, ADD/CMD, and DQ/DQS signals. 1=24ohms, 2=26.67ohms, 3=30ohms, 4=34.3ohms, 5=40ohms, 6=48ohms, 6=60ohms. .dqx_ctl: Drive strength control for DDR_DQX/DDR_DQS_X_P/N drivers. .ck_ctl: Drive strength control for DDR_CK_X_P/DDR_DIMMX_CSX_L/DDR_DIMMX_ODT_X drivers. .cmd_ctl: Drive strength control for CMD/A/RESET_L/CKEX drivers. The LMC controller software selects the most optimal CAS Latency that complies with the appropriate SPD values and the frequency that the DRAMS are being operated. When operating the DRAMs at frequencies substantially lower than their rated frequencies it might be necessary to limit the minimum CAS Latency the LMC controller software is allowed to select in order to make the DRAM work reliably. .min_cas_latency: Minimum allowed CAS Latency The value used for LMC0_RLEVEL_CTL[OFFSET_EN] determine how the read-leveling information that the Octeon II gathers is interpreted to determine the per-byte read delays. .offset_en: Value used for LMC0_RLEVEL_CTL[OFFSET_EN]. .offset_udimm: Value used for LMC0_RLEVEL_CTL[OFFSET] for UDIMMS. .offset_rdimm: Value used for LMC0_RLEVEL_CTL[OFFSET] for RDIMMS. The LMC configuration software sweeps through a range of ODT settings while measuring the per-byte read delays. During those measurements the software makes an assessment of the quality of the measurements in order to determine which measurements provide the most accurate delays. The automatic settings provide the option to allow that same assessment to determine the most optimal RODT_CTL and/or RTT_NOM settings. The automatic approach might provide the best means to determine the settings used for initial poweron of a new design. However, the final settings should be determined by board analysis, testing, and experience. .ddr_rtt_nom_auto: 1 means automatically set RTT_NOM value. .ddr_rodt_ctl_auto: 1 means automatically set RODT_CTL value. .rlevel_compute: Enables software interpretation of per-byte read delays using the measurements collected by the Octeon II rather than completely relying on the Octeon II to determine the delays. 1=software computation is recommended since a more complete analysis is implemented in software. .rlevel_comp_offset: Set to 2 unless instructed differently by Cavium. .rlevel_average_loops: Determines the number of times the read-leveling sequence is run for each rank. The results is then averaged across the number of loops. The default setting is 1. .ddr2t_udimm: .ddr2t_rdimm: Turn on the DDR 2T mode. 2-cycle window for CMD and address. This mode helps relieve setup time pressure on the address and command bus. Please refer to Micron's tech note tn_47_01 titled DDR2-533 Memory Design Guide for Two Dimm Unbuffered Systems for physical details. .disable_sequential_delay_check: As result of the flyby topology prescribed in the JEDEC specifications the byte delays should maintain a consistent increasing or decreasing trend across the bytes on standard dimms. This setting can be used disable that check for unusual circumstances where the check is not useful. .maximum_adjacent_rlevel_delay_increment: An additional sequential delay check for the delays that result from the flyby topology. This value specifies the maximum difference between the delays of adjacent bytes. A value of 0 disables this check. .fprch2 Front Porch Enable: When set, the turn-off time for the default DDR_DQ/DQS drivers is FPRCH2 CKs earlier. 00 = 0 CKs 01 = 1 CKs 10 = 2 CKs .parity: The parity input signal PAR_IN on each dimm must be strapped high or low on the board. This bit is programmed into LMC0_DIMM_CTL[PARITY] and it must be set to match the board strapping. This signal is typically strapped low. .mode32b: Enable 32-bit datapath mode. Set to 1 if only 32 DQ pins are used. (cn61xx, cn71xx) .dll_write_offset: FIXME: Add description .dll_read_offset: FIXME: Add description */ typedef struct { const char *part; int speed; uint64_t rlevel_rank[4][4]; } rlevel_table_t; typedef struct { uint8_t min_rtt_nom_idx; uint8_t max_rtt_nom_idx; uint8_t min_rodt_ctl; uint8_t max_rodt_ctl; //uint8_t dqx_ctl; uint8_t ck_ctl; uint8_t cmd_ctl; uint8_t ctl_ctl; uint8_t min_cas_latency; uint8_t offset_en; uint8_t offset_udimm; uint8_t offset_rdimm; uint8_t rlevel_compute; uint8_t ddr_rtt_nom_auto; uint8_t ddr_rodt_ctl_auto; uint8_t rlevel_comp_offset_udimm; uint8_t rlevel_comp_offset_rdimm; uint8_t rlevel_average_loops; uint8_t ddr2t_udimm; uint8_t ddr2t_rdimm; uint8_t disable_sequential_delay_check; uint8_t maximum_adjacent_rlevel_delay_increment; uint8_t parity; uint8_t fprch2; uint8_t mode32b; uint8_t measured_vref; const int8_t *dll_write_offset; /* Indexed by byte number (0-8, includes ecc byte) */ const int8_t *dll_read_offset; /* Indexed by byte number (0-8, includes ecc byte) */ const rlevel_table_t *rlevel_table; /* Only used if ENABLE_CUSTOM_RLEVEL_TABLE. List of DIMMs to check */ } ddr3_custom_config_t; typedef struct { dimm_config_t dimm_config_table[DDR_CFG_T_MAX_DIMMS]; /* Indexed by DIMM */ dimm_odt_config_t odt_1rank_config[DDR_CFG_T_MAX_DIMMS]; /* Indexed by number of DIMMs minus 1 */ dimm_odt_config_t odt_2rank_config[DDR_CFG_T_MAX_DIMMS]; /* Indexed by number of DIMMs minus 1 */ dimm_odt_config_t odt_4rank_config[DDR_CFG_T_MAX_DIMMS]; /* Indexed by number of DIMMs minus 1 */ ddr3_custom_config_t custom_lmc_config; } ddr_configuration_t; typedef struct { const char *name; ddr_configuration_t config[4]; /* Indexed by LMC */ int ddr_clock_hertz; } dram_config_t; extern int libdram_config(int node, const dram_config_t *dram_config, int ddr_clock_override); extern int libdram_tune(int node); //extern int libdram_margin_write_voltage(int node); //extern int libdram_margin_read_voltage(int node); //extern int libdram_margin_read_timing(int node); //extern int libdram_margin_write_timing(int node); extern int libdram_margin(int node); extern uint32_t libdram_get_freq(int node); extern uint32_t libdram_get_freq_from_pll(int node, int lmc); /** * Load a DRAM configuration based on the current bdk-config settings * * @param node Node the DRAM config is for * * @return Pointer to __libdram_global_cfg, a global structure. Returns NULL if bdk-config * lacks information about DRAM. */ extern const dram_config_t* libdram_config_load(bdk_node_t node); /* The various DRAM configs in the libdram/configs directory need space to store the DRAM config. Since only one config is ever in active use at a time, store the configs in __libdram_global_cfg. In a multi-node setup, independent calls to get the DRAM config will load first node 0's config, then node 1's */ extern dram_config_t __libdram_global_cfg; #endif /* __LIBDRAM_CONFIG_H__ */