io.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /* $Id: io.c,v 1.5 2004/02/22 23:08:43 kkojima Exp $
  2. *
  3. * linux/arch/sh/kernel/io_se.c
  4. *
  5. * Copyright (C) 2000 Kazumoto Kojima
  6. *
  7. * I/O routine for Hitachi SolutionEngine.
  8. *
  9. */
  10. #include <linux/kernel.h>
  11. #include <linux/types.h>
  12. #include <asm/io.h>
  13. #include <asm/se/se.h>
  14. /* SH pcmcia io window base, start and end. */
  15. int sh_pcic_io_wbase = 0xb8400000;
  16. int sh_pcic_io_start;
  17. int sh_pcic_io_stop;
  18. int sh_pcic_io_type;
  19. int sh_pcic_io_dummy;
  20. static inline void delay(void)
  21. {
  22. ctrl_inw(0xa0000000);
  23. }
  24. /* MS7750 requires special versions of in*, out* routines, since
  25. PC-like io ports are located at upper half byte of 16-bit word which
  26. can be accessed only with 16-bit wide. */
  27. static inline volatile __u16 *
  28. port2adr(unsigned int port)
  29. {
  30. if (port >= 0x2000)
  31. return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
  32. else if (port >= 0x1000)
  33. return (volatile __u16 *) (PA_83902 + (port << 1));
  34. else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
  35. return (volatile __u16 *) (sh_pcic_io_wbase + (port &~ 1));
  36. else
  37. return (volatile __u16 *) (PA_SUPERIO + (port << 1));
  38. }
  39. static inline int
  40. shifted_port(unsigned long port)
  41. {
  42. /* For IDE registers, value is not shifted */
  43. if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
  44. return 0;
  45. else
  46. return 1;
  47. }
  48. #define maybebadio(name,port) \
  49. printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
  50. #name, (port), (__u32) __builtin_return_address(0))
  51. unsigned char se_inb(unsigned long port)
  52. {
  53. if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
  54. return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
  55. else if (shifted_port(port))
  56. return (*port2adr(port) >> 8);
  57. else
  58. return (*port2adr(port))&0xff;
  59. }
  60. unsigned char se_inb_p(unsigned long port)
  61. {
  62. unsigned long v;
  63. if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
  64. v = *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
  65. else if (shifted_port(port))
  66. v = (*port2adr(port) >> 8);
  67. else
  68. v = (*port2adr(port))&0xff;
  69. delay();
  70. return v;
  71. }
  72. unsigned short se_inw(unsigned long port)
  73. {
  74. if (port >= 0x2000 ||
  75. (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
  76. return *port2adr(port);
  77. else
  78. maybebadio(inw, port);
  79. return 0;
  80. }
  81. unsigned int se_inl(unsigned long port)
  82. {
  83. maybebadio(inl, port);
  84. return 0;
  85. }
  86. void se_outb(unsigned char value, unsigned long port)
  87. {
  88. if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
  89. *(__u8 *)(sh_pcic_io_wbase + port) = value;
  90. else if (shifted_port(port))
  91. *(port2adr(port)) = value << 8;
  92. else
  93. *(port2adr(port)) = value;
  94. }
  95. void se_outb_p(unsigned char value, unsigned long port)
  96. {
  97. if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
  98. *(__u8 *)(sh_pcic_io_wbase + port) = value;
  99. else if (shifted_port(port))
  100. *(port2adr(port)) = value << 8;
  101. else
  102. *(port2adr(port)) = value;
  103. delay();
  104. }
  105. void se_outw(unsigned short value, unsigned long port)
  106. {
  107. if (port >= 0x2000 ||
  108. (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
  109. *port2adr(port) = value;
  110. else
  111. maybebadio(outw, port);
  112. }
  113. void se_outl(unsigned int value, unsigned long port)
  114. {
  115. maybebadio(outl, port);
  116. }
  117. void se_insb(unsigned long port, void *addr, unsigned long count)
  118. {
  119. volatile __u16 *p = port2adr(port);
  120. __u8 *ap = addr;
  121. if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
  122. volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + 0x40000 + port);
  123. while (count--)
  124. *ap++ = *bp;
  125. } else if (shifted_port(port)) {
  126. while (count--)
  127. *ap++ = *p >> 8;
  128. } else {
  129. while (count--)
  130. *ap++ = *p;
  131. }
  132. }
  133. void se_insw(unsigned long port, void *addr, unsigned long count)
  134. {
  135. volatile __u16 *p = port2adr(port);
  136. __u16 *ap = addr;
  137. while (count--)
  138. *ap++ = *p;
  139. }
  140. void se_insl(unsigned long port, void *addr, unsigned long count)
  141. {
  142. maybebadio(insl, port);
  143. }
  144. void se_outsb(unsigned long port, const void *addr, unsigned long count)
  145. {
  146. volatile __u16 *p = port2adr(port);
  147. const __u8 *ap = addr;
  148. if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
  149. volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + port);
  150. while (count--)
  151. *bp = *ap++;
  152. } else if (shifted_port(port)) {
  153. while (count--)
  154. *p = *ap++ << 8;
  155. } else {
  156. while (count--)
  157. *p = *ap++;
  158. }
  159. }
  160. void se_outsw(unsigned long port, const void *addr, unsigned long count)
  161. {
  162. volatile __u16 *p = port2adr(port);
  163. const __u16 *ap = addr;
  164. while (count--)
  165. *p = *ap++;
  166. }
  167. void se_outsl(unsigned long port, const void *addr, unsigned long count)
  168. {
  169. maybebadio(outsw, port);
  170. }
  171. /* Map ISA bus address to the real address. Only for PCMCIA. */
  172. /* ISA page descriptor. */
  173. static __u32 sh_isa_memmap[256];
  174. static int
  175. sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
  176. {
  177. int idx;
  178. if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
  179. return -1;
  180. idx = start >> 12;
  181. sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
  182. #if 0
  183. printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
  184. start, length, offset, idx, sh_isa_memmap[idx]);
  185. #endif
  186. return 0;
  187. }
  188. unsigned long
  189. se_isa_port2addr(unsigned long offset)
  190. {
  191. int idx;
  192. idx = (offset >> 12) & 0xff;
  193. offset &= 0xfff;
  194. return sh_isa_memmap[idx] + offset;
  195. }