pci.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2006 PA Semi, Inc
  4. *
  5. * Authors: Kip Walker, PA Semi
  6. * Olof Johansson, PA Semi
  7. *
  8. * Maintained by: Olof Johansson <[email protected]>
  9. *
  10. * Based on arch/powerpc/platforms/maple/pci.c
  11. */
  12. #include <linux/kernel.h>
  13. #include <linux/of_address.h>
  14. #include <linux/pci.h>
  15. #include <asm/pci-bridge.h>
  16. #include <asm/isa-bridge.h>
  17. #include <asm/machdep.h>
  18. #include <asm/ppc-pci.h>
  19. #include "pasemi.h"
  20. #define PA_PXP_CFA(bus, devfn, off) (((bus) << 20) | ((devfn) << 12) | (off))
  21. static inline int pa_pxp_offset_valid(u8 bus, u8 devfn, int offset)
  22. {
  23. /* Device 0 Function 0 is special: It's config space spans function 1 as
  24. * well, so allow larger offset. It's really a two-function device but the
  25. * second function does not probe.
  26. */
  27. if (bus == 0 && devfn == 0)
  28. return offset < 8192;
  29. else
  30. return offset < 4096;
  31. }
  32. static void volatile __iomem *pa_pxp_cfg_addr(struct pci_controller *hose,
  33. u8 bus, u8 devfn, int offset)
  34. {
  35. return hose->cfg_data + PA_PXP_CFA(bus, devfn, offset);
  36. }
  37. static inline int is_root_port(int busno, int devfn)
  38. {
  39. return ((busno == 0) && (PCI_FUNC(devfn) < 4) &&
  40. ((PCI_SLOT(devfn) == 16) || (PCI_SLOT(devfn) == 17)));
  41. }
  42. static inline int is_5945_reg(int reg)
  43. {
  44. return (((reg >= 0x18) && (reg < 0x34)) ||
  45. ((reg >= 0x158) && (reg < 0x178)));
  46. }
  47. static int workaround_5945(struct pci_bus *bus, unsigned int devfn,
  48. int offset, int len, u32 *val)
  49. {
  50. struct pci_controller *hose;
  51. void volatile __iomem *addr, *dummy;
  52. int byte;
  53. u32 tmp;
  54. if (!is_root_port(bus->number, devfn) || !is_5945_reg(offset))
  55. return 0;
  56. hose = pci_bus_to_host(bus);
  57. addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset & ~0x3);
  58. byte = offset & 0x3;
  59. /* Workaround bug 5945: write 0 to a dummy register before reading,
  60. * and write back what we read. We must read/write the full 32-bit
  61. * contents so we need to shift and mask by hand.
  62. */
  63. dummy = pa_pxp_cfg_addr(hose, bus->number, devfn, 0x10);
  64. out_le32(dummy, 0);
  65. tmp = in_le32(addr);
  66. out_le32(addr, tmp);
  67. switch (len) {
  68. case 1:
  69. *val = (tmp >> (8*byte)) & 0xff;
  70. break;
  71. case 2:
  72. if (byte == 0)
  73. *val = tmp & 0xffff;
  74. else
  75. *val = (tmp >> 16) & 0xffff;
  76. break;
  77. default:
  78. *val = tmp;
  79. break;
  80. }
  81. return 1;
  82. }
  83. #ifdef CONFIG_PPC_PASEMI_NEMO
  84. #define PXP_ERR_CFG_REG 0x4
  85. #define PXP_IGNORE_PCIE_ERRORS 0x800
  86. #define SB600_BUS 5
  87. static void sb600_set_flag(int bus)
  88. {
  89. static void __iomem *iob_mapbase = NULL;
  90. struct resource res;
  91. struct device_node *dn;
  92. int err;
  93. if (iob_mapbase == NULL) {
  94. dn = of_find_compatible_node(NULL, "isa", "pasemi,1682m-iob");
  95. if (!dn) {
  96. pr_crit("NEMO SB600 missing iob node\n");
  97. return;
  98. }
  99. err = of_address_to_resource(dn, 0, &res);
  100. of_node_put(dn);
  101. if (err) {
  102. pr_crit("NEMO SB600 missing resource\n");
  103. return;
  104. }
  105. pr_info("NEMO SB600 IOB base %08llx\n",res.start);
  106. iob_mapbase = ioremap(res.start + 0x100, 0x94);
  107. }
  108. if (iob_mapbase != NULL) {
  109. if (bus == SB600_BUS) {
  110. /*
  111. * This is the SB600's bus, tell the PCI-e root port
  112. * to allow non-zero devices to enumerate.
  113. */
  114. out_le32(iob_mapbase + PXP_ERR_CFG_REG, in_le32(iob_mapbase + PXP_ERR_CFG_REG) | PXP_IGNORE_PCIE_ERRORS);
  115. } else {
  116. /*
  117. * Only scan device 0 on other busses
  118. */
  119. out_le32(iob_mapbase + PXP_ERR_CFG_REG, in_le32(iob_mapbase + PXP_ERR_CFG_REG) & ~PXP_IGNORE_PCIE_ERRORS);
  120. }
  121. }
  122. }
  123. #else
  124. static void sb600_set_flag(int bus)
  125. {
  126. }
  127. #endif
  128. static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn,
  129. int offset, int len, u32 *val)
  130. {
  131. struct pci_controller *hose;
  132. void volatile __iomem *addr;
  133. hose = pci_bus_to_host(bus);
  134. if (!hose)
  135. return PCIBIOS_DEVICE_NOT_FOUND;
  136. if (!pa_pxp_offset_valid(bus->number, devfn, offset))
  137. return PCIBIOS_BAD_REGISTER_NUMBER;
  138. if (workaround_5945(bus, devfn, offset, len, val))
  139. return PCIBIOS_SUCCESSFUL;
  140. addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset);
  141. sb600_set_flag(bus->number);
  142. /*
  143. * Note: the caller has already checked that offset is
  144. * suitably aligned and that len is 1, 2 or 4.
  145. */
  146. switch (len) {
  147. case 1:
  148. *val = in_8(addr);
  149. break;
  150. case 2:
  151. *val = in_le16(addr);
  152. break;
  153. default:
  154. *val = in_le32(addr);
  155. break;
  156. }
  157. return PCIBIOS_SUCCESSFUL;
  158. }
  159. static int pa_pxp_write_config(struct pci_bus *bus, unsigned int devfn,
  160. int offset, int len, u32 val)
  161. {
  162. struct pci_controller *hose;
  163. void volatile __iomem *addr;
  164. hose = pci_bus_to_host(bus);
  165. if (!hose)
  166. return PCIBIOS_DEVICE_NOT_FOUND;
  167. if (!pa_pxp_offset_valid(bus->number, devfn, offset))
  168. return PCIBIOS_BAD_REGISTER_NUMBER;
  169. addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset);
  170. sb600_set_flag(bus->number);
  171. /*
  172. * Note: the caller has already checked that offset is
  173. * suitably aligned and that len is 1, 2 or 4.
  174. */
  175. switch (len) {
  176. case 1:
  177. out_8(addr, val);
  178. break;
  179. case 2:
  180. out_le16(addr, val);
  181. break;
  182. default:
  183. out_le32(addr, val);
  184. break;
  185. }
  186. return PCIBIOS_SUCCESSFUL;
  187. }
  188. static struct pci_ops pa_pxp_ops = {
  189. .read = pa_pxp_read_config,
  190. .write = pa_pxp_write_config,
  191. };
  192. static void __init setup_pa_pxp(struct pci_controller *hose)
  193. {
  194. hose->ops = &pa_pxp_ops;
  195. hose->cfg_data = ioremap(0xe0000000, 0x10000000);
  196. }
  197. static int __init pas_add_bridge(struct device_node *dev)
  198. {
  199. struct pci_controller *hose;
  200. pr_debug("Adding PCI host bridge %pOF\n", dev);
  201. hose = pcibios_alloc_controller(dev);
  202. if (!hose)
  203. return -ENOMEM;
  204. hose->first_busno = 0;
  205. hose->last_busno = 0xff;
  206. hose->controller_ops = pasemi_pci_controller_ops;
  207. setup_pa_pxp(hose);
  208. pr_info("Found PA-PXP PCI host bridge.\n");
  209. /* Interpret the "ranges" property */
  210. pci_process_bridge_OF_ranges(hose, dev, 1);
  211. /*
  212. * Scan for an isa bridge. This is needed to find the SB600 on the nemo
  213. * and does nothing on machines without one.
  214. */
  215. isa_bridge_find_early(hose);
  216. return 0;
  217. }
  218. void __init pas_pci_init(void)
  219. {
  220. struct device_node *np;
  221. int res;
  222. pci_set_flags(PCI_SCAN_ALL_PCIE_DEVS);
  223. np = of_find_compatible_node(of_root, NULL, "pasemi,rootbus");
  224. if (np) {
  225. res = pas_add_bridge(np);
  226. of_node_put(np);
  227. }
  228. }
  229. void __iomem *__init pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset)
  230. {
  231. struct pci_controller *hose;
  232. hose = pci_bus_to_host(dev->bus);
  233. return (void __iomem *)pa_pxp_cfg_addr(hose, dev->bus->number, dev->devfn, offset);
  234. }
  235. struct pci_controller_ops pasemi_pci_controller_ops;