summaryrefslogtreecommitdiffstats
path: root/arch/arm/common/sa1111.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/common/sa1111.c')
-rw-r--r--arch/arm/common/sa1111.c126
1 files changed, 97 insertions, 29 deletions
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 8ba7044c554d..9eaf65f43642 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -35,6 +35,58 @@
#include <asm/hardware/sa1111.h>
+/* SA1111 IRQs */
+#define IRQ_GPAIN0 (0)
+#define IRQ_GPAIN1 (1)
+#define IRQ_GPAIN2 (2)
+#define IRQ_GPAIN3 (3)
+#define IRQ_GPBIN0 (4)
+#define IRQ_GPBIN1 (5)
+#define IRQ_GPBIN2 (6)
+#define IRQ_GPBIN3 (7)
+#define IRQ_GPBIN4 (8)
+#define IRQ_GPBIN5 (9)
+#define IRQ_GPCIN0 (10)
+#define IRQ_GPCIN1 (11)
+#define IRQ_GPCIN2 (12)
+#define IRQ_GPCIN3 (13)
+#define IRQ_GPCIN4 (14)
+#define IRQ_GPCIN5 (15)
+#define IRQ_GPCIN6 (16)
+#define IRQ_GPCIN7 (17)
+#define IRQ_MSTXINT (18)
+#define IRQ_MSRXINT (19)
+#define IRQ_MSSTOPERRINT (20)
+#define IRQ_TPTXINT (21)
+#define IRQ_TPRXINT (22)
+#define IRQ_TPSTOPERRINT (23)
+#define SSPXMTINT (24)
+#define SSPRCVINT (25)
+#define SSPROR (26)
+#define AUDXMTDMADONEA (32)
+#define AUDRCVDMADONEA (33)
+#define AUDXMTDMADONEB (34)
+#define AUDRCVDMADONEB (35)
+#define AUDTFSR (36)
+#define AUDRFSR (37)
+#define AUDTUR (38)
+#define AUDROR (39)
+#define AUDDTS (40)
+#define AUDRDD (41)
+#define AUDSTO (42)
+#define IRQ_USBPWR (43)
+#define IRQ_HCIM (44)
+#define IRQ_HCIBUFFACC (45)
+#define IRQ_HCIRMTWKP (46)
+#define IRQ_NHCIMFCIR (47)
+#define IRQ_USB_PORT_RESUME (48)
+#define IRQ_S0_READY_NINT (49)
+#define IRQ_S1_READY_NINT (50)
+#define IRQ_S0_CD_VALID (51)
+#define IRQ_S1_CD_VALID (52)
+#define IRQ_S0_BVD1_STSCHG (53)
+#define IRQ_S1_BVD1_STSCHG (54)
+
extern void __init sa1110_mb_enable(void);
/*
@@ -49,6 +101,7 @@ struct sa1111 {
struct clk *clk;
unsigned long phys;
int irq;
+ int irq_base; /* base for cascaded on-chip IRQs */
spinlock_t lock;
void __iomem *base;
#ifdef CONFIG_PM
@@ -152,36 +205,37 @@ static void
sa1111_irq_handler(unsigned int irq, struct irq_desc *desc)
{
unsigned int stat0, stat1, i;
- void __iomem *base = get_irq_data(irq);
+ struct sa1111 *sachip = get_irq_data(irq);
+ void __iomem *mapbase = sachip->base + SA1111_INTC;
- stat0 = sa1111_readl(base + SA1111_INTSTATCLR0);
- stat1 = sa1111_readl(base + SA1111_INTSTATCLR1);
+ stat0 = sa1111_readl(mapbase + SA1111_INTSTATCLR0);
+ stat1 = sa1111_readl(mapbase + SA1111_INTSTATCLR1);
- sa1111_writel(stat0, base + SA1111_INTSTATCLR0);
+ sa1111_writel(stat0, mapbase + SA1111_INTSTATCLR0);
desc->chip->ack(irq);
- sa1111_writel(stat1, base + SA1111_INTSTATCLR1);
+ sa1111_writel(stat1, mapbase + SA1111_INTSTATCLR1);
if (stat0 == 0 && stat1 == 0) {
do_bad_IRQ(irq, desc);
return;
}
- for (i = IRQ_SA1111_START; stat0; i++, stat0 >>= 1)
+ for (i = 0; stat0; i++, stat0 >>= 1)
if (stat0 & 1)
- handle_edge_irq(i, irq_desc + i);
+ generic_handle_irq(i + sachip->irq_base);
- for (i = IRQ_SA1111_START + 32; stat1; i++, stat1 >>= 1)
+ for (i = 32; stat1; i++, stat1 >>= 1)
if (stat1 & 1)
- handle_edge_irq(i, irq_desc + i);
+ generic_handle_irq(i + sachip->irq_base);
/* For level-based interrupts */
desc->chip->unmask(irq);
}
-#define SA1111_IRQMASK_LO(x) (1 << (x - IRQ_SA1111_START))
-#define SA1111_IRQMASK_HI(x) (1 << (x - IRQ_SA1111_START - 32))
+#define SA1111_IRQMASK_LO(x) (1 << (x - sachip->irq_base))
+#define SA1111_IRQMASK_HI(x) (1 << (x - sachip->irq_base - 32))
static void sa1111_ack_irq(unsigned int irq)
{
@@ -189,7 +243,8 @@ static void sa1111_ack_irq(unsigned int irq)
static void sa1111_mask_lowirq(unsigned int irq)
{
- void __iomem *mapbase = get_irq_chip_data(irq);
+ struct sa1111 *sachip = get_irq_chip_data(irq);
+ void __iomem *mapbase = sachip->base + SA1111_INTC;
unsigned long ie0;
ie0 = sa1111_readl(mapbase + SA1111_INTEN0);
@@ -199,7 +254,8 @@ static void sa1111_mask_lowirq(unsigned int irq)
static void sa1111_unmask_lowirq(unsigned int irq)
{
- void __iomem *mapbase = get_irq_chip_data(irq);
+ struct sa1111 *sachip = get_irq_chip_data(irq);
+ void __iomem *mapbase = sachip->base + SA1111_INTC;
unsigned long ie0;
ie0 = sa1111_readl(mapbase + SA1111_INTEN0);
@@ -216,8 +272,9 @@ static void sa1111_unmask_lowirq(unsigned int irq)
*/
static int sa1111_retrigger_lowirq(unsigned int irq)
{
+ struct sa1111 *sachip = get_irq_chip_data(irq);
+ void __iomem *mapbase = sachip->base + SA1111_INTC;
unsigned int mask = SA1111_IRQMASK_LO(irq);
- void __iomem *mapbase = get_irq_chip_data(irq);
unsigned long ip0;
int i;
@@ -237,8 +294,9 @@ static int sa1111_retrigger_lowirq(unsigned int irq)
static int sa1111_type_lowirq(unsigned int irq, unsigned int flags)
{
+ struct sa1111 *sachip = get_irq_chip_data(irq);
+ void __iomem *mapbase = sachip->base + SA1111_INTC;
unsigned int mask = SA1111_IRQMASK_LO(irq);
- void __iomem *mapbase = get_irq_chip_data(irq);
unsigned long ip0;
if (flags == IRQ_TYPE_PROBE)
@@ -260,8 +318,9 @@ static int sa1111_type_lowirq(unsigned int irq, unsigned int flags)
static int sa1111_wake_lowirq(unsigned int irq, unsigned int on)
{
+ struct sa1111 *sachip = get_irq_chip_data(irq);
+ void __iomem *mapbase = sachip->base + SA1111_INTC;
unsigned int mask = SA1111_IRQMASK_LO(irq);
- void __iomem *mapbase = get_irq_chip_data(irq);
unsigned long we0;
we0 = sa1111_readl(mapbase + SA1111_WAKEEN0);
@@ -286,7 +345,8 @@ static struct irq_chip sa1111_low_chip = {
static void sa1111_mask_highirq(unsigned int irq)
{
- void __iomem *mapbase = get_irq_chip_data(irq);
+ struct sa1111 *sachip = get_irq_chip_data(irq);
+ void __iomem *mapbase = sachip->base + SA1111_INTC;
unsigned long ie1;
ie1 = sa1111_readl(mapbase + SA1111_INTEN1);
@@ -296,7 +356,8 @@ static void sa1111_mask_highirq(unsigned int irq)
static void sa1111_unmask_highirq(unsigned int irq)
{
- void __iomem *mapbase = get_irq_chip_data(irq);
+ struct sa1111 *sachip = get_irq_chip_data(irq);
+ void __iomem *mapbase = sachip->base + SA1111_INTC;
unsigned long ie1;
ie1 = sa1111_readl(mapbase + SA1111_INTEN1);
@@ -313,8 +374,9 @@ static void sa1111_unmask_highirq(unsigned int irq)
*/
static int sa1111_retrigger_highirq(unsigned int irq)
{
+ struct sa1111 *sachip = get_irq_chip_data(irq);
+ void __iomem *mapbase = sachip->base + SA1111_INTC;
unsigned int mask = SA1111_IRQMASK_HI(irq);
- void __iomem *mapbase = get_irq_chip_data(irq);
unsigned long ip1;
int i;
@@ -334,8 +396,9 @@ static int sa1111_retrigger_highirq(unsigned int irq)
static int sa1111_type_highirq(unsigned int irq, unsigned int flags)
{
+ struct sa1111 *sachip = get_irq_chip_data(irq);
+ void __iomem *mapbase = sachip->base + SA1111_INTC;
unsigned int mask = SA1111_IRQMASK_HI(irq);
- void __iomem *mapbase = get_irq_chip_data(irq);
unsigned long ip1;
if (flags == IRQ_TYPE_PROBE)
@@ -357,8 +420,9 @@ static int sa1111_type_highirq(unsigned int irq, unsigned int flags)
static int sa1111_wake_highirq(unsigned int irq, unsigned int on)
{
+ struct sa1111 *sachip = get_irq_chip_data(irq);
+ void __iomem *mapbase = sachip->base + SA1111_INTC;
unsigned int mask = SA1111_IRQMASK_HI(irq);
- void __iomem *mapbase = get_irq_chip_data(irq);
unsigned long we1;
we1 = sa1111_readl(mapbase + SA1111_WAKEEN1);
@@ -412,14 +476,14 @@ static void sa1111_setup_irq(struct sa1111 *sachip)
for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) {
set_irq_chip(irq, &sa1111_low_chip);
- set_irq_chip_data(irq, irqbase);
+ set_irq_chip_data(irq, sachip);
set_irq_handler(irq, handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
for (irq = AUDXMTDMADONEA; irq <= IRQ_S1_BVD1_STSCHG; irq++) {
set_irq_chip(irq, &sa1111_high_chip);
- set_irq_chip_data(irq, irqbase);
+ set_irq_chip_data(irq, sachip);
set_irq_handler(irq, handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
@@ -428,7 +492,7 @@ static void sa1111_setup_irq(struct sa1111 *sachip)
* Register SA1111 interrupt
*/
set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING);
- set_irq_data(sachip->irq, irqbase);
+ set_irq_data(sachip->irq, sachip);
set_irq_chained_handler(sachip->irq, sa1111_irq_handler);
}
@@ -887,8 +951,6 @@ static int sa1111_resume(struct platform_device *dev)
if (!save)
return 0;
- spin_lock_irqsave(&sachip->lock, flags);
-
/*
* Ensure that the SA1111 is still here.
* FIXME: shouldn't do this here.
@@ -905,6 +967,13 @@ static int sa1111_resume(struct platform_device *dev)
* First of all, wake up the chip.
*/
sa1111_wake(sachip);
+
+ /*
+ * Only lock for write ops. Also, sa1111_wake must be called with
+ * released spinlock!
+ */
+ spin_lock_irqsave(&sachip->lock, flags);
+
sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN0);
sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN1);
@@ -959,13 +1028,12 @@ static int sa1111_remove(struct platform_device *pdev)
struct sa1111 *sachip = platform_get_drvdata(pdev);
if (sachip) {
- __sa1111_remove(sachip);
- platform_set_drvdata(pdev, NULL);
-
#ifdef CONFIG_PM
kfree(sachip->saved_state);
sachip->saved_state = NULL;
#endif
+ __sa1111_remove(sachip);
+ platform_set_drvdata(pdev, NULL);
}
return 0;