diff options
| author | Vinod Koul <vinod.koul@intel.com> | 2013-01-21 09:35:12 -0500 |
|---|---|---|
| committer | Vinod Koul <vinod.koul@intel.com> | 2013-01-21 10:09:34 -0500 |
| commit | 6c5e6a3990ce64192b56ffafa5ffa5af129751d5 (patch) | |
| tree | 228632cd25a3ce0e00194fb492eaa4c50e5acbae | |
| parent | 77bcc497c60ec62dbb84abc809a6e218d53409e9 (diff) | |
| parent | da2ac56a1bc9c6c56244aa9ca990d5c5c7574b5f (diff) | |
Merge tag 'ux500-dma40' of //git.linaro.org/people/fabiobaltieri/linux.git
Pull ste_dma40 fixes from Fabio
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
| -rw-r--r-- | drivers/dma/ste_dma40.c | 489 | ||||
| -rw-r--r-- | drivers/dma/ste_dma40_ll.c | 29 | ||||
| -rw-r--r-- | drivers/dma/ste_dma40_ll.h | 130 | ||||
| -rw-r--r-- | include/linux/platform_data/dma-ste-dma40.h | 13 |
4 files changed, 518 insertions, 143 deletions
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index e5e60bb68d9d..ad860a221c33 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 |
| @@ -221,6 +355,7 @@ struct d40_lcla_pool { | |||
| 221 | * @allocated_dst: Same as for src but is dst. | 355 | * @allocated_dst: Same as for src but is dst. |
| 222 | * allocated_dst and allocated_src uses the D40_ALLOC* defines as well as | 356 | * allocated_dst and allocated_src uses the D40_ALLOC* defines as well as |
| 223 | * event line number. | 357 | * event line number. |
| 358 | * @use_soft_lli: To mark if the linked lists of channel are managed by SW. | ||
| 224 | */ | 359 | */ |
| 225 | struct d40_phy_res { | 360 | struct d40_phy_res { |
| 226 | spinlock_t lock; | 361 | spinlock_t lock; |
| @@ -228,6 +363,7 @@ struct d40_phy_res { | |||
| 228 | int num; | 363 | int num; |
| 229 | u32 allocated_src; | 364 | u32 allocated_src; |
| 230 | u32 allocated_dst; | ||
