From 19ead962c4c0331de6bd9624843f8a80608bff60 Mon Sep 17 00:00:00 2001 From: Maggie Li Date: Tue, 9 Dec 2008 21:52:42 +0000 Subject: AMD PISTACHIO mainboard support. The following ACPI features are supported: 1. S1, S4, S5 sleep and wake up (by power button). 2. Thermal configuration based on ADT7475. 3. HPET timer. 4. Interrupt routing based on ACPI table. Signed-off-by: Maggie Li Reviewed-by: Michael Xie Acked-by: Ronald G. Minnich git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3808 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/mainboard/amd/pistachio/mainboard.c | 333 ++++++++++++++++++++++++++++++++ 1 file changed, 333 insertions(+) create mode 100644 src/mainboard/amd/pistachio/mainboard.c (limited to 'src/mainboard/amd/pistachio/mainboard.c') diff --git a/src/mainboard/amd/pistachio/mainboard.c b/src/mainboard/amd/pistachio/mainboard.c new file mode 100644 index 0000000000..1b808031bc --- /dev/null +++ b/src/mainboard/amd/pistachio/mainboard.c @@ -0,0 +1,333 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "chip.h" + +#define ADT7475_ADDRESS 0x2E +#define SMBUS_IO_BASE 0x1000 + +extern u8 pm_ioread(u8 reg); +extern void pm_iowrite(u8 reg, u8 value); +extern u8 pm2_ioread(u8 reg); +extern void pm2_iowrite(u8 reg, u8 value); +extern int do_smbus_read_byte(u32 smbus_io_base, u32 device, u32 address); +extern int do_smbus_write_byte(u32 smbus_io_base, u32 device, u32 address, + u8 val); +#define ADT7475_read_byte(address) \ + do_smbus_read_byte(SMBUS_IO_BASE, ADT7475_ADDRESS, address) +#define ADT7475_write_byte(address, val) \ + do_smbus_write_byte(SMBUS_IO_BASE, ADT7475_ADDRESS, address, val) + +/******************************************************** +* pistachio uses a BCM5787 as on-board NIC. +* It has a pin named LOW_POWER to enable it into LOW POWER state. +* In order to run NIC, we should let it out of Low power state. This pin is +* controlled by GPM8. +* RPR4.2.3 GPM as GPIO +* GPM pins can be used as GPIO. The GPM I/O functions is controlled by three registers: +* I/O C50, C51, C52, PM I/O94, 95, 96. +* RPR4.2.3.1 GPM pins as Input +* RPR4.2.3.2 GPM pins as Output +* The R77 (on BRASS) / R81 (on Bronze) is not load! +* So NIC can work whether this function runs. +********************************************************/ +static void enable_onboard_nic() +{ + u8 byte; + + printk_info("enable_onboard_nic.\n"); + + /* enable GPM8 output */ + byte = pm_ioread(0x95); + byte &= 0xfe; + pm_iowrite(0x95, byte); + + /* GPM8 outputs low. */ + byte = pm_ioread(0x94); + byte &= 0xfe; + pm_iowrite(0x94, byte); +} + +/* + * set thermal config + */ +static void set_thermal_config() +{ + u8 byte, byte2; + u16 word; + u32 dword; + device_t sm_dev; + struct bus pbus; + + /* set adt7475 */ + ADT7475_write_byte(0x40, 0x04); + /* Config Register 6 */ + ADT7475_write_byte(0x10, 0x00); + /* Config Register 7 */ + ADT7475_write_byte(0x11, 0x00); + + /* set Offset 64 format, enable THERM on Remote 1& Remote 2 */ + ADT7475_write_byte(0x7c, 0xa0); + /* No offset for remote 2 */ + ADT7475_write_byte(0x72, 0x00); + /* PWM 1 configuration register CPU fan controlled by CPU Thermal Diode */ + ADT7475_write_byte(0x5c, 0x02); + /* PWM 3 configuration register Case fan controlled by 690 temp */ + ADT7475_write_byte(0x5e, 0x42); + + /* remote 1 low temp limit */ + ADT7475_write_byte(0x4e, 0x00); + /* remote 1 High temp limit (90C) */ + ADT7475_write_byte(0x4f, 0x9a); + + /* remote2 Low Temp Limit */ + ADT7475_write_byte(0x52, 0x00); + /* remote2 High Limit (90C) */ + ADT7475_write_byte(0x53, 0x9a); + + /* remote 1 therm temp limit (95C) */ + ADT7475_write_byte(0x6a, 0x9f); + /* remote 2 therm temp limit (95C) */ + ADT7475_write_byte(0x6c, 0x9f); + + /* PWM 1 minimum duty cycle (37%) */ + ADT7475_write_byte(0x64, 0x60); + /* PWM 1 Maximum duty cycle (100%) */ + ADT7475_write_byte(0x38, 0xff); + /* PWM 3 minimum duty cycle (37%) */ + ADT7475_write_byte(0x66, 0x60); + /* PWM 3 Maximum Duty Cycle (100%) */ + ADT7475_write_byte(0x3a, 0xff); + + /* Remote 1 temperature Tmin (32C) */ + ADT7475_write_byte(0x67, 0x60); + /* Remote 2 temperature Tmin (32C) */ + ADT7475_write_byte(0x69, 0x60); + /* remote 1 Trange (53C ramp range) */ + ADT7475_write_byte(0x5f, 0xe8); + /* remote 2 Trange (53C ramp range) */ + ADT7475_write_byte(0x61, 0xe8); + + /* PWM2 Duty cycle */ + ADT7475_write_byte(0x65, 0x00); + /* PWM2 Disabled */ + ADT7475_write_byte(0x5d, 0x80); + /* PWM2 Max Duty Cycle */ + ADT7475_write_byte(0x39, 0x00); + + /* Config Register 3 - enable smbalert & therm */ + ADT7475_write_byte(0x78, 0x03); + /* Config Register 4 - enable therm output */ + ADT7475_write_byte(0x7d, 0x09); + /* Interrupt Mask Register 2 - Mask SMB alert for Therm Conditions, Fan 2 fault, SmbAlert Fan for Therm Timer event */ + ADT7475_write_byte(0x75, 0x2a); + /* Config Register 1 Set Start bit */ + ADT7475_write_byte(0x40, 0x05); + /* Read status register to clear any old errors */ + byte2 = ADT7475_read_byte(0x42); + byte = ADT7475_read_byte(0x41); + + /* remote 1 temperature offset */ + ADT7475_write_byte(0x70, 0x00); + + printk_info("Init adt7475 end , status 0x42 %02x, status 0x41 %02x\n", + byte2, byte); + + /* sb600 setting for thermal config. Set SB600 GPM5 to trigger ACPI event */ + /* set GPM5 as GPM5, not DDR3_memory disable */ + byte = pm_ioread(0x8f); + byte |= 1 << 6; /* enable GPE */ + pm_iowrite(0x8f, byte); + + /* GPM5 as GPIO not USB OC */ + sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0)); + dword = + pci_cf8_conf1.read32(&pbus, sm_dev->bus->secondary, + sm_dev->path.u.pci.devfn, 0x64); + dword |= 1 << 19; + pci_cf8_conf1.write32(&pbus, sm_dev->bus->secondary, + sm_dev->path.u.pci.devfn, 0x64, dword); + + /* Enable Client Management Index/Data registers */ + dword = + pci_cf8_conf1.read32(&pbus, sm_dev->bus->secondary, + sm_dev->path.u.pci.devfn, 0x78); + dword |= 1 << 11; /* Cms_enable */ + pci_cf8_conf1.write32(&pbus, sm_dev->bus->secondary, + sm_dev->path.u.pci.devfn, 0x78, dword); + + /* MiscfuncEnable */ + byte = + pci_cf8_conf1.read8(&pbus, sm_dev->bus->secondary, + sm_dev->path.u.pci.devfn, 0x41); + byte |= (1 << 5); + pci_cf8_conf1.write8(&pbus, sm_dev->bus->secondary, + sm_dev->path.u.pci.devfn, 0x41, byte); + + /* set GPM5 as input */ + /* step1: set index register 0C50h to 13h (miscellaneous control) */ + outb(0x13, 0xC50); /* CMIndex */ + /* step2: set CM data register 0C51h bits [7:6] to 01b to set Input/Out control */ + byte = inb(0xC51); /* CMData */ + byte &= 0x3f; + byte |= 1 << 6; + outb(byte, 0xC51); + /* step3: set GPM port 0C52h appropriate bits to 1 to tri-state the GPM port */ + byte = inb(0xc52); /* GpmPort */ + byte |= 1 << 5; + outb(byte, 0xc52); + /* step4: set CM data register 0C51h bits [7:6] to 00b to set GPM port for read */ + byte = inb(0xc51); + byte &= 0x3f; + outb(byte, 0xc51); + + /* trigger SCI/SMI */ + byte = pm_ioread(0x34); + byte &= 0xcf; + pm_iowrite(0x34, byte); + + /* set GPM5 to not wake from s5 */ + byte = pm_ioread(0x77); + byte &= ~(1 << 5); + pm_iowrite(0x77, byte); + + /* trigger on falling edge */ + byte = pm_ioread(0x38); + byte &= ~(1 << 2); + pm_iowrite(0x38, byte); + + /* set SB600 GPIO 64 to GPIO with pull-up */ + byte = pm2_ioread(0x42); + byte &= 0x3f; + pm2_iowrite(0x42, byte); + + /* set GPIO 64 to input */ + word = + pci_cf8_conf1.read16(&pbus, sm_dev->bus->secondary, + sm_dev->path.u.pci.devfn, 0x56); + word |= 1 << 7; + pci_cf8_conf1.write16(&pbus, sm_dev->bus->secondary, + sm_dev->path.u.pci.devfn, 0x56, word); + + /* set GPIO 64 internal pull-up */ + byte = pm2_ioread(0xf0); + byte &= 0xee; + pm2_iowrite(0xf0, byte); + + /* set Talert to be active low */ + byte = pm_ioread(0x67); + byte &= ~(1 << 5); + pm_iowrite(0x67, byte); + + /* set Talert to generate ACPI event */ + byte = pm_ioread(0x3c); + byte &= 0xf3; + pm_iowrite(0x3c, byte); + + /* THERMTRIP pin */ + /* byte = pm_ioread(0x68); + * byte |= 1 << 3; + * pm_iowrite(0x68, byte); + * + * byte = pm_ioread(0x55); + * byte |= 1 << 0; + * pm_iowrite(0x55, byte); + * + * byte = pm_ioread(0x67); + * byte &= ~( 1 << 6); + * pm_iowrite(0x67, byte); + */ +} + +/************************************************* +* enable the dedicated function in pistachio board. +* This function called early than rs690_enable. +*************************************************/ +void pistachio_enable(device_t dev) +{ + struct mainboard_amd_pistachio_config *mainboard = + (struct mainboard_amd_pistachio_config *)dev->chip_info; + + printk_info("Mainboard Pistachio Enable. dev=0x%x\n", dev); + +#if (CONFIG_GFXUMA == 1) + msr_t msr, msr2; + + /* TOP_MEM: the top of DRAM below 4G */ + msr = rdmsr(TOP_MEM); + printk_info + ("pistachio_enable, TOP MEM: msr.lo = 0x%08x, msr.hi = 0x%08x\n", + msr.lo, msr.hi); + + /* TOP_MEM2: the top of DRAM above 4G */ + msr2 = rdmsr(TOP_MEM2); + printk_info + ("pistachio_enable, TOP MEM2: msr2.lo = 0x%08x, msr2.hi = 0x%08x\n", + msr2.lo, msr2.hi); + + switch (msr.lo) { + case 0x10000000: /* 256M system memory */ + uma_memory_size = 0x2000000; /* 32M recommended UMA */ + break; + + case 0x18000000: /* 384M system memory */ + uma_memory_size = 0x4000000; /* 64M recommended UMA */ + break; + + case 0x20000000: /* 512M system memory */ + uma_memory_size = 0x4000000; /* 64M recommended UMA */ + break; + + default: /* 1GB and above system memory */ + uma_memory_size = 0x8000000; /* 128M recommended UMA */ + break; + } + + uma_memory_start = msr.lo - uma_memory_size; /* TOP_MEM1 */ + printk_info("pistachio_enable: uma size 0x%08x, memory start 0x%08x\n", + uma_memory_size, uma_memory_start); + + /* TODO: TOP_MEM2 */ +#else + uma_memory_size = 0x8000000; /* 128M recommended UMA */ + uma_memory_start = 0x38000000; /* 1GB system memory supposed */ +#endif + + enable_onboard_nic(); + + set_thermal_config(); +} + +/* +* CONFIG_CHIP_NAME defined in Option.lb. +*/ +struct chip_operations mainboard_amd_pistachio_ops = { +#if CONFIG_CHIP_NAME == 1 + CHIP_NAME("AMD pistachio Mainboard") +#endif + .enable_dev = pistachio_enable, +}; -- cgit v1.2.3