Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * arch/arm/plat-spear/pl080.c
0004  *
0005  * DMAC pl080 definitions for SPEAr platform
0006  *
0007  * Copyright (C) 2012 ST Microelectronics
0008  * Viresh Kumar <vireshk@kernel.org>
0009  */
0010 
0011 #include <linux/amba/pl08x.h>
0012 #include <linux/amba/bus.h>
0013 #include <linux/bug.h>
0014 #include <linux/err.h>
0015 #include <linux/io.h>
0016 #include <linux/spinlock_types.h>
0017 #include "spear.h"
0018 #include "misc_regs.h"
0019 
0020 static spinlock_t lock = __SPIN_LOCK_UNLOCKED(x);
0021 
0022 struct {
0023     unsigned char busy;
0024     unsigned char val;
0025 } signals[16] = {{0, 0}, };
0026 
0027 int pl080_get_signal(const struct pl08x_channel_data *cd)
0028 {
0029     unsigned int signal = cd->min_signal, val;
0030     unsigned long flags;
0031 
0032     spin_lock_irqsave(&lock, flags);
0033 
0034     /* Return if signal is already acquired by somebody else */
0035     if (signals[signal].busy &&
0036             (signals[signal].val != cd->muxval)) {
0037         spin_unlock_irqrestore(&lock, flags);
0038         return -EBUSY;
0039     }
0040 
0041     /* If acquiring for the first time, configure it */
0042     if (!signals[signal].busy) {
0043         val = readl(DMA_CHN_CFG);
0044 
0045         /*
0046          * Each request line has two bits in DMA_CHN_CFG register. To
0047          * goto the bits of current request line, do left shift of
0048          * value by 2 * signal number.
0049          */
0050         val &= ~(0x3 << (signal * 2));
0051         val |= cd->muxval << (signal * 2);
0052         writel(val, DMA_CHN_CFG);
0053     }
0054 
0055     signals[signal].busy++;
0056     signals[signal].val = cd->muxval;
0057     spin_unlock_irqrestore(&lock, flags);
0058 
0059     return signal;
0060 }
0061 
0062 void pl080_put_signal(const struct pl08x_channel_data *cd, int signal)
0063 {
0064     unsigned long flags;
0065 
0066     spin_lock_irqsave(&lock, flags);
0067 
0068     /* if signal is not used */
0069     if (!signals[signal].busy)
0070         BUG();
0071 
0072     signals[signal].busy--;
0073 
0074     spin_unlock_irqrestore(&lock, flags);
0075 }