get file names right
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1514 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
		
							
								
								
									
										464
									
								
								src/southbridge/via/vt8235/vt8235.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										464
									
								
								src/southbridge/via/vt8235/vt8235.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,464 @@
 | 
			
		||||
 | 
			
		||||
#include <arch/io.h>
 | 
			
		||||
#include <device/device.h>
 | 
			
		||||
#include <device/pci.h>
 | 
			
		||||
#include <device/pci_ops.h>
 | 
			
		||||
#include <device/pci_ids.h>
 | 
			
		||||
#include <device/chip.h>
 | 
			
		||||
#include <console/console.h>
 | 
			
		||||
#include "vt8231.h"
 | 
			
		||||
#include "chip.h"
 | 
			
		||||
 | 
			
		||||
void pc_keyboard_init(void);
 | 
			
		||||
 | 
			
		||||
void hard_reset(void) 
 | 
			
		||||
{
 | 
			
		||||
	printk_err("NO HARD RESET ON VT8231! FIX ME!\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void usb_on(int enable)
 | 
			
		||||
{
 | 
			
		||||
	unsigned char regval;
 | 
			
		||||
 | 
			
		||||
	/* Base 8231 controller */
 | 
			
		||||
	device_t dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0);
 | 
			
		||||
	/* USB controller 1 */
 | 
			
		||||
	device_t dev2 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, 0);
 | 
			
		||||
	/* USB controller 2 */
 | 
			
		||||
	device_t dev3 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, dev2);
 | 
			
		||||
	
 | 
			
		||||
	/* enable USB1 */
 | 
			
		||||
	if(dev2) {
 | 
			
		||||
		if (enable) {
 | 
			
		||||
			pci_write_config8(dev2, 0x3c, 0x05);
 | 
			
		||||
			pci_write_config8(dev2, 0x04, 0x07);
 | 
			
		||||
		} else {
 | 
			
		||||
			pci_write_config8(dev2, 0x3c, 0x00);
 | 
			
		||||
			pci_write_config8(dev2, 0x04, 0x00);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if(dev0) {
 | 
			
		||||
		regval = pci_read_config8(dev0, 0x50);
 | 
			
		||||
		if (enable) 
 | 
			
		||||
			regval &= ~(0x10);    
 | 
			
		||||
		else
 | 
			
		||||
			regval |= 0x10;    	      
 | 
			
		||||
		pci_write_config8(dev0, 0x50, regval);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* enable USB2 */
 | 
			
		||||
	if(dev3) {
 | 
			
		||||
		if (enable) {
 | 
			
		||||
			pci_write_config8(dev3, 0x3c, 0x05);
 | 
			
		||||
			pci_write_config8(dev3, 0x04, 0x07);
 | 
			
		||||
		} else {
 | 
			
		||||
			pci_write_config8(dev3, 0x3c, 0x00);
 | 
			
		||||
			pci_write_config8(dev3, 0x04, 0x00);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if(dev0) {
 | 
			
		||||
		regval = pci_read_config8(dev0, 0x50);
 | 
			
		||||
		if (enable) 
 | 
			
		||||
			regval &= ~(0x20);    
 | 
			
		||||
		else
 | 
			
		||||
			regval |= 0x20;    
 | 
			
		||||
		pci_write_config8(dev0, 0x50, regval);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void keyboard_on(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned char regval;
 | 
			
		||||
	
 | 
			
		||||
	/* Base 8231 controller */
 | 
			
		||||
	device_t dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0);
 | 
			
		||||
	
 | 
			
		||||
	/* kevinh/Ispiri - update entire function to use 
 | 
			
		||||
	   new pci_write_config8 */
 | 
			
		||||
 | 
			
		||||
	if (dev0) {
 | 
			
		||||
		regval = pci_read_config8(dev0, 0x51);
 | 
			
		||||
		regval |= 0x0f; 
 | 
			
		||||
		pci_write_config8(dev0, 0x51, regval);
 | 
			
		||||
	}
 | 
			
		||||
	init_pc_keyboard(0x60, 0x64, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void nvram_on(void)
 | 
			
		||||
{
 | 
			
		||||
	/*
 | 
			
		||||
	 * the VIA 8231 South has a very different nvram setup than the 
 | 
			
		||||
	 * piix4e ...
 | 
			
		||||
	 * turn on ProMedia nvram.
 | 
			
		||||
	 * TO DO: use the PciWriteByte function here.
 | 
			
		||||
	 */
 | 
			
		||||
	
 | 
			
		||||
	/*
 | 
			
		||||
	 * kevinh/Ispiri - I don't think this is the correct address/value
 | 
			
		||||
	 * intel_conf_writeb(0x80008841, 0xFF);
 | 
			
		||||
	 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Enable the ethernet device and turn off stepping (because it is integrated 
 | 
			
		||||
 * inside the southbridge)
 | 
			
		||||
 */
 | 
			
		||||
static void ethernet_fixup()
 | 
			
		||||
{
 | 
			
		||||
	device_t	edev;
 | 
			
		||||
	uint8_t		byte;
 | 
			
		||||
 | 
			
		||||
	printk_info("Ethernet fixup\n");
 | 
			
		||||
 | 
			
		||||
	edev = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_7, 0);
 | 
			
		||||
	if (edev) {
 | 
			
		||||
		printk_debug("Configuring VIA LAN\n");
 | 
			
		||||
		
 | 
			
		||||
		/* We don't need stepping - though the device supports it */
 | 
			
		||||
		byte = pci_read_config8(edev, PCI_COMMAND);
 | 
			
		||||
		byte &= ~PCI_COMMAND_WAIT;
 | 
			
		||||
		pci_write_config8(edev, PCI_COMMAND, byte);
 | 
			
		||||
	} else {
 | 
			
		||||
		printk_debug("VIA LAN not found\n");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* we need to do things in this function so that PCI scan will find 
 | 
			
		||||
 * them.  One problem here is that we can't use ANY of the new device 
 | 
			
		||||
 * stuff. This work here precedes all that.      
 | 
			
		||||
 * Fundamental problem with linuxbios V2 architecture.
 | 
			
		||||
 * You can't do pci control in the C code without having done a PCI scan.
 | 
			
		||||
 * But in some cases you need to to pci control in the c code before doing
 | 
			
		||||
 * a PCI scan. But you can't use arch/romcc_io.h (the code you need) because
 | 
			
		||||
 * that has functions with the same name but different type signatures
 | 
			
		||||
 * (e.g. device_t). This needs to get fixed. We need low-level pci scans
 | 
			
		||||
 * in the C code. 
 | 
			
		||||
 */
 | 
			
		||||
static void vt8231_pci_enable(struct southbridge_via_vt8231_config *conf) 
 | 
			
		||||
{
 | 
			
		||||
	/*
 | 
			
		||||
	  unsigned long busdevfn = 0x8000;
 | 
			
		||||
	  if (conf->enable_ide) {
 | 
			
		||||
	  printk_debug("%s: enabling IDE function\n", __FUNCTION__);
 | 
			
		||||
	  }
 | 
			
		||||
	*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* PIRQ init
 | 
			
		||||
 */
 | 
			
		||||
void pci_assign_irqs(unsigned bus, unsigned slot, const unsigned char pIntAtoD[4]);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static const unsigned char southbridgeIrqs[4] = { 11, 5, 10, 12 };
 | 
			
		||||
static const unsigned char enetIrqs[4] = { 11, 5, 10, 12 };
 | 
			
		||||
static const unsigned char slotIrqs[4] = { 5, 10, 12, 11 };
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	Our IDSEL mappings are as follows
 | 
			
		||||
	PCI slot is AD31          (device 15) (00:14.0)
 | 
			
		||||
	Southbridge is AD28       (device 12) (00:11.0)
 | 
			
		||||
*/
 | 
			
		||||
static void pci_routing_fixup(void)
 | 
			
		||||
{
 | 
			
		||||
	device_t dev;
 | 
			
		||||
 | 
			
		||||
        dev = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0);
 | 
			
		||||
	printk_info("%s: dev is %p\n", __FUNCTION__, dev);
 | 
			
		||||
	if (dev) {
 | 
			
		||||
		/* initialize PCI interupts - these assignments depend
 | 
			
		||||
		   on the PCB routing of PINTA-D 
 | 
			
		||||
 | 
			
		||||
		   PINTA = IRQ11
 | 
			
		||||
		   PINTB = IRQ5
 | 
			
		||||
		   PINTC = IRQ10
 | 
			
		||||
		   PINTD = IRQ12
 | 
			
		||||
		*/
 | 
			
		||||
		pci_write_config8(dev, 0x55, 0xb0);
 | 
			
		||||
		pci_write_config8(dev, 0x56, 0xa5);
 | 
			
		||||
		pci_write_config8(dev, 0x57, 0xc0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Standard southbridge components
 | 
			
		||||
	printk_info("setting southbridge\n");
 | 
			
		||||
	pci_assign_irqs(0, 0x11, southbridgeIrqs);
 | 
			
		||||
 | 
			
		||||
	// Ethernet built into southbridge
 | 
			
		||||
	printk_info("setting ethernet\n");
 | 
			
		||||
	pci_assign_irqs(0, 0x12, enetIrqs);
 | 
			
		||||
 | 
			
		||||
	// PCI slot
 | 
			
		||||
	printk_info("setting pci slot\n");
 | 
			
		||||
	pci_assign_irqs(0, 0x14, slotIrqs);
 | 
			
		||||
	printk_info("%s: DONE\n", __FUNCTION__);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dump_south(void)
 | 
			
		||||
{
 | 
			
		||||
	device_t dev0;
 | 
			
		||||
	dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0);
 | 
			
		||||
	int i,j;
 | 
			
		||||
	
 | 
			
		||||
	for(i = 0; i < 256; i += 16) {
 | 
			
		||||
		printk_debug("0x%x: ", i);
 | 
			
		||||
		for(j = 0; j < 16; j++) {
 | 
			
		||||
			printk_debug("%02x ", pci_read_config8(dev0, i+j));
 | 
			
		||||
		}
 | 
			
		||||
		printk_debug("\n");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void vt8231_init(struct southbridge_via_vt8231_config *conf)
 | 
			
		||||
{
 | 
			
		||||
	unsigned char enables;
 | 
			
		||||
	device_t dev0;
 | 
			
		||||
	device_t dev1;
 | 
			
		||||
	device_t devpwr;
 | 
			
		||||
	
 | 
			
		||||
	// to do: use the pcibios_find function here, instead of 
 | 
			
		||||
	// hard coding the devfn. 
 | 
			
		||||
	// done - kevinh/Ispiri
 | 
			
		||||
	printk_debug("vt8231 init\n");
 | 
			
		||||
	/* Base 8231 controller */
 | 
			
		||||
	dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0);
 | 
			
		||||
	/* IDE controller */
 | 
			
		||||
	dev1 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, 0);
 | 
			
		||||
	/* Power management controller */
 | 
			
		||||
	devpwr = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4, 0);
 | 
			
		||||
 | 
			
		||||
	// enable the internal I/O decode
 | 
			
		||||
	enables = pci_read_config8(dev0, 0x6C);
 | 
			
		||||
	enables |= 0x80;
 | 
			
		||||
	pci_write_config8(dev0, 0x6C, enables);
 | 
			
		||||
	
 | 
			
		||||
	// Map 4MB of FLASH into the address space
 | 
			
		||||
	pci_write_config8(dev0, 0x41, 0x7f);
 | 
			
		||||
	
 | 
			
		||||
	// Set bit 6 of 0x40, because Award does it (IO recovery time)
 | 
			
		||||
	// IMPORTANT FIX - EISA 0x4d0 decoding must be on so that PCI 
 | 
			
		||||
	// interrupts can be properly marked as level triggered.
 | 
			
		||||
	enables = pci_read_config8(dev0, 0x40);
 | 
			
		||||
	pci_write_config8(dev0, 0x40, enables);
 | 
			
		||||
	
 | 
			
		||||
	// Set 0x42 to 0xf0 to match Award bios
 | 
			
		||||
	enables = pci_read_config8(dev0, 0x42);
 | 
			
		||||
	enables |= 0xf0;
 | 
			
		||||
	pci_write_config8(dev0, 0x42, enables);
 | 
			
		||||
	
 | 
			
		||||
	// Set bit 3 of 0x4a, to match award (dummy pci request)
 | 
			
		||||
	enables = pci_read_config8(dev0, 0x4a);
 | 
			
		||||
	enables |= 0x08;
 | 
			
		||||
	pci_write_config8(dev0, 0x4a, enables);
 | 
			
		||||
	
 | 
			
		||||
	// Set bit 3 of 0x4f to match award (use INIT# as cpu reset)
 | 
			
		||||
	enables = pci_read_config8(dev0, 0x4f);
 | 
			
		||||
	enables |= 0x08;
 | 
			
		||||
	pci_write_config8(dev0, 0x4f, enables);
 | 
			
		||||
	
 | 
			
		||||
	// Set 0x58 to 0x03 to match Award
 | 
			
		||||
	pci_write_config8(dev0, 0x58, 0x03);
 | 
			
		||||
	
 | 
			
		||||
	// enable the ethernet/RTC
 | 
			
		||||
	if(dev0) {
 | 
			
		||||
		enables = pci_read_config8(dev0, 0x51);
 | 
			
		||||
		enables |= 0x18; 
 | 
			
		||||
		pci_write_config8(dev0, 0x51, enables);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	// enable com1 and com2. 
 | 
			
		||||
	if (conf->enable_com_ports) {
 | 
			
		||||
		enables = pci_read_config8(dev0, 0x6e);
 | 
			
		||||
		
 | 
			
		||||
		/* 0x80 is enable com port b, 0x10 is to make it com2, 0x8
 | 
			
		||||
		 * is enable com port a as com1 kevinh/Ispiri - Old code
 | 
			
		||||
		 * thought 0x01 would make it com1, that was wrong enables =
 | 
			
		||||
		 * 0x80 | 0x10 | 0x8 ; pci_write_config8(dev0, 0x6e,
 | 
			
		||||
		 * enables); // note: this is also a redo of some port of
 | 
			
		||||
		 * assembly, but we want everything up.
 | 
			
		||||
		 */
 | 
			
		||||
		
 | 
			
		||||
		/* set com1 to 115 kbaud not clear how to do this yet.
 | 
			
		||||
		 * forget it; done in assembly.
 | 
			
		||||
		 */
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	// enable IDE, since Linux won't do it.
 | 
			
		||||
	// First do some more things to devfn (17,0)
 | 
			
		||||
	// note: this should already be cleared, according to the book. 
 | 
			
		||||
	enables = pci_read_config8(dev0, 0x50);
 | 
			
		||||
	printk_debug("IDE enable in reg. 50 is 0x%x\n", enables);
 | 
			
		||||
	enables &= ~8; // need manifest constant here!
 | 
			
		||||
	printk_debug("set IDE reg. 50 to 0x%x\n", enables);
 | 
			
		||||
	pci_write_config8(dev0, 0x50, enables);
 | 
			
		||||
	
 | 
			
		||||
	// set default interrupt values (IDE)
 | 
			
		||||
	enables = pci_read_config8(dev0, 0x4c);
 | 
			
		||||
	printk_debug("IRQs in reg. 4c are 0x%x\n", enables & 0xf);
 | 
			
		||||
	// clear out whatever was there. 
 | 
			
		||||
	enables &= ~0xf;
 | 
			
		||||
	enables |= 4;
 | 
			
		||||
	printk_debug("setting reg. 4c to 0x%x\n", enables);
 | 
			
		||||
	pci_write_config8(dev0, 0x4c, enables);
 | 
			
		||||
	
 | 
			
		||||
	// set up the serial port interrupts. 
 | 
			
		||||
	// com2 to 3, com1 to 4
 | 
			
		||||
	pci_write_config8(dev0, 0x46, 0x04);
 | 
			
		||||
	pci_write_config8(dev0, 0x47, 0x03);
 | 
			
		||||
	pci_write_config8(dev0, 0x6e, 0x98);
 | 
			
		||||
	//
 | 
			
		||||
	// Power management setup
 | 
			
		||||
	//
 | 
			
		||||
	// Set ACPI base address to IO 0x4000
 | 
			
		||||
	pci_write_config32(devpwr, 0x48, 0x4001);
 | 
			
		||||
	
 | 
			
		||||
	// Enable ACPI access (and setup like award)
 | 
			
		||||
	pci_write_config8(devpwr, 0x41, 0x84);
 | 
			
		||||
	
 | 
			
		||||
	// Set hardware monitor base address to IO 0x6000
 | 
			
		||||
	pci_write_config32(devpwr, 0x70, 0x6001);
 | 
			
		||||
	
 | 
			
		||||
	// Enable hardware monitor (and setup like award)
 | 
			
		||||
	pci_write_config8(devpwr, 0x74, 0x01);
 | 
			
		||||
	
 | 
			
		||||
	// set IO base address to 0x5000
 | 
			
		||||
	pci_write_config32(devpwr, 0x90, 0x5001);
 | 
			
		||||
	
 | 
			
		||||
	// Enable SMBus 
 | 
			
		||||
	pci_write_config8(devpwr, 0xd2, 0x01);
 | 
			
		||||
	
 | 
			
		||||
	//
 | 
			
		||||
	// IDE setup
 | 
			
		||||
	//
 | 
			
		||||
	if (! conf->enable_native_ide) {
 | 
			
		||||
		// Run the IDE controller in 'compatiblity mode - i.e. don't use PCI
 | 
			
		||||
		// interrupts.  Using PCI ints confuses linux for some reason.
 | 
			
		||||
		
 | 
			
		||||
		printk_info("%s: enabling compatibility IDE addresses\n", __FUNCTION__);
 | 
			
		||||
		enables = pci_read_config8(dev1, 0x42);
 | 
			
		||||
		printk_debug("enables in reg 0x42 0x%x\n", enables);
 | 
			
		||||
		enables &= ~0xc0;		// compatability mode
 | 
			
		||||
		pci_write_config8(dev1, 0x42, enables);
 | 
			
		||||
		enables = pci_read_config8(dev1, 0x42);
 | 
			
		||||
		printk_debug("enables in reg 0x42 read back as 0x%x\n", enables);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	enables = pci_read_config8(dev1, 0x40);
 | 
			
		||||
	printk_debug("enables in reg 0x40 0x%x\n", enables);
 | 
			
		||||
	enables |= 3;
 | 
			
		||||
	pci_write_config8(dev1, 0x40, enables);
 | 
			
		||||
	enables = pci_read_config8(dev1, 0x40);
 | 
			
		||||
	printk_debug("enables in reg 0x40 read back as 0x%x\n", enables);
 | 
			
		||||
	
 | 
			
		||||
	// Enable prefetch buffers
 | 
			
		||||
	enables = pci_read_config8(dev1, 0x41);
 | 
			
		||||
	enables |= 0xf0;
 | 
			
		||||
	pci_write_config8(dev1, 0x41, enables);
 | 
			
		||||
	
 | 
			
		||||
	// Lower thresholds (cause award does it)
 | 
			
		||||
	enables = pci_read_config8(dev1, 0x43);
 | 
			
		||||
	enables &= ~0x0f;
 | 
			
		||||
	enables |=  0x05;
 | 
			
		||||
	pci_write_config8(dev1, 0x43, enables);
 | 
			
		||||
	
 | 
			
		||||
	// PIO read prefetch counter (cause award does it)
 | 
			
		||||
	pci_write_config8(dev1, 0x44, 0x18);
 | 
			
		||||
	
 | 
			
		||||
	// Use memory read multiple
 | 
			
		||||
	pci_write_config8(dev1, 0x45, 0x1c);
 | 
			
		||||
	
 | 
			
		||||
	// address decoding. 
 | 
			
		||||
	// we want "flexible", i.e. 1f0-1f7 etc. or native PCI
 | 
			
		||||
	// kevinh@ispiri.com - the standard linux drivers seem ass slow when 
 | 
			
		||||
	// used in native mode - I've changed back to classic
 | 
			
		||||
	enables = pci_read_config8(dev1, 0x9);
 | 
			
		||||
	printk_debug("enables in reg 0x9 0x%x\n", enables);
 | 
			
		||||
	// by the book, set the low-order nibble to 0xa. 
 | 
			
		||||
	if (conf->enable_native_ide) {
 | 
			
		||||
		enables &= ~0xf;
 | 
			
		||||
		// cf/cg silicon needs an 'f' here. 
 | 
			
		||||
		enables |= 0xf;
 | 
			
		||||
	} else {
 | 
			
		||||
		enables &= ~0x5;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	pci_write_config8(dev1, 0x9, enables);
 | 
			
		||||
	enables = pci_read_config8(dev1, 0x9);
 | 
			
		||||
	printk_debug("enables in reg 0x9 read back as 0x%x\n", enables);
 | 
			
		||||
	
 | 
			
		||||
	// standard bios sets master bit. 
 | 
			
		||||
	enables = pci_read_config8(dev1, 0x4);
 | 
			
		||||
	printk_debug("command in reg 0x4 0x%x\n", enables);
 | 
			
		||||
	enables |= 7;
 | 
			
		||||
	
 | 
			
		||||
	// No need for stepping - kevinh@ispiri.com
 | 
			
		||||
	enables &= ~0x80;
 | 
			
		||||
	
 | 
			
		||||
	pci_write_config8(dev1, 0x4, enables);
 | 
			
		||||
	enables = pci_read_config8(dev1, 0x4);
 | 
			
		||||
	printk_debug("command in reg 0x4 reads back as 0x%x\n", enables);
 | 
			
		||||
	
 | 
			
		||||
	if (! conf->enable_native_ide) {
 | 
			
		||||
		// Use compatability mode - per award bios
 | 
			
		||||
		pci_write_config32(dev1, 0x10, 0x0);
 | 
			
		||||
		pci_write_config32(dev1, 0x14, 0x0);
 | 
			
		||||
		pci_write_config32(dev1, 0x18, 0x0);
 | 
			
		||||
		pci_write_config32(dev1, 0x1c, 0x0);
 | 
			
		||||
		
 | 
			
		||||
		// Force interrupts to use compat mode - just like Award bios
 | 
			
		||||
		pci_write_config8(dev1, 0x3d, 00);
 | 
			
		||||
		pci_write_config8(dev1, 0x3c, 0xff);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	/* set up isa bus -- i/o recovery time, rom write enable, extend-ale */
 | 
			
		||||
	pci_write_config8(dev0, 0x40, 0x54);
 | 
			
		||||
	ethernet_fixup();
 | 
			
		||||
	
 | 
			
		||||
	// Start the rtc
 | 
			
		||||
	rtc_init(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void southbridge_init(struct chip *chip, enum chip_pass pass)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	struct southbridge_via_vt8231_config *conf = 
 | 
			
		||||
		(struct southbridge_via_vt8231_config *)chip->chip_info;
 | 
			
		||||
 | 
			
		||||
	switch (pass) {
 | 
			
		||||
	case CONF_PASS_PRE_PCI:
 | 
			
		||||
		vt8231_pci_enable(conf);
 | 
			
		||||
		break;
 | 
			
		||||
		
 | 
			
		||||
	case CONF_PASS_POST_PCI:
 | 
			
		||||
		vt8231_init(conf);
 | 
			
		||||
		pci_routing_fixup();
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CONF_PASS_PRE_BOOT:
 | 
			
		||||
		dump_south();
 | 
			
		||||
		break;
 | 
			
		||||
		
 | 
			
		||||
	default:
 | 
			
		||||
		/* nothing yet */
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void enumerate(struct chip *chip)
 | 
			
		||||
{
 | 
			
		||||
	extern struct device_operations default_pci_ops_bus;
 | 
			
		||||
	chip_enumerate(chip);
 | 
			
		||||
	chip->dev->ops = &default_pci_ops_bus;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct chip_control southbridge_via_vt8231_control = {
 | 
			
		||||
	.enumerate = enumerate,
 | 
			
		||||
	.enable    = southbridge_init,
 | 
			
		||||
	.name      = "VIA vt8231"
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										195
									
								
								src/southbridge/via/vt8235/vt8235.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								src/southbridge/via/vt8235/vt8235.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,195 @@
 | 
			
		||||
/*
 | 
			
		||||
 * (C) Copyright 2000
 | 
			
		||||
 * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
 | 
			
		||||
 *
 | 
			
		||||
 * 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., 59 Temple Place, Suite 330, Boston,
 | 
			
		||||
 * MA 02111-1307 USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 /* winbond access routines and defines*/
 | 
			
		||||
 | 
			
		||||
/* from the winbond data sheet -
 | 
			
		||||
 The W83C553F SIO controller with PCI arbiter is a multi-function PCI device.
 | 
			
		||||
 Function 0 is the ISA bridge, and Function 1 is the bus master IDE controller.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*ISA bridge configuration space*/
 | 
			
		||||
 | 
			
		||||
#define W83C553F_VID		0x10AD
 | 
			
		||||
#define W83C553F_DID		0x0565
 | 
			
		||||
#define W83C553F_IDE		0x0105
 | 
			
		||||
 | 
			
		||||
/* Function 0 registers */
 | 
			
		||||
#define W83C553F_PCICONTR	0x40  /*pci control reg*/
 | 
			
		||||
#define W83C553F_SGBAR		0x41  /*scatter/gather base address reg*/
 | 
			
		||||
#define W83C553F_LBCR		0x42  /*Line Buffer Control reg*/
 | 
			
		||||
#define W83C553F_IDEIRCR	0x43  /*IDE Interrupt Routing Control  Reg*/
 | 
			
		||||
#define W83C553F_PCIIRCR	0x44  /*PCI Interrupt Routing Control Reg*/
 | 
			
		||||
#define W83C553F_BTBAR		0x46  /*BIOS Timer Base Address Register*/
 | 
			
		||||
#define W83C553F_IPADCR		0x48  /*ISA to PCI Address Decoder Control Register*/
 | 
			
		||||
#define W83C553F_IRADCR		0x49  /*ISA ROM Address Decoder Control Register*/
 | 
			
		||||
#define W83C553F_IPMHSAR	0x4a  /*ISA to PCI Memory Hole STart Address Register*/
 | 
			
		||||
#define W83C553F_IPMHSR		0x4b  /*ISA to PCI Memory Hols Size Register*/
 | 
			
		||||
#define W83C553F_CDR			0x4c  /*Clock Divisor Register*/
 | 
			
		||||
#define W83C553F_CSCR		0x4d  /*Chip Select Control Register*/
 | 
			
		||||
#define W83C553F_ATSCR		0x4e  /*AT System Control register*/
 | 
			
		||||
#define W83C553F_ATBCR		0x4f  /*AT Bus ControL Register*/
 | 
			
		||||
#define W83C553F_IRQBEE0R	0x60  /*IRQ Break Event Enable 0 Register*/
 | 
			
		||||
#define W83C553F_IRQBEE1R	0x61  /*IRQ Break Event Enable 1 Register*/
 | 
			
		||||
#define W83C553F_ABEER		0x62  /*Additional Break Event Enable Register*/
 | 
			
		||||
#define W83C553F_DMABEER	0x63  /*DMA Break Event Enable Register*/
 | 
			
		||||
 | 
			
		||||
/* Function 1 registers */
 | 
			
		||||
#define W83C553F_PIR		0x09  /*Programming Interface Register*/
 | 
			
		||||
#define W83C553F_IDECSR		0x40  /*IDE Control/Status Register*/
 | 
			
		||||
 | 
			
		||||
/* register bit definitions */
 | 
			
		||||
#define W83C553F_IPADCR_MBE512		0x1
 | 
			
		||||
#define W83C553F_IPADCR_MBE640		0x2
 | 
			
		||||
#define W83C553F_IPADCR_IPATOM4		0x10
 | 
			
		||||
#define W83C553F_IPADCR_IPATOM5		0x20
 | 
			
		||||
#define W83C553F_IPADCR_IPATOM6		0x40
 | 
			
		||||
#define W83C553F_IPADCR_IPATOM7		0x80
 | 
			
		||||
 | 
			
		||||
#define W83C553F_CSCR_UBIOSCSE		0x10
 | 
			
		||||
#define W83C553F_CSCR_BIOSWP		0x20
 | 
			
		||||
 | 
			
		||||
#define W83C553F_IDECSR_P0EN		0x01
 | 
			
		||||
#define W83C553F_IDECSR_P0F16		0x02
 | 
			
		||||
#define W83C553F_IDECSR_P1EN		0x10
 | 
			
		||||
#define W83C553F_IDECSR_P1F16		0x20
 | 
			
		||||
#define W83C553F_IDECSR_LEGIRQ		0x800
 | 
			
		||||
 | 
			
		||||
#define W83C553F_ATSCR_ISARE		0x40
 | 
			
		||||
#define W83C553F_ATSCR_FERRE		0x10
 | 
			
		||||
#define W83C553F_ATSCR_P92E		0x04
 | 
			
		||||
#define W83C553F_ATSCR_KRCEE		0x02
 | 
			
		||||
#define W83C553F_ATSCR_KGA20EE		0x01
 | 
			
		||||
 | 
			
		||||
#define W83C553F_PIR_BM			0x80
 | 
			
		||||
#define W83C553F_PIR_P1PROG		0x08
 | 
			
		||||
#define W83C553F_PIR_P1NL		0x04
 | 
			
		||||
#define W83C553F_PIR_P0PROG		0x02
 | 
			
		||||
#define W83C553F_PIR_P0NL		0x01
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Interrupt controller
 | 
			
		||||
 */
 | 
			
		||||
#define W83C553F_PIC1_ICW1	CONFIG_ISA_IO + 0x20
 | 
			
		||||
#define W83C553F_PIC1_ICW2	CONFIG_ISA_IO + 0x21
 | 
			
		||||
#define W83C553F_PIC1_ICW3	CONFIG_ISA_IO + 0x21
 | 
			
		||||
#define W83C553F_PIC1_ICW4	CONFIG_ISA_IO + 0x21
 | 
			
		||||
#define W83C553F_PIC1_OCW1	CONFIG_ISA_IO + 0x21
 | 
			
		||||
#define W83C553F_PIC1_OCW2	CONFIG_ISA_IO + 0x20
 | 
			
		||||
#define W83C553F_PIC1_OCW3	CONFIG_ISA_IO + 0x20
 | 
			
		||||
#define W83C553F_PIC1_ELC	CONFIG_ISA_IO + 0x4D0
 | 
			
		||||
#define W83C553F_PIC2_ICW1	CONFIG_ISA_IO + 0xA0
 | 
			
		||||
#define W83C553F_PIC2_ICW2	CONFIG_ISA_IO + 0xA1
 | 
			
		||||
#define W83C553F_PIC2_ICW3	CONFIG_ISA_IO + 0xA1
 | 
			
		||||
#define W83C553F_PIC2_ICW4	CONFIG_ISA_IO + 0xA1
 | 
			
		||||
#define W83C553F_PIC2_OCW1	CONFIG_ISA_IO + 0xA1
 | 
			
		||||
#define W83C553F_PIC2_OCW2	CONFIG_ISA_IO + 0xA0
 | 
			
		||||
#define W83C553F_PIC2_OCW3	CONFIG_ISA_IO + 0xA0
 | 
			
		||||
#define W83C553F_PIC2_ELC	CONFIG_ISA_IO + 0x4D1
 | 
			
		||||
 | 
			
		||||
#define W83C553F_TMR1_CMOD	CONFIG_ISA_IO + 0x43
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * DMA controller
 | 
			
		||||
 */
 | 
			
		||||
#define W83C553F_DMA1	CONFIG_ISA_IO + 0x000	/* channel 0 - 3 */
 | 
			
		||||
#define W83C553F_DMA2	CONFIG_ISA_IO + 0x0C0	/* channel 4 - 7 */
 | 
			
		||||
 | 
			
		||||
/* command/status register bit definitions */
 | 
			
		||||
 | 
			
		||||
#define W83C553F_CS_COM_DACKAL	(1<<7)	/* DACK# assert level */
 | 
			
		||||
#define W83C553F_CS_COM_DREQSAL	(1<<6)	/* DREQ sense assert level */
 | 
			
		||||
#define W83C553F_CS_COM_GAP	(1<<4)	/* group arbitration priority */
 | 
			
		||||
#define W83C553F_CS_COM_CGE	(1<<2)	/* channel group enable */
 | 
			
		||||
 | 
			
		||||
#define W83C553F_CS_STAT_CH0REQ	(1<<4)	/* channel 0 (4) DREQ status */
 | 
			
		||||
#define W83C553F_CS_STAT_CH1REQ	(1<<5)	/* channel 1 (5) DREQ status */
 | 
			
		||||
#define W83C553F_CS_STAT_CH2REQ	(1<<6)	/* channel 2 (6) DREQ status */
 | 
			
		||||
#define W83C553F_CS_STAT_CH3REQ	(1<<7)	/* channel 3 (7) DREQ status */
 | 
			
		||||
 | 
			
		||||
#define W83C553F_CS_STAT_CH0TC	(1<<0)	/* channel 0 (4) TC status */
 | 
			
		||||
#define W83C553F_CS_STAT_CH1TC	(1<<1)	/* channel 1 (5) TC status */
 | 
			
		||||
#define W83C553F_CS_STAT_CH2TC	(1<<2)	/* channel 2 (6) TC status */
 | 
			
		||||
#define W83C553F_CS_STAT_CH3TC	(1<<3)	/* channel 3 (7) TC status */
 | 
			
		||||
 | 
			
		||||
/* mode register bit definitions */
 | 
			
		||||
 | 
			
		||||
#define W83C553F_MODE_TM_DEMAND	(0<<6)	/* transfer mode - demand */
 | 
			
		||||
#define W83C553F_MODE_TM_SINGLE	(1<<6)	/* transfer mode - single */
 | 
			
		||||
#define W83C553F_MODE_TM_BLOCK	(2<<6)	/* transfer mode - block */
 | 
			
		||||
#define W83C553F_MODE_TM_CASCADE	(3<<6)	/* transfer mode - cascade */
 | 
			
		||||
#define W83C553F_MODE_ADDRDEC	(1<<5)	/* address increment/decrement select */
 | 
			
		||||
#define W83C553F_MODE_AUTOINIT	(1<<4)	/* autoinitialize enable */
 | 
			
		||||
#define W83C553F_MODE_TT_VERIFY	(0<<2)	/* transfer type - verify */
 | 
			
		||||
#define W83C553F_MODE_TT_WRITE	(1<<2)	/* transfer type - write */
 | 
			
		||||
#define W83C553F_MODE_TT_READ	(2<<2)	/* transfer type - read */
 | 
			
		||||
#define W83C553F_MODE_TT_ILLEGAL	(3<<2)	/* transfer type - illegal */
 | 
			
		||||
#define W83C553F_MODE_CH0SEL	(0<<0)	/* channel 0 (4) select */
 | 
			
		||||
#define W83C553F_MODE_CH1SEL	(1<<0)	/* channel 1 (5) select */
 | 
			
		||||
#define W83C553F_MODE_CH2SEL	(2<<0)	/* channel 2 (6) select */
 | 
			
		||||
#define W83C553F_MODE_CH3SEL	(3<<0)	/* channel 3 (7) select */
 | 
			
		||||
 | 
			
		||||
/* request register bit definitions */
 | 
			
		||||
 | 
			
		||||
#define W83C553F_REQ_CHSERREQ	(1<<2)	/* channel service request */
 | 
			
		||||
#define W83C553F_REQ_CH0SEL	(0<<0)	/* channel 0 (4) select */
 | 
			
		||||
#define W83C553F_REQ_CH1SEL	(1<<0)	/* channel 1 (5) select */
 | 
			
		||||
#define W83C553F_REQ_CH2SEL	(2<<0)	/* channel 2 (6) select */
 | 
			
		||||
#define W83C553F_REQ_CH3SEL	(3<<0)	/* channel 3 (7) select */
 | 
			
		||||
 | 
			
		||||
/* write single mask bit register bit definitions */
 | 
			
		||||
 | 
			
		||||
#define W83C553F_WSMB_CHMASKSEL	(1<<2)	/* channel mask select */
 | 
			
		||||
#define W83C553F_WSMB_CH0SEL	(0<<0)	/* channel 0 (4) select */
 | 
			
		||||
#define W83C553F_WSMB_CH1SEL	(1<<0)	/* channel 1 (5) select */
 | 
			
		||||
#define W83C553F_WSMB_CH2SEL	(2<<0)	/* channel 2 (6) select */
 | 
			
		||||
#define W83C553F_WSMB_CH3SEL	(3<<0)	/* channel 3 (7) select */
 | 
			
		||||
 | 
			
		||||
/* read/write all mask bits register bit definitions */
 | 
			
		||||
 | 
			
		||||
#define W83C553F_RWAMB_CH0MASK	(1<<0)	/* channel 0 (4) mask */
 | 
			
		||||
#define W83C553F_RWAMB_CH1MASK	(1<<1)	/* channel 1 (5) mask */
 | 
			
		||||
#define W83C553F_RWAMB_CH2MASK	(1<<2)	/* channel 2 (6) mask */
 | 
			
		||||
#define W83C553F_RWAMB_CH3MASK	(1<<3)	/* channel 3 (7) mask */
 | 
			
		||||
 | 
			
		||||
/* typedefs */
 | 
			
		||||
 | 
			
		||||
#define W83C553F_DMA1_CS		0x8
 | 
			
		||||
#define W83C553F_DMA1_WR		0x9
 | 
			
		||||
#define W83C553F_DMA1_WSMB		0xA
 | 
			
		||||
#define W83C553F_DMA1_WM		0xB
 | 
			
		||||
#define W83C553F_DMA1_CBP		0xC
 | 
			
		||||
#define W83C553F_DMA1_MC		0xD
 | 
			
		||||
#define W83C553F_DMA1_CM		0xE
 | 
			
		||||
#define W83C553F_DMA1_RWAMB		0xF
 | 
			
		||||
 | 
			
		||||
#define W83C553F_DMA2_CS		0xD0
 | 
			
		||||
#define W83C553F_DMA2_WR		0xD2
 | 
			
		||||
#define W83C553F_DMA2_WSMB		0xD4
 | 
			
		||||
#define W83C553F_DMA2_WM		0xD6
 | 
			
		||||
#define W83C553F_DMA2_CBP		0xD8
 | 
			
		||||
#define W83C553F_DMA2_MC		0xDA
 | 
			
		||||
#define W83C553F_DMA2_CM		0xDC
 | 
			
		||||
#define W83C553F_DMA2_RWAMB		0xDE
 | 
			
		||||
 | 
			
		||||
void initialise_w83c553f(void);
 | 
			
		||||
							
								
								
									
										75
									
								
								src/southbridge/via/vt8235/vt8235_early_serial.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								src/southbridge/via/vt8235/vt8235_early_serial.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Enable the serial evices on the VIA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* The base address is 0x15c, 0x2e, depending on config bytes */
 | 
			
		||||
 | 
			
		||||
#define SIO_BASE 0x3f0
 | 
			
		||||
#define SIO_DATA  SIO_BASE+1
 | 
			
		||||
 | 
			
		||||
static void vt8231_writesuper(uint8_t reg, uint8_t val) 
 | 
			
		||||
{
 | 
			
		||||
	outb(reg, SIO_BASE);
 | 
			
		||||
	outb(val, SIO_DATA);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void vt8231_writesiobyte(uint16_t reg, uint8_t val) 
 | 
			
		||||
{
 | 
			
		||||
	outb(val, reg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void vt8231_writesioword(uint16_t reg, uint16_t val) 
 | 
			
		||||
{
 | 
			
		||||
	outw(val, reg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* regs we use: 85, and the southbridge devfn is defined by the
 | 
			
		||||
   mainboard
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static void enable_vt8231_serial(void) 
 | 
			
		||||
{
 | 
			
		||||
	unsigned long x;
 | 
			
		||||
	uint8_t c;
 | 
			
		||||
	device_t dev;
 | 
			
		||||
	outb(6, 0x80);
 | 
			
		||||
	dev = pci_locate_device(PCI_ID(0x1106,0x8231), 0);
 | 
			
		||||
	
 | 
			
		||||
	if (dev == PCI_DEV_INVALID) {
 | 
			
		||||
		outb(7, 0x80);
 | 
			
		||||
		die("Serial controller not found\r\n");
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* first, you have to enable the superio and superio config. 
 | 
			
		||||
	   put a 6 reg 80
 | 
			
		||||
	*/
 | 
			
		||||
	c = pci_read_config8(dev, 0x50);
 | 
			
		||||
	c |= 6;
 | 
			
		||||
	pci_write_config8(dev, 0x50, c);
 | 
			
		||||
	outb(2, 0x80);
 | 
			
		||||
	// now go ahead and set up com1. 
 | 
			
		||||
	// set address
 | 
			
		||||
	vt8231_writesuper(0xf4, 0xfe);
 | 
			
		||||
	// enable serial out
 | 
			
		||||
	vt8231_writesuper(0xf2, 7);
 | 
			
		||||
	// That's it for the sio stuff.
 | 
			
		||||
	//	movl	$SUPERIOCONFIG, %eax
 | 
			
		||||
	//	movb	$9, %dl
 | 
			
		||||
	//	PCI_WRITE_CONFIG_BYTE
 | 
			
		||||
	// set up reg to set baud rate.
 | 
			
		||||
	vt8231_writesiobyte(0x3fb, 0x80);
 | 
			
		||||
	// Set 115 kb
 | 
			
		||||
	vt8231_writesioword(0x3f8, 1);
 | 
			
		||||
	// Set 9.6 kb
 | 
			
		||||
	//	WRITESIOWORD(0x3f8, 12)
 | 
			
		||||
	// now set no parity, one stop, 8 bits
 | 
			
		||||
	vt8231_writesiobyte(0x3fb, 3);
 | 
			
		||||
	// now turn on RTS, DRT
 | 
			
		||||
	vt8231_writesiobyte(0x3fc, 3);
 | 
			
		||||
	// Enable interrupts
 | 
			
		||||
	vt8231_writesiobyte(0x3f9, 0xf);
 | 
			
		||||
	// should be done. Dump a char for fun.
 | 
			
		||||
	vt8231_writesiobyte(0x3f8, 48);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										231
									
								
								src/southbridge/via/vt8235/vt8235_early_smbus.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								src/southbridge/via/vt8235/vt8235_early_smbus.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,231 @@
 | 
			
		||||
#define SMBUS_IO_BASE 0x5000
 | 
			
		||||
 | 
			
		||||
#define SMBHSTSTAT 0x0
 | 
			
		||||
#define SMBSLVSTAT 0x1
 | 
			
		||||
#define SMBHSTCTL  0x2
 | 
			
		||||
#define SMBHSTCMD  0x3
 | 
			
		||||
#define SMBXMITADD 0x4
 | 
			
		||||
#define SMBHSTDAT0 0x5
 | 
			
		||||
#define SMBHSTDAT1 0x6
 | 
			
		||||
#define SMBBLKDAT  0x7
 | 
			
		||||
#define SMBSLVCTL  0x8
 | 
			
		||||
#define SMBTRNSADD 0x9
 | 
			
		||||
#define SMBSLVDATA 0xa
 | 
			
		||||
#define SMLINK_PIN_CTL 0xe
 | 
			
		||||
#define SMBUS_PIN_CTL  0xf 
 | 
			
		||||
 | 
			
		||||
/* Define register settings */
 | 
			
		||||
#define HOST_RESET 0xff
 | 
			
		||||
#define DIMM_BASE 0xa0        // 1010000 is base for DIMM in SMBus
 | 
			
		||||
#define READ_CMD  0x01        // 1 in the 0 bit of SMBHSTADD states to READ
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define SMBUS_TIMEOUT (100*1000*10)
 | 
			
		||||
 | 
			
		||||
static void enable_smbus(void)
 | 
			
		||||
{
 | 
			
		||||
	device_t dev;
 | 
			
		||||
	unsigned char c;
 | 
			
		||||
	/* Power management controller */
 | 
			
		||||
	dev = pci_locate_device(PCI_ID(0x1106,0x8235), 0);
 | 
			
		||||
	
 | 
			
		||||
	if (dev == PCI_DEV_INVALID) {
 | 
			
		||||
		die("SMBUS controller not found\r\n");
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// set IO base address to SMBUS_IO_BASE
 | 
			
		||||
	pci_write_config32(dev, 0x90, SMBUS_IO_BASE|1);
 | 
			
		||||
	
 | 
			
		||||
	// Enable SMBus 
 | 
			
		||||
	c = pci_read_config8(dev, 0xd2);
 | 
			
		||||
	c |= 5;
 | 
			
		||||
	pci_write_config8(dev, 0xd2, c);
 | 
			
		||||
	
 | 
			
		||||
	/* make it work for I/O ...
 | 
			
		||||
	 */
 | 
			
		||||
	dev = pci_locate_device(PCI_ID(0x1106,0x8231), 0);
 | 
			
		||||
	c = pci_read_config8(dev, 4);
 | 
			
		||||
	c |= 1;
 | 
			
		||||
	pci_write_config8(dev, 4, c);
 | 
			
		||||
	print_debug_hex8(c);
 | 
			
		||||
	print_debug(" is the comm register\r\n");
 | 
			
		||||
	
 | 
			
		||||
	print_debug("SMBus controller enabled\r\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static inline void smbus_delay(void)
 | 
			
		||||
{
 | 
			
		||||
	outb(0x80, 0x80);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int smbus_wait_until_ready(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned char c;
 | 
			
		||||
	unsigned long loops;
 | 
			
		||||
	loops = SMBUS_TIMEOUT;
 | 
			
		||||
	do {
 | 
			
		||||
		unsigned char val;
 | 
			
		||||
		smbus_delay();
 | 
			
		||||
		c = inb(SMBUS_IO_BASE + SMBHSTSTAT);
 | 
			
		||||
		while((c & 1) == 1) {
 | 
			
		||||
			print_debug("c is ");
 | 
			
		||||
			print_debug_hex8(c);
 | 
			
		||||
			print_debug("\r\n");
 | 
			
		||||
			c = inb(SMBUS_IO_BASE + SMBHSTSTAT);
 | 
			
		||||
			/* nop */ 
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	} while(--loops);
 | 
			
		||||
	return loops?0:-1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void smbus_reset(void)
 | 
			
		||||
{
 | 
			
		||||
	outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT);
 | 
			
		||||
	outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT);
 | 
			
		||||
	outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT);
 | 
			
		||||
	outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT);
 | 
			
		||||
	
 | 
			
		||||
	smbus_wait_until_ready();
 | 
			
		||||
	print_debug("After reset status ");
 | 
			
		||||
	print_debug_hex8( inb(SMBUS_IO_BASE + SMBHSTSTAT));
 | 
			
		||||
	print_debug("\r\n");
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int smbus_wait_until_done(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long loops;
 | 
			
		||||
	unsigned char byte;
 | 
			
		||||
	loops = SMBUS_TIMEOUT;
 | 
			
		||||
	do {
 | 
			
		||||
		unsigned char val;
 | 
			
		||||
		smbus_delay();
 | 
			
		||||
		
 | 
			
		||||
		byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
 | 
			
		||||
		if (byte & 1)
 | 
			
		||||
			break;
 | 
			
		||||
		
 | 
			
		||||
	} while(--loops);
 | 
			
		||||
	return loops?0:-1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void smbus_print_error(unsigned char host_status_register)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	print_err("smbus_error: ");
 | 
			
		||||
	print_err_hex8(host_status_register);
 | 
			
		||||
	print_err("\r\n");
 | 
			
		||||
	if (host_status_register & (1 << 4)) {
 | 
			
		||||
		print_err("Interrup/SMI# was Failed Bus Transaction\r\n");
 | 
			
		||||
	}
 | 
			
		||||
	if (host_status_register & (1 << 3)) {
 | 
			
		||||
		print_err("Bus Error\r\n");
 | 
			
		||||
	}
 | 
			
		||||
	if (host_status_register & (1 << 2)) {
 | 
			
		||||
		print_err("Device Error\r\n");
 | 
			
		||||
	}
 | 
			
		||||
	if (host_status_register & (1 << 1)) {
 | 
			
		||||
		print_err("Interrupt/SMI# was Successful Completion\r\n");
 | 
			
		||||
	}
 | 
			
		||||
	if (host_status_register & (1 << 0)) {
 | 
			
		||||
		print_err("Host Busy\r\n");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* SMBus routines borrowed from VIA's Trident Driver */
 | 
			
		||||
/* this works, so I am not going to touch it for now -- rgm */
 | 
			
		||||
static unsigned char smbus_read_byte(unsigned char devAdr, 
 | 
			
		||||
				unsigned char bIndex) 
 | 
			
		||||
{
 | 
			
		||||
	unsigned short i;
 | 
			
		||||
	unsigned char  bData;
 | 
			
		||||
	unsigned char  sts = 0;
 | 
			
		||||
	
 | 
			
		||||
	/* clear host status */
 | 
			
		||||
	outb(0xff, SMBUS_IO_BASE);
 | 
			
		||||
	
 | 
			
		||||
	/* check SMBUS ready */
 | 
			
		||||
	for ( i = 0; i < 0xFFFF; i++ )
 | 
			
		||||
		if ( (inb(SMBUS_IO_BASE) & 0x01) == 0 )
 | 
			
		||||
			break;
 | 
			
		||||
	
 | 
			
		||||
	/* set host command */
 | 
			
		||||
	outb(bIndex, SMBUS_IO_BASE+3);
 | 
			
		||||
	
 | 
			
		||||
	/* set slave address */
 | 
			
		||||
	outb(devAdr | 0x01, SMBUS_IO_BASE+4);
 | 
			
		||||
	
 | 
			
		||||
	/* start */
 | 
			
		||||
	outb(0x48, SMBUS_IO_BASE+2);
 | 
			
		||||
	
 | 
			
		||||
	/* SMBUS Wait Ready */
 | 
			
		||||
	for ( i = 0; i < 0xFFFF; i++ )
 | 
			
		||||
		if ( ((sts = inb(SMBUS_IO_BASE)) & 0x01) == 0 )
 | 
			
		||||
			break;
 | 
			
		||||
	if ((sts & ~3) != 0) {
 | 
			
		||||
		smbus_print_error(sts);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	bData=inb(SMBUS_IO_BASE+5);
 | 
			
		||||
	
 | 
			
		||||
	return bData;
 | 
			
		||||
	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* for reference, here is the fancier version which we will use at some 
 | 
			
		||||
 * point
 | 
			
		||||
 */
 | 
			
		||||
# if 0
 | 
			
		||||
int smbus_read_byte(unsigned device, unsigned address, unsigned char *result)
 | 
			
		||||
{
 | 
			
		||||
	unsigned char host_status_register;
 | 
			
		||||
	unsigned char byte;
 | 
			
		||||
	
 | 
			
		||||
	reset();
 | 
			
		||||
	
 | 
			
		||||
	smbus_wait_until_ready();
 | 
			
		||||
	
 | 
			
		||||
	/* setup transaction */
 | 
			
		||||
	/* disable interrupts */
 | 
			
		||||
	outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
 | 
			
		||||
	/* set the device I'm talking too */
 | 
			
		||||
	outb(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBXMITADD);
 | 
			
		||||
	/* set the command/address... */
 | 
			
		||||
	outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
 | 
			
		||||
	/* set up for a byte data read */
 | 
			
		||||
	outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xE3) | (0x2 << 2),
 | 
			
		||||
		SMBUS_IO_BASE + SMBHSTCTL);
 | 
			
		||||
	
 | 
			
		||||
	/* clear any lingering errors, so the transaction will run */
 | 
			
		||||
	outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
 | 
			
		||||
	
 | 
			
		||||
	/* clear the data byte...*/
 | 
			
		||||
	outb(0, SMBUS_IO_BASE + SMBHSTDAT0);
 | 
			
		||||
	
 | 
			
		||||
	/* start the command */
 | 
			
		||||
	outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40),
 | 
			
		||||
		SMBUS_IO_BASE + SMBHSTCTL);
 | 
			
		||||
	
 | 
			
		||||
	/* poll for transaction completion */
 | 
			
		||||
	smbus_wait_until_done();
 | 
			
		||||
	
 | 
			
		||||
	host_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT);
 | 
			
		||||
	
 | 
			
		||||
	/* Ignore the In Use Status... */
 | 
			
		||||
	host_status_register &= ~(1 << 6);
 | 
			
		||||
	
 | 
			
		||||
	/* read results of transaction */
 | 
			
		||||
	byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);
 | 
			
		||||
	smbus_print_error(byte);
 | 
			
		||||
	
 | 
			
		||||
	*result = byte;
 | 
			
		||||
	return host_status_register != 0x02;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user