[coreboot-gerrit] New patch to review for coreboot: 4cc3de6 Add support for DMP Vortex86EX PCI southbridge.

Andrew Wu (arw@dmp.com.tw) gerrit at coreboot.org
Wed Jun 26 15:27:26 CEST 2013


Andrew Wu (arw at dmp.com.tw) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3547

-gerrit

commit 4cc3de6babbaee2f04f1112a0f04b159299e3e19
Author: Andrew Wu <arw at dmp.com.tw>
Date:   Wed Jun 26 21:24:59 2013 +0800

    Add support for DMP Vortex86EX PCI southbridge.
    
    Change-Id: Iad11cb1b22e9d1e2953b12221541b1478cad9665
    Signed-off-by: Andrew Wu <arw at dmp.com.tw>
---
 src/southbridge/Kconfig                      |   1 +
 src/southbridge/Makefile.inc                 |   1 +
 src/southbridge/dmp/Kconfig                  |  20 +
 src/southbridge/dmp/Makefile.inc             |  20 +
 src/southbridge/dmp/vortex86ex/Kconfig       |  22 ++
 src/southbridge/dmp/vortex86ex/Makefile.inc  |  22 ++
 src/southbridge/dmp/vortex86ex/chip.h        |  38 ++
 src/southbridge/dmp/vortex86ex/hard_reset.c  |  25 ++
 src/southbridge/dmp/vortex86ex/ide_sd_sata.c | 171 ++++++++
 src/southbridge/dmp/vortex86ex/southbridge.c | 557 +++++++++++++++++++++++++++
 src/southbridge/dmp/vortex86ex/southbridge.h |  42 ++
 11 files changed, 919 insertions(+)

diff --git a/src/southbridge/Kconfig b/src/southbridge/Kconfig
index 31b7cc6..84b5f8d 100644
--- a/src/southbridge/Kconfig
+++ b/src/southbridge/Kconfig
@@ -1,5 +1,6 @@
 source src/southbridge/amd/Kconfig
 source src/southbridge/broadcom/Kconfig
+source src/southbridge/dmp/Kconfig
 source src/southbridge/intel/Kconfig
 source src/southbridge/nvidia/Kconfig
 source src/southbridge/rdc/Kconfig
diff --git a/src/southbridge/Makefile.inc b/src/southbridge/Makefile.inc
index 130d459..106752b 100644
--- a/src/southbridge/Makefile.inc
+++ b/src/southbridge/Makefile.inc
@@ -1,5 +1,6 @@
 subdirs-y += amd
 subdirs-y += broadcom
+subdirs-y += dmp
 subdirs-y += intel
 subdirs-y += nvidia
 subdirs-y += rdc
