fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / arm / mach-versatile / core.c
index 239d989..bf71507 100644 (file)
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
 #include <linux/sysdev.h>
 #include <linux/interrupt.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
 
+#include <asm/cnt32_to_63.h>
 #include <asm/system.h>
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/leds.h>
+#include <asm/hardware/arm_timer.h>
+#include <asm/hardware/icst307.h>
+#include <asm/hardware/vic.h>
 #include <asm/mach-types.h>
-#include <asm/hardware/amba.h>
-#include <asm/hardware/amba_clcd.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
-#ifdef CONFIG_MMC
 #include <asm/mach/mmc.h>
-#endif
+
+#include "core.h"
+#include "clock.h"
 
 /*
  * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx
  *
  * Setup a VA for the Versatile Vectored Interrupt Controller.
  */
-#define VA_VIC_BASE             IO_ADDRESS(VERSATILE_VIC_BASE)
-#define VA_SIC_BASE             IO_ADDRESS(VERSATILE_SIC_BASE)
-
-static void vic_mask_irq(unsigned int irq)
-{
-       irq -= IRQ_VIC_START;
-       writel(1 << irq, VA_VIC_BASE + VIC_IRQ_ENABLE_CLEAR);
-}
-
-static void vic_unmask_irq(unsigned int irq)
-{
-       irq -= IRQ_VIC_START;
-       writel(1 << irq, VA_VIC_BASE + VIC_IRQ_ENABLE);
-}
-
-static struct irqchip vic_chip = {
-       .ack    = vic_mask_irq,
-       .mask   = vic_mask_irq,
-       .unmask = vic_unmask_irq,
-};
+#define __io_address(n)                __io(IO_ADDRESS(n))
+#define VA_VIC_BASE            __io_address(VERSATILE_VIC_BASE)
+#define VA_SIC_BASE            __io_address(VERSATILE_SIC_BASE)
 
 static void sic_mask_irq(unsigned int irq)
 {
@@ -82,19 +70,20 @@ static void sic_unmask_irq(unsigned int irq)
        writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_SET);
 }
 
-static struct irqchip sic_chip = {
+static struct irq_chip sic_chip = {
+       .name   = "SIC",
        .ack    = sic_mask_irq,
        .mask   = sic_mask_irq,
        .unmask = sic_unmask_irq,
 };
 
 static void
-sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+sic_handle_irq(unsigned int irq, struct irq_desc *desc)
 {
        unsigned long status = readl(VA_SIC_BASE + SIC_IRQ_STATUS);
 
        if (status == 0) {
-               do_bad_IRQ(irq, desc, regs);
+               do_bad_IRQ(irq, desc);
                return;
        }
 
@@ -105,63 +94,29 @@ sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
                irq += IRQ_SIC_START;
 
                desc = irq_desc + irq;
-               desc->handle(irq, desc, regs);
+               desc_handle_irq(irq, desc);
        } while (status);
 }
 
 #if 1
 #define IRQ_MMCI0A     IRQ_VICSOURCE22
-#define IRQ_MMCI1A     IRQ_VICSOURCE23
 #define IRQ_AACI       IRQ_VICSOURCE24
 #define IRQ_ETH                IRQ_VICSOURCE25
 #define PIC_MASK       0xFFD00000
 #else
 #define IRQ_MMCI0A     IRQ_SIC_MMCI0A
-#define IRQ_MMCI1A     IRQ_SIC_MMCI1A
 #define IRQ_AACI       IRQ_SIC_AACI
 #define IRQ_ETH                IRQ_SIC_ETH
 #define PIC_MASK       0
 #endif
 
-static void __init versatile_init_irq(void)
+void __init versatile_init_irq(void)
 {
-       unsigned int i, value;
-
-       /* Disable all interrupts initially. */
-
-       writel(0, VA_VIC_BASE + VIC_INT_SELECT);
-       writel(0, VA_VIC_BASE + VIC_IRQ_ENABLE);
-       writel(~0, VA_VIC_BASE + VIC_IRQ_ENABLE_CLEAR);
-       writel(0, VA_VIC_BASE + VIC_IRQ_STATUS);
-       writel(0, VA_VIC_BASE + VIC_ITCR);
-       writel(~0, VA_VIC_BASE + VIC_IRQ_SOFT_CLEAR);
+       unsigned int i;
 
-       /*
-        * Make sure we clear all existing interrupts
-        */
-       writel(0, VA_VIC_BASE + VIC_VECT_ADDR);
-       for (i = 0; i < 19; i++) {
-               value = readl(VA_VIC_BASE + VIC_VECT_ADDR);
-               writel(value, VA_VIC_BASE + VIC_VECT_ADDR);
-       }
-
-       for (i = 0; i < 16; i++) {
-               value = readl(VA_VIC_BASE + VIC_VECT_CNTL0 + (i * 4));
-               writel(value | VICVectCntl_Enable | i, VA_VIC_BASE + VIC_VECT_CNTL0 + (i * 4));
-       }
-
-       writel(32, VA_VIC_BASE + VIC_DEF_VECT_ADDR);
+       vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0);
 
