non coherent ht chain setup automatically
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1824 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
parent
20bd731b75
commit
2c956bbc19
|
@ -208,15 +208,6 @@ static void main(unsigned long bist)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct ht_chain ht_c[] = {
|
|
||||||
{ /* Link 2 of CPU0 */
|
|
||||||
.devreg = 0xe0, /* Preset bus num in resource map */
|
|
||||||
},
|
|
||||||
{ /* Link 1 of CPU1 */
|
|
||||||
.devreg = 0xe4, /* Preset bus num in resource map */
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
int needs_reset;
|
int needs_reset;
|
||||||
|
|
||||||
if (bist == 0) {
|
if (bist == 0) {
|
||||||
|
@ -245,8 +236,11 @@ static void main(unsigned long bist)
|
||||||
|
|
||||||
setup_quartet_resource_map();
|
setup_quartet_resource_map();
|
||||||
needs_reset = setup_coherent_ht_domain();
|
needs_reset = setup_coherent_ht_domain();
|
||||||
// needs_reset |= ht_setup_chain(PCI_DEV(0, 0x18, 0), 0x80);
|
#if 0
|
||||||
needs_reset |= ht_setup_chains(ht_c, sizeof(ht_c)/sizeof(ht_c[0]));
|
needs_reset |= ht_setup_chains(2);
|
||||||
|
#else
|
||||||
|
needs_reset |= ht_setup_chains_x();
|
||||||
|
#endif
|
||||||
if (needs_reset) {
|
if (needs_reset) {
|
||||||
print_info("ht reset -\r\n");
|
print_info("ht reset -\r\n");
|
||||||
soft_reset();
|
soft_reset();
|
||||||
|
|
|
@ -177,17 +177,6 @@ static void main(unsigned long bist)
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 1
|
|
||||||
static const struct ht_chain ht_c[] = {
|
|
||||||
{ /* Link 2 of CPU0 */
|
|
||||||
.devreg = 0xe0, /* Preset bus num in resource map */
|
|
||||||
},
|
|
||||||
{ /* Link 0 of CPU0 */
|
|
||||||
.devreg = 0xe4, /* Preset bus num in resource map */
|
|
||||||
},
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int needs_reset;
|
int needs_reset;
|
||||||
if (bist == 0) {
|
if (bist == 0) {
|
||||||
/* Skip this if there was a built in self test failure */
|
/* Skip this if there was a built in self test failure */
|
||||||
|
@ -228,9 +217,9 @@ static void main(unsigned long bist)
|
||||||
setup_s2885_resource_map();
|
setup_s2885_resource_map();
|
||||||
needs_reset = setup_coherent_ht_domain();
|
needs_reset = setup_coherent_ht_domain();
|
||||||
#if 0
|
#if 0
|
||||||
needs_reset |= ht_setup_chain(PCI_DEV(0, 0x18, 0), 0xc0);
|
needs_reset |= ht_setup_chains(2);
|
||||||
#else
|
#else
|
||||||
needs_reset |= ht_setup_chains(ht_c, sizeof(ht_c)/sizeof(ht_c[0]));
|
needs_reset |= ht_setup_chains_x();
|
||||||
#endif
|
#endif
|
||||||
if (needs_reset) {
|
if (needs_reset) {
|
||||||
print_info("ht reset -\r\n");
|
print_info("ht reset -\r\n");
|
||||||
|
|
|
@ -12,8 +12,7 @@ static unsigned ht_lookup_slave_capability(device_t dev)
|
||||||
hdr_type &= 0x7f;
|
hdr_type &= 0x7f;
|
||||||
|
|
||||||
if ((hdr_type == PCI_HEADER_TYPE_NORMAL) ||
|
if ((hdr_type == PCI_HEADER_TYPE_NORMAL) ||
|
||||||
(hdr_type == PCI_HEADER_TYPE_BRIDGE))
|
(hdr_type == PCI_HEADER_TYPE_BRIDGE)) {
|
||||||
{
|
|
||||||
pos = PCI_CAPABILITY_LIST;
|
pos = PCI_CAPABILITY_LIST;
|
||||||
}
|
}
|
||||||
if (pos > PCI_CAP_LIST_NEXT) {
|
if (pos > PCI_CAP_LIST_NEXT) {
|
||||||
|
@ -39,18 +38,26 @@ static unsigned ht_lookup_slave_capability(device_t dev)
|
||||||
static void ht_collapse_previous_enumeration(unsigned bus)
|
static void ht_collapse_previous_enumeration(unsigned bus)
|
||||||
{
|
{
|
||||||
device_t dev;
|
device_t dev;
|
||||||
|
uint32_t id;
|
||||||
|
|
||||||
|
/* Check if is already collapsed */
|
||||||
|
dev = PCI_DEV(bus, 0, 0);
|
||||||
|
id = pci_read_config32(dev, PCI_VENDOR_ID);
|
||||||
|
if ( ! ( (id == 0xffffffff) || (id == 0x00000000) ||
|
||||||
|
(id == 0x0000ffff) || (id == 0xffff0000) ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Spin through the devices and collapse any previous
|
/* Spin through the devices and collapse any previous
|
||||||
* hypertransport enumeration.
|
* hypertransport enumeration.
|
||||||
*/
|
*/
|
||||||
for(dev = PCI_DEV(bus, 0, 0); dev <= PCI_DEV(bus, 0x1f, 0x7); dev += PCI_DEV(0, 1, 0)) {
|
for(dev = PCI_DEV(bus, 1, 0); dev <= PCI_DEV(bus, 0x1f, 0x7); dev += PCI_DEV(0, 1, 0)) {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
unsigned pos, flags;
|
unsigned pos, flags;
|
||||||
|
|
||||||
id = pci_read_config32(dev, PCI_VENDOR_ID);
|
id = pci_read_config32(dev, PCI_VENDOR_ID);
|
||||||
if ((id == 0xffffffff) || (id == 0x00000000) ||
|
if ((id == 0xffffffff) || (id == 0x00000000) ||
|
||||||
(id == 0x0000ffff) || (id == 0xffff0000))
|
(id == 0x0000ffff) || (id == 0xffff0000)) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +99,7 @@ static unsigned ht_read_freq_cap(device_t dev, unsigned pos)
|
||||||
return freq_cap;
|
return freq_cap;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LINK_OFFS(WIDTH,FREQ,FREQ_CAP) \
|
#define LINK_OFFS(WIDTH,FREQ,FREQ_CAP) \
|
||||||
(((WIDTH & 0xff) << 16) | ((FREQ & 0xff) << 8) | (FREQ_CAP & 0xFF))
|
(((WIDTH & 0xff) << 16) | ((FREQ & 0xff) << 8) | (FREQ_CAP & 0xFF))
|
||||||
|
|
||||||
#define LINK_WIDTH(OFFS) ((OFFS >> 16) & 0xFF)
|
#define LINK_WIDTH(OFFS) ((OFFS >> 16) & 0xFF)
|
||||||
|
@ -196,8 +203,6 @@ static int ht_setup_chain(device_t udev, unsigned upos)
|
||||||
int reset_needed;
|
int reset_needed;
|
||||||
unsigned uoffs;
|
unsigned uoffs;
|
||||||
|
|
||||||
#warning "FIXME handle multiple chains!"
|
|
||||||
|
|
||||||
/* Make certain the HT bus is not enumerated */
|
/* Make certain the HT bus is not enumerated */
|
||||||
ht_collapse_previous_enumeration(0);
|
ht_collapse_previous_enumeration(0);
|
||||||
|
|
||||||
|
@ -214,8 +219,8 @@ static int ht_setup_chain(device_t udev, unsigned upos)
|
||||||
id = pci_read_config32(dev, PCI_VENDOR_ID);
|
id = pci_read_config32(dev, PCI_VENDOR_ID);
|
||||||
/* If the chain is enumerated quit */
|
/* If the chain is enumerated quit */
|
||||||
if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
|
if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
|
||||||
(((id >> 16) & 0xffff) == 0xffff) ||
|
(((id >> 16) & 0xffff) == 0xffff) ||
|
||||||
(((id >> 16) & 0xffff) == 0x0000)) {
|
(((id >> 16) & 0xffff) == 0x0000)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,9 +252,6 @@ static int ht_setup_chain(device_t udev, unsigned upos)
|
||||||
return reset_needed;
|
return reset_needed;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ht_chain {
|
|
||||||
unsigned devreg;
|
|
||||||
};
|
|
||||||
static int ht_setup_chainx(device_t udev, unsigned upos, unsigned bus)
|
static int ht_setup_chainx(device_t udev, unsigned upos, unsigned bus)
|
||||||
{
|
{
|
||||||
unsigned next_unitid, last_unitid;
|
unsigned next_unitid, last_unitid;
|
||||||
|
@ -274,14 +276,6 @@ static int ht_setup_chainx(device_t udev, unsigned upos, unsigned bus)
|
||||||
(((id >> 16) & 0xffff) == 0x0000)) {
|
(((id >> 16) & 0xffff) == 0x0000)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
print_debug("bus=");
|
|
||||||
print_debug_hex8(bus);
|
|
||||||
print_debug(" id =");
|
|
||||||
print_debug_hex32(id);
|
|
||||||
print_debug("\r\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
pos = ht_lookup_slave_capability(dev);
|
pos = ht_lookup_slave_capability(dev);
|
||||||
if (!pos) {
|
if (!pos) {
|
||||||
|
@ -311,7 +305,7 @@ static int ht_setup_chainx(device_t udev, unsigned upos, unsigned bus)
|
||||||
return reset_needed;
|
return reset_needed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ht_setup_chains(const struct ht_chain *ht_c, int ht_c_num)
|
static int ht_setup_chains(int ht_c_num)
|
||||||
{
|
{
|
||||||
/* Assumption the HT chain that is bus 0 has the HT I/O Hub on it.
|
/* Assumption the HT chain that is bus 0 has the HT I/O Hub on it.
|
||||||
* On most boards this just happens. If a cpu has multiple
|
* On most boards this just happens. If a cpu has multiple
|
||||||
|
@ -332,7 +326,7 @@ static int ht_setup_chains(const struct ht_chain *ht_c, int ht_c_num)
|
||||||
uint32_t dword;
|
uint32_t dword;
|
||||||
unsigned busn;
|
unsigned busn;
|
||||||
|
|
||||||
reg = pci_read_config32(PCI_DEV(0,0x18,1), ht_c[i].devreg);
|
reg = pci_read_config32(PCI_DEV(0,0x18,1), 0xe0 + i * 4);
|
||||||
|
|
||||||
//We need setup 0x94, 0xb4, and 0xd4 according to the reg
|
//We need setup 0x94, 0xb4, and 0xd4 according to the reg
|
||||||
devpos = ((reg & 0xf0)>>4)+0x18; // nodeid; it will decide 0x18 or 0x19
|
devpos = ((reg & 0xf0)>>4)+0x18; // nodeid; it will decide 0x18 or 0x19
|
||||||
|
@ -343,13 +337,9 @@ static int ht_setup_chains(const struct ht_chain *ht_c, int ht_c_num)
|
||||||
dword &= ~(0xffff<<8);
|
dword &= ~(0xffff<<8);
|
||||||
dword |= (reg & 0xffff0000)>>8;
|
dword |= (reg & 0xffff0000)>>8;
|
||||||
pci_write_config32( PCI_DEV(0, devpos,0), regpos , dword);
|
pci_write_config32( PCI_DEV(0, devpos,0), regpos , dword);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
print_debug("udev=(0,0x");
|
dump_pci_devices_on_bus(busn);
|
||||||
print_debug_hex8(devpos);
|
|
||||||
print_debug(",0) 0x");
|
|
||||||
print_debug_hex8(regpos);
|
|
||||||
print_debug("=");
|
|
||||||
print_debug_hex32(dword);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Make certain the HT bus is not enumerated */
|
/* Make certain the HT bus is not enumerated */
|
||||||
|
@ -357,10 +347,9 @@ static int ht_setup_chains(const struct ht_chain *ht_c, int ht_c_num)
|
||||||
|
|
||||||
upos = ((reg & 0xf00)>>8) * 0x20 + 0x80;
|
upos = ((reg & 0xf00)>>8) * 0x20 + 0x80;
|
||||||
udev = PCI_DEV(0, devpos, 0);
|
udev = PCI_DEV(0, devpos, 0);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
print_debug("\tupos=0x");
|
dump_pci_devices_on_bus(busn);
|
||||||
print_debug_hex32(upos);
|
|
||||||
print_debug("\r\n");
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
reset_needed |= ht_setup_chainx(udev,upos,busn );
|
reset_needed |= ht_setup_chainx(udev,upos,busn );
|
||||||
|
@ -369,3 +358,89 @@ static int ht_setup_chains(const struct ht_chain *ht_c, int ht_c_num)
|
||||||
|
|
||||||
return reset_needed;
|
return reset_needed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ht_setup_chains_x(void)
|
||||||
|
{
|
||||||
|
int nodeid;
|
||||||
|
uint32_t reg;
|
||||||
|
uint32_t tempreg;
|
||||||
|
unsigned next_busn;
|
||||||
|
int ht_c_num;
|
||||||
|
|
||||||
|
// read PCI_DEV(0,0x18,0) 0x64 bit [8:9] to find out SbLink m
|
||||||
|
reg = pci_read_config32(PCI_DEV(0, 0x18, 0), 0x64);
|
||||||
|
//update PCI_DEV(0, 0x18, 1) 0xe0 to 0x05000m03, and next_busn=5+1;
|
||||||
|
tempreg = 3 | ( 0<<4) | (((reg>>8) & 3)<<8) | (0<<16)| (5<<24);
|
||||||
|
pci_write_config32(PCI_DEV(0, 0x18, 1), 0xe0, tempreg);
|
||||||
|
next_busn=5+1; // 0 will be used ht chain with SB we need to keep SB in bus0 in auto stage
|
||||||
|
// clean others
|
||||||
|
for(ht_c_num=1;ht_c_num<4; ht_c_num++) {
|
||||||
|
pci_write_config32(PCI_DEV(0, 0x18, 1), 0xe0 + ht_c_num * 4, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(nodeid=0; nodeid<8; nodeid++) {
|
||||||
|
device_t dev;
|
||||||
|
unsigned linkn;
|
||||||
|
dev = PCI_DEV(0, 0x18+nodeid,0);
|
||||||
|
//read id, check id to see if dev exists ;
|
||||||
|
reg = pci_read_config32(dev, PCI_VENDOR_ID);
|
||||||
|
if (((reg & 0xffff) == 0x0000) || ((reg & 0xffff) == 0xffff) ||
|
||||||
|
(((reg >> 16) & 0xffff) == 0xffff) ||
|
||||||
|
(((reg >> 16) & 0xffff) == 0x0000)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for(linkn = 0; linkn<3; linkn++) {
|
||||||
|
unsigned regpos;
|
||||||
|
regpos = 0x98 + 0x20 * linkn;
|
||||||
|
reg = pci_read_config32(dev, regpos);
|
||||||
|
if ((reg & 7) != 7) continue; // it is not non conherent or not connected
|
||||||
|
tempreg = 3 | (nodeid <<4) | (linkn<<8);
|
||||||
|
//compare (temp & 0xffff), with (PCI(0, 0x18, 1) 0xe0 to 0xec & 0xfffff)
|
||||||
|
for(ht_c_num=0;ht_c_num<4; ht_c_num++) {
|
||||||
|
reg = pci_read_config32(PCI_DEV(0, 0x18, 1), 0xe0 + ht_c_num * 4);
|
||||||
|
if(((reg & 0xffff) == (tempreg & 0xffff)) || ((reg & 0xffff) == 0x0000)) { // we got it
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(ht_c_num == 4) break; //used up onle 4 non conherent allowed
|
||||||
|
//update to 0xe0...
|
||||||
|
if((reg & 0xf) == 3) continue; //SBLink so don't touch it
|
||||||
|
tempreg |= (next_busn<<16)|((next_busn+5)<<24);
|
||||||
|
pci_write_config32(PCI_DEV(0, 0x18, 1), 0xe0 + ht_c_num * 4, tempreg);
|
||||||
|
next_busn+=5+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//update 0xe0, 0xe4, 0xe8, 0xec from PCI_DEV(0, 0x18,1) to PCI_DEV(0, 0x19,1) to PCI_DEV(0, 0x1f,1);
|
||||||
|
|
||||||
|
for(nodeid = 1; nodeid<8; nodeid++) {
|
||||||
|
int i;
|
||||||
|
device_t dev;
|
||||||
|
dev = PCI_DEV(0, 0x18+nodeid,1);
|
||||||
|
//read id, check id to see if dev exists ;
|
||||||
|
reg = pci_read_config32(dev, PCI_VENDOR_ID);
|
||||||
|
if (((reg & 0xffff) == 0x0000) || ((reg & 0xffff) == 0xffff) ||
|
||||||
|
(((reg >> 16) & 0xffff) == 0xffff) ||
|
||||||
|
(((reg >> 16) & 0xffff) == 0x0000)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for(i = 0; i< 4; i++) {
|
||||||
|
unsigned regpos;
|
||||||
|
regpos = 0xe0 + i * 4;
|
||||||
|
reg = pci_read_config32(PCI_DEV(0, 0x18, 1), regpos);
|
||||||
|
pci_write_config32(dev, regpos, reg);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// recount ht_c_num
|
||||||
|
int i=0;
|
||||||
|
for(ht_c_num=0;ht_c_num<4; ht_c_num++) {
|
||||||
|
reg = pci_read_config32(PCI_DEV(0, 0x18, 1), 0xe0 + ht_c_num * 4);
|
||||||
|
if(((reg & 0xf) != 0x0)) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ht_setup_chains(i);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue