Updates to Tomato RAF including NGINX && PHP
[tomato.git] / release / src / shared / min_osl.c
blob25d6b4918e22c347137320f9b4121203073662e5
1 /*
2 * Initialization and support routines for self-booting
3 * compressed image.
5 * Copyright 2004, 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$
16 #include <typedefs.h>
17 #include <bcmdefs.h>
18 #include <osl.h>
19 #include <bcmutils.h>
20 #include <sbutils.h>
21 #include <hndcpu.h>
22 #include <sbchipc.h>
23 #include <hndchipc.h>
25 /* Cache support */
27 /* Cache and line sizes */
28 static uint icache_size, ic_lsize, dcache_size, dc_lsize;
30 static void
31 _change_cachability(uint32 cm)
33 uint32 prid, c0reg;
35 c0reg = MFC0(C0_CONFIG, 0);
36 c0reg &= ~CONF_CM_CMASK;
37 c0reg |= (cm & CONF_CM_CMASK);
38 MTC0(C0_CONFIG, 0, c0reg);
39 prid = MFC0(C0_PRID, 0);
40 if ((prid & (PRID_COMP_MASK | PRID_IMP_MASK)) ==
41 (PRID_COMP_BROADCOM | PRID_IMP_BCM3302)) {
42 c0reg = MFC0(C0_BROADCOM, 0);
43 /* Enable icache & dcache */
44 c0reg |= BRCM_IC_ENABLE | BRCM_DC_ENABLE;
45 MTC0(C0_BROADCOM, 0, c0reg);
48 static void (*change_cachability)(uint32);
50 void
51 caches_on(void)
53 uint32 config1;
54 uint start, end, size, lsize;
56 /* Save cache config */
57 config1 = MFC0(C0_CONFIG, 1);
59 icache_probe(config1, &size, &lsize);
60 icache_size = size;
61 ic_lsize = lsize;
63 dcache_probe(config1, &size, &lsize);
64 dcache_size = size;
65 dc_lsize = lsize;
67 /* If caches are not in the default state then
68 * presume that caches are already init'd
70 if ((MFC0(C0_CONFIG, 0) & CONF_CM_CMASK) != CONF_CM_UNCACHED) {
71 blast_dcache();
72 blast_icache();
73 return;
76 /* init icache */
77 start = KSEG0;
78 end = (start + icache_size);
79 MTC0(C0_TAGLO, 0, 0);
80 MTC0(C0_TAGHI, 0, 0);
81 while (start < end) {
82 cache_op(start, Index_Store_Tag_I);
83 start += ic_lsize;
86 /* init dcache */
87 start = KSEG0;
88 end = (start + dcache_size);
89 MTC0(C0_TAGLO, 0, 0);
90 MTC0(C0_TAGHI, 0, 0);
91 while (start < end) {
92 cache_op(start, Index_Store_Tag_D);
93 start += dc_lsize;
96 /* Must be in KSEG1 to change cachability */
97 change_cachability = (void (*)(uint32)) KSEG1ADDR(_change_cachability);
98 change_cachability(CONF_CM_CACHABLE_NONCOHERENT);
102 #define BCM4710_DUMMY_RREG() (((sbconfig_t *)(KSEG1ADDR(SB_ENUM_BASE + SBCONFIGOFF)))->sbimstate)
104 void
105 blast_dcache(void)
107 uint32 start, end;
109 start = KSEG0;
110 end = start + dcache_size;
112 while (start < end) {
113 BCM4710_DUMMY_RREG();
114 cache_op(start, Index_Writeback_Inv_D);
115 start += dc_lsize;
119 void
120 blast_icache(void)
122 uint32 start, end;
124 start = KSEG0;
125 end = start + icache_size;
127 while (start < end) {
128 cache_op(start, Index_Invalidate_I);
129 start += ic_lsize;
133 /* uart output */
135 struct serial_struct {
136 unsigned char *reg_base;
137 unsigned short reg_shift;
138 int irq;
139 int baud_base;
142 static struct serial_struct min_uart;
144 #define LOG_BUF_LEN (1024)
145 #define LOG_BUF_MASK (LOG_BUF_LEN-1)
146 static char log_buf[LOG_BUF_LEN];
147 static unsigned long log_start;
150 static inline int
151 serial_in(struct serial_struct *info, int offset)
153 return ((int)R_REG(NULL, (uint8 *)(info->reg_base + (offset << info->reg_shift))));
156 static inline void
157 serial_out(struct serial_struct *info, int offset, int value)
159 W_REG(NULL, (uint8 *)(info->reg_base + (offset << info->reg_shift)), value);
160 *((volatile unsigned int *) KSEG1ADDR(SB_ENUM_BASE));
163 void
164 putc(int c)
166 /* CR before LF */
167 if (c == '\n')
168 putc('\r');
170 /* Store in log buffer */
171 *((char *) KSEG1ADDR(&log_buf[log_start])) = (char) c;
172 log_start = (log_start + 1) & LOG_BUF_MASK;
174 /* No UART */
175 if (!min_uart.reg_base)
176 return;
178 while (!(serial_in(&min_uart, UART_LSR) & UART_LSR_THRE));
179 serial_out(&min_uart, UART_TX, c);
182 /* assert & debugging */
184 #ifdef BCMDBG_ASSERT
185 void
186 assfail(char *exp, char *file, int line)
188 printf("ASSERT %s file %s line %d\n", exp, file, line);
190 #endif /* BCMDBG_ASSERT */
192 /* general purpose memory allocation */
194 extern char text_start[], text_end[];
195 extern char data_start[], data_end[];
196 extern char bss_start[], bss_end[];
198 static ulong free_mem_ptr = 0;
199 static ulong free_mem_ptr_end = 0;
201 void *
202 malloc(uint size)
204 void *p;
206 /* Sanity check */
207 if (size < 0)
208 printf("Malloc error");
209 if (free_mem_ptr == 0)
210 printf("Memory error");
212 /* Align */
213 free_mem_ptr = (free_mem_ptr + 3) & ~3;
215 p = (void *) free_mem_ptr;
216 free_mem_ptr += size;
218 if (free_mem_ptr >= free_mem_ptr_end)
219 printf("Out of memory");
221 return p;
225 free(void *where)
227 return 0;
230 /* microsecond delay */
232 /* Default to 125 MHz */
233 static unsigned long cpu_clock = 125000000;
235 static inline void
236 __delay(uint loops)
238 __asm__ __volatile__(
239 ".set\tnoreorder\n"
240 "1:\tbnez\t%0,1b\n\t"
241 "subu\t%0,1\n\t"
242 ".set\treorder"
243 :"=r" (loops)
244 :"0" (loops));
247 void
248 udelay(uint us)
250 uint loops;
252 loops = cpu_clock / 5;
254 __delay(loops);
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 (min_uart.reg_base)
272 return;
274 min_uart.reg_base = regs;
275 min_uart.irq = irq;
276 min_uart.baud_base = baud_base / 16;
277 min_uart.reg_shift = reg_shift;
279 /* Set baud and 8N1 */
280 quot = (min_uart.baud_base + 57600) / 115200;
281 serial_out(&min_uart, UART_LCR, UART_LCR_DLAB);
282 serial_out(&min_uart, UART_DLL, quot & 0xff);
283 serial_out(&min_uart, UART_DLM, quot >> 8);
284 serial_out(&min_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 sb_t *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(SB_OSH);
312 sb_mips_init(sbh, 0);
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 ((void *)sbh);
322 /* translate bcmerros */
324 osl_error(int bcmerror)
326 if (bcmerror)
327 return -1;
328 else
329 return 0;