-       for (i = IRQ_VIC_START; i <= IRQ_VIC_END; i++) {
-               if (i != IRQ_VICSOURCE31) {
-                       set_irq_chip(i, &vic_chip);
-                       set_irq_handler(i, do_level_IRQ);
-                       set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-               }
-       }
-
-       set_irq_handler(IRQ_VICSOURCE31, sic_handle_irq);
-       vic_unmask_irq(IRQ_VICSOURCE31);
+       set_irq_chained_handler(IRQ_VICSOURCE31, sic_handle_irq);
 
        /* Do second interrupt controller */
        writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
@@ -169,7 +124,7 @@ static void __init versatile_init_irq(void)
        for (i = IRQ_SIC_START; i <= IRQ_SIC_END; i++) {
                if ((PIC_MASK & (1 << (i - IRQ_SIC_START))) == 0) {
                        set_irq_chip(i, &sic_chip);
-                       set_irq_handler(i, do_level_IRQ);
+                       set_irq_handler(i, handle_level_irq);
                        set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
                }
        }
@@ -185,44 +140,114 @@ static void __init versatile_init_irq(void)
 }
 
 static struct map_desc versatile_io_desc[] __initdata = {
- { IO_ADDRESS(VERSATILE_SYS_BASE),   VERSATILE_SYS_BASE,   SZ_4K,      MT_DEVICE },
- { IO_ADDRESS(VERSATILE_SIC_BASE),   VERSATILE_SIC_BASE,   SZ_4K,      MT_DEVICE },
- { IO_ADDRESS(VERSATILE_VIC_BASE),   VERSATILE_VIC_BASE,   SZ_4K,      MT_DEVICE },
- { IO_ADDRESS(VERSATILE_SCTL_BASE),  VERSATILE_SCTL_BASE,  SZ_4K * 9,  MT_DEVICE },
+       {
+               .virtual        =  IO_ADDRESS(VERSATILE_SYS_BASE),
+               .pfn            = __phys_to_pfn(VERSATILE_SYS_BASE),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE
+       }, {
+               .virtual        =  IO_ADDRESS(VERSATILE_SIC_BASE),
+               .pfn            = __phys_to_pfn(VERSATILE_SIC_BASE),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE
+       }, {
+               .virtual        =  IO_ADDRESS(VERSATILE_VIC_BASE),
+               .pfn            = __phys_to_pfn(VERSATILE_VIC_BASE),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE
+       }, {
+               .virtual        =  IO_ADDRESS(VERSATILE_SCTL_BASE),
+               .pfn            = __phys_to_pfn(VERSATILE_SCTL_BASE),
+               .length         = SZ_4K * 9,
+               .type           = MT_DEVICE
+       },
+#ifdef CONFIG_MACH_VERSATILE_AB
+       {
+               .virtual        =  IO_ADDRESS(VERSATILE_GPIO0_BASE),
+               .pfn            = __phys_to_pfn(VERSATILE_GPIO0_BASE),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE
+       }, {
+               .virtual        =  IO_ADDRESS(VERSATILE_IB2_BASE),
+               .pfn            = __phys_to_pfn(VERSATILE_IB2_BASE),
+               .length         = SZ_64M,
+               .type           = MT_DEVICE
+       },
+#endif
 #ifdef CONFIG_DEBUG_LL
- { IO_ADDRESS(VERSATILE_UART0_BASE), VERSATILE_UART0_BASE, SZ_4K,      MT_DEVICE },
+       {
+               .virtual        =  IO_ADDRESS(VERSATILE_UART0_BASE),
+               .pfn            = __phys_to_pfn(VERSATILE_UART0_BASE),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE
+       },
+#endif
+#ifdef CONFIG_PCI
+       {
+               .virtual        =  IO_ADDRESS(VERSATILE_PCI_CORE_BASE),
+               .pfn            = __phys_to_pfn(VERSATILE_PCI_CORE_BASE),
+               .length         = SZ_4K,
+               .type           = MT_DEVICE
+       }, {
+               .virtual        =  (unsigned long)VERSATILE_PCI_VIRT_BASE,
+               .pfn            = __phys_to_pfn(VERSATILE_PCI_BASE),
+               .length         = VERSATILE_PCI_BASE_SIZE,
+               .type           = MT_DEVICE
+       }, {
+               .virtual        =  (unsigned long)VERSATILE_PCI_CFG_VIRT_BASE,
+               .pfn            = __phys_to_pfn(VERSATILE_PCI_CFG_BASE),
+               .length         = VERSATILE_PCI_CFG_BASE_SIZE,
+               .type           = MT_DEVICE
+       },
+#if 0
+       {
+               .virtual        =  VERSATILE_PCI_VIRT_MEM_BASE0,
+               .pfn            = __phys_to_pfn(VERSATILE_PCI_MEM_BASE0),
+               .length         = SZ_16M,
+               .type           = MT_DEVICE
+       }, {
+               .virtual        =  VERSATILE_PCI_VIRT_MEM_BASE1,
+               .pfn            = __phys_to_pfn(VERSATILE_PCI_MEM_BASE1),
+               .length         = SZ_16M,
+               .type           = MT_DEVICE
+       }, {
+               .virtual        =  VERSATILE_PCI_VIRT_MEM_BASE2,
+               .pfn            = __phys_to_pfn(VERSATILE_PCI_MEM_BASE2),
+               .length         = SZ_16M,
+               .type           = MT_DEVICE
+       },
 #endif
-#ifdef FIXME
- { PCI_MEMORY_VADDR,                PHYS_PCI_MEM_BASE,    SZ_16M,     MT_DEVICE },
- { PCI_CONFIG_VADDR,                PHYS_PCI_CONFIG_BASE, SZ_16M,     MT_DEVICE },
- { PCI_V3_VADDR,                    PHYS_PCI_V3_BASE,     SZ_512K,    MT_DEVICE },
- { PCI_IO_VADDR,                    PHYS_PCI_IO_BASE,     SZ_64K,     MT_DEVICE },
 #endif
 };
 
