aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2012-09-17 14:25:47 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2012-09-17 14:25:47 -0400
commitcf899680feb87af09ea18eea87aa03ea56afd9ba (patch)
tree8e61cfc66e74b21928cfd8d69584d3324e7c31c2
parentd6a56ae7ac6121ef99500b3380e98f83a3d9e102 (diff)
parentcaaca999d335872a53b3fff8fa5af2de794d16a1 (diff)
Merge branch 'pm-shmobile'
* pm-shmobile: ARM: shmobile: Add A4S cpuidle state on sh7372 ARM: shmobile: Make sh7372 cpuidle handling more straightforward ARM: shmobile: Move definition of shmobile_init_late() to header ARM: shmobile: Remove the console check from sh7372_enter_suspend() ARM: shmobile: Rework adding devices to PM domains on AP4EVB ARM: shmobile: Rework adding devices to PM domains on Mackerel ARM: shmobile: Specify device latencies for Mackerel devices directly ARM: shmobile: Specify device latencies for SH7372 devices directly ARM: shmobile: Allow device latencies to be specified directly ARM: shmobile: Set PM domain on/off latencies directly ARM: shmobile: Make rmobile_init_pm_domain() static ARM: shmobile: Move r8a7779's PM domain objects to a table ARM: shmobile: Move r8a7740's PM domain objects to a table ARM: shmobile: Move sh7372's PM domain objects to a table ARM: shmobile: Do not access sh7372 A4S domain internals directly ARM: shmobile: Add routine for automatic PM domains initialization ARM: shmobile: Use domain names when adding subdomains to power domains ARM: shmobile: Drop r8a7779_add_device_to_domain() ARM: shmobile: Use names of power domains for adding devices to them
-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 f172ca85905c..264340a60f65 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -1229,6 +1229,15 @@ static struct i2c_board_info i2c1_devices[] = {
1229#define USCCR1 0xE6058144 1229#define USCCR1 0xE6058144
1230static void __init ap4evb_init(void) 1230static void __init ap4evb_init(void)
1231{ 1231{
1232 struct pm_domain_device domain_devices[] = {
1233 { "A4LC", &lcdc1_device, },
1234 { "A4LC", &lcdc_device, },
1235 { "A4MP", &fsi_device, },
1236 { "A3SP", &sh_mmcif_device, },
1237 { "A3SP", &sdhi0_device, },
1238 { "A3SP", &sdhi1_device, },
1239 { "A4R", &ceu_device, },
1240 };
1232 u32 srcr4; 1241 u32 srcr4;
1233 struct clk *clk; 1242 struct clk *clk;
1234 1243
@@ -1461,14 +1470,8 @@ static void __init ap4evb_init(void)
1461 1470
1462 platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices)); 1471 platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices));
1463 1472
1464 rmobile_add_device_to_domain(&sh7372_pd_a4lc, &lcdc1_device); 1473 rmobile_add_devices_to_domains(domain_devices,
1465 rmobile_add_device_to_domain(&sh7372_pd_a4lc, &lcdc_device); 1474 ARRAY_SIZE(domain_devices));
1466 rmobile_add_device_to_domain(&sh7372_pd_a4mp, &fsi_device);
1467
1468 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sh_mmcif_device);
1469 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi0_device);
1470 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi1_device);
1471 rmobile_add_device_to_domain(&sh7372_pd_a4r, &ceu_device);
1472 1475
1473 hdmi_init_pm_clock(); 1476 hdmi_init_pm_clock();
1474 fsi_init_pm_clock(); 1477 fsi_init_pm_clock();
@@ -1483,6 +1486,6 @@ MACHINE_START(AP4EVB, "ap4evb")
1483 .init_irq = sh7372_init_irq, 1486 .init_irq = sh7372_init_irq,
1484 .handle_irq = shmobile_handle_irq_intc, 1487 .handle_irq = shmobile_handle_irq_intc,
1485 .init_machine = ap4evb_init, 1488 .init_machine = ap4evb_init,
1486 .init_late = shmobile_init_late, 1489 .init_late = sh7372_pm_init_late,
1487 .timer = &shmobile_timer, 1490 .timer = &shmobile_timer,
1488MACHINE_END 1491MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
index 453a6e50db8b..da6117c326b9 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -1182,10 +1182,10 @@ static void __init eva_init(void)
1182 1182
1183 eva_clock_init(); 1183 eva_clock_init();
1184 1184
1185 rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &lcdc0_device); 1185 rmobile_add_device_to_domain("A4LC", &lcdc0_device);
1186 rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &hdmi_lcdc_device); 1186 rmobile_add_device_to_domain("A4LC", &hdmi_lcdc_device);
1187 if (usb) 1187 if (usb)
1188 rmobile_add_device_to_domain(&r8a7740_pd_a3sp, usb); 1188 rmobile_add_device_to_domain("A3SP", usb);
1189} 1189}
1190 1190
1191static void __init eva_earlytimer_init(void) 1191static 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 c129542f6aed..c76776a3e70d 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -1410,6 +1410,22 @@ static struct i2c_board_info i2c1_devices[] = {
1410#define USCCR1 0xE6058144 1410#define USCCR1 0xE6058144
1411static void __init mackerel_init(void) 1411static void __init mackerel_init(void)
1412{ 1412{
1413 struct pm_domain_device domain_devices[] = {
1414 { "A4LC", &lcdc_device, },
1415 { "A4LC", &hdmi_lcdc_device, },
1416 { "A4LC", &meram_device, },
1417 { "A4MP", &fsi_device, },
1418 { "A3SP", &usbhs0_device, },
1419 { "A3SP", &usbhs1_device, },
1420 { "A3SP", &nand_flash_device, },
1421 { "A3SP", &sh_mmcif_device, },
1422 { "A3SP", &sdhi0_device, },
1423#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
1424 { "A3SP", &sdhi1_device, },
1425#endif
1426 { "A3SP", &sdhi2_device, },
1427 { "A4R", &ceu_device, },
1428 };
1413 u32 srcr4; 1429 u32 srcr4;
1414 struct clk *clk; 1430 struct clk *clk;
1415 1431
@@ -1624,20 +1640,8 @@ static void __init mackerel_init(void)
1624 1640
1625 platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices)); 1641 platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices));
1626 1642
1627 rmobile_add_device_to_domain(&sh7372_pd_a4lc, &lcdc_device); 1643 rmobile_add_devices_to_domains(domain_devices,
1628 rmobile_add_device_to_domain(&sh7372_pd_a4lc, &hdmi_lcdc_device); 1644 ARRAY_SIZE(domain_devices));
1629 rmobile_add_device_to_domain(&sh7372_pd_a4lc, &meram_device);
1630 rmobile_add_device_to_domain(&sh7372_pd_a4mp, &fsi_device);
1631 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usbhs0_device);
1632 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usbhs1_device);
1633 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &nand_flash_device);
1634 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sh_mmcif_device);
1635 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi0_device);
1636#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
1637 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi1_device);
1638#endif
1639 rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi2_device);
1640 rmobile_add_device_to_domain(&sh7372_pd_a4r, &ceu_device);
1641 1645
1642 hdmi_init_pm_clock(); 1646 hdmi_init_pm_clock();
1643 sh7372_pm_init(); 1647 sh7372_pm_init();
@@ -1651,6 +1655,6 @@ MACHINE_START(MACKEREL, "mackerel")
1651 .init_irq = sh7372_init_irq, 1655 .init_irq = sh7372_init_irq,
1652 .handle_irq = shmobile_handle_irq_intc, 1656 .handle_irq = shmobile_handle_irq_intc,
1653 .init_machine = mackerel_init, 1657 .init_machine = mackerel_init,
1654 .init_late = shmobile_init_late, 1658 .init_late = sh7372_pm_init_late,
1655 .timer = &shmobile_timer, 1659 .timer = &shmobile_timer,
1656MACHINE_END 1660MACHINE_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 45e61dada030..eb89293fff4d 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -14,8 +14,10 @@ extern int shmobile_clk_init(void);
14extern void shmobile_handle_irq_intc(struct pt_regs *); 14extern void shmobile_handle_irq_intc(struct pt_regs *);
15extern struct platform_suspend_ops shmobile_suspend_ops; 15extern struct platform_suspend_ops shmobile_suspend_ops;
16struct cpuidle_driver; 16struct cpuidle_driver;
17extern void (*shmobile_cpuidle_modes[])(void); 17struct cpuidle_device;
18extern void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv); 18extern int shmobile_enter_wfi(struct cpuidle_device *dev,
19 struct cpuidle_driver *drv, int index);
20extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv);
19 21
20extern void sh7367_init_irq(void); 22extern void sh7367_init_irq(void);
21extern void sh7367_map_io(void); 23extern void sh7367_map_io(void);
@@ -86,8 +88,6 @@ extern int r8a7779_boot_secondary(unsigned int cpu);
86extern void r8a7779_smp_prepare_cpus(void); 88extern void r8a7779_smp_prepare_cpus(void);
87extern void r8a7779_register_twd(void); 89extern void r8a7779_register_twd(void);
88 90
89extern void shmobile_init_late(void);
90
91#ifdef CONFIG_SUSPEND 91#ifdef CONFIG_SUSPEND
92int shmobile_suspend_init(void); 92int shmobile_suspend_init(void);
93#else 93#else
@@ -100,4 +100,10 @@ int shmobile_cpuidle_init(void);
100static inline int shmobile_cpuidle_init(void) { return 0; } 100static inline int shmobile_cpuidle_init(void) { return 0; }
101#endif 101#endif
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 b07ad318eb2e..7ad47977d2e7 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
363#endif /* __ASM_R8A7779_H__ */ 355#endif /* __ASM_R8A7779_H__ */
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 a8562540f1d6..d37d368434da 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 792037069226..a7a5e20ae9a0 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>
@@ -71,20 +72,7 @@
71 72
72#ifdef CONFIG_PM 73#ifdef CONFIG_PM
73 74
74struct rmobile_pm_domain sh7372_pd_a4lc = { 75#define PM_DOMAIN_ON_OFF_LATENCY_NS 250000
75 .genpd.name = "A4LC",
76 .bit_shift = 1,
77};
78
79struct rmobile_pm_domain sh7372_pd_a4mp = {
80 .genpd.name = "A4MP",
81 .bit_shift = 2,
82};
83
84struct rmobile_pm_domain sh7372_pd_d4 = {
85 .genpd.name = "D4",
86 .bit_shift = 3,
87};
88 76
89static int sh7372_a4r_pd_suspend(void) 77static int sh7372_a4r_pd_suspend(void)
90{ 78{
@@ -93,39 +81,25 @@ static int sh7372_a4r_pd_suspend(void)
93 return 0; 81 return 0;
94} 82}
95 83
96struct rmobile_pm_domain sh7372_pd_a4r = { 84static bool a4s_suspend_ready;
97 .genpd.name = "A4R",
98 .bit_shift = 5,
99 .suspend = sh7372_a4r_pd_suspend,
100 .resume = sh7372_intcs_resume,
101};
102 85
103struct rmobile_pm_domain sh7372_pd_a3rv = { 86static int sh7372_a4s_pd_suspend(void)
104 .genpd.name = "A3RV",
105 .bit_shift = 6,
106};
107
108struct rmobile_pm_domain sh7372_pd_a3ri = {
109 .genpd.name = "A3RI",
110 .bit_shift = 8,
111};
112
113static int sh7372_pd_a4s_suspend(void)
114{ 87{
115 /* 88 /*
116 * The A4S domain contains the CPU core and therefore it should 89 * The A4S domain contains the CPU core and therefore it should
117 * only be turned off if the CPU is in use. 90 * only be turned off if the CPU is not in use. This may happen
91 * during system suspend, when SYSC is going to be used for generating
92 * resume signals and a4s_suspend_ready is set to let
93 * sh7372_enter_suspend() know that it can turn A4S off.
118 */ 94 */
95 a4s_suspend_ready = true;
119 return -EBUSY; 96 return -EBUSY;
120} 97}
121 98
122struct rmobile_pm_domain sh7372_pd_a4s = { 99static void sh7372_a4s_pd_resume(void)
123 .genpd.name = "A4S", 100{
124 .bit_shift = 10, 101 a4s_suspend_ready = false;
125 .gov = &pm_domain_always_on_gov, 102}
126 .no_debug = true,
127 .suspend = sh7372_pd_a4s_suspend,
128};
129 103
130static int sh7372_a3sp_pd_suspend(void) 104static int sh7372_a3sp_pd_suspend(void)
131{ 105{
@@ -136,18 +110,80 @@ static int sh7372_a3sp_pd_suspend(void)
136 return console_suspend_enabled ? 0 : -EBUSY; 110 return console_suspend_enabled ? 0 : -EBUSY;
137} 111}
138 112
139struct rmobile_pm_domain sh7372_pd_a3sp = { 113static struct rmobile_pm_domain sh7372_pm_domains[] = {
140 .genpd.name = "A3SP", 114 {
141 .bit_shift = 11, 115 .genpd.name = "A4LC",
142 .gov = &pm_domain_always_on_gov, 116 .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
143 .no_debug = true, 117 .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
144 .suspend = sh7372_a3sp_pd_suspend, 118 .bit_shift = 1,
119 },
120 {
121 .genpd.name = "A4MP",
122 .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
123 .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
124 .bit_shift = 2,
125 },
126 {
127 .genpd.name = "D4",
128 .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
129 .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
130 .bit_shift = 3,
131 },
132 {
133 .genpd.name = "A4R",
134 .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
135 .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
136 .bit_shift = 5,
137 .suspend = sh7372_a4r_pd_suspend,
138 .resume = sh7372_intcs_resume,
139 },
140 {
141 .genpd.name = "A3RV",
142 .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
143 .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
144 .bit_shift = 6,
145 },
146 {
147 .genpd.name = "A3RI",
148 .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
149 .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
150 .bit_shift = 8,
151 },
152 {
153 .genpd.name = "A4S",
154 .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
155 .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
156 .bit_shift = 10,
157 .gov = &pm_domain_always_on_gov,
158 .no_debug = true,
159 .suspend = sh7372_a4s_pd_suspend,
160 .resume = sh7372_a4s_pd_resume,
161 },
162 {
163 .genpd.name = "A3SP",
164 .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
165 .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
166 .bit_shift = 11,
167 .gov = &pm_domain_always_on_gov,
168 .no_debug = true,
169 .suspend = sh7372_a3sp_pd_suspend,
170 },
171 {
172 .genpd.name = "A3SG",
173 .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
174 .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
175 .bit_shift = 13,
176 },
145}; 177};
146 178
147struct rmobile_pm_domain sh7372_pd_a3sg = { 179void __init sh7372_init_pm_domains(void)
148 .genpd.name = "A3SG", 180{
149 .bit_shift = 13, 181 rmobile_init_domains(sh7372_pm_domains, ARRAY_SIZE(sh7372_pm_domains));
150}; 182 pm_genpd_add_subdomain_names("A4LC", "A3RV");
183 pm_genpd_add_subdomain_names("A4R", "A4LC");
184 pm_genpd_add_subdomain_names("A4S", "A3SG");
185 pm_genpd_add_subdomain_names("A4S", "A3SP");
186}
151 187
152#endif /* CONFIG_PM */ 188#endif /* CONFIG_PM */
153 189
@@ -303,6 +339,21 @@ static void sh7372_enter_a3sm_common(int pllc0_on)
303 sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); 339 sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc));
304 sh7372_enter_sysc(pllc0_on, 1 << 12); 340 sh7372_enter_sysc(pllc0_on, 1 << 12);
305} 341}
342
343static void sh7372_enter_a4s_common(int pllc0_on)
344{
345 sh7372_intca_suspend();
346 sh7372_set_reset_vector(SMFRAM);
347 sh7372_enter_sysc(pllc0_on, 1 << 10);
348 sh7372_intca_resume();
349}
350
351static void sh7372_pm_setup_smfram(void)
352{
353 memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100);
354}
355#else
356static inline void sh7372_pm_setup_smfram(void) {}
306#endif /* CONFIG_SUSPEND || CONFIG_CPU_IDLE */ 357#endif /* CONFIG_SUSPEND || CONFIG_CPU_IDLE */
307 358
308#ifdef CONFIG_CPU_IDLE 359#ifdef CONFIG_CPU_IDLE
@@ -312,7 +363,8 @@ static int sh7372_do_idle_core_standby(unsigned long unused)
312 return 0; 363 return 0;
313} 364}
314 365
315static void sh7372_enter_core_standby(void) 366static int sh7372_enter_core_standby(struct cpuidle_device *dev,
367 struct cpuidle_driver *drv, int index)
316{ 368{
317 sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); 369 sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc));
318 370
@@ -323,83 +375,102 @@ static void sh7372_enter_core_standby(void)
323 375
324 /* disable reset vector translation */ 376 /* disable reset vector translation */
325 __raw_writel(0, SBAR); 377 __raw_writel(0, SBAR);
378
379 return 1;
326} 380}
327 381
328static void sh7372_enter_a3sm_pll_on(void) 382static int sh7372_enter_a3sm_pll_on(struct cpuidle_device *dev,
383 struct cpuidle_driver *drv, int index)
329{ 384{
330 sh7372_enter_a3sm_common(1); 385 sh7372_enter_a3sm_common(1);
386 return 2;
331} 387}
332 388
333static void sh7372_enter_a3sm_pll_off(void) 389static int sh7372_enter_a3sm_pll_off(struct cpuidle_device *dev,
390 struct cpuidle_driver *drv, int index)
334{ 391{
335 sh7372_enter_a3sm_common(0); 392 sh7372_enter_a3sm_common(0);
393 return 3;
336} 394}
337 395
338static void sh7372_cpuidle_setup(struct cpuidle_driver *drv) 396static int sh7372_enter_a4s(struct cpuidle_device *dev,
397 struct cpuidle_driver *drv, int index)
339{ 398{
340 struct cpuidle_state *state = &drv->states[drv->state_count]; 399 unsigned long msk, msk2;
341 400
342 snprintf(state->name, CPUIDLE_NAME_LEN, "C2"); 401 if (!sh7372_sysc_valid(&msk, &msk2))
343 strncpy(state->desc, "Core Standby Mode", CPUIDLE_DESC_LEN); 402 return sh7372_enter_a3sm_pll_off(dev, drv, index);
344 state->exit_latency = 10; 403
345 state->target_residency = 20 + 10; 404 sh7372_setup_sysc(msk, msk2);
346 state->flags = CPUIDLE_FLAG_TIME_VALID; 405 sh7372_enter_a4s_common(0);
347 shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_core_standby; 406 return 4;
348 drv->state_count++;
349
350 state = &drv->states[drv->state_count];
351 snprintf(state->name, CPUIDLE_NAME_LEN, "C3");
352 strncpy(state->desc, "A3SM PLL ON", CPUIDLE_DESC_LEN);
353 state->exit_latency = 20;
354 state->target_residency = 30 + 20;
355 state->flags = CPUIDLE_FLAG_TIME_VALID;
356 shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_a3sm_pll_on;
357 drv->state_count++;
358
359 state = &drv->states[drv->state_count];
360 snprintf(state->name, CPUIDLE_NAME_LEN, "C4");
361 strncpy(state->desc, "A3SM PLL OFF", CPUIDLE_DESC_LEN);
362 state->exit_latency = 120;
363 state->target_residency = 30 + 120;
364 state->flags = CPUIDLE_FLAG_TIME_VALID;
365 shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_a3sm_pll_off;
366 drv->state_count++;
367} 407}
368 408
409static struct cpuidle_driver sh7372_cpuidle_driver = {
410 .name = "sh7372_cpuidle",
411 .owner = THIS_MODULE,
412 .en_core_tk_irqen = 1,
413 .state_count = 5,
414 .safe_state_index = 0, /* C1 */
415 .states[0] = ARM_CPUIDLE_WFI_STATE,
416 .states[0].enter = shmobile_enter_wfi,
417 .states[1] = {
418 .name = "C2",
419 .desc = "Core Standby Mode",
420 .exit_latency = 10,
421 .target_residency = 20 + 10,
422 .flags = CPUIDLE_FLAG_TIME_VALID,
423 .enter = sh7372_enter_core_standby,
424 },
425 .states[2] = {
426 .name = "C3",
427 .desc = "A3SM PLL ON",
428 .exit_latency = 20,
429 .target_residency = 30 + 20,
430 .flags = CPUIDLE_FLAG_TIME_VALID,
431 .enter = sh7372_enter_a3sm_pll_on,
432 },
433 .states[3] = {
434 .name = "C4",
435 .desc = "A3SM PLL OFF",
436 .exit_latency = 120,
437 .target_residency = 30 + 120,
438 .flags = CPUIDLE_FLAG_TIME_VALID,
439 .enter = sh7372_enter_a3sm_pll_off,
440 },
441 .states[4] = {
442 .name = "C5",
443 .desc = "A4S PLL OFF",
444 .exit_latency = 240,
445 .target_residency = 30 + 240,
446 .flags = CPUIDLE_FLAG_TIME_VALID,
447 .enter = sh7372_enter_a4s,
448 .disabled = true,
449 },
450};
451
369static void sh7372_cpuidle_init(void) 452static void sh7372_cpuidle_init(void)
370{ 453{
371 shmobile_cpuidle_setup = sh7372_cpuidle_setup; 454 shmobile_cpuidle_set_driver(&sh7372_cpuidle_driver);
372} 455}
373#else 456#else
374static void sh7372_cpuidle_init(void) {} 457static void sh7372_cpuidle_init(void) {}
375#endif 458#endif
376 459
377#ifdef CONFIG_SUSPEND 460#ifdef CONFIG_SUSPEND
378static void sh7372_enter_a4s_common(int pllc0_on)
379{
380 sh7372_intca_suspend();
381 memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100);
382 sh7372_set_reset_vector(SMFRAM);
383 sh7372_enter_sysc(pllc0_on, 1 << 10);
384 sh7372_intca_resume();
385}
386
387static int sh7372_enter_suspend(suspend_state_t suspend_state) 461static int sh7372_enter_suspend(suspend_state_t suspend_state)
388{ 462{
389 unsigned long msk, msk2; 463 unsigned long msk, msk2;
390 464
391 /* check active clocks to determine potential wakeup sources */ 465 /* check active clocks to determine potential wakeup sources */
392 if (sh7372_sysc_valid(&msk, &msk2)) { 466 if (sh7372_sysc_valid(&msk, &msk2) && a4s_suspend_ready) {
393 if (!console_suspend_enabled && 467 /* convert INTC mask/sense to SYSC mask/sense */
394 sh7372_pd_a4s.genpd.status == GPD_STATE_POWER_OFF) { 468 sh7372_setup_sysc(msk, msk2);
395 /* convert INTC mask/sense to SYSC mask/sense */ 469
396 sh7372_setup_sysc(msk, msk2); 470 /* enter A4S sleep with PLLC0 off */
397 471 pr_debug("entering A4S\n");
398 /* enter A4S sleep with PLLC0 off */ 472 sh7372_enter_a4s_common(0);
399 pr_debug("entering A4S\n"); 473 return 0;
400 sh7372_enter_a4s_common(0);
401 return 0;
402 }
403 } 474 }
404 475
405 /* default to enter A3SM sleep with PLLC0 off */ 476 /* default to enter A3SM sleep with PLLC0 off */
@@ -425,7 +496,7 @@ static int sh7372_pm_notifier_fn(struct notifier_block *notifier,
425 * executed during system suspend and resume, respectively, so 496 * executed during system suspend and resume, respectively, so
426 * that those functions don't crash while accessing the INTCS. 497 * that those functions don't crash while accessing the INTCS.
427 */ 498 */
428 pm_genpd_poweron(&sh7372_pd_a4r.genpd); 499 pm_genpd_name_poweron("A4R");
429 break; 500 break;
430 case PM_POST_SUSPEND: 501 case PM_POST_SUSPEND:
431 pm_genpd_poweroff_unused(); 502 pm_genpd_poweroff_unused();
@@ -454,6 +525,14 @@ void __init sh7372_pm_init(void)
454 /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */ 525 /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */
455 __raw_writel(0, PDNSEL); 526 __raw_writel(0, PDNSEL);
456 527
528 sh7372_pm_setup_smfram();
529
457 sh7372_suspend_init(); 530 sh7372_suspend_init();
458 sh7372_cpuidle_init(); 531 sh7372_cpuidle_init();
459} 532}
533
534void __init sh7372_pm_init_late(void)
535{
536 shmobile_init_late();
537 pm_genpd_name_attach_cpuidle("A4S", 4);
538}
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)