📄 em86xxapi.c
字号:
/***************************************** Copyright (c) 2002-2004 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){ // 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, REG_BASE_SYSTEM + SYS_gpio_dir); 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);#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#endif // 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);}//// 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//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); if (pdcache) *pdcache = (reg & 0x0004); if (pwriteback) *pwriteback = (reg & 0x0002);}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) ); if (icache > 0) reg |= 0x1000; else if (icache == 0) { reg &= ~0x1000; em86xx_flush_cache_data(); } if (dcache > 0) reg |= 0x0004; else if (dcache == 0) { reg &= ~0x0004; em86xx_flush_cache_data(); } if (writeback > 0) reg |= 0x0002; else if (writeback == 0) { reg &= ~0x0002; em86xx_clean_cache_data(); } __asm__ __volatile__ ( "mcr p15, 0, %0, c1, c0, 0\n" : : "r" (reg) );}void em86xx_clean_cache_data(void){ __asm__( "mcr p15, 0, %0, c7, c10, 0\n" // clean data : : "r" (0) );}void em86xx_clean_cache_data_region(unsigned int from, unsigned int to){ unsigned int flag; from &= ~0x0f; to &= ~0x0f; flag = em86xx_saveflag_cli(); for (; from <= to; from += 0x10) { __asm__ __volatile__ ( "mcr p15, 0, %0, c7, c10, 1\n" // clean data : : "r" (from) ); } em86xx_restoreflag(flag);}void em86xx_invalidate_cache_instruction(void){ unsigned int flag; flag = em86xx_saveflag_cli(); __asm__( "mcr p15, 0, %0, c7, c10, 0\n" // clean data "mcr p15, 0, %0, c7, c5, 0\n" // invalidate instruction : : "r" (0) ); em86xx_restoreflag(flag);}void em86xx_invalidate_cache_instruction_region(unsigned int from, unsigned int to){ unsigned int flag; from &= ~0x0f; to &= ~0x0f; flag = em86xx_saveflag_cli(); for (; from <= to; from += 0x10) { __asm__ __volatile__ ( "mcr p15, 0, %0, c7, c10, 1\n" // clean data "mcr p15, 0, %0, c7, c5, 1\n" // invalidate instruction : : "r" (from) ); } em86xx_restoreflag(flag);}void em86xx_invalidate_cache_data(void){ __asm__( "mcr p15, 0, %0, c7, c6, 0\n" // invalidate data : : "r" (0) );}void em86xx_invalidate_cache_data_region(unsigned int from, unsigned int to){ unsigned int flag; from &= ~0x0f; to &= ~0x0f; if (from < MEMORY_BASE_DRAMCTRL0) return; flag = em86xx_saveflag_cli(); for (; from <= to; from += 0x10) { __asm__ __volatile__ ( "mcr p15, 0, %0, c7, c6, 1\n" // invalidate data : : "r" (from) ); } em86xx_restoreflag(flag);}void em86xx_flush_cache_all(void){ unsigned int flag; flag = em86xx_saveflag_cli(); __asm__ __volatile__ ( "mcr p15, 0, %0, c7, c10, 0\n" // clean data cache "mcr p15, 0, %0, c7, c5, 0\n" // invalidate instruction cache "mcr p15, 0, %0, c7, c6, 0\n" // invalidate data cache : : "r" (0) ); em86xx_restoreflag(flag);}void em86xx_flush_cache_data(void){ unsigned int flag; flag = em86xx_saveflag_cli(); __asm__ __volatile__ ( "mcr p15, 0, %0, c7, c10, 0\n" // clean data cache "mcr p15, 0, %0, c7, c6, 0\n" // invalidate data cache : : "r" (0) ); em86xx_restoreflag(flag);}void em86xx_flush_cache_data_region(unsigned int from, unsigned int to){ unsigned int flag; from &= ~0x0f; to &= ~0x0f; if (from < MEMORY_BASE_DRAMCTRL0) return; flag = em86xx_saveflag_cli(); for (; from <= to; from += 0x10) { __asm__ __volatile__ ( "mcr p15, 0, %0, c7, c10, 1\n" // clean data cache "mcr p15, 0, %0, c7, c6, 1\n" // invalidate data cache : : "r" (from) ); } em86xx_restoreflag(flag);}// // interrupt / fast interrupt control//void em86xx_irq_init(void){ /* Disable all interrupts initially. */ __raw_writel(0xffffffff, REG_BASE_CPU + CPU_irq_enableclr); __raw_writel(0xffffffff, REG_BASE_CPU + CPU_fiq_enableclr); /* Disable edge detector */ __raw_writel(IRQMASK_RISINGEDGE, REG_BASE_CPU + CPU_edge_config_rise); __raw_writel(IRQMASK_FALLINGEDGE, REG_BASE_CPU + CPU_edge_config_fall); __raw_writel(__raw_readl(REG_BASE_CPU + CPU_edge_rawstat), REG_BASE_CPU + CPU_edge_rawstat);#if defined(CONFIG_ARCH_TANGO15) && (CONFIG_ARCH_TANGO15_REV > 1) /* Tango15 Rev B or above */ /* Disable all high 32 interrupts. */ __raw_writel(0xffffffff, REG_BASE_CPU + CPU_irq_enableclr_hi); __raw_writel(0xffffffff, REG_BASE_CPU + CPU_fiq_enableclr_hi); /* Disable edge detector */ __raw_writel(IRQMASK_RISINGEDGE_HI, REG_BASE_CPU + CPU_edge_config_rise_hi); __raw_writel(IRQMASK_FALLINGEDGE_HI, REG_BASE_CPU + CPU_edge_config_fall_hi); __raw_writel(__raw_readl(REG_BASE_CPU + CPU_edge_rawstat_hi), REG_BASE_CPU + CPU_edge_rawstat_hi);#endif}#define EM86XX_X_MASK(x) \ void em86xx_mask_##x##(unsigned int irq) \ { \ unsigned int reg; \ \ /* IRQ / FIQ disable */ \ reg = (1 << irq); \ __raw_writel(reg, REG_BASE_CPU + CPU_##x##_enableclr); \ \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -