📄 em86xxapi.c
字号:
/***************************************** Copyright (c) 2002-2007 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//* This file is part of the EM86XX boot loader *//* * em86xxapi.c * * by Ho Lee 01/23/2002 */#include "config.h"#include "uart.h"#include "io.h"#include "hardware.h"#include "irqs.h"#include "util.h"#include "vsprintf.h"#include "em86xxapi.h"extern int board_init(void);//// Intialization//int em86xx_init(void){#if defined(CONFIG_ARCH_TANGO15) && (CONFIG_ARCH_TANGO15_REV > 1) && !defined(CONFIG_ENABLE_NETWORK_TANGO15) unsigned long sys_gpio_dir = (unsigned long)(((unsigned long long)DEFAULT_GPIO_DIR) & 0xffff); unsigned long sys_gpio_out = (unsigned long)(((unsigned long long)DEFAULT_GPIO_OUTPUT) & 0xffff); unsigned long eth_gpio_dir = (unsigned long)((((unsigned long long)DEFAULT_GPIO_DIR) >> 16) & 0x1ffff); unsigned long eth_gpio_out = (unsigned long)((((unsigned long long)DEFAULT_GPIO_OUTPUT) >> 16) & 0x1ffff);#endif // setup remap register __raw_writel(DRAMBASE, REG_BASE_CPU + CPU_remap); // setup peripheral bus interface // CS0 : IDE, 16/16 (addr/data) // CS1 : // CS2 : parallel flash / FlexROM, 24/8 // CS3 : // default : __raw_writel(DEFAULT_PB_DEFAULT_TIMING, REG_BASE_HOST + PB_default_timing); __raw_writel(DEFAULT_PB_CS_CONFIG, REG_BASE_HOST + PB_cs_config); // timing 0 : __raw_writel(DEFAULT_PB_TIMING0, REG_BASE_HOST + PB_timing0); __raw_writel(DEFAULT_PB_USE_TIMING0, REG_BASE_HOST + PB_use_timing0); // timing 1 : __raw_writel(DEFAULT_PB_TIMING1, REG_BASE_HOST + PB_timing1); __raw_writel(DEFAULT_PB_USE_TIMING1, REG_BASE_HOST + PB_use_timing1); // timing 2 : __raw_writel(DEFAULT_PB_TIMING2, REG_BASE_HOST + PB_timing2); __raw_writel(DEFAULT_PB_USE_TIMING2, REG_BASE_HOST + PB_use_timing2); // timing 3 : __raw_writel(DEFAULT_PB_TIMING3, REG_BASE_HOST + PB_timing3); __raw_writel(DEFAULT_PB_USE_TIMING3, REG_BASE_HOST + PB_use_timing3); // timing 4 : __raw_writel(DEFAULT_PB_TIMING4, REG_BASE_HOST + PB_timing4); __raw_writel(DEFAULT_PB_USE_TIMING4, REG_BASE_HOST + PB_use_timing4); // timing 5 : __raw_writel(DEFAULT_PB_TIMING5, REG_BASE_HOST + PB_timing5); __raw_writel(DEFAULT_PB_USE_TIMING5, REG_BASE_HOST + PB_use_timing5); // setup mapping between GPIO and IRQ __raw_writel(DEFAULT_IRQ_GPIOMAP, REG_BASE_SYSTEM + SYS_gpio_int); // setup default GPIO pins direction and value (if set to output) __raw_writel(0xffff0000 | (DEFAULT_GPIO_DIR & 0xffff), REG_BASE_SYSTEM + SYS_gpio_dir);#if defined(CONFIG_ARCH_TANGO15) && (CONFIG_ARCH_TANGO15_REV > 1) && !defined(CONFIG_ENABLE_NETWORK_TANGO15) // Put ETH pins in gpio mode (17 pins: enumerated as 16-32) __raw_writel(0x1ffff, REG_BASE_HOST + ETH_gpio_mask1); __raw_writel(0x1ffff, REG_BASE_HOST + ETH_gpio_mode1); if (sys_gpio_dir != 0) /* Some pins are set to output */ __raw_writel((sys_gpio_dir << 16) | sys_gpio_out, REG_BASE_SYSTEM + SYS_gpio_data); if (eth_gpio_dir != 0) { __raw_writel(eth_gpio_dir, REG_BASE_HOST + ETH_gpio_mask1); __raw_writel(eth_gpio_dir, REG_BASE_HOST + ETH_gpio_dir1); __raw_writel(eth_gpio_dir, REG_BASE_HOST + ETH_gpio_mask1); __raw_writel(eth_gpio_dir & eth_gpio_out, REG_BASE_HOST + ETH_gpio_data1); }#else if (DEFAULT_GPIO_DIR != 0) /* Some pins are set to output */ __raw_writel((DEFAULT_GPIO_DIR << 16) | DEFAULT_GPIO_OUTPUT, REG_BASE_SYSTEM + SYS_gpio_data);#endif#ifdef CONFIG_ARCH_TANGO#ifdef CONFIG_ENABLE_IDE#ifdef CONFIG_ENABLE_IDE_ISA // IDE configuration compatible with Mambo // IDE pins are tristated __raw_writel(0x10800, REG_BASE_HOST + IDECTRL_pri_idectl);#else // Enable bus master IDE interface __raw_writel(0x08400, REG_BASE_HOST + IDECTRL_pri_idectl);#endif#endif#if defined(DEFAULT_CD0_FREQ) || defined(DEFAULT_CD1_FREQ) || defined(DEFAULT_CD2_FREQ) || defined(DEFAULT_CD3_FREQ) // Setup clean dividers em86xx_set_SYS_clean_dividers();#endif#endif /* CONFIG_ARCH_TANGO */ // Calling board specific initialization routine. board_init(); return 0;}//// Clock//unsigned long em86xx_getclock(void){ unsigned int reg, mult, div; unsigned long clock; reg = __raw_readl(REG_BASE_SYSTEM + SYS_clkgen0_pll); mult = reg & 0x03ff; div = (reg >> 16) & 0x003f; // clock = CPU_CLK_INPUT * (MULT + 2) / (DIV + 2) clock = idivide(EM86XX_EXT_CLOCK, div + 2); clock = clock * (mult + 2); return clock;}unsigned int em86xx_getclockmhz(void){ unsigned long clock = em86xx_getclock(); clock /= 1000000; clock >>= 1; return (unsigned int) clock;}// MULT = 9, DIV = 1 => 49.5 MHz// MULT = 20, DIV = 1 => 99.0 MHz// MULT = 31, DIV = 1 => 148.5 MHz// MULT = 42, DIV = 1 => 198.0 MHzvoid em86xx_setclockmhz(int clock){ unsigned int reg, mult, div; // clock = CPU_CLK_INPUT * (MULT + 2) / (DIV + 2) // MULT = clock * (DIV + 2) / CPU_CLK_INPUT - 2 // fix DIV as 1 if (clock > 100) div = 1; else div = 3; mult = clock * (div + 2); mult <<= 1; mult /= (EM86XX_EXT_CLOCK / 1000000); mult -= 2; reg = __raw_readl(REG_BASE_SYSTEM + SYS_clkgen0_pll); reg &= ~0x003f00ff; reg |= ((mult) | (div << 16)); __raw_writel(reg, REG_BASE_SYSTEM + SYS_clkgen0_pll);}#ifdef CONFIG_ARCH_TANGO#if defined(DEFAULT_CD0_FREQ) || defined(DEFAULT_CD1_FREQ) || defined(DEFAULT_CD2_FREQ) || defined(DEFAULT_CD3_FREQ)/*****************************************************************************//* *//* Sigma Desgin 1-5-2005 *//* Set the Clean Dividers Registers for TANGO 1.5 and 2.0 to a know state *//* Sys_Cleandiv will always be defined as SYSClk *//* Fout =----------------- *//* 2 + divider*2^(-27) *//*The below function finds the correct divider given Fout in .config<board> *//*****************************************************************************/unsigned int em86xx_calculate_SYS_clean_dividers(unsigned int freq){#if 0 unsigned int constant1 = 0x8000000; unsigned int constant2 = 0x10000000; unsigned int SYSClk, divider, num; SYSClk = em86xx_getclockmhz(); num = constant1 * SYSClk; divider = idivide(num, freq) - constant2; return divider;#else unsigned int SYSclk = em86xx_getclockmhz() * 1000000; return((idivide((SYSclk << 2), (freq >> 12)) - (2 << 14)) << 13);#endif}void em86xx_set_SYS_clean_dividers(void){ unsigned long reg;#ifdef DEFAULT_CD0_FREQ reg = em86xx_calculate_SYS_clean_dividers(DEFAULT_CD0_FREQ); __raw_writel(reg, REG_BASE_SYSTEM + SYS_cleandiv0_div);#endif#ifdef DEFAULT_CD1_FREQ reg = em86xx_calculate_SYS_clean_dividers(DEFAULT_CD1_FREQ); __raw_writel(reg, REG_BASE_SYSTEM + SYS_cleandiv1_div);#endif#ifdef DEFAULT_CD2_FREQ reg = em86xx_calculate_SYS_clean_dividers(DEFAULT_CD2_FREQ); __raw_writel(reg, REG_BASE_SYSTEM + SYS_cleandiv2_div);#endif#ifdef DEFAULT_CD3_FREQ reg = em86xx_calculate_SYS_clean_dividers(DEFAULT_CD3_FREQ); __raw_writel(reg, REG_BASE_SYSTEM + SYS_cleandiv3_div);#endif}#endif#endif /* CONFIG_ARCH_TANGO *///// Delay//void em86xx_usleep(int usec){#if 0 int i; unsigned long clock = em86xx_getclock(); clock >>= 20; clock >>= 1; clock /= 5; clock *= usec; for (i = 0; i < clock; ++i) ;#else unsigned int start, end; start = __raw_readl(REG_BASE_SYSTEM + SYS_xtal_in_cnt); end = start + (usec * 27); if (end <= start) while (__raw_readl(REG_BASE_SYSTEM + SYS_xtal_in_cnt) > start); while (__raw_readl(REG_BASE_SYSTEM + SYS_xtal_in_cnt) < end);#endif}void em86xx_msleep(int msec){#if 0 while (msec-- > 0) em86xx_usleep(990);#else while (msec-- > 0) em86xx_usleep(998);#endif}//// CPSR flag//// disable IRQ and FIQ and return original flagunsigned int em86xx_saveflag_clif(void){ unsigned int cpsr_reg; __asm__ __volatile__( "mrs r1, cpsr\n" // get CPSR "mov %0, r1\n" // save CPSR "orr r1, r1, #0xc0\n" // disable IRQ & FIQ "msr cpsr_c, r1\n" // set CPSR : "=r" (cpsr_reg) : : "r1"); return cpsr_reg;}// disable FIQ and return original flagunsigned int em86xx_saveflag_clf(void){ unsigned int cpsr_reg; __asm__ __volatile__( "mrs r1, cpsr\n" // get CPSR "mov %0, r1\n" // save CPSR "orr r1, r1, #0x40\n" // disable FIQ "msr cpsr_c, r1\n" // set CPSR : "=r" (cpsr_reg) : : "r1"); return cpsr_reg;}// disable IRQ and return original flagunsigned int em86xx_saveflag_cli(void){ unsigned int cpsr_reg; __asm__ __volatile__( "mrs r1, cpsr\n" // get CPSR "mov %0, r1\n" // save CPSR "orr r1, r1, #0x80\n" // disable IRQ "msr cpsr_c, r1\n" // set CPSR : "=r" (cpsr_reg) : : "r1"); return cpsr_reg;}// return CPSRunsigned int em86xx_getflag(void){ unsigned int cpsr_reg; __asm__ __volatile__( "mrs r1, cpsr\n" // get CPSR "mov %0, r1\n" : "=r" (cpsr_reg) : : "r1"); return cpsr_reg;}void em86xx_restoreflag(unsigned int cpsr_reg){ __asm__ __volatile__( "mov r1, %0\n" "msr cpsr_c, r1\n" : : "r" (cpsr_reg));}//// Cache control//int em86xx_cache_bist(void){ unsigned int reg = 0; int icache, dcache, writeback; em86xx_get_cache_state(&icache, &dcache, &writeback); em86xx_enable_cache(0, 0, 0); /* disable cache before BIST */ __asm__ __volatile__ ( "mcr p15, 0, %0, c7, c13, 0\n" "mcr p15, 0, %0, c7, c13, 1\n" : : "r" (reg) ); __asm__ __volatile__ ( "mrc p15, 0, %0, c8, c0, 0\n" : "=r" (reg) ); em86xx_enable_cache(icache, dcache, writeback); return reg & 0x3;}void em86xx_get_cache_state(int *picache, int *pdcache, int *pwriteback){ unsigned int reg; __asm__ __volatile__ ( "mrc p15, 0, %0, c1, c0, 0\n" : "=r" (reg) ); if (picache) *picache = (reg & 0x1000) ? 1 : 0; if (pdcache) *pdcache = (reg & 0x0004) ? 1 : 0; if (pwriteback) *pwriteback = (reg & 0x0002) ? 1 : 0;}void em86xx_enable_cache(int icache, int dcache, int writeback){ unsigned int reg; __asm__ __volatile__ ( "mrc p15, 0, %0, c1, c0, 0\n" : "=r" (reg) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -