From: Alice Guo <alice....@nxp.com>

This patch adds SCMI pin control protocol support to make the pin
controller driver based on SCMI, such as
drivers/pinctrl/nxp/pinctrl-imx-scmi.c, can be bound to the SCMI agent
device whose protocol id is 0x19.

Add U_BOOT_SCMI_PROTO_DRIVER() so that the SCMI agent device can choose
which SCMI protocol driver to bind by the bind function of struct
driver. This can avoid putting i.MX related code in scmi_agent-uclass.c.

Signed-off-by: Alice Guo <alice....@nxp.com>
---
 drivers/firmware/scmi/scmi_agent-uclass.c | 25 +++++++++++++++++++++++++
 drivers/pinctrl/nxp/pinctrl-imx-scmi.c    |  7 +++++++
 include/scmi_agent-uclass.h               | 17 +++++++++++++++++
 3 files changed, 49 insertions(+)

diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c 
b/drivers/firmware/scmi/scmi_agent-uclass.c
index 8c907c3b032..2ffdd5c881e 100644
--- a/drivers/firmware/scmi/scmi_agent-uclass.c
+++ b/drivers/firmware/scmi/scmi_agent-uclass.c
@@ -97,6 +97,9 @@ struct udevice *scmi_get_protocol(struct udevice *dev,
        case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
                proto = priv->voltagedom_dev;
                break;
+       case SCMI_PROTOCOL_ID_PINCTRL:
+               proto = priv->pinctrl_dev;
+               break;
        default:
                dev_err(dev, "Protocol not supported\n");
                proto = NULL;
@@ -147,6 +150,9 @@ static int scmi_add_protocol(struct udevice *dev,
        case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
                priv->voltagedom_dev = proto;
                break;
+       case SCMI_PROTOCOL_ID_PINCTRL:
+               priv->pinctrl_dev = proto;
+               break;
        default:
                dev_err(dev, "Protocol not supported\n");
                return -EPROTO;
@@ -352,6 +358,22 @@ static int scmi_fill_base_info(struct udevice *agent, 
struct udevice *dev)
        return 0;
 }
 
+static struct driver *scmi_proto_driver_get(unsigned int proto_id)
+{
+       struct scmi_proto_driver *start, *entry;
+       int n_ents;
+
+       start = ll_entry_start(struct scmi_proto_driver, scmi_proto_driver);
+       n_ents = ll_entry_count(struct scmi_proto_driver, scmi_proto_driver);
+
+       for (entry = start; entry != start + n_ents; entry++) {
+               if (entry->match->proto_id == proto_id)
+                       return entry->driver;
+       }
+
+       return NULL;
+}
+
 /*
  * SCMI agent devices binds devices of various uclasses depending on
  * the FDT description. scmi_bind_protocol() is a generic bind sequence
@@ -436,6 +458,9 @@ static int scmi_bind_protocols(struct udevice *dev)
                                drv = DM_DRIVER_GET(scmi_voltage_domain);
                        }
                        break;
+               case SCMI_PROTOCOL_ID_PINCTRL:
+                       drv = scmi_proto_driver_get(SCMI_PROTOCOL_ID_PINCTRL);
+                       break;
                default:
                        break;
                }
diff --git a/drivers/pinctrl/nxp/pinctrl-imx-scmi.c 
b/drivers/pinctrl/nxp/pinctrl-imx-scmi.c
index 0ed971369a3..dbd6ff437e5 100644
--- a/drivers/pinctrl/nxp/pinctrl-imx-scmi.c
+++ b/drivers/pinctrl/nxp/pinctrl-imx-scmi.c
@@ -9,6 +9,7 @@
 #include <dm/device_compat.h>
 #include <dm/pinctrl.h>
 #include <scmi_agent.h>
+#include <scmi_agent-uclass.h>
 #include <scmi_protocols.h>
 
 #include "pinctrl-imx.h"
@@ -150,3 +151,9 @@ U_BOOT_DRIVER(scmi_pinctrl_imx) = {
        .ops = &imx_scmi_pinctrl_ops,
        .flags = DM_FLAG_PRE_RELOC,
 };
+
+static struct scmi_proto_match match = {
+       .proto_id = SCMI_PROTOCOL_ID_PINCTRL,
+};
+
+U_BOOT_SCMI_PROTO_DRIVER(scmi_pinctrl_imx, &match);
diff --git a/include/scmi_agent-uclass.h b/include/scmi_agent-uclass.h
index 33e0e18c30d..d6586eb3ff9 100644
--- a/include/scmi_agent-uclass.h
+++ b/include/scmi_agent-uclass.h
@@ -27,6 +27,7 @@ struct scmi_channel;
  * @clock_dev:         SCMI clock protocol device
  * @resetdom_dev:      SCMI reset domain protocol device
  * @voltagedom_dev:    SCMI voltage domain protocol device
+ * @pinctrl_dev:       SCMI pin control protocol device
  */
 struct scmi_agent_priv {
        u32 version;
@@ -43,6 +44,7 @@ struct scmi_agent_priv {
        struct udevice *clock_dev;
        struct udevice *resetdom_dev;
        struct udevice *voltagedom_dev;
+       struct udevice *pinctrl_dev;
 };
 
 static inline u32 scmi_version(struct udevice *dev)
@@ -115,4 +117,19 @@ struct scmi_agent_ops {
                           struct scmi_msg *msg);
 };
 
+struct scmi_proto_match {
+       unsigned int proto_id;
+};
+
+struct scmi_proto_driver {
+       struct driver *driver;
+       const struct scmi_proto_match *match;
+};
+
+#define U_BOOT_SCMI_PROTO_DRIVER(__name, __match) \
+       ll_entry_declare(struct scmi_proto_driver, __name, scmi_proto_driver) = 
{ \
+               .driver = llsym(struct driver, __name, driver), \
+               .match = __match, \
+       }
+
 #endif /* _SCMI_TRANSPORT_UCLASS_H */

-- 
2.43.0

Reply via email to