Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  linux/arch/arm/kernel/dma.c
0004  *
0005  *  Copyright (C) 1995-2000 Russell King
0006  *
0007  *  Front-end to the DMA handling.  This handles the allocation/freeing
0008  *  of DMA channels, and provides a unified interface to the machines
0009  *  DMA facilities.
0010  */
0011 #include <linux/module.h>
0012 #include <linux/init.h>
0013 #include <linux/spinlock.h>
0014 #include <linux/errno.h>
0015 #include <linux/scatterlist.h>
0016 #include <linux/seq_file.h>
0017 #include <linux/proc_fs.h>
0018 
0019 #include <asm/dma.h>
0020 
0021 #include <asm/mach/dma.h>
0022 
0023 DEFINE_RAW_SPINLOCK(dma_spin_lock);
0024 EXPORT_SYMBOL(dma_spin_lock);
0025 
0026 static dma_t *dma_chan[MAX_DMA_CHANNELS];
0027 
0028 static inline dma_t *dma_channel(unsigned int chan)
0029 {
0030     if (chan >= MAX_DMA_CHANNELS)
0031         return NULL;
0032 
0033     return dma_chan[chan];
0034 }
0035 
0036 int __init isa_dma_add(unsigned int chan, dma_t *dma)
0037 {
0038     if (!dma->d_ops)
0039         return -EINVAL;
0040 
0041     sg_init_table(&dma->buf, 1);
0042 
0043     if (dma_chan[chan])
0044         return -EBUSY;
0045     dma_chan[chan] = dma;
0046     return 0;
0047 }
0048 
0049 /*
0050  * Request DMA channel
0051  *
0052  * On certain platforms, we have to allocate an interrupt as well...
0053  */
0054 int request_dma(unsigned int chan, const char *device_id)
0055 {
0056     dma_t *dma = dma_channel(chan);
0057     int ret;
0058 
0059     if (!dma)
0060         goto bad_dma;
0061 
0062     if (xchg(&dma->lock, 1) != 0)
0063         goto busy;
0064 
0065     dma->device_id = device_id;
0066     dma->active    = 0;
0067     dma->invalid   = 1;
0068 
0069     ret = 0;
0070     if (dma->d_ops->request)
0071         ret = dma->d_ops->request(chan, dma);
0072 
0073     if (ret)
0074         xchg(&dma->lock, 0);
0075 
0076     return ret;
0077 
0078 bad_dma:
0079     pr_err("dma: trying to allocate DMA%d\n", chan);
0080     return -EINVAL;
0081 
0082 busy:
0083     return -EBUSY;
0084 }
0085 EXPORT_SYMBOL(request_dma);
0086 
0087 /*
0088  * Free DMA channel
0089  *
0090  * On certain platforms, we have to free interrupt as well...
0091  */
0092 void free_dma(unsigned int chan)
0093 {
0094     dma_t *dma = dma_channel(chan);
0095 
0096     if (!dma)
0097         goto bad_dma;
0098 
0099     if (dma->active) {
0100         pr_err("dma%d: freeing active DMA\n", chan);
0101         dma->d_ops->disable(chan, dma);
0102         dma->active = 0;
0103     }
0104 
0105     if (xchg(&dma->lock, 0) != 0) {
0106         if (dma->d_ops->free)
0107             dma->d_ops->free(chan, dma);
0108         return;
0109     }
0110 
0111     pr_err("dma%d: trying to free free DMA\n", chan);
0112     return;
0113 
0114 bad_dma:
0115     pr_err("dma: trying to free DMA%d\n", chan);
0116 }
0117 EXPORT_SYMBOL(free_dma);
0118 
0119 /* Set DMA Scatter-Gather list
0120  */
0121 void set_dma_sg (unsigned int chan, struct scatterlist *sg, int nr_sg)
0122 {
0123     dma_t *dma = dma_channel(chan);
0124 
0125     if (dma->active)
0126         pr_err("dma%d: altering DMA SG while DMA active\n", chan);
0127 
0128     dma->sg = sg;
0129     dma->sgcount = nr_sg;
0130     dma->invalid = 1;
0131 }
0132 EXPORT_SYMBOL(set_dma_sg);
0133 
0134 /* Set DMA address
0135  *
0136  * Copy address to the structure, and set the invalid bit
0137  */
0138 void __set_dma_addr (unsigned int chan, void *addr)
0139 {
0140     dma_t *dma = dma_channel(chan);
0141 
0142     if (dma->active)
0143         pr_err("dma%d: altering DMA address while DMA active\n", chan);
0144 
0145     dma->sg = NULL;
0146     dma->addr = addr;
0147     dma->invalid = 1;
0148 }
0149 EXPORT_SYMBOL(__set_dma_addr);
0150 
0151 /* Set DMA byte count
0152  *
0153  * Copy address to the structure, and set the invalid bit
0154  */
0155 void set_dma_count (unsigned int chan, unsigned long count)
0156 {
0157     dma_t *dma = dma_channel(chan);
0158 
0159     if (dma->active)
0160         pr_err("dma%d: altering DMA count while DMA active\n", chan);
0161 
0162     dma->sg = NULL;
0163     dma->count = count;
0164     dma->invalid = 1;
0165 }
0166 EXPORT_SYMBOL(set_dma_count);
0167 
0168 /* Set DMA direction mode
0169  */
0170 void set_dma_mode (unsigned int chan, unsigned int mode)
0171 {
0172     dma_t *dma = dma_channel(chan);
0173 
0174     if (dma->active)
0175         pr_err("dma%d: altering DMA mode while DMA active\n", chan);
0176 
0177     dma->dma_mode = mode;
0178     dma->invalid = 1;
0179 }
0180 EXPORT_SYMBOL(set_dma_mode);
0181 
0182 /* Enable DMA channel
0183  */
0184 void enable_dma (unsigned int chan)
0185 {
0186     dma_t *dma = dma_channel(chan);
0187 
0188     if (!dma->lock)
0189         goto free_dma;
0190 
0191     if (dma->active == 0) {
0192         dma->active = 1;
0193         dma->d_ops->enable(chan, dma);
0194     }
0195     return;
0196 
0197 free_dma:
0198     pr_err("dma%d: trying to enable free DMA\n", chan);
0199     BUG();
0200 }
0201 EXPORT_SYMBOL(enable_dma);
0202 
0203 /* Disable DMA channel
0204  */
0205 void disable_dma (unsigned int chan)
0206 {
0207     dma_t *dma = dma_channel(chan);
0208 
0209     if (!dma->lock)
0210         goto free_dma;
0211 
0212     if (dma->active == 1) {
0213         dma->active = 0;
0214         dma->d_ops->disable(chan, dma);
0215     }
0216     return;
0217 
0218 free_dma:
0219     pr_err("dma%d: trying to disable free DMA\n", chan);
0220     BUG();
0221 }
0222 EXPORT_SYMBOL(disable_dma);
0223 
0224 /*
0225  * Is the specified DMA channel active?
0226  */
0227 int dma_channel_active(unsigned int chan)
0228 {
0229     dma_t *dma = dma_channel(chan);
0230     return dma->active;
0231 }
0232 EXPORT_SYMBOL(dma_channel_active);
0233 
0234 void set_dma_page(unsigned int chan, char pagenr)
0235 {
0236     pr_err("dma%d: trying to set_dma_page\n", chan);
0237 }
0238 EXPORT_SYMBOL(set_dma_page);
0239 
0240 void set_dma_speed(unsigned int chan, int cycle_ns)
0241 {
0242     dma_t *dma = dma_channel(chan);
0243     int ret = 0;
0244 
0245     if (dma->d_ops->setspeed)
0246         ret = dma->d_ops->setspeed(chan, dma, cycle_ns);
0247     dma->speed = ret;
0248 }
0249 EXPORT_SYMBOL(set_dma_speed);
0250 
0251 int get_dma_residue(unsigned int chan)
0252 {
0253     dma_t *dma = dma_channel(chan);
0254     int ret = 0;
0255 
0256     if (dma->d_ops->residue)
0257         ret = dma->d_ops->residue(chan, dma);
0258 
0259     return ret;
0260 }
0261 EXPORT_SYMBOL(get_dma_residue);
0262 
0263 #ifdef CONFIG_PROC_FS
0264 static int proc_dma_show(struct seq_file *m, void *v)
0265 {
0266     int i;
0267 
0268     for (i = 0 ; i < MAX_DMA_CHANNELS ; i++) {
0269         dma_t *dma = dma_channel(i);
0270         if (dma && dma->lock)
0271             seq_printf(m, "%2d: %s\n", i, dma->device_id);
0272     }
0273     return 0;
0274 }
0275 
0276 static int __init proc_dma_init(void)
0277 {
0278     proc_create_single("dma", 0, NULL, proc_dma_show);
0279     return 0;
0280 }
0281 
0282 __initcall(proc_dma_init);
0283 #endif