Merge branch 'for-linus' of git://git.open-osd.org/linux-open-osd
[pandora-kernel.git] / arch / arm / mach-versatile / core.c
index 136c32e..eb7ffa0 100644 (file)
@@ -50,6 +50,8 @@
 #include <mach/platform.h>
 #include <asm/hardware/timer-sp.h>
 
+#include <plat/clcd.h>
+#include <plat/fpga-irq.h>
 #include <plat/sched_clock.h>
 
 #include "core.h"
 #define VA_VIC_BASE            __io_address(VERSATILE_VIC_BASE)
 #define VA_SIC_BASE            __io_address(VERSATILE_SIC_BASE)
 
-static void sic_mask_irq(struct irq_data *d)
-{
-       unsigned int irq = d->irq - IRQ_SIC_START;
-
-       writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
-}
-
-static void sic_unmask_irq(struct irq_data *d)
-{
-       unsigned int irq = d->irq - IRQ_SIC_START;
-
-       writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_SET);
-}
-
-static struct irq_chip sic_chip = {
-       .name           = "SIC",
-       .irq_ack        = sic_mask_irq,
-       .irq_mask       = sic_mask_irq,
-       .irq_unmask     = sic_unmask_irq,
+static struct fpga_irq_data sic_irq = {
+       .base           = VA_SIC_BASE,
+       .irq_start      = IRQ_SIC_START,
+       .chip.name      = "SIC",
 };
 
-static void
-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);
-               return;
-       }
-
-       do {
-               irq = ffs(status) - 1;
-               status &= ~(1 << irq);
-
-               irq += IRQ_SIC_START;
-
-               generic_handle_irq(irq);
-       } while (status);
-}
-
 #if 1
 #define IRQ_MMCI0A     IRQ_VICSOURCE22
 #define IRQ_AACI       IRQ_VICSOURCE24
@@ -118,22 +85,11 @@ sic_handle_irq(unsigned int irq, struct irq_desc *desc)
 
 void __init versatile_init_irq(void)
 {
-       unsigned int i;
-
        vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0);
 
-       set_irq_chained_handler(IRQ_VICSOURCE31, sic_handle_irq);
-
-       /* Do second interrupt controller */
        writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
 
