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 #include <i2c.h> 11 12 #include <asm/fsl_ddr_sdram.h> 13 #include <asm/fsl_ddr_dimm_params.h> 14 15 static void 16 get_spd(ddr2_spd_eeprom_t *spd, unsigned char i2c_address) 17 { 18 i2c_read(i2c_address, 0, 1, (uchar *)spd, sizeof(ddr2_spd_eeprom_t)); 19 } 20 21 void fsl_ddr_get_spd(ddr2_spd_eeprom_t *ctrl_dimms_spd, 22 unsigned int ctrl_num) 23 { 24 unsigned int i; 25 unsigned int i2c_address = 0; 26 27 for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) { 28 if (ctrl_num == 0 && i == 0) { 29 i2c_address = SPD_EEPROM_ADDRESS1; 30 } 31 if (ctrl_num == 0 && i == 1) { 32 i2c_address = SPD_EEPROM_ADDRESS2; 33 } 34 if (ctrl_num == 1 && i == 0) { 35 i2c_address = SPD_EEPROM_ADDRESS3; 36 } 37 if (ctrl_num == 1 && i == 1) { 38 i2c_address = SPD_EEPROM_ADDRESS4; 39 } 40 get_spd(&(ctrl_dimms_spd[i]), i2c_address); 41 } 42 } 43 44 typedef struct { 45 u32 datarate_mhz_low; 46 u32 datarate_mhz_high; 47 u32 n_ranks; 48 u32 clk_adjust; 49 u32 cpo; 50 u32 write_data_delay; 51 } board_specific_parameters_t; 52 53 /* XXX: these values need to be checked for all interleaving modes. */ 54 const board_specific_parameters_t board_specific_parameters[2][16] = { 55 { 56 /* memory controller 0 */ 57 /* lo| hi| num| clk| cpo|wrdata */ 58 /* mhz| mhz|ranks|adjst| | delay */ 59 { 0, 333, 4, 7, 7, 3}, 60 {334, 400, 4, 7, 9, 3}, 61 {401, 549, 4, 7, 9, 3}, 62 {550, 650, 4, 7, 10, 4}, 63 64 { 0, 333, 3, 7, 7, 3}, 65 {334, 400, 3, 7, 9, 3}, 66 {401, 549, 3, 7, 9, 3}, 67 {550, 650, 3, 7, 10, 4}, 68 69 { 0, 333, 2, 7, 7, 3}, 70 {334, 400, 2, 7, 9, 3}, 71 {401, 549, 2, 7, 9, 3}, 72 {550, 650, 2, 7, 10, 4}, 73 74 { 0, 333, 1, 7, 7, 3}, 75 {334, 400, 1, 7, 9, 3}, 76 {401, 549, 1, 7, 9, 3}, 77 {550, 650, 1, 7, 10, 4} 78 }, 79 80 { 81 /* memory controller 1 */ 82 /* lo| hi| num| clk| cpo|wrdata */ 83 /* mhz| mhz|ranks|adjst| | delay */ 84 { 0, 333, 4, 7, 7, 3}, 85 {334, 400, 4, 7, 9, 3}, 86 {401, 549, 4, 7, 9, 3}, 87 {550, 650, 4, 7, 10, 4}, 88 89 { 0, 333, 3, 7, 7, 3}, 90 {334, 400, 3, 7, 9, 3}, 91 {401, 549, 3, 7, 9, 3}, 92 {550, 650, 3, 7, 10, 4}, 93 94 { 0, 333, 2, 7, 7, 3}, 95 {334, 400, 2, 7, 9, 3}, 96 {401, 549, 2, 7, 9, 3}, 97 {550, 650, 2, 7, 10, 4}, 98 99 { 0, 333, 1, 7, 7, 3}, 100 {334, 400, 1, 7, 9, 3}, 101 {401, 549, 1, 7, 9, 3}, 102 {550, 650, 1, 7, 10, 4} 103 } 104 }; 105 106 void fsl_ddr_board_options(memctl_options_t *popts, 107 dimm_params_t *pdimm, 108 unsigned int ctrl_num) 109 { 110 const board_specific_parameters_t *pbsp = 111 &(board_specific_parameters[ctrl_num][0]); 112 u32 num_params = sizeof(board_specific_parameters[ctrl_num]) / 113 sizeof(board_specific_parameters[0][0]); 114 u32 i; 115 u32 j; 116 ulong ddr_freq; 117 118 /* set odt_rd_cfg and odt_wr_cfg. If the there is only one dimm in 119 * that controller, set odt_wr_cfg to 4 for CS0, and 0 to CS1. If 120 * there are two dimms in the controller, set odt_rd_cfg to 3 and 121 * odt_wr_cfg to 3 for the even CS, 0 for the odd CS. 122 */ 123 for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { 124 if (i&1) { /* odd CS */ 125 popts->cs_local_opts[i].odt_rd_cfg = 0; 126 popts->cs_local_opts[i].odt_wr_cfg = 0; 127 } else { /* even CS */ 128 if ((CONFIG_DIMM_SLOTS_PER_CTLR == 2) && 129 (pdimm[i/2].n_ranks != 0)) { 130 popts->cs_local_opts[i].odt_rd_cfg = 3; 131 popts->cs_local_opts[i].odt_wr_cfg = 3; 132 } else { 133 popts->cs_local_opts[i].odt_rd_cfg = 0; 134 popts->cs_local_opts[i].odt_wr_cfg = 4; 135 } 136 } 137 } 138 139 /* Get clk_adjust, cpo, write_data_delay, according to the board ddr 140 * freqency and n_banks specified in board_specific_parameters table. 141 */ 142 ddr_freq = get_ddr_freq(0) / 1000000; 143 for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { 144 if (pdimm[j].n_ranks > 0) { 145 for (i = 0; i < num_params; i++) { 146 if (ddr_freq >= pbsp->datarate_mhz_low && 147 ddr_freq <= pbsp->datarate_mhz_high && 148 pdimm[j].n_ranks == pbsp->n_ranks) { 149 popts->clk_adjust = pbsp->clk_adjust; 150 popts->cpo_override = pbsp->cpo; 151 popts->write_data_delay = 152 pbsp->write_data_delay; 153 break; 154 } 155 pbsp++; 156 } 157 } 158 } 159 160 /* 2T timing enable */ 161 popts->twoT_en = 1; 162 } 163