Skip to content

Commit

Permalink
DMAENGINE: ste_dma40: support older silicon
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Linus Walleij authored and djbw committed Jun 23, 2010
1 parent 6b7acd8 commit f418559
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 4 deletions.
2 changes: 2 additions & 0 deletions arch/arm/mach-ux500/devices-db8500.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
1 change: 1 addition & 0 deletions arch/arm/mach-ux500/include/mach/db8500-regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
32 changes: 28 additions & 4 deletions drivers/dma/ste_dma40.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -1426,13 +1439,21 @@ 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)
d40_config_set_event(d40c, true);
res = d40_channel_execute_command(d40c, D40_DMA_RUN);
}

no_suspend:
spin_unlock_irqrestore(&d40c->lock, flags);
return res;
}
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -2324,20 +2346,21 @@ 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;
}

/* The number of physical channels on this HW */
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;

Expand All @@ -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;
Expand Down

0 comments on commit f418559

Please sign in to comment.