1 /* 2 * Copyright 2008 Freescale Semiconductor, Inc. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * Version 2 as published by the Free Software Foundation. 7 */ 8 9 #include <common.h> 10 11 #include <asm/fsl_ddr_sdram.h> 12 #include <asm/fsl_ddr_dimm_params.h> 13 14 typedef struct { 15 u32 datarate_mhz_low; 16 u32 datarate_mhz_high; 17 u32 n_ranks; 18 u32 clk_adjust; 19 u32 cpo; 20 u32 write_data_delay; 21 } board_specific_parameters_t; 22 23 /* XXX: these values need to be checked for all interleaving modes. */ 24 const board_specific_parameters_t board_specific_parameters[2][16] = { 25 { 26 /* memory controller 0 */ 27 /* lo| hi| num| clk| cpo|wrdata */ 28 /* mhz| mhz|ranks|adjst| | delay */ 29 { 0, 333, 4, 7, 7, 3}, 30 {334, 400, 4, 7, 9, 3}, 31 {401, 549, 4, 7, 9, 3}, 32 {550, 650, 4, 7, 10, 4}, 33 34 { 0, 333, 3, 7, 7, 3}, 35 {334, 400, 3, 7, 9, 3}, 36 {401, 549, 3, 7, 9, 3}, 37 {550, 650, 3, 7, 10, 4}, 38 39 { 0, 333, 2, 7, 7, 3}, 40 {334, 400, 2, 7, 9, 3}, 41 {401, 549, 2, 7, 9, 3}, 42 {550, 650, 2, 7, 10, 4}, 43 44 { 0, 333, 1, 7, 7, 3}, 45 {334, 400, 1, 7, 9, 3}, 46 {401, 549, 1, 7, 9, 3}, 47 {550, 650, 1, 7, 10, 4} 48 }, 49 50 { 51 /* memory controller 1 */ 52 /* lo| hi| num| clk| cpo|wrdata */ 53 /* mhz| mhz|ranks|adjst| | delay */ 54 { 0, 333, 4, 7, 7, 3}, 55 {334, 400, 4, 7, 9, 3}, 56 {401, 549, 4, 7, 9, 3}, 57 {550, 650, 4, 7, 10, 4}, 58 59 { 0, 333, 3, 7, 7, 3}, 60 {334, 400, 3, 7, 9, 3}, 61 {401, 549, 3, 7, 9, 3}, 62 {550, 650, 3, 7, 10, 4}, 63 64 { 0, 333, 2, 7, 7, 3}, 65 {334, 400, 2, 7, 9, 3}, 66 {401, 549, 2, 7, 9, 3}, 67 {550, 650, 2, 7, 10, 4}, 68 69 { 0, 333, 1, 7, 7, 3}, 70 {334, 400, 1, 7, 9, 3}, 71 {401, 549, 1, 7, 9, 3}, 72 {550, 650, 1, 7, 10, 4} 73 } 74 }; 75 76 void fsl_ddr_board_options(memctl_options_t *popts, 77 dimm_params_t *pdimm, 78 unsigned int ctrl_num) 79 { 80 const board_specific_parameters_t *pbsp = 81 &(board_specific_parameters[ctrl_num][0]); 82 u32 num_params = sizeof(board_specific_parameters[ctrl_num]) / 83 sizeof(board_specific_parameters[0][0]); 84 u32 i; 85 u32 j; 86 ulong ddr_freq; 87 88 /* set odt_rd_cfg and odt_wr_cfg. If the there is only one dimm in 89 * that controller, set odt_wr_cfg to 4 for CS0, and 0 to CS1. If 90 * there are two dimms in the controller, set odt_rd_cfg to 3 and 91 * odt_wr_cfg to 3 for the even CS, 0 for the odd CS. 92 */ 93 for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { 94 if (i&1) { /* odd CS */ 95 popts->cs_local_opts[i].odt_rd_cfg = 0; 96 popts->cs_local_opts[i].odt_wr_cfg = 0; 97 } else { /* even CS */ 98 if ((CONFIG_DIMM_SLOTS_PER_CTLR == 2) && 99 (pdimm[i/2].n_ranks != 0)) { 100 popts->cs_local_opts[i].odt_rd_cfg = 3; 101 popts->cs_local_opts[i].odt_wr_cfg = 3; 102 } else { 103 popts->cs_local_opts[i].odt_rd_cfg = 0; 104 popts->cs_local_opts[i].odt_wr_cfg = 4; 105 } 106 } 107 } 108 109 /* Get clk_adjust, cpo, write_data_delay, according to the board ddr 110 * freqency and n_banks specified in board_specific_parameters table. 111 */ 112 ddr_freq = get_ddr_freq(0) / 1000000; 113 for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { 114 if (pdimm[j].n_ranks > 0) { 115 for (i = 0; i < num_params; i++) { 116 if (ddr_freq >= pbsp->datarate_mhz_low && 117 ddr_freq <= pbsp->datarate_mhz_high && 118 pdimm[j].n_ranks == pbsp->n_ranks) { 119 popts->clk_adjust = pbsp->clk_adjust; 120 popts->cpo_override = pbsp->cpo; 121 popts->write_data_delay = 122 pbsp->write_data_delay; 123 break; 124 } 125 pbsp++; 126 } 127 } 128 } 129 130 if (i == num_params) { 131 printf("Warning: board specific timing not found " 132 "for data rate %lu MT/s!\n", ddr_freq); 133 } 134 135 /* 2T timing enable */ 136 popts->twoT_en = 1; 137 } 138