The branch main has been updated by andrew:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=d46f01fd590eab5b7c25c7b218d390704a5bcb81

commit d46f01fd590eab5b7c25c7b218d390704a5bcb81
Author:     Andrew Turner <[email protected]>
AuthorDate: 2023-10-04 09:32:29 +0000
Commit:     Andrew Turner <[email protected]>
CommitDate: 2024-04-11 09:58:56 +0000

    scmi: Split out the SCMI mailbox to a new file
    
    Add a new SCMI interface file to allow for multiple kind of transports
    and move the mailbox transport to its own file, using the new interface.
    
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D43039
---
 sys/conf/files.arm64                |   2 +
 sys/dev/firmware/arm/scmi.c         |  82 ++---------------
 sys/dev/firmware/arm/scmi.h         |  13 +++
 sys/dev/firmware/arm/scmi_if.m      |  32 +++++++
 sys/dev/firmware/arm/scmi_mailbox.c | 178 ++++++++++++++++++++++++++++++++++++
 5 files changed, 232 insertions(+), 75 deletions(-)

diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index 293a0ae1c0f9..5541a18af659 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -272,6 +272,8 @@ dev/etherswitch/felix/felix.c                       
optional enetc etherswitch fdt felix pci soc_nxp
 
 dev/firmware/arm/scmi.c                                optional fdt scmi
 dev/firmware/arm/scmi_clk.c                    optional fdt scmi
+dev/firmware/arm/scmi_if.m                     optional fdt scmi
+dev/firmware/arm/scmi_mailbox.c                        optional fdt scmi
 dev/firmware/arm/scmi_shmem.c                  optional fdt scmi
 
 dev/gpio/pl061.c                               optional pl061 gpio
diff --git a/sys/dev/firmware/arm/scmi.c b/sys/dev/firmware/arm/scmi.c
index 3101be245ee1..fae4ec676a17 100644
--- a/sys/dev/firmware/arm/scmi.c
+++ b/sys/dev/firmware/arm/scmi.c
@@ -47,15 +47,6 @@
 #include "scmi.h"
 #include "scmi_protocols.h"
 
-struct scmi_softc {
-       struct simplebus_softc  simplebus_sc;
-       device_t                dev;
-       device_t                tx_shmem;
-       struct arm_doorbell     *db;
-       struct mtx              mtx;
-       int                     req_done;
-};
-
 static device_t
 scmi_get_shmem(struct scmi_softc *sc, int index)
 {
@@ -90,26 +81,11 @@ scmi_get_shmem(struct scmi_softc *sc, int index)
        return (dev);
 }
 
-static void
-scmi_callback(void *arg)
-{
-       struct scmi_softc *sc;
-
-       sc = arg;
-
-       dprintf("%s sc %p\n", __func__, sc);
-
-       SCMI_LOCK(sc);
-       sc->req_done = 1;
-       wakeup(sc);
-       SCMI_UNLOCK(sc);
-}
-
 static int
 scmi_request_locked(struct scmi_softc *sc, struct scmi_req *req)
 {
        struct scmi_smt_header hdr;
-       int timeout;
+       int ret;
 
        bzero(&hdr, sizeof(struct scmi_smt_header));
 
@@ -125,6 +101,7 @@ scmi_request_locked(struct scmi_softc *sc, struct scmi_req 
*req)
        hdr.channel_status &= ~SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE;
        hdr.msg_header = req->protocol_id << SMT_HEADER_PROTOCOL_ID_S;
        hdr.msg_header |= req->message_id << SMT_HEADER_MESSAGE_ID_S;
+       /* TODO: Allocate a token */
        hdr.length = sizeof(hdr.msg_header) + req->in_size;
        hdr.flags |= SCMI_SHMEM_FLAG_INTR_ENABLED;
 
@@ -135,31 +112,9 @@ scmi_request_locked(struct scmi_softc *sc, struct scmi_req 
*req)
        scmi_shmem_write(sc->tx_shmem, SMT_HEADER_SIZE, req->in_buf,
            req->in_size);
 
-       sc->req_done = 0;
-
-       /* Interrupt SCP firmware. */
-       arm_doorbell_set(sc->db);
-
-       timeout = 200;
-
-       dprintf("%s: request\n", __func__);
-
-       do {
-               if (cold) {
-                       if (arm_doorbell_get(sc->db))
-                               break;
-                       DELAY(10000);
-               } else {
-                       msleep(sc, &sc->mtx, 0, "scmi", hz / 10);
-                       if (sc->req_done)
-                               break;
-               }
-       } while (timeout--);
-
-       if (timeout <= 0)
-               return (-1);
-
-       dprintf("%s: got reply, timeout %d\n", __func__, timeout);
+       ret = SCMI_XFER_MSG(sc->dev);
+       if (ret != 0)
+               return (ret);
 
        /* Read header. */
        scmi_shmem_read(sc->tx_shmem, 0, &hdr, SMT_HEADER_SIZE);
@@ -186,22 +141,7 @@ scmi_request(device_t dev, struct scmi_req *req)
        return (error);
 }
 
