blob: 4fbf32934276786d67850893cd935b81da727466 [file] [log] [blame]
Martin Rothebace9f2018-05-26 18:56:17 -06001/*
2 * This file is part of the coreboot project.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
Yinghai Lu70093f72004-07-01 03:55:03 +000014#include <console/console.h>
15#include <device/device.h>
16#include <device/pci.h>
17#include <device/pci_ids.h>
18#include <device/pci_ops.h>
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000019#include <assert.h>
Yinghai Lu70093f72004-07-01 03:55:03 +000020#include "82870.h"
21
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000022static int num_p64h2_ioapics = 0;
Yinghai Lu70093f72004-07-01 03:55:03 +000023
Elyes HAOUAS17c59f52018-05-13 13:38:38 +020024static void p64h2_ioapic_enable(struct device *dev)
Yinghai Lu70093f72004-07-01 03:55:03 +000025{
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020026 /* We have to enable MEM and Bus Master for IOAPIC */
27 uint16_t command = PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
Yinghai Lu70093f72004-07-01 03:55:03 +000028
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020029 pci_write_config16(dev, PCI_COMMAND, command);
Yinghai Lu70093f72004-07-01 03:55:03 +000030}
31
Uwe Hermannb69cb5a2010-10-26 22:46:43 +000032/**
33 * Configure one of the IOAPICs in a P64H2.
34 *
35 * Note that a PCI bus scan will detect both IOAPICs, so this function
36 * will be called twice for each P64H2 in the system.
37 *
38 * @param dev PCI bus/device/function of P64H2 IOAPIC.
39 * NOTE: There are two IOAPICs per P64H2, at D28:F0 and D30:F0.
40 */
Elyes HAOUAS17c59f52018-05-13 13:38:38 +020041static void p64h2_ioapic_init(struct device *dev)
Yinghai Lu70093f72004-07-01 03:55:03 +000042{
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020043 uint32_t memoryBase;
44 int apic_index, apic_id;
Yinghai Lu70093f72004-07-01 03:55:03 +000045
Elyes HAOUAS251279c2018-07-08 12:41:56 +020046 volatile uint32_t *pIndexRegister; /* io apic io memory space command address */
47 volatile uint32_t *pWindowRegister; /* io apic io memory space data address */
Yinghai Lu70093f72004-07-01 03:55:03 +000048
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020049 apic_index = num_p64h2_ioapics;
50 num_p64h2_ioapics++;
Yinghai Lu70093f72004-07-01 03:55:03 +000051
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020052 // A note on IOAPIC addresses:
53 // 0 and 1 are used for the local APICs of the dual virtual
54 // (hyper-threaded) CPUs of physical CPU 0 (devicetree.cb).
55 // 6 and 7 are used for the local APICs of the dual virtual
56 // (hyper-threaded) CPUs of physical CPU 1 (devicetree.cb).
57 // 2 is used for the IOAPIC in the 82801 southbridge (hard-coded in i82801xx_lpc.c)
Yinghai Lu70093f72004-07-01 03:55:03 +000058
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020059 // Map APIC index into APIC ID
60 // IDs 3, 4, 5, and 8+ are available (see above note)
Yinghai Lu70093f72004-07-01 03:55:03 +000061
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020062 if (apic_index < 3)
63 apic_id = apic_index + 3;
64 else
65 apic_id = apic_index + 5;
Yinghai Lu70093f72004-07-01 03:55:03 +000066
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020067 ASSERT(apic_id < 16); // ID is only 4 bits
Yinghai Lu70093f72004-07-01 03:55:03 +000068
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020069 // Read the MBAR address for setting up the IOAPIC in memory space
70 // NOTE: this address was assigned during enumeration of the bus
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000071
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020072 memoryBase = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
Elyes HAOUAS251279c2018-07-08 12:41:56 +020073 pIndexRegister = (volatile uint32_t *) memoryBase;
74 pWindowRegister = (volatile uint32_t *)(memoryBase + 0x10);
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000075
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020076 printk(BIOS_DEBUG, "IOAPIC %d at %02x:%02x.%01x MBAR = %p DataAddr = %p\n",
77 apic_id, dev->bus->secondary, PCI_SLOT(dev->path.pci.devfn),
78 PCI_FUNC(dev->path.pci.devfn), pIndexRegister, pWindowRegister);
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000079
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020080 apic_id <<= 24; // Convert ID to bitmask
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000081
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020082 *pIndexRegister = 0; // Select APIC ID register
Elyes HAOUASccd233b2017-07-03 21:48:52 +020083 *pWindowRegister = (*pWindowRegister & ~(0x0f << 24)) | apic_id; // Set the ID
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000084
Elyes HAOUASccd233b2017-07-03 21:48:52 +020085 if ((*pWindowRegister & (0x0f << 24)) != apic_id)
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020086 die("p64h2_ioapic_init failed");
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000087
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020088 *pIndexRegister = 3; // Select Boot Configuration register
89 *pWindowRegister |= 1; // Use Processor System Bus to deliver interrupts
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000090
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020091 if (!(*pWindowRegister & 1))
92 die("p64h2_ioapic_init failed");
Yinghai Lu70093f72004-07-01 03:55:03 +000093}
94
95static struct device_operations ioapic_ops = {
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020096 .read_resources = pci_dev_read_resources,
97 .set_resources = pci_dev_set_resources,
98 .enable_resources = pci_dev_enable_resources,
99 .init = p64h2_ioapic_init,
100 .scan_bus = 0,
101 .enable = p64h2_ioapic_enable,
Yinghai Lu70093f72004-07-01 03:55:03 +0000102};
103
Stefan Reinauerf1cf1f72007-10-24 09:08:58 +0000104static const struct pci_driver ioapic_driver __pci_driver = {
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200105 .ops = &ioapic_ops,
106 .vendor = PCI_VENDOR_ID_INTEL,
107 .device = PCI_DEVICE_ID_INTEL_82870_1E0,
Yinghai Lu70093f72004-07-01 03:55:03 +0000108
109};