1 /**
2  *
3  * \file
4  *
5  * \brief NMC1500 Peripherials Application Interface.
6  *
7  * Copyright (c) 2016-2017 Atmel Corporation. All rights reserved.
8  *
9  * \asf_license_start
10  *
11  * \page License
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions are met:
15  *
16  * 1. Redistributions of source code must retain the above copyright notice,
17  *    this list of conditions and the following disclaimer.
18  *
19  * 2. Redistributions in binary form must reproduce the above copyright notice,
20  *    this list of conditions and the following disclaimer in the documentation
21  *    and/or other materials provided with the distribution.
22  *
23  * 3. The name of Atmel may not be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
27  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
29  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
30  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  *
38  * \asf_license_stop
39  *
40  */
41 
42 #ifdef _M2M_ATE_FW_
43 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
44 INCLUDES
45 *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
46 #include "driver/include/m2m_ate_mode.h"
47 #include "driver/source/nmasic.h"
48 #include "driver/source/nmdrv.h"
49 #include "m2m_hif.h"
50 #include "driver/source/nmbus.h"
51 #include "bsp/include/nm_bsp.h"
52 
53 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
54 MACROS
55 *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
56 #define rInterrupt_CORTUS_0				(0x10a8)
57 #define rInterrupt_CORTUS_1				(0x10ac)
58 #define rInterrupt_CORTUS_2				(0x10b0)
59 
60 #define rBurstTx_NMI_TX_RATE				(0x161d00)
61 #define rBurstTx_NMI_NUM_TX_FRAMES			(0x161d04)
62 #define rBurstTx_NMI_TX_FRAME_LEN			(0x161d08)
63 #define rBurstTx_NMI_TX_CW_PARAM			(0x161d0c)
64 #define rBurstTx_NMI_TX_GAIN				(0x161d10)
65 #define rBurstTx_NMI_TX_DPD_CTRL			(0x161d14)
66 #define rBurstTx_NMI_USE_PMU				(0x161d18)
67 #define rBurstTx_NMI_TEST_CH				(0x161d1c)
68 #define rBurstTx_NMI_TX_PHY_CONT			(0x161d20)
69 #define rBurstTx_NMI_TX_CW_MODE				(0x161d24)
70 #define rBurstTx_NMI_TEST_XO_OFF			(0x161d28)
71 #define rBurstTx_NMI_USE_EFUSE_XO_OFF 		(0x161d2c)
72 
73 #define rBurstTx_NMI_MAC_FILTER_ENABLE_DA 	(0x161d30)
74 #define rBurstTx_NMI_MAC_ADDR_LO_PEER 		(0x161d34)
75 #define rBurstTx_NMI_MAC_ADDR_LO_SELF 		(0x161d38)
76 #define rBurstTx_NMI_MAC_ADDR_HI_PEER 		(0x161d3c)
77 #define rBurstTx_NMI_MAC_ADDR_HI_SELF		(0x161d40)
78 #define rBurstTx_NMI_RX_PKT_CNT_SUCCESS 	(0x161d44)
79 #define rBurstTx_NMI_RX_PKT_CNT_FAIL 		(0x161d48)
80 #define rBurstTx_NMI_SET_SELF_MAC_ADDR 		(0x161d4c)
81 #define rBurstTx_NMI_MAC_ADDR_LO_SA 		(0x161d50)
82 #define rBurstTx_NMI_MAC_ADDR_HI_SA 		(0x161d54)
83 #define rBurstTx_NMI_MAC_FILTER_ENABLE_SA 	(0x161d58)
84 
85 #define rBurstRx_NMI_RX_ALL_PKTS_CONT	(0x9898)
86 #define rBurstRx_NMI_RX_ERR_PKTS_CONT	(0x988c)
87 
88 #define TX_DGAIN_MAX_NUM_REGS			(4)
89 #define TX_DGAIN_REG_BASE_ADDRESS		(0x1240)
90 #define TX_GAIN_CODE_MAX_NUM_REGS		(3)
91 #define TX_GAIN_CODE_BASE_ADDRESS		(0x1250)
92 #define TX_PA_MAX_NUM_REGS				(3)
93 #define TX_PA_BASE_ADDRESS				(0x1e58)
94 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
95 VARIABLES
96 *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
97 volatile static uint8	gu8AteIsRunning	= 0;	/*!< ATE firmware status, 1 means ATE is running otherwise stopped */
98 volatile static uint8	gu8RxState		= 0;	/*!< RX status, 1 means Rx is running otherwise stopped */
99 volatile static uint8	gu8TxState		= 0;	/*!< TX status, 1 means Tx is running otherwise stopped */
100 volatile static uint32	gaAteFwTxRates[M2M_ATE_MAX_NUM_OF_RATES] =
101 {
102 	0x01, 0x02, 0x05, 0x0B,							/*B-Rats*/
103 	0x06, 0x09, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x36,	/*G-Rats*/
104 	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87	/*N-Rats*/
105 };
106 
107 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
108 STATIC FUNCTIONS
109 *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
m2m_ate_set_rx_status(uint8 u8Value)110 static void m2m_ate_set_rx_status(uint8 u8Value)
111 {
112 	gu8RxState = u8Value;
113 }
114 
m2m_ate_set_tx_status(uint8 u8Value)115 static void m2m_ate_set_tx_status(uint8 u8Value)
116 {
117 	gu8TxState = u8Value;
118 }
119 
120 /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
121 FUNCTION IMPLEMENTATION
122 *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
123 /*!
124 @fn	\
125 	sint8 m2m_ate_init(void);
126 
127 @brief
128 	This function used to download ATE firmware from flash and start it
129 
130 @return
131 	The function SHALL return 0 for success and a negative value otherwise.
132 */
m2m_ate_init(void)133 sint8 m2m_ate_init(void)
134 {
135 	sint8 s8Ret = M2M_SUCCESS;
136 	uint8 u8WifiMode = M2M_WIFI_MODE_ATE_HIGH;
137 
138 	s8Ret = nm_drv_init(&u8WifiMode);
139 
140 	return s8Ret;
141 }
142 
143 /*!
144 @fn	\
145 	sint8 m2m_ate_init(tstrM2mAteInit *pstrInit);
146 
147 @brief
148 	This function used to download ATE firmware from flash and start it
149 
150 @return
151 	The function SHALL return 0 for success and a negative value otherwise.
152 */
m2m_ate_init_param(tstrM2mAteInit * pstrInit)153 sint8 m2m_ate_init_param(tstrM2mAteInit *pstrInit)
154 {
155 	sint8 s8Ret = M2M_SUCCESS;
156 
157 	s8Ret = nm_drv_init((void*)&pstrInit->u8RxPwrMode);
158 
159 	return s8Ret;
160 }
161 
162 /*!
163 @fn	\
164 	sint8 m2m_ate_deinit(void);
165 
166 @brief
167 	De-Initialization of ATE firmware mode
168 
169 @return
170 	The function SHALL return 0 for success and a negative value otherwise.
171 */
m2m_ate_deinit(void)172 sint8 m2m_ate_deinit(void)
173 {
174 	return nm_drv_deinit(NULL);
175 }
176 
177 /*!
178 @fn	\
179 	sint8 m2m_ate_set_fw_state(uint8);
180 
181 @brief
182 	This function used to change ATE firmware status from running to stopped or vice versa.
183 
184 @param [in]	u8State
185 		Required state of ATE firmware, one of \ref tenuM2mAteFwState enumeration values.
186 @return
187 	The function SHALL return 0 for success and a negative value otherwise.
188 \sa
189 	m2m_ate_init
190 */
m2m_ate_set_fw_state(uint8 u8State)191 sint8 m2m_ate_set_fw_state(uint8 u8State)
192 {
193 	sint8		s8Ret	= M2M_SUCCESS;
194 	uint32_t	u32Val	= 0;
195 
196 	if((M2M_ATE_FW_STATE_STOP == u8State) && (M2M_ATE_FW_STATE_STOP != gu8AteIsRunning))
197 	{
198 		u32Val = nm_read_reg(rNMI_GLB_RESET);
199 		u32Val &= ~(1 << 10);
200 		s8Ret = nm_write_reg(rNMI_GLB_RESET, u32Val);
201 		gu8AteIsRunning = M2M_ATE_FW_STATE_STOP;
202 	}
203 	else if((M2M_ATE_FW_STATE_RUN == u8State) && (M2M_ATE_FW_STATE_RUN != gu8AteIsRunning))
204 	{
205 		/* 0x1118[0]=0 at power-on-reset: pad-based control. */
206 		/* Switch cortus reset register to register control. 0x1118[0]=1. */
207 		u32Val = nm_read_reg(rNMI_BOOT_RESET_MUX);
208 		u32Val |= (1 << 0);
209 		s8Ret = nm_write_reg(rNMI_BOOT_RESET_MUX, u32Val);
210 		if(M2M_SUCCESS != s8Ret)
211 		{
212 			goto __EXIT;
213 		}
214 		/**
215 		Write the firmware download complete magic value 0x10ADD09E at
216 		location 0xFFFF000C (Cortus map) or C000C (AHB map).
217 		This will let the boot-rom code execute from RAM.
218 		**/
219 		s8Ret = nm_write_reg(0xc0000, 0x71);
220 		if(M2M_SUCCESS != s8Ret)
221 		{
222 			goto __EXIT;
223 		}
224 
225 		u32Val = nm_read_reg(rNMI_GLB_RESET);
226 		if((u32Val & (1ul << 10)) == (1ul << 10))
227 		{
228 			u32Val &= ~(1ul << 10);
229 			s8Ret = nm_write_reg(rNMI_GLB_RESET, u32Val);
230 			if(M2M_SUCCESS != s8Ret)
231 			{
232 				goto __EXIT;
233 			}
234 		}
235 
236 		u32Val |= (1ul << 10);
237 		s8Ret = nm_write_reg(rNMI_GLB_RESET, u32Val);
238 		if(M2M_SUCCESS != s8Ret)
239 		{
240 			goto __EXIT;
241 		}
242 		gu8AteIsRunning = M2M_ATE_FW_STATE_RUN;
243 	}
244 	else
245 	{
246 		s8Ret = M2M_ATE_ERR_UNHANDLED_CASE;
247 	}
248 
249 __EXIT:
250 	if((M2M_SUCCESS == s8Ret) && (M2M_ATE_FW_STATE_RUN == gu8AteIsRunning))
251 	{
252 		nm_bsp_sleep(500);	/*wait for ATE firmware start up*/
253 	}
254 	return s8Ret;
255 }
256 
257 /*!
258 @fn	\
259 	sint8 m2m_ate_get_fw_state(uint8);
260 
261 @brief
262 	This function used to return status of ATE firmware.
263 
264 @return
265 	The function SHALL return status of ATE firmware, one of \ref tenuM2mAteFwState enumeration values.
266 \sa
267 	m2m_ate_init, m2m_ate_set_fw_state
268 */
m2m_ate_get_fw_state(void)269 sint8 m2m_ate_get_fw_state(void)
270 {
271 	return gu8AteIsRunning;
272 }
273 
274 /*!
275 @fn	\
276 	uint32 m2m_ate_get_tx_rate(uint8);
277 
278 @brief
279 	This function used to return value of TX rate required by application developer.
280 
281 @param [in]	u8Index
282 		Index of required rate , one of \ref tenuM2mAteTxIndexOfRates enumeration values.
283 @return
284 	The function SHALL return 0 for in case of failure otherwise selected rate value.
285 \sa
286 	tenuM2mAteTxIndexOfRates
287 */
m2m_ate_get_tx_rate(uint8 u8Index)288 uint32 m2m_ate_get_tx_rate(uint8 u8Index)
289 {
290 	if(M2M_ATE_MAX_NUM_OF_RATES <= u8Index)
291 	{
292 		return 0;
293 	}
294 	return gaAteFwTxRates[u8Index];
295 }
296 
297 /*!
298 @fn	\
299 	sint8 m2m_ate_get_tx_status(void);
300 
301 @brief
302 	This function used to return status of TX test case either running or stopped.
303 
304 @return
305 	The function SHALL return status of ATE firmware, 1 if TX is running otherwise 0.
306 \sa
307 	m2m_ate_start_tx, m2m_ate_stop_tx
308 */
m2m_ate_get_tx_status(void)309 sint8 m2m_ate_get_tx_status(void)
310 {
311 	return gu8TxState;
312 }
313 
314 /*!
315 @fn	\
316 	sint8 m2m_ate_start_tx(tstrM2mAteTx *)
317 
318 @brief
319 	This function used to start TX test case.
320 
321 @param [in]	strM2mAteTx
322 		Type of \ref tstrM2mAteTx, with the values required to enable TX test case. You must use \ref m2m_ate_init first.
323 @return
324 	The function SHALL return 0 for success and a negative value otherwise.
325 \sa
326 	m2m_ate_init, m2m_ate_stop_tx, m2m_ate_get_tx_status
327 */
m2m_ate_start_tx(tstrM2mAteTx * strM2mAteTx)328 sint8 m2m_ate_start_tx(tstrM2mAteTx * strM2mAteTx)
329 {
330 	sint8		s8Ret = M2M_SUCCESS;
331 	uint8	u8LoopCntr = 0;
332 	uint32_t 	val32;
333 
334 
335 	if(NULL == strM2mAteTx)
336 	{
337 		s8Ret = M2M_ATE_ERR_VALIDATE;
338 		goto __EXIT;
339 	}
340 
341 	if(0 != m2m_ate_get_tx_status())
342 	{
343 		s8Ret = M2M_ATE_ERR_TX_ALREADY_RUNNING;
344 		goto __EXIT;
345 	}
346 
347 	if(0 != m2m_ate_get_rx_status())
348 	{
349 		s8Ret = M2M_ATE_ERR_RX_ALREADY_RUNNING;
350 		goto __EXIT;
351 	}
352 
353 	if(	(strM2mAteTx->channel_num < M2M_ATE_CHANNEL_1) ||
354 		(strM2mAteTx->channel_num > M2M_ATE_CHANNEL_14) ||
355 		(strM2mAteTx->tx_gain_sel < M2M_ATE_TX_GAIN_DYNAMIC)	||
356 		(strM2mAteTx->tx_gain_sel > M2M_ATE_TX_GAIN_TELEC) ||
357 		(strM2mAteTx->frame_len > M2M_ATE_MAX_FRAME_LENGTH) ||
358 		(strM2mAteTx->frame_len < M2M_ATE_MIN_FRAME_LENGTH)
359 	)
360 	{
361 		s8Ret = M2M_ATE_ERR_VALIDATE;
362 		goto __EXIT;
363 	}
364 
365 	if(	(strM2mAteTx->duty_cycle < M2M_ATE_TX_DUTY_MAX_VALUE /*1*/) ||
366 		(strM2mAteTx->duty_cycle > M2M_ATE_TX_DUTY_MIN_VALUE /*10*/ ) ||
367 		(strM2mAteTx->dpd_ctrl < M2M_ATE_TX_DPD_DYNAMIC)	||
368 		(strM2mAteTx->dpd_ctrl > M2M_ATE_TX_DPD_ENABLED)  ||
369 		(strM2mAteTx->use_pmu > M2M_ATE_PMU_ENABLE)	||
370 		(strM2mAteTx->phy_burst_tx < M2M_ATE_TX_SRC_MAC) ||
371 		(strM2mAteTx->phy_burst_tx > M2M_ATE_TX_SRC_PHY) ||
372 		(strM2mAteTx->cw_tx < M2M_ATE_TX_MODE_NORM) ||
373 		(strM2mAteTx->cw_tx > M2M_ATE_TX_MODE_CW)
374 	)
375 	{
376 		s8Ret = M2M_ATE_ERR_VALIDATE;
377 		goto __EXIT;
378 	}
379 
380 	for(u8LoopCntr=0; u8LoopCntr<M2M_ATE_MAX_NUM_OF_RATES; u8LoopCntr++)
381 	{
382 		if(gaAteFwTxRates[u8LoopCntr] == strM2mAteTx->data_rate)
383 		{
384 			break;
385 		}
386 	}
387 
388 	if(M2M_ATE_MAX_NUM_OF_RATES == u8LoopCntr)
389 	{
390 		s8Ret = M2M_ATE_ERR_VALIDATE;
391 		goto __EXIT;
392 	}
393 
394 
395 
396 	s8Ret += nm_write_reg(rBurstTx_NMI_USE_PMU, strM2mAteTx->use_pmu);
397 	s8Ret += nm_write_reg(rBurstTx_NMI_TX_PHY_CONT, strM2mAteTx->phy_burst_tx);
398 	s8Ret += nm_write_reg(rBurstTx_NMI_NUM_TX_FRAMES, strM2mAteTx->num_frames);
399 	s8Ret += nm_write_reg(rBurstTx_NMI_TX_GAIN, strM2mAteTx->tx_gain_sel);
400 	s8Ret += nm_write_reg(rBurstTx_NMI_TEST_CH, strM2mAteTx->channel_num);
401 	s8Ret += nm_write_reg(rBurstTx_NMI_TX_FRAME_LEN, strM2mAteTx->frame_len);
402 	s8Ret += nm_write_reg(rBurstTx_NMI_TX_CW_PARAM, strM2mAteTx->duty_cycle);
403 	s8Ret += nm_write_reg(rBurstTx_NMI_TX_DPD_CTRL, strM2mAteTx->dpd_ctrl);
404 	s8Ret += nm_write_reg(rBurstTx_NMI_TX_RATE, strM2mAteTx->data_rate);
405 	s8Ret += nm_write_reg(rBurstTx_NMI_TX_CW_MODE, strM2mAteTx->cw_tx);
406 	s8Ret += nm_write_reg(rBurstTx_NMI_TEST_XO_OFF, strM2mAteTx->xo_offset_x1000);
407 	s8Ret += nm_write_reg(rBurstTx_NMI_USE_EFUSE_XO_OFF, strM2mAteTx->use_efuse_xo_offset);
408 
409 	val32	 = strM2mAteTx->peer_mac_addr[5]   << 0;
410 	val32	|= strM2mAteTx->peer_mac_addr[4]  << 8;
411 	val32	|= strM2mAteTx->peer_mac_addr[3]  << 16;
412 	nm_write_reg(rBurstTx_NMI_MAC_ADDR_LO_PEER, val32 );
413 
414 	val32	 = strM2mAteTx->peer_mac_addr[2]  << 0;
415 	val32	|= strM2mAteTx->peer_mac_addr[1] << 8;
416 	val32	|= strM2mAteTx->peer_mac_addr[0] << 16;
417 	nm_write_reg(rBurstTx_NMI_MAC_ADDR_HI_PEER, val32 );
418 
419 	if(M2M_SUCCESS == s8Ret)
420 	{
421 		s8Ret += nm_write_reg(rInterrupt_CORTUS_0, 1);	/*Interrupt Cortus*/
422 		m2m_ate_set_tx_status(1);
423 		nm_bsp_sleep(200);  /*Recommended*/
424 	}
425 
426 __EXIT:
427 	return s8Ret;
428 }
429 
430 /*!
431 @fn	\
432 	sint8 m2m_ate_stop_tx(void)
433 
434 @brief
435 	This function used to stop TX test case.
436 
437 @return
438 	The function SHALL return 0 for success and a negative value otherwise.
439 \sa
440 	m2m_ate_init, m2m_ate_start_tx, m2m_ate_get_tx_status
441 */
m2m_ate_stop_tx(void)442 sint8 m2m_ate_stop_tx(void)
443 {
444 	sint8	s8Ret = M2M_SUCCESS;
445 
446 	s8Ret = nm_write_reg(rInterrupt_CORTUS_1, 1);
447 	if(M2M_SUCCESS == s8Ret)
448 	{
449 		m2m_ate_set_tx_status(0);
450 	}
451 
452 	return s8Ret;
453 }
454 
455 /*!
456 @fn	\
457 	sint8 m2m_ate_get_rx_status(uint8);
458 
459 @brief
460 	This function used to return status of RX test case either running or stopped.
461 
462 @return
463 	The function SHALL return status of ATE firmware, 1 if RX is running otherwise 0.
464 \sa
465 	m2m_ate_start_rx, m2m_ate_stop_rx
466 */
m2m_ate_get_rx_status(void)467 sint8 m2m_ate_get_rx_status(void)
468 {
469 	return gu8RxState;
470 }
471 
472 /*!
473 @fn	\
474 	sint8 m2m_ate_start_rx(tstrM2mAteRx *)
475 
476 @brief
477 	This function used to start RX test case.
478 
479 @param [in]	strM2mAteRx
480 		Type of \ref tstrM2mAteRx, with the values required to enable RX test case. You must use \ref m2m_ate_init first.
481 @return
482 	The function SHALL return 0 for success and a negative value otherwise.
483 \sa
484 	m2m_ate_init, m2m_ate_stop_rx, m2m_ate_get_rx_status
485 */
m2m_ate_start_rx(tstrM2mAteRx * strM2mAteRxStr)486 sint8 m2m_ate_start_rx(tstrM2mAteRx * strM2mAteRxStr)
487 {
488 	sint8		s8Ret = M2M_SUCCESS;
489 	uint32  	val32;
490 	if(NULL == strM2mAteRxStr)
491 	{
492 		s8Ret = M2M_ATE_ERR_VALIDATE;
493 		goto __EXIT;
494 	}
495 
496 	if(0 != m2m_ate_get_tx_status())
497 	{
498 		s8Ret = M2M_ATE_ERR_TX_ALREADY_RUNNING;
499 		goto __EXIT;
500 	}
501 
502 	if(0 != m2m_ate_get_rx_status())
503 	{
504 		s8Ret = M2M_ATE_ERR_RX_ALREADY_RUNNING;
505 		goto __EXIT;
506 	}
507 
508 	if(	(strM2mAteRxStr->channel_num < M2M_ATE_CHANNEL_1) ||
509 		(strM2mAteRxStr->channel_num > M2M_ATE_CHANNEL_14)||
510 		(strM2mAteRxStr->use_pmu > M2M_ATE_PMU_ENABLE)
511 	)
512 	{
513 		s8Ret = M2M_ATE_ERR_VALIDATE;
514 		goto __EXIT;
515 	}
516 
517 	s8Ret += nm_write_reg(rBurstTx_NMI_TEST_CH, strM2mAteRxStr->channel_num);
518 	s8Ret += nm_write_reg(rBurstTx_NMI_USE_PMU, strM2mAteRxStr->use_pmu);
519 	s8Ret += nm_write_reg(rBurstTx_NMI_TEST_XO_OFF, strM2mAteRxStr->xo_offset_x1000);
520 	s8Ret += nm_write_reg(rBurstTx_NMI_USE_EFUSE_XO_OFF, strM2mAteRxStr->use_efuse_xo_offset);
521 
522 	if(strM2mAteRxStr->override_self_mac_addr)
523 	{
524 		val32	 = strM2mAteRxStr->self_mac_addr[5] << 0;
525 		val32	|= strM2mAteRxStr->self_mac_addr[4] << 8;
526 		val32	|= strM2mAteRxStr->self_mac_addr[3] << 16;
527 		nm_write_reg(rBurstTx_NMI_MAC_ADDR_LO_SELF, val32 );
528 
529 		val32	 = strM2mAteRxStr->self_mac_addr[2] << 0;
530 		val32	|= strM2mAteRxStr->self_mac_addr[1] << 8;
531 		val32	|= strM2mAteRxStr->self_mac_addr[0] << 16;
532 		nm_write_reg(rBurstTx_NMI_MAC_ADDR_HI_SELF, val32 );
533 	}
534 
535 	if(strM2mAteRxStr->mac_filter_en_sa)
536 	{
537 		val32	 = strM2mAteRxStr->peer_mac_addr[5] << 0;
538 		val32	|= strM2mAteRxStr->peer_mac_addr[4] << 8;
539 		val32	|= strM2mAteRxStr->peer_mac_addr[3] << 16;
540 		nm_write_reg(rBurstTx_NMI_MAC_ADDR_LO_SA, val32 );
541 
542 		val32	 = strM2mAteRxStr->peer_mac_addr[2] << 0;
543 		val32	|= strM2mAteRxStr->peer_mac_addr[1] << 8;
544 		val32	|= strM2mAteRxStr->peer_mac_addr[0] << 16;
545 		nm_write_reg(rBurstTx_NMI_MAC_ADDR_HI_SA, val32 );
546 	}
547 
548 	nm_write_reg(rBurstTx_NMI_MAC_FILTER_ENABLE_DA, strM2mAteRxStr->mac_filter_en_da);
549 	nm_write_reg(rBurstTx_NMI_MAC_FILTER_ENABLE_SA, strM2mAteRxStr->mac_filter_en_sa);
550 	nm_write_reg(rBurstTx_NMI_SET_SELF_MAC_ADDR, strM2mAteRxStr->override_self_mac_addr);
551 
552 	if(M2M_SUCCESS == s8Ret)
553 	{
554 		s8Ret += nm_write_reg(rInterrupt_CORTUS_2, 1);	/*Interrupt Cortus*/
555 		m2m_ate_set_rx_status(1);
556 		nm_bsp_sleep(10);  /*Recommended*/
557 	}
558 
559 __EXIT:
560 	return s8Ret;
561 }
562 
563 /*!
564 @fn	\
565 	sint8 m2m_ate_stop_rx(void)
566 
567 @brief
568 	This function used to stop RX test case.
569 
570 @return
571 	The function SHALL return 0 for success and a negative value otherwise.
572 \sa
573 	m2m_ate_init, m2m_ate_start_rx, m2m_ate_get_rx_status
574 */
m2m_ate_stop_rx(void)575 sint8 m2m_ate_stop_rx(void)
576 {
577 	m2m_ate_set_rx_status(0);
578 	nm_bsp_sleep(200);  /*Recommended*/
579 	return M2M_SUCCESS;
580 }
581 
582 /*!
583 @fn	\
584 	sint8 m2m_ate_read_rx_status(tstrM2mAteRxStatus *)
585 
586 @brief
587 	This function used to read RX statistics from ATE firmware.
588 
589 @param [out]	strM2mAteRxStatus
590 		Type of \ref tstrM2mAteRxStatus used to save statistics of RX test case. You must use \ref m2m_ate_start_rx first.
591 @return
592 	The function SHALL return 0 for success and a negative value otherwise.
593 \sa
594 	m2m_ate_init, m2m_ate_start_rx
595 */
m2m_ate_read_rx_status(tstrM2mAteRxStatus * strM2mAteRxStatus)596 sint8 m2m_ate_read_rx_status(tstrM2mAteRxStatus *strM2mAteRxStatus)
597 {
598 	sint8	s8Ret = M2M_SUCCESS;
599 
600 	if(NULL == strM2mAteRxStatus)
601 	{
602 		s8Ret = M2M_ATE_ERR_VALIDATE;
603 		goto __EXIT;
604 	}
605 
606 	if(0 != m2m_ate_get_tx_status())
607 	{
608 		s8Ret = M2M_ATE_ERR_TX_ALREADY_RUNNING;
609 		goto __EXIT;
610 	}
611 
612 	if (nm_read_reg(rBurstTx_NMI_MAC_FILTER_ENABLE_DA) || nm_read_reg(rBurstTx_NMI_MAC_FILTER_ENABLE_SA))
613 	{
614 		strM2mAteRxStatus->num_rx_pkts 		= 		nm_read_reg(rBurstTx_NMI_RX_PKT_CNT_SUCCESS) + nm_read_reg(rBurstTx_NMI_RX_PKT_CNT_FAIL);
615 		strM2mAteRxStatus->num_good_pkts 	= 		nm_read_reg(rBurstTx_NMI_RX_PKT_CNT_SUCCESS);
616 		strM2mAteRxStatus->num_err_pkts 	= 		nm_read_reg(rBurstTx_NMI_RX_PKT_CNT_FAIL);
617 	}
618 	else
619 	{
620 		strM2mAteRxStatus->num_rx_pkts = nm_read_reg(rBurstRx_NMI_RX_ALL_PKTS_CONT) + nm_read_reg(0x989c);
621 		strM2mAteRxStatus->num_err_pkts = nm_read_reg(rBurstRx_NMI_RX_ERR_PKTS_CONT);
622 		strM2mAteRxStatus->num_good_pkts = strM2mAteRxStatus->num_rx_pkts - strM2mAteRxStatus->num_err_pkts;
623 	}
624 
625 __EXIT:
626 	return s8Ret;
627 }
628 /*!
629 @fn	\
630 	sint8 m2m_ate_set_dig_gain(double dGaindB)
631 
632 @brief
633 	This function is used to set the digital gain
634 
635 @param [in]	double dGaindB
636 		The digital gain value required to be set.
637 @return
638 	The function SHALL return 0 for success and a negative value otherwise.
639 */
m2m_ate_set_dig_gain(double dGaindB)640 sint8 m2m_ate_set_dig_gain(double dGaindB)
641 {
642 	uint32_t dGain, val32;
643 	dGain = (uint32_t)(pow(10, dGaindB/20.0) * 1024.0);
644 
645 	val32 = nm_read_reg(0x160cd0);
646 	val32 &= ~(0x1ffful << 0);
647 	val32 |= (((uint32_t)dGain) << 0);
648 	nm_write_reg(0x160cd0, val32);
649 	return M2M_SUCCESS;
650 }
651 /*!
652 @fn	\
653 	sint8 m2m_ate_get_dig_gain(double * dGaindB)
654 
655 @brief
656 	This function is used to get the digital gain
657 
658 @param [out]	double * dGaindB
659 		The retrieved digital gain value obtained from HW registers in dB.
660 @return
661 	The function SHALL return 0 for success and a negative value otherwise.
662 */
m2m_ate_get_dig_gain(double * dGaindB)663 sint8 m2m_ate_get_dig_gain(double * dGaindB)
664 {
665 	uint32 dGain, val32;
666 
667 	if(!dGaindB) return M2M_ERR_INVALID_ARG;
668 
669 	val32 = nm_read_reg(0x160cd0);
670 
671 	dGain = (val32 >> 0) & 0x1ffful;
672 	*dGaindB = 20.0*log10((double)dGain / 1024.0);
673 
674 	return M2M_SUCCESS;
675 }
676 /*!
677 @fn	\
678 	void m2m_ate_set_pa_gain(uint8 gain_db)
679 
680 @brief
681 	This function is used to set the PA gain (18/15/12/9/6/3/0 only)
682 
683 @param [in]	uint8 gain_db
684 		PA gain level allowed (18/15/12/9/6/3/0 only)
685 
686 */
m2m_ate_set_pa_gain(uint8 gain_db)687 void m2m_ate_set_pa_gain(uint8 gain_db)
688 {
689 	uint32 PA_1e9c;
690 	uint8 aGain[] = {
691 		/* "0 dB"  */ 0x00,
692 		/* "3 dB"  */ 0x01,
693 		/* "6 dB"  */ 0x03,
694 		/* "9 dB"  */ 0x07,
695 		/* "12 dB" */ 0x0f,
696 		/* "15 dB" */ 0x1f,
697 	/* "18 dB" */ 0x3f };
698 	/* The variable PA gain is valid only for High power mode */
699 	PA_1e9c = nm_read_reg(0x1e9c);
700 	/* TX bank 0. */
701 	PA_1e9c &= ~(0x3ful << 8);
702 	PA_1e9c |= (((uint32)aGain[gain_db/3] & 0x3f) << 8);
703 	nm_write_reg(0x1e9c, PA_1e9c);
704 }
705 /*!
706 @fn	\
707 	sint8 m2m_ate_get_pa_gain(double *paGaindB)
708 
709 @brief
710 	This function is used to get the PA gain
711 
712 @param [out]	double *paGaindB
713 		The retrieved PA gain value obtained from HW registers in dB.
714 @return
715 	The function SHALL return 0 for success and a negative value otherwise.
716 */
m2m_ate_get_pa_gain(double * paGaindB)717 sint8 m2m_ate_get_pa_gain(double *paGaindB)
718 {
719 	uint32 val32, paGain;
720 	uint32 m_cmbPAGainStep;
721 
722 	if(!paGaindB)
723 		return M2M_ERR_INVALID_ARG;
724 
725 	val32 = nm_read_reg(0x1e9c);
726 
727 	paGain = (val32 >> 8) & 0x3f;
728 
729 	switch(paGain){
730 		case 0x1:
731 		m_cmbPAGainStep = 5;
732 		break;
733 		case 0x3:
734 		m_cmbPAGainStep = 4;
735 		break;
736 		case 0x7:
737 		m_cmbPAGainStep = 3;
738 		break;
739 		case 0xf:
740 		m_cmbPAGainStep = 2;
741 		break;
742 		case 0x1f:
743 		m_cmbPAGainStep = 1;
744 		break;
745 		case 0x3f:
746 		m_cmbPAGainStep = 0;
747 		break;
748 		default:
749 		m_cmbPAGainStep = 0;
750 		break;
751 	}
752 
753 	*paGaindB = 18 - m_cmbPAGainStep*3;
754 
755 	return M2M_SUCCESS;
756 }
757 /*!
758 @fn	\
759 	sint8 m2m_ate_get_ppa_gain(double * ppaGaindB)
760 
761 @brief
762 	This function is used to get the PPA gain
763 
764 @param [out]	uint32 * ppaGaindB
765 		The retrieved PPA gain value obtained from HW registers in dB.
766 @return
767 	The function SHALL return 0 for success and a negative value otherwise.
768 */
m2m_ate_get_ppa_gain(double * ppaGaindB)769 sint8 m2m_ate_get_ppa_gain(double * ppaGaindB)
770 {
771 	uint32 val32, ppaGain, m_cmbPPAGainStep;
772 
773 	if(!ppaGaindB) return M2M_ERR_INVALID_ARG;
774 
775 	val32 = nm_read_reg(0x1ea0);
776 
777 	ppaGain = (val32 >> 5) & 0x7;
778 
779 	switch(ppaGain){
780 		case 0x1:
781 		m_cmbPPAGainStep = 2;
782 		break;
783 		case 0x3:
784 		m_cmbPPAGainStep = 1;
785 		break;
786 		case 0x7:
787 		m_cmbPPAGainStep = 0;
788 		break;
789 		default:
790 		m_cmbPPAGainStep = 3;
791 		break;
792 	}
793 
794 	*ppaGaindB = 9 - m_cmbPPAGainStep*3;
795 
796 
797 	return M2M_SUCCESS;
798 }
799 /*!
800 @fn	\
801 	sint8 m2m_ate_get_tot_gain(double * totGaindB)
802 
803 @brief
804 	This function is used to calculate the total gain
805 
806 @param [out]	double * totGaindB
807 		The retrieved total gain value obtained from calculations made based on the digital gain, PA and PPA gain values.
808 @return
809 	The function SHALL return 0 for success and a negative value otherwise.
810 */
m2m_ate_get_tot_gain(double * totGaindB)811 sint8 m2m_ate_get_tot_gain(double * totGaindB)
812 {
813 	double dGaindB, paGaindB, ppaGaindB;
814 
815 	if(!totGaindB) return M2M_ERR_INVALID_ARG;
816 
817 	m2m_ate_get_pa_gain(&paGaindB);
818 	m2m_ate_get_ppa_gain(&ppaGaindB);
819 	m2m_ate_get_dig_gain(&dGaindB);
820 
821 	*totGaindB = dGaindB + paGaindB + ppaGaindB;
822 
823 	return M2M_SUCCESS;
824 }
825 
826 #endif //_M2M_ATE_FW_