coreboot-v3/northbridge/amd/k8/cpu.c
<<
>>
Prefs
   1/*
   2 * K8 northbridge 
   3 * This file is part of the coreboot project.
   4 * Copyright (C) 2004-2005 Linux Networx
   5 * (Written by Eric Biederman <ebiederman@lnxi.com> and Jason Schildt for Linux Networx)
   6 * Copyright (C) 2005-7 YingHai Lu
   7 * Copyright (C) 2005 Ollie Lo
   8 * Copyright (C) 2005-2007 Stefan Reinauer <stepan@openbios.org>
   9 * Copyright (C) 2008 Ronald G. Minnich <rminnich@gmail.com>
  10 *
  11 * This program is free software; you can redistribute it and/or modify
  12 * it under the terms of the GNU General Public License as published by
  13 * the Free Software Foundation; version 2 of the License.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 * GNU General Public License for more details.
  19 *
  20 * You should have received a copy of the GNU General Public License
  21 * along with this program; if not, write to the Free Software
  22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
  23 */
  24/* This should be done by Eric
  25        2004.12 yhlu add dual core support
  26        2005.01 yhlu add support move apic before pci_domain in MB Config.lb
  27        2005.02 yhlu add e0 memory hole support
  28        2005.11 yhlu add put sb ht chain on bus 0
  29*/
  30
  31#include <mainboard.h>
  32#include <config.h>
  33#include <console.h>
  34#include <lib.h>
  35#include <string.h>
  36#include <mtrr.h>
  37#include <macros.h>
  38#include <spd.h>
  39#include <cpu.h>
  40#include <msr.h>
  41#include <amd/k8/k8.h>
  42#include <amd/k8/sysconf.h>
  43#include <device/pci.h>
  44#include <device/hypertransport_def.h>
  45#include <device/hypertransport.h>
  46#include <mc146818rtc.h>
  47#include <lib.h>
  48#include  <lapic.h>
  49
  50static unsigned int cpu_bus_scan(struct device * dev, unsigned int max)
  51{
  52        struct bus *cpu_bus;
  53        struct device * dev_mc;
  54        int bsp_apicid;
  55        int i,j;
  56        unsigned nb_cfg_54;
  57        unsigned siblings;
  58        int e0_later_single_core; 
  59        int disable_siblings;
  60
  61        nb_cfg_54 = 0;
  62        sysconf.enabled_apic_ext_id = 0;
  63        sysconf.lift_bsp_apicid = 0;
  64        siblings = 0;
  65
  66        /* Find the bootstrap processors apicid */
  67        bsp_apicid = lapicid();
  68        sysconf.apicid_offset = bsp_apicid;
  69
  70        disable_siblings = !CONFIG_LOGICAL_CPUS;
  71#if CONFIG_LOGICAL_CPUS == 1
  72        get_option(&disable_siblings, "dual_core");
  73#endif
  74
  75        // for pre_e0, nb_cfg_54 can not be set, ( even set, when you read it still be 0)
  76        // How can I get the nb_cfg_54 of every node' nb_cfg_54 in bsp??? and differ d0 and e0 single core
  77
  78        nb_cfg_54 = read_nb_cfg_54();
  79
  80        dev_mc = dev_find_slot(0, PCI_DEVFN(0x18, 0));
  81        if (!dev_mc) {
  82                die("0:18.0 not found?");
  83        }
  84
  85        sysconf.nodes = ((pci_read_config32(dev_mc, 0x60)>>4) & 7) + 1;
  86        
  87
  88        if (pci_read_config32(dev_mc, 0x68) & (HTTC_APIC_EXT_ID|HTTC_APIC_EXT_BRD_CST))
  89        {
  90                sysconf.enabled_apic_ext_id = 1;
  91                if(bsp_apicid == 0) {
  92                        /* bsp apic id is not changed */
  93                        sysconf.apicid_offset = CONFIG_APIC_ID_OFFSET;
  94                } else 
  95                {
  96                        sysconf.lift_bsp_apicid = 1;
  97                }       
  98                
  99        }
 100
 101        /* Find which cpus are present */
 102        cpu_bus = &dev->link[0];
 103        for(i = 0; i < sysconf.nodes; i++) {
 104                struct device * dev, *cpu;
 105                struct device_path cpu_path;
 106
 107                /* Find the cpu's pci device */
 108                dev = dev_find_slot(0, PCI_DEVFN(0x18 + i, 3));
 109                if (!dev) {
 110                        /* If I am probing things in a weird order
 111                         * ensure all of the cpu's pci devices are found.
 112                         */
 113                        int j;
 114                        struct device * dev_f0;
 115                        for(j = 0; j <= 3; j++) {
 116                                dev = pci_probe_dev(NULL, dev_mc->bus,
 117                                        PCI_DEVFN(0x18 + i, j));
 118                        }
 119                        /* Ok, We need to set the links for that device.
 120                         * otherwise the device under it will not be scanned
 121                         */
 122                        dev_f0 = dev_find_slot(0, PCI_DEVFN(0x18+i,0));
 123                        if(dev_f0) {
 124                                dev_f0->links = 3;
 125                                for(j=0;j<3;j++) {
 126                                        dev_f0->link[j].link = j;
 127                                        dev_f0->link[j].dev = dev_f0;
 128                                }
 129                        }
 130
 131                }
 132
 133#warning clean this mess up
 134                e0_later_single_core = 0;
 135                if (dev && dev->enabled) {
 136                        j = pci_read_config32(dev, 0xe8);
 137                        j = (j >> 12) & 3; // dev is func 3
 138                        printk(BIOS_DEBUG, "  %s siblings=%d\n", dev_path(dev), j);
 139
 140                        if(nb_cfg_54) {
 141                                // For e0 single core if nb_cfg_54 is set, apicid will be 0, 2, 4.... 
 142                                //  ----> you can mixed single core e0 and dual core e0 at any sequence
 143                                // That is the typical case
 144
 145                                if(j == 0 ){
 146                                        e0_later_single_core = 1; // we are all f0 or later now. is_cpu_f0_in_bsp(i);  // We can read cpuid(1) from Func3
 147                                } else {
 148                                       e0_later_single_core = 0;
 149                                }
 150                                if(e0_later_single_core) { 
 151                                        printk(BIOS_DEBUG, "\tFound Rev E or Rev F later single core\n");
 152
 153                                        j=1; 
 154                                }
 155        
 156                                if(siblings > j ) {
 157                                }
 158                                else {
 159                                        siblings = j;
 160                                }
 161                        } else {
 162                                siblings = j;
 163                        }
 164                }
 165                
 166                unsigned jj;
 167                if(e0_later_single_core || disable_siblings) {
 168                        jj = 0;
 169                } else 
 170                {
 171                        jj = siblings;
 172                }
 173#if 0   
 174                jj = 0; // if create cpu core1 path in amd_siblings by core0
 175#endif
 176        
 177                for (j = 0; j <=jj; j++ ) {
 178                
 179                        /* Build the cpu device path */
 180                        cpu_path.type = DEVICE_PATH_APIC;
 181                        cpu_path.apic.apic_id = i * (nb_cfg_54?(siblings+1):1) + j * (nb_cfg_54?1:8);
 182                        
 183                        /* See if I can find the cpu */
 184                        cpu = find_dev_path(cpu_bus, &cpu_path);
 185                        
 186                        /* Enable the cpu if I have the processor */
 187                        if (dev && dev->enabled) {
 188                                /* this is a CPU */
 189                                struct device_id did;
 190                                did.type = DEVICE_ID_CPU;
 191#warning fill cpuid; right now it is zero
 192                                if (!cpu) {
 193                                        cpu = alloc_dev(cpu_bus, &cpu_path, &did);
 194                                }
 195                                if (cpu) {
 196                                        cpu->enabled = 1;
 197                                }
 198                        }
 199                
 200                        /* Disable the cpu if I don't have the processor */
 201                        if (cpu && (!dev || !dev->enabled)) {
 202                                cpu->enabled = 0;
 203                        }
 204
 205                        /* Report what I have done */
 206                        if (cpu) {
 207                                cpu->path.apic.node_id = i;
 208                                cpu->path.apic.core_id = j;
 209                                if(sysconf.enabled_apic_ext_id) {
 210                                        if(sysconf.lift_bsp_apicid) { 
 211                                                cpu->path.apic.apic_id += sysconf.apicid_offset;
 212                                        } else 
 213                                        {
 214                                               if (cpu->path.apic.apic_id != 0) 
 215                                                       cpu->path.apic.apic_id += sysconf.apicid_offset;
 216                                        }
 217                                }
 218                                printk(BIOS_DEBUG, "CPU: %s %s\n",
 219                                        dev_path(cpu), cpu->enabled?"enabled":"disabled");
 220                        }
 221
 222                } //j
 223        }
 224        return max;
 225}
 226
 227static void cpu_bus_init(struct device * dev)
 228{
 229        /* unclear if we need this any more. CPUs are in the device tree. */
 230        //      initialize_cpus(&dev->link[0]);
 231        //so what do we do? This is a first for v3. 
 232}
 233
 234static void cpu_bus_noop(struct device * dev) 
 235{
 236}
 237
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.