/*
 * 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);
}
