Here's one more review: On Sat, Oct 27, 2007 at 01:16:49AM +0200, Rudolf Marek wrote: > +void hard_reset(void) > +{ > + printk_err("NO HARD RESET ON VT8237R! FIX ME!\n"); > +} > + > +void writeback(struct device *dev, u16 where,u8 what) ^ missing space
> +{ > + u8 regval; > + > + pci_write_config8(dev, where, what); > + regval = pci_read_config8(dev, where); > + if (regval != what) { > + print_debug("Writeback to "); > + print_debug_hex8(where); > + print_debug("failed "); > + print_debug_hex8(regval); > + print_debug("\n "); > + } > +} Hm, looks generally useful, why not put it in some global debug.c file? > +void dump_south(device_t dev) > +{ > + int i, j; > + > + for (i = 0; i < 256; i += 16) { > + printk_debug("%02x: ", i); > + for (j = 0; j < 16; j++) { > + printk_debug("%02x ", > + pci_read_config8(dev, i + j)); > + } > + printk_debug("\n"); > + } > +} Ditto. There already exists such code in (various) debug.c files in the repo, I think. > + > +static void vt8237r_enable(struct device *dev) > +{ > + struct southbridge_via_vt8237r_config *sb = > + (struct southbridge_via_vt8237r_config *) dev->chip_info; > + > + /* function disable 1=disabled > + 7 Dev 17 fn 6 MC97 > + 6 Dev 17 fn 5 AC97 > + 5 Dev 16 fn 1 USB 1.1 UHCI Ports 2-3 > + 4 Dev 16 fn 0 USB 1.1 UHCI Ports 0-1 > + 3 Dev 15 fn 0 Serial ATA > + 2 Dev 16 fn 2 USB 1.1 UHCI Ports 4-5 > + 1 Dev 16 fn 4 USB 2.0 EHCI > + 0 Dev 16 fn 3 USB 1.1 UHCI Ports 6-7 > + */ Use Linux-style comments please: /* * Foo. * Bar. */ > + > + pci_write_config8(dev, 0x50, sb->fn_ctrl_lo); > + > + /* > + 7 USB Device Mode 1=dis > + 6 Reserved > + 5 Internal LAN Controller Clock Gating 1=gated > + 4 Internal LAN Controller 1=di > + 3 Internal RTC 1=en > + 2 Internal PS2 Mouse 1=en > + 1 Internal KBC Configuration 0=dis ports 0x2e/0x2f off 0xe0-0xef > + 0 Internal Keyboard Controller 1=en > + */ > + > + pci_write_config8(dev, 0x51, sb->fn_ctrl_hi); > + > + /* TODO: if SATA is disabled, move IDE to fn0 to conform PCI specs */ > +} > + > +struct chip_operations southbridge_via_vt8237r_ops = { > + CHIP_NAME("VIA VT8237R Southbridge") > + .enable_dev = vt8237r_enable, > +}; > Index: src/southbridge/via/vt8237r/Config.lb > =================================================================== > --- src/southbridge/via/vt8237r/Config.lb (revision 0) > +++ src/southbridge/via/vt8237r/Config.lb (revision 0) > @@ -0,0 +1,24 @@ > +## > +## This file is part of the LinuxBIOS project. > +## > +## Copyright (C) 2007 Rudolf Marek <[EMAIL PROTECTED]> > +## > +## 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 > +## > +config chip.h > +driver vt8237r.o > +driver vt8237r_ide.o > +driver vt8237r_lpc.o > +driver vt8237r_sata.o > +driver vt8237r_bridge.o UHCI? EHCI? AC97 audio / modem? LAN? What's the status there? > Index: src/southbridge/via/vt8237r/vt8237r_ide.c > =================================================================== > --- src/southbridge/via/vt8237r/vt8237r_ide.c (revision 0) > +++ src/southbridge/via/vt8237r/vt8237r_ide.c (revision 0) > @@ -0,0 +1,124 @@ > +/* > + * This file is part of the LinuxBIOS project. > + * > + * Based on other VIA SB code, no native mode. Interrupts from unconnected > HDDs > + * might occur if IRQ14/15 is used for PCI. Therefore no native mode support. Don't put this in the license header please, move it somewhere below as a normal comment. > + * > + * Copyright (C) 2007 Rudolf Marek <[EMAIL PROTECTED]> > + * > + * 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 <device/device.h> > +#include <device/pci.h> > +#include <device/pci_ops.h> > +#include <device/pci_ids.h> > +#include <console/console.h> > +#include "vt8237r.h" > +#include "chip.h" > + > +#define IDE_CS 0x40 > +#define IDE_CONF_I 0x41 > +#define IDE_CONF_II 0x42 > +#define IDE_CONF_FIFO 0x43 > +#define IDE_MISC_I 0x44 > +#define IDE_MISC_II 0x45 > +#define IDE_UDMA 0x50 Yep, either here or vt8237.h. > +static void ide_init(struct device *dev) > +{ > + struct southbridge_via_vt8237r_config *sb = > + (struct southbridge_via_vt8237r_config *) dev->chip_info; > + > + u8 enables; > + u32 cablesel; > + > + printk_info("Enabling VIA IDE.\n"); Not needed IMHO if the other lines are printed already. > + printk_info("%s IDE interface %s\n", "Primary", > + sb->ide0_enable ? "enabled" : "disabled"); > + printk_info("%s IDE interface %s\n", "Secondary", > + sb->ide1_enable ? "enabled" : "disabled"); > + enables = pci_read_config8(dev, IDE_CS) & ~0x3; > + enables |= (sb->ide0_enable << 1) | sb->ide1_enable; > + pci_write_config8(dev, IDE_CS, enables); > + enables = pci_read_config8(dev, IDE_CS); > + printk_debug("enables in reg 0x40 read back as 0x%x\n", enables); Why not use writeback() here (and in a few more places below)? > + /* enable only compatibility mode, cannot use IRQ14/IRQ15 for PCI > anyway */ Line too long, and it should start with capital letter and end with full stop. > + enables = pci_read_config8(dev, IDE_CONF_II); > + enables &= ~0xc0; > + pci_write_config8(dev,IDE_CONF_II, enables); > + enables = pci_read_config8(dev, IDE_CONF_II); > + printk_debug("enables in reg 0x42 read back as 0x%x\n", enables); > + > + /* Enable prefetch buffers */ > + enables = pci_read_config8(dev, IDE_CONF_I); > + enables |= 0xf0; > + pci_write_config8(dev, IDE_CONF_I, enables); > + > + /* flush FIFOs at half */ > + enables = pci_read_config8(dev, IDE_CONF_FIFO); > + enables &= 0xf0; > + enables |= (1 << 2) | (1 << 0); > + pci_write_config8(dev, IDE_CONF_FIFO, enables); > + > + /* PIO read prefetch counter, Bus Master IDE Status Register Read Retry > */ > + enables = pci_read_config8(dev, IDE_MISC_I); > + enables &= 0xe2; > + enables |= (1 << 4) | (1 << 3); > + pci_write_config8(dev, IDE_MISC_I, enables); > + > + /* Use memory read multiple, Memory-Write-and-Invalidate */ > + enables = pci_read_config8(dev, IDE_MISC_II); > + enables |= (1 << 2) | (1 << 3); > + pci_write_config8(dev, IDE_MISC_II, enables); > + > + /* address decoding */ > + /* disable the BARs, we use std ports */ Why? Just curious... > + pci_write_config32(dev, PCI_BASE_ADDRESS_0, 0x0); > + pci_write_config32(dev, PCI_BASE_ADDRESS_1, 0x0); > + pci_write_config32(dev, PCI_BASE_ADDRESS_2, 0x0); > + pci_write_config32(dev, PCI_BASE_ADDRESS_3, 0x0); > + > + /* Force interrupts to use compat mode */ > + pci_write_config8(dev, PCI_INTERRUPT_PIN, 0x0); > + pci_write_config8(dev, PCI_INTERRUPT_LINE, 0xff); > + /* standard bios sets master bit. */ > + enables = pci_read_config8(dev, PCI_COMMAND); > + enables |= PCI_COMMAND_MASTER | PCI_COMMAND_IO; > + pci_write_config8(dev, PCI_COMMAND, enables); > + enables = pci_read_config8(dev, 0x4); > + printk_debug("command in reg 0x4 reads back as 0x%x\n", enables); > + > + /* cable guy */ > + cablesel = pci_read_config32(dev, IDE_UDMA); > + cablesel &= ~((1 << 28) | (1 << 20) | (1 <<12) | (1 << 4)); > + cablesel |= (sb->ide0_cable << 28) | (sb->ide0_cable << 20) | > + (sb->ide1_cable << 12) | (sb->ide1_cable << 4); > + pci_write_config32(dev, IDE_UDMA, cablesel); > +} > + > +static struct device_operations ide_ops = { > + .read_resources = pci_dev_read_resources, > + .set_resources = pci_dev_set_resources, > + .enable_resources = pci_dev_enable_resources, > + .init = ide_init, > + .enable = 0, > + .ops_pci = 0, > +}; > + > +static struct pci_driver northbridge_driver __pci_driver = { > + .ops = &ide_ops, > + .vendor = PCI_VENDOR_ID_VIA, > + .device = PCI_DEVICE_ID_VIA_82C586_1, > +}; > Index: src/southbridge/via/vt8237r/vt8237r.h > =================================================================== > --- src/southbridge/via/vt8237r/vt8237r.h (revision 0) > +++ src/southbridge/via/vt8237r/vt8237r.h (revision 0) > @@ -0,0 +1,28 @@ > +/* > + * This file is part of the LinuxBIOS project. > + * > + * Copyright (C) 2007 Rudolf Marek <[EMAIL PROTECTED]> > + * > + * 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 > + */ > + > +/* static resources for VT8237R southbridge */ > + > +#define VT8237R_APIC_ID 0x2 > +#define VT8237R_ACPI_IO_BASE 0x500 > +#define VT8237R_SMBUS_IO_BASE 0x400 > +/* 0x0 disabled, 0x2 reserved 0xf = IRQ15 */ ^ missing comma? > +#define VT8237R_ACPI_IRQ 0x9 > +#define VT8237R_HPET_ADDR 0xfed00000ULL > +#define VT8237R_APIC_BASE 0xfec00000ULL > Index: src/southbridge/via/vt8237r/vt8237r_early_smbus.c > =================================================================== > --- src/southbridge/via/vt8237r/vt8237r_early_smbus.c (revision 0) > +++ src/southbridge/via/vt8237r/vt8237r_early_smbus.c (revision 0) > @@ -0,0 +1,172 @@ > +/* > + * This file is part of the LinuxBIOS project. > + * > + * Copyright (C) 2007 Corey Osgood <[EMAIL PROTECTED]> > + * Copyright (C) 2007 Rudolf Marek <[EMAIL PROTECTED]> > + * > + * 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 <device/pci_ids.h> > +#include "vt8237r.h" > + > +#define SMBHSTSTAT VT8237R_SMBUS_IO_BASE + 0x0 > +#define SMBSLVSTAT VT8237R_SMBUS_IO_BASE + 0x1 > +#define SMBHSTCTL VT8237R_SMBUS_IO_BASE + 0x2 > +#define SMBHSTCMD VT8237R_SMBUS_IO_BASE + 0x3 > +#define SMBXMITADD VT8237R_SMBUS_IO_BASE + 0x4 > +#define SMBHSTDAT0 VT8237R_SMBUS_IO_BASE + 0x5 > + > +/* Define register settings */ > +#define HOST_RESET 0xff > +#define DIMM_BASE (0x50<<1) Is this really needed in vt8237r_early_smbus.c? I don't think so. This address is dependent on the board anyway, correct? > +/* 1 in the 0 bit of SMBHSTADD states to READ */ > +#define READ_CMD 0x01 > + > +#define SMBUS_TIMEOUT (100*1000*10) > + > +#define I2C_TRANS_CMD 0x40 > +#define CLOCK_SLAVE_ADDRESS 0x69 > + > +/* Debugging macros. Only necessary if something isn't working right */ > + > +#if DEBUG_SMBUS == 1 > +#define PRINT_DEBUG(x) print_debug(x) > +#define PRINT_DEBUG_HEX16(x) print_debug_hex16(x) > +#else > +#define PRINT_DEBUG(x) > +#define PRINT_DEBUG_HEX16(x) > +#endif > +/* Internal functions */ Drop the above comment, not needed IMO. > + > +/* TODO: make define? */ > +#define SMBUS_DELAY() inb(0x80) Huh? It already is... > + > +static void smbus_print_error(u8 host_status_register, > + int loops) "int loops" can go in the same line. > +{ > + /* Check if there actually was an error */ > + if (host_status_register == 0x00 || host_status_register == 0x40 || Pretty long name, maybe host_status or so? It's relatively clear we talk about a register. > + host_status_register == 0x42) > + return; > + if (loops >= SMBUS_TIMEOUT) { > + print_err("SMBus Timout\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"); > + } This is probably a matter of taste, but for one-liners I learned to like this style: [...] if (loops >= SMBUS_TIMEOUT) print_err("SMBus Timout\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"); > +} > + > +static void smbus_wait_until_ready(void) > +{ > + int loops; > + > + PRINT_DEBUG("Waiting until smbus ready\r\n"); > + > + loops = 0; > + /* Yes, this is a mess, but it's the easiest way to do it */ > + while ((inb(SMBHSTSTAT) & 1) == 1 && loops <= SMBUS_TIMEOUT) > + ++loops; > + smbus_print_error(inb(SMBHSTSTAT), loops); > +} > + > +static void smbus_reset(void) > +{ > + outb(HOST_RESET, SMBHSTSTAT); > + /* Datasheet says we have to read it to take ownership of SMBus */ > + inb(SMBHSTSTAT); > + > + PRINT_DEBUG("After reset status: "); > + PRINT_DEBUG_HEX16(inb(SMBHSTSTAT)); Reading it twice won't do any harm here, I assume? > + PRINT_DEBUG("\r\n"); > +} > + > +/* Public functions */ Not needed. > +u8 smbus_read_byte(u32 dimm, u32 offset) > +{ > + u32 val; > + > + print_debug("DIMM "); > + print_debug_hex8(dimm); > + print_debug(" OFFSET "); > + print_debug_hex8(offset); > + print_debug("\r\n"); > + > + smbus_reset(); > + /* clear host data port */ > + outb(0x00, SMBHSTDAT0); > + SMBUS_DELAY(); > + smbus_wait_until_ready(); > + > + /* actual addr to reg format */ > + dimm = (dimm << 1); > + dimm |= 1; > + outb(dimm, SMBXMITADD); > + outb(offset, SMBHSTCMD); > + outb(0x48, SMBHSTCTL); What is 0x48? What effect does it have (should be a comment)? > + > + SMBUS_DELAY(); > + > + smbus_wait_until_ready(); > + > + val = inb(SMBHSTDAT0); > + print_debug("Read: "); > + print_debug_hex8(val); > + print_debug("\r\n"); > + > + smbus_reset(); /* probably don't have to do this, but it can't > hurt */ > + return val; /* can I just "return inb(SMBHSTDAT0)"? */ Depends. Will the read value (and side-effects, if any) be the same after the above reset? > +} > + > +void enable_smbus(void) > +{ > + device_t dev; > + > + /* Power management controller */ > + > + dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA, > + PCI_DEVICE_ID_VIA_VT8237R_ISA), 0); > + > + if (dev == PCI_DEV_INVALID) { > + die("Power Managment Controller not found\r\n"); > + } > + > + /* Set clock source */ > + pci_write_config8(dev, 0x94, 0xa0); Needs better comment, e.g. "Set clock source to RTC. Enable Internal PLL Reset During Suspend" or something like that. Also, 0x94 -> VT8237R_POWER_WELL_CONTROL (or just POWER_WELL_CONTROL). > + /* Write SMBus IO base to 0xd0, and enable SMBus */ > + pci_write_config16(dev, 0xd0, VT8237R_SMBUS_IO_BASE | 0x1); 0xd0 -> SMBUS_IO_BASE_REG (yes, the "REG" sucks, but in thise cause it can be confuѕed with VT8237R_SMBUS_IO_BASE otherwise) > + /* Set to Award value */ Nope... > + pci_write_config8(dev, 0xd2, 0x01); ... but bow about "Enable SMB controller functions"? 0xd2 -> SMBUS_HOST_CONFIG(URATION). > + /* make it work for I/O ... */ > + pci_write_config16(dev, PCI_COMMAND, PCI_COMMAND_IO); > + > + smbus_reset(); Again? Needed? > + > + /* reset the internal pointer */ > + inb(SMBHSTCTL); > +} > Index: src/southbridge/via/vt8237r/vt8237r_sata.c > =================================================================== > --- src/southbridge/via/vt8237r/vt8237r_sata.c (revision 0) > +++ src/southbridge/via/vt8237r/vt8237r_sata.c (revision 0) > @@ -0,0 +1,56 @@ > +/* > + * This file is part of the LinuxBIOS project. > + * > + * Copyright (C) 2007 Rudolf Marek <[EMAIL PROTECTED]> > + * > + * 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 <console/console.h> > +#include <device/device.h> > +#include <device/pci.h> > +#include <device/pci_ops.h> > +#include <device/pci_ids.h> > + > +#define SATA_MISC_CTRL 0x45 > + > +static void sata_init(struct device *dev) > +{ > + u8 reg; > + > + printk_debug("Configuring VIA SATA Controller\n"); > + /* class IDE Disk */ > + reg = pci_read_config8(dev, SATA_MISC_CTRL); > + reg &= 0x7f; /* Sub Class Write Protect off */ > + pci_write_config8(dev, SATA_MISC_CTRL, reg); > + /* change the device class to SATA from RAID */ > + pci_write_config8(dev, PCI_CLASS_DEVICE, 0x1); > + reg |= 0x80; /* Sub Class Write Protect on */ > + pci_write_config8(dev, SATA_MISC_CTRL, reg); > +} > + > +static struct device_operations sata_ops = { > + .read_resources = pci_dev_read_resources, > + .set_resources = pci_dev_set_resources, > + .enable_resources = pci_dev_enable_resources, > + .init = sata_init, > + .enable = 0, > + .ops_pci = 0, > +}; > + > +static struct pci_driver northbridge_driver __pci_driver = { > + .ops = &sata_ops, > + .vendor = PCI_VENDOR_ID_VIA, > + .device = PCI_DEVICE_ID_VIA_VT6420_SATA, > +}; > Index: src/southbridge/via/vt8237r/chip.h > =================================================================== > --- src/southbridge/via/vt8237r/chip.h (revision 0) > +++ src/southbridge/via/vt8237r/chip.h (revision 0) > @@ -0,0 +1,37 @@ > +/* > + * This file is part of the LinuxBIOS project. > + * > + * Copyright (C) 2007 Rudolf Marek <[EMAIL PROTECTED]> > + * > + * 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 > + */ > + > +#ifndef SOUTHBRIDGE_VIA_VT8237R_CHIP_H > +#define SOUTHBRIDGE_VIA_VT8237R_CHIP_H > + > +extern struct chip_operations southbridge_via_vt8237r_ops; > + > +struct southbridge_via_vt8237r_config { > + > + /* function enable bits, check vt8237r.c for details */ > + unsigned int fn_ctrl_lo; u16? > + unsigned int fn_ctrl_hi; > + int ide0_enable:1; > + int ide1_enable:1; > + /* 1 = 80-pin cable */ > + int ide0_cable:1; > + int ide1_cable:1; > +}; > + > +#endif /* SOUTHBRIDGE_VIA_VT8237R_CHIP_H */ > Index: src/southbridge/via/vt8237r/vt8237r_bridge.c > =================================================================== > --- src/southbridge/via/vt8237r/vt8237r_bridge.c (revision 0) > +++ src/southbridge/via/vt8237r/vt8237r_bridge.c (revision 0) > @@ -0,0 +1,57 @@ > +/* > + * This file is part of the LinuxBIOS project. > + * > + * Copyright (C) 2007 Rudolf Marek <[EMAIL PROTECTED]> > + * > + * 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 <device/device.h> > +#include <device/pci.h> > +#include <device/pci_ops.h> > +#include <device/pci_ids.h> > +#include <console/console.h> > + > +static void br_enable(struct device *dev) bridge_enable, no need to truncate it here, IMHO. > +{ > + > + print_debug("B188 device dump\n"); B188? > + /* VIA recommends this, sorry no known info */ > + writeback(dev, 0x40, 0x91); > + writeback(dev, 0x41, 0x40); > + writeback(dev, 0x43, 0x44); > + writeback(dev, 0x44, 0x31); > + writeback(dev, 0x45, 0x3a); > + writeback(dev, 0x46, 0x88); /* PCI ID lo */ > + writeback(dev, 0x47, 0xb1); /* PCI ID hi */ > + writeback(dev, 0x3e, 0x16); /* bridge control */ > + dump_south(dev); > +} > + > +static struct device_operations br_ops = { > + .read_resources = pci_bus_read_resources, > + .set_resources = pci_dev_set_resources, > + .enable_resources = pci_bus_enable_resources, > + .enable = br_enable, > + .scan_bus = pci_scan_bridge, > + .reset_bus = pci_bus_reset, > + .ops_pci = 0, > +}; > + > + > +static struct pci_driver northbridge_driver __pci_driver = { > + .ops = &br_ops, > + .vendor = PCI_VENDOR_ID_VIA, > + .device = PCI_DEVICE_ID_VIA_K8T890CE_BR, > +}; > Index: src/southbridge/via/vt8237r/vt8237r_lpc.c > =================================================================== > --- src/southbridge/via/vt8237r/vt8237r_lpc.c (revision 0) > +++ src/southbridge/via/vt8237r/vt8237r_lpc.c (revision 0) > @@ -0,0 +1,307 @@ > +/* > + * This file is part of the LinuxBIOS project. > + * Inspiration from other VIA SB code. > + * Copyright (C) 2007 Rudolf Marek <[EMAIL PROTECTED]> > + * > + * 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 <arch/io.h> > +#include <console/console.h> > +#include <device/device.h> > +#include <device/pci.h> > +#include <device/pci_ops.h> > +#include <device/pci_ids.h> > +#include <pc80/mc146818rtc.h> > +#include <cpu/x86/lapic.h> > +#include "vt8237r.h" > +#include "chip.h" > + > +#define ALL (0xff << 24) > +#define NONE (0) > +#define DISABLED (1 << 16) > +#define ENABLED (0 << 16) > +#define TRIGGER_EDGE (0 << 15) > +#define TRIGGER_LEVEL (1 << 15) > +#define POLARITY_HIGH (0 << 13) > +#define POLARITY_LOW (1 << 13) > +#define PHYSICAL_DEST (0 << 11) > +#define LOGICAL_DEST (1 << 11) > +#define ExtINT (7 << 8) > +#define NMI (4 << 8) > +#define SMI (2 << 8) > +#define INT (1 << 8) > + > +struct ioapicreg { > + u32 reg; > + u32 value_low, value_high; > +}; > + > +static struct ioapicreg ioapicregvalues[] = { You can merge them like this (as the struct is never needed anywhere else, AFAICS): static const struct { u32 reg; u32 value_low; u32 value_high; } ioapic_table[] = { // ... } > + > + /* IO-APIC virtual wire mode configuration */ > + /* mask, trigger, polarity, destination, delivery, vector */ > + {0, > + ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT, > + NONE}, > + {1, DISABLED, NONE}, > + {2, DISABLED, NONE}, > + {3, DISABLED, NONE}, > + {4, DISABLED, NONE}, > + {5, DISABLED, NONE}, > + {6, DISABLED, NONE}, > + {7, DISABLED, NONE}, > + {8, DISABLED, NONE}, > + {9, DISABLED, NONE}, > + {10, DISABLED, NONE}, > + {11, DISABLED, NONE}, > + {12, DISABLED, NONE}, > + {13, DISABLED, NONE}, > + {14, DISABLED, NONE}, > + {15, DISABLED, NONE}, > + {16, DISABLED, NONE}, > + {17, DISABLED, NONE}, > + {18, DISABLED, NONE}, > + {19, DISABLED, NONE}, > + {20, DISABLED, NONE}, > + {21, DISABLED, NONE}, > + {22, DISABLED, NONE}, > + {23, DISABLED, NONE}, > + /* Be careful and don't write past the end... */ > +}; > +extern void dump_south(device_t dev); Should be at the top of the file (if at all). > + > +static void setup_ioapic(u32 ioapic_base) > +{ > + u32 value_low, value_high, val; > + volatile u32 *l; > + struct ioapicreg *a = ioapicregvalues; Not needed? Use the static ioapic_table[] from above directly. > + int i; > + > + /* all delivered to CPU0 */ > + ioapicregvalues[0].value_high = (lapicid()) << (56 - 32); > + l = (unsigned long *) ioapic_base; > + /* set APIC to FSB message bus */ > + l[0] = 0x3; val = l[4]; Only one command per line please. > + l[4] = (val & 0xFFFFFE) | 1; > + /* set APIC ADDR - this will be VT8237R_APIC_ID */ > + l[0] = 0; val = l[4]; > + l[4] = (val & 0xF0FFFF) | (VT8237R_APIC_ID << 24); > + > + for (i = 0; > + i < sizeof(ioapicregvalues) / sizeof(ioapicregvalues[0]); ARRAY_SIZE (later). > + i++, a++) { > + l[0] = (a->reg * 2) + 0x10; > + l[4] = a->value_low; > + value_low = l[4]; > + l[0] = (a->reg * 2) + 0x11; > + l[4] = a->value_high; > + value_high = l[4]; > + if ((i == 0) && (value_low == 0xffffffff)) { > + printk_warning("IO APIC not responding.\n"); > + return; > + } > + } > +} > + > +static void pci_routing_fixup(struct device *dev) > +{ > + /* set up PCI IRQ routing, route everything through APIC */ Maybe make this a Doxygen comment at the top of the function? > + pci_write_config8(dev, 0x44, 0x00); /* PCI PNP Interrupt Routing > INTE/F - disable */ > + pci_write_config8(dev, 0x45, 0x00); /* PCI PNP Interrupt Routing > INTG/H - disable */ > + pci_write_config8(dev, 0x46, 0x10); /* Route INTE-INTH through > registers above, no map to INTA-INTD */ > + pci_write_config8(dev, 0x54, 0x00); /* PCI Interrupt Polarity */ > + pci_write_config8(dev, 0x55, 0x00); /* PCI INTA# Routing */ > + pci_write_config8(dev, 0x56, 0x00); /* PCI INTB#/C# Routing */ > + pci_write_config8(dev, 0x57, 0x00); /* PCI INTD# Routing */ > +} > +/* /** rather. (i.e. make it a Doxygen comment) > + * 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 !!!! Not sure we want _this_ in the comments ;) > + */ > + > +void setup_pm(device_t dev) > +{ > + /* Debounce LID and PWRBTN# Inputs for 16ms */ > + pci_write_config8(dev, 0x80, 0x20); > + /* Set ACPI base address to IO VT8237R_ACPI_IO_BASE */ > + pci_write_config16(dev, 0x88, VT8237R_ACPI_IO_BASE | 0x1); > + /* set ACPI to 9, need to set IRQ 9 override to level! > + set PSON gating */ > + pci_write_config8(dev, 0x82, 0x40 | VT8237R_ACPI_IRQ); > + /* primary interupt channel, define wake events 0=IRQ0 15=IRQ15 1=en */ > + pci_write_config16(dev, 0x84, 0x30b2); > + /* SMI output level to low, 7.5us throttle clock */ > + pci_write_config8(dev, 0x8d, 0x18); > + /* GP Timer Control 1s */ > + pci_write_config8(dev, 0x93, 0x88); > + /* 7=SMBus Clock from RTC 32.768KHz > + 5=Internall PLL reset from susp > + 2= GPO2 is GPIO > + */ Linux-style comments please. /* 7=SMBus Clock from RTC 32.768KHz * 5=Internall PLL reset from susp * 2= GPO2 is GPIO */ > + pci_write_config8(dev, 0x94, 0xa4); > + /* 7=stp to sust delay 1msec, > + 6=SUSST# Deasserted Before PWRGD for STD > + 3=GPO26/GPO27 is GPO > + 2=Disable Alert on Lan > + */ Ditto. > + pci_write_config8(dev, 0x95, 0xcc); > + /* Disable GP3 timer */ > + pci_write_config8(dev, 0x98, 0); > + /* enable SATA LED, disable special CPU Frequency Change - > + GPIO28 GPIO22 GPIO29 GPIO23 are GPIOs */ > + pci_write_config8(dev, 0xe5, 0x9); > + /* REQ5 as PCI request input - should be together with INTE-INTH */ > + pci_write_config8(dev, 0xe4, 0x4); > + /* Enable ACPI accessm RTC signal gated with PSON */ > + pci_write_config8(dev, 0x81, 0x84); > + /* clear status events */ > + outw(0xffff, VT8237R_ACPI_IO_BASE + 0x00); > + outw(0xffff, VT8237R_ACPI_IO_BASE + 0x20); > + outw(0xffff, VT8237R_ACPI_IO_BASE + 0x28); > + outl(0xffffffff, VT8237R_ACPI_IO_BASE + 0x30); > + /* disable SCI on GPIO */ > + outw(0x0, VT8237R_ACPI_IO_BASE + 0x22); > + /* disable SMI on GPIO */ > + outw(0x0, VT8237R_ACPI_IO_BASE + 0x24); > + /* disable all global enable SMIs */ > + outw(0x0, VT8237R_ACPI_IO_BASE + 0x2a); > + /* all SMI off, both IDE buses ON, PSON rising edge */ > + outw(0x0, VT8237R_ACPI_IO_BASE + 0x2c); > + /* primary activity SMI disable */ > + outl(0x0, VT8237R_ACPI_IO_BASE + 0x34); > + /* GP timer reload on none */ > + outl(0x0, VT8237R_ACPI_IO_BASE + 0x38); > + /* disable extended IO traps */ > + outb(0x0, VT8237R_ACPI_IO_BASE + 0x42); > + /* SCI is generated for RTC/pwrBtn/slpBtn */ > + outw(0x001, VT8237R_ACPI_IO_BASE + 0x04); > +} > + > +static void vt8237r_init(struct device *dev) > +{ > + u8 enables, byte; > + > + printk_debug("vt8237r init\n"); "VT8237R init", or maybe drop the whole comment? > + > + /* enable addr/data stepping */ > + byte = pci_read_config8(dev, PCI_COMMAND); > + byte |= PCI_COMMAND_WAIT; > + pci_write_config8(dev, PCI_COMMAND, byte); > + > + /* enable the internal I/O decode */ > + enables = pci_read_config8(dev, 0x6C); > + enables |= 0x80; > + pci_write_config8(dev, 0x6C, enables); > + > + /* FIXME Map 4MB of FLASH into the address space, > + this should be in CAR call */ Am I reading this correctly? This SB supports 4MB ROM chips then? > + /* pci_write_config8(dev, 0x41, 0x7f); */ > + > + /* Set bit 6 of 0x40, because Award does it (IO recovery time) "because AWARD does it" no good... > + IMPORTANT FIX - EISA = ECLR reg at 0x4d0! Decoding must be on so > that PCI > + interrupts can be properly marked as level triggered. */ > + enables = pci_read_config8(dev, 0x40); > + enables |= 0x44; > + pci_write_config8(dev, 0x40, enables); > + /* Line buffer control */ > + enables = pci_read_config8(dev, 0x42); > + enables |= 0xf8; > + pci_write_config8(dev, 0x42, enables); Oh, and please put an empty line after such "blocks" of enable-this-or-that lines... (easier to read) > + /* Delay Transaction Control */ > + pci_write_config8(dev, 0x43, 0xb); > + /* IO Recovery time */ > + pci_write_config8(dev, 0x4c, 0x44); > + /* ROM Memory Cycles Go To LPC */ > + pci_write_config8(dev, 0x59, 0x80); > + /* bypass Bypass APIC De-Assert Message, INTE#, INTF#, INTG#, INTH# as > PCI */ > + pci_write_config8(dev, 0x5B, 0xb); > + /* set Read Pass Write Control Enable (force A2 from APIC FSB to low) > */ > + pci_write_config8(dev, 0x48, 0x8c); > + /* Set 0x58 to 0x43 APIC and RTC */ > + pci_write_config8(dev, 0x58, 0x43); > + /* Set bit 3 of 0x4f (use INIT# as cpu reset) */ > + enables = pci_read_config8(dev, 0x4f); > + enables |= 0x08; > + pci_write_config8(dev, 0x4f, enables); > + /* enable serial irq, 6PCI clocks */ > + pci_write_config8(dev, 0x52, 0x9); > + /* enable HPET at: */ > + pci_write_config32(dev, 0x68, (VT8237R_HPET_ADDR | 0x80)); Maybe make it configurable via an hpet_enable variable? > + /* Power management setup */ > + setup_pm(dev); > + /* Start the rtc */ RTC > + rtc_init(0); > +} > + > +void vt8237r_read_resources(device_t dev) > +{ > + struct resource *res; > + > + pci_dev_read_resources(dev); > + /* fixed APIC resource */ > + res = new_resource(dev, 0x44); > + res->base = VT8237R_APIC_BASE; > + res->size = 256; > + res->limit = res->base + res->size - 1; > + res->align = 8; > + res->gran = 8; > + res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | > + IORESOURCE_STORED | IORESOURCE_ASSIGNED; > +} > + > +/** > + * The VT8237R is not a PCI bridge and has no resources of its own (other > + * than standard PC I/O addresses), however it does control the ISA bus > + * and so we need to manually call enable childrens resources on that bus. > + */ > +void vt8237r_enable_resources(device_t dev) > +{ > + pci_dev_enable_resources(dev); > + enable_childrens_resources(dev); > +} > + > +static void init_keyboard(struct device *dev) > +{ > + u8 regval; > + regval = pci_read_config8(dev, 0x51); > + if (regval & 0x1) > + init_pc_keyboard(0x60, 0x64, 0); > +} Hm, this is superio stuff usually. As the VT8237R integrates these kinds of functions I'm not sure how to procede. Extract the Superio-related stuff into src/superio/via/vt8237r/* or leave it here? Opinions? > + > +static void southbridge_init(struct device *dev) > +{ > + vt8237r_init(dev); > + pci_routing_fixup(dev); > + setup_ioapic(0xfec00000); Make 0xfec00000 a #define in *.h? It cannot change anyway right? In that case you can also drop the function parameter. > + setup_i8259(); > + init_keyboard(dev); What about other superio-stuff? Not done at all? Not available in the VT8237R? Yep, looks committable. Please repost with above fixes and Peters fixes. Uwe. -- http://www.hermann-uwe.de | http://www.holsham-traders.de http://www.crazy-hacks.org | http://www.unmaintained-free-software.org
signature.asc
Description: Digital signature
-- linuxbios mailing list linuxbios@linuxbios.org http://www.linuxbios.org/mailman/listinfo/linuxbios