diff options
Diffstat (limited to 'src/southbridge/via/vt8235')
-rw-r--r-- | src/southbridge/via/vt8235/vt8235.c | 346 | ||||
-rw-r--r-- | src/southbridge/via/vt8235/vt8235_early_smbus.c | 46 |
2 files changed, 265 insertions, 127 deletions
diff --git a/src/southbridge/via/vt8235/vt8235.c b/src/southbridge/via/vt8235/vt8235.c index ca5ab32ac3..fc4c6a6186 100644 --- a/src/southbridge/via/vt8235/vt8235.c +++ b/src/southbridge/via/vt8235/vt8235.c @@ -9,6 +9,8 @@ #include "vt8235.h" #include "chip.h" +void rtc_init(int i); + void pc_keyboard_init(void); void hard_reset(void) @@ -23,67 +25,78 @@ static void usb_on(int enable) /* Base 8235 controller */ device_t dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, 0); /* USB controller 1 */ - device_t dev2 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, 0); + device_t dev1 = 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); + device_t dev2 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, dev1); + /* USB controller 2 */ + device_t dev3 = dev_find_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_2, dev2); + + if(enable){ + if(dev0) { + regval = pci_read_config8(dev0, 0x50); + regval &= ~(0x36); + pci_write_config8(dev0, 0x50, regval); } - } - - 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); + + /* enable USB1 */ + if(dev1) { + pci_write_config8(dev1, 0x04, 0x07); + } + + /* enable USB2 */ + if(dev2) { + pci_write_config8(dev2, 0x04, 0x07); + } + + /* enable USB3 */ + if(dev3) { + pci_write_config8(dev3, 0x04, 0x07); + } + + }else{ + if(dev0) { + regval = pci_read_config8(dev0, 0x50); + regval |= 0x36; + pci_write_config8(dev0, 0x50, regval); + } + + /* disable USB1 */ + if(dev1) { + pci_write_config8(dev1, 0x3c, 0x00); + pci_write_config8(dev1, 0x04, 0x00); + } + + /* disable USB2 */ + if(dev2) { + pci_write_config8(dev2, 0x3c, 0x00); + pci_write_config8(dev2, 0x04, 0x00); + } + + /* disable USB3 */ + if(dev3) { + 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 8235 controller */ - device_t dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, 0); - - /* kevinh/Ispiri - update entire function to use - new pci_write_config8 */ + device_t dev0 = dev_find_device(PCI_VENDOR_ID_VIA, \ + PCI_DEVICE_ID_VIA_8235, 0); if (dev0) { regval = pci_read_config8(dev0, 0x51); - regval |= 0x0f; +// regval |= 0x0f; + /* !!!FIX let's try this */ + regval |= 0x1d; pci_write_config8(dev0, 0x51, regval); } - init_pc_keyboard(0x60, 0x64, 0); + pc_keyboard_init(); } static void nvram_on(void) @@ -152,16 +165,43 @@ static void vt8235_pci_enable(struct southbridge_via_vt8235_config *conf) */ void pci_assign_irqs(unsigned bus, unsigned slot, const unsigned char pIntAtoD[4]); +/* taken some liberties - changed irq structures to pins numbers so that it is easier to + * change PCI irq assignments without having to change each PCI function individually + */ -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 }; - +/* pciIrqs contains the irqs assigned for PCI pins A-D */ +/* setting will depend on motherboard as irqs can be quite scarce */ +/* e.g on EPIA-MII, 16 bit CF card wants a dedicated IRQ. A 16 bit card in pcmcia socket */ +/* may want another - for now only claim 3 interupts for PCI, leaving at least one spare */ +/* for CF. */ +/* On EPIA-M one could allocated all four irqs to different numbers since there are no cardbus */ +/* devices */ + + +static const unsigned char pciIrqs[4] = { 5 , 9 , 9, 10 }; + +static const unsigned char usbPins[4] = { 'A','B','C','D'}; +static const unsigned char enetPins[4] = { 'A','B','C','D'}; +static const unsigned char slotPins[4] = { 'B','C','D','A'}; +static const unsigned char firewirePins[4] = { 'B','C','D','A'}; +static const unsigned char vt8235Pins[4] = { 'A','B','C','D'}; +static const unsigned char vgaPins[4] = { 'A','B','C','D'}; +static const unsigned char cbPins[4] = { 'A','B','C','D'}; +static const unsigned char riserPins[4] = { 'A','B','C','D'}; /* Our IDSEL mappings are as follows PCI slot is AD31 (device 15) (00:14.0) Southbridge is AD28 (device 12) (00:11.0) */ +static unsigned char *pin_to_irq(const unsigned char *pin) +{ + static unsigned char Irqs[4]; + int i; + for (i = 0 ; i < 4 ; i++) + Irqs[i] = pciIrqs[ pin[i] - 'A' ]; + + return Irqs; +} static void pci_routing_fixup(void) { device_t dev; @@ -177,23 +217,47 @@ static void pci_routing_fixup(void) PINTC = IRQ10 PINTD = IRQ12 */ - pci_write_config8(dev, 0x55, 0xb0); - pci_write_config8(dev, 0x56, 0xa5); - pci_write_config8(dev, 0x57, 0xc0); + pci_write_config8(dev, 0x55, pciIrqs[0] << 4); + pci_write_config8(dev, 0x56, pciIrqs[1] | (pciIrqs[2] << 4) ); + pci_write_config8(dev, 0x57, pciIrqs[3] << 4); + } - // Standard southbridge components - printk_info("setting southbridge\n"); - pci_assign_irqs(0, 0x11, southbridgeIrqs); + + + // firewire built into southbridge + printk_info("setting firewire\n"); + pci_assign_irqs(0, 0x0d, pin_to_irq(firewirePins) ); + + // Standard usb components + printk_info("setting usb\n"); + pci_assign_irqs(0, 0x10, pin_to_irq(usbPins) ); + + // VT8235 + sound hardware + printk_info("setting vt8235\n"); + pci_assign_irqs(0, 0x11, pin_to_irq(vt8235Pins) ); // Ethernet built into southbridge printk_info("setting ethernet\n"); - pci_assign_irqs(0, 0x12, enetIrqs); + pci_assign_irqs(0, 0x12, pin_to_irq(enetPins) ); + + // VGA + printk_info("setting vga\n"); + pci_assign_irqs(1, 0x00, pin_to_irq(vgaPins) ); // PCI slot printk_info("setting pci slot\n"); - pci_assign_irqs(0, 0x14, slotIrqs); - printk_info("%s: DONE\n", __FUNCTION__); + pci_assign_irqs(0, 0x14, pin_to_irq(slotPins) ); + + // Cardbus slot + printk_info("setting cardbus slot\n"); + pci_assign_irqs(0, 0x0a, pin_to_irq(cbPins) ); + + // Via 2 slot riser card 2nd slot + printk_info("setting riser slot\n"); + pci_assign_irqs(0, 0x13, pin_to_irq(riserPins) ); + + } @@ -213,13 +277,76 @@ dump_south(void) } } +void set_led(void) +{ + + // set power led to steady now that lxbios has virtually done its job + device_t dev0; + dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235,0); + + pci_write_config8(dev0,0x94,0xb0); + +} + +/* set up the power management capabilities directly into ACPI mode */ +/* this avoids having to handle any System Management Interrupts (SMI's) which I can't */ +/* figure out how to do !!!! */ + +void setup_pm(device_t dev0) +{ + + // Set gen config 0 + pci_write_config8(dev0,0x80,0x20); + + // Set ACPI base address to IO 0x4000 + pci_write_config16(dev0, 0x88, 0x0401); + + // set ACPI irq to 5 + pci_write_config8(dev0,0x82,0x55); + + // primary interupt channel + pci_write_config16(dev0,0x84,0x30f2); + + // throttle / stop clock control + pci_write_config8(dev0,0x8d,0x18); + + pci_write_config8(dev0,0x93,0x88); + //pci_write_config8(dev0,0x94,0xb0); + pci_write_config8(dev0,0x95,0xc0); + pci_write_config8(dev0,0x98,0); + pci_write_config8(dev0,0x99,0xea); + pci_write_config8(dev0,0xe4,0x14); + pci_write_config8(dev0,0xe5,0x08); + + + // Enable ACPI access (and setup like award) + pci_write_config8(dev0, 0x81, 0x84); + + outw(0xffff,0x400); + outw(0xffff,0x420); + outw(0xffff,0x428); + outl(0xffffffff,0x430); + + outw(0x0,0x424); + outw(0x0,0x42a); + outw(0x1,0x42c); + outl(0x0,0x434); + outl(0x01,0x438); + outb(0x0,0x442); + outl(0xffff7fff,0x448); + outw(0x001,0x404); + + +} + static void vt8235_init(struct southbridge_via_vt8235_config *conf) { unsigned char enables; device_t dev0; device_t dev1; - device_t devpwr; - + //device_t devpwr; + //int i; + // to do: use the pcibios_find function here, instead of // hard coding the devfn. // done - kevinh/Ispiri @@ -243,6 +370,7 @@ static void vt8235_init(struct southbridge_via_vt8235_config *conf) // 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); + enables |= 0x45; pci_write_config8(dev0, 0x40, enables); // Set 0x42 to 0xf0 to match Award bios @@ -250,6 +378,17 @@ static void vt8235_init(struct southbridge_via_vt8235_config *conf) enables |= 0xf0; pci_write_config8(dev0, 0x42, enables); + + /* Set 0x58 to 0x03 to match Award */ + pci_write_config8(dev0, 0x58, 0x03); + + /* 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 bit 3 of 0x4a, to match award (dummy pci request) enables = pci_read_config8(dev0, 0x4a); enables |= 0x08; @@ -271,68 +410,24 @@ static void vt8235_init(struct southbridge_via_vt8235_config *conf) } - // 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 serial irq */ + pci_write_config8(dev0,0x52,0x9); + + /* dma */ + pci_write_config8(dev0, 0x53, 0x00); + + /* 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); + - } - // 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); + setup_pm(dev0); // + // // IDE setup // if (! conf->enable_native_ide) { @@ -422,6 +517,8 @@ static void vt8235_init(struct southbridge_via_vt8235_config *conf) // Start the rtc rtc_init(0); + + } static void southbridge_init(struct chip *chip, enum chip_pass pass) @@ -436,12 +533,23 @@ static void southbridge_init(struct chip *chip, enum chip_pass pass) break; case CONF_PASS_POST_PCI: + /* initialise the PIC - particularly so that VGA bios init code + doesn't get nasty unknown interupt vectors when it tries to establish + its interrupts. */ + setup_i8259(); vt8235_init(conf); pci_routing_fixup(); + usb_on(1); + keyboard_on(); + vga_fixup(); + + + break; case CONF_PASS_PRE_BOOT: dump_south(); + set_led(); break; default: diff --git a/src/southbridge/via/vt8235/vt8235_early_smbus.c b/src/southbridge/via/vt8235/vt8235_early_smbus.c index 79b73df01e..26beea933b 100644 --- a/src/southbridge/via/vt8235/vt8235_early_smbus.c +++ b/src/southbridge/via/vt8235/vt8235_early_smbus.c @@ -29,35 +29,64 @@ static void enable_smbus(void) { device_t dev; unsigned char c; + int i; /* Power management controller */ - dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235), 0); + dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235), 0); if (dev == PCI_DEV_INVALID) { die("SMBUS controller not found\r\n"); - } - + } + pci_write_config8(dev, 0xd2, (0x4 << 1 )); + // set IO base address to SMBUS_IO_BASE - pci_write_config32(dev, 0x90, SMBUS_IO_BASE|1); + pci_write_config16(dev, 0xd0, SMBUS_IO_BASE); // Enable SMBus pci_write_config8(dev, 0xd2, (0x4 << 1)|1); + // Enable RTC + pci_write_config8(dev,0x51,0x04); + /* make it work for I/O ... */ - pci_write_config8(dev, 4, 1); + pci_write_config16(dev, 4, 1); + + + /* tell the world we're alive - make power led flash during bios execution */ + pci_write_config8(dev,0x94,0xb2); + + + /* FIX for half baud rate problem */ + /* let clocks and the like settle */ + /* as yet arbitrary count - 1000 is too little 5000 works */ + for(i = 0 ; i < 5000 ; i++) + outb(0x80,0x80); + + /* southbridge doesn't seem to like to do much untill after this delay, so set up + * the flashing power LED again */ + pci_write_config8(dev,0x94,0xb2); /* The VT1211 serial port needs 48 mhz clock, on power up it is getting only 24 mhz, there is some mysterious device on the smbus that can fix this...this code below does it. */ outb(0xff, SMBUS_IO_BASE+SMBHSTSTAT); + outb(0xff, SMBUS_IO_BASE+SMBHSTSTAT); + outb(0xff, SMBUS_IO_BASE+SMBHSTSTAT); + outb(0xff, SMBUS_IO_BASE+SMBHSTSTAT); + for( ;;) { + c = inb(SMBUS_IO_BASE+SMBHSTSTAT); + if ((c & 1) == 0) + break; + } outb(0x7f, SMBUS_IO_BASE+SMBHSTDAT0); outb(0x83, SMBUS_IO_BASE+SMBHSTCMD); - outb(CLOCK_SLAVE_ADDRESS<<1, SMBUS_IO_BASE+SMBXMITADD); + outb(CLOCK_SLAVE_ADDRESS<<1 , SMBUS_IO_BASE+SMBXMITADD); outb(8 | I2C_TRANS_CMD, SMBUS_IO_BASE+SMBHSTCTL); + for (;;) { c = inb(SMBUS_IO_BASE+SMBHSTSTAT); - if (c & 1 == 0) + if ((c & 1) == 0) break; } } @@ -173,8 +202,9 @@ static unsigned char smbus_read_byte(unsigned char devAdr, /* SMBUS Wait Ready */ for ( i = 0; i < 0xFFFF; i++ ) - if ( ((sts = inb(SMBUS_IO_BASE)) & 0x01) == 0 ) + if ( ((sts = (inb(SMBUS_IO_BASE) & 0x1f)) & 0x01) == 0 ) break; + if ((sts & ~3) != 0) { smbus_print_error(sts); return 0; |