the attached patch is a rework of the patch you posted earlier.
Basically, I cleaned up the mixed tab/spaces indentation and
tried to make the layout more consistent.
--
http://www.hailfinger.org/
Commit yhLu's mcp55 code.
Not tested, the only way to test is to get his changes in and modify the failing bits AFAIK.
his tree diverged.
At the same time, nothing looks obviously wrong.
(Carl-Daniel Hailfinger: Fixed whitespace)
Signed-off-by: Ronald G. Minnich
rminnich@gmail.com
Signed-off-by: Carl-Daniel Hailfinger
c-d.hailfinger.devel.2006@gmx.net
Index: mcp55/romstrap.inc
===================================================================
--- mcp55/romstrap.inc (revision 0)
+++ mcp55/romstrap.inc (revision 0)
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ */
+ .section ".romstrap", "a", @progbits
+
+
+ .globl __romstrap_start
+__romstrap_start:
+rstables:
+ .long 0x2b16d065
+ .long 0x0
+ .long 0x0
+ .long linkedlist
+
+linkedlist:
+ .long 0x0003001C // 10h
+ .long 0x08000000 // 14h
+ .long 0x00000000 // 18h
+ .long 0xFFFFFFFF // 1Ch
+
+ .long 0xFFFFFFFF // 20h
+ .long 0xFFFFFFFF // 24h
+ .long 0xFFFFFFFF // 28h
+ .long 0xFFFFFFFF // 2Ch
+
+ .long 0x81543266 // 30h, MAC address low 4 byte ---> keep it in 0xffffffd0
+ .long 0x000000E0 // 34h, MAC address high 4 byte
+
+ .long 0x002309CE // 38h, UUID low 4 byte
+ .long 0x00E08100 // 3Ch, UUID high 4 byte
+
+rspointers:
+ .long rstables // It will be 0xffffffe0
+ .long rstables
+ .long rstables
+ .long rstables
+
+ .globl __romstrap_end
+
+__romstrap_end:
+.previous
Index: mcp55/mcp55.h
===================================================================
--- mcp55/mcp55.h (revision 0)
+++ mcp55/mcp55.h (revision 0)
@@ -0,0 +1,8 @@
+#ifndef MCP55_H
+#define MCP55_H
+
+#include "chip.h"
+
+void mcp55_enable(device_t dev);
+
+#endif /* MCP55_H */
Index: mcp55/mcp55_early_smbus.c
===================================================================
--- mcp55/mcp55_early_smbus.c (revision 0)
+++ mcp55/mcp55_early_smbus.c (revision 0)
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ * Copyright 2006,2007 AMD inc.
+ * by yinghai.lu@amd.com
+ */
+
+#include "mcp55_smbus.h"
+
+#define SMBUS0_IO_BASE 0x1000
+#define SMBUS1_IO_BASE (0x1000+(1<<8))
+/*SIZE 0x40 */
+
+static void enable_smbus(void)
+{
+ device_t dev;
+ dev = pci_locate_device(PCI_ID(0x10de, 0x0368), 0);
+#if 0
+ if (dev == PCI_DEV_INVALID) {
+ die("SMBUS controller not found\r\n");
+ }
+
+ print_debug("SMBus controller enabled\r\n");
+#endif
+ /* set smbus iobase */
+ pci_write_config32(dev, 0x20, SMBUS0_IO_BASE | 1);
+ pci_write_config32(dev, 0x24, SMBUS1_IO_BASE | 1);
+ /* Set smbus iospace enable */
+ pci_write_config16(dev, 0x4, 0x01);
+ /* clear any lingering errors, so the transaction will run */
+ outb(inb(SMBUS0_IO_BASE + SMBHSTSTAT), SMBUS0_IO_BASE + SMBHSTSTAT);
+ outb(inb(SMBUS1_IO_BASE + SMBHSTSTAT), SMBUS1_IO_BASE + SMBHSTSTAT);
+}
+
+static int smbus_recv_byte(unsigned device)
+{
+ return do_smbus_recv_byte(SMBUS0_IO_BASE, device);
+}
+static int smbus_send_byte(unsigned device, unsigned char val)
+{
+ return do_smbus_send_byte(SMBUS0_IO_BASE, device, val);
+}
+static int smbus_read_byte(unsigned device, unsigned address)
+{
+ return do_smbus_read_byte(SMBUS0_IO_BASE, device, address);
+}
+static int smbus_write_byte(unsigned device, unsigned address, unsigned char val)
+{
+ return do_smbus_write_byte(SMBUS0_IO_BASE, device, address, val);
+}
+
+static int smbusx_recv_byte(unsigned smb_index, unsigned device)
+{
+ return do_smbus_recv_byte(SMBUS0_IO_BASE + (smb_index<<8), device);
+}
+static int smbusx_send_byte(unsigned smb_index, unsigned device, unsigned char val)
+{
+ return do_smbus_send_byte(SMBUS0_IO_BASE + (smb_index<<8), device, val);
+}
+static int smbusx_read_byte(unsigned smb_index, unsigned device, unsigned address)
+{
+ return do_smbus_read_byte(SMBUS0_IO_BASE + (smb_index<<8), device, address);
+}
+static int smbusx_write_byte(unsigned smb_index, unsigned device, unsigned address, unsigned char val)
+{
+ return do_smbus_write_byte(SMBUS0_IO_BASE + (smb_index<<8), device, address, val);
+}
+
Index: mcp55/mcp55_sata.c
===================================================================
--- mcp55/mcp55_sata.c (revision 0)
+++ mcp55/mcp55_sata.c (revision 0)
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ * Copyright 2006,2007 AMD inc.
+ * by yinghai.lu@amd.com
+ */
+#include <console/console.h>
+#include <device/device.h>
+#include <delay.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "mcp55.h"
+
+static void sata_init(struct device *dev)
+{
+ uint32_t dword;
+
+ struct southbridge_nvidia_mcp55_config *conf;
+ conf = dev->chip_info;
+
+ dword = pci_read_config32(dev, 0x50);
+ /* Ensure prefetch is disabled */
+ dword &= ~((1 << 15) | (1 << 13));
+ if(conf) {
+ if (conf->sata1_enable) {
+ /* Enable secondary SATA interface */
+ dword |= (1<<0);
+ printk_debug("SATA S \t");
+ }
+ if (conf->sata0_enable) {
+ /* Enable primary SATA interface */
+ dword |= (1<<1);
+ printk_debug("SATA P \n");
+ }
+ } else {
+ dword |= (1<<1) | (1<<0);
+ printk_debug("SATA P and S \n");
+ }
+
+
+#if 1
+ dword &= ~(0x1f<<24);
+ dword |= (0x15<<24);
+#endif
+ pci_write_config32(dev, 0x50, dword);
+
+ dword = pci_read_config32(dev, 0xf8);
+ dword |= 2;
+ pci_write_config32(dev, 0xf8, dword);
+
+
+}
+
+static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ pci_write_config32(dev, 0x40,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+static struct pci_operations lops_pci = {
+ .set_subsystem = lpci_set_subsystem,
+};
+
+static struct device_operations sata_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+// .enable = mcp55_enable,
+ .init = sata_init,
+ .scan_bus = 0,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver sata0_driver __pci_driver = {
+ .ops = &sata_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_SATA0,
+};
+
+static struct pci_driver sata1_driver __pci_driver = {
+ .ops = &sata_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_SATA1,
+};
Index: mcp55/mcp55_usb.c
===================================================================
--- mcp55/mcp55_usb.c (revision 0)
+++ mcp55/mcp55_usb.c (revision 0)
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ * Copyright 2006,2007 AMD inc.
+ * by yinghai.lu@amd.com
+ */
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "mcp55.h"
+
+static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ pci_write_config32(dev, 0x40,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+static struct pci_operations lops_pci = {
+ .set_subsystem = lpci_set_subsystem,
+};
+
+static struct device_operations usb_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = 0,
+// .enable = mcp55_enable,
+ .scan_bus = 0,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver usb_driver __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_USB,
+};
+
Index: mcp55/mcp55_smbus.c
===================================================================
--- mcp55/mcp55_smbus.c (revision 0)
+++ mcp55/mcp55_smbus.c (revision 0)
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ * Copyright 2006,2007 AMD inc.
+ * by yinghai.lu@amd.com
+ */
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <device/smbus.h>
+#include <bitops.h>
+#include <arch/io.h>
+#include "mcp55.h"
+#include "mcp55_smbus.h"
+
+static int lsmbus_recv_byte(device_t dev)
+{
+ unsigned device;
+ struct resource *res;
+ struct bus *pbus;
+
+ device = dev->path.u.i2c.device;
+ pbus = get_pbus_smbus(dev);
+
+ res = find_resource(pbus->dev, 0x20 + (pbus->link * 4));
+
+ return do_smbus_recv_byte(res->base, device);
+}
+
+static int lsmbus_send_byte(device_t dev, uint8_t val)
+{
+ unsigned device;
+ struct resource *res;
+ struct bus *pbus;
+
+ device = dev->path.u.i2c.device;
+ pbus = get_pbus_smbus(dev);
+
+ res = find_resource(pbus->dev, 0x20 + (pbus->link * 4));
+
+ return do_smbus_send_byte(res->base, device, val);
+}
+
+static int lsmbus_read_byte(device_t dev, uint8_t address)
+{
+ unsigned device;
+ struct resource *res;
+ struct bus *pbus;
+
+ device = dev->path.u.i2c.device;
+ pbus = get_pbus_smbus(dev);
+
+ res = find_resource(pbus->dev, 0x20 + (pbus->link * 4));
+
+ return do_smbus_read_byte(res->base, device, address);
+}
+
+static int lsmbus_write_byte(device_t dev, uint8_t address, uint8_t val)
+{
+ unsigned device;
+ struct resource *res;
+ struct bus *pbus;
+
+ device = dev->path.u.i2c.device;
+ pbus = get_pbus_smbus(dev);
+
+ res = find_resource(pbus->dev, 0x20 + (pbus->link * 4));
+
+ return do_smbus_write_byte(res->base, device, address, val);
+}
+static struct smbus_bus_operations lops_smbus_bus = {
+ .recv_byte = lsmbus_recv_byte,
+ .send_byte = lsmbus_send_byte,
+ .read_byte = lsmbus_read_byte,
+ .write_byte = lsmbus_write_byte,
+};
+
+#if HAVE_ACPI_TABLES == 1
+unsigned pm_base;
+#endif
+
+static void mcp55_sm_read_resources(device_t dev)
+{
+ struct resource *res;
+ unsigned long index;
+
+ /* Get the normal pci resources of this device */
+ pci_dev_read_resources(dev);
+
+ for (index = 0x60; index <= 0x68; index+=4) { // We got another 3.
+ pci_get_resource(dev, index);
+ }
+ compact_resources(dev);
+
+}
+
+static void mcp55_sm_init(device_t dev)
+{
+#if HAVE_ACPI_TABLES == 1
+ struct resource *res;
+
+ res = find_resource(dev, 0x60);
+
+ if (res)
+ pm_base = res->base;
+#endif
+}
+
+static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ pci_write_config32(dev, 0x40,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = lpci_set_subsystem,
+};
+static struct device_operations smbus_ops = {
+ .read_resources = mcp55_sm_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = mcp55_sm_init,
+ .scan_bus = scan_static_bus,
+// .enable = mcp55_enable,
+ .ops_pci = &lops_pci,
+ .ops_smbus_bus = &lops_smbus_bus,
+};
+static struct pci_driver smbus_driver __pci_driver = {
+ .ops = &smbus_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_SM2,
+};
+
Index: mcp55/romstrap.lds
===================================================================
--- mcp55/romstrap.lds (revision 0)
+++ mcp55/romstrap.lds (revision 0)
@@ -0,0 +1,6 @@
+SECTIONS {
+ . = (_ROMBASE + ROM_IMAGE_SIZE - 0x10) - (__romstrap_end - __romstrap_start);
+ .romstrap (.): {
+ *(.romstrap)
+ }
+}
Index: mcp55/mcp55_smbus.h
===================================================================
--- mcp55/mcp55_smbus.h (revision 0)
+++ mcp55/mcp55_smbus.h (revision 0)
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ * Copyright 2006,2007 AMD inc.
+ * by yinghai.lu@amd.com
+ */
+#include <device/smbus_def.h>
+
+#define SMBHSTSTAT 0x1
+#define SMBHSTPRTCL 0x0
+#define SMBHSTCMD 0x3
+#define SMBXMITADD 0x2
+#define SMBHSTDAT0 0x4
+#define SMBHSTDAT1 0x5
+
+/* Between 1-10 seconds, We should never timeout normally
+ * Longer than this is just painful when a timeout condition occurs.
+ */
+#define SMBUS_TIMEOUT (100*1000*10)
+
+static inline void smbus_delay(void)
+{
+ outb(0x80, 0x80);
+}
+
+static int smbus_wait_until_ready(unsigned smbus_io_base)
+{
+ unsigned long loops;
+ loops = SMBUS_TIMEOUT;
+ do {
+ unsigned char val;
+ smbus_delay();
+ val = inb(smbus_io_base + SMBHSTSTAT);
+ val &= 0x1f;
+ if (val == 0) {
+ return 0;
+ }
+ outb(val,smbus_io_base + SMBHSTSTAT);
+ } while(--loops);
+ return -2;
+}
+
+static int smbus_wait_until_done(unsigned smbus_io_base)
+{
+ unsigned long loops;
+ loops = SMBUS_TIMEOUT;
+ do {
+ unsigned char val;
+ smbus_delay();
+
+ val = inb(smbus_io_base + SMBHSTSTAT);
+ if ( (val & 0xff) != 0) {
+ return 0;
+ }
+ } while(--loops);
+ return -3;
+}
+static int do_smbus_recv_byte(unsigned smbus_io_base, unsigned device)
+{
+ unsigned char global_status_register;
+ unsigned char byte;
+
+ /* set the device I'm talking too */
+ outb(((device & 0x7f) << 1)|1 , smbus_io_base + SMBXMITADD);
+ smbus_delay();
+ /* set the command/address... */
+ outb(0, smbus_io_base + SMBHSTCMD);
+ smbus_delay();
+ /* byte data recv */
+ outb(0x05, smbus_io_base + SMBHSTPRTCL);
+ smbus_delay();
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_done(smbus_io_base) < 0) {
+ return -3;
+ }
+
+ global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80; /* lose check */
+
+ /* read results of transaction */
+ byte = inb(smbus_io_base + SMBHSTDAT0);
+
+ if (global_status_register != 0x80) { // lose check, otherwise it should be 0
+ return -1;
+ }
+ return byte;
+}
+static int do_smbus_send_byte(unsigned smbus_io_base, unsigned device, unsigned char val)
+{
+ unsigned global_status_register;
+
+ outb(val, smbus_io_base + SMBHSTDAT0);
+ smbus_delay();
+
+ /* set the device I'm talking too */
+ outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBXMITADD);
+ smbus_delay();
+
+ outb(0, smbus_io_base + SMBHSTCMD);
+ smbus_delay();
+
+ /* set up for a byte data write */
+ outb(0x04, smbus_io_base + SMBHSTPRTCL);
+ smbus_delay();
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_done(smbus_io_base) < 0) {
+ return -3;
+ }
+ global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80; /* lose check */;
+
+ if (global_status_register != 0x80) {
+ return -1;
+ }
+ return 0;
+}
+static int do_smbus_read_byte(unsigned smbus_io_base, unsigned device, unsigned address)
+{
+ unsigned char global_status_register;
+ unsigned char byte;
+
+ /* set the device I'm talking too */
+ outb(((device & 0x7f) << 1)|1 , smbus_io_base + SMBXMITADD);
+ smbus_delay();
+ /* set the command/address... */
+ outb(address & 0xff, smbus_io_base + SMBHSTCMD);
+ smbus_delay();
+ /* byte data read */
+ outb(0x07, smbus_io_base + SMBHSTPRTCL);
+ smbus_delay();
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_done(smbus_io_base) < 0) {
+ return -3;
+ }
+
+ global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80; /* lose check */
+
+ /* read results of transaction */
+ byte = inb(smbus_io_base + SMBHSTDAT0);
+
+ if (global_status_register != 0x80) { // lose check, otherwise it should be 0
+ return -1;
+ }
+ return byte;
+}
+
+
+static int do_smbus_write_byte(unsigned smbus_io_base, unsigned device, unsigned address, unsigned char val)
+{
+ unsigned global_status_register;
+
+ outb(val, smbus_io_base + SMBHSTDAT0);
+ smbus_delay();
+
+ /* set the device I'm talking too */
+ outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBXMITADD);
+ smbus_delay();
+
+ outb(address & 0xff, smbus_io_base + SMBHSTCMD);
+ smbus_delay();
+
+ /* set up for a byte data write */
+ outb(0x06, smbus_io_base + SMBHSTPRTCL);
+ smbus_delay();
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_done(smbus_io_base) < 0) {
+ return -3;
+ }
+ global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80; /* lose check */;
+
+ if (global_status_register != 0x80) {
+ return -1;
+ }
+ return 0;
+}
+
Index: mcp55/mcp55_early_ctrl.c
===================================================================
--- mcp55/mcp55_early_ctrl.c (revision 0)
+++ mcp55/mcp55_early_ctrl.c (revision 0)
@@ -0,0 +1,39 @@
+static unsigned get_sbdn(unsigned bus)
+{
+ device_t dev;
+
+ /* Find the device.
+ */
+ dev = pci_locate_device_on_bus(
+ PCI_ID(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP55_HT),
+ bus);
+
+ return (dev>>15) & 0x1f;
+
+}
+
+static void hard_reset(void)
+{
+ set_bios_reset();
+
+ /* full reset */
+ outb(0x0a, 0x0cf9);
+ outb(0x0e, 0x0cf9);
+}
+static void enable_fid_change_on_sb(unsigned sbbusn, unsigned sbdn)
+{
+/* default value for mcp55 is good */
+ /* set VFSMAF ( VID/FID System Management Action Field) to 2 */
+
+}
+
+static void soft_reset(void)
+{
+ set_bios_reset();
+#if 1
+ /* link reset */
+ outb(0x02, 0x0cf9);
+ outb(0x06, 0x0cf9);
+#endif
+}
+
Index: mcp55/mcp55_enable_usbdebug_direct.c
===================================================================
--- mcp55/mcp55_enable_usbdebug_direct.c (revision 0)
+++ mcp55/mcp55_enable_usbdebug_direct.c (revision 0)
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ * Copyright 2006,2007 AMD inc.
+ * by yinghai.lu@amd.com
+ */
+
+#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE
+ #define MCP55_DEVN_BASE HT_CHAIN_END_UNITID_BASE
+#else
+ #define MCP55_DEVN_BASE HT_CHAIN_UNITID_BASE
+#endif
+
+#define EHCI_BAR_INDEX 0x10
+#define EHCI_BAR 0xFEF00000
+#define EHCI_DEBUG_OFFSET 0x98
+
+static void set_debug_port(unsigned port)
+{
+ uint32_t dword;
+ dword = pci_read_config32(PCI_DEV(0, MCP55_DEVN_BASE+2, 1), 0x74);
+ dword &= ~(0xf<<12);
+ dword |= (port<<12);
+ pci_write_config32(PCI_DEV(0, MCP55_DEVN_BASE+2, 1), 0x74, dword);
+
+}
+
+static void mcp55_enable_usbdebug_direct(unsigned port)
+{
+ set_debug_port(port);
+ pci_write_config32(PCI_DEV(0, MCP55_DEVN_BASE+2, 1), EHCI_BAR_INDEX, EHCI_BAR);
+ pci_write_config8(PCI_DEV(0, MCP55_DEVN_BASE+2, 1), 0x04, 0x2); // mem space enabe
+}
+
Index: mcp55/mcp55_ide.c
===================================================================
--- mcp55/mcp55_ide.c (revision 0)
+++ mcp55/mcp55_ide.c (revision 0)
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ * Copyright 2006,2007 AMD inc.
+ * by yinghai.lu@amd.com
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "mcp55.h"
+
+static void ide_init(struct device *dev)
+{
+ struct southbridge_nvidia_mcp55_config *conf;
+ /* Enable ide devices so the linux ide driver will work */
+ uint32_t dword;
+ uint16_t word;
+ uint8_t byte;
+ conf = dev->chip_info;
+
+ word = pci_read_config16(dev, 0x50);
+ /* Ensure prefetch is disabled */
+ word &= ~((1 << 15) | (1 << 13));
+ if (conf->ide1_enable) {
+ /* Enable secondary ide interface */
+ word |= (1<<0);
+ printk_debug("IDE1 \t");
+ }
+ if (conf->ide0_enable) {
+ /* Enable primary ide interface */
+ word |= (1<<1);
+ printk_debug("IDE0\n");
+ }
+
+ word |= (1<<12);
+ word |= (1<<14);
+
+ pci_write_config16(dev, 0x50, word);
+
+
+ byte = 0x20 ; // Latency: 64-->32
+ pci_write_config8(dev, 0xd, byte);
+
+ dword = pci_read_config32(dev, 0xf8);
+ dword |= 12;
+ pci_write_config32(dev, 0xf8, dword);
+#if CONFIG_PCI_ROM_RUN == 1
+ pci_dev_init(dev);
+#endif
+
+}
+
+static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ pci_write_config32(dev, 0x40,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+static struct pci_operations lops_pci = {
+ .set_subsystem = lpci_set_subsystem,
+};
+
+static struct device_operations ide_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = ide_init,
+ .scan_bus = 0,
+// .enable = mcp55_enable,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver ide_driver __pci_driver = {
+ .ops = &ide_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_IDE,
+};
+
Index: mcp55/mcp55_enable_rom.c
===================================================================
--- mcp55/mcp55_enable_rom.c (revision 0)
+++ mcp55/mcp55_enable_rom.c (revision 0)
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ * Copyright 2006,2007 AMD inc.
+ * by yinghai.lu@amd.com
+ */
+
+#if HT_CHAIN_END_UNITID_BASE < HT_CHAIN_UNITID_BASE
+ #define MCP55_DEVN_BASE HT_CHAIN_END_UNITID_BASE
+#else
+ #define MCP55_DEVN_BASE HT_CHAIN_UNITID_BASE
+#endif
+
+static void mcp55_enable_rom(void)
+{
+ uint8_t byte;
+ uint16_t word;
+ device_t addr;
+
+ /* Enable 4MB rom access at 0xFFC00000 - 0xFFFFFFFF */
+#if 0
+ /* default MCP55 LPC single */
+ addr = pci_locate_device(PCI_ID(0x10de, 0x0367), 0);
+#else
+// addr = pci_locate_device(PCI_ID(0x10de, 0x0360), 0);
+ addr = PCI_DEV(0, (MCP55_DEVN_BASE+1), 0);
+#endif
+
+ /* Set the 4MB enable bit bit */
+ byte = pci_read_config8(addr, 0x88);
+ byte |= 0xff; //256K
+ pci_write_config8(addr, 0x88, byte);
+ byte = pci_read_config8(addr, 0x8c);
+ byte |= 0xff; //1M
+ pci_write_config8(addr, 0x8c, byte);
+ word = pci_read_config16(addr, 0x90);
+ word |= 0x7fff; //15M
+ pci_write_config16(addr, 0x90, word);
+}
Index: mcp55/mcp55_early_setup_ss.h
===================================================================
--- mcp55/mcp55_early_setup_ss.h (revision 0)
+++ mcp55/mcp55_early_setup_ss.h (revision 0)
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ */
+
+static const unsigned int pcie_ss_tbl[] = {
+ 0x0C504103f,
+ 0x0C504103f,
+ 0x0C504103f,
+ 0x0C5042040,
+ 0x0C5042040,
+ 0x0C5042040,
+ 0x0C5043041,
+ 0x0C5043041,
+ 0x0C5043041,
+ 0x0C5043041,
+ 0x0C5044042,
+ 0x0C5044042,
+ 0x0C5044042,
+ 0x0C5045043,
+ 0x0C5045043,
+ 0x0C5045043,
+ 0x0C5045043,
+ 0x0C5045043,
+ 0x0C5046044,
+ 0x0C5046044,
+ 0x0C5046044,
+ 0x0C5046044,
+ 0x0C5047045,
+ 0x0C5047045,
+ 0x0C5047045,
+ 0x0C5047045,
+ 0x0C5047045,
+ 0x0C5048046,
+ 0x0C5048046,
+ 0x0C5048046,
+ 0x0C5048046,
+ 0x0C5049047,
+ 0x0C5049047,
+ 0x0C5049047,
+ 0x0C504a048,
+ 0x0C504a048,
+ 0x0C504b049,
+ 0x0C504b049,
+ 0x0C504a048,
+ 0x0C504a048,
+ 0x0C5049047,
+ 0x0C5049047,
+ 0x0C5048046,
+ 0x0C5048046,
+ 0x0C5048046,
+ 0x0C5047045,
+ 0x0C5047045,
+ 0x0C5047045,
+ 0x0C5047045,
+ 0x0C5047045,
+ 0x0C5046044,
+ 0x0C5046044,
+ 0x0C5046044,
+ 0x0C5046044,
+ 0x0C5045043,
+ 0x0C5045043,
+ 0x0C5045043,
+ 0x0C5044042,
+ 0x0C5044042,
+ 0x0C5044042,
+ 0x0C5043041,
+ 0x0C5043041,
+ 0x0C5042040,
+ 0x0C5042040,
+};
+static const unsigned int sata_ss_tbl[] = {
+ 0x0c9044042,
+ 0x0c9044042,
+ 0x0c9044042,
+ 0x0c9045043,
+ 0x0c9045043,
+ 0x0c9045043,
+ 0x0c9045043,
+ 0x0c9045043,
+ 0x0c9046044,
+ 0x0c9046044,
+ 0x0c9046044,
+ 0x0c9046044,
+ 0x0c9047045,
+ 0x0c9047045,
+ 0x0c9047045,
+ 0x0c9047045,
+ 0x0c9047045,
+ 0x0c9048046,
+ 0x0c9048046,
+ 0x0c9048046,
+ 0x0c9048046,
+ 0x0c9049047,
+ 0x0c9049047,
+ 0x0c9049047,
+ 0x0c9049047,
+ 0x0c904a048,
+ 0x0c904a048,
+ 0x0c904a048,
+ 0x0c904a048,
+ 0x0c904b049,
+ 0x0c904b049,
+ 0x0c904b049,
+ 0x0c904b049,
+ 0x0c904b049,
+ 0x0c904b049,
+ 0x0c904a048,
+ 0x0c904a048,
+ 0x0c904a048,
+ 0x0c904a048,
+ 0x0c9049047,
+ 0x0c9049047,
+ 0x0c9049047,
+ 0x0c9049047,
+ 0x0c9048046,
+ 0x0c9048046,
+ 0x0c9048046,
+ 0x0c9048046,
+ 0x0c9047045,
+ 0x0c9047045,
+ 0x0c9047045,
+ 0x0c9047045,
+ 0x0c9047045,
+ 0x0c9046044,
+ 0x0c9046044,
+ 0x0c9046044,
+ 0x0c9046044,
+ 0x0c9045043,
+ 0x0c9045043,
+ 0x0c9045043,
+ 0x0c9045043,
+ 0x0c9045043,
+ 0x0c9044042,
+ 0x0c9044042,
+ 0x0c9044042,
+};
+
+static const unsigned int cpu_ss_tbl[] = {
+ 0x0C5038036,
+ 0x0C5038036,
+ 0x0C5038036,
+ 0x0C5037035,
+ 0x0C5037035,
+ 0x0C5037035,
+ 0x0C5037035,
+ 0x0C5036034,
+ 0x0C5036034,
+ 0x0C5036034,
+ 0x0C5036034,
+ 0x0C5036034,
+ 0x0C5035033,
+ 0x0C5035033,
+ 0x0C5035033,
+ 0x0C5035033,
+ 0x0C5035033,
+ 0x0C5035033,
+ 0x0C5034032,
+ 0x0C5034032,
+ 0x0C5034032,
+ 0x0C5034032,
+ 0x0C5034032,
+ 0x0C5034032,
+ 0x0C5035033,
+ 0x0C5035033,
+ 0x0C5035033,
+ 0x0C5035033,
+ 0x0C5035033,
+ 0x0C5036034,
+ 0x0C5036034,
+ 0x0C5036034,
+ 0x0C5036034,
+ 0x0C5036034,
+ 0x0C5037035,
+ 0x0C5037035,
+ 0x0C5037035,
+ 0x0C5037035,
+ 0x0C5038036,
+ 0x0C5038036,
+ 0x0C5038036,
+ 0x0C5038036,
+ 0x0C5039037,
+ 0x0C5039037,
+ 0x0C5039037,
+ 0x0C5039037,
+ 0x0C503a038,
+ 0x0C503a038,
+ 0x0C503a038,
+ 0x0C503a038,
+ 0x0C503b039,
+ 0x0C503b039,
+ 0x0C503b039,
+ 0x0C503b039,
+ 0x0C503b039,
+ 0x0C503a038,
+ 0x0C503a038,
+ 0x0C503a038,
+ 0x0C503a038,
+ 0x0C503a038,
+ 0x0C5039037,
+ 0x0C5039037,
+ 0x0C5039037,
+ 0x0C5039037,
+};
+
+
Index: mcp55/Config.lb
===================================================================
--- mcp55/Config.lb (revision 0)
+++ mcp55/Config.lb (revision 0)
@@ -0,0 +1,14 @@
+config chip.h
+driver mcp55.o
+driver mcp55_usb.o
+driver mcp55_lpc.o
+driver mcp55_smbus.o
+driver mcp55_ide.o
+driver mcp55_sata.o
+driver mcp55_usb2.o
+driver mcp55_aza.o
+driver mcp55_nic.o
+driver mcp55_pci.o
+driver mcp55_pcie.o
+driver mcp55_ht.o
+object mcp55_reset.o
Index: mcp55/mcp55_nic.c
===================================================================
--- mcp55/mcp55_nic.c (revision 0)
+++ mcp55/mcp55_nic.c (revision 0)
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ * Copyright 2006,2007 AMD inc.
+ * by yinghai.lu@amd.com
+ */
+#include <console/console.h>
+#include <device/device.h>
+#include <device/smbus.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <arch/io.h>
+#include "mcp55.h"
+
+static int phy_read(uint8_t *base, unsigned phy_addr, unsigned phy_reg)
+{
+ uint32_t dword;
+ unsigned loop = 0x100;
+ writel(0x8000, base+0x190); //Clear MDIO lock bit
+ mdelay(1);
+ dword = readl(base+0x190);
+ if(dword & (1<<15)) return -1;
+
+ writel(1, base+0x180);
+ writel((phy_addr<<5) | (phy_reg),base + 0x190);
+ do{
+ dword = readl(base + 0x190);
+ if(--loop==0) return -4;
+ } while ((dword & (1<<15)) );
+
+ dword = readl(base + 0x180);
+ if(dword & 1) return -3;
+
+ dword = readl(base + 0x194);
+
+ return dword;
+
+}
+
+static int phy_detect(uint8_t *base)
+{
+ uint32_t dword;
+ int i;
+ int val;
+ unsigned id;
+ dword = readl(base+0x188);
+ dword &= ~(1<<20);
+ writel(dword, base+0x188);
+
+ phy_read(base, 0, 1);
+
+ for(i=1; i<=32; i++) {
+ int phyaddr = i & 0x1f;
+ val = phy_read(base, phyaddr, 1);
+ if(val<0) continue;
+ if((val & 0xffff) == 0xfffff) continue;
+ if((val & 0xffff) == 0) continue;
+ if(!(val & 1)) {
+ break; // Ethernet PHY
+ }
+ val = phy_read(base, phyaddr, 3);
+ if (val < 0 || val == 0xffff) continue;
+ id = val & 0xfc00;
+ val = phy_read(base, phyaddr, 2);
+ if (val < 0 || val == 0xffff) continue;
+ id |= ((val & 0xffff)<<16);
+ printk_debug("MCP55 MAC PHY ID 0x%08x PHY ADDR %d\n", id, i);
+// if((id == 0xe0180000) || (id==0x0032cc00))
+ break;
+ }
+
+ if(i>32) {
+ printk_debug("MCP55 MAC PHY not found\n");
+ }
+
+}
+static void nic_init(struct device *dev)
+{
+ uint32_t dword, old;
+ uint32_t mac_h, mac_l;
+ int eeprom_valid = 0;
+ struct southbridge_nvidia_mcp55_config *conf;
+
+ static uint32_t nic_index = 0;
+
+ uint8_t *base;
+ struct resource *res;
+
+ res = find_resource(dev, 0x10);
+
+ if(!res) return;
+
+ base = res->base;
+
+ phy_detect(base);
+
+#define NvRegPhyInterface 0xC0
+#define PHY_RGMII 0x10000000
+
+ writel(PHY_RGMII, base + NvRegPhyInterface);
+
+ conf = dev->chip_info;
+
+ if(conf->mac_eeprom_smbus != 0) {
+// read MAC address from EEPROM at first
+ struct device *dev_eeprom;
+ dev_eeprom = dev_find_slot_on_smbus(conf->mac_eeprom_smbus, conf->mac_eeprom_addr);
+
+ if(dev_eeprom) {
+ // if that is valid we will use that
+ unsigned char dat[6];
+ int status;
+ int i;
+ for(i=0;i<6;i++) {
+ status = smbus_read_byte(dev_eeprom, i);
+ if(status < 0) break;
+ dat[i] = status & 0xff;
+ }
+ if(status >= 0) {
+ mac_l = 0;
+ for(i=3;i>=0;i--) {
+ mac_l <<= 8;
+ mac_l += dat[i];
+ }
+ if(mac_l != 0xffffffff) {
+ mac_l += nic_index;
+ mac_h = 0;
+ for(i=5;i>=4;i--) {
+ mac_h <<= 8;
+ mac_h += dat[i];
+ }
+ eeprom_valid = 1;
+ }
+ }
+ }
+ }
+// if that is invalid we will read that from romstrap
+ if(!eeprom_valid) {
+ unsigned long mac_pos;
+ mac_pos = 0xffffffd0; // refer to romstrap.inc and romstrap.lds
+ mac_l = readl(mac_pos) + nic_index; // overflow?
+ mac_h = readl(mac_pos + 4);
+
+ }
+#if 1
+// set that into NIC MMIO
+#define NvRegMacAddrA 0xA8
+#define NvRegMacAddrB 0xAC
+ writel(mac_l, base + NvRegMacAddrA);
+ writel(mac_h, base + NvRegMacAddrB);
+#else
+// set that into NIC
+ pci_write_config32(dev, 0xa8, mac_l);
+ pci_write_config32(dev, 0xac, mac_h);
+#endif
+
+ nic_index++;
+
+#if CONFIG_PCI_ROM_RUN == 1
+ pci_dev_init(dev);// it will init option rom
+#endif
+
+}
+
+static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ pci_write_config32(dev, 0x40,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = lpci_set_subsystem,
+};
+
+static struct device_operations nic_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = nic_init,
+ .scan_bus = 0,
+// .enable = mcp55_enable,
+ .ops_pci = &lops_pci,
+};
+static struct pci_driver nic_driver __pci_driver = {
+ .ops = &nic_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_NIC,
+};
+static struct pci_driver nic_bridge_driver __pci_driver = {
+ .ops = &nic_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_NIC_BRIDGE,
+};
Index: mcp55/id.inc
===================================================================
--- mcp55/id.inc (revision 0)
+++ mcp55/id.inc (revision 0)
@@ -0,0 +1,16 @@
+
+ .section ".id", "a", @progbits
+
+ .globl __id_start
+__id_start:
+vendor:
+ .asciz MAINBOARD_VENDOR
+part:
+ .asciz MAINBOARD_PART_NUMBER
+.long __id_end + 0x80 - vendor /* Reverse offset to the vendor id */
+.long __id_end + 0x80 - part /* Reverse offset to the part number */
+.long PAYLOAD_SIZE + ROM_IMAGE_SIZE /* Size of this romimage */
+ .globl __id_end
+
+__id_end:
+.previous
Index: mcp55/mcp55_ht.c
===================================================================
--- mcp55/mcp55_ht.c (revision 0)
+++ mcp55/mcp55_ht.c (revision 0)
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ * Copyright 2006,2007 AMD inc.
+ * by yinghai.lu@amd.com
+ */
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "mcp55.h"
+
+static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ pci_write_config32(dev, 0x40,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+static struct pci_operations lops_pci = {
+ .set_subsystem = lpci_set_subsystem,
+};
+
+static struct device_operations ht_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = 0,
+ .scan_bus = 0,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver ht_driver __pci_driver = {
+ .ops = &ht_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_HT,
+};
+
Index: mcp55/mcp55_aza.c
===================================================================
--- mcp55/mcp55_aza.c (revision 0)
+++ mcp55/mcp55_aza.c (revision 0)
@@ -0,0 +1,250 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ * Copyright 2006,2007 AMD inc.
+ * by yinghai.lu@amd.com
+ */
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <arch/io.h>
+#include "mcp55.h"
+
+static int set_bits(uint8_t *port, uint32_t mask, uint32_t val)
+{
+ uint32_t dword;
+ int count;
+
+ val &= mask;
+ dword = readl(port);
+ dword &= ~mask;
+ dword |= val;
+ writel(dword, port);
+
+ count = 50;
+ do {
+ dword = readl(port);
+ dword &= mask;
+ udelay(100);
+ } while ((dword != val) && --count);
+
+ if(!count) return -1;
+
+ udelay(540);
+ return 0;
+
+}
+
+static int codec_detect(uint8_t *base)
+{
+ uint32_t dword;
+
+ /* 1 */
+ set_bits(base + 0x08, 1, 1);
+
+ /* 2 */
+ dword = readl(base + 0x0e);
+ dword |= 7;
+ writel(dword, base + 0x0e);
+
+ /* 3 */
+ set_bits(base + 0x08, 1, 0);
+
+ /* 4 */
+ set_bits(base + 0x08, 1, 1);
+
+ /* 5 */
+ dword = readl(base + 0xe);
+ dword &= 7;
+
+ /* 6 */
+ if(!dword) {
+ set_bits(base + 0x08, 1, 0);
+ printk_debug("No codec!\n");
+ return 0;
+ }
+ return dword;
+
+}
+
+static uint32_t verb_data[] = {
+#if 0
+ 0x00172001,
+ 0x001721e6,
+ 0x00172200,
+ 0x00172300,
+#endif
+
+ 0x01471c10,
+ 0x01471d44,
+ 0x01471e01,
+ 0x01471f01,
+//1
+ 0x01571c12,
+ 0x01571d14,
+ 0x01571e01,
+ 0x01571f01,
+//2
+ 0x01671c11,
+ 0x01671d60,
+ 0x01671e01,
+ 0x01671f01,
+//3
+ 0x01771c14,
+ 0x01771d20,
+ 0x01771e01,
+ 0x01771f01,
+//4
+ 0x01871c30,
+ 0x01871d9c,
+ 0x01871ea1,
+ 0x01871f01,
+//5
+ 0x01971c40,
+ 0x01971d9c,
+ 0x01971ea1,
+ 0x01971f02,
+//6
+ 0x01a71c31,
+ 0x01a71d34,
+ 0x01a71e81,
+ 0x01a71f01,
+//7
+ 0x01b71c1f,
+ 0x01b71d44,
+ 0x01b71e21,
+ 0x01b71f02,
+//8
+ 0x01c71cf0,
+ 0x01c71d11,
+ 0x01c71e11,
+ 0x01c71f41,
+//9
+ 0x01d71c3e,
+ 0x01d71d01,
+ 0x01d71e83,
+ 0x01d71f99,
+//10
+ 0x01e71c20,
+ 0x01e71d41,
+ 0x01e71e45,
+ 0x01e71f01,
+//11
+ 0x01f71c50,
+ 0x01f71d91,
+ 0x01f71ec5,
+ 0x01f71f01,
+};
+
+static unsigned find_verb(uint32_t viddid, uint32_t **verb)
+{
+ if(viddid != 0x10ec0880) return 0;
+ *verb = (uint32_t *)verb_data;
+ return sizeof(verb_data)/sizeof(uint32_t);
+}
+
+
+static void codec_init(uint8_t *base, int addr)
+{
+ uint32_t dword;
+ uint32_t *verb;
+ unsigned verb_size;
+ int i;
+
+ /* 1 */
+ do {
+ dword = readl(base + 0x68);
+ } while (dword & 1);
+
+ dword = (addr<<28) | 0x000f0000;
+ writel(dword, base + 0x60);
+
+ do {
+ dword = readl(base + 0x68);
+ } while ((dword & 3)!=2);
+
+ dword = readl(base + 0x64);
+
+ /* 2 */
+ printk_debug("codec viddid: %08x\n", dword);
+ verb_size = find_verb(dword, &verb);
+
+ if(!verb_size) {
+ printk_debug("No verb!\n");
+ return;
+ }
+
+ printk_debug("verb_size: %d\n", verb_size);
+ /* 3 */
+ for(i=0; i<verb_size; i++) {
+ do {
+ dword = readl(base + 0x68);
+ } while (dword & 1);
+
+ writel(verb[i], base + 0x60);
+
+ do {
+ dword = readl(base + 0x68);
+ } while ((dword & 3) != 2);
+ }
+ printk_debug("verb loaded!\n");
+}
+
+static void codecs_init(uint8_t *base, uint32_t codec_mask)
+{
+ int i;
+ for(i=2; i>=0; i--) {
+ if( codec_mask & (1<<i) )
+ codec_init(base, i);
+ }
+}
+
+static void aza_init(struct device *dev)
+{
+ uint8_t *base;
+ struct resource *res;
+ uint32_t codec_mask;
+
+ res = find_resource(dev, 0x10);
+ if(!res)
+ return;
+
+ base =(uint8_t *) res->base;
+ printk_debug("base = %08x\n", base);
+
+ codec_mask = codec_detect(base);
+
+ if(codec_mask) {
+ printk_debug("codec_mask = %02x\n", codec_mask);
+ codecs_init(base, codec_mask);
+ }
+}
+
+static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ pci_write_config32(dev, 0x40,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = lpci_set_subsystem,
+};
+
+static struct device_operations aza_audio_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+// .enable = mcp55_enable,
+ .init = aza_init,
+ .scan_bus = 0,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver azaaudio_driver __pci_driver = {
+ .ops = &aza_audio_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_AZA,
+};
+
Index: mcp55/mcp55_pci.c
===================================================================
--- mcp55/mcp55_pci.c (revision 0)
+++ mcp55/mcp55_pci.c (revision 0)
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ * Copyright 2006,2007 AMD inc.
+ * by yinghai.lu@amd.com
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "mcp55.h"
+
+static void pci_init(struct device *dev)
+{
+
+ uint32_t dword;
+ uint16_t word;
+#if CONFIG_PCI_64BIT_PREF_MEM == 1
+ device_t pci_domain_dev;
+ struct resource *mem1, *mem2;
+#endif
+
+ /* System error enable */
+ dword = pci_read_config32(dev, 0x04);
+ dword |= (1<<8); /* System error enable */
+ dword |= (1<<30); /* Clear possible errors */
+ pci_write_config32(dev, 0x04, dword);
+
+#if 1
+ //only need (a01,xx]
+ word = pci_read_config16(dev, 0x48);
+ word |= (1<<0); /* MRL2MRM */
+ word |= (1<<2); /* MR2MRM */
+ pci_write_config16(dev, 0x48, word);
+#endif
+
+#if 1
+ dword = pci_read_config32(dev, 0x4c);
+ dword |= 0x00440000; /*TABORT_SER_ENABLE Park Last Enable.*/
+ pci_write_config32(dev, 0x4c, dword);
+#endif
+
+#if CONFIG_PCI_64BIT_PREF_MEM == 1
+ pci_domain_dev = dev->bus->dev;
+ while(pci_domain_dev) {
+ if(pci_domain_dev->path.type == DEVICE_PATH_PCI_DOMAIN) break;
+ pci_domain_dev = pci_domain_dev->bus->dev;
+ }
+
+ if(!pci_domain_dev) return; // impossiable
+ mem1 = find_resource(pci_domain_dev, 1); // prefmem, it could be 64bit
+ mem2 = find_resource(pci_domain_dev, 2); // mem
+ if(mem1->base > mem2->base) {
+ dword = mem2->base & (0xffff0000UL);
+ printk_debug("PCI DOMAIN mem2 base = 0x%010Lx\n", mem2->base);
+ } else {
+ dword = mem1->base & (0xffff0000UL);
+ printk_debug("PCI DOMAIN mem1 (prefmem) base = 0x%010Lx\n", mem1->base);
+ }
+#else
+ dword = dev_root.resource[1].base & (0xffff0000UL);
+ printk_debug("dev_root mem base = 0x%010Lx\n", dev_root.resource[1].base);
+#endif
+ printk_debug("[0x50] <-- 0x%08x\n", dword);
+ pci_write_config32(dev, 0x50, dword); //TOM
+
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = 0,
+};
+
+static struct device_operations pci_ops = {
+ .read_resources = pci_bus_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_bus_enable_resources,
+ .init = pci_init,
+ .scan_bus = pci_scan_bridge,
+// .enable = mcp55_enable,
+ .reset_bus = pci_bus_reset,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver pci_driver __pci_driver = {
+ .ops = &pci_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_PCI,
+};
+
Index: mcp55/mcp55_usb2.c
===================================================================
--- mcp55/mcp55_usb2.c (revision 0)
+++ mcp55/mcp55_usb2.c (revision 0)
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ * Copyright 2006,2007 AMD inc.
+ * by yinghai.lu@amd.com
+ */
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "mcp55.h"
+#include <usbdebug_direct.h>
+
+extern struct ehci_debug_info dbg_info;
+
+static void usb2_init(struct device *dev)
+{
+ uint32_t dword;
+ dword = pci_read_config32(dev, 0xf8);
+ dword |= 40;
+ pci_write_config32(dev, 0xf8, dword);
+}
+
+static void usb2_set_resources(struct device *dev)
+{
+#if CONFIG_USBDEBUG_DIRECT
+ struct resource *res;
+ unsigned base;
+ unsigned old_debug;
+
+ old_debug = get_ehci_debug();
+ set_ehci_debug(0);
+#endif
+ pci_dev_set_resources(dev);
+
+#if CONFIG_USBDEBUG_DIRECT
+ res = find_resource(dev, 0x10);
+ set_ehci_debug(old_debug);
+ if (!res) return;
+ base = res->base;
+ set_ehci_base(base);
+ report_resource_stored(dev, res, "");
+#endif
+
+}
+
+static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ pci_write_config32(dev, 0x40,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+static struct pci_operations lops_pci = {
+ .set_subsystem = lpci_set_subsystem,
+};
+
+static struct device_operations usb2_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = usb2_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = usb2_init,
+// .enable = mcp55_enable,
+ .scan_bus = 0,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver usb2_driver __pci_driver = {
+ .ops = &usb2_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_USB2,
+};
Index: mcp55/mcp55_lpc.c
===================================================================
--- mcp55/mcp55_lpc.c (revision 0)
+++ mcp55/mcp55_lpc.c (revision 0)
@@ -0,0 +1,385 @@
+/*
+ * (C) 2003 Linux Networx, SuSE Linux AG
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ * 2006.1 yhlu add dest apicid for IRQ0
+ * Copyright 2006,2007 AMD inc.
+ * by yinghai.lu@amd.com
+ */
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pnp.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <pc80/mc146818rtc.h>
+#include <pc80/isa-dma.h>
+#include <bitops.h>
+#include <arch/io.h>
+#include <cpu/x86/lapic.h>
+#include "mcp55.h"
+
+#define NMI_OFF 0
+
+struct ioapicreg {
+ unsigned int reg;
+ unsigned int value_low, value_high;
+};
+
+static struct ioapicreg ioapicregvalues[] = {
+#define ALL (0xff << 24)
+#define NONE (0)
+#define DISABLED (1 << 16)
+#define ENABLED (0 << 16)
+#define TRIGGER_EDGE (0 << 15)
+#define TRIGGER_LEVEL (1 << 15)
+#define POLARITY_HIGH (0 << 13)
+#define POLARITY_LOW (1 << 13)
+#define PHYSICAL_DEST (0 << 11)
+#define LOGICAL_DEST (1 << 11)
+#define ExtINT (7 << 8)
+#define NMI (4 << 8)
+#define SMI (2 << 8)
+#define INT (1 << 8)
+ /* IO-APIC virtual wire mode configuration */
+ /* mask, trigger, polarity, destination, delivery, vector */
+ { 0, ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT, NONE},
+ { 1, DISABLED, NONE},
+ { 2, DISABLED, NONE},
+ { 3, DISABLED, NONE},
+ { 4, DISABLED, NONE},
+ { 5, DISABLED, NONE},
+ { 6, DISABLED, NONE},
+ { 7, DISABLED, NONE},
+ { 8, DISABLED, NONE},
+ { 9, DISABLED, NONE},
+ { 10, DISABLED, NONE},
+ { 11, DISABLED, NONE},
+ { 12, DISABLED, NONE},
+ { 13, DISABLED, NONE},
+ { 14, DISABLED, NONE},
+ { 15, DISABLED, NONE},
+ { 16, DISABLED, NONE},
+ { 17, DISABLED, NONE},
+ { 18, DISABLED, NONE},
+ { 19, DISABLED, NONE},
+ { 20, DISABLED, NONE},
+ { 21, DISABLED, NONE},
+ { 22, DISABLED, NONE},
+ { 23, DISABLED, NONE},
+ /* Be careful and don't write past the end... */
+};
+
+static void setup_ioapic(unsigned long ioapic_base)
+{
+ int i;
+ unsigned long value_low, value_high;
+// unsigned long ioapic_base = 0xfec00000;
+ volatile unsigned long *l;
+ struct ioapicreg *a = ioapicregvalues;
+
+ ioapicregvalues[0].value_high = lapicid()<<(56-32);
+
+ l = (unsigned long *) ioapic_base;
+
+ for (i = 0; i < sizeof(ioapicregvalues) / sizeof(ioapicregvalues[0]);
+ i++, a++) {
+ l[0] = (a->reg * 2) + 0x10;
+ l[4] = a->value_low;
+ value_low = l[4];
+ l[0] = (a->reg *2) + 0x11;
+ l[4] = a->value_high;
+ value_high = l[4];
+ if ((i==0) && (value_low == 0xffffffff)) {
+ printk_warning("IO APIC not responding.\n");
+ return;
+ }
+ printk_spew("for IRQ, reg 0x%08x value 0x%08x 0x%08x\n",
+ a->reg, a->value_low, a->value_high);
+ }
+}
+
+// 0x7a or e3
+#define PREVIOUS_POWER_STATE 0x7A
+
+#define MAINBOARD_POWER_OFF 0
+#define MAINBOARD_POWER_ON 1
+#define SLOW_CPU_OFF 0
+#define SLOW_CPU__ON 1
+
+#ifndef MAINBOARD_POWER_ON_AFTER_POWER_FAIL
+#define MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
+#endif
+
+static void lpc_common_init(device_t dev)
+{
+ uint8_t byte;
+ uint32_t dword;
+
+ /* IO APIC initialization */
+ byte = pci_read_config8(dev, 0x74);
+ byte |= (1<<0); // enable APIC
+ pci_write_config8(dev, 0x74, byte);
+ dword = pci_read_config32(dev, PCI_BASE_ADDRESS_1); // 0x14
+
+ setup_ioapic(dword);
+
+}
+
+static void lpc_slave_init(device_t dev)
+{
+ lpc_common_init(dev);
+}
+
+#if 0
+static void enable_hpet(struct device *dev)
+{
+ unsigned long hpet_address;
+
+ pci_write_config32(dev,0x44, 0xfed00001);
+ hpet_address=pci_read_config32(dev,0x44)& 0xfffffffe;
+ printk_debug("enabling HPET @0x%x\n", hpet_address);
+}
+#endif
+
+static void lpc_init(device_t dev)
+{
+ uint8_t byte;
+ uint8_t byte_old;
+ int on;
+ int nmi_option;
+
+ lpc_common_init(dev);
+
+#if 0
+ /* posted memory write enable */
+ byte = pci_read_config8(dev, 0x46);
+ pci_write_config8(dev, 0x46, byte | (1<<0));
+
+#endif
+ /* power after power fail */
+
+#if 1
+ on = MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
+ get_option(&on, "power_on_after_fail");
+ byte = pci_read_config8(dev, PREVIOUS_POWER_STATE);
+ byte &= ~0x40;
+ if (!on) {
+ byte |= 0x40;
+ }
+ pci_write_config8(dev, PREVIOUS_POWER_STATE, byte);
+ printk_info("set power %s after power fail\n", on?"on":"off");
+#endif
+ /* Throttle the CPU speed down for testing */
+ on = SLOW_CPU_OFF;
+ get_option(&on, "slow_cpu");
+ if(on) {
+ uint16_t pm10_bar;
+ uint32_t dword;
+ pm10_bar = (pci_read_config16(dev, 0x60)&0xff00);
+ outl(((on<<1)+0x10) ,(pm10_bar + 0x10));
+ dword = inl(pm10_bar + 0x10);
+ on = 8-on;
+ printk_debug("Throttling CPU %2d.%1.1d percent.\n",
+ (on*12)+(on>>1),(on&1)*5);
+ }
+
+#if 0
+// default is enabled
+ /* Enable Port 92 fast reset */
+ byte = pci_read_config8(dev, 0xe8);
+ byte |= ~(1 << 3);
+ pci_write_config8(dev, 0xe8, byte);
+#endif
+
+ /* Enable Error reporting */
+ /* Set up sync flood detected */
+ byte = pci_read_config8(dev, 0x47);
+ byte |= (1 << 1);
+ pci_write_config8(dev, 0x47, byte);
+
+ /* Set up NMI on errors */
+ byte = inb(0x70); // RTC70
+ byte_old = byte;
+ nmi_option = NMI_OFF;
+ get_option(&nmi_option, "nmi");
+ if (nmi_option) {
+ byte &= ~(1 << 7); /* set NMI */
+ } else {
+ byte |= ( 1 << 7); // Can not mask NMI from PCI-E and NMI_NOW
+ }
+ if( byte != byte_old) {
+ outb(0x70, byte);
+ }
+
+ /* Initialize the real time clock */
+ rtc_init(0);
+
+ /* Initialize isa dma */
+ isa_dma_init();
+
+ /* Initialize the High Precision Event Timers */
+// enable_hpet(dev);
+
+}
+
+static void mcp55_lpc_read_resources(device_t dev)
+{
+ struct resource *res;
+ unsigned long index;
+
+ /* Get the normal pci resources of this device */
+ pci_dev_read_resources(dev); // We got one for APIC, or one more for TRAP
+
+ /* Add an extra subtractive resource for both memory and I/O */
+ res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
+ res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
+
+ res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
+ res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
+
+}
+
+/**
+ * @brief Enable resources for children devices
+ *
+ * @param dev the device whos children's resources are to be enabled
+ *
+ * This function is call by the global enable_resources() indirectly via the
+ * device_operation::enable_resources() method of devices.
+ *
+ * Indirect mutual recursion:
+ * enable_childrens_resources() -> enable_resources()
+ * enable_resources() -> device_operation::enable_resources()
+ * device_operation::enable_resources() -> enable_children_resources()
+ */
+static void mcp55_lpc_enable_childrens_resources(device_t dev)
+{
+ unsigned link;
+ uint32_t reg, reg_var[4];
+ int i;
+ int var_num = 0;
+
+ reg = pci_read_config32(dev, 0xa0);
+
+ for (link = 0; link < dev->links; link++) {
+ device_t child;
+ for (child = dev->link[link].children; child; child = child->sibling) {
+ enable_resources(child);
+ if(child->have_resources && (child->path.type == DEVICE_PATH_PNP)) {
+ for(i=0;i<child->resources;i++) {
+ struct resource *res;
+ unsigned long base, end; // don't need long long
+ res = &child->resource[i];
+ if(!(res->flags & IORESOURCE_IO)) continue;
+ base = res->base;
+ end = resource_end(res);
+ printk_debug("mcp55 lpc decode:%s, base=0x%08x, end=0x%08x\n",dev_path(child),base, end);
+ switch(base) {
+ case 0x3f8: // COM1
+ reg |= (1<<0); break;
+ case 0x2f8: // COM2
+ reg |= (1<<1); break;
+ case 0x378: // Parallal 1
+ reg |= (1<<24); break;
+ case 0x3f0: // FD0
+ reg |= (1<<20); break;
+ case 0x220: // Aduio 0
+ reg |= (1<<8); break;
+ case 0x300: // Midi 0
+ reg |= (1<<12); break;
+ }
+ if( (base == 0x290) || (base >= 0x400)) {
+ if(var_num>=4) continue; // only 4 var ; compact them ?
+ reg |= (1<<(28+var_num));
+ reg_var[var_num++] = (base & 0xffff)|((end & 0xffff)<<16);
+ }
+ }
+ }
+ }
+ }
+ pci_write_config32(dev, 0xa0, reg);
+ for(i=0;i<var_num;i++) {
+ pci_write_config32(dev, 0xa8 + i*4, reg_var[i]);
+ }
+
+
+}
+
+static void mcp55_lpc_enable_resources(device_t dev)
+{
+ pci_dev_enable_resources(dev);
+ mcp55_lpc_enable_childrens_resources(dev);
+}
+
+static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ pci_write_config32(dev, 0x40,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = lpci_set_subsystem,
+};
+
+static struct device_operations lpc_ops = {
+ .read_resources = mcp55_lpc_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = mcp55_lpc_enable_resources,
+ .init = lpc_init,
+ .scan_bus = scan_static_bus,
+// .enable = mcp55_enable,
+ .ops_pci = &lops_pci,
+};
+static struct pci_driver lpc_driver __pci_driver = {
+ .ops = &lpc_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_LPC,
+};
+
+static struct pci_driver lpc_driver_pro __pci_driver = {
+ .ops = &lpc_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_PRO,
+};
+
+static struct pci_driver lpc_driver_lpc2 __pci_driver = {
+ .ops = &lpc_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_LPC_2,
+};
+static struct pci_driver lpc_driver_lpc3 __pci_driver = {
+ .ops = &lpc_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_LPC_3,
+};
+static struct pci_driver lpc_driver_lpc4 __pci_driver = {
+ .ops = &lpc_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_LPC_4,
+};
+static struct pci_driver lpc_driver_lpc5 __pci_driver = {
+ .ops = &lpc_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_LPC_5,
+};
+static struct pci_driver lpc_driver_lpc6 __pci_driver = {
+ .ops = &lpc_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_LPC_6,
+};
+
+static struct device_operations lpc_slave_ops = {
+ .read_resources = mcp55_lpc_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = lpc_slave_init,
+// .enable = mcp55_enable,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver lpc_driver_slave __pci_driver = {
+ .ops = &lpc_slave_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_SLAVE,
+};
Index: mcp55/chip.h
===================================================================
--- mcp55/chip.h (revision 0)
+++ mcp55/chip.h (revision 0)
@@ -0,0 +1,16 @@
+#ifndef MCP55_CHIP_H
+#define MCP55_CHIP_H
+
+struct southbridge_nvidia_mcp55_config
+{
+ unsigned int ide0_enable : 1;
+ unsigned int ide1_enable : 1;
+ unsigned int sata0_enable : 1;
+ unsigned int sata1_enable : 1;
+ unsigned int mac_eeprom_smbus;
+ unsigned int mac_eeprom_addr;
+};
+struct chip_operations;
+extern struct chip_operations southbridge_nvidia_mcp55_ops;
+
+#endif /* MCP55_CHIP_H */
Index: mcp55/mcp55.c
===================================================================
--- mcp55/mcp55.c (revision 0)
+++ mcp55/mcp55.c (revision 0)
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ * Copyright 2006,2007 AMD inc.
+ * by yinghai.lu@amd.com
+ */
+
+#include <console/console.h>
+
+#include <arch/io.h>
+
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "mcp55.h"
+
+static uint32_t final_reg;
+
+static device_t find_lpc_dev( device_t dev, unsigned devfn)
+{
+
+ device_t lpc_dev;
+
+ lpc_dev = dev_find_slot(dev->bus->secondary, devfn);
+
+ if ( !lpc_dev ) return lpc_dev;
+
+ if ((lpc_dev->vendor != PCI_VENDOR_ID_NVIDIA) || (
+ (lpc_dev->device < PCI_DEVICE_ID_NVIDIA_MCP55_LPC) ||
+ (lpc_dev->device > PCI_DEVICE_ID_NVIDIA_MCP55_PRO)
+ ) ) {
+ uint32_t id;
+ id = pci_read_config32(lpc_dev, PCI_VENDOR_ID);
+ if ( (id < (PCI_VENDOR_ID_NVIDIA | (PCI_DEVICE_ID_NVIDIA_MCP55_LPC << 16))) ||
+ (id > (PCI_VENDOR_ID_NVIDIA | (PCI_DEVICE_ID_NVIDIA_MCP55_PRO << 16)))
+ ) {
+ lpc_dev = 0;
+ }
+ }
+
+ return lpc_dev;
+}
+
+void mcp55_enable(device_t dev)
+{
+ device_t lpc_dev = 0;
+ device_t sm_dev = 0;
+ unsigned index = 0;
+ unsigned index2 = 0;
+ uint32_t reg_old, reg;
+ uint8_t byte;
+ unsigned deviceid;
+ unsigned vendorid;
+
+ struct southbridge_nvidia_mcp55_config *conf;
+ conf = dev->chip_info;
+ int i;
+
+ unsigned devfn;
+
+ if(dev->device==0x0000) {
+ vendorid = pci_read_config32(dev, PCI_VENDOR_ID);
+ deviceid = (vendorid>>16) & 0xffff;
+// vendorid &= 0xffff;
+ } else {
+// vendorid = dev->vendor;
+ deviceid = dev->device;
+ }
+
+ devfn = (dev->path.u.pci.devfn) & ~7;
+ switch(deviceid) {
+ case PCI_DEVICE_ID_NVIDIA_MCP55_HT:
+ return;
+
+ case PCI_DEVICE_ID_NVIDIA_MCP55_SM2://?
+ index = 16;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_MCP55_USB:
+ devfn -= (1<<3);
+ index = 8;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_MCP55_USB2:
+ devfn -= (1<<3);
+ index = 20;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_MCP55_NIC: //two
+ case PCI_DEVICE_ID_NVIDIA_MCP55_NIC_BRIDGE://two
+ devfn -= (7<<3);
+ index = 10;
+ for(i=0;i<2;i++) {
+ lpc_dev = find_lpc_dev(dev, devfn - (i<<3));
+ if(!lpc_dev) continue;
+ index -= i;
+ devfn -= (i<<3);
+ break;
+ }
+ break;
+ case PCI_DEVICE_ID_NVIDIA_MCP55_AZA:
+ devfn -= (5<<3);
+ index = 11;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_MCP55_IDE:
+ devfn -= (3<<3);
+ index = 14;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_MCP55_SATA0: //three
+ case PCI_DEVICE_ID_NVIDIA_MCP55_SATA1: //three
+ devfn -= (4<<3);
+ index = 22;
+ i = (dev->path.u.pci.devfn) & 7;
+ if(i>0) {
+ index -= (i+3);
+ }
+ break;
+ case PCI_DEVICE_ID_NVIDIA_MCP55_PCI:
+ devfn -= (5<<3);
+ index = 15;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_MCP55_PCIE_A:
+ devfn -= (0x9<<3); // to LPC
+ index2 = 9;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_MCP55_PCIE_B_C: //two
+ devfn -= (0xa<<3); // to LPC
+ index2 = 8;
+ for(i=0;i<2;i++) {
+ lpc_dev = find_lpc_dev(dev, devfn - (i<<3));
+ if(!lpc_dev) continue;
+ index2 -= i;
+ devfn -= (i<<3);
+ break;
+ }
+ break;
+ case PCI_DEVICE_ID_NVIDIA_MCP55_PCIE_D:
+ devfn -= (0xc<<3); // to LPC
+ index2 = 6;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_MCP55_PCIE_E:
+ devfn -= (0xd<<3); // to LPC
+ index2 = 5;
+ break;
+ case PCI_DEVICE_ID_NVIDIA_MCP55_PCIE_F:
+ devfn -= (0xe<<3); // to LPC
+ index2 = 4;
+ break;
+ default:
+ index = 0;
+ }
+
+ if(!lpc_dev)
+ lpc_dev = find_lpc_dev(dev, devfn);
+
+ if ( !lpc_dev ) return;
+
+ if(index2!=0) {
+ sm_dev = dev_find_slot(dev->bus->secondary, devfn + 1);
+ if(!sm_dev) return;
+
+ if ( sm_dev ) {
+ reg_old = reg = pci_read_config32(sm_dev, 0xe4);
+
+ if (!dev->enabled) { //disable it
+ reg |= (1<<index2);
+ }
+
+ if (reg != reg_old) {
+ pci_write_config32(sm_dev, 0xe4, reg);
+ }
+ }
+
+ index2 = 0;
+ return;
+ }
+
+
+ if ( index == 0) { // for LPC
+
+ // expose ioapic base
+ byte = pci_read_config8(lpc_dev, 0x74);
+ byte |= ((1<<1)); // expose the BAR
+ pci_write_config8(dev, 0x74, byte);
+
+ // expose trap base
+ byte = pci_read_config8(lpc_dev, 0xdd);
+ byte |= ((1<<0)|(1<<3)); // expose the BAR and enable write
+ pci_write_config8(dev, 0xdd, byte);
+
+ return;
+
+ }
+
+ if( index == 16) {
+ sm_dev = dev_find_slot(dev->bus->secondary, devfn + 1);
+ if(!sm_dev) return;
+
+ final_reg = pci_read_config32(sm_dev, 0xe8);
+ final_reg &= ~((1<<16)|(1<<8)|(1<<20)|(1<<14)|(1<<22)|(1<<18)|(1<<17)|(1<<15)|(1<<11)|(1<<10)|(1<<9));
+ pci_write_config32(sm_dev, 0xe8, final_reg); //enable all at first
+#if 0
+ reg_old = reg = pci_read_config32(sm_dev, 0xe4);
+// reg |= (1<<0);
+ reg &= ~(0x3f<<4);
+ if (reg != reg_old) {
+ printk_debug("mcp55.c pcie enabled\n");
+ pci_write_config32(sm_dev, 0xe4, reg);
+ }
+#endif
+ }
+
+ if (!dev->enabled) {
+ final_reg |= (1 << index);// disable it
+ //The reason for using final_reg, if diable func 1, the func 2 will be func 1 so We need disable them one time.
+ }
+
+ if(index == 9 ) { //NIC1 is the final, We need update final reg to 0xe8
+ sm_dev = dev_find_slot(dev->bus->secondary, devfn + 1);
+ if(!sm_dev) return;
+ reg_old = pci_read_config32(sm_dev, 0xe8);
+ if (final_reg != reg_old) {
+ pci_write_config32(sm_dev, 0xe8, final_reg);
+ }
+
+ }
+
+
+}
+
+struct chip_operations southbridge_nvidia_mcp55_ops = {
+ CHIP_NAME("Nvidia mcp55")
+ .enable_dev = mcp55_enable,
+};
Index: mcp55/mcp55_pcie.c
===================================================================
--- mcp55/mcp55_pcie.c (revision 0)
+++ mcp55/mcp55_pcie.c (revision 0)
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ * Copyright 2006,2007 AMD inc.
+ * by yinghai.lu@amd.com
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "mcp55.h"
+
+static void pcie_init(struct device *dev)
+{
+
+ /* Enable pci error detecting */
+ uint32_t dword;
+
+ /* System error enable */
+ dword = pci_read_config32(dev, 0x04);
+ dword |= (1<<8); /* System error enable */
+ dword |= (1<<30); /* Clear possible errors */
+ pci_write_config32(dev, 0x04, dword);
+
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = 0,
+};
+
+static struct device_operations pcie_ops = {
+ .read_resources = pci_bus_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_bus_enable_resources,
+ .init = pcie_init,
+ .scan_bus = pci_scan_bridge,
+// .enable = mcp55_enable,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver pciebc_driver __pci_driver = {
+ .ops = &pcie_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_PCIE_B_C,
+};
+static struct pci_driver pciee_driver __pci_driver = {
+ .ops = &pcie_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_PCIE_E,
+};
+static struct pci_driver pciea_driver __pci_driver = {
+ .ops = &pcie_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_PCIE_A,
+};
+static struct pci_driver pcief_driver __pci_driver = {
+ .ops = &pcie_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_PCIE_F,
+};
+static struct pci_driver pcied_driver __pci_driver = {
+ .ops = &pcie_ops,
+ .vendor = PCI_VENDOR_ID_NVIDIA,
+ .device = PCI_DEVICE_ID_NVIDIA_MCP55_PCIE_D,
+};
+
Index: mcp55/mcp55_early_setup_car.c
===================================================================
--- mcp55/mcp55_early_setup_car.c (revision 0)
+++ mcp55/mcp55_early_setup_car.c (revision 0)
@@ -0,0 +1,411 @@
+/*
+ * Copyright 2006 AMD
+ * by yinghai.lu@amd.com
+ */
+
+static int set_ht_link_mcp55(uint8_t ht_c_num)
+{
+ unsigned vendorid = 0x10de;
+ unsigned val = 0x01610109;
+ /* Nvidia mcp55 hardcode, hw can not set it automatically */
+ return set_ht_link_buffer_counts_chain(ht_c_num, vendorid, val);
+}
+
+static void setup_ss_table(unsigned index, unsigned where, unsigned control, const unsigned int *register_values, int max)
+{
+ int i;
+
+ unsigned val;
+
+ val = inl(control);
+ val &= 0xfffffffe;
+ outl(val, control);
+
+ outl(0, index); //index
+ for(i = 0; i < max; i++) {
+ unsigned long reg;
+ reg = register_values[i];
+ outl(reg, where);
+ }
+
+ val = inl(control);
+ val |= 1;
+ outl(val, control);
+
+}
+
+/* SIZE 0x100 */
+#define ANACTRL_IO_BASE 0x2800
+#define ANACTRL_REG_POS 0x68
+
+/* SIZE 0x100 */
+#define SYSCTRL_IO_BASE 0x2400
+#define SYSCTRL_REG_POS 0x64
+
+/* SIZE 0x100 */
+#define ACPICTRL_IO_BASE 0x2000
+#define ACPICTRL_REG_POS 0x60
+
+/*
+ 16 1 1 1 1 8 :0
+ 16 0 4 0 0 8 :1
+ 16 0 4 2 2 4 :2
+ 4 4 4 4 4 8 :3
+ 8 8 4 0 0 8 :4
+ 8 0 4 4 4 8 :5
+*/
+
+#ifndef MCP55_PCI_E_X_0
+ #define MCP55_PCI_E_X_0 4
+#endif
+#ifndef MCP55_PCI_E_X_1
+ #define MCP55_PCI_E_X_1 4
+#endif
+#ifndef MCP55_PCI_E_X_2
+ #define MCP55_PCI_E_X_2 4
+#endif
+#ifndef MCP55_PCI_E_X_3
+ #define MCP55_PCI_E_X_3 4
+#endif
+
+#ifndef MCP55_USE_NIC
+ #define MCP55_USE_NIC 0
+#endif
+
+#ifndef MCP55_USE_AZA
+ #define MCP55_USE_AZA 0
+#endif
+
+#define MCP55_CHIP_REV 3
+
+static void mcp55_early_set_port(unsigned mcp55_num, unsigned *busn, unsigned *devn, unsigned *io_base)
+{
+
+ static const unsigned int ctrl_devport_conf[] = {
+ PCI_ADDR(0, 1, 1, ANACTRL_REG_POS), ~(0x0000ff00), ANACTRL_IO_BASE,
+ PCI_ADDR(0, 1, 1, SYSCTRL_REG_POS), ~(0x0000ff00), SYSCTRL_IO_BASE,
+ PCI_ADDR(0, 1, 1, ACPICTRL_REG_POS), ~(0x0000ff00), ACPICTRL_IO_BASE,
+ };
+
+ int j;
+ for(j = 0; j < mcp55_num; j++ ) {
+ setup_resource_map_offset(ctrl_devport_conf,
+ sizeof(ctrl_devport_conf)/sizeof(ctrl_devport_conf[0]),
+ PCI_DEV(busn[j], devn[j], 0) , io_base[j]);
+ }
+}
+
+static void mcp55_early_clear_port(unsigned mcp55_num, unsigned *busn, unsigned *devn, unsigned *io_base)
+{
+
+ static const unsigned int ctrl_devport_conf_clear[] = {
+ PCI_ADDR(0, 1, 1, ANACTRL_REG_POS), ~(0x0000ff00), 0,
+ PCI_ADDR(0, 1, 1, SYSCTRL_REG_POS), ~(0x0000ff00), 0,
+ PCI_ADDR(0, 1, 1, ACPICTRL_REG_POS), ~(0x0000ff00), 0,
+ };
+
+ int j;
+ for(j = 0; j < mcp55_num; j++ ) {
+ setup_resource_map_offset(ctrl_devport_conf_clear,
+ sizeof(ctrl_devport_conf_clear)/sizeof(ctrl_devport_conf_clear[0]),
+ PCI_DEV(busn[j], devn[j], 0) , io_base[j]);
+ }
+
+
+}
+static void delayx(uint8_t value) {
+#if 1
+ int i;
+ for(i=0;i<0x8000;i++) {
+ outb(value, 0x80);
+ }
+#endif
+}
+
+static void mcp55_early_pcie_setup(unsigned busnx, unsigned devnx, unsigned anactrl_io_base, unsigned pci_e_x)
+{
+ uint32_t tgio_ctrl;
+ uint32_t pll_ctrl;
+ uint32_t dword;
+ int i;
+ device_t dev;
+ dev = PCI_DEV(busnx, devnx+1, 1);
+ dword = pci_read_config32(dev, 0xe4);
+ dword |= 0x3f0; // disable it at first
+ pci_write_config32(dev, 0xe4, dword);
+
+ for(i=0; i<3; i++) {
+ tgio_ctrl = inl(anactrl_io_base + 0xcc);
+ tgio_ctrl &= ~(3<<9);
+ tgio_ctrl |= (i<<9);
+ outl(tgio_ctrl, anactrl_io_base + 0xcc);
+ pll_ctrl = inl(anactrl_io_base + 0x30);
+ pll_ctrl |= (1<<31);
+ outl(pll_ctrl, anactrl_io_base + 0x30);
+ do {
+ pll_ctrl = inl(anactrl_io_base + 0x30);
+ } while (!(pll_ctrl & 1));
+ }
+ tgio_ctrl = inl(anactrl_io_base + 0xcc);
+ tgio_ctrl &= ~((7<<4)|(1<<8));
+ tgio_ctrl |= (pci_e_x<<4)|(1<<8);
+ outl(tgio_ctrl, anactrl_io_base + 0xcc);
+
+// wait 100us
+ delayx(1);
+
+ dword = pci_read_config32(dev, 0xe4);
+ dword &= ~(0x3f0); // enable
+ pci_write_config32(dev, 0xe4, dword);
+
+// need to wait 100ms
+ delayx(1000);
+}
+
+static void mcp55_early_setup(unsigned mcp55_num, unsigned *busn, unsigned *devn, unsigned *io_base, unsigned *pci_e_x)
+{
+
+ static const unsigned int ctrl_conf_1[] = {
+ RES_PORT_IO_32, ACPICTRL_IO_BASE + 0x10, 0x0007ffff, 0xff78000,
+ RES_PORT_IO_32, ACPICTRL_IO_BASE + 0xa4, 0xffedffff, 0x0012000,
+ RES_PORT_IO_32, ACPICTRL_IO_BASE + 0xac, 0xfffffdff, 0x0000200,
+ RES_PORT_IO_32, ACPICTRL_IO_BASE + 0xb4, 0xfffffffd, 0x0000002,
+
+ RES_PORT_IO_32, ANACTRL_IO_BASE + 0x24, 0xc0f0f08f, 0x26020230,
+ RES_PORT_IO_32, ANACTRL_IO_BASE + 0x34, 0x00000000, 0x22222222,
+ RES_PORT_IO_32, ANACTRL_IO_BASE + 0x08, 0x7FFFFFFF, 0x00000000,
+ RES_PORT_IO_32, ANACTRL_IO_BASE + 0x2C, 0x7FFFFFFF, 0x80000000,
+ RES_PORT_IO_32, ANACTRL_IO_BASE + 0xCC, 0xFFFFF9FF, 0x00000000,
+ RES_PORT_IO_32, ANACTRL_IO_BASE + 0x30, 0x8FFFFFFF, 0x40000000,
+ RES_PORT_IO_32, ANACTRL_IO_BASE + 0xCC, 0xFFFFF9FF, 0x00000200,
+ RES_PORT_IO_32, ANACTRL_IO_BASE + 0x30, 0x8FFFFFFF, 0x40000000,
+ RES_PORT_IO_32, ANACTRL_IO_BASE + 0xCC, 0xFFFFF9FF, 0x00000400,
+ RES_PORT_IO_32, ANACTRL_IO_BASE + 0x30, 0x8FFFFFFF, 0x40000000,
+ RES_PORT_IO_32, ANACTRL_IO_BASE + 0x74, 0xFFFF0FF5, 0x0000F000,
+ RES_PORT_IO_32, ANACTRL_IO_BASE + 0x78, 0xFF00FF00, 0x00100010,
+ RES_PORT_IO_32, ANACTRL_IO_BASE + 0x7C, 0xFF0FF0FF, 0x00500500,
+ RES_PORT_IO_32, ANACTRL_IO_BASE + 0x80, 0xFFFFFFE7, 0x00000000,
+ RES_PORT_IO_32, ANACTRL_IO_BASE + 0x60, 0xFFCFFFFF, 0x00300000,
+ RES_PORT_IO_32, ANACTRL_IO_BASE + 0x90, 0xFFFF00FF, 0x0000FF00,
+ RES_PORT_IO_32, ANACTRL_IO_BASE + 0x9C, 0xFF00FFFF, 0x00070000,
+
+ RES_PCI_IO, PCI_ADDR(0, 0, 0, 0x40), 0x00000000, 0xCB8410DE,
+ RES_PCI_IO, PCI_ADDR(0, 0, 0, 0x48), 0xFFFFDCED, 0x00002002,
+ RES_PCI_IO, PCI_ADDR(0, 0, 0, 0x78), 0xFFFFFF8E, 0x00000011,
+ RES_PCI_IO, PCI_ADDR(0, 0, 0, 0x80), 0xFFFF0000, 0x00009923,
+ RES_PCI_IO, PCI_ADDR(0, 0, 0, 0x88), 0xFFFFFFFE, 0x00000000,
+ RES_PCI_IO, PCI_ADDR(0, 0, 0, 0x8C), 0xFFFF0000, 0x0000007F,
+ RES_PCI_IO, PCI_ADDR(0, 0, 0, 0xDC), 0xFFFEFFFF, 0x00010000,
+
+ RES_PCI_IO, PCI_ADDR(0, 1, 0, 0x40), 0x00000000, 0xCB8410DE,
+ RES_PCI_IO, PCI_ADDR(0, 1, 0, 0x74), 0xFFFFFF7B, 0x00000084,
+ RES_PCI_IO, PCI_ADDR(0, 1, 0, 0xF8), 0xFFFFFFCF, 0x00000010,
+
+ RES_PCI_IO, PCI_ADDR(0, 1, 1, 0xC4), 0xFFFFFFFE, 0x00000001,
+ RES_PCI_IO, PCI_ADDR(0, 1, 1, 0xF0), 0x7FFFFFFD, 0x00000002,
+ RES_PCI_IO, PCI_ADDR(0, 1, 1, 0xF8), 0xFFFFFFCF, 0x00000010,
+
+ RES_PCI_IO, PCI_ADDR(0, 8, 0, 0x40), 0x00000000, 0xCB8410DE,
+ RES_PCI_IO, PCI_ADDR(0, 8, 0, 0x68), 0xFFFFFF00, 0x000000FF,
+ RES_PCI_IO, PCI_ADDR(0, 8, 0, 0xF8), 0xFFFFFFBF, 0x00000040,//Enable bridge mode
+
+ RES_PCI_IO, PCI_ADDR(0, 9, 0, 0x40), 0x00000000, 0xCB8410DE,
+ RES_PCI_IO, PCI_ADDR(0, 9, 0, 0x68), 0xFFFFFF00, 0x000000FF,
+ RES_PCI_IO, PCI_ADDR(0, 9, 0, 0xF8), 0xFFFFFFBF, 0x00000040,//Enable bridge mode
+ };
+
+ static const unsigned int ctrl_conf_1_1[] = {
+ RES_PCI_IO, PCI_ADDR(0, 5, 0, 0x40), 0x00000000, 0xCB8410DE,
+ RES_PCI_IO, PCI_ADDR(0, 5, 0, 0x50), 0xFFFFFFFC, 0x00000003,
+ RES_PCI_IO, PCI_ADDR(0, 5, 0, 0x64), 0xFFFFFFFE, 0x00000001,
+ RES_PCI_IO, PCI_ADDR(0, 5, 0, 0x70), 0xFFF0FFFF, 0x00040000,
+ RES_PCI_IO, PCI_ADDR(0, 5, 0, 0xAC), 0xFFFFF0FF, 0x00000100,
+ RES_PCI_IO, PCI_ADDR(0, 5, 0, 0x7C), 0xFFFFFFEF, 0x00000000,
+ RES_PCI_IO, PCI_ADDR(0, 5, 0, 0xC8), 0xFF00FF00, 0x000A000A,
+ RES_PCI_IO, PCI_ADDR(0, 5, 0, 0xD0), 0xF0FFFFFF, 0x03000000,
+ RES_PCI_IO, PCI_ADDR(0, 5, 0, 0xE0), 0xF0FFFFFF, 0x03000000,
+ };
+
+
+ static const unsigned int ctrl_conf_mcp55_only[] = {
+ RES_PCI_IO, PCI_ADDR(0, 1, 1, 0x40), 0x00000000, 0xCB8410DE,
+ RES_PCI_IO, PCI_ADDR(0, 1, 1, 0xE0), 0xFFFFFEFF, 0x00000000,
+ RES_PCI_IO, PCI_ADDR(0, 1, 1, 0xE4), 0xFFFFFFFB, 0x00000000,
+ RES_PCI_IO, PCI_ADDR(0, 1, 1, 0xE8), 0xFFA9C8FF, 0x00003000,
+
+ RES_PCI_IO, PCI_ADDR(0, 4, 0, 0x40), 0x00000000, 0xCB8410DE,
+ RES_PCI_IO, PCI_ADDR(0, 4, 0, 0xF8), 0xFFFFFFCF, 0x00000010,
+
+ RES_PCI_IO, PCI_ADDR(0, 2, 0, 0x40), 0x00000000, 0xCB8410DE,
+
+ RES_PCI_IO, PCI_ADDR(0, 2, 1, 0x40), 0x00000000, 0xCB8410DE,
+ RES_PCI_IO, PCI_ADDR(0, 2, 1, 0x64), 0xF87FFFFF, 0x05000000,
+ RES_PCI_IO, PCI_ADDR(0, 2, 1, 0x78), 0xFFC07FFF, 0x00360000,
+ RES_PCI_IO, PCI_ADDR(0, 2, 1, 0x68), 0xFE00D03F, 0x013F2C00,
+ RES_PCI_IO, PCI_ADDR(0, 2, 1, 0x70), 0xFFF7FFFF, 0x00080000,
+ RES_PCI_IO, PCI_ADDR(0, 2, 1, 0x7C), 0xFFFFF00F, 0x00000570,
+ RES_PCI_IO, PCI_ADDR(0, 2, 1, 0xF8), 0xFFFFFFCF, 0x00000010,
+
+ RES_PCI_IO, PCI_ADDR(0, 6, 0, 0x04), 0xFFFFFEFB, 0x00000104,
+ RES_PCI_IO, PCI_ADDR(0, 6, 0, 0x3C), 0xF5FFFFFF, 0x0A000000,
+ RES_PCI_IO, PCI_ADDR(0, 6, 0, 0x40), 0x00C8FFFF, 0x07330000,
+ RES_PCI_IO, PCI_ADDR(0, 6, 0, 0x48), 0xFFFFFFF8, 0x00000005,
+ RES_PCI_IO, PCI_ADDR(0, 6, 0, 0x4C), 0xFE02FFFF, 0x004C0000,
+ RES_PCI_IO, PCI_ADDR(0, 6, 0, 0x74), 0xFFFFFFC0, 0x00000000,
+ RES_PCI_IO, PCI_ADDR(0, 6, 0, 0xC0), 0x00000000, 0xCB8410DE,
+ RES_PCI_IO, PCI_ADDR(0, 6, 0, 0xC4), 0xFFFFFFF8, 0x00000007,
+
+#if MCP55_USE_AZA == 1
+ RES_PCI_IO, PCI_ADDR(0, 6, 1, 0x40), 0x00000000, 0xCB8410DE,
+
+// RES_PCI_IO, PCI_ADDR(0, 1, 1, 0xE4), ~(1<<14), 1<<14,
+#endif
+// play a while with GPIO in MCP55
+#ifdef MCP55_MB_SETUP
+ MCP55_MB_SETUP
+#endif
+
+#if MCP55_USE_AZA == 1
+ RES_PORT_IO_8, SYSCTRL_IO_BASE + 0xc0+ 21, ~(3<<2), (2<<2),
+ RES_PORT_IO_8, SYSCTRL_IO_BASE + 0xc0+ 22, ~(3<<2), (2<<2),
+ RES_PORT_IO_8, SYSCTRL_IO_BASE + 0xc0+ 46, ~(3<<2), (2<<2),
+#endif
+
+
+ };
+
+ static const unsigned int ctrl_conf_master_only[] = {
+
+ RES_PORT_IO_32, ACPICTRL_IO_BASE + 0x80, 0xEFFFFFF, 0x01000000,
+
+ RES_PCI_IO, PCI_ADDR(0, 1, 0, 0x78), 0xC0FFFFFF, 0x19000000,
+
+ //Master MCP55 ????YHLU
+ RES_PORT_IO_8, SYSCTRL_IO_BASE + 0xc0+ 0, ~(3<<2), (0<<2),
+
+ };
+
+ static const unsigned int ctrl_conf_2[] = {
+ /* I didn't put pcie related stuff here */
+
+ RES_PCI_IO, PCI_ADDR(0, 0, 0, 0x74), 0xFFFFF00F, 0x000009D0,
+ RES_PCI_IO, PCI_ADDR(0, 1, 0, 0x74), 0xFFFF7FFF, 0x00008000,
+
+ RES_PORT_IO_32, SYSCTRL_IO_BASE + 0x48, 0xFFFEFFFF, 0x00010000,
+
+ RES_PORT_IO_32, ANACTRL_IO_BASE + 0x60, 0xFFFFFF00, 0x00000012,
+
+
+#if MCP55_USE_NIC == 1
+ RES_PCI_IO, PCI_ADDR(0, 1, 1, 0xe4), ~((1<<22)|(1<<20)), (1<<22)|(1<<20),
+
+ RES_PORT_IO_8, SYSCTRL_IO_BASE + 0xc0+ 4, ~(0xff), ((0<<4)|(1<<2)|(0<<0)),
+ RES_PORT_IO_8, SYSCTRL_IO_BASE + 0xc0+ 4, ~(0xff), ((0<<4)|(1<<2)|(1<<0)),
+#endif
+
+ };
+
+
+ int j, i;
+
+ for(j=0; j<mcp55_num; j++) {
+ mcp55_early_pcie_setup(busn[j], devn[j], io_base[j] + ANACTRL_IO_BASE, pci_e_x[j]);
+
+ setup_resource_map_x_offset(ctrl_conf_1, sizeof(ctrl_conf_1)/sizeof(ctrl_conf_1[0]),
+ PCI_DEV(busn[j], devn[j], 0), io_base[j]);
+ for(i=0; i<3; i++) { // three SATA
+ setup_resource_map_x_offset(ctrl_conf_1_1, sizeof(ctrl_conf_1_1)/sizeof(ctrl_conf_1_1[0]),
+ PCI_DEV(busn[j], devn[j], i), io_base[j]);
+ }
+ if(busn[j] == 0) {
+ setup_resource_map_x_offset(ctrl_conf_mcp55_only, sizeof(ctrl_conf_mcp55_only)/sizeof(ctrl_conf_mcp55_only[0]),
+ PCI_DEV(busn[j], devn[j], 0), io_base[j]);
+ }
+
+ if( (busn[j] == 0) && (mcp55_num>1) ) {
+ setup_resource_map_x_offset(ctrl_conf_master_only, sizeof(ctrl_conf_master_only)/sizeof(ctrl_conf_master_only[0]),
+ PCI_DEV(busn[j], devn[j], 0), io_base[j]);
+ }
+
+ setup_resource_map_x_offset(ctrl_conf_2, sizeof(ctrl_conf_2)/sizeof(ctrl_conf_2[0]),
+ PCI_DEV(busn[j], devn[j], 0), io_base[j]);
+
+ }
+
+#if 0
+ for(j=0; j< mcp55_num; j++) {
+ // PCI-E (XSPLL) SS table 0x40, x044, 0x48
+ // SATA (SPPLL) SS table 0xb0, 0xb4, 0xb8
+ // CPU (PPLL) SS table 0xc0, 0xc4, 0xc8
+ setup_ss_table(io_base[j] + ANACTRL_IO_BASE+0x40, io_base[j] + ANACTRL_IO_BASE+0x44,
+ io_base[j] + ANACTRL_IO_BASE+0x48, pcie_ss_tbl, 64);
+ setup_ss_table(io_base[j] + ANACTRL_IO_BASE+0xb0, io_base[j] + ANACTRL_IO_BASE+0xb4,
+ io_base[j] + ANACTRL_IO_BASE+0xb8, sata_ss_tbl, 64);
+ setup_ss_table(io_base[j] + ANACTRL_IO_BASE+0xc0, io_base[j] + ANACTRL_IO_BASE+0xc4,
+ io_base[j] + ANACTRL_IO_BASE+0xc8, cpu_ss_tbl, 64);
+ }
+#endif
+
+}
+
+#ifndef HT_CHAIN_NUM_MAX
+
+#define HT_CHAIN_NUM_MAX 4
+#define HT_CHAIN_BUSN_D 0x40
+#define HT_CHAIN_IOBASE_D 0x4000
+
+#endif
+
+static int mcp55_early_setup_x(void)
+{
+ /*find out how many mcp55 we have */
+ unsigned busn[HT_CHAIN_NUM_MAX];
+ unsigned devn[HT_CHAIN_NUM_MAX];
+ unsigned io_base[HT_CHAIN_NUM_MAX];
+ /*
+ FIXME: May have problem if there is different MCP55 HTX card with different PCI_E lane allocation
+ Need to use same trick about pci1234 to verify node/link connection
+ */
+ unsigned pci_e_x[HT_CHAIN_NUM_MAX] = {MCP55_PCI_E_X_0, MCP55_PCI_E_X_1, MCP55_PCI_E_X_2, MCP55_PCI_E_X_3 };
+ int mcp55_num = 0;
+ unsigned busnx;
+ unsigned devnx;
+ int ht_c_index,j;
+
+ /* FIXME: multi pci segment handling */
+
+ /* Any system that only have IO55 without MCP55? */
+ for(ht_c_index = 0; ht_c_index<HT_CHAIN_NUM_MAX; ht_c_index++) {
+ busnx = ht_c_index * HT_CHAIN_BUSN_D;
+ for(devnx=0;devnx<0x20;devnx++) {
+ uint32_t id;
+ device_t dev;
+ dev = PCI_DEV(busnx, devnx, 0);
+ id = pci_read_config32(dev, PCI_VENDOR_ID);
+ if(id == 0x036910de) {
+ busn[mcp55_num] = busnx;
+ devn[mcp55_num] = devnx;
+ io_base[mcp55_num] = ht_c_index * HT_CHAIN_IOBASE_D; // we may have ht chain other than MCP55
+ mcp55_num++;
+ if(mcp55_num == MCP55_NUM) goto out;
+ break; // only one MCP55 on one chain
+ }
+ }
+ }
+
+out:
+ print_debug("mcp55_num:"); print_debug_hex8(mcp55_num); print_debug("\r\n");
+
+ mcp55_early_set_port(mcp55_num, busn, devn, io_base);
+ mcp55_early_setup(mcp55_num, busn, devn, io_base, pci_e_x);
+
+ mcp55_early_clear_port(mcp55_num, busn, devn, io_base);
+
+// set_ht_link_mcp55(HT_CHAIN_NUM_MAX);
+
+ return 0;
+
+}
+
+
+
Index: mcp55/mcp55_reset.c
===================================================================
--- mcp55/mcp55_reset.c (revision 0)
+++ mcp55/mcp55_reset.c (revision 0)
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2004 Tyan Computer
+ * by yhlu@tyan.com
+ * Copyright 2006,2007 AMD inc.
+ * by yinghai.lu@amd.com
+ */
+
+#include <arch/io.h>
+
+#define PCI_DEV(BUS, DEV, FN) ( \
+ (((BUS) & 0xFFF) << 20) | \
+ (((DEV) & 0x1F) << 15) | \
+ (((FN) & 0x7) << 12))
+
+typedef unsigned device_t;
+
+static void pci_write_config32(device_t dev, unsigned where, unsigned value)
+{
+ unsigned addr;
+ addr = (dev>>4) | where;
+ outl(0x80000000 | (addr & ~3), 0xCF8);
+ outl(value, 0xCFC);
+}
+
+static unsigned pci_read_config32(device_t dev, unsigned where)
+{
+ unsigned addr;
+ addr = (dev>>4) | where;
+ outl(0x80000000 | (addr & ~3), 0xCF8);
+ return inl(0xCFC);
+}
+
+#include "../../../northbridge/amd/amdk8/reset_test.c"
+
+void hard_reset(void)
+{
+ set_bios_reset();
+ /* Try rebooting through port 0xcf9 */
+ /* Actually it is not a real hard_reset --- it only reset coherent link table, but not reset link freq and width */
+ outb((0 <<3)|(0<<2)|(1<<1), 0xcf9);
+ outb((0 <<3)|(1<<2)|(1<<1), 0xcf9);
+}
+
Index: mcp55/id.lds
===================================================================
--- mcp55/id.lds (revision 0)
+++ mcp55/id.lds (revision 0)
@@ -0,0 +1,6 @@
+SECTIONS {
+ . = (_ROMBASE + ROM_IMAGE_SIZE - 0x80) - (__id_end - __id_start);
+ .id (.): {
+ *(.id)
+ }
+}