/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2007-2009 coresystems GmbH
 * Copyright (C) 2014 Google Inc.
 * Copyright (C) 2015 Intel Corporation.
 *
 * 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.
 */

// Intel SMBus Controller 0:1f.3

Device (SBUS)
{
	Name (_ADR, 0x001f0004)

#ifdef ENABLE_SMBUS_METHODS
	OperationRegion (SMBP, PCI_Config, 0x00, 0x100)
	Field(SMBP, DWordAcc, NoLock, Preserve)
	{
		Offset(0x40),
		,	2,
		I2CE,	1
	}

	OperationRegion (SMBI, SystemIO, SMBUS_IO_BASE, 0x20)
	Field (SMBI, ByteAcc, NoLock, Preserve)
	{
		HSTS,	8,	// Host Status
		,	8,
		HCNT,	8,	// Host Control
		HCMD,	8,	// Host Command
		TXSA,	8,	// Transmit Slave Address
		DAT0,	8,	// Host Data 0
		DAT1,	8,	// Host Data 1
		HBDB,	8,	// Host Block Data Byte
		PECK,	8,	// Packet Error Check
		RXSA,	8,	// Receive Slave Address
		RXDA,	16,	// Receive Slave Data
		AUXS,	8,	// Auxiliary Status
		AUXC,	8,	// Auxiliary Control
		SLPC,	8,	// SMLink Pin Control
		SBPC,	8,	// SMBus Pin Control
		SSTS,	8,	// Slave Status
		SCMD,	8,	// Slave Command
		NADR,	8,	// Notify Device Address
		NDLB,	8,	// Notify Data Low Byte
		NDLH,	8,	// Notify Data High Byte
	}

	// Kill all SMBus communication
	Method (KILL, 0, Serialized)
	{
		Or (HCNT, 0x02, HCNT)	// Send Kill
		Or (HSTS, 0xff, HSTS)	// Clean Status
	}

	// Check if last operation completed
	// return	Failure = 0, Success = 1
	Method (CMPL, 0, Serialized)
	{
		Store (4000, Local0)		// Timeout 200ms in 50us steps
		While (Local0) {
			If (And(HSTS, 0x02)) {	// Completion Status?
				Return (1)	// Operation Completed
			} Else {
				Stall (50)
				Decrement (Local0)
				If (LEqual(Local0, 0)) {
					KILL()
				}
			}
		}

		Return (0)		//  Failure
	}


	// Wait for SMBus to become ready
	Method (SRDY, 0, Serialized)
	{
		Store (200, Local0)	// Timeout 200ms
		While (Local0) {
			If (And(HSTS, 0x40)) {		// IN_USE?
				Sleep(1)		// Wait 1ms
				Decrement(Local0)	// timeout--
				If (LEqual(Local0, 0)) {
					Return (1)
				}
			} Else {
				Store (0, Local0)	// We're ready
			}
		}

		Store (4000, Local0)	// Timeout 200ms (50us * 4000)
		While (Local0) {
			If (And (HSTS, 0x01)) {		// Host Busy?
				Stall(50)		// Wait 50us
				Decrement(Local0)	// timeout--
				If (LEqual(Local0, 0)) {
					KILL()
				}
			} Else {
				Return (0)		// Success
			}
		}

		Return (1)		// Failure
	}

	// SMBus Send Byte
	// Arg0:	Address
	// Arg1:	Data
	// Return:	1 = Success, 0=Failure

	Method (SSXB, 2, Serialized)
	{

		// Is the SMBus Controller Ready?
		If (SRDY()) {
			Return (0)
		}

		// Send Byte
		Store (0, I2CE)		// SMBus Enable
		Store (0xbf, HSTS)
		Store (Arg0, TXSA)	// Write Address
		Store (Arg1, HCMD)	// Write Data

		Store (0x48, HCNT)	// Start + Byte Data Protocol

		If (CMPL()) {
			Or (HSTS, 0xff, HSTS)	// Clean up
			Return (1)		// Success
		}

		Return (0)
	}


	// SMBus Receive Byte
	// Arg0:	Address
	// Return:	0xffff = Failure, Data (8bit) = Success

	Method (SRXB, 2, Serialized)
	{

		// Is the SMBus Controller Ready?
		If (SRDY()) {
			Return (0xffff)
		}

		// Receive Byte
		Store (0, I2CE)		// SMBus Enable
		Store (0xbf, HSTS)
		Store (Or (Arg0, 1), TXSA)	// Write Address

		Store (0x44, HCNT)	// Start

		If (CMPL()) {
			Or (HSTS, 0xff, HSTS)	// Clean up
			Return (DAT0)		// Success
		}

		Return (0xffff)
	}


	// SMBus Write Byte
	// Arg0:	Address
	// Arg1:	Command
	// Arg2:	Data
	// Return:	1 = Success, 0=Failure

	Method (SWRB, 3, Serialized)
	{

		// Is the SMBus Controller Ready?
		If (SRDY()) {
			Return (0)
		}

		// Send Byte
		Store (0, I2CE)		// SMBus Enable
		Store (0xbf, HSTS)
		Store (Arg0, TXSA)	// Write Address
		Store (Arg1, HCMD)	// Write Command
		Store (Arg2, DAT0)	// Write Data

		Store (0x48, HCNT)	// Start + Byte Protocol

		If (CMPL()) {
			Or (HSTS, 0xff, HSTS)	// Clean up
			Return (1)		// Success
		}

		Return (0)
	}


	// SMBus Read Byte
	// Arg0:	Address
	// Arg1:	Command
	// Return:	0xffff = Failure, Data (8bit) = Success

	Method (SRDB, 2, Serialized)
	{

		// Is the SMBus Controller Ready?
		If (SRDY()) {
			Return (0xffff)
		}

		// Receive Byte
		Store (0, I2CE)			// SMBus Enable
		Store (0xbf, HSTS)
		Store (Or (Arg0, 1), TXSA)	// Write Address
		Store (Arg1, HCMD)		// Command

		Store (0x48, HCNT)		// Start

		If (CMPL()) {
			Or (HSTS, 0xff, HSTS)	// Clean up
			Return (DAT0)		// Success
		}

		Return (0xffff)
	}
#endif
}
