[coreboot] [v3] VT8237R support

Carl-Daniel Hailfinger c-d.hailfinger.devel.2006 at gmx.net
Sun Aug 10 21:30:54 CEST 2008


Hi Corey,

this seems to have slipped through the cracks.

On 24.03.2008 07:08, Corey Osgood wrote:
> Add preliminary, as yet untested support for the vt8237r, based on the code in 
> coreboot v2. This will need some fixes, but at the very least it compiles and 
> should do smbus operations.
>
> Signed-off-by: Corey Osgood <corey.osgood at gmail.com>
>   

Can you repost an updated patch? V3 has changed quite a bit in the last
few months, especially considering PCI access functions and other stuff.

Review follows:

> Index: southbridge/via/vt8237r/vt8237r.c
> ===================================================================
> --- southbridge/via/vt8237r/vt8237r.c	(revision 0)
> +++ southbridge/via/vt8237r/vt8237r.c	(revision 0)
> @@ -0,0 +1,465 @@
> +/*
> + * This file is part of the coreboot project.
> + *
> + * Copyright (C) 2007 Rudolf Marek <r.marek at assembler.cz>
> + * Copyright (C) 2008 Corey Osgood <corey.osgood at gmail.com>
> + *
> + * 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 <types.h>
> +#include <console.h>
> +#include <device/device.h>
> +#include <device/pci.h>
> +#include <mc146818rtc.h>
> +#include <string.h>
> +#include <keyboard.h>
> +#include <io.h>
> +#include <legacy.h>
> +#include <statictree.h>
> +#include "vt8237r.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)
> +
> +static struct ioapicreg {
> +	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},
> +};
> +
> +static void setup_ioapic(u32 ioapic_base)
> +{
> +#if 0  /* Commented because lapicid() doesn't exist, yet */
>   

Can you add a #warning before the #if 0? That way, we won't forget it.

> +	u32 value_low, value_high, val;
> +	volatile u32 *l;
>   

There has been an effort to use readX/writeX functions instead of
volatile accesses. You may want to change that. Then again, I don't have
a strong opinion either way.

> +	int i;
> +
> +	/* All delivered to CPU0. */
> +	ioapic_table[0].value_high = (lapicid()) << (56 - 32);
>   

Can you use a #define for the magic 56?

> +	l = (unsigned long *)ioapic_base;
> +
> +	/* Set APIC to FSB message bus. */
> +	l[0] = 0x3;
>   

Magic values...

> +	val = l[4];
> +	l[4] = (val & 0xFFFFFE) | 1;
>   

The line above is equivalent to
l[4] = (val & 0xffffff) | 1;

You decide which one is clearer. Anyway, the 0xFFFFFE is magic.

> +
> +	/* 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 < ARRAY_SIZE(ioapic_table); i++) {
> +		l[0] = (ioapic_table[i].reg * 2) + 0x10;
> +		l[4] = ioapic_table[i].value_low;
> +		value_low = l[4];
> +		l[0] = (ioapic_table[i].reg * 2) + 0x11;
> +		l[4] = ioapic_table[i].value_high;
> +		value_high = l[4];
> +
> +		if ((i == 0) && (value_low == 0xffffffff)) {
> +			printk_warning("IO APIC not responding.\n");
> +			return;
> +		}
> +	}
>   

Reading the code sequence above hurts. You set l[0] and l[4] always in
combination. What about helper functions like set_apic() and get_apic()?

> +#endif
> +}
> +
> +/** Set up PCI IRQ routing, route everything through APIC. */
> +static void pci_routing_fixup(struct device *dev)
> +{
> +	/* PCI PNP Interrupt Routing INTE/F - disable */
> +	pci_write_config8(dev, 0x44, 0x00);
> +
> +	/* PCI PNP Interrupt Routing INTG/H - disable */
> +	pci_write_config8(dev, 0x45, 0x00);
> +
> +	/* Route INTE-INTH through registers above, no map to INTA-INTD. */
> +	pci_write_config8(dev, 0x46, 0x10);
> +
> +	/* PCI Interrupt Polarity */
> +	pci_write_config8(dev, 0x54, 0x00);
> +
> +	/* PCI INTA# Routing */
> +	pci_write_config8(dev, 0x55, 0x00);
> +
> +	/* PCI INTB#/C# Routing */
> +	pci_write_config8(dev, 0x56, 0x00);
> +
> +	/* PCI INTD# Routing */
> +	pci_write_config8(dev, 0x57, 0x00);
>   

Well-commented, but I'd appreciate #defines for the magic locations as
well. Your call, though.

> +}
> +
> +/**
> + * Set up the power management capabilities directly into ACPI mode.
> + * This avoids having to handle any System Management Interrupts (SMIs).
> + */
> +static void setup_pm(struct device *dev)
>   

