1 /*
2  * Copyright 2024 Microchip Technology Inc. and its subsidiaries.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <stddef.h>
7 #include <stdint.h>
8 
9 #include <device_mec5.h>
10 #include "mec_pcfg.h"
11 #include "mec_defs.h"
12 #include "mec_ecia_api.h"
13 #include "mec_pcr_api.h"
14 #include "mec_uart_api.h"
15 #include "mec_retval.h"
16 
17 #define MEC_UART_INT_CLK_0 1843200u
18 #define MEC_UART_INT_CLK_1 48000000u
19 
20 struct mec_uart_info {
21     uintptr_t base_addr;
22     uint32_t devi;
23     uint16_t pcr_id;
24 };
25 
26 #define MEC_UART0_ECIA_INFO MEC5_ECIA_INFO(15, 0, 7, 40)
27 #define MEC_UART1_ECIA_INFO MEC5_ECIA_INFO(15, 1, 7, 41)
28 #define MEC_UART2_ECIA_INFO MEC5_ECIA_INFO(15, 25, 7, 183)
29 #define MEC_UART3_ECIA_INFO MEC5_ECIA_INFO(15, 26, 7, 184)
30 
31 static const struct mec_uart_info uart_instances[MEC5_UART_INSTANCES] = {
32     {MEC_UART0_BASE, MEC_UART0_ECIA_INFO, MEC_PCR_UART0 },
33     {MEC_UART1_BASE, MEC_UART1_ECIA_INFO, MEC_PCR_UART1 },
34 #if MEC5_UART_INSTANCES == 4
35     {MEC_UART2_BASE, MEC_UART2_ECIA_INFO, MEC_PCR_UART2 },
36     {MEC_UART3_BASE, MEC_UART3_ECIA_INFO, MEC_PCR_UART3 },
37 #endif
38 };
39 
40 static const uint8_t uart_word_len_tbl[MEC_UART_WORD_LEN_MAX] = {
41     (MEC_UART_LCR_WORD_LEN_5BITS << MEC_UART_LCR_WORD_LEN_Pos),
42     (MEC_UART_LCR_WORD_LEN_6BITS << MEC_UART_LCR_WORD_LEN_Pos),
43     (MEC_UART_LCR_WORD_LEN_7BITS << MEC_UART_LCR_WORD_LEN_Pos),
44     (MEC_UART_LCR_WORD_LEN_8BITS << MEC_UART_LCR_WORD_LEN_Pos),
45 };
46 
47 #define MEC5_UART_ODD_PARITY_REG_VAL (MEC_UART_LCR_PARITY_SEL_ODD << MEC_UART_LCR_PARITY_SEL_Pos)
48 #define MEC5_UART_EVEN_PARITY_REG_VAL (MEC_UART_LCR_PARITY_SEL_EVEN << MEC_UART_LCR_PARITY_SEL_Pos)
49 #define MEC5_UART_MARK_PARITY_REG_VAL (MEC_UART_LCR_PARITY_SEL_MARK << MEC_UART_LCR_PARITY_SEL_Pos)
50 #define MEC5_UART_SPACE_PARITY_REG_VAL \
51     (MEC_UART_LCR_PARITY_SEL_SPACE << MEC_UART_LCR_PARITY_SEL_Pos)
52 
53 static const uint8_t uart_parity_tbl[MEC_UART_PARITY_MAX] = {
54     0u,
55     (MEC_BIT(MEC_UART_LCR_PARITY_Pos) | MEC5_UART_ODD_PARITY_REG_VAL),
56     (MEC_BIT(MEC_UART_LCR_PARITY_Pos) | MEC5_UART_EVEN_PARITY_REG_VAL),
57     (MEC_BIT(MEC_UART_LCR_PARITY_Pos) | MEC5_UART_MARK_PARITY_REG_VAL),
58     (MEC_BIT(MEC_UART_LCR_PARITY_Pos) | MEC5_UART_SPACE_PARITY_REG_VAL),
59 };
60 
61 static const uint8_t uart_fcr_tbl[MEC_UART_FIFOS_CFG_MAX] = {
62     0u,
63     (MEC_BIT(MEC_UART_FCR_EXRF_Pos) | (MEC_UART_FCR_RXF_TLVL_1BYTE << MEC_UART_FCR_RXF_TLVL_Pos)),
64     (MEC_BIT(MEC_UART_FCR_EXRF_Pos) | (MEC_UART_FCR_RXF_TLVL_4BYTES << MEC_UART_FCR_RXF_TLVL_Pos)),
65     (MEC_BIT(MEC_UART_FCR_EXRF_Pos) | (MEC_UART_FCR_RXF_TLVL_8BYTES << MEC_UART_FCR_RXF_TLVL_Pos)),
66     (MEC_BIT(MEC_UART_FCR_EXRF_Pos) | (MEC_UART_FCR_RXF_TLVL_14BYTES << MEC_UART_FCR_RXF_TLVL_Pos)),
67 };
68 
get_uart_info(struct mec_uart_regs * regs)69 static struct mec_uart_info const *get_uart_info(struct mec_uart_regs *regs)
70 {
71     for (int i = 0; i < MEC5_UART_INSTANCES; i++) {
72         const struct mec_uart_info *p = &uart_instances[i];
73 
74         if (p->base_addr == (uintptr_t)regs) {
75             return p;
76         }
77     }
78 
79     return NULL;
80 }
81 
uart_baud_divider_get(struct mec_uart_regs * base)82 static uint32_t uart_baud_divider_get(struct mec_uart_regs *base)
83 {
84     uint32_t brdiv = 0u;
85 
86     base->LCR |= MEC_BIT(MEC_UART_LCR_DLAB_Pos);
87     brdiv = base->IER;
88     brdiv <<= 8;
89     brdiv |= base->RXB;
90     base->LCR &= (uint8_t)~MEC_BIT(MEC_UART_LCR_DLAB_Pos);
91 
92     return brdiv;
93 }
94 
uart_prog_fifos(struct mec_uart_regs * base,uint8_t fifo_mode)95 static void uart_prog_fifos(struct mec_uart_regs *base, uint8_t fifo_mode)
96 {
97     uint8_t temp = (MEC_BIT(MEC_UART_FCR_EXRF_Pos) | MEC_BIT(MEC_UART_FCR_CLR_RX_FIFO_Pos)
98                     | MEC_BIT(MEC_UART_FCR_CLR_TX_FIFO_Pos));
99 
100     /* enable and clear both FIFOs */
101     base->FCR = temp;
102     base->SCR = temp;
103 
104     temp = uart_fcr_tbl[fifo_mode];
105 
106     base->FCR = temp;
107     base->SCR = temp;
108 }
109 
mec_hal_uart_tx_fifo_size(struct mec_uart_regs * base)110 int mec_hal_uart_tx_fifo_size(struct mec_uart_regs *base)
111 {
112     const struct mec_uart_info *info = get_uart_info(base);
113 
114     if (!info) {
115         return MEC_RET_ERR_INVAL;
116     }
117 
118     if (base->SCR & MEC_BIT(MEC_UART_FCR_EXRF_Pos)) {
119         return 16;
120     }
121 
122     return 1;
123 }
124 
mec_hal_uart_rx_fifo_size(struct mec_uart_regs * base)125 int mec_hal_uart_rx_fifo_size(struct mec_uart_regs *base)
126 {
127     return mec_hal_uart_tx_fifo_size(base);
128 }
129 
130 /* Get the UART's source clock frequency.
131  * @return 0 normal return, clock_freq filled in with UART BAUD clock input
132  * frequency. If an external frequency was configured the clock_freq filled
133  * with 0. Non-zero return is an error due to bad UART base address or clock_freq
134  * parameter is a NULL pointer.
135  */
mec_hal_uart_clock_freq_get(struct mec_uart_regs * base,uint32_t * clock_freq)136 int mec_hal_uart_clock_freq_get(struct mec_uart_regs *base, uint32_t *clock_freq)
137 {
138     const struct mec_uart_info *info = get_uart_info(base);
139     uint32_t brdiv = 0u;
140 
141     if (!info || !clock_freq) {
142         return MEC_RET_ERR_INVAL;
143     }
144 
145     if (base->CFGS & MEC_BIT(MEC_UART_CFGS_CLK_SRC_EXT_Pos)) {
146         *clock_freq = 0u; /* external, we don't know */
147         return MEC_RET_OK;
148     }
149 
150     brdiv = uart_baud_divider_get(base);
151     if (brdiv & MEC_BIT(15)) {
152         *clock_freq = MEC_UART_INT_CLK_1;
153     } else {
154         *clock_freq = MEC_UART_INT_CLK_0;
155     }
156 
157     return MEC_RET_OK;
158 }
159 
mec_hal_uart_parity_set(struct mec_uart_regs * base,uint8_t parity)160 int mec_hal_uart_parity_set(struct mec_uart_regs *base, uint8_t parity)
161 {
162     const struct mec_uart_info *info = get_uart_info(base);
163     uint8_t val;
164 
165     if (!info || (parity >= MEC_UART_PARITY_MAX)) {
166         return MEC_RET_ERR_INVAL;
167     }
168 
169     val = uart_parity_tbl[parity];
170 
171     base->LSR = (base->LSR & (uint8_t)~(MEC_UART_LCR_PARITY_Msk | MEC_UART_LCR_PARITY_SEL_Msk))
172                 | val;
173 
174     return MEC_RET_OK;
175 }
176 
mec_hal_uart_parity_get(struct mec_uart_regs * base,uint8_t * parity)177 int mec_hal_uart_parity_get(struct mec_uart_regs *base, uint8_t *parity)
178 {
179     const struct mec_uart_info *info = get_uart_info(base);
180     uint8_t i, reg_val;
181 
182     if (!info || !parity) {
183         return MEC_RET_ERR_INVAL;
184     }
185 
186     reg_val = base->LCR & (MEC_UART_LCR_PARITY_Msk | MEC_UART_LCR_PARITY_SEL_Msk);
187 
188     for (i = 0; i < MEC_UART_PARITY_MAX; i++) {
189         if (reg_val == uart_parity_tbl[i]) {
190             *parity = i;
191             return MEC_RET_OK;
192         }
193     }
194 
195     return MEC_RET_ERR_INVAL;
196 }
197 
mec_hal_uart_word_len_set(struct mec_uart_regs * base,uint8_t word_len)198 int mec_hal_uart_word_len_set(struct mec_uart_regs *base, uint8_t word_len)
199 {
200     const struct mec_uart_info *info = get_uart_info(base);
201     uint8_t val;
202 
203     if (!info || (word_len >= MEC_UART_WORD_LEN_MAX)) {
204         return MEC_RET_ERR_INVAL;
205     }
206 
207     val = uart_word_len_tbl[word_len];
208 
209     base->LCR = (base->LCR & (uint8_t)~MEC_UART_LCR_WORD_LEN_Msk) | val;
210 
211     return MEC_RET_OK;
212 }
213 
mec_hal_uart_word_len_get(struct mec_uart_regs * base,uint8_t * word_len)214 int mec_hal_uart_word_len_get(struct mec_uart_regs *base, uint8_t *word_len)
215 {
216     const struct mec_uart_info *info = get_uart_info(base);
217     uint8_t temp = 0u;
218 
219     if (!info || !word_len) {
220         return MEC_RET_ERR_INVAL;
221     }
222 
223     temp = base->LCR & MEC_UART_LCR_WORD_LEN_Msk;
224     for (uint8_t i = 0; i < MEC_UART_WORD_LEN_MAX; i++) {
225         if (uart_word_len_tbl[i] == temp) {
226             *word_len = i;
227             return MEC_RET_OK;
228         }
229     }
230 
231     return MEC_RET_ERR_INVAL;
232 }
233 
234 /* Configure the number of stop bit per word.
235  * NOTE: if word length is 5 bits and 2 stop bits are selected the
236  * 16550 hardware will actually use 1.5 stop bits.
237  */
mec_hal_uart_stop_bits_set(struct mec_uart_regs * base,uint8_t stop_bits)238 int mec_hal_uart_stop_bits_set(struct mec_uart_regs *base, uint8_t stop_bits)
239 {
240     const struct mec_uart_info *info = get_uart_info(base);
241 
242     if (!info || (stop_bits >= MEC_UART_STOP_BITS_MAX)) {
243         return MEC_RET_ERR_INVAL;
244     }
245 
246     if (stop_bits == MEC_UART_STOP_BITS_2) {
247         base->LCR |= MEC_BIT(MEC_UART_LCR_STOP_BITS_Pos);
248     } else {
249         base->LCR &= (uint8_t)~MEC_BIT(MEC_UART_LCR_STOP_BITS_Pos);
250     }
251 
252     return MEC_RET_OK;
253 }
254 
mec_hal_uart_stop_bits_get(struct mec_uart_regs * base,uint8_t * stop_bits)255 int mec_hal_uart_stop_bits_get(struct mec_uart_regs *base, uint8_t *stop_bits)
256 {
257     const struct mec_uart_info *info = get_uart_info(base);
258 
259     if (!info || !stop_bits) {
260         return MEC_RET_ERR_INVAL;
261     }
262 
263     if (base->LCR & MEC_BIT(MEC_UART_LCR_STOP_BITS_Pos)) {
264         *stop_bits = MEC_UART_STOP_BITS_2;
265     } else {
266         *stop_bits |= MEC_UART_STOP_BITS_1;
267     }
268 
269     return MEC_RET_OK;
270 }
271 
mec_hal_uart_fifo_control(struct mec_uart_regs * base,uint8_t fifo_mode)272 int mec_hal_uart_fifo_control(struct mec_uart_regs *base, uint8_t fifo_mode)
273 {
274     const struct mec_uart_info *info = get_uart_info(base);
275 
276     if (!info || (fifo_mode >= MEC_UART_FIFOS_CFG_MAX)) {
277         return MEC_RET_ERR_INVAL;
278     }
279 
280     uart_prog_fifos(base, fifo_mode);
281 
282     return MEC_RET_OK;
283 }
284 
prog_cfg1(struct mec_uart_regs * regs,uint32_t config,uint32_t extclk_hz)285 static void prog_cfg1(struct mec_uart_regs *regs, uint32_t config, uint32_t extclk_hz)
286 {
287     uint32_t temp = 0;
288 
289     if (extclk_hz) {
290         temp = MEC_BIT(MEC_UART_CFGS_CLK_SRC_EXT_Pos);
291     }
292 
293     if (config & MEC_BIT(MEC5_UART_CFG_RESET_HOST_POS)) {
294         temp |= MEC_BIT(MEC_UART_CFGS_RESET_SRC_Pos);
295     }
296 
297     if (config & MEC_BIT(MEC5_UART_CFG_INVERT_LINES_POS)) {
298         temp |= MEC_BIT(MEC_UART_CFGS_POLARITY_Pos);
299     }
300 
301     regs->CFGS = (uint8_t)(temp & 0xffu);
302 }
303 
304 /* BAUD rate = clock_source / (baud_divisor * 16)
305  * baud_divisor = clock_source / (BAUD_rate * 16)
306  */
prog_baud_rate(struct mec_uart_regs * regs,uint32_t baud_rate,uint32_t extclk_hz)307 static int prog_baud_rate(struct mec_uart_regs *regs, uint32_t baud_rate, uint32_t extclk_hz)
308 {
309     uint32_t clksrc = 1843200u; /* 1.8432 MHz internal clock source */
310     uint32_t bdiv = 0;
311     uint16_t brg = 0;
312 
313     if (!baud_rate) {
314         return MEC_RET_ERR_INVAL;
315     }
316 
317     if (extclk_hz) {
318         clksrc = extclk_hz; /* external clock on UART_CLK pin */
319     } else if (baud_rate > 115200u) {
320         clksrc = 48000000u; /* 48MHz internal clock source */
321         brg |= MEC_BIT(15);
322     }
323 
324     bdiv = clksrc / (baud_rate * 16u);
325     /* BAUD rate generator uses b[14:0] for HW divider and b[15] for internal clock select */
326     if (!bdiv || (bdiv > 0x7fffu)) {
327         return MEC_RET_ERR_INVAL;
328     }
329 
330     brg |= (bdiv & 0x7fffu);
331     regs->LCR |= (uint8_t)MEC_BIT(MEC_UART_LCR_DLAB_Pos);
332     regs->TXB = (uint8_t)(brg & 0xffu); /* LSB */
333     regs->IER = (uint8_t)(brg >> 8); /* MSB */
334     regs->LCR &= (uint8_t)~MEC_BIT(MEC_UART_LCR_DLAB_Pos);
335 
336     return MEC_RET_OK;
337 }
338 
prog_word_len(struct mec_uart_regs * regs,uint32_t config)339 static void prog_word_len(struct mec_uart_regs *regs, uint32_t config)
340 {
341     uint32_t val = ((config & MEC5_UART_CFG_WORD_LEN_MSK) >> MEC5_UART_CFG_WORD_LEN_POS);
342 
343     val = (val << MEC_UART_LCR_WORD_LEN_Pos) & MEC_UART_LCR_WORD_LEN_Msk;
344     regs->LCR = (regs->LCR & (uint8_t)~MEC_UART_LCR_WORD_LEN_Msk) | (uint8_t)(val & 0xffu);
345 }
346 
prog_parity(struct mec_uart_regs * regs,uint32_t config)347 static void prog_parity(struct mec_uart_regs *regs, uint32_t config)
348 {
349     uint32_t val = ((config & MEC5_UART_CFG_PARITY_MSK) >> MEC5_UART_CFG_PARITY_POS);
350 
351     val <<= MEC_UART_LCR_PARITY_Pos;
352     regs->LCR = (regs->LCR & 0xc7u) | (uint8_t)(val & 0xffu);
353 }
354 
prog_stop_bits(struct mec_uart_regs * regs,uint32_t config)355 static void prog_stop_bits(struct mec_uart_regs *regs, uint32_t config)
356 {
357     if (config & MEC_BIT(MEC5_UART_CFG_STOP_BITS_POS)) {
358         regs->LCR |= (uint8_t)MEC_BIT(MEC_UART_LCR_STOP_BITS_Pos);
359     } else {
360         regs->LCR &= (uint8_t)~MEC_BIT(MEC_UART_LCR_STOP_BITS_Pos);
361     }
362 }
363 
364 /* NOTE: FCR is write-only */
prog_fifo(struct mec_uart_regs * regs,uint32_t config)365 static void prog_fifo(struct mec_uart_regs *regs, uint32_t config)
366 {
367     uint32_t temp = 0;
368     uint8_t fcr = 0;
369 
370     fcr = (uint8_t)MEC_BIT(MEC_UART_FCR_EXRF_Pos); /* enable FIFO */
371     regs->FCR = fcr;
372     regs->FCR = fcr | MEC_BIT(MEC_UART_FCR_CLR_RX_FIFO_Pos) | MEC_BIT(MEC_UART_FCR_CLR_TX_FIFO_Pos);
373     if (config & MEC_BIT(MEC5_UART_CFG_FIFO_EN_POS)) {
374         temp = (config & MEC5_UART_CFG_RX_FIFO_TRIG_LVL_MSK) >> MEC5_UART_CFG_RX_FIFO_TRIG_LVL_POS;
375         temp = (temp << MEC_UART_FCR_RXF_TLVL_Pos) & MEC_UART_FCR_RXF_TLVL_Msk;
376         fcr |= (uint8_t)(temp & 0xffu);
377     } else {
378         fcr = 0;
379     }
380     regs->FCR = fcr;
381     regs->SCR = fcr; /* save FCR in scratch HW register */
382 }
383 
uart_activate(struct mec_uart_regs * regs,uint8_t enable)384 static void uart_activate(struct mec_uart_regs *regs, uint8_t enable)
385 {
386     if (enable) {
387         regs->ACTV |= (uint8_t)MEC_BIT(MEC_UART_ACTV_CLKS_Pos);
388     } else {
389         regs->ACTV &= (uint8_t)~MEC_BIT(MEC_UART_ACTV_CLKS_Pos);
390     }
391 }
392 
uart_intr_out_enable(struct mec_uart_regs * regs,uint8_t enable)393 static void uart_intr_out_enable(struct mec_uart_regs *regs, uint8_t enable)
394 {
395     if (enable) {
396         regs->MCR |= (uint8_t)MEC_BIT(MEC_UART_MCR_OUT2_Pos);
397     } else {
398         regs->MCR &= (uint8_t)~MEC_BIT(MEC_UART_MCR_OUT2_Pos);
399     }
400 }
401 
mec_hal_uart_power_on(struct mec_uart_regs * regs,uint32_t cfg_flags)402 int mec_hal_uart_power_on(struct mec_uart_regs *regs, uint32_t cfg_flags)
403 {
404     const struct mec_uart_info *info = get_uart_info(regs);
405 
406     if (!info) {
407         return MEC_RET_ERR_INVAL;
408     }
409 
410     mec_hal_pcr_clr_blk_slp_en(info->pcr_id);
411     mec_hal_pcr_blk_reset(info->pcr_id);
412 
413     prog_cfg1(regs, cfg_flags, 0);
414 
415     return 0;
416 }
417 
mec_hal_uart_init(struct mec_uart_regs * regs,uint32_t baud_rate,uint32_t config,uint32_t extclk_hz)418 int mec_hal_uart_init(struct mec_uart_regs *regs, uint32_t baud_rate,
419                       uint32_t config, uint32_t extclk_hz)
420 {
421     const struct mec_uart_info *info = get_uart_info(regs);
422     uint8_t temp = 0;
423     int ret = 0;
424 
425     if (!info || (!baud_rate)) {
426         return MEC_RET_ERR_INVAL;
427     }
428 
429     mec_hal_girq_ctrl(info->devi, 0);
430     mec_hal_pcr_clr_blk_slp_en(info->pcr_id);
431     mec_hal_pcr_blk_reset(info->pcr_id);
432 
433     /* reset source, clock source, line invert */
434     prog_cfg1(regs, config, extclk_hz);
435 
436     /* enable block: allow configuration & operation */
437     uart_activate(regs, 1);
438 
439     /* BAUD rate generator */
440     ret = prog_baud_rate(regs, baud_rate, extclk_hz);
441     if (ret) {
442         return ret;
443     }
444 
445     /* word length */
446     prog_word_len(regs, config);
447 
448     /* parity */
449     prog_parity(regs, config);
450 
451     /* stop bits */
452     prog_stop_bits(regs, config);
453 
454     /* FIFO */
455     prog_fifo(regs, config);
456 
457     /* clear status by reading LSR and MSR. Note, THRE (empty transmit
458      * holding register) status will stay active.
459      */
460     temp = regs->SCR; /* preserve FCR value saved in SCR */
461     regs->SCR = regs->LSR;
462     regs->SCR = regs->RXB;
463     regs->SCR = regs->MSR;
464     regs->SCR = temp;
465 
466     /* interrupt enables */
467     uart_intr_out_enable(regs, 1);
468     mec_hal_girq_clr_src(info->devi);
469     if (config & MEC_BIT(MEC5_UART_CFG_GIRQ_EN_POS)) {
470         mec_hal_girq_ctrl(info->devi, 1);
471     }
472 
473     return MEC_RET_OK;
474 }
475 
mec_hal_uart_activate(struct mec_uart_regs * regs,uint8_t enable)476 int mec_hal_uart_activate(struct mec_uart_regs *regs, uint8_t enable)
477 {
478     if (!regs) {
479         return MEC_RET_ERR_INVAL;
480     }
481 
482     uart_activate(regs, enable);
483 
484     return MEC_RET_OK;
485 }
486 
mec_hal_uart_girq_ctrl(struct mec_uart_regs * regs,uint8_t enable)487 int mec_hal_uart_girq_ctrl(struct mec_uart_regs *regs, uint8_t enable)
488 {
489     const struct mec_uart_info *info = get_uart_info(regs);
490 
491     if (!info) {
492         return MEC_RET_ERR_INVAL;
493     }
494 
495     mec_hal_girq_ctrl(info->devi, enable);
496 
497     return MEC_RET_OK;
498 }
499 
mec_hal_uart_girq_clear(struct mec_uart_regs * regs)500 int mec_hal_uart_girq_clear(struct mec_uart_regs *regs)
501 {
502     const struct mec_uart_info *info = get_uart_info(regs);
503 
504     if (!info) {
505         return MEC_RET_ERR_INVAL;
506     }
507 
508     mec_hal_girq_clr_src(info->devi);
509 
510     return MEC_RET_OK;
511 }
512 
mec_hal_uart_is_girq_status(struct mec_uart_regs * regs)513 bool mec_hal_uart_is_girq_status(struct mec_uart_regs *regs)
514 {
515     const struct mec_uart_info *info = get_uart_info(regs);
516 
517     if (info && mec_hal_girq_src(info->devi)) {
518         return true;
519     }
520 
521     return false;
522 }
523 
mec_hal_uart_is_girq_result(struct mec_uart_regs * regs)524 bool mec_hal_uart_is_girq_result(struct mec_uart_regs *regs)
525 {
526     const struct mec_uart_info *info = get_uart_info(regs);
527 
528     if (info && mec_hal_girq_result(info->devi)) {
529         return true;
530     }
531 
532     return false;
533 }
534 
mec_hal_uart_baud_rate_set(struct mec_uart_regs * base,uint32_t baud,uint32_t extclk_hz)535 int mec_hal_uart_baud_rate_set(struct mec_uart_regs *base, uint32_t baud, uint32_t extclk_hz)
536 {
537     const struct mec_uart_info *info = get_uart_info(base);
538     int ret = 0;
539 
540     if (!info || (baud == 0)) {
541         return MEC_RET_ERR_INVAL;
542     }
543 
544     ret = prog_baud_rate(base, baud, extclk_hz);
545 
546     return ret;
547 }
548 
mec_hal_uart_intr_control(struct mec_uart_regs * base,uint8_t enmask)549 int mec_hal_uart_intr_control(struct mec_uart_regs *base, uint8_t enmask)
550 {
551     const struct mec_uart_info *info = get_uart_info(base);
552 
553     if (!info) {
554         return MEC_RET_ERR_INVAL;
555     }
556 
557     base->IER = enmask & (MEC_UART_IER_ERDAI_Msk | MEC_UART_IER_ETHREI_Msk
558                           | MEC_UART_IER_ELSI_Msk | MEC_UART_IER_EMSI_Msk);
559 
560     return MEC_RET_OK;
561 }
562 
563 /* Modify UART interrupt enables.
564  * msk = bit map to modify.
565  * val = new value for modified bits.
566  */
mec_hal_uart_intr_mask(struct mec_uart_regs * base,uint8_t msk,uint8_t val)567 int mec_hal_uart_intr_mask(struct mec_uart_regs *base, uint8_t msk, uint8_t val)
568 {
569     const struct mec_uart_info *info = get_uart_info(base);
570 
571     if (!info) {
572         return MEC_RET_ERR_INVAL;
573     }
574 
575     base->IER = (base->IER & ~msk) | val;
576 
577     return 0;
578 }
579 
mec_hal_uart_raw_status(struct mec_uart_regs * base,enum mec_uart_sts_reg regid,uint8_t * status)580 int mec_hal_uart_raw_status(struct mec_uart_regs *base, enum mec_uart_sts_reg regid,
581                             uint8_t *status)
582 {
583     const struct mec_uart_info *info = get_uart_info(base);
584 
585     if (!info || !status) {
586         return MEC_RET_ERR_INVAL;
587     }
588 
589     switch (regid) {
590     case MEC_UART_STS_REG_IID:
591         *status = base->IIR;
592         break;
593     case MEC_UART_STS_REG_LINE:
594         *status = base->LSR;
595         break;
596     case MEC_UART_STS_REG_MODEM:
597         *status = base->MSR;
598         break;
599     default:
600         return MEC_RET_ERR_INVAL;
601     }
602 
603     return MEC_RET_OK;
604 }
605 
606 /* Get UART pending interrupt status */
mec_hal_uart_pending_status(struct mec_uart_regs * base,enum mec_uart_ipend * ipend)607 int mec_hal_uart_pending_status(struct mec_uart_regs *base, enum mec_uart_ipend *ipend)
608 {
609     const struct mec_uart_info *info = get_uart_info(base);
610     uint8_t iir = 0u;
611 
612     if (!info || !ipend) {
613         return MEC_RET_ERR_INVAL;
614     }
615 
616     iir = base->IIR;
617 
618     if (iir & MEC_BIT(MEC_UART_FCR_EXRF_Pos)) {
619         *ipend = MEC_UART_IPEND_NONE;
620         return MEC_RET_OK;
621     }
622 
623     switch (iir >> 1) {
624     case 3u:
625         *ipend = MEC_UART_IPEND_RX_ERR;
626         break;
627     case 2u:
628     case 6u:
629         *ipend = MEC_UART_IPEND_RX_DATA;
630         break;
631     case 1u:
632         *ipend = MEC_UART_IPEND_TX;
633         break;
634     case 0u:
635         *ipend = MEC_UART_IPEND_MODEM;
636         break;
637     default:
638         *ipend = MEC_UART_IPEND_UNKOWN;
639         break;
640     }
641 
642     return MEC_RET_OK;
643 }
644 
645 /* Return 1 if LSR register indicates RX data is available else return 0 */
mec_hal_uart_is_rx_data(struct mec_uart_regs * base)646 int mec_hal_uart_is_rx_data(struct mec_uart_regs *base)
647 {
648     const struct mec_uart_info *info = get_uart_info(base);
649 
650     if (!info) {
651         return 0;
652     }
653 
654     if (base->LSR & MEC_BIT(MEC_UART_LSR_DRDY_Pos)) {
655         return 1;
656     }
657 
658     return 0;
659 }
660 
661 /* Return 1 if LSR register indicates TX holding/FIFO is empty else return 0 */
mec_hal_uart_is_tx_fifo_empty(struct mec_uart_regs * base)662 int mec_hal_uart_is_tx_fifo_empty(struct mec_uart_regs *base)
663 {
664     const struct mec_uart_info *info = get_uart_info(base);
665 
666     if (!info) {
667         return 0;
668     }
669 
670     if (base->LSR & MEC_BIT(MEC_UART_LSR_THRE_Pos)) {
671         return 1;
672     }
673 
674     return 0;
675 }
676 
677 /* Return 1 if TX shift register is empty which implies FIFO is empty */
mec_hal_uart_is_tx_empty(struct mec_uart_regs * base)678 int mec_hal_uart_is_tx_empty(struct mec_uart_regs *base)
679 {
680     const struct mec_uart_info *info = get_uart_info(base);
681 
682     if (!info) {
683         return 0;
684     }
685 
686     if (base->LSR & MEC_BIT(MEC_UART_LSR_THSE_Pos)) {
687         return 1;
688     }
689 
690     return 0;
691 }
692 
mec_hal_uart_dtr_rts_set(struct mec_uart_regs * base,uint8_t sel_rts,uint8_t pin_state)693 int mec_hal_uart_dtr_rts_set(struct mec_uart_regs *base, uint8_t sel_rts,
694                              uint8_t pin_state)
695 {
696     const struct mec_uart_info *info = get_uart_info(base);
697     uint8_t bitpos = MEC_UART_MCR_DTR_Pos;
698 
699     if (!info) {
700         return MEC_RET_ERR_INVAL;
701     }
702 
703     if (sel_rts) {
704         bitpos = MEC_UART_MCR_RTS_Pos;
705     }
706 
707     if (pin_state) {
708         base->MCR |= MEC_BIT(bitpos);
709     } else {
710         base->MCR &= (uint8_t)~MEC_BIT(bitpos);
711     }
712 
713     return MEC_RET_OK;
714 }
715 
716 /* UART interrupt priorties in the IIR register
717  * If the nIPEND bit is 0 then there is an interrupt b[3:1] indicate the
718  * interrupt source. IIR must be read multiple times until nIPEND -> 1
719  * UART_IIR_ID_RX_LS    Highest priority. Clear by reading LSR
720  * UART_IIR_ID_RX_TMOUT 2nd highest. Clear by reading RX buffer to remove byte.
721  * UART_IIR_ID_RX_DATA  2nd highest. Clear by reading RX buffer.
722  * UART_IIR_ID_THRE 3rd highest. Clear by writing data to TX buffer.
723  * UART_IIR_ID_MSR  Lowest. Clear by reading MSR
724  */
725 
726 /* 16550 style UART only has TX Holding Register Empty status. There is no
727  * HW mechanism to determine the amount of data in the TX FIFO.
728  * This routine writes a byte to the HW TX buffer if the TX Holding Register
729  * is empty else it returns MEC_RET_ERR_BUSY.
730  * SoC's with MEC5_UART_HAS_LSR2_REGISTER defined have a second Line Status
731  * register, LSR2, containing:
732  * bit[0] TX FIFO full (R/W)
733  * b[3:1] Reserved 0
734  * b[7:4] TX FIFO count (R/W) number of bytes in the TX FIFO which have not
735  * been sent.
736  */
mec_hal_uart_tx_byte(struct mec_uart_regs * base,uint8_t data)737 int mec_hal_uart_tx_byte(struct mec_uart_regs *base, uint8_t data)
738 {
739     const struct mec_uart_info *info = get_uart_info(base);
740 
741     if (!info) {
742         return MEC_RET_ERR_INVAL;
743     }
744 
745 #ifdef MEC5_UART_HAS_LSR2_REGISTER
746     if (base->IIR & MEC_UART_IIR_FIFO_STATE_Msk) { /* FIFOs enabled? */
747         if (!(base->LSRB & MEC_BIT(MEC_UART_LSRB_TXF_FULL_STS_Pos))) { /* if not full */
748             base->TXB = data;
749             return MEC_RET_OK;
750         }
751 
752         return MEC_RET_ERR_BUSY;
753     }
754 #endif
755 
756     /* if holding register is empty, we can write data to it */
757     if (base->LSR & MEC_BIT(MEC_UART_LSR_THRE_Pos)) {
758         base->TXB = data;
759         return MEC_RET_OK;
760     }
761 
762     return MEC_RET_ERR_BUSY;
763 }
764 
mec_hal_uart_tx(struct mec_uart_regs * base,const uint8_t * data,size_t datasz)765 int mec_hal_uart_tx(struct mec_uart_regs * base, const uint8_t *data, size_t datasz)
766 {
767     const struct mec_uart_info *info = get_uart_info(base);
768     size_t n = 0u;
769 
770     if (!info) {
771         return MEC_RET_ERR_INVAL;
772     }
773 
774     if (!data || !datasz) {
775         return MEC_RET_OK;
776     }
777 
778 #ifdef MEC5_UART_HAS_LSR2_REGISTER
779     if (base->IIR & MEC_UART_IIR_FIFO_STATE_Msk) { /* FIFOs enabled? */
780         while (n < datasz) {
781             if (!(base->LSRB & MEC_BIT(MEC_UART_LSRB_TXF_FULL_STS_Pos))) {
782                 base->TXB = data[n++];
783             }
784         }
785 
786         return MEC_RET_OK;
787     }
788 #endif
789 
790     while (n < datasz) {
791         if (base->LSR & MEC_BIT(MEC_UART_LSR_THRE_Pos)) {
792             size_t fill_len = datasz - n;
793 
794             if (fill_len > MEC_UART_FIFO_LEN) {
795                 fill_len = MEC_UART_FIFO_LEN;
796             }
797             while (fill_len--) {
798                 base->TXB = data[n];
799                 n++;
800             }
801         }
802     }
803 
804     return MEC_RET_OK;
805 }
806 
mec_hal_uart_rx_byte(struct mec_uart_regs * base,uint8_t * data)807 int mec_hal_uart_rx_byte(struct mec_uart_regs *base, uint8_t *data)
808 {
809     const struct mec_uart_info *info = get_uart_info(base);
810     uint8_t lsr = 0;
811     uint8_t temp = 0;
812 
813     if (!info || !data) {
814         return MEC_RET_ERR_INVAL;
815     }
816 
817     lsr = base->LSR;
818     if (base->LSR & MEC_BIT(MEC_UART_LSR_DRDY_Pos)) {
819         temp = base->RXB;
820         if (data) {
821             *data = temp;
822         }
823         if (lsr & (MEC_BIT(MEC_UART_LSR_OVR_ERR_Pos) | MEC_BIT(MEC_UART_LSR_PAR_ERR_Pos)
824                    | MEC_BIT(MEC_UART_LSR_FR_ERR_Pos))) {
825             return MEC_RET_ERR_BAD_DATA;
826         }
827         return MEC_RET_OK;
828     }
829 
830     return MEC_RET_ERR_NO_DATA;
831 }
832 
833 /* Power management
834  * UART will keep its CLK_REQ signal active even when PCR has asserted SLP_EN.
835  * Deep sleep shutdown of the PLL requires all CLK_REQ signals be inactive.
836  * Save the value of the UART Activate register and clear bit to cause
837  * the block to gate off its clocks and de-assert PCR CLK_REQ.
838  */
839 
840 static uint8_t uart_pm_save_buf[MEC5_UART_INSTANCES];
841 
mec_hal_uart_pm_save_disable(void)842 void mec_hal_uart_pm_save_disable(void)
843 {
844     for (int i = 0; i < MEC5_UART_INSTANCES; i++) {
845         struct mec_uart_regs *regs = (struct mec_uart_regs *)uart_instances[i].base_addr;
846 
847         uart_pm_save_buf[i] = regs->ACTV;
848         regs->ACTV = 0;
849     }
850 }
851 
mec_hal_uart_pm_restore(void)852 void mec_hal_uart_pm_restore(void)
853 {
854     for (int i = 0; i < MEC5_UART_INSTANCES; i++) {
855         struct mec_uart_regs *regs = (struct mec_uart_regs *)uart_instances[i].base_addr;
856 
857         regs->ACTV = uart_pm_save_buf[i];
858     }
859 }
860 
861 /* end mec_uart.c */
862