-static void __init versatile_map_io(void)
+void __init versatile_map_io(void)
 {
        iotable_init(versatile_io_desc, ARRAY_SIZE(versatile_io_desc));
 }
 
-#define VERSATILE_REFCOUNTER   (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_24MHz_OFFSET)
+#define VERSATILE_REFCOUNTER   (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_24MHz_OFFSET)
 
 /*
- * This is the VersatilePB sched_clock implementation.  This has
- * a resolution of 41.7ns, and a maximum value of about 179s.
+ * This is the Versatile sched_clock implementation.  This has
+ * a resolution of 41.7ns, and a maximum value of about 35583 days.
+ *
+ * The return value is guaranteed to be monotonic in that range as
+ * long as there is always less than 89 seconds between successive
+ * calls to this function.
  */
 unsigned long long sched_clock(void)
 {
-       unsigned long long v;
+       unsigned long long v = cnt32_to_63(readl(VERSATILE_REFCOUNTER));
 
-       v = (unsigned long long)readl(VERSATILE_REFCOUNTER) * 125;
-       do_div(v, 3);
+       /* the <<1 gets rid of the cnt_32_to_63 top bit saving on a bic insn */
+       v *= 125<<1;
+       do_div(v, 3<<1);
 
        return v;
 }
 
 
