📄 ixsspacc.c
字号:
/** * IxSspAcc.c * * File Version: $Revision: 0.1 $ * * Description: C file for Synchronous Serial Port (SSP) Access component (IxSspAcc) * * @par * IXP400 SW Release version 2.1 * * -- Copyright Notice -- * * @par * Copyright (c) 2001-2005, Intel Corporation. * All rights reserved. * * @par * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Intel Corporation nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * * @par * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * * @par * -- End of Copyright Notice -- */#ifdef __ixp46X#include "IxOsal.h"#include "IxSspAcc.h"#include "IxFeatureCtrl.h"/** * Local #defines */#define IX_SSP_CR0_OFFSET 0x0 /* SSP Control Register 0 (SSCR0) offset from IXP400_SSP_BASE */#define IX_SSP_CR1_OFFSET 0x4 /* SSP Control Register 1 (SSCR1) offset from IXP400_SSP_BASE */#define IX_SSP_SR_OFFSET 0x8 /* SSP Status Register (SSSR) offset from IXP400_SSP_BASE */#define IX_SSP_DR_OFFSET 0x10 /* SSP Data Register (SSDR) offset from IXP400_SSP_BASE */#define IX_SSP_FIFO_EMPTY 0x00 /* SSP FIFO empty value is zero */#define IX_SSP_FIFO_FULL 0x10 /* SSP FIFO full value is 16 */#define IX_SSP_FIFO_FULL_OR_EMPTY 0x00/* FIFO level indicates it can either be empty of full */#define IX_SSP_TX_FIFO_EXCEED_THLD 0x0 /* zero indicates a Tx FIFO exceed threshold for the Tx FIFO svc request bit of the SSSR */#define IX_SSP_RX_FIFO_BELOW_THLD 0x0 /* zero indicates a Rx FIFO below threshold for the Rx FIFO svc request bit of the SSSR */#define IX_SSP_IS_BUSY 0x1 /* One indicates a SSP busy for the SSP busy bit of the SSSR */#define IX_SSP_TX_FIFO_FULL 0x0 /* zero indicates a TX FIFO Full in the Tx FIFO not full bit of the SSSR */#define IX_SSP_RX_FIFO_EMPTY 0x0 /* zero indicates a RX FIFO Empty in the Rx FIFO not empty bit of the SSSR */#define IX_SSP_OVERRUN_HAS_OCCURRED 0x1 /* one indicates an overrun has occurred in the overrun bit of the SSSR */#define IX_SSP_INTERRUPT_ENABLE 0x1 /* one enables the interrupt in the SSCR1 */#define IX_SSP_INTERRUPT_DISABLE 0x0 /* one disables the interrupt in the SSCR1 */#define IX_SSP_INTERRUPTED 0x1 /* one indicates an interrupt has occured in the SSSR */#define IX_SSP_SET_TO_BE_CLEARED 0x1 /* Use for write 1 to clear in the registers *//* #defines for mask and location of SSP Control and Status Registers contents */#define IX_SSP_SERIAL_CLK_RATE_LOC 0x8#define IX_SSP_SERIAL_CLK_RATE_MASK (0xFF << IX_SSP_SERIAL_CLK_RATE_LOC)#define IX_SSP_PORT_STATUS_LOC 0x7#define IX_SSP_PORT_STATUS_MASK (0x1 << IX_SSP_PORT_STATUS_LOC)#define IX_SSP_CLK_SRC_LOC 0x6#define IX_SSP_CLK_SRC_MASK (0x1 << IX_SSP_CLK_SRC_LOC)#define IX_SSP_FRAME_FORMAT_LOC 0x4#define IX_SSP_FRAME_FORMAT_MASK (0x3 << IX_SSP_FRAME_FORMAT_LOC)#define IX_SSP_DATA_SIZE_LOC 0x0#define IX_SSP_DATA_SIZE_MASK (0xF << IX_SSP_DATA_SIZE_LOC)#define IX_SSP_RX_FIFO_THLD_LOC 0xA#define IX_SSP_RX_FIFO_THLD_MASK (0xF << IX_SSP_RX_FIFO_THLD_LOC)#define IX_SSP_TX_FIFO_THLD_LOC 0x6#define IX_SSP_TX_FIFO_THLD_MASK (0xF << IX_SSP_TX_FIFO_THLD_LOC)#define IX_SSP_MICROWIRE_CTL_WORD_LOC 0x5#define IX_SSP_MICROWIRE_CTL_WORD_MASK (0x1 << IX_SSP_MICROWIRE_CTL_WORD_LOC)#define IX_SSP_SPI_SCLK_PHASE_LOC 0x4#define IX_SSP_SPI_SCLK_PHASE_MASK (0x1 << IX_SSP_SPI_SCLK_PHASE_LOC)#define IX_SSP_SPI_SCLK_POLARITY_LOC 0x3#define IX_SSP_SPI_SCLK_POLARITY_MASK (0x1 << IX_SSP_SPI_SCLK_POLARITY_LOC)#define IX_SSP_LOOPBACK_ENABLE_LOC 0x2#define IX_SSP_LOOPBACK_ENABLE_MASK (0x1 << IX_SSP_LOOPBACK_ENABLE_LOC)#define IX_SSP_TX_FIFO_INT_ENABLE_LOC 0x1#define IX_SSP_TX_FIFO_INT_ENABLE_MASK (0x1 << IX_SSP_TX_FIFO_INT_ENABLE_LOC)#define IX_SSP_RX_FIFO_INT_ENABLE_LOC 0x0#define IX_SSP_RX_FIFO_INT_ENABLE_MASK (0x1 << IX_SSP_RX_FIFO_INT_ENABLE_LOC)#define IX_SSP_RX_FIFO_LVL_LOC 0xC#define IX_SSP_RX_FIFO_LVL_MASK (0xF << IX_SSP_RX_FIFO_LVL_LOC)#define IX_SSP_TX_FIFO_LVL_LOC 0x8#define IX_SSP_TX_FIFO_LVL_MASK (0xF << IX_SSP_TX_FIFO_LVL_LOC)#define IX_SSP_RX_FIFO_OVERRUN_LOC 0x7#define IX_SSP_RX_FIFO_OVERRUN_MASK (0x1 << IX_SSP_RX_FIFO_OVERRUN_LOC)#define IX_SSP_RX_FIFO_SVC_REQ_LOC 0x6#define IX_SSP_RX_FIFO_SVC_REQ_MASK (0x1 << IX_SSP_RX_FIFO_SVC_REQ_LOC)#define IX_SSP_TX_FIFO_SVC_REQ_LOC 0x5#define IX_SSP_TX_FIFO_SVC_REQ_MASK (0x1 << IX_SSP_TX_FIFO_SVC_REQ_LOC)#define IX_SSP_BUSY_LOC 0x4#define IX_SSP_BUSY_MASK (0x1 << IX_SSP_BUSY_LOC)#define IX_SSP_RX_FIFO_NOT_EMPTY_LOC 0x3#define IX_SSP_RX_FIFO_NOT_EMPTY_MASK (0x1 << IX_SSP_RX_FIFO_NOT_EMPTY_LOC)#define IX_SSP_TX_FIFO_NOT_FULL_LOC 0x2#define IX_SSP_TX_FIFO_NOT_FULL_MASK (0x1 << IX_SSP_TX_FIFO_NOT_FULL_LOC)/** * macros */#define IX_SSP_INIT_SUCCESS_CHECK(funcName, returnType) \ if(FALSE == ixSspAccInitComplete) \ { \ ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, \ funcName": SSP Access not initialized\n", \ 0,0,0,0,0,0); \ return returnType; \ } /* end of FALSE == ixSspAccInitComplete *//** * typedef *//* typedef to contain both SSP Control Register 0 and 1 */typedef struct{ UINT32 sscr0; UINT32 sscr1;} IxSspAccConfig;/** * Static variables defined here *//* Interrupt handler function pointers */static RxFIFOOverrunHandler ixRxFIFOOverrunHdlr = NULL;static RxFIFOThresholdHandler ixRxFIFOThsldHdlr = NULL;static TxFIFOThresholdHandler ixTxFIFOThsldHdlr = NULL;/* The addresses to be used to access the SSP Control Register 0 (CR0), SSP Control Register 1 (CR1), SSP Status Register (SR), and SSP Data Register (DR). The address is assigned on init. */static UINT32 ixSspCR0Addr = 0;static UINT32 ixSspCR1Addr = 0;static UINT32 ixSspSRAddr = 0;static UINT32 ixSspDRAddr = 0;/* Storage for the SSP configuration which is used over many functions toincrease efficiency */static IxSspAccConfig ixSspAccCfgStored;/* Storage for the SSP status which is used by many functions to avoid declaration of the same struct multiple times */static UINT32 ixSspAccStsStored;/* Storage for the SSP statistics counters */static IxSspAccStatsCounters ixSspAccStatsCounters;/* Flag to indicate if the mode is interrupt or poll. */static BOOL ixSspAccInterruptMode = FALSE;/* Flag to indicate if the init has been done and thus not performing some instructions that should not be done more than once (please refer to the init API. Example: memory mapping). if init is called more than once (which is allowed) */static BOOL ixSspAccInitComplete = FALSE;/** * static function declaration */PRIVATE void ixSspAccInterruptDetected (void);/** * Function definitions */PUBLIC IX_SSP_STATUSixSspAccInit ( IxSspInitVars *initVarsSelected){ IX_SSP_STATUS temp_return = 0; /* Check if the hardware supports SSP. By reading the device type, it can be determined if the hardware supports SSP. Currenlty only the IXP46X supports SSP. */ if(IX_FEATURE_CTRL_DEVICE_TYPE_IXP46X != ixFeatureCtrlDeviceRead()) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixSspAccInit: This hardware does not support SSP!\n", 0,0,0,0,0,0); return IX_SSP_NOT_SUPORTED; } /* end of device detected is not IXP46x */ /* Check if the initVarsSelected is NULL */ if(NULL == initVarsSelected) return IX_SSP_NULL_POINTER; /* Check if SSP Init has been called before to avoid multiple instances of memory mapping */ if(FALSE == ixSspAccInitComplete) { /* Memory map the control, status, and data registers of the SSP */ ixSspCR0Addr = (UINT32)IX_OSAL_MEM_MAP (IX_OSAL_IXP400_SSP_PHYS_BASE, IX_OSAL_IXP400_SSP_MAP_SIZE); ixSspCR1Addr = ixSspCR0Addr + IX_SSP_CR1_OFFSET; ixSspSRAddr = ixSspCR0Addr + IX_SSP_SR_OFFSET; ixSspDRAddr = ixSspCR0Addr + IX_SSP_DR_OFFSET; ixSspAccStatsReset(); /* Clear the SSP statistics counters */ ixSspAccInitComplete = TRUE; /* Set the Init Complete flag so that a call to init will not mem map and clear the stats again*/ } /* end of FALSE == ixSspAccInitComplete */ /* Set the SSP frame format (SPI, SSP, or Microwire) if format is valid */ if(IX_SSP_SUCCESS != ixSspAccFrameFormatSelect( initVarsSelected->FrameFormatSelected)) return IX_SSP_INVALID_FRAME_FORMAT_ENUM_VALUE; /* Set the data size if range is valid and FIFOs empty */ temp_return = ixSspAccDataSizeSelect(initVarsSelected->DataSizeSelected); if(IX_SSP_SUCCESS != temp_return) { return temp_return; } /* Set the clock source if source is valid */ if(IX_SSP_SUCCESS != ixSspAccClockSourceSelect( initVarsSelected->ClkSourceSelected)) return IX_SSP_INVALID_CLOCK_SOURCE_ENUM_VALUE; /* Set the Tx FIFO Threshold if level is valid */ if(IX_SSP_SUCCESS != ixSspAccTxFIFOThresholdSet( initVarsSelected->TxFIFOThresholdSelected)) return IX_SSP_INVALID_TX_FIFO_THRESHOLD_ENUM_VALUE; /* Set the Rx FIFO Threshold if level is valid */ if(IX_SSP_SUCCESS != ixSspAccRxFIFOThresholdSet( initVarsSelected->RxFIFOThresholdSelected)) return IX_SSP_INVALID_RX_FIFO_THRESHOLD_ENUM_VALUE; /* Unbind the SSP ISR if interrupt mode was enabled previously */ if(TRUE == ixSspAccInterruptMode) { if(IX_SUCCESS != ixOsalIrqUnbind(IX_OSAL_IXP400_SSP_IRQ_LVL)) { return IX_SSP_INT_UNBIND_FAIL; } /* end of ixOsalIrqUnbind Fail */ ixSspAccRxFIFOIntDisable(); ixSspAccTxFIFOIntDisable(); ixSspAccInterruptMode = FALSE; } /* end of ixSspAccInterruptMode == TRUE */ /* Check if either the Rx FIFO or the Tx FIFO interrupt is selected to be enabled, then enable interrupt mode */ if((TRUE == initVarsSelected->TxFIFOIntrEnable) || (TRUE == initVarsSelected->RxFIFOIntrEnable)) { /* Check if the Rx FIFO Overrun handler is NULL */ if(NULL == initVarsSelected->RxFIFOOverrunHdlr) return IX_SSP_RX_FIFO_OVERRUN_HANDLER_MISSING; /* Set the Rx FIFO Overrun handler */ ixRxFIFOOverrunHdlr = initVarsSelected->RxFIFOOverrunHdlr; /* Bind the SSP to the SSP ISR */ if(IX_SUCCESS != ixOsalIrqBind(IX_OSAL_IXP400_SSP_IRQ_LVL, (IxOsalVoidFnVoidPtr)ixSspAccInterruptDetected, NULL)) { return IX_SSP_INT_BIND_FAIL; } ixSspAccInterruptMode = TRUE; /* Set the Interrupt Mode flag to TRUE */ } /* end of interrupt mode selected */ else /* start of polling mode selected */ { /* Set the Rx FIFO Overrun handler to NULL */ ixRxFIFOOverrunHdlr = NULL; ixSspAccInterruptMode = FALSE; /* Set the Interrupt Mode flag to FALSE */ } /* end of polling mode selected */ /* Check if the Rx FIFO interrupt is selected to be enabled */ if(TRUE == initVarsSelected->RxFIFOIntrEnable) { /* Enable the Rx FIFO and set the Rx FIFO handler if handler pointer is not NULL */ if(IX_SSP_SUCCESS != ixSspAccRxFIFOIntEnable( initVarsSelected->RxFIFOThsldHdlr)) return IX_SSP_RX_FIFO_HANDLER_MISSING; } /* end of Rx FIFOIntrEnable Selected */ /* Check if the Tx FIFO interrupt is selected to be enabled */ if(TRUE == initVarsSelected->TxFIFOIntrEnable) { /* Enable the Tx FIFO and set the Tx FIFO handler if handler pointer is not NULL */ if(IX_SSP_SUCCESS != ixSspAccTxFIFOIntEnable( initVarsSelected->TxFIFOThsldHdlr)) return IX_SSP_TX_FIFO_HANDLER_MISSING; } /* end of Tx FIFOIntrEnable Selected */ /* Enable/disable the loopback */ ixSspAccLoopbackEnable(initVarsSelected->LoopbackEnable); if(SPI_FORMAT == initVarsSelected->FrameFormatSelected) { /* Set the SPI SCLK phase if phase selected is valid */ if(IX_SSP_SUCCESS != ixSspAccSpiSclkPhaseSet( initVarsSelected->SpiSclkPhaseSelected)) { return IX_SSP_INVALID_SPI_PHASE_ENUM_VALUE; } /* Set the SPI SCLK polarity if polarity selected is valid */ if(IX_SSP_SUCCESS != ixSspAccSpiSclkPolaritySet( initVarsSelected->SpiSclkPolaritySelected)) { return IX_SSP_INVALID_SPI_POLARITY_ENUM_VALUE; } } /* end of SPI_FORMAT */ if(MICROWIRE_FORMAT == initVarsSelected->FrameFormatSelected) { /* Set the Microwire control word size if size is valid and Tx FIFO empty */ temp_return = ixSspAccMicrowireControlWordSet( initVarsSelected->MicrowireCtlWordSelected); if(IX_SSP_SUCCESS != temp_return) { if(IX_SSP_TX_FIFO_NOT_EMPTY == temp_return) { return IX_SSP_FIFO_NOT_EMPTY_FOR_SETTING_CTL_CMD; } else { return IX_SSP_INVALID_MICROWIRE_CTL_CMD_ENUM_VALUE; } } /* end of temp_return != IX_SSP_SUCCESS */ } /* end of MICROWIRE_FORMAT */ /* Set the Serial clock rate to the selected */ ixSspAccSerialClockRateConfigure(initVarsSelected->SerialClkRateSelected); /* Enable the SSP Port to start receiving and transmitting data */ ixSspAccSSPPortStatusSet(SSP_PORT_ENABLE); return IX_SSP_SUCCESS;} /* endo of ixSspAccInit */PUBLIC IX_SSP_STATUSixSspAccUninit ( void){ if(TRUE == ixSspAccInitComplete) { /* Disable the SSP hardware */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -