aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-shmobile
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2012-01-08 19:56:37 -0500
committerPaul Mundt <lethal@linux-sh.org>2012-01-08 19:56:37 -0500
commit04cf399640b7acfa9abe2eb7900cd934db8af697 (patch)
treef9a055f2f0170550f5f0b0507b06ffce8d98945d /arch/arm/mach-shmobile
parent17f0056e6a2f3d1818801705f5e12b71217bf4ef (diff)
parenta0e86bd4252519321b0d102dc4ed90557aa7bee9 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux into rmobile-latest
Conflicts: arch/arm/mach-shmobile/Makefile Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/arm/mach-shmobile')
-rw-r--r--arch/arm/mach-shmobile/Makefile1
-rw-r--r--arch/arm/mach-shmobile/board-ag5evm.c4
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c2
-rw-r--r--arch/arm/mach-shmobile/board-g3evm.c2
-rw-r--r--arch/arm/mach-shmobile/board-g4evm.c2
-rw-r--r--arch/arm/mach-shmobile/board-kota2.c2
-rw-r--r--arch/arm/mach-shmobile/board-mackerel.c2
-rw-r--r--arch/arm/mach-shmobile/entry-gic.S18
-rw-r--r--arch/arm/mach-shmobile/include/mach/common.h5
-rw-r--r--arch/arm/mach-shmobile/include/mach/entry-macro.S9
-rw-r--r--arch/arm/mach-shmobile/include/mach/gpio.h2
-rw-r--r--arch/arm/mach-shmobile/include/mach/sh7372.h6
-rw-r--r--arch/arm/mach-shmobile/include/mach/system.h2
-rw-r--r--arch/arm/mach-shmobile/include/mach/vmalloc.h7
-rw-r--r--arch/arm/mach-shmobile/intc-sh7372.c50
-rw-r--r--arch/arm/mach-shmobile/pm-sh7372.c215
-rw-r--r--arch/arm/mach-shmobile/setup-sh7372.c6
-rw-r--r--arch/arm/mach-shmobile/sleep-sh7372.S21
18 files changed, 240 insertions, 116 deletions
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index 5ee604dcaf57..83e35f254bff 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -30,7 +30,6 @@ pfc-$(CONFIG_ARCH_R8A7740) += pfc-r8a7740.o
30obj-$(CONFIG_ARCH_SH7367) += entry-intc.o 30obj-$(CONFIG_ARCH_SH7367) += entry-intc.o
31obj-$(CONFIG_ARCH_SH7377) += entry-intc.o 31obj-$(CONFIG_ARCH_SH7377) += entry-intc.o
32obj-$(CONFIG_ARCH_SH7372) += entry-intc.o 32obj-$(CONFIG_ARCH_SH7372) += entry-intc.o
33obj-$(CONFIG_ARCH_SH73A0) += entry-gic.o
34obj-$(CONFIG_ARCH_R8A7740) += entry-intc.o 33obj-$(CONFIG_ARCH_R8A7740) += entry-intc.o
35 34
36# PM objects 35# PM objects
diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c
index 7119b87cbfa0..a4e6ca04e319 100644
--- a/arch/arm/mach-shmobile/board-ag5evm.c
+++ b/arch/arm/mach-shmobile/board-ag5evm.c
@@ -466,8 +466,6 @@ static struct map_desc ag5evm_io_desc[] __initdata = {
466static void __init ag5evm_map_io(void) 466static void __init ag5evm_map_io(void)
467{ 467{
468 iotable_init(ag5evm_io_desc, ARRAY_SIZE(ag5evm_io_desc)); 468 iotable_init(ag5evm_io_desc, ARRAY_SIZE(ag5evm_io_desc));
469 /* DMA memory at 0xf6000000 - 0xffdfffff */
470 init_consistent_dma_size(158 << 20);
471 469
472 /* setup early devices and console here as well */ 470 /* setup early devices and console here as well */
473 sh73a0_add_early_devices(); 471 sh73a0_add_early_devices();
@@ -609,7 +607,7 @@ MACHINE_START(AG5EVM, "ag5evm")
609 .map_io = ag5evm_map_io, 607 .map_io = ag5evm_map_io,
610 .nr_irqs = NR_IRQS_LEGACY, 608 .nr_irqs = NR_IRQS_LEGACY,
611 .init_irq = sh73a0_init_irq, 609 .init_irq = sh73a0_init_irq,
612 .handle_irq = shmobile_handle_irq_gic, 610 .handle_irq = gic_handle_irq,
613 .init_machine = ag5evm_init, 611 .init_machine = ag5evm_init,
614 .timer = &ag5evm_timer, 612 .timer = &ag5evm_timer,
615MACHINE_END 613MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 4c865ece9ac4..6a6f9f7568c2 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -1172,8 +1172,6 @@ static struct map_desc ap4evb_io_desc[] __initdata = {
1172static void __init ap4evb_map_io(void) 1172static void __init ap4evb_map_io(void)
1173{ 1173{
1174 iotable_init(ap4evb_io_desc, ARRAY_SIZE(ap4evb_io_desc)); 1174 iotable_init(ap4evb_io_desc, ARRAY_SIZE(ap4evb_io_desc));
1175 /* DMA memory at 0xf6000000 - 0xffdfffff */
1176 init_consistent_dma_size(158 << 20);
1177 1175
1178 /* setup early devices and console here as well */ 1176 /* setup early devices and console here as well */
1179 sh7372_add_early_devices(); 1177 sh7372_add_early_devices();
diff --git a/arch/arm/mach-shmobile/board-g3evm.c b/arch/arm/mach-shmobile/board-g3evm.c
index 8b620bf06221..72d557281b1f 100644
--- a/arch/arm/mach-shmobile/board-g3evm.c
+++ b/arch/arm/mach-shmobile/board-g3evm.c
@@ -261,8 +261,6 @@ static struct map_desc g3evm_io_desc[] __initdata = {
261static void __init g3evm_map_io(void) 261static void __init g3evm_map_io(void)
262{ 262{
263 iotable_init(g3evm_io_desc, ARRAY_SIZE(g3evm_io_desc)); 263 iotable_init(g3evm_io_desc, ARRAY_SIZE(g3evm_io_desc));
264 /* DMA memory at 0xf6000000 - 0xffdfffff */
265 init_consistent_dma_size(158 << 20);
266 264
267 /* setup early devices and console here as well */ 265 /* setup early devices and console here as well */
268 sh7367_add_early_devices(); 266 sh7367_add_early_devices();
diff --git a/arch/arm/mach-shmobile/board-g4evm.c b/arch/arm/mach-shmobile/board-g4evm.c
index 7719ddc5f591..2220b885cff5 100644
--- a/arch/arm/mach-shmobile/board-g4evm.c
+++ b/arch/arm/mach-shmobile/board-g4evm.c
@@ -275,8 +275,6 @@ static struct map_desc g4evm_io_desc[] __initdata = {
275static void __init g4evm_map_io(void) 275static void __init g4evm_map_io(void)
276{ 276{
277 iotable_init(g4evm_io_desc, ARRAY_SIZE(g4evm_io_desc)); 277 iotable_init(g4evm_io_desc, ARRAY_SIZE(g4evm_io_desc));
278 /* DMA memory at 0xf6000000 - 0xffdfffff */
279 init_consistent_dma_size(158 << 20);
280 278
281 /* setup early devices and console here as well */ 279 /* setup early devices and console here as well */
282 sh7377_add_early_devices(); 280 sh7377_add_early_devices();
diff --git a/arch/arm/mach-shmobile/board-kota2.c b/arch/arm/mach-shmobile/board-kota2.c
index f44150b5ae46..857ceeec1bb0 100644
--- a/arch/arm/mach-shmobile/board-kota2.c
+++ b/arch/arm/mach-shmobile/board-kota2.c
@@ -551,7 +551,7 @@ MACHINE_START(KOTA2, "kota2")
551 .map_io = kota2_map_io, 551 .map_io = kota2_map_io,
552 .nr_irqs = NR_IRQS_LEGACY, 552 .nr_irqs = NR_IRQS_LEGACY,
553 .init_irq = sh73a0_init_irq, 553 .init_irq = sh73a0_init_irq,
554 .handle_irq = shmobile_handle_irq_gic, 554 .handle_irq = gic_handle_irq,
555 .init_machine = kota2_init, 555 .init_machine = kota2_init,
556 .timer = &kota2_timer, 556 .timer = &kota2_timer,
557MACHINE_END 557MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 9c5e598e0e3d..ed5256687397 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -1390,8 +1390,6 @@ static struct map_desc mackerel_io_desc[] __initdata = {
1390static void __init mackerel_map_io(void) 1390static void __init mackerel_map_io(void)
1391{ 1391{
1392 iotable_init(mackerel_io_desc, ARRAY_SIZE(mackerel_io_desc)); 1392 iotable_init(mackerel_io_desc, ARRAY_SIZE(mackerel_io_desc));
1393 /* DMA memory at 0xf6000000 - 0xffdfffff */
1394 init_consistent_dma_size(158 << 20);
1395 1393
1396 /* setup early devices and console here as well */ 1394 /* setup early devices and console here as well */
1397 sh7372_add_early_devices(); 1395 sh7372_add_early_devices();
diff --git a/arch/arm/mach-shmobile/entry-gic.S b/arch/arm/mach-shmobile/entry-gic.S
deleted file mode 100644
index e20239b08c83..000000000000
--- a/arch/arm/mach-shmobile/entry-gic.S
+++ /dev/null
@@ -1,18 +0,0 @@
1/*
2 * ARM Interrupt demux handler using GIC
3 *
4 * Copyright (C) 2010 Magnus Damm
5 * Copyright (C) 2011 Paul Mundt
6 * Copyright (C) 2010 - 2011 Renesas Solutions Corp.
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <asm/assembler.h>
14#include <asm/entry-macro-multi.S>
15#include <asm/hardware/gic.h>
16#include <asm/hardware/entry-macro-gic.S>
17
18 arch_irq_handler shmobile_handle_irq_gic
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index 5055a00a83d4..3a9250bb6d05 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -7,7 +7,6 @@ extern void shmobile_secondary_vector(void);
7struct clk; 7struct clk;
8extern int clk_init(void); 8extern int clk_init(void);
9extern void shmobile_handle_irq_intc(struct pt_regs *); 9extern void shmobile_handle_irq_intc(struct pt_regs *);
10extern void shmobile_handle_irq_gic(struct pt_regs *);
11extern struct platform_suspend_ops shmobile_suspend_ops; 10extern struct platform_suspend_ops shmobile_suspend_ops;
12struct cpuidle_driver; 11struct cpuidle_driver;
13extern void (*shmobile_cpuidle_modes[])(void); 12extern void (*shmobile_cpuidle_modes[])(void);
@@ -35,8 +34,8 @@ extern void sh7372_add_standard_devices(void);
35extern void sh7372_clock_init(void); 34extern void sh7372_clock_init(void);
36extern void sh7372_pinmux_init(void); 35extern void sh7372_pinmux_init(void);
37extern void sh7372_pm_init(void); 36extern void sh7372_pm_init(void);
38extern void sh7372_resume_core_standby_a3sm(void); 37extern void sh7372_resume_core_standby_sysc(void);
39extern int sh7372_do_idle_a3sm(unsigned long unused); 38extern int sh7372_do_idle_sysc(unsigned long sleep_mode);
40extern struct clk sh7372_extal1_clk; 39extern struct clk sh7372_extal1_clk;
41extern struct clk sh7372_extal2_clk; 40extern struct clk sh7372_extal2_clk;
42 41
diff --git a/arch/arm/mach-shmobile/include/mach/entry-macro.S b/arch/arm/mach-shmobile/include/mach/entry-macro.S
index 8d4a416d4285..2a57b2964ee9 100644
--- a/arch/arm/mach-shmobile/include/mach/entry-macro.S
+++ b/arch/arm/mach-shmobile/include/mach/entry-macro.S
@@ -18,14 +18,5 @@
18 .macro disable_fiq 18 .macro disable_fiq
19 .endm 19 .endm
20 20
21 .macro get_irqnr_preamble, base, tmp
22 .endm
23
24 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
25 .endm
26
27 .macro test_for_ipi, irqnr, irqstat, base, tmp
28 .endm
29
30 .macro arch_ret_to_user, tmp1, tmp2 21 .macro arch_ret_to_user, tmp1, tmp2
31 .endm 22 .endm
diff --git a/arch/arm/mach-shmobile/include/mach/gpio.h b/arch/arm/mach-shmobile/include/mach/gpio.h
index 7bf0890e16ba..de795b42232a 100644
--- a/arch/arm/mach-shmobile/include/mach/gpio.h
+++ b/arch/arm/mach-shmobile/include/mach/gpio.h
@@ -12,8 +12,6 @@
12 12
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/errno.h> 14#include <linux/errno.h>
15
16#define ARCH_NR_GPIOS 1024
17#include <linux/sh_pfc.h> 15#include <linux/sh_pfc.h>
18 16
19#ifdef CONFIG_GPIOLIB 17#ifdef CONFIG_GPIOLIB
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h
index 84532f9629b2..8254ab86f6cd 100644
--- a/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ b/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -480,11 +480,10 @@ struct platform_device;
480struct sh7372_pm_domain { 480struct sh7372_pm_domain {
481 struct generic_pm_domain genpd; 481 struct generic_pm_domain genpd;
482 struct dev_power_governor *gov; 482 struct dev_power_governor *gov;
483 void (*suspend)(void); 483 int (*suspend)(void);
484 void (*resume)(void); 484 void (*resume)(void);
485 unsigned int bit_shift; 485 unsigned int bit_shift;
486 bool no_debug; 486 bool no_debug;
487 bool stay_on;
488}; 487};
489 488
490static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d) 489static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d)
@@ -499,6 +498,7 @@ extern struct sh7372_pm_domain sh7372_d4;
499extern struct sh7372_pm_domain sh7372_a4r; 498extern struct sh7372_pm_domain sh7372_a4r;
500extern struct sh7372_pm_domain sh7372_a3rv; 499extern struct sh7372_pm_domain sh7372_a3rv;
501extern struct sh7372_pm_domain sh7372_a3ri; 500extern struct sh7372_pm_domain sh7372_a3ri;
501extern struct sh7372_pm_domain sh7372_a4s;
502extern struct sh7372_pm_domain sh7372_a3sp; 502extern struct sh7372_pm_domain sh7372_a3sp;
503extern struct sh7372_pm_domain sh7372_a3sg; 503extern struct sh7372_pm_domain sh7372_a3sg;
504 504
@@ -515,5 +515,7 @@ extern void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd,
515 515
516extern void sh7372_intcs_suspend(void); 516extern void sh7372_intcs_suspend(void);
517extern void sh7372_intcs_resume(void); 517extern void sh7372_intcs_resume(void);
518extern void sh7372_intca_suspend(void);
519extern void sh7372_intca_resume(void);
518 520
519#endif /* __ASM_SH7372_H__ */ 521#endif /* __ASM_SH7372_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/system.h b/arch/arm/mach-shmobile/include/mach/system.h
index 76a687eeaa22..956ac18ddbf9 100644
--- a/arch/arm/mach-shmobile/include/mach/system.h
+++ b/arch/arm/mach-shmobile/include/mach/system.h
@@ -8,7 +8,7 @@ static inline void arch_idle(void)
8 8
9static inline void arch_reset(char mode, const char *cmd) 9static inline void arch_reset(char mode, const char *cmd)
10{ 10{
11 cpu_reset(0); 11 soft_restart(0);
12} 12}
13 13
14#endif 14#endif
diff --git a/arch/arm/mach-shmobile/include/mach/vmalloc.h b/arch/arm/mach-shmobile/include/mach/vmalloc.h
deleted file mode 100644
index 2b8fd8b942fe..000000000000
--- a/arch/arm/mach-shmobile/include/mach/vmalloc.h
+++ /dev/null
@@ -1,7 +0,0 @@
1#ifndef __ASM_MACH_VMALLOC_H
2#define __ASM_MACH_VMALLOC_H
3
4/* Vmalloc at ... - 0xe5ffffff */
5#define VMALLOC_END 0xe6000000UL
6
7#endif /* __ASM_MACH_VMALLOC_H */
diff --git a/arch/arm/mach-shmobile/intc-sh7372.c b/arch/arm/mach-shmobile/intc-sh7372.c
index 2d8856df80e2..89afcaba99a1 100644
--- a/arch/arm/mach-shmobile/intc-sh7372.c
+++ b/arch/arm/mach-shmobile/intc-sh7372.c
@@ -535,6 +535,7 @@ static struct resource intcs_resources[] __initdata = {
535static struct intc_desc intcs_desc __initdata = { 535static struct intc_desc intcs_desc __initdata = {
536 .name = "sh7372-intcs", 536 .name = "sh7372-intcs",
537 .force_enable = ENABLED_INTCS, 537 .force_enable = ENABLED_INTCS,
538 .skip_syscore_suspend = true,
538 .resource = intcs_resources, 539 .resource = intcs_resources,
539 .num_resources = ARRAY_SIZE(intcs_resources), 540 .num_resources = ARRAY_SIZE(intcs_resources),
540 .hw = INTC_HW_DESC(intcs_vectors, intcs_groups, intcs_mask_registers, 541 .hw = INTC_HW_DESC(intcs_vectors, intcs_groups, intcs_mask_registers,
@@ -611,3 +612,52 @@ void sh7372_intcs_resume(void)
611 for (k = 0x80; k <= 0x9c; k += 4) 612 for (k = 0x80; k <= 0x9c; k += 4)
612 __raw_writeb(ffd5[k], intcs_ffd5 + k); 613 __raw_writeb(ffd5[k], intcs_ffd5 + k);
613} 614}
615
616static unsigned short e694[0x200];
617static unsigned short e695[0x200];
618
619void sh7372_intca_suspend(void)
620{
621 int k;
622
623 for (k = 0x00; k <= 0x38; k += 4)
624 e694[k] = __raw_readw(0xe6940000 + k);
625
626 for (k = 0x80; k <= 0xb4; k += 4)
627 e694[k] = __raw_readb(0xe6940000 + k);
628
629 for (k = 0x180; k <= 0x1b4; k += 4)
630 e694[k] = __raw_readb(0xe6940000 + k);
631
632 for (k = 0x00; k <= 0x50; k += 4)
633 e695[k] = __raw_readw(0xe6950000 + k);
634
635 for (k = 0x80; k <= 0xa8; k += 4)
636 e695[k] = __raw_readb(0xe6950000 + k);
637
638 for (k = 0x180; k <= 0x1a8; k += 4)
639 e695[k] = __raw_readb(0xe6950000 + k);
640}
641
642void sh7372_intca_resume(void)
643{
644 int k;
645
646 for (k = 0x00; k <= 0x38; k += 4)
647 __raw_writew(e694[k], 0xe6940000 + k);
648
649 for (k = 0x80; k <= 0xb4; k += 4)
650 __raw_writeb(e694[k], 0xe6940000 + k);
651
652 for (k = 0x180; k <= 0x1b4; k += 4)
653 __raw_writeb(e694[k], 0xe6940000 + k);
654
655 for (k = 0x00; k <= 0x50; k += 4)
656 __raw_writew(e695[k], 0xe6950000 + k);
657
658 for (k = 0x80; k <= 0xa8; k += 4)
659 __raw_writeb(e695[k], 0xe6950000 + k);
660
661 for (k = 0x180; k <= 0x1a8; k += 4)
662 __raw_writeb(e695[k], 0xe6950000 + k);
663}
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c
index 0a5b22942fd3..77b8fc12fc2f 100644
--- a/arch/arm/mach-shmobile/pm-sh7372.c
+++ b/arch/arm/mach-shmobile/pm-sh7372.c
@@ -20,6 +20,7 @@
20#include <linux/delay.h> 20#include <linux/delay.h>
21#include <linux/irq.h> 21#include <linux/irq.h>
22#include <linux/bitrev.h> 22#include <linux/bitrev.h>
23#include <linux/console.h>
23#include <asm/system.h> 24#include <asm/system.h>
24#include <asm/io.h> 25#include <asm/io.h>
25#include <asm/tlbflush.h> 26#include <asm/tlbflush.h>
@@ -81,11 +82,12 @@ static int pd_power_down(struct generic_pm_domain *genpd)
81 struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd); 82 struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
82 unsigned int mask = 1 << sh7372_pd->bit_shift; 83 unsigned int mask = 1 << sh7372_pd->bit_shift;
83 84
84 if (sh7372_pd->suspend) 85 if (sh7372_pd->suspend) {
85 sh7372_pd->suspend(); 86 int ret = sh7372_pd->suspend();
86 87
87 if (sh7372_pd->stay_on) 88 if (ret)
88 return 0; 89 return ret;
90 }
89 91
90 if (__raw_readl(PSTR) & mask) { 92 if (__raw_readl(PSTR) & mask) {
91 unsigned int retry_count; 93 unsigned int retry_count;
@@ -100,22 +102,18 @@ static int pd_power_down(struct generic_pm_domain *genpd)
100 } 102 }
101 103
102 if (!sh7372_pd->no_debug) 104 if (!sh7372_pd->no_debug)
103 pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n", 105 pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n",
104 mask, __raw_readl(PSTR)); 106 genpd->name, mask, __raw_readl(PSTR));
105 107
106 return 0; 108 return 0;
107} 109}
108 110
109static int pd_power_up(struct generic_pm_domain *genpd) 111static int __pd_power_up(struct sh7372_pm_domain *sh7372_pd, bool do_resume)
110{ 112{
111 struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
112 unsigned int mask = 1 << sh7372_pd->bit_shift; 113 unsigned int mask = 1 << sh7372_pd->bit_shift;
113 unsigned int retry_count; 114 unsigned int retry_count;
114 int ret = 0; 115 int ret = 0;
115 116
116 if (sh7372_pd->stay_on)
117 goto out;
118
119 if (__raw_readl(PSTR) & mask) 117 if (__raw_readl(PSTR) & mask)
120 goto out; 118 goto out;
121 119
@@ -123,58 +121,88 @@ static int pd_power_up(struct generic_pm_domain *genpd)
123 121
124 for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) { 122 for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
125 if (!(__raw_readl(SWUCR) & mask)) 123 if (!(__raw_readl(SWUCR) & mask))
126 goto out; 124 break;
127 if (retry_count > PSTR_RETRIES) 125 if (retry_count > PSTR_RETRIES)
128 udelay(PSTR_DELAY_US); 126 udelay(PSTR_DELAY_US);
129 else 127 else
130 cpu_relax(); 128 cpu_relax();
131 } 129 }
132 if (__raw_readl(SWUCR) & mask) 130 if (!retry_count)
133 ret = -EIO; 131 ret = -EIO;
134 132
135 if (!sh7372_pd->no_debug) 133 if (!sh7372_pd->no_debug)
136 pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n", 134 pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
137 mask, __raw_readl(PSTR)); 135 sh7372_pd->genpd.name, mask, __raw_readl(PSTR));
138 136
139 out: 137 out:
140 if (ret == 0 && sh7372_pd->resume) 138 if (ret == 0 && sh7372_pd->resume && do_resume)
141 sh7372_pd->resume(); 139 sh7372_pd->resume();
142 140
143 return ret; 141 return ret;
144} 142}
145 143
146static void sh7372_a4r_suspend(void) 144static int pd_power_up(struct generic_pm_domain *genpd)
145{
146 return __pd_power_up(to_sh7372_pd(genpd), true);
147}
148
149static int sh7372_a4r_suspend(void)
147{ 150{
148 sh7372_intcs_suspend(); 151 sh7372_intcs_suspend();
149 __raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */ 152 __raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */
153 return 0;
150} 154}
151 155
152static bool pd_active_wakeup(struct device *dev) 156static bool pd_active_wakeup(struct device *dev)
153{ 157{
154 return true; 158 bool (*active_wakeup)(struct device *dev);
159
160 active_wakeup = dev_gpd_data(dev)->ops.active_wakeup;
161 return active_wakeup ? active_wakeup(dev) : true;
155} 162}
156 163
157static bool sh7372_power_down_forbidden(struct dev_pm_domain *domain) 164static int sh7372_stop_dev(struct device *dev)
158{ 165{
159 return false; 166 int (*stop)(struct device *dev);
167
168 stop = dev_gpd_data(dev)->ops.stop;
169 if (stop) {
170 int ret = stop(dev);
171 if (ret)
172 return ret;
173 }
174 return pm_clk_suspend(dev);
160} 175}
161 176
162struct dev_power_governor sh7372_always_on_gov = { 177static int sh7372_start_dev(struct device *dev)
163 .power_down_ok = sh7372_power_down_forbidden, 178{
164}; 179 int (*start)(struct device *dev);
180 int ret;
181
182 ret = pm_clk_resume(dev);
183 if (ret)
184 return ret;
185
186 start = dev_gpd_data(dev)->ops.start;
187 if (start)
188 ret = start(dev);
189
190 return ret;
191}
165 192
166void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd) 193void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd)
167{ 194{
168 struct generic_pm_domain *genpd = &sh7372_pd->genpd; 195 struct generic_pm_domain *genpd = &sh7372_pd->genpd;
196 struct dev_power_governor *gov = sh7372_pd->gov;
169 197
170 pm_genpd_init(genpd, sh7372_pd->gov, false); 198 pm_genpd_init(genpd, gov ? : &simple_qos_governor, false);
171 genpd->stop_device = pm_clk_suspend; 199 genpd->dev_ops.stop = sh7372_stop_dev;
172 genpd->start_device = pm_clk_resume; 200 genpd->dev_ops.start = sh7372_start_dev;
201 genpd->dev_ops.active_wakeup = pd_active_wakeup;
173 genpd->dev_irq_safe = true; 202 genpd->dev_irq_safe = true;
174 genpd->active_wakeup = pd_active_wakeup;
175 genpd->power_off = pd_power_down; 203 genpd->power_off = pd_power_down;
176 genpd->power_on = pd_power_up; 204 genpd->power_on = pd_power_up;
177 genpd->power_on(&sh7372_pd->genpd); 205 __pd_power_up(sh7372_pd, false);
178} 206}
179 207
180void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd, 208void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd,
@@ -194,44 +222,81 @@ void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd,
194} 222}
195 223
196struct sh7372_pm_domain sh7372_a4lc = { 224struct sh7372_pm_domain sh7372_a4lc = {
225 .genpd.name = "A4LC",
197 .bit_shift = 1, 226 .bit_shift = 1,
198}; 227};
199 228
200struct sh7372_pm_domain sh7372_a4mp = { 229struct sh7372_pm_domain sh7372_a4mp = {
230 .genpd.name = "A4MP",
201 .bit_shift = 2, 231 .bit_shift = 2,
202}; 232};
203 233
204struct sh7372_pm_domain sh7372_d4 = { 234struct sh7372_pm_domain sh7372_d4 = {
235 .genpd.name = "D4",
205 .bit_shift = 3, 236 .bit_shift = 3,
206}; 237};
207 238
208struct sh7372_pm_domain sh7372_a4r = { 239struct sh7372_pm_domain sh7372_a4r = {
240 .genpd.name = "A4R",
209 .bit_shift = 5, 241 .bit_shift = 5,
210 .gov = &sh7372_always_on_gov,
211 .suspend = sh7372_a4r_suspend, 242 .suspend = sh7372_a4r_suspend,
212 .resume = sh7372_intcs_resume, 243 .resume = sh7372_intcs_resume,
213 .stay_on = true,
214}; 244};
215 245
216struct sh7372_pm_domain sh7372_a3rv = { 246struct sh7372_pm_domain sh7372_a3rv = {
247 .genpd.name = "A3RV",
217 .bit_shift = 6, 248 .bit_shift = 6,
218}; 249};
219 250
220struct sh7372_pm_domain sh7372_a3ri = { 251struct sh7372_pm_domain sh7372_a3ri = {
252 .genpd.name = "A3RI",
221 .bit_shift = 8, 253 .bit_shift = 8,
222}; 254};
223 255
256static int sh7372_a4s_suspend(void)
257{
258 /*
259 * The A4S domain contains the CPU core and therefore it should
260 * only be turned off if the CPU is in use.
261 */
262 return -EBUSY;
263}
264
265struct sh7372_pm_domain sh7372_a4s = {
266 .genpd.name = "A4S",
267 .bit_shift = 10,
268 .gov = &pm_domain_always_on_gov,
269 .no_debug = true,
270 .suspend = sh7372_a4s_suspend,
271};
272
273static int sh7372_a3sp_suspend(void)
274{
275 /*
276 * Serial consoles make use of SCIF hardware located in A3SP,
277 * keep such power domain on if "no_console_suspend" is set.
278 */
279 return console_suspend_enabled ? -EBUSY : 0;
280}
281
224struct sh7372_pm_domain sh7372_a3sp = { 282struct sh7372_pm_domain sh7372_a3sp = {
283 .genpd.name = "A3SP",
225 .bit_shift = 11, 284 .bit_shift = 11,
226 .gov = &sh7372_always_on_gov, 285 .gov = &pm_domain_always_on_gov,
227 .no_debug = true, 286 .no_debug = true,
287 .suspend = sh7372_a3sp_suspend,
228}; 288};
229 289
230struct sh7372_pm_domain sh7372_a3sg = { 290struct sh7372_pm_domain sh7372_a3sg = {
291 .genpd.name = "A3SG",
231 .bit_shift = 13, 292 .bit_shift = 13,
232}; 293};
233 294
234#endif /* CONFIG_PM */ 295#else /* !CONFIG_PM */
296
297static inline void sh7372_a3sp_init(void) {}
298
299#endif /* !CONFIG_PM */
235 300
236#if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE) 301#if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE)
237static int sh7372_do_idle_core_standby(unsigned long unused) 302static int sh7372_do_idle_core_standby(unsigned long unused)
@@ -240,11 +305,16 @@ static int sh7372_do_idle_core_standby(unsigned long unused)
240 return 0; 305 return 0;
241} 306}
242 307
243static void sh7372_enter_core_standby(void) 308static void sh7372_set_reset_vector(unsigned long address)
244{ 309{
245 /* set reset vector, translate 4k */ 310 /* set reset vector, translate 4k */
246 __raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR); 311 __raw_writel(address, SBAR);
247 __raw_writel(0, APARMBAREA); 312 __raw_writel(0, APARMBAREA);
313}
314
315static void sh7372_enter_core_standby(void)
316{
317 sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc));
248 318
249 /* enter sleep mode with SYSTBCR to 0x10 */ 319 /* enter sleep mode with SYSTBCR to 0x10 */
250 __raw_writel(0x10, SYSTBCR); 320 __raw_writel(0x10, SYSTBCR);
@@ -257,27 +327,22 @@ static void sh7372_enter_core_standby(void)
257#endif 327#endif
258 328
259#ifdef CONFIG_SUSPEND 329#ifdef CONFIG_SUSPEND
260static void sh7372_enter_a3sm_common(int pllc0_on) 330static void sh7372_enter_sysc(int pllc0_on, unsigned long sleep_mode)
261{ 331{
262 /* set reset vector, translate 4k */
263 __raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR);
264 __raw_writel(0, APARMBAREA);
265
266 if (pllc0_on) 332 if (pllc0_on)
267 __raw_writel(0, PLLC01STPCR); 333 __raw_writel(0, PLLC01STPCR);
268 else 334 else
269 __raw_writel(1 << 28, PLLC01STPCR); 335 __raw_writel(1 << 28, PLLC01STPCR);
270 336
271 __raw_writel(0, PDNSEL); /* power-down A3SM only, not A4S */
272 __raw_readl(WUPSFAC); /* read wakeup int. factor before sleep */ 337 __raw_readl(WUPSFAC); /* read wakeup int. factor before sleep */
273 cpu_suspend(0, sh7372_do_idle_a3sm); 338 cpu_suspend(sleep_mode, sh7372_do_idle_sysc);
274 __raw_readl(WUPSFAC); /* read wakeup int. factor after wakeup */ 339 __raw_readl(WUPSFAC); /* read wakeup int. factor after wakeup */
275 340
276 /* disable reset vector translation */ 341 /* disable reset vector translation */
277 __raw_writel(0, SBAR); 342 __raw_writel(0, SBAR);
278} 343}
279 344
280static int sh7372_a3sm_valid(unsigned long *mskp, unsigned long *msk2p) 345static int sh7372_sysc_valid(unsigned long *mskp, unsigned long *msk2p)
281{ 346{
282 unsigned long mstpsr0, mstpsr1, mstpsr2, mstpsr3, mstpsr4; 347 unsigned long mstpsr0, mstpsr1, mstpsr2, mstpsr3, mstpsr4;
283 unsigned long msk, msk2; 348 unsigned long msk, msk2;
@@ -365,7 +430,7 @@ static void sh7372_icr_to_irqcr(unsigned long icr, u16 *irqcr1p, u16 *irqcr2p)
365 *irqcr2p = irqcr2; 430 *irqcr2p = irqcr2;
366} 431}
367 432
368static void sh7372_setup_a3sm(unsigned long msk, unsigned long msk2) 433static void sh7372_setup_sysc(unsigned long msk, unsigned long msk2)
369{ 434{
370 u16 irqcrx_low, irqcrx_high, irqcry_low, irqcry_high; 435 u16 irqcrx_low, irqcrx_high, irqcry_low, irqcry_high;
371 unsigned long tmp; 436 unsigned long tmp;
@@ -398,6 +463,22 @@ static void sh7372_setup_a3sm(unsigned long msk, unsigned long msk2)
398 __raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR3); 463 __raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR3);
399 __raw_writel((irqcry_high << 16) | irqcry_low, IRQCR4); 464 __raw_writel((irqcry_high << 16) | irqcry_low, IRQCR4);
400} 465}
466
467static void sh7372_enter_a3sm_common(int pllc0_on)
468{
469 sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc));
470 sh7372_enter_sysc(pllc0_on, 1 << 12);
471}
472
473static void sh7372_enter_a4s_common(int pllc0_on)
474{
475 sh7372_intca_suspend();
476 memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100);
477 sh7372_set_reset_vector(SMFRAM);
478 sh7372_enter_sysc(pllc0_on, 1 << 10);
479 sh7372_intca_resume();
480}
481
401#endif 482#endif
402 483
403#ifdef CONFIG_CPU_IDLE 484#ifdef CONFIG_CPU_IDLE
@@ -431,14 +512,20 @@ static int sh7372_enter_suspend(suspend_state_t suspend_state)
431 unsigned long msk, msk2; 512 unsigned long msk, msk2;
432 513
433 /* check active clocks to determine potential wakeup sources */ 514 /* check active clocks to determine potential wakeup sources */
434 if (sh7372_a3sm_valid(&msk, &msk2)) { 515 if (sh7372_sysc_valid(&msk, &msk2)) {
435
436 /* convert INTC mask and sense to SYSC mask and sense */ 516 /* convert INTC mask and sense to SYSC mask and sense */
437 sh7372_setup_a3sm(msk, msk2); 517 sh7372_setup_sysc(msk, msk2);
438 518
439 /* enter A3SM sleep with PLLC0 off */ 519 if (!console_suspend_enabled &&
440 pr_debug("entering A3SM\n"); 520 sh7372_a4s.genpd.status == GPD_STATE_POWER_OFF) {
441 sh7372_enter_a3sm_common(0); 521 /* enter A4S sleep with PLLC0 off */
522 pr_debug("entering A4S\n");
523 sh7372_enter_a4s_common(0);
524 } else {
525 /* enter A3SM sleep with PLLC0 off */
526 pr_debug("entering A3SM\n");
527 sh7372_enter_a3sm_common(0);
528 }
442 } else { 529 } else {
443 /* default to Core Standby that supports all wakeup sources */ 530 /* default to Core Standby that supports all wakeup sources */
444 pr_debug("entering Core Standby\n"); 531 pr_debug("entering Core Standby\n");
@@ -447,9 +534,37 @@ static int sh7372_enter_suspend(suspend_state_t suspend_state)
447 return 0; 534 return 0;
448} 535}
449 536
537/**
538 * sh7372_pm_notifier_fn - SH7372 PM notifier routine.
539 * @notifier: Unused.
540 * @pm_event: Event being handled.
541 * @unused: Unused.
542 */
543static int sh7372_pm_notifier_fn(struct notifier_block *notifier,
544 unsigned long pm_event, void *unused)
545{
546 switch (pm_event) {
547 case PM_SUSPEND_PREPARE:
548 /*
549 * This is necessary, because the A4R domain has to be "on"
550 * when suspend_device_irqs() and resume_device_irqs() are
551 * executed during system suspend and resume, respectively, so
552 * that those functions don't crash while accessing the INTCS.
553 */
554 pm_genpd_poweron(&sh7372_a4r.genpd);
555 break;
556 case PM_POST_SUSPEND:
557 pm_genpd_poweroff_unused();
558 break;
559 }
560
561 return NOTIFY_DONE;
562}
563
450static void sh7372_suspend_init(void) 564static void sh7372_suspend_init(void)
451{ 565{
452 shmobile_suspend_ops.enter = sh7372_enter_suspend; 566 shmobile_suspend_ops.enter = sh7372_enter_suspend;
567 pm_notifier(sh7372_pm_notifier_fn, 0);
453} 568}
454#else 569#else
455static void sh7372_suspend_init(void) {} 570static void sh7372_suspend_init(void) {}
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index 2380389e6ac5..c197f9d29d04 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -994,12 +994,16 @@ void __init sh7372_add_standard_devices(void)
994 sh7372_init_pm_domain(&sh7372_a4r); 994 sh7372_init_pm_domain(&sh7372_a4r);
995 sh7372_init_pm_domain(&sh7372_a3rv); 995 sh7372_init_pm_domain(&sh7372_a3rv);
996 sh7372_init_pm_domain(&sh7372_a3ri); 996 sh7372_init_pm_domain(&sh7372_a3ri);
997 sh7372_init_pm_domain(&sh7372_a3sg); 997 sh7372_init_pm_domain(&sh7372_a4s);
998 sh7372_init_pm_domain(&sh7372_a3sp); 998 sh7372_init_pm_domain(&sh7372_a3sp);
999 sh7372_init_pm_domain(&sh7372_a3sg);
999 1000
1000 sh7372_pm_add_subdomain(&sh7372_a4lc, &sh7372_a3rv); 1001 sh7372_pm_add_subdomain(&sh7372_a4lc, &sh7372_a3rv);
1001 sh7372_pm_add_subdomain(&sh7372_a4r, &sh7372_a4lc); 1002 sh7372_pm_add_subdomain(&sh7372_a4r, &sh7372_a4lc);
1002 1003
1004 sh7372_pm_add_subdomain(&sh7372_a4s, &sh7372_a3sg);
1005 sh7372_pm_add_subdomain(&sh7372_a4s, &sh7372_a3sp);
1006
1003 platform_add_devices(sh7372_early_devices, 1007 platform_add_devices(sh7372_early_devices,
1004 ARRAY_SIZE(sh7372_early_devices)); 1008 ARRAY_SIZE(sh7372_early_devices));
1005 1009
diff --git a/arch/arm/mach-shmobile/sleep-sh7372.S b/arch/arm/mach-shmobile/sleep-sh7372.S
index f3ab3c5810ea..1d564674451d 100644
--- a/arch/arm/mach-shmobile/sleep-sh7372.S
+++ b/arch/arm/mach-shmobile/sleep-sh7372.S
@@ -37,13 +37,18 @@
37#if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE) 37#if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE)
38 .align 12 38 .align 12
39 .text 39 .text
40 .global sh7372_resume_core_standby_a3sm 40 .global sh7372_resume_core_standby_sysc
41sh7372_resume_core_standby_a3sm: 41sh7372_resume_core_standby_sysc:
42 ldr pc, 1f 42 ldr pc, 1f
431: .long cpu_resume - PAGE_OFFSET + PLAT_PHYS_OFFSET 431: .long cpu_resume - PAGE_OFFSET + PLAT_PHYS_OFFSET
44 44
45 .global sh7372_do_idle_a3sm 45#define SPDCR 0xe6180008
46sh7372_do_idle_a3sm: 46
47 /* A3SM & A4S power down */
48 .global sh7372_do_idle_sysc
49sh7372_do_idle_sysc:
50 mov r8, r0 /* sleep mode passed in r0 */
51
47 /* 52 /*
48 * Clear the SCTLR.C bit to prevent further data cache 53 * Clear the SCTLR.C bit to prevent further data cache
49 * allocation. Clearing SCTLR.C would make all the data accesses 54 * allocation. Clearing SCTLR.C would make all the data accesses
@@ -80,13 +85,9 @@ sh7372_do_idle_a3sm:
80 dsb 85 dsb
81 dmb 86 dmb
82 87
83#define SPDCR 0xe6180008 88 /* SYSC power down */
84#define A3SM (1 << 12)
85
86 /* A3SM power down */
87 ldr r0, =SPDCR 89 ldr r0, =SPDCR
88 ldr r1, =A3SM 90 str r8, [r0]
89 str r1, [r0]
901: 911:
91 b 1b 92 b 1b
92 93