sead3-pic32-bus.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
  7. */
  8. #include <linux/delay.h>
  9. #include <linux/kernel.h>
  10. #include <linux/spinlock.h>
  11. #include <linux/io.h>
  12. #include <linux/errno.h>
  13. #define PIC32_NULL 0x00
  14. #define PIC32_RD 0x01
  15. #define PIC32_SYSRD 0x02
  16. #define PIC32_WR 0x10
  17. #define PIC32_SYSWR 0x20
  18. #define PIC32_IRQ_CLR 0x40
  19. #define PIC32_STATUS 0x80
  20. #define DELAY() udelay(100) /* FIXME: needed? */
  21. /* spinlock to ensure atomic access to PIC32 */
  22. static DEFINE_SPINLOCK(pic32_bus_lock);
  23. /* FIXME: io_remap these */
  24. static void __iomem *bus_xfer = (void __iomem *)0xbf000600;
  25. static void __iomem *bus_status = (void __iomem *)0xbf000060;
  26. static inline unsigned int ioready(void)
  27. {
  28. return readl(bus_status) & 1;
  29. }
  30. static inline void wait_ioready(void)
  31. {
  32. do { } while (!ioready());
  33. }
  34. static inline void wait_ioclear(void)
  35. {
  36. do { } while (ioready());
  37. }
  38. static inline void check_ioclear(void)
  39. {
  40. if (ioready()) {
  41. pr_debug("ioclear: initially busy\n");
  42. do {
  43. (void) readl(bus_xfer);
  44. DELAY();
  45. } while (ioready());
  46. pr_debug("ioclear: cleared busy\n");
  47. }
  48. }
  49. u32 pic32_bus_readl(u32 reg)
  50. {
  51. unsigned long flags;
  52. u32 status, val;
  53. spin_lock_irqsave(&pic32_bus_lock, flags);
  54. check_ioclear();
  55. writel((PIC32_RD << 24) | (reg & 0x00ffffff), bus_xfer);
  56. DELAY();
  57. wait_ioready();
  58. status = readl(bus_xfer);
  59. DELAY();
  60. val = readl(bus_xfer);
  61. wait_ioclear();
  62. pr_debug("pic32_bus_readl: *%x -> %x (status=%x)\n", reg, val, status);
  63. spin_unlock_irqrestore(&pic32_bus_lock, flags);
  64. return val;
  65. }
  66. void pic32_bus_writel(u32 val, u32 reg)
  67. {
  68. unsigned long flags;
  69. u32 status;
  70. spin_lock_irqsave(&pic32_bus_lock, flags);
  71. check_ioclear();
  72. writel((PIC32_WR << 24) | (reg & 0x00ffffff), bus_xfer);
  73. DELAY();
  74. writel(val, bus_xfer);
  75. DELAY();
  76. wait_ioready();
  77. status = readl(bus_xfer);
  78. wait_ioclear();
  79. pr_debug("pic32_bus_writel: *%x <- %x (status=%x)\n", reg, val, status);
  80. spin_unlock_irqrestore(&pic32_bus_lock, flags);
  81. }