[s3c24xx] glamo: Implement gpiolib for the glamo. Get rid of glamo-spi-gpio and
[openwrt/svn-archive/archive.git] / target / linux / s3c24xx / files-2.6.30 / drivers / mfd / glamo / glamo-core.c
index 42284e68d4faacf73c4d820b7477db1892cdc091..077a7a839c196115358d772d1779f5b8a20b3c55 100644 (file)
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/workqueue.h>
-#include <linux/wait.h>
 #include <linux/platform_device.h>
 #include <linux/kernel_stat.h>
 #include <linux/spinlock.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/glamo.h>
+#include <linux/spi/glamo.h>
+#include <linux/glamo-gpio.h>
 #include <linux/glamofb.h>
-#include <linux/mmc/mmc.h>
-#include <linux/mmc/host.h>
+#include <linux/io.h>
 
-#include <asm/io.h>
-#include <asm/uaccess.h>
 #include <asm/div64.h>
 
-#ifdef CONFIG_PM
 #include <linux/pm.h>
-#endif
 
 #include "glamo-regs.h"
 #include "glamo-core.h"
@@ -78,9 +74,10 @@ struct reg_range {
        char *name;
        char dump;
 };
+
 struct reg_range reg_range[] = {
        { 0x0000, 0x76,         "General",      1 },
-       { 0x0200, 0x16,         "Host Bus",     1 },
+       { 0x0200, 0x18,         "Host Bus",     1 },
        { 0x0300, 0x38,         "Memory",       1 },
 /*     { 0x0400, 0x100,        "Sensor",       0 }, */
 /*             { 0x0500, 0x300,        "ISP",          0 }, */
@@ -88,17 +85,15 @@ struct reg_range reg_range[] = {
 /*             { 0x0c00, 0xcc,         "MPEG",         0 }, */
        { 0x1100, 0xb2,         "LCD 1",        1 },
        { 0x1200, 0x64,         "LCD 2",        1 },
-       { 0x1400, 0x40,         "MMC",          1 },
+       { 0x1400, 0x42,         "MMC",          1 },
 /*             { 0x1500, 0x080,        "MPU 0",        0 },
        { 0x1580, 0x080,        "MPU 1",        0 },
        { 0x1600, 0x080,        "Cmd Queue",    0 },
-       { 0x1680, 0x080,        "RISC CPU",     0 },
+       { 0x1680, 0x080,        "RISC CPU",     0 },*/
        { 0x1700, 0x400,        "2D Unit",      0 },
-       { 0x1b00, 0x900,        "3D Unit",      0 }, */
+/*     { 0x1b00, 0x900,        "3D Unit",      0 }, */
 };
 
-static struct glamo_core *glamo_handle;
-
 static inline void __reg_write(struct glamo_core *glamo,
                                u_int16_t reg, u_int16_t val)
 {
@@ -150,100 +145,7 @@ static inline void __reg_clear_bit(struct glamo_core *glamo,
  * resources of sibling devices
  ***********************************************************************/
 
-#if 0
-static struct resource glamo_core_resources[] = {
-       {
-               .start  = GLAMO_REGOFS_GENERIC,
-               .end    = GLAMO_REGOFS_GENERIC + 0x400,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = 0,
-               .end    = 0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device glamo_core_dev = {
-       .name           = "glamo-core",
-       .resource       = &glamo_core_resources,
-       .num_resources  = ARRAY_SIZE(glamo_core_resources),
-};
-#endif
-
-static struct resource glamo_jpeg_resources[] = {
-       {
-               .start  = GLAMO_REGOFS_JPEG,
-               .end    = GLAMO_REGOFS_MPEG - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = IRQ_GLAMO_JPEG,
-               .end    = IRQ_GLAMO_JPEG,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device glamo_jpeg_dev = {
-       .name           = "glamo-jpeg",
-       .resource       = glamo_jpeg_resources,
-       .num_resources  = ARRAY_SIZE(glamo_jpeg_resources),
-};
-
-static struct resource glamo_mpeg_resources[] = {
-       {
-               .start  = GLAMO_REGOFS_MPEG,
-               .end    = GLAMO_REGOFS_LCD - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = IRQ_GLAMO_MPEG,
-               .end    = IRQ_GLAMO_MPEG,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device glamo_mpeg_dev = {
-       .name           = "glamo-mpeg",
-       .resource       = glamo_mpeg_resources,
-       .num_resources  = ARRAY_SIZE(glamo_mpeg_resources),
-};
-
-static struct resource glamo_2d_resources[] = {
-       {
-               .start  = GLAMO_REGOFS_2D,
-               .end    = GLAMO_REGOFS_3D - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = IRQ_GLAMO_2D,
-               .end    = IRQ_GLAMO_2D,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device glamo_2d_dev = {
-       .name           = "glamo-2d",
-       .resource       = glamo_2d_resources,
-       .num_resources  = ARRAY_SIZE(glamo_2d_resources),
-};
-
-static struct resource glamo_3d_resources[] = {
-       {
-               .start  = GLAMO_REGOFS_3D,
-               .end    = GLAMO_REGOFS_END - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device glamo_3d_dev = {
-       .name           = "glamo-3d",
-       .resource       = glamo_3d_resources,
-       .num_resources  = ARRAY_SIZE(glamo_3d_resources),
-};
-
-static struct platform_device glamo_spigpio_dev = {
-       .name           = "glamo-spi-gpio",
-};
-
 static struct resource glamo_fb_resources[] = {
-       /* FIXME: those need to be incremented by parent base */
        {
                .name   = "glamo-fb-regs",
                .start  = GLAMO_REGOFS_LCD,
@@ -257,15 +159,8 @@ static struct resource glamo_fb_resources[] = {
        },
 };
 
-static struct platform_device glamo_fb_dev = {
-       .name           = "glamo-fb",
-       .resource       = glamo_fb_resources,
-       .num_resources  = ARRAY_SIZE(glamo_fb_resources),
-};
-
 static struct resource glamo_mmc_resources[] = {
        {
-               /* FIXME: those need to be incremented by parent base */
                .start  = GLAMO_REGOFS_MMC,
                .end    = GLAMO_REGOFS_MPROC0 - 1,
                .flags  = IORESOURCE_MEM
@@ -281,39 +176,28 @@ static struct resource glamo_mmc_resources[] = {
        },
 };
 
-static struct glamo_mci_pdata glamo_mci_def_pdata = {
-       .gpio_detect            = 0,
-       .glamo_can_set_mci_power        = NULL, /* filled in from MFD platform data */
-/*     .ocr_avail      = MMC_VDD_20_21 |
-                         MMC_VDD_21_22 |
-                         MMC_VDD_22_23 |
-                         MMC_VDD_23_24 |
-                         MMC_VDD_24_25 |
-                         MMC_VDD_25_26 |
-                         MMC_VDD_26_27 |
-                         MMC_VDD_27_28 |
-                         MMC_VDD_28_29 |
-                         MMC_VDD_29_30 |
-                         MMC_VDD_30_31 |
-                         MMC_VDD_32_33,*/
-       .glamo_irq_is_wired     = NULL, /* filled in from MFD platform data */
-       .mci_suspending = NULL, /* filled in from MFD platform data */
-       .mci_all_dependencies_resumed = NULL, /* filled in from MFD platform data */
+enum glamo_cells {
+       GLAMO_CELL_FB,
+       GLAMO_CELL_MMC,
+       GLAMO_CELL_GPIO,
 };
 
-static void mangle_mem_resources(struct resource *res, int num_res,
-                                struct resource *parent)
-{
-       int i;
+static struct mfd_cell glamo_cells[] = {
+       [GLAMO_CELL_FB] = {
+               .name = "glamo-fb",
+               .num_resources = ARRAY_SIZE(glamo_fb_resources),
+               .resources = glamo_fb_resources,
+       },
+       [GLAMO_CELL_MMC] = {
+               .name = "glamo-mci",
+               .num_resources = ARRAY_SIZE(glamo_mmc_resources),
+               .resources = glamo_mmc_resources,
+       },
+       [GLAMO_CELL_GPIO] = {
+               .name = "glamo-gpio",
+       },
+};
 
-       for (i = 0; i < num_res; i++) {
-               if (res[i].flags != IORESOURCE_MEM)
-                       continue;
-               res[i].start += parent->start;
-               res[i].end += parent->start;
-               res[i].parent = parent;
-       }
-}
 
 /***********************************************************************
  * IRQ demultiplexer
@@ -322,32 +206,36 @@ static void mangle_mem_resources(struct resource *res, int num_res,
 
 static void glamo_ack_irq(unsigned int irq)
 {
+       struct glamo_core *glamo = (struct glamo_core*)get_irq_chip_data(irq);
        /* clear interrupt source */
-       __reg_write(glamo_handle, GLAMO_REG_IRQ_CLEAR,
+       __reg_write(glamo, GLAMO_REG_IRQ_CLEAR,
                    1 << irq2glamo(irq));
 }
 
 static void glamo_mask_irq(unsigned int irq)
 {
+       struct glamo_core *glamo = (struct glamo_core*)get_irq_chip_data(irq);
        u_int16_t tmp;
 
        /* clear bit in enable register */
-       tmp = __reg_read(glamo_handle, GLAMO_REG_IRQ_ENABLE);
+       tmp = __reg_read(glamo, GLAMO_REG_IRQ_ENABLE);
        tmp &= ~(1 << irq2glamo(irq));
-       __reg_write(glamo_handle, GLAMO_REG_IRQ_ENABLE, tmp);
+       __reg_write(glamo, GLAMO_REG_IRQ_ENABLE, tmp);
 }
 
 static void glamo_unmask_irq(unsigned int irq)
 {
+       struct glamo_core *glamo = (struct glamo_core*)get_irq_chip_data(irq);
        u_int16_t tmp;
 
        /* set bit in enable register */
-       tmp = __reg_read(glamo_handle, GLAMO_REG_IRQ_ENABLE);
+       tmp = __reg_read(glamo, GLAMO_REG_IRQ_ENABLE);
        tmp |= (1 << irq2glamo(irq));
-       __reg_write(glamo_handle, GLAMO_REG_IRQ_ENABLE, tmp);
+       __reg_write(glamo, GLAMO_REG_IRQ_ENABLE, tmp);
 }
 
 static struct irq_chip glamo_irq_chip = {
+       .name   = "glamo",
        .ack    = glamo_ack_irq,
        .mask   = glamo_mask_irq,
        .unmask = glamo_unmask_irq,
@@ -355,6 +243,7 @@ static struct irq_chip glamo_irq_chip = {
 
 static void glamo_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
 {
+       struct glamo_core *glamo = get_irq_desc_chip_data(desc);
        desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
 
        if (unlikely(desc->status & IRQ_INPROGRESS)) {
@@ -363,7 +252,7 @@ static void glamo_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
                desc->chip->ack(irq);
                return;
        }
-    kstat_incr_irqs_this_cpu(irq, desc);
+       kstat_incr_irqs_this_cpu(irq, desc);
 
        desc->chip->ack(irq);
        desc->status |= IRQ_INPROGRESS;
@@ -383,7 +272,7 @@ static void glamo_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
                desc->status &= ~IRQ_PENDING;
 
                /* read IRQ status register */
-               irqstatus = __reg_read(glamo_handle, GLAMO_REG_IRQ_STATUS);
+               irqstatus = __reg_read(glamo, GLAMO_REG_IRQ_STATUS);
                for (i = 0; i < 9; i++)
                        if (irqstatus & (1 << i))
                                desc_handle_irq(IRQ_GLAMO(i),
@@ -492,7 +381,8 @@ int __glamo_engine_enable(struct glamo_core *glamo, enum glamo_engine engine)
                                   GLAMO_CLOCK_MMC_EN_M9CLK |
                                   GLAMO_CLOCK_MMC_EN_TCLK |
                                   GLAMO_CLOCK_MMC_DG_M9CLK |
-                                  GLAMO_CLOCK_MMC_DG_TCLK, 0xffff);
+                                  GLAMO_CLOCK_MMC_DG_TCLK,
+                                  0xffff);
                /* enable the TCLK divider clk input */
                __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_GEN5_1,
                                                 GLAMO_CLOCK_GEN51_EN_DIV_TCLK,
@@ -574,7 +464,7 @@ int __glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine)
                /* disable the TCLK divider clk input */
                __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_GEN5_1,
                                        GLAMO_CLOCK_GEN51_EN_DIV_TCLK, 0);
-        break;
+               break;
        case GLAMO_ENGINE_CMDQ:
                        __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_2D,
                                           GLAMO_CLOCK_2D_EN_M6CLK,
@@ -588,7 +478,7 @@ int __glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine)
                break;
        case GLAMO_ENGINE_2D:
                        __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_2D,
-                                          GLAMO_CLOCK_2D_EN_M7CLK |
+                                                          GLAMO_CLOCK_2D_EN_M7CLK |
                                                           GLAMO_CLOCK_2D_EN_GCLK |
                                                           GLAMO_CLOCK_2D_DG_M7CLK |
                                                           GLAMO_CLOCK_2D_DG_GCLK,
@@ -654,7 +544,40 @@ u_int16_t glamo_engine_clkreg_get(struct glamo_core *glamo,
 }
 EXPORT_SYMBOL_GPL(glamo_engine_clkreg_get);
 
-struct glamo_script reset_regs[] = {
+static const struct glamo_script engine_div_regs[__NUM_GLAMO_ENGINES] = {
+       [GLAMO_ENGINE_LCD] = {GLAMO_REG_CLOCK_GEN5_1, GLAMO_CLOCK_GEN51_EN_DIV_DCLK},
+       [GLAMO_ENGINE_MMC] = {GLAMO_REG_CLOCK_GEN5_1, GLAMO_CLOCK_GEN51_EN_DIV_TCLK},
+       [GLAMO_ENGINE_2D]  = {GLAMO_REG_CLOCK_GEN5_1, GLAMO_CLOCK_GEN51_EN_DIV_GCLK},
+};
+
+void glamo_engine_div_enable(struct glamo_core *glamo, enum glamo_engine engine)
+{
+       uint16_t reg = engine_div_regs[engine].reg;
+       uint16_t bit = engine_div_regs[engine].val;
+       uint16_t val;
+
+       spin_lock(&glamo->lock);
+       val = __reg_read(glamo, reg);
+       __reg_write(glamo, reg, val | bit);
+       spin_unlock(&glamo->lock);
+       mdelay(5);
+}
+EXPORT_SYMBOL_GPL(glamo_engine_div_enable);
+
+void glamo_engine_div_disable(struct glamo_core *glamo, enum glamo_engine engine)
+{
+       uint16_t reg = engine_div_regs[engine].reg;
+       uint16_t bit = engine_div_regs[engine].val;
+       uint16_t val;
+
+       spin_lock(&glamo->lock);
+       val = __reg_read(glamo, reg);
+       __reg_write(glamo, reg, val & ~bit);
+       spin_unlock(&glamo->lock);
+}
+EXPORT_SYMBOL_GPL(glamo_engine_div_disable);
+
+static const struct glamo_script reset_regs[] = {
        [GLAMO_ENGINE_LCD] = {
                GLAMO_REG_CLOCK_LCD, GLAMO_CLOCK_LCD_RESET
        },
@@ -669,9 +592,9 @@ struct glamo_script reset_regs[] = {
        [GLAMO_ENGINE_MMC] = {
                GLAMO_REG_CLOCK_MMC, GLAMO_CLOCK_MMC_RESET
        },
-    [GLAMO_ENGINE_CMDQ] = {
-        GLAMO_REG_CLOCK_2D, GLAMO_CLOCK_2D_CQ_RESET
-    },
+       [GLAMO_ENGINE_CMDQ] = {
+               GLAMO_REG_CLOCK_2D, GLAMO_CLOCK_2D_CQ_RESET
+       },
        [GLAMO_ENGINE_2D] = {
                GLAMO_REG_CLOCK_2D, GLAMO_CLOCK_2D_RESET
        },
@@ -682,48 +605,27 @@ struct glamo_script reset_regs[] = {
 
 void glamo_engine_reset(struct glamo_core *glamo, enum glamo_engine engine)
 {
-       struct glamo_script *rst;
+       uint16_t reg = reset_regs[engine].reg;
+       uint16_t val = reset_regs[engine].val;
 
        if (engine >= ARRAY_SIZE(reset_regs)) {
                dev_warn(&glamo->pdev->dev, "unknown engine %u ", engine);
                return;
        }
 
-       rst = &reset_regs[engine];
 
        spin_lock(&glamo->lock);
-       __reg_set_bit(glamo, rst->reg, rst->val);
-       __reg_clear_bit(glamo, rst->reg, rst->val);
+       __reg_set_bit(glamo, reg, val);
+       __reg_clear_bit(glamo, reg, val);
        spin_unlock(&glamo->lock);
 }
 EXPORT_SYMBOL_GPL(glamo_engine_reset);
 
-void glamo_lcm_reset(int level)
-{
-       if (!glamo_handle)
-               return;
-
-       glamo_gpio_setpin(glamo_handle, GLAMO_GPIO4, level);
-       glamo_gpio_cfgpin(glamo_handle, GLAMO_GPIO4_OUTPUT);
-
-}
-EXPORT_SYMBOL_GPL(glamo_lcm_reset);
-
-enum glamo_pll {
-       GLAMO_PLL1,
-       GLAMO_PLL2,
-};
-
-static int glamo_pll_rate(struct glamo_core *glamo,
+int glamo_pll_rate(struct glamo_core *glamo,
                          enum glamo_pll pll)
 {
        u_int16_t reg;
-       unsigned int div = 512;
-       /* FIXME: move osci into platform_data */
-       unsigned int osci = 32768;
-
-       if (osci == 32768)
-               div = 1;
+       unsigned int osci = glamo->pdata->osci_clock_rate;
 
        switch (pll) {
        case GLAMO_PLL1:
@@ -735,18 +637,19 @@ static int glamo_pll_rate(struct glamo_core *glamo,
        default:
                return -EINVAL;
        }
-       return (osci/div)*reg;
+       return osci*reg;
 }
+EXPORT_SYMBOL_GPL(glamo_pll_rate);
 
 int glamo_engine_reclock(struct glamo_core *glamo,
                         enum glamo_engine engine,
-                        int ps)
+                        int hz)
 {
-       int pll, khz;
-       u_int16_t reg, mask, val = 0;
+       int pll;
+       u_int16_t reg, mask, div;
 
-       if (!ps)
-               return 0;
+       if (!hz)
+               return -EINVAL;
 
        switch (engine) {
        case GLAMO_ENGINE_LCD:
@@ -754,6 +657,11 @@ int glamo_engine_reclock(struct glamo_core *glamo,
                reg = GLAMO_REG_CLOCK_GEN7;
                mask = 0xff;
                break;
+       case GLAMO_ENGINE_MMC:
+               pll = GLAMO_PLL1;
+               reg = GLAMO_REG_CLOCK_GEN8;
+               mask = 0xff;
+               break;
        default:
                dev_warn(&glamo->pdev->dev,
                         "reclock of engine 0x%x not supported\n", engine);
@@ -762,23 +670,22 @@ int glamo_engine_reclock(struct glamo_core *glamo,
        }
 
        pll = glamo_pll_rate(glamo, pll);
-       khz = 1000000000UL / ps;
 
-       if (khz)
-               val = (pll / khz) / 1000;
+       div = pll / hz;
+
+       if (div != 0 && pll / div <= hz)
+               --div;
+
+       if (div > mask)
+               div = mask;
 
        dev_dbg(&glamo->pdev->dev,
-                       "PLL %d, kHZ %d, div %d\n", pll, khz, val);
+                       "PLL %d, kHZ %d, div %d\n", pll, hz / 1000, div);
 
-       if (val) {
-               val--;
-               reg_set_bit_mask(glamo, reg, mask, val);
-               mdelay(5); /* wait some time to stabilize */
+       reg_set_bit_mask(glamo, reg, mask, div);
+       mdelay(5); /* wait some time to stabilize */
 
-               return 0;
-       } else {
-               return -EINVAL;
-       }
+       return pll / (div + 1);
 }
 EXPORT_SYMBOL_GPL(glamo_engine_reclock);
 
@@ -786,14 +693,13 @@ EXPORT_SYMBOL_GPL(glamo_engine_reclock);
  * script support
  ***********************************************************************/
 
-int glamo_run_script(struct glamo_core *glamo, struct glamo_script *script,
+int glamo_run_script(struct glamo_core *glamo, const struct glamo_script *script,
                     int len, int may_sleep)
 {
        int i;
+    const struct glamo_script *line = script;
 
-       for (i = 0; i < len; i++) {
-               struct glamo_script *line = &script[i];
-
+       for (i = 0; i < len; ++i, ++line) {
                switch (line->reg) {
                case 0xffff:
                        return 0;
@@ -857,7 +763,7 @@ int glamo_run_script(struct glamo_core *glamo, struct glamo_script *script,
 }
 EXPORT_SYMBOL(glamo_run_script);
 
-static struct glamo_script glamo_init_script[] = {
+static const struct glamo_script glamo_init_script[] = {
        { GLAMO_REG_CLOCK_HOST,         0x1000 },
                { 0xfffe, 2 },
        { GLAMO_REG_CLOCK_MEMORY,       0x1000 },
@@ -942,11 +848,6 @@ static struct glamo_script glamo_init_script[] = {
        { GLAMO_REG_MEM_DRAM1,          0xe100 },
        { GLAMO_REG_MEM_DRAM2,          0x01d6 },
        { GLAMO_REG_CLOCK_MEMORY,       0x000b },
-       { GLAMO_REG_GPIO_GEN1,          0x000f },
-       { GLAMO_REG_GPIO_GEN2,          0x111e },
-       { GLAMO_REG_GPIO_GEN3,          0xccc3 },
-       { GLAMO_REG_GPIO_GEN4,          0x111e },
-       { GLAMO_REG_GPIO_GEN5,          0x000f },
 };
 #if 0
 static struct glamo_script glamo_resume_script[] = {
@@ -986,7 +887,7 @@ static void glamo_power(struct glamo_core *glamo,
 {
        int n;
        unsigned long flags;
-       
+
        spin_lock_irqsave(&glamo->lock, flags);
 
        dev_info(&glamo->pdev->dev, "***** glamo_power -> %d\n", new_state);
@@ -1208,20 +1109,12 @@ static int __init glamo_probe(struct platform_device *pdev)
 {
        int rc = 0, irq;
        struct glamo_core *glamo;
-       struct platform_device *glamo_mmc_dev;
-
-       if (glamo_handle) {
-               dev_err(&pdev->dev,
-                       "This driver supports only one instance\n");
-               return -EBUSY;
-       }
 
        glamo = kmalloc(GFP_KERNEL, sizeof(*glamo));
        if (!glamo)
                return -ENOMEM;
 
        spin_lock_init(&glamo->lock);
-       glamo_handle = glamo;
        glamo->pdev = pdev;
        glamo->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        glamo->irq = platform_get_irq(pdev, 0);
@@ -1234,14 +1127,7 @@ static int __init glamo_probe(struct platform_device *pdev)
 
        /* register a number of sibling devices whoise IOMEM resources
         * are siblings of pdev's IOMEM resource */
-#if 0
-       glamo_core_dev.dev.parent = &pdev.dev;
-       mangle_mem_resources(glamo_core_dev.resources,
-                            glamo_core_dev.num_resources, glamo->mem);
-       glamo_core_dev.resources[1].start = glamo->irq;
-       glamo_core_dev.resources[1].end = glamo->irq;
-       platform_device_register(&glamo_core_dev);
-#endif
+
        /* only remap the generic, hostbus and memory controller registers */
        glamo->base = ioremap(glamo->mem->start, 0x4000 /*GLAMO_REGOFS_VIDCAP*/);
        if (!glamo->base) {
@@ -1262,15 +1148,16 @@ static int __init glamo_probe(struct platform_device *pdev)
         */
 
        for (irq = IRQ_GLAMO(0); irq <= IRQ_GLAMO(8); irq++) {
-               set_irq_chip(irq, &glamo_irq_chip);
-               set_irq_handler(irq, handle_level_irq);
+               set_irq_chip_and_handler(irq, &glamo_irq_chip, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID);
+               set_irq_chip_data(irq, glamo);
        }
 
        if (glamo->pdata->glamo_irq_is_wired &&
            !glamo->pdata->glamo_irq_is_wired()) {
                set_irq_chained_handler(glamo->irq, glamo_irq_demux_handler);
                set_irq_type(glamo->irq, IRQ_TYPE_EDGE_FALLING);
+               set_irq_chip_data(glamo->irq, glamo);
                dev_info(&pdev->dev, "Glamo interrupt registered\n");
                glamo->irq_works = 1;
        } else {
@@ -1278,7 +1165,6 @@ static int __init glamo_probe(struct platform_device *pdev)
                glamo->irq_works = 0;
        }
 
-
        /* confirm it isn't insane version */
        if (!glamo_supported(glamo)) {
                dev_err(&pdev->dev, "This Glamo is not supported\n");
@@ -1302,60 +1188,19 @@ static int __init glamo_probe(struct platform_device *pdev)
                 glamo_pll_rate(glamo, GLAMO_PLL1),
                 glamo_pll_rate(glamo, GLAMO_PLL2));
 
-       /* bring MCI specific stuff over from our MFD platform data */
-       glamo_mci_def_pdata.glamo_can_set_mci_power =
-                                       glamo->pdata->glamo_can_set_mci_power;
-       glamo_mci_def_pdata.glamo_mci_use_slow =
-                                       glamo->pdata->glamo_mci_use_slow;
-       glamo_mci_def_pdata.glamo_irq_is_wired =
-                                       glamo->pdata->glamo_irq_is_wired;
-
-       /* start creating the siblings */
-
-       glamo_2d_dev.dev.parent = &pdev->dev;
-       mangle_mem_resources(glamo_2d_dev.resource,
-                            glamo_2d_dev.num_resources, glamo->mem);
-       platform_device_register(&glamo_2d_dev);
-
-       glamo_3d_dev.dev.parent = &pdev->dev;
-       mangle_mem_resources(glamo_3d_dev.resource,
-                            glamo_3d_dev.num_resources, glamo->mem);
-       platform_device_register(&glamo_3d_dev);
-
-       glamo_jpeg_dev.dev.parent = &pdev->dev;
-       mangle_mem_resources(glamo_jpeg_dev.resource,
-                            glamo_jpeg_dev.num_resources, glamo->mem);
-       platform_device_register(&glamo_jpeg_dev);
-
-       glamo_mpeg_dev.dev.parent = &pdev->dev;
-       mangle_mem_resources(glamo_mpeg_dev.resource,
-                            glamo_mpeg_dev.num_resources, glamo->mem);
-       platform_device_register(&glamo_mpeg_dev);
-
-       glamo->pdata->glamo = glamo;
-       glamo_fb_dev.dev.parent = &pdev->dev;
-       glamo_fb_dev.dev.platform_data = glamo->pdata;
-       mangle_mem_resources(glamo_fb_dev.resource,
-                            glamo_fb_dev.num_resources, glamo->mem);
-       platform_device_register(&glamo_fb_dev);
-
-       glamo->pdata->spigpio_info->glamo = glamo;
-       glamo_spigpio_dev.dev.parent = &pdev->dev;
-       glamo_spigpio_dev.dev.platform_data = glamo->pdata->spigpio_info;
-       platform_device_register(&glamo_spigpio_dev);
-
-       glamo_mmc_dev = glamo->pdata->mmc_dev;
-       glamo_mmc_dev->name = "glamo-mci";
-       glamo_mmc_dev->dev.parent = &pdev->dev;
-       glamo_mmc_dev->resource = glamo_mmc_resources;
-       glamo_mmc_dev->num_resources = ARRAY_SIZE(glamo_mmc_resources);
-    glamo_mmc_dev->dev.platform_data = &glamo_mci_def_pdata;
-
-       /* we need it later to give to the engine enable and disable */
-       glamo_mci_def_pdata.pglamo = glamo;
-       mangle_mem_resources(glamo_mmc_dev->resource,
-                            glamo_mmc_dev->num_resources, glamo->mem);
-       platform_device_register(glamo_mmc_dev);
+       /* register siblings */
+       glamo->pdata->mmc_data->core = glamo;
+       glamo_cells[GLAMO_CELL_MMC].platform_data = glamo->pdata->mmc_data;
+       glamo_cells[GLAMO_CELL_MMC].data_size =
+               sizeof(struct glamo_mmc_platform_data);
+
+       glamo->pdata->fb_data->core = glamo;
+       glamo_cells[GLAMO_CELL_FB].platform_data = glamo->pdata->fb_data;
+       glamo_cells[GLAMO_CELL_FB].data_size = sizeof(struct glamo_fb_platform_data);
+
+       mfd_add_devices(&pdev->dev, pdev->id, glamo_cells,
+                             ARRAY_SIZE(glamo_cells),
+                                                 glamo->mem, 0);
 
        /* only request the generic, hostbus and memory controller MMIO */
        glamo->mem = request_mem_region(glamo->mem->start,
@@ -1370,16 +1215,17 @@ static int __init glamo_probe(struct platform_device *pdev)
 bail_irq:
        disable_irq(glamo->irq);
        set_irq_chained_handler(glamo->irq, NULL);
+       set_irq_chip_data(glamo->irq, NULL);
 
        for (irq = IRQ_GLAMO(0); irq <= IRQ_GLAMO(8); irq++) {
                set_irq_flags(irq, 0);
                set_irq_chip(irq, NULL);
+               set_irq_chip_data(irq, NULL);
        }
 
        iounmap(glamo->base);
 bail_free:
        platform_set_drvdata(pdev, NULL);
-       glamo_handle = NULL;
        kfree(glamo);
 
        return rc;
@@ -1392,18 +1238,18 @@ static int glamo_remove(struct platform_device *pdev)
 
        disable_irq(glamo->irq);
        set_irq_chained_handler(glamo->irq, NULL);
+       set_irq_chip_data(glamo->irq, NULL);
 
        for (irq = IRQ_GLAMO(0); irq <= IRQ_GLAMO(8); irq++) {
                set_irq_flags(irq, 0);
                set_irq_chip(irq, NULL);
+               set_irq_chip_data(irq, NULL);
        }
 
        platform_set_drvdata(pdev, NULL);
-       platform_device_unregister(&glamo_fb_dev);
-       platform_device_unregister(glamo->pdata->mmc_dev);
+       mfd_remove_devices(&pdev->dev);
        iounmap(glamo->base);
        release_mem_region(glamo->mem->start, GLAMO_REGOFS_VIDCAP);
-       glamo_handle = NULL;
        kfree(glamo);
 
        return 0;
@@ -1411,35 +1257,41 @@ static int glamo_remove(struct platform_device *pdev)
 
 #ifdef CONFIG_PM
 
-static int glamo_suspend(struct platform_device *pdev, pm_message_t state)
+static int glamo_suspend(struct device *dev)
 {
-       glamo_handle->suspending = 1;
-       glamo_power(glamo_handle, GLAMO_POWER_SUSPEND);
+       struct glamo_core *glamo = dev_get_drvdata(dev);
+       glamo->suspending = 1;
+       glamo_power(glamo, GLAMO_POWER_SUSPEND);
 
        return 0;
 }
 
-static int glamo_resume(struct platform_device *pdev)
+static int glamo_resume(struct device *dev)
 {
-       glamo_power(glamo_handle, GLAMO_POWER_ON);
-       glamo_handle->suspending = 0;
-
+       struct glamo_core *glamo = dev_get_drvdata(dev);
+       glamo_power(glamo, GLAMO_POWER_ON);
+       glamo->suspending = 0;
        return 0;
 }
 
+static struct dev_pm_ops glamo_pm_ops = {
+       .suspend = glamo_suspend,
+       .resume  = glamo_resume,
+};
+
+#define GLAMO_PM_OPS (&glamo_pm_ops)
+
 #else
-#define glamo_suspend NULL
-#define glamo_resume  NULL
+#define GLAMO_PM_OPS NULL
 #endif
 
 static struct platform_driver glamo_driver = {
        .probe          = glamo_probe,
        .remove         = glamo_remove,
-       .suspend        = glamo_suspend,
-       .resume = glamo_resume,
        .driver         = {
                .name   = "glamo3362",
                .owner  = THIS_MODULE,
+               .pm     = GLAMO_PM_OPS,
        },
 };