-       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, handle_level_irq);
-                       set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-               }
-       }
+       fpga_irq_init(IRQ_VICSOURCE31, ~PIC_MASK, &sic_irq);
 
        /*
         * Interrupts on secondary controller from 0 to 8 are routed to
@@ -476,127 +432,7 @@ static struct clk_lookup lookups[] = {
 #define SYS_CLCD_ID_SANYO_2_5  (0x07 << 8)
 #define SYS_CLCD_ID_VGA                (0x1f << 8)
 
-static struct clcd_panel vga = {
-       .mode           = {
-               .name           = "VGA",
-               .refresh        = 60,
-               .xres           = 640,
-               .yres           = 480,
-               .pixclock       = 39721,
-               .left_margin    = 40,
-               .right_margin   = 24,
-               .upper_margin   = 32,
-               .lower_margin   = 11,
-               .hsync_len      = 96,
-               .vsync_len      = 2,
-               .sync           = 0,
-               .vmode          = FB_VMODE_NONINTERLACED,
-       },
-       .width          = -1,
-       .height         = -1,
-       .tim2           = TIM2_BCD | TIM2_IPC,
-       .cntl           = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
-       .bpp            = 16,
-};
-
-static struct clcd_panel sanyo_3_8_in = {
-       .mode           = {
-               .name           = "Sanyo QVGA",
-               .refresh        = 116,
-               .xres           = 320,
-               .yres           = 240,
-               .pixclock       = 100000,
-               .left_margin    = 6,
-               .right_margin   = 6,
-               .upper_margin   = 5,
-               .lower_margin   = 5,
-               .hsync_len      = 6,
-               .vsync_len      = 6,
-               .sync           = 0,
-               .vmode          = FB_VMODE_NONINTERLACED,
-       },
-       .width          = -1,
-       .height         = -1,
-       .tim2           = TIM2_BCD,
-       .cntl           = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
-       .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",
-               .refresh        = 390,
-               .xres           = 176,
-               .yres           = 220,
-               .pixclock       = 62500,
-               .left_margin    = 3,
-               .right_margin   = 2,
-               .upper_margin   = 1,
-               .lower_margin   = 0,
-               .hsync_len      = 3,
-               .vsync_len      = 2,
-               .sync           = 0,
-               .vmode          = FB_VMODE_NONINTERLACED,
-       },
-       .width          = -1,
-       .height         = -1,
-       .tim2           = TIM2_BCD | TIM2_IPC,
-       .cntl           = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
-       .bpp            = 16,
-};
-
-/*
- * Detect which LCD panel is connected, and return the appropriate
- * clcd_panel structure.  Note: we do not have any information on
- * the required timings for the 8.4in panel, so we presently assume
- * VGA timings.
- */
-static struct clcd_panel *versatile_clcd_panel(void)
-{
-       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)
-               panel = &vga;
-       else {
-               printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n",
-                       val);
-               panel = &vga;
-       }
-
-       return panel;
-}
+static bool is_sanyo_2_5_lcd;
 
 /*
  * Disable all display connectors on the interface module.
@@ -614,7 +450,7 @@ static void versatile_clcd_disable(struct clcd_fb *fb)
        /*
         * 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) {
+       if (machine_is_versatile_ab() && is_sanyo_2_5_lcd) {
                void __iomem *versatile_ib2_ctrl = __io_address(VERSATILE_IB2_CTRL);
                unsigned long ctrl;
 
@@ -630,18 +466,22 @@ static void versatile_clcd_disable(struct clcd_fb *fb)
  */
 static void versatile_clcd_enable(struct clcd_fb *fb)
 {
+       struct fb_var_screeninfo *var = &fb->fb.var;
        void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
        u32 val;
 
        val = readl(sys_clcd);
        val &= ~SYS_CLCD_MODE_MASK;
 
-       switch (fb->fb.var.green.length) {
+       switch (var->green.length) {
        case 5:
                val |= SYS_CLCD_MODE_5551;
                break;
        case 6:
-               val |= SYS_CLCD_MODE_565_RLSB;
+               if (var->red.offset == 0)
+                       val |= SYS_CLCD_MODE_565_RLSB;
+               else
+                       val |= SYS_CLCD_MODE_565_BLSB;
                break;
        case 8:
                val |= SYS_CLCD_MODE_888;
@@ -663,7 +503,7 @@ static void versatile_clcd_enable(struct clcd_fb *fb)
        /*
         * 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) {
+       if (machine_is_versatile_ab() && is_sanyo_2_5_lcd) {
                void __iomem *versatile_ib2_ctrl = __io_address(VERSATILE_IB2_CTRL);
                unsigned long ctrl;
 
@@ -674,50 +514,62 @@ static void versatile_clcd_enable(struct clcd_fb *fb)
 #endif
 }
 
-static unsigned long framesize = SZ_1M;
-
+/*
+ * Detect which LCD panel is connected, and return the appropriate
+ * clcd_panel structure.  Note: we do not have any information on
+ * the required timings for the 8.4in panel, so we presently assume
+ * VGA timings.
+ */
 static int versatile_clcd_setup(struct clcd_fb *fb)
 {
-       dma_addr_t dma;
+       void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
+       const char *panel_name;
+       u32 val;
 
-       fb->panel               = versatile_clcd_panel();
+       is_sanyo_2_5_lcd = false;
 
-       fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
-                                                   &dma, GFP_KERNEL);
-       if (!fb->fb.screen_base) {
-               printk(KERN_ERR "CLCD: unable to map framebuffer\n");
-               return -ENOMEM;
+       val = readl(sys_clcd) & SYS_CLCD_ID_MASK;
+       if (val == SYS_CLCD_ID_SANYO_3_8)
+               panel_name = "Sanyo TM38QV67A02A";
+       else if (val == SYS_CLCD_ID_SANYO_2_5) {
+               panel_name = "Sanyo QVGA Portrait";
+               is_sanyo_2_5_lcd = true;
+       } else if (val == SYS_CLCD_ID_EPSON_2_2)
+               panel_name = "Epson L2F50113T00";
+       else if (val == SYS_CLCD_ID_VGA)
+               panel_name = "VGA";
+       else {
+               printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n",
+                       val);
+               panel_name = "VGA";
        }
 
-       fb->fb.fix.smem_start   = dma;
-       fb->fb.fix.smem_len     = framesize;
+       fb->panel = versatile_clcd_get_panel(panel_name);
+       if (!fb->panel)
+               return -EINVAL;
 
-       return 0;
+       return versatile_clcd_setup_dma(fb, SZ_1M);
 }
 
-static int versatile_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
+static void versatile_clcd_decode(struct clcd_fb *fb, struct clcd_regs *regs)
 {
-       return dma_mmap_writecombine(&fb->dev->dev, vma,
-                                    fb->fb.screen_base,
-                                    fb->fb.fix.smem_start,
-                                    fb->fb.fix.smem_len);
-}
+       clcdfb_decode(fb, regs);
 
-static void versatile_clcd_remove(struct clcd_fb *fb)
-{
-       dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
-                             fb->fb.screen_base, fb->fb.fix.smem_start);
+       /* Always clear BGR for RGB565: we do the routing externally */
+       if (fb->fb.var.green.length == 6)
+               regs->cntl &= ~CNTL_BGR;
 }
 
 static struct clcd_board clcd_plat_data = {
        .name           = "Versatile",
+       .caps           = CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888,
        .check          = clcdfb_check,
-       .decode         = clcdfb_decode,
+       .decode         = versatile_clcd_decode,
        .disable        = versatile_clcd_disable,
        .enable         = versatile_clcd_enable,
        .setup          = versatile_clcd_setup,
-       .mmap           = versatile_clcd_mmap,
-       .remove         = versatile_clcd_remove,
+       .mmap           = versatile_clcd_mmap_dma,
+       .remove         = versatile_clcd_remove_dma,
 };
 
 static struct pl061_platform_data gpio0_plat_data = {
@@ -737,53 +589,35 @@ static struct pl022_ssp_controller ssp0_plat_data = {
 };
 
 #define AACI_IRQ       { IRQ_AACI, NO_IRQ }
-#define AACI_DMA       { 0x80, 0x81 }
 #define MMCI0_IRQ      { IRQ_MMCI0A,IRQ_SIC_MMCI0B }
-#define MMCI0_DMA      { 0x84, 0 }
 #define KMI0_IRQ       { IRQ_SIC_KMI0, NO_IRQ }
-#define KMI0_DMA       { 0, 0 }
 #define KMI1_IRQ       { IRQ_SIC_KMI1, NO_IRQ }
-#define KMI1_DMA       { 0, 0 }
 
 /*
  * These devices are connected directly to the multi-layer AHB switch
  */
 #define SMC_IRQ                { NO_IRQ, NO_IRQ }
-#define SMC_DMA                { 0, 0 }
 #define MPMC_IRQ       { NO_IRQ, NO_IRQ }
-#define MPMC_DMA       { 0, 0 }
 #define CLCD_IRQ       { IRQ_CLCDINT, NO_IRQ }
-#define CLCD_DMA       { 0, 0 }
 #define DMAC_IRQ       { IRQ_DMAINT, NO_IRQ }
-#define DMAC_DMA       { 0, 0 }
 
 /*
  * These devices are connected via the core APB bridge
  */
 #define SCTL_IRQ       { NO_IRQ, NO_IRQ }
-#define SCTL_DMA       { 0, 0 }
 #define WATCHDOG_IRQ   { IRQ_WDOGINT, NO_IRQ }
-#define WATCHDOG_DMA   { 0, 0 }
 #define GPIO0_IRQ      { IRQ_GPIOINT0, NO_IRQ }
-#define GPIO0_DMA      { 0, 0 }
 #define GPIO1_IRQ      { IRQ_GPIOINT1, NO_IRQ }
-#define GPIO1_DMA      { 0, 0 }
 #define RTC_IRQ                { IRQ_RTCINT, NO_IRQ }
-#define RTC_DMA                { 0, 0 }
 
 /*
  * These devices are connected via the DMA APB bridge
  */
 #define SCI_IRQ                { IRQ_SCIINT, NO_IRQ }
-#define SCI_DMA                { 7, 6 }
 #define UART0_IRQ      { IRQ_UARTINT0, NO_IRQ }
-#define UART0_DMA      { 15, 14 }
 #define UART1_IRQ      { IRQ_UARTINT1, NO_IRQ }
-#define UART1_DMA      { 13, 12 }
 #define UART2_IRQ      { IRQ_UARTINT2, NO_IRQ }
-#define UART2_DMA      { 11, 10 }
 #define SSP_IRQ                { IRQ_SSPINT, NO_IRQ }
-#define SSP_DMA                { 9, 8 }
 
 /* FPGA Primecells */
 AMBA_DEVICE(aaci,  "fpga:04", AACI,     NULL);
@@ -865,14 +699,21 @@ static void versatile_leds_event(led_event_t ledevt)
 }
 #endif /* CONFIG_LEDS */
 
-void __init versatile_init(void)
+/* Early initializations */
+void __init versatile_init_early(void)
 {
-       int i;
-
-       osc4_clk.vcoreg = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSCCLCD_OFFSET;
+       void __iomem *sys = __io_address(VERSATILE_SYS_BASE);
 
+       osc4_clk.vcoreg = sys + VERSATILE_SYS_OSCCLCD_OFFSET;
        clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 
+       versatile_sched_clock_init(sys + VERSATILE_SYS_24MHz_OFFSET, 24000000);
+}
+
+void __init versatile_init(void)
+{
+       int i;
+
        platform_device_register(&versatile_flash_device);
        platform_device_register(&versatile_i2c_device);
        platform_device_register(&smc91x_device);
@@ -888,12 +729,6 @@ void __init versatile_init(void)
 #endif
 }
 
-/*
- * The sched_clock counter
- */
-#define REFCOUNTER             (__io_address(VERSATILE_SYS_BASE) + \
-                                VERSATILE_SYS_24MHz_OFFSET)
-
 /*
  * Where is the timer (VA)?
  */
@@ -909,8 +744,6 @@ static void __init versatile_timer_init(void)
 {
        u32 val;
 
-       versatile_sched_clock_init(REFCOUNTER, 24000000);
-
        /* 
         * set clock frequency: 
         *      VERSATILE_REFCLK is 32KHz