coreboot-v3/northbridge/amd/k8/get_sblk_pci1234.c
<<
>>
Prefs
   1/*
   2 * This file is part of the coreboot project.
   3 *
   4 * Copyright (C) 2005 - 2008 Advanced Micro Devices, Inc.
   5 * Copyright (C) 2007 coresystems GmbH
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; version 2 of the License.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  19 */
  20
  21
  22// 2005.9 yhlu    serengeti support
  23// 2005.9 yhlu    modify that to more dynamic for AMD Opteron Based MB
  24// 2007.9 stepan  improve code documentation
  25
  26#include <mainboard.h>
  27#include <console.h>
  28#include <mtrr.h>
  29#include <macros.h>
  30#include <spd.h>
  31#include <cpu.h>
  32#include <msr.h>
  33#include <amd/k8/k8.h>
  34#include <amd/k8/sysconf.h>
  35#include <device/pci.h>
  36#include <device/hypertransport_def.h>
  37#include <mc146818rtc.h>
  38#include <lib.h>
  39
  40
  41#if 0
  42unsigned node_link_to_bus(unsigned node, unsigned link)
  43{
  44        struct device * dev;
  45        unsigned reg;
  46
  47        dev = dev_find_slot(0, PCI_DEVFN(0x18, 1));
  48        if (!dev) {
  49                return 0;
  50        }
  51        for(reg = 0xE0; reg < 0xF0; reg += 0x04) {
  52                u32 config_map;
  53                unsigned dst_node;
  54                unsigned dst_link;
  55                unsigned bus_base;
  56                config_map = pci_read_config32(dev, reg);
  57                if ((config_map & 3) != 3) {
  58                        continue;
  59                }
  60                dst_node = (config_map >> 4) & 7;
  61                dst_link = (config_map >> 8) & 3;
  62                bus_base = (config_map >> 16) & 0xff;
  63#if 0
  64                printk(BIOS_DEBUG, "node.link=bus: %d.%d=%d 0x%2x->0x%08x\n",
  65                        dst_node, dst_link, bus_base,
  66                        reg, config_map);
  67#endif
  68                if ((dst_node == node) && (dst_link == link))
  69                {
  70                        return bus_base;
  71                }
  72        }
  73        return 0;
  74}
  75#endif
  76
  77
  78/**
  79 * Why we need the pci1234[] array
  80 *
  81 * It will keep the sequence of HT devices in the HT link registers even when a
  82 * given HT I/O card is not installed.
  83 *
  84 * The final result for pci1234[] will be
  85 *
  86 *     pci1234[0] will record the south bridge link and bus range
  87 *     pci1234[i] will record HT chain i.
  88 *
  89 * For example, on the Tyan S2885 linxbios_ram will put the AMD8151 chain (HT
  90 * link 0) into the register 0xE0, and the AMD8131/8111 HT chain into the
  91 * register 0xE4.
  92 *
  93 * So we need to make sure that the south bridge link will always be on
  94 * pci1234[0].
  95 *
  96 * Imagine a scenario with multiple HT I/O cards, where you don't install HT I/O 1, 
  97 * but you only install HT I/O 2 and HT I/O 3. The HT I/Os  will end up in registers 
  98 * 0xE4 and 0xE8.
  99 *
 100 * But we want to leave pci1234[1] to HT I/O 1 (even though it is disabled),
 101 * and let HT I/O 2 and HT I/O 3 still use pci1234[2] and pci1234[3].
 102 *
 103 * So we keep the sequence. You need to preset the pci1234[1], pci1234[2],
 104 * pci1234[3] for this purpose.
 105 *
 106 * For this example you need to set
 107 *
 108 *     unsigned pci1234[] = {
 109 *             0x0000ff0,
 110 *             0x0000f10, // HT IO 1 card always on node 1
 111 *             0x0000f20, // HT IO 2 card always on node 2
 112 *             0x0000f30  // HT IO 3 card always on node 3
 113 *     };
 114 *
 115 * For 2P + htio(n1) + htio(n0_1) + htio(n1_1), 2P + htio(n1) + 2P + htio(n2) + htio(n3):
 116 * You need an array pci1234[6]:
 117 *
 118 *     unsigned pci1234[] = {
 119 *             0x0000ff0,
 120 *             0x0000010, // HT IO 1 card always on node 1
 121 *             0x0000f00, // HT IO 2 card always on node 0
 122 *             0x0000110, // HT IO 3 card always on node 1
 123 *             0x0000f20, // HT IO 4 card always on node 2
 124 *             0x0000f30  // HT IO 5 card always on node 3
 125 *     };
 126 *
 127 *
 128 * For 4p+htio(n1)+htio(n2)+htio(n3),4p+htio(n1)+4p+htio(n6)+htio(n7):  
 129 * You need an array pci1234[6]:
 130 *
 131 *     unsigned pci1234[] = {
 132 *             0x0000ff0,
 133 *             0x0000f10, // HT IO 1 card always on node 1
 134 *             0x0000f20, // HT IO 2 card always on node 2
 135 *             0x0000f30, // HT IO 3 card always on node 3
 136 *             0x0000f60, // HT IO 4 card always on node 6
 137 *             0x0000f70  // HT IO 5 card always on node 7
 138 *     };
 139 * 
 140 * 
 141 * For 2p + htio(n1) + htio(n0_1) + htio(n1_1), 2P + htio(n1) + 2P + 
 142 * htio(n2) + htio(n3), 2P + htio(n1) + 4P + htio(n4) + htio(n5), 
 143 * you need an array pci1234[8]:
 144 *
 145 *     unsigned pci1234[] = {
 146 *             0x0000ff0,
 147 *             0x0000010, // HT IO 1 card always on node 1
 148 *             0x0000f00, // HT IO 2 card always on node 0
 149 *             0x0000110, // HT IO 3 card always on node 1
 150 *             0x0000f20, // HT IO 4 card always on node 2
 151 *             0x0000f30  // HT IO 5 card always on node 3
 152 *             0x0000f40, // HT IO 6 card always on node 4
 153 *             0x0000f50  // HT IO 7 card always on node 5
 154 *     };
 155 * 
 156 * 
 157 * For 4P + htio(n1) + htio(n2) + htio(n3), 4p + htio(n1) + 2p + htio(n4) +
 158 * htio(n5), 4p + htio(n1) + 4p + htio(n6) + htio(n7), 
 159 * you need an array pci1234[8]:
 160 *
 161 *     unsigned pci1234[] = {
 162 *             0x0000ff0,
 163 *             0x0000f10, // HT IO 1 card always on node 1
 164 *             0x0000f20, // HT IO 2 card always on node 2
 165 *             0x0000f30, // HT IO 3 card always on node 3
 166 *             0x0000f40, // HT IO 4 card always on node 4
 167 *             0x0000f50  // HT IO 5 card always on node 5
 168 *             0x0000f60, // HT IO 6 card always on node 6
 169 *             0x0000f70  // HT IO 7 card always on node 7
 170 *     };
 171 * 
 172 * 
 173 * So the maximum posible value of HC_POSSIBLE_NUM is 8. (FIXME Why?)
 174 * 
 175 *     1n:       3
 176 *     2n: 2x2 - 1
 177 *     4n: 1x4 - 2 
 178 *     6n:       2 
 179 *     8n:       2 
 180 *  Total:      12 
 181 * 
 182 * Just put all the possible HT Node/link to the list tp pci1234[] in 
 183 * src/mainboard/<vendor>/<mainboard>get_bus_conf.c
 184 * 
 185 * Also don't forget to increase the ACPI_SSDTX_NUM etc (FIXME what else) if
 186 * you have too many SSDTs
 187 * 
 188 * What about co-processor in socket 1 on a 2 way system? Or socket 2 and
 189 * socket 3 on a 4 way system? Treat that as an HC, too!
 190 * 
 191 */
 192
 193void get_sblk_pci1234(void)
 194{
 195
 196        struct device * dev;
 197        int i,j;
 198        u32 dword;
 199
 200        /* read PCI_DEV(0,0x18,0) 0x64 bit [8:9] to find out SbLink m */
 201        dev = dev_find_slot(0, PCI_DEVFN(0x18,0));
 202        dword = pci_read_config32(dev, 0x64);
 203        sysconf.sblk = (dword>>8) & 0x3;
 204
 205        dword &=0x0300;
 206        dword |= 1;
 207        sysconf.pci1234[0] = dword;
 208        sysconf.hcid[0] = 0;
 209
 210        /* About hardcoded numbering for HT_IO support
 211         *
 212         * Set the node_id and link_id that could have a HT chain in the one
 213         * array, (FIXME: which one?) then check if is enabled. Then update
 214         * final value 
 215         */
 216
 217        /* Here we need to set hcdn
 218         *
 219         * 1. hypertransport.c needs to record hcdn_reg together with 0xe0,
 220         *    0xe4, 0xe8, 0xec when are set (FIXME: when WHAT is set?)
 221         *
 222         * 2. So at the same time we need update hcdn with hcdn_reg here. FIXME: Why?
 223         */
 224
 225        dev = dev_find_slot(0, PCI_DEVFN(0x18, 1));
 226
 227        for(j=0;j<4;j++) {
 228                u32 dwordx;
 229                dwordx = pci_read_config32(dev, 0xe0 + j*4);
 230                dwordx &=0xffff0ff1; /* keep bus num, node_id, link_num, enable bits */
 231                if((dwordx & 0xff1) == dword) { /* SBLINK */
 232                        sysconf.pci1234[0] = dwordx;
 233                        sysconf.hcdn[0] = sysconf.hcdn_reg[j];
 234                        continue;
 235                }
 236
 237                if((dwordx & 1) == 1) {
 238                        /* We need to find out the number of HC
 239                         * for exact match
 240                         */
 241                        for(i=1;i<sysconf.hc_possible_num;i++) {
 242                                if((dwordx & 0xff0) == (sysconf.pci1234[i] & 0xff0)) {
 243                                        sysconf.pci1234[i] = dwordx;
 244                                        sysconf.hcdn[i] = sysconf.hcdn_reg[j];
 245                                        break;
 246                                }
 247                        }
 248
 249                        /* For 0xff0 match or same node */
 250                        for(i=1;i<sysconf.hc_possible_num;i++) {
 251                                if((dwordx & 0xff0) == (dwordx & sysconf.pci1234[i] & 0xff0)) {
 252                                        sysconf.pci1234[i] = dwordx;
 253                                        sysconf.hcdn[i] = sysconf.hcdn_reg[j];
 254                                        break;
 255                                }
 256                        }
 257                }
 258        }
 259
 260        for(i=1;i<sysconf.hc_possible_num;i++) {
 261                if((sysconf.pci1234[i] & 1) != 1) {
 262                        sysconf.pci1234[i] = 0;
 263                        sysconf.hcdn[i] = 0x20202020;
 264                }
 265                sysconf.hcid[i] = 0;
 266        }
 267
 268}
 269
 270
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.