A comment about which device this function is called with would be great.

> +{
> +	/* Debounce LID and PWRBTN# Inputs for 16ms. */
> +	pci_write_config8(dev, 0x80, 0x20);
> +
> +	/* Set ACPI base address to I/O VT8237R_ACPI_IO_BASE. */
> +	pci_write_config16(dev, 0x88, VT8237R_ACPI_IO_BASE | 0x1);
> +
> +	/* Set ACPI to 9, must 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 = Internal 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
> +	 */
> +	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);
> +
> +	/* FIXME: Intel needs more bit set for C2/C3. */
> +
> +	/* Allow SLP# signal to assert LDTSTOP_L.
> +	 * Will work for C3 and for FID/VID change.
> +	 */
> +	outb(0x1, VT8237R_ACPI_IO_BASE + 0x11);
> +}
> +
> +static void vt8237r_init(struct device *dev)
>   

Doxygen comment, please. Including a hint which PCI device this is
called with.

> +{
> +	u8 enables, byte;
> +
> +	/* 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.
>   

Not really. This belongs in hardware_stage1() or vt8237_stage1().

> +	 */
> +	/* pci_write_config8(dev, 0x41, 0x7f); */
> +
> +	/* Set bit 6 of 0x40 (I/O recovery time).
> +	 * 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);
> +
> +	/* Delay transaction control */
> +	pci_write_config8(dev, 0x43, 0xb);
> +
> +	/* I/O recovery time */
> +	pci_write_config8(dev, 0x4c, 0x44);
> +
> +	/* ROM memory cycles go to LPC. */
> +	pci_write_config8(dev, 0x59, 0x80);
> +
> +	/* 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 VT8237R_HPET_ADDR. */
> +	pci_write_config32(dev, 0x68, (VT8237R_HPET_ADDR | 0x80));
> +
> +	/* Power management setup */
> +	setup_pm(dev);
> +
> +	/* Start the RTC. */
> +	rtc_init(0);
> +}
> +
> +static void vt8237r_read_resources(struct device *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.
> + */
> +static void vt8237r_enable_resources(struct device *dev)
> +{
> +	pci_dev_enable_resources(dev);
> +	enable_childrens_resources(dev);
> +}
> +
> +static void init_keyboard(struct device *dev)
> +{
> +	u8 regval = pci_read_config8(dev, 0x51);
> +	if (regval & 0x1)
> +		init_pc_keyboard(0x60, 0x64, 0);
> +}
> +
> +static void vt8237r_lpc_init(struct device *dev)
> +{
> +	vt8237r_init(dev);
> +	pci_routing_fixup(dev);
> +	setup_ioapic(VT8237R_APIC_BASE);
> +	setup_i8259();
> +	init_keyboard(dev);
> +}
> +
> +static void vt8237r_ide_init(struct device *dev)
> +{
> +	struct southbridge_via_vt8237r_ide_config *sb =
> +	    (struct southbridge_via_vt8237r_ide_config *)dev->device_configuration;
> +
> +	u8 enables;
> +	u32 cablesel;
> +
> +	printk(BIOS_INFO, "%s IDE interface %s\n", "Primary",
> +		    sb->ide0_enable ? "enabled" : "disabled");
> +	printk(BIOS_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(BIOS_DEBUG, "Enables in reg 0x40 read back as 0x%x\n", enables);
> +
> +	/* Enable only compatibility mode. */
> +	enables = pci_read_config8(dev, IDE_CONF_II);
> +	enables &= ~0xc0;
>   

Magic 0xc0.

> +	pci_write_config8(dev, IDE_CONF_II, enables);
> +	enables = pci_read_config8(dev, IDE_CONF_II);
> +	printk(BIOS_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;
>   

Magic 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 Reg. 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);
> +
> +	/* Force interrupts to use compat mode. */
> +	pci_write_config8(dev, PCI_INTERRUPT_PIN, 0x0);
> +	pci_write_config8(dev, PCI_INTERRUPT_LINE, 0xff);
> +
> +	/* Cable guy... */
> +	cablesel = pci_read_config32(dev, IDE_UDMA);
> +	cablesel &= ~((1 << 28) | (1 << 20) | (1 << 12) | (1 << 4));
> +	cablesel |= (sb->ide0_80pin_cable << 28) |
> +		    (sb->ide0_80pin_cable << 20) |
> +		    (sb->ide1_80pin_cable << 12) |
> +		    (sb->ide1_80pin_cable << 4);
> +	pci_write_config32(dev, IDE_UDMA, cablesel);
> +}
> +
> +static void vt8237r_sata_init(struct device *dev)
> +{
> +	u8 reg;
> +
> +	printk(BIOS_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);
> +
> +}
> +
> +/* You can override or extend each operation as needed for the device. */
> +struct device_operations vt8237r_lpc = {
> +	.id = {.type = DEVICE_ID_PCI,
> +		.u = {.pci = {	.vendor = PCI_VENDOR_ID_VIA,
>   

Remove the ".u =" because this is now an anonymous union.

> +				.device = PCI_DEVICE_ID_VIA_VT8237R_LPC}}},
> +	.constructor		 = default_device_constructor,
> +	//.phase3_scan		 = 0,
> +	.phase4_read_resources	 = pci_dev_read_resources,
> +	.phase4_set_resources	 = pci_dev_set_resources,
> +	.phase4_enable_disable	 = 0,
> +	.phase5_enable_resources = pci_dev_enable_resources,
> +	.phase6_init		 = vt8237r_lpc_init,
> +	.ops_pci		 = &pci_dev_ops_pci,
> +};
> +
> +struct device_operations vt8237r_ide = {
> +	.id = {.type = DEVICE_ID_PCI,
> +		.u = {.pci = {	.vendor = PCI_VENDOR_ID_VIA, 
>   

.u removal

> +				.device = PCI_DEVICE_ID_VIA_VT82XXX_IDE}}},
> +	.constructor		 = default_device_constructor,
> +	.phase3_scan		 = 0,
> +	.phase4_read_resources	 = pci_dev_read_resources,
> +	.phase4_set_resources	 = pci_dev_set_resources,
> +	.phase4_enable_disable	 = 0,
> +	.phase5_enable_resources = pci_dev_enable_resources,
> +	.phase6_init		 = vt8237r_ide_init,
> +	.ops_pci		 = &pci_dev_ops_pci,
> +};
> +
> +struct device_operations vt8237r_sata = {
> +	.id = {.type = DEVICE_ID_PCI,
> +		.u = {.pci = {	.vendor = PCI_VENDOR_ID_VIA,
>   

.u removal

> +				.device = PCI_DEVICE_ID_VIA_VT8237R_SATA}}},
> +	.constructor		 = default_device_constructor,
> +	.phase3_scan		 = 0,
> +	.phase4_read_resources	 = pci_dev_read_resources,
> +	.phase4_set_resources	 = pci_dev_set_resources,
> +	.phase4_enable_disable	 = 0,
> +	.phase5_enable_resources = pci_dev_enable_resources,
> +	.phase6_init		 = vt8237r_sata_init,
> +	.ops_pci		 = &pci_dev_ops_pci,
> +};
> Index: southbridge/via/vt8237r/ide
> ===================================================================
> --- southbridge/via/vt8237r/ide	(revision 0)
> +++ southbridge/via/vt8237r/ide	(revision 0)
> @@ -0,0 +1,27 @@
> +/*
> + * This file is part of the coreboot project.
> + *
> + * Copyright (C) 2008 Corey Osgood <corey.osgood at gmail.com>
> + *
> + * 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
> + */
> +
> +{
> +	device_operations = "vt8237r_ide";
> +	ide0_enable = "1";
> +	ide0_80pin_cable = "0";
> +	ide1_enable = "0";
> +	ide1_80pin_cable = "0";
> +};
> Index: southbridge/via/vt8237r/vt8237r.h
> ===================================================================
> --- southbridge/via/vt8237r/vt8237r.h	(revision 0)
> +++ southbridge/via/vt8237r/vt8237r.h	(revision 0)
> @@ -0,0 +1,74 @@
> +/*
> + * This file is part of the coreboot project.
> + *
> + * Copyright (C) 2007 Rudolf Marek <r.marek at assembler.cz>
> + *
> + * 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_VT8237R_H
> +#define SOUTHBRIDGE_VIA_VT8237R_VT8237R_H
> +
> +/* Static resources for the 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 */
> +#define VT8237R_ACPI_IRQ		0x9
> +#define VT8237R_HPET_ADDR		0xfed00000ULL
> +#define VT8237R_APIC_BASE		0xfec00000ULL
> +
> +/* IDE */
> +#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
> +#define SATA_MISC_CTRL			0x45
> +
> +/* SMBus */
> +#define VT8237R_POWER_WELL		0x94
> +#define VT8237R_SMBUS_IO_BASE_REG	0xd0
> +#define VT8237R_SMBUS_HOST_CONF		0xd2
> +
> +#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 HOST_RESET 			0xff
> +/* 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
> +
> +#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
> +
> +#define SMBUS_DELAY() inb(0x80)
> +
> +void vt8237r_stage1(void);
> +
> +#endif
> Index: southbridge/via/vt8237r/stage1.c
> ===================================================================
> --- southbridge/via/vt8237r/stage1.c	(revision 0)
> +++ southbridge/via/vt8237r/stage1.c	(revision 0)
> @@ -0,0 +1,36 @@
> +/*
> + * This file is part of the coreboot project.
> + *
> + * Copyright (C) 2008 Corey Osgood <corey.osgood at gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 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 <statictree.h>
> +#include "vt8237r.h"
> +
> +void vt8237r_stage1(void)
> +{
> +/*	struct device *dev = dev_find_pci_device(PCI_VENDOR_ID_VIA,
> +				       PCI_DEVICE_ID_VIA_VT8237R_LPC, 0);
> +	struct southbridge_via_vt8237r_dts_config *sb =
> +	    (struct southbridge_via_vt8237r_dts_config *)dev->device_operations;
> +
> +	pci_write_config8(dev, 0x50, sb->fn_ctrl_lo);
> +	pci_write_config8(dev, 0x51, sb->fn_ctrl_hi);
> +*/
> +}
> +
> Index: southbridge/via/vt8237r/dts
> ===================================================================
> --- southbridge/via/vt8237r/dts	(revision 0)
> +++ southbridge/via/vt8237r/dts	(revision 0)
> @@ -0,0 +1,25 @@
> +/*
> + * This file is part of the coreboot project.
> + *
> + * Copyright (C) 2008 Corey Osgood <corey.osgood at gmail.com>
> + *
> + * 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
> + */
> +
> +{
> +	fn_ctrl_lo = "0x00"
> +	fn_ctrl_hi = "0x00"
> +	device_operations = "vt8237r_lpc";
> +};
> Index: southbridge/via/vt8237r/Makefile
> ===================================================================
> --- southbridge/via/vt8237r/Makefile	(revision 0)
> +++ southbridge/via/vt8237r/Makefile	(revision 0)
> @@ -0,0 +1,26 @@
> +##
> +## This file is part of the coreboot project.
> +##
> +## Copyright (C) 2008 Corey Osgood <corey.osgood at gmail.com>
> +##
> +## 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
> +##
> +
> +ifeq ($(CONFIG_SOUTHBRIDGE_VIA_VT8237R),y)
> +
> +STAGE2_CHIPSET_OBJ += $(obj)/southbridge/via/vt8237r/vt8237r.o
> +STAGE0_CHIPSET_OBJ += $(obj)/southbridge/via/vt8237r/stage1.o
> +
> +endif
> Index: southbridge/via/vt8237r/smbus_initram.c
> ===================================================================
> --- southbridge/via/vt8237r/smbus_initram.c	(revision 0)
> +++ southbridge/via/vt8237r/smbus_initram.c	(revision 0)
> @@ -0,0 +1,208 @@
> +/*
> + * This file is part of the coreboot project.
> + *
> + * Copyright (C) 2007-2008 Corey Osgood <corey.osgood at gmail.com>
> + * Copyright (C) 2007 Rudolf Marek <r.marek at assembler.cz>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 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 <types.h>
> +#include <console.h>
> +#include <io.h>
> +#include <device/pci_ids.h>
> +#include "vt8237r.h"
> +
> +/**
> + * Print an error, should it occur. If no error, just exit.
> + *
> + * @param host_status The data returned on the host status register after
> + *		      a transaction is processed.
> + * @param loops The number of times a transaction was attempted.
> + */
> +static void smbus_print_error(u8 host_status, int loops)
> +{
> +	/* Check if there actually was an error. */
> +	if ((host_status == 0x00 || host_status == 0x40 ||
> +	     host_status == 0x42) && (loops < SMBUS_TIMEOUT))
> +		return;
> +
> +	if (loops >= SMBUS_TIMEOUT)
> +		printk(BIOS_ERR, "SMBus timeout\r\n");
> +	if (host_status & (1 << 4))
> +		printk(BIOS_ERR, "Interrupt/SMI# was Failed Bus Transaction\r\n");
> +	if (host_status & (1 << 3))
> +		printk(BIOS_ERR, "Bus error\r\n");
> +	if (host_status & (1 << 2))
> +		printk(BIOS_ERR, "Device error\r\n");
> +	if (host_status & (1 << 1))
> +		printk(BIOS_DEBUG, "Interrupt/SMI# completed successfully\r\n");
> +	if (host_status & (1 << 0))
> +		printk(BIOS_ERR, "Host busy\r\n");
> +}
> +
> +/**
> + * Wait for the SMBus to become ready to process the next transaction.
> + */
> +static void smbus_wait_until_ready(void)
> +{
> +	int loops;
> +
> +	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);
> +}
> +
> +/**
> + * Reset and take ownership of the SMBus.
> + */
> +static void smbus_reset(void)
> +{
> +	outb(HOST_RESET, SMBHSTSTAT);
> +
> +	/* Datasheet says we have to read it to take ownership of SMBus. */
> +	inb(SMBHSTSTAT);
> +}
> +
> +/**
> + * Read a byte from the SMBus.
> + *
> + * @param dimm The address location of the DIMM on the SMBus.
> + * @param offset The offset the data is located at.
> + */
> +u8 smbus_read_byte(u8 dimm, u8 offset)
> +{
> +	u8 val;
> +
> +	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);
> +
> +	/* Start transaction, byte data read. */
> +	outb(0x48, SMBHSTCTL);
> +	SMBUS_DELAY();
> +	smbus_wait_until_ready();
> +
> +	val = inb(SMBHSTDAT0);
> +	/* Probably don't have to do this, but it can't hurt. */
> +	smbus_reset();
> +
> +	return val;
> +}
> +static void smbus_enable(void)
> +{
> +	struct device *dev;
> +
> +	/* Power management controller */
> +	dev = dev_find_pci_device(PCI_VENDOR_ID_VIA,
> +				       PCI_DEVICE_ID_VIA_VT8237R_LPC, 0);
> +
> +	if (dev == PCI_DEV_INVALID)
> +		die("Power management controller not found\r\n");
> +
> +	/* 7 = SMBus Clock from RTC 32.768KHz
> +	 * 5 = Internal PLL reset from susp
> +	 */
> +	pci_write_config8(dev, VT8237R_POWER_WELL, 0xa0);
> +
> +	/* Enable SMBus. */
> +	pci_write_config16(dev, VT8237R_SMBUS_IO_BASE_REG,
> +			   VT8237R_SMBUS_IO_BASE | 0x1);
> +
> +	/* SMBus Host Configuration, enable. */
> +	pci_write_config8(dev, VT8237R_SMBUS_HOST_CONF, 0x01);
> +
> +	/* Make it work for I/O. */
> +	pci_write_config16(dev, PCI_COMMAND, PCI_COMMAND_IO);
> +
> +	smbus_reset();
> +
> +	/* Reset the internal pointer. */
> +	inb(SMBHSTCTL);}
>   

