powerpc/mpc85xx: Display a warning for unsupported DDR data rates
[oweals/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
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 }