pci.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * (C) Copyright 2001
  3. * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. #include <common.h>
  24. #include <ppc4xx.h>
  25. #include <asm/processor.h>
  26. #include <pci.h>
  27. u_long pci9054_iobase;
  28. #define PCI_PRIMARY_CAR (0x500000dc) /* PCI config address reg */
  29. #define PCI_PRIMARY_CDR (0x80000000) /* PCI config data reg */
  30. /*-----------------------------------------------------------------------------+
  31. | Subroutine: pci9054_read_config_dword
  32. | Description: Read a PCI configuration register
  33. | Inputs:
  34. | hose PCI Controller
  35. | dev PCI Bus+Device+Function number
  36. | offset Configuration register number
  37. | value Address of the configuration register value
  38. | Return value:
  39. | 0 Successful
  40. +-----------------------------------------------------------------------------*/
  41. int pci9054_read_config_dword(struct pci_controller *hose,
  42. pci_dev_t dev, int offset, u32* value)
  43. {
  44. unsigned long conAdrVal;
  45. unsigned long val;
  46. /* generate coded value for CON_ADR register */
  47. conAdrVal = dev | (offset & 0xfc) | 0x80000000;
  48. /* Load the CON_ADR (CAR) value first, then read from CON_DATA (CDR) */
  49. *(unsigned long *)PCI_PRIMARY_CAR = conAdrVal;
  50. /* Note: *pResult comes back as -1 if machine check happened */
  51. val = in32r(PCI_PRIMARY_CDR);
  52. *value = (unsigned long) val;
  53. out32r(PCI_PRIMARY_CAR, 0);
  54. if ((*(unsigned long *)0x50000304) & 0x60000000)
  55. {
  56. /* clear pci master/target abort bits */
  57. *(unsigned long *)0x50000304 = *(unsigned long *)0x50000304;
  58. }
  59. return 0;
  60. }
  61. /*-----------------------------------------------------------------------------+
  62. | Subroutine: pci9054_write_config_dword
  63. | Description: Write a PCI configuration register.
  64. | Inputs:
  65. | hose PCI Controller
  66. | dev PCI Bus+Device+Function number
  67. | offset Configuration register number
  68. | Value Configuration register value
  69. | Return value:
  70. | 0 Successful
  71. | Updated for pass2 errata #6. Need to disable interrupts and clear the
  72. | PCICFGADR reg after writing the PCICFGDATA reg.
  73. +-----------------------------------------------------------------------------*/
  74. int pci9054_write_config_dword(struct pci_controller *hose,
  75. pci_dev_t dev, int offset, u32 value)
  76. {
  77. unsigned long conAdrVal;
  78. conAdrVal = dev | (offset & 0xfc) | 0x80000000;
  79. *(unsigned long *)PCI_PRIMARY_CAR = conAdrVal;
  80. out32r(PCI_PRIMARY_CDR, value);
  81. out32r(PCI_PRIMARY_CAR, 0);
  82. /* clear pci master/target abort bits */
  83. *(unsigned long *)0x50000304 = *(unsigned long *)0x50000304;
  84. return (0);
  85. }
  86. /*-----------------------------------------------------------------------
  87. */
  88. #ifdef CONFIG_DASA_SIM
  89. static void pci_dasa_sim_config_pci9054(struct pci_controller *hose, pci_dev_t dev,
  90. struct pci_config_table *_)
  91. {
  92. unsigned int iobase;
  93. unsigned short status = 0;
  94. unsigned char timer;
  95. /*
  96. * Configure PLX PCI9054
  97. */
  98. pci_read_config_word(CFG_PCI9054_DEV_FN, PCI_COMMAND, &status);
  99. status |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
  100. pci_write_config_word(CFG_PCI9054_DEV_FN, PCI_COMMAND, status);
  101. /* Check the latency timer for values >= 0x60.
  102. */
  103. pci_read_config_byte(CFG_PCI9054_DEV_FN, PCI_LATENCY_TIMER, &timer);
  104. if (timer < 0x60)
  105. {
  106. pci_write_config_byte(CFG_PCI9054_DEV_FN, PCI_LATENCY_TIMER, 0x60);
  107. }
  108. /* Set I/O base register.
  109. */
  110. pci_write_config_dword(CFG_PCI9054_DEV_FN, PCI_BASE_ADDRESS_0, CFG_PCI9054_IOBASE);
  111. pci_read_config_dword(CFG_PCI9054_DEV_FN, PCI_BASE_ADDRESS_0, &iobase);
  112. pci9054_iobase = pci_mem_to_phys(CFG_PCI9054_DEV_FN, iobase & PCI_BASE_ADDRESS_MEM_MASK);
  113. if (pci9054_iobase == 0xffffffff)
  114. {
  115. printf("Error: Can not set I/O base register.\n");
  116. return;
  117. }
  118. }
  119. #endif
  120. static struct pci_config_table pci9054_config_table[] = {
  121. #ifndef CONFIG_PCI_PNP
  122. { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
  123. PCI_BUS(CFG_ETH_DEV_FN), PCI_DEV(CFG_ETH_DEV_FN), PCI_FUNC(CFG_ETH_DEV_FN),
  124. pci_cfgfunc_config_device, { CFG_ETH_IOBASE,
  125. CFG_ETH_IOBASE,
  126. PCI_COMMAND_IO | PCI_COMMAND_MASTER }},
  127. #ifdef CONFIG_DASA_SIM
  128. { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
  129. PCI_BUS(CFG_PCI9054_DEV_FN), PCI_DEV(CFG_PCI9054_DEV_FN), PCI_FUNC(CFG_PCI9054_DEV_FN),
  130. pci_dasa_sim_config_pci9054 },
  131. #endif
  132. #endif
  133. { }
  134. };
  135. static struct pci_controller pci9054_hose = {
  136. config_table: pci9054_config_table,
  137. };
  138. void pci_init_board(void)
  139. {
  140. struct pci_controller *hose = &pci9054_hose;
  141. /*
  142. * Register the hose
  143. */
  144. hose->first_busno = 0;
  145. hose->last_busno = 0xff;
  146. /* System memory space */
  147. pci_set_region(hose->regions + 0,
  148. 0x00000000, 0x00000000, 0x01000000,
  149. PCI_REGION_MEM | PCI_REGION_MEMORY);
  150. /* PCI Memory space */
  151. pci_set_region(hose->regions + 1,
  152. 0x00000000, 0xc0000000, 0x10000000,
  153. PCI_REGION_MEM);
  154. pci_set_ops(hose,
  155. pci_hose_read_config_byte_via_dword,
  156. pci_hose_read_config_word_via_dword,
  157. pci9054_read_config_dword,
  158. pci_hose_write_config_byte_via_dword,
  159. pci_hose_write_config_word_via_dword,
  160. pci9054_write_config_dword);
  161. hose->region_count = 2;
  162. pci_register_hose(hose);
  163. hose->last_busno = pci_hose_scan(hose);
  164. }