@@ -194,13 +194,21 @@ scmi_dev_match_id(struct scmi_device *scmi_dev, struct scmi_driver *scmi_drv)
if (!id)
return NULL;
- for (; id->protocol_id; id++)
- if (id->protocol_id == scmi_dev->protocol_id) {
- if (!id->name)
+ for (; id->protocol_id; id++) {
+ if (id->protocol_id != scmi_dev->protocol_id)
+ continue;
+ if (!id->name)
+ return id;
+
+ if (!strcmp(id->name, scmi_dev->name)) {
+ if (!id->compatible &&
+ device_property_read_string(&scmi_dev->dev, "compatible", NULL))
return id;
- else if (!strcmp(id->name, scmi_dev->name))
+
+ if (id->compatible && device_is_compatible(&scmi_dev->dev, id->compatible))
return id;
}
+ }
return NULL;
}
@@ -325,11 +333,14 @@ static void __scmi_device_destroy(struct scmi_device *scmi_dev)
static struct scmi_device *
__scmi_device_create(struct device_node *np, struct device *parent,
- int protocol, const char *name)
+ int protocol, const char *name, const char *compatible)
{
int id, retval;
struct scmi_device *scmi_dev;
+ if (compatible && !of_device_is_compatible(np, compatible))
+ return NULL;
+
/*
* If the same protocol/name device already exist under the same parent
* (i.e. SCMI instance) just return the existent device.
@@ -405,6 +416,7 @@ __scmi_device_create(struct device_node *np, struct device *parent,
* @name: The requested-name of the device to be created; this is optional
* and if no @name is provided, all the devices currently known to
* be requested on the SCMI bus for @protocol will be created.
+ * @compatible: The compatible string
*
* This method can be invoked to create a single well-defined device (like
* a transport device or a device requested by an SCMI driver loaded after
@@ -421,14 +433,14 @@ __scmi_device_create(struct device_node *np, struct device *parent,
*/
struct scmi_device *scmi_device_create(struct device_node *np,
struct device *parent, int protocol,
- const char *name)
+ const char *name, const char *compatible)
{
struct list_head *phead;
struct scmi_requested_dev *rdev;
struct scmi_device *scmi_dev = NULL;
if (name)
- return __scmi_device_create(np, parent, protocol, name);
+ return __scmi_device_create(np, parent, protocol, name, compatible);
mutex_lock(&scmi_requested_devices_mtx);
phead = idr_find(&scmi_requested_devices, protocol);
@@ -442,9 +454,20 @@ struct scmi_device *scmi_device_create(struct device_node *np,
list_for_each_entry(rdev, phead, node) {
struct scmi_device *sdev;
+ if (compatible) {
+ if (!rdev->id_table->compatible)
+ continue;
+ if (strcmp(compatible, rdev->id_table->compatible))
+ continue;
+ } else {
+ if (rdev->id_table->compatible)
+ continue;
+ }
+
sdev = __scmi_device_create(np, parent,
rdev->id_table->protocol_id,
- rdev->id_table->name);
+ rdev->id_table->name,
+ rdev->id_table->compatible);
/* Report errors and carry on... */
if (sdev)
scmi_dev = sdev;
@@ -149,7 +149,7 @@ extern struct blocking_notifier_head scmi_requested_devices_nh;
struct scmi_device *scmi_device_create(struct device_node *np,
struct device *parent, int protocol,
- const char *name);
+ const char *name, const char *compatible);
void scmi_device_destroy(struct device *parent, int protocol, const char *name);
int scmi_protocol_acquire(const struct scmi_handle *handle, u8 protocol_id);
@@ -261,15 +261,17 @@ EXPORT_SYMBOL_GPL(scmi_protocol_unregister);
* @name: The optional name of the device to be created: if not provided this
* call will lead to the creation of all the devices currently requested
* for the specified protocol.
+ * @compatible: optional, the compatible string
*/
static void scmi_create_protocol_devices(struct device_node *np,
struct scmi_info *info,
- int prot_id, const char *name)
+ int prot_id, const char *name,
+ const char *compatible)
{
struct scmi_device *sdev;
mutex_lock(&info->devreq_mtx);
- sdev = scmi_device_create(np, info->dev, prot_id, name);
+ sdev = scmi_device_create(np, info->dev, prot_id, name, compatible);
if (name && !sdev)
dev_err(info->dev,
"failed to create device for protocol 0x%X (%s)\n",
@@ -2354,7 +2356,7 @@ static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node,
snprintf(name, 32, "__scmi_transport_device_%s_%02X",
idx ? "rx" : "tx", prot_id);
/* Create a uniquely named, dedicated transport device for this chan */
- tdev = scmi_device_create(of_node, info->dev, prot_id, name);
+ tdev = scmi_device_create(of_node, info->dev, prot_id, name, NULL);
if (!tdev) {
dev_err(info->dev,
"failed to create transport device (%s)\n", name);
@@ -2550,7 +2552,7 @@ static int scmi_device_request_notifier(struct notifier_block *nb,
switch (action) {
case SCMI_BUS_NOTIFY_DEVICE_REQUEST:
scmi_create_protocol_devices(np, info, id_table->protocol_id,
- id_table->name);
+ id_table->name, id_table->compatible);
break;
case SCMI_BUS_NOTIFY_DEVICE_UNREQUEST:
scmi_destroy_protocol_devices(info, id_table->protocol_id,
@@ -2802,10 +2804,13 @@ static int scmi_probe(struct platform_device *pdev)
for_each_available_child_of_node(np, child) {
u32 prot_id;
+ const char *s = NULL;
if (of_property_read_u32(child, "reg", &prot_id))
continue;
+ of_property_read_string(child, "compatible", &s);
+
if (!FIELD_FIT(MSG_PROTOCOL_ID_MASK, prot_id))
dev_err(dev, "Out of range protocol %d\n", prot_id);
@@ -2828,7 +2833,7 @@ static int scmi_probe(struct platform_device *pdev)
}
of_node_get(child);
- scmi_create_protocol_devices(child, info, prot_id, NULL);
+ scmi_create_protocol_devices(child, info, prot_id, NULL, s);
}
return 0;
@@ -839,6 +839,7 @@ struct scmi_device {
u32 id;
u8 protocol_id;
const char *name;
+ const char *compatible; /* Optional */
struct device dev;
struct scmi_handle *handle;
};
@@ -848,6 +849,7 @@ struct scmi_device {
struct scmi_device_id {
u8 protocol_id;
const char *name;
+ const char *compatible; /* Optional */
};
struct scmi_driver {