Loading drivers/dma/shdma.c +54 −12 Original line number Original line Diff line number Diff line Loading @@ -70,12 +70,36 @@ static u32 sh_dmae_readl(struct sh_dmae_chan *sh_dc, u32 reg) static u16 dmaor_read(struct sh_dmae_device *shdev) 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) 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) { 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)); } } /* /* Loading Loading @@ -120,7 +144,7 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev) static bool dmae_is_busy(struct sh_dmae_chan *sh_chan) 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) if ((chcr & (CHCR_DE | CHCR_TE)) == CHCR_DE) return true; /* working */ return true; /* working */ Loading Loading @@ -167,18 +191,23 @@ 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) static void dmae_start(struct sh_dmae_chan *sh_chan) { { u32 chcr = sh_dmae_readl(sh_chan, CHCR); 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 | CHCR_IE; chcr |= CHCR_DE | shdev->chcr_ie_bit; 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) static void dmae_halt(struct sh_dmae_chan *sh_chan) { { u32 chcr = sh_dmae_readl(sh_chan, CHCR); 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); sh_dmae_writel(sh_chan, chcr, CHCR); chcr_write(sh_chan, chcr); } } static void dmae_init(struct sh_dmae_chan *sh_chan) static void dmae_init(struct sh_dmae_chan *sh_chan) Loading @@ -190,7 +219,7 @@ static void dmae_init(struct sh_dmae_chan *sh_chan) u32 chcr = DM_INC | SM_INC | 0x400 | log2size_to_chcr(sh_chan, u32 chcr = DM_INC | SM_INC | 0x400 | log2size_to_chcr(sh_chan, LOG2_DEFAULT_XFER_SIZE); LOG2_DEFAULT_XFER_SIZE); sh_chan->xmit_shift = calc_xmit_shift(sh_chan, chcr); 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) static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val) Loading @@ -200,7 +229,7 @@ static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val) return -EBUSY; return -EBUSY; sh_chan->xmit_shift = calc_xmit_shift(sh_chan, val); sh_chan->xmit_shift = calc_xmit_shift(sh_chan, val); sh_dmae_writel(sh_chan, val, CHCR); chcr_write(sh_chan, val); return 0; return 0; } } Loading @@ -216,6 +245,9 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val) if (dmae_is_busy(sh_chan)) if (dmae_is_busy(sh_chan)) return -EBUSY; return -EBUSY; if (pdata->no_dmars) return 0; /* in the case of a missing DMARS resource use first memory window */ /* in the case of a missing DMARS resource use first memory window */ if (!addr) if (!addr) addr = (u16 __iomem *)shdev->chan_reg; addr = (u16 __iomem *)shdev->chan_reg; Loading Loading @@ -840,7 +872,7 @@ static irqreturn_t sh_dmae_interrupt(int irq, void *data) spin_lock(&sh_chan->desc_lock); spin_lock(&sh_chan->desc_lock); chcr = sh_dmae_readl(sh_chan, CHCR); chcr = chcr_read(sh_chan); if (chcr & CHCR_TE) { if (chcr & CHCR_TE) { /* DMA stop */ /* DMA stop */ Loading Loading @@ -1138,6 +1170,16 @@ static int __init sh_dmae_probe(struct platform_device *pdev) /* platform data */ /* platform data */ shdev->pdata = pdata; shdev->pdata = pdata; if (pdata->chcr_offset) shdev->chcr_offset = pdata->chcr_offset; 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); platform_set_drvdata(pdev, shdev); pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev); Loading drivers/dma/shdma.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -47,6 +47,8 @@ struct sh_dmae_device { struct list_head node; struct list_head node; u32 __iomem *chan_reg; u32 __iomem *chan_reg; u16 __iomem *dmars; u16 __iomem *dmars; unsigned int chcr_offset; u32 chcr_ie_bit; }; }; #define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, common) #define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, common) Loading include/linux/sh_dma.h +8 −0 Original line number Original line Diff line number Diff line Loading @@ -62,6 +62,12 @@ struct sh_dmae_pdata { const unsigned int *ts_shift; const unsigned int *ts_shift; int ts_shift_num; int ts_shift_num; u16 dmaor_init; u16 dmaor_init; unsigned int chcr_offset; u32 chcr_ie_bit; unsigned int dmaor_is_32bit:1; unsigned int needs_tend_set:1; unsigned int no_dmars:1; }; }; /* DMA register */ /* DMA register */ Loading @@ -71,6 +77,8 @@ struct sh_dmae_pdata { #define CHCR 0x0C #define CHCR 0x0C #define DMAOR 0x40 #define DMAOR 0x40 #define TEND 0x18 /* USB-DMAC */ /* DMAOR definitions */ /* DMAOR definitions */ #define DMAOR_AE 0x00000004 #define DMAOR_AE 0x00000004 #define DMAOR_NMIF 0x00000002 #define DMAOR_NMIF 0x00000002 Loading Loading
drivers/dma/shdma.c +54 −12 Original line number Original line Diff line number Diff line Loading @@ -70,12 +70,36 @@ static u32 sh_dmae_readl(struct sh_dmae_chan *sh_dc, u32 reg) static u16 dmaor_read(struct sh_dmae_device *shdev) 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) 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) { 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)); } } /* /* Loading Loading @@ -120,7 +144,7 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev) static bool dmae_is_busy(struct sh_dmae_chan *sh_chan) 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) if ((chcr & (CHCR_DE | CHCR_TE)) == CHCR_DE) return true; /* working */ return true; /* working */ Loading Loading @@ -167,18 +191,23 @@ 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) static void dmae_start(struct sh_dmae_chan *sh_chan) { { u32 chcr = sh_dmae_readl(sh_chan, CHCR); 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 | CHCR_IE; chcr |= CHCR_DE | shdev->chcr_ie_bit; 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) static void dmae_halt(struct sh_dmae_chan *sh_chan) { { u32 chcr = sh_dmae_readl(sh_chan, CHCR); 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); sh_dmae_writel(sh_chan, chcr, CHCR); chcr_write(sh_chan, chcr); } } static void dmae_init(struct sh_dmae_chan *sh_chan) static void dmae_init(struct sh_dmae_chan *sh_chan) Loading @@ -190,7 +219,7 @@ static void dmae_init(struct sh_dmae_chan *sh_chan) u32 chcr = DM_INC | SM_INC | 0x400 | log2size_to_chcr(sh_chan, u32 chcr = DM_INC | SM_INC | 0x400 | log2size_to_chcr(sh_chan, LOG2_DEFAULT_XFER_SIZE); LOG2_DEFAULT_XFER_SIZE); sh_chan->xmit_shift = calc_xmit_shift(sh_chan, chcr); 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) static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val) Loading @@ -200,7 +229,7 @@ static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val) return -EBUSY; return -EBUSY; sh_chan->xmit_shift = calc_xmit_shift(sh_chan, val); sh_chan->xmit_shift = calc_xmit_shift(sh_chan, val); sh_dmae_writel(sh_chan, val, CHCR); chcr_write(sh_chan, val); return 0; return 0; } } Loading @@ -216,6 +245,9 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val) if (dmae_is_busy(sh_chan)) if (dmae_is_busy(sh_chan)) return -EBUSY; return -EBUSY; if (pdata->no_dmars) return 0; /* in the case of a missing DMARS resource use first memory window */ /* in the case of a missing DMARS resource use first memory window */ if (!addr) if (!addr) addr = (u16 __iomem *)shdev->chan_reg; addr = (u16 __iomem *)shdev->chan_reg; Loading Loading @@ -840,7 +872,7 @@ static irqreturn_t sh_dmae_interrupt(int irq, void *data) spin_lock(&sh_chan->desc_lock); spin_lock(&sh_chan->desc_lock); chcr = sh_dmae_readl(sh_chan, CHCR); chcr = chcr_read(sh_chan); if (chcr & CHCR_TE) { if (chcr & CHCR_TE) { /* DMA stop */ /* DMA stop */ Loading Loading @@ -1138,6 +1170,16 @@ static int __init sh_dmae_probe(struct platform_device *pdev) /* platform data */ /* platform data */ shdev->pdata = pdata; shdev->pdata = pdata; if (pdata->chcr_offset) shdev->chcr_offset = pdata->chcr_offset; 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); platform_set_drvdata(pdev, shdev); pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev); Loading
drivers/dma/shdma.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -47,6 +47,8 @@ struct sh_dmae_device { struct list_head node; struct list_head node; u32 __iomem *chan_reg; u32 __iomem *chan_reg; u16 __iomem *dmars; u16 __iomem *dmars; unsigned int chcr_offset; u32 chcr_ie_bit; }; }; #define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, common) #define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, common) Loading
include/linux/sh_dma.h +8 −0 Original line number Original line Diff line number Diff line Loading @@ -62,6 +62,12 @@ struct sh_dmae_pdata { const unsigned int *ts_shift; const unsigned int *ts_shift; int ts_shift_num; int ts_shift_num; u16 dmaor_init; u16 dmaor_init; unsigned int chcr_offset; u32 chcr_ie_bit; unsigned int dmaor_is_32bit:1; unsigned int needs_tend_set:1; unsigned int no_dmars:1; }; }; /* DMA register */ /* DMA register */ Loading @@ -71,6 +77,8 @@ struct sh_dmae_pdata { #define CHCR 0x0C #define CHCR 0x0C #define DMAOR 0x40 #define DMAOR 0x40 #define TEND 0x18 /* USB-DMAC */ /* DMAOR definitions */ /* DMAOR definitions */ #define DMAOR_AE 0x00000004 #define DMAOR_AE 0x00000004 #define DMAOR_NMIF 0x00000002 #define DMAOR_NMIF 0x00000002 Loading