diff options
-rw-r--r-- | arch/arm/mach-exynos/common.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-exynos/exynos.c | 23 | ||||
-rw-r--r-- | arch/arm/mach-exynos/pmu.c | 192 | ||||
-rw-r--r-- | arch/arm/mach-exynos/regs-pmu.h | 128 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-exynos5440.c | 29 |
5 files changed, 347 insertions, 26 deletions
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 431be1bca2e8..865f878063cc 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h | |||
@@ -12,7 +12,6 @@ | |||
12 | #ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H | 12 | #ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H |
13 | #define __ARCH_ARM_MACH_EXYNOS_COMMON_H | 13 | #define __ARCH_ARM_MACH_EXYNOS_COMMON_H |
14 | 14 | ||
15 | #include <linux/reboot.h> | ||
16 | #include <linux/of.h> | 15 | #include <linux/of.h> |
17 | 16 | ||
18 | #define EXYNOS3250_SOC_ID 0xE3472000 | 17 | #define EXYNOS3250_SOC_ID 0xE3472000 |
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index 6dc332fa55db..80d744db7dc7 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c | |||
@@ -137,28 +137,6 @@ static struct map_desc exynos5_iodesc[] __initdata = { | |||
137 | }, | 137 | }, |
138 | }; | 138 | }; |
139 | 139 | ||
140 | static void exynos_restart(enum reboot_mode mode, const char *cmd) | ||
141 | { | ||
142 | struct device_node *np; | ||
143 | u32 val = 0x1; | ||
144 | void __iomem *addr = pmu_base_addr + EXYNOS_SWRESET; | ||
145 | |||
146 | if (of_machine_is_compatible("samsung,exynos5440")) { | ||
147 | u32 status; | ||
148 | np = of_find_compatible_node(NULL, NULL, "samsung,exynos5440-clock"); | ||
149 | |||
150 | addr = of_iomap(np, 0) + 0xbc; | ||
151 | status = __raw_readl(addr); | ||
152 | |||
153 | addr = of_iomap(np, 0) + 0xcc; | ||
154 | val = __raw_readl(addr); | ||
155 | |||
156 | val = (val & 0xffff0000) | (status & 0xffff); | ||
157 | } | ||
158 | |||
159 | __raw_writel(val, addr); | ||
160 | } | ||
161 | |||
162 | static struct platform_device exynos_cpuidle = { | 140 | static struct platform_device exynos_cpuidle = { |
163 | .name = "exynos_cpuidle", | 141 | .name = "exynos_cpuidle", |
164 | #ifdef CONFIG_ARM_EXYNOS_CPUIDLE | 142 | #ifdef CONFIG_ARM_EXYNOS_CPUIDLE |
@@ -383,7 +361,6 @@ DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)") | |||
383 | .init_machine = exynos_dt_machine_init, | 361 | .init_machine = exynos_dt_machine_init, |
384 | .init_late = exynos_init_late, | 362 | .init_late = exynos_init_late, |
385 | .dt_compat = exynos_dt_compat, | 363 | .dt_compat = exynos_dt_compat, |
386 | .restart = exynos_restart, | ||
387 | .reserve = exynos_reserve, | 364 | .reserve = exynos_reserve, |
388 | .dt_fixup = exynos_dt_fixup, | 365 | .dt_fixup = exynos_dt_fixup, |
389 | MACHINE_END | 366 | MACHINE_END |
diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c index 6c8a76dd5494..c15761ca2f18 100644 --- a/arch/arm/mach-exynos/pmu.c +++ b/arch/arm/mach-exynos/pmu.c | |||
@@ -11,8 +11,11 @@ | |||
11 | 11 | ||
12 | #include <linux/io.h> | 12 | #include <linux/io.h> |
13 | #include <linux/of.h> | 13 | #include <linux/of.h> |
14 | #include <linux/of_address.h> | ||
14 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
15 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/notifier.h> | ||
18 | #include <linux/reboot.h> | ||
16 | 19 | ||
17 | 20 | ||
18 | #include "exynos-pmu.h" | 21 | #include "exynos-pmu.h" |
@@ -22,7 +25,7 @@ | |||
22 | 25 | ||
23 | struct exynos_pmu_conf { | 26 | struct exynos_pmu_conf { |
24 | unsigned int offset; | 27 | unsigned int offset; |
25 | unsigned int val[NUM_SYS_POWERDOWN]; | 28 | u8 val[NUM_SYS_POWERDOWN]; |
26 | }; | 29 | }; |
27 | 30 | ||
28 | struct exynos_pmu_data { | 31 | struct exynos_pmu_data { |
@@ -31,6 +34,7 @@ struct exynos_pmu_data { | |||
31 | 34 | ||
32 | void (*pmu_init)(void); | 35 | void (*pmu_init)(void); |
33 | void (*powerdown_conf)(enum sys_powerdown); | 36 | void (*powerdown_conf)(enum sys_powerdown); |
37 | void (*powerdown_conf_extra)(enum sys_powerdown); | ||
34 | }; | 38 | }; |
35 | 39 | ||
36 | struct exynos_pmu_context { | 40 | struct exynos_pmu_context { |
@@ -51,6 +55,92 @@ static inline u32 pmu_raw_readl(u32 offset) | |||
51 | return readl_relaxed(pmu_base_addr + offset); | 55 | return readl_relaxed(pmu_base_addr + offset); |
52 | } | 56 | } |
53 | 57 | ||
58 | static struct exynos_pmu_conf exynos3250_pmu_config[] = { | ||
59 | /* { .offset = offset, .val = { AFTR, W-AFTR, SLEEP } */ | ||
60 | { EXYNOS3_ARM_CORE0_SYS_PWR_REG, { 0x0, 0x0, 0x2} }, | ||
61 | { EXYNOS3_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} }, | ||
62 | { EXYNOS3_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} }, | ||
63 | { EXYNOS3_ARM_CORE1_SYS_PWR_REG, { 0x0, 0x0, 0x2} }, | ||
64 | { EXYNOS3_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} }, | ||
65 | { EXYNOS3_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} }, | ||
66 | { EXYNOS3_ISP_ARM_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
67 | { EXYNOS3_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} }, | ||
68 | { EXYNOS3_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} }, | ||
69 | { EXYNOS3_ARM_COMMON_SYS_PWR_REG, { 0x0, 0x0, 0x2} }, | ||
70 | { EXYNOS3_ARM_L2_SYS_PWR_REG, { 0x0, 0x0, 0x3} }, | ||
71 | { EXYNOS3_CMU_ACLKSTOP_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
72 | { EXYNOS3_CMU_SCLKSTOP_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
73 | { EXYNOS3_CMU_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
74 | { EXYNOS3_DRAM_FREQ_DOWN_SYS_PWR_REG, { 0x1, 0x1, 0x1} }, | ||
75 | { EXYNOS3_DDRPHY_DLLOFF_SYS_PWR_REG, { 0x1, 0x1, 0x1} }, | ||
76 | { EXYNOS3_LPDDR_PHY_DLL_LOCK_SYS_PWR_REG, { 0x1, 0x1, 0x1} }, | ||
77 | { EXYNOS3_CMU_ACLKSTOP_COREBLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
78 | { EXYNOS3_CMU_SCLKSTOP_COREBLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
79 | { EXYNOS3_CMU_RESET_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
80 | { EXYNOS3_APLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
81 | { EXYNOS3_MPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
82 | { EXYNOS3_BPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
83 | { EXYNOS3_VPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
84 | { EXYNOS3_EPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
85 | { EXYNOS3_UPLL_SYSCLK_SYS_PWR_REG, { 0x1, 0x1, 0x1} }, | ||
86 | { EXYNOS3_EPLLUSER_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
87 | { EXYNOS3_MPLLUSER_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
88 | { EXYNOS3_BPLLUSER_SYSCLK_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
89 | { EXYNOS3_CMU_CLKSTOP_CAM_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
90 | { EXYNOS3_CMU_CLKSTOP_MFC_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
91 | { EXYNOS3_CMU_CLKSTOP_G3D_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
92 | { EXYNOS3_CMU_CLKSTOP_LCD0_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
93 | { EXYNOS3_CMU_CLKSTOP_ISP_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
94 | { EXYNOS3_CMU_CLKSTOP_MAUDIO_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
95 | { EXYNOS3_CMU_RESET_CAM_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
96 | { EXYNOS3_CMU_RESET_MFC_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
97 | { EXYNOS3_CMU_RESET_G3D_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
98 | { EXYNOS3_CMU_RESET_LCD0_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
99 | { EXYNOS3_CMU_RESET_ISP_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
100 | { EXYNOS3_CMU_RESET_MAUDIO_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
101 | { EXYNOS3_TOP_BUS_SYS_PWR_REG, { 0x3, 0x0, 0x0} }, | ||
102 | { EXYNOS3_TOP_RETENTION_SYS_PWR_REG, { 0x1, 0x1, 0x1} }, | ||
103 | { EXYNOS3_TOP_PWR_SYS_PWR_REG, { 0x3, 0x3, 0x3} }, | ||
104 | { EXYNOS3_TOP_BUS_COREBLK_SYS_PWR_REG, { 0x3, 0x0, 0x0} }, | ||
105 | { EXYNOS3_TOP_RETENTION_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x1} }, | ||
106 | { EXYNOS3_TOP_PWR_COREBLK_SYS_PWR_REG, { 0x3, 0x3, 0x3} }, | ||
107 | { EXYNOS3_LOGIC_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
108 | { EXYNOS3_OSCCLK_GATE_SYS_PWR_REG, { 0x1, 0x1, 0x1} }, | ||
109 | { EXYNOS3_LOGIC_RESET_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
110 | { EXYNOS3_OSCCLK_GATE_COREBLK_SYS_PWR_REG, { 0x1, 0x0, 0x1} }, | ||
111 | { EXYNOS3_PAD_RETENTION_DRAM_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
112 | { EXYNOS3_PAD_RETENTION_MAUDIO_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
113 | { EXYNOS3_PAD_RETENTION_GPIO_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
114 | { EXYNOS3_PAD_RETENTION_UART_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
115 | { EXYNOS3_PAD_RETENTION_MMC0_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
116 | { EXYNOS3_PAD_RETENTION_MMC1_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
117 | { EXYNOS3_PAD_RETENTION_MMC2_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
118 | { EXYNOS3_PAD_RETENTION_SPI_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
119 | { EXYNOS3_PAD_RETENTION_EBIA_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
120 | { EXYNOS3_PAD_RETENTION_EBIB_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
121 | { EXYNOS3_PAD_RETENTION_JTAG_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
122 | { EXYNOS3_PAD_ISOLATION_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
123 | { EXYNOS3_PAD_ALV_SEL_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
124 | { EXYNOS3_XUSBXTI_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
125 | { EXYNOS3_XXTI_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
126 | { EXYNOS3_EXT_REGULATOR_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
127 | { EXYNOS3_EXT_REGULATOR_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
128 | { EXYNOS3_GPIO_MODE_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
129 | { EXYNOS3_GPIO_MODE_MAUDIO_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
130 | { EXYNOS3_TOP_ASB_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
131 | { EXYNOS3_TOP_ASB_ISOLATION_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
132 | { EXYNOS3_TOP_ASB_RESET_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
133 | { EXYNOS3_TOP_ASB_ISOLATION_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, | ||
134 | { EXYNOS3_CAM_SYS_PWR_REG, { 0x7, 0x0, 0x0} }, | ||
135 | { EXYNOS3_MFC_SYS_PWR_REG, { 0x7, 0x0, 0x0} }, | ||
136 | { EXYNOS3_G3D_SYS_PWR_REG, { 0x7, 0x0, 0x0} }, | ||
137 | { EXYNOS3_LCD0_SYS_PWR_REG, { 0x7, 0x0, 0x0} }, | ||
138 | { EXYNOS3_ISP_SYS_PWR_REG, { 0x7, 0x0, 0x0} }, | ||
139 | { EXYNOS3_MAUDIO_SYS_PWR_REG, { 0x7, 0x0, 0x0} }, | ||
140 | { EXYNOS3_CMU_SYSCLK_ISP_SYS_PWR_REG, { 0x1, 0x0, 0x0} }, | ||
141 | { PMU_TABLE_END,}, | ||
142 | }; | ||
143 | |||
54 | static const struct exynos_pmu_conf exynos4210_pmu_config[] = { | 144 | static const struct exynos_pmu_conf exynos4210_pmu_config[] = { |
55 | /* { .offset = offset, .val = { AFTR, LPA, SLEEP } */ | 145 | /* { .offset = offset, .val = { AFTR, LPA, SLEEP } */ |
56 | { S5P_ARM_CORE0_LOWPWR, { 0x0, 0x0, 0x2 } }, | 146 | { S5P_ARM_CORE0_LOWPWR, { 0x0, 0x0, 0x2 } }, |
@@ -495,6 +585,44 @@ static struct exynos_pmu_conf exynos5420_pmu_config[] = { | |||
495 | { PMU_TABLE_END,}, | 585 | { PMU_TABLE_END,}, |
496 | }; | 586 | }; |
497 | 587 | ||
588 | static unsigned int const exynos3250_list_feed[] = { | ||
589 | EXYNOS3_ARM_CORE_OPTION(0), | ||
590 | EXYNOS3_ARM_CORE_OPTION(1), | ||
591 | EXYNOS3_ARM_CORE_OPTION(2), | ||
592 | EXYNOS3_ARM_CORE_OPTION(3), | ||
593 | EXYNOS3_ARM_COMMON_OPTION, | ||
594 | EXYNOS3_TOP_PWR_OPTION, | ||
595 | EXYNOS3_CORE_TOP_PWR_OPTION, | ||
596 | S5P_CAM_OPTION, | ||
597 | S5P_MFC_OPTION, | ||
598 | S5P_G3D_OPTION, | ||
599 | S5P_LCD0_OPTION, | ||
600 | S5P_ISP_OPTION, | ||
601 | }; | ||
602 | |||
603 | static void exynos3250_powerdown_conf_extra(enum sys_powerdown mode) | ||
604 | { | ||
605 | unsigned int i; | ||
606 | unsigned int tmp; | ||
607 | |||
608 | /* Enable only SC_FEEDBACK */ | ||
609 | for (i = 0; i < ARRAY_SIZE(exynos3250_list_feed); i++) { | ||
610 | tmp = pmu_raw_readl(exynos3250_list_feed[i]); | ||
611 | tmp &= ~(EXYNOS3_OPTION_USE_SC_COUNTER); | ||
612 | tmp |= EXYNOS3_OPTION_USE_SC_FEEDBACK; | ||
613 | pmu_raw_writel(tmp, exynos3250_list_feed[i]); | ||
614 | } | ||
615 | |||
616 | if (mode != SYS_SLEEP) | ||
617 | return; | ||
618 | |||
619 | pmu_raw_writel(XUSBXTI_DURATION, EXYNOS3_XUSBXTI_DURATION); | ||
620 | pmu_raw_writel(XXTI_DURATION, EXYNOS3_XXTI_DURATION); | ||
621 | pmu_raw_writel(EXT_REGULATOR_DURATION, EXYNOS3_EXT_REGULATOR_DURATION); | ||
622 | pmu_raw_writel(EXT_REGULATOR_COREBLK_DURATION, | ||
623 | EXYNOS3_EXT_REGULATOR_COREBLK_DURATION); | ||
624 | } | ||
625 | |||
498 | static unsigned int const exynos5_list_both_cnt_feed[] = { | 626 | static unsigned int const exynos5_list_both_cnt_feed[] = { |
499 | EXYNOS5_ARM_CORE0_OPTION, | 627 | EXYNOS5_ARM_CORE0_OPTION, |
500 | EXYNOS5_ARM_CORE1_OPTION, | 628 | EXYNOS5_ARM_CORE1_OPTION, |
@@ -632,6 +760,9 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode) | |||
632 | pmu_data->pmu_config[i].offset); | 760 | pmu_data->pmu_config[i].offset); |
633 | } | 761 | } |
634 | 762 | ||
763 | if (pmu_data->powerdown_conf_extra) | ||
764 | pmu_data->powerdown_conf_extra(mode); | ||
765 | |||
635 | if (pmu_data->pmu_config_extra) { | 766 | if (pmu_data->pmu_config_extra) { |
636 | for (i = 0; pmu_data->pmu_config_extra[i].offset != PMU_TABLE_END; i++) | 767 | for (i = 0; pmu_data->pmu_config_extra[i].offset != PMU_TABLE_END; i++) |
637 | pmu_raw_writel(pmu_data->pmu_config_extra[i].val[mode], | 768 | pmu_raw_writel(pmu_data->pmu_config_extra[i].val[mode], |
@@ -639,6 +770,36 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode) | |||
639 | } | 770 | } |
640 | } | 771 | } |
641 | 772 | ||
773 | static void exynos3250_pmu_init(void) | ||
774 | { | ||
775 | unsigned int value; | ||
776 | |||
777 | /* | ||
778 | * To prevent from issuing new bus request form L2 memory system | ||
779 | * If core status is power down, should be set '1' to L2 power down | ||
780 | */ | ||
781 | value = pmu_raw_readl(EXYNOS3_ARM_COMMON_OPTION); | ||
782 | value |= EXYNOS3_OPTION_SKIP_DEACTIVATE_ACEACP_IN_PWDN; | ||
783 | pmu_raw_writel(value, EXYNOS3_ARM_COMMON_OPTION); | ||
784 | |||
785 | /* Enable USE_STANDBY_WFI for all CORE */ | ||
786 | pmu_raw_writel(S5P_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION); | ||
787 | |||
788 | /* | ||
789 | * Set PSHOLD port for output high | ||
790 | */ | ||
791 | value = pmu_raw_readl(S5P_PS_HOLD_CONTROL); | ||
792 | value |= S5P_PS_HOLD_OUTPUT_HIGH; | ||
793 | pmu_raw_writel(value, S5P_PS_HOLD_CONTROL); | ||
794 | |||
795 | /* | ||
796 | * Enable signal for PSHOLD port | ||
797 | */ | ||
798 | value = pmu_raw_readl(S5P_PS_HOLD_CONTROL); | ||
799 | value |= S5P_PS_HOLD_EN; | ||
800 | pmu_raw_writel(value, S5P_PS_HOLD_CONTROL); | ||
801 | } | ||
802 | |||
642 | static void exynos5250_pmu_init(void) | 803 | static void exynos5250_pmu_init(void) |
643 | { | 804 | { |
644 | unsigned int value; | 805 | unsigned int value; |
@@ -716,6 +877,19 @@ static void exynos5420_pmu_init(void) | |||
716 | pr_info("EXYNOS5420 PMU initialized\n"); | 877 | pr_info("EXYNOS5420 PMU initialized\n"); |
717 | } | 878 | } |
718 | 879 | ||
880 | static int pmu_restart_notify(struct notifier_block *this, | ||
881 | unsigned long code, void *unused) | ||
882 | { | ||
883 | pmu_raw_writel(0x1, EXYNOS_SWRESET); | ||
884 | |||
885 | return NOTIFY_DONE; | ||
886 | } | ||
887 | |||
888 | static const struct exynos_pmu_data exynos3250_pmu_data = { | ||
889 | .pmu_config = exynos3250_pmu_config, | ||
890 | .pmu_init = exynos3250_pmu_init, | ||
891 | .powerdown_conf_extra = exynos3250_powerdown_conf_extra, | ||
892 | }; | ||
719 | 893 | ||
720 | static const struct exynos_pmu_data exynos4210_pmu_data = { | 894 | static const struct exynos_pmu_data exynos4210_pmu_data = { |
721 | .pmu_config = exynos4210_pmu_config, | 895 | .pmu_config = exynos4210_pmu_config, |
@@ -747,6 +921,9 @@ static struct exynos_pmu_data exynos5420_pmu_data = { | |||
747 | */ | 921 | */ |
748 | static const struct of_device_id exynos_pmu_of_device_ids[] = { | 922 | static const struct of_device_id exynos_pmu_of_device_ids[] = { |
749 | { | 923 | { |
924 | .compatible = "samsung,exynos3250-pmu", | ||
925 | .data = &exynos3250_pmu_data, | ||
926 | }, { | ||
750 | .compatible = "samsung,exynos4210-pmu", | 927 | .compatible = "samsung,exynos4210-pmu", |
751 | .data = &exynos4210_pmu_data, | 928 | .data = &exynos4210_pmu_data, |
752 | }, { | 929 | }, { |
@@ -765,11 +942,20 @@ static const struct of_device_id exynos_pmu_of_device_ids[] = { | |||
765 | { /*sentinel*/ }, | 942 | { /*sentinel*/ }, |
766 | }; | 943 | }; |
767 | 944 | ||
945 | /* | ||
946 | * Exynos PMU restart notifier, handles restart functionality | ||
947 | */ | ||
948 | static struct notifier_block pmu_restart_handler = { | ||
949 | .notifier_call = pmu_restart_notify, | ||
950 | .priority = 128, | ||
951 | }; | ||
952 | |||
768 | static int exynos_pmu_probe(struct platform_device *pdev) | 953 | static int exynos_pmu_probe(struct platform_device *pdev) |
769 | { | 954 | { |
770 | const struct of_device_id *match; | 955 | const struct of_device_id *match; |
771 | struct device *dev = &pdev->dev; | 956 | struct device *dev = &pdev->dev; |
772 | struct resource *res; | 957 | struct resource *res; |
958 | int ret; | ||
773 | 959 | ||
774 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 960 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
775 | pmu_base_addr = devm_ioremap_resource(dev, res); | 961 | pmu_base_addr = devm_ioremap_resource(dev, res); |
@@ -794,6 +980,10 @@ static int exynos_pmu_probe(struct platform_device *pdev) | |||
794 | 980 | ||
795 | platform_set_drvdata(pdev, pmu_context); | 981 | platform_set_drvdata(pdev, pmu_context); |
796 | 982 | ||
983 | ret = register_restart_handler(&pmu_restart_handler); | ||
984 | if (ret) | ||
985 | dev_warn(dev, "can't register restart handler err=%d\n", ret); | ||
986 | |||
797 | dev_dbg(dev, "Exynos PMU Driver probe done\n"); | 987 | dev_dbg(dev, "Exynos PMU Driver probe done\n"); |
798 | return 0; | 988 | return 0; |
799 | } | 989 | } |
diff --git a/arch/arm/mach-exynos/regs-pmu.h b/arch/arm/mach-exynos/regs-pmu.h index 46b973b8cd83..b5f4406fc1b5 100644 --- a/arch/arm/mach-exynos/regs-pmu.h +++ b/arch/arm/mach-exynos/regs-pmu.h | |||
@@ -19,7 +19,20 @@ | |||
19 | #define S5P_CENTRAL_SEQ_OPTION 0x0208 | 19 | #define S5P_CENTRAL_SEQ_OPTION 0x0208 |
20 | 20 | ||
21 | #define S5P_USE_STANDBY_WFI0 (1 << 16) | 21 | #define S5P_USE_STANDBY_WFI0 (1 << 16) |
22 | #define S5P_USE_STANDBY_WFI1 (1 << 17) | ||
23 | #define S5P_USE_STANDBY_WFI2 (1 << 19) | ||
24 | #define S5P_USE_STANDBY_WFI3 (1 << 20) | ||
22 | #define S5P_USE_STANDBY_WFE0 (1 << 24) | 25 | #define S5P_USE_STANDBY_WFE0 (1 << 24) |
26 | #define S5P_USE_STANDBY_WFE1 (1 << 25) | ||
27 | #define S5P_USE_STANDBY_WFE2 (1 << 27) | ||
28 | #define S5P_USE_STANDBY_WFE3 (1 << 28) | ||
29 | |||
30 | #define S5P_USE_STANDBY_WFI_ALL \ | ||
31 | (S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFI1 | \ | ||
32 | S5P_USE_STANDBY_WFI2 | S5P_USE_STANDBY_WFI3 | \ | ||
33 | S5P_USE_STANDBY_WFE0 | S5P_USE_STANDBY_WFE1 | \ | ||
34 | S5P_USE_STANDBY_WFE2 | S5P_USE_STANDBY_WFE3) | ||
35 | |||
23 | #define S5P_USE_DELAYED_RESET_ASSERTION BIT(12) | 36 | #define S5P_USE_DELAYED_RESET_ASSERTION BIT(12) |
24 | 37 | ||
25 | #define EXYNOS_CORE_PO_RESET(n) ((1 << 4) << n) | 38 | #define EXYNOS_CORE_PO_RESET(n) ((1 << 4) << n) |
@@ -154,6 +167,17 @@ | |||
154 | #define S5P_PAD_RET_EBIA_OPTION 0x3188 | 167 | #define S5P_PAD_RET_EBIA_OPTION 0x3188 |
155 | #define S5P_PAD_RET_EBIB_OPTION 0x31A8 | 168 | #define S5P_PAD_RET_EBIB_OPTION 0x31A8 |
156 | 169 | ||
170 | #define S5P_PS_HOLD_CONTROL 0x330C | ||
171 | #define S5P_PS_HOLD_EN (1 << 31) | ||
172 | #define S5P_PS_HOLD_OUTPUT_HIGH (3 << 8) | ||
173 | |||
174 | #define S5P_CAM_OPTION 0x3C08 | ||
175 | #define S5P_MFC_OPTION 0x3C48 | ||
176 | #define S5P_G3D_OPTION 0x3C68 | ||
177 | #define S5P_LCD0_OPTION 0x3C88 | ||
178 | #define S5P_LCD1_OPTION 0x3CA8 | ||
179 | #define S5P_ISP_OPTION S5P_LCD1_OPTION | ||
180 | |||
157 | #define S5P_CORE_LOCAL_PWR_EN 0x3 | 181 | #define S5P_CORE_LOCAL_PWR_EN 0x3 |
158 | #define S5P_CORE_WAKEUP_FROM_LOCAL_CFG (0x3 << 8) | 182 | #define S5P_CORE_WAKEUP_FROM_LOCAL_CFG (0x3 << 8) |
159 | 183 | ||
@@ -214,6 +238,110 @@ | |||
214 | #define S5P_DIS_IRQ_CORE3 0x1034 | 238 | #define S5P_DIS_IRQ_CORE3 0x1034 |
215 | #define S5P_DIS_IRQ_CENTRAL3 0x1038 | 239 | #define S5P_DIS_IRQ_CENTRAL3 0x1038 |
216 | 240 | ||
241 | /* Only for EXYNOS3XXX */ | ||
242 | #define EXYNOS3_ARM_CORE0_SYS_PWR_REG 0x1000 | ||
243 | #define EXYNOS3_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG 0x1004 | ||
244 | #define EXYNOS3_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG 0x1008 | ||
245 | #define EXYNOS3_ARM_CORE1_SYS_PWR_REG 0x1010 | ||
246 | #define EXYNOS3_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG 0x1014 | ||
247 | #define EXYNOS3_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG 0x1018 | ||
248 | #define EXYNOS3_ISP_ARM_SYS_PWR_REG 0x1050 | ||
249 | #define EXYNOS3_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG 0x1054 | ||
250 | #define EXYNOS3_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG 0x1058 | ||
251 | #define EXYNOS3_ARM_COMMON_SYS_PWR_REG 0x1080 | ||
252 | #define EXYNOS3_ARM_L2_SYS_PWR_REG 0x10C0 | ||
253 | #define EXYNOS3_CMU_ACLKSTOP_SYS_PWR_REG 0x1100 | ||
254 | #define EXYNOS3_CMU_SCLKSTOP_SYS_PWR_REG 0x1104 | ||
255 | #define EXYNOS3_CMU_RESET_SYS_PWR_REG 0x110C | ||
256 | #define EXYNOS3_CMU_ACLKSTOP_COREBLK_SYS_PWR_REG 0x1110 | ||
257 | #define EXYNOS3_CMU_SCLKSTOP_COREBLK_SYS_PWR_REG 0x1114 | ||
258 | #define EXYNOS3_CMU_RESET_COREBLK_SYS_PWR_REG 0x111C | ||
259 | #define EXYNOS3_APLL_SYSCLK_SYS_PWR_REG 0x1120 | ||
260 | #define EXYNOS3_MPLL_SYSCLK_SYS_PWR_REG 0x1124 | ||
261 | #define EXYNOS3_VPLL_SYSCLK_SYS_PWR_REG 0x1128 | ||
262 | #define EXYNOS3_EPLL_SYSCLK_SYS_PWR_REG 0x112C | ||
263 | #define EXYNOS3_MPLLUSER_SYSCLK_SYS_PWR_REG 0x1130 | ||
264 | #define EXYNOS3_BPLLUSER_SYSCLK_SYS_PWR_REG 0x1134 | ||
265 | #define EXYNOS3_EPLLUSER_SYSCLK_SYS_PWR_REG 0x1138 | ||
266 | #define EXYNOS3_CMU_CLKSTOP_CAM_SYS_PWR_REG 0x1140 | ||
267 | #define EXYNOS3_CMU_CLKSTOP_MFC_SYS_PWR_REG 0x1148 | ||
268 | #define EXYNOS3_CMU_CLKSTOP_G3D_SYS_PWR_REG 0x114C | ||
269 | #define EXYNOS3_CMU_CLKSTOP_LCD0_SYS_PWR_REG 0x1150 | ||
270 | #define EXYNOS3_CMU_CLKSTOP_ISP_SYS_PWR_REG 0x1154 | ||
271 | #define EXYNOS3_CMU_CLKSTOP_MAUDIO_SYS_PWR_REG 0x1158 | ||
272 | #define EXYNOS3_CMU_RESET_CAM_SYS_PWR_REG 0x1160 | ||
273 | #define EXYNOS3_CMU_RESET_MFC_SYS_PWR_REG 0x1168 | ||
274 | #define EXYNOS3_CMU_RESET_G3D_SYS_PWR_REG 0x116C | ||
275 | #define EXYNOS3_CMU_RESET_LCD0_SYS_PWR_REG 0x1170 | ||
276 | #define EXYNOS3_CMU_RESET_ISP_SYS_PWR_REG 0x1174 | ||
277 | #define EXYNOS3_CMU_RESET_MAUDIO_SYS_PWR_REG 0x1178 | ||
278 | #define EXYNOS3_TOP_BUS_SYS_PWR_REG 0x1180 | ||
279 | #define EXYNOS3_TOP_RETENTION_SYS_PWR_REG 0x1184 | ||
280 | #define EXYNOS3_TOP_PWR_SYS_PWR_REG 0x1188 | ||
281 | #define EXYNOS3_TOP_BUS_COREBLK_SYS_PWR_REG 0x1190 | ||
282 | #define EXYNOS3_TOP_RETENTION_COREBLK_SYS_PWR_REG 0x1194 | ||
283 | #define EXYNOS3_TOP_PWR_COREBLK_SYS_PWR_REG 0x1198 | ||
284 | #define EXYNOS3_LOGIC_RESET_SYS_PWR_REG 0x11A0 | ||
285 | #define EXYNOS3_OSCCLK_GATE_SYS_PWR_REG 0x11A4 | ||
286 | #define EXYNOS3_LOGIC_RESET_COREBLK_SYS_PWR_REG 0x11B0 | ||
287 | #define EXYNOS3_OSCCLK_GATE_COREBLK_SYS_PWR_REG 0x11B4 | ||
288 | #define EXYNOS3_PAD_RETENTION_DRAM_SYS_PWR_REG 0x1200 | ||
289 | #define EXYNOS3_PAD_RETENTION_MAUDIO_SYS_PWR_REG 0x1204 | ||
290 | #define EXYNOS3_PAD_RETENTION_SPI_SYS_PWR_REG 0x1208 | ||
291 | #define EXYNOS3_PAD_RETENTION_MMC2_SYS_PWR_REG 0x1218 | ||
292 | #define EXYNOS3_PAD_RETENTION_GPIO_SYS_PWR_REG 0x1220 | ||
293 | #define EXYNOS3_PAD_RETENTION_UART_SYS_PWR_REG 0x1224 | ||
294 | #define EXYNOS3_PAD_RETENTION_MMC0_SYS_PWR_REG 0x1228 | ||
295 | #define EXYNOS3_PAD_RETENTION_MMC1_SYS_PWR_REG 0x122C | ||
296 | #define EXYNOS3_PAD_RETENTION_EBIA_SYS_PWR_REG 0x1230 | ||
297 | #define EXYNOS3_PAD_RETENTION_EBIB_SYS_PWR_REG 0x1234 | ||
298 | #define EXYNOS3_PAD_RETENTION_JTAG_SYS_PWR_REG 0x1238 | ||
299 | #define EXYNOS3_PAD_ISOLATION_SYS_PWR_REG 0x1240 | ||
300 | #define EXYNOS3_PAD_ALV_SEL_SYS_PWR_REG 0x1260 | ||
301 | #define EXYNOS3_XUSBXTI_SYS_PWR_REG 0x1280 | ||
302 | #define EXYNOS3_XXTI_SYS_PWR_REG 0x1284 | ||
303 | #define EXYNOS3_EXT_REGULATOR_SYS_PWR_REG 0x12C0 | ||
304 | #define EXYNOS3_EXT_REGULATOR_COREBLK_SYS_PWR_REG 0x12C4 | ||
305 | #define EXYNOS3_GPIO_MODE_SYS_PWR_REG 0x1300 | ||
306 | #define EXYNOS3_GPIO_MODE_MAUDIO_SYS_PWR_REG 0x1340 | ||
307 | #define EXYNOS3_TOP_ASB_RESET_SYS_PWR_REG 0x1344 | ||
308 | #define EXYNOS3_TOP_ASB_ISOLATION_SYS_PWR_REG 0x1348 | ||
309 | #define EXYNOS3_TOP_ASB_RESET_COREBLK_SYS_PWR_REG 0x1350 | ||
310 | #define EXYNOS3_TOP_ASB_ISOLATION_COREBLK_SYS_PWR_REG 0x1354 | ||
311 | #define EXYNOS3_CAM_SYS_PWR_REG 0x1380 | ||
312 | #define EXYNOS3_MFC_SYS_PWR_REG 0x1388 | ||
313 | #define EXYNOS3_G3D_SYS_PWR_REG 0x138C | ||
314 | #define EXYNOS3_LCD0_SYS_PWR_REG 0x1390 | ||
315 | #define EXYNOS3_ISP_SYS_PWR_REG 0x1394 | ||
316 | #define EXYNOS3_MAUDIO_SYS_PWR_REG 0x1398 | ||
317 | #define EXYNOS3_DRAM_FREQ_DOWN_SYS_PWR_REG 0x13B0 | ||
318 | #define EXYNOS3_DDRPHY_DLLOFF_SYS_PWR_REG 0x13B4 | ||
319 | #define EXYNOS3_CMU_SYSCLK_ISP_SYS_PWR_REG 0x13B8 | ||
320 | #define EXYNOS3_LPDDR_PHY_DLL_LOCK_SYS_PWR_REG 0x13C0 | ||
321 | #define EXYNOS3_BPLL_SYSCLK_SYS_PWR_REG 0x13C4 | ||
322 | #define EXYNOS3_UPLL_SYSCLK_SYS_PWR_REG 0x13C8 | ||
323 | |||
324 | #define EXYNOS3_ARM_CORE0_OPTION 0x2008 | ||
325 | #define EXYNOS3_ARM_CORE_OPTION(_nr) \ | ||
326 | (EXYNOS3_ARM_CORE0_OPTION + ((_nr) * 0x80)) | ||
327 | |||
328 | #define EXYNOS3_ARM_COMMON_OPTION 0x2408 | ||
329 | #define EXYNOS3_TOP_PWR_OPTION 0x2C48 | ||
330 | #define EXYNOS3_CORE_TOP_PWR_OPTION 0x2CA8 | ||
331 | #define EXYNOS3_XUSBXTI_DURATION 0x341C | ||
332 | #define EXYNOS3_XXTI_DURATION 0x343C | ||
333 | #define EXYNOS3_EXT_REGULATOR_DURATION 0x361C | ||
334 | #define EXYNOS3_EXT_REGULATOR_COREBLK_DURATION 0x363C | ||
335 | #define XUSBXTI_DURATION 0x00000BB8 | ||
336 | #define XXTI_DURATION XUSBXTI_DURATION | ||
337 | #define EXT_REGULATOR_DURATION 0x00001D4C | ||
338 | #define EXT_REGULATOR_COREBLK_DURATION EXT_REGULATOR_DURATION | ||
339 | |||
340 | /* for XXX_OPTION */ | ||
341 | #define EXYNOS3_OPTION_USE_SC_COUNTER (1 << 0) | ||
342 | #define EXYNOS3_OPTION_USE_SC_FEEDBACK (1 << 1) | ||
343 | #define EXYNOS3_OPTION_SKIP_DEACTIVATE_ACEACP_IN_PWDN (1 << 7) | ||
344 | |||
217 | /* For EXYNOS5 */ | 345 | /* For EXYNOS5 */ |
218 | 346 | ||
219 | #define EXYNOS5_AUTO_WDTRESET_DISABLE 0x0408 | 347 | #define EXYNOS5_AUTO_WDTRESET_DISABLE 0x0408 |
diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c index 00d1d00a41de..979e81389cdd 100644 --- a/drivers/clk/samsung/clk-exynos5440.c +++ b/drivers/clk/samsung/clk-exynos5440.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <linux/clk-provider.h> | 15 | #include <linux/clk-provider.h> |
16 | #include <linux/of.h> | 16 | #include <linux/of.h> |
17 | #include <linux/of_address.h> | 17 | #include <linux/of_address.h> |
18 | #include <linux/notifier.h> | ||
19 | #include <linux/reboot.h> | ||
18 | 20 | ||
19 | #include "clk.h" | 21 | #include "clk.h" |
20 | #include "clk-pll.h" | 22 | #include "clk-pll.h" |
@@ -23,6 +25,8 @@ | |||
23 | #define CPU_CLK_STATUS 0xfc | 25 | #define CPU_CLK_STATUS 0xfc |
24 | #define MISC_DOUT1 0x558 | 26 | #define MISC_DOUT1 0x558 |
25 | 27 | ||
28 | static void __iomem *reg_base; | ||
29 | |||
26 | /* parent clock name list */ | 30 | /* parent clock name list */ |
27 | PNAME(mout_armclk_p) = { "cplla", "cpllb" }; | 31 | PNAME(mout_armclk_p) = { "cplla", "cpllb" }; |
28 | PNAME(mout_spi_p) = { "div125", "div200" }; | 32 | PNAME(mout_spi_p) = { "div125", "div200" }; |
@@ -89,10 +93,30 @@ static const struct of_device_id ext_clk_match[] __initconst = { | |||
89 | {}, | 93 | {}, |
90 | }; | 94 | }; |
91 | 95 | ||
96 | static int exynos5440_clk_restart_notify(struct notifier_block *this, | ||
97 | unsigned long code, void *unused) | ||
98 | { | ||
99 | u32 val, status; | ||
100 | |||
101 | status = readl_relaxed(reg_base + 0xbc); | ||
102 | val = readl_relaxed(reg_base + 0xcc); | ||
103 | val = (val & 0xffff0000) | (status & 0xffff); | ||
104 | writel_relaxed(val, reg_base + 0xcc); | ||
105 | |||
106 | return NOTIFY_DONE; | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * Exynos5440 Clock restart notifier, handles restart functionality | ||
111 | */ | ||
112 | static struct notifier_block exynos5440_clk_restart_handler = { | ||
113 | .notifier_call = exynos5440_clk_restart_notify, | ||
114 | .priority = 128, | ||
115 | }; | ||
116 | |||
92 | /* register exynos5440 clocks */ | 117 | /* register exynos5440 clocks */ |
93 | static void __init exynos5440_clk_init(struct device_node *np) | 118 | static void __init exynos5440_clk_init(struct device_node *np) |
94 | { | 119 | { |
95 | void __iomem *reg_base; | ||
96 | struct samsung_clk_provider *ctx; | 120 | struct samsung_clk_provider *ctx; |
97 | 121 | ||
98 | reg_base = of_iomap(np, 0); | 122 | reg_base = of_iomap(np, 0); |
@@ -125,6 +149,9 @@ static void __init exynos5440_clk_init(struct device_node *np) | |||
125 | 149 | ||
126 | samsung_clk_of_add_provider(np, ctx); | 150 | samsung_clk_of_add_provider(np, ctx); |
127 | 151 | ||
152 | if (register_restart_handler(&exynos5440_clk_restart_handler)) | ||
153 | pr_warn("exynos5440 clock can't register restart handler\n"); | ||
154 | |||
128 | pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk")); | 155 | pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk")); |
129 | pr_info("exynos5440 clock initialization complete\n"); | 156 | pr_info("exynos5440 clock initialization complete\n"); |
130 | } | 157 | } |