aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorTong Liu <tong.liu@stericsson.com>2012-09-26 06:07:30 -0400
committerFabio Baltieri <fabio.baltieri@linaro.org>2013-01-14 04:50:48 -0500
commit3cb645dc85a050c8a6b5c2cbdcbe4b8f39dba1b8 (patch)
tree9031f1a3af3f74492e94ff057a50785c9ddc103b /drivers/dma
parent47db92f4a63499b1605b4c66f9347ba5479e7b19 (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.c306
-rw-r--r--drivers/dma/ste_dma40_ll.h130
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/*
104static 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 */
117static 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
138static 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
125static u32 d40_backup_regs_chan[] = { 163static 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 */
183struct d40_interrupt_lookup {
184 u32 src;
185 u32 clr;
186 bool is_error;
187 int offset;
188};
189
190
191static 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
204static 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 */
225struct d40_reg_val {
226 unsigned int reg;
227 unsigned int val;
228};
229
230static __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};
248static __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 */
442struct 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 */
335struct d40_base { 503struct 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 */
380struct 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 */
393struct d40_reg_val {
394 unsigned int reg;
395 unsigned int val;
396}; 538};
397 539
398static struct device *chan2dev(struct d40_chan *d40c) 540static 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
885static void d40_save_restore_registers(struct d40_base *base, bool save) 1027static void d40_save_restore_registers(struct d40_base *base, bool save)
@@ -1470,41 +1612,30 @@ err:
1470 1612
1471static irqreturn_t d40_handle_interrupt(int irq, void *data) 1613static 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:
3127static void __init d40_hw_init(struct d40_base *base) 3290static 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
3194static int __init d40_lcla_allocate(struct d40_base *base) 3344static 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