1 /**
2   ******************************************************************************
3   * @file    rtl8721dhp_usi_ssi.c
4   * @author
5   * @version V1.0.0
6   * @date    2017-11-27
7   * @brief   This file contains all the functions prototypes for USI-SPI:
8   *		- Initialization
9   *		- Clock polarity and phase setting
10   *		- SPI data frame size setting
11   *		- SPI baud rate setting
12   *		- Receive/Send data interface
13   *		- Get TRx FIFO valid entries
14   *		- check SPI device busy status
15   *		- DMA transfers management
16   *		- Interrupts and management
17   *
18   ******************************************************************************
19   * @attention
20   *
21   * This module is a confidential and proprietary property of RealTek and
22   * possession or use of this module requires written permission of RealTek.
23   *
24   * Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved.
25   ******************************************************************************
26   */
27 
28 #include "ameba_soc.h"
29 
30 /** @addtogroup USI_SPI_Exported_Functions
31 *@verbatim
32   *
33   *          ===================================================================
34   *                                 	How to use this driver
35   *          ===================================================================
36   *			1. Enable peripheral clock using the following functions
37   *
38   *
39   *			2. Configure the SPIx pinmux.
40   *
41   *
42   *			3. Disable the SPI using the USI_SSI_Cmd() function
43   *
44   *			4. Program the Polarity,Phase,Transfer Mode,Baud Rate Prescaler,DataFrameSize,
45   *				Interrupt TRx Threshold level,DMA TRx Threshold level and other parameters using
46   *				the USI_SSI_Init() function.
47   *
48   *			5. Enable the USI-SPI using the USI_SSI_Cmd() function
49   *
50   *			6. When using poll:
51   *				-Using USI_SSI_Writeable() function make sure that the transmit FIFO is not full,
52   *				then using USI_SSI_WriteData() function to send data
53   *
54   *				-Using USI_SSI_Readable() function make sure that the receive FIFO is not empty,
55   *				then using USI_SSI_ReadData() function to receive data
56   *
57   *			7. Enable corresponding interrupt using the function  USI_SSI_INTConfig() if you need to
58   *				use interrupt mode.
59   *
60   *			8. When using the DMA mode
61   *				- Configure & Initialize the DMA
62   *				- Active the DMA Tx or Rx using USI_SSI_SetDmaEnable() function
63   *
64   * @endverbatim
65   */
66 
67 /**
68   * @brief  Fills each USI_SSI_InitStruct member with its default value.
69   * @param  USI_SSI_InitStruct: pointer to a USI_SSI_InitTypeDef structure which will be
70   *         initialized.
71   * @retval None
72   */
73 void
USI_SSI_StructInit(USI_SSI_InitTypeDef * USI_SSI_InitStruct)74 USI_SSI_StructInit(USI_SSI_InitTypeDef* USI_SSI_InitStruct)
75 {
76 	USI_SSI_InitStruct->USI_SPI_RxThresholdLevel  =    0;  // if number of entries in the RX FIFO >= RxThresholdLevel + 1, RX interrupt asserted
77 	USI_SSI_InitStruct->USI_SPI_TxThresholdLevel  =    32;  // if number of empty entries in th TX FIFO >= TxThresholdLevel, TX interrupt asserted
78 	USI_SSI_InitStruct->USI_SPI_DmaRxDataLevel   =      3;
79 	USI_SSI_InitStruct->USI_SPI_DmaTxDataLevel   =    56;
80 	USI_SSI_InitStruct->USI_SPI_ClockDivider      = 6;
81 	USI_SSI_InitStruct->USI_SPI_DataFrameNumber   =    0;
82 	USI_SSI_InitStruct->USI_SPI_DataFrameSize     = USI_SPI_DFS_8_BITS;
83 	USI_SSI_InitStruct->USI_SPI_InterruptMask     =  0x0;
84 	USI_SSI_InitStruct->USI_SPI_SclkPhase             = USI_SPI_SCPH_TOGGLES_AT_START;
85 	USI_SSI_InitStruct->USI_SPI_SclkPolarity          = USI_SPI_SCPOL_INACTIVE_IS_HIGH;
86 	USI_SSI_InitStruct->USI_SPI_TransferMode          = USI_SPI_TMOD_TR;
87 
88 	USI_SSI_InitStruct->USI_SPI_RxSampleDelay	=	0;
89 	USI_SSI_InitStruct->USI_SPI_SSTogglePhase	=	0;
90 }
91 
92 
93 /**
94   * @brief    Initializes the USI-SPI registers according to the specified parameters
95   *         in USI_SSI_InitStruct.
96   * @param  usi_dev: where spi_dev can be USI0_DEV.
97   * @param  USI_SSI_InitStruct: pointer to a USI_SSI_InitTypeDef structure that contains
98   *         the configuration information for the USI-SPI peripheral.
99   * @retval None
100   */
101 
USI_SSI_Init(USI_TypeDef * usi_dev,USI_SSI_InitTypeDef * USI_SSI_InitStruct)102 void USI_SSI_Init(USI_TypeDef *usi_dev, USI_SSI_InitTypeDef *USI_SSI_InitStruct)
103 {
104 	u32 TempValue1  = 0, TempValue2 = 0;
105 
106 	assert_param(IS_USI_SPI_RxThresholdLevel(USI_SSI_InitStruct->USI_SPI_RxThresholdLevel));
107 	assert_param(IS_USI_SPI_TxThresholdLevel(USI_SSI_InitStruct->USI_SPI_TxThresholdLevel));
108 
109 	/* Set USI to SPI mode */
110 	TempValue1 = usi_dev->USI_MODE_CTRL;
111 	TempValue1  &= ~USI_SERIAL_MODE;
112 	TempValue1 |= USI_SERIAL_SPI_MODE;
113 	usi_dev->USI_MODE_CTRL = TempValue1;
114 
115 	/* Disable SPI and Tx/Rx Path, for some bits in SPI_CTRL are writeable only when Tx/Rx path are both disable.*/
116 	USI_SSI_Cmd(usi_dev, DISABLE);
117 	USI_SSI_TRxPath_Cmd(usi_dev, USI_SPI_RX_ENABLE | USI_SPI_TX_ENABLE, DISABLE);
118 
119 	/* Set SPI Control Register */
120 	TempValue1 = 0;
121 	TempValue1 |= USI_SSI_InitStruct->USI_SPI_DataFrameSize;
122 	TempValue1 |= (USI_SSI_InitStruct->USI_SPI_SclkPhase << 6);
123 	TempValue1 |= (USI_SSI_InitStruct->USI_SPI_SclkPolarity << 7);
124 
125 	/* Master Only */
126 	if (USI_SSI_InitStruct->USI_SPI_Role & USI_SPI_MASTER) {
127 		TempValue1 |= (USI_SSI_InitStruct->USI_SPI_ClockDivider) << 16;
128 		TempValue1 |= (USI_SSI_InitStruct->USI_SPI_RxSampleDelay) << 8;
129 		TempValue1 |= (USI_SSI_InitStruct->USI_SPI_SSTogglePhase) << 5;
130 		TempValue1 |= USI_SPI_MASTER_MODE;
131 
132 		TempValue2 |= (USI_SSI_InitStruct->USI_SPI_DataFrameNumber) << 16;
133 	}
134 	usi_dev->SPI_CTRL = TempValue1;
135 
136 	/* Set Tx/Rx FIFO Threshold Level*/
137 	usi_dev->TX_FIFO_CTRL = USI_SPI_TX_FIFO_DEPTH - USI_SSI_InitStruct->USI_SPI_TxThresholdLevel;
138 	usi_dev->RX_FIFO_CTRL = USI_SSI_InitStruct->USI_SPI_RxThresholdLevel + 1;
139 
140 	/* Set interrupt */
141 	usi_dev->INTERRUPT_ENABLE = USI_SSI_InitStruct->USI_SPI_InterruptMask & USI_SPI_INTERRUPT_MASK;
142 
143 	/*DMA level set */
144 	USI_SSI_SetDmaLevel(usi_dev, USI_SSI_InitStruct->USI_SPI_DmaTxDataLevel, USI_SSI_InitStruct->USI_SPI_DmaRxDataLevel);
145 
146 	/* Set Tx/Rx Path enable */
147 	switch(USI_SSI_InitStruct->USI_SPI_TransferMode){
148 		case USI_SPI_TMOD_TO:
149 			TempValue2 |= USI_SPI_TX_ENABLE;
150 		break;
151 		case USI_SPI_TMOD_RO:
152 			TempValue2 |= USI_SPI_RX_ENABLE;
153 		break;
154 		case USI_SPI_TMOD_TR:
155 			TempValue2 |= (USI_SPI_TX_ENABLE | USI_SPI_RX_ENABLE);
156 		break;
157 		default:
158 		break;
159 	}
160 	usi_dev->SPI_TRANS_EN  = TempValue2;
161 
162 	/* Enable SPI. SPI can work normally when Tx/Rx Path and all logic are released.*/
163 	USI_SSI_Cmd(usi_dev, ENABLE);
164 }
165 
166 /**
167   * @brief  Enables or disables USI-SPI peripheral.
168   * @param  usi_dev: where usi_dev can be USI0_DEV.
169   * @param  NewStatus: This parameter can be one of the following values:
170   *            @arg ENABLE
171   *            @arg DISABLE
172   * @retval None
173   */
174 
USI_SSI_Cmd(USI_TypeDef * usi_dev,u32 NewStatus)175 void USI_SSI_Cmd(USI_TypeDef *usi_dev, u32 NewStatus)
176 {
177 	if (NewStatus != DISABLE) {
178 		usi_dev->SW_RESET |= USI_SW_RESET_RSTB | USI_SW_RESET_RXFIFO_RSTB |
179 			USI_SW_RESET_TXFIFO_RSTB | USI_SW_RESET_RX_RSTB | USI_SW_RESET_TX_RSTB;
180 	} else {
181 		usi_dev->SW_RESET &= ~USI_SW_RESET_RSTB;
182 	}
183 }
184 
185 
186 /**
187   * @brief  Enables or disables USI-SPI Tx or Rx path.
188   * @param  usi_dev: where usi_dev can be USI0_DEV.
189   * @param  path: Tx or Rx path control bit, which can be
190   *            @arg USI_SPI_TX_ENABLE
191   *            @arg USI_SPI_RX_ENABLE
192   * @param  NewStatus: This parameter can be one of the following values:
193   *            @arg ENABLE
194   *            @arg DISABLE
195   * @retval None
196   */
197 
USI_SSI_TRxPath_Cmd(USI_TypeDef * usi_dev,u32 path,u32 NewStatus)198 void USI_SSI_TRxPath_Cmd(USI_TypeDef *usi_dev, u32 path, u32 NewStatus)
199 {
200 	if(NewStatus != DISABLE){
201 		usi_dev->SPI_TRANS_EN |= path;
202 	} else {
203 		usi_dev->SPI_TRANS_EN &= ~path;
204 	}
205 }
206 
207 /**
208   * @brief  Get USI-SPI Tx/Rx path configuration.
209   * @param  usi_dev: where usi_dev can be USI0_DEV.
210   * @retval  Current TRx Path setting, each bit of this value represents one
211   *		path which is as follows:
212   *
213   *  			bit 1 : USI_SPI_RX_ENABLE
214   *			- 0 : Rx Path is disable
215   *			- 1 : Rx Path is enable
216   *
217   *  			bit 0 : USI_SPI_TX_ENABLE
218   *			- 0 : Tx Path is disable
219   *			- 1 : Tx Path is enable
220   *
221   * @retval None
222   */
USI_SSI_GetTRxPath(USI_TypeDef * usi_dev)223 u32 USI_SSI_GetTRxPath(USI_TypeDef *usi_dev)
224 {
225 	return usi_dev->SPI_TRANS_EN & (USI_SPI_RX_ENABLE | USI_SPI_TX_ENABLE);
226 }
227 
228 /**
229   * @brief  Set USI SPI as Master or Slave.
230   * @param  usi_dev: where spi_dev can be USI0_DEV.
231   * @param  role: This parameter can be one of the following values:
232   *            @arg USI_SPI_MASTER
233   *            @arg USI_SPI_SLAVE
234   * @retval None
235   */
USI_SSI_SetRole(USI_TypeDef * usi_dev,u32 role)236 void USI_SSI_SetRole(USI_TypeDef *usi_dev, u32 role)
237 {
238 	u32 Temp;
239 	u32 trxpath = USI_SSI_GetTRxPath(usi_dev);
240 
241 	Temp = usi_dev->SPI_CTRL;
242 	Temp &= ~USI_SPI_MASTER_MODE;
243 	Temp |= (role << 4);
244 
245 	/* USI_SPI_MASTER_MODE is writeable only when Tx and Rx path are both disable */
246 	USI_SSI_TRxPath_Cmd(usi_dev, trxpath, DISABLE);
247 	usi_dev->SPI_CTRL = Temp;
248 	USI_SSI_TRxPath_Cmd(usi_dev, trxpath, ENABLE);
249 }
250 
251 
252 /**
253   * @brief  Enable or Disable USI-SPI interrupt.
254   * @param  usi_dev: where usi_dev can be USI0_DEV.
255   * @param  USI_SSI_IT: This parameter can be one of the following values or mixed:
256   *            @arg USI_TXFIFO_ALMOST_EMTY_INTR_EN
257   *            @arg USI_TXFIFO_OVERFLOW_INTR_EN
258   *            @arg USI_TXFIFO_UNDERFLOW_INTR_EN
259   *            @arg USI_RXFIFO_ALMOST_FULL_INTR_EN
260   *            @arg USI_RXFIFO_OVERFLOW_INTR_EN
261   *            @arg USI_RXFIFO_UNDERFLOW_INTR_EN
262   *            @arg USI_SPI_RX_DATA_FRM_ERR_INTER_EN
263   * @param   newState:This parameter can be one of the following values:
264   *            @arg ENABLE
265   *            @arg DISABLE
266   * @retval None
267   */
268 VOID
USI_SSI_INTConfig(USI_TypeDef * usi_dev,u32 USI_SSI_IT,u32 newState)269 USI_SSI_INTConfig(USI_TypeDef* usi_dev, u32 USI_SSI_IT, u32 newState)
270 {
271 	if (newState == ENABLE) {
272 		/* Enable the selected SSI interrupts */
273 		usi_dev->INTERRUPT_ENABLE |= USI_SSI_IT;
274 	} else {
275 		/* Disable the selected SSI interrupts */
276 		usi_dev->INTERRUPT_ENABLE &= ~USI_SSI_IT;
277 	}
278 }
279 
280 /**
281   * @brief  Set USI-SPI clock polarity.
282   * @param  usi_dev: where usi_dev can be USI0_DEV.
283   * @param  SclkPolarity: This parameter can be one of the following values:
284   *            @arg USI_SPI_SCPOL_INACTIVE_IS_HIGH
285   *            @arg USI_SPI_SCPOL_INACTIVE_IS_LOW
286   * @retval None
287   */
288 
USI_SSI_SetSclkPolarity(USI_TypeDef * usi_dev,u32 SclkPolarity)289 void USI_SSI_SetSclkPolarity(USI_TypeDef *usi_dev, u32 SclkPolarity)
290 {
291 	u32 Value;
292 	u32 trxpath = USI_SSI_GetTRxPath(usi_dev);
293 
294 	Value = usi_dev->SPI_CTRL;
295 	Value &= ~ USI_SPI_CPOL;
296 	Value |= (SclkPolarity << 7);
297 
298 	/* SPI_CPOL is writeable only when Tx and Rx path are both disable */
299 	USI_SSI_TRxPath_Cmd(usi_dev, trxpath, DISABLE);
300 	usi_dev->SPI_CTRL = Value;
301 	USI_SSI_TRxPath_Cmd(usi_dev, trxpath, ENABLE);
302 }
303 
304 /**
305   * @brief  Set USI-SPI clock phase.
306   * @param  usi_dev: where usi_dev can be USI0_DEV.
307   * @param  SclkPhase: This parameter can be one of the following values:
308   *            @arg USI_SPI_SCPH_TOGGLES_IN_MIDDLE
309   *            @arg USI_SPI_SCPH_TOGGLES_AT_START
310   * @retval None
311   */
312 
USI_SSI_SetSclkPhase(USI_TypeDef * usi_dev,u32 SclkPhase)313 void USI_SSI_SetSclkPhase(USI_TypeDef *usi_dev, u32 SclkPhase)
314 {
315 	u32 Value;
316 	u32 trxpath = USI_SSI_GetTRxPath(usi_dev);
317 
318 	Value = usi_dev->SPI_CTRL;
319 	Value &= ~USI_SPI_CPH;
320 	Value |= (SclkPhase << 6);
321 
322 	/* SPI_CPH is writeable only when Tx and Rx path are both disable */
323 	USI_SSI_TRxPath_Cmd(usi_dev, trxpath, DISABLE);
324 	usi_dev->SPI_CTRL = Value;
325 	USI_SSI_TRxPath_Cmd(usi_dev, trxpath, ENABLE);
326 }
327 
328 
329 /**
330   * @brief  Set USI-SPI SS Toggle Phase.
331   * @param  usi_dev: where usi_dev can be USI0_DEV.
332   * @param  TogglePhase: This parameter can be one of the following values:
333   *            @arg USI_SPI_SS_NOT_TOGGLE , means SPI support continuous transfer when spi_cph=0
334   *            @arg USI_SPI_SS_TOGGLE, means SPI donot support continuous transfer when spi_cph=0
335   *              and SS(CS) needs break.
336   * @retval None
337   */
338 
USI_SSI_SetSSTogglePhase(USI_TypeDef * usi_dev,u32 TogglePhase)339 void USI_SSI_SetSSTogglePhase(USI_TypeDef *usi_dev, u32 TogglePhase)
340 {
341 	u32 Value;
342 	u32 trxpath = USI_SSI_GetTRxPath(usi_dev);
343 
344 	Value = usi_dev->SPI_CTRL;
345 	Value &= ~USI_SPI_SS_TOG_PHASE;
346 	Value |= (TogglePhase << 5);
347 
348 	/* SPI_SS_TOG_PHASE is writeable only when Tx and Rx path are both disable */
349 	USI_SSI_TRxPath_Cmd(usi_dev, trxpath, DISABLE);
350 	usi_dev->SPI_CTRL = Value;
351 	USI_SSI_TRxPath_Cmd(usi_dev, trxpath, ENABLE);
352 }
353 
354 
355 /**
356   * @brief  Set USI-SPI data frame size.
357   * @param  usi_dev: where usi_dev can be USI0_DEV.
358   * @param  DataFrameSize: This parameter can be one of the following values:
359   *            @arg USI_SPI_DFS_4_BITS
360   *            @arg USI_SPI_DFS_5_BITS
361   *            @arg USI_SPI_DFS_6_BITS
362   *            @arg USI_SPI_DFS_7_BITS
363   *            @arg USI_SPI_DFS_8_BITS
364   *            @arg USI_SPI_DFS_9_BITS
365   *            @arg USI_SPI_DFS_10_BITS
366   *            @arg USI_SPI_DFS_11_BITS
367   *            @arg USI_SPI_DFS_12_BITS
368   *            @arg USI_SPI_DFS_13_BITS
369   *            @arg USI_SPI_DFS_14_BITS
370   *            @arg USI_SPI_DFS_15_BITS
371   *            @arg USI_SPI_DFS_16_BITS
372   * @retval None
373   */
374 
USI_SSI_SetDataFrameSize(USI_TypeDef * usi_dev,u32 DataFrameSize)375 void USI_SSI_SetDataFrameSize(USI_TypeDef *usi_dev, u32 DataFrameSize)
376 {
377 	u32 Value;
378 	u32 trxpath = USI_SSI_GetTRxPath(usi_dev);
379 
380 	Value = usi_dev->SPI_CTRL;
381 	Value &= ~USI_SPI_DAT_FRM_SIZE;
382 	Value |= DataFrameSize;
383 
384 	USI_SSI_TRxPath_Cmd(usi_dev, trxpath, DISABLE);
385 	usi_dev->SPI_CTRL = Value;
386 	USI_SSI_TRxPath_Cmd(usi_dev, trxpath, ENABLE);
387 }
388 
389 /**
390   * @brief  Set USI-SPI Rx Sample Dealy.
391   * @param  usi_dev: where usi_dev can be USI0_DEV.
392   * @param  SampleDelay: The number of ssi_clk cycles that to be delayed.
393   * @retval None
394   */
395 
USI_SSI_SetSampleDelay(USI_TypeDef * usi_dev,u32 SampleDelay)396 void USI_SSI_SetSampleDelay(USI_TypeDef *usi_dev, u32 SampleDelay)
397 {
398 	u32 Value;
399 	u32 trxpath = USI_SSI_GetTRxPath(usi_dev);
400 
401 	Value = usi_dev->SPI_CTRL;
402 	Value &= ~USI_SPI_RX_SAMPLE_DLY;
403 	Value |= (SampleDelay << 8);
404 
405 	USI_SSI_TRxPath_Cmd(usi_dev, trxpath, DISABLE);
406 	usi_dev->SPI_CTRL = Value;
407 	USI_SSI_TRxPath_Cmd(usi_dev, trxpath, ENABLE);
408 }
409 
410 /**
411   * @brief  Set the number of data frame to be received.
412   * @note Valid only when the device is configured as a master in RX Only mode.
413   * @param  usi_dev: where usi_dev can only be USI0_DEV.
414   * @param  DataFrameNumber: The number of data frames that to be received.
415   * @retval None
416   */
417 
USI_SSI_SetReadLen(USI_TypeDef * usi_dev,u32 DataFrameNumber)418 void USI_SSI_SetReadLen(USI_TypeDef *usi_dev, u32 DataFrameNumber)
419 {
420 	u32 Value;
421 	u32 trxpath = USI_SSI_GetTRxPath(usi_dev);
422 	assert_param((DataFrameNumber >= 1)&&(DataFrameNumber <= 0x10000));
423 
424 	Value = usi_dev->SPI_TRANS_EN;
425 	Value &= ~USI_SPI_RXONLY_NUM;
426 	Value |= ((DataFrameNumber - 1) << 16);
427 
428 	USI_SSI_TRxPath_Cmd(usi_dev, trxpath, DISABLE);
429 	usi_dev->SPI_TRANS_EN = Value;
430 	USI_SSI_TRxPath_Cmd(usi_dev, trxpath, ENABLE);
431 }
432 
433 /**
434   * @brief  Set USI-SPI clock divider.
435   * @note Valid only when the device is configured as a master.
436   *    And The LSB is always set to 0,and is unaffected by a write operation.
437   * @param  usi_dev: where usi_dev can only be USI0_DEV.
438   * @param  ClockDivider: Even value between 2 and 65534.
439   *		     And Fsclk_out=Fssi_clk/ClockDivider.
440   * @retval None
441   */
442 
USI_SSI_SetBaudDiv(USI_TypeDef * usi_dev,u32 ClockDivider)443 void USI_SSI_SetBaudDiv(USI_TypeDef *usi_dev, u32 ClockDivider)
444 {
445 	u32 Value;
446 	u32 trxpath = USI_SSI_GetTRxPath(usi_dev);
447 
448 	Value = usi_dev->SPI_CTRL;
449 	Value &= ~USI_SPI_MST_BAUD;
450 	Value |= (ClockDivider << 16);
451 
452 	USI_SSI_TRxPath_Cmd(usi_dev, trxpath, DISABLE);
453 	usi_dev->SPI_CTRL = Value;
454 	USI_SSI_TRxPath_Cmd(usi_dev, trxpath, ENABLE);
455 }
456 
457 /**
458   * @brief  Set USI-SPI Master clock.
459   * @param  USIx: where SPIx can be USI0_DEV.
460   * @param  BaudRate: baudrate for SPI bus, unit is HZ.
461   * @param  IpClk: IP Clock
462   * @retval None
463   * @note Valid only when the device is configured as a master.
464   * @note BaudRate <= (IpClk/2).
465   * @note As the clock divider can only be an even number. The final baudrate this function generates
466   * 		may be a little lower than the value of  BaudRate,which is setted by user.
467   * @note Fsclk_out = Fssi_clk /SCKDV
468   * @note for FPGA IpClk = CPU_ClkGet(_TRUE)
469   * @note for ASIC IpClk = CPU_ClkGet(_FALSE)/2
470   */
471 
USI_SSI_SetBaud(USI_TypeDef * USIx,u32 BaudRate,u32 IpClk)472 void USI_SSI_SetBaud(USI_TypeDef *USIx, u32 BaudRate, u32 IpClk)
473 {
474 	u32 ClockDivider;
475 
476 	assert_param(USIx == USI0_DEV);
477 	assert_param(BaudRate <= (IpClk/2));
478 
479 	/*Adjust SCKDV-Parameter to an even number */
480 	ClockDivider = IpClk/BaudRate + 1;
481 	if ((IpClk%BaudRate) > (BaudRate/2)) {
482 		ClockDivider++;
483 	}
484 	if (ClockDivider >= 0xFFFF) {
485 		/*  devider is 16 bits */
486 		ClockDivider = 0xFFFE;
487 	}
488 	ClockDivider &= 0xFFFE;     // bit 0 always is 0
489 
490 	USI_SSI_SetBaudDiv(USIx, ClockDivider);
491 }
492 
493 /**
494   * @brief Enables or disables USI-SPI TDMA and RDMA .
495   * @param  usi_dev: where usi_dev can be USI0_DEV.
496   * @param  newState:  This parameter can be one of the following values:
497   *              @arg ENABLE
498   *              @arg DISABLE
499   * @param  Mask:  This parameter can be one of the following values or mixed:
500   *              @arg USI_TX_DMA_ENABLE
501   *              @arg USI_RX_DMA_ENABLE
502   * @retval None
503   */
504 
USI_SSI_SetDmaEnable(USI_TypeDef * usi_dev,u32 newState,u32 Mask)505 void USI_SSI_SetDmaEnable(USI_TypeDef *usi_dev, u32 newState, u32 Mask)
506 {
507 	if (newState == DISABLE)
508 		usi_dev->DMA_ENABLE &= ~Mask;
509 	else
510 		usi_dev->DMA_ENABLE |= Mask;
511 }
512 
513 /**
514   * @brief Set USI-SPI DMA TxLevel and RxLevel.
515   * @param  usi_dev: where usi_dev can be USI0_DEV.
516   * @param  TxLevel:  Transmit FIFO Threshold level.Value range: 0 to 63.
517   *		The dma_tx_req is generated when the number of valid data entries in
518   *		the transmit FIFO is equal to or below this field value.
519   * @param  RxLevel:  Receive FIFO Threshold level.Value range: 0 to 63.
520   *		The dma_rx_req is generated when the number of valid data entries in the
521   *		receive FIFO is equal to or above this field value + 1.
522   * @retval None
523   */
524 
USI_SSI_SetDmaLevel(USI_TypeDef * usi_dev,u32 TxLevel,u32 RxLevel)525 void USI_SSI_SetDmaLevel(USI_TypeDef *usi_dev, u32 TxLevel, u32 RxLevel)
526 {
527 	u32 value = usi_dev->DMA_REQ_SIZE;
528 
529 	assert_param(IS_USI_SPI_TxDMALevel(TxLevel));
530 	assert_param(IS_USI_SPI_RxDMALevel(RxLevel));
531 
532 	/* Set TX FIFO water level to trigger Tx DMA transfer */
533 	value &= ~USI_TX_DMA_BURST_SIZE;
534 	value |= (USI_SPI_TX_FIFO_DEPTH - TxLevel);
535 
536 	/* Set RX FIFO water level to trigger Rx DMA transfer */
537 	value &= ~USI_RX_DMA_BURST_SIZE;
538 	value |= ((RxLevel + 1) << 16);
539 
540 	usi_dev->DMA_REQ_SIZE = value;
541 }
542 
543 /**
544   * @brief    Init and Enable USI-SPI TX GDMA.
545   * @param  Index: 0.
546   * @param  GDMA_InitStruct: pointer to a GDMA_InitTypeDef structure that contains
547   *         the configuration information for the GDMA peripheral.
548   * @param  CallbackData: GDMA callback data.
549   * @param  CallbackFunc: GDMA callback function.
550   * @param  pTxData: Tx Buffer.
551   * @param  Length: Tx Count.
552   * @retval   TRUE/FLASE
553   */
554 
USI_SSI_TXGDMA_Init(u32 Index,PGDMA_InitTypeDef GDMA_InitStruct,void * CallbackData,IRQ_FUN CallbackFunc,u8 * pTxData,u32 Length)555 BOOL USI_SSI_TXGDMA_Init(
556 	u32 Index,
557 	PGDMA_InitTypeDef GDMA_InitStruct,
558 	void *CallbackData,
559 	IRQ_FUN CallbackFunc,
560 	u8 *pTxData,
561 	u32 Length
562 	)
563 {
564 	USI_TypeDef *USIx = USI_DEV_TABLE[Index].USIx;
565 	u32 DataFrameSize = USI_SSI_GetDataFrameSize(USIx);
566 	u8 GdmaChnl;
567 
568 	assert_param(GDMA_InitStruct != NULL);
569 
570 	GdmaChnl = GDMA_ChnlAlloc(0, CallbackFunc, (u32)CallbackData, 12);//ACUT is 0x10, BCUT is 12
571 	if (GdmaChnl == 0xFF) {
572 		// No Available DMA channel
573 		return _FALSE;
574 	}
575 
576 	_memset((void *)GDMA_InitStruct, 0, sizeof(GDMA_InitTypeDef));
577 
578 	GDMA_InitStruct->GDMA_DIR      = TTFCMemToPeri;
579 	GDMA_InitStruct->GDMA_DstHandshakeInterface   = USI_DEV_TABLE[Index].Tx_HandshakeInterface;
580 	GDMA_InitStruct->GDMA_DstAddr = (u32)&USI_DEV_TABLE[Index].USIx->TX_FIFO_WRITE;
581 	GDMA_InitStruct->GDMA_Index   = 0;
582 	GDMA_InitStruct->GDMA_ChNum       = GdmaChnl;
583 	GDMA_InitStruct->GDMA_IsrType = (BlockType|TransferType|ErrType);
584 
585 	GDMA_InitStruct->GDMA_SrcMsize   = MsizeOne;
586 	GDMA_InitStruct->GDMA_DstMsize  = MsizeFour;
587 	GDMA_InitStruct->GDMA_SrcDataWidth = TrWidthFourBytes;
588 	GDMA_InitStruct->GDMA_DstDataWidth = TrWidthOneByte;
589 	GDMA_InitStruct->GDMA_DstInc = NoChange;
590 	GDMA_InitStruct->GDMA_SrcInc = IncType;
591 
592 	/*  Cofigure GDMA transfer */
593 	if (DataFrameSize > 8) {
594 		/*  16~9 bits mode */
595 		if (((Length & 0x03)==0) && (((u32)(pTxData) & 0x03)==0)) {
596 			/*  4-bytes aligned, move 4 bytes each transfer */
597 			GDMA_InitStruct->GDMA_SrcMsize   = MsizeFour;
598 			GDMA_InitStruct->GDMA_SrcDataWidth = TrWidthFourBytes;
599 			GDMA_InitStruct->GDMA_DstMsize  = MsizeEight;
600 			GDMA_InitStruct->GDMA_DstDataWidth = TrWidthTwoBytes;
601 			GDMA_InitStruct->GDMA_BlockSize = Length >> 2;
602 		} else if (((Length & 0x01)==0) && (((u32)(pTxData) & 0x01)==0)) {
603 			/*  2-bytes aligned, move 2 bytes each transfer */
604 			GDMA_InitStruct->GDMA_SrcMsize   = MsizeEight;
605 			GDMA_InitStruct->GDMA_SrcDataWidth = TrWidthTwoBytes;
606 			GDMA_InitStruct->GDMA_DstMsize  = MsizeEight;
607 			GDMA_InitStruct->GDMA_DstDataWidth = TrWidthTwoBytes;
608 			GDMA_InitStruct->GDMA_BlockSize = Length >> 1;
609 		} else {
610 			DBG_8195A("SSI_TXGDMA_Init: Aligment Err: pTxData=0x%x,  Length=%d\n", pTxData, Length);
611 			return _FALSE;
612 		}
613 	} else {
614 		/*  8~4 bits mode */
615 		if (((Length & 0x03)==0) && (((u32)(pTxData) & 0x03)==0)) {
616 			/*  4-bytes aligned, move 4 bytes each transfer */
617 			GDMA_InitStruct->GDMA_SrcMsize   = MsizeOne;
618 			GDMA_InitStruct->GDMA_SrcDataWidth = TrWidthFourBytes;
619 			GDMA_InitStruct->GDMA_BlockSize = Length >> 2;
620 		} else {
621 			GDMA_InitStruct->GDMA_SrcMsize   = MsizeFour;
622 			GDMA_InitStruct->GDMA_SrcDataWidth = TrWidthOneByte;
623 			GDMA_InitStruct->GDMA_BlockSize = Length;
624 		}
625 		GDMA_InitStruct->GDMA_DstMsize  = MsizeFour;
626 		GDMA_InitStruct->GDMA_DstDataWidth =  TrWidthOneByte;
627 	}
628 
629 	assert_param(GDMA_InitStruct->GDMA_BlockSize <= 4096);
630 
631 	GDMA_InitStruct->GDMA_SrcAddr = (u32)pTxData;
632 
633 	/*  Enable GDMA for TX */
634 	GDMA_Init(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, GDMA_InitStruct);
635 	GDMA_Cmd(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, ENABLE);
636 
637 	return _TRUE;
638 }
639 
640 /**
641   * @brief    Init and Enable USI-SPI RX GDMA.
642   * @param  Index: 0.
643   * @param  GDMA_InitStruct: pointer to a GDMA_InitTypeDef structure that contains
644   *         the configuration information for the GDMA peripheral.
645   * @param  CallbackData: GDMA callback data.
646   * @param  CallbackFunc: GDMA callback function.
647   * @param  pRxData: Rx Buffer.
648   * @param  Length: Rx Count.
649   * @retval   TRUE/FLASE
650   */
651 
652 BOOL
USI_SSI_RXGDMA_Init(u8 Index,GDMA_InitTypeDef * GDMA_InitStruct,void * CallbackData,IRQ_FUN CallbackFunc,u8 * pRxData,u32 Length)653 USI_SSI_RXGDMA_Init(
654 	u8 Index,
655 	GDMA_InitTypeDef *GDMA_InitStruct,
656 	void *CallbackData,
657 	IRQ_FUN CallbackFunc,
658 	u8  *pRxData,
659 	u32 Length
660 )
661 {
662 	USI_TypeDef *USIx = USI_DEV_TABLE[Index].USIx;
663 	u32 DataFrameSize = USI_SSI_GetDataFrameSize(USIx);
664 	u8 GdmaChnl;
665 
666 	assert_param(GDMA_InitStruct != NULL);
667 
668 	GdmaChnl = GDMA_ChnlAlloc(0, CallbackFunc, (u32)CallbackData, 12);//ACUT is 0x10, BCUT is 12
669 	if (GdmaChnl == 0xFF) {
670 		// No Available DMA channel
671 		return _FALSE;
672 	}
673 
674 	_memset((void *)GDMA_InitStruct, 0, sizeof(GDMA_InitTypeDef));
675 
676 	GDMA_InitStruct->GDMA_DIR      = TTFCPeriToMem;
677 	GDMA_InitStruct->GDMA_ReloadSrc = 0;
678 	GDMA_InitStruct->GDMA_SrcHandshakeInterface    = USI_DEV_TABLE[Index].Rx_HandshakeInterface;
679 	GDMA_InitStruct->GDMA_SrcAddr = (u32)&USI_DEV_TABLE[Index].USIx->RX_FIFO_READ;
680 	GDMA_InitStruct->GDMA_Index   = 0;
681 	GDMA_InitStruct->GDMA_ChNum       = GdmaChnl;
682 	GDMA_InitStruct->GDMA_IsrType = (BlockType|TransferType|ErrType);
683 
684 	GDMA_InitStruct->GDMA_SrcMsize   = MsizeEight;
685 	GDMA_InitStruct->GDMA_DstMsize  = MsizeFour;
686 	GDMA_InitStruct->GDMA_SrcDataWidth = TrWidthTwoBytes;
687 	GDMA_InitStruct->GDMA_DstDataWidth = TrWidthFourBytes;
688 	GDMA_InitStruct->GDMA_DstInc = IncType;
689 	GDMA_InitStruct->GDMA_SrcInc = NoChange;
690 
691 	/*  Cofigure GDMA transfer */
692 	if (DataFrameSize > 8) {
693 		/*  16~9 bits mode */
694 		GDMA_InitStruct->GDMA_SrcMsize   = MsizeFour;
695 		GDMA_InitStruct->GDMA_SrcDataWidth = TrWidthTwoBytes;
696 		GDMA_InitStruct->GDMA_BlockSize = Length >> 1;
697 
698 		if (((Length & 0x03)==0) && (((u32)(pRxData) & 0x03)==0)) {
699 			/*  4-bytes aligned, move 4 bytes each transfer */
700 			GDMA_InitStruct->GDMA_DstMsize  = MsizeFour;
701 			GDMA_InitStruct->GDMA_DstDataWidth = TrWidthFourBytes;
702 		} else if (((Length & 0x01)==0) &&	(((u32)(pRxData) & 0x01)==0)) {
703 			/*  2-bytes aligned, move 2 bytes each transfer */
704 			GDMA_InitStruct->GDMA_DstMsize  = MsizeEight;
705 			GDMA_InitStruct->GDMA_DstDataWidth = TrWidthTwoBytes;
706 		} else {
707 			DBG_8195A("SSI_RXGDMA_Init: Aligment Err: pTxData=0x%x,  Length=%d\n", pRxData, Length);
708 			return _FALSE;
709 		}
710 	} else {
711 		/*  8~4 bits mode */
712 		GDMA_InitStruct->GDMA_SrcMsize   = MsizeFour;
713 		GDMA_InitStruct->GDMA_SrcDataWidth =  TrWidthOneByte;
714 		GDMA_InitStruct->GDMA_BlockSize = Length;
715 		if (((Length & 0x03)==0) && (((u32)(pRxData) & 0x03)==0)) {
716 			/*  4-bytes aligned, move 4 bytes each transfer */
717 			GDMA_InitStruct->GDMA_DstMsize  = MsizeOne;
718 			GDMA_InitStruct->GDMA_DstDataWidth = TrWidthFourBytes;
719 		} else {
720 			GDMA_InitStruct->GDMA_DstMsize  = MsizeFour;
721 			GDMA_InitStruct->GDMA_DstDataWidth = TrWidthOneByte;
722 		}
723 	}
724 
725 	assert_param(GDMA_InitStruct->GDMA_BlockSize <= 4096);
726 
727 	GDMA_InitStruct->GDMA_DstAddr = (u32)pRxData;
728 
729 	/*  Enable GDMA for RX */
730 	GDMA_Init(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, GDMA_InitStruct);
731 	GDMA_Cmd(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, ENABLE);
732 
733 	return _TRUE;
734 }
735 
736 /**
737   * @brief Clear USI-SPI interrupt status.
738   * @param  usi_dev: where usi_dev can be USI0_DEV.
739   * @param  InterruptStatus:  The value of current interrupt status .
740   * @retval None
741   */
742 
USI_SSI_SetIsrClean(USI_TypeDef * usi_dev,u32 InterruptStatus)743 void USI_SSI_SetIsrClean(USI_TypeDef *usi_dev, u32 InterruptStatus)
744 {
745 	usi_dev->INTERRUPT_STATUS_CLR = InterruptStatus & USI_SPI_INTERRUPT_CLEAR_MASK;
746 }
747 
748 /**
749   * @brief Write data to USI-SPI transmit FIFO.
750   * @param  usi_dev: where usi_dev can be USI0_DEV.
751   * @param  value:  The data value that is to be transmitted .
752   * @retval None
753   */
754 
USI_SSI_WriteData(USI_TypeDef * usi_dev,u32 value)755 void USI_SSI_WriteData(USI_TypeDef *usi_dev, u32 value)
756 {
757 	usi_dev->TX_FIFO_WRITE = (value & USI_TX_FIFO_WRITE_DATA);
758 }
759 
760 /**
761   * @brief Set USI-SPI Rx FIFO threshold level
762   * @param  usi_dev: where usi_dev can be USI0_DEV.
763   * @param  RxThresholdLevel:  Rx FIFO Threshold Level.Value range: 0 to 63.
764   *		When the number of receive FIFO entries is greater than or equal to
765   *		this value + 1, the receive FIFO full interrupt is triggered.
766   * @retval None
767   */
768 
USI_SSI_SetRxFifoLevel(USI_TypeDef * usi_dev,u32 RxThresholdLevel)769 void USI_SSI_SetRxFifoLevel(USI_TypeDef *usi_dev, u32 RxThresholdLevel)
770 {
771 	assert_param(IS_USI_SPI_RxThresholdLevel(RxThresholdLevel));
772 
773 	usi_dev->RX_FIFO_CTRL = RxThresholdLevel + 1;
774 }
775 
776 /**
777   * @brief Set USI-SPI Tx FIFO threshold level.
778   * @param  usi_dev: where usi_dev can be USI0_DEV.
779   * @param  TxThresholdLevel:  Tx FIFO Threshold Level.Value range: 0 to 63.
780   *		When the number of transmit FIFO entries is less than or equal to this
781   *		value, the transmit FIFO empty interrupt is triggered.
782   * @retval None
783   */
784 
USI_SSI_SetTxFifoLevel(USI_TypeDef * usi_dev,u32 TxThresholdLevel)785 void USI_SSI_SetTxFifoLevel(USI_TypeDef *usi_dev, u32 TxThresholdLevel)
786 {
787 	assert_param(IS_USI_SPI_TxThresholdLevel(TxThresholdLevel));
788 
789 	usi_dev->TX_FIFO_CTRL = USI_SPI_TX_FIFO_DEPTH - TxThresholdLevel;
790 }
791 
792 /**
793   * @brief  Detemines whether USI-SPI transmit FIFO is full or not
794   * @param  usi_dev: where usi_dev can be USI0_DEV.
795   * @retval Transmit FIFO is full or not:
796   *        - 1: Not Full
797   *        - 0: Full
798   */
799 
USI_SSI_Writeable(USI_TypeDef * usi_dev)800 u32 USI_SSI_Writeable(USI_TypeDef *usi_dev)
801 {
802 	u32 Status = USI_SSI_GetTxFIFOStatus(usi_dev);
803 	u32 Writeable = (((Status & USI_TXFIFO_FULL) == 0) ? 1 : 0);
804 
805 	return Writeable;
806 }
807 
808 /**
809   * @brief  Detemine USI-SPI Receive FIFO is empty or not.
810   * @param  usi_dev: where usi_dev can be USI0_DEV.
811   * @retval Receive FIFO is empty or not:
812   *        - 1: Not Empty
813   *        - 0: Empty
814   */
815 
USI_SSI_Readable(USI_TypeDef * usi_dev)816 u32 USI_SSI_Readable(USI_TypeDef *usi_dev)
817 {
818 	u32 Status = USI_SSI_GetRxFIFOStatus(usi_dev);
819 	u32 Readable = (((Status & USI_RXFIFO_EMPTY) == 0) ? 1 : 0);
820 
821 	return Readable;
822 }
823 
824 /**
825   * @brief Read data from USI-SPI receive FIFO .
826   * @param  usi_dev: where usi_dev can be USI0_DEV.
827   * @retval The data received.
828   */
829 
USI_SSI_ReadData(USI_TypeDef * usi_dev)830 u32 USI_SSI_ReadData(USI_TypeDef *usi_dev)
831 {
832 	return usi_dev->RX_FIFO_READ;
833 }
834 
835 /**
836   * @brief  receive data from rx FIFO
837   * @param  usi_dev: where usi_dev can be USI0_DEV.
838   * @param  RxData: buffer to save data read from USI-SPI FIFO.
839   * @param  Length: number of data to be read.
840   * @retval transfer len
841   */
842 
USI_SSI_ReceiveData(USI_TypeDef * usi_dev,void * RxData,u32 Length)843 u32 USI_SSI_ReceiveData(USI_TypeDef *usi_dev,
844 	void* RxData,
845 	u32 Length
846 	)
847 {
848 	u32 ReceiveLevel;
849 	u32 DataFrameSize = USI_SSI_GetDataFrameSize(usi_dev);
850 	volatile u32 Readable = USI_SSI_Readable(usi_dev);
851 	u32 RxLength = Length;
852 
853 	while (Readable) {
854 		ReceiveLevel = USI_SSI_GetRxCount(usi_dev);
855 
856 		while (ReceiveLevel--) {
857 			if (RxData != NULL) {
858 				if (DataFrameSize > 8) {
859 					/*  16~9 bits mode */
860 					*((u16*)(RxData)) = (u16)USI_SSI_ReadData(usi_dev);
861 					RxData = (VOID*)(((u16*)RxData) + 1);
862 				} else {
863 					/*  8~4 bits mode */
864 					*((u8*)(RxData)) = (u8)USI_SSI_ReadData(usi_dev);
865 					RxData = (VOID*)(((u8*)RxData) + 1);
866 				}
867 			} else {
868 				/*  for Master mode, doing TX also will got RX data, so drop the dummy data */
869 				USI_SSI_ReadData(usi_dev);
870 			}
871 
872 			if (RxLength > 0) {
873 				RxLength--;
874 			}
875 			if (RxLength == 0) {
876 				break;
877 			}
878 		}
879 
880 		if (RxLength == 0) {
881 			break;
882 		}
883 
884 		Readable = USI_SSI_Readable(usi_dev);
885 	}
886 
887 	return (Length - RxLength);
888 }
889 
890 /**
891   * @brief  Send data to tx FIFO
892   * @param  usi_dev: where usi_dev can be USI0_DEV.
893   * @param  TxData: buffer to be written to Tx FIFO.
894   * @param  Length: number of data to be written.
895   * @param  Role: USI_SPI_MASTER or USI_SPI_SLAVE.
896   * @retval transfer len
897   */
898 
USI_SSI_SendData(USI_TypeDef * usi_dev,void * TxData,u32 Length,u32 Role)899 u32 USI_SSI_SendData(USI_TypeDef *usi_dev,
900 	void* TxData,
901 	u32 Length,
902 	u32 Role
903 	)
904 {
905 	u32 Writeable     = USI_SSI_Writeable(usi_dev);
906 	u32 TxWriteMax    = USI_SPI_TX_FIFO_DEPTH - USI_SSI_GetTxCount(usi_dev);
907 	u32 DataFrameSize = USI_SSI_GetDataFrameSize(usi_dev);
908 	u32 TxLength = Length;
909 
910 	if (Writeable) {
911 		/* Disable Tx FIFO Empty IRQ */
912 		USI_SSI_INTConfig(usi_dev, USI_TXFIFO_ALMOST_EMTY_INTR_EN, DISABLE);
913 
914 		while (TxWriteMax--) {
915 			if (DataFrameSize > 8) {
916 				// 16~9 bits mode
917 				if (TxData != NULL) {
918 					USI_SSI_WriteData(usi_dev, *((u16*)(TxData)));
919 					TxData = (VOID*)(((u16*)TxData) + 1);
920 				} else {
921 					// For master mode: Push a dummy to TX FIFO for Read
922 					if (Role == USI_SPI_MASTER) {
923 						USI_SSI_WriteData(usi_dev, (u16)0);// Dummy byte
924 					}
925 				}
926 			} else {
927 				// 8~4 bits mode
928 				if (TxData != NULL) {
929 					USI_SSI_WriteData(usi_dev, *((u8*)(TxData)));
930 					TxData = (VOID*)(((u8*)TxData) + 1);
931 				} else {
932 					// For master mode: Push a dummy to TX FIFO for Read
933 					if (Role == USI_SPI_MASTER) {
934 						USI_SSI_WriteData(usi_dev, (u8)0);// Dummy byte
935 					}
936 				}
937 			}
938 
939 			TxLength--;
940 
941 			if (TxLength == 0)
942 				break;
943 		}
944 
945 		/* Enable Tx FIFO Empty IRQ */
946 		USI_SSI_INTConfig(usi_dev, USI_TXFIFO_ALMOST_EMTY_INTR_EN, ENABLE);
947 	}
948 
949 	return (Length - TxLength);
950 }
951 
952 /**
953   * @brief Get the number of valid entries in receive FIFO.
954   * @param  usi_dev: where usi_dev can be USI0_DEV.
955   * @retval  The number of valid entries in receive FIFO.Value range:0-64.
956   */
957 
USI_SSI_GetRxCount(USI_TypeDef * usi_dev)958 u32 USI_SSI_GetRxCount(USI_TypeDef *usi_dev)
959 {
960 	u32 valid_cnt = (USI_SSI_GetRxFIFOStatus(usi_dev) & USI_RXFIFO_VALID_CNT) >> 8;
961 	return valid_cnt;
962 }
963 
964 /**
965   * @brief Get the number of valid entries in transmit FIFO.
966   * @param  usi_dev: where usi_dev can be USI0_DEV.
967   * @retval  The number of valid entries in transmit FIFO.Value range:0-64.
968   */
969 
USI_SSI_GetTxCount(USI_TypeDef * usi_dev)970 u32 USI_SSI_GetTxCount(USI_TypeDef *usi_dev)
971 {
972 	u32 empty_cnt = (USI_SSI_GetTxFIFOStatus(usi_dev) & USI_TXFIFO_EMPTY_SPACE) >> 8;
973 	return USI_SPI_TX_FIFO_DEPTH - empty_cnt;
974 }
975 
976 /**
977   * @brief Get USI-SPI Tx FIFO status.
978   * @param  usi_dev: where usi_dev can be USI0_DEV.
979   * @retval  Current Tx FIFO status:
980   *
981   *		bit [8:14] : USI_TXFIFO_EMPTY_SPACE
982   *			- Tx FIFO empty entry count
983   *
984   *		bit 2 : USI_TXFIFO_ALMOST_EMPTY_COPY
985   *			- 0 : Tx FIFO not almost empty
986   *			- 1 : Tx FIFO almost empty
987   *
988   *		bit 1 : USI_TXFIFO_EMPTY
989   *			- 0 : Tx FIFO not empty
990   *			- 1 : Tx FIFO is empty
991   *
992   *		bit 0 : USI_TXFIFO_FULL
993   *			- 0 : Tx FIFO not full
994   *			- 1 : Tx FIFO is full
995   *
996   */
USI_SSI_GetTxFIFOStatus(USI_TypeDef * usi_dev)997 u32 USI_SSI_GetTxFIFOStatus(USI_TypeDef *usi_dev)
998 {
999 	return usi_dev->TX_FIFO_STATUS;
1000 }
1001 
1002 /**
1003   * @brief Get USI-SPI Rx FIFO status.
1004   * @param  usi_dev: where usi_dev can be USI0_DEV.
1005   * @retval  Current Rx FIFO status:
1006   *
1007   *		bit [8:14] : USI_RXFIFO_VALID_CNT
1008   *			- Rx FIFO valid count
1009   *
1010   *		bit 2 : USI_RXFIFO_ALMOST_FULL_COPY
1011   *			- 0 : Rx FIFO not almost full
1012   *			- 1 : Rx FIFO almost full
1013   *
1014   *		bit 1 : USI_RXFIFO_EMPTY
1015   *			- 0 : Rx FIFO not empty
1016   *			- 1 : Rx FIFO is empty
1017   *
1018   *		bit 0 : USI_RXFIFO_FULL
1019   *			- 0 : Rx FIFO not full
1020   *			- 1 : Rx FIFO is full
1021   *
1022   */
USI_SSI_GetRxFIFOStatus(USI_TypeDef * usi_dev)1023 u32 USI_SSI_GetRxFIFOStatus(USI_TypeDef *usi_dev)
1024 {
1025 	return usi_dev->RX_FIFO_STATUS;
1026 }
1027 
1028 /**
1029   * @brief Get USI-SPI transfer status.
1030   * @param  usi_dev: where usi_dev can be USI0_DEV.
1031   * @retval  Current transfer status,each bit of this value represents one
1032   *		transfer status which is as follows:
1033   *
1034   *		bit 4 : USI_SPI_SLV_RX_ACTIVITY
1035   *			- 0 : SPI slave Rx path idle
1036   *			- 1 : SPI slave Rx path is active
1037   *
1038   *		bit 3 : USI_SPI_SLV_TX_ACTIVITY
1039   *			- 0 : SPI slave Tx path idle
1040   *			- 1 : SPI slave Tx path is active
1041   *
1042   *		bit 2 : USI_SPI_MST_RX_ACTIVITY
1043   *			- 0 : SPI master Rx path idle
1044   *			- 1 : SPI master Rx path is active
1045   *
1046   *		bit 1 : USI_SPI_MST_TX_ACTIVITY
1047   *			- 0 : SPI master Tx path idle
1048   *			- 1 : SPI master Tx path is active
1049   *
1050   *		bit 0 : USI_SPI_ACTIVITY
1051   *			- 0 : idle
1052   *			- 1 : active transferring data
1053   *
1054   */
USI_SSI_GetTransStatus(USI_TypeDef * usi_dev)1055 u32 USI_SSI_GetTransStatus(USI_TypeDef *usi_dev)
1056 {
1057 	return usi_dev->SPI_TRANS_STATUS;
1058 }
1059 
1060 
1061 /**
1062   * @brief Get USI-SPI data frame size.
1063   * @param  usi_dev: where usi_dev can be USI0_DEV.
1064   * @retval  Data frame size(value range : 4-16):
1065   *		- n : current data frame length is n bits
1066   */
1067 
USI_SSI_GetDataFrameSize(USI_TypeDef * usi_dev)1068 u32 USI_SSI_GetDataFrameSize(USI_TypeDef *usi_dev)
1069 {
1070 	u32 size = ((usi_dev->SPI_CTRL) & USI_SPI_DAT_FRM_SIZE) + 1;
1071 	return size;
1072 }
1073 
1074 /**
1075   * @brief  Detemine USI-SPI is busy or not.
1076   * @param  usi_dev: where usi_dev can be USI0_DEV.
1077   * @retval USI-SPI busy status value:
1078   *           - 1: Busy
1079   *           - 0: Not Busy
1080   */
1081 
USI_SSI_Busy(USI_TypeDef * usi_dev)1082 u32 USI_SSI_Busy(USI_TypeDef *usi_dev)
1083 {
1084 	u32 Status = USI_SSI_GetTransStatus(usi_dev);
1085 	u32 Busy = (((Status & USI_SPI_ACTIVITY) != 0) ? 1 : 0);
1086 
1087 	return Busy;
1088 }
1089 
1090 /**
1091   * @brief Get USI-SPI Interrupt Status.
1092   * @param  usi_dev: where usi_dev can be USI0_DEV.
1093   * @retval Current Interrupt Status,each bit of this value represents one
1094   *		interrupt status which is as follows:
1095   *
1096   *          bit 16: USI_SPI_RX_DATA_FRM_ERR_INTS
1097   *		  	- 0 : spi_rx_data_frame_err_intr interrupt not active after masking
1098   *			- 1 : spi_rx_data_frame_err_intr interrupt is active after masking
1099 
1100   *		bit 6 : USI_RXFIFO_UNDERFLOW_INTS
1101   *			- 0 : rxfifo_underflow_intr interrupt not active after masking
1102   *			- 1 : rxfifo_underflow_intr interrupt is active after masking
1103   *
1104   *		bit 5 : USI_RXFIFO_OVERFLOW_INTS
1105   *			- 0 : rxfifo_overflow_intr interrupt is not active after masking
1106   *			- 1 : rxfifo_overflow_intr interrupt is full after masking
1107   *
1108   *		bit 4 : USI_RXFIFO_ALMOST_FULL_INTS
1109   *			- 0 : rxfifo_almost_full_intr interrupt is not active after masking
1110   *			- 1 : rxfifo_almost_full_intr interrupt is active after masking
1111   *
1112   *		bit 2 : USI_TXFIFO_UNDERFLOW_INTS
1113   *			- 0 : txfifo_underflow_intr interrupt is not active after masking
1114   * 		       - 1 : txfifo_underflow_intr interrupt is active after masking
1115   *
1116   *		bit 1 : USI_TXFIFO_OVERFLOW_INTS
1117   *			- 0 : txfifo_overflow_intr interrupt is not active after masking
1118   *			- 1 : txfifo_overflow_intr interrupt is active after masking
1119   *
1120   *		bit 0 : USI_TXFIFO_ALMOST_EMTY_INTS
1121   *			- 0 : txfifo_almost_empty_intr interrupt is not active after masking
1122   *			- 1 : txfifo_almost_empty_intr interrupt is active after masking
1123   */
1124 
USI_SSI_GetIsr(USI_TypeDef * usi_dev)1125 u32 USI_SSI_GetIsr(USI_TypeDef *usi_dev)
1126 {
1127 	return usi_dev->INTERRUPT_STATUS;
1128 }
1129 
1130 /**
1131   * @brief Get USI-SPI Raw Interrupt Status.
1132   * @param  usi_dev: where usi_dev can be USI0_DEV.
1133   * @retval  Current Raw Interrupt Status,each bit of this value represents one
1134   *		raw interrupt status which is as follows:
1135   *
1136   *          bit 16: USI_SPI_RX_DATA_FRM_ERR_RSTS
1137   *		  	- 0 : spi_rx_data_frame_err_intr interrupt not active before masking
1138   *			- 1 : spi_rx_data_frame_err_intr interrupt is active before masking
1139   *
1140   *		bit 6 : USI_RXFIFO_UNDERFLOW_RSTS
1141   *			- 0 : rxfifo_underflow_intr interrupt not active before masking
1142   *			- 1 : rxfifo_underflow_intr interrupt is active before masking
1143   *
1144   *		bit 5 : USI_RXFIFO_OVERFLOW_RSTS
1145   *			- 0 : rxfifo_overflow_intr interrupt is not active before masking
1146   *			- 1 : rxfifo_overflow_intr interrupt is full before masking
1147   *
1148   *		bit 4 : USI_RXFIFO_ALMOST_FULL_RSTS
1149   *			- 0 : rxfifo_almost_full_intr interrupt is not active before masking
1150   *			- 1 : rxfifo_almost_full_intr interrupt is active before masking
1151   *
1152   *		bit 2 : USI_TXFIFO_UNDERFLOW_RSTS
1153   *			- 0 : txfifo_underflow_intr interrupt is not active before masking
1154   * 		       - 1 : txfifo_underflow_intr interrupt is active before masking
1155   *
1156   *		bit 1 : USI_TXFIFO_OVERFLOW_RSTS
1157   *			- 0 : txfifo_overflow_intr interrupt is not active before masking
1158   *			- 1 : txfifo_overflow_intr interrupt is active before masking
1159   *
1160   *		bit 0 : USI_TXFIFO_ALMOST_EMTY_RSTS
1161   *			- 0 : txfifo_almost_empty_intr interrupt is not active before masking
1162   *			- 1 : txfifo_almost_empty_intr interrupt is active before masking
1163   *
1164   */
USI_SSI_GetRawIsr(USI_TypeDef * usi_dev)1165 u32 USI_SSI_GetRawIsr(USI_TypeDef *usi_dev)
1166 {
1167 	return usi_dev->RAW_INTERRUPT_STATUS;
1168 }
1169 
1170 
1171 /******************* (C) COPYRIGHT 2016 Realtek Semiconductor *****END OF FILE****/
1172 
1173