ops-ddb5476.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /*
  2. * Copyright 2001 MontaVista Software Inc.
  3. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
  4. *
  5. * arch/mips/ddb5xxx/ddb5476/pci_ops.c
  6. * Define the pci_ops for DB5477.
  7. *
  8. * Much of the code is derived from the original DDB5074 port by
  9. * Geert Uytterhoeven <geert@sonycom.com>
  10. *
  11. * This program is free software; you can redistribute it and/or modify it
  12. * under the terms of the GNU General Public License as published by the
  13. * Free Software Foundation; either version 2 of the License, or (at your
  14. * option) any later version.
  15. *
  16. */
  17. #include <linux/pci.h>
  18. #include <linux/kernel.h>
  19. #include <linux/types.h>
  20. #include <asm/addrspace.h>
  21. #include <asm/debug.h>
  22. #include <asm/ddb5xxx/ddb5xxx.h>
  23. /*
  24. * config_swap structure records what set of pdar/pmr are used
  25. * to access pci config space. It also provides a place hold the
  26. * original values for future restoring.
  27. */
  28. struct pci_config_swap {
  29. u32 pdar;
  30. u32 pmr;
  31. u32 config_base;
  32. u32 config_size;
  33. u32 pdar_backup;
  34. u32 pmr_backup;
  35. };
  36. /*
  37. * On DDB5476, we have one set of swap registers
  38. */
  39. struct pci_config_swap ext_pci_swap = {
  40. DDB_PCIW0,
  41. DDB_PCIINIT0,
  42. DDB_PCI_CONFIG_BASE,
  43. DDB_PCI_CONFIG_SIZE
  44. };
  45. static int pci_config_workaround = 1;
  46. /*
  47. * access config space
  48. */
  49. static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus, /* 0 means top level bus */
  50. u32 slot_num)
  51. {
  52. u32 pci_addr = 0;
  53. u32 pciinit_offset = 0;
  54. u32 virt_addr = swap->config_base;
  55. u32 option;
  56. if (pci_config_workaround) {
  57. /* [jsun] work around Vrc5476 controller itself, returnning
  58. * slot 0 essentially makes vrc5476 invisible
  59. */
  60. if (slot_num == 12)
  61. slot_num = 0;
  62. #if 0
  63. /* BUG : skip P2P bridge for now */
  64. if (slot_num == 5)
  65. slot_num = 0;
  66. #endif
  67. } else {
  68. /* now we have to be hornest, returning the true
  69. * PCI config headers for vrc5476
  70. */
  71. if (slot_num == 12) {
  72. swap->pdar_backup = ddb_in32(swap->pdar);
  73. swap->pmr_backup = ddb_in32(swap->pmr);
  74. return DDB_BASE + DDB_PCI_BASE;
  75. }
  76. }
  77. /* minimum pdar (window) size is 2MB */
  78. db_assert(swap->config_size >= (2 << 20));
  79. db_assert(slot_num < (1 << 5));
  80. db_assert(bus < (1 << 8));
  81. /* backup registers */
  82. swap->pdar_backup = ddb_in32(swap->pdar);
  83. swap->pmr_backup = ddb_in32(swap->pmr);
  84. /* set the pdar (pci window) register */
  85. ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */
  86. 0, /* not on local memory bus */
  87. 0); /* not visible from PCI bus (N/A) */
  88. /*
  89. * calcuate the absolute pci config addr;
  90. * according to the spec, we start scanning from adr:11 (0x800)
  91. */
  92. if (bus == 0) {
  93. /* type 0 config */
  94. pci_addr = 0x800 << slot_num;
  95. } else {
  96. /* type 1 config */
  97. pci_addr = (bus << 16) | (slot_num << 11);
  98. /* panic("ddb_access_config_base: we don't support type 1 config Yet"); */
  99. }
  100. /*
  101. * if pci_addr is less than pci config window size, we set
  102. * pciinit_offset to 0 and adjust the virt_address.
  103. * Otherwise we will try to adjust pciinit_offset.
  104. */
  105. if (pci_addr < swap->config_size) {
  106. virt_addr = KSEG1ADDR(swap->config_base + pci_addr);
  107. pciinit_offset = 0;
  108. } else {
  109. db_assert((pci_addr & (swap->config_size - 1)) == 0);
  110. virt_addr = KSEG1ADDR(swap->config_base);
  111. pciinit_offset = pci_addr;
  112. }
  113. /* set the pmr register */
  114. option = DDB_PCI_ACCESS_32;
  115. if (bus != 0)
  116. option |= DDB_PCI_CFGTYPE1;
  117. ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option);
  118. return virt_addr;
  119. }
  120. static inline void ddb_close_config_base(struct pci_config_swap *swap)
  121. {
  122. ddb_out32(swap->pdar, swap->pdar_backup);
  123. ddb_out32(swap->pmr, swap->pmr_backup);
  124. }
  125. static int read_config_dword(struct pci_config_swap *swap,
  126. struct pci_dev *dev, u32 where, u32 * val)
  127. {
  128. u32 bus, slot_num, func_num;
  129. u32 base;
  130. db_assert((where & 3) == 0);
  131. db_assert(where < (1 << 8));
  132. /* check if the bus is top-level */
  133. if (dev->bus->parent != NULL) {
  134. bus = dev->bus->number;
  135. db_assert(bus != 0);
  136. } else {
  137. bus = 0;
  138. }
  139. slot_num = PCI_SLOT(dev->devfn);
  140. func_num = PCI_FUNC(dev->devfn);
  141. base = ddb_access_config_base(swap, bus, slot_num);
  142. *val = *(volatile u32 *) (base + (func_num << 8) + where);
  143. ddb_close_config_base(swap);
  144. return PCIBIOS_SUCCESSFUL;
  145. }
  146. static int read_config_word(struct pci_config_swap *swap,
  147. struct pci_dev *dev, u32 where, u16 * val)
  148. {
  149. int status;
  150. u32 result;
  151. db_assert((where & 1) == 0);
  152. status = read_config_dword(swap, dev, where & ~3, &result);
  153. if (where & 2)
  154. result >>= 16;
  155. *val = result & 0xffff;
  156. return status;
  157. }
  158. static int read_config_byte(struct pci_config_swap *swap,
  159. struct pci_dev *dev, u32 where, u8 * val)
  160. {
  161. int status;
  162. u32 result;
  163. status = read_config_dword(swap, dev, where & ~3, &result);
  164. if (where & 1)
  165. result >>= 8;
  166. if (where & 2)
  167. result >>= 16;
  168. *val = result & 0xff;
  169. return status;
  170. }
  171. static int write_config_dword(struct pci_config_swap *swap,
  172. struct pci_dev *dev, u32 where, u32 val)
  173. {
  174. u32 bus, slot_num, func_num;
  175. u32 base;
  176. db_assert((where & 3) == 0);
  177. db_assert(where < (1 << 8));
  178. /* check if the bus is top-level */
  179. if (dev->bus->parent != NULL) {
  180. bus = dev->bus->number;
  181. db_assert(bus != 0);
  182. } else {
  183. bus = 0;
  184. }
  185. slot_num = PCI_SLOT(dev->devfn);
  186. func_num = PCI_FUNC(dev->devfn);
  187. base = ddb_access_config_base(swap, bus, slot_num);
  188. *(volatile u32 *) (base + (func_num << 8) + where) = val;
  189. ddb_close_config_base(swap);
  190. return PCIBIOS_SUCCESSFUL;
  191. }
  192. static int write_config_word(struct pci_config_swap *swap,
  193. struct pci_dev *dev, u32 where, u16 val)
  194. {
  195. int status, shift = 0;
  196. u32 result;
  197. db_assert((where & 1) == 0);
  198. status = read_config_dword(swap, dev, where & ~3, &result);
  199. if (status != PCIBIOS_SUCCESSFUL)
  200. return status;
  201. if (where & 2)
  202. shift += 16;
  203. result &= ~(0xffff << shift);
  204. result |= val << shift;
  205. return write_config_dword(swap, dev, where & ~3, result);
  206. }
  207. static int write_config_byte(struct pci_config_swap *swap,
  208. struct pci_dev *dev, u32 where, u8 val)
  209. {
  210. int status, shift = 0;
  211. u32 result;
  212. status = read_config_dword(swap, dev, where & ~3, &result);
  213. if (status != PCIBIOS_SUCCESSFUL)
  214. return status;
  215. if (where & 2)
  216. shift += 16;
  217. if (where & 1)
  218. shift += 8;
  219. result &= ~(0xff << shift);
  220. result |= val << shift;
  221. return write_config_dword(swap, dev, where & ~3, result);
  222. }
  223. #define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \
  224. static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \
  225. { \
  226. return rw##_config_##unitname(pciswap, \
  227. dev, \
  228. where, \
  229. val); \
  230. }
  231. MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap)
  232. MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap)
  233. MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap)
  234. MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap)
  235. MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap)
  236. MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap)
  237. struct pci_ops ddb5476_ext_pci_ops = {
  238. extpci_read_config_byte,
  239. extpci_read_config_word,
  240. extpci_read_config_dword,
  241. extpci_write_config_byte,
  242. extpci_write_config_word,
  243. extpci_write_config_dword
  244. };