blob: ee85124b49af9dd7e06c475194c1c8f91dba53b3 [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>
19#include <pc80/mc146818rtc.h>
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000020#include <assert.h>
Yinghai Lu70093f72004-07-01 03:55:03 +000021#include "82870.h"
22
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000023static int num_p64h2_ioapics = 0;
Yinghai Lu70093f72004-07-01 03:55:03 +000024
Elyes HAOUAS17c59f52018-05-13 13:38:38 +020025static void p64h2_ioapic_enable(struct device *dev)
Yinghai Lu70093f72004-07-01 03:55:03 +000026{
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020027 /* We have to enable MEM and Bus Master for IOAPIC */
28 uint16_t command = PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
Yinghai Lu70093f72004-07-01 03:55:03 +000029
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020030 pci_write_config16(dev, PCI_COMMAND, command);
Yinghai Lu70093f72004-07-01 03:55:03 +000031}
32
Uwe Hermannb69cb5a2010-10-26 22:46:43 +000033/**
34 * Configure one of the IOAPICs in a P64H2.
35 *
36 * Note that a PCI bus scan will detect both IOAPICs, so this function
37 * will be called twice for each P64H2 in the system.
38 *
39 * @param dev PCI bus/device/function of P64H2 IOAPIC.
40 * NOTE: There are two IOAPICs per P64H2, at D28:F0 and D30:F0.
41 */
Elyes HAOUAS17c59f52018-05-13 13:38:38 +020042static void p64h2_ioapic_init(struct device *dev)
Yinghai Lu70093f72004-07-01 03:55:03 +000043{
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020044 uint32_t memoryBase;
45 int apic_index, apic_id;
Yinghai Lu70093f72004-07-01 03:55:03 +000046
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020047 volatile uint32_t* pIndexRegister; /* io apic io memory space command address */
48 volatile uint32_t* pWindowRegister; /* io apic io memory space data address */
Yinghai Lu70093f72004-07-01 03:55:03 +000049
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020050 apic_index = num_p64h2_ioapics;
51 num_p64h2_ioapics++;
Yinghai Lu70093f72004-07-01 03:55:03 +000052
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020053 // A note on IOAPIC addresses:
54 // 0 and 1 are used for the local APICs of the dual virtual
55 // (hyper-threaded) CPUs of physical CPU 0 (devicetree.cb).
56 // 6 and 7 are used for the local APICs of the dual virtual
57 // (hyper-threaded) CPUs of physical CPU 1 (devicetree.cb).
58 // 2 is used for the IOAPIC in the 82801 southbridge (hard-coded in i82801xx_lpc.c)
Yinghai Lu70093f72004-07-01 03:55:03 +000059
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020060 // Map APIC index into APIC ID
61 // IDs 3, 4, 5, and 8+ are available (see above note)
Yinghai Lu70093f72004-07-01 03:55:03 +000062
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020063 if (apic_index < 3)
64 apic_id = apic_index + 3;
65 else
66 apic_id = apic_index + 5;
Yinghai Lu70093f72004-07-01 03:55:03 +000067
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020068 ASSERT(apic_id < 16); // ID is only 4 bits
Yinghai Lu70093f72004-07-01 03:55:03 +000069
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020070 // Read the MBAR address for setting up the IOAPIC in memory space
71 // NOTE: this address was assigned during enumeration of the bus
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000072
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020073 memoryBase = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
74 pIndexRegister = (volatile uint32_t*) memoryBase;
75 pWindowRegister = (volatile uint32_t*)(memoryBase + 0x10);
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000076
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020077 printk(BIOS_DEBUG, "IOAPIC %d at %02x:%02x.%01x MBAR = %p DataAddr = %p\n",
78 apic_id, dev->bus->secondary, PCI_SLOT(dev->path.pci.devfn),
79 PCI_FUNC(dev->path.pci.devfn), pIndexRegister, pWindowRegister);
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000080
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020081 apic_id <<= 24; // Convert ID to bitmask
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000082
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020083 *pIndexRegister = 0; // Select APIC ID register
Elyes HAOUASccd233b2017-07-03 21:48:52 +020084 *pWindowRegister = (*pWindowRegister & ~(0x0f << 24)) | apic_id; // Set the ID
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000085
Elyes HAOUASccd233b2017-07-03 21:48:52 +020086 if ((*pWindowRegister & (0x0f << 24)) != apic_id)
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020087 die("p64h2_ioapic_init failed");
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000088
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020089 *pIndexRegister = 3; // Select Boot Configuration register
90 *pWindowRegister |= 1; // Use Processor System Bus to deliver interrupts
Steven J. Magnani09e4ef62005-09-14 13:56:25 +000091
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020092 if (!(*pWindowRegister & 1))
93 die("p64h2_ioapic_init failed");
Yinghai Lu70093f72004-07-01 03:55:03 +000094}
95
96static struct device_operations ioapic_ops = {
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020097 .read_resources = pci_dev_read_resources,
98 .set_resources = pci_dev_set_resources,
99 .enable_resources = pci_dev_enable_resources,
100 .init = p64h2_ioapic_init,
101 .scan_bus = 0,
102 .enable = p64h2_ioapic_enable,
Yinghai Lu70093f72004-07-01 03:55:03 +0000103};
104
Stefan Reinauerf1cf1f72007-10-24 09:08:58 +0000105static const struct pci_driver ioapic_driver __pci_driver = {
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200106 .ops = &ioapic_ops,
107 .vendor = PCI_VENDOR_ID_INTEL,
108 .device = PCI_DEVICE_ID_INTEL_82870_1E0,
Yinghai Lu70093f72004-07-01 03:55:03 +0000109
110};