drivers/firmware/psci/psci.c

Source file repositories/reference/linux-study-clean/drivers/firmware/psci/psci.c

File Facts

System
Linux kernel
Corpus path
drivers/firmware/psci/psci.c
Extension
.c
Size
20191 bytes
Lines
851
Domain
Driver Families
Bucket
drivers/firmware
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations psci_debugfs_ops = {
	.owner = THIS_MODULE,
	.open = psci_debugfs_open,
	.release = single_release,
	.read = seq_read,
	.llseek = seq_lseek
};

static int __init psci_debugfs_init(void)
{
	if (!invoke_psci_fn || !psci_ops.get_version)
		return 0;

	return PTR_ERR_OR_ZERO(debugfs_create_file("psci", 0444, NULL, NULL,
						   &psci_debugfs_ops));
}
late_initcall(psci_debugfs_init)
#endif

#ifdef CONFIG_CPU_IDLE
static noinstr int psci_suspend_finisher(unsigned long state)
{
	u32 power_state = state;
	phys_addr_t pa_cpu_resume;

	pa_cpu_resume = __pa_symbol_nodebug((unsigned long)cpu_resume);

	return psci_ops.cpu_suspend(power_state, pa_cpu_resume);
}

int psci_cpu_suspend_enter(u32 state)
{
	int ret;

	if (!psci_power_state_loses_context(state)) {
		struct arm_cpuidle_irq_context context;

		ct_cpuidle_enter();
		arm_cpuidle_save_irq_context(&context);
		ret = psci_ops.cpu_suspend(state, 0);
		arm_cpuidle_restore_irq_context(&context);
		ct_cpuidle_exit();
	} else {
		/*
		 * ARM64 cpu_suspend() wants to do ct_cpuidle_*() itself.
		 */
		if (!IS_ENABLED(CONFIG_ARM64))
			ct_cpuidle_enter();

		ret = cpu_suspend(state, psci_suspend_finisher);

		if (!IS_ENABLED(CONFIG_ARM64))
			ct_cpuidle_exit();
	}

	return ret;
}
#endif

static int psci_system_suspend(unsigned long unused)
{
	int err;
	phys_addr_t pa_cpu_resume = __pa_symbol(cpu_resume);

	err = invoke_psci_fn(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND),
			      pa_cpu_resume, 0, 0);
	return psci_to_linux_errno(err);
}

static int psci_system_suspend_enter(suspend_state_t state)
{
	pm_set_resume_via_firmware();

	return cpu_suspend(0, psci_system_suspend);
}

static int psci_system_suspend_begin(suspend_state_t state)
{
	pm_set_suspend_via_firmware();

	return 0;
}

static const struct platform_suspend_ops psci_suspend_ops = {
	.valid          = suspend_valid_only_mem,
	.enter          = psci_system_suspend_enter,
	.begin          = psci_system_suspend_begin,
};

static void __init psci_init_system_reset2(void)

Annotation

Implementation Notes