* [PATCH 1/3] ARM: exynos: Save combiner registers on suspend
@ 2012-07-20 18:14 Jonathan Kliegman
2012-07-20 18:14 ` [PATCH 2/3] ARM: exynos: change local variable combiner_data to use unique name Jonathan Kliegman
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Jonathan Kliegman @ 2012-07-20 18:14 UTC (permalink / raw)
To: linux-samsung-soc; +Cc: kgene.kim, Jonathan Kliegman
The interupt combiner registers need to be saved on suspend resume
or its interrupts (trackpad and keyboard most noticeably) won't work
after resume.
Signed-off-by: Jonathan Kliegman <kliegs@chromium.org>
---
arch/arm/mach-exynos/common.c | 74 +++++++++++++++++++++++++++++++++++++----
1 files changed, 67 insertions(+), 7 deletions(-)
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 4eb39cd..1b28aa6 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -22,6 +22,7 @@
#include <linux/export.h>
#include <linux/irqdomain.h>
#include <linux/of_address.h>
+#include <linux/cpu_pm.h>
#include <asm/proc-fns.h>
#include <asm/exception.h>
@@ -405,10 +406,14 @@ struct combiner_chip_data {
unsigned int irq_offset;
unsigned int irq_mask;
void __iomem *base;
+#ifdef CONFIG_PM
+ bool saved_on;
+#endif
};
static struct irq_domain *combiner_irq_domain;
static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
+static unsigned int rt_max_combiner_nr;
static inline void __iomem *combiner_base(struct irq_data *data)
{
@@ -535,6 +540,55 @@ static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq,
return 0;
}
+#ifdef CONFIG_PM
+static void combiner_save(void)
+{
+ int i;
+
+ for (i = 0; i < rt_max_combiner_nr; i++) {
+ if (combiner_data[i].irq_mask &
+ __raw_readl(combiner_data[i].base + COMBINER_ENABLE_SET)) {
+ combiner_data[i].saved_on = true;
+ } else {
+ combiner_data[i].saved_on = false;
+ }
+ }
+}
+
+static void combiner_restore(void)
+{
+ int i;
+
+ for (i = 0; i < rt_max_combiner_nr; i++) {
+ if (!combiner_data[i].saved_on)
+ continue;
+
+ __raw_writel(combiner_data[i].irq_mask,
+ combiner_data[i].base + COMBINER_ENABLE_SET);
+ }
+}
+
+
+static int combiner_notifier(struct notifier_block *self, unsigned long cmd,
+ void *v)
+{
+ switch (cmd) {
+ case CPU_PM_ENTER:
+ combiner_save();
+ break;
+ case CPU_PM_EXIT:
+ combiner_restore();
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block combiner_notifier_block = {
+ .notifier_call = combiner_notifier,
+};
+#endif
+
static struct irq_domain_ops combiner_irq_domain_ops = {
.xlate = combiner_irq_domain_xlate,
.map = combiner_irq_domain_map,
@@ -544,20 +598,21 @@ static void __init combiner_init(void __iomem *combiner_base,
struct device_node *np)
{
int i, irq, irq_base;
- unsigned int max_nr, nr_irq;
+ unsigned int nr_irq;
if (np) {
- if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) {
+ if (of_property_read_u32(np, "samsung,combiner-nr",
+ &rt_max_combiner_nr)) {
pr_warning("%s: number of combiners not specified, "
"setting default as %d.\n",
__func__, EXYNOS4_MAX_COMBINER_NR);
- max_nr = EXYNOS4_MAX_COMBINER_NR;
+ rt_max_combiner_nr = EXYNOS4_MAX_COMBINER_NR;
}
} else {
- max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR :
- EXYNOS4_MAX_COMBINER_NR;
+ rt_max_combiner_nr = soc_is_exynos5250() ?
+ EXYNOS5_MAX_COMBINER_NR : EXYNOS4_MAX_COMBINER_NR;
}
- nr_irq = max_nr * MAX_IRQ_IN_COMBINER;
+ nr_irq = rt_max_combiner_nr * MAX_IRQ_IN_COMBINER;
irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0);
if (IS_ERR_VALUE(irq_base)) {
@@ -572,7 +627,7 @@ static void __init combiner_init(void __iomem *combiner_base,
return;
}
- for (i = 0; i < max_nr; i++) {
+ for (i = 0; i < rt_max_combiner_nr; i++) {
combiner_init_one(i, combiner_base + (i >> 2) * 0x10);
irq = IRQ_SPI(i);
#ifdef CONFIG_OF
@@ -581,6 +636,11 @@ static void __init combiner_init(void __iomem *combiner_base,
#endif
combiner_cascade_irq(i, irq);
}
+
+#ifdef CONFIG_PM
+ /* Setup suspend/resume combiner saving */
+ cpu_pm_register_notifier(&combiner_notifier_block);
+#endif
}
#ifdef CONFIG_OF
--
1.7.7.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/3] ARM: exynos: change local variable combiner_data to use unique name
2012-07-20 18:14 [PATCH 1/3] ARM: exynos: Save combiner registers on suspend Jonathan Kliegman
@ 2012-07-20 18:14 ` Jonathan Kliegman
2012-07-20 18:14 ` [PATCH 3/3] ARM: exynos: Size combiner_data dynamically after dt parsing Jonathan Kliegman
2012-08-01 11:38 ` [PATCH 1/3] ARM: exynos: Save combiner registers on suspend Kukjin Kim
2 siblings, 0 replies; 8+ messages in thread
From: Jonathan Kliegman @ 2012-07-20 18:14 UTC (permalink / raw)
To: linux-samsung-soc; +Cc: kgene.kim, Jonathan Kliegman
combiner_data in combiner_base() has the same name as the global
combiner_data array. Clean this up.
Signed-off-by: Jonathan Kliegman <kliegs@chromium.org>
---
arch/arm/mach-exynos/common.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 1b28aa6..3627869 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -417,10 +417,10 @@ static unsigned int rt_max_combiner_nr;
static inline void __iomem *combiner_base(struct irq_data *data)
{
- struct combiner_chip_data *combiner_data =
+ struct combiner_chip_data *irq_combiner_data =
irq_data_get_irq_chip_data(data);
- return combiner_data->base;
+ return irq_combiner_data->base;
}
static void combiner_mask_irq(struct irq_data *data)
--
1.7.7.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/3] ARM: exynos: Size combiner_data dynamically after dt parsing
2012-07-20 18:14 [PATCH 1/3] ARM: exynos: Save combiner registers on suspend Jonathan Kliegman
2012-07-20 18:14 ` [PATCH 2/3] ARM: exynos: change local variable combiner_data to use unique name Jonathan Kliegman
@ 2012-07-20 18:14 ` Jonathan Kliegman
2012-08-01 11:38 ` [PATCH 1/3] ARM: exynos: Save combiner registers on suspend Kukjin Kim
2 siblings, 0 replies; 8+ messages in thread
From: Jonathan Kliegman @ 2012-07-20 18:14 UTC (permalink / raw)
To: linux-samsung-soc; +Cc: kgene.kim, Jonathan Kliegman
The number of combiner_data entries depends on the device tree parsing
now. Allocate the array based on the results of the parsing or fall
back on EXYNOS4 or EXYNOS5 defaults based on the SOC running.
Signed-off-by: Jonathan Kliegman <kliegs@chromium.org>
---
arch/arm/mach-exynos/common.c | 41 +++++++++++++++++++++++++----------------
1 files changed, 25 insertions(+), 16 deletions(-)
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 3627869..5075e0c 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -412,7 +412,7 @@ struct combiner_chip_data {
};
static struct irq_domain *combiner_irq_domain;
-static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
+static struct combiner_chip_data *combiner_data;
static unsigned int rt_max_combiner_nr;
static inline void __iomem *combiner_base(struct irq_data *data)
@@ -474,15 +474,6 @@ static struct irq_chip combiner_chip = {
static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
{
- unsigned int max_nr;
-
- if (soc_is_exynos5250())
- max_nr = EXYNOS5_MAX_COMBINER_NR;
- else
- max_nr = EXYNOS4_MAX_COMBINER_NR;
-
- if (combiner_nr >= max_nr)
- BUG();
if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0)
BUG();
irq_set_chained_handler(irq, combiner_handle_cascade_irq);
@@ -598,20 +589,37 @@ static void __init combiner_init(void __iomem *combiner_base,
struct device_node *np)
{
int i, irq, irq_base;
- unsigned int nr_irq;
+ unsigned int nr_irq, soc_max_nr;
+
+ soc_max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR :
+ EXYNOS4_MAX_COMBINER_NR;
if (np) {
if (of_property_read_u32(np, "samsung,combiner-nr",
&rt_max_combiner_nr)) {
+ rt_max_combiner_nr = soc_max_nr;
pr_warning("%s: number of combiners not specified, "
- "setting default as %d.\n",
- __func__, EXYNOS4_MAX_COMBINER_NR);
- rt_max_combiner_nr = EXYNOS4_MAX_COMBINER_NR;
+ "setting default as %d.\n",
+ __func__, rt_max_combiner_nr);
}
} else {
- rt_max_combiner_nr = soc_is_exynos5250() ?
- EXYNOS5_MAX_COMBINER_NR : EXYNOS4_MAX_COMBINER_NR;
+ rt_max_combiner_nr = soc_max_nr;
}
+ if (WARN_ON(rt_max_combiner_nr > soc_max_nr)) {
+ pr_warning("%s: more combiners specified (%d) than "
+ "architecture (%d) supports.",
+ __func__, rt_max_combiner_nr, soc_max_nr);
+ return;
+ }
+
+ combiner_data = kmalloc(sizeof(struct combiner_chip_data) *
+ rt_max_combiner_nr, GFP_KERNEL);
+ if (WARN_ON(!combiner_data)) {
+ pr_warning("%s: combiner_data memory allocation failed for %d "
+ "entries", __func__, rt_max_combiner_nr);
+ return;
+ }
+
nr_irq = rt_max_combiner_nr * MAX_IRQ_IN_COMBINER;
irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0);
@@ -624,6 +632,7 @@ static void __init combiner_init(void __iomem *combiner_base,
&combiner_irq_domain_ops, &combiner_data);
if (WARN_ON(!combiner_irq_domain)) {
pr_warning("%s: irq domain init failed\n", __func__);
+ kfree(combiner_data);
return;
}
--
1.7.7.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* RE: [PATCH 1/3] ARM: exynos: Save combiner registers on suspend
2012-07-20 18:14 [PATCH 1/3] ARM: exynos: Save combiner registers on suspend Jonathan Kliegman
2012-07-20 18:14 ` [PATCH 2/3] ARM: exynos: change local variable combiner_data to use unique name Jonathan Kliegman
2012-07-20 18:14 ` [PATCH 3/3] ARM: exynos: Size combiner_data dynamically after dt parsing Jonathan Kliegman
@ 2012-08-01 11:38 ` Kukjin Kim
2012-08-03 20:05 ` [PATCH v2 " Jonathan Kliegman
2 siblings, 1 reply; 8+ messages in thread
From: Kukjin Kim @ 2012-08-01 11:38 UTC (permalink / raw)
To: 'Jonathan Kliegman', linux-samsung-soc
Jonathan Kliegman wrote:
>
> The interupt combiner registers need to be saved on suspend resume
> or its interrupts (trackpad and keyboard most noticeably) won't work
> after resume.
>
> Signed-off-by: Jonathan Kliegman <kliegs@chromium.org>
> ---
> arch/arm/mach-exynos/common.c | 74
> +++++++++++++++++++++++++++++++++++++----
> 1 files changed, 67 insertions(+), 7 deletions(-)
[...]
> +#ifdef CONFIG_PM
#ifdef CONFIG_CPU_PM?
> +static void combiner_save(void)
> +{
> + int i;
> +
> + for (i = 0; i < rt_max_combiner_nr; i++) {
> + if (combiner_data[i].irq_mask &
> + __raw_readl(combiner_data[i].base +
COMBINER_ENABLE_SET))
> {
> + combiner_data[i].saved_on = true;
> + } else {
> + combiner_data[i].saved_on = false;
> + }
> + }
> +}
> +
> +static void combiner_restore(void)
> +{
> + int i;
> +
> + for (i = 0; i < rt_max_combiner_nr; i++) {
> + if (!combiner_data[i].saved_on)
> + continue;
> +
> + __raw_writel(combiner_data[i].irq_mask,
> + combiner_data[i].base + COMBINER_ENABLE_SET);
> + }
> +}
> +
> +
No need double empty lines :)
> +static int combiner_notifier(struct notifier_block *self, unsigned long
> cmd,
> + void *v)
> +{
> + switch (cmd) {
> + case CPU_PM_ENTER:
Should be CPU_CLUSTER_PM_ENTER?
> + combiner_save();
> + break;
> + case CPU_PM_EXIT:
CPU_CLUSTER_PM_EXIT?
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 1/3] ARM: exynos: Save combiner registers on suspend
2012-08-01 11:38 ` [PATCH 1/3] ARM: exynos: Save combiner registers on suspend Kukjin Kim
@ 2012-08-03 20:05 ` Jonathan Kliegman
2012-08-03 21:27 ` Sylwester Nawrocki
0 siblings, 1 reply; 8+ messages in thread
From: Jonathan Kliegman @ 2012-08-03 20:05 UTC (permalink / raw)
To: linux-samsung-soc; +Cc: kgene.kim, Jonathan Kliegman
The interupt combiner registers need to be saved on suspend and restored
on resume or combiner-based intterupts won't work after resume.
Signed-off-by: Jonathan Kliegman <kliegs@chromium.org>
---
arch/arm/mach-exynos/common.c | 74 +++++++++++++++++++++++++++++++++++++----
1 files changed, 67 insertions(+), 7 deletions(-)
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 4eb39cd..af296e5 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -22,6 +22,7 @@
#include <linux/export.h>
#include <linux/irqdomain.h>
#include <linux/of_address.h>
+#include <linux/cpu_pm.h>
#include <asm/proc-fns.h>
#include <asm/exception.h>
@@ -405,10 +406,14 @@ struct combiner_chip_data {
unsigned int irq_offset;
unsigned int irq_mask;
void __iomem *base;
+#ifdef CONFIG_CPU_PM
+ bool saved_on;
+#endif
};
static struct irq_domain *combiner_irq_domain;
static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
+static unsigned int rt_max_combiner_nr;
static inline void __iomem *combiner_base(struct irq_data *data)
{
@@ -535,6 +540,55 @@ static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq,
return 0;
}
+#ifdef CONFIG_CPU_PM
+static void combiner_save(void)
+{
+ int i;
+
+ for (i = 0; i < rt_max_combiner_nr; i++) {
+ if (combiner_data[i].irq_mask &
+ __raw_readl(combiner_data[i].base + COMBINER_ENABLE_SET)) {
+ combiner_data[i].saved_on = true;
+ } else {
+ combiner_data[i].saved_on = false;
+ }
+ }
+}
+
+static void combiner_restore(void)
+{
+ int i;
+
+ for (i = 0; i < rt_max_combiner_nr; i++) {
+ if (!combiner_data[i].saved_on)
+ continue;
+
+ __raw_writel(combiner_data[i].irq_mask,
+ combiner_data[i].base + COMBINER_ENABLE_SET);
+ }
+}
+
+
+static int combiner_notifier(struct notifier_block *self, unsigned long cmd,
+ void *v)
+{
+ switch (cmd) {
+ case CPU_CLUSTER_PM_ENTER:
+ combiner_save();
+ break;
+ case CPU_CLSUTER_PM_EXIT:
+ combiner_restore();
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block combiner_notifier_block = {
+ .notifier_call = combiner_notifier,
+};
+#endif
+
static struct irq_domain_ops combiner_irq_domain_ops = {
.xlate = combiner_irq_domain_xlate,
.map = combiner_irq_domain_map,
@@ -544,20 +598,21 @@ static void __init combiner_init(void __iomem *combiner_base,
struct device_node *np)
{
int i, irq, irq_base;
- unsigned int max_nr, nr_irq;
+ unsigned int nr_irq;
if (np) {
- if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) {
+ if (of_property_read_u32(np, "samsung,combiner-nr",
+ &rt_max_combiner_nr)) {
pr_warning("%s: number of combiners not specified, "
"setting default as %d.\n",
__func__, EXYNOS4_MAX_COMBINER_NR);
- max_nr = EXYNOS4_MAX_COMBINER_NR;
+ rt_max_combiner_nr = EXYNOS4_MAX_COMBINER_NR;
}
} else {
- max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR :
- EXYNOS4_MAX_COMBINER_NR;
+ rt_max_combiner_nr = soc_is_exynos5250() ?
+ EXYNOS5_MAX_COMBINER_NR : EXYNOS4_MAX_COMBINER_NR;
}
- nr_irq = max_nr * MAX_IRQ_IN_COMBINER;
+ nr_irq = rt_max_combiner_nr * MAX_IRQ_IN_COMBINER;
irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0);
if (IS_ERR_VALUE(irq_base)) {
@@ -572,7 +627,7 @@ static void __init combiner_init(void __iomem *combiner_base,
return;
}
- for (i = 0; i < max_nr; i++) {
+ for (i = 0; i < rt_max_combiner_nr; i++) {
combiner_init_one(i, combiner_base + (i >> 2) * 0x10);
irq = IRQ_SPI(i);
#ifdef CONFIG_OF
@@ -581,6 +636,11 @@ static void __init combiner_init(void __iomem *combiner_base,
#endif
combiner_cascade_irq(i, irq);
}
+
+#ifdef CONFIG_PM
+ /* Setup suspend/resume combiner saving */
+ cpu_pm_register_notifier(&combiner_notifier_block);
+#endif
}
#ifdef CONFIG_OF
--
1.7.7.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 1/3] ARM: exynos: Save combiner registers on suspend
2012-08-03 20:05 ` [PATCH v2 " Jonathan Kliegman
@ 2012-08-03 21:27 ` Sylwester Nawrocki
2012-08-03 21:52 ` Jonathan Kliegman
0 siblings, 1 reply; 8+ messages in thread
From: Sylwester Nawrocki @ 2012-08-03 21:27 UTC (permalink / raw)
To: Jonathan Kliegman; +Cc: linux-samsung-soc, kgene.kim
Hi Jonathan,
On 08/03/2012 10:05 PM, Jonathan Kliegman wrote:
> The interupt combiner registers need to be saved on suspend and restored
> on resume or combiner-based intterupts won't work after resume.
intterupts -> interrupts
> Signed-off-by: Jonathan Kliegman<kliegs@chromium.org>
> ---
> arch/arm/mach-exynos/common.c | 74 +++++++++++++++++++++++++++++++++++++----
> 1 files changed, 67 insertions(+), 7 deletions(-)
>
> diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
> index 4eb39cd..af296e5 100644
> --- a/arch/arm/mach-exynos/common.c
> +++ b/arch/arm/mach-exynos/common.c
> @@ -22,6 +22,7 @@
> #include<linux/export.h>
> #include<linux/irqdomain.h>
> #include<linux/of_address.h>
> +#include<linux/cpu_pm.h>
>
> #include<asm/proc-fns.h>
> #include<asm/exception.h>
> @@ -405,10 +406,14 @@ struct combiner_chip_data {
> unsigned int irq_offset;
> unsigned int irq_mask;
> void __iomem *base;
> +#ifdef CONFIG_CPU_PM
> + bool saved_on;
> +#endif
> };
>
> static struct irq_domain *combiner_irq_domain;
> static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
> +static unsigned int rt_max_combiner_nr;
>
> static inline void __iomem *combiner_base(struct irq_data *data)
> {
> @@ -535,6 +540,55 @@ static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq,
> return 0;
> }
>
> +#ifdef CONFIG_CPU_PM
> +static void combiner_save(void)
> +{
> + int i;
> +
> + for (i = 0; i< rt_max_combiner_nr; i++) {
> + if (combiner_data[i].irq_mask&
> + __raw_readl(combiner_data[i].base + COMBINER_ENABLE_SET)) {
> + combiner_data[i].saved_on = true;
> + } else {
> + combiner_data[i].saved_on = false;
> + }
> + }
> +}
> +
> +static void combiner_restore(void)
> +{
> + int i;
> +
> + for (i = 0; i< rt_max_combiner_nr; i++) {
> + if (!combiner_data[i].saved_on)
> + continue;
> +
> + __raw_writel(combiner_data[i].irq_mask,
> + combiner_data[i].base + COMBINER_ENABLE_SET);
> + }
> +}
> +
> +
> +static int combiner_notifier(struct notifier_block *self, unsigned long cmd,
> + void *v)
> +{
> + switch (cmd) {
> + case CPU_CLUSTER_PM_ENTER:
> + combiner_save();
> + break;
> + case CPU_CLSUTER_PM_EXIT:
Looks like this part of code wasn't compiled or some last minute changes
introduced this typo ?
> + combiner_restore();
> + break;
> + }
> +
> + return NOTIFY_OK;
> +}
> +
> +static struct notifier_block combiner_notifier_block = {
> + .notifier_call = combiner_notifier,
> +};
> +#endif
> +
> static struct irq_domain_ops combiner_irq_domain_ops = {
> .xlate = combiner_irq_domain_xlate,
> .map = combiner_irq_domain_map,
> @@ -544,20 +598,21 @@ static void __init combiner_init(void __iomem *combiner_base,
> struct device_node *np)
> {
> int i, irq, irq_base;
> - unsigned int max_nr, nr_irq;
> + unsigned int nr_irq;
>
> if (np) {
> - if (of_property_read_u32(np, "samsung,combiner-nr",&max_nr)) {
> + if (of_property_read_u32(np, "samsung,combiner-nr",
> + &rt_max_combiner_nr)) {
> pr_warning("%s: number of combiners not specified, "
> "setting default as %d.\n",
> __func__, EXYNOS4_MAX_COMBINER_NR);
> - max_nr = EXYNOS4_MAX_COMBINER_NR;
> + rt_max_combiner_nr = EXYNOS4_MAX_COMBINER_NR;
> }
> } else {
> - max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR :
> - EXYNOS4_MAX_COMBINER_NR;
> + rt_max_combiner_nr = soc_is_exynos5250() ?
> + EXYNOS5_MAX_COMBINER_NR : EXYNOS4_MAX_COMBINER_NR;
> }
> - nr_irq = max_nr * MAX_IRQ_IN_COMBINER;
> + nr_irq = rt_max_combiner_nr * MAX_IRQ_IN_COMBINER;
>
> irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0);
> if (IS_ERR_VALUE(irq_base)) {
> @@ -572,7 +627,7 @@ static void __init combiner_init(void __iomem *combiner_base,
> return;
> }
>
> - for (i = 0; i< max_nr; i++) {
> + for (i = 0; i< rt_max_combiner_nr; i++) {
> combiner_init_one(i, combiner_base + (i>> 2) * 0x10);
> irq = IRQ_SPI(i);
> #ifdef CONFIG_OF
> @@ -581,6 +636,11 @@ static void __init combiner_init(void __iomem *combiner_base,
> #endif
> combiner_cascade_irq(i, irq);
> }
> +
> +#ifdef CONFIG_PM
Shouldn't this also be CONFIG_CPU_PM ? Declaration of combiner_notifier_block
is compiled in only when CONFIG_CPU_PM is defined.
> + /* Setup suspend/resume combiner saving */
> + cpu_pm_register_notifier(&combiner_notifier_block);
> +#endif
> }
>
> #ifdef CONFIG_OF
Thanks,
Sylwester
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 1/3] ARM: exynos: Save combiner registers on suspend
2012-08-03 21:27 ` Sylwester Nawrocki
@ 2012-08-03 21:52 ` Jonathan Kliegman
2012-08-03 22:08 ` [PATCH v3 " Jonathan Kliegman
0 siblings, 1 reply; 8+ messages in thread
From: Jonathan Kliegman @ 2012-08-03 21:52 UTC (permalink / raw)
To: Sylwester Nawrocki; +Cc: linux-samsung-soc, kgene.kim
On Fri, Aug 3, 2012 at 5:27 PM, Sylwester Nawrocki
<sylvester.nawrocki@gmail.com> wrote:
> Hi Jonathan,
>
> On 08/03/2012 10:05 PM, Jonathan Kliegman wrote:
>> The interupt combiner registers need to be saved on suspend and restored
>> on resume or combiner-based intterupts won't work after resume.
>
> intterupts -> interrupts
Thanks, will fix.
>
>> Signed-off-by: Jonathan Kliegman<kliegs@chromium.org>
>> ---
>> arch/arm/mach-exynos/common.c | 74 +++++++++++++++++++++++++++++++++++++----
>> 1 files changed, 67 insertions(+), 7 deletions(-)
>>
>> diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
>> index 4eb39cd..af296e5 100644
>> --- a/arch/arm/mach-exynos/common.c
>> +++ b/arch/arm/mach-exynos/common.c
>> @@ -22,6 +22,7 @@
>> #include<linux/export.h>
>> #include<linux/irqdomain.h>
>> #include<linux/of_address.h>
>> +#include<linux/cpu_pm.h>
>>
>> #include<asm/proc-fns.h>
>> #include<asm/exception.h>
>> @@ -405,10 +406,14 @@ struct combiner_chip_data {
>> unsigned int irq_offset;
>> unsigned int irq_mask;
>> void __iomem *base;
>> +#ifdef CONFIG_CPU_PM
>> + bool saved_on;
>> +#endif
>> };
>>
>> static struct irq_domain *combiner_irq_domain;
>> static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
>> +static unsigned int rt_max_combiner_nr;
>>
>> static inline void __iomem *combiner_base(struct irq_data *data)
>> {
>> @@ -535,6 +540,55 @@ static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq,
>> return 0;
>> }
>>
>> +#ifdef CONFIG_CPU_PM
>> +static void combiner_save(void)
>> +{
>> + int i;
>> +
>> + for (i = 0; i< rt_max_combiner_nr; i++) {
>> + if (combiner_data[i].irq_mask&
>> + __raw_readl(combiner_data[i].base + COMBINER_ENABLE_SET)) {
>> + combiner_data[i].saved_on = true;
>> + } else {
>> + combiner_data[i].saved_on = false;
>> + }
>> + }
>> +}
>> +
>> +static void combiner_restore(void)
>> +{
>> + int i;
>> +
>> + for (i = 0; i< rt_max_combiner_nr; i++) {
>> + if (!combiner_data[i].saved_on)
>> + continue;
>> +
>> + __raw_writel(combiner_data[i].irq_mask,
>> + combiner_data[i].base + COMBINER_ENABLE_SET);
>> + }
>> +}
>> +
>> +
>> +static int combiner_notifier(struct notifier_block *self, unsigned long cmd,
>> + void *v)
>> +{
>> + switch (cmd) {
>> + case CPU_CLUSTER_PM_ENTER:
>> + combiner_save();
>> + break;
>> + case CPU_CLSUTER_PM_EXIT:
>
> Looks like this part of code wasn't compiled or some last minute changes
> introduced this typo ?
I had tested it (compiled and ran) but on a different branch. The
typo must have been introduced when I manually rebased against head.
Thanks for catching this.
>
>> + combiner_restore();
>> + break;
>> + }
>> +
>> + return NOTIFY_OK;
>> +}
>> +
>> +static struct notifier_block combiner_notifier_block = {
>> + .notifier_call = combiner_notifier,
>> +};
>> +#endif
>> +
>> static struct irq_domain_ops combiner_irq_domain_ops = {
>> .xlate = combiner_irq_domain_xlate,
>> .map = combiner_irq_domain_map,
>> @@ -544,20 +598,21 @@ static void __init combiner_init(void __iomem *combiner_base,
>> struct device_node *np)
>> {
>> int i, irq, irq_base;
>> - unsigned int max_nr, nr_irq;
>> + unsigned int nr_irq;
>>
>> if (np) {
>> - if (of_property_read_u32(np, "samsung,combiner-nr",&max_nr)) {
>> + if (of_property_read_u32(np, "samsung,combiner-nr",
>> + &rt_max_combiner_nr)) {
>> pr_warning("%s: number of combiners not specified, "
>> "setting default as %d.\n",
>> __func__, EXYNOS4_MAX_COMBINER_NR);
>> - max_nr = EXYNOS4_MAX_COMBINER_NR;
>> + rt_max_combiner_nr = EXYNOS4_MAX_COMBINER_NR;
>> }
>> } else {
>> - max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR :
>> - EXYNOS4_MAX_COMBINER_NR;
>> + rt_max_combiner_nr = soc_is_exynos5250() ?
>> + EXYNOS5_MAX_COMBINER_NR : EXYNOS4_MAX_COMBINER_NR;
>> }
>> - nr_irq = max_nr * MAX_IRQ_IN_COMBINER;
>> + nr_irq = rt_max_combiner_nr * MAX_IRQ_IN_COMBINER;
>>
>> irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0);
>> if (IS_ERR_VALUE(irq_base)) {
>> @@ -572,7 +627,7 @@ static void __init combiner_init(void __iomem *combiner_base,
>> return;
>> }
>>
>> - for (i = 0; i< max_nr; i++) {
>> + for (i = 0; i< rt_max_combiner_nr; i++) {
>> combiner_init_one(i, combiner_base + (i>> 2) * 0x10);
>> irq = IRQ_SPI(i);
>> #ifdef CONFIG_OF
>> @@ -581,6 +636,11 @@ static void __init combiner_init(void __iomem *combiner_base,
>> #endif
>> combiner_cascade_irq(i, irq);
>> }
>> +
>> +#ifdef CONFIG_PM
>
> Shouldn't this also be CONFIG_CPU_PM ? Declaration of combiner_notifier_block
> is compiled in only when CONFIG_CPU_PM is defined.
Correct, in fixing the previous two I missed this one. Will fix and
update patch.
Thanks for catching these.
>
>> + /* Setup suspend/resume combiner saving */
>> + cpu_pm_register_notifier(&combiner_notifier_block);
>> +#endif
>> }
>>
>> #ifdef CONFIG_OF
>
> Thanks,
> Sylwester
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 1/3] ARM: exynos: Save combiner registers on suspend
2012-08-03 21:52 ` Jonathan Kliegman
@ 2012-08-03 22:08 ` Jonathan Kliegman
0 siblings, 0 replies; 8+ messages in thread
From: Jonathan Kliegman @ 2012-08-03 22:08 UTC (permalink / raw)
To: linux-samsung-soc; +Cc: kgene.kim, sylvester.nawrocki, Jonathan Kliegman
The interrupt combiner registers need to be saved on suspend and restored
on resume or combiner-based interrupts won't work after resume.
Signed-off-by: Jonathan Kliegman <kliegs@chromium.org>
---
arch/arm/mach-exynos/common.c | 74 +++++++++++++++++++++++++++++++++++++----
1 files changed, 67 insertions(+), 7 deletions(-)
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 4eb39cd..b51b9fb 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -22,6 +22,7 @@
#include <linux/export.h>
#include <linux/irqdomain.h>
#include <linux/of_address.h>
+#include <linux/cpu_pm.h>
#include <asm/proc-fns.h>
#include <asm/exception.h>
@@ -405,10 +406,14 @@ struct combiner_chip_data {
unsigned int irq_offset;
unsigned int irq_mask;
void __iomem *base;
+#ifdef CONFIG_CPU_PM
+ bool saved_on;
+#endif
};
static struct irq_domain *combiner_irq_domain;
static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
+static unsigned int rt_max_combiner_nr;
static inline void __iomem *combiner_base(struct irq_data *data)
{
@@ -535,6 +540,55 @@ static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq,
return 0;
}
+#ifdef CONFIG_CPU_PM
+static void combiner_save(void)
+{
+ int i;
+
+ for (i = 0; i < rt_max_combiner_nr; i++) {
+ if (combiner_data[i].irq_mask &
+ __raw_readl(combiner_data[i].base + COMBINER_ENABLE_SET)) {
+ combiner_data[i].saved_on = true;
+ } else {
+ combiner_data[i].saved_on = false;
+ }
+ }
+}
+
+static void combiner_restore(void)
+{
+ int i;
+
+ for (i = 0; i < rt_max_combiner_nr; i++) {
+ if (!combiner_data[i].saved_on)
+ continue;
+
+ __raw_writel(combiner_data[i].irq_mask,
+ combiner_data[i].base + COMBINER_ENABLE_SET);
+ }
+}
+
+
+static int combiner_notifier(struct notifier_block *self, unsigned long cmd,
+ void *v)
+{
+ switch (cmd) {
+ case CPU_CLUSTER_PM_ENTER:
+ combiner_save();
+ break;
+ case CPU_CLUSTER_PM_EXIT:
+ combiner_restore();
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block combiner_notifier_block = {
+ .notifier_call = combiner_notifier,
+};
+#endif
+
static struct irq_domain_ops combiner_irq_domain_ops = {
.xlate = combiner_irq_domain_xlate,
.map = combiner_irq_domain_map,
@@ -544,20 +598,21 @@ static void __init combiner_init(void __iomem *combiner_base,
struct device_node *np)
{
int i, irq, irq_base;
- unsigned int max_nr, nr_irq;
+ unsigned int nr_irq;
if (np) {
- if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) {
+ if (of_property_read_u32(np, "samsung,combiner-nr",
+ &rt_max_combiner_nr)) {
pr_warning("%s: number of combiners not specified, "
"setting default as %d.\n",
__func__, EXYNOS4_MAX_COMBINER_NR);
- max_nr = EXYNOS4_MAX_COMBINER_NR;
+ rt_max_combiner_nr = EXYNOS4_MAX_COMBINER_NR;
}
} else {
- max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR :
- EXYNOS4_MAX_COMBINER_NR;
+ rt_max_combiner_nr = soc_is_exynos5250() ?
+ EXYNOS5_MAX_COMBINER_NR : EXYNOS4_MAX_COMBINER_NR;
}
- nr_irq = max_nr * MAX_IRQ_IN_COMBINER;
+ nr_irq = rt_max_combiner_nr * MAX_IRQ_IN_COMBINER;
irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0);
if (IS_ERR_VALUE(irq_base)) {
@@ -572,7 +627,7 @@ static void __init combiner_init(void __iomem *combiner_base,
return;
}
- for (i = 0; i < max_nr; i++) {
+ for (i = 0; i < rt_max_combiner_nr; i++) {
combiner_init_one(i, combiner_base + (i >> 2) * 0x10);
irq = IRQ_SPI(i);
#ifdef CONFIG_OF
@@ -581,6 +636,11 @@ static void __init combiner_init(void __iomem *combiner_base,
#endif
combiner_cascade_irq(i, irq);
}
+
+#ifdef CONFIG_CPU_PM
+ /* Setup suspend/resume combiner saving */
+ cpu_pm_register_notifier(&combiner_notifier_block);
+#endif
}
#ifdef CONFIG_OF
--
1.7.7.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2012-08-03 22:09 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-20 18:14 [PATCH 1/3] ARM: exynos: Save combiner registers on suspend Jonathan Kliegman
2012-07-20 18:14 ` [PATCH 2/3] ARM: exynos: change local variable combiner_data to use unique name Jonathan Kliegman
2012-07-20 18:14 ` [PATCH 3/3] ARM: exynos: Size combiner_data dynamically after dt parsing Jonathan Kliegman
2012-08-01 11:38 ` [PATCH 1/3] ARM: exynos: Save combiner registers on suspend Kukjin Kim
2012-08-03 20:05 ` [PATCH v2 " Jonathan Kliegman
2012-08-03 21:27 ` Sylwester Nawrocki
2012-08-03 21:52 ` Jonathan Kliegman
2012-08-03 22:08 ` [PATCH v3 " Jonathan Kliegman
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.