IMX31: Use template structures to access modules' registers from a base address (as for i2c) which makes drivers look nicer and makes array accesses of registers simpler. Throw in minor fix to fiq_handler dispatcher, otherwise no functional changes.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17270 a1c6a512-1295-4272-9138-f99709370657
diff --git a/firmware/export/imx31l.h b/firmware/export/imx31l.h
index 777fa69..9fc5133 100755
--- a/firmware/export/imx31l.h
+++ b/firmware/export/imx31l.h
@@ -494,74 +494,57 @@
 #define EPITSR_OCIF                     (1 << 0)
 
 /* GPIO */
-#define GPIO_DR_I               0x00 /* Offset - 0x00 */
-#define GPIO_GDIR_I             0x01 /* Offset - 0x04 */
-#define GPIO_PSR_I              0x02 /* Offset - 0x08 */
-#define GPIO_ICR1_I             0x03 /* Offset - 0x0C */
-#define GPIO_ICR2_I             0x04 /* Offset - 0x10 */
-#define GPIO_IMR_I              0x05 /* Offset - 0x14 */
-#define GPIO_ISR_I              0x06 /* Offset - 0x18 */
+#define GPIO1_DR                (*(REG32_PTR_T)(GPIO1_BASE_ADDR+0x00))
+#define GPIO1_GDIR              (*(REG32_PTR_T)(GPIO1_BASE_ADDR+0x04))
+#define GPIO1_PSR               (*(REG32_PTR_T)(GPIO1_BASE_ADDR+0x08))
+#define GPIO1_ICR1              (*(REG32_PTR_T)(GPIO1_BASE_ADDR+0x0C))
+#define GPIO1_ICR2              (*(REG32_PTR_T)(GPIO1_BASE_ADDR+0x10))
+#define GPIO1_IMR               (*(REG32_PTR_T)(GPIO1_BASE_ADDR+0x14))
+#define GPIO1_ISR               (*(REG32_PTR_T)(GPIO1_BASE_ADDR+0x18))
 
-#define GPIO1_DR                (((REG32_PTR_T)GPIO1_BASE_ADDR)[GPIO_DR_I])
-#define GPIO1_GDIR              (((REG32_PTR_T)GPIO1_BASE_ADDR)[GPIO_GDIR_I])
-#define GPIO1_PSR               (((REG32_PTR_T)GPIO1_BASE_ADDR)[GPIO_PSR_I])
-#define GPIO1_ICR1              (((REG32_PTR_T)GPIO1_BASE_ADDR)[GPIO_ICR1_I])
-#define GPIO1_ICR2              (((REG32_PTR_T)GPIO1_BASE_ADDR)[GPIO_ICR2_I])
-#define GPIO1_IMR               (((REG32_PTR_T)GPIO1_BASE_ADDR)[GPIO_IMR_I])
-#define GPIO1_ISR               (((REG32_PTR_T)GPIO1_BASE_ADDR)[GPIO_ISR_I])
+#define GPIO2_DR                (*(REG32_PTR_T)(GPIO2_BASE_ADDR+0x00))
+#define GPIO2_GDIR              (*(REG32_PTR_T)(GPIO2_BASE_ADDR+0x04))
+#define GPIO2_PSR               (*(REG32_PTR_T)(GPIO2_BASE_ADDR+0x08))
+#define GPIO2_ICR1              (*(REG32_PTR_T)(GPIO2_BASE_ADDR+0x0C))
+#define GPIO2_ICR2              (*(REG32_PTR_T)(GPIO2_BASE_ADDR+0x10))
+#define GPIO2_IMR               (*(REG32_PTR_T)(GPIO2_BASE_ADDR+0x14))
+#define GPIO2_ISR               (*(REG32_PTR_T)(GPIO2_BASE_ADDR+0x18))
 
