1 /*
2  * Copyright (c) 2016-2017 ARM Limited
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 "arm_uart_drv.h"
18 
19 #include <stddef.h>
20 
21 /* UART register map structure */
22 struct _arm_uart_reg_map_t {
23     volatile uint32_t data;   /* Offset: 0x000 (R/W) data register    */
24     volatile uint32_t state;  /* Offset: 0x004 (R/W) status register  */
25     volatile uint32_t ctrl;   /* Offset: 0x008 (R/W) control register */
26     union {
27         volatile uint32_t intrstatus;  /* Offset: 0x00c (R/ ) interrupt status
28                                         *                     register */
29         volatile uint32_t intrclear;   /* Offset: 0x00c ( /W) interrupt clear
30                                         *                     register  */
31     }intr_reg;
32     volatile uint32_t bauddiv;        /* Offset: 0x010 (R/W) Baudrate divider
33                                        *                     register */
34 };
35 
36 /* CTRL Register */
37 #define ARM_UART_TX_EN       (1ul << 0)
38 #define ARM_UART_RX_EN       (1ul << 1)
39 #define ARM_UART_TX_INTR_EN  (1ul << 2)
40 #define ARM_UART_RX_INTR_EN  (1ul << 3)
41 
42 /* STATE Register */
43 #define ARM_UART_TX_BF  (1ul << 0)
44 #define ARM_UART_RX_BF  (1ul << 1)
45 
46 /* INTSTATUS Register */
47 #define ARM_UART_TX_INTR  (1ul << 0)
48 #define ARM_UART_RX_INTR  (1ul << 1)
49 
50 /* UART state definitions */
51 #define ARM_UART_INITIALIZED  (1ul << 0)
52 
arm_uart_init(struct arm_uart_dev_t * dev,uint32_t system_clk)53 enum arm_uart_error_t arm_uart_init(struct arm_uart_dev_t* dev,
54                                     uint32_t system_clk)
55 {
56     struct _arm_uart_reg_map_t* p_uart =
57                                     (struct _arm_uart_reg_map_t*)dev->cfg->base;
58     if(system_clk == 0) {
59         return ARM_UART_ERR_INVALID_ARG;
60     }
61 
62     /* Sets baudrate and system clock */
63     dev->data->system_clk = system_clk;
64     dev->data->baudrate = dev->cfg->default_baudrate;
65 
66     /* Sets baudrate */
67     p_uart->bauddiv = (dev->data->system_clk / dev->cfg->default_baudrate);
68 
69     /* Enables receiver and transmitter */
70     p_uart->ctrl = ARM_UART_RX_EN | ARM_UART_TX_EN;
71 
72     dev->data->state = ARM_UART_INITIALIZED;
73 
74     return ARM_UART_ERR_NONE;
75 }
76 
arm_uart_set_baudrate(struct arm_uart_dev_t * dev,uint32_t baudrate)77 enum arm_uart_error_t arm_uart_set_baudrate(struct arm_uart_dev_t* dev,
78                                             uint32_t baudrate)
79 {
80     uint32_t bauddiv;
81     struct _arm_uart_reg_map_t* p_uart =
82                                     (struct _arm_uart_reg_map_t*)dev->cfg->base;
83 
84     if(baudrate == 0) {
85         return ARM_UART_ERR_INVALID_BAUD;
86     }
87 
88     if(!(dev->data->state & ARM_UART_INITIALIZED)) {
89         return ARM_UART_ERR_NOT_INIT;
90     }
91 
92     /* Sets baudrate */
93     bauddiv = (dev->data->system_clk / baudrate);
94     dev->data->baudrate = baudrate;
95 
96     /* Minimum bauddiv value */
97     if(bauddiv < 16) {
98         return ARM_UART_ERR_INVALID_BAUD;
99     }
100 
101     p_uart->bauddiv = bauddiv;
102 
103     return ARM_UART_ERR_NONE;
104 }
105 
arm_uart_get_baudrate(struct arm_uart_dev_t * dev)106 uint32_t arm_uart_get_baudrate(struct arm_uart_dev_t* dev)
107 {
108     return dev->data->baudrate;
109 }
110 
arm_uart_set_clock(struct arm_uart_dev_t * dev,uint32_t system_clk)111 enum arm_uart_error_t arm_uart_set_clock(struct arm_uart_dev_t* dev,
112                                          uint32_t system_clk)
113 {
114     struct _arm_uart_reg_map_t* p_uart =
115                                     (struct _arm_uart_reg_map_t*)dev->cfg->base;
116 
117     if(system_clk == 0) {
118         return ARM_UART_ERR_INVALID_ARG;
119     }
120 
121     if(!(dev->data->state & ARM_UART_INITIALIZED)) {
122         return ARM_UART_ERR_NOT_INIT;
123     }
124 
125     /* Sets system clock */
126     dev->data->system_clk = system_clk;
127 
128     /* Updates baudrate divider */
129     p_uart->bauddiv = (dev->data->system_clk / dev->data->baudrate);
130 
131     /* Enables receiver and transmitter */
132     return ARM_UART_ERR_NONE;
133 }
134 
arm_uart_read(struct arm_uart_dev_t * dev,uint8_t * byte)135 enum arm_uart_error_t arm_uart_read(struct arm_uart_dev_t* dev, uint8_t* byte)
136 {
137     struct _arm_uart_reg_map_t* p_uart =
138                                     (struct _arm_uart_reg_map_t*)dev->cfg->base;
139 
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         /* default: not defined to force all cases to be handled */
256         }
257     }
258 }
259