summaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-mxc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-mxc')
-rw-r--r--arch/arm/plat-mxc/avic.c91
-rw-r--r--arch/arm/plat-mxc/devices/platform-pata_imx.c2
-rw-r--r--arch/arm/plat-mxc/include/mach/common.h14
-rw-r--r--arch/arm/plat-mxc/include/mach/entry-macro.S58
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux-mx3.h1
-rw-r--r--arch/arm/plat-mxc/include/mach/mx25.h1
-rw-r--r--arch/arm/plat-mxc/irq-common.c21
-rw-r--r--arch/arm/plat-mxc/irq-common.h3
-rw-r--r--arch/arm/plat-mxc/tzic.c32
9 files changed, 128 insertions, 95 deletions
diff --git a/arch/arm/plat-mxc/avic.c b/arch/arm/plat-mxc/avic.c
index 55d2534ec727..8875fb415f68 100644
--- a/arch/arm/plat-mxc/avic.c
+++ b/arch/arm/plat-mxc/avic.c
@@ -50,6 +50,8 @@
void __iomem *avic_base;
+static u32 avic_saved_mask_reg[2];
+
#ifdef CONFIG_MXC_IRQ_PRIOR
static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
{
@@ -90,24 +92,8 @@ static int avic_set_irq_fiq(unsigned int irq, unsigned int type)
}
#endif /* CONFIG_FIQ */
-/* Disable interrupt number "irq" in the AVIC */
-static void mxc_mask_irq(struct irq_data *d)
-{
- __raw_writel(d->irq, avic_base + AVIC_INTDISNUM);
-}
-/* Enable interrupt number "irq" in the AVIC */
-static void mxc_unmask_irq(struct irq_data *d)
-{
- __raw_writel(d->irq, avic_base + AVIC_INTENNUM);
-}
-
-static struct mxc_irq_chip mxc_avic_chip = {
- .base = {
- .irq_ack = mxc_mask_irq,
- .irq_mask = mxc_mask_irq,
- .irq_unmask = mxc_unmask_irq,
- },
+static struct mxc_extra_irq avic_extra_irq = {
#ifdef CONFIG_MXC_IRQ_PRIOR
.set_priority = avic_irq_set_priority,
#endif
@@ -116,6 +102,68 @@ static struct mxc_irq_chip mxc_avic_chip = {
#endif
};
+#ifdef CONFIG_PM
+static void avic_irq_suspend(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = gc->chip_types;
+ int idx = gc->irq_base >> 5;
+
+ avic_saved_mask_reg[idx] = __raw_readl(avic_base + ct->regs.mask);
+ __raw_writel(gc->wake_active, avic_base + ct->regs.mask);
+}
+
+static void avic_irq_resume(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = gc->chip_types;
+ int idx = gc->irq_base >> 5;
+
+ __raw_writel(avic_saved_mask_reg[idx], avic_base + ct->regs.mask);
+}
+
+#else
+#define avic_irq_suspend NULL
+#define avic_irq_resume NULL
+#endif
+
+static __init void avic_init_gc(unsigned int irq_start)
+{
+ struct irq_chip_generic *gc;
+ struct irq_chip_type *ct;
+ int idx = irq_start >> 5;
+
+ gc = irq_alloc_generic_chip("mxc-avic", 1, irq_start, avic_base,
+ handle_level_irq);
+ gc->private = &avic_extra_irq;
+ gc->wake_enabled = IRQ_MSK(32);
+
+ ct = gc->chip_types;
+ ct->chip.irq_mask = irq_gc_mask_clr_bit;
+ ct->chip.irq_unmask = irq_gc_mask_set_bit;
+ ct->chip.irq_ack = irq_gc_mask_clr_bit;
+ ct->chip.irq_set_wake = irq_gc_set_wake;
+ ct->chip.irq_suspend = avic_irq_suspend;
+ ct->chip.irq_resume = avic_irq_resume;
+ ct->regs.mask = !idx ? AVIC_INTENABLEL : AVIC_INTENABLEH;
+ ct->regs.ack = ct->regs.mask;
+
+ irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
+}
+
+asmlinkage void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
+{
+ u32 nivector;
+
+ do {
+ nivector = __raw_readl(avic_base + AVIC_NIVECSR) >> 16;
+ if (nivector == 0xffff)
+ break;
+
+ handle_IRQ(nivector, regs);
+ } while (1);
+}
+
/*
* This function initializes the AVIC hardware and disables all the
* interrupts. It registers the interrupt enable and disable functions
@@ -140,11 +188,9 @@ void __init mxc_init_irq(void __iomem *irqbase)
/* all IRQ no FIQ */
__raw_writel(0, avic_base + AVIC_INTTYPEH);
__raw_writel(0, avic_base + AVIC_INTTYPEL);
- for (i = 0; i < AVIC_NUM_IRQS; i++) {
- irq_set_chip_and_handler(i, &mxc_avic_chip.base,
- handle_level_irq);
- set_irq_flags(i, IRQF_VALID);
- }
+
+ for (i = 0; i < AVIC_NUM_IRQS; i += 32)
+ avic_init_gc(i);
/* Set default priority value (0) for all IRQ's */
for (i = 0; i < 8; i++)
@@ -157,4 +203,3 @@ void __init mxc_init_irq(void __iomem *irqbase)
printk(KERN_INFO "MXC IRQ initialized\n");
}
-
diff --git a/arch/arm/plat-mxc/devices/platform-pata_imx.c b/arch/arm/plat-mxc/devices/platform-pata_imx.c
index de33048aad6a..70e2f2a44714 100644
--- a/arch/arm/plat-mxc/devices/platform-pata_imx.c
+++ b/arch/arm/plat-mxc/devices/platform-pata_imx.c
@@ -44,7 +44,7 @@ struct platform_device *__init imx_add_pata_imx(
struct resource res[] = {
{
.start = data->iobase,
- .end = data->iobase + data->iobase - 1,
+ .end = data->iobase + data->iosize - 1,
.flags = IORESOURCE_MEM,
},
{
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index 318e0da13a79..5bee446db51f 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -73,4 +73,18 @@ extern void mx51_efikamx_reset(void);
extern int mx53_revision(void);
extern int mx53_display_revision(void);
extern void imx_print_silicon_rev(const char *cpu, int srev);
+
+void avic_handle_irq(struct pt_regs *);
+void tzic_handle_irq(struct pt_regs *);
+
+#define imx1_handle_irq avic_handle_irq
+#define imx21_handle_irq avic_handle_irq
+#define imx25_handle_irq avic_handle_irq
+#define imx27_handle_irq avic_handle_irq
+#define imx31_handle_irq avic_handle_irq
+#define imx35_handle_irq avic_handle_irq
+#define imx50_handle_irq tzic_handle_irq
+#define imx51_handle_irq tzic_handle_irq
+#define imx53_handle_irq tzic_handle_irq
+
#endif
diff --git a/arch/arm/plat-mxc/include/mach/entry-macro.S b/arch/arm/plat-mxc/include/mach/entry-macro.S
index 066d464d322d..842fbcb0d6cc 100644
--- a/arch/arm/plat-mxc/include/mach/entry-macro.S
+++ b/arch/arm/plat-mxc/include/mach/entry-macro.S
@@ -9,72 +9,16 @@
* published by the Free Software Foundation.
*/
-#include <mach/hardware.h>
+/* Unused, we use CONFIG_MULTI_IRQ_HANDLER */
-#define AVIC_NIMASK 0x04
-
- @ this macro disables fast irq (not implemented)
.macro disable_fiq
.endm
.macro get_irqnr_preamble, base, tmp
-#ifndef CONFIG_MXC_TZIC
- ldr \base, =avic_base
- ldr \base, [\base]
-#ifdef CONFIG_MXC_IRQ_PRIOR
- ldr r4, [\base, #AVIC_NIMASK]
-#endif
-#elif defined CONFIG_MXC_TZIC
- ldr \base, =tzic_base
- ldr \base, [\base]
-#endif /* CONFIG_MXC_TZIC */
.endm
.macro arch_ret_to_user, tmp1, tmp2
.endm
- @ this macro checks which interrupt occurred
- @ and returns its number in irqnr
- @ and returns if an interrupt occurred in irqstat
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-#ifndef CONFIG_MXC_TZIC
- @ Load offset & priority of the highest priority
- @ interrupt pending from AVIC_NIVECSR
- ldr \irqstat, [\base, #0x40]
- @ Shift to get the decoded IRQ number, using ASR so
- @ 'no interrupt pending' becomes 0xffffffff
- mov \irqnr, \irqstat, asr #16
- @ set zero flag if IRQ + 1 == 0
- adds \tmp, \irqnr, #1
-#ifdef CONFIG_MXC_IRQ_PRIOR
- bicne \tmp, \irqstat, #0xFFFFFFE0
- strne \tmp, [\base, #AVIC_NIMASK]
- streq r4, [\base, #AVIC_NIMASK]
-#endif
-#elif defined CONFIG_MXC_TZIC
- @ Load offset & priority of the highest priority
- @ interrupt pending.
- @ 0x080 is INTSEC0 register
- @ 0xD80 is HIPND0 register
- mov \irqnr, #0
-1000: add \irqstat, \base, \irqnr, lsr #3
- ldr \tmp, [\irqstat, #0xd80]
- ldr \irqstat, [\irqstat, #0x080]
- ands \tmp, \tmp, \irqstat
- bne 1001f
- add \irqnr, \irqnr, #32
- cmp \irqnr, #128
- blo 1000b
- b 2001f
-1001: mov \irqstat, #1
-1002: tst \tmp, \irqstat
- bne 2002f
- movs \tmp, \tmp, lsr #1
- addne \irqnr, \irqnr, #1
- bne 1002b
-2001:
- mov \irqnr, #0
-2002:
- movs \irqnr, \irqnr
-#endif
.endm
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx3.h b/arch/arm/plat-mxc/include/mach/iomux-mx3.h
index c92f0b1f216f..63f22a009a65 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx3.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx3.h
@@ -735,6 +735,7 @@ enum iomux_pins {
#define MX31_PIN_KEY_COL5_KEY_COL5 IOMUX_MODE(MX31_PIN_KEY_COL5, IOMUX_CONFIG_FUNC)
#define MX31_PIN_KEY_COL6_KEY_COL6 IOMUX_MODE(MX31_PIN_KEY_COL6, IOMUX_CONFIG_FUNC)
#define MX31_PIN_KEY_COL7_KEY_COL7 IOMUX_MODE(MX31_PIN_KEY_COL7, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_WATCHDOG_RST__WATCHDOG_RST IOMUX_MODE(MX31_PIN_WATCHDOG_RST, IOMUX_CONFIG_FUNC)
/*
diff --git a/arch/arm/plat-mxc/include/mach/mx25.h b/arch/arm/plat-mxc/include/mach/mx25.h
index 8dcab80acff3..ccebf5ba12f0 100644
--- a/arch/arm/plat-mxc/include/mach/mx25.h
+++ b/arch/arm/plat-mxc/include/mach/mx25.h
@@ -41,6 +41,7 @@
#define MX25_SSI2_BASE_ADDR 0x50014000
#define MX25_SSI1_BASE_ADDR 0x50034000
#define MX25_NFC_BASE_ADDR 0xbb000000
+#define MX25_IIM_BASE_ADDR 0x53ff0000
#define MX25_DRYICE_BASE_ADDR 0x53ffc000
#define MX25_ESDHC1_BASE_ADDR 0x53fb4000
#define MX25_ESDHC2_BASE_ADDR 0x53fb8000
diff --git a/arch/arm/plat-mxc/irq-common.c b/arch/arm/plat-mxc/irq-common.c
index 96953e2e4f11..b6e11458e5ae 100644
--- a/arch/arm/plat-mxc/irq-common.c
+++ b/arch/arm/plat-mxc/irq-common.c
@@ -23,17 +23,17 @@
int imx_irq_set_priority(unsigned char irq, unsigned char prio)
{
- struct mxc_irq_chip *chip;
- struct irq_chip *base;
+ struct irq_chip_generic *gc;
+ struct mxc_extra_irq *exirq;
int ret;
ret = -ENOSYS;
- base = irq_get_chip(irq);
- if (base) {
- chip = container_of(base, struct mxc_irq_chip, base);
- if (chip->set_priority)
- ret = chip->set_priority(irq, prio);
+ gc = irq_get_chip_data(irq);
+ if (gc && gc->private) {
+ exirq = gc->private;
+ if (exirq->set_priority)
+ ret = exirq->set_priority(irq, prio);
}
return ret;
@@ -43,15 +43,16 @@ EXPORT_SYMBOL(imx_irq_set_priority);
int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
{
struct irq_chip_generic *gc;
- int (*set_irq_fiq)(unsigned int, unsigned int);
+ struct mxc_extra_irq *exirq;
int ret;
ret = -ENOSYS;
gc = irq_get_chip_data(irq);
if (gc && gc->private) {
- set_irq_fiq = gc->private;
- ret = set_irq_fiq(irq, type);
+ exirq = gc->private;
+ if (exirq->set_irq_fiq)
+ ret = exirq->set_irq_fiq(irq, type);
}
return ret;
diff --git a/arch/arm/plat-mxc/irq-common.h b/arch/arm/plat-mxc/irq-common.h
index 7203543fb1b3..6ccb3a14c693 100644
--- a/arch/arm/plat-mxc/irq-common.h
+++ b/arch/arm/plat-mxc/irq-common.h
@@ -19,9 +19,8 @@
#ifndef __PLAT_MXC_IRQ_COMMON_H__
#define __PLAT_MXC_IRQ_COMMON_H__
-struct mxc_irq_chip
+struct mxc_extra_irq
{
- struct irq_chip base;
int (*set_priority)(unsigned char irq, unsigned char prio);
int (*set_irq_fiq)(unsigned int irq, unsigned int type);
};
diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c
index f257fccdc394..e993a184189a 100644
--- a/arch/arm/plat-mxc/tzic.c
+++ b/arch/arm/plat-mxc/tzic.c
@@ -42,7 +42,7 @@
#define TZIC_SRCCLAR0 0x0280 /* Source Clear Register 0 */
#define TZIC_PRIORITY0 0x0400 /* Priority Register 0 */
#define TZIC_PND0 0x0D00 /* Pending Register 0 */
-#define TZIC_HIPND0 0x0D80 /* High Priority Pending Register */
+#define TZIC_HIPND(i) (0x0D80+ ((i) << 2)) /* High Priority Pending Register */
#define TZIC_WAKEUP0(i) (0x0E00 + ((i) << 2)) /* Wakeup Config Register */
#define TZIC_SWINT 0x0F00 /* Software Interrupt Rigger Register */
#define TZIC_ID0 0x0FD0 /* Indentification Register 0 */
@@ -74,6 +74,12 @@ static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
static unsigned int *wakeup_intr[4];
+static struct mxc_extra_irq tzic_extra_irq = {
+#ifdef CONFIG_FIQ
+ .set_irq_fiq = tzic_set_irq_fiq,
+#endif
+};
+
static __init void tzic_init_gc(unsigned int irq_start)
{
struct irq_chip_generic *gc;
@@ -82,7 +88,7 @@ static __init void tzic_init_gc(unsigned int irq_start)
gc = irq_alloc_generic_chip("tzic", 1, irq_start, tzic_base,
handle_level_irq);
- gc->private = tzic_set_irq_fiq;
+ gc->private = &tzic_extra_irq;
gc->wake_enabled = IRQ_MSK(32);
wakeup_intr[idx] = &gc->wake_active;
@@ -96,6 +102,28 @@ static __init void tzic_init_gc(unsigned int irq_start)
irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
}
+asmlinkage void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs)
+{
+ u32 stat;
+ int i, irqofs, handled;
+
+ do {
+ handled = 0;
+
+ for (i = 0; i < 4; i++) {
+ stat = __raw_readl(tzic_base + TZIC_HIPND(i)) &
+ __raw_readl(tzic_base + TZIC_INTSEC0(i));
+
+ while (stat) {
+ handled = 1;
+ irqofs = fls(stat) - 1;
+ handle_IRQ(irqofs + i * 32, regs);
+ stat &= ~(1 << irqofs);
+ }
+ }
+ } while (handled);
+}
+
/*
* This function initializes the TZIC hardware and disables all the
* interrupts. It registers the interrupt enable and disable functions
OpenPOWER on IntegriCloud