diff --git a/src/mainboard/via/epia-n/irq_links.asl b/src/mainboard/via/epia-n/irq_links.asl new file mode 100644 index 0000000000..fc93e760b5 --- /dev/null +++ b/src/mainboard/via/epia-n/irq_links.asl @@ -0,0 +1,571 @@ +/* + * Minimalist ACPI DSDT table for EPIA-N / NL + * Basic description of PCI Interrupt Assignments. + * This is expected to be included into _SB.PCI0 namespace + * (C) Copyright 2009 Jon Harrison + * + */ + + /* PCI PnP Routing Links */ + + /* Define how interrupt Link A is plumbed in */ + Device (LNKA) + { + Name (_HID, EisaId ("PNP0C0F")) + Name (_UID, 0x01) + /* Status - always return ready */ + Method (_STA, 0, NotSerialized) + { + /* See If Coreboot has allocated INTA# */ + And (PIRA, 0xF0, Local0) + If (LEqual (Local0, 0x00)) + { + Return (0x09) + } + Else + { + Return (0x0B) + } + } + + Method (_PRS, 0, NotSerialized) + { + Name (BUFA, ResourceTemplate () + { + IRQ (Level, ActiveLow, Shared, ) + {3,4,6,7,10,11,12} + }) + Return (BUFA) + } + + Method (_CRS, 0, NotSerialized) + { + Name (BUFA, ResourceTemplate () + { + IRQ (Level, ActiveLow, Shared, _Y07) + {} + }) + /* Read the Binary Encoded Field and Map this */ + /* onto the bitwise _INT field in the IRQ descriptor */ + /* See ACPI Spec for detail of _IRQ Descriptor */ + CreateByteField (BUFA, \_SB.PCI0.LNKA._CRS._Y07._INT, IRA1) + CreateByteField (BUFA, 0x02, IRA2) + Store (0x00, Local3) + Store (0x00, Local4) + And (PIRA, 0xF0, Local1) + ShiftRight (Local1, 0x04, Local1) + If (LNotEqual (Local1, 0x00)) + { + If (LGreater (Local1, 0x07)) + { + Subtract (Local1, 0x08, Local2) + ShiftLeft (One, Local2, Local4) + } + Else + { + If (LGreater (Local1, 0x00)) + { + ShiftLeft (One, Local1, Local3) + } + } + + Store (Local3, IRA1) + Store (Local4, IRA2) + } + Return (BUFA) + } + + /* Set Resources - dummy function to keep Linux ACPI happy + * Linux is more than happy not to tinker with irq + * assignments as long as the CRS and STA functions + * return good values + */ + Method (_SRS, 1, NotSerialized) {} + /* Disable - Set PnP Routing Reg to 0 */ + Method (_DIS, 0, NotSerialized ) + { + And (PIRA, 0x0F, PIRA) + } + } // End of LNKA + + Device (LNKB) + { + Name (_HID, EisaId ("PNP0C0F")) + Name (_UID, 0x02) + Method (_STA, 0, NotSerialized) + { + /* See If Coreboot has allocated INTB# */ + And (PIBC, 0x0F, Local0) + If (LEqual (Local0, 0x00)) + { + Return (0x09) + } + Else + { + Return (0x0B) + } + } + + Method (_PRS, 0, NotSerialized) + { + Name (BUFB, ResourceTemplate () + { + IRQ (Level, ActiveLow, Shared, ) + {3,4,6,7,10,11,12} + }) + Return (BUFB) + } + + Method (_CRS, 0, NotSerialized) + { + Name (BUFB, ResourceTemplate () + { + IRQ (Level, ActiveLow, Shared, _Y08) + {} + }) + /* Read the Binary Encoded Field and Map this */ + /* onto the bitwise _INT field in the IRQ descriptor */ + /* See ACPI Spec for detail of _IRQ Descriptor */ + CreateByteField (BUFB, \_SB.PCI0.LNKB._CRS._Y08._INT, IRB1) + CreateByteField (BUFB, 0x02, IRB2) + Store (0x00, Local3) + Store (0x00, Local4) + And (PIBC, 0x0F, Local1) + If (LNotEqual (Local1, 0x00)) + { + If (LGreater (Local1, 0x07)) + { + Subtract (Local1, 0x08, Local2) + ShiftLeft (One, Local2, Local4) + } + Else + { + If (LGreater (Local1, 0x00)) + { + ShiftLeft (One, Local1, Local3) + } + } + + Store (Local3, IRB1) + Store (Local4, IRB2) + } + Return (BUFB) + } + + /* Set Resources - dummy function to keep Linux ACPI happy + * Linux is more than happy not to tinker with irq + * assignments as long as the CRS and STA functions + * return good values + */ + Method (_SRS, 1, NotSerialized) {} + /* Disable - Set PnP Routing Reg to 0 */ + Method (_DIS, 0, NotSerialized ) + { + And (PIBC, 0xF0, PIBC) + } + + } // End of LNKB + + Device (LNKC) + { + Name (_HID, EisaId ("PNP0C0F")) + Name (_UID, 0x03) + Method (_STA, 0, NotSerialized) + { + /* See If Coreboot has allocated INTC# */ + And (PIBC, 0xF0, Local0) + If (LEqual (Local0, 0x00)) + { + Return (0x09) + } + Else + { + Return (0x0B) + } + } + + Method (_PRS, 0, NotSerialized) + { + Name (BUFC, ResourceTemplate () + { + IRQ (Level, ActiveLow, Shared, ) + {3,4,6,7,10,11,12} + }) + Return (BUFC) + } + + Method (_CRS, 0, NotSerialized) + { + Name (BUFC, ResourceTemplate () + { + IRQ (Level, ActiveLow, Shared, _Y09) + {} + }) + /* Read the Binary Encoded Field and Map this */ + /* onto the bitwise _INT field in the IRQ descriptor */ + /* See ACPI Spec for detail of _IRQ Descriptor */ + CreateByteField (BUFC, \_SB.PCI0.LNKC._CRS._Y09._INT, IRC1) + CreateByteField (BUFC, 0x02, IRC2) + Store (0x00, Local3) + Store (0x00, Local4) + And (PIBC, 0xF0, Local1) + ShiftRight (Local1, 0x04, Local1) + If (LNotEqual (Local1, 0x00)) + { + If (LGreater (Local1, 0x07)) + { + Subtract (Local1, 0x08, Local2) + ShiftLeft (One, Local2, Local4) + } + Else + { + If (LGreater (Local1, 0x00)) + { + ShiftLeft (One, Local1, Local3) + } + } + + Store (Local3, IRC1) + Store (Local4, IRC2) + } + Return (BUFC) + } + + /* Set Resources - dummy function to keep Linux ACPI happy + * Linux is more than happy not to tinker with irq + * assignments as long as the CRS and STA functions + * return good values + */ + Method (_SRS, 1, NotSerialized) {} + /* Disable - Set PnP Routing Reg to 0 */ + Method (_DIS, 0, NotSerialized ) + { + And (PIBC, 0x0F, PIBC) + } + +} // End of LNKC + +Device (LNKD) +{ + Name (_HID, EisaId ("PNP0C0F")) + Name (_UID, 0x04) + Method (_STA, 0, NotSerialized) + { + /* See If Coreboot has allocated INTD# */ + And (PIRD, 0xF0, Local0) + If (LEqual (Local0, 0x00)) + { + Return (0x09) + } + Else + { + Return (0x0B) + } + } + + Method (_PRS, 0, NotSerialized) + { + Name (BUFD, ResourceTemplate () + { + IRQ (Level, ActiveLow, Shared, ) + {3,4,6,7,10,11,12} + }) + Return (BUFD) + } + + Method (_CRS, 0, NotSerialized) + { + Name (BUFD, ResourceTemplate () + { + IRQ (Level, ActiveLow, Shared, _Y0A) + {} + }) + /* Read the Binary Encoded Field and Map this */ + /* onto the bitwise _INT field in the IRQ descriptor */ + /* See ACPI Spec for detail of _IRQ Descriptor */ + CreateByteField (BUFD, \_SB.PCI0.LNKD._CRS._Y0A._INT, IRD1) + CreateByteField (BUFD, 0x02, IRD2) + Store (0x00, Local3) + Store (0x00, Local4) + And (PIRD, 0xF0, Local1) + ShiftRight (Local1, 0x04, Local1) + If (LNotEqual (Local1, 0x00)) + { + If (LGreater (Local1, 0x07)) + { + Subtract (Local1, 0x08, Local2) + ShiftLeft (One, Local2, Local4) + } + Else + { + If (LGreater (Local1, 0x00)) + { + ShiftLeft (One, Local1, Local3) + } + } + + Store (Local3, IRD1) + Store (Local4, IRD2) + } + Return (BUFD) + } + + /* Set Resources - dummy function to keep Linux ACPI happy + * Linux is more than happy not to tinker with irq + * assignments as long as the CRS and STA functions + * return good values + */ + Method (_SRS, 1, NotSerialized) {} + /* Disable - Set PnP Routing Reg to 0 */ + Method (_DIS, 0, NotSerialized ) + { + And (PIRD, 0x0F, PIRD) + } + +} // End of LNKD + + +/* APIC IRQ Links */ + +Device (ATAI) +{ + Name (_HID, EisaId ("PNP0C0F")) + Name (_UID, 0x05) + Method (_STA, 0, NotSerialized) + { + /* ATFL == 0x02 if SATA Enabled */ + If (LNotEqual (ATFL, 0x02)) + { + /* Double Check By Reading SATA VID */ + /* Otherwise Compatibility Mode */ + If (LNotEqual (\_SB.PCI0.SATA.VID, 0x1106)) + { + Return (0x09) + } + Else + { + Return (0x0B) + } + } + Else + { + /* Serial ATA Enabled Check if PATA is in */ + /* Compatibility Mode */ + If (LEqual (\_SB.PCI0.PATA.ENAT, 0x0A)) + { + Return (0x09) + } + Else + { + Return (0x0B) + } + } + } + + Method (_PRS, 0, NotSerialized) + { + Name (ATAN, ResourceTemplate () + { + Interrupt (ResourceConsumer, Level, ActiveLow, Shared, ,, ) + { + 0x00000014, + } + }) + Return (ATAN) + } + + Method (_CRS, 0, NotSerialized) + { + Name (ATAB, ResourceTemplate () + { + Interrupt (ResourceConsumer, Level, ActiveLow, Shared, ,, _Y10) + { + 0x00000000, + } + }) + CreateByteField (ATAB, \_SB.PCI0.ATAI._CRS._Y10._INT, IRAI) + Store (0x14, IRAI) + Return (ATAB) + + } + + /* Set Resources - dummy function to keep Linux ACPI happy + * Linux is more than happy not to tinker with irq + * assignments as long as the CRS and STA functions + * return good values + */ + Method (_SRS, 1, NotSerialized) {} + /* Disable - dummy function to keep Linux ACPI happy */ + Method (_DIS, 0, NotSerialized ) {} + +} // End of ATA Interface Link + + +Device (USBI) +{ + Name (_HID, EisaId ("PNP0C0F")) + Name (_UID, 0x0A) + Method (_STA, 0, NotSerialized) + { + /* Check that at least one of the USB */ + /* functions is enabled */ + And (IDEB, 0x37, Local0) + If (LEqual (Local0, 0x37)) + { + Return (0x09) + } + Else + { + Return (0x0B) + } + } + + Method (_PRS, 0, NotSerialized) + { + Name (USBB, ResourceTemplate () + { + Interrupt (ResourceConsumer, Level, ActiveLow, Shared, ,, ) + { + 0x00000015, + } + }) + + Return(USBB) + } + + Method (_CRS, 0, NotSerialized) + { + Name (USBB, ResourceTemplate () + { + Interrupt (ResourceConsumer, Level, ActiveLow, Shared, ,, _Y12) + { + 0x00000000, + } + }) + CreateByteField (USBB, \_SB.PCI0.USBI._CRS._Y12._INT, IRBI) + Store (0x15, IRBI) + Return (USBB) + } + + + /* Set Resources - dummy function to keep Linux ACPI happy + * Linux is more than happy not to tinker with irq + * assignments as long as the CRS and STA functions + * return good values + */ + Method (_SRS, 1, NotSerialized) {} + /* Disable - dummy function to keep Linux ACPI happy */ + Method (_DIS, 0, NotSerialized ) {} +} + +Device (VT8I) +{ + Name (_HID, EisaId ("PNP0C0F")) + Name (_UID, 0x0B) + Method (_STA, 0, NotSerialized) + { + /* Check Whether Sound and/or Modem are Activated */ + If (LEqual (EAMC, 0x03)) + { + Return (0x09) + } + Else + { + Return (0x0B) + } + } + + Method (_PRS, 0, NotSerialized) + { + Name (A97C, ResourceTemplate () + { + Interrupt (ResourceConsumer, Level, ActiveLow, Shared, ,, ) + { + 0x00000016, + } + }) + Return (A97C) + } + + Method (_CRS, 0, NotSerialized) + { + Name (A97B, ResourceTemplate () + { + Interrupt (ResourceConsumer, Level, ActiveLow, Shared, ,, _Y14) + { + 0x00000000, + } + }) + CreateByteField (A97B, \_SB.PCI0.VT8I._CRS._Y14._INT, IRCI) + Store (0x16, IRCI) + Return (A97B) + } + + /* Set Resources - dummy function to keep Linux ACPI happy + * Linux is more than happy not to tinker with irq + * assignments as long as the CRS and STA functions + * return good values + */ + Method (_SRS, 1, NotSerialized) {} + /* Disable - dummy function to keep Linux ACPI happy */ + Method (_DIS, 0, NotSerialized ) {} + +} + + +Device (NICI) +{ + Name (_HID, EisaId ("PNP0C0F")) + Name (_UID, 0x0C) + Method (_STA, 0, NotSerialized) + { + /* Check if LAN Function is Enabled */ + /* Note that LAN Enable Polarity is different */ + /* from other functions in VT8237R !? */ + If (LEqual (ELAN, 0x00)) + { + Return (0x09) + } + Else + { + Return (0x0B) + } + } + + Method (_PRS, 0, NotSerialized) + { + Name (NICB, ResourceTemplate () + { + Interrupt (ResourceConsumer, Level, ActiveLow, Shared, ,, ) + { + 0x00000017, + } + }) + Return (NICB) + } + + Method (_CRS, 0, NotSerialized) + { + Name (NICD, ResourceTemplate () + { + Interrupt (ResourceConsumer, Level, ActiveLow, Shared, ,, _Y16) + { + 0x00000000, + } + }) + CreateByteField (NICD, \_SB.PCI0.NICI._CRS._Y16._INT, IRDI) + Store (0x17, IRDI) + Return (NICD) + } + + /* Set Resources - dummy function to keep Linux ACPI happy + * Linux is more than happy not to tinker with irq + * assignments as long as the CRS and STA functions + * return good values + */ + Method (_SRS, 1, NotSerialized) {} + /* Disable - dummy function to keep Linux ACPI happy */ + Method (_DIS, 0, NotSerialized ) {} + + +} diff --git a/src/mainboard/via/epia-n/mptable.c b/src/mainboard/via/epia-n/mptable.c new file mode 100644 index 0000000000..e0d5f8f456 --- /dev/null +++ b/src/mainboard/via/epia-n/mptable.c @@ -0,0 +1,115 @@ +/* generated by MPTable, version 2.0.15*/ +/* as modified by RGM for coreboot */ +#include +#include +#include +#include +#include + +void *smp_write_config_table(void *v) +{ + static const char sig[4] = "PCMP"; + static const char oem[8] = "LNXI "; + static const char productid[12] = "P4DPE "; + struct mp_config_table *mc; + + mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN); + memset(mc, 0, sizeof(*mc)); + + memcpy(mc->mpc_signature, sig, sizeof(sig)); + mc->mpc_length = sizeof(*mc); /* initially just the header */ + mc->mpc_spec = 0x04; + mc->mpc_checksum = 0; /* not yet computed */ + memcpy(mc->mpc_oem, oem, sizeof(oem)); + memcpy(mc->mpc_productid, productid, sizeof(productid)); + mc->mpc_oemptr = 0; + mc->mpc_oemsize = 0; + mc->mpc_entry_count = 0; /* No entries yet... */ + mc->mpc_lapic = LAPIC_ADDR; + mc->mpe_length = 0; + mc->mpe_checksum = 0; + mc->reserved = 0; + + smp_write_processors(mc); + + +/*Bus: Bus ID Type*/ + smp_write_bus(mc, 0, "PCI "); + smp_write_bus(mc, 1, "PCI "); + smp_write_bus(mc, 2, "ISA "); +/*I/O APICs: APIC ID Version State Address*/ + smp_write_ioapic(mc, 2, 0x20, 0xfec00000); + { + device_t dev; + struct resource *res; + dev = dev_find_slot(1, PCI_DEVFN(0x1e,0)); + if (dev) { + res = find_resource(dev, PCI_BASE_ADDRESS_0); + if (res) { + smp_write_ioapic(mc, 3, 0x20, res->base); + } + } + dev = dev_find_slot(1, PCI_DEVFN(0x1c,0)); + if (dev) { + res = find_resource(dev, PCI_BASE_ADDRESS_0); + if (res) { + smp_write_ioapic(mc, 4, 0x20, res->base); + } + } + dev = dev_find_slot(4, PCI_DEVFN(0x1e,0)); + if (dev) { + res = find_resource(dev, PCI_BASE_ADDRESS_0); + if (res) { + smp_write_ioapic(mc, 5, 0x20, res->base); + } + } + dev = dev_find_slot(4, PCI_DEVFN(0x1c,0)); + if (dev) { + res = find_resource(dev, PCI_BASE_ADDRESS_0); + if (res) { + smp_write_ioapic(mc, 8, 0x20, res->base); + } + } + } +/*I/O Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN# +*/ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x40, 0x2, 0x15); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x40, 0x2, 0x15); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x41, 0x2, 0x15); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x41, 0x2, 0x15); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x42, 0x2, 0x15); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x46, 0x2, 0x16); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x1, 0x0, 0x2, 0x10); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x48, 0x2, 0x17); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x3d, 0x2, 0x14); + smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x2, 0x0, 0x2, 0x0); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x2, 0x1, 0x2, 0x1); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x2, 0x0, 0x2, 0x2); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x2, 0x3, 0x2, 0x3); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x2, 0x4, 0x2, 0x4); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x2, 0x5, 0x2, 0x5); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x2, 0x6, 0x2, 0x6); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x2, 0x7, 0x2, 0x7); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x2, 0x8, 0x2, 0x8); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x2, 0x9, 0x2, 0x9); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x2, 0xd, 0x2, 0xd); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x2, 0xe, 0x2, 0xe); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x2, 0xf, 0x2, 0xf); +/*Local Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN#*/ + smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x0, 0x0, MP_APIC_ALL, 0x0); + smp_write_intsrc(mc, mp_NMI, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x0, 0x0, MP_APIC_ALL, 0x1); + /* There is no extension information... */ + + /* Compute the checksums */ + mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length); + mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length); + printk_debug("Wrote the mp table end at: %p - %p\n", + mc, smp_next_mpe_entry(mc)); + return smp_next_mpe_entry(mc); +} + +unsigned long write_smp_table(unsigned long addr) +{ + void *v; + v = smp_write_floating_table(addr); + return (unsigned long)smp_write_config_table(v); +} diff --git a/src/mainboard/via/epia-n/pata_methods.asl b/src/mainboard/via/epia-n/pata_methods.asl new file mode 100644 index 0000000000..68d505868e --- /dev/null +++ b/src/mainboard/via/epia-n/pata_methods.asl @@ -0,0 +1,132 @@ +/* + * Minimalist ACPI DSDT table for EPIA-N / NL + * Basic description of some hardware resources to allow + * interrupt assignments to be done. This is expected to be included + * into the PATA Device definition in ab_physical.asl + * (C) Copyright 2009 Jon Harrison + * + */ + +Name (TIM0, Package (0x07) +{ + Package (0x05) + { + 0x78, 0xB4, 0xF0, 0x017F, 0x0258 + }, + + Package (0x05) + { + 0x20, 0x22, 0x33, 0x47, 0x5D + }, + + Package (0x05) + { + 0x04, 0x03, 0x02, 0x01, 0x00 + }, + + Package (0x04) + { + 0x02, 0x01, 0x00, 0x00 + }, + + Package (0x07) + { + 0x78, 0x50, 0x3C, 0x2D, 0x1E, 0x14, 0x0F + }, + + Package (0x0F) + { + 0x06, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,0x00 + }, + + Package (0x07) + { + 0x0E, 0x08, 0x06, 0x04, 0x02, 0x01, 0x00 + } +}) + + +/* This method sets up the PATA Timing Control*/ +/* Note that a lot of this is done in the */ +/* Coreboot VT8237R Init code, but this is */ +/* already getting very cluttered with board */ +/* specific code. Using ACPI will allow this */ +/* to be de-cluttered a bit (so long as we're */ +/* running a ACPI Capable OS !!!) */ + +Method (PMEX, 0, Serialized) +{ + If (REGF) + { + /* Check if these regs are still at defaults */ + /* Board specific timing improvement if not */ + /* Already changed */ + If (LEqual (PMPT, 0xA8)) + { + Store (0x5D, PMPT) + } + + If (LEqual (PSPT, 0xA8)) + { + Store (0x5D, PSPT) + } + + If (LEqual (SMPT, 0xA8)) + { + Store (0x5D, SMPT) + } + + If (LEqual (SSPT, 0xA8)) + { + Store (0x5D, SSPT) + } + + } +} + +/* This Method Provides the method that is used to */ +/* Reset ATA Drives to POST reset condition */ +Method (GTF, 4, Serialized) +{ + Store (Buffer (0x07) + { + 0x03, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xEF + }, Local1) + Store (Buffer (0x07) + { + 0x03, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xEF + }, Local2) + CreateByteField (Local1, 0x01, MODE) + CreateByteField (Local2, 0x01, UMOD) + CreateByteField (Local1, 0x05, PCHA) + CreateByteField (Local2, 0x05, UCHA) + And (Arg0, 0x03, Local3) + If (LEqual (And (Local3, 0x01), 0x01)) + { + Store (0xB0, PCHA) + Store (0xB0, UCHA) + } + + If (Arg1) + { + Store (DerefOf (Index (DerefOf (Index (TIM0, 0x05)), Arg2)), + UMOD) + Or (UMOD, 0x40, UMOD) + } + Else + { + Store (Match (DerefOf (Index (TIM0, 0x01)), MEQ, Arg3, MTR, + 0x00, 0x00), Local0) + Or (0x20, DerefOf (Index (DerefOf (Index (TIM0, 0x03)), Local0 + )), UMOD) + } + + Store (Match (DerefOf (Index (TIM0, 0x01)), MEQ, Arg3, MTR, + 0x00, 0x00), Local0) + Or (0x08, DerefOf (Index (DerefOf (Index (TIM0, 0x02)), Local0 + )), MODE) + Concatenate (Local1, Local2, Local6) + Return (Local6) +} + diff --git a/src/mainboard/via/epia-n/pci_init.asl b/src/mainboard/via/epia-n/pci_init.asl new file mode 100644 index 0000000000..3169a03d50 --- /dev/null +++ b/src/mainboard/via/epia-n/pci_init.asl @@ -0,0 +1,30 @@ +/* + * Minimalist ACPI DSDT table for EPIA-N / NL + * Basic description of PCI Interrupt Assignments. + * This is expected to be included into _SB.PCI0 namespace + * (C) Copyright 2009 Jon Harrison + * + */ + +/* This file provides a PCI Bus Initialisation Method that sets + * some flags for use in the interrupt link assignment + */ + +Method (\_SB.PCI0._INI, 0, NotSerialized) +{ + + /* Checking for ATA Interface Enabled */ + Store (0x00, ATFL) + If (LEqual (EIDE, 0x01)) + { + Store (0x02, ATFL) + } + Else + { + If (LNotEqual (\_SB.PCI0.PATA.VID, 0x1106)) + { + Store (0x01, ATFL) + } + } + +} diff --git a/src/mainboard/via/epia-n/sb_physical.asl b/src/mainboard/via/epia-n/sb_physical.asl new file mode 100644 index 0000000000..c59feb64f0 --- /dev/null +++ b/src/mainboard/via/epia-n/sb_physical.asl @@ -0,0 +1,548 @@ +/* + * Minimalist ACPI DSDT table for EPIA-N / NL + * Basic description of some hardware resources to allow + * interrupt assignments to be done. This is expected to be included + * into _SB.PCI0 namespace + * (C) Copyright 2009 Jon Harrison + * + */ + + +/* Basic description of the VT8237R LPC Interface + * PCI Configuration Space + */ + +Device (VT8R) +{ + Name (_ADR, 0x00110000) + OperationRegion (USBC, PCI_Config, 0x50, 0x02) + Scope (\) + { + Field (\_SB.PCI0.VT8R.USBC, ByteAcc, NoLock, Preserve) + { + IDEB, 8 + } + } + + OperationRegion (VTSB, PCI_Config, 0x00, 0xE8) + Scope (\) + { + Field (\_SB.PCI0.VT8R.VTSB, ByteAcc, NoLock, Preserve) + { + Offset (0x02), + DEID, 16, + Offset (0x2C), + ID2C, 8, + ID2D, 8, + ID2E, 8, + ID2F, 8, + Offset (0x44), + PIRE, 4, + PIRF, 4, + PIRG, 4, + PIRH, 4, + POLE, 1, + POLF, 1, + POLG, 1, + POLH, 1, + ENR8, 1, + Offset (0x50), + ESB4, 1, + ESB3, 1, + ESB2, 1, + EIDE, 1, + EUSB, 1, + ESB1, 1, + EAMC, 2, + EKBC, 1, + KBCC, 1, + EPS2, 1, + ERTC, 1, + ELAN, 1, + , 2, + USBD, 1, + SIRQ, 8, + Offset (0x55), + PIRA, 8, + PIBC, 8, + PIRD, 8, + Offset (0x75), + BSAT, 1, + Offset (0x94), + PWC1, 2, + GPO1, 1, + GPO2, 1, + GPO3, 1, + PLLD, 1 + } + } +} + +/* Basic Description of Serial ATA Interface */ +Device (SATA) +{ + Name (_ADR, 0x000F0000) + Method (_STA, 0, NotSerialized) + { + If (LNotEqual (\_SB.PCI0.SATA.VID, 0x1106)) + { + Return (0x00) + } + Else + { + If (LEqual (\_SB.PCI0.SATA.CMDR, 0x00)) + { + Return (0x0D) + } + Else + { + Return (0x0F) + } + } + } + + OperationRegion (SAPR, PCI_Config, 0x00, 0xC2) + Field (SAPR, ByteAcc, NoLock, Preserve) + { + VID, 16, + Offset (0x04), + CMDR, 3, + Offset (0x3C), + IDEI, 8, + Offset (0x49), + , 6, + EPHY, 1 + } +} + +/* Basic Description of Parallel ATA Interface */ +/* An some initialisation of the interface */ +Device (PATA) +{ + Name (_ADR, 0x000F0001) + Name (REGF, 0x01) + Method (_STA, 0, NotSerialized) + { + If (LNotEqual (\_SB.PCI0.PATA.VID, 0x1106)) + { + Return (0x00) + } + Else + { + PMEX () + /* Check if the Interface is Enabled */ + If (LEqual (\_SB.PCI0.PATA.CMDR, 0x00)) + { + Return (0x0D) + } + Else + { + Return (0x0F) + } + } + } + + /* ACPI Spec says to check that regions are accessible */ + /* before trying to access them */ + Method (_REG, 2, NotSerialized) + { + /* Arg0 = Operating Region (0x02 == PCI_Config) */ + If (LEqual (Arg0, 0x02)) + { + /* Arg1 = Handler Connection Mode (0x01 == Connect) */ + Store (Arg1, REGF) + } + } + + Include("pata_methods.asl") + + + OperationRegion (PAPR, PCI_Config, 0x00, 0xC2) + Field (PAPR, ByteAcc, NoLock, Preserve) + { + VID, 16, + Offset (0x04), + CMDR, 3, + Offset (0x09), + ENAT, 4, + Offset (0x3C), + IDEI, 8, + Offset (0x40), + ESCH, 1, + EPCH, 1, + Offset (0x48), + SSPT, 8, + SMPT, 8, + PSPT, 8, + PMPT, 8, + Offset (0x50), + SSUT, 4, + SSCT, 1, + SSUE, 3, + SMUT, 4, + SMCT, 1, + SMUE, 3, + PSUT, 4, + PSCT, 1, + PSUE, 3, + PMUT, 4, + PMCT, 1, + PMUE, 3 + } + + + Device (CHN0) + { + Name (_ADR, 0x00) + Method (_STA, 0, NotSerialized) + { + If (LNotEqual (\_SB.PCI0.PATA.EPCH, 0x01)) + { + Return (0x00) + } + Else + { + Return (0x0F) + } + } + + Device (DRV0) + { + Name (_ADR, 0x00) + Method (_GTF, 0, NotSerialized) + { + Return (GTF (0x00, PMUE, PMUT, PMPT)) + } + } + + Device (DRV1) + { + Name (_ADR, 0x01) + Method (_GTF, 0, NotSerialized) + { + Return (GTF (0x01, PSUE, PSUT, PSPT)) + } + } + } + + Device (CHN1) + { + Name (_ADR, 0x01) + Method (_STA, 0, NotSerialized) + { + If (LNotEqual (ATFL, 0x02)) + { + If (LEqual (\_SB.PCI0.SATA.EPHY, 0x01)) + { + Return (0x00) + } + Else + { + If (LNotEqual (\_SB.PCI0.PATA.ESCH, 0x01)) + { + Return (0x00) + } + Else + { + Return (0x0F) + } + } + } + Else + { + If (LEqual (ATFL, 0x02)) + { + If (LNotEqual (\_SB.PCI0.PATA.ESCH, 0x01)) + { + Return (0x00) + } + Else + { + Return (0x0F) + } + } + Else + { + Return(0x00) + } + } + } + + Device (DRV0) + { + Name (_ADR, 0x00) + Method (_GTF, 0, NotSerialized) + { + Return (GTF (0x02, SMUE, SMUT, SMPT)) + } + } + + Device (DRV1) + { + Name (_ADR, 0x01) + Method (_GTF, 0, NotSerialized) + { + Return (GTF (0x03, SSUE, SSUT, SSPT)) + } + } + } +} // End of PATA Device + + +/* Implement Basic USB Presence detect and */ +/* Power Management Event mask */ +Device (USB0) +{ + Name (_ADR, 0x00100000) + Name (_PRW, Package (0x02) + { + 0x0E, + 0x03 + }) + + OperationRegion (U2F0, PCI_Config, 0x00, 0xC2) + Field (U2F0, ByteAcc, NoLock, Preserve) + { + VID, 16, + Offset (0x04), + CMDR, 3, + Offset (0x3C), + U0IR, 4, + Offset (0x84), + ECDX, 2 + } + + Method (_STA, 0, NotSerialized) + { + If (LNotEqual (\_SB.PCI0.USB0.VID, 0x1106)) + { + Return (0x00) + } + Else + { + If (LEqual (\_SB.PCI0.USB0.CMDR, 0x00)) + { + Return (0x0D) + } + Else + { + Return (0x0F) + } + } + } +} + +Device (USB1) +{ + Name (_ADR, 0x00100001) + Name (_PRW, Package (0x02) + { + 0x0E, + 0x03 + }) + + OperationRegion (U2F1, PCI_Config, 0x00, 0xC2) + Field (U2F1, ByteAcc, NoLock, Preserve) + { + VID, 16, + Offset (0x04), + CMDR, 3, + Offset (0x3C), + U1IR, 4, + Offset (0x84), + ECDX, 2 + } + + Method (_STA, 0, NotSerialized) + { + If (LNotEqual (\_SB.PCI0.USB1.VID, 0x1106)) + { + Return (0x00) + } + Else + { + If (LEqual (\_SB.PCI0.USB1.CMDR, 0x00)) + { + Return (0x0D) + } + Else + { + Return (0x0F) + } + } + } +} + +Device (USB2) +{ + Name (_ADR, 0x00100002) + Name (_PRW, Package (0x02) + { + 0x0E, + 0x03 + }) + + OperationRegion (U2F2, PCI_Config, 0x00, 0xC2) + Field (U2F2, ByteAcc, NoLock, Preserve) + { + VID, 16, + Offset (0x04), + CMDR, 3, + Offset (0x3C), + U2IR, 4, + Offset (0x84), + ECDX, 2 + } + + Method (_STA, 0, NotSerialized) + { + If (LNotEqual (\_SB.PCI0.USB2.VID, 0x1106)) + { + Return (0x00) + } + Else + { + If (LEqual (\_SB.PCI0.USB2.CMDR, 0x00)) + { + Return (0x0D) + } + Else + { + Return (0x0F) + } + } + } +} + +Device (USB3) +{ + Name (_ADR, 0x00100003) + Name (_PRW, Package (0x02) + { + 0x0E, + 0x03 + }) + + OperationRegion (U2F3, PCI_Config, 0x00, 0xC2) + Field (U2F3, ByteAcc, NoLock, Preserve) + { + VID, 16, + Offset (0x04), + CMDR, 3, + Offset (0x3C), + U3IR, 4, + Offset (0x84), + ECDX, 2 + } + + Method (_STA, 0, NotSerialized) + { + If (LNotEqual (\_SB.PCI0.USB3.VID, 0x1106)) + { + Return (0x00) + } + Else + { + If (LEqual (\_SB.PCI0.USB3.CMDR, 0x00)) + { + Return (0x0D) + } + Else + { + Return (0x0F) + } + } + } +} + +Device (USB4) +{ + Name (_ADR, 0x00100004) + Name (_PRW, Package (0x02) + { + 0x0E, + 0x03 + }) + + OperationRegion (U2F4, PCI_Config, 0x00, 0xC2) + Field (U2F4, ByteAcc, NoLock, Preserve) + { + VID, 16, + Offset (0x04), + CMDR, 3, + Offset (0x3C), + U4IR, 4, + Offset (0x84), + ECDX, 2 + } + + Method (_STA, 0, NotSerialized) + { + If (LNotEqual (\_SB.PCI0.USB4.VID, 0x1106)) + { + Return (0x00) + } + Else + { + If (LEqual (\_SB.PCI0.USB4.CMDR, 0x00)) + { + Return (0x0D) + } + Else + { + Return (0x0F) + } + } + } +} + +/* Basic Definition of Ethernet Interface */ +Device (NIC0) +{ + Name (_ADR, 0x00120000) + Name (_PRW, Package (0x02) + { + 0x03, + 0x05 + }) + + OperationRegion (NIC0, PCI_Config, 0x00, 0xC2) + Field (NIC0, ByteAcc, NoLock, Preserve) + { + VID, 16, + Offset (0x04), + CMDR, 3, + Offset (0x3C), + NIIR, 4, + } + + Method (_STA, 0, NotSerialized) + { + If (LNotEqual (\_SB.PCI0.NIC0.VID, 0x1106)) + { + Return (0x00) + } + Else + { + If (LEqual (\_SB.PCI0.NIC0.CMDR, 0x00)) + { + Return (0x0D) + } + Else + { + Return (0x0F) + } + } + } +} + +/* Very Basic Definition of Sound Controller */ +Device (AC97) +{ + Name (_ADR, 0x00110005) + Name (_PRW, Package (0x02) + { + 0x0D, + 0x05 + }) +} diff --git a/src/northbridge/via/cn400/vlink.c b/src/northbridge/via/cn400/vlink.c new file mode 100644 index 0000000000..1542af71fe --- /dev/null +++ b/src/northbridge/via/cn400/vlink.c @@ -0,0 +1,246 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2009 Jon Harrison + * + * 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 +#include +#include +#include +#include +#include "chip.h" +#include "northbridge.h" +#include "cn400.h" + +static void noop_1k(u32 knops) +{ + u32 i; + + for (i = 0; i < 1024 * knops; i++) { + __asm__ volatile ("nop\n\t"); + } + + return; +} + +/* Vlink Performance Improvements */ +static void vlink_init(device_t dev) +{ + u8 reg, reg8; + int i, j; + + printk_spew("Entering CN400 %s\n", __func__); + + /* Disconnect the VLink Before Changing Settings */ + reg = pci_read_config8(dev, 0x47); + reg |= 0x04; + pci_write_config8(dev, 0x47, reg); + + /* Wait for anything pending to flush */ + noop_1k(20); + + /* Setup Vlink Mode 1 */ + pci_write_config8(dev, 0x4F, 0x01); + pci_write_config8(dev, 0x48, 0x13); + + /* PCI Buffer Control */ + pci_write_config8(dev, 0x70, 0x82); + + /* CPU to PCI Flow Control */ + pci_write_config8(dev, 0x71, 0xc8); + pci_write_config8(dev, 0x72, 0xee); + + /* PCI Master Control */ + pci_write_config8(dev, 0x73, 0x01); + pci_write_config8(dev, 0x74, 0x20); + + /* PCI Arbitration 1 */ + pci_write_config8(dev, 0x75, 0x0f); + + /* PCI Arbitration 2 */ + pci_write_config8(dev, 0x76, 0x50); + pci_write_config8(dev, 0x77, 0x6e); + pci_write_config8(dev, 0x7F, 0x10); + + pci_write_config8(dev, 0x94, 0x20); + pci_write_config8(dev, 0x95, 0x0f); + + /* V-Link CKG Control 1 */ + pci_write_config8(dev, 0xB0, 0x01); + + /* V-Link NB Compensation Control */ + pci_write_config8(dev, 0xB5, 0x46); + pci_write_config8(dev, 0xB6, 0x68); + reg = pci_read_config8(dev, 0xB4); + reg |= 0x01; + pci_write_config8(dev, 0xB4, reg); + + /* V-Link NB Receive Strobe Delay */ + pci_write_config8(dev, 0xB7, 0x02); + + /* V-Link SB Compensation Control */ + pci_write_config8(dev, 0xB9, 0x84); + reg = pci_read_config8(dev, 0xB8); + reg |= 0x01; + pci_write_config8(dev, 0xB8, reg); + + pci_write_config8(dev, 0xBA, 0x6a); + pci_write_config8(dev, 0xBB, 0x01); + +#ifdef DEBUG_CN400 + /* Reconnect the VLink Before Continuing*/ + reg = pci_read_config8(dev, 0x47); + reg &= ~0x04; + pci_write_config8(dev, 0x47, reg); + + printk_spew("%s PCI Header Regs::\n", dev_path(dev)); + + for (i = 0 ; i < 16; i++) + { + printk_spew("%02X: ", i*16); + for (j = 0; j < 16; j++) + { + reg8 = pci_read_config8(dev, j+(i*16)); + printk_spew("%02X ", reg8); + } + printk_spew("\n"); + } +#endif +} + +static const struct device_operations vlink_operations = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = vlink_init, + .ops_pci = 0, +}; + +static const struct pci_driver vlink_driver __pci_driver = { + .ops = &vlink_operations, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_CN400_VLINK, +}; + +static void c3_host_init(device_t dev) +{ + u8 reg8; + int i, j; + + printk_spew("Entering CN400 %s\n", __func__); + + printk_spew("%s PCI Header Regs::\n", dev_path(dev)); + + for (i = 0 ; i < 16; i++) + { + printk_spew("%02X: ", i*16); + for (j = 0; j < 16; j++) + { + reg8 = pci_read_config8(dev, j+(i*16)); + printk_spew("%02X ", reg8); + } + printk_spew("\n"); + } + +} + +static const struct device_operations c3_host_operations = { + .read_resources = cn400_noop, + .set_resources = cn400_noop, + .enable_resources = cn400_noop, + .init = c3_host_init, + .ops_pci = 0, +}; + +static const struct pci_driver c3_host_driver __pci_driver = { + .ops = &c3_host_operations, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_CN400_HOST, +}; + + +static void c3_err_init(device_t dev) +{ + u8 reg8; + int i, j; + + printk_spew("Entering CN400 %s\n", __func__); + + printk_spew("%s PCI Header Regs::\n", dev_path(dev)); + + for (i = 0 ; i < 16; i++) + { + printk_spew("%02X: ", i*16); + for (j = 0; j < 16; j++) + { + reg8 = pci_read_config8(dev, j+(i*16)); + printk_spew("%02X ", reg8); + } + printk_spew("\n"); + } + +} + +static const struct device_operations c3_err_operations = { + .read_resources = cn400_noop, + .set_resources = cn400_noop, + .enable_resources = cn400_noop, + .init = c3_err_init, + .ops_pci = 0, +}; + +static const struct pci_driver c3_err_driver __pci_driver = { + .ops = &c3_err_operations, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_CN400_ERR, +}; + +static void cn400_pm_init(device_t dev) +{ + u8 reg8; + int i, j; + + printk_spew("Entering CN400 %s\n", __func__); + + printk_spew("%s PCI Header Regs::\n", dev_path(dev)); + + for (i = 0 ; i < 16; i++) + { + printk_spew("%02X: ", i*16); + for (j = 0; j < 16; j++) + { + reg8 = pci_read_config8(dev, j+(i*16)); + printk_spew("%02X ", reg8); + } + printk_spew("\n"); + } + +} + +static const struct device_operations cn400_pm_operations = { + .read_resources = cn400_noop, + .set_resources = cn400_noop, + .enable_resources = cn400_noop, + .init = cn400_pm_init, + .ops_pci = 0, +}; + +static const struct pci_driver cn400_pm_driver __pci_driver = { + .ops = &c3_err_operations, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_CN400_PM, +}; diff --git a/src/southbridge/via/vt8237r/vt8237r_nic.c b/src/southbridge/via/vt8237r/vt8237r_nic.c new file mode 100644 index 0000000000..9f618087cb --- /dev/null +++ b/src/southbridge/via/vt8237r/vt8237r_nic.c @@ -0,0 +1,62 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007, 2008 Rudolf Marek + * Copyright (C) 2009 Jon Harrison + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License v2 as published by + * the Free Software Foundation. + * + * 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 "vt8237r.h" + + +static void vt8237_eth_read_resources(struct device *dev) +{ +#ifdef CONFIG_EPIA_VT8237R_INIT + struct resource *res; + + /* Fix the I/O Resources of the USB2.0 Interface */ + res = new_resource(dev, PCI_BASE_ADDRESS_0); + res->base = 0xF6001000ULL; + res->size = 256; + res->align = 12; + res->gran = 8; + res->limit = res->base + res->size - 1; + res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | + IORESOURCE_ASSIGNED; +#else + pci_dev_read_resources(dev); +#endif + return; +} + + +static const struct device_operations vt8237_eth_ops = { + .read_resources = vt8237_eth_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = 0, + .enable = 0, + .ops_pci = 0, +}; + +static const struct pci_driver vt8237r_driver_eth __pci_driver = { + .ops = &vt8237_eth_ops, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_8233_7, +}; diff --git a/src/southbridge/via/vt8237r/vt8237r_usb.c b/src/southbridge/via/vt8237r/vt8237r_usb.c new file mode 100644 index 0000000000..bc4c34f8f9 --- /dev/null +++ b/src/southbridge/via/vt8237r/vt8237r_usb.c @@ -0,0 +1,166 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007, 2008 Rudolf Marek + * Copyright (C) 2009 Jon Harrison + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License v2 as published by + * the Free Software Foundation. + * + * 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 "vt8237r.h" + +#ifdef CONFIG_EPIA_VT8237R_INIT +u32 usb_io_addr[4] = {0xcc00, 0xd000, 0xd400, 0xd800}; +#endif + +static void usb_i_init(struct device *dev) +{ + +#ifdef CONFIG_EPIA_VT8237R_INIT + u8 reg8; + + printk_debug("Entering %s\n", __func__); + + printk_spew("%s Read %02X from PCI Command Reg\n", dev_path(dev), reg8); + + reg8 = pci_read_config8(dev, 0x04); + + reg8 = reg8 | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config8(dev, 0x04, reg8); + + printk_spew("%s Wrote %02X to PCI Command Reg\n", dev_path(dev), reg8); + + /* Set Cache Line Size and Latency Timer */ + pci_write_config8(dev, 0x0c, 0x08); + pci_write_config8(dev, 0x0d, 0x20); + + /* Enable Sub Device ID Back Door and set Generic */ + reg8 = pci_read_config8(dev, 0x42); + reg8 |= 0x10; + pci_write_config8(dev, 0x42, reg8); + pci_write_config16(dev, 0x2e, 0xAA07); + reg8 &= ~0x10; + pci_write_config8(dev, 0x42, reg8); + + + pci_write_config8(dev, 0x41, 0x12); + + pci_write_config8(dev, 0x49, 0x0B); + + /* Clear PCI Status */ + pci_write_config16(dev, 0x06, 0x7A10); +#endif + return; +} + +static void vt8237_usb_i_read_resources(struct device *dev) +{ +#ifdef CONFIG_EPIA_VT8237R_INIT + struct resource *res; + u8 function = (u8) dev->path.pci.devfn & 0x7; + + printk_spew("VT8237R Fixing USB 1.1 fn %d I/O resource = 0x%04X\n", function, usb_io_addr[function]); + + /* Fix the I/O Resources of the USB1.1 Interfaces */ + /* Auto PCI probe seems to size the resources */ + /* Incorrectly */ + res = new_resource(dev, PCI_BASE_ADDRESS_4); + res->base = usb_io_addr[function]; + res->size = 256; + res->limit = 0xffffUL; + res->align = 10; + res->gran = 8; + res->flags = IORESOURCE_IO | IORESOURCE_FIXED | + IORESOURCE_ASSIGNED; +#else + pci_dev_read_resources(dev); +#endif + return; +} + +static void usb_ii_init(struct device *dev) +{ +#ifdef CONFIG_EPIA_VT8237R_INIT + u8 reg8; + + printk_debug("Entering %s\n", __func__); + + /* Set memory Write and Invalidate */ + reg8 = pci_read_config8(dev, 0x04); + reg8 |= 0x10; + pci_write_config8(dev, 0x04, reg8); + + /* Set Cache line Size and Latency Timer */ + pci_write_config8(dev, 0x0c, 0x08); + pci_write_config8(dev, 0x0d, 0x20); + + /* Clear PCI Status */ + pci_write_config16(dev, 0x06, 0x7A10); +#endif + +} + +static void vt8237_usb_ii_read_resources(struct device *dev) +{ +#ifdef CONFIG_EPIA_VT8237R_INIT + struct resource *res; + + /* Fix the I/O Resources of the USB2.0 Interface */ + res = new_resource(dev, PCI_BASE_ADDRESS_0); + res->base = 0xF6000000ULL; + res->size = 256; + res->align = 12; + res->gran = 8; + res->limit = res->base + res->size - 1; + res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | + IORESOURCE_ASSIGNED; +#else + pci_dev_read_resources(dev); +#endif + return; +} + +static const struct device_operations usb_i_ops = { + .read_resources = vt8237_usb_i_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = usb_i_init, + .enable = 0, + .ops_pci = 0, +}; + +static const struct device_operations usb_ii_ops = { + .read_resources = vt8237_usb_ii_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = usb_ii_init, + .enable = 0, + .ops_pci = 0, +}; + +static const struct pci_driver vt8237r_driver_usbii __pci_driver = { + .ops = &usb_ii_ops, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_VT8237R_EHCI, +}; + +static const struct pci_driver vt8237r_driver_usbi __pci_driver = { + .ops = &usb_i_ops, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_VT8237R_UHCI, +};