tizen 2.4 release
[kernel/u-boot-tm1.git] / board / total5200 / sdram.c
1 /*
2  * (C) Copyright 2003-2004
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * (C) Copyright 2004
6  * Mark Jonas, Freescale Semiconductor, mark.jonas@freescale.com.
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  */
26
27 #include <common.h>
28 #include <mpc5xxx.h>
29
30 #include "sdram.h"
31
32 #ifndef CONFIG_SYS_RAMBOOT
33 static void mpc5xxx_sdram_start (sdram_conf_t *sdram_conf, int hi_addr)
34 {
35         long hi_addr_bit = hi_addr ? 0x01000000 : 0;
36
37         /* unlock mode register */
38         *(vu_long *)MPC5XXX_SDRAM_CTRL = sdram_conf->control | 0x80000000 | hi_addr_bit;
39         __asm__ volatile ("sync");
40
41         /* precharge all banks */
42         *(vu_long *)MPC5XXX_SDRAM_CTRL = sdram_conf->control | 0x80000002 | hi_addr_bit;
43         __asm__ volatile ("sync");
44
45         if (sdram_conf->ddr) {
46                 /* set mode register: extended mode */
47                 *(vu_long *)MPC5XXX_SDRAM_MODE = sdram_conf->emode;
48                 __asm__ volatile ("sync");
49
50                 /* set mode register: reset DLL */
51                 *(vu_long *)MPC5XXX_SDRAM_MODE = sdram_conf->mode | 0x04000000;
52                 __asm__ volatile ("sync");
53         }
54
55         /* precharge all banks */
56         *(vu_long *)MPC5XXX_SDRAM_CTRL = sdram_conf->control | 0x80000002 | hi_addr_bit;
57         __asm__ volatile ("sync");
58
59         /* auto refresh */
60         *(vu_long *)MPC5XXX_SDRAM_CTRL = sdram_conf->control | 0x80000004 | hi_addr_bit;
61         __asm__ volatile ("sync");
62
63         /* set mode register */
64         *(vu_long *)MPC5XXX_SDRAM_MODE = sdram_conf->mode;
65         __asm__ volatile ("sync");
66
67         /* normal operation */
68         *(vu_long *)MPC5XXX_SDRAM_CTRL = sdram_conf->control | hi_addr_bit;
69         __asm__ volatile ("sync");
70 }
71 #endif
72
73 /*
74  * ATTENTION: Although partially referenced initdram does NOT make real use
75  *            use of CONFIG_SYS_SDRAM_BASE. The code does not work if CONFIG_SYS_SDRAM_BASE
76  *            is something else than 0x00000000.
77  */
78
79 long int mpc5xxx_sdram_init (sdram_conf_t *sdram_conf)
80 {
81         ulong dramsize = 0;
82         ulong dramsize2 = 0;
83 #ifndef CONFIG_SYS_RAMBOOT
84         ulong test1, test2;
85
86         /* setup SDRAM chip selects */
87         *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x0000001e;/* 2G at 0x0 */
88         *(vu_long *)MPC5XXX_SDRAM_CS1CFG = 0x80000000;/* disabled */
89         __asm__ volatile ("sync");
90
91         /* setup config registers */
92         *(vu_long *)MPC5XXX_SDRAM_CONFIG1 = sdram_conf->config1;
93         *(vu_long *)MPC5XXX_SDRAM_CONFIG2 = sdram_conf->config2;
94         __asm__ volatile ("sync");
95
96         if (sdram_conf->ddr) {
97                 /* set tap delay */
98                 *(vu_long *)MPC5XXX_CDM_PORCFG = sdram_conf->tapdelay;
99                 __asm__ volatile ("sync");
100         }
101
102         /* find RAM size using SDRAM CS0 only */
103         mpc5xxx_sdram_start(sdram_conf, 0);
104         test1 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x80000000);
105         mpc5xxx_sdram_start(sdram_conf, 1);
106         test2 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x80000000);
107         if (test1 > test2) {
108                 mpc5xxx_sdram_start(sdram_conf, 0);
109                 dramsize = test1;
110         } else {
111                 dramsize = test2;
112         }
113
114         /* memory smaller than 1MB is impossible */
115         if (dramsize < (1 << 20)) {
116                 dramsize = 0;
117         }
118
119         /* set SDRAM CS0 size according to the amount of RAM found */
120         if (dramsize > 0) {
121                 *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x13 + __builtin_ffs(dramsize >> 20) - 1;
122         } else {
123                 *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0; /* disabled */
124         }
125
126         /* let SDRAM CS1 start right after CS0 */
127         *(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize + 0x0000001e;/* 2G */
128
129         /* find RAM size using SDRAM CS1 only */
130         mpc5xxx_sdram_start(sdram_conf, 0);
131         test1 = get_ram_size((long *)(CONFIG_SYS_SDRAM_BASE + dramsize), 0x80000000);
132         mpc5xxx_sdram_start(sdram_conf, 1);
133         test2 = get_ram_size((long *)(CONFIG_SYS_SDRAM_BASE + dramsize), 0x80000000);
134         if (test1 > test2) {
135                 mpc5xxx_sdram_start(sdram_conf, 0);
136                 dramsize2 = test1;
137         } else {
138                 dramsize2 = test2;
139         }
140
141         /* memory smaller than 1MB is impossible */
142         if (dramsize2 < (1 << 20)) {
143                 dramsize2 = 0;
144         }
145
146         /* set SDRAM CS1 size according to the amount of RAM found */
147         if (dramsize2 > 0) {
148                 *(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize
149                         | (0x13 + __builtin_ffs(dramsize2 >> 20) - 1);
150         } else {
151                 *(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize; /* disabled */
152         }
153
154 #else /* CONFIG_SYS_RAMBOOT */
155
156         /* retrieve size of memory connected to SDRAM CS0 */
157         dramsize = *(vu_long *)MPC5XXX_SDRAM_CS0CFG & 0xFF;
158         if (dramsize >= 0x13) {
159                 dramsize = (1 << (dramsize - 0x13)) << 20;
160         } else {
161                 dramsize = 0;
162         }
163
164         /* retrieve size of memory connected to SDRAM CS1 */
165         dramsize2 = *(vu_long *)MPC5XXX_SDRAM_CS1CFG & 0xFF;
166         if (dramsize2 >= 0x13) {
167                 dramsize2 = (1 << (dramsize2 - 0x13)) << 20;
168         } else {
169                 dramsize2 = 0;
170         }
171
172 #endif /* CONFIG_SYS_RAMBOOT */
173
174         return dramsize + dramsize2;
175 }