2 * This file is part of the coreboot project.
4 * Copyright (C) 2007-2009 coresystems GmbH
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <console/console.h>
19 #include <device/device.h>
20 #include <device/pci.h>
21 #include <device/pci_ids.h>
26 #include <arch/acpi.h>
29 static int get_pcie_bar(u32
*base
)
34 dev
= dev_find_slot(0, PCI_DEVFN(0, 0));
38 /* FIXME: Determine at runtime. */
40 pciexbar_reg
= sch_port_access_read(0, 0, 4);
42 pciexbar_reg
= sch_port_access_read(2, 9, 4);
45 if (!(pciexbar_reg
& (1 << 0)))
48 switch ((pciexbar_reg
>> 1) & 3) {
50 *base
= pciexbar_reg
& ((1 << 31) | (1 << 30) | (1 << 29) |
54 *base
= pciexbar_reg
& ((1 << 31) | (1 << 30) | (1 << 29) |
55 (1 << 28) | (1 << 27));
58 *base
= pciexbar_reg
& ((1 << 31) | (1 << 30) | (1 << 29) |
59 (1 << 28) | (1 << 27) | (1 << 26));
66 static void add_fixed_resources(struct device
*dev
, int index
)
68 struct resource
*resource
;
70 printk(BIOS_DEBUG
, "Adding CMC shadow area\n");
71 resource
= new_resource(dev
, index
++);
72 resource
->base
= (resource_t
) CMC_SHADOW
;
73 resource
->size
= (resource_t
) (64 * 1024);
74 resource
->flags
= IORESOURCE_MEM
| IORESOURCE_RESERVE
|
75 IORESOURCE_FIXED
| IORESOURCE_STORED
| IORESOURCE_ASSIGNED
;
78 static void pci_domain_set_resources(device_t dev
)
83 unsigned long long tomk
, tolud
, tomk_stolen
;
84 uint64_t uma_memory_base
= 0, uma_memory_size
= 0;
85 uint64_t tseg_memory_base
= 0, tseg_memory_size
= 0;
87 /* Can we find out how much memory we can use at most this way? */
88 pci_tolm
= find_pci_tolm(dev
->link_list
);
89 printk(BIOS_DEBUG
, "pci_tolm: 0x%x\n", pci_tolm
);
90 printk(BIOS_SPEW
, "Base of stolen memory: 0x%08x\n",
91 pci_read_config32(dev_find_slot(0, PCI_DEVFN(2, 0)), 0x5c));
93 tolud
= sch_port_access_read(2, 8, 4);
94 printk(BIOS_SPEW
, "Top of Low Used DRAM: 0x%08llx\n", tolud
);
99 /* Note: subtract IGD device and TSEG. */
100 reg8
= pci_read_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), 0x9e);
103 printk(BIOS_DEBUG
, "TSEG decoded, subtracting ");
108 tseg_size
= 1024; /* TSEG = 1M */
111 tseg_size
= 2048; /* TSEG = 2M */
114 tseg_size
= 8192; /* TSEG = 8M */
118 printk(BIOS_DEBUG
, "%dM\n", tseg_size
>> 10);
119 tomk_stolen
-= tseg_size
;
121 /* For reserving TSEG memory in the memory map */
122 tseg_memory_base
= tomk_stolen
* 1024ULL;
123 tseg_memory_size
= tseg_size
* 1024ULL;
126 reg16
= pci_read_config16(dev_find_slot(0, PCI_DEVFN(2, 0)), GGC
);
129 printk(BIOS_DEBUG
, "IGD decoded, subtracting ");
143 printk(BIOS_DEBUG
, "%dM UMA\n", uma_size
>> 10);
144 tomk_stolen
-= uma_size
;
146 /* For reserving UMA memory in the memory map. */
147 uma_memory_base
= tomk_stolen
* 1024ULL;
148 uma_memory_size
= uma_size
* 1024ULL;
152 * The following needs to be 2 lines, otherwise the second
153 * number is always 0.
155 printk(BIOS_INFO
, "Available memory: %dK", (u32
) tomk
);
156 printk(BIOS_INFO
, " (%dM)\n", (u32
) (tomk
>> 10));
158 /* Report the memory regions. */
159 ram_resource(dev
, 3, 0, 640);
160 ram_resource(dev
, 4, 768, (tomk
- 768));
161 uma_resource(dev
, 5, uma_memory_base
>> 10, uma_memory_size
>> 10);
162 mmio_resource(dev
, 6, tseg_memory_base
>> 10, tseg_memory_size
>> 10);
164 add_fixed_resources(dev
, 7);
166 assign_resources(dev
->link_list
);
168 set_top_of_ram(tomk
* 1024 - uma_memory_size
- tseg_memory_base
);
172 * TODO: We could determine how many PCIe busses we need in the bar. For now
173 * that number is hardcoded to a max of 64.
174 * See e7525/northbridge.c for an example.
176 static struct device_operations pci_domain_ops
= {
177 .read_resources
= pci_domain_read_resources
,
178 .set_resources
= pci_domain_set_resources
,
179 .enable_resources
= NULL
,
181 .scan_bus
= pci_domain_scan_bus
,
182 .ops_pci_bus
= pci_bus_default_ops
,
185 static void mc_read_resources(device_t dev
)
187 u32 pcie_config_base
;
190 pci_dev_read_resources(dev
);
193 * We use 0xcf as an unused index for our PCIe bar so that we find
196 buses
= get_pcie_bar(&pcie_config_base
);
198 struct resource
*resource
= new_resource(dev
, 0xcf);
199 mmconf_resource_init(resource
, pcie_config_base
, buses
);
203 static void intel_set_subsystem(device_t dev
, unsigned vendor
, unsigned device
)
205 if (!vendor
|| !device
) {
206 pci_write_config32(dev
, PCI_SUBSYSTEM_VENDOR_ID
,
207 pci_read_config32(dev
, PCI_VENDOR_ID
));
209 pci_write_config32(dev
, PCI_SUBSYSTEM_VENDOR_ID
,
210 ((device
& 0xffff) << 16) | (vendor
& 0xffff));
214 static struct pci_operations intel_pci_ops
= {
215 .set_subsystem
= intel_set_subsystem
,
218 static struct device_operations mc_ops
= {
219 .read_resources
= mc_read_resources
,
220 .set_resources
= pci_dev_set_resources
,
221 .enable_resources
= pci_dev_enable_resources
,
222 .acpi_fill_ssdt_generator
= generate_cpu_entries
,
224 .ops_pci
= &intel_pci_ops
,
227 static const struct pci_driver mc_driver __pci_driver
= {
229 .vendor
= PCI_VENDOR_ID_INTEL
,
233 static void cpu_bus_init(device_t dev
)
235 initialize_cpus(dev
->link_list
);
238 static struct device_operations cpu_bus_ops
= {
239 .read_resources
= DEVICE_NOOP
,
240 .set_resources
= DEVICE_NOOP
,
241 .enable_resources
= DEVICE_NOOP
,
242 .init
= cpu_bus_init
,
246 static void enable_dev(device_t dev
)
248 /* Set the operations if it is a special bus type. */
249 if (dev
->path
.type
== DEVICE_PATH_DOMAIN
) {
250 dev
->ops
= &pci_domain_ops
;
251 } else if (dev
->path
.type
== DEVICE_PATH_CPU_CLUSTER
) {
252 dev
->ops
= &cpu_bus_ops
;
256 struct chip_operations northbridge_intel_sch_ops
= {
257 CHIP_NAME("Intel SCH Northbridge")
258 .enable_dev
= enable_dev
,