From 5899a723b336da241b492583d7e55f1055f8f3b3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 17 Jun 2011 08:20:40 +0000 Subject: dmaengine: shdma: add chcr_write/read function CHCR register position is not same in all DMAC. This patch adds new "chcr_offset" to decide it. Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 41a21b3..40900c1 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -78,6 +78,20 @@ static void dmaor_write(struct sh_dmae_device *shdev, u16 data) __raw_writew(data, shdev->chan_reg + DMAOR / sizeof(u32)); } +static void chcr_write(struct sh_dmae_chan *sh_dc, u32 data) +{ + struct sh_dmae_device *shdev = to_sh_dev(sh_dc); + + __raw_writel(data, sh_dc->base + shdev->chcr_offset / sizeof(u32)); +} + +static u32 chcr_read(struct sh_dmae_chan *sh_dc) +{ + struct sh_dmae_device *shdev = to_sh_dev(sh_dc); + + return __raw_readl(sh_dc->base + shdev->chcr_offset / sizeof(u32)); +} + /* * Reset DMA controller * @@ -120,7 +134,7 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev) static bool dmae_is_busy(struct sh_dmae_chan *sh_chan) { - u32 chcr = sh_dmae_readl(sh_chan, CHCR); + u32 chcr = chcr_read(sh_chan); if ((chcr & (CHCR_DE | CHCR_TE)) == CHCR_DE) return true; /* working */ @@ -167,18 +181,18 @@ static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs *hw) static void dmae_start(struct sh_dmae_chan *sh_chan) { - u32 chcr = sh_dmae_readl(sh_chan, CHCR); + u32 chcr = chcr_read(sh_chan); chcr |= CHCR_DE | CHCR_IE; - sh_dmae_writel(sh_chan, chcr & ~CHCR_TE, CHCR); + chcr_write(sh_chan, chcr & ~CHCR_TE); } static void dmae_halt(struct sh_dmae_chan *sh_chan) { - u32 chcr = sh_dmae_readl(sh_chan, CHCR); + u32 chcr = chcr_read(sh_chan); chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE); - sh_dmae_writel(sh_chan, chcr, CHCR); + chcr_write(sh_chan, chcr); } static void dmae_init(struct sh_dmae_chan *sh_chan) @@ -190,7 +204,7 @@ static void dmae_init(struct sh_dmae_chan *sh_chan) u32 chcr = DM_INC | SM_INC | 0x400 | log2size_to_chcr(sh_chan, LOG2_DEFAULT_XFER_SIZE); sh_chan->xmit_shift = calc_xmit_shift(sh_chan, chcr); - sh_dmae_writel(sh_chan, chcr, CHCR); + chcr_write(sh_chan, chcr); } static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val) @@ -200,7 +214,7 @@ static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val) return -EBUSY; sh_chan->xmit_shift = calc_xmit_shift(sh_chan, val); - sh_dmae_writel(sh_chan, val, CHCR); + chcr_write(sh_chan, val); return 0; } @@ -840,7 +854,7 @@ static irqreturn_t sh_dmae_interrupt(int irq, void *data) spin_lock(&sh_chan->desc_lock); - chcr = sh_dmae_readl(sh_chan, CHCR); + chcr = chcr_read(sh_chan); if (chcr & CHCR_TE) { /* DMA stop */ @@ -1138,6 +1152,11 @@ static int __init sh_dmae_probe(struct platform_device *pdev) /* platform data */ shdev->pdata = pdata; + if (pdata->chcr_offset) + shdev->chcr_offset = pdata->chcr_offset; + else + shdev->chcr_offset = CHCR; + platform_set_drvdata(pdev, shdev); pm_runtime_enable(&pdev->dev); diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h index 6c73b65..6f064ca 100644 --- a/drivers/dma/shdma.h +++ b/drivers/dma/shdma.h @@ -47,6 +47,7 @@ struct sh_dmae_device { struct list_head node; u32 __iomem *chan_reg; u16 __iomem *dmars; + unsigned int chcr_offset; }; #define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, common) diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h index b08cd4e..41fe4c2 100644 --- a/include/linux/sh_dma.h +++ b/include/linux/sh_dma.h @@ -62,6 +62,7 @@ struct sh_dmae_pdata { const unsigned int *ts_shift; int ts_shift_num; u16 dmaor_init; + unsigned int chcr_offset; }; /* DMA register */ -- cgit v0.10.2 From 67c6269e5c998b53c2c08ce2befbbe20a7b6f57f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 17 Jun 2011 08:20:51 +0000 Subject: dmaengine: shdma: add chcr_ie_bit IE bit position on CHCR register is not same in all DMAC. This patch adds new "chcr_ie_bit" to decide it. Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 40900c1..9412de3 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -181,17 +181,19 @@ static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs *hw) static void dmae_start(struct sh_dmae_chan *sh_chan) { + struct sh_dmae_device *shdev = to_sh_dev(sh_chan); u32 chcr = chcr_read(sh_chan); - chcr |= CHCR_DE | CHCR_IE; + chcr |= CHCR_DE | shdev->chcr_ie_bit; chcr_write(sh_chan, chcr & ~CHCR_TE); } static void dmae_halt(struct sh_dmae_chan *sh_chan) { + struct sh_dmae_device *shdev = to_sh_dev(sh_chan); u32 chcr = chcr_read(sh_chan); - chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE); + chcr &= ~(CHCR_DE | CHCR_TE | shdev->chcr_ie_bit); chcr_write(sh_chan, chcr); } @@ -1157,6 +1159,11 @@ static int __init sh_dmae_probe(struct platform_device *pdev) else shdev->chcr_offset = CHCR; + if (pdata->chcr_ie_bit) + shdev->chcr_ie_bit = pdata->chcr_ie_bit; + else + shdev->chcr_ie_bit = CHCR_IE; + platform_set_drvdata(pdev, shdev); pm_runtime_enable(&pdev->dev); diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h index 6f064ca..dc56576 100644 --- a/drivers/dma/shdma.h +++ b/drivers/dma/shdma.h @@ -48,6 +48,7 @@ struct sh_dmae_device { u32 __iomem *chan_reg; u16 __iomem *dmars; unsigned int chcr_offset; + u32 chcr_ie_bit; }; #define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, common) diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h index 41fe4c2..96803aa 100644 --- a/include/linux/sh_dma.h +++ b/include/linux/sh_dma.h @@ -63,6 +63,7 @@ struct sh_dmae_pdata { int ts_shift_num; u16 dmaor_init; unsigned int chcr_offset; + u32 chcr_ie_bit; }; /* DMA register */ -- cgit v0.10.2 From e76c3af873025f5a704d56a28882be761e15657b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 17 Jun 2011 08:20:56 +0000 Subject: dmaengine: shdma: add dmaor_is_32bit flag Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 9412de3..6a21cd8 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -70,12 +70,22 @@ static u32 sh_dmae_readl(struct sh_dmae_chan *sh_dc, u32 reg) static u16 dmaor_read(struct sh_dmae_device *shdev) { - return __raw_readw(shdev->chan_reg + DMAOR / sizeof(u32)); + u32 __iomem *addr = shdev->chan_reg + DMAOR / sizeof(u32); + + if (shdev->pdata->dmaor_is_32bit) + return __raw_readl(addr); + else + return __raw_readw(addr); } static void dmaor_write(struct sh_dmae_device *shdev, u16 data) { - __raw_writew(data, shdev->chan_reg + DMAOR / sizeof(u32)); + u32 __iomem *addr = shdev->chan_reg + DMAOR / sizeof(u32); + + if (shdev->pdata->dmaor_is_32bit) + __raw_writel(data, addr); + else + __raw_writew(data, addr); } static void chcr_write(struct sh_dmae_chan *sh_dc, u32 data) diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h index 96803aa..f25afc6 100644 --- a/include/linux/sh_dma.h +++ b/include/linux/sh_dma.h @@ -64,6 +64,8 @@ struct sh_dmae_pdata { u16 dmaor_init; unsigned int chcr_offset; u32 chcr_ie_bit; + + unsigned int dmaor_is_32bit:1; }; /* DMA register */ -- cgit v0.10.2 From 260bf2c5f69f419b04b6861ca91565b5fb16ce48 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 17 Jun 2011 08:21:05 +0000 Subject: dmaengine: shdma: add .needs_tend_set / .no_dmars flags Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 6a21cd8..0f3ec8d 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -194,6 +194,9 @@ static void dmae_start(struct sh_dmae_chan *sh_chan) struct sh_dmae_device *shdev = to_sh_dev(sh_chan); u32 chcr = chcr_read(sh_chan); + if (shdev->pdata->needs_tend_set) + sh_dmae_writel(sh_chan, 0xFFFFFFFF, TEND); + chcr |= CHCR_DE | shdev->chcr_ie_bit; chcr_write(sh_chan, chcr & ~CHCR_TE); } @@ -242,6 +245,9 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val) if (dmae_is_busy(sh_chan)) return -EBUSY; + if (pdata->no_dmars) + return 0; + /* in the case of a missing DMARS resource use first memory window */ if (!addr) addr = (u16 __iomem *)shdev->chan_reg; diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h index f25afc6..cb2dd11 100644 --- a/include/linux/sh_dma.h +++ b/include/linux/sh_dma.h @@ -66,6 +66,8 @@ struct sh_dmae_pdata { u32 chcr_ie_bit; unsigned int dmaor_is_32bit:1; + unsigned int needs_tend_set:1; + unsigned int no_dmars:1; }; /* DMA register */ @@ -75,6 +77,8 @@ struct sh_dmae_pdata { #define CHCR 0x0C #define DMAOR 0x40 +#define TEND 0x18 /* USB-DMAC */ + /* DMAOR definitions */ #define DMAOR_AE 0x00000004 #define DMAOR_NMIF 0x00000002 -- cgit v0.10.2