aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-shmobile
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-02 21:32:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-02 21:32:35 -0400
commit16642a2e7be23bbda013fc32d8f6c68982eab603 (patch)
tree346ae485f485f6901e5d8150f0d34d178a7dd448 /arch/arm/mach-shmobile
parent51562cba98939da0a1d10fe7c25359b77a069033 (diff)
parentb9142167a2bb979b58b98ffcd928a311b55cbd9f (diff)
Merge tag 'pm-for-3.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management updates from Rafael J Wysocki: - Improved system suspend/resume and runtime PM handling for the SH TMU, CMT and MTU2 clock event devices (also used by ARM/shmobile). - Generic PM domains framework extensions related to cpuidle support and domain objects lookup using names. - ARM/shmobile power management updates including improved support for the SH7372's A4S power domain containing the CPU core. - cpufreq changes related to AMD CPUs support from Matthew Garrett, Andre Przywara and Borislav Petkov. - cpu0 cpufreq driver from Shawn Guo. - cpufreq governor fixes related to the relaxing of limit from Michal Pecio. - OMAP cpufreq updates from Axel Lin and Richard Zhao. - cpuidle ladder governor fixes related to the disabling of states from Carsten Emde and me. - Runtime PM core updates related to the interactions with the system suspend core from Alan Stern and Kevin Hilman. - Wakeup sources modification allowing more helper functions to be called from interrupt context from John Stultz and additional diagnostic code from Todd Poynor. - System suspend error code path fix from Feng Hong. Fixed up conflicts in cpufreq/powernow-k8 that stemmed from the workqueue fixes conflicting fairly badly with the removal of support for hardware P-state chips. The changes were independent but somewhat intertwined. * tag 'pm-for-3.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (76 commits) Revert "PM QoS: Use spinlock in the per-device PM QoS constraints code" PM / Runtime: let rpm_resume() succeed if RPM_ACTIVE, even when disabled, v2 cpuidle: rename function name "__cpuidle_register_driver", v2 cpufreq: OMAP: Check IS_ERR() instead of NULL for omap_device_get_by_hwmod_name cpuidle: remove some empty lines PM: Prevent runtime suspend during system resume PM QoS: Use spinlock in the per-device PM QoS constraints code PM / Sleep: use resume event when call dpm_resume_early cpuidle / ACPI : move cpuidle_device field out of the acpi_processor_power structure ACPI / processor: remove pointless variable initialization ACPI / processor: remove unused function parameter cpufreq: OMAP: remove loops_per_jiffy recalculate for smp sections: fix section conflicts in drivers/cpufreq cpufreq: conservative: update frequency when limits are relaxed cpufreq / ondemand: update frequency when limits are relaxed properly __init-annotate pm_sysrq_init() cpufreq: Add a generic cpufreq-cpu0 driver PM / OPP: Initialize OPP table from device tree ARM: add cpufreq transiton notifier to adjust loops_per_jiffy for smp cpufreq: Remove support for hardware P-state chips from powernow-k8 ...
Diffstat (limited to 'arch/arm/mach-shmobile')
-rw-r--r--arch/arm/mach-shmobile/Makefile2
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c21
-rw-r--r--arch/arm/mach-shmobile/board-armadillo800eva.c6
-rw-r--r--arch/arm/mach-shmobile/board-mackerel.c34
-rw-r--r--arch/arm/mach-shmobile/common.c24
-rw-r--r--arch/arm/mach-shmobile/cpuidle.c39
-rw-r--r--arch/arm/mach-shmobile/include/mach/common.h14
-rw-r--r--arch/arm/mach-shmobile/include/mach/pm-rmobile.h35
-rw-r--r--arch/arm/mach-shmobile/include/mach/r8a7740.h6
-rw-r--r--arch/arm/mach-shmobile/include/mach/r8a7779.h12
-rw-r--r--arch/arm/mach-shmobile/include/mach/sh7372.h20
-rw-r--r--arch/arm/mach-shmobile/pm-r8a7740.c42
-rw-r--r--arch/arm/mach-shmobile/pm-r8a7779.c71
-rw-r--r--arch/arm/mach-shmobile/pm-rmobile.c33
-rw-r--r--arch/arm/mach-shmobile/pm-sh7372.c283
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7740.c27
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7779.c5
-rw-r--r--arch/arm/mach-shmobile/setup-sh7372.c69
18 files changed, 407 insertions, 336 deletions
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index 0df5ae6740c6..fe2c97c179d1 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -3,7 +3,7 @@
3# 3#
4 4
5# Common objects 5# Common objects
6obj-y := timer.o console.o clock.o common.o 6obj-y := timer.o console.o clock.o
7 7
8# CPU objects 8# CPU objects
9obj-$(CONFIG_ARCH_SH7367) += setup-sh7367.o clock-sh7367.o intc-sh7367.o 9obj-$(CONFIG_ARCH_SH7367) += setup-sh7367.o clock-sh7367.o intc-sh7367.o
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index bc3b5da59e25..790dc68c4312 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -1231,6 +1231,15 @@ static struct i2c_board_info i2c1_devices[] = {
1231#define USCCR1 IOMEM(0xE6058144) 1231#define USCCR1 IOMEM(0xE6058144)
1232static void __init ap4evb_init(void) 1232static void __init ap4evb_init(void)
1233{ 1233{
1234 struct pm_domain_device domain_devices[] = {
1235 { "A4LC", &lcdc1_device, },
1236 { "A4LC", &lcdc_device, },
1237 { "A4MP", &fsi_device, },
1238 { "A3SP", &sh_mmcif_device, },
1239 { "A3SP", &sdhi0_device, },
1240 { "A3SP", &sdhi1_device, },
1241 { "A4R", &ceu_device, },
1242 };
1234 u32 srcr4; 1243 u32 srcr4;
1235 struct clk *clk; 1244 struct clk *clk;
1236 1245
@@ -1463,14 +1472,8 @@ static void __init ap4evb_init(void)
1463 1472
1464 platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices)); 1473 platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices));
1465 1474
1466 rmobile_add_device_to_domain(&sh7372_pd_a4lc, &lcdc1_device); 1475 rmobile_add_devices_to_domains(domain_devices,
1467 rmobile_add_device_to_domain(&sh7372_pd_a4lc, &lcdc_device); 1476 ARRAY_SIZE(domain_devices));
1468 rmobile_add_device_to_domain(&sh7372_pd_a4mp, &fsi_device);
1469
1470 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sh_mmcif_device);
1471 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi0_device);
1472 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi1_device);
1473 rmobile_add_device_to_domain(&sh7372_pd_a4r, &ceu_device);
1474 1477
1475 hdmi_init_pm_clock(); 1478 hdmi_init_pm_clock();
1476 fsi_init_pm_clock(); 1479 fsi_init_pm_clock();
@@ -1485,6 +1488,6 @@ MACHINE_START(AP4EVB, "ap4evb")
1485 .init_irq = sh7372_init_irq, 1488 .init_irq = sh7372_init_irq,
1486 .handle_irq = shmobile_handle_irq_intc, 1489 .handle_irq = shmobile_handle_irq_intc,
1487 .init_machine = ap4evb_init, 1490 .init_machine = ap4evb_init,
1488 .init_late = shmobile_init_late, 1491 .init_late = sh7372_pm_init_late,
1489 .timer = &shmobile_timer, 1492 .timer = &shmobile_timer,
1490MACHINE_END 1493MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
index c6593d394273..2912eab3b967 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -1209,10 +1209,10 @@ static void __init eva_init(void)
1209 1209
1210 eva_clock_init(); 1210 eva_clock_init();
1211 1211
1212 rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &lcdc0_device); 1212 rmobile_add_device_to_domain("A4LC", &lcdc0_device);
1213 rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &hdmi_lcdc_device); 1213 rmobile_add_device_to_domain("A4LC", &hdmi_lcdc_device);
1214 if (usb) 1214 if (usb)
1215 rmobile_add_device_to_domain(&r8a7740_pd_a3sp, usb); 1215 rmobile_add_device_to_domain("A3SP", usb);
1216} 1216}
1217 1217
1218static void __init eva_earlytimer_init(void) 1218static void __init eva_earlytimer_init(void)
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 62783b5d8813..0c27c810cf99 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -1412,6 +1412,22 @@ static struct i2c_board_info i2c1_devices[] = {
1412#define USCCR1 IOMEM(0xE6058144) 1412#define USCCR1 IOMEM(0xE6058144)
1413static void __init mackerel_init(void) 1413static void __init mackerel_init(void)
1414{ 1414{
1415 struct pm_domain_device domain_devices[] = {
1416 { "A4LC", &lcdc_device, },
1417 { "A4LC", &hdmi_lcdc_device, },
1418 { "A4LC", &meram_device, },
1419 { "A4MP", &fsi_device, },
1420 { "A3SP", &usbhs0_device, },
1421 { "A3SP", &usbhs1_device, },
1422 { "A3SP", &nand_flash_device, },
1423 { "A3SP", &sh_mmcif_device, },
1424 { "A3SP", &sdhi0_device, },
1425#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
1426 { "A3SP", &sdhi1_device, },
1427#endif
1428 { "A3SP", &sdhi2_device, },
1429 { "A4R", &ceu_device, },
1430 };
1415 u32 srcr4; 1431 u32 srcr4;
1416 struct clk *clk; 1432 struct clk *clk;
1417 1433
@@ -1626,20 +1642,8 @@ static void __init mackerel_init(void)
1626 1642
1627 platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices)); 1643 platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices));
1628 1644
1629 rmobile_add_device_to_domain(&sh7372_pd_a4lc, &lcdc_device); 1645 rmobile_add_devices_to_domains(domain_devices,
1630 rmobile_add_device_to_domain(&sh7372_pd_a4lc, &hdmi_lcdc_device); 1646 ARRAY_SIZE(domain_devices));
1631 rmobile_add_device_to_domain(&sh7372_pd_a4lc, &meram_device);
1632 rmobile_add_device_to_domain(&sh7372_pd_a4mp, &fsi_device);
1633 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usbhs0_device);
1634 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usbhs1_device);
1635 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &nand_flash_device);
1636 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sh_mmcif_device);
1637 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi0_device);
1638#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
1639 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi1_device);
1640#endif
1641 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi2_device);
1642 rmobile_add_device_to_domain(&sh7372_pd_a4r, &ceu_device);
1643 1647
1644 hdmi_init_pm_clock(); 1648 hdmi_init_pm_clock();
1645 sh7372_pm_init(); 1649 sh7372_pm_init();
@@ -1653,6 +1657,6 @@ MACHINE_START(MACKEREL, "mackerel")
1653 .init_irq = sh7372_init_irq, 1657 .init_irq = sh7372_init_irq,
1654 .handle_irq = shmobile_handle_irq_intc, 1658 .handle_irq = shmobile_handle_irq_intc,
1655 .init_machine = mackerel_init, 1659 .init_machine = mackerel_init,
1656 .init_late = shmobile_init_late, 1660 .init_late = sh7372_pm_init_late,
1657 .timer = &shmobile_timer, 1661 .timer = &shmobile_timer,
1658MACHINE_END 1662MACHINE_END
diff --git a/arch/arm/mach-shmobile/common.c b/arch/arm/mach-shmobile/common.c
deleted file mode 100644
index 608aba9d60d7..000000000000
--- a/arch/arm/mach-shmobile/common.c
+++ /dev/null
@@ -1,24 +0,0 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; version 2 of the License.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14 *
15 */
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <mach/common.h>
19
20void __init shmobile_init_late(void)
21{
22 shmobile_suspend_init();
23 shmobile_cpuidle_init();
24}
diff --git a/arch/arm/mach-shmobile/cpuidle.c b/arch/arm/mach-shmobile/cpuidle.c
index 7b541e911ab4..9e050268cde4 100644
--- a/arch/arm/mach-shmobile/cpuidle.c
+++ b/arch/arm/mach-shmobile/cpuidle.c
@@ -16,51 +16,38 @@
16#include <asm/cpuidle.h> 16#include <asm/cpuidle.h>
17#include <asm/io.h> 17#include <asm/io.h>
18 18
19static void shmobile_enter_wfi(void) 19int shmobile_enter_wfi(struct cpuidle_device *dev, struct cpuidle_driver *drv,
20 int index)
20{ 21{
21 cpu_do_idle(); 22 cpu_do_idle();
22} 23 return 0;
23
24void (*shmobile_cpuidle_modes[CPUIDLE_STATE_MAX])(void) = {
25 shmobile_enter_wfi, /* regular sleep mode */
26};
27
28static int shmobile_cpuidle_enter(struct cpuidle_device *dev,
29 struct cpuidle_driver *drv,
30 int index)
31{
32 shmobile_cpuidle_modes[index]();
33
34 return index;
35} 24}
36 25
37static struct cpuidle_device shmobile_cpuidle_dev; 26static struct cpuidle_device shmobile_cpuidle_dev;
38static struct cpuidle_driver shmobile_cpuidle_driver = { 27static struct cpuidle_driver shmobile_cpuidle_default_driver = {
39 .name = "shmobile_cpuidle", 28 .name = "shmobile_cpuidle",
40 .owner = THIS_MODULE, 29 .owner = THIS_MODULE,
41 .en_core_tk_irqen = 1, 30 .en_core_tk_irqen = 1,
42 .states[0] = ARM_CPUIDLE_WFI_STATE, 31 .states[0] = ARM_CPUIDLE_WFI_STATE,
32 .states[0].enter = shmobile_enter_wfi,
43 .safe_state_index = 0, /* C1 */ 33 .safe_state_index = 0, /* C1 */
44 .state_count = 1, 34 .state_count = 1,
45}; 35};
46 36
47void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv); 37static struct cpuidle_driver *cpuidle_drv = &shmobile_cpuidle_default_driver;
38
39void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv)
40{
41 cpuidle_drv = drv;
42}
48 43
49int shmobile_cpuidle_init(void) 44int shmobile_cpuidle_init(void)
50{ 45{
51 struct cpuidle_device *dev = &shmobile_cpuidle_dev; 46 struct cpuidle_device *dev = &shmobile_cpuidle_dev;
52 struct cpuidle_driver *drv = &shmobile_cpuidle_driver;
53 int i;
54
55 for (i = 0; i < CPUIDLE_STATE_MAX; i++)
56 drv->states[i].enter = shmobile_cpuidle_enter;
57
58 if (shmobile_cpuidle_setup)
59 shmobile_cpuidle_setup(drv);
60 47
61 cpuidle_register_driver(drv); 48 cpuidle_register_driver(cpuidle_drv);
62 49
63 dev->state_count = drv->state_count; 50 dev->state_count = cpuidle_drv->state_count;
64 cpuidle_register_device(dev); 51 cpuidle_register_device(dev);
65 52
66 return 0; 53 return 0;
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index f80f9c549393..ed77ab8c9143 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -13,8 +13,10 @@ extern int shmobile_clk_init(void);
13extern void shmobile_handle_irq_intc(struct pt_regs *); 13extern void shmobile_handle_irq_intc(struct pt_regs *);
14extern struct platform_suspend_ops shmobile_suspend_ops; 14extern struct platform_suspend_ops shmobile_suspend_ops;
15struct cpuidle_driver; 15struct cpuidle_driver;
16extern void (*shmobile_cpuidle_modes[])(void); 16struct cpuidle_device;
17extern void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv); 17extern int shmobile_enter_wfi(struct cpuidle_device *dev,
18 struct cpuidle_driver *drv, int index);
19extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv);
18 20
19extern void sh7367_init_irq(void); 21extern void sh7367_init_irq(void);
20extern void sh7367_map_io(void); 22extern void sh7367_map_io(void);
@@ -75,8 +77,6 @@ extern void r8a7740_meram_workaround(void);
75 77
76extern void r8a7779_register_twd(void); 78extern void r8a7779_register_twd(void);
77 79
78extern void shmobile_init_late(void);
79
80#ifdef CONFIG_SUSPEND 80#ifdef CONFIG_SUSPEND
81int shmobile_suspend_init(void); 81int shmobile_suspend_init(void);
82#else 82#else
@@ -100,4 +100,10 @@ static inline int shmobile_cpu_is_dead(unsigned int cpu) { return 1; }
100 100
101extern void shmobile_smp_init_cpus(unsigned int ncores); 101extern void shmobile_smp_init_cpus(unsigned int ncores);
102 102
103static inline void shmobile_init_late(void)
104{
105 shmobile_suspend_init();
106 shmobile_cpuidle_init();
107}
108
103#endif /* __ARCH_MACH_COMMON_H */ 109#endif /* __ARCH_MACH_COMMON_H */
diff --git a/arch/arm/mach-shmobile/include/mach/pm-rmobile.h b/arch/arm/mach-shmobile/include/mach/pm-rmobile.h
index 5a402840fe28..690553a06887 100644
--- a/arch/arm/mach-shmobile/include/mach/pm-rmobile.h
+++ b/arch/arm/mach-shmobile/include/mach/pm-rmobile.h
@@ -12,6 +12,8 @@
12 12
13#include <linux/pm_domain.h> 13#include <linux/pm_domain.h>
14 14
15#define DEFAULT_DEV_LATENCY_NS 250000
16
15struct platform_device; 17struct platform_device;
16 18
17struct rmobile_pm_domain { 19struct rmobile_pm_domain {
@@ -29,16 +31,33 @@ struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d)
29 return container_of(d, struct rmobile_pm_domain, genpd); 31 return container_of(d, struct rmobile_pm_domain, genpd);
30} 32}
31 33
34struct pm_domain_device {
35 const char *domain_name;
36 struct platform_device *pdev;
37};
38
32#ifdef CONFIG_PM 39#ifdef CONFIG_PM
33extern void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd); 40extern void rmobile_init_domains(struct rmobile_pm_domain domains[], int num);
34extern void rmobile_add_device_to_domain(struct rmobile_pm_domain *rmobile_pd, 41extern void rmobile_add_device_to_domain_td(const char *domain_name,
35 struct platform_device *pdev); 42 struct platform_device *pdev,
36extern void rmobile_pm_add_subdomain(struct rmobile_pm_domain *rmobile_pd, 43 struct gpd_timing_data *td);
37 struct rmobile_pm_domain *rmobile_sd); 44
45static inline void rmobile_add_device_to_domain(const char *domain_name,
46 struct platform_device *pdev)
47{
48 rmobile_add_device_to_domain_td(domain_name, pdev, NULL);
49}
50
51extern void rmobile_add_devices_to_domains(struct pm_domain_device data[],
52 int size);
38#else 53#else
39#define rmobile_init_pm_domain(pd) do { } while (0) 54
40#define rmobile_add_device_to_domain(pd, pdev) do { } while (0) 55#define rmobile_init_domains(domains, num) do { } while (0)
41#define rmobile_pm_add_subdomain(pd, sd) do { } while (0) 56#define rmobile_add_device_to_domain_td(name, pdev, td) do { } while (0)
57#define rmobile_add_device_to_domain(name, pdev) do { } while (0)
58
59static inline void rmobile_add_devices_to_domains(struct pm_domain_device d[],
60 int size) {}
42#endif /* CONFIG_PM */ 61#endif /* CONFIG_PM */
43 62
44#endif /* PM_RMOBILE_H */ 63#endif /* PM_RMOBILE_H */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
index 7143147780df..59d252f4cf97 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
@@ -607,9 +607,9 @@ enum {
607}; 607};
608 608
609#ifdef CONFIG_PM 609#ifdef CONFIG_PM
610extern struct rmobile_pm_domain r8a7740_pd_a4s; 610extern void __init r8a7740_init_pm_domains(void);
611extern struct rmobile_pm_domain r8a7740_pd_a3sp; 611#else
612extern struct rmobile_pm_domain r8a7740_pd_a4lc; 612static inline void r8a7740_init_pm_domains(void) {}
613#endif /* CONFIG_PM */ 613#endif /* CONFIG_PM */
614 614
615#endif /* __ASM_R8A7740_H__ */ 615#endif /* __ASM_R8A7740_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7779.h b/arch/arm/mach-shmobile/include/mach/r8a7779.h
index f504c5e81b47..499f52d2a4a1 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7779.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7779.h
@@ -347,17 +347,9 @@ extern int r8a7779_sysc_power_down(struct r8a7779_pm_ch *r8a7779_ch);
347extern int r8a7779_sysc_power_up(struct r8a7779_pm_ch *r8a7779_ch); 347extern int r8a7779_sysc_power_up(struct r8a7779_pm_ch *r8a7779_ch);
348 348
349#ifdef CONFIG_PM 349#ifdef CONFIG_PM
350extern struct r8a7779_pm_domain r8a7779_sh4a; 350extern void __init r8a7779_init_pm_domains(void);
351extern struct r8a7779_pm_domain r8a7779_sgx;
352extern struct r8a7779_pm_domain r8a7779_vdp1;
353extern struct r8a7779_pm_domain r8a7779_impx3;
354
355extern void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd);
356extern void r8a7779_add_device_to_domain(struct r8a7779_pm_domain *r8a7779_pd,
357 struct platform_device *pdev);
358#else 351#else
359#define r8a7779_init_pm_domain(pd) do { } while (0) 352static inline void r8a7779_init_pm_domains(void) {}
360#define r8a7779_add_device_to_domain(pd, pdev) do { } while (0)
361#endif /* CONFIG_PM */ 353#endif /* CONFIG_PM */
362 354
363extern struct smp_operations r8a7779_smp_ops; 355extern struct smp_operations r8a7779_smp_ops;
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h
index b59048e6d8fd..eb98b45c5089 100644
--- a/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ b/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -478,21 +478,17 @@ extern struct clk sh7372_fsibck_clk;
478extern struct clk sh7372_fsidiva_clk; 478extern struct clk sh7372_fsidiva_clk;
479extern struct clk sh7372_fsidivb_clk; 479extern struct clk sh7372_fsidivb_clk;
480 480
481#ifdef CONFIG_PM
482extern struct rmobile_pm_domain sh7372_pd_a4lc;
483extern struct rmobile_pm_domain sh7372_pd_a4mp;
484extern struct rmobile_pm_domain sh7372_pd_d4;
485extern struct rmobile_pm_domain sh7372_pd_a4r;
486extern struct rmobile_pm_domain sh7372_pd_a3rv;
487extern struct rmobile_pm_domain sh7372_pd_a3ri;
488extern struct rmobile_pm_domain sh7372_pd_a4s;
489extern struct rmobile_pm_domain sh7372_pd_a3sp;
490extern struct rmobile_pm_domain sh7372_pd_a3sg;
491#endif /* CONFIG_PM */
492
493extern void sh7372_intcs_suspend(void); 481extern void sh7372_intcs_suspend(void);
494extern void sh7372_intcs_resume(void); 482extern void sh7372_intcs_resume(void);
495extern void sh7372_intca_suspend(void); 483extern void sh7372_intca_suspend(void);
496extern void sh7372_intca_resume(void); 484extern void sh7372_intca_resume(void);
497 485
486#ifdef CONFIG_PM
487extern void __init sh7372_init_pm_domains(void);
488#else
489static inline void sh7372_init_pm_domains(void) {}
490#endif
491
492extern void __init sh7372_pm_init_late(void);
493
498#endif /* __ASM_SH7372_H__ */ 494#endif /* __ASM_SH7372_H__ */
diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c
index 893504d012a6..21e5316d2d88 100644
--- a/arch/arm/mach-shmobile/pm-r8a7740.c
+++ b/arch/arm/mach-shmobile/pm-r8a7740.c
@@ -21,14 +21,6 @@ static int r8a7740_pd_a4s_suspend(void)
21 return -EBUSY; 21 return -EBUSY;
22} 22}
23 23
24struct rmobile_pm_domain r8a7740_pd_a4s = {
25 .genpd.name = "A4S",
26 .bit_shift = 10,
27 .gov = &pm_domain_always_on_gov,
28 .no_debug = true,
29 .suspend = r8a7740_pd_a4s_suspend,
30};
31
32static int r8a7740_pd_a3sp_suspend(void) 24static int r8a7740_pd_a3sp_suspend(void)
33{ 25{
34 /* 26 /*
@@ -38,17 +30,31 @@ static int r8a7740_pd_a3sp_suspend(void)
38 return console_suspend_enabled ? 0 : -EBUSY; 30 return console_suspend_enabled ? 0 : -EBUSY;
39} 31}
40 32
41struct rmobile_pm_domain r8a7740_pd_a3sp = { 33static struct rmobile_pm_domain r8a7740_pm_domains[] = {
42 .genpd.name = "A3SP", 34 {
43 .bit_shift = 11, 35 .genpd.name = "A4S",
44 .gov = &pm_domain_always_on_gov, 36 .bit_shift = 10,
45 .no_debug = true, 37 .gov = &pm_domain_always_on_gov,
46 .suspend = r8a7740_pd_a3sp_suspend, 38 .no_debug = true,
39 .suspend = r8a7740_pd_a4s_suspend,
40 },
41 {
42 .genpd.name = "A3SP",
43 .bit_shift = 11,
44 .gov = &pm_domain_always_on_gov,
45 .no_debug = true,
46 .suspend = r8a7740_pd_a3sp_suspend,
47 },
48 {
49 .genpd.name = "A4LC",
50 .bit_shift = 1,
51 },
47}; 52};
48 53
49struct rmobile_pm_domain r8a7740_pd_a4lc = { 54void __init r8a7740_init_pm_domains(void)
50 .genpd.name = "A4LC", 55{
51 .bit_shift = 1, 56 rmobile_init_domains(r8a7740_pm_domains, ARRAY_SIZE(r8a7740_pm_domains));
52}; 57 pm_genpd_add_subdomain_names("A4S", "A3SP");
58}
53 59
54#endif /* CONFIG_PM */ 60#endif /* CONFIG_PM */
diff --git a/arch/arm/mach-shmobile/pm-r8a7779.c b/arch/arm/mach-shmobile/pm-r8a7779.c
index a18a4ae16d2b..d50a8e9b94a4 100644
--- a/arch/arm/mach-shmobile/pm-r8a7779.c
+++ b/arch/arm/mach-shmobile/pm-r8a7779.c
@@ -183,7 +183,7 @@ static bool pd_active_wakeup(struct device *dev)
183 return true; 183 return true;
184} 184}
185 185
186void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd) 186static void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd)
187{ 187{
188 struct generic_pm_domain *genpd = &r8a7779_pd->genpd; 188 struct generic_pm_domain *genpd = &r8a7779_pd->genpd;
189 189
@@ -199,43 +199,44 @@ void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd)
199 pd_power_up(&r8a7779_pd->genpd); 199 pd_power_up(&r8a7779_pd->genpd);
200} 200}
201 201
202void r8a7779_add_device_to_domain(struct r8a7779_pm_domain *r8a7779_pd, 202static struct r8a7779_pm_domain r8a7779_pm_domains[] = {
203 struct platform_device *pdev) 203 {
204{ 204 .genpd.name = "SH4A",
205 struct device *dev = &pdev->dev; 205 .ch = {
206 206 .chan_offs = 0x80, /* PWRSR1 .. PWRER1 */
207 pm_genpd_add_device(&r8a7779_pd->genpd, dev); 207 .isr_bit = 16, /* SH4A */
208 if (pm_clk_no_clocks(dev)) 208 },
209 pm_clk_add(dev, NULL); 209 },
210} 210 {
211 211 .genpd.name = "SGX",
212struct r8a7779_pm_domain r8a7779_sh4a = { 212 .ch = {
213 .ch = { 213 .chan_offs = 0xc0, /* PWRSR2 .. PWRER2 */
214 .chan_offs = 0x80, /* PWRSR1 .. PWRER1 */ 214 .isr_bit = 20, /* SGX */
215 .isr_bit = 16, /* SH4A */ 215 },
216 } 216 },
217}; 217 {
218 218 .genpd.name = "VDP1",
219struct r8a7779_pm_domain r8a7779_sgx = { 219 .ch = {
220 .ch = { 220 .chan_offs = 0x100, /* PWRSR3 .. PWRER3 */
221 .chan_offs = 0xc0, /* PWRSR2 .. PWRER2 */ 221 .isr_bit = 21, /* VDP */
222 .isr_bit = 20, /* SGX */ 222 },
223 } 223 },
224 {
225 .genpd.name = "IMPX3",
226 .ch = {
227 .chan_offs = 0x140, /* PWRSR4 .. PWRER4 */
228 .isr_bit = 24, /* IMP */
229 },
230 },
224}; 231};
225 232
226struct r8a7779_pm_domain r8a7779_vdp1 = { 233void __init r8a7779_init_pm_domains(void)
227 .ch = { 234{
228 .chan_offs = 0x100, /* PWRSR3 .. PWRER3 */ 235 int j;
229 .isr_bit = 21, /* VDP */
230 }
231};
232 236
233struct r8a7779_pm_domain r8a7779_impx3 = { 237 for (j = 0; j < ARRAY_SIZE(r8a7779_pm_domains); j++)
234 .ch = { 238 r8a7779_init_pm_domain(&r8a7779_pm_domains[j]);
235 .chan_offs = 0x140, /* PWRSR4 .. PWRER4 */ 239}
236 .isr_bit = 24, /* IMP */
237 }
238};
239 240
240#endif /* CONFIG_PM */ 241#endif /* CONFIG_PM */
241 242
diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c
index 32e177275e47..1fc05d9453d0 100644
--- a/arch/arm/mach-shmobile/pm-rmobile.c
+++ b/arch/arm/mach-shmobile/pm-rmobile.c
@@ -134,7 +134,7 @@ static int rmobile_pd_start_dev(struct device *dev)
134 return ret; 134 return ret;
135} 135}
136 136
137void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) 137static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
138{ 138{
139 struct generic_pm_domain *genpd = &rmobile_pd->genpd; 139 struct generic_pm_domain *genpd = &rmobile_pd->genpd;
140 struct dev_power_governor *gov = rmobile_pd->gov; 140 struct dev_power_governor *gov = rmobile_pd->gov;
@@ -149,19 +149,38 @@ void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
149 __rmobile_pd_power_up(rmobile_pd, false); 149 __rmobile_pd_power_up(rmobile_pd, false);
150} 150}
151 151
152void rmobile_add_device_to_domain(struct rmobile_pm_domain *rmobile_pd, 152void rmobile_init_domains(struct rmobile_pm_domain domains[], int num)
153 struct platform_device *pdev) 153{
154 int j;
155
156 for (j = 0; j < num; j++)
157 rmobile_init_pm_domain(&domains[j]);
158}
159
160void rmobile_add_device_to_domain_td(const char *domain_name,
161 struct platform_device *pdev,
162 struct gpd_timing_data *td)
154{ 163{
155 struct device *dev = &pdev->dev; 164 struct device *dev = &pdev->dev;
156 165
157 pm_genpd_add_device(&rmobile_pd->genpd, dev); 166 __pm_genpd_name_add_device(domain_name, dev, td);
158 if (pm_clk_no_clocks(dev)) 167 if (pm_clk_no_clocks(dev))
159 pm_clk_add(dev, NULL); 168 pm_clk_add(dev, NULL);
160} 169}
161 170
162void rmobile_pm_add_subdomain(struct rmobile_pm_domain *rmobile_pd, 171void rmobile_add_devices_to_domains(struct pm_domain_device data[],
163 struct rmobile_pm_domain *rmobile_sd) 172 int size)
164{ 173{
165 pm_genpd_add_subdomain(&rmobile_pd->genpd, &rmobile_sd->genpd); 174 struct gpd_timing_data latencies = {
175 .stop_latency_ns = DEFAULT_DEV_LATENCY_NS,
176 .start_latency_ns = DEFAULT_DEV_LATENCY_NS,
177 .save_state_latency_ns = DEFAULT_DEV_LATENCY_NS,
178 .restore_state_latency_ns = DEFAULT_DEV_LATENCY_NS,
179 };
180 int j;
181
182 for (j = 0; j < size; j++)
183 rmobile_add_device_to_domain_td(data[j].domain_name,
184 data[j].pdev, &latencies);
166} 185}
167#endif /* CONFIG_PM */ 186#endif /* CONFIG_PM */
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c
index 162121842a2b..a0826a48dd08 100644
--- a/arch/arm/mach-shmobile/pm-sh7372.c
+++ b/arch/arm/mach-shmobile/pm-sh7372.c
@@ -21,6 +21,7 @@
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 <linux/console.h>
24#include <asm/cpuidle.h>
24#include <asm/io.h> 25#include <asm/io.h>
25#include <asm/tlbflush.h> 26#include <asm/tlbflush.h>
26#include <asm/suspend.h> 27#include <asm/suspend.h>
@@ -72,20 +73,7 @@
72 73
73#ifdef CONFIG_PM 74#ifdef CONFIG_PM
74 75
75struct rmobile_pm_domain sh7372_pd_a4lc = { 76#define PM_DOMAIN_ON_OFF_LATENCY_NS 250000
76 .genpd.name = "A4LC",
77 .bit_shift = 1,
78};
79
80struct rmobile_pm_domain sh7372_pd_a4mp = {
81 .genpd.name = "A4MP",
82 .bit_shift = 2,
83};
84
85struct rmobile_pm_domain sh7372_pd_d4 = {
86 .genpd.name = "D4",
87 .bit_shift = 3,
88};
89 77
90static int sh7372_a4r_pd_suspend(void) 78static int sh7372_a4r_pd_suspend(void)
91{ 79{
@@ -94,39 +82,25 @@ static int sh7372_a4r_pd_suspend(void)
94 return 0; 82 return 0;
95} 83}
96 84
97struct rmobile_pm_domain sh7372_pd_a4r = { 85static bool a4s_suspend_ready;
98 .genpd.name = "A4R",
99 .bit_shift = 5,
100 .suspend = sh7372_a4r_pd_suspend,
101 .resume = sh7372_intcs_resume,
102};
103 86
104struct rmobile_pm_domain sh7372_pd_a3rv = { 87static int sh7372_a4s_pd_suspend(void)
105 .genpd.name = "A3RV",
106 .bit_shift = 6,
107};
108
109struct rmobile_pm_domain sh7372_pd_a3ri = {
110 .genpd.name = "A3RI",
111 .bit_shift = 8,
112};
113
114static int sh7372_pd_a4s_suspend(void)
115{ 88{
116 /* 89 /*
117 * The A4S domain contains the CPU core and therefore it should 90 * The A4S domain contains the CPU core and therefore it should
118 * only be turned off if the CPU is in use. 91 * only be turned off if the CPU is not in use. This may happen
92 * during system suspend, when SYSC is going to be used for generating
93 * resume signals and a4s_suspend_ready is set to let
94 * sh7372_enter_suspend() know that it can turn A4S off.
119 */ 95 */
96 a4s_suspend_ready = true;
120 return -EBUSY; 97 return -EBUSY;
121} 98}
122 99
123struct rmobile_pm_domain sh7372_pd_a4s = { 100static void sh7372_a4s_pd_resume(void)
124 .genpd.name = "A4S", 101{
125 .bit_shift = 10, 102 a4s_suspend_ready = false;
126 .gov = &pm_domain_always_on_gov, 103}
127 .no_debug = true,
128 .suspend = sh7372_pd_a4s_suspend,
129};
130 104
131static int sh7372_a3sp_pd_suspend(void) 105static int sh7372_a3sp_pd_suspend(void)
132{ 106{
@@ -137,18 +111,80 @@ static int sh7372_a3sp_pd_suspend(void)
137 return console_suspend_enabled ? 0 : -EBUSY; 111 return console_suspend_enabled ? 0 : -EBUSY;
138} 112}
139 113
140struct rmobile_pm_domain sh7372_pd_a3sp = { 114static struct rmobile_pm_domain sh7372_pm_domains[] = {
141 .genpd.name = "A3SP", 115 {
142 .bit_shift = 11, 116 .genpd.name = "A4LC",
143 .gov = &pm_domain_always_on_gov, 117 .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
144 .no_debug = true, 118 .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
145 .suspend = sh7372_a3sp_pd_suspend, 119 .bit_shift = 1,
120 },
121 {
122 .genpd.name = "A4MP",
123 .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
124 .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
125 .bit_shift = 2,
126 },
127 {
128 .genpd.name = "D4",
129 .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
130 .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
131 .bit_shift = 3,
132 },
133 {
134 .genpd.name = "A4R",
135 .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
136 .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
137 .bit_shift = 5,
138 .suspend = sh7372_a4r_pd_suspend,
139 .resume = sh7372_intcs_resume,
140 },
141 {
142 .genpd.name = "A3RV",
143 .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
144 .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
145 .bit_shift = 6,
146 },
147 {
148 .genpd.name = "A3RI",
149 .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
150 .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
151 .bit_shift = 8,
152 },
153 {
154 .genpd.name = "A4S",
155 .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
156 .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
157 .bit_shift = 10,
158 .gov = &pm_domain_always_on_gov,
159 .no_debug = true,
160 .suspend = sh7372_a4s_pd_suspend,
161 .resume = sh7372_a4s_pd_resume,
162 },
163 {
164 .genpd.name = "A3SP",
165 .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
166 .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
167 .bit_shift = 11,
168 .gov = &pm_domain_always_on_gov,
169 .no_debug = true,
170 .suspend = sh7372_a3sp_pd_suspend,
171 },
172 {
173 .genpd.name = "A3SG",
174 .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
175 .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
176 .bit_shift = 13,
177 },
146}; 178};
147 179
148struct rmobile_pm_domain sh7372_pd_a3sg = { 180void __init sh7372_init_pm_domains(void)
149 .genpd.name = "A3SG", 181{
150 .bit_shift = 13, 182 rmobile_init_domains(sh7372_pm_domains, ARRAY_SIZE(sh7372_pm_domains));
151}; 183 pm_genpd_add_subdomain_names("A4LC", "A3RV");
184 pm_genpd_add_subdomain_names("A4R", "A4LC");
185 pm_genpd_add_subdomain_names("A4S", "A3SG");
186 pm_genpd_add_subdomain_names("A4S", "A3SP");
187}
152 188
153#endif /* CONFIG_PM */ 189#endif /* CONFIG_PM */
154 190
@@ -304,6 +340,21 @@ static void sh7372_enter_a3sm_common(int pllc0_on)
304 sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); 340 sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc));
305 sh7372_enter_sysc(pllc0_on, 1 << 12); 341 sh7372_enter_sysc(pllc0_on, 1 << 12);
306} 342}
343
344static void sh7372_enter_a4s_common(int pllc0_on)
345{
346 sh7372_intca_suspend();
347 sh7372_set_reset_vector(SMFRAM);
348 sh7372_enter_sysc(pllc0_on, 1 << 10);
349 sh7372_intca_resume();
350}
351
352static void sh7372_pm_setup_smfram(void)
353{
354 memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100);
355}
356#else
357static inline void sh7372_pm_setup_smfram(void) {}
307#endif /* CONFIG_SUSPEND || CONFIG_CPU_IDLE */ 358#endif /* CONFIG_SUSPEND || CONFIG_CPU_IDLE */
308 359
309#ifdef CONFIG_CPU_IDLE 360#ifdef CONFIG_CPU_IDLE
@@ -313,7 +364,8 @@ static int sh7372_do_idle_core_standby(unsigned long unused)
313 return 0; 364 return 0;
314} 365}
315 366
316static void sh7372_enter_core_standby(void) 367static int sh7372_enter_core_standby(struct cpuidle_device *dev,
368 struct cpuidle_driver *drv, int index)
317{ 369{
318 sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); 370 sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc));
319 371
@@ -324,83 +376,102 @@ static void sh7372_enter_core_standby(void)
324 376
325 /* disable reset vector translation */ 377 /* disable reset vector translation */
326 __raw_writel(0, SBAR); 378 __raw_writel(0, SBAR);
379
380 return 1;
327} 381}
328 382
329static void sh7372_enter_a3sm_pll_on(void) 383static int sh7372_enter_a3sm_pll_on(struct cpuidle_device *dev,
384 struct cpuidle_driver *drv, int index)
330{ 385{
331 sh7372_enter_a3sm_common(1); 386 sh7372_enter_a3sm_common(1);
387 return 2;
332} 388}
333 389
334static void sh7372_enter_a3sm_pll_off(void) 390static int sh7372_enter_a3sm_pll_off(struct cpuidle_device *dev,
391 struct cpuidle_driver *drv, int index)
335{ 392{
336 sh7372_enter_a3sm_common(0); 393 sh7372_enter_a3sm_common(0);
394 return 3;
337} 395}
338 396
339static void sh7372_cpuidle_setup(struct cpuidle_driver *drv) 397static int sh7372_enter_a4s(struct cpuidle_device *dev,
398 struct cpuidle_driver *drv, int index)
340{ 399{
341 struct cpuidle_state *state = &drv->states[drv->state_count]; 400 unsigned long msk, msk2;
342 401
343 snprintf(state->name, CPUIDLE_NAME_LEN, "C2"); 402 if (!sh7372_sysc_valid(&msk, &msk2))
344 strncpy(state->desc, "Core Standby Mode", CPUIDLE_DESC_LEN); 403 return sh7372_enter_a3sm_pll_off(dev, drv, index);
345 state->exit_latency = 10; 404
346 state->target_residency = 20 + 10; 405 sh7372_setup_sysc(msk, msk2);
347 state->flags = CPUIDLE_FLAG_TIME_VALID; 406 sh7372_enter_a4s_common(0);
348 shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_core_standby; 407 return 4;
349 drv->state_count++;
350
351 state = &drv->states[drv->state_count];
352 snprintf(state->name, CPUIDLE_NAME_LEN, "C3");
353 strncpy(state->desc, "A3SM PLL ON", CPUIDLE_DESC_LEN);
354 state->exit_latency = 20;
355 state->target_residency = 30 + 20;
356 state->flags = CPUIDLE_FLAG_TIME_VALID;
357 shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_a3sm_pll_on;
358 drv->state_count++;
359
360 state = &drv->states[drv->state_count];
361 snprintf(state->name, CPUIDLE_NAME_LEN, "C4");
362 strncpy(state->desc, "A3SM PLL OFF", CPUIDLE_DESC_LEN);
363 state->exit_latency = 120;
364 state->target_residency = 30 + 120;
365 state->flags = CPUIDLE_FLAG_TIME_VALID;
366 shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_a3sm_pll_off;
367 drv->state_count++;
368} 408}
369 409
410static struct cpuidle_driver sh7372_cpuidle_driver = {
411 .name = "sh7372_cpuidle",
412 .owner = THIS_MODULE,
413 .en_core_tk_irqen = 1,
414 .state_count = 5,
415 .safe_state_index = 0, /* C1 */
416 .states[0] = ARM_CPUIDLE_WFI_STATE,
417 .states[0].enter = shmobile_enter_wfi,
418 .states[1] = {
419 .name = "C2",
420 .desc = "Core Standby Mode",
421 .exit_latency = 10,
422 .target_residency = 20 + 10,
423 .flags = CPUIDLE_FLAG_TIME_VALID,
424 .enter = sh7372_enter_core_standby,
425 },
426 .states[2] = {
427 .name = "C3",
428 .desc = "A3SM PLL ON",
429 .exit_latency = 20,
430 .target_residency = 30 + 20,
431 .flags = CPUIDLE_FLAG_TIME_VALID,
432 .enter = sh7372_enter_a3sm_pll_on,
433 },
434 .states[3] = {
435 .name = "C4",
436 .desc = "A3SM PLL OFF",
437 .exit_latency = 120,
438 .target_residency = 30 + 120,
439 .flags = CPUIDLE_FLAG_TIME_VALID,
440 .enter = sh7372_enter_a3sm_pll_off,
441 },
442 .states[4] = {
443 .name = "C5",
444 .desc = "A4S PLL OFF",
445 .exit_latency = 240,
446 .target_residency = 30 + 240,
447 .flags = CPUIDLE_FLAG_TIME_VALID,
448 .enter = sh7372_enter_a4s,
449 .disabled = true,
450 },
451};
452
370static void sh7372_cpuidle_init(void) 453static void sh7372_cpuidle_init(void)
371{ 454{
372 shmobile_cpuidle_setup = sh7372_cpuidle_setup; 455 shmobile_cpuidle_set_driver(&sh7372_cpuidle_driver);
373} 456}
374#else 457#else
375static void sh7372_cpuidle_init(void) {} 458static void sh7372_cpuidle_init(void) {}
376#endif 459#endif
377 460
378#ifdef CONFIG_SUSPEND 461#ifdef CONFIG_SUSPEND
379static void sh7372_enter_a4s_common(int pllc0_on)
380{
381 sh7372_intca_suspend();
382 memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100);
383 sh7372_set_reset_vector(SMFRAM);
384 sh7372_enter_sysc(pllc0_on, 1 << 10);
385 sh7372_intca_resume();
386}
387
388static int sh7372_enter_suspend(suspend_state_t suspend_state) 462static int sh7372_enter_suspend(suspend_state_t suspend_state)
389{ 463{
390 unsigned long msk, msk2; 464 unsigned long msk, msk2;
391 465
392 /* check active clocks to determine potential wakeup sources */ 466 /* check active clocks to determine potential wakeup sources */
393 if (sh7372_sysc_valid(&msk, &msk2)) { 467 if (sh7372_sysc_valid(&msk, &msk2) && a4s_suspend_ready) {
394 if (!console_suspend_enabled && 468 /* convert INTC mask/sense to SYSC mask/sense */
395 sh7372_pd_a4s.genpd.status == GPD_STATE_POWER_OFF) { 469 sh7372_setup_sysc(msk, msk2);
396 /* convert INTC mask/sense to SYSC mask/sense */ 470
397 sh7372_setup_sysc(msk, msk2); 471 /* enter A4S sleep with PLLC0 off */
398 472 pr_debug("entering A4S\n");
399 /* enter A4S sleep with PLLC0 off */ 473 sh7372_enter_a4s_common(0);
400 pr_debug("entering A4S\n"); 474 return 0;
401 sh7372_enter_a4s_common(0);
402 return 0;
403 }
404 } 475 }
405 476
406 /* default to enter A3SM sleep with PLLC0 off */ 477 /* default to enter A3SM sleep with PLLC0 off */
@@ -426,7 +497,7 @@ static int sh7372_pm_notifier_fn(struct notifier_block *notifier,
426 * executed during system suspend and resume, respectively, so 497 * executed during system suspend and resume, respectively, so
427 * that those functions don't crash while accessing the INTCS. 498 * that those functions don't crash while accessing the INTCS.
428 */ 499 */
429 pm_genpd_poweron(&sh7372_pd_a4r.genpd); 500 pm_genpd_name_poweron("A4R");
430 break; 501 break;
431 case PM_POST_SUSPEND: 502 case PM_POST_SUSPEND:
432 pm_genpd_poweroff_unused(); 503 pm_genpd_poweroff_unused();
@@ -455,6 +526,14 @@ void __init sh7372_pm_init(void)
455 /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */ 526 /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */
456 __raw_writel(0, PDNSEL); 527 __raw_writel(0, PDNSEL);
457 528
529 sh7372_pm_setup_smfram();
530
458 sh7372_suspend_init(); 531 sh7372_suspend_init();
459 sh7372_cpuidle_init(); 532 sh7372_cpuidle_init();
460} 533}
534
535void __init sh7372_pm_init_late(void)
536{
537 shmobile_init_late();
538 pm_genpd_name_attach_cpuidle("A4S", 4);
539}
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
index 78948a9dba0e..11bb1d984197 100644
--- a/arch/arm/mach-shmobile/setup-r8a7740.c
+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
@@ -673,12 +673,7 @@ void __init r8a7740_add_standard_devices(void)
673 r8a7740_i2c_workaround(&i2c0_device); 673 r8a7740_i2c_workaround(&i2c0_device);
674 r8a7740_i2c_workaround(&i2c1_device); 674 r8a7740_i2c_workaround(&i2c1_device);
675 675
676 /* PM domain */ 676 r8a7740_init_pm_domains();
677 rmobile_init_pm_domain(&r8a7740_pd_a4s);
678 rmobile_init_pm_domain(&r8a7740_pd_a3sp);
679 rmobile_init_pm_domain(&r8a7740_pd_a4lc);
680
681 rmobile_pm_add_subdomain(&r8a7740_pd_a4s, &r8a7740_pd_a3sp);
682 677
683 /* add devices */ 678 /* add devices */
684 platform_add_devices(r8a7740_early_devices, 679 platform_add_devices(r8a7740_early_devices,
@@ -688,16 +683,16 @@ void __init r8a7740_add_standard_devices(void)
688 683
689 /* add devices to PM domain */ 684 /* add devices to PM domain */
690 685
691 rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif0_device); 686 rmobile_add_device_to_domain("A3SP", &scif0_device);
692 rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif1_device); 687 rmobile_add_device_to_domain("A3SP", &scif1_device);
693 rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif2_device); 688 rmobile_add_device_to_domain("A3SP", &scif2_device);
694 rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif3_device); 689 rmobile_add_device_to_domain("A3SP", &scif3_device);
695 rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif4_device); 690 rmobile_add_device_to_domain("A3SP", &scif4_device);
696 rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif5_device); 691 rmobile_add_device_to_domain("A3SP", &scif5_device);
697 rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif6_device); 692 rmobile_add_device_to_domain("A3SP", &scif6_device);
698 rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif7_device); 693 rmobile_add_device_to_domain("A3SP", &scif7_device);
699 rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scifb_device); 694 rmobile_add_device_to_domain("A3SP", &scifb_device);
700 rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &i2c1_device); 695 rmobile_add_device_to_domain("A3SP", &i2c1_device);
701} 696}
702 697
703static void __init r8a7740_earlytimer_init(void) 698static void __init r8a7740_earlytimer_init(void)
diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c
index e98e46f6cf55..2917668f0091 100644
--- a/arch/arm/mach-shmobile/setup-r8a7779.c
+++ b/arch/arm/mach-shmobile/setup-r8a7779.c
@@ -251,10 +251,7 @@ void __init r8a7779_add_standard_devices(void)
251#endif 251#endif
252 r8a7779_pm_init(); 252 r8a7779_pm_init();
253 253
254 r8a7779_init_pm_domain(&r8a7779_sh4a); 254 r8a7779_init_pm_domains();
255 r8a7779_init_pm_domain(&r8a7779_sgx);
256 r8a7779_init_pm_domain(&r8a7779_vdp1);
257 r8a7779_init_pm_domain(&r8a7779_impx3);
258 255
259 platform_add_devices(r8a7779_early_devices, 256 platform_add_devices(r8a7779_early_devices,
260 ARRAY_SIZE(r8a7779_early_devices)); 257 ARRAY_SIZE(r8a7779_early_devices));
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index 838a87be1d5c..a07954fbcd22 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -1001,21 +1001,34 @@ static struct platform_device *sh7372_late_devices[] __initdata = {
1001 1001
1002void __init sh7372_add_standard_devices(void) 1002void __init sh7372_add_standard_devices(void)
1003{ 1003{
1004 rmobile_init_pm_domain(&sh7372_pd_a4lc); 1004 struct pm_domain_device domain_devices[] = {
1005 rmobile_init_pm_domain(&sh7372_pd_a4mp); 1005 { "A3RV", &vpu_device, },
1006 rmobile_init_pm_domain(&sh7372_pd_d4); 1006 { "A4MP", &spu0_device, },
1007 rmobile_init_pm_domain(&sh7372_pd_a4r); 1007 { "A4MP", &spu1_device, },
1008 rmobile_init_pm_domain(&sh7372_pd_a3rv); 1008 { "A3SP", &scif0_device, },
1009 rmobile_init_pm_domain(&sh7372_pd_a3ri); 1009 { "A3SP", &scif1_device, },
1010 rmobile_init_pm_domain(&sh7372_pd_a4s); 1010 { "A3SP", &scif2_device, },
1011 rmobile_init_pm_domain(&sh7372_pd_a3sp); 1011 { "A3SP", &scif3_device, },
1012 rmobile_init_pm_domain(&sh7372_pd_a3sg); 1012 { "A3SP", &scif4_device, },
1013 1013 { "A3SP", &scif5_device, },
1014 rmobile_pm_add_subdomain(&sh7372_pd_a4lc, &sh7372_pd_a3rv); 1014 { "A3SP", &scif6_device, },
1015 rmobile_pm_add_subdomain(&sh7372_pd_a4r, &sh7372_pd_a4lc); 1015 { "A3SP", &iic1_device, },
1016 1016 { "A3SP", &dma0_device, },
1017 rmobile_pm_add_subdomain(&sh7372_pd_a4s, &sh7372_pd_a3sg); 1017 { "A3SP", &dma1_device, },
1018 rmobile_pm_add_subdomain(&sh7372_pd_a4s, &sh7372_pd_a3sp); 1018 { "A3SP", &dma2_device, },
1019 { "A3SP", &usb_dma0_device, },
1020 { "A3SP", &usb_dma1_device, },
1021 { "A4R", &iic0_device, },
1022 { "A4R", &veu0_device, },
1023 { "A4R", &veu1_device, },
1024 { "A4R", &veu2_device, },
1025 { "A4R", &veu3_device, },
1026 { "A4R", &jpu_device, },
1027 { "A4R", &tmu00_device, },
1028 { "A4R", &tmu01_device, },
1029 };
1030
1031 sh7372_init_pm_domains();
1019 1032
1020 platform_add_devices(sh7372_early_devices, 1033 platform_add_devices(sh7372_early_devices,
1021 ARRAY_SIZE(sh7372_early_devices)); 1034 ARRAY_SIZE(sh7372_early_devices));
@@ -1023,30 +1036,8 @@ void __init sh7372_add_standard_devices(void)
1023 platform_add_devices(sh7372_late_devices, 1036 platform_add_devices(sh7372_late_devices,
1024 ARRAY_SIZE(sh7372_late_devices)); 1037 ARRAY_SIZE(sh7372_late_devices));
1025 1038
1026 rmobile_add_device_to_domain(&sh7372_pd_a3rv, &vpu_device); 1039 rmobile_add_devices_to_domains(domain_devices,
1027 rmobile_add_device_to_domain(&sh7372_pd_a4mp, &spu0_device); 1040 ARRAY_SIZE(domain_devices));
1028 rmobile_add_device_to_domain(&sh7372_pd_a4mp, &spu1_device);
1029 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif0_device);
1030 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif1_device);
1031 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif2_device);
1032 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif3_device);
1033 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif4_device);
1034 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif5_device);
1035 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif6_device);
1036 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &iic1_device);
1037 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &dma0_device);
1038 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &dma1_device);
1039 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &dma2_device);
1040 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usb_dma0_device);
1041 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usb_dma1_device);
1042 rmobile_add_device_to_domain(&sh7372_pd_a4r, &iic0_device);
1043 rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu0_device);
1044 rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu1_device);
1045 rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu2_device);
1046 rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu3_device);
1047 rmobile_add_device_to_domain(&sh7372_pd_a4r, &jpu_device);
1048 rmobile_add_device_to_domain(&sh7372_pd_a4r, &tmu00_device);
1049 rmobile_add_device_to_domain(&sh7372_pd_a4r, &tmu01_device);
1050} 1041}
1051 1042
1052static void __init sh7372_earlytimer_init(void) 1043static void __init sh7372_earlytimer_init(void)