| /* |
| * 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 initConfig. |
| * |
| *END**************************************************************************/ |
| void ECSPI_Init(ECSPI_Type* base, const ecspi_init_config_t* initConfig) |
| { |
| /* 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(initConfig->burstLength) | |
| ECSPI_CONREG_CHANNEL_SELECT(initConfig->channelSelect); |
| ECSPI_CONREG_REG(base) |= initConfig->ecspiAutoStart ? ECSPI_CONREG_SMC_MASK : 0; |
| |
| /* eCSPI CONFIGREG Configuration */ |
| ECSPI_CONFIGREG_REG(base) = ECSPI_CONFIGREG_SCLK_PHA(((initConfig->clockPhase) & 1) << (initConfig->channelSelect)) | |
| ECSPI_CONFIGREG_SCLK_POL(((initConfig->clockPolarity) & 1) << (initConfig->channelSelect)); |
| |
| /* Master or Slave mode Configuration */ |
| if(initConfig->mode == ecspiMasterMode) |
| { |
| /* Set baud rate in bits per second */ |
| ECSPI_CONREG_REG(base) |= ECSPI_CONREG_CHANNEL_MODE(1 << (initConfig->channelSelect)); |
| ECSPI_SetBaudRate(base, initConfig->clockRate, initConfig->baudRate); |
| } |
| else |
| ECSPI_CONREG_REG(base) &= ~ECSPI_CONREG_CHANNEL_MODE(1 << (initConfig->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 : ECSPI_SetDMACmd |
| * Description : Enable or disable the specified DMA Source. |
| * |
| *END**************************************************************************/ |
| void ECSPI_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 |
| ******************************************************************************/ |