ops-ddb5477.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /***********************************************************************
  2. * Copyright 2001 MontaVista Software Inc.
  3. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
  4. *
  5. * arch/mips/ddb5xxx/ddb5477/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. /*
  18. * DDB5477 has two PCI channels, external PCI and IOPIC (internal)
  19. * Therefore we provide two sets of pci_ops.
  20. */
  21. #include <linux/pci.h>
  22. #include <linux/kernel.h>
  23. #include <linux/types.h>
  24. #include <asm/addrspace.h>
  25. #include <asm/debug.h>
  26. #include <asm/ddb5xxx/ddb5xxx.h>
  27. /*
  28. * config_swap structure records what set of pdar/pmr are used
  29. * to access pci config space. It also provides a place hold the
  30. * original values for future restoring.
  31. */
  32. struct pci_config_swap {
  33. u32 pdar;
  34. u32 pmr;
  35. u32 config_base;
  36. u32 config_size;
  37. u32 pdar_backup;
  38. u32 pmr_backup;
  39. };
  40. /*
  41. * On DDB5477, we have two sets of swap registers, for ext PCI and IOPCI.
  42. */
  43. struct pci_config_swap ext_pci_swap = {
  44. DDB_PCIW0,
  45. DDB_PCIINIT00,
  46. DDB_PCI0_CONFIG_BASE,
  47. DDB_PCI0_CONFIG_SIZE
  48. };
  49. struct pci_config_swap io_pci_swap = {
  50. DDB_IOPCIW0,
  51. DDB_PCIINIT01,
  52. DDB_PCI1_CONFIG_BASE,
  53. DDB_PCI1_CONFIG_SIZE
  54. };
  55. /*
  56. * access config space
  57. */
  58. static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus, /* 0 means top level bus */
  59. u32 slot_num)
  60. {
  61. u32 pci_addr = 0;
  62. u32 pciinit_offset = 0;
  63. u32 virt_addr;
  64. u32 option;
  65. /* minimum pdar (window) size is 2MB */
  66. db_assert(swap->config_size >= (2 << 20));
  67. db_assert(slot_num < (1 << 5));
  68. db_assert(bus < (1 << 8));
  69. /* backup registers */
  70. swap->pdar_backup = ddb_in32(swap->pdar);
  71. swap->pmr_backup = ddb_in32(swap->pmr);
  72. /* set the pdar (pci window) register */
  73. ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */
  74. 0, /* not on local memory bus */
  75. 0); /* not visible from PCI bus (N/A) */
  76. /*
  77. * calcuate the absolute pci config addr;
  78. * according to the spec, we start scanning from adr:11 (0x800)
  79. */
  80. if (bus == 0) {
  81. /* type 0 config */
  82. pci_addr = 0x800 << slot_num;
  83. } else {
  84. /* type 1 config */
  85. pci_addr = (bus << 16) | (slot_num << 11);
  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_bus *bus, u32 devfn, u32 where,
  114. u32 * val)
  115. {
  116. u32 bus_num, slot_num, func_num;
  117. u32 base;
  118. db_assert((where & 3) == 0);
  119. db_assert(where < (1 << 8));
  120. /* check if the bus is top-level */
  121. if (bus->parent != NULL) {
  122. bus_num = bus->number;
  123. db_assert(bus_num != 0);
  124. } else {
  125. bus_num = 0;
  126. }
  127. slot_num = PCI_SLOT(devfn);
  128. func_num = PCI_FUNC(devfn);
  129. base = ddb_access_config_base(swap, bus_num, slot_num);
  130. *val = *(volatile u32 *) (base + (func_num << 8) + where);
  131. ddb_close_config_base(swap);
  132. return PCIBIOS_SUCCESSFUL;
  133. }
  134. static int read_config_word(struct pci_config_swap *swap,
  135. struct pci_bus *bus, u32 devfn, u32 where,
  136. u16 * val)
  137. {
  138. int status;
  139. u32 result;
  140. db_assert((where & 1) == 0);
  141. status = read_config_dword(swap, bus, devfn, where & ~3, &result);
  142. if (where & 2)
  143. result >>= 16;
  144. *val = result & 0xffff;
  145. return status;
  146. }
  147. static int read_config_byte(struct pci_config_swap *swap,
  148. struct pci_bus *bus, u32 devfn, u32 where,
  149. u8 * val)
  150. {
  151. int status;
  152. u32 result;
  153. status = read_config_dword(swap, bus, devfn, where & ~3, &result);
  154. if (where & 1)
  155. result >>= 8;
  156. if (where & 2)
  157. result >>= 16;
  158. *val = result & 0xff;
  159. return status;
  160. }
  161. static int write_config_dword(struct pci_config_swap *swap,
  162. struct pci_bus *bus, u32 devfn, u32 where,
  163. u32 val)
  164. {
  165. u32 bus_num, slot_num, func_num;
  166. u32 base;
  167. db_assert((where & 3) == 0);
  168. db_assert(where < (1 << 8));
  169. /* check if the bus is top-level */
  170. if (bus->parent != NULL) {
  171. bus_num = bus->number;
  172. db_assert(bus_num != 0);
  173. } else {
  174. bus_num = 0;
  175. }
  176. slot_num = PCI_SLOT(devfn);
  177. func_num = PCI_FUNC(devfn);
  178. base = ddb_access_config_base(swap, bus_num, slot_num);
  179. *(volatile u32 *) (base + (func_num << 8) + where) = val;
  180. ddb_close_config_base(swap);
  181. return PCIBIOS_SUCCESSFUL;
  182. }
  183. static int write_config_word(struct pci_config_swap *swap,
  184. struct pci_bus *bus, u32 devfn, u32 where, u16 val)
  185. {
  186. int status, shift = 0;
  187. u32 result;
  188. db_assert((where & 1) == 0);
  189. status = read_config_dword(swap, bus, devfn, where & ~3, &result);
  190. if (status != PCIBIOS_SUCCESSFUL)
  191. return status;
  192. if (where & 2)
  193. shift += 16;
  194. result &= ~(0xffff << shift);
  195. result |= val << shift;
  196. return write_config_dword(swap, bus, devfn, where & ~3, result);
  197. }
  198. static int write_config_byte(struct pci_config_swap *swap,
  199. struct pci_bus *bus, u32 devfn, u32 where, u8 val)
  200. {
  201. int status, shift = 0;
  202. u32 result;
  203. status = read_config_dword(swap, bus, devfn, where & ~3, &result);
  204. if (status != PCIBIOS_SUCCESSFUL)
  205. return status;
  206. if (where & 2)
  207. shift += 16;
  208. if (where & 1)
  209. shift += 8;
  210. result &= ~(0xff << shift);
  211. result |= val << shift;
  212. return write_config_dword(swap, bus, devfn, where & ~3, result);
  213. }
  214. #define MAKE_PCI_OPS(prefix, rw, pciswap, star) \
  215. static int prefix##_##rw##_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 star val) \
  216. { \
  217. if (size == 1) \
  218. return rw##_config_byte(pciswap, bus, devfn, where, (u8 star)val); \
  219. else if (size == 2) \
  220. return rw##_config_word(pciswap, bus, devfn, where, (u16 star)val); \
  221. /* Size must be 4 */ \
  222. return rw##_config_dword(pciswap, bus, devfn, where, val); \
  223. }
  224. MAKE_PCI_OPS(extpci, read, &ext_pci_swap, *)
  225. MAKE_PCI_OPS(extpci, write, &ext_pci_swap,)
  226. MAKE_PCI_OPS(iopci, read, &io_pci_swap, *)
  227. MAKE_PCI_OPS(iopci, write, &io_pci_swap,)
  228. struct pci_ops ddb5477_ext_pci_ops = {
  229. .read = extpci_read_config,
  230. .write = extpci_write_config
  231. };
  232. struct pci_ops ddb5477_io_pci_ops = {
  233. .read = iopci_read_config,
  234. .write = iopci_write_config
  235. };