Merge remote-tracking branch 'agust/next' into next
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 20 Feb 2013 00:39:05 +0000 (11:39 +1100)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 20 Feb 2013 00:39:05 +0000 (11:39 +1100)
<<
Please pull mpc5xxx patches for v3.9. The bestcomm driver is
moved to drivers/dma (so it will be usable for ColdFire).
mpc5121 now provides common dtsi file and existing mpc5121 device
trees use it. There are some minor clock init and sparse fixes
and updates for various 5200 device tree files from Grant. Some
fixes for bugs in the mpc5121 DIU driver are also included here
(Andrew Morton suggested to push them via my mpc5xxx tree).
>>

1  2 
arch/powerpc/platforms/512x/mpc512x_shared.c
arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
arch/powerpc/sysdev/Makefile
drivers/ata/pata_mpc52xx.c
drivers/dma/bestcomm/bestcomm.c
drivers/video/fsl-diu-fb.c

index c7f47cfa9c29a9b14078c5773af100b88997d02a,824cbee68df22ac849fe5f1435a9d9fcca47dd54..d30235b7e3f7fa792fdc86e0118f638e0538d90c
@@@ -68,6 -68,10 +68,6 @@@ struct fsl_diu_shared_fb 
        bool            in_use;
  };
  
 -void mpc512x_set_monitor_port(enum fsl_diu_monitor_port port)
 -{
 -}
 -
  #define DIU_DIV_MASK  0x000000ff
  void mpc512x_set_pixel_clock(unsigned int pixclock)
  {
@@@ -299,6 -303,7 +299,6 @@@ void __init mpc512x_setup_diu(void
                }
        }
  
 -      diu_ops.set_monitor_port        = mpc512x_set_monitor_port;
        diu_ops.set_pixel_clock         = mpc512x_set_pixel_clock;
        diu_ops.valid_monitor_port      = mpc512x_valid_monitor_port;
        diu_ops.release_bootmem         = mpc512x_release_bootmem;
@@@ -426,8 -431,38 +426,38 @@@ void __init mpc512x_psc_fifo_init(void
  
  void __init mpc512x_init(void)
  {
-       mpc512x_declare_of_platform_devices();
        mpc5121_clk_init();
+       mpc512x_declare_of_platform_devices();
        mpc512x_restart_init();
        mpc512x_psc_fifo_init();
  }
+ /**
+  * mpc512x_cs_config - Setup chip select configuration
+  * @cs: chip select number
+  * @val: chip select configuration value
+  *
+  * Perform chip select configuration for devices on LocalPlus Bus.
+  * Intended to dynamically reconfigure the chip select parameters
+  * for configurable devices on the bus.
+  */
+ int mpc512x_cs_config(unsigned int cs, u32 val)
+ {
+       static struct mpc512x_lpc __iomem *lpc;
+       struct device_node *np;
+       if (cs > 7)
+               return -EINVAL;
+       if (!lpc) {
+               np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-lpc");
+               lpc = of_iomap(np, 0);
+               of_node_put(np);
+               if (!lpc)
+                       return -ENOMEM;
+       }
+       out_be32(&lpc->cs_cfg[cs], val);
+       return 0;
+ }
+ EXPORT_SYMBOL(mpc512x_cs_config);
index f9f4537f546dfc7380b73ed002b17cf924339e7c,93fa645904e6043b39bdbe7b6342c23ca1e1fad1..be7b1aa4d54c5739b112cbd139b3b7e1d1b33c8e
@@@ -20,9 -20,9 +20,9 @@@
  #include <asm/mpc52xx.h>
  #include <asm/time.h>
  
- #include <sysdev/bestcomm/bestcomm.h>
- #include <sysdev/bestcomm/bestcomm_priv.h>
- #include <sysdev/bestcomm/gen_bd.h>
+ #include <linux/fsl/bestcomm/bestcomm.h>
+ #include <linux/fsl/bestcomm/bestcomm_priv.h>
+ #include <linux/fsl/bestcomm/gen_bd.h>
  
  MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
  MODULE_DESCRIPTION("MPC5200 LocalPlus FIFO device driver");
@@@ -470,7 -470,7 +470,7 @@@ void mpc52xx_lpbfifo_abort(struct mpc52
  }
  EXPORT_SYMBOL(mpc52xx_lpbfifo_abort);
  
 -static int __devinit mpc52xx_lpbfifo_probe(struct platform_device *op)
 +static int mpc52xx_lpbfifo_probe(struct platform_device *op)
  {
        struct resource res;
        int rc = -ENOMEM;
  }
  
  
 -static int __devexit mpc52xx_lpbfifo_remove(struct platform_device *op)
 +static int mpc52xx_lpbfifo_remove(struct platform_device *op)
  {
        if (lpbfifo.dev != &op->dev)
                return 0;
        return 0;
  }
  
 -static struct of_device_id mpc52xx_lpbfifo_match[] __devinitconst = {
 +static struct of_device_id mpc52xx_lpbfifo_match[] = {
        { .compatible = "fsl,mpc5200-lpbfifo", },
        {},
  };
@@@ -576,6 -576,6 +576,6 @@@ static struct platform_driver mpc52xx_l
                .of_match_table = mpc52xx_lpbfifo_match,
        },
        .probe = mpc52xx_lpbfifo_probe,
 -      .remove = __devexit_p(mpc52xx_lpbfifo_remove),
 +      .remove = mpc52xx_lpbfifo_remove,
  };
  module_platform_driver(mpc52xx_lpbfifo_driver);
