blob: 7a73ecff694cbbfa2006fd69fb692d8ce2015bdb [file] [log] [blame]
Stefan Reinauere2b53e12004-06-28 11:59:45 +00001#include <console/console.h>
2#include <arch/io.h>
Uwe Hermann74d1a6e2010-10-12 17:34:08 +00003#include <arch/ioapic.h>
Stefan Reinauere2b53e12004-06-28 11:59:45 +00004#include <stdint.h>
Stefan Reinauere2b53e12004-06-28 11:59:45 +00005#include <device/device.h>
6#include <device/pci.h>
Stefan Reinauere2b53e12004-06-28 11:59:45 +00007#include <stdlib.h>
8#include <string.h>
9#include <bitops.h>
10#include "chip.h"
Myles Watson2e672732009-11-12 16:38:03 +000011#include <delay.h>
Stefan Reinauere2b53e12004-06-28 11:59:45 +000012
Myles Watsonb8e20272009-10-15 13:35:47 +000013#if CONFIG_WRITE_HIGH_TABLES==1
Myles Watson0520d552009-05-11 22:44:14 +000014#define HIGH_TABLES_SIZE 64 // maximum size of high tables in KB
15extern uint64_t high_tables_base, high_tables_size;
16#endif
17
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000018#define CMOS_ADDR_PORT 0x70
19#define CMOS_DATA_PORT 0x71
20#define HIGH_RAM_ADDR 0x35
21#define LOW_RAM_ADDR 0x34
22
Myles Watson29cc9ed2009-07-02 18:56:24 +000023static void cpu_pci_domain_set_resources(device_t dev)
Eric Biederman6e53f502004-10-27 08:53:57 +000024{
Myles Watson894a3472010-06-09 22:41:35 +000025 u32 pci_tolm = find_pci_tolm(dev->link_list);
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000026 unsigned long tomk = 0, tolmk;
27 int idx;
Eric Biederman6e53f502004-10-27 08:53:57 +000028
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000029 outb (HIGH_RAM_ADDR, CMOS_ADDR_PORT);
30 tomk = ((unsigned long) inb(CMOS_DATA_PORT)) << 14;
31 outb (LOW_RAM_ADDR, CMOS_ADDR_PORT);
32 tomk |= ((unsigned long) inb(CMOS_DATA_PORT)) << 6;
33 tomk += 16 * 1024;
Ronald G. Minnich9cf642b2006-09-13 04:12:35 +000034
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000035 printk(BIOS_DEBUG, "Detected %lu Kbytes (%lu MiB) RAM.\n",
36 tomk, tomk / 1024);
Myles Watson032a9652009-05-11 22:24:53 +000037
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000038 /* Compute the top of Low memory */
39 tolmk = pci_tolm >> 10;
40 if (tolmk >= tomk) {
41 /* The PCI hole does not overlap the memory. */
42 tolmk = tomk;
43 }
44
45 /* Report the memory regions. */
46 idx = 10;
47 ram_resource(dev, idx++, 0, 640);
48 ram_resource(dev, idx++, 768, tolmk - 768);
Myles Watson0520d552009-05-11 22:44:14 +000049
Myles Watsonb8e20272009-10-15 13:35:47 +000050#if CONFIG_WRITE_HIGH_TABLES==1
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000051 /* Leave some space for ACPI, PIRQ and MP tables */
52 high_tables_base = (tomk - HIGH_TABLES_SIZE) * 1024;
53 high_tables_size = HIGH_TABLES_SIZE * 1024;
Myles Watson0520d552009-05-11 22:44:14 +000054#endif
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000055
Myles Watson894a3472010-06-09 22:41:35 +000056 assign_resources(dev->link_list);
Eric Biederman6e53f502004-10-27 08:53:57 +000057}
Stefan Reinauere2b53e12004-06-28 11:59:45 +000058
Myles Watson29cc9ed2009-07-02 18:56:24 +000059static void cpu_pci_domain_read_resources(struct device *dev)
Eric Biederman6e53f502004-10-27 08:53:57 +000060{
Myles Watson29cc9ed2009-07-02 18:56:24 +000061 struct resource *res;
62
63 pci_domain_read_resources(dev);
64
65 /* Reserve space for the IOAPIC. This should be in the Southbridge,
66 * but I couldn't tell which device to put it in. */
67 res = new_resource(dev, 2);
Uwe Hermann74d1a6e2010-10-12 17:34:08 +000068 res->base = IO_APIC_ADDR;
Myles Watson29cc9ed2009-07-02 18:56:24 +000069 res->size = 0x100000UL;
70 res->limit = 0xffffffffUL;
71 res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_STORED |
72 IORESOURCE_ASSIGNED;
73
74 /* Reserve space for the LAPIC. There's one in every processor, but
75 * the space only needs to be reserved once, so we do it here. */
76 res = new_resource(dev, 3);
77 res->base = 0xfee00000UL;
78 res->size = 0x10000UL;
79 res->limit = 0xffffffffUL;
80 res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_STORED |
81 IORESOURCE_ASSIGNED;
Eric Biederman6e53f502004-10-27 08:53:57 +000082}
83
84static struct device_operations pci_domain_ops = {
Myles Watson29cc9ed2009-07-02 18:56:24 +000085 .read_resources = cpu_pci_domain_read_resources,
86 .set_resources = cpu_pci_domain_set_resources,
Myles Watson7eac4452010-06-17 16:16:56 +000087 .enable_resources = NULL,
88 .init = NULL,
Myles Watson032a9652009-05-11 22:24:53 +000089 .scan_bus = pci_domain_scan_bus,
90};
Eric Biederman6e53f502004-10-27 08:53:57 +000091
92static void enable_dev(struct device *dev)
93{
Eric Biederman018d8dd2004-11-04 11:04:33 +000094 /* Set the operations if it is a special bus type */
95 if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
96 dev->ops = &pci_domain_ops;
Eric Biedermana9e632c2004-11-18 22:38:08 +000097 pci_set_method(dev);
Eric Biederman018d8dd2004-11-04 11:04:33 +000098 }
Stefan Reinauere2b53e12004-06-28 11:59:45 +000099}
100
Patrick Georgi35784b62010-04-08 12:47:35 +0000101struct chip_operations mainboard_emulation_qemu_x86_ops = {
Eric Biederman018d8dd2004-11-04 11:04:33 +0000102 CHIP_NAME("QEMU Northbridge")
Eric Biederman6e53f502004-10-27 08:53:57 +0000103 .enable_dev = enable_dev,
Stefan Reinauere2b53e12004-06-28 11:59:45 +0000104};