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 @@  #ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H  #define __ARCH_ARM_MACH_EXYNOS_COMMON_H -#include <linux/reboot.h>  #include <linux/of.h>  #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 = {  	},  }; -static void exynos_restart(enum reboot_mode mode, const char *cmd) -{ -	struct device_node *np; -	u32 val = 0x1; -	void __iomem *addr = pmu_base_addr + EXYNOS_SWRESET; - -	if (of_machine_is_compatible("samsung,exynos5440")) { -		u32 status; -		np = of_find_compatible_node(NULL, NULL, "samsung,exynos5440-clock"); - -		addr = of_iomap(np, 0) + 0xbc; -		status = __raw_readl(addr); - -		addr = of_iomap(np, 0) + 0xcc; -		val = __raw_readl(addr); - -		val = (val & 0xffff0000) | (status & 0xffff); -	} - -	__raw_writel(val, addr); -} -  static struct platform_device exynos_cpuidle = {  	.name              = "exynos_cpuidle",  #ifdef CONFIG_ARM_EXYNOS_CPUIDLE @@ -383,7 +361,6 @@ DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")  	.init_machine	= exynos_dt_machine_init,  	.init_late	= exynos_init_late,  	.dt_compat	= exynos_dt_compat, -	.restart	= exynos_restart,  	.reserve	= exynos_reserve,  	.dt_fixup	= exynos_dt_fixup,  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 @@  #include <linux/io.h>  #include <linux/of.h> +#include <linux/of_address.h>  #include <linux/platform_device.h>  #include <linux/delay.h> +#include <linux/notifier.h> +#include <linux/reboot.h>  #include "exynos-pmu.h" @@ -22,7 +25,7 @@  struct exynos_pmu_conf {  	unsigned int offset; -	unsigned int val[NUM_SYS_POWERDOWN]; +	u8 val[NUM_SYS_POWERDOWN];  };  struct exynos_pmu_data { @@ -31,6 +34,7 @@ struct exynos_pmu_data {  	void (*pmu_init)(void);  	void (*powerdown_conf)(enum sys_powerdown); +	void (*powerdown_conf_extra)(enum sys_powerdown);  };  struct exynos_pmu_context { @@ -51,6 +55,92 @@ static inline u32 pmu_raw_readl(u32 offset)  	return readl_relaxed(pmu_base_addr + offset);  } +static struct exynos_pmu_conf exynos3250_pmu_config[] = { +	/* { .offset = offset, .val = { AFTR, W-AFTR, SLEEP } */ +	{ EXYNOS3_ARM_CORE0_SYS_PWR_REG,		{ 0x0, 0x0, 0x2} }, +	{ EXYNOS3_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG,	{ 0x0, 0x0, 0x0} }, +	{ EXYNOS3_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} }, +	{ EXYNOS3_ARM_CORE1_SYS_PWR_REG,		{ 0x0, 0x0, 0x2} }, +	{ EXYNOS3_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG,	{ 0x0, 0x0, 0x0} }, +	{ EXYNOS3_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} }, +	{ EXYNOS3_ISP_ARM_SYS_PWR_REG,			{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG,	{ 0x0, 0x0, 0x0} }, +	{ EXYNOS3_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG,	{ 0x0, 0x0, 0x0} }, +	{ EXYNOS3_ARM_COMMON_SYS_PWR_REG,		{ 0x0, 0x0, 0x2} }, +	{ EXYNOS3_ARM_L2_SYS_PWR_REG,			{ 0x0, 0x0, 0x3} }, +	{ EXYNOS3_CMU_ACLKSTOP_SYS_PWR_REG,		{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_CMU_SCLKSTOP_SYS_PWR_REG,		{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_CMU_RESET_SYS_PWR_REG,		{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_DRAM_FREQ_DOWN_SYS_PWR_REG,		{ 0x1, 0x1, 0x1} }, +	{ EXYNOS3_DDRPHY_DLLOFF_SYS_PWR_REG,		{ 0x1, 0x1, 0x1} }, +	{ EXYNOS3_LPDDR_PHY_DLL_LOCK_SYS_PWR_REG,	{ 0x1, 0x1, 0x1} }, +	{ EXYNOS3_CMU_ACLKSTOP_COREBLK_SYS_PWR_REG,	{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_CMU_SCLKSTOP_COREBLK_SYS_PWR_REG,	{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_CMU_RESET_COREBLK_SYS_PWR_REG,	{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_APLL_SYSCLK_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_MPLL_SYSCLK_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_BPLL_SYSCLK_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_VPLL_SYSCLK_SYS_PWR_REG,		{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_EPLL_SYSCLK_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_UPLL_SYSCLK_SYS_PWR_REG,		{ 0x1, 0x1, 0x1} }, +	{ EXYNOS3_EPLLUSER_SYSCLK_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_MPLLUSER_SYSCLK_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_BPLLUSER_SYSCLK_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_CMU_CLKSTOP_CAM_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_CMU_CLKSTOP_MFC_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_CMU_CLKSTOP_G3D_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_CMU_CLKSTOP_LCD0_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_CMU_CLKSTOP_ISP_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_CMU_CLKSTOP_MAUDIO_SYS_PWR_REG,	{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_CMU_RESET_CAM_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_CMU_RESET_MFC_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_CMU_RESET_G3D_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_CMU_RESET_LCD0_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_CMU_RESET_ISP_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_CMU_RESET_MAUDIO_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ EXYNOS3_TOP_BUS_SYS_PWR_REG,			{ 0x3, 0x0, 0x0} }, +	{ EXYNOS3_TOP_RETENTION_SYS_PWR_REG,		{ 0x1, 0x1, 0x1} }, +	{ EXYNOS3_TOP_PWR_SYS_PWR_REG,			{ 0x3, 0x3, 0x3} }, +	{ EXYNOS3_TOP_BUS_COREBLK_SYS_PWR_REG,		{ 0x3, 0x0, 0x0} }, +	{ EXYNOS3_TOP_RETENTION_COREBLK_SYS_PWR_REG,	{ 0x1, 0x1, 0x1} }, +	{ EXYNOS3_TOP_PWR_COREBLK_SYS_PWR_REG,		{ 0x3, 0x3, 0x3} }, +	{ EXYNOS3_LOGIC_RESET_SYS_PWR_REG,		{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_OSCCLK_GATE_SYS_PWR_REG,		{ 0x1, 0x1, 0x1} }, +	{ EXYNOS3_LOGIC_RESET_COREBLK_SYS_PWR_REG,	{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_OSCCLK_GATE_COREBLK_SYS_PWR_REG,	{ 0x1, 0x0, 0x1} }, +	{ EXYNOS3_PAD_RETENTION_DRAM_SYS_PWR_REG,	{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_PAD_RETENTION_MAUDIO_SYS_PWR_REG,	{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_PAD_RETENTION_GPIO_SYS_PWR_REG,	{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_PAD_RETENTION_UART_SYS_PWR_REG,	{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_PAD_RETENTION_MMC0_SYS_PWR_REG,	{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_PAD_RETENTION_MMC1_SYS_PWR_REG,	{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_PAD_RETENTION_MMC2_SYS_PWR_REG,	{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_PAD_RETENTION_SPI_SYS_PWR_REG,	{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_PAD_RETENTION_EBIA_SYS_PWR_REG,	{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_PAD_RETENTION_EBIB_SYS_PWR_REG,	{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_PAD_RETENTION_JTAG_SYS_PWR_REG,	{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_PAD_ISOLATION_SYS_PWR_REG,		{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_PAD_ALV_SEL_SYS_PWR_REG,		{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_XUSBXTI_SYS_PWR_REG,			{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_XXTI_SYS_PWR_REG,			{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_EXT_REGULATOR_SYS_PWR_REG,		{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_EXT_REGULATOR_COREBLK_SYS_PWR_REG,	{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_GPIO_MODE_SYS_PWR_REG,		{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_GPIO_MODE_MAUDIO_SYS_PWR_REG,		{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_TOP_ASB_RESET_SYS_PWR_REG,		{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_TOP_ASB_ISOLATION_SYS_PWR_REG,	{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_TOP_ASB_RESET_COREBLK_SYS_PWR_REG,	{ 0x1, 0x1, 0x0} }, +	{ EXYNOS3_TOP_ASB_ISOLATION_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, +	{ EXYNOS3_CAM_SYS_PWR_REG,			{ 0x7, 0x0, 0x0} }, +	{ EXYNOS3_MFC_SYS_PWR_REG,			{ 0x7, 0x0, 0x0} }, +	{ EXYNOS3_G3D_SYS_PWR_REG,			{ 0x7, 0x0, 0x0} }, +	{ EXYNOS3_LCD0_SYS_PWR_REG,			{ 0x7, 0x0, 0x0} }, +	{ EXYNOS3_ISP_SYS_PWR_REG,			{ 0x7, 0x0, 0x0} }, +	{ EXYNOS3_MAUDIO_SYS_PWR_REG,			{ 0x7, 0x0, 0x0} }, +	{ EXYNOS3_CMU_SYSCLK_ISP_SYS_PWR_REG,		{ 0x1, 0x0, 0x0} }, +	{ PMU_TABLE_END,}, +}; +  static const struct exynos_pmu_conf exynos4210_pmu_config[] = {  	/* { .offset = offset, .val = { AFTR, LPA, SLEEP } */  	{ S5P_ARM_CORE0_LOWPWR,			{ 0x0, 0x0, 0x2 } }, @@ -495,6 +585,44 @@ static struct exynos_pmu_conf exynos5420_pmu_config[] = {  	{ PMU_TABLE_END,},  }; +static unsigned int const exynos3250_list_feed[] = { +	EXYNOS3_ARM_CORE_OPTION(0), +	EXYNOS3_ARM_CORE_OPTION(1), +	EXYNOS3_ARM_CORE_OPTION(2), +	EXYNOS3_ARM_CORE_OPTION(3), +	EXYNOS3_ARM_COMMON_OPTION, +	EXYNOS3_TOP_PWR_OPTION, +	EXYNOS3_CORE_TOP_PWR_OPTION, +	S5P_CAM_OPTION, +	S5P_MFC_OPTION, +	S5P_G3D_OPTION, +	S5P_LCD0_OPTION, +	S5P_ISP_OPTION, +}; + +static void exynos3250_powerdown_conf_extra(enum sys_powerdown mode) +{ +	unsigned int i; +	unsigned int tmp; + +	/* Enable only SC_FEEDBACK */ +	for (i = 0; i < ARRAY_SIZE(exynos3250_list_feed); i++) { +		tmp = pmu_raw_readl(exynos3250_list_feed[i]); +		tmp &= ~(EXYNOS3_OPTION_USE_SC_COUNTER); +		tmp |= EXYNOS3_OPTION_USE_SC_FEEDBACK; +		pmu_raw_writel(tmp, exynos3250_list_feed[i]); +	} + +	if (mode != SYS_SLEEP) +		return; + +	pmu_raw_writel(XUSBXTI_DURATION, EXYNOS3_XUSBXTI_DURATION); +	pmu_raw_writel(XXTI_DURATION, EXYNOS3_XXTI_DURATION); +	pmu_raw_writel(EXT_REGULATOR_DURATION, EXYNOS3_EXT_REGULATOR_DURATION); +	pmu_raw_writel(EXT_REGULATOR_COREBLK_DURATION, +		       EXYNOS3_EXT_REGULATOR_COREBLK_DURATION); +} +  static unsigned int const exynos5_list_both_cnt_feed[] = {  	EXYNOS5_ARM_CORE0_OPTION,  	EXYNOS5_ARM_CORE1_OPTION, @@ -632,6 +760,9 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)  					pmu_data->pmu_config[i].offset);  	} +	if (pmu_data->powerdown_conf_extra) +		pmu_data->powerdown_conf_extra(mode); +  	if (pmu_data->pmu_config_extra) {  		for (i = 0; pmu_data->pmu_config_extra[i].offset != PMU_TABLE_END; i++)  			pmu_raw_writel(pmu_data->pmu_config_extra[i].val[mode], @@ -639,6 +770,36 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)  	}  } +static void exynos3250_pmu_init(void) +{ +	unsigned int value; + +	/* +	 * To prevent from issuing new bus request form L2 memory system +	 * If core status is power down, should be set '1' to L2 power down +	 */ +	value = pmu_raw_readl(EXYNOS3_ARM_COMMON_OPTION); +	value |= EXYNOS3_OPTION_SKIP_DEACTIVATE_ACEACP_IN_PWDN; +	pmu_raw_writel(value, EXYNOS3_ARM_COMMON_OPTION); + +	/* Enable USE_STANDBY_WFI for all CORE */ +	pmu_raw_writel(S5P_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION); + +	/* +	 * Set PSHOLD port for output high +	 */ +	value = pmu_raw_readl(S5P_PS_HOLD_CONTROL); +	value |= S5P_PS_HOLD_OUTPUT_HIGH; +	pmu_raw_writel(value, S5P_PS_HOLD_CONTROL); + +	/* +	 * Enable signal for PSHOLD port +	 */ +	value = pmu_raw_readl(S5P_PS_HOLD_CONTROL); +	value |= S5P_PS_HOLD_EN; +	pmu_raw_writel(value, S5P_PS_HOLD_CONTROL); +} +  static void exynos5250_pmu_init(void)  {  	unsigned int value; @@ -716,6 +877,19 @@ static void exynos5420_pmu_init(void)  	pr_info("EXYNOS5420 PMU initialized\n");  } +static int pmu_restart_notify(struct notifier_block *this, +		unsigned long code, void *unused) +{ +	pmu_raw_writel(0x1, EXYNOS_SWRESET); + +	return NOTIFY_DONE; +} + +static const struct exynos_pmu_data exynos3250_pmu_data = { +	.pmu_config	= exynos3250_pmu_config, +	.pmu_init	= exynos3250_pmu_init, +	.powerdown_conf_extra	= exynos3250_powerdown_conf_extra, +};  static const struct exynos_pmu_data exynos4210_pmu_data = {  	.pmu_config	= exynos4210_pmu_config, @@ -747,6 +921,9 @@ static struct exynos_pmu_data exynos5420_pmu_data = {   */  static const struct of_device_id exynos_pmu_of_device_ids[] = {  	{ +		.compatible = "samsung,exynos3250-pmu", +		.data = &exynos3250_pmu_data, +	}, {  		.compatible = "samsung,exynos4210-pmu",  		.data = &exynos4210_pmu_data,  	}, { @@ -765,11 +942,20 @@ static const struct of_device_id exynos_pmu_of_device_ids[] = {  	{ /*sentinel*/ },  }; +/* + * Exynos PMU restart notifier, handles restart functionality + */ +static struct notifier_block pmu_restart_handler = { +	.notifier_call = pmu_restart_notify, +	.priority = 128, +}; +  static int exynos_pmu_probe(struct platform_device *pdev)  {  	const struct of_device_id *match;  	struct device *dev = &pdev->dev;  	struct resource *res; +	int ret;  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	pmu_base_addr = devm_ioremap_resource(dev, res); @@ -794,6 +980,10 @@ static int exynos_pmu_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, pmu_context); +	ret = register_restart_handler(&pmu_restart_handler); +	if (ret) +		dev_warn(dev, "can't register restart handler err=%d\n", ret); +  	dev_dbg(dev, "Exynos PMU Driver probe done\n");  	return 0;  } 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 @@  #define S5P_CENTRAL_SEQ_OPTION			0x0208  #define S5P_USE_STANDBY_WFI0			(1 << 16) +#define S5P_USE_STANDBY_WFI1			(1 << 17) +#define S5P_USE_STANDBY_WFI2			(1 << 19) +#define S5P_USE_STANDBY_WFI3			(1 << 20)  #define S5P_USE_STANDBY_WFE0			(1 << 24) +#define S5P_USE_STANDBY_WFE1			(1 << 25) +#define S5P_USE_STANDBY_WFE2			(1 << 27) +#define S5P_USE_STANDBY_WFE3			(1 << 28) + +#define S5P_USE_STANDBY_WFI_ALL \ +	(S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFI1 | \ +	 S5P_USE_STANDBY_WFI2 | S5P_USE_STANDBY_WFI3 | \ +	 S5P_USE_STANDBY_WFE0 | S5P_USE_STANDBY_WFE1 | \ +	 S5P_USE_STANDBY_WFE2 | S5P_USE_STANDBY_WFE3) +  #define S5P_USE_DELAYED_RESET_ASSERTION		BIT(12)  #define EXYNOS_CORE_PO_RESET(n)			((1 << 4) << n) @@ -154,6 +167,17 @@  #define S5P_PAD_RET_EBIA_OPTION			0x3188  #define S5P_PAD_RET_EBIB_OPTION			0x31A8 +#define S5P_PS_HOLD_CONTROL			0x330C +#define S5P_PS_HOLD_EN				(1 << 31) +#define S5P_PS_HOLD_OUTPUT_HIGH			(3 << 8) + +#define S5P_CAM_OPTION				0x3C08 +#define S5P_MFC_OPTION				0x3C48 +#define S5P_G3D_OPTION				0x3C68 +#define S5P_LCD0_OPTION				0x3C88 +#define S5P_LCD1_OPTION				0x3CA8 +#define S5P_ISP_OPTION				S5P_LCD1_OPTION +  #define S5P_CORE_LOCAL_PWR_EN			0x3  #define S5P_CORE_WAKEUP_FROM_LOCAL_CFG		(0x3 << 8) @@ -214,6 +238,110 @@  #define S5P_DIS_IRQ_CORE3			0x1034  #define S5P_DIS_IRQ_CENTRAL3			0x1038 +/* Only for EXYNOS3XXX */ +#define EXYNOS3_ARM_CORE0_SYS_PWR_REG			0x1000 +#define EXYNOS3_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG	0x1004 +#define EXYNOS3_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG	0x1008 +#define EXYNOS3_ARM_CORE1_SYS_PWR_REG			0x1010 +#define EXYNOS3_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG	0x1014 +#define EXYNOS3_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG	0x1018 +#define EXYNOS3_ISP_ARM_SYS_PWR_REG			0x1050 +#define EXYNOS3_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG	0x1054 +#define EXYNOS3_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG	0x1058 +#define EXYNOS3_ARM_COMMON_SYS_PWR_REG			0x1080 +#define EXYNOS3_ARM_L2_SYS_PWR_REG			0x10C0 +#define EXYNOS3_CMU_ACLKSTOP_SYS_PWR_REG		0x1100 +#define EXYNOS3_CMU_SCLKSTOP_SYS_PWR_REG		0x1104 +#define EXYNOS3_CMU_RESET_SYS_PWR_REG			0x110C +#define EXYNOS3_CMU_ACLKSTOP_COREBLK_SYS_PWR_REG	0x1110 +#define EXYNOS3_CMU_SCLKSTOP_COREBLK_SYS_PWR_REG	0x1114 +#define EXYNOS3_CMU_RESET_COREBLK_SYS_PWR_REG		0x111C +#define EXYNOS3_APLL_SYSCLK_SYS_PWR_REG			0x1120 +#define EXYNOS3_MPLL_SYSCLK_SYS_PWR_REG			0x1124 +#define EXYNOS3_VPLL_SYSCLK_SYS_PWR_REG			0x1128 +#define EXYNOS3_EPLL_SYSCLK_SYS_PWR_REG			0x112C +#define EXYNOS3_MPLLUSER_SYSCLK_SYS_PWR_REG		0x1130 +#define EXYNOS3_BPLLUSER_SYSCLK_SYS_PWR_REG		0x1134 +#define EXYNOS3_EPLLUSER_SYSCLK_SYS_PWR_REG		0x1138 +#define EXYNOS3_CMU_CLKSTOP_CAM_SYS_PWR_REG		0x1140 +#define EXYNOS3_CMU_CLKSTOP_MFC_SYS_PWR_REG		0x1148 +#define EXYNOS3_CMU_CLKSTOP_G3D_SYS_PWR_REG		0x114C +#define EXYNOS3_CMU_CLKSTOP_LCD0_SYS_PWR_REG		0x1150 +#define EXYNOS3_CMU_CLKSTOP_ISP_SYS_PWR_REG		0x1154 +#define EXYNOS3_CMU_CLKSTOP_MAUDIO_SYS_PWR_REG		0x1158 +#define EXYNOS3_CMU_RESET_CAM_SYS_PWR_REG		0x1160 +#define EXYNOS3_CMU_RESET_MFC_SYS_PWR_REG		0x1168 +#define EXYNOS3_CMU_RESET_G3D_SYS_PWR_REG		0x116C +#define EXYNOS3_CMU_RESET_LCD0_SYS_PWR_REG		0x1170 +#define EXYNOS3_CMU_RESET_ISP_SYS_PWR_REG		0x1174 +#define EXYNOS3_CMU_RESET_MAUDIO_SYS_PWR_REG		0x1178 +#define EXYNOS3_TOP_BUS_SYS_PWR_REG			0x1180 +#define EXYNOS3_TOP_RETENTION_SYS_PWR_REG		0x1184 +#define EXYNOS3_TOP_PWR_SYS_PWR_REG			0x1188 +#define EXYNOS3_TOP_BUS_COREBLK_SYS_PWR_REG		0x1190 +#define EXYNOS3_TOP_RETENTION_COREBLK_SYS_PWR_REG	0x1194 +#define EXYNOS3_TOP_PWR_COREBLK_SYS_PWR_REG		0x1198 +#define EXYNOS3_LOGIC_RESET_SYS_PWR_REG			0x11A0 +#define EXYNOS3_OSCCLK_GATE_SYS_PWR_REG			0x11A4 +#define EXYNOS3_LOGIC_RESET_COREBLK_SYS_PWR_REG		0x11B0 +#define EXYNOS3_OSCCLK_GATE_COREBLK_SYS_PWR_REG		0x11B4 +#define EXYNOS3_PAD_RETENTION_DRAM_SYS_PWR_REG		0x1200 +#define EXYNOS3_PAD_RETENTION_MAUDIO_SYS_PWR_REG	0x1204 +#define EXYNOS3_PAD_RETENTION_SPI_SYS_PWR_REG		0x1208 +#define EXYNOS3_PAD_RETENTION_MMC2_SYS_PWR_REG		0x1218 +#define EXYNOS3_PAD_RETENTION_GPIO_SYS_PWR_REG		0x1220 +#define EXYNOS3_PAD_RETENTION_UART_SYS_PWR_REG		0x1224 +#define EXYNOS3_PAD_RETENTION_MMC0_SYS_PWR_REG		0x1228 +#define EXYNOS3_PAD_RETENTION_MMC1_SYS_PWR_REG		0x122C +#define EXYNOS3_PAD_RETENTION_EBIA_SYS_PWR_REG		0x1230 +#define EXYNOS3_PAD_RETENTION_EBIB_SYS_PWR_REG		0x1234 +#define EXYNOS3_PAD_RETENTION_JTAG_SYS_PWR_REG		0x1238 +#define EXYNOS3_PAD_ISOLATION_SYS_PWR_REG		0x1240 +#define EXYNOS3_PAD_ALV_SEL_SYS_PWR_REG			0x1260 +#define EXYNOS3_XUSBXTI_SYS_PWR_REG			0x1280 +#define EXYNOS3_XXTI_SYS_PWR_REG			0x1284 +#define EXYNOS3_EXT_REGULATOR_SYS_PWR_REG		0x12C0 +#define EXYNOS3_EXT_REGULATOR_COREBLK_SYS_PWR_REG	0x12C4 +#define EXYNOS3_GPIO_MODE_SYS_PWR_REG			0x1300 +#define EXYNOS3_GPIO_MODE_MAUDIO_SYS_PWR_REG		0x1340 +#define EXYNOS3_TOP_ASB_RESET_SYS_PWR_REG		0x1344 +#define EXYNOS3_TOP_ASB_ISOLATION_SYS_PWR_REG		0x1348 +#define EXYNOS3_TOP_ASB_RESET_COREBLK_SYS_PWR_REG	0x1350 +#define EXYNOS3_TOP_ASB_ISOLATION_COREBLK_SYS_PWR_REG	0x1354 +#define EXYNOS3_CAM_SYS_PWR_REG				0x1380 +#define EXYNOS3_MFC_SYS_PWR_REG				0x1388 +#define EXYNOS3_G3D_SYS_PWR_REG				0x138C +#define EXYNOS3_LCD0_SYS_PWR_REG			0x1390 +#define EXYNOS3_ISP_SYS_PWR_REG				0x1394 +#define EXYNOS3_MAUDIO_SYS_PWR_REG			0x1398 +#define EXYNOS3_DRAM_FREQ_DOWN_SYS_PWR_REG		0x13B0 +#define EXYNOS3_DDRPHY_DLLOFF_SYS_PWR_REG		0x13B4 +#define EXYNOS3_CMU_SYSCLK_ISP_SYS_PWR_REG		0x13B8 +#define EXYNOS3_LPDDR_PHY_DLL_LOCK_SYS_PWR_REG		0x13C0 +#define EXYNOS3_BPLL_SYSCLK_SYS_PWR_REG			0x13C4 +#define EXYNOS3_UPLL_SYSCLK_SYS_PWR_REG			0x13C8 + +#define EXYNOS3_ARM_CORE0_OPTION			0x2008 +#define EXYNOS3_ARM_CORE_OPTION(_nr)	\ +			(EXYNOS3_ARM_CORE0_OPTION + ((_nr) * 0x80)) + +#define EXYNOS3_ARM_COMMON_OPTION			0x2408 +#define EXYNOS3_TOP_PWR_OPTION				0x2C48 +#define EXYNOS3_CORE_TOP_PWR_OPTION			0x2CA8 +#define EXYNOS3_XUSBXTI_DURATION			0x341C +#define EXYNOS3_XXTI_DURATION				0x343C +#define EXYNOS3_EXT_REGULATOR_DURATION			0x361C +#define EXYNOS3_EXT_REGULATOR_COREBLK_DURATION		0x363C +#define XUSBXTI_DURATION				0x00000BB8 +#define XXTI_DURATION					XUSBXTI_DURATION +#define EXT_REGULATOR_DURATION				0x00001D4C +#define EXT_REGULATOR_COREBLK_DURATION			EXT_REGULATOR_DURATION + +/* for XXX_OPTION */ +#define EXYNOS3_OPTION_USE_SC_COUNTER			(1 << 0) +#define EXYNOS3_OPTION_USE_SC_FEEDBACK			(1 << 1) +#define EXYNOS3_OPTION_SKIP_DEACTIVATE_ACEACP_IN_PWDN	(1 << 7) +  /* For EXYNOS5 */  #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 @@  #include <linux/clk-provider.h>  #include <linux/of.h>  #include <linux/of_address.h> +#include <linux/notifier.h> +#include <linux/reboot.h>  #include "clk.h"  #include "clk-pll.h" @@ -23,6 +25,8 @@  #define CPU_CLK_STATUS		0xfc  #define MISC_DOUT1		0x558 +static void __iomem *reg_base; +  /* parent clock name list */  PNAME(mout_armclk_p)	= { "cplla", "cpllb" };  PNAME(mout_spi_p)	= { "div125", "div200" }; @@ -89,10 +93,30 @@ static const struct of_device_id ext_clk_match[] __initconst = {  	{},  }; +static int exynos5440_clk_restart_notify(struct notifier_block *this, +		unsigned long code, void *unused) +{ +	u32 val, status; + +	status = readl_relaxed(reg_base + 0xbc); +	val = readl_relaxed(reg_base + 0xcc); +	val = (val & 0xffff0000) | (status & 0xffff); +	writel_relaxed(val, reg_base + 0xcc); + +	return NOTIFY_DONE; +} + +/* + * Exynos5440 Clock restart notifier, handles restart functionality + */ +static struct notifier_block exynos5440_clk_restart_handler = { +	.notifier_call = exynos5440_clk_restart_notify, +	.priority = 128, +}; +  /* register exynos5440 clocks */  static void __init exynos5440_clk_init(struct device_node *np)  { -	void __iomem *reg_base;  	struct samsung_clk_provider *ctx;  	reg_base = of_iomap(np, 0); @@ -125,6 +149,9 @@ static void __init exynos5440_clk_init(struct device_node *np)  	samsung_clk_of_add_provider(np, ctx); +	if (register_restart_handler(&exynos5440_clk_restart_handler)) +		pr_warn("exynos5440 clock can't register restart handler\n"); +  	pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk"));  	pr_info("exynos5440 clock initialization complete\n");  } | 
