1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * o Redistributions of source code must retain the above copyright notice, this list
9 * of conditions and the following disclaimer.
10 *
11 * o Redistributions in binary form must reproduce the above copyright notice, this
12 * list of conditions and the following disclaimer in the documentation and/or
13 * other materials provided with the distribution.
14 *
15 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "ecspi.h"
32
33 /*******************************************************************************
34 * Code
35 ******************************************************************************/
36
37 /*******************************************************************************
38 * eCSPI Initialization and Configuration functions
39 ******************************************************************************/
40 /*FUNCTION**********************************************************************
41 *
42 * Function Name : ECSPI_Init
43 * Description : Initializes the eCSPI module according to the specified
44 * parameters in the initConfig.
45 *
46 *END**************************************************************************/
ECSPI_Init(ECSPI_Type * base,const ecspi_init_config_t * initConfig)47 void ECSPI_Init(ECSPI_Type* base, const ecspi_init_config_t* initConfig)
48 {
49 /* Disable eCSPI module */
50 ECSPI_CONREG_REG(base) = 0;
51
52 /* Enable the eCSPI module before write to other registers */
53 ECSPI_Enable(base);
54
55 /* eCSPI CONREG Configuration */
56 ECSPI_CONREG_REG(base) |= ECSPI_CONREG_BURST_LENGTH(initConfig->burstLength) |
57 ECSPI_CONREG_CHANNEL_SELECT(initConfig->channelSelect);
58 ECSPI_CONREG_REG(base) |= initConfig->ecspiAutoStart ? ECSPI_CONREG_SMC_MASK : 0;
59
60 /* eCSPI CONFIGREG Configuration */
61 ECSPI_CONFIGREG_REG(base) = ECSPI_CONFIGREG_SCLK_PHA(((initConfig->clockPhase) & 1) << (initConfig->channelSelect)) |
62 ECSPI_CONFIGREG_SCLK_POL(((initConfig->clockPolarity) & 1) << (initConfig->channelSelect));
63
64 /* Master or Slave mode Configuration */
65 if(initConfig->mode == ecspiMasterMode)
66 {
67 /* Set baud rate in bits per second */
68 ECSPI_CONREG_REG(base) |= ECSPI_CONREG_CHANNEL_MODE(1 << (initConfig->channelSelect));
69 ECSPI_SetBaudRate(base, initConfig->clockRate, initConfig->baudRate);
70 }
71 else
72 ECSPI_CONREG_REG(base) &= ~ECSPI_CONREG_CHANNEL_MODE(1 << (initConfig->channelSelect));
73 }
74
75 /*FUNCTION**********************************************************************
76 *
77 * Function Name : ECSPI_SetSampClockSource
78 * Description : Configure the clock source for the sample period counter.
79 *
80 *END**************************************************************************/
ECSPI_SetSampClockSource(ECSPI_Type * base,uint32_t source)81 void ECSPI_SetSampClockSource(ECSPI_Type* base, uint32_t source)
82 {
83 /* Select the clock source */
84 if(source == ecspiSclk)
85 ECSPI_PERIODREG_REG(base) &= ~ECSPI_PERIODREG_CSRC_MASK;
86 else
87 ECSPI_PERIODREG_REG(base) |= ECSPI_PERIODREG_CSRC_MASK;
88 }
89
90 /*FUNCTION**********************************************************************
91 *
92 * Function Name : ECSPI_SetBaudRate
93 * Description : Calculated the eCSPI baud rate in bits per second.
94 *
95 *END**************************************************************************/
ECSPI_SetBaudRate(ECSPI_Type * base,uint32_t sourceClockInHz,uint32_t bitsPerSec)96 uint32_t ECSPI_SetBaudRate(ECSPI_Type* base, uint32_t sourceClockInHz, uint32_t bitsPerSec)
97 {
98 uint32_t div, pre_div;
99 uint32_t post_baud; /* baud rate after post divider */
100 uint32_t pre_baud; /* baud rate before pre divider */
101
102 if(sourceClockInHz <= bitsPerSec)
103 {
104 ECSPI_CONREG_REG(base) &= ~ECSPI_CONREG_PRE_DIVIDER_MASK;
105 ECSPI_CONREG_REG(base) &= ~ECSPI_CONREG_POST_DIVIDER_MASK;
106 return sourceClockInHz;
107 }
108
109 div = sourceClockInHz / bitsPerSec;
110 if(div < 16) /* pre_divider is enough */
111 {
112 if((sourceClockInHz - bitsPerSec * div) < ((bitsPerSec * (div + 1)) - sourceClockInHz))
113 pre_div = div - 1; /* pre_divider value is one less than the real divider */
114 else
115 pre_div = div;
116 ECSPI_CONREG_REG(base) = (ECSPI_CONREG_REG(base) & (~ECSPI_CONREG_PRE_DIVIDER_MASK)) |
117 ECSPI_CONREG_PRE_DIVIDER(pre_div);
118 ECSPI_CONREG_REG(base) = (ECSPI_CONREG_REG(base) & (~ECSPI_CONREG_POST_DIVIDER_MASK)) |
119 ECSPI_CONREG_POST_DIVIDER(0);
120 return sourceClockInHz / (pre_div + 1);
121 }
122
123 pre_baud = bitsPerSec * 16;
124 for(div = 1; div < 16; div++)
125 {
126 post_baud = sourceClockInHz >> div;
127 if(post_baud < pre_baud)
128 break;
129 }
130
131 if(div == 16) /* divider is not enough, set the biggest ones */
132 {
133 ECSPI_CONREG_REG(base) |= ECSPI_CONREG_PRE_DIVIDER(15);
134 ECSPI_CONREG_REG(base) |= ECSPI_CONREG_POST_DIVIDER(15);
135 return post_baud / 16;
136 }
137
138 /* find the closed one */
139 if((post_baud - bitsPerSec * (post_baud / bitsPerSec)) < ((bitsPerSec * ((post_baud / bitsPerSec) + 1)) - post_baud))
140 pre_div = post_baud / bitsPerSec - 1;
141 else
142 pre_div = post_baud / bitsPerSec;
143 ECSPI_CONREG_REG(base) = (ECSPI_CONREG_REG(base) & (~ECSPI_CONREG_PRE_DIVIDER_MASK)) |
144 ECSPI_CONREG_PRE_DIVIDER(pre_div);
145 ECSPI_CONREG_REG(base) = (ECSPI_CONREG_REG(base) & (~ECSPI_CONREG_POST_DIVIDER_MASK)) |
146 ECSPI_CONREG_POST_DIVIDER(div);
147 return post_baud / (pre_div + 1);
148 }
149
150 /*******************************************************************************
151 * DMA management functions
152 ******************************************************************************/
153 /*FUNCTION**********************************************************************
154 *
155 * Function Name : ECSPI_SetDMACmd
156 * Description : Enable or disable the specified DMA Source.
157 *
158 *END**************************************************************************/
ECSPI_SetDMACmd(ECSPI_Type * base,uint32_t source,bool enable)159 void ECSPI_SetDMACmd(ECSPI_Type* base, uint32_t source, bool enable)
160 {
161 /* Configure the DAM source */
162 if(enable)
163 ECSPI_DMAREG_REG(base) |= ((uint32_t)(1 << source));
164 else
165 ECSPI_DMAREG_REG(base) &= ~((uint32_t)(1 << source));
166 }
167
168 /*FUNCTION**********************************************************************
169 *
170 * Function Name : ECSPI_SetFIFOThreshold
171 * Description : Set the RXFIFO or TXFIFO threshold.
172 *
173 *END**************************************************************************/
ECSPI_SetFIFOThreshold(ECSPI_Type * base,uint32_t fifo,uint32_t threshold)174 void ECSPI_SetFIFOThreshold(ECSPI_Type* base, uint32_t fifo, uint32_t threshold)
175 {
176 /* configure the RXFIFO and TXFIFO threshold that can triggers a DMA/INT request */
177 if(fifo == ecspiTxfifoThreshold)
178 ECSPI_DMAREG_REG(base) = (ECSPI_DMAREG_REG(base) & (~ECSPI_DMAREG_TX_THRESHOLD_MASK)) |
179 ECSPI_DMAREG_TX_THRESHOLD(threshold);
180 else
181 ECSPI_DMAREG_REG(base) = (ECSPI_DMAREG_REG(base) & (~ECSPI_DMAREG_RX_THRESHOLD_MASK)) |
182 ECSPI_DMAREG_RX_THRESHOLD(threshold);
183 }
184
185 /*******************************************************************************
186 * Interrupts and flags management functions
187 ******************************************************************************/
188 /*FUNCTION**********************************************************************
189 *
190 * Function Name : ECSPI_SetIntCmd
191 * Description : Enable or disable eCSPI interrupts.
192 *
193 *END**************************************************************************/
ECSPI_SetIntCmd(ECSPI_Type * base,uint32_t flags,bool enable)194 void ECSPI_SetIntCmd(ECSPI_Type* base, uint32_t flags, bool enable)
195 {
196 /* Configure the Interrupt source */
197 if(enable)
198 ECSPI_INTREG_REG(base) |= flags;
199 else
200 ECSPI_INTREG_REG(base) &= ~flags;
201 }
202
203 /*******************************************************************************
204 * EOF
205 ******************************************************************************/
206