ops-sni.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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. * SNI specific PCI support for RM200/RM300.
  7. *
  8. * Copyright (C) 1997 - 2000, 2003 Ralf Baechle <ralf@linux-mips.org>
  9. */
  10. #include <linux/kernel.h>
  11. #include <linux/pci.h>
  12. #include <linux/types.h>
  13. #include <asm/sni.h>
  14. /*
  15. * It seems that on the RM200 only lower 3 bits of the 5 bit PCI device
  16. * address are decoded. We therefore manually have to reject attempts at
  17. * reading outside this range. Being on the paranoid side we only do this
  18. * test for bus 0 and hope forwarding and decoding work properly for any
  19. * subordinated busses.
  20. *
  21. * ASIC PCI only supports type 1 config cycles.
  22. */
  23. static int set_config_address(unsigned int busno, unsigned int devfn, int reg)
  24. {
  25. if ((devfn > 255) || (reg > 255))
  26. return PCIBIOS_BAD_REGISTER_NUMBER;
  27. if (busno == 0 && devfn >= PCI_DEVFN(8, 0))
  28. return PCIBIOS_DEVICE_NOT_FOUND;
  29. *(volatile u32 *)PCIMT_CONFIG_ADDRESS =
  30. ((busno & 0xff) << 16) |
  31. ((devfn & 0xff) << 8) |
  32. (reg & 0xfc);
  33. return PCIBIOS_SUCCESSFUL;
  34. }
  35. static int pcimt_read(struct pci_bus *bus, unsigned int devfn, int reg,
  36. int size, u32 * val)
  37. {
  38. int res;
  39. if ((res = set_config_address(bus->number, devfn, reg)))
  40. return res;
  41. switch (size) {
  42. case 1:
  43. *val = inb(PCIMT_CONFIG_DATA + (reg & 3));
  44. break;
  45. case 2:
  46. *val = inw(PCIMT_CONFIG_DATA + (reg & 2));
  47. break;
  48. case 4:
  49. *val = inl(PCIMT_CONFIG_DATA);
  50. break;
  51. }
  52. return 0;
  53. }
  54. static int pcimt_write(struct pci_bus *bus, unsigned int devfn, int reg,
  55. int size, u32 val)
  56. {
  57. int res;
  58. if ((res = set_config_address(bus->number, devfn, reg)))
  59. return res;
  60. switch (size) {
  61. case 1:
  62. outb(val, PCIMT_CONFIG_DATA + (reg & 3));
  63. break;
  64. case 2:
  65. outw(val, PCIMT_CONFIG_DATA + (reg & 2));
  66. break;
  67. case 4:
  68. outl(val, PCIMT_CONFIG_DATA);
  69. break;
  70. }
  71. return 0;
  72. }
  73. struct pci_ops sni_pcimt_ops = {
  74. .read = pcimt_read,
  75. .write = pcimt_write,
  76. };
  77. static int pcit_set_config_address(unsigned int busno, unsigned int devfn, int reg)
  78. {
  79. if ((devfn > 255) || (reg > 255) || (busno > 255))
  80. return PCIBIOS_BAD_REGISTER_NUMBER;
  81. outl((1 << 31) | ((busno & 0xff) << 16) | ((devfn & 0xff) << 8) | (reg & 0xfc), 0xcf8);
  82. return PCIBIOS_SUCCESSFUL;
  83. }
  84. static int pcit_read(struct pci_bus *bus, unsigned int devfn, int reg,
  85. int size, u32 * val)
  86. {
  87. int res;
  88. /*
  89. * on bus 0 we need to check, whether there is a device answering
  90. * for the devfn by doing a config write and checking the result. If
  91. * we don't do it, we will get a data bus error
  92. */
  93. if (bus->number == 0) {
  94. pcit_set_config_address(0, 0, 0x68);
  95. outl(inl(0xcfc) | 0xc0000000, 0xcfc);
  96. if ((res = pcit_set_config_address(0, devfn, 0)))
  97. return res;
  98. outl(0xffffffff, 0xcfc);
  99. pcit_set_config_address(0, 0, 0x68);
  100. if (inl(0xcfc) & 0x100000)
  101. return PCIBIOS_DEVICE_NOT_FOUND;
  102. }
  103. if ((res = pcit_set_config_address(bus->number, devfn, reg)))
  104. return res;
  105. switch (size) {
  106. case 1:
  107. *val = inb(PCIMT_CONFIG_DATA + (reg & 3));
  108. break;
  109. case 2:
  110. *val = inw(PCIMT_CONFIG_DATA + (reg & 2));
  111. break;
  112. case 4:
  113. *val = inl(PCIMT_CONFIG_DATA);
  114. break;
  115. }
  116. return 0;
  117. }
  118. static int pcit_write(struct pci_bus *bus, unsigned int devfn, int reg,
  119. int size, u32 val)
  120. {
  121. int res;
  122. if ((res = pcit_set_config_address(bus->number, devfn, reg)))
  123. return res;
  124. switch (size) {
  125. case 1:
  126. outb(val, PCIMT_CONFIG_DATA + (reg & 3));
  127. break;
  128. case 2:
  129. outw(val, PCIMT_CONFIG_DATA + (reg & 2));
  130. break;
  131. case 4:
  132. outl(val, PCIMT_CONFIG_DATA);
  133. break;
  134. }
  135. return 0;
  136. }
  137. struct pci_ops sni_pcit_ops = {
  138. .read = pcit_read,
  139. .write = pcit_write,
  140. };