1/* Wrapper for DMA channel allocator that updates DMA client muxing. 2 * Copyright 2004-2007, Axis Communications AB 3 */ 4 5#include <linux/kernel.h> 6#include <linux/module.h> 7#include <linux/errno.h> 8 9#include <asm/dma.h> 10#include <arch/svinto.h> 11#include <arch/system.h> 12 13/* Macro to access ETRAX 100 registers */ 14#define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \ 15 IO_STATE_(reg##_, field##_, _##val) 16 17 18static char used_dma_channels[MAX_DMA_CHANNELS]; 19static const char * used_dma_channels_users[MAX_DMA_CHANNELS]; 20 21int cris_request_dma(unsigned int dmanr, const char * device_id, 22 unsigned options, enum dma_owner owner) 23{ 24 unsigned long flags; 25 unsigned long int gens; 26 int fail = -EINVAL; 27 28 if (dmanr >= MAX_DMA_CHANNELS) { 29 printk(KERN_CRIT "cris_request_dma: invalid DMA channel %u\n", dmanr); 30 return -EINVAL; 31 } 32 33 local_irq_save(flags); 34 if (used_dma_channels[dmanr]) { 35 local_irq_restore(flags); 36 if (options & DMA_VERBOSE_ON_ERROR) { 37 printk(KERN_CRIT "Failed to request DMA %i for %s, already allocated by %s\n", dmanr, device_id, used_dma_channels_users[dmanr]); 38 } 39 if (options & DMA_PANIC_ON_ERROR) { 40 panic("request_dma error!"); 41 } 42 return -EBUSY; 43 } 44 45 gens = genconfig_shadow; 46 47 switch(owner) 48 { 49 case dma_eth: 50 if ((dmanr != NETWORK_TX_DMA_NBR) && 51 (dmanr != NETWORK_RX_DMA_NBR)) { 52 printk(KERN_CRIT "Invalid DMA channel for eth\n"); 53 goto bail; 54 } 55 break; 56 case dma_ser0: 57 if (dmanr == SER0_TX_DMA_NBR) { 58 SETS(gens, R_GEN_CONFIG, dma6, serial0); 59 } else if (dmanr == SER0_RX_DMA_NBR) { 60 SETS(gens, R_GEN_CONFIG, dma7, serial0); 61 } else { 62 printk(KERN_CRIT "Invalid DMA channel for ser0\n"); 63 goto bail; 64 } 65 break; 66 case dma_ser1: 67 if (dmanr == SER1_TX_DMA_NBR) { 68 SETS(gens, R_GEN_CONFIG, dma8, serial1); 69 } else if (dmanr == SER1_RX_DMA_NBR) { 70 SETS(gens, R_GEN_CONFIG, dma9, serial1); 71 } else { 72 printk(KERN_CRIT "Invalid DMA channel for ser1\n"); 73 goto bail; 74 } 75 break; 76 case dma_ser2: 77 if (dmanr == SER2_TX_DMA_NBR) { 78 SETS(gens, R_GEN_CONFIG, dma2, serial2); 79 } else if (dmanr == SER2_RX_DMA_NBR) { 80 SETS(gens, R_GEN_CONFIG, dma3, serial2); 81 } else { 82 printk(KERN_CRIT "Invalid DMA channel for ser2\n"); 83 goto bail; 84 } 85 break; 86 case dma_ser3: 87 if (dmanr == SER3_TX_DMA_NBR) { 88 SETS(gens, R_GEN_CONFIG, dma4, serial3); 89 } else if (dmanr == SER3_RX_DMA_NBR) { 90 SETS(gens, R_GEN_CONFIG, dma5, serial3); 91 } else { 92 printk(KERN_CRIT "Invalid DMA channel for ser3\n"); 93 goto bail; 94 } 95 break; 96 case dma_ata: 97 if (dmanr == ATA_TX_DMA_NBR) { 98 SETS(gens, R_GEN_CONFIG, dma2, ata); 99 } else if (dmanr == ATA_RX_DMA_NBR) { 100 SETS(gens, R_GEN_CONFIG, dma3, ata); 101 } else { 102 printk(KERN_CRIT "Invalid DMA channel for ata\n"); 103 goto bail; 104 } 105 break; 106 case dma_ext0: 107 if (dmanr == EXTDMA0_TX_DMA_NBR) { 108 SETS(gens, R_GEN_CONFIG, dma4, extdma0); 109 } else if (dmanr == EXTDMA0_RX_DMA_NBR) { 110 SETS(gens, R_GEN_CONFIG, dma5, extdma0); 111 } else { 112 printk(KERN_CRIT "Invalid DMA channel for ext0\n"); 113 goto bail; 114 } 115 break; 116 case dma_ext1: 117 if (dmanr == EXTDMA1_TX_DMA_NBR) { 118 SETS(gens, R_GEN_CONFIG, dma6, extdma1); 119 } else if (dmanr == EXTDMA1_RX_DMA_NBR) { 120 SETS(gens, R_GEN_CONFIG, dma7, extdma1); 121 } else { 122 printk(KERN_CRIT "Invalid DMA channel for ext1\n"); 123 goto bail; 124 } 125 break; 126 case dma_int6: 127 if (dmanr == MEM2MEM_RX_DMA_NBR) { 128 SETS(gens, R_GEN_CONFIG, dma7, intdma6); 129 } else { 130 printk(KERN_CRIT "Invalid DMA channel for int6\n"); 131 goto bail; 132 } 133 break; 134 case dma_int7: 135 if (dmanr == MEM2MEM_TX_DMA_NBR) { 136 SETS(gens, R_GEN_CONFIG, dma6, intdma7); 137 } else { 138 printk(KERN_CRIT "Invalid DMA channel for int7\n"); 139 goto bail; 140 } 141 break; 142 case dma_usb: 143 if (dmanr == USB_TX_DMA_NBR) { 144 SETS(gens, R_GEN_CONFIG, dma8, usb); 145 } else if (dmanr == USB_RX_DMA_NBR) { 146 SETS(gens, R_GEN_CONFIG, dma9, usb); 147 } else { 148 printk(KERN_CRIT "Invalid DMA channel for usb\n"); 149 goto bail; 150 } 151 break; 152 case dma_scsi0: 153 if (dmanr == SCSI0_TX_DMA_NBR) { 154 SETS(gens, R_GEN_CONFIG, dma2, scsi0); 155 } else if (dmanr == SCSI0_RX_DMA_NBR) { 156 SETS(gens, R_GEN_CONFIG, dma3, scsi0); 157 } else { 158 printk(KERN_CRIT "Invalid DMA channel for scsi0\n"); 159 goto bail; 160 } 161 break; 162 case dma_scsi1: 163 if (dmanr == SCSI1_TX_DMA_NBR) { 164 SETS(gens, R_GEN_CONFIG, dma4, scsi1); 165 } else if (dmanr == SCSI1_RX_DMA_NBR) { 166 SETS(gens, R_GEN_CONFIG, dma5, scsi1); 167 } else { 168 printk(KERN_CRIT "Invalid DMA channel for scsi1\n"); 169 goto bail; 170 } 171 break; 172 case dma_par0: 173 if (dmanr == PAR0_TX_DMA_NBR) { 174 SETS(gens, R_GEN_CONFIG, dma2, par0); 175 } else if (dmanr == PAR0_RX_DMA_NBR) { 176 SETS(gens, R_GEN_CONFIG, dma3, par0); 177 } else { 178 printk(KERN_CRIT "Invalid DMA channel for par0\n"); 179 goto bail; 180 } 181 break; 182 case dma_par1: 183 if (dmanr == PAR1_TX_DMA_NBR) { 184 SETS(gens, R_GEN_CONFIG, dma4, par1); 185 } else if (dmanr == PAR1_RX_DMA_NBR) { 186 SETS(gens, R_GEN_CONFIG, dma5, par1); 187 } else { 188 printk(KERN_CRIT "Invalid DMA channel for par1\n"); 189 goto bail; 190 } 191 break; 192 default: 193 printk(KERN_CRIT "Invalid DMA owner.\n"); 194 goto bail; 195 } 196 197 used_dma_channels[dmanr] = 1; 198 used_dma_channels_users[dmanr] = device_id; 199 200 { 201 volatile int i; 202 genconfig_shadow = gens; 203 *R_GEN_CONFIG = genconfig_shadow; 204 /* Wait 12 cycles before doing any DMA command */ 205 for(i = 6; i > 0; i--) 206 nop(); 207 } 208 fail = 0; 209 bail: 210 local_irq_restore(flags); 211 return fail; 212} 213 214void cris_free_dma(unsigned int dmanr, const char * device_id) 215{ 216 unsigned long flags; 217 if (dmanr >= MAX_DMA_CHANNELS) { 218 printk(KERN_CRIT "cris_free_dma: invalid DMA channel %u\n", dmanr); 219 return; 220 } 221 222 local_irq_save(flags); 223 if (!used_dma_channels[dmanr]) { 224 printk(KERN_CRIT "cris_free_dma: DMA channel %u not allocated\n", dmanr); 225 } else if (device_id != used_dma_channels_users[dmanr]) { 226 printk(KERN_CRIT "cris_free_dma: DMA channel %u not allocated by device\n", dmanr); 227 } else { 228 switch(dmanr) 229 { 230 case 0: 231 *R_DMA_CH0_CMD = IO_STATE(R_DMA_CH0_CMD, cmd, reset); 232 while (IO_EXTRACT(R_DMA_CH0_CMD, cmd, *R_DMA_CH0_CMD) == 233 IO_STATE_VALUE(R_DMA_CH0_CMD, cmd, reset)); 234 break; 235 case 1: 236 *R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, reset); 237 while (IO_EXTRACT(R_DMA_CH1_CMD, cmd, *R_DMA_CH1_CMD) == 238 IO_STATE_VALUE(R_DMA_CH1_CMD, cmd, reset)); 239 break; 240 case 2: 241 *R_DMA_CH2_CMD = IO_STATE(R_DMA_CH2_CMD, cmd, reset); 242 while (IO_EXTRACT(R_DMA_CH2_CMD, cmd, *R_DMA_CH2_CMD) == 243 IO_STATE_VALUE(R_DMA_CH2_CMD, cmd, reset)); 244 break; 245 case 3: 246 *R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, reset); 247 while (IO_EXTRACT(R_DMA_CH3_CMD, cmd, *R_DMA_CH3_CMD) == 248 IO_STATE_VALUE(R_DMA_CH3_CMD, cmd, reset)); 249 break; 250 case 4: 251 *R_DMA_CH4_CMD = IO_STATE(R_DMA_CH4_CMD, cmd, reset); 252 while (IO_EXTRACT(R_DMA_CH4_CMD, cmd, *R_DMA_CH4_CMD) == 253 IO_STATE_VALUE(R_DMA_CH4_CMD, cmd, reset)); 254 break; 255 case 5: 256 *R_DMA_CH5_CMD = IO_STATE(R_DMA_CH5_CMD, cmd, reset); 257 while (IO_EXTRACT(R_DMA_CH5_CMD, cmd, *R_DMA_CH5_CMD) == 258 IO_STATE_VALUE(R_DMA_CH5_CMD, cmd, reset)); 259 break; 260 case 6: 261 *R_DMA_CH6_CMD = IO_STATE(R_DMA_CH6_CMD, cmd, reset); 262 while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *R_DMA_CH6_CMD) == 263 IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset)); 264 break; 265 case 7: 266 *R_DMA_CH7_CMD = IO_STATE(R_DMA_CH7_CMD, cmd, reset); 267 while (IO_EXTRACT(R_DMA_CH7_CMD, cmd, *R_DMA_CH7_CMD) == 268 IO_STATE_VALUE(R_DMA_CH7_CMD, cmd, reset)); 269 break; 270 case 8: 271 *R_DMA_CH8_CMD = IO_STATE(R_DMA_CH8_CMD, cmd, reset); 272 while (IO_EXTRACT(R_DMA_CH8_CMD, cmd, *R_DMA_CH8_CMD) == 273 IO_STATE_VALUE(R_DMA_CH8_CMD, cmd, reset)); 274 break; 275 case 9: 276 *R_DMA_CH9_CMD = IO_STATE(R_DMA_CH9_CMD, cmd, reset); 277 while (IO_EXTRACT(R_DMA_CH9_CMD, cmd, *R_DMA_CH9_CMD) == 278 IO_STATE_VALUE(R_DMA_CH9_CMD, cmd, reset)); 279 break; 280 } 281 used_dma_channels[dmanr] = 0; 282 } 283 local_irq_restore(flags); 284} 285 286EXPORT_SYMBOL(cris_request_dma); 287EXPORT_SYMBOL(cris_free_dma); 288