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