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(&params);
455 
456     params.callback = tiDriverSpawnCallback;
457 
458     (*(pMutexHandle)) = MutexP_create(&params);
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(&params);
492 
493     params.mode = SemaphoreP_Mode_BINARY;
494 
495     params.callback = tiDriverSpawnCallback;
496 
497     (*(pSemHandle)) = SemaphoreP_create(1, &params);
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