blob: 7b84928883ef3db8e9099ff8ff744b03b580072a [file] [log] [blame]
Stefan Reinauere2b53e12004-06-28 11:59:45 +00001#include <console/console.h>
2#include <arch/io.h>
3#include <stdint.h>
Stefan Reinauere2b53e12004-06-28 11:59:45 +00004#include <device/device.h>
5#include <device/pci.h>
Stefan Reinauere2b53e12004-06-28 11:59:45 +00006#include <stdlib.h>
7#include <string.h>
8#include <bitops.h>
9#include "chip.h"
Myles Watson2e672732009-11-12 16:38:03 +000010#include <delay.h>
Stefan Reinauere2b53e12004-06-28 11:59:45 +000011
Stefan Reinauere4932dc2004-11-02 20:33:12 +000012static void ram_resource(device_t dev, unsigned long index,
Eric Biederman018d8dd2004-11-04 11:04:33 +000013 unsigned long basek, unsigned long sizek)
Stefan Reinauere4932dc2004-11-02 20:33:12 +000014{
Eric Biederman018d8dd2004-11-04 11:04:33 +000015 struct resource *resource;
Stefan Reinauere4932dc2004-11-02 20:33:12 +000016
Eric Biederman018d8dd2004-11-04 11:04:33 +000017 if (!sizek) {
18 return;
19 }
20 resource = new_resource(dev, index);
21 resource->base = ((resource_t)basek) << 10;
22 resource->size = ((resource_t)sizek) << 10;
23 resource->flags = IORESOURCE_MEM | IORESOURCE_CACHEABLE | \
24 IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
Stefan Reinauere4932dc2004-11-02 20:33:12 +000025}
26
Eric Biederman018d8dd2004-11-04 11:04:33 +000027static void tolm_test(void *gp, struct device *dev, struct resource *new)
28{
29 struct resource **best_p = gp;
30 struct resource *best;
31 best = *best_p;
32 if (!best || (best->base > new->base)) {
33 best = new;
34 }
35 *best_p = best;
36}
37
38static uint32_t find_pci_tolm(struct bus *bus)
39{
40 struct resource *min;
41 uint32_t tolm;
42 min = 0;
43 search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM, tolm_test, &min);
44 tolm = 0xffffffffUL;
45 if (min && tolm > min->base) {
46 tolm = min->base;
47 }
48 return tolm;
49}
Stefan Reinauere4932dc2004-11-02 20:33:12 +000050
Myles Watsonb8e20272009-10-15 13:35:47 +000051#if CONFIG_WRITE_HIGH_TABLES==1
Myles Watson0520d552009-05-11 22:44:14 +000052#define HIGH_TABLES_SIZE 64 // maximum size of high tables in KB
53extern uint64_t high_tables_base, high_tables_size;
54#endif
55
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000056#define CMOS_ADDR_PORT 0x70
57#define CMOS_DATA_PORT 0x71
58#define HIGH_RAM_ADDR 0x35
59#define LOW_RAM_ADDR 0x34
60
Myles Watson29cc9ed2009-07-02 18:56:24 +000061static void cpu_pci_domain_set_resources(device_t dev)
Eric Biederman6e53f502004-10-27 08:53:57 +000062{
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000063 u32 pci_tolm = find_pci_tolm(&dev->link[0]);
64 unsigned long tomk = 0, tolmk;
65 int idx;
Eric Biederman6e53f502004-10-27 08:53:57 +000066
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000067 outb (HIGH_RAM_ADDR, CMOS_ADDR_PORT);
68 tomk = ((unsigned long) inb(CMOS_DATA_PORT)) << 14;
69 outb (LOW_RAM_ADDR, CMOS_ADDR_PORT);
70 tomk |= ((unsigned long) inb(CMOS_DATA_PORT)) << 6;
71 tomk += 16 * 1024;
Ronald G. Minnich9cf642b2006-09-13 04:12:35 +000072
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000073 printk(BIOS_DEBUG, "Detected %lu Kbytes (%lu MiB) RAM.\n",
74 tomk, tomk / 1024);
Myles Watson032a9652009-05-11 22:24:53 +000075
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000076 /* Compute the top of Low memory */
77 tolmk = pci_tolm >> 10;
78 if (tolmk >= tomk) {
79 /* The PCI hole does not overlap the memory. */
80 tolmk = tomk;
81 }
82
83 /* Report the memory regions. */
84 idx = 10;
85 ram_resource(dev, idx++, 0, 640);
86 ram_resource(dev, idx++, 768, tolmk - 768);
Myles Watson0520d552009-05-11 22:44:14 +000087
Myles Watsonb8e20272009-10-15 13:35:47 +000088#if CONFIG_WRITE_HIGH_TABLES==1
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000089 /* Leave some space for ACPI, PIRQ and MP tables */
90 high_tables_base = (tomk - HIGH_TABLES_SIZE) * 1024;
91 high_tables_size = HIGH_TABLES_SIZE * 1024;
Myles Watson0520d552009-05-11 22:44:14 +000092#endif
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000093
Eric Biederman6e53f502004-10-27 08:53:57 +000094 assign_resources(&dev->link[0]);
95}
Stefan Reinauere2b53e12004-06-28 11:59:45 +000096
Myles Watson29cc9ed2009-07-02 18:56:24 +000097static void cpu_pci_domain_read_resources(struct device *dev)
Eric Biederman6e53f502004-10-27 08:53:57 +000098{
Myles Watson29cc9ed2009-07-02 18:56:24 +000099 struct resource *res;
100
101 pci_domain_read_resources(dev);
102
103 /* Reserve space for the IOAPIC. This should be in the Southbridge,
104 * but I couldn't tell which device to put it in. */
105 res = new_resource(dev, 2);
106 res->base = 0xfec00000UL;
107 res->size = 0x100000UL;
108 res->limit = 0xffffffffUL;
109 res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_STORED |
110 IORESOURCE_ASSIGNED;
111
112 /* Reserve space for the LAPIC. There's one in every processor, but
113 * the space only needs to be reserved once, so we do it here. */
114 res = new_resource(dev, 3);
115 res->base = 0xfee00000UL;
116 res->size = 0x10000UL;
117 res->limit = 0xffffffffUL;
118 res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_STORED |
119 IORESOURCE_ASSIGNED;
Eric Biederman6e53f502004-10-27 08:53:57 +0000120}
121
122static struct device_operations pci_domain_ops = {
Myles Watson29cc9ed2009-07-02 18:56:24 +0000123 .read_resources = cpu_pci_domain_read_resources,
124 .set_resources = cpu_pci_domain_set_resources,
Myles Watson032a9652009-05-11 22:24:53 +0000125 .enable_resources = enable_childrens_resources,
126 .init = 0,
127 .scan_bus = pci_domain_scan_bus,
128};
Eric Biederman6e53f502004-10-27 08:53:57 +0000129
130static void enable_dev(struct device *dev)
131{
Eric Biederman018d8dd2004-11-04 11:04:33 +0000132 /* Set the operations if it is a special bus type */
133 if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
134 dev->ops = &pci_domain_ops;
Eric Biedermana9e632c2004-11-18 22:38:08 +0000135 pci_set_method(dev);
Eric Biederman018d8dd2004-11-04 11:04:33 +0000136 }
Stefan Reinauere2b53e12004-06-28 11:59:45 +0000137}
138
Patrick Georgi35784b62010-04-08 12:47:35 +0000139struct chip_operations mainboard_emulation_qemu_x86_ops = {
Eric Biederman018d8dd2004-11-04 11:04:33 +0000140 CHIP_NAME("QEMU Northbridge")
Eric Biederman6e53f502004-10-27 08:53:57 +0000141 .enable_dev = enable_dev,
Stefan Reinauere2b53e12004-06-28 11:59:45 +0000142};