1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * linux/arch/arm/kernel/dma.c 4 * 5 * Copyright (C) 1995-2000 Russell King 6 * 7 * Front-end to the DMA handling. This handles the allocation/freeing 8 * of DMA channels, and provides a unified interface to the machines 9 * DMA facilities. 10 */ 11 #include <linux/module.h> 12 #include <linux/init.h> 13 #include <linux/spinlock.h> 14 #include <linux/errno.h> 15 #include <linux/scatterlist.h> 16 #include <linux/seq_file.h> 17 #include <linux/proc_fs.h> 18 19 #include <asm/dma.h> 20 21 #include <asm/mach/dma.h> 22 23 DEFINE_RAW_SPINLOCK(dma_spin_lock); 24 EXPORT_SYMBOL(dma_spin_lock); 25 26 static dma_t *dma_chan[MAX_DMA_CHANNELS]; 27 28 static inline dma_t *dma_channel(unsigned int chan) 29 { 30 if (chan >= MAX_DMA_CHANNELS) 31 return NULL; 32 33 return dma_chan[chan]; 34 } 35 36 int __init isa_dma_add(unsigned int chan, dma_t *dma) 37 { 38 if (!dma->d_ops) 39 return -EINVAL; 40 41 sg_init_table(&dma->buf, 1); 42 43 if (dma_chan[chan]) 44 return -EBUSY; 45 dma_chan[chan] = dma; 46 return 0; 47 } 48 49 /* 50 * Request DMA channel 51 * 52 * On certain platforms, we have to allocate an interrupt as well... 53 */ 54 int request_dma(unsigned int chan, const char *device_id) 55 { 56 dma_t *dma = dma_channel(chan); 57 int ret; 58 59 if (!dma) 60 goto bad_dma; 61 62 if (xchg(&dma->lock, 1) != 0) 63 goto busy; 64 65 dma->device_id = device_id; 66 dma->active = 0; 67 dma->invalid = 1; 68 69 ret = 0; 70 if (dma->d_ops->request) 71 ret = dma->d_ops->request(chan, dma); 72 73 if (ret) 74 xchg(&dma->lock, 0); 75 76 return ret; 77 78 bad_dma: 79 pr_err("dma: trying to allocate DMA%d\n", chan); 80 return -EINVAL; 81 82 busy: 83 return -EBUSY; 84 } 85 EXPORT_SYMBOL(request_dma); 86 87 /* 88 * Free DMA channel 89 * 90 * On certain platforms, we have to free interrupt as well... 91 */ 92 void free_dma(unsigned int chan) 93 { 94 dma_t *dma = dma_channel(chan); 95 96 if (!dma) 97 goto bad_dma; 98 99 if (dma->active) { 100 pr_err("dma%d: freeing active DMA\n", chan); 101 dma->d_ops->disable(chan, dma); 102 dma->active = 0; 103 } 104 105 if (xchg(&dma->lock, 0) != 0) { 106 if (dma->d_ops->free) 107 dma->d_ops->free(chan, dma); 108 return; 109 } 110 111 pr_err("dma%d: trying to free free DMA\n", chan); 112 return; 113 114 bad_dma: 115 pr_err("dma: trying to free DMA%d\n", chan); 116 } 117 EXPORT_SYMBOL(free_dma); 118 119 /* Set DMA Scatter-Gather list 120 */ 121 void set_dma_sg (unsigned int chan, struct scatterlist *sg, int nr_sg) 122 { 123 dma_t *dma = dma_channel(chan); 124 125 if (dma->active) 126 pr_err("dma%d: altering DMA SG while DMA active\n", chan); 127 128 dma->sg = sg; 129 dma->sgcount = nr_sg; 130 dma->invalid = 1; 131 } 132 EXPORT_SYMBOL(set_dma_sg); 133 134 /* Set DMA address 135 * 136 * Copy address to the structure, and set the invalid bit 137 */ 138 void __set_dma_addr (unsigned int chan, void *addr) 139 { 140 dma_t *dma = dma_channel(chan); 141 142 if (dma->active) 143 pr_err("dma%d: altering DMA address while DMA active\n", chan); 144 145 dma->sg = NULL; 146 dma->addr = addr; 147 dma->invalid = 1; 148 } 149 EXPORT_SYMBOL(__set_dma_addr); 150 151 /* Set DMA byte count 152 * 153 * Copy address to the structure, and set the invalid bit 154 */ 155 void set_dma_count (unsigned int chan, unsigned long count) 156 { 157 dma_t *dma = dma_channel(chan); 158 159 if (dma->active) 160 pr_err("dma%d: altering DMA count while DMA active\n", chan); 161 162 dma->sg = NULL; 163 dma->count = count; 164 dma->invalid = 1; 165 } 166 EXPORT_SYMBOL(set_dma_count); 167 168 /* Set DMA direction mode 169 */ 170 void set_dma_mode (unsigned int chan, unsigned int mode) 171 { 172 dma_t *dma = dma_channel(chan); 173 174 if (dma->active) 175 pr_err("dma%d: altering DMA mode while DMA active\n", chan); 176 177 dma->dma_mode = mode; 178 dma->invalid = 1; 179 } 180 EXPORT_SYMBOL(set_dma_mode); 181 182 /* Enable DMA channel 183 */ 184 void enable_dma (unsigned int chan) 185 { 186 dma_t *dma = dma_channel(chan); 187 188 if (!dma->lock) 189 goto free_dma; 190 191 if (dma->active == 0) { 192 dma->active = 1; 193 dma->d_ops->enable(chan, dma); 194 } 195 return; 196 197 free_dma: 198 pr_err("dma%d: trying to enable free DMA\n", chan); 199 BUG(); 200 } 201 EXPORT_SYMBOL(enable_dma); 202 203 /* Disable DMA channel 204 */ 205 void disable_dma (unsigned int chan) 206 { 207 dma_t *dma = dma_channel(chan); 208 209 if (!dma->lock) 210 goto free_dma; 211 212 if (dma->active == 1) { 213 dma->active = 0; 214 dma->d_ops->disable(chan, dma); 215 } 216 return; 217 218 free_dma: 219 pr_err("dma%d: trying to disable free DMA\n", chan); 220 BUG(); 221 } 222 EXPORT_SYMBOL(disable_dma); 223 224 /* 225 * Is the specified DMA channel active? 226 */ 227 int dma_channel_active(unsigned int chan) 228 { 229 dma_t *dma = dma_channel(chan); 230 return dma->active; 231 } 232 EXPORT_SYMBOL(dma_channel_active); 233 234 void set_dma_page(unsigned int chan, char pagenr) 235 { 236 pr_err("dma%d: trying to set_dma_page\n", chan); 237 } 238 EXPORT_SYMBOL(set_dma_page); 239 240 void set_dma_speed(unsigned int chan, int cycle_ns) 241 { 242 dma_t *dma = dma_channel(chan); 243 int ret = 0; 244 245 if (dma->d_ops->setspeed) 246 ret = dma->d_ops->setspeed(chan, dma, cycle_ns); 247 dma->speed = ret; 248 } 249 EXPORT_SYMBOL(set_dma_speed); 250 251 int get_dma_residue(unsigned int chan) 252 { 253 dma_t *dma = dma_channel(chan); 254 int ret = 0; 255 256 if (dma->d_ops->residue) 257 ret = dma->d_ops->residue(chan, dma); 258 259 return ret; 260 } 261 EXPORT_SYMBOL(get_dma_residue); 262 263 #ifdef CONFIG_PROC_FS 264 static int proc_dma_show(struct seq_file *m, void *v) 265 { 266 int i; 267 268 for (i = 0 ; i < MAX_DMA_CHANNELS ; i++) { 269 dma_t *dma = dma_channel(i); 270 if (dma && dma->lock) 271 seq_printf(m, "%2d: %s\n", i, dma->device_id); 272 } 273 return 0; 274 } 275 276 static int __init proc_dma_init(void) 277 { 278 proc_create_single("dma", 0, NULL, proc_dma_show); 279 return 0; 280 } 281 282 __initcall(proc_dma_init); 283 #endif 284