1 /**
2  *
3  * \file
4  *
5  * \brief This module contains NMC1000 M2M driver APIs implementation.
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 #include "common/include/nm_common.h"
43 #include "driver/source/nmbus.h"
44 #include "bsp/include/nm_bsp.h"
45 #include "driver/source/nmdrv.h"
46 #include "driver/source/nmasic.h"
47 #include "driver/include/m2m_types.h"
48 #include "spi_flash/include/spi_flash.h"
49 
50 #ifdef CONF_WINC_USE_SPI
51 #include "driver/source/nmspi.h"
52 #endif
53 
54 /**
55 *	@fn		nm_get_firmware_info(tstrM2mRev* M2mRev)
56 *	@brief	Get Firmware version info
57 *	@param [out]	M2mRev
58 *			    pointer holds address of structure "tstrM2mRev" that contains the firmware version parameters
59 *	@version	1.0
60 */
nm_get_firmware_info(tstrM2mRev * M2mRev)61 sint8 nm_get_firmware_info(tstrM2mRev* M2mRev)
62 {
63 	uint16  curr_drv_ver, min_req_drv_ver,curr_firm_ver;
64 	uint32	reg = 0;
65 	sint8	ret = M2M_SUCCESS;
66 
67 	ret = nm_read_reg_with_ret(NMI_REV_REG, &reg);
68 	//In case the Firmware running is ATE fw
69 	if(M2M_ATE_FW_IS_UP_VALUE == reg)
70 	{
71 		//Read FW info again from the register specified for ATE
72 		ret = nm_read_reg_with_ret(NMI_REV_REG_ATE, &reg);
73 	}
74 	M2mRev->u8DriverMajor	= M2M_GET_DRV_MAJOR(reg);
75 	M2mRev->u8DriverMinor   = M2M_GET_DRV_MINOR(reg);
76 	M2mRev->u8DriverPatch	= M2M_GET_DRV_PATCH(reg);
77 	M2mRev->u8FirmwareMajor	= M2M_GET_FW_MAJOR(reg);
78 	M2mRev->u8FirmwareMinor = M2M_GET_FW_MINOR(reg);
79 	M2mRev->u8FirmwarePatch = M2M_GET_FW_PATCH(reg);
80 	M2mRev->u32Chipid	= nmi_get_chipid();
81 	M2mRev->u16FirmwareSvnNum = 0;
82 
83 	curr_firm_ver   = M2M_MAKE_VERSION(M2mRev->u8FirmwareMajor, M2mRev->u8FirmwareMinor,M2mRev->u8FirmwarePatch);
84 	curr_drv_ver    = M2M_MAKE_VERSION(M2M_RELEASE_VERSION_MAJOR_NO, M2M_RELEASE_VERSION_MINOR_NO, M2M_RELEASE_VERSION_PATCH_NO);
85 	min_req_drv_ver = M2M_MAKE_VERSION(M2mRev->u8DriverMajor, M2mRev->u8DriverMinor,M2mRev->u8DriverPatch);
86 	if(curr_drv_ver <  min_req_drv_ver) {
87 		/*The current driver version should be larger or equal
88 		than the min driver that the current firmware support  */
89 		ret = M2M_ERR_FW_VER_MISMATCH;
90 	}
91 	if(curr_drv_ver >  curr_firm_ver) {
92 		/*The current driver should be equal or less than the firmware version*/
93 		ret = M2M_ERR_FW_VER_MISMATCH;
94 	}
95 	return ret;
96 }
97 /**
98 *	@fn		nm_get_firmware_info(tstrM2mRev* M2mRev)
99 *	@brief	Get Firmware version info
100 *	@param [out]	M2mRev
101 *			    pointer holds address of structure "tstrM2mRev" that contains the firmware version parameters
102 *	@version	1.0
103 */
nm_get_firmware_full_info(tstrM2mRev * pstrRev)104 sint8 nm_get_firmware_full_info(tstrM2mRev* pstrRev)
105 {
106 	uint16  curr_drv_ver, min_req_drv_ver,curr_firm_ver;
107 	uint32	reg = 0;
108 	sint8	ret = M2M_SUCCESS;
109 	tstrGpRegs strgp = {0};
110 	if (pstrRev != NULL)
111 	{
112 		m2m_memset((uint8*)pstrRev,0,sizeof(tstrM2mRev));
113 		ret = nm_read_reg_with_ret(rNMI_GP_REG_2, &reg);
114 		if(ret == M2M_SUCCESS)
115 		{
116 			if(reg != 0)
117 			{
118 				ret = nm_read_block(reg|0x30000,(uint8*)&strgp,sizeof(tstrGpRegs));
119 				if(ret == M2M_SUCCESS)
120 				{
121 					reg = strgp.u32Firmware_Ota_rev;
122 					reg &= 0x0000ffff;
123 					if(reg != 0)
124 					{
125 						ret = nm_read_block(reg|0x30000,(uint8*)pstrRev,sizeof(tstrM2mRev));
126 						if(ret == M2M_SUCCESS)
127 						{
128 							curr_firm_ver   = M2M_MAKE_VERSION(pstrRev->u8FirmwareMajor, pstrRev->u8FirmwareMinor,pstrRev->u8FirmwarePatch);
129 							curr_drv_ver    = M2M_MAKE_VERSION(M2M_RELEASE_VERSION_MAJOR_NO, M2M_RELEASE_VERSION_MINOR_NO, M2M_RELEASE_VERSION_PATCH_NO);
130 							min_req_drv_ver = M2M_MAKE_VERSION(pstrRev->u8DriverMajor, pstrRev->u8DriverMinor,pstrRev->u8DriverPatch);
131 							if((curr_firm_ver == 0)||(min_req_drv_ver == 0)||(min_req_drv_ver == 0)){
132 								ret = M2M_ERR_FAIL;
133 								goto EXIT;
134 							}
135 							if(curr_drv_ver <  min_req_drv_ver) {
136 								/*The current driver version should be larger or equal
137 								than the min driver that the current firmware support  */
138 								ret = M2M_ERR_FW_VER_MISMATCH;
139 								goto EXIT;
140 							}
141 							if(curr_drv_ver >  curr_firm_ver) {
142 								/*The current driver should be equal or less than the firmware version*/
143 								ret = M2M_ERR_FW_VER_MISMATCH;
144 								goto EXIT;
145 							}
146 						}
147 					}else {
148 						ret = M2M_ERR_FAIL;
149 					}
150 				}
151 			}else{
152 				ret = M2M_ERR_FAIL;
153 			}
154 		}
155 	}
156 EXIT:
157 	return ret;
158 }
159 /**
160 *	@fn		nm_get_ota_firmware_info(tstrM2mRev* pstrRev)
161 *	@brief	Get Firmware version info
162 *	@param [out]	M2mRev
163 *			    pointer holds address of structure "tstrM2mRev" that contains the firmware version parameters
164 
165 *	@version	1.0
166 */
nm_get_ota_firmware_info(tstrM2mRev * pstrRev)167 sint8 nm_get_ota_firmware_info(tstrM2mRev* pstrRev)
168 {
169 	uint16  curr_drv_ver, min_req_drv_ver,curr_firm_ver;
170 	uint32	reg = 0;
171 	sint8	ret;
172 	tstrGpRegs strgp = {0};
173 
174 	if (pstrRev != NULL)
175 	{
176 		m2m_memset((uint8*)pstrRev,0,sizeof(tstrM2mRev));
177 		ret = nm_read_reg_with_ret(rNMI_GP_REG_2, &reg);
178 		if(ret == M2M_SUCCESS)
179 		{
180 			if(reg != 0)
181 			{
182 				ret = nm_read_block(reg|0x30000,(uint8*)&strgp,sizeof(tstrGpRegs));
183 				if(ret == M2M_SUCCESS)
184 				{
185 					reg = strgp.u32Firmware_Ota_rev;
186 					reg >>= 16;
187 					if(reg != 0)
188 					{
189 						ret = nm_read_block(reg|0x30000,(uint8*)pstrRev,sizeof(tstrM2mRev));
190 						if(ret == M2M_SUCCESS)
191 						{
192 							curr_firm_ver   = M2M_MAKE_VERSION(pstrRev->u8FirmwareMajor, pstrRev->u8FirmwareMinor,pstrRev->u8FirmwarePatch);
193 							curr_drv_ver    = M2M_MAKE_VERSION(M2M_RELEASE_VERSION_MAJOR_NO, M2M_RELEASE_VERSION_MINOR_NO, M2M_RELEASE_VERSION_PATCH_NO);
194 							min_req_drv_ver = M2M_MAKE_VERSION(pstrRev->u8DriverMajor, pstrRev->u8DriverMinor,pstrRev->u8DriverPatch);
195 							if((curr_firm_ver == 0)||(min_req_drv_ver == 0)||(min_req_drv_ver == 0)){
196 								ret = M2M_ERR_FAIL;
197 								goto EXIT;
198 							}
199 							if(curr_drv_ver <  min_req_drv_ver) {
200 								/*The current driver version should be larger or equal
201 								than the min driver that the current firmware support  */
202 								ret = M2M_ERR_FW_VER_MISMATCH;
203 							}
204 							if(curr_drv_ver >  curr_firm_ver) {
205 								/*The current driver should be equal or less than the firmware version*/
206 								ret = M2M_ERR_FW_VER_MISMATCH;
207 							}
208 						}
209 					}else{
210 						ret = M2M_ERR_INVALID;
211 					}
212 				}
213 			}else{
214 				ret = M2M_ERR_FAIL;
215 			}
216 		}
217 	} else {
218 		ret = M2M_ERR_INVALID_ARG;
219 	}
220 EXIT:
221 	return ret;
222 }
223 
224 
225 
226 /*
227 *	@fn		nm_drv_init_download_mode
228 *	@brief	Initialize NMC1000 driver
229 *	@return	M2M_SUCCESS in case of success and Negative error code in case of failure
230 *   @param [in]	arg
231 *				Generic argument
232 *	@author	Viswanathan Murugesan
233 *	@date	10 Oct 2014
234 *	@version	1.0
235 */
nm_drv_init_download_mode()236 sint8 nm_drv_init_download_mode()
237 {
238 	sint8 ret = M2M_SUCCESS;
239 
240 	ret = nm_bus_iface_init(NULL);
241 	if (M2M_SUCCESS != ret) {
242 		M2M_ERR("[nmi start]: fail init bus\n");
243 		goto ERR1;
244 	}
245 
246 	/**
247 		TODO:reset the chip and halt the cpu in case of no wait efuse is set (add the no wait effuse check)
248 	*/
249 	if(!ISNMC3000(GET_CHIPID()))
250 	{
251 		/*Execuate that function only for 1500A/B, no room in 3000, but it may be needed in 3400 no wait*/
252 		chip_reset_and_cpu_halt();
253 	}
254 
255 #ifdef CONF_WINC_USE_SPI
256 	/* Must do this after global reset to set SPI data packet size. */
257 	nm_spi_init();
258 #endif
259 
260 	M2M_INFO("Chip ID %lx\n", nmi_get_chipid());
261 
262 	/*disable all interrupt in ROM (to disable uart) in 2b0 chip*/
263 	nm_write_reg(0x20300,0);
264 
265 ERR1:
266 	return ret;
267 }
268 
269 /*
270 *	@fn		nm_drv_init
271 *	@brief	Initialize NMC1000 driver
272 *	@return	M2M_SUCCESS in case of success and Negative error code in case of failure
273 *   @param [in]	arg
274 *				Generic argument
275 *	@author	M. Abdelmawla
276 *	@date	15 July 2012
277 *	@version	1.0
278 */
nm_drv_init(void * arg)279 sint8 nm_drv_init(void * arg)
280 {
281 	sint8 ret = M2M_SUCCESS;
282 	uint8 u8Mode;
283 
284 	if(NULL != arg) {
285 		u8Mode = *((uint8 *)arg);
286 		if((u8Mode < M2M_WIFI_MODE_NORMAL)||(u8Mode >= M2M_WIFI_MODE_MAX)) {
287 			u8Mode = M2M_WIFI_MODE_NORMAL;
288 		}
289 	} else {
290 		u8Mode = M2M_WIFI_MODE_NORMAL;
291 	}
292 
293 	ret = nm_bus_iface_init(NULL);
294 	if (M2M_SUCCESS != ret) {
295 		M2M_ERR("[nmi start]: fail init bus\n");
296 		goto ERR1;
297 	}
298 
299 #ifdef BUS_ONLY
300 	return;
301 #endif
302 
303 
304 #ifdef NO_HW_CHIP_EN
305 	ret = chip_wake();
306 	if (M2M_SUCCESS != ret) {
307 		M2M_ERR("[nmi start]: fail chip_wakeup\n");
308 		goto ERR2;
309 	}
310 	/**
311 	Go...
312 	**/
313 	ret = chip_reset();
314 	if (M2M_SUCCESS != ret) {
315 		goto ERR2;
316 	}
317 #endif
318 	M2M_INFO("Chip ID %lx\n", nmi_get_chipid());
319 #ifdef CONF_WINC_USE_SPI
320 	/* Must do this after global reset to set SPI data packet size. */
321 	nm_spi_init();
322 #endif
323 	ret = wait_for_bootrom(u8Mode);
324 	if (M2M_SUCCESS != ret) {
325 		goto ERR2;
326 	}
327 
328 	ret = wait_for_firmware_start(u8Mode);
329 	if (M2M_SUCCESS != ret) {
330 		goto ERR2;
331 	}
332 
333 	if((M2M_WIFI_MODE_ATE_HIGH == u8Mode)||(M2M_WIFI_MODE_ATE_LOW == u8Mode)) {
334 		goto ERR1;
335 	} else {
336 		/*continue running*/
337 	}
338 
339 	ret = enable_interrupts();
340 	if (M2M_SUCCESS != ret) {
341 		M2M_ERR("failed to enable interrupts..\n");
342 		goto ERR2;
343 	}
344 	return ret;
345 ERR2:
346 	nm_bus_iface_deinit();
347 ERR1:
348 	return ret;
349 }
350 
351 /*
352 *	@fn		nm_drv_deinit
353 *	@brief	Deinitialize NMC1000 driver
354 *	@author	M. Abdelmawla
355 *	@date	17 July 2012
356 *	@version	1.0
357 */
nm_drv_deinit(void * arg)358 sint8 nm_drv_deinit(void * arg)
359 {
360 	sint8 ret;
361 
362 	ret = chip_deinit();
363 	if (M2M_SUCCESS != ret) {
364 		M2M_ERR("[nmi stop]: chip_deinit fail\n");
365 		goto ERR1;
366 	}
367 
368 	/* Disable SPI flash to save power when the chip is off */
369 	ret = spi_flash_enable(0);
370 	if (M2M_SUCCESS != ret) {
371 		M2M_ERR("[nmi stop]: SPI flash disable fail\n");
372 		goto ERR1;
373 	}
374 
375 	ret = nm_bus_iface_deinit();
376 	if (M2M_SUCCESS != ret) {
377 		M2M_ERR("[nmi stop]: fail init bus\n");
378 		goto ERR1;
379 	}
380 #ifdef CONF_WINC_USE_SPI
381 	/* Must do this after global reset to set SPI data packet size. */
382 	nm_spi_deinit();
383 #endif
384 
385 ERR1:
386 	return ret;
387 }
388 
389 
390