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