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/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 +++++++++ 25 files changed, 2624 insertions(+), 2624 deletions(-) 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/sb700') 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