<p>Patrick Rudolph has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/23779">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">soc/cavium: Move UART<br><br>Move UART code to common folder.<br>Use addressmap.h instead of hardcoding registers.<br>Implement a function to wait # HCLKs and get rid of long delays.<br>Fix coding style.<br>Add comments.<br><br>Change-Id: I33a043b753651b0aa8cf8b31bd0ecde836859c64<br>Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com><br>---<br>M src/mainboard/cavium/cn8100_sff_evb/bootblock.c<br>M src/soc/cavium/cn81xx/Makefile.inc<br>D src/soc/cavium/cn81xx/include/soc/uart.h<br>D src/soc/cavium/cn81xx/uart.c<br>M src/soc/cavium/common/Makefile.inc<br>A src/soc/cavium/common/include/soc/uart.h<br>A src/soc/cavium/common/uart.c<br>7 files changed, 296 insertions(+), 177 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/79/23779/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/mainboard/cavium/cn8100_sff_evb/bootblock.c b/src/mainboard/cavium/cn8100_sff_evb/bootblock.c</span><br><span>index 977a295..8cf2307 100644</span><br><span>--- a/src/mainboard/cavium/cn8100_sff_evb/bootblock.c</span><br><span>+++ b/src/mainboard/cavium/cn8100_sff_evb/bootblock.c</span><br><span>@@ -26,18 +26,12 @@</span><br><span> </span><br><span> void bootblock_mainboard_early_init(void)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct cn81xx_uart *uart0 = (struct cn81xx_uart *)UAA0_PF_BAR0;</span><br><span style="color: hsl(0, 100%, 40%);">- struct cn81xx_uart *uart1 = (struct cn81xx_uart *)UAA1_PF_BAR0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#if IS_ENABLED(CONFIG_DRIVERS_UART)</span><br><span style="color: hsl(0, 100%, 40%);">- _Static_assert(CONFIG_CONSOLE_SERIAL_UART_ADDRESS == UAA0_PF_BAR0,</span><br><span style="color: hsl(0, 100%, 40%);">- "CONSOLE_SERIAL_UART should be UART0");</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!(uart0->uctl_ctl & UART_UCTL_CTL_H_CLK_EN))</span><br><span style="color: hsl(0, 100%, 40%);">- cavium_uart_setup(uart0, CONFIG_TTYS0_BAUD);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!(uart1->uctl_ctl & UART_UCTL_CTL_H_CLK_EN))</span><br><span style="color: hsl(0, 100%, 40%);">- cavium_uart_setup(uart1, CONFIG_TTYS0_BAUD);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (IS_ENABLED(CONFIG_BOOTBLOCK_CONSOLE)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!uart_is_enabled(0))</span><br><span style="color: hsl(120, 100%, 40%);">+ uart_setup(0, CONFIG_TTYS0_BAUD);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!uart_is_enabled(1))</span><br><span style="color: hsl(120, 100%, 40%);">+ uart_setup(0, CONFIG_TTYS0_BAUD);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> }</span><br><span> </span><br><span> static void configure_spi_flash(void)</span><br><span>diff --git a/src/soc/cavium/cn81xx/Makefile.inc b/src/soc/cavium/cn81xx/Makefile.inc</span><br><span>index 1ac9f69..f835b09 100644</span><br><span>--- a/src/soc/cavium/cn81xx/Makefile.inc</span><br><span>+++ b/src/soc/cavium/cn81xx/Makefile.inc</span><br><span>@@ -19,9 +19,6 @@</span><br><span> bootblock-$(CONFIG_BOOTBLOCK_CUSTOM) += bootblock_custom.S</span><br><span> </span><br><span> #bootblock-y += ../common/i2c.c</span><br><span style="color: hsl(0, 100%, 40%);">-ifeq ($(CONFIG_BOOTBLOCK_CONSOLE),y)</span><br><span style="color: hsl(0, 100%, 40%);">-bootblock-$(CONFIG_DRIVERS_UART) += uart.c</span><br><span style="color: hsl(0, 100%, 40%);">-endif</span><br><span> #bootblock-y += ../common/gpio.c</span><br><span> #bootblock-y += ../common/pwm.c</span><br><span> bootblock-y += bootblock.c</span><br><span>@@ -69,13 +66,11 @@</span><br><span> #verstage-y += gpio.c</span><br><span> #verstage-y += sdram.c</span><br><span> #verstage-y += ../common/i2c.c</span><br><span style="color: hsl(0, 100%, 40%);">-#verstage-$(CONFIG_DRIVERS_UART) += uart.c</span><br><span> </span><br><span> </span><br><span> ################################################################################</span><br><span> </span><br><span> romstage-y += ../common/cbmem.c</span><br><span style="color: hsl(0, 100%, 40%);">-romstage-$(CONFIG_DRIVERS_UART) += uart.c</span><br><span> romstage-y += mmu_operations.c</span><br><span> #romstage-y += ../common/pwm.c</span><br><span> #romstage-y += gpio.c</span><br><span>@@ -85,7 +80,6 @@</span><br><span> </span><br><span> ramstage-y += ../common/cbmem.c</span><br><span> ramstage-y += sdram.c</span><br><span style="color: hsl(0, 100%, 40%);">-ramstage-$(CONFIG_DRIVERS_UART) += uart.c</span><br><span> #ramstage-y += ../common/gpio.c</span><br><span> #ramstage-y += gpio.c</span><br><span> #ramstage-y += ../common/i2c.c</span><br><span>diff --git a/src/soc/cavium/cn81xx/include/soc/uart.h b/src/soc/cavium/cn81xx/include/soc/uart.h</span><br><span>deleted file mode 100644</span><br><span>index f45dbe1..0000000</span><br><span>--- a/src/soc/cavium/cn81xx/include/soc/uart.h</span><br><span>+++ /dev/null</span><br><span>@@ -1,51 +0,0 @@</span><br><span style="color: hsl(0, 100%, 40%);">-/*</span><br><span style="color: hsl(0, 100%, 40%);">- * This file is part of the coreboot project.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * Copyright 2017-present Facebook, Inc.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(0, 100%, 40%);">- * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(0, 100%, 40%);">- * the Free Software Foundation; version 2 of the License.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(0, 100%, 40%);">- * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(0, 100%, 40%);">- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(0, 100%, 40%);">- * GNU General Public License for more details.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#ifndef __SOC_CAVIUM_COMMON_INCLUDE_SOC_UART_H</span><br><span style="color: hsl(0, 100%, 40%);">-#define __SOC_CAVIUM_COMMON_INCLUDE_SOC_UART_H</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <drivers/uart/pl011.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <inttypes.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <types.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-struct cn81xx_uart {</span><br><span style="color: hsl(0, 100%, 40%);">- struct pl011_uart pl011;</span><br><span style="color: hsl(0, 100%, 40%);">- u64 uctl_ctl;</span><br><span style="color: hsl(0, 100%, 40%);">- u8 rsvd4[0x8];</span><br><span style="color: hsl(0, 100%, 40%);">- u64 uctl_spare0;</span><br><span style="color: hsl(0, 100%, 40%);">- u8 rsvd5[0xe0];</span><br><span style="color: hsl(0, 100%, 40%);">- u64 uctl_spare1;</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-check_member(cn81xx_uart, uctl_ctl, 0x1000);</span><br><span style="color: hsl(0, 100%, 40%);">-check_member(cn81xx_uart, uctl_spare1, 0x10f8);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#define UART_IBRD_BAUD_DIVINT_SHIFT 0</span><br><span style="color: hsl(0, 100%, 40%);">-#define UART_IBRD_BAUD_DIVINT_MASK 0xffff</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#define UART_FBRD_BAUD_DIVFRAC_SHIFT 0</span><br><span style="color: hsl(0, 100%, 40%);">-#define UART_FBRD_BAUD_DIVFRAC_MASK 0x3f</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#define UART_UCTL_CTL_UCTL_RST (1 << 0)</span><br><span style="color: hsl(0, 100%, 40%);">-#define UART_UCTL_CTL_UAA_RST (1 << 1)</span><br><span style="color: hsl(0, 100%, 40%);">-#define UART_UCTL_CTL_CSCLK_EN (1 << 4)</span><br><span style="color: hsl(0, 100%, 40%);">-#define UART_UCTL_CTL_H_CLKDIV_SEL_SHIFT 24</span><br><span style="color: hsl(0, 100%, 40%);">-#define UART_UCTL_CTL_H_CLKDIV_MASK 0x7</span><br><span style="color: hsl(0, 100%, 40%);">-#define UART_UCTL_CTL_H_CLKDIV_RST (1 << 28)</span><br><span style="color: hsl(0, 100%, 40%);">-#define UART_UCTL_CTL_H_CLK_BYP_SEL (1 << 29)</span><br><span style="color: hsl(0, 100%, 40%);">-#define UART_UCTL_CTL_H_CLK_EN (1 << 30)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-int cavium_uart_setup(struct cn81xx_uart *uart, int baudrate);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#endif /* __SOC_CAVIUM_COMMON_INCLUDE_SOC_UART_H */</span><br><span>diff --git a/src/soc/cavium/cn81xx/uart.c b/src/soc/cavium/cn81xx/uart.c</span><br><span>deleted file mode 100644</span><br><span>index aacca82..0000000</span><br><span>--- a/src/soc/cavium/cn81xx/uart.c</span><br><span>+++ /dev/null</span><br><span>@@ -1,105 +0,0 @@</span><br><span style="color: hsl(0, 100%, 40%);">-/*</span><br><span style="color: hsl(0, 100%, 40%);">- * This file is part of the coreboot project.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights</span><br><span style="color: hsl(0, 100%, 40%);">- * reserved.</span><br><span style="color: hsl(0, 100%, 40%);">- * Copyright 2017-present Facebook, Inc.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * SPDX-License-Identifier: BSD-3-Clause</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <arch/io.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <console/uart.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <delay.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <endian.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <stdint.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <soc/clock.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <soc/uart.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <assert.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#define UART_SCLK_DIV 3</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static size_t uart_sclk_divisor(size_t reg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- static const u8 div[] = {1, 2, 4, 6, 8, 16, 24, 32};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- assert(reg < ARRAY_SIZE(div));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return div[reg];</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-unsigned int uart_platform_refclk(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return thunderx_get_io_clock() / uart_sclk_divisor(UART_SCLK_DIV);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-uintptr_t uart_platform_base(int idx)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return CONFIG_CONSOLE_SERIAL_UART_ADDRESS;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-int cavium_uart_setup(struct cn81xx_uart *uart, int baudrate)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- /* 1.2.1 Initialization Sequence (Power-On/Hard/Cold Reset) */</span><br><span style="color: hsl(0, 100%, 40%);">- /* 1. Wait for IOI reset (srst_n) to deassert. */</span><br><span style="color: hsl(0, 100%, 40%);">- /* 2. Assert all resets:</span><br><span style="color: hsl(0, 100%, 40%);">- a. UAA reset: UCTL_CTL[UAA_RST] = 1</span><br><span style="color: hsl(0, 100%, 40%);">- b. UCTL reset: UCTL_CTL[UCTL_RST] = 1 */</span><br><span style="color: hsl(0, 100%, 40%);">- setbits_le64(&uart->uctl_ctl, UART_UCTL_CTL_UCTL_RST | UART_UCTL_CTL_UAA_RST);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* 3. Configure the HCLK:</span><br><span style="color: hsl(0, 100%, 40%);">- a. Reset the clock dividers: UCTL_CTL[H_CLKDIV_RST] = 1.</span><br><span style="color: hsl(0, 100%, 40%);">- b. Select the HCLK frequency</span><br><span style="color: hsl(0, 100%, 40%);">- i. UCTL_CTL[H_CLKDIV] = desired value,</span><br><span style="color: hsl(0, 100%, 40%);">- ii. UCTL_CTL[H_CLKDIV_EN] = 1 to enable the HCLK.</span><br><span style="color: hsl(0, 100%, 40%);">- iii. Readback UCTL_CTL to ensure the values take effect.</span><br><span style="color: hsl(0, 100%, 40%);">- c. Deassert the HCLK clock divider reset: UCTL_CTL[H_CLKDIV_RST] = 0. */</span><br><span style="color: hsl(0, 100%, 40%);">- clrsetbits_le64(&uart->uctl_ctl,</span><br><span style="color: hsl(0, 100%, 40%);">- UART_UCTL_CTL_H_CLKDIV_MASK << UART_UCTL_CTL_H_CLKDIV_SEL_SHIFT,</span><br><span style="color: hsl(0, 100%, 40%);">- UART_SCLK_DIV << UART_UCTL_CTL_H_CLKDIV_SEL_SHIFT);</span><br><span style="color: hsl(0, 100%, 40%);">- clrbits_le64(&uart->uctl_ctl, UART_UCTL_CTL_H_CLK_BYP_SEL);</span><br><span style="color: hsl(0, 100%, 40%);">- setbits_le64(&uart->uctl_ctl, UART_UCTL_CTL_H_CLK_EN);</span><br><span style="color: hsl(0, 100%, 40%);">- clrbits_le64(&uart->uctl_ctl, UART_UCTL_CTL_H_CLKDIV_RST);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* 4. Wait 20 HCLK cycles from step 3 for HCLK to start and async fifo</span><br><span style="color: hsl(0, 100%, 40%);">- to properly reset. */</span><br><span style="color: hsl(0, 100%, 40%);">- mdelay(200); /* Overkill */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* 5. Deassert UCTL and UAHC resets:</span><br><span style="color: hsl(0, 100%, 40%);">- a. UCTL_CTL[UCTL_RST] = 0</span><br><span style="color: hsl(0, 100%, 40%);">- b. Wait 10 HCLK cycles.</span><br><span style="color: hsl(0, 100%, 40%);">- c. UCTL_CTL[UAHC_RST] = 0</span><br><span style="color: hsl(0, 100%, 40%);">- d. You will have to wait 10 HCLK cycles before accessing any</span><br><span style="color: hsl(0, 100%, 40%);">- HCLK-only registers. */</span><br><span style="color: hsl(0, 100%, 40%);">- clrbits_le64(&uart->uctl_ctl, UART_UCTL_CTL_UCTL_RST);</span><br><span style="color: hsl(0, 100%, 40%);">- mdelay(100); /* Overkill */</span><br><span style="color: hsl(0, 100%, 40%);">- clrbits_le64(&uart->uctl_ctl, UART_UCTL_CTL_UAA_RST);</span><br><span style="color: hsl(0, 100%, 40%);">- mdelay(100); /* Overkill */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* 6. Enable conditional SCLK of UCTL by writing UCTL_CTL[CSCLK_EN] = 1. */</span><br><span style="color: hsl(0, 100%, 40%);">- setbits_le32(&uart->uctl_ctl, UART_UCTL_CTL_CSCLK_EN);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* 7. Initialize the integer and fractional baud rate divider registers</span><br><span style="color: hsl(0, 100%, 40%);">- UARTIBRD and UARTFBRD as follows:</span><br><span style="color: hsl(0, 100%, 40%);">- a. Baud Rate Divisor = UARTCLK/(16xBaud Rate) = BRDI + BRDF</span><br><span style="color: hsl(0, 100%, 40%);">- b. The fractional register BRDF, m is calculated as integer(BRDF x 64 + 0.5)</span><br><span style="color: hsl(0, 100%, 40%);">- Example calculation:</span><br><span style="color: hsl(0, 100%, 40%);">- If the required baud rate is 230400 and hclk = 4MHz then:</span><br><span style="color: hsl(0, 100%, 40%);">- Baud Rate Divisor = (4x10^6)/(16x230400) = 1.085</span><br><span style="color: hsl(0, 100%, 40%);">- This means BRDI = 1 and BRDF = 0.085.</span><br><span style="color: hsl(0, 100%, 40%);">- Therefore, fractional part, BRDF = integer((0.085x64)+0.5) = 5</span><br><span style="color: hsl(0, 100%, 40%);">- Generated baud rate divider = 1+5/64 = 1.078 */</span><br><span style="color: hsl(0, 100%, 40%);">- u64 divisor = thunderx_get_io_clock() /</span><br><span style="color: hsl(0, 100%, 40%);">- (baudrate * 16 * uart_sclk_divisor(UART_SCLK_DIV) / 64);</span><br><span style="color: hsl(0, 100%, 40%);">- write32(&uart->pl011.ibrd, divisor >> 6);</span><br><span style="color: hsl(0, 100%, 40%);">- write32(&uart->pl011.fbrd, divisor & UART_FBRD_BAUD_DIVFRAC_MASK);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* 8. Program the line control register UAA(0..1)_LCR_H and the control</span><br><span style="color: hsl(0, 100%, 40%);">- register UAA(0..1)_CR */</span><br><span style="color: hsl(0, 100%, 40%);">- /* 8-bits, FIFO enable */</span><br><span style="color: hsl(0, 100%, 40%);">- write32(&uart->pl011.lcr_h, PL011_UARTLCR_H_WLEN_8 | PL011_UARTLCR_H_FEN);</span><br><span style="color: hsl(0, 100%, 40%);">- /* RX/TX enable, UART enable */</span><br><span style="color: hsl(0, 100%, 40%);">- write32(&uart->pl011.cr, PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span>diff --git a/src/soc/cavium/common/Makefile.inc b/src/soc/cavium/common/Makefile.inc</span><br><span>index fce377c..feeeb6e 100644</span><br><span>--- a/src/soc/cavium/common/Makefile.inc</span><br><span>+++ b/src/soc/cavium/common/Makefile.inc</span><br><span>@@ -21,7 +21,10 @@</span><br><span> bootblock-y += gpio.c</span><br><span> bootblock-y += timer.c</span><br><span> bootblock-y += spi.c</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+bootblock-y += uart.c</span><br><span style="color: hsl(120, 100%, 40%);">+ifeq ($(CONFIG_BOOTBLOCK_CONSOLE),y)</span><br><span style="color: hsl(120, 100%, 40%);">+bootblock-$(CONFIG_DRIVERS_UART) += uart.c</span><br><span style="color: hsl(120, 100%, 40%);">+endif</span><br><span> </span><br><span> </span><br><span> romstage-y += twsi.c</span><br><span>@@ -29,14 +32,16 @@</span><br><span> romstage-y += gpio.c</span><br><span> romstage-y += timer.c</span><br><span> romstage-y += spi.c</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+romstage-y += uart.c</span><br><span style="color: hsl(120, 100%, 40%);">+romstage-$(CONFIG_DRIVERS_UART) += uart.c</span><br><span> </span><br><span> ramstage-y += twsi.c</span><br><span> ramstage-y += clock.c</span><br><span> ramstage-y += gpio.c</span><br><span> ramstage-y += timer.c</span><br><span> ramstage-y += spi.c</span><br><span style="color: hsl(120, 100%, 40%);">+ramstage-y += uart.c</span><br><span style="color: hsl(120, 100%, 40%);">+ramstage-$(CONFIG_DRIVERS_UART) += uart.c</span><br><span> </span><br><span> CPPFLAGS_common += -Isrc/soc/cavium/common/include</span><br><span> </span><br><span>diff --git a/src/soc/cavium/common/include/soc/uart.h b/src/soc/cavium/common/include/soc/uart.h</span><br><span>new file mode 100644</span><br><span>index 0000000..e402206</span><br><span>--- /dev/null</span><br><span>+++ b/src/soc/cavium/common/include/soc/uart.h</span><br><span>@@ -0,0 +1,25 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * This file is part of the coreboot project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2017-present Facebook, Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; version 2 of the License.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __SOC_CAVIUM_COMMON_INCLUDE_SOC_UART_H</span><br><span style="color: hsl(120, 100%, 40%);">+#define __SOC_CAVIUM_COMMON_INCLUDE_SOC_UART_H</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <inttypes.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <types.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int uart_is_enabled(const size_t bus);</span><br><span style="color: hsl(120, 100%, 40%);">+int uart_setup(const size_t bus, int baudrate);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* __SOC_CAVIUM_COMMON_INCLUDE_SOC_UART_H */</span><br><span>diff --git a/src/soc/cavium/common/uart.c b/src/soc/cavium/common/uart.c</span><br><span>new file mode 100644</span><br><span>index 0000000..b3cce8e</span><br><span>--- /dev/null</span><br><span>+++ b/src/soc/cavium/common/uart.c</span><br><span>@@ -0,0 +1,257 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * This file is part of the coreboot project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights</span><br><span style="color: hsl(120, 100%, 40%);">+ * reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright 2017-present Facebook, Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: BSD-3-Clause</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <arch/io.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <console/uart.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <delay.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <endian.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <soc/clock.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <soc/uart.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <assert.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <soc/addressmap.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <drivers/uart/pl011.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+union cn81xx_uart_ctl {</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 u;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct {</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 uctl_rst : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 uaa_rst : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 : 2;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 csclk_en : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 : 19;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 h_clkdiv_sel : 3;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 h_clkdiv_rst : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 h_clk_byp_sel : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 h_clk_en : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 : 33;</span><br><span style="color: hsl(120, 100%, 40%);">+ } s;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct cn81xx_uart {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct pl011_uart pl011;</span><br><span style="color: hsl(120, 100%, 40%);">+ union cn81xx_uart_ctl uctl_ctl;</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 rsvd4[0x8];</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 uctl_spare0;</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 rsvd5[0xe0];</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 uctl_spare1;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define UART_IBRD_BAUD_DIVINT_SHIFT 0</span><br><span style="color: hsl(120, 100%, 40%);">+#define UART_IBRD_BAUD_DIVINT_MASK 0xffff</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define UART_FBRD_BAUD_DIVFRAC_SHIFT 0</span><br><span style="color: hsl(120, 100%, 40%);">+#define UART_FBRD_BAUD_DIVFRAC_MASK 0x3f</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+check_member(cn81xx_uart, uctl_ctl, 0x1000);</span><br><span style="color: hsl(120, 100%, 40%);">+check_member(cn81xx_uart, uctl_spare1, 0x10f8);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define UART_SCLK_DIV 3</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns the current UART HCLK divider</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param reg The H_CLKDIV_SEL value</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return The HCLK divider</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static size_t uart_sclk_divisor(const size_t reg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ static const u8 div[] = {1, 2, 4, 6, 8, 16, 24, 32};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ assert(reg < ARRAY_SIZE(div));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return div[reg];</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns the current UART HCLK</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param uart The UART to operate on</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return The HCLK in Hz</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static size_t uart_hclk(struct cn81xx_uart *uart)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ union cn81xx_uart_ctl ctl;</span><br><span style="color: hsl(120, 100%, 40%);">+ const uint64_t sclk = thunderx_get_io_clock();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.u = read64(&uart->uctl_ctl);</span><br><span style="color: hsl(120, 100%, 40%);">+ return sclk / uart_sclk_divisor(ctl.s.h_clkdiv_sel);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+unsigned int uart_platform_refclk(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct cn81xx_uart *uart =</span><br><span style="color: hsl(120, 100%, 40%);">+ (struct cn81xx_uart *)CONFIG_CONSOLE_SERIAL_UART_ADDRESS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!uart)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return uart_hclk(uart);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+uintptr_t uart_platform_base(int idx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return CONFIG_CONSOLE_SERIAL_UART_ADDRESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Waits given count if HCLK cycles</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param uart The UART to operate on</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param hclks The number of HCLK cycles to wait</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void uart_wait_hclk(struct cn81xx_uart *uart, const size_t hclks)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const size_t hclk = uart_hclk(uart);</span><br><span style="color: hsl(120, 100%, 40%);">+ const size_t delay = (hclks * 1000000ULL) / hclk;</span><br><span style="color: hsl(120, 100%, 40%);">+ udelay(MAX(delay, 1));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns the UART state.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param bus The UART to operate on</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return Boolean: True if UART is enabled</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int uart_is_enabled(const size_t bus)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct cn81xx_uart *uart = (struct cn81xx_uart *)UAAx_PF_BAR0(bus);</span><br><span style="color: hsl(120, 100%, 40%);">+ union cn81xx_uart_ctl ctl;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ assert(uart);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!uart)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.u = read64(&uart->uctl_ctl);</span><br><span style="color: hsl(120, 100%, 40%);">+ return !!ctl.s.csclk_en;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Setup UART with desired BAUD rate in 8N1, no parity mode.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param bus The UART to operate on</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param baudrate baudrate to set up</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return Boolean: True on error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int uart_setup(const size_t bus, int baudrate)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ union cn81xx_uart_ctl ctl;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct cn81xx_uart *uart = (struct cn81xx_uart *)UAAx_PF_BAR0(bus);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ assert(uart);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!uart)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* 1.2.1 Initialization Sequence (Power-On/Hard/Cold Reset) */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* 1. Wait for IOI reset (srst_n) to deassert. */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /**</span><br><span style="color: hsl(120, 100%, 40%);">+ * 2. Assert all resets:</span><br><span style="color: hsl(120, 100%, 40%);">+ * a. UAA reset: UCTL_CTL[UAA_RST] = 1</span><br><span style="color: hsl(120, 100%, 40%);">+ * b. UCTL reset: UCTL_CTL[UCTL_RST] = 1</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.u = read64(&uart->uctl_ctl);</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.s.uctl_rst = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.s.uaa_rst = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ write64(&uart->uctl_ctl, ctl.u);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /**</span><br><span style="color: hsl(120, 100%, 40%);">+ * 3. Configure the HCLK:</span><br><span style="color: hsl(120, 100%, 40%);">+ * a. Reset the clock dividers: UCTL_CTL[H_CLKDIV_RST] = 1.</span><br><span style="color: hsl(120, 100%, 40%);">+ * b. Select the HCLK frequency</span><br><span style="color: hsl(120, 100%, 40%);">+ * i. UCTL_CTL[H_CLKDIV] = desired value,</span><br><span style="color: hsl(120, 100%, 40%);">+ * ii. UCTL_CTL[H_CLKDIV_EN] = 1 to enable the HCLK.</span><br><span style="color: hsl(120, 100%, 40%);">+ * iii. Readback UCTL_CTL to ensure the values take effect.</span><br><span style="color: hsl(120, 100%, 40%);">+ * c. Deassert the HCLK clock divider reset: UCTL_CTL[H_CLKDIV_RST] = 0.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.u = read64(&uart->uctl_ctl);</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.s.h_clkdiv_sel = UART_SCLK_DIV;</span><br><span style="color: hsl(120, 100%, 40%);">+ write64(&uart->uctl_ctl, ctl.u);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.u = read64(&uart->uctl_ctl);</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.s.h_clk_byp_sel = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ write64(&uart->uctl_ctl, ctl.u);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.u = read64(&uart->uctl_ctl);</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.s.h_clk_en = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ write64(&uart->uctl_ctl, ctl.u);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.u = read64(&uart->uctl_ctl);</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.s.h_clkdiv_rst = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ write64(&uart->uctl_ctl, ctl.u);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /**</span><br><span style="color: hsl(120, 100%, 40%);">+ * 4. Wait 20 HCLK cycles from step 3 for HCLK to start and async fifo</span><br><span style="color: hsl(120, 100%, 40%);">+ * to properly reset.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ uart_wait_hclk(uart, 20 + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /**</span><br><span style="color: hsl(120, 100%, 40%);">+ * 5. Deassert UCTL and UAHC resets:</span><br><span style="color: hsl(120, 100%, 40%);">+ * a. UCTL_CTL[UCTL_RST] = 0</span><br><span style="color: hsl(120, 100%, 40%);">+ * b. Wait 10 HCLK cycles.</span><br><span style="color: hsl(120, 100%, 40%);">+ * c. UCTL_CTL[UAHC_RST] = 0</span><br><span style="color: hsl(120, 100%, 40%);">+ * d. You will have to wait 10 HCLK cycles before accessing any</span><br><span style="color: hsl(120, 100%, 40%);">+ * HCLK-only registers.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.u = read64(&uart->uctl_ctl);</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.s.uctl_rst = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ write64(&uart->uctl_ctl, ctl.u);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ uart_wait_hclk(uart, 10 + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.u = read64(&uart->uctl_ctl);</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.s.uaa_rst = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ write64(&uart->uctl_ctl, ctl.u);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ uart_wait_hclk(uart, 10 + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /**</span><br><span style="color: hsl(120, 100%, 40%);">+ * 6. Enable conditional SCLK of UCTL by writing</span><br><span style="color: hsl(120, 100%, 40%);">+ * UCTL_CTL[CSCLK_EN] = 1.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.u = read64(&uart->uctl_ctl);</span><br><span style="color: hsl(120, 100%, 40%);">+ ctl.s.csclk_en = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ write64(&uart->uctl_ctl, ctl.u);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /**</span><br><span style="color: hsl(120, 100%, 40%);">+ * 7. Initialize the integer and fractional baud rate divider registers</span><br><span style="color: hsl(120, 100%, 40%);">+ * UARTIBRD and UARTFBRD as follows:</span><br><span style="color: hsl(120, 100%, 40%);">+ * a. Baud Rate Divisor = UARTCLK/(16xBaud Rate) = BRDI + BRDF</span><br><span style="color: hsl(120, 100%, 40%);">+ * b. The fractional register BRDF, m is calculated as</span><br><span style="color: hsl(120, 100%, 40%);">+ * integer(BRDF x 64 + 0.5)</span><br><span style="color: hsl(120, 100%, 40%);">+ * Example calculation:</span><br><span style="color: hsl(120, 100%, 40%);">+ * If the required baud rate is 230400 and hclk = 4MHz then:</span><br><span style="color: hsl(120, 100%, 40%);">+ * Baud Rate Divisor = (4x10^6)/(16x230400) = 1.085</span><br><span style="color: hsl(120, 100%, 40%);">+ * This means BRDI = 1 and BRDF = 0.085.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Therefore, fractional part, BRDF = integer((0.085x64)+0.5) = 5</span><br><span style="color: hsl(120, 100%, 40%);">+ * Generated baud rate divider = 1+5/64 = 1.078</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ u64 divisor = thunderx_get_io_clock() /</span><br><span style="color: hsl(120, 100%, 40%);">+ (baudrate * 16 * uart_sclk_divisor(UART_SCLK_DIV) / 64);</span><br><span style="color: hsl(120, 100%, 40%);">+ write32(&uart->pl011.ibrd, divisor >> 6);</span><br><span style="color: hsl(120, 100%, 40%);">+ write32(&uart->pl011.fbrd, divisor & UART_FBRD_BAUD_DIVFRAC_MASK);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /**</span><br><span style="color: hsl(120, 100%, 40%);">+ * 8. Program the line control register UAA(0..1)_LCR_H and the control</span><br><span style="color: hsl(120, 100%, 40%);">+ * register UAA(0..1)_CR</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* 8-bits, FIFO enable */</span><br><span style="color: hsl(120, 100%, 40%);">+ write32(&uart->pl011.lcr_h, PL011_UARTLCR_H_WLEN_8 |</span><br><span style="color: hsl(120, 100%, 40%);">+ PL011_UARTLCR_H_FEN);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* RX/TX enable, UART enable */</span><br><span style="color: hsl(120, 100%, 40%);">+ write32(&uart->pl011.cr, PL011_UARTCR_RXE | PL011_UARTCR_TXE |</span><br><span style="color: hsl(120, 100%, 40%);">+ PL011_UARTCR_UARTEN);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/23779">change 23779</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/23779"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I33a043b753651b0aa8cf8b31bd0ecde836859c64 </div>
<div style="display:none"> Gerrit-Change-Number: 23779 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Patrick Rudolph <patrick.rudolph@9elements.com> </div>