BCM WL 6.30.102.9 (r366174)
[tomato.git] / release / src-rt / shared / min_osl.c
blob72eacad4ab7ca135401d661905b6fb60ff952154
1 /*
2 * Initialization and support routines for self-booting compressed
3 * image.
5 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
14 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
16 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 * $Id: min_osl.c,v 1.28 2009-07-10 22:43:40 Exp $
22 #include <typedefs.h>
23 #include <bcmdefs.h>
24 #include <osl.h>
25 #include <bcmdevs.h>
26 #include <bcmutils.h>
27 #include <siutils.h>
28 #include <hndcpu.h>
29 #include <sbchipc.h>
30 #include <hndchipc.h>
32 /* Global ASSERT type */
33 uint32 g_assert_type = 0;
35 #ifdef mips
36 /* Cache support */
38 /* Cache and line sizes */
39 uint __icache_size, __ic_lsize, __dcache_size, __dc_lsize;
41 static void
42 _change_cachability(uint32 cm)
44 uint32 prid, c0reg;
46 c0reg = MFC0(C0_CONFIG, 0);
47 c0reg &= ~CONF_CM_CMASK;
48 c0reg |= (cm & CONF_CM_CMASK);
49 MTC0(C0_CONFIG, 0, c0reg);
50 prid = MFC0(C0_PRID, 0);
51 if (BCM330X(prid)) {
52 c0reg = MFC0(C0_BROADCOM, 0);
53 /* Enable icache & dcache */
54 c0reg |= BRCM_IC_ENABLE | BRCM_DC_ENABLE;
55 MTC0(C0_BROADCOM, 0, c0reg);
58 static void (*change_cachability)(uint32);
60 void
61 caches_on(void)
63 uint32 config, config1, r2, tmp;
64 uint start, end, size, lsize;
66 config = MFC0(C0_CONFIG, 0);
67 r2 = config & CONF_AR;
68 config1 = MFC0(C0_CONFIG, 1);
70 icache_probe(config1, &size, &lsize);
71 __icache_size = size;
72 __ic_lsize = lsize;
74 dcache_probe(config1, &size, &lsize);
75 __dcache_size = size;
76 __dc_lsize = lsize;
78 /* If caches are not in the default state then
79 * presume that caches are already init'd
81 if ((config & CONF_CM_CMASK) != CONF_CM_UNCACHED) {
82 blast_dcache();
83 blast_icache();
84 return;
87 tmp = R_REG(NULL, (uint32 *)(OSL_UNCACHED(SI_ENUM_BASE + CC_CHIPID)));
88 if (((tmp & CID_PKG_MASK) >> CID_PKG_SHIFT) != HDLSIM_PKG_ID) {
89 /* init icache */
90 start = KSEG0ADDR(caches_on) & 0xff800000;
91 end = (start + __icache_size);
92 MTC0(C0_TAGLO, 0, 0);
93 MTC0(C0_TAGHI, 0, 0);
94 while (start < end) {
95 cache_op(start, Index_Store_Tag_I);
96 start += __ic_lsize;
99 /* init dcache */
100 start = KSEG0ADDR(caches_on) & 0xff800000;
101 end = (start + __dcache_size);
102 if (r2) {
103 /* mips32r2 has the data tags in select 2 */
104 MTC0(C0_TAGLO, 2, 0);
105 MTC0(C0_TAGHI, 2, 0);
106 } else {
107 MTC0(C0_TAGLO, 0, 0);
108 MTC0(C0_TAGHI, 0, 0);
110 while (start < end) {
111 cache_op(start, Index_Store_Tag_D);
112 start += __dc_lsize;
116 /* Must be in KSEG1 to change cachability */
117 change_cachability = (void (*)(uint32))KSEG1ADDR(_change_cachability);
118 change_cachability(CONF_CM_CACHABLE_NONCOHERENT);
122 void
123 blast_dcache(void)
125 uint32 start, end;
127 start = KSEG0ADDR(blast_dcache) & 0xff800000;
128 end = start + __dcache_size;
130 while (start < end) {
131 cache_op(start, Index_Writeback_Inv_D);
132 start += __dc_lsize;
136 void
137 blast_icache(void)
139 uint32 start, end;
141 start = KSEG0ADDR(blast_icache) & 0xff800000;
142 end = start + __icache_size;
144 while (start < end) {
145 cache_op(start, Index_Invalidate_I);
146 start += __ic_lsize;
149 #endif /* mips */
151 /* uart output */
153 struct serial_struct {
154 unsigned char *reg_base;
155 unsigned short reg_shift;
156 int irq;
157 int baud_base;
160 static struct serial_struct min_uart;
162 #ifdef BCMDBG
163 #define LOG_BUF_LEN (16 * 1024)
164 #else
165 #define LOG_BUF_LEN (1024)
166 #endif
167 #define LOG_BUF_MASK (LOG_BUF_LEN-1)
168 static unsigned long log_idx;
169 static char log_buf[LOG_BUF_LEN];
172 static inline int
173 serial_in(struct serial_struct *info, int offset)
175 return ((int)R_REG(NULL, (uint8 *)(info->reg_base + (offset << info->reg_shift))));
178 static inline void
179 serial_out(struct serial_struct *info, int offset, int value)
181 W_REG(NULL, (uint8 *)(info->reg_base + (offset << info->reg_shift)), value);
184 void
185 putc(int c)
187 uint32 idx;
189 /* CR before LF */
190 if (c == '\n')
191 putc('\r');
193 /* Store in log buffer */
194 idx = *((uint32 *)OSL_UNCACHED((uintptr)&log_idx));
195 *((char *)OSL_UNCACHED(&log_buf[idx])) = (char)c;
196 *((uint32 *)OSL_UNCACHED((uintptr)&log_idx)) = (idx + 1) & LOG_BUF_MASK;
198 /* No UART */
199 if (!min_uart.reg_base)
200 return;
202 while (!(serial_in(&min_uart, UART_LSR) & UART_LSR_THRE));
203 serial_out(&min_uart, UART_TX, c);
206 /* assert & debugging */
208 #ifdef BCMDBG_ASSERT
209 void
210 assfail(char *exp, char *file, int line)
212 printf("ASSERT %s file %s line %d\n", exp, file, line);
214 #endif /* BCMDBG_ASSERT */
216 /* general purpose memory allocation */
218 extern char text_start[], text_end[];
219 extern char data_start[], data_end[];
220 extern char bss_start[], bss_end[];
222 static ulong free_mem_ptr = 0;
223 static ulong free_mem_ptr_end = 0;
225 void *
226 malloc(uint size)
228 void *p;
230 /* Sanity check */
231 if (size < 0)
232 printf("Malloc error\n");
233 if (free_mem_ptr == 0)
234 printf("Memory error\n");
236 /* Align */
237 free_mem_ptr = (free_mem_ptr + 3) & ~3;
239 p = (void *) free_mem_ptr;
240 free_mem_ptr += size;
242 if (free_mem_ptr >= free_mem_ptr_end)
243 printf("Out of memory\n");
245 return p;
249 free(void *where)
251 return 0;
254 /* get processor cycle count */
256 #if defined(mips)
257 #define get_cycle_count get_c0_count
258 #elif defined(__arm__) || defined(__thumb__) || defined(__thumb2__)
259 #define get_cycle_count get_arm_cyclecount
260 #endif
262 uint32
263 osl_getcycles(void)
265 return get_cycle_count();
268 /* microsecond delay */
270 /* Default to 125 MHz */
271 static uint32 cpu_clock = 125000000;
272 static uint32 c0counts_per_us = 125000000 / 2000000;
273 static uint32 c0counts_per_ms = 125000000 / 2000;
275 void
276 udelay(uint32 us)
278 uint32 curr, lim;
280 curr = get_cycle_count();
281 lim = curr + (us * c0counts_per_us);
283 if (lim < curr)
284 while (get_cycle_count() > curr)
287 while (get_cycle_count() < lim)
291 #ifndef MIN_DO_TRAP
293 /* No trap handling in self-decompressing boots */
294 extern void trap_init(void);
296 void
297 trap_init(void)
301 #endif /* !MIN_DO_TRAP */
303 static void
304 serial_add(void *regs, uint irq, uint baud_base, uint reg_shift)
306 int quot;
308 if (min_uart.reg_base)
309 return;
311 min_uart.reg_base = regs;
312 min_uart.irq = irq;
313 min_uart.baud_base = baud_base / 16;
314 min_uart.reg_shift = reg_shift;
316 /* Set baud and 8N1 */
317 quot = (min_uart.baud_base + 57600) / 115200;
318 serial_out(&min_uart, UART_LCR, UART_LCR_DLAB);
319 serial_out(&min_uart, UART_DLL, quot & 0xff);
320 serial_out(&min_uart, UART_DLM, quot >> 8);
321 serial_out(&min_uart, UART_LCR, UART_LCR_WLEN8);
323 /* According to the Synopsys website: "the serial clock
324 * modules must have time to see new register values
325 * and reset their respective state machines. This
326 * total time is guaranteed to be no more than
327 * (2 * baud divisor * 16) clock cycles of the slower
328 * of the two system clocks. No data should be transmitted
329 * or received before this maximum time expires."
331 udelay(1000);
335 void *
336 osl_init()
338 uint32 c0counts_per_cycle;
339 si_t *sih;
341 /* Scan backplane */
342 sih = si_kattach(SI_OSH);
344 if (sih == NULL)
345 return NULL;
347 #if defined(mips)
348 si_mips_init(sih, 0);
349 c0counts_per_cycle = 2;
350 #elif defined(__arm__) || defined(__thumb__) || defined(__thumb2__)
351 si_arm_init(sih);
352 c0counts_per_cycle = 1;
353 #else
354 #error "Unknow CPU"
355 #endif
356 cpu_clock = si_cpu_clock(sih);
357 c0counts_per_us = cpu_clock / (1000000 * c0counts_per_cycle);
358 c0counts_per_ms = si_cpu_clock(sih) / (1000 * c0counts_per_cycle);
360 /* Don't really need to talk to the uart in simulation */
361 if ((sih->chippkg != HDLSIM_PKG_ID) && (sih->chippkg != HWSIM_PKG_ID))
362 si_serial_init(sih, serial_add);
364 /* Init malloc */
365 free_mem_ptr = (ulong) bss_end;
366 free_mem_ptr_end = ((ulong)&sih) - 8192; /* Enough stack? */
368 return ((void *)sih);
371 /* translate bcmerros */
373 osl_error(int bcmerror)
375 if (bcmerror)
376 return -1;
377 else
378 return 0;