diff options
Diffstat (limited to 'platform/drivers/src/ecspi.c')
-rw-r--r-- | platform/drivers/src/ecspi.c | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/platform/drivers/src/ecspi.c b/platform/drivers/src/ecspi.c new file mode 100644 index 0000000..bdf4aa8 --- /dev/null +++ b/platform/drivers/src/ecspi.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o 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. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 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 HOLDER 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. + */ + +#include "ecspi.h" + +/******************************************************************************* + * Code + ******************************************************************************/ + +/******************************************************************************* + * ECSPI Initialization and Configuration functions + ******************************************************************************/ +/*FUNCTION********************************************************************** + * + * Function Name : ECSPI_Init + * Description : Initializes the ECSPI module according to the specified + * parameters in the initStruct. + * + *END**************************************************************************/ +void ECSPI_Init(ECSPI_Type* base, ecspi_init_t* initStruct) +{ + /* Disable ECSPI module */ + ECSPI_CONREG_REG(base) = 0; + + /* Enable the ECSPI module before write to other registers */ + ECSPI_Enable(base); + + /* ECSPI CONREG Configuration */ + ECSPI_CONREG_REG(base) |= ECSPI_CONREG_BURST_LENGTH(initStruct->burstLength) | + ECSPI_CONREG_CHANNEL_SELECT(initStruct->channelSelect); + ECSPI_CONREG_REG(base) |= initStruct->ecspiAutoStart ? ECSPI_CONREG_SMC_MASK : 0; + + /* ECSPI CONFIGREG Configuration */ + ECSPI_CONFIGREG_REG(base) = ECSPI_CONFIGREG_SCLK_PHA(((initStruct->clockPhase) & 1) << (initStruct->channelSelect)) | + ECSPI_CONFIGREG_SCLK_POL(((initStruct->clockPolarity) & 1) << (initStruct->channelSelect)); + + /* Master or Slave mode Configuration */ + if(initStruct->mode == ecspiMasterMode) + { + /* Set baud rate in bits per second */ + ECSPI_CONREG_REG(base) |= ECSPI_CONREG_CHANNEL_MODE(1 << (initStruct->channelSelect)); + ECSPI_SetBaudRate(base, initStruct->clockRate, initStruct->baudRate); + } + else + ECSPI_CONREG_REG(base) &= ~ECSPI_CONREG_CHANNEL_MODE(1 << (initStruct->channelSelect)); +} + +/*FUNCTION********************************************************************** + * + * Function Name : ECSPI_SetSampClockSource + * Description : Configure the clock source for the sample period counter. + * + *END**************************************************************************/ +void ECSPI_SetSampClockSource(ECSPI_Type* base, uint32_t source) +{ + /* Select the clock source */ + if(source == ecspiSclk) + ECSPI_PERIODREG_REG(base) &= ~ECSPI_PERIODREG_CSRC_MASK; + else + ECSPI_PERIODREG_REG(base) |= ECSPI_PERIODREG_CSRC_MASK; +} + +/*FUNCTION********************************************************************** + * + * Function Name : ECSPI_SetBaudRate + * Description : Calculated the ECSPI baud rate in bits per second. + * + *END**************************************************************************/ +uint32_t ECSPI_SetBaudRate(ECSPI_Type* base, uint32_t sourceClockInHz, uint32_t bitsPerSec) +{ + uint32_t div, pre_div; + uint32_t post_baud; /* baud rate after post divider */ + uint32_t pre_baud; /* baud rate before pre divider */ + + if(sourceClockInHz <= bitsPerSec) + { + ECSPI_CONREG_REG(base) &= ~ECSPI_CONREG_PRE_DIVIDER_MASK; + ECSPI_CONREG_REG(base) &= ~ECSPI_CONREG_POST_DIVIDER_MASK; + return sourceClockInHz; + } + + div = sourceClockInHz / bitsPerSec; + if(div < 16) /* pre_divider is enough */ + { + if((sourceClockInHz - bitsPerSec * div) < ((bitsPerSec * (div + 1)) - sourceClockInHz)) + pre_div = div - 1; /* pre_divider value is one less than the real divider */ + else + pre_div = div; + ECSPI_CONREG_REG(base) = (ECSPI_CONREG_REG(base) & (~ECSPI_CONREG_PRE_DIVIDER_MASK)) | + ECSPI_CONREG_PRE_DIVIDER(pre_div); + ECSPI_CONREG_REG(base) = (ECSPI_CONREG_REG(base) & (~ECSPI_CONREG_POST_DIVIDER_MASK)) | + ECSPI_CONREG_POST_DIVIDER(0); + return sourceClockInHz / (pre_div + 1); + } + + pre_baud = bitsPerSec * 16; + for(div = 1; div < 16; div++) + { + post_baud = sourceClockInHz >> div; + if(post_baud < pre_baud) + break; + } + + if(div == 16) /* divider is not enough, set the biggest ones */ + { + ECSPI_CONREG_REG(base) |= ECSPI_CONREG_PRE_DIVIDER(15); + ECSPI_CONREG_REG(base) |= ECSPI_CONREG_POST_DIVIDER(15); + return post_baud / 16; + } + + /* find the closed one */ + if((post_baud - bitsPerSec * (post_baud / bitsPerSec)) < ((bitsPerSec * ((post_baud / bitsPerSec) + 1)) - post_baud)) + pre_div = post_baud / bitsPerSec - 1; + else + pre_div = post_baud / bitsPerSec; + ECSPI_CONREG_REG(base) = (ECSPI_CONREG_REG(base) & (~ECSPI_CONREG_PRE_DIVIDER_MASK)) | + ECSPI_CONREG_PRE_DIVIDER(pre_div); + ECSPI_CONREG_REG(base) = (ECSPI_CONREG_REG(base) & (~ECSPI_CONREG_POST_DIVIDER_MASK)) | + ECSPI_CONREG_POST_DIVIDER(div); + return post_baud / (pre_div + 1); +} + +/******************************************************************************* + * DMA management functions + ******************************************************************************/ +/*FUNCTION********************************************************************** + * + * Function Name : ECSPPI_SetDMACmd + * Description : Enable or disable the specified DMA Source. + * + *END**************************************************************************/ +void ECSPPI_SetDMACmd(ECSPI_Type* base, uint32_t source, bool enable) +{ + /* Configure the DAM source */ + if(enable) + ECSPI_DMAREG_REG(base) |= ((uint32_t)(1 << source)); + else + ECSPI_DMAREG_REG(base) &= ~((uint32_t)(1 << source)); +} + +/*FUNCTION********************************************************************** + * + * Function Name : ECSPI_SetFIFOThreshold + * Description : Set the RXFIFO or TXFIFO threshold. + * + *END**************************************************************************/ +void ECSPI_SetFIFOThreshold(ECSPI_Type* base, uint32_t fifo, uint32_t threshold) +{ + /* configure the RXFIFO and TXFIFO threshold that can triggers a DMA/INT request */ + if(fifo == ecspiTxfifoThreshold) + ECSPI_DMAREG_REG(base) = (ECSPI_DMAREG_REG(base) & (~ECSPI_DMAREG_TX_THRESHOLD_MASK)) | + ECSPI_DMAREG_TX_THRESHOLD(threshold); + else + ECSPI_DMAREG_REG(base) = (ECSPI_DMAREG_REG(base) & (~ECSPI_DMAREG_RX_THRESHOLD_MASK)) | + ECSPI_DMAREG_RX_THRESHOLD(threshold); +} + +/******************************************************************************* + * Interrupts and flags management functions + ******************************************************************************/ +/*FUNCTION********************************************************************** + * + * Function Name : ECSPI_SetIntCmd + * Description : Enable or disable ECSPI interrupts. + * + *END**************************************************************************/ +void ECSPI_SetIntCmd(ECSPI_Type* base, uint32_t flags, bool enable) +{ + /* Configure the Interrupt source */ + if(enable) + ECSPI_INTREG_REG(base) |= flags; + else + ECSPI_INTREG_REG(base) &= ~flags; +} + +/******************************************************************************* + * EOF + ******************************************************************************/ |