📄 em86xx_dram.c
字号:
/***************************************** Copyright © 2001-2005 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************/#include "config.h"#include "uart.h"#include "util.h"#include "vsprintf.h"#include "em86xxapi.h"#include "emhwlib_registers.h"/* Format for interact with this mode: Input: GRB address -- read byte from given address GRW address -- read word from given address GRD address -- read dword from given address GWB address value -- write given byte value to given address GWW address value -- write given word value to given address GWD address value -- write given dword value to given address Q -- quit to normal bootloader address, value -- hexidecimal numeric string (max. 8 chars) Each command string followed by '\n' or '\r'. Output (for GRx command): hexidecimal value -- followed by '\n' To build this, in the configuration file, set STAGE0_XTRA_IMAGE_SIZE = 4096 DEBUG_DRAMADJUSTMENT = y and uncomment the line // #define LLAD_SUPPORT and do make.*/// #define LLAD_SUPPORT /* For turning bootloader into a small command shell */#ifdef CONFIG_USE_SYSCLK#define uart_reinit() do { __msleep(5); uart_init_port(DEFAULT_UART_PORT, DEFAULT_UART_BAUDRATE, 0); __msleep(5); } while (0)#else#define uart_reinit() do { __msleep(5); } while (0)#endif/* From rmdef/rmbtypes.h */typedef unsigned char RMuint8;typedef char RMint8;typedef unsigned short RMuint16;typedef short RMint16;typedef unsigned long RMuint32;typedef long RMint32;typedef unsigned char RMbool;typedef char RMascii;typedef int RMstatus;static inline RMuint32 gbus_read_uint32(RMuint32 byte_address){ return *((volatile RMuint32 *)byte_address);}static inline RMuint16 gbus_read_uint16(RMuint32 byte_address){ return *((volatile RMuint16 *)byte_address);}static inline RMuint8 gbus_read_uint8(RMuint32 byte_address){ return *((volatile RMuint8 *)byte_address);}static inline void gbus_write_uint32(RMuint32 byte_address, RMuint32 data){ *((volatile RMuint32 *)byte_address) = data;}static inline void gbus_write_uint16(RMuint32 byte_address, RMuint16 data){ *((volatile RMuint16 *)byte_address) = data;}static inline void gbus_write_uint8(RMuint32 byte_address, RMuint8 data){ *((volatile RMuint8 *)byte_address) = data;}#ifndef LLAD_SUPPORT#ifndef DEBUG_DRAMADJUSTMENT#define uart_init() ;#define uart_putc(x) ;#define uart_puts(x) ;#define uart_printf(x,...) ;#undef uart_reinit#define uart_reinit() do { __msleep(1); } while (0)#endif#define MIN_GOOD_SIZE 5 /* Minimum good size to look for */#define RMsetConsecutiveBits(target,begin,end,value) \ *(target)=( \ ( \ (*(target)) \ & \ (~( \ ( ( 1 << ((end)-(begin)+1) ) - 1 ) \ << \ (begin) \ ) \ ) \ ) \ | \ ( \ ( (value) & ( ( 1 << ((end)-(begin)+1) ) - 1 ) ) \ << \ (begin) \ ) \ )static void reset_state(int delay, unsigned long pll, unsigned long cfg);static RMuint32 test_capdelay_1freq_dram0_gfx(RMuint32 wd, RMuint32 *size);static RMuint32 test_with_fixed_wd(unsigned long wd, unsigned long *set_dunit_cfg, unsigned long *set_dunit_delay, unsigned long *size);#ifndef DEBUG_DRAMADJUSTMENTstatic void emergency(const char *s);#endif//static unsigned long ctable[] = { 0x06200000, 0x06300000, 0x03300000, 0x03400000, 0 };static const unsigned long ctable[] = { 0x03400000, 0x03300000, 0x06300000, 0x06200000 };void xtra_stage0(unsigned int configaddr){ register int i; RMuint32 res, size;// unsigned long saved_dunit_cfg = default_dram0_dunit_cfg;// unsigned long saved_delay0_ctrl = default_dram_dunit_delay0_ctrl; unsigned long set_dunit_cfg, set_dunit_delay; unsigned long test_system_clock, wd, wres;// unsigned long xtal_in1, xtal_in2;// xtal_in1 = gbus_read_uint32(REG_BASE_SYSTEM + SYS_xtal_in_cnt); uart_init(); uart_puts("\nDRAM Delay Adjustment\n"); if (((loaderconfig_t *)configaddr)->signature != LOADER_CONFIGSIGN) { uart_puts(" Invalid configuration\n"); return; } /* Overclock for 10% */ test_system_clock = (DEFAULT_CLKGEN_PLL & 0xfffffc00) | ((DEFAULT_CLKGEN_PLL & 0x000003ff) * 11 / 10); reset_state(0, test_system_clock, 0); uart_putc('\n'); for (wres = 0, wd = 6; wd <= 0xf; wd++) { res = test_with_fixed_wd(wd, &set_dunit_cfg, &set_dunit_delay, &size);// if (res >= (sizeof(ctable) >> 3)) if (res != 0) wres |= (1 << wd); } for (i = 6, wd = 0, res = 0xf; i < res; i++) { if (wd == 0) { if (((1 << i) & wres) != 0) wd = i; } else if (((1 << i) & (~wres)) != 0) res = i; } uart_printf("\n**** Best write delay: %d,%d (0x%x) ****\n", wd, res, wres);// if ((wd = ((res + wd) >> 1)) != 0) /* This is the best write delay we found */ if ((wd = (wd + ((res - wd - 1) >> 1))) != 0) /* This is the best write delay we found */ test_with_fixed_wd(wd, &set_dunit_cfg, &set_dunit_delay, &size); uart_printf("\nBest dunit_cfg 0x%08lx, dunit_delay 0x%08lx, write delay: %d, size %d. => ", set_dunit_cfg, set_dunit_delay, wd, size); if (size != 0) { uart_puts("applied.\n"); reset_state(set_dunit_delay, 0, set_dunit_cfg); } else { uart_puts("not applied.\n"); reset_state(0, 0, 0); /* Set to use new delay */#ifndef DEBUG_DRAMADJUSTMENT emergency("DRAM parms not found.");#endif }// xtal_in2 = gbus_read_uint32(REG_BASE_SYSTEM + SYS_xtal_in_cnt);// *((volatile unsigned long *)0x13000000) = xtal_in2 - xtal_in1; return;}static RMuint32 test_with_fixed_wd(RMuint32 wd, unsigned long *set_dunit_cfg, unsigned long *set_dunit_delay, unsigned long *size){ register int i; RMuint32 test_size, res, count; for (*set_dunit_cfg = *set_dunit_delay = *size = count = i = 0; i < (sizeof(ctable) >> 2); i++) { gbus_write_uint32(REG_BASE_dram_controller_0 + G2L_RESET_CONTROL, 3); gbus_write_uint32(REG_BASE_dram_controller_0 + G2L_RESET_CONTROL, 2); gbus_write_uint32(REG_BASE_dram_controller_0 + DRAM_dunit_cfg, (DEFAULT_DRAM0_DUNIT_CFG & 0xf88fffff) | ctable[i]); gbus_write_uint32(REG_BASE_dram_controller_0 + DRAM_dunit_delay0_ctrl, (DEFAULT_DRAM_DUNIT_DELAY0_CTRL & 0xfff0ffff) | (wd << 16)); gbus_write_uint32(REG_BASE_dram_controller_0 + G2L_RESET_CONTROL, 0); if ((res = test_capdelay_1freq_dram0_gfx(wd << 16, &test_size)) != 0) { if (test_size >= *size) { *set_dunit_cfg = gbus_read_uint32(REG_BASE_dram_controller_0 + DRAM_dunit_cfg); *set_dunit_delay = res; *size = test_size; } if (test_size >= MIN_GOOD_SIZE) count++; } } return(count);}static void __usleep(int usec){ unsigned long start, end; start = gbus_read_uint32(REG_BASE_SYSTEM + SYS_xtal_in_cnt); end = start + (usec * 27); if (end <= start) while (gbus_read_uint32(REG_BASE_SYSTEM + SYS_xtal_in_cnt) > start); while (gbus_read_uint32(REG_BASE_SYSTEM + SYS_xtal_in_cnt) < end);}static inline void __msleep(int msec){ while (msec-- > 0) __usleep(998);}#ifndef DEBUG_DRAMADJUSTMENT#if DEFAULT_UART_PORT == 0#define UART_BASE (UART0_BASE)#else#define UART_BASE (UART1_BASE)#endif#if DEFAULT_UART_STOPBITS == 2#define LCR ((DEFAULT_UART_DATABITS-5)|UART_LCR_STOP|DEFAULT_UART_PARITY)#else#define LCR ((DEFAULT_UART_DATABITS-5)|DEFAULT_UART_PARITY)#endifstatic void emergency(const char *ptr){ int clkdiv;#ifdef CONFIG_USE_SYSCLK unsigned long speed = ((EM86XX_EXT_CLOCK/((((DEFAULT_CLKGEN_PLL&0x3f0000)>>16)+2)*2))*((DEFAULT_CLKGEN_PLL&0x3ff)+2));#endif gbus_write_uint32(UART_BASE + UART_IER, 0x00); // IRQ ENABL: all disabled gbus_write_uint32(UART_BASE + UART_FCR, 0x1f); // FIFO CTRL: depth=16, clear rec & transm. FIFO, Tx.Trig = 4bytes gbus_write_uint32(UART_BASE + UART_LCR, LCR); // LINE CTRL: #ifdef CONFIG_USE_SYSCLK gbus_write_uint32(UART_BASE + UART_CLKSEL, 0x00); // CLK SEL : SELECT INTERNAL CLOCK clkdiv = speed / (DEFAULT_UART_BAUDRATE << 4);#else gbus_write_uint32(UART_BASE + UART_CLKSEL, 0x01); // CLK SEL : SELECT EXTERNAL CLOCK clkdiv = EM86XX_EXT_CLOCK / (DEFAULT_UART_BAUDRATE << 4);#endif gbus_write_uint32(UART_BASE + UART_CLKDIV, clkdiv); while (*ptr != '\0') { gbus_write_uint32(UART_BASE + UART_TBR, *ptr++); while ((gbus_read_uint32(UART_BASE + UART_LSR) & 0x20) == 0); } gbus_write_uint32(UART_BASE + UART_TBR, '\r'); while ((gbus_read_uint32(UART_BASE + UART_LSR) & 0x20) == 0);}#endifstatic void reset_state(int delay, unsigned long pll, unsigned long cfg){ int i; unsigned long rbase; gbus_write_uint32(REG_BASE_system_block + SYS_sysclk_mux, 0); gbus_write_uint32(REG_BASE_system_block + SYS_clkgen0_pll, pll ? pll : DEFAULT_CLKGEN_PLL); gbus_write_uint32(REG_BASE_system_block + SYS_sysclk_mux, 1); __msleep(1); for (rbase = REG_BASE_dram_controller_0, i = 0; i < 1; ++i, rbase += 0x10000) {// unsigned long rbase = 0x30000 + i * 0x10000; gbus_write_uint32(rbase + G2L_RESET_CONTROL, 3); gbus_write_uint32(rbase + G2L_RESET_CONTROL, 2); gbus_write_uint32(rbase, cfg ? cfg : DEFAULT_DRAM0_DUNIT_CFG); gbus_write_uint32(rbase + 4, delay ? delay : DEFAULT_DRAM_DUNIT_DELAY0_CTRL); gbus_write_uint32(rbase + G2L_RESET_CONTROL, 0); } uart_reinit();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -