/* SPDX-License-Identifier: GPL-2.0 */ /* * pl011.c - ARM PrimeCell PL011 serial, polled io * * the register layout is shared with the PL010 so we use the combined * struct like u-boot does. base comes from the dtb, never hardcoded. * * Copyright (C) 2026 Bradley Morgan * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include #include #include #include void pl011_init(uintptr_t base, uint32 clock, uint32 baud) { struct pl01x_regs *regs = (struct pl01x_regs *)base; uint32 divisor; uint32 remainder; uint32 fraction; /* baud divisor, same math as the PL011 TRM section 3.3.3 */ divisor = clock / (16 * baud); remainder = clock % (16 * baud); fraction = (8 * remainder + baud / 2) / baud; writel(0, ®s->pl011_cr); writel(0x7ff, ®s->pl011_icr); writel(divisor, ®s->pl011_ibrd); writel(fraction, ®s->pl011_fbrd); writel((3 << 5) | (1 << 4), ®s->pl011_lcrh); writel((1 << 0) | (1 << 8) | (1 << 9), ®s->pl011_cr); } void pl011_putc(uintptr_t base, char c) { struct pl01x_regs *regs = (struct pl01x_regs *)base; while (readl(®s->fr) & UART_PL01x_FR_TXFF) ; writel(c, ®s->dr); } int pl011_getc(uintptr_t base) { struct pl01x_regs *regs = (struct pl01x_regs *)base; if (readl(®s->fr) & UART_PL01x_FR_RXFE) return -1; return readl(®s->dr) & 0xff; }