From 7abf2b53a462612808d46d6d77a7f35261a0e5a3 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Fri, 9 Apr 2010 01:21:53 +0000 Subject: Gigabeat S/i.MX31: Sort files in the /target tree into things that are SoC-generic (into /imx31) and player-specific (into /gigabeat-s, based upon current appearances). Move i2s clock init into the appropriate file. Housekeeping only-- no functional changes. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25547 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/imx31/avic-imx31.c | 212 +++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 firmware/target/arm/imx31/avic-imx31.c (limited to 'firmware/target/arm/imx31/avic-imx31.c') diff --git a/firmware/target/arm/imx31/avic-imx31.c b/firmware/target/arm/imx31/avic-imx31.c new file mode 100644 index 0000000000..4ba7da4be0 --- /dev/null +++ b/firmware/target/arm/imx31/avic-imx31.c @@ -0,0 +1,212 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2007 by James Espinoza + * + * 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 +#include "system.h" +#include "imx31l.h" +#include "avic-imx31.h" +#include "panic.h" +#include "debug.h" + +static const char * avic_int_names[64] = +{ + "RESERVED0", "RESERVED1", "RESERVED2", "I2C3", + "I2C2", "MPEG4_ENCODER", "RTIC", "FIR", + "MMC/SDHC2", "MMC/SDHC1", "I2C1", "SSI2", + "SSI1", "CSPI2", "CSPI1", "ATA", + "MBX", "CSPI3", "UART3", "IIM", + "SIM1", "SIM2", "RNGA", "EVTMON", + "KPP", "RTC", "PWN", "EPIT2", + "EPIT1", "GPT", "PWR_FAIL", "CCM_DVFS", + "UART2", "NANDFC", "SDMA", "USB_HOST1", + "USB_HOST2", "USB_OTG", "RESERVED3", "MSHC1", + "MSHC2", "IPU_ERR", "IPU", "RESERVED4", + "RESERVED5", "UART1", "UART4", "UART5", + "ETC_IRQ", "SCC_SCM", "SCC_SMN", "GPIO2", + "GPIO1", "CCM_CLK", "PCMCIA", "WDOG", + "GPIO3", "RESERVED6", "EXT_PWMG", "EXT_TEMP", + "EXT_SENS1", "EXT_SENS2", "EXT_WDOG", "EXT_TV" +}; + +void UIE_VECTOR(void) +{ + int mode; + int offset; + + asm volatile ( + "mrs %0, cpsr \n" /* Mask core IRQ/FIQ */ + "orr %0, %0, #0xc0 \n" + "msr cpsr_c, %0 \n" + "and %0, %0, #0x1f \n" /* Get mode bits */ + : "=&r"(mode) + ); + + offset = mode == 0x11 ? + (int32_t)AVIC_FIVECSR : ((int32_t)AVIC_NIVECSR >> 16); + + panicf("Unhandled %s %d: %s", + mode == 0x11 ? "FIQ" : "IRQ", offset, + offset >= 0 ? avic_int_names[offset] : ""); +} + +/* We use the AVIC */ +void __attribute__((interrupt("IRQ"))) irq_handler(void) +{ + const int offset = (int32_t)AVIC_NIVECSR >> 16; + + if (offset == -1) + { + /* This is called occasionally for some unknown reason even with the + * avic enabled but returning normally appears to cause no harm. The + * KPP and ATA seem to have a part in it (common but multiplexed pins + * that can interfere). It will be investigated more thoroughly but + * for now it is simply an occasional irritant. */ + return; + } + + disable_interrupt(IRQ_FIQ_STATUS); + panicf("Unhandled IRQ %d in irq_handler: %s", offset, + offset >= 0 ? avic_int_names[offset] : ""); +} + +/* Accoring to section 9.3.5 of the UM, the AVIC doesn't accelerate + * fast interrupts and they must be dispatched */ +void __attribute__((naked)) fiq_handler(void) +{ + asm volatile ( + "mov r10, #0x68000000 \n" /* load AVIC base address */ + "ldr r9, [r10, #0x44] \n" /* read FIVECSR of AVIC */ + "add r10, r10, #0x100 \n" /* move pointer to base of VECTOR table */ + "ldr r8, [r10, r9, lsl #2] \n" /* read FIQ vector from VECTOR table */ + "bx r8 \n" /* jump to FIQ service routine */ + ); +} + +void avic_init(void) +{ + struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR; + int i; + + /* Disable all interrupts and set to unhandled */ + avic_disable_int(INT_ALL); + + /* Reset AVIC control */ + avic->intcntl = 0; + + /* Init all interrupts to type IRQ */ + avic_set_int_type(INT_ALL, INT_TYPE_IRQ); + + /* Set all normal to lowest priority */ + for (i = 0; i < 8; i++) + avic->nipriority[i] = 0; + + /* Set NM bit to enable VIC */ + avic->intcntl |= AVIC_INTCNTL_NM; + + /* Enable VE bit in CP15 Control reg to enable VIC */ + asm volatile ( + "mrc p15, 0, r0, c1, c0, 0 \n" + "orr r0, r0, #(1 << 24) \n" + "mcr p15, 0, r0, c1, c0, 0 \n" + : : : "r0"); + + /* Enable normal interrupts at all priorities */ + avic->nimask = 0x1f; +} + +void avic_set_int_priority(enum IMX31_INT_LIST ints, + unsigned long ni_priority) +{ + struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR; + volatile uint32_t *reg = &avic->nipriority[7 - (ints >> 3)]; + unsigned int shift = (ints & 0x7) << 2; + uint32_t mask = 0xful << shift; + *reg = (*reg & ~mask) | ((ni_priority << shift) & mask); +} + +void avic_enable_int(enum IMX31_INT_LIST ints, enum INT_TYPE intstype, + unsigned long ni_priority, void (*handler)(void)) +{ + struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR; + int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS); + + if (ints != INT_ALL) /* No mass-enable allowed */ + { + avic_set_int_type(ints, intstype); + avic->vector[ints] = (long)handler; + avic->intennum = ints; + avic_set_int_priority(ints, ni_priority); + } + + restore_interrupt(oldstatus); +} + +void avic_disable_int(enum IMX31_INT_LIST ints) +{ + struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR; + uint32_t i; + + if (ints == INT_ALL) + { + for (i = 0; i < 64; i++) + { + avic->intdisnum = i; + avic->vector[i] = (long)UIE_VECTOR; + } + } + else + { + avic->intdisnum = ints; + avic->vector[ints] = (long)UIE_VECTOR; + } +} + +static void set_int_type(int i, enum INT_TYPE intstype) +{ + /* INTTYPEH: vectors 63-32, INTTYPEL: vectors 31-0 */ + struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR; + volatile uint32_t *reg = &avic->inttype[1 - (i >> 5)]; + uint32_t val = 1L << (i & 0x1f); + + if (intstype == INT_TYPE_IRQ) + val = *reg & ~val; + else + val = *reg | val; + + *reg = val; +} + +void avic_set_int_type(enum IMX31_INT_LIST ints, enum INT_TYPE intstype) +{ + int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS); + + if (ints == INT_ALL) + { + int i; + for (i = 0; i < 64; i++) + set_int_type(i, intstype); + } + else + { + set_int_type(ints, intstype); + } + + restore_interrupt(oldstatus); +} -- cgit v1.2.3