blob: 70440c02c2e2051751f78d4a1771b17226d70d99 [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Martin Rothebace9f2018-05-26 18:56:17 -06002
Kyösti Mälkki5c2594e2021-06-08 10:47:24 +03003#include <arch/ioapic.h>
Yinghai Lu70093f72004-07-01 03:55:03 +00004#include <console/console.h>
5#include <device/device.h>
6#include <device/pci.h>
7#include <device/pci_ids.h>
8#include <device/pci_ops.h>
Steven J. Magnani09e4ef62005-09-14 13:56:25 +00009#include <assert.h>
Yinghai Lu70093f72004-07-01 03:55:03 +000010#include "82870.h"
11
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000012static int num_p64h2_ioapics = 0;
Yinghai Lu70093f72004-07-01 03:55:03 +000013
Elyes HAOUAS17c59f52018-05-13 13:38:38 +020014static void p64h2_ioapic_enable(struct device *dev)
Yinghai Lu70093f72004-07-01 03:55:03 +000015{
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020016 /* We have to enable MEM and Bus Master for IOAPIC */
17 uint16_t command = PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
Yinghai Lu70093f72004-07-01 03:55:03 +000018
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020019 pci_write_config16(dev, PCI_COMMAND, command);
Yinghai Lu70093f72004-07-01 03:55:03 +000020}
21
Uwe Hermannb69cb5a2010-10-26 22:46:43 +000022/**
23 * Configure one of the IOAPICs in a P64H2.
24 *
25 * Note that a PCI bus scan will detect both IOAPICs, so this function
26 * will be called twice for each P64H2 in the system.
27 *
28 * @param dev PCI bus/device/function of P64H2 IOAPIC.
29 * NOTE: There are two IOAPICs per P64H2, at D28:F0 and D30:F0.
30 */
Elyes HAOUAS17c59f52018-05-13 13:38:38 +020031static void p64h2_ioapic_init(struct device *dev)
Yinghai Lu70093f72004-07-01 03:55:03 +000032{
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020033 uint32_t memoryBase;
34 int apic_index, apic_id;
Yinghai Lu70093f72004-07-01 03:55:03 +000035
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020036 apic_index = num_p64h2_ioapics;
37 num_p64h2_ioapics++;
Yinghai Lu70093f72004-07-01 03:55:03 +000038
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020039 // A note on IOAPIC addresses:
40 // 0 and 1 are used for the local APICs of the dual virtual
41 // (hyper-threaded) CPUs of physical CPU 0 (devicetree.cb).
42 // 6 and 7 are used for the local APICs of the dual virtual
43 // (hyper-threaded) CPUs of physical CPU 1 (devicetree.cb).
44 // 2 is used for the IOAPIC in the 82801 southbridge (hard-coded in i82801xx_lpc.c)
Yinghai Lu70093f72004-07-01 03:55:03 +000045
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020046 // Map APIC index into APIC ID
47 // IDs 3, 4, 5, and 8+ are available (see above note)
Yinghai Lu70093f72004-07-01 03:55:03 +000048
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020049 if (apic_index < 3)
50 apic_id = apic_index + 3;
51 else
52 apic_id = apic_index + 5;
Yinghai Lu70093f72004-07-01 03:55:03 +000053
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020054 ASSERT(apic_id < 16); // ID is only 4 bits
Yinghai Lu70093f72004-07-01 03:55:03 +000055
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020056 // Read the MBAR address for setting up the IOAPIC in memory space
57 // NOTE: this address was assigned during enumeration of the bus
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000058
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020059 memoryBase = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000060
Kyösti Mälkki5c2594e2021-06-08 10:47:24 +030061 set_ioapic_id((void *)memoryBase, apic_id);
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000062
Kyösti Mälkki5c2594e2021-06-08 10:47:24 +030063 // Use Processor System Bus to deliver interrupts
64 ioapic_set_boot_config((void *)memoryBase, true);
Yinghai Lu70093f72004-07-01 03:55:03 +000065}
66
67static struct device_operations ioapic_ops = {
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020068 .read_resources = pci_dev_read_resources,
69 .set_resources = pci_dev_set_resources,
70 .enable_resources = pci_dev_enable_resources,
71 .init = p64h2_ioapic_init,
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020072 .enable = p64h2_ioapic_enable,
Yinghai Lu70093f72004-07-01 03:55:03 +000073};
74
Stefan Reinauerf1cf1f72007-10-24 09:08:58 +000075static const struct pci_driver ioapic_driver __pci_driver = {
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020076 .ops = &ioapic_ops,
77 .vendor = PCI_VENDOR_ID_INTEL,
78 .device = PCI_DEVICE_ID_INTEL_82870_1E0,
Yinghai Lu70093f72004-07-01 03:55:03 +000079
80};