nb/via/vx900: Drop support
Relocatable ramstage, postcar stage and C_ENVIRONMENT_BOOTBLOCK are now mandatory features, which this platform lacks. Change-Id: Ie971893da06fd3b1ac41dda398b1caeec3ee32db Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-on: https://review.coreboot.org/c/coreboot/+/36951 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Reviewed-by: Angel Pons <th3fanbus@gmail.com> Reviewed-by: HAOUAS Elyes <ehaouas@noos.fr> Reviewed-by: Nico Huber <nico.h@gmx.de>
This commit is contained in:
parent
4c38ed3c38
commit
0fd398a5a1
|
@ -1,48 +0,0 @@
|
|||
##
|
||||
## This file is part of the coreboot project.
|
||||
##
|
||||
## Copyright (C) 2011 Alexandru Gagniuc <mr.nuke.me@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.
|
||||
##
|
||||
|
||||
config NORTHBRIDGE_VIA_VX900
|
||||
bool
|
||||
select IOAPIC
|
||||
select DRIVERS_GENERIC_IOAPIC
|
||||
select HAVE_DEBUG_RAM_SETUP
|
||||
select HAVE_DEBUG_SMBUS
|
||||
select HAVE_CF9_RESET
|
||||
select NO_RELOCATABLE_RAMSTAGE
|
||||
|
||||
if NORTHBRIDGE_VIA_VX900
|
||||
|
||||
config MAX_PIRQ_LINKS
|
||||
int
|
||||
default 8
|
||||
|
||||
config MMCONF_BASE_ADDRESS
|
||||
hex
|
||||
default 0xe0000000
|
||||
|
||||
config MMCONF_BUS_NUMBER
|
||||
int
|
||||
default 256
|
||||
|
||||
config VGA_BIOS_ID
|
||||
string
|
||||
default "1106,7122"
|
||||
|
||||
config BOOTBLOCK_NORTHBRIDGE_INIT
|
||||
string
|
||||
default "northbridge/via/vx900/bootblock.c"
|
||||
|
||||
endif
|
|
@ -1,50 +0,0 @@
|
|||
##
|
||||
## This file is part of the coreboot project.
|
||||
##
|
||||
## Copyright (C) 2011-2013 Alexandru Gagniuc <mr.nuke.me@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.
|
||||
##
|
||||
|
||||
ifeq ($(CONFIG_NORTHBRIDGE_VIA_VX900),y)
|
||||
|
||||
romstage-y += pci_util.c
|
||||
romstage-y += early_smbus.c
|
||||
romstage-y += early_vx900.c
|
||||
romstage-y += early_host_bus_ctl.c
|
||||
romstage-y += raminit_ddr3.c
|
||||
romstage-y += memmap.c
|
||||
romstage-y += ./../../../device/dram/ddr3.c
|
||||
romstage-y += ./../../../southbridge/via/common/early_smbus_delay.c
|
||||
romstage-y += ./../../../southbridge/via/common/early_smbus_is_busy.c
|
||||
romstage-y += ./../../../southbridge/via/common/early_smbus_print_error.c
|
||||
romstage-y += ./../../../southbridge/via/common/early_smbus_reset.c
|
||||
romstage-y += ./../../../southbridge/via/common/early_smbus_wait_until_ready.c
|
||||
|
||||
ramstage-y += pci_util.c
|
||||
ramstage-y += pcie.c
|
||||
ramstage-y += northbridge.c
|
||||
ramstage-y += chrome9hd.c
|
||||
ramstage-y += traf_ctrl.c
|
||||
ramstage-y += sata.c
|
||||
ramstage-y += lpc.c
|
||||
ramstage-y += memmap.c
|
||||
|
||||
# The buildsystem only includes this file if CONFIG_VGA is selected.
|
||||
# We need to do some VGA I/O before the VGA can be initialized. We can make good
|
||||
# use of some of the functions there, so include them unconditionally
|
||||
ramstage-y += ./../../../drivers/pc80/vga/vga_io.c
|
||||
|
||||
|
||||
bootblock-y += romstrap.ld
|
||||
bootblock-y += romstrap.S
|
||||
|
||||
endif
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2017 Lubomir Rintel <lkundrak@v3.sk>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <device/pci_ops.h>
|
||||
|
||||
#if CONFIG_ROM_SIZE == 0x80000
|
||||
# define ROM_DECODE_MAP 0x00
|
||||
#elif CONFIG_ROM_SIZE == 0x100000
|
||||
# define ROM_DECODE_MAP 0x40
|
||||
#elif CONFIG_ROM_SIZE == 0x180000
|
||||
# define ROM_DECODE_MAP 0x60
|
||||
#elif CONFIG_ROM_SIZE == 0x200000
|
||||
# define ROM_DECODE_MAP 0x70
|
||||
#elif CONFIG_ROM_SIZE == 0x280000
|
||||
# define ROM_DECODE_MAP 0x78
|
||||
#elif CONFIG_ROM_SIZE == 0x300000
|
||||
# define ROM_DECODE_MAP 0x7c
|
||||
#elif CONFIG_ROM_SIZE == 0x380000
|
||||
# define ROM_DECODE_MAP 0x7e
|
||||
#elif CONFIG_ROM_SIZE == 0x400000
|
||||
# define ROM_DECODE_MAP 0x7f
|
||||
#else
|
||||
# error "Bad CONFIG_ROM_SIZE"
|
||||
#endif
|
||||
|
||||
static void bootblock_northbridge_init(void)
|
||||
{
|
||||
u8 reg;
|
||||
|
||||
pci_io_read_config8(PCI_DEV(0, 0x11, 0), 0x41);
|
||||
reg |= ROM_DECODE_MAP;
|
||||
pci_io_write_config8(PCI_DEV(0, 0x11, 0), 0x41, reg);
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@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.
|
||||
*/
|
||||
|
||||
#ifndef __VIA_VX900_CHIP_H__
|
||||
#define __VIA_VX900_CHIP_H__
|
||||
|
||||
struct northbridge_via_vx900_config {
|
||||
/**
|
||||
* \brief PCIe Lane[3:0] Function Select
|
||||
*
|
||||
* PCIe Lane3~Lane0 (PEXTX[3:0]P/VCC) can be used by the integrated
|
||||
* graphic controller to output its display data. The PCIe lanes will
|
||||
* be used to output DisplayPort data.
|
||||
*/
|
||||
u8 assign_pex_to_dp;
|
||||
|
||||
/**
|
||||
* \brief Lane Width for Root Port 1
|
||||
*
|
||||
* Two PCIe lanes are used for Root port 1. Root port 2 is disabled.
|
||||
*/
|
||||
u8 pcie_port1_2_lane_wide;
|
||||
|
||||
/**
|
||||
* \brief PIRQ line to which to route the external interrupt
|
||||
*
|
||||
* The VX900 features an external interrupt which can be routed to any
|
||||
* of the PIRQA->PIRQH lines. Usually, on-board devices are connected
|
||||
* to the external interrupt. In some vendor BIOS's pirq table, this
|
||||
* appears as link 9.
|
||||
*
|
||||
* Setting this line only affects the behavior of the integrated PIC. It
|
||||
* has no effect on the IOAPIC.
|
||||
*
|
||||
* The value of this register must be a literal upper-case character
|
||||
* from 'A' to 'H'.
|
||||
*/
|
||||
char ext_int_route_to_pirq;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,277 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@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.
|
||||
*/
|
||||
|
||||
#include <device/pci_ops.h>
|
||||
#include <console/console.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ids.h>
|
||||
#include <pc80/vga_io.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "vx900.h"
|
||||
|
||||
/**
|
||||
* @file chrome9hd.c
|
||||
*
|
||||
* \brief Initialization for Chrome9HD integrated graphics adapters
|
||||
*
|
||||
* This takes care of the initialization we need to do before calling the VGA
|
||||
* BIOS. The device is not documented in the VX900 datasheet.
|
||||
*
|
||||
* The device is documented in:
|
||||
* Open Graphics Programming Manual
|
||||
* Chrome9GraphicsHD Processor
|
||||
* VX900 Series System Processor
|
||||
* Part I: Graphics Core / 2D
|
||||
*
|
||||
* This document was released by VIA to the Xorg project, and is available at:
|
||||
* <http://www.x.org/docs/via/OGPM_Chrome9%20HD%20DX9%20_R100_PartI_Core_2D.pdf>
|
||||
*
|
||||
* STATUS:
|
||||
* We do the minimal initialization described in VIA documents. Running the VGA
|
||||
* option ROM does not get us a usable display. We configure the framebuffer and
|
||||
* the IGP is able to use it. GRUB2 and linux are capable of getting a usable
|
||||
* text console, which uses the monitor's native resolution (even 1920x1080).
|
||||
* The graphical console (linux) does not work properly.
|
||||
* @todo
|
||||
* 1. Figure out what sequence we need to do to get the VGA BIOS running
|
||||
* properly. Use the code provided by VIA and compare their sequence to ours,
|
||||
* fill in any missing steps, etc.
|
||||
* 2. Make BAR2 and the framebuffer use the same memory space. This is a feature
|
||||
* called "Direct framebuffer access" which allows us to save memory space by
|
||||
* setting BAR2 of the VGA to the location in memory of the framebuffer. This
|
||||
* reduces the amount of PCI MMIO space we need below 4G, and is especially
|
||||
* useful considering we only have 8GB (33 bits) of memory-mapped space.
|
||||
*/
|
||||
|
||||
/**
|
||||
* vx900_int15
|
||||
*
|
||||
* \brief INT15 helpers for Chrome9HD IGP
|
||||
*
|
||||
* The following are helpers for INT15 handlers for the VGA BIOS. The full set
|
||||
* of INT15 callbacks is described in
|
||||
*
|
||||
* VIA/S3Graphics
|
||||
* Video BIOS External Interface Specification for Chrome9 Series IGP
|
||||
* VX900 Series
|
||||
*
|
||||
* This document is only available under NDA, however, the callbacks are very
|
||||
* similar to other VIA/Intel IGP callbacks.
|
||||
*
|
||||
* Callback 0x5f18 is the most important one. It informs the VGA BIOS of the
|
||||
* RAM speed and framebuffer size. The other callbacks seem to be optional.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Get X86_BL value for VGA INT15 function 5f18
|
||||
*
|
||||
* Int15 5f18 lets the VGA BIOS know the framebuffer size and the memory speed.
|
||||
* This handler is very important. If it is not implemented, the VGA BIOS will
|
||||
* not work correctly.
|
||||
*
|
||||
* To use, just call this from the 15f18 handler, and place the return value in
|
||||
* X86_BL
|
||||
*
|
||||
* @code{.c}
|
||||
* case 0x5f18:
|
||||
* X86_BX = vx900_int15_get_5f18_bl();
|
||||
* res = 0;
|
||||
* break;
|
||||
* @endcode
|
||||
*
|
||||
*/
|
||||
u8 vx900_int15_get_5f18_bl(void)
|
||||
{
|
||||
u8 reg8, ret;
|
||||
struct device *dev;
|
||||
/*
|
||||
* BL Bit[7:4]
|
||||
* Memory Data Rate (not to be confused with fCLK)
|
||||
* 0000: 66MHz
|
||||
* 0001: 100MHz
|
||||
* 0010: 133MHz
|
||||
* 0011: 200MHz (DDR200)
|
||||
* 0100: 266MHz (DDR266)
|
||||
* 0101: 333MHz (DDR333)
|
||||
* 0110: 400MHz (DDR400)
|
||||
* 0111: 533MHz (DDR I/II 533)
|
||||
* 1000: 667MHz (DDR I/II 667)
|
||||
* 1001: 800MHz (DDR3 800)
|
||||
* 1010: 1066MHz (DDR3 1066)
|
||||
* 1011: 1333MHz (DDR3 1333)
|
||||
* Bit[3:0]
|
||||
* N: Frame Buffer Size 2^N MB
|
||||
*/
|
||||
dev = pcidev_on_root(0, 3);
|
||||
reg8 = pci_read_config8(dev, 0xa1);
|
||||
ret = (u32) ((reg8 & 0x70) >> 4) + 2;
|
||||
reg8 = pci_read_config8(dev, 0x90);
|
||||
reg8 = ((reg8 & 0x07) + 3) << 4;
|
||||
ret |= (u32) reg8;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
static void chrome9hd_set_sid_vid(u16 vendor, u16 device)
|
||||
{
|
||||
vga_sr_write(0x36, vendor >> 8); /* SVID high byte */
|
||||
vga_sr_write(0x35, vendor & 0xff); /* SVID low byte */
|
||||
vga_sr_write(0x38, device >> 8); /* SID high byte */
|
||||
vga_sr_write(0x37, device & 0xff); /* SID low byte */
|
||||
}
|
||||
|
||||
static void chrome9hd_handle_uma(struct device *dev)
|
||||
{
|
||||
u8 fb_pow = vx900_get_chrome9hd_fb_pow();
|
||||
|
||||
if (fb_pow == 0)
|
||||
return;
|
||||
|
||||
/* Step 7 - Let GFX know the framebuffer size (through PCI and IOCTL)
|
||||
* The size we set here affects the behavior of BAR2, and the amount of
|
||||
* MMIO space it requests. The default is 512MB, so if we don't set this
|
||||
* before reading the resources, we could waste space below 4G */
|
||||
pci_write_config8(dev, 0xb2, ((0xff << (fb_pow - 2)) & ~(1 << 7)));
|
||||
vga_sr_write(0x68, (0xff << (fb_pow - 1)));
|
||||
/* And also that the framebuffer is in the system, RAM */
|
||||
pci_or_config8(dev, 0xb0, 1 << 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initialization sequence before running the VGA BIOS
|
||||
*
|
||||
* This is the initialization sequence described in:
|
||||
*
|
||||
* BIOS Porting Guide
|
||||
* VX900 Series
|
||||
* All-in-One System Processor
|
||||
*
|
||||
* This document is only available under NDA.
|
||||
*/
|
||||
static void chrome9hd_biosguide_init_seq(struct device *dev)
|
||||
{
|
||||
struct device *mcu = dev_find_device(PCI_VENDOR_ID_VIA,
|
||||
PCI_DEVICE_ID_VIA_VX900_MEMCTRL, 0);
|
||||
struct device *host = dev_find_device(PCI_VENDOR_ID_VIA,
|
||||
PCI_DEVICE_ID_VIA_VX900_HOST_BR, 0);
|
||||
|
||||
/* Step 1 - Enable VGA controller */
|
||||
/* FIXME: This is the VGA hole @ 640k-768k, and the vga port io
|
||||
* We need the port IO, but can we disable the memory hole? */
|
||||
pci_or_config8(mcu, 0xa4, (1 << 7)); /* VGA memory hole */
|
||||
|
||||
/* Step 2 - Forward MDA cycles to GFX */
|
||||
pci_or_config8(host, 0x4e, (1 << 1));
|
||||
|
||||
/* Step 3 - Enable GFX I/O space */
|
||||
pci_or_config8(dev, PCI_COMMAND, PCI_COMMAND_IO);
|
||||
|
||||
/* Step 4 - Enable video subsystem */
|
||||
vga_enable_mask((1 << 0), (1 << 0));
|
||||
|
||||
/* FIXME: VGA IO Address Select. 3B5 or 3D5? */
|
||||
vga_misc_mask((1 << 0), (1 << 0));
|
||||
|
||||
/* Step 5 - Unlock accessing of IO space */
|
||||
vga_sr_write(0x10, 0x01);
|
||||
|
||||
chrome9hd_handle_uma(dev);
|
||||
|
||||
uint64_t gfx_base = get_uma_memory_base();
|
||||
if (gfx_base == 0)
|
||||
die("uma_memory_base not set. Abandon ship!\n");
|
||||
|
||||
/* Step 8 - Enable memory base register on the GFX */
|
||||
vga_sr_write(0x6d, (gfx_base >> 21) & 0xff); /* base 28:21 */
|
||||
vga_sr_write(0x6e, (gfx_base >> 29) & 0xff); /* base 36:29 */
|
||||
vga_sr_write(0x6f, 0x00); /* base 43:37 */
|
||||
|
||||
/* Step 9 - Set SID/VID */
|
||||
chrome9hd_set_sid_vid(0x1106, 0x7122);
|
||||
|
||||
}
|
||||
|
||||
static void chrome9hd_init(struct device *dev)
|
||||
{
|
||||
printk(BIOS_DEBUG, "======================================================\n");
|
||||
printk(BIOS_DEBUG, "== Chrome9 HD INIT\n");
|
||||
printk(BIOS_DEBUG, "======================================================\n");
|
||||
|
||||
chrome9hd_biosguide_init_seq(dev);
|
||||
|
||||
/* Prime PLL FIXME: bad comment */
|
||||
vga_sr_mask(0x3c, 1 << 2, 1 << 2);
|
||||
|
||||
/* FIXME: recheck; VGA IO Address Select. 3B5 or 3D5? */
|
||||
vga_misc_mask(1 << 0, 1 << 0);
|
||||
|
||||
/* FIXME: recheck; Enable Base VGA 16 Bits Decode */
|
||||
|
||||
u32 fb_address = pci_read_config32(dev, PCI_BASE_ADDRESS_2);
|
||||
fb_address &= ~0x0F;
|
||||
if (!fb_address) {
|
||||
printk(BIOS_WARNING, "Chrome9HD: No FB BAR assigned!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printk(BIOS_INFO, "Chrome: Using %dMB Framebuffer at 0x%08X.\n",
|
||||
256, fb_address);
|
||||
|
||||
printk(BIOS_DEBUG, "Initializing VGA...\n");
|
||||
|
||||
pci_dev_init(dev);
|
||||
|
||||
printk(BIOS_DEBUG, "Enable VGA console\n");
|
||||
|
||||
dump_pci_device(PCI_BDF(dev));
|
||||
}
|
||||
|
||||
static void chrome9hd_enable(struct device *dev)
|
||||
{
|
||||
struct device *mcu = dev_find_device(PCI_VENDOR_ID_VIA,
|
||||
PCI_DEVICE_ID_VIA_VX900_MEMCTRL, 0);
|
||||
/* FIXME: here? -=- ACLK 250MHz */
|
||||
pci_or_config8(mcu, 0xbb, 0x01);
|
||||
}
|
||||
|
||||
static void chrome9hd_disable(struct device *dev)
|
||||
{
|
||||
struct device *mcu = dev_find_device(PCI_VENDOR_ID_VIA,
|
||||
PCI_DEVICE_ID_VIA_VX900_MEMCTRL, 0);
|
||||
/* Disable GFX - This step effectively renders the GFX inert
|
||||
* It won't even show up as a PCI device during enumeration */
|
||||
pci_update_config8(mcu, 0xa1, (u8)~(1 << 7), 0);
|
||||
}
|
||||
|
||||
static struct device_operations chrome9hd_operations = {
|
||||
.read_resources = pci_dev_read_resources,
|
||||
.set_resources = pci_dev_set_resources,
|
||||
.enable_resources = pci_dev_enable_resources,
|
||||
.init = chrome9hd_init,
|
||||
.disable = chrome9hd_disable,
|
||||
.enable = chrome9hd_enable,
|
||||
.ops_pci = 0,
|
||||
};
|
||||
|
||||
static const struct pci_driver chrome9hd_driver __pci_driver = {
|
||||
.ops = &chrome9hd_operations,
|
||||
.vendor = PCI_VENDOR_ID_VIA,
|
||||
.device = PCI_DEVICE_ID_VIA_VX900_VGA,
|
||||
};
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@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.
|
||||
*/
|
||||
|
||||
#include <device/pci_ops.h>
|
||||
|
||||
#include "early_vx900.h"
|
||||
|
||||
static void vx900_cpu_bus_preram_setup(void)
|
||||
{
|
||||
/* Faster CPU to DRAM Cycle */
|
||||
pci_update_config8(HOST_BUS, 0x50, ~0x0f, 0x08);
|
||||
/* CPU Interface Control - Basic Options */
|
||||
pci_or_config8(HOST_BUS, 0x51, 0x6c);
|
||||
/*CPU Interface Control - Advanced Options */
|
||||
pci_write_config8(HOST_BUS, 0x52, 0xc7);
|
||||
/* Enable 8QW burst and 4QW request merging [4] and [2]
|
||||
* and special mode for read cycles bit[3] */
|
||||
pci_or_config8(HOST_BUS, 0x54, (1 << 4) | (1 << 2) | (1 << 3));
|
||||
/* High priority upstream requests on V4 bus */
|
||||
pci_write_config8(HOST_BUS, 0x56, 0x03);
|
||||
/* CPU to DRAM extra 1T access control */
|
||||
pci_or_config8(HOST_BUS, 0x59, (1 << 2));
|
||||
/* Queue reordering */
|
||||
pci_or_config8(HOST_BUS, 0x5f, (1 << 6));
|
||||
/* Only Write cycle of CPU->GFXCTL will flush the CPU->Memory FIFO */
|
||||
pci_or_config8(HOST_BUS, 0x98, 0x60);
|
||||
/* 1T delay for data on CPU bus */
|
||||
pci_write_config8(HOST_BUS, 0x9e, 0x0e);
|
||||
/* Arbitrate ownership of DRAM controller a few cycles earlier */
|
||||
pci_or_config8(HOST_BUS, 0x9f, (1 << 7));
|
||||
/* Write retire policy */
|
||||
pci_write_config8(HOST_BUS, 0x5d, 0xa2);
|
||||
/* Occupancy timer */
|
||||
pci_write_config8(HOST_BUS, 0x53, 0x44);
|
||||
/* Medium Threshold for Write Retire Policy - 6 requests */
|
||||
pci_or_config8(HOST_BUS, 0x56, 0x60);
|
||||
/* Bandwidth timer */
|
||||
pci_write_config8(HOST_BUS, 0x5e, 0x44);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure the CPU to northbridge bus (formerly, FSB)
|
||||
*
|
||||
* Configure the CPU <-> host interface. This interface is complex and needs to
|
||||
* be set up to operate properly. Configured parameters include bandwidth
|
||||
* arbitration. This function does not, however, change the physical interface
|
||||
* parameters, such as drive strength and signal timing. Instead, it assumes
|
||||
* that those parameters were already configured correctly from the ROMSTRAP.
|
||||
*/
|
||||
void vx900_cpu_bus_interface_setup(void)
|
||||
{
|
||||
vx900_cpu_bus_preram_setup();
|
||||
|
||||
dump_pci_device(HOST_BUS);
|
||||
}
|
|
@ -1,193 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2011 Alexandru Gagniuc <mr.nuke.me@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.
|
||||
*/
|
||||
|
||||
#include <device/pci_ids.h>
|
||||
#include "early_vx900.h"
|
||||
#include <device/early_smbus.h>
|
||||
|
||||
#include <arch/io.h>
|
||||
#include <device/pci_ops.h>
|
||||
#include <console/console.h>
|
||||
|
||||
/**
|
||||
* \brief SMBUS IO ports in relation to the base IO port
|
||||
*/
|
||||
#define SMBHSTSTAT(base) (u16)(u32)base + 0x0
|
||||
#define SMBSLVSTAT(base) (u16)(u32)base + 0x1
|
||||
#define SMBHSTCTL(base) (u16)(u32)base + 0x2
|
||||
#define SMBHSTCMD(base) (u16)(u32)base + 0x3
|
||||
#define SMBXMITADD(base) (u16)(u32)base + 0x4
|
||||
#define SMBHSTDAT0(base) (u16)(u32)base + 0x5
|
||||
#define SMBHSTDAT1(base) (u16)(u32)base + 0x6
|
||||
#define SMBBLKDAT(base) (u16)(u32)base + 0x7
|
||||
#define SMBSLVCTL(base) (u16)(u32)base + 0x8
|
||||
#define SMBTRNSADD(base) (u16)(u32)base + 0x9
|
||||
#define SMBSLVDATA (base) (u16)(u32)base + 0xa
|
||||
|
||||
static void smbus_delays(int delays)
|
||||
{
|
||||
while (delays--)
|
||||
smbus_delay();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a byte from the SMBus.
|
||||
*
|
||||
* @param smbus_dev The PCI address of the SMBus device .
|
||||
* @param addr The address location of the DIMM on the SMBus.
|
||||
* @param offset The offset the data is located at.
|
||||
*/
|
||||
u8 smbus_read_byte(u32 smbus_dev, u8 addr, u8 offset)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
/* Initialize SMBUS sequence */
|
||||
smbus_reset(smbus_dev);
|
||||
/* Clear host data port. */
|
||||
outb(0x00, SMBHSTDAT0(smbus_dev));
|
||||
|
||||
smbus_wait_until_ready(smbus_dev);
|
||||
smbus_delays(50);
|
||||
|
||||
/* Actual addr to reg format. */
|
||||
addr = (addr << 1);
|
||||
addr |= 1; /* read command */
|
||||
outb(addr, SMBXMITADD(smbus_dev));
|
||||
outb(offset, SMBHSTCMD(smbus_dev));
|
||||
/* Start transaction, byte data read. */
|
||||
outb(0x48, SMBHSTCTL(smbus_dev));
|
||||
smbus_wait_until_ready(smbus_dev);
|
||||
|
||||
val = inb(SMBHSTDAT0(smbus_dev));
|
||||
return val;
|
||||
}
|
||||
|
||||
void enable_smbus(void)
|
||||
{
|
||||
pci_devfn_t dev;
|
||||
u8 reg8;
|
||||
u32 smbus_dev = (u32) SMBUS_IO_BASE;
|
||||
|
||||
/* Locate the Power Management control */
|
||||
dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA,
|
||||
PCI_DEVICE_ID_VIA_VX900_LPC), 0);
|
||||
|
||||
if (dev == PCI_DEV_INVALID) {
|
||||
die("Power Management Controller not found\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* To use SMBus to manage devices on the system board, it is a must to
|
||||
* enable SMBus function by setting
|
||||
* PMU_RXD2[0] (SMBus Controller Enable) to 1.
|
||||
* And set PMU_RXD0 and PMU_RXD1 (SMBus I/O Base) to an appropriate
|
||||
* I/O port address, so that all registers in SMBus I/O port can be
|
||||
* accessed.
|
||||
*/
|
||||
|
||||
reg8 = pci_read_config8(dev, 0xd2);
|
||||
/* Enable SMBus controller */
|
||||
reg8 |= 1;
|
||||
/* Set SMBUS clock from 128k source */
|
||||
reg8 |= 1 << 2;
|
||||
pci_write_config8(dev, 0xd2, reg8);
|
||||
|
||||
reg8 = pci_read_config8(dev, 0x94);
|
||||
/* SMBUS clock from divider of 14.318 MHz */
|
||||
reg8 &= ~(1 << 7);
|
||||
pci_write_config8(dev, 0x94, reg8);
|
||||
|
||||
/* Set SMBus IO base */
|
||||
pci_write_config16(dev, 0xd0, SMBUS_IO_BASE);
|
||||
|
||||
/*
|
||||
* Initialize the SMBus sequence:
|
||||
*/
|
||||
/* Clear SMBus host status register */
|
||||
smbus_reset(smbus_dev);
|
||||
/* Clear SMBus host data 0 register */
|
||||
outb(0x00, SMBHSTDAT0(smbus_dev));
|
||||
|
||||
/* Wait for SMBUS */
|
||||
smbus_wait_until_ready(smbus_dev);
|
||||
|
||||
}
|
||||
|
||||
static int spd_get_length(u8 spd_byte0)
|
||||
{
|
||||
spd_byte0 &= 0xf;
|
||||
|
||||
switch (spd_byte0) {
|
||||
case 0x3:
|
||||
return 256;
|
||||
case 0x2:
|
||||
return 176;
|
||||
case 0x1:
|
||||
return 128;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void spd_read(u8 addr, spd_raw_data spd)
|
||||
{
|
||||
u8 reg;
|
||||
int i, regs;
|
||||
u32 smbus_dev = SMBUS_IO_BASE;
|
||||
|
||||
reg = smbus_read_byte(smbus_dev, addr, 2);
|
||||
if (reg != 0x0b) {
|
||||
printk(BIOS_DEBUG, "SMBUS device %x not a DDR3 module\n", addr);
|
||||
spd[2] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
reg = smbus_read_byte(smbus_dev, addr, 0);
|
||||
if ((regs = spd_get_length(reg)) == 0) {
|
||||
printk(BIOS_INFO, "No DIMM present at %x\n", addr);
|
||||
spd[2] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < regs; i++)
|
||||
spd[i] = smbus_read_byte(smbus_dev, addr, i);
|
||||
}
|
||||
|
||||
void dump_spd_data(spd_raw_data spd)
|
||||
{
|
||||
int len, i;
|
||||
u8 reg;
|
||||
|
||||
if ((len = spd_get_length(spd[0])) == 0) {
|
||||
printk(BIOS_DEBUG, "Invalid SPD\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* I originally saw this way to present SPD data in code from VIA. I
|
||||
* really liked the idea, so here it goes.
|
||||
*/
|
||||
printk(BIOS_DEBUG, " 00 01 02 03 04 05 06 07 07 09 0A 0B 0C 0D 0E 0F\n");
|
||||
printk(BIOS_DEBUG, "---+------------------------------------------------");
|
||||
for (i = 0; i < len; i++) {
|
||||
reg = spd[i];
|
||||
if ((i & 0x0f) == 0)
|
||||
printk(BIOS_DEBUG, "\n%.2x |", i);
|
||||
printk(BIOS_DEBUG, " %.2x", reg);
|
||||
}
|
||||
printk(BIOS_DEBUG, "\n");
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@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.
|
||||
*/
|
||||
|
||||
#include "early_vx900.h"
|
||||
#include <device/pci_ops.h>
|
||||
#include <console/console.h>
|
||||
|
||||
/**
|
||||
* \brief Enable accessing of PCI configuration space for all devices.
|
||||
*
|
||||
* Enable accessing of D0F1 through D0F7, which would otherwise not be
|
||||
* accessible. If MMCONF is enabled, configure it here. This is the first
|
||||
* function that should be called in romstage.
|
||||
*/
|
||||
void vx900_enable_pci_config_space(void)
|
||||
{
|
||||
/* MMCONF is not yet enabled, so we'll need to specify we want to do
|
||||
* pci_io. We don't want to do pci_mmio until we enable it */
|
||||
/* Enable multifunction bit for northbridge.
|
||||
* This enables the PCI configuration spaces of D0F1 to D0F7 to be
|
||||
* accessed */
|
||||
pci_io_write_config8(HOST_CTR, 0x4f, 0x01);
|
||||
|
||||
/* COOL, now enable MMCONF */
|
||||
u8 reg8 = pci_io_read_config8(TRAF_CTR, 0x60);
|
||||
reg8 |= 3;
|
||||
pci_io_write_config8(TRAF_CTR, 0x60, reg8);
|
||||
|
||||
reg8 = CONFIG_MMCONF_BASE_ADDRESS >> 28;
|
||||
pci_io_write_config8(TRAF_CTR, 0x61, reg8);
|
||||
}
|
||||
|
||||
/**
|
||||
*\brief Prints information regarding the hardware strapping on VX900
|
||||
*
|
||||
* Certain features on the VX900 are controlled by strapping pins which are
|
||||
* hardwired on the mainboard. These values determine whether the ROM is on the
|
||||
* SPI or LPC bus, or whether auto-reset is enabled.
|
||||
* \n
|
||||
* Having a feel for these values is important when trying to fix obscure
|
||||
* problems found when porting a mainboard based on the VX900.
|
||||
* \n
|
||||
* These values are decoded and printed to the terminal.
|
||||
*/
|
||||
void vx900_print_strapping_info(void)
|
||||
{
|
||||
u8 strap = pci_read_config8(SNMIC, 0x56);
|
||||
|
||||
printk(BIOS_DEBUG, "VX900 strapping pins indicate that:\n");
|
||||
printk(BIOS_DEBUG, " ROM is on %s bus\n",
|
||||
(strap & (1 << 0)) ? "SPI" : "LPC");
|
||||
printk(BIOS_DEBUG, " Auto reset is %s\n",
|
||||
(strap & (1 << 1)) ? "disabled" : "enabled");
|
||||
printk(BIOS_DEBUG, " LPC FWH command is %s\n",
|
||||
(strap & (1 << 2)) ? "enabled" : "disabled");
|
||||
printk(BIOS_DEBUG, " Debug link is is %s\n",
|
||||
(strap & (1 << 4)) ? "enabled" : "disabled");
|
||||
printk(BIOS_DEBUG, " PCI master mode is %s\n",
|
||||
(strap & (1 << 5)) ? "enabled" : "disabled");
|
||||
}
|
||||
|
||||
/**
|
||||
*\brief Disables the auto-reboot mechanism on VX900
|
||||
*
|
||||
* The VX900 has an auto-reboot mechanism that can be enabled by a hardware
|
||||
* strap. This mechanism can make development annoying, since we don't know if
|
||||
* the reset was caused by a bug in coreboot, or by this mechanism.
|
||||
*/
|
||||
void vx900_disable_auto_reboot(void)
|
||||
{
|
||||
if (pci_read_config8(SNMIC, 0x56) & (1 << 1)) {
|
||||
printk(BIOS_DEBUG, "Auto-reboot is disabled in hardware\n");
|
||||
return;
|
||||
}
|
||||
/* Disable the GP3 timer, which is the root of all evil */
|
||||
pci_write_config8(LPC, 0x98, 0);
|
||||
/* Yep, that's all it takes */
|
||||
printk(BIOS_DEBUG, "GP3 timer disabled."
|
||||
" Auto-reboot should not give you any more trouble.\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disables 'shadowing' of system ROM
|
||||
*
|
||||
* Disable unnecessary shadowing of the ROM in the first 1MB of address space.
|
||||
* coreboot runs in 32-bit mode from the start. Shadowing only gets in the way.
|
||||
* This function frees the entire 640k-1M range for DRAM. VGA may still use
|
||||
* the 640k-768k range, if enabled later.
|
||||
*/
|
||||
void vx900_disable_legacy_rom_shadow(void)
|
||||
{
|
||||
pci_write_config8(MCU, 0x80, 0xff); /* LPC ROM 768k - 832k */
|
||||
pci_write_config8(MCU, 0x81, 0xff); /* LPC ROM 832k - 896k */
|
||||
pci_write_config8(MCU, 0x82, 0xff); /* LPC ROM 896k - 960k */
|
||||
/* LPC ROM 960k - 1M * SMRAM: 640k - 768k */
|
||||
pci_write_config8(MCU, 0x83, 0x31);
|
||||
|
||||
/* Bits 6:0 are the ROM shadow on top of 4G, so leave those untouched */
|
||||
pci_update_config8(LPC, 0x41, (u8)~(1 << 7), 0); /* LPC ROM 896k - 960k */
|
||||
|
||||
pci_write_config8(SNMIC, 0x61, 0); /* 768k - 832k */
|
||||
pci_write_config8(SNMIC, 0x62, 0); /* 832k - 896k */
|
||||
pci_write_config8(SNMIC, 0x63, 0); /* 896k - 1M */
|
||||
pci_write_config8(SNMIC, 0x64, 0); /* 896k - 960k */
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disables the VX900 integrated graphics controller
|
||||
*
|
||||
* Disable the graphics controller entirely. It will no longer be visible as a
|
||||
* PCI device.
|
||||
*/
|
||||
void vx900_disable_gfx(void)
|
||||
{
|
||||
/* Disable GFX */
|
||||
pci_update_config8(MCU, 0xa1, (u8)~(1 << 7), 0);
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2011-2012 Alexandru Gagniuc <mr.nuke.me@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.
|
||||
*/
|
||||
|
||||
#ifndef EARLY_VX900_H
|
||||
#define EARLY_VX900_H
|
||||
|
||||
#include "raminit.h"
|
||||
#include "vx900.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* North Module devices */
|
||||
#define HOST_CTR PCI_DEV(0, 0, 0)
|
||||
#define ERR_REP PCI_DEV(0, 0, 1)
|
||||
#define HOST_BUS PCI_DEV(0, 0, 2)
|
||||
#define MCU PCI_DEV(0, 0, 3)
|
||||
#define POWERMAN PCI_DEV(0, 0, 4)
|
||||
#define TRAF_CTR PCI_DEV(0, 0, 5)
|
||||
#define NSBIC PCI_DEV(0, 0, 7)
|
||||
|
||||
#define GFX PCI_DEV(0, 1, 0)
|
||||
#define HDMI PCI_DEV(0, 1, 0)
|
||||
|
||||
#define PEXx PCI_DEV(0, 3, x)
|
||||
#define PEX_CTR PCI_DEV(0, 3, 4)
|
||||
|
||||
/* South Module devices */
|
||||
#define UARTx PCI_DEV(0, 0x0a, x)
|
||||
#define USB_MASS PCI_DEV(0, 0x0b, 0)
|
||||
#define SDIO PCI_DEV(0, 0x0c, 0)
|
||||
#define CARD_RD PCI_DEV(0, 0x0d, 0)
|
||||
#define SATA PCI_DEV(0, 0x0d, 0)
|
||||
#define USBx PCI_DEV(0, 0x10, x)
|
||||
#define USB_EHCI PCI_DEV(0, 0x10, 4)
|
||||
#define LPC PCI_DEV(0, 0x11, 0)
|
||||
#define PMU LPC
|
||||
#define SNMIC PCI_DEV(0, 0x11, 7)
|
||||
#define P2P PCI_DEV(0, 0x13, 0)
|
||||
#define HDAC PCI_DEV(0, 0x14, 0)
|
||||
|
||||
/* These control the behavior of raminit */
|
||||
#define RAMINIT_USE_HW_RXCR_CALIB 0
|
||||
#define RAMINIT_USE_HW_MRS_SEQ 0
|
||||
|
||||
|
||||
void enable_smbus(void);
|
||||
void dump_spd_data(spd_raw_data spd);
|
||||
void spd_read(u8 addr, spd_raw_data spd);
|
||||
|
||||
void vx900_enable_pci_config_space(void);
|
||||
void vx900_disable_legacy_rom_shadow(void);
|
||||
|
||||
void vx900_print_strapping_info(void);
|
||||
void vx900_disable_auto_reboot(void);
|
||||
|
||||
void vx900_cpu_bus_interface_setup(void);
|
||||
|
||||
void vx900_dram_set_gfx_resources(void);
|
||||
void vx900_disable_gfx(void);
|
||||
|
||||
#endif /* EARLY_VX900_H */
|
|
@ -1,266 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2012-2013 Alexandru Gagniuc <mr.nuke.me@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.
|
||||
*/
|
||||
|
||||
#include <device/pci_ops.h>
|
||||
#include <arch/pirq_routing.h>
|
||||
#include <console/console.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ids.h>
|
||||
#include <pc80/i8259.h>
|
||||
#include <drivers/generic/ioapic/chip.h>
|
||||
|
||||
#include "vx900.h"
|
||||
#include "chip.h"
|
||||
|
||||
/**
|
||||
* @file vx900/lpc.c
|
||||
*
|
||||
* STATUS:
|
||||
* We do a fair bit of setup, and most of it seems to work fairly well. There
|
||||
* are still a few FIXME items here and there, but overall, this code hasn't
|
||||
* been touched much from its initial 2012 version to 2013, when it was revived.
|
||||
*
|
||||
* We do the IOAPIC setup with the assumption that it is declared in the
|
||||
* mainboard's devicetree.cb. We cannot use the IOAPIC however. The interrupts
|
||||
* do not make it to the CPU. This issue is still under investigation.
|
||||
*
|
||||
* We also route PIRQs with CONFIG_PIRQ_ROUTE. This is currently the only way to
|
||||
* get interrupts working.
|
||||
*
|
||||
* On the VX900, the keyboard can be connected directly to the chipset
|
||||
* (referenced as "internal keyboard" in the documents). As long as that is the
|
||||
* case (not connected to the superIO), and we disable the superIO keyboard LDN,
|
||||
* it will work, but perhaps this should be more configurable.
|
||||
*/
|
||||
|
||||
static void vx900_lpc_misc_stuff(struct device *dev)
|
||||
{
|
||||
char extint;
|
||||
u8 val;
|
||||
struct northbridge_via_vx900_config *nb = (void *)dev->chip_info;
|
||||
|
||||
/* GPIO 11,10 to SATALED [1,0] */
|
||||
pci_or_config8(dev, 0xe4, 1 << 0);
|
||||
|
||||
/* Route the external interrupt line */
|
||||
extint = nb->ext_int_route_to_pirq;
|
||||
if (extint < 'A' || extint > 'H') {
|
||||
printk(BIOS_WARNING, "Invalid PIRQ%c for external interrupt\n",
|
||||
extint);
|
||||
} else {
|
||||
printk(BIOS_INFO, "Routing external interrupt to PIRQ%c\n",
|
||||
extint);
|
||||
val = extint - 'A';
|
||||
val |= (1 << 3); /* bit3 enables the external int */
|
||||
pci_update_config8(dev, 0x55, ~0xf, val);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void vx900_lpc_dma_setup(struct device *dev)
|
||||
{
|
||||
/* These are the steps recommended by VIA in order to get DMA running */
|
||||
|
||||
/* Enable Positive South Module PCI Cycle Decoding */
|
||||
/* FIXME: Setting this seems to hang our system */
|
||||
|
||||
/* Positive decoding for ROM + APIC + On-board IO ports */
|
||||
pci_or_config8(dev, 0x6c, (1 << 2) | (1 << 3) | (1 << 7));
|
||||
/* Enable DMA channels. BIOS guide recommends DMA channel 2 off */
|
||||
pci_write_config8(dev, 0x53, 0xfb);
|
||||
/* Disable PCI/DMA Memory Cycles Output to PCI Bus */
|
||||
pci_update_config8(dev, 0x5b, ~(1 << 5), 0);
|
||||
/* DMA bandwidth control - Improved bandwidth */
|
||||
pci_write_config8(dev, 0x53, 0xff);
|
||||
/* ISA Positive Decoding control */
|
||||
pci_write_config8(dev, 0x6d, 0xdf);
|
||||
pci_write_config8(dev, 0x6e, 0x98);
|
||||
pci_write_config8(dev, 0x6f, 0x30);
|
||||
}
|
||||
|
||||
/**
|
||||
*\brief VX900: Set up the south module IOAPIC (for the ISA/LPC bus)
|
||||
*
|
||||
* Enable the IOAPIC in the south module, and properly set it up.
|
||||
* \n
|
||||
* This is the hardware specific initialization for the IOAPIC, and complements
|
||||
* the setup done by the generic IOAPIC driver. In order for the IOAPIC to work
|
||||
* properly, it _must_ be declared in devicetree.cb .
|
||||
* \n
|
||||
* We are assuming this is called before the drivers/generic/ioapic code,
|
||||
* which should be the case if devicetree.cb is set up properly.
|
||||
*/
|
||||
static void vx900_lpc_ioapic_setup(struct device *dev)
|
||||
{
|
||||
/* Find the IOAPIC, and make sure it's set up correctly in devicetree.cb
|
||||
* If it's not, then the generic ioapic driver will not set it up
|
||||
* correctly, and the MP table will not be correctly generated */
|
||||
struct device *ioapic;
|
||||
for (ioapic = dev->next; ioapic; ioapic = ioapic->next) {
|
||||
if (ioapic->path.type == DEVICE_PATH_IOAPIC)
|
||||
break;
|
||||
}
|
||||
|
||||
/* You did put an IOAPIC in devicetree.cb, didn't you? */
|
||||
if (ioapic == 0) {
|
||||
/* We don't have enough info to set up the IOAPIC */
|
||||
printk(BIOS_ERR, "ERROR: South module IOAPIC not found. "
|
||||
"Check your devicetree.cb\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Found an IOAPIC, now we need to make sure it's the right one */
|
||||
ioapic_config_t *config = (ioapic_config_t *) ioapic->chip_info;
|
||||
if (!config->have_isa_interrupts) {
|
||||
/* Umh, is this the right IOAPIC ? */
|
||||
printk(BIOS_ERR, "ERROR: South module IOAPIC not carrying ISA "
|
||||
"interrupts. Check your devicetree.cb\n");
|
||||
printk(BIOS_ERR, "Will not initialize this IOAPIC.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* The base address of this IOAPIC _must_ be at 0xfec00000.
|
||||
* Don't move this value to a #define, as people might think it's
|
||||
* configurable. It is not. */
|
||||
const void *base = config->base;
|
||||
if (base != (void *)0xfec00000) {
|
||||
printk(BIOS_ERR, "ERROR: South module IOAPIC base should be at "
|
||||
"0xfec00000\n but we found it at %p\n", base);
|
||||
return;
|
||||
}
|
||||
|
||||
printk(BIOS_DEBUG, "VX900 LPC: Setting up the south module IOAPIC.\n");
|
||||
/* Enable IOAPIC
|
||||
* So much work for one line of code. Talk about bloat :)
|
||||
* The 8259 PIC should still work even if the IOAPIC is enabled, so
|
||||
* there's no crime in enabling the IOAPIC here. */
|
||||
pci_or_config8(dev, 0x58, 1 << 6);
|
||||
}
|
||||
|
||||
static void vx900_lpc_interrupt_stuff(struct device *dev)
|
||||
{
|
||||
/* Enable setting trigger mode through 0x4d0, and 0x4d1 ports
|
||||
* And enable I/O recovery time */
|
||||
pci_or_config8(dev, 0x40, (1 << 2) | (1 << 6));
|
||||
/* Set serial IRQ frame width to 6 PCI cycles (recommended by VIA)
|
||||
* And enable serial IRQ */
|
||||
pci_update_config8(dev, 0x52, ~(3 << 0), (1 << 3) | (1 << 0));
|
||||
|
||||
/* Disable IRQ12 storm FIXME: bad comment */
|
||||
pci_update_config8(dev, 0x51, ~(1 << 2), 0);
|
||||
|
||||
pci_write_config8(dev, 0x4c, (1 << 6));
|
||||
|
||||
/* FIXME: Do we really need this? SeaBIOS/linux runs fine without it.
|
||||
* Is this something the payload/OS should do, or is it safe for us to
|
||||
* do it? */
|
||||
/* Get the IRQs up and running */
|
||||
setup_i8259();
|
||||
|
||||
vx900_lpc_dma_setup(dev);
|
||||
|
||||
/* The IOAPIC is special, and we treat it separately */
|
||||
vx900_lpc_ioapic_setup(dev);
|
||||
}
|
||||
|
||||
static void vx900_lpc_init(struct device *dev)
|
||||
{
|
||||
vx900_lpc_interrupt_stuff(dev);
|
||||
vx900_lpc_misc_stuff(dev);
|
||||
dump_pci_device(PCI_BDF(dev));
|
||||
}
|
||||
|
||||
static void vx900_lpc_read_resources(struct device *dev)
|
||||
{
|
||||
struct resource *res;
|
||||
pci_dev_read_resources(dev);
|
||||
|
||||
/* MMIO space */
|
||||
res = new_resource(dev, VX900_MMCONFIG_MBAR);
|
||||
res->size = 0x1000;
|
||||
res->align = 12;
|
||||
res->gran = 12;
|
||||
res->limit = 0xffffffff;
|
||||
res->flags = IORESOURCE_MEM | IORESOURCE_RESERVE;
|
||||
|
||||
/* SPI controller */
|
||||
res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
|
||||
res->size = 0x8;
|
||||
res->align = 12;
|
||||
res->gran = 12;
|
||||
res->limit = 0xffffffff;
|
||||
res->flags = IORESOURCE_MEM | IORESOURCE_RESERVE;
|
||||
}
|
||||
|
||||
static void vx900_lpc_set_resources(struct device *dev)
|
||||
{
|
||||
struct resource *mmio, *spi;
|
||||
u32 reg;
|
||||
|
||||
mmio = find_resource(dev, VX900_MMCONFIG_MBAR);
|
||||
if (mmio) {
|
||||
report_resource_stored(dev, mmio, "<mmconfig>");
|
||||
mmio->flags |= IORESOURCE_STORED;
|
||||
reg = pci_read_config32(dev, VX900_MMCONFIG_MBAR);
|
||||
reg &= 0xff000000;
|
||||
reg |= mmio->base >> 8;
|
||||
pci_write_config32(dev, VX900_MMCONFIG_MBAR, reg);
|
||||
|
||||
spi = find_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
|
||||
if (spi) {
|
||||
report_resource_stored(dev, spi, "<spi>");
|
||||
spi->flags |= IORESOURCE_STORED;
|
||||
/* Set base and the enable bit. */
|
||||
((u32*)(uintptr_t)mmio->base)[0] = (spi->base | 0x01);
|
||||
}
|
||||
}
|
||||
pci_dev_set_resources(dev);
|
||||
}
|
||||
|
||||
static struct device_operations vx900_lpc_ops = {
|
||||
.read_resources = vx900_lpc_read_resources,
|
||||
.set_resources = vx900_lpc_set_resources,
|
||||
.enable_resources = pci_dev_enable_resources,
|
||||
.init = vx900_lpc_init,
|
||||
.scan_bus = scan_static_bus,
|
||||
};
|
||||
|
||||
static const struct pci_driver lpc_driver __pci_driver = {
|
||||
.ops = &vx900_lpc_ops,
|
||||
.vendor = PCI_VENDOR_ID_VIA,
|
||||
.device = PCI_DEVICE_ID_VIA_VX900_LPC,
|
||||
};
|
||||
|
||||
#if CONFIG(PIRQ_ROUTE)
|
||||
void pirq_assign_irqs(const u8 *pirq)
|
||||
{
|
||||
struct device *lpc;
|
||||
|
||||
lpc = dev_find_device(PCI_VENDOR_ID_VIA,
|
||||
PCI_DEVICE_ID_VIA_VX900_LPC, 0);
|
||||
|
||||
/* Take care of INTA -> INTD */
|
||||
pci_update_config8(lpc, 0x55, (u8)~(0xf << 4), pirq[0] << 4);
|
||||
pci_write_config8(lpc, 0x56, pirq[1] | (pirq[2] << 4));
|
||||
pci_write_config8(lpc, 0x57, pirq[3] << 4);
|
||||
|
||||
/* Enable INTE -> INTH to be on separate IRQs */
|
||||
pci_or_config8(lpc, 0x46, 1 << 4);
|
||||
/* Now do INTE -> INTH */
|
||||
pci_write_config8(lpc, 0x44, pirq[4] | (pirq[5] << 4));
|
||||
pci_write_config8(lpc, 0x45, pirq[6] | (pirq[7] << 4));
|
||||
}
|
||||
#endif
|
|
@ -1,135 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||
* Copyright (C) 2018 Lubomir Rintel <lkundrak@v3.sk>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define __SIMPLE_DEVICE__
|
||||
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ops.h>
|
||||
#include <cbmem.h>
|
||||
#include <console/console.h>
|
||||
#include <lib.h>
|
||||
|
||||
#include "vx900.h"
|
||||
|
||||
#define MCU PCI_DEV(0, 0, 3)
|
||||
|
||||
#define CHROME_9_HD_MIN_FB_SIZE 8
|
||||
#define CHROME_9_HD_MAX_FB_SIZE 512
|
||||
|
||||
/* Helper to determine the framebuffer size */
|
||||
void vx900_set_chrome9hd_fb_size(u32 size_mb)
|
||||
{
|
||||
u8 reg8, ranksize;
|
||||
u32 tom_mb, max_size_mb;
|
||||
int i;
|
||||
|
||||
/* The minimum framebuffer size is 8MB. */
|
||||
size_mb = MAX(size_mb, CHROME_9_HD_MIN_FB_SIZE);
|
||||
|
||||
/*
|
||||
* We have two limitations on the maximum framebuffer size:
|
||||
* 1) (Sanity) No more that 1/4 of system RAM
|
||||
* 2) (Hardware limitation) No larger than DRAM in last rank
|
||||
* Check both of these limitations and apply them to our framebuffer */
|
||||
tom_mb = (pci_read_config16(MCU, 0x88) & 0x07ff) << (24 - 20);
|
||||
max_size_mb = tom_mb >> 2;
|
||||
if (size_mb > max_size_mb) {
|
||||
printk(BIOS_ALERT, "The framebuffer size of %dMB is larger"
|
||||
" than 1/4 of available memory.\n"
|
||||
" Limiting framebuffer to %dMB\n", size_mb, max_size_mb);
|
||||
size_mb = max_size_mb;
|
||||
}
|
||||
|
||||
/* Now handle limitation #2
|
||||
* Look at the ending address of the memory ranks, from last to first,
|
||||
* until we find one that is not zero. That is our last rank, and its
|
||||
* size is the limit of our framebuffer. */
|
||||
/* FIXME: This has a bug. If we remap memory above 4G, we consider the
|
||||
* memory hole as part of our RAM. Thus if we install 3G, with a TOLM of
|
||||
* 2.5G, our TOM will be at 5G and we'll assume we have 5G RAM instead
|
||||
* of the actual 3.5G */
|
||||
for (i = VX900_MAX_MEM_RANKS - 1; i > -1; i--) {
|
||||
reg8 = pci_read_config8(MCU, 0x40 + i);
|
||||
if (reg8 == 0)
|
||||
continue;
|
||||
/* We've reached the last populated rank */
|
||||
ranksize = reg8 - pci_read_config8(MCU, 0x48 + i);
|
||||
max_size_mb = ranksize << 6;
|
||||
/* That's it. We got what we needed. */
|
||||
break;
|
||||
}
|
||||
if (size_mb > max_size_mb) {
|
||||
printk(BIOS_ALERT, "The framebuffer size of %dMB is larger"
|
||||
" than size of the last DRAM rank.\n"
|
||||
" Limiting framebuffer to %dMB\n", size_mb, max_size_mb);
|
||||
size_mb = max_size_mb;
|
||||
}
|
||||
|
||||
/* Now round down the framebuffer size to the closest power of 2 */
|
||||
if (size_mb == 0)
|
||||
die("Framebuffer size is 0\n");
|
||||
|
||||
int fb_pow = log2(size_mb);
|
||||
|
||||
size_mb = 1U << fb_pow;
|
||||
|
||||
if (size_mb < CHROME_9_HD_MIN_FB_SIZE || size_mb > CHROME_9_HD_MAX_FB_SIZE)
|
||||
die("Framebuffer size %u is out of range\n", size_mb);
|
||||
|
||||
pci_update_config8(MCU, 0xa1, ~(7 << 4), (fb_pow - 2) << 4);
|
||||
}
|
||||
|
||||
/* Gets the configured framebuffer size as a power of 2 */
|
||||
u8 vx900_get_chrome9hd_fb_pow(void)
|
||||
{
|
||||
u8 fb_pow = (pci_read_config8(MCU, 0xa1) >> 4) & 7;
|
||||
|
||||
if (fb_pow > 0)
|
||||
fb_pow += 2;
|
||||
|
||||
return fb_pow;
|
||||
}
|
||||
|
||||
/* Gets the configured framebuffer size in MB */
|
||||
u32 vx900_get_chrome9hd_fb_size(void)
|
||||
{
|
||||
u8 size = vx900_get_chrome9hd_fb_pow();
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
return 1 << size;
|
||||
}
|
||||
|
||||
u32 vx900_get_tolm(void)
|
||||
{
|
||||
return (pci_read_config16(MCU, 0x84) & 0xfff0) >> 4;
|
||||
}
|
||||
|
||||
void *cbmem_top_chipset(void)
|
||||
{
|
||||
uintptr_t tolm;
|
||||
uintptr_t fb_size;
|
||||
|
||||
tolm = vx900_get_tolm ();
|
||||
fb_size = vx900_get_chrome9hd_fb_size ();
|
||||
|
||||
if (tolm > 0xfc0 || tolm <= 0x3ff || fb_size == 0x0)
|
||||
return NULL;
|
||||
|
||||
return (void *)((tolm - fb_size) << 20);
|
||||
}
|
|
@ -1,345 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@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.
|
||||
*/
|
||||
|
||||
#include "vx900.h"
|
||||
#include "chip.h"
|
||||
|
||||
#include <console/console.h>
|
||||
#include <device/device.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ops.h>
|
||||
#include <device/pci_ids.h>
|
||||
#include <cpu/cpu.h>
|
||||
#include <cf9_reset.h>
|
||||
#include <reset.h>
|
||||
|
||||
#define RAM_4GB (((u64)1) << 32)
|
||||
|
||||
static uint64_t uma_memory_base = 0;
|
||||
static uint64_t uma_memory_size = 0;
|
||||
|
||||
/**
|
||||
* @file vx900/northbridge.c
|
||||
*
|
||||
* STATUS: Pretty good
|
||||
* One thing that needs to be thoroughly tested is the remap above 4G logic.
|
||||
* Unfortunately, while we cannot initialize odd ranks, our testing
|
||||
* possibilities are somewhat limited. A point of failure that is not covered is
|
||||
* when the amount of RAM and PCI config space added up exceeds 8GB. The
|
||||
* remapping mechanism will overflow, the effects of which are unknown.
|
||||
*/
|
||||
|
||||
void do_board_reset(void)
|
||||
{
|
||||
system_reset();
|
||||
}
|
||||
|
||||
uint64_t get_uma_memory_base(void)
|
||||
{
|
||||
printk(BIOS_DEBUG, "UMA base 0x%.8llx (%lluMB)\n", uma_memory_base,
|
||||
uma_memory_base >> 20);
|
||||
printk(BIOS_DEBUG, "UMA size 0x%.8llx (%lluMB)\n", uma_memory_size,
|
||||
uma_memory_size >> 20);
|
||||
return uma_memory_base;
|
||||
}
|
||||
|
||||
static u64 vx900_get_top_of_ram(struct device *mcu)
|
||||
{
|
||||
u16 reg16;
|
||||
/* The last valid DRAM address is computed by the MCU
|
||||
* One issue might be if we have a hole in the rank mappings, so that
|
||||
* virtual ranks are not mapped successively in the linear address space
|
||||
* (Ex: rank 0 mapped 0-1G, rank 1 mapped 2G-3G)
|
||||
* We don't do this awkward mapping in RAM init, so we don't worry about
|
||||
* it here, but it is something to keep in mind if having RAM issues */
|
||||
reg16 = pci_read_config16(mcu, 0x88) & 0x07ff;
|
||||
return (u64) reg16 << 24;
|
||||
}
|
||||
|
||||
/*
|
||||
* This guy is meant to go away, but for now, leave it in so that we can see
|
||||
* if the logic to remap RAM above 4G has errors.
|
||||
*/
|
||||
static void killme_debug_4g_remap_reg(u32 reg32)
|
||||
{
|
||||
if (reg32 & (1 << 0))
|
||||
printk(BIOS_DEBUG, "Mem remapping enabled\n");
|
||||
u64 remapstart = (reg32 >> 2) & 0x3ff;
|
||||
u64 remapend = (reg32 >> 14) & 0x3ff;
|
||||
remapstart <<= 26;
|
||||
remapend <<= 26;
|
||||
printk(BIOS_DEBUG, "Remapstart %lld(MB)\n", remapstart >> 20);
|
||||
printk(BIOS_DEBUG, "Remapend %lld(MB)\n", remapend >> 20);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Remap low memory colliding with PCI MMIO space, above 4G
|
||||
*
|
||||
* @param mcu The memory controller
|
||||
* @param tolm Top of low memory.
|
||||
*
|
||||
* @return The new top of memory.
|
||||
*/
|
||||
static u64 vx900_remap_above_4g(struct device *mcu, u32 tolm)
|
||||
{
|
||||
size_t i;
|
||||
u8 reg8, start8, end8, start, end;
|
||||
u16 reg16;
|
||||
u32 reg32;
|
||||
u64 tor, newtor, chunk;
|
||||
|
||||
/*
|
||||
* The remapping mechanism works like this:
|
||||
*
|
||||
* - Choose the top of low memory.
|
||||
* This becomes the "remap from"
|
||||
* - Choose a chunk above 4G where to remap.
|
||||
* This becomes "remap to"
|
||||
* - Choose a chunk above 4G where to end the remapping.
|
||||
* This becomes "remap until"
|
||||
*
|
||||
* This remaps a "chunk" of memory where we want to.
|
||||
* sizeof(chunk) = until - to;
|
||||
*
|
||||
* Therefore the memory region from "from" to " from + sizeof(chunk)"
|
||||
* becomes accessible at "to" to "until"
|
||||
*/
|
||||
if (tolm >= vx900_get_top_of_ram(mcu)) {
|
||||
printk(BIOS_DEBUG, "Nothing to remap\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is how the Vendor BIOS. Keep it for comparison for now */
|
||||
killme_debug_4g_remap_reg(0x00180141);
|
||||
/* We can remap with a granularity of 64MB, so align tolm */
|
||||
tolm &= ~((64 * MiB) - 1);
|
||||
|
||||
/* The "start remapping from where ?" register */
|
||||
reg16 = ((tolm >> 20) & 0xfff) << 4;
|
||||
pci_update_config16(mcu, 0x84, (u16)~0xfff0, reg16);
|
||||
|
||||
/* Find the chunk size */
|
||||
tor = vx900_get_top_of_ram(mcu);
|
||||
printk(BIOS_DEBUG, "Top of RAM %lldMB\n", tor >> 20);
|
||||
|
||||
if (tor < RAM_4GB) {
|
||||
chunk = tor - tolm;
|
||||
newtor = RAM_4GB + chunk;
|
||||
} else {
|
||||
chunk = (RAM_4GB - tolm);
|
||||
newtor = tor + chunk;
|
||||
}
|
||||
printk(BIOS_DEBUG, "New top of RAM %lldMB\n", newtor >> 20);
|
||||
|
||||
reg8 = tolm >> 26;
|
||||
/* Which rank does the PCI TOLM fall on? */
|
||||
for (i = 0; i < VX900_MAX_MEM_RANKS; i++) {
|
||||
end8 = pci_read_config8(mcu, 0x40 + i);
|
||||
if (reg8 > end8)
|
||||
continue;
|
||||
start8 = pci_read_config8(mcu, 0x48 + i);
|
||||
if (reg8 <= start8)
|
||||
continue;
|
||||
printk(BIOS_DEBUG, "Address %x falls on rank %zu\n", tolm, i);
|
||||
break;
|
||||
}
|
||||
|
||||
for (; i < VX900_MAX_MEM_RANKS; i++) {
|
||||
start = pci_read_config8(mcu, 0x48 + i);
|
||||
end = pci_read_config8(mcu, 0x40 + i);
|
||||
|
||||
if (end == 0) {
|
||||
printk(BIOS_DEBUG, "Huh? rank %zu empty?\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (end < (tolm >> 26)) {
|
||||
printk(BIOS_DEBUG, "Huh? rank %zu don't need remap?\n",
|
||||
i);
|
||||
continue;
|
||||
}
|
||||
|
||||
printk(BIOS_DEBUG, "Physical rank %u is mapped to\n"
|
||||
" Start address: 0x%.10llx (%dMB)\n"
|
||||
" End address: 0x%.10llx (%dMB)\n",
|
||||
(int)i,
|
||||
((u64) start << 26), (start << (26 - 20)),
|
||||
((u64) end << 26), (end << (26 - 20)));
|
||||
|
||||
if (end < (RAM_4GB >> 26))
|
||||
end = (RAM_4GB >> 26);
|
||||
|
||||
if (end >= (tolm >> 26))
|
||||
end += chunk >> 26;
|
||||
|
||||
if (start > (tolm >> 26))
|
||||
start += chunk >> 26;
|
||||
|
||||
pci_write_config8(mcu, 0x48 + i, start);
|
||||
pci_write_config8(mcu, 0x40 + i, end);
|
||||
|
||||
printk(BIOS_DEBUG, "ReMapped Physical rank %u, to\n"
|
||||
" Start address: 0x%.10llx (%dMB)\n"
|
||||
" End address: 0x%.10llx (%dMB)\n",
|
||||
(int)i,
|
||||
((u64) start << 26), (start << (26 - 20)),
|
||||
((u64) end << 26), (end << (26 - 20)));
|
||||
}
|
||||
|
||||
/* The "remap to where?" register */
|
||||
reg32 = ((MAX(tor, RAM_4GB) >> 26) & 0x3ff) << 2;
|
||||
/* The "remap until where?" register */
|
||||
reg32 |= ((newtor >> 26) & 0x3ff) << 14;
|
||||
/* Now enable the goodies */
|
||||
reg32 |= (1 << 0);
|
||||
pci_write_config32(mcu, 0xf8, reg32);
|
||||
printk(BIOS_DEBUG, "Wrote remap map %x\n", reg32);
|
||||
killme_debug_4g_remap_reg(reg32);
|
||||
|
||||
printk(BIOS_DEBUG, "New top of memory is at %lldMB\n", newtor >> 20);
|
||||
return newtor;
|
||||
}
|
||||
|
||||
static void vx900_set_resources(struct device *dev)
|
||||
{
|
||||
u32 pci_tolm, tomk, vx900_tolm, full_tolmk, fbufk, tolmk;
|
||||
|
||||
printk(BIOS_DEBUG, "========================================"
|
||||
"========================================\n");
|
||||
printk(BIOS_DEBUG, "============= VX900 memory sizing & Co. "
|
||||
"========================================\n");
|
||||
printk(BIOS_DEBUG, "========================================"
|
||||
"========================================\n");
|
||||
|
||||
int idx = 10;
|
||||
struct device *const mcu = dev_find_device(PCI_VENDOR_ID_VIA,
|
||||
PCI_DEVICE_ID_VIA_VX900_MEMCTRL,
|
||||
0);
|
||||
if (!mcu) {
|
||||
die("Something is terribly wrong.\n"
|
||||
" We tried locating the MCU on the PCI bus, "
|
||||
"but couldn't find it. Halting.\n");
|
||||
}
|
||||
|
||||
/* How much low adrress space do we have? */
|
||||
pci_tolm = find_pci_tolm(dev->link_list);
|
||||
printk(BIOS_SPEW, "Found PCI tolm at %.8x\n", pci_tolm);
|
||||
printk(BIOS_SPEW, "Found PCI tolm at %dMB\n", pci_tolm >> 20);
|
||||
|
||||
/* Figure out the total amount of RAM */
|
||||
tomk = vx900_get_top_of_ram(mcu) >> 10;
|
||||
printk(BIOS_SPEW, "Found top of memory at %dMB\n", tomk >> 10);
|
||||
|
||||
/* Do the same for top of low RAM */
|
||||
vx900_tolm = vx900_get_tolm();
|
||||
full_tolmk = vx900_tolm << (20 - 10);
|
||||
/* Remap above 4G if needed */
|
||||
full_tolmk = MIN(full_tolmk, pci_tolm >> 10);
|
||||
printk(BIOS_SPEW, "Found top of low memory at %dMB\n",
|
||||
full_tolmk >> 10);
|
||||
|
||||
/* What about the framebuffer for the integrated GPU? */
|
||||
fbufk = vx900_get_chrome9hd_fb_size() << (20 - 10);
|
||||
printk(BIOS_SPEW, "Integrated graphics buffer: %dMB\n", fbufk >> 10);
|
||||
|
||||
/* Can't use the framebuffer as system RAM, sorry */
|
||||
tolmk = MIN(full_tolmk, tomk);
|
||||
tolmk -= fbufk;
|
||||
ram_resource(dev, idx++, 0, 640);
|
||||
printk(BIOS_SPEW, "System RAM left: %dMB\n", tolmk >> 10);
|
||||
/* FIXME: how can we avoid leaving this hole?
|
||||
* Leave a hole for VGA, 0xa0000 - 0xc0000 ?? */
|
||||
/* TODO: VGA Memory hole can be disabled in SNMIC. Upper 64k of ROM seem
|
||||
* to be always mapped to the top of 1M, but this can be overcome with
|
||||
* some smart positive/subtractive resource decoding */
|
||||
ram_resource(dev, idx++, 768, (tolmk - 768));
|
||||
|
||||
uma_memory_size = (uint64_t)fbufk << 10;
|
||||
uma_memory_base = (uint64_t)tolmk << 10;
|
||||
|
||||
if (uma_memory_size > UINT32_MAX)
|
||||
die("uma_memory_size %llu exceeds 32-bit address range\n", uma_memory_size);
|
||||
|
||||
if (uma_memory_base > UINT32_MAX)
|
||||
die("uma_memory_base %llu exceeds 32-bit address range\n", uma_memory_base);
|
||||
|
||||
//uma_resource(dev, idx++, uma_memory_base>>10, uma_memory_size>>10);
|
||||
|
||||
printk(BIOS_DEBUG, "UMA @ %lldMB + %lldMB\n", uma_memory_base >> 20,
|
||||
uma_memory_size >> 20);
|
||||
/* FIXME: How do we handle remapping above 4G? */
|
||||
u64 tor = vx900_remap_above_4g(mcu, pci_tolm);
|
||||
if (tor)
|
||||
ram_resource(dev, idx++, RAM_4GB >> 10, (tor - RAM_4GB) >> 10);
|
||||
|
||||
printk(BIOS_DEBUG, "======================================================\n");
|
||||
assign_resources(dev->link_list);
|
||||
}
|
||||
|
||||
static void vx900_read_resources(struct device *dev)
|
||||
{
|
||||
/* Our fixed resources start at 0 */
|
||||
int idx = 0;
|
||||
/* Reserve our ROM mapped space */
|
||||
struct resource *res;
|
||||
res = new_resource(dev, idx++);
|
||||
res->size = CONFIG_ROM_SIZE;
|
||||
res->base = 0xffffffff - (res->size - 1);
|
||||
res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
|
||||
|
||||
/* Now do the same for our MMCONF
|
||||
* We always run with MMCONF enabled. We need to access the extended
|
||||
* config space when configuring PCI-Express links */
|
||||
mmconf_resource(dev, idx++);
|
||||
|
||||
pci_domain_read_resources(dev);
|
||||
}
|
||||
|
||||
static struct device_operations pci_domain_ops = {
|
||||
.read_resources = vx900_read_resources,
|
||||
.set_resources = vx900_set_resources,
|
||||
.enable_resources = NULL,
|
||||
.init = NULL,
|
||||
.scan_bus = pci_domain_scan_bus,
|
||||
};
|
||||
|
||||
static void cpu_bus_init(struct device *dev)
|
||||
{
|
||||
initialize_cpus(dev->link_list);
|
||||
}
|
||||
|
||||
static struct device_operations cpu_bus_ops = {
|
||||
.read_resources = DEVICE_NOOP,
|
||||
.set_resources = DEVICE_NOOP,
|
||||
.enable_resources = DEVICE_NOOP,
|
||||
.init = cpu_bus_init,
|
||||
.scan_bus = 0,
|
||||
};
|
||||
|
||||
static void enable_dev(struct device *dev)
|
||||
{
|
||||
/* Set the operations if it is a special bus type */
|
||||
if (dev->path.type == DEVICE_PATH_DOMAIN) {
|
||||
dev->ops = &pci_domain_ops;
|
||||
} else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
|
||||
dev->ops = &cpu_bus_ops;
|
||||
}
|
||||
}
|
||||
|
||||
struct chip_operations northbridge_via_vx900_ops = {
|
||||
CHIP_NAME("VIA VX900 Chipset")
|
||||
.enable_dev = enable_dev,
|
||||
};
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@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.
|
||||
*/
|
||||
|
||||
#include <console/console.h>
|
||||
#include <device/pci_ops.h>
|
||||
|
||||
#include "vx900.h"
|
||||
|
||||
void dump_pci_device(pci_devfn_t dev)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i <= 0xff; i++) {
|
||||
unsigned char val;
|
||||
if ((i & 0x0f) == 0)
|
||||
printk(BIOS_DEBUG, "%.2x:", i);
|
||||
|
||||
if ((i & 0x0f) == 0x08)
|
||||
printk(BIOS_DEBUG, " |");
|
||||
|
||||
val = pci_s_read_config8(dev, i);
|
||||
printk(BIOS_DEBUG, " %.2x", val);
|
||||
|
||||
if ((i & 0x0f) == 0x0f)
|
||||
printk(BIOS_DEBUG, "\n");
|
||||
}
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@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.
|
||||
*/
|
||||
|
||||
#include <device/pci_ops.h>
|
||||
#include <console/console.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pciexp.h>
|
||||
#include <device/pci_ids.h>
|
||||
|
||||
#include "vx900.h"
|
||||
|
||||
/**
|
||||
* @file vx900/pcie.c
|
||||
*
|
||||
* STATUS:
|
||||
* We do part of the sequence to initialize the PCIE link. The problem is that
|
||||
* the reset signal for each slot is connected to a GPO pin, but We don't know
|
||||
* which GPO pin. We need to figure out which GPIO pin is hooked to which slot,
|
||||
* and have a mechanism to specify this per-mainboard (devicetree.cb).
|
||||
*
|
||||
* There is currently no timeout detection mechanism for when a link comes up.
|
||||
* If the link never comes up, we hang.
|
||||
*/
|
||||
|
||||
static void vx900_pcie_link_init(struct device *dev)
|
||||
{
|
||||
u8 reg8;
|
||||
u32 reg32;
|
||||
|
||||
u8 fn = dev->path.pci.devfn & 0x07;
|
||||
|
||||
/* Step 1 : Check for presence of PCIE device */
|
||||
reg8 = pci_read_config8(dev, 0x5a);
|
||||
|
||||
if (reg8 & (1 << 6))
|
||||
printk(BIOS_DEBUG, "Card detected in PEX%i\n", fn);
|
||||
else
|
||||
return;
|
||||
|
||||
/* Step 2: Wait for device to enter L0 state */
|
||||
/* FIXME: implement timeout detection */
|
||||
while (0x8a != pci_read_config8(dev, 0x1c3));
|
||||
|
||||
/* Step 3: Clear PCIe error status, then check for failures */
|
||||
pci_write_config32(dev, 0x104, 0xffffffff);
|
||||
reg32 = pci_read_config32(dev, 0x104);
|
||||
if (0 != reg32) {
|
||||
printk(BIOS_DEBUG, "PEX init error. flags 0x%.8x\n", reg32);
|
||||
return;
|
||||
}
|
||||
|
||||
pci_write_config32(dev, 0x110, 0xffffffff);
|
||||
reg32 = pci_read_config32(dev, 0x110);
|
||||
if (0 != reg32)
|
||||
printk(BIOS_DEBUG, "PEX errors. flags 0x%.8x\n", reg32);
|
||||
|
||||
pci_write_config8(dev, 0xa4, 0xff);
|
||||
if (pci_read_config8(dev, 0x4a) & (1 << 3))
|
||||
printk(BIOS_DEBUG, "Unsupported request detected.\n");
|
||||
|
||||
pci_write_config8(dev, 0x15a, 0xff);
|
||||
if (pci_read_config8(dev, 0x15a) & (1 << 1))
|
||||
printk(BIOS_DEBUG, "Negotiation pending.\n");
|
||||
|
||||
/* Step 4: Read vendor ID */
|
||||
/* FIXME: Do we want to run through the whole sequence and delay boot
|
||||
* by several seconds if the device does not respond properly the first
|
||||
* time? */
|
||||
}
|
||||
|
||||
static void vx900_pex_dev_set_resources(struct device *dev)
|
||||
{
|
||||
assign_resources(dev->link_list);
|
||||
}
|
||||
|
||||
static void vx900_pex_init(struct device *dev)
|
||||
{
|
||||
/* FIXME: For some reason, PEX0 hangs on init. Find issue, fix it. */
|
||||
if ((dev->path.pci.devfn & 0x7) == 0)
|
||||
return;
|
||||
|
||||
vx900_pcie_link_init(dev);
|
||||
}
|
||||
|
||||
static struct device_operations vx900_pex_ops = {
|
||||
.read_resources = pci_bus_read_resources,
|
||||
.set_resources = vx900_pex_dev_set_resources,
|
||||
.enable_resources = pci_bus_enable_resources,
|
||||
.init = vx900_pex_init,
|
||||
.scan_bus = pciexp_scan_bridge,
|
||||
.reset_bus = pci_bus_reset,
|
||||
};
|
||||
|
||||
static const unsigned short pci_device_ids[] = {
|
||||
PCI_DEVICE_ID_VIA_VX900_PEX1,
|
||||
PCI_DEVICE_ID_VIA_VX900_PEX2,
|
||||
PCI_DEVICE_ID_VIA_VX900_PEX3,
|
||||
PCI_DEVICE_ID_VIA_VX900_PEX4,
|
||||
0,
|
||||
};
|
||||
|
||||
static const struct pci_driver pex_driver __pci_driver = {
|
||||
.ops = &vx900_pex_ops,
|
||||
.vendor = PCI_VENDOR_ID_VIA,
|
||||
.devices = pci_device_ids,
|
||||
|
||||
};
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2011 Alexandru Gagniuc <mr.nuke.me@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.
|
||||
*/
|
||||
|
||||
#ifndef RAMINIT_VX900_H
|
||||
#define RAMINIT_VX900_H
|
||||
|
||||
#include <device/dram/ddr3.h>
|
||||
#include "vx900.h"
|
||||
|
||||
#define SPD_END_LIST 0xff
|
||||
|
||||
typedef struct dimm_layout_st
|
||||
{
|
||||
/* The address of the DIMM on the SMBUS *
|
||||
* 0xFF to terminate the array*/
|
||||
u8 spd_addr[VX900_MAX_DIMM_SLOTS + 1];
|
||||
} dimm_layout;
|
||||
|
||||
typedef struct dimm_info_st
|
||||
{
|
||||
dimm_attr dimm[VX900_MAX_DIMM_SLOTS];
|
||||
} dimm_info;
|
||||
|
||||
typedef struct mem_rank_st {
|
||||
u16 start_addr;
|
||||
u16 end_addr;
|
||||
} mem_rank;
|
||||
|
||||
typedef struct rank_layout_st {
|
||||
u32 phys_rank_size_mb[VX900_MAX_MEM_RANKS];
|
||||
mem_rank virt[VX900_MAX_MEM_RANKS];
|
||||
dimm_flags_t flags[VX900_MAX_MEM_RANKS];
|
||||
} rank_layout;
|
||||
|
||||
typedef struct pci_reg8_st {
|
||||
u8 addr;
|
||||
u8 val;
|
||||
} pci_reg8;
|
||||
|
||||
typedef u8 timing_dly[8];
|
||||
|
||||
typedef struct delay_range_st {
|
||||
timing_dly low;
|
||||
timing_dly avg;
|
||||
timing_dly high;
|
||||
} delay_range;
|
||||
|
||||
typedef struct vx900_delay_calib_st {
|
||||
delay_range rx_dq_cr;
|
||||
delay_range rx_dqs;
|
||||
/* Transmit delays are calibrated for each dimm */
|
||||
delay_range tx_dq[VX900_MAX_DIMM_SLOTS];
|
||||
delay_range tx_dqs[VX900_MAX_DIMM_SLOTS];
|
||||
} vx900_delay_calib;
|
||||
|
||||
typedef struct ramctr_timing_st {
|
||||
enum spd_memory_type dram_type;
|
||||
enum spd_dimm_type dimm_type;
|
||||
u16 cas_supported;
|
||||
/* tLatencies are in units of ns, scaled by x256 */
|
||||
u32 tCK;
|
||||
u32 tAA;
|
||||
u32 tWR;
|
||||
u32 tRCD;
|
||||
u32 tRRD;
|
||||
u32 tRP;
|
||||
u32 tRAS;
|
||||
u32 tRC;
|
||||
u32 tRFC;
|
||||
u32 tWTR;
|
||||
u32 tRTP;
|
||||
u32 tFAW;
|
||||
/* Latencies in terms of clock cycles
|
||||
* They are saved separately as they are needed for DRAM MRS commands*/
|
||||
u8 CAS; /* CAS read latency */
|
||||
u8 CWL; /* CAS write latency */
|
||||
u8 WR; /* write recovery time */
|
||||
/* Number of dimms currently connected */
|
||||
u8 n_dimms;
|
||||
|
||||
} ramctr_timing;
|
||||
|
||||
void vx900_init_dram_ddr3(const dimm_layout *dimms);
|
||||
|
||||
#endif /* RAMINIT_VX900_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2004 Tyan Computer
|
||||
* (Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer)
|
||||
* Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
|
||||
* Copyright (C) 2009 One Laptop per Child, Association, Inc.
|
||||
* Copyright (C) 2011-2012 Alexandru Gagniuc <mr.nuke.me@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; version 2 of the License.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* As extracted from the manufacturer's ROM, the romstrap table looks like:
|
||||
* .long 0x77886047 .long 0x00777777
|
||||
* .long 0x00000000 .long 0x00000000
|
||||
* .long 0x00888888 .long 0x00AA1111
|
||||
* .long 0x00000000 .long 0x00000000
|
||||
*
|
||||
* The vendor BIOS then adjusts some of these settings very early on. Instead of
|
||||
* adjusting those settings in code, we work them in the romstrap table.
|
||||
*
|
||||
*/
|
||||
/* This file constructs the ROM strap table for VX900 */
|
||||
|
||||
.section ".romstrap", "a", @progbits
|
||||
|
||||
.globl __romstrap_start
|
||||
__romstrap_start:
|
||||
tblpointer:
|
||||
.long 0x77886047
|
||||
.long 0x00777777
|
||||
.long 0x00000000
|
||||
.long 0x00000000
|
||||
.long 0x00888888
|
||||
.long 0x00AA1111
|
||||
.long 0x00000000
|
||||
.long 0x00000000
|
||||
|
||||
/*
|
||||
* The pointer to above table should be at 0xffffffd0,
|
||||
* the table itself MUST be aligned to 128B it seems!
|
||||
*/
|
||||
rspointers:
|
||||
.long tblpointer // It will be 0xffffffd0
|
||||
|
||||
.globl __romstrap_end
|
||||
|
||||
__romstrap_end:
|
||||
.previous
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 AMD
|
||||
* (Written by Yinghai Lu <yinghai.lu@amd.com> for AMD)
|
||||
* Copyright (C) 2011 Alexandru Gagniuc <mr.nuke.me@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.
|
||||
*/
|
||||
|
||||
SECTIONS {
|
||||
. = (0x100000000 - 0x2c) - (__romstrap_end - __romstrap_start);
|
||||
.romstrap (.): {
|
||||
KEEP(*(.romstrap))
|
||||
}
|
||||
}
|
|
@ -1,275 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@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.
|
||||
*/
|
||||
|
||||
#include <console/console.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ops.h>
|
||||
#include <device/pci_ids.h>
|
||||
|
||||
#include "vx900.h"
|
||||
|
||||
/**
|
||||
* @file vx900/sata.c
|
||||
*
|
||||
* STATUS: Pretty good
|
||||
* The only issue is the SATA EPHY configuration. We do not know if it is board
|
||||
* specific or not. Otherwise, the SATA controller works without issues.
|
||||
*/
|
||||
|
||||
static void vx900_print_sata_errors(u32 flags)
|
||||
{
|
||||
/* Status flags */
|
||||
printk(BIOS_DEBUG, "\tPhyRdy %s\n",
|
||||
(flags & (1 << 16)) ? "changed" : "not changed");
|
||||
printk(BIOS_DEBUG, "\tCOMWAKE %s\n",
|
||||
(flags & (1 << 16)) ? "detected" : "not detected");
|
||||
printk(BIOS_DEBUG, "\tExchange as determined by COMINIT %s\n",
|
||||
(flags & (1 << 26)) ? "occurred" : "not occurred");
|
||||
printk(BIOS_DEBUG, "\tPort selector presence %s\n",
|
||||
(flags & (1 << 27)) ? "detected" : "not detected");
|
||||
/* Errors */
|
||||
if (flags & (1 << 0))
|
||||
printk(BIOS_DEBUG, "\tRecovered data integrity ERROR\n");
|
||||
if (flags & (1 << 1))
|
||||
printk(BIOS_DEBUG, "\tRecovered data communication ERROR\n");
|
||||
if (flags & (1 << 8))
|
||||
printk(BIOS_DEBUG, "\tNon-recovered Transient Data Integrity ERROR\n");
|
||||
if (flags & (1 << 9))
|
||||
printk(BIOS_DEBUG, "\tNon-recovered Persistent Communication or"
|
||||
"\tData Integrity ERROR\n");
|
||||
if (flags & (1 << 10))
|
||||
printk(BIOS_DEBUG, "\tProtocol ERROR\n");
|
||||
if (flags & (1 << 11))
|
||||
printk(BIOS_DEBUG, "\tInternal ERROR\n");
|
||||
if (flags & (1 << 17))
|
||||
printk(BIOS_DEBUG, "\tPHY Internal ERROR\n");
|
||||
if (flags & (1 << 19))
|
||||
printk(BIOS_DEBUG, "\t10B to 8B Decode ERROR\n");
|
||||
if (flags & (1 << 20))
|
||||
printk(BIOS_DEBUG, "\tDisparity ERROR\n");
|
||||
if (flags & (1 << 21))
|
||||
printk(BIOS_DEBUG, "\tCRC ERROR\n");
|
||||
if (flags & (1 << 22))
|
||||
printk(BIOS_DEBUG, "\tHandshake ERROR\n");
|
||||
if (flags & (1 << 23))
|
||||
printk(BIOS_DEBUG, "\tLink Sequence ERROR\n");
|
||||
if (flags & (1 << 24))
|
||||
printk(BIOS_DEBUG, "\tTransport State Transition ERROR\n");
|
||||
if (flags & (1 << 25))
|
||||
printk(BIOS_DEBUG, "\tUNRECOGNIZED FIS type\n");
|
||||
}
|
||||
|
||||
static void vx900_dbg_sata_errors(struct device *dev)
|
||||
{
|
||||
/* Port 0 */
|
||||
if (pci_read_config8(dev, 0xa0) & (1 << 0)) {
|
||||
printk(BIOS_DEBUG, "Device detected in SATA port 0.\n");
|
||||
u32 flags = pci_read_config32(dev, 0xa8);
|
||||
vx900_print_sata_errors(flags);
|
||||
};
|
||||
/* Port 1 */
|
||||
if (pci_read_config8(dev, 0xa1) & (1 << 0)) {
|
||||
printk(BIOS_DEBUG, "Device detected in SATA port 1.\n");
|
||||
u32 flags = pci_read_config32(dev, 0xac);
|
||||
vx900_print_sata_errors(flags);
|
||||
};
|
||||
}
|
||||
|
||||
typedef u8 sata_phy_config[64];
|
||||
|
||||
static sata_phy_config reference_ephy = {
|
||||
0x80, 0xb8, 0xf0, 0xfe, 0x40, 0x7e, 0xf6, 0xdd,
|
||||
0x1a, 0x22, 0xa0, 0x10, 0x02, 0xa9, 0x7c, 0x7e,
|
||||
0x00, 0x00, 0x00, 0x00, 0x40, 0x30, 0x84, 0x8c,
|
||||
0x75, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x20, 0x40, 0xd0, 0x41, 0x40, 0x00, 0x00, 0x08,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x20, 0x40, 0x50, 0x41, 0x40, 0x00, 0x00, 0x00,
|
||||
0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static u32 sata_phy_read32(struct device *dev, u8 index)
|
||||
{
|
||||
/* The SATA PHY control registers are accessed by a funny index/value
|
||||
* scheme. Each byte (0,1,2,3) has its own 4-bit index */
|
||||
index = (index >> 2) & 0xf;
|
||||
u16 i16 = index | (index << 4) | (index << 8) | (index << 12);
|
||||
/* The index */
|
||||
pci_write_config16(dev, 0x68, i16);
|
||||
/* The value */
|
||||
return pci_read_config32(dev, 0x64);
|
||||
}
|
||||
|
||||
static void sata_phy_write32(struct device *dev, u8 index, u32 val)
|
||||
{
|
||||
/* The SATA PHY control registers are accessed by a funny index/value
|
||||
* scheme. Each byte (0,1,2,3) has its own 4-bit index */
|
||||
index = (index >> 2) & 0xf;
|
||||
u16 i16 = index | (index << 4) | (index << 8) | (index << 12);
|
||||
/* The index */
|
||||
pci_write_config16(dev, 0x68, i16);
|
||||
/* The value */
|
||||
pci_write_config32(dev, 0x64, val);
|
||||
}
|
||||
|
||||
static void vx900_sata_read_phy_config(struct device *dev, sata_phy_config cfg)
|
||||
{
|
||||
size_t i;
|
||||
u32 *data = (u32 *) cfg;
|
||||
for (i = 0; i < (sizeof(sata_phy_config)) >> 2; i++) {
|
||||
data[i] = sata_phy_read32(dev, i << 2);
|
||||
}
|
||||
}
|
||||
|
||||
static void vx900_sata_write_phy_config(struct device *dev, sata_phy_config cfg)
|
||||
{
|
||||
size_t i;
|
||||
u32 *data = (u32 *) cfg;
|
||||
for (i = 0; i < (sizeof(sata_phy_config)) >> 2; i++) {
|
||||
sata_phy_write32(dev, i << 2, data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void vx900_sata_dump_phy_config(sata_phy_config cfg)
|
||||
{
|
||||
printk(BIOS_DEBUG, "SATA PHY config:\n");
|
||||
int i;
|
||||
for (i = 0; i < sizeof(sata_phy_config); i++) {
|
||||
unsigned char val;
|
||||
if ((i & 0x0f) == 0)
|
||||
printk(BIOS_DEBUG, "%02x:", i);
|
||||
val = cfg[i];
|
||||
if ((i & 7) == 0)
|
||||
printk(BIOS_DEBUG, " |");
|
||||
printk(BIOS_DEBUG, " %02x", val);
|
||||
if ((i & 0x0f) == 0x0f) {
|
||||
printk(BIOS_DEBUG, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief VX900: Place the onboard SATA controller in Native IDE mode
|
||||
*
|
||||
* AHCI mode requires a sub-class of 0x06, and Interface of 0x0
|
||||
* SATA mode requires a sub-class of 0x06, and Interface of 0x00
|
||||
* Unfortunately, setting the class to SATA, will prevent us from modyfing the
|
||||
* interface register to an AHCI/SATA compliant value. Thus, payloads or OS may
|
||||
* not properly identify this as a SATA controller.
|
||||
* We could set the class code to 0x04, which would cause the interface register
|
||||
* to become 0x00, which represents a RAID controller. Unfortunately, when we do
|
||||
* this, SeaBIOS will skip this as a storage device, and we will not be able to
|
||||
* boot.
|
||||
* Our only option is to operate in IDE mode. We choose native IDE so that we
|
||||
* can freely assign an IRQ, and are not forced to use IRQ14
|
||||
*/
|
||||
static void vx900_native_ide_mode(struct device *dev)
|
||||
{
|
||||
/* Disable subclass write protect */
|
||||
pci_update_config8(dev, 0x45, (u8)~(1 << 7), 0);
|
||||
/* Change the device class to IDE */
|
||||
pci_write_config16(dev, PCI_CLASS_DEVICE, PCI_CLASS_STORAGE_IDE);
|
||||
/* Re-enable subclass write protect */
|
||||
pci_or_config8(dev, 0x45, 1 << 7);
|
||||
/* Put it in native IDE mode */
|
||||
pci_write_config8(dev, PCI_CLASS_PROG, 0x8f);
|
||||
}
|
||||
|
||||
static void vx900_sata_init(struct device *dev)
|
||||
{
|
||||
/* Enable SATA primary channel IO access */
|
||||
pci_or_config8(dev, 0x40, 1 << 1);
|
||||
/* Just SATA, so it makes sense to be in native SATA mode */
|
||||
vx900_native_ide_mode(dev);
|
||||
|
||||
/* TP Layer Idle at least 20us before the Following Command */
|
||||
pci_or_config8(dev, 0x53, 1 << 7);
|
||||
/* Resend COMRESET When Recovering SATA Gen2 Device Error */
|
||||
pci_update_config8(dev, 0x62, ~(1 << 1), 1 << 7);
|
||||
|
||||
/* Fix "PMP Device Can't Detect HDD Normally" (VIA Porting Guide)
|
||||
* SATA device detection will not work unless we clear these bits.
|
||||
* Without doing this, SeaBIOS (and potentially other payloads) will
|
||||
* timeout when detecting SATA devices */
|
||||
pci_update_config8(dev, 0x89, ~(1 << 3) | (1 << 6), 0);
|
||||
|
||||
/* 12.7 Two Software Resets May Affect the System
|
||||
* When the software does the second reset before the first reset
|
||||
* finishes, it may cause the system hang. It would do one software
|
||||
* reset and check the BSY bit of one port only, and the BSY bit of
|
||||
* other port would be 1, then it does another software reset
|
||||
* immediately and causes the system hang.
|
||||
* This is because the first software reset doesn't finish, and the
|
||||
* state machine of the host controller conflicts, it can't finish the
|
||||
* second one anymore. The BSY bit of slave port would be always 1 after
|
||||
* the second software reset issues. BIOS should set the following
|
||||
* bit to avoid this issue. */
|
||||
pci_or_config8(dev, 0x80, 1 << 6);
|
||||
|
||||
/* We need to set the EPHY values before doing anything with the link */
|
||||
sata_phy_config ephy;
|
||||
vx900_sata_read_phy_config(dev, ephy);
|
||||
if (1) {
|
||||
vx900_sata_dump_phy_config(ephy);
|
||||
vx900_sata_write_phy_config(dev, reference_ephy);
|
||||
} else {
|
||||
/* Enable TX and RX driving resistance */
|
||||
/* TX - 50 Ohm */
|
||||
ephy[1] &= ~(0x1f << 3);
|
||||
ephy[1] |= (1 << 7) | (8 << 3);
|
||||
/* RX - 50 Ohm */
|
||||
ephy[2] &= ~(0x1f << 3);
|
||||
ephy[2] |= (1 << 7) | (8 << 3);
|
||||
vx900_sata_write_phy_config(dev, ephy);
|
||||
}
|
||||
|
||||
vx900_sata_read_phy_config(dev, ephy);
|
||||
vx900_sata_dump_phy_config(ephy);
|
||||
|
||||
/* Clear error flags */
|
||||
pci_write_config32(dev, 0xa8, 0xffffffff);
|
||||
pci_write_config32(dev, 0xac, 0xffffffff);
|
||||
|
||||
/* Start OOB link negotiation sequence */
|
||||
pci_or_config8(dev, 0xb9, 3 << 4);
|
||||
|
||||
/* FIXME: From now on, we are just doing DEBUG stuff
|
||||
* Wait until PHY communication is enabled */
|
||||
u32 wloops = 0;
|
||||
while (!(pci_read_config8(dev, 0xa0) & (1 << 1)))
|
||||
wloops++;
|
||||
printk(BIOS_SPEW, "SATA wait loops: %u\n", wloops);
|
||||
|
||||
vx900_dbg_sata_errors(dev);
|
||||
}
|
||||
|
||||
static void vx900_sata_read_resources(struct device *dev)
|
||||
{
|
||||
pci_dev_read_resources(dev);
|
||||
}
|
||||
|
||||
static struct device_operations vga_operations = {
|
||||
.read_resources = vx900_sata_read_resources,
|
||||
.set_resources = pci_dev_set_resources,
|
||||
.enable_resources = pci_dev_enable_resources,
|
||||
.init = vx900_sata_init,
|
||||
};
|
||||
|
||||
static const struct pci_driver chrome9hd_driver __pci_driver = {
|
||||
.ops = &vga_operations,
|
||||
.vendor = PCI_VENDOR_ID_VIA,
|
||||
.device = PCI_DEVICE_ID_VIA_VX900_SATA,
|
||||
};
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@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.
|
||||
*/
|
||||
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ops.h>
|
||||
#include <device/pci_ids.h>
|
||||
#include <console/console.h>
|
||||
#include <drivers/generic/ioapic/chip.h>
|
||||
|
||||
#include "vx900.h"
|
||||
#include "chip.h"
|
||||
|
||||
/**
|
||||
* @file vx900/traf_ctrl.c
|
||||
*
|
||||
* STATUS:
|
||||
* The same issues with the IOAPIC pointe in lpc.c also apply here.
|
||||
*
|
||||
* We need to check if the current PCIE lane configuration mechanism is sane.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief VX900: Set up the north module IOAPIC (for PCIE and VGA)
|
||||
*
|
||||
* Enable the IOAPIC in the south module, and properly set it up.
|
||||
* \n
|
||||
* This is the hardware specific initialization for the IOAPIC, and complements
|
||||
* the setup done by the generic IOAPIC driver. In order for the IOAPIC to work
|
||||
* properly, it _must_ be declared in devicetree.cb .
|
||||
* \n
|
||||
* We are assuming this is called before the drivers/generic/ioapic code,
|
||||
* which should be the case if devicetree.cb is set up properly.
|
||||
*/
|
||||
static void vx900_north_ioapic_setup(struct device *dev)
|
||||
{
|
||||
u8 base_val;
|
||||
struct device *ioapic;
|
||||
ioapic_config_t *config;
|
||||
/* Find the IOAPIC, and make sure it's set up correctly in devicetree.cb
|
||||
* If it's not, then the generic ioapic driver will not set it up
|
||||
* correctly, and the MP table will not be correctly generated */
|
||||
for (ioapic = dev->next; ioapic; ioapic = ioapic->next) {
|
||||
if (ioapic->path.type == DEVICE_PATH_IOAPIC)
|
||||
break;
|
||||
}
|
||||
/* You did put an IOAPIC in devicetree.cb, didn't you? */
|
||||
if (ioapic == 0) {
|
||||
/* We don't have enough info to set up the IOAPIC */
|
||||
printk(BIOS_ERR, "ERROR: North module IOAPIC not found. "
|
||||
"Check your devicetree.cb\n");
|
||||
return;
|
||||
}
|
||||
/* Found our IOAPIC, and it should not carry ISA interrupts */
|
||||
config = (ioapic_config_t *) ioapic->chip_info;
|
||||
if (config->have_isa_interrupts) {
|
||||
/* Umh, is this the right IOAPIC ? */
|
||||
printk(BIOS_ERR, "ERROR: North module IOAPIC should not carry "
|
||||
"ISA interrupts.\n" "Check your devicetree.cb\n");
|
||||
printk(BIOS_ERR, "Will not initialize this IOAPIC.\n");
|
||||
return;
|
||||
}
|
||||
/* The base address of this IOAPIC _must_
|
||||
* be between 0xfec00000 and 0xfecfff00
|
||||
* be 256-byte aligned
|
||||
*/
|
||||
if ((config->base < (void *)0xfec0000 || config->base > (void *)0xfecfff00)
|
||||
|| (((uintptr_t)config->base & 0xff) != 0)) {
|
||||
printk(BIOS_ERR, "ERROR: North module IOAPIC base should be "
|
||||
"between 0xfec00000 and 0xfecfff00\n"
|
||||
"and must be aligned to a 256-byte boundary, "
|
||||
"but we found it at 0x%p\n", config->base);
|
||||
return;
|
||||
}
|
||||
|
||||
printk(BIOS_DEBUG, "VX900 TRAF_CTR: Setting up the north module IOAPIC "
|
||||
"at %p\n", config->base);
|
||||
|
||||
/* First register of the IOAPIC base */
|
||||
base_val = (((uintptr_t)config->base) >> 8) & 0xff;
|
||||
pci_write_config8(dev, 0x41, base_val);
|
||||
/* Second register of the base.
|
||||
* Bit[7] also enables the IOAPIC and bit[5] enables MSI cycles */
|
||||
base_val = (((uintptr_t)config->base) >> 16) & 0xf;
|
||||
pci_or_config8(dev, 0x40, base_val | (1 << 7) | (1 << 5));
|
||||
}
|
||||
|
||||
/*
|
||||
* Configures the PCI-express ports
|
||||
*
|
||||
* FIXME: triple-quadruple-check this
|
||||
*/
|
||||
static void vx900_pex_link_setup(struct device *dev)
|
||||
{
|
||||
u8 reg8;
|
||||
struct northbridge_via_vx900_config *nb = (void *)dev->chip_info;
|
||||
|
||||
reg8 = pci_read_config8(dev, 0xb0);
|
||||
reg8 &= ~((1 << 7) | (1 << 3));
|
||||
|
||||
if (nb->assign_pex_to_dp)
|
||||
reg8 |= (1 << 7);
|
||||
|
||||
if (!nb->pcie_port1_2_lane_wide)
|
||||
reg8 |= (1 << 3);
|
||||
|
||||
pci_write_config8(dev, 0xb0, reg8);
|
||||
}
|
||||
|
||||
static void vx900_traf_ctr_init(struct device *dev)
|
||||
{
|
||||
vx900_north_ioapic_setup(dev);
|
||||
vx900_pex_link_setup(dev);
|
||||
}
|
||||
|
||||
static struct device_operations traf_ctrl_ops = {
|
||||
.read_resources = pci_dev_read_resources,
|
||||
.set_resources = pci_dev_set_resources,
|
||||
.enable_resources = pci_dev_enable_resources,
|
||||
.init = vx900_traf_ctr_init,
|
||||
/* Need this here, or the IOAPIC driver won't be called.
|
||||
* FIXME: Technically not a LPC bus. */
|
||||
.scan_bus = scan_static_bus,
|
||||
};
|
||||
|
||||
static const struct pci_driver traf_ctrl_driver __pci_driver = {
|
||||
.ops = &traf_ctrl_ops,
|
||||
.vendor = PCI_VENDOR_ID_VIA,
|
||||
.device = PCI_DEVICE_ID_VIA_VX900_TRAF,
|
||||
};
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2011 Alexandru Gagniuc <mr.nuke.me@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.
|
||||
*/
|
||||
#ifndef __VX900_H
|
||||
#define __VX900_H
|
||||
|
||||
#define VX900_ACPI_IO_BASE 0x0400
|
||||
|
||||
#define SMBUS_IO_BASE 0x500
|
||||
|
||||
#define VX900_MMCONFIG_MBAR 0xbc
|
||||
|
||||
/* The maximum number of DIMM slots that the VX900 supports */
|
||||
#define VX900_MAX_DIMM_SLOTS 2
|
||||
#define VX900_MAX_MEM_RANKS 4
|
||||
|
||||
#include <device/pci_ops.h>
|
||||
#include <device/pci.h>
|
||||
|
||||
u32 vx900_get_tolm(void);
|
||||
void vx900_set_chrome9hd_fb_size(u32 size_mb);
|
||||
u8 vx900_get_chrome9hd_fb_pow(void);
|
||||
u32 vx900_get_chrome9hd_fb_size(void);
|
||||
u8 vx900_int15_get_5f18_bl(void);
|
||||
uint64_t get_uma_memory_base(void);
|
||||
|
||||
/* We use these throughout the code. They really belong in a generic part of
|
||||
* coreboot, but until bureaucracy gets them there, we still need them */
|
||||
|
||||
void dump_pci_device(pci_devfn_t dev);
|
||||
|
||||
#endif /* __VX900_H */
|
Loading…
Reference in New Issue