index eca3d19304c7f8f66bd81c3b54d0b84bcd8ff247,3884776600fdf05077ae4ee883d0c559ad5c700a..b0a518e9759978a7255a334388d53c79a387ba61
@@@ -1,6 -1,6 +1,6 @@@
  subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
  
 -ccflags-$(CONFIG_PPC64)               := -mno-minimal-toc
 +ccflags-$(CONFIG_PPC64)               := $(NO_MINIMAL_TOC)
  
  mpic-msi-obj-$(CONFIG_PCI_MSI)        += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o
  obj-$(CONFIG_MPIC)            += mpic.o $(mpic-msi-obj-y)
@@@ -26,7 -26,6 +26,6 @@@ obj-$(CONFIG_SIMPLE_GPIO)     += simple_gpi
  obj-$(CONFIG_FSL_RIO)         += fsl_rio.o fsl_rmu.o
  obj-$(CONFIG_TSI108_BRIDGE)   += tsi108_pci.o tsi108_dev.o
  obj-$(CONFIG_QUICC_ENGINE)    += qe_lib/
- obj-$(CONFIG_PPC_BESTCOMM)    += bestcomm/
  mv64x60-$(CONFIG_PCI)         += mv64x60_pci.o
  obj-$(CONFIG_MV64X60)         += $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o \
                                   mv64x60_udbg.o
@@@ -37,7 -36,6 +36,7 @@@ obj-$(CONFIG_PPC_INDIRECT_PCI)        += indir
  obj-$(CONFIG_PPC_I8259)               += i8259.o
  obj-$(CONFIG_IPIC)            += ipic.o
  obj-$(CONFIG_4xx)             += uic.o
 +obj-$(CONFIG_PPC4xx_OCM)      += ppc4xx_ocm.o
  obj-$(CONFIG_4xx_SOC)         += ppc4xx_soc.o
  obj-$(CONFIG_XILINX_VIRTEX)   += xilinx_intc.o
  obj-$(CONFIG_XILINX_PCI)      += xilinx_pci.o
index 652f57e8348466e51b476ec68c4c39ba9b5a5864,0b363e9d42a5f3205d095ffac0529991925d7026..3a8fb28b71f28df9129277167703c96706b79d96
@@@ -26,9 -26,9 +26,9 @@@
  #include <asm/prom.h>
  #include <asm/mpc52xx.h>
  
- #include <sysdev/bestcomm/bestcomm.h>
- #include <sysdev/bestcomm/bestcomm_priv.h>
- #include <sysdev/bestcomm/ata.h>
+ #include <linux/fsl/bestcomm/bestcomm.h>
+ #include <linux/fsl/bestcomm/bestcomm_priv.h>
+ #include <linux/fsl/bestcomm/ata.h>
  
  #define DRV_NAME      "mpc52xx_ata"
  