-#define GPIO2_DR                (((REG32_PTR_T)GPIO2_BASE_ADDR)[GPIO_DR_I])
-#define GPIO2_GDIR              (((REG32_PTR_T)GPIO2_BASE_ADDR)[GPIO_GDIR_I])
-#define GPIO2_PSR               (((REG32_PTR_T)GPIO2_BASE_ADDR)[GPIO_PSR_I])
-#define GPIO2_ICR1              (((REG32_PTR_T)GPIO2_BASE_ADDR)[GPIO_ICR1_I])
-#define GPIO2_ICR2              (((REG32_PTR_T)GPIO2_BASE_ADDR)[GPIO_ICR2_I])
-#define GPIO2_IMR               (((REG32_PTR_T)GPIO2_BASE_ADDR)[GPIO_IMR_I])
-#define GPIO2_ISR               (((REG32_PTR_T)GPIO2_BASE_ADDR)[GPIO_ISR_I])
-
-#define GPIO3_DR                (((REG32_PTR_T)GPIO3_BASE_ADDR)[GPIO_DR_I])
-#define GPIO3_GDIR              (((REG32_PTR_T)GPIO3_BASE_ADDR)[GPIO_GDIR_I])
-#define GPIO3_PSR               (((REG32_PTR_T)GPIO3_BASE_ADDR)[GPIO_PSR_I])
-#define GPIO3_ICR1              (((REG32_PTR_T)GPIO3_BASE_ADDR)[GPIO_ICR1_I])
-#define GPIO3_ICR2              (((REG32_PTR_T)GPIO3_BASE_ADDR)[GPIO_ICR2_I])
-#define GPIO3_IMR               (((REG32_PTR_T)GPIO3_BASE_ADDR)[GPIO_IMR_I])
-#define GPIO3_ISR               (((REG32_PTR_T)GPIO3_BASE_ADDR)[GPIO_ISR_I])
+#define GPIO3_DR                (*(REG32_PTR_T)(GPIO3_BASE_ADDR+0x00))
+#define GPIO3_GDIR              (*(REG32_PTR_T)(GPIO3_BASE_ADDR+0x04))
+#define GPIO3_PSR               (*(REG32_PTR_T)(GPIO3_BASE_ADDR+0x08))
+#define GPIO3_ICR1              (*(REG32_PTR_T)(GPIO3_BASE_ADDR+0x0C))
+#define GPIO3_ICR2              (*(REG32_PTR_T)(GPIO3_BASE_ADDR+0x10))
+#define GPIO3_IMR               (*(REG32_PTR_T)(GPIO3_BASE_ADDR+0x14))
+#define GPIO3_ISR               (*(REG32_PTR_T)(GPIO3_BASE_ADDR+0x18))
 
 /* CSPI */
-#define CSPI_RXDATA_I           0x00 /* Offset - 0x00  */
-#define CSPI_TXDATA_I           0x01 /* Offset - 0x04  */
-#define CSPI_CONREG_I           0x02 /* Offset - 0x08  */
-#define CSPI_INTREG_I           0x03 /* Offset - 0x0C  */
-#define CSPI_DMAREG_I           0x04 /* Offset - 0x10  */
-#define CSPI_STATREG_I          0x05 /* Offset - 0x14  */
-#define CSPI_PERIODREG_I        0x06 /* Offset - 0x18  */
-#define CSPI_TESTREG_I          0x70 /* Offset - 0x1C0 */
+#define CSPI_RXDATA1            (*(REG32_PTR_T)(CSPI1_BASE_ADDR+0x00))
+#define CSPI_TXDATA1            (*(REG32_PTR_T)(CSPI1_BASE_ADDR+0x04))
+#define CSPI_CONREG1            (*(REG32_PTR_T)(CSPI1_BASE_ADDR+0x08))
+#define CSPI_INTREG1            (*(REG32_PTR_T)(CSPI1_BASE_ADDR+0x0C))
+#define CSPI_DMAREG1            (*(REG32_PTR_T)(CSPI1_BASE_ADDR+0x10))
+#define CSPI_STATREG1           (*(REG32_PTR_T)(CSPI1_BASE_ADDR+0x14))
+#define CSPI_PERIODREG1         (*(REG32_PTR_T)(CSPI1_BASE_ADDR+0x18))
+#define CSPI_TESTREG1           (*(REG32_PTR_T)(CSPI1_BASE_ADDR+0x1C0))
 
-#define CSPI_RXDATA1            (((REG32_PTR_T)CSPI1_BASE_ADDR)[CSPI_RXDATA_I])
-#define CSPI_TXDATA1            (((REG32_PTR_T)CSPI1_BASE_ADDR)[CSPI_TXDATA_I])
-#define CSPI_CONREG1            (((REG32_PTR_T)CSPI1_BASE_ADDR)[CSPI_CONREG_I])
-#define CSPI_INTREG1            (((REG32_PTR_T)CSPI1_BASE_ADDR)[CSPI_INTREG_I])
-#define CSPI_DMAREG1            (((REG32_PTR_T)CSPI1_BASE_ADDR)[CSPI_DMAREG_I])
-#define CSPI_STATREG1           (((REG32_PTR_T)CSPI1_BASE_ADDR)[CSPI_STATREG_I])
-#define CSPI_PERIODREG1         (((REG32_PTR_T)CSPI1_BASE_ADDR)[CSPI_PERIODREG_I])
-#define CSPI_TESTREG1           (((REG32_PTR_T)CSPI1_BASE_ADDR)[CSPI_TESTREG_I])
+#define CSPI_RXDATA2            (*(REG32_PTR_T)(CSPI2_BASE_ADDR+0x00))
+#define CSPI_TXDATA2            (*(REG32_PTR_T)(CSPI2_BASE_ADDR+0x04))
+#define CSPI_CONREG2            (*(REG32_PTR_T)(CSPI2_BASE_ADDR+0x08))
+#define CSPI_INTREG2            (*(REG32_PTR_T)(CSPI2_BASE_ADDR+0x0C))
+#define CSPI_DMAREG2            (*(REG32_PTR_T)(CSPI2_BASE_ADDR+0x10))
+#define CSPI_STATREG2           (*(REG32_PTR_T)(CSPI2_BASE_ADDR+0x14))
+#define CSPI_PERIODREG2         (*(REG32_PTR_T)(CSPI2_BASE_ADDR+0x18))
+#define CSPI_TESTREG2           (*(REG32_PTR_T)(CSPI2_BASE_ADDR+0x1C0))
 
