📄 l1jtag.c
字号:
/*
* +-------------------------------------------------------------------+
* | Copyright (c) 1995-2000 TriMedia Technologies Inc. |
* | |
* | This software is furnished under a license and may only be used |
* | and copied in accordance with the terms and conditions of such a |
* | license and with the inclusion of this copyright notice. This |
* | software or any other copies of this software may not be provided |
* | or otherwise made available to any other person. The ownership |
* | and title of this software is not transferred. |
* | |
* | The information in this software is subject to change without |
* | any prior notice and should not be construed as a commitment by |
* | TriMedia Technologies. |
* | |
* | This code and information is provided "as is" without any |
* | warranty of any kind, either expressed or implied, including but |
* | not limited to the implied warranties of merchantability and/or |
* | fitness for any particular purpose. |
* +-------------------------------------------------------------------+
*
* Module name : l1jtag.c
*
* Module type : IMPLEMENTATION
*
* Title : L1 boot code
*
* Description : L1 boot code. Copies L2 boot code via JTAG,
* outputs MMIO_BASE, DRAM_BASE, DRAM_LIMIT, and
* DRAM_CACHEABLE_LIMIT before L2 load starts
*
* Last update : March 22, 1999
* Added pragmas TCS_unroll=0 and TCS_no_graft
* to keep the code size below 2K
*/
#include <tm1/mmio.h>
/*
* NOTES on the CPU32 macro:
*
* If you are building an EEPROM for the TM1310 (a.k.a. CPU32/TM32) chip
* you need to add the following tmcc compiler option:
* -DCPU32
* to the L1_CFLAGS makefile macro in either Makefile.Unix or Makefile.Win;
* so that the proper JTAG Control registers are used for reading/writing
* the JTAG Data registers.
*/
#if defined(CPU32)
#define JTAG_CTL_2 (0x10380C)
#endif
/*
* Downloader Symbols
*/
extern UInt32 _clock_freq_init[];
extern UInt32 _begin_stack_init[];
extern volatile UInt32 _MMIO_base_init[];
/*
* Macros
*/
#define CACHE_BL_SIZE 64
#if defined(CPU32)
#define OFULL 0x1
#define IFULL 0x1
#define SLEEPLESS 0x2
#else
#define OFULL 0x1
#define IFULL 0x2
#define SLEEPLESS 0x4
#endif
/*
* Used by tmdbg. DO NOT ALTER THESE MACROS!!!
*
* 0x12340000 - version 1 of the L1 boot code, sends the magic number only
* 0x12340002 - version 2 of the L1 boot code, sends sdram info as well
* 0x12340003 - version 3 of the L1 boot code, similar to version 2, but for CPU32/TM1310
*/
#if defined(CPU32)
#define START_L2_LOAD 0x12340003
#else
#define START_L2_LOAD 0x12340002
#endif
#define JUMP_TO_L2_CODE 0x56780000
/*
* Globals
*/
UInt32 _clock_freq = (UInt32)_clock_freq_init;
volatile UInt32 *_MMIO_base = (volatile UInt32 *)_MMIO_base_init;
custom_op void dcb(long, void *);
custom_op void iclr(void);
/*
* DO NOT do the loop unrolling optimization, otherwise
* the code size will expand to beyond the 2K EEPROM limit.
*/
#pragma TCS_unroll=0
/*
* copyback_dcache (UInt32 addr, int nbytes)
* 1. addr must be cache aligned.
* This function flushes nbytes starting at addr to memory.
*
* L1 boot code copies L2 boot code from some device
* This needs to be flushed to memory before jumping to the
* L2 load address
*
*/
static void
copyback_dcache(UInt32 addr, UInt32 n)
{
UInt32 i;
for (i = 0; i < n; i = i + CACHE_BL_SIZE) {
dcb(0, (void *)(addr + i));
}
}
/*
* NOTE:
* iclr() is in a separate function to ensure that it is
* in a dtree by itself.
*/
static void
clear_icache(void)
{
iclr();
}
static void
wait_for_ifull(void)
{
UInt32 state;
do {
#if defined(CPU32)
state = MMIO(JTAG_CTL_2);
#else
state = MMIO(JTAG_CTL);
#endif
} while ((state & IFULL) == 0);
}
/*
* This function loads L2 code via JTAG, it returns the
* load address of L2 Boot code.
*
* l2_code_size: output parameter, set to L2 code size.
*
*/
static UInt32
load_l2_via_jtag(UInt32 * l2_code_size)
{
#pragma TCS_no_graft
/*
* 1. Indicate readiness to transfer of L2 code via jtag.
* 2. Transfer MMIO_BASE, DRAM_BASE, DRAM_LIMIT, and
* DRAM_CACHEABLE_LIMIT before L2 download starts.
*/
MMIO(JTAG_DATA_IN) = 0;
MMIO(JTAG_DATA_OUT) = START_L2_LOAD;
MMIO(JTAG_CTL) = (OFULL | SLEEPLESS);
#if defined(CPU32)
MMIO(JTAG_CTL_2) = 0;
#endif
wait_for_ifull();
MMIO(JTAG_DATA_OUT) = MMIO(MMIO_BASE);
MMIO(JTAG_CTL) = (OFULL | SLEEPLESS);
#if defined(CPU32)
MMIO(JTAG_CTL_2) = 0;
#endif
wait_for_ifull();
MMIO(JTAG_DATA_OUT) = MMIO(DRAM_BASE);
MMIO(JTAG_CTL) = (OFULL | SLEEPLESS);
#if defined(CPU32)
MMIO(JTAG_CTL_2) = 0;
#endif
wait_for_ifull();
MMIO(JTAG_DATA_OUT) = MMIO(DRAM_LIMIT);
MMIO(JTAG_CTL) = (OFULL | SLEEPLESS);
#if defined(CPU32)
MMIO(JTAG_CTL_2) = 0;
#endif
wait_for_ifull();
MMIO(JTAG_DATA_OUT) = MMIO(DRAM_CACHEABLE_LIMIT);
MMIO(JTAG_CTL) = (OFULL | SLEEPLESS);
#if defined(CPU32)
MMIO(JTAG_CTL_2) = 0;
#endif
while (1) {
Byte * load_addr;
UInt32 tmp, cksum;
UInt32 l2_load_addr;
/*
* bug502098: code_size needs to be signed so that the download
* while-loop would exit when code_size is NOT a
* multiple of 4. This is possible with the new tmld.
*/
Int32 code_size;
/*
* First piece of data: l2 load address
*/
wait_for_ifull();
/*
* Get L2 load address
*/
l2_load_addr = (UInt32)MMIO(JTAG_DATA_IN);
load_addr = (Byte *)l2_load_addr;
MMIO(JTAG_CTL) = SLEEPLESS;
#if defined(CPU32)
MMIO(JTAG_CTL_2) = 0;
#endif
/*
* Second piece of data: l2 code size in bytes
*/
wait_for_ifull();
/*
* Get L2 code size
*/
*l2_code_size = code_size = MMIO(JTAG_DATA_IN);
MMIO(JTAG_CTL) = SLEEPLESS;
#if defined(CPU32)
MMIO(JTAG_CTL_2) = 0;
#endif
cksum = 0;
while (code_size > 0) {
Byte byte;
wait_for_ifull();
tmp = MMIO(JTAG_DATA_IN);
MMIO(JTAG_DATA_OUT) = code_size;
MMIO(JTAG_CTL) = SLEEPLESS;
#if defined(CPU32)
MMIO(JTAG_CTL_2) = 0;
#endif
byte = (Byte)(tmp & 0xff);
cksum += byte;
*load_addr++ = byte;
byte = (Byte)((tmp >> 8) & 0xff);
cksum += byte;
*load_addr++ = byte;
byte = (Byte)((tmp >> 16) & 0xff);
cksum += byte;
*load_addr++ = byte;
byte = (Byte)((tmp >> 24) & 0xff);
cksum += byte;
*load_addr++ = byte;
code_size -= 4;
}
/*
* finished l2 load
*/
cksum |= 0x1;
MMIO(JTAG_DATA_OUT) = cksum;
MMIO(JTAG_CTL) = (OFULL | SLEEPLESS);
#if defined(CPU32)
MMIO(JTAG_CTL_2) = 0;
#endif
/*
* wait for next action. Another load or jump to l2_load_addr
*/
wait_for_ifull();
tmp = MMIO(JTAG_DATA_IN);
MMIO(JTAG_CTL) = SLEEPLESS;
#if defined(CPU32)
MMIO(JTAG_CTL_2) = 0;
#endif
if (tmp == JUMP_TO_L2_CODE)
return l2_load_addr;
} /* while (1) */
}
/*
* Copies L2 code via JTAG to SDRAM
*/
UInt32
L1main()
{
#pragma TCS_no_graft
UInt32 l2_code_size;
UInt32 l2_load_address;
#if defined(USING_PCI_INTERNAL_CLOSK)
/*
* enable the following code when the board does not have an
* external PCI clock.
*/
MMIO(XIO_CTL) = 0x3;
#endif
l2_load_address = load_l2_via_jtag(&l2_code_size);
/*
* flush data cache
*/
copyback_dcache(l2_load_address, l2_code_size);
/*
* clear any interrupts
*/
MMIO(ICLEAR) = 0xffffffff;
clear_icache();
/*
* Return from L1main() causes L2 code to be executed.
*/
return l2_load_address;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -