- First pass at code for generic link width and size determination
authorEric Biederman <ebiederm@xmission.com>
Mon, 21 Jul 2003 23:30:29 +0000 (23:30 +0000)
committerEric Biederman <ebiederm@xmission.com>
Mon, 21 Jul 2003 23:30:29 +0000 (23:30 +0000)
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@999 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1

src/devices/pci_device.c
src/include/device/pci_def.h
src/mainboard/arima/hdama/mptable.c
src/southbridge/amd/amd8131/amd8131_bridge.c

index 1c6498c16736050ec0ae02a380a7b6c9bce7fe32..a951aa5c5ca7a2958327b9c9cf23d0d3ffcfae33 100644 (file)
@@ -473,7 +473,8 @@ unsigned int pci_scan_bus(struct device *bus, unsigned int max)
        struct device *old_devices;
        struct device *child;
 #if HYPERTRANSPORT_SUPPORT
-       unsigned next_unitid, last_unitid;
+       unsigned next_unitid, last_unitid, previous_unitid;
+       int reset_needed;
 #endif
 
        printk_debug("PCI: pci_scan_bus for bus %d\n", bus->secondary);
@@ -486,17 +487,65 @@ unsigned int pci_scan_bus(struct device *bus, unsigned int max)
        
 
 #if HYPERTRANSPORT_SUPPORT
+       /* Spin through the devices and collapse any early
+        * hypertransport enumeration.
+        */
+       for(devfn = 0; devfn <= 0xff; devfn += 8) {
+               struct device dummy;
+               uint32_t id;
+               uint8_t hdr_type, pos;
+               dummy.bus = bus;
+               dummy.devfn = devfn;
+               id = pci_read_config32(&dummy, PCI_VENDOR_ID);
+               if (id == 0xffffffff || id == 0x00000000 || 
+                       id == 0x0000ffff || id == 0xffff0000) {
+                       continue;
+               }
+               hdr_type = pci_read_config8(&dummy, PCI_HEADER_TYPE);
+               pos = 0;
+               switch(hdr_type & 0x7f) {
+               case PCI_HEADER_TYPE_NORMAL:
+               case PCI_HEADER_TYPE_BRIDGE:
+                       pos = PCI_CAPABILITY_LIST;
+                       break;
+               }
+               if (pos > PCI_CAP_LIST_NEXT) {
+                       pos = pci_read_config8(&dummy, pos);
+               }
+               while(pos != 0) {
+                       uint8_t cap;
+                       cap = pci_read_config8(&dummy, pos + PCI_CAP_LIST_ID);
+                       printk_debug("Capability: 0x%02x @ 0x%02x\n", cap, pos);
+                       if (cap == PCI_CAP_ID_HT) {
+                               uint16_t flags;
+                               flags = pci_read_config16(&dummy, pos + PCI_CAP_FLAGS);
+                               printk_debug("flags: 0x%04x\n", (unsigned)flags);
+                               if ((flags >> 13) == 0) {
+                                       /* Clear the unitid */
+                                       flags &= ~0x1f;
+                                       pci_write_config16(&dummy, pos + PCI_CAP_FLAGS, flags);
+                                       break;
+                               }
+                       }
+                       pos = pci_read_config8(&dummy, pos + PCI_CAP_LIST_NEXT);
+               }
+       }
        /* If present assign unitid to a hypertransport chain */
