📄 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
*
* Last update : 5 March 1998
*
* Description :
*
* L1 boot code. Copies L2 boot code via JTAG to flash
*
* outputs MMIO_base, SDRAM_base, SDRAM limit and
* DRAM_CACHEABLE limit before L2 load starts
*
* Assumptions: Works only on DTV REF1 board with AMD Flash Am29F080 part
* (8 Mb x 4).
*
*/
#include <tm1/mmio.h>
/* downloader symbols */
extern UInt32 _clock_freq_init[];
extern UInt32 _begin_stack_init[];
extern volatile UInt32 _MMIO_base_init[];
/* MACROS */
#define CACHE_BL_SIZE 64
#define OFULL 0x1
#define IFULL 0x2
#define SLEEPLESS 0x4
/* Used by tmdbg. These macros cannot to be changed. */
#define START_L2_LOAD_V1 0x12340002
#define JUMP_TO_L2_CODE 0x56780000
/* globals */
unsigned long _clock_freq = (unsigned long) _clock_freq_init;
/* UInt32 *_MMIO_base = (volatile UInt32 *) _MMIO_base_init; */
/* local functions */
static unsigned load_l2_via_jtag (int *l2_code_size);
static void wait_for_ifull(void);
/*
* the code below will only work for:
*
* special DTV stand-alone boards with
* the AMD Am29F080 part (8 Mb x 4).
*
*/
#define FLASH_BASE_ADDRESS 0xFF400000
#define FLASH_SECTOR_SIZE 0x00040000
#define FLASH_N_SECTORS 16
#define FLASH_ADDRESS_LIMIT (FLASH_BASE_ADDRESS + FLASH_N_SECTORS * FLASH_SECTOR_SIZE)
void flash_chip_erase(void)
{
volatile unsigned long * flashbase = (unsigned long *) FLASH_BASE_ADDRESS;
*((flashbase + 0x5555)) = 0xAAAAAAAA;
*((flashbase + 0x2AAA)) = 0x55555555;
*((flashbase + 0x5555)) = 0x80808080;
*((flashbase + 0x5555)) = 0xAAAAAAAA;
*((flashbase + 0x2AAA)) = 0x55555555;
*((flashbase + 0x5555)) = 0x10101010;
while ((*flashbase) != 0xffffffff)
;
}
void flash_word_write(volatile unsigned long *address,
unsigned long data)
{
volatile unsigned long * flashbase = (unsigned long *) FLASH_BASE_ADDRESS;
*((flashbase + 0x5555)) = 0xAAAAAAAA;
*((flashbase + 0x2AAA)) = 0x55555555;
*((flashbase + 0x5555)) = 0xA0A0A0A0;
*address = data;
while (((*address)) != (data))
;
}
/* Copies L2 code via JTAG to flash */
unsigned int L1main ()
{
unsigned l2_load_address;
int l2_code_size;
flash_chip_erase();
/* Load L2 code via JTAG */
l2_load_address = load_l2_via_jtag(&l2_code_size);
/*
* On return from L1main(), l1start.trees goes into infinite loop
*/
return l2_load_address;
}
/*
* unsigned load_l2_via_jtag (int *l2_code_size)
* Loads L2 code via JTAG.
* Returns the load address of L2 Boot code
*
* l2_code_size : Output parameter. set to L2 code size.
*
*/
static unsigned
load_l2_via_jtag (int *l2_code_size)
{
unsigned char *load_addr, byte;
unsigned int l2_load_addr, tmp;
unsigned int cksum;
int code_size;
unsigned long data;
unsigned long * address;
/* 1. Indicate readiness to transfer of L2 code via jtag.
* 2. Transfer MMIO_BASE, SDRAM_BASE and SDRAM_LIMIT before L2
* download starts
*/
MMIO_B(_MMIO_base_init,JTAG_DATA_IN) = 0;
MMIO_B(_MMIO_base_init,JTAG_DATA_OUT) = START_L2_LOAD_V1;
MMIO_B(_MMIO_base_init,JTAG_CTL) = (OFULL | SLEEPLESS);
wait_for_ifull();
MMIO_B(_MMIO_base_init,JTAG_DATA_OUT) = MMIO_B(_MMIO_base_init,MMIO_BASE);
MMIO_B(_MMIO_base_init,JTAG_CTL) = (OFULL | SLEEPLESS);
wait_for_ifull();
MMIO_B(_MMIO_base_init,JTAG_DATA_OUT) = MMIO_B(_MMIO_base_init,DRAM_BASE);
MMIO_B(_MMIO_base_init,JTAG_CTL) = (OFULL | SLEEPLESS);
wait_for_ifull();
MMIO_B(_MMIO_base_init,JTAG_DATA_OUT) = MMIO_B(_MMIO_base_init,DRAM_LIMIT);
MMIO_B(_MMIO_base_init,JTAG_CTL) = (OFULL | SLEEPLESS);
wait_for_ifull();
MMIO_B(_MMIO_base_init,JTAG_DATA_OUT) = MMIO_B(_MMIO_base_init,DRAM_CACHEABLE_LIMIT);
MMIO_B(_MMIO_base_init,JTAG_CTL) = (OFULL | SLEEPLESS);
address = (unsigned long *) FLASH_BASE_ADDRESS;
while (1) {
/* First piece of data: l2 load address */
wait_for_ifull();
/* Get L2 load address */
l2_load_addr = (unsigned long) MMIO_B(_MMIO_base_init,JTAG_DATA_IN);
load_addr = (unsigned char *) l2_load_addr;
MMIO_B(_MMIO_base_init,JTAG_CTL) = SLEEPLESS;
/* second piece of data: l2 code size in bytes */
wait_for_ifull();
/* Get L2 code size */
*l2_code_size = code_size = MMIO_B(_MMIO_base_init,JTAG_DATA_IN);
MMIO_B(_MMIO_base_init,JTAG_CTL) = SLEEPLESS;
cksum = 0;
while (code_size > 0) {
wait_for_ifull();
tmp = MMIO_B(_MMIO_base_init,JTAG_DATA_IN);
MMIO_B(_MMIO_base_init,JTAG_DATA_OUT) = code_size;
MMIO_B(_MMIO_base_init,JTAG_CTL) = SLEEPLESS;
#ifdef __BIG_ENDIAN__
data = ((tmp & 0xff) << 24)
| (((tmp >> 8) & 0xff) << 16)
| (((tmp >> 16) & 0xff) << 8)
| ((tmp >> 24) & 0xff);
#else
data = tmp;
#endif
flash_word_write(address, data);
address++;
byte = (unsigned char) (tmp & 0xff);
cksum += byte;
load_addr++;
byte = (unsigned char) ((tmp >> 8) & 0xff);
cksum += byte;
load_addr++;
byte = (unsigned char) ((tmp >> 16) & 0xff);
cksum += byte;
load_addr++;
byte = (unsigned char) ((tmp >> 24) & 0xff);
cksum += byte;
load_addr++;
code_size -= 4;
}
/* finished l2 load */
cksum |= 0x1;
MMIO_B(_MMIO_base_init,JTAG_DATA_OUT) = cksum;
MMIO_B(_MMIO_base_init,JTAG_CTL) = (OFULL | SLEEPLESS);
/* wait for next action. Another load or jump to l2_load_addr */
wait_for_ifull();
tmp = MMIO_B(_MMIO_base_init,JTAG_DATA_IN);
MMIO_B(_MMIO_base_init,JTAG_CTL) = SLEEPLESS;
if (tmp == JUMP_TO_L2_CODE)
return l2_load_addr;
}
}
static void
wait_for_ifull(void)
{
unsigned state;
do {
state = MMIO_B(_MMIO_base_init,JTAG_CTL);
} while ((state & IFULL) == 0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -