1 /*
2  * Copyright (c) 2014-2019, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <stdint.h>
34 
35 /*
36  * By default disable both asserts and log for this module.
37  * This must be done before DebugP.h is included.
38  */
39 #ifndef DebugP_ASSERT_ENABLED
40 #define DebugP_ASSERT_ENABLED 0
41 #endif
42 #ifndef DebugP_LOG_ENABLED
43 #define DebugP_LOG_ENABLED 0
44 #endif
45 
46 #include <ti/drivers/dpl/ClockP.h>
47 #include <ti/drivers/dpl/DebugP.h>
48 #include <ti/drivers/dpl/HwiP.h>
49 #include <ti/drivers/dpl/SemaphoreP.h>
50 
51 #include <ti/drivers/Power.h>
52 #include <ti/drivers/power/PowerCC32XX.h>
53 #include <ti/drivers/uart/UARTCC32XXDMA.h>
54 #include <ti/drivers/dma/UDMACC32XX.h>
55 
56 /* driverlib header files */
57 #include <ti/devices/cc32xx/inc/hw_memmap.h>
58 #include <ti/devices/cc32xx/inc/hw_ocp_shared.h>
59 #include <ti/devices/cc32xx/inc/hw_ints.h>
60 #include <ti/devices/cc32xx/inc/hw_types.h>
61 #include <ti/devices/cc32xx/driverlib/rom.h>
62 #include <ti/devices/cc32xx/driverlib/rom_map.h>
63 #include <ti/devices/cc32xx/inc/hw_uart.h>
64 #include <ti/devices/cc32xx/driverlib/uart.h>
65 #include <ti/devices/cc32xx/driverlib/udma.h>
66 
67 /* DMA can handle transfers of at most 1024 elements */
68 #define MAXXFERSIZE 1024
69 
70 /* Pad configuration defines */
71 #define PAD_CONFIG_BASE (OCP_SHARED_BASE + OCP_SHARED_O_GPIO_PAD_CONFIG_0)
72 #define PAD_RESET_STATE 0xC61
73 
74 /* UARTCC32XXDMA functions */
75 void         UARTCC32XXDMA_close(UART_Handle handle);
76 int_fast16_t UARTCC32XXDMA_control(UART_Handle handle, uint_fast16_t cmd,
77                                    void *arg);
78 void         UARTCC32XXDMA_init(UART_Handle handle);
79 UART_Handle  UARTCC32XXDMA_open(UART_Handle handle, UART_Params *params);
80 int_fast32_t UARTCC32XXDMA_read(UART_Handle handle, void *buffer, size_t size);
81 void         UARTCC32XXDMA_readCancel(UART_Handle handle);
82 int_fast32_t UARTCC32XXDMA_readPolling(UART_Handle handle, void *buffer,
83                                        size_t size);
84 int_fast32_t UARTCC32XXDMA_write(UART_Handle handle, const void *buffer,
85                                  size_t size);
86 void         UARTCC32XXDMA_writeCancel(UART_Handle handle);
87 int_fast32_t UARTCC32XXDMA_writePolling(UART_Handle handle, const void *buffer,
88                                     size_t size);
89 
90 /* UART function table for UARTCC32XXDMA implementation */
91 const UART_FxnTable UARTCC32XXDMA_fxnTable = {
92     UARTCC32XXDMA_close,
93     UARTCC32XXDMA_control,
94     UARTCC32XXDMA_init,
95     UARTCC32XXDMA_open,
96     UARTCC32XXDMA_read,
97     UARTCC32XXDMA_readPolling,
98     UARTCC32XXDMA_readCancel,
99     UARTCC32XXDMA_write,
100     UARTCC32XXDMA_writePolling,
101     UARTCC32XXDMA_writeCancel
102 };
103 
104 /* Static functions */
105 static void UARTCC32XXDMA_configDMA(UART_Handle handle, bool isWrite);
106 static void UARTCC32XXDMA_hwiIntFxn(uintptr_t arg);
107 
108 static unsigned int getPowerMgrId(unsigned int baseAddr);
109 static void initHw(UART_Handle handle);
110 static int postNotifyFxn(unsigned int eventType, uintptr_t eventArg,
111         uintptr_t clientArg);
112 
113 static size_t readCancel(UART_Handle handle);
114 static void readSemCallback(UART_Handle handle, void *buffer, size_t count);
115 static void startTxFifoEmptyClk(UART_Handle handle, unsigned int size);
116 static size_t writeCancel(UART_Handle handle);
117 static void writeFinishedDoCallback(UART_Handle handle);
118 static void writeSemCallback(UART_Handle handle, void *buffer, size_t count);
119 
120 /*
121  * Function for checking whether flow control is enabled.
122  */
isFlowControlEnabled(UARTCC32XXDMA_HWAttrsV1 const * hwAttrs)123 static inline bool isFlowControlEnabled(UARTCC32XXDMA_HWAttrsV1 const  *hwAttrs) {
124     return ((hwAttrs->flowControl == UARTCC32XXDMA_FLOWCTRL_HARDWARE) &&
125         (hwAttrs->ctsPin != UARTCC32XXDMA_PIN_UNASSIGNED) &&
126             (hwAttrs->rtsPin != UARTCC32XXDMA_PIN_UNASSIGNED));
127 }
128 
129 
130 static const uint32_t dataLength[] = {
131     UART_CONFIG_WLEN_5, /* UART_LEN_5 */
132     UART_CONFIG_WLEN_6, /* UART_LEN_6 */
133     UART_CONFIG_WLEN_7, /* UART_LEN_7 */
134     UART_CONFIG_WLEN_8  /* UART_LEN_8 */
135 };
136 
137 static const uint32_t stopBits[] = {
138     UART_CONFIG_STOP_ONE,   /* UART_STOP_ONE */
139     UART_CONFIG_STOP_TWO    /* UART_STOP_TWO */
140 };
141 
142 static const uint32_t parityType[] = {
143     UART_CONFIG_PAR_NONE,   /* UART_PAR_NONE */
144     UART_CONFIG_PAR_EVEN,   /* UART_PAR_EVEN */
145     UART_CONFIG_PAR_ODD,    /* UART_PAR_ODD */
146     UART_CONFIG_PAR_ZERO,   /* UART_PAR_ZERO */
147     UART_CONFIG_PAR_ONE     /* UART_PAR_ONE */
148 };
149 
150 /*
151  *  ======== UARTCC32XXDMA_close ========
152  */
UARTCC32XXDMA_close(UART_Handle handle)153 void UARTCC32XXDMA_close(UART_Handle handle)
154 {
155     UARTCC32XXDMA_Object           *object = handle->object;
156     UARTCC32XXDMA_HWAttrsV1 const  *hwAttrs = handle->hwAttrs;
157     uint32_t                       padRegister;
158 
159     /* Disable UART and interrupts. */
160     MAP_UARTDMADisable(hwAttrs->baseAddr, UART_DMA_TX | UART_DMA_RX);
161     MAP_UARTDisable(hwAttrs->baseAddr);
162 
163     if (object->hwiHandle) {
164         HwiP_delete(object->hwiHandle);
165     }
166     if (object->writeSem) {
167         SemaphoreP_delete(object->writeSem);
168     }
169     if (object->readSem) {
170         SemaphoreP_delete(object->readSem);
171     }
172     if (object->txFifoEmptyClk) {
173         ClockP_delete(object->txFifoEmptyClk);
174     }
175 
176     if (object->dmaHandle) {
177         UDMACC32XX_close(object->dmaHandle);
178     }
179 
180     Power_unregisterNotify(&object->postNotify);
181     Power_releaseDependency(object->powerMgrId);
182 
183     if (object->txPin != (uint16_t)-1) {
184         PowerCC32XX_restoreParkState((PowerCC32XX_Pin)object->txPin,
185             object->prevParkTX);
186         object->txPin = (uint16_t)-1;
187     }
188 
189     if (object->rtsPin != (uint16_t)-1) {
190         PowerCC32XX_restoreParkState((PowerCC32XX_Pin)object->rtsPin,
191             object->prevParkRTS);
192         object->rtsPin = (uint16_t)-1;
193     }
194 
195     /* Restore pin pads to their reset states */
196     padRegister = (PinToPadGet((hwAttrs->rxPin) & 0xff)<<2) + PAD_CONFIG_BASE;
197     HWREG(padRegister) = PAD_RESET_STATE;
198     padRegister = (PinToPadGet((hwAttrs->txPin) & 0xff)<<2) + PAD_CONFIG_BASE;
199     HWREG(padRegister) = PAD_RESET_STATE;
200     if (isFlowControlEnabled(hwAttrs)) {
201         padRegister = (PinToPadGet((hwAttrs->ctsPin) & 0xff)<<2)
202             + PAD_CONFIG_BASE;
203         HWREG(padRegister) = PAD_RESET_STATE;
204         padRegister = (PinToPadGet((hwAttrs->rtsPin) & 0xff)<<2)
205             + PAD_CONFIG_BASE;
206         HWREG(padRegister) = PAD_RESET_STATE;
207     }
208 
209     object->opened = false;
210 
211     DebugP_log1("UART:(%p) closed", hwAttrs->baseAddr);
212 }
213 
214 /*
215  *  ======== UARTCC32XXDMA_control ========
216  *  @pre    Function assumes that the handle is not NULL
217  */
UARTCC32XXDMA_control(UART_Handle handle,uint_fast16_t cmd,void * arg)218 int_fast16_t UARTCC32XXDMA_control(UART_Handle handle, uint_fast16_t cmd,
219         void *arg)
220 {
221     UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
222 
223     switch (cmd) {
224         /* Specific UART CMDs */
225         case (UARTCC32XXDMA_CMD_IS_BUSY):
226             *(bool *)arg = MAP_UARTBusy(hwAttrs->baseAddr);
227             return (UART_STATUS_SUCCESS);
228 
229         case (UARTCC32XXDMA_CMD_IS_RX_DATA_AVAILABLE):
230             *(bool *)arg = MAP_UARTCharsAvail(hwAttrs->baseAddr);
231             return (UART_STATUS_SUCCESS);
232 
233         case (UARTCC32XXDMA_CMD_IS_TX_SPACE_AVAILABLE):
234             *(bool *)arg = MAP_UARTSpaceAvail(hwAttrs->baseAddr);
235             return (UART_STATUS_SUCCESS);
236 
237         default:
238             DebugP_log2("UART:(%p) UART CMD undefined: %d",
239                 hwAttrs->baseAddr, cmd);
240             return (UART_STATUS_UNDEFINEDCMD);
241     }
242 }
243 
244 /*
245  *  ======== UARTCC32XXDMA_init ========
246  */
UARTCC32XXDMA_init(UART_Handle handle)247 void UARTCC32XXDMA_init(UART_Handle handle)
248 {
249 }
250 
251 /*
252  *  ======== UARTCC32XXDMA_open ========
253  */
UARTCC32XXDMA_open(UART_Handle handle,UART_Params * params)254 UART_Handle UARTCC32XXDMA_open(UART_Handle handle, UART_Params *params)
255 {
256     uintptr_t                      key;
257     UARTCC32XXDMA_Object          *object = handle->object;
258     UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
259     SemaphoreP_Params              semParams;
260     HwiP_Params                    hwiParams;
261     ClockP_Params                  clockParams;
262     uint16_t                       pin;
263     uint16_t                       mode;
264 
265     /* Timeouts cannot be 0 */
266     DebugP_assert((params->writeTimeout != 0) && (params->readTimeout != 0));
267 
268     /* Check that a callback is set */
269     DebugP_assert((params->readMode != UART_MODE_CALLBACK) ||
270                   (params->readCallback != NULL));
271     DebugP_assert((params->writeMode != UART_MODE_CALLBACK) ||
272                   (params->writeCallback != NULL));
273 
274     /* Initialize the DMA */
275     UDMACC32XX_init();
276 
277     object->powerMgrId = getPowerMgrId(hwAttrs->baseAddr);
278     if (object->powerMgrId == (unsigned int)-1) {
279         DebugP_log1("UART:(%p) Failed to determine power resource id",
280                 hwAttrs->baseAddr);
281         return (NULL);
282     }
283 
284     /* Disable preemption while checking if the UART is open. */
285     key = HwiP_disable();
286 
287     /* Check if the UART is open already with the base addr. */
288     if (object->opened == true) {
289         HwiP_restore(key);
290 
291         DebugP_log1("UART:(%p) already in use.", hwAttrs->baseAddr);
292         return (NULL);
293     }
294 
295     object->opened = true;
296     HwiP_restore(key);
297 
298     /*
299      *  Register power dependency. Keeps the clock running in SLP
300      *  and DSLP modes.
301      */
302 
303     Power_setDependency(object->powerMgrId);
304 
305     /* Do a software reset of the peripheral */
306     PowerCC32XX_reset(object->powerMgrId);
307 
308     Power_registerNotify(&object->postNotify, PowerCC32XX_AWAKE_LPDS,
309             postNotifyFxn, (uintptr_t)handle);
310 
311     object->readMode       = params->readMode;
312     object->writeMode      = params->writeMode;
313     object->readTimeout    = params->readTimeout;
314     object->writeTimeout   = params->writeTimeout;
315     object->readCallback   = params->readCallback;
316     object->writeCallback  = params->writeCallback;
317     object->readReturnMode = params->readReturnMode;
318     object->readDataMode   = params->readDataMode;
319     object->writeDataMode  = params->writeDataMode;
320     object->readEcho       = params->readEcho;
321     object->baudRate       = params->baudRate;
322     object->stopBits       = params->stopBits;
323     object->dataLength     = params->dataLength;
324     object->parityType     = params->parityType;
325 
326     /* Set UART variables to defaults. */
327     object->writeBuf = NULL;
328     object->readBuf = NULL;
329     object->writeCount = 0;
330     object->readCount = 0;
331     object->writeSize = 0;
332     object->readSize = 0;
333     object->readSem = NULL;
334     object->writeSem = NULL;
335     object->txFifoEmptyClk = NULL;
336     object->txPin = (uint16_t)-1;
337 
338     /* DMA first */
339     object->dmaHandle = UDMACC32XX_open();
340     if (object->dmaHandle == NULL) {
341         UARTCC32XXDMA_close(handle);
342         DebugP_log1("UART:(%p) UDMACC32XX_open() failed.", hwAttrs->baseAddr);
343         return (NULL);
344     }
345 
346     pin = (hwAttrs->rxPin) & 0xff;
347     mode = (hwAttrs->rxPin >> 8) & 0xff;
348 
349     MAP_PinTypeUART((unsigned long)pin, (unsigned long)mode);
350 
351     pin = (hwAttrs->txPin) & 0xff;
352     mode = (hwAttrs->txPin >> 8) & 0xff;
353 
354     MAP_PinTypeUART((unsigned long)pin, (unsigned long)mode);
355 
356     /*
357      * Read and save TX pin park state; set to "don't park" while UART is
358      * open as device default is logic '1' during LPDS
359      */
360     object->prevParkTX =
361         (PowerCC32XX_ParkState) PowerCC32XX_getParkState((PowerCC32XX_Pin)pin);
362     PowerCC32XX_setParkState((PowerCC32XX_Pin)pin, ~1);
363     object->txPin = pin;
364 
365     if (isFlowControlEnabled(hwAttrs)) {
366         pin = (hwAttrs->ctsPin) & 0xff;
367         mode = (hwAttrs->ctsPin >> 8) & 0xff;
368         MAP_PinTypeUART((unsigned long)pin, (unsigned long)mode);
369 
370         pin = (hwAttrs->rtsPin) & 0xff;
371         mode = (hwAttrs->rtsPin >> 8) & 0xff;
372         MAP_PinTypeUART((unsigned long)pin, (unsigned long)mode);
373 
374         /*
375          * Read and save RTS pin park state; set to "don't park" while UART is
376          * open as device default is logic '1' during LPDS
377          */
378         object->prevParkRTS = (PowerCC32XX_ParkState)PowerCC32XX_getParkState(
379             (PowerCC32XX_Pin)pin);
380         PowerCC32XX_setParkState((PowerCC32XX_Pin)pin, ~1);
381         object->rtsPin = pin;
382 
383         /* Flow control will be enabled in initHw() */
384     }
385     HwiP_clearInterrupt(hwAttrs->intNum);
386 
387     HwiP_Params_init(&hwiParams);
388     hwiParams.arg = (uintptr_t)handle;
389     hwiParams.priority = hwAttrs->intPriority;
390     object->hwiHandle = HwiP_create(hwAttrs->intNum,
391                                     UARTCC32XXDMA_hwiIntFxn,
392                                     &hwiParams);
393     if (object->hwiHandle == NULL) {
394         DebugP_log1("UART:(%p) HwiP_create() failed", hwAttrs->baseAddr);
395         UARTCC32XXDMA_close(handle);
396         return (NULL);
397     }
398 
399     /* Disable the UART interrupt. */
400     MAP_UARTIntDisable(hwAttrs->baseAddr,
401                       (UART_INT_TX | UART_INT_RX | UART_INT_RT));
402 
403     SemaphoreP_Params_init(&semParams);
404     semParams.mode = SemaphoreP_Mode_BINARY;
405 
406     /* Create semaphores and set callbacks for BLOCKING modes. */
407     if (object->writeMode == UART_MODE_BLOCKING) {
408         object->writeCallback = &writeSemCallback;
409 
410         object->writeSem = SemaphoreP_create(0, &semParams);
411         if (object->writeSem == NULL) {
412             UARTCC32XXDMA_close(handle);
413             DebugP_log1("UART:(%p) Failed to create semaphore.",
414                         hwAttrs->baseAddr);
415             return (NULL);
416         }
417     }
418 
419     if (object->readMode == UART_MODE_BLOCKING) {
420         object->readCallback = &readSemCallback;
421 
422         object->readSem = SemaphoreP_create(0, &semParams);
423         if (object->readSem == NULL) {
424             UARTCC32XXDMA_close(handle);
425             DebugP_log1("UART:(%p) Failed to create semaphore.",
426                         hwAttrs->baseAddr);
427             return (NULL);
428         }
429     }
430 
431     /*
432      *  Clock object to ensure FIFO is drained before releasing Power
433      *  constraints.
434      */
435     ClockP_Params_init(&clockParams);
436     clockParams.arg = (uintptr_t)handle;
437 
438     object->txFifoEmptyClk = ClockP_create((ClockP_Fxn)&writeFinishedDoCallback,
439             0 /* timeout */, &(clockParams));
440 
441     if (object->txFifoEmptyClk == NULL) {
442         UARTCC32XXDMA_close(handle);
443         DebugP_log1("UART:(%p) ClockP_create() failed.",
444                     hwAttrs->baseAddr);
445         return (NULL);
446     }
447 
448     /* Initialize the hardware */
449     initHw(handle);
450 
451 
452     DebugP_log1("UART:(%p) opened", hwAttrs->baseAddr);
453 
454     /* Return the handle */
455     return (handle);
456 }
457 
458 /*
459  *  ======== UARTCC32XXDMA_read ========
460  */
UARTCC32XXDMA_read(UART_Handle handle,void * buffer,size_t size)461 int_fast32_t UARTCC32XXDMA_read(UART_Handle handle, void *buffer, size_t size)
462 {
463     uintptr_t             key;
464     UARTCC32XXDMA_Object *object = handle->object;
465 
466     /* DMA cannot handle transfer sizes > 1024 elements */
467     if (size > MAXXFERSIZE) {
468         DebugP_log1("UART:(%p) Data size too large.",
469                 ((UARTCC32XXDMA_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr);
470 
471         return (UART_ERROR);
472     }
473 
474     /* Disable preemption while checking if the uart is in use. */
475     key = HwiP_disable();
476     if (object->readSize) {
477         HwiP_restore(key);
478 
479         DebugP_log1("UART:(%p) Could not read data, uart in use.",
480                 ((UARTCC32XXDMA_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr);
481         return (UART_ERROR);
482     }
483 
484     /* Save the data to be read and restore interrupts. */
485     object->readBuf = buffer;
486     object->readSize = size;
487     object->readCount = 0;
488 
489     /* Set constraints to guarantee transaction */
490     Power_setConstraint(PowerCC32XX_DISALLOW_LPDS);
491 
492     /*
493      *  Start the DMA transfer.  Do this inside the critical
494      *  section to prevent UARTCC32XXDMA_readCancel() being called
495      *  after object->readSize is set, but before the DMA is
496      *  configured.  If that happened, the size in the DMA control
497      *  register would be 0, causing UARTCC32XXDMA_readCancel()
498      *  to assume all bytes were transferred.
499      */
500     UARTCC32XXDMA_configDMA(handle, false /* isWrite */);
501 
502     HwiP_restore(key);
503 
504     /* If readMode is blocking, block and get the status. */
505     if (object->readMode == UART_MODE_BLOCKING) {
506 
507         /* Pend on semaphore and wait for Hwi to finish. */
508         if (SemaphoreP_OK != SemaphoreP_pend(object->readSem,
509                     object->readTimeout)) {
510             key = HwiP_disable();
511 
512             /* Cancel the DMA without posting the semaphore */
513             (void)readCancel(handle);
514 
515             /*
516              *  If ISR ran after timeout, but before the call to
517              *  readCancel(), readSem would be posted. Pend on
518              *  the semaphore with 0 timeout so the next read
519              *  will block.
520              */
521             if (object->readCount == size) {
522                 SemaphoreP_pend(object->readSem, 0);
523             }
524 
525             HwiP_restore(key);
526 
527             DebugP_log2("UART:(%p) Read timed out, %d bytes read",
528                     ((UARTCC32XXDMA_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr,
529                     object->readCount);
530 
531         }
532         return (object->readCount);
533     }
534 
535     return (0);
536 }
537 
538 /*
539  *  ======== UARTCC32XXDMA_readPolling ========
540  */
UARTCC32XXDMA_readPolling(UART_Handle handle,void * buf,size_t size)541 int_fast32_t UARTCC32XXDMA_readPolling(UART_Handle handle, void *buf,
542         size_t size)
543 {
544     int32_t                        count = 0;
545     UARTCC32XXDMA_Object          *object = handle->object;
546     UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
547     unsigned char                 *buffer = (unsigned char *)buf;
548 
549     /* Read characters. */
550     while (size) {
551         *buffer = MAP_UARTCharGet(hwAttrs->baseAddr);
552         DebugP_log2("UART:(%p) Read character 0x%x",
553                     hwAttrs->baseAddr, *buffer);
554         count++;
555         size--;
556 
557         if (object->readDataMode == UART_DATA_TEXT && *buffer == '\r') {
558             /* Echo character if enabled. */
559             if (object->readEcho) {
560                 MAP_UARTCharPut(hwAttrs->baseAddr, '\r');
561             }
562             *buffer = '\n';
563         }
564 
565         /* Echo character if enabled. */
566         if (object->readEcho) {
567             MAP_UARTCharPut(hwAttrs->baseAddr, *buffer);
568         }
569 
570         /* If read return mode is newline, finish if a newline was received. */
571         if (object->readReturnMode == UART_RETURN_NEWLINE &&
572             *buffer == '\n') {
573             return (count);
574         }
575 
576         buffer++;
577     }
578 
579     DebugP_log2("UART:(%p) Read polling finished, %d bytes read",
580                 hwAttrs->baseAddr, count);
581 
582     return (count);
583 }
584 
585 /*
586  *  ======== UARTCC32XXDMA_readCancel ========
587  */
UARTCC32XXDMA_readCancel(UART_Handle handle)588 void UARTCC32XXDMA_readCancel(UART_Handle handle)
589 {
590     UARTCC32XXDMA_Object *object = handle->object;
591     size_t                size;
592 
593     /* Stop any ongoing DMA read */
594     size = readCancel(handle);
595 
596     if (size == 0) {
597         return;
598     }
599 
600     if (object->readMode == UART_MODE_CALLBACK) {
601         object->readCallback(handle, object->readBuf, object->readCount);
602     }
603     else if (object->readMode == UART_MODE_BLOCKING) {
604         /* We don't know if we're in an ISR, but we'll assume not. */
605         SemaphoreP_post(object->readSem);
606     }
607 
608     DebugP_log1("UART:(%p) Read canceled, 0 bytes read",
609             ((UARTCC32XXDMA_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr);
610 }
611 
612 /*
613  *  ======== UARTCC32XXDMA_write ========
614  */
UARTCC32XXDMA_write(UART_Handle handle,const void * buffer,size_t size)615 int_fast32_t UARTCC32XXDMA_write(UART_Handle handle, const void *buffer,
616         size_t size)
617 {
618     uintptr_t             key;
619     UARTCC32XXDMA_Object *object = handle->object;
620     UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
621 
622     /* DMA cannot handle transfer sizes > 1024 elements */
623     if (size > MAXXFERSIZE) {
624         DebugP_log1("UART:(%p) Data size too large.", hwAttrs->baseAddr);
625 
626         return (UART_ERROR);
627     }
628 
629     /* Disable preemption while checking if the uart is in use. */
630     key = HwiP_disable();
631     if (object->writeSize || UARTBusy(hwAttrs->baseAddr)) {
632         HwiP_restore(key);
633         DebugP_log1("UART:(%p) Could not write data, uart in use.",
634                 ((UARTCC32XXDMA_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr);
635 
636         return (UART_ERROR);
637     }
638 
639     /* Save the data to be written and restore interrupts. */
640     object->writeBuf = buffer;
641     object->writeCount = 0;
642     object->writeSize = size;
643 
644     /* Set constraints to guarantee transaction */
645     Power_setConstraint(PowerCC32XX_DISALLOW_LPDS);
646 
647     UARTCC32XXDMA_configDMA(handle, true /* isWrite */);
648 
649     HwiP_restore(key);
650 
651     /* If writeMode is blocking, block and get the status. */
652     if (object->writeMode == UART_MODE_BLOCKING) {
653         /* Pend on semaphore and wait for Hwi to finish. */
654         if (SemaphoreP_OK != SemaphoreP_pend(object->writeSem,
655                     object->writeTimeout)) {
656 
657             key = HwiP_disable();
658 
659             /* Stop any ongoing DMA writes and release Power constraints. */
660             (void)writeCancel(handle);
661 
662             /*
663              *  If ISR ran after timeout, but before the call to
664              *  writeCancel(), writeSem would be posted. Pend on
665              *  the semaphore so the next write call will block.
666              */
667             if (object->writeCount == size) {
668                 SemaphoreP_pend(object->writeSem, 0);
669             }
670 
671             HwiP_restore(key);
672 
673             DebugP_log2("UART:(%p) Write timed out, %d bytes written",
674                     ((UARTCC32XXDMA_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr,
675                     object->writeCount);
676 
677         }
678         return (object->writeCount);
679     }
680 
681     return (0);
682 }
683 
684 /*
685  *  ======== UARTCC32XXDMA_writePolling ========
686  */
UARTCC32XXDMA_writePolling(UART_Handle handle,const void * buf,size_t size)687 int_fast32_t UARTCC32XXDMA_writePolling(UART_Handle handle, const void *buf,
688         size_t size)
689 {
690     int32_t                        count = 0;
691     UARTCC32XXDMA_Object          *object = handle->object;
692     UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
693     unsigned char                 *buffer = (unsigned char *)buf;
694 
695     /* Write characters. */
696     while (size) {
697         if (object->writeDataMode == UART_DATA_TEXT && *buffer == '\n') {
698             MAP_UARTCharPut(hwAttrs->baseAddr, '\r');
699             count++;
700         }
701         MAP_UARTCharPut(hwAttrs->baseAddr, *buffer);
702 
703         DebugP_log2("UART:(%p) Wrote character 0x%x",
704                 ((UARTCC32XXDMA_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr,
705                 *buffer);
706         buffer++;
707         count++;
708         size--;
709     }
710 
711     DebugP_log2("UART:(%p) Write polling finished, %d bytes written",
712             ((UARTCC32XXDMA_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr,
713             count);
714 
715     return (count);
716 }
717 
718 /*
719  *  ======== UARTCC32XXDMA_writeCancel ========
720  */
UARTCC32XXDMA_writeCancel(UART_Handle handle)721 void UARTCC32XXDMA_writeCancel(UART_Handle handle)
722 {
723     UARTCC32XXDMA_Object *object = handle->object;
724     size_t                size;
725 
726     /* Stop any ongoing DMA transmits */
727     size = writeCancel(handle);
728 
729     if (size == 0) {
730         return;
731     }
732 
733     if (object->writeMode == UART_MODE_CALLBACK) {
734         object->writeCallback(handle, (uint8_t*)object->writeBuf,
735                 object->writeCount);
736     }
737     else  if (object->writeMode == UART_MODE_BLOCKING) {
738         /* We don't know if we're in an ISR, but we'll assume not. */
739         SemaphoreP_post(object->writeSem);
740     }
741 
742     DebugP_log2("UART:(%p) Write canceled, %d bytes written",
743             ((UARTCC32XXDMA_HWAttrsV1 const *)(handle->hwAttrs))->baseAddr,
744             object->writeCount);
745 }
746 
747 /*
748  *  ======== UARTCC32XXDMA_configDMA ========
749  *  Call with interrupts disabled.
750  */
UARTCC32XXDMA_configDMA(UART_Handle handle,bool isWrite)751 static void UARTCC32XXDMA_configDMA(UART_Handle handle, bool isWrite)
752 {
753     UARTCC32XXDMA_Object           *object = handle->object;
754     UARTCC32XXDMA_HWAttrsV1 const  *hwAttrs = handle->hwAttrs;
755     unsigned long                   channelControlOptions;
756 
757     if (isWrite) {
758         channelControlOptions = UDMA_SIZE_8 | UDMA_SRC_INC_8 |
759                 UDMA_DST_INC_NONE | UDMA_ARB_4;
760 
761         MAP_uDMAChannelControlSet(hwAttrs->txChannelIndex | UDMA_PRI_SELECT,
762                 channelControlOptions);
763 
764         MAP_uDMAChannelTransferSet(hwAttrs->txChannelIndex | UDMA_PRI_SELECT,
765                 UDMA_MODE_BASIC,
766                 (void *)object->writeBuf,
767                 (void *)(hwAttrs->baseAddr + UART_O_DR),
768                 object->writeSize);
769 
770         /*
771          *  Enable the DMA channel
772          *  This sets the channel's corresponding bit in the uDMA ENASET register.
773          *  The bit will be cleared when the transfer completes.
774          */
775         MAP_uDMAChannelEnable(hwAttrs->txChannelIndex);
776 
777         MAP_UARTIntClear(hwAttrs->baseAddr, UART_INT_DMATX);
778         MAP_UARTIntEnable(hwAttrs->baseAddr, UART_INT_DMATX);
779     }
780     else {
781         channelControlOptions = UDMA_SIZE_8 | UDMA_SRC_INC_NONE |
782                 UDMA_DST_INC_8 | UDMA_ARB_4;
783 
784         MAP_uDMAChannelControlSet(hwAttrs->rxChannelIndex | UDMA_PRI_SELECT,
785                 channelControlOptions);
786 
787         MAP_uDMAChannelTransferSet(hwAttrs->rxChannelIndex | UDMA_PRI_SELECT,
788                 UDMA_MODE_BASIC,
789                 (void *)(hwAttrs->baseAddr + UART_O_DR),
790                 object->readBuf,
791                 object->readSize);
792 
793         /* Enable DMA Channel */
794         MAP_uDMAChannelEnable(hwAttrs->rxChannelIndex);
795 
796         MAP_UARTIntClear(hwAttrs->baseAddr, UART_INT_DMARX);
797         MAP_UARTIntEnable(hwAttrs->baseAddr, UART_INT_DMARX);
798     }
799 
800     DebugP_log1("UART:(%p) DMA transfer enabled", hwAttrs->baseAddr);
801 
802     if (isWrite) {
803         DebugP_log3("UART:(%p) DMA transmit, txBuf: %p; Count: %d",
804                     hwAttrs->baseAddr, (uintptr_t)(object->writeBuf),
805                     object->writeSize);
806     }
807     else {
808         DebugP_log3("UART:(%p) DMA receive, rxBuf: %p; Count: %d",
809                     hwAttrs->baseAddr, (uintptr_t)(object->readBuf),
810                     object->readSize);
811     }
812 }
813 
814 /*
815  *  ======== UARTCC32XXDMA_hwiIntFxn ========
816  *  Hwi function that processes UART interrupts.
817  *
818  *  Three UART interrupts are enabled: Transmit FIFO is 4/8 empty,
819  *  receive FIFO is 4/8 full and a receive timeout between the time
820  *  the last character was received.
821  *
822  *  @param(arg)         The UART_Handle for this Hwi.
823  */
UARTCC32XXDMA_hwiIntFxn(uintptr_t arg)824 static void UARTCC32XXDMA_hwiIntFxn(uintptr_t arg)
825 {
826     uint32_t                       status;
827     UARTCC32XXDMA_Object          *object = ((UART_Handle)arg)->object;
828     UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = ((UART_Handle)arg)->hwAttrs;
829 
830     /*
831      *  Clear interrupts
832      *    UARTIntStatus(base, false) - read the raw interrupt status
833      *    UARTIntStatus(base, true)  - read masked interrupt status
834      */
835     status = MAP_UARTIntStatus(hwAttrs->baseAddr, false);
836     if (status & UART_INT_DMATX) {
837         MAP_UARTIntDisable(hwAttrs->baseAddr, UART_INT_DMATX);
838         MAP_UARTIntClear(hwAttrs->baseAddr, UART_INT_DMATX);
839     }
840 
841     if (status & UART_INT_DMARX) {
842         MAP_UARTIntDisable(hwAttrs->baseAddr, UART_INT_DMARX);
843         MAP_UARTIntClear(hwAttrs->baseAddr, UART_INT_DMARX);
844     }
845 
846     DebugP_log2("UART:(%p) Interrupt with mask 0x%x",
847                 hwAttrs->baseAddr, status);
848 
849     /* Read data if characters are available. */
850     if (object->readSize &&
851                 !MAP_uDMAChannelIsEnabled(hwAttrs->rxChannelIndex)) {
852         object->readCount = object->readSize;
853         object->readSize = 0;
854         object->readCallback((UART_Handle)arg, object->readBuf,
855                 object->readCount);
856 
857         Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
858 
859         DebugP_log2("UART:(%p) Read finished, %d bytes read",
860                     hwAttrs->baseAddr, object->readCount);
861     }
862 
863     /* Write completed. */
864     if (object->writeSize &&
865                 !MAP_uDMAChannelIsEnabled(hwAttrs->txChannelIndex)) {
866         object->writeCount = object->writeSize;
867         object->writeSize = 0;
868         /*
869          *  No more to write, but data is not shifted out yet.
870          *  Start TX FIFO Empty clock.
871          *  + 4 because it is 4 bytes left in TX FIFO when the TX FIFO
872          *  threshold interrupt occurs.
873          */
874         startTxFifoEmptyClk((UART_Handle)arg, 4);
875 
876         DebugP_log2("UART:(%p) Write finished, %d bytes written",
877                     hwAttrs->baseAddr, object->writeCount);
878     }
879 }
880 
881 /*
882  *  ======== getPowerMgrId ========
883  */
getPowerMgrId(unsigned int baseAddr)884 static unsigned int getPowerMgrId(unsigned int baseAddr)
885 {
886     switch (baseAddr) {
887         case UARTA0_BASE:
888             return (PowerCC32XX_PERIPH_UARTA0);
889         case UARTA1_BASE:
890             return (PowerCC32XX_PERIPH_UARTA1);
891         default:
892             return ((unsigned int)-1);
893     }
894 }
895 
896 /*
897  *  ======== initHw ========
898  *  Initialize the hardware.
899  */
initHw(UART_Handle handle)900 static void initHw(UART_Handle handle)
901 {
902     ClockP_FreqHz                 freq;
903     UARTCC32XXDMA_Object          *object = handle->object;
904     UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
905 
906     /*
907      *  Set the FIFO level to 4/8 empty and 4/8 full.
908      *  The UART generates a burst request based on the FIFO trigger
909      *  level. The arbitration size should be set to the amount
910      *  of data that the FIFO can transfer when the trigger level is reached.
911      *  Since arbitration size is a power of 2, we'll set the FIFO levels
912      *  to 4_8 so they can match the arbitration size of 4.
913      */
914     MAP_UARTFIFOLevelSet(hwAttrs->baseAddr, UART_FIFO_TX4_8, UART_FIFO_RX4_8);
915 
916     if (isFlowControlEnabled(hwAttrs)) {
917         /* Set flow control */
918         MAP_UARTFlowControlSet(hwAttrs->baseAddr,
919                 UART_FLOWCONTROL_TX | UART_FLOWCONTROL_RX);
920     }
921     else {
922         MAP_UARTFlowControlSet(hwAttrs->baseAddr, UART_FLOWCONTROL_NONE);
923     }
924 
925     ClockP_getCpuFreq(&freq);
926     MAP_UARTConfigSetExpClk(hwAttrs->baseAddr,
927                             freq.lo,
928                             object->baudRate,
929                             dataLength[object->dataLength] |
930                             stopBits[object->stopBits] |
931                             parityType[object->parityType]);
932 
933     MAP_UARTDMAEnable(hwAttrs->baseAddr, UART_DMA_TX | UART_DMA_RX);
934 
935     /* Configure DMA for TX and RX */
936     MAP_uDMAChannelAssign(hwAttrs->txChannelIndex);
937     MAP_uDMAChannelAttributeDisable(hwAttrs->txChannelIndex, UDMA_ATTR_ALTSELECT);
938 
939     MAP_uDMAChannelAssign(hwAttrs->rxChannelIndex);
940     MAP_uDMAChannelAttributeDisable(hwAttrs->rxChannelIndex, UDMA_ATTR_ALTSELECT);
941     MAP_UARTEnable(hwAttrs->baseAddr);
942 }
943 
944 /*
945  *  ======== postNotifyFxn ========
946  *  Called by Power module when waking up from LPDS.
947  */
postNotifyFxn(unsigned int eventType,uintptr_t eventArg,uintptr_t clientArg)948 static int postNotifyFxn(unsigned int eventType, uintptr_t eventArg,
949         uintptr_t clientArg)
950 {
951     initHw((UART_Handle)clientArg);
952 
953     return (Power_NOTIFYDONE);
954 }
955 
956 /*
957  *  ======== readCancel ========
958  *  Stop the current DMA receive transfer.
959  */
readCancel(UART_Handle handle)960 static size_t readCancel(UART_Handle handle)
961 {
962     uintptr_t                      key;
963     UARTCC32XXDMA_Object          *object = handle->object;
964     UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
965     uint32_t                       remainder;
966     int                            bytesTransferred;
967     size_t                         size;
968 
969     /* Disable interrupts to avoid reading data while changing state. */
970     key = HwiP_disable();
971 
972     size = object->readSize;
973 
974     /* Return if there is no read. */
975     if (!object->readSize) {
976         HwiP_restore(key);
977         return (size);
978     }
979 
980     /* Set channel bit in the ENACLR register */
981     MAP_uDMAChannelDisable(hwAttrs->rxChannelIndex);
982 
983     remainder = MAP_uDMAChannelSizeGet(hwAttrs->rxChannelIndex);
984     bytesTransferred = object->readSize - remainder;
985 
986     /*
987      *  Since object->readSize != 0, the ISR has not run and released
988      *  the Power constraint.  Release the constraint here.  Setting
989      *  object->readSize to 0 will prevent the ISR from releasing the
990      *  constraint in case it is pending.
991      */
992     Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
993 
994     /* Set size = 0 to prevent reading and restore interrupts. */
995     object->readSize = 0;
996     object->readCount = bytesTransferred;
997 
998     HwiP_restore(key);
999 
1000     return (size);
1001 }
1002 
1003 /*
1004  *  ======== readSemCallback ========
1005  *  Simple callback to post a semaphore for the blocking mode.
1006  */
readSemCallback(UART_Handle handle,void * buffer,size_t count)1007 static void readSemCallback(UART_Handle handle, void *buffer, size_t count)
1008 {
1009     UARTCC32XXDMA_Object *object = handle->object;
1010 
1011     SemaphoreP_post(object->readSem);
1012 }
1013 
1014 /*
1015  *  ======== writeSemCallback ========
1016  *  Simple callback to post a semaphore for the blocking mode.
1017  */
writeSemCallback(UART_Handle handle,void * buffer,size_t count)1018 static void writeSemCallback(UART_Handle handle, void *buffer, size_t count)
1019 {
1020     UARTCC32XXDMA_Object *object = handle->object;
1021 
1022     SemaphoreP_post(object->writeSem);
1023 }
1024 
1025 /*
1026  *  ======== writeCancel ========
1027  */
writeCancel(UART_Handle handle)1028 static size_t writeCancel(UART_Handle handle)
1029 {
1030     uintptr_t                      key;
1031     UARTCC32XXDMA_Object          *object = handle->object;
1032     UARTCC32XXDMA_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
1033     uint32_t                       remainder;
1034     int                            bytesTransferred;
1035     size_t                         size;
1036 
1037     /* Disable interrupts to avoid writing data while changing state. */
1038     key = HwiP_disable();
1039 
1040     size = object->writeSize;
1041 
1042     /* Set channel bit in the ENACLR register */
1043     MAP_uDMAChannelDisable(hwAttrs->txChannelIndex);
1044 
1045     remainder = MAP_uDMAChannelSizeGet(hwAttrs->txChannelIndex);
1046     bytesTransferred = object->writeSize - remainder;
1047 
1048     /* Return if there is no write. */
1049     if (!object->writeSize) {
1050         HwiP_restore(key);
1051 
1052         return (size);
1053     }
1054 
1055     /*
1056      *  If the transfer didn't complete, the ISR will not run to
1057      *  release the Power constraint, so do it here.
1058      */
1059     if (bytesTransferred < object->writeSize) {
1060         Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
1061     }
1062 
1063     /* Set size = 0 to prevent writing and restore interrupts. */
1064     object->writeSize = 0;
1065     object->writeCount = bytesTransferred;
1066 
1067     HwiP_restore(key);
1068 
1069     return (size);
1070 }
1071 
1072 /*
1073  *  ======== startTxFifoEmptyClk ========
1074  *  Last write to TX FIFO is done, but not shifted out yet. Start a clock
1075  *  which will trigger when the TX FIFO should be empty.
1076  *
1077  *  @param(handle)         The UART_Handle for ongoing write.
1078  *  @param(numData)        The number of data present in FIFO after last write
1079  */
startTxFifoEmptyClk(UART_Handle handle,unsigned int numData)1080 static void startTxFifoEmptyClk(UART_Handle handle, unsigned int numData)
1081 {
1082     UARTCC32XXDMA_Object *object = handle->object;
1083     unsigned int writeTimeout;
1084     unsigned int ticksPerSec;
1085 
1086     /* No more to write, but data is not shiftet out properly yet.
1087      *   1. Compute appropriate wait time for FIFO to empty out
1088      *       - 8 - for maximum data length
1089      *       - 3 - for one start bit and maximum of two stop bits
1090      */
1091     ticksPerSec = ClockP_getSystemTickFreq();
1092     writeTimeout = ((numData * (8 + 3) * ticksPerSec) + object->baudRate - 1)
1093                            / object->baudRate;
1094 
1095     /*   2. Configure clock object to trigger when FIFO is empty */
1096     ClockP_setTimeout(object->txFifoEmptyClk, writeTimeout);
1097     ClockP_start(object->txFifoEmptyClk);
1098 }
1099 
1100 /*
1101  *  ======== writeFinishedDoCallback ========
1102  *  Write finished - make callback
1103  *
1104  *  This function is called when the txFifoEmptyClk times out. The TX FIFO
1105  *  should now be empty.  Standby is allowed again.
1106  *
1107  *  @param(handle)         The UART_Handle for ongoing write.
1108  */
writeFinishedDoCallback(UART_Handle handle)1109 static void writeFinishedDoCallback(UART_Handle handle)
1110 {
1111     UARTCC32XXDMA_Object           *object;
1112     UARTCC32XXDMA_HWAttrsV1 const  *hwAttrs;
1113 
1114     /* Get the pointer to the object and hwAttrs */
1115     object = handle->object;
1116     hwAttrs = handle->hwAttrs;
1117 
1118     /* Stop the txFifoEmpty clock */
1119     ClockP_stop((ClockP_Handle)object->txFifoEmptyClk);
1120 
1121     /*   1. Function verifies that the FIFO is empty via BUSY flag */
1122     /*   2. Polls this flag if not yet ready (should not be necessary) */
1123     while (MAP_UARTBusy(hwAttrs->baseAddr));
1124 
1125     /* Release constraint since transaction is done */
1126     Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
1127 
1128     /* Make callback */
1129     object->writeCallback(handle, (uint8_t *)object->writeBuf,
1130                           object->writeCount);
1131     DebugP_log2("UART:(%p) Write finished, %d bytes written",
1132                 hwAttrs->baseAddr, object->writeCount);
1133 }
1134