+       last_unitid = 0;
        next_unitid = 1;
        do {
                struct device dummy;
                uint32_t id;
-               uint8_t hdr_type, pos;
+               uint8_t hdr_type, pos, previous_pos;
+
+               previous_unitid = last_unitid;
                last_unitid = next_unitid;
 
+               /* Read the next unassigned device off the stack */
                dummy.bus   = bus;
                dummy.devfn = 0;
                id = pci_read_config32(&dummy, PCI_VENDOR_ID);
+               /* If the chain is enumerated quit */
                if (id == 0xffffffff || id == 0x00000000 ||
                        id == 0x0000ffff || id == 0xffff0000) {
                        break;
@@ -512,28 +561,111 @@ unsigned int pci_scan_bus(struct device *bus, unsigned int max)
                if (pos > PCI_CAP_LIST_NEXT) {
                        pos = pci_read_config8(&dummy, pos);
                }
-               while(pos != 0) {
+               while(pos != 0) {   /* loop through the linked list */
                        uint8_t cap;
                        cap = pci_read_config8(&dummy, pos + PCI_CAP_LIST_ID);
                        printk_debug("Capability: 0x%02x @ 0x%02x\n", cap, pos);
                        if (cap == PCI_CAP_ID_HT) {
                                uint16_t flags;
+                               uint16_t links;
                                flags = pci_read_config16(&dummy, pos + PCI_CAP_FLAGS);
                                printk_debug("flags: 0x%04x\n", (unsigned)flags);
-                               if ((flags >> 13) == 0) {
+                               if ((flags >> 13) == 0) {  /* Entry is a Slave secondary */
+                                       struct device last, previous;
                                        unsigned count;
-                                       flags &= ~0x1f;
-                                       flags |= next_unitid & 0x1f;
-                                       count = (flags >> 5) & 0x1f;
+                                       unsigned width;
+                                       flags &= ~0x1f; /* mask out base unit ID */
+                                       flags |= next_unitid & 0x1f; /* assign ID */
+                                       count = (flags >> 5) & 0x1f; /* get unit count */
                                        printk_debug("unitid: 0x%02x, count: 0x%02x\n",
                                                next_unitid, count);
                                        pci_write_config16(&dummy, pos + PCI_CAP_FLAGS, flags);
                                        next_unitid += count;
+
+                                       if (previous_unitid == 0) { /* the link is back to the host */
+                                               /* calculate the previous pos for the host */
+                                               previous_pos = 0x80;
+                                               previous.bus = 0;
+                                               previous.devfn = 0x18 << 3;
+#warning "FIXME we should not hard code this!"
+                                       } else {
+                                               previous.bus = bus;
+                                               previous.devfn = previous_unitid << 3;
+                                       }
+                                       last.bus = bus;
+                                       last.devfn = last_unitid << 3;
+                                       /* Set link width and frequency */
+                                       flags = pci_read_config16(&last, pos + PCI_HT_CAP_SLAVE_FREQ_CAP0);
+                                       cap = pci_read_config8(&last, pos + PCI_HT_CAP_SLAVE_WIDTH0);
+                                       if(previous_unitid == 0) { /* the link is back to the host */
+                                               links = pci_read_config16(&previous, 
+                                                               previous_pos + PCI_HT_CAP_HOST_FREQ_CAP);
+                                               width = pci_read_config8(&previous, 
+                                                               previous_pos + PCI_HT_CAP_HOST_WIDTH);
+                                       }
+                                       else { /* The link is back up the chain */
+                                               links = pci_read_config16(&previous, 
+                                                               previous_pos + PCI_HT_CAP_SLAVE_FREQ_CAP1);
+                                               width = pci_read_config8(&previous, 
+                                                               previous_pos + PCI_HT_CAP_SLAVE_WIDTH1);
+                                       }
+                                       /* Calculate the highest possible frequency */
+                                       links &= flags;
+                                       for(flags = 0x40, count = 6; count; count--, flags >>= 1) {
+                                               if(flags & links) break;
+                                       }
+                                       /* Calculate the highest width */
+                                       width &= cap;
+                                       /* set the present device */
+                                       if(count != pci_read_config8(&last, pos + PCI_HT_CAP_HOST_FREQ)) {
+                                               pci_write_config8(&last, pos + PCI_HT_CAP_HOST_FREQ, count);
+                                               reset_needed = 1;
+                                       }
+                                       if(width != pci_read_config8(&last, pos + PCI_HT_CAP_SLAVE_WIDTH0 + 1)) {
+                                                pci_write_config8(&last, 
+                                                                               pos + PCI_HT_CAP_SLAVE_WIDTH0 + 1, width);
+                                                reset_needed = 1;
+                                        }
+
+                                       /* set the upstream device */
+                                        if(previous_unitid == 0) { /* the link is back to the host */
+                                                cap = pci_read_config8(&previous, previous_pos + PCI_HT_CAP_HOST_FREQ);
+                                               cap &= 0x0f;
+                                               if(count != cap) {
+                                                       pci_write_config8(&previous, 
+                                                                       previous_pos + PCI_HT_CAP_HOST_FREQ, count);
+                                                       reset_needed = 1;
+                                               }
+                                                cap = pci_read_config8(&previous, previous_pos + PCI_HT_CAP_HOST_WIDTH + 1);
+                                               if(width != cap) {
+                                                       pci_write_config8(&previous, 
+                                                                       previous_pos + PCI_HT_CAP_HOST_WIDTH + 1, width);
+                                                       reset_needed = 1;
+                                               }
+                                       }
+                                        else { /* The link is back up the chain */
+                                                cap = pci_read_config8(&previous, 
+                                                                       previous_pos + PCI_HT_CAP_SLAVE_FREQ1);
+                                                cap &= 0x0f;
+                                                if(count != cap) {
+                                                       pci_write_config8(&previous, 
+                                                               previous_pos + PCI_HT_CAP_SLAVE_FREQ1, count);
+                                                       reset_needed = 1;
+                                               }
+                                                cap = pci_read_config8(&previous, 
+                                                                       previous_pos + PCI_HT_CAP_SLAVE_WIDTH1 + 1);
+                                                if(width != cap) {
+                                                       pci_write_config8(&previous, 
+                                                               previous_pos + PCI_HT_CAP_SLAVE_WIDTH1, width);
+                                                       reset_needed = 1;
+                                               }
+                                        }
                                        break;
                                }
                        }
                        pos = pci_read_config8(&dummy, pos + PCI_CAP_LIST_NEXT);
                }
+               previous_pos = pos;
        } while((last_unitid != next_unitid) && (next_unitid <= 0x1f));
 #endif /* HYPERTRANSPORT_SUPPORT */
 
index 6a22cbe67f02dd42f0000e378c8cb1d26960ff7c..ad8f1e6b881936e34dea2c0ef0e7e51afe674cf1 100644 (file)
 #define  PCI_CAP_ID_HT          0x08
 #define PCI_CAP_LIST_NEXT      1       /* Next capability in the list */
 #define PCI_CAP_FLAGS          2       /* Capability defined flags (16 bits) */
-#define PCI_CAP_SIZEOF         4
+
+/* Hypertransport Registers */
+#define PCI_HT_CAP_SIZEOF         4
+#define PCI_HT_CAP_HOST_WIDTH     6    /* width value & capability  */
+#define PCI_HT_CAP_HOST_FREQ      0x09 /* Host frequency */
+#define PCI_HT_CAP_HOST_FREQ_CAP   0x0a        /* Host Frequency capability  */
+#define PCI_HT_CAP_SLAVE_WIDTH0           6    /* width value & capability  */
+#define PCI_HT_CAP_SLAVE_WIDTH1           0x0a /* width value & capability  to */
+#define PCI_HT_CAP_SLAVE_FREQ0    0x0d /* Slave frequency from */
+#define PCI_HT_CAP_SLAVE_FREQ1    0x011        /* Slave frequency to */
+#define PCI_HT_CAP_SLAVE_FREQ_CAP0 0x0e        /* Frequency capability from */
+#define PCI_HT_CAP_SLAVE_FREQ_CAP1 0x12        /* Frequency capability to */
 
 /* Power Management Registers */
 
index 43c122e129a96ef602b604dc18bab36b540dd8b8..856288590deed43c6e1402a6262ae86927170ebf 100644 (file)
@@ -150,43 +150,43 @@ void *smp_write_config_table(void *v, unsigned long * processor_map)
 
        /* PCI Slot 1 */
        smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
-               bus_8131_2, (1<<2)|0, 0x04, 0x1);
+               bus_8131_2, (1<<2)|0, 0x02, 0x11);
        smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
-               bus_8131_2, (1<<2)|1, 0x04, 0x2);
+               bus_8131_2, (1<<2)|1, 0x02, 0x12);
        smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
