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