⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 l1jtag.c

📁 TM1300/PNX1300系列DSP(主要用于视频处理)的自动boot程序
💻 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 + -