1 /* 2 * OMAP4 Power Management Routines 3 * 4 * Copyright (C) 2010 Texas Instruments, Inc. 5 * Rajendra Nayak <rnayak@ti.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 12 #include <linux/pm.h> 13 #include <linux/suspend.h> 14 #include <linux/module.h> 15 #include <linux/list.h> 16 #include <linux/err.h> 17 #include <linux/slab.h> 18 19 #include "powerdomain.h" 20 #include <mach/omap4-common.h> 21 22 struct power_state { 23 struct powerdomain *pwrdm; 24 u32 next_state; 25 #ifdef CONFIG_SUSPEND 26 u32 saved_state; 27 #endif 28 struct list_head node; 29 }; 30 31 static LIST_HEAD(pwrst_list); 32 33 #ifdef CONFIG_SUSPEND 34 static int omap4_pm_suspend(void) 35 { 36 do_wfi(); 37 return 0; 38 } 39 40 static int omap4_pm_enter(suspend_state_t suspend_state) 41 { 42 int ret = 0; 43 44 switch (suspend_state) { 45 case PM_SUSPEND_STANDBY: 46 case PM_SUSPEND_MEM: 47 ret = omap4_pm_suspend(); 48 break; 49 default: 50 ret = -EINVAL; 51 } 52 53 return ret; 54 } 55 56 static int omap4_pm_begin(suspend_state_t state) 57 { 58 disable_hlt(); 59 return 0; 60 } 61 62 static void omap4_pm_end(void) 63 { 64 enable_hlt(); 65 return; 66 } 67 68 static const struct platform_suspend_ops omap_pm_ops = { 69 .begin = omap4_pm_begin, 70 .end = omap4_pm_end, 71 .enter = omap4_pm_enter, 72 .valid = suspend_valid_only_mem, 73 }; 74 #endif /* CONFIG_SUSPEND */ 75 76 static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) 77 { 78 struct power_state *pwrst; 79 80 if (!pwrdm->pwrsts) 81 return 0; 82 83 pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC); 84 if (!pwrst) 85 return -ENOMEM; 86 pwrst->pwrdm = pwrdm; 87 pwrst->next_state = PWRDM_POWER_ON; 88 list_add(&pwrst->node, &pwrst_list); 89 90 return pwrdm_set_next_pwrst(pwrst->pwrdm, pwrst->next_state); 91 } 92 93 /** 94 * omap4_pm_init - Init routine for OMAP4 PM 95 * 96 * Initializes all powerdomain and clockdomain target states 97 * and all PRCM settings. 98 */ 99 static int __init omap4_pm_init(void) 100 { 101 int ret; 102 103 if (!cpu_is_omap44xx()) 104 return -ENODEV; 105 106 pr_err("Power Management for TI OMAP4.\n"); 107 108 #ifdef CONFIG_PM 109 ret = pwrdm_for_each(pwrdms_setup, NULL); 110 if (ret) { 111 pr_err("Failed to setup powerdomains\n"); 112 goto err2; 113 } 114 #endif 115 116 #ifdef CONFIG_SUSPEND 117 suspend_set_ops(&omap_pm_ops); 118 #endif /* CONFIG_SUSPEND */ 119 120 err2: 121 return ret; 122 } 123 late_initcall(omap4_pm_init); 124