diff options
author | Karan Jhavar <kjhavar@nvidia.com> | 2011-05-02 13:32:57 -0700 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-05-17 11:52:43 -0700 |
commit | 99f755b0c92dc8b4eaf9c235b3527220c95af236 (patch) | |
tree | 3f2f5b414199237b441d32630a83a8453b68f819 | |
parent | de4c80095b759924d0b8867918daa3dbc884c222 (diff) |
ARM: tegra: power LP0/LP1 selection via sysfs
Select LP0/LP1 on runtime using sysfs node /sys/power/suspend/type.
Valid selctions/commands are:
1. lp0
2. lp1
3. lp2
Change-Id: I335a8845dbfed7539ae4bf8aee3ba3b97ecb3db3
Reviewed-on: http://git-master/r/30081
Reviewed-by: Karan Jhavar <kjhavar@nvidia.com>
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Tested-by: Karan Jhavar <kjhavar@nvidia.com>
Reviewed-by: Scott Williams <scwilliams@nvidia.com>
Reviewed-by: Varun Wadekar <vwadekar@nvidia.com>
-rw-r--r-- | arch/arm/mach-tegra/gpio.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-tegra/irq.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-tegra/suspend.c | 75 |
3 files changed, 68 insertions, 19 deletions
diff --git a/arch/arm/mach-tegra/gpio.c b/arch/arm/mach-tegra/gpio.c index 66f37f9b4d65..25d1eaa31de1 100644 --- a/arch/arm/mach-tegra/gpio.c +++ b/arch/arm/mach-tegra/gpio.c @@ -240,8 +240,7 @@ static int tegra_gpio_irq_set_type(unsigned int irq, unsigned int type) else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) __set_irq_handler_unlocked(irq, handle_edge_irq); - if (tegra_get_suspend_mode() == TEGRA_SUSPEND_LP0) - tegra_set_lp0_wake_type(irq, type); + tegra_set_lp0_wake_type(irq, type); return 0; } @@ -363,12 +362,10 @@ static int tegra_gpio_wake_enable(unsigned int irq, unsigned int enable) struct tegra_gpio_bank *bank = get_irq_chip_data(irq); ret = tegra_set_lp1_wake(bank->irq, enable); + ret |= tegra_set_lp0_wake(irq, enable); if (ret) return ret; - if (tegra_get_suspend_mode() == TEGRA_SUSPEND_LP0) - return tegra_set_lp0_wake(irq, enable); - return 0; } #endif diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c index e9e51ba47575..3abc6da46167 100644 --- a/arch/arm/mach-tegra/irq.c +++ b/arch/arm/mach-tegra/irq.c @@ -270,10 +270,7 @@ static int tegra_set_wake(unsigned int irq, unsigned int enable) static int tegra_set_type(unsigned int irq, unsigned int flow_type) { - if (tegra_get_suspend_mode() == TEGRA_SUSPEND_LP0) - return tegra_set_lp0_wake_type(irq, flow_type); - - return 0; + return tegra_set_lp0_wake_type(irq, flow_type); } static void tegra_ack(unsigned int irq) diff --git a/arch/arm/mach-tegra/suspend.c b/arch/arm/mach-tegra/suspend.c index dc8ff5699849..80269b5f7c59 100644 --- a/arch/arm/mach-tegra/suspend.c +++ b/arch/arm/mach-tegra/suspend.c @@ -22,6 +22,7 @@ #include <linux/kernel.h> #include <linux/cpumask.h> +#include <linux/ctype.h> #include <linux/init.h> #include <linux/io.h> #include <linux/sched.h> @@ -181,6 +182,15 @@ static enum tegra_suspend_mode current_suspend_mode; static unsigned int tegra_time_in_suspend[32]; +struct kobject *suspend_kobj; + +static const char *tegra_suspend_name[TEGRA_MAX_SUSPEND_MODE] = { + [TEGRA_SUSPEND_NONE] = "none", + [TEGRA_SUSPEND_LP2] = "lp2", + [TEGRA_SUSPEND_LP1] = "lp1", + [TEGRA_SUSPEND_LP0] = "lp0", +}; + #if INSTRUMENT_CLUSTER_SWITCH enum tegra_cluster_switch_time_id { @@ -213,6 +223,49 @@ static unsigned long tegra_cluster_switch_times[tegra_cluster_switch_time_id_max #define cpu_number() 0 #endif +static ssize_t suspend_mode_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + char *start = buf; + char *end = buf + PAGE_SIZE; + + start += scnprintf(start, end - start, "%s ", \ + tegra_suspend_name[current_suspend_mode]); + start += scnprintf(start, end - start, "\n"); + + return start - buf; +} + +static ssize_t suspend_mode_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t n) +{ + int len; + const char *name_ptr; + enum tegra_suspend_mode new_mode; + + name_ptr = buf; + while (*name_ptr && !isspace(*name_ptr)) + name_ptr++; + len = name_ptr - buf; + if (!len) + goto bad_name; + + for (new_mode = TEGRA_SUSPEND_NONE; \ + new_mode < TEGRA_MAX_SUSPEND_MODE; ++new_mode) { + if (!strncmp(buf, tegra_suspend_name[new_mode], len)) { + current_suspend_mode = new_mode; + break; + } + } + +bad_name: + return n; +} + +static struct kobj_attribute suspend_mode_attribute = + __ATTR(mode, 0666, suspend_mode_show, suspend_mode_store); + static inline unsigned int time_to_bin(unsigned int time) { return fls(time); @@ -247,7 +300,7 @@ enum tegra_suspend_mode tegra_get_suspend_mode(void) if (!pdata) return TEGRA_SUSPEND_NONE; - return pdata->suspend_mode; + return current_suspend_mode; } #if defined(CONFIG_PM) || defined(CONFIG_CPU_IDLE) || !defined(CONFIG_ARCH_TEGRA_2x_SOC) @@ -678,8 +731,7 @@ void tegra_suspend_dram(bool do_lp0) pr_err_ratelimited("WFI for LP1 failed for CPU %d: count %lu\n", cpu, tegra_wfi_fail_count[cpu]); } - } - else { + } else { tegra_cpu_reset_handler_enable(); tegra_cpu_reset_handler_restore(); tegra_lp0_resume_mc(); @@ -1018,16 +1070,19 @@ void __init tegra_init_suspend(struct tegra_suspend_platform_data *plat) #endif current_suspend_mode = plat->suspend_mode; + + /* Create /sys/power/suspend/type */ + suspend_kobj = kobject_create_and_add("suspend", power_kobj); + if (suspend_kobj) { + if (sysfs_create_file(suspend_kobj, \ + &suspend_mode_attribute.attr)) + pr_err("%s: sysfs_create_file suspend type failed!", \ + __func__); + } } -#ifdef CONFIG_DEBUG_FS -static const char *tegra_suspend_name[TEGRA_MAX_SUSPEND_MODE] = { - [TEGRA_SUSPEND_NONE] = "none", - [TEGRA_SUSPEND_LP2] = "lp2", - [TEGRA_SUSPEND_LP1] = "lp1", - [TEGRA_SUSPEND_LP0] = "lp0", -}; +#ifdef CONFIG_DEBUG_FS static int tegra_suspend_debug_show(struct seq_file *s, void *data) { seq_printf(s, "%s\n", tegra_suspend_name[*(int *)s->private]); |