/* * This timeout must be long, as some services (example: image authentication) * take significant time to complete
*/ #define MPFS_SYS_CTRL_TIMEOUT_MS 30000
int mpfs_blocking_transaction(struct mpfs_sys_controller *sys_controller, struct mpfs_mss_msg *msg)
{ unsignedlong timeout = msecs_to_jiffies(MPFS_SYS_CTRL_TIMEOUT_MS); int ret;
ret = mutex_lock_interruptible(&transaction_lock); if (ret) return ret;
reinit_completion(&sys_controller->c);
ret = mbox_send_message(sys_controller->chan, msg); if (ret < 0) {
dev_warn(sys_controller->client.dev, "MPFS sys controller service timeout\n"); goto out;
}
/* * Unfortunately, the system controller will only deliver an interrupt * if a service succeeds. mbox_send_message() will block until the busy * flag is gone. If the busy flag is gone but no interrupt has arrived * to trigger the rx callback then the service can be deemed to have * failed. * The caller can then interrogate msg::response::resp_status to * determine the cause of the failure. * mbox_send_message() returns positive integers in the success path, so * ret needs to be cleared if we do get an interrupt.
*/ if (!wait_for_completion_timeout(&sys_controller->c, timeout)) {
ret = -EBADMSG;
dev_warn(sys_controller->client.dev, "MPFS sys controller service failed with status: %d\n",
msg->response->resp_status);
} else {
ret = 0;
}
staticint mpfs_sys_controller_probe(struct platform_device *pdev)
{ struct device *dev = &pdev->dev; struct mpfs_sys_controller *sys_controller; struct device_node *np; int i, ret;
sys_controller = kzalloc(sizeof(*sys_controller), GFP_KERNEL); if (!sys_controller) return -ENOMEM;
np = of_parse_phandle(dev->of_node, "microchip,bitstream-flash", 0); if (!np) goto no_flash;
sys_controller->flash = of_get_mtd_device_by_node(np);
of_node_put(np); if (IS_ERR(sys_controller->flash)) return dev_err_probe(dev, PTR_ERR(sys_controller->flash), "Failed to get flash\n");
sys_controller->chan = mbox_request_channel(&sys_controller->client, 0); if (IS_ERR(sys_controller->chan)) {
ret = dev_err_probe(dev, PTR_ERR(sys_controller->chan), "Failed to get mbox channel\n");
kfree(sys_controller); return ret;
}
for (i = 0; i < ARRAY_SIZE(subdevs); i++) {
subdevs[i].dev.parent = dev; if (platform_device_register(&subdevs[i]))
dev_warn(dev, "Error registering sub device %s\n", subdevs[i].name);
}
dev_info(&pdev->dev, "Registered MPFS system controller\n");
match = of_match_node(mpfs_sys_controller_of_match, dev->parent->of_node);
of_node_put(dev->parent->of_node); if (!match) goto err_no_device;
sys_controller = dev_get_drvdata(dev->parent); if (!sys_controller) goto err_bad_device;
if (!kref_get_unless_zero(&sys_controller->consumers)) goto err_bad_device;
ret = devm_add_action_or_reset(dev, mpfs_sys_controller_put, sys_controller); if (ret) return ERR_PTR(ret);
return sys_controller;
err_no_device:
dev_dbg(dev, "Parent device was not an MPFS system controller\n"); return ERR_PTR(-ENODEV);
err_bad_device:
dev_dbg(dev, "MPFS system controller found but could not register as a sub device\n"); return ERR_PTR(-EPROBE_DEFER);
}
EXPORT_SYMBOL(mpfs_sys_controller_get);