blob: 34c868e0f39fdde7d0375ada23d1ffd90f45866e [file] [log] [blame]
Richard Smithcb8eab42006-07-24 04:25:47 +00001#include <console/console.h>
2#include <arch/io.h>
3#include <stdint.h>
4#include <device/device.h>
5#include <device/pci.h>
6#include <device/pci_ids.h>
7#include <stdlib.h>
8#include <string.h>
9#include <bitops.h>
Corey Osgoode562f722008-12-19 03:36:48 +000010#include <cpu/cpu.h>
11#include <pc80/keyboard.h>
Richard Smithcb8eab42006-07-24 04:25:47 +000012#include "chip.h"
13#include "northbridge.h"
Uwe Hermann1a9c8922007-04-01 17:24:03 +000014#include "i440bx.h"
Richard Smithcb8eab42006-07-24 04:25:47 +000015
Myles Watson032a9652009-05-11 22:24:53 +000016static void northbridge_init(device_t dev)
Richard Smithcb8eab42006-07-24 04:25:47 +000017{
18 printk_spew("Northbridge Init\n");
19}
20
Richard Smithcb8eab42006-07-24 04:25:47 +000021static struct device_operations northbridge_operations = {
22 .read_resources = pci_dev_read_resources,
23 .set_resources = pci_dev_set_resources,
24 .enable_resources = pci_dev_enable_resources,
25 .init = northbridge_init,
26 .enable = 0,
27 .ops_pci = 0,
28};
29
Stefan Reinauerf1cf1f72007-10-24 09:08:58 +000030static const struct pci_driver northbridge_driver __pci_driver = {
Richard Smithcb8eab42006-07-24 04:25:47 +000031 .ops = &northbridge_operations,
32 .vendor = PCI_VENDOR_ID_INTEL,
Myles Watson032a9652009-05-11 22:24:53 +000033 .device = 0x7190,
Richard Smithcb8eab42006-07-24 04:25:47 +000034};
35
36
Richard Smithcb8eab42006-07-24 04:25:47 +000037#define BRIDGE_IO_MASK (IORESOURCE_IO | IORESOURCE_MEM)
38
39static void pci_domain_read_resources(device_t dev)
40{
Myles Watson032a9652009-05-11 22:24:53 +000041 struct resource *resource;
Richard Smithcb8eab42006-07-24 04:25:47 +000042
Myles Watson032a9652009-05-11 22:24:53 +000043 /* Initialize the system wide io space constraints */
44 resource = new_resource(dev, IOINDEX_SUBTRACTIVE(0,0));
45 resource->limit = 0xffffUL;
46 resource->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
Richard Smithcb8eab42006-07-24 04:25:47 +000047
Myles Watson032a9652009-05-11 22:24:53 +000048 /* Initialize the system wide memory resources constraints */
49 resource = new_resource(dev, IOINDEX_SUBTRACTIVE(1,0));
50 resource->limit = 0xffffffffULL;
51 resource->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
Richard Smithcb8eab42006-07-24 04:25:47 +000052}
53
54static void ram_resource(device_t dev, unsigned long index,
Myles Watson032a9652009-05-11 22:24:53 +000055 unsigned long basek, unsigned long sizek)
Richard Smithcb8eab42006-07-24 04:25:47 +000056{
Myles Watson032a9652009-05-11 22:24:53 +000057 struct resource *resource;
Richard Smithcb8eab42006-07-24 04:25:47 +000058
Myles Watson032a9652009-05-11 22:24:53 +000059 if (!sizek) {
60 return;
61 }
62 resource = new_resource(dev, index);
63 resource->base = ((resource_t)basek) << 10;
64 resource->size = ((resource_t)sizek) << 10;
65 resource->flags = IORESOURCE_MEM | IORESOURCE_CACHEABLE | \
66 IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
Richard Smithcb8eab42006-07-24 04:25:47 +000067}
68
69static void tolm_test(void *gp, struct device *dev, struct resource *new)
70{
71 struct resource **best_p = gp;
72 struct resource *best;
73 best = *best_p;
74 if (!best || (best->base > new->base)) {
75 best = new;
76 }
77 *best_p = best;
78}
79
80static uint32_t find_pci_tolm(struct bus *bus)
81{
82 struct resource *min;
83 uint32_t tolm;
84 min = 0;
85 search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM, tolm_test, &min);
86 tolm = 0xffffffffUL;
87 if (min && tolm > min->base) {
88 tolm = min->base;
89 }
90 return tolm;
91}
92
Stefan Reinauer08670622009-06-30 15:17:49 +000093#if CONFIG_HAVE_HIGH_TABLES==1
Stefan Reinauerb5fb0c52009-04-30 13:58:42 +000094#define HIGH_TABLES_SIZE 64 // maximum size of high tables in KB
95extern uint64_t high_tables_base, high_tables_size;
96#endif
Myles Watson032a9652009-05-11 22:24:53 +000097
Richard Smithcb8eab42006-07-24 04:25:47 +000098static void pci_domain_set_resources(device_t dev)
99{
Richard Smithcb8eab42006-07-24 04:25:47 +0000100 device_t mc_dev;
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000101 uint32_t pci_tolm;
Richard Smithcb8eab42006-07-24 04:25:47 +0000102
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000103 pci_tolm = find_pci_tolm(&dev->link[0]);
Richard Smithcb8eab42006-07-24 04:25:47 +0000104 mc_dev = dev->link[0].children;
105 if (mc_dev) {
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000106 uint16_t tolm_r;
Richard Smithcb8eab42006-07-24 04:25:47 +0000107 unsigned long tomk, tolmk;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000108 int idx;
Richard Smithcb8eab42006-07-24 04:25:47 +0000109
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000110 /* Figure out which areas are/should be occupied by RAM. The
111 * value of the highest DRB denotes the end of the physical
112 * memory (in units of 8MB).
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000113 */
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000114 tomk = ((unsigned long)pci_read_config8(mc_dev, DRB7));
Uwe Hermannf03e4e92007-05-10 23:59:20 +0000115
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000116 /* Convert to KB. */
117 tomk *= (8 * 1024);
118
119 printk_debug("Setting RAM size to %d MB\n", tomk / 1024);
120
121 /* Compute the top of low memory. */
122 tolmk = pci_tolm / 1024;
123
Richard Smithcb8eab42006-07-24 04:25:47 +0000124 if (tolmk >= tomk) {
Myles Watson032a9652009-05-11 22:24:53 +0000125 /* The PCI hole does not overlap the memory. */
Richard Smithcb8eab42006-07-24 04:25:47 +0000126 tolmk = tomk;
127 }
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000128
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000129 /* Report the memory regions. */
Richard Smithcb8eab42006-07-24 04:25:47 +0000130 idx = 10;
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000131 ram_resource(dev, idx++, 0, 640);
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000132 ram_resource(dev, idx++, 768, tolmk - 768);
Myles Watson032a9652009-05-11 22:24:53 +0000133
Stefan Reinauer08670622009-06-30 15:17:49 +0000134#if CONFIG_HAVE_HIGH_TABLES==1
Stefan Reinauerb5fb0c52009-04-30 13:58:42 +0000135 /* Leave some space for ACPI, PIRQ and MP tables */
136 high_tables_base = (tomk - HIGH_TABLES_SIZE) * 1024;
137 high_tables_size = HIGH_TABLES_SIZE * 1024;
138#endif
Richard Smithcb8eab42006-07-24 04:25:47 +0000139 }
140 assign_resources(&dev->link[0]);
141}
142
143static unsigned int pci_domain_scan_bus(device_t dev, unsigned int max)
144{
Myles Watson032a9652009-05-11 22:24:53 +0000145 max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0, 0), 0xff, max);
146 return max;
Richard Smithcb8eab42006-07-24 04:25:47 +0000147}
148
149static struct device_operations pci_domain_ops = {
Myles Watson032a9652009-05-11 22:24:53 +0000150 .read_resources = pci_domain_read_resources,
151 .set_resources = pci_domain_set_resources,
152 .enable_resources = enable_childrens_resources,
153 .init = 0,
154 .scan_bus = pci_domain_scan_bus,
155};
Richard Smithcb8eab42006-07-24 04:25:47 +0000156
157static void cpu_bus_init(device_t dev)
158{
Myles Watson032a9652009-05-11 22:24:53 +0000159 initialize_cpus(&dev->link[0]);
Richard Smithcb8eab42006-07-24 04:25:47 +0000160}
161
162static void cpu_bus_noop(device_t dev)
163{
164}
165
166static struct device_operations cpu_bus_ops = {
Myles Watson032a9652009-05-11 22:24:53 +0000167 .read_resources = cpu_bus_noop,
168 .set_resources = cpu_bus_noop,
169 .enable_resources = cpu_bus_noop,
170 .init = cpu_bus_init,
171 .scan_bus = 0,
Richard Smithcb8eab42006-07-24 04:25:47 +0000172};
173
174static void enable_dev(struct device *dev)
175{
Myles Watson032a9652009-05-11 22:24:53 +0000176 /* Set the operations if it is a special bus type */
177 if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
178 dev->ops = &pci_domain_ops;
Richard Smithcb8eab42006-07-24 04:25:47 +0000179 pci_set_method(dev);
Myles Watson032a9652009-05-11 22:24:53 +0000180 }
181 else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) {
182 dev->ops = &cpu_bus_ops;
183 }
Richard Smithcb8eab42006-07-24 04:25:47 +0000184}
185
186struct chip_operations northbridge_intel_i440bx_ops = {
Uwe Hermannf5a6fd22007-05-27 23:31:31 +0000187 CHIP_NAME("Intel 82443BX (440BX) Northbridge")
Uwe Hermann1a9c8922007-04-01 17:24:03 +0000188 .enable_dev = enable_dev,
Richard Smithcb8eab42006-07-24 04:25:47 +0000189};