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