1 /*
2  * Copyright (c) 2019-2020, 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 #include <string.h>
35 #include <stdlib.h>
36 #include <stdbool.h>
37 
38 #ifndef DebugP_ASSERT_ENABLED
39 #define DebugP_ASSERT_ENABLED 0
40 #endif
41 #ifndef DebugP_LOG_ENABLED
42 #define DebugP_LOG_ENABLED 0
43 #endif
44 
45 #include <ti/drivers/dpl/DebugP.h>
46 #include <ti/drivers/dpl/HwiP.h>
47 
48 #include <ti/drivers/i2s/I2SCC32XX.h>
49 #include <ti/drivers/Power.h>
50 #include <ti/drivers/power/PowerCC32XX.h>
51 #include <ti/drivers/dma/UDMACC32XX.h>
52 #include <ti/drivers/utils/List.h>
53 
54 #include <ti/devices/cc32xx/inc/hw_memmap.h>
55 #include <ti/devices/cc32xx/inc/hw_ocp_shared.h>
56 #include <ti/devices/cc32xx/inc/hw_ints.h>
57 #include <ti/devices/cc32xx/inc/hw_mcasp.h>
58 #include <ti/devices/cc32xx/inc/hw_apps_config.h>
59 #include <ti/devices/cc32xx/inc/hw_types.h>
60 #include <ti/devices/cc32xx/driverlib/rom.h>
61 #include <ti/devices/cc32xx/driverlib/rom_map.h>
62 #include <ti/devices/cc32xx/driverlib/interrupt.h>
63 #include <ti/devices/cc32xx/driverlib/i2s.h>
64 #include <ti/devices/cc32xx/driverlib/prcm.h>
65 #include <ti/devices/cc32xx/driverlib/udma.h>
66 
67 #define PinConfigPinMode(config)       (((config) >> 8) & 0xF)
68 #define PinConfigPin(config)           (((config) >> 0) & 0x3F)
69 #define PAD_CONFIG_BASE (OCP_SHARED_BASE + OCP_SHARED_O_GPIO_PAD_CONFIG_0)
70 #define PAD_RESET_STATE 0xC61
71 #define I2S_NB_CHANNELS_MAX                       8U
72 #define BYTE_LENGTH                               8U /* Length in bits of a byte*/
73 #define UDMA_MAX_TRANSFERLENGTH                   1023 /* This is the maximum transfer length for uDMA in MODE BASIC. Transfers lengths must be inferior or equal to this value. */
74 #define HWRESOLUTION                              4U /* All the settings are expressed in half-bytes (4 bits) */
75 #define PRCMI2SCLOCKFREQMIN                       234377 /* Minimum Frequency (in Hz) possible with only one divider */
76 #define HCLKDIVMAX                                0xFFF  /* Max division of ulHClkDiv (ulHClkDiv is a 12-bit clock divider) */
77 
78 #define DATA_SHIFT_NONE                           0x00 /* Value to use for RXFMT.RDATDLY and TXFMT.XDATDLY if no data shift is expected */
79 #define DATA_SHIFT_1                              0x01 /* Value to use for RXFMT.RDATDLY and TXFMT.XDATDLY if data are expected to shift by one - Value to use for true I2S format */
80 #define DATA_SHIFT_2                              0x02 /* Value to use for RXFMT.RDATDLY and TXFMT.XDATDLY if data are expected to shift by two */
81 
82 #define MCASP_RXFMCTL_FRWID_DEFAULT               0x10 /* This value is the default value to use for RXFMCTL.FRWID */
83 #define MCASP_TXFMCTL_FXWID_DEFAULT               0x10 /* This value is the default value to use for TXFMCTL.FXWID */
84 #define MCASP_RXFMCTL_RMOD_DEFAULT                0x100 /* This value is the default value to use for RXFMCTL.RMOD */
85 #define MCASP_TXFMCTL_XMOD_DEFAULT                0x100 /* This value is the default value to use for TXFMCTL.XMOD */
86 #define MCASP_AHCLKRCTL_HCLKRM_DEFAULT            0x8000 /* This value is the default value to use for AHCLKRCTL.HCLKRM */
87 #define MCASP_AHCLKXCTL_HCLKXM_DEFAULT            0x8000 /* This value is the default value to use for AHCLKXCTL.HCLKXM */
88 
89 /*
90  * This lookup table is used to configure the DMA channels for the appropriate
91  * (8bit, 16bit or 32bit) transfer sizes.
92  * Table for an I2S DMA RX channel.
93  */
94 static const uint32_t dmaRxConfig[] = {
95     UDMA_SIZE_8  | UDMA_SRC_INC_NONE | UDMA_DST_INC_8,
96     UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16,
97     UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_32,
98 };
99 
100 /*
101  * This lookup table is used to configure the DMA channels for the appropriate
102  * (8bit, 16bit or 32bit) transfer sizes.
103  * Table for an I2S DMA TX channel.
104  */
105 static const uint32_t dmaTxConfig[] = {
106     UDMA_SIZE_8  | UDMA_SRC_INC_8  | UDMA_DST_INC_NONE,
107     UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE,
108     UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_NONE,
109 };
110 
111 /*
112  * This lookup table is used to configure the DMA channels for the appropriate
113  * (8bit, 16bit or 32bit) transfer sizes.
114  * Table works for an both RX and TX I2S DMA channels.
115  */
116 #define UDMA_ARBLENGTH_DEFAULT 4
117 static const uint32_t dmaArbConfig [] = {
118     UDMA_ARB_1,
119     UDMA_ARB_2,
120     UDMA_ARB_4,
121     UDMA_ARB_8,
122     UDMA_ARB_16,
123     UDMA_ARB_32,
124     UDMA_ARB_64,
125     UDMA_ARB_128,
126 };
127 
128 /* Forward declarations */
129 static bool initObject(I2S_Handle handle, I2S_Params *params);
130 static void initIO(I2S_Handle handle);
131 static void initDMA(I2S_Handle handle);
132 static void initHw(I2S_Handle handle);
133 static int postNotify(unsigned int eventType, uintptr_t eventArg, uintptr_t clientArg);
134 
135 static void resetPin(unsigned long pinI2S);
136 static void openPin(unsigned long pinI2S);
137 static void restorePinpads(I2SCC32XX_HWAttrs const *hwAttrs);
138 
139 static void configSCK(I2S_Handle handle);
140 static void configWS(I2S_Handle handle);
141 static void configSerialFormat(I2S_Handle handle);
142 static uint8_t getNumberOfChannels(const uint8_t channelsList);
143 
144 static void I2S_hwiIntFxn(uintptr_t arg);
145 static void updateDataReadDMA(uintptr_t arg);
146 static void updateDataWriteDMA(uintptr_t arg);
147 static void updateDataReadCPU(uintptr_t arg);
148 static void updateDataWriteCPU(uintptr_t arg);
149 static void handleDMATransaction(I2S_Handle handle, I2S_Transaction *transaction, uint32_t transLength, I2SCC32XX_Interface *interface);
150 static void handleCPUTransaction(I2S_Handle handle, I2S_Transaction **ptrTransaction, I2SCC32XX_Interface *interface);
151 
152 /* Extern globals */
153 extern const I2S_Config I2S_config[];
154 extern const uint_least8_t I2S_count;
155 
156 /* Static globals */
157 static bool isInitialized = (bool)false;
158 
159 /*
160  *  ======== I2S_init ========
161  */
I2S_init(void)162 void I2S_init(void) {
163     uint_least8_t i;
164 
165     if (!isInitialized) {
166         /* Init each instances' driver */
167         for (i = 0; i < I2S_count; i++) {
168             I2S_Handle handle = (I2S_Handle)&(I2S_config[i]);
169             I2SCC32XX_Object *object = (I2SCC32XX_Object *)handle->object;
170             object->isOpen = (bool)false;
171         }
172         /* Init as well UDMA */
173         UDMACC32XX_init();
174         isInitialized = (bool)true;
175     }
176 }
177 
178 /*
179  *  ======== I2S_open ========
180  */
I2S_open(uint_least8_t index,I2S_Params * params)181 I2S_Handle I2S_open(uint_least8_t index, I2S_Params *params) {
182     I2S_Handle        handle;
183     I2SCC32XX_Object *object;
184     I2SCC32XX_HWAttrs const *hwAttrs;
185 
186     handle = (I2S_Handle)&(I2S_config[index]);
187     object = handle->object;
188 
189     /* Get the pointer to the object and hwAttrs */
190     hwAttrs = handle->hwAttrs;
191 
192     DebugP_assert(index < I2S_count);
193 
194     /* Check if module is initialized. */
195     if (!isInitialized ||  object->isOpen) {
196         handle =  NULL;
197     }
198     /* Initialization of the I2S-object and verification of the parameters. */
199     else if (!initObject(handle, params)) {
200         /* The parameters provided are not correct. */
201         handle = NULL;
202     }
203     /* Set Power, set HW and register interrupts */
204     else {
205         /* Register HW interrupt */
206         HwiP_Params hwiParams;
207         HwiP_clearInterrupt(INT_I2S);
208         HwiP_Params_init(&hwiParams);
209         hwiParams.arg = (uintptr_t)handle;
210         hwiParams.priority = hwAttrs->intPriority;
211         object->hwi = HwiP_create(INT_I2S, (HwiP_Fxn)I2S_hwiIntFxn, &hwiParams);
212 
213         if (object->hwi == NULL) {
214             /* HwiP creation failed */
215             handle = NULL;
216             restorePinpads(hwAttrs);
217         }
218         else {
219             object->isOpen = (bool)true;
220 
221             /* Set Power */
222             Power_setDependency(PowerCC32XX_PERIPH_I2S);
223             MAP_PRCMPeripheralReset(PRCM_I2S);
224 
225             /* Set DMA */
226             initDMA(handle);
227 
228             /* Set HardWare */
229             initHw(handle);
230 
231             Power_registerNotify(&(object->notifyObj), PowerCC32XX_AWAKE_LPDS, postNotify, (uint32_t)handle);
232 
233             MAP_I2SIntDisable(I2S_BASE, 0xFFFFFFFF);
234 
235             uintptr_t key = HwiP_disable();
236             /* Keep activatedFlags to be modified from somewhere else */
237             object->activatedFlag = 0;
238             HwiP_restore(key);
239         }
240     }
241 
242     return handle;
243 }
244 
245 /*
246  *  ======== I2S_close ========
247  */
I2S_close(I2S_Handle handle)248 void I2S_close(I2S_Handle handle)
249 {
250     /* Get the pointer to the object and hwAttrs */
251     I2SCC32XX_Object *object = handle->object;
252     I2SCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
253 
254     /* Disable interrupts. */
255     MAP_I2SIntDisable(I2S_BASE, 0xFFFFFFFF);
256 
257     uintptr_t key = HwiP_disable();
258     /* Keep activatedFlags to be modified from somewhere else */
259     object->activatedFlag = 0;
260     HwiP_restore(key);
261 
262     /* Close the uDMA */
263     if(object->dmaHandle != NULL) {
264         UDMACC32XX_close(object->dmaHandle);
265         object->dmaHandle = NULL;
266     }
267 
268     /* Delete the I2S HWI */
269     if(object->hwi != NULL) {
270         HwiP_delete(object->hwi);
271         object->hwi = NULL;
272     }
273 
274     Power_unregisterNotify(&(object->notifyObj));
275     /* Release power dependency - i.e. potentially power down serial domain. */
276     Power_releaseDependency(PowerCC32XX_PERIPH_I2S);
277 
278     /* Restore pin pads to their reset states */
279     restorePinpads(hwAttrs);
280 
281     /* Mark the module as available */
282     object->isOpen = (bool)false;
283 }
284 
285 /*
286  *  ======== I2S_setReadQueueHead ========
287  */
I2S_setReadQueueHead(I2S_Handle handle,I2S_Transaction * transaction)288 void I2S_setReadQueueHead(I2S_Handle handle, I2S_Transaction *transaction){
289 
290     DebugP_assert(transaction != 0x0);
291 
292     I2SCC32XX_Object    *object = handle->object;
293     I2SCC32XX_Interface *interface = &object->read;
294 
295     interface->activeTransfer = transaction;
296 }
297 
298 /*
299  *  ======== I2S_setWriteQueueHead ========
300  */
I2S_setWriteQueueHead(I2S_Handle handle,I2S_Transaction * transaction)301 void I2S_setWriteQueueHead(I2S_Handle handle, I2S_Transaction *transaction){
302 
303     DebugP_assert(transaction != 0x0);
304 
305     I2SCC32XX_Object    *object = handle->object;
306     I2SCC32XX_Interface *interface = &object->write;
307 
308     interface->activeTransfer = transaction;
309 }
310 
311 /*
312  *  ======== I2S_startClocks ========
313  */
I2S_startClocks(I2S_Handle handle)314 void I2S_startClocks(I2S_Handle handle) {
315 
316     I2SCC32XX_Object *object = handle->object;
317 
318     Power_setConstraint(PowerCC32XX_DISALLOW_LPDS);
319 
320     uint8_t mode = ((object->noOfInputs  != 0)? 1:0) << 1 |
321                    ((object->noOfOutputs != 0)? 1:0) << 0;
322 
323     MAP_I2SIntEnable(I2S_BASE,   I2S_INT_RSYNCERR | I2S_INT_XSYNCERR);
324 
325     uintptr_t key = HwiP_disable();
326     /* Keep activatedFlags to be modified from somewhere else */
327     object->activatedFlag |= I2S_STS_RSYNCERR | I2S_STS_XSYNCERR;
328     HwiP_restore(key);
329 
330     MAP_I2SEnable(I2S_BASE, (unsigned long)mode);
331 }
332 
333 /*
334  *  ======== I2S_stopClocks ========
335  */
I2S_stopClocks(I2S_Handle handle)336 void I2S_stopClocks(I2S_Handle handle) {
337 
338     I2SCC32XX_Object *object = handle->object;
339 
340     /* Wait for the transfers to be properly terminated */
341     while(object->isLastReadTransfer || object->isLastWriteTransfer);
342 
343     MAP_I2SIntDisable(I2S_BASE,    I2S_INT_RSYNCERR | I2S_INT_XSYNCERR);
344 
345     uintptr_t key = HwiP_disable();
346     /* Keep activatedFlags to be modified from somewhere else */
347     object->activatedFlag &= ~(I2S_STS_RSYNCERR | I2S_STS_XSYNCERR);
348     HwiP_restore(key);
349 
350     MAP_I2SDisable(I2S_BASE);
351     Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
352 }
353 
354 /*
355  *  ======== I2S_startRead ========
356  */
I2S_startRead(I2S_Handle handle)357 void I2S_startRead(I2S_Handle handle) {
358 
359     I2SCC32XX_Object *object = handle->object;
360     I2SCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
361     I2SCC32XX_DataInterface   *SD0;
362     I2SCC32XX_DataInterface   *SD1;
363 
364     /* Get the pointer to the SD0 and SD1 interfaces */
365     SD0 = &object->dataInterfaceSD0;
366     SD1 = &object->dataInterfaceSD1;
367 
368     if(object->noOfInputs != 0) {
369 
370         uintptr_t key = HwiP_disable();
371         if(object->isDMAUnused) {
372             /* Enable I2S_INT_RDATA | I2S_INT_ROVRN */
373             HWREG(I2S_BASE + MCASP_O_EVTCTLR) |= (((I2S_INT_RDATA | I2S_INT_ROVRN) >> 16) & 0xFF);
374             object->activatedFlag |= I2S_STS_ROVERN | I2S_STS_RDATA;
375             object->updateDataReadFxn((uintptr_t)handle);
376         }
377         else {
378             /* Turn on the DMA channel of the I2S Read interface */
379             MAP_uDMAChannelAttributeEnable(hwAttrs->rxChannelIndex,UDMA_ATTR_USEBURST);
380             MAP_uDMAChannelAssign(hwAttrs->rxChannelIndex);
381             object->updateDataReadFxn((uintptr_t)handle);
382             MAP_I2SRxFIFOEnable(I2S_BASE, object->udmaArbLength, object->noOfInputs);
383 
384             /* Enable I2S_INT_RDMA | I2S_INT_ROVRN | I2S_INT_RLAST */
385             /* Note: we do not activate the I2S_STS_RDMAERR flag (uDMA's responsibility) */
386             HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR ) |= (((I2S_INT_RDMA | I2S_INT_ROVRN | I2S_INT_RLAST) &0xC0000000) >> 20);
387             HWREG(I2S_BASE + MCASP_O_EVTCTLR) |= (((I2S_INT_RDMA | I2S_INT_ROVRN | I2S_INT_RLAST) >> 16) & 0xFF);
388             object->activatedFlag |= I2S_STS_RLAST | I2S_STS_ROVERN | I2S_STS_RDMA;
389         }
390         HwiP_restore(key);
391 
392         if(SD0->interfaceConfig == I2S_SD0_INPUT) {
393             MAP_I2SSerializerConfig(I2S_BASE, SD0->dataLine, I2S_SER_MODE_RX, I2S_INACT_LOW_LEVEL);
394         }
395         if(SD1->interfaceConfig == I2S_SD1_INPUT) {
396             MAP_I2SSerializerConfig(I2S_BASE, SD1->dataLine, I2S_SER_MODE_RX, I2S_INACT_LOW_LEVEL);
397         }
398     }
399 }
400 
401 /*
402  *  ======== I2S_startWrite ========
403  */
I2S_startWrite(I2S_Handle handle)404 void I2S_startWrite(I2S_Handle handle) {
405 
406     I2SCC32XX_Object *object = handle->object;
407     I2SCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
408     I2SCC32XX_DataInterface *SD0;
409     I2SCC32XX_DataInterface *SD1;
410 
411     /* Get the pointer to the SD0 and SD1 interfaces */
412     SD0 = &object->dataInterfaceSD0;
413     SD1 = &object->dataInterfaceSD1;
414 
415     if(object->noOfOutputs != 0) {
416 
417         uintptr_t key = HwiP_disable();
418         if(object->isDMAUnused) {
419             /* Enable I2S_INT_XDATA | I2S_INT_XUNDRN */
420             HWREG(I2S_BASE + MCASP_O_EVTCTLX) |= ((I2S_INT_XDATA | I2S_INT_XUNDRN) & 0xFF);
421             object->activatedFlag |= I2S_STS_XDATA | I2S_STS_XUNDRN;
422             object->updateDataWriteFxn((uintptr_t)handle);
423         }
424         else {
425             /* Turn on the DMA channel of the I2S Write interface */
426             MAP_uDMAChannelAttributeEnable(hwAttrs->txChannelIndex,UDMA_ATTR_USEBURST);
427             MAP_uDMAChannelAssign(hwAttrs->txChannelIndex);
428             object->updateDataWriteFxn((uintptr_t)handle);
429             MAP_I2STxFIFOEnable(I2S_BASE, object->udmaArbLength, object->noOfOutputs);
430 
431             /* Enable I2S_INT_XDMA | I2S_INT_XLAST | I2S_INT_XUNDRN */
432             /* Note: we do not activate the I2S_STS_XDMAERR flag (uDMA's responsibility) */
433             HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR ) |= (((I2S_INT_XDMA | I2S_INT_XLAST | I2S_INT_XUNDRN) &0xC0000000) >> 20);
434             HWREG(I2S_BASE + MCASP_O_EVTCTLX) |= ((I2S_INT_XDMA | I2S_INT_XLAST | I2S_INT_XUNDRN) & 0xFF);
435             object->activatedFlag |= I2S_STS_XLAST | I2S_STS_XUNDRN | I2S_STS_XDMA;
436         }
437         HwiP_restore(key);
438 
439         if(SD0->interfaceConfig == I2S_SD0_OUTPUT) {
440             MAP_I2SSerializerConfig(I2S_BASE, SD0->dataLine, I2S_SER_MODE_TX, I2S_INACT_LOW_LEVEL);
441         }
442         if(SD1->interfaceConfig == I2S_SD1_OUTPUT) {
443             MAP_I2SSerializerConfig(I2S_BASE, SD1->dataLine, I2S_SER_MODE_TX, I2S_INACT_LOW_LEVEL);
444         }
445     }
446 }
447 
448 /*
449  *  ======== I2S_stopRead ========
450  */
I2S_stopRead(I2S_Handle handle)451 void I2S_stopRead(I2S_Handle handle) {
452 
453     I2SCC32XX_Object *object = handle->object;
454     I2SCC32XX_DataInterface *SD0;
455     I2SCC32XX_DataInterface *SD1;
456 
457     /* Get the pointer to the SD0 and SD1 interfaces*/
458     SD0 = &object->dataInterfaceSD0;
459     SD1 = &object->dataInterfaceSD1;
460 
461     if(object->noOfInputs != 0) {
462 
463         if(!object->isDMAUnused) {
464             /* To stop the Read interface, we must wait for the end of the current DMA transaction*/
465             object->isLastReadTransfer = (bool)true;
466         }
467         else {
468 
469             MAP_I2SIntDisable(I2S_BASE, I2S_INT_RDMA | I2S_INT_ROVRN );
470 
471             uintptr_t key = HwiP_disable();
472             /* Keep activatedFlag to be modified from somewhere else */
473             object->activatedFlag &= ~(I2S_STS_RDMA  | I2S_STS_ROVERN);
474             HwiP_restore(key);
475 
476             if(SD0->interfaceConfig == I2S_SD0_INPUT) {
477                 MAP_I2SSerializerConfig(I2S_BASE, SD0->dataLine, I2S_SER_MODE_DISABLE, I2S_INACT_LOW_LEVEL);
478             }
479             if(SD1->interfaceConfig == I2S_SD1_INPUT) {
480                 MAP_I2SSerializerConfig(I2S_BASE, SD1->dataLine, I2S_SER_MODE_DISABLE, I2S_INACT_LOW_LEVEL);
481             }
482         }
483     }
484 }
485 
486 /*
487  *  ======== I2S_stopWrite ========
488  */
I2S_stopWrite(I2S_Handle handle)489 void I2S_stopWrite(I2S_Handle handle) {
490 
491     I2SCC32XX_Object *object = handle->object;
492     I2SCC32XX_DataInterface *SD0;
493     I2SCC32XX_DataInterface *SD1;
494 
495     /* Get the pointer to the SD0 and SD1 interfaces*/
496     SD0 = &object->dataInterfaceSD0;
497     SD1 = &object->dataInterfaceSD1;
498 
499     if(object->noOfOutputs != 0) {
500 
501         if(!object->isDMAUnused) {
502             /* To stop the Write interface, we must wait for the end of the current DMA transaction*/
503             object->isLastWriteTransfer = (bool)true;
504         }
505         else {
506 
507             MAP_I2SIntDisable(I2S_BASE, I2S_INT_XDMA | I2S_INT_XUNDRN);
508 
509             uintptr_t key = HwiP_disable();
510             /* Keep activatedFlag to be modified from somewhere else */
511             object->activatedFlag &= ~(I2S_STS_XDMA | I2S_STS_XUNDRN);
512             HwiP_restore(key);
513 
514             if(SD0->interfaceConfig == I2S_SD0_OUTPUT) {
515                 MAP_I2SSerializerConfig(I2S_BASE, SD0->dataLine, I2S_SER_MODE_DISABLE, I2S_INACT_LOW_LEVEL);
516             }
517             if(SD1->interfaceConfig == I2S_SD1_OUTPUT) {
518                 MAP_I2SSerializerConfig(I2S_BASE, SD1->dataLine, I2S_SER_MODE_DISABLE, I2S_INACT_LOW_LEVEL);
519             }
520         }
521     }
522 }
523 
524 /*
525 *  ======== initHw ========
526 *  This functions initializes the I2S hardware module.
527 *
528 *  @pre    Function assumes that the I2S handle is pointing to a hardware
529 *          module which has already been opened.
530 */
initHw(I2S_Handle handle)531 static void initHw(I2S_Handle handle) {
532 
533     /* Configure IOs */
534     initIO(handle);
535     /* Configure SCK clock (including sampling edge) */
536     configSCK(handle);
537     /* Configure WS clock (including WS inversion) */
538     configWS(handle);
539     /* Configure serial format (data-length, DMA use, MSB/LSB first, data padding, channels activated) */
540     configSerialFormat(handle);
541 }
542 
543 /*
544  *  ======== I2S_hwiIntFxn ========
545  *  Hwi function that processes I2S interrupts.
546  */
I2S_hwiIntFxn(uintptr_t arg)547 static void I2S_hwiIntFxn(uintptr_t arg) {
548 
549     I2S_Handle handle = (I2S_Handle)arg;
550     I2SCC32XX_Object const *object = handle->object;
551     uint16_t errStatus = 0U;
552 
553     /* Read and clear all the interrupt flags */
554     /* Note: in CPU mode, RDATA and XDATA flags must be cleared AFTER data update */
555     uint32_t rawInterruptStatus = (uint32_t)MAP_I2SIntStatus(I2S_BASE);
556     if(object->isDMAUnused) {
557         MAP_I2SIntClear(I2S_BASE,  rawInterruptStatus & ~I2S_STS_RDATA & ~I2S_STS_XDATA);
558     }
559     else {
560         MAP_I2SIntClear(I2S_BASE, rawInterruptStatus);
561     }
562 
563     /* Filter the interrupt-status to only consider the activated flags */
564     uint32_t interruptStatus = (rawInterruptStatus & object->activatedFlag);
565 
566 
567     /* Normal work */
568     if((interruptStatus & (uint32_t)(I2S_STS_RLAST | I2S_STS_RDATA | I2S_STS_RDMA)) != 0U)
569     {
570         object->updateDataReadFxn(arg);
571     }
572 
573     if((interruptStatus & (uint32_t)(I2S_STS_XLAST | I2S_STS_XDATA | I2S_STS_XDMA)) != 0U)
574     {
575         object->updateDataWriteFxn(arg);
576     }
577 
578     /* Read errors */
579     if((interruptStatus & (uint32_t)I2S_STS_ROVERN  ) != 0U)
580     {
581         errStatus |= I2S_PTR_READ_ERROR;
582     }
583 
584     if((interruptStatus & (uint32_t)I2S_STS_RSYNCERR) != 0U)
585     {
586         errStatus |= I2S_TIMEOUT_ERROR;
587     }
588 
589     if((interruptStatus & (uint32_t)I2S_STS_RDMAERR ) != 0U)
590     {
591         errStatus |= I2S_BUS_ERROR;
592     }
593 
594     /* Write errors */
595     if((interruptStatus & (uint32_t)I2S_STS_XUNDRN  ) != 0U)
596     {
597         errStatus |= I2S_PTR_WRITE_ERROR;
598     }
599 
600     if((interruptStatus & (uint32_t)I2S_STS_XSYNCERR) != 0U)
601     {
602         errStatus |= I2S_WS_ERROR;
603     }
604 
605     if((interruptStatus & (uint32_t)I2S_STS_XDMAERR ) != 0U)
606     {
607         errStatus |= I2S_BUS_ERROR;
608     }
609 
610     /* Triggering of the error-Callback (only one call, with potentially several status bits activated) */
611     if(errStatus != 0U) {
612         object->errorCallback(handle, errStatus, NULL);
613     }
614 }
615 
616 /*
617  *  ======== updateDataReadDMA ========
618  */
updateDataReadDMA(uintptr_t arg)619 static void updateDataReadDMA(uintptr_t arg) {
620     I2S_Handle handle = (I2S_Handle)arg;
621     I2SCC32XX_Object *object = handle->object;
622     I2SCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
623 
624     /* Wait for the mode to be changed to "stopped" */
625     if(MAP_uDMAChannelModeGet(hwAttrs->rxChannelIndex) == UDMA_MODE_STOP){
626 
627         if(!object->isLastReadTransfer) {
628 
629             I2S_Transaction *transaction = (I2S_Transaction *)object->read.activeTransfer;
630             if(transaction != NULL) {
631 
632                 uint32_t transLength = transaction->bufSize - transaction->bytesTransferred;                   /* transfer length expressed in bytes */
633                 transLength = transLength / (object->memorySlotLength / BYTE_LENGTH);                          /* expressed in number of samples (number of atomic DMA transfers) */
634                 transLength = (transLength > UDMA_MAX_TRANSFERLENGTH)? UDMA_MAX_TRANSFERLENGTH : transLength;  /* the transfer length of the uDMA is limited */
635                 transLength = transLength - (transLength % object->udmaArbLength);                             /* taking in consideration the limitation of the DMA (DMA copies each time UDMA_ARB_x samples) */
636 
637                 MAP_uDMAChannelControlSet(hwAttrs->rxChannelIndex,
638                                       object->read.udmaConfig);
639                 MAP_uDMAChannelTransferSet(hwAttrs->rxChannelIndex,
640                                        UDMA_MODE_BASIC,
641                                        (void *)I2S_RX_DMA_PORT,
642                                        (void *)((uint32_t)transaction->bufPtr + transaction->bytesTransferred),
643                                        transLength);
644 
645                 MAP_uDMAChannelEnable(hwAttrs->rxChannelIndex);
646 
647                 transLength = transLength * (object->memorySlotLength / BYTE_LENGTH);                         /* handleDMATransaction() expects transLength in bytes (not in samples): re-convert transLength in bytes */
648                 handleDMATransaction(handle, transaction, transLength, &object->read);
649             }
650         }
651         else {
652             I2SCC32XX_DataInterface *SD0;
653             I2SCC32XX_DataInterface *SD1;
654 
655             /* Get the pointer to the SD0 and SD1 interfaces*/
656             SD0 = &object->dataInterfaceSD0;
657             SD1 = &object->dataInterfaceSD1;
658 
659             MAP_I2SIntDisable(I2S_BASE, I2S_INT_RLAST | I2S_INT_RDMA | I2S_INT_ROVRN);
660             object->activatedFlag &=  ~(I2S_STS_RLAST | I2S_STS_RDMA | I2S_STS_ROVERN);
661 
662             MAP_I2SRxFIFODisable(I2S_BASE);
663 
664             if(SD0->interfaceConfig == I2S_SD0_INPUT) {
665                 MAP_I2SSerializerConfig(I2S_BASE, SD0->dataLine, I2S_SER_MODE_DISABLE, I2S_INACT_LOW_LEVEL);
666             }
667             if(SD1->interfaceConfig == I2S_SD1_INPUT) {
668                 MAP_I2SSerializerConfig(I2S_BASE, SD1->dataLine, I2S_SER_MODE_DISABLE, I2S_INACT_LOW_LEVEL);
669             }
670 
671             object->isLastReadTransfer = (bool)false;
672         }
673     }
674 }
675 
676 /*
677  *  ======== updateDataWriteDMA ========
678  */
updateDataWriteDMA(uintptr_t arg)679 static void updateDataWriteDMA(uintptr_t arg) {
680     I2S_Handle handle = (I2S_Handle)arg;
681     I2SCC32XX_Object *object = handle->object;
682     I2SCC32XX_HWAttrs const *hwAttrs = handle->hwAttrs;
683     I2SCC32XX_DataInterface *SD0;
684     I2SCC32XX_DataInterface *SD1;
685 
686     /* Wait for the mode to be changed to "stopped" */
687     if(MAP_uDMAChannelModeGet(hwAttrs->txChannelIndex) == UDMA_MODE_STOP){
688 
689         if(!object->isLastWriteTransfer) {
690             I2S_Transaction *transaction = (I2S_Transaction *)object->write.activeTransfer;
691             if(transaction != NULL) {
692 
693                 uint32_t transLength = transaction->bufSize - transaction->bytesTransferred;                   /* transfer length expressed in bits */
694                 transLength = transLength / (object->memorySlotLength / BYTE_LENGTH);                          /* expressed in number of samples (number of atomic DMA transfers) */
695                 transLength = (transLength > UDMA_MAX_TRANSFERLENGTH)? UDMA_MAX_TRANSFERLENGTH : transLength;  /* the transfer length of the uDMA is limited */
696                 transLength = transLength - (transLength % object->udmaArbLength);                             /* taking in consideration the limitation of the DMA (DMA copies each time UDMA_ARB_x samples) */
697 
698                 MAP_uDMAChannelControlSet(hwAttrs->txChannelIndex,
699                                       object->write.udmaConfig);
700                 MAP_uDMAChannelTransferSet(hwAttrs->txChannelIndex,
701                                        UDMA_MODE_BASIC,
702                                        (void *)((uint32_t)transaction->bufPtr + transaction->bytesTransferred),
703                                        (void *)I2S_TX_DMA_PORT,
704                                        transLength);
705 
706                 MAP_uDMAChannelEnable(hwAttrs->txChannelIndex);
707 
708                 transLength = transLength * (object->memorySlotLength / BYTE_LENGTH);                         /* handleDMATransaction() expects transLength in bytes (not in samples): re-convert transLength in bytes */
709                 handleDMATransaction(handle, transaction, transLength, &object->write);
710             }
711         }
712 
713         else {
714 
715             /* Get the pointer to the SD0 and SD1 interfaces*/
716             SD0 = &object->dataInterfaceSD0;
717             SD1 = &object->dataInterfaceSD1;
718 
719             MAP_I2SIntDisable(I2S_BASE, I2S_INT_XDMA | I2S_INT_XUNDRN | I2S_INT_XLAST);
720             object->activatedFlag &=  ~(I2S_STS_XDMA | I2S_STS_XUNDRN | I2S_STS_XLAST);
721 
722             MAP_I2STxFIFODisable(I2S_BASE);
723 
724             if(SD0->interfaceConfig == I2S_SD0_OUTPUT) {
725                 MAP_I2SSerializerConfig(I2S_BASE, SD0->dataLine, I2S_SER_MODE_DISABLE, I2S_INACT_LOW_LEVEL);
726             }
727             if(SD1->interfaceConfig == I2S_SD1_OUTPUT) {
728                 MAP_I2SSerializerConfig(I2S_BASE, SD1->dataLine, I2S_SER_MODE_DISABLE, I2S_INACT_LOW_LEVEL);
729             }
730 
731             object->isLastWriteTransfer = (bool)false;
732         }
733     }
734 }
735 
736 /*
737  *  ======== handleDMATransaction ========
738  *  This function avoid to duplicate the code dedicated to take care of the transactions in DMA mode.
739  *  This function remove the transaction from the list and trigger the user callback.
740  *
741  */
handleDMATransaction(I2S_Handle handle,I2S_Transaction * transactionFinished,uint32_t transLength,I2SCC32XX_Interface * interface)742 static void handleDMATransaction(I2S_Handle      handle,
743                                  I2S_Transaction *transactionFinished,
744                                  uint32_t        transLength,
745                                  I2SCC32XX_Interface   *interface){
746 
747     I2SCC32XX_Object *object = handle->object;
748 
749     /* Is the transaction finished? (i.e. all the element are sent or we cannot perform the next DMA) */
750     uint16_t dmaMinimumStep = object->udmaArbLength * object->memorySlotLength / BYTE_LENGTH;
751     if(((transactionFinished->bytesTransferred + transLength + dmaMinimumStep) > transactionFinished->bufSize)) {
752 
753         /* This transaction is finished */
754         interface->activeTransfer = (I2S_Transaction*)List_next(&transactionFinished->queueElement);
755 
756         transactionFinished->untransferredBytes = transactionFinished->bufSize - transLength;
757         transactionFinished->numberOfCompletions ++;
758         transactionFinished->bytesTransferred = 0;
759 
760         if(interface->activeTransfer == NULL) {
761             interface->callback(handle, I2S_ALL_TRANSACTIONS_SUCCESS, transactionFinished);
762 
763             /* If needed the interface must be stopped */
764             if(interface->activeTransfer != NULL){
765                 /* Application called I2S_setXxxxQueueHead()
766                  *     -> new transfers can be executed next time */
767             }
768             else if((I2S_Transaction*)List_next(&transactionFinished->queueElement) != NULL){
769                 /* Application queued transactions after the transaction finished
770                  *     -> activeTransfer must be modified and transfers can be executed next time */
771                 interface->activeTransfer = (I2S_Transaction*)List_next(&transactionFinished->queueElement);
772             }
773             else {
774                 /* Application did nothing, we need to stop the interface to avoid errors */
775                 interface->stopInterface(handle);
776             }
777         }
778         else {
779             interface->callback(handle, I2S_TRANSACTION_SUCCESS, transactionFinished);
780         }
781     }
782     else{
783         transactionFinished->bytesTransferred += transLength;
784     }
785 }
786 
787 /*
788  *  ======== updateDataReadCPU ========
789  */
updateDataReadCPU(uintptr_t arg)790 static void updateDataReadCPU(uintptr_t arg) {
791     I2S_Handle handle = (I2S_Handle)arg;
792     I2SCC32XX_Object *object = handle->object;
793     I2SCC32XX_DataInterface   *SD0;
794     I2SCC32XX_DataInterface   *SD1;
795 
796     /* Get the pointer to the SD0 and SD1 interfaces*/
797     SD0 = &object->dataInterfaceSD0;
798     SD1 = &object->dataInterfaceSD1;
799 
800     I2S_Transaction *transaction = (I2S_Transaction *)object->read.activeTransfer;
801     if(transaction != NULL) {
802 
803         bool dataKO = (bool)false;
804         uint32_t *ptrValue;
805         ptrValue = (uint32_t*)((uint32_t)transaction->bufPtr + (uint32_t)transaction->bytesTransferred);
806 
807         while((!dataKO) && (transaction != NULL)) {
808 
809             if((SD0->interfaceConfig == I2S_SD0_INPUT) && (transaction != NULL) && (!dataKO)) {
810 
811                 dataKO |= MAP_I2SDataGetNonBlocking(I2S_BASE, SD0->dataLine, (unsigned long*)ptrValue);
812 
813                 if(!dataKO) {
814 
815                     handleCPUTransaction(handle, &transaction, &object->read);
816 
817                     if(transaction != NULL){
818                         ptrValue = (uint32_t*)((uint32_t)transaction->bufPtr + (uint32_t)transaction->bytesTransferred);
819                     }
820                 }
821             }
822 
823             if((SD1->interfaceConfig == I2S_SD1_INPUT) && (transaction != NULL) && (!dataKO)) {
824 
825                 dataKO |= MAP_I2SDataGetNonBlocking(I2S_BASE, SD1->dataLine, (unsigned long*)ptrValue);
826 
827                 if(!dataKO) {
828 
829                     handleCPUTransaction(handle, &transaction, &object->read);
830 
831                     if(transaction != NULL){
832                         ptrValue = (uint32_t*)((uint32_t)transaction->bufPtr + (uint32_t)transaction->bytesTransferred);
833                     }
834                 }
835             }
836         }
837     }
838 
839     /* In CPU mode interrupt clearing must be done AFTER data update */
840     MAP_I2SIntClear(I2S_BASE,I2S_STS_RDATA);
841 }
842 
843 /*
844  *  ======== updateDataWriteCPU ========
845  */
updateDataWriteCPU(uintptr_t arg)846 static void updateDataWriteCPU(uintptr_t arg) {
847     I2S_Handle handle = (I2S_Handle)arg;
848     I2SCC32XX_Object *object = handle->object;
849     I2SCC32XX_DataInterface   *SD0;
850     I2SCC32XX_DataInterface   *SD1;
851 
852     /* Get the pointer to the SD0 and SD1 interfaces*/
853     SD0 = &object->dataInterfaceSD0;
854     SD1 = &object->dataInterfaceSD1;
855 
856     I2S_Transaction *transaction = (I2S_Transaction *)object->write.activeTransfer;
857     if(transaction != NULL) {
858 
859         bool dataKO = (bool)false;
860         uint32_t Value;
861         uint32_t *ptrValue = &Value;
862         ptrValue = (uint32_t*)((uint32_t)transaction->bufPtr + (uint32_t)transaction->bytesTransferred);
863         Value = *ptrValue;
864 
865         while((!dataKO) && (transaction != NULL)) {
866 
867             if((SD0->interfaceConfig == I2S_SD0_OUTPUT) && (transaction != NULL) && (!dataKO)) {
868 
869                 dataKO |= MAP_I2SDataPutNonBlocking(I2S_BASE, SD0->dataLine, Value);
870 
871                 if(!dataKO) {
872 
873                     handleCPUTransaction(handle, &transaction, &object->write);
874 
875                     if(transaction != NULL){
876                         ptrValue = (uint32_t*)((uint32_t)transaction->bufPtr + (uint32_t)transaction->bytesTransferred);
877                         Value = *ptrValue;
878                     }
879                 }
880             }
881 
882             if((SD1->interfaceConfig == I2S_SD1_OUTPUT) && (transaction != NULL) && (!dataKO)) {
883 
884                 dataKO |= MAP_I2SDataPutNonBlocking(I2S_BASE, SD1->dataLine, Value);
885 
886                 if(!dataKO) {
887 
888                     handleCPUTransaction(handle, &transaction, &object->write);
889 
890                     if(transaction != NULL){
891                         ptrValue = (uint32_t*)((uint32_t)transaction->bufPtr + (uint32_t)transaction->bytesTransferred);
892                         Value = *ptrValue;
893                     }
894                 }
895             }
896         }
897     }
898 
899     /* In CPU mode interrupt clearing must be done AFTER data update */
900     MAP_I2SIntClear(I2S_BASE,I2S_STS_XDATA);
901 }
902 
903 /*
904  *  ======== handleCPUTransaction ========
905  *  This function avoid to duplicate the code dedicated to take care of the transactions in CPU mode.
906  *  If needed, this function remove the transaction from the list and trigger the user callback.
907  */
handleCPUTransaction(I2S_Handle handle,I2S_Transaction ** ptrTransaction,I2SCC32XX_Interface * interface)908 static void handleCPUTransaction(I2S_Handle handle,
909                                  I2S_Transaction **ptrTransaction,
910                                  I2SCC32XX_Interface *interface){
911 
912     I2SCC32XX_Object const *object = handle->object;
913     I2S_Transaction *transaction = *ptrTransaction;
914 
915     transaction->bytesTransferred += object->memorySlotLength / BYTE_LENGTH;
916 
917     if(transaction->bytesTransferred >= transaction->bufSize){
918 
919         /* We note the transaction as finished */
920         transaction->numberOfCompletions ++;
921         transaction->untransferredBytes = transaction->bufSize - transaction->bytesTransferred;
922         transaction->bytesTransferred = 0;
923 
924         /* We now take in consideration the next transaction */
925         interface->activeTransfer = (I2S_Transaction*)List_next(&transaction->queueElement);
926         *ptrTransaction = (I2S_Transaction*)interface->activeTransfer; /* transaction pointer must be updated because
927                                                                         * it is potentially reused by the calling function */
928 
929         I2S_Transaction *newTransaction = *ptrTransaction;
930         if(newTransaction == NULL){
931             /* It's too late for the user to queue new transactions: the hardware is already running out of data */
932             interface->stopInterface(handle);
933         }
934         else if(List_next(&newTransaction->queueElement) == NULL) {
935             interface->callback(handle, I2S_ALL_TRANSACTIONS_SUCCESS, transaction);
936         }
937         else {
938             interface->callback(handle, I2S_TRANSACTION_SUCCESS, transaction);
939         }
940     }
941 }
942 
943 /*
944  *  ======== initObject ========
945  */
initObject(I2S_Handle handle,I2S_Params * params)946 static bool initObject(I2S_Handle handle, I2S_Params *params) {
947 
948     I2SCC32XX_Object          *object = handle->object;
949     I2SCC32XX_DataInterface   *SD0;
950     I2SCC32XX_DataInterface   *SD1;
951 
952     uint8_t indexDmaConfig = 0;
953     uint8_t indexDmaArbConfig = 0;
954 
955     bool retVal = (bool)true;
956 
957     /* Get the pointer to the SD0 and SD1 interfaces*/
958     SD0 = &object->dataInterfaceSD0;
959     SD1 = &object->dataInterfaceSD1;
960 
961     object->moduleRole           = params->moduleRole;
962     object->invertWS             = params->invertWS;
963     object->samplingEdge         = params->samplingEdge;
964     object->isMSBFirst           = params->isMSBFirst;
965     object->samplingFrequency    = params->samplingFrequency;
966     object->dataShift            = (params->trueI2sFormat)? DATA_SHIFT_1 : DATA_SHIFT_NONE;
967     object->isLastReadTransfer   = (bool)false;
968     object->isLastWriteTransfer  = (bool)false;
969 
970     DebugP_assert(params->memorySlotLength == I2S_MEMORY_LENGTH_8BITS  ||
971                   params->memorySlotLength == I2S_MEMORY_LENGTH_16BITS ||
972                   params->memorySlotLength == I2S_MEMORY_LENGTH_24BITS ||
973                   params->memorySlotLength == I2S_MEMORY_LENGTH_32BITS   );
974 
975     if(!params->isDMAUnused){
976         if(params->memorySlotLength <= I2S_MEMORY_LENGTH_8BITS){
977             indexDmaConfig = 0;
978             object->memorySlotLength = I2S_MEMORY_LENGTH_8BITS;
979         }
980         else if(params->memorySlotLength <= I2S_MEMORY_LENGTH_16BITS){
981             indexDmaConfig = 1;
982             object->memorySlotLength = I2S_MEMORY_LENGTH_16BITS;
983         }
984         else if(params->memorySlotLength <= I2S_MEMORY_LENGTH_32BITS){
985             indexDmaConfig = 2;
986             object->memorySlotLength = I2S_MEMORY_LENGTH_32BITS;
987         }
988         else {
989             retVal = (bool)false;
990         }
991     }
992     else {
993         indexDmaConfig = 0;
994         object->memorySlotLength = params->memorySlotLength;
995     }
996 
997     /* Computation of the sampleMask and the sampleRotation (to achieve before and after word padding) */
998     if(params->beforeWordPadding + params->bitsPerWord + params->afterWordPadding <= 32) {
999         object->dataLength      = params->beforeWordPadding + params->bitsPerWord + params->afterWordPadding;
1000 
1001         /* This is the default setting. Data are right aligned. */
1002         object->sampleMask      = 0xFFFFFFFF >> (32-object->memorySlotLength);
1003         object->sampleRotation  = (object->dataLength / HWRESOLUTION) % BYTE_LENGTH;
1004 
1005         /* Data truncation is made by masking the LSB of the samples. Data are still right aligned. */
1006         if(params->bitsPerWord < object->memorySlotLength) {
1007             object->sampleMask &= (0xFFFFFFFF << (object->memorySlotLength - params->bitsPerWord));
1008             object->sampleRotation += ((object->memorySlotLength - params->bitsPerWord) / HWRESOLUTION) % BYTE_LENGTH;
1009         }
1010 
1011         /* Data padding is made by increasing the left rotation (i.e. decreasing right rotation) */
1012         if(params->bitsPerWord > object->memorySlotLength) {
1013             object->sampleRotation -= ((params->bitsPerWord - object->memorySlotLength) / HWRESOLUTION) % BYTE_LENGTH;
1014         }
1015 
1016         /* After word padding is made by increasing the left rotation (i.e. decreasing right rotation) */
1017         if(params->afterWordPadding) {
1018             object->sampleRotation -= (params->afterWordPadding / HWRESOLUTION) % BYTE_LENGTH;
1019         }
1020     }
1021     else {
1022         retVal = (bool)false;
1023     }
1024 
1025     object->isDMAUnused          = params->isDMAUnused;
1026     if(object->isDMAUnused) {
1027         object->updateDataReadFxn  = updateDataReadCPU;
1028         object->updateDataWriteFxn = updateDataWriteCPU;
1029     }
1030     else {
1031         object->updateDataReadFxn  = updateDataReadDMA;
1032         object->updateDataWriteFxn = updateDataWriteDMA;
1033     }
1034 
1035     SD0->interfaceConfig      = params->SD0Use;
1036     SD0->channelsUsed         = params->SD0Channels;
1037     SD0->numberOfChannelsUsed = getNumberOfChannels((uint8_t)SD0->channelsUsed);
1038     SD0->dataLine             = I2S_DATA_LINE_0;
1039     SD1->interfaceConfig      = params->SD1Use;
1040     SD1->channelsUsed         = params->SD1Channels;
1041     SD1->numberOfChannelsUsed = getNumberOfChannels((uint8_t)SD1->channelsUsed);
1042     SD1->dataLine             = I2S_DATA_LINE_1;
1043 
1044     object->noOfInputs          =   ((SD0->interfaceConfig == I2S_SD0_INPUT)? 1: 0)
1045                                   + ((SD1->interfaceConfig == I2S_SD1_INPUT)? 1: 0);
1046     object->noOfOutputs         =   ((SD0->interfaceConfig == I2S_SD0_OUTPUT)? 1: 0)
1047                                   + ((SD1->interfaceConfig == I2S_SD1_OUTPUT)? 1: 0);
1048 
1049     /* Here we are looking for the biggest possible  uDMA arbitration length */
1050     if(params->fixedBufferLength == 0) {
1051         retVal = (bool)false;
1052     }
1053     else {
1054         if(params->fixedBufferLength != 1) {
1055             uint16_t const fixedBufferLength = (params->fixedBufferLength /(object->memorySlotLength/BYTE_LENGTH));
1056             int i;
1057 
1058             /* The udmaArbLength minimum value is 2 (= 2^1)*/
1059             object->udmaArbLength = 2;
1060             /* The udmaArbLength maximum value is 16 (= 2^4)*/
1061             for(i=2; i<=4; i++) {
1062                 if(fixedBufferLength % (1 << i) == 0) {
1063                     object->udmaArbLength = 1 << i;
1064                 }
1065             }
1066         }
1067         else {
1068             object->udmaArbLength = UDMA_ARBLENGTH_DEFAULT;
1069         }
1070     }
1071 
1072     /* Authorized Arbitration values are limited to 2, 4, 8, 16 */
1073     DebugP_assert(object->udmaArbLength == 2  ||
1074                   object->udmaArbLength == 4  ||
1075                   object->udmaArbLength == 8  ||
1076                   object->udmaArbLength == 16   );
1077 
1078     int i;
1079     for(i=0; i<BYTE_LENGTH; i++) {
1080         if(object->udmaArbLength == (1 << i)) {
1081             indexDmaArbConfig = i;
1082         }
1083     }
1084 
1085     object->read.udmaConfig = dmaRxConfig[indexDmaConfig] | dmaArbConfig[indexDmaArbConfig];
1086     object->read.stopInterface = I2S_stopRead;
1087     object->read.callback = params->readCallback;
1088     if((object->read.callback == NULL) && (object->noOfInputs != 0U)) {
1089         retVal = (bool)false;
1090     }
1091 
1092     object->write.udmaConfig = dmaTxConfig[indexDmaConfig] | dmaArbConfig[indexDmaArbConfig];
1093     object->write.stopInterface = I2S_stopWrite;
1094     object->write.callback = params->writeCallback;
1095     if((object->write.callback == NULL) && (object->noOfOutputs != 0U)) {
1096         retVal = (bool)false;
1097     }
1098 
1099     object->errorCallback = params->errorCallback;
1100     if(object->errorCallback == NULL) {
1101         retVal = (bool)false;
1102     }
1103 
1104     object->read.activeTransfer   = NULL;
1105     object->write.activeTransfer  = NULL;
1106 
1107     return retVal;
1108 }
1109 
1110 /*
1111  *  ======== initIO ========
1112  */
initIO(I2S_Handle handle)1113 static void initIO(I2S_Handle handle) {
1114 
1115     I2SCC32XX_HWAttrs const   *hwAttrs;
1116 
1117     /* Get the pointer to the object and hwAttrs */
1118     hwAttrs = handle->hwAttrs;
1119 
1120     DebugP_assert(hwAttrs->pinSD1 == I2SCC32XX_PIN_50_SD1 ||
1121                   hwAttrs->pinSD1 == I2SCC32XX_PIN_60_SD1 ||
1122                   hwAttrs->pinSD1 == I2SCC32XX_PIN_UNUSED);
1123 
1124     DebugP_assert(hwAttrs->pinSD0 == I2SCC32XX_PIN_45_SD0 ||
1125                   hwAttrs->pinSD0 == I2SCC32XX_PIN_50_SD0 ||
1126                   hwAttrs->pinSD0 == I2SCC32XX_PIN_52_SD0 ||
1127                   hwAttrs->pinSD0 == I2SCC32XX_PIN_64_SD0 ||
1128                   hwAttrs->pinSD0 == I2SCC32XX_PIN_UNUSED);
1129 
1130     DebugP_assert(hwAttrs->pinSCK == I2SCC32XX_PIN_03_SCK ||
1131                   hwAttrs->pinSCK == I2SCC32XX_PIN_52_SCK ||
1132                   hwAttrs->pinSCK == I2SCC32XX_PIN_53_SCK ||
1133                   hwAttrs->pinSCK == I2SCC32XX_PIN_UNUSED);
1134 
1135     DebugP_assert(hwAttrs->pinWS  == I2SCC32XX_PIN_02_WS ||
1136                   hwAttrs->pinWS  == I2SCC32XX_PIN_15_WS ||
1137                   hwAttrs->pinWS  == I2SCC32XX_PIN_17_WS ||
1138                   hwAttrs->pinWS  == I2SCC32XX_PIN_21_WS ||
1139                   hwAttrs->pinWS  == I2SCC32XX_PIN_45_WS ||
1140                   hwAttrs->pinWS  == I2SCC32XX_PIN_53_WS ||
1141                   hwAttrs->pinWS  == I2SCC32XX_PIN_63_WS);
1142 
1143     DebugP_assert(hwAttrs->pinSD1 == I2SCC32XX_PIN_62_SCKX ||
1144                   hwAttrs->pinSD1 == I2SCC32XX_PIN_UNUSED);
1145 
1146     openPin(hwAttrs->pinSD1);
1147     openPin(hwAttrs->pinSD0);
1148     openPin(hwAttrs->pinSCK);
1149     openPin(hwAttrs->pinSCKX);
1150     openPin(hwAttrs->pinWS);
1151 }
1152 
1153 /*
1154  *  ======== openPin ========
1155  */
openPin(unsigned long pinI2S)1156 static void openPin(unsigned long pinI2S) {
1157 
1158     if(pinI2S != I2SCC32XX_PIN_UNUSED) {
1159         MAP_PinTypeI2S((unsigned long)PinConfigPin(pinI2S),
1160                    (unsigned long)PinConfigPinMode(pinI2S));
1161     }
1162 }
1163 
1164 /*
1165  *  ======== resetPin ========
1166  */
resetPin(unsigned long pinI2S)1167 static void resetPin(unsigned long pinI2S) {
1168 
1169     if(pinI2S != I2SCC32XX_PIN_UNUSED) {
1170         uint32_t padRegister = (PinToPadGet((pinI2S) & 0x3f)<<2) + PAD_CONFIG_BASE;
1171         HWREG(padRegister) = PAD_RESET_STATE;
1172     }
1173 }
1174 
1175 /*
1176  *  ======== restorePinpads ========
1177  */
restorePinpads(I2SCC32XX_HWAttrs const * hwAttrs)1178 static void restorePinpads(I2SCC32XX_HWAttrs const *hwAttrs){
1179     resetPin(hwAttrs->pinSD1);
1180     resetPin(hwAttrs->pinSD0);
1181     resetPin(hwAttrs->pinSCK);
1182     resetPin(hwAttrs->pinSCKX);
1183     resetPin(hwAttrs->pinWS);
1184 }
1185 
1186 /*
1187  *  ======== initDMA ========
1188  */
initDMA(I2S_Handle handle)1189 static void initDMA(I2S_Handle handle) {
1190 
1191     I2SCC32XX_Object *object;
1192     object  = handle->object;
1193 
1194     if(!object->isDMAUnused) {
1195 
1196         object->dmaHandle = UDMACC32XX_open();
1197     }
1198 }
1199 
1200 /*
1201  *  ======== getNumberOfChannels ========
1202  */
getNumberOfChannels(const uint8_t channelsList)1203 static uint8_t getNumberOfChannels(const uint8_t channelsList) {
1204 
1205     uint8_t i = 0;
1206     uint8_t nbChannelsUsed = 0;
1207     for(i=0; i<(I2S_NB_CHANNELS_MAX); i++) {
1208         if(((channelsList >> i) & 1U) == 1U) {
1209             nbChannelsUsed ++;
1210         }
1211     }
1212     return nbChannelsUsed;
1213 }
1214 
1215 /*
1216  *  ======== configSCK ========
1217  */
configSCK(I2S_Handle handle)1218 static void configSCK(I2S_Handle handle) {
1219 
1220     I2SCC32XX_Object const *object;
1221 
1222     /* Get the pointer to the object*/
1223     object = handle->object;
1224 
1225     /* There are three freq dividers (one in the PRCM module, two in the I2S module).
1226      * Two of the three freq dividers are used to keep the possibility to activate
1227      * only the input (or only the output).
1228      * Smallest SCK frequency possible is 57 Hz. */
1229     unsigned long ulI2SClk  = object->samplingFrequency * object->dataLength * 2;
1230     unsigned long ulBitClk  = (ulI2SClk < PRCMI2SCLOCKFREQMIN)? PRCMI2SCLOCKFREQMIN : ulI2SClk;
1231     MAP_PRCMI2SClockFreqSet(ulBitClk);
1232 
1233     /* Calculate remaining divider */
1234     unsigned long remainingDivider = ((ulBitClk + ulI2SClk/2) / ulI2SClk); /* We want to round the integer division: ROUND(a/b)=(a+b/2)/b */;
1235     unsigned long ulHClkDiv = (remainingDivider == 0)? 0 :(remainingDivider-1);
1236     ulHClkDiv = (ulHClkDiv > HCLKDIVMAX)? HCLKDIVMAX : ulHClkDiv;
1237     unsigned long ulClkDiv  = 0; /* ulClkDiv is not activated */
1238 
1239     HWREG(I2S_BASE + MCASP_O_AHCLKXCTL) = (MCASP_AHCLKXCTL_HCLKXM_DEFAULT|ulHClkDiv);
1240     if(object->noOfOutputs != 0) {
1241 
1242         HWREG(I2S_BASE + MCASP_O_ACLKXCTL)  = (((object->samplingEdge << 7)   & MCASP_ACLKXCTL_CLKXP) |
1243                                                ((object->moduleRole   << 5)   & MCASP_ACLKXCTL_CLKXM) |
1244                                                ((ulClkDiv             << 0)   & MCASP_ACLKXCTL_CLKXDIV_M));
1245     }
1246 
1247     HWREG(I2S_BASE + MCASP_O_AHCLKRCTL) = (MCASP_AHCLKRCTL_HCLKRM_DEFAULT|ulHClkDiv);
1248     if(object->noOfInputs != 0) {
1249 
1250         HWREG(I2S_BASE + MCASP_O_ACLKRCTL)  = (((object->samplingEdge << 7)   & MCASP_ACLKRCTL_CLKRP) |
1251                                                ((object->moduleRole   << 5)   & MCASP_ACLKRCTL_CLKRM) |
1252                                                ((ulClkDiv             << 0)   & MCASP_ACLKRCTL_CLKRDIV_M));
1253     }
1254 
1255 }
1256 
1257 /*
1258  *  ======== configWS ========
1259  */
configWS(I2S_Handle handle)1260 static void configWS(I2S_Handle handle) {
1261 
1262     I2SCC32XX_Object const *object;
1263 
1264     /* Get the pointer to the object*/
1265     object = handle->object;
1266 
1267     if(object->noOfInputs != 0) {
1268         HWREG(I2S_BASE + MCASP_O_RXFMCTL) =  (  MCASP_RXFMCTL_RMOD_DEFAULT                       |
1269                                                 MCASP_RXFMCTL_FRWID_DEFAULT                      |
1270                                               ((object->moduleRole << 1)   & MCASP_RXFMCTL_FSRM) |
1271                                               ((object->invertWS   << 0)   & MCASP_RXFMCTL_FSRP));
1272     }
1273 
1274     /* Must be executed including in read-only mode */
1275     HWREG(I2S_BASE + MCASP_O_TXFMCTL) =  (  MCASP_TXFMCTL_XMOD_DEFAULT                       |
1276                                             MCASP_TXFMCTL_FXWID_DEFAULT                      |
1277                                           ((object->moduleRole << 1)   & MCASP_TXFMCTL_FSXM) |
1278                                           ((object->invertWS   << 0)   & MCASP_TXFMCTL_FSXP));
1279 }
1280 
1281 /*
1282  *  ======== configSerialFormat ========
1283  */
configSerialFormat(I2S_Handle handle)1284 static void configSerialFormat(I2S_Handle handle) {
1285 
1286     I2SCC32XX_Object          const *object;
1287     I2SCC32XX_DataInterface   const *SD0;
1288     I2SCC32XX_DataInterface   const *SD1;
1289 
1290     uint8_t channelsToActivate;
1291 
1292     /* Get the pointer to the SD0 and SD1 interfaces*/
1293     object  = handle->object;
1294     SD0     = &object->dataInterfaceSD0;
1295     SD1     = &object->dataInterfaceSD1;
1296 
1297     /* Expected values (intermediate values are also possible):
1298      * dataLength = 8     >>   dataLengthCC32XX = 0x3
1299      * dataLength = 16    >>   dataLengthCC32XX = 0x7
1300      * dataLength = 24    >>   dataLengthCC32XX = 0xB
1301      * dataLength = 32    >>   dataLengthCC32XX = 0xF
1302      * */
1303     uint8_t dataLengthCC32XX = 1;
1304     int i;
1305     for(i=HWRESOLUTION;i<=32;i+=HWRESOLUTION){
1306         if(object->dataLength > i) {
1307             dataLengthCC32XX += HWRESOLUTION/2;
1308         }
1309     }
1310 
1311     if(object->noOfInputs != 0) {
1312 
1313         channelsToActivate = ((SD0->interfaceConfig == I2S_SD0_INPUT)? SD0->channelsUsed: 0x00) |
1314                              ((SD1->interfaceConfig == I2S_SD1_INPUT)? SD1->channelsUsed: 0x00);
1315         HWREG(I2S_BASE + MCASP_O_RXFMT) = (((object->dataShift        << MCASP_RXFMT_RDATDLY_S) & MCASP_RXFMT_RDATDLY_M)|
1316                                            ((object->isMSBFirst       << 15                   ) & MCASP_RXFMT_RRVRS )   |
1317                                            ((dataLengthCC32XX         << MCASP_RXFMT_RSSZ_S   ) & MCASP_RXFMT_RSSZ_M)   |
1318                                            ((object->isDMAUnused      << 3                    ) & MCASP_RXFMT_RBUSEL)   |
1319                                            ((object->sampleRotation   << MCASP_RXFMT_RROT_S   ) & MCASP_RXFMT_RROT_M));
1320         HWREG(I2S_BASE + MCASP_O_RXMASK) = object->sampleMask;
1321         HWREG(I2S_BASE + MCASP_O_RXTDM) = channelsToActivate;
1322     }
1323 
1324     /* Must be executed including in read-only mode */
1325     channelsToActivate = ((SD0->interfaceConfig == I2S_SD0_OUTPUT)? SD0->channelsUsed: 0x00) |
1326                          ((SD1->interfaceConfig == I2S_SD1_OUTPUT)? SD1->channelsUsed: 0x00);
1327     HWREG(I2S_BASE + MCASP_O_TXFMT) = (((object->dataShift        << MCASP_TXFMT_XDATDLY_S) & MCASP_TXFMT_XDATDLY_M)|
1328                                        ((object->isMSBFirst       << 15                   ) & MCASP_TXFMT_XRVRS )   |
1329                                        ((dataLengthCC32XX         << MCASP_TXFMT_XSSZ_S   ) & MCASP_TXFMT_XSSZ_M)   |
1330                                        ((object->isDMAUnused      << 3                    ) & MCASP_TXFMT_XBUSEL)   |
1331                                        ((object->sampleRotation   << MCASP_TXFMT_XROT_S   ) & MCASP_TXFMT_XROT_M));
1332     HWREG(I2S_BASE + MCASP_O_TXMASK) = object->sampleMask;
1333     HWREG(I2S_BASE + MCASP_O_TXTDM) = channelsToActivate;
1334 }
1335 
1336 /*
1337  *  ======== postNotify ========
1338  *  This functions is called to notify the I2S driver of an ongoing transition
1339  *  out of LPDS mode.
1340  *  clientArg should be pointing to a hardware module which has already
1341  *  been opened.
1342  */
postNotify(unsigned int eventType,uintptr_t eventArg,uintptr_t clientArg)1343 static int postNotify(unsigned int eventType, uintptr_t eventArg, uintptr_t clientArg) {
1344 
1345     /* Reconfigure the hardware when returning from LPDS */
1346     initHw((I2S_Handle)clientArg);
1347 
1348     return (Power_NOTIFYDONE);
1349 }
1350