-#define VERSATILE_FLASHCTRL    (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_FLASH_OFFSET)
+#define VERSATILE_FLASHCTRL    (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_FLASH_OFFSET)
 
 static int versatile_flash_init(void)
 {
@@ -266,7 +291,7 @@ static struct flash_platform_data versatile_flash_data = {
 
 static struct resource versatile_flash_resource = {
        .start                  = VERSATILE_FLASH_BASE,
-       .end                    = VERSATILE_FLASH_BASE + VERSATILE_FLASH_SIZE,
+       .end                    = VERSATILE_FLASH_BASE + VERSATILE_FLASH_SIZE - 1,
        .flags                  = IORESOURCE_MEM,
 };
 
@@ -300,10 +325,22 @@ static struct platform_device smc91x_device = {
        .resource       = smc91x_resources,
 };
 
-#define VERSATILE_SYSMCI       (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET)
+static struct resource versatile_i2c_resource = {
+       .start                  = VERSATILE_I2C_BASE,
+       .end                    = VERSATILE_I2C_BASE + SZ_4K - 1,
+       .flags                  = IORESOURCE_MEM,
+};
+
+static struct platform_device versatile_i2c_device = {
+       .name                   = "versatile-i2c",
+       .id                     = -1,
+       .num_resources          = 1,
+       .resource               = &versatile_i2c_resource,
+};
+
+#define VERSATILE_SYSMCI       (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET)
 
-#ifdef CONFIG_MMC
-static unsigned int mmc_status(struct device *dev)
+unsigned int mmc_status(struct device *dev)
 {
        struct amba_device *adev = container_of(dev, struct amba_device, dev);
        u32 mask;
@@ -321,20 +358,46 @@ static struct mmc_platform_data mmc0_plat_data = {
        .status         = mmc_status,
 };
 
-static struct mmc_platform_data mmc1_plat_data = {
-       .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
-       .status         = mmc_status,
+/*
+ * Clock handling
+ */
+static const struct icst307_params versatile_oscvco_params = {
+       .ref            = 24000,
+       .vco_max        = 200000,
+       .vd_min         = 4 + 8,
+       .vd_max         = 511 + 8,
+       .rd_min         = 1 + 2,
+       .rd_max         = 127 + 2,
+};
+
+static void versatile_oscvco_set(struct clk *clk, struct icst307_vco vco)
+{
+       void __iomem *sys_lock = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LOCK_OFFSET;
+       void __iomem *sys_osc = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSCCLCD_OFFSET;
+       u32 val;
+
+       val = readl(sys_osc) & ~0x7ffff;
+       val |= vco.v | (vco.r << 9) | (vco.s << 16);
+
+       writel(0xa05f, sys_lock);
+       writel(val, sys_osc);
+       writel(0, sys_lock);
+}
+
+static struct clk versatile_clcd_clk = {
+       .name   = "CLCDCLK",
+       .params = &versatile_oscvco_params,
+       .setvco = versatile_oscvco_set,
 };
-#endif
 
 /*
  * CLCD support.
  */
 #define SYS_CLCD_MODE_MASK     (3 << 0)
-#define SYS_CLCD_MODE_5551     (0 << 0)
-#define SYS_CLCD_MODE_565      (1 << 0)
-#define SYS_CLCD_MODE_888      (2 << 0)
-#define SYS_CLCD_MODE_LT       (3 << 0)
+#define SYS_CLCD_MODE_888      (0 << 0)
+#define SYS_CLCD_MODE_5551     (1 << 0)
+#define SYS_CLCD_MODE_565_RLSB (2 << 0)
+#define SYS_CLCD_MODE_565_BLSB (3 << 0)
 #define SYS_CLCD_NLCDIOON      (1 << 2)
 #define SYS_CLCD_VDDPOSSWITCH  (1 << 3)
 #define SYS_CLCD_PWR3V5SWITCH  (1 << 4)
@@ -342,6 +405,7 @@ static struct mmc_platform_data mmc1_plat_data = {
 #define SYS_CLCD_ID_SANYO_3_8  (0x00 << 8)
 #define SYS_CLCD_ID_UNKNOWN_8_4        (0x01 << 8)
 #define SYS_CLCD_ID_EPSON_2_2  (0x02 << 8)
+#define SYS_CLCD_ID_SANYO_2_5  (0x07 << 8)
 #define SYS_CLCD_ID_VGA                (0x1f << 8)
 
 static struct clcd_panel vga = {
@@ -390,6 +454,29 @@ static struct clcd_panel sanyo_3_8_in = {
        .bpp            = 16,
 };
 
+static struct clcd_panel sanyo_2_5_in = {
+       .mode           = {
+               .name           = "Sanyo QVGA Portrait",
+               .refresh        = 116,
+               .xres           = 240,
+               .yres           = 320,
+               .pixclock       = 100000,
+               .left_margin    = 20,
+               .right_margin   = 10,
+               .upper_margin   = 2,
+               .lower_margin   = 2,
+               .hsync_len      = 10,
+               .vsync_len      = 2,
+               .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+       .width          = -1,
+       .height         = -1,
+       .tim2           = TIM2_IVS | TIM2_IHS | TIM2_IPC,
+       .cntl           = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+       .bpp            = 16,
+};
+
 static struct clcd_panel epson_2_2_in = {
        .mode           = {
                .name           = "Epson QCIF",
@@ -421,13 +508,15 @@ static struct clcd_panel epson_2_2_in = {
  */
 static struct clcd_panel *versatile_clcd_panel(void)
 {
-       unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
+       void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
        struct clcd_panel *panel = &vga;
        u32 val;
 
        val = readl(sys_clcd) & SYS_CLCD_ID_MASK;
        if (val == SYS_CLCD_ID_SANYO_3_8)
                panel = &sanyo_3_8_in;
+       else if (val == SYS_CLCD_ID_SANYO_2_5)
+               panel = &sanyo_2_5_in;
        else if (val == SYS_CLCD_ID_EPSON_2_2)
                panel = &epson_2_2_in;
        else if (val == SYS_CLCD_ID_VGA)
@@ -435,9 +524,10 @@ static struct clcd_panel *versatile_clcd_panel(void)
        else {
                printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n",
                        val);
+               panel = &vga;
        }
 
-       return &vga;
+       return panel;
 }
 
 /*
@@ -445,12 +535,26 @@ static struct clcd_panel *versatile_clcd_panel(void)
  */
 static void versatile_clcd_disable(struct clcd_fb *fb)
 {
-       unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
+       void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
        u32 val;
 
        val = readl(sys_clcd);
        val &= ~SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH;
        writel(val, sys_clcd);
+
+#ifdef CONFIG_MACH_VERSATILE_AB
+       /*
+        * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light off
+        */
+       if (machine_is_versatile_ab() && fb->panel == &sanyo_2_5_in) {
+               void __iomem *versatile_ib2_ctrl = __io_address(VERSATILE_IB2_CTRL);
+               unsigned long ctrl;
+
+               ctrl = readl(versatile_ib2_ctrl);
+               ctrl &= ~0x01;
+               writel(ctrl, versatile_ib2_ctrl);
+       }
+#endif
 }
 
 /*
@@ -458,7 +562,7 @@ static void versatile_clcd_disable(struct clcd_fb *fb)
  */
 static void versatile_clcd_enable(struct clcd_fb *fb)
 {
-       unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
+       void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
        u32 val;
 
        val = readl(sys_clcd);
@@ -466,19 +570,10 @@ static void versatile_clcd_enable(struct clcd_fb *fb)
 
        switch (fb->fb.var.green.length) {
        case 5:
-#if 0
-               /*
-                * For some undocumented reason, we need to select 565 mode
-                * even when using 555 with VGA.  Maybe this is only true
-                * for the VGA output and needs to be done for LCD panels?
-                * I can't get an explaination from the people who should
-                * know.
-                */
                val |= SYS_CLCD_MODE_5551;
                break;
-#endif
        case 6:
-               val |= SYS_CLCD_MODE_565;
+               val |= SYS_CLCD_MODE_565_RLSB;
                break;
        case 8:
                val |= SYS_CLCD_MODE_888;
@@ -495,6 +590,20 @@ static void versatile_clcd_enable(struct clcd_fb *fb)
         */
        val |= SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH;
        writel(val, sys_clcd);
+
+#ifdef CONFIG_MACH_VERSATILE_AB
+       /*
+        * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light on
+        */
+       if (machine_is_versatile_ab() && fb->panel == &sanyo_2_5_in) {
+               void __iomem *versatile_ib2_ctrl = __io_address(VERSATILE_IB2_CTRL);
+               unsigned long ctrl;
+
+               ctrl = readl(versatile_ib2_ctrl);
+               ctrl |= 0x01;
+               writel(ctrl, versatile_ib2_ctrl);
+       }
+#endif
 }
 
 static unsigned long framesize = SZ_1M;
@@ -518,6 +627,14 @@ static int versatile_clcd_setup(struct clcd_fb *fb)
        return 0;
 }
 
+static int versatile_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+       return dma_mmap_writecombine(&fb->dev->dev, vma,
+                                    fb->fb.screen_base,
+                                    fb->fb.fix.smem_start,
+                                    fb->fb.fix.smem_len);
+}
+
 static void versatile_clcd_remove(struct clcd_fb *fb)
 {
        dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
@@ -525,32 +642,16 @@ static void versatile_clcd_remove(struct clcd_fb *fb)
 }
 
 static struct clcd_board clcd_plat_data = {
-       .name           = "Versatile PB",
+       .name           = "Versatile",
        .check          = clcdfb_check,
        .decode         = clcdfb_decode,
        .disable        = versatile_clcd_disable,
        .enable         = versatile_clcd_enable,
        .setup          = versatile_clcd_setup,
+       .mmap           = versatile_clcd_mmap,
        .remove         = versatile_clcd_remove,
 };
 
-#define AMBA_DEVICE(name,busid,base,plat)                      \
-static struct amba_device name##_device = {                    \
-       .dev            = {                                     \
-               .coherent_dma_mask = ~0,                        \
-               .bus_id = busid,                                \
-               .platform_data = plat,                          \
-       },                                                      \
-       .res            = {                                     \
-               .start  = VERSATILE_##base##_BASE,              \
-               .end    = (VERSATILE_##base##_BASE) + SZ_4K - 1,\
-               .flags  = IORESOURCE_MEM,                       \
-       },                                                      \
-       .dma_mask       = ~0,                                   \
-       .irq            = base##_IRQ,                           \
-       /* .dma         = base##_DMA,*/                         \
-}
-
 #define AACI_IRQ       { IRQ_AACI, NO_IRQ }
 #define AACI_DMA       { 0x80, 0x81 }
 #define MMCI0_IRQ      { IRQ_MMCI0A,IRQ_SIC_MMCI0B }
@@ -559,12 +660,6 @@ static struct amba_device name##_device = {                        \
 #define KMI0_DMA       { 0, 0 }
 #define KMI1_IRQ       { IRQ_SIC_KMI1, NO_IRQ }
 #define KMI1_DMA       { 0, 0 }
-#define UART3_IRQ      { IRQ_SIC_UART3, NO_IRQ }
-#define UART3_DMA      { 0x86, 0x87 }
-#define SCI1_IRQ       { IRQ_SIC_SCI3, NO_IRQ }
-#define SCI1_DMA       { 0x88, 0x89 }
-#define MMCI1_IRQ      { IRQ_MMCI1A, IRQ_SIC_MMCI1B }
-#define MMCI1_DMA      { 0x85, 0 }
 
 /*
  * These devices are connected directly to the multi-layer AHB switch
@@ -589,10 +684,6 @@ static struct amba_device name##_device = {                        \
 #define GPIO0_DMA      { 0, 0 }
 #define GPIO1_IRQ      { IRQ_GPIOINT1, NO_IRQ }
 #define GPIO1_DMA      { 0, 0 }
-#define GPIO2_IRQ      { IRQ_GPIOINT2, NO_IRQ }
-#define GPIO2_DMA      { 0, 0 }
-#define GPIO3_IRQ      { IRQ_GPIOINT3, NO_IRQ }
-#define GPIO3_DMA      { 0, 0 }
 #define RTC_IRQ                { IRQ_RTCINT, NO_IRQ }
 #define RTC_DMA                { 0, 0 }
 
@@ -612,16 +703,9 @@ static struct amba_device name##_device = {                        \
 
 /* FPGA Primecells */
 AMBA_DEVICE(aaci,  "fpga:04", AACI,     NULL);
-#ifdef CONFIG_MMC
 AMBA_DEVICE(mmc0,  "fpga:05", MMCI0,    &mmc0_plat_data);
-#endif
 AMBA_DEVICE(kmi0,  "fpga:06", KMI0,     NULL);
 AMBA_DEVICE(kmi1,  "fpga:07", KMI1,     NULL);
-AMBA_DEVICE(uart3, "fpga:09", UART3,    NULL);
-AMBA_DEVICE(sci1,  "fpga:0a", SCI1,     NULL);
-#ifdef CONFIG_MMC
-AMBA_DEVICE(mmc1,  "fpga:0b", MMCI1,    &mmc1_plat_data);
-#endif
 
 /* DevChip Primecells */
 AMBA_DEVICE(smc,   "dev:00",  SMC,      NULL);
@@ -632,8 +716,6 @@ AMBA_DEVICE(sctl,  "dev:e0",  SCTL,     NULL);
 AMBA_DEVICE(wdog,  "dev:e1",  WATCHDOG, NULL);
 AMBA_DEVICE(gpio0, "dev:e4",  GPIO0,    NULL);
 AMBA_DEVICE(gpio1, "dev:e5",  GPIO1,    NULL);
-AMBA_DEVICE(gpio2, "dev:e6",  GPIO2,    NULL);
-AMBA_DEVICE(gpio3, "dev:e7",  GPIO3,    NULL);
 AMBA_DEVICE(rtc,   "dev:e8",  RTC,      NULL);
 AMBA_DEVICE(sci0,  "dev:f0",  SCI,      NULL);
 AMBA_DEVICE(uart0, "dev:f1",  UART0,    NULL);
@@ -646,7 +728,6 @@ static struct amba_device *amba_devs[] __initdata = {
        &uart0_device,
        &uart1_device,
        &uart2_device,
-       &uart3_device,
        &smc_device,
        &mpmc_device,
        &clcd_device,
@@ -654,24 +735,17 @@ static struct amba_device *amba_devs[] __initdata = {
        &wdog_device,
        &gpio0_device,
        &gpio1_device,
-       &gpio2_device,
-       &gpio3_device,
        &rtc_device,
        &sci0_device,
        &ssp0_device,
        &aaci_device,
-#ifdef CONFIG_MMC
        &mmc0_device,
-#endif
        &kmi0_device,
        &kmi1_device,
-       &sci1_device,
-#ifdef CONFIG_MMC
-       &mmc1_device,
-#endif
 };
 
-#define VA_LEDS_BASE (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET)
+#ifdef CONFIG_LEDS
+#define VA_LEDS_BASE (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET)
 
 static void versatile_leds_event(led_event_t ledevt)
 {
@@ -705,12 +779,16 @@ static void versatile_leds_event(led_event_t ledevt)
        writel(val, VA_LEDS_BASE);
        local_irq_restore(flags);
 }
+#endif /* CONFIG_LEDS */
 
-static void __init versatile_init(void)
+void __init versatile_init(void)
 {
        int i;
 
+       clk_register(&versatile_clcd_clk);
+
        platform_device_register(&versatile_flash_device);
+       platform_device_register(&versatile_i2c_device);
        platform_device_register(&smc91x_device);
 
        for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
@@ -718,57 +796,44 @@ static void __init versatile_init(void)
                amba_device_register(d, &iomem_resource);
        }
 
+#ifdef CONFIG_LEDS
        leds_event = versatile_leds_event;
+#endif
 }
 
 /*
  * Where is the timer (VA)?
  */
-#define TIMER0_VA_BASE          IO_ADDRESS(VERSATILE_TIMER0_1_BASE)
-#define TIMER1_VA_BASE         (IO_ADDRESS(VERSATILE_TIMER0_1_BASE) + 0x20)
-#define TIMER2_VA_BASE          IO_ADDRESS(VERSATILE_TIMER2_3_BASE)
-#define TIMER3_VA_BASE         (IO_ADDRESS(VERSATILE_TIMER2_3_BASE) + 0x20)
-#define VA_IC_BASE              IO_ADDRESS(VERSATILE_VIC_BASE) 
+#define TIMER0_VA_BASE          __io_address(VERSATILE_TIMER0_1_BASE)
+#define TIMER1_VA_BASE         (__io_address(VERSATILE_TIMER0_1_BASE) + 0x20)
+#define TIMER2_VA_BASE          __io_address(VERSATILE_TIMER2_3_BASE)
+#define TIMER3_VA_BASE         (__io_address(VERSATILE_TIMER2_3_BASE) + 0x20)
+#define VA_IC_BASE              __io_address(VERSATILE_VIC_BASE) 
 
 /*
  * How long is the timer interval?
  */
 #define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10)
 #if TIMER_INTERVAL >= 0x100000
-#define TIMER_RELOAD   (TIMER_INTERVAL >> 8)           /* Divide by 256 */
-#define TIMER_CTRL     0x88                            /* Enable, Clock / 256 */
+#define TIMER_RELOAD   (TIMER_INTERVAL >> 8)
+#define TIMER_DIVISOR  (TIMER_CTRL_DIV256)
 #define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC)
 #elif TIMER_INTERVAL >= 0x10000
 #define TIMER_RELOAD   (TIMER_INTERVAL >> 4)           /* Divide by 16 */
-#define TIMER_CTRL     0x84                            /* Enable, Clock / 16 */
+#define TIMER_DIVISOR  (TIMER_CTRL_DIV16)
 #define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC)
 #else
 #define TIMER_RELOAD   (TIMER_INTERVAL)
-#define TIMER_CTRL     0x80                            /* Enable */
+#define TIMER_DIVISOR  (TIMER_CTRL_DIV1)
 #define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
 #endif
 
-#define TIMER_CTRL_IE  (1 << 5)        /* Interrupt Enable */
-
-/*
- * What does it look like?
- */
-typedef struct TimerStruct {
-       unsigned long TimerLoad;
-       unsigned long TimerValue;
-       unsigned long TimerControl;
-       unsigned long TimerClear;
-} TimerStruct_t;
-
-extern unsigned long (*gettimeoffset)(void);
-
 /*
  * Returns number of ms since last clock interrupt.  Note that interrupts
  * will have been disabled by do_gettimeoffset()
  */
 static unsigned long versatile_gettimeoffset(void)
 {
-       volatile TimerStruct_t *timer0 = (TimerStruct_t *)TIMER0_VA_BASE;
        unsigned long ticks1, ticks2, status;
 
        /*
@@ -777,11 +842,11 @@ static unsigned long versatile_gettimeoffset(void)
         * an interrupt.  We get around this by ensuring that the
         * counter has not reloaded between our two reads.
         */
-       ticks2 = timer0->TimerValue & 0xffff;
+       ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
        do {
                ticks1 = ticks2;
-               status = __raw_readl(VA_IC_BASE + VIC_IRQ_RAW_STATUS);
-               ticks2 = timer0->TimerValue & 0xffff;
+               status = __raw_readl(VA_IC_BASE + VIC_RAW_STATUS);
+               ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
        } while (ticks2 > ticks1);
 
        /*
@@ -806,68 +871,65 @@ static unsigned long versatile_gettimeoffset(void)
 /*
  * IRQ handler for the timer
  */
-static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id)
 {
-       volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
+       write_seqlock(&xtime_lock);
 
        // ...clear the interrupt
-       timer0->TimerClear = 1;
+       writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
 
-       timer_tick(regs);
+       timer_tick();
+
+       write_sequnlock(&xtime_lock);
 
        return IRQ_HANDLED;
 }
 
 static struct irqaction versatile_timer_irq = {
        .name           = "Versatile Timer Tick",
-       .flags          = SA_INTERRUPT,
-       .handler        = versatile_timer_interrupt
+       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .handler        = versatile_timer_interrupt,
 };
 
 /*
  * Set up timer interrupt, and return the current time in seconds.
  */
-void __init versatile_init_time(void)
+static void __init versatile_timer_init(void)
 {
-       volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
-       volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE;
-       volatile TimerStruct_t *timer2 = (volatile TimerStruct_t *)TIMER2_VA_BASE;
-       volatile TimerStruct_t *timer3 = (volatile TimerStruct_t *)TIMER3_VA_BASE;
+       u32 val;
 
        /* 
         * set clock frequency: 
         *      VERSATILE_REFCLK is 32KHz
         *      VERSATILE_TIMCLK is 1MHz
         */
-       *(volatile unsigned int *)IO_ADDRESS(VERSATILE_SCTL_BASE) |= 
-         ((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | 
-          (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel));
+       val = readl(__io_address(VERSATILE_SCTL_BASE));
+       writel((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) |
+              (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | 
+              (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) |
+              (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel) | val,
+              __io_address(VERSATILE_SCTL_BASE));
 
        /*
         * Initialise to a known state (all timers off)
         */
-       timer0->TimerControl = 0;
-       timer1->TimerControl = 0;
-       timer2->TimerControl = 0;
-       timer3->TimerControl = 0;
+       writel(0, TIMER0_VA_BASE + TIMER_CTRL);
+       writel(0, TIMER1_VA_BASE + TIMER_CTRL);
+       writel(0, TIMER2_VA_BASE + TIMER_CTRL);
+       writel(0, TIMER3_VA_BASE + TIMER_CTRL);
 
-       timer0->TimerLoad    = TIMER_RELOAD;
-       timer0->TimerValue   = TIMER_RELOAD;
-       timer0->TimerControl = TIMER_CTRL | 0x40 | TIMER_CTRL_IE;  /* periodic + IE */
+       writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
+       writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_VALUE);
+       writel(TIMER_DIVISOR | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC |
+              TIMER_CTRL_IE, TIMER0_VA_BASE + TIMER_CTRL);
 
        /* 
         * Make irqs happen for the system timer
         */
        setup_irq(IRQ_TIMERINT0_1, &versatile_timer_irq);
-       gettimeoffset = versatile_gettimeoffset;
 }
 
-MACHINE_START(VERSATILE_PB, "ARM-Versatile PB")
-       MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd")
-       BOOT_MEM(0x00000000, 0x101f1000, 0xf11f1000)
-       BOOT_PARAMS(0x00000100)
-       MAPIO(versatile_map_io)
-       INITIRQ(versatile_init_irq)
-       INITTIME(versatile_init_time)
-       INIT_MACHINE(versatile_init)
-MACHINE_END
+struct sys_timer versatile_timer = {
+       .init           = versatile_timer_init,
+       .offset         = versatile_gettimeoffset,
+};