in arm_scmi/driver.c [1805:1909]
static int scmi_probe(struct platform_device *pdev)
{
int ret;
struct scmi_handle *handle;
const struct scmi_desc *desc;
struct scmi_info *info;
struct device *dev = &pdev->dev;
struct device_node *child, *np = dev->of_node;
desc = of_device_get_match_data(dev);
if (!desc)
return -EINVAL;
info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
info->dev = dev;
info->desc = desc;
INIT_LIST_HEAD(&info->node);
idr_init(&info->protocols);
mutex_init(&info->protocols_mtx);
idr_init(&info->active_protocols);
platform_set_drvdata(pdev, info);
idr_init(&info->tx_idr);
idr_init(&info->rx_idr);
handle = &info->handle;
handle->dev = info->dev;
handle->version = &info->version;
handle->devm_protocol_get = scmi_devm_protocol_get;
handle->devm_protocol_put = scmi_devm_protocol_put;
if (desc->ops->link_supplier) {
ret = desc->ops->link_supplier(dev);
if (ret)
return ret;
}
ret = scmi_txrx_setup(info, dev, SCMI_PROTOCOL_BASE);
if (ret)
return ret;
ret = scmi_xfer_info_init(info);
if (ret)
goto clear_txrx_setup;
if (scmi_notification_init(handle))
dev_err(dev, "SCMI Notifications NOT available.\n");
/*
* Trigger SCMI Base protocol initialization.
* It's mandatory and won't be ever released/deinit until the
* SCMI stack is shutdown/unloaded as a whole.
*/
ret = scmi_protocol_acquire(handle, SCMI_PROTOCOL_BASE);
if (ret) {
dev_err(dev, "unable to communicate with SCMI\n");
goto notification_exit;
}
mutex_lock(&scmi_list_mutex);
list_add_tail(&info->node, &scmi_list);
mutex_unlock(&scmi_list_mutex);
for_each_available_child_of_node(np, child) {
u32 prot_id;
if (of_property_read_u32(child, "reg", &prot_id))
continue;
if (!FIELD_FIT(MSG_PROTOCOL_ID_MASK, prot_id))
dev_err(dev, "Out of range protocol %d\n", prot_id);
if (!scmi_is_protocol_implemented(handle, prot_id)) {
dev_err(dev, "SCMI protocol %d not implemented\n",
prot_id);
continue;
}
/*
* Save this valid DT protocol descriptor amongst
* @active_protocols for this SCMI instance/
*/
ret = idr_alloc(&info->active_protocols, child,
prot_id, prot_id + 1, GFP_KERNEL);
if (ret != prot_id) {
dev_err(dev, "SCMI protocol %d already activated. Skip\n",
prot_id);
continue;
}
of_node_get(child);
scmi_create_protocol_devices(child, info, prot_id);
}
return 0;
notification_exit:
scmi_notification_exit(&info->handle);
clear_txrx_setup:
scmi_cleanup_txrx_channels(info);
return ret;
}