diff options
author | stepan <stepan@coresystems.de> | 2010-12-08 05:42:47 +0000 |
---|---|---|
committer | Stefan Reinauer <stepan@openbios.org> | 2010-12-08 05:42:47 +0000 |
commit | 836ae29ee325b1e3d28ff59468cc50913b1e24ce (patch) | |
tree | e2691a1e1ee1d795ffe7a99fb93778a9910044c2 /src/southbridge/sis/sis966/nic.c | |
parent | 1bc5ccac51d94cfb4f9666ecf2cac619d8dc80a6 (diff) | |
download | coreboot-836ae29ee325b1e3d28ff59468cc50913b1e24ce.tar.xz |
first round name simplification. drop the <component>_ prefix.
the prefix was introduced in the early v2 tree many years ago
because our old build system "newconfig" could not handle two files with
the same name in different paths like /path/to/usb.c and
/another/path/to/usb.c correctly. Only one of the files would end up
being compiled into the final image.
Since Kconfig (actually since shortly before we switched to Kconfig) we
don't suffer from that problem anymore. So we could drop the sb700_
prefix from all those filenames (or, the <componentname>_ prefix in general)
- makes it easier to fork off a new chipset
- makes it easier to diff against other chipsets
- storing redundant information in filenames seems wrong
Signed-off-by: <stepan@coresystems.de>
Acked-by: Patrick Georgi <patrick@georgi-clan.de>
Acked-by: Peter Stuge <peter@stuge.se>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6149 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/southbridge/sis/sis966/nic.c')
-rw-r--r-- | src/southbridge/sis/sis966/nic.c | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/src/southbridge/sis/sis966/nic.c b/src/southbridge/sis/sis966/nic.c new file mode 100644 index 0000000000..a7aeec37ed --- /dev/null +++ b/src/southbridge/sis/sis966/nic.c @@ -0,0 +1,365 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2004 Tyan Computer + * Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer. + * Copyright (C) 2006,2007 AMD + * Written by Yinghai Lu <yinghai.lu@amd.com> for AMD. + * Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS) + * Written by Morgan Tsai <my_tsai@sis.com> for SiS. + * + * 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 <console/console.h> +#include <device/device.h> +#include <device/smbus.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include <arch/io.h> +#include <delay.h> +#include "sis966.h" + + +u8 SiS_SiS191_init[6][3]={ +{0x04, 0xFF, 0x07}, +{0x2C, 0xFF, 0x39}, +{0x2D, 0xFF, 0x10}, +{0x2E, 0xFF, 0x91}, +{0x2F, 0xFF, 0x01}, +{0x00, 0x00, 0x00} //End of table +}; + + +#define StatusReg 0x1 +#define SMI_READ 0x0 +#define SMI_REQUEST 0x10 +#define TRUE 1 +#define FALSE 0 + +u16 MacAddr[3]; + + +static void writeApcByte(int addr, u8 value) +{ + outb(addr,0x78); + outb(value,0x79); +} + +static u8 readApcByte(int addr) +{ + u8 value; + outb(addr,0x78); + value=inb(0x79); + return(value); +} + +static void readApcMacAddr(void) +{ + u8 i; + +// enable APC in south bridge sis966 D2F0 + + outl(0x80001048,0xcf8); + outl((inl(0xcfc) & 0xfffffffd),0xcfc ); // enable IO78/79h for APC Index/Data + + printk(BIOS_DEBUG, "MAC addr in APC = "); + for(i = 0x9 ; i <=0xe ; i++) + { + printk(BIOS_DEBUG, "%2.2x",readApcByte(i)); + } + printk(BIOS_DEBUG, "\n"); + + /* Set APC Reload */ + writeApcByte(0x7,readApcByte(0x7)&0xf7); + writeApcByte(0x7,readApcByte(0x7)|0x0a); + + /* disable APC in south bridge */ + outl(0x80001048,0xcf8); + outl(inl(0xcfc)&0xffffffbf,0xcfc); +} + +static void set_apc(struct device *dev) +{ + u16 addr; + u16 i; + u8 bTmp; + + /* enable APC in south bridge sis966 D2F0 */ + outl(0x80001048,0xcf8); + outl((inl(0xcfc) & 0xfffffffd),0xcfc ); // enable IO78/79h for APC Index/Data + + for(i = 0 ; i <3; i++) + { + addr=0x9+2*i; + writeApcByte(addr,(u8)(MacAddr[i]&0xFF)); + writeApcByte(addr+1L,(u8)((MacAddr[i]>>8)&0xFF)); + // printf("%x - ",readMacAddrByte(0x59+i)); + } + + /* Set APC Reload */ + writeApcByte(0x7,readApcByte(0x7)&0xf7); + writeApcByte(0x7,readApcByte(0x7)|0x0a); + + /* disable APC in south bridge */ + outl(0x80001048,0xcf8); + outl(inl(0xcfc)&0xffffffbf,0xcfc); + + // CFG reg0x73 bit=1, tell driver MAC Address load to APC + bTmp = pci_read_config8(dev, 0x73); + bTmp|=0x1; + pci_write_config8(dev, 0x73, bTmp); +} + +/** + * Read one word out of the serial EEPROM. + * + * @param dev TODO + * @param base TODO + * @param Reg EEPROM word to read. + * @return Contents of EEPROM word (Reg). + */ +#define LoopNum 200 +static unsigned long ReadEEprom( struct device *dev, u32 base, u32 Reg) +{ + u32 data; + u32 i; + u32 ulValue; + + + ulValue = (0x80 | (0x2 << 8) | (Reg << 10)); //BIT_7 + + write32(base+0x3c, ulValue); + + mdelay(10); + + for(i=0 ; i <= LoopNum; i++) + { + ulValue=read32(base+0x3c); + + if(!(ulValue & 0x0080)) //BIT_7 + break; + + mdelay(100); + } + + mdelay(50); + + if(i==LoopNum) data=0x10000; + else{ + ulValue=read32(base+0x3c); + data = ((ulValue & 0xffff0000) >> 16); + } + + return data; +} + +static int phy_read(u32 base, unsigned phy_addr, unsigned phy_reg) +{ + u32 ulValue; + u32 Read_Cmd; + u16 usData; + + + + Read_Cmd = ((phy_reg << 11) | + (phy_addr << 6) | + SMI_READ | + SMI_REQUEST); + + // SmiMgtInterface Reg is the SMI management interface register(offset 44h) of MAC + write32(base+0x44, Read_Cmd); + + // Polling SMI_REQ bit to be deasserted indicated read command completed + do + { + // Wait 20 usec before checking status + mdelay(20); + ulValue = read32(base+0x44); + } while((ulValue & SMI_REQUEST) != 0); + //printk(BIOS_DEBUG, "base %x cmd %lx ret val %lx\n", tmp,Read_Cmd,ulValue); + usData=(ulValue>>16); + + + + return usData; + +} + +// Detect a valid PHY +// If there exist a valid PHY then return TRUE, else return FALSE +static int phy_detect(u32 base,u16 *PhyAddr) //BOOL PHY_Detect() +{ + int bFoundPhy = FALSE; + u16 usData; + int PhyAddress = 0; + + + // Scan all PHY address(0 ~ 31) to find a valid PHY + for(PhyAddress = 0; PhyAddress < 32; PhyAddress++) + { + usData=phy_read(base,PhyAddress,StatusReg); // Status register is a PHY's register(offset 01h) + + // Found a valid PHY + + if((usData != 0x0) && (usData != 0xffff)) + { + bFoundPhy = TRUE; + break; + } + } + + + if(!bFoundPhy) + { + printk(BIOS_DEBUG, "PHY not found !!!! \n"); + } + + *PhyAddr=PhyAddress; + + return bFoundPhy; +} + + +static void nic_init(struct device *dev) +{ + int val; + u16 PhyAddr; + u32 base; + struct resource *res; + + print_debug("NIC_INIT:---------->\n"); + +//-------------- enable NIC (SiS19x) ------------------------- +{ + u8 temp8; + int i=0; + while(SiS_SiS191_init[i][0] != 0) + { + temp8 = pci_read_config8(dev, SiS_SiS191_init[i][0]); + temp8 &= SiS_SiS191_init[i][1]; + temp8 |= SiS_SiS191_init[i][2]; + pci_write_config8(dev, SiS_SiS191_init[i][0], temp8); + i++; + }; +} +//----------------------------------------------------------- + +{ + unsigned long i; + unsigned long ulValue; + + res = find_resource(dev, 0x10); + + if(!res) + { + printk(BIOS_DEBUG, "NIC Cannot find resource..\n"); + return; + } + base = res->base; + printk(BIOS_DEBUG, "NIC base address %x\n",base); + + if(!(val=phy_detect(base,&PhyAddr))) + { + printk(BIOS_DEBUG, "PHY detect fail !!!!\n"); + return; + } + + ulValue=read32(base + 0x38L); // check EEPROM existing + + if((ulValue & 0x0002)) + { + + // read MAC address from EEPROM at first + + // if that is valid we will use that + + printk(BIOS_DEBUG, "EEPROM contents %lx \n",ReadEEprom( dev, base, 0LL)); + for(i=0;i<3;i++) { + //status = smbus_read_byte(dev_eeprom, i); + ulValue=ReadEEprom( dev, base, i+3L); + if (ulValue ==0x10000) break; // error + + MacAddr[i] =ulValue & 0xFFFF; + + } + }else{ + // read MAC address from firmware + printk(BIOS_DEBUG, "EEPROM invalid!!\nReg 0x38h=%.8lx \n",ulValue); + MacAddr[0]=read16(0xffffffc0); // mac address store at here + MacAddr[1]=read16(0xffffffc2); + MacAddr[2]=read16(0xffffffc4); + } + + set_apc(dev); + + readApcMacAddr(); + +#if DEBUG_NIC +{ + int i; + + print_debug("****** NIC PCI config ******"); + print_debug("\n 03020100 07060504 0B0A0908 0F0E0D0C"); + + for(i=0;i<0xff;i+=4){ + if((i%16)==0){ + print_debug("\n"); + print_debug_hex8(i); + print_debug(": "); + } + print_debug_hex32(pci_read_config32(dev,i)); + print_debug(" "); + } + print_debug("\n"); +} + + +#endif + +} + +print_debug("NIC_INIT:<----------\n"); +return; + + +} + +static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + pci_write_config32(dev, 0x40, + ((device & 0xffff) << 16) | (vendor & 0xffff)); +} + +static struct pci_operations lops_pci = { + .set_subsystem = lpci_set_subsystem, +}; + +static struct device_operations nic_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = nic_init, + .scan_bus = 0, +// .enable = sis966_enable, + .ops_pci = &lops_pci, +}; + +static const struct pci_driver nic_driver __pci_driver = { + .ops = &nic_ops, + .vendor = PCI_VENDOR_ID_SIS, + .device = PCI_DEVICE_ID_SIS_SIS966_NIC, +}; |