Add support for DMP Vortex86EX PCI southbridge.

Change-Id: Iad11cb1b22e9d1e2953b12221541b1478cad9665
Signed-off-by: Andrew Wu <arw@dmp.com.tw>
Reviewed-on: http://review.coreboot.org/3547
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
Andrew Wu 2013-06-26 21:24:59 +08:00 committed by Ronald G. Minnich
parent dd94fa93b4
commit 00bf647bf6
11 changed files with 919 additions and 0 deletions

View File

@ -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

View File

@ -1,5 +1,6 @@
subdirs-y += amd
subdirs-y += broadcom
subdirs-y += dmp
subdirs-y += intel
subdirs-y += nvidia
subdirs-y += rdc

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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)
{
}

View File

@ -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,
};

View File

@ -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
};

View File

@ -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 */