diff options
Diffstat (limited to 'drivers/dma/shdma.c')
-rw-r--r-- | drivers/dma/shdma.c | 66 |
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 | ||
71 | static u16 dmaor_read(struct sh_dmae_device *shdev) | 71 | static 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 | ||
76 | static void dmaor_write(struct sh_dmae_device *shdev, u16 data) | 81 | static 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 | |||
91 | static 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 | |||
98 | static 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 | ||
121 | static bool dmae_is_busy(struct sh_dmae_chan *sh_chan) | 145 | static 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 | ||
168 | static void dmae_start(struct sh_dmae_chan *sh_chan) | 192 | static 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 | ||
176 | static void dmae_halt(struct sh_dmae_chan *sh_chan) | 204 | static 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 | ||
184 | static void dmae_init(struct sh_dmae_chan *sh_chan) | 213 | static 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 | ||
196 | static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val) | 225 | static 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); |