You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

arm_io.h 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #ifndef _IPXE_ARM_IO_H
  2. #define _IPXE_ARM_IO_H
  3. /** @file
  4. *
  5. * iPXE I/O API for ARM
  6. *
  7. */
  8. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  9. #ifdef IOAPI_ARM
  10. #define IOAPI_PREFIX_arm
  11. #else
  12. #define IOAPI_PREFIX_arm __arm_
  13. #endif
  14. /*
  15. * Memory space mappings
  16. *
  17. */
  18. /** Page shift */
  19. #define PAGE_SHIFT 12
  20. /*
  21. * Physical<->Bus address mappings
  22. *
  23. */
  24. static inline __always_inline unsigned long
  25. IOAPI_INLINE ( arm, phys_to_bus ) ( unsigned long phys_addr ) {
  26. return phys_addr;
  27. }
  28. static inline __always_inline unsigned long
  29. IOAPI_INLINE ( arm, bus_to_phys ) ( unsigned long bus_addr ) {
  30. return bus_addr;
  31. }
  32. /*
  33. * MMIO reads and writes up to native word size
  34. *
  35. */
  36. #define ARM_READX( _suffix, _type, _insn_suffix, _reg_prefix ) \
  37. static inline __always_inline _type \
  38. IOAPI_INLINE ( arm, read ## _suffix ) ( volatile _type *io_addr ) { \
  39. _type data; \
  40. __asm__ __volatile__ ( "ldr" _insn_suffix " %" _reg_prefix "0, %1" \
  41. : "=r" ( data ) : "Qo" ( *io_addr ) ); \
  42. return data; \
  43. }
  44. #ifdef __aarch64__
  45. ARM_READX ( b, uint8_t, "b", "w" );
  46. ARM_READX ( w, uint16_t, "h", "w" );
  47. ARM_READX ( l, uint32_t, "", "w" );
  48. ARM_READX ( q, uint64_t, "", "" );
  49. #else
  50. ARM_READX ( b, uint8_t, "b", "" );
  51. ARM_READX ( w, uint16_t, "h", "" );
  52. ARM_READX ( l, uint32_t, "", "" );
  53. #endif
  54. #define ARM_WRITEX( _suffix, _type, _insn_suffix, _reg_prefix ) \
  55. static inline __always_inline void \
  56. IOAPI_INLINE ( arm, write ## _suffix ) ( _type data, \
  57. volatile _type *io_addr ) { \
  58. __asm__ __volatile__ ( "str" _insn_suffix " %" _reg_prefix "0, %1" \
  59. : : "r" ( data ), "Qo" ( *io_addr ) ); \
  60. }
  61. #ifdef __aarch64__
  62. ARM_WRITEX ( b, uint8_t, "b", "w" );
  63. ARM_WRITEX ( w, uint16_t, "h", "w" );
  64. ARM_WRITEX ( l, uint32_t, "", "w" );
  65. ARM_WRITEX ( q, uint64_t, "", "" );
  66. #else
  67. ARM_WRITEX ( b, uint8_t, "b", "" );
  68. ARM_WRITEX ( w, uint16_t, "h", "" );
  69. ARM_WRITEX ( l, uint32_t, "", "" );
  70. #endif
  71. /*
  72. * Dummy PIO reads and writes up to 32 bits
  73. *
  74. * There is no common standard for I/O-space access for ARM, and
  75. * non-MMIO peripherals are vanishingly rare. Provide dummy
  76. * implementations that will allow code to link and should cause
  77. * drivers to simply fail to detect hardware at runtime.
  78. *
  79. */
  80. #define ARM_INX( _suffix, _type ) \
  81. static inline __always_inline _type \
  82. IOAPI_INLINE ( arm, in ## _suffix ) ( volatile _type *io_addr __unused) { \
  83. return ~( (_type) 0 ); \
  84. } \
  85. static inline __always_inline void \
  86. IOAPI_INLINE ( arm, ins ## _suffix ) ( volatile _type *io_addr __unused, \
  87. _type *data, unsigned int count ) { \
  88. memset ( data, 0xff, count * sizeof ( *data ) ); \
  89. }
  90. ARM_INX ( b, uint8_t );
  91. ARM_INX ( w, uint16_t );
  92. ARM_INX ( l, uint32_t );
  93. #define ARM_OUTX( _suffix, _type ) \
  94. static inline __always_inline void \
  95. IOAPI_INLINE ( arm, out ## _suffix ) ( _type data __unused, \
  96. volatile _type *io_addr __unused ) { \
  97. /* Do nothing */ \
  98. } \
  99. static inline __always_inline void \
  100. IOAPI_INLINE ( arm, outs ## _suffix ) ( volatile _type *io_addr __unused, \
  101. const _type *data __unused, \
  102. unsigned int count __unused ) { \
  103. /* Do nothing */ \
  104. }
  105. ARM_OUTX ( b, uint8_t );
  106. ARM_OUTX ( w, uint16_t );
  107. ARM_OUTX ( l, uint32_t );
  108. /*
  109. * Slow down I/O
  110. *
  111. */
  112. static inline __always_inline void
  113. IOAPI_INLINE ( arm, iodelay ) ( void ) {
  114. /* Nothing to do */
  115. }
  116. /*
  117. * Memory barrier
  118. *
  119. */
  120. static inline __always_inline void
  121. IOAPI_INLINE ( arm, mb ) ( void ) {
  122. #ifdef __aarch64__
  123. __asm__ __volatile__ ( "dmb sy" );
  124. #else
  125. __asm__ __volatile__ ( "dmb" );
  126. #endif
  127. }
  128. #endif /* _IPXE_ARM_IO_H */