blob: dbe358773be20c69de299611afaee4bcb00908eb [file] [log] [blame]
wdenk6c7a1402004-07-11 19:17:20 +00001/*
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 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02008 * SPDX-License-Identifier: GPL-2.0+
wdenk6c7a1402004-07-11 19:17:20 +00009 */
10
11#include <common.h>
12#include <mpc5xxx.h>
13
14#include "sdram.h"
15
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020016#ifndef CONFIG_SYS_RAMBOOT
wdenk6c7a1402004-07-11 19:17:20 +000017static void mpc5xxx_sdram_start (sdram_conf_t *sdram_conf, int hi_addr)
18{
19 long hi_addr_bit = hi_addr ? 0x01000000 : 0;
20
21 /* unlock mode register */
22 *(vu_long *)MPC5XXX_SDRAM_CTRL = sdram_conf->control | 0x80000000 | hi_addr_bit;
23 __asm__ volatile ("sync");
24
25 /* precharge all banks */
26 *(vu_long *)MPC5XXX_SDRAM_CTRL = sdram_conf->control | 0x80000002 | hi_addr_bit;
27 __asm__ volatile ("sync");
28
29 if (sdram_conf->ddr) {
30 /* set mode register: extended mode */
31 *(vu_long *)MPC5XXX_SDRAM_MODE = sdram_conf->emode;
32 __asm__ volatile ("sync");
33
34 /* set mode register: reset DLL */
35 *(vu_long *)MPC5XXX_SDRAM_MODE = sdram_conf->mode | 0x04000000;
36 __asm__ volatile ("sync");
37 }
38
39 /* precharge all banks */
40 *(vu_long *)MPC5XXX_SDRAM_CTRL = sdram_conf->control | 0x80000002 | hi_addr_bit;
41 __asm__ volatile ("sync");
42
43 /* auto refresh */
44 *(vu_long *)MPC5XXX_SDRAM_CTRL = sdram_conf->control | 0x80000004 | hi_addr_bit;
45 __asm__ volatile ("sync");
46
47 /* set mode register */
48 *(vu_long *)MPC5XXX_SDRAM_MODE = sdram_conf->mode;
49 __asm__ volatile ("sync");
50
51 /* normal operation */
52 *(vu_long *)MPC5XXX_SDRAM_CTRL = sdram_conf->control | hi_addr_bit;
53 __asm__ volatile ("sync");
54}
55#endif
56
57/*
58 * ATTENTION: Although partially referenced initdram does NOT make real use
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020059 * use of CONFIG_SYS_SDRAM_BASE. The code does not work if CONFIG_SYS_SDRAM_BASE
wdenk6c7a1402004-07-11 19:17:20 +000060 * is something else than 0x00000000.
61 */
62
wdenk6c7a1402004-07-11 19:17:20 +000063long int mpc5xxx_sdram_init (sdram_conf_t *sdram_conf)
64{
65 ulong dramsize = 0;
66 ulong dramsize2 = 0;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020067#ifndef CONFIG_SYS_RAMBOOT
wdenk6c7a1402004-07-11 19:17:20 +000068 ulong test1, test2;
69
70 /* setup SDRAM chip selects */
71 *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x0000001e;/* 2G at 0x0 */
72 *(vu_long *)MPC5XXX_SDRAM_CS1CFG = 0x80000000;/* disabled */
73 __asm__ volatile ("sync");
74
75 /* setup config registers */
76 *(vu_long *)MPC5XXX_SDRAM_CONFIG1 = sdram_conf->config1;
77 *(vu_long *)MPC5XXX_SDRAM_CONFIG2 = sdram_conf->config2;
78 __asm__ volatile ("sync");
79
80 if (sdram_conf->ddr) {
81 /* set tap delay */
82 *(vu_long *)MPC5XXX_CDM_PORCFG = sdram_conf->tapdelay;
83 __asm__ volatile ("sync");
84 }
85
86 /* find RAM size using SDRAM CS0 only */
87 mpc5xxx_sdram_start(sdram_conf, 0);
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020088 test1 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x80000000);
wdenk6c7a1402004-07-11 19:17:20 +000089 mpc5xxx_sdram_start(sdram_conf, 1);
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020090 test2 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x80000000);
wdenk6c7a1402004-07-11 19:17:20 +000091 if (test1 > test2) {
92 mpc5xxx_sdram_start(sdram_conf, 0);
93 dramsize = test1;
94 } else {
95 dramsize = test2;
96 }
97
98 /* memory smaller than 1MB is impossible */
99 if (dramsize < (1 << 20)) {
100 dramsize = 0;
101 }
102
103 /* set SDRAM CS0 size according to the amount of RAM found */
104 if (dramsize > 0) {
105 *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x13 + __builtin_ffs(dramsize >> 20) - 1;
106 } else {
107 *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0; /* disabled */
108 }
109
110 /* let SDRAM CS1 start right after CS0 */
111 *(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize + 0x0000001e;/* 2G */
112
113 /* find RAM size using SDRAM CS1 only */
114 mpc5xxx_sdram_start(sdram_conf, 0);
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200115 test1 = get_ram_size((long *)(CONFIG_SYS_SDRAM_BASE + dramsize), 0x80000000);
wdenk6c7a1402004-07-11 19:17:20 +0000116 mpc5xxx_sdram_start(sdram_conf, 1);
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200117 test2 = get_ram_size((long *)(CONFIG_SYS_SDRAM_BASE + dramsize), 0x80000000);
wdenk6c7a1402004-07-11 19:17:20 +0000118 if (test1 > test2) {
119 mpc5xxx_sdram_start(sdram_conf, 0);
120 dramsize2 = test1;
121 } else {
122 dramsize2 = test2;
123 }
124
125 /* memory smaller than 1MB is impossible */
126 if (dramsize2 < (1 << 20)) {
127 dramsize2 = 0;
128 }
129
130 /* set SDRAM CS1 size according to the amount of RAM found */
131 if (dramsize2 > 0) {
132 *(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize
133 | (0x13 + __builtin_ffs(dramsize2 >> 20) - 1);
134 } else {
135 *(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize; /* disabled */
136 }
137
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200138#else /* CONFIG_SYS_RAMBOOT */
wdenk6c7a1402004-07-11 19:17:20 +0000139
140 /* retrieve size of memory connected to SDRAM CS0 */
141 dramsize = *(vu_long *)MPC5XXX_SDRAM_CS0CFG & 0xFF;
142 if (dramsize >= 0x13) {
143 dramsize = (1 << (dramsize - 0x13)) << 20;
144 } else {
145 dramsize = 0;
146 }
147
148 /* retrieve size of memory connected to SDRAM CS1 */
149 dramsize2 = *(vu_long *)MPC5XXX_SDRAM_CS1CFG & 0xFF;
150 if (dramsize2 >= 0x13) {
151 dramsize2 = (1 << (dramsize2 - 0x13)) << 20;
152 } else {
153 dramsize2 = 0;
154 }
155
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200156#endif /* CONFIG_SYS_RAMBOOT */
wdenk6c7a1402004-07-11 19:17:20 +0000157
158 return dramsize + dramsize2;
159}