-#define CSPI_RXDATA2            (((REG32_PTR_T)CSPI2_BASE_ADDR)[CSPI_RXDATA_I])
-#define CSPI_TXDATA2            (((REG32_PTR_T)CSPI2_BASE_ADDR)[CSPI_TXDATA_I])
-#define CSPI_CONREG2            (((REG32_PTR_T)CSPI2_BASE_ADDR)[CSPI_CONREG_I])
-#define CSPI_INTREG2            (((REG32_PTR_T)CSPI2_BASE_ADDR)[CSPI_INTREG_I])
-#define CSPI_DMAREG2            (((REG32_PTR_T)CSPI2_BASE_ADDR)[CSPI_DMAREG_I])
-#define CSPI_STATREG2           (((REG32_PTR_T)CSPI2_BASE_ADDR)[CSPI_STATREG_I])
-#define CSPI_PERIODREG2         (((REG32_PTR_T)CSPI2_BASE_ADDR)[CSPI_PERIODREG_I])
-#define CSPI_TESTREG2           (((REG32_PTR_T)CSPI2_BASE_ADDR)[CSPI_TESTREG_I])
-
-#define CSPI_RXDATA3            (((REG32_PTR_T)CSPI3_BASE_ADDR)[CSPI_RXDATA_I])
-#define CSPI_TXDATA3            (((REG32_PTR_T)CSPI3_BASE_ADDR)[CSPI_TXDATA_I])
-#define CSPI_CONREG3            (((REG32_PTR_T)CSPI3_BASE_ADDR)[CSPI_CONREG_I])
-#define CSPI_INTREG3            (((REG32_PTR_T)CSPI3_BASE_ADDR)[CSPI_INTREG_I])
-#define CSPI_DMAREG3            (((REG32_PTR_T)CSPI3_BASE_ADDR)[CSPI_DMAREG_I])
-#define CSPI_STATREG3           (((REG32_PTR_T)CSPI3_BASE_ADDR)[CSPI_STATREG_I])
-#define CSPI_PERIODREG3         (((REG32_PTR_T)CSPI3_BASE_ADDR)[CSPI_PERIODREG_I])
-#define CSPI_TESTREG3           (((REG32_PTR_T)CSPI3_BASE_ADDR)[CSPI_TESTREG_I])
+#define CSPI_RXDATA3            (*(REG32_PTR_T)(CSPI3_BASE_ADDR+0x00))
+#define CSPI_TXDATA3            (*(REG32_PTR_T)(CSPI3_BASE_ADDR+0x04))
+#define CSPI_CONREG3            (*(REG32_PTR_T)(CSPI3_BASE_ADDR+0x08))
+#define CSPI_INTREG3            (*(REG32_PTR_T)(CSPI3_BASE_ADDR+0x0C))
+#define CSPI_DMAREG3            (*(REG32_PTR_T)(CSPI3_BASE_ADDR+0x10))
+#define CSPI_STATREG3           (*(REG32_PTR_T)(CSPI3_BASE_ADDR+0x14))
+#define CSPI_PERIODREG3         (*(REG32_PTR_T)(CSPI3_BASE_ADDR+0x18))
+#define CSPI_TESTREG3           (*(REG32_PTR_T)(CSPI3_BASE_ADDR+0x1C0))
 
 /* CSPI CONREG flags/fields */
 #define CSPI_CONREG_CHIP_SELECT_SS0     (0 << 24)
