Tomato 1.28
[tomato.git] / release / src / shared / min_osl.c
blobd50a7fbc14ed9c97de97d1156a3005aa7fc0a01c
1 /*
2 * Initialization and support routines for self-booting
3 * compressed image.
5 * Copyright 2005, Broadcom Corporation
6 * All Rights Reserved.
7 *
8 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
9 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
10 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
11 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
13 * $Id: min_osl.c,v 1.1.1.3 2005/03/07 07:31:12 kanki Exp $
16 #include <osl.h>
17 #include <sbutils.h>
18 #include <bcmutils.h>
19 #include <hndmips.h>
21 /* Cache support */
23 /* Cache and line sizes */
24 static uint icache_size, ic_lsize, dcache_size, dc_lsize;
26 static void
27 _change_cachability(uint32 cm)
29 uint32 prid, c0reg;
31 c0reg = MFC0(C0_CONFIG, 0);
32 c0reg &= ~CONF_CM_CMASK;
33 c0reg |= (cm & CONF_CM_CMASK);
34 MTC0(C0_CONFIG, 0, c0reg);
35 prid = MFC0(C0_PRID, 0);
36 if ((prid & (PRID_COMP_MASK | PRID_IMP_MASK)) ==
37 (PRID_COMP_BROADCOM | PRID_IMP_BCM3302)) {
38 c0reg = MFC0(C0_BROADCOM, 0);
39 /* Enable icache */
40 c0reg |= (1 << 31);
41 /* Enable dcache */
42 c0reg |= (1 << 30);
43 MTC0(C0_BROADCOM, 0 , c0reg);
46 static void (*change_cachability)(uint32);
48 void
49 caches_on(void)
51 uint32 config1;
52 uint start, end, size, lsize;
54 /* Save cache config */
55 config1 = MFC0(C0_CONFIG, 1);
57 icache_probe(config1, &size, &lsize);
58 icache_size = size;
59 ic_lsize = lsize;
61 dcache_probe(config1, &size, &lsize);
62 dcache_size = size;
63 dc_lsize = lsize;
65 if ((MFC0(C0_CONFIG, 0) & CONF_CM_CMASK) != CONF_CM_UNCACHED) {
66 blast_dcache();
67 blast_icache();
68 return;
71 /* init icache */
72 start = KSEG0;
73 end = (start + icache_size);
74 MTC0(C0_TAGLO, 0, 0);
75 MTC0(C0_TAGHI, 0, 0);
76 while (start < end) {
77 cache_unroll(start, Index_Store_Tag_I);
78 start += ic_lsize;
81 /* init dcache */
82 start = KSEG0;
83 end = (start + dcache_size);
84 MTC0(C0_TAGLO, 0, 0);
85 MTC0(C0_TAGHI, 0, 0);
86 while (start < end) {
87 cache_unroll(start, Index_Store_Tag_D);
88 start += dc_lsize;
91 /* Must be in KSEG1 to change cachability */
92 change_cachability = (void (*)(uint32)) KSEG1ADDR(_change_cachability);
93 change_cachability(CONF_CM_CACHABLE_NONCOHERENT);
97 #define BCM4710_DUMMY_RREG() (((sbconfig_t *)(KSEG1ADDR(0x18000000 + SBCONFIGOFF)))->sbimstate)
99 void
100 blast_dcache(void)
102 uint32 start, end;
104 start = KSEG0;
105 end = start + dcache_size;
107 while(start < end) {
108 BCM4710_DUMMY_RREG();
109 cache_unroll(start, Index_Writeback_Inv_D);
110 start += dc_lsize;
114 void
115 blast_icache(void)
117 uint32 start, end;
119 start = KSEG0;
120 end = start + icache_size;
122 while(start < end) {
123 cache_unroll(start, Index_Invalidate_I);
124 start += ic_lsize;
128 /* uart output */
130 struct serial_struct {
131 unsigned char *iomem_base;
132 unsigned short iomem_reg_shift;
133 int irq;
134 int baud_base;
137 static struct serial_struct hndrte_uart;
139 #define LOG_BUF_LEN (1024)
140 #define LOG_BUF_MASK (LOG_BUF_LEN-1)
141 static char log_buf[LOG_BUF_LEN];
142 static unsigned long log_start;
145 static inline int
146 serial_in(struct serial_struct *info, int offset)
148 return ((int)R_REG((uint8 *)(info->iomem_base + (offset << info->iomem_reg_shift))));
151 static inline void
152 serial_out(struct serial_struct *info, int offset, int value)
154 W_REG((uint8 *)(info->iomem_base + (offset << info->iomem_reg_shift)), value);
155 *((volatile unsigned int *) KSEG1ADDR(0x18000000));
158 void
159 putc(int c)
161 /* CR before LF */
162 if (c == '\n')
163 putc('\r');
165 /* Store in log buffer */
166 *((char *) KSEG1ADDR(&log_buf[log_start])) = (char) c;
167 log_start = (log_start + 1) & LOG_BUF_MASK;
169 /* No UART */
170 if (!hndrte_uart.iomem_base)
171 return;
173 while (!(serial_in(&hndrte_uart, UART_LSR) & UART_LSR_THRE));
174 serial_out(&hndrte_uart, UART_TX, c);
177 /* assert & debugging */
180 /* general purpose memory allocation */
182 extern char text_start[], text_end[];
183 extern char data_start[], data_end[];
184 extern char bss_start[], bss_end[];
186 static ulong free_mem_ptr = 0;
187 static ulong free_mem_ptr_end = 0;
189 void *
190 malloc(uint size)
192 void *p;
194 /* Sanity check */
195 if (size < 0)
196 printf("Malloc error");
197 if (free_mem_ptr == 0)
198 printf("Memory error");
200 /* Align */
201 free_mem_ptr = (free_mem_ptr + 3) & ~3;
203 p = (void *) free_mem_ptr;
204 free_mem_ptr += size;
206 if (free_mem_ptr >= free_mem_ptr_end)
207 printf("Out of memory");
209 return p;
213 free(void *where)
215 return 0;
218 /* microsecond delay */
220 /* Default to 125 MHz */
221 static unsigned long cpu_clock = 125000000;
223 static inline void
224 __delay(uint loops)
226 __asm__ __volatile__ (
227 ".set\tnoreorder\n"
228 "1:\tbnez\t%0,1b\n\t"
229 "subu\t%0,1\n\t"
230 ".set\treorder"
231 :"=r" (loops)
232 :"0" (loops));
235 void
236 udelay(uint us)
238 uint loops;
240 loops = cpu_clock / 5;
242 __delay(loops);
245 extern char *
246 getvar(char *vars, char *name)
248 return NULL;
251 extern int
252 getintvar(char *vars, char *name)
254 return 0;
257 /* No trap handling in self-decompressing boots */
258 extern void trap_init(void);
260 void
261 trap_init(void)
266 static void
267 serial_add(void *regs, uint irq, uint baud_base, uint reg_shift)
269 int quot;
271 if (hndrte_uart.iomem_base)
272 return;
274 hndrte_uart.iomem_base = regs;
275 hndrte_uart.irq = irq;
276 hndrte_uart.baud_base = baud_base / 16;
277 hndrte_uart.iomem_reg_shift = reg_shift;
279 /* Set baud and 8N1 */
280 quot = (hndrte_uart.baud_base + 57600) / 115200;
281 serial_out(&hndrte_uart, UART_LCR, UART_LCR_DLAB);
282 serial_out(&hndrte_uart, UART_DLL, quot & 0xff);
283 serial_out(&hndrte_uart, UART_DLM, quot >> 8);
284 serial_out(&hndrte_uart, UART_LCR, UART_LCR_WLEN8);
286 /* According to the Synopsys website: "the serial clock
287 * modules must have time to see new register values
288 * and reset their respective state machines. This
289 * total time is guaranteed to be no more than
290 * (2 * baud divisor * 16) clock cycles of the slower
291 * of the two system clocks. No data should be transmitted
292 * or received before this maximum time expires."
294 udelay(1000);
298 void *
299 osl_init()
301 uint32 c0reg;
302 void *sbh;
304 /* Disable interrupts */
305 c0reg = MFC0(C0_STATUS, 0);
306 c0reg &= ~ST0_IE;
307 MTC0(C0_STATUS, 0 , c0reg);
309 /* Scan backplane */
310 sbh = sb_kattach();
312 sb_mips_init(sbh);
313 sb_serial_init(sbh, serial_add);
315 /* Init malloc */
316 free_mem_ptr = (ulong) bss_end;
317 free_mem_ptr_end = ((ulong)&c0reg) - 8192; /* Enough stack? */
319 return (sbh);