-               bus_8131_2, (1<<2)|2, 0x04, 0x3);
+               bus_8131_2, (1<<2)|2, 0x02, 0x13);
        smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
-               bus_8131_2, (1<<2)|3, 0x04, 0x0);
+               bus_8131_2, (1<<2)|3, 0x02, 0x10);
 
        /* PCI Slot 2 */
        smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
-               bus_8131_2, (2<<2)|0, 0x04, 0x2);
+               bus_8131_2, (2<<2)|0, 0x02, 0x12);
        smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
-               bus_8131_2, (2<<2)|1, 0x04, 0x3);
+               bus_8131_2, (2<<2)|1, 0x02, 0x13);
        smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
-               bus_8131_2, (2<<2)|2, 0x04, 0x0);
+               bus_8131_2, (2<<2)|2, 0x02, 0x10);
        smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
-               bus_8131_2, (2<<2)|3, 0x04, 0x1);
+               bus_8131_2, (2<<2)|3, 0x02, 0x11);
 
        /* PCI Slot 3 */
        smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
-               bus_8131_1, (1<<2)|0, 0x03, 0x1);
+               bus_8131_1, (1<<2)|0, 0x02, 0x11);
        smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
-               bus_8131_1, (1<<2)|1, 0x03, 0x2);
+               bus_8131_1, (1<<2)|1, 0x02, 0x12);
        smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
