diff options
Diffstat (limited to 'arch/arm/mach-omap1/dma.c')
-rw-r--r-- | arch/arm/mach-omap1/dma.c | 191 |
1 files changed, 79 insertions, 112 deletions
diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c index 5bb8ce86d54b..4be601b638d7 100644 --- a/arch/arm/mach-omap1/dma.c +++ b/arch/arm/mach-omap1/dma.c | |||
@@ -32,55 +32,51 @@ | |||
32 | 32 | ||
33 | #define OMAP1_DMA_BASE (0xfffed800) | 33 | #define OMAP1_DMA_BASE (0xfffed800) |
34 | #define OMAP1_LOGICAL_DMA_CH_COUNT 17 | 34 | #define OMAP1_LOGICAL_DMA_CH_COUNT 17 |
35 | #define OMAP1_DMA_STRIDE 0x40 | ||
36 | 35 | ||
37 | static u32 errata; | ||
38 | static u32 enable_1510_mode; | 36 | static u32 enable_1510_mode; |
39 | static u8 dma_stride; | 37 | |
40 | static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end; | 38 | static const struct omap_dma_reg reg_map[] = { |
41 | 39 | [GCR] = { 0x0400, 0x00, OMAP_DMA_REG_16BIT }, | |
42 | static u16 reg_map[] = { | 40 | [GSCR] = { 0x0404, 0x00, OMAP_DMA_REG_16BIT }, |
43 | [GCR] = 0x400, | 41 | [GRST1] = { 0x0408, 0x00, OMAP_DMA_REG_16BIT }, |
44 | [GSCR] = 0x404, | 42 | [HW_ID] = { 0x0442, 0x00, OMAP_DMA_REG_16BIT }, |
45 | [GRST1] = 0x408, | 43 | [PCH2_ID] = { 0x0444, 0x00, OMAP_DMA_REG_16BIT }, |
46 | [HW_ID] = 0x442, | 44 | [PCH0_ID] = { 0x0446, 0x00, OMAP_DMA_REG_16BIT }, |
47 | [PCH2_ID] = 0x444, | 45 | [PCH1_ID] = { 0x0448, 0x00, OMAP_DMA_REG_16BIT }, |
48 | [PCH0_ID] = 0x446, | 46 | [PCHG_ID] = { 0x044a, 0x00, OMAP_DMA_REG_16BIT }, |
49 | [PCH1_ID] = 0x448, | 47 | [PCHD_ID] = { 0x044c, 0x00, OMAP_DMA_REG_16BIT }, |
50 | [PCHG_ID] = 0x44a, | 48 | [CAPS_0] = { 0x044e, 0x00, OMAP_DMA_REG_2X16BIT }, |
51 | [PCHD_ID] = 0x44c, | 49 | [CAPS_1] = { 0x0452, 0x00, OMAP_DMA_REG_2X16BIT }, |
52 | [CAPS_0] = 0x44e, | 50 | [CAPS_2] = { 0x0456, 0x00, OMAP_DMA_REG_16BIT }, |
53 | [CAPS_1] = 0x452, | 51 | [CAPS_3] = { 0x0458, 0x00, OMAP_DMA_REG_16BIT }, |
54 | [CAPS_2] = 0x456, | 52 | [CAPS_4] = { 0x045a, 0x00, OMAP_DMA_REG_16BIT }, |
55 | [CAPS_3] = 0x458, | 53 | [PCH2_SR] = { 0x0460, 0x00, OMAP_DMA_REG_16BIT }, |
56 | [CAPS_4] = 0x45a, | 54 | [PCH0_SR] = { 0x0480, 0x00, OMAP_DMA_REG_16BIT }, |
57 | [PCH2_SR] = 0x460, | 55 | [PCH1_SR] = { 0x0482, 0x00, OMAP_DMA_REG_16BIT }, |
58 | [PCH0_SR] = 0x480, | 56 | [PCHD_SR] = { 0x04c0, 0x00, OMAP_DMA_REG_16BIT }, |
59 | [PCH1_SR] = 0x482, | ||
60 | [PCHD_SR] = 0x4c0, | ||
61 | 57 | ||
62 | /* Common Registers */ | 58 | /* Common Registers */ |
63 | [CSDP] = 0x00, | 59 | [CSDP] = { 0x0000, 0x40, OMAP_DMA_REG_16BIT }, |
64 | [CCR] = 0x02, | 60 | [CCR] = { 0x0002, 0x40, OMAP_DMA_REG_16BIT }, |
65 | [CICR] = 0x04, | 61 | [CICR] = { 0x0004, 0x40, OMAP_DMA_REG_16BIT }, |
66 | [CSR] = 0x06, | 62 | [CSR] = { 0x0006, 0x40, OMAP_DMA_REG_16BIT }, |
67 | [CEN] = 0x10, | 63 | [CEN] = { 0x0010, 0x40, OMAP_DMA_REG_16BIT }, |
68 | [CFN] = 0x12, | 64 | [CFN] = { 0x0012, 0x40, OMAP_DMA_REG_16BIT }, |
69 | [CSFI] = 0x14, | 65 | [CSFI] = { 0x0014, 0x40, OMAP_DMA_REG_16BIT }, |
70 | [CSEI] = 0x16, | 66 | [CSEI] = { 0x0016, 0x40, OMAP_DMA_REG_16BIT }, |
71 | [CPC] = 0x18, /* 15xx only */ | 67 | [CPC] = { 0x0018, 0x40, OMAP_DMA_REG_16BIT }, /* 15xx only */ |
72 | [CSAC] = 0x18, | 68 | [CSAC] = { 0x0018, 0x40, OMAP_DMA_REG_16BIT }, |
73 | [CDAC] = 0x1a, | 69 | [CDAC] = { 0x001a, 0x40, OMAP_DMA_REG_16BIT }, |
74 | [CDEI] = 0x1c, | 70 | [CDEI] = { 0x001c, 0x40, OMAP_DMA_REG_16BIT }, |
75 | [CDFI] = 0x1e, | 71 | [CDFI] = { 0x001e, 0x40, OMAP_DMA_REG_16BIT }, |
76 | [CLNK_CTRL] = 0x28, | 72 | [CLNK_CTRL] = { 0x0028, 0x40, OMAP_DMA_REG_16BIT }, |
77 | 73 | ||
78 | /* Channel specific register offsets */ | 74 | /* Channel specific register offsets */ |
79 | [CSSA] = 0x08, | 75 | [CSSA] = { 0x0008, 0x40, OMAP_DMA_REG_2X16BIT }, |
80 | [CDSA] = 0x0c, | 76 | [CDSA] = { 0x000c, 0x40, OMAP_DMA_REG_2X16BIT }, |
81 | [COLOR] = 0x20, | 77 | [COLOR] = { 0x0020, 0x40, OMAP_DMA_REG_2X16BIT }, |
82 | [CCR2] = 0x24, | 78 | [CCR2] = { 0x0024, 0x40, OMAP_DMA_REG_16BIT }, |
83 | [LCH_CTRL] = 0x2a, | 79 | [LCH_CTRL] = { 0x002a, 0x40, OMAP_DMA_REG_16BIT }, |
84 | }; | 80 | }; |
85 | 81 | ||
86 | static struct resource res[] __initdata = { | 82 | static struct resource res[] __initdata = { |
@@ -181,44 +177,36 @@ static struct resource res[] __initdata = { | |||
181 | static void __iomem *dma_base; | 177 | static void __iomem *dma_base; |
182 | static inline void dma_write(u32 val, int reg, int lch) | 178 | static inline void dma_write(u32 val, int reg, int lch) |
183 | { | 179 | { |
184 | u8 stride; | 180 | void __iomem *addr = dma_base; |
185 | u32 offset; | ||
186 | 181 | ||
187 | stride = (reg >= dma_common_ch_start) ? dma_stride : 0; | 182 | addr += reg_map[reg].offset; |
188 | offset = reg_map[reg] + (stride * lch); | 183 | addr += reg_map[reg].stride * lch; |
189 | 184 | ||
190 | __raw_writew(val, dma_base + offset); | 185 | __raw_writew(val, addr); |
191 | if ((reg > CLNK_CTRL && reg < CCEN) || | 186 | if (reg_map[reg].type == OMAP_DMA_REG_2X16BIT) |
192 | (reg > PCHD_ID && reg < CAPS_2)) { | 187 | __raw_writew(val >> 16, addr + 2); |
193 | u32 offset2 = reg_map[reg] + 2 + (stride * lch); | ||
194 | __raw_writew(val >> 16, dma_base + offset2); | ||
195 | } | ||
196 | } | 188 | } |
197 | 189 | ||
198 | static inline u32 dma_read(int reg, int lch) | 190 | static inline u32 dma_read(int reg, int lch) |
199 | { | 191 | { |
200 | u8 stride; | 192 | void __iomem *addr = dma_base; |
201 | u32 offset, val; | 193 | uint32_t val; |
202 | 194 | ||
203 | stride = (reg >= dma_common_ch_start) ? dma_stride : 0; | 195 | addr += reg_map[reg].offset; |
204 | offset = reg_map[reg] + (stride * lch); | 196 | addr += reg_map[reg].stride * lch; |
205 | 197 | ||
206 | val = __raw_readw(dma_base + offset); | 198 | val = __raw_readw(addr); |
207 | if ((reg > CLNK_CTRL && reg < CCEN) || | 199 | if (reg_map[reg].type == OMAP_DMA_REG_2X16BIT) |
208 | (reg > PCHD_ID && reg < CAPS_2)) { | 200 | val |= __raw_readw(addr + 2) << 16; |
209 | u16 upper; | 201 | |
210 | u32 offset2 = reg_map[reg] + 2 + (stride * lch); | ||
211 | upper = __raw_readw(dma_base + offset2); | ||
212 | val |= (upper << 16); | ||
213 | } | ||
214 | return val; | 202 | return val; |
215 | } | 203 | } |
216 | 204 | ||
217 | static void omap1_clear_lch_regs(int lch) | 205 | static void omap1_clear_lch_regs(int lch) |
218 | { | 206 | { |
219 | int i = dma_common_ch_start; | 207 | int i; |
220 | 208 | ||
221 | for (; i <= dma_common_ch_end; i += 1) | 209 | for (i = CPC; i <= COLOR; i += 1) |
222 | dma_write(0, i, lch); | 210 | dma_write(0, i, lch); |
223 | } | 211 | } |
224 | 212 | ||
@@ -255,8 +243,9 @@ static void omap1_show_dma_caps(void) | |||
255 | return; | 243 | return; |
256 | } | 244 | } |
257 | 245 | ||
258 | static u32 configure_dma_errata(void) | 246 | static unsigned configure_dma_errata(void) |
259 | { | 247 | { |
248 | unsigned errata = 0; | ||
260 | 249 | ||
261 | /* | 250 | /* |
262 | * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is | 251 | * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is |
@@ -272,11 +261,23 @@ static const struct platform_device_info omap_dma_dev_info = { | |||
272 | .name = "omap-dma-engine", | 261 | .name = "omap-dma-engine", |
273 | .id = -1, | 262 | .id = -1, |
274 | .dma_mask = DMA_BIT_MASK(32), | 263 | .dma_mask = DMA_BIT_MASK(32), |
264 | .res = res, | ||
265 | .num_res = 1, | ||
266 | }; | ||
267 | |||
268 | static struct omap_system_dma_plat_info dma_plat_info __initdata = { | ||
269 | .reg_map = reg_map, | ||
270 | .channel_stride = 0x40, | ||
271 | .show_dma_caps = omap1_show_dma_caps, | ||
272 | .clear_lch_regs = omap1_clear_lch_regs, | ||
273 | .clear_dma = omap1_clear_dma, | ||
274 | .dma_write = dma_write, | ||
275 | .dma_read = dma_read, | ||
275 | }; | 276 | }; |
276 | 277 | ||
277 | static int __init omap1_system_dma_init(void) | 278 | static int __init omap1_system_dma_init(void) |
278 | { | 279 | { |
279 | struct omap_system_dma_plat_info *p; | 280 | struct omap_system_dma_plat_info p; |
280 | struct omap_dma_dev_attr *d; | 281 | struct omap_dma_dev_attr *d; |
281 | struct platform_device *pdev, *dma_pdev; | 282 | struct platform_device *pdev, *dma_pdev; |
282 | int ret; | 283 | int ret; |
@@ -302,20 +303,12 @@ static int __init omap1_system_dma_init(void) | |||
302 | goto exit_iounmap; | 303 | goto exit_iounmap; |
303 | } | 304 | } |
304 | 305 | ||
305 | p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL); | ||
306 | if (!p) { | ||
307 | dev_err(&pdev->dev, "%s: Unable to allocate 'p' for %s\n", | ||
308 | __func__, pdev->name); | ||
309 | ret = -ENOMEM; | ||
310 | goto exit_iounmap; | ||
311 | } | ||
312 | |||
313 | d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL); | 306 | d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL); |
314 | if (!d) { | 307 | if (!d) { |
315 | dev_err(&pdev->dev, "%s: Unable to allocate 'd' for %s\n", | 308 | dev_err(&pdev->dev, "%s: Unable to allocate 'd' for %s\n", |
316 | __func__, pdev->name); | 309 | __func__, pdev->name); |
317 | ret = -ENOMEM; | 310 | ret = -ENOMEM; |
318 | goto exit_release_p; | 311 | goto exit_iounmap; |
319 | } | 312 | } |
320 | 313 | ||
321 | d->lch_count = OMAP1_LOGICAL_DMA_CH_COUNT; | 314 | d->lch_count = OMAP1_LOGICAL_DMA_CH_COUNT; |
@@ -336,17 +329,6 @@ static int __init omap1_system_dma_init(void) | |||
336 | d->dev_caps |= CLEAR_CSR_ON_READ; | 329 | d->dev_caps |= CLEAR_CSR_ON_READ; |
337 | d->dev_caps |= IS_WORD_16; | 330 | d->dev_caps |= IS_WORD_16; |
338 | 331 | ||
339 | |||
340 | d->chan = kzalloc(sizeof(struct omap_dma_lch) * | ||
341 | (d->lch_count), GFP_KERNEL); | ||
342 | if (!d->chan) { | ||
343 | dev_err(&pdev->dev, | ||
344 | "%s: Memory allocation failed for d->chan!\n", | ||
345 | __func__); | ||
346 | ret = -ENOMEM; | ||
347 | goto exit_release_d; | ||
348 | } | ||
349 | |||
350 | if (cpu_is_omap15xx()) | 332 | if (cpu_is_omap15xx()) |
351 | d->chan_count = 9; | 333 | d->chan_count = 9; |
352 | else if (cpu_is_omap16xx() || cpu_is_omap7xx()) { | 334 | else if (cpu_is_omap16xx() || cpu_is_omap7xx()) { |
@@ -356,35 +338,24 @@ static int __init omap1_system_dma_init(void) | |||
356 | d->chan_count = 9; | 338 | d->chan_count = 9; |
357 | } | 339 | } |
358 | 340 | ||
359 | p->dma_attr = d; | 341 | p = dma_plat_info; |
360 | 342 | p.dma_attr = d; | |
361 | p->show_dma_caps = omap1_show_dma_caps; | 343 | p.errata = configure_dma_errata(); |
362 | p->clear_lch_regs = omap1_clear_lch_regs; | ||
363 | p->clear_dma = omap1_clear_dma; | ||
364 | p->dma_write = dma_write; | ||
365 | p->dma_read = dma_read; | ||
366 | p->disable_irq_lch = NULL; | ||
367 | |||
368 | p->errata = configure_dma_errata(); | ||
369 | 344 | ||
370 | ret = platform_device_add_data(pdev, p, sizeof(*p)); | 345 | ret = platform_device_add_data(pdev, &p, sizeof(p)); |
371 | if (ret) { | 346 | if (ret) { |
372 | dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", | 347 | dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", |
373 | __func__, pdev->name, pdev->id); | 348 | __func__, pdev->name, pdev->id); |
374 | goto exit_release_chan; | 349 | goto exit_release_d; |
375 | } | 350 | } |
376 | 351 | ||
377 | ret = platform_device_add(pdev); | 352 | ret = platform_device_add(pdev); |
378 | if (ret) { | 353 | if (ret) { |
379 | dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", | 354 | dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", |
380 | __func__, pdev->name, pdev->id); | 355 | __func__, pdev->name, pdev->id); |
381 | goto exit_release_chan; | 356 | goto exit_release_d; |
382 | } | 357 | } |
383 | 358 | ||
384 | dma_stride = OMAP1_DMA_STRIDE; | ||
385 | dma_common_ch_start = CPC; | ||
386 | dma_common_ch_end = COLOR; | ||
387 | |||
388 | dma_pdev = platform_device_register_full(&omap_dma_dev_info); | 359 | dma_pdev = platform_device_register_full(&omap_dma_dev_info); |
389 | if (IS_ERR(dma_pdev)) { | 360 | if (IS_ERR(dma_pdev)) { |
390 | ret = PTR_ERR(dma_pdev); | 361 | ret = PTR_ERR(dma_pdev); |
@@ -395,12 +366,8 @@ static int __init omap1_system_dma_init(void) | |||
395 | 366 | ||
396 | exit_release_pdev: | 367 | exit_release_pdev: |
397 | platform_device_del(pdev); | 368 | platform_device_del(pdev); |
398 | exit_release_chan: | ||
399 | kfree(d->chan); | ||
400 | exit_release_d: | 369 | exit_release_d: |
401 | kfree(d); | 370 | kfree(d); |
402 | exit_release_p: | ||
403 | kfree(p); | ||
404 | exit_iounmap: | 371 | exit_iounmap: |
405 | iounmap(dma_base); | 372 | iounmap(dma_base); |
406 | exit_device_put: | 373 | exit_device_put: |