linux/arch/powerpc/platforms/pasemi/idle.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2006-2007 PA Semi, Inc
   4 *
   5 * Maintained by: Olof Johansson <olof@lixom.net>
   6 */
   7
   8#undef DEBUG
   9
  10#include <linux/kernel.h>
  11#include <linux/string.h>
  12#include <linux/irq.h>
  13
  14#include <asm/machdep.h>
  15#include <asm/reg.h>
  16#include <asm/smp.h>
  17
  18#include "pasemi.h"
  19
  20struct sleep_mode {
  21        char *name;
  22        void (*entry)(void);
  23};
  24
  25static struct sleep_mode modes[] = {
  26        { .name = "spin", .entry = &idle_spin },
  27        { .name = "doze", .entry = &idle_doze },
  28};
  29
  30static int current_mode = 0;
  31
  32static int pasemi_system_reset_exception(struct pt_regs *regs)
  33{
  34        /* If we were woken up from power savings, we need to return
  35         * to the calling function, since nip is not saved across
  36         * all modes.
  37         */
  38
  39        if (regs->msr & SRR1_WAKEMASK)
  40                regs->nip = regs->link;
  41
  42        switch (regs->msr & SRR1_WAKEMASK) {
  43        case SRR1_WAKEDEC:
  44                set_dec(1);
  45        case SRR1_WAKEEE:
  46                /*
  47                 * Handle these when interrupts get re-enabled and we take
  48                 * them as regular exceptions. We are in an NMI context
  49                 * and can't handle these here.
  50                 */
  51                break;
  52        default:
  53                /* do system reset */
  54                return 0;
  55        }
  56
  57        /* Set higher astate since we come out of power savings at 0 */
  58        restore_astate(hard_smp_processor_id());
  59
  60        /* everything handled */
  61        regs->msr |= MSR_RI;
  62        return 1;
  63}
  64
  65static int __init pasemi_idle_init(void)
  66{
  67#ifndef CONFIG_PPC_PASEMI_CPUFREQ
  68        pr_warn("No cpufreq driver, powersavings modes disabled\n");
  69        current_mode = 0;
  70#endif
  71
  72        ppc_md.system_reset_exception = pasemi_system_reset_exception;
  73        ppc_md.power_save = modes[current_mode].entry;
  74        pr_info("Using PA6T idle loop (%s)\n", modes[current_mode].name);
  75
  76        return 0;
  77}
  78machine_late_initcall(pasemi, pasemi_idle_init);
  79
  80static int __init idle_param(char *p)
  81{
  82        int i;
  83        for (i = 0; i < ARRAY_SIZE(modes); i++) {
  84                if (!strcmp(modes[i].name, p)) {
  85                        current_mode = i;
  86                        break;
  87                }
  88        }
  89        return 0;
  90}
  91
  92early_param("idle", idle_param);
  93