From 836ae29ee325b1e3d28ff59468cc50913b1e24ce Mon Sep 17 00:00:00 2001 From: stepan Date: Wed, 8 Dec 2010 05:42:47 +0000 Subject: first round name simplification. drop the _ prefix. the prefix was introduced in the early v2 tree many years ago because our old build system "newconfig" could not handle two files with the same name in different paths like /path/to/usb.c and /another/path/to/usb.c correctly. Only one of the files would end up being compiled into the final image. Since Kconfig (actually since shortly before we switched to Kconfig) we don't suffer from that problem anymore. So we could drop the sb700_ prefix from all those filenames (or, the _ prefix in general) - makes it easier to fork off a new chipset - makes it easier to diff against other chipsets - storing redundant information in filenames seems wrong Signed-off-by: Acked-by: Patrick Georgi Acked-by: Peter Stuge git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6149 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/southbridge/amd/amd8111/Makefile.inc | 20 +- src/southbridge/amd/amd8111/ac97.c | 52 + src/southbridge/amd/amd8111/acpi.c | 220 ++++ src/southbridge/amd/amd8111/amd8111_ac97.c | 52 - src/southbridge/amd/amd8111/amd8111_acpi.c | 220 ---- src/southbridge/amd/amd8111/amd8111_early_ctrl.c | 83 -- src/southbridge/amd/amd8111/amd8111_early_smbus.c | 48 - src/southbridge/amd/amd8111/amd8111_enable_rom.c | 42 - src/southbridge/amd/amd8111/amd8111_ide.c | 66 - src/southbridge/amd/amd8111/amd8111_lpc.c | 133 -- src/southbridge/amd/amd8111/amd8111_nic.c | 90 -- src/southbridge/amd/amd8111/amd8111_pci.c | 68 - src/southbridge/amd/amd8111/amd8111_reset.c | 76 -- src/southbridge/amd/amd8111/amd8111_smbus.c | 41 - src/southbridge/amd/amd8111/amd8111_usb.c | 37 - src/southbridge/amd/amd8111/amd8111_usb2.c | 45 - src/southbridge/amd/amd8111/bootblock.c | 2 +- src/southbridge/amd/amd8111/early_ctrl.c | 83 ++ src/southbridge/amd/amd8111/early_smbus.c | 48 + src/southbridge/amd/amd8111/enable_rom.c | 42 + src/southbridge/amd/amd8111/ide.c | 66 + src/southbridge/amd/amd8111/lpc.c | 133 ++ src/southbridge/amd/amd8111/nic.c | 90 ++ src/southbridge/amd/amd8111/pci.c | 68 + src/southbridge/amd/amd8111/reset.c | 76 ++ src/southbridge/amd/amd8111/smbus.c | 41 + src/southbridge/amd/amd8111/usb.c | 37 + src/southbridge/amd/amd8111/usb2.c | 45 + .../amd/amd8131-disable/amd8131_bridge.c | 116 -- src/southbridge/amd/amd8131-disable/bridge.c | 116 ++ src/southbridge/amd/amd8131/Makefile.inc | 2 +- src/southbridge/amd/amd8131/amd8131_bridge.c | 432 ------- src/southbridge/amd/amd8131/bridge.c | 432 +++++++ src/southbridge/amd/amd8132/Makefile.inc | 2 +- src/southbridge/amd/amd8132/amd8132_bridge.c | 433 ------- src/southbridge/amd/amd8132/bridge.c | 433 +++++++ src/southbridge/amd/amd8151/Makefile.inc | 2 +- src/southbridge/amd/amd8151/agp3.c | 90 ++ src/southbridge/amd/amd8151/amd8151_agp3.c | 90 -- src/southbridge/amd/cs5530/Makefile.inc | 8 +- src/southbridge/amd/cs5530/cs5530_enable_rom.c | 47 - src/southbridge/amd/cs5530/cs5530_ide.c | 78 -- src/southbridge/amd/cs5530/cs5530_isa.c | 64 - src/southbridge/amd/cs5530/cs5530_pirq.c | 39 - src/southbridge/amd/cs5530/cs5530_vga.c | 495 -------- src/southbridge/amd/cs5530/enable_rom.c | 47 + src/southbridge/amd/cs5530/ide.c | 78 ++ src/southbridge/amd/cs5530/isa.c | 64 + src/southbridge/amd/cs5530/pirq.c | 39 + src/southbridge/amd/cs5530/vga.c | 495 ++++++++ src/southbridge/amd/cs5535/Makefile.inc | 4 +- src/southbridge/amd/cs5535/cs5535_early_setup.c | 149 --- src/southbridge/amd/cs5535/cs5535_early_smbus.c | 22 - src/southbridge/amd/cs5535/cs5535_ide.c | 30 - src/southbridge/amd/cs5535/cs5535_smbus.h | 46 - src/southbridge/amd/cs5535/early_setup.c | 149 +++ src/southbridge/amd/cs5535/early_smbus.c | 22 + src/southbridge/amd/cs5535/ide.c | 30 + src/southbridge/amd/cs5535/smbus.h | 46 + src/southbridge/amd/cs5536/Makefile.inc | 4 +- src/southbridge/amd/cs5536/cs5536_early_setup.c | 275 ---- src/southbridge/amd/cs5536/cs5536_early_smbus.c | 213 ---- src/southbridge/amd/cs5536/cs5536_ide.c | 61 - src/southbridge/amd/cs5536/cs5536_pirq.c | 39 - src/southbridge/amd/cs5536/cs5536_smbus2.h | 317 ----- src/southbridge/amd/cs5536/early_setup.c | 275 ++++ src/southbridge/amd/cs5536/early_smbus.c | 213 ++++ src/southbridge/amd/cs5536/ide.c | 61 + src/southbridge/amd/cs5536/pirq.c | 39 + src/southbridge/amd/cs5536/smbus2.h | 317 +++++ src/southbridge/amd/rs690/Makefile.inc | 8 +- src/southbridge/amd/rs690/cmn.c | 324 +++++ src/southbridge/amd/rs690/early_setup.c | 484 +++++++ src/southbridge/amd/rs690/gfx.c | 625 +++++++++ src/southbridge/amd/rs690/ht.c | 90 ++ src/southbridge/amd/rs690/pcie.c | 401 ++++++ src/southbridge/amd/rs690/rs690_cmn.c | 324 ----- src/southbridge/amd/rs690/rs690_early_setup.c | 484 ------- src/southbridge/amd/rs690/rs690_gfx.c | 625 --------- src/southbridge/amd/rs690/rs690_ht.c | 90 -- src/southbridge/amd/rs690/rs690_pcie.c | 401 ------ src/southbridge/amd/rs780/Makefile.inc | 8 +- src/southbridge/amd/rs780/cmn.c | 403 ++++++ src/southbridge/amd/rs780/early_setup.c | 675 ++++++++++ src/southbridge/amd/rs780/gfx.c | 1340 ++++++++++++++++++++ src/southbridge/amd/rs780/ht.c | 90 ++ src/southbridge/amd/rs780/pcie.c | 392 ++++++ src/southbridge/amd/rs780/rev.h | 27 + src/southbridge/amd/rs780/rs780.h | 2 +- src/southbridge/amd/rs780/rs780_cmn.c | 403 ------ src/southbridge/amd/rs780/rs780_early_setup.c | 675 ---------- src/southbridge/amd/rs780/rs780_gfx.c | 1340 -------------------- src/southbridge/amd/rs780/rs780_ht.c | 90 -- src/southbridge/amd/rs780/rs780_pcie.c | 392 ------ src/southbridge/amd/rs780/rs780_rev.h | 27 - src/southbridge/amd/sb600/Makefile.inc | 20 +- src/southbridge/amd/sb600/ac97.c | 61 + src/southbridge/amd/sb600/bootblock.c | 2 +- src/southbridge/amd/sb600/early_setup.c | 660 ++++++++++ src/southbridge/amd/sb600/enable_rom.c | 65 + src/southbridge/amd/sb600/enable_usbdebug.c | 45 + src/southbridge/amd/sb600/hda.c | 331 +++++ src/southbridge/amd/sb600/ide.c | 72 ++ src/southbridge/amd/sb600/lpc.c | 225 ++++ src/southbridge/amd/sb600/pci.c | 142 +++ src/southbridge/amd/sb600/reset.c | 33 + src/southbridge/amd/sb600/sata.c | 265 ++++ src/southbridge/amd/sb600/sb600_ac97.c | 61 - src/southbridge/amd/sb600/sb600_early_setup.c | 660 ---------- src/southbridge/amd/sb600/sb600_enable_rom.c | 65 - src/southbridge/amd/sb600/sb600_enable_usbdebug.c | 45 - src/southbridge/amd/sb600/sb600_hda.c | 331 ----- src/southbridge/amd/sb600/sb600_ide.c | 72 -- src/southbridge/amd/sb600/sb600_lpc.c | 225 ---- src/southbridge/amd/sb600/sb600_pci.c | 142 --- src/southbridge/amd/sb600/sb600_reset.c | 33 - src/southbridge/amd/sb600/sb600_sata.c | 265 ---- src/southbridge/amd/sb600/sb600_sm.c | 375 ------ src/southbridge/amd/sb600/sb600_smbus.c | 214 ---- src/southbridge/amd/sb600/sb600_smbus.h | 64 - src/southbridge/amd/sb600/sb600_usb.c | 203 --- src/southbridge/amd/sb600/sm.c | 375 ++++++ src/southbridge/amd/sb600/smbus.c | 214 ++++ src/southbridge/amd/sb600/smbus.h | 64 + src/southbridge/amd/sb600/usb.c | 203 +++ src/southbridge/amd/sb700/Makefile.inc | 18 +- src/southbridge/amd/sb700/early_setup.c | 619 +++++++++ src/southbridge/amd/sb700/enable_usbdebug.c | 63 + src/southbridge/amd/sb700/hda.c | 232 ++++ src/southbridge/amd/sb700/ide.c | 85 ++ src/southbridge/amd/sb700/lpc.c | 238 ++++ src/southbridge/amd/sb700/pci.c | 128 ++ src/southbridge/amd/sb700/reset.c | 33 + src/southbridge/amd/sb700/sata.c | 294 +++++ src/southbridge/amd/sb700/sb700_early_setup.c | 619 --------- src/southbridge/amd/sb700/sb700_enable_usbdebug.c | 63 - src/southbridge/amd/sb700/sb700_hda.c | 232 ---- src/southbridge/amd/sb700/sb700_ide.c | 85 -- src/southbridge/amd/sb700/sb700_lpc.c | 238 ---- src/southbridge/amd/sb700/sb700_pci.c | 128 -- src/southbridge/amd/sb700/sb700_reset.c | 33 - src/southbridge/amd/sb700/sb700_sata.c | 294 ----- src/southbridge/amd/sb700/sb700_sm.c | 381 ------ src/southbridge/amd/sb700/sb700_smbus.c | 224 ---- src/southbridge/amd/sb700/sb700_smbus.h | 65 - src/southbridge/amd/sb700/sb700_usb.c | 253 ---- src/southbridge/amd/sb700/sm.c | 381 ++++++ src/southbridge/amd/sb700/smbus.c | 224 ++++ src/southbridge/amd/sb700/smbus.h | 65 + src/southbridge/amd/sb700/usb.c | 253 ++++ 150 files changed, 14219 insertions(+), 14219 deletions(-) create mode 100644 src/southbridge/amd/amd8111/ac97.c create mode 100644 src/southbridge/amd/amd8111/acpi.c delete mode 100644 src/southbridge/amd/amd8111/amd8111_ac97.c delete mode 100644 src/southbridge/amd/amd8111/amd8111_acpi.c delete mode 100644 src/southbridge/amd/amd8111/amd8111_early_ctrl.c delete mode 100644 src/southbridge/amd/amd8111/amd8111_early_smbus.c delete mode 100644 src/southbridge/amd/amd8111/amd8111_enable_rom.c delete mode 100644 src/southbridge/amd/amd8111/amd8111_ide.c delete mode 100644 src/southbridge/amd/amd8111/amd8111_lpc.c delete mode 100644 src/southbridge/amd/amd8111/amd8111_nic.c delete mode 100644 src/southbridge/amd/amd8111/amd8111_pci.c delete mode 100644 src/southbridge/amd/amd8111/amd8111_reset.c delete mode 100644 src/southbridge/amd/amd8111/amd8111_smbus.c delete mode 100644 src/southbridge/amd/amd8111/amd8111_usb.c delete mode 100644 src/southbridge/amd/amd8111/amd8111_usb2.c create mode 100644 src/southbridge/amd/amd8111/early_ctrl.c create mode 100644 src/southbridge/amd/amd8111/early_smbus.c create mode 100644 src/southbridge/amd/amd8111/enable_rom.c create mode 100644 src/southbridge/amd/amd8111/ide.c create mode 100644 src/southbridge/amd/amd8111/lpc.c create mode 100644 src/southbridge/amd/amd8111/nic.c create mode 100644 src/southbridge/amd/amd8111/pci.c create mode 100644 src/southbridge/amd/amd8111/reset.c create mode 100644 src/southbridge/amd/amd8111/smbus.c create mode 100644 src/southbridge/amd/amd8111/usb.c create mode 100644 src/southbridge/amd/amd8111/usb2.c delete mode 100644 src/southbridge/amd/amd8131-disable/amd8131_bridge.c create mode 100644 src/southbridge/amd/amd8131-disable/bridge.c delete mode 100644 src/southbridge/amd/amd8131/amd8131_bridge.c create mode 100644 src/southbridge/amd/amd8131/bridge.c delete mode 100644 src/southbridge/amd/amd8132/amd8132_bridge.c create mode 100644 src/southbridge/amd/amd8132/bridge.c create mode 100644 src/southbridge/amd/amd8151/agp3.c delete mode 100644 src/southbridge/amd/amd8151/amd8151_agp3.c delete mode 100644 src/southbridge/amd/cs5530/cs5530_enable_rom.c delete mode 100644 src/southbridge/amd/cs5530/cs5530_ide.c delete mode 100644 src/southbridge/amd/cs5530/cs5530_isa.c delete mode 100644 src/southbridge/amd/cs5530/cs5530_pirq.c delete mode 100644 src/southbridge/amd/cs5530/cs5530_vga.c create mode 100644 src/southbridge/amd/cs5530/enable_rom.c create mode 100644 src/southbridge/amd/cs5530/ide.c create mode 100644 src/southbridge/amd/cs5530/isa.c create mode 100644 src/southbridge/amd/cs5530/pirq.c create mode 100644 src/southbridge/amd/cs5530/vga.c delete mode 100644 src/southbridge/amd/cs5535/cs5535_early_setup.c delete mode 100644 src/southbridge/amd/cs5535/cs5535_early_smbus.c delete mode 100644 src/southbridge/amd/cs5535/cs5535_ide.c delete mode 100644 src/southbridge/amd/cs5535/cs5535_smbus.h create mode 100644 src/southbridge/amd/cs5535/early_setup.c create mode 100644 src/southbridge/amd/cs5535/early_smbus.c create mode 100644 src/southbridge/amd/cs5535/ide.c create mode 100644 src/southbridge/amd/cs5535/smbus.h delete mode 100644 src/southbridge/amd/cs5536/cs5536_early_setup.c delete mode 100644 src/southbridge/amd/cs5536/cs5536_early_smbus.c delete mode 100644 src/southbridge/amd/cs5536/cs5536_ide.c delete mode 100644 src/southbridge/amd/cs5536/cs5536_pirq.c delete mode 100644 src/southbridge/amd/cs5536/cs5536_smbus2.h create mode 100644 src/southbridge/amd/cs5536/early_setup.c create mode 100644 src/southbridge/amd/cs5536/early_smbus.c create mode 100644 src/southbridge/amd/cs5536/ide.c create mode 100644 src/southbridge/amd/cs5536/pirq.c create mode 100644 src/southbridge/amd/cs5536/smbus2.h create mode 100644 src/southbridge/amd/rs690/cmn.c create mode 100644 src/southbridge/amd/rs690/early_setup.c create mode 100644 src/southbridge/amd/rs690/gfx.c create mode 100644 src/southbridge/amd/rs690/ht.c create mode 100644 src/southbridge/amd/rs690/pcie.c delete mode 100644 src/southbridge/amd/rs690/rs690_cmn.c delete mode 100644 src/southbridge/amd/rs690/rs690_early_setup.c delete mode 100644 src/southbridge/amd/rs690/rs690_gfx.c delete mode 100644 src/southbridge/amd/rs690/rs690_ht.c delete mode 100644 src/southbridge/amd/rs690/rs690_pcie.c create mode 100644 src/southbridge/amd/rs780/cmn.c create mode 100644 src/southbridge/amd/rs780/early_setup.c create mode 100644 src/southbridge/amd/rs780/gfx.c create mode 100644 src/southbridge/amd/rs780/ht.c create mode 100644 src/southbridge/amd/rs780/pcie.c create mode 100644 src/southbridge/amd/rs780/rev.h delete mode 100644 src/southbridge/amd/rs780/rs780_cmn.c delete mode 100644 src/southbridge/amd/rs780/rs780_early_setup.c delete mode 100644 src/southbridge/amd/rs780/rs780_gfx.c delete mode 100644 src/southbridge/amd/rs780/rs780_ht.c delete mode 100644 src/southbridge/amd/rs780/rs780_pcie.c delete mode 100644 src/southbridge/amd/rs780/rs780_rev.h create mode 100644 src/southbridge/amd/sb600/ac97.c create mode 100644 src/southbridge/amd/sb600/early_setup.c create mode 100644 src/southbridge/amd/sb600/enable_rom.c create mode 100644 src/southbridge/amd/sb600/enable_usbdebug.c create mode 100644 src/southbridge/amd/sb600/hda.c create mode 100644 src/southbridge/amd/sb600/ide.c create mode 100644 src/southbridge/amd/sb600/lpc.c create mode 100644 src/southbridge/amd/sb600/pci.c create mode 100644 src/southbridge/amd/sb600/reset.c create mode 100644 src/southbridge/amd/sb600/sata.c delete mode 100644 src/southbridge/amd/sb600/sb600_ac97.c delete mode 100644 src/southbridge/amd/sb600/sb600_early_setup.c delete mode 100644 src/southbridge/amd/sb600/sb600_enable_rom.c delete mode 100644 src/southbridge/amd/sb600/sb600_enable_usbdebug.c delete mode 100644 src/southbridge/amd/sb600/sb600_hda.c delete mode 100644 src/southbridge/amd/sb600/sb600_ide.c delete mode 100644 src/southbridge/amd/sb600/sb600_lpc.c delete mode 100644 src/southbridge/amd/sb600/sb600_pci.c delete mode 100644 src/southbridge/amd/sb600/sb600_reset.c delete mode 100644 src/southbridge/amd/sb600/sb600_sata.c delete mode 100644 src/southbridge/amd/sb600/sb600_sm.c delete mode 100644 src/southbridge/amd/sb600/sb600_smbus.c delete mode 100644 src/southbridge/amd/sb600/sb600_smbus.h delete mode 100644 src/southbridge/amd/sb600/sb600_usb.c create mode 100644 src/southbridge/amd/sb600/sm.c create mode 100644 src/southbridge/amd/sb600/smbus.c create mode 100644 src/southbridge/amd/sb600/smbus.h create mode 100644 src/southbridge/amd/sb600/usb.c create mode 100644 src/southbridge/amd/sb700/early_setup.c create mode 100644 src/southbridge/amd/sb700/enable_usbdebug.c create mode 100644 src/southbridge/amd/sb700/hda.c create mode 100644 src/southbridge/amd/sb700/ide.c create mode 100644 src/southbridge/amd/sb700/lpc.c create mode 100644 src/southbridge/amd/sb700/pci.c create mode 100644 src/southbridge/amd/sb700/reset.c create mode 100644 src/southbridge/amd/sb700/sata.c delete mode 100644 src/southbridge/amd/sb700/sb700_early_setup.c delete mode 100644 src/southbridge/amd/sb700/sb700_enable_usbdebug.c delete mode 100644 src/southbridge/amd/sb700/sb700_hda.c delete mode 100644 src/southbridge/amd/sb700/sb700_ide.c delete mode 100644 src/southbridge/amd/sb700/sb700_lpc.c delete mode 100644 src/southbridge/amd/sb700/sb700_pci.c delete mode 100644 src/southbridge/amd/sb700/sb700_reset.c delete mode 100644 src/southbridge/amd/sb700/sb700_sata.c delete mode 100644 src/southbridge/amd/sb700/sb700_sm.c delete mode 100644 src/southbridge/amd/sb700/sb700_smbus.c delete mode 100644 src/southbridge/amd/sb700/sb700_smbus.h delete mode 100644 src/southbridge/amd/sb700/sb700_usb.c create mode 100644 src/southbridge/amd/sb700/sm.c create mode 100644 src/southbridge/amd/sb700/smbus.c create mode 100644 src/southbridge/amd/sb700/smbus.h create mode 100644 src/southbridge/amd/sb700/usb.c (limited to 'src/southbridge/amd') diff --git a/src/southbridge/amd/amd8111/Makefile.inc b/src/southbridge/amd/amd8111/Makefile.inc index b58fbaac88..cdad4a62ab 100644 --- a/src/southbridge/amd/amd8111/Makefile.inc +++ b/src/southbridge/amd/amd8111/Makefile.inc @@ -1,11 +1,11 @@ driver-y += amd8111.c -driver-y += amd8111_usb.c -driver-y += amd8111_lpc.c -driver-y += amd8111_ide.c -driver-y += amd8111_acpi.c -driver-y += amd8111_usb2.c -driver-y += amd8111_ac97.c -driver-y += amd8111_nic.c -driver-y += amd8111_pci.c -driver-y += amd8111_smbus.c -ramstage-y += amd8111_reset.c +driver-y += usb.c +driver-y += lpc.c +driver-y += ide.c +driver-y += acpi.c +driver-y += usb2.c +driver-y += ac97.c +driver-y += nic.c +driver-y += pci.c +driver-y += smbus.c +ramstage-y += reset.c diff --git a/src/southbridge/amd/amd8111/ac97.c b/src/southbridge/amd/amd8111/ac97.c new file mode 100644 index 0000000000..f49c9bfd5f --- /dev/null +++ b/src/southbridge/amd/amd8111/ac97.c @@ -0,0 +1,52 @@ +/* + * (C) 2003 Linux Networx + */ +#include +#include +#include +#include +#include +#include "amd8111.h" + +static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + pci_write_config32(dev, 0x2c, + ((device & 0xffff) << 16) | (vendor & 0xffff)); +} + +static struct pci_operations lops_pci = { + .set_subsystem = lpci_set_subsystem, +}; + +static struct device_operations ac97audio_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .enable = amd8111_enable, + .init = 0, + .scan_bus = 0, + .ops_pci = &lops_pci, +}; + +static const struct pci_driver ac97audio_driver __pci_driver = { + .ops = &ac97audio_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = 0x746D, +}; + + +static struct device_operations ac97modem_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .enable = amd8111_enable, + .init = 0, + .scan_bus = 0, + .ops_pci = &lops_pci, +}; + +static const struct pci_driver ac97modem_driver __pci_driver = { + .ops = &ac97modem_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = 0x746E, +}; diff --git a/src/southbridge/amd/amd8111/acpi.c b/src/southbridge/amd/amd8111/acpi.c new file mode 100644 index 0000000000..2ad54b78f6 --- /dev/null +++ b/src/southbridge/amd/amd8111/acpi.c @@ -0,0 +1,220 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "amd8111.h" +#include "amd8111_smbus.h" + +#define PREVIOUS_POWER_STATE 0x43 +#define MAINBOARD_POWER_OFF 0 +#define MAINBOARD_POWER_ON 1 +#define SLOW_CPU_OFF 0 +#define SLOW_CPU__ON 1 + +#ifndef CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL +#define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON +#endif + + +static int lsmbus_recv_byte(device_t dev) +{ + unsigned device; + struct resource *res; + + device = dev->path.i2c.device; + res = find_resource(get_pbus_smbus(dev)->dev, 0x58); + + return do_smbus_recv_byte(res->base, device); +} + +static int lsmbus_send_byte(device_t dev, uint8_t val) +{ + unsigned device; + struct resource *res; + + device = dev->path.i2c.device; + res = find_resource(get_pbus_smbus(dev)->dev, 0x58); + + return do_smbus_send_byte(res->base, device, val); +} + + +static int lsmbus_read_byte(device_t dev, uint8_t address) +{ + unsigned device; + struct resource *res; + + device = dev->path.i2c.device; + res = find_resource(get_pbus_smbus(dev)->dev, 0x58); + + return do_smbus_read_byte(res->base, device, address); +} + +static int lsmbus_write_byte(device_t dev, uint8_t address, uint8_t val) +{ + unsigned device; + struct resource *res; + + device = dev->path.i2c.device; + res = find_resource(get_pbus_smbus(dev)->dev, 0x58); + + return do_smbus_write_byte(res->base, device, address, val); +} + +#if CONFIG_GENERATE_ACPI_TABLES == 1 +unsigned pm_base; +#endif + +static void acpi_init(struct device *dev) +{ + uint8_t byte; + uint16_t pm10_bar; + uint32_t dword; + int on; + +#if 0 + uint16_t word; + printk(BIOS_DEBUG, "ACPI: disabling NMI watchdog.. "); + byte = pci_read_config8(dev, 0x49); + pci_write_config8(dev, 0x49, byte | (1<<2)); + + + byte = pci_read_config8(dev, 0x41); + pci_write_config8(dev, 0x41, byte | (1<<6)|(1<<2)); + + /* added from sourceforge */ + byte = pci_read_config8(dev, 0x48); + pci_write_config8(dev, 0x48, byte | (1<<3)); + + printk(BIOS_DEBUG, "done.\n"); + + + printk(BIOS_DEBUG, "ACPI: Routing IRQ 12 to PS2 port.. "); + word = pci_read_config16(dev, 0x46); + pci_write_config16(dev, 0x46, word | (1<<9)); + printk(BIOS_DEBUG, "done.\n"); +#endif + + /* To enable the register 0xcf9 in the IO space + * bit [D5] is set in the amd8111 configuration register. + * The config. reg. is devBx41. Register 0xcf9 allows + * hard reset capability to the system. For the ACPI + * reset.reg values in fadt.c to work this register + * must be enabled. + */ + byte = pci_read_config8(dev, 0x41); + pci_write_config8(dev, 0x41, byte | (1<<6)|(1<<5)); + + /* power on after power fail */ + on = CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL; + get_option(&on, "power_on_after_fail"); + byte = pci_read_config8(dev, PREVIOUS_POWER_STATE); + byte &= ~0x40; + if (!on) { + byte |= 0x40; + } + pci_write_config8(dev, PREVIOUS_POWER_STATE, byte); + printk(BIOS_INFO, "set power %s after power fail\n", on?"on":"off"); + + /* switch serial irq logic from quiet mode to continuous + * mode for Winbond W83627HF Rev. 17 + */ + byte = pci_read_config8(dev, 0x4a); + pci_write_config8(dev, 0x4a, byte | (1<<6)); + + /* Throttle the CPU speed down for testing */ + on = SLOW_CPU_OFF; + get_option(&on, "slow_cpu"); + if(on) { + pm10_bar = (pci_read_config16(dev, 0x58)&0xff00); + outl(((on<<1)+0x10) ,(pm10_bar + 0x10)); + dword = inl(pm10_bar + 0x10); + on = 8-on; + printk(BIOS_DEBUG, "Throttling CPU %2d.%1.1d percent.\n", + (on*12)+(on>>1),(on&1)*5); + } + +#if CONFIG_GENERATE_ACPI_TABLES == 1 + pm_base = pci_read_config16(dev, 0x58) & 0xff00; + printk(BIOS_DEBUG, "pm_base: 0x%04x\n",pm_base); +#endif + +} + +static void acpi_read_resources(device_t dev) +{ + struct resource *resource; + + /* Handle the generic bars */ + pci_dev_read_resources(dev); + + /* Add the ACPI/SMBUS bar */ + resource = new_resource(dev, 0x58); + resource->base = 0; + resource->size = 256; + resource->align = log2(256); + resource->gran = log2(256); + resource->limit = 65536; + resource->flags = IORESOURCE_IO; + resource->index = 0x58; +} + +static void acpi_enable_resources(device_t dev) +{ + uint8_t byte; + /* Enable the generic pci resources */ + pci_dev_enable_resources(dev); + + /* Enable the ACPI/SMBUS Bar */ + byte = pci_read_config8(dev, 0x41); + byte |= (1 << 7); + pci_write_config8(dev, 0x41, byte); + + /* Set the class code */ + pci_write_config32(dev, 0x60, 0x06800000); + +} + +static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + pci_write_config32(dev, 0x7c, + ((device & 0xffff) << 16) | (vendor & 0xffff)); +} + +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 struct pci_operations lops_pci = { + .set_subsystem = lpci_set_subsystem, +}; + +static struct device_operations acpi_ops = { + .read_resources = acpi_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = acpi_enable_resources, + .init = acpi_init, + .scan_bus = scan_static_bus, + /* We don't need amd8111_enable, chip ops takes care of it. + * It could be useful if these devices were not + * enabled by default. + */ +// .enable = amd8111_enable, + .ops_pci = &lops_pci, + .ops_smbus_bus = &lops_smbus_bus, +}; + +static const struct pci_driver acpi_driver __pci_driver = { + .ops = &acpi_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_8111_ACPI, +}; + diff --git a/src/southbridge/amd/amd8111/amd8111_ac97.c b/src/southbridge/amd/amd8111/amd8111_ac97.c deleted file mode 100644 index f49c9bfd5f..0000000000 --- a/src/southbridge/amd/amd8111/amd8111_ac97.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * (C) 2003 Linux Networx - */ -#include -#include -#include -#include -#include -#include "amd8111.h" - -static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) -{ - pci_write_config32(dev, 0x2c, - ((device & 0xffff) << 16) | (vendor & 0xffff)); -} - -static struct pci_operations lops_pci = { - .set_subsystem = lpci_set_subsystem, -}; - -static struct device_operations ac97audio_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .enable = amd8111_enable, - .init = 0, - .scan_bus = 0, - .ops_pci = &lops_pci, -}; - -static const struct pci_driver ac97audio_driver __pci_driver = { - .ops = &ac97audio_ops, - .vendor = PCI_VENDOR_ID_AMD, - .device = 0x746D, -}; - - -static struct device_operations ac97modem_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .enable = amd8111_enable, - .init = 0, - .scan_bus = 0, - .ops_pci = &lops_pci, -}; - -static const struct pci_driver ac97modem_driver __pci_driver = { - .ops = &ac97modem_ops, - .vendor = PCI_VENDOR_ID_AMD, - .device = 0x746E, -}; diff --git a/src/southbridge/amd/amd8111/amd8111_acpi.c b/src/southbridge/amd/amd8111/amd8111_acpi.c deleted file mode 100644 index 2ad54b78f6..0000000000 --- a/src/southbridge/amd/amd8111/amd8111_acpi.c +++ /dev/null @@ -1,220 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "amd8111.h" -#include "amd8111_smbus.h" - -#define PREVIOUS_POWER_STATE 0x43 -#define MAINBOARD_POWER_OFF 0 -#define MAINBOARD_POWER_ON 1 -#define SLOW_CPU_OFF 0 -#define SLOW_CPU__ON 1 - -#ifndef CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL -#define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON -#endif - - -static int lsmbus_recv_byte(device_t dev) -{ - unsigned device; - struct resource *res; - - device = dev->path.i2c.device; - res = find_resource(get_pbus_smbus(dev)->dev, 0x58); - - return do_smbus_recv_byte(res->base, device); -} - -static int lsmbus_send_byte(device_t dev, uint8_t val) -{ - unsigned device; - struct resource *res; - - device = dev->path.i2c.device; - res = find_resource(get_pbus_smbus(dev)->dev, 0x58); - - return do_smbus_send_byte(res->base, device, val); -} - - -static int lsmbus_read_byte(device_t dev, uint8_t address) -{ - unsigned device; - struct resource *res; - - device = dev->path.i2c.device; - res = find_resource(get_pbus_smbus(dev)->dev, 0x58); - - return do_smbus_read_byte(res->base, device, address); -} - -static int lsmbus_write_byte(device_t dev, uint8_t address, uint8_t val) -{ - unsigned device; - struct resource *res; - - device = dev->path.i2c.device; - res = find_resource(get_pbus_smbus(dev)->dev, 0x58); - - return do_smbus_write_byte(res->base, device, address, val); -} - -#if CONFIG_GENERATE_ACPI_TABLES == 1 -unsigned pm_base; -#endif - -static void acpi_init(struct device *dev) -{ - uint8_t byte; - uint16_t pm10_bar; - uint32_t dword; - int on; - -#if 0 - uint16_t word; - printk(BIOS_DEBUG, "ACPI: disabling NMI watchdog.. "); - byte = pci_read_config8(dev, 0x49); - pci_write_config8(dev, 0x49, byte | (1<<2)); - - - byte = pci_read_config8(dev, 0x41); - pci_write_config8(dev, 0x41, byte | (1<<6)|(1<<2)); - - /* added from sourceforge */ - byte = pci_read_config8(dev, 0x48); - pci_write_config8(dev, 0x48, byte | (1<<3)); - - printk(BIOS_DEBUG, "done.\n"); - - - printk(BIOS_DEBUG, "ACPI: Routing IRQ 12 to PS2 port.. "); - word = pci_read_config16(dev, 0x46); - pci_write_config16(dev, 0x46, word | (1<<9)); - printk(BIOS_DEBUG, "done.\n"); -#endif - - /* To enable the register 0xcf9 in the IO space - * bit [D5] is set in the amd8111 configuration register. - * The config. reg. is devBx41. Register 0xcf9 allows - * hard reset capability to the system. For the ACPI - * reset.reg values in fadt.c to work this register - * must be enabled. - */ - byte = pci_read_config8(dev, 0x41); - pci_write_config8(dev, 0x41, byte | (1<<6)|(1<<5)); - - /* power on after power fail */ - on = CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL; - get_option(&on, "power_on_after_fail"); - byte = pci_read_config8(dev, PREVIOUS_POWER_STATE); - byte &= ~0x40; - if (!on) { - byte |= 0x40; - } - pci_write_config8(dev, PREVIOUS_POWER_STATE, byte); - printk(BIOS_INFO, "set power %s after power fail\n", on?"on":"off"); - - /* switch serial irq logic from quiet mode to continuous - * mode for Winbond W83627HF Rev. 17 - */ - byte = pci_read_config8(dev, 0x4a); - pci_write_config8(dev, 0x4a, byte | (1<<6)); - - /* Throttle the CPU speed down for testing */ - on = SLOW_CPU_OFF; - get_option(&on, "slow_cpu"); - if(on) { - pm10_bar = (pci_read_config16(dev, 0x58)&0xff00); - outl(((on<<1)+0x10) ,(pm10_bar + 0x10)); - dword = inl(pm10_bar + 0x10); - on = 8-on; - printk(BIOS_DEBUG, "Throttling CPU %2d.%1.1d percent.\n", - (on*12)+(on>>1),(on&1)*5); - } - -#if CONFIG_GENERATE_ACPI_TABLES == 1 - pm_base = pci_read_config16(dev, 0x58) & 0xff00; - printk(BIOS_DEBUG, "pm_base: 0x%04x\n",pm_base); -#endif - -} - -static void acpi_read_resources(device_t dev) -{ - struct resource *resource; - - /* Handle the generic bars */ - pci_dev_read_resources(dev); - - /* Add the ACPI/SMBUS bar */ - resource = new_resource(dev, 0x58); - resource->base = 0; - resource->size = 256; - resource->align = log2(256); - resource->gran = log2(256); - resource->limit = 65536; - resource->flags = IORESOURCE_IO; - resource->index = 0x58; -} - -static void acpi_enable_resources(device_t dev) -{ - uint8_t byte; - /* Enable the generic pci resources */ - pci_dev_enable_resources(dev); - - /* Enable the ACPI/SMBUS Bar */ - byte = pci_read_config8(dev, 0x41); - byte |= (1 << 7); - pci_write_config8(dev, 0x41, byte); - - /* Set the class code */ - pci_write_config32(dev, 0x60, 0x06800000); - -} - -static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) -{ - pci_write_config32(dev, 0x7c, - ((device & 0xffff) << 16) | (vendor & 0xffff)); -} - -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 struct pci_operations lops_pci = { - .set_subsystem = lpci_set_subsystem, -}; - -static struct device_operations acpi_ops = { - .read_resources = acpi_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = acpi_enable_resources, - .init = acpi_init, - .scan_bus = scan_static_bus, - /* We don't need amd8111_enable, chip ops takes care of it. - * It could be useful if these devices were not - * enabled by default. - */ -// .enable = amd8111_enable, - .ops_pci = &lops_pci, - .ops_smbus_bus = &lops_smbus_bus, -}; - -static const struct pci_driver acpi_driver __pci_driver = { - .ops = &acpi_ops, - .vendor = PCI_VENDOR_ID_AMD, - .device = PCI_DEVICE_ID_AMD_8111_ACPI, -}; - diff --git a/src/southbridge/amd/amd8111/amd8111_early_ctrl.c b/src/southbridge/amd/amd8111/amd8111_early_ctrl.c deleted file mode 100644 index ece99ed40a..0000000000 --- a/src/southbridge/amd/amd8111/amd8111_early_ctrl.c +++ /dev/null @@ -1,83 +0,0 @@ -#include "amd8111.h" -#include - -/* by yhlu 2005.10 */ -static unsigned get_sbdn(unsigned bus) -{ - device_t dev; - - /* Find the device. - * There can only be one 8111 on a hypertransport chain/bus. - */ - dev = pci_locate_device_on_bus( - PCI_ID(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_PCI), - bus); - - return (dev>>15) & 0x1f; - -} - -static void enable_cf9_x(unsigned sbbusn, unsigned sbdn) -{ - device_t dev; - uint8_t byte; - - dev = PCI_DEV(sbbusn, sbdn+1, 3); //ACPI - /* enable cf9 */ - byte = pci_read_config8(dev, 0x41); - byte |= (1<<6) | (1<<5); - pci_write_config8(dev, 0x41, byte); -} - -static void enable_cf9(void) -{ - unsigned sblk = get_sblk(); - unsigned sbbusn = get_sbbusn(sblk); - unsigned sbdn = get_sbdn(sbbusn); - - enable_cf9_x(sbbusn, sbdn); -} - -void hard_reset(void) -{ - set_bios_reset(); - /* reset */ - enable_cf9(); - outb(0x0e, 0x0cf9); // make sure cf9 is enabled -} - -void enable_fid_change_on_sb(unsigned sbbusn, unsigned sbdn) -{ - device_t dev; - - dev = PCI_DEV(sbbusn, sbdn+1, 3); // ACPI - - pci_write_config8(dev, 0x74, 4); - - /* set VFSMAF ( VID/FID System Management Action Field) to 2 */ - pci_write_config32(dev, 0x70, 2<<12); - -} - -static void soft_reset_x(unsigned sbbusn, unsigned sbdn) -{ - device_t dev; - - dev = PCI_DEV(sbbusn, sbdn+1, 0); //ISA - - /* Reset */ - set_bios_reset(); - pci_write_config8(dev, 0x47, 1); - -} - -void soft_reset(void) -{ - - unsigned sblk = get_sblk(); - unsigned sbbusn = get_sbbusn(sblk); - unsigned sbdn = get_sbdn(sbbusn); - - return soft_reset_x(sbbusn, sbdn); - -} diff --git a/src/southbridge/amd/amd8111/amd8111_early_smbus.c b/src/southbridge/amd/amd8111/amd8111_early_smbus.c deleted file mode 100644 index e6d70847ea..0000000000 --- a/src/southbridge/amd/amd8111/amd8111_early_smbus.c +++ /dev/null @@ -1,48 +0,0 @@ -#include "amd8111_smbus.h" - -#define SMBUS_IO_BASE 0x0f00 - -static void enable_smbus(void) -{ - device_t dev; - uint8_t enable; - - dev = pci_locate_device(PCI_ID(0x1022, 0x746b), 0); - if (dev == PCI_DEV_INVALID) { - die("SMBUS controller not found\n"); - } - - pci_write_config32(dev, 0x58, SMBUS_IO_BASE | 1); - enable = pci_read_config8(dev, 0x41); - pci_write_config8(dev, 0x41, enable | (1 << 7)); - - /* check that we can see the smbus controller I/O. */ - if (inw(SMBUS_IO_BASE)==0xFF){ - die("SMBUS controller I/O not found\n"); - } - - /* clear any lingering errors, so the transaction will run */ - outw(inw(SMBUS_IO_BASE + SMBGSTATUS), SMBUS_IO_BASE + SMBGSTATUS); - print_spew("SMBus controller enabled\n"); -} - -static inline int smbus_recv_byte(unsigned device) -{ - return do_smbus_recv_byte(SMBUS_IO_BASE, device); -} - -static inline int smbus_send_byte(unsigned device, unsigned char val) -{ - return do_smbus_send_byte(SMBUS_IO_BASE, device, val); -} - -static inline int smbus_read_byte(unsigned device, unsigned address) -{ - return do_smbus_read_byte(SMBUS_IO_BASE, device, address); -} - -static inline int smbus_write_byte(unsigned device, unsigned address, unsigned char val) -{ - return do_smbus_write_byte(SMBUS_IO_BASE, device, address, val); -} - diff --git a/src/southbridge/amd/amd8111/amd8111_enable_rom.c b/src/southbridge/amd/amd8111/amd8111_enable_rom.c deleted file mode 100644 index 3e73112b47..0000000000 --- a/src/southbridge/amd/amd8111/amd8111_enable_rom.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2003 Linux Networx - * (Written by Eric Biederman for Linux Networx) - * - * 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 -#include -#include -#include - -/* Enable 5MB ROM access at 0xFFB00000 - 0xFFFFFFFF. */ -static void amd8111_enable_rom(void) -{ - u8 byte; - device_t dev; - - dev = pci_io_locate_device(PCI_ID(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_AMD_8111_ISA), 0); - - /* Note: The 0xFFFF0000 - 0xFFFFFFFF range is always enabled. */ - - /* Set the 5MB enable bits. */ - byte = pci_io_read_config8(dev, 0x43); - byte |= (1 << 7); /* Enable 0xFFC00000-0xFFFFFFFF (4MB). */ - byte |= (1 << 6); /* Enable 0xFFB00000-0xFFBFFFFF (1MB). */ - pci_io_write_config8(dev, 0x43, byte); -} diff --git a/src/southbridge/amd/amd8111/amd8111_ide.c b/src/southbridge/amd/amd8111/amd8111_ide.c deleted file mode 100644 index 3299875187..0000000000 --- a/src/southbridge/amd/amd8111/amd8111_ide.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include -#include -#include -#include -#include "amd8111.h" - -static void ide_init(struct device *dev) -{ - struct southbridge_amd_amd8111_config *conf; - /* Enable ide devices so the linux ide driver will work */ - uint16_t word; - uint8_t byte; - conf = dev->chip_info; - - word = pci_read_config16(dev, 0x40); - /* Ensure prefetch is disabled */ - word &= ~((1 << 15) | (1 << 13)); - if (conf->ide1_enable) { - /* Enable secondary ide interface */ - word |= (1<<0); - printk(BIOS_DEBUG, "IDE1 "); - } - if (conf->ide0_enable) { - /* Enable primary ide interface */ - word |= (1<<1); - printk(BIOS_DEBUG, "IDE0 "); - } - - word |= (1<<12); - word |= (1<<14); - - pci_write_config16(dev, 0x40, word); - - - byte = 0x20 ; // Latency: 64-->32 - pci_write_config8(dev, 0xd, byte); - - word = 0x0f; - pci_write_config16(dev, 0x42, word); -} - -static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) -{ - pci_write_config32(dev, 0x70, - ((device & 0xffff) << 16) | (vendor & 0xffff)); -} -static struct pci_operations lops_pci = { - .set_subsystem = lpci_set_subsystem, -}; -static struct device_operations ide_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = ide_init, - .scan_bus = 0, - .enable = amd8111_enable, - .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_AMD_8111_IDE, -}; - diff --git a/src/southbridge/amd/amd8111/amd8111_lpc.c b/src/southbridge/amd/amd8111/amd8111_lpc.c deleted file mode 100644 index e9bd5fc42b..0000000000 --- a/src/southbridge/amd/amd8111/amd8111_lpc.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * (C) 2003 Linux Networx, SuSE Linux AG - * 2006.1 yhlu add dest apicid for IRQ0 - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "amd8111.h" - -#define NMI_OFF 0 - -static void enable_hpet(struct device *dev) -{ - unsigned long hpet_address; - - pci_write_config32(dev,0xa0, 0xfed00001); - hpet_address = pci_read_config32(dev,0xa0)& 0xfffffffe; - printk(BIOS_DEBUG, "enabling HPET @0x%lx\n", hpet_address); - -} - -static void lpc_init(struct device *dev) -{ - uint8_t byte; - int nmi_option; - - /* IO APIC initialization */ - byte = pci_read_config8(dev, 0x4B); - byte |= 1; - pci_write_config8(dev, 0x4B, byte); - /* Don't rename IO APIC */ - setup_ioapic(IO_APIC_ADDR, 0); - - /* posted memory write enable */ - byte = pci_read_config8(dev, 0x46); - pci_write_config8(dev, 0x46, byte | (1<<0)); - - /* Enable 5Mib Rom window */ - byte = pci_read_config8(dev, 0x43); - byte |= 0xc0; - pci_write_config8(dev, 0x43, byte); - - /* Enable Port 92 fast reset */ - byte = pci_read_config8(dev, 0x41); - byte |= (1 << 5); - pci_write_config8(dev, 0x41, byte); - - /* Enable Error reporting */ - /* Set up sync flood detected */ - byte = pci_read_config8(dev, 0x47); - byte |= (1 << 1); - pci_write_config8(dev, 0x47, byte); - - /* Set up NMI on errors */ - byte = pci_read_config8(dev, 0x40); - byte |= (1 << 1); /* clear PW2LPC error */ - byte |= (1 << 6); /* clear LPCERR */ - pci_write_config8(dev, 0x40, byte); - nmi_option = NMI_OFF; - get_option(&nmi_option, "nmi"); - if (nmi_option) { - byte |= (1 << 7); /* set NMI */ - pci_write_config8(dev, 0x40, byte); - } - - /* Initialize the real time clock */ - rtc_init(0); - - /* Initialize isa dma */ - isa_dma_init(); - - /* Initialize the High Precision Event Timers */ - enable_hpet(dev); -} - -static void amd8111_lpc_read_resources(device_t dev) -{ - struct resource *res; - - /* Get the normal PCI resources of this device. */ - pci_dev_read_resources(dev); - - /* 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 = IO_APIC_ADDR; - res->size = 0x00001000; - res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; -} - -static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) -{ - pci_write_config32(dev, 0x70, - ((device & 0xffff) << 16) | (vendor & 0xffff)); -} - -static struct pci_operations lops_pci = { - .set_subsystem = lpci_set_subsystem, -}; - -static struct device_operations lpc_ops = { - .read_resources = amd8111_lpc_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = lpc_init, - .scan_bus = scan_static_bus, - .enable = amd8111_enable, - .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_AMD_8111_ISA, -}; diff --git a/src/southbridge/amd/amd8111/amd8111_nic.c b/src/southbridge/amd/amd8111/amd8111_nic.c deleted file mode 100644 index 4ab7212eda..0000000000 --- a/src/southbridge/amd/amd8111/amd8111_nic.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * (C) 2003 Linux Networx - */ -#include -#include -#include -#include -#include -#include -#include -#include "amd8111.h" - - -#define CMD3 0x54 - -typedef enum { - VAL3 = (1 << 31), /* VAL bit for byte 3 */ - VAL2 = (1 << 23), /* VAL bit for byte 2 */ - VAL1 = (1 << 15), /* VAL bit for byte 1 */ - VAL0 = (1 << 7), /* VAL bit for byte 0 */ -}VAL_BITS; - -typedef enum { - /* VAL3 */ - ASF_INIT_DONE_ALIAS = (1 << 29), - /* VAL2 */ - JUMBO = (1 << 21), - VSIZE = (1 << 20), - VLONLY = (1 << 19), - VL_TAG_DEL = (1 << 18), - /* VAL1 */ - EN_PMGR = (1 << 14), - INTLEVEL = (1 << 13), - FORCE_FULL_DUPLEX = (1 << 12), - FORCE_LINK_STATUS = (1 << 11), - APEP = (1 << 10), - MPPLBA = (1 << 9), - /* VAL0 */ - RESET_PHY_PULSE = (1 << 2), - RESET_PHY = (1 << 1), - PHY_RST_POL = (1 << 0), -}CMD3_BITS; - -static void nic_init(struct device *dev) -{ - struct southbridge_amd_amd8111_config *conf; - struct resource *resource; - unsigned long mmio; - - conf = dev->chip_info; - resource = find_resource(dev, PCI_BASE_ADDRESS_0); - mmio = resource->base; - - /* Hard Reset PHY */ - printk(BIOS_DEBUG, "Reseting PHY... "); - if (conf->phy_lowreset) { - write32((mmio + CMD3), VAL0 | PHY_RST_POL | RESET_PHY); - } else { - write32((mmio + CMD3), VAL0 | RESET_PHY); - } - mdelay(15); - write32((mmio + CMD3), RESET_PHY); - printk(BIOS_DEBUG, "Done\n"); -} - -static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) -{ - pci_write_config32(dev, 0xc8, - ((device & 0xffff) << 16) | (vendor & 0xffff)); -} - -static struct pci_operations lops_pci = { - .set_subsystem = lpci_set_subsystem, -}; - -static struct device_operations nic_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = nic_init, - .scan_bus = 0, - .enable = amd8111_enable, - .ops_pci = &lops_pci, -}; - -static const struct pci_driver nic_driver __pci_driver = { - .ops = &nic_ops, - .vendor = PCI_VENDOR_ID_AMD, - .device = PCI_DEVICE_ID_AMD_8111_NIC, -}; diff --git a/src/southbridge/amd/amd8111/amd8111_pci.c b/src/southbridge/amd/amd8111/amd8111_pci.c deleted file mode 100644 index 9e7724980f..0000000000 --- a/src/southbridge/amd/amd8111/amd8111_pci.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include -#include -#include -#include -#include "amd8111.h" - -static void pci_init(struct device *dev) -{ - - /* Enable pci error detecting */ - uint32_t dword; - - /* System error enable */ - dword = pci_read_config32(dev, 0x04); - dword |= (1<<8); /* System error enable */ - dword |= (7<<28); /* Clear possible errors */ - pci_write_config32(dev, 0x04, dword); - - /* System,Parity,timer,and abort error enable */ - dword = pci_read_config32(dev, 0x3c); - dword |= (1<<16); /* Parity */ - dword |= (1<<17); /* System */ - dword |= (1<<21); /* Master abort */ -// dword &= ~(1<<21); /* Master abort */ -// dword |= (1<<27); /* Discard timer */ - dword &= ~(1<<27); /* Discard timer */ - dword |= (1<<26); /* DTSTAT error clear */ - pci_write_config32(dev, 0x3c, dword); - - /* CRC flood enable */ - dword = pci_read_config32(dev, 0xc4); - dword |= (1<<1); /* CRC Flood enable */ - dword |= (1<<8); /* Clear any CRC errors */ - dword |= (1<<4); /* Clear any LKFAIL errors */ - pci_write_config32(dev, 0xc4, dword); - - /* Clear possible errors */ - dword = pci_read_config32(dev, 0x1c); - dword |= (1<<27); /* STA */ - dword |= (1<<28); /* RTA */ - dword |= (1<<29); /* RMA */ - dword |= (1<<30); /* RSE */ - dword |= (1<<31); /* DPE */ - dword |= (1<<24); /* MDPE */ - pci_write_config32(dev, 0x1c, dword); -} - -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, - /* PCI Subordinate bus reset is not implemented */ - .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_AMD_8111_PCI, -}; - diff --git a/src/southbridge/amd/amd8111/amd8111_reset.c b/src/southbridge/amd/amd8111/amd8111_reset.c deleted file mode 100644 index c96e898aea..0000000000 --- a/src/southbridge/amd/amd8111/amd8111_reset.c +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include -#include - -#define PCI_DEV(BUS, DEV, FN) ( \ - (((BUS) & 0xFFF) << 20) | \ - (((DEV) & 0x1F) << 15) | \ - (((FN) & 0x7) << 12)) - -#define PCI_ID(VENDOR_ID, DEVICE_ID) \ - ((((DEVICE_ID) & 0xFFFF) << 16) | ((VENDOR_ID) & 0xFFFF)) - -typedef unsigned device_t; - -static void pci_write_config8(device_t dev, unsigned where, unsigned char value) -{ - unsigned addr; - addr = (dev>>4) | where; - outl(0x80000000 | (addr & ~3), 0xCF8); - outb(value, 0xCFC + (addr & 3)); -} - -static void pci_write_config32(device_t dev, unsigned where, unsigned value) -{ - unsigned addr; - addr = (dev>>4) | where; - outl(0x80000000 | (addr & ~3), 0xCF8); - outl(value, 0xCFC); -} - -static unsigned pci_read_config32(device_t dev, unsigned where) -{ - unsigned addr; - addr = (dev>>4) | where; - outl(0x80000000 | (addr & ~3), 0xCF8); - return inl(0xCFC); -} - -#define PCI_DEV_INVALID (0xffffffffU) -static device_t pci_locate_device_on_bus(unsigned pci_id, unsigned bus) -{ - device_t dev, last; - dev = PCI_DEV(bus, 0, 0); - last = PCI_DEV(bus, 31, 7); - for(; dev <= last; dev += PCI_DEV(0,0,1)) { - unsigned int id; - id = pci_read_config32(dev, 0); - if (id == pci_id) { - return dev; - } - } - return PCI_DEV_INVALID; -} - -#include "../../../northbridge/amd/amdk8/reset_test.c" - - -void hard_reset(void) -{ - device_t dev; - unsigned bus; - unsigned node = 0; - unsigned link = get_sblk(); - - /* Find the device. - * There can only be one 8111 on a hypertransport chain/bus. - */ - bus = node_link_to_bus(node, link); - dev = pci_locate_device_on_bus( - PCI_ID(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_ISA), - bus); - - /* Reset */ - set_bios_reset(); - pci_write_config8(dev, 0x47, 1); -} diff --git a/src/southbridge/amd/amd8111/amd8111_smbus.c b/src/southbridge/amd/amd8111/amd8111_smbus.c deleted file mode 100644 index 0a0c58dce3..0000000000 --- a/src/southbridge/amd/amd8111/amd8111_smbus.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * (C) 2004 Linux Networx - */ -#include -#include -#include -#include -#include -#include -#include -#include "amd8111.h" - - -static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) -{ - pci_write_config32(dev, 0x44, - ((device & 0xffff) << 16) | (vendor & 0xffff)); -} - -static struct smbus_bus_operations lops_smbus_bus = { - /* I haven't seen the 2.0 SMBUS controller used yet. */ -}; -static struct pci_operations lops_pci = { - .set_subsystem = lpci_set_subsystem, -}; -static struct device_operations smbus_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = 0, - .scan_bus = scan_static_bus, - .enable = amd8111_enable, - .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_AMD_8111_SMB, -}; diff --git a/src/southbridge/amd/amd8111/amd8111_usb.c b/src/southbridge/amd/amd8111/amd8111_usb.c deleted file mode 100644 index 13dccf435b..0000000000 --- a/src/southbridge/amd/amd8111/amd8111_usb.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * (C) 2004 Linux Networx - */ -#include -#include -#include -#include -#include -#include -#include "amd8111.h" - - -static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) -{ - pci_write_config32(dev, 0x70, - ((device & 0xffff) << 16) | (vendor & 0xffff)); -} - -static struct pci_operations lops_pci = { - .set_subsystem = lpci_set_subsystem, -}; - -static struct device_operations usb_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = 0, - .scan_bus = scan_static_bus, -// .enable = amd8111_enable, - .ops_pci = &lops_pci, -}; - -static const struct pci_driver usb_driver __pci_driver = { - .ops = &usb_ops, - .vendor = PCI_VENDOR_ID_AMD, - .device = PCI_DEVICE_ID_AMD_8111_USB, -}; diff --git a/src/southbridge/amd/amd8111/amd8111_usb2.c b/src/southbridge/amd/amd8111/amd8111_usb2.c deleted file mode 100644 index 89115c3bbe..0000000000 --- a/src/southbridge/amd/amd8111/amd8111_usb2.c +++ /dev/null @@ -1,45 +0,0 @@ -//2003 Copywright Tyan - -#include -#include -#include -#include -#include -#include "amd8111.h" - -#if 0 - -static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) -{ - pci_write_config32(dev, 0x70, - ((device & 0xffff) << 16) | (vendor & 0xffff)); -} - -static struct pci_operations lops_pci = { - .set_subsystem = lpci_set_subsystem, -}; - -#endif - -static void amd8111_usb2_enable(device_t dev) -{ - // Due to buggy USB2 we force it to disable. - dev->enabled = 0; - amd8111_enable(dev); - printk(BIOS_DEBUG, "USB2 disabled.\n"); -} - -static struct device_operations usb2_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .scan_bus = 0, - .enable = amd8111_usb2_enable, - // .ops_pci = &lops_pci, -}; - -static const struct pci_driver usb2_driver __pci_driver = { - .ops = &usb2_ops, - .vendor = PCI_VENDOR_ID_AMD, - .device = PCI_DEVICE_ID_AMD_8111_USB2, -}; diff --git a/src/southbridge/amd/amd8111/bootblock.c b/src/southbridge/amd/amd8111/bootblock.c index 695f49898b..a11d1d30f4 100644 --- a/src/southbridge/amd/amd8111/bootblock.c +++ b/src/southbridge/amd/amd8111/bootblock.c @@ -1,4 +1,4 @@ -#include "southbridge/amd/amd8111/amd8111_enable_rom.c" +#include "southbridge/amd/amd8111/enable_rom.c" static void bootblock_southbridge_init(void) { diff --git a/src/southbridge/amd/amd8111/early_ctrl.c b/src/southbridge/amd/amd8111/early_ctrl.c new file mode 100644 index 0000000000..ece99ed40a --- /dev/null +++ b/src/southbridge/amd/amd8111/early_ctrl.c @@ -0,0 +1,83 @@ +#include "amd8111.h" +#include + +/* by yhlu 2005.10 */ +static unsigned get_sbdn(unsigned bus) +{ + device_t dev; + + /* Find the device. + * There can only be one 8111 on a hypertransport chain/bus. + */ + dev = pci_locate_device_on_bus( + PCI_ID(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_PCI), + bus); + + return (dev>>15) & 0x1f; + +} + +static void enable_cf9_x(unsigned sbbusn, unsigned sbdn) +{ + device_t dev; + uint8_t byte; + + dev = PCI_DEV(sbbusn, sbdn+1, 3); //ACPI + /* enable cf9 */ + byte = pci_read_config8(dev, 0x41); + byte |= (1<<6) | (1<<5); + pci_write_config8(dev, 0x41, byte); +} + +static void enable_cf9(void) +{ + unsigned sblk = get_sblk(); + unsigned sbbusn = get_sbbusn(sblk); + unsigned sbdn = get_sbdn(sbbusn); + + enable_cf9_x(sbbusn, sbdn); +} + +void hard_reset(void) +{ + set_bios_reset(); + /* reset */ + enable_cf9(); + outb(0x0e, 0x0cf9); // make sure cf9 is enabled +} + +void enable_fid_change_on_sb(unsigned sbbusn, unsigned sbdn) +{ + device_t dev; + + dev = PCI_DEV(sbbusn, sbdn+1, 3); // ACPI + + pci_write_config8(dev, 0x74, 4); + + /* set VFSMAF ( VID/FID System Management Action Field) to 2 */ + pci_write_config32(dev, 0x70, 2<<12); + +} + +static void soft_reset_x(unsigned sbbusn, unsigned sbdn) +{ + device_t dev; + + dev = PCI_DEV(sbbusn, sbdn+1, 0); //ISA + + /* Reset */ + set_bios_reset(); + pci_write_config8(dev, 0x47, 1); + +} + +void soft_reset(void) +{ + + unsigned sblk = get_sblk(); + unsigned sbbusn = get_sbbusn(sblk); + unsigned sbdn = get_sbdn(sbbusn); + + return soft_reset_x(sbbusn, sbdn); + +} diff --git a/src/southbridge/amd/amd8111/early_smbus.c b/src/southbridge/amd/amd8111/early_smbus.c new file mode 100644 index 0000000000..e6d70847ea --- /dev/null +++ b/src/southbridge/amd/amd8111/early_smbus.c @@ -0,0 +1,48 @@ +#include "amd8111_smbus.h" + +#define SMBUS_IO_BASE 0x0f00 + +static void enable_smbus(void) +{ + device_t dev; + uint8_t enable; + + dev = pci_locate_device(PCI_ID(0x1022, 0x746b), 0); + if (dev == PCI_DEV_INVALID) { + die("SMBUS controller not found\n"); + } + + pci_write_config32(dev, 0x58, SMBUS_IO_BASE | 1); + enable = pci_read_config8(dev, 0x41); + pci_write_config8(dev, 0x41, enable | (1 << 7)); + + /* check that we can see the smbus controller I/O. */ + if (inw(SMBUS_IO_BASE)==0xFF){ + die("SMBUS controller I/O not found\n"); + } + + /* clear any lingering errors, so the transaction will run */ + outw(inw(SMBUS_IO_BASE + SMBGSTATUS), SMBUS_IO_BASE + SMBGSTATUS); + print_spew("SMBus controller enabled\n"); +} + +static inline int smbus_recv_byte(unsigned device) +{ + return do_smbus_recv_byte(SMBUS_IO_BASE, device); +} + +static inline int smbus_send_byte(unsigned device, unsigned char val) +{ + return do_smbus_send_byte(SMBUS_IO_BASE, device, val); +} + +static inline int smbus_read_byte(unsigned device, unsigned address) +{ + return do_smbus_read_byte(SMBUS_IO_BASE, device, address); +} + +static inline int smbus_write_byte(unsigned device, unsigned address, unsigned char val) +{ + return do_smbus_write_byte(SMBUS_IO_BASE, device, address, val); +} + diff --git a/src/southbridge/amd/amd8111/enable_rom.c b/src/southbridge/amd/amd8111/enable_rom.c new file mode 100644 index 0000000000..3e73112b47 --- /dev/null +++ b/src/southbridge/amd/amd8111/enable_rom.c @@ -0,0 +1,42 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2003 Linux Networx + * (Written by Eric Biederman for Linux Networx) + * + * 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 +#include +#include +#include + +/* Enable 5MB ROM access at 0xFFB00000 - 0xFFFFFFFF. */ +static void amd8111_enable_rom(void) +{ + u8 byte; + device_t dev; + + dev = pci_io_locate_device(PCI_ID(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_8111_ISA), 0); + + /* Note: The 0xFFFF0000 - 0xFFFFFFFF range is always enabled. */ + + /* Set the 5MB enable bits. */ + byte = pci_io_read_config8(dev, 0x43); + byte |= (1 << 7); /* Enable 0xFFC00000-0xFFFFFFFF (4MB). */ + byte |= (1 << 6); /* Enable 0xFFB00000-0xFFBFFFFF (1MB). */ + pci_io_write_config8(dev, 0x43, byte); +} diff --git a/src/southbridge/amd/amd8111/ide.c b/src/southbridge/amd/amd8111/ide.c new file mode 100644 index 0000000000..3299875187 --- /dev/null +++ b/src/southbridge/amd/amd8111/ide.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include +#include "amd8111.h" + +static void ide_init(struct device *dev) +{ + struct southbridge_amd_amd8111_config *conf; + /* Enable ide devices so the linux ide driver will work */ + uint16_t word; + uint8_t byte; + conf = dev->chip_info; + + word = pci_read_config16(dev, 0x40); + /* Ensure prefetch is disabled */ + word &= ~((1 << 15) | (1 << 13)); + if (conf->ide1_enable) { + /* Enable secondary ide interface */ + word |= (1<<0); + printk(BIOS_DEBUG, "IDE1 "); + } + if (conf->ide0_enable) { + /* Enable primary ide interface */ + word |= (1<<1); + printk(BIOS_DEBUG, "IDE0 "); + } + + word |= (1<<12); + word |= (1<<14); + + pci_write_config16(dev, 0x40, word); + + + byte = 0x20 ; // Latency: 64-->32 + pci_write_config8(dev, 0xd, byte); + + word = 0x0f; + pci_write_config16(dev, 0x42, word); +} + +static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + pci_write_config32(dev, 0x70, + ((device & 0xffff) << 16) | (vendor & 0xffff)); +} +static struct pci_operations lops_pci = { + .set_subsystem = lpci_set_subsystem, +}; +static struct device_operations ide_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = ide_init, + .scan_bus = 0, + .enable = amd8111_enable, + .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_AMD_8111_IDE, +}; + diff --git a/src/southbridge/amd/amd8111/lpc.c b/src/southbridge/amd/amd8111/lpc.c new file mode 100644 index 0000000000..e9bd5fc42b --- /dev/null +++ b/src/southbridge/amd/amd8111/lpc.c @@ -0,0 +1,133 @@ +/* + * (C) 2003 Linux Networx, SuSE Linux AG + * 2006.1 yhlu add dest apicid for IRQ0 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "amd8111.h" + +#define NMI_OFF 0 + +static void enable_hpet(struct device *dev) +{ + unsigned long hpet_address; + + pci_write_config32(dev,0xa0, 0xfed00001); + hpet_address = pci_read_config32(dev,0xa0)& 0xfffffffe; + printk(BIOS_DEBUG, "enabling HPET @0x%lx\n", hpet_address); + +} + +static void lpc_init(struct device *dev) +{ + uint8_t byte; + int nmi_option; + + /* IO APIC initialization */ + byte = pci_read_config8(dev, 0x4B); + byte |= 1; + pci_write_config8(dev, 0x4B, byte); + /* Don't rename IO APIC */ + setup_ioapic(IO_APIC_ADDR, 0); + + /* posted memory write enable */ + byte = pci_read_config8(dev, 0x46); + pci_write_config8(dev, 0x46, byte | (1<<0)); + + /* Enable 5Mib Rom window */ + byte = pci_read_config8(dev, 0x43); + byte |= 0xc0; + pci_write_config8(dev, 0x43, byte); + + /* Enable Port 92 fast reset */ + byte = pci_read_config8(dev, 0x41); + byte |= (1 << 5); + pci_write_config8(dev, 0x41, byte); + + /* Enable Error reporting */ + /* Set up sync flood detected */ + byte = pci_read_config8(dev, 0x47); + byte |= (1 << 1); + pci_write_config8(dev, 0x47, byte); + + /* Set up NMI on errors */ + byte = pci_read_config8(dev, 0x40); + byte |= (1 << 1); /* clear PW2LPC error */ + byte |= (1 << 6); /* clear LPCERR */ + pci_write_config8(dev, 0x40, byte); + nmi_option = NMI_OFF; + get_option(&nmi_option, "nmi"); + if (nmi_option) { + byte |= (1 << 7); /* set NMI */ + pci_write_config8(dev, 0x40, byte); + } + + /* Initialize the real time clock */ + rtc_init(0); + + /* Initialize isa dma */ + isa_dma_init(); + + /* Initialize the High Precision Event Timers */ + enable_hpet(dev); +} + +static void amd8111_lpc_read_resources(device_t dev) +{ + struct resource *res; + + /* Get the normal PCI resources of this device. */ + pci_dev_read_resources(dev); + + /* 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 = IO_APIC_ADDR; + res->size = 0x00001000; + res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; +} + +static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + pci_write_config32(dev, 0x70, + ((device & 0xffff) << 16) | (vendor & 0xffff)); +} + +static struct pci_operations lops_pci = { + .set_subsystem = lpci_set_subsystem, +}; + +static struct device_operations lpc_ops = { + .read_resources = amd8111_lpc_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = lpc_init, + .scan_bus = scan_static_bus, + .enable = amd8111_enable, + .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_AMD_8111_ISA, +}; diff --git a/src/southbridge/amd/amd8111/nic.c b/src/southbridge/amd/amd8111/nic.c new file mode 100644 index 0000000000..4ab7212eda --- /dev/null +++ b/src/southbridge/amd/amd8111/nic.c @@ -0,0 +1,90 @@ +/* + * (C) 2003 Linux Networx + */ +#include +#include +#include +#include +#include +#include +#include +#include "amd8111.h" + + +#define CMD3 0x54 + +typedef enum { + VAL3 = (1 << 31), /* VAL bit for byte 3 */ + VAL2 = (1 << 23), /* VAL bit for byte 2 */ + VAL1 = (1 << 15), /* VAL bit for byte 1 */ + VAL0 = (1 << 7), /* VAL bit for byte 0 */ +}VAL_BITS; + +typedef enum { + /* VAL3 */ + ASF_INIT_DONE_ALIAS = (1 << 29), + /* VAL2 */ + JUMBO = (1 << 21), + VSIZE = (1 << 20), + VLONLY = (1 << 19), + VL_TAG_DEL = (1 << 18), + /* VAL1 */ + EN_PMGR = (1 << 14), + INTLEVEL = (1 << 13), + FORCE_FULL_DUPLEX = (1 << 12), + FORCE_LINK_STATUS = (1 << 11), + APEP = (1 << 10), + MPPLBA = (1 << 9), + /* VAL0 */ + RESET_PHY_PULSE = (1 << 2), + RESET_PHY = (1 << 1), + PHY_RST_POL = (1 << 0), +}CMD3_BITS; + +static void nic_init(struct device *dev) +{ + struct southbridge_amd_amd8111_config *conf; + struct resource *resource; + unsigned long mmio; + + conf = dev->chip_info; + resource = find_resource(dev, PCI_BASE_ADDRESS_0); + mmio = resource->base; + + /* Hard Reset PHY */ + printk(BIOS_DEBUG, "Reseting PHY... "); + if (conf->phy_lowreset) { + write32((mmio + CMD3), VAL0 | PHY_RST_POL | RESET_PHY); + } else { + write32((mmio + CMD3), VAL0 | RESET_PHY); + } + mdelay(15); + write32((mmio + CMD3), RESET_PHY); + printk(BIOS_DEBUG, "Done\n"); +} + +static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + pci_write_config32(dev, 0xc8, + ((device & 0xffff) << 16) | (vendor & 0xffff)); +} + +static struct pci_operations lops_pci = { + .set_subsystem = lpci_set_subsystem, +}; + +static struct device_operations nic_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = nic_init, + .scan_bus = 0, + .enable = amd8111_enable, + .ops_pci = &lops_pci, +}; + +static const struct pci_driver nic_driver __pci_driver = { + .ops = &nic_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_8111_NIC, +}; diff --git a/src/southbridge/amd/amd8111/pci.c b/src/southbridge/amd/amd8111/pci.c new file mode 100644 index 0000000000..9e7724980f --- /dev/null +++ b/src/southbridge/amd/amd8111/pci.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include "amd8111.h" + +static void pci_init(struct device *dev) +{ + + /* Enable pci error detecting */ + uint32_t dword; + + /* System error enable */ + dword = pci_read_config32(dev, 0x04); + dword |= (1<<8); /* System error enable */ + dword |= (7<<28); /* Clear possible errors */ + pci_write_config32(dev, 0x04, dword); + + /* System,Parity,timer,and abort error enable */ + dword = pci_read_config32(dev, 0x3c); + dword |= (1<<16); /* Parity */ + dword |= (1<<17); /* System */ + dword |= (1<<21); /* Master abort */ +// dword &= ~(1<<21); /* Master abort */ +// dword |= (1<<27); /* Discard timer */ + dword &= ~(1<<27); /* Discard timer */ + dword |= (1<<26); /* DTSTAT error clear */ + pci_write_config32(dev, 0x3c, dword); + + /* CRC flood enable */ + dword = pci_read_config32(dev, 0xc4); + dword |= (1<<1); /* CRC Flood enable */ + dword |= (1<<8); /* Clear any CRC errors */ + dword |= (1<<4); /* Clear any LKFAIL errors */ + pci_write_config32(dev, 0xc4, dword); + + /* Clear possible errors */ + dword = pci_read_config32(dev, 0x1c); + dword |= (1<<27); /* STA */ + dword |= (1<<28); /* RTA */ + dword |= (1<<29); /* RMA */ + dword |= (1<<30); /* RSE */ + dword |= (1<<31); /* DPE */ + dword |= (1<<24); /* MDPE */ + pci_write_config32(dev, 0x1c, dword); +} + +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, + /* PCI Subordinate bus reset is not implemented */ + .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_AMD_8111_PCI, +}; + diff --git a/src/southbridge/amd/amd8111/reset.c b/src/southbridge/amd/amd8111/reset.c new file mode 100644 index 0000000000..c96e898aea --- /dev/null +++ b/src/southbridge/amd/amd8111/reset.c @@ -0,0 +1,76 @@ +#include +#include +#include + +#define PCI_DEV(BUS, DEV, FN) ( \ + (((BUS) & 0xFFF) << 20) | \ + (((DEV) & 0x1F) << 15) | \ + (((FN) & 0x7) << 12)) + +#define PCI_ID(VENDOR_ID, DEVICE_ID) \ + ((((DEVICE_ID) & 0xFFFF) << 16) | ((VENDOR_ID) & 0xFFFF)) + +typedef unsigned device_t; + +static void pci_write_config8(device_t dev, unsigned where, unsigned char value) +{ + unsigned addr; + addr = (dev>>4) | where; + outl(0x80000000 | (addr & ~3), 0xCF8); + outb(value, 0xCFC + (addr & 3)); +} + +static void pci_write_config32(device_t dev, unsigned where, unsigned value) +{ + unsigned addr; + addr = (dev>>4) | where; + outl(0x80000000 | (addr & ~3), 0xCF8); + outl(value, 0xCFC); +} + +static unsigned pci_read_config32(device_t dev, unsigned where) +{ + unsigned addr; + addr = (dev>>4) | where; + outl(0x80000000 | (addr & ~3), 0xCF8); + return inl(0xCFC); +} + +#define PCI_DEV_INVALID (0xffffffffU) +static device_t pci_locate_device_on_bus(unsigned pci_id, unsigned bus) +{ + device_t dev, last; + dev = PCI_DEV(bus, 0, 0); + last = PCI_DEV(bus, 31, 7); + for(; dev <= last; dev += PCI_DEV(0,0,1)) { + unsigned int id; + id = pci_read_config32(dev, 0); + if (id == pci_id) { + return dev; + } + } + return PCI_DEV_INVALID; +} + +#include "../../../northbridge/amd/amdk8/reset_test.c" + + +void hard_reset(void) +{ + device_t dev; + unsigned bus; + unsigned node = 0; + unsigned link = get_sblk(); + + /* Find the device. + * There can only be one 8111 on a hypertransport chain/bus. + */ + bus = node_link_to_bus(node, link); + dev = pci_locate_device_on_bus( + PCI_ID(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_ISA), + bus); + + /* Reset */ + set_bios_reset(); + pci_write_config8(dev, 0x47, 1); +} diff --git a/src/southbridge/amd/amd8111/smbus.c b/src/southbridge/amd/amd8111/smbus.c new file mode 100644 index 0000000000..0a0c58dce3 --- /dev/null +++ b/src/southbridge/amd/amd8111/smbus.c @@ -0,0 +1,41 @@ +/* + * (C) 2004 Linux Networx + */ +#include +#include +#include +#include +#include +#include +#include +#include "amd8111.h" + + +static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + pci_write_config32(dev, 0x44, + ((device & 0xffff) << 16) | (vendor & 0xffff)); +} + +static struct smbus_bus_operations lops_smbus_bus = { + /* I haven't seen the 2.0 SMBUS controller used yet. */ +}; +static struct pci_operations lops_pci = { + .set_subsystem = lpci_set_subsystem, +}; +static struct device_operations smbus_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = 0, + .scan_bus = scan_static_bus, + .enable = amd8111_enable, + .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_AMD_8111_SMB, +}; diff --git a/src/southbridge/amd/amd8111/usb.c b/src/southbridge/amd/amd8111/usb.c new file mode 100644 index 0000000000..13dccf435b --- /dev/null +++ b/src/southbridge/amd/amd8111/usb.c @@ -0,0 +1,37 @@ +/* + * (C) 2004 Linux Networx + */ +#include +#include +#include +#include +#include +#include +#include "amd8111.h" + + +static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + pci_write_config32(dev, 0x70, + ((device & 0xffff) << 16) | (vendor & 0xffff)); +} + +static struct pci_operations lops_pci = { + .set_subsystem = lpci_set_subsystem, +}; + +static struct device_operations usb_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = 0, + .scan_bus = scan_static_bus, +// .enable = amd8111_enable, + .ops_pci = &lops_pci, +}; + +static const struct pci_driver usb_driver __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_8111_USB, +}; diff --git a/src/southbridge/amd/amd8111/usb2.c b/src/southbridge/amd/amd8111/usb2.c new file mode 100644 index 0000000000..89115c3bbe --- /dev/null +++ b/src/southbridge/amd/amd8111/usb2.c @@ -0,0 +1,45 @@ +//2003 Copywright Tyan + +#include +#include +#include +#include +#include +#include "amd8111.h" + +#if 0 + +static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + pci_write_config32(dev, 0x70, + ((device & 0xffff) << 16) | (vendor & 0xffff)); +} + +static struct pci_operations lops_pci = { + .set_subsystem = lpci_set_subsystem, +}; + +#endif + +static void amd8111_usb2_enable(device_t dev) +{ + // Due to buggy USB2 we force it to disable. + dev->enabled = 0; + amd8111_enable(dev); + printk(BIOS_DEBUG, "USB2 disabled.\n"); +} + +static struct device_operations usb2_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .scan_bus = 0, + .enable = amd8111_usb2_enable, + // .ops_pci = &lops_pci, +}; + +static const struct pci_driver usb2_driver __pci_driver = { + .ops = &usb2_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_8111_USB2, +}; diff --git a/src/southbridge/amd/amd8131-disable/amd8131_bridge.c b/src/southbridge/amd/amd8131-disable/amd8131_bridge.c deleted file mode 100644 index e90f497d95..0000000000 --- a/src/southbridge/amd/amd8131-disable/amd8131_bridge.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * (C) 2004 Linux Networx - */ -#include -#include -#include -#include -#include -#include - -static void amd8131_bus_read_resources(device_t dev) -{ - return; -} - -static void amd8131_bus_set_resources(device_t dev) -{ -#if 0 - pci_bus_read_resources(dev); -#endif - return; -} - -static void amd8131_bus_enable_resources(device_t dev) -{ -#if 0 - pci_dev_set_resources(dev); -#endif - return; -} - -static void amd8131_bus_init(device_t dev) -{ -#if 0 - pcix_init(dev); -#endif - return; -} - -static unsigned int amd8131_scan_bus(device_t bus, unsigned int max) -{ -#if 0 - max = pcix_scan_bridge(bus, max); -#endif - return max; -} - -static void amd8131_enable(device_t dev) -{ - uint32_t buses; - uint16_t cr; - - /* Clear all status bits and turn off memory, I/O and master enables. */ - pci_write_config16(dev, PCI_COMMAND, 0x0000); - pci_write_config16(dev, PCI_STATUS, 0xffff); - - /* - * Read the existing primary/secondary/subordinate bus - * number configuration. - */ - buses = pci_read_config32(dev, PCI_PRIMARY_BUS); - - /* Configure the bus numbers for this bridge: the configuration - * transactions will not be propagated by the bridge if it is not - * correctly configured. - */ - buses &= 0xff000000; - buses |= (((unsigned int) (dev->bus->secondary) << 0) | - ((unsigned int) (dev->bus->secondary) << 8) | - ((unsigned int) (dev->bus->secondary) << 16)); - pci_write_config32(dev, PCI_PRIMARY_BUS, buses); -} - -static struct device_operations pcix_ops = { - .read_resources = amd8131_bus_read_resources, - .set_resources = amd8131_bus_set_resources, - .enable_resources = amd8131_bus_enable_resources, - .init = amd8131_bus_init, - .scan_bus = 0, - .enable = amd8131_enable, -}; - -static const struct pci_driver pcix_driver __pci_driver = { - .ops = &pcix_ops, - .vendor = PCI_VENDOR_ID_AMD, - .device = 0x7450, -}; - - -static void ioapic_enable(device_t dev) -{ - uint32_t value; - value = pci_read_config32(dev, 0x44); - if (dev->enabled) { - value |= ((1 << 1) | (1 << 0)); - } else { - value &= ~((1 << 1) | (1 << 0)); - } - pci_write_config32(dev, 0x44, value); -} - -static struct device_operations ioapic_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = 0, - .scan_bus = 0, - .enable = ioapic_enable, -}; - -static const struct pci_driver ioapic_driver __pci_driver = { - .ops = &ioapic_ops, - .vendor = PCI_VENDOR_ID_AMD, - .device = 0x7451, - -}; diff --git a/src/southbridge/amd/amd8131-disable/bridge.c b/src/southbridge/amd/amd8131-disable/bridge.c new file mode 100644 index 0000000000..e90f497d95 --- /dev/null +++ b/src/southbridge/amd/amd8131-disable/bridge.c @@ -0,0 +1,116 @@ +/* + * (C) 2004 Linux Networx + */ +#include +#include +#include +#include +#include +#include + +static void amd8131_bus_read_resources(device_t dev) +{ + return; +} + +static void amd8131_bus_set_resources(device_t dev) +{ +#if 0 + pci_bus_read_resources(dev); +#endif + return; +} + +static void amd8131_bus_enable_resources(device_t dev) +{ +#if 0 + pci_dev_set_resources(dev); +#endif + return; +} + +static void amd8131_bus_init(device_t dev) +{ +#if 0 + pcix_init(dev); +#endif + return; +} + +static unsigned int amd8131_scan_bus(device_t bus, unsigned int max) +{ +#if 0 + max = pcix_scan_bridge(bus, max); +#endif + return max; +} + +static void amd8131_enable(device_t dev) +{ + uint32_t buses; + uint16_t cr; + + /* Clear all status bits and turn off memory, I/O and master enables. */ + pci_write_config16(dev, PCI_COMMAND, 0x0000); + pci_write_config16(dev, PCI_STATUS, 0xffff); + + /* + * Read the existing primary/secondary/subordinate bus + * number configuration. + */ + buses = pci_read_config32(dev, PCI_PRIMARY_BUS); + + /* Configure the bus numbers for this bridge: the configuration + * transactions will not be propagated by the bridge if it is not + * correctly configured. + */ + buses &= 0xff000000; + buses |= (((unsigned int) (dev->bus->secondary) << 0) | + ((unsigned int) (dev->bus->secondary) << 8) | + ((unsigned int) (dev->bus->secondary) << 16)); + pci_write_config32(dev, PCI_PRIMARY_BUS, buses); +} + +static struct device_operations pcix_ops = { + .read_resources = amd8131_bus_read_resources, + .set_resources = amd8131_bus_set_resources, + .enable_resources = amd8131_bus_enable_resources, + .init = amd8131_bus_init, + .scan_bus = 0, + .enable = amd8131_enable, +}; + +static const struct pci_driver pcix_driver __pci_driver = { + .ops = &pcix_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = 0x7450, +}; + + +static void ioapic_enable(device_t dev) +{ + uint32_t value; + value = pci_read_config32(dev, 0x44); + if (dev->enabled) { + value |= ((1 << 1) | (1 << 0)); + } else { + value &= ~((1 << 1) | (1 << 0)); + } + pci_write_config32(dev, 0x44, value); +} + +static struct device_operations ioapic_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = 0, + .scan_bus = 0, + .enable = ioapic_enable, +}; + +static const struct pci_driver ioapic_driver __pci_driver = { + .ops = &ioapic_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = 0x7451, + +}; diff --git a/src/southbridge/amd/amd8131/Makefile.inc b/src/southbridge/amd/amd8131/Makefile.inc index 395f0e0e0c..d5b3a5f88e 100644 --- a/src/southbridge/amd/amd8131/Makefile.inc +++ b/src/southbridge/amd/amd8131/Makefile.inc @@ -1 +1 @@ -driver-y += amd8131_bridge.c +driver-y += bridge.c diff --git a/src/southbridge/amd/amd8131/amd8131_bridge.c b/src/southbridge/amd/amd8131/amd8131_bridge.c deleted file mode 100644 index d258450a06..0000000000 --- a/src/southbridge/amd/amd8131/amd8131_bridge.c +++ /dev/null @@ -1,432 +0,0 @@ -/* - * (C) 2003-2004 Linux Networx - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#define NMI_OFF 0 - -#define NPUML 0xD9 /* Non prefetchable upper memory limit */ -#define NPUMB 0xD8 /* Non prefetchable upper memory base */ - -static void amd8131_walk_children(struct bus *bus, - void (*visit)(device_t dev, void *ptr), void *ptr) -{ - device_t child; - for(child = bus->children; child; child = child->sibling) - { - if (child->path.type != DEVICE_PATH_PCI) { - continue; - } - if (child->hdr_type == PCI_HEADER_TYPE_BRIDGE) { - amd8131_walk_children(child->link_list, visit, ptr); - } - visit(child, ptr); - } -} - -struct amd8131_bus_info { - unsigned sstatus; - unsigned rev; - int errata_56; - int master_devices; - int max_func; -}; - -static void amd8131_count_dev(device_t dev, void *ptr) -{ - struct amd8131_bus_info *info = ptr; - /* Don't count pci bridges */ - if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { - info->master_devices++; - } - if (PCI_FUNC(dev->path.pci.devfn) > info->max_func) { - info->max_func = PCI_FUNC(dev->path.pci.devfn); - } -} - - -static void amd8131_pcix_tune_dev(device_t dev, void *ptr) -{ - struct amd8131_bus_info *info = ptr; - unsigned cap; - unsigned status, cmd, orig_cmd; - unsigned max_read, max_tran; - int sib_funcs, sibs; - device_t sib; - - if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL) { - return; - } - cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); - if (!cap) { - return; - } - /* How many siblings does this device have? */ - sibs = info->master_devices - 1; - /* Count how many sibling functions this device has */ - sib_funcs = 0; - for(sib = dev->bus->children; sib; sib = sib->sibling) { - if (sib == dev) { - continue; - } - if (PCI_SLOT(sib->path.pci.devfn) != PCI_SLOT(dev->path.pci.devfn)) { - continue; - } - sib_funcs++; - } - - - printk(BIOS_DEBUG, "%s AMD8131 PCI-X tuning\n", dev_path(dev)); - status = pci_read_config32(dev, cap + PCI_X_STATUS); - orig_cmd = cmd = pci_read_config16(dev,cap + PCI_X_CMD); - - max_read = (status & PCI_X_STATUS_MAX_READ) >> 21; - max_tran = (status & PCI_X_STATUS_MAX_SPLIT) >> 23; - - /* Errata #49 don't allow 4K transactions */ - if (max_read >= 2) { - max_read = 2; - } - - /* Errata #37 Limit the number of split transactions to avoid starvation */ - if (sibs >= 2) { - /* At most 2 outstanding split transactions when we have - * 3 or more bus master devices on the bus. - */ - if (max_tran > 1) { - max_tran = 1; - } - } - else if (sibs == 1) { - /* At most 4 outstanding split transactions when we have - * 2 bus master devices on the bus. - */ - if (max_tran > 3) { - max_tran = 3; - } - } - else { - /* At most 8 outstanding split transactions when we have - * only one bus master device on the bus. - */ - if (max_tran > 4) { - max_tran = 4; - } - } - /* Errata #56 additional limits when the bus runs at 133Mhz */ - if (info->errata_56 && - (PCI_X_SSTATUS_MFREQ(info->sstatus) == PCI_X_SSTATUS_MODE1_133MHZ)) - { - unsigned limit_read; - /* Look at the number of siblings and compute the - * largest legal read size. - */ - if (sib_funcs == 0) { - /* 2k reads */ - limit_read = 2; - } - else if (sib_funcs <= 1) { - /* 1k reads */ - limit_read = 1; - } - else { - /* 512 byte reads */ - limit_read = 0; - } - if (max_read > limit_read) { - max_read = limit_read; - } - /* Look at the read size and the nubmer of siblings - * and compute how many outstanding transactions I can have. - */ - if (max_read == 2) { - /* 2K reads */ - if (max_tran > 0) { - /* Only 1 outstanding transaction allowed */ - max_tran = 0; - } - } - else if (max_read == 1) { - /* 1K reads */ - if (max_tran > (1 - sib_funcs)) { - /* At most 2 outstanding transactions */ - max_tran = 1 - sib_funcs; - } - } - else { - /* 512 byte reads */ - max_read = 0; - if (max_tran > (2 - sib_funcs)) { - /* At most 3 outstanding transactions */ - max_tran = 2 - sib_funcs; - } - } - } -#if 0 - printk(BIOS_DEBUG, "%s max_read: %d max_tran: %d sibs: %d sib_funcs: %d\n", - dev_path(dev), max_read, max_tran, sibs, sib_funcs, sib_funcs); -#endif - if (max_read != ((cmd & PCI_X_CMD_MAX_READ) >> 2)) { - cmd &= ~PCI_X_CMD_MAX_READ; - cmd |= max_read << 2; - } - if (max_tran != ((cmd & PCI_X_CMD_MAX_SPLIT) >> 4)) { - cmd &= ~PCI_X_CMD_MAX_SPLIT; - cmd |= max_tran << 4; - } - - /* Don't attempt to handle PCI-X errors */ - cmd &= ~PCI_X_CMD_DPERR_E; - /* The 8131 does not work properly with relax ordering enabled. - * Errata #58 - */ - cmd &= ~PCI_X_CMD_ERO; - if (orig_cmd != cmd) { - pci_write_config16(dev, cap + PCI_X_CMD, cmd); - } -} -static unsigned int amd8131_scan_bus(struct bus *bus, - unsigned min_devfn, unsigned max_devfn, unsigned int max) -{ - struct amd8131_bus_info info; - struct bus *pbus; - unsigned pos; - - - /* Find the children on the bus */ - max = pci_scan_bus(bus, min_devfn, max_devfn, max); - - /* Find the revision of the 8131 */ - info.rev = pci_read_config8(bus->dev, PCI_CLASS_REVISION); - - /* See which errata apply */ - info.errata_56 = info.rev <= 0x12; - - /* Find the pcix capability and get the secondary bus status */ - pos = pci_find_capability(bus->dev, PCI_CAP_ID_PCIX); - info.sstatus = pci_read_config16(bus->dev, pos + PCI_X_SEC_STATUS); - - /* Print the PCI-X bus speed */ - printk(BIOS_DEBUG, "PCI: %02x: %s\n", bus->secondary, pcix_speed(info.sstatus)); - - - /* Examine the bus and find out how loaded it is */ - info.max_func = 0; - info.master_devices = 0; - amd8131_walk_children(bus, amd8131_count_dev, &info); - - /* Disable the bus if there are no devices on it or - * we are running at 133Mhz and have a 4 function device. - * see errata #56 - */ - if (!bus->children || - (info.errata_56 && - (info.max_func >= 3) && - (PCI_X_SSTATUS_MFREQ(info.sstatus) == PCI_X_SSTATUS_MODE1_133MHZ))) - { - unsigned pcix_misc; - /* Disable all of my children */ - disable_children(bus); - - /* Remember the device is disabled */ - bus->dev->enabled = 0; - - /* Disable the PCI-X clocks */ - pcix_misc = pci_read_config32(bus->dev, 0x40); - pcix_misc &= ~(0x1f << 16); - pci_write_config32(bus->dev, 0x40, pcix_misc); - - return max; - } - - /* If we are in conventional PCI mode nothing more is necessary. - */ - if (PCI_X_SSTATUS_MFREQ(info.sstatus) == PCI_X_SSTATUS_CONVENTIONAL_PCI) { - return max; - } - - - /* Tune the devices on the bus */ - amd8131_walk_children(bus, amd8131_pcix_tune_dev, &info); - - /* Don't allow the 8131 or any of it's parent busses to - * implement relaxed ordering. Errata #58 - */ - for(pbus = bus; !pbus->disable_relaxed_ordering; pbus = pbus->dev->bus) { - printk(BIOS_SPEW, "%s disabling relaxed ordering\n", - bus_path(pbus)); - pbus->disable_relaxed_ordering = 1; - } - return max; -} - -static unsigned int amd8131_scan_bridge(device_t dev, unsigned int max) -{ - return do_pci_scan_bridge(dev, max, amd8131_scan_bus); -} - - -static void amd8131_pcix_init(device_t dev) -{ - uint32_t dword; - uint16_t word; - uint8_t byte; - int nmi_option; - - /* Enable memory write and invalidate ??? */ - byte = pci_read_config8(dev, 0x04); - byte |= 0x10; - pci_write_config8(dev, 0x04, byte); - - /* Set drive strength */ - word = pci_read_config16(dev, 0xe0); - word = 0x0404; - pci_write_config16(dev, 0xe0, word); - word = pci_read_config16(dev, 0xe4); - word = 0x0404; - pci_write_config16(dev, 0xe4, word); - - /* Set impedance */ - word = pci_read_config16(dev, 0xe8); - word = 0x0404; - pci_write_config16(dev, 0xe8, word); - - /* Set discard unrequested prefetch data */ - /* Errata #51 */ - word = pci_read_config16(dev, 0x4c); - word |= 1; - pci_write_config16(dev, 0x4c, word); - - /* Set split transaction limits */ - word = pci_read_config16(dev, 0xa8); - pci_write_config16(dev, 0xaa, word); - word = pci_read_config16(dev, 0xac); - pci_write_config16(dev, 0xae, word); - - /* Set up error reporting, enable all */ - /* system error enable */ - dword = pci_read_config32(dev, 0x04); - dword |= (1<<8); - pci_write_config32(dev, 0x04, dword); - - /* system and error parity enable */ - dword = pci_read_config32(dev, 0x3c); - dword |= (3<<16); - pci_write_config32(dev, 0x3c, dword); - - /* NMI enable */ - nmi_option = NMI_OFF; - get_option(&nmi_option, "nmi"); - if(nmi_option) { - dword = pci_read_config32(dev, 0x44); - dword |= (1<<0); - pci_write_config32(dev, 0x44, dword); - } - - /* Set up CRC flood enable */ - dword = pci_read_config32(dev, 0xc0); - if(dword) { /* do device A only */ - dword = pci_read_config32(dev, 0xc4); - dword |= (1<<1); - pci_write_config32(dev, 0xc4, dword); - dword = pci_read_config32(dev, 0xc8); - dword |= (1<<1); - pci_write_config32(dev, 0xc8, dword); - } - return; -} - -#define BRIDGE_40_BIT_SUPPORT 0 -#if BRIDGE_40_BIT_SUPPORT -static void bridge_read_resources(struct device *dev) -{ - struct resource *res; - pci_bus_read_resources(dev); - res = find_resource(dev, PCI_MEMORY_BASE); - if (res) { - res->limit = 0xffffffffffULL; - } -} - -static void bridge_set_resources(struct device *dev) -{ - struct resource *res; - res = find_resource(dev, PCI_MEMORY_BASE); - if (res) { - resource_t base, end; - /* set the memory range */ - dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; - res->flags |= IORESOURCE_STORED; - base = res->base; - end = resource_end(res); - pci_write_config16(dev, PCI_MEMORY_BASE, base >> 16); - pci_write_config8(dev, NPUML, (base >> 32) & 0xff); - pci_write_config16(dev, PCI_MEMORY_LIMIT, end >> 16); - pci_write_config8(dev, NPUMB, (end >> 32) & 0xff); - - report_resource_stored(dev, res, ""); - } - pci_dev_set_resources(dev); -} -#endif /* BRIDGE_40_BIT_SUPPORT */ - -static struct device_operations pcix_ops = { -#if BRIDGE_40_BIT_SUPPORT - .read_resources = bridge_read_resources, - .set_resources = bridge_set_resources, -#else - .read_resources = pci_bus_read_resources, - .set_resources = pci_dev_set_resources, -#endif - .enable_resources = pci_bus_enable_resources, - .init = amd8131_pcix_init, - .scan_bus = amd8131_scan_bridge, - .reset_bus = pci_bus_reset, -}; - -static const struct pci_driver pcix_driver __pci_driver = { - .ops = &pcix_ops, - .vendor = PCI_VENDOR_ID_AMD, - .device = 0x7450, -}; - - -static void ioapic_enable(device_t dev) -{ - uint32_t value; - - value = pci_read_config32(dev, 0x44); - if (dev->enabled) { - value |= ((1 << 1) | (1 << 0)); - } else { - value &= ~((1 << 1) | (1 << 0)); - } - pci_write_config32(dev, 0x44, value); -} - -static struct pci_operations pci_ops_pci_dev = { - .set_subsystem = pci_dev_set_subsystem, -}; -static struct device_operations ioapic_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = 0, - .scan_bus = 0, - .enable = ioapic_enable, - .ops_pci = &pci_ops_pci_dev, -}; - -static const struct pci_driver ioapic_driver __pci_driver = { - .ops = &ioapic_ops, - .vendor = PCI_VENDOR_ID_AMD, - .device = 0x7451, - -}; diff --git a/src/southbridge/amd/amd8131/bridge.c b/src/southbridge/amd/amd8131/bridge.c new file mode 100644 index 0000000000..d258450a06 --- /dev/null +++ b/src/southbridge/amd/amd8131/bridge.c @@ -0,0 +1,432 @@ +/* + * (C) 2003-2004 Linux Networx + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define NMI_OFF 0 + +#define NPUML 0xD9 /* Non prefetchable upper memory limit */ +#define NPUMB 0xD8 /* Non prefetchable upper memory base */ + +static void amd8131_walk_children(struct bus *bus, + void (*visit)(device_t dev, void *ptr), void *ptr) +{ + device_t child; + for(child = bus->children; child; child = child->sibling) + { + if (child->path.type != DEVICE_PATH_PCI) { + continue; + } + if (child->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + amd8131_walk_children(child->link_list, visit, ptr); + } + visit(child, ptr); + } +} + +struct amd8131_bus_info { + unsigned sstatus; + unsigned rev; + int errata_56; + int master_devices; + int max_func; +}; + +static void amd8131_count_dev(device_t dev, void *ptr) +{ + struct amd8131_bus_info *info = ptr; + /* Don't count pci bridges */ + if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { + info->master_devices++; + } + if (PCI_FUNC(dev->path.pci.devfn) > info->max_func) { + info->max_func = PCI_FUNC(dev->path.pci.devfn); + } +} + + +static void amd8131_pcix_tune_dev(device_t dev, void *ptr) +{ + struct amd8131_bus_info *info = ptr; + unsigned cap; + unsigned status, cmd, orig_cmd; + unsigned max_read, max_tran; + int sib_funcs, sibs; + device_t sib; + + if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL) { + return; + } + cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); + if (!cap) { + return; + } + /* How many siblings does this device have? */ + sibs = info->master_devices - 1; + /* Count how many sibling functions this device has */ + sib_funcs = 0; + for(sib = dev->bus->children; sib; sib = sib->sibling) { + if (sib == dev) { + continue; + } + if (PCI_SLOT(sib->path.pci.devfn) != PCI_SLOT(dev->path.pci.devfn)) { + continue; + } + sib_funcs++; + } + + + printk(BIOS_DEBUG, "%s AMD8131 PCI-X tuning\n", dev_path(dev)); + status = pci_read_config32(dev, cap + PCI_X_STATUS); + orig_cmd = cmd = pci_read_config16(dev,cap + PCI_X_CMD); + + max_read = (status & PCI_X_STATUS_MAX_READ) >> 21; + max_tran = (status & PCI_X_STATUS_MAX_SPLIT) >> 23; + + /* Errata #49 don't allow 4K transactions */ + if (max_read >= 2) { + max_read = 2; + } + + /* Errata #37 Limit the number of split transactions to avoid starvation */ + if (sibs >= 2) { + /* At most 2 outstanding split transactions when we have + * 3 or more bus master devices on the bus. + */ + if (max_tran > 1) { + max_tran = 1; + } + } + else if (sibs == 1) { + /* At most 4 outstanding split transactions when we have + * 2 bus master devices on the bus. + */ + if (max_tran > 3) { + max_tran = 3; + } + } + else { + /* At most 8 outstanding split transactions when we have + * only one bus master device on the bus. + */ + if (max_tran > 4) { + max_tran = 4; + } + } + /* Errata #56 additional limits when the bus runs at 133Mhz */ + if (info->errata_56 && + (PCI_X_SSTATUS_MFREQ(info->sstatus) == PCI_X_SSTATUS_MODE1_133MHZ)) + { + unsigned limit_read; + /* Look at the number of siblings and compute the + * largest legal read size. + */ + if (sib_funcs == 0) { + /* 2k reads */ + limit_read = 2; + } + else if (sib_funcs <= 1) { + /* 1k reads */ + limit_read = 1; + } + else { + /* 512 byte reads */ + limit_read = 0; + } + if (max_read > limit_read) { + max_read = limit_read; + } + /* Look at the read size and the nubmer of siblings + * and compute how many outstanding transactions I can have. + */ + if (max_read == 2) { + /* 2K reads */ + if (max_tran > 0) { + /* Only 1 outstanding transaction allowed */ + max_tran = 0; + } + } + else if (max_read == 1) { + /* 1K reads */ + if (max_tran > (1 - sib_funcs)) { + /* At most 2 outstanding transactions */ + max_tran = 1 - sib_funcs; + } + } + else { + /* 512 byte reads */ + max_read = 0; + if (max_tran > (2 - sib_funcs)) { + /* At most 3 outstanding transactions */ + max_tran = 2 - sib_funcs; + } + } + } +#if 0 + printk(BIOS_DEBUG, "%s max_read: %d max_tran: %d sibs: %d sib_funcs: %d\n", + dev_path(dev), max_read, max_tran, sibs, sib_funcs, sib_funcs); +#endif + if (max_read != ((cmd & PCI_X_CMD_MAX_READ) >> 2)) { + cmd &= ~PCI_X_CMD_MAX_READ; + cmd |= max_read << 2; + } + if (max_tran != ((cmd & PCI_X_CMD_MAX_SPLIT) >> 4)) { + cmd &= ~PCI_X_CMD_MAX_SPLIT; + cmd |= max_tran << 4; + } + + /* Don't attempt to handle PCI-X errors */ + cmd &= ~PCI_X_CMD_DPERR_E; + /* The 8131 does not work properly with relax ordering enabled. + * Errata #58 + */ + cmd &= ~PCI_X_CMD_ERO; + if (orig_cmd != cmd) { + pci_write_config16(dev, cap + PCI_X_CMD, cmd); + } +} +static unsigned int amd8131_scan_bus(struct bus *bus, + unsigned min_devfn, unsigned max_devfn, unsigned int max) +{ + struct amd8131_bus_info info; + struct bus *pbus; + unsigned pos; + + + /* Find the children on the bus */ + max = pci_scan_bus(bus, min_devfn, max_devfn, max); + + /* Find the revision of the 8131 */ + info.rev = pci_read_config8(bus->dev, PCI_CLASS_REVISION); + + /* See which errata apply */ + info.errata_56 = info.rev <= 0x12; + + /* Find the pcix capability and get the secondary bus status */ + pos = pci_find_capability(bus->dev, PCI_CAP_ID_PCIX); + info.sstatus = pci_read_config16(bus->dev, pos + PCI_X_SEC_STATUS); + + /* Print the PCI-X bus speed */ + printk(BIOS_DEBUG, "PCI: %02x: %s\n", bus->secondary, pcix_speed(info.sstatus)); + + + /* Examine the bus and find out how loaded it is */ + info.max_func = 0; + info.master_devices = 0; + amd8131_walk_children(bus, amd8131_count_dev, &info); + + /* Disable the bus if there are no devices on it or + * we are running at 133Mhz and have a 4 function device. + * see errata #56 + */ + if (!bus->children || + (info.errata_56 && + (info.max_func >= 3) && + (PCI_X_SSTATUS_MFREQ(info.sstatus) == PCI_X_SSTATUS_MODE1_133MHZ))) + { + unsigned pcix_misc; + /* Disable all of my children */ + disable_children(bus); + + /* Remember the device is disabled */ + bus->dev->enabled = 0; + + /* Disable the PCI-X clocks */ + pcix_misc = pci_read_config32(bus->dev, 0x40); + pcix_misc &= ~(0x1f << 16); + pci_write_config32(bus->dev, 0x40, pcix_misc); + + return max; + } + + /* If we are in conventional PCI mode nothing more is necessary. + */ + if (PCI_X_SSTATUS_MFREQ(info.sstatus) == PCI_X_SSTATUS_CONVENTIONAL_PCI) { + return max; + } + + + /* Tune the devices on the bus */ + amd8131_walk_children(bus, amd8131_pcix_tune_dev, &info); + + /* Don't allow the 8131 or any of it's parent busses to + * implement relaxed ordering. Errata #58 + */ + for(pbus = bus; !pbus->disable_relaxed_ordering; pbus = pbus->dev->bus) { + printk(BIOS_SPEW, "%s disabling relaxed ordering\n", + bus_path(pbus)); + pbus->disable_relaxed_ordering = 1; + } + return max; +} + +static unsigned int amd8131_scan_bridge(device_t dev, unsigned int max) +{ + return do_pci_scan_bridge(dev, max, amd8131_scan_bus); +} + + +static void amd8131_pcix_init(device_t dev) +{ + uint32_t dword; + uint16_t word; + uint8_t byte; + int nmi_option; + + /* Enable memory write and invalidate ??? */ + byte = pci_read_config8(dev, 0x04); + byte |= 0x10; + pci_write_config8(dev, 0x04, byte); + + /* Set drive strength */ + word = pci_read_config16(dev, 0xe0); + word = 0x0404; + pci_write_config16(dev, 0xe0, word); + word = pci_read_config16(dev, 0xe4); + word = 0x0404; + pci_write_config16(dev, 0xe4, word); + + /* Set impedance */ + word = pci_read_config16(dev, 0xe8); + word = 0x0404; + pci_write_config16(dev, 0xe8, word); + + /* Set discard unrequested prefetch data */ + /* Errata #51 */ + word = pci_read_config16(dev, 0x4c); + word |= 1; + pci_write_config16(dev, 0x4c, word); + + /* Set split transaction limits */ + word = pci_read_config16(dev, 0xa8); + pci_write_config16(dev, 0xaa, word); + word = pci_read_config16(dev, 0xac); + pci_write_config16(dev, 0xae, word); + + /* Set up error reporting, enable all */ + /* system error enable */ + dword = pci_read_config32(dev, 0x04); + dword |= (1<<8); + pci_write_config32(dev, 0x04, dword); + + /* system and error parity enable */ + dword = pci_read_config32(dev, 0x3c); + dword |= (3<<16); + pci_write_config32(dev, 0x3c, dword); + + /* NMI enable */ + nmi_option = NMI_OFF; + get_option(&nmi_option, "nmi"); + if(nmi_option) { + dword = pci_read_config32(dev, 0x44); + dword |= (1<<0); + pci_write_config32(dev, 0x44, dword); + } + + /* Set up CRC flood enable */ + dword = pci_read_config32(dev, 0xc0); + if(dword) { /* do device A only */ + dword = pci_read_config32(dev, 0xc4); + dword |= (1<<1); + pci_write_config32(dev, 0xc4, dword); + dword = pci_read_config32(dev, 0xc8); + dword |= (1<<1); + pci_write_config32(dev, 0xc8, dword); + } + return; +} + +#define BRIDGE_40_BIT_SUPPORT 0 +#if BRIDGE_40_BIT_SUPPORT +static void bridge_read_resources(struct device *dev) +{ + struct resource *res; + pci_bus_read_resources(dev); + res = find_resource(dev, PCI_MEMORY_BASE); + if (res) { + res->limit = 0xffffffffffULL; + } +} + +static void bridge_set_resources(struct device *dev) +{ + struct resource *res; + res = find_resource(dev, PCI_MEMORY_BASE); + if (res) { + resource_t base, end; + /* set the memory range */ + dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + res->flags |= IORESOURCE_STORED; + base = res->base; + end = resource_end(res); + pci_write_config16(dev, PCI_MEMORY_BASE, base >> 16); + pci_write_config8(dev, NPUML, (base >> 32) & 0xff); + pci_write_config16(dev, PCI_MEMORY_LIMIT, end >> 16); + pci_write_config8(dev, NPUMB, (end >> 32) & 0xff); + + report_resource_stored(dev, res, ""); + } + pci_dev_set_resources(dev); +} +#endif /* BRIDGE_40_BIT_SUPPORT */ + +static struct device_operations pcix_ops = { +#if BRIDGE_40_BIT_SUPPORT + .read_resources = bridge_read_resources, + .set_resources = bridge_set_resources, +#else + .read_resources = pci_bus_read_resources, + .set_resources = pci_dev_set_resources, +#endif + .enable_resources = pci_bus_enable_resources, + .init = amd8131_pcix_init, + .scan_bus = amd8131_scan_bridge, + .reset_bus = pci_bus_reset, +}; + +static const struct pci_driver pcix_driver __pci_driver = { + .ops = &pcix_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = 0x7450, +}; + + +static void ioapic_enable(device_t dev) +{ + uint32_t value; + + value = pci_read_config32(dev, 0x44); + if (dev->enabled) { + value |= ((1 << 1) | (1 << 0)); + } else { + value &= ~((1 << 1) | (1 << 0)); + } + pci_write_config32(dev, 0x44, value); +} + +static struct pci_operations pci_ops_pci_dev = { + .set_subsystem = pci_dev_set_subsystem, +}; +static struct device_operations ioapic_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = 0, + .scan_bus = 0, + .enable = ioapic_enable, + .ops_pci = &pci_ops_pci_dev, +}; + +static const struct pci_driver ioapic_driver __pci_driver = { + .ops = &ioapic_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = 0x7451, + +}; diff --git a/src/southbridge/amd/amd8132/Makefile.inc b/src/southbridge/amd/amd8132/Makefile.inc index f1e844af10..d5b3a5f88e 100644 --- a/src/southbridge/amd/amd8132/Makefile.inc +++ b/src/southbridge/amd/amd8132/Makefile.inc @@ -1 +1 @@ -driver-y += amd8132_bridge.c +driver-y += bridge.c diff --git a/src/southbridge/amd/amd8132/amd8132_bridge.c b/src/southbridge/amd/amd8132/amd8132_bridge.c deleted file mode 100644 index 192137a18e..0000000000 --- a/src/southbridge/amd/amd8132/amd8132_bridge.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2005,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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * 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 -#include -#include -#include -#include -#include -#include -#include - -#define NMI_OFF 0 - -#define NPUML 0xD9 /* Non prefetchable upper memory limit */ -#define NPUMB 0xD8 /* Non prefetchable upper memory base */ - -static void amd8132_walk_children(struct bus *bus, - void (*visit)(device_t dev, void *ptr), void *ptr) -{ - device_t child; - for(child = bus->children; child; child = child->sibling) - { - if (child->path.type != DEVICE_PATH_PCI) { - continue; - } - if (child->hdr_type == PCI_HEADER_TYPE_BRIDGE) { - amd8132_walk_children(child->link_list, visit, ptr); - } - visit(child, ptr); - } -} - -struct amd8132_bus_info { - unsigned sstatus; - unsigned rev; - int master_devices; - int max_func; -}; - -static void amd8132_count_dev(device_t dev, void *ptr) -{ - struct amd8132_bus_info *info = ptr; - /* Don't count pci bridges */ - if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { - info->master_devices++; - } - if (PCI_FUNC(dev->path.pci.devfn) > info->max_func) { - info->max_func = PCI_FUNC(dev->path.pci.devfn); - } -} - - -static void amd8132_pcix_tune_dev(device_t dev, void *ptr) -{ - struct amd8132_bus_info *info = ptr; - unsigned cap; - unsigned status, cmd, orig_cmd; - unsigned max_read, max_tran; - int sibs; - - if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL) { - return; - } - cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); - if (!cap) { - return; - } - /* How many siblings does this device have? */ - sibs = info->master_devices - 1; - - printk(BIOS_DEBUG, "%s AMD8132 PCI-X tuning\n", dev_path(dev)); - status = pci_read_config32(dev, cap + PCI_X_STATUS); - orig_cmd = cmd = pci_read_config16(dev,cap + PCI_X_CMD); - - max_read = (status & PCI_X_STATUS_MAX_READ) >> 21; - max_tran = (status & PCI_X_STATUS_MAX_SPLIT) >> 23; - - if (info->rev == 0x01) { // only a1 need it - /* Errata #53 Limit the number of split transactions to avoid starvation */ - if (sibs >= 2) { - /* At most 2 outstanding split transactions when we have - * 3 or more bus master devices on the bus. - */ - if (max_tran > 1) { - max_tran = 1; - } - } - else if (sibs == 1) { - /* At most 4 outstanding split transactions when we have - * 2 bus master devices on the bus. - */ - if (max_tran > 3) { - max_tran = 3; - } - } - else { - /* At most 8 outstanding split transactions when we have - * only one bus master device on the bus. - */ - if (max_tran > 4) { - max_tran = 4; - } - } - } - - if (max_read != ((cmd & PCI_X_CMD_MAX_READ) >> 2)) { - cmd &= ~PCI_X_CMD_MAX_READ; - cmd |= max_read << 2; - } - if (max_tran != ((cmd & PCI_X_CMD_MAX_SPLIT) >> 4)) { - cmd &= ~PCI_X_CMD_MAX_SPLIT; - cmd |= max_tran << 4; - } - - /* Don't attempt to handle PCI-X errors */ - cmd &= ~PCI_X_CMD_DPERR_E; - if (orig_cmd != cmd) { - pci_write_config16(dev, cap + PCI_X_CMD, cmd); - } - - -} -static unsigned int amd8132_scan_bus(struct bus *bus, - unsigned min_devfn, unsigned max_devfn, unsigned int max) -{ - struct amd8132_bus_info info; - unsigned pos; - - - /* Find the children on the bus */ - max = pci_scan_bus(bus, min_devfn, max_devfn, max); - - /* Find the revision of the 8132 */ - info.rev = pci_read_config8(bus->dev, PCI_CLASS_REVISION); - - /* Find the pcix capability and get the secondary bus status */ - pos = pci_find_capability(bus->dev, PCI_CAP_ID_PCIX); - info.sstatus = pci_read_config16(bus->dev, pos + PCI_X_SEC_STATUS); - - /* Print the PCI-X bus speed */ - printk(BIOS_DEBUG, "PCI: %02x: %s sstatus=%04x rev=%02x \n", bus->secondary, pcix_speed(info.sstatus), info.sstatus, info.rev); - - - /* Examine the bus and find out how loaded it is */ - info.max_func = 0; - info.master_devices = 0; - amd8132_walk_children(bus, amd8132_count_dev, &info); - -#if 0 - /* Disable the bus if there are no devices on it - */ - if (!bus->children) - { - unsigned pcix_misc; - /* Disable all of my children */ - disable_children(bus); - - /* Remember the device is disabled */ - bus->dev->enabled = 0; - - /* Disable the PCI-X clocks */ - pcix_misc = pci_read_config32(bus->dev, 0x40); - pcix_misc &= ~(0x1f << 16); - pci_write_config32(bus->dev, 0x40, pcix_misc); - - return max; - } -#endif - - /* If we are in conventional PCI mode nothing more is necessary. - */ - if (PCI_X_SSTATUS_MFREQ(info.sstatus) == PCI_X_SSTATUS_CONVENTIONAL_PCI) { - return max; - } - - /* Tune the devices on the bus */ - amd8132_walk_children(bus, amd8132_pcix_tune_dev, &info); - - return max; -} - -static unsigned int amd8132_scan_bridge(device_t dev, unsigned int max) -{ - return do_pci_scan_bridge(dev, max, amd8132_scan_bus); -} - - -static void amd8132_pcix_init(device_t dev) -{ - uint32_t dword; - uint8_t byte; - unsigned chip_rev; - - /* Find the revision of the 8132 */ - chip_rev = pci_read_config8(dev, PCI_CLASS_REVISION); - - /* Enable memory write and invalidate ??? */ - dword = pci_read_config32(dev, 0x04); - dword |= 0x10; - dword &= ~(1<<6); // PERSP Parity Error Response - pci_write_config32(dev, 0x04, dword); - - if (chip_rev == 0x01) { - /* Errata #37 */ - byte = pci_read_config8(dev, 0x0c); - if(byte == 0x08 ) - pci_write_config8(dev, 0x0c, 0x10); - -#if 0 - /* Errata #59*/ - dword = pci_read_config32(dev, 0x40); - dword &= ~(1<<31); - pci_write_config32(dev, 0x40, dword); -#endif - - } - - /* Set up error reporting, enable all */ - /* system error enable */ - dword = pci_read_config32(dev, 0x04); - dword |= (1<<8); - pci_write_config32(dev, 0x04, dword); - - /* system and error parity enable */ - dword = pci_read_config32(dev, 0x3c); - dword |= (3<<16); - pci_write_config32(dev, 0x3c, dword); - - dword = pci_read_config32(dev, 0x40); -// dword &= ~(1<<31); /* WriteChainEnable */ - dword |= (1<<31); - dword |= (1<<7);// must set to 1 - dword |= (3<<21); //PCIErrorSerrDisable - pci_write_config32(dev, 0x40, dword); - - /* EXTARB = 1, COMPAT = 0 */ - dword = pci_read_config32(dev, 0x48); - dword |= (1<<3); - dword &= ~(1<<0); - dword |= (1<<15); //CLEARPCILOG_L - dword |= (1<<19); //PERR FATAL Enable - dword |= (1<<22); // SERR FATAL Enable - dword |= (1<<23); // LPMARBENABLE - dword |= (0x61<<24); //LPMARBCOUNT - pci_write_config32(dev, 0x48, dword); - - dword = pci_read_config32(dev, 0x4c); - dword |= (1<<6); //intial prefetch for memory read line request - dword |= (1<<9); //continuous prefetch Enable for memory read line request - pci_write_config32(dev, 0x4c, dword); - - - /* Disable Single-Bit-Error Correction [30] = 0 */ - dword = pci_read_config32(dev, 0x70); - dword &= ~(1<<30); - pci_write_config32(dev, 0x70, dword); - - //link - dword = pci_read_config32(dev, 0xd4); - dword |= (0x5c<<16); - pci_write_config32(dev, 0xd4, dword); - - /* TxSlack0 [16:17] = 0, RxHwLookahdEn0 [18] = 1, TxSlack1 [24:25] = 0, RxHwLookahdEn1 [26] = 1 */ - dword = pci_read_config32(dev, 0xdc); - dword |= (1<<1) | (1<<4); // stream disable 1 to 0 , DBLINSRATE - dword |= (1<<18)|(1<<26); - dword &= ~((3<<16)|(3<<24)); - pci_write_config32(dev, 0xdc, dword); - - /* Set up CRC flood enable */ - dword = pci_read_config32(dev, 0xc0); - if(dword) { /* do device A only */ -#if 0 - dword = pci_read_config32(dev, 0xc4); - dword |= (1<<1); - pci_write_config32(dev, 0xc4, dword); - dword = pci_read_config32(dev, 0xc8); - dword |= (1<<1); - pci_write_config32(dev, 0xc8, dword); -#endif - - if (chip_rev == 0x11) { - /* [18] Clock Gate Enable = 1 */ - dword = pci_read_config32(dev, 0xf0); - dword |= 0x00040008; - pci_write_config32(dev, 0xf0, dword); - } - - } - return; -} - -#define BRIDGE_40_BIT_SUPPORT 0 -#if BRIDGE_40_BIT_SUPPORT -static void bridge_read_resources(struct device *dev) -{ - struct resource *res; - pci_bus_read_resources(dev); - res = find_resource(dev, PCI_MEMORY_BASE); - if (res) { - res->limit = 0xffffffffffULL; - } -} - -static void bridge_set_resources(struct device *dev) -{ - struct resource *res; - res = find_resource(dev, PCI_MEMORY_BASE); - if (res) { - resource_t base, end; - /* set the memory range */ - dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; - res->flags |= IORESOURCE_STORED; - base = res->base; - end = resource_end(res); - pci_write_config16(dev, PCI_MEMORY_BASE, base >> 16); - pci_write_config8(dev, NPUML, (base >> 32) & 0xff); - pci_write_config16(dev, PCI_MEMORY_LIMIT, end >> 16); - pci_write_config8(dev, NPUMB, (end >> 32) & 0xff); - - report_resource_stored(dev, res, ""); - } - pci_dev_set_resources(dev); -} -#endif /* BRIDGE_40_BIT_SUPPORT */ - -static struct device_operations pcix_ops = { -#if BRIDGE_40_BIT_SUPPORT - .read_resources = bridge_read_resources, - .set_resources = bridge_set_resources, -#else - .read_resources = pci_bus_read_resources, - .set_resources = pci_dev_set_resources, -#endif - .enable_resources = pci_bus_enable_resources, - .init = amd8132_pcix_init, - .scan_bus = amd8132_scan_bridge, - .reset_bus = pci_bus_reset, -}; - -static const struct pci_driver pcix_driver __pci_driver = { - .ops = &pcix_ops, - .vendor = PCI_VENDOR_ID_AMD, - .device = 0x7458, -}; - -static void ioapic_enable(device_t dev) -{ - uint32_t value; - - value = pci_read_config32(dev, 0x44); - if (dev->enabled) { - value |= ((1 << 1) | (1 << 0)); - } else { - value &= ~((1 << 1) | (1 << 0)); - } - pci_write_config32(dev, 0x44, value); -} -static void amd8132_ioapic_init(device_t dev) -{ - uint32_t dword; - unsigned chip_rev; - - /* Find the revision of the 8132 */ - chip_rev = pci_read_config8(dev, PCI_CLASS_REVISION); - - if (chip_rev == 0x01) { -#if 0 - /* Errata #43 */ - dword = pci_read_config32(dev, 0xc8); - dword |= (0x3<<23); - pci_write_config32(dev, 0xc8, dword); -#endif - - } - - - if( (chip_rev == 0x11) ||(chip_rev == 0x12) ) { - //for b1 b2 - /* Errata #73 */ - dword = pci_read_config32(dev, 0x80); - dword |= (0x1f<<5); - pci_write_config32(dev, 0x80, dword); - dword = pci_read_config32(dev, 0x88); - dword |= (0x1f<<5); - pci_write_config32(dev, 0x88, dword); - - /* Errata #74 */ - dword = pci_read_config32(dev, 0x7c); - dword &= ~(0x3<<30); - dword |= (0x01<<30); - pci_write_config32(dev, 0x7c, dword); - } - -} - -static struct pci_operations pci_ops_pci_dev = { - .set_subsystem = pci_dev_set_subsystem, -}; -static struct device_operations ioapic_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = amd8132_ioapic_init, - .scan_bus = 0, - .enable = ioapic_enable, - .ops_pci = &pci_ops_pci_dev, -}; - -static const struct pci_driver ioapic_driver __pci_driver = { - .ops = &ioapic_ops, - .vendor = PCI_VENDOR_ID_AMD, - .device = 0x7459, - -}; diff --git a/src/southbridge/amd/amd8132/bridge.c b/src/southbridge/amd/amd8132/bridge.c new file mode 100644 index 0000000000..192137a18e --- /dev/null +++ b/src/southbridge/amd/amd8132/bridge.c @@ -0,0 +1,433 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2005,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; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#define NMI_OFF 0 + +#define NPUML 0xD9 /* Non prefetchable upper memory limit */ +#define NPUMB 0xD8 /* Non prefetchable upper memory base */ + +static void amd8132_walk_children(struct bus *bus, + void (*visit)(device_t dev, void *ptr), void *ptr) +{ + device_t child; + for(child = bus->children; child; child = child->sibling) + { + if (child->path.type != DEVICE_PATH_PCI) { + continue; + } + if (child->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + amd8132_walk_children(child->link_list, visit, ptr); + } + visit(child, ptr); + } +} + +struct amd8132_bus_info { + unsigned sstatus; + unsigned rev; + int master_devices; + int max_func; +}; + +static void amd8132_count_dev(device_t dev, void *ptr) +{ + struct amd8132_bus_info *info = ptr; + /* Don't count pci bridges */ + if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { + info->master_devices++; + } + if (PCI_FUNC(dev->path.pci.devfn) > info->max_func) { + info->max_func = PCI_FUNC(dev->path.pci.devfn); + } +} + + +static void amd8132_pcix_tune_dev(device_t dev, void *ptr) +{ + struct amd8132_bus_info *info = ptr; + unsigned cap; + unsigned status, cmd, orig_cmd; + unsigned max_read, max_tran; + int sibs; + + if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL) { + return; + } + cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); + if (!cap) { + return; + } + /* How many siblings does this device have? */ + sibs = info->master_devices - 1; + + printk(BIOS_DEBUG, "%s AMD8132 PCI-X tuning\n", dev_path(dev)); + status = pci_read_config32(dev, cap + PCI_X_STATUS); + orig_cmd = cmd = pci_read_config16(dev,cap + PCI_X_CMD); + + max_read = (status & PCI_X_STATUS_MAX_READ) >> 21; + max_tran = (status & PCI_X_STATUS_MAX_SPLIT) >> 23; + + if (info->rev == 0x01) { // only a1 need it + /* Errata #53 Limit the number of split transactions to avoid starvation */ + if (sibs >= 2) { + /* At most 2 outstanding split transactions when we have + * 3 or more bus master devices on the bus. + */ + if (max_tran > 1) { + max_tran = 1; + } + } + else if (sibs == 1) { + /* At most 4 outstanding split transactions when we have + * 2 bus master devices on the bus. + */ + if (max_tran > 3) { + max_tran = 3; + } + } + else { + /* At most 8 outstanding split transactions when we have + * only one bus master device on the bus. + */ + if (max_tran > 4) { + max_tran = 4; + } + } + } + + if (max_read != ((cmd & PCI_X_CMD_MAX_READ) >> 2)) { + cmd &= ~PCI_X_CMD_MAX_READ; + cmd |= max_read << 2; + } + if (max_tran != ((cmd & PCI_X_CMD_MAX_SPLIT) >> 4)) { + cmd &= ~PCI_X_CMD_MAX_SPLIT; + cmd |= max_tran << 4; + } + + /* Don't attempt to handle PCI-X errors */ + cmd &= ~PCI_X_CMD_DPERR_E; + if (orig_cmd != cmd) { + pci_write_config16(dev, cap + PCI_X_CMD, cmd); + } + + +} +static unsigned int amd8132_scan_bus(struct bus *bus, + unsigned min_devfn, unsigned max_devfn, unsigned int max) +{ + struct amd8132_bus_info info; + unsigned pos; + + + /* Find the children on the bus */ + max = pci_scan_bus(bus, min_devfn, max_devfn, max); + + /* Find the revision of the 8132 */ + info.rev = pci_read_config8(bus->dev, PCI_CLASS_REVISION); + + /* Find the pcix capability and get the secondary bus status */ + pos = pci_find_capability(bus->dev, PCI_CAP_ID_PCIX); + info.sstatus = pci_read_config16(bus->dev, pos + PCI_X_SEC_STATUS); + + /* Print the PCI-X bus speed */ + printk(BIOS_DEBUG, "PCI: %02x: %s sstatus=%04x rev=%02x \n", bus->secondary, pcix_speed(info.sstatus), info.sstatus, info.rev); + + + /* Examine the bus and find out how loaded it is */ + info.max_func = 0; + info.master_devices = 0; + amd8132_walk_children(bus, amd8132_count_dev, &info); + +#if 0 + /* Disable the bus if there are no devices on it + */ + if (!bus->children) + { + unsigned pcix_misc; + /* Disable all of my children */ + disable_children(bus); + + /* Remember the device is disabled */ + bus->dev->enabled = 0; + + /* Disable the PCI-X clocks */ + pcix_misc = pci_read_config32(bus->dev, 0x40); + pcix_misc &= ~(0x1f << 16); + pci_write_config32(bus->dev, 0x40, pcix_misc); + + return max; + } +#endif + + /* If we are in conventional PCI mode nothing more is necessary. + */ + if (PCI_X_SSTATUS_MFREQ(info.sstatus) == PCI_X_SSTATUS_CONVENTIONAL_PCI) { + return max; + } + + /* Tune the devices on the bus */ + amd8132_walk_children(bus, amd8132_pcix_tune_dev, &info); + + return max; +} + +static unsigned int amd8132_scan_bridge(device_t dev, unsigned int max) +{ + return do_pci_scan_bridge(dev, max, amd8132_scan_bus); +} + + +static void amd8132_pcix_init(device_t dev) +{ + uint32_t dword; + uint8_t byte; + unsigned chip_rev; + + /* Find the revision of the 8132 */ + chip_rev = pci_read_config8(dev, PCI_CLASS_REVISION); + + /* Enable memory write and invalidate ??? */ + dword = pci_read_config32(dev, 0x04); + dword |= 0x10; + dword &= ~(1<<6); // PERSP Parity Error Response + pci_write_config32(dev, 0x04, dword); + + if (chip_rev == 0x01) { + /* Errata #37 */ + byte = pci_read_config8(dev, 0x0c); + if(byte == 0x08 ) + pci_write_config8(dev, 0x0c, 0x10); + +#if 0 + /* Errata #59*/ + dword = pci_read_config32(dev, 0x40); + dword &= ~(1<<31); + pci_write_config32(dev, 0x40, dword); +#endif + + } + + /* Set up error reporting, enable all */ + /* system error enable */ + dword = pci_read_config32(dev, 0x04); + dword |= (1<<8); + pci_write_config32(dev, 0x04, dword); + + /* system and error parity enable */ + dword = pci_read_config32(dev, 0x3c); + dword |= (3<<16); + pci_write_config32(dev, 0x3c, dword); + + dword = pci_read_config32(dev, 0x40); +// dword &= ~(1<<31); /* WriteChainEnable */ + dword |= (1<<31); + dword |= (1<<7);// must set to 1 + dword |= (3<<21); //PCIErrorSerrDisable + pci_write_config32(dev, 0x40, dword); + + /* EXTARB = 1, COMPAT = 0 */ + dword = pci_read_config32(dev, 0x48); + dword |= (1<<3); + dword &= ~(1<<0); + dword |= (1<<15); //CLEARPCILOG_L + dword |= (1<<19); //PERR FATAL Enable + dword |= (1<<22); // SERR FATAL Enable + dword |= (1<<23); // LPMARBENABLE + dword |= (0x61<<24); //LPMARBCOUNT + pci_write_config32(dev, 0x48, dword); + + dword = pci_read_config32(dev, 0x4c); + dword |= (1<<6); //intial prefetch for memory read line request + dword |= (1<<9); //continuous prefetch Enable for memory read line request + pci_write_config32(dev, 0x4c, dword); + + + /* Disable Single-Bit-Error Correction [30] = 0 */ + dword = pci_read_config32(dev, 0x70); + dword &= ~(1<<30); + pci_write_config32(dev, 0x70, dword); + + //link + dword = pci_read_config32(dev, 0xd4); + dword |= (0x5c<<16); + pci_write_config32(dev, 0xd4, dword); + + /* TxSlack0 [16:17] = 0, RxHwLookahdEn0 [18] = 1, TxSlack1 [24:25] = 0, RxHwLookahdEn1 [26] = 1 */ + dword = pci_read_config32(dev, 0xdc); + dword |= (1<<1) | (1<<4); // stream disable 1 to 0 , DBLINSRATE + dword |= (1<<18)|(1<<26); + dword &= ~((3<<16)|(3<<24)); + pci_write_config32(dev, 0xdc, dword); + + /* Set up CRC flood enable */ + dword = pci_read_config32(dev, 0xc0); + if(dword) { /* do device A only */ +#if 0 + dword = pci_read_config32(dev, 0xc4); + dword |= (1<<1); + pci_write_config32(dev, 0xc4, dword); + dword = pci_read_config32(dev, 0xc8); + dword |= (1<<1); + pci_write_config32(dev, 0xc8, dword); +#endif + + if (chip_rev == 0x11) { + /* [18] Clock Gate Enable = 1 */ + dword = pci_read_config32(dev, 0xf0); + dword |= 0x00040008; + pci_write_config32(dev, 0xf0, dword); + } + + } + return; +} + +#define BRIDGE_40_BIT_SUPPORT 0 +#if BRIDGE_40_BIT_SUPPORT +static void bridge_read_resources(struct device *dev) +{ + struct resource *res; + pci_bus_read_resources(dev); + res = find_resource(dev, PCI_MEMORY_BASE); + if (res) { + res->limit = 0xffffffffffULL; + } +} + +static void bridge_set_resources(struct device *dev) +{ + struct resource *res; + res = find_resource(dev, PCI_MEMORY_BASE); + if (res) { + resource_t base, end; + /* set the memory range */ + dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + res->flags |= IORESOURCE_STORED; + base = res->base; + end = resource_end(res); + pci_write_config16(dev, PCI_MEMORY_BASE, base >> 16); + pci_write_config8(dev, NPUML, (base >> 32) & 0xff); + pci_write_config16(dev, PCI_MEMORY_LIMIT, end >> 16); + pci_write_config8(dev, NPUMB, (end >> 32) & 0xff); + + report_resource_stored(dev, res, ""); + } + pci_dev_set_resources(dev); +} +#endif /* BRIDGE_40_BIT_SUPPORT */ + +static struct device_operations pcix_ops = { +#if BRIDGE_40_BIT_SUPPORT + .read_resources = bridge_read_resources, + .set_resources = bridge_set_resources, +#else + .read_resources = pci_bus_read_resources, + .set_resources = pci_dev_set_resources, +#endif + .enable_resources = pci_bus_enable_resources, + .init = amd8132_pcix_init, + .scan_bus = amd8132_scan_bridge, + .reset_bus = pci_bus_reset, +}; + +static const struct pci_driver pcix_driver __pci_driver = { + .ops = &pcix_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = 0x7458, +}; + +static void ioapic_enable(device_t dev) +{ + uint32_t value; + + value = pci_read_config32(dev, 0x44); + if (dev->enabled) { + value |= ((1 << 1) | (1 << 0)); + } else { + value &= ~((1 << 1) | (1 << 0)); + } + pci_write_config32(dev, 0x44, value); +} +static void amd8132_ioapic_init(device_t dev) +{ + uint32_t dword; + unsigned chip_rev; + + /* Find the revision of the 8132 */ + chip_rev = pci_read_config8(dev, PCI_CLASS_REVISION); + + if (chip_rev == 0x01) { +#if 0 + /* Errata #43 */ + dword = pci_read_config32(dev, 0xc8); + dword |= (0x3<<23); + pci_write_config32(dev, 0xc8, dword); +#endif + + } + + + if( (chip_rev == 0x11) ||(chip_rev == 0x12) ) { + //for b1 b2 + /* Errata #73 */ + dword = pci_read_config32(dev, 0x80); + dword |= (0x1f<<5); + pci_write_config32(dev, 0x80, dword); + dword = pci_read_config32(dev, 0x88); + dword |= (0x1f<<5); + pci_write_config32(dev, 0x88, dword); + + /* Errata #74 */ + dword = pci_read_config32(dev, 0x7c); + dword &= ~(0x3<<30); + dword |= (0x01<<30); + pci_write_config32(dev, 0x7c, dword); + } + +} + +static struct pci_operations pci_ops_pci_dev = { + .set_subsystem = pci_dev_set_subsystem, +}; +static struct device_operations ioapic_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = amd8132_ioapic_init, + .scan_bus = 0, + .enable = ioapic_enable, + .ops_pci = &pci_ops_pci_dev, +}; + +static const struct pci_driver ioapic_driver __pci_driver = { + .ops = &ioapic_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = 0x7459, + +}; diff --git a/src/southbridge/amd/amd8151/Makefile.inc b/src/southbridge/amd/amd8151/Makefile.inc index d9b46989c6..b25139108a 100644 --- a/src/southbridge/amd/amd8151/Makefile.inc +++ b/src/southbridge/amd/amd8151/Makefile.inc @@ -1 +1 @@ -driver-y += amd8151_agp3.c +driver-y += agp3.c diff --git a/src/southbridge/amd/amd8151/agp3.c b/src/southbridge/amd/amd8151/agp3.c new file mode 100644 index 0000000000..a2df7035c9 --- /dev/null +++ b/src/southbridge/amd/amd8151/agp3.c @@ -0,0 +1,90 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2003 Tyan Computer + * Written by Yinghai Lu for Tyan Computer. + * + * 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 +#include +#include +#include +#include + +static void agp3bridge_init(device_t dev) +{ + uint8_t byte; + + /* Enable BM, MEM and IO */ + byte = pci_read_config32(dev, 0x04); + byte |= 0x07; + pci_write_config8(dev, 0x04, byte); + + return; +} + +static struct device_operations agp3bridge_ops = { + .read_resources = pci_bus_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_bus_enable_resources, + .init = agp3bridge_init, + .scan_bus = pci_scan_bridge, +}; + +static const struct pci_driver agp3bridge_driver __pci_driver = { + .ops = &agp3bridge_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = 0x7455, // AGP Bridge +}; + +static void agp3dev_enable(device_t dev) +{ + uint32_t value; + + /* AGP enable */ + value = pci_read_config32(dev, 0xa8); + value |= (3<<8)|2; //AGP 8x + pci_write_config32(dev, 0xa8, value); + + /* enable BM and MEM */ + value = pci_read_config32(dev, 0x4); + value |= 6; + pci_write_config32(dev, 0x4, value); +#if 0 + /* FIXME: should we add agp aperture base and size here ? + * or it is done by AGP drivers */ +#endif +} + +static struct pci_operations pci_ops_pci_dev = { + .set_subsystem = pci_dev_set_subsystem, +}; + +static struct device_operations agp3dev_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = 0, + .scan_bus = 0, + .enable = agp3dev_enable, + .ops_pci = &pci_ops_pci_dev, +}; + +static const struct pci_driver agp3dev_driver __pci_driver = { + .ops = &agp3dev_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = 0x7454, //AGP Device +}; diff --git a/src/southbridge/amd/amd8151/amd8151_agp3.c b/src/southbridge/amd/amd8151/amd8151_agp3.c deleted file mode 100644 index a2df7035c9..0000000000 --- a/src/southbridge/amd/amd8151/amd8151_agp3.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2003 Tyan Computer - * Written by Yinghai Lu for Tyan Computer. - * - * 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 -#include -#include -#include -#include - -static void agp3bridge_init(device_t dev) -{ - uint8_t byte; - - /* Enable BM, MEM and IO */ - byte = pci_read_config32(dev, 0x04); - byte |= 0x07; - pci_write_config8(dev, 0x04, byte); - - return; -} - -static struct device_operations agp3bridge_ops = { - .read_resources = pci_bus_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_bus_enable_resources, - .init = agp3bridge_init, - .scan_bus = pci_scan_bridge, -}; - -static const struct pci_driver agp3bridge_driver __pci_driver = { - .ops = &agp3bridge_ops, - .vendor = PCI_VENDOR_ID_AMD, - .device = 0x7455, // AGP Bridge -}; - -static void agp3dev_enable(device_t dev) -{ - uint32_t value; - - /* AGP enable */ - value = pci_read_config32(dev, 0xa8); - value |= (3<<8)|2; //AGP 8x - pci_write_config32(dev, 0xa8, value); - - /* enable BM and MEM */ - value = pci_read_config32(dev, 0x4); - value |= 6; - pci_write_config32(dev, 0x4, value); -#if 0 - /* FIXME: should we add agp aperture base and size here ? - * or it is done by AGP drivers */ -#endif -} - -static struct pci_operations pci_ops_pci_dev = { - .set_subsystem = pci_dev_set_subsystem, -}; - -static struct device_operations agp3dev_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = 0, - .scan_bus = 0, - .enable = agp3dev_enable, - .ops_pci = &pci_ops_pci_dev, -}; - -static const struct pci_driver agp3dev_driver __pci_driver = { - .ops = &agp3dev_ops, - .vendor = PCI_VENDOR_ID_AMD, - .device = 0x7454, //AGP Device -}; diff --git a/src/southbridge/amd/cs5530/Makefile.inc b/src/southbridge/amd/cs5530/Makefile.inc index f51369fac1..4bde476743 100644 --- a/src/southbridge/amd/cs5530/Makefile.inc +++ b/src/southbridge/amd/cs5530/Makefile.inc @@ -19,7 +19,7 @@ ## driver-y += cs5530.c -driver-y += cs5530_isa.c -driver-y += cs5530_ide.c -driver-y += cs5530_vga.c -driver-y += cs5530_pirq.c +driver-y += isa.c +driver-y += ide.c +driver-y += vga.c +driver-y += pirq.c diff --git a/src/southbridge/amd/cs5530/cs5530_enable_rom.c b/src/southbridge/amd/cs5530/cs5530_enable_rom.c deleted file mode 100644 index 09ec3ed791..0000000000 --- a/src/southbridge/amd/cs5530/cs5530_enable_rom.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2009 Uwe Hermann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * 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 -#include "cs5530.h" - -static void cs5530_enable_rom(void) -{ - uint8_t reg8; - - /* So far all CS5530(A) ISA bridges we've seen are at 00:12.0. */ - device_t dev = PCI_DEV(0, 0x12, 0); - - /* - * Decode 0x000E0000-0x000FFFFF (128 KB), not just 64 KB, and - * decode 0xFF000000-0xFFFFFFFF (16 MB), not just 256 KB. - * - * Make the ROM write-protected. - */ - reg8 = pci_read_config8(dev, ROM_AT_LOGIC_CONTROL_REG); - reg8 |= LOWER_ROM_ADDRESS_RANGE; - reg8 |= UPPER_ROM_ADDRESS_RANGE; - reg8 &= ~ROM_WRITE_ENABLE; - pci_write_config8(dev, ROM_AT_LOGIC_CONTROL_REG, reg8); - - /* Set positive decode on ROM. */ - reg8 = pci_read_config8(dev, DECODE_CONTROL_REG2); - reg8 |= BIOS_ROM_POSITIVE_DECODE; - pci_write_config8(dev, DECODE_CONTROL_REG2, reg8); -} diff --git a/src/southbridge/amd/cs5530/cs5530_ide.c b/src/southbridge/amd/cs5530/cs5530_ide.c deleted file mode 100644 index a1fa2dc2c3..0000000000 --- a/src/southbridge/amd/cs5530/cs5530_ide.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007 Uwe Hermann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * 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 -#include -#include -#include -#include "cs5530.h" - -/** - * Initialize the IDE controller. - * - * Depending on the configuration variables 'ide0_enable' and 'ide1_enable' - * enable or disable the primary and secondary IDE interface, respectively. - * - * @param dev The device to use. - */ -static void ide_init(struct device *dev) -{ - uint8_t reg8; - struct southbridge_amd_cs5530_config *conf = dev->chip_info; - - reg8 = pci_read_config8(dev, DECODE_CONTROL_REG2); - - /* Enable/disable the primary IDE interface. */ - if (conf->ide0_enable) { - reg8 |= PRIMARY_IDE_ENABLE; - } else { - reg8 &= ~(PRIMARY_IDE_ENABLE); - } - - /* Enable/disable the secondary IDE interface. */ - if (conf->ide1_enable) { - reg8 |= SECONDARY_IDE_ENABLE; - } else { - reg8 &= ~(SECONDARY_IDE_ENABLE); - } - - pci_write_config8(dev, DECODE_CONTROL_REG2, reg8); - - printk(BIOS_INFO, "%s IDE interface %s\n", "Primary", - conf->ide0_enable ? "enabled" : "disabled"); - printk(BIOS_INFO, "%s IDE interface %s\n", "Secondary", - conf->ide1_enable ? "enabled" : "disabled"); -} - -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, - .enable = 0, - .scan_bus = scan_static_bus, - .ops_pci = 0, -}; - -static const struct pci_driver ide_driver __pci_driver = { - .ops = &ide_ops, - .vendor = PCI_VENDOR_ID_CYRIX, - .device = PCI_DEVICE_ID_CYRIX_5530_IDE, -}; diff --git a/src/southbridge/amd/cs5530/cs5530_isa.c b/src/southbridge/amd/cs5530/cs5530_isa.c deleted file mode 100644 index ff1617ddc3..0000000000 --- a/src/southbridge/amd/cs5530/cs5530_isa.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007 Uwe Hermann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * 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 -#include -#include -#include -#include -#include -#include "cs5530.h" - -static void cs5530_read_resources(device_t dev) -{ - struct resource* res; - - pci_dev_read_resources(dev); - - res = new_resource(dev, 1); - res->base = 0x0UL; - res->size = 0x1000UL; - res->limit = 0xffffUL; - res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; - - res = new_resource(dev, 3); /* IOAPIC */ - res->base = IO_APIC_ADDR; - res->size = 0x00001000; - res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; -} - -static void isa_init(struct device *dev) -{ -} - -static struct device_operations isa_ops = { - .read_resources = cs5530_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = isa_init, - .enable = 0, - .scan_bus = scan_static_bus, -}; - -static const struct pci_driver isa_driver __pci_driver = { - .ops = &isa_ops, - .vendor = PCI_VENDOR_ID_CYRIX, - .device = PCI_DEVICE_ID_CYRIX_5530_LEGACY, -}; diff --git a/src/southbridge/amd/cs5530/cs5530_pirq.c b/src/southbridge/amd/cs5530/cs5530_pirq.c deleted file mode 100644 index 693f7c4721..0000000000 --- a/src/southbridge/amd/cs5530/cs5530_pirq.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007 Nikolay Petukhov - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * 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 -#include -#include -#include - -#if (CONFIG_PIRQ_ROUTE==1 && CONFIG_GENERATE_PIRQ_TABLE==1) -void pirq_assign_irqs(const unsigned char pIntAtoD[4]) -{ - device_t pdev; - - pdev = dev_find_device(PCI_VENDOR_ID_CYRIX, - PCI_DEVICE_ID_CYRIX_5530_LEGACY, 0); - - if (pdev) { - pci_write_config8(pdev, 0x5c, (pIntAtoD[1] << 4 | pIntAtoD[0])); - pci_write_config8(pdev, 0x5d, (pIntAtoD[3] << 4 | pIntAtoD[2])); - } -} -#endif diff --git a/src/southbridge/amd/cs5530/cs5530_vga.c b/src/southbridge/amd/cs5530/cs5530_vga.c deleted file mode 100644 index 4a26251084..0000000000 --- a/src/southbridge/amd/cs5530/cs5530_vga.c +++ /dev/null @@ -1,495 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007 Juergen Beisert - * - * 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 - */ - -/** - * @brief Activate the VGA feature in a Geode GX1 based system with one - * of five possible VESA modes: VGA, SVGA, XGA, 4:3 SXGA and 5:4 SXGA. - * Also it is prepared to display a splash screen. - * - * In a Geode GX1 environment the companion CS5530 is the VGA - * interface only. It contains a PLL for pixel clock generation, - * DACs to generate the analogue RGB signals, drivers for HSYNC - * and VSYNC and drivers for a digital flatpanel. - * The graphic feature itself (framebuffer, acceleration unit) - * is not part of this device. It is part of the CPU device. - * But both depend on each other, we cannot divide them into - * different drivers. So this driver is not only a CS5530 driver, - * it is also a Geode GX1 chipset graphic driver. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#if CONFIG_GX1_VIDEO == 1 -/* - * Some register descriptions that are no listed in cpu/amd/gx1def.h - */ -#define CS5530_DOT_CLK_CONFIG 0x0024 -#define CS5530_DISPLAY_CONFIG 0x0004 - -#define DC_FB_ST_OFFSET 0x8310 /* framebuffer start offset */ -#define DC_CB_ST_OFFSET 0x8314 /* compression start offset */ -#define DC_CURS_ST_OFFSET 0x8318 /* cursor start offset */ -#define DC_VID_ST_OFFSET 0x8320 /* video start offset */ -#define DC_LINE_DELTA 0x8324 /* fb and cb skip counts */ -#define DC_BUF_SIZE 0x8328 /* fb and cb line size */ -#define DC_H_TIMING_1 0x8330 /* horizontal timing... */ -#define DC_H_TIMING_2 0x8334 -#define DC_H_TIMING_3 0x8338 -#define DC_FP_H_TIMING 0x833C -#define DC_V_TIMING_1 0x8340 /* vertical timing... */ -#define DC_V_TIMING_2 0x8344 -#define DC_V_TIMING_3 0x8348 -#define DC_FP_V_TIMING 0x834C -#define DC_TIMING_CFG 0x8308 -#define DC_OUTPUT_CFG 0x830C - -/** - * what colour depth should be used as default (in bpp) - * Note: Currently no other value than 16 is supported - */ -#define COLOUR_DEPTH 16 - -/** - * Support for a few basic video modes - * Note: all modes only for CRT. The flatpanel feature is - * not supported here (due to the lack of hardware to test) - */ -struct video_mode { - int pixel_clock; /*<< pixel clock in Hz */ - unsigned long pll_value; /*<< pll register value for this clock */ - - int visible_pixel; /*<< visible pixels in one line */ - int hsync_start; /*<< start of hsync behind visible pixels */ - int hsync_end; /*<< end of hsync behind its start */ - int line_length; /*<< whole line length */ - - int visible_lines; /*<< visible lines on screen */ - int vsync_start; /*<< vsync start behind last visible line */ - int vsync_end; /*<< end of vsync behind its start */ - int picture_length; /*<< whole screen length */ - - int sync_pol; /*<< 0: low, 1: high, bit 0 hsync, bit 1 vsync */ -}; - -/* - * values for .sync_pol in struct video_mode - */ -#define HSYNC_HIGH_POL 0 -#define HSYNC_LOW_POL 1 -#define VSYNC_HIGH_POL 0 -#define VSYNC_LOW_POL 2 - -/** - * 640x480 @ 72Hz hsync: 37.9kHz - * VESA standard mode for classic 4:3 monitors - * Copied from X11: - * ModeLine "640x480" 31.5 640 664 704 832 480 489 491 520 -hsync -vsync - */ -static const struct video_mode mode_640x480 = { - .pixel_clock = 31500000, - .pll_value = 0x33915801, - - .visible_pixel = 640, - .hsync_start = 664, - .hsync_end = 704, /* 1.27 us sync length */ - .line_length = 832, /* 26.39us */ - - .visible_lines = 480, - .vsync_start = 489, - .vsync_end = 491, - .picture_length = 520, /* 13.89ms */ - - .sync_pol = HSYNC_LOW_POL | VSYNC_LOW_POL, -}; - -/** - * 800x600 @ 72Hz hsync: 48.1kHz - * VESA standard mode for classic 4:3 monitors - * Copied from X11: - * ModeLine "800x600" 50.0 800 856 976 1040 600 637 643 666 +hsync +vsync - */ -static const struct video_mode mode_800x600 = { - .pixel_clock = 50000000, - .pll_value = 0x23088801, - - .visible_pixel = 800, - .hsync_start = 856, - .hsync_end = 976, - .line_length = 1040, /* 20.8us */ - - .visible_lines = 600, - .vsync_start = 637, - .vsync_end = 643, - .picture_length = 666, /* 13.89ms */ - - .sync_pol = HSYNC_HIGH_POL | VSYNC_HIGH_POL, -}; - -/** - * 1024x768 @ 70Hz (VESA) hsync: 56.5kHz - * Standard mode for classic 4:3 monitors - * Copied from X11: - * ModeLine "1024x768" 75.0 1024 1048 1184 1328 768 771 777 806 -hsync -vsync - */ -static const struct video_mode mode_1024x768 = { - .pixel_clock = 75000000, - .pll_value = 0x37E22801, - - .visible_pixel = 1024, - .hsync_start = 1048, - .hsync_end = 1184, - .line_length = 1328, /* 17.7us */ - - .visible_lines = 768, - .vsync_start = 771, - .vsync_end = 777, - .picture_length = 806, /* 14.3us */ - - .sync_pol = HSYNC_LOW_POL | VSYNC_LOW_POL, -}; - -/** - * 1280x960 @ 60Hz (VESA) hsync: 60.0kHz - * Mode for classic 4:3 monitors - * Copied from X11: - * ModeLine "1280x960" 108.0 1280 1376 1488 1800 960 961 964 1000 +hsync +vsync - */ -static const struct video_mode mode_1280x960 = { - .pixel_clock = 108000000, - .pll_value = 0x2710C805, - - .visible_pixel = 1280, - .hsync_start = 1376, - .hsync_end = 1488, - .line_length = 1800, /* 16.67us */ - - .visible_lines = 960, - .vsync_start = 961, - .vsync_end = 964, - .picture_length = 1000, /* 16.67ms */ - - .sync_pol = HSYNC_HIGH_POL | VSYNC_HIGH_POL, -}; - -/** - * 1280x1024 @ 60Hz (VESA) hsync: 64.0kHz - * Mode for modern 5:4 flat screens - * Copied from X11: - * ModeLine "1280x1024" 108.0 1280 1328 1440 1688 1024 1025 1028 1066 +hsync +vsync - */ -static const struct video_mode mode_1280x1024 = { - .pixel_clock = 108000000, - .pll_value = 0x2710C805, - - .visible_pixel = 1280, - .hsync_start = 1328, - .hsync_end = 1440, - .line_length = 1688, /* 15.6us */ - - .visible_lines = 1024, - .vsync_start = 1025, - .vsync_end = 1028, - .picture_length = 1066, - - .sync_pol = HSYNC_HIGH_POL | VSYNC_HIGH_POL, -}; - -/** - * List of supported common modes - */ -static const struct video_mode *modes[] = { - &mode_640x480, /* CONFIG_GX1_VIDEOMODE = 0 */ - &mode_800x600, /* CONFIG_GX1_VIDEOMODE = 1 */ - &mode_1024x768, /* CONFIG_GX1_VIDEOMODE = 2 */ - &mode_1280x960, /* CONFIG_GX1_VIDEOMODE = 3 */ - &mode_1280x1024 /* CONFIG_GX1_VIDEOMODE = 4 */ -}; - -/* make a sanity check at buildtime */ -#if CONFIG_GX1_VIDEOMODE > 4 -# error Requested video mode is unknown! -#endif - -/** - * Setup the pixel PLL in the companion chip - * @param[in] base register's base address - * @param[in] pll_val pll register value to be set - * - * The PLL to program here is located in the CS5530 - */ -static void cs5530_set_clock_frequency(u32 io_base, unsigned long pll_val) -{ - unsigned long reg; - - /* disable the PLL first, reset and power it down */ - reg = read32(io_base+CS5530_DOT_CLK_CONFIG) & ~0x20; - reg |= 0x80000100; - write32(io_base+CS5530_DOT_CLK_CONFIG, reg); - - /* write the new PLL setting */ - reg |= (pll_val & ~0x80000920); - write32(io_base+CS5530_DOT_CLK_CONFIG, reg); - - mdelay(1); /* wait for control voltage to be 0V */ - - /* enable the PLL */ - reg |= 0x00000800; - write32(io_base+CS5530_DOT_CLK_CONFIG, reg); - - /* clear reset */ - reg &= ~0x80000000; - write32(io_base+CS5530_DOT_CLK_CONFIG, reg); - - /* clear bypass */ - reg &= ~0x00000100; - write32(io_base+CS5530_DOT_CLK_CONFIG, reg); -} - -/** - * Setup memory layout - * @param[in] gx_base GX register area - * @param[in] mode Data about the video mode to setup - * - * Memory layout must be setup in Geode GX1's chipset. - * Note: This routine assumes unlocked DC registers. - * Note: Using compressed buffer is not supported yet! - * (makes more sense later, but not while booting) - * - * At this point a check is missed if the requested video - * mode is possible with the provided video memory. - * Check if symbol CONFIG_VIDEO_MB is at least: - * - 1 (=1MiB) for VGA and SVGA - * - 2 (=2MiB) for XGA - * - 4 (=4MiB) for SXGA - */ -static void dc_setup_layout(u32 gx_base, const struct video_mode *mode) -{ - u32 base = 0x00000000; - - write32(gx_base + DC_FB_ST_OFFSET, base); - - base += (COLOUR_DEPTH>>3) * mode->visible_pixel * mode->visible_lines; - - write32(gx_base + DC_CB_ST_OFFSET, base); - write32(gx_base + DC_CURS_ST_OFFSET, base); - write32(gx_base + DC_VID_ST_OFFSET, base); - write32(gx_base + DC_LINE_DELTA, ((COLOUR_DEPTH>>3) * mode->visible_pixel) >> 2); - write32(gx_base + DC_BUF_SIZE, ((COLOUR_DEPTH>>3) * mode->visible_pixel) >> 3); -} - -/** - * Setup the HSYNC/VSYNC, active video timing - * @param[in] gx_base GX register area - * @param[in] mode Data about the video mode to setup - * - * Sync signal generation is done in Geode GX1's chipset. - * Note: This routine assumes unlocked DC registers - * - * |<------------------------- htotal ----------------------------->| - * |<------------ hactive -------------->| | - * | hblankstart-->| | - * | hblankend-->| - * | hsyncstart-->| | - * | hsyncend-->| | - * |#####################################___________________________| RGB data - * |______________________________________________---------_________| HSYNC - * - * |<------------------------- vtotal ----------------------------->| - * |<------------ vactive -------------->| | - * | vblankstart-->| | - * | vblankend-->| - * | vsyncstart-->| | - * | vsyncend-->| | - * |#####################################___________________________| line data - * |______________________________________________---------_________| YSYNC - */ -static void dc_setup_timing(u32 gx_base, const struct video_mode *mode) -{ - u32 hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal; - u32 vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal; - - hactive = mode->visible_pixel & 0x7FF; - hblankstart = hactive; - hsyncstart = mode->hsync_start & 0x7FF; - hsyncend = mode->hsync_end & 0x7FF; - hblankend = mode->line_length & 0x7FF; - htotal = hblankend; - - vactive = mode->visible_lines & 0x7FF; - vblankstart = vactive; - vsyncstart = mode->vsync_start & 0x7FF; - vsyncend = mode->vsync_end & 0x7FF; - vblankend = mode->picture_length & 0x7FF; - vtotal = vblankend; - - /* row description */ - write32(gx_base + DC_H_TIMING_1, (hactive - 1) | ((htotal - 1) << 16)); - /* horizontal blank description */ - write32(gx_base + DC_H_TIMING_2, (hblankstart - 1) | ((hblankend - 1) << 16)); - /* horizontal sync description */ - write32(gx_base + DC_H_TIMING_3, (hsyncstart - 1) | ((hsyncend - 1) << 16)); - write32(gx_base + DC_FP_H_TIMING, (hsyncstart - 1) | ((hsyncend - 1) << 16)); - - /* line description */ - write32(gx_base + DC_V_TIMING_1, (vactive - 1) | ((vtotal - 1) << 16)); - /* vertical blank description */ - write32(gx_base + DC_V_TIMING_2, (vblankstart - 1) | ((vblankend - 1) << 16)); - /* vertical sync description */ - write32(gx_base + DC_V_TIMING_3, (vsyncstart - 1) | ((vsyncend - 1) << 16)); - write32(gx_base + DC_FP_V_TIMING, (vsyncstart - 2) | ((vsyncend - 2) << 16)); -} - -/** - * Setup required internals to bring the mode up and running - * @param[in] gx_base GX register area - * @param[in] mode Data about the video mode to setup - * - * Must be setup in Geode GX1's chipset. - * Note: This routine assumes unlocked DC registers. - */ -static void cs5530_activate_mode(u32 gx_base, const struct video_mode *mode) -{ - write32(gx_base + DC_GENERAL_CFG, 0x00000080); - mdelay(1); - dc_setup_layout(gx_base,mode); - dc_setup_timing(gx_base,mode); - - write32(gx_base + DC_GENERAL_CFG, 0x2000C581); - write32(gx_base + DC_TIMING_CFG, 0x0000002F); - write32(gx_base + DC_OUTPUT_CFG, 0x00003004); -} - -/** - * Activate the current mode to be "visible" outside - * @param[in] gx_base GX register area - * @param[in] mode Data about the video mode to setup - * - * As we now activate the interface this must be done - * in the CS5530 - */ -static void cs5530_activate_video(u32 io_base, const struct video_mode *mode) -{ - u32 val; - - val = (u32)mode->sync_pol << 8; - write32(io_base + CS5530_DISPLAY_CONFIG, val | 0x0020002F); -} - -#if CONFIG_SPLASH_GRAPHIC == 1 - -/* - * This bitmap file must provide: - * int width: pixel count in one line - * int height: line count - * int colours: ount of used colour - * unsigned long colour_map[]: RGB 565 colours to be used - * unsigned char bitmap[]: index per pixel into colour_map[], width*height pixels - */ -#include "bitmap.c" - -/* - * show a boot splash screen in the right lower corner of the screen - * swidth: screen width in pixel - * sheight: screen height in lines - * pitch: line pitch in bytes - * base: screen base address - * - * This routine assumes we are using a 16 bit colour depth! - */ -static void show_boot_splash_16(u32 swidth, u32 sheight, u32 pitch,void *base) -{ - int word_count,i; - unsigned short *adr; - u32 xstart,ystart,x,y; - /* - * fill the screen with the colour of the - * left top pixel in the graphic - */ - word_count = pitch * sheight; - adr = (unsigned short*)base; - for (i = 0; i < word_count; i++, adr++) - *adr = colour_map[bitmap[0]]; - - /* - * paint the splash - */ - xstart = swidth-width; - ystart = sheight-height; - for (y = 0; y < height; y++) { - adr=(unsigned short*)(base + pitch*(y+ystart) + 2 * xstart); - for (x = 0; x < width; x++) { - *adr=(unsigned short)colour_map[(int)bitmap[x + y * width]]; - adr++; - } - } -} -#else -# define show_boot_splash_16(w, x, y , z) -#endif - -/** - * coreboot management part - * @param[in] dev Info about the PCI device to initialise - */ -static void cs5530_vga_init(device_t dev) -{ - const struct video_mode *mode; - u32 io_base, gx_base; - - io_base = pci_read_config32(dev, 0x10); - gx_base = GX_BASE; - mode = modes[CONFIG_GX1_VIDEOMODE]; - - printk(BIOS_DEBUG, "Setting up video mode %dx%d with %d Hz clock\n", - mode->visible_pixel, mode->visible_lines, mode->pixel_clock); - - cs5530_set_clock_frequency(io_base, mode->pll_value); - - write32(gx_base + DC_UNLOCK, DC_UNLOCK_MAGIC); - - show_boot_splash_16(mode->visible_pixel, mode->visible_lines, - mode->visible_pixel * (COLOUR_DEPTH>>3), (void*)(GX_BASE + 0x800000)); - - cs5530_activate_mode(gx_base, mode); - - cs5530_activate_video(io_base, mode); - write32(gx_base + DC_UNLOCK, 0x00000000); -} - -static struct device_operations vga_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = cs5530_vga_init, - .enable = NULL, /* not required */ -}; - -static const struct pci_driver vga_pci_driver __pci_driver = { - .ops = &vga_ops, - .vendor = PCI_VENDOR_ID_CYRIX, - .device = PCI_DEVICE_ID_CYRIX_5530_VIDEO, -}; - -#endif /* #if CONFIG_GX1_VIDEO == 1 */ diff --git a/src/southbridge/amd/cs5530/enable_rom.c b/src/southbridge/amd/cs5530/enable_rom.c new file mode 100644 index 0000000000..09ec3ed791 --- /dev/null +++ b/src/southbridge/amd/cs5530/enable_rom.c @@ -0,0 +1,47 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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 +#include "cs5530.h" + +static void cs5530_enable_rom(void) +{ + uint8_t reg8; + + /* So far all CS5530(A) ISA bridges we've seen are at 00:12.0. */ + device_t dev = PCI_DEV(0, 0x12, 0); + + /* + * Decode 0x000E0000-0x000FFFFF (128 KB), not just 64 KB, and + * decode 0xFF000000-0xFFFFFFFF (16 MB), not just 256 KB. + * + * Make the ROM write-protected. + */ + reg8 = pci_read_config8(dev, ROM_AT_LOGIC_CONTROL_REG); + reg8 |= LOWER_ROM_ADDRESS_RANGE; + reg8 |= UPPER_ROM_ADDRESS_RANGE; + reg8 &= ~ROM_WRITE_ENABLE; + pci_write_config8(dev, ROM_AT_LOGIC_CONTROL_REG, reg8); + + /* Set positive decode on ROM. */ + reg8 = pci_read_config8(dev, DECODE_CONTROL_REG2); + reg8 |= BIOS_ROM_POSITIVE_DECODE; + pci_write_config8(dev, DECODE_CONTROL_REG2, reg8); +} diff --git a/src/southbridge/amd/cs5530/ide.c b/src/southbridge/amd/cs5530/ide.c new file mode 100644 index 0000000000..a1fa2dc2c3 --- /dev/null +++ b/src/southbridge/amd/cs5530/ide.c @@ -0,0 +1,78 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007 Uwe Hermann + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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 +#include +#include +#include +#include "cs5530.h" + +/** + * Initialize the IDE controller. + * + * Depending on the configuration variables 'ide0_enable' and 'ide1_enable' + * enable or disable the primary and secondary IDE interface, respectively. + * + * @param dev The device to use. + */ +static void ide_init(struct device *dev) +{ + uint8_t reg8; + struct southbridge_amd_cs5530_config *conf = dev->chip_info; + + reg8 = pci_read_config8(dev, DECODE_CONTROL_REG2); + + /* Enable/disable the primary IDE interface. */ + if (conf->ide0_enable) { + reg8 |= PRIMARY_IDE_ENABLE; + } else { + reg8 &= ~(PRIMARY_IDE_ENABLE); + } + + /* Enable/disable the secondary IDE interface. */ + if (conf->ide1_enable) { + reg8 |= SECONDARY_IDE_ENABLE; + } else { + reg8 &= ~(SECONDARY_IDE_ENABLE); + } + + pci_write_config8(dev, DECODE_CONTROL_REG2, reg8); + + printk(BIOS_INFO, "%s IDE interface %s\n", "Primary", + conf->ide0_enable ? "enabled" : "disabled"); + printk(BIOS_INFO, "%s IDE interface %s\n", "Secondary", + conf->ide1_enable ? "enabled" : "disabled"); +} + +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, + .enable = 0, + .scan_bus = scan_static_bus, + .ops_pci = 0, +}; + +static const struct pci_driver ide_driver __pci_driver = { + .ops = &ide_ops, + .vendor = PCI_VENDOR_ID_CYRIX, + .device = PCI_DEVICE_ID_CYRIX_5530_IDE, +}; diff --git a/src/southbridge/amd/cs5530/isa.c b/src/southbridge/amd/cs5530/isa.c new file mode 100644 index 0000000000..ff1617ddc3 --- /dev/null +++ b/src/southbridge/amd/cs5530/isa.c @@ -0,0 +1,64 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007 Uwe Hermann + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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 +#include +#include +#include +#include +#include +#include "cs5530.h" + +static void cs5530_read_resources(device_t dev) +{ + struct resource* res; + + pci_dev_read_resources(dev); + + res = new_resource(dev, 1); + res->base = 0x0UL; + res->size = 0x1000UL; + res->limit = 0xffffUL; + res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + + res = new_resource(dev, 3); /* IOAPIC */ + res->base = IO_APIC_ADDR; + res->size = 0x00001000; + res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; +} + +static void isa_init(struct device *dev) +{ +} + +static struct device_operations isa_ops = { + .read_resources = cs5530_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = isa_init, + .enable = 0, + .scan_bus = scan_static_bus, +}; + +static const struct pci_driver isa_driver __pci_driver = { + .ops = &isa_ops, + .vendor = PCI_VENDOR_ID_CYRIX, + .device = PCI_DEVICE_ID_CYRIX_5530_LEGACY, +}; diff --git a/src/southbridge/amd/cs5530/pirq.c b/src/southbridge/amd/cs5530/pirq.c new file mode 100644 index 0000000000..693f7c4721 --- /dev/null +++ b/src/southbridge/amd/cs5530/pirq.c @@ -0,0 +1,39 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007 Nikolay Petukhov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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 +#include +#include +#include + +#if (CONFIG_PIRQ_ROUTE==1 && CONFIG_GENERATE_PIRQ_TABLE==1) +void pirq_assign_irqs(const unsigned char pIntAtoD[4]) +{ + device_t pdev; + + pdev = dev_find_device(PCI_VENDOR_ID_CYRIX, + PCI_DEVICE_ID_CYRIX_5530_LEGACY, 0); + + if (pdev) { + pci_write_config8(pdev, 0x5c, (pIntAtoD[1] << 4 | pIntAtoD[0])); + pci_write_config8(pdev, 0x5d, (pIntAtoD[3] << 4 | pIntAtoD[2])); + } +} +#endif diff --git a/src/southbridge/amd/cs5530/vga.c b/src/southbridge/amd/cs5530/vga.c new file mode 100644 index 0000000000..4a26251084 --- /dev/null +++ b/src/southbridge/amd/cs5530/vga.c @@ -0,0 +1,495 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007 Juergen Beisert + * + * 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 + */ + +/** + * @brief Activate the VGA feature in a Geode GX1 based system with one + * of five possible VESA modes: VGA, SVGA, XGA, 4:3 SXGA and 5:4 SXGA. + * Also it is prepared to display a splash screen. + * + * In a Geode GX1 environment the companion CS5530 is the VGA + * interface only. It contains a PLL for pixel clock generation, + * DACs to generate the analogue RGB signals, drivers for HSYNC + * and VSYNC and drivers for a digital flatpanel. + * The graphic feature itself (framebuffer, acceleration unit) + * is not part of this device. It is part of the CPU device. + * But both depend on each other, we cannot divide them into + * different drivers. So this driver is not only a CS5530 driver, + * it is also a Geode GX1 chipset graphic driver. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#if CONFIG_GX1_VIDEO == 1 +/* + * Some register descriptions that are no listed in cpu/amd/gx1def.h + */ +#define CS5530_DOT_CLK_CONFIG 0x0024 +#define CS5530_DISPLAY_CONFIG 0x0004 + +#define DC_FB_ST_OFFSET 0x8310 /* framebuffer start offset */ +#define DC_CB_ST_OFFSET 0x8314 /* compression start offset */ +#define DC_CURS_ST_OFFSET 0x8318 /* cursor start offset */ +#define DC_VID_ST_OFFSET 0x8320 /* video start offset */ +#define DC_LINE_DELTA 0x8324 /* fb and cb skip counts */ +#define DC_BUF_SIZE 0x8328 /* fb and cb line size */ +#define DC_H_TIMING_1 0x8330 /* horizontal timing... */ +#define DC_H_TIMING_2 0x8334 +#define DC_H_TIMING_3 0x8338 +#define DC_FP_H_TIMING 0x833C +#define DC_V_TIMING_1 0x8340 /* vertical timing... */ +#define DC_V_TIMING_2 0x8344 +#define DC_V_TIMING_3 0x8348 +#define DC_FP_V_TIMING 0x834C +#define DC_TIMING_CFG 0x8308 +#define DC_OUTPUT_CFG 0x830C + +/** + * what colour depth should be used as default (in bpp) + * Note: Currently no other value than 16 is supported + */ +#define COLOUR_DEPTH 16 + +/** + * Support for a few basic video modes + * Note: all modes only for CRT. The flatpanel feature is + * not supported here (due to the lack of hardware to test) + */ +struct video_mode { + int pixel_clock; /*<< pixel clock in Hz */ + unsigned long pll_value; /*<< pll register value for this clock */ + + int visible_pixel; /*<< visible pixels in one line */ + int hsync_start; /*<< start of hsync behind visible pixels */ + int hsync_end; /*<< end of hsync behind its start */ + int line_length; /*<< whole line length */ + + int visible_lines; /*<< visible lines on screen */ + int vsync_start; /*<< vsync start behind last visible line */ + int vsync_end; /*<< end of vsync behind its start */ + int picture_length; /*<< whole screen length */ + + int sync_pol; /*<< 0: low, 1: high, bit 0 hsync, bit 1 vsync */ +}; + +/* + * values for .sync_pol in struct video_mode + */ +#define HSYNC_HIGH_POL 0 +#define HSYNC_LOW_POL 1 +#define VSYNC_HIGH_POL 0 +#define VSYNC_LOW_POL 2 + +/** + * 640x480 @ 72Hz hsync: 37.9kHz + * VESA standard mode for classic 4:3 monitors + * Copied from X11: + * ModeLine "640x480" 31.5 640 664 704 832 480 489 491 520 -hsync -vsync + */ +static const struct video_mode mode_640x480 = { + .pixel_clock = 31500000, + .pll_value = 0x33915801, + + .visible_pixel = 640, + .hsync_start = 664, + .hsync_end = 704, /* 1.27 us sync length */ + .line_length = 832, /* 26.39us */ + + .visible_lines = 480, + .vsync_start = 489, + .vsync_end = 491, + .picture_length = 520, /* 13.89ms */ + + .sync_pol = HSYNC_LOW_POL | VSYNC_LOW_POL, +}; + +/** + * 800x600 @ 72Hz hsync: 48.1kHz + * VESA standard mode for classic 4:3 monitors + * Copied from X11: + * ModeLine "800x600" 50.0 800 856 976 1040 600 637 643 666 +hsync +vsync + */ +static const struct video_mode mode_800x600 = { + .pixel_clock = 50000000, + .pll_value = 0x23088801, + + .visible_pixel = 800, + .hsync_start = 856, + .hsync_end = 976, + .line_length = 1040, /* 20.8us */ + + .visible_lines = 600, + .vsync_start = 637, + .vsync_end = 643, + .picture_length = 666, /* 13.89ms */ + + .sync_pol = HSYNC_HIGH_POL | VSYNC_HIGH_POL, +}; + +/** + * 1024x768 @ 70Hz (VESA) hsync: 56.5kHz + * Standard mode for classic 4:3 monitors + * Copied from X11: + * ModeLine "1024x768" 75.0 1024 1048 1184 1328 768 771 777 806 -hsync -vsync + */ +static const struct video_mode mode_1024x768 = { + .pixel_clock = 75000000, + .pll_value = 0x37E22801, + + .visible_pixel = 1024, + .hsync_start = 1048, + .hsync_end = 1184, + .line_length = 1328, /* 17.7us */ + + .visible_lines = 768, + .vsync_start = 771, + .vsync_end = 777, + .picture_length = 806, /* 14.3us */ + + .sync_pol = HSYNC_LOW_POL | VSYNC_LOW_POL, +}; + +/** + * 1280x960 @ 60Hz (VESA) hsync: 60.0kHz + * Mode for classic 4:3 monitors + * Copied from X11: + * ModeLine "1280x960" 108.0 1280 1376 1488 1800 960 961 964 1000 +hsync +vsync + */ +static const struct video_mode mode_1280x960 = { + .pixel_clock = 108000000, + .pll_value = 0x2710C805, + + .visible_pixel = 1280, + .hsync_start = 1376, + .hsync_end = 1488, + .line_length = 1800, /* 16.67us */ + + .visible_lines = 960, + .vsync_start = 961, + .vsync_end = 964, + .picture_length = 1000, /* 16.67ms */ + + .sync_pol = HSYNC_HIGH_POL | VSYNC_HIGH_POL, +}; + +/** + * 1280x1024 @ 60Hz (VESA) hsync: 64.0kHz + * Mode for modern 5:4 flat screens + * Copied from X11: + * ModeLine "1280x1024" 108.0 1280 1328 1440 1688 1024 1025 1028 1066 +hsync +vsync + */ +static const struct video_mode mode_1280x1024 = { + .pixel_clock = 108000000, + .pll_value = 0x2710C805, + + .visible_pixel = 1280, + .hsync_start = 1328, + .hsync_end = 1440, + .line_length = 1688, /* 15.6us */ + + .visible_lines = 1024, + .vsync_start = 1025, + .vsync_end = 1028, + .picture_length = 1066, + + .sync_pol = HSYNC_HIGH_POL | VSYNC_HIGH_POL, +}; + +/** + * List of supported common modes + */ +static const struct video_mode *modes[] = { + &mode_640x480, /* CONFIG_GX1_VIDEOMODE = 0 */ + &mode_800x600, /* CONFIG_GX1_VIDEOMODE = 1 */ + &mode_1024x768, /* CONFIG_GX1_VIDEOMODE = 2 */ + &mode_1280x960, /* CONFIG_GX1_VIDEOMODE = 3 */ + &mode_1280x1024 /* CONFIG_GX1_VIDEOMODE = 4 */ +}; + +/* make a sanity check at buildtime */ +#if CONFIG_GX1_VIDEOMODE > 4 +# error Requested video mode is unknown! +#endif + +/** + * Setup the pixel PLL in the companion chip + * @param[in] base register's base address + * @param[in] pll_val pll register value to be set + * + * The PLL to program here is located in the CS5530 + */ +static void cs5530_set_clock_frequency(u32 io_base, unsigned long pll_val) +{ + unsigned long reg; + + /* disable the PLL first, reset and power it down */ + reg = read32(io_base+CS5530_DOT_CLK_CONFIG) & ~0x20; + reg |= 0x80000100; + write32(io_base+CS5530_DOT_CLK_CONFIG, reg); + + /* write the new PLL setting */ + reg |= (pll_val & ~0x80000920); + write32(io_base+CS5530_DOT_CLK_CONFIG, reg); + + mdelay(1); /* wait for control voltage to be 0V */ + + /* enable the PLL */ + reg |= 0x00000800; + write32(io_base+CS5530_DOT_CLK_CONFIG, reg); + + /* clear reset */ + reg &= ~0x80000000; + write32(io_base+CS5530_DOT_CLK_CONFIG, reg); + + /* clear bypass */ + reg &= ~0x00000100; + write32(io_base+CS5530_DOT_CLK_CONFIG, reg); +} + +/** + * Setup memory layout + * @param[in] gx_base GX register area + * @param[in] mode Data about the video mode to setup + * + * Memory layout must be setup in Geode GX1's chipset. + * Note: This routine assumes unlocked DC registers. + * Note: Using compressed buffer is not supported yet! + * (makes more sense later, but not while booting) + * + * At this point a check is missed if the requested video + * mode is possible with the provided video memory. + * Check if symbol CONFIG_VIDEO_MB is at least: + * - 1 (=1MiB) for VGA and SVGA + * - 2 (=2MiB) for XGA + * - 4 (=4MiB) for SXGA + */ +static void dc_setup_layout(u32 gx_base, const struct video_mode *mode) +{ + u32 base = 0x00000000; + + write32(gx_base + DC_FB_ST_OFFSET, base); + + base += (COLOUR_DEPTH>>3) * mode->visible_pixel * mode->visible_lines; + + write32(gx_base + DC_CB_ST_OFFSET, base); + write32(gx_base + DC_CURS_ST_OFFSET, base); + write32(gx_base + DC_VID_ST_OFFSET, base); + write32(gx_base + DC_LINE_DELTA, ((COLOUR_DEPTH>>3) * mode->visible_pixel) >> 2); + write32(gx_base + DC_BUF_SIZE, ((COLOUR_DEPTH>>3) * mode->visible_pixel) >> 3); +} + +/** + * Setup the HSYNC/VSYNC, active video timing + * @param[in] gx_base GX register area + * @param[in] mode Data about the video mode to setup + * + * Sync signal generation is done in Geode GX1's chipset. + * Note: This routine assumes unlocked DC registers + * + * |<------------------------- htotal ----------------------------->| + * |<------------ hactive -------------->| | + * | hblankstart-->| | + * | hblankend-->| + * | hsyncstart-->| | + * | hsyncend-->| | + * |#####################################___________________________| RGB data + * |______________________________________________---------_________| HSYNC + * + * |<------------------------- vtotal ----------------------------->| + * |<------------ vactive -------------->| | + * | vblankstart-->| | + * | vblankend-->| + * | vsyncstart-->| | + * | vsyncend-->| | + * |#####################################___________________________| line data + * |______________________________________________---------_________| YSYNC + */ +static void dc_setup_timing(u32 gx_base, const struct video_mode *mode) +{ + u32 hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal; + u32 vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal; + + hactive = mode->visible_pixel & 0x7FF; + hblankstart = hactive; + hsyncstart = mode->hsync_start & 0x7FF; + hsyncend = mode->hsync_end & 0x7FF; + hblankend = mode->line_length & 0x7FF; + htotal = hblankend; + + vactive = mode->visible_lines & 0x7FF; + vblankstart = vactive; + vsyncstart = mode->vsync_start & 0x7FF; + vsyncend = mode->vsync_end & 0x7FF; + vblankend = mode->picture_length & 0x7FF; + vtotal = vblankend; + + /* row description */ + write32(gx_base + DC_H_TIMING_1, (hactive - 1) | ((htotal - 1) << 16)); + /* horizontal blank description */ + write32(gx_base + DC_H_TIMING_2, (hblankstart - 1) | ((hblankend - 1) << 16)); + /* horizontal sync description */ + write32(gx_base + DC_H_TIMING_3, (hsyncstart - 1) | ((hsyncend - 1) << 16)); + write32(gx_base + DC_FP_H_TIMING, (hsyncstart - 1) | ((hsyncend - 1) << 16)); + + /* line description */ + write32(gx_base + DC_V_TIMING_1, (vactive - 1) | ((vtotal - 1) << 16)); + /* vertical blank description */ + write32(gx_base + DC_V_TIMING_2, (vblankstart - 1) | ((vblankend - 1) << 16)); + /* vertical sync description */ + write32(gx_base + DC_V_TIMING_3, (vsyncstart - 1) | ((vsyncend - 1) << 16)); + write32(gx_base + DC_FP_V_TIMING, (vsyncstart - 2) | ((vsyncend - 2) << 16)); +} + +/** + * Setup required internals to bring the mode up and running + * @param[in] gx_base GX register area + * @param[in] mode Data about the video mode to setup + * + * Must be setup in Geode GX1's chipset. + * Note: This routine assumes unlocked DC registers. + */ +static void cs5530_activate_mode(u32 gx_base, const struct video_mode *mode) +{ + write32(gx_base + DC_GENERAL_CFG, 0x00000080); + mdelay(1); + dc_setup_layout(gx_base,mode); + dc_setup_timing(gx_base,mode); + + write32(gx_base + DC_GENERAL_CFG, 0x2000C581); + write32(gx_base + DC_TIMING_CFG, 0x0000002F); + write32(gx_base + DC_OUTPUT_CFG, 0x00003004); +} + +/** + * Activate the current mode to be "visible" outside + * @param[in] gx_base GX register area + * @param[in] mode Data about the video mode to setup + * + * As we now activate the interface this must be done + * in the CS5530 + */ +static void cs5530_activate_video(u32 io_base, const struct video_mode *mode) +{ + u32 val; + + val = (u32)mode->sync_pol << 8; + write32(io_base + CS5530_DISPLAY_CONFIG, val | 0x0020002F); +} + +#if CONFIG_SPLASH_GRAPHIC == 1 + +/* + * This bitmap file must provide: + * int width: pixel count in one line + * int height: line count + * int colours: ount of used colour + * unsigned long colour_map[]: RGB 565 colours to be used + * unsigned char bitmap[]: index per pixel into colour_map[], width*height pixels + */ +#include "bitmap.c" + +/* + * show a boot splash screen in the right lower corner of the screen + * swidth: screen width in pixel + * sheight: screen height in lines + * pitch: line pitch in bytes + * base: screen base address + * + * This routine assumes we are using a 16 bit colour depth! + */ +static void show_boot_splash_16(u32 swidth, u32 sheight, u32 pitch,void *base) +{ + int word_count,i; + unsigned short *adr; + u32 xstart,ystart,x,y; + /* + * fill the screen with the colour of the + * left top pixel in the graphic + */ + word_count = pitch * sheight; + adr = (unsigned short*)base; + for (i = 0; i < word_count; i++, adr++) + *adr = colour_map[bitmap[0]]; + + /* + * paint the splash + */ + xstart = swidth-width; + ystart = sheight-height; + for (y = 0; y < height; y++) { + adr=(unsigned short*)(base + pitch*(y+ystart) + 2 * xstart); + for (x = 0; x < width; x++) { + *adr=(unsigned short)colour_map[(int)bitmap[x + y * width]]; + adr++; + } + } +} +#else +# define show_boot_splash_16(w, x, y , z) +#endif + +/** + * coreboot management part + * @param[in] dev Info about the PCI device to initialise + */ +static void cs5530_vga_init(device_t dev) +{ + const struct video_mode *mode; + u32 io_base, gx_base; + + io_base = pci_read_config32(dev, 0x10); + gx_base = GX_BASE; + mode = modes[CONFIG_GX1_VIDEOMODE]; + + printk(BIOS_DEBUG, "Setting up video mode %dx%d with %d Hz clock\n", + mode->visible_pixel, mode->visible_lines, mode->pixel_clock); + + cs5530_set_clock_frequency(io_base, mode->pll_value); + + write32(gx_base + DC_UNLOCK, DC_UNLOCK_MAGIC); + + show_boot_splash_16(mode->visible_pixel, mode->visible_lines, + mode->visible_pixel * (COLOUR_DEPTH>>3), (void*)(GX_BASE + 0x800000)); + + cs5530_activate_mode(gx_base, mode); + + cs5530_activate_video(io_base, mode); + write32(gx_base + DC_UNLOCK, 0x00000000); +} + +static struct device_operations vga_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = cs5530_vga_init, + .enable = NULL, /* not required */ +}; + +static const struct pci_driver vga_pci_driver __pci_driver = { + .ops = &vga_ops, + .vendor = PCI_VENDOR_ID_CYRIX, + .device = PCI_DEVICE_ID_CYRIX_5530_VIDEO, +}; + +#endif /* #if CONFIG_GX1_VIDEO == 1 */ diff --git a/src/southbridge/amd/cs5535/Makefile.inc b/src/southbridge/amd/cs5535/Makefile.inc index ba092f125b..5fecea8e7e 100644 --- a/src/southbridge/amd/cs5535/Makefile.inc +++ b/src/southbridge/amd/cs5535/Makefile.inc @@ -1,4 +1,4 @@ driver-y += cs5535.c -#driver-y += cs5535_pci.c -#driver-y += cs5535_ide.c +#driver-y += pci.c +#driver-y += ide.c ramstage-y += chipsetinit.c diff --git a/src/southbridge/amd/cs5535/cs5535_early_setup.c b/src/southbridge/amd/cs5535/cs5535_early_setup.c deleted file mode 100644 index 1a612cc55f..0000000000 --- a/src/southbridge/amd/cs5535/cs5535_early_setup.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * - * cs5535_early_setup.c: Early chipset initialization for CS5535 companion device - * - * - * This file implements the initialization sequence documented in section 4.2 of - * AMD Geode GX Processor CS5535 Companion Device GoedeROM Porting Guide. - * - */ - -/** - * @brief Setup PCI IDSEL for CS5535 - * - * - */ - -static void cs5535_setup_extmsr(void) -{ - msr_t msr; - - /* forward MSR access to CS5535_GLINK_PORT_NUM to CS5535_DEV_NUM */ - msr.hi = msr.lo = 0x00000000; -#if CS5535_GLINK_PORT_NUM <= 4 - msr.lo = CS5535_DEV_NUM << ((CS5535_GLINK_PORT_NUM - 1) * 8); -#else - msr.hi = CS5535_DEV_NUM << ((CS5535_GLINK_PORT_NUM - 5) * 8); -#endif - wrmsr(0x5000201e, msr); -} - -static void cs5535_setup_idsel(void) -{ - /* write IDSEL to the write once register at address 0x0000 */ - outl(0x1 << (CS5535_DEV_NUM + 10), 0); -} - -static void cs5535_usb_swapsif(void) -{ - msr_t msr; - - msr = rdmsr(0x51600005); - //USB Serial short detect bit. - if (msr.hi & 0x10) { - /* We need to preserve bits 32,33,35 and not clear any BIST error, but clear the - * SERSHRT error bit */ - msr.hi &= 0xFFFFFFFB; - wrmsr(0x51600005, msr); - } -} - -static void cs5535_setup_iobase(void) -{ - msr_t msr; - /* setup LBAR for SMBus controller */ - msr.hi = 0x0000f001; - msr.lo = SMBUS_IO_BASE; - wrmsr(MDD_LBAR_SMB, msr); - - /* setup LBAR for GPIO */ - msr.hi = 0x0000f001; - msr.lo = GPIO_IO_BASE; - wrmsr(MDD_LBAR_GPIO, msr); - - /* setup LBAR for MFGPT */ - msr.hi = 0x0000f001; - msr.lo = MFGPT_IO_BASE; - wrmsr(MDD_LBAR_MFGPT, msr); - - /* setup LBAR for ACPI */ - msr.hi = 0x0000f001; - msr.lo = ACPI_IO_BASE; - wrmsr(MDD_LBAR_ACPI, msr); - - /* setup LBAR for PM Support */ - msr.hi = 0x0000f001; - msr.lo = PMS_IO_BASE; - wrmsr(MDD_LBAR_PMS, msr); -} - -static void cs5535_setup_gpio(void) -{ - uint32_t val; - - /* setup GPIO pins 14/15 for SDA/SCL */ - val = (1<<14 | 1<<15); - /* Output Enable */ - outl(0x3fffc000, 0x6100 + 0x04); - //outl(val, 0x6100 + 0x04); - /* Output AUX1 */ - outl(0x3fffc000, 0x6100 + 0x10); - //outl(val, 0x6100 + 0x10); - /* Input Enable */ - //outl(0x0f5af0a5, 0x6100 + 0x20); - outl(0x3fffc000, 0x6100 + 0x20); - //outl(val, 0x6100 + 0x20); - /* Input AUX1 */ - //outl(0x3ffbc004, 0x6100 + 0x34); - outl(0x3fffc000, 0x6100 + 0x34); - //outl(val, 0x6100 + 0x34); -} - -void cs5535_disable_internal_uart(void) -{ -} - -static void cs5535_setup_cis_mode(void) -{ - msr_t msr; - - /* setup CPU interface serial to mode C on both sides */ - msr = rdmsr(GLPCI_SB_CTRL); - msr.lo &= ~0x18; - msr.lo |= 0x10; - wrmsr(GLPCI_SB_CTRL, msr); - //Only do this if we are building for 5535 - msr.lo = 0x2; - msr.hi = 0x0; - wrmsr(VIP_GIO_MSR_SEL, msr); -} - -static void dummy(void) -{ -} - -static void cs5535_early_setup(void) -{ - msr_t msr; - - cs5535_setup_extmsr(); - - msr = rdmsr(GLCP_SYS_RSTPLL); - if (msr.lo & (0x3f << 26)) { - /* PLL is already set and we are reboot from PLL reset */ - print_debug("reboot from BIOS reset\n"); - return; - } - print_debug("Setup idsel\n"); - cs5535_setup_idsel(); - print_debug("Setup iobase\n"); - cs5535_usb_swapsif(); - cs5535_setup_iobase(); - print_debug("Setup gpio\n"); - cs5535_setup_gpio(); - print_debug("Setup cis_mode\n"); - cs5535_setup_cis_mode(); - print_debug("Setup smbus\n"); - cs5535_enable_smbus(); - dummy(); -} diff --git a/src/southbridge/amd/cs5535/cs5535_early_smbus.c b/src/southbridge/amd/cs5535/cs5535_early_smbus.c deleted file mode 100644 index 0aab46f6a3..0000000000 --- a/src/southbridge/amd/cs5535/cs5535_early_smbus.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "cs5535_smbus.h" - -#define SMBUS_IO_BASE 0x6000 - -/* initialization for SMBus Controller */ -static void cs5535_enable_smbus(void) -{ - unsigned char val; - - /* reset SMBUS controller */ - outb(0, SMBUS_IO_BASE + SMB_CTRL2); - - /* Set SCL freq and enable SMB controller */ - val = inb(SMBUS_IO_BASE + SMB_CTRL2); - val |= ((0x20 << 1) | SMB_CTRL2_ENABLE); - outb(val, SMBUS_IO_BASE + SMB_CTRL2); - - /* Setup SMBus host controller address to 0xEF */ - val = inb(SMBUS_IO_BASE + SMB_ADD); - val |= (0xEF | SMB_ADD_SAEN); - outb(val, SMBUS_IO_BASE + SMB_ADD); -} diff --git a/src/southbridge/amd/cs5535/cs5535_ide.c b/src/southbridge/amd/cs5535/cs5535_ide.c deleted file mode 100644 index b997ca2463..0000000000 --- a/src/southbridge/amd/cs5535/cs5535_ide.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include -#include -#include -#include "cs5535.h" - -static void ide_init(struct device *dev) -{ - printk(BIOS_SPEW, "cs5535_ide: %s\n", __func__); -} - -static void ide_enable(struct device *dev) -{ - printk(BIOS_SPEW, "cs5535_ide: %s\n", __func__); -} - -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, - .enable = ide_enable, -}; - -static const struct pci_driver ide_driver __pci_driver = { - .ops = &ide_ops, - .vendor = PCI_VENDOR_ID_NS, - .device = PCI_DEVICE_ID_NS_CS5535_IDE, -}; diff --git a/src/southbridge/amd/cs5535/cs5535_smbus.h b/src/southbridge/amd/cs5535/cs5535_smbus.h deleted file mode 100644 index db35f6ee7b..0000000000 --- a/src/southbridge/amd/cs5535/cs5535_smbus.h +++ /dev/null @@ -1,46 +0,0 @@ -//#include -#define SMBUS_ERROR -1 -#define SMBUS_WAIT_UNTIL_READY_TIMEOUT -2 -#define SMBUS_WAIT_UNTIL_DONE_TIMEOUT -3 - -#define SMB_SDA 0x00 -#define SMB_STS 0x01 -#define SMB_CTRL_STS 0x02 -#define SMB_CTRL1 0x03 -#define SMB_ADD 0x04 -#define SMB_CTRL2 0x05 -#define SMB_CTRL3 0x06 - -#define SMB_STS_SLVSTP (0x01 << 7) -#define SMB_STS_SDAST (0x01 << 6) -#define SMB_STS_BER (0x01 << 5) -#define SMB_STS_NEGACK (0x01 << 4) -#define SMB_STS_STASTR (0x01 << 3) -#define SMB_STS_NMATCH (0x01 << 2) -#define SMB_STS_MASTER (0x01 << 1) -#define SMB_STS_XMIT (0x01 << 0) - -#define SMB_CSTS_TGSCL (0x01 << 5) -#define SMB_CSTS_TSDA (0x01 << 4) -#define SMB_CSTS_GCMTCH (0x01 << 3) -#define SMB_CSTS_MATCH (0x01 << 2) -#define SMB_CSTS_BB (0x01 << 1) -#define SMB_CSTS_BUSY (0x01 << 0) - -#define SMB_CTRL1_STASTRE (0x01 << 7) -#define SMB_CTRL1_NMINTE (0x01 << 6) -#define SMB_CTRL1_GCMEN (0x01 << 5) -#define SMB_CTRL1_ACK (0x01 << 4) -#define SMB_CTRL1_RSVD (0x01 << 3) -#define SMB_CTRL1_INTEN (0x01 << 2) -#define SMB_CTRL1_STOP (0x01 << 1) -#define SMB_CTRL1_START (0x01 << 0) - -#define SMB_ADD_SAEN (0x01 << 7) - -#define SMB_CTRL2_ENABLE 0x01 - -#define SMBUS_TIMEOUT (100*1000*10) -#define SMBUS_STATUS_MASK 0xfbff - -#define SMBUS_IO_BASE 0x6000 diff --git a/src/southbridge/amd/cs5535/early_setup.c b/src/southbridge/amd/cs5535/early_setup.c new file mode 100644 index 0000000000..1a612cc55f --- /dev/null +++ b/src/southbridge/amd/cs5535/early_setup.c @@ -0,0 +1,149 @@ +/* + * + * cs5535_early_setup.c: Early chipset initialization for CS5535 companion device + * + * + * This file implements the initialization sequence documented in section 4.2 of + * AMD Geode GX Processor CS5535 Companion Device GoedeROM Porting Guide. + * + */ + +/** + * @brief Setup PCI IDSEL for CS5535 + * + * + */ + +static void cs5535_setup_extmsr(void) +{ + msr_t msr; + + /* forward MSR access to CS5535_GLINK_PORT_NUM to CS5535_DEV_NUM */ + msr.hi = msr.lo = 0x00000000; +#if CS5535_GLINK_PORT_NUM <= 4 + msr.lo = CS5535_DEV_NUM << ((CS5535_GLINK_PORT_NUM - 1) * 8); +#else + msr.hi = CS5535_DEV_NUM << ((CS5535_GLINK_PORT_NUM - 5) * 8); +#endif + wrmsr(0x5000201e, msr); +} + +static void cs5535_setup_idsel(void) +{ + /* write IDSEL to the write once register at address 0x0000 */ + outl(0x1 << (CS5535_DEV_NUM + 10), 0); +} + +static void cs5535_usb_swapsif(void) +{ + msr_t msr; + + msr = rdmsr(0x51600005); + //USB Serial short detect bit. + if (msr.hi & 0x10) { + /* We need to preserve bits 32,33,35 and not clear any BIST error, but clear the + * SERSHRT error bit */ + msr.hi &= 0xFFFFFFFB; + wrmsr(0x51600005, msr); + } +} + +static void cs5535_setup_iobase(void) +{ + msr_t msr; + /* setup LBAR for SMBus controller */ + msr.hi = 0x0000f001; + msr.lo = SMBUS_IO_BASE; + wrmsr(MDD_LBAR_SMB, msr); + + /* setup LBAR for GPIO */ + msr.hi = 0x0000f001; + msr.lo = GPIO_IO_BASE; + wrmsr(MDD_LBAR_GPIO, msr); + + /* setup LBAR for MFGPT */ + msr.hi = 0x0000f001; + msr.lo = MFGPT_IO_BASE; + wrmsr(MDD_LBAR_MFGPT, msr); + + /* setup LBAR for ACPI */ + msr.hi = 0x0000f001; + msr.lo = ACPI_IO_BASE; + wrmsr(MDD_LBAR_ACPI, msr); + + /* setup LBAR for PM Support */ + msr.hi = 0x0000f001; + msr.lo = PMS_IO_BASE; + wrmsr(MDD_LBAR_PMS, msr); +} + +static void cs5535_setup_gpio(void) +{ + uint32_t val; + + /* setup GPIO pins 14/15 for SDA/SCL */ + val = (1<<14 | 1<<15); + /* Output Enable */ + outl(0x3fffc000, 0x6100 + 0x04); + //outl(val, 0x6100 + 0x04); + /* Output AUX1 */ + outl(0x3fffc000, 0x6100 + 0x10); + //outl(val, 0x6100 + 0x10); + /* Input Enable */ + //outl(0x0f5af0a5, 0x6100 + 0x20); + outl(0x3fffc000, 0x6100 + 0x20); + //outl(val, 0x6100 + 0x20); + /* Input AUX1 */ + //outl(0x3ffbc004, 0x6100 + 0x34); + outl(0x3fffc000, 0x6100 + 0x34); + //outl(val, 0x6100 + 0x34); +} + +void cs5535_disable_internal_uart(void) +{ +} + +static void cs5535_setup_cis_mode(void) +{ + msr_t msr; + + /* setup CPU interface serial to mode C on both sides */ + msr = rdmsr(GLPCI_SB_CTRL); + msr.lo &= ~0x18; + msr.lo |= 0x10; + wrmsr(GLPCI_SB_CTRL, msr); + //Only do this if we are building for 5535 + msr.lo = 0x2; + msr.hi = 0x0; + wrmsr(VIP_GIO_MSR_SEL, msr); +} + +static void dummy(void) +{ +} + +static void cs5535_early_setup(void) +{ + msr_t msr; + + cs5535_setup_extmsr(); + + msr = rdmsr(GLCP_SYS_RSTPLL); + if (msr.lo & (0x3f << 26)) { + /* PLL is already set and we are reboot from PLL reset */ + print_debug("reboot from BIOS reset\n"); + return; + } + print_debug("Setup idsel\n"); + cs5535_setup_idsel(); + print_debug("Setup iobase\n"); + cs5535_usb_swapsif(); + cs5535_setup_iobase(); + print_debug("Setup gpio\n"); + cs5535_setup_gpio(); + print_debug("Setup cis_mode\n"); + cs5535_setup_cis_mode(); + print_debug("Setup smbus\n"); + cs5535_enable_smbus(); + dummy(); +} diff --git a/src/southbridge/amd/cs5535/early_smbus.c b/src/southbridge/amd/cs5535/early_smbus.c new file mode 100644 index 0000000000..25b6951daa --- /dev/null +++ b/src/southbridge/amd/cs5535/early_smbus.c @@ -0,0 +1,22 @@ +#include "smbus.h" + +#define SMBUS_IO_BASE 0x6000 + +/* initialization for SMBus Controller */ +static void cs5535_enable_smbus(void) +{ + unsigned char val; + + /* reset SMBUS controller */ + outb(0, SMBUS_IO_BASE + SMB_CTRL2); + + /* Set SCL freq and enable SMB controller */ + val = inb(SMBUS_IO_BASE + SMB_CTRL2); + val |= ((0x20 << 1) | SMB_CTRL2_ENABLE); + outb(val, SMBUS_IO_BASE + SMB_CTRL2); + + /* Setup SMBus host controller address to 0xEF */ + val = inb(SMBUS_IO_BASE + SMB_ADD); + val |= (0xEF | SMB_ADD_SAEN); + outb(val, SMBUS_IO_BASE + SMB_ADD); +} diff --git a/src/southbridge/amd/cs5535/ide.c b/src/southbridge/amd/cs5535/ide.c new file mode 100644 index 0000000000..b997ca2463 --- /dev/null +++ b/src/southbridge/amd/cs5535/ide.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include +#include "cs5535.h" + +static void ide_init(struct device *dev) +{ + printk(BIOS_SPEW, "cs5535_ide: %s\n", __func__); +} + +static void ide_enable(struct device *dev) +{ + printk(BIOS_SPEW, "cs5535_ide: %s\n", __func__); +} + +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, + .enable = ide_enable, +}; + +static const struct pci_driver ide_driver __pci_driver = { + .ops = &ide_ops, + .vendor = PCI_VENDOR_ID_NS, + .device = PCI_DEVICE_ID_NS_CS5535_IDE, +}; diff --git a/src/southbridge/amd/cs5535/smbus.h b/src/southbridge/amd/cs5535/smbus.h new file mode 100644 index 0000000000..db35f6ee7b --- /dev/null +++ b/src/southbridge/amd/cs5535/smbus.h @@ -0,0 +1,46 @@ +//#include +#define SMBUS_ERROR -1 +#define SMBUS_WAIT_UNTIL_READY_TIMEOUT -2 +#define SMBUS_WAIT_UNTIL_DONE_TIMEOUT -3 + +#define SMB_SDA 0x00 +#define SMB_STS 0x01 +#define SMB_CTRL_STS 0x02 +#define SMB_CTRL1 0x03 +#define SMB_ADD 0x04 +#define SMB_CTRL2 0x05 +#define SMB_CTRL3 0x06 + +#define SMB_STS_SLVSTP (0x01 << 7) +#define SMB_STS_SDAST (0x01 << 6) +#define SMB_STS_BER (0x01 << 5) +#define SMB_STS_NEGACK (0x01 << 4) +#define SMB_STS_STASTR (0x01 << 3) +#define SMB_STS_NMATCH (0x01 << 2) +#define SMB_STS_MASTER (0x01 << 1) +#define SMB_STS_XMIT (0x01 << 0) + +#define SMB_CSTS_TGSCL (0x01 << 5) +#define SMB_CSTS_TSDA (0x01 << 4) +#define SMB_CSTS_GCMTCH (0x01 << 3) +#define SMB_CSTS_MATCH (0x01 << 2) +#define SMB_CSTS_BB (0x01 << 1) +#define SMB_CSTS_BUSY (0x01 << 0) + +#define SMB_CTRL1_STASTRE (0x01 << 7) +#define SMB_CTRL1_NMINTE (0x01 << 6) +#define SMB_CTRL1_GCMEN (0x01 << 5) +#define SMB_CTRL1_ACK (0x01 << 4) +#define SMB_CTRL1_RSVD (0x01 << 3) +#define SMB_CTRL1_INTEN (0x01 << 2) +#define SMB_CTRL1_STOP (0x01 << 1) +#define SMB_CTRL1_START (0x01 << 0) + +#define SMB_ADD_SAEN (0x01 << 7) + +#define SMB_CTRL2_ENABLE 0x01 + +#define SMBUS_TIMEOUT (100*1000*10) +#define SMBUS_STATUS_MASK 0xfbff + +#define SMBUS_IO_BASE 0x6000 diff --git a/src/southbridge/amd/cs5536/Makefile.inc b/src/southbridge/amd/cs5536/Makefile.inc index a1a36833fc..75c6e5c930 100644 --- a/src/southbridge/amd/cs5536/Makefile.inc +++ b/src/southbridge/amd/cs5536/Makefile.inc @@ -18,5 +18,5 @@ ## driver-y += cs5536.c -driver-y += cs5536_ide.c -driver-y += cs5536_pirq.c +driver-y += ide.c +driver-y += pirq.c diff --git a/src/southbridge/amd/cs5536/cs5536_early_setup.c b/src/southbridge/amd/cs5536/cs5536_early_setup.c deleted file mode 100644 index 047c1a21a0..0000000000 --- a/src/southbridge/amd/cs5536/cs5536_early_setup.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007 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 version 2 as - * published by the Free Software Foundation. - * - * 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 - */ - -/* - * cs5536_early_setup.c: Early chipset initialization for CS5536 companion device - * This file implements the initialization sequence documented in section 4.2 of - * AMD Geode GX Processor CS5536 Companion Device GoedeROM Porting Guide. - */ - -/** - * @brief Setup PCI IDSEL for CS5536 - */ -static void cs5536_setup_extmsr(void) -{ - msr_t msr; - - /* forward MSR access to CS5536_GLINK_PORT_NUM to CS5536_DEV_NUM */ - msr.hi = msr.lo = 0x00000000; -#if CS5536_GLINK_PORT_NUM <= 4 - msr.lo = CS5536_DEV_NUM << (unsigned char)((CS5536_GLINK_PORT_NUM - 1) * 8); -#else - msr.hi = CS5536_DEV_NUM << (unsigned char)((CS5536_GLINK_PORT_NUM - 5) * 8); -#endif - wrmsr(GLPCI_ExtMSR, msr); -} - -static void cs5536_setup_idsel(void) -{ - /* write IDSEL to the write once register at address 0x0000 */ - outl(0x1 << (CS5536_DEV_NUM + 10), 0); -} - -static void cs5536_usb_swapsif(void) -{ - msr_t msr; - - msr = rdmsr(USB1_SB_GLD_MSR_CAP + 0x5); - //USB Serial short detect bit. - if (msr.hi & 0x10) { - /* We need to preserve bits 32,33,35 and not clear any BIST - * error, but clear the SERSHRT error bit */ - - msr.hi &= 0xFFFFFFFB; - wrmsr(USB1_SB_GLD_MSR_CAP + 0x5, msr); - } -} - -static void cs5536_setup_iobase(void) -{ - msr_t msr; - /* setup LBAR for SMBus controller */ - msr.hi = 0x0000f001; - msr.lo = SMBUS_IO_BASE; - wrmsr(MDD_LBAR_SMB, msr); - - /* setup LBAR for GPIO */ - msr.hi = 0x0000f001; - msr.lo = GPIO_IO_BASE; - wrmsr(MDD_LBAR_GPIO, msr); - - /* setup LBAR for MFGPT */ - msr.hi = 0x0000f001; - msr.lo = MFGPT_IO_BASE; - wrmsr(MDD_LBAR_MFGPT, msr); - - /* setup LBAR for ACPI */ - msr.hi = 0x0000f001; - msr.lo = ACPI_IO_BASE; - wrmsr(MDD_LBAR_ACPI, msr); - - /* setup LBAR for PM Support */ - msr.hi = 0x0000f001; - msr.lo = PMS_IO_BASE; - wrmsr(MDD_LBAR_PMS, msr); -} - -static void cs5536_setup_power_button(void) -{ -#if CONFIG_ENABLE_POWER_BUTTON - outl(0x40020000, PMS_IO_BASE + 0x40); -#endif - - /* setup WORK_AUX/GPIO24, it is the external signal for 5536 - * vsb_work_aux controls all voltage rails except Vstandby & Vmem. - * We need to enable, OUT_AUX1 and OUTPUT_ENABLE in this order. - * If WORK_AUX/GPIO24 is not enabled then soft-off will not work. - */ - outl(GPIOH_24_SET, GPIO_IO_BASE + GPIOH_OUT_AUX1_SELECT); - outl(GPIOH_24_SET, GPIO_IO_BASE + GPIOH_OUTPUT_ENABLE); - -} - -static void cs5536_setup_gpio(void) -{ - uint32_t val; - - /* setup GPIO pins 14/15 for SDA/SCL */ - val = GPIOL_15_SET | GPIOL_14_SET; - /* Output Enable */ - outl(val, GPIO_IO_BASE + GPIOL_OUT_AUX1_SELECT); - /* Output AUX1 */ - outl(val, GPIO_IO_BASE + GPIOL_OUTPUT_ENABLE); - /* Input Enable */ - outl(val, GPIO_IO_BASE + GPIOL_IN_AUX1_SELECT); - /* Input AUX1 */ - outl(val, GPIO_IO_BASE + GPIOL_INPUT_ENABLE); -} - -void cs5536_disable_internal_uart(void) -{ - msr_t msr; - /* The UARTs default to enabled. - * Disable and reset them and configure them later. (SIO init) - */ - msr = rdmsr(MDD_UART1_CONF); - msr.lo = 1; // reset - wrmsr(MDD_UART1_CONF, msr); - msr.lo = 0; // disabled - wrmsr(MDD_UART1_CONF, msr); - - msr = rdmsr(MDD_UART2_CONF); - msr.lo = 1; // reset - wrmsr(MDD_UART2_CONF, msr); - msr.lo = 0; // disabled - wrmsr(MDD_UART2_CONF, msr); -} - -static void cs5536_setup_cis_mode(void) -{ - msr_t msr; - - /* setup CPU interface serial to mode B to match CPU */ - msr = rdmsr(GLPCI_SB_CTRL); - msr.lo &= ~0x18; - msr.lo |= 0x10; - wrmsr(GLPCI_SB_CTRL, msr); -} - -/** - * Enable the on-chip UART. - * - * See page 412 of the AMD Geode CS5536 Companion Device data book. - */ -static void cs5536_setup_onchipuart1(void) -{ - msr_t msr; - - /* Setup early for polling only mode. - * 1. Enable GPIO 8 to OUT_AUX1, 9 to IN_AUX1. - * GPIO LBAR + 0x04, LBAR + 0x10, LBAR + 0x20, LBAR + 34 - * 2. Enable UART I/O space in MDD. - * MSR 0x51400014 bit 18:16 - * 3. Enable UART controller. - * MSR 0x5140003A bit 0, 1 - */ - - /* GPIO8 - UART1_TX */ - /* Set: Output Enable (0x4) */ - outl(GPIOL_8_SET, GPIO_IO_BASE + GPIOL_OUTPUT_ENABLE); - /* Set: OUTAUX1 Select (0x10) */ - outl(GPIOL_8_SET, GPIO_IO_BASE + GPIOL_OUT_AUX1_SELECT); - - /* GPIO9 - UART1_RX */ - /* Set: Input Enable (0x20) */ - outl(GPIOL_9_SET, GPIO_IO_BASE + GPIOL_INPUT_ENABLE); - /* Set: INAUX1 Select (0x34) */ - outl(GPIOL_9_SET, GPIO_IO_BASE + GPIOL_IN_AUX1_SELECT); - - /* Set address to 0x3F8. */ - msr = rdmsr(MDD_LEG_IO); - msr.lo |= 0x7 << 16; - wrmsr(MDD_LEG_IO, msr); - - /* Bit 1 = DEVEN (device enable) - * Bit 4 = EN_BANKS (allow access to the upper banks) - */ - msr.lo = (1 << 4) | (1 << 1); - msr.hi = 0; - - /* Enable COM1. */ - wrmsr(MDD_UART1_CONF, msr); -} - -static void cs5536_setup_onchipuart2(void) -{ - msr_t msr; - - /* GPIO4 - UART2_TX */ - /* Set: Output Enable (0x4) */ - outl(GPIOL_4_SET, GPIO_IO_BASE + GPIOL_OUTPUT_ENABLE); - /* Set: OUTAUX1 Select (0x10) */ - outl(GPIOL_4_SET, GPIO_IO_BASE + GPIOL_OUT_AUX1_SELECT); - /* GPIO4 - UART2_RX */ - /* Set: Input Enable (0x20) */ - outl(GPIOL_3_SET, GPIO_IO_BASE + GPIOL_INPUT_ENABLE); - /* Set: INAUX1 Select (0x34) */ - outl(GPIOL_3_SET, GPIO_IO_BASE + GPIOL_IN_AUX1_SELECT); - - /* Set: GPIO 3 + 3 Pull Up (0x18) */ - outl(GPIOL_3_SET | GPIOL_4_SET, - GPIO_IO_BASE + GPIOL_PULLUP_ENABLE); - - /* set address to 2F8 */ - msr = rdmsr(MDD_LEG_IO); - msr.lo |= 0x5 << 20; - wrmsr(MDD_LEG_IO, msr); - - /* Bit 1 = DEVEN (device enable) - * Bit 4 = EN_BANKS (allow access to the upper banks - */ - msr.lo = (1 << 4) | (1 << 1); - msr.hi = 0; - - /* enable COM2 */ - wrmsr(MDD_UART2_CONF, msr); -} - -void cs5536_setup_onchipuart(int uart) -{ - switch (uart) { - case 1: - cs5536_setup_onchipuart1(); - break; - case 2: - cs5536_setup_onchipuart2(); - break; - } -} - - -/* note: you can't do prints in here in most cases, - * and we don't want to hang on serial, so they are - * commented out - */ -static void cs5536_early_setup(void) -{ - msr_t msr; - - cs5536_setup_extmsr(); - cs5536_setup_cis_mode(); - - msr = rdmsr(GLCP_SYS_RSTPLL); - if (msr.lo & (0x3f << 26)) { - /* PLL is already set and we are reboot from PLL reset */ - //print_debug("reboot from BIOS reset\n"); - return; - } - //print_debug("Setup idsel\n"); - cs5536_setup_idsel(); - //print_debug("Setup iobase\n"); - cs5536_usb_swapsif(); - cs5536_setup_iobase(); - //print_debug("Setup gpio\n"); - cs5536_setup_gpio(); - //print_debug("Setup smbus\n"); - cs5536_enable_smbus(); - //print_debug("Setup power button\n"); - cs5536_setup_power_button(); -} diff --git a/src/southbridge/amd/cs5536/cs5536_early_smbus.c b/src/southbridge/amd/cs5536/cs5536_early_smbus.c deleted file mode 100644 index 5cb815d250..0000000000 --- a/src/southbridge/amd/cs5536/cs5536_early_smbus.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007 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 version 2 as - * published by the Free Software Foundation. - * - * 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 "cs5536.h" - -#define SMBUS_ERROR -1 -#define SMBUS_WAIT_UNTIL_READY_TIMEOUT -2 -#define SMBUS_WAIT_UNTIL_DONE_TIMEOUT -3 -#define SMBUS_TIMEOUT (1000) - -/* initialization for SMBus Controller */ -static void cs5536_enable_smbus(void) -{ - - /* Set SCL freq and enable SMB controller */ - /*outb((0x20 << 1) | SMB_CTRL2_ENABLE, smbus_io_base + SMB_CTRL2); */ - outb((0x7F << 1) | SMB_CTRL2_ENABLE, SMBUS_IO_BASE + SMB_CTRL2); - - /* Setup SMBus host controller address to 0xEF */ - outb((0xEF | SMB_ADD_SAEN), SMBUS_IO_BASE + SMB_ADD); - -} - -static void smbus_delay(void) -{ - /* inb(0x80); */ -} - -static int smbus_wait(unsigned smbus_io_base) -{ - unsigned long loops = SMBUS_TIMEOUT; - unsigned char val; - - do { - smbus_delay(); - val = inb(smbus_io_base + SMB_STS); - if ((val & SMB_STS_SDAST) != 0) - break; - if (val & (SMB_STS_BER | SMB_STS_NEGACK)) { - /*printk(BIOS_DEBUG, "SMBUS WAIT ERROR %x\n", val); */ - return SMBUS_ERROR; - } - } while (--loops); - return loops ? 0 : SMBUS_WAIT_UNTIL_READY_TIMEOUT; -} - -/* generate a smbus start condition */ -static int smbus_start_condition(unsigned smbus_io_base) -{ - unsigned char val; - - /* issue a START condition */ - val = inb(smbus_io_base + SMB_CTRL1); - outb(val | SMB_CTRL1_START, smbus_io_base + SMB_CTRL1); - - /* check for bus conflict */ - val = inb(smbus_io_base + SMB_STS); - if ((val & SMB_STS_BER) != 0) - return SMBUS_ERROR; - - return smbus_wait(smbus_io_base); -} - -static int smbus_check_stop_condition(unsigned smbus_io_base) -{ - unsigned char val; - unsigned long loops; - loops = SMBUS_TIMEOUT; - /* check for SDA status */ - do { - smbus_delay(); - val = inb(smbus_io_base + SMB_CTRL1); - if ((val & SMB_CTRL1_STOP) == 0) { - break; - } - outb((0x7F << 1) | SMB_CTRL2_ENABLE, smbus_io_base + SMB_CTRL2); - } while (--loops); - return loops ? 0 : SMBUS_WAIT_UNTIL_READY_TIMEOUT; -} - -static int smbus_stop_condition(unsigned smbus_io_base) -{ - outb(SMB_CTRL1_STOP, smbus_io_base + SMB_CTRL1); - return smbus_wait(smbus_io_base); -} - -static int smbus_ack(unsigned smbus_io_base, int state) -{ - unsigned char val = inb(smbus_io_base + SMB_CTRL1); - -/* if (state) */ - outb(val | SMB_CTRL1_ACK, smbus_io_base + SMB_CTRL1); -/* else - outb(val & ~SMB_CTRL1_ACK, smbus_io_base + SMB_CTRL1); -*/ - return 0; -} - -static int smbus_send_slave_address(unsigned smbus_io_base, - unsigned char device) -{ - unsigned char val; - - /* send the slave address */ - outb(device, smbus_io_base + SMB_SDA); - - /* check for bus conflict and NACK */ - val = inb(smbus_io_base + SMB_STS); - if (((val & SMB_STS_BER) != 0) || ((val & SMB_STS_NEGACK) != 0)) { - /* printk(BIOS_DEBUG, "SEND SLAVE ERROR (%x)\n", val); */ - return SMBUS_ERROR; - } - return smbus_wait(smbus_io_base); -} - -static int smbus_send_command(unsigned smbus_io_base, unsigned char command) -{ - unsigned char val; - - /* send the command */ - outb(command, smbus_io_base + SMB_SDA); - - /* check for bus conflict and NACK */ - val = inb(smbus_io_base + SMB_STS); - if (((val & SMB_STS_BER) != 0) || ((val & SMB_STS_NEGACK) != 0)) - return SMBUS_ERROR; - - return smbus_wait(smbus_io_base); -} - -static unsigned char smbus_get_result(unsigned smbus_io_base) -{ - return inb(smbus_io_base + SMB_SDA); -} - -static unsigned char do_smbus_read_byte(unsigned smbus_io_base, - unsigned char device, - unsigned char address) -{ - unsigned char error = 0; - - if ((smbus_check_stop_condition(smbus_io_base))) { - error = 1; - goto err; - } - - if ((smbus_start_condition(smbus_io_base))) { - error = 2; - goto err; - } - - if ((smbus_send_slave_address(smbus_io_base, device << 1))) { - error = 3; - goto err; - } - - smbus_ack(smbus_io_base, 1); - - if ((smbus_send_command(smbus_io_base, address))) { - error = 4; - goto err; - } - - if ((smbus_start_condition(smbus_io_base))) { - error = 5; - goto err; - } - - if ((smbus_send_slave_address(smbus_io_base, (device << 1) | 0x01))) { - error = 6; - goto err; - } - - if ((smbus_stop_condition(smbus_io_base))) { - error = 7; - goto err; - } - - return smbus_get_result(smbus_io_base); - - err: - print_debug("SMBUS READ ERROR:"); - print_debug_hex8(error); - print_debug(" device:"); - print_debug_hex8(device); - print_debug("\n"); - /* stop, clean up the error, and leave */ - smbus_stop_condition(smbus_io_base); - outb(inb(smbus_io_base + SMB_STS), smbus_io_base + SMB_STS); - outb(0x0, smbus_io_base + SMB_STS); - return 0xFF; -} - -static inline int smbus_read_byte(unsigned device, unsigned address) -{ - return do_smbus_read_byte(SMBUS_IO_BASE, device, address); -} diff --git a/src/southbridge/amd/cs5536/cs5536_ide.c b/src/southbridge/amd/cs5536/cs5536_ide.c deleted file mode 100644 index c4cc652e93..0000000000 --- a/src/southbridge/amd/cs5536/cs5536_ide.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007 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 version 2 as - * published by the Free Software Foundation. - * - * 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 -#include -#include -#include -#include -#include "cs5536.h" - -#define IDE_CFG 0x40 - #define CHANEN (1L << 1) - #define PWB (1L << 14) - #define CABLE (1L << 16) -#define IDE_DTC 0x48 -#define IDE_CAST 0x4C -#define IDE_ETC 0x50 - -static void ide_init(struct device *dev) -{ - uint32_t ide_cfg; - - printk(BIOS_SPEW, "cs5536_ide: %s\n", __func__); - /* GPIO and IRQ setup are handled in the main chipset code. */ - - // Enable the channel and Post Write Buffer - // NOTE: Only 32-bit writes to the data buffer are allowed when PWB is set - ide_cfg = pci_read_config32(dev, IDE_CFG); - ide_cfg |= CHANEN | PWB; - pci_write_config32(dev, IDE_CFG, ide_cfg); -} - -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, - .enable = 0, -}; - -static const struct pci_driver ide_driver __pci_driver = { - .ops = &ide_ops, - .vendor = PCI_VENDOR_ID_AMD, - .device = PCI_DEVICE_ID_AMD_CS5536_B0_IDE, -}; diff --git a/src/southbridge/amd/cs5536/cs5536_pirq.c b/src/southbridge/amd/cs5536/cs5536_pirq.c deleted file mode 100644 index b2ae1fe3af..0000000000 --- a/src/southbridge/amd/cs5536/cs5536_pirq.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007 Nikolay Petukhov - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * 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 -#include -#include -#include - -#if (CONFIG_PIRQ_ROUTE==1 && CONFIG_GENERATE_PIRQ_TABLE==1) -void pirq_assign_irqs(const unsigned char pIntAtoD[4]) -{ - device_t pdev; - - pdev = dev_find_device(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_AMD_CS5536_ISA, 0); - - if (pdev) { - pci_write_config16(pdev, 0x5c, (pIntAtoD[3] << 12 - | pIntAtoD[2] << 8 | pIntAtoD[1] << 4 | pIntAtoD[0])); - } -} -#endif diff --git a/src/southbridge/amd/cs5536/cs5536_smbus2.h b/src/southbridge/amd/cs5536/cs5536_smbus2.h deleted file mode 100644 index dea08a437c..0000000000 --- a/src/southbridge/amd/cs5536/cs5536_smbus2.h +++ /dev/null @@ -1,317 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * 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 - */ - -#define SMBUS_ERROR -1 -#define SMBUS_WAIT_UNTIL_READY_TIMEOUT -2 -#define SMBUS_WAIT_UNTIL_DONE_TIMEOUT -3 - -#define SMB_SDA 0x00 -#define SMB_STS 0x01 -#define SMB_CTRL_STS 0x02 -#define SMB_CTRL1 0x03 -#define SMB_ADD 0x04 -#define SMB_CTRL2 0x05 -#define SMB_CTRL3 0x06 - -#define SMB_STS_SLVSTP (0x01 << 7) -#define SMB_STS_SDAST (0x01 << 6) -#define SMB_STS_BER (0x01 << 5) -#define SMB_STS_NEGACK (0x01 << 4) -#define SMB_STS_STASTR (0x01 << 3) -#define SMB_STS_NMATCH (0x01 << 2) -#define SMB_STS_MASTER (0x01 << 1) -#define SMB_STS_XMIT (0x01 << 0) - -#define SMB_CSTS_TGSCL (0x01 << 5) -#define SMB_CSTS_TSDA (0x01 << 4) -#define SMB_CSTS_GCMTCH (0x01 << 3) -#define SMB_CSTS_MATCH (0x01 << 2) -#define SMB_CSTS_BB (0x01 << 1) -#define SMB_CSTS_BUSY (0x01 << 0) - -#define SMB_CTRL1_STASTRE (0x01 << 7) -#define SMB_CTRL1_NMINTE (0x01 << 6) -#define SMB_CTRL1_GCMEN (0x01 << 5) -#define SMB_CTRL1_ACK (0x01 << 4) -#define SMB_CTRL1_RSVD (0x01 << 3) -#define SMB_CTRL1_INTEN (0x01 << 2) -#define SMB_CTRL1_STOP (0x01 << 1) -#define SMB_CTRL1_START (0x01 << 0) - -#define SMB_ADD_SAEN (0x01 << 7) - -#define SMB_CTRL2_ENABLE 0x01 - -#define SMBUS_TIMEOUT (100*1000*10) -#define SMBUS_STATUS_MASK 0xfbff - -static void smbus_delay(void) -{ - inb(0x80); -} - -static int smbus_wait(unsigned smbus_io_base) -{ - unsigned long loops = SMBUS_TIMEOUT; - unsigned char val; - - do { - smbus_delay(); - val = inb(smbus_io_base + SMB_STS); - if ((val & SMB_STS_SDAST) != 0) - break; - if (val & (SMB_STS_BER | SMB_STS_NEGACK)) { - printk(BIOS_DEBUG, "SMBUS WAIT ERROR %x\n", val); - return SMBUS_ERROR; - } - } while (--loops); - - outb(0, smbus_io_base + SMB_STS); - return loops ? 0 : SMBUS_WAIT_UNTIL_READY_TIMEOUT; -} - -static int smbus_write(unsigned smbus_io_base, unsigned char byte) -{ - - outb(byte, smbus_io_base + SMB_SDA); - return smbus_wait(smbus_io_base); -} - -/* generate a smbus start condition */ -static int smbus_start_condition(unsigned smbus_io_base) -{ - unsigned char val; - - /* issue a START condition */ - val = inb(smbus_io_base + SMB_CTRL1); - outb(val | SMB_CTRL1_START, smbus_io_base + SMB_CTRL1); - - /* check for bus conflict */ - val = inb(smbus_io_base + SMB_STS); - if ((val & SMB_STS_BER) != 0) - return SMBUS_ERROR; - - return smbus_wait(smbus_io_base); -} - -static int smbus_check_stop_condition(unsigned smbus_io_base) -{ - unsigned char val; - unsigned long loops; - loops = SMBUS_TIMEOUT; - /* check for SDA status */ - do { - smbus_delay(); - val = inb(smbus_io_base + SMB_CTRL1); - if ((val & SMB_CTRL1_STOP) == 0) { - break; - } - } while (--loops); - return loops ? 0 : SMBUS_WAIT_UNTIL_READY_TIMEOUT; - - /* Make sure everything is cleared and ready to go */ - - val = inb(smbus_io_base + SMB_CTRL1); - outb(val & ~(SMB_CTRL1_STASTRE | SMB_CTRL1_NMINTE), - smbus_io_base + SMB_CTRL1); - - outb(SMB_STS_BER | SMB_STS_NEGACK | SMB_STS_STASTR, - smbus_io_base + SMB_STS); - - val = inb(smbus_io_base + SMB_CTRL_STS); - outb(val | SMB_CSTS_BB, smbus_io_base + SMB_CTRL_STS); -} - -static int smbus_stop_condition(unsigned smbus_io_base) -{ - unsigned char val; - val = inb(smbus_io_base + SMB_CTRL1); - outb(SMB_CTRL1_STOP, smbus_io_base + SMB_CTRL1); - - return 0; -} - -static int smbus_ack(unsigned smbus_io_base, int state) -{ - unsigned char val = inb(smbus_io_base + SMB_CTRL1); - - if (state) - outb(val | SMB_CTRL1_ACK, smbus_io_base + SMB_CTRL1); - else - outb(val & ~SMB_CTRL1_ACK, smbus_io_base + SMB_CTRL1); - - return 0; -} - -static int smbus_send_slave_address(unsigned smbus_io_base, - unsigned char device) -{ - unsigned char val; - - /* send the slave address */ - outb(device, smbus_io_base + SMB_SDA); - - /* check for bus conflict and NACK */ - val = inb(smbus_io_base + SMB_STS); - if (((val & SMB_STS_BER) != 0) || ((val & SMB_STS_NEGACK) != 0)) { - printk(BIOS_DEBUG, "SEND SLAVE ERROR (%x)\n", val); - return SMBUS_ERROR; - } - return smbus_wait(smbus_io_base); -} - -static int smbus_send_command(unsigned smbus_io_base, unsigned char command) -{ - unsigned char val; - - /* send the command */ - outb(command, smbus_io_base + SMB_SDA); - - /* check for bus conflict and NACK */ - val = inb(smbus_io_base + SMB_STS); - if (((val & SMB_STS_BER) != 0) || ((val & SMB_STS_NEGACK) != 0)) - return SMBUS_ERROR; - - return smbus_wait(smbus_io_base); -} - -static void _doread(unsigned smbus_io_base, unsigned char device, - unsigned char address, unsigned char *data, int count) -{ - int ret; - int index = 0; - unsigned char val; - - if ((ret = smbus_check_stop_condition(smbus_io_base))) - goto err; - - index++; - - if ((ret = smbus_start_condition(smbus_io_base))) - goto err; - - index++; /* 2 */ - if ((ret = smbus_send_slave_address(smbus_io_base, device))) - goto err; - - index++; - if ((ret = smbus_send_command(smbus_io_base, address))) - goto err; - - index++; - if ((ret = smbus_start_condition(smbus_io_base))) - goto err; - - /* Clear the ack for multiple byte reads */ - smbus_ack(smbus_io_base, (count == 1) ? 1 : 0); - - index++; - if ((ret = smbus_send_slave_address(smbus_io_base, device | 0x01))) - goto err; - - while (count) { - /* Set the ACK if this is the next to last byte */ - smbus_ack(smbus_io_base, (count == 2) ? 1 : 0); - - /* Set the stop bit if this is the last byte to read */ - - if (count == 1) - smbus_stop_condition(smbus_io_base); - - val = inb(smbus_io_base + SMB_SDA); - *data++ = val; - - if (count > 1) { - ret = smbus_wait(smbus_io_base); - if (ret) - return; - } - - count--; - } - - return; - - err: - printk(BIOS_DEBUG, "SMBUS READ ERROR (%d): %d\n", index, ret); -} - -static inline unsigned char do_smbus_read_byte(unsigned smbus_io_base, - unsigned char device, unsigned char address) -{ - unsigned char val = 0; - _doread(smbus_io_base, device, address, &val, sizeof(val)); - return val; -} - -static inline unsigned short do_smbus_read_word(unsigned smbus_io_base, - unsigned char device, unsigned char address) -{ - unsigned short val = 0; - _doread(smbus_io_base, device, address, (unsigned char *)&val, - sizeof(val)); - return val; -} - -static int _dowrite(unsigned smbus_io_base, unsigned char device, - unsigned char address, unsigned char *data, int count) -{ - - int ret; - - if ((ret = smbus_check_stop_condition(smbus_io_base))) - goto err; - - if ((ret = smbus_start_condition(smbus_io_base))) - goto err; - - if ((ret = smbus_send_slave_address(smbus_io_base, device))) - goto err; - - if ((ret = smbus_send_command(smbus_io_base, address))) - goto err; - - while (count) { - if ((ret = smbus_write(smbus_io_base, *data++))) - goto err; - count--; - } - - smbus_stop_condition(smbus_io_base); - return 0; - - err: - printk(BIOS_DEBUG, "SMBUS WRITE ERROR: %d\n", ret); - return -1; -} - -static inline int do_smbus_write_byte(unsigned smbus_io_base, - unsigned char device, unsigned char address, unsigned char data) -{ - return _dowrite(smbus_io_base, device, address, - (unsigned char *)&data, 1); -} - -static inline int do_smbus_write_word(unsigned smbus_io_base, - unsigned char device, unsigned char address, unsigned short data) -{ - return _dowrite(smbus_io_base, device, address, (unsigned char *)&data, - 2); -} diff --git a/src/southbridge/amd/cs5536/early_setup.c b/src/southbridge/amd/cs5536/early_setup.c new file mode 100644 index 0000000000..047c1a21a0 --- /dev/null +++ b/src/southbridge/amd/cs5536/early_setup.c @@ -0,0 +1,275 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007 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 version 2 as + * published by the Free Software Foundation. + * + * 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 + */ + +/* + * cs5536_early_setup.c: Early chipset initialization for CS5536 companion device + * This file implements the initialization sequence documented in section 4.2 of + * AMD Geode GX Processor CS5536 Companion Device GoedeROM Porting Guide. + */ + +/** + * @brief Setup PCI IDSEL for CS5536 + */ +static void cs5536_setup_extmsr(void) +{ + msr_t msr; + + /* forward MSR access to CS5536_GLINK_PORT_NUM to CS5536_DEV_NUM */ + msr.hi = msr.lo = 0x00000000; +#if CS5536_GLINK_PORT_NUM <= 4 + msr.lo = CS5536_DEV_NUM << (unsigned char)((CS5536_GLINK_PORT_NUM - 1) * 8); +#else + msr.hi = CS5536_DEV_NUM << (unsigned char)((CS5536_GLINK_PORT_NUM - 5) * 8); +#endif + wrmsr(GLPCI_ExtMSR, msr); +} + +static void cs5536_setup_idsel(void) +{ + /* write IDSEL to the write once register at address 0x0000 */ + outl(0x1 << (CS5536_DEV_NUM + 10), 0); +} + +static void cs5536_usb_swapsif(void) +{ + msr_t msr; + + msr = rdmsr(USB1_SB_GLD_MSR_CAP + 0x5); + //USB Serial short detect bit. + if (msr.hi & 0x10) { + /* We need to preserve bits 32,33,35 and not clear any BIST + * error, but clear the SERSHRT error bit */ + + msr.hi &= 0xFFFFFFFB; + wrmsr(USB1_SB_GLD_MSR_CAP + 0x5, msr); + } +} + +static void cs5536_setup_iobase(void) +{ + msr_t msr; + /* setup LBAR for SMBus controller */ + msr.hi = 0x0000f001; + msr.lo = SMBUS_IO_BASE; + wrmsr(MDD_LBAR_SMB, msr); + + /* setup LBAR for GPIO */ + msr.hi = 0x0000f001; + msr.lo = GPIO_IO_BASE; + wrmsr(MDD_LBAR_GPIO, msr); + + /* setup LBAR for MFGPT */ + msr.hi = 0x0000f001; + msr.lo = MFGPT_IO_BASE; + wrmsr(MDD_LBAR_MFGPT, msr); + + /* setup LBAR for ACPI */ + msr.hi = 0x0000f001; + msr.lo = ACPI_IO_BASE; + wrmsr(MDD_LBAR_ACPI, msr); + + /* setup LBAR for PM Support */ + msr.hi = 0x0000f001; + msr.lo = PMS_IO_BASE; + wrmsr(MDD_LBAR_PMS, msr); +} + +static void cs5536_setup_power_button(void) +{ +#if CONFIG_ENABLE_POWER_BUTTON + outl(0x40020000, PMS_IO_BASE + 0x40); +#endif + + /* setup WORK_AUX/GPIO24, it is the external signal for 5536 + * vsb_work_aux controls all voltage rails except Vstandby & Vmem. + * We need to enable, OUT_AUX1 and OUTPUT_ENABLE in this order. + * If WORK_AUX/GPIO24 is not enabled then soft-off will not work. + */ + outl(GPIOH_24_SET, GPIO_IO_BASE + GPIOH_OUT_AUX1_SELECT); + outl(GPIOH_24_SET, GPIO_IO_BASE + GPIOH_OUTPUT_ENABLE); + +} + +static void cs5536_setup_gpio(void) +{ + uint32_t val; + + /* setup GPIO pins 14/15 for SDA/SCL */ + val = GPIOL_15_SET | GPIOL_14_SET; + /* Output Enable */ + outl(val, GPIO_IO_BASE + GPIOL_OUT_AUX1_SELECT); + /* Output AUX1 */ + outl(val, GPIO_IO_BASE + GPIOL_OUTPUT_ENABLE); + /* Input Enable */ + outl(val, GPIO_IO_BASE + GPIOL_IN_AUX1_SELECT); + /* Input AUX1 */ + outl(val, GPIO_IO_BASE + GPIOL_INPUT_ENABLE); +} + +void cs5536_disable_internal_uart(void) +{ + msr_t msr; + /* The UARTs default to enabled. + * Disable and reset them and configure them later. (SIO init) + */ + msr = rdmsr(MDD_UART1_CONF); + msr.lo = 1; // reset + wrmsr(MDD_UART1_CONF, msr); + msr.lo = 0; // disabled + wrmsr(MDD_UART1_CONF, msr); + + msr = rdmsr(MDD_UART2_CONF); + msr.lo = 1; // reset + wrmsr(MDD_UART2_CONF, msr); + msr.lo = 0; // disabled + wrmsr(MDD_UART2_CONF, msr); +} + +static void cs5536_setup_cis_mode(void) +{ + msr_t msr; + + /* setup CPU interface serial to mode B to match CPU */ + msr = rdmsr(GLPCI_SB_CTRL); + msr.lo &= ~0x18; + msr.lo |= 0x10; + wrmsr(GLPCI_SB_CTRL, msr); +} + +/** + * Enable the on-chip UART. + * + * See page 412 of the AMD Geode CS5536 Companion Device data book. + */ +static void cs5536_setup_onchipuart1(void) +{ + msr_t msr; + + /* Setup early for polling only mode. + * 1. Enable GPIO 8 to OUT_AUX1, 9 to IN_AUX1. + * GPIO LBAR + 0x04, LBAR + 0x10, LBAR + 0x20, LBAR + 34 + * 2. Enable UART I/O space in MDD. + * MSR 0x51400014 bit 18:16 + * 3. Enable UART controller. + * MSR 0x5140003A bit 0, 1 + */ + + /* GPIO8 - UART1_TX */ + /* Set: Output Enable (0x4) */ + outl(GPIOL_8_SET, GPIO_IO_BASE + GPIOL_OUTPUT_ENABLE); + /* Set: OUTAUX1 Select (0x10) */ + outl(GPIOL_8_SET, GPIO_IO_BASE + GPIOL_OUT_AUX1_SELECT); + + /* GPIO9 - UART1_RX */ + /* Set: Input Enable (0x20) */ + outl(GPIOL_9_SET, GPIO_IO_BASE + GPIOL_INPUT_ENABLE); + /* Set: INAUX1 Select (0x34) */ + outl(GPIOL_9_SET, GPIO_IO_BASE + GPIOL_IN_AUX1_SELECT); + + /* Set address to 0x3F8. */ + msr = rdmsr(MDD_LEG_IO); + msr.lo |= 0x7 << 16; + wrmsr(MDD_LEG_IO, msr); + + /* Bit 1 = DEVEN (device enable) + * Bit 4 = EN_BANKS (allow access to the upper banks) + */ + msr.lo = (1 << 4) | (1 << 1); + msr.hi = 0; + + /* Enable COM1. */ + wrmsr(MDD_UART1_CONF, msr); +} + +static void cs5536_setup_onchipuart2(void) +{ + msr_t msr; + + /* GPIO4 - UART2_TX */ + /* Set: Output Enable (0x4) */ + outl(GPIOL_4_SET, GPIO_IO_BASE + GPIOL_OUTPUT_ENABLE); + /* Set: OUTAUX1 Select (0x10) */ + outl(GPIOL_4_SET, GPIO_IO_BASE + GPIOL_OUT_AUX1_SELECT); + /* GPIO4 - UART2_RX */ + /* Set: Input Enable (0x20) */ + outl(GPIOL_3_SET, GPIO_IO_BASE + GPIOL_INPUT_ENABLE); + /* Set: INAUX1 Select (0x34) */ + outl(GPIOL_3_SET, GPIO_IO_BASE + GPIOL_IN_AUX1_SELECT); + + /* Set: GPIO 3 + 3 Pull Up (0x18) */ + outl(GPIOL_3_SET | GPIOL_4_SET, + GPIO_IO_BASE + GPIOL_PULLUP_ENABLE); + + /* set address to 2F8 */ + msr = rdmsr(MDD_LEG_IO); + msr.lo |= 0x5 << 20; + wrmsr(MDD_LEG_IO, msr); + + /* Bit 1 = DEVEN (device enable) + * Bit 4 = EN_BANKS (allow access to the upper banks + */ + msr.lo = (1 << 4) | (1 << 1); + msr.hi = 0; + + /* enable COM2 */ + wrmsr(MDD_UART2_CONF, msr); +} + +void cs5536_setup_onchipuart(int uart) +{ + switch (uart) { + case 1: + cs5536_setup_onchipuart1(); + break; + case 2: + cs5536_setup_onchipuart2(); + break; + } +} + + +/* note: you can't do prints in here in most cases, + * and we don't want to hang on serial, so they are + * commented out + */ +static void cs5536_early_setup(void) +{ + msr_t msr; + + cs5536_setup_extmsr(); + cs5536_setup_cis_mode(); + + msr = rdmsr(GLCP_SYS_RSTPLL); + if (msr.lo & (0x3f << 26)) { + /* PLL is already set and we are reboot from PLL reset */ + //print_debug("reboot from BIOS reset\n"); + return; + } + //print_debug("Setup idsel\n"); + cs5536_setup_idsel(); + //print_debug("Setup iobase\n"); + cs5536_usb_swapsif(); + cs5536_setup_iobase(); + //print_debug("Setup gpio\n"); + cs5536_setup_gpio(); + //print_debug("Setup smbus\n"); + cs5536_enable_smbus(); + //print_debug("Setup power button\n"); + cs5536_setup_power_button(); +} diff --git a/src/southbridge/amd/cs5536/early_smbus.c b/src/southbridge/amd/cs5536/early_smbus.c new file mode 100644 index 0000000000..5cb815d250 --- /dev/null +++ b/src/southbridge/amd/cs5536/early_smbus.c @@ -0,0 +1,213 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007 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 version 2 as + * published by the Free Software Foundation. + * + * 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 "cs5536.h" + +#define SMBUS_ERROR -1 +#define SMBUS_WAIT_UNTIL_READY_TIMEOUT -2 +#define SMBUS_WAIT_UNTIL_DONE_TIMEOUT -3 +#define SMBUS_TIMEOUT (1000) + +/* initialization for SMBus Controller */ +static void cs5536_enable_smbus(void) +{ + + /* Set SCL freq and enable SMB controller */ + /*outb((0x20 << 1) | SMB_CTRL2_ENABLE, smbus_io_base + SMB_CTRL2); */ + outb((0x7F << 1) | SMB_CTRL2_ENABLE, SMBUS_IO_BASE + SMB_CTRL2); + + /* Setup SMBus host controller address to 0xEF */ + outb((0xEF | SMB_ADD_SAEN), SMBUS_IO_BASE + SMB_ADD); + +} + +static void smbus_delay(void) +{ + /* inb(0x80); */ +} + +static int smbus_wait(unsigned smbus_io_base) +{ + unsigned long loops = SMBUS_TIMEOUT; + unsigned char val; + + do { + smbus_delay(); + val = inb(smbus_io_base + SMB_STS); + if ((val & SMB_STS_SDAST) != 0) + break; + if (val & (SMB_STS_BER | SMB_STS_NEGACK)) { + /*printk(BIOS_DEBUG, "SMBUS WAIT ERROR %x\n", val); */ + return SMBUS_ERROR; + } + } while (--loops); + return loops ? 0 : SMBUS_WAIT_UNTIL_READY_TIMEOUT; +} + +/* generate a smbus start condition */ +static int smbus_start_condition(unsigned smbus_io_base) +{ + unsigned char val; + + /* issue a START condition */ + val = inb(smbus_io_base + SMB_CTRL1); + outb(val | SMB_CTRL1_START, smbus_io_base + SMB_CTRL1); + + /* check for bus conflict */ + val = inb(smbus_io_base + SMB_STS); + if ((val & SMB_STS_BER) != 0) + return SMBUS_ERROR; + + return smbus_wait(smbus_io_base); +} + +static int smbus_check_stop_condition(unsigned smbus_io_base) +{ + unsigned char val; + unsigned long loops; + loops = SMBUS_TIMEOUT; + /* check for SDA status */ + do { + smbus_delay(); + val = inb(smbus_io_base + SMB_CTRL1); + if ((val & SMB_CTRL1_STOP) == 0) { + break; + } + outb((0x7F << 1) | SMB_CTRL2_ENABLE, smbus_io_base + SMB_CTRL2); + } while (--loops); + return loops ? 0 : SMBUS_WAIT_UNTIL_READY_TIMEOUT; +} + +static int smbus_stop_condition(unsigned smbus_io_base) +{ + outb(SMB_CTRL1_STOP, smbus_io_base + SMB_CTRL1); + return smbus_wait(smbus_io_base); +} + +static int smbus_ack(unsigned smbus_io_base, int state) +{ + unsigned char val = inb(smbus_io_base + SMB_CTRL1); + +/* if (state) */ + outb(val | SMB_CTRL1_ACK, smbus_io_base + SMB_CTRL1); +/* else + outb(val & ~SMB_CTRL1_ACK, smbus_io_base + SMB_CTRL1); +*/ + return 0; +} + +static int smbus_send_slave_address(unsigned smbus_io_base, + unsigned char device) +{ + unsigned char val; + + /* send the slave address */ + outb(device, smbus_io_base + SMB_SDA); + + /* check for bus conflict and NACK */ + val = inb(smbus_io_base + SMB_STS); + if (((val & SMB_STS_BER) != 0) || ((val & SMB_STS_NEGACK) != 0)) { + /* printk(BIOS_DEBUG, "SEND SLAVE ERROR (%x)\n", val); */ + return SMBUS_ERROR; + } + return smbus_wait(smbus_io_base); +} + +static int smbus_send_command(unsigned smbus_io_base, unsigned char command) +{ + unsigned char val; + + /* send the command */ + outb(command, smbus_io_base + SMB_SDA); + + /* check for bus conflict and NACK */ + val = inb(smbus_io_base + SMB_STS); + if (((val & SMB_STS_BER) != 0) || ((val & SMB_STS_NEGACK) != 0)) + return SMBUS_ERROR; + + return smbus_wait(smbus_io_base); +} + +static unsigned char smbus_get_result(unsigned smbus_io_base) +{ + return inb(smbus_io_base + SMB_SDA); +} + +static unsigned char do_smbus_read_byte(unsigned smbus_io_base, + unsigned char device, + unsigned char address) +{ + unsigned char error = 0; + + if ((smbus_check_stop_condition(smbus_io_base))) { + error = 1; + goto err; + } + + if ((smbus_start_condition(smbus_io_base))) { + error = 2; + goto err; + } + + if ((smbus_send_slave_address(smbus_io_base, device << 1))) { + error = 3; + goto err; + } + + smbus_ack(smbus_io_base, 1); + + if ((smbus_send_command(smbus_io_base, address))) { + error = 4; + goto err; + } + + if ((smbus_start_condition(smbus_io_base))) { + error = 5; + goto err; + } + + if ((smbus_send_slave_address(smbus_io_base, (device << 1) | 0x01))) { + error = 6; + goto err; + } + + if ((smbus_stop_condition(smbus_io_base))) { + error = 7; + goto err; + } + + return smbus_get_result(smbus_io_base); + + err: + print_debug("SMBUS READ ERROR:"); + print_debug_hex8(error); + print_debug(" device:"); + print_debug_hex8(device); + print_debug("\n"); + /* stop, clean up the error, and leave */ + smbus_stop_condition(smbus_io_base); + outb(inb(smbus_io_base + SMB_STS), smbus_io_base + SMB_STS); + outb(0x0, smbus_io_base + SMB_STS); + return 0xFF; +} + +static inline int smbus_read_byte(unsigned device, unsigned address) +{ + return do_smbus_read_byte(SMBUS_IO_BASE, device, address); +} diff --git a/src/southbridge/amd/cs5536/ide.c b/src/southbridge/amd/cs5536/ide.c new file mode 100644 index 0000000000..c4cc652e93 --- /dev/null +++ b/src/southbridge/amd/cs5536/ide.c @@ -0,0 +1,61 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007 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 version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include "cs5536.h" + +#define IDE_CFG 0x40 + #define CHANEN (1L << 1) + #define PWB (1L << 14) + #define CABLE (1L << 16) +#define IDE_DTC 0x48 +#define IDE_CAST 0x4C +#define IDE_ETC 0x50 + +static void ide_init(struct device *dev) +{ + uint32_t ide_cfg; + + printk(BIOS_SPEW, "cs5536_ide: %s\n", __func__); + /* GPIO and IRQ setup are handled in the main chipset code. */ + + // Enable the channel and Post Write Buffer + // NOTE: Only 32-bit writes to the data buffer are allowed when PWB is set + ide_cfg = pci_read_config32(dev, IDE_CFG); + ide_cfg |= CHANEN | PWB; + pci_write_config32(dev, IDE_CFG, ide_cfg); +} + +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, + .enable = 0, +}; + +static const struct pci_driver ide_driver __pci_driver = { + .ops = &ide_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_CS5536_B0_IDE, +}; diff --git a/src/southbridge/amd/cs5536/pirq.c b/src/southbridge/amd/cs5536/pirq.c new file mode 100644 index 0000000000..b2ae1fe3af --- /dev/null +++ b/src/southbridge/amd/cs5536/pirq.c @@ -0,0 +1,39 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007 Nikolay Petukhov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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 +#include +#include +#include + +#if (CONFIG_PIRQ_ROUTE==1 && CONFIG_GENERATE_PIRQ_TABLE==1) +void pirq_assign_irqs(const unsigned char pIntAtoD[4]) +{ + device_t pdev; + + pdev = dev_find_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_CS5536_ISA, 0); + + if (pdev) { + pci_write_config16(pdev, 0x5c, (pIntAtoD[3] << 12 + | pIntAtoD[2] << 8 | pIntAtoD[1] << 4 | pIntAtoD[0])); + } +} +#endif diff --git a/src/southbridge/amd/cs5536/smbus2.h b/src/southbridge/amd/cs5536/smbus2.h new file mode 100644 index 0000000000..dea08a437c --- /dev/null +++ b/src/southbridge/amd/cs5536/smbus2.h @@ -0,0 +1,317 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007 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; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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 + */ + +#define SMBUS_ERROR -1 +#define SMBUS_WAIT_UNTIL_READY_TIMEOUT -2 +#define SMBUS_WAIT_UNTIL_DONE_TIMEOUT -3 + +#define SMB_SDA 0x00 +#define SMB_STS 0x01 +#define SMB_CTRL_STS 0x02 +#define SMB_CTRL1 0x03 +#define SMB_ADD 0x04 +#define SMB_CTRL2 0x05 +#define SMB_CTRL3 0x06 + +#define SMB_STS_SLVSTP (0x01 << 7) +#define SMB_STS_SDAST (0x01 << 6) +#define SMB_STS_BER (0x01 << 5) +#define SMB_STS_NEGACK (0x01 << 4) +#define SMB_STS_STASTR (0x01 << 3) +#define SMB_STS_NMATCH (0x01 << 2) +#define SMB_STS_MASTER (0x01 << 1) +#define SMB_STS_XMIT (0x01 << 0) + +#define SMB_CSTS_TGSCL (0x01 << 5) +#define SMB_CSTS_TSDA (0x01 << 4) +#define SMB_CSTS_GCMTCH (0x01 << 3) +#define SMB_CSTS_MATCH (0x01 << 2) +#define SMB_CSTS_BB (0x01 << 1) +#define SMB_CSTS_BUSY (0x01 << 0) + +#define SMB_CTRL1_STASTRE (0x01 << 7) +#define SMB_CTRL1_NMINTE (0x01 << 6) +#define SMB_CTRL1_GCMEN (0x01 << 5) +#define SMB_CTRL1_ACK (0x01 << 4) +#define SMB_CTRL1_RSVD (0x01 << 3) +#define SMB_CTRL1_INTEN (0x01 << 2) +#define SMB_CTRL1_STOP (0x01 << 1) +#define SMB_CTRL1_START (0x01 << 0) + +#define SMB_ADD_SAEN (0x01 << 7) + +#define SMB_CTRL2_ENABLE 0x01 + +#define SMBUS_TIMEOUT (100*1000*10) +#define SMBUS_STATUS_MASK 0xfbff + +static void smbus_delay(void) +{ + inb(0x80); +} + +static int smbus_wait(unsigned smbus_io_base) +{ + unsigned long loops = SMBUS_TIMEOUT; + unsigned char val; + + do { + smbus_delay(); + val = inb(smbus_io_base + SMB_STS); + if ((val & SMB_STS_SDAST) != 0) + break; + if (val & (SMB_STS_BER | SMB_STS_NEGACK)) { + printk(BIOS_DEBUG, "SMBUS WAIT ERROR %x\n", val); + return SMBUS_ERROR; + } + } while (--loops); + + outb(0, smbus_io_base + SMB_STS); + return loops ? 0 : SMBUS_WAIT_UNTIL_READY_TIMEOUT; +} + +static int smbus_write(unsigned smbus_io_base, unsigned char byte) +{ + + outb(byte, smbus_io_base + SMB_SDA); + return smbus_wait(smbus_io_base); +} + +/* generate a smbus start condition */ +static int smbus_start_condition(unsigned smbus_io_base) +{ + unsigned char val; + + /* issue a START condition */ + val = inb(smbus_io_base + SMB_CTRL1); + outb(val | SMB_CTRL1_START, smbus_io_base + SMB_CTRL1); + + /* check for bus conflict */ + val = inb(smbus_io_base + SMB_STS); + if ((val & SMB_STS_BER) != 0) + return SMBUS_ERROR; + + return smbus_wait(smbus_io_base); +} + +static int smbus_check_stop_condition(unsigned smbus_io_base) +{ + unsigned char val; + unsigned long loops; + loops = SMBUS_TIMEOUT; + /* check for SDA status */ + do { + smbus_delay(); + val = inb(smbus_io_base + SMB_CTRL1); + if ((val & SMB_CTRL1_STOP) == 0) { + break; + } + } while (--loops); + return loops ? 0 : SMBUS_WAIT_UNTIL_READY_TIMEOUT; + + /* Make sure everything is cleared and ready to go */ + + val = inb(smbus_io_base + SMB_CTRL1); + outb(val & ~(SMB_CTRL1_STASTRE | SMB_CTRL1_NMINTE), + smbus_io_base + SMB_CTRL1); + + outb(SMB_STS_BER | SMB_STS_NEGACK | SMB_STS_STASTR, + smbus_io_base + SMB_STS); + + val = inb(smbus_io_base + SMB_CTRL_STS); + outb(val | SMB_CSTS_BB, smbus_io_base + SMB_CTRL_STS); +} + +static int smbus_stop_condition(unsigned smbus_io_base) +{ + unsigned char val; + val = inb(smbus_io_base + SMB_CTRL1); + outb(SMB_CTRL1_STOP, smbus_io_base + SMB_CTRL1); + + return 0; +} + +static int smbus_ack(unsigned smbus_io_base, int state) +{ + unsigned char val = inb(smbus_io_base + SMB_CTRL1); + + if (state) + outb(val | SMB_CTRL1_ACK, smbus_io_base + SMB_CTRL1); + else + outb(val & ~SMB_CTRL1_ACK, smbus_io_base + SMB_CTRL1); + + return 0; +} + +static int smbus_send_slave_address(unsigned smbus_io_base, + unsigned char device) +{ + unsigned char val; + + /* send the slave address */ + outb(device, smbus_io_base + SMB_SDA); + + /* check for bus conflict and NACK */ + val = inb(smbus_io_base + SMB_STS); + if (((val & SMB_STS_BER) != 0) || ((val & SMB_STS_NEGACK) != 0)) { + printk(BIOS_DEBUG, "SEND SLAVE ERROR (%x)\n", val); + return SMBUS_ERROR; + } + return smbus_wait(smbus_io_base); +} + +static int smbus_send_command(unsigned smbus_io_base, unsigned char command) +{ + unsigned char val; + + /* send the command */ + outb(command, smbus_io_base + SMB_SDA); + + /* check for bus conflict and NACK */ + val = inb(smbus_io_base + SMB_STS); + if (((val & SMB_STS_BER) != 0) || ((val & SMB_STS_NEGACK) != 0)) + return SMBUS_ERROR; + + return smbus_wait(smbus_io_base); +} + +static void _doread(unsigned smbus_io_base, unsigned char device, + unsigned char address, unsigned char *data, int count) +{ + int ret; + int index = 0; + unsigned char val; + + if ((ret = smbus_check_stop_condition(smbus_io_base))) + goto err; + + index++; + + if ((ret = smbus_start_condition(smbus_io_base))) + goto err; + + index++; /* 2 */ + if ((ret = smbus_send_slave_address(smbus_io_base, device))) + goto err; + + index++; + if ((ret = smbus_send_command(smbus_io_base, address))) + goto err; + + index++; + if ((ret = smbus_start_condition(smbus_io_base))) + goto err; + + /* Clear the ack for multiple byte reads */ + smbus_ack(smbus_io_base, (count == 1) ? 1 : 0); + + index++; + if ((ret = smbus_send_slave_address(smbus_io_base, device | 0x01))) + goto err; + + while (count) { + /* Set the ACK if this is the next to last byte */ + smbus_ack(smbus_io_base, (count == 2) ? 1 : 0); + + /* Set the stop bit if this is the last byte to read */ + + if (count == 1) + smbus_stop_condition(smbus_io_base); + + val = inb(smbus_io_base + SMB_SDA); + *data++ = val; + + if (count > 1) { + ret = smbus_wait(smbus_io_base); + if (ret) + return; + } + + count--; + } + + return; + + err: + printk(BIOS_DEBUG, "SMBUS READ ERROR (%d): %d\n", index, ret); +} + +static inline unsigned char do_smbus_read_byte(unsigned smbus_io_base, + unsigned char device, unsigned char address) +{ + unsigned char val = 0; + _doread(smbus_io_base, device, address, &val, sizeof(val)); + return val; +} + +static inline unsigned short do_smbus_read_word(unsigned smbus_io_base, + unsigned char device, unsigned char address) +{ + unsigned short val = 0; + _doread(smbus_io_base, device, address, (unsigned char *)&val, + sizeof(val)); + return val; +} + +static int _dowrite(unsigned smbus_io_base, unsigned char device, + unsigned char address, unsigned char *data, int count) +{ + + int ret; + + if ((ret = smbus_check_stop_condition(smbus_io_base))) + goto err; + + if ((ret = smbus_start_condition(smbus_io_base))) + goto err; + + if ((ret = smbus_send_slave_address(smbus_io_base, device))) + goto err; + + if ((ret = smbus_send_command(smbus_io_base, address))) + goto err; + + while (count) { + if ((ret = smbus_write(smbus_io_base, *data++))) + goto err; + count--; + } + + smbus_stop_condition(smbus_io_base); + return 0; + + err: + printk(BIOS_DEBUG, "SMBUS WRITE ERROR: %d\n", ret); + return -1; +} + +static inline int do_smbus_write_byte(unsigned smbus_io_base, + unsigned char device, unsigned char address, unsigned char data) +{ + return _dowrite(smbus_io_base, device, address, + (unsigned char *)&data, 1); +} + +static inline int do_smbus_write_word(unsigned smbus_io_base, + unsigned char device, unsigned char address, unsigned short data) +{ + return _dowrite(smbus_io_base, device, address, (unsigned char *)&data, + 2); +} diff --git a/src/southbridge/amd/rs690/Makefile.inc b/src/southbridge/amd/rs690/Makefile.inc index c728be56a4..5849340ce0 100644 --- a/src/southbridge/amd/rs690/Makefile.inc +++ b/src/southbridge/amd/rs690/Makefile.inc @@ -1,5 +1,5 @@ driver-y += rs690.c -driver-y += rs690_cmn.c -driver-y += rs690_pcie.c -driver-y += rs690_ht.c -driver-y += rs690_gfx.c +driver-y += cmn.c +driver-y += pcie.c +driver-y += ht.c +driver-y += gfx.c diff --git a/src/southbridge/amd/rs690/cmn.c b/src/southbridge/amd/rs690/cmn.c new file mode 100644 index 0000000000..5e06d4f9d8 --- /dev/null +++ b/src/southbridge/amd/rs690/cmn.c @@ -0,0 +1,324 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "rs690.h" + +static u32 nb_read_index(device_t dev, u32 index_reg, u32 index) +{ + pci_write_config32(dev, index_reg, index); + return pci_read_config32(dev, index_reg + 0x4); +} + +static void nb_write_index(device_t dev, u32 index_reg, u32 index, u32 data) +{ + + pci_write_config32(dev, index_reg, index); + pci_write_config32(dev, index_reg + 0x4, data); + +} + +/* extension registers */ +u32 pci_ext_read_config32(device_t nb_dev, device_t dev, u32 reg) +{ + /*get BAR3 base address for nbcfg0x1c */ + u32 addr = pci_read_config32(nb_dev, 0x1c) & ~0xF; + printk(BIOS_DEBUG, "addr=%x,bus=%x,devfn=%x\n", addr, dev->bus->secondary, + dev->path.pci.devfn); + addr |= dev->bus->secondary << 20 | /* bus num */ + dev->path.pci.devfn << 12 | reg; + return *((u32 *) addr); +} + +void pci_ext_write_config32(device_t nb_dev, device_t dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + + /*get BAR3 base address for nbcfg0x1c */ + u32 addr = pci_read_config32(nb_dev, 0x1c) & ~0xF; + /*printk(BIOS_DEBUG, "write: addr=%x,bus=%x,devfn=%x\n", addr, dev->bus->secondary, + dev->path.pci.devfn);*/ + addr |= dev->bus->secondary << 20 | /* bus num */ + dev->path.pci.devfn << 12 | reg_pos; + + reg = reg_old = *((u32 *) addr); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + *((u32 *) addr) = reg; + } +} + +u32 nbmisc_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBMISC_INDEX, (index)); +} + +void nbmisc_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBMISC_INDEX, ((index) | 0x80), (data)); +} + +u32 nbpcie_p_read_index(device_t dev, u32 index) +{ + return nb_read_index((dev), NBPCIE_INDEX, (index)); +} + +void nbpcie_p_write_index(device_t dev, u32 index, u32 data) +{ + nb_write_index((dev), NBPCIE_INDEX, (index), (data)); +} + +u32 nbpcie_ind_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBPCIE_INDEX, (index)); +} + +void nbpcie_ind_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBPCIE_INDEX, (index), (data)); +} + +u32 htiu_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBHTIU_INDEX, (index)); +} + +void htiu_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBHTIU_INDEX, ((index) | 0x100), (data)); +} + +u32 nbmc_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBMC_INDEX, (index)); +} + +void nbmc_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBMC_INDEX, ((index) | 1 << 9), (data)); +} + +void set_nbcfg_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + reg = reg_old = pci_read_config32(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + pci_write_config32(nb_dev, reg_pos, reg); + } +} + +void set_nbcfg_enable_bits_8(device_t nb_dev, u32 reg_pos, u8 mask, u8 val) +{ + u8 reg_old, reg; + reg = reg_old = pci_read_config8(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + pci_write_config8(nb_dev, reg_pos, reg); + } +} + +void set_nbmc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + reg = reg_old = nbmc_read_index(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + nbmc_write_index(nb_dev, reg_pos, reg); + } +} + +void set_htiu_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + reg = reg_old = htiu_read_index(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + htiu_write_index(nb_dev, reg_pos, reg); + } +} + +void set_nbmisc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + reg = reg_old = nbmisc_read_index(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + nbmisc_write_index(nb_dev, reg_pos, reg); + } +} + +void set_pcie_enable_bits(device_t dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + reg = reg_old = nb_read_index(dev, NBPCIE_INDEX, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + nb_write_index(dev, NBPCIE_INDEX, reg_pos, reg); + } +} + +/*********************************************************** +* To access bar3 we need to program PCI MMIO 7 in K8. +* in_out: +* 1: enable/enter k8 temp mmio base +* 0: disable/restore +***********************************************************/ +void ProgK8TempMmioBase(u8 in_out, u32 pcie_base_add, u32 mmio_base_add) +{ + /* K8 Function1 is address map */ + device_t k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1)); + device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); + + if (in_out) { + u32 dword, sblk; + + /* Get SBLink value (HyperTransport I/O Hub Link ID). */ + dword = pci_read_config32(k8_f0, 0x64); + sblk = (dword >> 8) & 0x3; + + /* Fill MMIO limit/base pair. */ + pci_write_config32(k8_f1, 0xbc, + (((pcie_base_add + 0x10000000 - + 1) >> 8) & 0xffffff00) | 0x80 | (sblk << 4)); + pci_write_config32(k8_f1, 0xb8, (pcie_base_add >> 8) | 0x3); + pci_write_config32(k8_f1, 0xb4, + (((mmio_base_add + 0x10000000 - + 1) >> 8) & 0xffffff00) | (sblk << 4)); + pci_write_config32(k8_f1, 0xb0, (mmio_base_add >> 8) | 0x3); + } else { + pci_write_config32(k8_f1, 0xb8, 0); + pci_write_config32(k8_f1, 0xbc, 0); + pci_write_config32(k8_f1, 0xb0, 0); + pci_write_config32(k8_f1, 0xb4, 0); + } +} + +void PcieReleasePortTraining(device_t nb_dev, device_t dev, u32 port) +{ + switch (port) { + case 2: /* GFX, bit4-5 */ + case 3: + set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG, + 1 << (port + 2), 0 << (port + 2)); + break; + case 4: /* GPP, bit20-24 */ + case 5: + case 6: + case 7: + set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG, + 1 << (port + 17), 0 << (port + 17)); + break; + } +} + +/******************************************************************************************************** +* Output: +* 0: no device is present. +* 1: device is present and is trained. +********************************************************************************************************/ +u8 PcieTrainPort(device_t nb_dev, device_t dev, u32 port) +{ + u16 count = 5000; + u32 lc_state, reg; + int8_t current, res = 0; + + while (count--) { + mdelay(40); + udelay(200); + lc_state = nbpcie_p_read_index(dev, 0xa5); /* lc_state */ + printk(BIOS_DEBUG, "PcieLinkTraining port=%x:lc current state=%x\n", + port, lc_state); + current = lc_state & 0x3f; /* get LC_CURRENT_STATE, bit0-5 */ + + switch (current) { + case 0x00: /* 0x00-0x04 means no device is present */ + case 0x01: + case 0x02: + case 0x03: + case 0x04: + res = 0; + count = 0; + break; + case 0x07: /* device is in compliance state (training sequence is doen). Move to train the next device */ + res = 1; /* TODO: CIM sets it to 0 */ + count = 0; + break; + case 0x10: + reg = + pci_ext_read_config32(nb_dev, dev, + PCIE_VC0_RESOURCE_STATUS); + printk(BIOS_DEBUG, "PcieTrainPort reg=0x%x\n", reg); + /* check bit1 */ + if (reg & VC_NEGOTIATION_PENDING) { /* bit1=1 means the link needs to be re-trained. */ + /* set bit8=1, bit0-2=bit4-6 */ + u32 tmp; + reg = + nbpcie_p_read_index(dev, + PCIE_LC_LINK_WIDTH); + tmp = (reg >> 4) && 0x3; /* get bit4-6 */ + reg &= 0xfff8; /* clear bit0-2 */ + reg += tmp; /* merge */ + reg |= 1 << 8; + count++; /* CIM said "keep in loop"? */ + } else { + res = 1; + count = 0; + } + break; + default: /* reset pcie */ + res = 0; + count = 0; /* break loop */ + break; + } + } + return res; +} + +/* +* Compliant with CIM_33's ATINB_SetToms. +* Set Top Of Memory below and above 4G. +*/ +void rs690_set_tom(device_t nb_dev) +{ + extern uint64_t uma_memory_base; + + /* set TOM */ + pci_write_config32(nb_dev, 0x90, uma_memory_base); + nbmc_write_index(nb_dev, 0x1e, uma_memory_base); +} + diff --git a/src/southbridge/amd/rs690/early_setup.c b/src/southbridge/amd/rs690/early_setup.c new file mode 100644 index 0000000000..f29d136791 --- /dev/null +++ b/src/southbridge/amd/rs690/early_setup.c @@ -0,0 +1,484 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2008 Carl-Daniel Hailfinger + * + * 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 + */ + + +#define NBHTIU_INDEX 0xA8 +#define NBMISC_INDEX 0x60 +#define NBMC_INDEX 0xE8 + +static u32 nb_read_index(device_t dev, u32 index_reg, u32 index) +{ + pci_write_config32(dev, index_reg, index); + return pci_read_config32(dev, index_reg + 0x4); +} + +static void nb_write_index(device_t dev, u32 index_reg, u32 index, u32 data) +{ + pci_write_config32(dev, index_reg, index /* | 0x80 */ ); + pci_write_config32(dev, index_reg + 0x4, data); +} + +static u32 nbmisc_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBMISC_INDEX, (index)); +} + +static void nbmisc_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBMISC_INDEX, ((index) | 0x80), (data)); +} + +static u32 htiu_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBHTIU_INDEX, (index)); +} + +static void htiu_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBHTIU_INDEX, ((index) | 0x100), (data)); +} + +static u32 nbmc_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBMC_INDEX, (index)); +} + +static void nbmc_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBMC_INDEX, ((index) | 1 << 9), (data)); +} + +static void set_htiu_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, + u32 val) +{ + u32 reg_old, reg; + reg = reg_old = htiu_read_index(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + htiu_write_index(nb_dev, reg_pos, reg); + } +} + +static void set_nbmisc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, + u32 val) +{ + u32 reg_old, reg; + reg = reg_old = nbmisc_read_index(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + nbmisc_write_index(nb_dev, reg_pos, reg); + } +} + +static void set_nbcfg_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, + u32 val) +{ + u32 reg_old, reg; + reg = reg_old = pci_read_config32(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + pci_write_config32(nb_dev, reg_pos, reg); + } +} + +static void set_nbcfg_enable_bits_8(device_t nb_dev, u32 reg_pos, u8 mask, + u8 val) +{ + u8 reg_old, reg; + reg = reg_old = pci_read_config8(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + pci_write_config8(nb_dev, reg_pos, reg); + } +} + +static void set_nbmc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, + u32 val) +{ + u32 reg_old, reg; + reg = reg_old = nbmc_read_index(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + nbmc_write_index(nb_dev, reg_pos, reg); + } +} + +/* +* Compliant with CIM_33's ATINB_PrepareInit +*/ +static void get_cpu_rev(void) +{ + u32 eax, ebx, ecx, edx; + __asm__ volatile ("cpuid":"=a" (eax), "=b"(ebx), "=c"(ecx), "=d"(edx) + :"0"(1)); + printk(BIOS_INFO, "get_cpu_rev EAX=0x%x.\n", eax); + if (eax <= 0xfff) + printk(BIOS_INFO, "CPU Rev is K8_Cx.\n"); + else if (eax <= 0x10fff) + printk(BIOS_INFO, "CPU Rev is K8_Dx.\n"); + else if (eax <= 0x20fff) + printk(BIOS_INFO, "CPU Rev is K8_Ex.\n"); + else if (eax <= 0x40fff) + printk(BIOS_INFO, "CPU Rev is K8_Fx.\n"); + else if (eax == 0x60fb1 || eax == 0x60f81) /*These two IDS are exception, they are G1. */ + printk(BIOS_INFO, "CPU Rev is K8_G1.\n"); + else if (eax <= 0X60FF0) + printk(BIOS_INFO, "CPU Rev is K8_G0.\n"); + else if (eax <= 0x100000) + printk(BIOS_INFO, "CPU Rev is K8_G1.\n"); + else + printk(BIOS_INFO, "CPU Rev is K8_10.\n"); +} + +static u8 get_nb_rev(device_t nb_dev) +{ + u32 reg; + reg = pci_read_config32(nb_dev, 0x00); + if (0x7911 == (reg >> 16)) + return 7; + reg = pci_read_config8(nb_dev, 0x89); /* copy from CIM, can't find in doc */ + if (reg & 0x2) /* check bit1 */ + return 7; + if (reg & 0x1) /* check bit0 */ + return 6; + else + return 5; +} + +/***************************************** +* Compliant with CIM_33's ATINB_HTInit +* Init HT link speed/width for rs690 -- k8 link +*****************************************/ +static void rs690_htinit(void) +{ + /* + * About HT, it has been done in enumerate_ht_chain(). + */ + device_t k8_f0, rs690_f0; + u32 reg; + u8 reg8; + u8 k8_ht_freq; + + k8_f0 = PCI_DEV(0, 0x18, 0); + /************************ + * get k8's ht freq, in k8's function 0, offset 0x88 + * bit11-8, specifics the maximum operation frequency of the link's transmitter clock. + * The link frequency field (Frq) is cleared by cold reset. SW can write a nonzero + * value to this reg, and that value takes effect on the next warm reset or + * LDTSTOP_L disconnect sequence. + * 0000b = 200Mhz + * 0010b = 400Mhz + * 0100b = 600Mhz + * 0101b = 800Mhz + * 0110b = 1Ghz + * 1111b = 1Ghz + ************************/ + reg = pci_read_config32(k8_f0, 0x88); + k8_ht_freq = (reg & 0xf00) >> 8; + printk(BIOS_SPEW, "rs690_htinit k8_ht_freq=%x.\n", k8_ht_freq); + rs690_f0 = PCI_DEV(0, 0, 0); + reg8 = pci_read_config8(rs690_f0, 0x9c); + printk(BIOS_SPEW, "rs690_htinit NB_CFG_Q_F1000_800=%x\n", reg8); + /* For 1000 MHz HT, NB_CFG_Q_F1000_800 bit 0 MUST be set. + * For any other HT frequency, NB_CFG_Q_F1000_800 bit 0 MUST NOT be set. + */ + if (((k8_ht_freq == 0x6) || (k8_ht_freq == 0xf)) && (!(reg8 & 0x1))) { + printk(BIOS_INFO, "rs690_htinit setting bit 0 in NB_CFG_Q_F1000_800 to use 1 GHz HT\n"); + reg8 |= 0x1; + pci_write_config8(rs690_f0, 0x9c, reg8); + } else if ((k8_ht_freq != 0x6) && (k8_ht_freq != 0xf) && (reg8 & 0x1)) { + printk(BIOS_INFO, "rs690_htinit clearing bit 0 in NB_CFG_Q_F1000_800 to not use 1 GHz HT\n"); + reg8 &= ~0x1; + pci_write_config8(rs690_f0, 0x9c, reg8); + } +} + +/******************************************************* +* Optimize k8 with UMA. +* See BKDG_NPT_0F guide for details. +* The processor node is addressed by its Node ID on the HT link and can be +* accessed with a device number in the PCI configuration space on Bus0. +* The Node ID 0 is mapped to Device 24 (0x18), the Node ID 1 is mapped +* to Device 25, and so on. +* The processor implements configuration registers in PCI configuration +* space using the following four headers +* Function0: HT technology configuration +* Function1: Address map configuration +* Function2: DRAM and HT technology Trace mode configuration +* Function3: Miscellaneous configuration +*******************************************************/ +static void k8_optimization(void) +{ + device_t k8_f0, k8_f2, k8_f3; + msr_t msr; + + printk(BIOS_INFO, "k8_optimization()\n"); + k8_f0 = PCI_DEV(0, 0x18, 0); + k8_f2 = PCI_DEV(0, 0x18, 2); + k8_f3 = PCI_DEV(0, 0x18, 3); + + pci_write_config32(k8_f0, 0x90, 0x01700178); /* CIM NPT_Optimization */ + set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 28, 0 << 28); + set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 26 | 1 << 27, + 1 << 26 | 1 << 27); + set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 11, 1 << 11); + set_nbcfg_enable_bits(k8_f0, 0x84, 1 << 11 | 1 << 13 | 1 << 15, 1 << 11 | 1 << 13 | 1 << 15); /* TODO */ + + pci_write_config32(k8_f3, 0x70, 0x51320111); /* CIM NPT_Optimization */ + pci_write_config32(k8_f3, 0x74, 0x50304021); + pci_write_config32(k8_f3, 0x78, 0x08002A00); + if (pci_read_config32(k8_f3, 0xE8) & 0x3<<12) + pci_write_config32(k8_f3, 0x7C, 0x0000211B); /* dual core */ + else + pci_write_config32(k8_f3, 0x7C, 0x0000211C); /* single core */ + set_nbcfg_enable_bits_8(k8_f3, 0xDC, 0xFF, 0x25); + + set_nbcfg_enable_bits(k8_f2, 0xA0, 1 << 5, 1 << 5); + set_nbcfg_enable_bits(k8_f2, 0x94, 0xF << 24, 7 << 24); + set_nbcfg_enable_bits(k8_f2, 0x90, 1 << 10, 1 << 10); + set_nbcfg_enable_bits(k8_f2, 0xA0, 3 << 2, 3 << 2); + set_nbcfg_enable_bits(k8_f2, 0xA0, 1 << 5, 1 << 5); + + msr = rdmsr(0xC001001F); + msr.lo &= ~(1 << 9); + msr.hi &= ~(1 << 4); + wrmsr(0xC001001F, msr); +} + +/***************************************** +* Compliant with CIM_33's ATINB_PCICFG_POR_TABLE +*****************************************/ +static void rs690_por_pcicfg_init(device_t nb_dev) +{ + /* enable PCI Memory Access */ + set_nbcfg_enable_bits_8(nb_dev, 0x04, (u8)(~0xFD), 0x02); + /* Set RCRB Enable */ + set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xFF), 0x1); + /* allow decode of 640k-1MB */ + set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xEF), 0x10); + /* Enable PM2_CNTL(BAR2) IO mapped cfg write access to be broadcast to both NB and SB */ + set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xFF), 0x4); + /* Power Management Register Enable */ + set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xFF), 0x80); + + /* Reg4Ch[1]=1 (APIC_ENABLE) force cpu request with address 0xFECx_xxxx to south-bridge + * Reg4Ch[6]=1 (BMMsgEn) enable BM_Set message generation + * BMMsgEn */ + set_nbcfg_enable_bits_8(nb_dev, 0x4C, (u8)(~0x00), 0x42 | 1); + + /* Reg4Ch[16]=1 (WakeC2En) enable Wake_from_C2 message generation. + * Reg4Ch[18]=1 (P4IntEnable) Enable north-bridge to accept MSI with address 0xFEEx_xxxx from south-bridge */ + set_nbcfg_enable_bits_8(nb_dev, 0x4E, (u8)(~0xFF), 0x05); + /* Reg94h[4:0] = 0x0 P drive strength offset 0 + * Reg94h[6:5] = 0x2 P drive strength additive adjust */ + set_nbcfg_enable_bits_8(nb_dev, 0x94, (u8)(~0x80), 0x40); + + /* Reg94h[20:16] = 0x0 N drive strength offset 0 + * Reg94h[22:21] = 0x2 N drive strength additive adjust */ + set_nbcfg_enable_bits_8(nb_dev, 0x96, (u8)(~0x80), 0x40); + + /* Reg80h[4:0] = 0x0 Termination offset + * Reg80h[6:5] = 0x2 Termination additive adjust */ + set_nbcfg_enable_bits_8(nb_dev, 0x80, (u8)(~0x80), 0x40); + + /* Reg80h[14] = 0x1 Enable receiver termination control */ + set_nbcfg_enable_bits_8(nb_dev, 0x81, (u8)(~0xFF), 0x40); + + /* Reg94h[15] = 0x1 Enables HT transmitter advanced features to be turned on + * Reg94h[14] = 0x1 Enable drive strength control */ + set_nbcfg_enable_bits_8(nb_dev, 0x95, (u8)(~0x3F), 0xC4); + + /* Reg94h[31:29] = 0x7 Enables HT transmitter de-emphasis */ + set_nbcfg_enable_bits_8(nb_dev, 0x97, (u8)(~0x1F), 0xE0); + + /*Reg8Ch[10:9] = 0x3 Enables Gfx Debug BAR, + * force this BAR as mem type in rs690_gfx.c */ + set_nbcfg_enable_bits_8(nb_dev, 0x8D, (u8)(~0xFF), 0x03); + +} + +/***************************************** +* Compliant with CIM_33's ATINB_MCIndex_POR_TABLE +*****************************************/ +static void rs690_por_mc_index_init(device_t nb_dev) +{ + set_nbmc_enable_bits(nb_dev, 0x7A, ~0xFFFFFF80, 0x0000005F); + set_nbmc_enable_bits(nb_dev, 0xD8, ~0x00000000, 0x00600060); + set_nbmc_enable_bits(nb_dev, 0xD9, ~0x00000000, 0x00600060); + set_nbmc_enable_bits(nb_dev, 0xE0, ~0x00000000, 0x00000000); + set_nbmc_enable_bits(nb_dev, 0xE1, ~0x00000000, 0x00000000); + set_nbmc_enable_bits(nb_dev, 0xE8, ~0x00000000, 0x003E003E); + set_nbmc_enable_bits(nb_dev, 0xE9, ~0x00000000, 0x003E003E); +} + +/***************************************** +* Compliant with CIM_33's ATINB_MISCIND_POR_TABLE +* Compliant with CIM_33's MISC_INIT_TBL +*****************************************/ +static void rs690_por_misc_index_init(device_t nb_dev) +{ + /* NB_MISC_IND_WR_EN + IOC_PCIE_CNTL + * Block non-snoop DMA request if PMArbDis is set. + * Set BMSetDis */ + set_nbmisc_enable_bits(nb_dev, 0x0B, ~0xFFFF0000, 0x00000180); + set_nbmisc_enable_bits(nb_dev, 0x01, ~0xFFFFFFFF, 0x00000040); + + /* NBCFG (NBMISCIND 0x0): NB_CNTL - + * HIDE_NB_AGP_CAP ([0], default=1)HIDE + * HIDE_P2P_AGP_CAP ([1], default=1)HIDE + * HIDE_NB_GART_BAR ([2], default=1)HIDE + * AGPMODE30 ([4], default=0)DISABLE + * AGP30ENCHANCED ([5], default=0)DISABLE + * HIDE_AGP_CAP ([8], default=1)ENABLE */ + set_nbmisc_enable_bits(nb_dev, 0x00, ~0xFFFF0000, 0x00000506); /* set bit 10 for MSI */ + + /* NBMISCIND:0x6A[16]= 1 SB link can get a full swing + * set_nbmisc_enable_bits(nb_dev, 0x6A, 0ffffffffh, 000010000); + * NBMISCIND:0x6A[17]=1 Set CMGOOD_OVERRIDE. */ + set_nbmisc_enable_bits(nb_dev, 0x6A, ~0xffffffff, 0x00020000); + + /* NBMISIND:0x40 Bit[8]=1 and Bit[10]=1 following bits are required to set in order to allow LVDS or PWM features to work. */ + set_nbmisc_enable_bits(nb_dev, 0x40, ~0xffffffff, 0x00000500); + + /* NBMISIND:0xC Bit[13]=1 Enable GSM mode for C1e or C3 with pop-up. */ + set_nbmisc_enable_bits(nb_dev, 0x0C, ~0xffffffff, 0x00002000); + + /* Set NBMISIND:0x1F[3] to map NB F2 interrupt pin to INTB# */ + set_nbmisc_enable_bits(nb_dev, 0x1F, ~0xffffffff, 0x00000008); + + /* Compliant with CIM_33's MISC_INIT_TBL, except Hide NB_BAR3_PCIE + * Enable access to DEV8 + * Enable setPower message for all ports + */ + set_nbmisc_enable_bits(nb_dev, 0x00, 1 << 6, 1 << 6); + set_nbmisc_enable_bits(nb_dev, 0x0b, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x51, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x53, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x55, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x57, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x59, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x5B, 1 << 20, 1 << 20); + + set_nbmisc_enable_bits(nb_dev, 0x00, 1 << 7, 1 << 7); + set_nbmisc_enable_bits(nb_dev, 0x07, 0x000000f0, 0x30); + /* Disable bus-master trigger event from SB and Enable set_slot_power message to SB */ + set_nbmisc_enable_bits(nb_dev, 0x0B, 0xffffffff, 0x500180); +} + +/***************************************** +* Compliant with CIM_33's ATINB_HTIUNBIND_POR_TABLE +*****************************************/ +static void rs690_por_htiu_index_init(device_t nb_dev) +{ + /* 0xBC: + * Enables GSM mode for C1e or C3 with pop-up + * Prevents AllowLdtStop from being asserted during HT link recovery + * Allows FID cycles to be serviced faster. Needed for RS690 A12. No harm in RS690 A11 */ + set_htiu_enable_bits(nb_dev, 0x05, ~0xffffffff, 0x0BC); + /* 0x4203A202: + * Enables writes to pass in-progress reads + * Enables streaming of CPU writes + * Enables extended write buffer for CPU writes + * Enables additional response buffers + * Enables special reads to pass writes + * Enables decoding of C1e/C3 and FID cycles + * Enables HTIU-display handshake bypass. + * Enables tagging fix */ + set_htiu_enable_bits(nb_dev, 0x06, ~0xFFFFFFFE, 0x4203A202); + + /* Enables byte-write optimization for IOC requests + * Disables delaying STPCLK de-assert during FID sequence. Needed when enhanced UMA arbitration is used. + * Disables upstream system-management delay */ + set_htiu_enable_bits(nb_dev, 0x07, ~0xFFFFFFF9, 0x001); + + /* HTIUNBIND 0x16 [1] = 0x1 Enable crc decoding fix */ + set_htiu_enable_bits(nb_dev, 0x16, ~0xFFFFFFFF, 0x2); +} + +/***************************************** +* Compliant with CIM_33's ATINB_POR_INIT_JMPDI +* Configure RS690 registers to power-on default RPR. +* POR: Power On Reset +* RPR: Register Programming Requirements +*****************************************/ +static void rs690_por_init(device_t nb_dev) +{ + printk(BIOS_INFO, "rs690_por_init\n"); + /* ATINB_PCICFG_POR_TABLE, initialize the values for rs690 PCI Config registers */ + rs690_por_pcicfg_init(nb_dev); + + /* ATINB_MCIND_POR_TABLE */ + rs690_por_mc_index_init(nb_dev); + + /* ATINB_MISCIND_POR_TABLE */ + rs690_por_misc_index_init(nb_dev); + + /* ATINB_HTIUNBIND_POR_TABLE */ + rs690_por_htiu_index_init(nb_dev); + + /* ATINB_CLKCFG_PORT_TABLE */ + /* rs690 A11 SB Link full swing? */ +} + +/* enable CFG access to Dev8, which is the SB P2P Bridge */ +static void enable_rs690_dev8(void) +{ + set_nbmisc_enable_bits(PCI_DEV(0, 0, 0), 0x00, 1 << 6, 1 << 6); +} + + + +/* +* Compliant with CIM_33's AtiNBInitEarlyPost (AtiInitNBBeforePCIInit). +*/ +static void rs690_before_pci_init(void) +{ +} + +/* +* The calling sequence is same as CIM. +*/ +static void rs690_early_setup(void) +{ + device_t nb_dev = PCI_DEV(0, 0, 0); + printk(BIOS_INFO, "rs690_early_setup()\n"); + + /*ATINB_PrepareInit */ + get_cpu_rev(); + switch (get_nb_rev(nb_dev)) { /* PCIEMiscInit */ + case 5: + printk(BIOS_INFO, "NB Revision is A11.\n"); + break; + case 6: + printk(BIOS_INFO, "NB Revision is A12.\n"); + break; + case 7: + printk(BIOS_INFO, "NB Revision is A21.\n"); + break; + } + + k8_optimization(); + rs690_por_init(nb_dev); +} diff --git a/src/southbridge/amd/rs690/gfx.c b/src/southbridge/amd/rs690/gfx.c new file mode 100644 index 0000000000..c55f2bc3d3 --- /dev/null +++ b/src/southbridge/amd/rs690/gfx.c @@ -0,0 +1,625 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 + */ + +/* + * for rs690 internal graphics device + * device id of internal grphics: + * RS690M/T: 0x791f + * RS690: 0x791e + */ +#include +#include +#include +#include +#include +#include +#include "rs690.h" + +#define CLK_CNTL_INDEX 0x8 +#define CLK_CNTL_DATA 0xC + +#ifdef UNUSED_CODE +static u32 clkind_read(device_t dev, u32 index) +{ + u32 gfx_bar2 = pci_read_config32(dev, 0x18) & ~0xF; + + *(u32*)(gfx_bar2+CLK_CNTL_INDEX) = index & 0x7F; + return *(u32*)(gfx_bar2+CLK_CNTL_DATA); +} +#endif + +static void clkind_write(device_t dev, u32 index, u32 data) +{ + u32 gfx_bar2 = pci_read_config32(dev, 0x18) & ~0xF; + /* printk(BIOS_INFO, "gfx bar 2 %02x\n", gfx_bar2); */ + + *(u32*)(gfx_bar2+CLK_CNTL_INDEX) = index | 1<<7; + *(u32*)(gfx_bar2+CLK_CNTL_DATA) = data; +} + +/* +* pci_dev_read_resources thinks it is a IO type. +* We have to force it to mem type. +*/ +static void rs690_gfx_read_resources(device_t dev) +{ + printk(BIOS_INFO, "rs690_gfx_read_resources.\n"); + + /* The initial value of 0x24 is 0xFFFFFFFF, which is confusing. + Even if we write 0xFFFFFFFF into it, it will be 0xFFF00000, + which tells us it is a memory address base. + */ + pci_write_config32(dev, 0x24, 0x00000000); + + /* Get the normal pci resources of this device */ + pci_dev_read_resources(dev); + compact_resources(dev); +} + +static void internal_gfx_pci_dev_init(struct device *dev) +{ + u16 deviceid, vendorid; + deviceid = pci_read_config16(dev, PCI_DEVICE_ID); + vendorid = pci_read_config16(dev, PCI_VENDOR_ID); + printk(BIOS_INFO, "internal_gfx_pci_dev_init device=%x, vendor=%x.\n", + deviceid, vendorid); + + pci_dev_init(dev); + + /* clk ind */ + clkind_write(dev, 0x08, 0x01); + clkind_write(dev, 0x0C, 0x22); + clkind_write(dev, 0x0F, 0x0); + clkind_write(dev, 0x11, 0x0); + clkind_write(dev, 0x12, 0x0); + clkind_write(dev, 0x14, 0x0); + clkind_write(dev, 0x15, 0x0); + clkind_write(dev, 0x16, 0x0); + clkind_write(dev, 0x17, 0x0); + clkind_write(dev, 0x18, 0x0); + clkind_write(dev, 0x19, 0x0); + clkind_write(dev, 0x1A, 0x0); + clkind_write(dev, 0x1B, 0x0); + clkind_write(dev, 0x1C, 0x0); + clkind_write(dev, 0x1D, 0x0); + clkind_write(dev, 0x1E, 0x0); + clkind_write(dev, 0x26, 0x0); + clkind_write(dev, 0x27, 0x0); + clkind_write(dev, 0x28, 0x0); + clkind_write(dev, 0x5C, 0x0); +} + + +/* +* Set registers in RS690 and CPU to enable the internal GFX. +* Please refer to CIM source code and BKDG. +*/ +static void rs690_internal_gfx_enable(device_t dev) +{ + u32 l_dword; + int i; + device_t k8_f0 = 0, k8_f2 = 0; + device_t nb_dev = dev_find_slot(0, 0); + + printk(BIOS_INFO, "rs690_internal_gfx_enable dev=0x%p, nb_dev=0x%p.\n", dev, + nb_dev); + + /* set APERTURE_SIZE, 128M. */ + l_dword = pci_read_config32(nb_dev, 0x8c); + printk(BIOS_INFO, "nb_dev, 0x8c=0x%x\n", l_dword); + l_dword &= 0xffffff8f; + pci_write_config32(nb_dev, 0x8c, l_dword); + + /* set TOM */ + rs690_set_tom(nb_dev); + + /* LPC DMA Deadlock workaround? */ + k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); + l_dword = pci_read_config32(k8_f0, 0x68); + l_dword &= ~(1 << 22); + l_dword |= (1 << 21); + pci_write_config32(k8_f0, 0x68, l_dword); + + /* Enable 64bit mode. */ + set_nbmc_enable_bits(nb_dev, 0x5f, 0, 1 << 9); + set_nbmc_enable_bits(nb_dev, 0xb0, 0, 1 << 8); + + /* 64bit Latency. */ + set_nbmc_enable_bits(nb_dev, 0x5f, 0x7c00, 0x800); + + /* UMA dual channel control register. */ + nbmc_write_index(nb_dev, 0x86, 0x3d); + + /* check the setting later!! */ + set_htiu_enable_bits(nb_dev, 0x07, 1 << 7, 0); + + /* UMA mode, powerdown memory PLL. */ + set_nbmc_enable_bits(nb_dev, 0x74, 0, 1 << 31); + + /* Copy CPU DDR Controller to NB MC. */ + /* Why K8_MC_REG80 is special? */ + k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2)); + for (i = 0; i <= (0x80 - 0x40) / 4; i++) { + l_dword = pci_read_config32(k8_f2, 0x40 + i * 4); + nbmc_write_index(nb_dev, 0x63 + i, l_dword); + } + + /* Set K8 MC for UMA, Family F. */ + l_dword = pci_read_config32(k8_f2, 0xa0); + l_dword |= 0x2c; + pci_write_config32(k8_f2, 0xa0, l_dword); + l_dword = pci_read_config32(k8_f2, 0x94); + l_dword &= 0xf0ffffff; + l_dword |= 0x07000000; + pci_write_config32(k8_f2, 0x94, l_dword); + + /* set FB size and location. */ + nbmc_write_index(nb_dev, 0x1b, 0x00); + l_dword = nbmc_read_index(nb_dev, 0x1c); + l_dword &= 0xffff0; + l_dword |= 0x400 << 20; + l_dword |= 0x4; + nbmc_write_index(nb_dev, 0x1c, l_dword); + l_dword = nbmc_read_index(nb_dev, 0x1d); + l_dword &= 0xfffff000; + l_dword |= 0x0400; + nbmc_write_index(nb_dev, 0x1d, l_dword); + nbmc_write_index(nb_dev, 0x100, 0x3fff3800); + + /* Program MC table. */ + set_nbmc_enable_bits(nb_dev, 0x00, 0, 1 << 31); + l_dword = nbmc_read_index(nb_dev, 0x91); + l_dword |= 0x5; + nbmc_write_index(nb_dev, 0x91, l_dword); + set_nbmc_enable_bits(nb_dev, 0xb1, 0, 1 << 6); + set_nbmc_enable_bits(nb_dev, 0xc3, 0, 1); + + /* TODO: the optimization of voltage and frequency */ +} + +static struct pci_operations lops_pci = { + .set_subsystem = pci_dev_set_subsystem, +}; + +static struct device_operations pcie_ops = { + .read_resources = rs690_gfx_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = internal_gfx_pci_dev_init, /* The option ROM initializes the device. rs690_gfx_init, */ + .scan_bus = 0, + .enable = rs690_internal_gfx_enable, + .ops_pci = &lops_pci, +}; + +/* + * The dev id of 690G is 791E, while the id of 690M, 690T is 791F. + * We should list both of them here. + * */ +static const struct pci_driver pcie_driver_690t __pci_driver = { + .ops = &pcie_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_RS690MT_INT_GFX, +}; + +static const struct pci_driver pcie_driver_690 __pci_driver = { + .ops = &pcie_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_RS690_INT_GFX, +}; + +/* step 12 ~ step 14 from rpr */ +static void single_port_configuration(device_t nb_dev, device_t dev) +{ + u8 result, width; + u32 reg32; + struct southbridge_amd_rs690_config *cfg = + (struct southbridge_amd_rs690_config *)nb_dev->chip_info; + + printk(BIOS_INFO, "rs690_gfx_init single_port_configuration.\n"); + + /* step 12 training, releases hold training for GFX port 0 (device 2) */ + set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 4, 0<<4); + PcieReleasePortTraining(nb_dev, dev, 2); + result = PcieTrainPort(nb_dev, dev, 2); + printk(BIOS_INFO, "rs690_gfx_init single_port_configuration step12.\n"); + + /* step 13 Power Down Control */ + /* step 13.1 Enables powering down transmitter and receiver pads along with PLL macros. */ + set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 1 << 0); + + /* step 13.a Link Training was NOT successful */ + if (!result) { + set_nbmisc_enable_bits(nb_dev, 0x8, 0, 0x3 << 4); /* prevent from training. */ + set_nbmisc_enable_bits(nb_dev, 0xc, 0, 0x3 << 2); /* hide the GFX bridge. */ + if (cfg->gfx_tmds) + nbpcie_ind_write_index(nb_dev, 0x65, 0xccf0f0); + else { + nbpcie_ind_write_index(nb_dev, 0x65, 0xffffffff); + set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 3, 1 << 3); + } + } else { /* step 13.b Link Training was successful */ + + reg32 = nbpcie_p_read_index(dev, 0xa2); + width = (reg32 >> 4) & 0x7; + printk(BIOS_DEBUG, "GFX LC_LINK_WIDTH = 0x%x.\n", width); + switch (width) { + case 1: + case 2: + nbpcie_ind_write_index(nb_dev, 0x65, + cfg->gfx_lane_reversal ? 0x7f7f : 0xccfefe); + break; + case 4: + nbpcie_ind_write_index(nb_dev, 0x65, + cfg->gfx_lane_reversal ? 0x3f3f : 0xccfcfc); + break; + case 8: + nbpcie_ind_write_index(nb_dev, 0x65, + cfg->gfx_lane_reversal ? 0x0f0f : 0xccf0f0); + break; + } + } + printk(BIOS_INFO, "rs690_gfx_init single_port_configuration step13.\n"); + + /* step 14 Reset Enumeration Timer, disables the shortening of the enumeration timer */ + set_pcie_enable_bits(dev, 0x70, 1 << 19, 0 << 19); + printk(BIOS_INFO, "rs690_gfx_init single_port_configuration step14.\n"); +} + +/* step 15 ~ step 18 from rpr */ +static void dual_port_configuration(device_t nb_dev, device_t dev) +{ + u8 result, width; + u32 reg32; + struct southbridge_amd_rs690_config *cfg = + (struct southbridge_amd_rs690_config *)nb_dev->chip_info; + + /* step 15: Training for Device 2 */ + set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 4, 0 << 4); + /* Releases hold training for GFX port 0 (device 2) */ + PcieReleasePortTraining(nb_dev, dev, 2); + /* PCIE Link Training Sequence */ + result = PcieTrainPort(nb_dev, dev, 2); + + /* step 16: Power Down Control for Device 2 */ + /* step 16.a Link Training was NOT successful */ + if (!result) { + /* Powers down all lanes for port A */ + nbpcie_ind_write_index(nb_dev, 0x65, 0x0f0f); + } else { /* step 16.b Link Training was successful */ + + reg32 = nbpcie_p_read_index(dev, 0xa2); + width = (reg32 >> 4) & 0x7; + printk(BIOS_DEBUG, "GFX LC_LINK_WIDTH = 0x%x.\n", width); + switch (width) { + case 1: + case 2: + nbpcie_ind_write_index(nb_dev, 0x65, + cfg->gfx_lane_reversal ? 0x0707 : 0x0e0e); + break; + case 4: + nbpcie_ind_write_index(nb_dev, 0x65, + cfg->gfx_lane_reversal ? 0x0303 : 0x0c0c); + break; + } + } + + /* step 17: Training for Device 3 */ + set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 5, 0 << 5); + /* Releases hold training for GFX port 0 (device 3) */ + PcieReleasePortTraining(nb_dev, dev, 3); + /* PCIE Link Training Sequence */ + result = PcieTrainPort(nb_dev, dev, 3); + + /*step 18: Power Down Control for Device 3 */ + /* step 18.a Link Training was NOT successful */ + if (!result) { + /* Powers down all lanes for port B and PLL1 */ + nbpcie_ind_write_index(nb_dev, 0x65, 0xccf0f0); + } else { /* step 18.b Link Training was successful */ + + reg32 = nbpcie_p_read_index(dev, 0xa2); + width = (reg32 >> 4) & 0x7; + printk(BIOS_DEBUG, "GFX LC_LINK_WIDTH = 0x%x.\n", width); + switch (width) { + case 1: + case 2: + nbpcie_ind_write_index(nb_dev, 0x65, + cfg->gfx_lane_reversal ? 0x7070 : 0xe0e0); + break; + case 4: + nbpcie_ind_write_index(nb_dev, 0x65, + cfg->gfx_lane_reversal ? 0x3030 : 0xc0c0); + break; + } + } +} + + +/* For single port GFX configuration Only +* width: +* 000 = x16 +* 001 = x1 +* 010 = x2 +* 011 = x4 +* 100 = x8 +* 101 = x12 (not supported) +* 110 = x16 +*/ +static void dynamic_link_width_control(device_t nb_dev, device_t dev, u8 width) +{ + u32 reg32; + device_t sb_dev; + struct southbridge_amd_rs690_config *cfg = + (struct southbridge_amd_rs690_config *)nb_dev->chip_info; + + /* step 5.9.1.1 */ + reg32 = nbpcie_p_read_index(dev, 0xa2); + + /* step 5.9.1.2 */ + set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 1 << 0); + /* step 5.9.1.3 */ + set_pcie_enable_bits(dev, 0xa2, 3 << 0, width << 0); + /* step 5.9.1.4 */ + set_pcie_enable_bits(dev, 0xa2, 1 << 8, 1 << 8); + /* step 5.9.2.4 */ + if (0 == cfg->gfx_reconfiguration) + set_pcie_enable_bits(dev, 0xa2, 1 << 11, 1 << 11); + + /* step 5.9.1.5 */ + do { + reg32 = nbpcie_p_read_index(dev, 0xa2); + } + while (reg32 & 0x100); + + /* step 5.9.1.6 */ + sb_dev = dev_find_slot(0, PCI_DEVFN(8, 0)); + do { + reg32 = pci_ext_read_config32(nb_dev, sb_dev, + PCIE_VC0_RESOURCE_STATUS); + } while (reg32 & VC_NEGOTIATION_PENDING); + + /* step 5.9.1.7 */ + reg32 = nbpcie_p_read_index(dev, 0xa2); + if (((reg32 & 0x70) >> 4) != 0x6) { + /* the unused lanes should be powered off. */ + } + + /* step 5.9.1.8 */ + set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 0 << 0); +} + +/* +* GFX Core initialization, dev2, dev3 +*/ +void rs690_gfx_init(device_t nb_dev, device_t dev, u32 port) +{ + u16 reg16; + struct southbridge_amd_rs690_config *cfg = + (struct southbridge_amd_rs690_config *)nb_dev->chip_info; + + printk(BIOS_INFO, "rs690_gfx_init, nb_dev=0x%p, dev=0x%p, port=0x%x.\n", + nb_dev, dev, port); + + /* step 0, REFCLK_SEL, skip A11 revision */ + set_nbmisc_enable_bits(nb_dev, 0x6a, 1 << 9, + cfg->gfx_dev2_dev3 ? 1 << 9 : 0 << 9); + printk(BIOS_INFO, "rs690_gfx_init step0.\n"); + + /* step 1, lane reversal (only need if CMOS option is enabled) */ + if (cfg->gfx_lane_reversal) { + set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); + if (cfg->gfx_dual_slot) + set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 3, 1 << 3); + } + printk(BIOS_INFO, "rs690_gfx_init step1.\n"); + + /* step 1.1, dual-slot gfx configuration (only need if CMOS option is enabled) */ + /* AMD calls the configuration CrossFire */ + if (cfg->gfx_dual_slot) + set_nbmisc_enable_bits(nb_dev, 0x0, 0xf << 8, 5 << 8); + printk(BIOS_INFO, "rs690_gfx_init step2.\n"); + + /* step 2, TMDS, (only need if CMOS option is enabled) */ + if (cfg->gfx_tmds) { + } + + /* step 3, GFX overclocking, (only need if CMOS option is enabled) */ + /* skip */ + + /* step 4, reset the GFX link */ + /* step 4.1 asserts both calibration reset and global reset */ + set_nbmisc_enable_bits(nb_dev, 0x8, 0x3 << 14, 0x3 << 14); + + /* step 4.2 de-asserts calibration reset */ + set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 14, 0 << 14); + + /* step 4.3 wait for at least 200us */ + udelay(200); + + /* step 4.4 de-asserts global reset */ + set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 15, 0 << 15); + + /* step 4.5 asserts both calibration reset and global reset */ + /* a weird step in RPR, don't do that */ + /* set_nbmisc_enable_bits(nb_dev, 0x8, 0x3 << 14, 0x3 << 14); */ + + /* step 4.6 bring external GFX device out of reset, wait for 1ms */ + mdelay(1); + printk(BIOS_INFO, "rs690_gfx_init step4.\n"); + + /* step 5 program PCIE memory mapped configuration space */ + /* done by enable_pci_bar3() before */ + + /* step 6 SBIOS compile flags */ + if (cfg->gfx_tmds) { + /* step 6.2.2 Clock-Muxing Control */ + /* step 6.2.2.1 */ + set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 16, 1 << 16); + + /* step 6.2.2.2 */ + set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 8, 1 << 8); + set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 10, 1 << 10); + + /* step 6.2.2.3 */ + set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 26, 1 << 26); + + /* step 6.2.3 Lane-Muxing Control */ + /* step 6.2.3.1 */ + set_nbmisc_enable_bits(nb_dev, 0x37, 0x3 << 8, 0x2 << 8); + + /* step 6.2.4 Received Data Control */ + /* step 6.2.4.1 */ + set_pcie_enable_bits(nb_dev, 0x40, 0x3 << 16, 0x2 << 16); + + /* step 6.2.4.2 */ + set_pcie_enable_bits(nb_dev, 0x40, 0x3 << 18, 0x3 << 18); + + /* step 6.2.4.3 */ + set_pcie_enable_bits(nb_dev, 0x40, 0x3 << 20, 0x0 << 20); + + /* step 6.2.4.4 */ + set_pcie_enable_bits(nb_dev, 0x40, 0x3 << 22, 0x1 << 22); + + /* step 6.2.5 PLL Power Down Control */ + /* step 6.2.5.1 */ + set_nbmisc_enable_bits(nb_dev, 0x35, 0x3 << 6, 0x0 << 6); + + /* step 6.2.6 Driving Strength Control */ + /* step 6.2.6.1 */ + set_nbmisc_enable_bits(nb_dev, 0x34, 0x1 << 24, 0x0 << 24); + + /* step 6.2.6.2 */ + set_nbmisc_enable_bits(nb_dev, 0x35, 0x3 << 2, 0x3 << 2); + } + + printk(BIOS_INFO, "rs690_gfx_init step6.\n"); + + /* step 7 compliance state, (only need if CMOS option is enabled) */ + /* the compliance stete is just for test. refer to 4.2.5.2 of PCIe specification */ + if (cfg->gfx_compliance) { + /* force compliance */ + set_nbmisc_enable_bits(nb_dev, 0x32, 1 << 6, 1 << 6); + /* release hold training for device 2. GFX initialization is done. */ + set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 4, 0 << 4); + dynamic_link_width_control(nb_dev, dev, cfg->gfx_link_width); + printk(BIOS_INFO, "rs690_gfx_init step7.\n"); + return; + } + + /* step 8 common initialization */ + /* step 8.1 sets RCB timeout to be 25ms */ + set_pcie_enable_bits(dev, 0x70, 7 << 16, 3 << 16); + printk(BIOS_INFO, "rs690_gfx_init step8.1.\n"); + + /* step 8.2 disables slave ordering logic */ + set_pcie_enable_bits(nb_dev, 0x20, 1 << 8, 1 << 8); + printk(BIOS_INFO, "rs690_gfx_init step8.2.\n"); + + /* step 8.3 sets DMA payload size to 64 bytes */ + set_pcie_enable_bits(nb_dev, 0x10, 7 << 10, 4 << 10); + printk(BIOS_INFO, "rs690_gfx_init step8.3.\n"); + + /* step 8.4 if the LTSSM could not see all 8 TS1 during Polling Active, it can still + * time out and go back to Detect Idle.*/ + set_pcie_enable_bits(dev, 0x02, 1 << 14, 1 << 14); + printk(BIOS_INFO, "rs690_gfx_init step8.4.\n"); + + /* step 8.5 shortens the enumeration timer */ + set_pcie_enable_bits(dev, 0x70, 1 << 19, 1 << 19); + printk(BIOS_INFO, "rs690_gfx_init step8.5.\n"); + + /* step 8.6 blocks DMA traffic during C3 state */ + set_pcie_enable_bits(dev, 0x10, 1 << 0, 0 << 0); + printk(BIOS_INFO, "rs690_gfx_init step8.6.\n"); + + /* step 8.7 Do not gate the electrical idle form the PHY + * step 8.8 Enables the escape from L1L23 */ + set_pcie_enable_bits(dev, 0xa0, 3 << 30, 3 << 30); + printk(BIOS_INFO, "rs690_gfx_init step8.8.\n"); + + /* step 8.9 Setting this register to 0x1 will workaround a PCI Compliance failure reported by Vista DTM. + * SLOT_IMPLEMENTED@PCIE_CAP */ + reg16 = pci_read_config16(dev, 0x5a); + reg16 |= 0x100; + pci_write_config16(dev, 0x5a, reg16); + printk(BIOS_INFO, "rs690_gfx_init step8.9.\n"); + + /* step 8.10 Setting this register to 0x1 will hide the Advanced Error Rporting Capabilities in the PCIE Brider. + * This will workaround several failures reported by the PCI Compliance test under Vista DTM. */ + set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 31, 0 << 31); + printk(BIOS_INFO, "rs690_gfx_init step8.10.\n"); + + /* step 8.11 Sets REGS_DLP_IGNORE_IN_L1_EN to ignore DLLPs during L1 so that txclk can be turned off. */ + set_pcie_enable_bits(nb_dev, 0x02, 1 << 0, 1 << 0); + printk(BIOS_INFO, "rs690_gfx_init step8.11.\n"); + + /* step 8.12 Sets REGS_LC_DONT_GO_TO_L0S_IF_L1_ARMED to prevent lc to go to from L0 to Rcv_L0s if L1 is armed. */ + set_pcie_enable_bits(nb_dev, 0x02, 1 << 6, 1 << 6); + printk(BIOS_INFO, "rs690_gfx_init step8.12.\n"); + + /* step 8.13 Sets CMGOOD_OVERRIDE. */ + set_nbmisc_enable_bits(nb_dev, 0x6a, 1 << 17, 1 << 17); + printk(BIOS_INFO, "rs690_gfx_init step8.13.\n"); + + /* step 9 Enable TLP Flushing, for non-AMD GFX devices and Hot-Plug devices only. */ + /* skip */ + + /* step 10 Optional Features, only needed if CMOS option is enabled. */ + /* step 10.a: L0s */ + /* enabling L0s in the RS690 GFX port(s) */ + set_pcie_enable_bits(nb_dev, 0xF9, 3 << 13, 2 << 13); + set_pcie_enable_bits(dev, 0xA0, 0xf << 8, 8 << 8); + reg16 = pci_read_config16(dev, 0x68); + reg16 |= 1 << 0; + /* L0s is intended as a power saving state */ + /* pci_write_config16(dev, 0x68, reg16); */ + + /* enabling L0s in the External GFX Device(s) */ + + /* step 10.b: active state power management (ASPM L1) */ + /* TO DO */ + + /* step 10.c: turning off PLL During L1/L23 */ + set_pcie_enable_bits(nb_dev, 0x40, 1 << 3, 1 << 3); + set_pcie_enable_bits(nb_dev, 0x40, 1 << 9, 1 << 9); + + /* step 10.d: TXCLK clock gating */ + set_nbmisc_enable_bits(nb_dev, 0x7, 3, 3); + set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 22, 1 << 22); + set_pcie_enable_bits(nb_dev, 0x11, 0xf << 4, 0xc << 4); + + /* step 10.e: LCLK clock gating, done in rs690_config_misc_clk() */ + + /* step 11 Poll GPIO to determine whether it is single-port or dual-port configuration. + * While details will be added later in the document, for now assue the single-port configuration. */ + /* skip */ + + /* Single-port/Dual-port configureation. */ + switch (cfg->gfx_dual_slot) { + case 0: + single_port_configuration(nb_dev, dev); + break; + case 1: + dual_port_configuration(nb_dev, dev); + break; + default: + printk(BIOS_INFO, "Incorrect configuration of external gfx slot.\n"); + break; + } +} diff --git a/src/southbridge/amd/rs690/ht.c b/src/southbridge/amd/rs690/ht.c new file mode 100644 index 0000000000..26824b5322 --- /dev/null +++ b/src/southbridge/amd/rs690/ht.c @@ -0,0 +1,90 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 +#include +#include +#include +#include +#include "rs690.h" + +/* for UMA internal graphics */ +void avoid_lpc_dma_deadlock(device_t nb_dev, device_t sb_dev) +{ + device_t k8_f0; + u8 reg; + + k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); + set_nbcfg_enable_bits(k8_f0, 0x68, 3 << 21, 1 << 21); + + reg = nbpcie_p_read_index(sb_dev, 0x10); + reg |= 0x100; /* bit9=1 */ + nbpcie_p_write_index(sb_dev, 0x10, reg); + + reg = nbpcie_p_read_index(nb_dev, 0x10); + reg |= 0x100; /* bit9=1 */ + nbpcie_p_write_index(nb_dev, 0x10, reg); + + /* Enable NP protocol over PCIE for memory-mapped writes targeting LPC + * Set this bit to avoid a deadlock condition. */ + reg = htiu_read_index(nb_dev, 0x6); + reg |= 0x1000000; /* bit26 */ + htiu_write_index(nb_dev, 0x6, reg); +} + +static void pcie_init(struct device *dev) +{ + /* Enable pci error detecting */ + u32 dword; + + printk(BIOS_INFO, "pcie_init in rs690_ht.c\n"); + + /* System error enable */ + dword = pci_read_config32(dev, 0x04); + dword |= (1 << 8); /* System error enable */ + dword |= (1 << 30); /* Clear possible errors */ + pci_write_config32(dev, 0x04, dword); + + /* + * 1 is APIC enable + * 18 is enable nb to accept A4 interrupt request from SB. + */ + dword = pci_read_config32(dev, 0x4C); + dword |= 1 << 1 | 1 << 18; /* Clear possible errors */ + pci_write_config32(dev, 0x4C, dword); +} + +static struct pci_operations lops_pci = { + .set_subsystem = pci_dev_set_subsystem, +}; + +static struct device_operations ht_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = pcie_init, + .scan_bus = 0, + .ops_pci = &lops_pci, +}; + +static const struct pci_driver ht_driver __pci_driver = { + .ops = &ht_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_RS690_HT, +}; diff --git a/src/southbridge/amd/rs690/pcie.c b/src/southbridge/amd/rs690/pcie.c new file mode 100644 index 0000000000..f02e0d73b4 --- /dev/null +++ b/src/southbridge/amd/rs690/pcie.c @@ -0,0 +1,401 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 +#include +#include +#include +#include +#include +#include "rs690.h" + +/*------------------------------------------------ +* Global variable +------------------------------------------------*/ +PCIE_CFG AtiPcieCfg = { + PCIE_ENABLE_STATIC_DEV_REMAP, /* Config */ + 0, /* ResetReleaseDelay */ + 0, /* Gfx0Width */ + 0, /* Gfx1Width */ + 0, /* GfxPayload */ + 0, /* GppPayload */ + 0, /* PortDetect, filled by GppSbInit */ + 0, /* PortHp */ + 0, /* DbgConfig */ + 0, /* DbgConfig2 */ + 0, /* GfxLx */ + 0, /* GppLx */ + 0, /* NBSBLx */ + 0, /* PortSlotInit */ + 0, /* Gfx0Pwr */ + 0, /* Gfx1Pwr */ + 0 /* GppPwr */ +}; + +static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port); +static void ValidatePortEn(device_t nb_dev); + +static void ValidatePortEn(device_t nb_dev) +{ +} + + +/***************************************************************** +* Compliant with CIM_33's PCIEPowerOffGppPorts +* Power off unused GPP lines +*****************************************************************/ +static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port) +{ + u32 reg; + u16 state_save; + struct southbridge_amd_rs690_config *cfg = + (struct southbridge_amd_rs690_config *)nb_dev->chip_info; + u8 state = cfg->port_enable; + + if (!(AtiPcieCfg.Config & PCIE_DISABLE_HIDE_UNUSED_PORTS)) + state &= AtiPcieCfg.PortDetect; + state = ~state; + state &= (1 << 4) + (1 << 5) + (1 << 6) + (1 << 7); + state_save = state << 17; + state &= !(AtiPcieCfg.PortHp); + reg = nbmisc_read_index(nb_dev, 0x0c); + reg |= state; + nbmisc_write_index(nb_dev, 0x0c, reg); + + reg = nbmisc_read_index(nb_dev, 0x08); + reg |= state_save; + nbmisc_write_index(nb_dev, 0x08, reg); + + if ((AtiPcieCfg.Config & PCIE_OFF_UNUSED_GPP_LANES) + && !(AtiPcieCfg. + Config & (PCIE_DISABLE_HIDE_UNUSED_PORTS + + PCIE_GFX_COMPLIANCE))) { + } + + if (!cfg->gfx_tmds){ + /* step 3 Power Down Control for Southbridge */ + reg = nbpcie_p_read_index(dev, 0xa2); + + switch ((reg >> 4) & 0x7) { /* get bit 4-6, LC_LINK_WIDTH_RD */ + case 1: + nbpcie_ind_write_index(nb_dev, 0x65, 0x0e0e); + break; + case 2: + nbpcie_ind_write_index(nb_dev, 0x65, 0x0c0c); + break; + default: + break; + } + } +} + +#ifdef UNUSED_CODE +static void pcie_init(struct device *dev) +{ + /* Enable pci error detecting */ + u32 dword; + + printk(BIOS_DEBUG, "pcie_init in rs690_pcie.c\n"); + + /* System error enable */ + dword = pci_read_config32(dev, 0x04); + dword |= (1 << 8); /* System error enable */ + dword |= (1 << 30); /* Clear possible errors */ + pci_write_config32(dev, 0x04, dword); +} +#endif + +/********************************************************************** +**********************************************************************/ +static void switching_gpp_configurations(device_t nb_dev, device_t sb_dev) +{ + u32 reg; + struct southbridge_amd_rs690_config *cfg = + (struct southbridge_amd_rs690_config *)nb_dev->chip_info; + + /* enables GPP reconfiguration */ + reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7); + reg |= + (RECONFIG_GPPSB_EN + RECONFIG_GPPSB_LINK_CONFIG + + RECONFIG_GPPSB_ATOMIC_RESET); + nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg); + + /* sets desired GPPSB configurations, bit4-7 */ + reg = nbmisc_read_index(nb_dev, 0x67); + reg &= 0xffffff0f; /* clean */ + reg |= cfg->gpp_configuration << 4; + nbmisc_write_index(nb_dev, 0x67, reg); + + /* read bit14 and write back its inverst value */ + reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7); + reg ^= RECONFIG_GPPSB_GPPSB; + nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg); + + /* delay 1ms */ + mdelay(1); + + /* waits until SB has trained to L0, poll for bit0-5 = 0x10 */ + do { + reg = nbpcie_p_read_index(sb_dev, PCIE_LC_STATE0); + reg &= 0x3f; /* remain LSB [5:0] bits */ + } while (LC_STATE_RECONFIG_GPPSB != reg); + + /* ensures that virtual channel negotiation is completed. poll for bit1 = 0 */ + do { + reg = + pci_ext_read_config32(nb_dev, sb_dev, + PCIE_VC0_RESOURCE_STATUS); + } while (reg & VC_NEGOTIATION_PENDING); +} + +/***************************************************************** +* The rs690 uses NBCONFIG:0x1c (BAR3) to map the PCIE Extended Configuration +* Space to a 256MB range within the first 4GB of addressable memory. +*****************************************************************/ +void enable_pcie_bar3(device_t nb_dev) +{ + printk(BIOS_DEBUG, "enable_pcie_bar3()\n"); + set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 1 << 30); /* Enables writes to the BAR3 register. */ + set_nbcfg_enable_bits(nb_dev, 0x84, 7 << 16, 0 << 16); + + pci_write_config32(nb_dev, 0x1C, EXT_CONF_BASE_ADDRESS); /* PCIEMiscInit */ + pci_write_config32(nb_dev, 0x20, 0x00000000); + set_htiu_enable_bits(nb_dev, 0x32, 1 << 28, 1 << 28); /* PCIEMiscInit */ + ProgK8TempMmioBase(1, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS); +} + +/***************************************************************** +* We should disable bar3 when we want to exit rs690_enable, because bar3 will be +* remapped in set_resource later. +*****************************************************************/ +void disable_pcie_bar3(device_t nb_dev) +{ + printk(BIOS_DEBUG, "disable_pcie_bar3()\n"); + set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 0 << 30); /* Disable writes to the BAR3. */ + pci_write_config32(nb_dev, 0x1C, 0); /* clear BAR3 address */ + ProgK8TempMmioBase(0, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS); +} + +/***************************************** +* Compliant with CIM_33's PCIEGPPInit +* nb_dev: +* root bridge struct +* dev: +* p2p bridge struct +* port: +* p2p bridge number, 4-8 +*****************************************/ +void rs690_gpp_sb_init(device_t nb_dev, device_t dev, u32 port) +{ + u8 reg8; + u16 reg16; + device_t sb_dev; + struct southbridge_amd_rs690_config *cfg = + (struct southbridge_amd_rs690_config *)nb_dev->chip_info; + printk(BIOS_DEBUG, "gpp_sb_init nb_dev=0x%p, dev=0x%p, port=0x%x\n", nb_dev, dev, port); + + /* init GPP core */ + set_pcie_enable_bits(nb_dev, 0x20 | PCIE_CORE_INDEX_GPPSB, 1 << 8, + 1 << 8); + /* PCIE initialization 5.10.2: rpr 2.12*/ + set_pcie_enable_bits(nb_dev, 0x02 | PCIE_CORE_INDEX_GPPSB, 1 << 0, 1 << 0); /* no description in datasheet. */ + + /* init GPPSB port */ + /* Sets RCB timeout to be 100ms by setting bits[18:16] to 3 b101 and shortens the enumeration timer by setting bit[19] to 1*/ + set_pcie_enable_bits(dev, 0x70, 0xF << 16, 0xd << 16); + /* PCIE initialization 5.10.2: rpr 2.4 */ + set_pcie_enable_bits(dev, 0x02, ~0xffffffff, 1 << 14); + /* Do not gate the electrical idle from the PHY and enables the escape from L1L23 */ + set_pcie_enable_bits(dev, 0xA0, ~0xffffffbf, (3 << 30) | (3 << 12) | (3 << 4)); + /* PCIE initialization 5.10.2: rpr 2.13 */ + set_pcie_enable_bits(dev, 0x02, ~0xffffffff, 1 << 6); + + /* SLOT_IMPLEMENTED in pcieConfig space */ + reg8 = pci_read_config8(dev, 0x5b); + reg8 |= 1 << 0; + pci_write_config8(dev, 0x5b, reg8); + + reg16 = pci_read_config16(dev, 0x5a); + reg16 |= 0x100; + pci_write_config16(dev, 0x5a, reg16); + nbmisc_write_index(nb_dev, 0x34, 0); + + /* check compliance rpr step 2.1*/ + if (AtiPcieCfg.Config & PCIE_GPP_COMPLIANCE) { + u32 tmp; + tmp = nbmisc_read_index(nb_dev, 0x67); + tmp |= 1 << 3; + nbmisc_write_index(nb_dev, 0x67, tmp); + } + + /* step 5: dynamic slave CPL buffer allocation */ + set_pcie_enable_bits(nb_dev, 0x20 | PCIE_CORE_INDEX_GPPSB, 1 << 11, 1 << 11); + + /* step 5a: Training for GPP devices */ + /* init GPP */ + switch (port) { + case 4: /* GPP */ + case 5: + case 6: + case 7: + /* Blocks DMA traffic during C3 state */ + set_pcie_enable_bits(dev, 0x10, 1 << 0, 0 << 0); + /* Enabels TLP flushing */ + set_pcie_enable_bits(dev, 0x20, 1 << 19, 0 << 19); + + /* check port enable */ + if (cfg->port_enable & (1 << port)) { + PcieReleasePortTraining(nb_dev, dev, port); + if (!(AtiPcieCfg.Config & PCIE_GPP_COMPLIANCE)) { + u8 res = PcieTrainPort(nb_dev, dev, port); + printk(BIOS_DEBUG, "PcieTrainPort port=0x%x result=%d\n", port, res); + if (res) { + AtiPcieCfg.PortDetect |= 1 << port; + } + } + } + break; + case 8: /* SB */ + break; + } + PciePowerOffGppPorts(nb_dev, dev, port); + + /* step 5b: GFX devices in a GPP slot */ + + /* step 6a: VCI */ + sb_dev = dev_find_slot(0, PCI_DEVFN(8, 0)); + if (port == 8) { + /* The code below between #if and #endif causes a hang on HDA init. + * So we skip it. */ +#if 0 + /* Clear bits 7:1 */ + pci_ext_write_config32(nb_dev, sb_dev, 0x114, 0x3f << 1, 0 << 1); + /* Maps Traffic Class 1-7 to VC1 */ + pci_ext_write_config32(nb_dev, sb_dev, 0x120, 0x7f << 1, 0x7f << 1); + /* Assigns VC ID to 1 */ + pci_ext_write_config32(nb_dev, sb_dev, 0x120, 7 << 24, 1 << 24); + /* Enables VC1 */ + pci_ext_write_config32(nb_dev, sb_dev, 0x120, 1 << 31, 1 << 31); + + do { + reg16 = pci_ext_read_config32(nb_dev, sb_dev, 0x124); + reg16 &= 0x2; + } while (reg16); /*bit[1] = 0 means VC1 flow control initialization is successful */ +#endif + } + + /* step 6b: L0s for the southbridge link */ + /* To enalbe L0s in the southbridage*/ + + /* step 6c: L0s for the GPP link(s) */ + /* To eable L0s in the RS690 for the GPP port(s) */ + set_pcie_enable_bits(nb_dev, 0xf9, 3 << 13, 2 << 13); + set_pcie_enable_bits(dev, 0xa0, 0xf << 8, 0x9 << 8); + reg16 = pci_read_config16(dev, 0x68); + reg16 |= 1 << 0; + pci_write_config16(dev, 0x68, reg16); + + /* step 6d: ASPM L1 for the southbridge link */ + /* To enalbe L1s in the southbridage*/ + + /* step 6e: ASPM L1 for GPP link(s) */; + set_pcie_enable_bits(nb_dev, 0xf9, 3 << 13, 2 << 13); + set_pcie_enable_bits(dev, 0xa0, 3 << 12, 3 << 12); + set_pcie_enable_bits(dev, 0xa0, 0xf << 4, 3 << 4); + reg16 = pci_read_config16(dev, 0x68); + reg16 &= ~0xff; + reg16 |= 1 << 1; + pci_write_config16(dev, 0x68, reg16); + + /* step 6f: Turning off PLL during L1/L23 */ + set_pcie_enable_bits(nb_dev, 0x40, 1 << 3, 1 << 3); + set_pcie_enable_bits(nb_dev, 0x40, 1 << 9, 1 << 9); + + /* step 6g: TXCLK clock gating */ + set_nbmisc_enable_bits(nb_dev, 0x7, 3 << 4, 3 << 4); + set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 22, 1 << 22); + set_pcie_enable_bits(nb_dev, 0x11, 0xf << 4, 0xc << 4); + + /* step 6h: LCLK clock gating, done in rs690_config_misc_clk() */ +} + +/***************************************** +* Compliant with CIM_33's PCIEConfigureGPPCore +*****************************************/ +void config_gpp_core(device_t nb_dev, device_t sb_dev) +{ + u32 reg; + struct southbridge_amd_rs690_config *cfg = + (struct southbridge_amd_rs690_config *)nb_dev->chip_info; + + reg = nbmisc_read_index(nb_dev, 0x20); + if (AtiPcieCfg.Config & PCIE_ENABLE_STATIC_DEV_REMAP) + reg &= 0xfffffffd; /* set bit1 = 0 */ + else + reg |= 0x2; /* set bit1 = 1 */ + nbmisc_write_index(nb_dev, 0x20, reg); + + reg = nbmisc_read_index(nb_dev, 0x67); /* get STRAP_BIF_LINK_CONFIG_GPPSB at bit 4-7 */ + if (cfg->gpp_configuration != ((reg >> 4) & 0xf)) + switching_gpp_configurations(nb_dev, sb_dev); + ValidatePortEn(nb_dev); +} + +#ifdef UNUSED_CODE +/***************************************** +* Compliant with CIM_33's PCIEMiscClkProg +*****************************************/ +void pcie_config_misc_clk(device_t nb_dev) +{ + u32 reg; + struct bus pbus; /* fake bus for dev0 fun1 */ + + reg = pci_read_config32(nb_dev, 0x4c); + reg |= 1 << 0; + pci_write_config32(nb_dev, 0x4c, reg); + + if (AtiPcieCfg.Config & PCIE_GFX_CLK_GATING) { + /* TXCLK Clock Gating */ + set_nbmisc_enable_bits(nb_dev, 0x07, 3 << 0, 3 << 0); + set_nbmisc_enable_bits(nb_dev, 0x07, 1 << 22, 1 << 22); + set_pcie_enable_bits(nb_dev, 0x11 | PCIE_CORE_INDEX_GFX, (3 << 6) | (~0xf), 3 << 6); + + /* LCLK Clock Gating */ + reg = pci_cf8_conf1.read32(&pbus, 0, 1, 0x94); + reg &= ~(1 << 16); + pci_cf8_conf1.write32(&pbus, 0, 1, 0x94, reg); + } + + if (AtiPcieCfg.Config & PCIE_GPP_CLK_GATING) { + /* TXCLK Clock Gating */ + set_nbmisc_enable_bits(nb_dev, 0x07, 3 << 4, 3 << 4); + set_nbmisc_enable_bits(nb_dev, 0x07, 1 << 22, 1 << 22); + set_pcie_enable_bits(nb_dev, 0x11 | PCIE_CORE_INDEX_GPPSB, (3 << 6) | (~0xf), 3 << 6); + + /* LCLK Clock Gating */ + reg = pci_cf8_conf1.read32(&pbus, 0, 1, 0x94); + reg &= ~(1 << 24); + pci_cf8_conf1.write32(&pbus, 0, 1, 0x94, reg); + } + + reg = pci_read_config32(nb_dev, 0x4c); + reg &= ~(1 << 0); + pci_write_config32(nb_dev, 0x4c, reg); +} +#endif diff --git a/src/southbridge/amd/rs690/rs690_cmn.c b/src/southbridge/amd/rs690/rs690_cmn.c deleted file mode 100644 index 5e06d4f9d8..0000000000 --- a/src/southbridge/amd/rs690/rs690_cmn.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include "rs690.h" - -static u32 nb_read_index(device_t dev, u32 index_reg, u32 index) -{ - pci_write_config32(dev, index_reg, index); - return pci_read_config32(dev, index_reg + 0x4); -} - -static void nb_write_index(device_t dev, u32 index_reg, u32 index, u32 data) -{ - - pci_write_config32(dev, index_reg, index); - pci_write_config32(dev, index_reg + 0x4, data); - -} - -/* extension registers */ -u32 pci_ext_read_config32(device_t nb_dev, device_t dev, u32 reg) -{ - /*get BAR3 base address for nbcfg0x1c */ - u32 addr = pci_read_config32(nb_dev, 0x1c) & ~0xF; - printk(BIOS_DEBUG, "addr=%x,bus=%x,devfn=%x\n", addr, dev->bus->secondary, - dev->path.pci.devfn); - addr |= dev->bus->secondary << 20 | /* bus num */ - dev->path.pci.devfn << 12 | reg; - return *((u32 *) addr); -} - -void pci_ext_write_config32(device_t nb_dev, device_t dev, u32 reg_pos, u32 mask, u32 val) -{ - u32 reg_old, reg; - - /*get BAR3 base address for nbcfg0x1c */ - u32 addr = pci_read_config32(nb_dev, 0x1c) & ~0xF; - /*printk(BIOS_DEBUG, "write: addr=%x,bus=%x,devfn=%x\n", addr, dev->bus->secondary, - dev->path.pci.devfn);*/ - addr |= dev->bus->secondary << 20 | /* bus num */ - dev->path.pci.devfn << 12 | reg_pos; - - reg = reg_old = *((u32 *) addr); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - *((u32 *) addr) = reg; - } -} - -u32 nbmisc_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBMISC_INDEX, (index)); -} - -void nbmisc_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBMISC_INDEX, ((index) | 0x80), (data)); -} - -u32 nbpcie_p_read_index(device_t dev, u32 index) -{ - return nb_read_index((dev), NBPCIE_INDEX, (index)); -} - -void nbpcie_p_write_index(device_t dev, u32 index, u32 data) -{ - nb_write_index((dev), NBPCIE_INDEX, (index), (data)); -} - -u32 nbpcie_ind_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBPCIE_INDEX, (index)); -} - -void nbpcie_ind_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBPCIE_INDEX, (index), (data)); -} - -u32 htiu_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBHTIU_INDEX, (index)); -} - -void htiu_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBHTIU_INDEX, ((index) | 0x100), (data)); -} - -u32 nbmc_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBMC_INDEX, (index)); -} - -void nbmc_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBMC_INDEX, ((index) | 1 << 9), (data)); -} - -void set_nbcfg_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) -{ - u32 reg_old, reg; - reg = reg_old = pci_read_config32(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - pci_write_config32(nb_dev, reg_pos, reg); - } -} - -void set_nbcfg_enable_bits_8(device_t nb_dev, u32 reg_pos, u8 mask, u8 val) -{ - u8 reg_old, reg; - reg = reg_old = pci_read_config8(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - pci_write_config8(nb_dev, reg_pos, reg); - } -} - -void set_nbmc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) -{ - u32 reg_old, reg; - reg = reg_old = nbmc_read_index(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - nbmc_write_index(nb_dev, reg_pos, reg); - } -} - -void set_htiu_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) -{ - u32 reg_old, reg; - reg = reg_old = htiu_read_index(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - htiu_write_index(nb_dev, reg_pos, reg); - } -} - -void set_nbmisc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) -{ - u32 reg_old, reg; - reg = reg_old = nbmisc_read_index(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - nbmisc_write_index(nb_dev, reg_pos, reg); - } -} - -void set_pcie_enable_bits(device_t dev, u32 reg_pos, u32 mask, u32 val) -{ - u32 reg_old, reg; - reg = reg_old = nb_read_index(dev, NBPCIE_INDEX, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - nb_write_index(dev, NBPCIE_INDEX, reg_pos, reg); - } -} - -/*********************************************************** -* To access bar3 we need to program PCI MMIO 7 in K8. -* in_out: -* 1: enable/enter k8 temp mmio base -* 0: disable/restore -***********************************************************/ -void ProgK8TempMmioBase(u8 in_out, u32 pcie_base_add, u32 mmio_base_add) -{ - /* K8 Function1 is address map */ - device_t k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1)); - device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); - - if (in_out) { - u32 dword, sblk; - - /* Get SBLink value (HyperTransport I/O Hub Link ID). */ - dword = pci_read_config32(k8_f0, 0x64); - sblk = (dword >> 8) & 0x3; - - /* Fill MMIO limit/base pair. */ - pci_write_config32(k8_f1, 0xbc, - (((pcie_base_add + 0x10000000 - - 1) >> 8) & 0xffffff00) | 0x80 | (sblk << 4)); - pci_write_config32(k8_f1, 0xb8, (pcie_base_add >> 8) | 0x3); - pci_write_config32(k8_f1, 0xb4, - (((mmio_base_add + 0x10000000 - - 1) >> 8) & 0xffffff00) | (sblk << 4)); - pci_write_config32(k8_f1, 0xb0, (mmio_base_add >> 8) | 0x3); - } else { - pci_write_config32(k8_f1, 0xb8, 0); - pci_write_config32(k8_f1, 0xbc, 0); - pci_write_config32(k8_f1, 0xb0, 0); - pci_write_config32(k8_f1, 0xb4, 0); - } -} - -void PcieReleasePortTraining(device_t nb_dev, device_t dev, u32 port) -{ - switch (port) { - case 2: /* GFX, bit4-5 */ - case 3: - set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG, - 1 << (port + 2), 0 << (port + 2)); - break; - case 4: /* GPP, bit20-24 */ - case 5: - case 6: - case 7: - set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG, - 1 << (port + 17), 0 << (port + 17)); - break; - } -} - -/******************************************************************************************************** -* Output: -* 0: no device is present. -* 1: device is present and is trained. -********************************************************************************************************/ -u8 PcieTrainPort(device_t nb_dev, device_t dev, u32 port) -{ - u16 count = 5000; - u32 lc_state, reg; - int8_t current, res = 0; - - while (count--) { - mdelay(40); - udelay(200); - lc_state = nbpcie_p_read_index(dev, 0xa5); /* lc_state */ - printk(BIOS_DEBUG, "PcieLinkTraining port=%x:lc current state=%x\n", - port, lc_state); - current = lc_state & 0x3f; /* get LC_CURRENT_STATE, bit0-5 */ - - switch (current) { - case 0x00: /* 0x00-0x04 means no device is present */ - case 0x01: - case 0x02: - case 0x03: - case 0x04: - res = 0; - count = 0; - break; - case 0x07: /* device is in compliance state (training sequence is doen). Move to train the next device */ - res = 1; /* TODO: CIM sets it to 0 */ - count = 0; - break; - case 0x10: - reg = - pci_ext_read_config32(nb_dev, dev, - PCIE_VC0_RESOURCE_STATUS); - printk(BIOS_DEBUG, "PcieTrainPort reg=0x%x\n", reg); - /* check bit1 */ - if (reg & VC_NEGOTIATION_PENDING) { /* bit1=1 means the link needs to be re-trained. */ - /* set bit8=1, bit0-2=bit4-6 */ - u32 tmp; - reg = - nbpcie_p_read_index(dev, - PCIE_LC_LINK_WIDTH); - tmp = (reg >> 4) && 0x3; /* get bit4-6 */ - reg &= 0xfff8; /* clear bit0-2 */ - reg += tmp; /* merge */ - reg |= 1 << 8; - count++; /* CIM said "keep in loop"? */ - } else { - res = 1; - count = 0; - } - break; - default: /* reset pcie */ - res = 0; - count = 0; /* break loop */ - break; - } - } - return res; -} - -/* -* Compliant with CIM_33's ATINB_SetToms. -* Set Top Of Memory below and above 4G. -*/ -void rs690_set_tom(device_t nb_dev) -{ - extern uint64_t uma_memory_base; - - /* set TOM */ - pci_write_config32(nb_dev, 0x90, uma_memory_base); - nbmc_write_index(nb_dev, 0x1e, uma_memory_base); -} - diff --git a/src/southbridge/amd/rs690/rs690_early_setup.c b/src/southbridge/amd/rs690/rs690_early_setup.c deleted file mode 100644 index f29d136791..0000000000 --- a/src/southbridge/amd/rs690/rs690_early_setup.c +++ /dev/null @@ -1,484 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 Advanced Micro Devices, Inc. - * Copyright (C) 2008 Carl-Daniel Hailfinger - * - * 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 - */ - - -#define NBHTIU_INDEX 0xA8 -#define NBMISC_INDEX 0x60 -#define NBMC_INDEX 0xE8 - -static u32 nb_read_index(device_t dev, u32 index_reg, u32 index) -{ - pci_write_config32(dev, index_reg, index); - return pci_read_config32(dev, index_reg + 0x4); -} - -static void nb_write_index(device_t dev, u32 index_reg, u32 index, u32 data) -{ - pci_write_config32(dev, index_reg, index /* | 0x80 */ ); - pci_write_config32(dev, index_reg + 0x4, data); -} - -static u32 nbmisc_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBMISC_INDEX, (index)); -} - -static void nbmisc_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBMISC_INDEX, ((index) | 0x80), (data)); -} - -static u32 htiu_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBHTIU_INDEX, (index)); -} - -static void htiu_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBHTIU_INDEX, ((index) | 0x100), (data)); -} - -static u32 nbmc_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBMC_INDEX, (index)); -} - -static void nbmc_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBMC_INDEX, ((index) | 1 << 9), (data)); -} - -static void set_htiu_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, - u32 val) -{ - u32 reg_old, reg; - reg = reg_old = htiu_read_index(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - htiu_write_index(nb_dev, reg_pos, reg); - } -} - -static void set_nbmisc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, - u32 val) -{ - u32 reg_old, reg; - reg = reg_old = nbmisc_read_index(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - nbmisc_write_index(nb_dev, reg_pos, reg); - } -} - -static void set_nbcfg_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, - u32 val) -{ - u32 reg_old, reg; - reg = reg_old = pci_read_config32(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - pci_write_config32(nb_dev, reg_pos, reg); - } -} - -static void set_nbcfg_enable_bits_8(device_t nb_dev, u32 reg_pos, u8 mask, - u8 val) -{ - u8 reg_old, reg; - reg = reg_old = pci_read_config8(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - pci_write_config8(nb_dev, reg_pos, reg); - } -} - -static void set_nbmc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, - u32 val) -{ - u32 reg_old, reg; - reg = reg_old = nbmc_read_index(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - nbmc_write_index(nb_dev, reg_pos, reg); - } -} - -/* -* Compliant with CIM_33's ATINB_PrepareInit -*/ -static void get_cpu_rev(void) -{ - u32 eax, ebx, ecx, edx; - __asm__ volatile ("cpuid":"=a" (eax), "=b"(ebx), "=c"(ecx), "=d"(edx) - :"0"(1)); - printk(BIOS_INFO, "get_cpu_rev EAX=0x%x.\n", eax); - if (eax <= 0xfff) - printk(BIOS_INFO, "CPU Rev is K8_Cx.\n"); - else if (eax <= 0x10fff) - printk(BIOS_INFO, "CPU Rev is K8_Dx.\n"); - else if (eax <= 0x20fff) - printk(BIOS_INFO, "CPU Rev is K8_Ex.\n"); - else if (eax <= 0x40fff) - printk(BIOS_INFO, "CPU Rev is K8_Fx.\n"); - else if (eax == 0x60fb1 || eax == 0x60f81) /*These two IDS are exception, they are G1. */ - printk(BIOS_INFO, "CPU Rev is K8_G1.\n"); - else if (eax <= 0X60FF0) - printk(BIOS_INFO, "CPU Rev is K8_G0.\n"); - else if (eax <= 0x100000) - printk(BIOS_INFO, "CPU Rev is K8_G1.\n"); - else - printk(BIOS_INFO, "CPU Rev is K8_10.\n"); -} - -static u8 get_nb_rev(device_t nb_dev) -{ - u32 reg; - reg = pci_read_config32(nb_dev, 0x00); - if (0x7911 == (reg >> 16)) - return 7; - reg = pci_read_config8(nb_dev, 0x89); /* copy from CIM, can't find in doc */ - if (reg & 0x2) /* check bit1 */ - return 7; - if (reg & 0x1) /* check bit0 */ - return 6; - else - return 5; -} - -/***************************************** -* Compliant with CIM_33's ATINB_HTInit -* Init HT link speed/width for rs690 -- k8 link -*****************************************/ -static void rs690_htinit(void) -{ - /* - * About HT, it has been done in enumerate_ht_chain(). - */ - device_t k8_f0, rs690_f0; - u32 reg; - u8 reg8; - u8 k8_ht_freq; - - k8_f0 = PCI_DEV(0, 0x18, 0); - /************************ - * get k8's ht freq, in k8's function 0, offset 0x88 - * bit11-8, specifics the maximum operation frequency of the link's transmitter clock. - * The link frequency field (Frq) is cleared by cold reset. SW can write a nonzero - * value to this reg, and that value takes effect on the next warm reset or - * LDTSTOP_L disconnect sequence. - * 0000b = 200Mhz - * 0010b = 400Mhz - * 0100b = 600Mhz - * 0101b = 800Mhz - * 0110b = 1Ghz - * 1111b = 1Ghz - ************************/ - reg = pci_read_config32(k8_f0, 0x88); - k8_ht_freq = (reg & 0xf00) >> 8; - printk(BIOS_SPEW, "rs690_htinit k8_ht_freq=%x.\n", k8_ht_freq); - rs690_f0 = PCI_DEV(0, 0, 0); - reg8 = pci_read_config8(rs690_f0, 0x9c); - printk(BIOS_SPEW, "rs690_htinit NB_CFG_Q_F1000_800=%x\n", reg8); - /* For 1000 MHz HT, NB_CFG_Q_F1000_800 bit 0 MUST be set. - * For any other HT frequency, NB_CFG_Q_F1000_800 bit 0 MUST NOT be set. - */ - if (((k8_ht_freq == 0x6) || (k8_ht_freq == 0xf)) && (!(reg8 & 0x1))) { - printk(BIOS_INFO, "rs690_htinit setting bit 0 in NB_CFG_Q_F1000_800 to use 1 GHz HT\n"); - reg8 |= 0x1; - pci_write_config8(rs690_f0, 0x9c, reg8); - } else if ((k8_ht_freq != 0x6) && (k8_ht_freq != 0xf) && (reg8 & 0x1)) { - printk(BIOS_INFO, "rs690_htinit clearing bit 0 in NB_CFG_Q_F1000_800 to not use 1 GHz HT\n"); - reg8 &= ~0x1; - pci_write_config8(rs690_f0, 0x9c, reg8); - } -} - -/******************************************************* -* Optimize k8 with UMA. -* See BKDG_NPT_0F guide for details. -* The processor node is addressed by its Node ID on the HT link and can be -* accessed with a device number in the PCI configuration space on Bus0. -* The Node ID 0 is mapped to Device 24 (0x18), the Node ID 1 is mapped -* to Device 25, and so on. -* The processor implements configuration registers in PCI configuration -* space using the following four headers -* Function0: HT technology configuration -* Function1: Address map configuration -* Function2: DRAM and HT technology Trace mode configuration -* Function3: Miscellaneous configuration -*******************************************************/ -static void k8_optimization(void) -{ - device_t k8_f0, k8_f2, k8_f3; - msr_t msr; - - printk(BIOS_INFO, "k8_optimization()\n"); - k8_f0 = PCI_DEV(0, 0x18, 0); - k8_f2 = PCI_DEV(0, 0x18, 2); - k8_f3 = PCI_DEV(0, 0x18, 3); - - pci_write_config32(k8_f0, 0x90, 0x01700178); /* CIM NPT_Optimization */ - set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 28, 0 << 28); - set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 26 | 1 << 27, - 1 << 26 | 1 << 27); - set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 11, 1 << 11); - set_nbcfg_enable_bits(k8_f0, 0x84, 1 << 11 | 1 << 13 | 1 << 15, 1 << 11 | 1 << 13 | 1 << 15); /* TODO */ - - pci_write_config32(k8_f3, 0x70, 0x51320111); /* CIM NPT_Optimization */ - pci_write_config32(k8_f3, 0x74, 0x50304021); - pci_write_config32(k8_f3, 0x78, 0x08002A00); - if (pci_read_config32(k8_f3, 0xE8) & 0x3<<12) - pci_write_config32(k8_f3, 0x7C, 0x0000211B); /* dual core */ - else - pci_write_config32(k8_f3, 0x7C, 0x0000211C); /* single core */ - set_nbcfg_enable_bits_8(k8_f3, 0xDC, 0xFF, 0x25); - - set_nbcfg_enable_bits(k8_f2, 0xA0, 1 << 5, 1 << 5); - set_nbcfg_enable_bits(k8_f2, 0x94, 0xF << 24, 7 << 24); - set_nbcfg_enable_bits(k8_f2, 0x90, 1 << 10, 1 << 10); - set_nbcfg_enable_bits(k8_f2, 0xA0, 3 << 2, 3 << 2); - set_nbcfg_enable_bits(k8_f2, 0xA0, 1 << 5, 1 << 5); - - msr = rdmsr(0xC001001F); - msr.lo &= ~(1 << 9); - msr.hi &= ~(1 << 4); - wrmsr(0xC001001F, msr); -} - -/***************************************** -* Compliant with CIM_33's ATINB_PCICFG_POR_TABLE -*****************************************/ -static void rs690_por_pcicfg_init(device_t nb_dev) -{ - /* enable PCI Memory Access */ - set_nbcfg_enable_bits_8(nb_dev, 0x04, (u8)(~0xFD), 0x02); - /* Set RCRB Enable */ - set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xFF), 0x1); - /* allow decode of 640k-1MB */ - set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xEF), 0x10); - /* Enable PM2_CNTL(BAR2) IO mapped cfg write access to be broadcast to both NB and SB */ - set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xFF), 0x4); - /* Power Management Register Enable */ - set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xFF), 0x80); - - /* Reg4Ch[1]=1 (APIC_ENABLE) force cpu request with address 0xFECx_xxxx to south-bridge - * Reg4Ch[6]=1 (BMMsgEn) enable BM_Set message generation - * BMMsgEn */ - set_nbcfg_enable_bits_8(nb_dev, 0x4C, (u8)(~0x00), 0x42 | 1); - - /* Reg4Ch[16]=1 (WakeC2En) enable Wake_from_C2 message generation. - * Reg4Ch[18]=1 (P4IntEnable) Enable north-bridge to accept MSI with address 0xFEEx_xxxx from south-bridge */ - set_nbcfg_enable_bits_8(nb_dev, 0x4E, (u8)(~0xFF), 0x05); - /* Reg94h[4:0] = 0x0 P drive strength offset 0 - * Reg94h[6:5] = 0x2 P drive strength additive adjust */ - set_nbcfg_enable_bits_8(nb_dev, 0x94, (u8)(~0x80), 0x40); - - /* Reg94h[20:16] = 0x0 N drive strength offset 0 - * Reg94h[22:21] = 0x2 N drive strength additive adjust */ - set_nbcfg_enable_bits_8(nb_dev, 0x96, (u8)(~0x80), 0x40); - - /* Reg80h[4:0] = 0x0 Termination offset - * Reg80h[6:5] = 0x2 Termination additive adjust */ - set_nbcfg_enable_bits_8(nb_dev, 0x80, (u8)(~0x80), 0x40); - - /* Reg80h[14] = 0x1 Enable receiver termination control */ - set_nbcfg_enable_bits_8(nb_dev, 0x81, (u8)(~0xFF), 0x40); - - /* Reg94h[15] = 0x1 Enables HT transmitter advanced features to be turned on - * Reg94h[14] = 0x1 Enable drive strength control */ - set_nbcfg_enable_bits_8(nb_dev, 0x95, (u8)(~0x3F), 0xC4); - - /* Reg94h[31:29] = 0x7 Enables HT transmitter de-emphasis */ - set_nbcfg_enable_bits_8(nb_dev, 0x97, (u8)(~0x1F), 0xE0); - - /*Reg8Ch[10:9] = 0x3 Enables Gfx Debug BAR, - * force this BAR as mem type in rs690_gfx.c */ - set_nbcfg_enable_bits_8(nb_dev, 0x8D, (u8)(~0xFF), 0x03); - -} - -/***************************************** -* Compliant with CIM_33's ATINB_MCIndex_POR_TABLE -*****************************************/ -static void rs690_por_mc_index_init(device_t nb_dev) -{ - set_nbmc_enable_bits(nb_dev, 0x7A, ~0xFFFFFF80, 0x0000005F); - set_nbmc_enable_bits(nb_dev, 0xD8, ~0x00000000, 0x00600060); - set_nbmc_enable_bits(nb_dev, 0xD9, ~0x00000000, 0x00600060); - set_nbmc_enable_bits(nb_dev, 0xE0, ~0x00000000, 0x00000000); - set_nbmc_enable_bits(nb_dev, 0xE1, ~0x00000000, 0x00000000); - set_nbmc_enable_bits(nb_dev, 0xE8, ~0x00000000, 0x003E003E); - set_nbmc_enable_bits(nb_dev, 0xE9, ~0x00000000, 0x003E003E); -} - -/***************************************** -* Compliant with CIM_33's ATINB_MISCIND_POR_TABLE -* Compliant with CIM_33's MISC_INIT_TBL -*****************************************/ -static void rs690_por_misc_index_init(device_t nb_dev) -{ - /* NB_MISC_IND_WR_EN + IOC_PCIE_CNTL - * Block non-snoop DMA request if PMArbDis is set. - * Set BMSetDis */ - set_nbmisc_enable_bits(nb_dev, 0x0B, ~0xFFFF0000, 0x00000180); - set_nbmisc_enable_bits(nb_dev, 0x01, ~0xFFFFFFFF, 0x00000040); - - /* NBCFG (NBMISCIND 0x0): NB_CNTL - - * HIDE_NB_AGP_CAP ([0], default=1)HIDE - * HIDE_P2P_AGP_CAP ([1], default=1)HIDE - * HIDE_NB_GART_BAR ([2], default=1)HIDE - * AGPMODE30 ([4], default=0)DISABLE - * AGP30ENCHANCED ([5], default=0)DISABLE - * HIDE_AGP_CAP ([8], default=1)ENABLE */ - set_nbmisc_enable_bits(nb_dev, 0x00, ~0xFFFF0000, 0x00000506); /* set bit 10 for MSI */ - - /* NBMISCIND:0x6A[16]= 1 SB link can get a full swing - * set_nbmisc_enable_bits(nb_dev, 0x6A, 0ffffffffh, 000010000); - * NBMISCIND:0x6A[17]=1 Set CMGOOD_OVERRIDE. */ - set_nbmisc_enable_bits(nb_dev, 0x6A, ~0xffffffff, 0x00020000); - - /* NBMISIND:0x40 Bit[8]=1 and Bit[10]=1 following bits are required to set in order to allow LVDS or PWM features to work. */ - set_nbmisc_enable_bits(nb_dev, 0x40, ~0xffffffff, 0x00000500); - - /* NBMISIND:0xC Bit[13]=1 Enable GSM mode for C1e or C3 with pop-up. */ - set_nbmisc_enable_bits(nb_dev, 0x0C, ~0xffffffff, 0x00002000); - - /* Set NBMISIND:0x1F[3] to map NB F2 interrupt pin to INTB# */ - set_nbmisc_enable_bits(nb_dev, 0x1F, ~0xffffffff, 0x00000008); - - /* Compliant with CIM_33's MISC_INIT_TBL, except Hide NB_BAR3_PCIE - * Enable access to DEV8 - * Enable setPower message for all ports - */ - set_nbmisc_enable_bits(nb_dev, 0x00, 1 << 6, 1 << 6); - set_nbmisc_enable_bits(nb_dev, 0x0b, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x51, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x53, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x55, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x57, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x59, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x5B, 1 << 20, 1 << 20); - - set_nbmisc_enable_bits(nb_dev, 0x00, 1 << 7, 1 << 7); - set_nbmisc_enable_bits(nb_dev, 0x07, 0x000000f0, 0x30); - /* Disable bus-master trigger event from SB and Enable set_slot_power message to SB */ - set_nbmisc_enable_bits(nb_dev, 0x0B, 0xffffffff, 0x500180); -} - -/***************************************** -* Compliant with CIM_33's ATINB_HTIUNBIND_POR_TABLE -*****************************************/ -static void rs690_por_htiu_index_init(device_t nb_dev) -{ - /* 0xBC: - * Enables GSM mode for C1e or C3 with pop-up - * Prevents AllowLdtStop from being asserted during HT link recovery - * Allows FID cycles to be serviced faster. Needed for RS690 A12. No harm in RS690 A11 */ - set_htiu_enable_bits(nb_dev, 0x05, ~0xffffffff, 0x0BC); - /* 0x4203A202: - * Enables writes to pass in-progress reads - * Enables streaming of CPU writes - * Enables extended write buffer for CPU writes - * Enables additional response buffers - * Enables special reads to pass writes - * Enables decoding of C1e/C3 and FID cycles - * Enables HTIU-display handshake bypass. - * Enables tagging fix */ - set_htiu_enable_bits(nb_dev, 0x06, ~0xFFFFFFFE, 0x4203A202); - - /* Enables byte-write optimization for IOC requests - * Disables delaying STPCLK de-assert during FID sequence. Needed when enhanced UMA arbitration is used. - * Disables upstream system-management delay */ - set_htiu_enable_bits(nb_dev, 0x07, ~0xFFFFFFF9, 0x001); - - /* HTIUNBIND 0x16 [1] = 0x1 Enable crc decoding fix */ - set_htiu_enable_bits(nb_dev, 0x16, ~0xFFFFFFFF, 0x2); -} - -/***************************************** -* Compliant with CIM_33's ATINB_POR_INIT_JMPDI -* Configure RS690 registers to power-on default RPR. -* POR: Power On Reset -* RPR: Register Programming Requirements -*****************************************/ -static void rs690_por_init(device_t nb_dev) -{ - printk(BIOS_INFO, "rs690_por_init\n"); - /* ATINB_PCICFG_POR_TABLE, initialize the values for rs690 PCI Config registers */ - rs690_por_pcicfg_init(nb_dev); - - /* ATINB_MCIND_POR_TABLE */ - rs690_por_mc_index_init(nb_dev); - - /* ATINB_MISCIND_POR_TABLE */ - rs690_por_misc_index_init(nb_dev); - - /* ATINB_HTIUNBIND_POR_TABLE */ - rs690_por_htiu_index_init(nb_dev); - - /* ATINB_CLKCFG_PORT_TABLE */ - /* rs690 A11 SB Link full swing? */ -} - -/* enable CFG access to Dev8, which is the SB P2P Bridge */ -static void enable_rs690_dev8(void) -{ - set_nbmisc_enable_bits(PCI_DEV(0, 0, 0), 0x00, 1 << 6, 1 << 6); -} - - - -/* -* Compliant with CIM_33's AtiNBInitEarlyPost (AtiInitNBBeforePCIInit). -*/ -static void rs690_before_pci_init(void) -{ -} - -/* -* The calling sequence is same as CIM. -*/ -static void rs690_early_setup(void) -{ - device_t nb_dev = PCI_DEV(0, 0, 0); - printk(BIOS_INFO, "rs690_early_setup()\n"); - - /*ATINB_PrepareInit */ - get_cpu_rev(); - switch (get_nb_rev(nb_dev)) { /* PCIEMiscInit */ - case 5: - printk(BIOS_INFO, "NB Revision is A11.\n"); - break; - case 6: - printk(BIOS_INFO, "NB Revision is A12.\n"); - break; - case 7: - printk(BIOS_INFO, "NB Revision is A21.\n"); - break; - } - - k8_optimization(); - rs690_por_init(nb_dev); -} diff --git a/src/southbridge/amd/rs690/rs690_gfx.c b/src/southbridge/amd/rs690/rs690_gfx.c deleted file mode 100644 index c55f2bc3d3..0000000000 --- a/src/southbridge/amd/rs690/rs690_gfx.c +++ /dev/null @@ -1,625 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 - */ - -/* - * for rs690 internal graphics device - * device id of internal grphics: - * RS690M/T: 0x791f - * RS690: 0x791e - */ -#include -#include -#include -#include -#include -#include -#include "rs690.h" - -#define CLK_CNTL_INDEX 0x8 -#define CLK_CNTL_DATA 0xC - -#ifdef UNUSED_CODE -static u32 clkind_read(device_t dev, u32 index) -{ - u32 gfx_bar2 = pci_read_config32(dev, 0x18) & ~0xF; - - *(u32*)(gfx_bar2+CLK_CNTL_INDEX) = index & 0x7F; - return *(u32*)(gfx_bar2+CLK_CNTL_DATA); -} -#endif - -static void clkind_write(device_t dev, u32 index, u32 data) -{ - u32 gfx_bar2 = pci_read_config32(dev, 0x18) & ~0xF; - /* printk(BIOS_INFO, "gfx bar 2 %02x\n", gfx_bar2); */ - - *(u32*)(gfx_bar2+CLK_CNTL_INDEX) = index | 1<<7; - *(u32*)(gfx_bar2+CLK_CNTL_DATA) = data; -} - -/* -* pci_dev_read_resources thinks it is a IO type. -* We have to force it to mem type. -*/ -static void rs690_gfx_read_resources(device_t dev) -{ - printk(BIOS_INFO, "rs690_gfx_read_resources.\n"); - - /* The initial value of 0x24 is 0xFFFFFFFF, which is confusing. - Even if we write 0xFFFFFFFF into it, it will be 0xFFF00000, - which tells us it is a memory address base. - */ - pci_write_config32(dev, 0x24, 0x00000000); - - /* Get the normal pci resources of this device */ - pci_dev_read_resources(dev); - compact_resources(dev); -} - -static void internal_gfx_pci_dev_init(struct device *dev) -{ - u16 deviceid, vendorid; - deviceid = pci_read_config16(dev, PCI_DEVICE_ID); - vendorid = pci_read_config16(dev, PCI_VENDOR_ID); - printk(BIOS_INFO, "internal_gfx_pci_dev_init device=%x, vendor=%x.\n", - deviceid, vendorid); - - pci_dev_init(dev); - - /* clk ind */ - clkind_write(dev, 0x08, 0x01); - clkind_write(dev, 0x0C, 0x22); - clkind_write(dev, 0x0F, 0x0); - clkind_write(dev, 0x11, 0x0); - clkind_write(dev, 0x12, 0x0); - clkind_write(dev, 0x14, 0x0); - clkind_write(dev, 0x15, 0x0); - clkind_write(dev, 0x16, 0x0); - clkind_write(dev, 0x17, 0x0); - clkind_write(dev, 0x18, 0x0); - clkind_write(dev, 0x19, 0x0); - clkind_write(dev, 0x1A, 0x0); - clkind_write(dev, 0x1B, 0x0); - clkind_write(dev, 0x1C, 0x0); - clkind_write(dev, 0x1D, 0x0); - clkind_write(dev, 0x1E, 0x0); - clkind_write(dev, 0x26, 0x0); - clkind_write(dev, 0x27, 0x0); - clkind_write(dev, 0x28, 0x0); - clkind_write(dev, 0x5C, 0x0); -} - - -/* -* Set registers in RS690 and CPU to enable the internal GFX. -* Please refer to CIM source code and BKDG. -*/ -static void rs690_internal_gfx_enable(device_t dev) -{ - u32 l_dword; - int i; - device_t k8_f0 = 0, k8_f2 = 0; - device_t nb_dev = dev_find_slot(0, 0); - - printk(BIOS_INFO, "rs690_internal_gfx_enable dev=0x%p, nb_dev=0x%p.\n", dev, - nb_dev); - - /* set APERTURE_SIZE, 128M. */ - l_dword = pci_read_config32(nb_dev, 0x8c); - printk(BIOS_INFO, "nb_dev, 0x8c=0x%x\n", l_dword); - l_dword &= 0xffffff8f; - pci_write_config32(nb_dev, 0x8c, l_dword); - - /* set TOM */ - rs690_set_tom(nb_dev); - - /* LPC DMA Deadlock workaround? */ - k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); - l_dword = pci_read_config32(k8_f0, 0x68); - l_dword &= ~(1 << 22); - l_dword |= (1 << 21); - pci_write_config32(k8_f0, 0x68, l_dword); - - /* Enable 64bit mode. */ - set_nbmc_enable_bits(nb_dev, 0x5f, 0, 1 << 9); - set_nbmc_enable_bits(nb_dev, 0xb0, 0, 1 << 8); - - /* 64bit Latency. */ - set_nbmc_enable_bits(nb_dev, 0x5f, 0x7c00, 0x800); - - /* UMA dual channel control register. */ - nbmc_write_index(nb_dev, 0x86, 0x3d); - - /* check the setting later!! */ - set_htiu_enable_bits(nb_dev, 0x07, 1 << 7, 0); - - /* UMA mode, powerdown memory PLL. */ - set_nbmc_enable_bits(nb_dev, 0x74, 0, 1 << 31); - - /* Copy CPU DDR Controller to NB MC. */ - /* Why K8_MC_REG80 is special? */ - k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2)); - for (i = 0; i <= (0x80 - 0x40) / 4; i++) { - l_dword = pci_read_config32(k8_f2, 0x40 + i * 4); - nbmc_write_index(nb_dev, 0x63 + i, l_dword); - } - - /* Set K8 MC for UMA, Family F. */ - l_dword = pci_read_config32(k8_f2, 0xa0); - l_dword |= 0x2c; - pci_write_config32(k8_f2, 0xa0, l_dword); - l_dword = pci_read_config32(k8_f2, 0x94); - l_dword &= 0xf0ffffff; - l_dword |= 0x07000000; - pci_write_config32(k8_f2, 0x94, l_dword); - - /* set FB size and location. */ - nbmc_write_index(nb_dev, 0x1b, 0x00); - l_dword = nbmc_read_index(nb_dev, 0x1c); - l_dword &= 0xffff0; - l_dword |= 0x400 << 20; - l_dword |= 0x4; - nbmc_write_index(nb_dev, 0x1c, l_dword); - l_dword = nbmc_read_index(nb_dev, 0x1d); - l_dword &= 0xfffff000; - l_dword |= 0x0400; - nbmc_write_index(nb_dev, 0x1d, l_dword); - nbmc_write_index(nb_dev, 0x100, 0x3fff3800); - - /* Program MC table. */ - set_nbmc_enable_bits(nb_dev, 0x00, 0, 1 << 31); - l_dword = nbmc_read_index(nb_dev, 0x91); - l_dword |= 0x5; - nbmc_write_index(nb_dev, 0x91, l_dword); - set_nbmc_enable_bits(nb_dev, 0xb1, 0, 1 << 6); - set_nbmc_enable_bits(nb_dev, 0xc3, 0, 1); - - /* TODO: the optimization of voltage and frequency */ -} - -static struct pci_operations lops_pci = { - .set_subsystem = pci_dev_set_subsystem, -}; - -static struct device_operations pcie_ops = { - .read_resources = rs690_gfx_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = internal_gfx_pci_dev_init, /* The option ROM initializes the device. rs690_gfx_init, */ - .scan_bus = 0, - .enable = rs690_internal_gfx_enable, - .ops_pci = &lops_pci, -}; - -/* - * The dev id of 690G is 791E, while the id of 690M, 690T is 791F. - * We should list both of them here. - * */ -static const struct pci_driver pcie_driver_690t __pci_driver = { - .ops = &pcie_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_RS690MT_INT_GFX, -}; - -static const struct pci_driver pcie_driver_690 __pci_driver = { - .ops = &pcie_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_RS690_INT_GFX, -}; - -/* step 12 ~ step 14 from rpr */ -static void single_port_configuration(device_t nb_dev, device_t dev) -{ - u8 result, width; - u32 reg32; - struct southbridge_amd_rs690_config *cfg = - (struct southbridge_amd_rs690_config *)nb_dev->chip_info; - - printk(BIOS_INFO, "rs690_gfx_init single_port_configuration.\n"); - - /* step 12 training, releases hold training for GFX port 0 (device 2) */ - set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 4, 0<<4); - PcieReleasePortTraining(nb_dev, dev, 2); - result = PcieTrainPort(nb_dev, dev, 2); - printk(BIOS_INFO, "rs690_gfx_init single_port_configuration step12.\n"); - - /* step 13 Power Down Control */ - /* step 13.1 Enables powering down transmitter and receiver pads along with PLL macros. */ - set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 1 << 0); - - /* step 13.a Link Training was NOT successful */ - if (!result) { - set_nbmisc_enable_bits(nb_dev, 0x8, 0, 0x3 << 4); /* prevent from training. */ - set_nbmisc_enable_bits(nb_dev, 0xc, 0, 0x3 << 2); /* hide the GFX bridge. */ - if (cfg->gfx_tmds) - nbpcie_ind_write_index(nb_dev, 0x65, 0xccf0f0); - else { - nbpcie_ind_write_index(nb_dev, 0x65, 0xffffffff); - set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 3, 1 << 3); - } - } else { /* step 13.b Link Training was successful */ - - reg32 = nbpcie_p_read_index(dev, 0xa2); - width = (reg32 >> 4) & 0x7; - printk(BIOS_DEBUG, "GFX LC_LINK_WIDTH = 0x%x.\n", width); - switch (width) { - case 1: - case 2: - nbpcie_ind_write_index(nb_dev, 0x65, - cfg->gfx_lane_reversal ? 0x7f7f : 0xccfefe); - break; - case 4: - nbpcie_ind_write_index(nb_dev, 0x65, - cfg->gfx_lane_reversal ? 0x3f3f : 0xccfcfc); - break; - case 8: - nbpcie_ind_write_index(nb_dev, 0x65, - cfg->gfx_lane_reversal ? 0x0f0f : 0xccf0f0); - break; - } - } - printk(BIOS_INFO, "rs690_gfx_init single_port_configuration step13.\n"); - - /* step 14 Reset Enumeration Timer, disables the shortening of the enumeration timer */ - set_pcie_enable_bits(dev, 0x70, 1 << 19, 0 << 19); - printk(BIOS_INFO, "rs690_gfx_init single_port_configuration step14.\n"); -} - -/* step 15 ~ step 18 from rpr */ -static void dual_port_configuration(device_t nb_dev, device_t dev) -{ - u8 result, width; - u32 reg32; - struct southbridge_amd_rs690_config *cfg = - (struct southbridge_amd_rs690_config *)nb_dev->chip_info; - - /* step 15: Training for Device 2 */ - set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 4, 0 << 4); - /* Releases hold training for GFX port 0 (device 2) */ - PcieReleasePortTraining(nb_dev, dev, 2); - /* PCIE Link Training Sequence */ - result = PcieTrainPort(nb_dev, dev, 2); - - /* step 16: Power Down Control for Device 2 */ - /* step 16.a Link Training was NOT successful */ - if (!result) { - /* Powers down all lanes for port A */ - nbpcie_ind_write_index(nb_dev, 0x65, 0x0f0f); - } else { /* step 16.b Link Training was successful */ - - reg32 = nbpcie_p_read_index(dev, 0xa2); - width = (reg32 >> 4) & 0x7; - printk(BIOS_DEBUG, "GFX LC_LINK_WIDTH = 0x%x.\n", width); - switch (width) { - case 1: - case 2: - nbpcie_ind_write_index(nb_dev, 0x65, - cfg->gfx_lane_reversal ? 0x0707 : 0x0e0e); - break; - case 4: - nbpcie_ind_write_index(nb_dev, 0x65, - cfg->gfx_lane_reversal ? 0x0303 : 0x0c0c); - break; - } - } - - /* step 17: Training for Device 3 */ - set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 5, 0 << 5); - /* Releases hold training for GFX port 0 (device 3) */ - PcieReleasePortTraining(nb_dev, dev, 3); - /* PCIE Link Training Sequence */ - result = PcieTrainPort(nb_dev, dev, 3); - - /*step 18: Power Down Control for Device 3 */ - /* step 18.a Link Training was NOT successful */ - if (!result) { - /* Powers down all lanes for port B and PLL1 */ - nbpcie_ind_write_index(nb_dev, 0x65, 0xccf0f0); - } else { /* step 18.b Link Training was successful */ - - reg32 = nbpcie_p_read_index(dev, 0xa2); - width = (reg32 >> 4) & 0x7; - printk(BIOS_DEBUG, "GFX LC_LINK_WIDTH = 0x%x.\n", width); - switch (width) { - case 1: - case 2: - nbpcie_ind_write_index(nb_dev, 0x65, - cfg->gfx_lane_reversal ? 0x7070 : 0xe0e0); - break; - case 4: - nbpcie_ind_write_index(nb_dev, 0x65, - cfg->gfx_lane_reversal ? 0x3030 : 0xc0c0); - break; - } - } -} - - -/* For single port GFX configuration Only -* width: -* 000 = x16 -* 001 = x1 -* 010 = x2 -* 011 = x4 -* 100 = x8 -* 101 = x12 (not supported) -* 110 = x16 -*/ -static void dynamic_link_width_control(device_t nb_dev, device_t dev, u8 width) -{ - u32 reg32; - device_t sb_dev; - struct southbridge_amd_rs690_config *cfg = - (struct southbridge_amd_rs690_config *)nb_dev->chip_info; - - /* step 5.9.1.1 */ - reg32 = nbpcie_p_read_index(dev, 0xa2); - - /* step 5.9.1.2 */ - set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 1 << 0); - /* step 5.9.1.3 */ - set_pcie_enable_bits(dev, 0xa2, 3 << 0, width << 0); - /* step 5.9.1.4 */ - set_pcie_enable_bits(dev, 0xa2, 1 << 8, 1 << 8); - /* step 5.9.2.4 */ - if (0 == cfg->gfx_reconfiguration) - set_pcie_enable_bits(dev, 0xa2, 1 << 11, 1 << 11); - - /* step 5.9.1.5 */ - do { - reg32 = nbpcie_p_read_index(dev, 0xa2); - } - while (reg32 & 0x100); - - /* step 5.9.1.6 */ - sb_dev = dev_find_slot(0, PCI_DEVFN(8, 0)); - do { - reg32 = pci_ext_read_config32(nb_dev, sb_dev, - PCIE_VC0_RESOURCE_STATUS); - } while (reg32 & VC_NEGOTIATION_PENDING); - - /* step 5.9.1.7 */ - reg32 = nbpcie_p_read_index(dev, 0xa2); - if (((reg32 & 0x70) >> 4) != 0x6) { - /* the unused lanes should be powered off. */ - } - - /* step 5.9.1.8 */ - set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 0 << 0); -} - -/* -* GFX Core initialization, dev2, dev3 -*/ -void rs690_gfx_init(device_t nb_dev, device_t dev, u32 port) -{ - u16 reg16; - struct southbridge_amd_rs690_config *cfg = - (struct southbridge_amd_rs690_config *)nb_dev->chip_info; - - printk(BIOS_INFO, "rs690_gfx_init, nb_dev=0x%p, dev=0x%p, port=0x%x.\n", - nb_dev, dev, port); - - /* step 0, REFCLK_SEL, skip A11 revision */ - set_nbmisc_enable_bits(nb_dev, 0x6a, 1 << 9, - cfg->gfx_dev2_dev3 ? 1 << 9 : 0 << 9); - printk(BIOS_INFO, "rs690_gfx_init step0.\n"); - - /* step 1, lane reversal (only need if CMOS option is enabled) */ - if (cfg->gfx_lane_reversal) { - set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); - if (cfg->gfx_dual_slot) - set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 3, 1 << 3); - } - printk(BIOS_INFO, "rs690_gfx_init step1.\n"); - - /* step 1.1, dual-slot gfx configuration (only need if CMOS option is enabled) */ - /* AMD calls the configuration CrossFire */ - if (cfg->gfx_dual_slot) - set_nbmisc_enable_bits(nb_dev, 0x0, 0xf << 8, 5 << 8); - printk(BIOS_INFO, "rs690_gfx_init step2.\n"); - - /* step 2, TMDS, (only need if CMOS option is enabled) */ - if (cfg->gfx_tmds) { - } - - /* step 3, GFX overclocking, (only need if CMOS option is enabled) */ - /* skip */ - - /* step 4, reset the GFX link */ - /* step 4.1 asserts both calibration reset and global reset */ - set_nbmisc_enable_bits(nb_dev, 0x8, 0x3 << 14, 0x3 << 14); - - /* step 4.2 de-asserts calibration reset */ - set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 14, 0 << 14); - - /* step 4.3 wait for at least 200us */ - udelay(200); - - /* step 4.4 de-asserts global reset */ - set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 15, 0 << 15); - - /* step 4.5 asserts both calibration reset and global reset */ - /* a weird step in RPR, don't do that */ - /* set_nbmisc_enable_bits(nb_dev, 0x8, 0x3 << 14, 0x3 << 14); */ - - /* step 4.6 bring external GFX device out of reset, wait for 1ms */ - mdelay(1); - printk(BIOS_INFO, "rs690_gfx_init step4.\n"); - - /* step 5 program PCIE memory mapped configuration space */ - /* done by enable_pci_bar3() before */ - - /* step 6 SBIOS compile flags */ - if (cfg->gfx_tmds) { - /* step 6.2.2 Clock-Muxing Control */ - /* step 6.2.2.1 */ - set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 16, 1 << 16); - - /* step 6.2.2.2 */ - set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 8, 1 << 8); - set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 10, 1 << 10); - - /* step 6.2.2.3 */ - set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 26, 1 << 26); - - /* step 6.2.3 Lane-Muxing Control */ - /* step 6.2.3.1 */ - set_nbmisc_enable_bits(nb_dev, 0x37, 0x3 << 8, 0x2 << 8); - - /* step 6.2.4 Received Data Control */ - /* step 6.2.4.1 */ - set_pcie_enable_bits(nb_dev, 0x40, 0x3 << 16, 0x2 << 16); - - /* step 6.2.4.2 */ - set_pcie_enable_bits(nb_dev, 0x40, 0x3 << 18, 0x3 << 18); - - /* step 6.2.4.3 */ - set_pcie_enable_bits(nb_dev, 0x40, 0x3 << 20, 0x0 << 20); - - /* step 6.2.4.4 */ - set_pcie_enable_bits(nb_dev, 0x40, 0x3 << 22, 0x1 << 22); - - /* step 6.2.5 PLL Power Down Control */ - /* step 6.2.5.1 */ - set_nbmisc_enable_bits(nb_dev, 0x35, 0x3 << 6, 0x0 << 6); - - /* step 6.2.6 Driving Strength Control */ - /* step 6.2.6.1 */ - set_nbmisc_enable_bits(nb_dev, 0x34, 0x1 << 24, 0x0 << 24); - - /* step 6.2.6.2 */ - set_nbmisc_enable_bits(nb_dev, 0x35, 0x3 << 2, 0x3 << 2); - } - - printk(BIOS_INFO, "rs690_gfx_init step6.\n"); - - /* step 7 compliance state, (only need if CMOS option is enabled) */ - /* the compliance stete is just for test. refer to 4.2.5.2 of PCIe specification */ - if (cfg->gfx_compliance) { - /* force compliance */ - set_nbmisc_enable_bits(nb_dev, 0x32, 1 << 6, 1 << 6); - /* release hold training for device 2. GFX initialization is done. */ - set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 4, 0 << 4); - dynamic_link_width_control(nb_dev, dev, cfg->gfx_link_width); - printk(BIOS_INFO, "rs690_gfx_init step7.\n"); - return; - } - - /* step 8 common initialization */ - /* step 8.1 sets RCB timeout to be 25ms */ - set_pcie_enable_bits(dev, 0x70, 7 << 16, 3 << 16); - printk(BIOS_INFO, "rs690_gfx_init step8.1.\n"); - - /* step 8.2 disables slave ordering logic */ - set_pcie_enable_bits(nb_dev, 0x20, 1 << 8, 1 << 8); - printk(BIOS_INFO, "rs690_gfx_init step8.2.\n"); - - /* step 8.3 sets DMA payload size to 64 bytes */ - set_pcie_enable_bits(nb_dev, 0x10, 7 << 10, 4 << 10); - printk(BIOS_INFO, "rs690_gfx_init step8.3.\n"); - - /* step 8.4 if the LTSSM could not see all 8 TS1 during Polling Active, it can still - * time out and go back to Detect Idle.*/ - set_pcie_enable_bits(dev, 0x02, 1 << 14, 1 << 14); - printk(BIOS_INFO, "rs690_gfx_init step8.4.\n"); - - /* step 8.5 shortens the enumeration timer */ - set_pcie_enable_bits(dev, 0x70, 1 << 19, 1 << 19); - printk(BIOS_INFO, "rs690_gfx_init step8.5.\n"); - - /* step 8.6 blocks DMA traffic during C3 state */ - set_pcie_enable_bits(dev, 0x10, 1 << 0, 0 << 0); - printk(BIOS_INFO, "rs690_gfx_init step8.6.\n"); - - /* step 8.7 Do not gate the electrical idle form the PHY - * step 8.8 Enables the escape from L1L23 */ - set_pcie_enable_bits(dev, 0xa0, 3 << 30, 3 << 30); - printk(BIOS_INFO, "rs690_gfx_init step8.8.\n"); - - /* step 8.9 Setting this register to 0x1 will workaround a PCI Compliance failure reported by Vista DTM. - * SLOT_IMPLEMENTED@PCIE_CAP */ - reg16 = pci_read_config16(dev, 0x5a); - reg16 |= 0x100; - pci_write_config16(dev, 0x5a, reg16); - printk(BIOS_INFO, "rs690_gfx_init step8.9.\n"); - - /* step 8.10 Setting this register to 0x1 will hide the Advanced Error Rporting Capabilities in the PCIE Brider. - * This will workaround several failures reported by the PCI Compliance test under Vista DTM. */ - set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 31, 0 << 31); - printk(BIOS_INFO, "rs690_gfx_init step8.10.\n"); - - /* step 8.11 Sets REGS_DLP_IGNORE_IN_L1_EN to ignore DLLPs during L1 so that txclk can be turned off. */ - set_pcie_enable_bits(nb_dev, 0x02, 1 << 0, 1 << 0); - printk(BIOS_INFO, "rs690_gfx_init step8.11.\n"); - - /* step 8.12 Sets REGS_LC_DONT_GO_TO_L0S_IF_L1_ARMED to prevent lc to go to from L0 to Rcv_L0s if L1 is armed. */ - set_pcie_enable_bits(nb_dev, 0x02, 1 << 6, 1 << 6); - printk(BIOS_INFO, "rs690_gfx_init step8.12.\n"); - - /* step 8.13 Sets CMGOOD_OVERRIDE. */ - set_nbmisc_enable_bits(nb_dev, 0x6a, 1 << 17, 1 << 17); - printk(BIOS_INFO, "rs690_gfx_init step8.13.\n"); - - /* step 9 Enable TLP Flushing, for non-AMD GFX devices and Hot-Plug devices only. */ - /* skip */ - - /* step 10 Optional Features, only needed if CMOS option is enabled. */ - /* step 10.a: L0s */ - /* enabling L0s in the RS690 GFX port(s) */ - set_pcie_enable_bits(nb_dev, 0xF9, 3 << 13, 2 << 13); - set_pcie_enable_bits(dev, 0xA0, 0xf << 8, 8 << 8); - reg16 = pci_read_config16(dev, 0x68); - reg16 |= 1 << 0; - /* L0s is intended as a power saving state */ - /* pci_write_config16(dev, 0x68, reg16); */ - - /* enabling L0s in the External GFX Device(s) */ - - /* step 10.b: active state power management (ASPM L1) */ - /* TO DO */ - - /* step 10.c: turning off PLL During L1/L23 */ - set_pcie_enable_bits(nb_dev, 0x40, 1 << 3, 1 << 3); - set_pcie_enable_bits(nb_dev, 0x40, 1 << 9, 1 << 9); - - /* step 10.d: TXCLK clock gating */ - set_nbmisc_enable_bits(nb_dev, 0x7, 3, 3); - set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 22, 1 << 22); - set_pcie_enable_bits(nb_dev, 0x11, 0xf << 4, 0xc << 4); - - /* step 10.e: LCLK clock gating, done in rs690_config_misc_clk() */ - - /* step 11 Poll GPIO to determine whether it is single-port or dual-port configuration. - * While details will be added later in the document, for now assue the single-port configuration. */ - /* skip */ - - /* Single-port/Dual-port configureation. */ - switch (cfg->gfx_dual_slot) { - case 0: - single_port_configuration(nb_dev, dev); - break; - case 1: - dual_port_configuration(nb_dev, dev); - break; - default: - printk(BIOS_INFO, "Incorrect configuration of external gfx slot.\n"); - break; - } -} diff --git a/src/southbridge/amd/rs690/rs690_ht.c b/src/southbridge/amd/rs690/rs690_ht.c deleted file mode 100644 index 26824b5322..0000000000 --- a/src/southbridge/amd/rs690/rs690_ht.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 -#include -#include -#include -#include -#include "rs690.h" - -/* for UMA internal graphics */ -void avoid_lpc_dma_deadlock(device_t nb_dev, device_t sb_dev) -{ - device_t k8_f0; - u8 reg; - - k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); - set_nbcfg_enable_bits(k8_f0, 0x68, 3 << 21, 1 << 21); - - reg = nbpcie_p_read_index(sb_dev, 0x10); - reg |= 0x100; /* bit9=1 */ - nbpcie_p_write_index(sb_dev, 0x10, reg); - - reg = nbpcie_p_read_index(nb_dev, 0x10); - reg |= 0x100; /* bit9=1 */ - nbpcie_p_write_index(nb_dev, 0x10, reg); - - /* Enable NP protocol over PCIE for memory-mapped writes targeting LPC - * Set this bit to avoid a deadlock condition. */ - reg = htiu_read_index(nb_dev, 0x6); - reg |= 0x1000000; /* bit26 */ - htiu_write_index(nb_dev, 0x6, reg); -} - -static void pcie_init(struct device *dev) -{ - /* Enable pci error detecting */ - u32 dword; - - printk(BIOS_INFO, "pcie_init in rs690_ht.c\n"); - - /* System error enable */ - dword = pci_read_config32(dev, 0x04); - dword |= (1 << 8); /* System error enable */ - dword |= (1 << 30); /* Clear possible errors */ - pci_write_config32(dev, 0x04, dword); - - /* - * 1 is APIC enable - * 18 is enable nb to accept A4 interrupt request from SB. - */ - dword = pci_read_config32(dev, 0x4C); - dword |= 1 << 1 | 1 << 18; /* Clear possible errors */ - pci_write_config32(dev, 0x4C, dword); -} - -static struct pci_operations lops_pci = { - .set_subsystem = pci_dev_set_subsystem, -}; - -static struct device_operations ht_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = pcie_init, - .scan_bus = 0, - .ops_pci = &lops_pci, -}; - -static const struct pci_driver ht_driver __pci_driver = { - .ops = &ht_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_RS690_HT, -}; diff --git a/src/southbridge/amd/rs690/rs690_pcie.c b/src/southbridge/amd/rs690/rs690_pcie.c deleted file mode 100644 index f02e0d73b4..0000000000 --- a/src/southbridge/amd/rs690/rs690_pcie.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 -#include -#include -#include -#include -#include -#include "rs690.h" - -/*------------------------------------------------ -* Global variable -------------------------------------------------*/ -PCIE_CFG AtiPcieCfg = { - PCIE_ENABLE_STATIC_DEV_REMAP, /* Config */ - 0, /* ResetReleaseDelay */ - 0, /* Gfx0Width */ - 0, /* Gfx1Width */ - 0, /* GfxPayload */ - 0, /* GppPayload */ - 0, /* PortDetect, filled by GppSbInit */ - 0, /* PortHp */ - 0, /* DbgConfig */ - 0, /* DbgConfig2 */ - 0, /* GfxLx */ - 0, /* GppLx */ - 0, /* NBSBLx */ - 0, /* PortSlotInit */ - 0, /* Gfx0Pwr */ - 0, /* Gfx1Pwr */ - 0 /* GppPwr */ -}; - -static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port); -static void ValidatePortEn(device_t nb_dev); - -static void ValidatePortEn(device_t nb_dev) -{ -} - - -/***************************************************************** -* Compliant with CIM_33's PCIEPowerOffGppPorts -* Power off unused GPP lines -*****************************************************************/ -static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port) -{ - u32 reg; - u16 state_save; - struct southbridge_amd_rs690_config *cfg = - (struct southbridge_amd_rs690_config *)nb_dev->chip_info; - u8 state = cfg->port_enable; - - if (!(AtiPcieCfg.Config & PCIE_DISABLE_HIDE_UNUSED_PORTS)) - state &= AtiPcieCfg.PortDetect; - state = ~state; - state &= (1 << 4) + (1 << 5) + (1 << 6) + (1 << 7); - state_save = state << 17; - state &= !(AtiPcieCfg.PortHp); - reg = nbmisc_read_index(nb_dev, 0x0c); - reg |= state; - nbmisc_write_index(nb_dev, 0x0c, reg); - - reg = nbmisc_read_index(nb_dev, 0x08); - reg |= state_save; - nbmisc_write_index(nb_dev, 0x08, reg); - - if ((AtiPcieCfg.Config & PCIE_OFF_UNUSED_GPP_LANES) - && !(AtiPcieCfg. - Config & (PCIE_DISABLE_HIDE_UNUSED_PORTS + - PCIE_GFX_COMPLIANCE))) { - } - - if (!cfg->gfx_tmds){ - /* step 3 Power Down Control for Southbridge */ - reg = nbpcie_p_read_index(dev, 0xa2); - - switch ((reg >> 4) & 0x7) { /* get bit 4-6, LC_LINK_WIDTH_RD */ - case 1: - nbpcie_ind_write_index(nb_dev, 0x65, 0x0e0e); - break; - case 2: - nbpcie_ind_write_index(nb_dev, 0x65, 0x0c0c); - break; - default: - break; - } - } -} - -#ifdef UNUSED_CODE -static void pcie_init(struct device *dev) -{ - /* Enable pci error detecting */ - u32 dword; - - printk(BIOS_DEBUG, "pcie_init in rs690_pcie.c\n"); - - /* System error enable */ - dword = pci_read_config32(dev, 0x04); - dword |= (1 << 8); /* System error enable */ - dword |= (1 << 30); /* Clear possible errors */ - pci_write_config32(dev, 0x04, dword); -} -#endif - -/********************************************************************** -**********************************************************************/ -static void switching_gpp_configurations(device_t nb_dev, device_t sb_dev) -{ - u32 reg; - struct southbridge_amd_rs690_config *cfg = - (struct southbridge_amd_rs690_config *)nb_dev->chip_info; - - /* enables GPP reconfiguration */ - reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7); - reg |= - (RECONFIG_GPPSB_EN + RECONFIG_GPPSB_LINK_CONFIG + - RECONFIG_GPPSB_ATOMIC_RESET); - nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg); - - /* sets desired GPPSB configurations, bit4-7 */ - reg = nbmisc_read_index(nb_dev, 0x67); - reg &= 0xffffff0f; /* clean */ - reg |= cfg->gpp_configuration << 4; - nbmisc_write_index(nb_dev, 0x67, reg); - - /* read bit14 and write back its inverst value */ - reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7); - reg ^= RECONFIG_GPPSB_GPPSB; - nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg); - - /* delay 1ms */ - mdelay(1); - - /* waits until SB has trained to L0, poll for bit0-5 = 0x10 */ - do { - reg = nbpcie_p_read_index(sb_dev, PCIE_LC_STATE0); - reg &= 0x3f; /* remain LSB [5:0] bits */ - } while (LC_STATE_RECONFIG_GPPSB != reg); - - /* ensures that virtual channel negotiation is completed. poll for bit1 = 0 */ - do { - reg = - pci_ext_read_config32(nb_dev, sb_dev, - PCIE_VC0_RESOURCE_STATUS); - } while (reg & VC_NEGOTIATION_PENDING); -} - -/***************************************************************** -* The rs690 uses NBCONFIG:0x1c (BAR3) to map the PCIE Extended Configuration -* Space to a 256MB range within the first 4GB of addressable memory. -*****************************************************************/ -void enable_pcie_bar3(device_t nb_dev) -{ - printk(BIOS_DEBUG, "enable_pcie_bar3()\n"); - set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 1 << 30); /* Enables writes to the BAR3 register. */ - set_nbcfg_enable_bits(nb_dev, 0x84, 7 << 16, 0 << 16); - - pci_write_config32(nb_dev, 0x1C, EXT_CONF_BASE_ADDRESS); /* PCIEMiscInit */ - pci_write_config32(nb_dev, 0x20, 0x00000000); - set_htiu_enable_bits(nb_dev, 0x32, 1 << 28, 1 << 28); /* PCIEMiscInit */ - ProgK8TempMmioBase(1, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS); -} - -/***************************************************************** -* We should disable bar3 when we want to exit rs690_enable, because bar3 will be -* remapped in set_resource later. -*****************************************************************/ -void disable_pcie_bar3(device_t nb_dev) -{ - printk(BIOS_DEBUG, "disable_pcie_bar3()\n"); - set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 0 << 30); /* Disable writes to the BAR3. */ - pci_write_config32(nb_dev, 0x1C, 0); /* clear BAR3 address */ - ProgK8TempMmioBase(0, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS); -} - -/***************************************** -* Compliant with CIM_33's PCIEGPPInit -* nb_dev: -* root bridge struct -* dev: -* p2p bridge struct -* port: -* p2p bridge number, 4-8 -*****************************************/ -void rs690_gpp_sb_init(device_t nb_dev, device_t dev, u32 port) -{ - u8 reg8; - u16 reg16; - device_t sb_dev; - struct southbridge_amd_rs690_config *cfg = - (struct southbridge_amd_rs690_config *)nb_dev->chip_info; - printk(BIOS_DEBUG, "gpp_sb_init nb_dev=0x%p, dev=0x%p, port=0x%x\n", nb_dev, dev, port); - - /* init GPP core */ - set_pcie_enable_bits(nb_dev, 0x20 | PCIE_CORE_INDEX_GPPSB, 1 << 8, - 1 << 8); - /* PCIE initialization 5.10.2: rpr 2.12*/ - set_pcie_enable_bits(nb_dev, 0x02 | PCIE_CORE_INDEX_GPPSB, 1 << 0, 1 << 0); /* no description in datasheet. */ - - /* init GPPSB port */ - /* Sets RCB timeout to be 100ms by setting bits[18:16] to 3 b101 and shortens the enumeration timer by setting bit[19] to 1*/ - set_pcie_enable_bits(dev, 0x70, 0xF << 16, 0xd << 16); - /* PCIE initialization 5.10.2: rpr 2.4 */ - set_pcie_enable_bits(dev, 0x02, ~0xffffffff, 1 << 14); - /* Do not gate the electrical idle from the PHY and enables the escape from L1L23 */ - set_pcie_enable_bits(dev, 0xA0, ~0xffffffbf, (3 << 30) | (3 << 12) | (3 << 4)); - /* PCIE initialization 5.10.2: rpr 2.13 */ - set_pcie_enable_bits(dev, 0x02, ~0xffffffff, 1 << 6); - - /* SLOT_IMPLEMENTED in pcieConfig space */ - reg8 = pci_read_config8(dev, 0x5b); - reg8 |= 1 << 0; - pci_write_config8(dev, 0x5b, reg8); - - reg16 = pci_read_config16(dev, 0x5a); - reg16 |= 0x100; - pci_write_config16(dev, 0x5a, reg16); - nbmisc_write_index(nb_dev, 0x34, 0); - - /* check compliance rpr step 2.1*/ - if (AtiPcieCfg.Config & PCIE_GPP_COMPLIANCE) { - u32 tmp; - tmp = nbmisc_read_index(nb_dev, 0x67); - tmp |= 1 << 3; - nbmisc_write_index(nb_dev, 0x67, tmp); - } - - /* step 5: dynamic slave CPL buffer allocation */ - set_pcie_enable_bits(nb_dev, 0x20 | PCIE_CORE_INDEX_GPPSB, 1 << 11, 1 << 11); - - /* step 5a: Training for GPP devices */ - /* init GPP */ - switch (port) { - case 4: /* GPP */ - case 5: - case 6: - case 7: - /* Blocks DMA traffic during C3 state */ - set_pcie_enable_bits(dev, 0x10, 1 << 0, 0 << 0); - /* Enabels TLP flushing */ - set_pcie_enable_bits(dev, 0x20, 1 << 19, 0 << 19); - - /* check port enable */ - if (cfg->port_enable & (1 << port)) { - PcieReleasePortTraining(nb_dev, dev, port); - if (!(AtiPcieCfg.Config & PCIE_GPP_COMPLIANCE)) { - u8 res = PcieTrainPort(nb_dev, dev, port); - printk(BIOS_DEBUG, "PcieTrainPort port=0x%x result=%d\n", port, res); - if (res) { - AtiPcieCfg.PortDetect |= 1 << port; - } - } - } - break; - case 8: /* SB */ - break; - } - PciePowerOffGppPorts(nb_dev, dev, port); - - /* step 5b: GFX devices in a GPP slot */ - - /* step 6a: VCI */ - sb_dev = dev_find_slot(0, PCI_DEVFN(8, 0)); - if (port == 8) { - /* The code below between #if and #endif causes a hang on HDA init. - * So we skip it. */ -#if 0 - /* Clear bits 7:1 */ - pci_ext_write_config32(nb_dev, sb_dev, 0x114, 0x3f << 1, 0 << 1); - /* Maps Traffic Class 1-7 to VC1 */ - pci_ext_write_config32(nb_dev, sb_dev, 0x120, 0x7f << 1, 0x7f << 1); - /* Assigns VC ID to 1 */ - pci_ext_write_config32(nb_dev, sb_dev, 0x120, 7 << 24, 1 << 24); - /* Enables VC1 */ - pci_ext_write_config32(nb_dev, sb_dev, 0x120, 1 << 31, 1 << 31); - - do { - reg16 = pci_ext_read_config32(nb_dev, sb_dev, 0x124); - reg16 &= 0x2; - } while (reg16); /*bit[1] = 0 means VC1 flow control initialization is successful */ -#endif - } - - /* step 6b: L0s for the southbridge link */ - /* To enalbe L0s in the southbridage*/ - - /* step 6c: L0s for the GPP link(s) */ - /* To eable L0s in the RS690 for the GPP port(s) */ - set_pcie_enable_bits(nb_dev, 0xf9, 3 << 13, 2 << 13); - set_pcie_enable_bits(dev, 0xa0, 0xf << 8, 0x9 << 8); - reg16 = pci_read_config16(dev, 0x68); - reg16 |= 1 << 0; - pci_write_config16(dev, 0x68, reg16); - - /* step 6d: ASPM L1 for the southbridge link */ - /* To enalbe L1s in the southbridage*/ - - /* step 6e: ASPM L1 for GPP link(s) */; - set_pcie_enable_bits(nb_dev, 0xf9, 3 << 13, 2 << 13); - set_pcie_enable_bits(dev, 0xa0, 3 << 12, 3 << 12); - set_pcie_enable_bits(dev, 0xa0, 0xf << 4, 3 << 4); - reg16 = pci_read_config16(dev, 0x68); - reg16 &= ~0xff; - reg16 |= 1 << 1; - pci_write_config16(dev, 0x68, reg16); - - /* step 6f: Turning off PLL during L1/L23 */ - set_pcie_enable_bits(nb_dev, 0x40, 1 << 3, 1 << 3); - set_pcie_enable_bits(nb_dev, 0x40, 1 << 9, 1 << 9); - - /* step 6g: TXCLK clock gating */ - set_nbmisc_enable_bits(nb_dev, 0x7, 3 << 4, 3 << 4); - set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 22, 1 << 22); - set_pcie_enable_bits(nb_dev, 0x11, 0xf << 4, 0xc << 4); - - /* step 6h: LCLK clock gating, done in rs690_config_misc_clk() */ -} - -/***************************************** -* Compliant with CIM_33's PCIEConfigureGPPCore -*****************************************/ -void config_gpp_core(device_t nb_dev, device_t sb_dev) -{ - u32 reg; - struct southbridge_amd_rs690_config *cfg = - (struct southbridge_amd_rs690_config *)nb_dev->chip_info; - - reg = nbmisc_read_index(nb_dev, 0x20); - if (AtiPcieCfg.Config & PCIE_ENABLE_STATIC_DEV_REMAP) - reg &= 0xfffffffd; /* set bit1 = 0 */ - else - reg |= 0x2; /* set bit1 = 1 */ - nbmisc_write_index(nb_dev, 0x20, reg); - - reg = nbmisc_read_index(nb_dev, 0x67); /* get STRAP_BIF_LINK_CONFIG_GPPSB at bit 4-7 */ - if (cfg->gpp_configuration != ((reg >> 4) & 0xf)) - switching_gpp_configurations(nb_dev, sb_dev); - ValidatePortEn(nb_dev); -} - -#ifdef UNUSED_CODE -/***************************************** -* Compliant with CIM_33's PCIEMiscClkProg -*****************************************/ -void pcie_config_misc_clk(device_t nb_dev) -{ - u32 reg; - struct bus pbus; /* fake bus for dev0 fun1 */ - - reg = pci_read_config32(nb_dev, 0x4c); - reg |= 1 << 0; - pci_write_config32(nb_dev, 0x4c, reg); - - if (AtiPcieCfg.Config & PCIE_GFX_CLK_GATING) { - /* TXCLK Clock Gating */ - set_nbmisc_enable_bits(nb_dev, 0x07, 3 << 0, 3 << 0); - set_nbmisc_enable_bits(nb_dev, 0x07, 1 << 22, 1 << 22); - set_pcie_enable_bits(nb_dev, 0x11 | PCIE_CORE_INDEX_GFX, (3 << 6) | (~0xf), 3 << 6); - - /* LCLK Clock Gating */ - reg = pci_cf8_conf1.read32(&pbus, 0, 1, 0x94); - reg &= ~(1 << 16); - pci_cf8_conf1.write32(&pbus, 0, 1, 0x94, reg); - } - - if (AtiPcieCfg.Config & PCIE_GPP_CLK_GATING) { - /* TXCLK Clock Gating */ - set_nbmisc_enable_bits(nb_dev, 0x07, 3 << 4, 3 << 4); - set_nbmisc_enable_bits(nb_dev, 0x07, 1 << 22, 1 << 22); - set_pcie_enable_bits(nb_dev, 0x11 | PCIE_CORE_INDEX_GPPSB, (3 << 6) | (~0xf), 3 << 6); - - /* LCLK Clock Gating */ - reg = pci_cf8_conf1.read32(&pbus, 0, 1, 0x94); - reg &= ~(1 << 24); - pci_cf8_conf1.write32(&pbus, 0, 1, 0x94, reg); - } - - reg = pci_read_config32(nb_dev, 0x4c); - reg &= ~(1 << 0); - pci_write_config32(nb_dev, 0x4c, reg); -} -#endif diff --git a/src/southbridge/amd/rs780/Makefile.inc b/src/southbridge/amd/rs780/Makefile.inc index f76e517c82..db425702d6 100644 --- a/src/southbridge/amd/rs780/Makefile.inc +++ b/src/southbridge/amd/rs780/Makefile.inc @@ -1,5 +1,5 @@ driver-y += rs780.c -driver-y += rs780_cmn.c -driver-y += rs780_pcie.c -driver-y += rs780_ht.c -driver-y += rs780_gfx.c +driver-y += cmn.c +driver-y += pcie.c +driver-y += ht.c +driver-y += gfx.c diff --git a/src/southbridge/amd/rs780/cmn.c b/src/southbridge/amd/rs780/cmn.c new file mode 100644 index 0000000000..4bd870bbf2 --- /dev/null +++ b/src/southbridge/amd/rs780/cmn.c @@ -0,0 +1,403 @@ +/* + * 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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rs780.h" + +static u32 nb_read_index(device_t dev, u32 index_reg, u32 index) +{ + pci_write_config32(dev, index_reg, index); + return pci_read_config32(dev, index_reg + 0x4); +} + +static void nb_write_index(device_t dev, u32 index_reg, u32 index, u32 data) +{ + pci_write_config32(dev, index_reg, index); + pci_write_config32(dev, index_reg + 0x4, data); +} + +/* extension registers */ +u32 pci_ext_read_config32(device_t nb_dev, device_t dev, u32 reg) +{ + /*get BAR3 base address for nbcfg0x1c */ + u32 addr = pci_read_config32(nb_dev, 0x1c) & ~0xF; + printk(BIOS_DEBUG, "addr=%x,bus=%x,devfn=%x\n", addr, dev->bus->secondary, + dev->path.pci.devfn); + addr |= dev->bus->secondary << 20 | /* bus num */ + dev->path.pci.devfn << 12 | reg; + return *((u32 *) addr); +} + +void pci_ext_write_config32(device_t nb_dev, device_t dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + + /*get BAR3 base address for nbcfg0x1c */ + u32 addr = pci_read_config32(nb_dev, 0x1c) & ~0xF; + /*printk(BIOS_DEBUG, "write: addr=%x,bus=%x,devfn=%x\n", addr, dev->bus->secondary, + dev->path.pci.devfn);*/ + addr |= dev->bus->secondary << 20 | /* bus num */ + dev->path.pci.devfn << 12 | reg_pos; + + reg = reg_old = *((u32 *) addr); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + *((u32 *) addr) = reg; + } +} + +u32 nbmisc_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBMISC_INDEX, (index)); +} + +void nbmisc_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBMISC_INDEX, ((index) | 0x80), (data)); +} + +u32 nbpcie_p_read_index(device_t dev, u32 index) +{ + return nb_read_index((dev), NBPCIE_INDEX, (index)); +} + +void nbpcie_p_write_index(device_t dev, u32 index, u32 data) +{ + nb_write_index((dev), NBPCIE_INDEX, (index), (data)); +} + +u32 nbpcie_ind_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBPCIE_INDEX, (index)); +} + +void nbpcie_ind_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBPCIE_INDEX, (index), (data)); +} + +u32 htiu_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBHTIU_INDEX, (index)); +} + +void htiu_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBHTIU_INDEX, ((index) | 0x100), (data)); +} + +u32 nbmc_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBMC_INDEX, (index)); +} + +void nbmc_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBMC_INDEX, ((index) | 1 << 9), (data)); +} + +void set_nbcfg_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + reg = reg_old = pci_read_config32(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + pci_write_config32(nb_dev, reg_pos, reg); + } +} + +void set_nbcfg_enable_bits_8(device_t nb_dev, u32 reg_pos, u8 mask, u8 val) +{ + u8 reg_old, reg; + reg = reg_old = pci_read_config8(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + pci_write_config8(nb_dev, reg_pos, reg); + } +} + +void set_nbmc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + reg = reg_old = nbmc_read_index(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + nbmc_write_index(nb_dev, reg_pos, reg); + } +} + +void set_htiu_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + reg = reg_old = htiu_read_index(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + htiu_write_index(nb_dev, reg_pos, reg); + } +} + +void set_nbmisc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + reg = reg_old = nbmisc_read_index(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + nbmisc_write_index(nb_dev, reg_pos, reg); + } +} + +void set_pcie_enable_bits(device_t dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + reg = reg_old = nb_read_index(dev, NBPCIE_INDEX, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + nb_write_index(dev, NBPCIE_INDEX, reg_pos, reg); + } +} + +/*********************************************************** +* To access bar3 we need to program PCI MMIO 7 in K8. +* in_out: +* 1: enable/enter k8 temp mmio base +* 0: disable/restore +***********************************************************/ +void ProgK8TempMmioBase(u8 in_out, u32 pcie_base_add, u32 mmio_base_add) +{ + /* K8 Function1 is address map */ + device_t k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1)); + device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); + + if (in_out) { + u32 dword, sblk; + + /* Get SBLink value (HyperTransport I/O Hub Link ID). */ + dword = pci_read_config32(k8_f0, 0x64); + sblk = (dword >> 8) & 0x3; + + /* Fill MMIO limit/base pair. */ + pci_write_config32(k8_f1, 0xbc, + (((pcie_base_add + 0x10000000 - + 1) >> 8) & 0xffffff00) | 0x80 | (sblk << 4)); + pci_write_config32(k8_f1, 0xb8, (pcie_base_add >> 8) | 0x3); + pci_write_config32(k8_f1, 0xb4, + (((mmio_base_add + 0x10000000 - + 1) >> 8) & 0xffffff00) | (sblk << 4)); + pci_write_config32(k8_f1, 0xb0, (mmio_base_add >> 8) | 0x3); + } else { + pci_write_config32(k8_f1, 0xb8, 0); + pci_write_config32(k8_f1, 0xbc, 0); + pci_write_config32(k8_f1, 0xb0, 0); + pci_write_config32(k8_f1, 0xb4, 0); + } +} + +void PcieReleasePortTraining(device_t nb_dev, device_t dev, u32 port) +{ + switch (port) { + case 2: /* GFX, bit4-5 */ + case 3: + set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG, + 1 << (port + 2), 0 << (port + 2)); + break; + case 4: /* GPPSB, bit20-24 */ + case 5: + case 6: + case 7: + set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG, + 1 << (port + 17), 0 << (port + 17)); + break; + case 9: /* GPP, bit 4,5 of miscind 0x2D */ + case 10: + set_nbmisc_enable_bits(nb_dev, 0x2D, + 1 << (port - 5), 0 << (port - 5)); + break; + } +} + +/******************************************************************************************************** +* Output: +* 0: no device is present. +* 1: device is present and is trained. +********************************************************************************************************/ +u8 PcieTrainPort(device_t nb_dev, device_t dev, u32 port) +{ + u16 count = 5000; + u32 lc_state, reg, current_link_width, lane_mask; + int8_t current, res = 0; + u32 gfx_gpp_sb_sel; + void set_pcie_dereset(void); + void set_pcie_reset(void); + + switch (port) { + case 2 ... 3: + gfx_gpp_sb_sel = PCIE_CORE_INDEX_GFX; + break; + case 4 ... 7: + gfx_gpp_sb_sel = PCIE_CORE_INDEX_GPPSB; + break; + case 9 ... 10: + gfx_gpp_sb_sel = PCIE_CORE_INDEX_GPP; + break; + default: + gfx_gpp_sb_sel = -1; + return 0; + } + + while (count--) { + mdelay(40); + udelay(200); + lc_state = nbpcie_p_read_index(dev, 0xa5); /* lc_state */ + printk(BIOS_DEBUG, "PcieLinkTraining port=%x:lc current state=%x\n", + port, lc_state); + current = lc_state & 0x3f; /* get LC_CURRENT_STATE, bit0-5 */ + + switch (current) { + case 0x00: /* 0x00-0x04 means no device is present */ + case 0x01: + case 0x02: + case 0x03: + case 0x04: + res = 0; + count = 0; + break; + case 0x06: + /* read back current link width [6:4]. */ + current_link_width = (nbpcie_p_read_index(dev, 0xA2) >> 4) & 0x7; + /* 4 means 7:4 and 15:12 + * 3 means 7:2 and 15:10 + * 2 means 7:1 and 15:9 + * egnoring the reversal case + */ + lane_mask = (0xFF << (current_link_width - 2) * 2) & 0xFF; + reg = nbpcie_ind_read_index(nb_dev, 0x65 | gfx_gpp_sb_sel); + reg |= lane_mask << 8 | lane_mask; + reg = 0xE0E0; /* TODO: See the comments in rs780_pcie.c, at about line 145. */ + nbpcie_ind_write_index(nb_dev, 0x65 | gfx_gpp_sb_sel, reg); + printk(BIOS_DEBUG, "link_width=%x, lane_mask=%x", + current_link_width, lane_mask); + set_pcie_reset(); + mdelay(1); + set_pcie_dereset(); + break; + case 0x07: /* device is in compliance state (training sequence is done). Move to train the next device */ + res = 0; + count = 0; + break; + case 0x10: + reg = + pci_ext_read_config32(nb_dev, dev, + PCIE_VC0_RESOURCE_STATUS); + printk(BIOS_DEBUG, "PcieTrainPort reg=0x%x\n", reg); + /* check bit1 */ + if (reg & VC_NEGOTIATION_PENDING) { /* bit1=1 means the link needs to be re-trained. */ + /* set bit8=1, bit0-2=bit4-6 */ + u32 tmp; + reg = + nbpcie_p_read_index(dev, + PCIE_LC_LINK_WIDTH); + tmp = (reg >> 4) && 0x3; /* get bit4-6 */ + reg &= 0xfff8; /* clear bit0-2 */ + reg += tmp; /* merge */ + reg |= 1 << 8; + count++; /* CIM said "keep in loop"? */ + } else { + res = 1; + count = 0; + } + break; + default: /* reset pcie */ + res = 0; + count = 0; /* break loop */ + break; + } + } + return res; +} + +/* +* Compliant with CIM_33's ATINB_SetToms. +* Set Top Of Memory below and above 4G. +*/ +void rs780_set_tom(device_t nb_dev) +{ + extern uint64_t uma_memory_base; + + /* set TOM */ + pci_write_config32(nb_dev, 0x90, uma_memory_base); + //nbmc_write_index(nb_dev, 0x1e, uma_memory_base); +} + +// extract single bit +u32 extractbit(u32 data, int bit_number) +{ + return (data >> bit_number) & 1; +} + +// extract bit field +u32 extractbits(u32 source, int lsb, int msb) +{ + int field_width = msb - lsb + 1; + u32 mask = 0xFFFFFFFF >> (32 - field_width); + return (source >> lsb) & mask; +} + +// return AMD cpuid family +int cpuidFamily(void) +{ + u32 baseFamily, extendedFamily, fms; + + fms = cpuid_eax (1); + baseFamily = extractbits (fms, 8, 11); + extendedFamily = extractbits (fms, 20, 27); + return baseFamily + extendedFamily; +} + + +// return non-zero for AMD family 0Fh processor found +int is_family0Fh(void) +{ + return cpuidFamily() == 0x0F; +} + + +// return non-zero for AMD family 10h processor found +int is_family10h(void) +{ + return cpuidFamily() == 0x10; +} diff --git a/src/southbridge/amd/rs780/early_setup.c b/src/southbridge/amd/rs780/early_setup.c new file mode 100644 index 0000000000..a93ba83172 --- /dev/null +++ b/src/southbridge/amd/rs780/early_setup.c @@ -0,0 +1,675 @@ +/* + * 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 CONFIG_NORTHBRIDGE_AMD_AMDFAM10 +#define CONFIG_NORTHBRIDGE_AMD_AMDFAM10 0 +#endif + +#include "rev.h" + +#define NBHTIU_INDEX 0x94 /* Note: It is different with RS690, whose HTIU index is 0xA8 */ +#define NBMISC_INDEX 0x60 +#define NBMC_INDEX 0xE8 + +static u32 nb_read_index(device_t dev, u32 index_reg, u32 index) +{ + pci_write_config32(dev, index_reg, index); + return pci_read_config32(dev, index_reg + 0x4); +} + +static void nb_write_index(device_t dev, u32 index_reg, u32 index, u32 data) +{ + pci_write_config32(dev, index_reg, index /* | 0x80 */ ); + pci_write_config32(dev, index_reg + 0x4, data); +} + +static u32 nbmisc_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBMISC_INDEX, (index)); +} + +static void nbmisc_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBMISC_INDEX, ((index) | 0x80), (data)); +} + +static u32 htiu_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBHTIU_INDEX, (index)); +} + +static void htiu_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBHTIU_INDEX, ((index) | 0x100), (data)); +} + +static u32 nbmc_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBMC_INDEX, (index)); +} + +static void nbmc_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBMC_INDEX, ((index) | 1 << 9), (data)); +} + +static void set_htiu_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, + u32 val) +{ + u32 reg_old, reg; + reg = reg_old = htiu_read_index(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + htiu_write_index(nb_dev, reg_pos, reg); + } +} + +static void set_nbmisc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, + u32 val) +{ + u32 reg_old, reg; + reg = reg_old = nbmisc_read_index(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + nbmisc_write_index(nb_dev, reg_pos, reg); + } +} + +static void set_nbcfg_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, + u32 val) +{ + u32 reg_old, reg; + reg = reg_old = pci_read_config32(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + pci_write_config32(nb_dev, reg_pos, reg); + } +} +/* family 10 only, for reg > 0xFF */ +#if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 +static void set_fam10_ext_cfg_enable_bits(device_t fam10_dev, u32 reg_pos, u32 mask, + u32 val) +{ + u32 reg_old, reg; + reg = reg_old = Get_NB32(fam10_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + Set_NB32(fam10_dev, reg_pos, reg); + } +} +#else +#define set_fam10_ext_cfg_enable_bits(a, b, c, d) do {} while (0) +#endif + + +static void set_nbcfg_enable_bits_8(device_t nb_dev, u32 reg_pos, u8 mask, + u8 val) +{ + u8 reg_old, reg; + reg = reg_old = pci_read_config8(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + pci_write_config8(nb_dev, reg_pos, reg); + } +} + +static void set_nbmc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, + u32 val) +{ + u32 reg_old, reg; + reg = reg_old = nbmc_read_index(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + nbmc_write_index(nb_dev, reg_pos, reg); + } +} + +static void get_cpu_rev(void) +{ + u32 eax; + + eax = cpuid_eax(1); + printk(BIOS_INFO, "get_cpu_rev EAX=0x%x.\n", eax); + if (eax <= 0xfff) + printk(BIOS_INFO, "CPU Rev is K8_Cx.\n"); + else if (eax <= 0x10fff) + printk(BIOS_INFO, "CPU Rev is K8_Dx.\n"); + else if (eax <= 0x20fff) + printk(BIOS_INFO, "CPU Rev is K8_Ex.\n"); + else if (eax <= 0x40fff) + printk(BIOS_INFO, "CPU Rev is K8_Fx.\n"); + else if (eax == 0x60fb1 || eax == 0x60f81) /*These two IDS are exception, they are G1. */ + printk(BIOS_INFO, "CPU Rev is K8_G1.\n"); + else if (eax <= 0X60FF0) + printk(BIOS_INFO, "CPU Rev is K8_G0.\n"); + else if (eax <= 0x100000) + printk(BIOS_INFO, "CPU Rev is K8_G1.\n"); + else if (eax <= 0x100f00) + printk(BIOS_INFO, "CPU Rev is Fam 10.\n"); + else + printk(BIOS_INFO, "CPU Rev is K8_10.\n"); +} + +static u8 is_famly10(void) +{ + return (cpuid_eax(1) & 0xff00000) != 0; +} + +#if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 /* save some spaces */ +static u8 l3_cache(void) +{ + return (cpuid_edx(0x80000006) & (0x3FFF << 18)) != 0; +} + +static u8 cpu_core_number(void) +{ + return (cpuid_ecx(0x80000008) & 0xFF) + 1; +} +#endif + +static u8 get_nb_rev(device_t nb_dev) +{ + u8 reg; + reg = pci_read_config8(nb_dev, 0x89); /* copy from CIM, can't find in doc */ + switch(reg & 3) + { + case 0x01: + reg = REV_RS780_A12; + break; + case 0x02: + reg = REV_RS780_A13; + break; + default: + reg = REV_RS780_A11; + break; + } + return reg; +} + +/***************************************** + * Init HT link speed/width for rs780 -- k8 link + * 1: Check CPU Family, Family10? + * 2: Get CPU's HT speed and width + * 3: Decide HT mode 1 or 3 by HT Speed. >1GHz: HT3, else HT1 + *****************************************/ +static const u8 rs780_ibias[] = { + /* 1, 3 are reserved. */ + [0x0] = 0x4C, /* 200Mhz HyperTransport 1 only */ + [0x2] = 0x4C, /* 400Mhz HyperTransport 1 only */ + [0x4] = 0xB6, /* 600Mhz HyperTransport 1 only */ + [0x5] = 0x4C, /* 800Mhz HyperTransport 1 only */ + [0x6] = 0x9D, /* 1Ghz HyperTransport 1 only */ + /* HT3 for Family 10 */ + [0x7] = 0xB6, /* 1.2Ghz HyperTransport 3 only */ + [0x8] = 0x2B, /* 1.4Ghz HyperTransport 3 only */ + [0x9] = 0x4C, /* 1.6Ghz HyperTransport 3 only */ + [0xa] = 0x6C, /* 1.8Ghz HyperTransport 3 only */ + [0xb] = 0x9D, /* 2.0Ghz HyperTransport 3 only */ + [0xc] = 0xAD, /* 2.2Ghz HyperTransport 3 only */ + [0xd] = 0xB6, /* 2.4Ghz HyperTransport 3 only */ + [0xe] = 0xC6, /* 2.6Ghz HyperTransport 3 only */ +}; + +static void rs780_htinit(void) +{ + /* + * About HT, it has been done in enumerate_ht_chain(). + */ + device_t cpu_f0, rs780_f0, clk_f1; + u32 reg; + u8 cpu_ht_freq, ibias; + + cpu_f0 = PCI_DEV(0, 0x18, 0); + /************************ + * get cpu's ht freq, in cpu's function 0, offset 0x88 + * bit11-8, specifics the maximum operation frequency of the link's transmitter clock. + * The link frequency field (Frq) is cleared by cold reset. SW can write a nonzero + * value to this reg, and that value takes effect on the next warm reset or + * LDTSTOP_L disconnect sequence. + * please see the table rs780_ibias about the value and its corresponding frequency. + ************************/ + reg = pci_read_config32(cpu_f0, 0x88); + cpu_ht_freq = (reg & 0xf00) >> 8; + printk(BIOS_INFO, "rs780_htinit cpu_ht_freq=%x.\n", cpu_ht_freq); + rs780_f0 = PCI_DEV(0, 0, 0); + //set_nbcfg_enable_bits(rs780_f0, 0xC8, 0x7<<24 | 0x7<<28, 1<<24 | 1<<28); + + clk_f1 = PCI_DEV(0, 0, 1); /* We need to make sure the F1 is accessible. */ + + ibias = rs780_ibias[cpu_ht_freq]; + + /* If HT freq>1GHz, we assume the CPU is fam10, else it is K8. + * Is it appropriate? + * Frequency is 1GHz, i.e. cpu_ht_freq is 6, in most cases. + * So we check 6 only, it would be faster. */ + if ((cpu_ht_freq == 0x6) || (cpu_ht_freq == 0x5) || (cpu_ht_freq == 0x4) || + (cpu_ht_freq == 0x2) || (cpu_ht_freq == 0x0)) { + printk(BIOS_INFO, "rs780_htinit: HT1 mode\n"); + + /* HT1 mode, RPR 8.4.2 */ + /* set IBIAS code */ + set_nbcfg_enable_bits(clk_f1, 0xD8, 0x3FF, ibias); + /* Optimizes chipset HT transmitter drive strength */ + set_htiu_enable_bits(rs780_f0, 0x2A, 0x3, 0x1); + } else if ((cpu_ht_freq > 0x6) && (cpu_ht_freq < 0xf)) { + printk(BIOS_INFO, "rs780_htinit: HT3 mode\n"); + + #if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 /* save some spaces */ + /* HT3 mode, RPR 8.4.3 */ + set_nbcfg_enable_bits(rs780_f0, 0x9c, 0x3 << 16, 0); + + /* set IBIAS code */ + set_nbcfg_enable_bits(clk_f1, 0xD8, 0x3FF, ibias); + /* Optimizes chipset HT transmitter drive strength */ + set_htiu_enable_bits(rs780_f0, 0x2A, 0x3, 0x1); + /* Enables error-retry mode */ + set_nbcfg_enable_bits(rs780_f0, 0x44, 0x1, 0x1); + /* Enables scrambling and Disalbes command throttling */ + set_nbcfg_enable_bits(rs780_f0, 0xac, (1 << 3) | (1 << 14), (1 << 3) | (1 << 14)); + /* Enables transmitter de-emphasis */ + set_nbcfg_enable_bits(rs780_f0, 0xa4, 1 << 31, 1 << 31); + /* Enabels transmitter de-emphasis level */ + /* Sets training 0 time */ + set_nbcfg_enable_bits(rs780_f0, 0xa0, 0x3F, 0x14); + + /* Enables strict TM4 detection */ + set_htiu_enable_bits(rs780_f0, 0x15, 0x1 << 22, 0x1 << 22); + /* Enables proprer DLL reset sequence */ + set_htiu_enable_bits(rs780_f0, 0x16, 0x1 << 10, 0x1 << 10); + + /* HyperTransport 3 Processor register settings to be done in northbridge */ + /* Enables error-retry mode */ + set_fam10_ext_cfg_enable_bits(cpu_f0, 0x130, 1 << 0, 1 << 0); + /* Enables scrambling */ + set_fam10_ext_cfg_enable_bits(cpu_f0, 0x170, 1 << 3, 1 << 3); + /* Enables transmitter de-emphasis + * This depends on the PCB design and the trace */ + /* TODO: */ + /* Disables command throttling */ + set_fam10_ext_cfg_enable_bits(cpu_f0, 0x168, 1 << 10, 1 << 10); + /* Sets Training 0 Time. See T0Time table for encodings */ + set_fam10_ext_cfg_enable_bits(cpu_f0, 0x16C, 0x3F, 0x20); + /* TODO: */ + #endif /* #if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 */ + } +} + +#if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 != 1 /* save some spaces */ +/******************************************************* +* Optimize k8 with UMA. +* See BKDG_NPT_0F guide for details. +* The processor node is addressed by its Node ID on the HT link and can be +* accessed with a device number in the PCI configuration space on Bus0. +* The Node ID 0 is mapped to Device 24 (0x18), the Node ID 1 is mapped +* to Device 25, and so on. +* The processor implements configuration registers in PCI configuration +* space using the following four headers +* Function0: HT technology configuration +* Function1: Address map configuration +* Function2: DRAM and HT technology Trace mode configuration +* Function3: Miscellaneous configuration +*******************************************************/ +static void k8_optimization(void) +{ + device_t k8_f0, k8_f2, k8_f3; + msr_t msr; + + printk(BIOS_INFO, "k8_optimization()\n"); + k8_f0 = PCI_DEV(0, 0x18, 0); + k8_f2 = PCI_DEV(0, 0x18, 2); + k8_f3 = PCI_DEV(0, 0x18, 3); + + /* 8.6.6 K8 Buffer Allocation Settings */ + pci_write_config32(k8_f0, 0x90, 0x01700169); /* CIM NPT_Optimization */ + set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 28, 0 << 28); + set_nbcfg_enable_bits(k8_f0, 0x68, 3 << 26, 3 << 26); + set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 11, 1 << 11); + /* set_nbcfg_enable_bits(k8_f0, 0x84, 1 << 11 | 1 << 13 | 1 << 15, 1 << 11 | 1 << 13 | 1 << 15); */ /* TODO */ + + pci_write_config32(k8_f3, 0x70, 0x51220111); + pci_write_config32(k8_f3, 0x74, 0x50404021); + pci_write_config32(k8_f3, 0x78, 0x08002A00); + if (pci_read_config32(k8_f3, 0xE8) & 0x3<<12) + pci_write_config32(k8_f3, 0x7C, 0x0000211A); /* dual core */ + else + pci_write_config32(k8_f3, 0x7C, 0x0000212B); /* single core */ + set_nbcfg_enable_bits_8(k8_f3, 0xDC, 0xFF, 0x25); + + set_nbcfg_enable_bits(k8_f2, 0xA0, 1 << 5, 1 << 5); + set_nbcfg_enable_bits(k8_f2, 0x94, 0xF << 24, 7 << 24); + set_nbcfg_enable_bits(k8_f2, 0x90, 1 << 10, 0 << 10); + set_nbcfg_enable_bits(k8_f2, 0xA0, 3 << 2, 3 << 2); + set_nbcfg_enable_bits(k8_f2, 0xA0, 1 << 5, 1 << 5); + + msr = rdmsr(0xC001001F); + msr.lo &= ~(1 << 9); + msr.hi &= ~(1 << 4); + wrmsr(0xC001001F, msr); +} +#else +#define k8_optimization() do{}while(0) +#endif /* #if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 != 1 */ + +#if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 /* save some spaces */ +static void fam10_optimization(void) +{ + device_t cpu_f0, cpu_f2, cpu_f3; + u32 val; + + printk(BIOS_INFO, "fam10_optimization()\n"); + + cpu_f0 = PCI_DEV(0, 0x18, 0); + cpu_f2 = PCI_DEV(0, 0x18, 2); + cpu_f3 = PCI_DEV(0, 0x18, 3); + + /* 8.6.4.1 */ + /* Table 8-13 */ + pci_write_config32(cpu_f0, 0x90, 0x808502D0); + /* Table 8-14 */ + pci_write_config32(cpu_f0, 0x94, 0x00000000); + + /* Table 8-15 */ + val = pci_read_config32(cpu_f0, 0x68); + val |= 1 << 24; + pci_write_config32(cpu_f0, 0x68, val); + + /* Table 8-16 */ + val = pci_read_config32(cpu_f0, 0x84); + val &= ~(1 << 12); + pci_write_config32(cpu_f0, 0x84, val); + + /* Table 8-17 */ + val = pci_read_config32(cpu_f2, 0x90); + val &= ~(1 << 10); + pci_write_config32(cpu_f2, 0x90, val); + + /* Table 8-18 */ + pci_write_config32(cpu_f3, 0x6C, 0x60018051); + /* Table 8-19 */ + pci_write_config32(cpu_f3, 0x70, 0x60321151); + /* Table 8-20 */ + pci_write_config32(cpu_f3, 0x74, 0x00980101); + /* Table 8-21 */ + pci_write_config32(cpu_f3, 0x78, 0x00200C14); + /* Table 8-22 */ + pci_write_config32(cpu_f3, 0x7C, 0x00070811); /* TODO: Check if L3 Cache is enabled. */ + + /* Table 8-23 */ + Set_NB32(cpu_f3, 0x140, 0x00D33656); + /* Table 8-24 */ + Set_NB32(cpu_f3, 0x144, 0x00000036); + /* Table 8-25 */ + Set_NB32(cpu_f3, 0x148, 0x8000832A); + /* Table 8-26 */ + Set_NB32(cpu_f3, 0x158, 0); + /* L3 Disabled: L3 Enabled: */ + /* cores: 2 3 4 2 3 4 */ + /* bit8:4 28 26 24 24 20 16 */ + if (!l3_cache()) { + Set_NB32(cpu_f3, 0x1A0, 4 << 12 | (24 + 2*(4-cpu_core_number())) << 4 | 2); + } else { + Set_NB32(cpu_f3, 0x1A0, 4 << 12 | (16 + 4*(4-cpu_core_number())) << 4 | 4); + } +} +#else +#define fam10_optimization() do{}while(0) +#endif /* #if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 */ + +/***************************************** +* rs780_por_pcicfg_init() +*****************************************/ +static void rs780_por_pcicfg_init(device_t nb_dev) +{ + /* enable PCI Memory Access */ + set_nbcfg_enable_bits_8(nb_dev, 0x04, (u8)(~0xFD), 0x02); + /* Set RCRB Enable */ + set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xFF), 0x1); + /* allow decode of 640k-1MB */ + set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xEF), 0x10); + /* Enable PM2_CNTL(BAR2) IO mapped cfg write access to be broadcast to both NB and SB */ + set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xFF), 0x4); + /* Power Management Register Enable */ + set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xFF), 0x80); + + /* Reg4Ch[1]=1 (APIC_ENABLE) force cpu request with address 0xFECx_xxxx to south-bridge + * Reg4Ch[6]=1 (BMMsgEn) enable BM_Set message generation + * BMMsgEn */ + set_nbcfg_enable_bits_8(nb_dev, 0x4C, (u8)(~0x00), 0x42 | 1); + + /* Reg4Ch[16]=1 (WakeC2En) enable Wake_from_C2 message generation. + * Reg4Ch[18]=1 (P4IntEnable) Enable north-bridge to accept MSI with address 0xFEEx_xxxx from south-bridge */ + set_nbcfg_enable_bits_8(nb_dev, 0x4E, (u8)(~0xFF), 0x05); + /* Reg94h[4:0] = 0x0 P drive strength offset 0 + * Reg94h[6:5] = 0x2 P drive strength additive adjust */ + set_nbcfg_enable_bits_8(nb_dev, 0x94, (u8)(~0x80), 0x40); + + /* Reg94h[20:16] = 0x0 N drive strength offset 0 + * Reg94h[22:21] = 0x2 N drive strength additive adjust */ + set_nbcfg_enable_bits_8(nb_dev, 0x96, (u8)(~0x80), 0x40); + + /* Reg80h[4:0] = 0x0 Termination offset + * Reg80h[6:5] = 0x2 Termination additive adjust */ + set_nbcfg_enable_bits_8(nb_dev, 0x80, (u8)(~0x80), 0x40); + + /* Reg80h[14] = 0x1 Enable receiver termination control */ + set_nbcfg_enable_bits_8(nb_dev, 0x81, (u8)(~0xFF), 0x40); + + /* Reg94h[15] = 0x1 Enables HT transmitter advanced features to be turned on + * Reg94h[14] = 0x1 Enable drive strength control */ + set_nbcfg_enable_bits_8(nb_dev, 0x95, (u8)(~0x3F), 0xC4); + + /* Reg94h[31:29] = 0x7 Enables HT transmitter de-emphasis */ + set_nbcfg_enable_bits_8(nb_dev, 0x97, (u8)(~0x1F), 0xE0); + + /* Reg8Ch[9] enables Gfx Debug BAR programming + * Reg8Ch[10] enables Gfx Debug BAR operation + * Enable programming of the debug bar now, but enable + * operation only after it has been programmed */ + set_nbcfg_enable_bits_8(nb_dev, 0x8D, (u8)(~0xFF), 0x02); +} + +static void rs780_por_mc_index_init(device_t nb_dev) +{ + set_nbmc_enable_bits(nb_dev, 0x7A, ~0xFFFFFF80, 0x0000005F); + set_nbmc_enable_bits(nb_dev, 0xD8, ~0x00000000, 0x00600060); + set_nbmc_enable_bits(nb_dev, 0xD9, ~0x00000000, 0x00600060); + set_nbmc_enable_bits(nb_dev, 0xE0, ~0x00000000, 0x00000000); + set_nbmc_enable_bits(nb_dev, 0xE1, ~0x00000000, 0x00000000); + set_nbmc_enable_bits(nb_dev, 0xE8, ~0x00000000, 0x003E003E); + set_nbmc_enable_bits(nb_dev, 0xE9, ~0x00000000, 0x003E003E); +} + +static void rs780_por_misc_index_init(device_t nb_dev) +{ + /* NB_MISC_IND_WR_EN + IOC_PCIE_CNTL + * Block non-snoop DMA request if PMArbDis is set. + * Set BMSetDis */ + set_nbmisc_enable_bits(nb_dev, 0x0B, ~0xFFFF0000, 0x00000180); + set_nbmisc_enable_bits(nb_dev, 0x01, ~0xFFFFFFFF, 0x00000040); + + /* NBCFG (NBMISCIND 0x0): NB_CNTL - + * HIDE_NB_AGP_CAP ([0], default=1)HIDE + * HIDE_P2P_AGP_CAP ([1], default=1)HIDE + * HIDE_NB_GART_BAR ([2], default=1)HIDE + * AGPMODE30 ([4], default=0)DISABLE + * AGP30ENCHANCED ([5], default=0)DISABLE + * HIDE_AGP_CAP ([8], default=1)ENABLE */ + set_nbmisc_enable_bits(nb_dev, 0x00, ~0xFFFF0000, 0x00000506); /* set bit 10 for MSI */ + + /* NBMISCIND:0x6A[16]= 1 SB link can get a full swing + * set_nbmisc_enable_bits(nb_dev, 0x6A, 0ffffffffh, 000010000); + * NBMISCIND:0x6A[17]=1 Set CMGOOD_OVERRIDE. */ + set_nbmisc_enable_bits(nb_dev, 0x6A, ~0xffffffff, 0x00020000); + + /* NBMISIND:0x40 Bit[8]=1 and Bit[10]=1 following bits are required to set in order to allow LVDS or PWM features to work. */ + set_nbmisc_enable_bits(nb_dev, 0x40, ~0xffffffff, 0x00000500); + + /* NBMISIND:0xC Bit[13]=1 Enable GSM mode for C1e or C3 with pop-up. */ + set_nbmisc_enable_bits(nb_dev, 0x0C, ~0xffffffff, 0x00002000); + + /* Set NBMISIND:0x1F[3] to map NB F2 interrupt pin to INTB# */ + set_nbmisc_enable_bits(nb_dev, 0x1F, ~0xffffffff, 0x00000008); + + /* + * Enable access to DEV8 + * Enable setPower message for all ports + */ + set_nbmisc_enable_bits(nb_dev, 0x00, 1 << 6, 1 << 6); + set_nbmisc_enable_bits(nb_dev, 0x0b, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x51, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x53, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x55, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x57, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x59, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x5B, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x5D, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x5F, 1 << 20, 1 << 20); + + set_nbmisc_enable_bits(nb_dev, 0x00, 1 << 7, 1 << 7); + set_nbmisc_enable_bits(nb_dev, 0x07, 0x000000f0, 0x30); + + set_nbmisc_enable_bits(nb_dev, 0x01, 0xFFFFFFFF, 0x48); + /* Disable bus-master trigger event from SB and Enable set_slot_power message to SB */ + set_nbmisc_enable_bits(nb_dev, 0x0B, 0xffffffff, 0x500180); +} + +/***************************************** +* Some setting is from rpr. Some is from CIMx. +*****************************************/ +static void rs780_por_htiu_index_init(device_t nb_dev) +{ +#if 0 /* get from rpr. */ + set_htiu_enable_bits(nb_dev, 0x1C, 0x1<<17, 0x1<<17); + set_htiu_enable_bits(nb_dev, 0x06, 0x1<<0, 0x0<<0); + set_htiu_enable_bits(nb_dev, 0x06, 0x1<<1, 0x1<<1); + set_htiu_enable_bits(nb_dev, 0x06, 0x1<<9, 0x1<<9); + set_htiu_enable_bits(nb_dev, 0x06, 0x1<<13, 0x1<<13); + set_htiu_enable_bits(nb_dev, 0x06, 0x1<<17, 0x1<<17); + set_htiu_enable_bits(nb_dev, 0x06, 0x3<<15, 0x3<<15); + set_htiu_enable_bits(nb_dev, 0x06, 0x1<<25, 0x1<<25); + set_htiu_enable_bits(nb_dev, 0x06, 0x1<<30, 0x1<<30); + + set_htiu_enable_bits(nb_dev, 0x07, 0x1<<0, 0x1<<0); + set_htiu_enable_bits(nb_dev, 0x07, 0x1<<1, 0x0<<1); + set_htiu_enable_bits(nb_dev, 0x07, 0x1<<2, 0x0<<2); + set_htiu_enable_bits(nb_dev, 0x07, 0x1<<15, 0x1<<15); + + set_htiu_enable_bits(nb_dev, 0x0C, 0x3<<0, 0x1<<0); + set_htiu_enable_bits(nb_dev, 0x0C, 0x3<<2, 0x2<<2); + set_htiu_enable_bits(nb_dev, 0x0C, 0x3<<4, 0x0<<4); + + /* A12 only */ + set_htiu_enable_bits(nb_dev, 0x2D, 0x1<<4, 0x1<<4); + set_htiu_enable_bits(nb_dev, 0x2D, 0x1<<6, 0x1<<6); + set_htiu_enable_bits(nb_dev, 0x05, 0x1<<2, 0x1<<2); + + set_htiu_enable_bits(nb_dev, 0x1E, 0xFFFFFFFF, 0xFFFFFFFF); +#else /* get from CIM. It is more reliable than above. */ + set_htiu_enable_bits(nb_dev, 0x05, (1<<10|1<<9), 1<<10 | 1<<9); + set_htiu_enable_bits(nb_dev, 0x06, ~0xFFFFFFFE, 0x04203A202); + + set_htiu_enable_bits(nb_dev, 0x07, ~0xFFFFFFF9, 0x8001/* | 7 << 8 */); /* fam 10 */ + + set_htiu_enable_bits(nb_dev, 0x15, ~0xFFFFFFFF, 1<<31| 1<<30 | 1<<27); + set_htiu_enable_bits(nb_dev, 0x1C, ~0xFFFFFFFF, 0xFFFE0000); + + set_htiu_enable_bits(nb_dev, 0x4B, (1<<11), 1<<11); + + set_htiu_enable_bits(nb_dev, 0x0C, ~0xFFFFFFC0, 1<<0|1<<3); + + set_htiu_enable_bits(nb_dev, 0x17, (1<<27|1<<1), 0x1<<1); + set_htiu_enable_bits(nb_dev, 0x17, 0x1 << 30, 0x1<<30); + + set_htiu_enable_bits(nb_dev, 0x19, (0xFFFFF+(1<<31)), 0x186A0+(1<<31)); + + set_htiu_enable_bits(nb_dev, 0x16, (0x3F<<10), 0x7<<10); + + set_htiu_enable_bits(nb_dev, 0x23, 0xFFFFFFF, 1<<28); + + set_htiu_enable_bits(nb_dev, 0x1E, 0xFFFFFFFF, 0xFFFFFFFF); +#endif +} + +/***************************************** +* Configure RS780 registers to power-on default RPR. +* POR: Power On Reset +* RPR: Register Programming Requirements +*****************************************/ +static void rs780_por_init(device_t nb_dev) +{ + printk(BIOS_INFO, "rs780_por_init\n"); + /* ATINB_PCICFG_POR_TABLE, initialize the values for rs780 PCI Config registers */ + rs780_por_pcicfg_init(nb_dev); + + /* ATINB_MCIND_POR_TABLE */ + rs780_por_mc_index_init(nb_dev); + + /* ATINB_MISCIND_POR_TABLE */ + rs780_por_misc_index_init(nb_dev); + + /* ATINB_HTIUNBIND_POR_TABLE */ + rs780_por_htiu_index_init(nb_dev); + + /* ATINB_CLKCFG_PORT_TABLE */ + /* rs780 A11 SB Link full swing? */ +} + +/* enable CFG access to Dev8, which is the SB P2P Bridge */ +static void enable_rs780_dev8(void) +{ + set_nbmisc_enable_bits(PCI_DEV(0, 0, 0), 0x00, 1 << 6, 1 << 6); +} + +static void rs780_before_pci_init(void) +{ +} + +static void rs780_early_setup(void) +{ + device_t nb_dev = PCI_DEV(0, 0, 0); + printk(BIOS_INFO, "rs780_early_setup()\n"); + + get_cpu_rev(); + + /* The printk(BIOS_INFO, s) below cause the system unstable. */ + switch (get_nb_rev(nb_dev)) { + case REV_RS780_A11: + /* printk(BIOS_INFO, "NB Revision is A11.\n"); */ + break; + case REV_RS780_A12: + /* printk(BIOS_INFO, "NB Revision is A12.\n"); */ + break; + case REV_RS780_A13: + /* printk(BIOS_INFO, "NB Revision is A13.\n"); */ + break; + } + + if (is_famly10()) + fam10_optimization(); + else + k8_optimization(); + + rs780_por_init(nb_dev); +} diff --git a/src/southbridge/amd/rs780/gfx.c b/src/southbridge/amd/rs780/gfx.c new file mode 100644 index 0000000000..1763c36047 --- /dev/null +++ b/src/southbridge/amd/rs780/gfx.c @@ -0,0 +1,1340 @@ +/* + * 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 + */ + +/* + * for rs780 internal graphics device + * device id of internal grphics: + * RS780: 0x9610 + * RS780C: 0x9611 + * RS780M: 0x9612 + * RS780MC:0x9613 + * RS780E: 0x9615 + * RS785G: 0x9710 - just works, not much tested + */ +#include +#include +#include +#include +#include +#include +#include +#include "rs780.h" +extern int is_dev3_present(void); +void set_pcie_reset(void); +void set_pcie_dereset(void); + +extern uint64_t uma_memory_base, uma_memory_size; + +/* Trust the original resource allocation. Don't do it again. */ +#undef DONT_TRUST_RESOURCE_ALLOCATION +//#define DONT_TRUST_RESOURCE_ALLOCATION + +#define CLK_CNTL_INDEX 0x8 +#define CLK_CNTL_DATA 0xC + +/* The Integrated Info Table. */ +ATOM_INTEGRATED_SYSTEM_INFO_V2 vgainfo; + +#ifdef UNUSED_CODE +static u32 clkind_read(device_t dev, u32 index) +{ + u32 gfx_bar2 = pci_read_config32(dev, 0x18) & ~0xF; + + *(u32*)(gfx_bar2+CLK_CNTL_INDEX) = index & 0x7F; + return *(u32*)(gfx_bar2+CLK_CNTL_DATA); +} +#endif + +static void clkind_write(device_t dev, u32 index, u32 data) +{ + u32 gfx_bar2 = pci_read_config32(dev, 0x18) & ~0xF; + /* printk(BIOS_DEBUG, "gfx bar 2 %02x\n", gfx_bar2); */ + + *(u32*)(gfx_bar2+CLK_CNTL_INDEX) = index | 1<<7; + *(u32*)(gfx_bar2+CLK_CNTL_DATA) = data; +} + +/* +* pci_dev_read_resources thinks it is a IO type. +* We have to force it to mem type. +*/ +static void rs780_gfx_read_resources(device_t dev) +{ + printk(BIOS_DEBUG, "rs780_gfx_read_resources.\n"); + + /* The initial value of 0x24 is 0xFFFFFFFF, which is confusing. + Even if we write 0xFFFFFFFF into it, it will be 0xFFF00000, + which tells us it is a memory address base. + */ + pci_write_config32(dev, 0x24, 0x00000000); + + /* Get the normal pci resources of this device */ + pci_dev_read_resources(dev); + compact_resources(dev); +} + +typedef struct _MMIORANGE +{ + u32 Base; + u32 Limit; + u8 Attribute; +} MMIORANGE; + +MMIORANGE MMIO[8], CreativeMMIO[8]; + +#define CIM_STATUS u32 +#define CIM_SUCCESS 0x00000000 +#define CIM_ERROR 0x80000000 +#define CIM_UNSUPPORTED 0x80000001 +#define CIM_DISABLEPORT 0x80000002 + +#define MMIO_ATTRIB_NP_ONLY 1 +#define MMIO_ATTRIB_BOTTOM_TO_TOP 1<<1 +#define MMIO_ATTRIB_SKIP_ZERO 1<<2 + +#ifdef DONT_TRUST_RESOURCE_ALLOCATION +static MMIORANGE* AllocMMIO(MMIORANGE* pMMIO) +{ + int i; + for (i=0; i<8; i++) { + if (pMMIO[i].Limit == 0) + return &pMMIO[i]; + } + return 0; +} + +static void FreeMMIO(MMIORANGE* pMMIO) +{ + pMMIO->Base = 0; + pMMIO->Limit = 0; +} + +static u32 SetMMIO(u32 Base, u32 Limit, u8 Attribute, MMIORANGE *pMMIO) +{ + int i; + MMIORANGE * TempRange; + for(i=0; i<8; i++) + { + if(pMMIO[i].Attribute != Attribute && Base >= pMMIO[i].Base && Limit <= pMMIO[i].Limit) + { + TempRange = AllocMMIO(pMMIO); + if(TempRange == 0) return 0x80000000; + TempRange->Base = Limit; + TempRange->Limit = pMMIO[i].Limit; + TempRange->Attribute = pMMIO[i].Attribute; + pMMIO[i].Limit = Base; + } + } + TempRange = AllocMMIO(pMMIO); + if(TempRange == 0) return 0x80000000; + TempRange->Base = Base; + TempRange->Limit = Limit; + TempRange->Attribute = Attribute; + return 0; +} + +static u8 FinalizeMMIO(MMIORANGE *pMMIO) +{ + int i, j, n = 0; + for(i=0; i<8; i++) + { + if (pMMIO[i].Base == pMMIO[i].Limit) + { + FreeMMIO(&pMMIO[i]); + continue; + } + for(j=0; j> 8) & 0xFF; + BusEnd = (Value >> 16) & 0xFF; + for(Bus = BusStart; Bus <= BusEnd; Bus++) + { + for(Dev = 0; Dev <= 0x1f; Dev++) + { + tempdev = dev_find_slot(Bus, Dev << 3); + Value = pci_read_config32(tempdev, 0); + printk(BIOS_DEBUG, "Dev ID %x \n", Value); + if((Value & 0xffff) == 0x1102) + {//Creative + //Found Creative SB + u32 MMIOStart = 0xffffffff; + u32 MMIOLimit = 0; + for(Reg = 0x10; Reg < 0x20; Reg+=4) + { + u32 BaseA, LimitA; + BaseA = pci_read_config32(tempdev, Reg); + Value = BaseA; + if(!(Value & 0x01)) + { + Value = Value & 0xffffff00; + if(Value != 0) + { + if(MMIOStart > Value) + MMIOStart = Value; + LimitA = 0xffffffff; + //WritePCI(PciAddress,AccWidthUint32,&LimitA); + pci_write_config32(tempdev, Reg, LimitA); + //ReadPCI(PciAddress,AccWidthUint32,&LimitA); + LimitA = pci_read_config32(tempdev, Reg); + LimitA = Value + (~LimitA + 1); + //WritePCI(PciAddress,AccWidthUint32,&BaseA); + pci_write_config32(tempdev, Reg, BaseA); + if (LimitA > MMIOLimit) + MMIOLimit = LimitA; + } + } + } + printk(BIOS_DEBUG, " MMIOStart %x MMIOLimit %x \n", MMIOStart, MMIOLimit); + if (MMIOStart < MMIOLimit) + { + Status = SetMMIO(MMIOStart>>8, MMIOLimit>>8, 0x80, pMMIO); + if(Status == CIM_ERROR) return Status; + } + } + } + } + if(Status == CIM_SUCCESS) + { + //Lets optimize MMIO + if(FinalizeMMIO(pMMIO) > 4) + { + Status = CIM_ERROR; + } + } + + return Status; +} + +static void ProgramMMIO(MMIORANGE *pMMIO, u8 LinkID, u8 Attribute) +{ + int i, j, n = 7; + device_t k8_f1; + + k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1)); + + for(i = 0; i < 8; i++) + { + int k = 0, MmioReg; + u32 Base = 0; + u32 Limit = 0; + for(j = 0; j < 8; j++) + { + if (Base < pMMIO[j].Base) + { + Base = pMMIO[j].Base; + k = j; + } + } + if(pMMIO[k].Limit != 0) + { + if(Attribute & MMIO_ATTRIB_NP_ONLY && pMMIO[k].Attribute == 0 ) + { + Base = 0; + } + else + { + Base = pMMIO[k].Base | 0x3; + Limit= ((pMMIO[k].Limit - 1) & 0xffffff00) | pMMIO[k].Attribute | (LinkID << 4); + } + FreeMMIO(&pMMIO[k]); + } + if (Attribute & MMIO_ATTRIB_SKIP_ZERO && Base == 0 && Limit == 0) continue; + MmioReg = (Attribute & MMIO_ATTRIB_BOTTOM_TO_TOP)?n:(7-n); + n--; + //RWPCI(PCI_ADDRESS(0,CPU_DEV,CPU_F1,0x80+MmioReg*8),AccWidthUint32 |S3_SAVE,0x0,0x0); + pci_write_config32(k8_f1, 0x80+MmioReg*8, 0); + + //WritePCI(PCI_ADDRESS(0,CPU_DEV,CPU_F1,0x84+MmioReg*8),AccWidthUint32 |S3_SAVE,&Limit); + pci_write_config32(k8_f1, 0x84+MmioReg*8, Limit); + + //WritePCI(PCI_ADDRESS(0,CPU_DEV,CPU_F1,0x80+MmioReg*8),AccWidthUint32 |S3_SAVE,&Base); + pci_write_config32(k8_f1, 0x80+MmioReg*8, Base); + } +} +#endif + +static void internal_gfx_pci_dev_init(struct device *dev) +{ + unsigned char * bpointer; + volatile u32 * GpuF0MMReg; + volatile u32 * pointer; + int i; + u16 command; + u32 value; + u16 deviceid, vendorid; + device_t nb_dev = dev_find_slot(0, 0); + device_t k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2)); + device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); + static const u8 ht_freq_lookup [] = {2, 0, 4, 0, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 0, 0, 28, 30, 32}; + static const u8 ht_width_lookup [] = {8, 16, 0, 0, 2, 4, 0, 0}; + static const u16 memclk_lookup_fam0F [] = {100, 0, 133, 0, 0, 166, 0, 200}; + static const u16 memclk_lookup_fam10 [] = {200, 266, 333, 400, 533, 667, 800, 800}; + + /* We definetely will use this in future. Just leave it here. */ + /*struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)dev->chip_info;*/ + + deviceid = pci_read_config16(dev, PCI_DEVICE_ID); + vendorid = pci_read_config16(dev, PCI_VENDOR_ID); + printk(BIOS_DEBUG, "internal_gfx_pci_dev_init device=%x, vendor=%x.\n", + deviceid, vendorid); + + command = pci_read_config16(dev, 0x04); + command |= 0x7; + pci_write_config16(dev, 0x04, command); + + /* Clear vgainfo. */ + bpointer = (unsigned char *) &vgainfo; + for(i=0; i>8)|((value&0xff000000)>>8); + *(GpuF0MMReg + 0x2c04/4) = ((value&0xff00)<<8); + *(GpuF0MMReg + 0x5428/4) = ((value&0xffff0000)+0x10000)-((value&0xffff)<<16); + *(GpuF0MMReg + 0xF774/4) = 0xffffffff; + *(GpuF0MMReg + 0xF770/4) = 0x00000001; + *(GpuF0MMReg + 0x2000/4) = 0x00000011; + *(GpuF0MMReg + 0x200c/4) = 0x00000020; + *(GpuF0MMReg + 0x2010/4) = 0x10204810; + *(GpuF0MMReg + 0x2010/4) = 0x00204810; + *(GpuF0MMReg + 0x2014/4) = 0x10408810; + *(GpuF0MMReg + 0x2014/4) = 0x00408810; + *(GpuF0MMReg + 0x2414/4) = 0x00000080; + *(GpuF0MMReg + 0x2418/4) = 0x84422415; + *(GpuF0MMReg + 0x2418/4) = 0x04422415; + *(GpuF0MMReg + 0x5490/4) = 0x00000001; + *(GpuF0MMReg + 0x7de4/4) |= (1<<3) | (1<<4); + /* Force allow LDT_STOP Cool'n'Quiet workaround. */ + *(GpuF0MMReg + 0x655c/4) |= 1<<4; + + // disable write combining, needed for stability + // reference bios does this only for RS780 rev A11 + // need to figure out why we need it for all revs + *(GpuF0MMReg + 0x2000/4) = 0x00000010; + *(GpuF0MMReg + 0x2408/4) = 1 << 9; + *(GpuF0MMReg + 0x2000/4) = 0x00000011; + + /* GFX_InitFBAccess finished. */ + +#if (CONFIG_GFXUMA == 1) /* for UMA mode. */ + /* GFX_StartMC. */ + set_nbmc_enable_bits(nb_dev, 0x02, 0x00000000, 0x80000000); + set_nbmc_enable_bits(nb_dev, 0x01, 0x00000000, 0x00000001); + set_nbmc_enable_bits(nb_dev, 0x01, 0x00000000, 0x00000004); + set_nbmc_enable_bits(nb_dev, 0x01, 0x00040000, 0x00000000); + set_nbmc_enable_bits(nb_dev, 0xB1, 0xFFFF0000, 0x00000040); + set_nbmc_enable_bits(nb_dev, 0xC3, 0x00000000, 0x00000001); + set_nbmc_enable_bits(nb_dev, 0x07, 0xFFFFFFFF, 0x00000018); + set_nbmc_enable_bits(nb_dev, 0x06, 0xFFFFFFFF, 0x00000102); + set_nbmc_enable_bits(nb_dev, 0x09, 0xFFFFFFFF, 0x40000008); + set_nbmc_enable_bits(nb_dev, 0x06, 0x00000000, 0x80000000); + /* GFX_StartMC finished. */ +#else + /* for SP mode. */ + set_nbmc_enable_bits(nb_dev, 0xaa, 0xf0, 0x30); + set_nbmc_enable_bits(nb_dev, 0xce, 0xf0, 0x30); + set_nbmc_enable_bits(nb_dev, 0xca, 0xff000000, 0x47000000); + set_nbmc_enable_bits(nb_dev, 0xcb, 0x3f000000, 0x01000000); + set_nbmc_enable_bits(nb_dev, 0x01, 0, 1<<0); + set_nbmc_enable_bits(nb_dev, 0x04, 0, 1<<31); + set_nbmc_enable_bits(nb_dev, 0xb4, 0x3f, 0x3f); + set_nbmc_enable_bits(nb_dev, 0xb4, 0, 1<<6); + set_nbmc_enable_bits(nb_dev, 0xc3, 1<<11, 0); + set_nbmc_enable_bits(nb_dev, 0xa0, 1<<29, 0); + nbmc_write_index(nb_dev, 0xa4, 0x3484576f); + nbmc_write_index(nb_dev, 0xa5, 0x222222df); + nbmc_write_index(nb_dev, 0xa6, 0x00000000); + nbmc_write_index(nb_dev, 0xa7, 0x00000000); + set_nbmc_enable_bits(nb_dev, 0xc3, 1<<8, 0); + udelay(10); + set_nbmc_enable_bits(nb_dev, 0xc3, 1<<9, 0); + udelay(10); + set_nbmc_enable_bits(nb_dev, 0x01, 0, 1<<2); + udelay(200); + set_nbmc_enable_bits(nb_dev, 0x01, 0, 1<<3); + set_nbmc_enable_bits(nb_dev, 0xa0, 0, 1<<31); + udelay(500); + set_nbmc_enable_bits(nb_dev, 0x02, 0, 1<<31); + set_nbmc_enable_bits(nb_dev, 0xa0, 0, 1<<30); + set_nbmc_enable_bits(nb_dev, 0xa0, 1<<31, 0); + set_nbmc_enable_bits(nb_dev, 0xa0, 0, 1<<29); + nbmc_write_index(nb_dev, 0xa4, 0x23484576); + nbmc_write_index(nb_dev, 0xa5, 0x00000000); + nbmc_write_index(nb_dev, 0xa6, 0x00000000); + nbmc_write_index(nb_dev, 0xa7, 0x00000000); + /* GFX_StartMC finished. */ + + /* GFX_SPPowerManagment, don't care for new. */ + /* Post MC Init table programming. */ + set_nbmc_enable_bits(nb_dev, 0xac, ~(0xfffffff0), 0x0b); + + /* Do we need Write and Read Calibration? */ + /* GFX_Init finished. */ +#endif + + /* GFX_InitIntegratedInfo. */ + /* fill the Integrated Info Table. */ + vgainfo.sHeader.usStructureSize = sizeof(ATOM_INTEGRATED_SYSTEM_INFO_V2); + vgainfo.sHeader.ucTableFormatRevision = 1; + vgainfo.sHeader.ucTableContentRevision = 2; + +#if (CONFIG_GFXUMA == 0) /* SP mode. */ + // Side port support is incomplete, do not use it + // These parameters must match the motherboard + vgainfo.ulBootUpSidePortClock = 667*100; + vgainfo.ucMemoryType = 3; // 3=ddr3 sp mem, 2=ddr2 sp mem + vgainfo.ulMinSidePortClock = 333*100; +#endif + + vgainfo.ulBootUpEngineClock = 500 * 100; // setup option on reference BIOS, 500 is default + + // find the DDR memory frequency + if (is_family10h()) { + value = pci_read_config32(k8_f2, 0x94); // read channel 0 DRAM Configuration High Register + if (extractbit(value, 14)) // if channel 0 disabled, channel 1 must have memory + value = pci_read_config32(k8_f2, 0x194);// read channel 1 DRAM Configuration High Register + vgainfo.ulBootUpUMAClock = memclk_lookup_fam10 [extractbits (value, 0, 2)] * 100; + } + if (is_family0Fh()) { + value = pci_read_config32(k8_f2, 0x94); + vgainfo.ulBootUpUMAClock = memclk_lookup_fam0F [extractbits (value, 20, 22)] * 100; + } + + /* UMA Channel Number: 1 or 2. */ + vgainfo.ucUMAChannelNumber = 1; + if (is_family0Fh()) { + value = pci_read_config32(k8_f2, 0x90); + if (extractbit(value, 11)) // 128-bit mode + vgainfo.ucUMAChannelNumber = 2; + } + if (is_family10h()) { + u32 dch0 = pci_read_config32(k8_f2, 0x94); + u32 dch1 = pci_read_config32(k8_f2, 0x194); + if (extractbit(dch0, 14) == 0 && extractbit(dch1, 14) == 0) { // both channels enabled + value = pci_read_config32(k8_f2, 0x110); + if (extractbit(value, 4)) // ganged mode + vgainfo.ucUMAChannelNumber = 2; + } + } + + // processor type + if (is_family0Fh()) + vgainfo.ulCPUCapInfo = 3; + if (is_family10h()) + vgainfo.ulCPUCapInfo = 2; + + /* HT speed */ + value = pci_read_config8(nb_dev, 0xd1); + value = ht_freq_lookup [value] * 100; // HT link frequency in MHz + vgainfo.ulHTLinkFreq = value * 100; // HT frequency in units of 100 MHz + vgainfo.ulHighVoltageHTLinkFreq = vgainfo.ulHTLinkFreq; + vgainfo.ulLowVoltageHTLinkFreq = vgainfo.ulHTLinkFreq; + + if (value <= 1800) + vgainfo.ulLowVoltageHTLinkFreq = vgainfo.ulHTLinkFreq; + else { + int sblink, cpuLnkFreqCap, nbLnkFreqCap; + value = pci_read_config32(k8_f0, 0x64); + sblink = extractbits(value, 8, 10); + cpuLnkFreqCap = pci_read_config16(k8_f0, 0x8a + sblink * 0x20); + nbLnkFreqCap = pci_read_config16(nb_dev, 0xd2); + if (cpuLnkFreqCap & nbLnkFreqCap & (1 << 10)) // if both 1800 MHz capable + vgainfo.ulLowVoltageHTLinkFreq = 1800*100; + } + + /* HT width. */ + value = pci_read_config8(nb_dev, 0xcb); + vgainfo.usMinDownStreamHTLinkWidth = + vgainfo.usMaxDownStreamHTLinkWidth = + vgainfo.usMinUpStreamHTLinkWidth = + vgainfo.usMaxUpStreamHTLinkWidth = + vgainfo.usMinHTLinkWidth = + vgainfo.usMaxHTLinkWidth = ht_width_lookup [extractbits(value, 0, 2)]; + + if (is_family0Fh()) { + vgainfo.usUMASyncStartDelay = 322; + vgainfo.usUMADataReturnTime = 286; + } + + if (is_family10h()) { + static u16 t0mult_lookup [] = {10, 50, 200, 2000}; + int t0time, t0scale; + value = pci_read_config32(k8_f0, 0x16c); + t0time = extractbits(value, 0, 3); + t0scale = extractbits(value, 4, 5); + vgainfo.usLinkStatusZeroTime = t0mult_lookup [t0scale] * t0time; + vgainfo.usUMASyncStartDelay = 100; + if (vgainfo.ulHTLinkFreq < 1000 * 100) { // less than 1000 MHz + vgainfo.usUMADataReturnTime = 300; + vgainfo.usLinkStatusZeroTime = 6 * 100; // 6us for GH in HT1 mode + } + else { + int lssel; + value = pci_read_config32(nb_dev, 0xac); + lssel = extractbits (value, 7, 8); + vgainfo.usUMADataReturnTime = 1300; + if (lssel == 0) vgainfo.usUMADataReturnTime = 150; + } + } + + /* Transfer the Table to VBIOS. */ + pointer = (u32 *)&vgainfo; + for(i=0; i> 8; + if(Base32 < Limit32) + { + Status = GetCreativeMMIO(&CreativeMMIO[0]); + if(Status != CIM_ERROR) + SetMMIO(Base32, Limit32, 0x0, &MMIO[0]); + } + /* Set MMIO for prefetchable P2P. */ + if(Status != CIM_ERROR) + { + temp = pci_read_config32(dev0x14, 0x24); + + Base32 = (temp & 0x0fff0) <<8; + Limit32 = ((temp & 0x0fff00000) + 0x100000) >> 8; + if(Base32 < Limit32) + SetMMIO(Base32, Limit32, 0x0, &MMIO[0]); + } + + FinalizeMMIO(&MMIO[0]); + + ProgramMMIO(&CreativeMMIO[0], 0, MMIO_ATTRIB_NP_ONLY); + ProgramMMIO(&MMIO[0], 0, MMIO_ATTRIB_NP_ONLY | MMIO_ATTRIB_BOTTOM_TO_TOP | MMIO_ATTRIB_SKIP_ZERO); +#endif + + pci_dev_init(dev); + + /* clk ind */ + clkind_write(dev, 0x08, 0x01); + clkind_write(dev, 0x0C, 0x22); + clkind_write(dev, 0x0F, 0x0); + clkind_write(dev, 0x11, 0x0); + clkind_write(dev, 0x12, 0x0); + clkind_write(dev, 0x14, 0x0); + clkind_write(dev, 0x15, 0x0); + clkind_write(dev, 0x16, 0x0); + clkind_write(dev, 0x17, 0x0); + clkind_write(dev, 0x18, 0x0); + clkind_write(dev, 0x19, 0x0); + clkind_write(dev, 0x1A, 0x0); + clkind_write(dev, 0x1B, 0x0); + clkind_write(dev, 0x1C, 0x0); + clkind_write(dev, 0x1D, 0x0); + clkind_write(dev, 0x1E, 0x0); + clkind_write(dev, 0x26, 0x0); + clkind_write(dev, 0x27, 0x0); + clkind_write(dev, 0x28, 0x0); + clkind_write(dev, 0x5C, 0x0); +} + + +/* +* Set registers in RS780 and CPU to enable the internal GFX. +* Please refer to CIM source code and BKDG. +*/ + +static void rs780_internal_gfx_enable(device_t dev) +{ + u32 l_dword; + int i; + device_t nb_dev = dev_find_slot(0, 0); + msr_t sysmem; + +#if (CONFIG_GFXUMA == 0) + u32 FB_Start, FB_End; +#endif + + printk(BIOS_DEBUG, "rs780_internal_gfx_enable dev = 0x%p, nb_dev = 0x%p.\n", dev, nb_dev); + + sysmem = rdmsr(0xc001001a); + printk(BIOS_DEBUG, "sysmem = %x_%x\n", sysmem.hi, sysmem.lo); + + /* The system top memory in 780. */ + pci_write_config32(nb_dev, 0x90, sysmem.lo); + htiu_write_index(nb_dev, 0x30, 0); + htiu_write_index(nb_dev, 0x31, 0); + + /* Disable external GFX and enable internal GFX. */ + l_dword = pci_read_config32(nb_dev, 0x8c); + l_dword &= ~(1<<0); + l_dword |= 1<<1; + pci_write_config32(nb_dev, 0x8c, l_dword); + + /* NB_SetDefaultIndexes */ + pci_write_config32(nb_dev, 0x94, 0x7f); + pci_write_config32(nb_dev, 0x60, 0x7f); + pci_write_config32(nb_dev, 0xe0, 0); + + /* NB_InitEarlyNB finished. */ + + /* LPC DMA Deadlock workaround? */ + /* GFX_InitCommon*/ + device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); + l_dword = pci_read_config32(k8_f0, 0x68); + l_dword &= ~(3 << 21); + l_dword |= (1 << 21); + pci_write_config32(k8_f0, 0x68, l_dword); + + /* GFX_InitCommon. */ + nbmc_write_index(nb_dev, 0x23, 0x00c00010); + set_nbmc_enable_bits(nb_dev, 0x16, 1<<15, 1<<15); + set_nbmc_enable_bits(nb_dev, 0x25, 0xffffffff, 0x111f111f); + set_htiu_enable_bits(nb_dev, 0x37, 1<<24, 1<<24); + +#if (CONFIG_GFXUMA == 1) + /* GFX_InitUMA. */ + /* Copy CPU DDR Controller to NB MC. */ + device_t k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1)); + device_t k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2)); + device_t k8_f4 = dev_find_slot(0, PCI_DEVFN(0x18, 4)); + for (i = 0; i < 12; i++) + { + l_dword = pci_read_config32(k8_f2, 0x40 + i * 4); + nbmc_write_index(nb_dev, 0x30 + i, l_dword); + } + + l_dword = pci_read_config32(k8_f2, 0x80); + nbmc_write_index(nb_dev, 0x3c, l_dword); + l_dword = pci_read_config32(k8_f2, 0x94); + set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<<22))<<16); + set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<< 8))<<17); + l_dword = pci_read_config32(k8_f2, 0x90); + set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<<10))<<18); + if (is_family10h()) + { + for (i = 0; i < 12; i++) + { + l_dword = pci_read_config32(k8_f2, 0x140 + i * 4); + nbmc_write_index(nb_dev, 0x3d + i, l_dword); + } + + l_dword = pci_read_config32(k8_f2, 0x180); + nbmc_write_index(nb_dev, 0x49, l_dword); + l_dword = pci_read_config32(k8_f2, 0x194); + set_nbmc_enable_bits(nb_dev, 0x49, 0, !!(l_dword & (1<<22))<<16); + set_nbmc_enable_bits(nb_dev, 0x49, 0, !!(l_dword & (1<< 8))<<17); + l_dword = pci_read_config32(k8_f2, 0x190); + set_nbmc_enable_bits(nb_dev, 0x49, 0, !!(l_dword & (1<<10))<<18); + + l_dword = pci_read_config32(k8_f2, 0x110); + nbmc_write_index(nb_dev, 0x4a, l_dword); + l_dword = pci_read_config32(k8_f2, 0x114); + nbmc_write_index(nb_dev, 0x4b, l_dword); + l_dword = pci_read_config32(k8_f4, 0x44); + set_nbmc_enable_bits(nb_dev, 0x4a, 0, !!(l_dword & (1<<22))<<24); + l_dword = pci_read_config32(k8_f1, 0x40); + nbmc_write_index(nb_dev, 0x4c, l_dword); + l_dword = pci_read_config32(k8_f1, 0xf0); + nbmc_write_index(nb_dev, 0x4d, l_dword); + } + + + /* Set UMA in the 780 side. */ + /* UMA start address, size. */ + /* The UMA starts at 0xC0000000 of internal RS780 address space + [31:16] addr of last byte | [31:16] addr of first byte + */ + nbmc_write_index(nb_dev, 0x10, ((uma_memory_size - 1 + 0xC0000000) & (~0xffff)) | 0xc000); + nbmc_write_index(nb_dev, 0x11, uma_memory_base); + nbmc_write_index(nb_dev, 0x12, 0); + nbmc_write_index(nb_dev, 0xf0, uma_memory_size >> 20); + /* GFX_InitUMA finished. */ +#else + /* GFX_InitSP. */ + /* SP memory:Hynix HY5TQ1G631ZNFP. 128MB = 64M * 16. 667MHz. DDR3. */ + + /* Enable Async mode. */ + set_nbmc_enable_bits(nb_dev, 0x06, 7<<8, 1<<8); + set_nbmc_enable_bits(nb_dev, 0x08, 1<<10, 0); + /* The last item in AsynchMclkTaskFileIndex. Why? */ + /* MC_MPLL_CONTROL2. */ + nbmc_write_index(nb_dev, 0x07, 0x40100028); + /* MC_MPLL_DIV_CONTROL. */ + nbmc_write_index(nb_dev, 0x0b, 0x00000028); + /* MC_MPLL_FREQ_CONTROL. */ + set_nbmc_enable_bits(nb_dev, 0x09, 3<<12|15<<16|15<<8, 1<<12|4<<16|0<<8); + /* MC_MPLL_CONTROL3. For PM. */ + set_nbmc_enable_bits(nb_dev, 0x08, 0xff<<13, 1<<13|1<<18); + /* MPLL_CAL_TRIGGER. */ + set_nbmc_enable_bits(nb_dev, 0x06, 0, 1<<0); + udelay(200); /* time is long enough? */ + set_nbmc_enable_bits(nb_dev, 0x06, 0, 1<<1); + set_nbmc_enable_bits(nb_dev, 0x06, 1<<0, 0); + /* MCLK_SRC_USE_MPLL. */ + set_nbmc_enable_bits(nb_dev, 0x02, 0, 1<<20); + + /* Pre Init MC. */ + nbmc_write_index(nb_dev, 0x01, 0x88108280); + set_nbmc_enable_bits(nb_dev, 0x02, ~(1<<20), 0x00030200); + nbmc_write_index(nb_dev, 0x04, 0x08881018); + nbmc_write_index(nb_dev, 0x05, 0x000000bb); + nbmc_write_index(nb_dev, 0x0c, 0x0f00001f); + nbmc_write_index(nb_dev, 0xa1, 0x01f10000); + /* MCA_INIT_DLL_PM. */ + set_nbmc_enable_bits(nb_dev, 0xc9, 1<<24, 1<<24); + nbmc_write_index(nb_dev, 0xa2, 0x74f20000); + nbmc_write_index(nb_dev, 0xa3, 0x8af30000); + nbmc_write_index(nb_dev, 0xaf, 0x47d0a41c); + nbmc_write_index(nb_dev, 0xb0, 0x88800130); + nbmc_write_index(nb_dev, 0xb1, 0x00000040); + nbmc_write_index(nb_dev, 0xb4, 0x41247000); + nbmc_write_index(nb_dev, 0xb5, 0x00066664); + nbmc_write_index(nb_dev, 0xb6, 0x00000022); + nbmc_write_index(nb_dev, 0xb7, 0x00000044); + nbmc_write_index(nb_dev, 0xb8, 0xbbbbbbbb); + nbmc_write_index(nb_dev, 0xb9, 0xbbbbbbbb); + nbmc_write_index(nb_dev, 0xba, 0x55555555); + nbmc_write_index(nb_dev, 0xc1, 0x00000000); + nbmc_write_index(nb_dev, 0xc2, 0x00000000); + nbmc_write_index(nb_dev, 0xc3, 0x80006b00); + nbmc_write_index(nb_dev, 0xc4, 0x00066664); + nbmc_write_index(nb_dev, 0xc5, 0x00000000); + nbmc_write_index(nb_dev, 0xd2, 0x00000022); + nbmc_write_index(nb_dev, 0xd3, 0x00000044); + nbmc_write_index(nb_dev, 0xd6, 0x00050005); + nbmc_write_index(nb_dev, 0xd7, 0x00000000); + nbmc_write_index(nb_dev, 0xd8, 0x00700070); + nbmc_write_index(nb_dev, 0xd9, 0x00700070); + nbmc_write_index(nb_dev, 0xe0, 0x00200020); + nbmc_write_index(nb_dev, 0xe1, 0x00200020); + nbmc_write_index(nb_dev, 0xe8, 0x00200020); + nbmc_write_index(nb_dev, 0xe9, 0x00200020); + nbmc_write_index(nb_dev, 0xe0, 0x00180018); + nbmc_write_index(nb_dev, 0xe1, 0x00180018); + nbmc_write_index(nb_dev, 0xe8, 0x00180018); + nbmc_write_index(nb_dev, 0xe9, 0x00180018); + + /* Misc options. */ + /* Memory Termination. */ + set_nbmc_enable_bits(nb_dev, 0xa1, 0x0ff, 0x044); + set_nbmc_enable_bits(nb_dev, 0xb4, 0xf00, 0xb00); +#if 0 + /* Controller Termation. */ + set_nbmc_enable_bits(nb_dev, 0xb1, 0x77770000, 0x77770000); +#endif + + /* OEM Init MC. 667MHz. */ + nbmc_write_index(nb_dev, 0xa8, 0x7a5aaa78); + nbmc_write_index(nb_dev, 0xa9, 0x514a2319); + nbmc_write_index(nb_dev, 0xaa, 0x54400520); + nbmc_write_index(nb_dev, 0xab, 0x441460ff); + nbmc_write_index(nb_dev, 0xa0, 0x20f00a48); + set_nbmc_enable_bits(nb_dev, 0xa2, ~(0xffffffc7), 0x10); + nbmc_write_index(nb_dev, 0xb2, 0x00000303); + set_nbmc_enable_bits(nb_dev, 0xb1, ~(0xffffff70), 0x45); + /* Do it later. */ + /* set_nbmc_enable_bits(nb_dev, 0xac, ~(0xfffffff0), 0x0b); */ + + /* Init PM timing. */ + for(i=0; i<4; i++) + { + l_dword = nbmc_read_index(nb_dev, 0xa0+i); + nbmc_write_index(nb_dev, 0xc8+i, l_dword); + } + for(i=0; i<4; i++) + { + l_dword = nbmc_read_index(nb_dev, 0xa8+i); + nbmc_write_index(nb_dev, 0xcc+i, l_dword); + } + l_dword = nbmc_read_index(nb_dev, 0xb1); + set_nbmc_enable_bits(nb_dev, 0xc8, 0xff<<24, ((l_dword&0x0f)<<24)|((l_dword&0xf00)<<20)); + + /* Init MC FB. */ + /* FB_Start = ; FB_End = ; iSpSize = 0x0080, 128MB. */ + nbmc_write_index(nb_dev, 0x11, 0x40000000); + FB_Start = 0xc00 + 0x080; + FB_End = 0xc00 + 0x080; + nbmc_write_index(nb_dev, 0x10, (((FB_End&0xfff)<<20)-0x10000)|(((FB_Start&0xfff)-0x080)<<4)); + set_nbmc_enable_bits(nb_dev, 0x0d, ~0x000ffff0, (FB_Start&0xfff)<<20); + nbmc_write_index(nb_dev, 0x0f, 0); + nbmc_write_index(nb_dev, 0x0e, (FB_Start&0xfff)|(0xaaaa<<12)); +#endif + + /* GFX_InitSP finished. */ +} + +static struct pci_operations lops_pci = { + .set_subsystem = pci_dev_set_subsystem, +}; + +static struct device_operations pcie_ops = { + .read_resources = rs780_gfx_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = internal_gfx_pci_dev_init, /* The option ROM initializes the device. rs780_gfx_init, */ + .scan_bus = 0, + .enable = rs780_internal_gfx_enable, + .ops_pci = &lops_pci, +}; + +/* + * We should list all of them here. + * */ +static const struct pci_driver pcie_driver_780 __pci_driver = { + .ops = &pcie_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_RS780_INT_GFX, +}; + +static const struct pci_driver pcie_driver_780c __pci_driver = { + .ops = &pcie_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_RS780C_INT_GFX, +}; +static const struct pci_driver pcie_driver_780m __pci_driver = { + .ops = &pcie_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_RS780M_INT_GFX, +}; +static const struct pci_driver pcie_driver_780mc __pci_driver = { + .ops = &pcie_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_RS780MC_INT_GFX, +}; +static const struct pci_driver pcie_driver_780e __pci_driver = { + .ops = &pcie_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_RS780E_INT_GFX, +}; +static const struct pci_driver pcie_driver_785g __pci_driver = { + .ops = &pcie_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_RS785G_INT_GFX, +}; + +/* step 12 ~ step 14 from rpr */ +static void single_port_configuration(device_t nb_dev, device_t dev) +{ + u8 result, width; + u32 reg32; + struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)nb_dev->chip_info; + + printk(BIOS_DEBUG, "rs780_gfx_init single_port_configuration.\n"); + + /* step 12 training, releases hold training for GFX port 0 (device 2) */ + PcieReleasePortTraining(nb_dev, dev, 2); + result = PcieTrainPort(nb_dev, dev, 2); + printk(BIOS_DEBUG, "rs780_gfx_init single_port_configuration step12.\n"); + + /* step 13 Power Down Control */ + /* step 13.1 Enables powering down transmitter and receiver pads along with PLL macros. */ + set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 1 << 0); + + /* step 13.a Link Training was NOT successful */ + if (!result) { + set_nbmisc_enable_bits(nb_dev, 0x8, 0, 0x3 << 4); /* prevent from training. */ + set_nbmisc_enable_bits(nb_dev, 0xc, 0, 0x3 << 2); /* hide the GFX bridge. */ + if (cfg->gfx_tmds) + nbpcie_ind_write_index(nb_dev, 0x65, 0xccf0f0); + else { + nbpcie_ind_write_index(nb_dev, 0x65, 0xffffffff); + set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 3, 1 << 3); + } + } else { /* step 13.b Link Training was successful */ + set_pcie_enable_bits(dev, 0xA2, 0xFF, 0x1); + reg32 = nbpcie_p_read_index(dev, 0x29); + width = reg32 & 0xFF; + printk(BIOS_DEBUG, "GFX Inactive Lanes = 0x%x.\n", width); + switch (width) { + case 1: + case 2: + nbpcie_ind_write_index(nb_dev, 0x65, + cfg->gfx_lane_reversal ? 0x7f7f : 0xccfefe); + break; + case 4: + nbpcie_ind_write_index(nb_dev, 0x65, + cfg->gfx_lane_reversal ? 0x3f3f : 0xccfcfc); + break; + case 8: + nbpcie_ind_write_index(nb_dev, 0x65, + cfg->gfx_lane_reversal ? 0x0f0f : 0xccf0f0); + break; + } + } + printk(BIOS_DEBUG, "rs780_gfx_init single_port_configuration step13.\n"); + + /* step 14 Reset Enumeration Timer, disables the shortening of the enumeration timer */ + set_pcie_enable_bits(dev, 0x70, 1 << 19, 1 << 19); + printk(BIOS_DEBUG, "rs780_gfx_init single_port_configuration step14.\n"); +} + +static void dual_port_configuration(device_t nb_dev, device_t dev) +{ + u8 result, width; + u32 reg32, dev_ind = dev->path.pci.devfn >> 3; + struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)nb_dev->chip_info; + + /* 5.4.1.2 Dual Port Configuration */ + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); + set_nbmisc_enable_bits(nb_dev, 0x08, 0xF << 8, 0x5 << 8); + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); + + /* 5.7. Training for Device 2 */ + /* 5.7.1. Releases hold training for GFX port 0 (device 2) */ + PcieReleasePortTraining(nb_dev, dev, dev_ind); + /* 5.7.2- 5.7.9. PCIE Link Training Sequence */ + result = PcieTrainPort(nb_dev, dev, dev_ind); + + /* Power Down Control for Device 2 */ + /* Link Training was NOT successful */ + if (!result) { + /* Powers down all lanes for port A */ + /* nbpcie_ind_write_index(nb_dev, 0x65, 0x0f0f); */ + /* Note: I have to disable the slot where there isnt a device, + * otherwise the system will hang. I dont know why. */ + set_nbmisc_enable_bits(nb_dev, 0x0c, 1 << dev_ind, 1 << dev_ind); + + } else { /* step 16.b Link Training was successful */ + reg32 = nbpcie_p_read_index(dev, 0xa2); + width = (reg32 >> 4) & 0x7; + printk(BIOS_DEBUG, "GFX LC_LINK_WIDTH = 0x%x.\n", width); + switch (width) { + case 1: + case 2: + nbpcie_ind_write_index(nb_dev, 0x65, + cfg->gfx_lane_reversal ? 0x0707 : 0x0e0e); + break; + case 4: + nbpcie_ind_write_index(nb_dev, 0x65, + cfg->gfx_lane_reversal ? 0x0303 : 0x0c0c); + break; + } + } +} + +/* For single port GFX configuration Only +* width: +* 000 = x16 +* 001 = x1 +* 010 = x2 +* 011 = x4 +* 100 = x8 +* 101 = x12 (not supported) +* 110 = x16 +*/ +static void dynamic_link_width_control(device_t nb_dev, device_t dev, u8 width) +{ + u32 reg32; + device_t sb_dev; + struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)nb_dev->chip_info; + + /* step 5.9.1.1 */ + reg32 = nbpcie_p_read_index(dev, 0xa2); + + /* step 5.9.1.2 */ + set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 1 << 0); + /* step 5.9.1.3 */ + set_pcie_enable_bits(dev, 0xa2, 3 << 0, width << 0); + /* step 5.9.1.4 */ + set_pcie_enable_bits(dev, 0xa2, 1 << 8, 1 << 8); + /* step 5.9.2.4 */ + if (0 == cfg->gfx_reconfiguration) + set_pcie_enable_bits(dev, 0xa2, 1 << 11, 1 << 11); + + /* step 5.9.1.5 */ + do { + reg32 = nbpcie_p_read_index(dev, 0xa2); + } + while (reg32 & 0x100); + + /* step 5.9.1.6 */ + sb_dev = dev_find_slot(0, PCI_DEVFN(8, 0)); + do { + reg32 = pci_ext_read_config32(nb_dev, sb_dev, + PCIE_VC0_RESOURCE_STATUS); + } while (reg32 & VC_NEGOTIATION_PENDING); + + /* step 5.9.1.7 */ + reg32 = nbpcie_p_read_index(dev, 0xa2); + if (((reg32 & 0x70) >> 4) != 0x6) { + /* the unused lanes should be powered off. */ + } + + /* step 5.9.1.8 */ + set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 0 << 0); +} + +/* +* GFX Core initialization, dev2, dev3 +*/ +void rs780_gfx_init(device_t nb_dev, device_t dev, u32 port) +{ + u32 reg32; + struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)nb_dev->chip_info; + + printk(BIOS_DEBUG, "rs780_gfx_init, nb_dev=0x%p, dev=0x%p, port=0x%x.\n", + nb_dev, dev, port); + + /* GFX Core Initialization */ + //if (port == 2) return; + + /* step 2, TMDS, (only need if CMOS option is enabled) */ + if (cfg->gfx_tmds) { + } + +#if 1 /* external clock mode */ + /* table 5-22, 5.9.1. REFCLK */ + /* 5.9.1.1. Disables the GFX REFCLK transmitter so that the GFX + * REFCLK PAD can be driven by an external source. */ + /* 5.9.1.2. Enables GFX REFCLK receiver to receive the REFCLK from an external source. */ + set_nbmisc_enable_bits(nb_dev, 0x38, 1 << 29 | 1 << 28 | 1 << 26, 1 << 28); + + /* 5.9.1.3 Selects the GFX REFCLK to be the source for PLL A. */ + /* 5.9.1.4 Selects the GFX REFCLK to be the source for PLL B. */ + /* 5.9.1.5 Selects the GFX REFCLK to be the source for PLL C. */ + set_nbmisc_enable_bits(nb_dev, 0x28, 3 << 6 | 3 << 8 | 3 << 10, + 1 << 6 | 1 << 8 | 1 << 10); + reg32 = nbmisc_read_index(nb_dev, 0x28); + printk(BIOS_DEBUG, "misc 28 = %x\n", reg32); + + /* 5.9.1.6.Selects the single ended GFX REFCLK to be the source for core logic. */ + set_nbmisc_enable_bits(nb_dev, 0x6C, 1 << 31, 1 << 31); +#else /* internal clock mode */ + /* table 5-23, 5.9.1. REFCLK */ + /* 5.9.1.1. Enables the GFX REFCLK transmitter so that the GFX + * REFCLK PAD can be driven by the SB REFCLK. */ + /* 5.9.1.2. Disables GFX REFCLK receiver from receiving the + * REFCLK from an external source.*/ + set_nbmisc_enable_bits(nb_dev, 0x38, 1 << 29 | 1 << 28, 1 << 29 | 0 << 28); + + /* 5.9.1.3 Selects the GFX REFCLK to be the source for PLL A. */ + /* 5.9.1.4 Selects the GFX REFCLK to be the source for PLL B. */ + /* 5.9.1.5 Selects the GFX REFCLK to be the source for PLL C. */ + set_nbmisc_enable_bits(nb_dev, 0x28, 3 << 6 | 3 << 8 | 3 << 10, + 0); + reg32 = nbmisc_read_index(nb_dev, 0x28); + printk(BIOS_DEBUG, "misc 28 = %x\n", reg32); + + /* 5.9.1.6.Selects the single ended GFX REFCLK to be the source for core logic. */ + set_nbmisc_enable_bits(nb_dev, 0x6C, 1 << 31, 0 << 31); +#endif + + /* step 5.9.3, GFX overclocking, (only need if CMOS option is enabled) */ + /* 5.9.3.1. Increases PLL BW for 6G operation.*/ + /* set_nbmisc_enable_bits(nb_dev, 0x36, 0x3FF << 4, 0xB5 << 4); */ + /* skip */ + + /* step 5.9.4, reset the GFX link */ + /* step 5.9.4.1 asserts both calibration reset and global reset */ + set_nbmisc_enable_bits(nb_dev, 0x8, 0x3 << 14, 0x3 << 14); + + /* step 5.9.4.2 de-asserts calibration reset */ + set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 14, 0 << 14); + + /* step 5.9.4.3 wait for at least 200us */ + udelay(300); + + /* step 5.9.4.4 de-asserts global reset */ + set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 15, 0 << 15); + + /* 5.9.5 Reset PCIE_GFX Slot */ + /* It is done in mainboard.c */ + set_pcie_reset(); + mdelay(1); + set_pcie_dereset(); + + /* step 5.9.8 program PCIE memory mapped configuration space */ + /* done by enable_pci_bar3() before */ + + /* step 7 compliance state, (only need if CMOS option is enabled) */ + /* the compliance stete is just for test. refer to 4.2.5.2 of PCIe specification */ + if (cfg->gfx_compliance) { + /* force compliance */ + set_nbmisc_enable_bits(nb_dev, 0x32, 1 << 6, 1 << 6); + /* release hold training for device 2. GFX initialization is done. */ + set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 4, 0 << 4); + dynamic_link_width_control(nb_dev, dev, cfg->gfx_link_width); + printk(BIOS_DEBUG, "rs780_gfx_init step7.\n"); + return; + } + + /* 5.9.12 Core Initialization. */ + /* 5.9.12.1 sets RCB timeout to be 25ms */ + /* 5.9.12.2. RCB Cpl timeout on link down. */ + set_pcie_enable_bits(dev, 0x70, 7 << 16 | 1 << 19, 4 << 16 | 1 << 19); + printk(BIOS_DEBUG, "rs780_gfx_init step5.9.12.1.\n"); + + /* step 5.9.12.3 disables slave ordering logic */ + set_pcie_enable_bits(nb_dev, 0x20, 1 << 8, 1 << 8); + printk(BIOS_DEBUG, "rs780_gfx_init step5.9.12.3.\n"); + + /* step 5.9.12.4 sets DMA payload size to 64 bytes */ + set_pcie_enable_bits(nb_dev, 0x10, 7 << 10, 4 << 10); + /* 5.9.12.5. Blocks DMA traffic during C3 state. */ + set_pcie_enable_bits(dev, 0x10, 1 << 0, 0 << 0); + + /* 5.9.12.6. Disables RC ordering logic */ + set_pcie_enable_bits(nb_dev, 0x20, 1 << 9, 1 << 9); + + /* Enabels TLP flushing. */ + /* Note: It is got from RS690. The system will hang without this action. */ + set_pcie_enable_bits(dev, 0x20, 1 << 19, 0 << 19); + + /* 5.9.12.7. Ignores DLLPs during L1 so that txclk can be turned off */ + set_pcie_enable_bits(nb_dev, 0x2, 1 << 0, 1 << 0); + + /* 5.9.12.8 Prevents LC to go from L0 to Rcv_L0s if L1 is armed. */ + set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11); + + /* 5.9.12.9 CMGOOD_OVERRIDE for end point initiated lane degradation. */ + set_nbmisc_enable_bits(nb_dev, 0x6a, 1 << 17, 1 << 17); + printk(BIOS_DEBUG, "rs780_gfx_init step5.9.12.9.\n"); + + /* 5.9.12.10 Sets the timer in Config state from 20us to */ + /* 5.9.12.11 De-asserts RX_EN in L0s. */ + /* 5.9.12.12 Enables de-assertion of PG2RX_CR_EN to lock clock + * recovery parameter when lane is in electrical idle in L0s.*/ + set_pcie_enable_bits(dev, 0xB1, 1 << 23 | 1 << 19 | 1 << 28, 1 << 23 | 1 << 19 | 1 << 28); + + /* 5.9.12.13. Turns off offset calibration. */ + /* 5.9.12.14. Enables Rx Clock gating in CDR */ + set_nbmisc_enable_bits(nb_dev, 0x34, 1 << 10/* | 1 << 22 */, 1 << 10/* | 1 << 22 */); + + /* 5.9.12.15. Sets number of TX Clocks to drain TX Pipe to 3. */ + set_pcie_enable_bits(dev, 0xA0, 0xF << 4, 3 << 4); + + /* 5.9.12.16. Lets PI use Electrical Idle from PHY when + * turning off PLL in L1 at Gen2 speed instead Inferred Electrical Idle. */ + set_pcie_enable_bits(nb_dev, 0x40, 3 << 14, 2 << 14); + + /* 5.9.12.17. Prevents the Electrical Idle from causing a transition from Rcv_L0 to Rcv_L0s. */ + set_pcie_enable_bits(dev, 0xB1, 1 << 20, 1 << 20); + + /* 5.9.12.18. Prevents the LTSSM from going to Rcv_L0s if it has already + * acknowledged a request to go to L1. */ + set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11); + + /* 5.9.12.19. LDSK only taking deskew on deskewing error detect */ + set_pcie_enable_bits(nb_dev, 0x40, 1 << 28, 0 << 28); + + /* 5.9.12.20. Bypasses lane de-skew logic if in x1 */ + set_pcie_enable_bits(nb_dev, 0xC2, 1 << 14, 1 << 14); + + /* 5.9.12.21. Sets Electrical Idle Threshold. */ + set_nbmisc_enable_bits(nb_dev, 0x35, 3 << 21, 2 << 21); + + /* 5.9.12.22. Advertises -6 dB de-emphasis value in TS1 Data Rate Identifier + * Only if CMOS Option in section. skip */ + + /* 5.9.12.23. Disables GEN2 capability of the device. */ + set_pcie_enable_bits(dev, 0xA4, 1 << 0, 0 << 0); + + /* 5.9.12.24.Disables advertising Upconfigure Support. */ + set_pcie_enable_bits(dev, 0xA2, 1 << 13, 1 << 13); + + /* 5.9.12.25. No comment in RPR. */ + set_nbmisc_enable_bits(nb_dev, 0x39, 1 << 10, 0 << 10); + + /* 5.9.12.26. This capacity is required since links wider than x1 and/or multiple link + * speed are supported */ + set_pcie_enable_bits(nb_dev, 0xC1, 1 << 0, 1 << 0); + + /* 5.9.12.27. Enables NVG86 ECO. A13 above only. */ + if (get_nb_rev(nb_dev) == REV_RS780_A12) /* A12 */ + set_pcie_enable_bits(dev, 0x02, 1 << 11, 1 << 11); + + /* 5.9.12.28 Hides and disables the completion timeout method. */ + set_pcie_enable_bits(nb_dev, 0xC1, 1 << 2, 0 << 2); + + /* 5.9.12.29. Use the bif_core de-emphasis strength by default. */ + /* set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 28, 1 << 28); */ + + /* 5.9.12.30. Set TX arbitration algorithm to round robin */ + set_pcie_enable_bits(nb_dev, 0x1C, + 1 << 0 | 0x1F << 1 | 0x1F << 6, + 1 << 0 | 0x04 << 1 | 0x04 << 6); + + /* Single-port/Dual-port configureation. */ + switch (cfg->gfx_dual_slot) { + case 0: + /* step 1, lane reversal (only need if build config option is enabled) */ + if (cfg->gfx_lane_reversal) { + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); + set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); + } + printk(BIOS_DEBUG, "rs780_gfx_init step1.\n"); + + printk(BIOS_DEBUG, "device = %x\n", dev->path.pci.devfn >> 3); + if((dev->path.pci.devfn >> 3) == 2) { + single_port_configuration(nb_dev, dev); + } else { + set_nbmisc_enable_bits(nb_dev, 0xc, 0, 0x2 << 2); /* hide the GFX bridge. */ + printk(BIOS_INFO, "Single port. Do nothing.\n"); // If dev3 + } + + break; + case 1: + /* step 1, lane reversal (only need if build config option is enabled) */ + if (cfg->gfx_lane_reversal) { + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); + set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); + set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 3, 1 << 3); + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); + } + printk(BIOS_DEBUG, "rs780_gfx_init step1.\n"); + /* step 1.1, dual-slot gfx configuration (only need if CMOS option is enabled) */ + /* AMD calls the configuration CrossFire */ + set_nbmisc_enable_bits(nb_dev, 0x0, 0xf << 8, 5 << 8); + printk(BIOS_DEBUG, "rs780_gfx_init step2.\n"); + + printk(BIOS_DEBUG, "device = %x\n", dev->path.pci.devfn >> 3); + dual_port_configuration(nb_dev, dev); + break; + + case 2: + + if(is_dev3_present()){ + /* step 1, lane reversal (only need if CMOS option is enabled) */ + if (cfg->gfx_lane_reversal) { + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); + set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); + set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 3, 1 << 3); + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); + } + printk(BIOS_DEBUG, "rs780_gfx_init step1.\n"); + /* step 1.1, dual-slot gfx configuration (only need if CMOS option is enabled) */ + /* AMD calls the configuration CrossFire */ + set_nbmisc_enable_bits(nb_dev, 0x0, 0xf << 8, 5 << 8); + printk(BIOS_DEBUG, "rs780_gfx_init step2.\n"); + + + printk(BIOS_DEBUG, "device = %x\n", dev->path.pci.devfn >> 3); + dual_port_configuration(nb_dev, dev); + + }else{ + if (cfg->gfx_lane_reversal) { + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); + set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); + } + printk(BIOS_DEBUG, "rs780_gfx_init step1.\n"); + + if((dev->path.pci.devfn >> 3) == 2) + single_port_configuration(nb_dev, dev); + else{ + set_nbmisc_enable_bits(nb_dev, 0xc, 0, 0x2 << 2); /* hide the GFX bridge. */ + printk(BIOS_DEBUG, "If dev3.., single port. Do nothing.\n"); + } + } + + default: + printk(BIOS_INFO, "Incorrect configuration of external GFX slot.\n"); + break; + } +} diff --git a/src/southbridge/amd/rs780/ht.c b/src/southbridge/amd/rs780/ht.c new file mode 100644 index 0000000000..03d4f84645 --- /dev/null +++ b/src/southbridge/amd/rs780/ht.c @@ -0,0 +1,90 @@ +/* + * 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 +#include +#include +#include +#include +#include "rs780.h" + +/* for UMA internal graphics */ +void avoid_lpc_dma_deadlock(device_t nb_dev, device_t sb_dev) +{ + device_t cpu_f0; + u8 reg; + + cpu_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); + set_nbcfg_enable_bits(cpu_f0, 0x68, 3 << 21, 1 << 21); + + reg = nbpcie_p_read_index(sb_dev, 0x10); + reg |= 0x100; /* bit9=1 */ + nbpcie_p_write_index(sb_dev, 0x10, reg); + + reg = nbpcie_p_read_index(nb_dev, 0x10); + reg |= 0x100; /* bit9=1 */ + nbpcie_p_write_index(nb_dev, 0x10, reg); + + /* Enable NP protocol over PCIE for memory-mapped writes targeting LPC + * Set this bit to avoid a deadlock condition. */ + reg = htiu_read_index(nb_dev, 0x6); + reg |= 0x1000000; /* bit26 */ + htiu_write_index(nb_dev, 0x6, reg); +} + +static void pcie_init(struct device *dev) +{ + /* Enable pci error detecting */ + u32 dword; + + printk(BIOS_INFO, "pcie_init in rs780_ht.c\n"); + + /* System error enable */ + dword = pci_read_config32(dev, 0x04); + dword |= (1 << 8); /* System error enable */ + dword |= (1 << 30); /* Clear possible errors */ + pci_write_config32(dev, 0x04, dword); + + /* + * 1 is APIC enable + * 18 is enable nb to accept A4 interrupt request from SB. + */ + dword = pci_read_config32(dev, 0x4C); + dword |= 1 << 1 | 1 << 18; /* Clear possible errors */ + pci_write_config32(dev, 0x4C, dword); +} + +static struct pci_operations lops_pci = { + .set_subsystem = pci_dev_set_subsystem, +}; + +static struct device_operations ht_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = pcie_init, + .scan_bus = 0, + .ops_pci = &lops_pci, +}; + +static const struct pci_driver ht_driver __pci_driver = { + .ops = &ht_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_RS780_HT, +}; diff --git a/src/southbridge/amd/rs780/pcie.c b/src/southbridge/amd/rs780/pcie.c new file mode 100644 index 0000000000..9cbd832661 --- /dev/null +++ b/src/southbridge/amd/rs780/pcie.c @@ -0,0 +1,392 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include "rs780.h" + +/*------------------------------------------------ +* Global variable +------------------------------------------------*/ +PCIE_CFG AtiPcieCfg = { + PCIE_ENABLE_STATIC_DEV_REMAP, /* Config */ + 0, /* ResetReleaseDelay */ + 0, /* Gfx0Width */ + 0, /* Gfx1Width */ + 0, /* GfxPayload */ + 0, /* GppPayload */ + 0, /* PortDetect, filled by GppSbInit */ + 0, /* PortHp */ + 0, /* DbgConfig */ + 0, /* DbgConfig2 */ + 0, /* GfxLx */ + 0, /* GppLx */ + 0, /* NBSBLx */ + 0, /* PortSlotInit */ + 0, /* Gfx0Pwr */ + 0, /* Gfx1Pwr */ + 0 /* GppPwr */ +}; + +static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port); +static void ValidatePortEn(device_t nb_dev); + +static void ValidatePortEn(device_t nb_dev) +{ +} + +/***************************************************************** +* Compliant with CIM_33's PCIEPowerOffGppPorts +* Power off unused GPP lines +*****************************************************************/ +static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port) +{ + u32 reg; + u16 state_save; + struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)nb_dev->chip_info; + u8 state = cfg->port_enable; + + if (!(AtiPcieCfg.Config & PCIE_DISABLE_HIDE_UNUSED_PORTS)) + state &= AtiPcieCfg.PortDetect; + state = ~state; + state &= (1 << 4) + (1 << 5) + (1 << 6) + (1 << 7); + state_save = state << 17; + state &= !(AtiPcieCfg.PortHp); + reg = nbmisc_read_index(nb_dev, 0x0c); + reg |= state; + nbmisc_write_index(nb_dev, 0x0c, reg); + + reg = nbmisc_read_index(nb_dev, 0x08); + reg |= state_save; + nbmisc_write_index(nb_dev, 0x08, reg); + + if ((AtiPcieCfg.Config & PCIE_OFF_UNUSED_GPP_LANES) + && !(AtiPcieCfg. + Config & (PCIE_DISABLE_HIDE_UNUSED_PORTS + + PCIE_GFX_COMPLIANCE))) { + } + /* step 3 Power Down Control for Southbridge */ + reg = nbpcie_p_read_index(dev, 0xa2); + + switch ((reg >> 4) & 0x7) { /* get bit 4-6, LC_LINK_WIDTH_RD */ + case 1: + nbpcie_ind_write_index(nb_dev, 0x65, 0x0e0e); + break; + case 2: + nbpcie_ind_write_index(nb_dev, 0x65, 0x0c0c); + break; + default: + break; + } +} + +/********************************************************************** +**********************************************************************/ +static void switching_gppsb_configurations(device_t nb_dev, device_t sb_dev) +{ + u32 reg; + struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)nb_dev->chip_info; + + /* 5.5.7.1-3 enables GPP reconfiguration */ + reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7); + reg |= + (RECONFIG_GPPSB_EN + RECONFIG_GPPSB_LINK_CONFIG + + RECONFIG_GPPSB_ATOMIC_RESET); + nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg); + + /* 5.5.7.4a. De-asserts STRAP_BIF_all_valid for PCIE-GPPSB core */ + reg = nbmisc_read_index(nb_dev, 0x66); + reg |= 1 << 31; + nbmisc_write_index(nb_dev, 0x66, reg); + /* 5.5.7.4b. sets desired GPPSB configurations, bit4-7 */ + reg = nbmisc_read_index(nb_dev, 0x67); + reg &= 0xFFFFff0f; /* clean */ + reg |= cfg->gppsb_configuration << 4; + nbmisc_write_index(nb_dev, 0x67, reg); + +#if 1 + /* NOTE: + * In CIMx 4.5.0 and RPR, 4c is done before 5 & 6. But in this way, + * a x4 device in port B (dev 4) of Configuration B can only be detected + * as x1, instead of x4. When the port B is being trained, the + * LC_CURRENT_STATE is 6 and the LC_LINK_WIDTH_RD is 1. We have + * to set the PCIEIND:0x65 as 0xE0E0 and reset the slot. Then the card + * seems to work in x1 mode. + * In the 2nd way below, we do the 5 & 6 before 4c. it conforms the + * CIMx 4.3.0. It conflicts with RPR. But based on the test result I've + * made so far, I haven't found any mistake. + */ + /* 5.5.7.4c. Asserts STRAP_BIF_all_valid for PCIE-GPPSB core */ + reg = nbmisc_read_index(nb_dev, 0x66); + reg &= ~(1 << 31); + nbmisc_write_index(nb_dev, 0x66, reg); + + /* 5.5.7.5-6. read bit14 and write back its inverst value */ + reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7); + reg ^= RECONFIG_GPPSB_GPPSB; + nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg); +#else + /* 5.5.7.5-6. read bit14 and write back its inverst value */ + reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7); + reg ^= RECONFIG_GPPSB_GPPSB; + nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg); + + /* 5.5.7.4c. Asserts STRAP_BIF_all_valid for PCIE-GPPSB core */ + reg = nbmisc_read_index(nb_dev, 0x66); + reg &= ~(1 << 31); + nbmisc_write_index(nb_dev, 0x66, reg); +#endif + /* 5.5.7.7. delay 1ms */ + mdelay(1); + + /* 5.5.7.8. waits until SB has trained to L0, poll for bit0-5 = 0x10 */ + do { + reg = nbpcie_p_read_index(sb_dev, PCIE_LC_STATE0); + reg &= 0x3f; /* remain LSB [5:0] bits */ + } while (LC_STATE_RECONFIG_GPPSB != reg); + + /* 5.5.7.9.ensures that virtual channel negotiation is completed. poll for bit1 = 0 */ + do { + reg = + pci_ext_read_config32(nb_dev, sb_dev, + PCIE_VC0_RESOURCE_STATUS); + } while (reg & VC_NEGOTIATION_PENDING); +} + +static void switching_gpp_configurations(device_t nb_dev, device_t sb_dev) +{ + u32 reg; + struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)nb_dev->chip_info; + + /* 5.6.2.1. De-asserts STRAP_BIF_all_valid for PCIE-GPP core */ + reg = nbmisc_read_index(nb_dev, 0x22); + reg |= 1 << 14; + nbmisc_write_index(nb_dev, 0x22, reg); + /* 5.6.2.2. sets desired GPPSB configurations, bit4-7 */ + reg = nbmisc_read_index(nb_dev, 0x2D); + reg &= ~(0xF << 7); /* clean */ + reg |= cfg->gpp_configuration << 7; + nbmisc_write_index(nb_dev, 0x2D, reg); + /* 5.6.2.3. Asserts STRAP_BIF_all_valid for PCIE-GPP core */ + reg = nbmisc_read_index(nb_dev, 0x22); + reg &= ~(1 << 14); + nbmisc_write_index(nb_dev, 0x22, reg); +} + +/***************************************************************** +* The rs780 uses NBCONFIG:0x1c (BAR3) to map the PCIE Extended Configuration +* Space to a 256MB range within the first 4GB of addressable memory. +*****************************************************************/ +void enable_pcie_bar3(device_t nb_dev) +{ + printk(BIOS_DEBUG, "enable_pcie_bar3()\n"); + set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 1 << 30); /* Enables writes to the BAR3 register. */ + set_nbcfg_enable_bits(nb_dev, 0x84, 7 << 16, 0 << 16); + + pci_write_config32(nb_dev, 0x1C, EXT_CONF_BASE_ADDRESS); /* PCIEMiscInit */ + pci_write_config32(nb_dev, 0x20, 0x00000000); + set_htiu_enable_bits(nb_dev, 0x32, 1 << 28, 1 << 28); /* PCIEMiscInit */ + ProgK8TempMmioBase(1, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS); +} + +/***************************************************************** +* We should disable bar3 when we want to exit rs780_enable, because bar3 will be +* remapped in set_resource later. +*****************************************************************/ +void disable_pcie_bar3(device_t nb_dev) +{ + printk(BIOS_DEBUG, "disable_pcie_bar3()\n"); + pci_write_config32(nb_dev, 0x1C, 0); /* clear BAR3 address */ + set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 0 << 30); /* Disable writes to the BAR3. */ + set_htiu_enable_bits(nb_dev, 0x32, 1 << 28, 0); /* disable bar3 decode */ + ProgK8TempMmioBase(0, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS); +} + +/***************************************** +* Compliant with CIM_33's PCIEGPPInit +* nb_dev: +* root bridge struct +* dev: +* p2p bridge struct +* port: +* p2p bridge number, 4-10 +*****************************************/ +void rs780_gpp_sb_init(device_t nb_dev, device_t dev, u32 port) +{ + u32 gfx_gpp_sb_sel; + struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)nb_dev->chip_info; + printk(BIOS_DEBUG, "gpp_sb_init nb_dev=0x%x, dev=0x%x, port=0x%x\n", nb_dev->path.pci.devfn, dev->path.pci.devfn, port); + + gfx_gpp_sb_sel = port >= 4 && port <= 8 ? + PCIE_CORE_INDEX_GPPSB : /* 4,5,6,7,8 */ + PCIE_CORE_INDEX_GPP; /* 9,10 */ + /* init GPP core */ + /* 5.10.8.3. Disable slave ordering logic */ + set_pcie_enable_bits(nb_dev, 0x20 | gfx_gpp_sb_sel, 1 << 8, + 1 << 8); + /* 5.10.8.7. PCIE initialization 5.10.2: rpr 2.12*/ + set_pcie_enable_bits(nb_dev, 0x02 | gfx_gpp_sb_sel, 1 << 0, 1 << 0); /* no description in datasheet. */ + + /* init GPPSB port. rpr 5.10.8 */ + /* 5.10.8.1-5.10.8.2. Sets RCB timeout to be 100ms/4=25ms by setting bits[18:16] to 3 h4 + * and shortens the enumeration timer by setting bit[19] to 1 + */ + set_pcie_enable_bits(dev, 0x70, 0xF << 16, 0x4 << 16 | 1 << 19); + /* 5.10.8.4. Sets DMA payload size to 64 bytes. */ + set_pcie_enable_bits(nb_dev, 0x10 | gfx_gpp_sb_sel, 7 << 10, 4 << 10); + /* 5.10.8.6. Disable RC ordering logic */ + set_pcie_enable_bits(nb_dev, 0x20 | gfx_gpp_sb_sel, 1 << 9, 1 << 9); + /* 5.10.8.7. Ignores DLLs druing L1 */ + set_pcie_enable_bits(nb_dev, 0x02 | gfx_gpp_sb_sel, 1 << 0, 1 << 0); + /* 5.10.8.8. Prevents LCto go from L0 to Rcv_L0s if L1 is armed. */ + set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11); + /* 5.10.8.9. Sets timer in Config state from 20us to 1us. + * 5.10.8.10. De-asserts RX_EN in L0s + * 5.10.8.11. Enables de-assertion of PG2RX_CR_EN to lock clock recovery parameter when .. */ + set_pcie_enable_bits(dev, 0xB1, 1 << 23 | 1 << 19 | 1 << 28, 1 <<23 | 1 << 19 | 1 << 28); + /* 5.10.8.12. Turns off offset calibration */ + /* 5.10.8.13. Enables Rx Clock gating in CDR */ + if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB) + set_nbmisc_enable_bits(nb_dev, 0x67, 1 << 14 | 1 << 26, 1 << 14 | 1 << 26); /* 4,5,6,7 */ + else + set_nbmisc_enable_bits(nb_dev, 0x24, 1 << 29 | 1 << 28, 1 << 29 | 1 << 28); /* 9,10 */ + /* 5.10.8.14. Sets number of TX Clocks to drain TX Pipe to 3 */ + set_pcie_enable_bits(dev, 0xA0, 0xF << 4, 0x3 << 4); + /* 5.10.8.15. empty */ + /* 5.10.8.16. P_ELEC_IDLE_MODE */ + set_pcie_enable_bits(nb_dev, 0x40 | gfx_gpp_sb_sel, 0x3 << 14, 0x2 << 14); + /* 5.10.8.17. LC_BLOCK_EL_IDLE_IN_L0 */ + set_pcie_enable_bits(dev, 0xB1, 1 << 20, 1 << 20); + /* 5.10.8.18. LC_DONT_GO_TO_L0S_IFL1_ARMED */ + set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11); + /* 5.10.8.19. RXP_REALIGN_ON_EACH_TSX_OR_SKP */ + set_pcie_enable_bits(nb_dev, 0x40 | gfx_gpp_sb_sel, 1 << 28, 0 << 28); + /* 5.10.8.20. Bypass lane de-skew logic if in x1 */ + set_pcie_enable_bits(nb_dev, 0xC2 | gfx_gpp_sb_sel, 1 << 14, 1 << 14); + /* 5.10.8.21. sets electrical idle threshold. */ + if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB) + set_nbmisc_enable_bits(nb_dev, 0x6A, 3 << 22, 2 << 22); + else + set_nbmisc_enable_bits(nb_dev, 0x24, 3 << 16, 2 << 16); + + /* 5.10.8.22. Disable GEN2 */ + /* TODO: should be 2 seperated cases. */ + set_nbmisc_enable_bits(nb_dev, 0x39, 1 << 31, 0 << 31); + set_nbmisc_enable_bits(nb_dev, 0x22, 1 << 5, 0 << 5); + set_nbmisc_enable_bits(nb_dev, 0x34, 1 << 31, 0 << 31); + set_nbmisc_enable_bits(nb_dev, 0x37, 7 << 5, 0 << 5); + /* 5.10.8.23. Disables GEN2 capability of the device. RPR says enable? No! */ + set_pcie_enable_bits(dev, 0xA4, 1 << 0, 0 << 0); + /* 5.10.8.24. Disable advertising upconfigure support. */ + set_pcie_enable_bits(dev, 0xA2, 1 << 13, 1 << 13); + /* 5.10.8.25-26. STRAP_BIF_DSN_EN */ + if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB) + set_nbmisc_enable_bits(nb_dev, 0x68, 1 << 19, 0 << 19); + else + set_nbmisc_enable_bits(nb_dev, 0x22, 1 << 3, 0 << 3); + /* 5.10.8.27-28. */ + set_pcie_enable_bits(nb_dev, 0xC1 | gfx_gpp_sb_sel, 1 << 0 | 1 << 2, 1 << 0 | 0 << 2); + /* 5.10.8.29. Uses the bif_core de-emphasis strength by default. */ + if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB) { + set_nbmisc_enable_bits(nb_dev, 0x67, 1 << 10, 1 << 10); + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 29, 1 << 29); + } + else { + set_nbmisc_enable_bits(nb_dev, 0x39, 1 << 30, 1 << 30); + } + /* 5.10.8.30. Set TX arbitration algorithm to round robin. */ + set_pcie_enable_bits(nb_dev, 0x1C | gfx_gpp_sb_sel, + 1 << 0 | 0x1F << 1 | 0x1F << 6, + 1 << 0 | 0x04 << 1 | 0x04 << 6); + + /* check compliance rpr step 2.1*/ + if (AtiPcieCfg.Config & PCIE_GPP_COMPLIANCE) { + u32 tmp; + tmp = nbmisc_read_index(nb_dev, 0x67); + tmp |= 1 << 3; + nbmisc_write_index(nb_dev, 0x67, tmp); + } + + /* step 5: dynamic slave CPL buffer allocation. Disable it, otherwise linux hangs. Why? */ + /* set_pcie_enable_bits(nb_dev, 0x20 | gfx_gpp_sb_sel, 1 << 11, 1 << 11); */ + + /* step 5a: Training for GPP devices */ + /* init GPP */ + switch (port) { + case 4: /* GPP */ + case 5: + case 6: + case 7: + case 9: + case 10: + /* 5.10.8.5. Blocks DMA traffic during C3 state */ + set_pcie_enable_bits(dev, 0x10, 1 << 0, 0 << 0); + /* Enabels TLP flushing */ + set_pcie_enable_bits(dev, 0x20, 1 << 19, 0 << 19); + + /* check port enable */ + if (cfg->port_enable & (1 << port)) { + PcieReleasePortTraining(nb_dev, dev, port); + if (!(AtiPcieCfg.Config & PCIE_GPP_COMPLIANCE)) { + u8 res = PcieTrainPort(nb_dev, dev, port); + printk(BIOS_DEBUG, "PcieTrainPort port=0x%x result=%d\n", port, res); + if (res) { + AtiPcieCfg.PortDetect |= 1 << port; + } + } + } + break; + case 8: /* SB */ + break; + } + PciePowerOffGppPorts(nb_dev, dev, port); +} + +/***************************************** +* Compliant with CIM_33's PCIEConfigureGPPCore +*****************************************/ +void config_gpp_core(device_t nb_dev, device_t sb_dev) +{ + u32 reg; + struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)nb_dev->chip_info; + + reg = nbmisc_read_index(nb_dev, 0x20); + if (AtiPcieCfg.Config & PCIE_ENABLE_STATIC_DEV_REMAP) + reg &= 0xfffffffd; /* set bit1 = 0 */ + else + reg |= 0x2; /* set bit1 = 1 */ + nbmisc_write_index(nb_dev, 0x20, reg); + + reg = nbmisc_read_index(nb_dev, 0x67); /* get STRAP_BIF_LINK_CONFIG_GPPSB at bit 4-7 */ + if (cfg->gppsb_configuration != ((reg >> 4) & 0xf)) + switching_gppsb_configurations(nb_dev, sb_dev); + reg = nbmisc_read_index(nb_dev, 0x2D); /* get STRAP_BIF_LINK_CONFIG_GPP at bit 7-10 */ + if (cfg->gpp_configuration != ((reg >> 7) & 0xf)) + switching_gpp_configurations(nb_dev, sb_dev); + ValidatePortEn(nb_dev); +} diff --git a/src/southbridge/amd/rs780/rev.h b/src/southbridge/amd/rs780/rev.h new file mode 100644 index 0000000000..94ab752f9f --- /dev/null +++ b/src/southbridge/amd/rs780/rev.h @@ -0,0 +1,27 @@ +/* + * 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 __RS780_REV_H__ +#define __RS780_REV_H__ + +#define REV_RS780_A11 0 +#define REV_RS780_A12 1 +#define REV_RS780_A13 2 + +#endif /* __RS780_REV_H__ */ diff --git a/src/southbridge/amd/rs780/rs780.h b/src/southbridge/amd/rs780/rs780.h index c91a4b3022..aba3e6929b 100644 --- a/src/southbridge/amd/rs780/rs780.h +++ b/src/southbridge/amd/rs780/rs780.h @@ -23,7 +23,7 @@ #include #include #include "chip.h" -#include "rs780_rev.h" +#include "rev.h" #define NBMISC_INDEX 0x60 #define NBHTIU_INDEX 0x94 diff --git a/src/southbridge/amd/rs780/rs780_cmn.c b/src/southbridge/amd/rs780/rs780_cmn.c deleted file mode 100644 index 4bd870bbf2..0000000000 --- a/src/southbridge/amd/rs780/rs780_cmn.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - * 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 - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "rs780.h" - -static u32 nb_read_index(device_t dev, u32 index_reg, u32 index) -{ - pci_write_config32(dev, index_reg, index); - return pci_read_config32(dev, index_reg + 0x4); -} - -static void nb_write_index(device_t dev, u32 index_reg, u32 index, u32 data) -{ - pci_write_config32(dev, index_reg, index); - pci_write_config32(dev, index_reg + 0x4, data); -} - -/* extension registers */ -u32 pci_ext_read_config32(device_t nb_dev, device_t dev, u32 reg) -{ - /*get BAR3 base address for nbcfg0x1c */ - u32 addr = pci_read_config32(nb_dev, 0x1c) & ~0xF; - printk(BIOS_DEBUG, "addr=%x,bus=%x,devfn=%x\n", addr, dev->bus->secondary, - dev->path.pci.devfn); - addr |= dev->bus->secondary << 20 | /* bus num */ - dev->path.pci.devfn << 12 | reg; - return *((u32 *) addr); -} - -void pci_ext_write_config32(device_t nb_dev, device_t dev, u32 reg_pos, u32 mask, u32 val) -{ - u32 reg_old, reg; - - /*get BAR3 base address for nbcfg0x1c */ - u32 addr = pci_read_config32(nb_dev, 0x1c) & ~0xF; - /*printk(BIOS_DEBUG, "write: addr=%x,bus=%x,devfn=%x\n", addr, dev->bus->secondary, - dev->path.pci.devfn);*/ - addr |= dev->bus->secondary << 20 | /* bus num */ - dev->path.pci.devfn << 12 | reg_pos; - - reg = reg_old = *((u32 *) addr); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - *((u32 *) addr) = reg; - } -} - -u32 nbmisc_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBMISC_INDEX, (index)); -} - -void nbmisc_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBMISC_INDEX, ((index) | 0x80), (data)); -} - -u32 nbpcie_p_read_index(device_t dev, u32 index) -{ - return nb_read_index((dev), NBPCIE_INDEX, (index)); -} - -void nbpcie_p_write_index(device_t dev, u32 index, u32 data) -{ - nb_write_index((dev), NBPCIE_INDEX, (index), (data)); -} - -u32 nbpcie_ind_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBPCIE_INDEX, (index)); -} - -void nbpcie_ind_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBPCIE_INDEX, (index), (data)); -} - -u32 htiu_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBHTIU_INDEX, (index)); -} - -void htiu_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBHTIU_INDEX, ((index) | 0x100), (data)); -} - -u32 nbmc_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBMC_INDEX, (index)); -} - -void nbmc_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBMC_INDEX, ((index) | 1 << 9), (data)); -} - -void set_nbcfg_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) -{ - u32 reg_old, reg; - reg = reg_old = pci_read_config32(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - pci_write_config32(nb_dev, reg_pos, reg); - } -} - -void set_nbcfg_enable_bits_8(device_t nb_dev, u32 reg_pos, u8 mask, u8 val) -{ - u8 reg_old, reg; - reg = reg_old = pci_read_config8(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - pci_write_config8(nb_dev, reg_pos, reg); - } -} - -void set_nbmc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) -{ - u32 reg_old, reg; - reg = reg_old = nbmc_read_index(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - nbmc_write_index(nb_dev, reg_pos, reg); - } -} - -void set_htiu_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) -{ - u32 reg_old, reg; - reg = reg_old = htiu_read_index(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - htiu_write_index(nb_dev, reg_pos, reg); - } -} - -void set_nbmisc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) -{ - u32 reg_old, reg; - reg = reg_old = nbmisc_read_index(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - nbmisc_write_index(nb_dev, reg_pos, reg); - } -} - -void set_pcie_enable_bits(device_t dev, u32 reg_pos, u32 mask, u32 val) -{ - u32 reg_old, reg; - reg = reg_old = nb_read_index(dev, NBPCIE_INDEX, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - nb_write_index(dev, NBPCIE_INDEX, reg_pos, reg); - } -} - -/*********************************************************** -* To access bar3 we need to program PCI MMIO 7 in K8. -* in_out: -* 1: enable/enter k8 temp mmio base -* 0: disable/restore -***********************************************************/ -void ProgK8TempMmioBase(u8 in_out, u32 pcie_base_add, u32 mmio_base_add) -{ - /* K8 Function1 is address map */ - device_t k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1)); - device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); - - if (in_out) { - u32 dword, sblk; - - /* Get SBLink value (HyperTransport I/O Hub Link ID). */ - dword = pci_read_config32(k8_f0, 0x64); - sblk = (dword >> 8) & 0x3; - - /* Fill MMIO limit/base pair. */ - pci_write_config32(k8_f1, 0xbc, - (((pcie_base_add + 0x10000000 - - 1) >> 8) & 0xffffff00) | 0x80 | (sblk << 4)); - pci_write_config32(k8_f1, 0xb8, (pcie_base_add >> 8) | 0x3); - pci_write_config32(k8_f1, 0xb4, - (((mmio_base_add + 0x10000000 - - 1) >> 8) & 0xffffff00) | (sblk << 4)); - pci_write_config32(k8_f1, 0xb0, (mmio_base_add >> 8) | 0x3); - } else { - pci_write_config32(k8_f1, 0xb8, 0); - pci_write_config32(k8_f1, 0xbc, 0); - pci_write_config32(k8_f1, 0xb0, 0); - pci_write_config32(k8_f1, 0xb4, 0); - } -} - -void PcieReleasePortTraining(device_t nb_dev, device_t dev, u32 port) -{ - switch (port) { - case 2: /* GFX, bit4-5 */ - case 3: - set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG, - 1 << (port + 2), 0 << (port + 2)); - break; - case 4: /* GPPSB, bit20-24 */ - case 5: - case 6: - case 7: - set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG, - 1 << (port + 17), 0 << (port + 17)); - break; - case 9: /* GPP, bit 4,5 of miscind 0x2D */ - case 10: - set_nbmisc_enable_bits(nb_dev, 0x2D, - 1 << (port - 5), 0 << (port - 5)); - break; - } -} - -/******************************************************************************************************** -* Output: -* 0: no device is present. -* 1: device is present and is trained. -********************************************************************************************************/ -u8 PcieTrainPort(device_t nb_dev, device_t dev, u32 port) -{ - u16 count = 5000; - u32 lc_state, reg, current_link_width, lane_mask; - int8_t current, res = 0; - u32 gfx_gpp_sb_sel; - void set_pcie_dereset(void); - void set_pcie_reset(void); - - switch (port) { - case 2 ... 3: - gfx_gpp_sb_sel = PCIE_CORE_INDEX_GFX; - break; - case 4 ... 7: - gfx_gpp_sb_sel = PCIE_CORE_INDEX_GPPSB; - break; - case 9 ... 10: - gfx_gpp_sb_sel = PCIE_CORE_INDEX_GPP; - break; - default: - gfx_gpp_sb_sel = -1; - return 0; - } - - while (count--) { - mdelay(40); - udelay(200); - lc_state = nbpcie_p_read_index(dev, 0xa5); /* lc_state */ - printk(BIOS_DEBUG, "PcieLinkTraining port=%x:lc current state=%x\n", - port, lc_state); - current = lc_state & 0x3f; /* get LC_CURRENT_STATE, bit0-5 */ - - switch (current) { - case 0x00: /* 0x00-0x04 means no device is present */ - case 0x01: - case 0x02: - case 0x03: - case 0x04: - res = 0; - count = 0; - break; - case 0x06: - /* read back current link width [6:4]. */ - current_link_width = (nbpcie_p_read_index(dev, 0xA2) >> 4) & 0x7; - /* 4 means 7:4 and 15:12 - * 3 means 7:2 and 15:10 - * 2 means 7:1 and 15:9 - * egnoring the reversal case - */ - lane_mask = (0xFF << (current_link_width - 2) * 2) & 0xFF; - reg = nbpcie_ind_read_index(nb_dev, 0x65 | gfx_gpp_sb_sel); - reg |= lane_mask << 8 | lane_mask; - reg = 0xE0E0; /* TODO: See the comments in rs780_pcie.c, at about line 145. */ - nbpcie_ind_write_index(nb_dev, 0x65 | gfx_gpp_sb_sel, reg); - printk(BIOS_DEBUG, "link_width=%x, lane_mask=%x", - current_link_width, lane_mask); - set_pcie_reset(); - mdelay(1); - set_pcie_dereset(); - break; - case 0x07: /* device is in compliance state (training sequence is done). Move to train the next device */ - res = 0; - count = 0; - break; - case 0x10: - reg = - pci_ext_read_config32(nb_dev, dev, - PCIE_VC0_RESOURCE_STATUS); - printk(BIOS_DEBUG, "PcieTrainPort reg=0x%x\n", reg); - /* check bit1 */ - if (reg & VC_NEGOTIATION_PENDING) { /* bit1=1 means the link needs to be re-trained. */ - /* set bit8=1, bit0-2=bit4-6 */ - u32 tmp; - reg = - nbpcie_p_read_index(dev, - PCIE_LC_LINK_WIDTH); - tmp = (reg >> 4) && 0x3; /* get bit4-6 */ - reg &= 0xfff8; /* clear bit0-2 */ - reg += tmp; /* merge */ - reg |= 1 << 8; - count++; /* CIM said "keep in loop"? */ - } else { - res = 1; - count = 0; - } - break; - default: /* reset pcie */ - res = 0; - count = 0; /* break loop */ - break; - } - } - return res; -} - -/* -* Compliant with CIM_33's ATINB_SetToms. -* Set Top Of Memory below and above 4G. -*/ -void rs780_set_tom(device_t nb_dev) -{ - extern uint64_t uma_memory_base; - - /* set TOM */ - pci_write_config32(nb_dev, 0x90, uma_memory_base); - //nbmc_write_index(nb_dev, 0x1e, uma_memory_base); -} - -// extract single bit -u32 extractbit(u32 data, int bit_number) -{ - return (data >> bit_number) & 1; -} - -// extract bit field -u32 extractbits(u32 source, int lsb, int msb) -{ - int field_width = msb - lsb + 1; - u32 mask = 0xFFFFFFFF >> (32 - field_width); - return (source >> lsb) & mask; -} - -// return AMD cpuid family -int cpuidFamily(void) -{ - u32 baseFamily, extendedFamily, fms; - - fms = cpuid_eax (1); - baseFamily = extractbits (fms, 8, 11); - extendedFamily = extractbits (fms, 20, 27); - return baseFamily + extendedFamily; -} - - -// return non-zero for AMD family 0Fh processor found -int is_family0Fh(void) -{ - return cpuidFamily() == 0x0F; -} - - -// return non-zero for AMD family 10h processor found -int is_family10h(void) -{ - return cpuidFamily() == 0x10; -} diff --git a/src/southbridge/amd/rs780/rs780_early_setup.c b/src/southbridge/amd/rs780/rs780_early_setup.c deleted file mode 100644 index 57a7b62427..0000000000 --- a/src/southbridge/amd/rs780/rs780_early_setup.c +++ /dev/null @@ -1,675 +0,0 @@ -/* - * 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 CONFIG_NORTHBRIDGE_AMD_AMDFAM10 -#define CONFIG_NORTHBRIDGE_AMD_AMDFAM10 0 -#endif - -#include "rs780_rev.h" - -#define NBHTIU_INDEX 0x94 /* Note: It is different with RS690, whose HTIU index is 0xA8 */ -#define NBMISC_INDEX 0x60 -#define NBMC_INDEX 0xE8 - -static u32 nb_read_index(device_t dev, u32 index_reg, u32 index) -{ - pci_write_config32(dev, index_reg, index); - return pci_read_config32(dev, index_reg + 0x4); -} - -static void nb_write_index(device_t dev, u32 index_reg, u32 index, u32 data) -{ - pci_write_config32(dev, index_reg, index /* | 0x80 */ ); - pci_write_config32(dev, index_reg + 0x4, data); -} - -static u32 nbmisc_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBMISC_INDEX, (index)); -} - -static void nbmisc_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBMISC_INDEX, ((index) | 0x80), (data)); -} - -static u32 htiu_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBHTIU_INDEX, (index)); -} - -static void htiu_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBHTIU_INDEX, ((index) | 0x100), (data)); -} - -static u32 nbmc_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBMC_INDEX, (index)); -} - -static void nbmc_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBMC_INDEX, ((index) | 1 << 9), (data)); -} - -static void set_htiu_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, - u32 val) -{ - u32 reg_old, reg; - reg = reg_old = htiu_read_index(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - htiu_write_index(nb_dev, reg_pos, reg); - } -} - -static void set_nbmisc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, - u32 val) -{ - u32 reg_old, reg; - reg = reg_old = nbmisc_read_index(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - nbmisc_write_index(nb_dev, reg_pos, reg); - } -} - -static void set_nbcfg_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, - u32 val) -{ - u32 reg_old, reg; - reg = reg_old = pci_read_config32(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - pci_write_config32(nb_dev, reg_pos, reg); - } -} -/* family 10 only, for reg > 0xFF */ -#if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 -static void set_fam10_ext_cfg_enable_bits(device_t fam10_dev, u32 reg_pos, u32 mask, - u32 val) -{ - u32 reg_old, reg; - reg = reg_old = Get_NB32(fam10_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - Set_NB32(fam10_dev, reg_pos, reg); - } -} -#else -#define set_fam10_ext_cfg_enable_bits(a, b, c, d) do {} while (0) -#endif - - -static void set_nbcfg_enable_bits_8(device_t nb_dev, u32 reg_pos, u8 mask, - u8 val) -{ - u8 reg_old, reg; - reg = reg_old = pci_read_config8(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - pci_write_config8(nb_dev, reg_pos, reg); - } -} - -static void set_nbmc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, - u32 val) -{ - u32 reg_old, reg; - reg = reg_old = nbmc_read_index(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - nbmc_write_index(nb_dev, reg_pos, reg); - } -} - -static void get_cpu_rev(void) -{ - u32 eax; - - eax = cpuid_eax(1); - printk(BIOS_INFO, "get_cpu_rev EAX=0x%x.\n", eax); - if (eax <= 0xfff) - printk(BIOS_INFO, "CPU Rev is K8_Cx.\n"); - else if (eax <= 0x10fff) - printk(BIOS_INFO, "CPU Rev is K8_Dx.\n"); - else if (eax <= 0x20fff) - printk(BIOS_INFO, "CPU Rev is K8_Ex.\n"); - else if (eax <= 0x40fff) - printk(BIOS_INFO, "CPU Rev is K8_Fx.\n"); - else if (eax == 0x60fb1 || eax == 0x60f81) /*These two IDS are exception, they are G1. */ - printk(BIOS_INFO, "CPU Rev is K8_G1.\n"); - else if (eax <= 0X60FF0) - printk(BIOS_INFO, "CPU Rev is K8_G0.\n"); - else if (eax <= 0x100000) - printk(BIOS_INFO, "CPU Rev is K8_G1.\n"); - else if (eax <= 0x100f00) - printk(BIOS_INFO, "CPU Rev is Fam 10.\n"); - else - printk(BIOS_INFO, "CPU Rev is K8_10.\n"); -} - -static u8 is_famly10(void) -{ - return (cpuid_eax(1) & 0xff00000) != 0; -} - -#if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 /* save some spaces */ -static u8 l3_cache(void) -{ - return (cpuid_edx(0x80000006) & (0x3FFF << 18)) != 0; -} - -static u8 cpu_core_number(void) -{ - return (cpuid_ecx(0x80000008) & 0xFF) + 1; -} -#endif - -static u8 get_nb_rev(device_t nb_dev) -{ - u8 reg; - reg = pci_read_config8(nb_dev, 0x89); /* copy from CIM, can't find in doc */ - switch(reg & 3) - { - case 0x01: - reg = REV_RS780_A12; - break; - case 0x02: - reg = REV_RS780_A13; - break; - default: - reg = REV_RS780_A11; - break; - } - return reg; -} - -/***************************************** - * Init HT link speed/width for rs780 -- k8 link - * 1: Check CPU Family, Family10? - * 2: Get CPU's HT speed and width - * 3: Decide HT mode 1 or 3 by HT Speed. >1GHz: HT3, else HT1 - *****************************************/ -static const u8 rs780_ibias[] = { - /* 1, 3 are reserved. */ - [0x0] = 0x4C, /* 200Mhz HyperTransport 1 only */ - [0x2] = 0x4C, /* 400Mhz HyperTransport 1 only */ - [0x4] = 0xB6, /* 600Mhz HyperTransport 1 only */ - [0x5] = 0x4C, /* 800Mhz HyperTransport 1 only */ - [0x6] = 0x9D, /* 1Ghz HyperTransport 1 only */ - /* HT3 for Family 10 */ - [0x7] = 0xB6, /* 1.2Ghz HyperTransport 3 only */ - [0x8] = 0x2B, /* 1.4Ghz HyperTransport 3 only */ - [0x9] = 0x4C, /* 1.6Ghz HyperTransport 3 only */ - [0xa] = 0x6C, /* 1.8Ghz HyperTransport 3 only */ - [0xb] = 0x9D, /* 2.0Ghz HyperTransport 3 only */ - [0xc] = 0xAD, /* 2.2Ghz HyperTransport 3 only */ - [0xd] = 0xB6, /* 2.4Ghz HyperTransport 3 only */ - [0xe] = 0xC6, /* 2.6Ghz HyperTransport 3 only */ -}; - -static void rs780_htinit(void) -{ - /* - * About HT, it has been done in enumerate_ht_chain(). - */ - device_t cpu_f0, rs780_f0, clk_f1; - u32 reg; - u8 cpu_ht_freq, ibias; - - cpu_f0 = PCI_DEV(0, 0x18, 0); - /************************ - * get cpu's ht freq, in cpu's function 0, offset 0x88 - * bit11-8, specifics the maximum operation frequency of the link's transmitter clock. - * The link frequency field (Frq) is cleared by cold reset. SW can write a nonzero - * value to this reg, and that value takes effect on the next warm reset or - * LDTSTOP_L disconnect sequence. - * please see the table rs780_ibias about the value and its corresponding frequency. - ************************/ - reg = pci_read_config32(cpu_f0, 0x88); - cpu_ht_freq = (reg & 0xf00) >> 8; - printk(BIOS_INFO, "rs780_htinit cpu_ht_freq=%x.\n", cpu_ht_freq); - rs780_f0 = PCI_DEV(0, 0, 0); - //set_nbcfg_enable_bits(rs780_f0, 0xC8, 0x7<<24 | 0x7<<28, 1<<24 | 1<<28); - - clk_f1 = PCI_DEV(0, 0, 1); /* We need to make sure the F1 is accessible. */ - - ibias = rs780_ibias[cpu_ht_freq]; - - /* If HT freq>1GHz, we assume the CPU is fam10, else it is K8. - * Is it appropriate? - * Frequency is 1GHz, i.e. cpu_ht_freq is 6, in most cases. - * So we check 6 only, it would be faster. */ - if ((cpu_ht_freq == 0x6) || (cpu_ht_freq == 0x5) || (cpu_ht_freq == 0x4) || - (cpu_ht_freq == 0x2) || (cpu_ht_freq == 0x0)) { - printk(BIOS_INFO, "rs780_htinit: HT1 mode\n"); - - /* HT1 mode, RPR 8.4.2 */ - /* set IBIAS code */ - set_nbcfg_enable_bits(clk_f1, 0xD8, 0x3FF, ibias); - /* Optimizes chipset HT transmitter drive strength */ - set_htiu_enable_bits(rs780_f0, 0x2A, 0x3, 0x1); - } else if ((cpu_ht_freq > 0x6) && (cpu_ht_freq < 0xf)) { - printk(BIOS_INFO, "rs780_htinit: HT3 mode\n"); - - #if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 /* save some spaces */ - /* HT3 mode, RPR 8.4.3 */ - set_nbcfg_enable_bits(rs780_f0, 0x9c, 0x3 << 16, 0); - - /* set IBIAS code */ - set_nbcfg_enable_bits(clk_f1, 0xD8, 0x3FF, ibias); - /* Optimizes chipset HT transmitter drive strength */ - set_htiu_enable_bits(rs780_f0, 0x2A, 0x3, 0x1); - /* Enables error-retry mode */ - set_nbcfg_enable_bits(rs780_f0, 0x44, 0x1, 0x1); - /* Enables scrambling and Disalbes command throttling */ - set_nbcfg_enable_bits(rs780_f0, 0xac, (1 << 3) | (1 << 14), (1 << 3) | (1 << 14)); - /* Enables transmitter de-emphasis */ - set_nbcfg_enable_bits(rs780_f0, 0xa4, 1 << 31, 1 << 31); - /* Enabels transmitter de-emphasis level */ - /* Sets training 0 time */ - set_nbcfg_enable_bits(rs780_f0, 0xa0, 0x3F, 0x14); - - /* Enables strict TM4 detection */ - set_htiu_enable_bits(rs780_f0, 0x15, 0x1 << 22, 0x1 << 22); - /* Enables proprer DLL reset sequence */ - set_htiu_enable_bits(rs780_f0, 0x16, 0x1 << 10, 0x1 << 10); - - /* HyperTransport 3 Processor register settings to be done in northbridge */ - /* Enables error-retry mode */ - set_fam10_ext_cfg_enable_bits(cpu_f0, 0x130, 1 << 0, 1 << 0); - /* Enables scrambling */ - set_fam10_ext_cfg_enable_bits(cpu_f0, 0x170, 1 << 3, 1 << 3); - /* Enables transmitter de-emphasis - * This depends on the PCB design and the trace */ - /* TODO: */ - /* Disables command throttling */ - set_fam10_ext_cfg_enable_bits(cpu_f0, 0x168, 1 << 10, 1 << 10); - /* Sets Training 0 Time. See T0Time table for encodings */ - set_fam10_ext_cfg_enable_bits(cpu_f0, 0x16C, 0x3F, 0x20); - /* TODO: */ - #endif /* #if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 */ - } -} - -#if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 != 1 /* save some spaces */ -/******************************************************* -* Optimize k8 with UMA. -* See BKDG_NPT_0F guide for details. -* The processor node is addressed by its Node ID on the HT link and can be -* accessed with a device number in the PCI configuration space on Bus0. -* The Node ID 0 is mapped to Device 24 (0x18), the Node ID 1 is mapped -* to Device 25, and so on. -* The processor implements configuration registers in PCI configuration -* space using the following four headers -* Function0: HT technology configuration -* Function1: Address map configuration -* Function2: DRAM and HT technology Trace mode configuration -* Function3: Miscellaneous configuration -*******************************************************/ -static void k8_optimization(void) -{ - device_t k8_f0, k8_f2, k8_f3; - msr_t msr; - - printk(BIOS_INFO, "k8_optimization()\n"); - k8_f0 = PCI_DEV(0, 0x18, 0); - k8_f2 = PCI_DEV(0, 0x18, 2); - k8_f3 = PCI_DEV(0, 0x18, 3); - - /* 8.6.6 K8 Buffer Allocation Settings */ - pci_write_config32(k8_f0, 0x90, 0x01700169); /* CIM NPT_Optimization */ - set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 28, 0 << 28); - set_nbcfg_enable_bits(k8_f0, 0x68, 3 << 26, 3 << 26); - set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 11, 1 << 11); - /* set_nbcfg_enable_bits(k8_f0, 0x84, 1 << 11 | 1 << 13 | 1 << 15, 1 << 11 | 1 << 13 | 1 << 15); */ /* TODO */ - - pci_write_config32(k8_f3, 0x70, 0x51220111); - pci_write_config32(k8_f3, 0x74, 0x50404021); - pci_write_config32(k8_f3, 0x78, 0x08002A00); - if (pci_read_config32(k8_f3, 0xE8) & 0x3<<12) - pci_write_config32(k8_f3, 0x7C, 0x0000211A); /* dual core */ - else - pci_write_config32(k8_f3, 0x7C, 0x0000212B); /* single core */ - set_nbcfg_enable_bits_8(k8_f3, 0xDC, 0xFF, 0x25); - - set_nbcfg_enable_bits(k8_f2, 0xA0, 1 << 5, 1 << 5); - set_nbcfg_enable_bits(k8_f2, 0x94, 0xF << 24, 7 << 24); - set_nbcfg_enable_bits(k8_f2, 0x90, 1 << 10, 0 << 10); - set_nbcfg_enable_bits(k8_f2, 0xA0, 3 << 2, 3 << 2); - set_nbcfg_enable_bits(k8_f2, 0xA0, 1 << 5, 1 << 5); - - msr = rdmsr(0xC001001F); - msr.lo &= ~(1 << 9); - msr.hi &= ~(1 << 4); - wrmsr(0xC001001F, msr); -} -#else -#define k8_optimization() do{}while(0) -#endif /* #if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 != 1 */ - -#if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 /* save some spaces */ -static void fam10_optimization(void) -{ - device_t cpu_f0, cpu_f2, cpu_f3; - u32 val; - - printk(BIOS_INFO, "fam10_optimization()\n"); - - cpu_f0 = PCI_DEV(0, 0x18, 0); - cpu_f2 = PCI_DEV(0, 0x18, 2); - cpu_f3 = PCI_DEV(0, 0x18, 3); - - /* 8.6.4.1 */ - /* Table 8-13 */ - pci_write_config32(cpu_f0, 0x90, 0x808502D0); - /* Table 8-14 */ - pci_write_config32(cpu_f0, 0x94, 0x00000000); - - /* Table 8-15 */ - val = pci_read_config32(cpu_f0, 0x68); - val |= 1 << 24; - pci_write_config32(cpu_f0, 0x68, val); - - /* Table 8-16 */ - val = pci_read_config32(cpu_f0, 0x84); - val &= ~(1 << 12); - pci_write_config32(cpu_f0, 0x84, val); - - /* Table 8-17 */ - val = pci_read_config32(cpu_f2, 0x90); - val &= ~(1 << 10); - pci_write_config32(cpu_f2, 0x90, val); - - /* Table 8-18 */ - pci_write_config32(cpu_f3, 0x6C, 0x60018051); - /* Table 8-19 */ - pci_write_config32(cpu_f3, 0x70, 0x60321151); - /* Table 8-20 */ - pci_write_config32(cpu_f3, 0x74, 0x00980101); - /* Table 8-21 */ - pci_write_config32(cpu_f3, 0x78, 0x00200C14); - /* Table 8-22 */ - pci_write_config32(cpu_f3, 0x7C, 0x00070811); /* TODO: Check if L3 Cache is enabled. */ - - /* Table 8-23 */ - Set_NB32(cpu_f3, 0x140, 0x00D33656); - /* Table 8-24 */ - Set_NB32(cpu_f3, 0x144, 0x00000036); - /* Table 8-25 */ - Set_NB32(cpu_f3, 0x148, 0x8000832A); - /* Table 8-26 */ - Set_NB32(cpu_f3, 0x158, 0); - /* L3 Disabled: L3 Enabled: */ - /* cores: 2 3 4 2 3 4 */ - /* bit8:4 28 26 24 24 20 16 */ - if (!l3_cache()) { - Set_NB32(cpu_f3, 0x1A0, 4 << 12 | (24 + 2*(4-cpu_core_number())) << 4 | 2); - } else { - Set_NB32(cpu_f3, 0x1A0, 4 << 12 | (16 + 4*(4-cpu_core_number())) << 4 | 4); - } -} -#else -#define fam10_optimization() do{}while(0) -#endif /* #if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 */ - -/***************************************** -* rs780_por_pcicfg_init() -*****************************************/ -static void rs780_por_pcicfg_init(device_t nb_dev) -{ - /* enable PCI Memory Access */ - set_nbcfg_enable_bits_8(nb_dev, 0x04, (u8)(~0xFD), 0x02); - /* Set RCRB Enable */ - set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xFF), 0x1); - /* allow decode of 640k-1MB */ - set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xEF), 0x10); - /* Enable PM2_CNTL(BAR2) IO mapped cfg write access to be broadcast to both NB and SB */ - set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xFF), 0x4); - /* Power Management Register Enable */ - set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xFF), 0x80); - - /* Reg4Ch[1]=1 (APIC_ENABLE) force cpu request with address 0xFECx_xxxx to south-bridge - * Reg4Ch[6]=1 (BMMsgEn) enable BM_Set message generation - * BMMsgEn */ - set_nbcfg_enable_bits_8(nb_dev, 0x4C, (u8)(~0x00), 0x42 | 1); - - /* Reg4Ch[16]=1 (WakeC2En) enable Wake_from_C2 message generation. - * Reg4Ch[18]=1 (P4IntEnable) Enable north-bridge to accept MSI with address 0xFEEx_xxxx from south-bridge */ - set_nbcfg_enable_bits_8(nb_dev, 0x4E, (u8)(~0xFF), 0x05); - /* Reg94h[4:0] = 0x0 P drive strength offset 0 - * Reg94h[6:5] = 0x2 P drive strength additive adjust */ - set_nbcfg_enable_bits_8(nb_dev, 0x94, (u8)(~0x80), 0x40); - - /* Reg94h[20:16] = 0x0 N drive strength offset 0 - * Reg94h[22:21] = 0x2 N drive strength additive adjust */ - set_nbcfg_enable_bits_8(nb_dev, 0x96, (u8)(~0x80), 0x40); - - /* Reg80h[4:0] = 0x0 Termination offset - * Reg80h[6:5] = 0x2 Termination additive adjust */ - set_nbcfg_enable_bits_8(nb_dev, 0x80, (u8)(~0x80), 0x40); - - /* Reg80h[14] = 0x1 Enable receiver termination control */ - set_nbcfg_enable_bits_8(nb_dev, 0x81, (u8)(~0xFF), 0x40); - - /* Reg94h[15] = 0x1 Enables HT transmitter advanced features to be turned on - * Reg94h[14] = 0x1 Enable drive strength control */ - set_nbcfg_enable_bits_8(nb_dev, 0x95, (u8)(~0x3F), 0xC4); - - /* Reg94h[31:29] = 0x7 Enables HT transmitter de-emphasis */ - set_nbcfg_enable_bits_8(nb_dev, 0x97, (u8)(~0x1F), 0xE0); - - /* Reg8Ch[9] enables Gfx Debug BAR programming - * Reg8Ch[10] enables Gfx Debug BAR operation - * Enable programming of the debug bar now, but enable - * operation only after it has been programmed */ - set_nbcfg_enable_bits_8(nb_dev, 0x8D, (u8)(~0xFF), 0x02); -} - -static void rs780_por_mc_index_init(device_t nb_dev) -{ - set_nbmc_enable_bits(nb_dev, 0x7A, ~0xFFFFFF80, 0x0000005F); - set_nbmc_enable_bits(nb_dev, 0xD8, ~0x00000000, 0x00600060); - set_nbmc_enable_bits(nb_dev, 0xD9, ~0x00000000, 0x00600060); - set_nbmc_enable_bits(nb_dev, 0xE0, ~0x00000000, 0x00000000); - set_nbmc_enable_bits(nb_dev, 0xE1, ~0x00000000, 0x00000000); - set_nbmc_enable_bits(nb_dev, 0xE8, ~0x00000000, 0x003E003E); - set_nbmc_enable_bits(nb_dev, 0xE9, ~0x00000000, 0x003E003E); -} - -static void rs780_por_misc_index_init(device_t nb_dev) -{ - /* NB_MISC_IND_WR_EN + IOC_PCIE_CNTL - * Block non-snoop DMA request if PMArbDis is set. - * Set BMSetDis */ - set_nbmisc_enable_bits(nb_dev, 0x0B, ~0xFFFF0000, 0x00000180); - set_nbmisc_enable_bits(nb_dev, 0x01, ~0xFFFFFFFF, 0x00000040); - - /* NBCFG (NBMISCIND 0x0): NB_CNTL - - * HIDE_NB_AGP_CAP ([0], default=1)HIDE - * HIDE_P2P_AGP_CAP ([1], default=1)HIDE - * HIDE_NB_GART_BAR ([2], default=1)HIDE - * AGPMODE30 ([4], default=0)DISABLE - * AGP30ENCHANCED ([5], default=0)DISABLE - * HIDE_AGP_CAP ([8], default=1)ENABLE */ - set_nbmisc_enable_bits(nb_dev, 0x00, ~0xFFFF0000, 0x00000506); /* set bit 10 for MSI */ - - /* NBMISCIND:0x6A[16]= 1 SB link can get a full swing - * set_nbmisc_enable_bits(nb_dev, 0x6A, 0ffffffffh, 000010000); - * NBMISCIND:0x6A[17]=1 Set CMGOOD_OVERRIDE. */ - set_nbmisc_enable_bits(nb_dev, 0x6A, ~0xffffffff, 0x00020000); - - /* NBMISIND:0x40 Bit[8]=1 and Bit[10]=1 following bits are required to set in order to allow LVDS or PWM features to work. */ - set_nbmisc_enable_bits(nb_dev, 0x40, ~0xffffffff, 0x00000500); - - /* NBMISIND:0xC Bit[13]=1 Enable GSM mode for C1e or C3 with pop-up. */ - set_nbmisc_enable_bits(nb_dev, 0x0C, ~0xffffffff, 0x00002000); - - /* Set NBMISIND:0x1F[3] to map NB F2 interrupt pin to INTB# */ - set_nbmisc_enable_bits(nb_dev, 0x1F, ~0xffffffff, 0x00000008); - - /* - * Enable access to DEV8 - * Enable setPower message for all ports - */ - set_nbmisc_enable_bits(nb_dev, 0x00, 1 << 6, 1 << 6); - set_nbmisc_enable_bits(nb_dev, 0x0b, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x51, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x53, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x55, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x57, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x59, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x5B, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x5D, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x5F, 1 << 20, 1 << 20); - - set_nbmisc_enable_bits(nb_dev, 0x00, 1 << 7, 1 << 7); - set_nbmisc_enable_bits(nb_dev, 0x07, 0x000000f0, 0x30); - - set_nbmisc_enable_bits(nb_dev, 0x01, 0xFFFFFFFF, 0x48); - /* Disable bus-master trigger event from SB and Enable set_slot_power message to SB */ - set_nbmisc_enable_bits(nb_dev, 0x0B, 0xffffffff, 0x500180); -} - -/***************************************** -* Some setting is from rpr. Some is from CIMx. -*****************************************/ -static void rs780_por_htiu_index_init(device_t nb_dev) -{ -#if 0 /* get from rpr. */ - set_htiu_enable_bits(nb_dev, 0x1C, 0x1<<17, 0x1<<17); - set_htiu_enable_bits(nb_dev, 0x06, 0x1<<0, 0x0<<0); - set_htiu_enable_bits(nb_dev, 0x06, 0x1<<1, 0x1<<1); - set_htiu_enable_bits(nb_dev, 0x06, 0x1<<9, 0x1<<9); - set_htiu_enable_bits(nb_dev, 0x06, 0x1<<13, 0x1<<13); - set_htiu_enable_bits(nb_dev, 0x06, 0x1<<17, 0x1<<17); - set_htiu_enable_bits(nb_dev, 0x06, 0x3<<15, 0x3<<15); - set_htiu_enable_bits(nb_dev, 0x06, 0x1<<25, 0x1<<25); - set_htiu_enable_bits(nb_dev, 0x06, 0x1<<30, 0x1<<30); - - set_htiu_enable_bits(nb_dev, 0x07, 0x1<<0, 0x1<<0); - set_htiu_enable_bits(nb_dev, 0x07, 0x1<<1, 0x0<<1); - set_htiu_enable_bits(nb_dev, 0x07, 0x1<<2, 0x0<<2); - set_htiu_enable_bits(nb_dev, 0x07, 0x1<<15, 0x1<<15); - - set_htiu_enable_bits(nb_dev, 0x0C, 0x3<<0, 0x1<<0); - set_htiu_enable_bits(nb_dev, 0x0C, 0x3<<2, 0x2<<2); - set_htiu_enable_bits(nb_dev, 0x0C, 0x3<<4, 0x0<<4); - - /* A12 only */ - set_htiu_enable_bits(nb_dev, 0x2D, 0x1<<4, 0x1<<4); - set_htiu_enable_bits(nb_dev, 0x2D, 0x1<<6, 0x1<<6); - set_htiu_enable_bits(nb_dev, 0x05, 0x1<<2, 0x1<<2); - - set_htiu_enable_bits(nb_dev, 0x1E, 0xFFFFFFFF, 0xFFFFFFFF); -#else /* get from CIM. It is more reliable than above. */ - set_htiu_enable_bits(nb_dev, 0x05, (1<<10|1<<9), 1<<10 | 1<<9); - set_htiu_enable_bits(nb_dev, 0x06, ~0xFFFFFFFE, 0x04203A202); - - set_htiu_enable_bits(nb_dev, 0x07, ~0xFFFFFFF9, 0x8001/* | 7 << 8 */); /* fam 10 */ - - set_htiu_enable_bits(nb_dev, 0x15, ~0xFFFFFFFF, 1<<31| 1<<30 | 1<<27); - set_htiu_enable_bits(nb_dev, 0x1C, ~0xFFFFFFFF, 0xFFFE0000); - - set_htiu_enable_bits(nb_dev, 0x4B, (1<<11), 1<<11); - - set_htiu_enable_bits(nb_dev, 0x0C, ~0xFFFFFFC0, 1<<0|1<<3); - - set_htiu_enable_bits(nb_dev, 0x17, (1<<27|1<<1), 0x1<<1); - set_htiu_enable_bits(nb_dev, 0x17, 0x1 << 30, 0x1<<30); - - set_htiu_enable_bits(nb_dev, 0x19, (0xFFFFF+(1<<31)), 0x186A0+(1<<31)); - - set_htiu_enable_bits(nb_dev, 0x16, (0x3F<<10), 0x7<<10); - - set_htiu_enable_bits(nb_dev, 0x23, 0xFFFFFFF, 1<<28); - - set_htiu_enable_bits(nb_dev, 0x1E, 0xFFFFFFFF, 0xFFFFFFFF); -#endif -} - -/***************************************** -* Configure RS780 registers to power-on default RPR. -* POR: Power On Reset -* RPR: Register Programming Requirements -*****************************************/ -static void rs780_por_init(device_t nb_dev) -{ - printk(BIOS_INFO, "rs780_por_init\n"); - /* ATINB_PCICFG_POR_TABLE, initialize the values for rs780 PCI Config registers */ - rs780_por_pcicfg_init(nb_dev); - - /* ATINB_MCIND_POR_TABLE */ - rs780_por_mc_index_init(nb_dev); - - /* ATINB_MISCIND_POR_TABLE */ - rs780_por_misc_index_init(nb_dev); - - /* ATINB_HTIUNBIND_POR_TABLE */ - rs780_por_htiu_index_init(nb_dev); - - /* ATINB_CLKCFG_PORT_TABLE */ - /* rs780 A11 SB Link full swing? */ -} - -/* enable CFG access to Dev8, which is the SB P2P Bridge */ -static void enable_rs780_dev8(void) -{ - set_nbmisc_enable_bits(PCI_DEV(0, 0, 0), 0x00, 1 << 6, 1 << 6); -} - -static void rs780_before_pci_init(void) -{ -} - -static void rs780_early_setup(void) -{ - device_t nb_dev = PCI_DEV(0, 0, 0); - printk(BIOS_INFO, "rs780_early_setup()\n"); - - get_cpu_rev(); - - /* The printk(BIOS_INFO, s) below cause the system unstable. */ - switch (get_nb_rev(nb_dev)) { - case REV_RS780_A11: - /* printk(BIOS_INFO, "NB Revision is A11.\n"); */ - break; - case REV_RS780_A12: - /* printk(BIOS_INFO, "NB Revision is A12.\n"); */ - break; - case REV_RS780_A13: - /* printk(BIOS_INFO, "NB Revision is A13.\n"); */ - break; - } - - if (is_famly10()) - fam10_optimization(); - else - k8_optimization(); - - rs780_por_init(nb_dev); -} diff --git a/src/southbridge/amd/rs780/rs780_gfx.c b/src/southbridge/amd/rs780/rs780_gfx.c deleted file mode 100644 index 1763c36047..0000000000 --- a/src/southbridge/amd/rs780/rs780_gfx.c +++ /dev/null @@ -1,1340 +0,0 @@ -/* - * 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 - */ - -/* - * for rs780 internal graphics device - * device id of internal grphics: - * RS780: 0x9610 - * RS780C: 0x9611 - * RS780M: 0x9612 - * RS780MC:0x9613 - * RS780E: 0x9615 - * RS785G: 0x9710 - just works, not much tested - */ -#include -#include -#include -#include -#include -#include -#include -#include "rs780.h" -extern int is_dev3_present(void); -void set_pcie_reset(void); -void set_pcie_dereset(void); - -extern uint64_t uma_memory_base, uma_memory_size; - -/* Trust the original resource allocation. Don't do it again. */ -#undef DONT_TRUST_RESOURCE_ALLOCATION -//#define DONT_TRUST_RESOURCE_ALLOCATION - -#define CLK_CNTL_INDEX 0x8 -#define CLK_CNTL_DATA 0xC - -/* The Integrated Info Table. */ -ATOM_INTEGRATED_SYSTEM_INFO_V2 vgainfo; - -#ifdef UNUSED_CODE -static u32 clkind_read(device_t dev, u32 index) -{ - u32 gfx_bar2 = pci_read_config32(dev, 0x18) & ~0xF; - - *(u32*)(gfx_bar2+CLK_CNTL_INDEX) = index & 0x7F; - return *(u32*)(gfx_bar2+CLK_CNTL_DATA); -} -#endif - -static void clkind_write(device_t dev, u32 index, u32 data) -{ - u32 gfx_bar2 = pci_read_config32(dev, 0x18) & ~0xF; - /* printk(BIOS_DEBUG, "gfx bar 2 %02x\n", gfx_bar2); */ - - *(u32*)(gfx_bar2+CLK_CNTL_INDEX) = index | 1<<7; - *(u32*)(gfx_bar2+CLK_CNTL_DATA) = data; -} - -/* -* pci_dev_read_resources thinks it is a IO type. -* We have to force it to mem type. -*/ -static void rs780_gfx_read_resources(device_t dev) -{ - printk(BIOS_DEBUG, "rs780_gfx_read_resources.\n"); - - /* The initial value of 0x24 is 0xFFFFFFFF, which is confusing. - Even if we write 0xFFFFFFFF into it, it will be 0xFFF00000, - which tells us it is a memory address base. - */ - pci_write_config32(dev, 0x24, 0x00000000); - - /* Get the normal pci resources of this device */ - pci_dev_read_resources(dev); - compact_resources(dev); -} - -typedef struct _MMIORANGE -{ - u32 Base; - u32 Limit; - u8 Attribute; -} MMIORANGE; - -MMIORANGE MMIO[8], CreativeMMIO[8]; - -#define CIM_STATUS u32 -#define CIM_SUCCESS 0x00000000 -#define CIM_ERROR 0x80000000 -#define CIM_UNSUPPORTED 0x80000001 -#define CIM_DISABLEPORT 0x80000002 - -#define MMIO_ATTRIB_NP_ONLY 1 -#define MMIO_ATTRIB_BOTTOM_TO_TOP 1<<1 -#define MMIO_ATTRIB_SKIP_ZERO 1<<2 - -#ifdef DONT_TRUST_RESOURCE_ALLOCATION -static MMIORANGE* AllocMMIO(MMIORANGE* pMMIO) -{ - int i; - for (i=0; i<8; i++) { - if (pMMIO[i].Limit == 0) - return &pMMIO[i]; - } - return 0; -} - -static void FreeMMIO(MMIORANGE* pMMIO) -{ - pMMIO->Base = 0; - pMMIO->Limit = 0; -} - -static u32 SetMMIO(u32 Base, u32 Limit, u8 Attribute, MMIORANGE *pMMIO) -{ - int i; - MMIORANGE * TempRange; - for(i=0; i<8; i++) - { - if(pMMIO[i].Attribute != Attribute && Base >= pMMIO[i].Base && Limit <= pMMIO[i].Limit) - { - TempRange = AllocMMIO(pMMIO); - if(TempRange == 0) return 0x80000000; - TempRange->Base = Limit; - TempRange->Limit = pMMIO[i].Limit; - TempRange->Attribute = pMMIO[i].Attribute; - pMMIO[i].Limit = Base; - } - } - TempRange = AllocMMIO(pMMIO); - if(TempRange == 0) return 0x80000000; - TempRange->Base = Base; - TempRange->Limit = Limit; - TempRange->Attribute = Attribute; - return 0; -} - -static u8 FinalizeMMIO(MMIORANGE *pMMIO) -{ - int i, j, n = 0; - for(i=0; i<8; i++) - { - if (pMMIO[i].Base == pMMIO[i].Limit) - { - FreeMMIO(&pMMIO[i]); - continue; - } - for(j=0; j> 8) & 0xFF; - BusEnd = (Value >> 16) & 0xFF; - for(Bus = BusStart; Bus <= BusEnd; Bus++) - { - for(Dev = 0; Dev <= 0x1f; Dev++) - { - tempdev = dev_find_slot(Bus, Dev << 3); - Value = pci_read_config32(tempdev, 0); - printk(BIOS_DEBUG, "Dev ID %x \n", Value); - if((Value & 0xffff) == 0x1102) - {//Creative - //Found Creative SB - u32 MMIOStart = 0xffffffff; - u32 MMIOLimit = 0; - for(Reg = 0x10; Reg < 0x20; Reg+=4) - { - u32 BaseA, LimitA; - BaseA = pci_read_config32(tempdev, Reg); - Value = BaseA; - if(!(Value & 0x01)) - { - Value = Value & 0xffffff00; - if(Value != 0) - { - if(MMIOStart > Value) - MMIOStart = Value; - LimitA = 0xffffffff; - //WritePCI(PciAddress,AccWidthUint32,&LimitA); - pci_write_config32(tempdev, Reg, LimitA); - //ReadPCI(PciAddress,AccWidthUint32,&LimitA); - LimitA = pci_read_config32(tempdev, Reg); - LimitA = Value + (~LimitA + 1); - //WritePCI(PciAddress,AccWidthUint32,&BaseA); - pci_write_config32(tempdev, Reg, BaseA); - if (LimitA > MMIOLimit) - MMIOLimit = LimitA; - } - } - } - printk(BIOS_DEBUG, " MMIOStart %x MMIOLimit %x \n", MMIOStart, MMIOLimit); - if (MMIOStart < MMIOLimit) - { - Status = SetMMIO(MMIOStart>>8, MMIOLimit>>8, 0x80, pMMIO); - if(Status == CIM_ERROR) return Status; - } - } - } - } - if(Status == CIM_SUCCESS) - { - //Lets optimize MMIO - if(FinalizeMMIO(pMMIO) > 4) - { - Status = CIM_ERROR; - } - } - - return Status; -} - -static void ProgramMMIO(MMIORANGE *pMMIO, u8 LinkID, u8 Attribute) -{ - int i, j, n = 7; - device_t k8_f1; - - k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1)); - - for(i = 0; i < 8; i++) - { - int k = 0, MmioReg; - u32 Base = 0; - u32 Limit = 0; - for(j = 0; j < 8; j++) - { - if (Base < pMMIO[j].Base) - { - Base = pMMIO[j].Base; - k = j; - } - } - if(pMMIO[k].Limit != 0) - { - if(Attribute & MMIO_ATTRIB_NP_ONLY && pMMIO[k].Attribute == 0 ) - { - Base = 0; - } - else - { - Base = pMMIO[k].Base | 0x3; - Limit= ((pMMIO[k].Limit - 1) & 0xffffff00) | pMMIO[k].Attribute | (LinkID << 4); - } - FreeMMIO(&pMMIO[k]); - } - if (Attribute & MMIO_ATTRIB_SKIP_ZERO && Base == 0 && Limit == 0) continue; - MmioReg = (Attribute & MMIO_ATTRIB_BOTTOM_TO_TOP)?n:(7-n); - n--; - //RWPCI(PCI_ADDRESS(0,CPU_DEV,CPU_F1,0x80+MmioReg*8),AccWidthUint32 |S3_SAVE,0x0,0x0); - pci_write_config32(k8_f1, 0x80+MmioReg*8, 0); - - //WritePCI(PCI_ADDRESS(0,CPU_DEV,CPU_F1,0x84+MmioReg*8),AccWidthUint32 |S3_SAVE,&Limit); - pci_write_config32(k8_f1, 0x84+MmioReg*8, Limit); - - //WritePCI(PCI_ADDRESS(0,CPU_DEV,CPU_F1,0x80+MmioReg*8),AccWidthUint32 |S3_SAVE,&Base); - pci_write_config32(k8_f1, 0x80+MmioReg*8, Base); - } -} -#endif - -static void internal_gfx_pci_dev_init(struct device *dev) -{ - unsigned char * bpointer; - volatile u32 * GpuF0MMReg; - volatile u32 * pointer; - int i; - u16 command; - u32 value; - u16 deviceid, vendorid; - device_t nb_dev = dev_find_slot(0, 0); - device_t k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2)); - device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); - static const u8 ht_freq_lookup [] = {2, 0, 4, 0, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 0, 0, 28, 30, 32}; - static const u8 ht_width_lookup [] = {8, 16, 0, 0, 2, 4, 0, 0}; - static const u16 memclk_lookup_fam0F [] = {100, 0, 133, 0, 0, 166, 0, 200}; - static const u16 memclk_lookup_fam10 [] = {200, 266, 333, 400, 533, 667, 800, 800}; - - /* We definetely will use this in future. Just leave it here. */ - /*struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)dev->chip_info;*/ - - deviceid = pci_read_config16(dev, PCI_DEVICE_ID); - vendorid = pci_read_config16(dev, PCI_VENDOR_ID); - printk(BIOS_DEBUG, "internal_gfx_pci_dev_init device=%x, vendor=%x.\n", - deviceid, vendorid); - - command = pci_read_config16(dev, 0x04); - command |= 0x7; - pci_write_config16(dev, 0x04, command); - - /* Clear vgainfo. */ - bpointer = (unsigned char *) &vgainfo; - for(i=0; i>8)|((value&0xff000000)>>8); - *(GpuF0MMReg + 0x2c04/4) = ((value&0xff00)<<8); - *(GpuF0MMReg + 0x5428/4) = ((value&0xffff0000)+0x10000)-((value&0xffff)<<16); - *(GpuF0MMReg + 0xF774/4) = 0xffffffff; - *(GpuF0MMReg + 0xF770/4) = 0x00000001; - *(GpuF0MMReg + 0x2000/4) = 0x00000011; - *(GpuF0MMReg + 0x200c/4) = 0x00000020; - *(GpuF0MMReg + 0x2010/4) = 0x10204810; - *(GpuF0MMReg + 0x2010/4) = 0x00204810; - *(GpuF0MMReg + 0x2014/4) = 0x10408810; - *(GpuF0MMReg + 0x2014/4) = 0x00408810; - *(GpuF0MMReg + 0x2414/4) = 0x00000080; - *(GpuF0MMReg + 0x2418/4) = 0x84422415; - *(GpuF0MMReg + 0x2418/4) = 0x04422415; - *(GpuF0MMReg + 0x5490/4) = 0x00000001; - *(GpuF0MMReg + 0x7de4/4) |= (1<<3) | (1<<4); - /* Force allow LDT_STOP Cool'n'Quiet workaround. */ - *(GpuF0MMReg + 0x655c/4) |= 1<<4; - - // disable write combining, needed for stability - // reference bios does this only for RS780 rev A11 - // need to figure out why we need it for all revs - *(GpuF0MMReg + 0x2000/4) = 0x00000010; - *(GpuF0MMReg + 0x2408/4) = 1 << 9; - *(GpuF0MMReg + 0x2000/4) = 0x00000011; - - /* GFX_InitFBAccess finished. */ - -#if (CONFIG_GFXUMA == 1) /* for UMA mode. */ - /* GFX_StartMC. */ - set_nbmc_enable_bits(nb_dev, 0x02, 0x00000000, 0x80000000); - set_nbmc_enable_bits(nb_dev, 0x01, 0x00000000, 0x00000001); - set_nbmc_enable_bits(nb_dev, 0x01, 0x00000000, 0x00000004); - set_nbmc_enable_bits(nb_dev, 0x01, 0x00040000, 0x00000000); - set_nbmc_enable_bits(nb_dev, 0xB1, 0xFFFF0000, 0x00000040); - set_nbmc_enable_bits(nb_dev, 0xC3, 0x00000000, 0x00000001); - set_nbmc_enable_bits(nb_dev, 0x07, 0xFFFFFFFF, 0x00000018); - set_nbmc_enable_bits(nb_dev, 0x06, 0xFFFFFFFF, 0x00000102); - set_nbmc_enable_bits(nb_dev, 0x09, 0xFFFFFFFF, 0x40000008); - set_nbmc_enable_bits(nb_dev, 0x06, 0x00000000, 0x80000000); - /* GFX_StartMC finished. */ -#else - /* for SP mode. */ - set_nbmc_enable_bits(nb_dev, 0xaa, 0xf0, 0x30); - set_nbmc_enable_bits(nb_dev, 0xce, 0xf0, 0x30); - set_nbmc_enable_bits(nb_dev, 0xca, 0xff000000, 0x47000000); - set_nbmc_enable_bits(nb_dev, 0xcb, 0x3f000000, 0x01000000); - set_nbmc_enable_bits(nb_dev, 0x01, 0, 1<<0); - set_nbmc_enable_bits(nb_dev, 0x04, 0, 1<<31); - set_nbmc_enable_bits(nb_dev, 0xb4, 0x3f, 0x3f); - set_nbmc_enable_bits(nb_dev, 0xb4, 0, 1<<6); - set_nbmc_enable_bits(nb_dev, 0xc3, 1<<11, 0); - set_nbmc_enable_bits(nb_dev, 0xa0, 1<<29, 0); - nbmc_write_index(nb_dev, 0xa4, 0x3484576f); - nbmc_write_index(nb_dev, 0xa5, 0x222222df); - nbmc_write_index(nb_dev, 0xa6, 0x00000000); - nbmc_write_index(nb_dev, 0xa7, 0x00000000); - set_nbmc_enable_bits(nb_dev, 0xc3, 1<<8, 0); - udelay(10); - set_nbmc_enable_bits(nb_dev, 0xc3, 1<<9, 0); - udelay(10); - set_nbmc_enable_bits(nb_dev, 0x01, 0, 1<<2); - udelay(200); - set_nbmc_enable_bits(nb_dev, 0x01, 0, 1<<3); - set_nbmc_enable_bits(nb_dev, 0xa0, 0, 1<<31); - udelay(500); - set_nbmc_enable_bits(nb_dev, 0x02, 0, 1<<31); - set_nbmc_enable_bits(nb_dev, 0xa0, 0, 1<<30); - set_nbmc_enable_bits(nb_dev, 0xa0, 1<<31, 0); - set_nbmc_enable_bits(nb_dev, 0xa0, 0, 1<<29); - nbmc_write_index(nb_dev, 0xa4, 0x23484576); - nbmc_write_index(nb_dev, 0xa5, 0x00000000); - nbmc_write_index(nb_dev, 0xa6, 0x00000000); - nbmc_write_index(nb_dev, 0xa7, 0x00000000); - /* GFX_StartMC finished. */ - - /* GFX_SPPowerManagment, don't care for new. */ - /* Post MC Init table programming. */ - set_nbmc_enable_bits(nb_dev, 0xac, ~(0xfffffff0), 0x0b); - - /* Do we need Write and Read Calibration? */ - /* GFX_Init finished. */ -#endif - - /* GFX_InitIntegratedInfo. */ - /* fill the Integrated Info Table. */ - vgainfo.sHeader.usStructureSize = sizeof(ATOM_INTEGRATED_SYSTEM_INFO_V2); - vgainfo.sHeader.ucTableFormatRevision = 1; - vgainfo.sHeader.ucTableContentRevision = 2; - -#if (CONFIG_GFXUMA == 0) /* SP mode. */ - // Side port support is incomplete, do not use it - // These parameters must match the motherboard - vgainfo.ulBootUpSidePortClock = 667*100; - vgainfo.ucMemoryType = 3; // 3=ddr3 sp mem, 2=ddr2 sp mem - vgainfo.ulMinSidePortClock = 333*100; -#endif - - vgainfo.ulBootUpEngineClock = 500 * 100; // setup option on reference BIOS, 500 is default - - // find the DDR memory frequency - if (is_family10h()) { - value = pci_read_config32(k8_f2, 0x94); // read channel 0 DRAM Configuration High Register - if (extractbit(value, 14)) // if channel 0 disabled, channel 1 must have memory - value = pci_read_config32(k8_f2, 0x194);// read channel 1 DRAM Configuration High Register - vgainfo.ulBootUpUMAClock = memclk_lookup_fam10 [extractbits (value, 0, 2)] * 100; - } - if (is_family0Fh()) { - value = pci_read_config32(k8_f2, 0x94); - vgainfo.ulBootUpUMAClock = memclk_lookup_fam0F [extractbits (value, 20, 22)] * 100; - } - - /* UMA Channel Number: 1 or 2. */ - vgainfo.ucUMAChannelNumber = 1; - if (is_family0Fh()) { - value = pci_read_config32(k8_f2, 0x90); - if (extractbit(value, 11)) // 128-bit mode - vgainfo.ucUMAChannelNumber = 2; - } - if (is_family10h()) { - u32 dch0 = pci_read_config32(k8_f2, 0x94); - u32 dch1 = pci_read_config32(k8_f2, 0x194); - if (extractbit(dch0, 14) == 0 && extractbit(dch1, 14) == 0) { // both channels enabled - value = pci_read_config32(k8_f2, 0x110); - if (extractbit(value, 4)) // ganged mode - vgainfo.ucUMAChannelNumber = 2; - } - } - - // processor type - if (is_family0Fh()) - vgainfo.ulCPUCapInfo = 3; - if (is_family10h()) - vgainfo.ulCPUCapInfo = 2; - - /* HT speed */ - value = pci_read_config8(nb_dev, 0xd1); - value = ht_freq_lookup [value] * 100; // HT link frequency in MHz - vgainfo.ulHTLinkFreq = value * 100; // HT frequency in units of 100 MHz - vgainfo.ulHighVoltageHTLinkFreq = vgainfo.ulHTLinkFreq; - vgainfo.ulLowVoltageHTLinkFreq = vgainfo.ulHTLinkFreq; - - if (value <= 1800) - vgainfo.ulLowVoltageHTLinkFreq = vgainfo.ulHTLinkFreq; - else { - int sblink, cpuLnkFreqCap, nbLnkFreqCap; - value = pci_read_config32(k8_f0, 0x64); - sblink = extractbits(value, 8, 10); - cpuLnkFreqCap = pci_read_config16(k8_f0, 0x8a + sblink * 0x20); - nbLnkFreqCap = pci_read_config16(nb_dev, 0xd2); - if (cpuLnkFreqCap & nbLnkFreqCap & (1 << 10)) // if both 1800 MHz capable - vgainfo.ulLowVoltageHTLinkFreq = 1800*100; - } - - /* HT width. */ - value = pci_read_config8(nb_dev, 0xcb); - vgainfo.usMinDownStreamHTLinkWidth = - vgainfo.usMaxDownStreamHTLinkWidth = - vgainfo.usMinUpStreamHTLinkWidth = - vgainfo.usMaxUpStreamHTLinkWidth = - vgainfo.usMinHTLinkWidth = - vgainfo.usMaxHTLinkWidth = ht_width_lookup [extractbits(value, 0, 2)]; - - if (is_family0Fh()) { - vgainfo.usUMASyncStartDelay = 322; - vgainfo.usUMADataReturnTime = 286; - } - - if (is_family10h()) { - static u16 t0mult_lookup [] = {10, 50, 200, 2000}; - int t0time, t0scale; - value = pci_read_config32(k8_f0, 0x16c); - t0time = extractbits(value, 0, 3); - t0scale = extractbits(value, 4, 5); - vgainfo.usLinkStatusZeroTime = t0mult_lookup [t0scale] * t0time; - vgainfo.usUMASyncStartDelay = 100; - if (vgainfo.ulHTLinkFreq < 1000 * 100) { // less than 1000 MHz - vgainfo.usUMADataReturnTime = 300; - vgainfo.usLinkStatusZeroTime = 6 * 100; // 6us for GH in HT1 mode - } - else { - int lssel; - value = pci_read_config32(nb_dev, 0xac); - lssel = extractbits (value, 7, 8); - vgainfo.usUMADataReturnTime = 1300; - if (lssel == 0) vgainfo.usUMADataReturnTime = 150; - } - } - - /* Transfer the Table to VBIOS. */ - pointer = (u32 *)&vgainfo; - for(i=0; i> 8; - if(Base32 < Limit32) - { - Status = GetCreativeMMIO(&CreativeMMIO[0]); - if(Status != CIM_ERROR) - SetMMIO(Base32, Limit32, 0x0, &MMIO[0]); - } - /* Set MMIO for prefetchable P2P. */ - if(Status != CIM_ERROR) - { - temp = pci_read_config32(dev0x14, 0x24); - - Base32 = (temp & 0x0fff0) <<8; - Limit32 = ((temp & 0x0fff00000) + 0x100000) >> 8; - if(Base32 < Limit32) - SetMMIO(Base32, Limit32, 0x0, &MMIO[0]); - } - - FinalizeMMIO(&MMIO[0]); - - ProgramMMIO(&CreativeMMIO[0], 0, MMIO_ATTRIB_NP_ONLY); - ProgramMMIO(&MMIO[0], 0, MMIO_ATTRIB_NP_ONLY | MMIO_ATTRIB_BOTTOM_TO_TOP | MMIO_ATTRIB_SKIP_ZERO); -#endif - - pci_dev_init(dev); - - /* clk ind */ - clkind_write(dev, 0x08, 0x01); - clkind_write(dev, 0x0C, 0x22); - clkind_write(dev, 0x0F, 0x0); - clkind_write(dev, 0x11, 0x0); - clkind_write(dev, 0x12, 0x0); - clkind_write(dev, 0x14, 0x0); - clkind_write(dev, 0x15, 0x0); - clkind_write(dev, 0x16, 0x0); - clkind_write(dev, 0x17, 0x0); - clkind_write(dev, 0x18, 0x0); - clkind_write(dev, 0x19, 0x0); - clkind_write(dev, 0x1A, 0x0); - clkind_write(dev, 0x1B, 0x0); - clkind_write(dev, 0x1C, 0x0); - clkind_write(dev, 0x1D, 0x0); - clkind_write(dev, 0x1E, 0x0); - clkind_write(dev, 0x26, 0x0); - clkind_write(dev, 0x27, 0x0); - clkind_write(dev, 0x28, 0x0); - clkind_write(dev, 0x5C, 0x0); -} - - -/* -* Set registers in RS780 and CPU to enable the internal GFX. -* Please refer to CIM source code and BKDG. -*/ - -static void rs780_internal_gfx_enable(device_t dev) -{ - u32 l_dword; - int i; - device_t nb_dev = dev_find_slot(0, 0); - msr_t sysmem; - -#if (CONFIG_GFXUMA == 0) - u32 FB_Start, FB_End; -#endif - - printk(BIOS_DEBUG, "rs780_internal_gfx_enable dev = 0x%p, nb_dev = 0x%p.\n", dev, nb_dev); - - sysmem = rdmsr(0xc001001a); - printk(BIOS_DEBUG, "sysmem = %x_%x\n", sysmem.hi, sysmem.lo); - - /* The system top memory in 780. */ - pci_write_config32(nb_dev, 0x90, sysmem.lo); - htiu_write_index(nb_dev, 0x30, 0); - htiu_write_index(nb_dev, 0x31, 0); - - /* Disable external GFX and enable internal GFX. */ - l_dword = pci_read_config32(nb_dev, 0x8c); - l_dword &= ~(1<<0); - l_dword |= 1<<1; - pci_write_config32(nb_dev, 0x8c, l_dword); - - /* NB_SetDefaultIndexes */ - pci_write_config32(nb_dev, 0x94, 0x7f); - pci_write_config32(nb_dev, 0x60, 0x7f); - pci_write_config32(nb_dev, 0xe0, 0); - - /* NB_InitEarlyNB finished. */ - - /* LPC DMA Deadlock workaround? */ - /* GFX_InitCommon*/ - device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); - l_dword = pci_read_config32(k8_f0, 0x68); - l_dword &= ~(3 << 21); - l_dword |= (1 << 21); - pci_write_config32(k8_f0, 0x68, l_dword); - - /* GFX_InitCommon. */ - nbmc_write_index(nb_dev, 0x23, 0x00c00010); - set_nbmc_enable_bits(nb_dev, 0x16, 1<<15, 1<<15); - set_nbmc_enable_bits(nb_dev, 0x25, 0xffffffff, 0x111f111f); - set_htiu_enable_bits(nb_dev, 0x37, 1<<24, 1<<24); - -#if (CONFIG_GFXUMA == 1) - /* GFX_InitUMA. */ - /* Copy CPU DDR Controller to NB MC. */ - device_t k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1)); - device_t k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2)); - device_t k8_f4 = dev_find_slot(0, PCI_DEVFN(0x18, 4)); - for (i = 0; i < 12; i++) - { - l_dword = pci_read_config32(k8_f2, 0x40 + i * 4); - nbmc_write_index(nb_dev, 0x30 + i, l_dword); - } - - l_dword = pci_read_config32(k8_f2, 0x80); - nbmc_write_index(nb_dev, 0x3c, l_dword); - l_dword = pci_read_config32(k8_f2, 0x94); - set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<<22))<<16); - set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<< 8))<<17); - l_dword = pci_read_config32(k8_f2, 0x90); - set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<<10))<<18); - if (is_family10h()) - { - for (i = 0; i < 12; i++) - { - l_dword = pci_read_config32(k8_f2, 0x140 + i * 4); - nbmc_write_index(nb_dev, 0x3d + i, l_dword); - } - - l_dword = pci_read_config32(k8_f2, 0x180); - nbmc_write_index(nb_dev, 0x49, l_dword); - l_dword = pci_read_config32(k8_f2, 0x194); - set_nbmc_enable_bits(nb_dev, 0x49, 0, !!(l_dword & (1<<22))<<16); - set_nbmc_enable_bits(nb_dev, 0x49, 0, !!(l_dword & (1<< 8))<<17); - l_dword = pci_read_config32(k8_f2, 0x190); - set_nbmc_enable_bits(nb_dev, 0x49, 0, !!(l_dword & (1<<10))<<18); - - l_dword = pci_read_config32(k8_f2, 0x110); - nbmc_write_index(nb_dev, 0x4a, l_dword); - l_dword = pci_read_config32(k8_f2, 0x114); - nbmc_write_index(nb_dev, 0x4b, l_dword); - l_dword = pci_read_config32(k8_f4, 0x44); - set_nbmc_enable_bits(nb_dev, 0x4a, 0, !!(l_dword & (1<<22))<<24); - l_dword = pci_read_config32(k8_f1, 0x40); - nbmc_write_index(nb_dev, 0x4c, l_dword); - l_dword = pci_read_config32(k8_f1, 0xf0); - nbmc_write_index(nb_dev, 0x4d, l_dword); - } - - - /* Set UMA in the 780 side. */ - /* UMA start address, size. */ - /* The UMA starts at 0xC0000000 of internal RS780 address space - [31:16] addr of last byte | [31:16] addr of first byte - */ - nbmc_write_index(nb_dev, 0x10, ((uma_memory_size - 1 + 0xC0000000) & (~0xffff)) | 0xc000); - nbmc_write_index(nb_dev, 0x11, uma_memory_base); - nbmc_write_index(nb_dev, 0x12, 0); - nbmc_write_index(nb_dev, 0xf0, uma_memory_size >> 20); - /* GFX_InitUMA finished. */ -#else - /* GFX_InitSP. */ - /* SP memory:Hynix HY5TQ1G631ZNFP. 128MB = 64M * 16. 667MHz. DDR3. */ - - /* Enable Async mode. */ - set_nbmc_enable_bits(nb_dev, 0x06, 7<<8, 1<<8); - set_nbmc_enable_bits(nb_dev, 0x08, 1<<10, 0); - /* The last item in AsynchMclkTaskFileIndex. Why? */ - /* MC_MPLL_CONTROL2. */ - nbmc_write_index(nb_dev, 0x07, 0x40100028); - /* MC_MPLL_DIV_CONTROL. */ - nbmc_write_index(nb_dev, 0x0b, 0x00000028); - /* MC_MPLL_FREQ_CONTROL. */ - set_nbmc_enable_bits(nb_dev, 0x09, 3<<12|15<<16|15<<8, 1<<12|4<<16|0<<8); - /* MC_MPLL_CONTROL3. For PM. */ - set_nbmc_enable_bits(nb_dev, 0x08, 0xff<<13, 1<<13|1<<18); - /* MPLL_CAL_TRIGGER. */ - set_nbmc_enable_bits(nb_dev, 0x06, 0, 1<<0); - udelay(200); /* time is long enough? */ - set_nbmc_enable_bits(nb_dev, 0x06, 0, 1<<1); - set_nbmc_enable_bits(nb_dev, 0x06, 1<<0, 0); - /* MCLK_SRC_USE_MPLL. */ - set_nbmc_enable_bits(nb_dev, 0x02, 0, 1<<20); - - /* Pre Init MC. */ - nbmc_write_index(nb_dev, 0x01, 0x88108280); - set_nbmc_enable_bits(nb_dev, 0x02, ~(1<<20), 0x00030200); - nbmc_write_index(nb_dev, 0x04, 0x08881018); - nbmc_write_index(nb_dev, 0x05, 0x000000bb); - nbmc_write_index(nb_dev, 0x0c, 0x0f00001f); - nbmc_write_index(nb_dev, 0xa1, 0x01f10000); - /* MCA_INIT_DLL_PM. */ - set_nbmc_enable_bits(nb_dev, 0xc9, 1<<24, 1<<24); - nbmc_write_index(nb_dev, 0xa2, 0x74f20000); - nbmc_write_index(nb_dev, 0xa3, 0x8af30000); - nbmc_write_index(nb_dev, 0xaf, 0x47d0a41c); - nbmc_write_index(nb_dev, 0xb0, 0x88800130); - nbmc_write_index(nb_dev, 0xb1, 0x00000040); - nbmc_write_index(nb_dev, 0xb4, 0x41247000); - nbmc_write_index(nb_dev, 0xb5, 0x00066664); - nbmc_write_index(nb_dev, 0xb6, 0x00000022); - nbmc_write_index(nb_dev, 0xb7, 0x00000044); - nbmc_write_index(nb_dev, 0xb8, 0xbbbbbbbb); - nbmc_write_index(nb_dev, 0xb9, 0xbbbbbbbb); - nbmc_write_index(nb_dev, 0xba, 0x55555555); - nbmc_write_index(nb_dev, 0xc1, 0x00000000); - nbmc_write_index(nb_dev, 0xc2, 0x00000000); - nbmc_write_index(nb_dev, 0xc3, 0x80006b00); - nbmc_write_index(nb_dev, 0xc4, 0x00066664); - nbmc_write_index(nb_dev, 0xc5, 0x00000000); - nbmc_write_index(nb_dev, 0xd2, 0x00000022); - nbmc_write_index(nb_dev, 0xd3, 0x00000044); - nbmc_write_index(nb_dev, 0xd6, 0x00050005); - nbmc_write_index(nb_dev, 0xd7, 0x00000000); - nbmc_write_index(nb_dev, 0xd8, 0x00700070); - nbmc_write_index(nb_dev, 0xd9, 0x00700070); - nbmc_write_index(nb_dev, 0xe0, 0x00200020); - nbmc_write_index(nb_dev, 0xe1, 0x00200020); - nbmc_write_index(nb_dev, 0xe8, 0x00200020); - nbmc_write_index(nb_dev, 0xe9, 0x00200020); - nbmc_write_index(nb_dev, 0xe0, 0x00180018); - nbmc_write_index(nb_dev, 0xe1, 0x00180018); - nbmc_write_index(nb_dev, 0xe8, 0x00180018); - nbmc_write_index(nb_dev, 0xe9, 0x00180018); - - /* Misc options. */ - /* Memory Termination. */ - set_nbmc_enable_bits(nb_dev, 0xa1, 0x0ff, 0x044); - set_nbmc_enable_bits(nb_dev, 0xb4, 0xf00, 0xb00); -#if 0 - /* Controller Termation. */ - set_nbmc_enable_bits(nb_dev, 0xb1, 0x77770000, 0x77770000); -#endif - - /* OEM Init MC. 667MHz. */ - nbmc_write_index(nb_dev, 0xa8, 0x7a5aaa78); - nbmc_write_index(nb_dev, 0xa9, 0x514a2319); - nbmc_write_index(nb_dev, 0xaa, 0x54400520); - nbmc_write_index(nb_dev, 0xab, 0x441460ff); - nbmc_write_index(nb_dev, 0xa0, 0x20f00a48); - set_nbmc_enable_bits(nb_dev, 0xa2, ~(0xffffffc7), 0x10); - nbmc_write_index(nb_dev, 0xb2, 0x00000303); - set_nbmc_enable_bits(nb_dev, 0xb1, ~(0xffffff70), 0x45); - /* Do it later. */ - /* set_nbmc_enable_bits(nb_dev, 0xac, ~(0xfffffff0), 0x0b); */ - - /* Init PM timing. */ - for(i=0; i<4; i++) - { - l_dword = nbmc_read_index(nb_dev, 0xa0+i); - nbmc_write_index(nb_dev, 0xc8+i, l_dword); - } - for(i=0; i<4; i++) - { - l_dword = nbmc_read_index(nb_dev, 0xa8+i); - nbmc_write_index(nb_dev, 0xcc+i, l_dword); - } - l_dword = nbmc_read_index(nb_dev, 0xb1); - set_nbmc_enable_bits(nb_dev, 0xc8, 0xff<<24, ((l_dword&0x0f)<<24)|((l_dword&0xf00)<<20)); - - /* Init MC FB. */ - /* FB_Start = ; FB_End = ; iSpSize = 0x0080, 128MB. */ - nbmc_write_index(nb_dev, 0x11, 0x40000000); - FB_Start = 0xc00 + 0x080; - FB_End = 0xc00 + 0x080; - nbmc_write_index(nb_dev, 0x10, (((FB_End&0xfff)<<20)-0x10000)|(((FB_Start&0xfff)-0x080)<<4)); - set_nbmc_enable_bits(nb_dev, 0x0d, ~0x000ffff0, (FB_Start&0xfff)<<20); - nbmc_write_index(nb_dev, 0x0f, 0); - nbmc_write_index(nb_dev, 0x0e, (FB_Start&0xfff)|(0xaaaa<<12)); -#endif - - /* GFX_InitSP finished. */ -} - -static struct pci_operations lops_pci = { - .set_subsystem = pci_dev_set_subsystem, -}; - -static struct device_operations pcie_ops = { - .read_resources = rs780_gfx_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = internal_gfx_pci_dev_init, /* The option ROM initializes the device. rs780_gfx_init, */ - .scan_bus = 0, - .enable = rs780_internal_gfx_enable, - .ops_pci = &lops_pci, -}; - -/* - * We should list all of them here. - * */ -static const struct pci_driver pcie_driver_780 __pci_driver = { - .ops = &pcie_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_RS780_INT_GFX, -}; - -static const struct pci_driver pcie_driver_780c __pci_driver = { - .ops = &pcie_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_RS780C_INT_GFX, -}; -static const struct pci_driver pcie_driver_780m __pci_driver = { - .ops = &pcie_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_RS780M_INT_GFX, -}; -static const struct pci_driver pcie_driver_780mc __pci_driver = { - .ops = &pcie_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_RS780MC_INT_GFX, -}; -static const struct pci_driver pcie_driver_780e __pci_driver = { - .ops = &pcie_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_RS780E_INT_GFX, -}; -static const struct pci_driver pcie_driver_785g __pci_driver = { - .ops = &pcie_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_RS785G_INT_GFX, -}; - -/* step 12 ~ step 14 from rpr */ -static void single_port_configuration(device_t nb_dev, device_t dev) -{ - u8 result, width; - u32 reg32; - struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)nb_dev->chip_info; - - printk(BIOS_DEBUG, "rs780_gfx_init single_port_configuration.\n"); - - /* step 12 training, releases hold training for GFX port 0 (device 2) */ - PcieReleasePortTraining(nb_dev, dev, 2); - result = PcieTrainPort(nb_dev, dev, 2); - printk(BIOS_DEBUG, "rs780_gfx_init single_port_configuration step12.\n"); - - /* step 13 Power Down Control */ - /* step 13.1 Enables powering down transmitter and receiver pads along with PLL macros. */ - set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 1 << 0); - - /* step 13.a Link Training was NOT successful */ - if (!result) { - set_nbmisc_enable_bits(nb_dev, 0x8, 0, 0x3 << 4); /* prevent from training. */ - set_nbmisc_enable_bits(nb_dev, 0xc, 0, 0x3 << 2); /* hide the GFX bridge. */ - if (cfg->gfx_tmds) - nbpcie_ind_write_index(nb_dev, 0x65, 0xccf0f0); - else { - nbpcie_ind_write_index(nb_dev, 0x65, 0xffffffff); - set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 3, 1 << 3); - } - } else { /* step 13.b Link Training was successful */ - set_pcie_enable_bits(dev, 0xA2, 0xFF, 0x1); - reg32 = nbpcie_p_read_index(dev, 0x29); - width = reg32 & 0xFF; - printk(BIOS_DEBUG, "GFX Inactive Lanes = 0x%x.\n", width); - switch (width) { - case 1: - case 2: - nbpcie_ind_write_index(nb_dev, 0x65, - cfg->gfx_lane_reversal ? 0x7f7f : 0xccfefe); - break; - case 4: - nbpcie_ind_write_index(nb_dev, 0x65, - cfg->gfx_lane_reversal ? 0x3f3f : 0xccfcfc); - break; - case 8: - nbpcie_ind_write_index(nb_dev, 0x65, - cfg->gfx_lane_reversal ? 0x0f0f : 0xccf0f0); - break; - } - } - printk(BIOS_DEBUG, "rs780_gfx_init single_port_configuration step13.\n"); - - /* step 14 Reset Enumeration Timer, disables the shortening of the enumeration timer */ - set_pcie_enable_bits(dev, 0x70, 1 << 19, 1 << 19); - printk(BIOS_DEBUG, "rs780_gfx_init single_port_configuration step14.\n"); -} - -static void dual_port_configuration(device_t nb_dev, device_t dev) -{ - u8 result, width; - u32 reg32, dev_ind = dev->path.pci.devfn >> 3; - struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)nb_dev->chip_info; - - /* 5.4.1.2 Dual Port Configuration */ - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); - set_nbmisc_enable_bits(nb_dev, 0x08, 0xF << 8, 0x5 << 8); - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); - - /* 5.7. Training for Device 2 */ - /* 5.7.1. Releases hold training for GFX port 0 (device 2) */ - PcieReleasePortTraining(nb_dev, dev, dev_ind); - /* 5.7.2- 5.7.9. PCIE Link Training Sequence */ - result = PcieTrainPort(nb_dev, dev, dev_ind); - - /* Power Down Control for Device 2 */ - /* Link Training was NOT successful */ - if (!result) { - /* Powers down all lanes for port A */ - /* nbpcie_ind_write_index(nb_dev, 0x65, 0x0f0f); */ - /* Note: I have to disable the slot where there isnt a device, - * otherwise the system will hang. I dont know why. */ - set_nbmisc_enable_bits(nb_dev, 0x0c, 1 << dev_ind, 1 << dev_ind); - - } else { /* step 16.b Link Training was successful */ - reg32 = nbpcie_p_read_index(dev, 0xa2); - width = (reg32 >> 4) & 0x7; - printk(BIOS_DEBUG, "GFX LC_LINK_WIDTH = 0x%x.\n", width); - switch (width) { - case 1: - case 2: - nbpcie_ind_write_index(nb_dev, 0x65, - cfg->gfx_lane_reversal ? 0x0707 : 0x0e0e); - break; - case 4: - nbpcie_ind_write_index(nb_dev, 0x65, - cfg->gfx_lane_reversal ? 0x0303 : 0x0c0c); - break; - } - } -} - -/* For single port GFX configuration Only -* width: -* 000 = x16 -* 001 = x1 -* 010 = x2 -* 011 = x4 -* 100 = x8 -* 101 = x12 (not supported) -* 110 = x16 -*/ -static void dynamic_link_width_control(device_t nb_dev, device_t dev, u8 width) -{ - u32 reg32; - device_t sb_dev; - struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)nb_dev->chip_info; - - /* step 5.9.1.1 */ - reg32 = nbpcie_p_read_index(dev, 0xa2); - - /* step 5.9.1.2 */ - set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 1 << 0); - /* step 5.9.1.3 */ - set_pcie_enable_bits(dev, 0xa2, 3 << 0, width << 0); - /* step 5.9.1.4 */ - set_pcie_enable_bits(dev, 0xa2, 1 << 8, 1 << 8); - /* step 5.9.2.4 */ - if (0 == cfg->gfx_reconfiguration) - set_pcie_enable_bits(dev, 0xa2, 1 << 11, 1 << 11); - - /* step 5.9.1.5 */ - do { - reg32 = nbpcie_p_read_index(dev, 0xa2); - } - while (reg32 & 0x100); - - /* step 5.9.1.6 */ - sb_dev = dev_find_slot(0, PCI_DEVFN(8, 0)); - do { - reg32 = pci_ext_read_config32(nb_dev, sb_dev, - PCIE_VC0_RESOURCE_STATUS); - } while (reg32 & VC_NEGOTIATION_PENDING); - - /* step 5.9.1.7 */ - reg32 = nbpcie_p_read_index(dev, 0xa2); - if (((reg32 & 0x70) >> 4) != 0x6) { - /* the unused lanes should be powered off. */ - } - - /* step 5.9.1.8 */ - set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 0 << 0); -} - -/* -* GFX Core initialization, dev2, dev3 -*/ -void rs780_gfx_init(device_t nb_dev, device_t dev, u32 port) -{ - u32 reg32; - struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)nb_dev->chip_info; - - printk(BIOS_DEBUG, "rs780_gfx_init, nb_dev=0x%p, dev=0x%p, port=0x%x.\n", - nb_dev, dev, port); - - /* GFX Core Initialization */ - //if (port == 2) return; - - /* step 2, TMDS, (only need if CMOS option is enabled) */ - if (cfg->gfx_tmds) { - } - -#if 1 /* external clock mode */ - /* table 5-22, 5.9.1. REFCLK */ - /* 5.9.1.1. Disables the GFX REFCLK transmitter so that the GFX - * REFCLK PAD can be driven by an external source. */ - /* 5.9.1.2. Enables GFX REFCLK receiver to receive the REFCLK from an external source. */ - set_nbmisc_enable_bits(nb_dev, 0x38, 1 << 29 | 1 << 28 | 1 << 26, 1 << 28); - - /* 5.9.1.3 Selects the GFX REFCLK to be the source for PLL A. */ - /* 5.9.1.4 Selects the GFX REFCLK to be the source for PLL B. */ - /* 5.9.1.5 Selects the GFX REFCLK to be the source for PLL C. */ - set_nbmisc_enable_bits(nb_dev, 0x28, 3 << 6 | 3 << 8 | 3 << 10, - 1 << 6 | 1 << 8 | 1 << 10); - reg32 = nbmisc_read_index(nb_dev, 0x28); - printk(BIOS_DEBUG, "misc 28 = %x\n", reg32); - - /* 5.9.1.6.Selects the single ended GFX REFCLK to be the source for core logic. */ - set_nbmisc_enable_bits(nb_dev, 0x6C, 1 << 31, 1 << 31); -#else /* internal clock mode */ - /* table 5-23, 5.9.1. REFCLK */ - /* 5.9.1.1. Enables the GFX REFCLK transmitter so that the GFX - * REFCLK PAD can be driven by the SB REFCLK. */ - /* 5.9.1.2. Disables GFX REFCLK receiver from receiving the - * REFCLK from an external source.*/ - set_nbmisc_enable_bits(nb_dev, 0x38, 1 << 29 | 1 << 28, 1 << 29 | 0 << 28); - - /* 5.9.1.3 Selects the GFX REFCLK to be the source for PLL A. */ - /* 5.9.1.4 Selects the GFX REFCLK to be the source for PLL B. */ - /* 5.9.1.5 Selects the GFX REFCLK to be the source for PLL C. */ - set_nbmisc_enable_bits(nb_dev, 0x28, 3 << 6 | 3 << 8 | 3 << 10, - 0); - reg32 = nbmisc_read_index(nb_dev, 0x28); - printk(BIOS_DEBUG, "misc 28 = %x\n", reg32); - - /* 5.9.1.6.Selects the single ended GFX REFCLK to be the source for core logic. */ - set_nbmisc_enable_bits(nb_dev, 0x6C, 1 << 31, 0 << 31); -#endif - - /* step 5.9.3, GFX overclocking, (only need if CMOS option is enabled) */ - /* 5.9.3.1. Increases PLL BW for 6G operation.*/ - /* set_nbmisc_enable_bits(nb_dev, 0x36, 0x3FF << 4, 0xB5 << 4); */ - /* skip */ - - /* step 5.9.4, reset the GFX link */ - /* step 5.9.4.1 asserts both calibration reset and global reset */ - set_nbmisc_enable_bits(nb_dev, 0x8, 0x3 << 14, 0x3 << 14); - - /* step 5.9.4.2 de-asserts calibration reset */ - set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 14, 0 << 14); - - /* step 5.9.4.3 wait for at least 200us */ - udelay(300); - - /* step 5.9.4.4 de-asserts global reset */ - set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 15, 0 << 15); - - /* 5.9.5 Reset PCIE_GFX Slot */ - /* It is done in mainboard.c */ - set_pcie_reset(); - mdelay(1); - set_pcie_dereset(); - - /* step 5.9.8 program PCIE memory mapped configuration space */ - /* done by enable_pci_bar3() before */ - - /* step 7 compliance state, (only need if CMOS option is enabled) */ - /* the compliance stete is just for test. refer to 4.2.5.2 of PCIe specification */ - if (cfg->gfx_compliance) { - /* force compliance */ - set_nbmisc_enable_bits(nb_dev, 0x32, 1 << 6, 1 << 6); - /* release hold training for device 2. GFX initialization is done. */ - set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 4, 0 << 4); - dynamic_link_width_control(nb_dev, dev, cfg->gfx_link_width); - printk(BIOS_DEBUG, "rs780_gfx_init step7.\n"); - return; - } - - /* 5.9.12 Core Initialization. */ - /* 5.9.12.1 sets RCB timeout to be 25ms */ - /* 5.9.12.2. RCB Cpl timeout on link down. */ - set_pcie_enable_bits(dev, 0x70, 7 << 16 | 1 << 19, 4 << 16 | 1 << 19); - printk(BIOS_DEBUG, "rs780_gfx_init step5.9.12.1.\n"); - - /* step 5.9.12.3 disables slave ordering logic */ - set_pcie_enable_bits(nb_dev, 0x20, 1 << 8, 1 << 8); - printk(BIOS_DEBUG, "rs780_gfx_init step5.9.12.3.\n"); - - /* step 5.9.12.4 sets DMA payload size to 64 bytes */ - set_pcie_enable_bits(nb_dev, 0x10, 7 << 10, 4 << 10); - /* 5.9.12.5. Blocks DMA traffic during C3 state. */ - set_pcie_enable_bits(dev, 0x10, 1 << 0, 0 << 0); - - /* 5.9.12.6. Disables RC ordering logic */ - set_pcie_enable_bits(nb_dev, 0x20, 1 << 9, 1 << 9); - - /* Enabels TLP flushing. */ - /* Note: It is got from RS690. The system will hang without this action. */ - set_pcie_enable_bits(dev, 0x20, 1 << 19, 0 << 19); - - /* 5.9.12.7. Ignores DLLPs during L1 so that txclk can be turned off */ - set_pcie_enable_bits(nb_dev, 0x2, 1 << 0, 1 << 0); - - /* 5.9.12.8 Prevents LC to go from L0 to Rcv_L0s if L1 is armed. */ - set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11); - - /* 5.9.12.9 CMGOOD_OVERRIDE for end point initiated lane degradation. */ - set_nbmisc_enable_bits(nb_dev, 0x6a, 1 << 17, 1 << 17); - printk(BIOS_DEBUG, "rs780_gfx_init step5.9.12.9.\n"); - - /* 5.9.12.10 Sets the timer in Config state from 20us to */ - /* 5.9.12.11 De-asserts RX_EN in L0s. */ - /* 5.9.12.12 Enables de-assertion of PG2RX_CR_EN to lock clock - * recovery parameter when lane is in electrical idle in L0s.*/ - set_pcie_enable_bits(dev, 0xB1, 1 << 23 | 1 << 19 | 1 << 28, 1 << 23 | 1 << 19 | 1 << 28); - - /* 5.9.12.13. Turns off offset calibration. */ - /* 5.9.12.14. Enables Rx Clock gating in CDR */ - set_nbmisc_enable_bits(nb_dev, 0x34, 1 << 10/* | 1 << 22 */, 1 << 10/* | 1 << 22 */); - - /* 5.9.12.15. Sets number of TX Clocks to drain TX Pipe to 3. */ - set_pcie_enable_bits(dev, 0xA0, 0xF << 4, 3 << 4); - - /* 5.9.12.16. Lets PI use Electrical Idle from PHY when - * turning off PLL in L1 at Gen2 speed instead Inferred Electrical Idle. */ - set_pcie_enable_bits(nb_dev, 0x40, 3 << 14, 2 << 14); - - /* 5.9.12.17. Prevents the Electrical Idle from causing a transition from Rcv_L0 to Rcv_L0s. */ - set_pcie_enable_bits(dev, 0xB1, 1 << 20, 1 << 20); - - /* 5.9.12.18. Prevents the LTSSM from going to Rcv_L0s if it has already - * acknowledged a request to go to L1. */ - set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11); - - /* 5.9.12.19. LDSK only taking deskew on deskewing error detect */ - set_pcie_enable_bits(nb_dev, 0x40, 1 << 28, 0 << 28); - - /* 5.9.12.20. Bypasses lane de-skew logic if in x1 */ - set_pcie_enable_bits(nb_dev, 0xC2, 1 << 14, 1 << 14); - - /* 5.9.12.21. Sets Electrical Idle Threshold. */ - set_nbmisc_enable_bits(nb_dev, 0x35, 3 << 21, 2 << 21); - - /* 5.9.12.22. Advertises -6 dB de-emphasis value in TS1 Data Rate Identifier - * Only if CMOS Option in section. skip */ - - /* 5.9.12.23. Disables GEN2 capability of the device. */ - set_pcie_enable_bits(dev, 0xA4, 1 << 0, 0 << 0); - - /* 5.9.12.24.Disables advertising Upconfigure Support. */ - set_pcie_enable_bits(dev, 0xA2, 1 << 13, 1 << 13); - - /* 5.9.12.25. No comment in RPR. */ - set_nbmisc_enable_bits(nb_dev, 0x39, 1 << 10, 0 << 10); - - /* 5.9.12.26. This capacity is required since links wider than x1 and/or multiple link - * speed are supported */ - set_pcie_enable_bits(nb_dev, 0xC1, 1 << 0, 1 << 0); - - /* 5.9.12.27. Enables NVG86 ECO. A13 above only. */ - if (get_nb_rev(nb_dev) == REV_RS780_A12) /* A12 */ - set_pcie_enable_bits(dev, 0x02, 1 << 11, 1 << 11); - - /* 5.9.12.28 Hides and disables the completion timeout method. */ - set_pcie_enable_bits(nb_dev, 0xC1, 1 << 2, 0 << 2); - - /* 5.9.12.29. Use the bif_core de-emphasis strength by default. */ - /* set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 28, 1 << 28); */ - - /* 5.9.12.30. Set TX arbitration algorithm to round robin */ - set_pcie_enable_bits(nb_dev, 0x1C, - 1 << 0 | 0x1F << 1 | 0x1F << 6, - 1 << 0 | 0x04 << 1 | 0x04 << 6); - - /* Single-port/Dual-port configureation. */ - switch (cfg->gfx_dual_slot) { - case 0: - /* step 1, lane reversal (only need if build config option is enabled) */ - if (cfg->gfx_lane_reversal) { - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); - set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); - } - printk(BIOS_DEBUG, "rs780_gfx_init step1.\n"); - - printk(BIOS_DEBUG, "device = %x\n", dev->path.pci.devfn >> 3); - if((dev->path.pci.devfn >> 3) == 2) { - single_port_configuration(nb_dev, dev); - } else { - set_nbmisc_enable_bits(nb_dev, 0xc, 0, 0x2 << 2); /* hide the GFX bridge. */ - printk(BIOS_INFO, "Single port. Do nothing.\n"); // If dev3 - } - - break; - case 1: - /* step 1, lane reversal (only need if build config option is enabled) */ - if (cfg->gfx_lane_reversal) { - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); - set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); - set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 3, 1 << 3); - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); - } - printk(BIOS_DEBUG, "rs780_gfx_init step1.\n"); - /* step 1.1, dual-slot gfx configuration (only need if CMOS option is enabled) */ - /* AMD calls the configuration CrossFire */ - set_nbmisc_enable_bits(nb_dev, 0x0, 0xf << 8, 5 << 8); - printk(BIOS_DEBUG, "rs780_gfx_init step2.\n"); - - printk(BIOS_DEBUG, "device = %x\n", dev->path.pci.devfn >> 3); - dual_port_configuration(nb_dev, dev); - break; - - case 2: - - if(is_dev3_present()){ - /* step 1, lane reversal (only need if CMOS option is enabled) */ - if (cfg->gfx_lane_reversal) { - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); - set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); - set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 3, 1 << 3); - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); - } - printk(BIOS_DEBUG, "rs780_gfx_init step1.\n"); - /* step 1.1, dual-slot gfx configuration (only need if CMOS option is enabled) */ - /* AMD calls the configuration CrossFire */ - set_nbmisc_enable_bits(nb_dev, 0x0, 0xf << 8, 5 << 8); - printk(BIOS_DEBUG, "rs780_gfx_init step2.\n"); - - - printk(BIOS_DEBUG, "device = %x\n", dev->path.pci.devfn >> 3); - dual_port_configuration(nb_dev, dev); - - }else{ - if (cfg->gfx_lane_reversal) { - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); - set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); - } - printk(BIOS_DEBUG, "rs780_gfx_init step1.\n"); - - if((dev->path.pci.devfn >> 3) == 2) - single_port_configuration(nb_dev, dev); - else{ - set_nbmisc_enable_bits(nb_dev, 0xc, 0, 0x2 << 2); /* hide the GFX bridge. */ - printk(BIOS_DEBUG, "If dev3.., single port. Do nothing.\n"); - } - } - - default: - printk(BIOS_INFO, "Incorrect configuration of external GFX slot.\n"); - break; - } -} diff --git a/src/southbridge/amd/rs780/rs780_ht.c b/src/southbridge/amd/rs780/rs780_ht.c deleted file mode 100644 index 03d4f84645..0000000000 --- a/src/southbridge/amd/rs780/rs780_ht.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include "rs780.h" - -/* for UMA internal graphics */ -void avoid_lpc_dma_deadlock(device_t nb_dev, device_t sb_dev) -{ - device_t cpu_f0; - u8 reg; - - cpu_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); - set_nbcfg_enable_bits(cpu_f0, 0x68, 3 << 21, 1 << 21); - - reg = nbpcie_p_read_index(sb_dev, 0x10); - reg |= 0x100; /* bit9=1 */ - nbpcie_p_write_index(sb_dev, 0x10, reg); - - reg = nbpcie_p_read_index(nb_dev, 0x10); - reg |= 0x100; /* bit9=1 */ - nbpcie_p_write_index(nb_dev, 0x10, reg); - - /* Enable NP protocol over PCIE for memory-mapped writes targeting LPC - * Set this bit to avoid a deadlock condition. */ - reg = htiu_read_index(nb_dev, 0x6); - reg |= 0x1000000; /* bit26 */ - htiu_write_index(nb_dev, 0x6, reg); -} - -static void pcie_init(struct device *dev) -{ - /* Enable pci error detecting */ - u32 dword; - - printk(BIOS_INFO, "pcie_init in rs780_ht.c\n"); - - /* System error enable */ - dword = pci_read_config32(dev, 0x04); - dword |= (1 << 8); /* System error enable */ - dword |= (1 << 30); /* Clear possible errors */ - pci_write_config32(dev, 0x04, dword); - - /* - * 1 is APIC enable - * 18 is enable nb to accept A4 interrupt request from SB. - */ - dword = pci_read_config32(dev, 0x4C); - dword |= 1 << 1 | 1 << 18; /* Clear possible errors */ - pci_write_config32(dev, 0x4C, dword); -} - -static struct pci_operations lops_pci = { - .set_subsystem = pci_dev_set_subsystem, -}; - -static struct device_operations ht_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = pcie_init, - .scan_bus = 0, - .ops_pci = &lops_pci, -}; - -static const struct pci_driver ht_driver __pci_driver = { - .ops = &ht_ops, - .vendor = PCI_VENDOR_ID_AMD, - .device = PCI_DEVICE_ID_AMD_RS780_HT, -}; diff --git a/src/southbridge/amd/rs780/rs780_pcie.c b/src/southbridge/amd/rs780/rs780_pcie.c deleted file mode 100644 index 9cbd832661..0000000000 --- a/src/southbridge/amd/rs780/rs780_pcie.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include -#include "rs780.h" - -/*------------------------------------------------ -* Global variable -------------------------------------------------*/ -PCIE_CFG AtiPcieCfg = { - PCIE_ENABLE_STATIC_DEV_REMAP, /* Config */ - 0, /* ResetReleaseDelay */ - 0, /* Gfx0Width */ - 0, /* Gfx1Width */ - 0, /* GfxPayload */ - 0, /* GppPayload */ - 0, /* PortDetect, filled by GppSbInit */ - 0, /* PortHp */ - 0, /* DbgConfig */ - 0, /* DbgConfig2 */ - 0, /* GfxLx */ - 0, /* GppLx */ - 0, /* NBSBLx */ - 0, /* PortSlotInit */ - 0, /* Gfx0Pwr */ - 0, /* Gfx1Pwr */ - 0 /* GppPwr */ -}; - -static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port); -static void ValidatePortEn(device_t nb_dev); - -static void ValidatePortEn(device_t nb_dev) -{ -} - -/***************************************************************** -* Compliant with CIM_33's PCIEPowerOffGppPorts -* Power off unused GPP lines -*****************************************************************/ -static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port) -{ - u32 reg; - u16 state_save; - struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)nb_dev->chip_info; - u8 state = cfg->port_enable; - - if (!(AtiPcieCfg.Config & PCIE_DISABLE_HIDE_UNUSED_PORTS)) - state &= AtiPcieCfg.PortDetect; - state = ~state; - state &= (1 << 4) + (1 << 5) + (1 << 6) + (1 << 7); - state_save = state << 17; - state &= !(AtiPcieCfg.PortHp); - reg = nbmisc_read_index(nb_dev, 0x0c); - reg |= state; - nbmisc_write_index(nb_dev, 0x0c, reg); - - reg = nbmisc_read_index(nb_dev, 0x08); - reg |= state_save; - nbmisc_write_index(nb_dev, 0x08, reg); - - if ((AtiPcieCfg.Config & PCIE_OFF_UNUSED_GPP_LANES) - && !(AtiPcieCfg. - Config & (PCIE_DISABLE_HIDE_UNUSED_PORTS + - PCIE_GFX_COMPLIANCE))) { - } - /* step 3 Power Down Control for Southbridge */ - reg = nbpcie_p_read_index(dev, 0xa2); - - switch ((reg >> 4) & 0x7) { /* get bit 4-6, LC_LINK_WIDTH_RD */ - case 1: - nbpcie_ind_write_index(nb_dev, 0x65, 0x0e0e); - break; - case 2: - nbpcie_ind_write_index(nb_dev, 0x65, 0x0c0c); - break; - default: - break; - } -} - -/********************************************************************** -**********************************************************************/ -static void switching_gppsb_configurations(device_t nb_dev, device_t sb_dev) -{ - u32 reg; - struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)nb_dev->chip_info; - - /* 5.5.7.1-3 enables GPP reconfiguration */ - reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7); - reg |= - (RECONFIG_GPPSB_EN + RECONFIG_GPPSB_LINK_CONFIG + - RECONFIG_GPPSB_ATOMIC_RESET); - nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg); - - /* 5.5.7.4a. De-asserts STRAP_BIF_all_valid for PCIE-GPPSB core */ - reg = nbmisc_read_index(nb_dev, 0x66); - reg |= 1 << 31; - nbmisc_write_index(nb_dev, 0x66, reg); - /* 5.5.7.4b. sets desired GPPSB configurations, bit4-7 */ - reg = nbmisc_read_index(nb_dev, 0x67); - reg &= 0xFFFFff0f; /* clean */ - reg |= cfg->gppsb_configuration << 4; - nbmisc_write_index(nb_dev, 0x67, reg); - -#if 1 - /* NOTE: - * In CIMx 4.5.0 and RPR, 4c is done before 5 & 6. But in this way, - * a x4 device in port B (dev 4) of Configuration B can only be detected - * as x1, instead of x4. When the port B is being trained, the - * LC_CURRENT_STATE is 6 and the LC_LINK_WIDTH_RD is 1. We have - * to set the PCIEIND:0x65 as 0xE0E0 and reset the slot. Then the card - * seems to work in x1 mode. - * In the 2nd way below, we do the 5 & 6 before 4c. it conforms the - * CIMx 4.3.0. It conflicts with RPR. But based on the test result I've - * made so far, I haven't found any mistake. - */ - /* 5.5.7.4c. Asserts STRAP_BIF_all_valid for PCIE-GPPSB core */ - reg = nbmisc_read_index(nb_dev, 0x66); - reg &= ~(1 << 31); - nbmisc_write_index(nb_dev, 0x66, reg); - - /* 5.5.7.5-6. read bit14 and write back its inverst value */ - reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7); - reg ^= RECONFIG_GPPSB_GPPSB; - nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg); -#else - /* 5.5.7.5-6. read bit14 and write back its inverst value */ - reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7); - reg ^= RECONFIG_GPPSB_GPPSB; - nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg); - - /* 5.5.7.4c. Asserts STRAP_BIF_all_valid for PCIE-GPPSB core */ - reg = nbmisc_read_index(nb_dev, 0x66); - reg &= ~(1 << 31); - nbmisc_write_index(nb_dev, 0x66, reg); -#endif - /* 5.5.7.7. delay 1ms */ - mdelay(1); - - /* 5.5.7.8. waits until SB has trained to L0, poll for bit0-5 = 0x10 */ - do { - reg = nbpcie_p_read_index(sb_dev, PCIE_LC_STATE0); - reg &= 0x3f; /* remain LSB [5:0] bits */ - } while (LC_STATE_RECONFIG_GPPSB != reg); - - /* 5.5.7.9.ensures that virtual channel negotiation is completed. poll for bit1 = 0 */ - do { - reg = - pci_ext_read_config32(nb_dev, sb_dev, - PCIE_VC0_RESOURCE_STATUS); - } while (reg & VC_NEGOTIATION_PENDING); -} - -static void switching_gpp_configurations(device_t nb_dev, device_t sb_dev) -{ - u32 reg; - struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)nb_dev->chip_info; - - /* 5.6.2.1. De-asserts STRAP_BIF_all_valid for PCIE-GPP core */ - reg = nbmisc_read_index(nb_dev, 0x22); - reg |= 1 << 14; - nbmisc_write_index(nb_dev, 0x22, reg); - /* 5.6.2.2. sets desired GPPSB configurations, bit4-7 */ - reg = nbmisc_read_index(nb_dev, 0x2D); - reg &= ~(0xF << 7); /* clean */ - reg |= cfg->gpp_configuration << 7; - nbmisc_write_index(nb_dev, 0x2D, reg); - /* 5.6.2.3. Asserts STRAP_BIF_all_valid for PCIE-GPP core */ - reg = nbmisc_read_index(nb_dev, 0x22); - reg &= ~(1 << 14); - nbmisc_write_index(nb_dev, 0x22, reg); -} - -/***************************************************************** -* The rs780 uses NBCONFIG:0x1c (BAR3) to map the PCIE Extended Configuration -* Space to a 256MB range within the first 4GB of addressable memory. -*****************************************************************/ -void enable_pcie_bar3(device_t nb_dev) -{ - printk(BIOS_DEBUG, "enable_pcie_bar3()\n"); - set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 1 << 30); /* Enables writes to the BAR3 register. */ - set_nbcfg_enable_bits(nb_dev, 0x84, 7 << 16, 0 << 16); - - pci_write_config32(nb_dev, 0x1C, EXT_CONF_BASE_ADDRESS); /* PCIEMiscInit */ - pci_write_config32(nb_dev, 0x20, 0x00000000); - set_htiu_enable_bits(nb_dev, 0x32, 1 << 28, 1 << 28); /* PCIEMiscInit */ - ProgK8TempMmioBase(1, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS); -} - -/***************************************************************** -* We should disable bar3 when we want to exit rs780_enable, because bar3 will be -* remapped in set_resource later. -*****************************************************************/ -void disable_pcie_bar3(device_t nb_dev) -{ - printk(BIOS_DEBUG, "disable_pcie_bar3()\n"); - pci_write_config32(nb_dev, 0x1C, 0); /* clear BAR3 address */ - set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 0 << 30); /* Disable writes to the BAR3. */ - set_htiu_enable_bits(nb_dev, 0x32, 1 << 28, 0); /* disable bar3 decode */ - ProgK8TempMmioBase(0, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS); -} - -/***************************************** -* Compliant with CIM_33's PCIEGPPInit -* nb_dev: -* root bridge struct -* dev: -* p2p bridge struct -* port: -* p2p bridge number, 4-10 -*****************************************/ -void rs780_gpp_sb_init(device_t nb_dev, device_t dev, u32 port) -{ - u32 gfx_gpp_sb_sel; - struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)nb_dev->chip_info; - printk(BIOS_DEBUG, "gpp_sb_init nb_dev=0x%x, dev=0x%x, port=0x%x\n", nb_dev->path.pci.devfn, dev->path.pci.devfn, port); - - gfx_gpp_sb_sel = port >= 4 && port <= 8 ? - PCIE_CORE_INDEX_GPPSB : /* 4,5,6,7,8 */ - PCIE_CORE_INDEX_GPP; /* 9,10 */ - /* init GPP core */ - /* 5.10.8.3. Disable slave ordering logic */ - set_pcie_enable_bits(nb_dev, 0x20 | gfx_gpp_sb_sel, 1 << 8, - 1 << 8); - /* 5.10.8.7. PCIE initialization 5.10.2: rpr 2.12*/ - set_pcie_enable_bits(nb_dev, 0x02 | gfx_gpp_sb_sel, 1 << 0, 1 << 0); /* no description in datasheet. */ - - /* init GPPSB port. rpr 5.10.8 */ - /* 5.10.8.1-5.10.8.2. Sets RCB timeout to be 100ms/4=25ms by setting bits[18:16] to 3 h4 - * and shortens the enumeration timer by setting bit[19] to 1 - */ - set_pcie_enable_bits(dev, 0x70, 0xF << 16, 0x4 << 16 | 1 << 19); - /* 5.10.8.4. Sets DMA payload size to 64 bytes. */ - set_pcie_enable_bits(nb_dev, 0x10 | gfx_gpp_sb_sel, 7 << 10, 4 << 10); - /* 5.10.8.6. Disable RC ordering logic */ - set_pcie_enable_bits(nb_dev, 0x20 | gfx_gpp_sb_sel, 1 << 9, 1 << 9); - /* 5.10.8.7. Ignores DLLs druing L1 */ - set_pcie_enable_bits(nb_dev, 0x02 | gfx_gpp_sb_sel, 1 << 0, 1 << 0); - /* 5.10.8.8. Prevents LCto go from L0 to Rcv_L0s if L1 is armed. */ - set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11); - /* 5.10.8.9. Sets timer in Config state from 20us to 1us. - * 5.10.8.10. De-asserts RX_EN in L0s - * 5.10.8.11. Enables de-assertion of PG2RX_CR_EN to lock clock recovery parameter when .. */ - set_pcie_enable_bits(dev, 0xB1, 1 << 23 | 1 << 19 | 1 << 28, 1 <<23 | 1 << 19 | 1 << 28); - /* 5.10.8.12. Turns off offset calibration */ - /* 5.10.8.13. Enables Rx Clock gating in CDR */ - if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB) - set_nbmisc_enable_bits(nb_dev, 0x67, 1 << 14 | 1 << 26, 1 << 14 | 1 << 26); /* 4,5,6,7 */ - else - set_nbmisc_enable_bits(nb_dev, 0x24, 1 << 29 | 1 << 28, 1 << 29 | 1 << 28); /* 9,10 */ - /* 5.10.8.14. Sets number of TX Clocks to drain TX Pipe to 3 */ - set_pcie_enable_bits(dev, 0xA0, 0xF << 4, 0x3 << 4); - /* 5.10.8.15. empty */ - /* 5.10.8.16. P_ELEC_IDLE_MODE */ - set_pcie_enable_bits(nb_dev, 0x40 | gfx_gpp_sb_sel, 0x3 << 14, 0x2 << 14); - /* 5.10.8.17. LC_BLOCK_EL_IDLE_IN_L0 */ - set_pcie_enable_bits(dev, 0xB1, 1 << 20, 1 << 20); - /* 5.10.8.18. LC_DONT_GO_TO_L0S_IFL1_ARMED */ - set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11); - /* 5.10.8.19. RXP_REALIGN_ON_EACH_TSX_OR_SKP */ - set_pcie_enable_bits(nb_dev, 0x40 | gfx_gpp_sb_sel, 1 << 28, 0 << 28); - /* 5.10.8.20. Bypass lane de-skew logic if in x1 */ - set_pcie_enable_bits(nb_dev, 0xC2 | gfx_gpp_sb_sel, 1 << 14, 1 << 14); - /* 5.10.8.21. sets electrical idle threshold. */ - if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB) - set_nbmisc_enable_bits(nb_dev, 0x6A, 3 << 22, 2 << 22); - else - set_nbmisc_enable_bits(nb_dev, 0x24, 3 << 16, 2 << 16); - - /* 5.10.8.22. Disable GEN2 */ - /* TODO: should be 2 seperated cases. */ - set_nbmisc_enable_bits(nb_dev, 0x39, 1 << 31, 0 << 31); - set_nbmisc_enable_bits(nb_dev, 0x22, 1 << 5, 0 << 5); - set_nbmisc_enable_bits(nb_dev, 0x34, 1 << 31, 0 << 31); - set_nbmisc_enable_bits(nb_dev, 0x37, 7 << 5, 0 << 5); - /* 5.10.8.23. Disables GEN2 capability of the device. RPR says enable? No! */ - set_pcie_enable_bits(dev, 0xA4, 1 << 0, 0 << 0); - /* 5.10.8.24. Disable advertising upconfigure support. */ - set_pcie_enable_bits(dev, 0xA2, 1 << 13, 1 << 13); - /* 5.10.8.25-26. STRAP_BIF_DSN_EN */ - if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB) - set_nbmisc_enable_bits(nb_dev, 0x68, 1 << 19, 0 << 19); - else - set_nbmisc_enable_bits(nb_dev, 0x22, 1 << 3, 0 << 3); - /* 5.10.8.27-28. */ - set_pcie_enable_bits(nb_dev, 0xC1 | gfx_gpp_sb_sel, 1 << 0 | 1 << 2, 1 << 0 | 0 << 2); - /* 5.10.8.29. Uses the bif_core de-emphasis strength by default. */ - if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB) { - set_nbmisc_enable_bits(nb_dev, 0x67, 1 << 10, 1 << 10); - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 29, 1 << 29); - } - else { - set_nbmisc_enable_bits(nb_dev, 0x39, 1 << 30, 1 << 30); - } - /* 5.10.8.30. Set TX arbitration algorithm to round robin. */ - set_pcie_enable_bits(nb_dev, 0x1C | gfx_gpp_sb_sel, - 1 << 0 | 0x1F << 1 | 0x1F << 6, - 1 << 0 | 0x04 << 1 | 0x04 << 6); - - /* check compliance rpr step 2.1*/ - if (AtiPcieCfg.Config & PCIE_GPP_COMPLIANCE) { - u32 tmp; - tmp = nbmisc_read_index(nb_dev, 0x67); - tmp |= 1 << 3; - nbmisc_write_index(nb_dev, 0x67, tmp); - } - - /* step 5: dynamic slave CPL buffer allocation. Disable it, otherwise linux hangs. Why? */ - /* set_pcie_enable_bits(nb_dev, 0x20 | gfx_gpp_sb_sel, 1 << 11, 1 << 11); */ - - /* step 5a: Training for GPP devices */ - /* init GPP */ - switch (port) { - case 4: /* GPP */ - case 5: - case 6: - case 7: - case 9: - case 10: - /* 5.10.8.5. Blocks DMA traffic during C3 state */ - set_pcie_enable_bits(dev, 0x10, 1 << 0, 0 << 0); - /* Enabels TLP flushing */ - set_pcie_enable_bits(dev, 0x20, 1 << 19, 0 << 19); - - /* check port enable */ - if (cfg->port_enable & (1 << port)) { - PcieReleasePortTraining(nb_dev, dev, port); - if (!(AtiPcieCfg.Config & PCIE_GPP_COMPLIANCE)) { - u8 res = PcieTrainPort(nb_dev, dev, port); - printk(BIOS_DEBUG, "PcieTrainPort port=0x%x result=%d\n", port, res); - if (res) { - AtiPcieCfg.PortDetect |= 1 << port; - } - } - } - break; - case 8: /* SB */ - break; - } - PciePowerOffGppPorts(nb_dev, dev, port); -} - -/***************************************** -* Compliant with CIM_33's PCIEConfigureGPPCore -*****************************************/ -void config_gpp_core(device_t nb_dev, device_t sb_dev) -{ - u32 reg; - struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)nb_dev->chip_info; - - reg = nbmisc_read_index(nb_dev, 0x20); - if (AtiPcieCfg.Config & PCIE_ENABLE_STATIC_DEV_REMAP) - reg &= 0xfffffffd; /* set bit1 = 0 */ - else - reg |= 0x2; /* set bit1 = 1 */ - nbmisc_write_index(nb_dev, 0x20, reg); - - reg = nbmisc_read_index(nb_dev, 0x67); /* get STRAP_BIF_LINK_CONFIG_GPPSB at bit 4-7 */ - if (cfg->gppsb_configuration != ((reg >> 4) & 0xf)) - switching_gppsb_configurations(nb_dev, sb_dev); - reg = nbmisc_read_index(nb_dev, 0x2D); /* get STRAP_BIF_LINK_CONFIG_GPP at bit 7-10 */ - if (cfg->gpp_configuration != ((reg >> 7) & 0xf)) - switching_gpp_configurations(nb_dev, sb_dev); - ValidatePortEn(nb_dev); -} diff --git a/src/southbridge/amd/rs780/rs780_rev.h b/src/southbridge/amd/rs780/rs780_rev.h deleted file mode 100644 index 94ab752f9f..0000000000 --- a/src/southbridge/amd/rs780/rs780_rev.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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 __RS780_REV_H__ -#define __RS780_REV_H__ - -#define REV_RS780_A11 0 -#define REV_RS780_A12 1 -#define REV_RS780_A13 2 - -#endif /* __RS780_REV_H__ */ diff --git a/src/southbridge/amd/sb600/Makefile.inc b/src/southbridge/amd/sb600/Makefile.inc index 854539b9b3..b5903616c0 100644 --- a/src/southbridge/amd/sb600/Makefile.inc +++ b/src/southbridge/amd/sb600/Makefile.inc @@ -1,11 +1,11 @@ driver-y += sb600.c -driver-y += sb600_usb.c -driver-y += sb600_lpc.c -driver-y += sb600_sm.c -driver-y += sb600_ide.c -driver-y += sb600_sata.c -driver-y += sb600_hda.c -driver-y += sb600_ac97.c -driver-y += sb600_pci.c -ramstage-y += sb600_reset.c -romstage-y += sb600_enable_usbdebug.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 += ac97.c +driver-y += pci.c +ramstage-y += reset.c +romstage-y += enable_usbdebug.c diff --git a/src/southbridge/amd/sb600/ac97.c b/src/southbridge/amd/sb600/ac97.c new file mode 100644 index 0000000000..e9eae65fb6 --- /dev/null +++ b/src/southbridge/amd/sb600/ac97.c @@ -0,0 +1,61 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 +#include +#include +#include +#include +#include "sb600.h" + +static struct pci_operations lops_pci = { + .set_subsystem = pci_dev_set_subsystem, +}; + +static struct device_operations ac97audio_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, +/* .enable = sb600_enable, */ + .init = 0, + .scan_bus = 0, + .ops_pci = &lops_pci, +}; + +static const struct pci_driver ac97audio_driver __pci_driver = { + .ops = &ac97audio_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_SB600_ACI, +}; + +static struct device_operations ac97modem_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, +/* .enable = sb600_enable, */ + .init = 0, + .scan_bus = 0, + .ops_pci = &lops_pci, +}; + +static const struct pci_driver ac97modem_driver __pci_driver = { + .ops = &ac97modem_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_SB600_MCI, +}; diff --git a/src/southbridge/amd/sb600/bootblock.c b/src/southbridge/amd/sb600/bootblock.c index dd943d79b7..a5eb2f2fac 100644 --- a/src/southbridge/amd/sb600/bootblock.c +++ b/src/southbridge/amd/sb600/bootblock.c @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "southbridge/amd/sb600/sb600_enable_rom.c" +#include "southbridge/amd/sb600/enable_rom.c" static void bootblock_southbridge_init(void) { diff --git a/src/southbridge/amd/sb600/early_setup.c b/src/southbridge/amd/sb600/early_setup.c new file mode 100644 index 0000000000..45b29c1d58 --- /dev/null +++ b/src/southbridge/amd/sb600/early_setup.c @@ -0,0 +1,660 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 +#include +#include "sb600.h" +#include "smbus.c" + +#define SMBUS_IO_BASE 0x1000 /* Is it a temporary SMBus I/O base address? */ + /*SIZE 0x40 */ + +static void pmio_write(u8 reg, u8 value) +{ + outb(reg, PM_INDEX); + outb(value, PM_INDEX + 1); +} + +static u8 pmio_read(u8 reg) +{ + outb(reg, PM_INDEX); + return inb(PM_INDEX + 1); +} + +/* RPR 2.1: Get SB ASIC Revision. */ +static u8 get_sb600_revision(void) +{ + device_t dev; + dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); + + if (dev == PCI_DEV_INVALID) { + die("SMBUS controller not found\n"); + /* NOT REACHED */ + } + return pci_read_config8(dev, 0x08); +} + + +/*************************************** +* Legacy devices are mapped to LPC space. +* Serial port 0 +* KBC Port +* ACPI Micro-controller port +* This function does not change port 0x80 decoding. +* Console output through any port besides 0x3f8 is unsupported. +* If you use FWH ROMs, you have to setup IDSEL. +* Reviewed-by: Carl-Daniel Hailfinger +* Reviewed against AMD SB600 Register Reference Manual rev. 3.03, section 3.1 +* (LPC ISA Bridge) +***************************************/ +static void sb600_lpc_init(void) +{ + u8 reg8; + u32 reg32; + device_t dev; + + dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); /* SMBUS controller */ + /* NOTE: Set BootTimerDisable, otherwise it would keep rebooting!! + * This bit has no meaning if debug strap is not enabled. So if the + * board keeps rebooting and the code fails to reach here, we could + * disable the debug strap first. */ + reg32 = pci_read_config32(dev, 0x4C); + reg32 |= 1 << 31; + pci_write_config32(dev, 0x4C, reg32); + + /* Enable lpc controller */ + reg32 = pci_read_config32(dev, 0x64); + reg32 |= 1 << 20; + pci_write_config32(dev, 0x64, reg32); + + dev = pci_locate_device(PCI_ID(0x1002, 0x438d), 0); /* LPC Controller */ + /* Decode port 0x3f8-0x3ff (Serial 0) */ + // XXX Serial port decode on LPC is hardcoded to 0x3f8 + reg8 = pci_read_config8(dev, 0x44); + reg8 |= 1 << 6; + pci_write_config8(dev, 0x44, reg8); + + /* Decode port 0x60 & 0x64 (PS/2 keyboard) and port 0x62 & 0x66 (ACPI)*/ + reg8 = pci_read_config8(dev, 0x47); + reg8 |= (1 << 5) | (1 << 6); + pci_write_config8(dev, 0x47, reg8); + + /* Super I/O, RTC */ + reg8 = pci_read_config8(dev, 0x48); + /* Decode ports 0x2e-0x2f, 0x4e-0x4f (SuperI/O configuration) */ + reg8 |= (1 << 1) | (1 << 0); + /* Decode port 0x70-0x73 (RTC) */ + reg8 |= (1 << 6); + pci_write_config8(dev, 0x48, reg8); +} + +/* what is its usage? */ +static u32 get_sbdn(u32 bus) +{ + device_t dev; + + /* Find the device. */ + dev = pci_locate_device_on_bus(PCI_ID(0x1002, 0x4385), bus); + return (dev >> 15) & 0x1f; +} + +static u8 dual_core(void) +{ + return (pci_read_config32(PCI_DEV(0, 0x18, 3), 0xE8) & (0x3<<12)) != 0; +} + +/* + * SB600 VFSMAF (VID/FID System Management Action Field) is 010b by default. + * RPR 2.3.3 C-state and VID/FID change for the K8 platform. +*/ +static void enable_fid_change_on_sb(u32 sbbusn, u32 sbdn) +{ + u8 byte; + byte = pmio_read(0x9a); + byte &= ~0x34; + if (dual_core()) + byte |= 0x34; + else + byte |= 0x04; + pmio_write(0x9a, byte); + + byte = pmio_read(0x8f); + byte &= ~0x30; + byte |= 0x20; + pmio_write(0x8f, byte); + + pmio_write(0x8b, 0x01); + pmio_write(0x8a, 0x90); + + if(get_sb600_revision() > 0x13) + pmio_write(0x88, 0x10); + else + pmio_write(0x88, 0x06); + + byte = pmio_read(0x7c); + byte &= ~0x01; + byte |= 0x01; + pmio_write(0x7c, byte); + + /* Must be 0 for K8 platform. */ + byte = pmio_read(0x68); + byte &= ~0x01; + pmio_write(0x68, byte); + /* Must be 0 for K8 platform. */ + byte = pmio_read(0x8d); + byte &= ~(1<<6); + pmio_write(0x8d, byte); + + byte = pmio_read(0x61); + byte &= ~0x04; + pmio_write(0x61, byte); + + byte = pmio_read(0x42); + byte &= ~0x04; + pmio_write(0x42, byte); + + if (get_sb600_revision() == 0x14) { + pmio_write(0x89, 0x10); + + byte = pmio_read(0x52); + byte |= 0x80; + pmio_write(0x52, byte); + } +} + +void hard_reset(void) +{ + set_bios_reset(); + + /* full reset */ + outb(0x0a, 0x0cf9); + outb(0x0e, 0x0cf9); +} + +void soft_reset(void) +{ + set_bios_reset(); + /* link reset */ + outb(0x06, 0x0cf9); +} + +void sb600_pci_port80(void) +{ + u8 byte; + device_t dev; + + /* P2P Bridge */ + dev = pci_locate_device(PCI_ID(0x1002, 0x4384), 0); + + /* Chip Control: Enable subtractive decoding */ + byte = pci_read_config8(dev, 0x40); + byte |= 1 << 5; + pci_write_config8(dev, 0x40, byte); + + /* Misc Control: Enable subtractive decoding if 0x40 bit 5 is set */ + byte = pci_read_config8(dev, 0x4B); + byte |= 1 << 7; + pci_write_config8(dev, 0x4B, byte); + + /* The same IO Base and IO Limit here is meaningful because we set the + * bridge to be subtractive. During early setup stage, we have to make + * sure that data can go through port 0x80. + */ + /* IO Base: 0xf000 */ + byte = pci_read_config8(dev, 0x1C); + byte |= 0xF << 4; + pci_write_config8(dev, 0x1C, byte); + + /* IO Limit: 0xf000 */ + byte = pci_read_config8(dev, 0x1D); + byte |= 0xF << 4; + pci_write_config8(dev, 0x1D, byte); + + /* PCI Command: Enable IO response */ + byte = pci_read_config8(dev, 0x04); + byte |= 1 << 0; + pci_write_config8(dev, 0x04, byte); + + /* LPC controller */ + dev = pci_locate_device(PCI_ID(0x1002, 0x438D), 0); + + byte = pci_read_config8(dev, 0x4A); + byte &= ~(1 << 5); /* disable lpc port 80 */ + pci_write_config8(dev, 0x4A, byte); +} + +void sb600_lpc_port80(void) +{ + u8 byte; + device_t dev; + u32 reg32; + + /* Enable LPC controller */ + dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); + reg32 = pci_read_config32(dev, 0x64); + reg32 |= 0x00100000; /* lpcEnable */ + pci_write_config32(dev, 0x64, reg32); + + /* Enable port 80 LPC decode in pci function 3 configuration space. */ + dev = pci_locate_device(PCI_ID(0x1002, 0x438d), 0); + byte = pci_read_config8(dev, 0x4a); + byte |= 1 << 5; /* enable port 80 */ + pci_write_config8(dev, 0x4a, byte); +} + +/* sbDevicesPorInitTable */ +static void sb600_devices_por_init(void) +{ + device_t dev; + u8 byte; + + printk(BIOS_INFO, "sb600_devices_por_init()\n"); + /* SMBus Device, BDF:0-20-0 */ + printk(BIOS_INFO, "sb600_devices_por_init(): SMBus Device, BDF:0-20-0\n"); + dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); + + if (dev == PCI_DEV_INVALID) { + die("SMBUS controller not found\n"); + /* NOT REACHED */ + } + printk(BIOS_INFO, "SMBus controller enabled, sb revision is 0x%x\n", + get_sb600_revision()); + + /* sbPorAtStartOfTblCfg */ + /* Set A-Link bridge access address. This address is set at device 14h, function 0, register 0xf0. + * This is an I/O address. The I/O address must be on 16-byte boundry. */ + pci_write_config32(dev, 0xf0, AB_INDX); + + /* To enable AB/BIF DMA access, a specific register inside the BIF register space needs to be configured first. */ + /*Enables the SB600 to send transactions upstream over A-Link Express interface. */ + axcfg_reg(0x04, 1 << 2, 1 << 2); + axindxc_reg(0x21, 0xff, 0); + + /* 2.3.5:Enabling Non-Posted Memory Write for the K8 Platform */ + axindxc_reg(0x10, 1 << 9, 1 << 9); + /* END of sbPorAtStartOfTblCfg */ + + /* sbDevicesPorInitTables */ + /* set smbus iobase */ + pci_write_config32(dev, 0x10, SMBUS_IO_BASE | 1); + + /* enable smbus controller interface */ + byte = pci_read_config8(dev, 0xd2); + byte |= (1 << 0); + pci_write_config8(dev, 0xd2, byte); + + /* set smbus 1, ASF 2.0 (Alert Standard Format), iobase */ + pci_write_config16(dev, 0x58, SMBUS_IO_BASE | 0x11); + + /* TODO: I don't know the useage of followed two lines. I copied them from CIM. */ + pci_write_config8(dev, 0x0a, 0x1); + pci_write_config8(dev, 0x0b, 0x6); + + /* KB2RstEnable */ + pci_write_config8(dev, 0x40, 0xd4); + + /* Enable ISA Address 0-960K decoding */ + pci_write_config8(dev, 0x48, 0x0f); + + /* Enable ISA Address 0xC0000-0xDFFFF decode */ + pci_write_config8(dev, 0x49, 0xff); + + /* Enable decode cycles to IO C50, C51, C52 GPM controls. */ + byte = pci_read_config8(dev, 0x41); + byte &= 0x80; + byte |= 0x33; + pci_write_config8(dev, 0x41, byte); + + /* Legacy DMA Prefetch Enhancement, CIM masked it. */ + /* pci_write_config8(dev, 0x43, 0x1); */ + + /* Disabling Legacy USB Fast SMI# */ + byte = pci_read_config8(dev, 0x62); + byte |= 0x24; + pci_write_config8(dev, 0x62, byte); + + /* Features Enable */ + pci_write_config32(dev, 0x64, 0x829E7DBF); /* bit10: Enables the HPET interrupt. */ + + /* SerialIrq Control */ + pci_write_config8(dev, 0x69, 0x90); + + /* Test Mode, PCIB_SReset_En Mask is set. */ + pci_write_config8(dev, 0x6c, 0x20); + + /* IO Address Enable, CIM set 0x78 only and masked 0x79. */ + /*pci_write_config8(dev, 0x79, 0x4F); */ + pci_write_config8(dev, 0x78, 0xFF); + + /* This register is not used on sb600. It came from older chipset. */ + /*pci_write_config8(dev, 0x95, 0xFF); */ + + /* Set smbus iospace enable, I don't know why write 0x04 into reg5 that is reserved */ + pci_write_config16(dev, 0x4, 0x0407); + + /* clear any lingering errors, so the transaction will run */ + outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); + + /* IDE Device, BDF:0-20-1 */ + printk(BIOS_INFO, "sb600_devices_por_init(): IDE Device, BDF:0-20-1\n"); + dev = pci_locate_device(PCI_ID(0x1002, 0x438C), 0); + /* Disable prefetch */ + byte = pci_read_config8(dev, 0x63); + byte |= 0x1; + pci_write_config8(dev, 0x63, byte); + + /* LPC Device, BDF:0-20-3 */ + printk(BIOS_INFO, "sb600_devices_por_init(): LPC Device, BDF:0-20-3\n"); + dev = pci_locate_device(PCI_ID(0x1002, 0x438D), 0); + /* DMA enable */ + pci_write_config8(dev, 0x40, 0x04); + + /* IO Port Decode Enable */ + pci_write_config8(dev, 0x44, 0xFF); + pci_write_config8(dev, 0x45, 0xFF); + pci_write_config8(dev, 0x46, 0xC3); + pci_write_config8(dev, 0x47, 0xFF); + + // TODO: This has already been done(?) + /* IO/Mem Port Decode Enable, I don't know why CIM disable some ports. + * Disable LPC TimeOut counter, enable SuperIO Configuration Port (2e/2f), + * Alternate SuperIO Configuration Port (4e/4f), Wide Generic IO Port (64/65). */ + byte = pci_read_config8(dev, 0x48); + byte |= (1 << 1) | (1 << 0); /* enable Super IO config port 2e-2h, 4e-4f */ + byte |= 1 << 6; /* enable for RTC I/O range */ + pci_write_config8(dev, 0x48, byte); + pci_write_config8(dev, 0x49, 0xFF); + /* Enable 0x480-0x4bf, 0x4700-0x470B */ + byte = pci_read_config8(dev, 0x4A); + byte |= ((1 << 1) + (1 << 6)); /*0x42, save the configuraion for port 0x80. */ + pci_write_config8(dev, 0x4A, byte); + + /* Enable Tpm12_en and Tpm_legacy. I don't know what is its usage and copied from CIM. */ + pci_write_config8(dev, 0x7C, 0x05); + + /* P2P Bridge, BDF:0-20-4, the configuration of the registers in this dev are copied from CIM, + * TODO: I don't know what are their mean? */ + printk(BIOS_INFO, "sb600_devices_por_init(): P2P Bridge, BDF:0-20-4\n"); + dev = pci_locate_device(PCI_ID(0x1002, 0x4384), 0); + /* I don't know why CIM tried to write into a read-only reg! */ + /*pci_write_config8(dev, 0x0c, 0x20) */ ; + + /* Arbiter enable. */ + pci_write_config8(dev, 0x43, 0xff); + + /* Set PCDMA request into hight priority list. */ + /* pci_write_config8(dev, 0x49, 0x1) */ ; + + pci_write_config8(dev, 0x40, 0x26); + + /* I don't know why CIM set reg0x1c as 0x11. + * System will block at sdram_initialize() if I set it before call sdram_initialize(). + * If it is necessary to set reg0x1c as 0x11, please call this function after sdram_initialize(). + * pci_write_config8(dev, 0x1c, 0x11); + * pci_write_config8(dev, 0x1d, 0x11);*/ + + /*CIM set this register; but I didn't find its description in RPR. + On DBM690T platform, I didn't find different between set and skip this register. + But on Filbert platform, the DEBUG message from serial port on Peanut board can't be displayed + after the bit0 of this register is set. + pci_write_config8(dev, 0x04, 0x21); + */ + pci_write_config8(dev, 0x0d, 0x40); + pci_write_config8(dev, 0x1b, 0x40); + /* Enable PCIB_DUAL_EN_UP will fix potential problem with PCI cards. */ + pci_write_config8(dev, 0x50, 0x01); + + /* SATA Device, BDF:0-18-0, Non-Raid-5 SATA controller */ + printk(BIOS_INFO, "sb600_devices_por_init(): SATA Device, BDF:0-18-0\n"); + dev = pci_locate_device(PCI_ID(0x1002, 0x4380), 0); + + /*PHY Global Control, we are using A14. + * default: 0x2c40 for ASIC revision A12 and below + * 0x2c00 for ASIC revision A13 and above.*/ + pci_write_config16(dev, 0x86, 0x2C00); + + /* PHY Port0-3 Control */ + pci_write_config32(dev, 0x88, 0xB400DA); + pci_write_config32(dev, 0x8c, 0xB400DA); + pci_write_config32(dev, 0x90, 0xB400DA); + pci_write_config32(dev, 0x94, 0xB400DA); + + /* Port0-3 BIST Control/Status */ + pci_write_config8(dev, 0xa5, 0xB8); + pci_write_config8(dev, 0xad, 0xB8); + pci_write_config8(dev, 0xb5, 0xB8); + pci_write_config8(dev, 0xbd, 0xB8); +} + +/* sbPmioPorInitTable, Pre-initializing PMIO register space +* The power management (PM) block is resident in the PCI/LPC/ISA bridge. +* The PM regs are accessed via IO mapped regs 0xcd6 and 0xcd7. +* The index address is first programmed into IO reg 0xcd6. +* Read or write values are accessed through IO reg 0xcd7. +*/ +static void sb600_pmio_por_init(void) +{ + u8 byte; + + printk(BIOS_INFO, "sb600_pmio_por_init()\n"); + /* K8KbRstEn, KB_RST# control for K8 system. */ + byte = pmio_read(0x66); + byte |= 0x20; + pmio_write(0x66, byte); + + /* RPR2.3.4 S3/S4/S5 Function for the K8 Platform. */ + byte = pmio_read(0x52); + byte &= 0xc0; + byte |= 0x08; + pmio_write(0x52, byte); + + /* C state enable and SLP enable in C states. */ + byte = pmio_read(0x67); + byte |= 0x6; + pmio_write(0x67, byte); + + /* CIM sets 0x0e, but bit2 is for P4 system. */ + byte = pmio_read(0x68); + byte &= 0xf0; + byte |= 0x0c; + pmio_write(0x68, byte); + + /* Watch Dog Timer Control + * Set watchdog time base to 0xfec000f0 to avoid SCSI card boot failure. + * But I don't find WDT is enabled in SMBUS 0x41 bit3 in CIM. + */ + pmio_write(0x6c, 0xf0); + pmio_write(0x6d, 0x00); + pmio_write(0x6e, 0xc0); + pmio_write(0x6f, 0xfe); + + /* rpr2.14: Enables HPET periodical mode */ + byte = pmio_read(0x9a); + byte |= 1 << 7; + pmio_write(0x9a, byte); + byte = pmio_read(0x9f); + byte |= 1 << 5; + pmio_write(0x9f, byte); + byte = pmio_read(0x9e); + byte |= (1 << 6) | (1 << 7); + pmio_write(0x9e, byte); + + /* rpr2.14: Hides SM bus controller Bar1 where stores HPET MMIO base address */ + /* We have to clear this bit here, otherwise the kernel hangs. */ + byte = pmio_read(0x55); + byte |= 1 << 7; + byte |= 1 << 1; + pmio_write(0x55, byte); + + /* rpr2.14: Make HPET MMIO decoding controlled by the memory enable bit in command register of LPC ISA bridage */ + byte = pmio_read(0x52); + byte |= 1 << 6; + pmio_write(0x52, byte); + + /* rpr2.22: PLL Reset */ + byte = pmio_read(0x86); + byte |= 1 << 7; + pmio_write(0x86, byte); + + /* rpr2.3.3 */ + /* This provides 16us delay before the assertion of LDTSTP# when C3 is entered. + * The delay will allow USB DMA to go on in a continuous manner + */ + pmio_write(0x89, 0x10); + /* Set this bit to allow pop-up request being latched during the minimum LDTSTP# assertion time */ + byte = pmio_read(0x52); + byte |= 1 << 7; + pmio_write(0x52, byte); + + /* rpr2.15: ASF Remote Control Action */ + byte = pmio_read(0x9f); + byte |= 1 << 6; + pmio_write(0x9f, byte); + + /* rpr2.19: Enabling Spread Spectrum */ + byte = pmio_read(0x42); + byte |= 1 << 7; + pmio_write(0x42, byte); +} + +/* +* Compliant with CIM_48's sbPciCfg. +* Add any south bridge setting. +*/ +static void sb600_pci_cfg(void) +{ + device_t dev; + u8 byte; + + /* SMBus Device, BDF:0-20-0 */ + dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); + /* Eable the hidden revision ID, available after A13. */ + byte = pci_read_config8(dev, 0x70); + byte |= (1 << 8); + pci_write_config8(dev, 0x70, byte); + /* rpr2.20 Disable Timer IRQ Enhancement for proper operation of the 8254 timer, 0xae[5]. */ + byte = pci_read_config8(dev, 0xae); + byte |= (1 << 5); + pci_write_config8(dev, 0xae, byte); + + /* Enable watchdog decode timer */ + byte = pci_read_config8(dev, 0x41); + byte |= (1 << 3); + pci_write_config8(dev, 0x41, byte); + + /* Set to 1 to reset USB on the software (such as IO-64 or IO-CF9 cycles) + * generated PCIRST#. */ + byte = pmio_read(0x65); + byte |= (1 << 4); + pmio_write(0x65, byte); + /*For A13 and above. */ + if (get_sb600_revision() > 0x12) { + /* rpr2.16 C-State Reset, PMIO 0x9f[7]. */ + byte = pmio_read(0x9f); + byte |= (1 << 7); + pmio_write(0x9f, byte); + /* rpr2.17 PCI Clock Period will increase to 30.8ns. 0x53[7]. */ + byte = pmio_read(0x53); + byte |= (1 << 7); + pmio_write(0x53, byte); + } + + /* IDE Device, BDF:0-20-1 */ + dev = pci_locate_device(PCI_ID(0x1002, 0x438C), 0); + /* Enable IDE Explicit prefetch, 0x63[0] clear */ + byte = pci_read_config8(dev, 0x63); + byte &= 0xfe; + pci_write_config8(dev, 0x63, byte); + + /* LPC Device, BDF:0-20-3 */ + dev = pci_locate_device(PCI_ID(0x1002, 0x438D), 0); + /* rpr7.2 Enabling LPC DMA function. */ + byte = pci_read_config8(dev, 0x40); + byte |= (1 << 2); + pci_write_config8(dev, 0x40, byte); + /* rpr7.3 Disabling LPC TimeOut. 0x48[7] clear. */ + byte = pci_read_config8(dev, 0x48); + byte &= 0x7f; + pci_write_config8(dev, 0x48, byte); + /* rpr7.5 Disabling LPC MSI Capability, 0x78[1] clear. */ + byte = pci_read_config8(dev, 0x78); + byte &= 0xfd; + pci_write_config8(dev, 0x78, byte); + + /* SATA Device, BDF:0-18-0, Non-Raid-5 SATA controller */ + dev = pci_locate_device(PCI_ID(0x1002, 0x4380), 0); + /* rpr6.8 Disabling SATA MSI Capability, for A13 and above, 0x42[7]. */ + if (0x12 < get_sb600_revision()) { + u32 reg32; + reg32 = pci_read_config32(dev, 0x40); + reg32 |= (1 << 23); + pci_write_config32(dev, 0x40, reg32); + } + + /* EHCI Device, BDF:0-19-5, ehci usb controller */ + dev = pci_locate_device(PCI_ID(0x1002, 0x4386), 0); + /* rpr5.10 Disabling USB EHCI MSI Capability. 0x50[6]. */ + byte = pci_read_config8(dev, 0x50); + byte |= (1 << 6); + pci_write_config8(dev, 0x50, byte); + + /* OHCI0 Device, BDF:0-19-0, ohci usb controller #0 */ + dev = pci_locate_device(PCI_ID(0x1002, 0x4387), 0); + /* rpr5.11 Disabling USB OHCI MSI Capability. 0x40[12:8]=0x1f. */ + byte = pci_read_config8(dev, 0x41); + byte |= 0x1f; + pci_write_config8(dev, 0x41, byte); + +} + +/* +* Compliant with CIM_48's ATSBPowerOnResetInitJSP +*/ +static void sb600_por_init(void) +{ + /* sbDevicesPorInitTable + sbK8PorInitTable */ + sb600_devices_por_init(); + + /* sbPmioPorInitTable + sbK8PmioPorInitTable */ + sb600_pmio_por_init(); +} + +/* +* Compliant with CIM_48's AtiSbBeforePciInit +* It should be called during early POST after memory detection and BIOS shadowing but before PCI bus enumeration. +*/ +static void sb600_before_pci_init(void) +{ + sb600_pci_cfg(); +} + +/* +* This function should be called after enable_sb600_smbus(). +*/ +static void sb600_early_setup(void) +{ + printk(BIOS_INFO, "sb600_early_setup()\n"); + sb600_por_init(); +} + +static int smbus_read_byte(u32 device, u32 address) +{ + return do_smbus_read_byte(SMBUS_IO_BASE, device, address); +} + diff --git a/src/southbridge/amd/sb600/enable_rom.c b/src/southbridge/amd/sb600/enable_rom.c new file mode 100644 index 0000000000..b2668420ce --- /dev/null +++ b/src/southbridge/amd/sb600/enable_rom.c @@ -0,0 +1,65 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 +#include +#include +#include + +/* + * 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 SB600 power-on default is to map 256K ROM space. + * + * Details: AMD SB600 BIOS Developer's Guide (BDG), page 15. + */ +static void sb600_enable_rom(void) +{ + u8 reg8; + device_t dev; + + dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_ATI, + PCI_DEVICE_ID_ATI_SB600_LPC), 0); + + /* 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, 0xffc0); /* 4 MB */ + /* Enable LPC ROM range end at 0xffff(ffff). */ + pci_write_config16(dev, 0x6e, 0xffff); +} diff --git a/src/southbridge/amd/sb600/enable_usbdebug.c b/src/southbridge/amd/sb600/enable_usbdebug.c new file mode 100644 index 0000000000..b4d97b0da2 --- /dev/null +++ b/src/southbridge/amd/sb600/enable_usbdebug.c @@ -0,0 +1,45 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 +#include +#include +#include +#include +#include "sb600.h" + +/* Required for successful build, but currently empty. */ +void set_debug_port(unsigned int port) +{ + /* TODO: Allow changing the physical USB port used as Debug Port. */ +} + +void sb600_enable_usbdebug(unsigned int port) +{ + device_t dev = PCI_DEV(0, 0x13, 5); /* USB EHCI, D19:F5 */ + + /* Select the requested physical USB port (1-15) as the Debug Port. */ + set_debug_port(port); + + /* Set the EHCI BAR address. */ + pci_write_config32(dev, EHCI_BAR_INDEX, CONFIG_EHCI_BAR); + + /* Enable access to the EHCI memory space registers. */ + pci_write_config8(dev, PCI_COMMAND, PCI_COMMAND_MEMORY); +} diff --git a/src/southbridge/amd/sb600/hda.c b/src/southbridge/amd/sb600/hda.c new file mode 100644 index 0000000000..84df3f169f --- /dev/null +++ b/src/southbridge/amd/sb600/hda.c @@ -0,0 +1,331 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 +#include +#include +#include +#include +#include +#include +#include "sb600.h" + +#define HDA_ICII_REG 0x68 +#define HDA_ICII_BUSY (1 << 0) +#define HDA_ICII_VALID (1 << 1) + +static int set_bits(u32 port, u32 mask, u32 val) +{ + u32 dword; + int count; + + /* Write (val & ~mask) to port */ + val &= mask; + dword = read32(port); + dword &= ~mask; + dword |= val; + write32(port, dword); + + /* Wait for readback of register to + * match what was just written to it + */ + count = 50; + do { + /* Wait 1ms based on BKDG wait time */ + mdelay(1); + dword = read32(port); + dword &= mask; + } while ((dword != val) && --count); + + /* Timeout occurred */ + if (!count) + return -1; + return 0; +} + +static u32 codec_detect(u32 base) +{ + u32 dword; + + /* Set Bit0 to 0 to enter reset state (BAR + 0x8)[0] */ + if (set_bits(base + 0x08, 1, 0) == -1) + goto no_codec; + + /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */ + if (set_bits(base + 0x08, 1, 1) == -1) + goto no_codec; + + /* Delay for 1 ms since the BKDG does */ + mdelay(1); + + /* Read in Codec location (BAR + 0xe)[3..0]*/ + dword = read32(base + 0xe); + dword &= 0x0F; + if (!dword) + goto no_codec; + + return dword; + +no_codec: + /* Codec Not found */ + /* Put HDA back in reset (BAR + 0x8) [0] */ + set_bits(base + 0x08, 1, 0); + printk(BIOS_DEBUG, "No codec!\n"); + return 0; +} + +static u32 cim_verb_data[] = { + 0x01471c10, + 0x01471d40, + 0x01471e01, + 0x01471f01, +/* 1 */ + 0x01571c12, + 0x01571d10, + 0x01571e01, + 0x01571f01, +/* 2 */ + 0x01671c11, + 0x01671d60, + 0x01671e01, + 0x01671f01, +/* 3 */ + 0x01771c14, + 0x01771d20, + 0x01771e01, + 0x01771f01, +/* 4 */ + 0x01871c30, + 0x01871d90, + 0x01871ea1, + 0x01871f01, +/* 5 */ + 0x01971cf0, + 0x01971d11, + 0x01971e11, + 0x01971f41, +/* 6 */ + 0x01a71c80, + 0x01a71d30, + 0x01a71e81, + 0x01a71f01, +/* 7 */ + 0x01b71cf0, + 0x01b71d11, + 0x01b71e11, + 0x01b71f41, +/* 8 */ + 0x01c71cf0, + 0x01c71d11, + 0x01c71e11, + 0x01c71f41, +/* 9 */ + 0x01d71cf0, + 0x01d71d11, + 0x01d71e11, + 0x01d71f41, +/* 10 */ + 0x01e71c50, + 0x01e71d11, + 0x01e71e44, + 0x01e71f01, +/* 11 */ + 0x01f71c60, + 0x01f71d61, + 0x01f71ec4, + 0x01f71f01, +}; + +static u32 find_verb(u32 viddid, u32 ** verb) +{ + device_t azalia_dev = dev_find_slot(0, PCI_DEVFN(0x14, 2)); + struct southbridge_amd_sb600_config *cfg = + (struct southbridge_amd_sb600_config *)azalia_dev->chip_info; + printk(BIOS_DEBUG, "Dev=%s\n", dev_path(azalia_dev)); + printk(BIOS_DEBUG, "Default viddid=%x\n", cfg->hda_viddid); + printk(BIOS_DEBUG, "Reading viddid=%x\n", viddid); + if (!cfg) + return 0; + if (viddid != cfg->hda_viddid) + return 0; + *verb = (u32 *) cim_verb_data; + return sizeof(cim_verb_data) / sizeof(u32); +} + +/** + * Wait 50usec for the codec to indicate it is ready + * no response would imply that the codec is non-operative + */ +static int wait_for_ready(u32 base) +{ + /* Use a 50 usec timeout - the Linux kernel uses the + * same duration */ + + int timeout = 50; + + while(timeout--) { + u32 dword=read32(base + HDA_ICII_REG); + if (!(dword & HDA_ICII_BUSY)) + return 0; + udelay(1); + } + + return -1; +} + +/** + * Wait 50usec for the codec to indicate that it accepted + * the previous command. No response would imply that the code + * is non-operative + */ +static int wait_for_valid(u32 base) +{ + /* Use a 50 usec timeout - the Linux kernel uses the + * same duration */ + + int timeout = 50; + while(timeout--) { + u32 dword = read32(base + HDA_ICII_REG); + if ((dword & (HDA_ICII_VALID | HDA_ICII_BUSY)) == + HDA_ICII_VALID) + return 0; + udelay(1); + } + + return 1; +} + +static void codec_init(u32 base, int addr) +{ + u32 dword; + u32 *verb; + u32 verb_size; + int i; + + /* 1 */ + if (wait_for_ready(base) == -1) + return; + + dword = (addr << 28) | 0x000f0000; + write32(base + 0x60, dword); + + if (wait_for_valid(base) == -1) + return; + + dword = read32(base + 0x64); + + /* 2 */ + printk(BIOS_DEBUG, "codec viddid: %08x\n", dword); + verb_size = find_verb(dword, &verb); + + if (!verb_size) { + printk(BIOS_DEBUG, "No verb!\n"); + return; + } + + printk(BIOS_DEBUG, "verb_size: %d\n", verb_size); + /* 3 */ + for (i = 0; i < verb_size; i++) { + if (wait_for_ready(base) == -1) + return; + + write32(base + 0x60, verb[i]); + + if (wait_for_valid(base) == -1) + return; + } + printk(BIOS_DEBUG, "verb loaded!\n"); +} + +static void codecs_init(u32 base, u32 codec_mask) +{ + int i; + for (i = 2; i >= 0; i--) { + if (codec_mask & (1 << i)) + codec_init(base, i); + } +} + +static void hda_init(struct device *dev) +{ + u8 byte; + u32 dword; + u32 base; + struct resource *res; + u32 codec_mask; + device_t sm_dev; + + /* Enable azalia - PM_io 0x59[4], disable ac97 - PM_io 0x59[1..0] */ + pm_iowrite(0x59, 0xB); + + /* Find the SMBus */ + /* FIXME: Need to find out why the call below crashes. */ + /*sm_dev = dev_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_ATI_SB600_SM, 0);*/ + sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0)); + + /* Set routing pin - SMBus ExtFunc (0xf8/0xfc) */ + pci_write_config32(sm_dev, 0xf8, 0x00); + pci_write_config8(sm_dev, 0xfc, 0xAA); + /* Set INTA - SMBus 0x63 [2..0] */ + byte = pci_read_config8(sm_dev, 0x63); + byte &= ~0x7; + byte |= 0x0; /* INTA:0x0 - INTH:0x7 */ + pci_write_config8(sm_dev, 0x63, byte); + + /* Program the 2C to 0x437b1002 */ + dword = 0x437b1002; + pci_write_config32(dev, 0x2c, dword); + + /* Read in BAR */ + /* Is this right? HDA allows for a 64-bit BAR + * but this is only setup for a 32-bit one + */ + res = find_resource(dev, 0x10); + if (!res) + return; + + base = (u32)res->base; + printk(BIOS_DEBUG, "base = 0x%x\n", base); + codec_mask = codec_detect(base); + + if (codec_mask) { + printk(BIOS_DEBUG, "codec_mask = %02x\n", codec_mask); + codecs_init(base, codec_mask); + } +} + +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, + /*.enable = sb600_enable, */ + .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_ATI, + .device = PCI_DEVICE_ID_ATI_SB600_HDA, +}; diff --git a/src/southbridge/amd/sb600/ide.c b/src/southbridge/amd/sb600/ide.c new file mode 100644 index 0000000000..e38e83fdd7 --- /dev/null +++ b/src/southbridge/amd/sb600/ide.c @@ -0,0 +1,72 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 +#include +#include +#include +#include +#include "sb600.h" + +static void ide_init(struct device *dev) +{ + /* Enable ide devices so the linux ide driver will work */ + u32 dword; + u8 byte; + + /* RPR10.1 disable MSI */ + dword = pci_read_config32(dev, 0x70); + dword &= ~(1 << 16); + pci_write_config32(dev, 0x70, dword); + + /* Enable UDMA on all devices, it will become UDMA0 (default PIO is PIO0) */ + byte = pci_read_config8(dev, 0x54); + byte |= 0xf; + pci_write_config8(dev, 0x54, byte); + + /* Enable I/O Access&& Bus Master */ + dword = pci_read_config16(dev, 0x4); + dword |= 1 << 2; + pci_write_config16(dev, 0x4, dword); + +#if CONFIG_PCI_ROM_RUN == 1 + pci_dev_init(dev); +#endif + +} + +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, + /* .enable = sb600_enable, */ + .ops_pci = &lops_pci, +}; + +static const struct pci_driver ide_driver __pci_driver = { + .ops = &ide_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_SB600_IDE, +}; diff --git a/src/southbridge/amd/sb600/lpc.c b/src/southbridge/amd/sb600/lpc.c new file mode 100644 index 0000000000..6a17f72318 --- /dev/null +++ b/src/southbridge/amd/sb600/lpc.c @@ -0,0 +1,225 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sb600.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(); + + /* RPR 7.2 Enable DMA transaction on the LPC bus */ + byte = pci_read_config8(dev, 0x40); + byte |= (1 << 2); + pci_write_config8(dev, 0x40, byte); + + /* RPR 7.3 Disable the timeout mechanism on LPC */ + byte = pci_read_config8(dev, 0x48); + byte &= ~(1 << 7); + pci_write_config8(dev, 0x48, byte); + + /* RPR 7.5 Disable LPC MSI Capability */ + byte = pci_read_config8(dev, 0x78); + byte &= ~(1 << 1); + pci_write_config8(dev, 0x78, byte); + +} + +static void sb600_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 = IO_APIC_ADDR; + res->size = 0x00001000; + res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + + compact_resources(dev); +} + +/** + * @brief Enable resources for children devices + * + * @param dev the device whos children's resources are to be enabled + * + */ +static void sb600_lpc_enable_childrens_resources(device_t dev) +{ + struct bus *link; + u32 reg, reg_x; + int var_num = 0; + u16 reg_var[3]; + + reg = pci_read_config32(dev, 0x44); + reg_x = pci_read_config32(dev, 0x48); + + for (link = dev->link_list; link; link = link->next) { + device_t child; + for (child = link->children; child; + child = child->sibling) { + if (child->enabled + && (child->path.type == DEVICE_PATH_PNP)) { + struct resource *res; + for (res = child->resource_list; res; res = res->next) { + u32 base, end; /* don't need long long */ + if (!(res->flags & IORESOURCE_IO)) + continue; + base = res->base; + end = resource_end(res); + printk(BIOS_DEBUG, "sb600 lpc decode:%s, base=0x%08x, end=0x%08x\n", + dev_path(child), base, end); + switch (base) { + case 0x60: /* KB */ + case 0x64: /* MS */ + reg |= (1 << 29); + break; + case 0x3f8: /* COM1 */ + reg |= (1 << 6); + break; + case 0x2f8: /* COM2 */ + reg |= (1 << 7); + break; + case 0x378: /* Parallal 1 */ + reg |= (1 << 0); + break; + case 0x3f0: /* FD0 */ + reg |= (1 << 26); + break; + case 0x220: /* Aduio 0 */ + reg |= (1 << 8); + break; + case 0x300: /* Midi 0 */ + reg |= (1 << 18); + break; + case 0x400: + reg_x |= (1 << 16); + break; + case 0x480: + reg_x |= (1 << 17); + break; + case 0x500: + reg_x |= (1 << 18); + break; + case 0x580: + reg_x |= (1 << 19); + break; + case 0x4700: + reg_x |= (1 << 22); + break; + case 0xfd60: + reg_x |= (1 << 23); + break; + default: + if (var_num >= 3) + continue; /* only 3 var ; compact them ? */ + switch (var_num) { + case 0: + reg_x |= (1 << 2); + break; + case 1: + reg_x |= (1 << 24); + break; + case 2: + reg_x |= (1 << 25); + break; + } + reg_var[var_num++] = + base & 0xffff; + } + } + } + } + } + pci_write_config32(dev, 0x44, reg); + pci_write_config32(dev, 0x48, reg_x); + /* Set WideIO for as many IOs found (fall through is on purpose) */ + switch (var_num) { + case 2: + pci_write_config16(dev, 0x90, reg_var[2]); + case 1: + pci_write_config16(dev, 0x66, reg_var[1]); + case 0: + pci_write_config16(dev, 0x64, reg_var[0]); + break; + } +} + +static void sb600_lpc_enable_resources(device_t dev) +{ + pci_dev_enable_resources(dev); + sb600_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 = sb600_lpc_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = sb600_lpc_enable_resources, + .init = lpc_init, + .scan_bus = scan_static_bus, + /* .enable = sb600_enable, */ + .ops_pci = &lops_pci, +}; +static const struct pci_driver lpc_driver __pci_driver = { + .ops = &lpc_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_SB600_LPC, +}; diff --git a/src/southbridge/amd/sb600/pci.c b/src/southbridge/amd/sb600/pci.c new file mode 100644 index 0000000000..66ca29bd78 --- /dev/null +++ b/src/southbridge/amd/sb600/pci.c @@ -0,0 +1,142 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 +#include +#include +#include +#include +#include "sb600.h" + +static void pci_init(struct device *dev) +{ + u32 dword; + u16 word; + u8 byte; + + /* RPR 4.1 Enables the PCI-bridge subtractive decode */ + /* This setting is strongly recommended since it supports some legacy PCI add-on cards,such as BIOS debug cards */ + byte = pci_read_config8(dev, 0x4B); + byte |= 1 << 7; + pci_write_config8(dev, 0x4B, byte); + byte = pci_read_config8(dev, 0x40); + byte |= 1 << 5; + pci_write_config8(dev, 0x40, byte); + + /* RPR4.2 PCI-bridge upstream dual address window */ + /* this setting is applicable if the system memory is more than 4GB,and the PCI device can support dual address access */ + byte = pci_read_config8(dev, 0x50); + byte |= 1 << 0; + pci_write_config8(dev, 0x50, byte); + + /* RPR 4.3 PCI bus 64-byte DMA read access */ + /* Enhance the PCI bus DMA performance */ + byte = pci_read_config8(dev, 0x4B); + byte |= 1 << 4; + pci_write_config8(dev, 0x4B, byte); + + /* RPR 4.4 Enables the PCIB writes to be cacheline aligned. */ + /* The size of the writes will be set in the Cacheline Register */ + byte = pci_read_config8(dev, 0x40); + byte |= 1 << 1; + pci_write_config8(dev, 0x40, byte); + + /* RPR 4.5 Enables the PCIB to retain ownership of the bus on the Primary side and on the Secondary side when GNT# is deasserted */ + pci_write_config8(dev, 0x0D, 0x40); + pci_write_config8(dev, 0x1B, 0x40); + + /* RPR 4.6 Enable the command matching checking function on "Memory Read" & "Memory Read Line" commands */ + byte = pci_read_config8(dev, 0x4B); + byte |= 1 << 6; + pci_write_config8(dev, 0x4B, byte); + + /* RPR 4.7 When enabled, the PCI arbiter checks for the Bus Idle before asserting GNT# */ + byte = pci_read_config8(dev, 0x4B); + byte |= 1 << 0; + pci_write_config8(dev, 0x4B, byte); + + /* RPR 4.8 Adjusts the GNT# de-assertion time */ + word = pci_read_config16(dev, 0x64); + word |= 1 << 12; + pci_write_config16(dev, 0x64, word); + + /* RPR 4.9 Fast Back to Back transactions support */ + byte = pci_read_config8(dev, 0x48); + byte |= 1 << 2; + pci_write_config8(dev, 0x48, byte); + + /* RPR 4.10 Enable Lock Operation */ + byte = pci_read_config8(dev, 0x48); + byte |= 1 << 3; + pci_write_config8(dev, 0x48, byte); + byte = pci_read_config8(dev, 0x40); + byte |= (1 << 2); + pci_write_config8(dev, 0x40, byte); + + /* RPR 4.11 Enable additional optional PCI clock */ + word = pci_read_config16(dev, 0x64); + word |= 1 << 8; + pci_write_config16(dev, 0x64, word); + + /* rpr4.12 Disable Fewer-Retry Mode for A11-A13 only. 0x64[5:4] clear */ + byte = pci_read_config8(dev, 0x64); + byte &= 0xcf; + pci_write_config8(dev, 0x64, byte); + + /* rpr4.14 Disabling Downstream Flush, for A12 only, 0x64[18]. */ + dword = pci_read_config32(dev, 0x64); + dword |= (1 << 18); + pci_write_config32(dev, 0x64, dword); + + /* RPR 4.13 Enable One-Prefetch-Channel Mode */ + dword = pci_read_config32(dev, 0x64); + dword |= 1 << 20; + pci_write_config32(dev, 0x64, dword); + + /* RPR 4.15 Disable PCIB MSI Capability */ + byte = pci_read_config8(dev, 0x40); + byte &= ~(1 << 3); + pci_write_config8(dev, 0x40, byte); + + /* rpr4.16 Adjusting CLKRUN# */ + dword = pci_read_config32(dev, 0x64); + dword |= (1 << 15); + pci_write_config32(dev, 0x64, dword); +} + +static struct pci_operations lops_pci = { + .set_subsystem = 0, +}; + +static struct device_operations pci_ops = { + .read_resources = pci_bus_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_bus_enable_resources, + .init = pci_init, + .scan_bus = pci_scan_bridge, + /* .enable = sb600_enable, */ + .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_ATI, + .device = PCI_DEVICE_ID_ATI_SB600_PCI, +}; diff --git a/src/southbridge/amd/sb600/reset.c b/src/southbridge/amd/sb600/reset.c new file mode 100644 index 0000000000..af80576204 --- /dev/null +++ b/src/southbridge/amd/sb600/reset.c @@ -0,0 +1,33 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 +#include +#include + +#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/sb600/sata.c b/src/southbridge/amd/sb600/sata.c new file mode 100644 index 0000000000..055e7daa85 --- /dev/null +++ b/src/southbridge/amd/sb600/sata.c @@ -0,0 +1,265 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2008 Carl-Daniel Hailfinger + * + * 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 +#include +#include +#include +#include +#include +#include +#include "sb600.h" + +static int sata_drive_detect(int portnum, u16 iobar) +{ + u8 byte, byte2; + int i = 0; + outb(0xA0 + 0x10 * (portnum % 2), iobar + 0x6); + while (byte = inb(iobar + 0x6), byte2 = inb(iobar + 0x7), + (byte != (0xA0 + 0x10 * (portnum % 2))) || + ((byte2 & 0x88) != 0)) { + printk(BIOS_SPEW, "0x6=%x, 0x7=%x\n", byte, byte2); + if (byte != (0xA0 + 0x10 * (portnum % 2))) { + /* This will happen at the first iteration of this loop + * if the first SATA port is unpopulated and the + * second SATA port is populated. + */ + printk(BIOS_DEBUG, "drive no longer selected after %i ms, " + "retrying init\n", i * 10); + return 1; + } else + printk(BIOS_SPEW, "drive detection not yet completed, " + "waiting...\n"); + mdelay(10); + i++; + } + printk(BIOS_SPEW, "drive detection done after %i ms\n", i * 10); + return 0; +} + +static void sata_init(struct device *dev) +{ + u8 byte; + u16 word; + u32 dword; + u32 sata_bar5; + u16 sata_bar0, sata_bar1, sata_bar2, sata_bar3, sata_bar4; + int i, j; + + struct southbridge_ati_sb600_config *conf; + conf = dev->chip_info; + + device_t sm_dev; + /* SATA SMBus Disable */ + /* sm_dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); */ + sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0)); + /* Disable SATA SMBUS */ + byte = pci_read_config8(sm_dev, 0xad); + byte |= (1 << 1); + /* Enable SATA and power saving */ + byte = pci_read_config8(sm_dev, 0xad); + byte |= (1 << 0); + byte |= (1 << 5); + pci_write_config8(sm_dev, 0xad, byte); + /* Set the interrupt Mapping to INTG# */ + byte = pci_read_config8(sm_dev, 0xaf); + byte = 0x6 << 2; + pci_write_config8(sm_dev, 0xaf, byte); + + /* get base address */ + sata_bar5 = pci_read_config32(dev, 0x24) & ~0x3FF; + sata_bar0 = pci_read_config16(dev, 0x10) & ~0x7; + sata_bar1 = pci_read_config16(dev, 0x14) & ~0x3; + sata_bar2 = pci_read_config16(dev, 0x18) & ~0x7; + sata_bar3 = pci_read_config16(dev, 0x1C) & ~0x3; + sata_bar4 = pci_read_config16(dev, 0x20) & ~0xf; + + printk(BIOS_SPEW, "sata_bar0=%x\n", sata_bar0); /* 3030 */ + printk(BIOS_SPEW, "sata_bar1=%x\n", sata_bar1); /* 3070 */ + printk(BIOS_SPEW, "sata_bar2=%x\n", sata_bar2); /* 3040 */ + printk(BIOS_SPEW, "sata_bar3=%x\n", sata_bar3); /* 3080 */ + printk(BIOS_SPEW, "sata_bar4=%x\n", sata_bar4); /* 3000 */ + printk(BIOS_SPEW, "sata_bar5=%x\n", sata_bar5); /* e0309000 */ + + /* Program the 2C to 0x43801002 */ + dword = 0x43801002; + pci_write_config32(dev, 0x2c, dword); + + /* SERR-Enable */ + word = pci_read_config16(dev, 0x04); + word |= (1 << 8); + pci_write_config16(dev, 0x04, word); + + /* Dynamic power saving */ + byte = pci_read_config8(dev, 0x40); + byte |= (1 << 2); + pci_write_config8(dev, 0x40, byte); + + /* Set SATA Operation Mode, Set to IDE mode */ + byte = pci_read_config8(dev, 0x40); + byte |= (1 << 0); + byte |= (1 << 4); + pci_write_config8(dev, 0x40, byte); + + dword = 0x01018f00; + pci_write_config32(dev, 0x8, dword); + + byte = pci_read_config8(dev, 0x40); + byte &= ~(1 << 0); + pci_write_config8(dev, 0x40, byte); + + /* Enable the SATA watchdog counter */ + byte = pci_read_config8(dev, 0x44); + byte |= (1 << 0); + pci_write_config8(dev, 0x44, byte); + + /* Program the watchdog counter to 0x10 */ + byte = 0x10; + pci_write_config8(dev, 0x46, byte); + + /* RPR6.5 Program the PHY Global Control to 0x2C00 for A13 */ + word = 0x2c00; + pci_write_config16(dev, 0x86, word); + + /* RPR6.5 Program the Phy Tuning4Ports */ + dword = 0x00B401D6; + pci_write_config32(dev, 0x88, dword); + pci_write_config32(dev, 0x8c, dword); + pci_write_config32(dev, 0x90, dword); + pci_write_config32(dev, 0x94, dword); + + byte = 0xB8; + pci_write_config8(dev, 0xA5, byte); + pci_write_config8(dev, 0xAD, byte); + pci_write_config8(dev, 0xB5, byte); + pci_write_config8(dev, 0xBD, byte); + + /* RPR 6.8 */ + word = pci_read_config16(dev, 0x42); + word |= 1 << 7; + pci_write_config16(dev, 0x42, word); + /* RPR 6.9 */ + dword = pci_read_config32(dev, 0x40); + dword |= 1 << 25; + pci_write_config32(dev, 0x40, dword); + + /* Enable the I/O, MM, BusMaster access for SATA */ + byte = pci_read_config8(dev, 0x4); + byte |= 7 << 0; + pci_write_config8(dev, 0x4, byte); + + /* RPR6.6 SATA drive detection. */ + /* Use BAR5+0x128,BAR0 for Primary Slave */ + /* Use BAR5+0x1A8,BAR0 for Primary Slave */ + /* Use BAR5+0x228,BAR2 for Secondary Master */ + /* Use BAR5+0x2A8,BAR2 for Secondary Slave */ + + for (i = 0; i < 4; i++) { + byte = read8(sata_bar5 + 0x128 + 0x80 * i); + printk(BIOS_SPEW, "SATA port %i status = %x\n", i, byte); + byte &= 0xF; + + if( byte == 0x1 ) { + /* If the drive status is 0x1 then we see it but we aren't talking to it. */ + /* Try to do something about it. */ + printk(BIOS_SPEW, "SATA device detected but not talking. Trying lower speed.\n"); + + /* Read in Port-N Serial ATA Control Register */ + byte = read8(sata_bar5 + 0x12C + 0x80 * i); + + /* Set Reset Bit and 1.5g bit */ + byte |= 0x11; + write8((sata_bar5 + 0x12C + 0x80 * i), byte); + + /* Wait 1ms */ + mdelay(1); + + /* Clear Reset Bit */ + byte &= ~0x01; + write8((sata_bar5 + 0x12C + 0x80 * i), byte); + + /* Wait 1ms */ + mdelay(1); + + /* Reread status */ + byte = read8(sata_bar5 + 0x128 + 0x80 * i); + printk(BIOS_SPEW, "SATA port %i status = %x\n", i, byte); + byte &= 0xF; + } + + if (byte == 0x3) { + for (j = 0; j < 10; j++) { + if (!sata_drive_detect(i, ((i / 2) == 0) ? sata_bar0 : sata_bar2)) + break; + } + printk(BIOS_DEBUG, "%s %s device is %sready after %i tries\n", + (i / 2) ? "Secondary" : "Primary", + (i % 2 ) ? "Slave" : "Master", + (j == 10) ? "not " : "", + (j == 10) ? j : j + 1); + } else { + printk(BIOS_DEBUG, "No %s %s SATA drive on Slot%i\n", + (i / 2) ? "Secondary" : "Primary", + (i % 2 ) ? "Slave" : "Master", i); + } + } + + /* Below is CIM InitSataLateFar */ + /* Enable interrupts from the HBA */ + byte = read8(sata_bar5 + 0x4); + byte |= 1 << 1; + write8((sata_bar5 + 0x4), byte); + + /* Clear error status */ + write32((sata_bar5 + 0x130), 0xFFFFFFFF); + write32((sata_bar5 + 0x1b0), 0xFFFFFFFF); + write32((sata_bar5 + 0x230), 0xFFFFFFFF); + write32((sata_bar5 + 0x2b0), 0xFFFFFFFF); + + /* Clear SATA status,Firstly we get the AcpiGpe0BlkAddr */ + /* ????? why CIM does not set the AcpiGpe0BlkAddr , but use it??? */ + + /* word = 0x0000; */ + /* word = pm_ioread(0x28); */ + /* byte = pm_ioread(0x29); */ + /* word |= byte<<8; */ + /* printk(BIOS_DEBUG, "AcpiGpe0Blk addr = %x\n", word); */ + /* write32(word, 0x80000000); */ +} + +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, + /* .enable = sb600_enable, */ + .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_ATI, + .device = PCI_DEVICE_ID_ATI_SB600_SATA, +}; diff --git a/src/southbridge/amd/sb600/sb600_ac97.c b/src/southbridge/amd/sb600/sb600_ac97.c deleted file mode 100644 index e9eae65fb6..0000000000 --- a/src/southbridge/amd/sb600/sb600_ac97.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 -#include -#include -#include -#include -#include "sb600.h" - -static struct pci_operations lops_pci = { - .set_subsystem = pci_dev_set_subsystem, -}; - -static struct device_operations ac97audio_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, -/* .enable = sb600_enable, */ - .init = 0, - .scan_bus = 0, - .ops_pci = &lops_pci, -}; - -static const struct pci_driver ac97audio_driver __pci_driver = { - .ops = &ac97audio_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_SB600_ACI, -}; - -static struct device_operations ac97modem_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, -/* .enable = sb600_enable, */ - .init = 0, - .scan_bus = 0, - .ops_pci = &lops_pci, -}; - -static const struct pci_driver ac97modem_driver __pci_driver = { - .ops = &ac97modem_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_SB600_MCI, -}; diff --git a/src/southbridge/amd/sb600/sb600_early_setup.c b/src/southbridge/amd/sb600/sb600_early_setup.c deleted file mode 100644 index 3ed8dd85de..0000000000 --- a/src/southbridge/amd/sb600/sb600_early_setup.c +++ /dev/null @@ -1,660 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 -#include -#include "sb600.h" -#include "sb600_smbus.c" - -#define SMBUS_IO_BASE 0x1000 /* Is it a temporary SMBus I/O base address? */ - /*SIZE 0x40 */ - -static void pmio_write(u8 reg, u8 value) -{ - outb(reg, PM_INDEX); - outb(value, PM_INDEX + 1); -} - -static u8 pmio_read(u8 reg) -{ - outb(reg, PM_INDEX); - return inb(PM_INDEX + 1); -} - -/* RPR 2.1: Get SB ASIC Revision. */ -static u8 get_sb600_revision(void) -{ - device_t dev; - dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); - - if (dev == PCI_DEV_INVALID) { - die("SMBUS controller not found\n"); - /* NOT REACHED */ - } - return pci_read_config8(dev, 0x08); -} - - -/*************************************** -* Legacy devices are mapped to LPC space. -* Serial port 0 -* KBC Port -* ACPI Micro-controller port -* This function does not change port 0x80 decoding. -* Console output through any port besides 0x3f8 is unsupported. -* If you use FWH ROMs, you have to setup IDSEL. -* Reviewed-by: Carl-Daniel Hailfinger -* Reviewed against AMD SB600 Register Reference Manual rev. 3.03, section 3.1 -* (LPC ISA Bridge) -***************************************/ -static void sb600_lpc_init(void) -{ - u8 reg8; - u32 reg32; - device_t dev; - - dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); /* SMBUS controller */ - /* NOTE: Set BootTimerDisable, otherwise it would keep rebooting!! - * This bit has no meaning if debug strap is not enabled. So if the - * board keeps rebooting and the code fails to reach here, we could - * disable the debug strap first. */ - reg32 = pci_read_config32(dev, 0x4C); - reg32 |= 1 << 31; - pci_write_config32(dev, 0x4C, reg32); - - /* Enable lpc controller */ - reg32 = pci_read_config32(dev, 0x64); - reg32 |= 1 << 20; - pci_write_config32(dev, 0x64, reg32); - - dev = pci_locate_device(PCI_ID(0x1002, 0x438d), 0); /* LPC Controller */ - /* Decode port 0x3f8-0x3ff (Serial 0) */ - // XXX Serial port decode on LPC is hardcoded to 0x3f8 - reg8 = pci_read_config8(dev, 0x44); - reg8 |= 1 << 6; - pci_write_config8(dev, 0x44, reg8); - - /* Decode port 0x60 & 0x64 (PS/2 keyboard) and port 0x62 & 0x66 (ACPI)*/ - reg8 = pci_read_config8(dev, 0x47); - reg8 |= (1 << 5) | (1 << 6); - pci_write_config8(dev, 0x47, reg8); - - /* Super I/O, RTC */ - reg8 = pci_read_config8(dev, 0x48); - /* Decode ports 0x2e-0x2f, 0x4e-0x4f (SuperI/O configuration) */ - reg8 |= (1 << 1) | (1 << 0); - /* Decode port 0x70-0x73 (RTC) */ - reg8 |= (1 << 6); - pci_write_config8(dev, 0x48, reg8); -} - -/* what is its usage? */ -static u32 get_sbdn(u32 bus) -{ - device_t dev; - - /* Find the device. */ - dev = pci_locate_device_on_bus(PCI_ID(0x1002, 0x4385), bus); - return (dev >> 15) & 0x1f; -} - -static u8 dual_core(void) -{ - return (pci_read_config32(PCI_DEV(0, 0x18, 3), 0xE8) & (0x3<<12)) != 0; -} - -/* - * SB600 VFSMAF (VID/FID System Management Action Field) is 010b by default. - * RPR 2.3.3 C-state and VID/FID change for the K8 platform. -*/ -static void enable_fid_change_on_sb(u32 sbbusn, u32 sbdn) -{ - u8 byte; - byte = pmio_read(0x9a); - byte &= ~0x34; - if (dual_core()) - byte |= 0x34; - else - byte |= 0x04; - pmio_write(0x9a, byte); - - byte = pmio_read(0x8f); - byte &= ~0x30; - byte |= 0x20; - pmio_write(0x8f, byte); - - pmio_write(0x8b, 0x01); - pmio_write(0x8a, 0x90); - - if(get_sb600_revision() > 0x13) - pmio_write(0x88, 0x10); - else - pmio_write(0x88, 0x06); - - byte = pmio_read(0x7c); - byte &= ~0x01; - byte |= 0x01; - pmio_write(0x7c, byte); - - /* Must be 0 for K8 platform. */ - byte = pmio_read(0x68); - byte &= ~0x01; - pmio_write(0x68, byte); - /* Must be 0 for K8 platform. */ - byte = pmio_read(0x8d); - byte &= ~(1<<6); - pmio_write(0x8d, byte); - - byte = pmio_read(0x61); - byte &= ~0x04; - pmio_write(0x61, byte); - - byte = pmio_read(0x42); - byte &= ~0x04; - pmio_write(0x42, byte); - - if (get_sb600_revision() == 0x14) { - pmio_write(0x89, 0x10); - - byte = pmio_read(0x52); - byte |= 0x80; - pmio_write(0x52, byte); - } -} - -void hard_reset(void) -{ - set_bios_reset(); - - /* full reset */ - outb(0x0a, 0x0cf9); - outb(0x0e, 0x0cf9); -} - -void soft_reset(void) -{ - set_bios_reset(); - /* link reset */ - outb(0x06, 0x0cf9); -} - -void sb600_pci_port80(void) -{ - u8 byte; - device_t dev; - - /* P2P Bridge */ - dev = pci_locate_device(PCI_ID(0x1002, 0x4384), 0); - - /* Chip Control: Enable subtractive decoding */ - byte = pci_read_config8(dev, 0x40); - byte |= 1 << 5; - pci_write_config8(dev, 0x40, byte); - - /* Misc Control: Enable subtractive decoding if 0x40 bit 5 is set */ - byte = pci_read_config8(dev, 0x4B); - byte |= 1 << 7; - pci_write_config8(dev, 0x4B, byte); - - /* The same IO Base and IO Limit here is meaningful because we set the - * bridge to be subtractive. During early setup stage, we have to make - * sure that data can go through port 0x80. - */ - /* IO Base: 0xf000 */ - byte = pci_read_config8(dev, 0x1C); - byte |= 0xF << 4; - pci_write_config8(dev, 0x1C, byte); - - /* IO Limit: 0xf000 */ - byte = pci_read_config8(dev, 0x1D); - byte |= 0xF << 4; - pci_write_config8(dev, 0x1D, byte); - - /* PCI Command: Enable IO response */ - byte = pci_read_config8(dev, 0x04); - byte |= 1 << 0; - pci_write_config8(dev, 0x04, byte); - - /* LPC controller */ - dev = pci_locate_device(PCI_ID(0x1002, 0x438D), 0); - - byte = pci_read_config8(dev, 0x4A); - byte &= ~(1 << 5); /* disable lpc port 80 */ - pci_write_config8(dev, 0x4A, byte); -} - -void sb600_lpc_port80(void) -{ - u8 byte; - device_t dev; - u32 reg32; - - /* Enable LPC controller */ - dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); - reg32 = pci_read_config32(dev, 0x64); - reg32 |= 0x00100000; /* lpcEnable */ - pci_write_config32(dev, 0x64, reg32); - - /* Enable port 80 LPC decode in pci function 3 configuration space. */ - dev = pci_locate_device(PCI_ID(0x1002, 0x438d), 0); - byte = pci_read_config8(dev, 0x4a); - byte |= 1 << 5; /* enable port 80 */ - pci_write_config8(dev, 0x4a, byte); -} - -/* sbDevicesPorInitTable */ -static void sb600_devices_por_init(void) -{ - device_t dev; - u8 byte; - - printk(BIOS_INFO, "sb600_devices_por_init()\n"); - /* SMBus Device, BDF:0-20-0 */ - printk(BIOS_INFO, "sb600_devices_por_init(): SMBus Device, BDF:0-20-0\n"); - dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); - - if (dev == PCI_DEV_INVALID) { - die("SMBUS controller not found\n"); - /* NOT REACHED */ - } - printk(BIOS_INFO, "SMBus controller enabled, sb revision is 0x%x\n", - get_sb600_revision()); - - /* sbPorAtStartOfTblCfg */ - /* Set A-Link bridge access address. This address is set at device 14h, function 0, register 0xf0. - * This is an I/O address. The I/O address must be on 16-byte boundry. */ - pci_write_config32(dev, 0xf0, AB_INDX); - - /* To enable AB/BIF DMA access, a specific register inside the BIF register space needs to be configured first. */ - /*Enables the SB600 to send transactions upstream over A-Link Express interface. */ - axcfg_reg(0x04, 1 << 2, 1 << 2); - axindxc_reg(0x21, 0xff, 0); - - /* 2.3.5:Enabling Non-Posted Memory Write for the K8 Platform */ - axindxc_reg(0x10, 1 << 9, 1 << 9); - /* END of sbPorAtStartOfTblCfg */ - - /* sbDevicesPorInitTables */ - /* set smbus iobase */ - pci_write_config32(dev, 0x10, SMBUS_IO_BASE | 1); - - /* enable smbus controller interface */ - byte = pci_read_config8(dev, 0xd2); - byte |= (1 << 0); - pci_write_config8(dev, 0xd2, byte); - - /* set smbus 1, ASF 2.0 (Alert Standard Format), iobase */ - pci_write_config16(dev, 0x58, SMBUS_IO_BASE | 0x11); - - /* TODO: I don't know the useage of followed two lines. I copied them from CIM. */ - pci_write_config8(dev, 0x0a, 0x1); - pci_write_config8(dev, 0x0b, 0x6); - - /* KB2RstEnable */ - pci_write_config8(dev, 0x40, 0xd4); - - /* Enable ISA Address 0-960K decoding */ - pci_write_config8(dev, 0x48, 0x0f); - - /* Enable ISA Address 0xC0000-0xDFFFF decode */ - pci_write_config8(dev, 0x49, 0xff); - - /* Enable decode cycles to IO C50, C51, C52 GPM controls. */ - byte = pci_read_config8(dev, 0x41); - byte &= 0x80; - byte |= 0x33; - pci_write_config8(dev, 0x41, byte); - - /* Legacy DMA Prefetch Enhancement, CIM masked it. */ - /* pci_write_config8(dev, 0x43, 0x1); */ - - /* Disabling Legacy USB Fast SMI# */ - byte = pci_read_config8(dev, 0x62); - byte |= 0x24; - pci_write_config8(dev, 0x62, byte); - - /* Features Enable */ - pci_write_config32(dev, 0x64, 0x829E7DBF); /* bit10: Enables the HPET interrupt. */ - - /* SerialIrq Control */ - pci_write_config8(dev, 0x69, 0x90); - - /* Test Mode, PCIB_SReset_En Mask is set. */ - pci_write_config8(dev, 0x6c, 0x20); - - /* IO Address Enable, CIM set 0x78 only and masked 0x79. */ - /*pci_write_config8(dev, 0x79, 0x4F); */ - pci_write_config8(dev, 0x78, 0xFF); - - /* This register is not used on sb600. It came from older chipset. */ - /*pci_write_config8(dev, 0x95, 0xFF); */ - - /* Set smbus iospace enable, I don't know why write 0x04 into reg5 that is reserved */ - pci_write_config16(dev, 0x4, 0x0407); - - /* clear any lingering errors, so the transaction will run */ - outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); - - /* IDE Device, BDF:0-20-1 */ - printk(BIOS_INFO, "sb600_devices_por_init(): IDE Device, BDF:0-20-1\n"); - dev = pci_locate_device(PCI_ID(0x1002, 0x438C), 0); - /* Disable prefetch */ - byte = pci_read_config8(dev, 0x63); - byte |= 0x1; - pci_write_config8(dev, 0x63, byte); - - /* LPC Device, BDF:0-20-3 */ - printk(BIOS_INFO, "sb600_devices_por_init(): LPC Device, BDF:0-20-3\n"); - dev = pci_locate_device(PCI_ID(0x1002, 0x438D), 0); - /* DMA enable */ - pci_write_config8(dev, 0x40, 0x04); - - /* IO Port Decode Enable */ - pci_write_config8(dev, 0x44, 0xFF); - pci_write_config8(dev, 0x45, 0xFF); - pci_write_config8(dev, 0x46, 0xC3); - pci_write_config8(dev, 0x47, 0xFF); - - // TODO: This has already been done(?) - /* IO/Mem Port Decode Enable, I don't know why CIM disable some ports. - * Disable LPC TimeOut counter, enable SuperIO Configuration Port (2e/2f), - * Alternate SuperIO Configuration Port (4e/4f), Wide Generic IO Port (64/65). */ - byte = pci_read_config8(dev, 0x48); - byte |= (1 << 1) | (1 << 0); /* enable Super IO config port 2e-2h, 4e-4f */ - byte |= 1 << 6; /* enable for RTC I/O range */ - pci_write_config8(dev, 0x48, byte); - pci_write_config8(dev, 0x49, 0xFF); - /* Enable 0x480-0x4bf, 0x4700-0x470B */ - byte = pci_read_config8(dev, 0x4A); - byte |= ((1 << 1) + (1 << 6)); /*0x42, save the configuraion for port 0x80. */ - pci_write_config8(dev, 0x4A, byte); - - /* Enable Tpm12_en and Tpm_legacy. I don't know what is its usage and copied from CIM. */ - pci_write_config8(dev, 0x7C, 0x05); - - /* P2P Bridge, BDF:0-20-4, the configuration of the registers in this dev are copied from CIM, - * TODO: I don't know what are their mean? */ - printk(BIOS_INFO, "sb600_devices_por_init(): P2P Bridge, BDF:0-20-4\n"); - dev = pci_locate_device(PCI_ID(0x1002, 0x4384), 0); - /* I don't know why CIM tried to write into a read-only reg! */ - /*pci_write_config8(dev, 0x0c, 0x20) */ ; - - /* Arbiter enable. */ - pci_write_config8(dev, 0x43, 0xff); - - /* Set PCDMA request into hight priority list. */ - /* pci_write_config8(dev, 0x49, 0x1) */ ; - - pci_write_config8(dev, 0x40, 0x26); - - /* I don't know why CIM set reg0x1c as 0x11. - * System will block at sdram_initialize() if I set it before call sdram_initialize(). - * If it is necessary to set reg0x1c as 0x11, please call this function after sdram_initialize(). - * pci_write_config8(dev, 0x1c, 0x11); - * pci_write_config8(dev, 0x1d, 0x11);*/ - - /*CIM set this register; but I didn't find its description in RPR. - On DBM690T platform, I didn't find different between set and skip this register. - But on Filbert platform, the DEBUG message from serial port on Peanut board can't be displayed - after the bit0 of this register is set. - pci_write_config8(dev, 0x04, 0x21); - */ - pci_write_config8(dev, 0x0d, 0x40); - pci_write_config8(dev, 0x1b, 0x40); - /* Enable PCIB_DUAL_EN_UP will fix potential problem with PCI cards. */ - pci_write_config8(dev, 0x50, 0x01); - - /* SATA Device, BDF:0-18-0, Non-Raid-5 SATA controller */ - printk(BIOS_INFO, "sb600_devices_por_init(): SATA Device, BDF:0-18-0\n"); - dev = pci_locate_device(PCI_ID(0x1002, 0x4380), 0); - - /*PHY Global Control, we are using A14. - * default: 0x2c40 for ASIC revision A12 and below - * 0x2c00 for ASIC revision A13 and above.*/ - pci_write_config16(dev, 0x86, 0x2C00); - - /* PHY Port0-3 Control */ - pci_write_config32(dev, 0x88, 0xB400DA); - pci_write_config32(dev, 0x8c, 0xB400DA); - pci_write_config32(dev, 0x90, 0xB400DA); - pci_write_config32(dev, 0x94, 0xB400DA); - - /* Port0-3 BIST Control/Status */ - pci_write_config8(dev, 0xa5, 0xB8); - pci_write_config8(dev, 0xad, 0xB8); - pci_write_config8(dev, 0xb5, 0xB8); - pci_write_config8(dev, 0xbd, 0xB8); -} - -/* sbPmioPorInitTable, Pre-initializing PMIO register space -* The power management (PM) block is resident in the PCI/LPC/ISA bridge. -* The PM regs are accessed via IO mapped regs 0xcd6 and 0xcd7. -* The index address is first programmed into IO reg 0xcd6. -* Read or write values are accessed through IO reg 0xcd7. -*/ -static void sb600_pmio_por_init(void) -{ - u8 byte; - - printk(BIOS_INFO, "sb600_pmio_por_init()\n"); - /* K8KbRstEn, KB_RST# control for K8 system. */ - byte = pmio_read(0x66); - byte |= 0x20; - pmio_write(0x66, byte); - - /* RPR2.3.4 S3/S4/S5 Function for the K8 Platform. */ - byte = pmio_read(0x52); - byte &= 0xc0; - byte |= 0x08; - pmio_write(0x52, byte); - - /* C state enable and SLP enable in C states. */ - byte = pmio_read(0x67); - byte |= 0x6; - pmio_write(0x67, byte); - - /* CIM sets 0x0e, but bit2 is for P4 system. */ - byte = pmio_read(0x68); - byte &= 0xf0; - byte |= 0x0c; - pmio_write(0x68, byte); - - /* Watch Dog Timer Control - * Set watchdog time base to 0xfec000f0 to avoid SCSI card boot failure. - * But I don't find WDT is enabled in SMBUS 0x41 bit3 in CIM. - */ - pmio_write(0x6c, 0xf0); - pmio_write(0x6d, 0x00); - pmio_write(0x6e, 0xc0); - pmio_write(0x6f, 0xfe); - - /* rpr2.14: Enables HPET periodical mode */ - byte = pmio_read(0x9a); - byte |= 1 << 7; - pmio_write(0x9a, byte); - byte = pmio_read(0x9f); - byte |= 1 << 5; - pmio_write(0x9f, byte); - byte = pmio_read(0x9e); - byte |= (1 << 6) | (1 << 7); - pmio_write(0x9e, byte); - - /* rpr2.14: Hides SM bus controller Bar1 where stores HPET MMIO base address */ - /* We have to clear this bit here, otherwise the kernel hangs. */ - byte = pmio_read(0x55); - byte |= 1 << 7; - byte |= 1 << 1; - pmio_write(0x55, byte); - - /* rpr2.14: Make HPET MMIO decoding controlled by the memory enable bit in command register of LPC ISA bridage */ - byte = pmio_read(0x52); - byte |= 1 << 6; - pmio_write(0x52, byte); - - /* rpr2.22: PLL Reset */ - byte = pmio_read(0x86); - byte |= 1 << 7; - pmio_write(0x86, byte); - - /* rpr2.3.3 */ - /* This provides 16us delay before the assertion of LDTSTP# when C3 is entered. - * The delay will allow USB DMA to go on in a continuous manner - */ - pmio_write(0x89, 0x10); - /* Set this bit to allow pop-up request being latched during the minimum LDTSTP# assertion time */ - byte = pmio_read(0x52); - byte |= 1 << 7; - pmio_write(0x52, byte); - - /* rpr2.15: ASF Remote Control Action */ - byte = pmio_read(0x9f); - byte |= 1 << 6; - pmio_write(0x9f, byte); - - /* rpr2.19: Enabling Spread Spectrum */ - byte = pmio_read(0x42); - byte |= 1 << 7; - pmio_write(0x42, byte); -} - -/* -* Compliant with CIM_48's sbPciCfg. -* Add any south bridge setting. -*/ -static void sb600_pci_cfg(void) -{ - device_t dev; - u8 byte; - - /* SMBus Device, BDF:0-20-0 */ - dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); - /* Eable the hidden revision ID, available after A13. */ - byte = pci_read_config8(dev, 0x70); - byte |= (1 << 8); - pci_write_config8(dev, 0x70, byte); - /* rpr2.20 Disable Timer IRQ Enhancement for proper operation of the 8254 timer, 0xae[5]. */ - byte = pci_read_config8(dev, 0xae); - byte |= (1 << 5); - pci_write_config8(dev, 0xae, byte); - - /* Enable watchdog decode timer */ - byte = pci_read_config8(dev, 0x41); - byte |= (1 << 3); - pci_write_config8(dev, 0x41, byte); - - /* Set to 1 to reset USB on the software (such as IO-64 or IO-CF9 cycles) - * generated PCIRST#. */ - byte = pmio_read(0x65); - byte |= (1 << 4); - pmio_write(0x65, byte); - /*For A13 and above. */ - if (get_sb600_revision() > 0x12) { - /* rpr2.16 C-State Reset, PMIO 0x9f[7]. */ - byte = pmio_read(0x9f); - byte |= (1 << 7); - pmio_write(0x9f, byte); - /* rpr2.17 PCI Clock Period will increase to 30.8ns. 0x53[7]. */ - byte = pmio_read(0x53); - byte |= (1 << 7); - pmio_write(0x53, byte); - } - - /* IDE Device, BDF:0-20-1 */ - dev = pci_locate_device(PCI_ID(0x1002, 0x438C), 0); - /* Enable IDE Explicit prefetch, 0x63[0] clear */ - byte = pci_read_config8(dev, 0x63); - byte &= 0xfe; - pci_write_config8(dev, 0x63, byte); - - /* LPC Device, BDF:0-20-3 */ - dev = pci_locate_device(PCI_ID(0x1002, 0x438D), 0); - /* rpr7.2 Enabling LPC DMA function. */ - byte = pci_read_config8(dev, 0x40); - byte |= (1 << 2); - pci_write_config8(dev, 0x40, byte); - /* rpr7.3 Disabling LPC TimeOut. 0x48[7] clear. */ - byte = pci_read_config8(dev, 0x48); - byte &= 0x7f; - pci_write_config8(dev, 0x48, byte); - /* rpr7.5 Disabling LPC MSI Capability, 0x78[1] clear. */ - byte = pci_read_config8(dev, 0x78); - byte &= 0xfd; - pci_write_config8(dev, 0x78, byte); - - /* SATA Device, BDF:0-18-0, Non-Raid-5 SATA controller */ - dev = pci_locate_device(PCI_ID(0x1002, 0x4380), 0); - /* rpr6.8 Disabling SATA MSI Capability, for A13 and above, 0x42[7]. */ - if (0x12 < get_sb600_revision()) { - u32 reg32; - reg32 = pci_read_config32(dev, 0x40); - reg32 |= (1 << 23); - pci_write_config32(dev, 0x40, reg32); - } - - /* EHCI Device, BDF:0-19-5, ehci usb controller */ - dev = pci_locate_device(PCI_ID(0x1002, 0x4386), 0); - /* rpr5.10 Disabling USB EHCI MSI Capability. 0x50[6]. */ - byte = pci_read_config8(dev, 0x50); - byte |= (1 << 6); - pci_write_config8(dev, 0x50, byte); - - /* OHCI0 Device, BDF:0-19-0, ohci usb controller #0 */ - dev = pci_locate_device(PCI_ID(0x1002, 0x4387), 0); - /* rpr5.11 Disabling USB OHCI MSI Capability. 0x40[12:8]=0x1f. */ - byte = pci_read_config8(dev, 0x41); - byte |= 0x1f; - pci_write_config8(dev, 0x41, byte); - -} - -/* -* Compliant with CIM_48's ATSBPowerOnResetInitJSP -*/ -static void sb600_por_init(void) -{ - /* sbDevicesPorInitTable + sbK8PorInitTable */ - sb600_devices_por_init(); - - /* sbPmioPorInitTable + sbK8PmioPorInitTable */ - sb600_pmio_por_init(); -} - -/* -* Compliant with CIM_48's AtiSbBeforePciInit -* It should be called during early POST after memory detection and BIOS shadowing but before PCI bus enumeration. -*/ -static void sb600_before_pci_init(void) -{ - sb600_pci_cfg(); -} - -/* -* This function should be called after enable_sb600_smbus(). -*/ -static void sb600_early_setup(void) -{ - printk(BIOS_INFO, "sb600_early_setup()\n"); - sb600_por_init(); -} - -static int smbus_read_byte(u32 device, u32 address) -{ - return do_smbus_read_byte(SMBUS_IO_BASE, device, address); -} - diff --git a/src/southbridge/amd/sb600/sb600_enable_rom.c b/src/southbridge/amd/sb600/sb600_enable_rom.c deleted file mode 100644 index b2668420ce..0000000000 --- a/src/southbridge/amd/sb600/sb600_enable_rom.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 -#include -#include -#include - -/* - * 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 SB600 power-on default is to map 256K ROM space. - * - * Details: AMD SB600 BIOS Developer's Guide (BDG), page 15. - */ -static void sb600_enable_rom(void) -{ - u8 reg8; - device_t dev; - - dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_ATI, - PCI_DEVICE_ID_ATI_SB600_LPC), 0); - - /* 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, 0xffc0); /* 4 MB */ - /* Enable LPC ROM range end at 0xffff(ffff). */ - pci_write_config16(dev, 0x6e, 0xffff); -} diff --git a/src/southbridge/amd/sb600/sb600_enable_usbdebug.c b/src/southbridge/amd/sb600/sb600_enable_usbdebug.c deleted file mode 100644 index b4d97b0da2..0000000000 --- a/src/southbridge/amd/sb600/sb600_enable_usbdebug.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 -#include -#include -#include -#include -#include "sb600.h" - -/* Required for successful build, but currently empty. */ -void set_debug_port(unsigned int port) -{ - /* TODO: Allow changing the physical USB port used as Debug Port. */ -} - -void sb600_enable_usbdebug(unsigned int port) -{ - device_t dev = PCI_DEV(0, 0x13, 5); /* USB EHCI, D19:F5 */ - - /* Select the requested physical USB port (1-15) as the Debug Port. */ - set_debug_port(port); - - /* Set the EHCI BAR address. */ - pci_write_config32(dev, EHCI_BAR_INDEX, CONFIG_EHCI_BAR); - - /* Enable access to the EHCI memory space registers. */ - pci_write_config8(dev, PCI_COMMAND, PCI_COMMAND_MEMORY); -} diff --git a/src/southbridge/amd/sb600/sb600_hda.c b/src/southbridge/amd/sb600/sb600_hda.c deleted file mode 100644 index 84df3f169f..0000000000 --- a/src/southbridge/amd/sb600/sb600_hda.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 -#include -#include -#include -#include -#include -#include -#include "sb600.h" - -#define HDA_ICII_REG 0x68 -#define HDA_ICII_BUSY (1 << 0) -#define HDA_ICII_VALID (1 << 1) - -static int set_bits(u32 port, u32 mask, u32 val) -{ - u32 dword; - int count; - - /* Write (val & ~mask) to port */ - val &= mask; - dword = read32(port); - dword &= ~mask; - dword |= val; - write32(port, dword); - - /* Wait for readback of register to - * match what was just written to it - */ - count = 50; - do { - /* Wait 1ms based on BKDG wait time */ - mdelay(1); - dword = read32(port); - dword &= mask; - } while ((dword != val) && --count); - - /* Timeout occurred */ - if (!count) - return -1; - return 0; -} - -static u32 codec_detect(u32 base) -{ - u32 dword; - - /* Set Bit0 to 0 to enter reset state (BAR + 0x8)[0] */ - if (set_bits(base + 0x08, 1, 0) == -1) - goto no_codec; - - /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */ - if (set_bits(base + 0x08, 1, 1) == -1) - goto no_codec; - - /* Delay for 1 ms since the BKDG does */ - mdelay(1); - - /* Read in Codec location (BAR + 0xe)[3..0]*/ - dword = read32(base + 0xe); - dword &= 0x0F; - if (!dword) - goto no_codec; - - return dword; - -no_codec: - /* Codec Not found */ - /* Put HDA back in reset (BAR + 0x8) [0] */ - set_bits(base + 0x08, 1, 0); - printk(BIOS_DEBUG, "No codec!\n"); - return 0; -} - -static u32 cim_verb_data[] = { - 0x01471c10, - 0x01471d40, - 0x01471e01, - 0x01471f01, -/* 1 */ - 0x01571c12, - 0x01571d10, - 0x01571e01, - 0x01571f01, -/* 2 */ - 0x01671c11, - 0x01671d60, - 0x01671e01, - 0x01671f01, -/* 3 */ - 0x01771c14, - 0x01771d20, - 0x01771e01, - 0x01771f01, -/* 4 */ - 0x01871c30, - 0x01871d90, - 0x01871ea1, - 0x01871f01, -/* 5 */ - 0x01971cf0, - 0x01971d11, - 0x01971e11, - 0x01971f41, -/* 6 */ - 0x01a71c80, - 0x01a71d30, - 0x01a71e81, - 0x01a71f01, -/* 7 */ - 0x01b71cf0, - 0x01b71d11, - 0x01b71e11, - 0x01b71f41, -/* 8 */ - 0x01c71cf0, - 0x01c71d11, - 0x01c71e11, - 0x01c71f41, -/* 9 */ - 0x01d71cf0, - 0x01d71d11, - 0x01d71e11, - 0x01d71f41, -/* 10 */ - 0x01e71c50, - 0x01e71d11, - 0x01e71e44, - 0x01e71f01, -/* 11 */ - 0x01f71c60, - 0x01f71d61, - 0x01f71ec4, - 0x01f71f01, -}; - -static u32 find_verb(u32 viddid, u32 ** verb) -{ - device_t azalia_dev = dev_find_slot(0, PCI_DEVFN(0x14, 2)); - struct southbridge_amd_sb600_config *cfg = - (struct southbridge_amd_sb600_config *)azalia_dev->chip_info; - printk(BIOS_DEBUG, "Dev=%s\n", dev_path(azalia_dev)); - printk(BIOS_DEBUG, "Default viddid=%x\n", cfg->hda_viddid); - printk(BIOS_DEBUG, "Reading viddid=%x\n", viddid); - if (!cfg) - return 0; - if (viddid != cfg->hda_viddid) - return 0; - *verb = (u32 *) cim_verb_data; - return sizeof(cim_verb_data) / sizeof(u32); -} - -/** - * Wait 50usec for the codec to indicate it is ready - * no response would imply that the codec is non-operative - */ -static int wait_for_ready(u32 base) -{ - /* Use a 50 usec timeout - the Linux kernel uses the - * same duration */ - - int timeout = 50; - - while(timeout--) { - u32 dword=read32(base + HDA_ICII_REG); - if (!(dword & HDA_ICII_BUSY)) - return 0; - udelay(1); - } - - return -1; -} - -/** - * Wait 50usec for the codec to indicate that it accepted - * the previous command. No response would imply that the code - * is non-operative - */ -static int wait_for_valid(u32 base) -{ - /* Use a 50 usec timeout - the Linux kernel uses the - * same duration */ - - int timeout = 50; - while(timeout--) { - u32 dword = read32(base + HDA_ICII_REG); - if ((dword & (HDA_ICII_VALID | HDA_ICII_BUSY)) == - HDA_ICII_VALID) - return 0; - udelay(1); - } - - return 1; -} - -static void codec_init(u32 base, int addr) -{ - u32 dword; - u32 *verb; - u32 verb_size; - int i; - - /* 1 */ - if (wait_for_ready(base) == -1) - return; - - dword = (addr << 28) | 0x000f0000; - write32(base + 0x60, dword); - - if (wait_for_valid(base) == -1) - return; - - dword = read32(base + 0x64); - - /* 2 */ - printk(BIOS_DEBUG, "codec viddid: %08x\n", dword); - verb_size = find_verb(dword, &verb); - - if (!verb_size) { - printk(BIOS_DEBUG, "No verb!\n"); - return; - } - - printk(BIOS_DEBUG, "verb_size: %d\n", verb_size); - /* 3 */ - for (i = 0; i < verb_size; i++) { - if (wait_for_ready(base) == -1) - return; - - write32(base + 0x60, verb[i]); - - if (wait_for_valid(base) == -1) - return; - } - printk(BIOS_DEBUG, "verb loaded!\n"); -} - -static void codecs_init(u32 base, u32 codec_mask) -{ - int i; - for (i = 2; i >= 0; i--) { - if (codec_mask & (1 << i)) - codec_init(base, i); - } -} - -static void hda_init(struct device *dev) -{ - u8 byte; - u32 dword; - u32 base; - struct resource *res; - u32 codec_mask; - device_t sm_dev; - - /* Enable azalia - PM_io 0x59[4], disable ac97 - PM_io 0x59[1..0] */ - pm_iowrite(0x59, 0xB); - - /* Find the SMBus */ - /* FIXME: Need to find out why the call below crashes. */ - /*sm_dev = dev_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_ATI_SB600_SM, 0);*/ - sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0)); - - /* Set routing pin - SMBus ExtFunc (0xf8/0xfc) */ - pci_write_config32(sm_dev, 0xf8, 0x00); - pci_write_config8(sm_dev, 0xfc, 0xAA); - /* Set INTA - SMBus 0x63 [2..0] */ - byte = pci_read_config8(sm_dev, 0x63); - byte &= ~0x7; - byte |= 0x0; /* INTA:0x0 - INTH:0x7 */ - pci_write_config8(sm_dev, 0x63, byte); - - /* Program the 2C to 0x437b1002 */ - dword = 0x437b1002; - pci_write_config32(dev, 0x2c, dword); - - /* Read in BAR */ - /* Is this right? HDA allows for a 64-bit BAR - * but this is only setup for a 32-bit one - */ - res = find_resource(dev, 0x10); - if (!res) - return; - - base = (u32)res->base; - printk(BIOS_DEBUG, "base = 0x%x\n", base); - codec_mask = codec_detect(base); - - if (codec_mask) { - printk(BIOS_DEBUG, "codec_mask = %02x\n", codec_mask); - codecs_init(base, codec_mask); - } -} - -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, - /*.enable = sb600_enable, */ - .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_ATI, - .device = PCI_DEVICE_ID_ATI_SB600_HDA, -}; diff --git a/src/southbridge/amd/sb600/sb600_ide.c b/src/southbridge/amd/sb600/sb600_ide.c deleted file mode 100644 index e38e83fdd7..0000000000 --- a/src/southbridge/amd/sb600/sb600_ide.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 -#include -#include -#include -#include -#include "sb600.h" - -static void ide_init(struct device *dev) -{ - /* Enable ide devices so the linux ide driver will work */ - u32 dword; - u8 byte; - - /* RPR10.1 disable MSI */ - dword = pci_read_config32(dev, 0x70); - dword &= ~(1 << 16); - pci_write_config32(dev, 0x70, dword); - - /* Enable UDMA on all devices, it will become UDMA0 (default PIO is PIO0) */ - byte = pci_read_config8(dev, 0x54); - byte |= 0xf; - pci_write_config8(dev, 0x54, byte); - - /* Enable I/O Access&& Bus Master */ - dword = pci_read_config16(dev, 0x4); - dword |= 1 << 2; - pci_write_config16(dev, 0x4, dword); - -#if CONFIG_PCI_ROM_RUN == 1 - pci_dev_init(dev); -#endif - -} - -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, - /* .enable = sb600_enable, */ - .ops_pci = &lops_pci, -}; - -static const struct pci_driver ide_driver __pci_driver = { - .ops = &ide_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_SB600_IDE, -}; diff --git a/src/southbridge/amd/sb600/sb600_lpc.c b/src/southbridge/amd/sb600/sb600_lpc.c deleted file mode 100644 index 6a17f72318..0000000000 --- a/src/southbridge/amd/sb600/sb600_lpc.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sb600.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(); - - /* RPR 7.2 Enable DMA transaction on the LPC bus */ - byte = pci_read_config8(dev, 0x40); - byte |= (1 << 2); - pci_write_config8(dev, 0x40, byte); - - /* RPR 7.3 Disable the timeout mechanism on LPC */ - byte = pci_read_config8(dev, 0x48); - byte &= ~(1 << 7); - pci_write_config8(dev, 0x48, byte); - - /* RPR 7.5 Disable LPC MSI Capability */ - byte = pci_read_config8(dev, 0x78); - byte &= ~(1 << 1); - pci_write_config8(dev, 0x78, byte); - -} - -static void sb600_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 = IO_APIC_ADDR; - res->size = 0x00001000; - res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; - - compact_resources(dev); -} - -/** - * @brief Enable resources for children devices - * - * @param dev the device whos children's resources are to be enabled - * - */ -static void sb600_lpc_enable_childrens_resources(device_t dev) -{ - struct bus *link; - u32 reg, reg_x; - int var_num = 0; - u16 reg_var[3]; - - reg = pci_read_config32(dev, 0x44); - reg_x = pci_read_config32(dev, 0x48); - - for (link = dev->link_list; link; link = link->next) { - device_t child; - for (child = link->children; child; - child = child->sibling) { - if (child->enabled - && (child->path.type == DEVICE_PATH_PNP)) { - struct resource *res; - for (res = child->resource_list; res; res = res->next) { - u32 base, end; /* don't need long long */ - if (!(res->flags & IORESOURCE_IO)) - continue; - base = res->base; - end = resource_end(res); - printk(BIOS_DEBUG, "sb600 lpc decode:%s, base=0x%08x, end=0x%08x\n", - dev_path(child), base, end); - switch (base) { - case 0x60: /* KB */ - case 0x64: /* MS */ - reg |= (1 << 29); - break; - case 0x3f8: /* COM1 */ - reg |= (1 << 6); - break; - case 0x2f8: /* COM2 */ - reg |= (1 << 7); - break; - case 0x378: /* Parallal 1 */ - reg |= (1 << 0); - break; - case 0x3f0: /* FD0 */ - reg |= (1 << 26); - break; - case 0x220: /* Aduio 0 */ - reg |= (1 << 8); - break; - case 0x300: /* Midi 0 */ - reg |= (1 << 18); - break; - case 0x400: - reg_x |= (1 << 16); - break; - case 0x480: - reg_x |= (1 << 17); - break; - case 0x500: - reg_x |= (1 << 18); - break; - case 0x580: - reg_x |= (1 << 19); - break; - case 0x4700: - reg_x |= (1 << 22); - break; - case 0xfd60: - reg_x |= (1 << 23); - break; - default: - if (var_num >= 3) - continue; /* only 3 var ; compact them ? */ - switch (var_num) { - case 0: - reg_x |= (1 << 2); - break; - case 1: - reg_x |= (1 << 24); - break; - case 2: - reg_x |= (1 << 25); - break; - } - reg_var[var_num++] = - base & 0xffff; - } - } - } - } - } - pci_write_config32(dev, 0x44, reg); - pci_write_config32(dev, 0x48, reg_x); - /* Set WideIO for as many IOs found (fall through is on purpose) */ - switch (var_num) { - case 2: - pci_write_config16(dev, 0x90, reg_var[2]); - case 1: - pci_write_config16(dev, 0x66, reg_var[1]); - case 0: - pci_write_config16(dev, 0x64, reg_var[0]); - break; - } -} - -static void sb600_lpc_enable_resources(device_t dev) -{ - pci_dev_enable_resources(dev); - sb600_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 = sb600_lpc_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = sb600_lpc_enable_resources, - .init = lpc_init, - .scan_bus = scan_static_bus, - /* .enable = sb600_enable, */ - .ops_pci = &lops_pci, -}; -static const struct pci_driver lpc_driver __pci_driver = { - .ops = &lpc_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_SB600_LPC, -}; diff --git a/src/southbridge/amd/sb600/sb600_pci.c b/src/southbridge/amd/sb600/sb600_pci.c deleted file mode 100644 index 66ca29bd78..0000000000 --- a/src/southbridge/amd/sb600/sb600_pci.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 -#include -#include -#include -#include -#include "sb600.h" - -static void pci_init(struct device *dev) -{ - u32 dword; - u16 word; - u8 byte; - - /* RPR 4.1 Enables the PCI-bridge subtractive decode */ - /* This setting is strongly recommended since it supports some legacy PCI add-on cards,such as BIOS debug cards */ - byte = pci_read_config8(dev, 0x4B); - byte |= 1 << 7; - pci_write_config8(dev, 0x4B, byte); - byte = pci_read_config8(dev, 0x40); - byte |= 1 << 5; - pci_write_config8(dev, 0x40, byte); - - /* RPR4.2 PCI-bridge upstream dual address window */ - /* this setting is applicable if the system memory is more than 4GB,and the PCI device can support dual address access */ - byte = pci_read_config8(dev, 0x50); - byte |= 1 << 0; - pci_write_config8(dev, 0x50, byte); - - /* RPR 4.3 PCI bus 64-byte DMA read access */ - /* Enhance the PCI bus DMA performance */ - byte = pci_read_config8(dev, 0x4B); - byte |= 1 << 4; - pci_write_config8(dev, 0x4B, byte); - - /* RPR 4.4 Enables the PCIB writes to be cacheline aligned. */ - /* The size of the writes will be set in the Cacheline Register */ - byte = pci_read_config8(dev, 0x40); - byte |= 1 << 1; - pci_write_config8(dev, 0x40, byte); - - /* RPR 4.5 Enables the PCIB to retain ownership of the bus on the Primary side and on the Secondary side when GNT# is deasserted */ - pci_write_config8(dev, 0x0D, 0x40); - pci_write_config8(dev, 0x1B, 0x40); - - /* RPR 4.6 Enable the command matching checking function on "Memory Read" & "Memory Read Line" commands */ - byte = pci_read_config8(dev, 0x4B); - byte |= 1 << 6; - pci_write_config8(dev, 0x4B, byte); - - /* RPR 4.7 When enabled, the PCI arbiter checks for the Bus Idle before asserting GNT# */ - byte = pci_read_config8(dev, 0x4B); - byte |= 1 << 0; - pci_write_config8(dev, 0x4B, byte); - - /* RPR 4.8 Adjusts the GNT# de-assertion time */ - word = pci_read_config16(dev, 0x64); - word |= 1 << 12; - pci_write_config16(dev, 0x64, word); - - /* RPR 4.9 Fast Back to Back transactions support */ - byte = pci_read_config8(dev, 0x48); - byte |= 1 << 2; - pci_write_config8(dev, 0x48, byte); - - /* RPR 4.10 Enable Lock Operation */ - byte = pci_read_config8(dev, 0x48); - byte |= 1 << 3; - pci_write_config8(dev, 0x48, byte); - byte = pci_read_config8(dev, 0x40); - byte |= (1 << 2); - pci_write_config8(dev, 0x40, byte); - - /* RPR 4.11 Enable additional optional PCI clock */ - word = pci_read_config16(dev, 0x64); - word |= 1 << 8; - pci_write_config16(dev, 0x64, word); - - /* rpr4.12 Disable Fewer-Retry Mode for A11-A13 only. 0x64[5:4] clear */ - byte = pci_read_config8(dev, 0x64); - byte &= 0xcf; - pci_write_config8(dev, 0x64, byte); - - /* rpr4.14 Disabling Downstream Flush, for A12 only, 0x64[18]. */ - dword = pci_read_config32(dev, 0x64); - dword |= (1 << 18); - pci_write_config32(dev, 0x64, dword); - - /* RPR 4.13 Enable One-Prefetch-Channel Mode */ - dword = pci_read_config32(dev, 0x64); - dword |= 1 << 20; - pci_write_config32(dev, 0x64, dword); - - /* RPR 4.15 Disable PCIB MSI Capability */ - byte = pci_read_config8(dev, 0x40); - byte &= ~(1 << 3); - pci_write_config8(dev, 0x40, byte); - - /* rpr4.16 Adjusting CLKRUN# */ - dword = pci_read_config32(dev, 0x64); - dword |= (1 << 15); - pci_write_config32(dev, 0x64, dword); -} - -static struct pci_operations lops_pci = { - .set_subsystem = 0, -}; - -static struct device_operations pci_ops = { - .read_resources = pci_bus_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_bus_enable_resources, - .init = pci_init, - .scan_bus = pci_scan_bridge, - /* .enable = sb600_enable, */ - .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_ATI, - .device = PCI_DEVICE_ID_ATI_SB600_PCI, -}; diff --git a/src/southbridge/amd/sb600/sb600_reset.c b/src/southbridge/amd/sb600/sb600_reset.c deleted file mode 100644 index af80576204..0000000000 --- a/src/southbridge/amd/sb600/sb600_reset.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 -#include -#include - -#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/sb600/sb600_sata.c b/src/southbridge/amd/sb600/sb600_sata.c deleted file mode 100644 index 055e7daa85..0000000000 --- a/src/southbridge/amd/sb600/sb600_sata.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 Advanced Micro Devices, Inc. - * Copyright (C) 2008 Carl-Daniel Hailfinger - * - * 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 -#include -#include -#include -#include -#include -#include -#include "sb600.h" - -static int sata_drive_detect(int portnum, u16 iobar) -{ - u8 byte, byte2; - int i = 0; - outb(0xA0 + 0x10 * (portnum % 2), iobar + 0x6); - while (byte = inb(iobar + 0x6), byte2 = inb(iobar + 0x7), - (byte != (0xA0 + 0x10 * (portnum % 2))) || - ((byte2 & 0x88) != 0)) { - printk(BIOS_SPEW, "0x6=%x, 0x7=%x\n", byte, byte2); - if (byte != (0xA0 + 0x10 * (portnum % 2))) { - /* This will happen at the first iteration of this loop - * if the first SATA port is unpopulated and the - * second SATA port is populated. - */ - printk(BIOS_DEBUG, "drive no longer selected after %i ms, " - "retrying init\n", i * 10); - return 1; - } else - printk(BIOS_SPEW, "drive detection not yet completed, " - "waiting...\n"); - mdelay(10); - i++; - } - printk(BIOS_SPEW, "drive detection done after %i ms\n", i * 10); - return 0; -} - -static void sata_init(struct device *dev) -{ - u8 byte; - u16 word; - u32 dword; - u32 sata_bar5; - u16 sata_bar0, sata_bar1, sata_bar2, sata_bar3, sata_bar4; - int i, j; - - struct southbridge_ati_sb600_config *conf; - conf = dev->chip_info; - - device_t sm_dev; - /* SATA SMBus Disable */ - /* sm_dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); */ - sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0)); - /* Disable SATA SMBUS */ - byte = pci_read_config8(sm_dev, 0xad); - byte |= (1 << 1); - /* Enable SATA and power saving */ - byte = pci_read_config8(sm_dev, 0xad); - byte |= (1 << 0); - byte |= (1 << 5); - pci_write_config8(sm_dev, 0xad, byte); - /* Set the interrupt Mapping to INTG# */ - byte = pci_read_config8(sm_dev, 0xaf); - byte = 0x6 << 2; - pci_write_config8(sm_dev, 0xaf, byte); - - /* get base address */ - sata_bar5 = pci_read_config32(dev, 0x24) & ~0x3FF; - sata_bar0 = pci_read_config16(dev, 0x10) & ~0x7; - sata_bar1 = pci_read_config16(dev, 0x14) & ~0x3; - sata_bar2 = pci_read_config16(dev, 0x18) & ~0x7; - sata_bar3 = pci_read_config16(dev, 0x1C) & ~0x3; - sata_bar4 = pci_read_config16(dev, 0x20) & ~0xf; - - printk(BIOS_SPEW, "sata_bar0=%x\n", sata_bar0); /* 3030 */ - printk(BIOS_SPEW, "sata_bar1=%x\n", sata_bar1); /* 3070 */ - printk(BIOS_SPEW, "sata_bar2=%x\n", sata_bar2); /* 3040 */ - printk(BIOS_SPEW, "sata_bar3=%x\n", sata_bar3); /* 3080 */ - printk(BIOS_SPEW, "sata_bar4=%x\n", sata_bar4); /* 3000 */ - printk(BIOS_SPEW, "sata_bar5=%x\n", sata_bar5); /* e0309000 */ - - /* Program the 2C to 0x43801002 */ - dword = 0x43801002; - pci_write_config32(dev, 0x2c, dword); - - /* SERR-Enable */ - word = pci_read_config16(dev, 0x04); - word |= (1 << 8); - pci_write_config16(dev, 0x04, word); - - /* Dynamic power saving */ - byte = pci_read_config8(dev, 0x40); - byte |= (1 << 2); - pci_write_config8(dev, 0x40, byte); - - /* Set SATA Operation Mode, Set to IDE mode */ - byte = pci_read_config8(dev, 0x40); - byte |= (1 << 0); - byte |= (1 << 4); - pci_write_config8(dev, 0x40, byte); - - dword = 0x01018f00; - pci_write_config32(dev, 0x8, dword); - - byte = pci_read_config8(dev, 0x40); - byte &= ~(1 << 0); - pci_write_config8(dev, 0x40, byte); - - /* Enable the SATA watchdog counter */ - byte = pci_read_config8(dev, 0x44); - byte |= (1 << 0); - pci_write_config8(dev, 0x44, byte); - - /* Program the watchdog counter to 0x10 */ - byte = 0x10; - pci_write_config8(dev, 0x46, byte); - - /* RPR6.5 Program the PHY Global Control to 0x2C00 for A13 */ - word = 0x2c00; - pci_write_config16(dev, 0x86, word); - - /* RPR6.5 Program the Phy Tuning4Ports */ - dword = 0x00B401D6; - pci_write_config32(dev, 0x88, dword); - pci_write_config32(dev, 0x8c, dword); - pci_write_config32(dev, 0x90, dword); - pci_write_config32(dev, 0x94, dword); - - byte = 0xB8; - pci_write_config8(dev, 0xA5, byte); - pci_write_config8(dev, 0xAD, byte); - pci_write_config8(dev, 0xB5, byte); - pci_write_config8(dev, 0xBD, byte); - - /* RPR 6.8 */ - word = pci_read_config16(dev, 0x42); - word |= 1 << 7; - pci_write_config16(dev, 0x42, word); - /* RPR 6.9 */ - dword = pci_read_config32(dev, 0x40); - dword |= 1 << 25; - pci_write_config32(dev, 0x40, dword); - - /* Enable the I/O, MM, BusMaster access for SATA */ - byte = pci_read_config8(dev, 0x4); - byte |= 7 << 0; - pci_write_config8(dev, 0x4, byte); - - /* RPR6.6 SATA drive detection. */ - /* Use BAR5+0x128,BAR0 for Primary Slave */ - /* Use BAR5+0x1A8,BAR0 for Primary Slave */ - /* Use BAR5+0x228,BAR2 for Secondary Master */ - /* Use BAR5+0x2A8,BAR2 for Secondary Slave */ - - for (i = 0; i < 4; i++) { - byte = read8(sata_bar5 + 0x128 + 0x80 * i); - printk(BIOS_SPEW, "SATA port %i status = %x\n", i, byte); - byte &= 0xF; - - if( byte == 0x1 ) { - /* If the drive status is 0x1 then we see it but we aren't talking to it. */ - /* Try to do something about it. */ - printk(BIOS_SPEW, "SATA device detected but not talking. Trying lower speed.\n"); - - /* Read in Port-N Serial ATA Control Register */ - byte = read8(sata_bar5 + 0x12C + 0x80 * i); - - /* Set Reset Bit and 1.5g bit */ - byte |= 0x11; - write8((sata_bar5 + 0x12C + 0x80 * i), byte); - - /* Wait 1ms */ - mdelay(1); - - /* Clear Reset Bit */ - byte &= ~0x01; - write8((sata_bar5 + 0x12C + 0x80 * i), byte); - - /* Wait 1ms */ - mdelay(1); - - /* Reread status */ - byte = read8(sata_bar5 + 0x128 + 0x80 * i); - printk(BIOS_SPEW, "SATA port %i status = %x\n", i, byte); - byte &= 0xF; - } - - if (byte == 0x3) { - for (j = 0; j < 10; j++) { - if (!sata_drive_detect(i, ((i / 2) == 0) ? sata_bar0 : sata_bar2)) - break; - } - printk(BIOS_DEBUG, "%s %s device is %sready after %i tries\n", - (i / 2) ? "Secondary" : "Primary", - (i % 2 ) ? "Slave" : "Master", - (j == 10) ? "not " : "", - (j == 10) ? j : j + 1); - } else { - printk(BIOS_DEBUG, "No %s %s SATA drive on Slot%i\n", - (i / 2) ? "Secondary" : "Primary", - (i % 2 ) ? "Slave" : "Master", i); - } - } - - /* Below is CIM InitSataLateFar */ - /* Enable interrupts from the HBA */ - byte = read8(sata_bar5 + 0x4); - byte |= 1 << 1; - write8((sata_bar5 + 0x4), byte); - - /* Clear error status */ - write32((sata_bar5 + 0x130), 0xFFFFFFFF); - write32((sata_bar5 + 0x1b0), 0xFFFFFFFF); - write32((sata_bar5 + 0x230), 0xFFFFFFFF); - write32((sata_bar5 + 0x2b0), 0xFFFFFFFF); - - /* Clear SATA status,Firstly we get the AcpiGpe0BlkAddr */ - /* ????? why CIM does not set the AcpiGpe0BlkAddr , but use it??? */ - - /* word = 0x0000; */ - /* word = pm_ioread(0x28); */ - /* byte = pm_ioread(0x29); */ - /* word |= byte<<8; */ - /* printk(BIOS_DEBUG, "AcpiGpe0Blk addr = %x\n", word); */ - /* write32(word, 0x80000000); */ -} - -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, - /* .enable = sb600_enable, */ - .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_ATI, - .device = PCI_DEVICE_ID_ATI_SB600_SATA, -}; diff --git a/src/southbridge/amd/sb600/sb600_sm.c b/src/southbridge/amd/sb600/sb600_sm.c deleted file mode 100644 index b074edb89e..0000000000 --- a/src/southbridge/amd/sb600/sb600_sm.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sb600.h" -#include "sb600_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 - -/* -* SB600 enables all USB controllers by default in SMBUS Control. -* SB600 enables SATA by default in SMBUS Control. -*/ -static void sm_init(device_t dev) -{ - u8 byte; - u8 byte_old; - u32 dword; - u32 ioapic_base; - u32 on; - u32 nmi_option; - - printk(BIOS_INFO, "sm_init().\n"); - - ioapic_base = pci_read_config32(dev, 0x74) & (0xffffffe0); /* some like mem resource, but does not have enable bit */ - /* Don't rename APIC ID */ - clear_ioapic(ioapic_base); - - dword = pci_read_config8(dev, 0x62); - dword |= 1 << 2; - pci_write_config8(dev, 0x62, dword); - - dword = pci_read_config32(dev, 0x78); - dword |= 1 << 9; - pci_write_config32(dev, 0x78, dword); /* enable 0xCD6 0xCD7 */ - - /* bit 10: MultiMediaTimerIrqEn */ - dword = pci_read_config8(dev, 0x64); - dword |= 1 << 10; - pci_write_config8(dev, 0x64, dword); - /* enable serial irq */ - byte = pci_read_config8(dev, 0x69); - byte |= 1 << 7; /* enable serial irq function */ - byte &= ~(0xF << 2); - byte |= 4 << 2; /* set NumSerIrqBits=4 */ - pci_write_config8(dev, 0x69, byte); - - byte = pm_ioread(0x61); - byte |= 1 << 1; /* Set to enable NB/SB handshake during IOAPIC interrupt for AMD K8/K7 */ - pm_iowrite(0x61, byte); - - /* disable SMI */ - byte = pm_ioread(0x53); - byte |= 1 << 3; - pm_iowrite(0x53, byte); - - /* power after power fail */ - on = CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL; - get_option(&on, "power_on_after_fail"); - byte = pm_ioread(0x74); - byte &= ~0x03; - if (on) { - byte |= 2; - } - byte |= 1 << 2; - pm_iowrite(0x74, byte); - printk(BIOS_INFO, "set power %s after power fail\n", on ? "on" : "off"); - - /* sb600 rpr:2.3.3: */ - byte = pm_ioread(0x9A); - byte |= 1 << 5 | 1 << 4 | 1 << 2; - pm_iowrite(0x9A, byte); - - byte = pm_ioread(0x8F); - byte |= 1 << 5; - byte &= ~(1 << 4); - pm_iowrite(0x8F, byte); - - pm_iowrite(0x8B, 0x01); - pm_iowrite(0x8A, 0x90); - pm_iowrite(0x88, 0x10); /* A21 */ - - byte = pm_ioread(0x7C); - byte |= 1 << 0; - pm_iowrite(0x7C, byte); - - byte = pm_ioread(0x68); - byte &= ~(1 << 1); - /* 2.6 */ - byte |= 1 << 2; - pm_iowrite(0x68, byte); - - /* 2.6 */ - byte = pm_ioread(0x65); - byte &= ~(1 << 7); - pm_iowrite(0x65, byte); - - /* 2.3.4 */ - byte = pm_ioread(0x52); - byte &= ~0x2F; - byte |= 0x8; - pm_iowrite(0x52, byte); - - byte = pm_ioread(0x8D); - byte &= ~(1 << 6); - pm_iowrite(0x8D, byte); - - byte = pm_ioread(0x61); - byte &= ~(1 << 2); - pm_iowrite(0x61, byte); - - byte = pm_ioread(0x42); - byte &= ~(1 << 2); - pm_iowrite(0x42, byte); - - /* Set up NMI on errors */ - byte = inb(0x70); /* RTC70 */ - byte_old = byte; - nmi_option = NMI_OFF; - get_option(&nmi_option, "nmi"); - if (nmi_option) { - byte &= ~(1 << 7); /* set NMI */ - printk(BIOS_INFO, "++++++++++set NMI+++++\n"); - } else { - byte |= (1 << 7); /* Can not mask NMI from PCI-E and NMI_NOW */ - printk(BIOS_INFO, "++++++++++no set NMI+++++\n"); - } - byte &= ~(1 << 7); - if (byte != byte_old) { - outb(byte, 0x70); - } - - /* 2.10 IO Trap Settings */ - abcfg_reg(0x10090, 1 << 16, 1 << 16); - - /* ab index */ - pci_write_config32(dev, 0xF0, AB_INDX); - /* Initialize the real time clock */ - rtc_init(0); - - /*3.4 Enabling IDE/PCIB Prefetch for Performance Enhancement */ - abcfg_reg(0x10060, 9 << 17, 9 << 17); - abcfg_reg(0x10064, 9 << 17, 9 << 17); - - /* 3.5 Enabling OHCI Prefetch for Performance Enhancement */ - abcfg_reg(0x80, 1 << 0, 1<< 0); - - /* 3.6 B-Link Client's Credit Variable Settings for the Downstream Arbitration Equation */ - /* 3.7 Enabling Additional Address Bits Checking in Downstream */ - abcfg_reg(0x9c, 3 << 0, 3 << 0); - - /* 3.8 Set B-Link Prefetch Mode */ - abcfg_reg(0x80, 3 << 17, 3 << 17); - - /* 3.9 Enabling Detection of Upstream Interrupts */ - abcfg_reg(0x94, 1 << 20,1 << 20); - - /* 3.10: Enabling Downstream Posted Transactions to Pass Non-Posted - * Transactions for the K8 Platform (for All Revisions) */ - abcfg_reg(0x10090, 1 << 8, 1 << 8); - - /* 3.11:Programming Cycle Delay for AB and BIF Clock Gating */ - /* 3.12: Enabling AB and BIF Clock Gating */ - abcfg_reg(0x10054, 0xFFFF0000, 0x1040000); - abcfg_reg(0x54, 0xFF << 16, 4 << 16); - printk(BIOS_INFO, "3.11, ABCFG:0x54\n"); - abcfg_reg(0x54, 1 << 24, 1 << 24); - printk(BIOS_INFO, "3.12, ABCFG:0x54\n"); - abcfg_reg(0x98, 0x0000FF00, 0x00004700); - - /* 3.13:Enabling AB Int_Arbiter Enhancement (for All Revisions) */ - abcfg_reg(0x10054, 0x0000FFFF, 0x07FF); - - /* 3.14:Enabling L1 on A-link Express */ - axcfg_reg(0x68, 0x00000003, 0x2); - axindxp_reg(0xa0, 0x0000F000, 0x6000); - - abcfg_reg(0x10098, 0xFFFFFFFF, 0x4000); - abcfg_reg(0x04, 0xFFFFFFFF, 0x6); - printk(BIOS_INFO, "sm_init() end\n"); - - /* Enable NbSb virtual channel */ - axcfg_reg(0x114, 0x3f << 1, 0 << 1); - axcfg_reg(0x120, 0x7f << 1, 0x7f << 1); - axcfg_reg(0x120, 7 << 24, 1 << 24); - axcfg_reg(0x120, 1 << 31, 1 << 31); - abcfg_reg(0x50, 1 << 3, 1 << 3); -} - -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, 0x10); - - 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, 0x10); - - 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, 0x10); - - 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, 0x10); - - 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 sb600_sm_read_resources(device_t dev) -{ - struct resource *res; - u8 byte; - - /* rpr2.14: Hides SM bus controller Bar1 where stores HPET MMIO base address */ - byte = pm_ioread(0x55); - byte |= 1 << 7; - pm_iowrite(0x55, byte); - - /* Get the normal pci resources of this device */ - /* pci_dev_read_resources(dev); */ - - byte = pm_ioread(0x55); - byte &= ~(1 << 7); - pm_iowrite(0x55, byte); - - /* apic */ - res = new_resource(dev, 0x74); - res->base = IO_APIC_ADDR; - res->size = 256 * 0x10; - res->limit = 0xFFFFFFFFUL; /* res->base + res->size -1; */ - res->align = 8; - res->gran = 8; - res->flags = IORESOURCE_MEM | IORESOURCE_FIXED; - - res = new_resource(dev, 0x14); /* hpet */ - res->base = 0xfed00000; /* reset hpet to widely accepted address */ - res->size = 0x400; - res->limit = 0xFFFFFFFFUL; /* res->base + res->size -1; */ - res->align = 8; - res->gran = 8; - res->flags = IORESOURCE_MEM | IORESOURCE_FIXED; - /* dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; */ - - /* smbus */ - res = new_resource(dev, 0x10); - res->base = 0xB00; - res->size = 0x10; - res->limit = 0xFFFFUL; /* res->base + res->size -1; */ - res->align = 8; - res->gran = 8; - res->flags = IORESOURCE_IO | IORESOURCE_FIXED; - - compact_resources(dev); - -} - -static void sb600_sm_set_resources(struct device *dev) -{ - struct resource *res; - u8 byte; - - pci_dev_set_resources(dev); - - /* rpr2.14: Make HPET MMIO decoding controlled by the memory enable bit in command register of LPC ISA bridge */ - byte = pm_ioread(0x52); - byte |= 1 << 6; - pm_iowrite(0x52, byte); - - res = find_resource(dev, 0x74); - pci_write_config32(dev, 0x74, res->base | 1 << 3); - - res = find_resource(dev, 0x14); - pci_write_config32(dev, 0x14, res->base); - - res = find_resource(dev, 0x10); - pci_write_config32(dev, 0x10, res->base | 1); -} - -static struct pci_operations lops_pci = { - .set_subsystem = pci_dev_set_subsystem, -}; - -static struct device_operations smbus_ops = { - .read_resources = sb600_sm_read_resources, - .set_resources = sb600_sm_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = sm_init, - .scan_bus = scan_static_bus, - /* .enable = sb600_enable, */ - .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_ATI, - .device = PCI_DEVICE_ID_ATI_SB600_SM, -}; diff --git a/src/southbridge/amd/sb600/sb600_smbus.c b/src/southbridge/amd/sb600/sb600_smbus.c deleted file mode 100644 index 0cc0e62c04..0000000000 --- a/src/southbridge/amd/sb600/sb600_smbus.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 "sb600_smbus.h" - -static inline void smbus_delay(void) -{ - outb(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; -} - -static void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val) -{ - u32 tmp; - - outl((reg_space & 0x3) << 30 | reg_addr, AB_INDX); - tmp = inl(AB_DATA); - - tmp &= ~mask; - tmp |= val; - - /* printk(BIOS_DEBUG, "about write %x, index=%x", tmp, (reg_space&0x3)<<30 | reg_addr); */ - outl((reg_space & 0x3) << 30 | reg_addr, AB_INDX); /* probably we dont have to do it again. */ - outl(tmp, AB_DATA); -} - -/* space = 0: AX_INDXC, AX_DATAC -* space = 1: AX_INDXP, AX_DATAP - */ -static void alink_ax_indx(u32 space /*c or p? */ , u32 axindc, - u32 mask, u32 val) -{ - u32 tmp; - - /* read axindc to tmp */ - outl(space << 30 | space << 3 | 0x30, AB_INDX); - outl(axindc, AB_DATA); - outl(space << 30 | space << 3 | 0x34, AB_INDX); - tmp = inl(AB_DATA); - - tmp &= ~mask; - tmp |= val; - - /* write tmp */ - outl(space << 30 | space << 3 | 0x30, AB_INDX); - outl(axindc, AB_DATA); - outl(space << 30 | space << 3 | 0x34, AB_INDX); - outl(tmp, AB_DATA); -} diff --git a/src/southbridge/amd/sb600/sb600_smbus.h b/src/southbridge/amd/sb600/sb600_smbus.h deleted file mode 100644 index 684d0e62c4..0000000000 --- a/src/southbridge/amd/sb600/sb600_smbus.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 SB600_SMBUS_H -#define SB600_SMBUS_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 1 -#define AXCFG 2 -#define ABCFG 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(0, (reg), (mask), (val)) -#define axindxp_reg(reg, mask, val) \ - alink_ax_indx(1, (reg), (mask), (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); -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); - -#endif diff --git a/src/southbridge/amd/sb600/sb600_usb.c b/src/southbridge/amd/sb600/sb600_usb.c deleted file mode 100644 index 7539f083c6..0000000000 --- a/src/southbridge/amd/sb600/sb600_usb.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 -#include -#include -#include -#include -#include -#include -#include "sb600.h" - -static struct pci_operations lops_pci = { - .set_subsystem = pci_dev_set_subsystem, -}; - -static void usb_init(struct device *dev) -{ - u8 byte; - u16 word; - u32 dword; - - /* Enable OHCI0-4 and EHCI Controllers */ - device_t sm_dev; - sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0)); - byte = pci_read_config8(sm_dev, 0x68); - byte |= 0x3F; - pci_write_config8(sm_dev, 0x68, byte); - - /* RPR 5.2 Enables the USB PME Event,Enable USB resume support */ - byte = pm_ioread(0x61); - byte |= 1 << 6; - pm_iowrite(0x61, byte); - byte = pm_ioread(0x65); - byte |= 1 << 2; - pm_iowrite(0x65, byte); - - /* RPR 5.3 Support USB device wakeup from the S4/S5 state */ - byte = pm_ioread(0x65); - byte &= ~(1 << 0); - pm_iowrite(0x65, byte); - - /* RPR 5.6 Enable the USB controller to get reset by any software that generate a PCIRst# condition */ - byte = pm_ioread(0x65); - byte |= (1 << 4); - pm_iowrite(0x65, byte); - - /* RPR 5.11 Disable OHCI MSI Capability */ - word = pci_read_config16(dev, 0x40); - word |= (0x1F << 8); - pci_write_config16(dev, 0x40, word); - - /* RPR 5.8 Disable the OHCI Dynamic Power Saving feature */ - dword = pci_read_config32(dev, 0x50); - dword &= ~(1 << 16); - pci_write_config32(dev, 0x50, dword); - - /* RPR 5.12 Enable prevention of OHCI accessing the invalid system memory address range */ - word = pci_read_config16(dev, 0x50); - word |= 1 << 15; - pci_write_config16(dev, 0x50, word); - - /* RPR 5.15 Disable SMI handshake in between USB and ACPI for USB legacy support. */ - /* The BIOS should always set this bit to prevent the malfunction on USB legacy keyboard/mouse support */ - word = pci_read_config16(dev, 0x50); - word |= 1 << 12; - pci_write_config16(dev, 0x50, word); -} - -static void usb_init2(struct device *dev) -{ - u8 byte; - u16 word; - u32 dword; - u32 usb2_bar0; - /* dword = pci_read_config32(dev, 0xf8); */ - /* dword |= 40; */ - /* pci_write_config32(dev, 0xf8, dword); */ - - usb2_bar0 = pci_read_config32(dev, 0x10) & ~0xFF; - printk(BIOS_INFO, "usb2_bar0=0x%x\n", usb2_bar0); - - /* RPR5.4 Enables the USB PHY auto calibration resister to match 45ohm resistance */ - dword = 0x00020F00; - write32(usb2_bar0 + 0xC0, dword); - - /* RPR5.5 Sets In/OUT FIFO threshold for best performance */ - dword = 0x00200040; - write32(usb2_bar0 + 0xA4, dword); - - /* RPR5.9 Disable the EHCI Dynamic Power Saving feature */ - word = read16(usb2_bar0 + 0xBC); - word &= ~(1 << 12); - write16(usb2_bar0 + 0xBC, word); - - /* RPR5.10 Disable EHCI MSI support */ - byte = pci_read_config8(dev, 0x50); - byte |= (1 << 6); - pci_write_config8(dev, 0x50, byte); - - /* RPR5.13 Disable C3 time enhancement feature */ - dword = pci_read_config32(dev, 0x50); - dword &= ~(1 << 28); - pci_write_config32(dev, 0x50, dword); - - /* RPR5.14 Disable USB PHY PLL Reset signal to come from ACPI */ - byte = pci_read_config8(dev, 0x54); - byte &= ~(1 << 0); - pci_write_config8(dev, 0x54, byte); -} - -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, - /*.enable = sb600_enable, */ - .scan_bus = 0, - .ops_pci = &lops_pci, -}; - -static const struct pci_driver usb_0_driver __pci_driver = { - .ops = &usb_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_SB600_USB_0, -}; -static const struct pci_driver usb_1_driver __pci_driver = { - .ops = &usb_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_SB600_USB_1, -}; -static const struct pci_driver usb_2_driver __pci_driver = { - .ops = &usb_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_SB600_USB_2, -}; -static const struct pci_driver usb_3_driver __pci_driver = { - .ops = &usb_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_SB600_USB_3, -}; -static const struct pci_driver usb_4_driver __pci_driver = { - .ops = &usb_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_SB600_USB_4, -}; - -static struct device_operations usb_ops2 = { - .read_resources = pci_dev_read_resources, - .set_resources = usb_set_resources, /* pci_dev_set_resources, */ - .enable_resources = pci_dev_enable_resources, - .init = usb_init2, - /*.enable = sb600_enable, */ - .scan_bus = 0, - .ops_pci = &lops_pci, -}; - -static const struct pci_driver usb_5_driver __pci_driver = { - .ops = &usb_ops2, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_SB600_USB2, -}; - diff --git a/src/southbridge/amd/sb600/sm.c b/src/southbridge/amd/sb600/sm.c new file mode 100644 index 0000000000..1a0d6acdd8 --- /dev/null +++ b/src/southbridge/amd/sb600/sm.c @@ -0,0 +1,375 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sb600.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 + +/* +* SB600 enables all USB controllers by default in SMBUS Control. +* SB600 enables SATA by default in SMBUS Control. +*/ +static void sm_init(device_t dev) +{ + u8 byte; + u8 byte_old; + u32 dword; + u32 ioapic_base; + u32 on; + u32 nmi_option; + + printk(BIOS_INFO, "sm_init().\n"); + + ioapic_base = pci_read_config32(dev, 0x74) & (0xffffffe0); /* some like mem resource, but does not have enable bit */ + /* Don't rename APIC ID */ + clear_ioapic(ioapic_base); + + dword = pci_read_config8(dev, 0x62); + dword |= 1 << 2; + pci_write_config8(dev, 0x62, dword); + + dword = pci_read_config32(dev, 0x78); + dword |= 1 << 9; + pci_write_config32(dev, 0x78, dword); /* enable 0xCD6 0xCD7 */ + + /* bit 10: MultiMediaTimerIrqEn */ + dword = pci_read_config8(dev, 0x64); + dword |= 1 << 10; + pci_write_config8(dev, 0x64, dword); + /* enable serial irq */ + byte = pci_read_config8(dev, 0x69); + byte |= 1 << 7; /* enable serial irq function */ + byte &= ~(0xF << 2); + byte |= 4 << 2; /* set NumSerIrqBits=4 */ + pci_write_config8(dev, 0x69, byte); + + byte = pm_ioread(0x61); + byte |= 1 << 1; /* Set to enable NB/SB handshake during IOAPIC interrupt for AMD K8/K7 */ + pm_iowrite(0x61, byte); + + /* disable SMI */ + byte = pm_ioread(0x53); + byte |= 1 << 3; + pm_iowrite(0x53, byte); + + /* power after power fail */ + on = CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL; + get_option(&on, "power_on_after_fail"); + byte = pm_ioread(0x74); + byte &= ~0x03; + if (on) { + byte |= 2; + } + byte |= 1 << 2; + pm_iowrite(0x74, byte); + printk(BIOS_INFO, "set power %s after power fail\n", on ? "on" : "off"); + + /* sb600 rpr:2.3.3: */ + byte = pm_ioread(0x9A); + byte |= 1 << 5 | 1 << 4 | 1 << 2; + pm_iowrite(0x9A, byte); + + byte = pm_ioread(0x8F); + byte |= 1 << 5; + byte &= ~(1 << 4); + pm_iowrite(0x8F, byte); + + pm_iowrite(0x8B, 0x01); + pm_iowrite(0x8A, 0x90); + pm_iowrite(0x88, 0x10); /* A21 */ + + byte = pm_ioread(0x7C); + byte |= 1 << 0; + pm_iowrite(0x7C, byte); + + byte = pm_ioread(0x68); + byte &= ~(1 << 1); + /* 2.6 */ + byte |= 1 << 2; + pm_iowrite(0x68, byte); + + /* 2.6 */ + byte = pm_ioread(0x65); + byte &= ~(1 << 7); + pm_iowrite(0x65, byte); + + /* 2.3.4 */ + byte = pm_ioread(0x52); + byte &= ~0x2F; + byte |= 0x8; + pm_iowrite(0x52, byte); + + byte = pm_ioread(0x8D); + byte &= ~(1 << 6); + pm_iowrite(0x8D, byte); + + byte = pm_ioread(0x61); + byte &= ~(1 << 2); + pm_iowrite(0x61, byte); + + byte = pm_ioread(0x42); + byte &= ~(1 << 2); + pm_iowrite(0x42, byte); + + /* Set up NMI on errors */ + byte = inb(0x70); /* RTC70 */ + byte_old = byte; + nmi_option = NMI_OFF; + get_option(&nmi_option, "nmi"); + if (nmi_option) { + byte &= ~(1 << 7); /* set NMI */ + printk(BIOS_INFO, "++++++++++set NMI+++++\n"); + } else { + byte |= (1 << 7); /* Can not mask NMI from PCI-E and NMI_NOW */ + printk(BIOS_INFO, "++++++++++no set NMI+++++\n"); + } + byte &= ~(1 << 7); + if (byte != byte_old) { + outb(byte, 0x70); + } + + /* 2.10 IO Trap Settings */ + abcfg_reg(0x10090, 1 << 16, 1 << 16); + + /* ab index */ + pci_write_config32(dev, 0xF0, AB_INDX); + /* Initialize the real time clock */ + rtc_init(0); + + /*3.4 Enabling IDE/PCIB Prefetch for Performance Enhancement */ + abcfg_reg(0x10060, 9 << 17, 9 << 17); + abcfg_reg(0x10064, 9 << 17, 9 << 17); + + /* 3.5 Enabling OHCI Prefetch for Performance Enhancement */ + abcfg_reg(0x80, 1 << 0, 1<< 0); + + /* 3.6 B-Link Client's Credit Variable Settings for the Downstream Arbitration Equation */ + /* 3.7 Enabling Additional Address Bits Checking in Downstream */ + abcfg_reg(0x9c, 3 << 0, 3 << 0); + + /* 3.8 Set B-Link Prefetch Mode */ + abcfg_reg(0x80, 3 << 17, 3 << 17); + + /* 3.9 Enabling Detection of Upstream Interrupts */ + abcfg_reg(0x94, 1 << 20,1 << 20); + + /* 3.10: Enabling Downstream Posted Transactions to Pass Non-Posted + * Transactions for the K8 Platform (for All Revisions) */ + abcfg_reg(0x10090, 1 << 8, 1 << 8); + + /* 3.11:Programming Cycle Delay for AB and BIF Clock Gating */ + /* 3.12: Enabling AB and BIF Clock Gating */ + abcfg_reg(0x10054, 0xFFFF0000, 0x1040000); + abcfg_reg(0x54, 0xFF << 16, 4 << 16); + printk(BIOS_INFO, "3.11, ABCFG:0x54\n"); + abcfg_reg(0x54, 1 << 24, 1 << 24); + printk(BIOS_INFO, "3.12, ABCFG:0x54\n"); + abcfg_reg(0x98, 0x0000FF00, 0x00004700); + + /* 3.13:Enabling AB Int_Arbiter Enhancement (for All Revisions) */ + abcfg_reg(0x10054, 0x0000FFFF, 0x07FF); + + /* 3.14:Enabling L1 on A-link Express */ + axcfg_reg(0x68, 0x00000003, 0x2); + axindxp_reg(0xa0, 0x0000F000, 0x6000); + + abcfg_reg(0x10098, 0xFFFFFFFF, 0x4000); + abcfg_reg(0x04, 0xFFFFFFFF, 0x6); + printk(BIOS_INFO, "sm_init() end\n"); + + /* Enable NbSb virtual channel */ + axcfg_reg(0x114, 0x3f << 1, 0 << 1); + axcfg_reg(0x120, 0x7f << 1, 0x7f << 1); + axcfg_reg(0x120, 7 << 24, 1 << 24); + axcfg_reg(0x120, 1 << 31, 1 << 31); + abcfg_reg(0x50, 1 << 3, 1 << 3); +} + +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, 0x10); + + 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, 0x10); + + 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, 0x10); + + 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, 0x10); + + 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 sb600_sm_read_resources(device_t dev) +{ + struct resource *res; + u8 byte; + + /* rpr2.14: Hides SM bus controller Bar1 where stores HPET MMIO base address */ + byte = pm_ioread(0x55); + byte |= 1 << 7; + pm_iowrite(0x55, byte); + + /* Get the normal pci resources of this device */ + /* pci_dev_read_resources(dev); */ + + byte = pm_ioread(0x55); + byte &= ~(1 << 7); + pm_iowrite(0x55, byte); + + /* apic */ + res = new_resource(dev, 0x74); + res->base = IO_APIC_ADDR; + res->size = 256 * 0x10; + res->limit = 0xFFFFFFFFUL; /* res->base + res->size -1; */ + res->align = 8; + res->gran = 8; + res->flags = IORESOURCE_MEM | IORESOURCE_FIXED; + + res = new_resource(dev, 0x14); /* hpet */ + res->base = 0xfed00000; /* reset hpet to widely accepted address */ + res->size = 0x400; + res->limit = 0xFFFFFFFFUL; /* res->base + res->size -1; */ + res->align = 8; + res->gran = 8; + res->flags = IORESOURCE_MEM | IORESOURCE_FIXED; + /* dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; */ + + /* smbus */ + res = new_resource(dev, 0x10); + res->base = 0xB00; + res->size = 0x10; + res->limit = 0xFFFFUL; /* res->base + res->size -1; */ + res->align = 8; + res->gran = 8; + res->flags = IORESOURCE_IO | IORESOURCE_FIXED; + + compact_resources(dev); + +} + +static void sb600_sm_set_resources(struct device *dev) +{ + struct resource *res; + u8 byte; + + pci_dev_set_resources(dev); + + /* rpr2.14: Make HPET MMIO decoding controlled by the memory enable bit in command register of LPC ISA bridge */ + byte = pm_ioread(0x52); + byte |= 1 << 6; + pm_iowrite(0x52, byte); + + res = find_resource(dev, 0x74); + pci_write_config32(dev, 0x74, res->base | 1 << 3); + + res = find_resource(dev, 0x14); + pci_write_config32(dev, 0x14, res->base); + + res = find_resource(dev, 0x10); + pci_write_config32(dev, 0x10, res->base | 1); +} + +static struct pci_operations lops_pci = { + .set_subsystem = pci_dev_set_subsystem, +}; + +static struct device_operations smbus_ops = { + .read_resources = sb600_sm_read_resources, + .set_resources = sb600_sm_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = sm_init, + .scan_bus = scan_static_bus, + /* .enable = sb600_enable, */ + .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_ATI, + .device = PCI_DEVICE_ID_ATI_SB600_SM, +}; diff --git a/src/southbridge/amd/sb600/smbus.c b/src/southbridge/amd/sb600/smbus.c new file mode 100644 index 0000000000..cdd1930b5f --- /dev/null +++ b/src/southbridge/amd/sb600/smbus.c @@ -0,0 +1,214 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 "smbus.h" + +static inline void smbus_delay(void) +{ + outb(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; +} + +static void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val) +{ + u32 tmp; + + outl((reg_space & 0x3) << 30 | reg_addr, AB_INDX); + tmp = inl(AB_DATA); + + tmp &= ~mask; + tmp |= val; + + /* printk(BIOS_DEBUG, "about write %x, index=%x", tmp, (reg_space&0x3)<<30 | reg_addr); */ + outl((reg_space & 0x3) << 30 | reg_addr, AB_INDX); /* probably we dont have to do it again. */ + outl(tmp, AB_DATA); +} + +/* space = 0: AX_INDXC, AX_DATAC +* space = 1: AX_INDXP, AX_DATAP + */ +static void alink_ax_indx(u32 space /*c or p? */ , u32 axindc, + u32 mask, u32 val) +{ + u32 tmp; + + /* read axindc to tmp */ + outl(space << 30 | space << 3 | 0x30, AB_INDX); + outl(axindc, AB_DATA); + outl(space << 30 | space << 3 | 0x34, AB_INDX); + tmp = inl(AB_DATA); + + tmp &= ~mask; + tmp |= val; + + /* write tmp */ + outl(space << 30 | space << 3 | 0x30, AB_INDX); + outl(axindc, AB_DATA); + outl(space << 30 | space << 3 | 0x34, AB_INDX); + outl(tmp, AB_DATA); +} diff --git a/src/southbridge/amd/sb600/smbus.h b/src/southbridge/amd/sb600/smbus.h new file mode 100644 index 0000000000..684d0e62c4 --- /dev/null +++ b/src/southbridge/amd/sb600/smbus.h @@ -0,0 +1,64 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 SB600_SMBUS_H +#define SB600_SMBUS_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 1 +#define AXCFG 2 +#define ABCFG 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(0, (reg), (mask), (val)) +#define axindxp_reg(reg, mask, val) \ + alink_ax_indx(1, (reg), (mask), (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); +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); + +#endif diff --git a/src/southbridge/amd/sb600/usb.c b/src/southbridge/amd/sb600/usb.c new file mode 100644 index 0000000000..7539f083c6 --- /dev/null +++ b/src/southbridge/amd/sb600/usb.c @@ -0,0 +1,203 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 +#include +#include +#include +#include +#include +#include +#include "sb600.h" + +static struct pci_operations lops_pci = { + .set_subsystem = pci_dev_set_subsystem, +}; + +static void usb_init(struct device *dev) +{ + u8 byte; + u16 word; + u32 dword; + + /* Enable OHCI0-4 and EHCI Controllers */ + device_t sm_dev; + sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0)); + byte = pci_read_config8(sm_dev, 0x68); + byte |= 0x3F; + pci_write_config8(sm_dev, 0x68, byte); + + /* RPR 5.2 Enables the USB PME Event,Enable USB resume support */ + byte = pm_ioread(0x61); + byte |= 1 << 6; + pm_iowrite(0x61, byte); + byte = pm_ioread(0x65); + byte |= 1 << 2; + pm_iowrite(0x65, byte); + + /* RPR 5.3 Support USB device wakeup from the S4/S5 state */ + byte = pm_ioread(0x65); + byte &= ~(1 << 0); + pm_iowrite(0x65, byte); + + /* RPR 5.6 Enable the USB controller to get reset by any software that generate a PCIRst# condition */ + byte = pm_ioread(0x65); + byte |= (1 << 4); + pm_iowrite(0x65, byte); + + /* RPR 5.11 Disable OHCI MSI Capability */ + word = pci_read_config16(dev, 0x40); + word |= (0x1F << 8); + pci_write_config16(dev, 0x40, word); + + /* RPR 5.8 Disable the OHCI Dynamic Power Saving feature */ + dword = pci_read_config32(dev, 0x50); + dword &= ~(1 << 16); + pci_write_config32(dev, 0x50, dword); + + /* RPR 5.12 Enable prevention of OHCI accessing the invalid system memory address range */ + word = pci_read_config16(dev, 0x50); + word |= 1 << 15; + pci_write_config16(dev, 0x50, word); + + /* RPR 5.15 Disable SMI handshake in between USB and ACPI for USB legacy support. */ + /* The BIOS should always set this bit to prevent the malfunction on USB legacy keyboard/mouse support */ + word = pci_read_config16(dev, 0x50); + word |= 1 << 12; + pci_write_config16(dev, 0x50, word); +} + +static void usb_init2(struct device *dev) +{ + u8 byte; + u16 word; + u32 dword; + u32 usb2_bar0; + /* dword = pci_read_config32(dev, 0xf8); */ + /* dword |= 40; */ + /* pci_write_config32(dev, 0xf8, dword); */ + + usb2_bar0 = pci_read_config32(dev, 0x10) & ~0xFF; + printk(BIOS_INFO, "usb2_bar0=0x%x\n", usb2_bar0); + + /* RPR5.4 Enables the USB PHY auto calibration resister to match 45ohm resistance */ + dword = 0x00020F00; + write32(usb2_bar0 + 0xC0, dword); + + /* RPR5.5 Sets In/OUT FIFO threshold for best performance */ + dword = 0x00200040; + write32(usb2_bar0 + 0xA4, dword); + + /* RPR5.9 Disable the EHCI Dynamic Power Saving feature */ + word = read16(usb2_bar0 + 0xBC); + word &= ~(1 << 12); + write16(usb2_bar0 + 0xBC, word); + + /* RPR5.10 Disable EHCI MSI support */ + byte = pci_read_config8(dev, 0x50); + byte |= (1 << 6); + pci_write_config8(dev, 0x50, byte); + + /* RPR5.13 Disable C3 time enhancement feature */ + dword = pci_read_config32(dev, 0x50); + dword &= ~(1 << 28); + pci_write_config32(dev, 0x50, dword); + + /* RPR5.14 Disable USB PHY PLL Reset signal to come from ACPI */ + byte = pci_read_config8(dev, 0x54); + byte &= ~(1 << 0); + pci_write_config8(dev, 0x54, byte); +} + +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, + /*.enable = sb600_enable, */ + .scan_bus = 0, + .ops_pci = &lops_pci, +}; + +static const struct pci_driver usb_0_driver __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_SB600_USB_0, +}; +static const struct pci_driver usb_1_driver __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_SB600_USB_1, +}; +static const struct pci_driver usb_2_driver __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_SB600_USB_2, +}; +static const struct pci_driver usb_3_driver __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_SB600_USB_3, +}; +static const struct pci_driver usb_4_driver __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_SB600_USB_4, +}; + +static struct device_operations usb_ops2 = { + .read_resources = pci_dev_read_resources, + .set_resources = usb_set_resources, /* pci_dev_set_resources, */ + .enable_resources = pci_dev_enable_resources, + .init = usb_init2, + /*.enable = sb600_enable, */ + .scan_bus = 0, + .ops_pci = &lops_pci, +}; + +static const struct pci_driver usb_5_driver __pci_driver = { + .ops = &usb_ops2, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_SB600_USB2, +}; + diff --git a/src/southbridge/amd/sb700/Makefile.inc b/src/southbridge/amd/sb700/Makefile.inc index dd97df31e6..8d1c20813a 100644 --- a/src/southbridge/amd/sb700/Makefile.inc +++ b/src/southbridge/amd/sb700/Makefile.inc @@ -1,10 +1,10 @@ driver-y += sb700.c -driver-y += sb700_usb.c -driver-y += sb700_lpc.c -driver-y += sb700_sm.c -driver-y += sb700_ide.c -driver-y += sb700_sata.c -driver-y += sb700_hda.c -driver-y += sb700_pci.c -ramstage-y += sb700_reset.c -romstage-y += sb700_enable_usbdebug.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 +ramstage-y += reset.c +romstage-y += enable_usbdebug.c diff --git a/src/southbridge/amd/sb700/early_setup.c b/src/southbridge/amd/sb700/early_setup.c new file mode 100644 index 0000000000..81ffc1c7d5 --- /dev/null +++ b/src/southbridge/amd/sb700/early_setup.c @@ -0,0 +1,619 @@ +/* + * 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 _SB700_EARLY_SETUP_C_ +#define _SB700_EARLY_SETUP_C_ + +#include +#include +#include "sb700.h" +#include "smbus.c" + +#define SMBUS_IO_BASE 0x6000 /* Is it a temporary SMBus I/O base address? */ + /*SIZE 0x40 */ + +static void pmio_write(u8 reg, u8 value) +{ + outb(reg, PM_INDEX); + outb(value, PM_INDEX + 1); +} + +static u8 pmio_read(u8 reg) +{ + outb(reg, PM_INDEX); + return inb(PM_INDEX + 1); +} + +/* RPR 2.28: Get SB ASIC Revision. */ +static u8 set_sb700_revision(void) +{ + device_t dev; + u8 rev_id, enable_14Mhz, byte; + u8 rev = 0; + + /* if (rev != 0) return rev; */ + + dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); + + if (dev == PCI_DEV_INVALID) { + die("SMBUS controller not found\n"); + /* NOT REACHED */ + } + rev_id = pci_read_config8(dev, 0x08); + + if (rev_id == 0x39) { + enable_14Mhz = (pmio_read(0x53) >> 6) & 1; + if (enable_14Mhz == 0x0) + rev = 0x11; /* A11 */ + else if (enable_14Mhz == 0x1) { + /* This happens, if does, only once. So later if we need to get + * the revision ID, we don't have to make such a big function. + * We just get reg 0x8 in smbus dev. 0x39 is A11, 0x3A is A12. */ + rev = 0x12; + byte = pci_read_config8(dev, 0x40); + byte |= 1 << 0; + pci_write_config8(dev, 0x40, byte); + + pci_write_config8(dev, 0x08, 0x3A); /* Change 0x39 to 0x3A. */ + + byte &= ~(1 << 0); + pci_write_config8(dev, 0x40, byte); + } + } else if (rev_id == 0x3A) { /* A12 will be 0x3A after BIOS is initialized */ + rev = 0x12; + } else if (rev_id == 0x3C) { + rev = 0x14; + } else if (rev_id == 0x3D) { + rev = 0x15; + } else + die("It is not SB700 or SB710\n"); + + return rev; +} + +/*************************************** +* Legacy devices are mapped to LPC space. +* Serial port 0 +* KBC Port +* ACPI Micro-controller port +* LPC ROM size +* This function does not change port 0x80 decoding. +* Console output through any port besides 0x3f8 is unsupported. +* If you use FWH ROMs, you have to setup IDSEL. +***************************************/ +static void sb700_lpc_init(void) +{ + u8 reg8; + u32 reg32; + device_t dev; + + dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); /* SMBUS controller */ + /* NOTE: Set BootTimerDisable, otherwise it would keep rebooting!! + * This bit has no meaning if debug strap is not enabled. So if the + * board keeps rebooting and the code fails to reach here, we could + * disable the debug strap first. */ + reg32 = pci_read_config32(dev, 0x4C); + reg32 |= 1 << 31; + pci_write_config32(dev, 0x4C, reg32); + + /* Enable lpc controller */ + reg32 = pci_read_config32(dev, 0x64); + reg32 |= 1 << 20; + pci_write_config32(dev, 0x64, reg32); + + dev = pci_locate_device(PCI_ID(0x1002, 0x439d), 0); /* LPC Controller */ + /* Decode port 0x3f8-0x3ff (Serial 0) */ + // XXX Serial port decode on LPC is hardcoded to 0x3f8 + reg8 = pci_read_config8(dev, 0x44); + reg8 |= 1 << 6; + pci_write_config8(dev, 0x44, reg8); + + /* Decode port 0x60 & 0x64 (PS/2 keyboard) and port 0x62 & 0x66 (ACPI)*/ + reg8 = pci_read_config8(dev, 0x47); + reg8 |= (1 << 5) | (1 << 6); + pci_write_config8(dev, 0x47, reg8); + + /* Enable PrefetchEnSPIFromHost to speed up SPI flash read (does not affect LPC) */ + reg8 = pci_read_config8(dev, 0xbb); + reg8 |= 1 << 0; + pci_write_config8(dev, 0xbb, reg8); + + /* SuperIO, LPC ROM */ + reg8 = pci_read_config8(dev, 0x48); + /* Decode ports 0x2e-0x2f, 0x4e-0x4f (SuperI/O configuration) */ + reg8 |= (1 << 1) | (1 << 0); + /* Decode variable LPC ROM address ranges 1&2 (see register 0x68-0x6b, 0x6c-0x6f) */ + reg8 |= (1 << 3) | (1 << 4); + /* Decode port 0x70-0x73 (RTC) */ + reg8 |= 1 << 6; + pci_write_config8(dev, 0x48, reg8); + + /* hardware should enable LPC ROM by pin straps */ + /* ROM access at 0xFFF80000/0xFFF00000 - 0xFFFFFFFF */ + /* See detail in 43366_sb700_bdg_nda_1.01.pdf page 17. */ + /* enable LPC ROM range mirroring start 0x000e(0000) */ + pci_write_config16(dev, 0x68, 0x000e); + /* enable LPC ROM range mirroring end 0x000f(ffff) */ + pci_write_config16(dev, 0x6a, 0x000f); + /* enable LPC ROM range start, 0xfff8(0000): 512KB, 0xfff0(0000): 1MB */ + pci_write_config16(dev, 0x6c, 0xfff0); + /* enable LPC ROM range end at 0xffff(ffff) */ + pci_write_config16(dev, 0x6e, 0xffff); +} + +/* what is its usage? */ +static u32 get_sbdn(u32 bus) +{ + device_t dev; + + /* Find the device. */ + dev = pci_locate_device_on_bus(PCI_ID(0x1002, 0x4385), bus); + return (dev >> 15) & 0x1f; +} + +static u8 dual_core(void) +{ + return (pci_read_config32(PCI_DEV(0, 0x18, 3), 0xE8) & (0x3<<12)) != 0; +} + +/* + * RPR 2.4 C-state and VID/FID change for the K8 platform. + */ +static void enable_fid_change_on_sb(u32 sbbusn, u32 sbdn) +{ + u8 byte; + byte = pmio_read(0x9a); + byte &= ~0x34; + if (dual_core()) + byte |= 0x34; + else + byte |= 0x04; + pmio_write(0x9a, byte); + + byte = pmio_read(0x8f); + byte &= ~0x30; + byte |= 0x20; + pmio_write(0x8f, byte); + + pmio_write(0x8b, 0x01); /* TODO: if the HT Link is 200 MHz, it is 0x0A. It doesnt often happen. */ + pmio_write(0x8a, 0x90); + + pmio_write(0x88, 0x10); + + byte = pmio_read(0x7c); + byte |= 0x03; + pmio_write(0x7c, byte); + + /* Must be 0 for K8 platform. */ + byte = pmio_read(0x68); + byte &= ~0x01; + pmio_write(0x68, byte); + /* Must be 0 for K8 platform. */ + byte = pmio_read(0x8d); + byte &= ~(1<<6); + pmio_write(0x8d, byte); + + byte = pmio_read(0x61); + byte &= ~0x04; + pmio_write(0x61, byte); + + byte = pmio_read(0x42); + byte &= ~0x04; + pmio_write(0x42, byte); + + pmio_write(0x89, 0x10); +} + +void hard_reset(void) +{ + set_bios_reset(); + + /* full reset */ + outb(0x0a, 0x0cf9); + outb(0x0e, 0x0cf9); +} + +void soft_reset(void) +{ + set_bios_reset(); + /* link reset */ + outb(0x06, 0x0cf9); +} + +void sb700_pci_port80(void) +{ + u8 byte; + device_t dev; + + /* P2P Bridge */ + dev = pci_locate_device(PCI_ID(0x1002, 0x4384), 0); + + /* Chip Control: Enable subtractive decoding */ + byte = pci_read_config8(dev, 0x40); + byte |= 1 << 5; + pci_write_config8(dev, 0x40, byte); + + /* Misc Control: Enable subtractive decoding if 0x40 bit 5 is set */ + byte = pci_read_config8(dev, 0x4B); + byte |= 1 << 7; + pci_write_config8(dev, 0x4B, byte); + + /* The same IO Base and IO Limit here is meaningful because we set the + * bridge to be subtractive. During early setup stage, we have to make + * sure that data can go through port 0x80. + */ + /* IO Base: 0xf000 */ + byte = pci_read_config8(dev, 0x1C); + byte |= 0xF << 4; + pci_write_config8(dev, 0x1C, byte); + + /* IO Limit: 0xf000 */ + byte = pci_read_config8(dev, 0x1D); + byte |= 0xF << 4; + pci_write_config8(dev, 0x1D, byte); + + /* PCI Command: Enable IO response */ + byte = pci_read_config8(dev, 0x04); + byte |= 1 << 0; + pci_write_config8(dev, 0x04, byte); + + /* LPC controller */ + dev = pci_locate_device(PCI_ID(0x1002, 0x439D), 0); + + byte = pci_read_config8(dev, 0x4A); + byte &= ~(1 << 5); /* disable lpc port 80 */ + pci_write_config8(dev, 0x4A, byte); +} + +void sb700_lpc_port80(void) +{ + u8 byte; + device_t dev; + u32 reg32; + + /* Enable LPC controller */ + dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); + reg32 = pci_read_config32(dev, 0x64); + reg32 |= 0x00100000; /* lpcEnable */ + pci_write_config32(dev, 0x64, reg32); + + /* Enable port 80 LPC decode in pci function 3 configuration space. */ + dev = 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); +} + +/* sbDevicesPorInitTable */ +static void sb700_devices_por_init(void) +{ + device_t dev; + u8 byte; + + printk(BIOS_INFO, "sb700_devices_por_init()\n"); + /* SMBus Device, BDF:0-20-0 */ + printk(BIOS_INFO, "sb700_devices_por_init(): SMBus Device, BDF:0-20-0\n"); + dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); + + if (dev == PCI_DEV_INVALID) { + die("SMBUS controller not found\n"); + /* NOT REACHED */ + } + printk(BIOS_INFO, "SMBus controller enabled, sb revision is A%x\n", + set_sb700_revision()); + + /* sbPorAtStartOfTblCfg */ + /* Set A-Link bridge access address. This address is set at device 14h, function 0, register 0xf0. + * This is an I/O address. The I/O address must be on 16-byte boundry. */ + pci_write_config32(dev, 0xf0, AB_INDX); + + /* To enable AB/BIF DMA access, a specific register inside the BIF register space needs to be configured first. */ + /* 4.3:Enables the SB700 to send transactions upstream over A-Link Express interface. */ + axcfg_reg(0x04, 1 << 2, 1 << 2); + axindxc_reg(0x21, 0xff, 0); + + /* 2.5:Enabling Non-Posted Memory Write for the K8 Platform */ + axindxc_reg(0x10, 1 << 9, 1 << 9); + /* END of sbPorAtStartOfTblCfg */ + + /* sbDevicesPorInitTables */ + /* set smbus iobase */ + pci_write_config32(dev, 0x90, SMBUS_IO_BASE | 1); + + /* enable smbus controller interface */ + byte = pci_read_config8(dev, 0xd2); + byte |= (1 << 0); + pci_write_config8(dev, 0xd2, byte); + + /* KB2RstEnable */ + pci_write_config8(dev, 0x40, 0x44); + + /* Enable ISA Address 0-960K decoding */ + pci_write_config8(dev, 0x48, 0x0f); + + /* Enable ISA Address 0xC0000-0xDFFFF decode */ + pci_write_config8(dev, 0x49, 0xff); + + /* Enable decode cycles to IO C50, C51, C52 GPM controls. */ + byte = pci_read_config8(dev, 0x41); + byte &= 0x80; + byte |= 0x33; + pci_write_config8(dev, 0x41, byte); + + /* Legacy DMA Prefetch Enhancement, CIM masked it. */ + /* pci_write_config8(dev, 0x43, 0x1); */ + + /* Disabling Legacy USB Fast SMI# */ + byte = pci_read_config8(dev, 0x62); + byte |= 0x24; + pci_write_config8(dev, 0x62, byte); + + /* Features Enable */ + pci_write_config32(dev, 0x64, 0x829E79BF); /* bit10: Enables the HPET interrupt. */ + + /* SerialIrq Control */ + pci_write_config8(dev, 0x69, 0x90); + + /* Test Mode, PCIB_SReset_En Mask is set. */ + pci_write_config8(dev, 0x6c, 0x20); + + /* IO Address Enable, CIM set 0x78 only and masked 0x79. */ + /*pci_write_config8(dev, 0x79, 0x4F); */ + pci_write_config8(dev, 0x78, 0xFF); + + /* Set smbus iospace enable, I don't know why write 0x04 into reg5 that is reserved */ + pci_write_config16(dev, 0x4, 0x0407); + + /* clear any lingering errors, so the transaction will run */ + outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); + + /* IDE Device, BDF:0-20-1 */ + printk(BIOS_INFO, "sb700_devices_por_init(): IDE Device, BDF:0-20-1\n"); + dev = pci_locate_device(PCI_ID(0x1002, 0x439C), 0); + /* Disable prefetch */ + byte = pci_read_config8(dev, 0x63); + byte |= 0x1; + pci_write_config8(dev, 0x63, byte); + + /* LPC Device, BDF:0-20-3 */ + printk(BIOS_INFO, "sb700_devices_por_init(): LPC Device, BDF:0-20-3\n"); + dev = pci_locate_device(PCI_ID(0x1002, 0x439D), 0); + /* DMA enable */ + pci_write_config8(dev, 0x40, 0x04); + + /* IO Port Decode Enable */ + pci_write_config8(dev, 0x44, 0xFF); + pci_write_config8(dev, 0x45, 0xFF); + pci_write_config8(dev, 0x46, 0xC3); + pci_write_config8(dev, 0x47, 0xFF); + + /* IO/Mem Port Decode Enable, I don't know why CIM disable some ports. + * Disable LPC TimeOut counter, enable SuperIO Configuration Port (2e/2f), + * Alternate SuperIO Configuration Port (4e/4f), Wide Generic IO Port (64/65). + * Enable bits for LPC ROM memory address range 1&2 for 1M ROM setting.*/ + byte = pci_read_config8(dev, 0x48); + byte |= (1 << 1) | (1 << 0); /* enable Super IO config port 2e-2h, 4e-4f */ + byte |= (1 << 3) | (1 << 4); /* enable for LPC ROM address range1&2, Enable 512KB rom access at 0xFFF80000 - 0xFFFFFFFF */ + byte |= 1 << 6; /* enable for RTC I/O range */ + pci_write_config8(dev, 0x48, byte); + pci_write_config8(dev, 0x49, 0xFF); + /* Enable 0x480-0x4bf, 0x4700-0x470B */ + byte = pci_read_config8(dev, 0x4A); + byte |= ((1 << 1) + (1 << 6)); /*0x42, save the configuraion for port 0x80. */ + pci_write_config8(dev, 0x4A, byte); + + /* Set LPC ROM size, it has been done in sb700_lpc_init(). + * enable LPC ROM range, 0xfff8: 512KB, 0xfff0: 1MB; + * enable LPC ROM range, 0xfff8: 512KB, 0xfff0: 1MB + * pci_write_config16(dev, 0x68, 0x000e) + * pci_write_config16(dev, 0x6c, 0xfff0);*/ + + /* Enable Tpm12_en and Tpm_legacy. I don't know what is its usage and copied from CIM. */ + pci_write_config8(dev, 0x7C, 0x05); + + /* P2P Bridge, BDF:0-20-4, the configuration of the registers in this dev are copied from CIM, + */ + printk(BIOS_INFO, "sb700_devices_por_init(): P2P Bridge, BDF:0-20-4\n"); + dev = pci_locate_device(PCI_ID(0x1002, 0x4384), 0); + + /* Arbiter enable. */ + pci_write_config8(dev, 0x43, 0xff); + + /* Set PCDMA request into hight priority list. */ + /* pci_write_config8(dev, 0x49, 0x1) */ ; + + pci_write_config8(dev, 0x40, 0x26); + + pci_write_config8(dev, 0x0d, 0x40); + pci_write_config8(dev, 0x1b, 0x40); + /* Enable PCIB_DUAL_EN_UP will fix potential problem with PCI cards. */ + pci_write_config8(dev, 0x50, 0x01); + + /* SATA Device, BDF:0-17-0, Non-Raid-5 SATA controller */ + printk(BIOS_INFO, "sb700_devices_por_init(): SATA Device, BDF:0-18-0\n"); + dev = pci_locate_device(PCI_ID(0x1002, 0x4390), 0); + + /*PHY Global Control*/ + pci_write_config16(dev, 0x86, 0x2C00); +} + +/* sbPmioPorInitTable, Pre-initializing PMIO register space +* The power management (PM) block is resident in the PCI/LPC/ISA bridge. +* The PM regs are accessed via IO mapped regs 0xcd6 and 0xcd7. +* The index address is first programmed into IO reg 0xcd6. +* Read or write values are accessed through IO reg 0xcd7. +*/ +static void sb700_pmio_por_init(void) +{ + u8 byte; + + printk(BIOS_INFO, "sb700_pmio_por_init()\n"); + /* K8KbRstEn, KB_RST# control for K8 system. */ + byte = pmio_read(0x66); + byte |= 0x20; + pmio_write(0x66, byte); + + /* RPR2.31 PM_TURN_OFF_MSG during ASF Shutdown. */ + if (get_sb700_revision(pci_locate_device(PCI_ID(0x1002, 0x4385), 0)) <= 0x12) { + byte = pmio_read(0x65); + byte &= ~(1 << 7); + pmio_write(0x65, byte); + + byte = pmio_read(0x75); + byte &= 0xc0; + byte |= 0x05; + pmio_write(0x75, byte); + + byte = pmio_read(0x52); + byte &= 0xc0; + byte |= 0x08; + pmio_write(0x52, byte); + } else { + byte = pmio_read(0xD7); + byte |= 1 << 0; + pmio_write(0xD7, byte); + + byte = pmio_read(0x65); + byte |= 1 << 7; + pmio_write(0x65, byte); + + byte = pmio_read(0x75); + byte &= 0xc0; + byte |= 0x01; + pmio_write(0x75, byte); + + byte = pmio_read(0x52); + byte &= 0xc0; + byte |= 0x02; + pmio_write(0x52, byte); + + } + + /* Watch Dog Timer Control + * Set watchdog time base to 0xfec000f0 to avoid SCSI card boot failure. + * But I don't find WDT is enabled in SMBUS 0x41 bit3 in CIM. + */ + pmio_write(0x6c, 0xf0); + pmio_write(0x6d, 0x00); + pmio_write(0x6e, 0xc0); + pmio_write(0x6f, 0xfe); + + /* rpr2.15: Enabling Spread Spectrum */ + byte = pmio_read(0x42); + byte |= 1 << 7; + pmio_write(0x42, byte); + /* TODO: Check if it is necessary. IDE reset */ + byte = pmio_read(0xB2); + byte |= 1 << 0; + pmio_write(0xB2, byte); +} + +/* +* Add any south bridge setting. +*/ +static void sb700_pci_cfg(void) +{ + device_t dev; + u8 byte; + + /* SMBus Device, BDF:0-20-0 */ + dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); + /* Enable watchdog decode timer */ + byte = pci_read_config8(dev, 0x41); + byte |= (1 << 3); + pci_write_config8(dev, 0x41, byte); + + /* Set to 1 to reset USB on the software (such as IO-64 or IO-CF9 cycles) + * generated PCIRST#. */ + byte = pmio_read(0x65); + byte |= (1 << 4); + pmio_write(0x65, byte); + + /* IDE Device, BDF:0-20-1 */ + dev = pci_locate_device(PCI_ID(0x1002, 0x439C), 0); + /* Enable IDE Explicit prefetch, 0x63[0] clear */ + byte = pci_read_config8(dev, 0x63); + byte &= 0xfe; + pci_write_config8(dev, 0x63, byte); + + /* LPC Device, BDF:0-20-3 */ + /* The code below is ported from old chipset. It is not + * mentioned in RPR. But I keep them. The registers and the + * comments are compatible. */ + dev = pci_locate_device(PCI_ID(0x1002, 0x439D), 0); + /* Enabling LPC DMA function. */ + byte = pci_read_config8(dev, 0x40); + byte |= (1 << 2); + pci_write_config8(dev, 0x40, byte); + /* Disabling LPC TimeOut. 0x48[7] clear. */ + byte = pci_read_config8(dev, 0x48); + byte &= 0x7f; + pci_write_config8(dev, 0x48, byte); + /* Disabling LPC MSI Capability, 0x78[1] clear. */ + byte = pci_read_config8(dev, 0x78); + byte &= 0xfd; + pci_write_config8(dev, 0x78, byte); + + /* SATA Device, BDF:0-17-0, Non-Raid-5 SATA controller */ + dev = pci_locate_device(PCI_ID(0x1002, 0x4390), 0); + /* rpr7.12 SATA MSI and D3 Power State Capability. */ + byte = pci_read_config8(dev, 0x40); + byte |= 1 << 0; + pci_write_config8(dev, 0x40, byte); + if (get_sb700_revision(pci_locate_device(PCI_ID(0x1002, 0x4385), 0)) <= 0x12) + pci_write_config8(dev, 0x34, 0x70); /* set 0x61 to 0x70 if S1 is not supported. */ + else + pci_write_config8(dev, 0x34, 0x50); /* set 0x61 to 0x50 if S1 is not supported. */ + byte &= ~(1 << 0); + pci_write_config8(dev, 0x40, byte); +} + +/* +*/ +static void sb700_por_init(void) +{ + /* sbDevicesPorInitTable + sbK8PorInitTable */ + sb700_devices_por_init(); + + /* sbPmioPorInitTable + sbK8PmioPorInitTable */ + sb700_pmio_por_init(); +} + +/* +* It should be called during early POST after memory detection and BIOS shadowing but before PCI bus enumeration. +*/ +static void sb700_before_pci_init(void) +{ + sb700_pci_cfg(); +} + +/* +* This function should be called after enable_sb700_smbus(). +*/ +static void sb700_early_setup(void) +{ + printk(BIOS_INFO, "sb700_early_setup()\n"); + sb700_por_init(); +} + +static int smbus_read_byte(u32 device, u32 address) +{ + return do_smbus_read_byte(SMBUS_IO_BASE, device, address); +} +#endif diff --git a/src/southbridge/amd/sb700/enable_usbdebug.c b/src/southbridge/amd/sb700/enable_usbdebug.c new file mode 100644 index 0000000000..d74a9bbc9f --- /dev/null +++ b/src/southbridge/amd/sb700/enable_usbdebug.c @@ -0,0 +1,63 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 Advanced Micro Devices, Inc. + * Copyright (C) 2010 Uwe Hermann + * + * 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 +#include +#include +#include +#include +#include "sb700.h" + +#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); +} + +/* + * Note: The SB700 has two EHCI devices, D18:F2 and D19:F2. + * This code currently only supports the first one, i.e., USB Debug devices + * attached to physical USB ports belonging to the first EHCI device. + */ +void sb700_enable_usbdebug(unsigned int port) +{ + device_t dev = PCI_DEV(0, 0x12, 2); /* USB EHCI, D18:F2 */ + + /* Set the EHCI BAR address. */ + pci_write_config32(dev, EHCI_BAR_INDEX, CONFIG_EHCI_BAR); + + /* Enable access to the EHCI memory space registers. */ + pci_write_config8(dev, PCI_COMMAND, PCI_COMMAND_MEMORY); + + /* + * Select the requested physical USB port (1-15) as the Debug Port. + * Must be called after the EHCI BAR has been set up (see above). + */ + set_debug_port(port); +} diff --git a/src/southbridge/amd/sb700/hda.c b/src/southbridge/amd/sb700/hda.c new file mode 100644 index 0000000000..417d513e90 --- /dev/null +++ b/src/southbridge/amd/sb700/hda.c @@ -0,0 +1,232 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include "sb700.h" + +#define HDA_ICII_REG 0x68 +#define HDA_ICII_BUSY (1 << 0) +#define HDA_ICII_VALID (1 << 1) + +static int set_bits(u32 port, u32 mask, u32 val) +{ + u32 dword; + int count; + + /* Write (val & ~mask) to port */ + val &= mask; + dword = read32(port); + dword &= ~mask; + dword |= val; + write32(port, dword); + + /* Wait for readback of register to + * match what was just written to it + */ + count = 50; + do { + /* Wait 1ms based on BKDG wait time */ + mdelay(1); + dword = read32(port); + dword &= mask; + } while ((dword != val) && --count); + + /* Timeout occured */ + if (!count) + return -1; + return 0; +} + +static u32 codec_detect(u32 base) +{ + u32 dword; + + /* Set Bit0 to 0 to enter reset state (BAR + 0x8)[0] */ + if (set_bits(base + 0x08, 1, 0) == -1) + goto no_codec; + + /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */ + if (set_bits(base + 0x08, 1, 1) == -1) + goto no_codec; + + /* Delay for 1 ms since the BKDG does */ + mdelay(1); + + /* Read in Codec location (BAR + 0xe)[3..0]*/ + dword = read32(base + 0xe); + dword &= 0x0F; + if (!dword) + goto no_codec; + + return dword; + +no_codec: + /* Codec Not found */ + /* Put HDA back in reset (BAR + 0x8) [0] */ + set_bits(base + 0x08, 1, 0); + printk(BIOS_DEBUG, "No codec!\n"); + return 0; +} + +/** + * Wait 50usec for the codec to indicate it is ready + * no response would imply that the codec is non-operative + */ +static int wait_for_ready(u32 base) +{ + /* Use a 50 usec timeout - the Linux kernel uses the + * same duration */ + + int timeout = 50; + + while(timeout--) { + u32 dword=read32(base + HDA_ICII_REG); + if (!(dword & HDA_ICII_BUSY)) + return 0; + udelay(1); + } + + return -1; +} + +/** + * Wait 50usec for the codec to indicate that it accepted + * the previous command. No response would imply that the code + * is non-operative + */ +static int wait_for_valid(u32 base) +{ + /* Use a 50 usec timeout - the Linux kernel uses the + * same duration */ + + int timeout = 50; + while(timeout--) { + u32 dword = read32(base + HDA_ICII_REG); + if ((dword & (HDA_ICII_VALID | HDA_ICII_BUSY)) == + HDA_ICII_VALID) + return 0; + udelay(1); + } + + return 1; +} + +static void codec_init(u32 base, int addr) +{ + u32 dword; + + /* 1 */ + if (wait_for_ready(base) == -1) + return; + + dword = (addr << 28) | 0x000f0000; + write32(base + 0x60, dword); + + if (wait_for_valid(base) == -1) + return; + + dword = read32(base + 0x64); + + /* 2 */ + printk(BIOS_DEBUG, "%x(th) codec viddid: %08x\n", addr, dword); +} + +static void codecs_init(u32 base, u32 codec_mask) +{ + int i; + for (i = 2; i >= 0; i--) { + if (codec_mask & (1 << i)) + codec_init(base, i); + } +} + +static void hda_init(struct device *dev) +{ + u8 byte; + u32 dword; + u32 base; + struct resource *res; + u32 codec_mask; + device_t sm_dev; + + /* Enable azalia - PM_io 0x59[3], no ac97 in sb700. */ + byte = pm_ioread(0x59); + byte |= 1 << 3; + pm_iowrite(0x59, byte); + + /* Find the SMBus */ + /* FIXME: Need to find out why the call below crashes. */ + /*sm_dev = dev_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_ATI_SB700_SM, 0);*/ + sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0)); + + /* Set routing pin - SMBus ExtFunc (0xf8/0xfc) */ + pci_write_config32(sm_dev, 0xf8, 0x00); + pci_write_config8(sm_dev, 0xfc, 0xAA); + /* Set INTA - SMBus 0x63 [2..0] */ + byte = pci_read_config8(sm_dev, 0x63); + byte &= ~0x7; + byte |= 0x0; /* INTA:0x0 - INTH:0x7 */ + pci_write_config8(sm_dev, 0x63, byte); + + /* Program the 2C to 0x437b1002 */ + dword = 0x437b1002; + pci_write_config32(dev, 0x2c, dword); + + /* Read in BAR */ + /* Is this right? HDA allows for a 64-bit BAR + * but this is only setup for a 32-bit one + */ + res = find_resource(dev, 0x10); + if (!res) + return; + + base = (u32)res->base; + printk(BIOS_DEBUG, "base = 0x%x\n", base); + codec_mask = codec_detect(base); + + if (codec_mask) { + printk(BIOS_DEBUG, "codec_mask = %02x\n", codec_mask); + codecs_init(base, codec_mask); + } +} + +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_ATI, + .device = PCI_DEVICE_ID_ATI_SB700_HDA, +}; diff --git a/src/southbridge/amd/sb700/ide.c b/src/southbridge/amd/sb700/ide.c new file mode 100644 index 0000000000..4652ca2539 --- /dev/null +++ b/src/southbridge/amd/sb700/ide.c @@ -0,0 +1,85 @@ +/* + * 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 +#include +#include +#include +#include +#include "sb700.h" + +static void ide_init(struct device *dev) +{ + struct southbridge_amd_sb700_config *conf; + /* Enable ide devices so the linux ide driver will work */ + u32 dword; + u8 byte; + + conf = dev->chip_info; + + /* RPR9.1 disable MSI */ + /* TODO: For A14, it should set as 1. I doubt it. */ + dword = pci_read_config32(dev, 0x70); + dword &= ~(1 << 16); + pci_write_config32(dev, 0x70, dword); + + /* Enable UDMA on all devices, it will become UDMA0 (default PIO is PIO0) */ + byte = pci_read_config8(dev, 0x54); + byte |= 0xf; + pci_write_config8(dev, 0x54, byte); + + /* Enable I/O Access&& Bus Master */ + dword = pci_read_config16(dev, 0x4); + dword |= 1 << 2; + pci_write_config16(dev, 0x4, dword); + + /* set ide as primary, if you want to boot from IDE, you'd better set it + * in $vendor/$mainboard/devicetree.cb */ + + + if (conf->boot_switch_sata_ide == 1) { + struct device *sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0)); + byte = pci_read_config8(sm_dev, 0xAD); + byte |= 1 << 4; + pci_write_config8(sm_dev, 0xAD, byte); + } + +#if CONFIG_PCI_ROM_RUN == 1 + pci_dev_init(dev); +#endif +} + +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_ATI, + .device = PCI_DEVICE_ID_ATI_SB700_IDE, +}; diff --git a/src/southbridge/amd/sb700/lpc.c b/src/southbridge/amd/sb700/lpc.c new file mode 100644 index 0000000000..a3a50c6c9b --- /dev/null +++ b/src/southbridge/amd/sb700/lpc.c @@ -0,0 +1,238 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sb700.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 */ +#if CONFIG_SOUTHBRIDGE_AMD_SB700_SKIP_ISA_DMA_INIT + printk(BIOS_DEBUG, "Skipping isa_dma_init() to avoid getting stuck.\n"); +#else + isa_dma_init(); +#endif + + /* 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); + pci_write_config8(dev, 0x78, byte); +} + +static void sb700_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 = IO_APIC_ADDR; + res->size = 0x00001000; + res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + + compact_resources(dev); +} + +static void sb700_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 whose children's resources are to be enabled + * + */ +static void sb700_lpc_enable_childrens_resources(device_t dev) +{ + struct bus *link; + u32 reg, reg_x; + int var_num = 0; + u16 reg_var[3]; + + reg = pci_read_config32(dev, 0x44); + reg_x = pci_read_config32(dev, 0x48); + + for (link = dev->link_list; link; link = link->next) { + device_t child; + for (child = link->children; child; + child = child->sibling) { + if (child->enabled + && (child->path.type == DEVICE_PATH_PNP)) { + struct resource *res; + for (res = child->resource_list; res; res = res->next) { + u32 base, end; /* don't need long long */ + if (!(res->flags & IORESOURCE_IO)) + continue; + base = res->base; + end = resource_end(res); + printk(BIOS_DEBUG, "sb700 lpc decode:%s, base=0x%08x, end=0x%08x\n", + dev_path(child), base, end); + switch (base) { + case 0x60: /* KB */ + case 0x64: /* MS */ + reg |= (1 << 29); + break; + case 0x3f8: /* COM1 */ + reg |= (1 << 6); + break; + case 0x2f8: /* COM2 */ + reg |= (1 << 7); + break; + case 0x378: /* Parallal 1 */ + reg |= (1 << 0); + break; + case 0x3f0: /* FD0 */ + reg |= (1 << 26); + break; + case 0x220: /* Aduio 0 */ + reg |= (1 << 8); + break; + case 0x300: /* Midi 0 */ + reg |= (1 << 18); + break; + case 0x400: + reg_x |= (1 << 16); + break; + case 0x480: + reg_x |= (1 << 17); + break; + case 0x500: + reg_x |= (1 << 18); + break; + case 0x580: + reg_x |= (1 << 19); + break; + case 0x4700: + reg_x |= (1 << 22); + break; + case 0xfd60: + reg_x |= (1 << 23); + break; + default: + if (var_num >= 3) + continue; /* only 3 var ; compact them ? */ + switch (var_num) { + case 0: + reg_x |= (1 << 2); + break; + case 1: + reg_x |= (1 << 24); + break; + case 2: + reg_x |= (1 << 25); + break; + } + reg_var[var_num++] = + base & 0xffff; + } + } + } + } + } + pci_write_config32(dev, 0x44, reg); + pci_write_config32(dev, 0x48, reg_x); + /* Set WideIO for as many IOs found (fall through is on purpose) */ + switch (var_num) { + case 2: + pci_write_config16(dev, 0x90, reg_var[2]); + case 1: + pci_write_config16(dev, 0x66, reg_var[1]); + case 0: + pci_write_config16(dev, 0x64, reg_var[0]); + break; + } +} + +static void sb700_lpc_enable_resources(device_t dev) +{ + pci_dev_enable_resources(dev); + sb700_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 = sb700_lpc_read_resources, + .set_resources = sb700_lpc_set_resources, + .enable_resources = sb700_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_ATI, + .device = PCI_DEVICE_ID_ATI_SB700_LPC, +}; diff --git a/src/southbridge/amd/sb700/pci.c b/src/southbridge/amd/sb700/pci.c new file mode 100644 index 0000000000..d1e9851b9d --- /dev/null +++ b/src/southbridge/amd/sb700/pci.c @@ -0,0 +1,128 @@ +/* + * 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 +#include +#include +#include +#include +#include "sb700.h" + +static void pci_init(struct device *dev) +{ + u32 dword; + u16 word; + u8 byte; + + /* RPR 5.1 Enables the PCI-bridge subtractive decode */ + /* This setting is strongly recommended since it supports some legacy PCI add-on cards,such as BIOS debug cards */ + byte = pci_read_config8(dev, 0x4B); + byte |= 1 << 7; + pci_write_config8(dev, 0x4B, byte); + byte = pci_read_config8(dev, 0x40); + byte |= 1 << 5; + pci_write_config8(dev, 0x40, byte); + + /* RPR5.2 PCI-bridge upstream dual address window */ + /* this setting is applicable if the system memory is more than 4GB,and the PCI device can support dual address access */ + byte = pci_read_config8(dev, 0x50); + byte |= 1 << 0; + pci_write_config8(dev, 0x50, byte); + + /* RPR 5.3 PCI bus 64-byte DMA read access */ + /* Enhance the PCI bus DMA performance */ + byte = pci_read_config8(dev, 0x4B); + byte |= 1 << 4; + pci_write_config8(dev, 0x4B, byte); + + /* RPR 5.4 Enables the PCIB writes to be cacheline aligned. */ + /* The size of the writes will be set in the Cacheline Register */ + byte = pci_read_config8(dev, 0x40); + byte |= 1 << 1; + pci_write_config8(dev, 0x40, byte); + + /* RPR 5.5 Enables the PCIB to retain ownership of the bus on the Primary side and on the Secondary side when GNT# is deasserted */ + pci_write_config8(dev, 0x0D, 0x40); + pci_write_config8(dev, 0x1B, 0x40); + + /* RPR 5.6 Enable the command matching checking function on "Memory Read" & "Memory Read Line" commands */ + byte = pci_read_config8(dev, 0x4B); + byte |= 1 << 6; + pci_write_config8(dev, 0x4B, byte); + + /* RPR 5.7 When enabled, the PCI arbiter checks for the Bus Idle before asserting GNT# */ + byte = pci_read_config8(dev, 0x4B); + byte |= 1 << 0; + pci_write_config8(dev, 0x4B, byte); + + /* RPR 5.8 Adjusts the GNT# de-assertion time */ + word = pci_read_config16(dev, 0x64); + word |= 1 << 12; + pci_write_config16(dev, 0x64, word); + + /* RPR 5.9 Fast Back to Back transactions support */ + byte = pci_read_config8(dev, 0x48); + byte |= 1 << 2; + /* pci_write_config8(dev, 0x48, byte); */ + + /* RPR 5.10 Enable Lock Operation */ + /* byte = pci_read_config8(dev, 0x48); */ + byte |= 1 << 3; + pci_write_config8(dev, 0x48, byte); + + /* RPR 5.11 Enable additional optional PCI clock */ + word = pci_read_config16(dev, 0x64); + word |= 1 << 8; + pci_write_config16(dev, 0x64, word); + + /* RPR 5.12 Enable One-Prefetch-Channel Mode */ + dword = pci_read_config32(dev, 0x64); + dword |= 1 << 20; + pci_write_config32(dev, 0x64, dword); + + /* RPR 5.13 Disable PCIB MSI Capability */ + byte = pci_read_config8(dev, 0x40); + byte &= ~(1 << 3); + pci_write_config8(dev, 0x40, byte); + + /* rpr5.14 Adjusting CLKRUN# */ + dword = pci_read_config32(dev, 0x64); + dword |= (1 << 15); + pci_write_config32(dev, 0x64, dword); +} + +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_ATI, + .device = PCI_DEVICE_ID_ATI_SB700_PCI, +}; diff --git a/src/southbridge/amd/sb700/reset.c b/src/southbridge/amd/sb700/reset.c new file mode 100644 index 0000000000..32ee66b4b5 --- /dev/null +++ b/src/southbridge/amd/sb700/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 +#include +#include + +#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/sb700/sata.c b/src/southbridge/amd/sb700/sata.c new file mode 100644 index 0000000000..08b9aa8ad9 --- /dev/null +++ b/src/southbridge/amd/sb700/sata.c @@ -0,0 +1,294 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include "sb700.h" + +static int sata_drive_detect(int portnum, u16 iobar) +{ + u8 byte, byte2; + int i = 0; + outb(0xA0 + 0x10 * (portnum % 2), iobar + 0x6); + while (byte = inb(iobar + 0x6), byte2 = inb(iobar + 0x7), + (byte != (0xA0 + 0x10 * (portnum % 2))) || + ((byte2 & 0x88) != 0)) { + printk(BIOS_SPEW, "0x6=%x, 0x7=%x\n", byte, byte2); + if (byte != (0xA0 + 0x10 * (portnum % 2))) { + /* This will happen at the first iteration of this loop + * if the first SATA port is unpopulated and the + * second SATA port is poulated. + */ + printk(BIOS_DEBUG, "drive no longer selected after %i ms, " + "retrying init\n", i * 10); + return 1; + } else + printk(BIOS_SPEW, "drive detection not yet completed, " + "waiting...\n"); + mdelay(10); + i++; + } + printk(BIOS_SPEW, "drive detection done after %i ms\n", i * 10); + return 0; +} + + /* This function can be overloaded in mainboard.c */ + +void __attribute__((weak)) sb700_setup_sata_phys(struct device *dev) { + /* RPR7.6.1 Program the PHY Global Control to 0x2C00 */ + pci_write_config16(dev, 0x86, 0x2c00); + + /* RPR7.6.2 SATA GENI PHY ports setting */ + pci_write_config32(dev, 0x88, 0x01B48017); + pci_write_config32(dev, 0x8c, 0x01B48019); + pci_write_config32(dev, 0x90, 0x01B48016); + pci_write_config32(dev, 0x94, 0x01B48016); + pci_write_config32(dev, 0x98, 0x01B48016); + pci_write_config32(dev, 0x9C, 0x01B48016); + + /* RPR7.6.3 SATA GEN II PHY port setting for port [0~5]. */ + pci_write_config16(dev, 0xA0, 0xA09A); + pci_write_config16(dev, 0xA2, 0xA09F); + pci_write_config16(dev, 0xA4, 0xA07A); + pci_write_config16(dev, 0xA6, 0xA07A); + pci_write_config16(dev, 0xA8, 0xA07A); + pci_write_config16(dev, 0xAA, 0xA07A); +} + +static void sata_init(struct device *dev) +{ + u8 byte; + u16 word; + u32 dword; + u8 rev_id; + u32 sata_bar5; + u16 sata_bar0, sata_bar1, sata_bar2, sata_bar3, sata_bar4; + int i, j; + + struct southbridge_ati_sb700_config *conf; + conf = dev->chip_info; + + device_t sm_dev; + /* SATA SMBus Disable */ + /* sm_dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); */ + sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0)); + /* Disable SATA SMBUS */ + byte = pci_read_config8(sm_dev, 0xad); + byte |= (1 << 1); + /* Enable SATA and power saving */ + byte = pci_read_config8(sm_dev, 0xad); + byte |= (1 << 0); + byte |= (1 << 5); + pci_write_config8(sm_dev, 0xad, byte); + + /* RPR 7.2 SATA Initialization */ + /* Set the interrupt Mapping to INTG# */ + byte = pci_read_config8(sm_dev, 0xaf); + byte = 0x6 << 2; + pci_write_config8(sm_dev, 0xaf, byte); + + /* get rev_id */ + rev_id = pci_read_config8(sm_dev, 0x08) - 0x28; + + /* get base address */ + sata_bar5 = pci_read_config32(dev, 0x24) & ~0x3FF; + sata_bar0 = pci_read_config16(dev, 0x10) & ~0x7; + sata_bar1 = pci_read_config16(dev, 0x14) & ~0x3; + sata_bar2 = pci_read_config16(dev, 0x18) & ~0x7; + sata_bar3 = pci_read_config16(dev, 0x1C) & ~0x3; + sata_bar4 = pci_read_config16(dev, 0x20) & ~0xf; + + printk(BIOS_SPEW, "sata_bar0=%x\n", sata_bar0); /* 3030 */ + printk(BIOS_SPEW, "sata_bar1=%x\n", sata_bar1); /* 3070 */ + printk(BIOS_SPEW, "sata_bar2=%x\n", sata_bar2); /* 3040 */ + printk(BIOS_SPEW, "sata_bar3=%x\n", sata_bar3); /* 3080 */ + printk(BIOS_SPEW, "sata_bar4=%x\n", sata_bar4); /* 3000 */ + printk(BIOS_SPEW, "sata_bar5=%x\n", sata_bar5); /* e0309000 */ + + /* disable combined mode */ + byte = pci_read_config8(sm_dev, 0xAD); + byte &= ~(1 << 3); + pci_write_config8(sm_dev, 0xAD, byte); + /* Program the 2C to 0x43801002 */ + dword = 0x43801002; + pci_write_config32(dev, 0x2c, dword); + + /* SERR-Enable */ + word = pci_read_config16(dev, 0x04); + word |= (1 << 8); + pci_write_config16(dev, 0x04, word); + + /* Dynamic power saving */ + byte = pci_read_config8(dev, 0x40); + byte |= (1 << 2); + pci_write_config8(dev, 0x40, byte); + + /* Set SATA Operation Mode, Set to IDE mode */ + byte = pci_read_config8(dev, 0x40); + byte |= (1 << 0); + byte |= (1 << 4); + pci_write_config8(dev, 0x40, byte); + + dword = 0x01018f00; + pci_write_config32(dev, 0x8, dword); + + byte = pci_read_config8(dev, 0x40); + byte &= ~(1 << 0); + pci_write_config8(dev, 0x40, byte); + + /* Enable the SATA watchdog counter */ + byte = pci_read_config8(dev, 0x44); + byte |= (1 << 0); + pci_write_config8(dev, 0x44, byte); + + /* Set bit 29 and 24 for A12 */ + dword = pci_read_config32(dev, 0x40); + if (rev_id < 0x14) /* before A12 */ + dword |= (1 << 29); + else + dword &= ~(1 << 29); /* A14 and above */ + pci_write_config32(dev, 0x40, dword); + + /* set bit 21 for A12 */ + dword = pci_read_config32(dev, 0x48); + if (rev_id < 0x14) /* before A12 */ + dword |= 1 << 24 | 1 << 21; + else { + dword &= ~(1 << 24 | 1 << 21); /* A14 and above */ + dword &= ~0xFF80; /* 15:7 */ + dword |= 1 << 15 | 0x7F << 7; + } + pci_write_config32(dev, 0x48, dword); + + /* Program the watchdog counter to 0x10 */ + byte = 0x10; + pci_write_config8(dev, 0x46, byte); + sb700_setup_sata_phys(dev); + /* Enable the I/O, MM, BusMaster access for SATA */ + byte = pci_read_config8(dev, 0x4); + byte |= 7 << 0; + pci_write_config8(dev, 0x4, byte); + + /* RPR7.7 SATA drive detection. */ + /* Use BAR5+0x128,BAR0 for Primary Slave */ + /* Use BAR5+0x1A8,BAR0 for Primary Slave */ + /* Use BAR5+0x228,BAR2 for Secondary Master */ + /* Use BAR5+0x2A8,BAR2 for Secondary Slave */ + /* Use BAR5+0x328,PATA_BAR0/2 for Primary/Secondary master emulation */ + /* Use BAR5+0x3A8,PATA_BAR0/2 for Primary/Secondary Slave emulation */ + + /* TODO: port 4,5, which are PATA emulations. What are PATA_BARs? */ + + for (i = 0; i < 4; i++) { + byte = read8(sata_bar5 + 0x128 + 0x80 * i); + printk(BIOS_SPEW, "SATA port %i status = %x\n", i, byte); + byte &= 0xF; + if( byte == 0x1 ) { + /* If the drive status is 0x1 then we see it but we aren't talking to it. */ + /* Try to do something about it. */ + printk(BIOS_SPEW, "SATA device detected but not talking. Trying lower speed.\n"); + + /* Read in Port-N Serial ATA Control Register */ + byte = read8(sata_bar5 + 0x12C + 0x80 * i); + + /* Set Reset Bit and 1.5g bit */ + byte |= 0x11; + write8((sata_bar5 + 0x12C + 0x80 * i), byte); + + /* Wait 1ms */ + mdelay(1); + + /* Clear Reset Bit */ + byte &= ~0x01; + write8((sata_bar5 + 0x12C + 0x80 * i), byte); + + /* Wait 1ms */ + mdelay(1); + + /* Reread status */ + byte = read8(sata_bar5 + 0x128 + 0x80 * i); + printk(BIOS_SPEW, "SATA port %i status = %x\n", i, byte); + byte &= 0xF; + } + + if (byte == 0x3) { + for (j = 0; j < 10; j++) { + if (!sata_drive_detect(i, ((i / 2) == 0) ? sata_bar0 : sata_bar2)) + break; + } + printk(BIOS_DEBUG, "%s %s device is %sready after %i tries\n", + (i / 2) ? "Secondary" : "Primary", + (i % 2 ) ? "Slave" : "Master", + (j == 10) ? "not " : "", + (j == 10) ? j : j + 1); + } else { + printk(BIOS_DEBUG, "No %s %s SATA drive on Slot%i\n", + (i / 2) ? "Secondary" : "Primary", + (i % 2 ) ? "Slave" : "Master", i); + } + } + + /* Below is CIM InitSataLateFar */ + /* Enable interrupts from the HBA */ + byte = read8(sata_bar5 + 0x4); + byte |= 1 << 1; + write8((sata_bar5 + 0x4), byte); + + /* Clear error status */ + write32((sata_bar5 + 0x130), 0xFFFFFFFF); + write32((sata_bar5 + 0x1b0), 0xFFFFFFFF); + write32((sata_bar5 + 0x230), 0xFFFFFFFF); + write32((sata_bar5 + 0x2b0), 0xFFFFFFFF); + write32((sata_bar5 + 0x330), 0xFFFFFFFF); + write32((sata_bar5 + 0x3b0), 0xFFFFFFFF); + + /* Clear SATA status,Firstly we get the AcpiGpe0BlkAddr */ + /* ????? why CIM does not set the AcpiGpe0BlkAddr , but use it??? */ + + /* word = 0x0000; */ + /* word = pm_ioread(0x28); */ + /* byte = pm_ioread(0x29); */ + /* word |= byte<<8; */ + /* printk(BIOS_DEBUG, "AcpiGpe0Blk addr = %x\n", word); */ + /* write32(word, 0x80000000); */ +} + +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_ATI, + .device = PCI_DEVICE_ID_ATI_SB700_SATA, +}; diff --git a/src/southbridge/amd/sb700/sb700_early_setup.c b/src/southbridge/amd/sb700/sb700_early_setup.c deleted file mode 100644 index 9f8d44f6c7..0000000000 --- a/src/southbridge/amd/sb700/sb700_early_setup.c +++ /dev/null @@ -1,619 +0,0 @@ -/* - * 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 _SB700_EARLY_SETUP_C_ -#define _SB700_EARLY_SETUP_C_ - -#include -#include -#include "sb700.h" -#include "sb700_smbus.c" - -#define SMBUS_IO_BASE 0x6000 /* Is it a temporary SMBus I/O base address? */ - /*SIZE 0x40 */ - -static void pmio_write(u8 reg, u8 value) -{ - outb(reg, PM_INDEX); - outb(value, PM_INDEX + 1); -} - -static u8 pmio_read(u8 reg) -{ - outb(reg, PM_INDEX); - return inb(PM_INDEX + 1); -} - -/* RPR 2.28: Get SB ASIC Revision. */ -static u8 set_sb700_revision(void) -{ - device_t dev; - u8 rev_id, enable_14Mhz, byte; - u8 rev = 0; - - /* if (rev != 0) return rev; */ - - dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); - - if (dev == PCI_DEV_INVALID) { - die("SMBUS controller not found\n"); - /* NOT REACHED */ - } - rev_id = pci_read_config8(dev, 0x08); - - if (rev_id == 0x39) { - enable_14Mhz = (pmio_read(0x53) >> 6) & 1; - if (enable_14Mhz == 0x0) - rev = 0x11; /* A11 */ - else if (enable_14Mhz == 0x1) { - /* This happens, if does, only once. So later if we need to get - * the revision ID, we don't have to make such a big function. - * We just get reg 0x8 in smbus dev. 0x39 is A11, 0x3A is A12. */ - rev = 0x12; - byte = pci_read_config8(dev, 0x40); - byte |= 1 << 0; - pci_write_config8(dev, 0x40, byte); - - pci_write_config8(dev, 0x08, 0x3A); /* Change 0x39 to 0x3A. */ - - byte &= ~(1 << 0); - pci_write_config8(dev, 0x40, byte); - } - } else if (rev_id == 0x3A) { /* A12 will be 0x3A after BIOS is initialized */ - rev = 0x12; - } else if (rev_id == 0x3C) { - rev = 0x14; - } else if (rev_id == 0x3D) { - rev = 0x15; - } else - die("It is not SB700 or SB710\n"); - - return rev; -} - -/*************************************** -* Legacy devices are mapped to LPC space. -* Serial port 0 -* KBC Port -* ACPI Micro-controller port -* LPC ROM size -* This function does not change port 0x80 decoding. -* Console output through any port besides 0x3f8 is unsupported. -* If you use FWH ROMs, you have to setup IDSEL. -***************************************/ -static void sb700_lpc_init(void) -{ - u8 reg8; - u32 reg32; - device_t dev; - - dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); /* SMBUS controller */ - /* NOTE: Set BootTimerDisable, otherwise it would keep rebooting!! - * This bit has no meaning if debug strap is not enabled. So if the - * board keeps rebooting and the code fails to reach here, we could - * disable the debug strap first. */ - reg32 = pci_read_config32(dev, 0x4C); - reg32 |= 1 << 31; - pci_write_config32(dev, 0x4C, reg32); - - /* Enable lpc controller */ - reg32 = pci_read_config32(dev, 0x64); - reg32 |= 1 << 20; - pci_write_config32(dev, 0x64, reg32); - - dev = pci_locate_device(PCI_ID(0x1002, 0x439d), 0); /* LPC Controller */ - /* Decode port 0x3f8-0x3ff (Serial 0) */ - // XXX Serial port decode on LPC is hardcoded to 0x3f8 - reg8 = pci_read_config8(dev, 0x44); - reg8 |= 1 << 6; - pci_write_config8(dev, 0x44, reg8); - - /* Decode port 0x60 & 0x64 (PS/2 keyboard) and port 0x62 & 0x66 (ACPI)*/ - reg8 = pci_read_config8(dev, 0x47); - reg8 |= (1 << 5) | (1 << 6); - pci_write_config8(dev, 0x47, reg8); - - /* Enable PrefetchEnSPIFromHost to speed up SPI flash read (does not affect LPC) */ - reg8 = pci_read_config8(dev, 0xbb); - reg8 |= 1 << 0; - pci_write_config8(dev, 0xbb, reg8); - - /* SuperIO, LPC ROM */ - reg8 = pci_read_config8(dev, 0x48); - /* Decode ports 0x2e-0x2f, 0x4e-0x4f (SuperI/O configuration) */ - reg8 |= (1 << 1) | (1 << 0); - /* Decode variable LPC ROM address ranges 1&2 (see register 0x68-0x6b, 0x6c-0x6f) */ - reg8 |= (1 << 3) | (1 << 4); - /* Decode port 0x70-0x73 (RTC) */ - reg8 |= 1 << 6; - pci_write_config8(dev, 0x48, reg8); - - /* hardware should enable LPC ROM by pin straps */ - /* ROM access at 0xFFF80000/0xFFF00000 - 0xFFFFFFFF */ - /* See detail in 43366_sb700_bdg_nda_1.01.pdf page 17. */ - /* enable LPC ROM range mirroring start 0x000e(0000) */ - pci_write_config16(dev, 0x68, 0x000e); - /* enable LPC ROM range mirroring end 0x000f(ffff) */ - pci_write_config16(dev, 0x6a, 0x000f); - /* enable LPC ROM range start, 0xfff8(0000): 512KB, 0xfff0(0000): 1MB */ - pci_write_config16(dev, 0x6c, 0xfff0); - /* enable LPC ROM range end at 0xffff(ffff) */ - pci_write_config16(dev, 0x6e, 0xffff); -} - -/* what is its usage? */ -static u32 get_sbdn(u32 bus) -{ - device_t dev; - - /* Find the device. */ - dev = pci_locate_device_on_bus(PCI_ID(0x1002, 0x4385), bus); - return (dev >> 15) & 0x1f; -} - -static u8 dual_core(void) -{ - return (pci_read_config32(PCI_DEV(0, 0x18, 3), 0xE8) & (0x3<<12)) != 0; -} - -/* - * RPR 2.4 C-state and VID/FID change for the K8 platform. - */ -static void enable_fid_change_on_sb(u32 sbbusn, u32 sbdn) -{ - u8 byte; - byte = pmio_read(0x9a); - byte &= ~0x34; - if (dual_core()) - byte |= 0x34; - else - byte |= 0x04; - pmio_write(0x9a, byte); - - byte = pmio_read(0x8f); - byte &= ~0x30; - byte |= 0x20; - pmio_write(0x8f, byte); - - pmio_write(0x8b, 0x01); /* TODO: if the HT Link is 200 MHz, it is 0x0A. It doesnt often happen. */ - pmio_write(0x8a, 0x90); - - pmio_write(0x88, 0x10); - - byte = pmio_read(0x7c); - byte |= 0x03; - pmio_write(0x7c, byte); - - /* Must be 0 for K8 platform. */ - byte = pmio_read(0x68); - byte &= ~0x01; - pmio_write(0x68, byte); - /* Must be 0 for K8 platform. */ - byte = pmio_read(0x8d); - byte &= ~(1<<6); - pmio_write(0x8d, byte); - - byte = pmio_read(0x61); - byte &= ~0x04; - pmio_write(0x61, byte); - - byte = pmio_read(0x42); - byte &= ~0x04; - pmio_write(0x42, byte); - - pmio_write(0x89, 0x10); -} - -void hard_reset(void) -{ - set_bios_reset(); - - /* full reset */ - outb(0x0a, 0x0cf9); - outb(0x0e, 0x0cf9); -} - -void soft_reset(void) -{ - set_bios_reset(); - /* link reset */ - outb(0x06, 0x0cf9); -} - -void sb700_pci_port80(void) -{ - u8 byte; - device_t dev; - - /* P2P Bridge */ - dev = pci_locate_device(PCI_ID(0x1002, 0x4384), 0); - - /* Chip Control: Enable subtractive decoding */ - byte = pci_read_config8(dev, 0x40); - byte |= 1 << 5; - pci_write_config8(dev, 0x40, byte); - - /* Misc Control: Enable subtractive decoding if 0x40 bit 5 is set */ - byte = pci_read_config8(dev, 0x4B); - byte |= 1 << 7; - pci_write_config8(dev, 0x4B, byte); - - /* The same IO Base and IO Limit here is meaningful because we set the - * bridge to be subtractive. During early setup stage, we have to make - * sure that data can go through port 0x80. - */ - /* IO Base: 0xf000 */ - byte = pci_read_config8(dev, 0x1C); - byte |= 0xF << 4; - pci_write_config8(dev, 0x1C, byte); - - /* IO Limit: 0xf000 */ - byte = pci_read_config8(dev, 0x1D); - byte |= 0xF << 4; - pci_write_config8(dev, 0x1D, byte); - - /* PCI Command: Enable IO response */ - byte = pci_read_config8(dev, 0x04); - byte |= 1 << 0; - pci_write_config8(dev, 0x04, byte); - - /* LPC controller */ - dev = pci_locate_device(PCI_ID(0x1002, 0x439D), 0); - - byte = pci_read_config8(dev, 0x4A); - byte &= ~(1 << 5); /* disable lpc port 80 */ - pci_write_config8(dev, 0x4A, byte); -} - -void sb700_lpc_port80(void) -{ - u8 byte; - device_t dev; - u32 reg32; - - /* Enable LPC controller */ - dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); - reg32 = pci_read_config32(dev, 0x64); - reg32 |= 0x00100000; /* lpcEnable */ - pci_write_config32(dev, 0x64, reg32); - - /* Enable port 80 LPC decode in pci function 3 configuration space. */ - dev = 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); -} - -/* sbDevicesPorInitTable */ -static void sb700_devices_por_init(void) -{ - device_t dev; - u8 byte; - - printk(BIOS_INFO, "sb700_devices_por_init()\n"); - /* SMBus Device, BDF:0-20-0 */ - printk(BIOS_INFO, "sb700_devices_por_init(): SMBus Device, BDF:0-20-0\n"); - dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); - - if (dev == PCI_DEV_INVALID) { - die("SMBUS controller not found\n"); - /* NOT REACHED */ - } - printk(BIOS_INFO, "SMBus controller enabled, sb revision is A%x\n", - set_sb700_revision()); - - /* sbPorAtStartOfTblCfg */ - /* Set A-Link bridge access address. This address is set at device 14h, function 0, register 0xf0. - * This is an I/O address. The I/O address must be on 16-byte boundry. */ - pci_write_config32(dev, 0xf0, AB_INDX); - - /* To enable AB/BIF DMA access, a specific register inside the BIF register space needs to be configured first. */ - /* 4.3:Enables the SB700 to send transactions upstream over A-Link Express interface. */ - axcfg_reg(0x04, 1 << 2, 1 << 2); - axindxc_reg(0x21, 0xff, 0); - - /* 2.5:Enabling Non-Posted Memory Write for the K8 Platform */ - axindxc_reg(0x10, 1 << 9, 1 << 9); - /* END of sbPorAtStartOfTblCfg */ - - /* sbDevicesPorInitTables */ - /* set smbus iobase */ - pci_write_config32(dev, 0x90, SMBUS_IO_BASE | 1); - - /* enable smbus controller interface */ - byte = pci_read_config8(dev, 0xd2); - byte |= (1 << 0); - pci_write_config8(dev, 0xd2, byte); - - /* KB2RstEnable */ - pci_write_config8(dev, 0x40, 0x44); - - /* Enable ISA Address 0-960K decoding */ - pci_write_config8(dev, 0x48, 0x0f); - - /* Enable ISA Address 0xC0000-0xDFFFF decode */ - pci_write_config8(dev, 0x49, 0xff); - - /* Enable decode cycles to IO C50, C51, C52 GPM controls. */ - byte = pci_read_config8(dev, 0x41); - byte &= 0x80; - byte |= 0x33; - pci_write_config8(dev, 0x41, byte); - - /* Legacy DMA Prefetch Enhancement, CIM masked it. */ - /* pci_write_config8(dev, 0x43, 0x1); */ - - /* Disabling Legacy USB Fast SMI# */ - byte = pci_read_config8(dev, 0x62); - byte |= 0x24; - pci_write_config8(dev, 0x62, byte); - - /* Features Enable */ - pci_write_config32(dev, 0x64, 0x829E79BF); /* bit10: Enables the HPET interrupt. */ - - /* SerialIrq Control */ - pci_write_config8(dev, 0x69, 0x90); - - /* Test Mode, PCIB_SReset_En Mask is set. */ - pci_write_config8(dev, 0x6c, 0x20); - - /* IO Address Enable, CIM set 0x78 only and masked 0x79. */ - /*pci_write_config8(dev, 0x79, 0x4F); */ - pci_write_config8(dev, 0x78, 0xFF); - - /* Set smbus iospace enable, I don't know why write 0x04 into reg5 that is reserved */ - pci_write_config16(dev, 0x4, 0x0407); - - /* clear any lingering errors, so the transaction will run */ - outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); - - /* IDE Device, BDF:0-20-1 */ - printk(BIOS_INFO, "sb700_devices_por_init(): IDE Device, BDF:0-20-1\n"); - dev = pci_locate_device(PCI_ID(0x1002, 0x439C), 0); - /* Disable prefetch */ - byte = pci_read_config8(dev, 0x63); - byte |= 0x1; - pci_write_config8(dev, 0x63, byte); - - /* LPC Device, BDF:0-20-3 */ - printk(BIOS_INFO, "sb700_devices_por_init(): LPC Device, BDF:0-20-3\n"); - dev = pci_locate_device(PCI_ID(0x1002, 0x439D), 0); - /* DMA enable */ - pci_write_config8(dev, 0x40, 0x04); - - /* IO Port Decode Enable */ - pci_write_config8(dev, 0x44, 0xFF); - pci_write_config8(dev, 0x45, 0xFF); - pci_write_config8(dev, 0x46, 0xC3); - pci_write_config8(dev, 0x47, 0xFF); - - /* IO/Mem Port Decode Enable, I don't know why CIM disable some ports. - * Disable LPC TimeOut counter, enable SuperIO Configuration Port (2e/2f), - * Alternate SuperIO Configuration Port (4e/4f), Wide Generic IO Port (64/65). - * Enable bits for LPC ROM memory address range 1&2 for 1M ROM setting.*/ - byte = pci_read_config8(dev, 0x48); - byte |= (1 << 1) | (1 << 0); /* enable Super IO config port 2e-2h, 4e-4f */ - byte |= (1 << 3) | (1 << 4); /* enable for LPC ROM address range1&2, Enable 512KB rom access at 0xFFF80000 - 0xFFFFFFFF */ - byte |= 1 << 6; /* enable for RTC I/O range */ - pci_write_config8(dev, 0x48, byte); - pci_write_config8(dev, 0x49, 0xFF); - /* Enable 0x480-0x4bf, 0x4700-0x470B */ - byte = pci_read_config8(dev, 0x4A); - byte |= ((1 << 1) + (1 << 6)); /*0x42, save the configuraion for port 0x80. */ - pci_write_config8(dev, 0x4A, byte); - - /* Set LPC ROM size, it has been done in sb700_lpc_init(). - * enable LPC ROM range, 0xfff8: 512KB, 0xfff0: 1MB; - * enable LPC ROM range, 0xfff8: 512KB, 0xfff0: 1MB - * pci_write_config16(dev, 0x68, 0x000e) - * pci_write_config16(dev, 0x6c, 0xfff0);*/ - - /* Enable Tpm12_en and Tpm_legacy. I don't know what is its usage and copied from CIM. */ - pci_write_config8(dev, 0x7C, 0x05); - - /* P2P Bridge, BDF:0-20-4, the configuration of the registers in this dev are copied from CIM, - */ - printk(BIOS_INFO, "sb700_devices_por_init(): P2P Bridge, BDF:0-20-4\n"); - dev = pci_locate_device(PCI_ID(0x1002, 0x4384), 0); - - /* Arbiter enable. */ - pci_write_config8(dev, 0x43, 0xff); - - /* Set PCDMA request into hight priority list. */ - /* pci_write_config8(dev, 0x49, 0x1) */ ; - - pci_write_config8(dev, 0x40, 0x26); - - pci_write_config8(dev, 0x0d, 0x40); - pci_write_config8(dev, 0x1b, 0x40); - /* Enable PCIB_DUAL_EN_UP will fix potential problem with PCI cards. */ - pci_write_config8(dev, 0x50, 0x01); - - /* SATA Device, BDF:0-17-0, Non-Raid-5 SATA controller */ - printk(BIOS_INFO, "sb700_devices_por_init(): SATA Device, BDF:0-18-0\n"); - dev = pci_locate_device(PCI_ID(0x1002, 0x4390), 0); - - /*PHY Global Control*/ - pci_write_config16(dev, 0x86, 0x2C00); -} - -/* sbPmioPorInitTable, Pre-initializing PMIO register space -* The power management (PM) block is resident in the PCI/LPC/ISA bridge. -* The PM regs are accessed via IO mapped regs 0xcd6 and 0xcd7. -* The index address is first programmed into IO reg 0xcd6. -* Read or write values are accessed through IO reg 0xcd7. -*/ -static void sb700_pmio_por_init(void) -{ - u8 byte; - - printk(BIOS_INFO, "sb700_pmio_por_init()\n"); - /* K8KbRstEn, KB_RST# control for K8 system. */ - byte = pmio_read(0x66); - byte |= 0x20; - pmio_write(0x66, byte); - - /* RPR2.31 PM_TURN_OFF_MSG during ASF Shutdown. */ - if (get_sb700_revision(pci_locate_device(PCI_ID(0x1002, 0x4385), 0)) <= 0x12) { - byte = pmio_read(0x65); - byte &= ~(1 << 7); - pmio_write(0x65, byte); - - byte = pmio_read(0x75); - byte &= 0xc0; - byte |= 0x05; - pmio_write(0x75, byte); - - byte = pmio_read(0x52); - byte &= 0xc0; - byte |= 0x08; - pmio_write(0x52, byte); - } else { - byte = pmio_read(0xD7); - byte |= 1 << 0; - pmio_write(0xD7, byte); - - byte = pmio_read(0x65); - byte |= 1 << 7; - pmio_write(0x65, byte); - - byte = pmio_read(0x75); - byte &= 0xc0; - byte |= 0x01; - pmio_write(0x75, byte); - - byte = pmio_read(0x52); - byte &= 0xc0; - byte |= 0x02; - pmio_write(0x52, byte); - - } - - /* Watch Dog Timer Control - * Set watchdog time base to 0xfec000f0 to avoid SCSI card boot failure. - * But I don't find WDT is enabled in SMBUS 0x41 bit3 in CIM. - */ - pmio_write(0x6c, 0xf0); - pmio_write(0x6d, 0x00); - pmio_write(0x6e, 0xc0); - pmio_write(0x6f, 0xfe); - - /* rpr2.15: Enabling Spread Spectrum */ - byte = pmio_read(0x42); - byte |= 1 << 7; - pmio_write(0x42, byte); - /* TODO: Check if it is necessary. IDE reset */ - byte = pmio_read(0xB2); - byte |= 1 << 0; - pmio_write(0xB2, byte); -} - -/* -* Add any south bridge setting. -*/ -static void sb700_pci_cfg(void) -{ - device_t dev; - u8 byte; - - /* SMBus Device, BDF:0-20-0 */ - dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); - /* Enable watchdog decode timer */ - byte = pci_read_config8(dev, 0x41); - byte |= (1 << 3); - pci_write_config8(dev, 0x41, byte); - - /* Set to 1 to reset USB on the software (such as IO-64 or IO-CF9 cycles) - * generated PCIRST#. */ - byte = pmio_read(0x65); - byte |= (1 << 4); - pmio_write(0x65, byte); - - /* IDE Device, BDF:0-20-1 */ - dev = pci_locate_device(PCI_ID(0x1002, 0x439C), 0); - /* Enable IDE Explicit prefetch, 0x63[0] clear */ - byte = pci_read_config8(dev, 0x63); - byte &= 0xfe; - pci_write_config8(dev, 0x63, byte); - - /* LPC Device, BDF:0-20-3 */ - /* The code below is ported from old chipset. It is not - * mentioned in RPR. But I keep them. The registers and the - * comments are compatible. */ - dev = pci_locate_device(PCI_ID(0x1002, 0x439D), 0); - /* Enabling LPC DMA function. */ - byte = pci_read_config8(dev, 0x40); - byte |= (1 << 2); - pci_write_config8(dev, 0x40, byte); - /* Disabling LPC TimeOut. 0x48[7] clear. */ - byte = pci_read_config8(dev, 0x48); - byte &= 0x7f; - pci_write_config8(dev, 0x48, byte); - /* Disabling LPC MSI Capability, 0x78[1] clear. */ - byte = pci_read_config8(dev, 0x78); - byte &= 0xfd; - pci_write_config8(dev, 0x78, byte); - - /* SATA Device, BDF:0-17-0, Non-Raid-5 SATA controller */ - dev = pci_locate_device(PCI_ID(0x1002, 0x4390), 0); - /* rpr7.12 SATA MSI and D3 Power State Capability. */ - byte = pci_read_config8(dev, 0x40); - byte |= 1 << 0; - pci_write_config8(dev, 0x40, byte); - if (get_sb700_revision(pci_locate_device(PCI_ID(0x1002, 0x4385), 0)) <= 0x12) - pci_write_config8(dev, 0x34, 0x70); /* set 0x61 to 0x70 if S1 is not supported. */ - else - pci_write_config8(dev, 0x34, 0x50); /* set 0x61 to 0x50 if S1 is not supported. */ - byte &= ~(1 << 0); - pci_write_config8(dev, 0x40, byte); -} - -/* -*/ -static void sb700_por_init(void) -{ - /* sbDevicesPorInitTable + sbK8PorInitTable */ - sb700_devices_por_init(); - - /* sbPmioPorInitTable + sbK8PmioPorInitTable */ - sb700_pmio_por_init(); -} - -/* -* It should be called during early POST after memory detection and BIOS shadowing but before PCI bus enumeration. -*/ -static void sb700_before_pci_init(void) -{ - sb700_pci_cfg(); -} - -/* -* This function should be called after enable_sb700_smbus(). -*/ -static void sb700_early_setup(void) -{ - printk(BIOS_INFO, "sb700_early_setup()\n"); - sb700_por_init(); -} - -static int smbus_read_byte(u32 device, u32 address) -{ - return do_smbus_read_byte(SMBUS_IO_BASE, device, address); -} -#endif diff --git a/src/southbridge/amd/sb700/sb700_enable_usbdebug.c b/src/southbridge/amd/sb700/sb700_enable_usbdebug.c deleted file mode 100644 index d74a9bbc9f..0000000000 --- a/src/southbridge/amd/sb700/sb700_enable_usbdebug.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2010 Advanced Micro Devices, Inc. - * Copyright (C) 2010 Uwe Hermann - * - * 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 -#include -#include -#include -#include -#include "sb700.h" - -#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); -} - -/* - * Note: The SB700 has two EHCI devices, D18:F2 and D19:F2. - * This code currently only supports the first one, i.e., USB Debug devices - * attached to physical USB ports belonging to the first EHCI device. - */ -void sb700_enable_usbdebug(unsigned int port) -{ - device_t dev = PCI_DEV(0, 0x12, 2); /* USB EHCI, D18:F2 */ - - /* Set the EHCI BAR address. */ - pci_write_config32(dev, EHCI_BAR_INDEX, CONFIG_EHCI_BAR); - - /* Enable access to the EHCI memory space registers. */ - pci_write_config8(dev, PCI_COMMAND, PCI_COMMAND_MEMORY); - - /* - * Select the requested physical USB port (1-15) as the Debug Port. - * Must be called after the EHCI BAR has been set up (see above). - */ - set_debug_port(port); -} diff --git a/src/southbridge/amd/sb700/sb700_hda.c b/src/southbridge/amd/sb700/sb700_hda.c deleted file mode 100644 index 417d513e90..0000000000 --- a/src/southbridge/amd/sb700/sb700_hda.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include -#include -#include "sb700.h" - -#define HDA_ICII_REG 0x68 -#define HDA_ICII_BUSY (1 << 0) -#define HDA_ICII_VALID (1 << 1) - -static int set_bits(u32 port, u32 mask, u32 val) -{ - u32 dword; - int count; - - /* Write (val & ~mask) to port */ - val &= mask; - dword = read32(port); - dword &= ~mask; - dword |= val; - write32(port, dword); - - /* Wait for readback of register to - * match what was just written to it - */ - count = 50; - do { - /* Wait 1ms based on BKDG wait time */ - mdelay(1); - dword = read32(port); - dword &= mask; - } while ((dword != val) && --count); - - /* Timeout occured */ - if (!count) - return -1; - return 0; -} - -static u32 codec_detect(u32 base) -{ - u32 dword; - - /* Set Bit0 to 0 to enter reset state (BAR + 0x8)[0] */ - if (set_bits(base + 0x08, 1, 0) == -1) - goto no_codec; - - /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */ - if (set_bits(base + 0x08, 1, 1) == -1) - goto no_codec; - - /* Delay for 1 ms since the BKDG does */ - mdelay(1); - - /* Read in Codec location (BAR + 0xe)[3..0]*/ - dword = read32(base + 0xe); - dword &= 0x0F; - if (!dword) - goto no_codec; - - return dword; - -no_codec: - /* Codec Not found */ - /* Put HDA back in reset (BAR + 0x8) [0] */ - set_bits(base + 0x08, 1, 0); - printk(BIOS_DEBUG, "No codec!\n"); - return 0; -} - -/** - * Wait 50usec for the codec to indicate it is ready - * no response would imply that the codec is non-operative - */ -static int wait_for_ready(u32 base) -{ - /* Use a 50 usec timeout - the Linux kernel uses the - * same duration */ - - int timeout = 50; - - while(timeout--) { - u32 dword=read32(base + HDA_ICII_REG); - if (!(dword & HDA_ICII_BUSY)) - return 0; - udelay(1); - } - - return -1; -} - -/** - * Wait 50usec for the codec to indicate that it accepted - * the previous command. No response would imply that the code - * is non-operative - */ -static int wait_for_valid(u32 base) -{ - /* Use a 50 usec timeout - the Linux kernel uses the - * same duration */ - - int timeout = 50; - while(timeout--) { - u32 dword = read32(base + HDA_ICII_REG); - if ((dword & (HDA_ICII_VALID | HDA_ICII_BUSY)) == - HDA_ICII_VALID) - return 0; - udelay(1); - } - - return 1; -} - -static void codec_init(u32 base, int addr) -{ - u32 dword; - - /* 1 */ - if (wait_for_ready(base) == -1) - return; - - dword = (addr << 28) | 0x000f0000; - write32(base + 0x60, dword); - - if (wait_for_valid(base) == -1) - return; - - dword = read32(base + 0x64); - - /* 2 */ - printk(BIOS_DEBUG, "%x(th) codec viddid: %08x\n", addr, dword); -} - -static void codecs_init(u32 base, u32 codec_mask) -{ - int i; - for (i = 2; i >= 0; i--) { - if (codec_mask & (1 << i)) - codec_init(base, i); - } -} - -static void hda_init(struct device *dev) -{ - u8 byte; - u32 dword; - u32 base; - struct resource *res; - u32 codec_mask; - device_t sm_dev; - - /* Enable azalia - PM_io 0x59[3], no ac97 in sb700. */ - byte = pm_ioread(0x59); - byte |= 1 << 3; - pm_iowrite(0x59, byte); - - /* Find the SMBus */ - /* FIXME: Need to find out why the call below crashes. */ - /*sm_dev = dev_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_ATI_SB700_SM, 0);*/ - sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0)); - - /* Set routing pin - SMBus ExtFunc (0xf8/0xfc) */ - pci_write_config32(sm_dev, 0xf8, 0x00); - pci_write_config8(sm_dev, 0xfc, 0xAA); - /* Set INTA - SMBus 0x63 [2..0] */ - byte = pci_read_config8(sm_dev, 0x63); - byte &= ~0x7; - byte |= 0x0; /* INTA:0x0 - INTH:0x7 */ - pci_write_config8(sm_dev, 0x63, byte); - - /* Program the 2C to 0x437b1002 */ - dword = 0x437b1002; - pci_write_config32(dev, 0x2c, dword); - - /* Read in BAR */ - /* Is this right? HDA allows for a 64-bit BAR - * but this is only setup for a 32-bit one - */ - res = find_resource(dev, 0x10); - if (!res) - return; - - base = (u32)res->base; - printk(BIOS_DEBUG, "base = 0x%x\n", base); - codec_mask = codec_detect(base); - - if (codec_mask) { - printk(BIOS_DEBUG, "codec_mask = %02x\n", codec_mask); - codecs_init(base, codec_mask); - } -} - -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_ATI, - .device = PCI_DEVICE_ID_ATI_SB700_HDA, -}; diff --git a/src/southbridge/amd/sb700/sb700_ide.c b/src/southbridge/amd/sb700/sb700_ide.c deleted file mode 100644 index 4652ca2539..0000000000 --- a/src/southbridge/amd/sb700/sb700_ide.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include "sb700.h" - -static void ide_init(struct device *dev) -{ - struct southbridge_amd_sb700_config *conf; - /* Enable ide devices so the linux ide driver will work */ - u32 dword; - u8 byte; - - conf = dev->chip_info; - - /* RPR9.1 disable MSI */ - /* TODO: For A14, it should set as 1. I doubt it. */ - dword = pci_read_config32(dev, 0x70); - dword &= ~(1 << 16); - pci_write_config32(dev, 0x70, dword); - - /* Enable UDMA on all devices, it will become UDMA0 (default PIO is PIO0) */ - byte = pci_read_config8(dev, 0x54); - byte |= 0xf; - pci_write_config8(dev, 0x54, byte); - - /* Enable I/O Access&& Bus Master */ - dword = pci_read_config16(dev, 0x4); - dword |= 1 << 2; - pci_write_config16(dev, 0x4, dword); - - /* set ide as primary, if you want to boot from IDE, you'd better set it - * in $vendor/$mainboard/devicetree.cb */ - - - if (conf->boot_switch_sata_ide == 1) { - struct device *sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0)); - byte = pci_read_config8(sm_dev, 0xAD); - byte |= 1 << 4; - pci_write_config8(sm_dev, 0xAD, byte); - } - -#if CONFIG_PCI_ROM_RUN == 1 - pci_dev_init(dev); -#endif -} - -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_ATI, - .device = PCI_DEVICE_ID_ATI_SB700_IDE, -}; diff --git a/src/southbridge/amd/sb700/sb700_lpc.c b/src/southbridge/amd/sb700/sb700_lpc.c deleted file mode 100644 index a3a50c6c9b..0000000000 --- a/src/southbridge/amd/sb700/sb700_lpc.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sb700.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 */ -#if CONFIG_SOUTHBRIDGE_AMD_SB700_SKIP_ISA_DMA_INIT - printk(BIOS_DEBUG, "Skipping isa_dma_init() to avoid getting stuck.\n"); -#else - isa_dma_init(); -#endif - - /* 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); - pci_write_config8(dev, 0x78, byte); -} - -static void sb700_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 = IO_APIC_ADDR; - res->size = 0x00001000; - res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; - - compact_resources(dev); -} - -static void sb700_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 whose children's resources are to be enabled - * - */ -static void sb700_lpc_enable_childrens_resources(device_t dev) -{ - struct bus *link; - u32 reg, reg_x; - int var_num = 0; - u16 reg_var[3]; - - reg = pci_read_config32(dev, 0x44); - reg_x = pci_read_config32(dev, 0x48); - - for (link = dev->link_list; link; link = link->next) { - device_t child; - for (child = link->children; child; - child = child->sibling) { - if (child->enabled - && (child->path.type == DEVICE_PATH_PNP)) { - struct resource *res; - for (res = child->resource_list; res; res = res->next) { - u32 base, end; /* don't need long long */ - if (!(res->flags & IORESOURCE_IO)) - continue; - base = res->base; - end = resource_end(res); - printk(BIOS_DEBUG, "sb700 lpc decode:%s, base=0x%08x, end=0x%08x\n", - dev_path(child), base, end); - switch (base) { - case 0x60: /* KB */ - case 0x64: /* MS */ - reg |= (1 << 29); - break; - case 0x3f8: /* COM1 */ - reg |= (1 << 6); - break; - case 0x2f8: /* COM2 */ - reg |= (1 << 7); - break; - case 0x378: /* Parallal 1 */ - reg |= (1 << 0); - break; - case 0x3f0: /* FD0 */ - reg |= (1 << 26); - break; - case 0x220: /* Aduio 0 */ - reg |= (1 << 8); - break; - case 0x300: /* Midi 0 */ - reg |= (1 << 18); - break; - case 0x400: - reg_x |= (1 << 16); - break; - case 0x480: - reg_x |= (1 << 17); - break; - case 0x500: - reg_x |= (1 << 18); - break; - case 0x580: - reg_x |= (1 << 19); - break; - case 0x4700: - reg_x |= (1 << 22); - break; - case 0xfd60: - reg_x |= (1 << 23); - break; - default: - if (var_num >= 3) - continue; /* only 3 var ; compact them ? */ - switch (var_num) { - case 0: - reg_x |= (1 << 2); - break; - case 1: - reg_x |= (1 << 24); - break; - case 2: - reg_x |= (1 << 25); - break; - } - reg_var[var_num++] = - base & 0xffff; - } - } - } - } - } - pci_write_config32(dev, 0x44, reg); - pci_write_config32(dev, 0x48, reg_x); - /* Set WideIO for as many IOs found (fall through is on purpose) */ - switch (var_num) { - case 2: - pci_write_config16(dev, 0x90, reg_var[2]); - case 1: - pci_write_config16(dev, 0x66, reg_var[1]); - case 0: - pci_write_config16(dev, 0x64, reg_var[0]); - break; - } -} - -static void sb700_lpc_enable_resources(device_t dev) -{ - pci_dev_enable_resources(dev); - sb700_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 = sb700_lpc_read_resources, - .set_resources = sb700_lpc_set_resources, - .enable_resources = sb700_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_ATI, - .device = PCI_DEVICE_ID_ATI_SB700_LPC, -}; diff --git a/src/southbridge/amd/sb700/sb700_pci.c b/src/southbridge/amd/sb700/sb700_pci.c deleted file mode 100644 index d1e9851b9d..0000000000 --- a/src/southbridge/amd/sb700/sb700_pci.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include "sb700.h" - -static void pci_init(struct device *dev) -{ - u32 dword; - u16 word; - u8 byte; - - /* RPR 5.1 Enables the PCI-bridge subtractive decode */ - /* This setting is strongly recommended since it supports some legacy PCI add-on cards,such as BIOS debug cards */ - byte = pci_read_config8(dev, 0x4B); - byte |= 1 << 7; - pci_write_config8(dev, 0x4B, byte); - byte = pci_read_config8(dev, 0x40); - byte |= 1 << 5; - pci_write_config8(dev, 0x40, byte); - - /* RPR5.2 PCI-bridge upstream dual address window */ - /* this setting is applicable if the system memory is more than 4GB,and the PCI device can support dual address access */ - byte = pci_read_config8(dev, 0x50); - byte |= 1 << 0; - pci_write_config8(dev, 0x50, byte); - - /* RPR 5.3 PCI bus 64-byte DMA read access */ - /* Enhance the PCI bus DMA performance */ - byte = pci_read_config8(dev, 0x4B); - byte |= 1 << 4; - pci_write_config8(dev, 0x4B, byte); - - /* RPR 5.4 Enables the PCIB writes to be cacheline aligned. */ - /* The size of the writes will be set in the Cacheline Register */ - byte = pci_read_config8(dev, 0x40); - byte |= 1 << 1; - pci_write_config8(dev, 0x40, byte); - - /* RPR 5.5 Enables the PCIB to retain ownership of the bus on the Primary side and on the Secondary side when GNT# is deasserted */ - pci_write_config8(dev, 0x0D, 0x40); - pci_write_config8(dev, 0x1B, 0x40); - - /* RPR 5.6 Enable the command matching checking function on "Memory Read" & "Memory Read Line" commands */ - byte = pci_read_config8(dev, 0x4B); - byte |= 1 << 6; - pci_write_config8(dev, 0x4B, byte); - - /* RPR 5.7 When enabled, the PCI arbiter checks for the Bus Idle before asserting GNT# */ - byte = pci_read_config8(dev, 0x4B); - byte |= 1 << 0; - pci_write_config8(dev, 0x4B, byte); - - /* RPR 5.8 Adjusts the GNT# de-assertion time */ - word = pci_read_config16(dev, 0x64); - word |= 1 << 12; - pci_write_config16(dev, 0x64, word); - - /* RPR 5.9 Fast Back to Back transactions support */ - byte = pci_read_config8(dev, 0x48); - byte |= 1 << 2; - /* pci_write_config8(dev, 0x48, byte); */ - - /* RPR 5.10 Enable Lock Operation */ - /* byte = pci_read_config8(dev, 0x48); */ - byte |= 1 << 3; - pci_write_config8(dev, 0x48, byte); - - /* RPR 5.11 Enable additional optional PCI clock */ - word = pci_read_config16(dev, 0x64); - word |= 1 << 8; - pci_write_config16(dev, 0x64, word); - - /* RPR 5.12 Enable One-Prefetch-Channel Mode */ - dword = pci_read_config32(dev, 0x64); - dword |= 1 << 20; - pci_write_config32(dev, 0x64, dword); - - /* RPR 5.13 Disable PCIB MSI Capability */ - byte = pci_read_config8(dev, 0x40); - byte &= ~(1 << 3); - pci_write_config8(dev, 0x40, byte); - - /* rpr5.14 Adjusting CLKRUN# */ - dword = pci_read_config32(dev, 0x64); - dword |= (1 << 15); - pci_write_config32(dev, 0x64, dword); -} - -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_ATI, - .device = PCI_DEVICE_ID_ATI_SB700_PCI, -}; diff --git a/src/southbridge/amd/sb700/sb700_reset.c b/src/southbridge/amd/sb700/sb700_reset.c deleted file mode 100644 index 32ee66b4b5..0000000000 --- a/src/southbridge/amd/sb700/sb700_reset.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 -#include -#include - -#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/sb700/sb700_sata.c b/src/southbridge/amd/sb700/sb700_sata.c deleted file mode 100644 index 08b9aa8ad9..0000000000 --- a/src/southbridge/amd/sb700/sb700_sata.c +++ /dev/null @@ -1,294 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include -#include -#include "sb700.h" - -static int sata_drive_detect(int portnum, u16 iobar) -{ - u8 byte, byte2; - int i = 0; - outb(0xA0 + 0x10 * (portnum % 2), iobar + 0x6); - while (byte = inb(iobar + 0x6), byte2 = inb(iobar + 0x7), - (byte != (0xA0 + 0x10 * (portnum % 2))) || - ((byte2 & 0x88) != 0)) { - printk(BIOS_SPEW, "0x6=%x, 0x7=%x\n", byte, byte2); - if (byte != (0xA0 + 0x10 * (portnum % 2))) { - /* This will happen at the first iteration of this loop - * if the first SATA port is unpopulated and the - * second SATA port is poulated. - */ - printk(BIOS_DEBUG, "drive no longer selected after %i ms, " - "retrying init\n", i * 10); - return 1; - } else - printk(BIOS_SPEW, "drive detection not yet completed, " - "waiting...\n"); - mdelay(10); - i++; - } - printk(BIOS_SPEW, "drive detection done after %i ms\n", i * 10); - return 0; -} - - /* This function can be overloaded in mainboard.c */ - -void __attribute__((weak)) sb700_setup_sata_phys(struct device *dev) { - /* RPR7.6.1 Program the PHY Global Control to 0x2C00 */ - pci_write_config16(dev, 0x86, 0x2c00); - - /* RPR7.6.2 SATA GENI PHY ports setting */ - pci_write_config32(dev, 0x88, 0x01B48017); - pci_write_config32(dev, 0x8c, 0x01B48019); - pci_write_config32(dev, 0x90, 0x01B48016); - pci_write_config32(dev, 0x94, 0x01B48016); - pci_write_config32(dev, 0x98, 0x01B48016); - pci_write_config32(dev, 0x9C, 0x01B48016); - - /* RPR7.6.3 SATA GEN II PHY port setting for port [0~5]. */ - pci_write_config16(dev, 0xA0, 0xA09A); - pci_write_config16(dev, 0xA2, 0xA09F); - pci_write_config16(dev, 0xA4, 0xA07A); - pci_write_config16(dev, 0xA6, 0xA07A); - pci_write_config16(dev, 0xA8, 0xA07A); - pci_write_config16(dev, 0xAA, 0xA07A); -} - -static void sata_init(struct device *dev) -{ - u8 byte; - u16 word; - u32 dword; - u8 rev_id; - u32 sata_bar5; - u16 sata_bar0, sata_bar1, sata_bar2, sata_bar3, sata_bar4; - int i, j; - - struct southbridge_ati_sb700_config *conf; - conf = dev->chip_info; - - device_t sm_dev; - /* SATA SMBus Disable */ - /* sm_dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); */ - sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0)); - /* Disable SATA SMBUS */ - byte = pci_read_config8(sm_dev, 0xad); - byte |= (1 << 1); - /* Enable SATA and power saving */ - byte = pci_read_config8(sm_dev, 0xad); - byte |= (1 << 0); - byte |= (1 << 5); - pci_write_config8(sm_dev, 0xad, byte); - - /* RPR 7.2 SATA Initialization */ - /* Set the interrupt Mapping to INTG# */ - byte = pci_read_config8(sm_dev, 0xaf); - byte = 0x6 << 2; - pci_write_config8(sm_dev, 0xaf, byte); - - /* get rev_id */ - rev_id = pci_read_config8(sm_dev, 0x08) - 0x28; - - /* get base address */ - sata_bar5 = pci_read_config32(dev, 0x24) & ~0x3FF; - sata_bar0 = pci_read_config16(dev, 0x10) & ~0x7; - sata_bar1 = pci_read_config16(dev, 0x14) & ~0x3; - sata_bar2 = pci_read_config16(dev, 0x18) & ~0x7; - sata_bar3 = pci_read_config16(dev, 0x1C) & ~0x3; - sata_bar4 = pci_read_config16(dev, 0x20) & ~0xf; - - printk(BIOS_SPEW, "sata_bar0=%x\n", sata_bar0); /* 3030 */ - printk(BIOS_SPEW, "sata_bar1=%x\n", sata_bar1); /* 3070 */ - printk(BIOS_SPEW, "sata_bar2=%x\n", sata_bar2); /* 3040 */ - printk(BIOS_SPEW, "sata_bar3=%x\n", sata_bar3); /* 3080 */ - printk(BIOS_SPEW, "sata_bar4=%x\n", sata_bar4); /* 3000 */ - printk(BIOS_SPEW, "sata_bar5=%x\n", sata_bar5); /* e0309000 */ - - /* disable combined mode */ - byte = pci_read_config8(sm_dev, 0xAD); - byte &= ~(1 << 3); - pci_write_config8(sm_dev, 0xAD, byte); - /* Program the 2C to 0x43801002 */ - dword = 0x43801002; - pci_write_config32(dev, 0x2c, dword); - - /* SERR-Enable */ - word = pci_read_config16(dev, 0x04); - word |= (1 << 8); - pci_write_config16(dev, 0x04, word); - - /* Dynamic power saving */ - byte = pci_read_config8(dev, 0x40); - byte |= (1 << 2); - pci_write_config8(dev, 0x40, byte); - - /* Set SATA Operation Mode, Set to IDE mode */ - byte = pci_read_config8(dev, 0x40); - byte |= (1 << 0); - byte |= (1 << 4); - pci_write_config8(dev, 0x40, byte); - - dword = 0x01018f00; - pci_write_config32(dev, 0x8, dword); - - byte = pci_read_config8(dev, 0x40); - byte &= ~(1 << 0); - pci_write_config8(dev, 0x40, byte); - - /* Enable the SATA watchdog counter */ - byte = pci_read_config8(dev, 0x44); - byte |= (1 << 0); - pci_write_config8(dev, 0x44, byte); - - /* Set bit 29 and 24 for A12 */ - dword = pci_read_config32(dev, 0x40); - if (rev_id < 0x14) /* before A12 */ - dword |= (1 << 29); - else - dword &= ~(1 << 29); /* A14 and above */ - pci_write_config32(dev, 0x40, dword); - - /* set bit 21 for A12 */ - dword = pci_read_config32(dev, 0x48); - if (rev_id < 0x14) /* before A12 */ - dword |= 1 << 24 | 1 << 21; - else { - dword &= ~(1 << 24 | 1 << 21); /* A14 and above */ - dword &= ~0xFF80; /* 15:7 */ - dword |= 1 << 15 | 0x7F << 7; - } - pci_write_config32(dev, 0x48, dword); - - /* Program the watchdog counter to 0x10 */ - byte = 0x10; - pci_write_config8(dev, 0x46, byte); - sb700_setup_sata_phys(dev); - /* Enable the I/O, MM, BusMaster access for SATA */ - byte = pci_read_config8(dev, 0x4); - byte |= 7 << 0; - pci_write_config8(dev, 0x4, byte); - - /* RPR7.7 SATA drive detection. */ - /* Use BAR5+0x128,BAR0 for Primary Slave */ - /* Use BAR5+0x1A8,BAR0 for Primary Slave */ - /* Use BAR5+0x228,BAR2 for Secondary Master */ - /* Use BAR5+0x2A8,BAR2 for Secondary Slave */ - /* Use BAR5+0x328,PATA_BAR0/2 for Primary/Secondary master emulation */ - /* Use BAR5+0x3A8,PATA_BAR0/2 for Primary/Secondary Slave emulation */ - - /* TODO: port 4,5, which are PATA emulations. What are PATA_BARs? */ - - for (i = 0; i < 4; i++) { - byte = read8(sata_bar5 + 0x128 + 0x80 * i); - printk(BIOS_SPEW, "SATA port %i status = %x\n", i, byte); - byte &= 0xF; - if( byte == 0x1 ) { - /* If the drive status is 0x1 then we see it but we aren't talking to it. */ - /* Try to do something about it. */ - printk(BIOS_SPEW, "SATA device detected but not talking. Trying lower speed.\n"); - - /* Read in Port-N Serial ATA Control Register */ - byte = read8(sata_bar5 + 0x12C + 0x80 * i); - - /* Set Reset Bit and 1.5g bit */ - byte |= 0x11; - write8((sata_bar5 + 0x12C + 0x80 * i), byte); - - /* Wait 1ms */ - mdelay(1); - - /* Clear Reset Bit */ - byte &= ~0x01; - write8((sata_bar5 + 0x12C + 0x80 * i), byte); - - /* Wait 1ms */ - mdelay(1); - - /* Reread status */ - byte = read8(sata_bar5 + 0x128 + 0x80 * i); - printk(BIOS_SPEW, "SATA port %i status = %x\n", i, byte); - byte &= 0xF; - } - - if (byte == 0x3) { - for (j = 0; j < 10; j++) { - if (!sata_drive_detect(i, ((i / 2) == 0) ? sata_bar0 : sata_bar2)) - break; - } - printk(BIOS_DEBUG, "%s %s device is %sready after %i tries\n", - (i / 2) ? "Secondary" : "Primary", - (i % 2 ) ? "Slave" : "Master", - (j == 10) ? "not " : "", - (j == 10) ? j : j + 1); - } else { - printk(BIOS_DEBUG, "No %s %s SATA drive on Slot%i\n", - (i / 2) ? "Secondary" : "Primary", - (i % 2 ) ? "Slave" : "Master", i); - } - } - - /* Below is CIM InitSataLateFar */ - /* Enable interrupts from the HBA */ - byte = read8(sata_bar5 + 0x4); - byte |= 1 << 1; - write8((sata_bar5 + 0x4), byte); - - /* Clear error status */ - write32((sata_bar5 + 0x130), 0xFFFFFFFF); - write32((sata_bar5 + 0x1b0), 0xFFFFFFFF); - write32((sata_bar5 + 0x230), 0xFFFFFFFF); - write32((sata_bar5 + 0x2b0), 0xFFFFFFFF); - write32((sata_bar5 + 0x330), 0xFFFFFFFF); - write32((sata_bar5 + 0x3b0), 0xFFFFFFFF); - - /* Clear SATA status,Firstly we get the AcpiGpe0BlkAddr */ - /* ????? why CIM does not set the AcpiGpe0BlkAddr , but use it??? */ - - /* word = 0x0000; */ - /* word = pm_ioread(0x28); */ - /* byte = pm_ioread(0x29); */ - /* word |= byte<<8; */ - /* printk(BIOS_DEBUG, "AcpiGpe0Blk addr = %x\n", word); */ - /* write32(word, 0x80000000); */ -} - -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_ATI, - .device = PCI_DEVICE_ID_ATI_SB700_SATA, -}; diff --git a/src/southbridge/amd/sb700/sb700_sm.c b/src/southbridge/amd/sb700/sb700_sm.c deleted file mode 100644 index e700c0b5f3..0000000000 --- a/src/southbridge/amd/sb700/sb700_sm.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sb700.h" -#include "sb700_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 - -/* -* SB700 enables all USB controllers by default in SMBUS Control. -* SB700 enables SATA by default in SMBUS Control. -*/ -static void sm_init(device_t dev) -{ - u8 byte; - u8 byte_old; - u32 dword; - u32 ioapic_base; - u32 on; - u32 nmi_option; - - printk(BIOS_INFO, "sm_init().\n"); - - ioapic_base = pci_read_config32(dev, 0x74) & (0xffffffe0); /* some like mem resource, but does not have enable bit */ - /* Don't rename APIC ID */ - /* TODO: We should call setup_ioapic() here. But kernel hangs if cpu is K8. - * We need to check out why and change back. */ - clear_ioapic(ioapic_base); - - /* 2.10 Interrupt Routing/Filtering */ - dword = pci_read_config8(dev, 0x62); - dword |= 3; - pci_write_config8(dev, 0x62, dword); - - /* Delay back to back interrupts to the CPU. */ - dword = pci_read_config16(dev, 0x64); - dword |= 1 << 13; - pci_write_config16(dev, 0x64, dword); - - /* rrg:K8 INTR Enable (BIOS should set this bit after PIC initialization) */ - /* rpr 2.1 Enabling Legacy Interrupt */ - dword = pci_read_config8(dev, 0x62); - dword |= 1 << 2; - pci_write_config8(dev, 0x62, dword); - - dword = pci_read_config32(dev, 0x78); - dword |= 1 << 9; - pci_write_config32(dev, 0x78, dword); /* enable 0xCD6 0xCD7 */ - - /* bit 10: MultiMediaTimerIrqEn */ - dword = pci_read_config8(dev, 0x64); - dword |= 1 << 10; - pci_write_config8(dev, 0x64, dword); - /* enable serial irq */ - byte = pci_read_config8(dev, 0x69); - byte |= 1 << 7; /* enable serial irq function */ - byte &= ~(0xF << 2); - byte |= 4 << 2; /* set NumSerIrqBits=4 */ - pci_write_config8(dev, 0x69, byte); - - /* IRQ0From8254 */ - byte = pci_read_config8(dev, 0x41); - byte &= ~(1 << 7); - pci_write_config8(dev, 0x41, byte); - - byte = pm_ioread(0x61); - byte |= 1 << 1; /* Set to enable NB/SB handshake during IOAPIC interrupt for AMD K8/K7 */ - pm_iowrite(0x61, byte); - - /* disable SMI */ - byte = pm_ioread(0x53); - byte |= 1 << 3; - pm_iowrite(0x53, byte); - - /* power after power fail */ - on = CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL; - get_option(&on, "power_on_after_fail"); - byte = pm_ioread(0x74); - byte &= ~0x03; - if (on) { - byte |= 2; - } - byte |= 1 << 2; - pm_iowrite(0x74, byte); - printk(BIOS_INFO, "set power %s after power fail\n", on ? "on" : "off"); - - byte = pm_ioread(0x68); - byte &= ~(1 << 1); - /* 2.7 */ - byte |= 1 << 2; - pm_iowrite(0x68, byte); - - /* 2.7 */ - byte = pm_ioread(0x65); - byte &= ~(1 << 7); - pm_iowrite(0x65, byte); - - /* 2.16 */ - byte = pm_ioread(0x55); - byte |= 1 << 5; - pm_iowrite(0x55, byte); - - byte = pm_ioread(0xD7); - byte |= 1 << 6 | 1 << 1;; - pm_iowrite(0xD7, byte); - - /* 2.15 */ - byte = pm_ioread(0x42); - byte &= ~(1 << 2); - pm_iowrite(0x42, byte); - - /* Set up NMI on errors */ - byte = inb(0x70); /* RTC70 */ - byte_old = byte; - nmi_option = NMI_OFF; - get_option(&nmi_option, "nmi"); - if (nmi_option) { - byte &= ~(1 << 7); /* set NMI */ - printk(BIOS_INFO, "++++++++++set NMI+++++\n"); - } else { - byte |= (1 << 7); /* Can not mask NMI from PCI-E and NMI_NOW */ - printk(BIOS_INFO, "++++++++++no set NMI+++++\n"); - } - byte &= ~(1 << 7); - if (byte != byte_old) { - outb(byte, 0x70); - } - - /* 2.11 IO Trap Settings */ - abcfg_reg(0x10090, 1 << 16, 1 << 16); - - /* ab index */ - pci_write_config32(dev, 0xF0, AB_INDX); - /* Initialize the real time clock */ - rtc_init(0); - - /* 4.3 Enabling Upstream DMA Access */ - axcfg_reg(0x04, 1 << 2, 1 << 2); - /* 4.4 Enabling IDE/PCIB Prefetch for Performance Enhancement */ - abcfg_reg(0x10060, 9 << 17, 9 << 17); - abcfg_reg(0x10064, 9 << 17, 9 << 17); - - /* 4.5 Enabling OHCI Prefetch for Performance Enhancement, A12 */ - abcfg_reg(0x80, 1 << 0, 1<< 0); - - /* 4.6 B-Link Client's Credit Variable Settings for the Downstream Arbitration Equation */ - /* 4.7 Enabling Additional Address Bits Checking in Downstream */ - /* 4.15 IO write and SMI ordering enhancement*/ - abcfg_reg(0x9c, 3 << 0 | 1 << 8, 3 << 0 | 1 << 8); - - /* 4.8 Set B-Link Prefetch Mode */ - abcfg_reg(0x80, 3 << 17, 3 << 17); - - /* 4.9 Enabling Detection of Upstream Interrupts */ - abcfg_reg(0x94, 1 << 20 | 0x7FFFF, 1 << 20 | 0x00FEE); - - /* 4.10: Enabling Downstream Posted Transactions to Pass Non-Posted - * Transactions for the K8 Platform (for All Revisions) */ - abcfg_reg(0x10090, 1 << 8, 1 << 8); - - /* 4.11:Programming Cycle Delay for AB and BIF Clock Gating */ - /* 4.12: Enabling AB and BIF Clock Gating */ - abcfg_reg(0x10054, 0xFFFF0000, 0x1040000); - abcfg_reg(0x54, 0xFF << 16, 4 << 16); - abcfg_reg(0x54, 1 << 24, 0 << 24); - abcfg_reg(0x98, 0x0000FF00, 0x00004700); - - /* 4.13:Enabling AB Int_Arbiter Enhancement (for All Revisions) */ - abcfg_reg(0x10054, 0x0000FFFF, 0x07FF); - - /* 4.14:Enabling Requester ID for upstream traffic. */ - abcfg_reg(0x98, 1 << 16, 1 << 16); - - /* 9.2: Enabling IDE Data Bus DD7 Pull Down Resistor */ - byte = pm2_ioread(0xE5); - byte |= 1 << 2; - pm2_iowrite(0xE5, byte); - - /* Enable IDE controller. */ - byte = pm_ioread(0x59); - byte &= ~(1 << 1); - pm_iowrite(0x59, byte); - - printk(BIOS_INFO, "sm_init() end\n"); - - /* Enable NbSb virtual channel */ - axcfg_reg(0x114, 0x3f << 1, 0 << 1); - axcfg_reg(0x120, 0x7f << 1, 0x7f << 1); - axcfg_reg(0x120, 7 << 24, 1 << 24); - axcfg_reg(0x120, 1 << 31, 1 << 31); - abcfg_reg(0x50, 1 << 3, 1 << 3); -} - -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 sb700_sm_read_resources(device_t dev) -{ - struct resource *res; - u8 byte; - - /* rpr2.14: Hides SM bus controller Bar1 where stores HPET MMIO base address */ - byte = pm_ioread(0x55); - byte |= 1 << 7; - pm_iowrite(0x55, byte); - - /* Get the normal pci resources of this device */ - /* pci_dev_read_resources(dev); */ - - byte = pm_ioread(0x55); - byte &= ~(1 << 7); - pm_iowrite(0x55, byte); - - /* apic */ - res = new_resource(dev, 0x74); - res->base = IO_APIC_ADDR; - res->size = 256 * 0x10; - res->limit = 0xFFFFFFFFUL; /* res->base + res->size -1; */ - res->align = 8; - res->gran = 8; - res->flags = IORESOURCE_MEM | IORESOURCE_FIXED; - - #if 0 /* Linux ACPI crashes when it is 1. For late debugging. */ - res = new_resource(dev, 0x14); /* TODO: hpet */ - res->base = 0xfed00000; /* reset hpet to widely accepted address */ - res->size = 0x400; - res->limit = 0xFFFFFFFFUL; /* res->base + res->size -1; */ - res->align = 8; - res->gran = 8; - res->flags = IORESOURCE_MEM | IORESOURCE_FIXED; - #endif - /* dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; */ - - /* smbus */ - res = new_resource(dev, 0x90); - res->base = 0xB00; - res->size = 0x10; - res->limit = 0xFFFFUL; /* res->base + res->size -1; */ - res->align = 8; - res->gran = 8; - res->flags = IORESOURCE_IO | IORESOURCE_FIXED; - - compact_resources(dev); -} - -static void sb700_sm_set_resources(struct device *dev) -{ - struct resource *res; - u8 byte; - - pci_dev_set_resources(dev); - - /* rpr2.14: Make HPET MMIO decoding controlled by the memory enable bit in command register of LPC ISA bridge */ - byte = pm_ioread(0x52); - byte |= 1 << 6; - pm_iowrite(0x52, byte); - - res = find_resource(dev, 0x74); - pci_write_config32(dev, 0x74, res->base | 1 << 3); -#if 0 /* TODO:hpet */ - res = find_resource(dev, 0x14); - pci_write_config32(dev, 0x14, res->base); -#endif - res = find_resource(dev, 0x90); - pci_write_config32(dev, 0x90, res->base | 1); -} - -static struct pci_operations lops_pci = { - .set_subsystem = pci_dev_set_subsystem, -}; - -static struct device_operations smbus_ops = { - .read_resources = sb700_sm_read_resources, - .set_resources = sb700_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_ATI, - .device = PCI_DEVICE_ID_ATI_SB700_SM, -}; diff --git a/src/southbridge/amd/sb700/sb700_smbus.c b/src/southbridge/amd/sb700/sb700_smbus.c deleted file mode 100644 index ee1653df3e..0000000000 --- a/src/southbridge/amd/sb700/sb700_smbus.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * 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 _SB700_SMBUS_C_ -#define _SB700_SMBUS_C_ - -#include "sb700_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; -} - -static void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val) -{ - u32 tmp; - - outl((reg_space & 0x3) << 30 | 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.*/ - reg_addr & 0x10000 ? outl(0, AB_INDX) : NULL; - - tmp &= ~mask; - tmp |= val; - - /* printk(BIOS_DEBUG, "about write %x, index=%x", tmp, (reg_space&0x3)<<30 | reg_addr); */ - outl((reg_space & 0x3) << 30 | reg_addr, AB_INDX); /* probably we dont have to do it again. */ - outl(tmp, AB_DATA); - reg_addr & 0x10000 ? outl(0, AB_INDX) : NULL; -} - -/* space = 0: AX_INDXC, AX_DATAC - * space = 1: AX_INDXP, AX_DATAP - */ -static inline void alink_ax_indx(u32 space /*c or p? */ , u32 axindc, - u32 mask, u32 val) -{ - u32 tmp; - - /* read axindc to tmp */ - outl(space << 30 | space << 3 | 0x30, AB_INDX); - outl(axindc, AB_DATA); - outl(space << 30 | space << 3 | 0x34, AB_INDX); - tmp = inl(AB_DATA); - - tmp &= ~mask; - tmp |= val; - - /* write tmp */ - outl(space << 30 | space << 3 | 0x30, AB_INDX); - outl(axindc, AB_DATA); - outl(space << 30 | space << 3 | 0x34, AB_INDX); - outl(tmp, AB_DATA); -} -#endif diff --git a/src/southbridge/amd/sb700/sb700_smbus.h b/src/southbridge/amd/sb700/sb700_smbus.h deleted file mode 100644 index c21a1dc0a2..0000000000 --- a/src/southbridge/amd/sb700/sb700_smbus.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 SB700_SMBUS_H -#define SB700_SMBUS_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 1 -#define AXCFG 2 -#define ABCFG 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(0, (reg), (mask), (val)) -#define axindxp_reg(reg, mask, val) \ - alink_ax_indx(1, (reg), (mask), (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); -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); - - -#endif diff --git a/src/southbridge/amd/sb700/sb700_usb.c b/src/southbridge/amd/sb700/sb700_usb.c deleted file mode 100644 index 3b3ad584a7..0000000000 --- a/src/southbridge/amd/sb700/sb700_usb.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include -#include -#include "sb700.h" - -static struct pci_operations lops_pci = { - .set_subsystem = pci_dev_set_subsystem, -}; - -static void usb_init(struct device *dev) -{ - u8 byte; - u16 word; - - /* 6.1 Enable OHCI0-4 and EHCI Controllers */ - device_t sm_dev; - sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0)); - byte = pci_read_config8(sm_dev, 0x68); - byte |= 0xFF; - pci_write_config8(sm_dev, 0x68, byte); - - /* RPR 6.2 Enables the USB PME Event,Enable USB resume support */ - byte = pm_ioread(0x61); - byte |= 1 << 6; - pm_iowrite(0x61, byte); - byte = pm_ioread(0x65); - byte |= 1 << 2; - pm_iowrite(0x65, byte); - - /* RPR 6.3 Support USB device wakeup from the S4/S5 state */ - byte = pm_ioread(0x65); - byte &= ~(1 << 0); - pm_iowrite(0x65, byte); - - /* RPR 6.5 Enable the USB controller to get reset by any software that generate a PCIRst# condition */ - byte = pm_ioread(0x65); - byte |= (1 << 4); - pm_iowrite(0x65, byte); - - /* RPR 6.10 Disable OHCI MSI Capability. */ - word = pci_read_config16(dev, 0x40); - word |= (0x3 << 8); - pci_write_config16(dev, 0x40, word); -} - -static void usb_init2(struct device *dev) -{ - u32 dword; - u32 usb2_bar0; - device_t sm_dev; - u8 rev; - - sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0)); - rev = get_sb700_revision(sm_dev); - - /* dword = pci_read_config32(dev, 0xf8); */ - /* dword |= 40; */ - /* pci_write_config32(dev, 0xf8, dword); */ - - usb2_bar0 = pci_read_config32(dev, 0x10) & ~0xFF; - printk(BIOS_INFO, "usb2_bar0=0x%x\n", usb2_bar0); - - /* RPR6.4 Enables the USB PHY auto calibration resister to match 45ohm resistance */ - dword = 0x00020F00; - write32(usb2_bar0 + 0xC0, dword); - - /* RPR6.9 Sets In/OUT FIFO threshold for best performance */ - dword = 0x00400040; - write32(usb2_bar0 + 0xA4, dword); - - /* RPR6.11 Disabling EHCI Advance Asynchronous Enhancement */ - dword = pci_read_config32(dev, 0x50); - dword |= (1 << 28); - pci_write_config32(dev, 0x50, dword); - - /* RPR 6.12 EHCI Advance PHY Power Savings */ - /* RPR says it is just for A12. CIMM sets it when it is above A11. */ - /* But it makes the linux crash, so we skip it */ - #if 0 - dword = pci_read_config32(dev, 0x50); - dword |= 1 << 31; - pci_write_config32(dev, 0x50, dword); - #endif - - /* RPR6.13 Enabling Fix for EHCI Controller Driver Yellow Sign Issue */ - /* RPR says it is just for A12. CIMx sets it when it is above A11. */ - dword = pci_read_config32(dev, 0x50); - dword |= (1 << 20); - pci_write_config32(dev, 0x50, dword); - - /* RPR6.15 EHCI Async Park Mode */ - dword = pci_read_config32(dev, 0x50); - dword |= (1 << 23); - pci_write_config32(dev, 0x50, dword); - - /* Each step below causes the linux crashes. Leave them here - * for future debugging. */ -#if 0 - u8 byte; - u16 word; - - /* RPR6.16 Disable EHCI MSI support */ - byte = pci_read_config8(dev, 0x50); - byte |= (1 << 6); - pci_write_config8(dev, 0x50, byte); - - /* RPR6.17 Disable the EHCI Dynamic Power Saving feature */ - word = read32(usb2_bar0 + 0xBC); - word &= ~(1 << 12); - write16(usb2_bar0 + 0xBC, word); - - /* RPR6.19 USB Controller DMA Read Delay Tolerant. */ - if (rev >= REV_SB700_A14) { - byte = pci_read_config8(dev, 0x50); - byte |= (1 << 7); - pci_write_config8(dev, 0x50, byte); - } - - /* RPR6.20 Async Park Mode. */ - /* RPR recommends not to set these bits. */ - #if 0 - dword = pci_read_config32(dev, 0x50); - dword |= 1 << 23; - if (rev >= REV_SB700_A14) { - dword &= ~(1 << 2); - } - pci_write_config32(dev, 0x50, dword); - #endif - - /* RPR6.22 Advance Async Enhancement */ - /* RPR6.23 USB Periodic Cache Setting */ - dword = pci_read_config32(dev, 0x50); - if (rev == REV_SB700_A12) { - dword |= 1 << 28; /* 6.22 */ - dword |= 1 << 27; /* 6.23 */ - } else if (rev >= REV_SB700_A14) { - dword |= 1 << 3; - dword &= ~(1 << 28); /* 6.22 */ - dword |= 1 << 8; - dword &= ~(1 << 27); /* 6.23 */ - } - printk(BIOS_DEBUG, "rpr 6.23, final dword=%x\n", dword); -#endif -} - -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_ATI, - .device = PCI_DEVICE_ID_ATI_SB700_USB_18_0, -}; - -static const struct pci_driver usb_1_driver __pci_driver = { - .ops = &usb_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_SB700_USB_18_1, -}; - -/* 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_ATI, - * .device = PCI_DEVICE_ID_ATI_SB700_USB_19_0, - * }; - * static const struct pci_driver usb_4_driver __pci_driver = { - * .ops = &usb_ops, - * .vendor = PCI_VENDOR_ID_ATI, - * .device = PCI_DEVICE_ID_ATI_SB700_USB_19_1, - * }; - */ - -static const struct pci_driver usb_4_driver __pci_driver = { - .ops = &usb_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_SB700_USB_20_5, -}; - -static struct device_operations usb_ops2 = { - .read_resources = pci_dev_read_resources, - .set_resources = usb_set_resources, /* pci_dev_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_ATI, - .device = PCI_DEVICE_ID_ATI_SB700_USB_18_2, -}; -/* - * static const struct pci_driver usb_5_driver __pci_driver = { - * .ops = &usb_ops2, - * .vendor = PCI_VENDOR_ID_ATI, - * .device = PCI_DEVICE_ID_ATI_SB700_USB_19_2, - * }; - */ diff --git a/src/southbridge/amd/sb700/sm.c b/src/southbridge/amd/sb700/sm.c new file mode 100644 index 0000000000..69df215f52 --- /dev/null +++ b/src/southbridge/amd/sb700/sm.c @@ -0,0 +1,381 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sb700.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 + +/* +* SB700 enables all USB controllers by default in SMBUS Control. +* SB700 enables SATA by default in SMBUS Control. +*/ +static void sm_init(device_t dev) +{ + u8 byte; + u8 byte_old; + u32 dword; + u32 ioapic_base; + u32 on; + u32 nmi_option; + + printk(BIOS_INFO, "sm_init().\n"); + + ioapic_base = pci_read_config32(dev, 0x74) & (0xffffffe0); /* some like mem resource, but does not have enable bit */ + /* Don't rename APIC ID */ + /* TODO: We should call setup_ioapic() here. But kernel hangs if cpu is K8. + * We need to check out why and change back. */ + clear_ioapic(ioapic_base); + + /* 2.10 Interrupt Routing/Filtering */ + dword = pci_read_config8(dev, 0x62); + dword |= 3; + pci_write_config8(dev, 0x62, dword); + + /* Delay back to back interrupts to the CPU. */ + dword = pci_read_config16(dev, 0x64); + dword |= 1 << 13; + pci_write_config16(dev, 0x64, dword); + + /* rrg:K8 INTR Enable (BIOS should set this bit after PIC initialization) */ + /* rpr 2.1 Enabling Legacy Interrupt */ + dword = pci_read_config8(dev, 0x62); + dword |= 1 << 2; + pci_write_config8(dev, 0x62, dword); + + dword = pci_read_config32(dev, 0x78); + dword |= 1 << 9; + pci_write_config32(dev, 0x78, dword); /* enable 0xCD6 0xCD7 */ + + /* bit 10: MultiMediaTimerIrqEn */ + dword = pci_read_config8(dev, 0x64); + dword |= 1 << 10; + pci_write_config8(dev, 0x64, dword); + /* enable serial irq */ + byte = pci_read_config8(dev, 0x69); + byte |= 1 << 7; /* enable serial irq function */ + byte &= ~(0xF << 2); + byte |= 4 << 2; /* set NumSerIrqBits=4 */ + pci_write_config8(dev, 0x69, byte); + + /* IRQ0From8254 */ + byte = pci_read_config8(dev, 0x41); + byte &= ~(1 << 7); + pci_write_config8(dev, 0x41, byte); + + byte = pm_ioread(0x61); + byte |= 1 << 1; /* Set to enable NB/SB handshake during IOAPIC interrupt for AMD K8/K7 */ + pm_iowrite(0x61, byte); + + /* disable SMI */ + byte = pm_ioread(0x53); + byte |= 1 << 3; + pm_iowrite(0x53, byte); + + /* power after power fail */ + on = CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL; + get_option(&on, "power_on_after_fail"); + byte = pm_ioread(0x74); + byte &= ~0x03; + if (on) { + byte |= 2; + } + byte |= 1 << 2; + pm_iowrite(0x74, byte); + printk(BIOS_INFO, "set power %s after power fail\n", on ? "on" : "off"); + + byte = pm_ioread(0x68); + byte &= ~(1 << 1); + /* 2.7 */ + byte |= 1 << 2; + pm_iowrite(0x68, byte); + + /* 2.7 */ + byte = pm_ioread(0x65); + byte &= ~(1 << 7); + pm_iowrite(0x65, byte); + + /* 2.16 */ + byte = pm_ioread(0x55); + byte |= 1 << 5; + pm_iowrite(0x55, byte); + + byte = pm_ioread(0xD7); + byte |= 1 << 6 | 1 << 1;; + pm_iowrite(0xD7, byte); + + /* 2.15 */ + byte = pm_ioread(0x42); + byte &= ~(1 << 2); + pm_iowrite(0x42, byte); + + /* Set up NMI on errors */ + byte = inb(0x70); /* RTC70 */ + byte_old = byte; + nmi_option = NMI_OFF; + get_option(&nmi_option, "nmi"); + if (nmi_option) { + byte &= ~(1 << 7); /* set NMI */ + printk(BIOS_INFO, "++++++++++set NMI+++++\n"); + } else { + byte |= (1 << 7); /* Can not mask NMI from PCI-E and NMI_NOW */ + printk(BIOS_INFO, "++++++++++no set NMI+++++\n"); + } + byte &= ~(1 << 7); + if (byte != byte_old) { + outb(byte, 0x70); + } + + /* 2.11 IO Trap Settings */ + abcfg_reg(0x10090, 1 << 16, 1 << 16); + + /* ab index */ + pci_write_config32(dev, 0xF0, AB_INDX); + /* Initialize the real time clock */ + rtc_init(0); + + /* 4.3 Enabling Upstream DMA Access */ + axcfg_reg(0x04, 1 << 2, 1 << 2); + /* 4.4 Enabling IDE/PCIB Prefetch for Performance Enhancement */ + abcfg_reg(0x10060, 9 << 17, 9 << 17); + abcfg_reg(0x10064, 9 << 17, 9 << 17); + + /* 4.5 Enabling OHCI Prefetch for Performance Enhancement, A12 */ + abcfg_reg(0x80, 1 << 0, 1<< 0); + + /* 4.6 B-Link Client's Credit Variable Settings for the Downstream Arbitration Equation */ + /* 4.7 Enabling Additional Address Bits Checking in Downstream */ + /* 4.15 IO write and SMI ordering enhancement*/ + abcfg_reg(0x9c, 3 << 0 | 1 << 8, 3 << 0 | 1 << 8); + + /* 4.8 Set B-Link Prefetch Mode */ + abcfg_reg(0x80, 3 << 17, 3 << 17); + + /* 4.9 Enabling Detection of Upstream Interrupts */ + abcfg_reg(0x94, 1 << 20 | 0x7FFFF, 1 << 20 | 0x00FEE); + + /* 4.10: Enabling Downstream Posted Transactions to Pass Non-Posted + * Transactions for the K8 Platform (for All Revisions) */ + abcfg_reg(0x10090, 1 << 8, 1 << 8); + + /* 4.11:Programming Cycle Delay for AB and BIF Clock Gating */ + /* 4.12: Enabling AB and BIF Clock Gating */ + abcfg_reg(0x10054, 0xFFFF0000, 0x1040000); + abcfg_reg(0x54, 0xFF << 16, 4 << 16); + abcfg_reg(0x54, 1 << 24, 0 << 24); + abcfg_reg(0x98, 0x0000FF00, 0x00004700); + + /* 4.13:Enabling AB Int_Arbiter Enhancement (for All Revisions) */ + abcfg_reg(0x10054, 0x0000FFFF, 0x07FF); + + /* 4.14:Enabling Requester ID for upstream traffic. */ + abcfg_reg(0x98, 1 << 16, 1 << 16); + + /* 9.2: Enabling IDE Data Bus DD7 Pull Down Resistor */ + byte = pm2_ioread(0xE5); + byte |= 1 << 2; + pm2_iowrite(0xE5, byte); + + /* Enable IDE controller. */ + byte = pm_ioread(0x59); + byte &= ~(1 << 1); + pm_iowrite(0x59, byte); + + printk(BIOS_INFO, "sm_init() end\n"); + + /* Enable NbSb virtual channel */ + axcfg_reg(0x114, 0x3f << 1, 0 << 1); + axcfg_reg(0x120, 0x7f << 1, 0x7f << 1); + axcfg_reg(0x120, 7 << 24, 1 << 24); + axcfg_reg(0x120, 1 << 31, 1 << 31); + abcfg_reg(0x50, 1 << 3, 1 << 3); +} + +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 sb700_sm_read_resources(device_t dev) +{ + struct resource *res; + u8 byte; + + /* rpr2.14: Hides SM bus controller Bar1 where stores HPET MMIO base address */ + byte = pm_ioread(0x55); + byte |= 1 << 7; + pm_iowrite(0x55, byte); + + /* Get the normal pci resources of this device */ + /* pci_dev_read_resources(dev); */ + + byte = pm_ioread(0x55); + byte &= ~(1 << 7); + pm_iowrite(0x55, byte); + + /* apic */ + res = new_resource(dev, 0x74); + res->base = IO_APIC_ADDR; + res->size = 256 * 0x10; + res->limit = 0xFFFFFFFFUL; /* res->base + res->size -1; */ + res->align = 8; + res->gran = 8; + res->flags = IORESOURCE_MEM | IORESOURCE_FIXED; + + #if 0 /* Linux ACPI crashes when it is 1. For late debugging. */ + res = new_resource(dev, 0x14); /* TODO: hpet */ + res->base = 0xfed00000; /* reset hpet to widely accepted address */ + res->size = 0x400; + res->limit = 0xFFFFFFFFUL; /* res->base + res->size -1; */ + res->align = 8; + res->gran = 8; + res->flags = IORESOURCE_MEM | IORESOURCE_FIXED; + #endif + /* dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; */ + + /* smbus */ + res = new_resource(dev, 0x90); + res->base = 0xB00; + res->size = 0x10; + res->limit = 0xFFFFUL; /* res->base + res->size -1; */ + res->align = 8; + res->gran = 8; + res->flags = IORESOURCE_IO | IORESOURCE_FIXED; + + compact_resources(dev); +} + +static void sb700_sm_set_resources(struct device *dev) +{ + struct resource *res; + u8 byte; + + pci_dev_set_resources(dev); + + /* rpr2.14: Make HPET MMIO decoding controlled by the memory enable bit in command register of LPC ISA bridge */ + byte = pm_ioread(0x52); + byte |= 1 << 6; + pm_iowrite(0x52, byte); + + res = find_resource(dev, 0x74); + pci_write_config32(dev, 0x74, res->base | 1 << 3); +#if 0 /* TODO:hpet */ + res = find_resource(dev, 0x14); + pci_write_config32(dev, 0x14, res->base); +#endif + res = find_resource(dev, 0x90); + pci_write_config32(dev, 0x90, res->base | 1); +} + +static struct pci_operations lops_pci = { + .set_subsystem = pci_dev_set_subsystem, +}; + +static struct device_operations smbus_ops = { + .read_resources = sb700_sm_read_resources, + .set_resources = sb700_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_ATI, + .device = PCI_DEVICE_ID_ATI_SB700_SM, +}; diff --git a/src/southbridge/amd/sb700/smbus.c b/src/southbridge/amd/sb700/smbus.c new file mode 100644 index 0000000000..e47bceed47 --- /dev/null +++ b/src/southbridge/amd/sb700/smbus.c @@ -0,0 +1,224 @@ +/* + * 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 _SB700_SMBUS_C_ +#define _SB700_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; +} + +static void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val) +{ + u32 tmp; + + outl((reg_space & 0x3) << 30 | 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.*/ + reg_addr & 0x10000 ? outl(0, AB_INDX) : NULL; + + tmp &= ~mask; + tmp |= val; + + /* printk(BIOS_DEBUG, "about write %x, index=%x", tmp, (reg_space&0x3)<<30 | reg_addr); */ + outl((reg_space & 0x3) << 30 | reg_addr, AB_INDX); /* probably we dont have to do it again. */ + outl(tmp, AB_DATA); + reg_addr & 0x10000 ? outl(0, AB_INDX) : NULL; +} + +/* space = 0: AX_INDXC, AX_DATAC + * space = 1: AX_INDXP, AX_DATAP + */ +static inline void alink_ax_indx(u32 space /*c or p? */ , u32 axindc, + u32 mask, u32 val) +{ + u32 tmp; + + /* read axindc to tmp */ + outl(space << 30 | space << 3 | 0x30, AB_INDX); + outl(axindc, AB_DATA); + outl(space << 30 | space << 3 | 0x34, AB_INDX); + tmp = inl(AB_DATA); + + tmp &= ~mask; + tmp |= val; + + /* write tmp */ + outl(space << 30 | space << 3 | 0x30, AB_INDX); + outl(axindc, AB_DATA); + outl(space << 30 | space << 3 | 0x34, AB_INDX); + outl(tmp, AB_DATA); +} +#endif diff --git a/src/southbridge/amd/sb700/smbus.h b/src/southbridge/amd/sb700/smbus.h new file mode 100644 index 0000000000..c21a1dc0a2 --- /dev/null +++ b/src/southbridge/amd/sb700/smbus.h @@ -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 + */ + +#ifndef SB700_SMBUS_H +#define SB700_SMBUS_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 1 +#define AXCFG 2 +#define ABCFG 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(0, (reg), (mask), (val)) +#define axindxp_reg(reg, mask, val) \ + alink_ax_indx(1, (reg), (mask), (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); +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); + + +#endif diff --git a/src/southbridge/amd/sb700/usb.c b/src/southbridge/amd/sb700/usb.c new file mode 100644 index 0000000000..3b3ad584a7 --- /dev/null +++ b/src/southbridge/amd/sb700/usb.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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include "sb700.h" + +static struct pci_operations lops_pci = { + .set_subsystem = pci_dev_set_subsystem, +}; + +static void usb_init(struct device *dev) +{ + u8 byte; + u16 word; + + /* 6.1 Enable OHCI0-4 and EHCI Controllers */ + device_t sm_dev; + sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0)); + byte = pci_read_config8(sm_dev, 0x68); + byte |= 0xFF; + pci_write_config8(sm_dev, 0x68, byte); + + /* RPR 6.2 Enables the USB PME Event,Enable USB resume support */ + byte = pm_ioread(0x61); + byte |= 1 << 6; + pm_iowrite(0x61, byte); + byte = pm_ioread(0x65); + byte |= 1 << 2; + pm_iowrite(0x65, byte); + + /* RPR 6.3 Support USB device wakeup from the S4/S5 state */ + byte = pm_ioread(0x65); + byte &= ~(1 << 0); + pm_iowrite(0x65, byte); + + /* RPR 6.5 Enable the USB controller to get reset by any software that generate a PCIRst# condition */ + byte = pm_ioread(0x65); + byte |= (1 << 4); + pm_iowrite(0x65, byte); + + /* RPR 6.10 Disable OHCI MSI Capability. */ + word = pci_read_config16(dev, 0x40); + word |= (0x3 << 8); + pci_write_config16(dev, 0x40, word); +} + +static void usb_init2(struct device *dev) +{ + u32 dword; + u32 usb2_bar0; + device_t sm_dev; + u8 rev; + + sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0)); + rev = get_sb700_revision(sm_dev); + + /* dword = pci_read_config32(dev, 0xf8); */ + /* dword |= 40; */ + /* pci_write_config32(dev, 0xf8, dword); */ + + usb2_bar0 = pci_read_config32(dev, 0x10) & ~0xFF; + printk(BIOS_INFO, "usb2_bar0=0x%x\n", usb2_bar0); + + /* RPR6.4 Enables the USB PHY auto calibration resister to match 45ohm resistance */ + dword = 0x00020F00; + write32(usb2_bar0 + 0xC0, dword); + + /* RPR6.9 Sets In/OUT FIFO threshold for best performance */ + dword = 0x00400040; + write32(usb2_bar0 + 0xA4, dword); + + /* RPR6.11 Disabling EHCI Advance Asynchronous Enhancement */ + dword = pci_read_config32(dev, 0x50); + dword |= (1 << 28); + pci_write_config32(dev, 0x50, dword); + + /* RPR 6.12 EHCI Advance PHY Power Savings */ + /* RPR says it is just for A12. CIMM sets it when it is above A11. */ + /* But it makes the linux crash, so we skip it */ + #if 0 + dword = pci_read_config32(dev, 0x50); + dword |= 1 << 31; + pci_write_config32(dev, 0x50, dword); + #endif + + /* RPR6.13 Enabling Fix for EHCI Controller Driver Yellow Sign Issue */ + /* RPR says it is just for A12. CIMx sets it when it is above A11. */ + dword = pci_read_config32(dev, 0x50); + dword |= (1 << 20); + pci_write_config32(dev, 0x50, dword); + + /* RPR6.15 EHCI Async Park Mode */ + dword = pci_read_config32(dev, 0x50); + dword |= (1 << 23); + pci_write_config32(dev, 0x50, dword); + + /* Each step below causes the linux crashes. Leave them here + * for future debugging. */ +#if 0 + u8 byte; + u16 word; + + /* RPR6.16 Disable EHCI MSI support */ + byte = pci_read_config8(dev, 0x50); + byte |= (1 << 6); + pci_write_config8(dev, 0x50, byte); + + /* RPR6.17 Disable the EHCI Dynamic Power Saving feature */ + word = read32(usb2_bar0 + 0xBC); + word &= ~(1 << 12); + write16(usb2_bar0 + 0xBC, word); + + /* RPR6.19 USB Controller DMA Read Delay Tolerant. */ + if (rev >= REV_SB700_A14) { + byte = pci_read_config8(dev, 0x50); + byte |= (1 << 7); + pci_write_config8(dev, 0x50, byte); + } + + /* RPR6.20 Async Park Mode. */ + /* RPR recommends not to set these bits. */ + #if 0 + dword = pci_read_config32(dev, 0x50); + dword |= 1 << 23; + if (rev >= REV_SB700_A14) { + dword &= ~(1 << 2); + } + pci_write_config32(dev, 0x50, dword); + #endif + + /* RPR6.22 Advance Async Enhancement */ + /* RPR6.23 USB Periodic Cache Setting */ + dword = pci_read_config32(dev, 0x50); + if (rev == REV_SB700_A12) { + dword |= 1 << 28; /* 6.22 */ + dword |= 1 << 27; /* 6.23 */ + } else if (rev >= REV_SB700_A14) { + dword |= 1 << 3; + dword &= ~(1 << 28); /* 6.22 */ + dword |= 1 << 8; + dword &= ~(1 << 27); /* 6.23 */ + } + printk(BIOS_DEBUG, "rpr 6.23, final dword=%x\n", dword); +#endif +} + +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_ATI, + .device = PCI_DEVICE_ID_ATI_SB700_USB_18_0, +}; + +static const struct pci_driver usb_1_driver __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_SB700_USB_18_1, +}; + +/* 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_ATI, + * .device = PCI_DEVICE_ID_ATI_SB700_USB_19_0, + * }; + * static const struct pci_driver usb_4_driver __pci_driver = { + * .ops = &usb_ops, + * .vendor = PCI_VENDOR_ID_ATI, + * .device = PCI_DEVICE_ID_ATI_SB700_USB_19_1, + * }; + */ + +static const struct pci_driver usb_4_driver __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_SB700_USB_20_5, +}; + +static struct device_operations usb_ops2 = { + .read_resources = pci_dev_read_resources, + .set_resources = usb_set_resources, /* pci_dev_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_ATI, + .device = PCI_DEVICE_ID_ATI_SB700_USB_18_2, +}; +/* + * static const struct pci_driver usb_5_driver __pci_driver = { + * .ops = &usb_ops2, + * .vendor = PCI_VENDOR_ID_ATI, + * .device = PCI_DEVICE_ID_ATI_SB700_USB_19_2, + * }; + */ -- cgit v1.2.3