common.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/pci.h>
  3. #include <linux/interrupt.h>
  4. #include <linux/timer.h>
  5. #include <linux/kernel.h>
  6. /*
  7. * These functions are used early on before PCI scanning is done
  8. * and all of the pci_dev and pci_bus structures have been created.
  9. */
  10. static struct pci_dev *fake_pci_dev(struct pci_channel *hose,
  11. int top_bus, int busnr, int devfn)
  12. {
  13. static struct pci_dev dev;
  14. static struct pci_bus bus;
  15. dev.bus = &bus;
  16. dev.sysdata = hose;
  17. dev.devfn = devfn;
  18. bus.number = busnr;
  19. bus.sysdata = hose;
  20. bus.ops = hose->pci_ops;
  21. if(busnr != top_bus)
  22. /* Fake a parent bus structure. */
  23. bus.parent = &bus;
  24. else
  25. bus.parent = NULL;
  26. return &dev;
  27. }
  28. #define EARLY_PCI_OP(rw, size, type) \
  29. int __init early_##rw##_config_##size(struct pci_channel *hose, \
  30. int top_bus, int bus, int devfn, int offset, type value) \
  31. { \
  32. return pci_##rw##_config_##size( \
  33. fake_pci_dev(hose, top_bus, bus, devfn), \
  34. offset, value); \
  35. }
  36. EARLY_PCI_OP(read, byte, u8 *)
  37. EARLY_PCI_OP(read, word, u16 *)
  38. EARLY_PCI_OP(read, dword, u32 *)
  39. EARLY_PCI_OP(write, byte, u8)
  40. EARLY_PCI_OP(write, word, u16)
  41. EARLY_PCI_OP(write, dword, u32)
  42. int __init pci_is_66mhz_capable(struct pci_channel *hose,
  43. int top_bus, int current_bus)
  44. {
  45. u32 pci_devfn;
  46. u16 vid;
  47. int cap66 = -1;
  48. u16 stat;
  49. int ret;
  50. pr_info("PCI: Checking 66MHz capabilities...\n");
  51. for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
  52. if (PCI_FUNC(pci_devfn))
  53. continue;
  54. ret = early_read_config_word(hose, top_bus, current_bus,
  55. pci_devfn, PCI_VENDOR_ID, &vid);
  56. if (ret != PCIBIOS_SUCCESSFUL)
  57. continue;
  58. if (PCI_POSSIBLE_ERROR(vid))
  59. continue;
  60. /* check 66MHz capability */
  61. if (cap66 < 0)
  62. cap66 = 1;
  63. if (cap66) {
  64. early_read_config_word(hose, top_bus, current_bus,
  65. pci_devfn, PCI_STATUS, &stat);
  66. if (!(stat & PCI_STATUS_66MHZ)) {
  67. printk(KERN_DEBUG
  68. "PCI: %02x:%02x not 66MHz capable.\n",
  69. current_bus, pci_devfn);
  70. cap66 = 0;
  71. break;
  72. }
  73. }
  74. }
  75. return cap66 > 0;
  76. }
  77. static void pcibios_enable_err(struct timer_list *t)
  78. {
  79. struct pci_channel *hose = from_timer(hose, t, err_timer);
  80. del_timer(&hose->err_timer);
  81. printk(KERN_DEBUG "PCI: re-enabling error IRQ.\n");
  82. enable_irq(hose->err_irq);
  83. }
  84. static void pcibios_enable_serr(struct timer_list *t)
  85. {
  86. struct pci_channel *hose = from_timer(hose, t, serr_timer);
  87. del_timer(&hose->serr_timer);
  88. printk(KERN_DEBUG "PCI: re-enabling system error IRQ.\n");
  89. enable_irq(hose->serr_irq);
  90. }
  91. void pcibios_enable_timers(struct pci_channel *hose)
  92. {
  93. if (hose->err_irq) {
  94. timer_setup(&hose->err_timer, pcibios_enable_err, 0);
  95. }
  96. if (hose->serr_irq) {
  97. timer_setup(&hose->serr_timer, pcibios_enable_serr, 0);
  98. }
  99. }
  100. /*
  101. * A simple handler for the regular PCI status errors, called from IRQ
  102. * context.
  103. */
  104. unsigned int pcibios_handle_status_errors(unsigned long addr,
  105. unsigned int status,
  106. struct pci_channel *hose)
  107. {
  108. unsigned int cmd = 0;
  109. if (status & PCI_STATUS_REC_MASTER_ABORT) {
  110. printk(KERN_DEBUG "PCI: master abort, pc=0x%08lx\n", addr);
  111. cmd |= PCI_STATUS_REC_MASTER_ABORT;
  112. }
  113. if (status & PCI_STATUS_REC_TARGET_ABORT) {
  114. printk(KERN_DEBUG "PCI: target abort: ");
  115. pcibios_report_status(PCI_STATUS_REC_TARGET_ABORT |
  116. PCI_STATUS_SIG_TARGET_ABORT |
  117. PCI_STATUS_REC_MASTER_ABORT, 1);
  118. pr_cont("\n");
  119. cmd |= PCI_STATUS_REC_TARGET_ABORT;
  120. }
  121. if (status & (PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY)) {
  122. printk(KERN_DEBUG "PCI: parity error detected: ");
  123. pcibios_report_status(PCI_STATUS_PARITY |
  124. PCI_STATUS_DETECTED_PARITY, 1);
  125. pr_cont("\n");
  126. cmd |= PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY;
  127. /* Now back off of the IRQ for awhile */
  128. if (hose->err_irq) {
  129. disable_irq_nosync(hose->err_irq);
  130. hose->err_timer.expires = jiffies + HZ;
  131. add_timer(&hose->err_timer);
  132. }
  133. }
  134. return cmd;
  135. }