1 /*
2 * Copyright (c) 2016-2018 ARM Limited
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include "arm_uart_drv.h"
19
20 #include <stddef.h>
21
22 /* UART register map structure */
23 struct _arm_uart_reg_map_t {
24 volatile uint32_t data; /* Offset: 0x000 (R/W) data register */
25 volatile uint32_t state; /* Offset: 0x004 (R/W) status register */
26 volatile uint32_t ctrl; /* Offset: 0x008 (R/W) control register */
27 union {
28 volatile uint32_t intrstatus; /* Offset: 0x00c (R/ ) interrupt status
29 * register */
30 volatile uint32_t intrclear; /* Offset: 0x00c ( /W) interrupt clear
31 * register */
32 }intr_reg;
33 volatile uint32_t bauddiv; /* Offset: 0x010 (R/W) Baudrate divider
34 * register */
35 };
36
37 /* CTRL Register */
38 #define ARM_UART_TX_EN (1ul << 0)
39 #define ARM_UART_RX_EN (1ul << 1)
40 #define ARM_UART_TX_INTR_EN (1ul << 2)
41 #define ARM_UART_RX_INTR_EN (1ul << 3)
42
43 /* STATE Register */
44 #define ARM_UART_TX_BF (1ul << 0)
45 #define ARM_UART_RX_BF (1ul << 1)
46
47 /* INTSTATUS Register */
48 #define ARM_UART_TX_INTR (1ul << 0)
49 #define ARM_UART_RX_INTR (1ul << 1)
50
51 /* UART state definitions */
52 #define ARM_UART_INITIALIZED (1ul << 0)
53
arm_uart_init(struct arm_uart_dev_t * dev,uint32_t system_clk)54 enum arm_uart_error_t arm_uart_init(struct arm_uart_dev_t* dev,
55 uint32_t system_clk)
56 {
57 struct _arm_uart_reg_map_t* p_uart =
58 (struct _arm_uart_reg_map_t*)dev->cfg->base;
59 if(system_clk == 0) {
60 return ARM_UART_ERR_INVALID_ARG;
61 }
62
63 /* Sets baudrate and system clock */
64 dev->data->system_clk = system_clk;
65 dev->data->baudrate = dev->cfg->default_baudrate;
66
67 /* Sets baudrate */
68 p_uart->bauddiv = (dev->data->system_clk / dev->cfg->default_baudrate);
69
70 /* Enables receiver and transmitter */
71 p_uart->ctrl = ARM_UART_RX_EN | ARM_UART_TX_EN;
72
73 dev->data->state = ARM_UART_INITIALIZED;
74
75 return ARM_UART_ERR_NONE;
76 }
77
arm_uart_set_baudrate(struct arm_uart_dev_t * dev,uint32_t baudrate)78 enum arm_uart_error_t arm_uart_set_baudrate(struct arm_uart_dev_t* dev,
79 uint32_t baudrate)
80 {
81 uint32_t bauddiv;
82 struct _arm_uart_reg_map_t* p_uart =
83 (struct _arm_uart_reg_map_t*)dev->cfg->base;
84
85 if(baudrate == 0) {
86 return ARM_UART_ERR_INVALID_BAUD;
87 }
88
89 if(!(dev->data->state & ARM_UART_INITIALIZED)) {
90 return ARM_UART_ERR_NOT_INIT;
91 }
92
93 /* Sets baudrate */
94 bauddiv = (dev->data->system_clk / baudrate);
95 dev->data->baudrate = baudrate;
96
97 /* Minimum bauddiv value */
98 if(bauddiv < 16) {
99 return ARM_UART_ERR_INVALID_BAUD;
100 }
101
102 p_uart->bauddiv = bauddiv;
103
104 return ARM_UART_ERR_NONE;
105 }
106
arm_uart_get_baudrate(struct arm_uart_dev_t * dev)107 uint32_t arm_uart_get_baudrate(struct arm_uart_dev_t* dev)
108 {
109 return dev->data->baudrate;
110 }
111
arm_uart_set_clock(struct arm_uart_dev_t * dev,uint32_t system_clk)112 enum arm_uart_error_t arm_uart_set_clock(struct arm_uart_dev_t* dev,
113 uint32_t system_clk)
114 {
115 struct _arm_uart_reg_map_t* p_uart =
116 (struct _arm_uart_reg_map_t*)dev->cfg->base;
117
118 if(system_clk == 0) {
119 return ARM_UART_ERR_INVALID_ARG;
120 }
121
122 if(!(dev->data->state & ARM_UART_INITIALIZED)) {
123 return ARM_UART_ERR_NOT_INIT;
124 }
125
126 /* Sets system clock */
127 dev->data->system_clk = system_clk;
128
129 /* Updates baudrate divider */
130 p_uart->bauddiv = (dev->data->system_clk / dev->data->baudrate);
131
132 /* Enables receiver and transmitter */
133 return ARM_UART_ERR_NONE;
134 }
135
arm_uart_read(struct arm_uart_dev_t * dev,uint8_t * byte)136 enum arm_uart_error_t arm_uart_read(struct arm_uart_dev_t* dev, uint8_t* byte)
137 {
138 struct _arm_uart_reg_map_t* p_uart =
139 (struct _arm_uart_reg_map_t*)dev->cfg->base;
140 if(!(p_uart->state & ARM_UART_RX_BF)) {
141 return ARM_UART_ERR_NOT_READY;
142 }
143
144 /* Reads data */
145 *byte = (uint8_t)p_uart->data;
146
147 return ARM_UART_ERR_NONE;
148 }
149
arm_uart_write(struct arm_uart_dev_t * dev,uint8_t byte)150 enum arm_uart_error_t arm_uart_write(struct arm_uart_dev_t* dev, uint8_t byte)
151 {
152 struct _arm_uart_reg_map_t* p_uart =
153 (struct _arm_uart_reg_map_t*)dev->cfg->base;
154
155 if(p_uart->state & ARM_UART_TX_BF) {
156 return ARM_UART_ERR_NOT_READY;
157 }
158
159 /* Sends data */
160 p_uart->data = byte;
161
162 return ARM_UART_ERR_NONE;
163 }
164
arm_uart_irq_tx_enable(struct arm_uart_dev_t * dev)165 enum arm_uart_error_t arm_uart_irq_tx_enable(struct arm_uart_dev_t* dev)
166 {
167 struct _arm_uart_reg_map_t* p_uart =
168 (struct _arm_uart_reg_map_t*)dev->cfg->base;
169
170 if(!(dev->data->state & ARM_UART_INITIALIZED)) {
171 return ARM_UART_ERR_NOT_INIT;
172 }
173
174 p_uart->ctrl |= ARM_UART_TX_INTR_EN;
175
176 return ARM_UART_ERR_NONE;
177 }
178
arm_uart_irq_tx_disable(struct arm_uart_dev_t * dev)179 void arm_uart_irq_tx_disable(struct arm_uart_dev_t* dev)
180 {
181 struct _arm_uart_reg_map_t* p_uart =
182 (struct _arm_uart_reg_map_t*)dev->cfg->base;
183
184 if(dev->data->state & ARM_UART_INITIALIZED ) {
185 p_uart->ctrl &= ~ARM_UART_TX_INTR_EN;
186 }
187 }
188
arm_uart_tx_ready(struct arm_uart_dev_t * dev)189 uint32_t arm_uart_tx_ready(struct arm_uart_dev_t* dev)
190 {
191 struct _arm_uart_reg_map_t* p_uart =
192 (struct _arm_uart_reg_map_t*)dev->cfg->base;
193
194 if(!(dev->data->state & ARM_UART_INITIALIZED)) {
195 return 0;
196 }
197
198 return !(p_uart->state & ARM_UART_TX_BF);
199 }
200
arm_uart_irq_rx_enable(struct arm_uart_dev_t * dev)201 enum arm_uart_error_t arm_uart_irq_rx_enable(struct arm_uart_dev_t* dev)
202 {
203 struct _arm_uart_reg_map_t* p_uart =
204 (struct _arm_uart_reg_map_t*)dev->cfg->base;
205
206 if(!(dev->data->state & ARM_UART_INITIALIZED)) {
207 return ARM_UART_ERR_NOT_INIT;
208 }
209
210 p_uart->ctrl |= ARM_UART_RX_INTR_EN;
211
212 return ARM_UART_ERR_NONE;
213 }
214
arm_uart_irq_rx_disable(struct arm_uart_dev_t * dev)215 void arm_uart_irq_rx_disable(struct arm_uart_dev_t* dev)
216 {
217 struct _arm_uart_reg_map_t* p_uart =
218 (struct _arm_uart_reg_map_t*)dev->cfg->base;
219
220 if(dev->data->state & ARM_UART_INITIALIZED) {
221 p_uart->ctrl &= ~ARM_UART_RX_INTR_EN;
222 }
223 }
224
arm_uart_rx_ready(struct arm_uart_dev_t * dev)225 uint32_t arm_uart_rx_ready(struct arm_uart_dev_t* dev)
226 {
227 struct _arm_uart_reg_map_t* p_uart =
228 (struct _arm_uart_reg_map_t*)dev->cfg->base;
229
230 if(!(dev->data->state & ARM_UART_INITIALIZED)) {
231 return 0;
232 }
233
234 return (p_uart->state & ARM_UART_RX_BF);
235 }
236
arm_uart_clear_interrupt(struct arm_uart_dev_t * dev,enum arm_uart_irq_t irq)237 void arm_uart_clear_interrupt(struct arm_uart_dev_t* dev,
238 enum arm_uart_irq_t irq)
239 {
240 struct _arm_uart_reg_map_t* p_uart =
241 (struct _arm_uart_reg_map_t*)dev->cfg->base;
242
243 if(dev->data->state & ARM_UART_INITIALIZED) {
244 /* Clears pending interrupts */
245 switch(irq) {
246 case ARM_UART_IRQ_RX:
247 p_uart->intr_reg.intrclear = ARM_UART_RX_INTR;
248 break;
249 case ARM_UART_IRQ_TX:
250 p_uart->intr_reg.intrclear = ARM_UART_TX_INTR;
251 break;
252 case ARM_UART_IRQ_COMBINED:
253 p_uart->intr_reg.intrclear = (ARM_UART_RX_INTR | ARM_UART_TX_INTR);
254 break;
255 case ARM_UART_IRQ_NONE:
256 break;
257 /* default: not defined to force all cases to be handled */
258 }
259 }
260 }
261
arm_uart_get_interrupt_status(struct arm_uart_dev_t * dev)262 enum arm_uart_irq_t arm_uart_get_interrupt_status(struct arm_uart_dev_t* dev)
263 {
264 struct _arm_uart_reg_map_t* p_uart =
265 (struct _arm_uart_reg_map_t*)dev->cfg->base;
266 enum arm_uart_irq_t intrstatus = ARM_UART_IRQ_NONE;
267
268
269 if(dev->data->state & ARM_UART_INITIALIZED) {
270 switch(p_uart->intr_reg.intrstatus) {
271 case ARM_UART_TX_INTR:
272 intrstatus = ARM_UART_IRQ_TX;
273 break;
274 case ARM_UART_RX_INTR:
275 intrstatus = ARM_UART_IRQ_RX;
276 break;
277 case ARM_UART_TX_INTR | ARM_UART_RX_INTR:
278 intrstatus = ARM_UART_IRQ_COMBINED;
279 break;
280 default:
281 break;
282 }
283 }
284
285 return intrstatus;
286 }