1 /*
2 * cc_pal.c - CC32xx Host Driver Implementation
3 *
4 * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
5 *
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the
17 * distribution.
18 *
19 * Neither the name of Texas Instruments Incorporated nor the names of
20 * its contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 */
36 /******************************************************************************
37 * cc_pal.c
38 *
39 * SimpleLink Wi-Fi abstraction file for CC32xx
40 ******************************************************************************/
41
42 /* Board includes */
43 #include <ti/drivers/net/wifi/simplelink.h>
44 #include <ti/drivers/net/wifi/porting/cc_pal.h>
45 #include <ti/drivers/dpl/HwiP.h>
46 #include <ti/drivers/SPI.h>
47
48 #include <ti/devices/cc32xx/inc/hw_ints.h>
49 #include <ti/devices/cc32xx/inc/hw_udma.h>
50 #include <ti/devices/cc32xx/inc/hw_types.h>
51 #include <ti/devices/cc32xx/inc/hw_memmap.h>
52 #include <ti/devices/cc32xx/inc/hw_gprcm.h>
53 #include <ti/devices/cc32xx/inc/hw_mcspi.h>
54 #include <ti/devices/cc32xx/inc/hw_common_reg.h>
55 #include <ti/devices/cc32xx/inc/hw_ocp_shared.h>
56 #include <ti/devices/cc32xx/inc/hw_apps_rcm.h>
57 #include <ti/devices/cc32xx/inc/hw_gprcm.h>
58 #include <ti/devices/cc32xx/inc/hw_hib1p2.h>
59 #include "ti/devices/cc32xx/driverlib/rom.h"
60 #include "ti/devices/cc32xx/driverlib/rom_map.h"
61 #include <ti/devices/cc32xx/driverlib/interrupt.h>
62 #include <ti/devices/cc32xx/driverlib/prcm.h>
63 #include <ti/devices/cc32xx/driverlib/timer.h>
64 #include <ti/drivers/net/wifi/source/driver.h>
65
66 /* NWP_SPARE_REG_5 - (OCP_SHARED_BASE + OCP_SHARED_O_SPARE_REG_5)
67 - Bits 31:02 - Reserved
68 - Bits 01 - SLSTOP1 - NWP in Reset, Power Domain Down
69 - Bits 00 - Reserved
70 */
71 #define NWP_SPARE_REG_5 (OCP_SHARED_BASE + OCP_SHARED_O_SPARE_REG_5)
72 #define NWP_SPARE_REG_5_SLSTOP (0x00000002)
73
74 /* ANA_DCDC_PARAMS0 - (HIB1P2_BASE + HIB1P2_O_ANA_DCDC_PARAMETERS0)
75 - Bits 31:28 - Reserved
76 - Bits 27 - Override PWM mode (==> PFM)
77 - Bits 26:00 - Reserved
78 */
79 #define ANA_DCDC_PARAMS0 (HIB1P2_BASE + HIB1P2_O_ANA_DCDC_PARAMETERS0)
80 #define ANA_DCDC_PARAMS0_PWMOVERRIDE (0x08000000)
81
82 /* WAKENWP - (ARCM_BASE + APPS_RCM_O_APPS_TO_NWP_WAKE_REQUEST)
83 - Bits 31:01 - Reserved
84 - Bits 00 - Wake Request to NWP
85 */
86 #define WAKENWP (ARCM_BASE + APPS_RCM_O_APPS_TO_NWP_WAKE_REQUEST)
87 #define WAKENWP_WAKEREQ (APPS_RCM_APPS_TO_NWP_WAKE_REQUEST_APPS_TO_NWP_WAKEUP_REQUEST)
88
89 /* NWP_PWR_STATE - (GPRCM_BASE + GPRCM_O_NWP_PWR_STATE)
90 - Bits 31:12 - Reserved
91 - Bits 11:08 - Active (0x3)
92 - Bits 07:00 - Reserved
93 */
94 #define NWP_PWR_STATE (GPRCM_BASE + GPRCM_O_NWP_PWR_STATE)
95 #define NWP_PWR_STATE_PWRMASK (0x00000F00)
96 #define NWP_PWR_STATE_PWRACTIVE (0x00000300)
97
98 /* NWP_LPDS_WAKEUPCFG - (GPRCM_BASE + GPRCM_O_NWP_LPDS_WAKEUP_CFG)
99 - Bits 31:08 - Reserved
100 - Bits 07:00 - WakeUp Config AppsToNwp Wake (0x20) - reset condition
101 */
102 #define NWP_LPDS_WAKEUPCFG (GPRCM_BASE + GPRCM_O_NWP_LPDS_WAKEUP_CFG)
103 #define NWP_LPDS_WAKEUPCFG_APPS2NWP (0x00000020)
104 #define NWP_LPDS_WAKEUPCFG_TIMEOUT_MSEC (600)
105
106 /* N2A_INT_MASK_SET - (COMMON_REG_BASE + COMMON_REG_O_NW_INT_MASK_SET) */
107 #define N2A_INT_MASK_SET (COMMON_REG_BASE + COMMON_REG_O_NW_INT_MASK_SET)
108 /* N2A_INT_MASK_CLR - (COMMON_REG_BASE + COMMON_REG_O_NW_INT_MASK_CLR) */
109 #define N2A_INT_MASK_CLR (COMMON_REG_BASE + COMMON_REG_O_NW_INT_MASK_CLR)
110 /* N2A_INT_ACK - (COMMON_REG_BASE + COMMON_REG_O_NW_INT_ACK) */
111 #define N2A_INT_ACK (COMMON_REG_BASE + COMMON_REG_O_NW_INT_ACK)
112 #define NWP_N2A_INT_ACK_TIMEOUT_MSEC (3000)
113
114 /* A2N_INT_STS_CLR - (COMMON_REG_BASE + COMMON_REG_O_APPS_INT_STS_CLR) */
115 #define A2N_INT_STS_CLR (COMMON_REG_BASE + COMMON_REG_O_APPS_INT_STS_CLR)
116 /* A2N_INT_TRIG - (COMMON_REG_BASE + COMMON_REG_O_APPS_INT_TRIG) */
117 #define A2N_INT_TRIG (COMMON_REG_BASE + COMMON_REG_O_APPS_INT_TRIG)
118 /* A2N_INT_STS_RAW - (COMMON_REG_BASE + COMMON_REG_O_APPS_INT_STS_RAW) */
119 #define A2N_INT_STS_RAW (COMMON_REG_BASE + COMMON_REG_O_APPS_INT_STS_RAW)
120
121 #define uSEC_DELAY(x) (ROM_UtilsDelayDirect(x*80/3))
122 #define MAX_DMA_RECV_TRANSACTION_SIZE (4096)
123 #define SPI_RATE_20M (20000000)
124 #define SPI_RATE_30M (30000000)
125
126 HwiP_Handle g_intHandle = 0;
127
128 //****************************************************************************
129 // LOCAL FUNCTIONS
130 //****************************************************************************
131
spi_Open(char * ifName,unsigned long flags)132 Fd_t spi_Open(char *ifName, unsigned long flags)
133 {
134 void *lspi_hndl;
135 unsigned int lspi_index;
136 SPI_Params SPI_Config;
137 SPI_Params_init(&SPI_Config);
138
139 /* configure the SPI settings */
140 SPI_Config.transferMode = SPI_MODE_BLOCKING;
141 SPI_Config.mode = SPI_MASTER;
142
143 /* Check NWP generation */
144 if((HWREG(GPRCM_BASE + GPRCM_O_GPRCM_DIEID_READ_REG4) >> 24) & 0x02)
145 {
146 SPI_Config.bitRate = SPI_RATE_30M;
147 }
148 else
149 {
150 SPI_Config.bitRate = SPI_RATE_20M;
151 }
152 SPI_Config.dataSize = 32;
153 SPI_Config.frameFormat = SPI_POL0_PHA0;
154
155 /* index of the link SPI initialization configuration in the SPI_Config table */
156 lspi_index = 0;
157 lspi_hndl = SPI_open(lspi_index, &SPI_Config);
158 if(NULL == lspi_hndl)
159 {
160 return -1;
161 }
162 else
163 {
164 return (Fd_t)lspi_hndl;
165 }
166 }
167
168
spi_Close(Fd_t fd)169 int spi_Close(Fd_t fd)
170 {
171 SPI_close((void *)fd);
172 return 0;
173 }
174
175
spi_Read(Fd_t fd,unsigned char * pBuff,int len)176 int spi_Read(Fd_t fd, unsigned char *pBuff, int len)
177 {
178 SPI_Transaction transact_details;
179 int read_size = 0;
180
181 /* check if the link SPI has been initialized successfully */
182 if(fd < 0)
183 {
184 return -1;
185 }
186
187 transact_details.txBuf = NULL;
188 transact_details.arg = NULL;
189 while(len > 0)
190 {
191 /* DMA can transfer upto a maximum of 1024 words in one go. So, if
192 the data to be read is more than 1024 words, it will be done in
193 parts */
194 /* length is received in bytes, should be specified in words for the
195 * SPI driver.
196 */
197 if(len > MAX_DMA_RECV_TRANSACTION_SIZE)
198 {
199 transact_details.count = (MAX_DMA_RECV_TRANSACTION_SIZE +3)>>2;
200 transact_details.rxBuf = (void*)(pBuff + read_size);
201 if(SPI_transfer((SPI_Handle)fd, &transact_details))
202 {
203 read_size += MAX_DMA_RECV_TRANSACTION_SIZE;
204 len = len - MAX_DMA_RECV_TRANSACTION_SIZE;
205 }
206 else
207 {
208 return -1;
209 }
210
211 }
212 else
213 {
214 transact_details.count = (len+3)>>2;
215 transact_details.rxBuf = (void*)(pBuff + read_size);
216 if(SPI_transfer((SPI_Handle)fd, &transact_details))
217 {
218 read_size += len;
219 len = 0;
220 return read_size;
221 }
222 else
223 {
224 return -1;
225 }
226 }
227 }
228
229 return(read_size);
230 }
231
232
spi_Write(Fd_t fd,unsigned char * pBuff,int len)233 int spi_Write(Fd_t fd, unsigned char *pBuff, int len)
234 {
235 SPI_Transaction transact_details;
236 int write_size = 0;
237
238 /* check if the link SPI has been initialized successfully */
239 if(fd < 0)
240 {
241 return -1;
242 }
243
244 transact_details.rxBuf = NULL;
245 transact_details.arg = NULL;
246 while(len > 0)
247 {
248 /* configure the transaction details.
249 * length is received in bytes, should be specified in words for the SPI
250 * driver.
251 */
252 if(len > MAX_DMA_RECV_TRANSACTION_SIZE)
253 {
254 transact_details.count = (MAX_DMA_RECV_TRANSACTION_SIZE +3)>>2;
255 transact_details.txBuf = (void*)(pBuff + write_size);
256 if(SPI_transfer((SPI_Handle)fd, &transact_details))
257 {
258 write_size += MAX_DMA_RECV_TRANSACTION_SIZE;
259 len = len - MAX_DMA_RECV_TRANSACTION_SIZE;
260 }
261 else
262 {
263 return -1;
264 }
265 }
266 else
267 {
268 transact_details.count = (len+3)>>2;
269 transact_details.txBuf = (void*)(pBuff + write_size);
270 if(SPI_transfer((SPI_Handle)fd, &transact_details))
271 {
272 write_size += len;
273 len = 0;
274 return write_size;
275 }
276 else
277 {
278 return -1;
279 }
280 }
281 }
282
283 return(write_size);
284 }
285
286
NwpRegisterInterruptHandler(P_EVENT_HANDLER InterruptHdl,void * pValue)287 int NwpRegisterInterruptHandler(P_EVENT_HANDLER InterruptHdl , void* pValue)
288 {
289
290 HwiP_Params nwp_iParams;
291
292 HwiP_Params_init(&nwp_iParams);
293
294 HwiP_clearInterrupt(INT_NWPIC);
295
296 if(!InterruptHdl)
297 {
298 HwiP_delete(g_intHandle);
299 return OS_OK;
300 }
301 else
302 {
303 nwp_iParams.priority = INT_PRIORITY_LVL_1 ;
304
305 }
306 g_intHandle = HwiP_create(INT_NWPIC , (HwiP_Fxn)(InterruptHdl) , &nwp_iParams);
307
308 if(!g_intHandle)
309 {
310 return -1;
311 }
312 else
313 {
314 return OS_OK ;
315 }
316 }
317
318
NwpMaskInterrupt()319 void NwpMaskInterrupt()
320 {
321 (*(unsigned long *)N2A_INT_MASK_SET) = 0x1;
322 }
323
324
NwpUnMaskInterrupt()325 void NwpUnMaskInterrupt()
326 {
327 (*(unsigned long *)N2A_INT_MASK_CLR) = 0x1;
328 }
329
330
NwpPowerOn(void)331 void NwpPowerOn(void)
332 {
333 /* bring the 1.32 eco out of reset */
334 HWREG(NWP_SPARE_REG_5) &= ~NWP_SPARE_REG_5_SLSTOP;
335
336 /* Clear host IRQ indication */
337 HWREG(N2A_INT_ACK) = 1;
338
339 /* NWP Wake-up */
340 HWREG(WAKENWP) = WAKENWP_WAKEREQ;
341
342 //UnMask Host Interrupt
343 NwpUnMaskInterrupt();
344 }
345
346
NwpPowerOff(void)347 void NwpPowerOff(void)
348 {
349
350 volatile unsigned long apps_int_sts_raw;
351 volatile unsigned long sl_stop_ind = HWREG(NWP_SPARE_REG_5);
352 volatile unsigned long nwp_lpds_wake_cfg = HWREG(NWP_LPDS_WAKEUPCFG);
353 _SlTimeoutParams_t SlTimeoutInfo = {0};
354
355 if((nwp_lpds_wake_cfg != NWP_LPDS_WAKEUPCFG_APPS2NWP) && /* Check for NWP POR condition - APPS2NWP is reset condition */
356 !(sl_stop_ind & NWP_SPARE_REG_5_SLSTOP)) /* Check if sl_stop was executed */
357 {
358 HWREG(0xE000E104) = 0x200; /* Enable the out of band interrupt, this is not a wake-up source*/
359 HWREG(A2N_INT_TRIG) = 0x1; /* Trigger out of band interrupt */
360 HWREG(WAKENWP) = WAKENWP_WAKEREQ; /* Wake-up the NWP */
361
362 _SlDrvStartMeasureTimeout(&SlTimeoutInfo, NWP_N2A_INT_ACK_TIMEOUT_MSEC);
363
364 /* Wait for the A2N_INT_TRIG to be cleared by the NWP to indicate it's awake and ready for shutdown.
365 * poll until APPs->NWP interrupt is cleared or timeout :
366 * for service pack 3.1.99.1 or higher, this condition is fulfilled in less than 1 mSec.
367 * Otherwise, in some cases it may require up to 3000 mSec of waiting. */
368
369 apps_int_sts_raw = HWREG(A2N_INT_STS_RAW);
370 while(!(apps_int_sts_raw & 0x1))
371 {
372 if(_SlDrvIsTimeoutExpired(&SlTimeoutInfo))
373 {
374 break;
375 }
376 apps_int_sts_raw = HWREG(A2N_INT_STS_RAW);
377 }
378
379 WAIT_NWP_SHUTDOWN_READY;
380 }
381
382 /* Clear Out of band interrupt, Acked by the NWP */
383 HWREG(A2N_INT_STS_CLR) = 0x1;
384
385 /* Mask Host Interrupt */
386 NwpMaskInterrupt();
387
388 /* Switch to PFM Mode */
389 HWREG(ANA_DCDC_PARAMS0) &= ~ANA_DCDC_PARAMS0_PWMOVERRIDE;
390
391 /* sl_stop ECO for PG1.32 devices */
392 HWREG(NWP_SPARE_REG_5) |= NWP_SPARE_REG_5_SLSTOP;
393
394 /* Wait for 20 uSec, which is the minimal time between on-off cycle */
395 uSEC_DELAY(20);
396 }
397
398 #if defined(SL_PLATFORM_MULTI_THREADED)
399
Semaphore_pend_handle(sem_t * pSemHandle,uint32_t timeout)400 int Semaphore_pend_handle(sem_t* pSemHandle, uint32_t timeout)
401 {
402 if (OS_WAIT_FOREVER == timeout)
403 {
404 return sem_wait(pSemHandle);
405 }
406 else
407 {
408 struct timespec abstime;
409 abstime.tv_nsec = 0;
410 abstime.tv_sec = 0;
411
412 /* Since POSIX timeout are relative and not absolute,
413 * take the current timestamp. */
414 clock_gettime(CLOCK_REALTIME, &abstime);
415 if(abstime.tv_nsec < 0)
416 {
417 abstime.tv_sec = timeout;
418 return (sem_timedwait(pSemHandle, &abstime));
419 }
420
421 /* Add the amount of time to wait */
422 abstime.tv_sec += timeout / 1000;
423 abstime.tv_nsec += (timeout % 1000) * 1000000;
424
425 abstime.tv_sec += (abstime.tv_nsec / 1000000000);
426 abstime.tv_nsec = abstime.tv_nsec % 1000000000;
427
428 /* Call the semaphore wait API */
429 return(sem_timedwait(pSemHandle, &abstime));
430 }
431 }
432
Mutex_create_handle(pthread_mutex_t * pMutexHandle)433 int Mutex_create_handle(pthread_mutex_t *pMutexHandle)
434 {
435 pthread_mutexattr_t attr;
436 pthread_mutexattr_init(&attr);
437 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
438
439 if (pthread_mutex_init(pMutexHandle, &attr) < 0)
440 {
441 return Mutex_FAILURE ;
442 }
443
444 return Mutex_OK;
445 }
446
447
448 #else
449
Mutex_create_handle(MutexP_Handle * pMutexHandle)450 int Mutex_create_handle(MutexP_Handle* pMutexHandle)
451 {
452 MutexP_Params params;
453
454 MutexP_Params_init(¶ms);
455
456 params.callback = tiDriverSpawnCallback;
457
458 (*(pMutexHandle)) = MutexP_create(¶ms);
459
460 if(!(*(pMutexHandle)))
461 {
462 return Mutex_FAILURE ;
463 }
464
465 return Mutex_OK;
466 }
467
MutexP_delete_handle(MutexP_Handle * pMutexHandle)468 int MutexP_delete_handle(MutexP_Handle* pMutexHandle)
469 {
470 MutexP_delete(*(pMutexHandle));
471 return(Mutex_OK);
472 }
473
Mutex_unlock(MutexP_Handle pMutexHandle)474 int Mutex_unlock(MutexP_Handle pMutexHandle)
475 {
476 MutexP_unlock(pMutexHandle, 0);
477 return(Mutex_OK);
478 }
479
480
Mutex_lock(MutexP_Handle pMutexHandle)481 int Mutex_lock(MutexP_Handle pMutexHandle)
482 {
483 MutexP_lock(pMutexHandle);
484 return(Mutex_OK);
485 }
486
SemaphoreP_create_handle(SemaphoreP_Handle * pSemHandle)487 int SemaphoreP_create_handle(SemaphoreP_Handle* pSemHandle)
488 {
489 SemaphoreP_Params params;
490
491 SemaphoreP_Params_init(¶ms);
492
493 params.mode = SemaphoreP_Mode_BINARY;
494
495 params.callback = tiDriverSpawnCallback;
496
497 (*(pSemHandle)) = SemaphoreP_create(1, ¶ms);
498
499 if(!(*(pSemHandle)))
500 {
501 return Semaphore_FAILURE ;
502 }
503
504 return Semaphore_OK;
505 }
506
SemaphoreP_delete_handle(SemaphoreP_Handle * pSemHandle)507 int SemaphoreP_delete_handle(SemaphoreP_Handle* pSemHandle)
508 {
509 SemaphoreP_delete(*(pSemHandle));
510 return Semaphore_OK;
511 }
512
SemaphoreP_post_handle(SemaphoreP_Handle * pSemHandle)513 int SemaphoreP_post_handle(SemaphoreP_Handle* pSemHandle)
514 {
515 SemaphoreP_post(*(pSemHandle));
516 return Semaphore_OK;
517 }
518 #endif
519
520
TimerGetCurrentTimestamp()521 unsigned long TimerGetCurrentTimestamp()
522 {
523 return (ClockP_getSystemTicks());
524 }
525
526
NwpWaitForShutDownInd()527 void NwpWaitForShutDownInd()
528 {
529 volatile unsigned long nwp_wakup_ind = HWREG(NWP_LPDS_WAKEUPCFG);
530 _SlTimeoutParams_t SlTimeoutInfo = {0};
531
532 _SlDrvStartMeasureTimeout(&SlTimeoutInfo, NWP_LPDS_WAKEUPCFG_TIMEOUT_MSEC);
533
534 while(nwp_wakup_ind != NWP_LPDS_WAKEUPCFG_APPS2NWP)
535 {
536 if(_SlDrvIsTimeoutExpired(&SlTimeoutInfo))
537 {
538 return;
539 }
540 nwp_wakup_ind = HWREG(NWP_LPDS_WAKEUPCFG);
541 }
542
543 return ;
544 }
545