1/*  *********************************************************************
2    *  SB1250 Board Support Package
3    *
4    *  Board-specific initialization		File: BCM91125F_INIT.S
5    *
6    *  This module contains the assembly-language part of the init
7    *  code for this board support package.  The routine
8    *  "board_earlyinit" lives here.
9    *
10    *  Author:  Mitch Lichtenberg
11    *
12    *********************************************************************
13    *
14    *  Copyright 2000,2001,2002,2003
15    *  Broadcom Corporation. All rights reserved.
16    *
17    *  This software is furnished under license and may be used and
18    *  copied only in accordance with the following terms and
19    *  conditions.  Subject to these conditions, you may download,
20    *  copy, install, use, modify and distribute modified or unmodified
21    *  copies of this software in source and/or binary form.  No title
22    *  or ownership is transferred hereby.
23    *
24    *  1) Any source code used, modified or distributed must reproduce
25    *     and retain this copyright notice and list of conditions
26    *     as they appear in the source file.
27    *
28    *  2) No right is granted to use any trade name, trademark, or
29    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
30    *     name may not be used to endorse or promote products derived
31    *     from this software without the prior written permission of
32    *     Broadcom Corporation.
33    *
34    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
35    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
36    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
37    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
38    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
39    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
40    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
41    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
44    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
45    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
46    *     THE POSSIBILITY OF SUCH DAMAGE.
47    ********************************************************************* */
48
49
50#include "sbmips.h"
51#include "sb1250_genbus.h"
52#include "sb1250_regs.h"
53#include "sb1250_scd.h"
54#include "bsp_config.h"
55#include "cpu_config.h"
56#include "mipsmacros.h"
57#include "bcm91125f.h"
58#include "sb1250_draminit.h"
59#include "sb1250_smbus.h"
60
61		.text
62
63/*  *********************************************************************
64    *  Macros
65    ********************************************************************* */
66
67/*
68 * Define this to send the LED messages to the serial port instead
69 * of to the LEDs.
70 */
71
72/*#define _SERIAL_PORT_LEDS_*/
73
74#ifdef _SERIAL_PORT_LEDS_
75#include "sb1250_uart.h"		/* need this for serial defs */
76#endif
77
78
79/*  *********************************************************************
80    *  BOARD_EARLYINIT()
81    *
82    *  Initialize board registers.  This is the earliest
83    *  time the BSP gets control.  This routine cannot assume that
84    *  memory is operational, and therefore all code in this routine
85    *  must run from registers only.  The $ra register must not
86    *  be modified, as it contains the return address.
87    *
88    *  This routine will be called from uncached space, before
89    *  the caches are initialized.  If you want to make
90    *  subroutine calls from here, you must use the CALLKSEG1 macro.
91    *
92    *  Among other things, this is where the GPIO registers get
93    *  programmed to make on-board LEDs function, or other startup
94    *  that has to be done before anything will work.
95    *
96    *  Input parameters:
97    *  	   nothing
98    *
99    *  Return value:
100    *  	   nothing
101    ********************************************************************* */
102
103LEAF(board_earlyinit)
104
105
106       #
107       # Configure the GPIOs
108       #
109
110		li	t0,PHYS_TO_K1(A_GPIO_DIRECTION)
111		li	t1,GPIO_OUTPUT_MASK
112		sd	t1,0(t0)
113
114		li	t0,PHYS_TO_K1(A_GPIO_INT_TYPE)
115		li	t1,GPIO_INTERRUPT_MASK
116		sd	t1,0(t0)
117
118       #
119       # Turn off the diagnostic LED.
120       #
121		li	t0,PHYS_TO_K1(A_GPIO_PIN_CLR)
122		li	t1,M_GPIO_DEBUG_LED
123		sd	t1,0(t0)
124
125       #
126       # Configure the LEDs
127       #
128
129		li	t0,PHYS_TO_K1(A_IO_EXT_CS_BASE(LEDS_CS))
130		li	t1,LEDS_PHYS >> S_IO_ADDRBASE
131		sd	t1,R_IO_EXT_START_ADDR(t0)
132
133		li	t1,LEDS_SIZE-1	/* Needs to be 1 smaller, se UM for details */
134		sd	t1,R_IO_EXT_MULT_SIZE(t0)
135
136		li	t1,LEDS_TIMING0
137		sd	t1,R_IO_EXT_TIME_CFG0(t0)
138
139		li	t1,LEDS_TIMING1
140		sd	t1,R_IO_EXT_TIME_CFG1(t0)
141
142		li	t1,LEDS_CONFIG
143		sd	t1,R_IO_EXT_CFG(t0)
144
145	#
146	# Configure CS 0 size from 4MB to 16MB
147	#
148		li	t0,PHYS_TO_K1(A_IO_EXT_CS_BASE(BOOTROM_CS))
149
150		li	t1,BOOTROM_SIZE-1
151		sd	t1,R_IO_EXT_MULT_SIZE(t0)
152
153
154
155	/*
156	 * If the CPU is a 1250 or hybrid, certain initialization has
157	 * to be done so that the chip can be used like an 112x.
158	 */
159
160	/* First, figure out what type of SOC we're on. */
161	ld	t1, PHYS_TO_K1(A_SCD_SYSTEM_REVISION)
162	SYS_SOC_TYPE(t3, t1)
163	bne	t3, K_SYS_SOC_TYPE_BCM1250, is_bcm112x
164
165	/*
166	 * We have a 1250 or hybrid.  Initialize registers as appropriate.
167	 */
168
169	/*
170	 * If we're not already running as a uniprocessor, get us there.
171	 */
172	dsrl    t1, t1, S_SYS_PART      # part number now in t1
173	and	t3, t1, 0xf00
174	dsrl	t3, t3, 8		# t3 = numcpus
175
176	ld	t4, PHYS_TO_K1(A_SCD_SYSTEM_CFG)
177	or	t4, t4, M_SYS_SB_SOFTRES
178	xor	t4, t4, M_SYS_SB_SOFTRES
179	sd	t4, PHYS_TO_K1(A_SCD_SYSTEM_CFG)	/* clear soft reset */
180
181	beq	t3, 1, 2f
182
183	or	t4, t4, M_SYS_SB_SOFTRES | M_SYS_UNICPU0
184	sd	t4, PHYS_TO_K1(A_SCD_SYSTEM_CFG)	/* go unicpu */
185	sync
1861:
187	b	1b
1882:
189
190	/*
191	 * Clean up MC 0.
192	 */
193
194	li	t0, PHYS_TO_K1(A_MC_BASE_0)
195	dli	t1, V_MC_CONFIG_DEFAULT | M_MC_ECC_DISABLE | \
196		    V_MC_CS_MODE_MSB_CS
197	sd	t1, R_MC_CONFIG(t0)
198	sd	zero, R_MC_CS_START(t0)
199	sd	zero, R_MC_CS_END(t0)
200	sd	zero, R_MC_CS_INTERLEAVE(t0)
201	sd	zero, R_MC_CS_ATTR(t0)
202	sd	zero, R_MC_TEST_DATA(t0)
203	sd	zero, R_MC_TEST_ECC(t0)
204
205	/*
206	 * Zero out MAC 2's address register.  (This has
207	 * undefined value after reset, but OSes may check
208	 * it on some parts to see if they should init
209	 * the interface.  This is a convenient place
210	 * to zero it.)
211	 */
212
213	li	t0, PHYS_TO_K1(A_MAC_BASE_2)
214	sd	zero, R_MAC_ETHERNET_ADDR(t0)
215
216is_bcm112x:
217
218#ifdef _SERIAL_PORT_LEDS_
219
220	# Program the mode register for 8 bits/char, no parity
221
222		li	t0,PHYS_TO_K1(A_DUART_MODE_REG_1_A)
223		li	t1,V_DUART_BITS_PER_CHAR_8 | V_DUART_PARITY_MODE_NONE
224		sd	t1,(t0)
225
226	# Program the mode register for 1 stop bit, ignore CTS
227
228		li	t0,PHYS_TO_K1(A_DUART_MODE_REG_2_A)
229		li	t1,M_DUART_STOP_BIT_LEN_1
230		sd	t1,(t0)
231
232	# Program the baud rate to 115200
233
234		li	t0,PHYS_TO_K1(A_DUART_CLK_SEL_A)
235		li	t1,V_DUART_BAUD_RATE(115200)
236		sd	t1,(t0)
237
238	# Dont use any interrupts
239
240		li	t0,PHYS_TO_K1(A_DUART_IMR)
241		ld	t1,(t0)
242		and	t1,~M_DUART_IMR_ALL_A
243		sd	t1,(t0)
244
245	# Enable sending and receiving
246
247		li	t0,PHYS_TO_K1(A_DUART_CMD_A)
248		li	t1,M_DUART_RX_EN | M_DUART_TX_EN
249		sd	t1,(t0)
250
251#endif
252
253	j	ra
254
255END(board_earlyinit)
256
257
258/*  *********************************************************************
259    *  BOARD_DRAMINFO
260    *
261    *  Return the address of the DRAM information table
262    *
263    *  Input parameters:
264    *  	   nothing
265    *
266    *  Return value:
267    *  	   v0 - DRAM info table, return 0 to use default table
268    ********************************************************************* */
269
270#define smb_cmd      t9
271#define smb_start    t8
272#define smb_status   t7
273#define smb_data     t6
274#define spd_byte     t4
275#define SMBUS_0_READBYTE(slvaddr,devaddr,result)			\
2761:	ld	t1,(smb_status)	;					\
277	and	t1,M_SMB_BUSY ;						\
278	bnez	t1,1b ;							\
279	li	t1,devaddr ;						\
280	sd	t1,(smb_cmd) ;						\
281	li	t1,(V_SMB_TT(K_SMB_TT_WR1BYTE) | slvaddr) ;		\
282	sd	t1,(smb_start) ;					\
2831:	ld	t1,(smb_status) ;					\
284	and	t1,M_SMB_BUSY ;						\
285	bnez	t1,1b ;							\
286	li	t1,(V_SMB_TT(K_SMB_TT_RD1BYTE) | slvaddr) ;		\
287	sd	t1,(smb_start) ;					\
2881:	ld	t1,(smb_status) ;					\
289	and	t1,M_SMB_BUSY ;						\
290	bnez	t1,1b ;							\
291	ld	t1,(smb_data) ;						\
292	and	t1,0xFF ;						\
293	move	result,t1
294
295LEAF(board_draminfo)
296
297       /*
298	* Check a few bytes to make sure SPD EEPROM contains valid info.  If it does, use it.
299	* if not, use manual tables.  The ATMEL EEPROM is @ chan 0, addr 0x54.
300        */
301
302	        li	smb_cmd,PHYS_TO_K1(A_SMB_CMD_0)
303		li	smb_start,PHYS_TO_K1(A_SMB_START_0)
304		li	smb_status,PHYS_TO_K1(A_SMB_STATUS_0)
305		li	smb_data,PHYS_TO_K1(A_SMB_DATA_0)
306
307	# Initialize smbus chan 0
308	        li	t0,PHYS_TO_K1(A_SMB_FREQ_0)
309		li	t1,K_SMB_FREQ_100KHZ
310		sd	t1,(t0)
311
312	        li	t0,PHYS_TO_K1(A_SMB_CONTROL_0)
313		sd	zero,(t0)
314
315	# Check memory type @ byte 2.  0x07(SDRAM DDR)
316		SMBUS_0_READBYTE(SPDEEPROM_SMBUS_DEV,JEDEC_SPD_MEMTYPE,spd_byte)
317		li	t2,0x07 /*JEDEC SDRAM memory type*/
318		bne	spd_byte,t2,man
319
320	# Check rows @ byte 3.  0x0D(13)
321		SMBUS_0_READBYTE(SPDEEPROM_SMBUS_DEV,JEDEC_SPD_ROWS,spd_byte)
322		li	t2,0x0D  /*There should be 13 rows*/
323		bne	spd_byte,t2,man
324
325	# Check columns @ byte 4.  0x09(9)
326		SMBUS_0_READBYTE(SPDEEPROM_SMBUS_DEV,JEDEC_SPD_COLS,spd_byte)
327		li	t2,0x09  /*There should be 9 columns*/
328		bne	spd_byte,t2,man
329
330	# Check refresh rate/type @ byte 12. 0x82 -> 128 KHZ
331		SMBUS_0_READBYTE(SPDEEPROM_SMBUS_DEV,JEDEC_SPD_RFSH,spd_byte)
332		li	t2,0x82  /*Refresh rate should be set for 128 KHZ*/
333		bne	spd_byte,t2,man
334
335	# All checks passed.  Use SPD to configure
336		la	v0,spd
337		b	done
338
339man:		la	v0,man_table
340
341done:
342		j	ra
343
344spd:
345
346	/*
347	 * Globals: Only one memory controller, no port interleaving
348	 */
349	DRAM_GLOBALS(0)
350        DRAM_CHAN_CFG(MC_CHAN1, DRT10(8,0), JEDEC, CASCHECK, BLKSIZE32, CFG_DRAM_CSINTERLEAVE, CFG_DRAM_ECC, MCFLG_DS_REDUCED)
351	DRAM_CHAN_CLKCFG(0x00,0x08,0x08,0x00,0x0F,0x0F)
352
353	DRAM_CS_SPD(MC_CS0, 0, 0, 0x54)
354	DRAM_EOT
355
356man_table:
357
358	/*
359	 * DRAM globals: Only one memory controller, no port interleaving
360	 */
361
362	DRAM_GLOBALS(0)
363
364	/*
365	 * 128MB on MC 1 (JEDEC SDRAM)
366	 * Samsung K4H561638B - 16Mx16 chips
367	 *
368	 * Minimum tMEMCLK: 8.0ns (125Mhz max freq)
369	 *
370	 * CS0 Geometry: 13 rows, 9 columns, 2 bankbits
371	 *
372	 * 128khz refresh, CAS Latency 2.5
373	 * Timing (ns):   tCK=7.50 tRAS=45 tRP=20.00 tRRD=15.0 tRCD=20.0 tRFC=auto tRC=auto
374	 *
375	 * Clock Config: Default
376	 */
377
378        DRAM_CHAN_CFG(MC_CHAN1, DRT10(8,0), JEDEC, CASCHECK, BLKSIZE32, CFG_DRAM_CSINTERLEAVE, CFG_DRAM_ECC, MCFLG_DS_REDUCED)
379	DRAM_CHAN_CLKCFG(0x00,0x08,0x08,0x00,0x07,0x0F)
380
381	DRAM_CS_GEOM(MC_CS0, 13, 9, 2)
382	DRAM_CS_TIMING(DRT10(7,5), JEDEC_RFSH_128khz, JEDEC_CASLAT_25, 0,  45, DRT4(20,0), DRT4(15,0),  DRT4(20,0),  0, 0)
383
384
385	DRAM_EOT
386
387END(board_draminfo)
388
389/*  *********************************************************************
390    *  BOARD_UARTA_TXCHAR
391    *
392    *  Transmit a single character via UART A
393    *
394    *  Input parameters:
395    *  	   a0 - character to transmit (low-order 8 bits)
396    *
397    *  Return value:
398    *  	   nothing
399    *
400    *  Registers used:
401    *  	   t0,t1
402    ********************************************************************* */
403#ifdef _SERIAL_PORT_LEDS_
404LEAF(board_uarta_txchar)
405
406	# Wait until there is space in the transmit buffer
407
4081:		li	t0,PHYS_TO_K1(A_DUART_STATUS_A)
409		ld	t1,(t0)			# Get status bits
410		and	t1,M_DUART_TX_RDY	# test for ready
411		beq	t1,0,1b			# keep going till ready
412
413	# Okay, now send the character.
414
415		li	t0,PHYS_TO_K1(A_DUART_TX_HOLD_A)
416		sd	a0,(t0)
417
418	# done!
419
420		j	ra
421
422END(board_uarta_txchar)
423#endif
424
425/*  *********************************************************************
426    *  BOARD_SETLEDS(x)
427    *
428    *  Set LEDs for boot-time progress indication.  Not used if
429    *  the board does not have progress LEDs.  This routine
430    *  must not call any other routines, since it may be invoked
431    *  either from KSEG0 or KSEG1 and it may be invoked
432    *  whether or not the icache is operational.
433    *
434    *  Input parameters:
435    *  	   a0 - LED value (8 bits per character, 4 characters)
436    *
437    *  Return value:
438    *  	   nothing
439    *
440    *  Registers used:
441    *  	   t0,t1,t2,t3
442    ********************************************************************* */
443
444#define LED_CHAR0	(32+8*3)
445#define LED_CHAR1	(32+8*2)
446#define LED_CHAR2	(32+8*1)
447#define LED_CHAR3	(32+8*0)
448
449LEAF(board_setleds)
450
451#ifdef _SERIAL_PORT_LEDS_
452		move	t3,ra
453		move	t2,a0
454
455		li	a0,'['
456		bal	board_uarta_txchar
457
458		move	a0,t2
459		rol	a0,8
460		bal	board_uarta_txchar
461
462		rol	a0,8
463		bal	board_uarta_txchar
464
465		rol	a0,8
466		bal	board_uarta_txchar
467
468		rol	a0,8
469		bal	board_uarta_txchar
470
471		li	a0,']'
472		bal	board_uarta_txchar
473		li	a0,13
474		bal	board_uarta_txchar
475		li	a0,10
476		bal	board_uarta_txchar
477
478		move	ra,t3
479#else
480
481	/*
482	 * Sending to LEDs
483	 */
484		li	t0,PHYS_TO_K1(LEDS_PHYS)
485
486		rol	a0,a0,8
487		and	t1,a0,0xFF
488		sb	t1,LED_CHAR0(t0)
489
490		rol	a0,a0,8
491		and	t1,a0,0xFF
492		sb	t1,LED_CHAR1(t0)
493
494		rol	a0,a0,8
495		and	t1,a0,0xFF
496		sb	t1,LED_CHAR2(t0)
497
498		rol	a0,a0,8
499		and	t1,a0,0xFF
500		sb	t1,LED_CHAR3(t0)
501
502#endif
503		j	ra
504
505END(board_setleds)
506
507
508
509