blob: 18996482d6e810476c4a62484c84b2d64a40efd1 [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
Rudolf Marek97be27e2010-12-13 19:50:25 +000014#include <cbmem.h>
Myles Watson0520d552009-05-11 22:44:14 +000015#endif
16
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000017#define CMOS_ADDR_PORT 0x70
18#define CMOS_DATA_PORT 0x71
19#define HIGH_RAM_ADDR 0x35
20#define LOW_RAM_ADDR 0x34
21
Myles Watson29cc9ed2009-07-02 18:56:24 +000022static void cpu_pci_domain_set_resources(device_t dev)
Eric Biederman6e53f502004-10-27 08:53:57 +000023{
Myles Watson894a3472010-06-09 22:41:35 +000024 u32 pci_tolm = find_pci_tolm(dev->link_list);
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000025 unsigned long tomk = 0, tolmk;
26 int idx;
Eric Biederman6e53f502004-10-27 08:53:57 +000027
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000028 outb (HIGH_RAM_ADDR, CMOS_ADDR_PORT);
29 tomk = ((unsigned long) inb(CMOS_DATA_PORT)) << 14;
30 outb (LOW_RAM_ADDR, CMOS_ADDR_PORT);
31 tomk |= ((unsigned long) inb(CMOS_DATA_PORT)) << 6;
32 tomk += 16 * 1024;
Ronald G. Minnich9cf642b2006-09-13 04:12:35 +000033
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000034 printk(BIOS_DEBUG, "Detected %lu Kbytes (%lu MiB) RAM.\n",
35 tomk, tomk / 1024);
Myles Watson032a9652009-05-11 22:24:53 +000036
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000037 /* Compute the top of Low memory */
38 tolmk = pci_tolm >> 10;
39 if (tolmk >= tomk) {
40 /* The PCI hole does not overlap the memory. */
41 tolmk = tomk;
42 }
43
44 /* Report the memory regions. */
45 idx = 10;
46 ram_resource(dev, idx++, 0, 640);
47 ram_resource(dev, idx++, 768, tolmk - 768);
Myles Watson0520d552009-05-11 22:44:14 +000048
Myles Watsonb8e20272009-10-15 13:35:47 +000049#if CONFIG_WRITE_HIGH_TABLES==1
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000050 /* Leave some space for ACPI, PIRQ and MP tables */
Rudolf Marek97be27e2010-12-13 19:50:25 +000051 high_tables_base = (tomk * 1024) - HIGH_MEMORY_SIZE;
52 high_tables_size = HIGH_MEMORY_SIZE;
Myles Watson0520d552009-05-11 22:44:14 +000053#endif
Valdimir Serbinenko7339f362010-05-03 16:21:52 +000054
Myles Watson894a3472010-06-09 22:41:35 +000055 assign_resources(dev->link_list);
Eric Biederman6e53f502004-10-27 08:53:57 +000056}
Stefan Reinauere2b53e12004-06-28 11:59:45 +000057
Myles Watson29cc9ed2009-07-02 18:56:24 +000058static void cpu_pci_domain_read_resources(struct device *dev)
Eric Biederman6e53f502004-10-27 08:53:57 +000059{
Myles Watson29cc9ed2009-07-02 18:56:24 +000060 struct resource *res;
61
62 pci_domain_read_resources(dev);
63
64 /* Reserve space for the IOAPIC. This should be in the Southbridge,
65 * but I couldn't tell which device to put it in. */
66 res = new_resource(dev, 2);
Uwe Hermann74d1a6e2010-10-12 17:34:08 +000067 res->base = IO_APIC_ADDR;
Myles Watson29cc9ed2009-07-02 18:56:24 +000068 res->size = 0x100000UL;
69 res->limit = 0xffffffffUL;
70 res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_STORED |
71 IORESOURCE_ASSIGNED;
72
73 /* Reserve space for the LAPIC. There's one in every processor, but
74 * the space only needs to be reserved once, so we do it here. */
75 res = new_resource(dev, 3);
76 res->base = 0xfee00000UL;
77 res->size = 0x10000UL;
78 res->limit = 0xffffffffUL;
79 res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_STORED |
80 IORESOURCE_ASSIGNED;
Eric Biederman6e53f502004-10-27 08:53:57 +000081}
82
83static struct device_operations pci_domain_ops = {
Myles Watson29cc9ed2009-07-02 18:56:24 +000084 .read_resources = cpu_pci_domain_read_resources,
85 .set_resources = cpu_pci_domain_set_resources,
Myles Watson7eac4452010-06-17 16:16:56 +000086 .enable_resources = NULL,
87 .init = NULL,
Myles Watson032a9652009-05-11 22:24:53 +000088 .scan_bus = pci_domain_scan_bus,
89};
Eric Biederman6e53f502004-10-27 08:53:57 +000090
91static void enable_dev(struct device *dev)
92{
Eric Biederman018d8dd2004-11-04 11:04:33 +000093 /* Set the operations if it is a special bus type */
94 if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
95 dev->ops = &pci_domain_ops;
Eric Biedermana9e632c2004-11-18 22:38:08 +000096 pci_set_method(dev);
Eric Biederman018d8dd2004-11-04 11:04:33 +000097 }
Stefan Reinauere2b53e12004-06-28 11:59:45 +000098}
99
Patrick Georgi35784b62010-04-08 12:47:35 +0000100struct chip_operations mainboard_emulation_qemu_x86_ops = {
Eric Biederman018d8dd2004-11-04 11:04:33 +0000101 CHIP_NAME("QEMU Northbridge")
Eric Biederman6e53f502004-10-27 08:53:57 +0000102 .enable_dev = enable_dev,
Stefan Reinauere2b53e12004-06-28 11:59:45 +0000103};