/* * Copyright 2008-2012 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. */ /* * Generic driver for Freescale DDR2/DDR3 memory controller. * Based on code from spd_sdram.c * Author: James Yang [at freescale.com] */ #include #include #include "ddr.h" static uint32_t compute_cas_write_latency(void) { uint32_t cwl; const uint32_t mclk_ps = get_memory_clk_period_ps(); if (mclk_ps >= 2500) cwl = 5; else if (mclk_ps >= 1875) cwl = 6; else if (mclk_ps >= 1500) cwl = 7; else if (mclk_ps >= 1250) cwl = 8; else if (mclk_ps >= 1070) cwl = 9; else if (mclk_ps >= 935) cwl = 10; else if (mclk_ps >= 833) cwl = 11; else if (mclk_ps >= 750) cwl = 12; else cwl = 12; return cwl; } static void set_csn_config(int dimm_number, int i, struct fsl_ddr_cfg_regs_s *ddr, const struct memctl_options_s *popts, const struct dimm_params_s *dimm) { uint32_t cs_n_en = 0, ap_n_en = 0, odt_rd_cfg = 0, odt_wr_cfg = 0, ba_bits_cs_n = 0, row_bits_cs_n = 0, col_bits_cs_n = 0, n_banks_per_sdram_device; int go_config = 0; switch (i) { case 0: if (dimm[dimm_number].n_ranks > 0) go_config = 1; break; case 1: if ((dimm_number == 0 && dimm[0].n_ranks > 1) || (dimm_number == 1 && dimm[1].n_ranks > 0)) go_config = 1; break; case 2: if ((dimm_number == 0 && dimm[0].n_ranks > 2) || (dimm_number >= 1 && dimm[dimm_number].n_ranks > 0)) go_config = 1; break; case 3: if ((dimm_number == 0 && dimm[0].n_ranks > 3) || (dimm_number == 1 && dimm[1].n_ranks > 1) || (dimm_number == 3 && dimm[3].n_ranks > 0)) go_config = 1; break; default: break; } if (go_config) { /* Chip Select enable */ cs_n_en = 1; /* CSn auto-precharge enable */ ap_n_en = popts->cs_local_opts[i].auto_precharge; /* ODT for reads configuration */ odt_rd_cfg = popts->cs_local_opts[i].odt_rd_cfg; /* ODT for writes configuration */ odt_wr_cfg = popts->cs_local_opts[i].odt_wr_cfg; /* Num of bank bits for SDRAM on CSn */ n_banks_per_sdram_device = dimm[dimm_number].n_banks_per_sdram_device; ba_bits_cs_n = __ilog2(n_banks_per_sdram_device) - 2; /* Num of row bits for SDRAM on CSn */ row_bits_cs_n = dimm[dimm_number].n_row_addr - 12; /* Num of ocl bits for SDRAM on CSn */ col_bits_cs_n = dimm[dimm_number].n_col_addr - 8; } ddr->cs[i].config = (((cs_n_en & 0x1) << 31) | ((ap_n_en & 0x1) << 23) | ((odt_rd_cfg & 0x7) << 20) | ((odt_wr_cfg & 0x7) << 16) | ((ba_bits_cs_n & 0x3) << 14) | ((row_bits_cs_n & 0x7) << 8) | ((col_bits_cs_n & 0x7) << 0)); } static void set_timing_cfg_0(struct fsl_ddr_cfg_regs_s *ddr, const struct memctl_options_s *popts, const struct dimm_params_s *dimm) { uint32_t trwt_mclk = 0, twrt_mclk = 0, act_pd_exit_mclk, pre_pd_exit_mclk, taxpd_mclk, tmrd_mclk, txp, data_rate = fsl_get_ddr_freq(0); if (popts->sdram_type == SDRAM_TYPE_DDR2) { act_pd_exit_mclk = popts->txard; pre_pd_exit_mclk = popts->txp; taxpd_mclk = popts->taxpd; tmrd_mclk = popts->tmrd; } else { /* * tXARD is not part of the DDR3 specification, use the * parameter txp instead of it. That is: * txp=max(3nCK, 7.5ns). As well, use tAXPD=1. */ txp = max_t(uint32_t, (get_memory_clk_period_ps() * 3), 7500); data_rate = fsl_get_ddr_freq(0); tmrd_mclk = 4; /* for faster clock, need more time for data setup */ if (popts->trwt_override) trwt_mclk = popts->trwt; else if (data_rate / 1000000 > 1800) trwt_mclk = 2; else trwt_mclk = 0; if (data_rate / 1000000 > 1150) twrt_mclk = 1; else twrt_mclk = 0; taxpd_mclk = 1; if (popts->dynamic_power == 0) { act_pd_exit_mclk = 1; pre_pd_exit_mclk = 1; } else { /* act_pd_exit_mclk = tXARD, see above */ act_pd_exit_mclk = picos_to_mclk(txp); /* Mode register MR0[A12] is '1' - fast exit */ pre_pd_exit_mclk = act_pd_exit_mclk; } } ddr->timing_cfg_0 = (((trwt_mclk & 0x3) << 30) | ((twrt_mclk & 0x3) << 28) | ((act_pd_exit_mclk & 0xf) << 20) | ((pre_pd_exit_mclk & 0xf) << 16) | ((taxpd_mclk & 0xf) << 8) | ((tmrd_mclk & 0x1f) << 0) ); } static void set_timing_cfg_3(struct fsl_ddr_cfg_regs_s *ddr, const struct memctl_options_s *popts, const struct common_timing_params_s *dimm, uint32_t cas_latency, uint32_t additive_latency) { uint32_t ext_pretoact, ext_acttopre, ext_acttorw, ext_refrec, ext_wrrec; ext_pretoact = picos_to_mclk(dimm->tRP_ps) >> 4; ext_acttopre = picos_to_mclk(dimm->tRAS_ps) >> 4; ext_acttorw = picos_to_mclk(dimm->tRCD_ps) >> 4; cas_latency = ((cas_latency << 1) - 1) >> 4; additive_latency = additive_latency >> 4; ext_refrec = (picos_to_mclk(dimm->tRFC_ps) - 8) >> 4; /* ext_wrrec only deals with 16 clock and above, or 14 with OTF */ ext_wrrec = (picos_to_mclk(dimm->tWR_ps) + (popts->otf_burst_chop_en ? 2 : 0)) >> 4; ddr->timing_cfg_3 = (((ext_pretoact & 0x1) << 28) | ((ext_acttopre & 0x3) << 24) | ((ext_acttorw & 0x1) << 22) | ((ext_refrec & 0x1F) << 16) | ((cas_latency & 0x3) << 12) | ((additive_latency & 0x1) << 10) | ((ext_wrrec & 0x1) << 8) ); } static void set_timing_cfg_1(struct fsl_ddr_cfg_regs_s *ddr, const struct memctl_options_s *popts, const struct common_timing_params_s *dimm, uint32_t cas_latency) { uint32_t pretoact_mclk, acttopre_mclk, acttorw_mclk, refrec_ctrl, wrrec_mclk, acttoact_mclk, wrtord_mclk; /* DDR_SDRAM_MODE doesn't support 9,11,13,15 */ static const u8 wrrec_table[] = { 1, 2, 3, 4, 5, 6, 7, 8, 10, 10, 12, 12, 14, 14, 0, 0 }; pretoact_mclk = picos_to_mclk(dimm->tRP_ps); acttopre_mclk = picos_to_mclk(dimm->tRAS_ps); acttorw_mclk = picos_to_mclk(dimm->tRCD_ps); /* * Translate CAS Latency to a DDR controller field value: * * CAS Lat DDR II Ctrl * Clocks SPD Bit Value * ------- ------- ------ * 1.0 0001 * 1.5 0010 * 2.0 2 0011 * 2.5 0100 * 3.0 3 0101 * 3.5 0110 * 4.0 4 0111 * 4.5 1000 * 5.0 5 1001 */ cas_latency = (cas_latency << 1) - 1; refrec_ctrl = picos_to_mclk(dimm->tRFC_ps) - 8; acttoact_mclk = picos_to_mclk(dimm->tRRD_ps); wrrec_mclk = picos_to_mclk(dimm->tWR_ps); if (wrrec_mclk <= 16) wrrec_mclk = wrrec_table[wrrec_mclk - 1]; if (popts->otf_burst_chop_en) wrrec_mclk += 2; wrtord_mclk = picos_to_mclk(dimm->tWTR_ps); if (popts->sdram_type == SDRAM_TYPE_DDR2) { wrtord_mclk = max_t(uint32_t, wrtord_mclk, 2); } else { wrtord_mclk = max_t(uint32_t, wrtord_mclk, 4); acttoact_mclk = max_t(uint32_t, acttoact_mclk, 4); } if (popts->otf_burst_chop_en) wrtord_mclk += 2; ddr->timing_cfg_1 = (((pretoact_mclk & 0x0F) << 28) | ((acttopre_mclk & 0x0F) << 24) | ((acttorw_mclk & 0xF) << 20) | ((cas_latency & 0xF) << 16) | ((refrec_ctrl & 0xF) << 12) | ((wrrec_mclk & 0x0F) << 8) | ((acttoact_mclk & 0x0F) << 4) | ((wrtord_mclk & 0x0F) << 0)); } static void set_timing_cfg_2(struct fsl_ddr_cfg_regs_s *ddr, const struct memctl_options_s *popts, const struct common_timing_params_s *dimm, uint32_t cas_latency, uint32_t additive_latency) { uint32_t cpo, rd_to_pre, wr_data_delay, cke_pls, four_act; cpo = popts->cpo_override; rd_to_pre = picos_to_mclk(dimm->tRTP_ps); if (popts->sdram_type == SDRAM_TYPE_DDR2) { cas_latency = cas_latency - 1; rd_to_pre = max_t(uint32_t, rd_to_pre, 2); } else { cas_latency = compute_cas_write_latency(); rd_to_pre = max_t(uint32_t, rd_to_pre, 4); } if (popts->otf_burst_chop_en) rd_to_pre += 2; wr_data_delay = popts->write_data_delay; cke_pls = picos_to_mclk(popts->tCKE_clock_pulse_width_ps); four_act = picos_to_mclk(popts->tFAW_window_four_activates_ps); ddr->timing_cfg_2 = (((additive_latency & 0xf) << 28) | ((cpo & 0x1f) << 23) | ((cas_latency & 0xf) << 19) | ((rd_to_pre & 7) << 13) | ((wr_data_delay & 7) << 10) | ((cke_pls & 0x7) << 6) | ((four_act & 0x3f) << 0)); } static void set_ddr_sdram_cfg(struct fsl_ddr_cfg_regs_s *ddr, const struct memctl_options_s *popts, const struct common_timing_params_s *dimm) { uint32_t mem_en, sren, ecc_en, sdram_type, dyn_pwr, dbw, twoT_en, hse, threet_en, eight_be = 0; mem_en = 1; sren = popts->self_refresh_in_sleep; if (dimm->all_DIMMs_ECC_capable) ecc_en = popts->ECC_mode; else ecc_en = 0; sdram_type = popts->sdram_type; twoT_en = popts->twoT_en; dyn_pwr = popts->dynamic_power; dbw = popts->data_bus_width; hse = popts->half_strength_driver_enable; threet_en = popts->threet_en; if (sdram_type == SDRAM_TYPE_DDR3) if ((popts->burst_length == DDR_BL8) || (dbw == 1)) eight_be = 1; ddr->ddr_sdram_cfg = (((mem_en & 0x1) << 31) | ((sren & 0x1) << 30) | ((ecc_en & 0x1) << 29) | ((sdram_type & 0x7) << 24) | ((dyn_pwr & 0x1) << 21) | ((dbw & 0x3) << 19) | ((eight_be & 0x1) << 18) | ((threet_en & 0x1) << 16) | ((twoT_en & 0x1) << 15) | ((hse & 0x1) << 3)); } static void set_ddr_sdram_cfg_2(struct fsl_ddr_cfg_regs_s *ddr, const struct memctl_options_s *popts) { struct ddr_board_info_s *bi = popts->board_info; uint32_t i, dll_rst_dis, dqs_cfg, odt_cfg = 0, num_pr, d_init = 0, obc_cfg = 0, x4_en, md_en = 0, rcw_en = 0; dll_rst_dis = popts->dll_rst_dis; dqs_cfg = popts->DQS_config; /* * Check for On-Die Termination options and * assert ODT only during reads to DRAM. */ for (i = 0; i < bi->cs_per_ctrl; i++) if (popts->cs_local_opts[i].odt_rd_cfg || popts->cs_local_opts[i].odt_wr_cfg) { odt_cfg = SDRAM_CFG2_ODT_ONLY_READ; break; } /* Default number of posted refresh */ num_pr = 1; if (popts->ECC_init_using_memctl) { d_init = 1; ddr->ddr_data_init = popts->data_init; } if (popts->sdram_type == SDRAM_TYPE_DDR3) { obc_cfg = popts->otf_burst_chop_en; md_en = popts->mirrored_dimm; } x4_en = popts->x4_en ? 1 : 0; ddr->ddr_sdram_cfg_2 = (((dll_rst_dis & 0x1) << 29) | ((dqs_cfg & 0x3) << 26) | ((odt_cfg & 0x3) << 21) | ((num_pr & 0xf) << 12) | (x4_en << 10) | ((obc_cfg & 0x1) << 6) | ((d_init & 0x1) << 4) | ((rcw_en & 0x1) << 2) | ((md_en & 0x1) << 0) ); } static void set_ddr_sdram_mode_2(struct fsl_ddr_cfg_regs_s *ddr, const struct memctl_options_s *popts, const struct common_timing_params_s *dimm) { uint16_t esdmode2; uint32_t rtt_wr, srt = 0, cwl; cwl = compute_cas_write_latency() - 5; if (popts->rtt_override) rtt_wr = popts->rtt_wr_override_value; else rtt_wr = popts->cs_local_opts[0].odt_rtt_wr; if (dimm->extended_op_srt) srt = dimm->extended_op_srt; esdmode2 = (((rtt_wr & 0x3) << 9) | ((srt & 0x1) << 7) | ((cwl & 0x7) << 3) ); ddr->ddr_sdram_mode_2 = (esdmode2 & 0xffff) << 16; } static void set_ddr_sdram_interval(struct fsl_ddr_cfg_regs_s *ddr, const struct memctl_options_s *popts, const struct common_timing_params_s *dimm) { uint32_t refint, bstopre; refint = picos_to_mclk(dimm->refresh_rate_ps); /* Precharge interval */ bstopre = popts->bstopre; ddr->ddr_sdram_interval = (((refint & 0xFFFF) << 16) | ((bstopre & 0x3FFF) << 0)); } void set_ddr3_sdram_mode(struct fsl_ddr_cfg_regs_s *ddr, const struct memctl_options_s *popts, const struct common_timing_params_s *dimm, uint32_t cas_latency, uint32_t additive_latency) { uint16_t esdmode, sdmode; /* Mode Register - MR1 */ uint32_t rtt, al; /* Mode Register - MR0 */ uint32_t dll_on, wr = 0, dll_rst, mode, caslat = 4, bt, bl, wr_mclk; /* * DDR_SDRAM_MODE doesn't support 9,11,13,15 * Please refer JEDEC Standard No. 79-3E for Mode Register MR0 * for this table */ static const u8 wr_table[] = {1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0}; uint8_t cas_latency_table[] = { /* From 5 to 16 clocks */ 0x2, 0x4, 0x6, 0x8, 0xa, 0xc, 0xe, 0x1, 0x3, 0x5, 0x7, 0x9, }; const unsigned int mclk_ps = get_memory_clk_period_ps(); if (popts->rtt_override) rtt = popts->rtt_override_value; else rtt = popts->cs_local_opts[0].odt_rtt_norm; if (additive_latency == (cas_latency - 1)) al = 1; else if (additive_latency == (cas_latency - 2)) al = 2; else al = 0; /* * The esdmode value will also be used for writing * MR1 during write leveling for DDR3, although the * bits specifically related to the write leveling * scheme will be handled automatically by the DDR * controller. So wrlvl_en is set to 0 here. */ esdmode = (((rtt & 0x4) << 7) | ((rtt & 0x2) << 5) | ((al & 0x3) << 3) | ((rtt & 0x1) << 2) ); /* * DLL control for precharge PD * 0=slow exit DLL off (tXPDLL) * 1=fast exit DLL on (tXP) */ dll_on = 1; wr_mclk = (dimm->tWR_ps + mclk_ps - 1) / mclk_ps; if (wr_mclk <= 16) wr = wr_table[wr_mclk - 5]; dll_rst = 0; /* dll no reset */ mode = 0; /* normal mode */ /* look up table to get the cas latency bits */ if (cas_latency >= 5 && cas_latency <= 16) caslat = cas_latency_table[cas_latency - 5]; /* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */ bt = 0; switch (popts->burst_length) { case DDR_BL8: bl = 0; break; case DDR_OTF: bl = 1; break; case DDR_BC4: bl = 2; break; default: bl = 1; break; } sdmode = (((dll_on & 0x1) << 12) | ((wr & 0x7) << 9) | ((dll_rst & 0x1) << 8) | ((mode & 0x1) << 7) | (((caslat >> 1) & 0x7) << 4) | ((bt & 0x1) << 3) | ((caslat & 1) << 2) | ((bl & 0x3) << 0) ); ddr->ddr_sdram_mode = (((esdmode & 0xffff) << 16) | ((sdmode & 0xffff) << 0) ); } void set_ddr2_sdram_mode(struct fsl_ddr_cfg_regs_s *ddr, const struct memctl_options_s *popts, const struct common_timing_params_s *dimm, uint32_t cas_latency, uint32_t additive_latency) { uint16_t esdmode, sdmode; uint32_t dqs_en, rtt, al, wr, bl; const uint32_t mclk_ps = get_memory_clk_period_ps(); /* DQS# Enable: 0=enable, 1=disable */ dqs_en = !popts->DQS_config; /* Posted CAS# additive latency (AL) */ al = additive_latency; /* Internal Termination Resistor */ if (popts->rtt_override) rtt = popts->rtt_override_value; else rtt = popts->cs_local_opts[0].odt_rtt_norm; /* * Extended SDRAM mode. * The variable also selects: * - OCD set to exit mode * - all outputs bit i.e DQ, DQS, RDQS output enabled * - RDQS ball disabled * - DQS ball enabled * - DLL enabled * - Output drive strength: full strength. */ esdmode = (((dqs_en & 0x1) << 10) | ((rtt & 0x2) << 5) | ((al & 0x7) << 3) | ((rtt & 0x1) << 2)); /* Write recovery */ wr = ((dimm->tWR_ps + mclk_ps - 1) / mclk_ps) - 1; switch (popts->burst_length) { case DDR_BL4: bl = 2; break; case DDR_BL8: bl = 3; break; default: bl = 2; break; } /* SDRAM mode * The variable also selects: * - power down mode: fast exit (normal) * - DLL reset disabled. * - burst type: sequential */ sdmode = (((wr & 0x7) << 9) | ((cas_latency & 0x7) << 4) | ((bl & 0x7) << 0)); ddr->ddr_sdram_mode = (((esdmode & 0xFFFF) << 16) | ((sdmode & 0xFFFF) << 0)); } void set_ddrx_sdram_mode(struct fsl_ddr_cfg_regs_s *ddr, const struct memctl_options_s *popts, const struct common_timing_params_s *dimm, uint32_t cas_latency, uint32_t additive_latency) { if (popts->sdram_type == SDRAM_TYPE_DDR2) set_ddr2_sdram_mode(ddr, popts, dimm, cas_latency, additive_latency); else set_ddr3_sdram_mode(ddr, popts, dimm, cas_latency, additive_latency); } uint32_t check_fsl_memctl_config_regs(const struct fsl_ddr_cfg_regs_s *ddr) { /* * DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN should not * be set at the same time. */ if ((ddr->ddr_sdram_cfg & 0x10000000) && (ddr->ddr_sdram_cfg & 0x00008000)) return 1; return 0; } static void set_timing_cfg_4(struct fsl_ddr_cfg_regs_s *ddr, const struct memctl_options_s *popts) { uint32_t rrt = 0, wwt = 0, dll_lock = 1; if (popts->burst_length != DDR_BL8) rrt = wwt = 2; ddr->timing_cfg_4 = (((rrt & 0xf) << 20) | ((wwt & 0xf) << 16) | (dll_lock & 0x3) ); } static void set_timing_cfg_5(struct fsl_ddr_cfg_regs_s *ddr, const struct memctl_options_s *popts, uint32_t cas_latency) { uint32_t rodt_on, rodt_off = 4, wodt_on = 1, wodt_off = 4; /* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */ rodt_on = cas_latency - ((ddr->timing_cfg_2 & 0x00780000) >> 19) + 1; ddr->timing_cfg_5 = (((rodt_on & 0x1f) << 24) | ((rodt_off & 0x7) << 20) | ((wodt_on & 0x1f) << 12) | ((wodt_off & 0x7) << 8) ); } static void set_ddr_zq_cntl(struct fsl_ddr_cfg_regs_s *ddr, uint32_t zq_en) { uint32_t zqinit = 0, zqoper = 0, zqcs = 0; if (zq_en) { zqinit = 9; zqoper = 8; zqcs = 6; } ddr->ddr_zq_cntl = (((zq_en & 0x1) << 31) | ((zqinit & 0xf) << 24) | ((zqoper & 0xf) << 16) | ((zqcs & 0xf) << 8) ); } static void set_ddr_wrlvl_cntl(struct fsl_ddr_cfg_regs_s *ddr, uint32_t wrlvl_en, const struct memctl_options_s *popts) { uint32_t wrlvl_mrd = 0, wrlvl_odten = 0, wrlvl_dqsen = 0, wrlvl_wlr = 0, wrlvl_start = 0, wrlvl_smpl = 0; /* Enable write leveling for DDR3 due to fly-by topology */ if (wrlvl_en) { wrlvl_mrd = 0x6; wrlvl_odten = 0x7; wrlvl_dqsen = 0x5; /* * Write leveling sample time at least need 6 clocks * higher than tWLO to allow enough time for progagation * delay and sampling the prime data bits. */ wrlvl_smpl = 0xf; /* * Write leveling repetition time. At least tWLO + 6 clocks * Set it to 64 */ wrlvl_wlr = 0x6; /* * Write leveling start time * The value use for the DQS_ADJUST for the first sample * when write leveling is enabled. It probably needs to be * overriden per platform. */ wrlvl_start = 0x8; if (popts->wrlvl_override) { wrlvl_smpl = popts->wrlvl_sample; wrlvl_start = popts->wrlvl_start; } } ddr->ddr_wrlvl_cntl = (((wrlvl_en & 0x1) << 31) | ((wrlvl_mrd & 0x7) << 24) | ((wrlvl_odten & 0x7) << 20) | ((wrlvl_dqsen & 0x7) << 16) | ((wrlvl_smpl & 0xf) << 12) | ((wrlvl_wlr & 0x7) << 8) | ((wrlvl_start & 0x1f) << 0) ); } uint32_t compute_fsl_memctl_config_regs(const struct memctl_options_s *popts, struct fsl_ddr_cfg_regs_s *ddr, const struct common_timing_params_s *dimm, const struct dimm_params_s *dimmp, uint32_t dbw_cap_adj) { struct ddr_board_info_s *binfo = popts->board_info; uint32_t cas_latency, additive_latency, i, cs_per_dimm, dimm_number, zq_en, wrlvl_en, sr_it = 0; uint64_t ea, sa, rank_density; if (dimm == NULL) return 1; memset(ddr, 0, sizeof(struct fsl_ddr_cfg_regs_s)); /* Process overrides first. */ if (popts->cas_latency_override) cas_latency = popts->cas_latency_override_value; else cas_latency = dimm->lowest_common_SPD_caslat; if (popts->additive_latency_override) additive_latency = popts->additive_latency_override_value; else additive_latency = dimm->additive_latency; if (popts->auto_self_refresh_en) sr_it = popts->sr_it; /* Chip Select Memory Bounds (CSn_BNDS) */ for (i = 0; i < binfo->cs_per_ctrl; i++) { cs_per_dimm = binfo->cs_per_ctrl / binfo->dimm_slots_per_ctrl; dimm_number = i / cs_per_dimm; rank_density = dimmp[dimm_number].rank_density >> dbw_cap_adj; if (dimmp[dimm_number].n_ranks == 0) continue; sa = dimmp[dimm_number].base_address; ea = sa + rank_density - 1; if (dimmp[dimm_number].n_ranks > (i % cs_per_dimm)) { sa += (i % cs_per_dimm) * rank_density; ea += (i % cs_per_dimm) * rank_density; } else { sa = 0; ea = 0; } sa >>= 24; ea >>= 24; ddr->cs[i].bnds = (((sa & 0xffff) << 16) | ((ea & 0xffff) << 0)); set_csn_config(dimm_number, i, ddr, popts, dimmp); } set_timing_cfg_0(ddr, popts, dimmp); set_timing_cfg_3(ddr, popts, dimm, cas_latency, additive_latency); set_timing_cfg_1(ddr, popts, dimm, cas_latency); set_timing_cfg_2(ddr, popts, dimm, cas_latency, additive_latency); ddr->ddr_cdr1 = popts->ddr_cdr1; ddr->ddr_cdr1 = popts->ddr_cdr2; set_ddr_sdram_cfg(ddr, popts, dimm); set_ddr_sdram_cfg_2(ddr, popts); set_ddrx_sdram_mode(ddr, popts, dimm, cas_latency, additive_latency); if (popts->sdram_type == SDRAM_TYPE_DDR3) { set_ddr_sdram_mode_2(ddr, popts, dimm); set_timing_cfg_4(ddr, popts); set_timing_cfg_5(ddr, popts, cas_latency); zq_en = (popts->zq_en) ? 1 : 0; set_ddr_zq_cntl(ddr, zq_en); wrlvl_en = (popts->wrlvl_en) ? 1 : 0; set_ddr_wrlvl_cntl(ddr, wrlvl_en, popts); } set_ddr_sdram_interval(ddr, popts, dimm); ddr->ddr_data_init = popts->data_init; ddr->ddr_sdram_clk_cntl = (popts->clk_adjust & 0xF) << 23; ddr->ddr_sr_cntr = (sr_it & 0xf) << 16; return check_fsl_memctl_config_regs(ddr); }