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