diff options
Diffstat (limited to 'src/mainboard/momentum/apache/boardutil.c')
-rw-r--r-- | src/mainboard/momentum/apache/boardutil.c | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/src/mainboard/momentum/apache/boardutil.c b/src/mainboard/momentum/apache/boardutil.c new file mode 100644 index 0000000000..370d1a47e5 --- /dev/null +++ b/src/mainboard/momentum/apache/boardutil.c @@ -0,0 +1,406 @@ +/* + * Copyright (C) 2003, Greg Watson <gwatson@lanl.gov> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +/* + * Do very early board initialization: + * + * - Configure External Bus (EBC) + * - Setup Flash + * - Setup NVRTC + * - Setup Board Control and Status Registers (BCSR) + * - Enable UART0 for debugging + */ + +#include "boardutil.h" +#include "ppc970lib.h" +#include "ppc970.h" +#include "stddef.h" +#include "string.h" + +/*----------------------------------------------------------------------------+ +| What_platform. ++----------------------------------------------------------------------------*/ +int what_platform() +{ + + #ifdef PPC970FX_EVB_LITE + return(PLATFORM_EVB_LITE); + #endif + #ifdef PPC970FX_EVB + return(PLATFORM_EVB_FINAL); + #endif +} + +/*----------------------------------------------------------------------------+ +| Get_system_info. Cannot access any global variables in this function. ++----------------------------------------------------------------------------*/ +void get_system_info(board_cfg_data_t *board_cfg) +{ + + unsigned long msr; + unsigned long data; + + if (board_cfg==NULL) { + (void)ppcHalt(); + } + msr=ppcAndMsr((unsigned long)~MSR_EE); + board_cfg->usr_config_ver[0]='1'; + board_cfg->usr_config_ver[1]='.'; + board_cfg->usr_config_ver[2]='0'; + board_cfg->usr_config_ver[3]='\0'; + /*-------------------------------------------------------------------------+ + | Read power status register. + +-------------------------------------------------------------------------*/ + data=read_psr()&SCOM_PSR_FREQ_MASK; + if (data==SCOM_PSR_FREQ_FULL) { + board_cfg->freq_ratio=1; + } else if (data==SCOM_PSR_FREQ_HALF) { + board_cfg->freq_ratio=2; + } else if (data==SCOM_PSR_FREQ_QUARTER) { + board_cfg->freq_ratio=4; + } else { + board_cfg->freq_ratio=0; + } + /*-------------------------------------------------------------------------+ + | Read information passed from service processor. + +-------------------------------------------------------------------------*/ + if (get_ei_ratio(&data)==0) { + board_cfg->ei_ratio=data; + } else { + board_cfg->ei_ratio=0; + } + if (get_sys_clk(&data)==0) { + board_cfg->sys_freq=data; + } else { + board_cfg->sys_freq=0; + } + if (get_pll_mult(&data)==0) { + if (board_cfg->freq_ratio!=0) { + board_cfg->cpu_freq=(board_cfg->sys_freq* data)/ board_cfg->freq_ratio; + } else { + board_cfg->cpu_freq=0; + } + } else { + data=0; + board_cfg->cpu_freq=0; + } + /*-------------------------------------------------------------------------+ + | On some boards we have to execute with timers running on internal clock. + +-------------------------------------------------------------------------*/ + if ((ppcMfspr_any(SPR_HID0)&HID0_EXT_TB_EN)==0) { + board_cfg->tmr_freq=(board_cfg->sys_freq* data)/ PPC970_TB_RATIO; + } else { + board_cfg->tmr_freq=EXT_TIME_BASE_FREQ; + } + /*-------------------------------------------------------------------------+ + | If the above calculation did not yield valid timer speed try to estimate + | it. + +-------------------------------------------------------------------------*/ + if (board_cfg->tmr_freq==0) { + board_cfg->tmr_freq=timebase_speed_calc(UART1_MMIO_BASE); + } + /*-------------------------------------------------------------------------+ + | Read information passed from service processor. + +-------------------------------------------------------------------------*/ + board_cfg->mem_size=sdram_size(); + /*-------------------------------------------------------------------------+ + | Assign rest of the information. + +-------------------------------------------------------------------------*/ + board_cfg->ser_freq=UART_INPUT_CLOCK; + board_cfg->procver=ppcMfspr_any(SPR_PVR); + board_cfg->hid0=ppcMfspr_any(SPR_HID0); + board_cfg->hid1=ppcMfspr_any(SPR_HID1); + board_cfg->hid4=ppcMfspr_any(SPR_HID4); + board_cfg->hid5=ppcMfspr_any(SPR_HID5); + board_cfg->hior=ppcMfspr_any(SPR_HIOR); + board_cfg->sdr1=ppcMfspr_any(SPR_SDR1); + board_cfg->procstr[0]='9'; + board_cfg->procstr[1]='7'; + board_cfg->procstr[2]='0'; + board_cfg->procstr[3]='F'; + board_cfg->procstr[4]='X'; + board_cfg->procstr[5]='\0'; + board_cfg->reserved[0]='\0'; + (void)get_hwd_addr((char *)board_cfg->hwaddr0, 0); + (void)ppcMtmsr(msr); + return; +} + +/*----------------------------------------------------------------------------+ +| Get_hwd_addr. ++----------------------------------------------------------------------------*/ +int get_hwd_addr(char *dest, + int ethernet_num) +{ + + bios_data_struct_t *bios_data; + char *src; + unsigned char nc; + int len; + int num; + + bios_data=(bios_data_struct_t *)PIBS_DATABASE_ADDR; + if (ethernet_num!=0) { + for(len=0;len<ETHERNET_HW_ADDR_LEN;len++) { + dest[len]=(char)0xFF; + } + return(-1); + } else { + src=bios_data->bios_eth_hwd0; + } + len=0; + while((src[len]!='\0') && (len<(ETHERNET_HW_ADDR_LEN* 3))) { + len++; + } + if (len!=(ETHERNET_HW_ADDR_LEN* 2)) { + for(len=0;len<ETHERNET_HW_ADDR_LEN;len++) { + dest[len]=(char)0xFF; + } + return(-1); + } + for(len=0;len<(ETHERNET_HW_ADDR_LEN* 2);len++) { + nc=toupper((int)src[len]); + if ((nc>='0') && (nc<='9')) { + num=nc- '0'; + } else if ((nc>='A') && (nc<='F')) { + num=nc- 'A'+ 0xA; + } else { + for(len=0;len<ETHERNET_HW_ADDR_LEN;len++) { + dest[len]=(char)0xFF; + } + return(-1); + } + if ((len%2)==0) { + dest[len/ 2]=(char)num; + } else { + dest[len/ 2]=(char)((dest[len/ 2]* 0x10)+ num); + } + } + return(0); +} + +/*----------------------------------------------------------------------------+ +| Get_sys_clk. ++----------------------------------------------------------------------------*/ +int get_sys_clk(unsigned long *value) +{ + + unsigned long data; + + if (read_sp_data(SUPER_IO_NVRAM_DATA_VALID, 4, &data)!=0) { + return(-1); + } + if (data!=SUPER_IO_VALID_VALUE) { + return(-1); + } + if (read_sp_data(SUPER_IO_NVRAM_SYS_CLK, 4, &data)!=0) { + return(-1); + } + *value=data; + return(0); +} + +/*----------------------------------------------------------------------------+ +| Get_pll_mult. ++----------------------------------------------------------------------------*/ +int get_pll_mult(unsigned long *value) +{ + + unsigned long data; + + if (read_sp_data(SUPER_IO_NVRAM_DATA_VALID, 4, &data)!=0) { + return(-1); + } + if (data!=SUPER_IO_VALID_VALUE) { + return(-1); + } + if (read_sp_data(SUPER_IO_NVRAM_CLK_MULT, 1, value)!=0) { + return(-1); + } + return(0); +} + +/*----------------------------------------------------------------------------+ +| Get_ei_ratio. ++----------------------------------------------------------------------------*/ +int get_ei_ratio(unsigned long *value) +{ + + unsigned long data; + + if (read_sp_data(SUPER_IO_NVRAM_DATA_VALID, 4, &data)!=0) { + return(-1); + } + if (data!=SUPER_IO_VALID_VALUE) { + return(-1); + } + if (read_sp_data(SUPER_IO_NVRAM_EI_RATIO, 1, &data)!=0) { + return(-1); + } + + if (data==0x0000000000000000) data=PPC970_EI_RATIO_000; + else if (data==0x0000000000000001) data=PPC970_EI_RATIO_001; + else if (data==0x0000000000000002) data=PPC970_EI_RATIO_010; + else if (data==0x0000000000000003) data=PPC970_EI_RATIO_011; + else if (data==0x0000000000000004) data=PPC970_EI_RATIO_100; + else if (data==0x0000000000000005) data=PPC970_EI_RATIO_101; + else if (data==0x0000000000000006) data=PPC970_EI_RATIO_110; + else return(-1); + + *value=data; + return(0); +} + +/*----------------------------------------------------------------------------+ +| Read_sp_data. ++----------------------------------------------------------------------------*/ +int read_sp_data(unsigned int offset, + unsigned int count, unsigned long *data) +{ + + unsigned long addr_index; + unsigned long addr_data; + unsigned long addr; + unsigned int new_data; + unsigned int i; + + /*-------------------------------------------------------------------------+ + | If this is not a JS20 or EVB platform then just return. + +-------------------------------------------------------------------------*/ + if (what_platform()==PLATFORM_EVB_FINAL) { + addr_index=NB_HT_IO_BASE_CPU+ SUPER_IO_ADDR_NVRAM; + addr_data=NB_HT_IO_BASE_CPU+ SUPER_IO_ADDR_NVRAM+ 1; + *data=0x0000000000000000; + for(i=0;i<count;i++) { + (void)outbyte(addr_index, offset+ i); + new_data=inbyte(addr_data); + *data|=new_data<<((count- i- 1)* 8); + } + return(0); + } else if (what_platform()==PLATFORM_EVB_LITE) { + addr=SB_NVRAM_ADDR; + *data=0x0000000000000000; + for(i=0;i<count;i++) { + new_data=inbyte(addr+ i+ offset); + *data|=new_data<<((count- i- 1)* 8); + } + return(0); + } + return(-1); +} + +/*----------------------------------------------------------------------------+ +| Write_sp_data. ++----------------------------------------------------------------------------*/ +int write_sp_data(unsigned int offset, + unsigned int data) +{ + + unsigned long addr_index; + unsigned long addr_data; + unsigned long addr; + + /*-------------------------------------------------------------------------+ + | If this is not a JS20 or EVB platform then just return. + +-------------------------------------------------------------------------*/ + if (what_platform()==PLATFORM_EVB_FINAL) { + addr_index=NB_HT_IO_BASE_CPU+ SUPER_IO_ADDR_NVRAM; + addr_data=NB_HT_IO_BASE_CPU+ SUPER_IO_ADDR_NVRAM+ 1; + (void)outbyte(addr_index, offset); + (void)outbyte(addr_data, data); + return(0); + } else if (what_platform()==PLATFORM_EVB_LITE) { + addr=SB_NVRAM_ADDR; + (void)outbyte(addr+ offset, data); + return(0); + } + return(-1); +} + +/*----------------------------------------------------------------------------+ +| Read_psr. ++----------------------------------------------------------------------------*/ +unsigned long read_psr() +{ + + unsigned long msr; + unsigned long value; + + msr=ppcAndMsr((unsigned long)~MSR_EE); + (void)ppcMtspr_any(SPR_SCOMC, SCOM_ADDR_PSR_READ); + (void)ppcIsync(); + value=ppcMfspr_any(SPR_SCOMD); + (void)ppcIsync(); + (void)ppcMtmsr(msr); + return(value); +} + +/*----------------------------------------------------------------------------+ +| Write_pcr_pcrh. ++----------------------------------------------------------------------------*/ +void write_pcr_pcrh(unsigned long data) +{ + + unsigned long msr; + + msr=ppcAndMsr((unsigned long)~MSR_EE); + /*-------------------------------------------------------------------------+ + | First write to PCR with all 0 (errata). + +-------------------------------------------------------------------------*/ + (void)ppcMtspr_any(SPR_SCOMD, SCOM_ADDR_PCR_DATA_MASK); + (void)ppcIsync(); + (void)ppcMtspr_any(SPR_SCOMC, SCOM_ADDR_PCR_WRITE); + (void)ppcIsync(); + /*-------------------------------------------------------------------------+ + | Write to PCRH. + +-------------------------------------------------------------------------*/ + (void)ppcMtspr_any(SPR_SCOMD, 0x0000000000000000UL); + (void)ppcIsync(); + (void)ppcMtspr_any(SPR_SCOMC, SCOM_ADDR_PCR_WRITE); + (void)ppcIsync(); + /*-------------------------------------------------------------------------+ + | Write to PCR. + +-------------------------------------------------------------------------*/ + (void)ppcMtspr_any(SPR_SCOMD, data|SCOM_ADDR_PCR_DATA_MASK); + (void)ppcIsync(); + (void)ppcMtspr_any(SPR_SCOMC, SCOM_ADDR_PCR_WRITE); + (void)ppcIsync(); + (void)ppcMtmsr(msr); + return; +} + +/*----------------------------------------------------------------------------+ +| Is_writable. ++----------------------------------------------------------------------------*/ +int is_writable(unsigned long addr, + unsigned long len) +{ + + if ((addr>=BOOT_BASE) && (addr<SDRAM_UPPER_BASE)) { + return(0); + } + if ((addr+ len)>=BOOT_BASE) { + return(0); + } + return(1); +} + |