drivers/cpuidle/cpuidle-tegra.c

Source file repositories/reference/linux-study-clean/drivers/cpuidle/cpuidle-tegra.c

File Facts

System
Linux kernel
Corpus path
drivers/cpuidle/cpuidle-tegra.c
Extension
.c
Size
9676 bytes
Lines
404
Domain
Driver Families
Bucket
drivers/cpuidle
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

if (cpu > 0) {
			tegra_enable_cpu_clock(cpu);
			tegra_cpu_out_of_reset(cpu);
			flowctrl_write_cpu_halt(cpu, 0);
		}
	}
}

static int tegra_cpuidle_cc6_enter(unsigned int cpu)
{
	int ret;

	if (cpu > 0) {
		ret = cpu_suspend(cpu, tegra_pm_park_secondary_cpu);
	} else {
		ret = tegra_cpuidle_wait_for_secondary_cpus_parking();
		if (!ret)
			ret = tegra_pm_enter_lp2();

		tegra_cpuidle_unpark_secondary_cpus();
	}

	return ret;
}

static int tegra_cpuidle_c7_enter(void)
{
	int err;

	err = call_firmware_op(prepare_idle, TF_PM_MODE_LP2_NOFLUSH_L2);
	if (err && err != -ENOSYS)
		return err;

	return cpu_suspend(0, tegra30_pm_secondary_cpu_suspend);
}

static int tegra_cpuidle_coupled_barrier(struct cpuidle_device *dev)
{
	if (tegra_pending_sgi()) {
		/*
		 * CPU got local interrupt that will be lost after GIC's
		 * shutdown because GIC driver doesn't save/restore the
		 * pending SGI state across CPU cluster PM.  Abort and retry
		 * next time.
		 */
		atomic_set(&tegra_abort_flag, 1);
	}

	cpuidle_coupled_parallel_barrier(dev, &tegra_idle_barrier);

	if (atomic_read(&tegra_abort_flag)) {
		cpuidle_coupled_parallel_barrier(dev, &tegra_idle_barrier);
		atomic_set(&tegra_abort_flag, 0);
		return -EINTR;
	}

	return 0;
}

static __cpuidle int tegra_cpuidle_state_enter(struct cpuidle_device *dev,
					       int index, unsigned int cpu)
{
	int err;

	/*
	 * CC6 state is the "CPU cluster power-off" state.  In order to
	 * enter this state, at first the secondary CPU cores need to be
	 * parked into offline mode, then the last CPU should clean out
	 * remaining dirty cache lines into DRAM and trigger Flow Controller
	 * logic that turns off the cluster's power domain (which includes
	 * CPU cores, GIC and L2 cache).
	 */
	if (index == TEGRA_CC6) {
		err = tegra_cpuidle_coupled_barrier(dev);
		if (err)
			return err;
	}

	local_fiq_disable();
	tegra_pm_set_cpu_in_lp2();
	cpu_pm_enter();

	ct_cpuidle_enter();

	switch (index) {
	case TEGRA_C7:
		err = tegra_cpuidle_c7_enter();
		break;

	case TEGRA_CC6:

Annotation

Implementation Notes