From 56d90311f306c329ca96da8b7b724f963eb0a8a2 Mon Sep 17 00:00:00 2001 From: kettenis Date: Sat, 24 Apr 2021 10:33:09 +0000 Subject: [PATCH] The variation in access size requirements and spacing of registers of NS16550 clones is a bit of a mess. There are FDT properties that describe these but these proprties are optional for some variants and the default values depend on the compatible string being used. Most variants that have shown up in the ARM world use 32-bit access and spacing. But true NS16550A implementations of course use 8-bit access and spacing. So look at the compatible strings to set up the appropriate defaults. Makes the "true" NS16550A implemented by QEMU work for RISCV targets. ok jsg@, drahn@ --- sys/dev/fdt/com_fdt.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/sys/dev/fdt/com_fdt.c b/sys/dev/fdt/com_fdt.c index 29a6528bd6e..c8192b2c560 100644 --- a/sys/dev/fdt/com_fdt.c +++ b/sys/dev/fdt/com_fdt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: com_fdt.c,v 1.4 2020/03/23 21:40:01 uaa Exp $ */ +/* $OpenBSD: com_fdt.c,v 1.5 2021/04/24 10:33:09 kettenis Exp $ */ /* * Copyright (c) 2016 Patrick Wildt * @@ -52,11 +52,13 @@ void com_fdt_init_cons(void) { struct fdt_reg reg; + uint32_t width, shift; void *node; if ((node = fdt_find_cons("brcm,bcm2835-aux-uart")) == NULL && - (node = fdt_find_cons("snps,dw-apb-uart")) == NULL && (node = fdt_find_cons("marvell,armada-38x-uart")) == NULL && + (node = fdt_find_cons("ns16550a")) == NULL && + (node = fdt_find_cons("snps,dw-apb-uart")) == NULL && (node = fdt_find_cons("ti,omap3-uart")) == NULL && (node = fdt_find_cons("ti,omap4-uart")) == NULL) return; @@ -71,8 +73,16 @@ com_fdt_init_cons(void) * comcnattach() does by doing the minimal setup here. */ - comcons_reg_width = OF_getpropint(stdout_node, "reg-io-width", 4); - comcons_reg_shift = OF_getpropint(stdout_node, "reg-shift", 2); + if (OF_is_compatible(stdout_node, "ns16550a")) { + width = 1; + shift = 0; + } else { + width = 4; + shift = 2; + } + + comcons_reg_width = OF_getpropint(stdout_node, "reg-io-width", width); + comcons_reg_shift = OF_getpropint(stdout_node, "reg-shift", shift); comconsiot = fdt_cons_bs_tag; if (bus_space_map(comconsiot, reg.addr, reg.size, 0, &comconsioh)) @@ -87,8 +97,9 @@ com_fdt_match(struct device *parent, void *match, void *aux) struct fdt_attach_args *faa = aux; return (OF_is_compatible(faa->fa_node, "brcm,bcm2835-aux-uart") || - OF_is_compatible(faa->fa_node, "snps,dw-apb-uart") || OF_is_compatible(faa->fa_node, "marvell,armada-38x-uart") || + OF_is_compatible(faa->fa_node, "ns16550a") || + OF_is_compatible(faa->fa_node, "snps,dw-apb-uart") || OF_is_compatible(faa->fa_node, "ti,omap3-uart") || OF_is_compatible(faa->fa_node, "ti,omap4-uart")); } @@ -99,7 +110,7 @@ com_fdt_attach(struct device *parent, struct device *self, void *aux) struct com_softc *sc = (struct com_softc *)self; struct fdt_attach_args *faa = aux; int (*intr)(void *) = comintr; - uint32_t freq; + uint32_t freq, width, shift; if (faa->fa_nreg < 1) return; @@ -121,8 +132,16 @@ com_fdt_attach(struct device *parent, struct device *self, void *aux) sc->sc_uarttype = COM_UART_16550; sc->sc_frequency = freq ? freq : COM_FREQ; - sc->sc_reg_width = OF_getpropint(faa->fa_node, "reg-io-width", 4); - sc->sc_reg_shift = OF_getpropint(faa->fa_node, "reg-shift", 2); + if (OF_is_compatible(stdout_node, "ns16550a")) { + width = 1; + shift = 0; + } else { + width = 4; + shift = 2; + } + + sc->sc_reg_width = OF_getpropint(faa->fa_node, "reg-io-width", width); + sc->sc_reg_shift = OF_getpropint(faa->fa_node, "reg-shift", shift); if (OF_is_compatible(faa->fa_node, "snps,dw-apb-uart") || OF_is_compatible(faa->fa_node, "marvell,armada-38x-uart")) -- 2.20.1