pl080.c 1.6 KB

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