diff options
Diffstat (limited to 'src/northbridge/via/vt8623/northbridge.c')
-rw-r--r-- | src/northbridge/via/vt8623/northbridge.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/src/northbridge/via/vt8623/northbridge.c b/src/northbridge/via/vt8623/northbridge.c new file mode 100644 index 0000000000..5f5e5d9dd8 --- /dev/null +++ b/src/northbridge/via/vt8623/northbridge.c @@ -0,0 +1,122 @@ +#include <console/console.h> +#include <arch/io.h> +#include <stdint.h> +#include <mem.h> +#include <part/sizeram.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/hypertransport.h> +#include <device/chip.h> +#include <stdlib.h> +#include <string.h> +#include <bitops.h> +#include "chip.h" +#include "northbridge.h" + +static const uint8_t ramregs[] = {0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x56, 0x57}; + +struct mem_range *sizeram(void) +{ + unsigned long mmio_basek; + static struct mem_range mem[10]; + device_t dev; + int i, idx; + unsigned char rambits; + + dev = dev_find_slot(0, 0); + if (!dev) { + printk_err("Cannot find PCI: 0:0\n"); + return 0; + } + mem[0].basek = 0; + mem[0].sizek = 65536; + idx = 1; + while(idx < sizeof(mem)/sizeof(mem[0])) { + mem[idx].basek = 0; + mem[idx].sizek = 0; + idx++; + } + for(rambits = 0, i = 0; i < sizeof(ramregs)/sizeof(ramregs[0]); i++) { + unsigned char reg; + reg = pci_read_config8(dev, ramregs[i]); + /* these are ENDING addresses, not sizes. + * if there is memory in this slot, then reg will be > rambits. + * So we just take the max, that gives us total. + * We take the highest one to cover for once and future linuxbios + * bugs. We warn about bugs. + */ + if (reg > rambits) + rambits = reg; + if (reg < rambits) + printk_err("ERROR! register 0x%x is not set!\n", + ramregs[i]); + } + + printk_debug("I would set ram size to 0x%x Kbytes\n", (rambits)*8*1024); + mem[0].sizek = rambits*8*1024; +#if 1 + for(i = 0; i < idx; i++) { + printk_debug("mem[%d].basek = %08x mem[%d].sizek = %08x\n", + i, mem[i].basek, i, mem[i].sizek); + } +#endif + + return mem; +} +static void enumerate(struct chip *chip) +{ + extern struct device_operations default_pci_ops_bus; + chip_enumerate(chip); + chip->dev->ops = &default_pci_ops_bus; +} + +/* + * This fixup is based on capturing values from an Award bios. Without + * this fixup the DMA write performance is awful (i.e. hdparm -t /dev/hda is 20x + * slower than normal, ethernet drops packets). + * Apparently these registers govern some sort of bus master behavior. + */ +static void random_fixup() { + device_t pcidev = dev_find_slot(0, 0); + + printk_spew("VT8601 random fixup ...\n"); + if (pcidev) { + pci_write_config8(pcidev, 0x70, 0xc0); + pci_write_config8(pcidev, 0x71, 0x88); + pci_write_config8(pcidev, 0x72, 0xec); + pci_write_config8(pcidev, 0x73, 0x0c); + pci_write_config8(pcidev, 0x74, 0x0e); + pci_write_config8(pcidev, 0x75, 0x81); + pci_write_config8(pcidev, 0x76, 0x52); + } +} + +static void northbridge_init(struct chip *chip, enum chip_pass pass) +{ + + struct northbridge_via_vt8601_config *conf = + (struct northbridge_via_vt8601_config *)chip->chip_info; + + switch (pass) { + case CONF_PASS_PRE_PCI: + break; + + case CONF_PASS_POST_PCI: + break; + + case CONF_PASS_PRE_BOOT: + random_fixup(); + break; + + default: + /* nothing yet */ + break; + } +} + +struct chip_control northbridge_via_vt8601_control = { + .enumerate = enumerate, + .enable = northbridge_init, + .name = "VIA vt8601 Northbridge", +}; |