Page MenuHomeFreeBSD

D38592.id117213.diff
No OneTemporary

D38592.id117213.diff

diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -186,6 +186,7 @@
dev/dpaa2/dpaa2_bp.c optional soc_nxp_ls dpaa2
dev/dpaa2/dpaa2_cmd_if.m optional soc_nxp_ls dpaa2
dev/dpaa2/dpaa2_con.c optional soc_nxp_ls dpaa2
+dev/dpaa2/dpaa2_console.c optional soc_nxp_ls dpaa2 fdt
dev/dpaa2/dpaa2_io.c optional soc_nxp_ls dpaa2
dev/dpaa2/dpaa2_mac.c optional soc_nxp_ls dpaa2
dev/dpaa2/dpaa2_mc.c optional soc_nxp_ls dpaa2
diff --git a/sys/dev/dpaa2/dpaa2_console.c b/sys/dev/dpaa2/dpaa2_console.c
new file mode 100644
--- /dev/null
+++ b/sys/dev/dpaa2/dpaa2_console.c
@@ -0,0 +1,573 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2022-2023 Bjoern A. Zeeb
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Some docs are in:
+ * - https://www.nxp.com.cn/docs/en/application-note/AN13329.pdf
+ * - DPAA2UM
+ */
+
+#include "opt_platform.h"
+#include "opt_acpi.h"
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/pmap.h>
+
+#ifdef FDT
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+MALLOC_DECLARE(M_DPAA2_MC);
+
+/* Table 6-1. MC Memory Map */
+#define MC_REG_MCFBA 0x20
+#define MC_REG_MCFBALR_OFF 0x00
+#define MC_REG_MCFBALR_MASK 0xe0000000
+#define MC_REG_MCFBAHR_OFF 0x04
+#define MC_REG_MCFBAHR_MASK 0x0001ffff
+
+/* Firmware Consoles. */
+#define MC_BUFFER_OFFSET 0x01000000
+#define MC_BUFFER_SIZE (1024 * 1024 * 16)
+#define MC_OFFSET_DELTA MC_BUFFER_OFFSET
+
+#define AIOP_BUFFER_OFFSET 0x06000000
+#define AIOP_BUFFER_SIZE (1024 * 1024 * 16)
+#define AIOP_OFFSET_DELTA 0
+
+/* MC and AIOP Magic words */
+#define MAGIC_MC 0x4d430100
+#define MAGIC_AIOP 0x41494F50
+
+#define LOG_HEADER_FLAG_BUFFER_WRAPAROUND \
+ 0x80000000
+#define LAST_BYTE(a) \
+ ((a) & ~(LOG_HEADER_FLAG_BUFFER_WRAPAROUND))
+
+struct dpaa2_cons_dev {
+ struct cdev *cdev;
+ struct mtx mtx;
+ size_t offset;
+ uint32_t magic;
+
+ uint32_t hdr_magic;
+ uint32_t hdr_eobyte;
+ uint32_t hdr_start;
+ uint32_t hdr_len;
+
+ uoff_t start;
+ uoff_t end;
+ uoff_t eod;
+ uoff_t cur;
+
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ vm_size_t size;
+};
+
+struct dpaa2_cons_softc {
+ struct resource *res;
+ bus_space_tag_t bst;
+ uint64_t mcfba;
+ struct dpaa2_cons_dev mc_cd;
+ struct dpaa2_cons_dev aiop_cd;
+};
+
+struct dpaa2_cons_hdr {
+ uint32_t magic;
+ uint32_t _reserved;
+ uint32_t start;
+ uint32_t len;
+ uint32_t eobyte;
+};
+
+#define DPAA2_MC_READ_4(_sc, _r) bus_read_4((_sc)->res, (_r))
+
+/* Management interface */
+static d_open_t dpaa2_cons_open;
+static d_close_t dpaa2_cons_close;
+static d_read_t dpaa2_cons_read;
+
+static struct cdevsw dpaa2_mc_cons_cdevsw = {
+ .d_version = D_VERSION,
+ .d_flags = 0,
+ .d_open = dpaa2_cons_open,
+ .d_close = dpaa2_cons_close,
+ .d_read = dpaa2_cons_read,
+ .d_name = "fsl_mc_console",
+};
+
+static struct cdevsw dpaa2_aiop_cons_cdevsw = {
+ .d_version = D_VERSION,
+ .d_flags = 0,
+ .d_open = dpaa2_cons_open,
+ .d_close = dpaa2_cons_close,
+ .d_read = dpaa2_cons_read,
+ .d_name = "fsl_aiop_console",
+};
+
+static size_t
+dpaa2_cons_read_bs(struct dpaa2_cons_dev *cd, size_t offset, void *dst, size_t len)
+{
+ size_t count, l;
+ uint8_t *p;
+
+ count = 0;
+ p = dst;
+ l = offset % 8;
+ if (l != 0) {
+ bus_space_read_region_1(cd->bst, cd->bsh, offset + count, p + count, l);
+ count += l;
+ len -= l;
+ }
+
+ l = len / 8;
+ if (l != 0) {
+ bus_space_read_region_8(cd->bst, cd->bsh, offset + count, (uint64_t *)(p + count), l);
+ l *= 8;
+ count += l;
+ len -= l;
+ }
+ l = len / 4;
+ if (l != 0) {
+ bus_space_read_region_4(cd->bst, cd->bsh, offset + count, (uint32_t *)(p + count), l);
+ l *= 4;
+ count += l;
+ len -= l;
+ }
+ l = len / 2;
+ if (l != 0) {
+ bus_space_read_region_2(cd->bst, cd->bsh, offset + count, (uint16_t *)(p + count), l);
+ l *= 2;
+ count += l;
+ len -= l;
+ }
+ if (len != 0) {
+ bus_space_read_region_1(cd->bst, cd->bsh, offset + count, p + count, len);
+ count += len;
+ }
+
+ return (count);
+}
+
+static int
+dpaa2_cons_open(struct cdev *cdev, int flags, int fmt, struct thread *td)
+{
+ struct dpaa2_cons_dev *cd;
+ struct dpaa2_cons_hdr hdr;
+ size_t rlen __diagused;
+ uint32_t wrapped;
+
+ if (flags & FWRITE)
+ return (EACCES);
+
+ cd = cdev->si_drv1;
+ if (cd->size == 0)
+ return (ENODEV);
+
+ mtx_lock(&cd->mtx);
+ rlen = dpaa2_cons_read_bs(cd, 0, &hdr, sizeof(hdr));
+ KASSERT(rlen == sizeof(hdr), ("%s:%d: rlen %zu != count %zu, cdev %p "
+ "cd %p\n", __func__, __LINE__, rlen, sizeof(hdr), cdev, cd));
+
+ cd->hdr_magic = hdr.magic;
+ if (cd->hdr_magic != cd->magic) {
+ mtx_unlock(&cd->mtx);
+ return (ENODEV);
+ }
+
+ cd->hdr_eobyte = hdr.eobyte;
+ cd->hdr_start = hdr.start;
+ cd->hdr_len = hdr.len;
+
+ cd->start = cd->hdr_start - cd->offset;
+ cd->end = cd->start + cd->hdr_len;
+
+ wrapped = cd->hdr_eobyte & LOG_HEADER_FLAG_BUFFER_WRAPAROUND;
+ cd->eod = cd->start + LAST_BYTE(cd->hdr_eobyte);
+
+ if (wrapped && cd->eod != cd->end)
+ cd->cur = cd->eod + 1;
+ else
+ cd->cur = cd->start;
+ mtx_unlock(&cd->mtx);
+
+ return (0);
+}
+
+static int
+dpaa2_cons_close(struct cdev *cdev, int flags, int fmt, struct thread *td)
+{
+ struct dpaa2_cons_dev *cd;
+
+ cd = cdev->si_drv1;
+ mtx_lock(&cd->mtx);
+ cd->hdr_magic = cd->hdr_eobyte = cd->hdr_start = cd->hdr_len = 0;
+ cd->start = cd->end = 0;
+ mtx_unlock(&cd->mtx);
+
+ return (0);
+}
+
+static int
+dpaa2_cons_read(struct cdev *cdev, struct uio *uio, int flag)
+{
+ char buf[128];
+ struct dpaa2_cons_dev *cd;
+ size_t len, size, count;
+ size_t rlen __diagused;
+ int error;
+
+ cd = cdev->si_drv1;
+ mtx_lock(&cd->mtx);
+ if (cd->cur == cd->eod) {
+ mtx_unlock(&cd->mtx);
+ return (0);
+ } else if (cd->cur > cd->eod) {
+ len = (cd->end - cd->cur) + (cd->eod - cd->start);
+ } else {
+ len = cd->eod - cd->cur;
+ }
+ size = cd->end - cd->cur;
+
+ if (len > size) {
+ /* dump cur [size] */
+ while (uio->uio_resid > 0) {
+ count = imin(sizeof(buf), uio->uio_resid);
+ if (count > size)
+ count = size;
+
+ rlen = dpaa2_cons_read_bs(cd, cd->cur, buf, count);
+ KASSERT(rlen == count, ("%s:%d: rlen %zu != count %zu, "
+ "cdev %p cd %p\n", __func__, __LINE__, rlen, count,
+ cdev, cd));
+
+ cd->cur += count;
+ len -= count;
+ size -= count;
+ mtx_unlock(&cd->mtx);
+ error = uiomove_frombuf(buf, count, uio);
+ if (error != 0 || uio->uio_resid == 0)
+ return (error);
+ mtx_lock(&cd->mtx);
+ }
+ cd->cur = cd->start;
+ }
+
+ /* dump cur [len] */
+ while (len > 0 && uio->uio_resid > 0) {
+ count = imin(sizeof(buf), uio->uio_resid);
+ if (count > len)
+ count = len;
+
+ rlen = dpaa2_cons_read_bs(cd, cd->cur, buf, count);
+ KASSERT(rlen == count, ("%s:%d: rlen %zu != count %zu, cdev %p "
+ "cd %p\n", __func__, __LINE__, rlen, count, cdev, cd));
+
+ cd->cur += count;
+ len -= count;
+ mtx_unlock(&cd->mtx);
+ error = uiomove_frombuf(buf, count, uio);
+ if (error != 0 || uio->uio_resid == 0)
+ return (error);
+ mtx_lock(&cd->mtx);
+ }
+ mtx_unlock(&cd->mtx);
+ return (0);
+}
+
+static int
+dpaa2_cons_create_dev(device_t dev, bus_addr_t pa, size_t size,
+ size_t offset, uint32_t magic, struct cdevsw *devsw,
+ struct dpaa2_cons_dev *cd)
+{
+ struct dpaa2_cons_softc *sc;
+ struct dpaa2_cons_hdr hdr;
+ struct make_dev_args md_args;
+ size_t len;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ error = bus_space_map(sc->bst, pa, size, 0, &cd->bsh);
+ if (error != 0) {
+ device_printf(dev, "%s: failed to map bus space %#jx/%zu: %d\n",
+ __func__, (uintmax_t)pa, size, error);
+ return (error);
+ }
+
+ cd->bst = sc->bst;
+ cd->size = size;
+
+ len = dpaa2_cons_read_bs(cd, 0, &hdr, sizeof(hdr));
+ if (len != sizeof(hdr)) {
+ device_printf(dev, "%s: failed to read hdr for %#jx/%zu: %d\n",
+ __func__, (uintmax_t)pa, size, error);
+ bus_space_unmap(cd->bst, cd->bsh, cd->size);
+ cd->size = 0;
+ return (EIO);
+ }
+
+ /* This checks probably needs to be removed one day? */
+ if (hdr.magic != magic) {
+ if (bootverbose)
+ device_printf(dev, "%s: magic wrong for %#jx/%zu: "
+ "%#010x != %#010x, no console?\n", __func__,
+ (uintmax_t)pa, size, hdr.magic, magic);
+ bus_space_unmap(cd->bst, cd->bsh, cd->size);
+ cd->size = 0;
+ return (ENOENT);
+ }
+
+ if (hdr.start - offset > size) {
+ device_printf(dev, "%s: range wrong for %#jx/%zu: %u - %zu > %zu\n",
+ __func__, (uintmax_t)pa, size, hdr.start, offset, size);
+ bus_space_unmap(cd->bst, cd->bsh, cd->size);
+ cd->size = 0;
+ return (ERANGE);
+ }
+
+ cd->offset = offset;
+ cd->magic = magic;
+ mtx_init(&cd->mtx, "dpaa2 cons", NULL, MTX_DEF);
+
+ make_dev_args_init(&md_args);
+ md_args.mda_devsw = devsw;
+ md_args.mda_uid = 0;
+ md_args.mda_gid = 69;
+ md_args.mda_mode = S_IRUSR | S_IRGRP;
+ md_args.mda_unit = 0;
+ md_args.mda_si_drv1 = cd;
+ error = make_dev_s(&md_args, &cd->cdev, "%s", devsw->d_name);
+ if (error != 0) {
+ device_printf(dev, "%s: make_dev_s failed for %#jx/%zu: %d\n",
+ __func__, (uintmax_t)pa, size, error);
+ mtx_destroy(&cd->mtx);
+ bus_space_unmap(cd->bst, cd->bsh, cd->size);
+ cd->size = 0;
+ return (error);
+ }
+
+ if (bootverbose)
+ device_printf(dev, "dpaa2 console %s at pa %#jx size %#010zx "
+ "(%zu) offset %zu, hdr: magic %#010x start %#010x len "
+ "%#010x eobyte %#010x\n", devsw->d_name, (uintmax_t)pa,
+ size, size, offset, hdr.magic, hdr.start, hdr.len, hdr.eobyte);
+
+ return (0);
+}
+
+static int
+dpaa2_cons_attach_common(device_t dev)
+{
+ struct dpaa2_cons_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ dpaa2_cons_create_dev(dev, (bus_addr_t)(sc->mcfba + MC_BUFFER_OFFSET),
+ MC_BUFFER_SIZE, MC_OFFSET_DELTA, MAGIC_MC,
+ &dpaa2_mc_cons_cdevsw, &sc->mc_cd);
+
+ dpaa2_cons_create_dev(dev, (bus_addr_t)(sc->mcfba + AIOP_BUFFER_OFFSET),
+ AIOP_BUFFER_SIZE, AIOP_OFFSET_DELTA, MAGIC_AIOP,
+ &dpaa2_aiop_cons_cdevsw, &sc->aiop_cd);
+
+ return (0);
+}
+
+static void
+dpaa2_cons_detach_common(struct dpaa2_cons_dev *cd)
+{
+
+ bus_space_unmap(cd->bst, cd->bsh, cd->size);
+ mtx_destroy(&cd->mtx);
+}
+
+static int
+dpaa2_cons_detach(device_t dev)
+{
+ struct dpaa2_cons_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (sc->aiop_cd.cdev != NULL)
+ destroy_dev(sc->aiop_cd.cdev);
+ if (sc->mc_cd.cdev != NULL)
+ destroy_dev(sc->mc_cd.cdev);
+
+ if (sc->aiop_cd.size != 0)
+ dpaa2_cons_detach_common(&sc->aiop_cd);
+ if (sc->mc_cd.size != 0)
+ dpaa2_cons_detach_common(&sc->mc_cd);
+
+ if (sc->res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->res),
+ sc->res);
+
+ return (0);
+}
+
+#ifdef __notyet__
+#ifdef ACPI
+static int
+dpaa2_cons_acpi_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ device_set_desc(dev, "DPAA2 Console Driver");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+dpaa2_cons_acpi_attach(device_t dev)
+{
+ struct dpaa2_cons_softc *sc;
+ uint32_t val;
+ int error, rid;
+
+ sc = device_get_softc(dev);
+
+ rid = 0;
+ sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (sc->res == NULL) {
+ device_printf(dev, "Could not allocate memory\n");
+ return (ENXIO);
+ }
+ sc->bst = rman_get_bustag(sc->res);
+
+ val = DPAA2_MC_READ_4(sc, MC_REG_MCFBALR_OFF);
+ val &= MC_REG_MCFBALR_MASK;
+ sc->mcfba |= val;
+ val = DPAA2_MC_READ_4(sc, MC_REG_MCFBAHR_OFF);
+ val &= MC_REG_MCFBAHR_MASK;
+ sc->mcfba |= ((uint64_t)val << 32);
+
+ error = dpaa2_cons_attach_common(dev);
+
+ return (error);
+}
+
+static device_method_t dpaa2_cons_acpi_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, dpaa2_cons_acpi_probe),
+ DEVMETHOD(device_attach, dpaa2_cons_acpi_attach),
+ DEVMETHOD(device_detach, dpaa2_cons_detach),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(dpaa2_cons_acpi, dpaa2_cons_acpi_driver, dpaa2_cons_acpi_methods,
+ sizeof(struct dpaa2_cons_softc));
+
+DRIVER_MODULE(dpaa2_cons_acpi, simplebus, dpaa2_cons_acpi_driver, 0, 0);
+MODULE_DEPEND(dpaa2_cons_acpi, dpaa2_mc, 1, 1, 1);
+#endif
+#endif /* 0 */
+
+#ifdef FDT
+static struct ofw_compat_data compat_data[] = {
+ { "fsl,dpaa2-console", 1 },
+ { NULL, 0 }
+};
+
+static int
+dpaa2_cons_fdt_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+ return (ENXIO);
+
+ device_set_desc(dev, "DPAA2 Console Driver");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+dpaa2_cons_fdt_attach(device_t dev)
+{
+ struct dpaa2_cons_softc *sc;
+ uint32_t val;
+ int error, rid;
+
+ sc = device_get_softc(dev);
+
+ rid = 0;
+ sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (sc->res == NULL) {
+ device_printf(dev, "Could not allocate memory\n");
+ return (ENXIO);
+ }
+ sc->bst = rman_get_bustag(sc->res);
+
+ val = DPAA2_MC_READ_4(sc, MC_REG_MCFBALR_OFF);
+ val &= MC_REG_MCFBALR_MASK;
+ sc->mcfba |= val;
+ val = DPAA2_MC_READ_4(sc, MC_REG_MCFBAHR_OFF);
+ val &= MC_REG_MCFBAHR_MASK;
+ sc->mcfba |= ((uint64_t)val << 32);
+
+ error = dpaa2_cons_attach_common(dev);
+
+ return (error);
+}
+
+static device_method_t dpaa2_cons_fdt_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, dpaa2_cons_fdt_probe),
+ DEVMETHOD(device_attach, dpaa2_cons_fdt_attach),
+ DEVMETHOD(device_detach, dpaa2_cons_detach),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(dpaa2_cons_fdt, dpaa2_cons_fdt_driver, dpaa2_cons_fdt_methods,
+ sizeof(struct dpaa2_cons_softc));
+
+DRIVER_MODULE(dpaa2_cons_fdt, simplebus, dpaa2_cons_fdt_driver, 0, 0);
+#endif
diff --git a/sys/modules/dpaa2/Makefile b/sys/modules/dpaa2/Makefile
--- a/sys/modules/dpaa2/Makefile
+++ b/sys/modules/dpaa2/Makefile
@@ -17,6 +17,8 @@
SRCS+= dpaa2_mc_if.c dpaa2_mc_if.h
SRCS+= memac_mdio_common.c memac_mdio_if.c memac_mdio_if.h
+SRCS+= dpaa2_console.c
+
SRCS+= bus_if.h device_if.h miibus_if.h
SRCS+= pcib_if.h pci_if.h
SRCS+= opt_acpi.h opt_platform.h

File Metadata

Mime Type
text/plain
Expires
Mon, Nov 18, 2:33 PM (1 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14699375
Default Alt Text
D38592.id117213.diff (15 KB)

Event Timeline