2 * Initialization and support routines for self-booting compressed
5 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
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 $
32 /* Global ASSERT type */
33 uint32 g_assert_type
= 0;
38 /* Cache and line sizes */
39 uint __icache_size
, __ic_lsize
, __dcache_size
, __dc_lsize
;
42 _change_cachability(uint32 cm
)
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);
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
);
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
);
74 dcache_probe(config1
, &size
, &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
) {
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
) {
90 start
= KSEG0ADDR(caches_on
) & 0xff800000;
91 end
= (start
+ __icache_size
);
95 cache_op(start
, Index_Store_Tag_I
);
100 start
= KSEG0ADDR(caches_on
) & 0xff800000;
101 end
= (start
+ __dcache_size
);
103 /* mips32r2 has the data tags in select 2 */
104 MTC0(C0_TAGLO
, 2, 0);
105 MTC0(C0_TAGHI
, 2, 0);
107 MTC0(C0_TAGLO
, 0, 0);
108 MTC0(C0_TAGHI
, 0, 0);
110 while (start
< end
) {
111 cache_op(start
, Index_Store_Tag_D
);
116 /* Must be in KSEG1 to change cachability */
117 change_cachability
= (void (*)(uint32
))KSEG1ADDR(_change_cachability
);
118 change_cachability(CONF_CM_CACHABLE_NONCOHERENT
);
127 start
= KSEG0ADDR(blast_dcache
) & 0xff800000;
128 end
= start
+ __dcache_size
;
130 while (start
< end
) {
131 cache_op(start
, Index_Writeback_Inv_D
);
141 start
= KSEG0ADDR(blast_icache
) & 0xff800000;
142 end
= start
+ __icache_size
;
144 while (start
< end
) {
145 cache_op(start
, Index_Invalidate_I
);
153 struct serial_struct
{
154 unsigned char *reg_base
;
155 unsigned short reg_shift
;
160 static struct serial_struct min_uart
;
163 #define LOG_BUF_LEN (16 * 1024)
165 #define LOG_BUF_LEN (1024)
167 #define LOG_BUF_MASK (LOG_BUF_LEN-1)
168 static unsigned long log_idx
;
169 static char log_buf
[LOG_BUF_LEN
];
173 serial_in(struct serial_struct
*info
, int offset
)
175 return ((int)R_REG(NULL
, (uint8
*)(info
->reg_base
+ (offset
<< info
->reg_shift
))));
179 serial_out(struct serial_struct
*info
, int offset
, int value
)
181 W_REG(NULL
, (uint8
*)(info
->reg_base
+ (offset
<< info
->reg_shift
)), value
);
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
;
199 if (!min_uart
.reg_base
)
202 while (!(serial_in(&min_uart
, UART_LSR
) & UART_LSR_THRE
));
203 serial_out(&min_uart
, UART_TX
, c
);
206 /* assert & debugging */
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;
232 printf("Malloc error\n");
233 if (free_mem_ptr
== 0)
234 printf("Memory error\n");
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");
254 /* get processor cycle count */
257 #define get_cycle_count get_c0_count
258 #elif defined(__arm__) || defined(__thumb__) || defined(__thumb2__)
259 #define get_cycle_count get_arm_cyclecount
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;
280 curr
= get_cycle_count();
281 lim
= curr
+ (us
* c0counts_per_us
);
284 while (get_cycle_count() > curr
)
287 while (get_cycle_count() < lim
)
293 /* No trap handling in self-decompressing boots */
294 extern void trap_init(void);
301 #endif /* !MIN_DO_TRAP */
304 serial_add(void *regs
, uint irq
, uint baud_base
, uint reg_shift
)
308 if (min_uart
.reg_base
)
311 min_uart
.reg_base
= regs
;
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."
338 uint32 c0counts_per_cycle
;
342 sih
= si_kattach(SI_OSH
);
348 si_mips_init(sih
, 0);
349 c0counts_per_cycle
= 2;
350 #elif defined(__arm__) || defined(__thumb__) || defined(__thumb2__)
352 c0counts_per_cycle
= 1;
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
);
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
)