Skip to content

Commit

Permalink
mx51: support FIQ on TZIC, revised
Browse files Browse the repository at this point in the history
Add support for FIQ on mx51 TZIC

TZIC changes tested with FIQ audio on an mx51 board

AVIC changes build with mx3_defconfig, not tested

Signed-off-by: Peter Horton <phorton@bitbox.co.uk>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
  • Loading branch information
Peter Horton authored and Sascha Hauer committed Dec 14, 2010
1 parent 8be9252 commit cdc3f10
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 28 deletions.
2 changes: 1 addition & 1 deletion arch/arm/plat-mxc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#

# Common support
obj-y := clock.o gpio.o time.o devices.o cpu.o system.o
obj-y := clock.o gpio.o time.o devices.o cpu.o system.o irq-common.o

# MX51 uses the TZIC interrupt controller, older platforms use AVIC
obj-$(CONFIG_MXC_TZIC) += tzic.o
Expand Down
32 changes: 19 additions & 13 deletions arch/arm/plat-mxc/avic.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include <asm/mach/irq.h>
#include <mach/hardware.h>

#include "irq-common.h"

#define AVIC_INTCNTL 0x00 /* int control reg */
#define AVIC_NIMASK 0x04 /* int mask reg */
#define AVIC_INTENNUM 0x08 /* int enable number reg */
Expand All @@ -46,9 +48,9 @@

void __iomem *avic_base;

int imx_irq_set_priority(unsigned char irq, unsigned char prio)
{
#ifdef CONFIG_MXC_IRQ_PRIOR
static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
{
unsigned int temp;
unsigned int mask = 0x0F << irq % 8 * 4;

Expand All @@ -62,14 +64,11 @@ int imx_irq_set_priority(unsigned char irq, unsigned char prio)
__raw_writel(temp, avic_base + AVIC_NIPRIORITY(irq / 8));

return 0;
#else
return -ENOSYS;
#endif
}
EXPORT_SYMBOL(imx_irq_set_priority);
#endif

#ifdef CONFIG_FIQ
int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
static int avic_set_irq_fiq(unsigned int irq, unsigned int type)
{
unsigned int irqt;

Expand All @@ -87,7 +86,6 @@ int mxc_set_irq_fiq(unsigned int irq, unsigned int type)

return 0;
}
EXPORT_SYMBOL(mxc_set_irq_fiq);
#endif /* CONFIG_FIQ */

/* Disable interrupt number "irq" in the AVIC */
Expand All @@ -102,10 +100,18 @@ static void mxc_unmask_irq(unsigned int irq)
__raw_writel(irq, avic_base + AVIC_INTENNUM);
}

