diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/device/dram/ddr3.c | 223 | ||||
-rw-r--r-- | src/include/device/dram/ddr3.h | 130 |
2 files changed, 0 insertions, 353 deletions
diff --git a/src/device/dram/ddr3.c b/src/device/dram/ddr3.c index d28bfbea4d..0a32d02de9 100644 --- a/src/device/dram/ddr3.c +++ b/src/device/dram/ddr3.c @@ -638,226 +638,3 @@ void dram_print_spd_ddr3(const struct dimm_attr_ddr3_st *dimm) printk(BIOS_INFO, " tCMDmin : %3u\n", DIV_ROUND_UP(dimm->tCMD, 256)); } - -/*============================================================================== - *= DDR3 MRS helpers - *----------------------------------------------------------------------------*/ - -/* - * MRS command structure: - * cmd[15:0] = Address pins MA[15:0] - * cmd[18:16] = Bank address BA[2:0] - */ - -/* Map tWR value to a bitmask of the MR0 cycle */ -static u16 ddr3_twr_to_mr0_map(u8 twr) -{ - if ((twr >= 5) && (twr <= 8)) - return (twr - 4) << 9; - - /* - * From 8T onwards, we can only use even values. Round up if we are - * given an odd value. - */ - if ((twr >= 9) && (twr <= 14)) - return ((twr + 1) >> 1) << 9; - - /* tWR == 16T is [000] */ - return 0; -} - -/* Map the CAS latency to a bitmask for the MR0 cycle */ -static u16 ddr3_cas_to_mr0_map(u8 cas) -{ - u16 mask = 0; - /* A[6:4] are bits [2:0] of (CAS - 4) */ - mask = ((cas - 4) & 0x07) << 4; - - /* A2 is the MSB of (CAS - 4) */ - if ((cas - 4) & (1 << 3)) - mask |= (1 << 2); - - return mask; -} - -/** - * \brief Get command address for a DDR3 MR0 command - * - * The DDR3 specification only covers odd write_recovery up to 7T. If an odd - * write_recovery greater than 7 is specified, it will be rounded up. If a tWR - * greater than 8 is specified, it is recommended to explicitly round it up or - * down before calling this function. - * - * write_recovery and cas are given in clock cycles. For example, a CAS of 7T - * should be given as 7. - * - * @param precharge_pd - * @param write_recovery Write recovery latency, tWR in clock cycles. - * @param dll_reset - * @param mode - * @param cas CAS latency in clock cycles. - * @param burst_type - * @param burst_length - */ -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 burst_type, - enum ddr3_mr0_burst_length burst_length) -{ - mrs_cmd_t cmd = 0 << 16; - - if (precharge_pd == DDR3_MR0_PRECHARGE_FAST) - cmd |= (1 << 12); - - cmd |= ddr3_twr_to_mr0_map(write_recovery); - - if (dll_reset == DDR3_MR0_DLL_RESET_YES) - cmd |= (1 << 8); - - if (mode == DDR3_MR0_MODE_TEST) - cmd |= (1 << 7); - - cmd |= ddr3_cas_to_mr0_map(cas); - - if (burst_type == DDR3_MR0_BURST_TYPE_INTERLEAVED) - cmd |= (1 << 3); - - cmd |= (burst_length & 0x03) << 0; - - return cmd; -} - -static u16 ddr3_rtt_nom_to_mr1_map(enum ddr3_mr1_rtt_nom rtt_nom) -{ - u16 mask = 0; - /* A9 <-> rtt_nom[2] */ - if (rtt_nom & (1 << 2)) - mask |= (1 << 9); - /* A6 <-> rtt_nom[1] */ - if (rtt_nom & (1 << 1)) - mask |= (1 << 6); - /* A2 <-> rtt_nom[0] */ - if (rtt_nom & (1 << 0)) - mask |= (1 << 2); - - return mask; -} - -static u16 ddr3_ods_to_mr1_map(enum ddr3_mr1_ods ods) -{ - u16 mask = 0; - /* A5 <-> ods[1] */ - if (ods & (1 << 1)) - mask |= (1 << 5); - /* A1 <-> ods[0] */ - if (ods & (1 << 0)) - mask |= (1 << 1); - - return mask; -} - -/** - * \brief Get command address for a DDR3 MR1 command - */ -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 ods, - enum ddr3_mr1_additive_latency additive_latency, - enum ddr3_mr1_dll dll_disable) -{ - mrs_cmd_t cmd = 1 << 16; - - if (qoff == DDR3_MR1_QOFF_DISABLE) - cmd |= (1 << 12); - - if (tqds == DDR3_MR1_TQDS_ENABLE) - cmd |= (1 << 11); - - cmd |= ddr3_rtt_nom_to_mr1_map(rtt_nom); - - if (write_leveling == DDR3_MR1_WRLVL_ENABLE) - cmd |= (1 << 7); - - cmd |= ddr3_ods_to_mr1_map(ods); - - cmd |= (additive_latency & 0x03) << 3; - - if (dll_disable == DDR3_MR1_DLL_DISABLE) - cmd |= (1 << 0); - - return cmd; -} - -/** - * \brief Get command address for a DDR3 MR2 command - * - * cas_cwl is given in clock cycles. For example, a cas_cwl of 7T should be - * given as 7. - * - * @param rtt_wr - * @param extended_temp - * @param self_refresh - * @param cas_cwl CAS write latency in clock cycles. - */ - -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 cmd = 2 << 16; - - cmd |= (rtt_wr & 0x03) << 9; - - if (extended_temp == DDR3_MR2_SRT_EXTENDED) - cmd |= (1 << 7); - - if (self_refresh == DDR3_MR2_ASR_AUTO) - cmd |= (1 << 6); - - cmd |= ((cas_cwl - 5) & 0x07) << 3; - - return cmd; -} - -/** - * \brief Get command address for a DDR3 MR3 command - * - * @param dataflow_from_mpr Specify a non-zero value to put DRAM in read - * leveling mode. Zero for normal operation. - */ -mrs_cmd_t ddr3_get_mr3(char dataflow_from_mpr) -{ - mrs_cmd_t cmd = 3 << 16; - - if (dataflow_from_mpr) - cmd |= (1 << 2); - - return cmd; -} - -/** - * \brief Mirror the address bits for this MRS command - * - * Swap the following bits in the MRS command: - * - MA3 <-> MA4 - * - MA5 <-> MA6 - * - MA7 <-> MA8 - * - BA0 <-> BA1 - */ -mrs_cmd_t ddr3_mrs_mirror_pins(mrs_cmd_t cmd) -{ - u32 downshift, upshift; - /* High bits= A4 | A6 | A8 | BA1 */ - /* Low bits = A3 | A5 | A7 | BA0 */ - u32 lowbits = (1 << 3) | (1 << 5) | (1 << 7) | (1 << 16); - downshift = (cmd & (lowbits << 1)); - upshift = (cmd & lowbits); - cmd &= ~(lowbits | (lowbits << 1)); - cmd |= (downshift >> 1) | (upshift << 1); - return cmd; -} diff --git a/src/include/device/dram/ddr3.h b/src/include/device/dram/ddr3.h index 17910ff4bd..9ec5248af7 100644 --- a/src/include/device/dram/ddr3.h +++ b/src/include/device/dram/ddr3.h @@ -181,135 +181,5 @@ int spd_xmp_decode_ddr3(struct dimm_attr_ddr3_st *dimm, enum cb_err spd_add_smbios17(const u8 channel, const u8 slot, const u16 selected_freq, const struct dimm_attr_ddr3_st *info); -/** - * \brief Read double word from specified address - * - * Should be useful when doing an MRS to the DIMM - */ -static inline u32 volatile_read(volatile uintptr_t addr) -{ - volatile u32 result; - result = *(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_DDR3L_H */ |