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