aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2013-12-10 06:08:01 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2014-04-03 19:31:49 -0400
commit596c471b69249764d8e241b004736878204daa0f (patch)
tree9d5b253c7372d0e36965c85617e183418918b4b7
parent34a378fcb9273d73dbd6b209952d2f6bf88a3dd0 (diff)
dmaengine: omap-dma: move register read/writes into omap-dma.c
Export the DMA register information from the SoC specific data, such that we can access the registers directly in omap-dma.c, mapping the register region ourselves as well. Rather than calculating the DMA channel register in its entirety for each access, we pre-calculate an offset base address for the allocated DMA channel and then just use the appropriate register offset. Acked-by: Tony Lindgren <tony@atomide.com> Acked-by: Vinod Koul <vinod.koul@intel.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/mach-omap1/dma.c4
-rw-r--r--arch/arm/mach-omap2/dma.c18
-rw-r--r--drivers/dma/omap-dma.c96
-rw-r--r--include/linux/omap-dma.h2
4 files changed, 105 insertions, 15 deletions
diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index a8c83ccc36fb..4be601b638d7 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -261,9 +261,13 @@ static const struct platform_device_info omap_dma_dev_info = {
261 .name = "omap-dma-engine", 261 .name = "omap-dma-engine",
262 .id = -1, 262 .id = -1,
263 .dma_mask = DMA_BIT_MASK(32), 263 .dma_mask = DMA_BIT_MASK(32),
264 .res = res,
265 .num_res = 1,
264}; 266};
265 267
266static struct omap_system_dma_plat_info dma_plat_info __initdata = { 268static struct omap_system_dma_plat_info dma_plat_info __initdata = {
269 .reg_map = reg_map,
270 .channel_stride = 0x40,
267 .show_dma_caps = omap1_show_dma_caps, 271 .show_dma_caps = omap1_show_dma_caps,
268 .clear_lch_regs = omap1_clear_lch_regs, 272 .clear_lch_regs = omap1_clear_lch_regs,
269 .clear_dma = omap1_clear_dma, 273 .clear_dma = omap1_clear_dma,
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index 6331fc4b4054..5689c88d986d 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -205,12 +205,20 @@ static unsigned configure_dma_errata(void)
205} 205}
206 206
207static struct omap_system_dma_plat_info dma_plat_info __initdata = { 207static struct omap_system_dma_plat_info dma_plat_info __initdata = {
208 .reg_map = reg_map,
209 .channel_stride = 0x60,
208 .show_dma_caps = omap2_show_dma_caps, 210 .show_dma_caps = omap2_show_dma_caps,
209 .clear_dma = omap2_clear_dma, 211 .clear_dma = omap2_clear_dma,
210 .dma_write = dma_write, 212 .dma_write = dma_write,
211 .dma_read = dma_read, 213 .dma_read = dma_read,
212}; 214};
213 215
216static struct platform_device_info omap_dma_dev_info = {
217 .name = "omap-dma-engine",
218 .id = -1,
219 .dma_mask = DMA_BIT_MASK(32),
220};
221
214/* One time initializations */ 222/* One time initializations */
215static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) 223static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
216{ 224{
@@ -231,11 +239,15 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
231 return PTR_ERR(pdev); 239 return PTR_ERR(pdev);
232 } 240 }
233 241
242 omap_dma_dev_info.res = pdev->resource;
243 omap_dma_dev_info.num_res = pdev->num_resources;
244
234 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 245 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
235 if (!mem) { 246 if (!mem) {
236 dev_err(&pdev->dev, "%s: no mem resource\n", __func__); 247 dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
237 return -EINVAL; 248 return -EINVAL;
238 } 249 }
250
239 dma_base = ioremap(mem->start, resource_size(mem)); 251 dma_base = ioremap(mem->start, resource_size(mem));
240 if (!dma_base) { 252 if (!dma_base) {
241 dev_err(&pdev->dev, "%s: ioremap fail\n", __func__); 253 dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
@@ -256,12 +268,6 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused)
256 return 0; 268 return 0;
257} 269}
258 270
259static const struct platform_device_info omap_dma_dev_info = {
260 .name = "omap-dma-engine",
261 .id = -1,
262 .dma_mask = DMA_BIT_MASK(32),
263};
264
265static int __init omap2_system_dma_init(void) 271static int __init omap2_system_dma_init(void)
266{ 272{
267 struct platform_device *pdev; 273 struct platform_device *pdev;
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 1e0018f36384..00f8e566cf12 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -27,13 +27,16 @@ struct omap_dmadev {
27 spinlock_t lock; 27 spinlock_t lock;
28 struct tasklet_struct task; 28 struct tasklet_struct task;
29 struct list_head pending; 29 struct list_head pending;
30 void __iomem *base;
31 const struct omap_dma_reg *reg_map;
30 struct omap_system_dma_plat_info *plat; 32 struct omap_system_dma_plat_info *plat;
31}; 33};
32 34
33struct omap_chan { 35struct omap_chan {
34 struct virt_dma_chan vc; 36 struct virt_dma_chan vc;
35 struct list_head node; 37 struct list_head node;
36 struct omap_system_dma_plat_info *plat; 38 void __iomem *channel_base;
39 const struct omap_dma_reg *reg_map;
37 40
38 struct dma_slave_config cfg; 41 struct dma_slave_config cfg;
39 unsigned dma_sig; 42 unsigned dma_sig;
@@ -170,24 +173,77 @@ static void omap_dma_desc_free(struct virt_dma_desc *vd)
170 kfree(container_of(vd, struct omap_desc, vd)); 173 kfree(container_of(vd, struct omap_desc, vd));
171} 174}
172 175
176static void omap_dma_write(uint32_t val, unsigned type, void __iomem *addr)
177{
178 switch (type) {
179 case OMAP_DMA_REG_16BIT:
180 writew_relaxed(val, addr);
181 break;
182 case OMAP_DMA_REG_2X16BIT:
183 writew_relaxed(val, addr);
184 writew_relaxed(val >> 16, addr + 2);
185 break;
186 case OMAP_DMA_REG_32BIT:
187 writel_relaxed(val, addr);
188 break;
189 default:
190 WARN_ON(1);
191 }
192}
193
194static unsigned omap_dma_read(unsigned type, void __iomem *addr)
195{
196 unsigned val;
197
198 switch (type) {
199 case OMAP_DMA_REG_16BIT:
200 val = readw_relaxed(addr);
201 break;
202 case OMAP_DMA_REG_2X16BIT:
203 val = readw_relaxed(addr);
204 val |= readw_relaxed(addr + 2) << 16;
205 break;
206 case OMAP_DMA_REG_32BIT:
207 val = readl_relaxed(addr);
208 break;
209 default:
210 WARN_ON(1);
211 val = 0;
212 }
213
214 return val;
215}
216
173static void omap_dma_glbl_write(struct omap_dmadev *od, unsigned reg, unsigned val) 217static void omap_dma_glbl_write(struct omap_dmadev *od, unsigned reg, unsigned val)
174{ 218{
175 od->plat->dma_write(val, reg, 0); 219 const struct omap_dma_reg *r = od->reg_map + reg;
220
221 WARN_ON(r->stride);
222
223 omap_dma_write(val, r->type, od->base + r->offset);
176} 224}
177 225
178static unsigned omap_dma_glbl_read(struct omap_dmadev *od, unsigned reg) 226static unsigned omap_dma_glbl_read(struct omap_dmadev *od, unsigned reg)
179{ 227{
180 return od->plat->dma_read(reg, 0); 228 const struct omap_dma_reg *r = od->reg_map + reg;
229
230 WARN_ON(r->stride);
231
232 return omap_dma_read(r->type, od->base + r->offset);
181} 233}
182 234
183static void omap_dma_chan_write(struct omap_chan *c, unsigned reg, unsigned val) 235static void omap_dma_chan_write(struct omap_chan *c, unsigned reg, unsigned val)
184{ 236{
185 c->plat->dma_write(val, reg, c->dma_ch); 237 const struct omap_dma_reg *r = c->reg_map + reg;
238
239 omap_dma_write(val, r->type, c->channel_base + r->offset);
186} 240}
187 241
188static unsigned omap_dma_chan_read(struct omap_chan *c, unsigned reg) 242static unsigned omap_dma_chan_read(struct omap_chan *c, unsigned reg)
189{ 243{
190 return c->plat->dma_read(reg, c->dma_ch); 244 const struct omap_dma_reg *r = c->reg_map + reg;
245
246 return omap_dma_read(r->type, c->channel_base + r->offset);
191} 247}
192 248
193static void omap_dma_clear_csr(struct omap_chan *c) 249static void omap_dma_clear_csr(struct omap_chan *c)
@@ -198,6 +254,12 @@ static void omap_dma_clear_csr(struct omap_chan *c)
198 omap_dma_chan_write(c, CSR, ~0); 254 omap_dma_chan_write(c, CSR, ~0);
199} 255}
200 256
257static void omap_dma_assign(struct omap_dmadev *od, struct omap_chan *c,
258 unsigned lch)
259{
260 c->channel_base = od->base + od->plat->channel_stride * lch;
261}
262
201static void omap_dma_start(struct omap_chan *c, struct omap_desc *d) 263static void omap_dma_start(struct omap_chan *c, struct omap_desc *d)
202{ 264{
203 struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); 265 struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device);
@@ -400,18 +462,26 @@ static void omap_dma_sched(unsigned long data)
400 462
401static int omap_dma_alloc_chan_resources(struct dma_chan *chan) 463static int omap_dma_alloc_chan_resources(struct dma_chan *chan)
402{ 464{
465 struct omap_dmadev *od = to_omap_dma_dev(chan->device);
403 struct omap_chan *c = to_omap_dma_chan(chan); 466 struct omap_chan *c = to_omap_dma_chan(chan);
467 int ret;
468
469 dev_dbg(od->ddev.dev, "allocating channel for %u\n", c->dma_sig);
404 470
405 dev_dbg(c->vc.chan.device->dev, "allocating channel for %u\n", c->dma_sig); 471 ret = omap_request_dma(c->dma_sig, "DMA engine", omap_dma_callback,
472 c, &c->dma_ch);
406 473
407 return omap_request_dma(c->dma_sig, "DMA engine", 474 if (ret >= 0)
408 omap_dma_callback, c, &c->dma_ch); 475 omap_dma_assign(od, c, c->dma_ch);
476
477 return ret;
409} 478}
410 479
411static void omap_dma_free_chan_resources(struct dma_chan *chan) 480static void omap_dma_free_chan_resources(struct dma_chan *chan)
412{ 481{
413 struct omap_chan *c = to_omap_dma_chan(chan); 482 struct omap_chan *c = to_omap_dma_chan(chan);
414 483
484 c->channel_base = NULL;
415 vchan_free_chan_resources(&c->vc); 485 vchan_free_chan_resources(&c->vc);
416 omap_free_dma(c->dma_ch); 486 omap_free_dma(c->dma_ch);
417 487
@@ -917,7 +987,7 @@ static int omap_dma_chan_init(struct omap_dmadev *od, int dma_sig)
917 if (!c) 987 if (!c)
918 return -ENOMEM; 988 return -ENOMEM;
919 989
920 c->plat = od->plat; 990 c->reg_map = od->reg_map;
921 c->dma_sig = dma_sig; 991 c->dma_sig = dma_sig;
922 c->vc.desc_free = omap_dma_desc_free; 992 c->vc.desc_free = omap_dma_desc_free;
923 vchan_init(&c->vc, &od->ddev); 993 vchan_init(&c->vc, &od->ddev);
@@ -944,16 +1014,24 @@ static void omap_dma_free(struct omap_dmadev *od)
944static int omap_dma_probe(struct platform_device *pdev) 1014static int omap_dma_probe(struct platform_device *pdev)
945{ 1015{
946 struct omap_dmadev *od; 1016 struct omap_dmadev *od;
1017 struct resource *res;
947 int rc, i; 1018 int rc, i;
948 1019
949 od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL); 1020 od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL);
950 if (!od) 1021 if (!od)
951 return -ENOMEM; 1022 return -ENOMEM;
952 1023
1024 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1025 od->base = devm_ioremap_resource(&pdev->dev, res);
1026 if (IS_ERR(od->base))
1027 return PTR_ERR(od->base);
1028
953 od->plat = omap_get_plat_info(); 1029 od->plat = omap_get_plat_info();
954 if (!od->plat) 1030 if (!od->plat)
955 return -EPROBE_DEFER; 1031 return -EPROBE_DEFER;
956 1032
1033 od->reg_map = od->plat->reg_map;
1034
957 dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); 1035 dma_cap_set(DMA_SLAVE, od->ddev.cap_mask);
958 dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); 1036 dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask);
959 od->ddev.device_alloc_chan_resources = omap_dma_alloc_chan_resources; 1037 od->ddev.device_alloc_chan_resources = omap_dma_alloc_chan_resources;
diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h
index 7813636a193d..41a13e70f41f 100644
--- a/include/linux/omap-dma.h
+++ b/include/linux/omap-dma.h
@@ -285,6 +285,8 @@ struct omap_dma_reg {
285 285
286/* System DMA platform data structure */ 286/* System DMA platform data structure */
287struct omap_system_dma_plat_info { 287struct omap_system_dma_plat_info {
288 const struct omap_dma_reg *reg_map;
289 unsigned channel_stride;
288 struct omap_dma_dev_attr *dma_attr; 290 struct omap_dma_dev_attr *dma_attr;
289 u32 errata; 291 u32 errata;
290 void (*show_dma_caps)(void); 292 void (*show_dma_caps)(void);