Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102758524
D43044.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D43044.diff
View Options
diff --git a/sys/dev/firmware/arm/scmi.h b/sys/dev/firmware/arm/scmi.h
--- a/sys/dev/firmware/arm/scmi.h
+++ b/sys/dev/firmware/arm/scmi.h
@@ -51,7 +51,6 @@
struct scmi_softc {
struct simplebus_softc simplebus_sc;
device_t dev;
- device_t a2p_dev;
struct mtx mtx;
};
diff --git a/sys/dev/firmware/arm/scmi.c b/sys/dev/firmware/arm/scmi.c
--- a/sys/dev/firmware/arm/scmi.c
+++ b/sys/dev/firmware/arm/scmi.c
@@ -43,11 +43,8 @@
#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"
-#include "scmi_shmem.h"
#define SCMI_HDR_TOKEN_S 18
#define SCMI_HDR_TOKEN_BF (0x3fff)
@@ -75,7 +72,6 @@
static int
scmi_request_locked(struct scmi_softc *sc, struct scmi_req *req)
{
- uint32_t reply_header;
int ret;
SCMI_ASSERT_LOCKED(sc);
@@ -85,29 +81,12 @@
req->msg_header |= SCMI_MSG_TYPE_CMD << SCMI_HDR_MESSAGE_TYPE_S;
req->msg_header |= req->protocol_id << SCMI_HDR_PROTOCOL_ID_S;
- ret = scmi_shmem_prepare_msg(sc->a2p_dev, req, cold);
- if (ret != 0)
- return (ret);
-
- ret = SCMI_XFER_MSG(sc->dev);
- if (ret != 0)
- goto out;
-
- /* Read header. */
- ret = scmi_shmem_read_msg_header(sc->a2p_dev, &reply_header);
- if (ret != 0)
- goto out;
-
- if (reply_header != req->msg_header) {
- ret = EPROTO;
- goto out;
- }
+ ret = SCMI_XFER_MSG(sc->dev, req);
+ if (ret == 0)
+ ret = SCMI_COLLECT_REPLY(sc->dev, req);
- ret = scmi_shmem_read_msg_payload(sc->a2p_dev, req->out_buf,
- req->out_size);
-
-out:
- scmi_shmem_tx_complete(sc->a2p_dev);
+ if (ret == 0 || ret != EBUSY)
+ SCMI_TX_COMPLETE(sc->dev, NULL);
return (ret);
}
@@ -141,16 +120,14 @@
if (node == -1)
return (ENXIO);
- sc->a2p_dev = scmi_shmem_get(dev, node, SCMI_CHAN_A2P);
- if (sc->a2p_dev == NULL) {
- device_printf(dev, "A2P shmem dev not found.\n");
- return (ENXIO);
- }
-
mtx_init(&sc->mtx, device_get_nameunit(dev), "SCMI", MTX_DEF);
simplebus_init(dev, node);
+ error = SCMI_TRANSPORT_INIT(dev);
+ if (error != 0)
+ return (error);
+
/*
* Allow devices to identify.
*/
@@ -171,6 +148,7 @@
scmi_detach(device_t dev)
{
+ SCMI_TRANSPORT_CLEANUP(dev);
return (0);
}
diff --git a/sys/dev/firmware/arm/scmi_if.m b/sys/dev/firmware/arm/scmi_if.m
--- a/sys/dev/firmware/arm/scmi_if.m
+++ b/sys/dev/firmware/arm/scmi_if.m
@@ -27,6 +27,29 @@
INTERFACE scmi;
+HEADER {
+ struct scmi_req;
+};
+
+METHOD int transport_init {
+ device_t dev;
+};
+
+METHOD void transport_cleanup {
+ device_t dev;
+};
+
METHOD int xfer_msg {
device_t dev;
+ struct scmi_req *req;
+};
+
+METHOD int collect_reply {
+ device_t dev;
+ struct scmi_req *req;
+};
+
+METHOD void tx_complete {
+ device_t dev;
+ void *chan;
};
diff --git a/sys/dev/firmware/arm/scmi_mailbox.c b/sys/dev/firmware/arm/scmi_mailbox.c
--- a/sys/dev/firmware/arm/scmi_mailbox.c
+++ b/sys/dev/firmware/arm/scmi_mailbox.c
@@ -53,10 +53,19 @@
struct scmi_mailbox_softc {
struct scmi_softc base;
+ device_t a2p_dev;
struct arm_doorbell *db;
int req_done;
};
+static int scmi_mailbox_transport_init(device_t);
+static void scmi_mailbox_transport_cleanup(device_t);
+static int scmi_mailbox_xfer_msg(device_t, struct scmi_req *);
+static int scmi_mailbox_collect_reply(device_t, struct scmi_req *);
+static void scmi_mailbox_tx_complete(device_t, void *);
+
+static int scmi_mailbox_probe(device_t);
+
static void
scmi_mailbox_callback(void *arg)
{
@@ -73,16 +82,64 @@
}
static int
-scmi_mailbox_xfer_msg(device_t dev)
+scmi_mailbox_transport_init(device_t dev)
+{
+ struct scmi_mailbox_softc *sc;
+ phandle_t node;
+
+ sc = device_get_softc(dev);
+
+ node = ofw_bus_get_node(dev);
+ if (node == -1)
+ return (ENXIO);
+ /*
+ * TODO
+ * - Support P2A shmem + IRQ/doorbell
+ * - Support other mailbox devices
+ */
+ sc->a2p_dev = scmi_shmem_get(dev, node, SCMI_CHAN_A2P);
+ if (sc->a2p_dev == NULL) {
+ device_printf(dev, "A2P shmem dev not found.\n");
+ return (ENXIO);
+ }
+
+ /* TODO: Fix ofw_get...mbox doorbell names NOT required in Linux DT */
+ 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);
+
+ return (0);
+}
+
+static void
+scmi_mailbox_transport_cleanup(device_t dev)
+{
+ struct scmi_mailbox_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ arm_doorbell_set_handler(sc->db, NULL, NULL);
+}
+
+static int
+scmi_mailbox_xfer_msg(device_t dev, struct scmi_req *req)
{
struct scmi_mailbox_softc *sc;
- int timeout;
+ int ret, timeout;
sc = device_get_softc(dev);
SCMI_ASSERT_LOCKED(&sc->base);
sc->req_done = 0;
+ ret = scmi_shmem_prepare_msg(sc->a2p_dev, req, cold);
+ if (ret != 0)
+ return (ret);
+
/* Interrupt SCP firmware. */
arm_doorbell_set(sc->db);
@@ -92,7 +149,7 @@
do {
if (cold) {
- if (scmi_shmem_poll_msg(sc->base.a2p_dev))
+ if (scmi_shmem_poll_msg(sc->a2p_dev))
break;
DELAY(10000);
} else {
@@ -103,7 +160,7 @@
} while (timeout--);
if (timeout <= 0)
- return (-1);
+ return (ETIMEDOUT);
dprintf("%s: got reply, timeout %d\n", __func__, timeout);
@@ -111,63 +168,59 @@
}
static int
-scmi_mailbox_probe(device_t dev)
+scmi_mailbox_collect_reply(device_t dev, struct scmi_req *req)
{
+ struct scmi_mailbox_softc *sc;
+ uint32_t reply_header;
+ int ret;
- if (!ofw_bus_is_compatible(dev, "arm,scmi"))
- return (ENXIO);
+ sc = device_get_softc(dev);
- if (!ofw_bus_status_okay(dev))
- return (ENXIO);
+ /* Read header. */
+ ret = scmi_shmem_read_msg_header(sc->a2p_dev, &reply_header);
+ if (ret != 0)
+ return (ret);
- device_set_desc(dev, "ARM SCMI interface driver");
+ if (reply_header != req->msg_header)
+ return (EPROTO);
- return (BUS_PROBE_DEFAULT);
+ return (scmi_shmem_read_msg_payload(sc->a2p_dev, req->out_buf,
+ req->out_size));
}
-static int
-scmi_mailbox_attach(device_t dev)
+static void
+scmi_mailbox_tx_complete(device_t dev, void *chan)
{
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);
+ scmi_shmem_tx_complete(sc->a2p_dev);
}
static int
-scmi_mailbox_detach(device_t dev)
+scmi_mailbox_probe(device_t dev)
{
- struct scmi_mailbox_softc *sc;
- sc = device_get_softc(dev);
+ if (!ofw_bus_is_compatible(dev, "arm,scmi"))
+ return (ENXIO);
- arm_doorbell_set_handler(sc->db, NULL, NULL);
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
- return (0);
+ device_set_desc(dev, "ARM SCMI interface driver");
+
+ return (BUS_PROBE_DEFAULT);
}
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(scmi_transport_init, scmi_mailbox_transport_init),
+ DEVMETHOD(scmi_transport_cleanup, scmi_mailbox_transport_cleanup),
+ DEVMETHOD(scmi_xfer_msg, scmi_mailbox_xfer_msg),
+ DEVMETHOD(scmi_collect_reply, scmi_mailbox_collect_reply),
+ DEVMETHOD(scmi_tx_complete, scmi_mailbox_tx_complete),
DEVMETHOD_END
};
diff --git a/sys/dev/firmware/arm/scmi_shmem.c b/sys/dev/firmware/arm/scmi_shmem.c
--- a/sys/dev/firmware/arm/scmi_shmem.c
+++ b/sys/dev/firmware/arm/scmi_shmem.c
@@ -210,7 +210,7 @@
if ((channel_status & SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE) == 0) {
scmi_shmem_release_channel(sc);
device_printf(dev, "Shmem channel busy. Abort !.\n");
- return (1);
+ return (EBUSY);
}
/* Update header */
diff --git a/sys/dev/firmware/arm/scmi_smc.c b/sys/dev/firmware/arm/scmi_smc.c
--- a/sys/dev/firmware/arm/scmi_smc.c
+++ b/sys/dev/firmware/arm/scmi_smc.c
@@ -48,25 +48,88 @@
#include "scmi.h"
#include "scmi_protocols.h"
+#include "scmi_shmem.h"
struct scmi_smc_softc {
struct scmi_softc base;
uint32_t smc_id;
+ device_t a2p_dev;
};
+static int scmi_smc_transport_init(device_t);
+static int scmi_smc_xfer_msg(device_t, struct scmi_req *);
+static int scmi_smc_collect_reply(device_t, struct scmi_req *);
+static void scmi_smc_tx_complete(device_t, void *);
+
+static int scmi_smc_probe(device_t);
+static int scmi_smc_attach(device_t);
+
static int
-scmi_smc_xfer_msg(device_t dev)
+scmi_smc_transport_init(device_t dev)
{
struct scmi_smc_softc *sc;
+ phandle_t node;
+ ssize_t len;
+
+ sc = device_get_softc(dev);
+
+ node = ofw_bus_get_node(dev);
+ len = OF_getencprop(node, "arm,smc-id", &sc->smc_id,
+ sizeof(sc->smc_id));
+ if (len <= 0) {
+ device_printf(dev, "No SMC ID found\n");
+ return (EINVAL);
+ }
+
+ device_printf(dev, "smc id %x\n", sc->smc_id);
+
+ sc->a2p_dev = scmi_shmem_get(dev, node, SCMI_CHAN_A2P);
+ if (sc->a2p_dev == NULL) {
+ device_printf(dev, "A2P shmem dev not found.\n");
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static int
+scmi_smc_xfer_msg(device_t dev, struct scmi_req *req)
+{
+ struct scmi_smc_softc *sc;
+ int ret;
sc = device_get_softc(dev);
SCMI_ASSERT_LOCKED(&sc->base);
+ ret = scmi_shmem_prepare_msg(sc->a2p_dev, req, cold);
+ if (ret != 0)
+ return (ret);
+
arm_smccc_smc(sc->smc_id, 0, 0, 0, 0, 0, 0, 0, NULL);
return (0);
}
+static int
+scmi_smc_collect_reply(device_t dev, struct scmi_req *req)
+{
+ struct scmi_smc_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ return (scmi_shmem_read_msg_payload(sc->a2p_dev, req->out_buf,
+ req->out_size));
+}
+
+static void
+scmi_smc_tx_complete(device_t dev, void *chan)
+{
+ struct scmi_smc_softc *sc;
+
+ sc = device_get_softc(dev);
+ scmi_shmem_tx_complete(sc->a2p_dev);
+}
+
static int
scmi_smc_probe(device_t dev)
{
@@ -104,20 +167,15 @@
return (scmi_attach(dev));
}
-static int
-scmi_smc_detach(device_t dev)
-{
-
- return (0);
-}
-
static device_method_t scmi_smc_methods[] = {
DEVMETHOD(device_probe, scmi_smc_probe),
DEVMETHOD(device_attach, scmi_smc_attach),
- DEVMETHOD(device_detach, scmi_smc_detach),
/* SCMI interface */
- DEVMETHOD(scmi_xfer_msg, scmi_smc_xfer_msg),
+ DEVMETHOD(scmi_transport_init, scmi_smc_transport_init),
+ DEVMETHOD(scmi_xfer_msg, scmi_smc_xfer_msg),
+ DEVMETHOD(scmi_collect_reply, scmi_smc_collect_reply),
+ DEVMETHOD(scmi_tx_complete, scmi_smc_tx_complete),
DEVMETHOD_END
};
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Nov 17, 6:33 PM (21 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14683236
Default Alt Text
D43044.diff (10 KB)
Attached To
Mode
D43044: scmi: Add new SCMI interfaces for init and message processing
Attached
Detach File
Event Timeline
Log In to Comment