mutex_lock(&wcnss->iris_lock); if (!wcnss->iris) {
dev_err(wcnss->dev, "no iris registered\n");
ret = -EINVAL; goto release_iris_lock;
}
for (i = 0; i < wcnss->num_pds; i++) {
dev_pm_genpd_set_performance_state(wcnss->pds[i], INT_MAX);
ret = pm_runtime_get_sync(wcnss->pds[i]); if (ret < 0) {
pm_runtime_put_noidle(wcnss->pds[i]); goto disable_pds;
}
}
ret = regulator_bulk_enable(wcnss->num_vregs, wcnss->vregs); if (ret) goto disable_pds;
ret = qcom_iris_enable(wcnss->iris); if (ret) goto disable_regulators;
ret = qcom_scm_pas_auth_and_reset(WCNSS_PAS_ID); if (ret) {
dev_err(wcnss->dev, "failed to authenticate image and release reset\n"); goto disable_iris;
}
ret = wait_for_completion_timeout(&wcnss->start_done,
msecs_to_jiffies(5000)); if (wcnss->ready_irq > 0 && ret == 0) { /* We have a ready_irq, but it didn't fire in time. */
dev_err(wcnss->dev, "start timed out\n");
qcom_scm_pas_shutdown(WCNSS_PAS_ID);
ret = -ETIMEDOUT; goto disable_iris;
}
ret = 0;
disable_iris:
qcom_iris_disable(wcnss->iris);
disable_regulators:
regulator_bulk_disable(wcnss->num_vregs, wcnss->vregs);
disable_pds: for (i--; i >= 0; i--) {
pm_runtime_put(wcnss->pds[i]);
dev_pm_genpd_set_performance_state(wcnss->pds[i], 0);
}
release_iris_lock:
mutex_unlock(&wcnss->iris_lock);
static irqreturn_t wcnss_handover_interrupt(int irq, void *dev)
{ /* * XXX: At this point we're supposed to release the resources that we * have been holding on behalf of the WCNSS. Unfortunately this * interrupt comes way before the other side seems to be done. * * So we're currently relying on the ready interrupt firing later then * this and we just disable the resources at the end of wcnss_start().
*/
/* Handle single power domain */ if (wcnss->num_pds == 1 && dev->pm_domain) {
pm_runtime_disable(dev); return;
}
for (i = 0; i < wcnss->num_pds; i++)
dev_pm_domain_detach(wcnss->pds[i], false);
}
staticint wcnss_init_regulators(struct qcom_wcnss *wcnss, conststruct wcnss_vreg_info *info, int num_vregs, int num_pd_vregs)
{ struct regulator_bulk_data *bulk; int ret; int i;
/* * If attaching the power domains suceeded we can skip requesting * the regulators for the power domains. For old device trees we need to * reserve extra space to manage them through the regulator interface.
*/ if (wcnss->num_pds) {
info += wcnss->num_pds; /* Handle single power domain case */ if (wcnss->num_pds < num_pd_vregs)
num_vregs += num_pd_vregs - wcnss->num_pds;
} else {
num_vregs += num_pd_vregs;
}
/* * We might need to fallback to regulators instead of power domains * for old device trees. Don't report an error in that case.
*/
ret = wcnss_init_pds(wcnss, data->pd_names); if (ret && (ret != -ENODATA || !data->num_pd_vregs)) return ret;
ret = wcnss_init_regulators(wcnss, data->vregs, data->num_vregs,
data->num_pd_vregs); if (ret) goto detach_pds;
ret = wcnss_request_irq(wcnss, pdev, "wdog", false, wcnss_wdog_interrupt); if (ret < 0) goto detach_pds;
wcnss->wdog_irq = ret;
ret = wcnss_request_irq(wcnss, pdev, "fatal", false, wcnss_fatal_interrupt); if (ret < 0) goto detach_pds;
wcnss->fatal_irq = ret;
ret = wcnss_request_irq(wcnss, pdev, "ready", true, wcnss_ready_interrupt); if (ret < 0) goto detach_pds;
wcnss->ready_irq = ret;
ret = wcnss_request_irq(wcnss, pdev, "handover", true, wcnss_handover_interrupt); if (ret < 0) goto detach_pds;
wcnss->handover_irq = ret;
ret = wcnss_request_irq(wcnss, pdev, "stop-ack", true, wcnss_stop_ack_interrupt); if (ret < 0) goto detach_pds;
wcnss->stop_ack_irq = ret;
if (wcnss->stop_ack_irq) {
wcnss->state = devm_qcom_smem_state_get(&pdev->dev, "stop",
&wcnss->stop_bit); if (IS_ERR(wcnss->state)) {
ret = PTR_ERR(wcnss->state); goto detach_pds;
}
}
qcom_add_smd_subdev(rproc, &wcnss->smd_subdev);
wcnss->sysmon = qcom_add_sysmon_subdev(rproc, "wcnss", WCNSS_SSCTL_ID); if (IS_ERR(wcnss->sysmon)) {
ret = PTR_ERR(wcnss->sysmon); goto detach_pds;
}
wcnss->iris = qcom_iris_probe(&pdev->dev, &wcnss->use_48mhz_xo); if (IS_ERR(wcnss->iris)) {
ret = PTR_ERR(wcnss->iris); goto detach_pds;
}
ret = rproc_add(rproc); if (ret) goto remove_iris;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.