ops-ddb5074.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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. if (slot_num == 5)
  58. slot_num = 14;
  59. } else {
  60. if (slot_num == 5)
  61. return DDB_BASE + DDB_PCI_BASE;
  62. }
  63. /* minimum pdar (window) size is 2MB */
  64. db_assert(swap->config_size >= (2 << 20));
  65. db_assert(slot_num < (1 << 5));
  66. db_assert(bus < (1 << 8));
  67. /* backup registers */
  68. swap->pdar_backup = ddb_in32(swap->pdar);
  69. swap->pmr_backup = ddb_in32(swap->pmr);
  70. /* set the pdar (pci window) register */
  71. ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */
  72. 0, /* not on local memory bus */
  73. 0); /* not visible from PCI bus (N/A) */
  74. /*
  75. * calcuate the absolute pci config addr;
  76. * according to the spec, we start scanning from adr:11 (0x800)
  77. */
  78. if (bus == 0) {
  79. /* type 0 config */
  80. pci_addr = 0x00040000 << slot_num;
  81. } else {
  82. /* type 1 config */
  83. pci_addr = 0x00040000 << slot_num;
  84. panic
  85. ("ddb_access_config_base: we don't support type 1 config Yet");
  86. }
  87. /*
  88. * if pci_addr is less than pci config window size, we set
  89. * pciinit_offset to 0 and adjust the virt_address.
  90. * Otherwise we will try to adjust pciinit_offset.
  91. */
  92. if (pci_addr < swap->config_size) {
  93. virt_addr = KSEG1ADDR(swap->config_base + pci_addr);
  94. pciinit_offset = 0;
  95. } else {
  96. db_assert((pci_addr & (swap->config_size - 1)) == 0);
  97. virt_addr = KSEG1ADDR(swap->config_base);
  98. pciinit_offset = pci_addr;
  99. }
  100. /* set the pmr register */
  101. option = DDB_PCI_ACCESS_32;
  102. if (bus != 0)
  103. option |= DDB_PCI_CFGTYPE1;
  104. ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option);
  105. return virt_addr;
  106. }
  107. static inline void ddb_close_config_base(struct pci_config_swap *swap)
  108. {
  109. ddb_out32(swap->pdar, swap->pdar_backup);
  110. ddb_out32(swap->pmr, swap->pmr_backup);
  111. }
  112. static int read_config_dword(struct pci_config_swap *swap,
  113. struct pci_dev *dev, u32 where, u32 * val)
  114. {
  115. u32 bus, slot_num, func_num;
  116. u32 base;
  117. db_assert((where & 3) == 0);
  118. db_assert(where < (1 << 8));
  119. /* check if the bus is top-level */
  120. if (dev->bus->parent != NULL) {
  121. bus = dev->bus->number;
  122. db_assert(bus != 0);
  123. } else {
  124. bus = 0;
  125. }
  126. slot_num = PCI_SLOT(dev->devfn);
  127. func_num = PCI_FUNC(dev->devfn);
  128. base = ddb_access_config_base(swap, bus, slot_num);
  129. *val = *(volatile u32 *) (base + (func_num << 8) + where);
  130. ddb_close_config_base(swap);
  131. return PCIBIOS_SUCCESSFUL;
  132. }
  133. static int read_config_word(struct pci_config_swap *swap,
  134. struct pci_dev *dev, u32 where, u16 * val)
  135. {
  136. int status;
  137. u32 result;
  138. db_assert((where & 1) == 0);
  139. status = read_config_dword(swap, dev, where & ~3, &result);
  140. if (where & 2)
  141. result >>= 16;
  142. *val = result & 0xffff;
  143. return status;
  144. }
  145. static int read_config_byte(struct pci_config_swap *swap,
  146. struct pci_dev *dev, u32 where, u8 * val)
  147. {
  148. int status;
  149. u32 result;
  150. status = read_config_dword(swap, dev, where & ~3, &result);
  151. if (where & 1)
  152. result >>= 8;
  153. if (where & 2)
  154. result >>= 16;
  155. *val = result & 0xff;
  156. return status;
  157. }
  158. static int write_config_dword(struct pci_config_swap *swap,
  159. struct pci_dev *dev, u32 where, u32 val)
  160. {
  161. u32 bus, slot_num, func_num;
  162. u32 base;
  163. db_assert((where & 3) == 0);
  164. db_assert(where < (1 << 8));
  165. /* check if the bus is top-level */
  166. if (dev->bus->parent != NULL) {
  167. bus = dev->bus->number;
  168. db_assert(bus != 0);
  169. } else {
  170. bus = 0;
  171. }
  172. slot_num = PCI_SLOT(dev->devfn);
  173. func_num = PCI_FUNC(dev->devfn);
  174. base = ddb_access_config_base(swap, bus, slot_num);
  175. *(volatile u32 *) (base + (func_num << 8) + where) = val;
  176. ddb_close_config_base(swap);
  177. return PCIBIOS_SUCCESSFUL;
  178. }
  179. static int write_config_word(struct pci_config_swap *swap,
  180. struct pci_dev *dev, u32 where, u16 val)
  181. {
  182. int status, shift = 0;
  183. u32 result;
  184. db_assert((where & 1) == 0);
  185. status = read_config_dword(swap, dev, where & ~3, &result);
  186. if (status != PCIBIOS_SUCCESSFUL)
  187. return status;
  188. if (where & 2)
  189. shift += 16;
  190. result &= ~(0xffff << shift);
  191. result |= val << shift;
  192. return write_config_dword(swap, dev, where & ~3, result);
  193. }
  194. static int write_config_byte(struct pci_config_swap *swap,
  195. struct pci_dev *dev, u32 where, u8 val)
  196. {
  197. int status, shift = 0;
  198. u32 result;
  199. status = read_config_dword(swap, dev, where & ~3, &result);
  200. if (status != PCIBIOS_SUCCESSFUL)
  201. return status;
  202. if (where & 2)
  203. shift += 16;
  204. if (where & 1)
  205. shift += 8;
  206. result &= ~(0xff << shift);
  207. result |= val << shift;
  208. return write_config_dword(swap, dev, where & ~3, result);
  209. }
  210. #define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \
  211. static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \
  212. { \
  213. return rw##_config_##unitname(pciswap, \
  214. dev, \
  215. where, \
  216. val); \
  217. }
  218. MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap)
  219. MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap)
  220. MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap)
  221. MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap)
  222. MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap)
  223. MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap)
  224. struct pci_ops ddb5476_ext_pci_ops = {
  225. extpci_read_config_byte,
  226. extpci_read_config_word,
  227. extpci_read_config_dword,
  228. extpci_write_config_byte,
  229. extpci_write_config_word,
  230. extpci_write_config_dword
  231. };