xref: /arm-trusted-firmware/plat/nuvoton/npcm845x/npcm845x_serial_port.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * Copyright (C) 2017-2023 Nuvoton Ltd.
5*91f16700Schasinglulu  *
6*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
7*91f16700Schasinglulu  */
8*91f16700Schasinglulu 
9*91f16700Schasinglulu #include <stdbool.h>
10*91f16700Schasinglulu 
11*91f16700Schasinglulu #include <arch.h>
12*91f16700Schasinglulu #include <arch_helpers.h>
13*91f16700Schasinglulu #include <common/debug.h>
14*91f16700Schasinglulu #include <drivers/arm/gicv2.h>
15*91f16700Schasinglulu #include <drivers/delay_timer.h>
16*91f16700Schasinglulu #include <drivers/generic_delay_timer.h>
17*91f16700Schasinglulu #include <lib/mmio.h>
18*91f16700Schasinglulu #include <lib/psci/psci.h>
19*91f16700Schasinglulu #include <npcm845x_clock.h>
20*91f16700Schasinglulu #include <npcm845x_gcr.h>
21*91f16700Schasinglulu #include <npcm845x_lpuart.h>
22*91f16700Schasinglulu #include <plat_npcm845x.h>
23*91f16700Schasinglulu 
24*91f16700Schasinglulu 
25*91f16700Schasinglulu uintptr_t npcm845x_get_base_uart(UART_DEV_T devNum)
26*91f16700Schasinglulu {
27*91f16700Schasinglulu 	return 0xF0000000 + devNum * 0x1000;
28*91f16700Schasinglulu }
29*91f16700Schasinglulu 
30*91f16700Schasinglulu uintptr_t npcm845x_get_base_clk(void)
31*91f16700Schasinglulu {
32*91f16700Schasinglulu 	return 0xF0801000;
33*91f16700Schasinglulu }
34*91f16700Schasinglulu 
35*91f16700Schasinglulu uintptr_t npcm845x_get_base_gcr(void)
36*91f16700Schasinglulu {
37*91f16700Schasinglulu 	return 0xF0800000;
38*91f16700Schasinglulu }
39*91f16700Schasinglulu 
40*91f16700Schasinglulu void npcm845x_wait_for_empty(int uart_n)
41*91f16700Schasinglulu {
42*91f16700Schasinglulu 	volatile struct npcmX50_uart *uart = (struct npcmX50_uart *)npcm845x_get_base_uart(uart_n);
43*91f16700Schasinglulu 
44*91f16700Schasinglulu 	while ((*(uint8_t *)(uintptr_t)(&uart->lsr) & 0x40) == 0x00) {
45*91f16700Schasinglulu /*
46*91f16700Schasinglulu  * wait for THRE (Transmitter Holding Register Empty)
47*91f16700Schasinglulu  * and TSR (Transmitter Shift Register) to be empty.
48*91f16700Schasinglulu  * Some delay. notice needed some delay so UartUpdateTool
49*91f16700Schasinglulu  * will pass w/o error log
50*91f16700Schasinglulu  */
51*91f16700Schasinglulu 	}
52*91f16700Schasinglulu 
53*91f16700Schasinglulu 	volatile int delay;
54*91f16700Schasinglulu 
55*91f16700Schasinglulu 	for (delay = 0; delay < 10000; delay++) {
56*91f16700Schasinglulu 		;
57*91f16700Schasinglulu 	}
58*91f16700Schasinglulu }
59*91f16700Schasinglulu 
60*91f16700Schasinglulu int UART_Init(UART_DEV_T devNum,  UART_BAUDRATE_T baudRate)
61*91f16700Schasinglulu {
62*91f16700Schasinglulu 	uint32_t val = 0;
63*91f16700Schasinglulu 	uintptr_t clk_base = npcm845x_get_base_clk();
64*91f16700Schasinglulu 	uintptr_t gcr_base =  npcm845x_get_base_gcr();
65*91f16700Schasinglulu 	uintptr_t uart_base = npcm845x_get_base_uart(devNum);
66*91f16700Schasinglulu 	volatile struct npcmX50_uart *uart = (struct npcmX50_uart *)uart_base;
67*91f16700Schasinglulu 
68*91f16700Schasinglulu /* Use  CLKREF to be independent of CPU frequency */
69*91f16700Schasinglulu 	volatile struct clk_ctl *clk_ctl_obj = (struct clk_ctl *)clk_base;
70*91f16700Schasinglulu 	volatile struct npcm845x_gcr *gcr_ctl_obj =
71*91f16700Schasinglulu 		(struct npcm845x_gcr *)gcr_base;
72*91f16700Schasinglulu 
73*91f16700Schasinglulu 	clk_ctl_obj->clksel = clk_ctl_obj->clksel & ~(0x3 << 8);
74*91f16700Schasinglulu 	clk_ctl_obj->clksel = clk_ctl_obj->clksel | (0x2 << 8);
75*91f16700Schasinglulu 
76*91f16700Schasinglulu 	/* Set devider according to baudrate */
77*91f16700Schasinglulu 	clk_ctl_obj->clkdiv1 =
78*91f16700Schasinglulu 		(unsigned int)(clk_ctl_obj->clkdiv1 & ~(0x1F << 16));
79*91f16700Schasinglulu 
80*91f16700Schasinglulu 	/* clear bits 11-15 - set value 0 */
81*91f16700Schasinglulu 	if (devNum == UART3_DEV) {
82*91f16700Schasinglulu 		clk_ctl_obj->clkdiv2 =
83*91f16700Schasinglulu 			(unsigned int)(clk_ctl_obj->clkdiv2 & ~(0x1F << 11));
84*91f16700Schasinglulu 	}
85*91f16700Schasinglulu 
86*91f16700Schasinglulu 	npcm845x_wait_for_empty(devNum);
87*91f16700Schasinglulu 
88*91f16700Schasinglulu 	val = (uint32_t)LCR_WLS_8bit;
89*91f16700Schasinglulu 	mmio_write_8((uintptr_t)&uart->lcr, (uint8_t)val);
90*91f16700Schasinglulu 
91*91f16700Schasinglulu 	/* disable all interrupts */
92*91f16700Schasinglulu 	mmio_write_8((uintptr_t)&uart->ier, 0);
93*91f16700Schasinglulu 
94*91f16700Schasinglulu 	/*
95*91f16700Schasinglulu 	 * Set the RX FIFO trigger level, reset RX, TX FIFO
96*91f16700Schasinglulu 	 */
97*91f16700Schasinglulu 	val = (uint32_t)(FCR_FME | FCR_RFR | FCR_TFR | FCR_RFITL_4B);
98*91f16700Schasinglulu 
99*91f16700Schasinglulu 	/* reset TX and RX FIFO */
100*91f16700Schasinglulu 	mmio_write_8((uintptr_t)(&uart->fcr), (uint8_t)val);
101*91f16700Schasinglulu 
102*91f16700Schasinglulu 	/* Set port for 8 bit, 1 stop, no parity */
103*91f16700Schasinglulu 	val = (uint32_t)LCR_WLS_8bit;
104*91f16700Schasinglulu 
105*91f16700Schasinglulu 	/* Set DLAB bit; Accesses the Divisor Latch Registers (DLL, DLM). */
106*91f16700Schasinglulu 	val |= 0x80;
107*91f16700Schasinglulu 	mmio_write_8((uintptr_t)(&uart->lcr), (uint8_t)val);
108*91f16700Schasinglulu 
109*91f16700Schasinglulu 	/* Baud Rate = UART Clock 24MHz / (16 * (11+2)) = 115384 */
110*91f16700Schasinglulu 	mmio_write_8((uintptr_t)(&uart->dll), 11);
111*91f16700Schasinglulu 	mmio_write_8((uintptr_t)(&uart->dlm), 0x00);
112*91f16700Schasinglulu 
113*91f16700Schasinglulu 	val = mmio_read_8((uintptr_t)&uart->lcr);
114*91f16700Schasinglulu 
115*91f16700Schasinglulu 	/* Clear DLAB bit; Accesses RBR, THR or IER registers. */
116*91f16700Schasinglulu 	val &= 0x7F;
117*91f16700Schasinglulu 	mmio_write_8((uintptr_t)(&uart->lcr), (uint8_t)val);
118*91f16700Schasinglulu 
119*91f16700Schasinglulu 	if (devNum == UART0_DEV) {
120*91f16700Schasinglulu 		gcr_ctl_obj->mfsel4 &= ~(1 << 1);
121*91f16700Schasinglulu 		gcr_ctl_obj->mfsel1 |= 1 << 9;
122*91f16700Schasinglulu 	} else if (devNum == UART3_DEV) {
123*91f16700Schasinglulu 		/* Pin Mux */
124*91f16700Schasinglulu 		gcr_ctl_obj->mfsel4 &= ~(1 << 1);
125*91f16700Schasinglulu 		gcr_ctl_obj->mfsel1 |= 1 << 11;
126*91f16700Schasinglulu 		gcr_ctl_obj->spswc &= (7 << 0);
127*91f16700Schasinglulu 		gcr_ctl_obj->spswc |= (2 << 0);
128*91f16700Schasinglulu 	} else {
129*91f16700Schasinglulu 		/* halt */
130*91f16700Schasinglulu 		while (1) {
131*91f16700Schasinglulu 			;
132*91f16700Schasinglulu 		}
133*91f16700Schasinglulu 	}
134*91f16700Schasinglulu 
135*91f16700Schasinglulu 	return 0;
136*91f16700Schasinglulu }
137