arch/arm/mach-exynos/mcpm-exynos.c

Source file repositories/reference/linux-study-clean/arch/arm/mach-exynos/mcpm-exynos.c

File Facts

System
Linux kernel
Corpus path
arch/arm/mach-exynos/mcpm-exynos.c
Extension
.c
Size
8634 bytes
Lines
315
Domain
Architecture Layer
Bucket
arch/arm
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

while (timeout && !pmu_raw_readl(S5P_PMU_SPARE2)) {
				timeout--;
				udelay(10);
			}

			if (timeout == 0) {
				pr_err("cpu %u cluster %u powerup failed\n",
				       cpu, cluster);
				exynos_cpu_power_down(cpunr);
				return -ETIMEDOUT;
			}

			pmu_raw_writel(EXYNOS5420_KFC_CORE_RESET(cpu),
					EXYNOS_SWRESET);
		}
	}

	return 0;
}

static int exynos_cluster_powerup(unsigned int cluster)
{
	pr_debug("%s: cluster %u\n", __func__, cluster);
	if (cluster >= EXYNOS5420_NR_CLUSTERS)
		return -EINVAL;

	exynos_cluster_power_up(cluster);
	return 0;
}

static void exynos_cpu_powerdown_prepare(unsigned int cpu, unsigned int cluster)
{
	unsigned int cpunr = cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER);

	pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
	BUG_ON(cpu >= EXYNOS5420_CPUS_PER_CLUSTER ||
			cluster >= EXYNOS5420_NR_CLUSTERS);
	exynos_cpu_power_down(cpunr);
}

static void exynos_cluster_powerdown_prepare(unsigned int cluster)
{
	pr_debug("%s: cluster %u\n", __func__, cluster);
	BUG_ON(cluster >= EXYNOS5420_NR_CLUSTERS);
	exynos_cluster_power_down(cluster);
}

static void exynos_cpu_cache_disable(void)
{
	/* Disable and flush the local CPU cache. */
	exynos_v7_exit_coherency_flush(louis);
}

static void exynos_cluster_cache_disable(void)
{
	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
		/*
		 * On the Cortex-A15 we need to disable
		 * L2 prefetching before flushing the cache.
		 */
		asm volatile(
		"mcr	p15, 1, %0, c15, c0, 3\n\t"
		"isb\n\t"
		"dsb"
		: : "r" (0x400));
	}

	/* Flush all cache levels for this cluster. */
	exynos_v7_exit_coherency_flush(all);

	/*
	 * Disable cluster-level coherency by masking
	 * incoming snoops and DVM messages:
	 */
	cci_disable_port_by_cpu(read_cpuid_mpidr());
}

static int exynos_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
{
	unsigned int tries = 100;
	unsigned int cpunr = cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER);

	pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
	BUG_ON(cpu >= EXYNOS5420_CPUS_PER_CLUSTER ||
			cluster >= EXYNOS5420_NR_CLUSTERS);

	/* Wait for the core state to be OFF */
	while (tries--) {
		if ((exynos_cpu_power_state(cpunr) == 0))
			return 0; /* success: the CPU is halted */

Annotation

Implementation Notes