From a67d4fd1ffffc76c328717f2519e3d7e7792f2b8 Mon Sep 17 00:00:00 2001 From: Marc Jones Date: Fri, 4 May 2007 19:05:36 +0000 Subject: This patch re-implements support for the CS5536 companion chip for the AMD GX and LX processors. This aguments the previous code, which was very specific to the OLPC platform with general purpose support and better integration with the VSA and CPUs. Signed-off-by: Marc Jones Acked-by: Stefan Reinauer git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2631 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/include/device/pci_ids.h | 3 +- src/southbridge/amd/cs5536/Config.lb | 22 +- src/southbridge/amd/cs5536/chip.h | 40 +- src/southbridge/amd/cs5536/cs5536.c | 689 +++++++++++++++++++----- src/southbridge/amd/cs5536/cs5536.h | 469 +++++++++++++++- src/southbridge/amd/cs5536/cs5536_early_setup.c | 257 ++++----- src/southbridge/amd/cs5536/cs5536_early_smbus.c | 216 +++++++- src/southbridge/amd/cs5536/cs5536_ide.c | 48 +- src/southbridge/amd/cs5536/cs5536_smbus.h | 180 ------- src/southbridge/amd/cs5536/cs5536_smbus2.h | 3 +- 10 files changed, 1411 insertions(+), 516 deletions(-) delete mode 100644 src/southbridge/amd/cs5536/cs5536_smbus.h (limited to 'src') diff --git a/src/include/device/pci_ids.h b/src/include/device/pci_ids.h index 74a60b229c..85fa3363c5 100644 --- a/src/include/device/pci_ids.h +++ b/src/include/device/pci_ids.h @@ -452,12 +452,13 @@ #define PCI_DEVICE_ID_AMD_AES 0x2082 #define PCI_DEVICE_ID_AMD_CS5536_ISA 0x2090 #define PCI_DEVICE_ID_AMD_CS5536_FLASH 0x2091 -#define PCI_DEVICE_ID_AMD_CS5536_IDE 0x2092 +#define PCI_DEVICE_ID_AMD_CS5536_IDE_A0 0x2092 #define PCI_DEVICE_ID_AMD_CS5536_AUDIO 0x2093 #define PCI_DEVICE_ID_AMD_CS5536_OHCI 0x2094 #define PCI_DEVICE_ID_AMD_CS5536_EHCI 0x2095 #define PCI_DEVICE_ID_AMD_CS5536_UDC 0x2096 #define PCI_DEVICE_ID_AMD_CS5536_OTG 0x2097 +#define PCI_DEVICE_ID_AMD_CS5536_IDE 0x209A #define PCI_VENDOR_ID_TRIDENT 0x1023 #define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX 0x2000 diff --git a/src/southbridge/amd/cs5536/Config.lb b/src/southbridge/amd/cs5536/Config.lb index 618db33f4f..bf1763b42e 100644 --- a/src/southbridge/amd/cs5536/Config.lb +++ b/src/southbridge/amd/cs5536/Config.lb @@ -1,4 +1,22 @@ +#/* +#* This file is part of the LinuxBIOS project. +#* +#* +#* This program is free software; you can redistribute it and/or modify +#* it under the terms of the GNU General Public License version 2 as +#* published by the Free Software Foundation. +#* +#* This program is distributed in the hope that it will be useful, +#* but WITHOUT ANY WARRANTY; without even the implied warranty of +#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#* GNU General Public License for more details. +#* +#* You should have received a copy of the GNU General Public License +#* along with this program; if not, write to the Free Software +#* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#*/ + + config chip.h driver cs5536.o -#driver cs5536_pci.o -#driver cs5536_ide.o +driver cs5536_ide.o diff --git a/src/southbridge/amd/cs5536/chip.h b/src/southbridge/amd/cs5536/chip.h index 6bd87430fd..7c8a249872 100644 --- a/src/southbridge/amd/cs5536/chip.h +++ b/src/southbridge/amd/cs5536/chip.h @@ -1,28 +1,32 @@ +/* +* +* Copyright (C) 2007 Advanced Micro Devices +* +*/ + #ifndef _SOUTHBRIDGE_AMD_CS5536 #define _SOUTHBRIDGE_AMD_CS5536 -#define MAX_UNWANTED_VPCI 10 /* increase if needed */ +#define MAX_UNWANTED_VPCI 8 /* increase if needed */ extern struct chip_operations southbridge_amd_cs5536_ops; struct southbridge_amd_cs5536_config { - /* interrupt enable for LPC bus */ - int lpc_serirq_enable; /* how to enable, e.g. 0x80 */ - int lpc_irq; /* what to enable, e.g. 0x18 */ - int enable_gpio0_inta; /* almost always will be true */ - int enable_ide_nand_flash; /* if you are using nand flash instead of IDE drive */ - int enable_uarta; /* internal uarta interrupt enable */ - int enable_USBP4_host; /* Enable USB Port 4 as a host */ - /* following are IRQ numbers for various southbridge resources. */ - /* I have guessed at some things, as I still don't have an lspci from anyone */ - int ide_irq; /* f.2 */ - int audio_irq; /* f.3 */ - int usbf4_irq; /* f.4 */ - int usbf5_irq; /* f.5 */ - int usbf6_irq; /* f.6 */ - int usbf7_irq; /* f.7 */ - /* the following allow you to disable unwanted virtualized PCI devices */ - unsigned long unwanted_vpci[MAX_UNWANTED_VPCI]; + unsigned int lpc_serirq_enable; /* interrupt enables for LPC bus; each bit is an irq 0-15 */ + unsigned int lpc_serirq_polarity; /* LPC IRQ polarity; each bit is an irq 0-15 */ + unsigned char lpc_serirq_mode; /* 0:Continuous 1:Quiet */ + unsigned int enable_gpio_int_route; /* GPIO(0-0x20) for INT D:C:B:A, 0xFF=none. See virtual pci spec... */ + unsigned char enable_ide_nand_flash; /* 0:IDE 1:FLASH, if you are using nand flash instead of IDE drive */ + unsigned char enable_USBP4_device; /* Enable USB Port 4 0:host 1:device */ + unsigned int enable_USBP4_overcurrent; /* 0:off, xxxx:overcurrent setting, e.g. 0x3FEA CS5536 - Data Book (pages 380-381) */ + unsigned char com1_enable; /* enable COM1 */ + unsigned int com1_address; /* e.g. 0x3F8 */ + unsigned int com1_irq; /* e.g. 4 */ + unsigned char com2_enable; /* enable COM2 */ + unsigned int com2_address; /* e.g. 0x2F8 */ + unsigned int com2_irq; /* e.g. 3 */ + unsigned int unwanted_vpci[MAX_UNWANTED_VPCI]; /* the following allow you to disable unwanted virtualized PCI devices */ + }; #endif /* _SOUTHBRIDGE_AMD_CS5536 */ diff --git a/src/southbridge/amd/cs5536/cs5536.c b/src/southbridge/amd/cs5536/cs5536.c index 47958dba6a..e5f9878ab7 100644 --- a/src/southbridge/amd/cs5536/cs5536.c +++ b/src/southbridge/amd/cs5536/cs5536.c @@ -1,3 +1,21 @@ +/* +* This file is part of the LinuxBIOS project. +* +* Copyright (C) 2007 Advanced Micro Devices +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ #include #include @@ -5,167 +23,575 @@ #include #include #include -#include +#include +#include +#include #include +#include +#include #include "chip.h" +#include "cs5536.h" +extern void setup_i8259(void); -#define PIN_OPT_IDE (1ULL<<0) /* 0 for flash, 1 for IDE */ +struct msrinit { + uint32_t msrnum; + msr_t msr; +}; -/* Intended value for LBAR_FLSH0: 4KiB, enabled, MMIO, NAND, @0x20000000 */ -/* NOTE: no longer used, prune at some point */ -/* OOPS: steve's changes don't work, so we have to keep this */ -msr_t flsh0 = { .hi=0xFFFFF007, .lo=0x20000000}; +/* Master Configuration Register for Bus Masters.*/ +struct msrinit SB_MASTER_CONF_TABLE[] = { + {USB2_SB_GLD_MSR_CONF, {.hi=0,.lo=0x00008f000}}, + {ATA_SB_GLD_MSR_CONF, {.hi=0,.lo=0x00048f000}}, + {AC97_SB_GLD_MSR_CONF, {.hi=0,.lo=0x00008f000}}, + {MDD_SB_GLD_MSR_CONF, {.hi=0,.lo=0x00000f000}}, + {0,{0,0}} +}; -static void -enable_ide_nand_flash(){ - msr_t msr; - printk_err("cs5536: %s\n", __FUNCTION__); -#if 1 - printk_err("WARNING: using deprecated flash enable mechanism\n"); - /* steve took this one out ... not sure if needed or not */ - msr = rdmsr(MDD_LBAR_FLSH0); - - if ( ((msr.hi) & 7) != 7) { - printk_err("MDD_LBAR_FLSH0 was 0x%08x%08x\n", msr.hi,msr.lo); - wrmsr(MDD_LBAR_FLSH0, flsh0); - } - msr = rdmsr(MDD_LBAR_FLSH0); - printk_err("MDD_LBAR_FLSH0 is 0x%08x%08x\n", msr.hi,msr.lo); -#endif - msr = rdmsr(MDD_PIN_OPT); - if (msr.lo & PIN_OPT_IDE) { - printk_err("MDD_PIN_OPT was 0x%08x%08x\n", msr.hi,msr.lo); - msr.lo &= ~PIN_OPT_IDE; - wrmsr(MDD_PIN_OPT, msr); - } - msr = rdmsr(MDD_PIN_OPT); - printk_err("MDD_PIN_OPT is 0x%08x%08x\n", msr.hi,msr.lo); - - msr = rdmsr(MDD_NANDF_DATA); - if (msr.lo != 0x00100010) { - printk_err("MDD_NANDF_DATA was 0x%08x%08x\n", msr.hi,msr.lo); - msr.lo = 0x00100010; - wrmsr(MDD_NANDF_DATA, msr); - } - msr = rdmsr(MDD_NANDF_DATA); - printk_err("MDD_NANDF_DATA is 0x%08x%08x\n", msr.hi,msr.lo); - - msr = rdmsr(MDD_NADF_CNTL); - if (msr.lo != 0x0010) { - printk_err("MDD_NADF_CNTL was 0x%08x%08x\n", msr.hi,msr.lo); - msr.lo = 0x0010; - wrmsr(MDD_NADF_CNTL, msr); - } - msr = rdmsr(MDD_NADF_CNTL); - printk_err("MDD_NADF_CNTL is 0x%08x%08x\n", msr.hi,msr.lo); - printk_err("cs5536: EXIT %s\n", __FUNCTION__); +/* 5536 Clock Gating*/ +struct msrinit CS5536_CLOCK_GATING_TABLE[] = { +/* MSR Setting*/ + {GLIU_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000004}}, + {GLPCI_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, + {GLCP_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000004}}, + {MDD_SB_GLD_MSR_PM, {.hi=0,.lo=0x050554111}}, /* SMBus clock gating errata (PBZ 2226 & SiBZ 3977)*/ + {ATA_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, + {AC97_SB_GLD_MSR_PM, {.hi=0,.lo=0x000000005}}, + {0,{0,0}} +}; + +struct acpiinit { + uint16_t ioreg; + uint32_t regdata; +}; + +struct acpiinit acpi_init_table[] = { + {ACPI_IO_BASE + 0x00, 0x01000000}, + {ACPI_IO_BASE + 0x08, 0}, + {ACPI_IO_BASE + 0x0C, 0}, + {ACPI_IO_BASE + 0x1C, 0}, + {ACPI_IO_BASE + 0x18, 0x0FFFFFFFF}, + {ACPI_IO_BASE + 0x00, 0x0000FFFF}, + {PMS_IO_BASE + PM_SCLK, 0x000000E00}, + {PMS_IO_BASE + PM_SED, 0x000004601}, + {PMS_IO_BASE + PM_SIDD, 0x000008C02}, + {PMS_IO_BASE + PM_WKD, 0x0000000A0}, + {PMS_IO_BASE + PM_WKXD, 0x0000000A0}, + {0,0,0} +}; + +struct FLASH_DEVICE { + unsigned char fType; /* Flash type: NOR or NAND */ + unsigned char fInterface; /* Flash interface: I/O or Memory */ + unsigned long fMask; /* Flash size/mask */ +}; + +struct FLASH_DEVICE FlashInitTable[] = { + { FLASH_TYPE_NAND, FLASH_IF_MEM, FLASH_MEM_4K }, /* CS0, or Flash Device 0 */ + { FLASH_TYPE_NONE, 0, 0 }, /* CS1, or Flash Device 1 */ + { FLASH_TYPE_NONE, 0, 0 }, /* CS2, or Flash Device 2 */ + { FLASH_TYPE_NONE, 0, 0 }, /* CS3, or Flash Device 3 */ +}; + +#define FlashInitTableLen (sizeof(FlashInitTable)/sizeof(FlashInitTable[0])) + +uint32_t FlashPort[] = { + MDD_LBAR_FLSH0, + MDD_LBAR_FLSH1, + MDD_LBAR_FLSH2, + MDD_LBAR_FLSH3 + }; + + +/* ***************************************************************************/ +/* **/ +/* * pmChipsetInit*/ +/* **/ +/* * Program ACPI LBAR and initialize ACPI registers.*/ +/* **/ +/* ***************************************************************************/ +static void pmChipsetInit(void) { + uint32_t val = 0; + uint16_t port; + + port = (PMS_IO_BASE + 0x010); + val = 0x0E00 ; /* 1ms*/ + outl(val, port); + + /* PM_WKXD*/ + /* Make sure bits[3:0]=0000b to clear the*/ + /* saved Sx state*/ + port = (PMS_IO_BASE + 0x034); + val = 0x0A0 ; /* 5ms*/ + outl(val, port); + + /* PM_WKD*/ + port = (PMS_IO_BASE + 0x030); + outl(val, port); + + /* PM_SED*/ + port = (PMS_IO_BASE + 0x014); +/* mov eax, 0x057642 ; 100ms, works*/ + val = 0x04601 ; /* 5ms*/ + outl(val, port); + + /* PM_SIDD*/ + port = (PMS_IO_BASE + 0x020); +/* mov eax, 0x0AEC84 ; 200ms, works*/ + val = 0x08C02 ; /* 10ms*/ + outl(val, port); } -#if 0 -/* note: this is a candidate for inclusion in src/devices/pci_device.c */ -void -setup_irq(unsigned irq, char *name, unsigned level, unsigned bus, unsigned device, unsigned fn){ - if (irq) { - unsigned devfn = PCI_DEVFN(device,fn); - device_t dev = dev_find_slot(bus, devfn); - if (dev) { - pci_write_config8(dev, PCI_INTERRUPT_LINE, irq); - if (level) - pci_level_irq(irq); + +/*************************************************************************** + * + * ChipsetFlashSetup + * + * Flash LBARs need to be setup before VSA init so the PCI BARs have + * correct size info. Call this routine only if flash needs to be + * configured (don't call it if you want IDE). + * + **************************************************************************/ +static void ChipsetFlashSetup(void){ + msr_t msr; + int i; + int numEnabled = 0; + + printk_debug("ChipsetFlashSetup: Start\n"); + for (i = 0; i < FlashInitTableLen; i++) { + if (FlashInitTable[i].fType != FLASH_TYPE_NONE) { + printk_debug("Enable CS%d\n", i); + /* we need to configure the memory/IO mask */ + msr = rdmsr(FlashPort[i]); + msr.hi = 0; /* start with the "enabled" bit clear */ + if (FlashInitTable[i].fType == FLASH_TYPE_NAND) + msr.hi |= 0x00000002; + else + msr.hi &= ~0x00000002; + if (FlashInitTable[i].fInterface == FLASH_IF_MEM) + msr.hi |= 0x00000004; + else + msr.hi &= ~0x00000004; + msr.hi |= FlashInitTable[i].fMask; + printk_debug("MSR(0x%08X, %08X_%08X)\n", FlashPort[i], msr.hi, msr.lo); + wrmsr(FlashPort[i], msr); + + /* now write-enable the device */ + msr = rdmsr(MDD_NORF_CNTRL); + msr.lo |= (1 << i); + printk_debug("MSR(0x%08X, %08X_%08X)\n", MDD_NORF_CNTRL, msr.hi, msr.lo); + wrmsr(MDD_NORF_CNTRL, msr); + + /* update the number enabled */ + numEnabled++; } - else - printk_err("%s: Can't find %s at 0x%x\n", __FUNCTION__, name, devfn); } + + printk_debug("ChipsetFlashSetup: Finish\n"); + +} +/* ***************************************************************************/ +/* **/ +/* * enable_ide_nand_flash_header */ +/* Run after VSA init to enable the flash PCI device header */ +/* **/ +/* ***************************************************************************/ +static void enable_ide_nand_flash_header(){ + /* Tell VSA to use FLASH PCI header. Not IDE header.*/ + outl(0x80007A40, 0xCF8); + outl(0xDEADBEEF, 0xCFC); } -#endif -static void southbridge_init(struct device *dev) -{ - struct southbridge_amd_cs5536_config *sb = (struct southbridge_amd_cs5536_config *)dev->chip_info; - const unsigned char slots_cpu[4] = {11, 0, 0, 0}; - const unsigned char slots_sb[4] = {11, 5, 10, 10}; - msr_t msr; - int i; - /* - * struct device *gpiodev; - * unsigned short gpiobase = MDD_GPIO; - */ - printk_err("cs5536: %s\n", __FUNCTION__); - setup_i8259(); +#define RTC_CENTURY 0x32 +#define RTC_DOMA 0x3D +#define RTC_MONA 0x3E + +static void lpc_init(struct southbridge_amd_cs5536_config *sb){ + msr_t msr; if (sb->lpc_serirq_enable) { msr.lo = sb->lpc_serirq_enable; - msr.hi = 0; - wrmsr(MDD_LPC_SIRQ, msr); - } - if (sb->lpc_irq) { - msr.lo = sb->lpc_irq; msr.hi = 0; wrmsr(MDD_IRQM_LPC, msr); + if (sb->lpc_serirq_polarity) { + msr.lo = sb->lpc_serirq_polarity << 16; + msr.lo |= (sb->lpc_serirq_mode << 6) | (1 << 7); /* enable */ + msr.hi = 0; + wrmsr(MDD_LPC_SIRQ, msr); + } + } + + /* Allow DMA from LPC */ + msr = rdmsr(MDD_DMA_MAP); + msr.lo = 0x7777; + wrmsr(MDD_DMA_MAP, msr); + + /* enable the RTC/CMOS century byte at address 32h */ + msr = rdmsr(MDD_RTC_CENTURY_OFFSET); + msr.lo = RTC_CENTURY; + wrmsr(MDD_RTC_CENTURY_OFFSET, msr); + + /* enable the RTC/CMOS day of month and month alarms */ + msr = rdmsr(MDD_RTC_DOMA_IND); + msr.lo = RTC_DOMA; + wrmsr(MDD_RTC_DOMA_IND, msr); + + msr = rdmsr(MDD_RTC_MONA_IND); + msr.lo = RTC_MONA; + wrmsr(MDD_RTC_MONA_IND, msr); + + rtc_init(0); + + isa_dma_init(); +} + + +static void uarts_init(struct southbridge_amd_cs5536_config *sb){ + msr_t msr; + uint16_t addr; + uint32_t gpio_addr; + device_t dev; + + dev = dev_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, 0); + gpio_addr = pci_read_config32(dev, PCI_BASE_ADDRESS_1); + gpio_addr &= ~1; /* clear IO bit */ + printk_debug("GPIO_ADDR: %08X\n", gpio_addr); + + /* This could be extended to support IR modes */ + + /* COM1 */ + if (sb->com1_enable){ + /* Set the address */ + switch (sb->com1_address){ + case 0x3F8: + addr = 7; + break; + + case 0x3E8: + addr = 6; + break; + + case 0x2F8: + addr = 5; + break; + + case 0x2E8: + addr = 4; + break; + } + msr = rdmsr(MDD_LEG_IO); + msr.lo |= addr << 16; + wrmsr(MDD_LEG_IO,msr); + + /* Set the IRQ */ + msr = rdmsr(MDD_IRQM_YHIGH); + msr.lo |= sb->com1_irq << 24; + wrmsr(MDD_IRQM_YHIGH, msr); + + /* GPIO8 - UART1_TX */ + /* Set: Output Enable (0x4) */ + outl(GPIOL_8_SET, gpio_addr + GPIOL_OUTPUT_ENABLE); + /* Set: OUTAUX1 Select (0x10) */ + outl(GPIOL_8_SET, gpio_addr + GPIOL_OUT_AUX1_SELECT); + + /* GPIO8 - UART1_RX */ + /* Set: Input Enable (0x20) */ + outl(GPIOL_9_SET, gpio_addr + GPIOL_INPUT_ENABLE); + /* Set: INAUX1 Select (0x34) */ + outl(GPIOL_9_SET, gpio_addr + GPIOL_IN_AUX1_SELECT); + + /* Set: GPIO 8 + 9 Pull Up (0x18) */ + outl(GPIOL_8_SET | GPIOL_9_SET, gpio_addr + GPIOL_PULLUP_ENABLE); + + /* enable COM1 */ + /* Bit 1 = device enable Bit 4 = allow access to the upper banks */ + msr.lo = (1 << 4) | (1 << 1); + msr.hi = 0; + wrmsr(MDD_UART1_CONF, msr); + } + else{ + /* Reset and disable COM1 */ + msr = rdmsr(MDD_UART1_CONF); + msr.lo = 1; // reset + wrmsr(MDD_UART1_CONF, msr); + msr.lo = 0; // disabled + wrmsr(MDD_UART1_CONF, msr); - if (sb->enable_gpio0_inta){ - msr = rdmsr(MDD_IRQM_ZHIGH); - msr.lo |= 0x10; - wrmsr(MDD_IRQM_ZHIGH, msr); - /* todo: look the device up. But we know that gpiobase is 0x6100 */ - /* oh gosh, all the defines from AMD assume 6100. Don't bother looking up! */ - outl(GPIOL_0_SET|GPIOL_1_SET|GPIOL_3_SET, GPIOL_INPUT_ENABLE); - outl(GPIOL_0_SET,GPIOL_EVENTS_ENABLE); - /* magic stuff */ - outl(0x3081, GPIOL_INPUT_INVERT_ENABLE); - outl(GPIOL_0_SET, GPIO_MAPPER_X); + /* Disable the IRQ */ + msr = rdmsr(MDD_LEG_IO); + msr.lo |= ~(0xF << 16); + wrmsr(MDD_LEG_IO,msr); } - if (sb->enable_uarta){ - printk_err("cs5536: %s: enable uarta, msr MDD_IRQM_YHIGH(%x) \n", - __FUNCTION__, MDD_IRQM_YHIGH); + /* COM2 */ + if (sb->com2_enable){ + switch (sb->com2_address){ + case 0x3F8: + addr = 7; + break; + + case 0x3E8: + addr = 6; + break; + + case 0x2F8: + addr = 5; + break; + + case 0x2E8: + addr = 4; + break; + } + msr = rdmsr(MDD_LEG_IO); + msr.lo |= addr << 20; + wrmsr(MDD_LEG_IO,msr); + + + /* Set the IRQ */ msr = rdmsr(MDD_IRQM_YHIGH); - msr.lo |= 0x04000000; + msr.lo |= sb->com2_irq << 28; wrmsr(MDD_IRQM_YHIGH, msr); + + /* GPIO3 - UART2_RX */ + /* Set: Output Enable (0x4) */ + outl(GPIOL_3_SET, gpio_addr + GPIOL_OUTPUT_ENABLE); + /* Set: OUTAUX1 Select (0x10) */ + outl(GPIOL_3_SET,gpio_addr + GPIOL_OUT_AUX1_SELECT); + + /* GPIO4 - UART2_TX */ + /* Set: Input Enable (0x20) */ + outl(GPIOL_4_SET, gpio_addr + GPIOL_INPUT_ENABLE); + /* Set: INAUX1 Select (0x34) */ + outl(GPIOL_4_SET, gpio_addr + GPIOL_IN_AUX1_SELECT); + + /* Set: GPIO 3 + 3 Pull Up (0x18) */ + outl(GPIOL_3_SET | GPIOL_4_SET, gpio_addr + GPIOL_PULLUP_ENABLE); + + /* enable COM2 */ + /* Bit 1 = device enable Bit 4 = allow access to the upper banks */ + msr.lo = (1 << 4) | (1 << 1); + msr.hi = 0; + wrmsr(MDD_UART2_CONF, msr); + } + else{ + /* Reset and disable COM2 */ + msr = rdmsr(MDD_UART2_CONF); + msr.lo = 1; // reset + wrmsr(MDD_UART2_CONF, msr); + msr.lo = 0; // disabled + wrmsr(MDD_UART2_CONF, msr); - printk_err("cs5536: %s: enable_ide_nand_flash is %d\n", __FUNCTION__, sb->enable_ide_nand_flash); - if (sb->enable_ide_nand_flash) { - enable_ide_nand_flash(); + /* Disable the IRQ */ + msr = rdmsr(MDD_LEG_IO); + msr.lo |= ~(0xF << 20); + wrmsr(MDD_LEG_IO,msr); } +} + -#if 0 - /* irq handling */ - setup_irq(sb->audio_irq, "audio", 1, 0, 0xf, 2); - setup_irq(sb->usbf4_irq, "usb f4", 1, 0, 0xf, 4); - setup_irq(sb->usbf5_irq, "usb f5", 1, 0, 0xf, 5); - setup_irq(sb->usbf6_irq, "usb f6", 1, 0, 0xf, 6); - setup_irq(sb->usbf7_irq, "usb f7", 1, 0, 0xf, 7); -#else - /* CPU (80000800 = 00.01.00) */ - pci_assign_irqs(0, 0x01, slots_cpu); /* bus=0, device=0x01, slots={11,0,0,0} */ - - /* Southbridge (80007800 = 00.0F.00) */ - pci_assign_irqs(0, 0x0F, slots_sb); /* bus=0, device=0x0F, slots={11,5,10,10} */ -#endif - if (sb->enable_USBP4_host) { - unsigned long val; - unsigned long uocmux; +#define HCCPARAMS 0x08 +#define IPREG04 0xA0 + #define USB_HCCPW_SET (1 << 1) +#define UOCCAP 0x00 + #define APU_SET (1 << 15) +#define UOCMUX 0x04 + #define PMUX_HOST 0x02 + #define PMUX_DEVICE 0x03 + #define PUEN_SET (1 << 2) +#define UDCDEVCTL 0x404 + #define UDC_SD_SET (1 << 10) +#define UOCCTL 0x0C + #define PADEN_SET (1 << 7) - outl(0x80007F10, 0xCF8); - outl(0x0EFC00000, 0xCFC); - uocmux = *((unsigned long *) 0x0EFC00004); - uocmux &= ~3; - uocmux |= 2; +static void enable_USB_port4(struct southbridge_amd_cs5536_config *sb) +{ + uint32_t * bar; + msr_t msr; + device_t dev; + + + dev = dev_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_EHCI, 0); + if(dev){ + + /* Serial Short Detect Enable */ + msr = rdmsr(USB2_SB_GLD_MSR_CONF); + msr.hi |= USB2_UPPER_SSDEN_SET; + wrmsr(USB2_SB_GLD_MSR_CONF, msr); - *((unsigned long *) 0x0EFC00004) = uocmux; + /* write to clear diag register */ + wrmsr(USB2_SB_GLD_MSR_DIAG,rdmsr(USB2_SB_GLD_MSR_DIAG)); + + bar = (uint32_t *) pci_read_config32(dev, PCI_BASE_ADDRESS_0); + + /* Make HCCPARAMS writeable */ + *(bar + IPREG04) |= USB_HCCPW_SET; + + /* ; EECP=50h, IST=01h, ASPC=1 */ + *(bar + HCCPARAMS) = 0x00005012; } + + dev = dev_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_OTG, 0); + if(dev){ + bar = (uint32_t *) pci_read_config32(dev, PCI_BASE_ADDRESS_0); + + *(bar + UOCMUX) &= PUEN_SET; + + /* Host or Device? */ + if (sb->enable_USBP4_device) { + *(bar + UOCMUX) |= PMUX_DEVICE; + } + else{ + *(bar + UOCMUX) |= PMUX_HOST; + } + + /* Overcurrent configuration */ + if (sb->enable_USBP4_overcurrent) { + *(bar + UOCCAP) |= sb->enable_USBP4_overcurrent; + } + } + + /* PBz#6466: If the UOC(OTG) device, port 4, is configured as a device, + * then perform the following sequence: + * + * - set SD bit in DEVCTRL udc register + * - set PADEN (former OTGPADEN) bit in uoc register + * - set APU bit in uoc register */ + if (sb->enable_USBP4_device) { + dev = dev_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_UDC, 0); + if(dev){ + bar = (uint32_t *) pci_read_config32(dev, PCI_BASE_ADDRESS_0); + *(bar + UDCDEVCTL) |= UDC_SD_SET; + + } + + dev = dev_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_OTG, 0); + if(dev){ + bar = (uint32_t *) pci_read_config32(dev, PCI_BASE_ADDRESS_0); + *(bar + UOCCTL) |= PADEN_SET; + *(bar + UOCCAP) |= APU_SET; + } + } + + /* Disable virtual PCI UDC and OTG headers */ + dev = dev_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_UDC, 0); + if(dev){ + pci_write_config8(dev, 0x7C, 0xDEADBEEF); + } + + dev = dev_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_OTG, 0); + if(dev){ + pci_write_config8(dev, 0x7C, 0xDEADBEEF); + } +} + +/* ***************************************************************************/ +/* **/ +/* * ChipsetInit */ +/* Called from northbridge init (Pre-VSA). */ +/* **/ +/* ***************************************************************************/ +void chipsetinit (void){ + device_t dev; + msr_t msr; + uint32_t msrnum; + struct southbridge_amd_cs5536_config *sb = (struct southbridge_amd_cs5536_config *)dev->chip_info; + struct msrinit *csi; + + outb( P80_CHIPSET_INIT, 0x80); + + /* we hope NEVER to be in linuxbios when S3 resumes + if (! IsS3Resume()) */ + { + struct acpiinit *aci = acpi_init_table; + for(; aci->ioreg; aci++) { + outl(aci->regdata, aci->ioreg); + inl(aci->ioreg); + } + + pmChipsetInit(); + } + + + /* set hd IRQ */ + outl( GPIOL_2_SET, GPIO_IO_BASE + GPIOL_INPUT_ENABLE); + outl( GPIOL_2_SET, GPIO_IO_BASE + GPIOL_IN_AUX1_SELECT); + + /* Allow IO read and writes during a ATA DMA operation.*/ + /* This could be done in the HD rom but do it here for easier debugging.*/ + msrnum = ATA_SB_GLD_MSR_ERR; + msr = rdmsr(msrnum); + msr.lo &= ~0x100; + wrmsr(msrnum, msr); + + /* Enable Post Primary IDE.*/ + msrnum = GLPCI_SB_CTRL; + msr = rdmsr(msrnum); + msr.lo |= GLPCI_CRTL_PPIDE_SET; + wrmsr(msrnum, msr); + + + csi = SB_MASTER_CONF_TABLE; + for(; csi->msrnum; csi++){ + msr.lo = csi->msr.lo; + msr.hi = csi->msr.hi; + wrmsr(csi->msrnum, msr); // MSR - see table above + } + + /* Flash BAR size Setup*/ + printk_err("%sDoing ChipsetFlashSetup()\n", sb->enable_ide_nand_flash == 1 ? "" : "Not "); + if (sb->enable_ide_nand_flash == 1) + ChipsetFlashSetup(); + + /* */ + /* Set up Hardware Clock Gating*/ + /* */ + { + csi = CS5536_CLOCK_GATING_TABLE; + for(; csi->msrnum; csi++){ + msr.lo = csi->msr.lo; + msr.hi = csi->msr.hi; + wrmsr(csi->msrnum, msr); // MSR - see table above + } + } +} + +static void southbridge_init(struct device *dev) +{ + struct southbridge_amd_cs5536_config *sb = (struct southbridge_amd_cs5536_config *)dev->chip_info; + int i; + /* + * struct device *gpiodev; + * unsigned short gpiobase = MDD_GPIO; + */ + + printk_err("cs5536: %s\n", __FUNCTION__); + setup_i8259(); + lpc_init(sb); + uarts_init(sb); + + if (sb->enable_gpio_int_route){ + vrWrite((VRC_MISCELLANEOUS << 8) + PCI_INT_AB, (sb->enable_gpio_int_route & 0xFFFF)); + vrWrite((VRC_MISCELLANEOUS << 8) + PCI_INT_CD, (sb->enable_gpio_int_route >> 16)); + } + + printk_err("cs5536: %s: enable_ide_nand_flash is %d\n", __FUNCTION__, sb->enable_ide_nand_flash); + if (sb->enable_ide_nand_flash == 1) { + enable_ide_nand_flash_header(); + } + + enable_USB_port4(sb); + /* disable unwanted virtual PCI devices */ for (i = 0; (i < MAX_UNWANTED_VPCI) && (0 != sb->unwanted_vpci[i]); i++) { printk_debug("Disabling VPCI device: 0x%08X\n", sb->unwanted_vpci[i]); outl(sb->unwanted_vpci[i] + 0x7C, 0xCF8); - outl(0xDEADBEEF, 0xCFC); + outl(0xDEADBEEF, 0xCFC); } } @@ -173,7 +599,8 @@ static void southbridge_init(struct device *dev) static void southbridge_enable(struct device *dev) { printk_err("cs5536: %s: dev is %p\n", __FUNCTION__, dev); - } + +} static void cs5536_pci_dev_enable_resources(device_t dev) { @@ -183,23 +610,23 @@ static void cs5536_pci_dev_enable_resources(device_t dev) } static struct device_operations southbridge_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, .enable_resources = cs5536_pci_dev_enable_resources, - .init = southbridge_init, -// .enable = southbridge_enable, - .scan_bus = scan_static_bus, + .init = southbridge_init, +// .enable = southbridge_enable, + .scan_bus = scan_static_bus, }; static struct pci_driver cs5536_pci_driver __pci_driver = { - .ops = &southbridge_ops, + .ops = &southbridge_ops, .vendor = PCI_VENDOR_ID_AMD, .device = PCI_DEVICE_ID_AMD_CS5536_ISA }; struct chip_operations southbridge_amd_cs5536_ops = { CHIP_NAME("AMD Geode CS5536 Southbridge") - /* This only called when this device is listed in the + /* This is only called when this device is listed in the * static device tree. */ .enable_dev = southbridge_enable, diff --git a/src/southbridge/amd/cs5536/cs5536.h b/src/southbridge/amd/cs5536/cs5536.h index 10259c6e6d..17d1922b7a 100644 --- a/src/southbridge/amd/cs5536/cs5536.h +++ b/src/southbridge/amd/cs5536/cs5536.h @@ -1,4 +1,471 @@ +/* +* This file is part of the LinuxBIOS project. +* +* Copyright (C) 2007 Advanced Micro Devices +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + #ifndef _CS5536_H #define _CS5536_H -#endif +#define Cx5536_ID ( 0x208F1022) + +/* SouthBridge Equates */ +#define CS5536_GLINK_PORT_NUM 0x02 /* port of the SouthBridge */ +#define NB_PCI ((2 << 29) + (4 << 26)) /* NB GLPCI is in the same location on all Geodes. */ +#define MSR_SB ((CS5536_GLINK_PORT_NUM << 23) + NB_PCI) /* address to the SouthBridge */ +#define SB_SHIFT 20 /* 29 -> 26 -> 23 -> 20...... When making a SB address uses this shift. */ + +#define CS5536_DEV_NUM 0x0F /* default PCI device number for CS5536 */ +#define SMBUS_IO_BASE 0x6000 +#define GPIO_IO_BASE 0x6100 +#define MFGPT_IO_BASE 0x6200 +#define ACPI_IO_BASE 0x9C00 +#define PMS_IO_BASE 0x9D00 + +#define CS5535_IDSEL 0x02000000 // IDSEL = AD25, device #15 +#define CHIPSET_DEV_NUM 15 +#define IDSEL_BASE 11 // bit 11 = device 1 + +/* Cs5536 as follows. */ +/* SB_GLIU */ +/* port0 - GLIU */ +/* port1 - GLPCI */ +/* port2 - USB Controller #2 */ +/* port3 - ATA-5 Controller */ +/* port4 - MDD */ +/* port5 - AC97 */ +/* port6 - USB Controller #1 */ +/* port7 - GLCP */ + +#define MSR_SB_GLIU ((9 << 14) + MSR_SB) /* 51024xxx or 510*xxxx - fake out just like GL0 on CPU. */ +#define MSR_SB_GLPCI (MSR_SB) /* 5100xxxx - don't go to the GLIU */ +#define MSR_SB_USB2 ((2 << SB_SHIFT) + MSR_SB) /* 5120xxxx */ +#define MSR_SB_ATA ((3 << SB_SHIFT) + MSR_SB) /* 5130xxxx */ +#define MSR_SB_MDD ((4 << SB_SHIFT) + MSR_SB) /* 5140xxxx, a.k.a. DIVIL = Diverse Integrated Logic device */ +#define MSR_SB_AC97 ((5 << SB_SHIFT) + MSR_SB) /* 5150xxxx */ +#define MSR_SB_USB1 ((6 << SB_SHIFT) + MSR_SB) /* 5160xxxx */ +#define MSR_SB_GLCP ((7 << SB_SHIFT) + MSR_SB) /* 5170xxxx */ + +/* */ +/* GLIU*/ +/* */ +#define GLIU_SB_GLD_MSR_CAP (MSR_SB_GLIU + 0x00) +#define GLIU_SB_GLD_MSR_CONF (MSR_SB_GLIU + 0x01) +#define GLIU_SB_GLD_MSR_PM (MSR_SB_GLIU + 0x04) + +/* */ +/* USB1*/ +/* */ +#define USB1_SB_GLD_MSR_CAP (MSR_SB_USB1 + 0x00) +#define USB1_SB_GLD_MSR_CONF (MSR_SB_USB1 + 0x01) +#define USB1_SB_GLD_MSR_PM (MSR_SB_USB1 + 0x04) + +/* */ +/* USB2*/ +/* */ +#define USB2_SB_GLD_MSR_CAP (MSR_SB_USB2 + 0x00) +#define USB2_SB_GLD_MSR_CONF (MSR_SB_USB2 + 0x01) + #define USB2_UPPER_SSDEN_SET (1 << 3 ) /* Bit 35 */ +#define USB2_SB_GLD_MSR_PM (MSR_SB_USB2 + 0x04) +#define USB2_SB_GLD_MSR_DIAG (MSR_SB_USB2 + 0x05) +#define USB2_SB_GLD_MSR_OHCI_BASE (MSR_SB_USB2 + 0x08) +#define USB2_SB_GLD_MSR_EHCI_BASE (MSR_SB_USB2 + 0x09) +#define USB2_SB_GLD_MSR_DEVCTL_BASE (MSR_SB_USB2 + 0x0A) +#define USB2_SB_GLD_MSR_UOC_BASE (MSR_SB_USB2 + 0x0B) /* Option controller base */ + +/* */ +/* ATA*/ +/* */ +#define ATA_SB_GLD_MSR_CAP (MSR_SB_ATA + 0x00) +#define ATA_SB_GLD_MSR_CONF (MSR_SB_ATA + 0x01) +#define ATA_SB_GLD_MSR_ERR (MSR_SB_ATA + 0x03) +#define ATA_SB_GLD_MSR_PM (MSR_SB_ATA + 0x04) + +/* */ +/* AC97*/ +/* */ +#define AC97_SB_GLD_MSR_CAP (MSR_SB_AC97 + 0x00) +#define AC97_SB_GLD_MSR_CONF (MSR_SB_AC97 + 0x01) +#define AC97_SB_GLD_MSR_PM (MSR_SB_AC97 + 0x04) + +/* */ +/* GLPCI*/ +/* */ +#define GLPCI_SB_GLD_MSR_CAP (MSR_SB_GLPCI + 0x00) +#define GLPCI_SB_GLD_MSR_CONF (MSR_SB_GLPCI + 0x01) +#define GLPCI_SB_GLD_MSR_PM (MSR_SB_GLPCI + 0x04) +#define GLPCI_SB_CTRL (MSR_SB_GLPCI + 0x10) +#define GLPCI_CRTL_PPIDE_SET (1 << 17) +/* */ +/* GLCP*/ +/* */ +#define GLCP_SB_GLD_MSR_CAP (MSR_SB_GLCP + 0x00) +#define GLCP_SB_GLD_MSR_CONF (MSR_SB_GLCP + 0x01) +#define GLCP_SB_GLD_MSR_PM (MSR_SB_GLCP + 0x04) +#define GLCP_SB_CLKOFF (MSR_SB_GLCP + 0x10) + +/* */ +/* MDD*/ +/* */ +#define MDD_SB_GLD_MSR_CAP (MSR_SB_MDD + 0x00) +#define MDD_SB_GLD_MSR_CONF (MSR_SB_MDD + 0x01) +#define MDD_SB_GLD_MSR_PM (MSR_SB_MDD + 0x04) +#define LBAR_EN (0x01) +#define IO_MASK (0x1f) +#define MEM_MASK (0x0FFFFF) +#define MDD_LBAR_IRQ (MSR_SB_MDD + 0x08) +#define MDD_LBAR_KEL1 (MSR_SB_MDD + 0x09) +#define MDD_LBAR_KEL2 (MSR_SB_MDD + 0x0A) +#define MDD_LBAR_SMB (MSR_SB_MDD + 0x0B) +#define MDD_LBAR_GPIO (MSR_SB_MDD + 0x0C) +#define MDD_LBAR_MFGPT (MSR_SB_MDD + 0x0D) +#define MDD_LBAR_ACPI (MSR_SB_MDD + 0x0E) +#define MDD_LBAR_PMS (MSR_SB_MDD + 0x0F) + +#define MDD_LBAR_FLSH0 (MSR_SB_MDD + 0x010) +#define MDD_LBAR_FLSH1 (MSR_SB_MDD + 0x011) +#define MDD_LBAR_FLSH2 (MSR_SB_MDD + 0x012) +#define MDD_LBAR_FLSH3 (MSR_SB_MDD + 0x013) +#define MDD_LEG_IO (MSR_SB_MDD + 0x014) +#define MDD_PIN_OPT (MSR_SB_MDD + 0x015) +#define MDD_SOFT_IRQ (MSR_SB_MDD + 0x016) +#define MDD_SOFT_RESET (MSR_SB_MDD + 0x017) +#define MDD_NORF_CNTRL (MSR_SB_MDD + 0x018) +#define MDD_NORF_T01 (MSR_SB_MDD + 0x019) +#define MDD_NORF_T23 (MSR_SB_MDD + 0x01A) +#define MDD_NANDF_DATA (MSR_SB_MDD + 0x01B) +#define MDD_NADF_CNTL (MSR_SB_MDD + 0x01C) +#define MDD_AC_DMA (MSR_SB_MDD + 0x01E) +#define MDD_KEL_CNTRL (MSR_SB_MDD + 0x01F) + +#define MDD_IRQM_YLOW (MSR_SB_MDD + 0x020) +#define MDD_IRQM_YHIGH (MSR_SB_MDD + 0x021) +#define MDD_IRQM_ZLOW (MSR_SB_MDD + 0x022) +#define MDD_IRQM_ZHIGH (MSR_SB_MDD + 0x023) +#define MDD_IRQM_PRIM (MSR_SB_MDD + 0x024) +#define MDD_IRQM_LPC (MSR_SB_MDD + 0x025) +#define MDD_IRQM_LXIRR (MSR_SB_MDD + 0x026) +#define MDD_IRQM_HXIRR (MSR_SB_MDD + 0x027) + +#define MDD_MFGPT_IRQ (MSR_SB_MDD + 0x028) +#define MDD_MFGPT_NR (MSR_SB_MDD + 0x029) +#define MDD_MFGPT_RES0 (MSR_SB_MDD + 0x02A) +#define MDD_MFGPT_RES1 (MSR_SB_MDD + 0x02B) + +#define MDD_FLOP_S3F2 (MSR_SB_MDD + 0x030) +#define MDD_FLOP_S3F7 (MSR_SB_MDD + 0x031) +#define MDD_FLOP_S372 (MSR_SB_MDD + 0x032) +#define MDD_FLOP_S377 (MSR_SB_MDD + 0x033) + +#define MDD_PIC_S (MSR_SB_MDD + 0x034) +#define MDD_PIT_S (MSR_SB_MDD + 0x036) +#define MDD_PIT_CNTRL (MSR_SB_MDD + 0x037) + +#define MDD_UART1_MOD (MSR_SB_MDD + 0x038) +#define MDD_UART1_DON (MSR_SB_MDD + 0x039) +#define MDD_UART1_CONF (MSR_SB_MDD + 0x03A) +#define MDD_UART2_MOD (MSR_SB_MDD + 0x03C) +#define MDD_UART2_DON (MSR_SB_MDD + 0x03D) +#define MDD_UART2_CONF (MSR_SB_MDD + 0x03E) + +#define MDD_DMA_MAP (MSR_SB_MDD + 0x040) +#define MDD_DMA_SHAD1 (MSR_SB_MDD + 0x041) +#define MDD_DMA_SHAD2 (MSR_SB_MDD + 0x042) +#define MDD_DMA_SHAD3 (MSR_SB_MDD + 0x043) +#define MDD_DMA_SHAD4 (MSR_SB_MDD + 0x044) +#define MDD_DMA_SHAD5 (MSR_SB_MDD + 0x045) +#define MDD_DMA_SHAD6 (MSR_SB_MDD + 0x046) +#define MDD_DMA_SHAD7 (MSR_SB_MDD + 0x047) +#define MDD_DMA_SHAD8 (MSR_SB_MDD + 0x048) +#define MDD_DMA_SHAD9 (MSR_SB_MDD + 0x049) + +#define MDD_LPC_EADDR (MSR_SB_MDD + 0x04C) +#define MDD_LPC_ESTAT (MSR_SB_MDD + 0x04D) +#define MDD_LPC_SIRQ (MSR_SB_MDD + 0x04E) +#define MDD_LPC_RES (MSR_SB_MDD + 0x04F) + +#define MDD_PML_TMR (MSR_SB_MDD + 0x050) +#define MDD_RTC_RAM_LO_CK (MSR_SB_MDD + 0x054) +#define MDD_RTC_DOMA_IND (MSR_SB_MDD + 0x055) +#define MDD_RTC_MONA_IND (MSR_SB_MDD + 0x056) +#define MDD_RTC_CENTURY_OFFSET (MSR_SB_MDD + 0x057) + + +/* ***********************************************************/ +/* LBUS Device Equates - */ +/* ***********************************************************/ + +/* */ +/* SMBus*/ +/* */ + +#define SMB_SDA 0x00 +#define SMB_STS 0x01 +#define SMB_STS_SLVSTP (0x01 << 7) +#define SMB_STS_SDAST (0x01 << 6) +#define SMB_STS_BER (0x01 << 5) +#define SMB_STS_NEGACK (0x01 << 4) +#define SMB_STS_STASTR (0x01 << 3) +#define SMB_STS_NMATCH (0x01 << 2) +#define SMB_STS_MASTER (0x01 << 1) +#define SMB_STS_XMIT (0x01 << 0) + +#define SMB_CTRL_STS 0x02 +#define SMB_CSTS_TGSCL (0x01 << 5) +#define SMB_CSTS_TSDA (0x01 << 4) +#define SMB_CSTS_GCMTCH (0x01 << 3) +#define SMB_CSTS_MATCH (0x01 << 2) +#define SMB_CSTS_BB (0x01 << 1) +#define SMB_CSTS_BUSY (0x01 << 0) + +#define SMB_CTRL1 0x03 +#define SMB_CTRL1_STASTRE (0x01 << 7) +#define SMB_CTRL1_NMINTE (0x01 << 6) +#define SMB_CTRL1_GCMEN (0x01 << 5) +#define SMB_CTRL1_ACK (0x01 << 4) +#define SMB_CTRL1_RSVD (0x01 << 3) +#define SMB_CTRL1_INTEN (0x01 << 2) +#define SMB_CTRL1_STOP (0x01 << 1) +#define SMB_CTRL1_START (0x01 << 0) + +#define SMB_ADD 0x04 +#define SMB_ADD_SAEN (0x01 << 7) + +#define SMB_CTRL2 0x05 +#define SMB_CTRL2_ENABLE (0x01 << 0) + +#define SMB_CTRL3 0x06 + +/* */ +/* GPIO*/ +/* */ + +#define GPIOL_0_SET (1 << 0) +#define GPIOL_1_SET (1 << 1) +#define GPIOL_2_SET (1 << 2) +#define GPIOL_3_SET (1 << 3) +#define GPIOL_4_SET (1 << 4) +#define GPIOL_5_SET (1 << 5) +#define GPIOL_6_SET (1 << 6) +#define GPIOL_7_SET (1 << 7) +#define GPIOL_8_SET (1 << 8) +#define GPIOL_9_SET (1 << 9) +#define GPIOL_10_SET (1 << 10) +#define GPIOL_11_SET (1 << 11) +#define GPIOL_12_SET (1 << 12) +#define GPIOL_13_SET (1 << 13) +#define GPIOL_14_SET (1 << 14) +#define GPIOL_15_SET (1 << 15) + +#define GPIOL_0_CLEAR (1 << 16) +#define GPIOL_1_CLEAR (1 << 17) +#define GPIOL_2_CLEAR (1 << 18) +#define GPIOL_3_CLEAR (1 << 19) +#define GPIOL_4_CLEAR (1 << 20) +#define GPIOL_5_CLEAR (1 << 21) +#define GPIOL_6_CLEAR (1 << 22) +#define GPIOL_7_CLEAR (1 << 23) +#define GPIOL_8_CLEAR (1 << 24) +#define GPIOL_9_CLEAR (1 << 25) +#define GPIOL_10_CLEAR (1 << 26) +#define GPIOL_11_CLEAR (1 << 27) +#define GPIOL_12_CLEAR (1 << 28) +#define GPIOL_13_CLEAR (1 << 29) +#define GPIOL_14_CLEAR (1 << 30) +#define GPIOL_15_CLEAR (1 << 31) + +#define GPIOH_16_SET (1 << 0) +#define GPIOH_17_SET (1 << 1) +#define GPIOH_18_SET (1 << 2) +#define GPIOH_19_SET (1 << 3) +#define GPIOH_20_SET (1 << 4) +#define GPIOH_21_SET (1 << 5) +#define GPIOH_22_SET (1 << 6) +#define GPIOH_23_SET (1 << 7) +#define GPIOH_24_SET (1 << 8) +#define GPIOH_25_SET (1 << 9) +#define GPIOH_26_SET (1 << 10) +#define GPIOH_27_SET (1 << 11) +#define GPIOH_28_SET (1 << 12) +#define GPIOH_29_SET (1 << 13) +#define GPIOH_30_SET (1 << 14) +#define GPIOH_31_SET (1 << 15) + +#define GPIOH_16_CLEAR (1 << 16) +#define GPIOH_17_CLEAR (1 << 17) +#define GPIOH_18_CLEAR (1 << 18) +#define GPIOH_19_CLEAR (1 << 19) +#define GPIOH_20_CLEAR (1 << 20) +#define GPIOH_21_CLEAR (1 << 21) +#define GPIOH_22_CLEAR (1 << 22) +#define GPIOH_23_CLEAR (1 << 23) +#define GPIOH_24_CLEAR (1 << 24) +#define GPIOH_25_CLEAR (1 << 25) +#define GPIOH_26_CLEAR (1 << 26) +#define GPIOH_27_CLEAR (1 << 27) +#define GPIOH_28_CLEAR (1 << 28) +#define GPIOH_29_CLEAR (1 << 29) +#define GPIOH_30_CLEAR (1 << 30) +#define GPIOH_31_CLEAR (1 << 31) + + +/* GPIO LOW Bank Bit Registers*/ +#define GPIOL_OUTPUT_VALUE (0x00) +#define GPIOL_OUTPUT_ENABLE (0x04) +#define GPIOL_OUT_OPENDRAIN (0x08) +#define GPIOL_OUTPUT_INVERT_ENABLE (0x0C) +#define GPIOL_OUT_AUX1_SELECT (0x10) +#define GPIOL_OUT_AUX2_SELECT (0x14) +#define GPIOL_PULLUP_ENABLE (0x18) +#define GPIOL_PULLDOWN_ENABLE (0x1C) +#define GPIOL_INPUT_ENABLE (0x20) +#define GPIOL_INPUT_INVERT_ENABLE (0x24) +#define GPIOL_IN_FILTER_ENABLE (0x28) +#define GPIOL_IN_EVENTCOUNT_ENABLE (0x2C) +#define GPIOL_READ_BACK (0x30) +#define GPIOL_IN_AUX1_SELECT (0x34) +#define GPIOL_EVENTS_ENABLE (0x38) +#define GPIOL_LOCK_ENABLE (0x3C) +#define GPIOL_IN_POSEDGE_ENABLE (0x40) +#define GPIOL_IN_NEGEDGE_ENABLE (0x44) +#define GPIOL_IN_POSEDGE_STATUS (0x48) +#define GPIOL_IN_NEGEDGE_STATUS (0x4C) + +/* GPIO High Bank Bit Registers*/ +#define GPIOH_OUTPUT_VALUE (0x80) +#define GPIOH_OUTPUT_ENABLE (0x84) +#define GPIOH_OUT_OPENDRAIN (0x88) +#define GPIOH_OUTPUT_INVERT_ENABLE (0x8C) +#define GPIOH_OUT_AUX1_SELECT (0x90) +#define GPIOH_OUT_AUX2_SELECT (0x94) +#define GPIOH_PULLUP_ENABLE (0x98) +#define GPIOH_PULLDOWN_ENABLE (0x9C) +#define GPIOH_INPUT_ENABLE (0x0A0) +#define GPIOH_INPUT_INVERT_ENABLE (0x0A4) +#define GPIOH_IN_FILTER_ENABLE (0x0A8) +#define GPIOH_IN_EVENTCOUNT_ENABLE (0x0AC) +#define GPIOH_READ_BACK (0x0B0) +#define GPIOH_IN_AUX1_SELECT (0x0B4) +#define GPIOH_EVENTS_ENABLE (0x0B8) +#define GPIOH_LOCK_ENABLE (0x0BC) +#define GPIOH_IN_POSEDGE_ENABLE (0x0C0) +#define GPIOH_IN_NEGEDGE_ENABLE (0x0C4) +#define GPIOH_IN_POSEDGE_STATUS (0x0C8) +#define GPIOH_IN_NEGEDGE_STATUS (0x0CC) + +/* Input Conditioning Function Registers*/ +#define GPIO_00_FILTER_AMOUNT (0x50) +#define GPIO_00_FILTER_COUNT (0x52) +#define GPIO_00_EVENT_COUNT (0x54) +#define GPIO_00_EVENTCOMPARE_VALUE (0x56) +#define GPIO_01_FILTER_AMOUNT (0x58) +#define GPIO_01_FILTER_COUNT (0x5A) +#define GPIO_01_EVENT_COUNT (0x5C) +#define GPIO_01_EVENTCOMPARE_VALUE (0x5E) +#define GPIO_02_FILTER_AMOUNT (0x60) +#define GPIO_02_FILTER_COUNT (0x62) +#define GPIO_02_EVENT_COUNT (0x64) +#define GPIO_02_EVENTCOMPARE_VALUE (0x66) +#define GPIO_03_FILTER_AMOUNT (0x68) +#define GPIO_03_FILTER_COUNT (0x6A) +#define GPIO_03_EVENT_COUNT (0x6C) +#define GPIO_03_EVENTCOMPARE_VALUE (0x6E) +#define GPIO_04_FILTER_AMOUNT (0x70) +#define GPIO_04_FILTER_COUNT (0x72) +#define GPIO_04_EVENT_COUNT (0x74) +#define GPIO_04_EVENTCOMPARE_VALUE (0x76) +#define GPIO_05_FILTER_AMOUNT (0x78) +#define GPIO_05_FILTER_COUNT (0x7A) +#define GPIO_05_EVENT_COUNT (0x7C) +#define GPIO_05_EVENTCOMPARE_VALUE (0x7E) +#define GPIO_06_FILTER_AMOUNT (0x0D0) +#define GPIO_06_FILTER_COUNT (0x0D2) +#define GPIO_06_EVENT_COUNT (0x0D4) +#define GPIO_06_EVENTCOMPARE_VALUE (0x0D6) +#define GPIO_07_FILTER_AMOUNT (0x0D8) +#define GPIO_07_FILTER_COUNT (0x0DA) +#define GPIO_07_EVENT_COUNT (0x0DC) +#define GPIO_07_EVENTCOMPARE_VALUE (0x0DE) + +/* R/W GPIO Interrupt &PME Mapper Registers*/ +#define GPIO_MAPPER_X (0x0E0) +#define GPIO_MAPPER_Y (0x0E4) +#define GPIO_MAPPER_Z (0x0E8) +#define GPIO_MAPPER_W (0x0EC) +#define GPIO_FE_SELECT_0 (0x0F0) +#define GPIO_FE_SELECT_1 (0x0F1) +#define GPIO_FE_SELECT_2 (0x0F2) +#define GPIO_FE_SELECT_3 (0x0F3) +#define GPIO_FE_SELECT_4 (0x0F4) +#define GPIO_FE_SELECT_5 (0x0F5) +#define GPIO_FE_SELECT_6 (0x0F6) +#define GPIO_FE_SELECT_7 (0x0F7) + +/* Event Counter Decrement Registers*/ +#define GPIOL_IN_EVENT_DECREMENT (0x0F8) +#define GPIOH_IN_EVENT_DECREMENT (0x0FC) + +/* PMC register*/ +#define PM_SSD (0x00) +#define PM_SCXA (0x04) +#define PM_SCYA (0x08) +#define PM_SODA (0x0C) +#define PM_SCLK (0x10) +#define PM_SED (0x14) +#define PM_SCXD (0x18) +#define PM_SCYD (0x1C) +#define PM_SIDD (0x20) +#define PM_WKD (0x30) +#define PM_WKXD (0x34) +#define PM_RD (0x38) +#define PM_WKXA (0x3C) +#define PM_FSD (0x40) +#define PM_TSD (0x44) +#define PM_PSD (0x48) +#define PM_NWKD (0x4C) +#define PM_AWKD (0x50) +#define PM_SSC (0x54) + + +/* FLASH device macros */ +#define FLASH_TYPE_NONE 0 /* No flash device installed */ +#define FLASH_TYPE_NAND 1 /* NAND device */ +#define FLASH_TYPE_NOR 2 /* NOR device */ + +#define FLASH_IF_MEM 1 /* Memory or memory-mapped I/O interface for Flash device */ +#define FLASH_IF_IO 2 /* I/O interface for Flash device */ + +/* Flash Memory Mask values */ +#define FLASH_MEM_DEFAULT 0x00000000 +#define FLASH_MEM_4K 0xFFFFF000 +#define FLASH_MEM_8K 0xFFFFE000 +#define FLASH_MEM_16K 0xFFFFC000 +#define FLASH_MEM_128K 0xFFFE0000 +#define FLASH_MEM_512K 0xFFFC0000 +#define FLASH_MEM_4M 0xFFC00000 +#define FLASH_MEM_8M 0xFF800000 +#define FLASH_MEM_16M 0xFF000000 + +/* Flash IO Mask values */ +#define FLASH_IO_DEFAULT 0x00000000 +#define FLASH_IO_16B 0x0000FFF0 +#define FLASH_IO_32B 0x0000FFE0 +#define FLASH_IO_64B 0x0000FFC0 +#define FLASH_IO_128B 0x0000FF80 +#define FLASH_IO_256B 0x0000FF00 + + +#endif /* _CS5536_H */ diff --git a/src/southbridge/amd/cs5536/cs5536_early_setup.c b/src/southbridge/amd/cs5536/cs5536_early_setup.c index 241b345b8e..b2b3fe6468 100644 --- a/src/southbridge/amd/cs5536/cs5536_early_setup.c +++ b/src/southbridge/amd/cs5536/cs5536_early_setup.c @@ -1,23 +1,31 @@ +/* +* This file is part of the LinuxBIOS project. +* +* Copyright (C) 2007 Advanced Micro Devices +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* - * * cs5536_early_setup.c: Early chipset initialization for CS5536 companion device - * - * - * This file implements the initialization sequence documented in section 4.2 of - * AMD Geode GX Processor CS5536 Companion Device GoedeROM Porting Guide. - * + * This file implements the initialization sequence documented in section 4.2 of + * AMD Geode GX Processor CS5536 Companion Device GoedeROM Porting Guide. */ -#define CS5536_GLINK_PORT_NUM 0x02 /* the geode link port number to the CS5536 */ -#define CS5536_DEV_NUM 0x0F /* default PCI device number for CS5536 */ - /** * @brief Setup PCI IDSEL for CS5536 - * - * */ - static void cs5536_setup_extmsr(void) { msr_t msr; @@ -25,11 +33,11 @@ static void cs5536_setup_extmsr(void) /* forward MSR access to CS5536_GLINK_PORT_NUM to CS5536_DEV_NUM */ msr.hi = msr.lo = 0x00000000; if (CS5536_GLINK_PORT_NUM <= 4) { - msr.lo = CS5536_DEV_NUM << ((CS5536_GLINK_PORT_NUM - 1) * 8); + msr.lo = CS5536_DEV_NUM << (unsigned char)((CS5536_GLINK_PORT_NUM - 1) * 8); } else { - msr.hi = CS5536_DEV_NUM << ((CS5536_GLINK_PORT_NUM - 5) * 8); + msr.hi = CS5536_DEV_NUM << (unsigned char)((CS5536_GLINK_PORT_NUM - 5) * 8); } - wrmsr(0x5000201e, msr); + wrmsr(GLPCI_ExtMSR, msr); } static void cs5536_setup_idsel(void) @@ -42,212 +50,156 @@ static void cs5536_usb_swapsif(void) { msr_t msr; - msr = rdmsr(0x51600005); + msr = rdmsr(USB1_SB_GLD_MSR_CAP + 0x5); //USB Serial short detect bit. if (msr.hi & 0x10) { - /* We need to preserve bits 32,33,35 and not clear any BIST error, but clear the - * SERSHRT error bit */ + /* We need to preserve bits 32,33,35 and not clear any BIST + * error, but clear the SERSHRT error bit */ + msr.hi &= 0xFFFFFFFB; - wrmsr(0x51600005, msr); + wrmsr(USB1_SB_GLD_MSR_CAP + 0x5, msr); } } -static int cs5536_setup_iobase(void) +static void cs5536_setup_iobase(void) { msr_t msr; - /* setup LBAR for SMBus controller */ - __builtin_wrmsr(0x5140000b, 0x00006000, 0x0000f001); + msr.hi = 0x0000f001; + msr.lo = SMBUS_IO_BASE; + wrmsr(MDD_LBAR_SMB, msr); + /* setup LBAR for GPIO */ - __builtin_wrmsr(0x5140000c, 0x00006100, 0x0000f001); + msr.hi = 0x0000f001; + msr.lo = GPIO_IO_BASE; + wrmsr(MDD_LBAR_GPIO, msr); + /* setup LBAR for MFGPT */ - __builtin_wrmsr(0x5140000d, 0x00006200, 0x0000f001); + msr.hi = 0x0000f001; + msr.lo = MFGPT_IO_BASE; + wrmsr(MDD_LBAR_MFGPT, msr); + /* setup LBAR for ACPI */ - __builtin_wrmsr(0x5140000e, 0x00009c00, 0x0000f001); + msr.hi = 0x0000f001; + msr.lo = ACPI_IO_BASE; + wrmsr(MDD_LBAR_ACPI, msr); + /* setup LBAR for PM Support */ - __builtin_wrmsr(0x5140000f, 0x00009d00, 0x0000f001); + msr.hi = 0x0000f001; + msr.lo = PMS_IO_BASE; + wrmsr(MDD_LBAR_PMS, msr); } -static void cs5536_setup_power_bottun(void) +static void cs5536_setup_power_button(void) { - /* not implemented yet */ -#if 0 - pwrBtn_setup: - ; - ; Power Button Setup - ; - ;mov eax, 0C0020000h ; 4 seconds + lock - mov eax, 040020000h ; 4 seconds no lock - mov dx, PMLogic_BASE + 40h - out dx, eax + /* Power Button Setup */ + outl(0x40020000, PMS_IO_BASE + 0x40); - ; setup GPIO24, it is the external signal for 5536 vsb_work_aux + /* setup GPIO24, it is the external signal for 5536 vsb_work_aux ; which controls all voltage rails except Vstandby & Vmem. ; We need to enable, OUT_AUX1 and OUTPUT_ENABLE in this order. - ; If GPIO24 is not enabled then soft-off will not work. - mov dx, GPIOH_OUT_AUX1_SELECT - mov eax, GPIOH_24_SET - out dx, eax - mov dx, GPIOH_OUTPUT_ENABLE - out dx, eax + ; If GPIO24 is not enabled then soft-off will not work. */ + outl(GPIOH_24_SET, GPIO_IO_BASE + GPIOH_OUT_AUX1_SELECT); + outl(GPIOH_24_SET, GPIO_IO_BASE + GPIOH_OUTPUT_ENABLE); -#endif } static void cs5536_setup_gpio(void) { uint32_t val; - /* setup GPIO pins 14/15 for SDA/SCL */ - val = (1<<14 | 1<<15); - /* Output Enable */ - outl(0x3fffc000, 0x6100 + 0x04); - //outl(val, 0x6100 + 0x04); - /* Output AUX1 */ - outl(0x3fffc000, 0x6100 + 0x10); - //outl(val, 0x6100 + 0x10); - /* Input Enable */ - //outl(0x0f5af0a5, 0x6100 + 0x20); - outl(0x3fffc000, 0x6100 + 0x20); - //outl(val, 0x6100 + 0x20); - /* Input AUX1 */ - //outl(0x3ffbc004, 0x6100 + 0x34); - outl(0x3fffc000, 0x6100 + 0x34); - //outl(val, 0x6100 + 0x34); - -#if 0 - /* changes proposed by Ollie; we will test this later. */ /* setup GPIO pins 14/15 for SDA/SCL */ val = GPIOL_15_SET | GPIOL_14_SET; /* Output Enable */ - //outl(0x3fffc000, 0x6100 + 0x04); - outl(val, 0x6100 + 0x04); + outl(val, GPIO_IO_BASE + GPIOL_OUT_AUX1_SELECT); /* Output AUX1 */ - //outl(0x3fffc000, 0x6100 + 0x10); - outl(val, 0x6100 + 0x10); + outl(val, GPIO_IO_BASE + GPIOL_OUTPUT_ENABLE); /* Input Enable */ - //outl(0x3fffc000, 0x6100 + 0x20); - outl(val, 0x6100 + 0x20); + outl(val, GPIO_IO_BASE + GPIOL_IN_AUX1_SELECT); /* Input AUX1 */ - //outl(0x3fffc000, 0x6100 + 0x34); - outl(val, 0x6100 + 0x34); -#endif + outl(val, GPIO_IO_BASE + GPIOL_INPUT_ENABLE); } static void cs5536_disable_internal_uart(void) { - /* not implemented yet */ -#if 0 - ; The UARTs default to enabled. - ; Disable and reset them and configure them later. (SIO init) - mov ecx, MDD_UART1_CONF - RDMSR - mov eax, 1h ; reset - WRMSR - mov eax, 0h ; disabled - WRMSR - - mov ecx, MDD_UART2_CONF - RDMSR - mov eax, 1h ; reset - WRMSR - mov eax, 0h ; disabled - WRMSR - -#endif + msr_t msr; + /* ; The UARTs default to enabled. + ; Disable and reset them and configure them later. (SIO init) */ + msr = rdmsr(MDD_UART1_CONF); + msr.lo = 1; // reset + wrmsr(MDD_UART1_CONF, msr); + msr.lo = 0; // disabled + wrmsr(MDD_UART1_CONF, msr); + + msr = rdmsr(MDD_UART2_CONF); + msr.lo = 1; // reset + wrmsr(MDD_UART2_CONF, msr); + msr.lo = 0; // disabled + wrmsr(MDD_UART2_CONF, msr); } static void cs5536_setup_cis_mode(void) { msr_t msr; - /* setup CPU interface serial to mode C on both sides */ - msr = __builtin_rdmsr(0x51000010); + /* setup CPU interface serial to mode B to match CPU */ + msr = rdmsr(GLPCI_SB_CTRL); msr.lo &= ~0x18; msr.lo |= 0x10; - __builtin_wrmsr(0x51000010, msr.lo, msr.hi); - //Only do this if we are building for 5536 - __builtin_wrmsr(0x54002010, 0x00000002, 0x00000000); + wrmsr(GLPCI_SB_CTRL, msr); } -static void dummy(void) -{ -} /* see page 412 of the cs5536 companion book */ -static int cs5536_setup_onchipuart(void) +static void cs5536_setup_onchipuart(void) { - unsigned long m; - /* + msr_t msr; + + /* Setup early for polling only mode. * 1. Eanble GPIO 8 to OUT_AUX1, 9 to IN_AUX1 - * GPIO LBAR + 0x04, LBAR + 0x10, LBAR + 0x20, LBAR + 34 + * GPIO LBAR + 0x04, LBAR + 0x10, LBAR + 0x20, LBAR + 34 * 2. Enable UART IO space in MDD - * MSR 0x51400014 bit 18:16 + * MSR 0x51400014 bit 18:16 * 3. Enable UART controller - * MSR 0x5140003A bit 0, 1 - * 4. IRQ routing on IRQ Mapper - * MSR 0x51400021 bit [27:24] + * MSR 0x5140003A bit 0, 1 */ - msr_t msr; - - /* Bit 1 = DEVEN (device enable) - * Bit 4 = EN_BANKS (allow access to the upper banks) - */ - - msr.lo = (1 << 4) | (1 << 1); - msr.hi = 0; - /* This enables COM2, but that should be done elsewhere - wrmsr(0x5140003e, msr); - */ - - /* enable COM1 */ - wrmsr(0x5140003a, msr); /* GPIO8 - UART1_TX */ /* Set: Output Enable (0x4) */ - m = inl(GPIOL_OUTPUT_ENABLE); - m |= GPIOL_8_SET; - m &= ~GPIOL_8_CLEAR; - outl(m,GPIOL_OUTPUT_ENABLE); + outl(GPIOL_8_SET, GPIO_IO_BASE + GPIOL_OUTPUT_ENABLE); /* Set: OUTAUX1 Select (0x10) */ - m = inl(GPIOL_OUT_AUX1_SELECT); - m |= GPIOL_8_SET; - m &= ~GPIOL_8_CLEAR; - outl(m,GPIOL_OUT_AUX1_SELECT); - /* Set: Pull Up (0x18) */ - m = inl(GPIOL_PULLUP_ENABLE); - m |= GPIOL_8_SET; - m &= ~GPIOL_8_CLEAR; + outl(GPIOL_8_SET, GPIO_IO_BASE + GPIOL_OUT_AUX1_SELECT); /* GPIO9 - UART1_RX */ - /* Set: Pull Up (0x18) */ - m |= GPIOL_9_SET; - m &= ~GPIOL_9_CLEAR; - outl(m,GPIOL_PULLUP_ENABLE); /* Set: Input Enable (0x20) */ - m = inl(GPIOL_INPUT_ENABLE); - m |= GPIOL_9_SET; - m &= ~GPIOL_9_CLEAR; - outl(m,GPIOL_INPUT_ENABLE); + outl(GPIOL_9_SET, GPIO_IO_BASE + GPIOL_INPUT_ENABLE); /* Set: INAUX1 Select (0x34) */ - m = inl(GPIOL_IN_AUX1_SELECT); - m |= GPIOL_9_SET; - m &= ~GPIOL_9_CLEAR; - outl(m,GPIOL_IN_AUX1_SELECT); + outl(GPIOL_9_SET, GPIO_IO_BASE + GPIOL_IN_AUX1_SELECT); + /* set address to 3F8 */ msr = rdmsr(MDD_LEG_IO); msr.lo |= 0x7 << 16; wrmsr(MDD_LEG_IO,msr); + + /* Bit 1 = DEVEN (device enable) + * Bit 4 = EN_BANKS (allow access to the upper banks + */ + msr.lo = (1 << 4) | (1 << 1); + msr.hi = 0; + + /* enable COM1 */ + wrmsr(MDD_UART1_CONF, msr); } -/* note: you can't do prints in here in most cases, - * and we don't want to hang on serial, so they are - * commented out +/* note: you can't do prints in here in most cases, + * and we don't want to hang on serial, so they are + * commented out */ -static int cs5536_early_setup(void) +static void cs5536_early_setup(void) { msr_t msr; cs5536_setup_extmsr(); + cs5536_setup_cis_mode(); msr = rdmsr(GLCP_SYS_RSTPLL); if (msr.lo & (0x3f << 26)) { @@ -262,9 +214,8 @@ static int cs5536_early_setup(void) cs5536_setup_iobase(); //print_debug("Setup gpio\r\n"); cs5536_setup_gpio(); - //print_debug("Setup cis_mode\r\n"); - cs5536_setup_cis_mode(); //print_debug("Setup smbus\r\n"); cs5536_enable_smbus(); - dummy(); + //print_debug("Setup power button\r\n"); + cs5536_setup_power_button(); } diff --git a/src/southbridge/amd/cs5536/cs5536_early_smbus.c b/src/southbridge/amd/cs5536/cs5536_early_smbus.c index 0605d0cb82..a7617f8c43 100644 --- a/src/southbridge/amd/cs5536/cs5536_early_smbus.c +++ b/src/southbridge/amd/cs5536/cs5536_early_smbus.c @@ -1,45 +1,215 @@ -#include "cs5536_smbus.h" +/* +* This file is part of the LinuxBIOS project. +* +* Copyright (C) 2007 Advanced Micro Devices +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "cs5536.h" + +#define SMBUS_ERROR -1 +#define SMBUS_WAIT_UNTIL_READY_TIMEOUT -2 +#define SMBUS_WAIT_UNTIL_DONE_TIMEOUT -3 +#define SMBUS_TIMEOUT (1000) -#define SMBUS_IO_BASE 0x6000 /* initialization for SMBus Controller */ -static int cs5536_enable_smbus(void) +static void cs5536_enable_smbus(void) { - unsigned char val; - - /* reset SMBUS controller */ - outb(0, SMBUS_IO_BASE + SMB_CTRL2); /* Set SCL freq and enable SMB controller */ - val = inb(SMBUS_IO_BASE + SMB_CTRL2); - val |= ((0x20 << 1) | SMB_CTRL2_ENABLE); - outb(val, SMBUS_IO_BASE + SMB_CTRL2); + /*outb((0x20 << 1) | SMB_CTRL2_ENABLE, smbus_io_base + SMB_CTRL2);*/ + outb((0x7F << 1) | SMB_CTRL2_ENABLE, SMBUS_IO_BASE + SMB_CTRL2); /* Setup SMBus host controller address to 0xEF */ - val = inb(SMBUS_IO_BASE + SMB_ADD); - val |= (0xEF | SMB_ADD_SAEN); - outb(val, SMBUS_IO_BASE + SMB_ADD); + outb((0xEF | SMB_ADD_SAEN), SMBUS_IO_BASE + SMB_ADD); + +} + +static void smbus_delay(void) +{ + /* inb(0x80); */ +} + + +static int smbus_wait(unsigned smbus_io_base) { + unsigned long loops = SMBUS_TIMEOUT; + unsigned char val; + + do { + smbus_delay(); + val = inb(smbus_io_base + SMB_STS); + if ((val & SMB_STS_SDAST) != 0) + break; + if (val & (SMB_STS_BER | SMB_STS_NEGACK)) { + /*printk_debug("SMBUS WAIT ERROR %x\n", val);*/ + return SMBUS_ERROR; + } + } while(--loops); + return loops ? 0 : SMBUS_WAIT_UNTIL_READY_TIMEOUT; +} + +/* generate a smbus start condition */ +static int smbus_start_condition(unsigned smbus_io_base) +{ + unsigned char val; + + /* issue a START condition */ + val = inb(smbus_io_base + SMB_CTRL1); + outb(val | SMB_CTRL1_START, smbus_io_base + SMB_CTRL1); + + /* check for bus conflict */ + val = inb(smbus_io_base + SMB_STS); + if ((val & SMB_STS_BER) != 0) + return SMBUS_ERROR; + + return smbus_wait(smbus_io_base); +} + +static int smbus_check_stop_condition(unsigned smbus_io_base) +{ + unsigned char val; + unsigned long loops; + loops = SMBUS_TIMEOUT; + /* check for SDA status */ + do { + smbus_delay(); + val = inb(smbus_io_base + SMB_CTRL1); + if ((val & SMB_CTRL1_STOP) == 0) { + break; + } + outb((0x7F << 1) | SMB_CTRL2_ENABLE, smbus_io_base + SMB_CTRL2); + } while(--loops); + return loops?0:SMBUS_WAIT_UNTIL_READY_TIMEOUT; +} + +static int smbus_stop_condition(unsigned smbus_io_base) +{ + outb(SMB_CTRL1_STOP, smbus_io_base + SMB_CTRL1); + return smbus_wait(smbus_io_base); } -static int smbus_read_byte(unsigned device, unsigned address) +static int smbus_ack(unsigned smbus_io_base, int state) { - return do_smbus_read_byte(SMBUS_IO_BASE, device, address-1); + unsigned char val = inb(smbus_io_base + SMB_CTRL1); + +/* if (state) */ + outb(val | SMB_CTRL1_ACK, smbus_io_base + SMB_CTRL1); +/* else + outb(val & ~SMB_CTRL1_ACK, smbus_io_base + SMB_CTRL1); +*/ + return 0; } -#if 0 -static int smbus_recv_byte(unsigned device) +static int smbus_send_slave_address(unsigned smbus_io_base, unsigned char device) { - return do_smbus_recv_byte(SMBUS_IO_BASE, device); + unsigned char val; + + /* send the slave address */ + outb(device, smbus_io_base + SMB_SDA); + + /* check for bus conflict and NACK */ + val = inb(smbus_io_base + SMB_STS); + if (((val & SMB_STS_BER) != 0) || + ((val & SMB_STS_NEGACK) != 0)) { + /* printk_debug("SEND SLAVE ERROR (%x)\n", val);*/ + return SMBUS_ERROR; + } + return smbus_wait(smbus_io_base); } -static int smbus_send_byte(unsigned device, unsigned char val) +static int smbus_send_command(unsigned smbus_io_base, unsigned char command) { - return do_smbus_send_byte(SMBUS_IO_BASE, device, val); + unsigned char val; + + /* send the command */ + outb(command, smbus_io_base + SMB_SDA); + + /* check for bus conflict and NACK */ + val = inb(smbus_io_base + SMB_STS); + if (((val & SMB_STS_BER) != 0) || + ((val & SMB_STS_NEGACK) != 0)) + return SMBUS_ERROR; + + return smbus_wait(smbus_io_base); +} + +static unsigned char smbus_get_result(unsigned smbus_io_base) +{ + return inb(smbus_io_base + SMB_SDA); } +static unsigned char do_smbus_read_byte(unsigned smbus_io_base, unsigned char device, unsigned char address) +{ + unsigned char error = 0; + + if ((smbus_check_stop_condition(smbus_io_base))) { + error = 1; + goto err; + } + + if ((smbus_start_condition(smbus_io_base))) { + error = 2; + goto err; + } + + if ((smbus_send_slave_address(smbus_io_base, device))) { + error = 3; + goto err; + } + + smbus_ack(smbus_io_base, 1 ); + + if ((smbus_send_command(smbus_io_base, address))) { + error = 4; + goto err; + } + + if ((smbus_start_condition(smbus_io_base))) { + error = 5; + goto err; + } + + if ((smbus_send_slave_address(smbus_io_base, device | 0x01))) { + error = 6; + goto err; + } -static int smbus_write_byte(unsigned device, unsigned address, unsigned char val) + if ((smbus_stop_condition(smbus_io_base))) { + error = 7; + goto err; + } + + return smbus_get_result(smbus_io_base); + + +err: + print_debug("SMBUS READ ERROR:"); + print_debug_hex8(error); + print_debug(" device:"); + print_debug_hex8(device); + print_debug("\r\n"); + /* stop, clean up the error, and leave */ + smbus_stop_condition(smbus_io_base); + outb(inb(smbus_io_base + SMB_STS), smbus_io_base + SMB_STS); + outb(0x0, smbus_io_base + SMB_STS); + return 0xFF; +} + +static inline int smbus_read_byte(unsigned device, unsigned address) { - return do_smbus_write_byte(SMBUS_IO_BASE, device, address, val); + return do_smbus_read_byte(SMBUS_IO_BASE, device, address); } -#endif + diff --git a/src/southbridge/amd/cs5536/cs5536_ide.c b/src/southbridge/amd/cs5536/cs5536_ide.c index 284b5037d8..1f4a2dbfd6 100644 --- a/src/southbridge/amd/cs5536/cs5536_ide.c +++ b/src/southbridge/amd/cs5536/cs5536_ide.c @@ -1,3 +1,22 @@ +/* +* This file is part of the LinuxBIOS project. +* +* Copyright (C) 2007 Advanced Micro Devices +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + #include #include #include @@ -5,26 +24,45 @@ #include #include "cs5536.h" +#define IDE_CFG 0x40 + #define CHANEN (1L << 1) + #define PWB (1L << 14) + #define CABLE (1L << 16) +#define IDE_DTC 0x48 +#define IDE_CAST 0x4C +#define IDE_ETC 0x50 + static void ide_init(struct device *dev) { + uint32_t ide_cfg; + printk_spew("cs5536_ide: %s\n", __FUNCTION__); + /* GPIO and IRQ setup are handled in the main chipset code. */ + + // Enable the channel and Post Write Buffer + // NOTE: Only 32-bit writes to the data buffer are allowed when PWB is set + ide_cfg = pci_read_config32(dev, IDE_CFG); + ide_cfg |= CHANEN | PWB; + pci_write_config8(dev, IDE_CFG, ide_cfg); } static void ide_enable(struct device *dev) { + printk_spew("cs5536_ide: %s\n", __FUNCTION__); + } static struct device_operations ide_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, .enable_resources = pci_dev_enable_resources, - .init = ide_init, - .enable = ide_enable, + .init = ide_init, + .enable = 0, }; static struct pci_driver ide_driver __pci_driver = { - .ops = &ide_ops, + .ops = &ide_ops, .vendor = PCI_VENDOR_ID_AMD, .device = PCI_DEVICE_ID_AMD_CS5536_IDE, }; diff --git a/src/southbridge/amd/cs5536/cs5536_smbus.h b/src/southbridge/amd/cs5536/cs5536_smbus.h deleted file mode 100644 index 9cf55ba29c..0000000000 --- a/src/southbridge/amd/cs5536/cs5536_smbus.h +++ /dev/null @@ -1,180 +0,0 @@ -//#include -#define SMBUS_ERROR -1 -#define SMBUS_WAIT_UNTIL_READY_TIMEOUT -2 -#define SMBUS_WAIT_UNTIL_DONE_TIMEOUT -3 - -#define SMB_SDA 0x00 -#define SMB_STS 0x01 -#define SMB_CTRL_STS 0x02 -#define SMB_CTRL1 0x03 -#define SMB_ADD 0x04 -#define SMB_CTRL2 0x05 -#define SMB_CTRL3 0x06 - -#define SMB_STS_SLVSTP (0x01 << 7) -#define SMB_STS_SDAST (0x01 << 6) -#define SMB_STS_BER (0x01 << 5) -#define SMB_STS_NEGACK (0x01 << 4) -#define SMB_STS_STASTR (0x01 << 3) -#define SMB_STS_NMATCH (0x01 << 2) -#define SMB_STS_MASTER (0x01 << 1) -#define SMB_STS_XMIT (0x01 << 0) - -#define SMB_CSTS_TGSCL (0x01 << 5) -#define SMB_CSTS_TSDA (0x01 << 4) -#define SMB_CSTS_GCMTCH (0x01 << 3) -#define SMB_CSTS_MATCH (0x01 << 2) -#define SMB_CSTS_BB (0x01 << 1) -#define SMB_CSTS_BUSY (0x01 << 0) - -#define SMB_CTRL1_STASTRE (0x01 << 7) -#define SMB_CTRL1_NMINTE (0x01 << 6) -#define SMB_CTRL1_GCMEN (0x01 << 5) -#define SMB_CTRL1_ACK (0x01 << 4) -#define SMB_CTRL1_RSVD (0x01 << 3) -#define SMB_CTRL1_INTEN (0x01 << 2) -#define SMB_CTRL1_STOP (0x01 << 1) -#define SMB_CTRL1_START (0x01 << 0) - -#define SMB_ADD_SAEN (0x01 << 7) - -#define SMB_CTRL2_ENABLE 0x01 - -#define SMBUS_TIMEOUT (100*1000*10) -#define SMBUS_STATUS_MASK 0xfbff - -#define SMBUS_IO_BASE 0x6000 - -static void smbus_delay(void) -{ - outb(0x80, 0x80); -} - -/* generate a smbus start condition */ -static int smbus_start_condition(unsigned smbus_io_base) -{ - unsigned char val; - unsigned long loops; - loops = SMBUS_TIMEOUT; - - /* issue a START condition */ - val = inb(smbus_io_base + SMB_CTRL1); - outb(val | SMB_CTRL1_START, smbus_io_base + SMB_CTRL1); - - /* check for bus conflict */ - val = inb(smbus_io_base + SMB_STS); - if ((val & SMB_STS_BER) != 0) - return SMBUS_ERROR; - - /* check for SDA status */ - do { - smbus_delay(); - val = inw(smbus_io_base + SMB_STS); - if ((val & SMB_STS_SDAST) != 0) { - break; - } - } while(--loops); - return loops?0:SMBUS_WAIT_UNTIL_READY_TIMEOUT; -} - -static int smbus_check_stop_condition(unsigned smbus_io_base) -{ - unsigned char val; - unsigned long loops; - loops = SMBUS_TIMEOUT; - /* check for SDA status */ - do { - smbus_delay(); - val = inw(smbus_io_base + SMB_CTRL1); - if ((val & SMB_CTRL1_STOP) == 0) { - break; - } - } while(--loops); - return loops?0:SMBUS_WAIT_UNTIL_READY_TIMEOUT; -} - -static int smbus_stop_condition(unsigned smbus_io_base) -{ - unsigned char val; - val = inb(smbus_io_base + SMB_CTRL1); - outb(SMB_CTRL1_STOP, smbus_io_base + SMB_CTRL1); -} - -static int smbus_send_slave_address(unsigned smbus_io_base, unsigned char device) -{ - unsigned char val; - unsigned long loops; - loops = SMBUS_TIMEOUT; - - /* send the slave address */ - outb(device, smbus_io_base + SMB_SDA); - - /* check for bus conflict and NACK */ - val = inb(smbus_io_base + SMB_STS); - if (((val & SMB_STS_BER) != 0) || - ((val & SMB_STS_NEGACK) != 0)) - return SMBUS_ERROR; - - /* check for SDA status */ - do { - smbus_delay(); - val = inw(smbus_io_base + SMB_STS); - if ((val & SMB_STS_SDAST) != 0) { - break; - } - } while(--loops); - return loops?0:SMBUS_WAIT_UNTIL_READY_TIMEOUT; -} - -static int smbus_send_command(unsigned smbus_io_base, unsigned char command) -{ - unsigned char val; - unsigned long loops; - loops = SMBUS_TIMEOUT; - - /* send the command */ - outb(command, smbus_io_base + SMB_SDA); - - /* check for bus conflict and NACK */ - val = inb(smbus_io_base + SMB_STS); - if (((val & SMB_STS_BER) != 0) || - ((val & SMB_STS_NEGACK) != 0)) - return SMBUS_ERROR; - - /* check for SDA status */ - do { - smbus_delay(); - val = inw(smbus_io_base + SMB_STS); - if ((val & SMB_STS_SDAST) != 0) { - break; - } - } while(--loops); - return loops?0:SMBUS_WAIT_UNTIL_READY_TIMEOUT; -} - -static unsigned char do_smbus_read_byte(unsigned smbus_io_base, unsigned char device, unsigned char address) -{ - unsigned char val, val1; - - smbus_check_stop_condition(smbus_io_base); - - smbus_start_condition(smbus_io_base); - - smbus_send_slave_address(smbus_io_base, device); - - smbus_send_command(smbus_io_base, address); - - smbus_start_condition(smbus_io_base); - - smbus_send_slave_address(smbus_io_base, device | 0x01); - - /* send NACK to slave */ - val = inb(smbus_io_base + SMB_CTRL1); - outb(val | SMB_CTRL1_ACK, smbus_io_base + SMB_CTRL1); - - val = inb(smbus_io_base + SMB_SDA); - - //smbus_stop_condition(smbus_io_base); - - return val; -} diff --git a/src/southbridge/amd/cs5536/cs5536_smbus2.h b/src/southbridge/amd/cs5536/cs5536_smbus2.h index 3f5dad002e..cb4a1e731d 100644 --- a/src/southbridge/amd/cs5536/cs5536_smbus2.h +++ b/src/southbridge/amd/cs5536/cs5536_smbus2.h @@ -43,11 +43,10 @@ #define SMBUS_TIMEOUT (100*1000*10) #define SMBUS_STATUS_MASK 0xfbff -#define SMBUS_IO_BASE 0x6000 static void smbus_delay(void) { - outb(0x80, 0x80); + inb(0x80); } static int smbus_wait(unsigned smbus_io_base) { -- cgit v1.2.3