io.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * I/O string operations
  3. * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  4. * Copyright (C) 2006 IBM Corporation
  5. *
  6. * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
  7. * and Paul Mackerras.
  8. *
  9. * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
  10. * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
  11. *
  12. * Rewritten in C by Stephen Rothwell.
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public License
  16. * as published by the Free Software Foundation; either version
  17. * 2 of the License, or (at your option) any later version.
  18. */
  19. #include <linux/kernel.h>
  20. #include <linux/types.h>
  21. #include <linux/compiler.h>
  22. #include <linux/export.h>
  23. #include <asm/io.h>
  24. #include <asm/firmware.h>
  25. #include <asm/bug.h>
  26. /* See definition in io.h */
  27. bool isa_io_special;
  28. void _insb(const volatile u8 __iomem *port, void *buf, long count)
  29. {
  30. u8 *tbuf = buf;
  31. u8 tmp;
  32. if (unlikely(count <= 0))
  33. return;
  34. asm volatile("sync");
  35. do {
  36. tmp = *port;
  37. eieio();
  38. *tbuf++ = tmp;
  39. } while (--count != 0);
  40. asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
  41. }
  42. EXPORT_SYMBOL(_insb);
  43. void _outsb(volatile u8 __iomem *port, const void *buf, long count)
  44. {
  45. const u8 *tbuf = buf;
  46. if (unlikely(count <= 0))
  47. return;
  48. asm volatile("sync");
  49. do {
  50. *port = *tbuf++;
  51. } while (--count != 0);
  52. asm volatile("sync");
  53. }
  54. EXPORT_SYMBOL(_outsb);
  55. void _insw_ns(const volatile u16 __iomem *port, void *buf, long count)
  56. {
  57. u16 *tbuf = buf;
  58. u16 tmp;
  59. if (unlikely(count <= 0))
  60. return;
  61. asm volatile("sync");
  62. do {
  63. tmp = *port;
  64. eieio();
  65. *tbuf++ = tmp;
  66. } while (--count != 0);
  67. asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
  68. }
  69. EXPORT_SYMBOL(_insw_ns);
  70. void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count)
  71. {
  72. const u16 *tbuf = buf;
  73. if (unlikely(count <= 0))
  74. return;
  75. asm volatile("sync");
  76. do {
  77. *port = *tbuf++;
  78. } while (--count != 0);
  79. asm volatile("sync");
  80. }
  81. EXPORT_SYMBOL(_outsw_ns);
  82. void _insl_ns(const volatile u32 __iomem *port, void *buf, long count)
  83. {
  84. u32 *tbuf = buf;
  85. u32 tmp;
  86. if (unlikely(count <= 0))
  87. return;
  88. asm volatile("sync");
  89. do {
  90. tmp = *port;
  91. eieio();
  92. *tbuf++ = tmp;
  93. } while (--count != 0);
  94. asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
  95. }
  96. EXPORT_SYMBOL(_insl_ns);
  97. void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count)
  98. {
  99. const u32 *tbuf = buf;
  100. if (unlikely(count <= 0))
  101. return;
  102. asm volatile("sync");
  103. do {
  104. *port = *tbuf++;
  105. } while (--count != 0);
  106. asm volatile("sync");
  107. }
  108. EXPORT_SYMBOL(_outsl_ns);
  109. #define IO_CHECK_ALIGN(v,a) ((((unsigned long)(v)) & ((a) - 1)) == 0)
  110. notrace void
  111. _memset_io(volatile void __iomem *addr, int c, unsigned long n)
  112. {
  113. void *p = (void __force *)addr;
  114. u32 lc = c;
  115. lc |= lc << 8;
  116. lc |= lc << 16;
  117. __asm__ __volatile__ ("sync" : : : "memory");
  118. while(n && !IO_CHECK_ALIGN(p, 4)) {
  119. *((volatile u8 *)p) = c;
  120. p++;
  121. n--;
  122. }
  123. while(n >= 4) {
  124. *((volatile u32 *)p) = lc;
  125. p += 4;
  126. n -= 4;
  127. }
  128. while(n) {
  129. *((volatile u8 *)p) = c;
  130. p++;
  131. n--;
  132. }
  133. __asm__ __volatile__ ("sync" : : : "memory");
  134. }
  135. EXPORT_SYMBOL(_memset_io);
  136. void _memcpy_fromio(void *dest, const volatile void __iomem *src,
  137. unsigned long n)
  138. {
  139. void *vsrc = (void __force *) src;
  140. __asm__ __volatile__ ("sync" : : : "memory");
  141. while(n && (!IO_CHECK_ALIGN(vsrc, 4) || !IO_CHECK_ALIGN(dest, 4))) {
  142. *((u8 *)dest) = *((volatile u8 *)vsrc);
  143. eieio();
  144. vsrc++;
  145. dest++;
  146. n--;
  147. }
  148. while(n >= 4) {
  149. *((u32 *)dest) = *((volatile u32 *)vsrc);
  150. eieio();
  151. vsrc += 4;
  152. dest += 4;
  153. n -= 4;
  154. }
  155. while(n) {
  156. *((u8 *)dest) = *((volatile u8 *)vsrc);
  157. eieio();
  158. vsrc++;
  159. dest++;
  160. n--;
  161. }
  162. __asm__ __volatile__ ("sync" : : : "memory");
  163. }
  164. EXPORT_SYMBOL(_memcpy_fromio);
  165. void _memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n)
  166. {
  167. void *vdest = (void __force *) dest;
  168. __asm__ __volatile__ ("sync" : : : "memory");
  169. while(n && (!IO_CHECK_ALIGN(vdest, 4) || !IO_CHECK_ALIGN(src, 4))) {
  170. *((volatile u8 *)vdest) = *((u8 *)src);
  171. src++;
  172. vdest++;
  173. n--;
  174. }
  175. while(n >= 4) {
  176. *((volatile u32 *)vdest) = *((volatile u32 *)src);
  177. src += 4;
  178. vdest += 4;
  179. n-=4;
  180. }
  181. while(n) {
  182. *((volatile u8 *)vdest) = *((u8 *)src);
  183. src++;
  184. vdest++;
  185. n--;
  186. }
  187. __asm__ __volatile__ ("sync" : : : "memory");
  188. }
  189. EXPORT_SYMBOL(_memcpy_toio);