arch/powerpc/sysdev/fsl_rcpm.c

Source file repositories/reference/linux-study-clean/arch/powerpc/sysdev/fsl_rcpm.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/sysdev/fsl_rcpm.c
Extension
.c
Size
8740 bytes
Lines
383
Domain
Architecture Layer
Bucket
arch/powerpc
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

if (cpu_is_offline(primary) && cpu_is_offline(primary + 1)) {
			/* if both threads are offline, put the cpu in PH20 */
			rcpm_v2_cpu_enter_state(cpu, E500_PM_PH20);
		} else {
			/* if only one thread is offline, disable the thread */
			qoriq_disable_thread(cpu);
		}
	}
#endif

	if (threads_per_core == 1)
		rcpm_v2_cpu_enter_state(cpu, E500_PM_PH20);
}

static void rcpm_v1_cpu_exit_state(int cpu, int state)
{
	int hw_cpu = get_hard_smp_processor_id(cpu);
	unsigned int mask = 1 << hw_cpu;

	switch (state) {
	case E500_PM_PH10:
		clrbits32(&rcpm_v1_regs->cdozcr, mask);
		break;
	case E500_PM_PH15:
		clrbits32(&rcpm_v1_regs->cnapcr, mask);
		break;
	default:
		pr_warn("Unknown cpu PM state (%d)\n", state);
		break;
	}
}

static void rcpm_v1_cpu_up_prepare(int cpu)
{
	rcpm_v1_cpu_exit_state(cpu, E500_PM_PH15);
	rcpm_v1_irq_unmask(cpu);
}

static void rcpm_v2_cpu_exit_state(int cpu, int state)
{
	int hw_cpu = get_hard_smp_processor_id(cpu);
	u32 mask = 1 << cpu_core_index_of_thread(cpu);

	switch (state) {
	case E500_PM_PH10:
		setbits32(&rcpm_v2_regs->tph10clrr0, 1 << hw_cpu);
		break;
	case E500_PM_PH15:
		setbits32(&rcpm_v2_regs->pcph15clrr, mask);
		break;
	case E500_PM_PH20:
		setbits32(&rcpm_v2_regs->pcph20clrr, mask);
		break;
	case E500_PM_PH30:
		setbits32(&rcpm_v2_regs->pcph30clrr, mask);
		break;
	default:
		pr_warn("Unknown cpu PM state (%d)\n", state);
	}
}

static void rcpm_v2_cpu_up_prepare(int cpu)
{
	rcpm_v2_cpu_exit_state(cpu, E500_PM_PH20);
	rcpm_v2_irq_unmask(cpu);
}

static int rcpm_v1_plat_enter_state(int state)
{
	u32 *pmcsr_reg = &rcpm_v1_regs->powmgtcsr;
	int ret = 0;
	int result;

	switch (state) {
	case PLAT_PM_SLEEP:
		setbits32(pmcsr_reg, RCPM_POWMGTCSR_SLP);

		/* Upon resume, wait for RCPM_POWMGTCSR_SLP bit to be clear. */
		result = spin_event_timeout(
		  !(in_be32(pmcsr_reg) & RCPM_POWMGTCSR_SLP), 10000, 10);
		if (!result) {
			pr_err("timeout waiting for SLP bit to be cleared\n");
			ret = -ETIMEDOUT;
		}
		break;
	default:
		pr_warn("Unknown platform PM state (%d)", state);
		ret = -EINVAL;
	}

Annotation

Implementation Notes