]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
DMAENGINE: ste_dma40: support older silicon
authorLinus Walleij <linus.walleij@stericsson.com>
Wed, 23 Jun 2010 01:06:42 +0000 (18:06 -0700)
committerDan Williams <dan.j.williams@intel.com>
Wed, 23 Jun 2010 01:06:42 +0000 (18:06 -0700)
This makes sure the DMA40 driver will also work on the oldest
silicon revisions that have the on-chip memory on another location
in the DB8500 and also requires explicit suspend before starting
or resuming a logical channel.

Signed-off-by: Linus Walleij <linus.walleij@stericsson.com>
[added parenthesis to the definition of U8500_DMA_LCPA_BASE_ED]
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
arch/arm/mach-ux500/devices-db8500.c
arch/arm/mach-ux500/include/mach/db8500-regs.h
drivers/dma/ste_dma40.c

index e2b7c31ef37228812f95b2adc0476992069637fb..c62cdbee3bd9bf4b55d3328211d8b908abd7d2e7 100644 (file)
@@ -213,4 +213,6 @@ void dma40_u8500ed_fixup(void)
        dma40_plat_data.memcpy_len = 0;
        dma40_resources[0].start = U8500_DMA_BASE_ED;
        dma40_resources[0].end = U8500_DMA_BASE_ED + SZ_4K - 1;
+       dma40_resources[1].start = U8500_DMA_LCPA_BASE_ED;
+       dma40_resources[1].end = U8500_DMA_LCPA_BASE_ED + 2 * SZ_1K - 1;
 }
index 897fa35078ef296a8d2ea7113dd0264344c405c8..f000218210c947ea406692ee1663ee7ac5395ab9 100644 (file)
@@ -17,6 +17,7 @@
 #define U8500_ESRAM_BANK4      (U8500_ESRAM_BANK3 + U8500_ESRAM_BANK_SIZE)
 /* Use bank 4 for DMA LCPA */
 #define U8500_DMA_LCPA_BASE    U8500_ESRAM_BANK4
+#define U8500_DMA_LCPA_BASE_ED (U8500_ESRAM_BANK4 + 0x4000)
 
 #define U8500_PER3_BASE                0x80000000
 #define U8500_STM_BASE         0x80100000
index 1d21fbd419d182f7e64ee4c3c431165d85401fff..21a759731ef1433e44e694f0e5920fe30ea7e2ff 100644 (file)
@@ -218,6 +218,7 @@ struct d40_chan {
  * the same physical register.
  * @dev: The device structure.
  * @virtbase: The virtual base address of the DMA's register.
+ * @rev: silicon revision detected.
  * @clk: Pointer to the DMA clock structure.
  * @phy_start: Physical memory start of the DMA registers.
  * @phy_size: Size of the DMA register map.
@@ -250,6 +251,7 @@ struct d40_base {
        spinlock_t                       execmd_lock;
        struct device                    *dev;
        void __iomem                     *virtbase;
+       u8                                rev:4;
        struct clk                       *clk;
        phys_addr_t                       phy_start;
        resource_size_t                   phy_size;
@@ -757,6 +759,17 @@ static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx)
 
 static int d40_start(struct d40_chan *d40c)
 {
+       if (d40c->base->rev == 0) {
+               int err;
+
+               if (d40c->log_num != D40_PHY_CHAN) {
+                       err = d40_channel_execute_command(d40c,
+                                                         D40_DMA_SUSPEND_REQ);
+                       if (err)
+                               return err;
+               }
+       }
+
        if (d40c->log_num != D40_PHY_CHAN)
                d40_config_set_event(d40c, true);
 
@@ -1426,6 +1439,13 @@ static int d40_resume(struct dma_chan *chan)
 
        spin_lock_irqsave(&d40c->lock, flags);
 
+       if (d40c->base->rev == 0)
+               if (d40c->log_num != D40_PHY_CHAN) {
+                       res = d40_channel_execute_command(d40c,
+                                                         D40_DMA_SUSPEND_REQ);
+                       goto no_suspend;
+               }
+
        /* If bytes left to transfer or linked tx resume job */
        if (d40_residue(d40c) || d40_tx_is_linked(d40c)) {
                if (d40c->log_num != D40_PHY_CHAN)
@@ -1433,6 +1453,7 @@ static int d40_resume(struct dma_chan *chan)
                res = d40_channel_execute_command(d40c, D40_DMA_RUN);
        }
 
+no_suspend:
        spin_unlock_irqrestore(&d40c->lock, flags);
        return res;
 }
@@ -2286,6 +2307,7 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
        int num_log_chans = 0;
        int num_phy_chans;
        int i;
+       u32 val;
 
        clk = clk_get(&pdev->dev, NULL);
 
@@ -2324,12 +2346,13 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
                }
        }
 
-       i = readl(virtbase + D40_DREG_PERIPHID2);
+       /* Get silicon revision */
+       val = readl(virtbase + D40_DREG_PERIPHID2);
 
-       if ((i & 0xf) != D40_PERIPHID2_DESIGNER) {
+       if ((val & 0xf) != D40_PERIPHID2_DESIGNER) {
                dev_err(&pdev->dev,
                        "[%s] Unknown designer! Got %x wanted %x\n",
-                       __func__, i & 0xf, D40_PERIPHID2_DESIGNER);
+                       __func__, val & 0xf, D40_PERIPHID2_DESIGNER);
                goto failure;
        }
 
@@ -2337,7 +2360,7 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
        num_phy_chans = 4 * (readl(virtbase + D40_DREG_ICFG) & 0x7) + 4;
 
        dev_info(&pdev->dev, "hardware revision: %d @ 0x%x\n",
-                (i >> 4) & 0xf, res->start);
+                (val >> 4) & 0xf, res->start);
 
        plat_data = pdev->dev.platform_data;
 
@@ -2359,6 +2382,7 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
                goto failure;
        }
 
+       base->rev = (val >> 4) & 0xf;
        base->clk = clk;
        base->num_phy_chans = num_phy_chans;
        base->num_log_chans = num_log_chans;