blob: ae3b50007f22baec2b852e7759c03797affe5b60 [file] [log] [blame]
wdenk591dda52002-11-18 00:14:45 +00001/*
2 * (C) Copyright 2002
3 * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>.
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/* stuff specific for the sc520,
25 * but idependent of implementation */
26
wdenk591dda52002-11-18 00:14:45 +000027#include <common.h>
wdenk591dda52002-11-18 00:14:45 +000028#include <asm/io.h>
wdenk591dda52002-11-18 00:14:45 +000029#include <asm/ic/sc520.h>
30
Wolfgang Denk6405a152006-03-31 18:32:53 +020031DECLARE_GLOBAL_DATA_PTR;
32
wdenk57b2d802003-06-27 21:31:46 +000033/*
34 * utility functions for boards based on the AMD sc520
35 *
wdenk591dda52002-11-18 00:14:45 +000036 * void write_mmcr_byte(u16 mmcr, u8 data)
37 * void write_mmcr_word(u16 mmcr, u16 data)
38 * void write_mmcr_long(u16 mmcr, u32 data)
wdenk57b2d802003-06-27 21:31:46 +000039 *
wdenk591dda52002-11-18 00:14:45 +000040 * u8 read_mmcr_byte(u16 mmcr)
41 * u16 read_mmcr_word(u16 mmcr)
42 * u32 read_mmcr_long(u16 mmcr)
wdenk57b2d802003-06-27 21:31:46 +000043 *
wdenk591dda52002-11-18 00:14:45 +000044 * void init_sc520(void)
45 * unsigned long init_sc520_dram(void)
wdenk591dda52002-11-18 00:14:45 +000046 */
47
48static u32 mmcr_base= 0xfffef000;
49
50void write_mmcr_byte(u16 mmcr, u8 data)
51{
52 writeb(data, mmcr+mmcr_base);
53}
54
55void write_mmcr_word(u16 mmcr, u16 data)
56{
wdenk57b2d802003-06-27 21:31:46 +000057 writew(data, mmcr+mmcr_base);
wdenk591dda52002-11-18 00:14:45 +000058}
59
60void write_mmcr_long(u16 mmcr, u32 data)
61{
62 writel(data, mmcr+mmcr_base);
63}
64
65u8 read_mmcr_byte(u16 mmcr)
66{
67 return readb(mmcr+mmcr_base);
68}
69
70u16 read_mmcr_word(u16 mmcr)
71{
wdenk57b2d802003-06-27 21:31:46 +000072 return readw(mmcr+mmcr_base);
wdenk591dda52002-11-18 00:14:45 +000073}
74
75u32 read_mmcr_long(u16 mmcr)
76{
77 return readl(mmcr+mmcr_base);
78}
79
80
81void init_sc520(void)
82{
wdenk591dda52002-11-18 00:14:45 +000083 /* Set the UARTxCTL register at it's slower,
wdenk57b2d802003-06-27 21:31:46 +000084 * baud clock giving us a 1.8432 MHz reference
wdenk591dda52002-11-18 00:14:45 +000085 */
86 write_mmcr_byte(SC520_UART1CTL, 7);
87 write_mmcr_byte(SC520_UART2CTL, 7);
wdenk57b2d802003-06-27 21:31:46 +000088
wdenk591dda52002-11-18 00:14:45 +000089 /* first set the timer pin mapping */
90 write_mmcr_byte(SC520_CLKSEL, 0x72); /* no clock frequency selected, use 1.1892MHz */
wdenk57b2d802003-06-27 21:31:46 +000091
wdenk591dda52002-11-18 00:14:45 +000092 /* enable PCI bus arbitrer */
93 write_mmcr_byte(SC520_SYSARBCTL,0x02); /* enable concurrent mode */
wdenk57b2d802003-06-27 21:31:46 +000094
wdenk591dda52002-11-18 00:14:45 +000095 write_mmcr_word(SC520_SYSARBMENB,0x1f); /* enable external grants */
96 write_mmcr_word(SC520_HBCTL,0x04); /* enable posted-writes */
97
98
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020099 if (CONFIG_SYS_SC520_HIGH_SPEED) {
wdenk591dda52002-11-18 00:14:45 +0000100 write_mmcr_byte(SC520_CPUCTL, 0x2); /* set it to 133 MHz and write back */
101 gd->cpu_clk = 133000000;
102 printf("## CPU Speed set to 133MHz\n");
103 } else {
104 write_mmcr_byte(SC520_CPUCTL, 1); /* set CPU to 100 MHz and write back cache */
105 printf("## CPU Speed set to 100MHz\n");
106 gd->cpu_clk = 100000000;
107 }
wdenk57b2d802003-06-27 21:31:46 +0000108
wdenk591dda52002-11-18 00:14:45 +0000109
110 /* wait at least one millisecond */
wdenk57b2d802003-06-27 21:31:46 +0000111 asm("movl $0x2000,%%ecx\n"
wdenk591dda52002-11-18 00:14:45 +0000112 "wait_loop: pushl %%ecx\n"
113 "popl %%ecx\n"
114 "loop wait_loop\n": : : "ecx");
115
116 /* turn on the SDRAM write buffer */
117 write_mmcr_byte(SC520_DBCTL, 0x11);
118
119 /* turn on the cache and disable write through */
120 asm("movl %%cr0, %%eax\n"
121 "andl $0x9fffffff, %%eax\n"
122 "movl %%eax, %%cr0\n" : : : "eax");
123}
124
125unsigned long init_sc520_dram(void)
126{
wdenk591dda52002-11-18 00:14:45 +0000127 bd_t *bd = gd->bd;
wdenk57b2d802003-06-27 21:31:46 +0000128
wdenk591dda52002-11-18 00:14:45 +0000129 u32 dram_present=0;
130 u32 dram_ctrl;
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200131#ifdef CONFIG_SYS_SDRAM_DRCTMCTL
Wolfgang Denk8ceef302006-08-14 23:23:06 +0200132 /* these memory control registers are set up in the assember part,
133 * in sc520_asm.S, during 'mem_init'. If we muck with them here,
134 * after we are running a stack in RAM, we have troubles. Besides,
Wolfgang Denkdd314d12006-08-27 18:10:01 +0200135 * these refresh and delay values are better ? simply specified
Wolfgang Denk8ceef302006-08-14 23:23:06 +0200136 * outright in the include/configs/{cfg} file since the HW designer
137 * simply dictates it.
138 */
139#else
wdenk591dda52002-11-18 00:14:45 +0000140 int val;
wdenk57b2d802003-06-27 21:31:46 +0000141
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200142 int cas_precharge_delay = CONFIG_SYS_SDRAM_PRECHARGE_DELAY;
143 int refresh_rate = CONFIG_SYS_SDRAM_REFRESH_RATE;
144 int ras_cas_delay = CONFIG_SYS_SDRAM_RAS_CAS_DELAY;
wdenk57b2d802003-06-27 21:31:46 +0000145
wdenk591dda52002-11-18 00:14:45 +0000146 /* set SDRAM speed here */
wdenk57b2d802003-06-27 21:31:46 +0000147
148 refresh_rate/=78;
wdenk591dda52002-11-18 00:14:45 +0000149 if (refresh_rate<=1) {
150 val = 0; /* 7.8us */
151 } else if (refresh_rate==2) {
152 val = 1; /* 15.6us */
153 } else if (refresh_rate==3 || refresh_rate==4) {
154 val = 2; /* 31.2us */
155 } else {
156 val = 3; /* 62.4us */
157 }
Wolfgang Denk8ceef302006-08-14 23:23:06 +0200158
wdenk591dda52002-11-18 00:14:45 +0000159 write_mmcr_byte(SC520_DRCCTL, (read_mmcr_byte(SC520_DRCCTL) & 0xcf) | (val<<4));
wdenk57b2d802003-06-27 21:31:46 +0000160
wdenk591dda52002-11-18 00:14:45 +0000161 val = read_mmcr_byte(SC520_DRCTMCTL);
162 val &= 0xf0;
wdenk57b2d802003-06-27 21:31:46 +0000163
164 if (cas_precharge_delay==3) {
wdenk591dda52002-11-18 00:14:45 +0000165 val |= 0x04; /* 3T */
wdenk57b2d802003-06-27 21:31:46 +0000166 } else if (cas_precharge_delay==4) {
wdenk591dda52002-11-18 00:14:45 +0000167 val |= 0x08; /* 4T */
wdenk57b2d802003-06-27 21:31:46 +0000168 } else if (cas_precharge_delay>4) {
wdenk591dda52002-11-18 00:14:45 +0000169 val |= 0x0c;
wdenk57b2d802003-06-27 21:31:46 +0000170 }
171
wdenk591dda52002-11-18 00:14:45 +0000172 if (ras_cas_delay > 3) {
wdenk57b2d802003-06-27 21:31:46 +0000173 val |= 2;
wdenk591dda52002-11-18 00:14:45 +0000174 } else {
wdenk57b2d802003-06-27 21:31:46 +0000175 val |= 1;
wdenk591dda52002-11-18 00:14:45 +0000176 }
177 write_mmcr_byte(SC520_DRCTMCTL, val);
Wolfgang Denk8ceef302006-08-14 23:23:06 +0200178#endif
wdenk591dda52002-11-18 00:14:45 +0000179
180 /* We read-back the configuration of the dram
181 * controller that the assembly code wrote */
182 dram_ctrl = read_mmcr_long(SC520_DRCBENDADR);
wdenk57b2d802003-06-27 21:31:46 +0000183
wdenk591dda52002-11-18 00:14:45 +0000184 bd->bi_dram[0].start = 0;
185 if (dram_ctrl & 0x80) {
186 /* bank 0 enabled */
187 dram_present = bd->bi_dram[1].start = (dram_ctrl & 0x7f) << 22;
wdenk57b2d802003-06-27 21:31:46 +0000188 bd->bi_dram[0].size = bd->bi_dram[1].start;
wdenk591dda52002-11-18 00:14:45 +0000189
190 } else {
191 bd->bi_dram[0].size = 0;
192 bd->bi_dram[1].start = bd->bi_dram[0].start;
193 }
wdenk57b2d802003-06-27 21:31:46 +0000194
wdenk591dda52002-11-18 00:14:45 +0000195 if (dram_ctrl & 0x8000) {
196 /* bank 1 enabled */
197 dram_present = bd->bi_dram[2].start = (dram_ctrl & 0x7f00) << 14;
wdenk57b2d802003-06-27 21:31:46 +0000198 bd->bi_dram[1].size = bd->bi_dram[2].start - bd->bi_dram[1].start;
wdenk591dda52002-11-18 00:14:45 +0000199 } else {
200 bd->bi_dram[1].size = 0;
201 bd->bi_dram[2].start = bd->bi_dram[1].start;
202 }
wdenk57b2d802003-06-27 21:31:46 +0000203
wdenk591dda52002-11-18 00:14:45 +0000204 if (dram_ctrl & 0x800000) {
205 /* bank 2 enabled */
206 dram_present = bd->bi_dram[3].start = (dram_ctrl & 0x7f0000) << 6;
wdenk57b2d802003-06-27 21:31:46 +0000207 bd->bi_dram[2].size = bd->bi_dram[3].start - bd->bi_dram[2].start;
wdenk591dda52002-11-18 00:14:45 +0000208 } else {
209 bd->bi_dram[2].size = 0;
210 bd->bi_dram[3].start = bd->bi_dram[2].start;
wdenk57b2d802003-06-27 21:31:46 +0000211 }
212
wdenk591dda52002-11-18 00:14:45 +0000213 if (dram_ctrl & 0x80000000) {
214 /* bank 3 enabled */
215 dram_present = (dram_ctrl & 0x7f000000) >> 2;
216 bd->bi_dram[3].size = dram_present - bd->bi_dram[3].start;
217 } else {
218 bd->bi_dram[3].size = 0;
219 }
220
wdenk57b2d802003-06-27 21:31:46 +0000221
222#if 0
wdenk591dda52002-11-18 00:14:45 +0000223 printf("Configured %d bytes of dram\n", dram_present);
wdenk57b2d802003-06-27 21:31:46 +0000224#endif
wdenk591dda52002-11-18 00:14:45 +0000225 gd->ram_size = dram_present;
wdenk57b2d802003-06-27 21:31:46 +0000226
wdenk591dda52002-11-18 00:14:45 +0000227 return dram_present;
228}
229
Graeme Russ27a2bf42009-02-24 21:12:20 +1100230#ifdef CONFIG_SYS_SC520_RESET
Graeme Russ382827c2008-12-07 10:29:03 +1100231void reset_cpu(ulong addr)
232{
233 printf("Resetting using SC520 MMCR\n");
234 /* Write a '1' to the SYS_RST of the RESCFG MMCR */
235 write_mmcr_word(SC520_RESCFG, 0x0001);
236
237 /* NOTREACHED */
238}
239#endif