1 /*
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 
27 #include <common.h>
28 #include <asm/io.h>
29 #include <asm/ic/sc520.h>
30 
31 DECLARE_GLOBAL_DATA_PTR;
32 
33 /*
34  * utility functions for boards based on the AMD sc520
35  *
36  * void init_sc520(void)
37  * unsigned long init_sc520_dram(void)
38  */
39 
40 volatile sc520_mmcr_t *sc520_mmcr = (sc520_mmcr_t *)0xfffef000;
41 
init_sc520(void)42 void init_sc520(void)
43 {
44 	/* Set the UARTxCTL register at it's slower,
45 	 * baud clock giving us a 1.8432 MHz reference
46 	 */
47 	writeb(0x07, &sc520_mmcr->uart1ctl);
48 	writeb(0x07, &sc520_mmcr->uart2ctl);
49 
50 	/* first set the timer pin mapping */
51 	writeb(0x72, &sc520_mmcr->clksel);	/* no clock frequency selected, use 1.1892MHz */
52 
53 	/* enable PCI bus arbitrer */
54 	writeb(0x02, &sc520_mmcr->sysarbctl);	/* enable concurrent mode */
55 
56 	writeb(0x1f, &sc520_mmcr->sysarbmenb);	/* enable external grants */
57 	writeb(0x04, &sc520_mmcr->hbctl);	/* enable posted-writes */
58 
59 	if (CONFIG_SYS_SC520_HIGH_SPEED) {
60 		writeb(0x02, &sc520_mmcr->cpuctl);	/* set it to 133 MHz and write back */
61 		gd->cpu_clk = 133000000;
62 		printf("## CPU Speed set to 133MHz\n");
63 	} else {
64 		writeb(0x01, &sc520_mmcr->cpuctl);	/* set it to 100 MHz and write back */
65 		printf("## CPU Speed set to 100MHz\n");
66 		gd->cpu_clk = 100000000;
67 	}
68 
69 
70 	/* wait at least one millisecond */
71 	asm("movl	$0x2000,%%ecx\n"
72 	    "0:		pushl %%ecx\n"
73 	    "popl	%%ecx\n"
74 	    "loop 0b\n": : : "ecx");
75 
76 	/* turn on the SDRAM write buffer */
77 	writeb(0x11, &sc520_mmcr->dbctl);
78 
79 	/* turn on the cache and disable write through */
80 	asm("movl	%%cr0, %%eax\n"
81 	    "andl	$0x9fffffff, %%eax\n"
82 	    "movl	%%eax, %%cr0\n"  : : : "eax");
83 }
84 
init_sc520_dram(void)85 unsigned long init_sc520_dram(void)
86 {
87 	bd_t *bd = gd->bd;
88 
89 	u32 dram_present=0;
90 	u32 dram_ctrl;
91 
92 #ifdef CONFIG_SYS_SDRAM_DRCTMCTL
93 	/* these memory control registers are set up in the assember part,
94 	 * in sc520_asm.S, during 'mem_init'.  If we muck with them here,
95 	 * after we are running a stack in RAM, we have troubles.  Besides,
96 	 * these refresh and delay values are better ? simply specified
97 	 * outright in the include/configs/{cfg} file since the HW designer
98 	 * simply dictates it.
99 	 */
100 #else
101 	u8 tmp;
102 	u8 val;
103 
104 	int cas_precharge_delay = CONFIG_SYS_SDRAM_PRECHARGE_DELAY;
105 	int refresh_rate        = CONFIG_SYS_SDRAM_REFRESH_RATE;
106 	int ras_cas_delay       = CONFIG_SYS_SDRAM_RAS_CAS_DELAY;
107 
108 	/* set SDRAM speed here */
109 
110 	refresh_rate/=78;
111 	if (refresh_rate<=1) {
112 		val = 0;  /* 7.8us */
113 	} else if (refresh_rate==2) {
114 		val = 1;  /* 15.6us */
115 	} else if (refresh_rate==3 || refresh_rate==4) {
116 		val = 2;  /* 31.2us */
117 	} else {
118 		val = 3;  /* 62.4us */
119 	}
120 
121 	tmp = (readb(&sc520_mmcr->drcctl) & 0xcf) | (val<<4);
122 	writeb(tmp, &sc520_mmcr->drcctl);
123 
124 	val = readb(&sc520_mmcr->drctmctl) & 0xf0;
125 
126 	if (cas_precharge_delay==3) {
127 		val |= 0x04;   /* 3T */
128 	} else if (cas_precharge_delay==4) {
129 		val |= 0x08;   /* 4T */
130 	} else if (cas_precharge_delay>4) {
131 		val |= 0x0c;
132 	}
133 
134 	if (ras_cas_delay > 3) {
135 		val |= 2;
136 	} else {
137 		val |= 1;
138 	}
139 	writeb(val, &c520_mmcr->drctmctl);
140 #endif
141 
142 	/* We read-back the configuration of the dram
143 	 * controller that the assembly code wrote */
144 	dram_ctrl = readl(&sc520_mmcr->drcbendadr);
145 
146 	bd->bi_dram[0].start = 0;
147 	if (dram_ctrl & 0x80) {
148 		/* bank 0 enabled */
149 		dram_present = bd->bi_dram[1].start = (dram_ctrl & 0x7f) << 22;
150 		bd->bi_dram[0].size = bd->bi_dram[1].start;
151 
152 	} else {
153 		bd->bi_dram[0].size = 0;
154 		bd->bi_dram[1].start = bd->bi_dram[0].start;
155 	}
156 
157 	if (dram_ctrl & 0x8000) {
158 		/* bank 1 enabled */
159 		dram_present = bd->bi_dram[2].start = (dram_ctrl & 0x7f00) << 14;
160 		bd->bi_dram[1].size = bd->bi_dram[2].start -  bd->bi_dram[1].start;
161 	} else {
162 		bd->bi_dram[1].size = 0;
163 		bd->bi_dram[2].start = bd->bi_dram[1].start;
164 	}
165 
166 	if (dram_ctrl & 0x800000) {
167 		/* bank 2 enabled */
168 		dram_present = bd->bi_dram[3].start = (dram_ctrl & 0x7f0000) << 6;
169 		bd->bi_dram[2].size = bd->bi_dram[3].start -  bd->bi_dram[2].start;
170 	} else {
171 		bd->bi_dram[2].size = 0;
172 		bd->bi_dram[3].start = bd->bi_dram[2].start;
173 	}
174 
175 	if (dram_ctrl & 0x80000000) {
176 		/* bank 3 enabled */
177 		dram_present  = (dram_ctrl & 0x7f000000) >> 2;
178 		bd->bi_dram[3].size = dram_present -  bd->bi_dram[3].start;
179 	} else {
180 		bd->bi_dram[3].size = 0;
181 	}
182 
183 
184 #if 0
185 	printf("Configured %d bytes of dram\n", dram_present);
186 #endif
187 	gd->ram_size = dram_present;
188 
189 	return dram_present;
190 }
191 
192 #ifdef CONFIG_SYS_SC520_RESET
reset_cpu(ulong addr)193 void reset_cpu(ulong addr)
194 {
195 	printf("Resetting using SC520 MMCR\n");
196 	/* Write a '1' to the SYS_RST of the RESCFG MMCR */
197 	writeb(0x01, &sc520_mmcr->rescfg);
198 
199 	/* NOTREACHED */
200 }
201 #endif
202