powerpc/8xxx: Replace fsl_ddr_get_mem_data_rate with get_ddr_freq()
[platform/kernel/u-boot.git] / board / freescale / mpc8641hpcn / ddr.c
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 }