mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-28 15:20:41 +00:00
DMAENGINE: ste_dma40: support older silicon
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>
This commit is contained in:
parent
6b7acd8442
commit
f41855929c
3 changed files with 31 additions and 4 deletions
|
@ -213,4 +213,6 @@ void dma40_u8500ed_fixup(void)
|
||||||
dma40_plat_data.memcpy_len = 0;
|
dma40_plat_data.memcpy_len = 0;
|
||||||
dma40_resources[0].start = U8500_DMA_BASE_ED;
|
dma40_resources[0].start = U8500_DMA_BASE_ED;
|
||||||
dma40_resources[0].end = U8500_DMA_BASE_ED + SZ_4K - 1;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#define U8500_ESRAM_BANK4 (U8500_ESRAM_BANK3 + U8500_ESRAM_BANK_SIZE)
|
#define U8500_ESRAM_BANK4 (U8500_ESRAM_BANK3 + U8500_ESRAM_BANK_SIZE)
|
||||||
/* Use bank 4 for DMA LCPA */
|
/* Use bank 4 for DMA LCPA */
|
||||||
#define U8500_DMA_LCPA_BASE U8500_ESRAM_BANK4
|
#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_PER3_BASE 0x80000000
|
||||||
#define U8500_STM_BASE 0x80100000
|
#define U8500_STM_BASE 0x80100000
|
||||||
|
|
|
@ -218,6 +218,7 @@ struct d40_chan {
|
||||||
* the same physical register.
|
* the same physical register.
|
||||||
* @dev: The device structure.
|
* @dev: The device structure.
|
||||||
* @virtbase: The virtual base address of the DMA's register.
|
* @virtbase: The virtual base address of the DMA's register.
|
||||||
|
* @rev: silicon revision detected.
|
||||||
* @clk: Pointer to the DMA clock structure.
|
* @clk: Pointer to the DMA clock structure.
|
||||||
* @phy_start: Physical memory start of the DMA registers.
|
* @phy_start: Physical memory start of the DMA registers.
|
||||||
* @phy_size: Size of the DMA register map.
|
* @phy_size: Size of the DMA register map.
|
||||||
|
@ -250,6 +251,7 @@ struct d40_base {
|
||||||
spinlock_t execmd_lock;
|
spinlock_t execmd_lock;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
void __iomem *virtbase;
|
void __iomem *virtbase;
|
||||||
|
u8 rev:4;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
phys_addr_t phy_start;
|
phys_addr_t phy_start;
|
||||||
resource_size_t phy_size;
|
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)
|
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)
|
if (d40c->log_num != D40_PHY_CHAN)
|
||||||
d40_config_set_event(d40c, true);
|
d40_config_set_event(d40c, true);
|
||||||
|
|
||||||
|
@ -1426,6 +1439,13 @@ static int d40_resume(struct dma_chan *chan)
|
||||||
|
|
||||||
spin_lock_irqsave(&d40c->lock, flags);
|
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 bytes left to transfer or linked tx resume job */
|
||||||
if (d40_residue(d40c) || d40_tx_is_linked(d40c)) {
|
if (d40_residue(d40c) || d40_tx_is_linked(d40c)) {
|
||||||
if (d40c->log_num != D40_PHY_CHAN)
|
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);
|
res = d40_channel_execute_command(d40c, D40_DMA_RUN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
no_suspend:
|
||||||
spin_unlock_irqrestore(&d40c->lock, flags);
|
spin_unlock_irqrestore(&d40c->lock, flags);
|
||||||
return res;
|
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_log_chans = 0;
|
||||||
int num_phy_chans;
|
int num_phy_chans;
|
||||||
int i;
|
int i;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
clk = clk_get(&pdev->dev, NULL);
|
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,
|
dev_err(&pdev->dev,
|
||||||
"[%s] Unknown designer! Got %x wanted %x\n",
|
"[%s] Unknown designer! Got %x wanted %x\n",
|
||||||
__func__, i & 0xf, D40_PERIPHID2_DESIGNER);
|
__func__, val & 0xf, D40_PERIPHID2_DESIGNER);
|
||||||
goto failure;
|
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;
|
num_phy_chans = 4 * (readl(virtbase + D40_DREG_ICFG) & 0x7) + 4;
|
||||||
|
|
||||||
dev_info(&pdev->dev, "hardware revision: %d @ 0x%x\n",
|
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;
|
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;
|
goto failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base->rev = (val >> 4) & 0xf;
|
||||||
base->clk = clk;
|
base->clk = clk;
|
||||||
base->num_phy_chans = num_phy_chans;
|
base->num_phy_chans = num_phy_chans;
|
||||||
base->num_log_chans = num_log_chans;
|
base->num_log_chans = num_log_chans;
|
||||||
|
|
Loading…
Reference in a new issue