0001
0002
0003
0004
0005
0006
0007
0008 #undef DEBUG
0009
0010 #include <linux/kernel.h>
0011 #include <linux/string.h>
0012 #include <linux/irq.h>
0013
0014 #include <asm/machdep.h>
0015 #include <asm/reg.h>
0016 #include <asm/smp.h>
0017
0018 #include "pasemi.h"
0019
0020 struct sleep_mode {
0021 char *name;
0022 void (*entry)(void);
0023 };
0024
0025 static struct sleep_mode modes[] = {
0026 { .name = "spin", .entry = &idle_spin },
0027 { .name = "doze", .entry = &idle_doze },
0028 };
0029
0030 static int current_mode = 0;
0031
0032 static int pasemi_system_reset_exception(struct pt_regs *regs)
0033 {
0034
0035
0036
0037
0038
0039 if (regs->msr & SRR1_WAKEMASK)
0040 regs_set_return_ip(regs, regs->link);
0041
0042 switch (regs->msr & SRR1_WAKEMASK) {
0043 case SRR1_WAKEDEC:
0044 set_dec(1);
0045 break;
0046 case SRR1_WAKEEE:
0047
0048
0049
0050
0051
0052 break;
0053 default:
0054
0055 return 0;
0056 }
0057
0058
0059 restore_astate(hard_smp_processor_id());
0060
0061
0062 regs_set_recoverable(regs);
0063 return 1;
0064 }
0065
0066 static int __init pasemi_idle_init(void)
0067 {
0068 #ifndef CONFIG_PPC_PASEMI_CPUFREQ
0069 pr_warn("No cpufreq driver, powersavings modes disabled\n");
0070 current_mode = 0;
0071 #endif
0072
0073 ppc_md.system_reset_exception = pasemi_system_reset_exception;
0074 ppc_md.power_save = modes[current_mode].entry;
0075 pr_info("Using PA6T idle loop (%s)\n", modes[current_mode].name);
0076
0077 return 0;
0078 }
0079 machine_late_initcall(pasemi, pasemi_idle_init);
0080
0081 static int __init idle_param(char *p)
0082 {
0083 int i;
0084 for (i = 0; i < ARRAY_SIZE(modes); i++) {
0085 if (!strcmp(modes[i].name, p)) {
0086 current_mode = i;
0087 break;
0088 }
0089 }
0090 return 0;
0091 }
0092
0093 early_param("idle", idle_param);