What's that trailing "}"?

> +
> +}
> +
> +/**
> + * A fixup for some systems that need time for the SMBus to "warm up". This is 
> + * needed on some VT823x based systems, where the SMBus spurts out bad data for 
> + * a short time after power on. This has been seen on the VIA Epia series and 
> + * Jetway J7F2-series. It reads the ID byte from SMBus, looking for 
> + * known-good data from a slot/address. Exits on either good data or a timeout.
> + *
> + * TODO: This should probably go into some global file, but one would need to
> + *       be created just for it. If some other chip needs/wants it, we can
> + *       worry about it then.
> + *
> + * @param ctrl The memory controller and SMBus addresses.
> + */
> +void smbus_fixup(const struct mem_controller *ctrl)
> +{
> +	int i, ram_slots, current_slot = 0;
> +	u8 result = 0;
> +
> +	ram_slots = ARRAY_SIZE(ctrl->channel0);
> +	if (!ram_slots) {
> +		printk(BIOS_ERR, "smbus_fixup() thinks there are no RAM slots!\r\n");
> +		return;
> +	}
> +
> +	/*
> +	 * Bad SPD data should be either 0 or 0xff, but YMMV. So we look for
> +	 * the ID bytes of SDRAM, DDR, DDR2, and DDR3 (and anything in between).
> +	 * VT8237R has only been seen on DDR and DDR2 based systems, so far.
> +	 */
> +	for (i = 0; (i < SMBUS_TIMEOUT && ((result < SPD_MEMORY_TYPE_SDRAM) ||
> +				(result > SPD_MEMORY_TYPE_SDRAM_DDR3))); i++) {
> +
> +		if (current_slot > ram_slots)
> +			current_slot = 0;
> +
> +		result = smbus_read_byte(ctrl->channel0[current_slot],
> +					 SPD_MEMORY_TYPE);
> +		current_slot++;
> +		PRINT_DEBUG(".");
>   

printk() please.

> +	}
> +
> +	if (i >= SMBUS_TIMEOUT)
> +		print_err("SMBus timed out while warming up\r\n");
>   

printk() please.

> +	else
> +		PRINT_DEBUG("Done\r\n");
>   

printk() please.

> +}
> +
> +void enable_rom_decode(void)
> +{
> +	struct device *dev;
> +
> +	/* Bus Control and Power Management  */
> +	dev = dev_find_pci_device(PCI_VENDOR_ID_VIA,
> +				       PCI_DEVICE_ID_VIA_VT8237R_LPC, 0);
> +
> +	if (dev == PCI_DEV_INVALID)
> +		die("SB not found\r\n");
> +
> +	/* ROM decode last 1MB FFC00000 - FFFFFFFF */
> +	pci_write_config8(dev, 0x41, 0x7f);
> +}
> Index: Kconfig
> ===================================================================
> --- Kconfig	(revision 644)
> +++ Kconfig	(working copy)
> @@ -80,6 +80,8 @@
>  	boolean
>  config SOUTHBRIDGE_INTEL_I82371EB
>  	boolean
> +config SOUTHBRIDGE_VIA_VT8237R
> +	boolean
>  
>  # Super I/Os:
>  config SUPERIO_WINBOND_W83627HF
> Index: include/device/pci_ids.h
> ===================================================================
> --- include/device/pci_ids.h	(revision 644)
> +++ include/device/pci_ids.h	(working copy)
> @@ -155,4 +155,10 @@
>  #define PCI_VENDOR_ID_CIRRUS			0x1013
>  #define PCI_DEVICE_ID_CIRRUS_5446		0x00b8	/* Used by QEMU */
>  
> +/* Need to check these */
> +#define PCI_VENDOR_ID_VIA			0x1106
> +#define PCI_DEVICE_ID_VIA_VT8237R_LPC		0x3074
> +#define PCI_DEVICE_ID_VIA_VT82XXX_IDE		0x0571
> +#define PCI_DEVICE_ID_VIA_VT8237R_SATA		0x3149
> +
>  #endif /* DEVICE_PCI_IDS_H */
>
>
>   

I think with another iteration this will be golden.
Bonus points if you fix this in v2 as well.

Regards,
Carl-Daniel

-- 
http://www.hailfinger.org/





More information about the coreboot mailing list