root/arch/arm64/kernel/cpuidle.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. arm_cpuidle_init
  2. arm_cpuidle_suspend
  3. psci_acpi_cpu_init_idle
  4. acpi_processor_ffh_lpi_probe
  5. acpi_processor_ffh_lpi_enter

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * ARM64 CPU idle arch support
   4  *
   5  * Copyright (C) 2014 ARM Ltd.
   6  * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
   7  */
   8 
   9 #include <linux/acpi.h>
  10 #include <linux/cpuidle.h>
  11 #include <linux/cpu_pm.h>
  12 #include <linux/of.h>
  13 #include <linux/of_device.h>
  14 #include <linux/psci.h>
  15 
  16 #include <asm/cpuidle.h>
  17 #include <asm/cpu_ops.h>
  18 
  19 int arm_cpuidle_init(unsigned int cpu)
  20 {
  21         int ret = -EOPNOTSUPP;
  22 
  23         if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_suspend &&
  24                         cpu_ops[cpu]->cpu_init_idle)
  25                 ret = cpu_ops[cpu]->cpu_init_idle(cpu);
  26 
  27         return ret;
  28 }
  29 
  30 /**
  31  * arm_cpuidle_suspend() - function to enter a low-power idle state
  32  * @arg: argument to pass to CPU suspend operations
  33  *
  34  * Return: 0 on success, -EOPNOTSUPP if CPU suspend hook not initialized, CPU
  35  * operations back-end error code otherwise.
  36  */
  37 int arm_cpuidle_suspend(int index)
  38 {
  39         int cpu = smp_processor_id();
  40 
  41         return cpu_ops[cpu]->cpu_suspend(index);
  42 }
  43 
  44 #ifdef CONFIG_ACPI
  45 
  46 #include <acpi/processor.h>
  47 
  48 #define ARM64_LPI_IS_RETENTION_STATE(arch_flags) (!(arch_flags))
  49 
  50 static int psci_acpi_cpu_init_idle(unsigned int cpu)
  51 {
  52         int i, count;
  53         struct acpi_lpi_state *lpi;
  54         struct acpi_processor *pr = per_cpu(processors, cpu);
  55 
  56         /*
  57          * If the PSCI cpu_suspend function hook has not been initialized
  58          * idle states must not be enabled, so bail out
  59          */
  60         if (!psci_ops.cpu_suspend)
  61                 return -EOPNOTSUPP;
  62 
  63         if (unlikely(!pr || !pr->flags.has_lpi))
  64                 return -EINVAL;
  65 
  66         count = pr->power.count - 1;
  67         if (count <= 0)
  68                 return -ENODEV;
  69 
  70         for (i = 0; i < count; i++) {
  71                 u32 state;
  72 
  73                 lpi = &pr->power.lpi_states[i + 1];
  74                 /*
  75                  * Only bits[31:0] represent a PSCI power_state while
  76                  * bits[63:32] must be 0x0 as per ARM ACPI FFH Specification
  77                  */
  78                 state = lpi->address;
  79                 if (!psci_power_state_is_valid(state)) {
  80                         pr_warn("Invalid PSCI power state %#x\n", state);
  81                         return -EINVAL;
  82                 }
  83         }
  84 
  85         return 0;
  86 }
  87 
  88 int acpi_processor_ffh_lpi_probe(unsigned int cpu)
  89 {
  90         return psci_acpi_cpu_init_idle(cpu);
  91 }
  92 
  93 int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
  94 {
  95         u32 state = lpi->address;
  96 
  97         if (ARM64_LPI_IS_RETENTION_STATE(lpi->arch_flags))
  98                 return CPU_PM_CPU_IDLE_ENTER_RETENTION_PARAM(psci_cpu_suspend_enter,
  99                                                 lpi->index, state);
 100         else
 101                 return CPU_PM_CPU_IDLE_ENTER_PARAM(psci_cpu_suspend_enter,
 102                                              lpi->index, state);
 103 }
 104 #endif

/* [<][>][^][v][top][bottom][index][help] */