aboutsummaryrefslogtreecommitdiff
path: root/plat/mediatek/common/drivers/uart/uart.c
blob: b940eb3396016a175a090ab6b7f707226273412c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/*
 * Copyright (c) 2020, MediaTek Inc. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <lib/mmio.h>
#include <uart.h>

static struct mt_uart uart_save_addr[DRV_SUPPORT_UART_PORTS];

static const uint32_t uart_base_addr[DRV_SUPPORT_UART_PORTS] = {
	UART0_BASE,
	UART1_BASE
};

void mt_uart_restore(void)
{
	int uart_idx = UART_PORT0;
	struct mt_uart *uart;
	unsigned long base;

	/* Must NOT print any debug log before UART restore */
	for (uart_idx = UART_PORT0; uart_idx < HW_SUPPORT_UART_PORTS;
	     uart_idx++) {

		uart = &uart_save_addr[uart_idx];
		base = uart->base;

		mmio_write_32(UART_LCR(base), UART_LCR_MODE_B);
		mmio_write_32(UART_EFR(base), uart->registers.efr);
		mmio_write_32(UART_LCR(base), uart->registers.lcr);
		mmio_write_32(UART_FCR(base), uart->registers.fcr);

		/* baudrate */
		mmio_write_32(UART_HIGHSPEED(base), uart->registers.highspeed);
		mmio_write_32(UART_FRACDIV_L(base), uart->registers.fracdiv_l);
		mmio_write_32(UART_FRACDIV_M(base), uart->registers.fracdiv_m);
		mmio_write_32(UART_LCR(base),
			      uart->registers.lcr | UART_LCR_DLAB);
		mmio_write_32(UART_DLL(base), uart->registers.dll);
		mmio_write_32(UART_DLH(base), uart->registers.dlh);
		mmio_write_32(UART_LCR(base), uart->registers.lcr);
		mmio_write_32(UART_SAMPLE_COUNT(base),
			      uart->registers.sample_count);
		mmio_write_32(UART_SAMPLE_POINT(base),
			      uart->registers.sample_point);
		mmio_write_32(UART_GUARD(base), uart->registers.guard);

		/* flow control */
		mmio_write_32(UART_ESCAPE_EN(base), uart->registers.escape_en);
		mmio_write_32(UART_MCR(base), uart->registers.mcr);
		mmio_write_32(UART_IER(base), uart->registers.ier);
		mmio_write_32(UART_SCR(base), uart->registers.scr);
	}
}

void mt_uart_save(void)
{
	int uart_idx = UART_PORT0;
	struct mt_uart *uart;
	unsigned long base;

	for (uart_idx = UART_PORT0; uart_idx < HW_SUPPORT_UART_PORTS;
	     uart_idx++) {

		uart_save_addr[uart_idx].base = uart_base_addr[uart_idx];
		base = uart_base_addr[uart_idx];
		uart = &uart_save_addr[uart_idx];
		uart->registers.lcr = mmio_read_32(UART_LCR(base));

		mmio_write_32(UART_LCR(base), UART_LCR_MODE_B);
		uart->registers.efr = mmio_read_32(UART_EFR(base));
		mmio_write_32(UART_LCR(base), uart->registers.lcr);
		uart->registers.fcr = mmio_read_32(UART_FCR_RD(base));

		/* baudrate */
		uart->registers.highspeed = mmio_read_32(UART_HIGHSPEED(base));
		uart->registers.fracdiv_l = mmio_read_32(UART_FRACDIV_L(base));
		uart->registers.fracdiv_m = mmio_read_32(UART_FRACDIV_M(base));
		mmio_write_32(UART_LCR(base),
			      uart->registers.lcr | UART_LCR_DLAB);
		uart->registers.dll = mmio_read_32(UART_DLL(base));
		uart->registers.dlh = mmio_read_32(UART_DLH(base));
		mmio_write_32(UART_LCR(base), uart->registers.lcr);
		uart->registers.sample_count = mmio_read_32(
						UART_SAMPLE_COUNT(base));
		uart->registers.sample_point = mmio_read_32(
						UART_SAMPLE_POINT(base));
		uart->registers.guard = mmio_read_32(UART_GUARD(base));

		/* flow control */
		uart->registers.escape_en = mmio_read_32(UART_ESCAPE_EN(base));
		uart->registers.mcr = mmio_read_32(UART_MCR(base));
		uart->registers.ier = mmio_read_32(UART_IER(base));
		uart->registers.scr = mmio_read_32(UART_SCR(base));
	}
}

void mt_console_uart_cg(int on)
{
	if (on == 1) {
		mmio_write_32(UART_CLOCK_GATE_CLR, UART0_CLOCK_GATE_BIT);
	} else {
		mmio_write_32(UART_CLOCK_GATE_SET, UART0_CLOCK_GATE_BIT);
	}
}

uint32_t mt_console_uart_cg_status(void)
{
	return mmio_read_32(UART_CLOCK_GATE_STA) & UART0_CLOCK_GATE_BIT;
}