Index: southbridge/nvidia/mcp55/stage1_usbdebug.c Index: southbridge/nvidia/mcp55/stage1_enable_rom.c Index: southbridge/nvidia/mcp55/stage1.c Index: mainboard/amd/serengeti/initram.c Index: mainboard/amd/serengeti/Makefile Index: mainboard/gigabyte/m57sli/mainboard.h Index: mainboard/gigabyte/m57sli/initram.c Index: mainboard/gigabyte/m57sli/stage1.c Index: mainboard/gigabyte/m57sli/Makefile Index: northbridge/amd/k8/coherent_ht.c Index: northbridge/amd/k8/get_nodes.c Index: northbridge/amd/k8/incoherent_ht_chain.c The mcp55 builds again. This time around there is substantial dram and other initram support. Clean up some definitions, i.e. define some things in mainboard.h and remove them from other .c files. This junk is all over the place in v2 and it is now in one per-mainboard place in v3. Clean up makefiles so they are more similar, board to board. As we learn, we may be able to make some of the makefile definitions common to all k8 boards -- that would be nice. Add real initram to the m57sli. Add sio setup functions to the SOUTHBRIDGE, this time, not EVERY MAINBOARD! break get_nodes out of coherent_ht.c. Break two functions for incoherent ht chains out of incoherent ht support. Signed-off-by: Ronald G. Minnich Index: southbridge/nvidia/mcp55/stage1_usbdebug.c =================================================================== --- southbridge/nvidia/mcp55/stage1_usbdebug.c (revision 875) +++ southbridge/nvidia/mcp55/stage1_usbdebug.c (working copy) @@ -21,13 +21,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/* This should probably be a config variable. */ -#if HT_CHAIN_END_UNITID_BASE != 0x20 - #define MCP55_DEVN_BASE HT_CHAIN_END_UNITID_BASE -#else - #define MCP55_DEVN_BASE HT_CHAIN_UNITID_BASE -#endif - +#include #define EHCI_BAR_INDEX 0x10 #define EHCI_BAR 0xFEF00000 #define EHCI_DEBUG_OFFSET 0x98 Index: southbridge/nvidia/mcp55/stage1_enable_rom.c =================================================================== --- southbridge/nvidia/mcp55/stage1_enable_rom.c (revision 0) +++ southbridge/nvidia/mcp55/stage1_enable_rom.c (revision 0) @@ -0,0 +1,47 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2004 Tyan Computer + * Written by Yinghai Lu for Tyan Computer. + * Copyright (C) 2006,2007 AMD + * Written by Yinghai Lu for AMD. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +void mcp55_enable_rom(void) +{ + u8 byte; + u16 word; + u32 addr; + + /* Enable 4MB rom access at 0xFFC00000 - 0xFFFFFFFF */ + addr = PCI_BDF(0, (MCP55_DEVN_BASE+1), 0); + + /* Set the 4MB enable bit bit */ + byte = pci_conf1_read_config8(addr, 0x88); + byte |= 0xff; //256K + pci_conf1_write_config8(addr, 0x88, byte); + byte = pci_conf1_read_config8(addr, 0x8c); + byte |= 0xff; //1M + pci_conf1_write_config8(addr, 0x8c, byte); + word = pci_conf1_read_config16(addr, 0x90); + word |= 0x7fff; //15M + pci_conf1_write_config16(addr, 0x90, word); +} Index: southbridge/nvidia/mcp55/stage1.c =================================================================== --- southbridge/nvidia/mcp55/stage1.c (revision 876) +++ southbridge/nvidia/mcp55/stage1.c (working copy) @@ -28,8 +28,10 @@ #include #include "mcp55.h" -#warning fix disgusting define of MCP55_NUM it is mainboard dependent -#define MCP55_NUM 1 +#ifndef MCP55_NUM +#error MCP55_NUM should be defined in mainboard.h (in the mainboard directory) +#endif + int set_ht_link_mcp55(u8 ht_c_num) { int set_ht_link_buffer_counts_chain(u8 ht_c_num, unsigned vendorid, unsigned val); @@ -441,10 +443,10 @@ } +void set_bios_reset(void); void hard_reset(void) { -#warning what is set_bios_reset -// set_bios_reset(); + set_bios_reset(); /* full reset */ outb(0x0a, 0x0cf9); @@ -460,12 +462,31 @@ void soft_reset(void) { -#warning what is set_bios_reset -// set_bios_reset(); -#if 1 + set_bios_reset(); /* link reset */ outb(0x02, 0x0cf9); outb(0x06, 0x0cf9); -#endif } +/* this seems to be needed. The mcp55 is a real mess. I won't miss it. */ +void sio_setup(u32 devn) +{ + + unsigned value; + u32 dword; + u8 byte; + + byte = pci_conf1_read_config8(PCI_BDF(0, devn+1 , 0), 0x7b); + byte |= 0x20; + pci_conf1_write_config8(PCI_BDF(0, devn+1 , 0), 0x7b, byte); + + dword = pci_conf1_read_config32(PCI_BDF(0, devn+1 , 0), 0xa0); + dword |= (1<<0); + pci_conf1_write_config32(PCI_BDF(0, devn+1 , 0), 0xa0, dword); + + dword = pci_conf1_read_config32(PCI_BDF(0, devn+1 , 0), 0xa4); + dword |= (1<<16); + pci_conf1_write_config32(PCI_BDF(0, devn+1 , 0), 0xa4, dword); +} + + Index: mainboard/amd/serengeti/initram.c =================================================================== --- mainboard/amd/serengeti/initram.c (revision 875) +++ mainboard/amd/serengeti/initram.c (working copy) @@ -249,9 +249,6 @@ dump_pci_device_index_wait(PCI_DEV(0, 0x19, 2), 0x98); #endif -#warning re-implement post_cache_as_ram - // post_cache_as_ram(); // bsp switch stack to ram and copy sysinfo ram now - printk(BIOS_DEBUG, "stage1 returns\n"); return 0; } Index: mainboard/amd/serengeti/Makefile =================================================================== --- mainboard/amd/serengeti/Makefile (revision 875) +++ mainboard/amd/serengeti/Makefile (working copy) @@ -24,13 +24,13 @@ $(src)/mainboard/$(MAINBOARDDIR)/stage1.c \ $(src)/mainboard/$(MAINBOARDDIR)/option_table.c \ $(src)/arch/x86/stage1_mtrr.c \ - $(src)/southbridge/amd/amd8111/stage1_smbus.c \ - $(src)/southbridge/amd/amd8111/stage1_ctrl.c \ - $(src)/southbridge/amd/amd8111/stage1_enable_rom.c \ $(src)/arch/x86/amd/model_fxx/dualcore_id.c \ $(src)/arch/x86/amd/model_fxx/stage1.c \ $(src)/northbridge/amd/k8/coherent_ht.c \ $(src)/northbridge/amd/k8/libstage1.c \ + $(src)/southbridge/amd/amd8111/stage1_smbus.c \ + $(src)/southbridge/amd/amd8111/stage1_ctrl.c \ + $(src)/southbridge/amd/amd8111/stage1_enable_rom.c \ INITRAM_SRC= $(src)/mainboard/$(MAINBOARDDIR)/initram.c \ $(src)/northbridge/amd/k8/raminit.c \ Index: mainboard/gigabyte/m57sli/mainboard.h =================================================================== --- mainboard/gigabyte/m57sli/mainboard.h (revision 877) +++ mainboard/gigabyte/m57sli/mainboard.h (working copy) @@ -46,3 +46,6 @@ /* you don't want to set this in Kconfig or dts either. It's dangerous! */ #define CONFIG_AP_CODE_IN_CAR 0 +/* MCP55 is another fun challenge */ +#define MCP55_NUM 1 +#define MCP55_DEVN_BASE HT_CHAIN_UNITID_BASE Index: mainboard/gigabyte/m57sli/initram.c =================================================================== --- mainboard/gigabyte/m57sli/initram.c (revision 876) +++ mainboard/gigabyte/m57sli/initram.c (working copy) @@ -30,15 +30,14 @@ #include #include #include +#include #include #include #include #include -# warning fix hard_reset -void hard_reset(void) -{ -} +void hard_reset(void); + void memreset_setup(void) { } @@ -58,9 +57,99 @@ */ int main(void) { - printk(BIOS_DEBUG, "Hi there from stage1\n"); - post_code(POST_START_OF_MAIN); + void enable_smbus(void); + void enable_fid_change_on_sb(u16 sbbusn, u16 sbdn); + void soft_reset_x(unsigned sbbusn, unsigned sbdn); + int cpu_init_detected(unsigned int nodeid); + void start_all_cores(void); + void set_sysinfo_in_ram(unsigned val); + int mcp55_early_setup_x(void); + void soft_reset(void); - printk(BIOS_DEBUG, "stage1 returns\n"); + struct msr msr; + static const u16 spd_addr[] = { + (0xa << 3) | 0, (0xa << 3) | 2, 0, 0, + (0xa << 3) | 1, (0xa << 3) | 3, 0, 0, +#if CONFIG_MAX_PHYSICAL_CPUS > 1 + (0xa << 3) | 4, (0xa << 3) | 6, 0, 0, + (0xa << 3) | 5, (0xa << 3) | 7, 0, 0, +#endif + }; + struct sys_info *sysinfo = &(global_vars()->sys_info); + + int needs_reset = 0; + unsigned bsp_apicid = 0; + int init_detected; + struct node_core_id me; + + me = get_node_core_id(); + printk(BIOS_DEBUG, "Hi there from stage1, cpu%d, core%d\n", me.nodeid, me.coreid); + + init_detected = cpu_init_detected(me.nodeid); + printk(BIOS_DEBUG, "init_detected: %d\n", init_detected); + /* well, here we are. For starters, we need to know if this is cpu0 core0. + * cpu0 core 0 will do all the DRAM setup. + */ + bsp_apicid = init_cpus(init_detected, sysinfo); + + printk(BIOS_DEBUG, "bsp_apicid=%02x\n", bsp_apicid); + + set_sysinfo_in_ram(0); // in BSP so could hold all ap until sysinfo is in ram + setup_coherent_ht_domain(); // routing table and start other core0 + + wait_all_core0_started(); +#if CONFIG_LOGICAL_CPUS==1 + // It is said that we should start core1 after all core0 launched + /* because optimize_link_coherent_ht is moved out from setup_coherent_ht_domain, + * So here need to make sure last core0 is started, esp for two way system, + * (there may be apic id conflicts in that case) + */ + start_all_cores(); + wait_all_other_cores_started(bsp_apicid); +#endif + + /* it will set up chains and store link pair for optimization later */ + ht_setup_chains_x(sysinfo); // it will init sblnk and sbbusn, nodes, sbdn + + msr = rdmsr(FIDVID_STATUS); + printk(BIOS_DEBUG, "begin msr fid, vid %08x:%08x\n", msr.hi, msr.lo); + + + enable_fid_change(); + + enable_fid_change_on_sb(sysinfo->sbbusn, sysinfo->sbdn); + + init_fidvid_bsp(bsp_apicid); + + msr = rdmsr(FIDVID_STATUS); + printk(BIOS_DEBUG, "end msr fid, vid %08x:%08x\n", msr.hi, msr.lo); + + + needs_reset |= optimize_link_coherent_ht(); + needs_reset |= optimize_link_incoherent_ht(sysinfo); + needs_reset |= mcp55_early_setup_x(); + + // fidvid change will issue one LDTSTOP and the HT change will be effective too + if (needs_reset) { + printk(BIOS_INFO, "ht reset -\n"); + soft_reset(); + } + allow_all_aps_stop(bsp_apicid); + + //It's the time to set ctrl in sysinfo now; + fill_mem_ctrl(sysinfo->nodes, sysinfo->ctrl, spd_addr); + + enable_smbus(); + + memreset_setup(); + + //do we need apci timer, tsc...., only debug need it for better output + /* all ap stopped? */ +// init_timer(); // Need to use TMICT to synconize FID/VID + + sdram_initialize(sysinfo->nodes, sysinfo->ctrl, sysinfo); + + printk(BIOS_DEBUG, "initram returns\n"); return 0; } + Index: mainboard/gigabyte/m57sli/stage1.c =================================================================== --- mainboard/gigabyte/m57sli/stage1.c (revision 876) +++ mainboard/gigabyte/m57sli/stage1.c (working copy) @@ -295,11 +295,12 @@ }; - void hardware_stage1(void) { void it8716f_enable_serial(u8 dev, u8 serial, u16 iobase); void enumerate_ht_chain(void); + void sio_setup(u32 devn); + void mcp55_enable_rom(void); int max; u8 tmp; @@ -325,6 +326,8 @@ setup_resource_map(register_values, max); enumerate_ht_chain(); + sio_setup(MCP55_DEVN_BASE); + mcp55_enable_rom(); printk(BIOS_ERR, "Done.\n"); post_code(POST_START_OF_MAIN); Index: mainboard/gigabyte/m57sli/Makefile =================================================================== --- mainboard/gigabyte/m57sli/Makefile (revision 876) +++ mainboard/gigabyte/m57sli/Makefile (working copy) @@ -25,16 +25,19 @@ $(src)/arch/x86/stage1_mtrr.c \ $(src)/arch/x86/amd/model_fxx/dualcore_id.c \ $(src)/arch/x86/amd/model_fxx/stage1.c \ + $(src)/northbridge/amd/k8/get_nodes.c \ + $(src)/northbridge/amd/k8/incoherent_ht_chain.c \ + $(src)/northbridge/amd/k8/libstage1.c \ $(src)/southbridge/nvidia/mcp55/stage1_smbus.c \ - $(src)/northbridge/amd/k8/coherent_ht.c \ - $(src)/northbridge/amd/k8/incoherent_ht.c \ - $(src)/northbridge/amd/k8/libstage1.c \ + $(src)/southbridge/nvidia/mcp55/stage1_enable_rom.c \ INITRAM_SRC= $(src)/mainboard/$(MAINBOARDDIR)/initram.c \ $(src)/northbridge/amd/k8/raminit.c \ $(src)/northbridge/amd/k8/dqs.c \ $(src)/northbridge/amd/k8/reset_test.c \ $(src)/southbridge/nvidia/mcp55/stage1_smbus.c \ + $(src)/northbridge/amd/k8/incoherent_ht.c \ + $(src)/northbridge/amd/k8/coherent_ht.c \ $(src)/arch/x86/amd/model_fxx/dualcore.c \ $(src)/arch/x86/amd/model_fxx/fidvid.c \ $(src)/arch/x86/amd/model_fxx/init_cpus.c \ Index: northbridge/amd/k8/coherent_ht.c =================================================================== --- northbridge/amd/k8/coherent_ht.c (revision 875) +++ northbridge/amd/k8/coherent_ht.c (working copy) @@ -1689,17 +1689,6 @@ return needs_reset; } -/** - * get_nodes - * see page 46 of the BKDG Publication # 26094 Revision: 3.30 Issue Date: February 2006 - * @returns an int containing the number of nodes. - * The format of the register is 32 bits, and the node count is in bits 4-6 - */ -unsigned int get_nodes(void) -{ - return ((pci_conf1_read_config32(PCI_BDF(0, 0x18, 0), NODEID)>>4) & 7) + 1; -} - int optimize_link_coherent_ht(void) { int needs_reset = 0; Index: northbridge/amd/k8/get_nodes.c =================================================================== --- northbridge/amd/k8/get_nodes.c (revision 875) +++ northbridge/amd/k8/get_nodes.c (working copy) @@ -22,60 +22,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA */ - -/* - * This algorithm assumes a grid configuration as follows: - * - * nodes : 1 2 4 6 8 - * org. : 1x1 2x1 2x2 2x3 2x4 - Ladder: - CPU7-------------CPU6 - | | - | | - | | - | | - | | - | | - CPU5-------------CPU4 - | | - | | - | | - | | - | | - | | - CPU3-------------CPU2 - | | - | | - | | - | | - | | - | | - CPU1-------------CPU0 - CONFIG_CROSS_BAR_47_56: - CPU7-------------CPU6 - | \____ ___/ | - | \ / | - | \/ | - | /\ | - | / \ | - | ____/ \___ | - CPU5 CPU4 - | | - | | - | | - | | - | | - | | - CPU3-------------CPU2 - | | - | | - | | - | | - | | - | | - CPU1-------------CPU0 - */ - #include #include #include @@ -90,1605 +36,6 @@ #include #include -#define enable_bsp_routing() enable_routing(0) - -#define NODE_HT(x) PCI_BDF(0,24+x,0) -#define NODE_MP(x) PCI_BDF(0,24+x,1) -#define NODE_MC(x) PCI_BDF(0,24+x,3) - -#define DEFAULT 0x00010101 /* default row entry */ - - -#ifndef CONFIG_CROSS_BAR_47_56 - #define CONFIG_CROSS_BAR_47_56 0 -#endif - -#ifndef TRY_HIGH_FIRST - #define TRY_HIGH_FIRST 0 -#endif - -#ifndef K8_HT_CHECK_PENDING_LINK - #if CONFIG_MAX_PHYSICAL_CPUS >= 4 - #define K8_HT_CHECK_PENDING_LINK 1 - #else - #define K8_HT_CHECK_PENDING_LINK 0 - #endif -#endif - -#ifndef ENABLE_APIC_EXT_ID - #define ENABLE_APIC_EXT_ID 0 -#endif - - -inline void print_linkn (const char *strval, u8 byteval) -{ - printk(BIOS_DEBUG, "%s%02x\n", strval, byteval); -} - -void disable_probes(void) -{ - /* disable read/write/fill probes for uniprocessor setup - * they don't make sense if only one cpu is available - */ - - /* Hypertransport Transaction Control Register - * F0:0x68 - * [ 0: 0] Disable read byte probe - * 0 = Probes issues - * 1 = Probes not issued - * [ 1: 1] Disable Read Doubleword probe - * 0 = Probes issued - * 1 = Probes not issued - * [ 2: 2] Disable write byte probes - * 0 = Probes issued - * 1 = Probes not issued - * [ 3: 3] Disable Write Doubleword Probes - * 0 = Probes issued - * 1 = Probes not issued. - * [10:10] Disable Fill Probe - * 0 = Probes issued for cache fills - * 1 = Probes not issued for cache fills. - */ - - u32 val; - - printk(BIOS_SPEW, "Disabling read/write/fill probes for UP... "); - - val=pci_conf1_read_config32(NODE_HT(0), HT_TRANSACTION_CONTROL); - val |= HTTC_DIS_FILL_P | HTTC_DIS_RMT_MEM_C | HTTC_DIS_P_MEM_C | - HTTC_DIS_MTS | HTTC_DIS_WR_DW_P | HTTC_DIS_WR_B_P | - HTTC_DIS_RD_DW_P | HTTC_DIS_RD_B_P; - pci_conf1_write_config32(NODE_HT(0), HT_TRANSACTION_CONTROL, val); - - printk(BIOS_SPEW, "done.\n"); - -} - -void enable_apic_ext_id(u8 node) -{ -#if ENABLE_APIC_EXT_ID==1 -#warning "FIXME Is the right place to enable apic ext id here?" - - u32 val; - - val = pci_conf1_read_config32(NODE_HT(node), 0x68); - val |= (HTTC_APIC_EXT_SPUR | HTTC_APIC_EXT_ID | HTTC_APIC_EXT_BRD_CST); - pci_conf1_write_config32(NODE_HT(node), 0x68, val); -#endif -} - -void enable_routing(u8 node) -{ - u32 val; - - /* HT Initialization Control Register - * F0:0x6C - * [ 0: 0] Routing Table Disable - * 0 = Packets are routed according to routing tables - * 1 = Packets are routed according to the default link field - * [ 1: 1] Request Disable (BSP should clear this) - * 0 = Request packets may be generated - * 1 = Request packets may not be generated. - * [ 3: 2] Default Link (Read-only) - * 00 = LDT0 - * 01 = LDT1 - * 10 = LDT2 - * 11 = CPU on same node - * [ 4: 4] Cold Reset - * - Scratch bit cleared by a cold reset - * [ 5: 5] BIOS Reset Detect - * - Scratch bit cleared by a cold reset - * [ 6: 6] INIT Detect - * - Scratch bit cleared by a warm or cold reset not by an INIT - * - */ - - /* Enable routing table */ - printk(BIOS_SPEW, "Enabling routing table for node %x", node); - - val=pci_conf1_read_config32(NODE_HT(node), 0x6c); - val &= ~((1<<1)|(1<<0)); - pci_conf1_write_config32(NODE_HT(node), 0x6c, val); - - printk(BIOS_SPEW, " done.\r\n"); -} - -void fill_row(u8 node, u8 row, u32 value) -{ - pci_conf1_write_config32(NODE_HT(node), 0x40+(row<<2), value); -} - -#if CONFIG_MAX_PHYSICAL_CPUS > 1 -u8 link_to_register(int ldt) -{ - /* - * [ 0: 3] Request Route - * [0] Route to this node - * [1] Route to Link 0 - * [2] Route to Link 1 - * [3] Route to Link 2 - */ - - if (ldt&0x08) return 0x40; - if (ldt&0x04) return 0x20; - if (ldt&0x02) return 0x00; - - /* we should never get here */ - printk(BIOS_SPEW, "Unknown Link\n"); - return 0; -} - -u32 get_row(u8 node, u8 row) -{ - return pci_conf1_read_config32(NODE_HT(node), 0x40+(row<<2)); -} - -int link_connection(u8 src, u8 dest) -{ - return get_row(src, dest) & 0x0f; -} - -void rename_temp_node(u8 node) -{ - u32 val; - - printk(BIOS_SPEW, "Renaming current temporary node to %x", node); - - val=pci_conf1_read_config32(NODE_HT(7), 0x60); - val &= (~7); /* clear low bits. */ - val |= node; /* new node */ - pci_conf1_write_config32(NODE_HT(7), 0x60, val); - - printk(BIOS_SPEW, " done.\n"); -} - -int verify_connection(u8 dest) -{ - /* See if we have a valid connection to dest */ - u32 val; - - /* Verify that the coherent hypertransport link is - * established and actually working by reading the - * remode node's vendor/device id - */ - val = pci_conf1_read_config32(NODE_HT(dest),0); - if(val != 0x11001022) - return 0; - - return 1; -} - -u16 read_freq_cap(u32 dev, u8 pos) -{ - /* Handle bugs in valid hypertransport frequency reporting */ - u16 freq_cap; - u32 id; - - freq_cap = pci_conf1_read_config16(dev, pos); - freq_cap &= ~(1 << HT_FREQ_VENDOR); /* Ignore Vendor HT frequencies */ - -#ifdef CONFIG_K8_HT_FREQ_1G_SUPPORT - { - return freq_cap; - } -#endif - - id = pci_conf1_read_config32(dev, 0); - - /* AMD K8 Unsupported 1Ghz? */ - if (id == (PCI_VENDOR_ID_AMD | (0x1100 << 16))) { - freq_cap &= ~(1 << HT_FREQ_1000Mhz); - } - - return freq_cap; -} - -/* figure out how to merge this and the one in incoherent_ht */ -int optimize_connection(u32 node1, u8 link1, u32 node2, u8 link2) -{ - static const u8 link_width_to_pow2[]= { 3, 4, 0, 5, 1, 2, 0, 0 }; - static const u8 pow2_to_link_width[] = { 0x7, 4, 5, 0, 1, 3 }; - u16 freq_cap1, freq_cap2; - u8 width_cap1, width_cap2, width, old_width, ln_width1, ln_width2; - u8 freq, old_freq; - int needs_reset; - /* Set link width and frequency */ - - /* Initially assume everything is already optimized and I don't need a reset */ - needs_reset = 0; - - /* Get the frequency capabilities */ - freq_cap1 = read_freq_cap(node1, link1 + PCI_HT_CAP_HOST_FREQ_CAP); - freq_cap2 = read_freq_cap(node2, link2 + PCI_HT_CAP_HOST_FREQ_CAP); - - /* Calculate the highest possible frequency */ - freq = log2c(freq_cap1 & freq_cap2); - - /* See if I am changing the link freqency */ - old_freq = pci_conf1_read_config8(node1, link1 + PCI_HT_CAP_HOST_FREQ); - old_freq &= 0x0f; - needs_reset |= old_freq != freq; - old_freq = pci_conf1_read_config8(node2, link2 + PCI_HT_CAP_HOST_FREQ); - old_freq &= 0x0f; - needs_reset |= old_freq != freq; - - /* Set the Calulcated link frequency */ - pci_conf1_write_config8(node1, link1 + PCI_HT_CAP_HOST_FREQ, freq); - pci_conf1_write_config8(node2, link2 + PCI_HT_CAP_HOST_FREQ, freq); - - /* Get the width capabilities */ - width_cap1 = pci_conf1_read_config8(node1, link1 + PCI_HT_CAP_HOST_WIDTH); - width_cap2 = pci_conf1_read_config8(node2, link2 + PCI_HT_CAP_HOST_WIDTH); - - /* Calculate node1's input width */ - ln_width1 = link_width_to_pow2[width_cap1 & 7]; - ln_width2 = link_width_to_pow2[(width_cap2 >> 4) & 7]; - if (ln_width1 > ln_width2) { - ln_width1 = ln_width2; - } - width = pow2_to_link_width[ln_width1]; - /* Calculate node1's output width */ - ln_width1 = link_width_to_pow2[(width_cap1 >> 4) & 7]; - ln_width2 = link_width_to_pow2[width_cap2 & 7]; - if (ln_width1 > ln_width2) { - ln_width1 = ln_width2; - } - width |= pow2_to_link_width[ln_width1] << 4; - - /* See if I am changing node1's width */ - old_width = pci_conf1_read_config8(node1, link1 + PCI_HT_CAP_HOST_WIDTH + 1); - old_width &= 0x77; - needs_reset |= old_width != width; - - /* Set node1's widths */ - pci_conf1_write_config8(node1, link1 + PCI_HT_CAP_HOST_WIDTH + 1, width); - - // * Calculate node2's width */ - width = ((width & 0x70) >> 4) | ((width & 0x7) << 4); - - /* See if I am changing node2's width */ - old_width = pci_conf1_read_config8(node2, link2 + PCI_HT_CAP_HOST_WIDTH + 1); - old_width &= 0x77; - needs_reset |= old_width != width; - - /* Set node2's widths */ - pci_conf1_write_config8(node2, link2 + PCI_HT_CAP_HOST_WIDTH + 1, width); - - return needs_reset; -} - -u8 get_linkn_first(u8 byte) -{ - if(byte & 0x02) { byte = 0; } - else if(byte & 0x04) { byte = 1; } - else if(byte & 0x08) { byte = 2; } - return byte; -} - -u8 get_linkn_last(u8 byte) -{ - if(byte & 0x02) { byte &= 0x0f; byte |= 0x00; } - if(byte & 0x04) { byte &= 0x0f; byte |= 0x10; } - if(byte & 0x08) { byte &= 0x0f; byte |= 0x20; } - return byte>>4; -} - -u8 get_linkn_last_count(u8 byte) -{ - byte &= 0x0f; - if(byte & 0x02) { byte &= 0xcf; byte |= 0x00; byte+=0x40; } - if(byte & 0x04) { byte &= 0xcf; byte |= 0x10; byte+=0x40; } - if(byte & 0x08) { byte &= 0xcf; byte |= 0x20; byte+=0x40; } - return byte>>4; -} - -void setup_row_local(u8 source, u8 row) /* source will be 7 when it is for temp use*/ -{ - u8 linkn; - u32 val; - val = 1; - for(linkn = 0; linkn<3; linkn++) { - u8 regpos; - u32 reg; - regpos = 0x98 + 0x20 * linkn; - reg = pci_conf1_read_config32(NODE_HT(source), regpos); - if ((reg & 0x17) != 3) continue; /* it is not conherent or not connected*/ - val |= 1<<(linkn+1); - } - val <<= 16; - val |= 0x0101; - fill_row(source,row, val); -} - -void setup_row_direct_x(u8 temp, u8 source, u8 dest, u8 linkn) -{ - u32 val; - u32 val_s; - val = 1<<(linkn+1); - val |= 1<<(linkn+1+8); /*for direct connect response route should equal to request table*/ - - if(((source &1)!=(dest &1)) -#if CONFIG_CROSS_BAR_47_56 - && ( (source<4)||(source>5) ) //(6,7) (7,6) should still be here - //(6,5) (7,4) should be here -#endif - ){ - val |= (1<<16); - } else { - /*for CONFIG_CROSS_BAR_47_56 47, 56, should be here too - and for 47, 56, 57, 75, 46, 64 we need to substract another link to - 6, 7, 6, 6, 7, 7 - */ - val_s = get_row(temp, source); - val |= ((val_s>>16) - (1<<(linkn+1)))<<16; - } - - fill_row(temp,dest, val ); -} - -#if CONFIG_CROSS_BAR_47_56 -void opt_broadcast_rt(u8 source, u8 dest, u8 kickout) { - u32 val; - val = get_row(source, dest); - val -= link_connection(source, kickout)<<16; - fill_row(source, dest, val); -} - -void opt_broadcast_rt_group(const u8 *conn, int num) { - int i; - - for(i=0; i 1*/ - - -#if CONFIG_MAX_PHYSICAL_CPUS > 2 -#if !CONFIG_CROSS_BAR_47_56 -void setup_row_indirect_x(u8 temp, u8 source, u8 dest) -#else -void setup_row_indirect_x(u8 temp, u8 source, u8 dest, u8 gateway, u8 diff) -#endif -{ - /*for indirect connection, we need to compute the val from val_s(source, source), and val_g(source, gateway) */ - u32 val_s; - u32 val; -#if !CONFIG_CROSS_BAR_47_56 - u8 gateway; - u8 diff; - if(source>= 16; - val_s &= 0xfe; - -#if !CONFIG_CROSS_BAR_47_56 - diff = ((source&1)!=(dest &1)); -#endif - - if(diff && (val_s!=(val&0xff)) ) { /* use another connect as response*/ - val_s -= val & 0xff; -#if (CONFIG_MAX_PHYSICAL_CPUS > 4) || (CONFIG_MAX_PHYSICAL_CPUS_4_BUT_MORE_INSTALLED == 1) - u8 byte; - /* Some node have two links left - * don't worry we only have (2, (3 as source need to handle - */ - byte = val_s; - byte = get_linkn_last_count(byte); - if((byte>>2)>1) { /* make sure not the corner*/ - if(source>16) - link_connection(temp, gateway))<<16; - } - - fill_row(temp, dest, val); - -} - -#if !CONFIG_CROSS_BAR_47_56 -void setup_row_indirect(u8 source, u8 dest) -{ - setup_row_indirect_x(source, source, dest); -} -#else -void setup_row_indirect(u8 source, u8 dest, u8 gateway, u8 diff) -{ - setup_row_indirect_x(source, source, dest, gateway, diff); -} -#endif - -void setup_row_indirect_group(const u8 *conn, int num) -{ - int i; - -#if !CONFIG_CROSS_BAR_47_56 - for(i=0; i 2*/ - - -void setup_uniprocessor(void) -{ - printk(BIOS_SPEW, "Enabling UP settings\r\n"); -#if CONFIG_LOGICAL_CPUS==1 - unsigned tmp = (pci_conf1_read_config32(NODE_MC(0), 0xe8) >> 12) & 3; - if (tmp>0) return; -#endif - disable_probes(); -} - -#if CONFIG_MAX_PHYSICAL_CPUS > 2 -int optimize_connection_group(const u8 *opt_conn, int num) { - int needs_reset = 0; - int i; - for(i=0; i 1 -unsigned setup_smp2(void) -{ - unsigned nodes; - u8 byte; - u32 val; - nodes = 2; - - setup_row_local(0, 0); /* it will update the broadcast RT*/ - - val = get_row(0,0); - byte = (val>>16) & 0xfe; - if(byte<0x2) { /* no coherent connection so get out.*/ - nodes = 1; - return nodes; - } - - /* Setup and check a temporary connection to node 1 */ -#if TRY_HIGH_FIRST == 1 - byte = get_linkn_last(byte); /* Max Link to node1 */ -#else - byte = get_linkn_first(byte); /*Min Link to node1 --- according to AMD*/ -#endif - print_linkn("(0,1) link=", byte); - setup_row_direct(0,1, byte); - setup_temp_row(0, 1); - - verify_connection(7); - - /* We found 2 nodes so far */ - val = pci_conf1_read_config32(NODE_HT(7), 0x6c); - byte = (val>>2) & 0x3; /*get default link on node7 to node0*/ - print_linkn("(1,0) link=", byte); - setup_row_local(7,1); - setup_remote_row_direct(1, 0, byte); - -#if (CONFIG_MAX_PHYSICAL_CPUS > 4) || (CONFIG_MAX_PHYSICAL_CPUS_4_BUT_MORE_INSTALLED == 1) - val = get_row(7,1); - byte = (val>>16) & 0xfe; - byte = get_linkn_last_count(byte); - if((byte>>2)==3) { /* Oh! we need to treat it as node2. So use another link*/ - val = get_row(0,0); - byte = (val>>16) & 0xfe; -#if TRY_HIGH_FIRST == 1 - byte = get_linkn_first(byte); /* Min link to Node1 */ -#else - byte = get_linkn_last(byte); /* Max link to Node1*/ -#endif - print_linkn("\t-->(0,1) link=", byte); - setup_row_direct(0,1, byte); - setup_temp_row(0, 1); - - verify_connection(7); - - /* We found 2 nodes so far */ - val = pci_conf1_read_config32(NODE_HT(7), 0x6c); - byte = (val>>2) & 0x3; /* get default link on node7 to node0*/ - print_linkn("\t-->(1,0) link=", byte); - setup_row_local(7,1); - setup_remote_row_direct(1, 0, byte); - } -#endif - - setup_remote_node(1); /* Setup the regs on the remote node */ - rename_temp_node(1); /* Rename Node 7 to Node 1 */ - enable_routing(1); /* Enable routing on Node 1 */ -#if 0 - /*don't need and it is done by clear_dead_links */ - clear_temp_row(0); -#endif - - return nodes; -} -#endif /*CONFIG_MAX_PHYSICAL_CPUS > 1 */ - -#if CONFIG_MAX_PHYSICAL_CPUS > 2 - -unsigned setup_smp4(void) -{ - unsigned nodes; - u8 byte; - u32 val; - - nodes=4; - - /* Setup and check temporary connection from Node 0 to Node 2 */ - val = get_row(0,0); - byte = ((val>>16) & 0xfe) - link_connection(0,1); - byte = get_linkn_last_count(byte); - - if((byte>>2)==0) { /* We should have two coherent for 4p and above*/ - nodes = 2; - return nodes; - } - - byte &= 3; /* bit [3,2] is count-1*/ - print_linkn("(0,2) link=", byte); - setup_row_direct(0, 2, byte); /*(0,2) direct link done*/ - - /* We found 3 nodes so far. Now setup a temporary - * connection from node 0 to node 3 via node 1 - */ - setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */ - /* here should setup_row_direct(1,3) at first, before that we should find the link in node 1 to 3*/ - val = get_row(1,1); - byte = ((val>>16) & 0xfe) - link_connection(1,0); - byte = get_linkn_first(byte); - print_linkn("(1,3) link=", byte); - setup_row_direct(1,3,byte); /* (1, 3) direct link done*/ - - /* We found 4 nodes so far. Now setup all nodes for 4p */ - // We need to make sure 0,2 and 1,3 link is set already -#if !CONFIG_CROSS_BAR_47_56 - static const u8 conn4_1[] = { - 0,3, - 1,2, - }; -#else - static const u8 conn4_1[] = { - 0,3,2,1, - 1,2,3,1, - }; -#endif - - setup_row_indirect_group(conn4_1, ARRAY_SIZE(conn4_1)); - - setup_temp_row(0,2); - verify_connection(7); - val = pci_conf1_read_config32(NODE_HT(7), 0x6c); - byte = (val>>2) & 0x3; /* get default link on 7 to 0*/ - print_linkn("(2,0) link=", byte); - - setup_row_local(7,2); - setup_remote_row_direct(2, 0, byte); /* node 2 to node 0 direct link done */ - setup_remote_node(2); /* Setup the regs on the remote node */ - - rename_temp_node(2); /* Rename Node 7 to Node 2 */ - enable_routing(2); /* Enable routing on Node 2 */ - - setup_temp_row(0,1); - setup_temp_row(1,3); - verify_connection(7); - - val = pci_conf1_read_config32(NODE_HT(7), 0x6c); - byte = (val>>2) & 0x3; /* get default link on 7 to 1*/ - print_linkn("(3,1) link=", byte); - - setup_row_local(7,3); - setup_remote_row_direct(3, 1, byte); /* node 3 to node 1 direct link done */ - setup_remote_node(3); /* Setup the regs on the remote node */ - - /* We need to init link between 2, and 3 direct link */ - val = get_row(2,2); - byte = ((val>>16) & 0xfe) - link_connection(2,0); - byte = get_linkn_last_count(byte); - print_linkn("(2,3) link=", byte & 3); - - setup_row_direct(2,3, byte & 0x3); - setup_temp_row(0,2); - setup_temp_row(2,3); - verify_connection(7); /* to 3*/ - -#if (CONFIG_MAX_PHYSICAL_CPUS > 4) || (CONFIG_MAX_PHYSICAL_CPUS_4_BUT_MORE_INSTALLED == 1) - /* We need to find out which link is to node3 */ - if((byte>>2)==2) { /* one to node3, one to node0, one to node4*/ - val = get_row(7,3); - if((val>>16) == 1) { /* that link is to node4, because via node1 it has been set, recompute it*/ - val = get_row(2,2); - byte = ((val>>16) & 0xfe) - link_connection(2,0); - byte = get_linkn_first(byte); - print_linkn("\t-->(2,3) link=", byte); - setup_row_direct(2,3,byte); - setup_temp_row(2,3); - verify_connection(7); /* to 3*/ - } - } -#endif - - val = pci_conf1_read_config32(NODE_HT(7), 0x6c); - byte = (val>>2) & 0x3; /* get default link on 7 to 2*/ - print_linkn("(3,2) link=", byte); - setup_remote_row_direct(3,2, byte); - -#if (CONFIG_MAX_PHYSICAL_CPUS > 4) || (CONFIG_MAX_PHYSICAL_CPUS_4_BUT_MORE_INSTALLED == 1) - /* set link from 3 to 5 before enable it*/ - val = get_row(7,3); - byte = ((val>>16) & 0xfe) - link_connection(7,2) - link_connection(7,1); - byte = get_linkn_last_count(byte); - if((byte>>2)==1) { /* We should have three coherent links on node 3 for 6p and above*/ - byte &= 3; /*bit [3,2] is count-2*/ - print_linkn("(3,5) link=", byte); - setup_remote_row_direct(3, 5, byte); - } - - val = get_row(2,2); - byte = ((val>>16) & 0xfe) - link_connection(2,3) - link_connection(2,0); - byte = get_linkn_last_count(byte); - - if((byte>>2)==1) { /* We should have three coherent link on node 2 for 6p and above*/ - byte &= 3; /* bit [3,2] is count-2*/ - print_linkn("(2,4) link=", byte); - setup_row_direct(2, 4, byte); - } -#endif - - //Beside 3, 1 is set, We need to make sure 3, 5 is set already in case has three link in 3 -#if !CONFIG_CROSS_BAR_47_56 - static const u8 conn4_3[] = { - 3,0, - }; -#else - static const u8 conn4_3[] = { - 3,0,1,1, - }; -#endif - setup_remote_row_indirect_group(conn4_3, ARRAY_SIZE(conn4_3)); - -/* ready to enable RT for Node 3 */ - rename_temp_node(3); - enable_routing(3); /* enable routing on node 3 (temp.) */ - - // beside 2, 0 is set, We need to make sure 2, 4 link is set already in case has three link in 2 -#if !CONFIG_CROSS_BAR_47_56 - static const u8 conn4_2[] = { - 2,1, - }; -#else - static const u8 conn4_2[] = { - 2,1,0,1, - }; -#endif - setup_row_indirect_group(conn4_2, ARRAY_SIZE(conn4_2)); - -#if 0 - /*We need to do sth to reverse work for setup_temp_row (0,1) (1,3) */ - /* it will be done by clear_dead_links */ - clear_temp_row(0); - clear_temp_row(1); -#endif - - return nodes; - -} - -#endif /* CONFIG_MAX_PHYSICAL_CPUS > 2 */ - -#if CONFIG_MAX_PHYSICAL_CPUS > 4 - -unsigned setup_smp6(void) -{ - unsigned nodes; - u8 byte; - u32 val; - - nodes=6; - - /* Setup and check temporary connection from Node 0 to Node 4 through 2*/ - val = get_row(2,2); - byte = ((val>>16) & 0xfe) - link_connection(2,3) - link_connection(2,0); - byte = get_linkn_last_count(byte); - - if((byte>>2)==0) { /* We should have three coherent link on node 2 for 6p and above*/ - nodes = 4; - return nodes; - } - - /* Setup and check temporary connection from Node 0 to Node 5 through 1, 3*/ - /* set link from 3 to 5 before enable it*/ - val = get_row(3,3); - byte = ((val>>16) & 0xfe) - link_connection(3,2) - link_connection(3,1); - byte = get_linkn_last_count(byte); - if((byte>>2)==0) { /* We should have three coherent links on node 3 for 6p and above*/ - nodes = 4; - return nodes; - } - - /* We found 6 nodes so far. Now setup all nodes for 6p */ -#warning "FIXME we need to find out the correct gateway for 6p" - static const u8 conn6_1[] = { -#if !CONFIG_CROSS_BAR_47_56 - 0, 4, - 0, 5, - 1, 4, - 1, 5, - 2, 5, - 3, 4, -#else - 0, 4, 2, 0, - 0, 5, 2, 1, - 1, 4, 3, 1, - 1, 5, 3, 0, - 2, 5, 3, 0, - 3, 4, 2, 0, -#endif - }; - - setup_row_indirect_group(conn6_1, ARRAY_SIZE(conn6_1)); - - for(byte=0; byte<4; byte+=2) { - setup_temp_row(byte,byte+2); - } - verify_connection(7); - val = pci_conf1_read_config32(NODE_HT(7), 0x6c); - byte = (val>>2) & 0x3; /*get default link on 7 to 2*/ - print_linkn("(4,2) link=", byte); - - setup_row_local(7,4); - setup_remote_row_direct(4, 2, byte); - setup_remote_node(4); /* Setup the regs on the remote node */ - - /* Set indirect connection to 0, to 3 */ - //we only need to set 4,0 here - static const u8 conn6_2[] = { -#if !CONFIG_CROSS_BAR_47_56 - 4, 0, -#else - 4, 0, 2, 0, -#endif - }; - - setup_remote_row_indirect_group(conn6_2, ARRAY_SIZE(conn6_2)); - - rename_temp_node(4); - enable_routing(4); - - setup_temp_row(0,1); - for(byte=0; byte<4; byte+=2) { - setup_temp_row(byte+1,byte+3); - } - verify_connection(7); - - val = pci_conf1_read_config32(NODE_HT(7), 0x6c); - byte = (val>>2) & 0x3; /* get default link on 7 to 3*/ - print_linkn("(5,3) link=", byte); - setup_row_local(7,5); - setup_remote_row_direct(5, 3, byte); - setup_remote_node(5); /* Setup the regs on the remote node */ - -#if !CONFIG_CROSS_BAR_47_56 - /* We need to init link between 4, and 5 direct link */ - val = get_row(4,4); - byte = ((val>>16) & 0xfe) - link_connection(4,2); - byte = get_linkn_last_count(byte); - print_linkn("(4,5) link=", byte & 3); - - setup_row_direct(4,5, byte & 0x3); - setup_temp_row(0,2); - setup_temp_row(2,4); - setup_temp_row(4,5); - verify_connection(7); /* to 5*/ - -#if CONFIG_MAX_PHYSICAL_CPUS > 6 - /* We need to find out which link is to node5 */ - - if((byte>>2)==2) { /* one to node5, one to node2, one to node6*/ - val = get_row(7,5); - if((val>>16) == 1) { /* that link is to node6, because via node 3 node 5 has been set*/ - val = get_row(4,4); - byte = ((val>>16) & 0xfe) - link_connection(4,2); - byte = get_linkn_first(byte); - print_linkn("\t-->(4,5) link=", byte); - setup_row_direct(4,5,byte); - setup_temp_row(4,5); - verify_connection(7); /* to 5*/ - } - } -#endif - - val = pci_conf1_read_config32(NODE_HT(7), 0x6c); - byte = (val>>2) & 0x3; /* get default link on 7 to 4*/ - print_linkn("(5,4) link=", byte); - setup_remote_row_direct(5,4, byte); - - //init 5, 7 here - val = get_row(7,5); - byte = ((val>>16) & 0xfe) - link_connection(7,4) - link_connection(7,3); - byte = get_linkn_last_count(byte); - if((byte>>2)==1) { /* We should have three coherent links on node 5 for 6p and above*/ - byte &= 3; /*bit [3,2] is count-2*/ - print_linkn("(5,7) link=", byte); - setup_remote_row_direct(5, 7, byte); - } - - //init 4,6 here - val = get_row(4,4); - byte = ((val>>16) & 0xfe) - link_connection(4,5) - link_connection(4,2); - byte = get_linkn_last_count(byte); - - if((byte>>2)==1) { /* We should have three coherent link on node 4 for 6p and above*/ - byte &= 3; /* bit [3,2] is count-2*/ - print_linkn("(4,6) link=", byte); - setup_row_direct(4, 6, byte); - } - -#endif - - //We need to set 5,0 here only, We need to set up 5, 7 to make 5,0 - /* Set indirect connection to 0, to 3 for indirect we will use clockwise routing */ - static const u8 conn6_3[] = { -#if !CONFIG_CROSS_BAR_47_56 - 5, 0, -#else - 5, 0, 3, 0, -#endif - }; - - setup_remote_row_indirect_group(conn6_3, ARRAY_SIZE(conn6_3)); - -/* ready to enable RT for 5 */ - rename_temp_node(5); - enable_routing(5); /* enable routing on node 5 (temp.) */ - - static const u8 conn6_4[] = { -#if !CONFIG_CROSS_BAR_47_56 - 4, 1, - 4, 3, - - 5, 2, - 5, 1, - -#else - 4, 1, 2, 0, - 4, 3, 2, 0, - 4, 5, 2, 0, - - 5, 2, 3, 0, - 5, 1, 3, 0, - 5, 4, 3, 0, - -#endif - }; - - setup_row_indirect_group(conn6_4, ARRAY_SIZE(conn6_4)); - -#if 0 - /* We need to do sth about reverse about setup_temp_row (0,1), (2,4), (1, 3), (3,5) - * It will be done by clear_dead_links - */ - for(byte=0; byte<4; byte++) { - clear_temp_row(byte); - } -#endif - - return nodes; - -} - -#endif /* CONFIG_MAX_PHYSICAL_CPUS > 4 */ - -#if CONFIG_MAX_PHYSICAL_CPUS > 6 - -unsigned setup_smp8(void) -{ - unsigned nodes; - u8 byte; - u32 val; - - nodes=8; - - /* Setup and check temporary connection from Node 0 to Node 6 via 2 and 4 to 7 */ - val = get_row(4,4); -#if CONFIG_CROSS_BAR_47_56 - byte = ((val>>16) & 0xfe) - link_connection(4,2); -#else - byte = ((val>>16) & 0xfe) - link_connection(4,5) - link_connection(4,2); - byte = get_linkn_last_count(byte); /* Max link to 6*/ - if((byte>>2)==0) { /* We should have two or three coherent links on node 4 for 8p*/ - nodes = 6; - return nodes; - } -#endif - -#if CONFIG_CROSS_BAR_47_56 - byte = get_linkn_last_count(byte); /* Max link to 6*/ - if((byte>>2)<2) { /* We should have two or three coherent links on node 4 for 8p*/ - nodes = 6; - return nodes; - } -#if TRY_HIGH_FIRST == 1 - byte = ((val>>16) & 0xfe) - link_connection(4,2); - byte = get_linkn_first(byte); /*Min link to 6*/ -#else - byte &= 3; /* bit [3,2] is count-1 or 2*/ -#endif - print_linkn("(4,6) link=", byte); - setup_row_direct(4, 6, byte); -#endif - -#if !CONFIG_CROSS_BAR_47_56 - /* Setup and check temporary connection from Node 0 to Node 7 through 1, 3, 5*/ - val = get_row(5,5); - byte = ((val>>16) & 0xfe) - link_connection(5,4) - link_connection(5,3); - byte = get_linkn_last_count(byte); - if((byte>>2)==0) { /* We should have three coherent links on node 5 for 6p and above*/ - nodes = 6; - return nodes; - } -#endif - - /* We found 8 nodes so far. Now setup all nodes for 8p */ - static const u8 conn8_1[] = { -#if !CONFIG_CROSS_BAR_47_56 - 0, 6, - /*0, 7,*/ - 1, 6, - /*1, 7,*/ - 2, 6, - /*2, 7,*/ - 3, 6, - /*3, 7,*/ - /*4, 7,*/ - 5, 6, -#else - 0, 6, 2, 0, - /*0, 7, 2, 0,*/ - 1, 6, 3, 0, - /*1, 7, 3, 0,*/ - 2, 6, 4, 0, - /*2, 7, 4, 0,*/ - 3, 6, 5, 1, - /*3, 7, 5, 0,*/ -#endif - }; - - setup_row_indirect_group(conn8_1,ARRAY_SIZE(conn8_1)); - - for(byte=0; byte<6; byte+=2) { - setup_temp_row(byte,byte+2); - } - verify_connection(7); - val = pci_conf1_read_config32(NODE_HT(7), 0x6c); - byte = (val>>2) & 0x3; /* get default link on 7 to 4*/ - print_linkn("(6,4) link=", byte); - - setup_row_local(7,6); - setup_remote_row_direct(6, 4, byte); - setup_remote_node(6); /* Setup the regs on the remote node */ - /* Set indirect connection to 0, to 3 */ -#warning "FIXME we need to find out the correct gateway for 8p" - static const u8 conn8_2[] = { -#if !CONFIG_CROSS_BAR_47_56 - 6, 0, -#else - 6, 0, 4, 0, -#endif - }; - - setup_remote_row_indirect_group(conn8_2, ARRAY_SIZE(conn8_2)); - -#if CONFIG_CROSS_BAR_47_56 - //init 5, 6 here - /* here init 5, 6 */ - /* Setup and check temporary connection from Node 0 to Node 5 through 1, 3, 5*/ - val = get_row(5,5); - byte = ((val>>16) & 0xfe) - link_connection(5,3); -#if TRY_HIGH_FIRST == 1 - byte = get_linkn_first(byte); -#else - byte = get_linkn_last(byte); -#endif - print_linkn("(5,6) link=", byte); - setup_row_direct(5, 6, byte); - - setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */ - for(byte=0; byte<4; byte+=2) { - setup_temp_row(byte+1,byte+3); - } - setup_temp_row(5,6); - - verify_connection(7); - - val = get_row(7,6); // to chect it if it is node6 before renaming - if( (val>>16) == 1) { // it is real node 7 so swap it - /* We need to recompute link to 6 */ - val = get_row(5,5); - byte = ((val>>16) & 0xfe) - link_connection(5,3); -#if TRY_HIGH_FIRST == 1 - byte = get_linkn_first(byte); -#else - byte = get_linkn_last(byte); -#endif - print_linkn("\t-->(5,6) link=", byte); - setup_row_direct(5, 6, byte); -#if 0 - setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */ - for(byte=0; byte<4; byte+=2) { - setup_temp_row(byte+1,byte+3); - } -#endif - setup_temp_row(5,6); - - verify_connection(7); - } - val = pci_conf1_read_config32(NODE_HT(7), 0x6c); - byte = (val>>2) & 0x3; /* get default link on 7 to 5*/ - print_linkn("(6,5) link=", byte); - setup_remote_row_direct(6, 5, byte); - /*Till now 56, 65 done */ -#endif - - rename_temp_node(6); - enable_routing(6); - -#if !CONFIG_CROSS_BAR_47_56 - setup_temp_row(0,1); - for(byte=0; byte<6; byte+=2) { - setup_temp_row(byte+1,byte+3); - } - - verify_connection(7); - - val = pci_conf1_read_config32(NODE_HT(7), 0x6c); - byte = (val>>2) & 0x3; /* get default link on 7 to 5*/ - print_linkn("(7,5) link=", byte); - setup_row_local(7,7); - setup_remote_row_direct(7, 5, byte); - -#else - val = get_row(4,4); - byte = ((val>>16) & 0xfe) - link_connection(4,2) - link_connection(4,6); - byte = get_linkn_first(byte); - print_linkn("(4,7) link=", byte); - setup_row_direct(4, 7, byte); - - /* Setup and check temporary connection from Node 0 to Node 7 through 2, and 4*/ - for(byte=0; byte<4; byte+=2) { - setup_temp_row(byte,byte+2); - } - - verify_connection(7); - - val = pci_conf1_read_config32(NODE_HT(7), 0x6c); - byte = (val>>2) & 0x3; /* get default link on 7 to 4*/ - print_linkn("(7,4) link=", byte); - setup_row_local(7,7); - setup_remote_row_direct(7, 4, byte); - /* till now 4-7, 7-4 done. */ -#endif - setup_remote_node(7); /* Setup the regs on the remote node */ - -#if CONFIG_CROSS_BAR_47_56 - /* here init 5, 7 */ - /* Setup and check temporary connection from Node 0 to Node 5 through 1, 3, 5*/ - val = get_row(5,5); - byte = ((val>>16) & 0xfe) - link_connection(5,3) - link_connection(5,6); - byte = get_linkn_first(byte); - print_linkn("(5,7) link=", byte); - setup_row_direct(5, 7, byte); - - setup_temp_row(0,1); /* temp. link between nodes 0 and 1 */ - for(byte=0; byte<4; byte+=2) { - setup_temp_row(byte+1,byte+3); - } - - verify_connection(7); - - val = pci_conf1_read_config32(NODE_HT(7), 0x6c); - byte = (val>>2) & 0x3; /* get default link on 7 to 5*/ - print_linkn("(7,5) link=", byte); - setup_remote_row_direct(7, 5, byte); - /*Till now 57, 75 done */ - -#endif - - /* We need to init link between 6, and 7 direct link */ - val = get_row(6,6); -#if !CONFIG_CROSS_BAR_47_56 - byte = ((val>>16) & 0xfe) - link_connection(6,4); -#else - byte = ((val>>16) & 0xfe) - link_connection(6,4) - link_connection(6,5); -#endif - byte = get_linkn_first(byte); - print_linkn("(6,7) link=", byte); - setup_row_direct(6,7, byte); - - val = get_row(7,7); -#if !CONFIG_CROSS_BAR_47_56 - byte = ((val>>16) & 0xfe) - link_connection(7,5); -#else - byte = ((val>>16) & 0xfe) - link_connection(7,5) - link_connection(7,4); -#endif - byte = get_linkn_first(byte); - print_linkn("(7,6) link=", byte); - setup_row_direct(7,6, byte); - - /* Set indirect connection to 0, to 3 for indirect we will use clockwise routing */ - static const u8 conn8_3[] = { -#if !CONFIG_CROSS_BAR_47_56 - 0, 7, /* restore it*/ - 1, 7, - 2, 7, - 3, 7, - 4, 7, - - 6, 1, - 6, 2, - 6, 3, - 6, 5, - - 7, 0, - 7, 1, - 7, 2, - 7, 3, - 7, 4, -#else - - - 4, 5, 6, 1, - 5, 4, 7, 1, - - 6, 1, 5, 0, // or 4, 1 - 6, 2, 4, 0, - 6, 3, 5, 0, // or 4, 1 - - 7, 0, 4, 0, // or 5, 1 - 7, 1, 5, 0, - 7, 2, 4, 0, // or 5, 1 - 7, 3, 5, 0, - - 0, 7, 2, 0, /* restore it*/ - 1, 7, 3, 0, - 2, 7, 4, 1, - 3, 7, 5, 0, - - 2, 5, 4, 1, /* reset it */ - 3, 4, 5, 1, - - 4, 1, 2, 1, /* reset it */ - 4, 3, 2, 1, - - 5, 2, 3, 1, /* reset it */ - 5, 0, 3, 1, - -#endif - }; - - setup_row_indirect_group(conn8_3, ARRAY_SIZE(conn8_3)); - -#if CONFIG_CROSS_BAR_47_56 - /* for 47, 56, 57, 75, 46, 64 we need to substract another link to - 6, 7, 6, 6, 7, 7 */ - static const u8 conn8_4[] = { -//direct - 4, 7, 6, - 5, 6, 7, - 5, 7, 6, - 7, 5, 6, - 4, 6, 7, - 6, 4, 7, - -//in direct - 0, 6, 1, - 0, 7, 1, - - 1, 6, 0, - 1, 7, 0, - - 2, 6, 3, -// 2, 7, 3, + - -// 3, 6, 1, + - 3, 7, 2, - - 6, 0, 7, - 6, 1, 7, // needed for via 5 - 6, 1, 4, // ??? - 6, 2, 7, - 6, 3, 7, // needed for via 5 - 6, 3, 4, //??? - 7, 0, 6, // needed for via 4 - 7, 0, 5, //??? - 7, 1, 6, - 7, 2, 6, // needed for via 4 - 7, 2, 5, //??? - 7, 3, 6, - }; - - opt_broadcast_rt_group(conn8_4, ARRAY_SIZE(conn8_4)); - - static const u8 conn8_5[] = { - 2, 7, 0, - - 3, 6, 1, - }; - - opt_broadcast_rt_plus_group(conn8_5, ARRAY_SIZE(conn8_5)); -#endif - - - -/* ready to enable RT for Node 7 */ - enable_routing(7); /* enable routing on node 7 (temp.) */ - - return nodes; -} - -#endif /* CONFIG_MAX_PHYSICAL_CPUS > 6 */ - - -#if CONFIG_MAX_PHYSICAL_CPUS > 1 - -unsigned setup_smp(void) -{ - unsigned nodes; - - printk(BIOS_SPEW, "Enabling SMP settings\r\n"); - - nodes = setup_smp2(); -#if CONFIG_MAX_PHYSICAL_CPUS > 2 - if(nodes == 2) - nodes = setup_smp4(); -#endif - -#if CONFIG_MAX_PHYSICAL_CPUS > 4 - if(nodes == 4) - nodes = setup_smp6(); -#endif - -#if CONFIG_MAX_PHYSICAL_CPUS > 6 - if(nodes == 6) - nodes = setup_smp8(); -#endif - -#if CONFIG_USE_PRINTK_IN_CAR - printk_debug("%02x nodes initialized.\r\n", nodes); -#else - print_debug_hex8(nodes); - print_debug(" nodes initialized.\r\n"); -#endif - - return nodes; -} - -unsigned verify_mp_capabilities(unsigned nodes) -{ - unsigned node, mask; - - mask = 0x06; /* BigMPCap */ - - for (node=0; node 2 - case 0x02: /* MPCap */ - if(nodes > 2) { - print_err("Going back to DP\r\n"); - return 2; - } - break; -#endif - case 0x00: /* Non SMP */ - if(nodes >1 ) { - print_err("Going back to UP\r\n"); - return 1; - } - break; - } - - return nodes; - -} - - -void clear_dead_routes(unsigned nodes) -{ - int last_row; - int node, row; -#if CONFIG_MAX_PHYSICAL_CPUS == 8 - if(nodes==8) return;/* don't touch (7,7)*/ -#endif - last_row = nodes; - if (nodes == 1) { - last_row = 0; - } - for(node = 7; node >= 0; node--) { - for(row = 7; row >= last_row; row--) { - fill_row(node, row, DEFAULT); - } - } - - /* Update the local row */ - for( node=0; node> 8) & 0xff)) << 16) | 0x0101); - } -} -#endif /* CONFIG_MAX_PHYSICAL_CPUS > 1 */ - -#if CONFIG_LOGICAL_CPUS==1 -unsigned verify_dualcore(unsigned nodes) -{ - unsigned node, totalcpus, tmp; - - totalcpus = 0; - for (node=0; node> 12) & 3 ; - totalcpus += (tmp + 1); - } - - return totalcpus; - -} -#endif - -void coherent_ht_finalize(unsigned nodes) -{ - unsigned node; - int dual_core = 0; -#if CONFIG_LOGICAL_CPUS==1 - unsigned total_cpus; - - get_option(&dual_core, "dual_core"); - if(dual_core) { - total_cpus = verify_dualcore(nodes); - } - else { - total_cpus = nodes; - } -#endif - - /* set up cpu count and node count and enable Limit - * Config Space Range for all available CPUs. - * Also clear non coherent hypertransport bus range - * registers on Hammer A0 revision. - */ - - printk(BIOS_SPEW, "coherent_ht_finalize\r\n"); - for (node = 0; node < nodes; node++) { - u32 dev; - u32 val; - dev = NODE_HT(node); - - /* Set the Total CPU and Node count in the system */ - val = pci_conf1_read_config32(dev, 0x60); - val &= (~0x000F0070); -#if CONFIG_LOGICAL_CPUS==1 - val |= ((total_cpus-1)<<16)|((nodes-1)<<4); -#else - val |= ((nodes-1)<<16)|((nodes-1)<<4); -#endif - pci_conf1_write_config32(dev, 0x60, val); - - /* Only respond to real cpu pci configuration cycles - * and optimize the HT settings - */ - val=pci_conf1_read_config32(dev, HT_TRANSACTION_CONTROL); - val &= ~((HTTC_BUF_REL_PRI_MASK << HTTC_BUF_REL_PRI_SHIFT) | - (HTTC_MED_PRI_BYP_CNT_MASK << HTTC_MED_PRI_BYP_CNT_SHIFT) | - (HTTC_HI_PRI_BYP_CNT_MASK << HTTC_HI_PRI_BYP_CNT_SHIFT)); - val |= HTTC_LIMIT_CLDT_CFG | - (HTTC_BUF_REL_PRI_8 << HTTC_BUF_REL_PRI_SHIFT) | - (3 << HTTC_MED_PRI_BYP_CNT_SHIFT) | - (3 << HTTC_HI_PRI_BYP_CNT_SHIFT); - pci_conf1_write_config32(dev, HT_TRANSACTION_CONTROL, val); - - } - - printk(BIOS_SPEW, "done\r\n"); -} - -int apply_cpu_errata_fixes(unsigned int nodes) -{ - unsigned node; - int needs_reset = 0; - for(node = 0; node < nodes; node++) { - u32 dev; - dev = NODE_MC(node); - } - return needs_reset; -} - -int optimize_link_read_pointers(unsigned nodes) -{ - unsigned node; - int needs_reset = 0; - for(node = 0; node < nodes; node++) { - u32 f0_dev, f3_dev; - u32 cmd_ref, cmd; - int link; - f0_dev = NODE_HT(node); - f3_dev = NODE_MC(node); - cmd_ref = cmd = pci_conf1_read_config32(f3_dev, 0xdc); - for(link = 0; link < 3; link++) { - u32 link_type; - unsigned reg; - /* This works on an Athlon64 because unimplemented links return 0 */ - reg = 0x98 + (link * 0x20); - link_type = pci_conf1_read_config32(f0_dev, reg); - /* Only handle coherent links */ - if ((link_type & (LinkConnected | InitComplete|NonCoherent)) == - (LinkConnected|InitComplete)) - { - cmd &= ~(0xff << (link *8)); - cmd |= 0x25 << (link *8); - } - } - if (cmd != cmd_ref) { - pci_conf1_write_config32(f3_dev, 0xdc, cmd); - needs_reset = 1; - } - } - return needs_reset; -} - /** * get_nodes * see page 46 of the BKDG Publication # 26094 Revision: 3.30 Issue Date: February 2006 @@ -1700,86 +47,3 @@ return ((pci_conf1_read_config32(PCI_BDF(0, 0x18, 0), NODEID)>>4) & 7) + 1; } -int optimize_link_coherent_ht(void) -{ - int needs_reset = 0; - - unsigned nodes; - - nodes = get_nodes(); - -#if CONFIG_MAX_PHYSICAL_CPUS > 1 - if(nodes>1) { - needs_reset |= optimize_connection( - NODE_HT(0), 0x80 + link_to_register(link_connection(0,1)), - NODE_HT(1), 0x80 + link_to_register(link_connection(1,0)) ); - } - -#if CONFIG_MAX_PHYSICAL_CPUS > 2 - if(nodes>2) { - /* optimize physical connections - by LYH */ - static const u8 opt_conn4[] = { - 0,2, - 1,3, - 2,3, - }; - needs_reset |= optimize_connection_group(opt_conn4, ARRAY_SIZE(opt_conn4)); - } -#endif - -#if CONFIG_MAX_PHYSICAL_CPUS > 4 - if(nodes>4) { - static const u8 opt_conn6[] ={ - 2, 4, - 3, 5, - #if !CONFIG_CROSS_BAR_47_56 - 4, 5, - #endif - }; - needs_reset |= optimize_connection_group(opt_conn6, ARRAY_SIZE(opt_conn6)); - } -#endif - -#if CONFIG_MAX_PHYSICAL_CPUS > 6 - if(nodes>6) { - static const u8 opt_conn8[] ={ - 4, 6, - #if CONFIG_CROSS_BAR_47_56 - 4, 7, - 5, 6, - #endif - 5, 7, - 6, 7, - }; - needs_reset |= optimize_connection_group(opt_conn8, ARRAY_SIZE(opt_conn8)); - } -#endif - -#endif - - needs_reset |= apply_cpu_errata_fixes(nodes); - needs_reset |= optimize_link_read_pointers(nodes); - - return needs_reset; -} - -void setup_coherent_ht_domain(void) -{ - unsigned nodes; - nodes = 1; - - enable_bsp_routing(); - -#if CONFIG_MAX_PHYSICAL_CPUS > 1 - nodes = setup_smp(); - nodes = verify_mp_capabilities(nodes); - clear_dead_routes(nodes); -#endif - - if (nodes == 1) { - setup_uniprocessor(); - } - coherent_ht_finalize(nodes); - -} - Index: northbridge/amd/k8/incoherent_ht_chain.c =================================================================== --- northbridge/amd/k8/incoherent_ht_chain.c (revision 875) +++ northbridge/amd/k8/incoherent_ht_chain.c (working copy) @@ -37,608 +37,7 @@ #include #include #include -static void print_linkn_in (const char *strval, u8 byteval) -{ - printk(BIOS_DEBUG, "%s%02x\n", strval, byteval); -} -u8 ht_lookup_capability(u32 bdf, u16 val) -{ - u8 pos; - u8 hdr_type; - - hdr_type = pci_conf1_read_config8(bdf, PCI_HEADER_TYPE); - pos = 0; - hdr_type &= 0x7f; - - if ((hdr_type == PCI_HEADER_TYPE_NORMAL) || - (hdr_type == PCI_HEADER_TYPE_BRIDGE)) { - pos = PCI_CAPABILITY_LIST; - } - if (pos > PCI_CAP_LIST_NEXT) { - pos = pci_conf1_read_config8(bdf, pos); - } - while(pos != 0) { /* loop through the linked list */ - u8 cap; - cap = pci_conf1_read_config8(bdf, pos + PCI_CAP_LIST_ID); - if (cap == PCI_CAP_ID_HT) { - u16 flags; - - flags = pci_conf1_read_config16(bdf, pos + PCI_CAP_FLAGS); - if ((flags >> 13) == val) { - /* Entry is a slave or host , success... */ - break; - } - } - pos = pci_conf1_read_config8(bdf, pos + PCI_CAP_LIST_NEXT); - } - return pos; -} - -static u8 ht_lookup_slave_capability(u32 bdf) -{ - return ht_lookup_capability(bdf, 0); // Slave/Primary Interface Block Format -} - -static u8 ht_lookup_host_capability(u32 bdf) -{ - return ht_lookup_capability(bdf, 1); // Host/Secondary Interface Block Format -} - -static void ht_collapse_previous_enumeration(u8 bus, unsigned offset_unitid) -{ - u32 bdf; - u32 id; - - //actually, only for one HT device HT chain, and unitid is 0 -#if HT_CHAIN_UNITID_BASE == 0 - if(offset_unitid) { - return; - } -#endif - - /* Check if is already collapsed */ - if((!offset_unitid) || (offset_unitid && (!((HT_CHAIN_END_UNITID_BASE == 0) && (HT_CHAIN_END_UNITID_BASE > 24) & 0xFF) -#define LINK_WIDTH(OFFS) ((OFFS >> 16) & 0xFF) -#define LINK_FREQ(OFFS) ((OFFS >> 8) & 0xFF) -#define LINK_FREQ_CAP(OFFS) ((OFFS) & 0xFF) - -#define PCI_HT_HOST_OFFS LINK_OFFS( \ - PCI_HT_CAP_HOST_CTRL, \ - PCI_HT_CAP_HOST_WIDTH, \ - PCI_HT_CAP_HOST_FREQ, \ - PCI_HT_CAP_HOST_FREQ_CAP) - -#define PCI_HT_SLAVE0_OFFS LINK_OFFS( \ - PCI_HT_CAP_SLAVE_CTRL0, \ - PCI_HT_CAP_SLAVE_WIDTH0, \ - PCI_HT_CAP_SLAVE_FREQ0, \ - PCI_HT_CAP_SLAVE_FREQ_CAP0) - -#define PCI_HT_SLAVE1_OFFS LINK_OFFS( \ - PCI_HT_CAP_SLAVE_CTRL1, \ - PCI_HT_CAP_SLAVE_WIDTH1, \ - PCI_HT_CAP_SLAVE_FREQ1, \ - PCI_HT_CAP_SLAVE_FREQ_CAP1) - -static int ht_optimize_link( - u32 bdf1, u8 pos1, unsigned offs1, - u32 bdf2, u8 pos2, unsigned offs2) -{ - static const u8 link_width_to_pow2[]= { 3, 4, 0, 5, 1, 2, 0, 0 }; - static const u8 pow2_to_link_width[] = { 0x7, 4, 5, 0, 1, 3 }; - u16 freq_cap1, freq_cap2; - u8 width_cap1, width_cap2, width, old_width, ln_width1, ln_width2; - u8 freq, old_freq; - int needs_reset; - /* Set link width and frequency */ - - /* Initially assume everything is already optimized and I don't need a reset */ - needs_reset = 0; - - /* Get the frequency capabilities */ - freq_cap1 = ht_read_freq_cap(bdf1, pos1 + LINK_FREQ_CAP(offs1)); - freq_cap2 = ht_read_freq_cap(bdf2, pos2 + LINK_FREQ_CAP(offs2)); - - /* Calculate the highest possible frequency */ - freq = log2c(freq_cap1 & freq_cap2); - - /* See if I am changing the link freqency */ - old_freq = pci_conf1_read_config8(bdf1, pos1 + LINK_FREQ(offs1)); - old_freq &= 0x0f; - needs_reset |= old_freq != freq; - old_freq = pci_conf1_read_config8(bdf2, pos2 + LINK_FREQ(offs2)); - old_freq &= 0x0f; - needs_reset |= old_freq != freq; - - /* Set the Calulcated link frequency */ - pci_conf1_write_config8(bdf1, pos1 + LINK_FREQ(offs1), freq); - pci_conf1_write_config8(bdf2, pos2 + LINK_FREQ(offs2), freq); - - /* Get the width capabilities */ - width_cap1 = ht_read_width_cap(bdf1, pos1 + LINK_WIDTH(offs1)); - width_cap2 = ht_read_width_cap(bdf2, pos2 + LINK_WIDTH(offs2)); - - /* Calculate dev1's input width */ - ln_width1 = link_width_to_pow2[width_cap1 & 7]; - ln_width2 = link_width_to_pow2[(width_cap2 >> 4) & 7]; - if (ln_width1 > ln_width2) { - ln_width1 = ln_width2; - } - width = pow2_to_link_width[ln_width1]; - /* Calculate dev1's output width */ - ln_width1 = link_width_to_pow2[(width_cap1 >> 4) & 7]; - ln_width2 = link_width_to_pow2[width_cap2 & 7]; - if (ln_width1 > ln_width2) { - ln_width1 = ln_width2; - } - width |= pow2_to_link_width[ln_width1] << 4; - - /* See if I am changing dev1's width */ - old_width = pci_conf1_read_config8(bdf1, pos1 + LINK_WIDTH(offs1) + 1); - old_width &= 0x77; - needs_reset |= old_width != width; - - /* Set dev1's widths */ - pci_conf1_write_config8(bdf1, pos1 + LINK_WIDTH(offs1) + 1, width); - - /* Calculate dev2's width */ - width = ((width & 0x70) >> 4) | ((width & 0x7) << 4); - - /* See if I am changing dev2's width */ - old_width = pci_conf1_read_config8(bdf2, pos2 + LINK_WIDTH(offs2) + 1); - old_width &= 0x77; - needs_reset |= old_width != width; - - /* Set dev2's widths */ - pci_conf1_write_config8(bdf2, pos2 + LINK_WIDTH(offs2) + 1, width); - - return needs_reset; -} - -void ht_setup_chainx(u32 bdf, u8 upos, u8 bus, - unsigned offset_unitid, struct sys_info *sysinfo); - -int scan_pci_bus( unsigned bus , struct sys_info *sysinfo) -{ - /* - here we already can access PCI_DEV(bus, 0, 0) to PCI_DEV(bus, 0x1f, 0x7) - So We can scan these devices to find out if they are bridge - If it is pci bridge, We need to set busn in bridge, and go on - For ht bridge, We need to set the busn in bridge and ht_setup_chainx, and the scan_pci_bus - */ - unsigned int devfn; - unsigned new_bus; - unsigned max_bus; - - new_bus = (bus & 0xff); // mask out the reset_needed - - if(new_bus<0x40) { - max_bus = 0x3f; - } else if (new_bus<0x80) { - max_bus = 0x7f; - } else if (new_bus<0xc0) { - max_bus = 0xbf; - } else { - max_bus = 0xff; - } - - new_bus = bus; - - for (devfn = 0; devfn <= 0xff; devfn++) { - u8 hdr_type; - u16 class; - u32 buses; - u32 bdf; - u16 cr; - bdf = PCI_BDF((bus & 0xff), ((devfn>>3) & 0x1f), (devfn & 0x7)); - hdr_type = pci_conf1_read_config8(bdf, PCI_HEADER_TYPE); - class = pci_conf1_read_config16(bdf, PCI_CLASS_DEVICE); - - switch(hdr_type & 0x7f) { /* header type */ - case PCI_HEADER_TYPE_BRIDGE: - if (class != PCI_CLASS_BRIDGE_PCI) goto bad; - /* set the bus range dev */ - - /* Clear all status bits and turn off memory, I/O and master enables. */ - cr = pci_conf1_read_config16(bdf, PCI_COMMAND); - pci_conf1_write_config16(bdf, PCI_COMMAND, 0x0000); - pci_conf1_write_config16(bdf, PCI_STATUS, 0xffff); - - buses = pci_conf1_read_config32(bdf, PCI_PRIMARY_BUS); - - buses &= 0xff000000; - new_bus++; - buses |= (((unsigned int) (bus & 0xff) << 0) | - ((unsigned int) (new_bus & 0xff) << 8) | - ((unsigned int) max_bus << 16)); - pci_conf1_write_config32(bdf, PCI_PRIMARY_BUS, buses); - - /* here we need to figure out if dev is a ht bridge - if it is ht bridge, we need to call ht_setup_chainx at first - Not verified --- yhlu - */ - u8 upos; - upos = ht_lookup_host_capability(bdf); // one func one ht sub - if (upos) { // sub ht chain - u8 busn; - busn = (new_bus & 0xff); - /* Make certain the HT bus is not enumerated */ - ht_collapse_previous_enumeration(busn, 0); - /* scan the ht chain */ - ht_setup_chainx(bdf,upos,busn, 0, sysinfo); // don't need offset unitid - } - - new_bus = scan_pci_bus(new_bus, sysinfo); - /* set real max bus num in that */ - - buses = (buses & 0xff00ffff) | - ((unsigned int) (new_bus & 0xff) << 16); - pci_conf1_write_config32(bdf, PCI_PRIMARY_BUS, buses); - - pci_conf1_write_config16(bdf, PCI_COMMAND, cr); - - break; - default: - bad: - ; - } - - /* if this is not a multi function device, - * or the device is not present don't waste - * time probing another function. - * Skip to next device. - */ - if ( ((devfn & 0x07) == 0x00) && ((hdr_type & 0x80) != 0x80)) - { - devfn += 0x07; - } - } - - return new_bus; -} - -void ht_setup_chainx(u32 bdf, u8 upos, u8 bus, - unsigned offset_unitid, struct sys_info *sysinfo) -{ - //even HT_CHAIN_UNITID_BASE == 0, we still can go through this function, because of end_of_chain check, also We need it to optimize link - - u8 next_unitid, last_unitid; - unsigned uoffs; - -#if HT_CHAIN_END_UNITID_BASE != 0x20 - /* let's record the device of last ht device, - * So we can set the Unitid to HT_CHAIN_END_UNITID_BASE - */ - unsigned real_last_unitid = 0; - u8 real_last_pos = 0; - int ht_dev_num = 0; - u8 end_used = 0; -#endif - - uoffs = PCI_HT_HOST_OFFS; - next_unitid = (offset_unitid) ? HT_CHAIN_UNITID_BASE:1; - - do { - u32 id; - u8 pos; - u16 flags, ctrl; - u8 count; - unsigned offs; - - /* Wait until the link initialization is complete */ - do { - ctrl = pci_conf1_read_config16(bdf, upos + LINK_CTRL(uoffs)); - /* Is this the end of the hypertransport chain? */ - if (ctrl & (1 << 6)) { - goto end_of_chain; - } - - if (ctrl & ((1 << 4) | (1 << 8))) { - /* - * Either the link has failed, or we have - * a CRC error. - * Sometimes this can happen due to link - * retrain, so lets knock it down and see - * if its transient - */ - ctrl |= ((1 << 4) | (1 <<8)); // Link fail + Crc - pci_conf1_write_config16(bdf, upos + LINK_CTRL(uoffs), ctrl); - ctrl = pci_conf1_read_config16(bdf, upos + LINK_CTRL(uoffs)); - if (ctrl & ((1 << 4) | (1 << 8))) { - printk(BIOS_ERR, "Detected error on Hypertransport Link\n"); - break; - } - } - } while((ctrl & (1 << 5)) == 0); - - u32 abdf = PCI_BDF(bus, 0, 0); - last_unitid = next_unitid; - - id = pci_conf1_read_config32(abdf, PCI_VENDOR_ID); - - /* If the chain is enumerated quit */ - if ( (id == 0xffffffff) || (id == 0x00000000) || - (id == 0x0000ffff) || (id == 0xffff0000)) - { - break; - } - - pos = ht_lookup_slave_capability(abdf); - if (!pos) { - printk(BIOS_ERR, "udev=%08x upos = %08x uoffs = %08x", - bdf, upos, uoffs); - printk(BIOS_ERR, ": HT link capability not found\n"); - - } - - -#if HT_CHAIN_END_UNITID_BASE != 0x20 - if(offset_unitid) { - if(next_unitid>= (bus ? 0x20:0x18) ) { - if(!end_used) { - next_unitid = HT_CHAIN_END_UNITID_BASE; - end_used = 1; - } else { - goto out; - } - - } - real_last_pos = pos; - real_last_unitid = next_unitid; - ht_dev_num++; - } -#endif - /* Update the Unitid of the current device */ - flags = pci_conf1_read_config16(abdf, pos + PCI_CAP_FLAGS); - flags &= ~0x1f; /* mask out the base Unit ID */ - flags |= next_unitid & 0x1f; - pci_conf1_write_config16(abdf, pos + PCI_CAP_FLAGS, flags); - - /* Compute the number of unitids consumed */ - count = (flags >> 5) & 0x1f; - - /* Note the change in device number */ - abdf = PCI_BDF(bus, next_unitid, 0); - - next_unitid += count; - - /* Find which side of the ht link we are on, - * by reading which direction our last write to PCI_CAP_FLAGS - * came from. - */ - flags = pci_conf1_read_config16(abdf, pos + PCI_CAP_FLAGS); - offs = ((flags>>10) & 1) ? PCI_HT_SLAVE1_OFFS : PCI_HT_SLAVE0_OFFS; - - /* store the link pair here and we will Setup the Hypertransport link later, after we get final FID/VID */ - { - struct link_pair_st *link_pair = &sysinfo->link_pair[sysinfo->link_pair_num]; - link_pair->udev = bdf; - link_pair->upos = upos; - link_pair->uoffs = uoffs; - link_pair->dev = abdf; - link_pair->pos = pos; - link_pair->offs = offs; - sysinfo->link_pair_num++; - } - - /* Remeber the location of the last device */ - bdf = abdf; - upos = pos; - uoffs = ( offs != PCI_HT_SLAVE0_OFFS ) ? PCI_HT_SLAVE0_OFFS : PCI_HT_SLAVE1_OFFS; - - } while (last_unitid != next_unitid ); - -#if HT_CHAIN_END_UNITID_BASE != 0x20 -out: -#endif -end_of_chain: ; - -#if HT_CHAIN_END_UNITID_BASE != 0x20 - if(offset_unitid && (ht_dev_num>1) && (real_last_unitid != HT_CHAIN_END_UNITID_BASE) && !end_used ) { - u16 flags; - int i; - flags = pci_conf1_read_config16(PCI_BDF(bus,real_last_unitid,0), real_last_pos + PCI_CAP_FLAGS); - flags &= ~0x1f; - flags |= HT_CHAIN_END_UNITID_BASE & 0x1f; - pci_conf1_write_config16(PCI_BDF(bus, real_last_unitid, 0), real_last_pos + PCI_CAP_FLAGS, flags); - - // Here need to change the dev in the array - for(i=0;ilink_pair_num;i++) - { - struct link_pair_st *link_pair = &sysinfo->link_pair[i]; - if(link_pair->udev == PCI_BDF(bus, real_last_unitid, 0)) { - link_pair->udev = PCI_BDF(bus, HT_CHAIN_END_UNITID_BASE, 0); - continue; - } - if(link_pair->dev == PCI_BDF(bus, real_last_unitid, 0)) { - link_pair->dev = PCI_BDF(bus, HT_CHAIN_END_UNITID_BASE, 0); - } - } - - } -#endif - -} - -void ht_setup_chain(u32 bdf, unsigned upos, struct sys_info *sysinfo) -{ - unsigned offset_unitid = 0; -#if ((HT_CHAIN_UNITID_BASE != 1) || (HT_CHAIN_END_UNITID_BASE != 0x20)) - offset_unitid = 1; -#endif - - /* 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 - * non Coherent links the appropriate bus registers for the - * links needs to be programed to point at bus 0. - */ - - /* Make certain the HT bus is not enumerated */ - ht_collapse_previous_enumeration(0, 0); - -#if ((HT_CHAIN_UNITID_BASE != 1) || (HT_CHAIN_END_UNITID_BASE != 0x20)) - offset_unitid = 1; -#endif - - ht_setup_chainx(bdf, upos, 0, offset_unitid, sysinfo); -} - -int optimize_link_read_pointer(u8 node, u8 linkn, u8 linkt, u8 val) -{ - u32 dword, dword_old; - u8 link_type; - - /* This works on an Athlon64 because unimplemented links return 0 */ - dword = pci_conf1_read_config32(PCI_BDF(0,0x18+node,0), 0x98 + (linkn * 0x20)); - link_type = dword & 0xff; - - - if ( (link_type & 7) == linkt ) { /* Coherent Link only linkt = 3, ncoherent = 7*/ - dword_old = dword = pci_conf1_read_config32(PCI_BDF(0,0x18+node,3), 0xdc); - dword &= ~( 0xff<<(linkn *8) ); - dword |= val << (linkn *8); - - if (dword != dword_old) { - pci_conf1_write_config32(PCI_BDF(0,0x18+node,3), 0xdc, dword); - return 1; - } - } - - return 0; -} - -static int optimize_link_read_pointers_chain(u8 ht_c_num) -{ - int reset_needed; - u8 i; - - reset_needed = 0; - - for (i = 0; i < ht_c_num; i++) { - u32 reg; - u8 nodeid, linkn; - u8 busn; - u8 val; - unsigned devn = 1; - - #if ((HT_CHAIN_UNITID_BASE != 1) || (HT_CHAIN_END_UNITID_BASE != 0x20)) - #if SB_HT_CHAIN_UNITID_OFFSET_ONLY == 1 - if(i==0) // to check if it is sb ht chain - #endif - devn = HT_CHAIN_UNITID_BASE; - #endif - - reg = pci_conf1_read_config32(PCI_BDF(0,0x18,1), 0xe0 + i * 4); - - nodeid = ((reg & 0xf0)>>4); // nodeid - linkn = ((reg & 0xf00)>>8); // link n - busn = (reg & 0xff0000)>>16; //busn - - reg = pci_conf1_read_config32( PCI_BDF(busn, devn, 0), PCI_VENDOR_ID); // ? the chain dev maybe offseted - if ( (reg & 0xffff) == PCI_VENDOR_ID_AMD) { - val = 0x25; - } else if ( (reg & 0xffff) == PCI_VENDOR_ID_NVIDIA ) { - val = 0x25;//??? - } else { - continue; - } - - reset_needed |= optimize_link_read_pointer(nodeid, linkn, 0x07, val); - - } - - return reset_needed; -} - int set_ht_link_buffer_count(u8 node, u8 linkn, u8 linkt, unsigned val) { u32 dword; @@ -697,214 +96,3 @@ return reset_needed; } - -static void ht_setup_chains(u8 ht_c_num, struct sys_info *sysinfo) -{ - /* 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 - * non Coherent links the appropriate bus registers for the - * links needs to be programed to point at bus 0. - */ - u8 upos; - u32 ubdf; - u8 i; - - sysinfo->link_pair_num = 0; - - // first one is SB Chain - for (i = 0; i < ht_c_num; i++) { - u32 reg; - u8 devpos; - unsigned regpos; - u32 dword; - u8 busn; - unsigned offset_unitid = 0; - - reg = pci_conf1_read_config32(PCI_BDF(0,0x18,1), 0xe0 + i * 4); - - //We need setup 0x94, 0xb4, and 0xd4 according to the reg - devpos = ((reg & 0xf0)>>4)+0x18; // nodeid; it will decide 0x18 or 0x19 - regpos = ((reg & 0xf00)>>8) * 0x20 + 0x94; // link n; it will decide 0x94 or 0xb4, 0x0xd4; - busn = (reg & 0xff0000)>>16; - - dword = pci_conf1_read_config32( PCI_BDF(0, devpos, 0), regpos) ; - dword &= ~(0xffff<<8); - dword |= (reg & 0xffff0000)>>8; - pci_conf1_write_config32( PCI_BDF(0, devpos,0), regpos , dword); - - - #if ((HT_CHAIN_UNITID_BASE != 1) || (HT_CHAIN_END_UNITID_BASE != 0x20)) - #if SB_HT_CHAIN_UNITID_OFFSET_ONLY == 1 - if(i==0) // to check if it is sb ht chain - #endif - offset_unitid = 1; - #endif - - /* Make certain the HT bus is not enumerated */ - ht_collapse_previous_enumeration(busn, offset_unitid); - - upos = ((reg & 0xf00)>>8) * 0x20 + 0x80; - ubdf = PCI_BDF(0, devpos, 0); - - ht_setup_chainx(ubdf,upos,busn, offset_unitid, sysinfo); // all not - - #if (CONFIG_K8_SCAN_PCI_BUS == 1) - bus = busn; // we need 32 bit - scan_pci_bus(bus, sysinfo); - #endif - } - -} - -unsigned int get_nodes(void); - -void ht_setup_chains_x(struct sys_info *sysinfo) -{ - unsigned int get_sbdn(unsigned int bus); - u8 nodeid; - u32 reg; - u32 tempreg; - u8 next_busn; - u8 ht_c_num; - u8 nodes; -#if CONFIG_K8_ALLOCATE_IO_RANGE == 1 - unsigned next_io_base; -#endif - - nodes = get_nodes(); - - /* read PCI_DEV(0,0x18,0) 0x64 bit [8:9] to find out SbLink m */ - reg = pci_conf1_read_config32(PCI_BDF(0, 0x18, 0), 0x64); - /* update PCI_DEV(0, 0x18, 1) 0xe0 to 0x05000m03, and next_busn=0x3f+1 */ - print_linkn_in("SBLink=", ((reg>>8) & 3) ); - sysinfo->sblk = (reg>>8) & 3; - sysinfo->sbbusn = 0; - sysinfo->nodes = nodes; - tempreg = 3 | ( 0<<4) | (((reg>>8) & 3)<<8) | (0<<16)| (0x3f<<24); - pci_conf1_write_config32(PCI_BDF(0, 0x18, 1), 0xe0, tempreg); - - next_busn=0x3f+1; /* 0 will be used ht chain with SB we need to keep SB in bus0 in auto stage*/ - -#if CONFIG_K8_ALLOCATE_IO_RANGE == 1 - /* io range allocation */ - tempreg = 0 | (((reg>>8) & 0x3) << 4 )| (0x3<<12); //limit - pci_conf1_write_config32(PCI_BDF(0, 0x18, 1), 0xC4, tempreg); - tempreg = 3 | ( 3<<4) | (0<<12); //base - pci_conf1_write_config32(PCI_BDF(0, 0x18, 1), 0xC0, tempreg); - next_io_base = 0x3+0x1; -#endif - - /* clean others */ - for(ht_c_num=1;ht_c_num<4; ht_c_num++) { - pci_conf1_write_config32(PCI_BDF(0, 0x18, 1), 0xe0 + ht_c_num * 4, 0); - -#if CONFIG_K8_ALLOCATE_IO_RANGE == 1 - /* io range allocation */ - pci_conf1_write_config32(PCI_BDF(0, 0x18, 1), 0xc4 + ht_c_num * 8, 0); - pci_conf1_write_config32(PCI_BDF(0, 0x18, 1), 0xc0 + ht_c_num * 8, 0); -#endif - } - - for(nodeid=0; nodeid