xref: /rk3399_ARM-atf/plat/mediatek/drivers/uart/uart.c (revision 3374752fc15f173bb059cd8732e2119989c1504c)
1*3374752fSBo-Chen Chen /*
2*3374752fSBo-Chen Chen  * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
3*3374752fSBo-Chen Chen  *
4*3374752fSBo-Chen Chen  * SPDX-License-Identifier: BSD-3-Clause
5*3374752fSBo-Chen Chen  */
6*3374752fSBo-Chen Chen 
7*3374752fSBo-Chen Chen #include <lib/mmio.h>
8*3374752fSBo-Chen Chen #include <uart.h>
9*3374752fSBo-Chen Chen 
10*3374752fSBo-Chen Chen static struct mt_uart uart_save_addr[DRV_SUPPORT_UART_PORTS];
11*3374752fSBo-Chen Chen 
12*3374752fSBo-Chen Chen static const uint32_t uart_base_addr[DRV_SUPPORT_UART_PORTS] = {
13*3374752fSBo-Chen Chen 	UART0_BASE,
14*3374752fSBo-Chen Chen 	UART1_BASE
15*3374752fSBo-Chen Chen };
16*3374752fSBo-Chen Chen 
17*3374752fSBo-Chen Chen void mt_uart_restore(void)
18*3374752fSBo-Chen Chen {
19*3374752fSBo-Chen Chen 	int uart_idx = UART_PORT0;
20*3374752fSBo-Chen Chen 	struct mt_uart *uart;
21*3374752fSBo-Chen Chen 	unsigned long base;
22*3374752fSBo-Chen Chen 
23*3374752fSBo-Chen Chen 	/* Must NOT print any debug log before UART restore */
24*3374752fSBo-Chen Chen 	for (uart_idx = UART_PORT0; uart_idx < HW_SUPPORT_UART_PORTS;
25*3374752fSBo-Chen Chen 	     uart_idx++) {
26*3374752fSBo-Chen Chen 
27*3374752fSBo-Chen Chen 		uart = &uart_save_addr[uart_idx];
28*3374752fSBo-Chen Chen 		base = uart->base;
29*3374752fSBo-Chen Chen 
30*3374752fSBo-Chen Chen 		mmio_write_32(UART_LCR(base), UART_LCR_MODE_B);
31*3374752fSBo-Chen Chen 		mmio_write_32(UART_EFR(base), uart->registers.efr);
32*3374752fSBo-Chen Chen 		mmio_write_32(UART_LCR(base), uart->registers.lcr);
33*3374752fSBo-Chen Chen 		mmio_write_32(UART_FCR(base), uart->registers.fcr);
34*3374752fSBo-Chen Chen 
35*3374752fSBo-Chen Chen 		/* baudrate */
36*3374752fSBo-Chen Chen 		mmio_write_32(UART_HIGHSPEED(base), uart->registers.highspeed);
37*3374752fSBo-Chen Chen 		mmio_write_32(UART_FRACDIV_L(base), uart->registers.fracdiv_l);
38*3374752fSBo-Chen Chen 		mmio_write_32(UART_FRACDIV_M(base), uart->registers.fracdiv_m);
39*3374752fSBo-Chen Chen 		mmio_write_32(UART_LCR(base),
40*3374752fSBo-Chen Chen 			      uart->registers.lcr | UART_LCR_DLAB);
41*3374752fSBo-Chen Chen 		mmio_write_32(UART_DLL(base), uart->registers.dll);
42*3374752fSBo-Chen Chen 		mmio_write_32(UART_DLH(base), uart->registers.dlh);
43*3374752fSBo-Chen Chen 		mmio_write_32(UART_LCR(base), uart->registers.lcr);
44*3374752fSBo-Chen Chen 		mmio_write_32(UART_SAMPLE_COUNT(base),
45*3374752fSBo-Chen Chen 			      uart->registers.sample_count);
46*3374752fSBo-Chen Chen 		mmio_write_32(UART_SAMPLE_POINT(base),
47*3374752fSBo-Chen Chen 			      uart->registers.sample_point);
48*3374752fSBo-Chen Chen 		mmio_write_32(UART_GUARD(base), uart->registers.guard);
49*3374752fSBo-Chen Chen 
50*3374752fSBo-Chen Chen 		/* flow control */
51*3374752fSBo-Chen Chen 		mmio_write_32(UART_ESCAPE_EN(base), uart->registers.escape_en);
52*3374752fSBo-Chen Chen 		mmio_write_32(UART_MCR(base), uart->registers.mcr);
53*3374752fSBo-Chen Chen 		mmio_write_32(UART_IER(base), uart->registers.ier);
54*3374752fSBo-Chen Chen 		mmio_write_32(UART_SCR(base), uart->registers.scr);
55*3374752fSBo-Chen Chen 	}
56*3374752fSBo-Chen Chen }
57*3374752fSBo-Chen Chen 
58*3374752fSBo-Chen Chen void mt_uart_save(void)
59*3374752fSBo-Chen Chen {
60*3374752fSBo-Chen Chen 	int uart_idx = UART_PORT0;
61*3374752fSBo-Chen Chen 	struct mt_uart *uart;
62*3374752fSBo-Chen Chen 	unsigned long base;
63*3374752fSBo-Chen Chen 
64*3374752fSBo-Chen Chen 	for (uart_idx = UART_PORT0; uart_idx < HW_SUPPORT_UART_PORTS;
65*3374752fSBo-Chen Chen 	     uart_idx++) {
66*3374752fSBo-Chen Chen 
67*3374752fSBo-Chen Chen 		uart_save_addr[uart_idx].base = uart_base_addr[uart_idx];
68*3374752fSBo-Chen Chen 		base = uart_base_addr[uart_idx];
69*3374752fSBo-Chen Chen 		uart = &uart_save_addr[uart_idx];
70*3374752fSBo-Chen Chen 		uart->registers.lcr = mmio_read_32(UART_LCR(base));
71*3374752fSBo-Chen Chen 
72*3374752fSBo-Chen Chen 		mmio_write_32(UART_LCR(base), UART_LCR_MODE_B);
73*3374752fSBo-Chen Chen 		uart->registers.efr = mmio_read_32(UART_EFR(base));
74*3374752fSBo-Chen Chen 		mmio_write_32(UART_LCR(base), uart->registers.lcr);
75*3374752fSBo-Chen Chen 		uart->registers.fcr = mmio_read_32(UART_FCR_RD(base));
76*3374752fSBo-Chen Chen 
77*3374752fSBo-Chen Chen 		/* baudrate */
78*3374752fSBo-Chen Chen 		uart->registers.highspeed = mmio_read_32(UART_HIGHSPEED(base));
79*3374752fSBo-Chen Chen 		uart->registers.fracdiv_l = mmio_read_32(UART_FRACDIV_L(base));
80*3374752fSBo-Chen Chen 		uart->registers.fracdiv_m = mmio_read_32(UART_FRACDIV_M(base));
81*3374752fSBo-Chen Chen 		mmio_write_32(UART_LCR(base),
82*3374752fSBo-Chen Chen 			      uart->registers.lcr | UART_LCR_DLAB);
83*3374752fSBo-Chen Chen 		uart->registers.dll = mmio_read_32(UART_DLL(base));
84*3374752fSBo-Chen Chen 		uart->registers.dlh = mmio_read_32(UART_DLH(base));
85*3374752fSBo-Chen Chen 		mmio_write_32(UART_LCR(base), uart->registers.lcr);
86*3374752fSBo-Chen Chen 		uart->registers.sample_count = mmio_read_32(
87*3374752fSBo-Chen Chen 						UART_SAMPLE_COUNT(base));
88*3374752fSBo-Chen Chen 		uart->registers.sample_point = mmio_read_32(
89*3374752fSBo-Chen Chen 						UART_SAMPLE_POINT(base));
90*3374752fSBo-Chen Chen 		uart->registers.guard = mmio_read_32(UART_GUARD(base));
91*3374752fSBo-Chen Chen 
92*3374752fSBo-Chen Chen 		/* flow control */
93*3374752fSBo-Chen Chen 		uart->registers.escape_en = mmio_read_32(UART_ESCAPE_EN(base));
94*3374752fSBo-Chen Chen 		uart->registers.mcr = mmio_read_32(UART_MCR(base));
95*3374752fSBo-Chen Chen 		uart->registers.ier = mmio_read_32(UART_IER(base));
96*3374752fSBo-Chen Chen 		uart->registers.scr = mmio_read_32(UART_SCR(base));
97*3374752fSBo-Chen Chen 	}
98*3374752fSBo-Chen Chen }
99*3374752fSBo-Chen Chen 
100*3374752fSBo-Chen Chen void mt_console_uart_cg(int on)
101*3374752fSBo-Chen Chen {
102*3374752fSBo-Chen Chen 	if (on == 1) {
103*3374752fSBo-Chen Chen 		mmio_write_32(UART_CLOCK_GATE_CLR, UART0_CLOCK_GATE_BIT);
104*3374752fSBo-Chen Chen 	} else {
105*3374752fSBo-Chen Chen 		mmio_write_32(UART_CLOCK_GATE_SET, UART0_CLOCK_GATE_BIT);
106*3374752fSBo-Chen Chen 	}
107*3374752fSBo-Chen Chen }
108*3374752fSBo-Chen Chen 
109*3374752fSBo-Chen Chen uint32_t mt_console_uart_cg_status(void)
110*3374752fSBo-Chen Chen {
111*3374752fSBo-Chen Chen 	return mmio_read_32(UART_CLOCK_GATE_STA) & UART0_CLOCK_GATE_BIT;
112*3374752fSBo-Chen Chen }
113