patch-2.4.19 linux-2.4.19/arch/arm/mach-sa1100/sa1111.c
Next file: linux-2.4.19/arch/arm/mach-sa1100/sa1111.h
Previous file: linux-2.4.19/arch/arm/mach-sa1100/sa1111-pcibuf.c
Back to the patch index
Back to the overall index
- Lines: 308
- Date:
Fri Aug 2 17:39:42 2002
- Orig file:
linux-2.4.18/arch/arm/mach-sa1100/sa1111.c
- Orig date:
Thu Oct 11 09:04:57 2001
diff -urN linux-2.4.18/arch/arm/mach-sa1100/sa1111.c linux-2.4.19/arch/arm/mach-sa1100/sa1111.c
@@ -15,6 +15,7 @@
* All initialization functions provided here are intended to be called
* from machine specific code with proper arguments when required.
*/
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/delay.h>
@@ -22,57 +23,80 @@
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
+#include <linux/ioport.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/arch/irq.h>
+#include <asm/hardware/sa1111.h>
+
#include "sa1111.h"
+struct resource sa1111_resource = {
+ name: "SA1111",
+};
+
+EXPORT_SYMBOL(sa1111_resource);
+
/*
- * SA1111 Interrupt support
+ * SA1111 interrupt support
*/
-
-void sa1111_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs )
+void sa1111_IRQ_demux(int irq, void *dev_id, struct pt_regs *regs)
{
- int i;
unsigned long stat0, stat1;
- for(;;) {
- stat0 = INTSTATCLR0, stat1 = INTSTATCLR1;
- if( !stat0 && !stat1 ) break;
- if( stat0 )
- for( i = 0; i < 32; i++ )
- if( stat0 & (1<<i) )
- do_IRQ( SA1111_IRQ(i), regs );
-
- if( stat1 )
- for( i = 32; i < 55; i++ )
- if( stat1 & (1<<(i-32)) )
- do_IRQ( SA1111_IRQ(i), regs );
+ while (1) {
+ int i;
+
+ stat0 = INTSTATCLR0;
+ stat1 = INTSTATCLR1;
+
+ if (stat0 == 0 && stat1 == 0)
+ break;
+
+ for (i = IRQ_SA1111_START; stat0; i++, stat0 >>= 1)
+ if (stat0 & 1)
+ do_IRQ(i, regs);
+
+ for (i = IRQ_SA1111_START + 32; stat1; i++, stat1 >>= 1)
+ if (stat1 & 1)
+ do_IRQ(i, regs);
}
}
-static struct irqaction sa1111_irq = {
- name: "SA1111",
- handler: sa1111_IRQ_demux,
- flags: SA_INTERRUPT
-};
+#define SA1111_IRQMASK_LO(x) (1 << (x - IRQ_SA1111_START))
+#define SA1111_IRQMASK_HI(x) (1 << (x - IRQ_SA1111_START - 32))
+/*
+ * A note about masking IRQs:
+ *
+ * The GPIO IRQ edge detection only functions while the IRQ itself is
+ * enabled; edges are not detected while the IRQ is disabled.
+ *
+ * This is especially important for the PCMCIA signals, where we must
+ * pick up every transition. We therefore do not disable the IRQs
+ * while processing them.
+ *
+ * However, since we are changed to a GPIO on the host processor,
+ * all SA1111 IRQs will be disabled while we're processing any SA1111
+ * IRQ.
+ *
+ * Note also that changing INTPOL while an IRQ is enabled will itself
+ * trigger an IRQ.
+ */
static void sa1111_mask_and_ack_lowirq(unsigned int irq)
{
- unsigned int mask = 1 << (irq - SA1111_IRQ(0));
+ unsigned int mask = SA1111_IRQMASK_LO(irq);
- // broken hardware: interrupt events are lost if they occur
- // while the interrupts are disabled.
//INTEN0 &= ~mask;
INTSTATCLR0 = mask;
}
static void sa1111_mask_and_ack_highirq(unsigned int irq)
{
- unsigned int mask = 1 << (irq - SA1111_IRQ(32));
+ unsigned int mask = SA1111_IRQMASK_HI(irq);
//INTEN1 &= ~mask;
INTSTATCLR1 = mask;
@@ -80,27 +104,29 @@
static void sa1111_mask_lowirq(unsigned int irq)
{
- //INTEN0 &= ~(1 << (irq - SA1111_IRQ(0)));
+ INTEN0 &= ~SA1111_IRQMASK_LO(irq);
}
static void sa1111_mask_highirq(unsigned int irq)
{
- //INTEN1 &= ~(1 << (irq - SA1111_IRQ(32)));
+ INTEN1 &= ~SA1111_IRQMASK_HI(irq);
}
static void sa1111_unmask_lowirq(unsigned int irq)
{
- INTEN0 |= 1 << (irq - SA1111_IRQ(0));
+ INTEN0 |= SA1111_IRQMASK_LO(irq);
}
static void sa1111_unmask_highirq(unsigned int irq)
{
- INTEN1 |= 1 << ((irq - SA1111_IRQ(32)));
+ INTEN1 |= SA1111_IRQMASK_HI(irq);
}
void __init sa1111_init_irq(int irq_nr)
{
- int irq;
+ int irq, ret;
+
+ request_mem_region(_INTTEST0, 512, "irqs");
/* disable all IRQs */
INTEN0 = 0;
@@ -111,21 +137,21 @@
* specifies that S0ReadyInt and S1ReadyInt should be '1'.
*/
INTPOL0 = 0;
- INTPOL1 = 1 << (S0_READY_NINT - SA1111_IRQ(32)) |
- 1 << (S1_READY_NINT - SA1111_IRQ(32));
+ INTPOL1 = SA1111_IRQMASK_HI(S0_READY_NINT) |
+ SA1111_IRQMASK_HI(S1_READY_NINT);
/* clear all IRQs */
INTSTATCLR0 = -1;
INTSTATCLR1 = -1;
- for (irq = SA1111_IRQ(0); irq <= SA1111_IRQ(26); irq++) {
+ for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) {
irq_desc[irq].valid = 1;
irq_desc[irq].probe_ok = 0;
irq_desc[irq].mask_ack = sa1111_mask_and_ack_lowirq;
irq_desc[irq].mask = sa1111_mask_lowirq;
irq_desc[irq].unmask = sa1111_unmask_lowirq;
}
- for (irq = SA1111_IRQ(32); irq <= SA1111_IRQ(54); irq++) {
+ for (irq = AUDXMTDMADONEA; irq <= S1_BVD1_STSCHG; irq++) {
irq_desc[irq].valid = 1;
irq_desc[irq].probe_ok = 0;
irq_desc[irq].mask_ack = sa1111_mask_and_ack_highirq;
@@ -134,28 +160,60 @@
}
/* Register SA1111 interrupt */
- if (irq_nr >= 0)
- setup_arm_irq(irq_nr, &sa1111_irq);
+ if (irq_nr < 0)
+ return;
+
+ ret = request_irq(irq_nr, sa1111_IRQ_demux, SA_INTERRUPT,
+ "SA1111", NULL);
+ if (ret < 0)
+ printk(KERN_ERR "SA1111: unable to claim IRQ%d: %d\n",
+ irq_nr, ret);
}
-/*
- * Probe for a SA1111 chip.
+/**
+ * sa1111_probe - probe for a single SA1111 chip.
+ * @phys_addr: physical address of device.
+ *
+ * Probe for a SA1111 chip. This must be called
+ * before any other SA1111-specific code.
+ *
+ * Returns:
+ * %-ENODEV device not found.
+ * %-EBUSY physical address already marked in-use.
+ * %0 successful.
*/
-
-int __init sa1111_probe(void)
+int __init sa1111_probe(unsigned long phys_addr)
{
- unsigned long id = SBI_SKID;
+ unsigned long id;
int ret = -ENODEV;
- if ((id & SKID_ID_MASK) == SKID_SA1111_ID) {
- printk(KERN_INFO "SA-1111 Microprocessor Companion Chip: "
- "silicon revision %lx, metal revision %lx\n",
- (id & SKID_SIREV_MASK)>>4, (id & SKID_MTREV_MASK));
- ret = 0;
- } else {
- printk(KERN_DEBUG "SA-1111 not detected: ID = %08lx\n", id);
+ sa1111_resource.start = phys_addr;
+ sa1111_resource.end = phys_addr + 0x2000;
+
+ if (request_resource(&iomem_resource, &sa1111_resource)) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /*
+ * Probe for the chip. Only touch the SBI registers.
+ */
+ id = SBI_SKID;
+ if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
+ printk(KERN_DEBUG "SA1111 not detected: ID = %08lx\n", id);
+ ret = -ENODEV;
+ goto release;
}
+ printk(KERN_INFO "SA1111 Microprocessor Companion Chip: "
+ "silicon revision %lx, metal revision %lx\n",
+ (id & SKID_SIREV_MASK)>>4, (id & SKID_MTREV_MASK));
+
+ return 0;
+
+ release:
+ release_resource(&sa1111_resource);
+ out:
return ret;
}
@@ -175,6 +233,10 @@
*/
void sa1111_wake(void)
{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
/*
* First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
* (SA-1110 Developer's Manual, section 9.1.2.1)
@@ -210,6 +272,8 @@
* Ensure all clocks are initially off.
*/
SKPCR = 0;
+
+ local_irq_restore(flags);
}
void sa1111_doze(void)
@@ -242,12 +306,17 @@
*/
void __init sa1110_mb_disable(void)
{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
PGSR &= ~GPIO_MBGNT;
GPCR = GPIO_MBGNT;
GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT;
GAFR &= ~(GPIO_MBGNT | GPIO_MBREQ);
+ local_irq_restore(flags);
}
/*
@@ -256,10 +325,19 @@
*/
void __init sa1110_mb_enable(void)
{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
PGSR &= ~GPIO_MBGNT;
GPCR = GPIO_MBGNT;
GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT;
GAFR |= (GPIO_MBGNT | GPIO_MBREQ);
TUCR |= TUCR_MR;
+
+ local_irq_restore(flags);
}
+
+EXPORT_SYMBOL(sa1111_wake);
+EXPORT_SYMBOL(sa1111_doze);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)