drivers/pmdomain/ti/ti_sci_pm_domains.c

Source file repositories/reference/linux-study-clean/drivers/pmdomain/ti/ti_sci_pm_domains.c

File Facts

System
Linux kernel
Corpus path
drivers/pmdomain/ti/ti_sci_pm_domains.c
Extension
.c
Size
8785 bytes
Lines
328
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 ti_sci_genpd_provider {
	const struct ti_sci_handle *ti_sci;
	struct device *dev;
	struct list_head pd_list;
	struct genpd_onecell_data data;
};

/**
 * struct ti_sci_pm_domain: TI specific data needed for power domain
 * @idx: index of the device that identifies it with the system
 *	 control processor.
 * @exclusive: Permissions for exclusive request or shared request of the
 *	       device.
 * @pd: generic_pm_domain for use with the genpd framework
 * @node: link for the genpd list
 * @parent: link to the parent TI SCI genpd provider
 */
struct ti_sci_pm_domain {
	int idx;
	u8 exclusive;
	struct generic_pm_domain pd;
	struct list_head node;
	struct ti_sci_genpd_provider *parent;
};

#define genpd_to_ti_sci_pd(gpd) container_of(gpd, struct ti_sci_pm_domain, pd)

static inline bool ti_sci_pd_is_valid_constraint(s32 val)
{
	return val != PM_QOS_RESUME_LATENCY_NO_CONSTRAINT;
}

#ifdef CONFIG_PM_SLEEP
static void ti_sci_pd_set_lat_constraint(struct device *dev, s32 val)
{
	struct generic_pm_domain *genpd = pd_to_genpd(dev->pm_domain);
	struct ti_sci_pm_domain *pd = genpd_to_ti_sci_pd(genpd);
	const struct ti_sci_handle *ti_sci = pd->parent->ti_sci;
	u16 val_ms;
	int ret;

	/* PM QoS latency unit is usecs, TI SCI uses msecs */
	val_ms = val / USEC_PER_MSEC;
	ret = ti_sci->ops.pm_ops.set_latency_constraint(ti_sci, val_ms, TISCI_MSG_CONSTRAINT_SET);
	if (ret)
		dev_err(dev, "ti_sci_pd: set latency constraint failed: ret=%d\n",
			ret);
	else
		dev_dbg(dev, "ti_sci_pd: ID:%d set latency constraint %d\n",
			pd->idx, val);
}
#endif

static inline void ti_sci_pd_set_wkup_constraint(struct device *dev)
{
	struct generic_pm_domain *genpd = pd_to_genpd(dev->pm_domain);
	struct ti_sci_pm_domain *pd = genpd_to_ti_sci_pd(genpd);
	const struct ti_sci_handle *ti_sci = pd->parent->ti_sci;
	int ret;

	if (device_may_wakeup(dev) || device_wakeup_path(dev)) {
		/*
		 * If device can wakeup using IO daisy chain wakeups,
		 * we do not want to set a constraint.
		 */
		if (device_out_band_wakeup(dev)) {
			dev_dbg(dev, "%s: has out of band wakeup, not setting constraints\n", \
					__func__);
			return;
		}

		ret = ti_sci->ops.pm_ops.set_device_constraint(ti_sci, pd->idx,
							       TISCI_MSG_CONSTRAINT_SET);
		if (!ret)
			dev_dbg(dev, "ti_sci_pd: ID:%d set device constraint.\n", pd->idx);
	}
}

/*
 * ti_sci_pd_power_off(): genpd power down hook
 * @domain: pointer to the powerdomain to power off
 */
static int ti_sci_pd_power_off(struct generic_pm_domain *domain)
{
	struct ti_sci_pm_domain *pd = genpd_to_ti_sci_pd(domain);
	const struct ti_sci_handle *ti_sci = pd->parent->ti_sci;

	return ti_sci->ops.dev_ops.put_device(ti_sci, pd->idx);
}

Annotation

Implementation Notes