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, ®);
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, ®);
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, ®);
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, ®);
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