1 /*
2  * Copyright (c) 2019-2021 Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Licensed under the Apache License, Version 2.0 (the License); you may
7  * not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include "uart.h"
20 #include <stdint.h>
21 #include <stdio.h>
22 
23 #define UART0_BASE 0x49303000
24 #define UART0_BAUDRATE 115200
25 #define SYSTEM_CORE_CLOCK 25000000
26 
27 /*------------- Universal Asynchronous Receiver Transmitter (UART) -----------*/
28 
29 #define __IO volatile
30 #define __I volatile const
31 #define __O volatile
32 
33 typedef struct
34 {
35     __IO uint32_t DATA;  /* Offset: 0x000 (R/W) Data Register    */
36     __IO uint32_t STATE; /* Offset: 0x004 (R/W) Status Register  */
37     __IO uint32_t CTRL;  /* Offset: 0x008 (R/W) Control Register */
38     union
39     {
40         __I uint32_t INTSTATUS; /* Offset: 0x00C (R/ ) Interrupt Status Register */
41         __O uint32_t INTCLEAR;  /* Offset: 0x00C ( /W) Interrupt Clear Register  */
42     };
43     __IO uint32_t BAUDDIV; /* Offset: 0x010 (R/W) Baudrate Divider Register */
44 } CMSDK_UART_TypeDef;
45 
46 #define CMSDK_UART0_BASE UART0_BASE
47 #define CMSDK_UART0 ((CMSDK_UART_TypeDef *)CMSDK_UART0_BASE)
48 #define CMSDK_UART0_BAUDRATE UART0_BAUDRATE
49 
uart_init(void)50 void uart_init(void)
51 {
52     // SystemCoreClock / 9600
53     CMSDK_UART0->BAUDDIV = SYSTEM_CORE_CLOCK / CMSDK_UART0_BAUDRATE;
54 
55     CMSDK_UART0->CTRL = ((1ul << 0) | /* TX enable */
56                          (1ul << 1)); /* RX enable */
57 }
58 
59 // Output a character
uart_putc(unsigned char my_ch)60 unsigned char uart_putc(unsigned char my_ch)
61 {
62     while ((CMSDK_UART0->STATE & 1))
63         ; // Wait if Transmit Holding register is full
64 
65     if (my_ch == '\n')
66     {
67         CMSDK_UART0->DATA = '\r';
68         while ((CMSDK_UART0->STATE & 1))
69             ; // Wait if Transmit Holding register is full
70     }
71 
72     CMSDK_UART0->DATA = my_ch; // write to transmit holding register
73 
74     return (my_ch);
75 }
76 
77 // Get a character
uart_getc(void)78 unsigned char uart_getc(void)
79 {
80     unsigned char my_ch;
81     // unsigned int  cnt;
82 
83     while ((CMSDK_UART0->STATE & 2) == 0) // Wait if Receive Holding register is empty
84     {
85 #if 0
86         cnt = MPS3_FPGAIO->CLK100HZ / 50;
87         if (cnt & 0x8)
88             MPS3_FPGAIO->LED = 0x01 << (cnt & 0x7);
89         else
90             MPS3_FPGAIO->LED = 0x80 >> (cnt & 0x7);
91 #endif
92     }
93 
94     my_ch = CMSDK_UART0->DATA;
95 
96     // Convert CR to LF
97     if (my_ch == '\r')
98         my_ch = '\n';
99 
100     return (my_ch);
101 }
102