162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2016 Freescale Semiconductor, Inc. 462306a36Sopenharmony_ci * Copyright 2017-2018 NXP 562306a36Sopenharmony_ci * Author: Dong Aisheng <aisheng.dong@nxp.com> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/io.h> 962306a36Sopenharmony_ci#include <linux/of.h> 1062306a36Sopenharmony_ci#include <linux/of_address.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "common.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define SMC_PMCTRL 0x10 1562306a36Sopenharmony_ci#define BP_PMCTRL_PSTOPO 16 1662306a36Sopenharmony_ci#define PSTOPO_PSTOP3 0x3 1762306a36Sopenharmony_ci#define PSTOPO_PSTOP2 0x2 1862306a36Sopenharmony_ci#define PSTOPO_PSTOP1 0x1 1962306a36Sopenharmony_ci#define BP_PMCTRL_RUNM 8 2062306a36Sopenharmony_ci#define RUNM_RUN 0 2162306a36Sopenharmony_ci#define BP_PMCTRL_STOPM 0 2262306a36Sopenharmony_ci#define STOPM_STOP 0 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define BM_PMCTRL_PSTOPO (3 << BP_PMCTRL_PSTOPO) 2562306a36Sopenharmony_ci#define BM_PMCTRL_RUNM (3 << BP_PMCTRL_RUNM) 2662306a36Sopenharmony_ci#define BM_PMCTRL_STOPM (7 << BP_PMCTRL_STOPM) 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic void __iomem *smc1_base; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ciint imx7ulp_set_lpm(enum ulp_cpu_pwr_mode mode) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci u32 val = readl_relaxed(smc1_base + SMC_PMCTRL); 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci /* clear all */ 3562306a36Sopenharmony_ci val &= ~(BM_PMCTRL_RUNM | BM_PMCTRL_STOPM | BM_PMCTRL_PSTOPO); 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci switch (mode) { 3862306a36Sopenharmony_ci case ULP_PM_RUN: 3962306a36Sopenharmony_ci /* system/bus clock enabled */ 4062306a36Sopenharmony_ci val |= PSTOPO_PSTOP3 << BP_PMCTRL_PSTOPO; 4162306a36Sopenharmony_ci break; 4262306a36Sopenharmony_ci case ULP_PM_WAIT: 4362306a36Sopenharmony_ci /* system clock disabled, bus clock enabled */ 4462306a36Sopenharmony_ci val |= PSTOPO_PSTOP2 << BP_PMCTRL_PSTOPO; 4562306a36Sopenharmony_ci break; 4662306a36Sopenharmony_ci case ULP_PM_STOP: 4762306a36Sopenharmony_ci /* system/bus clock disabled */ 4862306a36Sopenharmony_ci val |= PSTOPO_PSTOP1 << BP_PMCTRL_PSTOPO; 4962306a36Sopenharmony_ci break; 5062306a36Sopenharmony_ci default: 5162306a36Sopenharmony_ci return -EINVAL; 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci writel_relaxed(val, smc1_base + SMC_PMCTRL); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci return 0; 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_civoid __init imx7ulp_pm_init(void) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci struct device_node *np; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-smc1"); 6462306a36Sopenharmony_ci smc1_base = of_iomap(np, 0); 6562306a36Sopenharmony_ci of_node_put(np); 6662306a36Sopenharmony_ci WARN_ON(!smc1_base); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci imx7ulp_set_lpm(ULP_PM_RUN); 6962306a36Sopenharmony_ci} 70