aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/shdma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma/shdma.c')
-rw-r--r--drivers/dma/shdma.c66
1 files changed, 54 insertions, 12 deletions
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index 707d30ce3354..7f49235d14b9 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -70,12 +70,36 @@ static u32 sh_dmae_readl(struct sh_dmae_chan *sh_dc, u32 reg)
70 70
71static u16 dmaor_read(struct sh_dmae_device *shdev) 71static u16 dmaor_read(struct sh_dmae_device *shdev)
72{ 72{
73 return __raw_readw(shdev->chan_reg + DMAOR / sizeof(u32)); 73 u32 __iomem *addr = shdev->chan_reg + DMAOR / sizeof(u32);
74
75 if (shdev->pdata->dmaor_is_32bit)
76 return __raw_readl(addr);
77 else
78 return __raw_readw(addr);
74} 79}
75 80
76static void dmaor_write(struct sh_dmae_device *shdev, u16 data) 81static void dmaor_write(struct sh_dmae_device *shdev, u16 data)
77{ 82{
78 __raw_writew(data, shdev->chan_reg + DMAOR / sizeof(u32)); 83 u32 __iomem *addr = shdev->chan_reg + DMAOR / sizeof(u32);
84
85 if (shdev->pdata->dmaor_is_32bit)
86 __raw_writel(data, addr);
87 else
88 __raw_writew(data, addr);
89}
90
91static void chcr_write(struct sh_dmae_chan *sh_dc, u32 data)
92{
93 struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
94
95 __raw_writel(data, sh_dc->base + shdev->chcr_offset / sizeof(u32));
96}
97
98static u32 chcr_read(struct sh_dmae_chan *sh_dc)
99{
100 struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
101
102 return __raw_readl(sh_dc->base + shdev->chcr_offset / sizeof(u32));
79} 103}
80 104
81/* 105/*
@@ -120,7 +144,7 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev)
120 144
121static bool dmae_is_busy(struct sh_dmae_chan *sh_chan) 145static bool dmae_is_busy(struct sh_dmae_chan *sh_chan)
122{ 146{
123 u32 chcr = sh_dmae_readl(sh_chan, CHCR); 147 u32 chcr = chcr_read(sh_chan);
124 148
125 if ((chcr & (CHCR_DE | CHCR_TE)) == CHCR_DE) 149 if ((chcr & (CHCR_DE | CHCR_TE)) == CHCR_DE)
126 return true; /* working */ 150 return true; /* working */
@@ -167,18 +191,23 @@ static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs *hw)
167 191
168static void dmae_start(struct sh_dmae_chan *sh_chan) 192static void dmae_start(struct sh_dmae_chan *sh_chan)
169{ 193{
170 u32 chcr = sh_dmae_readl(sh_chan, CHCR); 194 struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
195 u32 chcr = chcr_read(sh_chan);
171 196
172 chcr |= CHCR_DE | CHCR_IE; 197 if (shdev->pdata->needs_tend_set)
173 sh_dmae_writel(sh_chan, chcr & ~CHCR_TE, CHCR); 198 sh_dmae_writel(sh_chan, 0xFFFFFFFF, TEND);
199
200 chcr |= CHCR_DE | shdev->chcr_ie_bit;
201 chcr_write(sh_chan, chcr & ~CHCR_TE);
174} 202}
175 203
176static void dmae_halt(struct sh_dmae_chan *sh_chan) 204static void dmae_halt(struct sh_dmae_chan *sh_chan)
177{ 205{
178 u32 chcr = sh_dmae_readl(sh_chan, CHCR); 206 struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
207 u32 chcr = chcr_read(sh_chan);
179 208
180 chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE); 209 chcr &= ~(CHCR_DE | CHCR_TE | shdev->chcr_ie_bit);
181 sh_dmae_writel(sh_chan, chcr, CHCR); 210 chcr_write(sh_chan, chcr);
182} 211}
183 212
184static void dmae_init(struct sh_dmae_chan *sh_chan) 213static void dmae_init(struct sh_dmae_chan *sh_chan)
@@ -190,7 +219,7 @@ static void dmae_init(struct sh_dmae_chan *sh_chan)
190 u32 chcr = DM_INC | SM_INC | 0x400 | log2size_to_chcr(sh_chan, 219 u32 chcr = DM_INC | SM_INC | 0x400 | log2size_to_chcr(sh_chan,
191 LOG2_DEFAULT_XFER_SIZE); 220 LOG2_DEFAULT_XFER_SIZE);
192 sh_chan->xmit_shift = calc_xmit_shift(sh_chan, chcr); 221 sh_chan->xmit_shift = calc_xmit_shift(sh_chan, chcr);
193 sh_dmae_writel(sh_chan, chcr, CHCR); 222 chcr_write(sh_chan, chcr);
194} 223}
195 224
196static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val) 225static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val)
@@ -200,7 +229,7 @@ static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val)
200 return -EBUSY; 229 return -EBUSY;
201 230
202 sh_chan->xmit_shift = calc_xmit_shift(sh_chan, val); 231 sh_chan->xmit_shift = calc_xmit_shift(sh_chan, val);
203 sh_dmae_writel(sh_chan, val, CHCR); 232 chcr_write(sh_chan, val);
204 233
205 return 0; 234 return 0;
206} 235}
@@ -216,6 +245,9 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
216 if (dmae_is_busy(sh_chan)) 245 if (dmae_is_busy(sh_chan))
217 return -EBUSY; 246 return -EBUSY;
218 247
248 if (pdata->no_dmars)
249 return 0;
250
219 /* in the case of a missing DMARS resource use first memory window */ 251 /* in the case of a missing DMARS resource use first memory window */
220 if (!addr) 252 if (!addr)
221 addr = (u16 __iomem *)shdev->chan_reg; 253 addr = (u16 __iomem *)shdev->chan_reg;
@@ -840,7 +872,7 @@ static irqreturn_t sh_dmae_interrupt(int irq, void *data)
840 872
841 spin_lock(&sh_chan->desc_lock); 873 spin_lock(&sh_chan->desc_lock);
842 874
843 chcr = sh_dmae_readl(sh_chan, CHCR); 875 chcr = chcr_read(sh_chan);
844 876
845 if (chcr & CHCR_TE) { 877 if (chcr & CHCR_TE) {
846 /* DMA stop */ 878 /* DMA stop */
@@ -1138,6 +1170,16 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
1138 /* platform data */ 1170 /* platform data */
1139 shdev->pdata = pdata; 1171 shdev->pdata = pdata;
1140 1172
1173 if (pdata->chcr_offset)
1174 shdev->chcr_offset = pdata->chcr_offset;
1175 else
1176 shdev->chcr_offset = CHCR;
1177
1178 if (pdata->chcr_ie_bit)
1179 shdev->chcr_ie_bit = pdata->chcr_ie_bit;
1180 else
1181 shdev->chcr_ie_bit = CHCR_IE;
1182
1141 platform_set_drvdata(pdev, shdev); 1183 platform_set_drvdata(pdev, shdev);
1142 1184
1143 pm_runtime_enable(&pdev->dev); 1185 pm_runtime_enable(&pdev->dev);