1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * arch/arm/plat-spear/pl080.c 4 * 5 * DMAC pl080 definitions for SPEAr platform 6 * 7 * Copyright (C) 2012 ST Microelectronics 8 * Viresh Kumar <vireshk@kernel.org> 9 */ 10 11 #include <linux/amba/pl08x.h> 12 #include <linux/amba/bus.h> 13 #include <linux/bug.h> 14 #include <linux/err.h> 15 #include <linux/io.h> 16 #include <linux/spinlock_types.h> 17 #include "spear.h" 18 #include "misc_regs.h" 19 #include "pl080.h" 20 21 static spinlock_t lock = __SPIN_LOCK_UNLOCKED(x); 22 23 struct { 24 unsigned char busy; 25 unsigned char val; 26 } signals[16] = {{0, 0}, }; 27 28 int pl080_get_signal(const struct pl08x_channel_data *cd) 29 { 30 unsigned int signal = cd->min_signal, val; 31 unsigned long flags; 32 33 spin_lock_irqsave(&lock, flags); 34 35 /* Return if signal is already acquired by somebody else */ 36 if (signals[signal].busy && 37 (signals[signal].val != cd->muxval)) { 38 spin_unlock_irqrestore(&lock, flags); 39 return -EBUSY; 40 } 41 42 /* If acquiring for the first time, configure it */ 43 if (!signals[signal].busy) { 44 val = readl(DMA_CHN_CFG); 45 46 /* 47 * Each request line has two bits in DMA_CHN_CFG register. To 48 * goto the bits of current request line, do left shift of 49 * value by 2 * signal number. 50 */ 51 val &= ~(0x3 << (signal * 2)); 52 val |= cd->muxval << (signal * 2); 53 writel(val, DMA_CHN_CFG); 54 } 55 56 signals[signal].busy++; 57 signals[signal].val = cd->muxval; 58 spin_unlock_irqrestore(&lock, flags); 59 60 return signal; 61 } 62 63 void pl080_put_signal(const struct pl08x_channel_data *cd, int signal) 64 { 65 unsigned long flags; 66 67 spin_lock_irqsave(&lock, flags); 68 69 /* if signal is not used */ 70 if (!signals[signal].busy) 71 BUG(); 72 73 signals[signal].busy--; 74 75 spin_unlock_irqrestore(&lock, flags); 76 } 77