18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * RCPM(Run Control/Power Management) support 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2012-2015 Freescale Semiconductor Inc. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Chenhui Zhao <chenhui.zhao@freescale.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "%s: " fmt, __func__ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/types.h> 138c2ecf20Sopenharmony_ci#include <linux/errno.h> 148c2ecf20Sopenharmony_ci#include <linux/of_address.h> 158c2ecf20Sopenharmony_ci#include <linux/export.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <asm/io.h> 188c2ecf20Sopenharmony_ci#include <linux/fsl/guts.h> 198c2ecf20Sopenharmony_ci#include <asm/cputhreads.h> 208c2ecf20Sopenharmony_ci#include <asm/fsl_pm.h> 218c2ecf20Sopenharmony_ci#include <asm/smp.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic struct ccsr_rcpm_v1 __iomem *rcpm_v1_regs; 248c2ecf20Sopenharmony_cistatic struct ccsr_rcpm_v2 __iomem *rcpm_v2_regs; 258c2ecf20Sopenharmony_cistatic unsigned int fsl_supported_pm_modes; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic void rcpm_v1_irq_mask(int cpu) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci int hw_cpu = get_hard_smp_processor_id(cpu); 308c2ecf20Sopenharmony_ci unsigned int mask = 1 << hw_cpu; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci setbits32(&rcpm_v1_regs->cpmimr, mask); 338c2ecf20Sopenharmony_ci setbits32(&rcpm_v1_regs->cpmcimr, mask); 348c2ecf20Sopenharmony_ci setbits32(&rcpm_v1_regs->cpmmcmr, mask); 358c2ecf20Sopenharmony_ci setbits32(&rcpm_v1_regs->cpmnmimr, mask); 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic void rcpm_v2_irq_mask(int cpu) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci int hw_cpu = get_hard_smp_processor_id(cpu); 418c2ecf20Sopenharmony_ci unsigned int mask = 1 << hw_cpu; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci setbits32(&rcpm_v2_regs->tpmimr0, mask); 448c2ecf20Sopenharmony_ci setbits32(&rcpm_v2_regs->tpmcimr0, mask); 458c2ecf20Sopenharmony_ci setbits32(&rcpm_v2_regs->tpmmcmr0, mask); 468c2ecf20Sopenharmony_ci setbits32(&rcpm_v2_regs->tpmnmimr0, mask); 478c2ecf20Sopenharmony_ci} 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic void rcpm_v1_irq_unmask(int cpu) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci int hw_cpu = get_hard_smp_processor_id(cpu); 528c2ecf20Sopenharmony_ci unsigned int mask = 1 << hw_cpu; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci clrbits32(&rcpm_v1_regs->cpmimr, mask); 558c2ecf20Sopenharmony_ci clrbits32(&rcpm_v1_regs->cpmcimr, mask); 568c2ecf20Sopenharmony_ci clrbits32(&rcpm_v1_regs->cpmmcmr, mask); 578c2ecf20Sopenharmony_ci clrbits32(&rcpm_v1_regs->cpmnmimr, mask); 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistatic void rcpm_v2_irq_unmask(int cpu) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci int hw_cpu = get_hard_smp_processor_id(cpu); 638c2ecf20Sopenharmony_ci unsigned int mask = 1 << hw_cpu; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci clrbits32(&rcpm_v2_regs->tpmimr0, mask); 668c2ecf20Sopenharmony_ci clrbits32(&rcpm_v2_regs->tpmcimr0, mask); 678c2ecf20Sopenharmony_ci clrbits32(&rcpm_v2_regs->tpmmcmr0, mask); 688c2ecf20Sopenharmony_ci clrbits32(&rcpm_v2_regs->tpmnmimr0, mask); 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cistatic void rcpm_v1_set_ip_power(bool enable, u32 mask) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci if (enable) 748c2ecf20Sopenharmony_ci setbits32(&rcpm_v1_regs->ippdexpcr, mask); 758c2ecf20Sopenharmony_ci else 768c2ecf20Sopenharmony_ci clrbits32(&rcpm_v1_regs->ippdexpcr, mask); 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic void rcpm_v2_set_ip_power(bool enable, u32 mask) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci if (enable) 828c2ecf20Sopenharmony_ci setbits32(&rcpm_v2_regs->ippdexpcr[0], mask); 838c2ecf20Sopenharmony_ci else 848c2ecf20Sopenharmony_ci clrbits32(&rcpm_v2_regs->ippdexpcr[0], mask); 858c2ecf20Sopenharmony_ci} 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistatic void rcpm_v1_cpu_enter_state(int cpu, int state) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci int hw_cpu = get_hard_smp_processor_id(cpu); 908c2ecf20Sopenharmony_ci unsigned int mask = 1 << hw_cpu; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci switch (state) { 938c2ecf20Sopenharmony_ci case E500_PM_PH10: 948c2ecf20Sopenharmony_ci setbits32(&rcpm_v1_regs->cdozcr, mask); 958c2ecf20Sopenharmony_ci break; 968c2ecf20Sopenharmony_ci case E500_PM_PH15: 978c2ecf20Sopenharmony_ci setbits32(&rcpm_v1_regs->cnapcr, mask); 988c2ecf20Sopenharmony_ci break; 998c2ecf20Sopenharmony_ci default: 1008c2ecf20Sopenharmony_ci pr_warn("Unknown cpu PM state (%d)\n", state); 1018c2ecf20Sopenharmony_ci break; 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic void rcpm_v2_cpu_enter_state(int cpu, int state) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci int hw_cpu = get_hard_smp_processor_id(cpu); 1088c2ecf20Sopenharmony_ci u32 mask = 1 << cpu_core_index_of_thread(cpu); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci switch (state) { 1118c2ecf20Sopenharmony_ci case E500_PM_PH10: 1128c2ecf20Sopenharmony_ci /* one bit corresponds to one thread for PH10 of 6500 */ 1138c2ecf20Sopenharmony_ci setbits32(&rcpm_v2_regs->tph10setr0, 1 << hw_cpu); 1148c2ecf20Sopenharmony_ci break; 1158c2ecf20Sopenharmony_ci case E500_PM_PH15: 1168c2ecf20Sopenharmony_ci setbits32(&rcpm_v2_regs->pcph15setr, mask); 1178c2ecf20Sopenharmony_ci break; 1188c2ecf20Sopenharmony_ci case E500_PM_PH20: 1198c2ecf20Sopenharmony_ci setbits32(&rcpm_v2_regs->pcph20setr, mask); 1208c2ecf20Sopenharmony_ci break; 1218c2ecf20Sopenharmony_ci case E500_PM_PH30: 1228c2ecf20Sopenharmony_ci setbits32(&rcpm_v2_regs->pcph30setr, mask); 1238c2ecf20Sopenharmony_ci break; 1248c2ecf20Sopenharmony_ci default: 1258c2ecf20Sopenharmony_ci pr_warn("Unknown cpu PM state (%d)\n", state); 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistatic void rcpm_v1_cpu_die(int cpu) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci rcpm_v1_cpu_enter_state(cpu, E500_PM_PH15); 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64 1358c2ecf20Sopenharmony_cistatic void qoriq_disable_thread(int cpu) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci int thread = cpu_thread_in_core(cpu); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci book3e_stop_thread(thread); 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci#endif 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cistatic void rcpm_v2_cpu_die(int cpu) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64 1468c2ecf20Sopenharmony_ci int primary; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci if (threads_per_core == 2) { 1498c2ecf20Sopenharmony_ci primary = cpu_first_thread_sibling(cpu); 1508c2ecf20Sopenharmony_ci if (cpu_is_offline(primary) && cpu_is_offline(primary + 1)) { 1518c2ecf20Sopenharmony_ci /* if both threads are offline, put the cpu in PH20 */ 1528c2ecf20Sopenharmony_ci rcpm_v2_cpu_enter_state(cpu, E500_PM_PH20); 1538c2ecf20Sopenharmony_ci } else { 1548c2ecf20Sopenharmony_ci /* if only one thread is offline, disable the thread */ 1558c2ecf20Sopenharmony_ci qoriq_disable_thread(cpu); 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci } 1588c2ecf20Sopenharmony_ci#endif 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci if (threads_per_core == 1) 1618c2ecf20Sopenharmony_ci rcpm_v2_cpu_enter_state(cpu, E500_PM_PH20); 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic void rcpm_v1_cpu_exit_state(int cpu, int state) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci int hw_cpu = get_hard_smp_processor_id(cpu); 1678c2ecf20Sopenharmony_ci unsigned int mask = 1 << hw_cpu; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci switch (state) { 1708c2ecf20Sopenharmony_ci case E500_PM_PH10: 1718c2ecf20Sopenharmony_ci clrbits32(&rcpm_v1_regs->cdozcr, mask); 1728c2ecf20Sopenharmony_ci break; 1738c2ecf20Sopenharmony_ci case E500_PM_PH15: 1748c2ecf20Sopenharmony_ci clrbits32(&rcpm_v1_regs->cnapcr, mask); 1758c2ecf20Sopenharmony_ci break; 1768c2ecf20Sopenharmony_ci default: 1778c2ecf20Sopenharmony_ci pr_warn("Unknown cpu PM state (%d)\n", state); 1788c2ecf20Sopenharmony_ci break; 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic void rcpm_v1_cpu_up_prepare(int cpu) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci rcpm_v1_cpu_exit_state(cpu, E500_PM_PH15); 1858c2ecf20Sopenharmony_ci rcpm_v1_irq_unmask(cpu); 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic void rcpm_v2_cpu_exit_state(int cpu, int state) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci int hw_cpu = get_hard_smp_processor_id(cpu); 1918c2ecf20Sopenharmony_ci u32 mask = 1 << cpu_core_index_of_thread(cpu); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci switch (state) { 1948c2ecf20Sopenharmony_ci case E500_PM_PH10: 1958c2ecf20Sopenharmony_ci setbits32(&rcpm_v2_regs->tph10clrr0, 1 << hw_cpu); 1968c2ecf20Sopenharmony_ci break; 1978c2ecf20Sopenharmony_ci case E500_PM_PH15: 1988c2ecf20Sopenharmony_ci setbits32(&rcpm_v2_regs->pcph15clrr, mask); 1998c2ecf20Sopenharmony_ci break; 2008c2ecf20Sopenharmony_ci case E500_PM_PH20: 2018c2ecf20Sopenharmony_ci setbits32(&rcpm_v2_regs->pcph20clrr, mask); 2028c2ecf20Sopenharmony_ci break; 2038c2ecf20Sopenharmony_ci case E500_PM_PH30: 2048c2ecf20Sopenharmony_ci setbits32(&rcpm_v2_regs->pcph30clrr, mask); 2058c2ecf20Sopenharmony_ci break; 2068c2ecf20Sopenharmony_ci default: 2078c2ecf20Sopenharmony_ci pr_warn("Unknown cpu PM state (%d)\n", state); 2088c2ecf20Sopenharmony_ci } 2098c2ecf20Sopenharmony_ci} 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_cistatic void rcpm_v2_cpu_up_prepare(int cpu) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci rcpm_v2_cpu_exit_state(cpu, E500_PM_PH20); 2148c2ecf20Sopenharmony_ci rcpm_v2_irq_unmask(cpu); 2158c2ecf20Sopenharmony_ci} 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_cistatic int rcpm_v1_plat_enter_state(int state) 2188c2ecf20Sopenharmony_ci{ 2198c2ecf20Sopenharmony_ci u32 *pmcsr_reg = &rcpm_v1_regs->powmgtcsr; 2208c2ecf20Sopenharmony_ci int ret = 0; 2218c2ecf20Sopenharmony_ci int result; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci switch (state) { 2248c2ecf20Sopenharmony_ci case PLAT_PM_SLEEP: 2258c2ecf20Sopenharmony_ci setbits32(pmcsr_reg, RCPM_POWMGTCSR_SLP); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci /* Upon resume, wait for RCPM_POWMGTCSR_SLP bit to be clear. */ 2288c2ecf20Sopenharmony_ci result = spin_event_timeout( 2298c2ecf20Sopenharmony_ci !(in_be32(pmcsr_reg) & RCPM_POWMGTCSR_SLP), 10000, 10); 2308c2ecf20Sopenharmony_ci if (!result) { 2318c2ecf20Sopenharmony_ci pr_err("timeout waiting for SLP bit to be cleared\n"); 2328c2ecf20Sopenharmony_ci ret = -ETIMEDOUT; 2338c2ecf20Sopenharmony_ci } 2348c2ecf20Sopenharmony_ci break; 2358c2ecf20Sopenharmony_ci default: 2368c2ecf20Sopenharmony_ci pr_warn("Unknown platform PM state (%d)", state); 2378c2ecf20Sopenharmony_ci ret = -EINVAL; 2388c2ecf20Sopenharmony_ci } 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci return ret; 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_cistatic int rcpm_v2_plat_enter_state(int state) 2448c2ecf20Sopenharmony_ci{ 2458c2ecf20Sopenharmony_ci u32 *pmcsr_reg = &rcpm_v2_regs->powmgtcsr; 2468c2ecf20Sopenharmony_ci int ret = 0; 2478c2ecf20Sopenharmony_ci int result; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci switch (state) { 2508c2ecf20Sopenharmony_ci case PLAT_PM_LPM20: 2518c2ecf20Sopenharmony_ci /* clear previous LPM20 status */ 2528c2ecf20Sopenharmony_ci setbits32(pmcsr_reg, RCPM_POWMGTCSR_P_LPM20_ST); 2538c2ecf20Sopenharmony_ci /* enter LPM20 status */ 2548c2ecf20Sopenharmony_ci setbits32(pmcsr_reg, RCPM_POWMGTCSR_LPM20_RQ); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci /* At this point, the device is in LPM20 status. */ 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci /* resume ... */ 2598c2ecf20Sopenharmony_ci result = spin_event_timeout( 2608c2ecf20Sopenharmony_ci !(in_be32(pmcsr_reg) & RCPM_POWMGTCSR_LPM20_ST), 10000, 10); 2618c2ecf20Sopenharmony_ci if (!result) { 2628c2ecf20Sopenharmony_ci pr_err("timeout waiting for LPM20 bit to be cleared\n"); 2638c2ecf20Sopenharmony_ci ret = -ETIMEDOUT; 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci break; 2668c2ecf20Sopenharmony_ci default: 2678c2ecf20Sopenharmony_ci pr_warn("Unknown platform PM state (%d)\n", state); 2688c2ecf20Sopenharmony_ci ret = -EINVAL; 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci return ret; 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_cistatic int rcpm_v1_plat_enter_sleep(void) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci return rcpm_v1_plat_enter_state(PLAT_PM_SLEEP); 2778c2ecf20Sopenharmony_ci} 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_cistatic int rcpm_v2_plat_enter_sleep(void) 2808c2ecf20Sopenharmony_ci{ 2818c2ecf20Sopenharmony_ci return rcpm_v2_plat_enter_state(PLAT_PM_LPM20); 2828c2ecf20Sopenharmony_ci} 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_cistatic void rcpm_common_freeze_time_base(u32 *tben_reg, int freeze) 2858c2ecf20Sopenharmony_ci{ 2868c2ecf20Sopenharmony_ci static u32 mask; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci if (freeze) { 2898c2ecf20Sopenharmony_ci mask = in_be32(tben_reg); 2908c2ecf20Sopenharmony_ci clrbits32(tben_reg, mask); 2918c2ecf20Sopenharmony_ci } else { 2928c2ecf20Sopenharmony_ci setbits32(tben_reg, mask); 2938c2ecf20Sopenharmony_ci } 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci /* read back to push the previous write */ 2968c2ecf20Sopenharmony_ci in_be32(tben_reg); 2978c2ecf20Sopenharmony_ci} 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_cistatic void rcpm_v1_freeze_time_base(bool freeze) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci rcpm_common_freeze_time_base(&rcpm_v1_regs->ctbenr, freeze); 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic void rcpm_v2_freeze_time_base(bool freeze) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci rcpm_common_freeze_time_base(&rcpm_v2_regs->pctbenr, freeze); 3078c2ecf20Sopenharmony_ci} 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_cistatic unsigned int rcpm_get_pm_modes(void) 3108c2ecf20Sopenharmony_ci{ 3118c2ecf20Sopenharmony_ci return fsl_supported_pm_modes; 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_cistatic const struct fsl_pm_ops qoriq_rcpm_v1_ops = { 3158c2ecf20Sopenharmony_ci .irq_mask = rcpm_v1_irq_mask, 3168c2ecf20Sopenharmony_ci .irq_unmask = rcpm_v1_irq_unmask, 3178c2ecf20Sopenharmony_ci .cpu_enter_state = rcpm_v1_cpu_enter_state, 3188c2ecf20Sopenharmony_ci .cpu_exit_state = rcpm_v1_cpu_exit_state, 3198c2ecf20Sopenharmony_ci .cpu_up_prepare = rcpm_v1_cpu_up_prepare, 3208c2ecf20Sopenharmony_ci .cpu_die = rcpm_v1_cpu_die, 3218c2ecf20Sopenharmony_ci .plat_enter_sleep = rcpm_v1_plat_enter_sleep, 3228c2ecf20Sopenharmony_ci .set_ip_power = rcpm_v1_set_ip_power, 3238c2ecf20Sopenharmony_ci .freeze_time_base = rcpm_v1_freeze_time_base, 3248c2ecf20Sopenharmony_ci .get_pm_modes = rcpm_get_pm_modes, 3258c2ecf20Sopenharmony_ci}; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_cistatic const struct fsl_pm_ops qoriq_rcpm_v2_ops = { 3288c2ecf20Sopenharmony_ci .irq_mask = rcpm_v2_irq_mask, 3298c2ecf20Sopenharmony_ci .irq_unmask = rcpm_v2_irq_unmask, 3308c2ecf20Sopenharmony_ci .cpu_enter_state = rcpm_v2_cpu_enter_state, 3318c2ecf20Sopenharmony_ci .cpu_exit_state = rcpm_v2_cpu_exit_state, 3328c2ecf20Sopenharmony_ci .cpu_up_prepare = rcpm_v2_cpu_up_prepare, 3338c2ecf20Sopenharmony_ci .cpu_die = rcpm_v2_cpu_die, 3348c2ecf20Sopenharmony_ci .plat_enter_sleep = rcpm_v2_plat_enter_sleep, 3358c2ecf20Sopenharmony_ci .set_ip_power = rcpm_v2_set_ip_power, 3368c2ecf20Sopenharmony_ci .freeze_time_base = rcpm_v2_freeze_time_base, 3378c2ecf20Sopenharmony_ci .get_pm_modes = rcpm_get_pm_modes, 3388c2ecf20Sopenharmony_ci}; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_cistatic const struct of_device_id rcpm_matches[] = { 3418c2ecf20Sopenharmony_ci { 3428c2ecf20Sopenharmony_ci .compatible = "fsl,qoriq-rcpm-1.0", 3438c2ecf20Sopenharmony_ci .data = &qoriq_rcpm_v1_ops, 3448c2ecf20Sopenharmony_ci }, 3458c2ecf20Sopenharmony_ci { 3468c2ecf20Sopenharmony_ci .compatible = "fsl,qoriq-rcpm-2.0", 3478c2ecf20Sopenharmony_ci .data = &qoriq_rcpm_v2_ops, 3488c2ecf20Sopenharmony_ci }, 3498c2ecf20Sopenharmony_ci { 3508c2ecf20Sopenharmony_ci .compatible = "fsl,qoriq-rcpm-2.1", 3518c2ecf20Sopenharmony_ci .data = &qoriq_rcpm_v2_ops, 3528c2ecf20Sopenharmony_ci }, 3538c2ecf20Sopenharmony_ci {}, 3548c2ecf20Sopenharmony_ci}; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ciint __init fsl_rcpm_init(void) 3578c2ecf20Sopenharmony_ci{ 3588c2ecf20Sopenharmony_ci struct device_node *np; 3598c2ecf20Sopenharmony_ci const struct of_device_id *match; 3608c2ecf20Sopenharmony_ci void __iomem *base; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci np = of_find_matching_node_and_match(NULL, rcpm_matches, &match); 3638c2ecf20Sopenharmony_ci if (!np) 3648c2ecf20Sopenharmony_ci return 0; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci base = of_iomap(np, 0); 3678c2ecf20Sopenharmony_ci of_node_put(np); 3688c2ecf20Sopenharmony_ci if (!base) { 3698c2ecf20Sopenharmony_ci pr_err("of_iomap() error.\n"); 3708c2ecf20Sopenharmony_ci return -ENOMEM; 3718c2ecf20Sopenharmony_ci } 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci rcpm_v1_regs = base; 3748c2ecf20Sopenharmony_ci rcpm_v2_regs = base; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci /* support sleep by default */ 3778c2ecf20Sopenharmony_ci fsl_supported_pm_modes = FSL_PM_SLEEP; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci qoriq_pm_ops = match->data; 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci return 0; 3828c2ecf20Sopenharmony_ci} 383