@@@ -621,10 -621,9 +621,10 @@@ static struct ata_port_operations mpc52
        .qc_prep                = ata_noop_qc_prep,
  };
  
 -static int __devinit
 -mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv,
 -                   unsigned long raw_ata_regs, int mwdma_mask, int udma_mask)
 +static int mpc52xx_ata_init_one(struct device *dev,
 +                              struct mpc52xx_ata_priv *priv,
 +                              unsigned long raw_ata_regs,
 +                              int mwdma_mask, int udma_mask)
  {
        struct ata_host *host;
        struct ata_port *ap;
  /* OF Platform driver                                                       */
  /* ======================================================================== */
  
 -static int __devinit
 -mpc52xx_ata_probe(struct platform_device *op)
 +static int mpc52xx_ata_probe(struct platform_device *op)
  {
        unsigned int ipb_freq;
        struct resource res_mem;
index 0000000000000000000000000000000000000000,67371fb820d39fea57e16f0dc0fb405e98f1d6fa..3a189460328226d9d0acab9ad5bc6a24afe28f22
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,532 +1,531 @@@
 -static struct of_device_id mpc52xx_sram_ids[] __devinitdata = {
+ /*
+  * Driver for MPC52xx processor BestComm peripheral controller
+  *
+  *
+  * Copyright (C) 2006-2007 Sylvain Munaut <tnt@246tNt.com>
+  * Copyright (C) 2005      Varma Electronics Oy,
+  *                         ( by Andrey Volkov <avolkov@varma-el.com> )
+  * Copyright (C) 2003-2004 MontaVista, Software, Inc.
+  *                         ( by Dale Farnsworth <dfarnsworth@mvista.com> )
+  *
+  * This file is licensed under the terms of the GNU General Public License
+  * version 2. This program is licensed "as is" without any warranty of any
+  * kind, whether express or implied.
+  */
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/of.h>
+ #include <linux/of_device.h>
+ #include <linux/of_platform.h>
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/mpc52xx.h>
+ #include <linux/fsl/bestcomm/sram.h>
+ #include <linux/fsl/bestcomm/bestcomm_priv.h>
+ #include "linux/fsl/bestcomm/bestcomm.h"
+ #define DRIVER_NAME "bestcomm-core"
+ /* MPC5200 device tree match tables */
 -static int __devinit
 -bcom_engine_init(void)
++static struct of_device_id mpc52xx_sram_ids[] = {
+       { .compatible = "fsl,mpc5200-sram", },
+       { .compatible = "mpc5200-sram", },
+       {}
+ };
+ struct bcom_engine *bcom_eng = NULL;
+ EXPORT_SYMBOL_GPL(bcom_eng);  /* needed for inline functions */
+ /* ======================================================================== */
+ /* Public and private API                                                   */
+ /* ======================================================================== */
+ /* Private API */
+ struct bcom_task *
+ bcom_task_alloc(int bd_count, int bd_size, int priv_size)
+ {
+       int i, tasknum = -1;
+       struct bcom_task *tsk;
+       /* Don't try to do anything if bestcomm init failed */
+       if (!bcom_eng)
+               return NULL;
+       /* Get and reserve a task num */
+       spin_lock(&bcom_eng->lock);
+       for (i=0; i<BCOM_MAX_TASKS; i++)
+               if (!bcom_eng->tdt[i].stop) {   /* we use stop as a marker */
+                       bcom_eng->tdt[i].stop = 0xfffffffful; /* dummy addr */
+                       tasknum = i;
+                       break;
+               }
+       spin_unlock(&bcom_eng->lock);
+       if (tasknum < 0)
+               return NULL;
+       /* Allocate our structure */
+       tsk = kzalloc(sizeof(struct bcom_task) + priv_size, GFP_KERNEL);
+       if (!tsk)
+               goto error;
+       tsk->tasknum = tasknum;
+       if (priv_size)
+               tsk->priv = (void*)tsk + sizeof(struct bcom_task);
+       /* Get IRQ of that task */
+       tsk->irq = irq_of_parse_and_map(bcom_eng->ofnode, tsk->tasknum);
+       if (tsk->irq == NO_IRQ)
+               goto error;
+       /* Init the BDs, if needed */
+       if (bd_count) {
+               tsk->cookie = kmalloc(sizeof(void*) * bd_count, GFP_KERNEL);
+               if (!tsk->cookie)
+                       goto error;
+               tsk->bd = bcom_sram_alloc(bd_count * bd_size, 4, &tsk->bd_pa);
+               if (!tsk->bd)
+                       goto error;
+               memset(tsk->bd, 0x00, bd_count * bd_size);
+               tsk->num_bd = bd_count;
+               tsk->bd_size = bd_size;
+       }
+       return tsk;
+ error:
+       if (tsk) {
+               if (tsk->irq != NO_IRQ)
+                       irq_dispose_mapping(tsk->irq);
+               bcom_sram_free(tsk->bd);
+               kfree(tsk->cookie);
+               kfree(tsk);
+       }
+       bcom_eng->tdt[tasknum].stop = 0;
+       return NULL;
+ }
+ EXPORT_SYMBOL_GPL(bcom_task_alloc);
+ void
+ bcom_task_free(struct bcom_task *tsk)
+ {
+       /* Stop the task */
+       bcom_disable_task(tsk->tasknum);
+       /* Clear TDT */
+       bcom_eng->tdt[tsk->tasknum].start = 0;
+       bcom_eng->tdt[tsk->tasknum].stop  = 0;
+       /* Free everything */
+       irq_dispose_mapping(tsk->irq);
+       bcom_sram_free(tsk->bd);
+       kfree(tsk->cookie);
+       kfree(tsk);
+ }
+ EXPORT_SYMBOL_GPL(bcom_task_free);
+ int
+ bcom_load_image(int task, u32 *task_image)
+ {
+       struct bcom_task_header *hdr = (struct bcom_task_header *)task_image;
+       struct bcom_tdt *tdt;
+       u32 *desc, *var, *inc;
+       u32 *desc_src, *var_src, *inc_src;
+       /* Safety checks */
+       if (hdr->magic != BCOM_TASK_MAGIC) {
+               printk(KERN_ERR DRIVER_NAME
+                       ": Trying to load invalid microcode\n");
+               return -EINVAL;
+       }
+       if ((task < 0) || (task >= BCOM_MAX_TASKS)) {
+               printk(KERN_ERR DRIVER_NAME
+                       ": Trying to load invalid task %d\n", task);
+               return -EINVAL;
+       }
+       /* Initial load or reload */
+       tdt = &bcom_eng->tdt[task];
+       if (tdt->start) {
+               desc = bcom_task_desc(task);
+               if (hdr->desc_size != bcom_task_num_descs(task)) {
+                       printk(KERN_ERR DRIVER_NAME
+                               ": Trying to reload wrong task image "
+                               "(%d size %d/%d)!\n",
+                               task,
+                               hdr->desc_size,
+                               bcom_task_num_descs(task));
+                       return -EINVAL;
+               }
+       } else {
+               phys_addr_t start_pa;
+               desc = bcom_sram_alloc(hdr->desc_size * sizeof(u32), 4, &start_pa);
+               if (!desc)
+                       return -ENOMEM;
+               tdt->start = start_pa;
+               tdt->stop = start_pa + ((hdr->desc_size-1) * sizeof(u32));
+       }
+       var = bcom_task_var(task);
+       inc = bcom_task_inc(task);
+       /* Clear & copy */
+       memset(var, 0x00, BCOM_VAR_SIZE);
+       memset(inc, 0x00, BCOM_INC_SIZE);
+       desc_src = (u32 *)(hdr + 1);
+       var_src = desc_src + hdr->desc_size;
+       inc_src = var_src + hdr->var_size;
+       memcpy(desc, desc_src, hdr->desc_size * sizeof(u32));
+       memcpy(var + hdr->first_var, var_src, hdr->var_size * sizeof(u32));
+       memcpy(inc, inc_src, hdr->inc_size * sizeof(u32));
+       return 0;
+ }
+ EXPORT_SYMBOL_GPL(bcom_load_image);
+ void
+ bcom_set_initiator(int task, int initiator)
+ {
+       int i;
+       int num_descs;
+       u32 *desc;
+       int next_drd_has_initiator;
+       bcom_set_tcr_initiator(task, initiator);
+       /* Just setting tcr is apparently not enough due to some problem */
+       /* with it. So we just go thru all the microcode and replace in  */
+       /* the DRD directly */
+       desc = bcom_task_desc(task);
+       next_drd_has_initiator = 1;
+       num_descs = bcom_task_num_descs(task);
+       for (i=0; i<num_descs; i++, desc++) {
+               if (!bcom_desc_is_drd(*desc))
+                       continue;
+               if (next_drd_has_initiator)
+                       if (bcom_desc_initiator(*desc) != BCOM_INITIATOR_ALWAYS)
+                               bcom_set_desc_initiator(desc, initiator);
+               next_drd_has_initiator = !bcom_drd_is_extended(*desc);
+       }
+ }
+ EXPORT_SYMBOL_GPL(bcom_set_initiator);
+ /* Public API */
+ void
+ bcom_enable(struct bcom_task *tsk)
+ {
+       bcom_enable_task(tsk->tasknum);
+ }
+ EXPORT_SYMBOL_GPL(bcom_enable);
+ void
+ bcom_disable(struct bcom_task *tsk)
+ {
+       bcom_disable_task(tsk->tasknum);
+ }
+ EXPORT_SYMBOL_GPL(bcom_disable);
+ /* ======================================================================== */
+ /* Engine init/cleanup                                                      */
+ /* ======================================================================== */
+ /* Function Descriptor table */
+ /* this will need to be updated if Freescale changes their task code FDT */
+ static u32 fdt_ops[] = {
+       0xa0045670,     /* FDT[48] - load_acc()   */
+       0x80045670,     /* FDT[49] - unload_acc() */
+       0x21800000,     /* FDT[50] - and()        */
+       0x21e00000,     /* FDT[51] - or()         */
+       0x21500000,     /* FDT[52] - xor()        */
+       0x21400000,     /* FDT[53] - andn()       */
+       0x21500000,     /* FDT[54] - not()        */
+       0x20400000,     /* FDT[55] - add()        */
+       0x20500000,     /* FDT[56] - sub()        */
+       0x20800000,     /* FDT[57] - lsh()        */
+       0x20a00000,     /* FDT[58] - rsh()        */
+       0xc0170000,     /* FDT[59] - crc8()       */
+       0xc0145670,     /* FDT[60] - crc16()      */
+       0xc0345670,     /* FDT[61] - crc32()      */
+       0xa0076540,     /* FDT[62] - endian32()   */
+       0xa0000760,     /* FDT[63] - endian16()   */
+ };
 -static int __devinit mpc52xx_bcom_probe(struct platform_device *op)
++static int bcom_engine_init(void)
+ {
+       int task;
+       phys_addr_t tdt_pa, ctx_pa, var_pa, fdt_pa;
+       unsigned int tdt_size, ctx_size, var_size, fdt_size;
+       /* Allocate & clear SRAM zones for FDT, TDTs, contexts and vars/incs */
+       tdt_size = BCOM_MAX_TASKS * sizeof(struct bcom_tdt);
+       ctx_size = BCOM_MAX_TASKS * BCOM_CTX_SIZE;
+       var_size = BCOM_MAX_TASKS * (BCOM_VAR_SIZE + BCOM_INC_SIZE);
+       fdt_size = BCOM_FDT_SIZE;
+       bcom_eng->tdt = bcom_sram_alloc(tdt_size, sizeof(u32), &tdt_pa);
+       bcom_eng->ctx = bcom_sram_alloc(ctx_size, BCOM_CTX_ALIGN, &ctx_pa);
+       bcom_eng->var = bcom_sram_alloc(var_size, BCOM_VAR_ALIGN, &var_pa);
+       bcom_eng->fdt = bcom_sram_alloc(fdt_size, BCOM_FDT_ALIGN, &fdt_pa);
+       if (!bcom_eng->tdt || !bcom_eng->ctx || !bcom_eng->var || !bcom_eng->fdt) {
+               printk(KERN_ERR "DMA: SRAM alloc failed in engine init !\n");
+               bcom_sram_free(bcom_eng->tdt);
+               bcom_sram_free(bcom_eng->ctx);
+               bcom_sram_free(bcom_eng->var);
+               bcom_sram_free(bcom_eng->fdt);
+               return -ENOMEM;
+       }
+       memset(bcom_eng->tdt, 0x00, tdt_size);
+       memset(bcom_eng->ctx, 0x00, ctx_size);
+       memset(bcom_eng->var, 0x00, var_size);
+       memset(bcom_eng->fdt, 0x00, fdt_size);
+       /* Copy the FDT for the EU#3 */
+       memcpy(&bcom_eng->fdt[48], fdt_ops, sizeof(fdt_ops));
+       /* Initialize Task base structure */
+       for (task=0; task<BCOM_MAX_TASKS; task++)
+       {
+               out_be16(&bcom_eng->regs->tcr[task], 0);
+               out_8(&bcom_eng->regs->ipr[task], 0);
+               bcom_eng->tdt[task].context     = ctx_pa;
+               bcom_eng->tdt[task].var = var_pa;
+               bcom_eng->tdt[task].fdt = fdt_pa;
+               var_pa += BCOM_VAR_SIZE + BCOM_INC_SIZE;
+               ctx_pa += BCOM_CTX_SIZE;
+       }
+       out_be32(&bcom_eng->regs->taskBar, tdt_pa);
+       /* Init 'always' initiator */
+       out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ALWAYS], BCOM_IPR_ALWAYS);
+       /* Disable COMM Bus Prefetch on the original 5200; it's broken */
+       if ((mfspr(SPRN_SVR) & MPC5200_SVR_MASK) == MPC5200_SVR)
+               bcom_disable_prefetch();
+       /* Init lock */
+       spin_lock_init(&bcom_eng->lock);
+       return 0;
+ }
+ static void
+ bcom_engine_cleanup(void)
+ {
+       int task;
+       /* Stop all tasks */
+       for (task=0; task<BCOM_MAX_TASKS; task++)
+       {
+               out_be16(&bcom_eng->regs->tcr[task], 0);
+               out_8(&bcom_eng->regs->ipr[task], 0);
+       }
+       out_be32(&bcom_eng->regs->taskBar, 0ul);
+       /* Release the SRAM zones */
+       bcom_sram_free(bcom_eng->tdt);
+       bcom_sram_free(bcom_eng->ctx);
+       bcom_sram_free(bcom_eng->var);
+       bcom_sram_free(bcom_eng->fdt);
+ }
+ /* ======================================================================== */
+ /* OF platform driver                                                       */
+ /* ======================================================================== */
++static int mpc52xx_bcom_probe(struct platform_device *op)
+ {
+       struct device_node *ofn_sram;
+       struct resource res_bcom;
+       int rv;
+       /* Inform user we're ok so far */
+       printk(KERN_INFO "DMA: MPC52xx BestComm driver\n");
+       /* Get the bestcomm node */
+       of_node_get(op->dev.of_node);
+       /* Prepare SRAM */
+       ofn_sram = of_find_matching_node(NULL, mpc52xx_sram_ids);
+       if (!ofn_sram) {
+               printk(KERN_ERR DRIVER_NAME ": "
+                       "No SRAM found in device tree\n");
+               rv = -ENODEV;
+               goto error_ofput;
+       }
+       rv = bcom_sram_init(ofn_sram, DRIVER_NAME);
+       of_node_put(ofn_sram);
+       if (rv) {
+               printk(KERN_ERR DRIVER_NAME ": "
+                       "Error in SRAM init\n");
+               goto error_ofput;
+       }
+       /* Get a clean struct */
+       bcom_eng = kzalloc(sizeof(struct bcom_engine), GFP_KERNEL);
+       if (!bcom_eng) {
+               printk(KERN_ERR DRIVER_NAME ": "
+                       "Can't allocate state structure\n");
+               rv = -ENOMEM;
+               goto error_sramclean;
+       }
+       /* Save the node */
+       bcom_eng->ofnode = op->dev.of_node;
+       /* Get, reserve & map io */
+       if (of_address_to_resource(op->dev.of_node, 0, &res_bcom)) {
+               printk(KERN_ERR DRIVER_NAME ": "
+                       "Can't get resource\n");
+               rv = -EINVAL;
+               goto error_sramclean;
+       }
+       if (!request_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma),
+                               DRIVER_NAME)) {
+               printk(KERN_ERR DRIVER_NAME ": "
+                       "Can't request registers region\n");
+               rv = -EBUSY;
+               goto error_sramclean;
+       }
+       bcom_eng->regs_base = res_bcom.start;
+       bcom_eng->regs = ioremap(res_bcom.start, sizeof(struct mpc52xx_sdma));
+       if (!bcom_eng->regs) {
+               printk(KERN_ERR DRIVER_NAME ": "
+                       "Can't map registers\n");
+               rv = -ENOMEM;
+               goto error_release;
+       }
+       /* Now, do the real init */
+       rv = bcom_engine_init();
+       if (rv)
+               goto error_unmap;
+       /* Done ! */
+       printk(KERN_INFO "DMA: MPC52xx BestComm engine @%08lx ok !\n",
+               (long)bcom_eng->regs_base);
+       return 0;
+       /* Error path */
+ error_unmap:
+       iounmap(bcom_eng->regs);
+ error_release:
+       release_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma));
+ error_sramclean:
+       kfree(bcom_eng);
+       bcom_sram_cleanup();
+ error_ofput:
+       of_node_put(op->dev.of_node);
+       printk(KERN_ERR "DMA: MPC52xx BestComm init failed !\n");
+       return rv;
+ }
+ static int mpc52xx_bcom_remove(struct platform_device *op)
+ {
+       /* Clean up the engine */
+       bcom_engine_cleanup();
+       /* Cleanup SRAM */
+       bcom_sram_cleanup();
+       /* Release regs */
+       iounmap(bcom_eng->regs);
+       release_mem_region(bcom_eng->regs_base, sizeof(struct mpc52xx_sdma));
+       /* Release the node */
+       of_node_put(bcom_eng->ofnode);
+       /* Release memory */
+       kfree(bcom_eng);
+       bcom_eng = NULL;
+       return 0;
+ }
+ static struct of_device_id mpc52xx_bcom_of_match[] = {
+       { .compatible = "fsl,mpc5200-bestcomm", },
+       { .compatible = "mpc5200-bestcomm", },
+       {},
+ };
+ MODULE_DEVICE_TABLE(of, mpc52xx_bcom_of_match);
+ static struct platform_driver mpc52xx_bcom_of_platform_driver = {
+       .probe          = mpc52xx_bcom_probe,
+       .remove         = mpc52xx_bcom_remove,
+       .driver = {
+               .name = DRIVER_NAME,
+               .owner = THIS_MODULE,
+               .of_match_table = mpc52xx_bcom_of_match,
+       },
+ };
+ /* ======================================================================== */
+ /* Module                                                                   */
+ /* ======================================================================== */
+ static int __init
+ mpc52xx_bcom_init(void)
+ {
+       return platform_driver_register(&mpc52xx_bcom_of_platform_driver);
+ }
+ static void __exit
+ mpc52xx_bcom_exit(void)
+ {
+       platform_driver_unregister(&mpc52xx_bcom_of_platform_driver);
+ }
+ /* If we're not a module, we must make sure everything is setup before  */
+ /* anyone tries to use us ... that's why we use subsys_initcall instead */
+ /* of module_init. */
+ subsys_initcall(mpc52xx_bcom_init);
+ module_exit(mpc52xx_bcom_exit);
+ MODULE_DESCRIPTION("Freescale MPC52xx BestComm DMA");
+ MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
+ MODULE_AUTHOR("Andrey Volkov <avolkov@varma-el.com>");
+ MODULE_AUTHOR("Dale Farnsworth <dfarnsworth@mvista.com>");
+ MODULE_LICENSE("GPL v2");
index 19cfd7a925638f305c7e349490ade67cf6dd425c,d33e8720cbb90957edda70fc874651c965b26d67..41fbd9453c5fa5611406b25477073174efd0b2d5
@@@ -55,7 -55,7 +55,7 @@@
   * order if increasing resolution and frequency.  The 320x240-60 mode is
   * the initial AOI for the second and third planes.
   */
 -static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
 +static struct fb_videomode fsl_diu_mode_db[] = {
        {
                .refresh        = 60,
                .xres           = 1024,
@@@ -944,7 -944,7 +944,7 @@@ static u32 fsl_diu_get_pixel_format(uns
  #define PF_COMP_0_MASK                0x0000000F
  #define PF_COMP_0_SHIFT               0
  
- #define MAKE_PF(alpha, red, blue, green, size, c0, c1, c2, c3) \
+ #define MAKE_PF(alpha, red, green, blue, size, c0, c1, c2, c3) \
        cpu_to_le32(PF_BYTE_F | (alpha << PF_ALPHA_C_SHIFT) | \
        (blue << PF_BLUE_C_SHIFT) | (green << PF_GREEN_C_SHIFT) | \
        (red << PF_RED_C_SHIFT) | (c3 << PF_COMP_3_SHIFT) | \
        switch (bits_per_pixel) {
        case 32:
                /* 0x88883316 */
-               return MAKE_PF(3, 2, 0, 1, 3, 8, 8, 8, 8);
+               return MAKE_PF(3, 2, 1, 0, 3, 8, 8, 8, 8);
        case 24:
                /* 0x88082219 */
-               return MAKE_PF(4, 0, 1, 2, 2, 0, 8, 8, 8);
+               return MAKE_PF(4, 0, 1, 2, 2, 8, 8, 8, 0);
        case 16:
                /* 0x65053118 */
                return MAKE_PF(4, 2, 1, 0, 1, 5, 6, 5, 0);
@@@ -1232,6 -1232,16 +1232,16 @@@ static int fsl_diu_ioctl(struct fb_inf
        return 0;
  }
  
+ static inline void fsl_diu_enable_interrupts(struct fsl_diu_data *data)
+ {
+       u32 int_mask = INT_UNDRUN; /* enable underrun detection */
+       if (IS_ENABLED(CONFIG_NOT_COHERENT_CACHE))
+               int_mask |= INT_VSYNC; /* enable vertical sync */
+       clrbits32(&data->diu_reg->int_mask, int_mask);
+ }
  /* turn on fb if count == 1
   */
  static int fsl_diu_open(struct fb_info *info, int user)
                if (res < 0)
                        mfbi->count--;
                else {
-                       struct fsl_diu_data *data = mfbi->parent;
- #ifdef CONFIG_NOT_COHERENT_CACHE
-                       /*
-                        * Enable underrun detection and vertical sync
-                        * interrupts.
-                        */
-                       clrbits32(&data->diu_reg->int_mask,
-                                 INT_UNDRUN | INT_VSYNC);
- #else
-                       /* Enable underrun detection */
-                       clrbits32(&data->diu_reg->int_mask, INT_UNDRUN);
- #endif
+                       fsl_diu_enable_interrupts(mfbi->parent);
                        fsl_diu_enable_panel(info);
                }
        }
@@@ -1283,9 -1281,18 +1281,18 @@@ static int fsl_diu_release(struct fb_in
        mfbi->count--;
        if (mfbi->count == 0) {
                struct fsl_diu_data *data = mfbi->parent;
+               bool disable = true;
+               int i;
  
-               /* Disable interrupts */
-               out_be32(&data->diu_reg->int_mask, 0xffffffff);
+               /* Disable interrupts only if all AOIs are closed */
+               for (i = 0; i < NUM_AOIS; i++) {
+                       struct mfb_info *mi = data->fsl_diu_info[i].par;
+                       if (mi->count)
+                               disable = false;
+               }
+               if (disable)
+                       out_be32(&data->diu_reg->int_mask, 0xffffffff);
                fsl_diu_disable_panel(info);
        }
  
@@@ -1307,7 -1314,7 +1314,7 @@@ static struct fb_ops fsl_diu_ops = 
        .fb_release = fsl_diu_release,
  };
  
 -static int __devinit install_fb(struct fb_info *info)
 +static int install_fb(struct fb_info *info)
  {
        int rc;
        struct mfb_info *mfbi = info->par;
@@@ -1518,7 -1525,7 +1525,7 @@@ static ssize_t show_monitor(struct devi
        return 0;
  }
  
 -static int __devinit fsl_diu_probe(struct platform_device *pdev)
 +static int fsl_diu_probe(struct platform_device *pdev)
  {
        struct device_node *np = pdev->dev.of_node;
        struct mfb_info *mfbi;
        out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr);
        out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr);
  
-       for (i = 0; i < NUM_AOIS; i++) {
-               ret = install_fb(&data->fsl_diu_info[i]);
-               if (ret) {
-                       dev_err(&pdev->dev, "could not register fb %d\n", i);
-                       goto error;
-               }
-       }
        /*
         * Older versions of U-Boot leave interrupts enabled, so disable
         * all of them and clear the status register.
        in_be32(&data->diu_reg->int_status);
  
        ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb",
-                         &data->diu_reg);
+                         data->diu_reg);
        if (ret) {
                dev_err(&pdev->dev, "could not claim irq\n");
                goto error;
        }
  
+       for (i = 0; i < NUM_AOIS; i++) {
+               ret = install_fb(&data->fsl_diu_info[i]);
+               if (ret) {
+                       dev_err(&pdev->dev, "could not register fb %d\n", i);
+                       free_irq(data->irq, data->diu_reg);
+                       goto error;
+               }
+       }
        sysfs_attr_init(&data->dev_attr.attr);
        data->dev_attr.attr.name = "monitor";
        data->dev_attr.attr.mode = S_IRUGO|S_IWUSR;
@@@ -1667,7 -1675,7 +1675,7 @@@ static int fsl_diu_remove(struct platfo
        data = dev_get_drvdata(&pdev->dev);
        disable_lcdc(&data->fsl_diu_info[0]);
  
-       free_irq(data->irq, &data->diu_reg);
+       free_irq(data->irq, data->diu_reg);
  
        for (i = 0; i < NUM_AOIS; i++)
                uninstall_fb(&data->fsl_diu_info[i]);