Skip to content

Commit

Permalink
firmware: arm_scmi: Add support for multiple device per protocol
Browse files Browse the repository at this point in the history
Currently only one scmi device is created for each protocol enumerated.
However, there is requirement to make use of some procotols by multiple
kernel subsystems/frameworks. One such example is SCMI PERFORMANCE
protocol which can be used by both cpufreq and devfreq drivers.
Similarly, SENSOR protocol may be used by hwmon and iio subsystems,
and POWER protocol may be used by genpd and regulator drivers.

In order to achieve that, let us extend the scmi bus to match based
not only protocol id but also the scmi device name if one is available.

Reviewed-by: Cristian Marussi <cristian.marussi@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
  • Loading branch information
sudeep-holla committed Dec 24, 2019
1 parent e42617b commit ee7a9c9
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 7 deletions.
20 changes: 17 additions & 3 deletions drivers/firmware/arm_scmi/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@ scmi_dev_match_id(struct scmi_device *scmi_dev, struct scmi_driver *scmi_drv)
return NULL;

for (; id->protocol_id; id++)
if (id->protocol_id == scmi_dev->protocol_id)
return id;
if (id->protocol_id == scmi_dev->protocol_id) {
if (!id->name)
return id;
else if (!strcmp(id->name, scmi_dev->name))
return id;
}

return NULL;
}
Expand Down Expand Up @@ -125,7 +129,8 @@ static void scmi_device_release(struct device *dev)
}

struct scmi_device *
scmi_device_create(struct device_node *np, struct device *parent, int protocol)
scmi_device_create(struct device_node *np, struct device *parent, int protocol,
const char *name)
{
int id, retval;
struct scmi_device *scmi_dev;
Expand All @@ -134,8 +139,15 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol)
if (!scmi_dev)
return NULL;

scmi_dev->name = kstrdup_const(name ?: "unknown", GFP_KERNEL);
if (!scmi_dev->name) {
kfree(scmi_dev);
return NULL;
}

id = ida_simple_get(&scmi_bus_id, 1, 0, GFP_KERNEL);
if (id < 0) {
kfree_const(scmi_dev->name);
kfree(scmi_dev);
return NULL;
}
Expand All @@ -154,13 +166,15 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol)

return scmi_dev;
put_dev:
kfree_const(scmi_dev->name);
put_device(&scmi_dev->dev);
ida_simple_remove(&scmi_bus_id, id);
return NULL;
}

void scmi_device_destroy(struct scmi_device *scmi_dev)
{
kfree_const(scmi_dev->name);
scmi_handle_put(scmi_dev->handle);
ida_simple_remove(&scmi_bus_id, scmi_dev->id);
device_unregister(&scmi_dev->dev);
Expand Down
6 changes: 3 additions & 3 deletions drivers/firmware/arm_scmi/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -803,11 +803,11 @@ scmi_mbox_txrx_setup(struct scmi_info *info, struct device *dev, int prot_id)

static inline void
scmi_create_protocol_device(struct device_node *np, struct scmi_info *info,
int prot_id)
int prot_id, const char *name)
{
struct scmi_device *sdev;

sdev = scmi_device_create(np, info->dev, prot_id);
sdev = scmi_device_create(np, info->dev, prot_id, name);
if (!sdev) {
dev_err(info->dev, "failed to create %d protocol device\n",
prot_id);
Expand Down Expand Up @@ -892,7 +892,7 @@ static int scmi_probe(struct platform_device *pdev)
continue;
}

scmi_create_protocol_device(child, info, prot_id);
scmi_create_protocol_device(child, info, prot_id, NULL);
}

return 0;
Expand Down
5 changes: 4 additions & 1 deletion include/linux/scmi_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,18 +257,21 @@ enum scmi_std_protocol {
struct scmi_device {
u32 id;
u8 protocol_id;
const char *name;
struct device dev;
struct scmi_handle *handle;
};

#define to_scmi_dev(d) container_of(d, struct scmi_device, dev)

struct scmi_device *
scmi_device_create(struct device_node *np, struct device *parent, int protocol);
scmi_device_create(struct device_node *np, struct device *parent, int protocol,
const char *name);
void scmi_device_destroy(struct scmi_device *scmi_dev);

struct scmi_device_id {
u8 protocol_id;
const char *name;
};

struct scmi_driver {
Expand Down

0 comments on commit ee7a9c9

Please sign in to comment.