[Differential] D42286: support for scmi-smc transport
"titus_edc.ro (Titus Manea)" <[email protected]>
| Newsgroups | gmane.os.freebsd.devel.arm |
|---|---|
| Message-ID | <[email protected]> |
titus_edc.ro created this revision. titus_edc.ro added a reviewer: freebsd-arm-list. Herald added a subscriber: imp. Herald added a reviewer: andrew. Herald added a reviewer: andrew. titus_edc.ro requested review of this revision. REVISION SUMMARY add support for arm,scmi-smc transport i used to enable cpu clock / cpufreq_dt on rk3566 boards also and glue code for clk_recalc_freq driver should load after mmio-shmem but before cpufreq_dt REPOSITORY rG FreeBSD src repository REVISION DETAIL https://reviews.freebsd.org/D42286 AFFECTED FILES sys/dev/firmware/arm/scmi.c sys/dev/firmware/arm/scmi_clk.c EMAIL PREFERENCES https://reviews.freebsd.org/settings/panel/emailpreferences/ To: titus_edc.ro, freebsd-arm-list, andrew Cc: imp, pstef, dsl
D42286.129076.patch
(text/x-patch, 4.2 KB)
diff --git a/sys/dev/firmware/arm/scmi_clk.c b/sys/dev/firmware/arm/scmi_clk.c
--- a/sys/dev/firmware/arm/scmi_clk.c
+++ b/sys/dev/firmware/arm/scmi_clk.c
@@ -155,8 +155,16 @@
static int
scmi_clknode_recalc_freq(struct clknode *clk, uint64_t *freq)
{
+ struct scmi_clknode_softc *clk_sc;
+ struct scmi_clk_softc *sc;
+ int error;
+ clk_sc = clknode_get_softc(clk);
+ sc = device_get_softc(clk_sc->dev);
- return (0);
+ error = scmi_clk_get_rate(sc, clk_sc->clock_id, freq);
+ dprintf("%s: %ld\n", __func__, *freq);
+
+ return (error);
}
static int
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
@@ -44,10 +44,15 @@
#include <dev/ofw/ofw_bus_subr.h>
#include "dev/mailbox/arm/arm_doorbell.h"
+#include "dev/psci/psci.h"
#include "scmi.h"
#include "scmi_protocols.h"
+enum scmi_transport {
+ SCMI_SMC = 1,
+ SCMI_MBOX,
+};
struct scmi_softc {
struct simplebus_softc simplebus_sc;
device_t dev;
@@ -55,6 +60,8 @@
struct arm_doorbell *db;
struct mtx mtx;
int req_done;
+ uint32_t smc_id;
+ uint8_t ttype;
};
static device_t
@@ -110,7 +117,7 @@
scmi_request_locked(struct scmi_softc *sc, struct scmi_req *req)
{
struct scmi_smt_header hdr;
- int timeout;
+ int timeout, status;
bzero(&hdr, sizeof(struct scmi_smt_header));
@@ -127,7 +134,8 @@
hdr.msg_header = req->protocol_id << SMT_HEADER_PROTOCOL_ID_S;
hdr.msg_header |= req->message_id << SMT_HEADER_MESSAGE_ID_S;
hdr.length = sizeof(hdr.msg_header) + req->in_size;
- hdr.flags |= SCMI_SHMEM_FLAG_INTR_ENABLED;
+ if(sc->ttype == SCMI_MBOX)
+ hdr.flags |= SCMI_SHMEM_FLAG_INTR_ENABLED;
/* Write header */
scmi_shmem_write(sc->tx_shmem, 0, &hdr, SMT_HEADER_SIZE);
@@ -135,7 +143,7 @@
/* Write request */
scmi_shmem_write(sc->tx_shmem, SMT_HEADER_SIZE, req->in_buf,
req->in_size);
-
+ if(sc->ttype == SCMI_MBOX) {
sc->req_done = 0;
/* Interrupt SCP firmware. */
@@ -161,14 +169,18 @@
return (-1);
dprintf("%s: got reply, timeout %d\n", __func__, timeout);
-
+ } else {
+ status = psci_call(sc->smc_id, 0, 0, 0);
+ if(status)
+ return (status);
+ }
/* Read header. */
scmi_shmem_read(sc->tx_shmem, 0, &hdr, SMT_HEADER_SIZE);
/* Read response */
scmi_shmem_read(sc->tx_shmem, SMT_HEADER_SIZE, req->out_buf,
req->out_size);
-
+/* printf("TRALALA :%08x\n",hdr.channel_status);*/
return (0);
}
@@ -187,12 +199,17 @@
return (error);
}
+
+static struct ofw_compat_data compat_data[] = {
+ {"arm,scmi", SCMI_MBOX},
+ {"arm,scmi-smc", SCMI_SMC},
+ {NULL, 0}
+};
static int
scmi_probe(device_t dev)
{
-
- if (!ofw_bus_is_compatible(dev, "arm,scmi"))
- return (ENXIO);
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
if (!ofw_bus_status_okay(dev))
return (ENXIO);
@@ -208,10 +225,9 @@
struct scmi_softc *sc;
phandle_t node;
int error;
-
sc = device_get_softc(dev);
sc->dev = dev;
-
+ sc->ttype = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
node = ofw_bus_get_node(dev);
if (node == -1)
return (ENXIO);
@@ -222,16 +238,22 @@
return (ENXIO);
}
- sc->db = arm_doorbell_ofw_get(sc->dev, "tx");
- if (sc->db == NULL) {
- device_printf(dev, "Doorbell device not found.\n");
+ if(sc->ttype == SCMI_MBOX) {
+ sc->db = arm_doorbell_ofw_get(sc->dev, "tx");
+ if (sc->db == NULL) {
+ device_printf(dev, "Doorbell device not found.\n");
+ return (ENXIO);
+ }
+
+ arm_doorbell_set_handler(sc->db, scmi_callback, sc);
+ } else {
+ if(OF_getencprop(node, "arm,smc-id", &sc->smc_id, sizeof(sc->smc_id)) <= 0) {
+ device_printf(dev, "arm,smc-id 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);
/*
@@ -267,5 +289,5 @@
DEFINE_CLASS_1(scmi, scmi_driver, scmi_methods, sizeof(struct scmi_softc),
simplebus_driver);
-DRIVER_MODULE(scmi, simplebus, scmi_driver, 0, 0);
+EARLY_DRIVER_MODULE(scmi, simplebus, scmi_driver, 0, 0, BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_LATE);
MODULE_VERSION(scmi, 1);