#include <linux/init.h>
#include <linux/list.h>
#include <linux/timer.h>
+#include <linux/io.h>
#include <mach/hardware.h>
#include <asm/irq.h>
-#include <asm/io.h>
#include <asm/mach/irq.h>
/*
*
* We simply use the ENABLE DISABLE registers inside of the IMX
- * to turn on/off specific interrupts. FIXME- We should
- * also add support for the accelerated interrupt controller
- * by putting offets to irq jump code in the appropriate
- * places.
+ * to turn on/off specific interrupts.
*
*/
__raw_writel(irq, IMX_AITC_INTENNUM);
}
+ #ifdef CONFIG_FIQ
+ int imx_set_irq_fiq(unsigned int irq, unsigned int type)
+ {
+ unsigned int irqt;
+
+ if (irq >= IMX_IRQS)
+ return -EINVAL;
+
+ if (irq < IMX_IRQS / 2) {
+ irqt = __raw_readl(IMX_AITC_INTTYPEL) & ~(1 << irq);
+ __raw_writel(irqt | (!!type << irq), IMX_AITC_INTTYPEL);
+ } else {
+ irq -= IMX_IRQS / 2;
+ irqt = __raw_readl(IMX_AITC_INTTYPEH) & ~(1 << irq);
+ __raw_writel(irqt | (!!type << irq), IMX_AITC_INTTYPEH);
+ }
+
+ return 0;
+ }
+ EXPORT_SYMBOL(imx_set_irq_fiq);
+ #endif /* CONFIG_FIQ */
+
static int
imx_gpio_irq_type(unsigned int _irq, unsigned int type)
{
imx_gpio_handler(unsigned int mask, unsigned int irq,
struct irq_desc *desc)
{
- desc = irq_desc + irq;
while (mask) {
if (mask & 1) {
DEBUG_IRQ("handling irq %d\n", irq);
- desc_handle_irq(irq, desc);
+ generic_handle_irq(irq);
}
irq++;
- desc++;
mask >>= 1;
}
}
/* Release masking of interrupts according to priority */
__raw_writel(-1, IMX_AITC_NIMASK);
+
+ #ifdef CONFIG_FIQ
+ /* Initialize FIQ */
+ init_FIQ();
+ #endif
}
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/serial_8250.h>
+ #include <linux/irq.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/map.h>
#include <mach/common.h>
#include <mach/board-mx31ads.h>
+ #include <mach/imx-uart.h>
+ #include <mach/iomux-mx3.h>
/*!
* @file mx31ads.c
}
#endif
+ #if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
+ static struct imxuart_platform_data uart_pdata = {
+ .flags = IMXUART_HAVE_RTSCTS,
+ };
+
+ static inline void mxc_init_imx_uart(void)
+ {
+ mxc_iomux_mode(MX31_PIN_CTS1__CTS1);
+ mxc_iomux_mode(MX31_PIN_RTS1__RTS1);
+ mxc_iomux_mode(MX31_PIN_TXD1__TXD1);
+ mxc_iomux_mode(MX31_PIN_RXD1__RXD1);
+
+ mxc_register_device(&mxc_uart_device0, &uart_pdata);
+ }
+ #else /* !SERIAL_IMX */
+ static inline void mxc_init_imx_uart(void)
+ {
+ }
+ #endif /* !SERIAL_IMX */
+
+ static void mx31ads_expio_irq_handler(u32 irq, struct irq_desc *desc)
+ {
+ u32 imr_val;
+ u32 int_valid;
+ u32 expio_irq;
+
+ imr_val = __raw_readw(PBC_INTMASK_SET_REG);
+ int_valid = __raw_readw(PBC_INTSTATUS_REG) & imr_val;
+
+ expio_irq = MXC_EXP_IO_BASE;
+ for (; int_valid != 0; int_valid >>= 1, expio_irq++) {
+ if ((int_valid & 1) == 0)
+ continue;
+
+ generic_handle_irq(expio_irq);
+ }
+ }
+
+ /*
+ * Disable an expio pin's interrupt by setting the bit in the imr.
+ * @param irq an expio virtual irq number
+ */
+ static void expio_mask_irq(u32 irq)
+ {
+ u32 expio = MXC_IRQ_TO_EXPIO(irq);
+ /* mask the interrupt */
+ __raw_writew(1 << expio, PBC_INTMASK_CLEAR_REG);
+ __raw_readw(PBC_INTMASK_CLEAR_REG);
+ }
+
+ /*
+ * Acknowledge an expanded io pin's interrupt by clearing the bit in the isr.
+ * @param irq an expanded io virtual irq number
+ */
+ static void expio_ack_irq(u32 irq)
+ {
+ u32 expio = MXC_IRQ_TO_EXPIO(irq);
+ /* clear the interrupt status */
+ __raw_writew(1 << expio, PBC_INTSTATUS_REG);
+ }
+
+ /*
+ * Enable a expio pin's interrupt by clearing the bit in the imr.
+ * @param irq a expio virtual irq number
+ */
+ static void expio_unmask_irq(u32 irq)
+ {
+ u32 expio = MXC_IRQ_TO_EXPIO(irq);
+ /* unmask the interrupt */
+ __raw_writew(1 << expio, PBC_INTMASK_SET_REG);
+ }
+
+ static struct irq_chip expio_irq_chip = {
+ .ack = expio_ack_irq,
+ .mask = expio_mask_irq,
+ .unmask = expio_unmask_irq,
+ };
+
+ static void __init mx31ads_init_expio(void)
+ {
+ int i;
+
+ printk(KERN_INFO "MX31ADS EXPIO(CPLD) hardware\n");
+
+ /*
+ * Configure INT line as GPIO input
+ */
+ mxc_iomux_mode(IOMUX_MODE(MX31_PIN_GPIO1_4, IOMUX_CONFIG_GPIO));
+
+ /* disable the interrupt and clear the status */
+ __raw_writew(0xFFFF, PBC_INTMASK_CLEAR_REG);
+ __raw_writew(0xFFFF, PBC_INTSTATUS_REG);
+ for (i = MXC_EXP_IO_BASE; i < (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES);
+ i++) {
+ set_irq_chip(i, &expio_irq_chip);
+ set_irq_handler(i, handle_level_irq);
+ set_irq_flags(i, IRQF_VALID);
+ }
+ set_irq_type(EXPIO_PARENT_INT, IRQ_TYPE_LEVEL_HIGH);
+ set_irq_chained_handler(EXPIO_PARENT_INT, mx31ads_expio_irq_handler);
+ }
+
/*!
* This structure defines static mappings for the i.MX31ADS board.
*/
.virtual = AIPS1_BASE_ADDR_VIRT,
.pfn = __phys_to_pfn(AIPS1_BASE_ADDR),
.length = AIPS1_SIZE,
- .type = MT_NONSHARED_DEVICE
+ .type = MT_DEVICE_NONSHARED
}, {
.virtual = SPBA0_BASE_ADDR_VIRT,
.pfn = __phys_to_pfn(SPBA0_BASE_ADDR),
.length = SPBA0_SIZE,
- .type = MT_NONSHARED_DEVICE
+ .type = MT_DEVICE_NONSHARED
}, {
.virtual = AIPS2_BASE_ADDR_VIRT,
.pfn = __phys_to_pfn(AIPS2_BASE_ADDR),
.length = AIPS2_SIZE,
- .type = MT_NONSHARED_DEVICE
+ .type = MT_DEVICE_NONSHARED
}, {
.virtual = CS4_BASE_ADDR_VIRT,
.pfn = __phys_to_pfn(CS4_BASE_ADDR),
iotable_init(mx31ads_io_desc, ARRAY_SIZE(mx31ads_io_desc));
}
+ void __init mx31ads_init_irq(void)
+ {
+ mxc_init_irq();
+ mx31ads_init_expio();
+ }
+
/*!
* Board specific initialization.
*/
static void __init mxc_board_init(void)
{
mxc_init_extuart();
+ mxc_init_imx_uart();
}
static void __init mx31ads_timer_init(void)
.io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = PHYS_OFFSET + 0x100,
.map_io = mx31ads_map_io,
- .init_irq = mxc_init_irq,
+ .init_irq = mx31ads_init_irq,
.init_machine = mxc_board_init,
.timer = &mx31ads_timer,
MACHINE_END
*/
#include <linux/irq.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <mach/common.h>
#define AVIC_BASE IO_ADDRESS(AVIC_BASE_ADDR)
#define AVIC_INTENABLEL (AVIC_BASE + 0x14) /* int enable reg low */
#define AVIC_INTTYPEH (AVIC_BASE + 0x18) /* int type reg high */
#define AVIC_INTTYPEL (AVIC_BASE + 0x1C) /* int type reg low */
- #define AVIC_NIPRIORITY7 (AVIC_BASE + 0x20) /* norm int priority lvl7 */
- #define AVIC_NIPRIORITY6 (AVIC_BASE + 0x24) /* norm int priority lvl6 */
- #define AVIC_NIPRIORITY5 (AVIC_BASE + 0x28) /* norm int priority lvl5 */
- #define AVIC_NIPRIORITY4 (AVIC_BASE + 0x2C) /* norm int priority lvl4 */
- #define AVIC_NIPRIORITY3 (AVIC_BASE + 0x30) /* norm int priority lvl3 */
- #define AVIC_NIPRIORITY2 (AVIC_BASE + 0x34) /* norm int priority lvl2 */
- #define AVIC_NIPRIORITY1 (AVIC_BASE + 0x38) /* norm int priority lvl1 */
- #define AVIC_NIPRIORITY0 (AVIC_BASE + 0x3C) /* norm int priority lvl0 */
+ #define AVIC_NIPRIORITY(x) (AVIC_BASE + (0x20 + 4 * (7 - (x)))) /* int priority */
#define AVIC_NIVECSR (AVIC_BASE + 0x40) /* norm int vector/status */
#define AVIC_FIVECSR (AVIC_BASE + 0x44) /* fast int vector/status */
#define AVIC_INTSRCH (AVIC_BASE + 0x48) /* int source reg high */
#define IIM_PROD_REV_SH 3
#define IIM_PROD_REV_LEN 5
+ #ifdef CONFIG_MXC_IRQ_PRIOR
+ void imx_irq_set_priority(unsigned char irq, unsigned char prio)
+ {
+ unsigned int temp;
+ unsigned int mask = 0x0F << irq % 8 * 4;
+
+ if (irq > 63)
+ return;
+
+ temp = __raw_readl(AVIC_NIPRIORITY(irq / 8));
+ temp &= ~mask;
+ temp |= prio & mask;
+
+ __raw_writel(temp, AVIC_NIPRIORITY(irq / 8));
+ }
+ EXPORT_SYMBOL(imx_irq_set_priority);
+ #endif
+
/* Disable interrupt number "irq" in the AVIC */
static void mxc_mask_irq(unsigned int irq)
{
set_irq_flags(i, IRQF_VALID);
}
- /* Set WDOG2's interrupt the highest priority level (bit 28-31) */
- reg = __raw_readl(AVIC_NIPRIORITY6);
- reg |= (0xF << 28);
- __raw_writel(reg, AVIC_NIPRIORITY6);
+ /* Set default priority value (0) for all IRQ's */
+ for (i = 0; i < 8; i++)
+ __raw_writel(0, AVIC_NIPRIORITY(i));
/* init architectures chained interrupt handler */
mxc_register_gpios();