• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }