diff options
author | zbao <fishbaozi@gmail.com> | 2012-07-13 18:47:03 +0800 |
---|---|---|
committer | Patrick Georgi <patrick@georgi-clan.de> | 2012-07-14 16:29:52 +0200 |
commit | 246e84bc0d04e3e670ca815eca32bcfa3be7e2c2 (patch) | |
tree | 10aadb7c1812235e2572d528a91f339d758f217d /src/southbridge | |
parent | 22b7a55a4db9d9bfa69113a8e25e86f21ce8ab6e (diff) | |
download | coreboot-246e84bc0d04e3e670ca815eca32bcfa3be7e2c2.tar.xz |
AGESA F15 wrapper for Hudson.
Hudson code has been integrated from CIMx to AGESA. This patch is about the wrapper.
Change-Id: I63d951982140b82a3a77a97eb3d55fc75fc0caa3
Signed-off-by: Zheng Bao <zheng.bao@amd.com>
Signed-off-by: zbao <fishbaozi@gmail.com>
Reviewed-on: http://review.coreboot.org/1157
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
Diffstat (limited to 'src/southbridge')
27 files changed, 2332 insertions, 1 deletions
diff --git a/src/southbridge/amd/Kconfig b/src/southbridge/amd/Kconfig index 1b997aefd6..867afcaf8b 100644 --- a/src/southbridge/amd/Kconfig +++ b/src/southbridge/amd/Kconfig @@ -12,4 +12,5 @@ source src/southbridge/amd/rs780/Kconfig source src/southbridge/amd/sb700/Kconfig source src/southbridge/amd/sb800/Kconfig source src/southbridge/amd/cimx/Kconfig +source src/southbridge/amd/agesa/Kconfig source src/southbridge/amd/sr5650/Kconfig diff --git a/src/southbridge/amd/Makefile.inc b/src/southbridge/amd/Makefile.inc index 9bc58cd358..970971518a 100644 --- a/src/southbridge/amd/Makefile.inc +++ b/src/southbridge/amd/Makefile.inc @@ -14,6 +14,7 @@ subdirs-$(CONFIG_SOUTHBRIDGE_AMD_CS5536) += cs5536 subdirs-$(CONFIG_SOUTHBRIDGE_AMD_CIMX_SB700) += cimx subdirs-$(CONFIG_SOUTHBRIDGE_AMD_CIMX_SB800) += cimx subdirs-$(CONFIG_SOUTHBRIDGE_AMD_CIMX_SB900) += cimx +subdirs-$(CONFIG_SOUTHBRIDGE_AMD_AGESA_HUDSON) += agesa ifeq ($(CONFIG_HAVE_ACPI_RESUME), y) ifeq ($(CONFIG_CPU_AMD_AGESA), y) @@ -21,7 +22,7 @@ ifeq ($(CONFIG_CPU_AMD_AGESA), y) $(obj)/s3.rom: echo " S3 NVRAM 0xffff0000 (S3 storage area)" # force C locale, so cygwin awk doesn't try to interpret the 0xff below as UTF-8 (or worse) - LC_ALL=C awk 'BEGIN {for (i=0; i<20480; i++) {printf "%c", 255}}' > $@.tmp + LC_ALL=C awk 'BEGIN {for (i=0; i<32768; i++) {printf "%c", 255}}' > $@.tmp mv $@.tmp $@ cbfs-files-y += s3nv diff --git a/src/southbridge/amd/agesa/Kconfig b/src/southbridge/amd/agesa/Kconfig new file mode 100644 index 0000000000..29e00a68fa --- /dev/null +++ b/src/southbridge/amd/agesa/Kconfig @@ -0,0 +1,20 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2012 Advanced Micro Devices, 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/amd/agesa/hudson/Kconfig diff --git a/src/southbridge/amd/agesa/Makefile.inc b/src/southbridge/amd/agesa/Makefile.inc new file mode 100644 index 0000000000..72e62ac7f2 --- /dev/null +++ b/src/southbridge/amd/agesa/Makefile.inc @@ -0,0 +1,19 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2012 Advanced Micro Devices, 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_AMD_AGESA_HUDSON) += hudson diff --git a/src/southbridge/amd/agesa/hudson/Kconfig b/src/southbridge/amd/agesa/hudson/Kconfig new file mode 100644 index 0000000000..5b2904232a --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/Kconfig @@ -0,0 +1,208 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2010 Advanced Micro Devices, 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_AMD_AGESA_HUDSON + bool + select IOAPIC + select HAVE_USBDEBUG + select TINY_BOOTBLOCK + +config BOOTBLOCK_SOUTHBRIDGE_INIT + string + default "southbridge/amd/agesa/hudson/bootblock.c" + depends on SOUTHBRIDGE_AMD_AGESA_HUDSON + +config SOUTHBRIDGE_AMD_HUDSON_SKIP_ISA_DMA_INIT + bool + default n + depends on SOUTHBRIDGE_AMD_AGESA_HUDSON + +config EHCI_BAR + hex + default 0xfef00000 if SOUTHBRIDGE_AMD_AGESA_HUDSON + +config EHCI_DEBUG_OFFSET + hex + default 0xe0 if SOUTHBRIDGE_AMD_AGESA_HUDSON + + +if SOUTHBRIDGE_AMD_AGESA_HUDSON + +config HUDSON_XHCI_FWM + bool "Add xhci firmware" + default y + help + Add Hudson 2/3/4 XHCI Firmware to support the onboard usb3.0 + Please contact AMD to obtain the related firmware + +config HUDSON_IMC_FWM + bool "Add imc firmware" + default y + help + Add Hudson 2/3/4 IMC Firmware to support the onboard fan control + Please contact AMD to obtain the related firmware + +config HUDSON_GEC_FWM + bool "Add gec firmware" + default n + help + Add Hudson 2/3/4 GEC Firmware + Please contact AMD to obtain the related firmware + +config HUDSON_XHCI_FWM_FILE + string "XHCI firmware path and filename" + default "3rdparty/amd/hudson/xhci.bin" + depends on HUDSON_XHCI_FWM + +config HUDSON_IMC_FWM_FILE + string "IMC firmware path and filename" + default "3rdparty/amd/hudson/imc.bin" + depends on HUDSON_IMC_FWM + +config HUDSON_GEC_FWM_FILE + string "GEC firmware path and filename" + default "src/southbridge/amd/agesa/hudson/gec.bin" + depends on HUDSON_GEC_FWM + +config HUDSON_FWM + bool + default y if HUDSON_XHCI_FWM || HUDSON_IMC_FWM || HUDSON_GEC_FWM + default n if !HUDSON_XHCI_FWM && !HUDSON_IMC_FWM && !HUDSON_GEC_FWM + +if HUDSON_FWM + +config HUDSON_FWM_POSITION + hex "Hudson Firmware rom Position" + default 0xFFF20000 if BOARD_ROMSIZE_KB_1024 + default 0xFFE20000 if BOARD_ROMSIZE_KB_2048 + default 0xFFC20000 if BOARD_ROMSIZE_KB_4096 + default 0xFF820000 if BOARD_ROMSIZE_KB_8192 + default 0xFF020000 if BOARD_ROMSIZE_KB_16384 + help + Hudson requires the firmware MUST to be located at + a specific address (ROM start address + 0x20000), otherwise + xhci host Controller can not find or load the xhci firmware. + + The firmware start address is dependent on the ROM chip size. + The default offset is 0x20000 from the ROM start address, namely + 0xFFF20000 if flash chip size is 1M + 0xFFE20000 if flash chip size is 2M + 0xFFC20000 if flash chip size is 4M + 0xFF820000 if flash chip size is 8M + 0xFF020000 if flash chip size is 16M +endif + +choice + prompt "SATA Mode" + default HUDSON_SATA_IDE + help + Select the mode in which SATA should be driven. NATIVE AHCI, or RAID. + The default is NATIVE. + +config HUDSON_SATA_IDE + bool "NATIVE" + help + NATIVE is the default mode and does not require a ROM. + +config HUDSON_SATA_RAID + bool "RAID" + help + HUDSON RAID mode must have the two required ROM files. + +config HUDSON_SATA_AHCI + bool "AHCI" + help + AHCI may work with or without AHCI ROM. It depends on the payload support. + For example, seabios does not require the AHCI ROM. + +config HUDSON_SATA_LEGACY_IDE + bool "LEGACY IDE" + help + TODO + +config HUDSON_SATA_IDE2AHCI + bool "IDE to AHCI" + help + TODO + +config HUDSON_SATA_AHCI7804 + bool "AHCI7804" + help + AHCI ROM Required, and AMD driver required in the OS. + +config HUDSON_SATA_IDE2AHCI7804 + bool "IDE to AHCI7804" + help + AHCI ROM Required, and AMD driver required in the OS. +endchoice + +config HUDSON_SATA_MODE + hex + depends on (HUDSON_SATA_IDE || HUDSON_SATA_RAID || HUDSON_SATA_AHCI) + default "0x0" if HUDSON_SATA_IDE + default "0x1" if HUDSON_SATA_RAID + default "0x2" if HUDSON_SATA_AHCI + default "0x3" if HUDSON_SATA_LEGACY_IDE + default "0x4" if HUDSON_SATA_IDE2AHCI + default "0x5" if HUDSON_SATA_AHCI7804 + default "0x6" if HUDSON_SATA_IDE2AHCI7804 + +if HUDSON_SATA_AHCI || HUDSON_SATA_AHCI7804 +config AHCI_ROM_ID + string "AHCI device PCI IDs" + default "1022,7801" if HUDSON_SATA_AHCI + default "1022,7804" if HUDSON_SATA_AHCI7804 + +config HUDSON_AHCI_ROM + bool "Add a AHCI ROM" + +config AHCI_ROM_FILE + string "AHCI ROM path and filename" + depends on HUDSON_AHCI_ROM + default "src/southbridge/amd/agesa/hudson/ahci.bin" +endif + +if HUDSON_SATA_RAID +config RAID_ROM_ID + string "RAID device PCI IDs" + default "1022,7802" + help + 1022,7802 for SATA NON-RAID5 module, 1022,7803 for SATA RAID5 mode + +config RAID_ROM_FILE + string "RAID ROM path and filename" + depends on HUDSON_SATA_RAID + default "src/southbridge/amd/agesa/hudson/raid.bin" + +config RAID_MISC_ROM_FILE + string "RAID Misc ROM path and filename" + default "src/southbridge/amd/agesa/hudson/misc.bin" + depends on HUDSON_SATA_RAID + +config RAID_MISC_ROM_POSITION + hex "RAID Misc ROM Position" + default 0xFFF00000 + depends on HUDSON_SATA_RAID + help + The RAID ROM requires that the MISC ROM is located between the range + 0xFFF0_0000 to 0xFFF0_FFFF. Also, it must 1K bytes aligned. + The CONFIG_ROM_SIZE must larger than 0x100000. +endif + +endif diff --git a/src/southbridge/amd/agesa/hudson/Makefile.inc b/src/southbridge/amd/agesa/hudson/Makefile.inc new file mode 100644 index 0000000000..19ffae18fd --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/Makefile.inc @@ -0,0 +1,34 @@ +driver-y += hudson.c +driver-y += usb.c +driver-y += lpc.c +driver-y += sm.c +driver-y += ide.c +driver-y += sata.c +driver-y += hda.c +driver-y += pci.c +driver-y += pcie.c +ramstage-$(CONFIG_GENERATE_ACPI_TABLES) += fadt.c +ramstage-y += reset.c +romstage-y += enable_usbdebug.c +romstage-y += early_setup.c + +ramstage-$(CONFIG_HAVE_ACPI_RESUME) += spi.c + +$(obj)/hudson.bin: + python $(src)/southbridge/amd/agesa/hudson/hudson_fwm.py $(CONFIG_HUDSON_FWM_POSITION) $@ $(CONFIG_HUDSON_XHCI_FWM_FILE) $(CONFIG_HUDSON_IMC_FWM_FILE) "" + +ifeq ($(CONFIG_HUDSON_FWM), y) +cbfs-files-y += hudson/fwm +hudson/fwm-file := $(obj)/hudson.bin +hudson/fwm-position := $(CONFIG_HUDSON_FWM_POSITION) +hudson/fwm-type := raw +endif + +#ifeq ($(CONFIG_HUDSON_SATA_AHCI), y) +ifdef CONFIG_HUDSON_AHCI_ROM +stripped_ahci_rom_id = $(call strip_quotes,$(CONFIG_AHCI_ROM_ID)) +cbfs-files-y += pci$(stripped_ahci_rom_id).rom +pci$(stripped_ahci_rom_id).rom-file := $(call strip_quotes,$(CONFIG_AHCI_ROM_FILE)) +pci$(stripped_ahci_rom_id).rom-type := optionrom +#endif +endif diff --git a/src/southbridge/amd/agesa/hudson/bootblock.c b/src/southbridge/amd/agesa/hudson/bootblock.c new file mode 100644 index 0000000000..1d0be0ae70 --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/bootblock.c @@ -0,0 +1,68 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, 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 <stdint.h> +#include <arch/io.h> +#include <arch/romcc_io.h> +#include <device/pci_ids.h> + +/* + * Enable 4MB (LPC) ROM access at 0xFFC00000 - 0xFFFFFFFF. + * + * Hardware should enable LPC ROM by pin straps. This function does not + * handle the theoretically possible PCI ROM, FWH, or SPI ROM configurations. + * + * The HUDSON power-on default is to map 512K ROM space. + * + */ +static void hudson_enable_rom(void) +{ + u8 reg8; + device_t dev; + + dev = PCI_DEV(0, 0x14, 3); + + /* Decode variable LPC ROM address ranges 1 and 2. */ + reg8 = pci_read_config8(dev, 0x48); + reg8 |= (1 << 3) | (1 << 4); + pci_write_config8(dev, 0x48, reg8); + + /* LPC ROM address range 1: */ + /* Enable LPC ROM range mirroring start at 0x000e(0000). */ + pci_write_config16(dev, 0x68, 0x000e); + /* Enable LPC ROM range mirroring end at 0x000f(ffff). */ + pci_write_config16(dev, 0x6a, 0x000f); + + /* LPC ROM address range 2: */ + /* + * Enable LPC ROM range start at: + * 0xfff8(0000): 512KB + * 0xfff0(0000): 1MB + * 0xffe0(0000): 2MB + * 0xffc0(0000): 4MB + */ + pci_write_config16(dev, 0x6c, 0x10000 - (CONFIG_COREBOOT_ROMSIZE_KB >> 6)); + /* Enable LPC ROM range end at 0xffff(ffff). */ + pci_write_config16(dev, 0x6e, 0xffff); +} + +static void bootblock_southbridge_init(void) +{ + hudson_enable_rom(); +} diff --git a/src/southbridge/amd/agesa/hudson/chip.h b/src/southbridge/amd/agesa/hudson/chip.h new file mode 100644 index 0000000000..7732f6d2fe --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/chip.h @@ -0,0 +1,36 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, 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 HUDSON_CHIP_H +#define HUDSON_CHIP_H + +struct southbridge_amd_agesa_hudson_config +{ + #if 1 + u32 ide0_enable : 1; + u32 sata0_enable : 1; + u32 boot_switch_sata_ide : 1; + u32 hda_viddid; + u8 gpp_configuration; + #endif +}; +struct chip_operations; +extern struct chip_operations southbridge_amd_agesa_hudson_ops; + +#endif /* HUDSON_CHIP_H */ diff --git a/src/southbridge/amd/agesa/hudson/early_setup.c b/src/southbridge/amd/agesa/hudson/early_setup.c new file mode 100644 index 0000000000..8cf380bdf6 --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/early_setup.c @@ -0,0 +1,112 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, 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 _HUDSON_EARLY_SETUP_C_ +#define _HUDSON_EARLY_SETUP_C_ + +#include <stdint.h> +#include <arch/io.h> /* inl, outl */ +#include <arch/romcc_io.h> /* device_t */ +#include <arch/acpi.h> +#include <console/console.h> +#include <reset.h> +#include <arch/cpu.h> +#include <cbmem.h> +#include "hudson.h" + +void hudson_lpc_port80(void) +{ + u8 byte; + device_t dev; + + /* Enable LPC controller */ + outb(0xEC, 0xCD6); + byte = inb(0xCD7); + byte |= 1; + outb(0xEC, 0xCD6); + outb(byte, 0xCD7); + + /* Enable port 80 LPC decode in pci function 3 configuration space. */ + dev = PCI_DEV(0, 0x14, 3);//pci_locate_device(PCI_ID(0x1002, 0x439D), 0); + byte = pci_read_config8(dev, 0x4a); + byte |= 1 << 5; /* enable port 80 */ + pci_write_config8(dev, 0x4a, byte); +} + +int s3_save_nvram_early(u32 dword, int size, int nvram_pos) +{ + int i; + printk(BIOS_DEBUG, "Writing %x of size %d to nvram pos: %d\n", dword, size, nvram_pos); + + for (i = 0; i<size; i++) { + outb(nvram_pos, BIOSRAM_INDEX); + outb((dword >>(8 * i)) & 0xff , BIOSRAM_DATA); + nvram_pos++; + } + + return nvram_pos; +} + +int s3_load_nvram_early(int size, u32 *old_dword, int nvram_pos) +{ + u32 data = *old_dword; + int i; + for (i = 0; i<size; i++) { + outb(nvram_pos, BIOSRAM_INDEX); + data &= ~(0xff << (i * 8)); + data |= inb(BIOSRAM_DATA) << (i *8); + nvram_pos++; + } + *old_dword = data; + printk(BIOS_DEBUG, "Loading %x of size %d to nvram pos:%d\n", *old_dword, size, + nvram_pos-size); + return nvram_pos; +} + +#if CONFIG_HAVE_ACPI_RESUME == 1 +int acpi_get_sleep_type(void) +{ + u16 tmp = inw(PM1_CNT_BLK_ADDRESS); + tmp = ((tmp & (7 << 10)) >> 10); + /* printk(BIOS_DEBUG, "SLP_TYP type was %x\n", tmp); */ + return (int)tmp; +} +#endif + +#if CONFIG_HAVE_ACPI_RESUME == 1 +int acpi_is_wakeup_early(void) +{ + return (acpi_get_sleep_type() == 3); +} +#endif + +struct cbmem_entry *get_cbmem_toc(void) +{ + uint32_t xdata = 0; + int xnvram_pos = 0xf8, xi; + for (xi = 0; xi<4; xi++) { + outb(xnvram_pos, BIOSRAM_INDEX); + xdata &= ~(0xff << (xi * 8)); + xdata |= inb(BIOSRAM_DATA) << (xi *8); + xnvram_pos++; + } + return (struct cbmem_entry *) xdata; +} + +#endif diff --git a/src/southbridge/amd/agesa/hudson/enable_usbdebug.c b/src/southbridge/amd/agesa/hudson/enable_usbdebug.c new file mode 100644 index 0000000000..c558a2698a --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/enable_usbdebug.c @@ -0,0 +1,52 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, 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 <stdint.h> +#include <arch/io.h> +#include <arch/romcc_io.h> +#include <usbdebug.h> +#include <device/pci_def.h> +#include "hudson.h" + +#ifndef HUDSON_DEVN_BASE +#define HUDSON_DEVN_BASE 0 +#endif + +#define EHCI_EOR (CONFIG_EHCI_BAR + 0x20) +#define DEBUGPORT_MISC_CONTROL (EHCI_EOR + 0x80) + +void set_debug_port(unsigned int port) +{ + u32 reg32; + + /* Write the port number to DEBUGPORT_MISC_CONTROL[31:28]. */ + reg32 = read32(DEBUGPORT_MISC_CONTROL); + reg32 &= ~(0xf << 28); + reg32 |= (port << 28); + reg32 |= (1 << 27); /* Enable Debug Port port number remapping. */ + write32(DEBUGPORT_MISC_CONTROL, reg32); +} + + +void enable_usbdebug(unsigned int port) +{ + pci_write_config32(PCI_DEV(0, HUDSON_DEVN_BASE + 0x13, 5), + EHCI_BAR_INDEX, CONFIG_EHCI_BAR); + pci_write_config8(PCI_DEV(0, HUDSON_DEVN_BASE + 0x13, 5), 0x04, 0x2); /* mem space enabe */ + set_debug_port(port); +} diff --git a/src/southbridge/amd/agesa/hudson/fadt.c b/src/southbridge/amd/agesa/hudson/fadt.c new file mode 100644 index 0000000000..ee0334cc5a --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/fadt.c @@ -0,0 +1,186 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Advanced Micro Devices, 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 + */ + +/* + * ACPI - create the Fixed ACPI Description Tables (FADT) + */ + +#include <string.h> +#include <console/console.h> +#include <arch/acpi.h> +#include <arch/io.h> +#include <device/device.h> +#include "hudson.h" + +void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) +{ + acpi_header_t *header = &(fadt->header); + + printk(BIOS_DEBUG, "pm_base: 0x%04x\n", HUDSON_ACPI_IO_BASE); + + /* Prepare the header */ + memset((void *)fadt, 0, sizeof(acpi_fadt_t)); + memcpy(header->signature, "FACP", 4); + header->length = 244; + header->revision = 3; + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, "COREBOOT", 8); + memcpy(header->asl_compiler_id, ASLC, 4); + header->asl_compiler_revision = 0; + + fadt->firmware_ctrl = (u32) facs; + fadt->dsdt = (u32) dsdt; + /* 3=Workstation,4=Enterprise Server, 7=Performance Server */ + fadt->preferred_pm_profile = 0x03; + fadt->sci_int = 9; + /* disable system management mode by setting to 0: */ + fadt->smi_cmd = 0; + fadt->acpi_enable = 0xf0; + fadt->acpi_disable = 0xf1; + fadt->s4bios_req = 0x0; + fadt->pstate_cnt = 0xe2; + + pm_iowrite(0x60, ACPI_PM_EVT_BLK & 0xFF); + pm_iowrite(0x61, ACPI_PM_EVT_BLK >> 8); + pm_iowrite(0x62, ACPI_PM1_CNT_BLK & 0xFF); + pm_iowrite(0x63, ACPI_PM1_CNT_BLK >> 8); + pm_iowrite(0x64, ACPI_PM_TMR_BLK & 0xFF); + pm_iowrite(0x65, ACPI_PM_TMR_BLK >> 8); + pm_iowrite(0x68, ACPI_GPE0_BLK & 0xFF); + pm_iowrite(0x69, ACPI_GPE0_BLK >> 8); + + /* CpuControl is in \_PR.CPU0, 6 bytes */ + pm_iowrite(0x66, ACPI_CPU_CONTROL & 0xFF); + pm_iowrite(0x67, ACPI_CPU_CONTROL >> 8); + + pm_iowrite(0x6A, 0); /* AcpiSmiCmdLo */ + pm_iowrite(0x6B, 0); /* AcpiSmiCmdHi */ + + pm_iowrite(0x6C, ACPI_PMA_CNT_BLK & 0xFF); + pm_iowrite(0x6D, ACPI_PMA_CNT_BLK >> 8); + + pm_iowrite(0x74, 1<<0 | 1<<1 | 1<<4 | 1<<2); /* AcpiDecodeEnable, When set, SB uses + * the contents of the PM registers at + * index 60-6B to decode ACPI I/O address. + * AcpiSmiEn & SmiCmdEn*/ + /* RTC_En_En, TMR_En_En, GBL_EN_EN */ + outl(0x1, ACPI_PM1_CNT_BLK); /* set SCI_EN */ + fadt->pm1a_evt_blk = ACPI_PM_EVT_BLK; + fadt->pm1b_evt_blk = 0x0000; + fadt->pm1a_cnt_blk = ACPI_PM1_CNT_BLK; + fadt->pm1b_cnt_blk = 0x0000; + fadt->pm2_cnt_blk = ACPI_PMA_CNT_BLK; + fadt->pm_tmr_blk = ACPI_PM_TMR_BLK; + fadt->gpe0_blk = ACPI_GPE0_BLK; + fadt->gpe1_blk = 0x0000; /* we dont have gpe1 block, do we? */ + + fadt->pm1_evt_len = 4; + fadt->pm1_cnt_len = 2; + fadt->pm2_cnt_len = 1; + fadt->pm_tmr_len = 4; + fadt->gpe0_blk_len = 8; + fadt->gpe1_blk_len = 0; + fadt->gpe1_base = 0; + + fadt->cst_cnt = 0xe3; + fadt->p_lvl2_lat = 101; + fadt->p_lvl3_lat = 1001; + fadt->flush_size = 0; + fadt->flush_stride = 0; + fadt->duty_offset = 1; + fadt->duty_width = 3; + fadt->day_alrm = 0; /* 0x7d these have to be */ + fadt->mon_alrm = 0; /* 0x7e added to cmos.layout */ + fadt->century = 0; /* 0x7f to make rtc alrm work */ + fadt->iapc_boot_arch = 0x3; /* See table 5-11 */ + fadt->flags = 0x0001c1a5 | 1 << 10;/* 0x25; */ + + fadt->res2 = 0; + + fadt->reset_reg.space_id = 1; + fadt->reset_reg.bit_width = 8; + fadt->reset_reg.bit_offset = 0; + fadt->reset_reg.resv = 0; + fadt->reset_reg.addrl = 0xcf9; + fadt->reset_reg.addrh = 0x0; + + fadt->reset_value = 6; + fadt->x_firmware_ctl_l = (u32) facs; + fadt->x_firmware_ctl_h = 0; + fadt->x_dsdt_l = (u32) dsdt; + fadt->x_dsdt_h = 0; + + fadt->x_pm1a_evt_blk.space_id = 1; + fadt->x_pm1a_evt_blk.bit_width = 32; + fadt->x_pm1a_evt_blk.bit_offset = 0; + fadt->x_pm1a_evt_blk.resv = 0; + fadt->x_pm1a_evt_blk.addrl = ACPI_PM_EVT_BLK; + fadt->x_pm1a_evt_blk.addrh = 0x0; + + fadt->x_pm1b_evt_blk.space_id = 1; + fadt->x_pm1b_evt_blk.bit_width = 4; + fadt->x_pm1b_evt_blk.bit_offset = 0; + fadt->x_pm1b_evt_blk.resv = 0; + fadt->x_pm1b_evt_blk.addrl = 0x0; + fadt->x_pm1b_evt_blk.addrh = 0x0; + + fadt->x_pm1a_cnt_blk.space_id = 1; + fadt->x_pm1a_cnt_blk.bit_width = 16; + fadt->x_pm1a_cnt_blk.bit_offset = 0; + fadt->x_pm1a_cnt_blk.resv = 0; + fadt->x_pm1a_cnt_blk.addrl = ACPI_PM1_CNT_BLK; + fadt->x_pm1a_cnt_blk.addrh = 0x0; + + fadt->x_pm1b_cnt_blk.space_id = 1; + fadt->x_pm1b_cnt_blk.bit_width = 2; + fadt->x_pm1b_cnt_blk.bit_offset = 0; + fadt->x_pm1b_cnt_blk.resv = 0; + fadt->x_pm1b_cnt_blk.addrl = 0x0; + fadt->x_pm1b_cnt_blk.addrh = 0x0; + + fadt->x_pm2_cnt_blk.space_id = 1; + fadt->x_pm2_cnt_blk.bit_width = 0; + fadt->x_pm2_cnt_blk.bit_offset = 0; + fadt->x_pm2_cnt_blk.resv = 0; + fadt->x_pm2_cnt_blk.addrl = ACPI_PMA_CNT_BLK; + fadt->x_pm2_cnt_blk.addrh = 0x0; + + fadt->x_pm_tmr_blk.space_id = 1; + fadt->x_pm_tmr_blk.bit_width = 32; + fadt->x_pm_tmr_blk.bit_offset = 0; + fadt->x_pm_tmr_blk.resv = 0; + fadt->x_pm_tmr_blk.addrl = ACPI_PM_TMR_BLK; + fadt->x_pm_tmr_blk.addrh = 0x0; + + fadt->x_gpe0_blk.space_id = 1; + fadt->x_gpe0_blk.bit_width = 32; + fadt->x_gpe0_blk.bit_offset = 0; + fadt->x_gpe0_blk.resv = 0; + fadt->x_gpe0_blk.addrl = ACPI_GPE0_BLK; + fadt->x_gpe0_blk.addrh = 0x0; + + fadt->x_gpe1_blk.space_id = 1; + fadt->x_gpe1_blk.bit_width = 0; + fadt->x_gpe1_blk.bit_offset = 0; + fadt->x_gpe1_blk.resv = 0; + fadt->x_gpe1_blk.addrl = 0; + fadt->x_gpe1_blk.addrh = 0x0; + + header->checksum = acpi_checksum((void *)fadt, sizeof(acpi_fadt_t)); +} diff --git a/src/southbridge/amd/agesa/hudson/hda.c b/src/southbridge/amd/agesa/hudson/hda.c new file mode 100644 index 0000000000..fcd9f7f0ec --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/hda.c @@ -0,0 +1,51 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, 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_ids.h> +#include <device/pci_ops.h> +#include <arch/io.h> +#include <delay.h> +#include "hudson.h" + + +static void hda_init(struct device *dev) +{ +} + +static struct pci_operations lops_pci = { + .set_subsystem = pci_dev_set_subsystem, +}; + +static struct device_operations hda_audio_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = hda_init, + .scan_bus = 0, + .ops_pci = &lops_pci, +}; + +static const struct pci_driver hdaaudio_driver __pci_driver = { + .ops = &hda_audio_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_ATI_SB900_HDA, +}; diff --git a/src/southbridge/amd/agesa/hudson/hudson.c b/src/southbridge/amd/agesa/hudson/hudson.c new file mode 100644 index 0000000000..ce450429fa --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/hudson.c @@ -0,0 +1,122 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, 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 <arch/io.h> +#include <arch/acpi.h> + +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include <cbmem.h> +#include "hudson.h" +#include "smbus.h" + +#if CONFIG_HAVE_ACPI_RESUME == 1 +int acpi_get_sleep_type(void) +{ + u16 tmp = inw(PM1_CNT_BLK_ADDRESS); + tmp = ((tmp & (7 << 10)) >> 10); + /* printk(BIOS_DEBUG, "SLP_TYP type was %x\n", tmp); */ + return (int)tmp; +} +#endif + +void set_cbmem_toc(struct cbmem_entry *toc) +{ + u32 dword = (u32) toc; + int nvram_pos = 0xf8, i; /* temp */ + /* printk(BIOS_DEBUG, "dword=%x\n", dword); */ + for (i = 0; i<4; i++) { + /* printk(BIOS_DEBUG, "nvram_pos=%x, dword>>(8*i)=%x\n", nvram_pos, (dword >>(8 * i)) & 0xff); */ + outb(nvram_pos, BIOSRAM_INDEX); + outb((dword >>(8 * i)) & 0xff , BIOSRAM_DATA); + nvram_pos++; + } +} + +void set_sm_enable_bits(device_t sm_dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + reg = reg_old = pci_read_config32(sm_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + pci_write_config32(sm_dev, reg_pos, reg); + } +} + +static void pmio_write_index(u16 port_base, u8 reg, u8 value) +{ + outb(reg, port_base); + outb(value, port_base + 1); +} + +static u8 pmio_read_index(u16 port_base, u8 reg) +{ + outb(reg, port_base); + return inb(port_base + 1); +} + +void pm_iowrite(u8 reg, u8 value) +{ + pmio_write_index(PM_INDEX, reg, value); +} + +u8 pm_ioread(u8 reg) +{ + return pmio_read_index(PM_INDEX, reg); +} + +void pm2_iowrite(u8 reg, u8 value) +{ + pmio_write_index(PM2_INDEX, reg, value); +} + +u8 pm2_ioread(u8 reg) +{ + return pmio_read_index(PM2_INDEX, reg); +} + + +void hudson_enable(device_t dev) +{ + printk(BIOS_DEBUG, "sb800_enable()\n"); +} + +struct cbmem_entry *get_cbmem_toc(void) +{ + uint32_t xdata = 0; + int xnvram_pos = 0xf8, xi; + for (xi = 0; xi<4; xi++) { + outb(xnvram_pos, BIOSRAM_INDEX); + xdata &= ~(0xff << (xi * 8)); + xdata |= inb(BIOSRAM_DATA) << (xi *8); + xnvram_pos++; + } + return (struct cbmem_entry *) xdata; +} + + +struct chip_operations southbridge_amd_agesa_hudson_ops = { + CHIP_NAME("ATI HUDSON") + .enable_dev = hudson_enable, +}; diff --git a/src/southbridge/amd/agesa/hudson/hudson.h b/src/southbridge/amd/agesa/hudson/hudson.h new file mode 100644 index 0000000000..28faea49fb --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/hudson.h @@ -0,0 +1,75 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, 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 HUDSON_H +#define HUDSON_H + +#include <device/pci_ids.h> +#include "chip.h" + +/* Power management index/data registers */ +#define BIOSRAM_INDEX 0xcd4 +#define BIOSRAM_DATA 0xcd5 +#define PM_INDEX 0xcd6 +#define PM_DATA 0xcd7 +#define PM2_INDEX 0xcd0 +#define PM2_DATA 0xcd1 + +#define HUDSON_ACPI_IO_BASE 0x800 + +#define ACPI_PM_EVT_BLK (HUDSON_ACPI_IO_BASE + 0x00) /* 4 bytes */ +#define ACPI_PM1_CNT_BLK (HUDSON_ACPI_IO_BASE + 0x04) /* 2 bytes */ +#define ACPI_PMA_CNT_BLK (HUDSON_ACPI_IO_BASE + 0x0F) /* 1 byte, TODO: Is it 0xFE00? */ +#define ACPI_PM_TMR_BLK (HUDSON_ACPI_IO_BASE + 0x18) /* 4 bytes */ +#define ACPI_GPE0_BLK (HUDSON_ACPI_IO_BASE + 0x10) /* 8 bytes */ +#define ACPI_CPU_CONTROL (HUDSON_ACPI_IO_BASE + 0x08) /* 6 bytes */ + +void pm_iowrite(u8 reg, u8 value); +u8 pm_ioread(u8 reg); +void pm2_iowrite(u8 reg, u8 value); +u8 pm2_ioread(u8 reg); +void set_sm_enable_bits(device_t sm_dev, u32 reg_pos, u32 mask, u32 val); + +#define REV_HUDSON_A11 0x11 +#define REV_HUDSON_A12 0x12 + +#define PM1_EVT_BLK_ADDRESS 0x800 // AcpiPm1EvtBlkAddr; +#define PM1_CNT_BLK_ADDRESS 0x804 // AcpiPm1CntBlkAddr; +#define PM1_TMR_BLK_ADDRESS 0x808 // AcpiPmTmrBlkAddr; +#define CPU_CNT_BLK_ADDRESS 0x810 // CpuControlBlkAddr; +#define GPE0_BLK_ADDRESS 0x820 // AcpiGpe0BlkAddr; +#define SMI_CMD_PORT 0xB0 // SmiCmdPortAddr; +#define ACPI_PMA_CNT_BLK_ADDRESS 0xFE00 // AcpiPmaCntBlkAddr; + +#ifdef __PRE_RAM__ +void hudson_lpc_port80(void); +void hudson_pci_port80(void); +void hudson_clk_output_48Mhz(void); + +int s3_save_nvram_early(u32 dword, int size, int nvram_pos); +int s3_load_nvram_early(int size, u32 *old_dword, int nvram_pos); + +int acpi_is_wakeup_early(void); + +#else +void hudson_enable(device_t dev); +void __attribute__((weak)) hudson_setup_sata_phys(struct device *dev); +#endif + +#endif /* HUDSON_H */ diff --git a/src/southbridge/amd/agesa/hudson/hudson_fwm.py b/src/southbridge/amd/agesa/hudson/hudson_fwm.py new file mode 100644 index 0000000000..ad60b3b4e4 --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/hudson_fwm.py @@ -0,0 +1,64 @@ +import sys, os, re +import struct +from Queue import Queue + +def main(start_addr, file_name, xhci_name, imc_name, gec_name): + fwm_sig = 0x55AA55AA # Hudson-2/3/4 firmware signature + fwm_header_len = 0x10 # 55AA55AA, imc_off, gec_off, xhci_off + + if not os.path.exists(xhci_name): + print "XHCI firmware %s does not exist\n" % xhci_name + sys.exit(1) + if not os.path.exists(imc_name): + print "IMC firmware %s does not exist\n" % imc_name + sys.exit(1) + + f = open(file_name, "w") + print "write to file " + file_name + + imc_offset = 0x10000 # 64K Bytes offset, hardcoded + imc_addr = start_addr + imc_offset; #startaddr + 0x10000 + gec_offset = 0 #TODO + gec_addr = 0 #TODO + xhci_addr = start_addr + fwm_header_len #ROMSIG take 0x10 bytes + + format="I" # one unsigned integer + data=struct.pack(format, fwm_sig) + f.write(data) + data=struct.pack(format, imc_addr) + f.write(data) + data=struct.pack(format, gec_addr) + f.write(data) + data=struct.pack(format, xhci_addr) + f.write(data) + + fwm_content = open(xhci_name).read() + f.write(fwm_content) + + imc_content = open(imc_name).read() + f.seek(0) + f.seek(imc_offset) + f.write(imc_content) +# if os.path.exists(gec_name): +# gec_conent = open(gec_name).read() +# f.seek(0) +# f.seek(gec_offset) +# f.write(gec_content) + + f.close() + print "done\n" + + +if __name__ == '__main__': + if (len(sys.argv) < 6): + print "\nUsage: %s <rom_addr> <rom_file> <xhci_rom> <imc_rom> <gec_rom>\n" % sys.argv[0] + print "Example: %s 0xFFF20000 hudson.bin xhci.bin imc.bin gec.bin\n" % sys.argv[0] + sys.exit(1) + rom_addr = int(sys.argv[1], 16) + rom_file = sys.argv[2] + xhci_file = sys.argv[3] + imc_file = sys.argv[4] + gec_file = sys.argv[5] + print "%x %s %s %s %s" % (rom_addr, rom_file, xhci_file, imc_file, gec_file) + + main(rom_addr, rom_file, xhci_file, imc_file, gec_file) diff --git a/src/southbridge/amd/agesa/hudson/ide.c b/src/southbridge/amd/agesa/hudson/ide.c new file mode 100644 index 0000000000..44dcfe05ac --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/ide.c @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, 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_ids.h> +#include <device/pci_ops.h> +#include "hudson.h" + +static void ide_init(struct device *dev) +{ +} + +static struct pci_operations lops_pci = { + .set_subsystem = pci_dev_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, + .ops_pci = &lops_pci, +}; + +static const struct pci_driver ide_driver __pci_driver = { + .ops = &ide_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_ATI_SB900_IDE, +}; diff --git a/src/southbridge/amd/agesa/hudson/lpc.c b/src/southbridge/amd/agesa/hudson/lpc.c new file mode 100644 index 0000000000..4dd6083b1e --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/lpc.c @@ -0,0 +1,148 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, 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/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 "hudson.h" + +static void lpc_init(device_t dev) +{ + u8 byte; + u32 dword; + device_t sm_dev; + + /* Enable the LPC Controller */ + sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0)); + dword = pci_read_config32(sm_dev, 0x64); + dword |= 1 << 20; + pci_write_config32(sm_dev, 0x64, dword); + + /* Initialize isa dma */ + isa_dma_init(); + + /* Enable DMA transaction on the LPC bus */ + byte = pci_read_config8(dev, 0x40); + byte |= (1 << 2); + pci_write_config8(dev, 0x40, byte); + + /* Disable the timeout mechanism on LPC */ + byte = pci_read_config8(dev, 0x48); + byte &= ~(1 << 7); + pci_write_config8(dev, 0x48, byte); + + /* Disable LPC MSI Capability */ + byte = pci_read_config8(dev, 0x78); + byte &= ~(1 << 1); + byte &= ~(1 << 0); /* Keep the old way. i.e., when bus master/DMA cycle is going + on on LPC, it holds PCI grant, so no LPC slave cycle can + interrupt and visit LPC. */ + pci_write_config8(dev, 0x78, byte); + + /* bit0: Enable prefetch a cacheline (64 bytes) when Host reads code from SPI rom */ + /* bit3: Fix SPI_CS# timing issue when running at 66M. TODO:A12. */ + byte = pci_read_config8(dev, 0xBB); + byte |= 1 << 0 | 1 << 3; + pci_write_config8(dev, 0xBB, byte); +} + +static void hudson_lpc_read_resources(device_t dev) +{ + struct resource *res; + + /* Get the normal pci resources of this device */ + pci_dev_read_resources(dev); /* We got one for APIC, or one more for TRAP */ + + pci_get_resource(dev, 0xA0); /* SPI ROM base address */ + + /* Add an extra subtractive resource for both memory and I/O. */ + res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0)); + res->base = 0; + res->size = 0x1000; + res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | + IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + + res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0)); + res->base = 0xff800000; + res->size = 0x00800000; /* 8 MB for flash */ + res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | + IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + + //res = new_resource(dev, 3); /* IOAPIC */ + //res->base = 0xfec00000; + //res->size = 0x00001000; + //res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + + compact_resources(dev); +} + +static void hudson_lpc_set_resources(struct device *dev) +{ + struct resource *res; + + pci_dev_set_resources(dev); + + /* Specical case. SPI Base Address. The SpiRomEnable should be set. */ + res = find_resource(dev, 0xA0); + pci_write_config32(dev, 0xA0, res->base | 1 << 1); + +} + +/** + * @brief Enable resources for children devices + * + * @param dev the device whos children's resources are to be enabled + * + */ +static void hudson_lpc_enable_childrens_resources(device_t dev) +{ + printk(BIOS_DEBUG, "hudson_lpc_enable_childrens_resources\n"); + +} + +static void hudson_lpc_enable_resources(device_t dev) +{ + pci_dev_enable_resources(dev); + hudson_lpc_enable_childrens_resources(dev); +} + +static struct pci_operations lops_pci = { + .set_subsystem = pci_dev_set_subsystem, +}; + +static struct device_operations lpc_ops = { + .read_resources = hudson_lpc_read_resources, + .set_resources = hudson_lpc_set_resources, + .enable_resources = hudson_lpc_enable_resources, + .init = lpc_init, + .scan_bus = scan_static_bus, + .ops_pci = &lops_pci, +}; +static const struct pci_driver lpc_driver __pci_driver = { + .ops = &lpc_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_ATI_SB900_LPC, +}; diff --git a/src/southbridge/amd/agesa/hudson/pci.c b/src/southbridge/amd/agesa/hudson/pci.c new file mode 100644 index 0000000000..492e195c65 --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/pci.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, 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_ids.h> +#include <device/pci_ops.h> +#include "hudson.h" + +static void pci_init(struct device *dev) +{ +} + +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, + .reset_bus = pci_bus_reset, + .ops_pci = &lops_pci, +}; + +static const struct pci_driver pci_driver __pci_driver = { + .ops = &pci_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_ATI_SB900_PCI, +}; diff --git a/src/southbridge/amd/agesa/hudson/pcie.c b/src/southbridge/amd/agesa/hudson/pcie.c new file mode 100644 index 0000000000..feb99144b5 --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/pcie.c @@ -0,0 +1,65 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, 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_ids.h> +#include <device/pci_ops.h> +#include "hudson.h" + +static void pcie_init(struct device *dev) +{ +} + +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 = pcie_init, + .scan_bus = pci_scan_bridge, + .reset_bus = pci_bus_reset, + .ops_pci = &lops_pci, +}; + +static const struct pci_driver pciea_driver __pci_driver = { + .ops = &pci_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_ATI_SB900_PCIEA, +}; + +static const struct pci_driver pcieb_driver __pci_driver = { + .ops = &pci_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_ATI_SB900_PCIEB, +}; +static const struct pci_driver pciec_driver __pci_driver = { + .ops = &pci_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_ATI_SB900_PCIEC, +}; +static const struct pci_driver pcied_driver __pci_driver = { + .ops = &pci_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_ATI_SB900_PCIED, +}; diff --git a/src/southbridge/amd/agesa/hudson/reset.c b/src/southbridge/amd/agesa/hudson/reset.c new file mode 100644 index 0000000000..32ee66b4b5 --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/reset.c @@ -0,0 +1,33 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, 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 <reset.h> +#include <arch/io.h> +#include <arch/romcc_io.h> + +#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); +} diff --git a/src/southbridge/amd/agesa/hudson/sata.c b/src/southbridge/amd/agesa/hudson/sata.c new file mode 100644 index 0000000000..ce3d96b90d --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/sata.c @@ -0,0 +1,51 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, 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 <delay.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include <arch/io.h> +#include "hudson.h" + + +static void sata_init(struct device *dev) +{ +} + +static struct pci_operations lops_pci = { + /* .set_subsystem = pci_dev_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, + .init = sata_init, + .scan_bus = 0, + .ops_pci = &lops_pci, +}; + +static const struct pci_driver sata0_driver __pci_driver = { + .ops = &sata_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_ATI_SB900_SATA, +}; diff --git a/src/southbridge/amd/agesa/hudson/sm.c b/src/southbridge/amd/agesa/hudson/sm.c new file mode 100644 index 0000000000..36742aa31c --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/sm.c @@ -0,0 +1,174 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, 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_ids.h> +#include <device/pci_ops.h> +#include <device/smbus.h> +#include <pc80/mc146818rtc.h> +#include <bitops.h> +#include <arch/io.h> +#include <cpu/x86/lapic.h> +#include <arch/ioapic.h> +#include <stdlib.h> +#include "hudson.h" +#include "smbus.c" + +#define NMI_OFF 0 + +#define MAINBOARD_POWER_OFF 0 +#define MAINBOARD_POWER_ON 1 + +#ifndef CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL +#define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON +#endif + +#define BIT0 (1 << 0) +#define BIT1 (1 << 1) +#define BIT2 (1 << 2) +#define BIT3 (1 << 3) +#define BIT4 (1 << 4) +#define BIT5 (1 << 5) +#define BIT6 (1 << 6) +#define BIT7 (1 << 7) + +#define BIT8 (1 << 8 ) +#define BIT9 (1 << 9 ) +#define BIT10 (1 << 10) +#define BIT11 (1 << 11) +#define BIT12 (1 << 12) +#define BIT13 (1 << 13) +#define BIT14 (1 << 14) +#define BIT15 (1 << 15) + +#define BIT16 (1 << 16) +#define BIT17 (1 << 17) +#define BIT18 (1 << 18) +#define BIT19 (1 << 19) +#define BIT20 (1 << 20) +#define BIT21 (1 << 21) +#define BIT22 (1 << 22) +#define BIT23 (1 << 23) +#define BIT24 (1 << 24) +#define BIT25 (1 << 25) +#define BIT26 (1 << 26) +#define BIT27 (1 << 27) +#define BIT28 (1 << 28) +#define BIT29 (1 << 29) +#define BIT30 (1 << 30) +#define BIT31 (1 << 31) + +/* +* HUDSON enables all USB controllers by default in SMBUS Control. +* HUDSON enables SATA by default in SMBUS Control. +*/ + +static void sm_init(device_t dev) +{ +} + +static int lsmbus_recv_byte(device_t dev) +{ + u32 device; + struct resource *res; + struct bus *pbus; + + device = dev->path.i2c.device; + pbus = get_pbus_smbus(dev); + + res = find_resource(pbus->dev, 0x90); + + return do_smbus_recv_byte(res->base, device); +} + +static int lsmbus_send_byte(device_t dev, u8 val) +{ + u32 device; + struct resource *res; + struct bus *pbus; + + device = dev->path.i2c.device; + pbus = get_pbus_smbus(dev); + + res = find_resource(pbus->dev, 0x90); + + return do_smbus_send_byte(res->base, device, val); +} + +static int lsmbus_read_byte(device_t dev, u8 address) +{ + u32 device; + struct resource *res; + struct bus *pbus; + + device = dev->path.i2c.device; + pbus = get_pbus_smbus(dev); + + res = find_resource(pbus->dev, 0x90); + + return do_smbus_read_byte(res->base, device, address); +} + +static int lsmbus_write_byte(device_t dev, u8 address, u8 val) +{ + u32 device; + struct resource *res; + struct bus *pbus; + + device = dev->path.i2c.device; + pbus = get_pbus_smbus(dev); + + res = find_resource(pbus->dev, 0x90); + + 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, +}; + +static void hudson_sm_read_resources(device_t dev) +{ +} + +static void hudson_sm_set_resources(struct device *dev) +{ +} + +static struct pci_operations lops_pci = { + .set_subsystem = pci_dev_set_subsystem, +}; +static struct device_operations smbus_ops = { + .read_resources = hudson_sm_read_resources, + .set_resources = hudson_sm_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = sm_init, + .scan_bus = scan_static_bus, + .ops_pci = &lops_pci, + .ops_smbus_bus = &lops_smbus_bus, +}; +static const struct pci_driver smbus_driver __pci_driver = { + .ops = &smbus_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_ATI_SB900_SM, +}; diff --git a/src/southbridge/amd/agesa/hudson/smbus.c b/src/southbridge/amd/agesa/hudson/smbus.c new file mode 100644 index 0000000000..9db936c31f --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/smbus.c @@ -0,0 +1,253 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, 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 _SB800_SMBUS_C_ +#define _SB800_SMBUS_C_ + +#include "smbus.h" + +static inline void smbus_delay(void) +{ + outb(inb(0x80), 0x80); +} + +static int smbus_wait_until_ready(u32 smbus_io_base) +{ + u32 loops; + loops = SMBUS_TIMEOUT; + do { + u8 val; + val = inb(smbus_io_base + SMBHSTSTAT); + val &= 0x1f; + if (val == 0) { /* ready now */ + return 0; + } + outb(val, smbus_io_base + SMBHSTSTAT); + } while (--loops); + return -2; /* time out */ +} + +static int smbus_wait_until_done(u32 smbus_io_base) +{ + u32 loops; + loops = SMBUS_TIMEOUT; + do { + u8 val; + + val = inb(smbus_io_base + SMBHSTSTAT); + val &= 0x1f; /* mask off reserved bits */ + if (val & 0x1c) { + return -5; /* error */ + } + if (val == 0x02) { + outb(val, smbus_io_base + SMBHSTSTAT); /* clear status */ + return 0; + } + } while (--loops); + return -3; /* timeout */ +} + +int do_smbus_recv_byte(u32 smbus_io_base, u32 device) +{ + u8 byte; + + if (smbus_wait_until_ready(smbus_io_base) < 0) { + return -2; /* not ready */ + } + + /* set the device I'm talking too */ + outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR); + + byte = inb(smbus_io_base + SMBHSTCTRL); + byte &= 0xe3; /* Clear [4:2] */ + byte |= (1 << 2) | (1 << 6); /* Byte data read/write command, start the command */ + outb(byte, smbus_io_base + SMBHSTCTRL); + + /* poll for transaction completion */ + if (smbus_wait_until_done(smbus_io_base) < 0) { + return -3; /* timeout or error */ + } + + /* read results of transaction */ + byte = inb(smbus_io_base + SMBHSTCMD); + + return byte; +} + +int do_smbus_send_byte(u32 smbus_io_base, u32 device, u8 val) +{ + u8 byte; + + if (smbus_wait_until_ready(smbus_io_base) < 0) { + return -2; /* not ready */ + } + + /* set the command... */ + outb(val, smbus_io_base + SMBHSTCMD); + + /* set the device I'm talking too */ + outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR); + + byte = inb(smbus_io_base + SMBHSTCTRL); + byte &= 0xe3; /* Clear [4:2] */ + byte |= (1 << 2) | (1 << 6); /* Byte data read/write command, start the command */ + outb(byte, smbus_io_base + SMBHSTCTRL); + + /* poll for transaction completion */ + if (smbus_wait_until_done(smbus_io_base) < 0) { + return -3; /* timeout or error */ + } + + return 0; +} + +int do_smbus_read_byte(u32 smbus_io_base, u32 device, + u32 address) +{ + u8 byte; + + if (smbus_wait_until_ready(smbus_io_base) < 0) { + return -2; /* not ready */ + } + + /* set the command/address... */ + outb(address & 0xff, smbus_io_base + SMBHSTCMD); + + /* set the device I'm talking too */ + outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR); + + byte = inb(smbus_io_base + SMBHSTCTRL); + byte &= 0xe3; /* Clear [4:2] */ + byte |= (1 << 3) | (1 << 6); /* Byte data read/write command, start the command */ + outb(byte, smbus_io_base + SMBHSTCTRL); + + /* poll for transaction completion */ + if (smbus_wait_until_done(smbus_io_base) < 0) { + return -3; /* timeout or error */ + } + + /* read results of transaction */ + byte = inb(smbus_io_base + SMBHSTDAT0); + + return byte; +} + +int do_smbus_write_byte(u32 smbus_io_base, u32 device, + u32 address, u8 val) +{ + u8 byte; + + if (smbus_wait_until_ready(smbus_io_base) < 0) { + return -2; /* not ready */ + } + + /* set the command/address... */ + outb(address & 0xff, smbus_io_base + SMBHSTCMD); + + /* set the device I'm talking too */ + outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR); + + /* output value */ + outb(val, smbus_io_base + SMBHSTDAT0); + + byte = inb(smbus_io_base + SMBHSTCTRL); + byte &= 0xe3; /* Clear [4:2] */ + byte |= (1 << 3) | (1 << 6); /* Byte data read/write command, start the command */ + outb(byte, smbus_io_base + SMBHSTCTRL); + + /* poll for transaction completion */ + if (smbus_wait_until_done(smbus_io_base) < 0) { + return -3; /* timeout or error */ + } + + return 0; +} + +void alink_ab_indx(u32 reg_space, u32 reg_addr, + u32 mask, u32 val) +{ + u32 tmp; + + outl((reg_space & 0x7) << 29 | reg_addr, AB_INDX); + tmp = inl(AB_DATA); + /* rpr 4.2 + * For certain revisions of the chip, the ABCFG registers, + * with an address of 0x100NN (where 'N' is any hexadecimal + * number), require an extra programming step.*/ + outl(0, AB_INDX); + + tmp &= ~mask; + tmp |= val; + + /* printk(BIOS_DEBUG, "about write %x, index=%x", tmp, (reg_space&0x3)<<29 | reg_addr); */ + outl((reg_space & 0x7) << 29 | reg_addr, AB_INDX); /* probably we dont have to do it again. */ + outl(tmp, AB_DATA); + outl(0, AB_INDX); +} + +void alink_rc_indx(u32 reg_space, u32 reg_addr, u32 port, + u32 mask, u32 val) +{ + u32 tmp; + + outl((reg_space & 0x7) << 29 | (port & 3) << 24 | reg_addr, AB_INDX); + tmp = inl(AB_DATA); + /* rpr 4.2 + * For certain revisions of the chip, the ABCFG registers, + * with an address of 0x100NN (where 'N' is any hexadecimal + * number), require an extra programming step.*/ + outl(0, AB_INDX); + + tmp &= ~mask; + tmp |= val; + + //printk(BIOS_DEBUG, "about write %x, index=%x", tmp, (reg_space&0x3)<<29 | (port&3) << 24 | reg_addr); + outl((reg_space & 0x7) << 29 | (port & 3) << 24 | reg_addr, AB_INDX); /* probably we dont have to do it again. */ + outl(tmp, AB_DATA); + outl(0, AB_INDX); +} + +/* space = 0: AX_INDXC, AX_DATAC + * space = 1: AX_INDXP, AX_DATAP + */ +void alink_ax_indx(u32 space /*c or p? */ , u32 axindc, + u32 mask, u32 val) +{ + u32 tmp; + + /* read axindc to tmp */ + outl(space << 29 | space << 3 | 0x30, AB_INDX); + outl(axindc, AB_DATA); + outl(0, AB_INDX); + outl(space << 29 | space << 3 | 0x34, AB_INDX); + tmp = inl(AB_DATA); + outl(0, AB_INDX); + + tmp &= ~mask; + tmp |= val; + + /* write tmp */ + outl(space << 29 | space << 3 | 0x30, AB_INDX); + outl(axindc, AB_DATA); + outl(0, AB_INDX); + outl(space << 29 | space << 3 | 0x34, AB_INDX); + outl(tmp, AB_DATA); + outl(0, AB_INDX); +} +#endif diff --git a/src/southbridge/amd/agesa/hudson/smbus.h b/src/southbridge/amd/agesa/hudson/smbus.h new file mode 100644 index 0000000000..fce8e96572 --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/smbus.h @@ -0,0 +1,76 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, 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 SB800_SMBUS_H +#define SB800_SMBUS_H + +//#include <stdint.h> + +#define SMBHSTSTAT 0x0 +#define SMBSLVSTAT 0x1 +#define SMBHSTCTRL 0x2 +#define SMBHSTCMD 0x3 +#define SMBHSTADDR 0x4 +#define SMBHSTDAT0 0x5 +#define SMBHSTDAT1 0x6 +#define SMBHSTBLKDAT 0x7 + +#define SMBSLVCTRL 0x8 +#define SMBSLVCMD_SHADOW 0x9 +#define SMBSLVEVT 0xa +#define SMBSLVDAT 0xc + +#define AX_INDXC 0 +#define AX_INDXP 2 +#define AXCFG 4 +#define ABCFG 6 +#define RC_INDXC 1 +#define RC_INDXP 3 + +#define AB_INDX 0xCD8 +#define AB_DATA (AB_INDX+4) + +/* 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) + +#define abcfg_reg(reg, mask, val) \ + alink_ab_indx((ABCFG), (reg), (mask), (val)) +#define axcfg_reg(reg, mask, val) \ + alink_ab_indx((AXCFG), (reg), (mask), (val)) +#define axindxc_reg(reg, mask, val) \ + alink_ax_indx((AX_INDXC), (reg), (mask), (val)) +#define axindxp_reg(reg, mask, val) \ + alink_ax_indx((AX_INDXP), (reg), (mask), (val)) +#define rcindxc_reg(reg, port, mask, val) \ + alink_rc_indx((RC_INDXC), (reg), (port), (mask), (val)) +#define rcindxp_reg(reg, port, mask, val) \ + alink_rc_indx((RC_INDXP), (reg), (port), (mask), (val)) + +int do_smbus_read_byte(u32 smbus_io_base, u32 device, u32 address); +int do_smbus_write_byte(u32 smbus_io_base, u32 device, u32 address, u8 val); +int do_smbus_recv_byte(u32 smbus_io_base, u32 device); +int do_smbus_send_byte(u32 smbus_io_base, u32 device, u8 val); +void alink_rc_indx(u32 reg_space, u32 reg_addr, u32 port, u32 mask, u32 val); +void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val); +void alink_ax_indx(u32 space /*c or p? */ , u32 axindc, u32 mask, u32 val); + + +#endif diff --git a/src/southbridge/amd/agesa/hudson/spi.c b/src/southbridge/amd/agesa/hudson/spi.c new file mode 100644 index 0000000000..ad8b6d4f44 --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/spi.c @@ -0,0 +1,218 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Advanced Micro Devices, 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 <arch/io.h> +#include <device/device.h> +#include "spi.h" + +void execute_command(volatile u8 * spi_address) +{ + *(spi_address + 2) |= 1; +} + +void wait4command_complete(volatile u8 * spi_address) +{ +// while (*(spi_address + 2) & 1) + while ((*(spi_address + 2) & 1) && (*(spi_address + 3) & 0x80)) + printk(BIOS_DEBUG, "wait4CommandComplete\n"); +} + +void reset_internal_fifo_pointer(volatile u8 * spi_address) +{ + u8 val; + + do { + *(spi_address + 2) |= 0x10; + val = *(spi_address + 0xd); + } while (val & 0x7); +} + +u8 read_spi_status(volatile u8 * spi_address) +{ + u8 val; + *spi_address = 0x05; + *(spi_address + 1) = 0x21; + reset_internal_fifo_pointer(spi_address); + *(spi_address + 0xC) = 0x0; /* dummy */ + reset_internal_fifo_pointer(spi_address); + execute_command(spi_address); + wait4command_complete(spi_address); + reset_internal_fifo_pointer(spi_address); + val = *(spi_address + 0xC); + val = *(spi_address + 0xC); + val = *(spi_address + 0xC); + return val; +} + +void wait4flashpart_ready(volatile u8 * spi_address) +{ + while (read_spi_status(spi_address) & 1) ; +} + +void write_spi_status(volatile u8 * spi_address, u8 status) +{ + *spi_address = 0x50; /* EWSR */ + *(spi_address + 1) = 0; /* RxByte=TxByte=0 */ + execute_command(spi_address); + wait4command_complete(spi_address); + + *spi_address = 0x01; /* WRSR */ + *(spi_address + 1) = 0x01; + reset_internal_fifo_pointer(spi_address); + *(spi_address + 0xC) = status; + reset_internal_fifo_pointer(spi_address); + execute_command(spi_address); + wait4command_complete(spi_address); + wait4flashpart_ready(spi_address); + + read_spi_status(spi_address); +} + +void read_spi_id(volatile u8 * spi_address) +{ + u8 mid = 0, did = 0; + *spi_address = 0x90; + *(spi_address + 1) = 0x23; /* RxByte=2, TxByte=3 */ + reset_internal_fifo_pointer(spi_address); + *(spi_address + 0xC) = 0; + *(spi_address + 0xC) = 0; + *(spi_address + 0xC) = 0; + reset_internal_fifo_pointer(spi_address); + execute_command(spi_address); + wait4command_complete(spi_address); + reset_internal_fifo_pointer(spi_address); + mid = *(spi_address + 0xC); + printk(BIOS_DEBUG, "mid=%x, did=%x\n", mid, did); + mid = *(spi_address + 0xC); + printk(BIOS_DEBUG, "mid=%x, did=%x\n", mid, did); + mid = *(spi_address + 0xC); + printk(BIOS_DEBUG, "mid=%x, did=%x\n", mid, did); + + mid = *(spi_address + 0xC); + did = *(spi_address + 0xC); + printk(BIOS_DEBUG, "mid=%x, did=%x\n", mid, did); +} + +void spi_write_enable(volatile u8 * spi_address) +{ + *spi_address = 0x06; /* Write Enable */ + *(spi_address + 1) = 0x0; /* RxByte=0, TxByte=0 */ + execute_command(spi_address); + wait4command_complete(spi_address); +} + +void spi_write_disable(volatile u8 * spi_address) +{ + *spi_address = 0x04; /* Write Enable */ + *(spi_address + 1) = 0x0; /* RxByte=0, TxByte=0 */ + execute_command(spi_address); + wait4command_complete(spi_address); +} + +void sector_erase_spi(volatile u8 * spi_address, u32 address) +{ + spi_write_enable(spi_address); + *spi_address = 0x20; + *(spi_address + 1) = 0x03; /* RxByte=0, TxByte=3 */ + + reset_internal_fifo_pointer(spi_address); + *(spi_address + 0xC) = (address >> 16) & 0xFF; + *(spi_address + 0xC) = (address >> 8) & 0xFF; + *(spi_address + 0xC) = (address >> 0) & 0xFF; + reset_internal_fifo_pointer(spi_address); + execute_command(spi_address); + wait4command_complete(spi_address); + wait4flashpart_ready(spi_address); +} + +void chip_erase_spi(volatile u8 * spi_address) +{ + spi_write_enable(spi_address); + *spi_address = 0xC7; + *(spi_address + 1) = 0x00; + execute_command(spi_address); + wait4command_complete(spi_address); + wait4flashpart_ready(spi_address); +} + +void byte_program(volatile u8 * spi_address, u32 address, u32 data) +{ + spi_write_enable(spi_address); + *spi_address = 0x02; + *(spi_address + 1) = 0x0 << 4 | 4; + reset_internal_fifo_pointer(spi_address); + *(spi_address + 0xC) = (address >> 16) & 0xFF; + *(spi_address + 0xC) = (address >> 8) & 0xFF; + *(spi_address + 0xC) = (address >> 0) & 0xFF; + *(spi_address + 0xC) = data & 0xFF; + reset_internal_fifo_pointer(spi_address); + execute_command(spi_address); + wait4command_complete(spi_address); + wait4flashpart_ready(spi_address); +} + +void dword_noneAAI_program(volatile u8 * spi_address, u32 address, u32 data) +{ + u8 i; + /* + * printk(BIOS_SPEW, "%s: addr=%x, data=%x\n", __func__, address, data); + */ + for (i = 0; i < 4; i++) { + spi_write_enable(spi_address); + *spi_address = 0x02; + *(spi_address + 1) = 0x0 << 4 | 4; + reset_internal_fifo_pointer(spi_address); + *(spi_address + 0xC) = (address >> 16) & 0xFF; + *(spi_address + 0xC) = (address >> 8) & 0xFF; + *(spi_address + 0xC) = (address >> 0) & 0xFF; + *(spi_address + 0xC) = data & 0xFF; + data >>= 8; + address++; + reset_internal_fifo_pointer(spi_address); + execute_command(spi_address); + wait4command_complete(spi_address); + wait4flashpart_ready(spi_address); + } +} + +void dword_program(volatile u8 * spi_address, u32 address, u32 data) +{ + spi_write_enable(spi_address); + *spi_address = 0x02; + *(spi_address + 1) = 0x0 << 4 | 7; + reset_internal_fifo_pointer(spi_address); + *(spi_address + 0xC) = (address >> 16) & 0xFF; + *(spi_address + 0xC) = (address >> 8) & 0xFF; + *(spi_address + 0xC) = (address >> 0) & 0xFF; + *(spi_address + 0xC) = data & 0xFF; + *(spi_address + 0xC) = (data >> 8) & 0xFF; + *(spi_address + 0xC) = (data >> 16) & 0xFF; + *(spi_address + 0xC) = (data >> 24) & 0xFF; + reset_internal_fifo_pointer(spi_address); + execute_command(spi_address); + wait4command_complete(spi_address); + wait4flashpart_ready(spi_address); +} + +void direct_byte_program(volatile u8 * spi_address, volatile u32 * address, u32 data) +{ + spi_write_enable(spi_address); + *address = data; + wait4flashpart_ready(spi_address); +} diff --git a/src/southbridge/amd/agesa/hudson/spi.h b/src/southbridge/amd/agesa/hudson/spi.h new file mode 100644 index 0000000000..657ce4e2f4 --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/spi.h @@ -0,0 +1,43 @@ +/* + ***************************************************************************** + * + * This file is part of the coreboot project. + * + * Copyright (C) 2012 Advanced Micro Devices, 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 _HUDSON_CIMX_SPI_H_ +#define _HUDSON_CIMX_SPI_H_ + +void execute_command(volatile u8 * spi_address); +void wait4command_complete(volatile u8 * spi_address); +void reset_internal_fifo_pointer(volatile u8 * spi_address); +u8 read_spi_status(volatile u8 * spi_address); +void wait4flashpart_ready(volatile u8 * spi_address); +void write_spi_status(volatile u8 * spi_address, u8 status); +void read_spi_id(volatile u8 * spi_address); +void spi_write_enable(volatile u8 * spi_address); +void spi_write_disable(volatile u8 * spi_address); +void sector_erase_spi(volatile u8 * spi_address, u32 address); +void chip_erase_spi(volatile u8 * spi_address); +void byte_program(volatile u8 * spi_address, u32 address, u32 data); +void dword_noneAAI_program(volatile u8 * spi_address, u32 address, u32 data); +void dword_program(volatile u8 * spi_address, u32 address, u32 data); +void direct_byte_program(volatile u8 * spi_address, volatile u32 * address, u32 data); + +#endif diff --git a/src/southbridge/amd/agesa/hudson/usb.c b/src/southbridge/amd/agesa/hudson/usb.c new file mode 100644 index 0000000000..0d3ba9ea2c --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/usb.c @@ -0,0 +1,124 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, 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_ids.h> +#include <device/pci_ops.h> +#include <usbdebug.h> +#include <arch/io.h> +#include "hudson.h" + +static struct pci_operations lops_pci = { + .set_subsystem = pci_dev_set_subsystem, +}; + +static void usb_init(struct device *dev) +{ +} + +static void usb_set_resources(struct device *dev) +{ +#if CONFIG_USBDEBUG + struct resource *res; + u32 base; + u32 old_debug; + + old_debug = get_ehci_debug(); + set_ehci_debug(0); +#endif + pci_dev_set_resources(dev); + +#if CONFIG_USBDEBUG + 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 struct device_operations usb_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = usb_set_resources, /* pci_dev_set_resources, */ + .enable_resources = pci_dev_enable_resources, + .init = usb_init, + .scan_bus = 0, + .ops_pci = &lops_pci, +}; + +static const struct pci_driver usb_0_driver __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_ATI_SB900_USB_18_0, +}; +static const struct pci_driver usb_1_driver __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_ATI_SB900_USB_18_2, +}; + +/* the pci id of usb ctrl 0 and 1 are the same. */ +/* + * static const struct pci_driver usb_3_driver __pci_driver = { + * .ops = &usb_ops, + * .vendor = PCI_VENDOR_ID_AMD, + * .device = PCI_DEVICE_ID_ATI_HUDSON_USB_19_0, + * }; + * static const struct pci_driver usb_4_driver __pci_driver = { + * .ops = &usb_ops, + * .vendor = PCI_VENDOR_ID_AMD, + * .device = PCI_DEVICE_ID_ATI_HUDSON_USB_19_1, + * }; + */ + +static const struct pci_driver usb_4_driver __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_ATI_SB900_USB_20_5, +}; + +/* +static struct device_operations usb_ops2 = { + .read_resources = pci_dev_read_resources, + .set_resources = usb_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = usb_init2, + .scan_bus = 0, + .ops_pci = &lops_pci, +}; +*/ +/* +static const struct pci_driver usb_5_driver __pci_driver = { + .ops = &usb_ops2, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_ATI_HUDSON_USB_18_2, +}; +*/ +/* + * static const struct pci_driver usb_5_driver __pci_driver = { + * .ops = &usb_ops2, + * .vendor = PCI_VENDOR_ID_AMD, + * .device = PCI_DEVICE_ID_ATI_HUDSON_USB_19_2, + * }; + */ |