1 /*
2  * Copyright (c) 2016-2019 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 
19 #include <stddef.h>
20 
21 /* UART register map structure */
22 struct _uart_cmsdk_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                                         */
30         volatile uint32_t intrclear;   /* Offset: 0x00c ( /W) interrupt clear
31                                         *                     register
32                                         */
33     }intr_reg;
34     volatile uint32_t bauddiv;        /* Offset: 0x010 (R/W) Baudrate divider
35                                        *                     register
36                                        */
37 };
38 
39 /* CTRL Register */
40 #define UART_CMSDK_TX_EN       (1ul << 0)
41 #define UART_CMSDK_RX_EN       (1ul << 1)
42 #define UART_CMSDK_TX_INTR_EN  (1ul << 2)
43 #define UART_CMSDK_RX_INTR_EN  (1ul << 3)
44 
45 /* STATE Register */
46 #define UART_CMSDK_TX_BF  (1ul << 0)
47 #define UART_CMSDK_RX_BF  (1ul << 1)
48 
49 /* INTSTATUS Register */
50 #define UART_CMSDK_TX_INTR  (1ul << 0)
51 #define UART_CMSDK_RX_INTR  (1ul << 1)
52 
53 /* UART state definitions */
54 #define UART_CMSDK_INITIALIZED  (1ul << 0)
55 
uart_cmsdk_init(struct uart_cmsdk_dev_t * dev,uint32_t system_clk)56 enum uart_cmsdk_error_t uart_cmsdk_init(struct uart_cmsdk_dev_t* dev,
57                                     uint32_t system_clk)
58 {
59     struct _uart_cmsdk_reg_map_t* p_uart =
60                                  (struct _uart_cmsdk_reg_map_t*)dev->cfg->base;
61     if(system_clk == 0) {
62         return UART_CMSDK_ERR_INVALID_ARG;
63     }
64 
65     /* Sets baudrate and system clock */
66     dev->data->system_clk = system_clk;
67     dev->data->baudrate = dev->cfg->default_baudrate;
68 
69     /* Sets baudrate */
70     p_uart->bauddiv = (dev->data->system_clk / dev->cfg->default_baudrate);
71 
72     /* Enables receiver and transmitter */
73     p_uart->ctrl = UART_CMSDK_RX_EN | UART_CMSDK_TX_EN;
74 
75     dev->data->state = UART_CMSDK_INITIALIZED;
76 
77     return UART_CMSDK_ERR_NONE;
78 }
79 
uart_cmsdk_set_baudrate(struct uart_cmsdk_dev_t * dev,uint32_t baudrate)80 enum uart_cmsdk_error_t uart_cmsdk_set_baudrate(struct uart_cmsdk_dev_t* dev,
81                                             uint32_t baudrate)
82 {
83     uint32_t bauddiv;
84     struct _uart_cmsdk_reg_map_t* p_uart =
85                                  (struct _uart_cmsdk_reg_map_t*)dev->cfg->base;
86 
87     if(baudrate == 0) {
88         return UART_CMSDK_ERR_INVALID_BAUD;
89     }
90 
91     if(!(dev->data->state & UART_CMSDK_INITIALIZED)) {
92         return UART_CMSDK_ERR_NOT_INIT;
93     }
94 
95     /* Sets baudrate */
96     bauddiv = (dev->data->system_clk / baudrate);
97     dev->data->baudrate = baudrate;
98 
99     /* Minimum bauddiv value */
100     if(bauddiv < 16) {
101         return UART_CMSDK_ERR_INVALID_BAUD;
102     }
103 
104     p_uart->bauddiv = bauddiv;
105 
106     return UART_CMSDK_ERR_NONE;
107 }
108 
uart_cmsdk_get_baudrate(struct uart_cmsdk_dev_t * dev)109 uint32_t uart_cmsdk_get_baudrate(struct uart_cmsdk_dev_t* dev)
110 {
111     return dev->data->baudrate;
112 }
113 
uart_cmsdk_set_clock(struct uart_cmsdk_dev_t * dev,uint32_t system_clk)114 enum uart_cmsdk_error_t uart_cmsdk_set_clock(struct uart_cmsdk_dev_t* dev,
115                                          uint32_t system_clk)
116 {
117     struct _uart_cmsdk_reg_map_t* p_uart =
118                                  (struct _uart_cmsdk_reg_map_t*)dev->cfg->base;
119 
120     if(system_clk == 0) {
121         return UART_CMSDK_ERR_INVALID_ARG;
122     }
123 
124     if(!(dev->data->state & UART_CMSDK_INITIALIZED)) {
125         return UART_CMSDK_ERR_NOT_INIT;
126     }
127 
128     /* Sets system clock */
129     dev->data->system_clk = system_clk;
130 
131     /* Updates baudrate divider */
132     p_uart->bauddiv = (dev->data->system_clk / dev->data->baudrate);
133 
134     /* Enables receiver and transmitter */
135     return UART_CMSDK_ERR_NONE;
136 }
137 
uart_cmsdk_read(struct uart_cmsdk_dev_t * dev,uint8_t * byte)138 enum uart_cmsdk_error_t uart_cmsdk_read(struct uart_cmsdk_dev_t* dev,
139                                                                  uint8_t* byte)
140 {
141     struct _uart_cmsdk_reg_map_t* p_uart =
142                                  (struct _uart_cmsdk_reg_map_t*)dev->cfg->base;
143 
144     if(!(p_uart->state & UART_CMSDK_RX_BF)) {
145         return UART_CMSDK_ERR_NOT_READY;
146     }
147 
148     /* Reads data */
149     *byte = (uint8_t)p_uart->data;
150 
151     return UART_CMSDK_ERR_NONE;
152 }
153 
uart_cmsdk_write(struct uart_cmsdk_dev_t * dev,uint8_t byte)154 enum uart_cmsdk_error_t uart_cmsdk_write(struct uart_cmsdk_dev_t* dev,
155                                                                   uint8_t byte)
156 {
157     struct _uart_cmsdk_reg_map_t* p_uart =
158                                  (struct _uart_cmsdk_reg_map_t*)dev->cfg->base;
159 
160     if(p_uart->state & UART_CMSDK_TX_BF) {
161         return UART_CMSDK_ERR_NOT_READY;
162     }
163 
164     /* Sends data */
165     p_uart->data = byte;
166 
167     return UART_CMSDK_ERR_NONE;
168 }
169 
uart_cmsdk_irq_tx_enable(struct uart_cmsdk_dev_t * dev)170 enum uart_cmsdk_error_t uart_cmsdk_irq_tx_enable(struct uart_cmsdk_dev_t* dev)
171 {
172     struct _uart_cmsdk_reg_map_t* p_uart =
173                                  (struct _uart_cmsdk_reg_map_t*)dev->cfg->base;
174 
175     if(!(dev->data->state & UART_CMSDK_INITIALIZED)) {
176         return UART_CMSDK_ERR_NOT_INIT;
177     }
178 
179     p_uart->ctrl |= UART_CMSDK_TX_INTR_EN;
180 
181     return UART_CMSDK_ERR_NONE;
182 }
183 
uart_cmsdk_irq_tx_disable(struct uart_cmsdk_dev_t * dev)184 void uart_cmsdk_irq_tx_disable(struct uart_cmsdk_dev_t* dev)
185 {
186     struct _uart_cmsdk_reg_map_t* p_uart =
187                                  (struct _uart_cmsdk_reg_map_t*)dev->cfg->base;
188 
189     if(dev->data->state & UART_CMSDK_INITIALIZED ) {
190         p_uart->ctrl &= ~UART_CMSDK_TX_INTR_EN;
191     }
192 }
193 
uart_cmsdk_tx_ready(struct uart_cmsdk_dev_t * dev)194 uint32_t uart_cmsdk_tx_ready(struct uart_cmsdk_dev_t* dev)
195 {
196     struct _uart_cmsdk_reg_map_t* p_uart =
197                                  (struct _uart_cmsdk_reg_map_t*)dev->cfg->base;
198 
199     if(!(dev->data->state & UART_CMSDK_INITIALIZED)) {
200         return 0;
201     }
202 
203     return !(p_uart->state & UART_CMSDK_TX_BF);
204 }
205 
uart_cmsdk_irq_rx_enable(struct uart_cmsdk_dev_t * dev)206 enum uart_cmsdk_error_t uart_cmsdk_irq_rx_enable(struct uart_cmsdk_dev_t* dev)
207 {
208     struct _uart_cmsdk_reg_map_t* p_uart =
209                                  (struct _uart_cmsdk_reg_map_t*)dev->cfg->base;
210 
211     if(!(dev->data->state & UART_CMSDK_INITIALIZED)) {
212         return UART_CMSDK_ERR_NOT_INIT;
213     }
214 
215     p_uart->ctrl |= UART_CMSDK_RX_INTR_EN;
216 
217     return UART_CMSDK_ERR_NONE;
218 }
219 
uart_cmsdk_irq_rx_disable(struct uart_cmsdk_dev_t * dev)220 void uart_cmsdk_irq_rx_disable(struct uart_cmsdk_dev_t* dev)
221 {
222     struct _uart_cmsdk_reg_map_t* p_uart =
223                                  (struct _uart_cmsdk_reg_map_t*)dev->cfg->base;
224 
225     if(dev->data->state & UART_CMSDK_INITIALIZED) {
226         p_uart->ctrl &= ~UART_CMSDK_RX_INTR_EN;
227     }
228 }
229 
uart_cmsdk_rx_ready(struct uart_cmsdk_dev_t * dev)230 uint32_t uart_cmsdk_rx_ready(struct uart_cmsdk_dev_t* dev)
231 {
232     struct _uart_cmsdk_reg_map_t* p_uart =
233                                   (struct _uart_cmsdk_reg_map_t*)dev->cfg->base;
234 
235     if(!(dev->data->state & UART_CMSDK_INITIALIZED)) {
236         return 0;
237     }
238 
239     return (p_uart->state & UART_CMSDK_RX_BF);
240 }
241 
uart_cmsdk_clear_interrupt(struct uart_cmsdk_dev_t * dev,enum uart_cmsdk_irq_t irq)242 void uart_cmsdk_clear_interrupt(struct uart_cmsdk_dev_t* dev,
243                               enum uart_cmsdk_irq_t irq)
244 {
245     struct _uart_cmsdk_reg_map_t* p_uart =
246                                  (struct _uart_cmsdk_reg_map_t*)dev->cfg->base;
247 
248     if(dev->data->state & UART_CMSDK_INITIALIZED) {
249         /* Clears pending interrupts */
250         switch(irq) {
251         case UART_CMSDK_IRQ_RX:
252             p_uart->intr_reg.intrclear = UART_CMSDK_RX_INTR;
253             break;
254         case UART_CMSDK_IRQ_TX:
255             p_uart->intr_reg.intrclear = UART_CMSDK_TX_INTR;
256             break;
257         case UART_CMSDK_IRQ_COMBINED:
258             p_uart->intr_reg.intrclear =
259                                       (UART_CMSDK_RX_INTR | UART_CMSDK_TX_INTR);
260             break;
261         /* default: not defined to force all cases to be handled */
262         }
263     }
264 }
265