-               bus_8131_1, (1<<2)|2, 0x03, 0x3);
+               bus_8131_1, (1<<2)|2, 0x02, 0x13);
        smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
-               bus_8131_1, (1<<2)|3, 0x03, 0x0);
+               bus_8131_1, (1<<2)|3, 0x02, 0x10);
 
        /* PCI Slot 4 */
        smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
-               bus_8131_1, (2<<2)|0, 0x03, 0x2);
+               bus_8131_1, (2<<2)|0, 0x02, 0x12);
        smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
-               bus_8131_1, (2<<2)|1, 0x03, 0x3);
+               bus_8131_1, (2<<2)|1, 0x02, 0x13);
        smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
-               bus_8131_1, (2<<2)|2, 0x03, 0x0);
+               bus_8131_1, (2<<2)|2, 0x02, 0x10);
        smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
-               bus_8131_1, (2<<2)|3, 0x03, 0x1);
+               bus_8131_1, (2<<2)|3, 0x02, 0x11);
 
        /* PCI Slot 5 */
 #warning "FIXME get the irqs right, it's just hacked to work for now"
index 9ef83da50dd8a01f8e3c2d7abb06520b983787c6..ded548023421c63ef9e726e5ef5d5733d311260d 100644 (file)
@@ -9,6 +9,28 @@
 
 static void pcix_init(device_t dev)
 {
+       uint16_t word;
+       uint8_t byte;
+
+       
+       /* Enable memory write and invalidate ??? */
+       byte = pci_read_config8(dev, 0x04);
+        byte |= 0x10;
+        pci_write_config8(dev, 0x04, byte);
+       
+       /* Set drive strength */
+       word = pci_read_config16(dev, 0xe0);
+        word = 0x0404;
+        pci_write_config16(dev, 0xe0, word);
+       word = pci_read_config16(dev, 0xe4);
+        word = 0x0404;
+        pci_write_config16(dev, 0xe4, word);
+       
+       /* Set impedance */
+       word = pci_read_config16(dev, 0xe8);
+        word = 0x0404;
+        pci_write_config16(dev, 0xe8, word);
+
        return;
 }