pl080.c 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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 <viresh.kumar@st.com>
  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. #include <linux/amba/pl08x.h>
  14. #include <linux/amba/bus.h>
  15. #include <linux/bug.h>
  16. #include <linux/err.h>
  17. #include <linux/io.h>
  18. #include <linux/spinlock_types.h>
  19. #include <mach/spear.h>
  20. #include <mach/misc_regs.h>
  21. static spinlock_t lock = __SPIN_LOCK_UNLOCKED(x);
  22. struct {
  23. unsigned char busy;
  24. unsigned char val;
  25. } signals[16] = {{0, 0}, };
  26. int pl080_get_signal(struct pl08x_dma_chan *ch)
  27. {
  28. const struct pl08x_channel_data *cd = ch->cd;
  29. unsigned int signal = cd->min_signal, val;
  30. unsigned long flags;
  31. spin_lock_irqsave(&lock, flags);
  32. /* Return if signal is already acquired by somebody else */
  33. if (signals[signal].busy &&
  34. (signals[signal].val != cd->muxval)) {
  35. spin_unlock_irqrestore(&lock, flags);
  36. return -EBUSY;
  37. }
  38. /* If acquiring for the first time, configure it */
  39. if (!signals[signal].busy) {
  40. val = readl(DMA_CHN_CFG);
  41. /*
  42. * Each request line has two bits in DMA_CHN_CFG register. To
  43. * goto the bits of current request line, do left shift of
  44. * value by 2 * signal number.
  45. */
  46. val &= ~(0x3 << (signal * 2));
  47. val |= cd->muxval << (signal * 2);
  48. writel(val, DMA_CHN_CFG);
  49. }
  50. signals[signal].busy++;
  51. signals[signal].val = cd->muxval;
  52. spin_unlock_irqrestore(&lock, flags);
  53. return signal;
  54. }
  55. void pl080_put_signal(struct pl08x_dma_chan *ch)
  56. {
  57. const struct pl08x_channel_data *cd = ch->cd;
  58. unsigned long flags;
  59. spin_lock_irqsave(&lock, flags);
  60. /* if signal is not used */
  61. if (!signals[cd->min_signal].busy)
  62. BUG();
  63. signals[cd->min_signal].busy--;
  64. spin_unlock_irqrestore(&lock, flags);
  65. }