mpc52xx_pci.c 6.7 KB

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