rockbox/firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c
Michael Sevakis cb06108024 Meg-FX: Enable a real tick in the bootloader. Do cleanups before switching to firmware and cache handling. Put proper main return address in lr.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19368 a1c6a512-1295-4272-9138-f99709370657
2008-12-08 23:31:05 +00:00

232 lines
6 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2007 by Michael Sevakis
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "kernel.h"
#include "system.h"
#include "panic.h"
#include "mmu-arm.h"
#include "cpu.h"
#define default_interrupt(name) \
extern __attribute__((weak,alias("UIRQ"))) void name (void)
default_interrupt(EINT0);
default_interrupt(EINT1);
default_interrupt(EINT2);
default_interrupt(EINT3);
default_interrupt(EINT4_7);
default_interrupt(EINT8_23);
default_interrupt(CAM);
default_interrupt(nBATT_FLT);
default_interrupt(TICK);
default_interrupt(WDT_AC97);
default_interrupt(TIMER0);
default_interrupt(TIMER1);
default_interrupt(TIMER2);
default_interrupt(TIMER3);
default_interrupt(TIMER4);
default_interrupt(UART2);
default_interrupt(LCD);
default_interrupt(DMA0);
default_interrupt(DMA1);
default_interrupt(DMA2);
default_interrupt(DMA3);
default_interrupt(SDI);
default_interrupt(SPI0);
default_interrupt(UART1);
default_interrupt(NFCON);
default_interrupt(USBD);
default_interrupt(USBH);
default_interrupt(IIC);
default_interrupt(UART0);
default_interrupt(SPI1);
default_interrupt(RTC);
default_interrupt(ADC);
static void (* const irqvector[32])(void) =
{
EINT0, EINT1, EINT2, EINT3,
EINT4_7, EINT8_23, CAM, nBATT_FLT, TICK, WDT_AC97,
TIMER0, TIMER1, TIMER2, TIMER3, TIMER4, UART2,
LCD, DMA0, DMA1, DMA2, DMA3, SDI,
SPI0, UART1, NFCON, USBD, USBH, IIC,
UART0, SPI1, RTC, ADC,
};
static const char * const irqname[32] =
{
"EINT0", "EINT1", "EINT2", "EINT3",
"EINT4_7", "EINT8_23", "CAM", "nBATT_FLT", "TICK", "WDT_AC97",
"TIMER0", "TIMER1", "TIMER2", "TIMER3", "TIMER4", "UART2",
"LCD", "DMA0", "DMA1", "DMA2", "DMA3", "SDI",
"SPI0", "UART1", "NFCON", "USBD", "USBH", "IIC",
"UART0", "SPI1", "RTC", "ADC"
};
static void UIRQ(void)
{
unsigned int offset = INTOFFSET;
panicf("Unhandled IRQ %02X: %s", offset, irqname[offset]);
}
void irq_handler(void) __attribute__((interrupt ("IRQ"), naked));
void irq_handler(void)
{
asm volatile (
"sub lr, lr, #4 \r\n"
"stmfd sp!, {r0-r3, ip, lr} \r\n"
"mov r0, #0x4a000000 \r\n" /* INTOFFSET = 0x4a000014 */
"ldr r0, [r0, #0x14] \r\n"
"ldr r1, =irqvector \r\n"
"ldr r1, [r1, r0, lsl #2] \r\n"
"mov lr, pc \r\n"
"bx r1 \r\n"
"ldmfd sp!, {r0-r3, ip, pc}^ \r\n"
);
}
void system_reboot(void)
{
WTCON = 0;
WTCNT = WTDAT = 1 ;
WTCON = 0x21;
for(;;)
;
}
static void set_page_tables(void)
{
map_section(0, 0, 0x1000, CACHE_NONE); /* map every memory region to itself */
map_section(0x30000000, 0, 32, CACHE_ALL); /* map RAM to 0 and enable caching for it */
map_section((int)FRAME, (int)FRAME, 1, BUFFERED); /* enable buffered writing for the framebuffer */
}
void memory_init(void)
{
ttb_init();
set_page_tables();
enable_mmu();
}
void s3c_regmod32(volatile unsigned long *reg, unsigned long bits,
unsigned long mask)
{
int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS);
*reg = (*reg & ~mask) | (bits & mask);
restore_interrupt(oldstatus);
}
void s3c_regset32(volatile unsigned long *reg, unsigned long bits)
{
s3c_regmod32(reg, bits, bits);
}
void s3c_regclr32(volatile unsigned long *reg, unsigned long bits)
{
s3c_regmod32(reg, 0, bits);
}
#ifdef BOOTLOADER
void system_prepare_fw_start(void)
{
tick_stop();
disable_interrupt(IRQ_FIQ_STATUS);
INTMSK = 0xFFFFFFFF;
}
#endif
void system_init(void)
{
INTMSK = 0xFFFFFFFF;
INTMOD = 0;
SRCPND = 0xFFFFFFFF;
INTPND = 0xFFFFFFFF;
INTSUBMSK = 0xFFFFFFFF;
SUBSRCPND = 0xFFFFFFFF;
GPBCON |= 0x85;
GPBDAT |= 0x07;
GPBUP |= 0x20F;
/* Take care of flash related pins */
GPCCON |= 0x1000;
GPCDAT &= ~0x40;
GPCUP |= 0x51;
GPDCON |= 0x05;
GPDUP |= 0x03;
GPDDAT &= ~0x03;
GPFCON |= 0x00000AAA;
GPFUP |= 0xFF;
GPGCON |= 0x01001000;
GPGUP |= 0x70;
GPHCON |= 0x4005;
GPHDAT |= 0x03;
/* TODO: do something with PRIORITY */
/* Turn off currently-not or never-needed devices.
* Be careful here, it is possible to freeze the device by disabling
* clocks at the wrong time.
*
* Turn off AC97, Camera, SPI, IIS, I2C, UARTS, MMC/SD/SDIO Controller
* USB device, USB host, NAND flash controller.
*
* IDLE, Sleep, LCDC, PWM timer, GPIO, RTC, and ADC are untouched (on)
*/
CLKCON &= ~0xFF1ED0;
CLKSLOW |= 0x80;
}
int system_memory_guard(int newmode)
{
(void)newmode;
return 0;
}
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
void set_cpu_frequency(long frequency)
{
if (frequency == CPUFREQ_MAX)
{
asm volatile("mov r0, #0\n"
"mrc p15, 0, r0, c1, c0, 0\n"
"orr r0, r0, #3<<30\n" /* set to Asynchronous mode*/
"mcr p15, 0, r0, c1, c0, 0" : : : "r0");
FREQ = CPUFREQ_MAX;
}
else
{
asm volatile("mov r0, #0\n"
"mrc p15, 0, r0, c1, c0, 0\n"
"bic r0, r0, #3<<30\n" /* set to FastBus mode*/
"mcr p15, 0, r0, c1, c0, 0" : : : "r0");
FREQ = CPUFREQ_NORMAL;
}
}
#endif