3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4 * Marius Groeger <mgroeger@sysgo.de>
6 * Board specific routines for the MBX
9 * - interface to VPD data (mac address, clock speeds)
11 * - serial io initialisation
12 * - ethernet io initialisation
14 * -----------------------------------------------------------------
15 * See file CREDITS for list of people who contributed to this
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License as
20 * published by the Free Software Foundation; either version 2 of
21 * the License, or (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
41 /* ------------------------------------------------------------------------- */
43 static const uint sdram_table_40
[] = {
44 /* DRAM - single read. (offset 0 in upm RAM)
46 0xCFAFC004, 0x0FAFC404, 0x0CAF0C04, 0x30AF0C00,
47 0xF1BF4805, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
49 /* DRAM - burst read. (offset 8 in upm RAM)
51 0xCFAFC004, 0x0FAFC404, 0x0CAF0C04, 0x03AF0C08,
52 0x0CAF0C04, 0x03AF0C08, 0x0CAF0C04, 0x03AF0C08,
53 0x0CAF0C04, 0x30AF0C00, 0xF3BF4805, 0xFFFFC005,
54 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
56 /* DRAM - single write. (offset 18 in upm RAM)
58 0xCFFF0004, 0x0FFF0404, 0x0CFF0C00, 0x33FF4804,
59 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
61 /* DRAM - burst write. (offset 20 in upm RAM)
63 0xCFFF0004, 0x0FFF0404, 0x0CFF0C00, 0x03FF0C0C,
64 0x0CFF0C00, 0x03FF0C0C, 0x0CFF0C00, 0x03FF0C0C,
65 0x0CFF0C00, 0x33FF4804, 0xFFFFC005, 0xFFFFC005,
66 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
68 /* refresh (offset 30 in upm RAM)
70 0xFCFFC004, 0xC0FFC004, 0x01FFC004, 0x0FFFC004,
71 0x3FFFC004, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
72 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
74 /* exception. (offset 3c in upm RAM)
76 0xFFFFC007, 0xFFFFC007, 0xFFFFC007, 0xFFFFC007,
79 static const uint sdram_table_50
[] = {
80 /* DRAM - single read. (offset 0 in upm RAM)
82 0xCFAFC004, 0x0FAFC404, 0x0CAF8C04, 0x10AF0C04,
83 0xF0AF0C00, 0xF3BF4805, 0xFFFFC005, 0xFFFFC005,
85 /* DRAM - burst read. (offset 8 in upm RAM)
87 0xCFAFC004, 0X0FAFC404, 0X0CAF8C04, 0X00AF0C04,
88 /* 0X07AF0C08, 0X0CAF0C04, 0X01AF0C04, 0X0FAF0C04, */
89 0X07AF0C08, 0X0CAF0C04, 0X01AF0C04, 0X0FAF0C08,
90 0X0CAF0C04, 0X01AF0C04, 0X0FAF0C08, 0X0CAF0C04,
91 /* 0X10AF0C04, 0XF0AFC000, 0XF3FF4805, 0XFFFFC005, */
92 0X10AF0C04, 0XF0AFC000, 0XF3BF4805, 0XFFFFC005,
94 /* DRAM - single write. (offset 18 in upm RAM)
96 0xCFFF0004, 0x0FFF0404, 0x0CFF0C00, 0x13FF4804,
97 0xFFFFC004, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
99 /* DRAM - burst write. (offset 20 in upm RAM)
101 0xCFFF0004, 0x0FFF0404, 0x0CFF0C00, 0x03FF0C0C,
102 0x0CFF0C00, 0x03FF0C0C, 0x0CFF0C00, 0x03FF0C0C,
103 0x0CFF0C00, 0x13FF4804, 0xFFFFC004, 0xFFFFC005,
104 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
106 /* refresh (offset 30 in upm RAM)
108 0xFCFFC004, 0xC0FFC004, 0x01FFC004, 0x0FFFC004,
109 0x1FFFC004, 0xFFFFC004, 0xFFFFC005, 0xFFFFC005,
110 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005,
112 /* exception. (offset 3c in upm RAM)
114 0xFFFFC007, 0xFFFFC007, 0xFFFFC007, 0xFFFFC007,
117 /* ------------------------------------------------------------------------- */
119 static unsigned int get_reffreq(void);
120 static unsigned int board_get_cpufreq(void);
124 volatile immap_t
*immr
= (immap_t
*) CFG_IMMR
;
125 volatile memctl8xx_t
*memctl
= &immr
->im_memctl
;
126 ulong speed
, refclock
, plprcr
, sccr
;
127 ulong br0_32
= memctl
->memc_br0
& 0x400;
129 /* real-time clock status and control register */
130 immr
->im_sitk
.sitk_rtcsck
= KAPWR_KEY
;
131 immr
->im_sit
.sit_rtcsc
= 0x00C3;
133 /* SIEL and SIMASK Registers (see MBX PRG 2-3) */
134 immr
->im_siu_conf
.sc_simask
= 0x00000000;
135 immr
->im_siu_conf
.sc_siel
= 0xAAAA0000;
136 immr
->im_siu_conf
.sc_tesr
= 0xFFFFFFFF;
139 * Prepare access to i2c bus. The MBX offers 3 devices on the i2c bus:
140 * 1. Vital Product Data (contains clock speeds, MAC address etc, see vpd.h)
141 * 2. RAM Specs (see dimm.h)
142 * 2. DIMM Specs (see dimm.h)
146 /* system clock and reset control register */
147 immr
->im_clkrstk
.cark_sccrk
= KAPWR_KEY
;
148 sccr
= immr
->im_clkrst
.car_sccr
;
151 immr
->im_clkrst
.car_sccr
= sccr
;
153 speed
= board_get_cpufreq ();
154 refclock
= get_reffreq ();
156 #if ((CFG_PLPRCR & PLPRCR_MF_MSK) != 0)
159 plprcr
= immr
->im_clkrst
.car_plprcr
;
160 plprcr
&= PLPRCR_MF_MSK
; /* isolate MF field */
161 plprcr
|= CFG_PLPRCR
; /* reset control bits */
164 #ifdef CFG_USE_OSCCLK /* See doc/README.MBX ! */
165 plprcr
|= ((speed
+ refclock
/ 2) / refclock
- 1) << 20;
168 immr
->im_clkrstk
.cark_plprcrk
= KAPWR_KEY
;
169 immr
->im_clkrst
.car_plprcr
= plprcr
;
172 * preliminary setup of memory controller:
173 * - map Flash, otherwise configuration/status
174 * registers won't be accessible when read
176 * - map NVRAM and configuation/status registers.
177 * - map pci registers.
178 * - DON'T map ram yet, this is done in initdram().
180 switch (speed
/ 1000000) {
182 memctl
->memc_br0
= 0xFE000000 | br0_32
| 1;
183 memctl
->memc_or0
= 0xFF800930;
184 memctl
->memc_or4
= CFG_NVRAM_OR
| 0x920;
185 memctl
->memc_br4
= CFG_NVRAM_BASE
| 0x401;
188 memctl
->memc_br0
= 0xFE000000 | br0_32
| 1;
189 memctl
->memc_or0
= 0xFF800940;
190 memctl
->memc_or4
= CFG_NVRAM_OR
| 0x930;
191 memctl
->memc_br4
= CFG_NVRAM_BASE
| 0x401;
197 #ifdef CONFIG_USE_PCI
198 memctl
->memc_or5
= CFG_PCIMEM_OR
;
199 memctl
->memc_br5
= CFG_PCIMEM_BASE
| 0x001;
200 memctl
->memc_or6
= CFG_PCIBRIDGE_OR
;
201 memctl
->memc_br6
= CFG_PCIBRIDGE_BASE
| 0x001;
204 * FIXME: I do not understand why I have to call this to
205 * initialise the control register here before booting from
206 * the PCMCIA card but if I do not the Linux kernel falls
207 * over in a big heap. If you can answer this question I
208 * would like to know about it.
213 void board_serial_init (void)
215 MBX_CSR1
&= ~(CSR1_COM1EN
| CSR1_XCVRDIS
);
218 void board_ether_init (void)
220 MBX_CSR1
&= ~(CSR1_EAEN
| CSR1_ELEN
);
221 MBX_CSR1
|= CSR1_ETEN
| CSR1_TPEN
| CSR1_FDDIS
;
224 static unsigned int board_get_cpufreq (void)
226 #ifndef CONFIG_8xx_GCLK_FREQ
227 vpd_packet_t
*packet
;
229 packet
= vpd_find_packet (VPD_PID_ICS
);
230 return *((ulong
*) packet
->data
);
232 return((unsigned int)CONFIG_8xx_GCLK_FREQ
);
233 #endif /* CONFIG_8xx_GCLK_FREQ */
236 static unsigned int get_reffreq (void)
238 vpd_packet_t
*packet
;
240 packet
= vpd_find_packet (VPD_PID_RCS
);
241 return *((ulong
*) packet
->data
);
244 void board_get_enetaddr (uchar
* addr
)
247 vpd_packet_t
*packet
;
249 packet
= vpd_find_packet (VPD_PID_EA
);
250 for (i
= 0; i
< 6; i
++)
251 addr
[i
] = packet
->data
[i
];
255 * Check Board Identity:
258 int checkboard (void)
260 vpd_packet_t
*packet
;
262 const char *const fmt
=
263 "\n *** Warning: Low Battery Status - %s Battery ***";
267 packet
= vpd_find_packet (VPD_PID_PID
);
268 for (i
= 0; i
< packet
->size
; i
++) {
269 serial_putc (packet
->data
[i
]);
271 packet
= vpd_find_packet (VPD_PID_MT
);
272 for (i
= 0; i
< packet
->size
; i
++) {
273 serial_putc (packet
->data
[i
]);
276 packet
= vpd_find_packet (VPD_PID_FAN
);
277 for (i
= 0; i
< packet
->size
; i
++) {
278 serial_putc (packet
->data
[i
]);
282 if (!(MBX_CSR2
& SR2_BATGD
))
283 printf (fmt
, "On-Board");
284 if (!(MBX_CSR2
& SR2_NVBATGD
))
285 printf (fmt
, "NVRAM");
292 /* ------------------------------------------------------------------------- */
294 static ulong
get_ramsize (dimm_t
* dimm
)
298 if (dimm
->fmt
== 1 || dimm
->fmt
== 2 || dimm
->fmt
== 3
300 size
= (1 << (dimm
->n_row
+ dimm
->n_col
)) * dimm
->n_banks
*
301 ((dimm
->data_w_hi
<< 8 | dimm
->data_w_lo
) / 8);
307 phys_size_t
initdram (int board_type
)
309 volatile immap_t
*immap
= (immap_t
*) CFG_IMMR
;
310 volatile memctl8xx_t
*memctl
= &immap
->im_memctl
;
311 unsigned long ram_sz
= 0;
312 unsigned long dimm_sz
= 0;
313 dimm_t vpd_dimm
, vpd_dram
;
314 unsigned int speed
= board_get_cpufreq () / 1000000;
316 if (vpd_read (0xa2, (uchar
*) & vpd_dimm
, sizeof (vpd_dimm
), 0) > 0) {
317 dimm_sz
= get_ramsize (&vpd_dimm
);
319 if (vpd_read (0xa6, (uchar
*) & vpd_dram
, sizeof (vpd_dram
), 0) > 0) {
320 ram_sz
= get_ramsize (&vpd_dram
);
324 * Only initialize memory controller when running from FLASH.
325 * When running from RAM, don't touch it.
327 if ((ulong
) initdram
& 0xff000000) {
329 ulong br0_32
= memctl
->memc_br0
& 0x400;
333 upmconfig (UPMA
, (uint
*) sdram_table_40
,
334 sizeof (sdram_table_40
) / sizeof (uint
));
335 memctl
->memc_mptpr
= 0x0200;
336 memctl
->memc_mamr
= dimm_sz
? 0x06801000 : 0x13801000;
337 memctl
->memc_or7
= 0xff800930;
338 memctl
->memc_br7
= 0xfc000000 | (br0_32
^ br0_32
) | 1;
341 upmconfig (UPMA
, (uint
*) sdram_table_50
,
342 sizeof (sdram_table_50
) / sizeof (uint
));
343 memctl
->memc_mptpr
= 0x0200;
344 memctl
->memc_mamr
= dimm_sz
? 0x08801000 : 0x1880100;
345 memctl
->memc_or7
= 0xff800940;
346 memctl
->memc_br7
= 0xfc000000 | (br0_32
^ br0_32
) | 1;
353 /* now map ram and dimm, largest one first */
354 dimm_bank
= dimm_sz
/ 2;
356 memctl
->memc_or1
= ~(ram_sz
- 1) | 0x400;
357 memctl
->memc_br1
= CFG_SDRAM_BASE
| 0x81;
358 memctl
->memc_br2
= 0;
359 memctl
->memc_br3
= 0;
360 } else if (ram_sz
> dimm_bank
) {
361 memctl
->memc_or1
= ~(ram_sz
- 1) | 0x400;
362 memctl
->memc_br1
= CFG_SDRAM_BASE
| 0x81;
363 memctl
->memc_or2
= ~(dimm_bank
- 1) | 0x400;
364 memctl
->memc_br2
= (CFG_SDRAM_BASE
+ ram_sz
) | 0x81;
365 memctl
->memc_or3
= ~(dimm_bank
- 1) | 0x400;
366 memctl
->memc_br3
= (CFG_SDRAM_BASE
+ ram_sz
+ dimm_bank
) \
369 memctl
->memc_or2
= ~(dimm_bank
- 1) | 0x400;
370 memctl
->memc_br2
= CFG_SDRAM_BASE
| 0x81;
371 memctl
->memc_or3
= ~(dimm_bank
- 1) | 0x400;
372 memctl
->memc_br3
= (CFG_SDRAM_BASE
+ dimm_bank
) | 0x81;
373 memctl
->memc_or1
= ~(ram_sz
- 1) | 0x400;
374 memctl
->memc_br1
= (CFG_SDRAM_BASE
+ dimm_sz
) | 0x81;
378 return ram_sz
+ dimm_sz
;