/** * zynqmp_gpd_is_active_wakeup_path() - Check if device is in wakeup source * path * @dev: Device to check for wakeup source path * @not_used: Data member (not required) * * This function is checks device's child hierarchy and checks if any device is * set as wakeup source. * * Return: 1 if device is in wakeup source path else 0
*/ staticint zynqmp_gpd_is_active_wakeup_path(struct device *dev, void *not_used)
{ int may_wakeup;
may_wakeup = device_may_wakeup(dev); if (may_wakeup) return may_wakeup;
/** * zynqmp_gpd_power_on() - Power on PM domain * @domain: Generic PM domain * * This function is called before devices inside a PM domain are resumed, to * power on PM domain. * * Return: 0 on success, error code otherwise
*/ staticint zynqmp_gpd_power_on(struct generic_pm_domain *domain)
{ struct zynqmp_pm_domain *pd = to_zynqmp_pm_domain(domain); int ret;
ret = zynqmp_pm_set_requirement(pd->node_id,
ZYNQMP_PM_CAPABILITY_ACCESS,
ZYNQMP_PM_MAX_QOS,
ZYNQMP_PM_REQUEST_ACK_BLOCKING); if (ret) {
dev_err(&domain->dev, "failed to set requirement to 0x%x for PM node id %d: %d\n",
ZYNQMP_PM_CAPABILITY_ACCESS, pd->node_id, ret); return ret;
}
dev_dbg(&domain->dev, "set requirement to 0x%x for PM node id %d\n",
ZYNQMP_PM_CAPABILITY_ACCESS, pd->node_id);
return 0;
}
/** * zynqmp_gpd_power_off() - Power off PM domain * @domain: Generic PM domain * * This function is called after devices inside a PM domain are suspended, to * power off PM domain. * * Return: 0 on success, error code otherwise
*/ staticint zynqmp_gpd_power_off(struct generic_pm_domain *domain)
{ struct zynqmp_pm_domain *pd = to_zynqmp_pm_domain(domain); int ret; struct pm_domain_data *pdd, *tmp;
u32 capabilities = min_capability; bool may_wakeup;
/* If domain is already released there is nothing to be done */ if (!pd->requested) {
dev_dbg(&domain->dev, "PM node id %d is already released\n",
pd->node_id); return 0;
}
list_for_each_entry_safe(pdd, tmp, &domain->dev_list, list_node) { /* If device is in wakeup path, set capability to WAKEUP */
may_wakeup = zynqmp_gpd_is_active_wakeup_path(pdd->dev, NULL); if (may_wakeup) {
dev_dbg(pdd->dev, "device is in wakeup path in %s\n",
domain->name);
capabilities = ZYNQMP_PM_CAPABILITY_WAKEUP; break;
}
}
ret = zynqmp_pm_set_requirement(pd->node_id, capabilities, 0,
ZYNQMP_PM_REQUEST_ACK_NO); if (ret) {
dev_err(&domain->dev, "failed to set requirement to 0x%x for PM node id %d: %d\n",
capabilities, pd->node_id, ret); return ret;
}
dev_dbg(&domain->dev, "set requirement to 0x%x for PM node id %d\n",
capabilities, pd->node_id);
return 0;
}
/** * zynqmp_gpd_attach_dev() - Attach device to the PM domain * @domain: Generic PM domain * @dev: Device to attach * * Return: 0 on success, error code otherwise
*/ staticint zynqmp_gpd_attach_dev(struct generic_pm_domain *domain, struct device *dev)
{ struct zynqmp_pm_domain *pd = to_zynqmp_pm_domain(domain); int ret;
/* If this is not the first device to attach there is nothing to do */ if (domain->device_count) return 0;
ret = zynqmp_pm_request_node(pd->node_id, 0, 0,
ZYNQMP_PM_REQUEST_ACK_BLOCKING); if (ret) {
dev_err(&domain->dev, "%s request failed for node %d: %d\n",
domain->name, pd->node_id, ret); return ret;
}
pd->requested = true;
dev_dbg(&domain->dev, "%s requested PM node id %d\n",
dev_name(dev), pd->node_id);
return 0;
}
/** * zynqmp_gpd_detach_dev() - Detach device from the PM domain * @domain: Generic PM domain * @dev: Device to detach
*/ staticvoid zynqmp_gpd_detach_dev(struct generic_pm_domain *domain, struct device *dev)
{ struct zynqmp_pm_domain *pd = to_zynqmp_pm_domain(domain); int ret;
/* If this is not the last device to detach there is nothing to do */ if (domain->device_count) return;
ret = zynqmp_pm_release_node(pd->node_id); if (ret) {
dev_err(&domain->dev, "failed to release PM node id %d: %d\n",
pd->node_id, ret); return;
}
pd->requested = false;
dev_dbg(&domain->dev, "%s released PM node id %d\n",
dev_name(dev), pd->node_id);
}
if (genpdspec->args_count != 1) return ERR_PTR(-EINVAL);
/* Check for existing pm domains */ for (i = 0; i < ZYNQMP_NUM_DOMAINS; i++) { if (pd[i].node_id == idx) goto done;
}
/* * Add index in empty node_id of power domain list as no existing * power domain found for current index.
*/ for (i = 0; i < ZYNQMP_NUM_DOMAINS; i++) { if (pd[i].node_id == 0) {
pd[i].node_id = idx; break;
}
}
done: if (!genpd_data->domains[i] || i == ZYNQMP_NUM_DOMAINS) return ERR_PTR(-ENOENT);
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.