static struct irq_chip mxc_avic_chip = {
.ack = mxc_mask_irq,
.mask = mxc_mask_irq,
.unmask = mxc_unmask_irq,
static struct mxc_irq_chip mxc_avic_chip = {
.base = {
.ack = mxc_mask_irq,
.mask = mxc_mask_irq,
.unmask = mxc_unmask_irq,
},
#ifdef CONFIG_MXC_IRQ_PRIOR
.set_priority = avic_irq_set_priority,
#endif
#ifdef CONFIG_FIQ
.set_irq_fiq = avic_set_irq_fiq,
#endif
};

/*
Expand Down Expand Up @@ -133,7 +139,7 @@ void __init mxc_init_irq(void __iomem *irqbase)
__raw_writel(0, avic_base + AVIC_INTTYPEH);
__raw_writel(0, avic_base + AVIC_INTTYPEL);
for (i = 0; i < MXC_INTERNAL_IRQS; i++) {
set_irq_chip(i, &mxc_avic_chip);
set_irq_chip(i, &mxc_avic_chip.base);
set_irq_handler(i, handle_level_irq);
set_irq_flags(i, IRQF_VALID);
}
Expand Down
14 changes: 7 additions & 7 deletions arch/arm/plat-mxc/include/mach/entry-macro.S
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@
#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
mov \irqstat, #0x0D80
1000:
ldr \tmp, [\irqstat, \base]
cmp \tmp, #0
bne 1001f
addeq \irqnr, \irqnr, #32
addeq \irqstat, \irqstat, #4
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
Expand Down
60 changes: 60 additions & 0 deletions arch/arm/plat-mxc/irq-common.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (C) BitBox Ltd 2010
*
* 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 program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/

#include <linux/module.h>
#include <linux/irq.h>

#include "irq-common.h"

int imx_irq_set_priority(unsigned char irq, unsigned char prio)
{
struct mxc_irq_chip *chip;
struct irq_chip *base;
int ret;

ret = -ENOSYS;

base = get_irq_chip(irq);
if (base) {
chip = container_of(base, struct mxc_irq_chip, base);
if (chip->set_priority)
ret = chip->set_priority(irq, prio);
}

return ret;
}
EXPORT_SYMBOL(imx_irq_set_priority);

int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
{
struct mxc_irq_chip *chip;
struct irq_chip *base;
int ret;

ret = -ENOSYS;

base = get_irq_chip(irq);
if (base) {
chip = container_of(base, struct mxc_irq_chip, base);
if (chip->set_irq_fiq)
ret = chip->set_irq_fiq(irq, type);
}

return ret;
}
EXPORT_SYMBOL(mxc_set_irq_fiq);
29 changes: 29 additions & 0 deletions arch/arm/plat-mxc/irq-common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (C) BitBox Ltd 2010
*
* 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 program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/

#ifndef __PLAT_MXC_IRQ_COMMON_H__
#define __PLAT_MXC_IRQ_COMMON_H__

struct mxc_irq_chip
{
struct irq_chip base;
int (*set_priority)(unsigned char irq, unsigned char prio);
int (*set_irq_fiq)(unsigned int irq, unsigned int type);
};

#endif
46 changes: 39 additions & 7 deletions arch/arm/plat-mxc/tzic.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include <mach/hardware.h>
#include <mach/common.h>

#include "irq-common.h"

/*
*****************************************
* TZIC Registers *
Expand All @@ -47,6 +49,25 @@

void __iomem *tzic_base; /* Used as irq controller base in entry-macro.S */

#ifdef CONFIG_FIQ
static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
{
unsigned int index, mask, value;

index = irq >> 5;
if (unlikely(index >= 4))
return -EINVAL;
mask = 1U << (irq & 0x1F);

value = __raw_readl(tzic_base + TZIC_INTSEC0(index)) | mask;
if (type)
value &= ~mask;
__raw_writel(value, tzic_base + TZIC_INTSEC0(index));

return 0;
}
#endif

/**
* tzic_mask_irq() - Disable interrupt number "irq" in the TZIC
*
Expand Down Expand Up @@ -104,12 +125,17 @@ static int tzic_set_wake_irq(unsigned int irq, unsigned int enable)
return 0;
}

static struct irq_chip mxc_tzic_chip = {
.name = "MXC_TZIC",
.ack = tzic_mask_irq,
.mask = tzic_mask_irq,
.unmask = tzic_unmask_irq,
.set_wake = tzic_set_wake_irq,
static struct mxc_irq_chip mxc_tzic_chip = {
.base = {
.name = "MXC_TZIC",
.ack = tzic_mask_irq,
.mask = tzic_mask_irq,
.unmask = tzic_unmask_irq,
.set_wake = tzic_set_wake_irq,
},
#ifdef CONFIG_FIQ
.set_irq_fiq = tzic_set_irq_fiq,
#endif
};

/*
Expand Down Expand Up @@ -141,10 +167,16 @@ void __init tzic_init_irq(void __iomem *irqbase)
/* all IRQ no FIQ Warning :: No selection */

for (i = 0; i < MXC_INTERNAL_IRQS; i++) {
set_irq_chip(i, &mxc_tzic_chip);
set_irq_chip(i, &mxc_tzic_chip.base);
set_irq_handler(i, handle_level_irq);
set_irq_flags(i, IRQF_VALID);
}

#ifdef CONFIG_FIQ
/* Initialize FIQ */
init_FIQ();
#endif

pr_info("TrustZone Interrupt Controller (TZIC) initialized\n");
}

Expand Down

0 comments on commit cdc3f10

Please sign in to comment.