1 /*
2  * Copyright (c) 2013-2024, Arm Limited. All rights reserved.
3  * Copyright (c) 2019-2020 Cypress Semiconductor Corporation. All rights reserved.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  *
7  * Licensed under the Apache License, Version 2.0 (the License); you may
8  * not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
15  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 /* This is a modified copy of the ref_twincpu version at
21  * platform/ext/target/ref_twincpu/CMSIS_Driver/Driver_USART.c
22  */
23 
24 #include "Driver_USART.h"
25 #include "tfm_hal_device_header.h"
26 #include "cmsis_driver_config.h"
27 #include "RTE_Device.h"
28 
29 #include "cycfg.h"
30 #include "cy_device.h"
31 #include "cy_scb_uart.h"
32 
33 #ifndef ARG_UNUSED
34 #define ARG_UNUSED(arg)  (void)arg
35 #endif
36 
37 /* Driver version */
38 #define ARM_USART_DRV_VERSION  ARM_DRIVER_VERSION_MAJOR_MINOR(2, 2)
39 
40 /* Driver Version */
41 static const ARM_DRIVER_VERSION DriverVersion = {
42     ARM_USART_API_VERSION,
43     ARM_USART_DRV_VERSION
44 };
45 
46 /* Driver Capabilities */
47 static const ARM_USART_CAPABILITIES DriverCapabilities = {
48     1, /* supports UART (Asynchronous) mode */
49     0, /* supports Synchronous Master mode */
50     0, /* supports Synchronous Slave mode */
51     0, /* supports UART Single-wire mode */
52     0, /* supports UART IrDA mode */
53     0, /* supports UART Smart Card mode */
54     0, /* Smart Card Clock generator available */
55     0, /* RTS Flow Control available */
56     0, /* CTS Flow Control available */
57     0, /* Transmit completed event: \ref ARM_USARTx_EVENT_TX_COMPLETE */
58     0, /* Signal receive character timeout event: \ref ARM_USARTx_EVENT_RX_TIMEOUT */
59     0, /* RTS Line: 0=not available, 1=available */
60     0, /* CTS Line: 0=not available, 1=available */
61     0, /* DTR Line: 0=not available, 1=available */
62     0, /* DSR Line: 0=not available, 1=available */
63     0, /* DCD Line: 0=not available, 1=available */
64     0, /* RI Line: 0=not available, 1=available */
65     0, /* Signal CTS change event: \ref ARM_USARTx_EVENT_CTS */
66     0, /* Signal DSR change event: \ref ARM_USARTx_EVENT_DSR */
67     0, /* Signal DCD change event: \ref ARM_USARTx_EVENT_DCD */
68     0, /* Signal RI change event: \ref ARM_USARTx_EVENT_RI */
69     0  /* Reserved */
70 };
71 
ARM_USART_GetVersion(void)72 static ARM_DRIVER_VERSION ARM_USART_GetVersion(void)
73 {
74     return DriverVersion;
75 }
76 
ARM_USART_GetCapabilities(void)77 static ARM_USART_CAPABILITIES ARM_USART_GetCapabilities(void)
78 {
79     return DriverCapabilities;
80 }
81 
82 typedef struct {
83     CySCB_Type* base;                  /* UART device structure */
84     uint32_t tx_nbr_bytes;             /* Number of bytes transfered */
85     uint32_t rx_nbr_bytes;             /* Number of bytes recevied */
86     ARM_USART_SignalEvent_t cb_event;  /* Callback function for events */
87 } UARTx_Resources;
88 
USARTx_convert_retval(cy_en_scb_uart_status_t val)89 static int32_t USARTx_convert_retval(cy_en_scb_uart_status_t val)
90 {
91     switch (val) {
92     case CY_SCB_UART_SUCCESS:
93         return ARM_DRIVER_OK;
94     case CY_SCB_UART_BAD_PARAM:
95         return ARM_DRIVER_ERROR_PARAMETER;
96     case CY_SCB_UART_RECEIVE_BUSY:
97     case CY_SCB_UART_TRANSMIT_BUSY:
98         return ARM_DRIVER_ERROR_BUSY;
99     }
100 }
101 
ARM_USARTx_Initialize(UARTx_Resources * uart_dev)102 static int32_t ARM_USARTx_Initialize(UARTx_Resources* uart_dev)
103 {
104     cy_en_scb_uart_status_t retval;
105 
106 #if CY_SYSTEM_CPU_CM0P
107     cy_stc_scb_uart_config_t config = KITPROG_UART_config;
108 
109     /* Assign and configure pins, assign clock divider */
110     retval = Cy_SCB_UART_Init(uart_dev->base, &config, NULL);
111 
112     Cy_SCB_UART_ClearRxFifo(uart_dev->base);
113     Cy_SCB_UART_ClearTxFifo(uart_dev->base);
114 
115     if (retval == CY_SCB_UART_SUCCESS)
116         Cy_SCB_UART_Enable(uart_dev->base);
117 #else
118     // all hw initializations is done on the cm0p side
119     retval = CY_SCB_UART_SUCCESS;
120 
121 #endif
122     return USARTx_convert_retval(retval);
123 }
124 
ARM_USARTx_Uninitialize(UARTx_Resources * uart_dev)125 static uint32_t ARM_USARTx_Uninitialize(UARTx_Resources* uart_dev)
126 {
127     Cy_SCB_UART_Disable(uart_dev->base, NULL);
128 
129     Cy_SCB_UART_DeInit(uart_dev->base);
130 
131     return ARM_DRIVER_OK;
132 }
133 
134 
ARM_USARTx_PowerControl(UARTx_Resources * uart_dev,ARM_POWER_STATE state)135 static int32_t ARM_USARTx_PowerControl(UARTx_Resources* uart_dev,
136                                        ARM_POWER_STATE state)
137 {
138     ARG_UNUSED(uart_dev);
139 
140     switch (state) {
141     case ARM_POWER_OFF:
142     case ARM_POWER_LOW:
143         return ARM_DRIVER_ERROR_UNSUPPORTED;
144     case ARM_POWER_FULL:
145         /* Nothing to be done */
146         return ARM_DRIVER_OK;
147     /* default:  The default is not defined intentionally to force the
148      *           compiler to check that all the enumeration values are
149      *           covered in the switch.*/
150     }
151 }
152 
ARM_USARTx_Send(UARTx_Resources * uart_dev,const void * data,uint32_t num)153 static int32_t ARM_USARTx_Send(UARTx_Resources* uart_dev, const void *data,
154                                uint32_t num)
155 {
156     void *p_data = (void *)data;
157 
158     if ((data == NULL) || (num == 0U)) {
159         /* Invalid parameters */
160         return ARM_DRIVER_ERROR_PARAMETER;
161     }
162 
163     Cy_SCB_UART_PutArrayBlocking(uart_dev->base, p_data, num);
164 
165     while (!Cy_SCB_UART_IsTxComplete(uart_dev->base))
166         ;
167 
168     uart_dev->tx_nbr_bytes = num;
169 
170     return ARM_DRIVER_OK;
171 }
172 
ARM_USARTx_Receive(UARTx_Resources * uart_dev,void * data,uint32_t num)173 static int32_t ARM_USARTx_Receive(UARTx_Resources* uart_dev,
174                                   void *data, uint32_t num)
175 {
176     if ((data == NULL) || (num == 0U)) {
177         // Invalid parameters
178         return ARM_DRIVER_ERROR_PARAMETER;
179     }
180 
181     Cy_SCB_UART_GetArrayBlocking(uart_dev->base, data, num);
182 
183     uart_dev->rx_nbr_bytes = num;
184 
185     return ARM_DRIVER_OK;
186 }
187 
ARM_USARTx_Transfer(UARTx_Resources * uart_dev,const void * data_out,void * data_in,uint32_t num)188 static int32_t ARM_USARTx_Transfer(UARTx_Resources* uart_dev,
189                                    const void *data_out, void *data_in,
190                                    uint32_t num)
191 {
192     ARG_UNUSED(uart_dev);
193     ARG_UNUSED(data_out);
194     ARG_UNUSED(data_in);
195     ARG_UNUSED(num);
196 
197     return ARM_DRIVER_ERROR_UNSUPPORTED;
198 }
199 
ARM_USARTx_GetTxCount(UARTx_Resources * uart_dev)200 static uint32_t ARM_USARTx_GetTxCount(UARTx_Resources* uart_dev)
201 {
202     return uart_dev->tx_nbr_bytes;
203 }
204 
ARM_USARTx_GetRxCount(UARTx_Resources * uart_dev)205 static uint32_t ARM_USARTx_GetRxCount(UARTx_Resources* uart_dev)
206 {
207     return uart_dev->rx_nbr_bytes;
208 }
209 
USARTx_SetDataBits(uint32_t control,cy_stc_scb_uart_config_t * config)210 static int32_t USARTx_SetDataBits(uint32_t control,
211                                    cy_stc_scb_uart_config_t *config)
212 {
213     switch (control & ARM_USART_DATA_BITS_Msk) {
214     case ARM_USART_DATA_BITS_5:
215         config->dataWidth = 5;
216         break;
217 
218     case ARM_USART_DATA_BITS_6:
219         config->dataWidth = 6;
220         break;
221 
222     case ARM_USART_DATA_BITS_7:
223         config->dataWidth = 7;
224         break;
225 
226     case ARM_USART_DATA_BITS_8:
227         config->dataWidth = 8;
228         break;
229 
230     case ARM_USART_DATA_BITS_9:
231         config->dataWidth = 9;
232         break;
233 
234     default:
235         return ARM_DRIVER_ERROR_UNSUPPORTED;
236     }
237 
238     return ARM_DRIVER_OK;
239 }
240 
USARTx_SetParity(uint32_t control,cy_stc_scb_uart_config_t * config)241 static int32_t USARTx_SetParity(uint32_t control,
242                                  cy_stc_scb_uart_config_t *config)
243 {
244     switch (control & ARM_USART_PARITY_Msk) {
245     case ARM_USART_PARITY_NONE:
246         config->parity = CY_SCB_UART_PARITY_NONE;
247         break;
248 
249     case ARM_USART_PARITY_EVEN:
250         config->parity = CY_SCB_UART_PARITY_EVEN;
251         break;
252 
253     case ARM_USART_PARITY_ODD:
254         config->parity = CY_SCB_UART_PARITY_ODD;
255         break;
256 
257     default:
258         return ARM_DRIVER_ERROR_UNSUPPORTED;
259     }
260 
261     return ARM_DRIVER_OK;
262 }
263 
USARTx_SetStopBits(uint32_t control,cy_stc_scb_uart_config_t * config)264 static int32_t USARTx_SetStopBits(uint32_t control,
265                                    cy_stc_scb_uart_config_t *config)
266 {
267     switch (control & ARM_USART_STOP_BITS_Msk) {
268     case ARM_USART_STOP_BITS_1:
269         config->stopBits = CY_SCB_UART_STOP_BITS_1;
270         break;
271 
272     case ARM_USART_STOP_BITS_2:
273         config->stopBits = CY_SCB_UART_STOP_BITS_2;
274         break;
275 
276     case ARM_USART_STOP_BITS_1_5:
277         config->stopBits = CY_SCB_UART_STOP_BITS_1_5;
278         break;
279 
280     default:
281         return ARM_DRIVER_ERROR_UNSUPPORTED;
282     }
283 
284     return ARM_DRIVER_OK;
285 }
286 
USARTx_SetFlowControl(uint32_t control,cy_stc_scb_uart_config_t * config)287 static void USARTx_SetFlowControl(uint32_t control,
288                                   cy_stc_scb_uart_config_t *config)
289 {
290     /* First, deal with CTS */
291     switch (control & ARM_USART_FLOW_CONTROL_Msk) {
292     case ARM_USART_FLOW_CONTROL_NONE:
293     case ARM_USART_FLOW_CONTROL_RTS:
294         config->enableCts = false;
295         config->ctsPolarity = CY_SCB_UART_ACTIVE_LOW;
296         break;
297 
298     case ARM_USART_FLOW_CONTROL_CTS:
299     case ARM_USART_FLOW_CONTROL_RTS_CTS:
300         config->enableCts = true;
301         config->ctsPolarity = CY_SCB_UART_ACTIVE_LOW;
302         break;
303     }
304 
305     /* Then RTS */
306     switch (control & ARM_USART_FLOW_CONTROL_Msk) {
307     case ARM_USART_FLOW_CONTROL_NONE:
308     case ARM_USART_FLOW_CONTROL_CTS:
309         config->rtsRxFifoLevel = 0;
310         config->rtsPolarity = CY_SCB_UART_ACTIVE_LOW;
311         break;
312 
313     case ARM_USART_FLOW_CONTROL_RTS:
314     case ARM_USART_FLOW_CONTROL_RTS_CTS:
315         config->rtsRxFifoLevel = 8; /* TODO What's a sensible value ? */
316         config->rtsPolarity = CY_SCB_UART_ACTIVE_LOW;
317         break;
318     }
319 }
320 
ARM_USARTx_Control(UARTx_Resources * uart_dev,uint32_t control,uint32_t arg)321 static int32_t ARM_USARTx_Control(UARTx_Resources* uart_dev, uint32_t control,
322                                   uint32_t arg)
323 {
324     cy_stc_scb_uart_config_t config = KITPROG_UART_config;
325     uint32_t retval;
326 
327     switch (control & ARM_USART_CONTROL_Msk) {
328         case ARM_USART_MODE_ASYNCHRONOUS:
329             /* TODO Default values work for 115200 baud,
330              * but we should set config.oversample to
331              * a value derived from the divider
332              */
333             break;
334         /* Unsupported command */
335         default:
336             return ARM_DRIVER_ERROR_UNSUPPORTED;
337     }
338 
339     Cy_SCB_UART_Disable(uart_dev->base, NULL);
340 
341     /* UART Data bits */
342     retval = USARTx_SetDataBits(control, &config);
343     if (retval != ARM_DRIVER_OK)
344         return retval;
345 
346     /* UART Parity */
347     retval = USARTx_SetParity(control, &config);
348     if (retval != ARM_DRIVER_OK)
349         return retval;
350 
351     /* USART Stop bits */
352     retval = USARTx_SetStopBits(control, &config);
353     if (retval != ARM_DRIVER_OK)
354         return retval;
355 
356     /* USART Flow Control */
357     USARTx_SetFlowControl(control, &config);
358 
359     Cy_SCB_UART_ClearRxFifo(uart_dev->base);
360     Cy_SCB_UART_ClearTxFifo(uart_dev->base);
361 
362     Cy_SCB_UART_Enable(uart_dev->base);
363 
364     return ARM_DRIVER_OK;
365 }
366 
ARM_USARTx_GetStatus(UARTx_Resources * uart_dev)367 static ARM_USART_STATUS ARM_USARTx_GetStatus(UARTx_Resources* uart_dev)
368 {
369     ARM_USART_STATUS status = {0, 0, 0, 0, 0, 0, 0, 0};
370     return status;
371 }
372 
ARM_USARTx_SetModemControl(UARTx_Resources * uart_dev,ARM_USART_MODEM_CONTROL control)373 static int32_t ARM_USARTx_SetModemControl(UARTx_Resources* uart_dev,
374                                           ARM_USART_MODEM_CONTROL control)
375 {
376     ARG_UNUSED(control);
377     return ARM_DRIVER_ERROR_UNSUPPORTED;
378 }
379 
ARM_USARTx_GetModemStatus(UARTx_Resources * uart_dev)380 static ARM_USART_MODEM_STATUS ARM_USARTx_GetModemStatus(UARTx_Resources* uart_dev)
381 {
382     ARM_USART_MODEM_STATUS modem_status = {0, 0, 0, 0, 0};
383     return modem_status;
384 }
385 
386 /* Per-UART macros */
387 #define DEFINE_UARTX(N) static UARTx_Resources USART##N##_DEV = { \
388     .base = SCB##N, \
389     .tx_nbr_bytes = 0, \
390     .rx_nbr_bytes = 0, \
391     .cb_event = NULL, \
392 }; \
393 \
394 static int32_t ARM_USART##N##_Initialize(ARM_USART_SignalEvent_t cb_event) \
395 { \
396     USART##N##_DEV.cb_event = cb_event; \
397     return ARM_USARTx_Initialize(&USART##N##_DEV); \
398 } \
399 \
400 static int32_t ARM_USART##N##_Uninitialize(void) \
401 { \
402     return ARM_USARTx_Uninitialize(&USART##N##_DEV); \
403 } \
404 \
405 static int32_t ARM_USART##N##_PowerControl(ARM_POWER_STATE state) \
406 { \
407     return ARM_USARTx_PowerControl(&USART##N##_DEV, state); \
408 } \
409  \
410 static int32_t ARM_USART##N##_Send(const void *data, uint32_t num) \
411 { \
412     return ARM_USARTx_Send(&USART##N##_DEV, data, num); \
413 } \
414  \
415 static int32_t ARM_USART##N##_Receive(void *data, uint32_t num) \
416 { \
417     return ARM_USARTx_Receive(&USART##N##_DEV, data, num); \
418 } \
419  \
420 static int32_t ARM_USART##N##_Transfer(const void *data_out, void *data_in, \
421                                    uint32_t num) \
422 { \
423     return ARM_USARTx_Transfer(&USART##N##_DEV, data_out, data_in, num); \
424 } \
425  \
426 static uint32_t ARM_USART##N##_GetTxCount(void) \
427 { \
428     return ARM_USARTx_GetTxCount(&USART##N##_DEV); \
429 } \
430  \
431 static uint32_t ARM_USART##N##_GetRxCount(void) \
432 { \
433     return ARM_USARTx_GetRxCount(&USART##N##_DEV); \
434 } \
435 static int32_t ARM_USART##N##_Control(uint32_t control, uint32_t arg) \
436 { \
437     return ARM_USARTx_Control(&USART##N##_DEV, control, arg); \
438 } \
439  \
440 static ARM_USART_STATUS ARM_USART##N##_GetStatus(void) \
441 { \
442     return ARM_USARTx_GetStatus(&USART##N##_DEV); \
443 } \
444  \
445 static int32_t ARM_USART##N##_SetModemControl(ARM_USART_MODEM_CONTROL control) \
446 { \
447     return ARM_USARTx_SetModemControl(&USART##N##_DEV, control); \
448 } \
449  \
450 static ARM_USART_MODEM_STATUS ARM_USART##N##_GetModemStatus(void) \
451 { \
452     return ARM_USARTx_GetModemStatus(&USART##N##_DEV); \
453 } \
454  \
455 extern ARM_DRIVER_USART Driver_USART##N; \
456 ARM_DRIVER_USART Driver_USART##N = { \
457     ARM_USART_GetVersion, \
458     ARM_USART_GetCapabilities, \
459     ARM_USART##N##_Initialize, \
460     ARM_USART##N##_Uninitialize, \
461     ARM_USART##N##_PowerControl, \
462     ARM_USART##N##_Send, \
463     ARM_USART##N##_Receive, \
464     ARM_USART##N##_Transfer, \
465     ARM_USART##N##_GetTxCount, \
466     ARM_USART##N##_GetRxCount, \
467     ARM_USART##N##_Control, \
468     ARM_USART##N##_GetStatus, \
469     ARM_USART##N##_SetModemControl, \
470     ARM_USART##N##_GetModemStatus \
471 };
472 
473 #if (RTE_USART0)
474 DEFINE_UARTX(0)
475 #endif
476 
477 #if (RTE_USART1)
478 DEFINE_UARTX(1)
479 #endif
480 
481 #if (RTE_USART2)
482 DEFINE_UARTX(2)
483 #endif
484 
485 #if (RTE_USART3)
486 DEFINE_UARTX(3)
487 #endif
488 
489 #if (RTE_USART4)
490 DEFINE_UARTX(4)
491 #endif
492 
493 #if (RTE_USART5)
494 DEFINE_UARTX(5)
495 #endif
496 
497 #if (RTE_USART6)
498 DEFINE_UARTX(6)
499 #endif
500 
501 #if (RTE_USART7)
502 DEFINE_UARTX(7)
503 #endif
504