2007-10-28 11:08:10 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
|
|
* \/ \/ \/ \/ \/
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* Copyright (C) 2007 by Dave Chapman
|
|
|
|
*
|
2008-06-28 18:10:04 +00:00
|
|
|
* 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.
|
2007-10-28 11:08:10 +00:00
|
|
|
*
|
|
|
|
* 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"
|
|
|
|
|
2008-05-03 07:49:39 +00:00
|
|
|
/* Externally defined interrupt handlers */
|
2008-05-02 19:12:09 +00:00
|
|
|
extern void TIMER(void);
|
2008-05-03 07:49:39 +00:00
|
|
|
extern void ADC(void);
|
2008-10-14 05:13:21 +00:00
|
|
|
extern void USB_DEVICE(void);
|
2008-05-02 19:12:09 +00:00
|
|
|
|
|
|
|
void irq(void)
|
|
|
|
{
|
|
|
|
int irq = IREQ & 0x7fffffff;
|
|
|
|
CREQ = irq; /* Clears the corresponding IRQ status */
|
|
|
|
|
|
|
|
if (irq & TIMER0_IRQ_MASK)
|
|
|
|
TIMER();
|
2008-05-03 07:49:39 +00:00
|
|
|
else if (irq & ADC_IRQ_MASK)
|
|
|
|
ADC();
|
2008-10-14 05:13:21 +00:00
|
|
|
#ifdef HAVE_USBSTACK
|
2008-09-06 17:50:59 +00:00
|
|
|
else if (irq & USBD_IRQ_MASK)
|
2008-10-14 05:13:21 +00:00
|
|
|
USB_DEVICE();
|
2008-09-06 17:50:59 +00:00
|
|
|
#endif
|
2008-05-02 19:12:09 +00:00
|
|
|
else
|
|
|
|
panicf("Unhandled IRQ 0x%08X", irq);
|
|
|
|
}
|
|
|
|
|
2008-09-06 17:50:59 +00:00
|
|
|
void fiq_handler(void) __attribute__((interrupt ("FIQ"), naked));
|
|
|
|
|
|
|
|
#ifdef BOOTLOADER
|
2008-05-02 19:12:09 +00:00
|
|
|
void fiq_handler(void)
|
|
|
|
{
|
|
|
|
/* TODO */
|
|
|
|
}
|
2008-09-06 17:50:59 +00:00
|
|
|
#endif
|
2008-05-02 19:12:09 +00:00
|
|
|
|
2007-10-28 11:08:10 +00:00
|
|
|
void system_reboot(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2009-01-08 10:15:32 +00:00
|
|
|
void system_exception_wait(void)
|
|
|
|
{
|
|
|
|
while (1);
|
|
|
|
}
|
|
|
|
|
2007-10-28 11:08:10 +00:00
|
|
|
/* TODO - these should live in the target-specific directories and
|
|
|
|
once we understand what all the GPIO pins do, move the init to the
|
|
|
|
specific driver for that hardware. For now, we just perform the
|
|
|
|
same GPIO init as the original firmware - this makes it easier to
|
|
|
|
investigate what the GPIO pins do.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef LOGIK_DAX
|
|
|
|
static void gpio_init(void)
|
|
|
|
{
|
|
|
|
/* Do what the original firmware does */
|
|
|
|
GPIOD_FUNC = 0;
|
|
|
|
GPIOD_DIR = 0x3f0;
|
|
|
|
GPIOD = 0xe0;
|
2010-01-03 10:19:43 +00:00
|
|
|
|
2007-10-28 11:08:10 +00:00
|
|
|
GPIOE_FUNC = 0;
|
|
|
|
GPIOE_DIR = 0xe0;
|
|
|
|
GPIOE = 0;
|
2010-01-03 10:19:43 +00:00
|
|
|
|
2007-10-28 11:08:10 +00:00
|
|
|
GPIOA_FUNC = 0;
|
|
|
|
GPIOA_DIR = 0xffff1000; /* 0 - 0xf000 */
|
|
|
|
GPIOA = 0x1080;
|
2010-01-03 10:19:43 +00:00
|
|
|
|
2007-10-28 11:08:10 +00:00
|
|
|
GPIOB_FUNC = 0x16a3;
|
|
|
|
GPIOB_DIR = 0x6ffff;
|
|
|
|
GPIOB = 0;
|
2010-01-03 10:19:43 +00:00
|
|
|
|
2007-10-28 11:08:10 +00:00
|
|
|
GPIOC_FUNC = 1;
|
2008-05-02 19:12:09 +00:00
|
|
|
GPIOC_DIR = 0x03ffffff; /* mvn r2, 0xfc000000 */
|
2007-10-28 11:08:10 +00:00
|
|
|
GPIOC = 0;
|
|
|
|
}
|
|
|
|
#elif defined(IAUDIO_7)
|
|
|
|
static void gpio_init(void)
|
|
|
|
{
|
|
|
|
/* Do what the original firmware does */
|
|
|
|
GPIOA_FUNC = 0;
|
|
|
|
GPIOB_FUNC = 0x1623;
|
|
|
|
GPIOC_FUNC = 1;
|
|
|
|
GPIOD_FUNC = 0;
|
|
|
|
GPIOE_FUNC = 0;
|
|
|
|
GPIOA = 0x30;
|
2008-12-21 19:16:54 +00:00
|
|
|
GPIOB = 0x00c00;
|
2007-10-28 11:08:10 +00:00
|
|
|
GPIOC = 0;
|
|
|
|
GPIOD = 0x180;
|
2008-12-21 19:16:54 +00:00
|
|
|
GPIOE = 0x80;
|
2008-09-06 17:50:59 +00:00
|
|
|
GPIOA_DIR = 0x84b0;
|
2008-12-21 19:16:54 +00:00
|
|
|
GPIOB_DIR = 0x80c00;
|
2007-10-28 11:08:10 +00:00
|
|
|
GPIOC_DIR = 0x2000000;
|
|
|
|
GPIOD_DIR = 0x3e3;
|
|
|
|
GPIOE_DIR = 0x88;
|
|
|
|
}
|
2008-05-02 19:12:09 +00:00
|
|
|
#elif defined(SANSA_M200)
|
|
|
|
static void gpio_init(void)
|
|
|
|
{
|
|
|
|
/* TODO - Implement for M200 */
|
|
|
|
}
|
2008-06-21 15:18:36 +00:00
|
|
|
#elif defined(SANSA_C100)
|
|
|
|
static void gpio_init(void)
|
|
|
|
{
|
|
|
|
/* Do what the original firmware does */
|
|
|
|
GPIOA_FUNC = 0;
|
|
|
|
GPIOB_FUNC = 0x16A3;
|
|
|
|
GPIOC_FUNC = 1;
|
|
|
|
GPIOD_FUNC |= 2;
|
|
|
|
GPIOE_FUNC = 0;
|
2010-01-03 10:19:43 +00:00
|
|
|
|
2008-06-21 15:18:36 +00:00
|
|
|
GPIOA_DIR = 0xFFFF0E00;
|
|
|
|
GPIOB_DIR = 0x6FFFF;
|
|
|
|
GPIOC_DIR = 0x03FFFFFF;
|
|
|
|
GPIOD_DIR = 0x3F7;
|
|
|
|
GPIOE_DIR = 0x9B;
|
|
|
|
|
|
|
|
GPIOA = 0x80;
|
|
|
|
GPIOB = 0;
|
|
|
|
GPIOC = 0;
|
|
|
|
GPIOD |= 0xC0;
|
|
|
|
GPIOE = 0x9B;
|
|
|
|
}
|
2007-10-28 11:08:10 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Second function called in the original firmware's startup code - we just
|
|
|
|
set up the clocks in the same way as the original firmware for now. */
|
|
|
|
static void clock_init(void)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
2008-05-02 19:12:09 +00:00
|
|
|
/* STP = 0x1, PW = 0x04 , HLD = 0x0 */
|
2007-10-28 11:08:10 +00:00
|
|
|
CSCFG3 = (CSCFG3 &~ 0x3fff) | 0x820;
|
|
|
|
|
2008-05-02 19:12:09 +00:00
|
|
|
/* XIN=External main, Fcpu=Fsys, BCKDIV=1 (Fbus = Fsys / 2) */
|
2007-10-28 11:08:10 +00:00
|
|
|
CLKCTRL = (CLKCTRL & ~0xff) | 0x14;
|
|
|
|
|
|
|
|
if (BMI & 0x20)
|
2008-05-02 19:12:09 +00:00
|
|
|
PCLKCFG0 = 0xc82d7000; /* EN1 = 1, XIN=Ext. main, DIV1 = 0x2d, P1 = 1 */
|
2007-10-28 11:08:10 +00:00
|
|
|
else
|
2008-05-02 19:12:09 +00:00
|
|
|
PCLKCFG0 = 0xc8ba7000; /* EN1 = 1, XIN=Ext. main, DIV1 = 0xba, P1 = 1 */
|
2007-10-28 11:08:10 +00:00
|
|
|
|
|
|
|
MCFG |= 0x2000;
|
|
|
|
|
|
|
|
#ifdef LOGIK_DAX
|
|
|
|
/* Only seen in the Logik DAX original firmware */
|
|
|
|
SDCFG = (SDCFG & ~0x7000) | 0x2000;
|
|
|
|
#endif
|
|
|
|
|
2008-05-02 19:12:09 +00:00
|
|
|
/* Disable PLL */
|
2007-10-28 11:08:10 +00:00
|
|
|
PLL0CFG |= 0x80000000;
|
|
|
|
|
2008-05-02 19:12:09 +00:00
|
|
|
/* Enable PLL, M=0xcf, P=0x13. m=M+8, p=P+2, S = 0
|
|
|
|
Fout = (215/21)*12MHz = 122857142Hz */
|
2007-10-28 11:08:10 +00:00
|
|
|
PLL0CFG = 0x0000cf13;
|
|
|
|
|
|
|
|
i = 8000;
|
|
|
|
while (--i) {};
|
|
|
|
|
2008-05-02 19:12:09 +00:00
|
|
|
/* Enable PLL0 */
|
|
|
|
CLKDIVC = 0x81000000;
|
|
|
|
|
|
|
|
/* Fsys = PLL0, Fcpu = Fsys, Fbus=Fsys / 2 */
|
2007-10-28 11:08:10 +00:00
|
|
|
CLKCTRL = 0x80000010;
|
|
|
|
|
|
|
|
asm volatile (
|
|
|
|
"nop \n\t"
|
|
|
|
"nop \n\t"
|
|
|
|
);
|
2009-09-04 09:36:53 +00:00
|
|
|
|
|
|
|
/* Enable Z-Clock */
|
|
|
|
PCLKCFG5 |= (1<<31) | (4<<28); /* Timer Z-Clock enable, XIN direct*/
|
|
|
|
|
|
|
|
/* Set TC32 timer to be our USEC_TIMER (Xin divided by 12 = 1MHz) */
|
|
|
|
TC32MCNT = 0;
|
|
|
|
TC32LDV = 0;
|
|
|
|
TC32EN = (1<<24) | 11;
|
2007-10-28 11:08:10 +00:00
|
|
|
}
|
|
|
|
|
2008-05-02 19:12:09 +00:00
|
|
|
static void cpu_init(void)
|
|
|
|
{
|
|
|
|
/* Memory protection - see page 48 of ARM946 TRM
|
|
|
|
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0201d/DDI0201D_arm946es_r1p1_trm.pdf
|
|
|
|
*/
|
|
|
|
asm volatile (
|
|
|
|
/* Region 0 - addr=0, size=4GB, enabled */
|
|
|
|
"mov r0, #0x3f \n\t"
|
|
|
|
"mcr p15, 0, r0, c6, c0, 0 \n\t"
|
|
|
|
"mcr p15, 0, r0, c6, c0, 1 \n\t"
|
|
|
|
|
2008-06-21 15:18:36 +00:00
|
|
|
#if defined(LOGIK_DAX) || defined(SANSA_C100)
|
2008-05-02 19:12:09 +00:00
|
|
|
/* Address region 1 - addr 0x2fff0000, size=64KB, enabled*/
|
|
|
|
"ldr r0, =0x2fff001f \n\t"
|
|
|
|
#elif defined(IAUDIO_7)
|
|
|
|
/* Address region 1 - addr 0x20000000, size=8KB, enabled*/
|
|
|
|
"mov r0, #0x19 \n\t"
|
|
|
|
"add r0, r0, #0x20000000 \n\t"
|
|
|
|
#elif defined(SANSA_M200)
|
|
|
|
/* Address region 1 - addr 0x20000000, size=256MB, enabled*/
|
|
|
|
"mov r0, #0x37 \n\t"
|
|
|
|
"add r0, r0, #0x20000000 \n\t"
|
|
|
|
#endif
|
|
|
|
"mcr p15, 0, r0, c6, c1, 0 \n\t"
|
|
|
|
"mcr p15, 0, r0, c6, c1, 1 \n\t"
|
|
|
|
|
|
|
|
/* Address region 2 - addr 0x30000000, size=256MB, enabled*/
|
|
|
|
"mov r0, #0x37 \n\t"
|
|
|
|
"add r0, r0, #0x30000000 \n\t"
|
|
|
|
"mcr p15, 0, r0, c6, c2, 0 \n\t"
|
|
|
|
"mcr p15, 0, r0, c6, c2, 1 \n\t"
|
|
|
|
|
|
|
|
/* Address region 2 - addr 0x40000000, size=512MB, enabled*/
|
|
|
|
"mov r0, #0x39 \n\t"
|
|
|
|
"add r0, r0, #0x40000000 \n\t"
|
|
|
|
"mcr p15, 0, r0, c6, c3, 0 \n\t"
|
|
|
|
"mcr p15, 0, r0, c6, c3, 1 \n\t"
|
|
|
|
|
|
|
|
/* Address region 4 - addr 0x60000000, size=256MB, enabled*/
|
|
|
|
"mov r0, #0x37 \n\t"
|
|
|
|
"add r0, r0, #0x60000000 \n\t"
|
|
|
|
"mcr p15, 0, r0, c6, c4, 0 \n\t"
|
|
|
|
"mcr p15, 0, r0, c6, c4, 1 \n\t"
|
|
|
|
|
|
|
|
/* Address region 5 - addr 0x10000000, size=256MB, enabled*/
|
|
|
|
"mov r0, #0x37 \n\t"
|
|
|
|
"add r0, r0, #0x10000000 \n\t"
|
|
|
|
"mcr p15, 0, r0, c6, c5, 0 \n\t"
|
|
|
|
"mcr p15, 0, r0, c6, c5, 1 \n\t"
|
|
|
|
|
|
|
|
/* Address region 6 - addr 0x80000000, size=2GB, enabled*/
|
|
|
|
"mov r0, #0x37 \n\t"
|
|
|
|
"add r0, r0, #0x80000006 \n\t"
|
|
|
|
"mcr p15, 0, r0, c6, c6, 0 \n\t"
|
|
|
|
"mcr p15, 0, r0, c6, c6, 1 \n\t"
|
|
|
|
|
|
|
|
/* Address region 7 - addr 0x3000f000, size=4KB, enabled*/
|
|
|
|
"ldr r0, =0x3000f017 \n\t"
|
|
|
|
"mcr p15, 0, r0, c6, c7, 0 \n\t"
|
|
|
|
"mcr p15, 0, r0, c6, c7, 1 \n\t"
|
|
|
|
|
2010-01-03 10:19:43 +00:00
|
|
|
|
2008-05-02 19:12:09 +00:00
|
|
|
/* Register 5 - Access Permission Registers */
|
|
|
|
|
|
|
|
"ldr r0, =0xffff \n\t"
|
|
|
|
"mcr p15, 0, r0, c5, c0, 0 \n\t" /* write data access permission bits */
|
|
|
|
"mcr p15, 0, r0, c5, c0, 1 \n\t" /* write instruction access permission bits */
|
|
|
|
|
|
|
|
"mov r0, #0xa7 \n\t"
|
|
|
|
"mcr p15, 0, r0, c3, c0, 0 \n\t" /* set write buffer control register */
|
|
|
|
|
2008-06-21 15:18:36 +00:00
|
|
|
#if defined(LOGIK_DAX) || defined(SANSA_C100)
|
2008-05-02 19:12:09 +00:00
|
|
|
"mov r0, #0xa5 \n\t"
|
2008-06-21 15:18:36 +00:00
|
|
|
#elif defined(IAUDIO_7) || defined(SANSA_M200)
|
2008-05-02 19:12:09 +00:00
|
|
|
"mov r0, #0xa7 \n\t"
|
2010-08-28 10:17:19 +00:00
|
|
|
#else
|
2008-05-02 19:12:09 +00:00
|
|
|
#error NOT DEFINED FOR THIS TARGET!
|
|
|
|
#endif
|
|
|
|
"mcr p15, 0, r0, c2, c0, 0 \n\t"
|
|
|
|
"mcr p15, 0, r0, c2, c0, 1 \n\t"
|
|
|
|
|
|
|
|
"mov r0, #0xa0000006 \n\t"
|
|
|
|
"mcr p15, 0, r0, c9, c1, 0 \n\t"
|
|
|
|
|
|
|
|
"ldr r1, =0x1107d \n\t"
|
|
|
|
"mov r0, #0x0 \n\t"
|
|
|
|
"mcr p15, 0, r0, c7, c5, 0 \n\t" /* Flush instruction cache */
|
|
|
|
"mcr p15, 0, r0, c7, c6, 0 \n\t" /* Flush data cache */
|
|
|
|
|
|
|
|
"mcr p15, 0, r1, c1, c0, 0 \n\t" /* CPU control bits */
|
|
|
|
: : : "r0", "r1"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-28 11:08:10 +00:00
|
|
|
|
|
|
|
void system_init(void)
|
|
|
|
{
|
2008-05-02 19:12:09 +00:00
|
|
|
/* mask all interrupts */
|
|
|
|
IEN = 0;
|
|
|
|
|
|
|
|
/* Set all interrupts as IRQ for now - some may need to be FIQ in future */
|
|
|
|
IRQSEL = 0xffffffff;
|
|
|
|
|
|
|
|
/* Set master enable bit */
|
|
|
|
IEN = 0x80000000;
|
|
|
|
|
|
|
|
cpu_init();
|
2007-10-28 11:08:10 +00:00
|
|
|
clock_init();
|
|
|
|
gpio_init();
|
2008-05-02 19:12:09 +00:00
|
|
|
|
|
|
|
enable_irq();
|
2007-10-28 11:08:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int system_memory_guard(int newmode)
|
|
|
|
{
|
|
|
|
(void)newmode;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
|
|
|
|
|
|
|
void set_cpu_frequency(long frequency)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|