diff --git a/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c b/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c
index 6b64bfa..ce2932a 100644
--- a/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c
@@ -74,9 +74,9 @@
 void __attribute__((naked)) fiq_handler(void)
 {
     asm volatile (
-        "mov r10, #0x6c000000      \n" /* load AVIC base address */
+        "mov r10, #0x68000000      \n" /* load AVIC base address */
         "ldr r9, [r10, #0x44]      \n" /* read FIVECSR of AVIC */
-        "add r10, r10, #100        \n" /* move pointer to base of VECTOR table */
+        "add r10, r10, #0x100      \n" /* move pointer to base of VECTOR table */
         "ldr r8, [r10, r9, lsl #2] \n" /* read FIQ vector from VECTOR table */
         "bx  r8                    \n" /* jump to FIQ service routine */
     );
@@ -84,23 +84,24 @@
 
 void avic_init(void)
 {
+    struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR;
     int i;
 
     /* Disable all interrupts and set to unhandled */
     avic_disable_int(ALL);
 
     /* Reset AVIC control */
-    INTCNTL = 0;
+    avic->intcntl = 0;
 
     /* Init all interrupts to type IRQ */
     avic_set_int_type(ALL, IRQ);
 
     /* Set all normal to lowest priority */
     for (i = 0; i < 8; i++)
-        NIPRIORITY(i) = 0;
+        avic->nipriority[i] = 0;
 
     /* Set NM bit to enable VIC */
-    INTCNTL |= INTCNTL_NM;
+    avic->intcntl |= INTCNTL_NM;
 
     /* Enable VE bit in CP15 Control reg to enable VIC */
     asm volatile (
@@ -110,28 +111,30 @@
         : : : "r0");
 
     /* Enable normal interrupts at all priorities */
-    NIMASK = 0x1f;
+    avic->nimask = 0x1f;
 }
 
 void avic_set_int_priority(enum IMX31_INT_LIST ints,
                            unsigned long ni_priority)
 {
-    volatile unsigned long *reg = &NIPRIORITY((63 - ints) / 8);
-    unsigned int shift = 4*(ints % 8);
-    unsigned long mask = 0xful << shift;
+    struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR;
+    volatile uint32_t *reg = &avic->nipriority[7 - (ints >> 3)];
+    unsigned int shift = (ints & 0x7) << 2;
+    uint32_t mask = 0xful << shift;
     *reg = (*reg & ~mask) | ((ni_priority << shift) & mask);
 }
 
 void avic_enable_int(enum IMX31_INT_LIST ints, enum INT_TYPE intstype,
                      unsigned long ni_priority, void (*handler)(void))
 {
+    struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR;
     int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS);
 
     if (ints != ALL) /* No mass-enable allowed */
     {
         avic_set_int_type(ints, intstype);
-        VECTOR(ints) = (long)handler;
-        INTENNUM = ints;
+        avic->vector[ints] = (long)handler;
+        avic->intennum = ints;
         avic_set_int_priority(ints, ni_priority);
     }
 
@@ -140,38 +143,30 @@
 
 void avic_disable_int(enum IMX31_INT_LIST ints)
 {
-    long i;
+    struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR;
+    uint32_t i;
 
     if (ints == ALL)
     {
         for (i = 0; i < 64; i++)
         {
-            INTDISNUM = i;
-            VECTOR(i) = (long)UIE_VECTOR;
+            avic->intdisnum = i;
+            avic->vector[i] = (long)UIE_VECTOR;
         }
     }
     else
     {
-        INTDISNUM = ints;
-        VECTOR(ints) = (long)UIE_VECTOR;
+        avic->intdisnum = ints;
+        avic->vector[ints] = (long)UIE_VECTOR;
     }
 }
 
 static void set_int_type(int i, enum INT_TYPE intstype)
 {
-    volatile unsigned long *reg;
-    long val;
-
-    if (i >= 32)
-    {
-        reg = &INTTYPEH;
-        val = 1L << (i - 32);
-    }
-    else
-    {
-        reg = &INTTYPEL;
-        val = 1L << i;
-    }
+    /* INTTYPEH: vectors 63-32, INTTYPEL: vectors 31-0 */
+    struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR;
+    volatile uint32_t *reg = &avic->inttype[1 - (i >> 5)];
+    uint32_t val = 1L << (i & 0x1f);
 
     if (intstype == IRQ)
         val = *reg & ~val;
diff --git a/firmware/target/arm/imx31/gigabeat-s/avic-imx31.h b/firmware/target/arm/imx31/gigabeat-s/avic-imx31.h
index 7bb7c09..a2e1b34 100644
--- a/firmware/target/arm/imx31/gigabeat-s/avic-imx31.h
+++ b/firmware/target/arm/imx31/gigabeat-s/avic-imx31.h
@@ -19,6 +19,157 @@
 #ifndef AVIC_IMX31_H
 #define AVIC_IMX31_H
 
+struct avic_map
+{
+    volatile uint32_t intcntl;              /* 00h */
+    volatile uint32_t nimask;               /* 04h */
+    volatile uint32_t intennum;             /* 08h */
+    volatile uint32_t intdisnum;            /* 0Ch */
+    union                                   /* 10h */
+    {
+        struct
+        {
+            volatile uint32_t intenableh;   /* 10h */
+            volatile uint32_t intenablel;   /* 14h */
+        };
+        volatile uint32_t intenable[2];     /* H,L */
+    };
+    union
+    {
+        struct
+        {
+            volatile uint32_t inttypeh;     /* 18h */
+            volatile uint32_t inttypel;     /* 1Ch */
+        };
+        volatile uint32_t inttype[2];       /* H,L */
+    };
+    union
+    {
+        struct
+        {
+            volatile uint32_t nipriority7;  /* 20h */
+            volatile uint32_t nipriority6;  /* 24h */
+            volatile uint32_t nipriority5;  /* 28h */
+            volatile uint32_t nipriority4;  /* 2Ch */
+            volatile uint32_t nipriority3;  /* 30h */
+            volatile uint32_t nipriority2;  /* 34h */
+            volatile uint32_t nipriority1;  /* 38h */
+            volatile uint32_t nipriority0;  /* 3Ch */
+        };
+        volatile uint32_t nipriority[8];    /* 7-0 */
+    };
+    volatile uint32_t nivecsr;              /* 40h */
+    volatile uint32_t fivecsr;              /* 44h */
+    union
+    {
+        struct
+        {
+            volatile uint32_t intsrch;      /* 48h */
+            volatile uint32_t intsrcl;      /* 4Ch */
+        };
+        volatile uint32_t intsrc[2];        /* H,L */
+    };
+    union
+    {
+        struct
+        {
+            volatile uint32_t intfrch;      /* 50h */
+            volatile uint32_t intfrcl;      /* 54h */
+        };
+        volatile uint32_t intfrc[2];        /* H,L */
+    };
+    union
+    {
+        struct
+        {
+            volatile uint32_t nipndh;       /* 58h */
+            volatile uint32_t nipndl;       /* 5Ch */
+        };
+        volatile uint32_t nipnd[2];         /* H,L */
+    };
+    union
+    {
+        struct
+        {
+            volatile uint32_t fipndh;       /* 60h */
+            volatile uint32_t fipndl;       /* 64h */
+        };
+        volatile uint32_t fipnd[2];         /* H,L */
+    };
+    volatile uint32_t skip1[0x26];          /* 68h */
+    union                                   /* 100h */ 
+    {
+        struct
+        {
+            volatile uint32_t reserved0;
+            volatile uint32_t reserved1;
+            volatile uint32_t reserved2;
+            volatile uint32_t i2c3;
+            volatile uint32_t i2c2;
+            volatile uint32_t mpeg4encoder;
+            volatile uint32_t rtic;
+            volatile uint32_t fir;
+            volatile uint32_t mmc_sdhc2;
+            volatile uint32_t mmc_sdhc1;
+            volatile uint32_t i2c1;
+            volatile uint32_t ssi2;
+            volatile uint32_t ssi1;
+            volatile uint32_t cspi2;
+            volatile uint32_t cspi1;
+            volatile uint32_t ata;
+            volatile uint32_t mbx;
+            volatile uint32_t cspi3;
+            volatile uint32_t uart3;
+            volatile uint32_t iim;
+            volatile uint32_t sim1;
+            volatile uint32_t sim2;
+            volatile uint32_t rnga;
+            volatile uint32_t evtmon;
+            volatile uint32_t kpp;
+            volatile uint32_t rtc;
+            volatile uint32_t pwn;
+            volatile uint32_t epit2;
+            volatile uint32_t epit1;
+            volatile uint32_t gpt;
+            volatile uint32_t pwr_fail;
+            volatile uint32_t ccm_dvfs;
+            volatile uint32_t uart2;
+            volatile uint32_t nandfc;
+            volatile uint32_t sdma;
+            volatile uint32_t usb_host1;
+            volatile uint32_t usb_host2;
+            volatile uint32_t usb_otg;
+            volatile uint32_t reserved3;
+            volatile uint32_t mshc1;
+            volatile uint32_t mshc2;
+            volatile uint32_t ipu_err;
+            volatile uint32_t ipu;
+            volatile uint32_t reserved4;
+            volatile uint32_t reserved5;
+            volatile uint32_t uart1;
+            volatile uint32_t uart4;
+            volatile uint32_t uart5;
+            volatile uint32_t etc_irq;
+            volatile uint32_t scc_scm;
+            volatile uint32_t scc_smn;
+            volatile uint32_t gpio2;
+            volatile uint32_t gpio1;
+            volatile uint32_t ccm_clk;
+            volatile uint32_t pcmcia;
+            volatile uint32_t wdog;
+            volatile uint32_t gpio3;
+            volatile uint32_t reserved6;
+            volatile uint32_t ext_pwmg;
+            volatile uint32_t ext_temp;
+            volatile uint32_t ext_sense1;
+            volatile uint32_t ext_sense2;
+            volatile uint32_t ext_wdog;
+            volatile uint32_t ext_tv;
+        };
+        volatile uint32_t vector[0x40];     /* 100h */
+    };
+};
+
 enum INT_TYPE
 {
     IRQ = 0,
diff --git a/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c b/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c
index a7427f1..0b76b84 100644
--- a/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c
@@ -44,7 +44,7 @@
 
 static struct gpio_module_descriptor
 {
-    volatile unsigned long *base;       /* Module base address */
+    struct gpio_map * const base;       /* Module base address */
     enum IMX31_INT_LIST ints;           /* AVIC int number */
     void (*handler)(void);              /* Interrupt function */
     const struct gpio_event_list *list; /* Event handler list */
@@ -52,21 +52,21 @@
 {
 #if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS)
     {
-        .base    = (unsigned long *)GPIO1_BASE_ADDR,
+        .base    = (struct gpio_map *)GPIO1_BASE_ADDR,
         .ints    = GPIO1,
         .handler = GPIO1_HANDLER,
     },
 #endif
 #if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
     {
-        .base    = (unsigned long *)GPIO2_BASE_ADDR,
+        .base    = (struct gpio_map *)GPIO2_BASE_ADDR,
         .ints    = GPIO2,
         .handler = GPIO2_HANDLER,
     },
 #endif
 #if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
     {
-        .base    = (unsigned long *)GPIO3_BASE_ADDR,
+        .base    = (struct gpio_map *)GPIO3_BASE_ADDR,
         .ints    = GPIO3,
         .handler = GPIO3_HANDLER,
     },
@@ -77,17 +77,17 @@
 {
     const struct gpio_module_descriptor * const desc = &gpio_descs[gpio];
     const struct gpio_event_list * const list = desc->list;
-    volatile unsigned long * const base = desc->base;
+    struct gpio_map * const base = desc->base;
     unsigned i;
 
     /* Intersect pending and unmasked bits */
-    unsigned long pending = base[GPIO_ISR_I] & base[GPIO_IMR_I];
+    uint32_t pending = base->isr & base->imr;
 
     /* Call each event handler in order */
     for (i = 0; i < list->count; i++)
     {
         const struct gpio_event * const event = &list->events[i];
-        unsigned long bit = 1ul << event->line;
+        uint32_t bit = 1ul << event->line;
 
         if ((pending & bit) && event->callback())
             pending &= ~bit;
@@ -144,10 +144,10 @@
 {
     const struct gpio_module_descriptor * const desc = &gpio_descs[gpio];
     const struct gpio_event * const event = &desc->list->events[id];
-    volatile unsigned long * const base = desc->base;
-    volatile unsigned long * icr;
-    unsigned long mask;
-    unsigned long imr;
+    struct gpio_map * const base = desc->base;
+    volatile uint32_t *icr;
+    uint32_t mask;
+    uint32_t imr;
     int shift;
 
     if (id >= desc->list->count)
@@ -155,7 +155,7 @@
 
     int oldlevel = disable_irq_save();
 
-    imr =  base[GPIO_IMR_I];
+    imr =  base->imr;
 
     if (imr == 0)
     {
@@ -165,14 +165,14 @@
     }
 
     /* Set the line sense */
-    icr = &base[GPIO_ICR1_I] + event->line / 16;
-    shift = 2*(event->line % 16);
+    icr = &base->icr[event->line >> 4];
+    shift = (event->line & 15) << 1;
     mask = GPIO_SENSE_CONFIG_MASK << shift;
 
     *icr = (*icr & ~mask) | ((event->sense << shift) & mask);
 
     /* Unmask the line */
-    base[GPIO_IMR_I] = imr | (1ul << event->line);
+    base->imr = imr | (1ul << event->line);
 
     restore_irq(oldlevel);
 
@@ -183,8 +183,8 @@
 {
     const struct gpio_module_descriptor * const desc = &gpio_descs[gpio];
     const struct gpio_event * const event = &desc->list->events[id];
-    volatile unsigned long * const base = desc->base;
-    unsigned long imr;
+    struct gpio_map * const base = desc->base;
+    uint32_t imr;
 
     if (id >= desc->list->count)
         return;
@@ -192,10 +192,10 @@
     int oldlevel = disable_irq_save();
 
     /* Remove bit from mask */
-    imr = base[GPIO_IMR_I] & ~(1ul << event->line);
+    imr = base->imr & ~(1ul << event->line);
 
     /* Mask the line */
-    base[GPIO_IMR_I] = imr;
+    base->imr = imr;
 
     if (imr == 0)
     {
diff --git a/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.h b/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.h
index a197558..f6e0730 100644
--- a/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.h
+++ b/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.h
@@ -51,6 +51,17 @@
 
 #define GPIO_SENSE_CONFIG_MASK 0x3
 
+/* Register map for each module */
+struct gpio_map
+{
+    volatile uint32_t dr;        /* 00h */
+    volatile uint32_t gdir;      /* 04h */
+    volatile uint32_t psr;       /* 08h */
+    volatile uint32_t icr[2];    /* 0Ch */
+    volatile uint32_t imr;       /* 14h */
+    volatile uint32_t isr;       /* 18h */
+};
+
 /* Pending events will be called in array order */
 
 /* Describes a single event for a pin */
diff --git a/firmware/target/arm/imx31/gigabeat-s/spi-imx31.c b/firmware/target/arm/imx31/gigabeat-s/spi-imx31.c
index bcbe85a..415511e 100644
--- a/firmware/target/arm/imx31/gigabeat-s/spi-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/spi-imx31.c
@@ -16,7 +16,8 @@
  * KIND, either express or implied.
  *
  ****************************************************************************/
-#include "cpu.h"
+#include "config.h"
+#include "system.h"
 #include "spi-imx31.h"
 #include "avic-imx31.h"
 #include "clkctl-imx31.h"
@@ -37,7 +38,7 @@
 /* State data associatated with each CSPI module */
 static struct spi_module_descriptor
 {
-    volatile unsigned long *base;
+    struct cspi_map * const base;
     int enab;
     struct spi_node *last;
     enum IMX31_CG_LIST cg;
@@ -53,7 +54,7 @@
 {
 #if (SPI_MODULE_MASK & USE_CSPI1_MODULE)
     {
-        .base    = (unsigned long *)CSPI1_BASE_ADDR,
+        .base    = (struct cspi_map *)CSPI1_BASE_ADDR,
         .cg      = CG_CSPI1,
         .ints    = CSPI1,
         .handler = CSPI1_HANDLER,
@@ -61,7 +62,7 @@
 #endif
 #if (SPI_MODULE_MASK & USE_CSPI2_MODULE)
     {
-        .base    = (unsigned long *)CSPI2_BASE_ADDR,
+        .base    = (struct cspi_map *)CSPI2_BASE_ADDR,
         .cg      = CG_CSPI2,
         .ints    = CSPI2,
         .handler = CSPI2_HANDLER,
@@ -69,7 +70,7 @@
 #endif
 #if (SPI_MODULE_MASK & USE_CSPI3_MODULE)
     {
-        .base    = (unsigned long *)CSPI3_BASE_ADDR,
+        .base    = (struct cspi_map *)CSPI3_BASE_ADDR,
         .cg      = CG_CSPI3,
         .ints    = CSPI3,
         .handler = CSPI3_HANDLER,
@@ -81,16 +82,16 @@
 static void spi_interrupt(enum spi_module_number spi)
 {
     struct spi_module_descriptor *desc = &spi_descs[spi];
-    volatile unsigned long * const base = desc->base;
+    struct cspi_map * const base = desc->base;
     struct spi_transfer *trans = desc->trans;
     int inc = desc->byte_size + 1;
 
     if (desc->rxcount > 0)
     {
         /* Data received - empty out RXFIFO */
-        while ((base[CSPI_STATREG_I] & CSPI_STATREG_RR) != 0)
+        while ((base->statreg & CSPI_STATREG_RR) != 0)
         {
-            uint32_t word = base[CSPI_RXDATA_I];
+            uint32_t word = base->rxdata;
 
             switch (desc->byte_size & 3)
             {
@@ -108,20 +109,20 @@
 
             if (--desc->rxcount < 4)
             {
-                unsigned long intreg = base[CSPI_INTREG_I];
+                unsigned long intreg = base->intreg;
 
                 if (desc->rxcount <= 0)
                 {
                     /* No more to receive - stop RX interrupts */
                     intreg &= ~(CSPI_INTREG_RHEN | CSPI_INTREG_RREN);
-                    base[CSPI_INTREG_I] = intreg;
+                    base->intreg = intreg;
                     break;
                 }
                 else if (!(intreg & CSPI_INTREG_RREN))
                 {
                     /* < 4 words expected - switch to RX ready */
                     intreg &= ~CSPI_INTREG_RHEN;
-                    base[CSPI_INTREG_I] = intreg | CSPI_INTREG_RREN;
+                    base->intreg = intreg | CSPI_INTREG_RREN;
                 }
             }
         }
@@ -130,7 +131,7 @@
     if (trans->count > 0)
     {
         /* Data to transmit - fill TXFIFO or write until exhausted */
-        while ((base[CSPI_STATREG_I] & CSPI_STATREG_TF) == 0)
+        while ((base->statreg & CSPI_STATREG_TF) == 0)
         {
             uint32_t word = 0;
 
@@ -148,21 +149,21 @@
 
             trans->txbuf += inc;
 
-            base[CSPI_TXDATA_I] = word;
+            base->txdata = word;
 
             if (--trans->count <= 0)
             {
                 /* Out of data - stop TX interrupts */
-                base[CSPI_INTREG_I] &= ~CSPI_INTREG_THEN;
+                base->intreg &= ~CSPI_INTREG_THEN;
                 break;
             }
         }
     }
 
     /* If all interrupts have been remasked - we're done */
-    if (base[CSPI_INTREG_I] == 0)
+    if (base->intreg == 0)
     {
-        base[CSPI_STATREG_I] = CSPI_STATREG_TC | CSPI_STATREG_BO;
+        base->statreg = CSPI_STATREG_TC | CSPI_STATREG_BO;
         wakeup_signal(&desc->w);
     }
 }
@@ -193,9 +194,9 @@
 static bool spi_set_context(struct spi_node *node,
                             struct spi_module_descriptor *desc)
 {
-    volatile unsigned long * const base = desc->base;
+    struct cspi_map * const base = desc->base;
 
-    if ((base[CSPI_CONREG_I] & CSPI_CONREG_EN) == 0)
+    if ((base->conreg & CSPI_CONREG_EN) == 0)
         return false;
 
     if (node != desc->last)
@@ -205,13 +206,13 @@
         desc->byte_size = (((node->conreg >> 8) & 0x1f) + 1 + 7) / 8 - 1;
 
         /* Keep reserved and start bits cleared. Keep enabled bit. */
-        base[CSPI_CONREG_I] =
+        base->conreg =
             (node->conreg & ~(0xfcc8e000 | CSPI_CONREG_XCH | CSPI_CONREG_SMC))
             | CSPI_CONREG_EN;
         /* Set the wait-states */
-        base[CSPI_PERIODREG_I] = node->periodreg & 0xffff;
+        base->periodreg = node->periodreg & 0xffff;
         /* Clear out any spuriously-pending interrupts */
-        base[CSPI_STATREG_I] = CSPI_STATREG_TC | CSPI_STATREG_BO;
+        base->statreg = CSPI_STATREG_TC | CSPI_STATREG_BO;
     }
 
     return true;
@@ -252,16 +253,16 @@
     if (++desc->enab == 1)
     {
         /* First enable for this module */
-        volatile unsigned long * const base = desc->base;
+        struct cspi_map * const base = desc->base;
 
         /* Enable clock-gating register */
         imx31_clkctl_module_clock_gating(desc->cg, CGM_ON_ALL);
         
         /* Reset */
-        base[CSPI_CONREG_I] &= ~CSPI_CONREG_EN;
-        base[CSPI_CONREG_I] |= CSPI_CONREG_EN;
-        base[CSPI_INTREG_I] = 0;
-        base[CSPI_STATREG_I] = CSPI_STATREG_TC | CSPI_STATREG_BO;
+        base->conreg &= ~CSPI_CONREG_EN;
+        base->conreg |= CSPI_CONREG_EN;
+        base->intreg = 0;
+        base->statreg = CSPI_STATREG_TC | CSPI_STATREG_BO;
 
         /* Enable interrupt at controller level */
         avic_enable_int(desc->ints, IRQ, 6, desc->handler);
@@ -280,13 +281,13 @@
     if (desc->enab > 0 && --desc->enab == 0)
     {
         /* Last enable for this module */
-        volatile unsigned long * const base = desc->base;
+        struct cspi_map * const base = desc->base;
 
         /* Disable interrupt at controller level */
         avic_disable_int(desc->ints);
 
         /* Disable interface */
-        base[CSPI_CONREG_I] &= ~CSPI_CONREG_EN;
+        base->conreg &= ~CSPI_CONREG_EN;
 
         /* Disable interface clock */
         imx31_clkctl_module_clock_gating(desc->cg, CGM_OFF);
@@ -310,7 +311,7 @@
 
     if (retval)
     {
-        volatile unsigned long * const base = desc->base;
+        struct cspi_map * const base = desc->base;
         unsigned long intreg;
 
         desc->trans = trans;
@@ -323,15 +324,15 @@
             CSPI_INTREG_RREN : /* Must grab data on every word */
             CSPI_INTREG_RHEN;  /* Enough data to wait for half-full */
 
-        base[CSPI_INTREG_I] = intreg;
+        base->intreg = intreg;
 
         /* Start transfer */
-        base[CSPI_CONREG_I] |= CSPI_CONREG_XCH;
+        base->conreg |= CSPI_CONREG_XCH;
 
         if (wakeup_wait(&desc->w, HZ) != OBJ_WAIT_SUCCEEDED)
         {
-            base[CSPI_INTREG_I] = 0;
-            base[CSPI_CONREG_I] &= ~CSPI_CONREG_XCH;
+            base->intreg = 0;
+            base->conreg &= ~CSPI_CONREG_XCH;
             retval = false;
         }
     }
diff --git a/firmware/target/arm/imx31/gigabeat-s/spi-imx31.h b/firmware/target/arm/imx31/gigabeat-s/spi-imx31.h
index 0708483..2e10459 100644
--- a/firmware/target/arm/imx31/gigabeat-s/spi-imx31.h
+++ b/firmware/target/arm/imx31/gigabeat-s/spi-imx31.h
@@ -39,6 +39,19 @@
     SPI_NUM_CSPI,
 };
 
+struct cspi_map
+{
+    volatile uint32_t rxdata;       /* 00h */
+    volatile uint32_t txdata;       /* 04h */
+    volatile uint32_t conreg;       /* 08h */
+    volatile uint32_t intreg;       /* 0Ch */
+    volatile uint32_t dmareg;       /* 10h */
+    volatile uint32_t statreg;      /* 14h */
+    volatile uint32_t periodreg;    /* 18h */
+    volatile uint32_t skip1[0x69];  /* 1Ch */
+    volatile uint32_t testreg;      /* 1C0h */
+};
+
 struct spi_node
 {
     enum spi_module_number num; /* Module number (CSPIx_NUM) */