-static int
-scmi_probe(device_t dev)
-{
-
-       if (!ofw_bus_is_compatible(dev, "arm,scmi"))
-               return (ENXIO);
-
-       if (!ofw_bus_status_okay(dev))
-               return (ENXIO);
-
-       device_set_desc(dev, "ARM SCMI interface driver");
-
-       return (BUS_PROBE_DEFAULT);
-}
-
-static int
+int
 scmi_attach(device_t dev)
 {
        struct scmi_softc *sc;
@@ -221,16 +161,8 @@ scmi_attach(device_t dev)
                return (ENXIO);
        }
 
-       sc->db = arm_doorbell_ofw_get(sc->dev, "tx");
-       if (sc->db == NULL) {
-               device_printf(dev, "Doorbell device not found.\n");
-               return (ENXIO);
-       }
-
        mtx_init(&sc->mtx, device_get_nameunit(dev), "SCMI", MTX_DEF);
 
-       arm_doorbell_set_handler(sc->db, scmi_callback, sc);
-
        simplebus_init(dev, node);
 
        /*
@@ -257,9 +189,9 @@ scmi_detach(device_t dev)
 }
 
 static device_method_t scmi_methods[] = {
-       DEVMETHOD(device_probe,         scmi_probe),
        DEVMETHOD(device_attach,        scmi_attach),
        DEVMETHOD(device_detach,        scmi_detach),
+
        DEVMETHOD_END
 };
 
diff --git a/sys/dev/firmware/arm/scmi.h b/sys/dev/firmware/arm/scmi.h
index 34faa3ff7e73..f1c81a609894 100644
--- a/sys/dev/firmware/arm/scmi.h
+++ b/sys/dev/firmware/arm/scmi.h
@@ -31,12 +31,21 @@
 #ifndef        _ARM64_SCMI_SCMI_H_
 #define        _ARM64_SCMI_SCMI_H_
 
+#include "scmi_if.h"
+
 #define        SCMI_LOCK(sc)           mtx_lock(&(sc)->mtx)
 #define        SCMI_UNLOCK(sc)         mtx_unlock(&(sc)->mtx)
 #define        SCMI_ASSERT_LOCKED(sc)  mtx_assert(&(sc)->mtx, MA_OWNED)
 
 #define dprintf(fmt, ...)
 
+struct scmi_softc {
+       struct simplebus_softc  simplebus_sc;
+       device_t                dev;
+       device_t                tx_shmem;
+       struct mtx              mtx;
+};
+
 /* Shared Memory Transfer. */
 struct scmi_smt_header {
        uint32_t reserved;
@@ -71,7 +80,11 @@ struct scmi_req {
        uint32_t out_size;
 };
 
+DECLARE_CLASS(scmi_driver);
+
+int scmi_attach(device_t dev);
 int scmi_request(device_t dev, struct scmi_req *req);
+
 void scmi_shmem_read(device_t dev, bus_size_t offset, void *buf,
     bus_size_t len);
 void scmi_shmem_write(device_t dev, bus_size_t offset, const void *buf,
diff --git a/sys/dev/firmware/arm/scmi_if.m b/sys/dev/firmware/arm/scmi_if.m
new file mode 100644
index 000000000000..524cf0fb0d66
--- /dev/null
+++ b/sys/dev/firmware/arm/scmi_if.m
@@ -0,0 +1,32 @@
+#-
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2023 Arm Ltd
+#
+# 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 unmodified, 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 ``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 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.
+#
+
+INTERFACE scmi;
+
+METHOD int xfer_msg {
+       device_t dev;
+};
diff --git a/sys/dev/firmware/arm/scmi_mailbox.c 
b/sys/dev/firmware/arm/scmi_mailbox.c
new file mode 100644
index 000000000000..bebdc7348b98
--- /dev/null
+++ b/sys/dev/firmware/arm/scmi_mailbox.c
@@ -0,0 +1,178 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2022 Ruslan Bukin <[email protected]>
+ * Copyright (c) 2023 Arm Ltd
+ *
+ * This work was supported by Innovate UK project 105694, "Digital Security
+ * by Design (DSbD) Technology Platform Prototype".
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+
+#include <dev/clk/clk.h>
+#include <dev/fdt/simplebus.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "dev/mailbox/arm/arm_doorbell.h"
+
+#include "scmi.h"
+#include "scmi_protocols.h"
+
+struct scmi_mailbox_softc {
+       struct scmi_softc       base;
+       struct arm_doorbell     *db;
+       int                     req_done;
+};
+
+static void
+scmi_mailbox_callback(void *arg)
+{
+       struct scmi_mailbox_softc *sc;
+
+       sc = arg;
+
+       dprintf("%s sc %p\n", __func__, sc);
+
+       SCMI_LOCK(&sc->base);
+       sc->req_done = 1;
+       wakeup(sc);
+       SCMI_UNLOCK(&sc->base);
+}
+
+static int
+scmi_mailbox_xfer_msg(device_t dev)
+{
+       struct scmi_mailbox_softc *sc;
+       int timeout;
+
+       sc = device_get_softc(dev);
+       SCMI_ASSERT_LOCKED(&sc->base);
+
+       sc->req_done = 0;
+
+       /* Interrupt SCP firmware. */
+       arm_doorbell_set(sc->db);
+
+       timeout = 200;
+
+       dprintf("%s: request\n", __func__);
+
+       do {
+               if (cold) {
+                       if (arm_doorbell_get(sc->db))
+                               break;
+                       DELAY(10000);
+               } else {
+                       msleep(sc, &sc->base.mtx, 0, "scmi", hz / 10);
+                       if (sc->req_done)
+                               break;
+               }
+       } while (timeout--);
+
+       if (timeout <= 0)
+               return (-1);
+
+       dprintf("%s: got reply, timeout %d\n", __func__, timeout);
+
+       return (0);
+}
+
+static int
+scmi_mailbox_probe(device_t dev)
+{
+
+       if (!ofw_bus_is_compatible(dev, "arm,scmi"))
+               return (ENXIO);
+
+       if (!ofw_bus_status_okay(dev))
+               return (ENXIO);
+
+       device_set_desc(dev, "ARM SCMI interface driver");
+
+       return (BUS_PROBE_DEFAULT);
+}
+
+static int
+scmi_mailbox_attach(device_t dev)
+{
+       struct scmi_mailbox_softc *sc;
+       int ret;
+
+       sc = device_get_softc(dev);
+
+       /* TODO: Support other mailbox devices */
+       sc->db = arm_doorbell_ofw_get(dev, "tx");
+       if (sc->db == NULL) {
+               device_printf(dev, "Doorbell device not found.\n");
+               return (ENXIO);
+       }
+
+       arm_doorbell_set_handler(sc->db, scmi_mailbox_callback, sc);
+
+       ret = scmi_attach(dev);
+       if (ret != 0)
+               arm_doorbell_set_handler(sc->db, NULL, NULL);
+
+       return (ret);
+}
+
+static int
+scmi_mailbox_detach(device_t dev)
+{
+       struct scmi_mailbox_softc *sc;
+
+       sc = device_get_softc(dev);
+
+       arm_doorbell_set_handler(sc->db, NULL, NULL);
+
+       return (0);
+}
+
+static device_method_t scmi_mailbox_methods[] = {
+       DEVMETHOD(device_probe,         scmi_mailbox_probe),
+       DEVMETHOD(device_attach,        scmi_mailbox_attach),
+       DEVMETHOD(device_detach,        scmi_mailbox_detach),
+
+       /* SCMI interface */
+       DEVMETHOD(scmi_xfer_msg,        scmi_mailbox_xfer_msg),
+
+       DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(scmi_mailbox, scmi_mailbox_driver, scmi_mailbox_methods,
+    sizeof(struct scmi_mailbox_softc), scmi_driver);
+
+DRIVER_MODULE(scmi_mailbox, simplebus, scmi_mailbox_driver, 0, 0);
+MODULE_VERSION(scmi_mailbox, 1);

Reply via email to