/* * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved. * * Copyright (C) 2017-2023 Nuvoton Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include #include #include #include #include #include #include uintptr_t npcm845x_get_base_uart(UART_DEV_T devNum) { return 0xF0000000 + devNum * 0x1000; } uintptr_t npcm845x_get_base_clk(void) { return 0xF0801000; } uintptr_t npcm845x_get_base_gcr(void) { return 0xF0800000; } void npcm845x_wait_for_empty(int uart_n) { volatile struct npcmX50_uart *uart = (struct npcmX50_uart *)npcm845x_get_base_uart(uart_n); while ((*(uint8_t *)(uintptr_t)(&uart->lsr) & 0x40) == 0x00) { /* * wait for THRE (Transmitter Holding Register Empty) * and TSR (Transmitter Shift Register) to be empty. * Some delay. notice needed some delay so UartUpdateTool * will pass w/o error log */ } volatile int delay; for (delay = 0; delay < 10000; delay++) { ; } } int UART_Init(UART_DEV_T devNum, UART_BAUDRATE_T baudRate) { uint32_t val = 0; uintptr_t clk_base = npcm845x_get_base_clk(); uintptr_t gcr_base = npcm845x_get_base_gcr(); uintptr_t uart_base = npcm845x_get_base_uart(devNum); volatile struct npcmX50_uart *uart = (struct npcmX50_uart *)uart_base; /* Use CLKREF to be independent of CPU frequency */ volatile struct clk_ctl *clk_ctl_obj = (struct clk_ctl *)clk_base; volatile struct npcm845x_gcr *gcr_ctl_obj = (struct npcm845x_gcr *)gcr_base; clk_ctl_obj->clksel = clk_ctl_obj->clksel & ~(0x3 << 8); clk_ctl_obj->clksel = clk_ctl_obj->clksel | (0x2 << 8); /* Set devider according to baudrate */ clk_ctl_obj->clkdiv1 = (unsigned int)(clk_ctl_obj->clkdiv1 & ~(0x1F << 16)); /* clear bits 11-15 - set value 0 */ if (devNum == UART3_DEV) { clk_ctl_obj->clkdiv2 = (unsigned int)(clk_ctl_obj->clkdiv2 & ~(0x1F << 11)); } npcm845x_wait_for_empty(devNum); val = (uint32_t)LCR_WLS_8bit; mmio_write_8((uintptr_t)&uart->lcr, (uint8_t)val); /* disable all interrupts */ mmio_write_8((uintptr_t)&uart->ier, 0); /* * Set the RX FIFO trigger level, reset RX, TX FIFO */ val = (uint32_t)(FCR_FME | FCR_RFR | FCR_TFR | FCR_RFITL_4B); /* reset TX and RX FIFO */ mmio_write_8((uintptr_t)(&uart->fcr), (uint8_t)val); /* Set port for 8 bit, 1 stop, no parity */ val = (uint32_t)LCR_WLS_8bit; /* Set DLAB bit; Accesses the Divisor Latch Registers (DLL, DLM). */ val |= 0x80; mmio_write_8((uintptr_t)(&uart->lcr), (uint8_t)val); /* Baud Rate = UART Clock 24MHz / (16 * (11+2)) = 115384 */ mmio_write_8((uintptr_t)(&uart->dll), 11); mmio_write_8((uintptr_t)(&uart->dlm), 0x00); val = mmio_read_8((uintptr_t)&uart->lcr); /* Clear DLAB bit; Accesses RBR, THR or IER registers. */ val &= 0x7F; mmio_write_8((uintptr_t)(&uart->lcr), (uint8_t)val); if (devNum == UART0_DEV) { gcr_ctl_obj->mfsel4 &= ~(1 << 1); gcr_ctl_obj->mfsel1 |= 1 << 9; } else if (devNum == UART3_DEV) { /* Pin Mux */ gcr_ctl_obj->mfsel4 &= ~(1 << 1); gcr_ctl_obj->mfsel1 |= 1 << 11; gcr_ctl_obj->spswc &= (7 << 0); gcr_ctl_obj->spswc |= (2 << 0); } else { /* halt */ while (1) { ; } } return 0; }