blob: 60f7abbc5f8ca040940ad1b01bf7477d1da4dd0d [file] [log] [blame]
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2005 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <reset.h>
#include "bcm5785.h"
static void bcm5785_enable_lpc(void)
{
uint8_t byte;
device_t dev;
dev = pci_locate_device(PCI_ID(0x1166, 0x0234), 0);
/* LPC Control 0 */
byte = pci_read_config8(dev, 0x44);
/* Serial 0 */
byte |= (1<<6);
pci_write_config8(dev, 0x44, byte);
/* LPC Control 4 */
byte = pci_read_config8(dev, 0x48);
/* superio port 0x2e/4e enable */
byte |=(1<<1)|(1<<0);
pci_write_config8(dev, 0x48, byte);
}
static void bcm5785_enable_wdt_port_cf9(void)
{
device_t dev;
uint32_t dword;
uint32_t dword_old;
dev = pci_locate_device(PCI_ID(0x1166, 0x0205), 0);
dword_old = pci_read_config32(dev, 0x4c);
dword = dword_old | (1<<4); //enable Timer Func
if(dword != dword_old ) {
pci_write_config32(dev, 0x4c, dword);
}
dword_old = pci_read_config32(dev, 0x6c);
dword = dword_old | (1<<9); //unhide Timer Func in pci space
if(dword != dword_old ) {
pci_write_config32(dev, 0x6c, dword);
}
dev = pci_locate_device(PCI_ID(0x1166, 0x0238), 0);
/* enable cf9 */
pci_write_config8(dev, 0x40, (1<<2));
}
unsigned get_sbdn(unsigned bus)
{
device_t dev;
/* Find the device.
* There can only be one bcm5785 on a hypertransport chain/bus.
*/
dev = pci_locate_device_on_bus(
PCI_ID(0x1166, 0x0036),
bus);
return (dev>>15) & 0x1f;
}
#define SB_VFSMAF 0
void enable_fid_change_on_sb(unsigned sbbusn, unsigned sbdn)
{
//ACPI Decode Enable
outb(0x0e, 0xcd6);
outb((1<<3), 0xcd7);
// set port to 0x2060
outb(0x67, 0xcd6);
outb(0x60, 0xcd7);
outb(0x68, 0xcd6);
outb(0x20, 0xcd7);
outb(0x69, 0xcd6);
outb(7, 0xcd7);
outb(0x64, 0xcd6);
outb(9, 0xcd7);
}
void ldtstop_sb(void)
{
outb(1, 0x2060);
}
void hard_reset(void)
{
bcm5785_enable_wdt_port_cf9();
set_bios_reset();
/* full reset */
outb(0x0a, 0x0cf9);
outb(0x0e, 0x0cf9);
}
void soft_reset(void)
{
bcm5785_enable_wdt_port_cf9();
set_bios_reset();
#if 1
/* link reset */
// outb(0x02, 0x0cf9);
outb(0x06, 0x0cf9);
#endif
}
static void bcm5785_enable_msg(void)
{
device_t dev;
uint32_t dword;
uint32_t dword_old;
uint8_t byte;
dev = pci_locate_device(PCI_ID(0x1166, 0x0205), 0);
byte = pci_read_config8(dev, 0x42);
byte = (1<<1); //enable a20
pci_write_config8(dev, 0x42, byte);
dword_old = pci_read_config32(dev, 0x6c);
// bit 5: enable A20 Message
// bit 4: enable interrupt messages
// bit 3: enable reset init message
// bit 2: enable keyboard init message
// bit 1: enable upsteam messages
// bit 0: enable shutdowm message to init generation
dword = dword_old | (1<<5) | (1<<3) | (1<<2) | (1<<1) | (1<<0); // bit 1 and bit 4 must be set, otherwise interrupt msg will not be delivered to the processor
if(dword != dword_old ) {
pci_write_config32(dev, 0x6c, dword);
}
}
static void bcm5785_early_setup(void)
{
uint8_t byte;
uint32_t dword;
device_t dev;
//F0
// enable device on bcm5785 at first
dev = pci_locate_device(PCI_ID(0x1166, 0x0205), 0);
dword = pci_read_config32(dev, 0x64);
dword |= (1<<15) | (1<<11) | (1<<3); // ioapci enable
dword |= (1<<8); // USB enable
dword |= /* (1<<27)|*/(1<<14); // IDE enable
pci_write_config32(dev, 0x64, dword);
byte = pci_read_config8(dev, 0x84);
byte |= (1<<0); // SATA enable
pci_write_config8(dev, 0x84, byte);
// WDT and cf9 for later in coreboot_ram to call hard_reset
bcm5785_enable_wdt_port_cf9();
bcm5785_enable_msg();
// IDE related
//F0
byte = pci_read_config8(dev, 0x4e);
byte |= (1<<4); //enable IDE ext regs
pci_write_config8(dev, 0x4e, byte);
//F1
dev = pci_locate_device(PCI_ID(0x1166, 0x0214), 0);
byte = pci_read_config8(dev, 0x48);
byte &= ~1; // disable pri channel
pci_write_config8(dev, 0x48, byte);
pci_write_config8(dev, 0xb0, 0x01);
pci_write_config8(dev, 0xb2, 0x02);
byte = pci_read_config8(dev, 0x06);
byte |= (1<<4); // so b0, b2 can not be changed from now
pci_write_config8(dev, 0x06, byte);
byte = pci_read_config8(dev, 0x49);
byte |= 1; // enable second channel
pci_write_config8(dev, 0x49, byte);
//F2
dev = pci_locate_device(PCI_ID(0x1166, 0x0234), 0);
byte = pci_read_config8(dev, 0x40);
byte |= (1<<3)|(1<<2); // LPC Retry, LPC to PCI DMA enable
pci_write_config8(dev, 0x40, byte);
pci_write_config32(dev, 0x60, 0x0000ffff); // LPC Memory hole start and end
// USB related
pci_write_config8(dev, 0x90, 0x40);
pci_write_config8(dev, 0x92, 0x06);
pci_write_config8(dev, 0x9c, 0x7c); //PHY timinig register
pci_write_config8(dev, 0xa4, 0x02); //mask reg - low/full speed func
pci_write_config8(dev, 0xa5, 0x02); //mask reg - low/full speed func
pci_write_config8(dev, 0xa6, 0x00); //mask reg - high speed func
pci_write_config8(dev, 0xb4, 0x40);
}