📄 pmic.c
字号:
//
// Copyright (C) 2004-2007, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//------------------------------------------------------------------------------
//
// File: pmic.c
//
// This file contains the OAL support code for the PMIC interface.
//
//------------------------------------------------------------------------------
#include <bsp.h>
#include "regs.h"
#include "regs_regulator.h"
//------------------------------------------------------------------------------
// External Functions
extern VOID OALClockSetGatingMode(DDK_CLOCK_GATE_INDEX index,
DDK_CLOCK_GATE_MODE mode);
//------------------------------------------------------------------------------
// External Variables
extern BOOL g_oalPostInit;
extern CRITICAL_SECTION g_oalPmicMutex;
extern PBSP_ARGS g_pBSPARGS; // From debug.c
//------------------------------------------------------------------------------
// Defines
#define PMIC_SPI_DATA_LSH 0
#define PMIC_SPI_NULL_LSH 24
#define PMIC_SPI_ADDR_LSH 25
#define PMIC_SPI_RW_LSH 31
#define PMIC_SPI_DATA_WID 24
#define PMIC_SPI_NULL_WID 1
#define PMIC_SPI_ADDR_WID 6
#define PMIC_SPI_RW_WID 1
#define PMIC_SPI_RW_READ 0
#define PMIC_SPI_RW_WRITE 1
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
// Global Variables
//------------------------------------------------------------------------------
// Local Variables
static PCSP_CSPI_REGS g_pCSPI;
static UINT32 g_INTREG;
static DDK_CLOCK_GATE_INDEX g_CGI;
//------------------------------------------------------------------------------
// Functions
//------------------------------------------------------------------------------
//
// Function: OALPmicLock
//
// Obtains a lock for the CSPI hardware so that the OAL and PMIC core driver
// can safely share access.
//
// Parameters:
// None.
//
// Returns:
// None.
//
//------------------------------------------------------------------------------
static void OALPmicLock(void)
{
// There is no need to acquire a critical section before accessing the
// CSPI bus if the OAL is still in the initialization stage since we
// are guaranteed that no other PMIC device drivers will be running yet.
if (g_oalPostInit) {
// Must ensure exclusive access to the CSPI bus for the OAL until
// the current CSPI transaction is completed.
EnterCriticalSection(&g_oalPmicMutex);
}
OALClockSetGatingMode(g_CGI, DDK_CLOCK_GATE_MODE_ENABLE);
INSREG32BF(&g_pCSPI->CONTROLREG,
CSPI_CONTROLREG_SPIEN, CSPI_CONTROLREG_SPIEN_ENABLE);
// Store the current INT register configuration and turn
// off all interrupts
g_INTREG = INREG32(&g_pCSPI->INT);
OUTREG32(&g_pCSPI->INT, 0);
}
//------------------------------------------------------------------------------
//
// Function: OALPmicUnlock
//
// Release the lock previously obtained by OALPmicLock.
//
// Parameters:
// None.
//
// Returns:
// None.
//
//------------------------------------------------------------------------------
static void OALPmicUnlock(void)
{
// Restore INTREG configuration
OUTREG32(&g_pCSPI->INT, g_INTREG);
INSREG32BF(&g_pCSPI->CONTROLREG,
CSPI_CONTROLREG_SPIEN, CSPI_CONTROLREG_SPIEN_DISABLE);
OALClockSetGatingMode(g_CGI, DDK_CLOCK_GATE_MODE_DISABLE);
if (g_oalPostInit) {
// The current CSPI transaction has been completed. Other PMIC
// device drivers or the OAL may now access the CSPI bus.
LeaveCriticalSection(&g_oalPmicMutex);
}
}
//------------------------------------------------------------------------------
//
// Function: OALPmicCalcDiv
//
// Calculates the CSPI data rate divider needed to obtain the specified
// data transfer frequency.
//
// Parameters:
// freq
// [in] Target CSPI bit clock frequency.
//
// Returns:
// Calculated divider for the CSPI DATARATE bits.
//
//------------------------------------------------------------------------------
static UINT32 OALPmicCalcDiv(UINT32 freq)
{
UINT32 n, div, cspiClk;
// CSPI uses PERCLK2 as clock input
cspiClk = g_pBSPARGS->clockFreq[DDK_CLOCK_SIGNAL_PERDIV2];
for (n = CSPI_CONTROLREG_DATARATE_DIV4;
n < CSPI_CONTROLREG_DATARATE_DIV512; n++) {
if (n % 2)
div = 3 * (2 << (((n-1)/2 - 1))); // odd
else
div = 2 * (2 << ((n/2) - 1)); // even
if ((cspiClk / div) <= freq) break;
}
return div;
}
//------------------------------------------------------------------------------
//
// Function: OALPmicExchange
//
// Performs a data exchange with the PMIC.
//
// Parameters:
// packet
// [in] Read/Write packet sent to the PMIC
//
// data
// [in] data read from the exchange
//
// Returns:
// Returns TRUE if successful, otherwise returns FALSE.
//
//------------------------------------------------------------------------------
static BOOL OALPmicExchange(UINT32 packet, PUINT32 pData)
{
// Write the packet to the TXFIFO
OUTREG32(&g_pCSPI->TXDATA, packet);
// Start the exchange
INSREG32BF(&g_pCSPI->CONTROLREG,
CSPI_CONTROLREG_XCH, CSPI_CONTROLREG_XCH_EN);
// Wait until transaction is complete
while (!(INREG32(&g_pCSPI->INT) & CSP_BITFMASK(CSPI_INT_RR))) {
if (g_oalPostInit) {
// WinCE 6.00 does not implement the SC_Sleep() API that was
// available in WinCE 5.00 and there is no suitable alternative
// API. Note that calling NKSleep(0) simply causes this thread
// to hang. Therefore, we can only use a NO-OP here.
;
}
};
// Read the data
*pData = INREG32(&g_pCSPI->RXDATA);
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: OALPmicWrite
//
// Writes data to the specified PMIC register address.
//
// Parameters:
// addr
// [in] PMIC register address
//
// data
// [in] data to write
//
// Returns:
// Returns TRUE if successful, otherwise returns FALSE.
//
//------------------------------------------------------------------------------
BOOL OALPmicWrite(UINT32 addr, UINT32 data)
{
BOOL rc;
UINT32 temp;
UINT32 packet = CSP_BITFVAL(PMIC_SPI_RW, PMIC_SPI_RW_WRITE);
CSP_BITFINS(packet, PMIC_SPI_DATA, data);
CSP_BITFINS(packet, PMIC_SPI_ADDR, addr);
// Transfer the packet and discard the data
OALPmicLock();
rc = OALPmicExchange(packet, &temp);
OALPmicUnlock();
return rc;
}
//------------------------------------------------------------------------------
//
// Function: OALPmicRead
//
// Reads data from the specified PMIC register address.
//
// Parameters:
// addr
// [in] PMIC register address
//
// data
// [out] data read
//
// Returns:
// Returns TRUE if successful, otherwise returns FALSE.
//
//------------------------------------------------------------------------------
BOOL OALPmicRead(UINT32 addr, PUINT32 pData)
{
BOOL rc;
UINT32 packet = CSP_BITFVAL(PMIC_SPI_RW, PMIC_SPI_RW_READ);
CSP_BITFINS(packet, PMIC_SPI_ADDR, addr);
// Transfer the packet and read the data
OALPmicLock();
rc = OALPmicExchange(packet, pData);
OALPmicUnlock();
return rc;
}
//------------------------------------------------------------------------------
//
// Function: OALPmicWriteMasked
//
// Writes data to particular set of bits within a specified PMIC register
// address.
//
// Parameters:
// addr
// [in] PMIC register address
//
// mask
// [in] Bit mask for specifying the bits to be written
//
// data
// [in] data to write
//
// Returns:
// Returns TRUE if successful, otherwise returns FALSE.
//
//------------------------------------------------------------------------------
BOOL OALPmicWriteMasked(UINT32 addr, UINT32 mask, UINT32 data)
{
BOOL rc = FALSE;
UINT32 temp;
UINT32 packet = CSP_BITFVAL(PMIC_SPI_RW, PMIC_SPI_RW_READ);
CSP_BITFINS(packet, PMIC_SPI_ADDR, addr);
// Transfer the packet and read the data
OALPmicLock();
if (!OALPmicExchange(packet, &temp)) {
ERRORMSG(TRUE, (_T("OALPmicExchange failed\r\n")));
goto cleanUp;
}
CSP_BITFINS(packet, PMIC_SPI_RW, PMIC_SPI_RW_WRITE);
CSP_BITFINS(packet, PMIC_SPI_DATA, (temp & (~mask)) | (data & mask));
// Transfer the packet and discard the data
if (!OALPmicExchange(packet, &temp)) {
ERRORMSG(TRUE, (_T("OALPmicExchange failed\r\n")));
goto cleanUp;
}
rc = TRUE;
cleanUp:
OALPmicUnlock();
return rc;
}
//------------------------------------------------------------------------------
//
// Function: OALPmicSetSupplyVoltages
//
// Configures the normal and standby voltages for the CPU.
//
// Parameters:
// voltCodeNormal
// [in] Voltage code for the PMIC normal (non-DVS) voltage
//
// voltCodeStandby
// [in] Voltage code for the PMIC standby voltage
//
// Returns:
// Returns TRUE if successful, otherwise returns FALSE.
//
//------------------------------------------------------------------------------
BOOL OALPmicSetSupplyVoltages(UINT32 voltCodeNormal, UINT32 voltCodeStandby)
{
BOOL rc;
DWORD dwStart;
rc = OALPmicWriteMasked(MC13783_SW0_ADDR,
CSP_BITFMASK(MC13783_SW0_SW1A) |
CSP_BITFMASK(MC13783_SW0_SW1ASTBY),
CSP_BITFVAL(MC13783_SW0_SW1A, voltCodeNormal) |
CSP_BITFVAL(MC13783_SW0_SW1ASTBY, voltCodeStandby));
// Wait ~1 msec for the supply voltage to settle
dwStart = OALTimerGetCount();
while((OALTimerGetCount() - dwStart) < g_oalTimer.countsPerMSec);
return rc;
}
//------------------------------------------------------------------------------
//
// Function: OALPmicInit
//
// Initializes the PMIC interface for OAL communication.
//
// Parameters:
// voltCodeNormal
// [in] Voltage code for the PMIC normal (non-DVS) voltage
//
// voltCodeStandby
// [in] Voltage code for the PMIC standby voltage
//
// Returns:
// Returns TRUE if successful, otherwise returns FALSE.
//
//------------------------------------------------------------------------------
BOOL OALPmicInit(UINT32 voltCodeNormal, UINT32 voltCodeStandby)
{
BOOL rc = FALSE;
UINT32 temp;
PCSP_GPIO_REGS pGPIO;
pGPIO = (PCSP_GPIO_REGS)OALPAtoUA(CSP_BASE_REG_PA_GPIO);
// PD25 - PD31
// CSPI1_RDY, CSPI1_SS2, CSPI1_SS1, CSPI1_SS0, CSPI1_SCLK, CSPI1_MISO, CSPI1_MOSI
// Note: PD26 is muxed with USBH2_DATA5/RCV.
OAL_IOMUX_PRI_PINS(pGPIO, GPIO_PORT_D, 0xFE000000);
// CSPI1 mapping
g_pCSPI = (PCSP_CSPI_REGS)OALPAtoUA(CSP_BASE_REG_PA_CSPI1);
if (g_pCSPI == NULL) {
OALMSG(OAL_ERROR, (_T("OALPmicInit: OALPAtoUA returned NULL\r\n")));
goto cleanUp;
}
// Turn on CSPI clocks
g_CGI = DDK_CLOCK_GATE_INDEX_CSPI1;
OALClockSetGatingMode(g_CGI, DDK_CLOCK_GATE_MODE_ENABLE);
// Configure the CSPI interface and enable it before writing to
// other CSPI registers
OUTREG32(&g_pCSPI->CONTROLREG,
CSP_BITFVAL(CSPI_CONTROLREG_SPIEN, CSPI_CONTROLREG_SPIEN_ENABLE) |
CSP_BITFVAL(CSPI_CONTROLREG_MODE, CSPI_CONTROLREG_MODE_MASTER) |
CSP_BITFVAL(CSPI_CONTROLREG_XCH, CSPI_CONTROLREG_XCH_IDLE) |
CSP_BITFVAL(CSPI_CONTROLREG_POL, CSPI_CONTROLREG_POL_ACTIVE_HIGH) |
CSP_BITFVAL(CSPI_CONTROLREG_PHA, CSPI_CONTROLREG_PHA0) |
CSP_BITFVAL(CSPI_CONTROLREG_SSCTL, CSPI_CONTROLREG_SSCTL_ASSERT) |
CSP_BITFVAL(CSPI_CONTROLREG_SSPOL, CSPI_CONTROLREG_SSPOL_ACTIVE_HIGH) |
CSP_BITFVAL(CSPI_CONTROLREG_BITCOUNT, CSPI_CONTROLREG_BITCOUNT_32BIT) |
CSP_BITFVAL(CSPI_CONTROLREG_DATARATE, OALPmicCalcDiv(BSP_PMIC_CSPI_FREQ)) |
CSP_BITFVAL(CSPI_CONTROLREG_DRCTL, CSPI_CONTROLREG_DRCTL_DONTCARE) |
CSP_BITFVAL(CSPI_CONTROLREG_CS, CSPI_CONTROLREG_CS_SS0));
OUTREG32(&g_pCSPI->INT, 0);
OUTREG32(&g_pCSPI->DMA, 0);
OUTREG32(&g_pCSPI->TEST, 0);
// Turn the CSPI module and clocks off to save power between transfers
INSREG32BF(&g_pCSPI->CONTROLREG,
CSPI_CONTROLREG_SPIEN, CSPI_CONTROLREG_SPIEN_DISABLE);
OALClockSetGatingMode(g_CGI, DDK_CLOCK_GATE_MODE_DISABLE);
// Configure PC14 as CPLD_PRIINT (Note: Muxed with TOU1)
OAL_IOMUX_INTR_PIN(pGPIO, BSP_PMIC_GPIO_PORT,
BSP_PMIC_GPIO_PIN, GPIO_INT_TYPE_POSLEVEL);
rc = OALPmicSetSupplyVoltages(voltCodeNormal, voltCodeStandby);
OALPmicRead(MC13783_SW0_ADDR, &temp);
OALMSGS(OAL_INFO, (_T("SW1A voltages: 0x%x (normal = %d, DVS = %d, standby = %d)\r\n"),
temp, CSP_BITFEXT(temp, MC13783_SW0_SW1A), CSP_BITFEXT(temp, MC13783_SW0_SW1A),
CSP_BITFEXT(temp, MC13783_SW0_SW1ASTBY)));
OALPmicRead(MC13783_SW4_ADDR, &temp);
OALMSGS(OAL_INFO, (_T("SW1A configuration: 0x%x (mode = %d, standby mode = %d, DVS speed = %d, panic = %d, soft start = %d)\r\n"),
temp, CSP_BITFEXT(temp, MC13783_SW4_SW1AMODE), CSP_BITFEXT(temp, MC13783_SW4_SW1ASTBYMODE),
CSP_BITFEXT(temp, MC13783_SW4_SW1ADVSSPEED), CSP_BITFEXT(temp, MC13783_SW4_SW1APANIC),
CSP_BITFEXT(temp, MC13783_SW4_SW1ASFST)));
cleanUp:
return rc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -