/arch/sh/cchips/hd6446x/hd64465/io.c

https://bitbucket.org/evzijst/gittest · C · 216 lines · 161 code · 39 blank · 16 comment · 30 complexity · ffccd166fee7a8a7da9b2c3f47126080 MD5 · raw file

  1. /*
  2. * $Id: io.c,v 1.4 2003/08/03 03:05:10 lethal Exp $
  3. * by Greg Banks <gbanks@pocketpenguins.com>
  4. * (c) 2000 PocketPenguins Inc
  5. *
  6. * Derived from io_hd64461.c, which bore the message:
  7. * Copyright (C) 2000 YAEGASHI Takeshi
  8. *
  9. * Typical I/O routines for HD64465 system.
  10. */
  11. #include <linux/config.h>
  12. #include <linux/kernel.h>
  13. #include <linux/module.h>
  14. #include <asm/io.h>
  15. #include <asm/hd64465/hd64465.h>
  16. #define HD64465_DEBUG 0
  17. #if HD64465_DEBUG
  18. #define DPRINTK(args...) printk(args)
  19. #define DIPRINTK(n, args...) if (hd64465_io_debug>(n)) printk(args)
  20. #else
  21. #define DPRINTK(args...)
  22. #define DIPRINTK(n, args...)
  23. #endif
  24. /* This is a hack suitable only for debugging IO port problems */
  25. int hd64465_io_debug;
  26. EXPORT_SYMBOL(hd64465_io_debug);
  27. /* Low iomap maps port 0-1K to addresses in 8byte chunks */
  28. #define HD64465_IOMAP_LO_THRESH 0x400
  29. #define HD64465_IOMAP_LO_SHIFT 3
  30. #define HD64465_IOMAP_LO_MASK ((1<<HD64465_IOMAP_LO_SHIFT)-1)
  31. #define HD64465_IOMAP_LO_NMAP (HD64465_IOMAP_LO_THRESH>>HD64465_IOMAP_LO_SHIFT)
  32. static unsigned long hd64465_iomap_lo[HD64465_IOMAP_LO_NMAP];
  33. static unsigned char hd64465_iomap_lo_shift[HD64465_IOMAP_LO_NMAP];
  34. /* High iomap maps port 1K-64K to addresses in 1K chunks */
  35. #define HD64465_IOMAP_HI_THRESH 0x10000
  36. #define HD64465_IOMAP_HI_SHIFT 10
  37. #define HD64465_IOMAP_HI_MASK ((1<<HD64465_IOMAP_HI_SHIFT)-1)
  38. #define HD64465_IOMAP_HI_NMAP (HD64465_IOMAP_HI_THRESH>>HD64465_IOMAP_HI_SHIFT)
  39. static unsigned long hd64465_iomap_hi[HD64465_IOMAP_HI_NMAP];
  40. static unsigned char hd64465_iomap_hi_shift[HD64465_IOMAP_HI_NMAP];
  41. #ifndef MAX
  42. #define MAX(a,b) ((a)>(b)?(a):(b))
  43. #endif
  44. #define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x))
  45. void hd64465_port_map(unsigned short baseport, unsigned int nports,
  46. unsigned long addr, unsigned char shift)
  47. {
  48. unsigned int port, endport = baseport + nports;
  49. DPRINTK("hd64465_port_map(base=0x%04hx, n=0x%04hx, addr=0x%08lx,endport=0x%04x)\n",
  50. baseport, nports, addr,endport);
  51. for (port = baseport ;
  52. port < endport && port < HD64465_IOMAP_LO_THRESH ;
  53. port += (1<<HD64465_IOMAP_LO_SHIFT)) {
  54. DPRINTK(" maplo[0x%x] = 0x%08lx\n", port, addr);
  55. hd64465_iomap_lo[port>>HD64465_IOMAP_LO_SHIFT] = addr;
  56. hd64465_iomap_lo_shift[port>>HD64465_IOMAP_LO_SHIFT] = shift;
  57. addr += (1<<(HD64465_IOMAP_LO_SHIFT));
  58. }
  59. for (port = MAX(baseport, HD64465_IOMAP_LO_THRESH) ;
  60. port < endport && port < HD64465_IOMAP_HI_THRESH ;
  61. port += (1<<HD64465_IOMAP_HI_SHIFT)) {
  62. DPRINTK(" maphi[0x%x] = 0x%08lx\n", port, addr);
  63. hd64465_iomap_hi[port>>HD64465_IOMAP_HI_SHIFT] = addr;
  64. hd64465_iomap_hi_shift[port>>HD64465_IOMAP_HI_SHIFT] = shift;
  65. addr += (1<<(HD64465_IOMAP_HI_SHIFT));
  66. }
  67. }
  68. EXPORT_SYMBOL(hd64465_port_map);
  69. void hd64465_port_unmap(unsigned short baseport, unsigned int nports)
  70. {
  71. unsigned int port, endport = baseport + nports;
  72. DPRINTK("hd64465_port_unmap(base=0x%04hx, n=0x%04hx)\n",
  73. baseport, nports);
  74. for (port = baseport ;
  75. port < endport && port < HD64465_IOMAP_LO_THRESH ;
  76. port += (1<<HD64465_IOMAP_LO_SHIFT)) {
  77. hd64465_iomap_lo[port>>HD64465_IOMAP_LO_SHIFT] = 0;
  78. }
  79. for (port = MAX(baseport, HD64465_IOMAP_LO_THRESH) ;
  80. port < endport && port < HD64465_IOMAP_HI_THRESH ;
  81. port += (1<<HD64465_IOMAP_HI_SHIFT)) {
  82. hd64465_iomap_hi[port>>HD64465_IOMAP_HI_SHIFT] = 0;
  83. }
  84. }
  85. EXPORT_SYMBOL(hd64465_port_unmap);
  86. unsigned long hd64465_isa_port2addr(unsigned long port)
  87. {
  88. unsigned long addr = 0;
  89. unsigned char shift;
  90. /* handle remapping of low IO ports */
  91. if (port < HD64465_IOMAP_LO_THRESH) {
  92. addr = hd64465_iomap_lo[port >> HD64465_IOMAP_LO_SHIFT];
  93. shift = hd64465_iomap_lo_shift[port >> HD64465_IOMAP_LO_SHIFT];
  94. if (addr != 0)
  95. addr += (port & HD64465_IOMAP_LO_MASK) << shift;
  96. else
  97. printk(KERN_NOTICE "io_hd64465: access to un-mapped port %lx\n", port);
  98. } else if (port < HD64465_IOMAP_HI_THRESH) {
  99. addr = hd64465_iomap_hi[port >> HD64465_IOMAP_HI_SHIFT];
  100. shift = hd64465_iomap_hi_shift[port >> HD64465_IOMAP_HI_SHIFT];
  101. if (addr != 0)
  102. addr += (port & HD64465_IOMAP_HI_MASK) << shift;
  103. else
  104. printk(KERN_NOTICE "io_hd64465: access to un-mapped port %lx\n", port);
  105. }
  106. /* HD64465 internal devices (0xb0000000) */
  107. else if (port < 0x20000)
  108. addr = CONFIG_HD64465_IOBASE + port - 0x10000;
  109. /* Whole physical address space (0xa0000000) */
  110. else
  111. addr = P2SEGADDR(port);
  112. DIPRINTK(2, "PORT2ADDR(0x%08lx) = 0x%08lx\n", port, addr);
  113. return addr;
  114. }
  115. static inline void delay(void)
  116. {
  117. ctrl_inw(0xa0000000);
  118. }
  119. unsigned char hd64465_inb(unsigned long port)
  120. {
  121. unsigned long addr = PORT2ADDR(port);
  122. unsigned long b = (addr == 0 ? 0 : *(volatile unsigned char*)addr);
  123. DIPRINTK(0, "inb(%08lx) = %02x\n", addr, (unsigned)b);
  124. return b;
  125. }
  126. unsigned char hd64465_inb_p(unsigned long port)
  127. {
  128. unsigned long v;
  129. unsigned long addr = PORT2ADDR(port);
  130. v = (addr == 0 ? 0 : *(volatile unsigned char*)addr);
  131. delay();
  132. DIPRINTK(0, "inb_p(%08lx) = %02x\n", addr, (unsigned)v);
  133. return v;
  134. }
  135. unsigned short hd64465_inw(unsigned long port)
  136. {
  137. unsigned long addr = PORT2ADDR(port);
  138. unsigned long b = (addr == 0 ? 0 : *(volatile unsigned short*)addr);
  139. DIPRINTK(0, "inw(%08lx) = %04lx\n", addr, b);
  140. return b;
  141. }
  142. unsigned int hd64465_inl(unsigned long port)
  143. {
  144. unsigned long addr = PORT2ADDR(port);
  145. unsigned int b = (addr == 0 ? 0 : *(volatile unsigned long*)addr);
  146. DIPRINTK(0, "inl(%08lx) = %08x\n", addr, b);
  147. return b;
  148. }
  149. void hd64465_outb(unsigned char b, unsigned long port)
  150. {
  151. unsigned long addr = PORT2ADDR(port);
  152. DIPRINTK(0, "outb(%02x, %08lx)\n", (unsigned)b, addr);
  153. if (addr != 0)
  154. *(volatile unsigned char*)addr = b;
  155. }
  156. void hd64465_outb_p(unsigned char b, unsigned long port)
  157. {
  158. unsigned long addr = PORT2ADDR(port);
  159. DIPRINTK(0, "outb_p(%02x, %08lx)\n", (unsigned)b, addr);
  160. if (addr != 0)
  161. *(volatile unsigned char*)addr = b;
  162. delay();
  163. }
  164. void hd64465_outw(unsigned short b, unsigned long port)
  165. {
  166. unsigned long addr = PORT2ADDR(port);
  167. DIPRINTK(0, "outw(%04x, %08lx)\n", (unsigned)b, addr);
  168. if (addr != 0)
  169. *(volatile unsigned short*)addr = b;
  170. }
  171. void hd64465_outl(unsigned int b, unsigned long port)
  172. {
  173. unsigned long addr = PORT2ADDR(port);
  174. DIPRINTK(0, "outl(%08x, %08lx)\n", b, addr);
  175. if (addr != 0)
  176. *(volatile unsigned long*)addr = b;
  177. }