xref: /OK3568_Linux_fs/kernel/arch/arm/mach-imx/pm-imx7ulp.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2016 Freescale Semiconductor, Inc.
4*4882a593Smuzhiyun  * Copyright 2017-2018 NXP
5*4882a593Smuzhiyun  *   Author: Dong Aisheng <aisheng.dong@nxp.com>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/io.h>
9*4882a593Smuzhiyun #include <linux/of.h>
10*4882a593Smuzhiyun #include <linux/of_address.h>
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include "common.h"
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #define SMC_PMCTRL		0x10
15*4882a593Smuzhiyun #define BP_PMCTRL_PSTOPO        16
16*4882a593Smuzhiyun #define PSTOPO_PSTOP3		0x3
17*4882a593Smuzhiyun #define PSTOPO_PSTOP2		0x2
18*4882a593Smuzhiyun #define PSTOPO_PSTOP1		0x1
19*4882a593Smuzhiyun #define BP_PMCTRL_RUNM		8
20*4882a593Smuzhiyun #define RUNM_RUN		0
21*4882a593Smuzhiyun #define BP_PMCTRL_STOPM		0
22*4882a593Smuzhiyun #define STOPM_STOP		0
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #define BM_PMCTRL_PSTOPO	(3 << BP_PMCTRL_PSTOPO)
25*4882a593Smuzhiyun #define BM_PMCTRL_RUNM		(3 << BP_PMCTRL_RUNM)
26*4882a593Smuzhiyun #define BM_PMCTRL_STOPM		(7 << BP_PMCTRL_STOPM)
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun static void __iomem *smc1_base;
29*4882a593Smuzhiyun 
imx7ulp_set_lpm(enum ulp_cpu_pwr_mode mode)30*4882a593Smuzhiyun int imx7ulp_set_lpm(enum ulp_cpu_pwr_mode mode)
31*4882a593Smuzhiyun {
32*4882a593Smuzhiyun 	u32 val = readl_relaxed(smc1_base + SMC_PMCTRL);
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun 	/* clear all */
35*4882a593Smuzhiyun 	val &= ~(BM_PMCTRL_RUNM | BM_PMCTRL_STOPM | BM_PMCTRL_PSTOPO);
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun 	switch (mode) {
38*4882a593Smuzhiyun 	case ULP_PM_RUN:
39*4882a593Smuzhiyun 		/* system/bus clock enabled */
40*4882a593Smuzhiyun 		val |= PSTOPO_PSTOP3 << BP_PMCTRL_PSTOPO;
41*4882a593Smuzhiyun 		break;
42*4882a593Smuzhiyun 	case ULP_PM_WAIT:
43*4882a593Smuzhiyun 		/* system clock disabled, bus clock enabled */
44*4882a593Smuzhiyun 		val |= PSTOPO_PSTOP2 << BP_PMCTRL_PSTOPO;
45*4882a593Smuzhiyun 		break;
46*4882a593Smuzhiyun 	case ULP_PM_STOP:
47*4882a593Smuzhiyun 		/* system/bus clock disabled */
48*4882a593Smuzhiyun 		val |= PSTOPO_PSTOP1 << BP_PMCTRL_PSTOPO;
49*4882a593Smuzhiyun 		break;
50*4882a593Smuzhiyun 	default:
51*4882a593Smuzhiyun 		return -EINVAL;
52*4882a593Smuzhiyun 	}
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	writel_relaxed(val, smc1_base + SMC_PMCTRL);
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	return 0;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun 
imx7ulp_pm_init(void)59*4882a593Smuzhiyun void __init imx7ulp_pm_init(void)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun 	struct device_node *np;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-smc1");
64*4882a593Smuzhiyun 	smc1_base = of_iomap(np, 0);
65*4882a593Smuzhiyun 	of_node_put(np);
66*4882a593Smuzhiyun 	WARN_ON(!smc1_base);
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	imx7ulp_set_lpm(ULP_PM_RUN);
69*4882a593Smuzhiyun }
70