diff --git a/drivers/firmware/scmi/base.c b/drivers/firmware/scmi/base.c
index 04018eb6ecf3..224e0ca7a915 100644
--- a/drivers/firmware/scmi/base.c
+++ b/drivers/firmware/scmi/base.c
@@ -484,6 +484,12 @@ static int scmi_base_probe(struct udevice *dev)
 		return ret;
 	}
 
+	ret = scmi_fill_base_info(dev->parent);
+	if (ret) {
+		dev_err(dev, "get information failed\n");
+		return ret;
+	}
+
 	return ret;
 }
 
diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
index 6fd948ae6ddf..ec15580cc947 100644
--- a/drivers/firmware/scmi/scmi_agent-uclass.c
+++ b/drivers/firmware/scmi/scmi_agent-uclass.c
@@ -56,6 +56,9 @@ struct udevice *scmi_get_protocol(struct udevice *dev,
 	}
 
 	switch (id) {
+	case SCMI_PROTOCOL_ID_BASE:
+		proto = priv->base_dev;
+		break;
 	case SCMI_PROTOCOL_ID_CLOCK:
 		proto = priv->clock_dev;
 		break;
@@ -100,6 +103,9 @@ static int scmi_add_protocol(struct udevice *dev,
 	}
 
 	switch (proto_id) {
+	case SCMI_PROTOCOL_ID_BASE:
+		priv->base_dev = proto;
+		break;
 	case SCMI_PROTOCOL_ID_CLOCK:
 		priv->clock_dev = proto;
 		break;
@@ -149,6 +155,20 @@ static int scmi_bind_protocols(struct udevice *dev)
 		return -EBUSY;
 	}
 
+	drv = DM_DRIVER_GET(scmi_base_drv);
+	name = "scmi-base.0";
+	ret = device_bind(dev, drv, name, NULL, ofnode_null(), &proto);
+	if (ret) {
+		dev_err(dev, "failed to bind base protocol\n");
+		return ret;
+	}
+	ret = scmi_add_protocol(dev, SCMI_PROTOCOL_ID_BASE, proto);
+	if (ret) {
+		dev_err(dev, "failed to add protocol: %s, ret: %d\n",
+			proto->name, ret);
+		return ret;
+	}
+
 	dev_for_each_subnode(node, dev) {
 		u32 protocol_id;
 
@@ -262,6 +282,90 @@ int devm_scmi_process_msg(struct udevice *dev, struct scmi_channel *channel,
 	return -EPROTONOSUPPORT;
 }
 
+int scmi_fill_base_info(struct udevice *dev)
+{
+	struct scmi_agent_priv *priv;
+	struct udevice *base;
+	const struct scmi_base_ops *ops;
+	int ret;
+
+	priv = dev_get_uclass_plat(dev);
+
+	base = priv->base_dev;
+	if (!base) {
+		dev_err(dev, "Base protocol not found\n");
+		return -EPROTO;
+	}
+
+	ops = dev_get_driver_ops(base);
+	if (!ops) {
+		dev_err(base, "Operations in Base protocol not found\n");
+		return -EPROTO;
+	}
+	ret = (*ops->protocol_version)(base, &priv->version);
+	if (ret) {
+		dev_err(base, "protocol_version() failed (%d)\n", ret);
+		return ret;
+	}
+	/* check for required version */
+	if (priv->version < SCMI_BASE_PROTOCOL_VERSION) {
+		dev_err(base, "base protocol version (%d) lower than expected\n",
+			priv->version);
+		return -EPROTO;
+	}
+
+	ret = (*ops->protocol_attrs)(base, &priv->num_agents,
+				     &priv->num_protocols);
+	if (ret) {
+		dev_err(base, "protocol_attrs() failed (%d)\n", ret);
+		return ret;
+	}
+	ret = (*ops->base_discover_vendor)(base, priv->vendor);
+	if (ret) {
+		dev_err(base, "base_discover_vendor() failed (%d)\n", ret);
+		return ret;
+	}
+	ret = (*ops->base_discover_sub_vendor)(base, priv->sub_vendor);
+	if (ret) {
+		if (ret != -EOPNOTSUPP) {
+			dev_err(base, "base_discover_sub_vendor() failed (%d)\n",
+				ret);
+			return ret;
+		}
+		strcpy(priv->sub_vendor, "NA");
+	}
+	ret = (*ops->base_discover_impl_version)(base,
+						 &priv->impl_version);
+	if (ret) {
+		dev_err(base, "base_discover_impl_version() failed (%d)\n",
+			ret);
+		return ret;
+	}
+
+	priv->agent_id = 0xffffffff; /* to avoid false claim */
+	ret = (*ops->base_discover_agent)(base, 0xffffffff,
+					  &priv->agent_id, priv->agent_name);
+	if (ret) {
+		if (ret != -EOPNOTSUPP) {
+			dev_err(base,
+				"base_discover_agent() failed for myself (%d)\n",
+				ret);
+			return ret;
+		}
+		priv->agent_name[0] = '\0';
+	}
+
+	ret = (*ops->base_discover_list_protocols)(base,
+						    &priv->protocols);
+	if (ret != priv->num_protocols) {
+		dev_err(base, "base_discover_list_protocols() failed (%d)\n",
+			ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 UCLASS_DRIVER(scmi_agent) = {
 	.id		= UCLASS_SCMI_AGENT,
 	.name		= "scmi_agent",
diff --git a/include/scmi_agent-uclass.h b/include/scmi_agent-uclass.h
index 6c3d1321b1aa..8ead08b38fb1 100644
--- a/include/scmi_agent-uclass.h
+++ b/include/scmi_agent-uclass.h
@@ -5,22 +5,94 @@
 #ifndef _SCMI_AGENT_UCLASS_H
 #define _SCMI_AGENT_UCLASS_H
 
+#include <scmi_protocols.h>
+
 struct udevice;
 struct scmi_msg;
 struct scmi_channel;
 
 /**
  * struct scmi_agent_priv - private data maintained by agent instance
- * @clock_dev:	SCMI clock protocol device
- * @clock_dev:	SCMI reset domain protocol device
- * @clock_dev:	SCMI voltage domain protocol device
+ * @version:		Version
+ * @num_agents:		Number of agents
+ * @num_protocols:	Number of protocols
+ * @impl_version:	Implementation version
+ * @protocols:		Array of protocol IDs
+ * @vendor:		Vendor name
+ * @sub_vendor:		Sub-vendor name
+ * @agent_name:		Agent name
+ * agent_id:		Identifier of agent
+ * @base_dev:		SCMI base protocol device
+ * @clock_dev:		SCMI block protocol device
+ * @clock_dev:		SCMI reset domain protocol device
+ * @clock_dev:		SCMI voltage domain protocol device
  */
 struct scmi_agent_priv {
+	u32 version;
+	u32 num_agents;
+	u32 num_protocols;
+	u32 impl_version;
+	u8 *protocols;
+	u8 vendor[SCMI_BASE_NAME_LENGTH_MAX];
+	u8 sub_vendor[SCMI_BASE_NAME_LENGTH_MAX];
+	u8 agent_name[SCMI_BASE_NAME_LENGTH_MAX];
+	u32 agent_id;
+	struct udevice *base_dev;
 	struct udevice *clock_dev;
 	struct udevice *resetdom_dev;
 	struct udevice *voltagedom_dev;
 };
 
+static inline u32 scmi_version(struct udevice *dev)
+{
+	return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->version;
+}
+
+static inline u32 scmi_num_agents(struct udevice *dev)
+{
+	return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->num_agents;
+}
+
+static inline u32 scmi_num_protocols(struct udevice *dev)
+{
+	return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->num_protocols;
+}
+
+static inline u32 scmi_impl_version(struct udevice *dev)
+{
+	return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->impl_version;
+}
+
+static inline u8 *scmi_protocols(struct udevice *dev)
+{
+	return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->protocols;
+}
+
+static inline u8 *scmi_vendor(struct udevice *dev)
+{
+	return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->vendor;
+}
+
+static inline u8 *scmi_sub_vendor(struct udevice *dev)
+{
+	return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->sub_vendor;
+}
+
+static inline u8 *scmi_agent_name(struct udevice *dev)
+{
+	return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->agent_name;
+}
+
+static inline u32 scmi_agent_id(struct udevice *dev)
+{
+	return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->agent_id;
+}
+
+static inline struct udevice *scmi_base_dev(struct udevice *dev)
+{
+	return ((struct scmi_agent_priv *)dev_get_uclass_plat(dev))->base_dev;
+}
+
 /**
  * struct scmi_transport_ops - The functions that a SCMI transport layer must implement.
  */
diff --git a/include/scmi_agent.h b/include/scmi_agent.h
index f77c10f7abfd..07e99f19726e 100644
--- a/include/scmi_agent.h
+++ b/include/scmi_agent.h
@@ -91,4 +91,14 @@ struct udevice *scmi_get_protocol(struct udevice *dev,
  */
 int scmi_to_linux_errno(s32 scmi_errno);
 
+/**
+ * scmi_fill_base_info - fill information about services by SCMI server
+ * @dev:        SCMI device
+ *
+ * Fill basic information about services provided by SCMI server
+ *
+ * Return:      0 on success, error code otherwise
+ */
+int scmi_fill_base_info(struct udevice *dev);
+
 #endif /* SCMI_H */
