1 /*
2  * Copyright (c) 2016-2023 Arm Limited. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "uart_cmsdk_drv.h"
18 #include "uart_cmsdk_reg_map.h"
19 
20 #include <stddef.h>
21 
22 /* CTRL Register */
23 #define UART_CMSDK_TX_EN       (1ul << 0)
24 #define UART_CMSDK_RX_EN       (1ul << 1)
25 #define UART_CMSDK_TX_INTR_EN  (1ul << 2)
26 #define UART_CMSDK_RX_INTR_EN  (1ul << 3)
27 
28 /* STATE Register */
29 #define UART_CMSDK_TX_BF  (1ul << 0)
30 #define UART_CMSDK_RX_BF  (1ul << 1)
31 
32 /* INTSTATUS Register */
33 #define UART_CMSDK_TX_INTR  (1ul << 0)
34 #define UART_CMSDK_RX_INTR  (1ul << 1)
35 
36 /* UART state definitions */
37 #define UART_CMSDK_INITIALIZED  (1ul << 0)
38 
uart_cmsdk_init(struct uart_cmsdk_dev_t * dev,uint32_t system_clk)39 enum uart_cmsdk_error_t uart_cmsdk_init(struct uart_cmsdk_dev_t* dev,
40                                     uint32_t system_clk)
41 {
42     struct uart_cmsdk_reg_map_t* p_uart =
43                                  (struct uart_cmsdk_reg_map_t*)dev->cfg->base;
44     if(system_clk == 0) {
45         return UART_CMSDK_ERR_INVALID_ARG;
46     }
47 
48     /* Sets baudrate and system clock */
49     dev->data->system_clk = system_clk;
50     dev->data->baudrate = dev->cfg->default_baudrate;
51 
52     /* Sets baudrate */
53     p_uart->bauddiv = (dev->data->system_clk / dev->cfg->default_baudrate);
54 
55     /* Enables receiver and transmitter */
56     p_uart->ctrl = UART_CMSDK_RX_EN | UART_CMSDK_TX_EN;
57 
58     dev->data->state = UART_CMSDK_INITIALIZED;
59 
60     return UART_CMSDK_ERR_NONE;
61 }
62 
uart_cmsdk_set_baudrate(struct uart_cmsdk_dev_t * dev,uint32_t baudrate)63 enum uart_cmsdk_error_t uart_cmsdk_set_baudrate(struct uart_cmsdk_dev_t* dev,
64                                             uint32_t baudrate)
65 {
66     uint32_t bauddiv;
67     struct uart_cmsdk_reg_map_t* p_uart =
68                                  (struct uart_cmsdk_reg_map_t*)dev->cfg->base;
69 
70     if(baudrate == 0) {
71         return UART_CMSDK_ERR_INVALID_BAUD;
72     }
73 
74     if(!(dev->data->state & UART_CMSDK_INITIALIZED)) {
75         return UART_CMSDK_ERR_NOT_INIT;
76     }
77 
78     bauddiv = (dev->data->system_clk / baudrate);
79 
80     /* Minimum bauddiv value */
81     if(bauddiv < 16) {
82         return UART_CMSDK_ERR_INVALID_BAUD;
83     }
84 
85     /* Sets baudrate */
86     dev->data->baudrate = baudrate;
87     p_uart->bauddiv = bauddiv;
88 
89     return UART_CMSDK_ERR_NONE;
90 }
91 
uart_cmsdk_get_baudrate(struct uart_cmsdk_dev_t * dev)92 uint32_t uart_cmsdk_get_baudrate(struct uart_cmsdk_dev_t* dev)
93 {
94     return dev->data->baudrate;
95 }
96 
uart_cmsdk_set_clock(struct uart_cmsdk_dev_t * dev,uint32_t system_clk)97 enum uart_cmsdk_error_t uart_cmsdk_set_clock(struct uart_cmsdk_dev_t* dev,
98                                          uint32_t system_clk)
99 {
100     struct uart_cmsdk_reg_map_t* p_uart =
101                                  (struct uart_cmsdk_reg_map_t*)dev->cfg->base;
102 
103     if(system_clk == 0) {
104         return UART_CMSDK_ERR_INVALID_ARG;
105     }
106 
107     if(!(dev->data->state & UART_CMSDK_INITIALIZED)) {
108         return UART_CMSDK_ERR_NOT_INIT;
109     }
110 
111     /* Sets system clock */
112     dev->data->system_clk = system_clk;
113 
114     /* Updates baudrate divider */
115     p_uart->bauddiv = (dev->data->system_clk / dev->data->baudrate);
116 
117     /* Enables receiver and transmitter */
118     return UART_CMSDK_ERR_NONE;
119 }
120 
uart_cmsdk_read(struct uart_cmsdk_dev_t * dev,uint8_t * byte)121 enum uart_cmsdk_error_t uart_cmsdk_read(struct uart_cmsdk_dev_t* dev,
122                                                                  uint8_t* byte)
123 {
124     struct uart_cmsdk_reg_map_t* p_uart =
125                                  (struct uart_cmsdk_reg_map_t*)dev->cfg->base;
126 
127     if(!(p_uart->state & UART_CMSDK_RX_BF)) {
128         return UART_CMSDK_ERR_NOT_READY;
129     }
130 
131     /* Reads data */
132     *byte = (uint8_t)p_uart->data;
133 
134     return UART_CMSDK_ERR_NONE;
135 }
136 
uart_cmsdk_write(struct uart_cmsdk_dev_t * dev,uint8_t byte)137 enum uart_cmsdk_error_t uart_cmsdk_write(struct uart_cmsdk_dev_t* dev,
138                                                                   uint8_t byte)
139 {
140     struct uart_cmsdk_reg_map_t* p_uart =
141                                  (struct uart_cmsdk_reg_map_t*)dev->cfg->base;
142 
143     if(p_uart->state & UART_CMSDK_TX_BF) {
144         return UART_CMSDK_ERR_NOT_READY;
145     }
146 
147     /* Sends data */
148     p_uart->data = byte;
149 
150     return UART_CMSDK_ERR_NONE;
151 }
152 
uart_cmsdk_irq_tx_enable(struct uart_cmsdk_dev_t * dev)153 enum uart_cmsdk_error_t uart_cmsdk_irq_tx_enable(struct uart_cmsdk_dev_t* dev)
154 {
155     struct uart_cmsdk_reg_map_t* p_uart =
156                                  (struct uart_cmsdk_reg_map_t*)dev->cfg->base;
157 
158     if(!(dev->data->state & UART_CMSDK_INITIALIZED)) {
159         return UART_CMSDK_ERR_NOT_INIT;
160     }
161 
162     p_uart->ctrl |= UART_CMSDK_TX_INTR_EN;
163 
164     return UART_CMSDK_ERR_NONE;
165 }
166 
uart_cmsdk_irq_tx_disable(struct uart_cmsdk_dev_t * dev)167 void uart_cmsdk_irq_tx_disable(struct uart_cmsdk_dev_t* dev)
168 {
169     struct uart_cmsdk_reg_map_t* p_uart =
170                                  (struct uart_cmsdk_reg_map_t*)dev->cfg->base;
171 
172     if(dev->data->state & UART_CMSDK_INITIALIZED ) {
173         p_uart->ctrl &= ~UART_CMSDK_TX_INTR_EN;
174     }
175 }
176 
uart_cmsdk_tx_ready(struct uart_cmsdk_dev_t * dev)177 uint32_t uart_cmsdk_tx_ready(struct uart_cmsdk_dev_t* dev)
178 {
179     struct uart_cmsdk_reg_map_t* p_uart =
180                                  (struct uart_cmsdk_reg_map_t*)dev->cfg->base;
181 
182     if(!(dev->data->state & UART_CMSDK_INITIALIZED)) {
183         return 0;
184     }
185 
186     return !(p_uart->state & UART_CMSDK_TX_BF);
187 }
188 
uart_cmsdk_irq_rx_enable(struct uart_cmsdk_dev_t * dev)189 enum uart_cmsdk_error_t uart_cmsdk_irq_rx_enable(struct uart_cmsdk_dev_t* dev)
190 {
191     struct uart_cmsdk_reg_map_t* p_uart =
192                                  (struct uart_cmsdk_reg_map_t*)dev->cfg->base;
193 
194     if(!(dev->data->state & UART_CMSDK_INITIALIZED)) {
195         return UART_CMSDK_ERR_NOT_INIT;
196     }
197 
198     p_uart->ctrl |= UART_CMSDK_RX_INTR_EN;
199 
200     return UART_CMSDK_ERR_NONE;
201 }
202 
uart_cmsdk_irq_rx_disable(struct uart_cmsdk_dev_t * dev)203 void uart_cmsdk_irq_rx_disable(struct uart_cmsdk_dev_t* dev)
204 {
205     struct uart_cmsdk_reg_map_t* p_uart =
206                                  (struct uart_cmsdk_reg_map_t*)dev->cfg->base;
207 
208     if(dev->data->state & UART_CMSDK_INITIALIZED) {
209         p_uart->ctrl &= ~UART_CMSDK_RX_INTR_EN;
210     }
211 }
212 
uart_cmsdk_rx_ready(struct uart_cmsdk_dev_t * dev)213 uint32_t uart_cmsdk_rx_ready(struct uart_cmsdk_dev_t* dev)
214 {
215     struct uart_cmsdk_reg_map_t* p_uart =
216                                   (struct uart_cmsdk_reg_map_t*)dev->cfg->base;
217 
218     if(!(dev->data->state & UART_CMSDK_INITIALIZED)) {
219         return 0;
220     }
221 
222     return (p_uart->state & UART_CMSDK_RX_BF);
223 }
224 
uart_cmsdk_clear_interrupt(struct uart_cmsdk_dev_t * dev,enum uart_cmsdk_irq_t irq)225 void uart_cmsdk_clear_interrupt(struct uart_cmsdk_dev_t* dev,
226                               enum uart_cmsdk_irq_t irq)
227 {
228     struct uart_cmsdk_reg_map_t* p_uart =
229                                  (struct uart_cmsdk_reg_map_t*)dev->cfg->base;
230 
231     if(dev->data->state & UART_CMSDK_INITIALIZED) {
232         /* Clears pending interrupts */
233         switch(irq) {
234         case UART_CMSDK_IRQ_RX:
235             p_uart->intr_reg.intrclear = UART_CMSDK_RX_INTR;
236             break;
237         case UART_CMSDK_IRQ_TX:
238             p_uart->intr_reg.intrclear = UART_CMSDK_TX_INTR;
239             break;
240         case UART_CMSDK_IRQ_COMBINED:
241             p_uart->intr_reg.intrclear =
242                                       (UART_CMSDK_RX_INTR | UART_CMSDK_TX_INTR);
243             break;
244         /* default: not defined to force all cases to be handled */
245         }
246     }
247 }
248 
uart_cmsdk_tx_enable(struct uart_cmsdk_dev_t * dev)249 enum uart_cmsdk_error_t uart_cmsdk_tx_enable(struct uart_cmsdk_dev_t* dev)
250 {
251     struct uart_cmsdk_reg_map_t* p_uart =
252                                  (struct uart_cmsdk_reg_map_t*)dev->cfg->base;
253 
254     if (!(dev->data->state & UART_CMSDK_INITIALIZED)) {
255         return UART_CMSDK_ERR_NOT_INIT;
256     }
257 
258     p_uart->ctrl |= UART_CMSDK_TX_EN;
259 
260     return UART_CMSDK_ERR_NONE;
261 }
262 
uart_cmsdk_tx_disable(struct uart_cmsdk_dev_t * dev)263 void uart_cmsdk_tx_disable(struct uart_cmsdk_dev_t* dev)
264 {
265     struct uart_cmsdk_reg_map_t* p_uart =
266                                  (struct uart_cmsdk_reg_map_t*)dev->cfg->base;
267 
268     if (dev->data->state & UART_CMSDK_INITIALIZED ) {
269         p_uart->ctrl &= ~UART_CMSDK_TX_EN;
270     }
271 }
272 
uart_cmsdk_rx_enable(struct uart_cmsdk_dev_t * dev)273 enum uart_cmsdk_error_t uart_cmsdk_rx_enable(struct uart_cmsdk_dev_t* dev)
274 {
275     struct uart_cmsdk_reg_map_t* p_uart =
276                                  (struct uart_cmsdk_reg_map_t*)dev->cfg->base;
277 
278     if (!(dev->data->state & UART_CMSDK_INITIALIZED)) {
279         return UART_CMSDK_ERR_NOT_INIT;
280     }
281 
282     p_uart->ctrl |= UART_CMSDK_RX_EN;
283 
284     return UART_CMSDK_ERR_NONE;
285 }
286 
uart_cmsdk_rx_disable(struct uart_cmsdk_dev_t * dev)287 void uart_cmsdk_rx_disable(struct uart_cmsdk_dev_t* dev)
288 {
289     struct uart_cmsdk_reg_map_t* p_uart =
290                                  (struct uart_cmsdk_reg_map_t*)dev->cfg->base;
291 
292     if (dev->data->state & UART_CMSDK_INITIALIZED ) {
293         p_uart->ctrl &= ~UART_CMSDK_RX_EN;
294     }
295 }
296