blob: ac637ff81784a077ff265929b7bd23b2d7e23cc9 [file] [log] [blame]
Marc Jones8ae8c882007-12-19 01:32:08 +00001/*
Stefan Reinauer7e61e452008-01-18 10:35:56 +00002 * This file is part of the coreboot project.
Marc Jones8ae8c882007-12-19 01:32:08 +00003 *
Marc Jones8ae8c882007-12-19 01:32:08 +00004 * 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.
Marc Jones8ae8c882007-12-19 01:32:08 +000012 */
13
Marc Jones8ae8c882007-12-19 01:32:08 +000014#include <console/console.h>
Marc Jones8ae8c882007-12-19 01:32:08 +000015#include <cpu/x86/lapic.h>
16#include <device/device.h>
17#include <device/pci.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020018#include <device/pci_ops.h>
Marc Jones8ae8c882007-12-19 01:32:08 +000019#include <pc80/mc146818rtc.h>
20#include <smp/spinlock.h>
21#include <cpu/x86/mtrr.h>
Stefan Reinauer991f1842015-11-22 23:40:29 +010022#include <cpu/amd/msr.h>
Marc Jones8ae8c882007-12-19 01:32:08 +000023#include <cpu/amd/model_10xxx_rev.h>
24#include <cpu/amd/amdfam10_sysconf.h>
25
Elyes HAOUAS99f0a512018-05-04 18:09:27 +020026extern struct device *get_node_pci(u32 nodeid, u32 fn);
Marc Jones8ae8c882007-12-19 01:32:08 +000027
28#if 0
29static int first_time = 1;
30#endif
31
32#include "quadcore_id.c"
33
34static u32 get_max_siblings(u32 nodes)
35{
Elyes HAOUAS99f0a512018-05-04 18:09:27 +020036 struct device *dev;
Marc Jones8ae8c882007-12-19 01:32:08 +000037 u32 nodeid;
Evelyn Huang284409f2017-05-30 16:05:58 -060038 u32 siblings = 0;
Marc Jones8ae8c882007-12-19 01:32:08 +000039
40 //get max siblings from all the nodes
Evelyn Huang284409f2017-05-30 16:05:58 -060041 for (nodeid = 0; nodeid < nodes; nodeid++) {
Marc Jones8ae8c882007-12-19 01:32:08 +000042 int j;
43 dev = get_node_pci(nodeid, 3);
44 j = (pci_read_config32(dev, 0xe8) >> 12) & 3;
Evelyn Huang284409f2017-05-30 16:05:58 -060045 if (siblings < j)
Marc Jones8ae8c882007-12-19 01:32:08 +000046 siblings = j;
Marc Jones8ae8c882007-12-19 01:32:08 +000047 }
48
49 return siblings;
50}
51
52
53static void enable_apic_ext_id(u32 nodes)
54{
Elyes HAOUAS99f0a512018-05-04 18:09:27 +020055 struct device *dev;
Marc Jones8ae8c882007-12-19 01:32:08 +000056 u32 nodeid;
57
58 //enable APIC_EXIT_ID all the nodes
Evelyn Huang284409f2017-05-30 16:05:58 -060059 for (nodeid = 0; nodeid < nodes; nodeid++) {
Marc Jones8ae8c882007-12-19 01:32:08 +000060 u32 val;
61 dev = get_node_pci(nodeid, 0);
62 val = pci_read_config32(dev, 0x68);
Elyes HAOUAS168ef392017-06-27 22:54:42 +020063 val |= (1 << 17)|(1 << 18);
Marc Jones8ae8c882007-12-19 01:32:08 +000064 pci_write_config32(dev, 0x68, val);
65 }
66}
67
68
69u32 get_apicid_base(u32 ioapic_num)
70{
71 u32 apicid_base;
72 u32 siblings;
73 u32 nb_cfg_54;
74
Julius Werner5d1f9a02019-03-07 17:07:26 -080075 u32 disable_siblings = !CONFIG(LOGICAL_CPUS);
Marc Jones8ae8c882007-12-19 01:32:08 +000076
Myles Watson4839e2c2010-04-08 15:06:44 +000077 get_option(&disable_siblings, "multi_core");
Marc Jones8ae8c882007-12-19 01:32:08 +000078
79 siblings = get_max_siblings(sysconf.nodes);
80
Evelyn Huang284409f2017-05-30 16:05:58 -060081 if (sysconf.bsp_apicid > 0) {
82 // IOAPIC could start from 0
Marc Jones8ae8c882007-12-19 01:32:08 +000083 return 0;
Evelyn Huang284409f2017-05-30 16:05:58 -060084 } else if (sysconf.enabled_apic_ext_id) {
85 // enabled ext id but bsp = 0
Marc Jones8ae8c882007-12-19 01:32:08 +000086 return 1;
87 }
88
89 nb_cfg_54 = read_nb_cfg_54();
90
91
Martin Roth4c3ab732013-07-08 16:23:54 -060092 //Construct apicid_base
Marc Jones8ae8c882007-12-19 01:32:08 +000093
Evelyn Huang284409f2017-05-30 16:05:58 -060094 if ((!disable_siblings) && (siblings > 0)) {
Martin Roth4c3ab732013-07-08 16:23:54 -060095 /* for 8 way dual core, we will used up apicid 16:16, actually
Marc Jones8ae8c882007-12-19 01:32:08 +000096 16 is not allowed by current kernel and the kernel will try
Elyes HAOUASd6e96862016-08-21 10:12:15 +020097 to get one that is small than 16 to make IOAPIC work. I don't
98 know when the kernel can support 256 APIC id.
Marc Jones8ae8c882007-12-19 01:32:08 +000099 (APIC_EXT_ID is enabled) */
100
101 //4:10 for two way 8:12 for four way 16:16 for eight way
Evelyn Huang284409f2017-05-30 16:05:58 -0600102 //Use CONFIG_MAX_PHYSICAL_CPUS instead of nodes
103 //for better consistency?
104 apicid_base = nb_cfg_54 ? (siblings+1) * sysconf.nodes :
105 8 * siblings + sysconf.nodes;
Marc Jones8ae8c882007-12-19 01:32:08 +0000106
107 } else {
108 apicid_base = sysconf.nodes;
109 }
110
Evelyn Huang284409f2017-05-30 16:05:58 -0600111 if ((apicid_base+ioapic_num-1) > 0xf) {
Marc Jones8ae8c882007-12-19 01:32:08 +0000112 // We need to enable APIC EXT ID
Elyes HAOUAS7c8d74c2016-08-23 21:41:43 +0200113 printk(BIOS_SPEW, "if the IOAPIC device doesn't support 256 APIC id,\n you need to set CONFIG_ENABLE_APIC_EXT_ID in MB Option.lb so you can spare 16 id for IOAPIC\n");
Marc Jones8ae8c882007-12-19 01:32:08 +0000114 enable_apic_ext_id(sysconf.nodes);
115 }
116
117 return apicid_base;
118}