Merge branch 'origin' into kconfig-for-1.3.1
[platform/kernel/u-boot.git] / board / purple / purple.c
1 /*
2  * (C) Copyright 2003
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25 #include <command.h>
26 #include <asm/inca-ip.h>
27 #include <asm/regdef.h>
28 #include <asm/mipsregs.h>
29 #include <asm/io.h>
30 #include <asm/addrspace.h>
31 #include <asm/cacheops.h>
32
33 #include "sconsole.h"
34
35 #define cache_unroll(base,op)                   \
36         __asm__ __volatile__("                  \
37                 .set noreorder;                 \
38                 .set mips3;                     \
39                 cache %1, (%0);                 \
40                 .set mips0;                     \
41                 .set reorder"                   \
42                 :                               \
43                 : "r" (base),                   \
44                   "i" (op));
45
46 typedef void (*FUNCPTR)(ulong *source, ulong *destination, ulong nlongs);
47
48 extern void     asc_serial_init         (void);
49 extern void     asc_serial_putc         (char);
50 extern void     asc_serial_puts         (const char *);
51 extern int      asc_serial_getc         (void);
52 extern int      asc_serial_tstc         (void);
53 extern void     asc_serial_setbrg       (void);
54
55 static void sdram_timing_init (ulong size)
56 {
57         register uint pass;
58         register uint done;
59         register uint count;
60         register uint p0, p1, p2, p3, p4;
61         register uint addr;
62
63 #define WRITE_MC_IOGP_1 *(uint *)0xbf800800 = (p1<<14)+(p2<<13)+(p4<<8)+(p0<<4)+p3;
64 #define WRITE_MC_IOGP_2 *(uint *)0xbf800800 = (p1<<14)+(p2<<13)+((p4-16)<<8)+(p0<<4)+p3;
65
66         done = 0;
67         p0 = 2;
68         while (p0 < 4 && done == 0) {
69             p1 = 0;
70             while (p1 < 2 && done == 0) {
71                 p2 = 0;
72                 while (p2 < 2 && done == 0) {
73                     p3 = 0;
74                     while (p3 < 16 && done == 0) {
75                         count = 0;
76                         p4 = 0;
77                         while (p4 < 32 && done == 0) {
78                             WRITE_MC_IOGP_1;
79
80                             for (addr = KSEG1 + 0x4000;
81                                  addr < KSEG1ADDR (size);
82                                  addr = addr + 4) {
83                                         *(uint *) addr = 0xaa55aa55;
84                             }
85
86                             pass = 1;
87
88                             for (addr = KSEG1 + 0x4000;
89                                  addr < KSEG1ADDR (size) && pass == 1;
90                                  addr = addr + 4) {
91                                         if (*(uint *) addr != 0xaa55aa55)
92                                                 pass = 0;
93                             }
94
95                             if (pass == 1) {
96                                 count++;
97                             } else {
98                                 count = 0;
99                             }
100
101                             if (count == 32) {
102                                 WRITE_MC_IOGP_2;
103                                 done = 1;
104                             }
105                             p4++;
106                         }
107                         p3++;
108                     }
109                     p2++;
110                 }
111                 p1++;
112             }
113             p0++;
114             if (p0 == 1)
115                 p0++;
116         }
117 }
118
119 long int initdram(int board_type)
120 {
121         /* The only supported number of SDRAM banks is 4.
122          */
123 #define CFG_NB  4
124
125         ulong   cfgpb0  = *INCA_IP_SDRAM_MC_CFGPB0;
126         ulong   cfgdw   = *INCA_IP_SDRAM_MC_CFGDW;
127         int     cols    = cfgpb0 & 0xF;
128         int     rows    = (cfgpb0 & 0xF0) >> 4;
129         int     dw      = cfgdw & 0xF;
130         ulong   size    = (1 << (rows + cols)) * (1 << (dw - 1)) * CFG_NB;
131         void (*  sdram_init) (ulong);
132
133         sdram_init = (void (*)(ulong)) KSEG0ADDR(&sdram_timing_init);
134
135         sdram_init(0x10000);
136
137         return size;
138 }
139
140 int checkboard (void)
141 {
142
143         unsigned long chipid = *(unsigned long *)0xB800C800;
144
145         printf ("Board: Purple PLB 2800 chip version %ld, ", chipid & 0xF);
146
147         printf("CPU Speed %d MHz\n", CPU_CLOCK_RATE/1000000);
148
149         set_io_port_base(0);
150
151         return 0;
152 }
153
154 int misc_init_r (void)
155 {
156         asc_serial_init ();
157
158         sconsole_putc   = asc_serial_putc;
159         sconsole_puts   = asc_serial_puts;
160         sconsole_getc   = asc_serial_getc;
161         sconsole_tstc   = asc_serial_tstc;
162         sconsole_setbrg = asc_serial_setbrg;
163
164         sconsole_flush ();
165         return (0);
166 }
167
168 /*******************************************************************************
169 *
170 * copydwords - copy one buffer to another a long at a time
171 *
172 * This routine copies the first <nlongs> longs from <source> to <destination>.
173 */
174 static void copydwords (ulong *source, ulong *destination, ulong nlongs)
175 {
176         ulong temp,temp1;
177         ulong *dstend = destination + nlongs;
178
179         while (destination < dstend)
180         {
181                 temp = *source++;
182                 /* dummy read from sdram */
183                 temp1 = *(ulong *)0xa0000000;
184                 /* avoid optimization from compliler */
185                 *(ulong *)0xbf0081f8 = temp1 + temp;
186                 *destination++ = temp;
187
188         }
189 }
190
191 /*******************************************************************************
192 *
193 * copyLongs - copy one buffer to another a long at a time
194 *
195 * This routine copies the first <nlongs> longs from <source> to <destination>.
196 */
197 static void copyLongs (ulong *source, ulong *destination, ulong nlongs)
198 {
199         FUNCPTR absEntry;
200
201         absEntry = (FUNCPTR)(0xbf008000+((ulong)copydwords & 0x7));
202         absEntry(source, destination, nlongs);
203 }
204
205 /*******************************************************************************
206 *
207 * programLoad - load program into ram
208 *
209 * This routine load copydwords into ram
210 *
211 */
212 static void programLoad(void)
213 {
214         FUNCPTR absEntry;
215         ulong *src,*dst;
216
217         src = (ulong *)(TEXT_BASE + 0x428);
218         dst = (ulong *)0xbf0081d0;
219
220         absEntry = (FUNCPTR)(TEXT_BASE + 0x400);
221         absEntry(src,dst,0x6);
222
223         src = (ulong *)((ulong)copydwords & 0xfffffff8);
224         dst = (ulong *)0xbf008000;
225
226         absEntry(src,dst,0x38);
227 }
228
229 /*******************************************************************************
230 *
231 * copy_code - copy u-boot image from flash to RAM
232 *
233 * This routine is needed to solve flash problems on this board
234 *
235 */
236 void copy_code (ulong dest_addr)
237 {
238         extern long uboot_end_data;
239         unsigned long start;
240         unsigned long end;
241
242         /* load copydwords into ram
243          */
244         programLoad();
245
246         /* copy u-boot code
247          */
248         copyLongs((ulong *)CFG_MONITOR_BASE,
249                   (ulong *)dest_addr,
250                   ((ulong)&uboot_end_data - CFG_MONITOR_BASE + 3) / 4);
251
252
253         /* flush caches
254          */
255
256         start = KSEG0;
257         end = start + CFG_DCACHE_SIZE;
258         while(start < end) {
259                 cache_unroll(start,Index_Writeback_Inv_D);
260                 start += CFG_CACHELINE_SIZE;
261         }
262
263         start = KSEG0;
264         end = start + CFG_ICACHE_SIZE;
265         while(start < end) {
266                 cache_unroll(start,Index_Invalidate_I);
267                 start += CFG_CACHELINE_SIZE;
268         }
269 }