diff options
Diffstat (limited to 'src/include/device')
-rw-r--r-- | src/include/device/dram/ddr3.h | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/src/include/device/dram/ddr3.h b/src/include/device/dram/ddr3.h index 926f7b9db0..69c072bb08 100644 --- a/src/include/device/dram/ddr3.h +++ b/src/include/device/dram/ddr3.h @@ -186,4 +186,123 @@ static inline u32 volatile_read(volatile u32 addr) return result; } +/** + * \brief Representation of an MRS command + * + * This represents an MRS command as seen by the DIMM. This is not a memory + * address that can be read to generate an MRS command. The mapping of CPU + * to memory pins is hardware-dependent. + * \n + * The idea is to generalize the MRS code, and only need a hardware-specific + * function to map the MRS bits to CPU address bits. An MRS command can be + * sent like: + * @code{.c} + * u32 addr; + * mrs_cmd_t mrs; + * chipset_enable_mrs_command_mode(); + * mrs = ddr3_get_mr2(rtt_wr, srt, asr, cwl) + * if (rank_has_mirrorred_pins) + * mrs = ddr3_mrs_mirror_pins(mrs); + * addr = chipset_specific_get_mrs_addr(mrs); + * volatile_read(addr); + * @endcode + * + * The MRS representation has the following structure: + * - cmd[15:0] = Address pins MA[15:0] + * - cmd[18:16] = Bank address BA[2:0] + */ +typedef u32 mrs_cmd_t; + +enum ddr3_mr0_precharge { + DDR3_MR0_PRECHARGE_SLOW = 0, + DDR3_MR0_PRECHARGE_FAST = 1, +}; +enum ddr3_mr0_mode { + DDR3_MR0_MODE_NORMAL = 0, + DDR3_MR0_MODE_TEST = 1, +}; +enum ddr3_mr0_dll_reset { + DDR3_MR0_DLL_RESET_NO = 0, + DDR3_MR0_DLL_RESET_YES = 1, +}; +enum ddr3_mr0_burst_type { + DDR3_MR0_BURST_TYPE_SEQUENTIAL = 0, + DDR3_MR0_BURST_TYPE_INTERLEAVED = 1, +}; +enum ddr3_mr0_burst_length { + DDR3_MR0_BURST_LENGTH_8 = 0, + DDR3_MR0_BURST_LENGTH_CHOP = 1, + DDR3_MR0_BURST_LENGTH_4 = 2, +}; +mrs_cmd_t ddr3_get_mr0(enum ddr3_mr0_precharge precharge_pd, + u8 write_recovery, + enum ddr3_mr0_dll_reset dll_reset, + enum ddr3_mr0_mode mode, + u8 cas, + enum ddr3_mr0_burst_type interleaved_burst, + enum ddr3_mr0_burst_length burst_length); + +enum ddr3_mr1_qoff { + DDR3_MR1_QOFF_ENABLE = 0, + DDR3_MR1_QOFF_DISABLE = 1, +}; +enum ddr3_mr1_tqds { + DDR3_MR1_TQDS_DISABLE = 0, + DDR3_MR1_TQDS_ENABLE = 1, +}; +enum ddr3_mr1_write_leveling { + DDR3_MR1_WRLVL_DISABLE = 0, + DDR3_MR1_WRLVL_ENABLE = 1, +}; +enum ddr3_mr1_rtt_nom { + DDR3_MR1_RTT_NOM_OFF = 0, + DDR3_MR1_RTT_NOM_RZQ4 = 1, + DDR3_MR1_RTT_NOM_RZQ2 = 2, + DDR3_MR1_RTT_NOM_RZQ6 = 3, + DDR3_MR1_RTT_NOM_RZQ12 = 4, + DDR3_MR1_RTT_NOM_RZQ8 = 5, +}; +enum ddr3_mr1_additive_latency { + DDR3_MR1_AL_DISABLE = 0, + DDR3_MR1_AL_CL_MINUS_1 = 1, + DDR3_MR1_AL_CL_MINUS_2 = 2, +}; +enum ddr3_mr1_ods { + DDR3_MR1_ODS_RZQ6 = 0, + DDR3_MR1_ODS_RZQ7 = 1, +}; +enum ddr3_mr1_dll { + DDR3_MR1_DLL_ENABLE = 0, + DDR3_MR1_DLL_DISABLE = 1, +}; + +mrs_cmd_t ddr3_get_mr1(enum ddr3_mr1_qoff qoff, + enum ddr3_mr1_tqds tqds, + enum ddr3_mr1_rtt_nom rtt_nom, + enum ddr3_mr1_write_leveling write_leveling, + enum ddr3_mr1_ods output_drive_strenght, + enum ddr3_mr1_additive_latency additive_latency, + enum ddr3_mr1_dll dll_disable); + +enum ddr3_mr2_rttwr { + DDR3_MR2_RTTWR_OFF = 0, + DDR3_MR2_RTTWR_RZQ4 = 1, + DDR3_MR2_RTTWR_RZQ2 = 2, +}; +enum ddr3_mr2_srt_range { + DDR3_MR2_SRT_NORMAL = 0, + DDR3_MR2_SRT_EXTENDED = 1, +}; +enum ddr3_mr2_asr { + DDR3_MR2_ASR_MANUAL = 0, + DDR3_MR2_ASR_AUTO = 1, +}; + +mrs_cmd_t ddr3_get_mr2(enum ddr3_mr2_rttwr rtt_wr, + enum ddr3_mr2_srt_range extended_temp, + enum ddr3_mr2_asr self_refresh, u8 cas_cwl); + +mrs_cmd_t ddr3_get_mr3(char dataflow_from_mpr); +mrs_cmd_t ddr3_mrs_mirror_pins(mrs_cmd_t cmd); + #endif /* DEVICE_DRAM_DDR3_H */ |