1 #include <console/console.h>
5 #include <part/sizeram.h>
6 #include <device/device.h>
7 #include <device/pci.h>
8 #include <device/hypertransport.h>
9 #include <device/chip.h>
14 #include "northbridge.h"
16 struct mem_range *sizeram(void)
18 unsigned long mmio_basek;
19 static struct mem_range mem[10];
23 #warning "FIXME handle interleaved nodes"
24 dev = dev_find_slot(0, PCI_DEVFN(0x18, 1));
26 printk_err("Cannot find PCI: 0:18.1\n");
29 mmio_basek = (dev_root.resource[1].base >> 10);
30 /* Round mmio_basek to something the processor can support */
31 mmio_basek &= ~((1 << 6) -1);
34 #warning "FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M MMIO hole"
35 /* Round the mmio hold to 256M */
36 mmio_basek &= ~((256*1024) - 1);
40 printk_debug("mmio_base: %dKB\n", mmio_basek);
43 for(idx = i = 0; i < 8; i++) {
45 unsigned basek, limitk, sizek;
46 base = pci_read_config32(dev, 0x40 + (i<<3));
47 limit = pci_read_config32(dev, 0x44 + (i<<3));
48 if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) {
51 basek = (base & 0xffff0000) >> 2;
52 limitk = ((limit + 0x00010000) & 0xffff0000) >> 2;
53 sizek = limitk - basek;
55 ((mem[idx -1].basek + mem[idx - 1].sizek) == basek)) {
56 mem[idx -1].sizek += sizek;
59 mem[idx].basek = basek;
60 mem[idx].sizek = sizek;
63 /* See if I need to split the region to accomodate pci memory space */
64 if ((mem[idx - 1].basek <= mmio_basek) &&
65 ((mem[idx - 1].basek + mem[idx - 1].sizek) > mmio_basek)) {
66 if (mem[idx - 1].basek < mmio_basek) {
68 pre_sizek = mmio_basek - mem[idx - 1].basek;
69 mem[idx].basek = mmio_basek;
70 mem[idx].sizek = mem[idx - 1].sizek - pre_sizek;
71 mem[idx - 1].sizek = pre_sizek;
74 if ((mem[idx - 1].basek + mem[idx - 1].sizek) <= 4*1024*1024) {
78 mem[idx - 1].basek = 4*1024*1024;
79 mem[idx - 1].sizek -= (4*1024*1024 - mmio_basek);
84 for(i = 0; i < idx; i++) {
85 printk_debug("mem[%d].basek = %08x mem[%d].sizek = %08x\n",
86 i, mem[i].basek, i, mem[i].sizek);
89 while(idx < sizeof(mem)/sizeof(mem[0])) {
98 static device_t __f1_dev[F1_DEVS];
101 static void debug_f1_devs(void)
104 for(i = 0; i < F1_DEVS; i++) {
108 printk_debug("__f1_dev[%d]: %s bus: %p\n",
109 i, dev_path(dev), dev->bus);
115 static void get_f1_devs(void)
121 for(i = 0; i < F1_DEVS; i++) {
122 __f1_dev[i] = dev_find_slot(0, PCI_DEVFN(0x18 + i, 1));
125 die("Cannot find 0:0x18.1\n");
129 static uint32_t f1_read_config32(unsigned reg)
132 return pci_read_config32(__f1_dev[0], reg);
135 static void f1_write_config32(unsigned reg, uint32_t value)
139 for(i = 0; i < F1_DEVS; i++) {
143 pci_write_config32(dev, reg, value);
148 static unsigned int amdk8_nodeid(device_t dev)
150 return (dev->path.u.pci.devfn >> 3) - 0x18;
154 #define LinkConnected (1 << 0)
155 #define InitComplete (1 << 1)
156 #define NonCoherent (1 << 2)
157 #define ConnectionPending (1 << 4)
158 static unsigned int amdk8_scan_chains(device_t dev, unsigned int max)
162 nodeid = amdk8_nodeid(dev);
164 printk_debug("amdk8_scan_chains max: %d starting...\n", max);
166 for(link = 0; link < dev->links; link++) {
168 uint32_t busses, config_busses;
169 unsigned free_reg, config_reg;
170 dev->link[link].cap = 0x80 + (link *0x20);
172 link_type = pci_read_config32(dev, dev->link[link].cap + 0x18);
173 } while(link_type & ConnectionPending);
174 if (!(link_type & LinkConnected)) {
178 link_type = pci_read_config32(dev, dev->link[link].cap + 0x18);
179 } while(!(link_type & InitComplete));
180 if (!(link_type & NonCoherent)) {
183 /* See if there is an available configuration space mapping register in function 1. */
185 for(config_reg = 0xe0; config_reg <= 0xec; config_reg += 4) {
187 config = f1_read_config32(config_reg);
188 if (!free_reg && ((config & 3) == 0)) {
189 free_reg = config_reg;
192 if (((config & 3) == 3) &&
193 (((config >> 4) & 7) == nodeid) &&
194 (((config >> 8) & 3) == link)) {
198 if (free_reg && (config_reg > 0xec)) {
199 config_reg = free_reg;
201 /* If we can't find an available configuration space mapping register skip this bus */
202 if (config_reg > 0xec) {
206 /* Set up the primary, secondary and subordinate bus numbers. We have
207 * no idea how many busses are behind this bridge yet, so we set the subordinate
208 * bus number to 0xff for the moment.
210 dev->link[link].secondary = ++max;
211 dev->link[link].subordinate = 0xff;
213 /* Read the existing primary/secondary/subordinate bus
214 * number configuration.
216 busses = pci_read_config32(dev, dev->link[link].cap + 0x14);
217 config_busses = f1_read_config32(config_reg);
219 /* Configure the bus numbers for this bridge: the configuration
220 * transactions will not be propagates by the bridge if it is not
221 * correctly configured
223 busses &= 0xff000000;
224 busses |= (((unsigned int)(dev->bus->secondary) << 0) |
225 ((unsigned int)(dev->link[link].secondary) << 8) |
226 ((unsigned int)(dev->link[link].subordinate) << 16));
227 pci_write_config32(dev, dev->link[link].cap + 0x14, busses);
229 config_busses &= 0x0000ffff;
230 config_busses |= ((dev->link[link].secondary) << 16) |
231 ((dev->link[link].subordinate) << 24);
232 f1_write_config32(config_reg, config_busses);
235 printk_debug("Hyper transport scan link: %d max: %d\n", link, max);
237 /* Now we can scan all of the subordinate busses i.e. the chain on the hypertranport link */
238 max = hypertransport_scan_chain(&dev->link[link], max);
241 printk_debug("Hyper transport scan link: %d new max: %d\n", link, max);
244 /* We know the number of busses behind this bridge. Set the subordinate
245 * bus number to it's real value
247 dev->link[link].subordinate = max;
248 busses = (busses & 0xff00ffff) |
249 ((unsigned int) (dev->link[link].subordinate) << 16);
250 pci_write_config32(dev, dev->link[link].cap + 0x14, busses);
252 config_busses = (config_busses & 0x00ffffff) | (dev->link[link].subordinate << 24);
253 f1_write_config32(config_reg, config_busses);
255 printk_debug("Hypertransport scan link done\n");
259 printk_debug("amdk8_scan_chains max: %d done\n", max);
265 static unsigned amdk8_find_iopair(unsigned nodeid, unsigned link)
267 unsigned free_reg, reg;
270 for(reg = 0xc0; reg <= 0xd8; reg += 0x8) {
271 uint32_t base, limit;
272 base = f1_read_config32(reg);
273 limit = f1_read_config32(reg + 0x4);
274 /* Do I have a free register */
275 if (!free_reg && ((base & 3) == 0)) {
278 /* Do I have a match for this node and link? */
279 if (((base & 3) == 3) &&
280 ((limit & 3) == nodeid) &&
281 (((limit >> 4) & 3) == link)) {
285 /* If I didn't find an exact match return a free register */
289 /* Return an available I/O pair or 0 on failure */
293 static unsigned amdk8_find_mempair(unsigned nodeid, unsigned link)
295 unsigned free_reg, reg;
297 for(reg = 0x80; reg <= 0xb8; reg += 0x8) {
298 uint32_t base, limit;
299 base = f1_read_config32(reg);
300 limit = f1_read_config32(reg + 0x4);
301 /* Do I have a free register */
302 if (!free_reg && ((base & 3) == 0)) {
305 /* Do I have a match for this node and link? */
306 if (((base & 3) == 3) &&
307 ((limit & 3) == nodeid) &&
308 (((limit >> 4) & 3) == link)) {
312 /* If I didn't find an exact match return a free register */
316 /* Return an available I/O pair or 0 on failure */
320 static void amdk8_link_read_bases(device_t dev, unsigned nodeid, unsigned link)
322 unsigned int reg = dev->resources;
325 /* Initialize the io space constraints on the current bus */
326 index = amdk8_find_iopair(nodeid, link);
328 dev->resource[reg].base = 0;
329 dev->resource[reg].size = 0;
330 dev->resource[reg].align = log2(HT_IO_HOST_ALIGN);
331 dev->resource[reg].gran = log2(HT_IO_HOST_ALIGN);
332 dev->resource[reg].limit = 0xffffUL;
333 dev->resource[reg].flags = IORESOURCE_IO;
334 dev->resource[reg].index = index | (link & 0x3);
335 compute_allocate_resource(&dev->link[link], &dev->resource[reg],
336 IORESOURCE_IO, IORESOURCE_IO);
340 /* Initialize the memory constraints on the current bus */
341 index = amdk8_find_mempair(nodeid, link);
343 dev->resource[reg].base = 0;
344 dev->resource[reg].size = 0;
345 dev->resource[reg].align = log2(HT_MEM_HOST_ALIGN);
346 dev->resource[reg].gran = log2(HT_MEM_HOST_ALIGN);
347 dev->resource[reg].limit = 0xffffffffUL;
348 dev->resource[reg].flags = IORESOURCE_MEM;
349 dev->resource[reg].index = index | (link & 0x3);
350 compute_allocate_resource(&dev->link[link], &dev->resource[reg],
351 IORESOURCE_MEM, IORESOURCE_MEM);
354 dev->resources = reg;
357 static void amdk8_read_resources(device_t dev)
359 unsigned nodeid, link;
360 nodeid = amdk8_nodeid(dev);
362 memset(&dev->resource, 0, sizeof(dev->resource));
363 for(link = 0; link < dev->links; link++) {
364 if (dev->link[link].children) {
365 amdk8_link_read_bases(dev, nodeid, link);
370 static void amdk8_set_resource(device_t dev, struct resource *resource, unsigned nodeid)
372 unsigned long rbase, rlimit;
374 /* Make certain the resource has actually been set */
375 if (!(resource->flags & IORESOURCE_SET)) {
379 /* Only handle PCI memory and IO resources */
380 if (!(resource->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
383 /* Get the base address */
384 rbase = resource->base;
386 /* Get the limit (rounded up) */
387 rlimit = rbase + ((resource->size + resource->align - 1UL) & ~(resource->align -1)) - 1UL;
389 /* Get the register and link */
390 reg = resource->index & ~3;
391 link = resource->index & 3;
393 if (resource->flags & IORESOURCE_IO) {
394 uint32_t base, limit;
395 compute_allocate_resource(&dev->link[link], resource,
396 IORESOURCE_IO, IORESOURCE_IO);
397 base = f1_read_config32(reg);
398 limit = f1_read_config32(reg + 0x4);
400 base |= rbase & 0x01fff000;
403 limit |= rlimit & 0x01fff000;
404 limit |= (link & 3) << 4;
405 limit |= (nodeid & 3);
406 f1_write_config32(reg + 0x4, limit);
407 f1_write_config32(reg, base);
409 else if (resource->flags & IORESOURCE_MEM) {
410 uint32_t base, limit;
411 compute_allocate_resource(&dev->link[link], resource,
412 IORESOURCE_MEM, IORESOURCE_MEM);
413 base = f1_read_config32(reg);
414 limit = f1_read_config32(reg + 0x4);
416 base |= (rbase & 0xffff0000) >> 8;
419 limit |= (rlimit & 0xffff0000) >> 8;
420 limit |= (link & 3) << 4;
421 limit |= (nodeid & 3);
422 f1_write_config32(reg + 0x4, limit);
423 f1_write_config32(reg, base);
426 "%s %02x <- [0x%08lx - 0x%08lx] node %d link %d %s\n",
431 (resource->flags & IORESOURCE_IO)? "io": "mem");
434 static void amdk8_set_resources(device_t dev)
436 unsigned nodeid, link;
439 /* Find the nodeid */
440 nodeid = amdk8_nodeid(dev);
442 /* Set each resource we have found */
443 for(i = 0; i < dev->resources; i++) {
444 amdk8_set_resource(dev, &dev->resource[i], nodeid);
447 for(link = 0; link < dev->links; link++) {
449 bus = &dev->link[link];
451 assign_resources(bus);
456 unsigned int amdk8_scan_root_bus(device_t root, unsigned int max)
458 return pci_scan_bus(&root->link[0], PCI_DEVFN(0x18, 0), 0xff, max);
461 static struct device_operations northbridge_operations = {
462 .read_resources = amdk8_read_resources,
463 .set_resources = amdk8_set_resources,
464 .enable_resources = pci_dev_enable_resources,
466 .scan_bus = amdk8_scan_chains,
471 static void enumerate(struct chip *chip)
473 chip_enumerate(chip);
474 chip->dev->ops = &northbridge_operations;
477 struct chip_control northbridge_amd_amdk8_control = {
478 .name = "AMD K8 Northbridge",
479 .enumerate = enumerate,