diff options
author | Tong Liu <tong.liu@stericsson.com> | 2012-09-26 06:07:30 -0400 |
---|---|---|
committer | Fabio Baltieri <fabio.baltieri@linaro.org> | 2013-01-14 04:50:48 -0500 |
commit | 3cb645dc85a050c8a6b5c2cbdcbe4b8f39dba1b8 (patch) | |
tree | 9031f1a3af3f74492e94ff057a50785c9ddc103b /drivers/dma | |
parent | 47db92f4a63499b1605b4c66f9347ba5479e7b19 (diff) |
dmaengine: ste_dma40: support more than 128 event lines
U8540 DMA controller is different from u9540 we need define new
registers and use them to support handling more than 128 event lines.
Signed-off-by: Tong Liu <tong.liu@stericsson.com>
Reviewed-by: Per Forlin <per.forlin@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/ste_dma40.c | 306 | ||||
-rw-r--r-- | drivers/dma/ste_dma40_ll.h | 130 |
2 files changed, 355 insertions, 81 deletions
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index ca18117def0a..67e565bffe16 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c | |||
@@ -53,6 +53,8 @@ | |||
53 | #define D40_ALLOC_PHY (1 << 30) | 53 | #define D40_ALLOC_PHY (1 << 30) |
54 | #define D40_ALLOC_LOG_FREE 0 | 54 | #define D40_ALLOC_LOG_FREE 0 |
55 | 55 | ||
56 | #define MAX(a, b) (((a) < (b)) ? (b) : (a)) | ||
57 | |||
56 | /** | 58 | /** |
57 | * enum 40_command - The different commands and/or statuses. | 59 | * enum 40_command - The different commands and/or statuses. |
58 | * | 60 | * |
@@ -100,8 +102,19 @@ static u32 d40_backup_regs[] = { | |||
100 | 102 | ||
101 | #define BACKUP_REGS_SZ ARRAY_SIZE(d40_backup_regs) | 103 | #define BACKUP_REGS_SZ ARRAY_SIZE(d40_backup_regs) |
102 | 104 | ||
103 | /* TODO: Check if all these registers have to be saved/restored on dma40 v3 */ | 105 | /* |
104 | static u32 d40_backup_regs_v3[] = { | 106 | * since 9540 and 8540 has the same HW revision |
107 | * use v4a for 9540 or ealier | ||
108 | * use v4b for 8540 or later | ||
109 | * HW revision: | ||
110 | * DB8500ed has revision 0 | ||
111 | * DB8500v1 has revision 2 | ||
112 | * DB8500v2 has revision 3 | ||
113 | * AP9540v1 has revision 4 | ||
114 | * DB8540v1 has revision 4 | ||
115 | * TODO: Check if all these registers have to be saved/restored on dma40 v4a | ||
116 | */ | ||
117 | static u32 d40_backup_regs_v4a[] = { | ||
105 | D40_DREG_PSEG1, | 118 | D40_DREG_PSEG1, |
106 | D40_DREG_PSEG2, | 119 | D40_DREG_PSEG2, |
107 | D40_DREG_PSEG3, | 120 | D40_DREG_PSEG3, |
@@ -120,7 +133,32 @@ static u32 d40_backup_regs_v3[] = { | |||
120 | D40_DREG_RCEG4, | 133 | D40_DREG_RCEG4, |
121 | }; | 134 | }; |
122 | 135 | ||
123 | #define BACKUP_REGS_SZ_V3 ARRAY_SIZE(d40_backup_regs_v3) | 136 | #define BACKUP_REGS_SZ_V4A ARRAY_SIZE(d40_backup_regs_v4a) |
137 | |||
138 | static u32 d40_backup_regs_v4b[] = { | ||
139 | D40_DREG_CPSEG1, | ||
140 | D40_DREG_CPSEG2, | ||
141 | D40_DREG_CPSEG3, | ||
142 | D40_DREG_CPSEG4, | ||
143 | D40_DREG_CPSEG5, | ||
144 | D40_DREG_CPCEG1, | ||
145 | D40_DREG_CPCEG2, | ||
146 | D40_DREG_CPCEG3, | ||
147 | D40_DREG_CPCEG4, | ||
148 | D40_DREG_CPCEG5, | ||
149 | D40_DREG_CRSEG1, | ||
150 | D40_DREG_CRSEG2, | ||
151 | D40_DREG_CRSEG3, | ||
152 | D40_DREG_CRSEG4, | ||
153 | D40_DREG_CRSEG5, | ||
154 | D40_DREG_CRCEG1, | ||
155 | D40_DREG_CRCEG2, | ||
156 | D40_DREG_CRCEG3, | ||
157 | D40_DREG_CRCEG4, | ||
158 | D40_DREG_CRCEG5, | ||
159 | }; | ||
160 | |||
161 | #define BACKUP_REGS_SZ_V4B ARRAY_SIZE(d40_backup_regs_v4b) | ||
124 | 162 | ||
125 | static u32 d40_backup_regs_chan[] = { | 163 | static u32 d40_backup_regs_chan[] = { |
126 | D40_CHAN_REG_SSCFG, | 164 | D40_CHAN_REG_SSCFG, |
@@ -134,6 +172,102 @@ static u32 d40_backup_regs_chan[] = { | |||
134 | }; | 172 | }; |
135 | 173 | ||
136 | /** | 174 | /** |
175 | * struct d40_interrupt_lookup - lookup table for interrupt handler | ||
176 | * | ||
177 | * @src: Interrupt mask register. | ||
178 | * @clr: Interrupt clear register. | ||
179 | * @is_error: true if this is an error interrupt. | ||
180 | * @offset: start delta in the lookup_log_chans in d40_base. If equals to | ||
181 | * D40_PHY_CHAN, the lookup_phy_chans shall be used instead. | ||
182 | */ | ||
183 | struct d40_interrupt_lookup { | ||
184 | u32 src; | ||
185 | u32 clr; | ||
186 | bool is_error; | ||
187 | int offset; | ||
188 | }; | ||
189 | |||
190 | |||
191 | static struct d40_interrupt_lookup il_v4a[] = { | ||
192 | {D40_DREG_LCTIS0, D40_DREG_LCICR0, false, 0}, | ||
193 | {D40_DREG_LCTIS1, D40_DREG_LCICR1, false, 32}, | ||
194 | {D40_DREG_LCTIS2, D40_DREG_LCICR2, false, 64}, | ||
195 | {D40_DREG_LCTIS3, D40_DREG_LCICR3, false, 96}, | ||
196 | {D40_DREG_LCEIS0, D40_DREG_LCICR0, true, 0}, | ||
197 | {D40_DREG_LCEIS1, D40_DREG_LCICR1, true, 32}, | ||
198 | {D40_DREG_LCEIS2, D40_DREG_LCICR2, true, 64}, | ||
199 | {D40_DREG_LCEIS3, D40_DREG_LCICR3, true, 96}, | ||
200 | {D40_DREG_PCTIS, D40_DREG_PCICR, false, D40_PHY_CHAN}, | ||
201 | {D40_DREG_PCEIS, D40_DREG_PCICR, true, D40_PHY_CHAN}, | ||
202 | }; | ||
203 | |||
204 | static struct d40_interrupt_lookup il_v4b[] = { | ||
205 | {D40_DREG_CLCTIS1, D40_DREG_CLCICR1, false, 0}, | ||
206 | {D40_DREG_CLCTIS2, D40_DREG_CLCICR2, false, 32}, | ||
207 | {D40_DREG_CLCTIS3, D40_DREG_CLCICR3, false, 64}, | ||
208 | {D40_DREG_CLCTIS4, D40_DREG_CLCICR4, false, 96}, | ||
209 | {D40_DREG_CLCTIS5, D40_DREG_CLCICR5, false, 128}, | ||
210 | {D40_DREG_CLCEIS1, D40_DREG_CLCICR1, true, 0}, | ||
211 | {D40_DREG_CLCEIS2, D40_DREG_CLCICR2, true, 32}, | ||
212 | {D40_DREG_CLCEIS3, D40_DREG_CLCICR3, true, 64}, | ||
213 | {D40_DREG_CLCEIS4, D40_DREG_CLCICR4, true, 96}, | ||
214 | {D40_DREG_CLCEIS5, D40_DREG_CLCICR5, true, 128}, | ||
215 | {D40_DREG_CPCTIS, D40_DREG_CPCICR, false, D40_PHY_CHAN}, | ||
216 | {D40_DREG_CPCEIS, D40_DREG_CPCICR, true, D40_PHY_CHAN}, | ||
217 | }; | ||
218 | |||
219 | /** | ||
220 | * struct d40_reg_val - simple lookup struct | ||
221 | * | ||
222 | * @reg: The register. | ||
223 | * @val: The value that belongs to the register in reg. | ||
224 | */ | ||
225 | struct d40_reg_val { | ||
226 | unsigned int reg; | ||
227 | unsigned int val; | ||
228 | }; | ||
229 | |||
230 | static __initdata struct d40_reg_val dma_init_reg_v4a[] = { | ||
231 | /* Clock every part of the DMA block from start */ | ||
232 | { .reg = D40_DREG_GCC, .val = D40_DREG_GCC_ENABLE_ALL}, | ||
233 | |||
234 | /* Interrupts on all logical channels */ | ||
235 | { .reg = D40_DREG_LCMIS0, .val = 0xFFFFFFFF}, | ||
236 | { .reg = D40_DREG_LCMIS1, .val = 0xFFFFFFFF}, | ||
237 | { .reg = D40_DREG_LCMIS2, .val = 0xFFFFFFFF}, | ||
238 | { .reg = D40_DREG_LCMIS3, .val = 0xFFFFFFFF}, | ||
239 | { .reg = D40_DREG_LCICR0, .val = 0xFFFFFFFF}, | ||
240 | { .reg = D40_DREG_LCICR1, .val = 0xFFFFFFFF}, | ||
241 | { .reg = D40_DREG_LCICR2, .val = 0xFFFFFFFF}, | ||
242 | { .reg = D40_DREG_LCICR3, .val = 0xFFFFFFFF}, | ||
243 | { .reg = D40_DREG_LCTIS0, .val = 0xFFFFFFFF}, | ||
244 | { .reg = D40_DREG_LCTIS1, .val = 0xFFFFFFFF}, | ||
245 | { .reg = D40_DREG_LCTIS2, .val = 0xFFFFFFFF}, | ||
246 | { .reg = D40_DREG_LCTIS3, .val = 0xFFFFFFFF} | ||
247 | }; | ||
248 | static __initdata struct d40_reg_val dma_init_reg_v4b[] = { | ||
249 | /* Clock every part of the DMA block from start */ | ||
250 | { .reg = D40_DREG_GCC, .val = D40_DREG_GCC_ENABLE_ALL}, | ||
251 | |||
252 | /* Interrupts on all logical channels */ | ||
253 | { .reg = D40_DREG_CLCMIS1, .val = 0xFFFFFFFF}, | ||
254 | { .reg = D40_DREG_CLCMIS2, .val = 0xFFFFFFFF}, | ||
255 | { .reg = D40_DREG_CLCMIS3, .val = 0xFFFFFFFF}, | ||
256 | { .reg = D40_DREG_CLCMIS4, .val = 0xFFFFFFFF}, | ||
257 | { .reg = D40_DREG_CLCMIS5, .val = 0xFFFFFFFF}, | ||
258 | { .reg = D40_DREG_CLCICR1, .val = 0xFFFFFFFF}, | ||
259 | { .reg = D40_DREG_CLCICR2, .val = 0xFFFFFFFF}, | ||
260 | { .reg = D40_DREG_CLCICR3, .val = 0xFFFFFFFF}, | ||
261 | { .reg = D40_DREG_CLCICR4, .val = 0xFFFFFFFF}, | ||
262 | { .reg = D40_DREG_CLCICR5, .val = 0xFFFFFFFF}, | ||
263 | { .reg = D40_DREG_CLCTIS1, .val = 0xFFFFFFFF}, | ||
264 | { .reg = D40_DREG_CLCTIS2, .val = 0xFFFFFFFF}, | ||
265 | { .reg = D40_DREG_CLCTIS3, .val = 0xFFFFFFFF}, | ||
266 | { .reg = D40_DREG_CLCTIS4, .val = 0xFFFFFFFF}, | ||
267 | { .reg = D40_DREG_CLCTIS5, .val = 0xFFFFFFFF} | ||
268 | }; | ||
269 | |||
270 | /** | ||
137 | * struct d40_lli_pool - Structure for keeping LLIs in memory | 271 | * struct d40_lli_pool - Structure for keeping LLIs in memory |
138 | * | 272 | * |
139 | * @base: Pointer to memory area when the pre_alloc_lli's are not large | 273 | * @base: Pointer to memory area when the pre_alloc_lli's are not large |
@@ -289,6 +423,38 @@ struct d40_chan { | |||
289 | }; | 423 | }; |
290 | 424 | ||
291 | /** | 425 | /** |
426 | * struct d40_gen_dmac - generic values to represent u8500/u8540 DMA | ||
427 | * controller | ||
428 | * | ||
429 | * @backup: the pointer to the registers address array for backup | ||
430 | * @backup_size: the size of the registers address array for backup | ||
431 | * @realtime_en: the realtime enable register | ||
432 | * @realtime_clear: the realtime clear register | ||
433 | * @high_prio_en: the high priority enable register | ||
434 | * @high_prio_clear: the high priority clear register | ||
435 | * @interrupt_en: the interrupt enable register | ||
436 | * @interrupt_clear: the interrupt clear register | ||
437 | * @il: the pointer to struct d40_interrupt_lookup | ||
438 | * @il_size: the size of d40_interrupt_lookup array | ||
439 | * @init_reg: the pointer to the struct d40_reg_val | ||
440 | * @init_reg_size: the size of d40_reg_val array | ||
441 | */ | ||
442 | struct d40_gen_dmac { | ||
443 | u32 *backup; | ||
444 | u32 backup_size; | ||
445 | u32 realtime_en; | ||
446 | u32 realtime_clear; | ||
447 | u32 high_prio_en; | ||
448 | u32 high_prio_clear; | ||
449 | u32 interrupt_en; | ||
450 | u32 interrupt_clear; | ||
451 | struct d40_interrupt_lookup *il; | ||
452 | u32 il_size; | ||
453 | struct d40_reg_val *init_reg; | ||
454 | u32 init_reg_size; | ||
455 | }; | ||
456 | |||
457 | /** | ||
292 | * struct d40_base - The big global struct, one for each probe'd instance. | 458 | * struct d40_base - The big global struct, one for each probe'd instance. |
293 | * | 459 | * |
294 | * @interrupt_lock: Lock used to make sure one interrupt is handle a time. | 460 | * @interrupt_lock: Lock used to make sure one interrupt is handle a time. |
@@ -326,11 +492,13 @@ struct d40_chan { | |||
326 | * @desc_slab: cache for descriptors. | 492 | * @desc_slab: cache for descriptors. |
327 | * @reg_val_backup: Here the values of some hardware registers are stored | 493 | * @reg_val_backup: Here the values of some hardware registers are stored |
328 | * before the DMA is powered off. They are restored when the power is back on. | 494 | * before the DMA is powered off. They are restored when the power is back on. |
329 | * @reg_val_backup_v3: Backup of registers that only exits on dma40 v3 and | 495 | * @reg_val_backup_v4: Backup of registers that only exits on dma40 v3 and |
330 | * later. | 496 | * later |
331 | * @reg_val_backup_chan: Backup data for standard channel parameter registers. | 497 | * @reg_val_backup_chan: Backup data for standard channel parameter registers. |
332 | * @gcc_pwr_off_mask: Mask to maintain the channels that can be turned off. | 498 | * @gcc_pwr_off_mask: Mask to maintain the channels that can be turned off. |
333 | * @initialized: true if the dma has been initialized | 499 | * @initialized: true if the dma has been initialized |
500 | * @gen_dmac: the struct for generic registers values to represent u8500/8540 | ||
501 | * DMA controller | ||
334 | */ | 502 | */ |
335 | struct d40_base { | 503 | struct d40_base { |
336 | spinlock_t interrupt_lock; | 504 | spinlock_t interrupt_lock; |
@@ -362,37 +530,11 @@ struct d40_base { | |||
362 | resource_size_t lcpa_size; | 530 | resource_size_t lcpa_size; |
363 | struct kmem_cache *desc_slab; | 531 | struct kmem_cache *desc_slab; |
364 | u32 reg_val_backup[BACKUP_REGS_SZ]; | 532 | u32 reg_val_backup[BACKUP_REGS_SZ]; |
365 | u32 reg_val_backup_v3[BACKUP_REGS_SZ_V3]; | 533 | u32 reg_val_backup_v4[MAX(BACKUP_REGS_SZ_V4A, BACKUP_REGS_SZ_V4B)]; |
366 | u32 *reg_val_backup_chan; | 534 | u32 *reg_val_backup_chan; |
367 | u16 gcc_pwr_off_mask; | 535 | u16 gcc_pwr_off_mask; |
368 | bool initialized; | 536 | bool initialized; |
369 | }; | 537 | struct d40_gen_dmac gen_dmac; |
370 | |||
371 | /** | ||
372 | * struct d40_interrupt_lookup - lookup table for interrupt handler | ||
373 | * | ||
374 | * @src: Interrupt mask register. | ||
375 | * @clr: Interrupt clear register. | ||
376 | * @is_error: true if this is an error interrupt. | ||
377 | * @offset: start delta in the lookup_log_chans in d40_base. If equals to | ||
378 | * D40_PHY_CHAN, the lookup_phy_chans shall be used instead. | ||
379 | */ | ||
380 | struct d40_interrupt_lookup { | ||
381 | u32 src; | ||
382 | u32 clr; | ||
383 | bool is_error; | ||
384 | int offset; | ||
385 | }; | ||
386 | |||
387 | /** | ||
388 | * struct d40_reg_val - simple lookup struct | ||
389 | * | ||
390 | * @reg: The register. | ||
391 | * @val: The value that belongs to the register in reg. | ||
392 | */ | ||
393 | struct d40_reg_val { | ||
394 | unsigned int reg; | ||
395 | unsigned int val; | ||
396 | }; | 538 | }; |
397 | 539 | ||
398 | static struct device *chan2dev(struct d40_chan *d40c) | 540 | static struct device *chan2dev(struct d40_chan *d40c) |
@@ -875,11 +1017,11 @@ static void d40_save_restore_registers(struct d40_base *base, bool save) | |||
875 | save); | 1017 | save); |
876 | 1018 | ||
877 | /* Save/Restore registers only existing on dma40 v3 and later */ | 1019 | /* Save/Restore registers only existing on dma40 v3 and later */ |
878 | if (base->rev >= 3) | 1020 | if (base->gen_dmac.backup) |
879 | dma40_backup(base->virtbase, base->reg_val_backup_v3, | 1021 | dma40_backup(base->virtbase, base->reg_val_backup_v4, |
880 | d40_backup_regs_v3, | 1022 | base->gen_dmac.backup, |
881 | ARRAY_SIZE(d40_backup_regs_v3), | 1023 | base->gen_dmac.backup_size, |
882 | save); | 1024 | save); |
883 | } | 1025 | } |
884 | #else | 1026 | #else |
885 | static void d40_save_restore_registers(struct d40_base *base, bool save) | 1027 | static void d40_save_restore_registers(struct d40_base *base, bool save) |
@@ -1470,41 +1612,30 @@ err: | |||
1470 | 1612 | ||
1471 | static irqreturn_t d40_handle_interrupt(int irq, void *data) | 1613 | static irqreturn_t d40_handle_interrupt(int irq, void *data) |
1472 | { | 1614 | { |
1473 | static const struct d40_interrupt_lookup il[] = { | ||
1474 | {D40_DREG_LCTIS0, D40_DREG_LCICR0, false, 0}, | ||
1475 | {D40_DREG_LCTIS1, D40_DREG_LCICR1, false, 32}, | ||
1476 | {D40_DREG_LCTIS2, D40_DREG_LCICR2, false, 64}, | ||
1477 | {D40_DREG_LCTIS3, D40_DREG_LCICR3, false, 96}, | ||
1478 | {D40_DREG_LCEIS0, D40_DREG_LCICR0, true, 0}, | ||
1479 | {D40_DREG_LCEIS1, D40_DREG_LCICR1, true, 32}, | ||
1480 | {D40_DREG_LCEIS2, D40_DREG_LCICR2, true, 64}, | ||
1481 | {D40_DREG_LCEIS3, D40_DREG_LCICR3, true, 96}, | ||
1482 | {D40_DREG_PCTIS, D40_DREG_PCICR, false, D40_PHY_CHAN}, | ||
1483 | {D40_DREG_PCEIS, D40_DREG_PCICR, true, D40_PHY_CHAN}, | ||
1484 | }; | ||
1485 | |||
1486 | int i; | 1615 | int i; |
1487 | u32 regs[ARRAY_SIZE(il)]; | ||
1488 | u32 idx; | 1616 | u32 idx; |
1489 | u32 row; | 1617 | u32 row; |
1490 | long chan = -1; | 1618 | long chan = -1; |
1491 | struct d40_chan *d40c; | 1619 | struct d40_chan *d40c; |
1492 | unsigned long flags; | 1620 | unsigned long flags; |
1493 | struct d40_base *base = data; | 1621 | struct d40_base *base = data; |
1622 | u32 regs[base->gen_dmac.il_size]; | ||
1623 | struct d40_interrupt_lookup *il = base->gen_dmac.il; | ||
1624 | u32 il_size = base->gen_dmac.il_size; | ||
1494 | 1625 | ||
1495 | spin_lock_irqsave(&base->interrupt_lock, flags); | 1626 | spin_lock_irqsave(&base->interrupt_lock, flags); |
1496 | 1627 | ||
1497 | /* Read interrupt status of both logical and physical channels */ | 1628 | /* Read interrupt status of both logical and physical channels */ |
1498 | for (i = 0; i < ARRAY_SIZE(il); i++) | 1629 | for (i = 0; i < il_size; i++) |
1499 | regs[i] = readl(base->virtbase + il[i].src); | 1630 | regs[i] = readl(base->virtbase + il[i].src); |
1500 | 1631 | ||
1501 | for (;;) { | 1632 | for (;;) { |
1502 | 1633 | ||
1503 | chan = find_next_bit((unsigned long *)regs, | 1634 | chan = find_next_bit((unsigned long *)regs, |
1504 | BITS_PER_LONG * ARRAY_SIZE(il), chan + 1); | 1635 | BITS_PER_LONG * il_size, chan + 1); |
1505 | 1636 | ||
1506 | /* No more set bits found? */ | 1637 | /* No more set bits found? */ |
1507 | if (chan == BITS_PER_LONG * ARRAY_SIZE(il)) | 1638 | if (chan == BITS_PER_LONG * il_size) |
1508 | break; | 1639 | break; |
1509 | 1640 | ||
1510 | row = chan / BITS_PER_LONG; | 1641 | row = chan / BITS_PER_LONG; |
@@ -2189,12 +2320,14 @@ static void __d40_set_prio_rt(struct d40_chan *d40c, int dev_type, bool src) | |||
2189 | { | 2320 | { |
2190 | bool realtime = d40c->dma_cfg.realtime; | 2321 | bool realtime = d40c->dma_cfg.realtime; |
2191 | bool highprio = d40c->dma_cfg.high_priority; | 2322 | bool highprio = d40c->dma_cfg.high_priority; |
2192 | u32 rtreg = realtime ? D40_DREG_RSEG1 : D40_DREG_RCEG1; | 2323 | u32 rtreg; |
2193 | u32 event = D40_TYPE_TO_EVENT(dev_type); | 2324 | u32 event = D40_TYPE_TO_EVENT(dev_type); |
2194 | u32 group = D40_TYPE_TO_GROUP(dev_type); | 2325 | u32 group = D40_TYPE_TO_GROUP(dev_type); |
2195 | u32 bit = 1 << event; | 2326 | u32 bit = 1 << event; |
2196 | u32 prioreg; | 2327 | u32 prioreg; |
2328 | struct d40_gen_dmac *dmac = &d40c->base->gen_dmac; | ||
2197 | 2329 | ||
2330 | rtreg = realtime ? dmac->realtime_en : dmac->realtime_clear; | ||
2198 | /* | 2331 | /* |
2199 | * Due to a hardware bug, in some cases a logical channel triggered by | 2332 | * Due to a hardware bug, in some cases a logical channel triggered by |
2200 | * a high priority destination event line can generate extra packet | 2333 | * a high priority destination event line can generate extra packet |
@@ -2206,7 +2339,7 @@ static void __d40_set_prio_rt(struct d40_chan *d40c, int dev_type, bool src) | |||
2206 | if (!src && chan_is_logical(d40c)) | 2339 | if (!src && chan_is_logical(d40c)) |
2207 | highprio = false; | 2340 | highprio = false; |
2208 | 2341 | ||
2209 | prioreg = highprio ? D40_DREG_PSEG1 : D40_DREG_PCEG1; | 2342 | prioreg = highprio ? dmac->high_prio_en : dmac->high_prio_clear; |
2210 | 2343 | ||
2211 | /* Destination event lines are stored in the upper halfword */ | 2344 | /* Destination event lines are stored in the upper halfword */ |
2212 | if (!src) | 2345 | if (!src) |
@@ -3056,6 +3189,36 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) | |||
3056 | base->phy_chans = ((void *)base) + ALIGN(sizeof(struct d40_base), 4); | 3189 | base->phy_chans = ((void *)base) + ALIGN(sizeof(struct d40_base), 4); |
3057 | base->log_chans = &base->phy_chans[num_phy_chans]; | 3190 | base->log_chans = &base->phy_chans[num_phy_chans]; |
3058 | 3191 | ||
3192 | if (base->plat_data->num_of_phy_chans == 14) { | ||
3193 | base->gen_dmac.backup = d40_backup_regs_v4b; | ||
3194 | base->gen_dmac.backup_size = BACKUP_REGS_SZ_V4B; | ||
3195 | base->gen_dmac.interrupt_en = D40_DREG_CPCMIS; | ||
3196 | base->gen_dmac.interrupt_clear = D40_DREG_CPCICR; | ||
3197 | base->gen_dmac.realtime_en = D40_DREG_CRSEG1; | ||
3198 | base->gen_dmac.realtime_clear = D40_DREG_CRCEG1; | ||
3199 | base->gen_dmac.high_prio_en = D40_DREG_CPSEG1; | ||
3200 | base->gen_dmac.high_prio_clear = D40_DREG_CPCEG1; | ||
3201 | base->gen_dmac.il = il_v4b; | ||
3202 | base->gen_dmac.il_size = ARRAY_SIZE(il_v4b); | ||
3203 | base->gen_dmac.init_reg = dma_init_reg_v4b; | ||
3204 | base->gen_dmac.init_reg_size = ARRAY_SIZE(dma_init_reg_v4b); | ||
3205 | } else { | ||
3206 | if (base->rev >= 3) { | ||
3207 | base->gen_dmac.backup = d40_backup_regs_v4a; | ||
3208 | base->gen_dmac.backup_size = BACKUP_REGS_SZ_V4A; | ||
3209 | } | ||
3210 | base->gen_dmac.interrupt_en = D40_DREG_PCMIS; | ||
3211 | base->gen_dmac.interrupt_clear = D40_DREG_PCICR; | ||
3212 | base->gen_dmac.realtime_en = D40_DREG_RSEG1; | ||
3213 | base->gen_dmac.realtime_clear = D40_DREG_RCEG1; | ||
3214 | base->gen_dmac.high_prio_en = D40_DREG_PSEG1; | ||
3215 | base->gen_dmac.high_prio_clear = D40_DREG_PCEG1; | ||
3216 | base->gen_dmac.il = il_v4a; | ||
3217 | base->gen_dmac.il_size = ARRAY_SIZE(il_v4a); | ||
3218 | base->gen_dmac.init_reg = dma_init_reg_v4a; | ||
3219 | base->gen_dmac.init_reg_size = ARRAY_SIZE(dma_init_reg_v4a); | ||
3220 | } | ||
3221 | |||
3059 | base->phy_res = kzalloc(num_phy_chans * sizeof(struct d40_phy_res), | 3222 | base->phy_res = kzalloc(num_phy_chans * sizeof(struct d40_phy_res), |
3060 | GFP_KERNEL); | 3223 | GFP_KERNEL); |
3061 | if (!base->phy_res) | 3224 | if (!base->phy_res) |
@@ -3127,31 +3290,15 @@ failure: | |||
3127 | static void __init d40_hw_init(struct d40_base *base) | 3290 | static void __init d40_hw_init(struct d40_base *base) |
3128 | { | 3291 | { |
3129 | 3292 | ||
3130 | static struct d40_reg_val dma_init_reg[] = { | ||
3131 | /* Clock every part of the DMA block from start */ | ||
3132 | { .reg = D40_DREG_GCC, .val = D40_DREG_GCC_ENABLE_ALL}, | ||
3133 | |||
3134 | /* Interrupts on all logical channels */ | ||
3135 | { .reg = D40_DREG_LCMIS0, .val = 0xFFFFFFFF}, | ||
3136 | { .reg = D40_DREG_LCMIS1, .val = 0xFFFFFFFF}, | ||
3137 | { .reg = D40_DREG_LCMIS2, .val = 0xFFFFFFFF}, | ||
3138 | { .reg = D40_DREG_LCMIS3, .val = 0xFFFFFFFF}, | ||
3139 | { .reg = D40_DREG_LCICR0, .val = 0xFFFFFFFF}, | ||
3140 | { .reg = D40_DREG_LCICR1, .val = 0xFFFFFFFF}, | ||
3141 | { .reg = D40_DREG_LCICR2, .val = 0xFFFFFFFF}, | ||
3142 | { .reg = D40_DREG_LCICR3, .val = 0xFFFFFFFF}, | ||
3143 | { .reg = D40_DREG_LCTIS0, .val = 0xFFFFFFFF}, | ||
3144 | { .reg = D40_DREG_LCTIS1, .val = 0xFFFFFFFF}, | ||
3145 | { .reg = D40_DREG_LCTIS2, .val = 0xFFFFFFFF}, | ||
3146 | { .reg = D40_DREG_LCTIS3, .val = 0xFFFFFFFF} | ||
3147 | }; | ||
3148 | int i; | 3293 | int i; |
3149 | u32 prmseo[2] = {0, 0}; | 3294 | u32 prmseo[2] = {0, 0}; |
3150 | u32 activeo[2] = {0xFFFFFFFF, 0xFFFFFFFF}; | 3295 | u32 activeo[2] = {0xFFFFFFFF, 0xFFFFFFFF}; |
3151 | u32 pcmis = 0; | 3296 | u32 pcmis = 0; |
3152 | u32 pcicr = 0; | 3297 | u32 pcicr = 0; |
3298 | struct d40_reg_val *dma_init_reg = base->gen_dmac.init_reg; | ||
3299 | u32 reg_size = base->gen_dmac.init_reg_size; | ||
3153 | 3300 | ||
3154 | for (i = 0; i < ARRAY_SIZE(dma_init_reg); i++) | 3301 | for (i = 0; i < reg_size; i++) |
3155 | writel(dma_init_reg[i].val, | 3302 | writel(dma_init_reg[i].val, |
3156 | base->virtbase + dma_init_reg[i].reg); | 3303 | base->virtbase + dma_init_reg[i].reg); |
3157 | 3304 | ||
@@ -3184,11 +3331,14 @@ static void __init d40_hw_init(struct d40_base *base) | |||
3184 | writel(activeo[0], base->virtbase + D40_DREG_ACTIVO); | 3331 | writel(activeo[0], base->virtbase + D40_DREG_ACTIVO); |
3185 | 3332 | ||
3186 | /* Write which interrupt to enable */ | 3333 | /* Write which interrupt to enable */ |
3187 | writel(pcmis, base->virtbase + D40_DREG_PCMIS); | 3334 | writel(pcmis, base->virtbase + base->gen_dmac.interrupt_en); |
3188 | 3335 | ||
3189 | /* Write which interrupt to clear */ | 3336 | /* Write which interrupt to clear */ |
3190 | writel(pcicr, base->virtbase + D40_DREG_PCICR); | 3337 | writel(pcicr, base->virtbase + base->gen_dmac.interrupt_clear); |
3191 | 3338 | ||
3339 | /* These are __initdata and cannot be accessed after init */ | ||
3340 | base->gen_dmac.init_reg = NULL; | ||
3341 | base->gen_dmac.init_reg_size = 0; | ||
3192 | } | 3342 | } |
3193 | 3343 | ||
3194 | static int __init d40_lcla_allocate(struct d40_base *base) | 3344 | static int __init d40_lcla_allocate(struct d40_base *base) |
diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h index 6d47373f3f58..fdde8ef77542 100644 --- a/drivers/dma/ste_dma40_ll.h +++ b/drivers/dma/ste_dma40_ll.h | |||
@@ -125,7 +125,7 @@ | |||
125 | #define D40_DREG_GCC 0x000 | 125 | #define D40_DREG_GCC 0x000 |
126 | #define D40_DREG_GCC_ENA 0x1 | 126 | #define D40_DREG_GCC_ENA 0x1 |
127 | /* This assumes that there are only 4 event groups */ | 127 | /* This assumes that there are only 4 event groups */ |
128 | #define D40_DREG_GCC_ENABLE_ALL 0xff01 | 128 | #define D40_DREG_GCC_ENABLE_ALL 0x3ff01 |
129 | #define D40_DREG_GCC_EVTGRP_POS 8 | 129 | #define D40_DREG_GCC_EVTGRP_POS 8 |
130 | #define D40_DREG_GCC_SRC 0 | 130 | #define D40_DREG_GCC_SRC 0 |
131 | #define D40_DREG_GCC_DST 1 | 131 | #define D40_DREG_GCC_DST 1 |
@@ -148,14 +148,31 @@ | |||
148 | 148 | ||
149 | #define D40_DREG_LCPA 0x020 | 149 | #define D40_DREG_LCPA 0x020 |
150 | #define D40_DREG_LCLA 0x024 | 150 | #define D40_DREG_LCLA 0x024 |
151 | |||
152 | #define D40_DREG_SSEG1 0x030 | ||
153 | #define D40_DREG_SSEG2 0x034 | ||
154 | #define D40_DREG_SSEG3 0x038 | ||
155 | #define D40_DREG_SSEG4 0x03C | ||
156 | |||
157 | #define D40_DREG_SCEG1 0x040 | ||
158 | #define D40_DREG_SCEG2 0x044 | ||
159 | #define D40_DREG_SCEG3 0x048 | ||
160 | #define D40_DREG_SCEG4 0x04C | ||
161 | |||
151 | #define D40_DREG_ACTIVE 0x050 | 162 | #define D40_DREG_ACTIVE 0x050 |
152 | #define D40_DREG_ACTIVO 0x054 | 163 | #define D40_DREG_ACTIVO 0x054 |
153 | #define D40_DREG_FSEB1 0x058 | 164 | #define D40_DREG_CIDMOD 0x058 |
154 | #define D40_DREG_FSEB2 0x05C | 165 | #define D40_DREG_TCIDV 0x05C |
155 | #define D40_DREG_PCMIS 0x060 | 166 | #define D40_DREG_PCMIS 0x060 |
156 | #define D40_DREG_PCICR 0x064 | 167 | #define D40_DREG_PCICR 0x064 |
157 | #define D40_DREG_PCTIS 0x068 | 168 | #define D40_DREG_PCTIS 0x068 |
158 | #define D40_DREG_PCEIS 0x06C | 169 | #define D40_DREG_PCEIS 0x06C |
170 | |||
171 | #define D40_DREG_SPCMIS 0x070 | ||
172 | #define D40_DREG_SPCICR 0x074 | ||
173 | #define D40_DREG_SPCTIS 0x078 | ||
174 | #define D40_DREG_SPCEIS 0x07C | ||
175 | |||
159 | #define D40_DREG_LCMIS0 0x080 | 176 | #define D40_DREG_LCMIS0 0x080 |
160 | #define D40_DREG_LCMIS1 0x084 | 177 | #define D40_DREG_LCMIS1 0x084 |
161 | #define D40_DREG_LCMIS2 0x088 | 178 | #define D40_DREG_LCMIS2 0x088 |
@@ -172,6 +189,33 @@ | |||
172 | #define D40_DREG_LCEIS1 0x0B4 | 189 | #define D40_DREG_LCEIS1 0x0B4 |
173 | #define D40_DREG_LCEIS2 0x0B8 | 190 | #define D40_DREG_LCEIS2 0x0B8 |
174 | #define D40_DREG_LCEIS3 0x0BC | 191 | #define D40_DREG_LCEIS3 0x0BC |
192 | |||
193 | #define D40_DREG_SLCMIS1 0x0C0 | ||
194 | #define D40_DREG_SLCMIS2 0x0C4 | ||
195 | #define D40_DREG_SLCMIS3 0x0C8 | ||
196 | #define D40_DREG_SLCMIS4 0x0CC | ||
197 | |||
198 | #define D40_DREG_SLCICR1 0x0D0 | ||
199 | #define D40_DREG_SLCICR2 0x0D4 | ||
200 | #define D40_DREG_SLCICR3 0x0D8 | ||
201 | #define D40_DREG_SLCICR4 0x0DC | ||
202 | |||
203 | #define D40_DREG_SLCTIS1 0x0E0 | ||
204 | #define D40_DREG_SLCTIS2 0x0E4 | ||
205 | #define D40_DREG_SLCTIS3 0x0E8 | ||
206 | #define D40_DREG_SLCTIS4 0x0EC | ||
207 | |||
208 | #define D40_DREG_SLCEIS1 0x0F0 | ||
209 | #define D40_DREG_SLCEIS2 0x0F4 | ||
210 | #define D40_DREG_SLCEIS3 0x0F8 | ||
211 | #define D40_DREG_SLCEIS4 0x0FC | ||
212 | |||
213 | #define D40_DREG_FSESS1 0x100 | ||
214 | #define D40_DREG_FSESS2 0x104 | ||
215 | |||
216 | #define D40_DREG_FSEBS1 0x108 | ||
217 | #define D40_DREG_FSEBS2 0x10C | ||
218 | |||
175 | #define D40_DREG_PSEG1 0x110 | 219 | #define D40_DREG_PSEG1 0x110 |
176 | #define D40_DREG_PSEG2 0x114 | 220 | #define D40_DREG_PSEG2 0x114 |
177 | #define D40_DREG_PSEG3 0x118 | 221 | #define D40_DREG_PSEG3 0x118 |
@@ -188,6 +232,86 @@ | |||
188 | #define D40_DREG_RCEG2 0x144 | 232 | #define D40_DREG_RCEG2 0x144 |
189 | #define D40_DREG_RCEG3 0x148 | 233 | #define D40_DREG_RCEG3 0x148 |
190 | #define D40_DREG_RCEG4 0x14C | 234 | #define D40_DREG_RCEG4 0x14C |
235 | |||
236 | #define D40_DREG_PREFOT 0x15C | ||
237 | #define D40_DREG_EXTCFG 0x160 | ||
238 | |||
239 | #define D40_DREG_CPSEG1 0x200 | ||
240 | #define D40_DREG_CPSEG2 0x204 | ||
241 | #define D40_DREG_CPSEG3 0x208 | ||
242 | #define D40_DREG_CPSEG4 0x20C | ||
243 | #define D40_DREG_CPSEG5 0x210 | ||
244 | |||
245 | #define D40_DREG_CPCEG1 0x220 | ||
246 | #define D40_DREG_CPCEG2 0x224 | ||
247 | #define D40_DREG_CPCEG3 0x228 | ||
248 | #define D40_DREG_CPCEG4 0x22C | ||
249 | #define D40_DREG_CPCEG5 0x230 | ||
250 | |||
251 | #define D40_DREG_CRSEG1 0x240 | ||
252 | #define D40_DREG_CRSEG2 0x244 | ||
253 | #define D40_DREG_CRSEG3 0x248 | ||
254 | #define D40_DREG_CRSEG4 0x24C | ||
255 | #define D40_DREG_CRSEG5 0x250 | ||
256 | |||
257 | #define D40_DREG_CRCEG1 0x260 | ||
258 | #define D40_DREG_CRCEG2 0x264 | ||
259 | #define D40_DREG_CRCEG3 0x268 | ||
260 | #define D40_DREG_CRCEG4 0x26C | ||
261 | #define D40_DREG_CRCEG5 0x270 | ||
262 | |||
263 | #define D40_DREG_CFSESS1 0x280 | ||
264 | #define D40_DREG_CFSESS2 0x284 | ||
265 | #define D40_DREG_CFSESS3 0x288 | ||
266 | |||
267 | #define D40_DREG_CFSEBS1 0x290 | ||
268 | #define D40_DREG_CFSEBS2 0x294 | ||
269 | #define D40_DREG_CFSEBS3 0x298 | ||
270 | |||
271 | #define D40_DREG_CLCMIS1 0x300 | ||
272 | #define D40_DREG_CLCMIS2 0x304 | ||
273 | #define D40_DREG_CLCMIS3 0x308 | ||
274 | #define D40_DREG_CLCMIS4 0x30C | ||
275 | #define D40_DREG_CLCMIS5 0x310 | ||
276 | |||
277 | #define D40_DREG_CLCICR1 0x320 | ||
278 | #define D40_DREG_CLCICR2 0x324 | ||
279 | #define D40_DREG_CLCICR3 0x328 | ||
280 | #define D40_DREG_CLCICR4 0x32C | ||
281 | #define D40_DREG_CLCICR5 0x330 | ||
282 | |||
283 | #define D40_DREG_CLCTIS1 0x340 | ||
284 | #define D40_DREG_CLCTIS2 0x344 | ||
285 | #define D40_DREG_CLCTIS3 0x348 | ||
286 | #define D40_DREG_CLCTIS4 0x34C | ||
287 | #define D40_DREG_CLCTIS5 0x350 | ||
288 | |||
289 | #define D40_DREG_CLCEIS1 0x360 | ||
290 | #define D40_DREG_CLCEIS2 0x364 | ||
291 | #define D40_DREG_CLCEIS3 0x368 | ||
292 | #define D40_DREG_CLCEIS4 0x36C | ||
293 | #define D40_DREG_CLCEIS5 0x370 | ||
294 | |||
295 | #define D40_DREG_CPCMIS 0x380 | ||
296 | #define D40_DREG_CPCICR 0x384 | ||
297 | #define D40_DREG_CPCTIS 0x388 | ||
298 | #define D40_DREG_CPCEIS 0x38C | ||
299 | |||
300 | #define D40_DREG_SCCIDA1 0xE80 | ||
301 | #define D40_DREG_SCCIDA2 0xE90 | ||
302 | #define D40_DREG_SCCIDA3 0xEA0 | ||
303 | #define D40_DREG_SCCIDA4 0xEB0 | ||
304 | #define D40_DREG_SCCIDA5 0xEC0 | ||
305 | |||
306 | #define D40_DREG_SCCIDB1 0xE84 | ||
307 | #define D40_DREG_SCCIDB2 0xE94 | ||
308 | #define D40_DREG_SCCIDB3 0xEA4 | ||
309 | #define D40_DREG_SCCIDB4 0xEB4 | ||
310 | #define D40_DREG_SCCIDB5 0xEC4 | ||
311 | |||
312 | #define D40_DREG_PRSCCIDA 0xF80 | ||
313 | #define D40_DREG_PRSCCIDB 0xF84 | ||
314 | |||
191 | #define D40_DREG_STFU 0xFC8 | 315 | #define D40_DREG_STFU 0xFC8 |
192 | #define D40_DREG_ICFG 0xFCC | 316 | #define D40_DREG_ICFG 0xFCC |
193 | #define D40_DREG_PERIPHID0 0xFE0 | 317 | #define D40_DREG_PERIPHID0 0xFE0 |