You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
971 lines
32 KiB
971 lines
32 KiB
//*****************************************************************************
|
|
//
|
|
// peci.c - Driver for the Platform Environment Control Interface (PECI)
|
|
// module.
|
|
//
|
|
// Copyright (c) 2010-2011 Texas Instruments Incorporated. All rights reserved.
|
|
// Software License Agreement
|
|
//
|
|
// Texas Instruments (TI) is supplying this software for use solely and
|
|
// exclusively on TI's microcontroller products. The software is owned by
|
|
// TI and/or its suppliers, and is protected under applicable copyright
|
|
// laws. You may not combine this software with "viral" open-source
|
|
// software in order to form a larger program.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
|
|
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
|
|
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
|
|
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
|
|
// DAMAGES, FOR ANY REASON WHATSOEVER.
|
|
//
|
|
// This is part of revision 8264 of the Stellaris Peripheral Driver Library.
|
|
//
|
|
//*****************************************************************************
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! \addtogroup peci_api
|
|
//! @{
|
|
//
|
|
//*****************************************************************************
|
|
|
|
#include "inc/hw_ints.h"
|
|
#include "inc/hw_memmap.h"
|
|
#include "inc/hw_peci.h"
|
|
#include "inc/hw_sysctl.h"
|
|
#include "inc/hw_types.h"
|
|
#include "driverlib/debug.h"
|
|
#include "driverlib/interrupt.h"
|
|
#include "driverlib/peci.h"
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// The following defines provide characteristics of the PECI module that are
|
|
// important to the driver but which can not be gleaned from the register
|
|
// definitions.
|
|
//
|
|
//*****************************************************************************
|
|
#define PECI_MAX_BAUD 2000000 // Maximum baud rate
|
|
#define PECI_MIN_BAUD 2000 // Minimum baud rate
|
|
#define PECI_MIN_RATIO 8 // Minimum baud rate divider
|
|
#define PECI_MAX_RATIO 65535 // Maximum baud rate divider
|
|
#define PECI_POLL_PRESCALE 4096 // Polling timer prescaler
|
|
#define PECI_MIN_POLL 2 // Minimum polling interval (ms)
|
|
#define PECI_MAX_POLL 1000 // Maximum polling interval (ms)
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! \internal
|
|
//! Checks a PECI domain.
|
|
//!
|
|
//! \param ulDomain is the PECI domain identifier.
|
|
//!
|
|
//! This function determines if a domain identifier is valid.
|
|
//!
|
|
//! \return Returns \b true if the domain identifier is valid and \b false
|
|
//! otherwise.
|
|
//
|
|
//*****************************************************************************
|
|
#ifdef DEBUG
|
|
static tBoolean
|
|
PECIDomainValid(unsigned long ulDomain)
|
|
{
|
|
return((ulDomain == PECI_DOMAIN_M0D0) ||
|
|
(ulDomain == PECI_DOMAIN_M0D1) ||
|
|
(ulDomain == PECI_DOMAIN_M1D0) ||
|
|
(ulDomain == PECI_DOMAIN_M1D1));
|
|
}
|
|
#endif
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Sets the configuration of the PECI module.
|
|
//!
|
|
//! \param ulBase is the base address of the PECI module.
|
|
//! \param ulPECIClk is the rate of the clock supplied to the PECI module.
|
|
//! \param ulBaud is the bit rate that should be used for the PECI transfers.
|
|
//! \param ulPoll is the polling rate, in ms, that should be used for the
|
|
//! time between PECI polls.
|
|
//! \param ulOffset is the offset to be applied to all temperature values to
|
|
//! convert from relative to absolute.
|
|
//! \param ulRetry is the number of retry attempts for a PECI transaction.
|
|
//!
|
|
//! This function initializes operation of the PECI block. It programs the bit
|
|
//! rate, polling rate and retry counts for PECI transactions. It also
|
|
//! programs the offset value to be used to translate relative temperature
|
|
//! values from PECI transactions to absolute values. At the end of this
|
|
//! function, no host/domain combinations are enabled. Each desired
|
|
//! host/domain combination can be configured/enabled with a call to
|
|
//! PECIDomainEnable().
|
|
//!
|
|
//! The peripheral clock is the same as the processor clock. This value is
|
|
//! returned by SysCtlClockGet(), or it can be explicitly hard coded if it is
|
|
//! constant and known (to save the code/execution overhead of a call to
|
|
//! SysCtlClockGet()).
|
|
//!
|
|
//! The \e ulBaud parameter defines the bit rate for the PECI transactions.
|
|
//! This value is used to calculate a divisor value based on the specified
|
|
//! \e ulPECIClk. If the exact baud rate cannot be achieved (due to rounding),
|
|
//! the baud rate is programmed to the nearest value that is less than the
|
|
//! specified value.
|
|
//!
|
|
//! The \e ulPoll parameter defines the polling rate, in milliseconds, used
|
|
//! for PECI transactions. For generation of the polling rate, the \e
|
|
//! ulPECIClk is pre-divided by \b 4096. A value of 0 disables the polling
|
|
//! feature. If the exact polling rate cannot be achieved (due to rounding),
|
|
//! the polling rate is programmed to the nearest value that is greater than
|
|
//! the specified value.
|
|
//!
|
|
//! The \e ulRetry parameter defines the number of PECI transactions that are
|
|
//! attempted before indicating an error condition.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
PECIConfigSet(unsigned long ulBase, unsigned long ulPECIClk,
|
|
unsigned long ulBaud, unsigned long ulPoll,
|
|
unsigned long ulOffset, unsigned long ulRetry)
|
|
{
|
|
unsigned long ulTemp, ulDiv;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
ASSERT(ulPECIClk != 0);
|
|
ASSERT((ulBaud != 0) && (ulBaud <= PECI_MAX_BAUD) &&
|
|
(ulBaud >= PECI_MIN_BAUD) &&
|
|
((ulBaud * 4 * PECI_MIN_RATIO) < ulPECIClk));
|
|
ASSERT((ulPoll == 0) ||
|
|
((ulPoll >= PECI_MIN_POLL) && (ulPoll <= PECI_MAX_POLL)));
|
|
|
|
//
|
|
// Generate value for the PECI Control Register.
|
|
//
|
|
ulTemp = ((ulOffset << PECI_CTL_OFFSET_S) & PECI_CTL_OFFSET_M);
|
|
ulTemp |= ((ulRetry << PECI_CTL_CRETRY_S) & PECI_CTL_CRETRY_M);
|
|
HWREG(ulBase + PECI_O_CTL) = ulTemp;
|
|
|
|
//
|
|
// Compute the divisor for the PECI baud rate clock.
|
|
// Round up, to ensure programmed baud rate is <= specified rate.
|
|
// Ensure that proper ratio is maintained for clock:baud.
|
|
//
|
|
ulDiv = (ulPECIClk + (4 * ulBaud) - 1) / (4 * ulBaud);
|
|
ulDiv = (ulDiv < PECI_MIN_RATIO) ? PECI_MIN_RATIO : ulDiv;
|
|
ulDiv = (ulDiv > PECI_MAX_RATIO) ? PECI_MAX_RATIO : ulDiv;
|
|
ulTemp = ((ulDiv << PECI_DIV_BAUD_S) & PECI_DIV_BAUD_M);
|
|
|
|
//
|
|
// Compute the divisor for the PECI polling rate.
|
|
// Round up, to ensure programmed polling rate is >= specified rate.
|
|
//
|
|
ulDiv = ((ulPoll == 0) ? 0 : ((((ulPECIClk * ulPoll) / 1000) +
|
|
(PECI_POLL_PRESCALE - 1)) /
|
|
PECI_POLL_PRESCALE));
|
|
ulTemp |= ((ulDiv << PECI_DIV_POLL_S) & PECI_DIV_POLL_M);;
|
|
HWREG(ulBase + PECI_O_DIV) = ulTemp;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Gets the current configuration of the PECI module.
|
|
//!
|
|
//! \param ulBase is the base address of the PECI module.
|
|
//! \param ulPECIClk is the rate of the clock supplied to the PECI module.
|
|
//! \param pulBaud is a pointer to storage for the bit rate.
|
|
//! \param pulPoll is a pointer to storage for the polling rate.
|
|
//! \param pulOffset is a pointer to stoarage for the offset.
|
|
//! \param pulRetry is a pointer to storage for the retry count.
|
|
//!
|
|
//! The baud rate and poll rate for the PECI module are determined, given an
|
|
//! explicitly provided peripheral clock. The returned rates are the actual
|
|
//! rates being used; they may not be the same as the requested rates, due to
|
|
//! rounding in the calculations.
|
|
//!
|
|
//! The peripheral clock is the same as the processor clock. This value is
|
|
//! returned by SysCtlClockGet(), or it can be explicitly hard coded if it is
|
|
//! constant and known (to save the code/execution overhead of a call to
|
|
//! SysCtlClockGet()).
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
PECIConfigGet(unsigned long ulBase, unsigned long ulPECIClk,
|
|
unsigned long *pulBaud, unsigned long *pulPoll,
|
|
unsigned long *pulOffset, unsigned long *pulRetry)
|
|
{
|
|
unsigned long ulTemp;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
ASSERT(ulPECIClk != 0);
|
|
ASSERT(*pulBaud != 0);
|
|
ASSERT(*pulPoll != 0);
|
|
ASSERT(*pulOffset != 0);
|
|
ASSERT(*pulRetry != 0);
|
|
|
|
//
|
|
// Retrieve the Offset and Retry values
|
|
//
|
|
ulTemp = HWREG(ulBase + PECI_O_CTL);
|
|
*pulOffset = ((ulTemp & PECI_CTL_OFFSET_M) >> PECI_CTL_OFFSET_S);
|
|
*pulRetry = ((ulTemp & PECI_CTL_CRETRY_M) >> PECI_CTL_CRETRY_S);
|
|
|
|
//
|
|
// Calculate the baud rate.
|
|
//
|
|
ulTemp = HWREG(ulBase + PECI_O_DIV);
|
|
*pulBaud = ulPECIClk / ((ulTemp & PECI_DIV_BAUD_M) >> PECI_DIV_BAUD_S);
|
|
|
|
//
|
|
// Compute the divisor for the PECI polling rate.
|
|
// Round up, to ensure programmed polling rate is >= specified rate.
|
|
//
|
|
*pulPoll = ((((ulTemp & PECI_DIV_POLL_M) >> PECI_DIV_POLL_S) * 1000) /
|
|
(ulPECIClk / PECI_POLL_PRESCALE));
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Enables bypassing of negotiation errors.
|
|
//!
|
|
//! \param ulBase is the base address of the PECI module.
|
|
//!
|
|
//! This function enables bypassing of negotiation errors that might occur
|
|
//! during a PECI transaction. When enabled, negotiation errors are ignored.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
PECIBypassEnable(unsigned long ulBase)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
|
|
//
|
|
// Enable bypass.
|
|
//
|
|
HWREG(ulBase + PECI_O_CTL) |= PECI_CTL_BYERR;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Disables bypassing of negotiation errors.
|
|
//!
|
|
//! \param ulBase is the base address of the PECI module.
|
|
//!
|
|
//! This function disables bypassing of negotiation errors that might occur
|
|
//! during a PECI transaction. When disabled, negotiation errors are reported
|
|
//! and the remainder of the transaction is aborted.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
PECIBypassDisable(unsigned long ulBase)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
|
|
//
|
|
// Disable bypass.
|
|
//
|
|
HWREG(ulBase + PECI_O_CTL) &= ~PECI_CTL_BYERR;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Sets the configuration of the specified PECI domain.
|
|
//!
|
|
//! \param ulBase is the base address of the PECI module.
|
|
//! \param ulDomain is the PECI domain that should be configured.
|
|
//! \param ulHigh is the high temperature threshold value.
|
|
//! \param ulLow is the low temperature threshold value.
|
|
//!
|
|
//! This function configures the specified PECI domain for temperature
|
|
//! monitoring operations. The values for \e ulHigh and \e ulLow can be
|
|
//! specified as values relative to the maximum temperature allowed, or they
|
|
//! can be specified as absolute temperatures if an offset was programmed
|
|
//! in the PECIConfigSet() function.
|
|
//!
|
|
//! The \e ulDomain parameter can be one of the following values:
|
|
//! \b PECI_DOMAIN_M0D0, \b PECI_DOMAIN_M0D1, \b PECI_DOMAIN_M1D0, or
|
|
//! \b PECI_DOMAIN_M1D1.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
PECIDomainConfigSet(unsigned long ulBase, unsigned long ulDomain,
|
|
unsigned long ulHigh, unsigned long ulLow)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
ASSERT(PECIDomainValid(ulDomain));
|
|
ASSERT(ulHigh <= 0xFFFF);
|
|
ASSERT(ulLow <= 0xFFFF);
|
|
ASSERT(ulHigh > ulLow);
|
|
|
|
//
|
|
// Set the HTHRESH and LTHRESH fields in the domain control/status
|
|
// register.
|
|
//
|
|
HWREG(ulBase + PECI_O_M0D0C + (ulDomain * 4)) =
|
|
(((ulHigh << PECI_M0D0C_HITHR_S) & PECI_M0D0C_HITHR_M) |
|
|
((ulLow << PECI_M0D0C_LOTHR_S) & PECI_M0D0C_LOTHR_M));
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Gets the configuration of the specified PECI domain.
|
|
//!
|
|
//! \param ulBase is the base address of the PECI module.
|
|
//! \param ulDomain is the PECI domain that should be configured.
|
|
//! \param pulHigh is a pointer to storage for the high threshold.
|
|
//! \param pulLow is a pointer to storage for the low threshold.
|
|
//!
|
|
//! This function configures the specified PECI domain for temperature
|
|
//! monitoring operations. The values for \e ulHigh and \e ulLow can be
|
|
//! specified as values relative to the maximum temperature allowed, or they
|
|
//! can be specified as absolute temperatures if an offset was programmed
|
|
//! in the PECIConfigSet() function.
|
|
//!
|
|
//! The \e ulDomain parameter can be one of the following values:
|
|
//! \b PECI_DOMAIN_M0D0, \b PECI_DOMAIN_M0D1, \b PECI_DOMAIN_M1D0, or
|
|
//! \b PECI_DOMAIN_M1D1.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
PECIDomainConfigGet(unsigned long ulBase, unsigned long ulDomain,
|
|
unsigned long *pulHigh, unsigned long *pulLow)
|
|
{
|
|
unsigned long ulTemp;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
ASSERT(PECIDomainValid(ulDomain));
|
|
ASSERT(pulHigh != 0);
|
|
ASSERT(pulLow != 0);
|
|
|
|
//
|
|
// Get the HTHRESH and LTHRESH fields in the domain control/status
|
|
// register.
|
|
//
|
|
ulTemp = HWREG(ulBase + PECI_O_M0D0C + (ulDomain * 4));
|
|
*pulHigh = ((ulTemp && PECI_M0D0C_HITHR_M) >> PECI_M0D0C_HITHR_S);
|
|
*pulLow = ((ulTemp && PECI_M0D0C_LOTHR_M) >> PECI_M0D0C_LOTHR_S);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Enables a domain within the PECI module.
|
|
//!
|
|
//! \param ulBase is the base address of the PECI module.
|
|
//! \param ulDomain is the PECI domain that should be enabled.
|
|
//!
|
|
//! This function enables the specified PECI domain for temperature monitoring
|
|
//! operations.
|
|
//!
|
|
//! The \e ulDomain parameter can be one of the following values:
|
|
//! \b PECI_DOMAIN_M0D0, \b PECI_DOMAIN_M0D1, \b PECI_DOMAIN_M1D0, or
|
|
//! \b PECI_DOMAIN_M1D1.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
PECIDomainEnable(unsigned long ulBase, unsigned long ulDomain)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
ASSERT(PECIDomainValid(ulDomain));
|
|
|
|
//
|
|
// Enable the specified domain.
|
|
//
|
|
HWREG(ulBase + PECI_O_CTL) |= (1 << ulDomain);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Disables a domain within the PECI module.
|
|
//!
|
|
//! \param ulBase is the base address of the PECI module.
|
|
//! \param ulDomain is the PECI domain that should be disabled.
|
|
//!
|
|
//! This function disables the specified PECI domain.
|
|
//!
|
|
//! The \e ulDomain parameter can be one of the following values:
|
|
//! \b PECI_DOMAIN_M0D0, \b PECI_DOMAIN_M0D1, \b PECI_DOMAIN_M1D0, or
|
|
//! \b PECI_DOMAIN_M1D1.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
PECIDomainDisable(unsigned long ulBase, unsigned long ulDomain)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
ASSERT(PECIDomainValid(ulDomain));
|
|
|
|
//
|
|
// Disable the specified domain.
|
|
//
|
|
HWREG(ulBase + PECI_O_CTL) &= ~(1 << ulDomain);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Reads the current temperature value for the specified domain.
|
|
//!
|
|
//! \param ulBase is the base address of the PECI module.
|
|
//! \param ulDomain is the PECI domain that should be disabled.
|
|
//!
|
|
//! This function returns the most recently read temperature value from the
|
|
//! specified domain.
|
|
//!
|
|
//! The \e ulDomain parameter can be one of the following values:
|
|
//! \b PECI_DOMAIN_M0D0, \b PECI_DOMAIN_M0D1, \b PECI_DOMAIN_M1D0, or
|
|
//! \b PECI_DOMAIN_M1D1.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
unsigned long
|
|
PECIDomainValueGet(unsigned long ulBase, unsigned long ulDomain)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
ASSERT(PECIDomainValid(ulDomain));
|
|
|
|
//
|
|
// Return the most recently polled temperature value
|
|
//
|
|
return(((HWREG(ulBase + PECI_O_M0D0 + (ulDomain * 4)) &
|
|
PECI_M0D0_VALUE_M)));
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Reads the maximum/error value for the specified domain.
|
|
//!
|
|
//! \param ulBase is the base address of the PECI module.
|
|
//! \param ulDomain is the PECI domain that should be disabled.
|
|
//!
|
|
//! This function returns the maximum temperature value for the specified
|
|
//! domain.
|
|
//!
|
|
//! The \e ulDomain parameter can be one of the following values:
|
|
//! \b PECI_DOMAIN_M0D0, \b PECI_DOMAIN_M0D1, \b PECI_DOMAIN_M1D0, or
|
|
//! \b PECI_DOMAIN_M1D1.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
unsigned long
|
|
PECIDomainMaxReadGet(unsigned long ulBase, unsigned long ulDomain)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
ASSERT(PECIDomainValid(ulDomain));
|
|
|
|
//
|
|
// Return the most recently polled temperature value
|
|
//
|
|
return(((HWREG(ulBase + PECI_O_M0D0 + (ulDomain * 4)) &
|
|
PECI_M0D0_MAXREAD_M) >> PECI_M0D0_MAXREAD_S));
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Clears the current temperature value for the specified domain.
|
|
//!
|
|
//! \param ulBase is the base address of the PECI module.
|
|
//! \param ulDomain is the PECI domain that should be disabled.
|
|
//!
|
|
//! This function clears the current and maximum values for the specified
|
|
//! domain.
|
|
//!
|
|
//! The \e ulDomain parameter can be one of the following values:
|
|
//! \b PECI_DOMAIN_M0D0, \b PECI_DOMAIN_M0D1, \b PECI_DOMAIN_M1D0, or
|
|
//! \b PECI_DOMAIN_M1D1.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
PECIDomainValueClear(unsigned long ulBase, unsigned long ulDomain)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
ASSERT(PECIDomainValid(ulDomain));
|
|
|
|
//
|
|
// Clear the temperature value.
|
|
//
|
|
HWREG(ulBase + PECI_O_M0D0 + (ulDomain * 4) ) &= ~PECI_M0D0_VALUE_M;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Clears the maximum/error value for the specified domain.
|
|
//!
|
|
//! \param ulBase is the base address of the PECI module.
|
|
//! \param ulDomain is the PECI domain that should be disabled.
|
|
//!
|
|
//! This function clears the current and maximum values for the specified
|
|
//! domain.
|
|
//!
|
|
//! The \e ulDomain parameter can be one of the following values:
|
|
//! \b PECI_DOMAIN_M0D0, \b PECI_DOMAIN_M0D1, \b PECI_DOMAIN_M1D0, or
|
|
//! \b PECI_DOMAIN_M1D1.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
PECIDomainMaxReadClear(unsigned long ulBase, unsigned long ulDomain)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
ASSERT(PECIDomainValid(ulDomain));
|
|
|
|
//
|
|
// Clear the maximum/error value.
|
|
//
|
|
HWREG(ulBase + PECI_O_M0D0 + (ulDomain * 4) ) &= ~PECI_M0D0_MAXREAD_M;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Registers an interrupt handler for the PECI module.
|
|
//!
|
|
//! \param ulBase specifies the PECI module base address.
|
|
//! \param pfnHandler is a pointer to the function to be called when the
|
|
//! PECI interrupt occurs.
|
|
//!
|
|
//! This function registers the handler to be called when an PECI interrupt
|
|
//! occurs. This function enables the global interrupt in the interrupt
|
|
//! controller; specific PECI interrupts must be enabled via PECIIntEnable().
|
|
//! If necessary, it is the interrupt handler's responsibility to clear the
|
|
//! interrupt source via PECIIntClear().
|
|
//!
|
|
//! \sa IntRegister() for important information about registering interrupt
|
|
//! handlers.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
PECIIntRegister(unsigned long ulBase, void (*pfnHandler)(void))
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
ASSERT(pfnHandler != 0);
|
|
|
|
//
|
|
// Register the interrupt handler.
|
|
//
|
|
IntRegister(INT_PECI0, pfnHandler);
|
|
|
|
//
|
|
// Enable the PECI interrupt.
|
|
//
|
|
IntEnable(INT_PECI0);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Unregisters an interrupt handler for the PECI module.
|
|
//!
|
|
//! \param ulBase specifies the PECI module base address.
|
|
//!
|
|
//! This function unregisters the handler to be called when a PECI interrupt
|
|
//! occurs. This function also masks off the interrupt in the interrupt
|
|
//! controller so that the interrupt handler no longer is called.
|
|
//!
|
|
//! \sa IntRegister() for important information about registering interrupt
|
|
//! handlers.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
PECIIntUnregister(unsigned long ulBase)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
|
|
//
|
|
// Disable the PECI interrupt.
|
|
//
|
|
IntDisable(INT_PECI0);
|
|
|
|
//
|
|
// Unregister the interrupt handler.
|
|
//
|
|
IntUnregister(INT_PECI0);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Enables individual PECI interrupt sources.
|
|
//!
|
|
//! \param ulBase specifies the PECI module base address.
|
|
//! \param ulIntFlags is a bit mask of the interrupt sources to be enabled.
|
|
//! \param ulIntMode is the mode for the PECI domain interrupts.
|
|
//!
|
|
//! This function enables the indicated PECI interrupt sources. Only the
|
|
//! sources that are enabled can be reflected to the processor interrupt;
|
|
//! disabled sources have no effect on the processor.
|
|
//!
|
|
//! The \e ulIntFlags parameter can be any of the following values:
|
|
//! \b PECI_READ, \b PECI_ERR, \b PECI_AC, \b PECI_M0D0, \b PECI_M0D1,
|
|
//! \b PECI_M1D0, or \b PECI_M1D1.
|
|
//!
|
|
//! The \e ulIntMode parameter is used to configure the interrupt mode for
|
|
//! the corresponding \b PECI_DOMAIN_MnDm field, and can be any of the
|
|
//! following values: \b PECI_M0D0_MODE1, \b PECI_M0D0_MODE2,
|
|
//! \b PECI_M0D0_MODE3, \b PECI_M0D1_MODE1, \b PECI_M0D1_MODE2,
|
|
//! \b PECI_M0D1_MODE3. \b PECI_M1D0_MODE1, \b PECI_M1D0_MODE2,
|
|
//! \b PECI_M1D0_MODE3, \b PECI_M1D1_MODE1, \b PECI_M1D1_MODE2, or
|
|
//! \b PECI_M1D1_MODE3.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
PECIIntEnable(unsigned long ulBase, unsigned long ulIntFlags,
|
|
unsigned long ulIntMode)
|
|
{
|
|
unsigned long ulTemp;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
|
|
//
|
|
// Get the current mask value.
|
|
//
|
|
ulTemp = HWREG(ulBase + PECI_O_IM);
|
|
|
|
//
|
|
// Clear the bit/bit-fields that are configured, based on the value
|
|
// in the flags parameter.
|
|
//
|
|
ulTemp &= ~ulIntFlags;
|
|
|
|
//
|
|
// Set/Enable the bit/bit-fields based on the value in the flags and mode
|
|
// parameter. The flags parameter alters the bits in the lower half
|
|
// of the mask, while the mode alters the bit fields in the upper
|
|
// half of the mask.
|
|
//
|
|
ulTemp |= (0x0000FFFF & ulIntFlags);
|
|
ulTemp |= (0xFFFF0000 & ulIntMode);
|
|
HWREG(ulBase + PECI_O_IM) = ulTemp;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Disables individual PECI interrupt sources.
|
|
//!
|
|
//! \param ulBase specifies the PECI module base address.
|
|
//! \param ulIntFlags is a bit mask of the interrupt sources to be disabled.
|
|
//!
|
|
//! This function disables the indicated PECI interrupt sources. Only the
|
|
//! sources that are enabled can be reflected to the processor interrupt;
|
|
//! disabled sources have no effect on the processor.
|
|
//!
|
|
//! The \e ulIntFlags parameter can be any of the following values:
|
|
//! \b PECI_READ, \b PECI_ERR, \b PECI_AC, \b PECI_M0D0, \b PECI_M0D1,
|
|
//! \b PECI_M1D0, or \b PECI_M1D1.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
PECIIntDisable(unsigned long ulBase, unsigned long ulIntFlags)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
|
|
//
|
|
// Disable the specified interrupts.
|
|
//
|
|
HWREG(ulBase + PECI_O_IM) &= ~ulIntFlags;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Gets the current interrupt status.
|
|
//!
|
|
//! \param ulBase specifies the PECI module base address.
|
|
//! \param bMasked is \b false if the raw interrupt status is required or
|
|
//! \b true if the masked interrupt status is required.
|
|
//!
|
|
//! This function returns the interrupt status for the PECI module. Either the
|
|
//! raw interrupt status or the status of interrupts that are allowed to
|
|
//! reflect to the processor can be returned.
|
|
//!
|
|
//! The interpretation of the PECI_DOMAIN_MnDm fields vary based on the mode
|
|
//! value programed using the PECIIntEnable() function for the field. Each
|
|
//! field may take on one of the following values:
|
|
//! \b PECI_MnDm_MODE1_HIGH, \b PECI_MnDm_MODE2_MID, \b PECI_MnDm_MODE2_HIGH,
|
|
//! \b PECI_MnDm_MODE3_LOW, \b PECI_MnDm_MODE3_MID, or \b PECI_MnDm_MODE3_HIGH.
|
|
//!
|
|
//! \return The current interrupt status, enumerated as a bit field of
|
|
//! \b PECI_READ, \b PECI_ERR, \b PECI_AC, \b PECI_M0D0, \b PECI_M0D1,
|
|
//! \b PECI_M1D0, or \b PECI_M1D1.
|
|
//
|
|
//*****************************************************************************
|
|
unsigned long
|
|
PECIIntStatus(unsigned long ulBase, tBoolean bMasked)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
|
|
//
|
|
// Return either the interrupt status or the raw interrupt status as
|
|
// requested.
|
|
//
|
|
if(bMasked)
|
|
{
|
|
return(HWREG(ulBase + PECI_O_MIS));
|
|
}
|
|
else
|
|
{
|
|
return(HWREG(ulBase + PECI_O_RIS));
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Clears PECI interrupt sources.
|
|
//!
|
|
//! \param ulBase specifies the PECI module base address.
|
|
//! \param ulIntFlags is a bit mask of the interrupt sources to be cleared.
|
|
//!
|
|
//! This function clears the specified PECI interrupt sources so that they no
|
|
//! longer assert. This function must be called in the interrupt handler to
|
|
//! keep the interrupts from being recognized again immediately upon exit.
|
|
//! The \e ulIntFlags parameter can consist of any combination of the
|
|
//! \b PECI_READ, \b PECI_ERR, \b PECI_AC, \b PECI_M0D0, \b PECI_M0D1,
|
|
//! \b PECI_M1D0, or \b PECI_M1D1 values.
|
|
//!
|
|
//! \note Because there is a write buffer in the Cortex-M processor, it may
|
|
//! take several clock cycles before the interrupt source is actually cleared.
|
|
//! Therefore, it is recommended that the interrupt source be cleared early in
|
|
//! the interrupt handler (as opposed to the very last action) to avoid
|
|
//! returning from the interrupt handler before the interrupt source is
|
|
//! actually cleared. Failure to do so may result in the interrupt handler
|
|
//! being immediately reentered (because the interrupt controller still sees
|
|
//! the interrupt source asserted).
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
PECIIntClear(unsigned long ulBase, unsigned long ulIntFlags)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
|
|
//
|
|
// Clear the requested interrupt sources.
|
|
//
|
|
HWREG(ulBase + PECI_O_IC) = ulIntFlags;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Sends a PECI Advanced Command.
|
|
//!
|
|
//! \param ulBase specifies the PECI module base address.
|
|
//!
|
|
//! This function sends a PECI Advanced Command. If the interface is not IDLE,
|
|
//! it waits for the interface to become IDLE then sends the command. The
|
|
//! function parameters are used to populate the message control fields before
|
|
//! activating the command.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
PECIAdvCmdSend(unsigned long ulBase, unsigned char ucCmd,
|
|
unsigned char ucHidRe, unsigned char ucDomain,
|
|
unsigned char ucProcAdd, unsigned long ulArg,
|
|
unsigned char ucSize, unsigned long ulData0,
|
|
unsigned long ulData1)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
|
|
//
|
|
// Wait for the interface to be idle.
|
|
//
|
|
while(HWREG(ulBase + PECI_O_ACCODE) == 0xFFFFFFFF)
|
|
{
|
|
}
|
|
|
|
//
|
|
// Fill in the registers for the advanced command.
|
|
//
|
|
HWREG(ulBase + PECI_O_ACARG) = ulArg;
|
|
HWREG(ulBase + PECI_O_ACRDWR0) = ulData0;
|
|
HWREG(ulBase + PECI_O_ACRDWR1) = ulData1;
|
|
HWREG(ulBase + PECI_O_ACADDR) = (ucHidRe << 24) |
|
|
(ucSize << 16) |
|
|
(ucDomain << 8) |
|
|
(ucProcAdd << 0);
|
|
|
|
//
|
|
// Now, issue the command.
|
|
//
|
|
HWREG(ulBase + PECI_O_ACCMD) = ucCmd;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Sends a PECI Advanced Command (non blocking).
|
|
//!
|
|
//! \param ulBase specifies the PECI module base address.
|
|
//!
|
|
//! This function sends a PECI Advanced Command. If the interface is not IDLE,
|
|
//! it returns immediately. Otherwise, it sends the the command. The function
|
|
//! paramters are used to populate the message control fields before activating
|
|
//! the command.
|
|
//!
|
|
//! \return None.
|
|
//
|
|
//*****************************************************************************
|
|
unsigned long
|
|
PECIAdvCmdSendNonBlocking(unsigned long ulBase, unsigned char ucCmd,
|
|
unsigned char ucHidRe, unsigned char ucDomain,
|
|
unsigned char ucProcAdd, unsigned long ulArg,
|
|
unsigned char ucSize, unsigned long ulData0,
|
|
unsigned long ulData1)
|
|
{
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
|
|
//
|
|
// Check for the interface to be idle.
|
|
// If not, return immediately.
|
|
//
|
|
if(HWREG(ulBase + PECI_O_ACCODE) == 0xFFFFFFFF)
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
//
|
|
// Send the command.
|
|
//
|
|
PECIAdvCmdSend(ulBase, ucCmd, ucHidRe, ucDomain, ucProcAdd, ulArg,
|
|
ucSize, ulData0, ulData1);
|
|
|
|
//
|
|
// Return, indicating that the command has been issued.
|
|
//
|
|
return(1);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! Obtains status of previous PECI Advanced Command.
|
|
//!
|
|
//! \param ulBase specifies the PECI module base address.
|
|
//!
|
|
//! This function gets the status of a previously issued PECI Advanced Command.
|
|
//! If the command has completed, and the data pointers are non-zero, the data
|
|
//! registers are read and saved.
|
|
//!
|
|
//! \return -1 if command has not yet been completed, otherwise, the return
|
|
//! code associated with the Advanced Command.
|
|
//
|
|
//*****************************************************************************
|
|
unsigned long
|
|
PECIAdvCmdStatusGet(unsigned long ulBase, unsigned long *pulData0,
|
|
unsigned long *pulData1)
|
|
{
|
|
unsigned long ulCode;
|
|
|
|
//
|
|
// Check the arguments.
|
|
//
|
|
ASSERT(ulBase == PECI0_BASE);
|
|
|
|
//
|
|
// If the command has completed, optionally read and save the data
|
|
// registers.
|
|
//
|
|
ulCode = HWREG(ulBase + PECI_O_ACCODE);
|
|
if(ulCode != 0xFFFFFFFF)
|
|
{
|
|
if(pulData0 != (void *)0)
|
|
{
|
|
*pulData0 = HWREG(ulBase + PECI_O_ACRDWR0);
|
|
}
|
|
if(pulData1 != (void *)0)
|
|
{
|
|
*pulData1 = HWREG(ulBase + PECI_O_ACRDWR1);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Return the command code from the most recently completed command.
|
|
//
|
|
return(ulCode);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Close the Doxygen group.
|
|
//! @}
|
|
//
|
|
//*****************************************************************************
|
|
|