drivers/pmdomain/xilinx/zynqmp-pm-domains.c

Source file repositories/reference/linux-study-clean/drivers/pmdomain/xilinx/zynqmp-pm-domains.c

File Facts

System
Linux kernel
Corpus path
drivers/pmdomain/xilinx/zynqmp-pm-domains.c
Extension
.c
Size
7795 bytes
Lines
305
Domain
Driver Families
Bucket
drivers/pmdomain
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct zynqmp_pm_domain {
	struct generic_pm_domain gpd;
	u32 node_id;
	bool requested;
};

#define to_zynqmp_pm_domain(pm_domain) \
	container_of(pm_domain, struct zynqmp_pm_domain, gpd)

/**
 * 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
 */
static int 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;

	return device_for_each_child(dev, NULL,
			zynqmp_gpd_is_active_wakeup_path);
}

/**
 * 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
 */
static int 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
 */
static int 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);

Annotation

Implementation Notes