mpc52xx_pci.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*
  2. * PCI code for the Freescale MPC52xx embedded CPU.
  3. *
  4. *
  5. * Maintainer : Sylvain Munaut <tnt@246tNt.com>
  6. *
  7. * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
  8. *
  9. * This file is licensed under the terms of the GNU General Public License
  10. * version 2. This program is licensed "as is" without any warranty of any
  11. * kind, whether express or implied.
  12. */
  13. #include <linux/config.h>
  14. #include <asm/pci.h>
  15. #include <asm/mpc52xx.h>
  16. #include "mpc52xx_pci.h"
  17. #include <asm/delay.h>
  18. #include <asm/machdep.h>
  19. /* This macro is defined to activate the workaround for the bug
  20. 435 of the MPC5200 (L25R). With it activated, we don't do any
  21. 32 bits configuration access during type-1 cycles */
  22. #define MPC5200_BUG_435_WORKAROUND
  23. static int
  24. mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
  25. int offset, int len, u32 *val)
  26. {
  27. struct pci_controller *hose = bus->sysdata;
  28. u32 value;
  29. if (ppc_md.pci_exclude_device)
  30. if (ppc_md.pci_exclude_device(bus->number, devfn))
  31. return PCIBIOS_DEVICE_NOT_FOUND;
  32. out_be32(hose->cfg_addr,
  33. (1 << 31) |
  34. ((bus->number - hose->bus_offset) << 16) |
  35. (devfn << 8) |
  36. (offset & 0xfc));
  37. mb();
  38. #ifdef MPC5200_BUG_435_WORKAROUND
  39. if (bus->number != hose->bus_offset) {
  40. switch (len) {
  41. case 1:
  42. value = in_8(((u8 __iomem *)hose->cfg_data) + (offset & 3));
  43. break;
  44. case 2:
  45. value = in_le16(((u16 __iomem *)hose->cfg_data) + ((offset>>1) & 1));
  46. break;
  47. default:
  48. value = in_le16((u16 __iomem *)hose->cfg_data) |
  49. (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
  50. break;
  51. }
  52. }
  53. else
  54. #endif
  55. {
  56. value = in_le32(hose->cfg_data);
  57. if (len != 4) {
  58. value >>= ((offset & 0x3) << 3);
  59. value &= 0xffffffff >> (32 - (len << 3));
  60. }
  61. }
  62. *val = value;
  63. out_be32(hose->cfg_addr, 0);
  64. mb();
  65. return PCIBIOS_SUCCESSFUL;
  66. }
  67. static int
  68. mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
  69. int offset, int len, u32 val)
  70. {
  71. struct pci_controller *hose = bus->sysdata;
  72. u32 value, mask;
  73. if (ppc_md.pci_exclude_device)
  74. if (ppc_md.pci_exclude_device(bus->number, devfn))
  75. return PCIBIOS_DEVICE_NOT_FOUND;
  76. out_be32(hose->cfg_addr,
  77. (1 << 31) |
  78. ((bus->number - hose->bus_offset) << 16) |
  79. (devfn << 8) |
  80. (offset & 0xfc));
  81. mb();
  82. #ifdef MPC5200_BUG_435_WORKAROUND
  83. if (bus->number != hose->bus_offset) {
  84. switch (len) {
  85. case 1:
  86. out_8(((u8 __iomem *)hose->cfg_data) +
  87. (offset & 3), val);
  88. break;
  89. case 2:
  90. out_le16(((u16 __iomem *)hose->cfg_data) +
  91. ((offset>>1) & 1), val);
  92. break;
  93. default:
  94. out_le16((u16 __iomem *)hose->cfg_data,
  95. (u16)val);
  96. out_le16(((u16 __iomem *)hose->cfg_data) + 1,
  97. (u16)(val>>16));
  98. break;
  99. }
  100. }
  101. else
  102. #endif
  103. {
  104. if (len != 4) {
  105. value = in_le32(hose->cfg_data);
  106. offset = (offset & 0x3) << 3;
  107. mask = (0xffffffff >> (32 - (len << 3)));
  108. mask <<= offset;
  109. value &= ~mask;
  110. val = value | ((val << offset) & mask);
  111. }
  112. out_le32(hose->cfg_data, val);
  113. }
  114. mb();
  115. out_be32(hose->cfg_addr, 0);
  116. mb();
  117. return PCIBIOS_SUCCESSFUL;
  118. }
  119. static struct pci_ops mpc52xx_pci_ops = {
  120. .read = mpc52xx_pci_read_config,
  121. .write = mpc52xx_pci_write_config
  122. };
  123. static void __init
  124. mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs)
  125. {
  126. u32 tmp;
  127. /* Setup control regs */
  128. tmp = in_be32(&pci_regs->scr);
  129. tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
  130. out_be32(&pci_regs->scr, tmp);
  131. /* Setup windows */
  132. out_be32(&pci_regs->iw0btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
  133. MPC52xx_PCI_MEM_START + MPC52xx_PCI_MEM_OFFSET,
  134. MPC52xx_PCI_MEM_START,
  135. MPC52xx_PCI_MEM_SIZE ));
  136. out_be32(&pci_regs->iw1btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
  137. MPC52xx_PCI_MMIO_START + MPC52xx_PCI_MEM_OFFSET,
  138. MPC52xx_PCI_MMIO_START,
  139. MPC52xx_PCI_MMIO_SIZE ));
  140. out_be32(&pci_regs->iw2btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
  141. MPC52xx_PCI_IO_BASE,
  142. MPC52xx_PCI_IO_START,
  143. MPC52xx_PCI_IO_SIZE ));
  144. out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(
  145. ( MPC52xx_PCI_IWCR_ENABLE | /* iw0btar */
  146. MPC52xx_PCI_IWCR_READ_MULTI |
  147. MPC52xx_PCI_IWCR_MEM ),
  148. ( MPC52xx_PCI_IWCR_ENABLE | /* iw1btar */
  149. MPC52xx_PCI_IWCR_READ |
  150. MPC52xx_PCI_IWCR_MEM ),
  151. ( MPC52xx_PCI_IWCR_ENABLE | /* iw2btar */
  152. MPC52xx_PCI_IWCR_IO )
  153. ));
  154. out_be32(&pci_regs->tbatr0,
  155. MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO );
  156. out_be32(&pci_regs->tbatr1,
  157. MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM );
  158. out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD);
  159. /* Reset the exteral bus ( internal PCI controller is NOT resetted ) */
  160. /* Not necessary and can be a bad thing if for example the bootloader
  161. is displaying a splash screen or ... Just left here for
  162. documentation purpose if anyone need it */
  163. tmp = in_be32(&pci_regs->gscr);
  164. #if 0
  165. out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
  166. udelay(50);
  167. #endif
  168. out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR);
  169. }
  170. static void
  171. mpc52xx_pci_fixup_resources(struct pci_dev *dev)
  172. {
  173. int i;
  174. /* We don't rely on boot loader for PCI and resets all
  175. devices */
  176. for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
  177. struct resource *res = &dev->resource[i];
  178. if (res->end > res->start) { /* Only valid resources */
  179. res->end -= res->start;
  180. res->start = 0;
  181. res->flags |= IORESOURCE_UNSET;
  182. }
  183. }
  184. /* The PCI Host bridge of MPC52xx has a prefetch memory resource
  185. fixed to 1Gb. Doesn't fit in the resource system so we remove it */
  186. if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
  187. ( dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200
  188. || dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200B) ) {
  189. struct resource *res = &dev->resource[1];
  190. res->start = res->end = res->flags = 0;
  191. }
  192. }
  193. void __init
  194. mpc52xx_find_bridges(void)
  195. {
  196. struct mpc52xx_pci __iomem *pci_regs;
  197. struct pci_controller *hose;
  198. pci_assign_all_buses = 1;
  199. pci_regs = ioremap(MPC52xx_PA(MPC52xx_PCI_OFFSET), MPC52xx_PCI_SIZE);
  200. if (!pci_regs)
  201. return;
  202. hose = pcibios_alloc_controller();
  203. if (!hose) {
  204. iounmap(pci_regs);
  205. return;
  206. }
  207. ppc_md.pci_swizzle = common_swizzle;
  208. ppc_md.pcibios_fixup_resources = mpc52xx_pci_fixup_resources;
  209. hose->first_busno = 0;
  210. hose->last_busno = 0xff;
  211. hose->bus_offset = 0;
  212. hose->ops = &mpc52xx_pci_ops;
  213. mpc52xx_pci_setup(pci_regs);
  214. hose->pci_mem_offset = MPC52xx_PCI_MEM_OFFSET;
  215. hose->io_base_virt = ioremap(MPC52xx_PCI_IO_BASE, MPC52xx_PCI_IO_SIZE);
  216. isa_io_base = (unsigned long) hose->io_base_virt;
  217. hose->cfg_addr = &pci_regs->car;
  218. hose->cfg_data = hose->io_base_virt;
  219. /* Setup resources */
  220. pci_init_resource(&hose->mem_resources[0],
  221. MPC52xx_PCI_MEM_START,
  222. MPC52xx_PCI_MEM_STOP,
  223. IORESOURCE_MEM|IORESOURCE_PREFETCH,
  224. "PCI prefetchable memory");
  225. pci_init_resource(&hose->mem_resources[1],
  226. MPC52xx_PCI_MMIO_START,
  227. MPC52xx_PCI_MMIO_STOP,
  228. IORESOURCE_MEM,
  229. "PCI memory");
  230. pci_init_resource(&hose->io_resource,
  231. MPC52xx_PCI_IO_START,
  232. MPC52xx_PCI_IO_STOP,
  233. IORESOURCE_IO,
  234. "PCI I/O");
  235. }