dma: mv_xor: allow channels to be registered directly from the main device
authorThomas Petazzoni <thomas.petazzoni@free-electrons.com>
Mon, 29 Oct 2012 15:54:49 +0000 (16:54 +0100)
committerThomas Petazzoni <thomas.petazzoni@free-electrons.com>
Tue, 20 Nov 2012 14:58:56 +0000 (15:58 +0100)
Extend the XOR engine driver (currently called "mv_xor_shared") so
that XOR channels can be passed in the platform_data structure, and be
registered from there.

This will allow the users of the driver to be converted to the single
platform_driver variant of the mv_xor driver.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
drivers/dma/mv_xor.c
drivers/dma/mv_xor.h
include/linux/platform_data/dma-mv_xor.h

index f7b9919..6ed3162 100644 (file)
@@ -1292,7 +1292,9 @@ static int mv_xor_shared_probe(struct platform_device *pdev)
 {
        const struct mbus_dram_target_info *dram;
        struct mv_xor_shared_private *msp;
+       struct mv_xor_shared_platform_data *pdata = pdev->dev.platform_data;
        struct resource *res;
+       int i, ret;
 
        dev_notice(&pdev->dev, "Marvell shared XOR driver\n");
 
@@ -1334,12 +1336,55 @@ static int mv_xor_shared_probe(struct platform_device *pdev)
        if (!IS_ERR(msp->clk))
                clk_prepare_enable(msp->clk);
 
+       if (pdata && pdata->channels) {
+               for (i = 0; i < MV_XOR_MAX_CHANNELS; i++) {
+                       struct mv_xor_platform_data *cd;
+                       int irq;
+
+                       cd = &pdata->channels[i];
+                       if (!cd) {
+                               ret = -ENODEV;
+                               goto err_channel_add;
+                       }
+
+                       irq = platform_get_irq(pdev, i);
+                       if (irq < 0) {
+                               ret = irq;
+                               goto err_channel_add;
+                       }
+
+                       msp->channels[i] =
+                               mv_xor_channel_add(msp, pdev, cd->hw_id,
+                                                  cd->cap_mask,
+                                                  cd->pool_size, irq);
+                       if (IS_ERR(msp->channels[i])) {
+                               ret = PTR_ERR(msp->channels[i]);
+                               goto err_channel_add;
+                       }
+               }
+       }
+
        return 0;
+
+err_channel_add:
+       for (i = 0; i < MV_XOR_MAX_CHANNELS; i++)
+               if (msp->channels[i])
+                       mv_xor_channel_remove(msp->channels[i]);
+
+       clk_disable_unprepare(msp->clk);
+       clk_put(msp->clk);
+       return ret;
 }
 
 static int mv_xor_shared_remove(struct platform_device *pdev)
 {
        struct mv_xor_shared_private *msp = platform_get_drvdata(pdev);
+       int i;
+
+       for (i = 0; i < MV_XOR_MAX_CHANNELS; i++) {
+               if (msp->channels[i])
+                       mv_xor_channel_remove(msp->channels[i]);
+       }
 
        if (!IS_ERR(msp->clk)) {
                clk_disable_unprepare(msp->clk);
index a0641ae..686575f 100644 (file)
@@ -26,6 +26,7 @@
 #define USE_TIMER
 #define MV_XOR_SLOT_SIZE               64
 #define MV_XOR_THRESHOLD               1
+#define MV_XOR_MAX_CHANNELS             2
 
 #define XOR_OPERATION_MODE_XOR         0
 #define XOR_OPERATION_MODE_MEMCPY      2
 #define WINDOW_BAR_ENABLE(chan)        (0x240 + ((chan) << 2))
 
 struct mv_xor_shared_private {
-       void __iomem    *xor_base;
-       void __iomem    *xor_high_base;
-       struct clk      *clk;
+       void __iomem         *xor_base;
+       void __iomem         *xor_high_base;
+       struct clk           *clk;
+       struct mv_xor_device *channels[MV_XOR_MAX_CHANNELS];
 };
 
 
index 2ba1f7d..f2aed97 100644 (file)
@@ -20,5 +20,8 @@ struct mv_xor_platform_data {
        size_t                          pool_size;
 };
 
+struct mv_xor_shared_platform_data {
+       struct mv_xor_platform_data    *channels;
+};
 
 #endif