From 8ae8c8822068ef1722c08073ffa4ecc25633cbee Mon Sep 17 00:00:00 2001 From: Marc Jones Date: Wed, 19 Dec 2007 01:32:08 +0000 Subject: Initial AMD Barcelona support for rev Bx. These are the core files for HyperTransport, DDR2 Memory, and multi-core initialization. Signed-off-by: Marc Jones Reviewed-by: Jordan Crouse Acked-by: Myles Watson git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3014 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/cpu/amd/model_10xxx/pstate.c | 456 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 456 insertions(+) create mode 100644 src/cpu/amd/model_10xxx/pstate.c (limited to 'src/cpu/amd/model_10xxx/pstate.c') diff --git a/src/cpu/amd/model_10xxx/pstate.c b/src/cpu/amd/model_10xxx/pstate.c new file mode 100644 index 0000000000..a3545a0d74 --- /dev/null +++ b/src/cpu/amd/model_10xxx/pstate.c @@ -0,0 +1,456 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2007 Advanced Micro Devices, Inc. + * + * 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; version 2 of the License. + * + * 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 +#include +#include +#include +#include +#include + +#include "../../../northbridge/amd/amdfam10/amdfam10.h" + +#include +#include +#include +#include +#include + +#include + +#include +#include + +extern device_t get_node_pci(u32 nodeid, u32 fn); + +#include "fidvid_common.c" + +#define PSTATES_DEBUG 0 + + + +static void inline dump_msr_pstates(u32 nodes) +{ +#if PSTATES_DEBUG==1 + int i, j; + for(j=0; j<5; j++) { + printk_debug("P%d:", j); + for(i=0;i>8)&3) { + case 0: times = 1000; break; + case 1: times = 100; break; + case 2: times = 10; break; + default: + //error + times = 1; + } + + return (val & 0xff) * times; + +} + + +static u32 get_powerstep(u32 val) +{ + u32 time; + if(val<4) {time = (4 - val)*100;} + else if(val<8) { time = (9+4-val)*10;} + else { time = (10+8-val) * 5; } + + return time; + +} + + +static u32 get_plllocktime(u32 val) +{ + u32 time; + switch(val) { + case 0: + case 1: + case 2: + case 3: + time = val+1; break; + case 4: time = 8; break; + case 5: time = 16; break; + default: + //erro2 + time = 1; + } + return time; +} + + +static void disable_pstate(u32 nodes, u32 *p) +{ + int i; + + for(i=0;i> 31); + if(!enable) { + disable_pstate(nodes, p); + return; + } + corecof_min = ((sysconf.msr_pstate[0*5+p[0]].lo & 0x3f) + 0x10)>>((sysconf.msr_pstate[0*5+p[0]].lo>>6) & 7); + pwrval_max = sysconf.msr_pstate[0*5+p[0]].hi & 0x3ff; + pwrvalue_max = get_pwrvalue(pwrval_max); + + for(i=1; i> 31); + if(!enable) { + disable_pstate(nodes, p); + return; + } + + u32 coredid = ((sysconf.msr_pstate[i*5+p[i]].lo>>6) & 7); + u32 corecof = ((sysconf.msr_pstate[i*5+p[i]].lo & 0x3f) + 0x10)>>coredid; + if(corecofpwrvalue_max) { + pwrvalue_max = pwrvalue; + pwrval_max = pwrval; + } + } + + for(i=0; i>6) & 7); + u32 corefid = (corecof_min<>7) & 0x3f; + for(j=0; j<5; j++) { + val = pci_read_config32(f4_dev[i], 0x1e0 + (j<<2)); + nbdid = ((val>>16) & 1); + sysconf.msr_pstate[i*5+j].lo = (val & 0xffff) | (nbdid<<22) | ((nbdid?nbvid1:nbvid0)<<25); + sysconf.msr_pstate[i*5+j].hi = (((val>>17) & 0x3ff) << (32-32)) | (((val>>27) & 1)<<(63-32)); + } + } + + dump_msr_pstates(nodes); + + sysconf.needs_update_pstate_msrs = 0; // normal case for all sockets are installed same conf CPU + + for(i=1; (i>28) & 7)); + if(p_htc[i] == 0) { + val |= 1<<28; + pci_write_config32(f3_dev[i], 0x64, val); + val = pci_read_config32(f3_dev[i], 0x68); //stc + val &= ~(7<<28); + val |= (1<<28); + pci_write_config32(f3_dev[i], 0x68, val); + + p_htc[i] = 1; + } + } + if(htc_cap) { + match_pstate(nodes, p_htc); + + dump_p("P_htc\n", nodes, p_htc); + dump_msr_pstates(nodes); + } + + //p_lowest + for(i=0;i((val>>8) & 7)) { + val &= ~(7<<8); + val |= (p_lowest[i])<<8; + pci_write_config32(f3_dev[i], 0xdc, val); + } + else { + p_lowest[i] = (val>>8) & 7; + } + } + if(htc_cap) { + for(i=0;ihi & (1<<(63-32)) )) continue; + if((msr_pstate->lo & 0x3f) != corefid) { + corefid_equal = 0; + break; + } + } + for(j=0; j<5; j++) { + struct p_state_t *p_state; + msr_t *msr_pstate; + msr_pstate = &sysconf.msr_pstate[i*5+j]; + if(!(msr_pstate->hi & (1<<(63-32)) )) continue; + p_state = &sysconf.p_state[i*5+sysconf.p_state_num]; + u32 coredid = ((msr_pstate->lo>>6) & 7); + u32 corecof = ((msr_pstate->lo & 0x3f) + 0x10)>>coredid; + p_state->corefreq = corecof; + + u32 pwrval, pwrvalue; + pwrval = msr_pstate->hi & 0x3ff; + pwrvalue = get_pwrvalue(pwrval); + p_state->power = pwrvalue; + + u32 lat; + val = pci_read_config32(f3_dev[i], 0xd4); + lat = 15 * (get_powerstep((val>>24)& 0xf)+get_powerstep((val>>20)& 0xf)) /1000; + if(!corefid_equal) { + val = pci_read_config32(f3_dev[i], 0xa0); + lat += get_plllocktime((val >> 11 ) & 7); + } + p_state->transition_lat = lat; + p_state->busmaster_lat = lat; + + p_state->control = j; + p_state->status = j; + + sysconf.p_state_num++; + } + // don't need look at other nodes + if(!sysconf.p_state_num) break; + } +} + + +//it will update pstates info from ram into MSR +void init_pstates(device_t dev, u32 nodeid, u32 coreid) +{ + int j; + msr_t msr; + + if(sysconf.needs_update_pstate_msrs) { + for(j=0; j < 5; j++) { + wrmsr(0xC0010064 + j, sysconf.msr_pstate[nodeid * 5 + j]); + } + } + + /* Set TSC Freq Select: TSC increments at the rate of the core P-state 0 */ + msr = rdmsr(0xC0010015); + msr.lo |= 1 << 24; + wrmsr(0xC0010015, msr); + + // Enter the state P0 + //FIXME I don't think that this works correctly. May depend on early fid/vid setup. + if(sysconf.p_state_num) + set_core_nb_max_pstate_after_other_warm_reset(nodeid, coreid); + +} -- cgit v1.2.3