qemu.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  5. */
  6. #include <common.h>
  7. #include <pci.h>
  8. #include <qemu_fw_cfg.h>
  9. #include <asm/irq.h>
  10. #include <asm/post.h>
  11. #include <asm/processor.h>
  12. #include <asm/arch/device.h>
  13. #include <asm/arch/qemu.h>
  14. static bool i440fx;
  15. static void enable_pm_piix(void)
  16. {
  17. u8 en;
  18. u16 cmd;
  19. /* Set the PM I/O base */
  20. pci_write_config32(PIIX_PM, PMBA, CONFIG_ACPI_PM1_BASE | 1);
  21. /* Enable access to the PM I/O space */
  22. pci_read_config16(PIIX_PM, PCI_COMMAND, &cmd);
  23. cmd |= PCI_COMMAND_IO;
  24. pci_write_config16(PIIX_PM, PCI_COMMAND, cmd);
  25. /* PM I/O Space Enable (PMIOSE) */
  26. pci_read_config8(PIIX_PM, PMREGMISC, &en);
  27. en |= PMIOSE;
  28. pci_write_config8(PIIX_PM, PMREGMISC, en);
  29. }
  30. static void enable_pm_ich9(void)
  31. {
  32. /* Set the PM I/O base */
  33. pci_write_config32(ICH9_PM, PMBA, CONFIG_ACPI_PM1_BASE | 1);
  34. }
  35. static void qemu_chipset_init(void)
  36. {
  37. u16 device, xbcs;
  38. int pam, i;
  39. /*
  40. * i440FX and Q35 chipset have different PAM register offset, but with
  41. * the same bitfield layout. Here we determine the offset based on its
  42. * PCI device ID.
  43. */
  44. pci_read_config16(PCI_BDF(0, 0, 0), PCI_DEVICE_ID, &device);
  45. i440fx = (device == PCI_DEVICE_ID_INTEL_82441);
  46. pam = i440fx ? I440FX_PAM : Q35_PAM;
  47. /*
  48. * Initialize Programmable Attribute Map (PAM) Registers
  49. *
  50. * Configure legacy segments C/D/E/F to system RAM
  51. */
  52. for (i = 0; i < PAM_NUM; i++)
  53. pci_write_config8(PCI_BDF(0, 0, 0), pam + i, PAM_RW);
  54. if (i440fx) {
  55. /*
  56. * Enable legacy IDE I/O ports decode
  57. *
  58. * Note: QEMU always decode legacy IDE I/O port on PIIX chipset.
  59. * However Linux ata_piix driver does sanity check on these two
  60. * registers to see whether legacy ports decode is turned on.
  61. * This is to make Linux ata_piix driver happy.
  62. */
  63. pci_write_config16(PIIX_IDE, IDE0_TIM, IDE_DECODE_EN);
  64. pci_write_config16(PIIX_IDE, IDE1_TIM, IDE_DECODE_EN);
  65. /* Enable I/O APIC */
  66. pci_read_config16(PIIX_ISA, XBCS, &xbcs);
  67. xbcs |= APIC_EN;
  68. pci_write_config16(PIIX_ISA, XBCS, xbcs);
  69. enable_pm_piix();
  70. } else {
  71. /* Configure PCIe ECAM base address */
  72. pci_write_config32(PCI_BDF(0, 0, 0), PCIEX_BAR,
  73. CONFIG_PCIE_ECAM_BASE | BAR_EN);
  74. enable_pm_ich9();
  75. }
  76. #ifdef CONFIG_QFW
  77. qemu_fwcfg_init();
  78. #endif
  79. }
  80. int arch_cpu_init(void)
  81. {
  82. int ret;
  83. post_code(POST_CPU_INIT);
  84. ret = x86_cpu_init_f();
  85. if (ret)
  86. return ret;
  87. return 0;
  88. }
  89. #ifndef CONFIG_EFI_STUB
  90. int print_cpuinfo(void)
  91. {
  92. post_code(POST_CPU_INFO);
  93. return default_print_cpuinfo();
  94. }
  95. #endif
  96. void reset_cpu(ulong addr)
  97. {
  98. /* cold reset */
  99. x86_full_reset();
  100. }
  101. int arch_early_init_r(void)
  102. {
  103. qemu_chipset_init();
  104. return 0;
  105. }
  106. #ifdef CONFIG_GENERATE_MP_TABLE
  107. int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq)
  108. {
  109. u8 irq;
  110. if (i440fx) {
  111. /*
  112. * Not like most x86 platforms, the PIRQ[A-D] on PIIX3 are not
  113. * connected to I/O APIC INTPIN#16-19. Instead they are routed
  114. * to an irq number controled by the PIRQ routing register.
  115. */
  116. pci_read_config8(PCI_BDF(bus, dev, func),
  117. PCI_INTERRUPT_LINE, &irq);
  118. } else {
  119. /*
  120. * ICH9's PIRQ[A-H] are not consecutive numbers from 0 to 7.
  121. * PIRQ[A-D] still maps to [0-3] but PIRQ[E-H] maps to [8-11].
  122. */
  123. irq = pirq < 8 ? pirq + 16 : pirq + 12;
  124. }
  125. return irq;
  126. }
  127. #endif