diff --git a/src/southbridge/dmp/Kconfig b/src/southbridge/dmp/Kconfig
new file mode 100644
index 0000000..1c5b8c7
--- /dev/null
+++ b/src/southbridge/dmp/Kconfig
@@ -0,0 +1,20 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2013 DMP Electronics Inc.
+##
+## 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.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+##
+
+source src/southbridge/dmp/vortex86ex/Kconfig
diff --git a/src/southbridge/dmp/Makefile.inc b/src/southbridge/dmp/Makefile.inc
new file mode 100644
index 0000000..a94e935
--- /dev/null
+++ b/src/southbridge/dmp/Makefile.inc
@@ -0,0 +1,20 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2013 DMP Electronics Inc.
+##
+## 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.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+##
+
+subdirs-$(CONFIG_SOUTHBRIDGE_DMP_VORTEX86EX) += vortex86ex
diff --git a/src/southbridge/dmp/vortex86ex/Kconfig b/src/southbridge/dmp/vortex86ex/Kconfig
new file mode 100644
index 0000000..e12477c
--- /dev/null
+++ b/src/southbridge/dmp/vortex86ex/Kconfig
@@ -0,0 +1,22 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2013 DMP Electronics Inc.
+##
+## 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.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+##
+
+config SOUTHBRIDGE_DMP_VORTEX86EX
+	bool
+	select HAVE_HARD_RESET
diff --git a/src/southbridge/dmp/vortex86ex/Makefile.inc b/src/southbridge/dmp/vortex86ex/Makefile.inc
new file mode 100644
index 0000000..6d2a921
--- /dev/null
+++ b/src/southbridge/dmp/vortex86ex/Makefile.inc
@@ -0,0 +1,22 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2013 DMP Electronics Inc.
+##
+## 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.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+##
+
+ramstage-y += southbridge.c
+ramstage-y += hard_reset.c
+ramstage-y += ide_sd_sata.c
diff --git a/src/southbridge/dmp/vortex86ex/chip.h b/src/southbridge/dmp/vortex86ex/chip.h
new file mode 100644
index 0000000..09312f9
--- /dev/null
+++ b/src/southbridge/dmp/vortex86ex/chip.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 DMP Electronics Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _SOUTHBRIDGE_DMP_VORTEX86EX
+#define _SOUTHBRIDGE_DMP_VORTEX86EX
+
+struct southbridge_dmp_vortex86ex_config {
+	/* PCI function enables */
+	/* i.e. so that pci scan bus will find them. */
+	/* I am putting in IDE as an example but obviously this needs
+	 * to be more complete!
+	 */
+	int enable_ide;
+	/* enables of functions of devices */
+	int enable_usb;
+	int enable_native_ide;
+	int enable_com_ports;
+	int enable_keyboard;
+	int enable_nvram;
+};
+
+#endif				/* _SOUTHBRIDGE_DMP_VORTEX86EX */
diff --git a/src/southbridge/dmp/vortex86ex/hard_reset.c b/src/southbridge/dmp/vortex86ex/hard_reset.c
new file mode 100644
index 0000000..5d216ab
--- /dev/null
+++ b/src/southbridge/dmp/vortex86ex/hard_reset.c
@@ -0,0 +1,25 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 DMP Electronics Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <reset.h>
+
+void hard_reset(void)
+{
+}
diff --git a/src/southbridge/dmp/vortex86ex/ide_sd_sata.c b/src/southbridge/dmp/vortex86ex/ide_sd_sata.c
new file mode 100644
index 0000000..8214549
--- /dev/null
+++ b/src/southbridge/dmp/vortex86ex/ide_sd_sata.c
@@ -0,0 +1,171 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 DMP Electronics Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <delay.h>
+#include <stdlib.h>
+#include <string.h>
+#include <arch/io.h>
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+
+/* Vortex86EX IDE to SD/STAT controller need to enable ATA decoder and
+ * setup timing. */
+
+/*
+ * Primary ATA Timing Register (PATR) - Offset 40-41h
+ * Secondary ATA Timing Register (PATR) - Offset 42-43h
+ *
+ * Bit     R/W     Default Description
+ * 15      R/W     0h      ATA Decode Enable. Decode the I/O addressing ranges assigned to this controller.
+ *                         1: Enabled.
+ *                         0: Disabled.
+ * 14      R/W     0b      Device 1 ATA Timing Register Enable
+ *                         1: Enable the device 1 ATA timing.
+ *                         0: Disable the device 1 ATA timing
+ * 13-12   R/W     0h      IORDY Sample Mode. Sets the setup time before IORDY are sampled.
+ *                         00: PIO-0
+ *                         10: PIO-2, SW-2
+ *                         10: PIO-3, PIO-4, MW-1, MW-2
+ *                         11: Reserved
+ * 11-10   RO      0h      Reserved
+ * 9-8     R/W     0h      Recovery Mode. Sets the hold time after IORDY are sampled.
+ *                         00: PIO-0, PIO-2, SW-2
+ *                         10: PIO-3, MW-1
+ *                         10: Reserved
+ *                         11: PIO-4, MW-2
+ * 7       R/W     0b      DMA Timing Enable Only Select 1
+ *                         1: Enable the device timings for DMA operation for device 1
+ *                         0: Disable the device timings for DMA operation for device 1
+ * 6       R/W     0b      ATA/ATAPI Device Indicator 1
+ *                         1: Indicate presence od an ATA device
+ *                         0: Indicate presence od an ATAPI device
+ * 5       R/W     0b      IORDY Sample Point Enabled Select 1
+ *                         1: Enable IORDY sample for PIO transfers for device 1
+ *                         0: Disable IORDY sample for PIO transfers for device 1
+ * 4       R/W     0b      Fast Drive Timing Select 1
+ *                         1: Enable faster than PIO-0 timing modes for device 1
+ *                         0: Disable faster than PIO-0 timing modes for device 1
+ * 3       R/W     0b      DMA Timing Enable Only Select 0
+ *                         1: Enable the device timings for DMA operation for device 0
+ *                         0: Disable the device timings for DMA operation for device 0
+ * 2       R/W     0b      ATA/ATAPI Device Indicator 0
+ *                         1: Indicate presence od an ATA device
+ *                         0: Indicate presence od an ATAPI device
+ * 1       R/W     0b      IORDY Sample Point Enabled Select 0
+ *                         1: Enable IORDY sample for PIO transfers for device 0
+ *                         0: Disable IORDY sample for PIO transfers for device 0
+ * 0       R/W     0b      Fast Drive Timing Select 0
+ *                         1: Enable faster than PIO-0 timing modes for device 0
+ *                         0: Disable faster than PIO-0 timing modes for device 0
+ * */
+
+static void init_ide_ata_timing(struct device *dev)
+{
+	u16 ata_timing_pri, ata_timing_sec;
+	u32 ata_timing_reg32;
+	/* Primary channel is SD. */
+#if CONFIG_IDE1_ENABLE
+	ata_timing_pri = 0x8000;
+#else
+	ata_timing_pri = 0x0000;	// Disable this channel.
+#endif
+	/* Secondary channel is SATA. */
+#if CONFIG_IDE2_ENABLE
+	ata_timing_sec = 0xa30f;	// This setting value works well.
+#else
+	ata_timing_sec = 0x0000;	// Disable this channel.
+#endif
+	ata_timing_reg32 = (ata_timing_sec << 16) | ata_timing_pri;
+	pci_write_config32(dev, 0x40, ata_timing_reg32);
+#if CONFIG_IDE_NATIVE_MODE
+	/* Set both IDE channels to native mode. */
+	u8 prog_if;
+	prog_if = pci_read_config8(dev, 0x09);
+	prog_if |= 5;
+	pci_write_config8(dev, 0x09, prog_if);
+#endif
+	/* MMC function enable. */
+	u32 sd_ctrl_reg;
+	sd_ctrl_reg = pci_read_config32(dev, 0x94);
+	sd_ctrl_reg |= 0x0200;
+	pci_write_config32(dev, 0x94, sd_ctrl_reg);
+	printk(BIOS_INFO, "Vortex86EX IDE controller ATA TIMING reg = %08x\n", ata_timing_reg32);
+}
+
+static void setup_std_ide_compatible(struct device *dev)
+{
+#if CONFIG_IDE_STANDARD_COMPATIBLE
+	// Misc Control Register (MCR) Offset 90h
+	// bit 0 = Vendor ID Access, bit 1 = Device ID Access.
+	u8 mcr;
+	u16 vendor = (u16) (CONFIG_IDE_COMPATIBLE_SELECTION >> 16);
+	u16 device = (u16) (CONFIG_IDE_COMPATIBLE_SELECTION & 0xffff);
+	// unlock vendor/device ID access bits.
+	mcr = pci_read_config8(dev, 0x90);
+	pci_write_config8(dev, 0x90, mcr | 3);
+	pci_write_config16(dev, 0x00, vendor);
+	pci_write_config16(dev, 0x02, device);
+	// restore lock bits.
+	pci_write_config8(dev, 0x90, mcr);
+#endif
+}
+
+static void vortex_ide_init(struct device *dev)
+{
+	if (dev->device == 0x1010) {
+		// This is SX/old DX IDE controller.
+		// Set IOCFG bit 15/13 : IDE Decoder Enable for Primary/Secondary channel.
+		u16 iocfg = 0xa000;
+		pci_write_config16(dev, 0x40, iocfg);
+	} else if (dev->device == 0x1011 || dev->device == 0x1012) {
+		// This is new DX/MX/MX+/DX2 IDE controller.
+		init_ide_ata_timing(dev);
+		setup_std_ide_compatible(dev);
+	}
+}
+
+static struct device_operations vortex_ide_ops = {
+	.read_resources   = pci_dev_read_resources,
+	.set_resources    = pci_dev_set_resources,
+	.enable_resources = pci_dev_enable_resources,
+	.init             = vortex_ide_init,
+	.scan_bus         = 0,
+};
+
+static const struct pci_driver vortex_ide_driver_1010 __pci_driver = {
+	.ops    = &vortex_ide_ops,
+	.vendor = PCI_VENDOR_ID_RDC,
+	.device = 0x1010,
+};
+
+static const struct pci_driver vortex_ide_driver_1011 __pci_driver = {
+	.ops    = &vortex_ide_ops,
+	.vendor = PCI_VENDOR_ID_RDC,
+	.device = 0x1011,
+};
+
+static const struct pci_driver vortex_ide_driver_1012 __pci_driver = {
+	.ops    = &vortex_ide_ops,
+	.vendor = PCI_VENDOR_ID_RDC,
+	.device = 0x1012,
+};
diff --git a/src/southbridge/dmp/vortex86ex/southbridge.c b/src/southbridge/dmp/vortex86ex/southbridge.c
new file mode 100644
index 0000000..28fe3c9
--- /dev/null
+++ b/src/southbridge/dmp/vortex86ex/southbridge.c
@@ -0,0 +1,557 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 DMP Electronics Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ops.h>
+#include <device/pci_ids.h>
+#include <pc80/mc146818rtc.h>
+#include <string.h>
+#include "arch/io.h"
+#include "chip.h"
+#include "southbridge.h"
+
+/* IRQ number to S/B PCI Interrupt routing table reg(0x58/0xb4) mapping table. */
+static const unsigned char irq_to_int_routing[16] = {
+	0x0, 0x0, 0x0, 0x2,	// IRQ0-2 is unmappable, IRQ3 = 2.
+	0x4, 0x5, 0x7, 0x6,	// IRQ4-7 = 4, 5, 7, 6.
+	0x0, 0x1, 0x3, 0x9,	// IRQ8 is unmappable, IRQ9-11 = 1, 3, 9.
+	0xb, 0x0, 0xd, 0xf	// IRQ12 = b, IRQ13 is unmappable, IRQ14-15 = d, f.
+};
+
+/* S/B PCI Interrupt routing table reg(0x58) field bit shift. */
+#define EHCIH_IRQ_SHIFT 28
+#define OHCII_IRQ_SHIFT 24
+#define MAC_IRQ_SHIFT 16
+#define RT3_IRQ_SHIFT 12
+#define RT2_IRQ_SHIFT 8
+#define RT1_IRQ_SHIFT 4
+#define RT0_IRQ_SHIFT 0
+
+/* S/B Extend PCI Interrupt routing table reg(0xb4) field bit shift. */
+#define USBD_IRQ_SHIFT 16
+#define SIDE_IRQ_SHIFT 12
+#define PIDE_IRQ_SHIFT 8
+
+/* in-chip PCI device IRQs(0 for disabled). */
+#define EHCII_IRQ 5
+#define OHCII_IRQ 5
+#define MAC_IRQ 6
+
+#define USBD_IRQ 0
+#define PIDE_IRQ 5
+
+/* RT0-3 IRQs. */
+#define RT3_IRQ 3
+#define RT2_IRQ 4
+#define RT1_IRQ 5
+#define RT0_IRQ 6
+
+/* IDE legacy mode IRQs. */
+#define IDE1_LEGACY_IRQ 14
+#define IDE2_LEGACY_IRQ 15
+
+/* Internal parallel port */
+#define LPT_INT_C 0
+#define LPT_INT_ACK_SET 0
+#define LPT_UE 1
+#define LPT_PDMAS 0
+#define LPT_DREQS 0
+
+/* Post codes */
+#define POST_KBD_FW_UPLOAD 0x06
+#define POST_KBD_CHK_READY 0x07
+#define POST_KBD_IS_READY 0x08
+#define POST_KBD_FW_VERIFY_FAILURE 0x82
+
+static u8 get_pci_dev_func(device_t dev)
+{
+	return PCI_FUNC(dev->path.pci.devfn);
+}
+
+static void verify_dmp_keyboard_error(void)
+{
+	post_code(POST_KBD_FW_VERIFY_FAILURE);
+	die("Internal keyboard firmware verify error!\n");
+}
+
+static void upload_dmp_keyboard_firmware(struct device *dev)
+{
+	u32 reg_sb_c0;
+	u32 fwptr;
+
+	// enable firmware uploading function by set bit 10.
+	post_code(POST_KBD_FW_UPLOAD);
+	reg_sb_c0 = pci_read_config32(dev, SB_REG_IPFCR);
+	pci_write_config32(dev, SB_REG_IPFCR, reg_sb_c0 | 0x400);
+
+	outw(0, 0x62);		// reset upload address to 0.
+	// upload 4096 bytes from 0xFFFFE000.
+	outsb(0x66, (u8 *) 0xffffe000, 4096);
+	// upload 4096 bytes from 0xFFFFC000.
+	outsb(0x66, (u8 *) 0xffffc000, 4096);
+
+	outw(0, 0x62);		// reset upload address to 0.
+	// verify 4096 bytes from 0xFFFFE000.
+	for (fwptr = 0xffffe000; fwptr < 0xfffff000; fwptr++) {
+		if (inb(0x66) != *(u8 *) fwptr) {
+			verify_dmp_keyboard_error();
+		}
+	}
+	// verify 4096 bytes from 0xFFFFC000.
+	for (fwptr = 0xffffc000; fwptr < 0xffffd000; fwptr++) {
+		if (inb(0x66) != *(u8 *) fwptr) {
+			verify_dmp_keyboard_error();
+		}
+	}
+
+	// disable firmware uploading.
+	pci_write_config32(dev, SB_REG_IPFCR, reg_sb_c0 & ~0x400L);
+	// wait keyboard controller ready by checking status port bit 2.
+	post_code(POST_KBD_CHK_READY);
+	while ((inb(0x64) & 0x4) == 0) {
+	}
+	post_code(POST_KBD_IS_READY);
+}
+
+static void pci_routing_fixup(struct device *dev)
+{
+	const unsigned slot[3] = { 0 };
+	const unsigned char slot_irqs[1][4] = {
+		{RT0_IRQ, RT1_IRQ, RT2_IRQ, RT3_IRQ},
+	};
+	const int slot_num = 1;
+	int i;
+	u32 int_routing = 0;
+	u32 ext_int_routing = 0;
+
+	/* assign PCI-e bridge (bus#0, dev#1, fn#0) IRQ to RT0. */
+	pci_assign_irqs(0, 1, slot_irqs[0]);
+
+	/* RT0 is enabled. */
+	int_routing |= irq_to_int_routing[RT0_IRQ] << RT0_IRQ_SHIFT;
+
+	/* assign PCI slot IRQs. */
+	for (i = 0; i < slot_num; i++) {
+		pci_assign_irqs(1, slot[i], slot_irqs[i]);
+	}
+
+	/* Read PCI slot IRQs to see if RT1-3 is used, and enables it */
+	for (i = 0; i < slot_num; i++) {
+		unsigned int funct;
+		device_t pdev;
+		u8 irq;
+
+		/* Each slot may contain up to eight functions. */
+		for (funct = 0; funct < 8; funct++) {
+			pdev = dev_find_slot(1, (slot[i] << 3) + funct);
+			if (!pdev)
+				continue;
+			irq = pci_read_config8(pdev, PCI_INTERRUPT_LINE);
+			if (irq == RT1_IRQ) {
+				int_routing |= irq_to_int_routing[RT1_IRQ] << RT1_IRQ_SHIFT;
+			} else if (irq == RT2_IRQ) {
+				int_routing |= irq_to_int_routing[RT2_IRQ] << RT2_IRQ_SHIFT;
+			} else if (irq == RT3_IRQ) {
+				int_routing |= irq_to_int_routing[RT3_IRQ] << RT3_IRQ_SHIFT;
+			}
+		}
+	}
+
+	/* Setup S/B PCI Interrupt routing table reg(0x58). */
+	int_routing |= irq_to_int_routing[EHCII_IRQ] << EHCIH_IRQ_SHIFT;
+	int_routing |= irq_to_int_routing[OHCII_IRQ] << OHCII_IRQ_SHIFT;
+	int_routing |= irq_to_int_routing[MAC_IRQ] << MAC_IRQ_SHIFT;
+	pci_write_config32(dev, SB_REG_PIRQ_X_ROUT, int_routing);
+
+	/* Setup S/B PCI Extend Interrupt routing table reg(0xb4). */
+	ext_int_routing |= irq_to_int_routing[USBD_IRQ] << USBD_IRQ_SHIFT;
+#if CONFIG_IDE_NATIVE_MODE
+	/* IDE in native mode, only uses one IRQ. */
+	ext_int_routing |= irq_to_int_routing[0] << SIDE_IRQ_SHIFT;
+	ext_int_routing |= irq_to_int_routing[PIDE_IRQ] << PIDE_IRQ_SHIFT;
+#else
+	/* IDE in legacy mode, use IRQ 14, 15. */
+	ext_int_routing |= irq_to_int_routing[IDE2_LEGACY_IRQ] << SIDE_IRQ_SHIFT;
+	ext_int_routing |= irq_to_int_routing[IDE1_LEGACY_IRQ] << PIDE_IRQ_SHIFT;
+#endif
+	pci_write_config32(dev, SB_REG_PIRQ_X_ROUT2, ext_int_routing);
+
+	/* Assign in-chip PCI device IRQs. */
+	if (MAC_IRQ) {
+		unsigned char irqs[4] = { MAC_IRQ, 0, 0, 0 };
+		pci_assign_irqs(0, 0x8, irqs);
+	}
+	if (OHCII_IRQ && EHCII_IRQ) {
+		unsigned char irqs[4] = { OHCII_IRQ, EHCII_IRQ, 0, 0 };
+		pci_assign_irqs(0, 0xa, irqs);
+	}
+	if (CONFIG_IDE_NATIVE_MODE && PIDE_IRQ) {
+		/* IDE in native mode, setup PCI IRQ. */
+		unsigned char irqs[4] = { PIDE_IRQ, 0, 0, 0 };
+		pci_assign_irqs(0, 0xc, irqs);
+	}
+	if (USBD_IRQ) {
+		unsigned char irqs[4] = { USBD_IRQ, 0, 0, 0 };
+		pci_assign_irqs(0, 0xf, irqs);
+	}
+}
+
+static void vortex_sb_init(struct device *dev)
+{
+	u32 lpt_reg = 0;
+
+#if CONFIG_LPT_ENABLE
+	int ppmod = 0;
+#if CONFIG_LPT_MODE_BPP
+	ppmod = 0;
+#elif CONFIG_LPT_MODE_EPP_19_AND_SPP
+	ppmod = 1;
+#elif CONFIG_LPT_MODE_ECP
+	ppmod = 2;
+#elif CONFIG_LPT_MODE_ECP_AND_EPP_19
+	ppmod = 3;
+#elif CONFIG_LPT_MODE_SPP
+	ppmod = 4;
+#elif CONFIG_LPT_MODE_EPP_17_AND_SPP
+	ppmod = 5;
+#elif CONFIG_LPT_MODE_ECP_AND_EPP_17
+	ppmod = 7;
+#else
+#error CONFIG_LPT_MODE error.
+#endif
+
+	/* Setup internal parallel port */
+	lpt_reg |= (LPT_INT_C << 28);
+	lpt_reg |= (LPT_INT_ACK_SET << 27);
+	lpt_reg |= (ppmod << 24);
+	lpt_reg |= (LPT_UE << 23);
+	lpt_reg |= (LPT_PDMAS << 22);
+	lpt_reg |= (LPT_DREQS << 20);
+	lpt_reg |= (irq_to_int_routing[CONFIG_LPT_IRQ] << 16);
+	lpt_reg |= (CONFIG_LPT_IO << 0);
+#endif				// CONFIG_LPT_ENABLE
+	pci_write_config32(dev, SB_REG_IPPCR, lpt_reg);
+}
+
+#define SETUP_GPIO_ADDR(n) \
+	u32 cfg##n = (CONFIG_GPIO_P##n##_DIR_ADDR << 16) | (CONFIG_GPIO_P##n##_DATA_ADDR);\
+	outl(cfg##n, base + 4 + (n * 4));\
+	gpio_enable_mask |= (1 << n);
+
+#define INIT_GPIO(n) \
+	outb(CONFIG_GPIO_P##n##_INIT_DIR, CONFIG_GPIO_P##n##_DIR_ADDR);\
+	outb(CONFIG_GPIO_P##n##_INIT_DATA, CONFIG_GPIO_P##n##_DATA_ADDR);
+
+static void ex_sb_gpio_init(struct device *dev)
+{
+	const int base = 0xb00;
+	u32 gpio_enable_mask = 0;
+	/* S/B register 63h - 62h : GPIO Port Config IO Base Address */
+	pci_write_config16(dev, SB_REG_GPIO_CFG_IO_BASE, base | 1);
+	/* Set GPIO port 0~9 base address.
+	 * Config Base + 04h, 08h, 0ch... : GPIO port 0~9 data/dir decode addr.
+	 * Bit 31-16 : DBA, GPIO direction base address.
+	 * Bit 15-0  : DPBA, GPIO data port base address.
+	 * */
+#if CONFIG_GPIO_P0_ENABLE
+	SETUP_GPIO_ADDR(0)
+#endif
+#if CONFIG_GPIO_P1_ENABLE
+	SETUP_GPIO_ADDR(1)
+#endif
+#if CONFIG_GPIO_P2_ENABLE
+	SETUP_GPIO_ADDR(2)
+#endif
+#if CONFIG_GPIO_P3_ENABLE
+	SETUP_GPIO_ADDR(3)
+#endif
+#if CONFIG_GPIO_P4_ENABLE
+	SETUP_GPIO_ADDR(4)
+#endif
+#if CONFIG_GPIO_P5_ENABLE
+	SETUP_GPIO_ADDR(5)
+#endif
+#if CONFIG_GPIO_P6_ENABLE
+	SETUP_GPIO_ADDR(6)
+#endif
+#if CONFIG_GPIO_P7_ENABLE
+	SETUP_GPIO_ADDR(7)
+#endif
+#if CONFIG_GPIO_P8_ENABLE
+	SETUP_GPIO_ADDR(8)
+#endif
+#if CONFIG_GPIO_P9_ENABLE
+	SETUP_GPIO_ADDR(9)
+#endif
+	/* Enable GPIO port 0~9. */
+	outl(gpio_enable_mask, base);
+	/* Set GPIO port 0-9 initial dir and data. */
+#if CONFIG_GPIO_P0_ENABLE
+	INIT_GPIO(0)
+#endif
+#if CONFIG_GPIO_P1_ENABLE
+	INIT_GPIO(1)
+#endif
+#if CONFIG_GPIO_P2_ENABLE
+	INIT_GPIO(2)
+#endif
+#if CONFIG_GPIO_P3_ENABLE
+	INIT_GPIO(3)
+#endif
+#if CONFIG_GPIO_P4_ENABLE
+	INIT_GPIO(4)
+#endif
+#if CONFIG_GPIO_P5_ENABLE
+	INIT_GPIO(5)
+#endif
+#if CONFIG_GPIO_P6_ENABLE
+	INIT_GPIO(6)
+#endif
+#if CONFIG_GPIO_P7_ENABLE
+	INIT_GPIO(7)
+#endif
+#if CONFIG_GPIO_P8_ENABLE
+	INIT_GPIO(8)
+#endif
+#if CONFIG_GPIO_P9_ENABLE
+	INIT_GPIO(9)
+#endif
+	/* Disable GPIO Port Config IO Base Address. */
+	pci_write_config16(dev, SB_REG_GPIO_CFG_IO_BASE, 0x0);
+}
+
+static u32 make_uart_config(u16 base, u8 irq)
+{
+	u8 mapped_irq = irq_to_int_routing[irq];
+	u32 cfg = 0;
+	cfg |= 1 << 23;			// UE = enabled.
+	cfg |= (mapped_irq << 16);	// UIRT.
+	cfg |= base;			// UIOA.
+	return cfg;
+}
+
+#define SETUP_UART(n) \
+	uart_cfg = make_uart_config(CONFIG_UART##n##_IO, CONFIG_UART##n##_IRQ);\
+	outl(uart_cfg, base + (n - 1) * 4);\
+	uart8250_init(CONFIG_UART##n##_IO, 115200 / CONFIG_UART##n##_BAUD);
+
+static void ex_sb_uart_init(struct device *dev)
+{
+	const int base = 0xc00;
+	u32 uart_cfg = 0;
+	/* S/B register 61h - 60h : UART Config IO Base Address */
+	pci_write_config16(dev, SB_REG_UART_CFG_IO_BASE, base | 1);
+	/* setup UART */
+#if CONFIG_UART1_ENABLE
+	SETUP_UART(1)
+#endif
+#if CONFIG_UART2_ENABLE
+	SETUP_UART(2)
+#endif
+#if CONFIG_UART3_ENABLE
+	SETUP_UART(3)
+#endif
+#if CONFIG_UART4_ENABLE
+	SETUP_UART(4)
+#endif
+#if CONFIG_UART5_ENABLE
+	SETUP_UART(5)
+#endif
+#if CONFIG_UART6_ENABLE
+	SETUP_UART(6)
+#endif
+#if CONFIG_UART7_ENABLE
+	SETUP_UART(7)
+#endif
+#if CONFIG_UART8_ENABLE
+	SETUP_UART(8)
+#endif
+#if CONFIG_UART9_ENABLE
+	SETUP_UART(9)
+#endif
+#if CONFIG_UART10_ENABLE
+	SETUP_UART(10)
+#endif
+	/* Keep UART Config I/O base address */
+	//pci_write_config16(SB, SB_REG_UART_CFG_IO_BASE, 0x0);
+}
+
+static int get_rtc_update_in_progress(void)
+{
+	if (cmos_read(RTC_REG_A) & RTC_UIP)
+		return 1;
+	return 0;
+}
+
+static void unsafe_read_cmos_rtc(u8 rtc[7])
+{
+	rtc[0] = cmos_read(RTC_CLK_ALTCENTURY);
+	rtc[1] = cmos_read(RTC_CLK_YEAR);
+	rtc[2] = cmos_read(RTC_CLK_MONTH);
+	rtc[3] = cmos_read(RTC_CLK_DAYOFMONTH);
+	rtc[4] = cmos_read(RTC_CLK_HOUR);
+	rtc[5] = cmos_read(RTC_CLK_MINUTE);
+	rtc[6] = cmos_read(RTC_CLK_SECOND);
+}
+
+static void read_cmos_rtc(u8 rtc[7])
+{
+	/* Read RTC twice and check update-in-progress flag, to make
+	 * sure RTC is correct */
+	u8 rtc_old[7], rtc_new[7];
+	while (get_rtc_update_in_progress()) ;
+	unsafe_read_cmos_rtc(rtc_new);
+	do {
+		memcpy(rtc_old, rtc_new, 7);
+		while (get_rtc_update_in_progress()) ;
+		unsafe_read_cmos_rtc(rtc_new);
+	} while (memcmp(rtc_new, rtc_old, 7) != 0);
+}
+
+/*
+ * Convert a number in decimal format into the BCD format.
+ * Return 255 if not a valid BCD value.
+ */
+static u8 bcd2dec(u8 bcd)
+{
+	u8 h, l;
+	h = bcd >> 4;
+	l = bcd & 0xf;
+	if (h > 9 || l > 9)
+		return 255;
+	return h * 10 + l;
+}
+
+static void fix_cmos_rtc_time(void)
+{
+	/* Read RTC data. */
+	u8 rtc[7];
+	read_cmos_rtc(rtc);
+
+	/* Convert RTC from BCD format to binary. */
+	u8 bin_rtc[7];
+	int i;
+	for (i = 0; i < 8; i++) {
+		bin_rtc[i] = bcd2dec(rtc[i]);
+	}
+
+	/* If RTC date is invalid, fix it. */
+	if (bin_rtc[0] > 99 || bin_rtc[1] > 99 || bin_rtc[2] > 12 || bin_rtc[3] > 31) {
+		/* Set PC compatible timing mode. */
+		cmos_write(0x26, RTC_REG_A);
+		cmos_write(0x02, RTC_REG_B);
+		/* Now setup a default date 2008/08/08 08:08:08. */
+		cmos_write(0x8, RTC_CLK_SECOND);
+		cmos_write(0x8, RTC_CLK_MINUTE);
+		cmos_write(0x8, RTC_CLK_HOUR);
+		cmos_write(0x6, RTC_CLK_DAYOFWEEK);	/* Friday */
+		cmos_write(0x8, RTC_CLK_DAYOFMONTH);
+		cmos_write(0x8, RTC_CLK_MONTH);
+		cmos_write(0x8, RTC_CLK_YEAR);
+		cmos_write(0x20, RTC_CLK_ALTCENTURY);
+	}
+}
+
+static void vortex86_sb_set_io_resv(device_t dev, u32 io_resv_size)
+{
+	struct resource *res;
+	res = new_resource(dev, 1);
+	res->base = 0x0UL;
+	res->size = io_resv_size;
+	res->limit = 0xffffUL;
+	res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+}
+
+static void vortex86_sb_set_spi_flash_size(device_t dev, u32 flash_size)
+{
+	/* SPI flash is in topmost of 4G memory space */
+	struct resource *res;
+	res = new_resource(dev, 2);
+	res->base = 0x100000000LL - flash_size;
+	res->size = flash_size;
+	res->limit = 0xffffffffUL;
+	res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
+}
+
+static void vortex86_sb_read_resources(device_t dev)
+{
+	u32 flash_size = 8 * 1024 * 1024;
+
+	pci_dev_read_resources(dev);
+
+	if (dev->device == 0x6011) {
+		/* It is EX CPU southbridge */
+		if (get_pci_dev_func(dev) != 0) {
+			/* only for function 0, skip function 1 */
+			return;
+		}
+		/* default SPI flash ROM is 64MB */
+		flash_size = 64 * 1024 * 1024;
+	}
+
+	/* Reserve space for I/O */
+	vortex86_sb_set_io_resv(dev, 0x1000UL);
+
+	/* Reserve space for flash */
+	vortex86_sb_set_spi_flash_size(dev, flash_size);
+}
+
+static void southbridge_init(struct device *dev)
+{
+	if (dev->device == 0x6011) {
+		/* It is EX CPU southbridge */
+		if (get_pci_dev_func(dev) != 0) {
+			/* only for function 0, skip function 1 */
+			return;
+		}
+	}
+	upload_dmp_keyboard_firmware(dev);
+	vortex_sb_init(dev);
+	if (dev->device == 0x6011) {
+		ex_sb_gpio_init(dev);
+		ex_sb_uart_init(dev);
+	}
+	pci_routing_fixup(dev);
+
+	fix_cmos_rtc_time();
+	rtc_init(0);
+}
+
+static struct device_operations vortex_sb_ops = {
+	.read_resources   = vortex86_sb_read_resources,
+	.set_resources    = pci_dev_set_resources,
+	.enable_resources = pci_dev_enable_resources,
+	.init             = &southbridge_init,
+	.scan_bus         = scan_static_bus,
+	.enable           = 0,
+	.ops_pci          = 0,
+};
+
+static const struct pci_driver pci_driver_6011 __pci_driver = {
+	.ops    = &vortex_sb_ops,
+	.vendor = PCI_VENDOR_ID_RDC,
+	.device = 0x6011,	/* EX CPU S/B ID */
+};
+
+struct chip_operations southbridge_dmp_vortex86ex_ops = {
+	CHIP_NAME("DMP Vortex86EX Southbridge")
+	.enable_dev = 0
+};
diff --git a/src/southbridge/dmp/vortex86ex/southbridge.h b/src/southbridge/dmp/vortex86ex/southbridge.h
new file mode 100644
index 0000000..60e6dbc
--- /dev/null
+++ b/src/southbridge/dmp/vortex86ex/southbridge.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 DMP Electronics Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef SOUTHBRIDGE_H
+#define SOUTHBRIDGE_H
+
+#define	SB			PCI_DEV(0, 7, 0)
+#define	SB_REG_LPCCR		0x41
+#define	SB_REG_FRCSCR		0x42
+#define	SB_REG_PIRQ_X_ROUT	0x58
+#define	SB_REG_UART_CFG_IO_BASE	0x60
+#define	SB_REG_GPIO_CFG_IO_BASE	0x62
+#define	SB_REG_CS_BASE0		0x90
+#define	SB_REG_CS_BASE_MASK0	0x94
+#define	SB_REG_CS_BASE1		0x98
+#define	SB_REG_CS_BASE_MASK1	0x9c
+#define	SB_REG_IPPCR		0xb0
+#define	SB_REG_PIRQ_X_ROUT2	0xb4
+#define	SB_REG_OCDCR		0xbc
+#define	SB_REG_IPFCR		0xc0
+#define	SB_REG_FRWPR		0xc4
+#define	SB_REG_STRAP		0xce
+
+#define	SYSTEM_CTL_PORT         0x92
+
+#endif				/* SOUTHBRIDGE_H */



More information about the coreboot-gerrit mailing list