^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * OMAP4 PRM module functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2011-2012 Texas Instruments, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2010 Nokia Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Benoît Cousson
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Paul Walmsley
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Rajendra Nayak <rnayak@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/cpu_pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "soc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "iomap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "vp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "prm44xx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "prcm43xx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "prm-regbits-44xx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "prcm44xx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "prminst44xx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "powerdomain.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include "pm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* Static data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static void omap44xx_prm_read_pending_irqs(unsigned long *events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static void omap44xx_prm_ocp_barrier(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static void omap44xx_prm_restore_irqen(u32 *saved_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static void omap44xx_prm_reconfigure_io_chain(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static const struct omap_prcm_irq omap4_prcm_irqs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) OMAP_PRCM_IRQ("io", 9, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static struct omap_prcm_irq_setup omap4_prcm_irq_setup = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .ack = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .mask = OMAP4_PRM_IRQENABLE_MPU_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .pm_ctrl = OMAP4_PRM_IO_PMCTRL_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .nr_regs = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .irqs = omap4_prcm_irqs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .nr_irqs = ARRAY_SIZE(omap4_prcm_irqs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .read_pending_irqs = &omap44xx_prm_read_pending_irqs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .ocp_barrier = &omap44xx_prm_ocp_barrier,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .save_and_clear_irqen = &omap44xx_prm_save_and_clear_irqen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) .restore_irqen = &omap44xx_prm_restore_irqen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) .reconfigure_io_chain = &omap44xx_prm_reconfigure_io_chain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct omap_prm_irq_context {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned long irq_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) unsigned long pm_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static struct omap_prm_irq_context omap_prm_context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * omap44xx_prm_reset_src_map - map from bits in the PRM_RSTST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * hardware register (which are specific to OMAP44xx SoCs) to reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * source ID bit shifts (which is an OMAP SoC-independent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * enumeration)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static struct prm_reset_src_map omap44xx_prm_reset_src_map[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) { OMAP4430_GLOBAL_WARM_SW_RST_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) { OMAP4430_GLOBAL_COLD_RST_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) { OMAP4430_MPU_SECURITY_VIOL_RST_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) { OMAP4430_MPU_WDT_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) { OMAP4430_SECURE_WDT_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) { OMAP4430_EXTERNAL_WARM_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) { OMAP4430_VDD_MPU_VOLT_MGR_RST_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) OMAP_VDD_MPU_VM_RST_SRC_ID_SHIFT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) { OMAP4430_VDD_IVA_VOLT_MGR_RST_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) OMAP_VDD_IVA_VM_RST_SRC_ID_SHIFT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) { OMAP4430_VDD_CORE_VOLT_MGR_RST_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) OMAP_VDD_CORE_VM_RST_SRC_ID_SHIFT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) { OMAP4430_ICEPICK_RST_SHIFT, OMAP_ICEPICK_RST_SRC_ID_SHIFT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) { OMAP4430_C2C_RST_SHIFT, OMAP_C2C_RST_SRC_ID_SHIFT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) { -1, -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* PRM low-level functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /* Read a register in a CM/PRM instance in the PRM module */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static u32 omap4_prm_read_inst_reg(s16 inst, u16 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return readl_relaxed(prm_base.va + inst + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /* Write into a register in a CM/PRM instance in the PRM module */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) writel_relaxed(val, prm_base.va + inst + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* Read-modify-write a register in a PRM module. Caller must lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) v = omap4_prm_read_inst_reg(inst, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) v &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) v |= bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) omap4_prm_write_inst_reg(v, inst, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /* PRM VP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * struct omap4_vp - OMAP4 VP register access description.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * @irqstatus_mpu: offset to IRQSTATUS_MPU register for VP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct omap4_vp {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) u32 irqstatus_mpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) u32 tranxdone_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static struct omap4_vp omap4_vp[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) [OMAP4_VP_VDD_MPU_ID] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) [OMAP4_VP_VDD_IVA_ID] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) [OMAP4_VP_VDD_CORE_ID] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .irqstatus_mpu = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static u32 omap4_prm_vp_check_txdone(u8 vp_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct omap4_vp *vp = &omap4_vp[vp_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) u32 irqstatus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) irqstatus = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) OMAP4430_PRM_OCP_SOCKET_INST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) vp->irqstatus_mpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return irqstatus & vp->tranxdone_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static void omap4_prm_vp_clear_txdone(u8 vp_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct omap4_vp *vp = &omap4_vp[vp_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) omap4_prminst_write_inst_reg(vp->tranxdone_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) OMAP4430_PRM_PARTITION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) OMAP4430_PRM_OCP_SOCKET_INST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) vp->irqstatus_mpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) u32 omap4_prm_vcvp_read(u8 offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) s32 inst = omap4_prmst_get_prm_dev_inst();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (inst == PRM_INSTANCE_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) inst, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) void omap4_prm_vcvp_write(u32 val, u8 offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) s32 inst = omap4_prmst_get_prm_dev_inst();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (inst == PRM_INSTANCE_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) inst, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) s32 inst = omap4_prmst_get_prm_dev_inst();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (inst == PRM_INSTANCE_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return omap4_prminst_rmw_inst_reg_bits(mask, bits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) OMAP4430_PRM_PARTITION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) inst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static inline u32 _read_pending_irq_reg(u16 irqen_offs, u16 irqst_offs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) u32 mask, st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /* XXX read mask from RAM? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) mask = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) irqen_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) st = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, irqst_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return mask & st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * omap44xx_prm_read_pending_irqs - read pending PRM MPU IRQs into @events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * @events: ptr to two consecutive u32s, preallocated by caller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * Read PRM_IRQSTATUS_MPU* bits, AND'ed with the currently-enabled PRM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * MPU IRQs, and store the result into the two u32s pointed to by @events.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * No return value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) static void omap44xx_prm_read_pending_irqs(unsigned long *events)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) for (i = 0; i < omap4_prcm_irq_setup.nr_regs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) events[i] = _read_pending_irq_reg(omap4_prcm_irq_setup.mask +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) i * 4, omap4_prcm_irq_setup.ack + i * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * omap44xx_prm_ocp_barrier - force buffered MPU writes to the PRM to complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * Force any buffered writes to the PRM IP block to complete. Needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * by the PRM IRQ handler, which reads and writes directly to the IP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * block, to avoid race conditions after acknowledging or clearing IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * bits. No return value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static void omap44xx_prm_ocp_barrier(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) OMAP4_REVISION_PRM_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * omap44xx_prm_save_and_clear_irqen - save/clear PRM_IRQENABLE_MPU* regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * @saved_mask: ptr to a u32 array to save IRQENABLE bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * Save the PRM_IRQENABLE_MPU and PRM_IRQENABLE_MPU_2 registers to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * @saved_mask. @saved_mask must be allocated by the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * Intended to be used in the PRM interrupt handler suspend callback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * The OCP barrier is needed to ensure the write to disable PRM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * interrupts reaches the PRM before returning; otherwise, spurious
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * interrupts might occur. No return value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) u16 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) for (i = 0; i < omap4_prcm_irq_setup.nr_regs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) reg = omap4_prcm_irq_setup.mask + i * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) saved_mask[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) omap4_prm_write_inst_reg(0, OMAP4430_PRM_OCP_SOCKET_INST, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /* OCP barrier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) OMAP4_REVISION_PRM_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * omap44xx_prm_restore_irqen - set PRM_IRQENABLE_MPU* registers from args
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * @saved_mask: ptr to a u32 array of IRQENABLE bits saved previously
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * Restore the PRM_IRQENABLE_MPU and PRM_IRQENABLE_MPU_2 registers from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * @saved_mask. Intended to be used in the PRM interrupt handler resume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * callback to restore values saved by omap44xx_prm_save_and_clear_irqen().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * No OCP barrier should be needed here; any pending PRM interrupts will fire
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * once the writes reach the PRM. No return value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static void omap44xx_prm_restore_irqen(u32 *saved_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) for (i = 0; i < omap4_prcm_irq_setup.nr_regs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) omap4_prm_write_inst_reg(saved_mask[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) OMAP4430_PRM_OCP_SOCKET_INST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) omap4_prcm_irq_setup.mask + i * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * omap44xx_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * Clear any previously-latched I/O wakeup events and ensure that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * I/O wakeup gates are aligned with the current mux settings. Works
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * deasserting WUCLKIN and waiting for WUCLKOUT to be deasserted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * No return value. XXX Are the final two steps necessary?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static void omap44xx_prm_reconfigure_io_chain(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) s32 inst = omap4_prmst_get_prm_dev_inst();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (inst == PRM_INSTANCE_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) /* Trigger WUCLKIN enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) OMAP4430_WUCLK_CTRL_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) inst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) omap4_prcm_irq_setup.pm_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) omap_test_timeout(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) (((omap4_prm_read_inst_reg(inst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) omap4_prcm_irq_setup.pm_ctrl) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) OMAP4430_WUCLK_STATUS_MASK) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) OMAP4430_WUCLK_STATUS_SHIFT) == 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) MAX_IOPAD_LATCH_TIME, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (i == MAX_IOPAD_LATCH_TIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) pr_warn("PRM: I/O chain clock line assertion timed out\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) /* Trigger WUCLKIN disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, 0x0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) inst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) omap4_prcm_irq_setup.pm_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) omap_test_timeout(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) (((omap4_prm_read_inst_reg(inst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) omap4_prcm_irq_setup.pm_ctrl) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) OMAP4430_WUCLK_STATUS_MASK) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) OMAP4430_WUCLK_STATUS_SHIFT) == 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) MAX_IOPAD_LATCH_TIME, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (i == MAX_IOPAD_LATCH_TIME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) pr_warn("PRM: I/O chain clock line deassertion timed out\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) * omap44xx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * Activates the I/O wakeup event latches and allows events logged by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * those latches to signal a wakeup event to the PRCM. For I/O wakeups
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * to occur, WAKEUPENABLE bits must be set in the pad mux registers, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * omap44xx_prm_reconfigure_io_chain() must be called. No return value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static void omap44xx_prm_enable_io_wakeup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) s32 inst = omap4_prmst_get_prm_dev_inst();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (inst == PRM_INSTANCE_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) omap4_prm_rmw_inst_reg_bits(OMAP4430_GLOBAL_WUEN_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) OMAP4430_GLOBAL_WUEN_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) inst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) omap4_prcm_irq_setup.pm_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * omap44xx_prm_read_reset_sources - return the last SoC reset source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * Return a u32 representing the last reset sources of the SoC. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * returned reset source bits are standardized across OMAP SoCs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static u32 omap44xx_prm_read_reset_sources(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct prm_reset_src_map *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) u32 r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) s32 inst = omap4_prmst_get_prm_dev_inst();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (inst == PRM_INSTANCE_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) v = omap4_prm_read_inst_reg(inst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) OMAP4_RM_RSTST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) p = omap44xx_prm_reset_src_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) while (p->reg_shift >= 0 && p->std_shift >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (v & (1 << p->reg_shift))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) r |= 1 << p->std_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * omap44xx_prm_was_any_context_lost_old - was module hardware context lost?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * @part: PRM partition ID (e.g., OMAP4430_PRM_PARTITION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * @inst: PRM instance offset (e.g., OMAP4430_PRM_MPU_INST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * @idx: CONTEXT register offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * Return 1 if any bits were set in the *_CONTEXT_* register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * identified by (@part, @inst, @idx), which means that some context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * was lost for that module; otherwise, return 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static bool omap44xx_prm_was_any_context_lost_old(u8 part, s16 inst, u16 idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return (omap4_prminst_read_inst_reg(part, inst, idx)) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * omap44xx_prm_clear_context_lost_flags_old - clear context loss flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * @part: PRM partition ID (e.g., OMAP4430_PRM_PARTITION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * @inst: PRM instance offset (e.g., OMAP4430_PRM_MPU_INST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * @idx: CONTEXT register offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * Clear hardware context loss bits for the module identified by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * (@part, @inst, @idx). No return value. XXX Writes to reserved bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * is there a way to avoid this?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) static void omap44xx_prm_clear_context_loss_flags_old(u8 part, s16 inst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) u16 idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) omap4_prminst_write_inst_reg(0xffffffff, part, inst, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) /* Powerdomain low-level functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) omap4_prminst_rmw_inst_reg_bits(OMAP_POWERSTATE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) (pwrst << OMAP_POWERSTATE_SHIFT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) pwrdm->prcm_partition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) static int omap4_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) OMAP4_PM_PWSTCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) v &= OMAP_POWERSTATE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) v >>= OMAP_POWERSTATE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) static int omap4_pwrdm_read_pwrst(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) OMAP4_PM_PWSTST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) v &= OMAP_POWERSTATEST_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) v >>= OMAP_POWERSTATEST_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static int omap4_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) OMAP4_PM_PWSTST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) v &= OMAP4430_LASTPOWERSTATEENTERED_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) v >>= OMAP4430_LASTPOWERSTATEENTERED_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) static int omap4_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) (1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) pwrdm->prcm_partition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static int omap4_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) omap4_prminst_rmw_inst_reg_bits(OMAP4430_LASTPOWERSTATEENTERED_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) OMAP4430_LASTPOWERSTATEENTERED_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) pwrdm->prcm_partition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) pwrdm->prcm_offs, OMAP4_PM_PWSTST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) static int omap4_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) v = pwrst << __ffs(OMAP4430_LOGICRETSTATE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOGICRETSTATE_MASK, v,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) pwrdm->prcm_partition, pwrdm->prcm_offs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) OMAP4_PM_PWSTCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) static int omap4_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) u8 pwrst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) u32 m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) pwrdm->prcm_partition, pwrdm->prcm_offs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) OMAP4_PM_PWSTCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) static int omap4_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) u8 pwrst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) u32 m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) pwrdm->prcm_partition, pwrdm->prcm_offs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) OMAP4_PM_PWSTCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) static int omap4_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) OMAP4_PM_PWSTST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) v &= OMAP4430_LOGICSTATEST_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) v >>= OMAP4430_LOGICSTATEST_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) OMAP4_PM_PWSTCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) v &= OMAP4430_LOGICRETSTATE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) v >>= OMAP4430_LOGICRETSTATE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * omap4_pwrdm_read_prev_logic_pwrst - read the previous logic powerstate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) * @pwrdm: struct powerdomain * to read the state for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) * Reads the previous logic powerstate for a powerdomain. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) * function must determine the previous logic powerstate by first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) * checking the previous powerstate for the domain. If that was OFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) * then logic has been lost. If previous state was RETENTION, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) * function reads the setting for the next retention logic state to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) * see the actual value. In every other case, the logic is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) * depending whether the logic was retained or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) static int omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) int state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) state = omap4_pwrdm_read_prev_pwrst(pwrdm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (state == PWRDM_POWER_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return PWRDM_POWER_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (state != PWRDM_POWER_RET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return PWRDM_POWER_RET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return omap4_pwrdm_read_logic_retst(pwrdm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) u32 m, v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) OMAP4_PM_PWSTST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) v &= m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) v >>= __ffs(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) u32 m, v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) OMAP4_PM_PWSTCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) v &= m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) v >>= __ffs(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * omap4_pwrdm_read_prev_mem_pwrst - reads the previous memory powerstate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * @pwrdm: struct powerdomain * to read mem powerstate for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * @bank: memory bank index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * Reads the previous memory powerstate for a powerdomain. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * function must determine the previous memory powerstate by first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * checking the previous powerstate for the domain. If that was OFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) * then logic has been lost. If previous state was RETENTION, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * function reads the setting for the next memory retention state to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) * see the actual value. In every other case, the logic is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) * depending whether logic was retained or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) int state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) state = omap4_pwrdm_read_prev_pwrst(pwrdm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (state == PWRDM_POWER_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return PWRDM_POWER_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (state != PWRDM_POWER_RET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) return PWRDM_POWER_RET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return omap4_pwrdm_read_mem_retst(pwrdm, bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) u32 c = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) * REVISIT: pwrdm_wait_transition() may be better implemented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) * via a callback and a periodic timer check -- how long do we expect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) * powerdomain transitions to take?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) /* XXX Is this udelay() value meaningful? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) pwrdm->prcm_offs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) OMAP4_PM_PWSTST) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) OMAP_INTRANSITION_MASK) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) (c++ < PWRDM_TRANSITION_BAILOUT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (c > PWRDM_TRANSITION_BAILOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) pr_err("powerdomain: %s: waited too long to complete transition\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) pwrdm->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) pr_debug("powerdomain: completed transition in %d loops\n", c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) static int omap4_check_vcvp(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (prm_features & PRM_HAS_VOLTAGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * omap4_pwrdm_save_context - Saves the powerdomain state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * @pwrdm: pointer to individual powerdomain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * The function saves the powerdomain state control information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * This is needed in rtc+ddr modes where we lose powerdomain context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) static void omap4_pwrdm_save_context(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) pwrdm->context = omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) pwrdm->prcm_offs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) pwrdm->pwrstctrl_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * Do not save LOWPOWERSTATECHANGE, writing a 1 indicates a request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) * reading back a 1 indicates a request in progress.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) pwrdm->context &= ~OMAP4430_LOWPOWERSTATECHANGE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * omap4_pwrdm_restore_context - Restores the powerdomain state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * @pwrdm: pointer to individual powerdomain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * The function restores the powerdomain state control information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * This is needed in rtc+ddr modes where we lose powerdomain context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) static void omap4_pwrdm_restore_context(struct powerdomain *pwrdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) int st, ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) st = omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) pwrdm->prcm_offs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) pwrdm->pwrstctrl_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) omap4_prminst_write_inst_reg(pwrdm->context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) pwrdm->prcm_partition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) pwrdm->prcm_offs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) pwrdm->pwrstctrl_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) /* Make sure we only wait for a transition if there is one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) st &= OMAP_POWERSTATEST_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) ctrl = OMAP_POWERSTATEST_MASK & pwrdm->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (st != ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) omap4_pwrdm_wait_transition(pwrdm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct pwrdm_ops omap4_pwrdm_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) .pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) .pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) .pwrdm_read_pwrst = omap4_pwrdm_read_pwrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) .pwrdm_read_prev_pwrst = omap4_pwrdm_read_prev_pwrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) .pwrdm_set_lowpwrstchange = omap4_pwrdm_set_lowpwrstchange,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) .pwrdm_clear_all_prev_pwrst = omap4_pwrdm_clear_all_prev_pwrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) .pwrdm_set_logic_retst = omap4_pwrdm_set_logic_retst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) .pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) .pwrdm_read_prev_logic_pwrst = omap4_pwrdm_read_prev_logic_pwrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) .pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) .pwrdm_read_mem_pwrst = omap4_pwrdm_read_mem_pwrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) .pwrdm_read_mem_retst = omap4_pwrdm_read_mem_retst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) .pwrdm_read_prev_mem_pwrst = omap4_pwrdm_read_prev_mem_pwrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) .pwrdm_set_mem_onst = omap4_pwrdm_set_mem_onst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) .pwrdm_set_mem_retst = omap4_pwrdm_set_mem_retst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) .pwrdm_wait_transition = omap4_pwrdm_wait_transition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) .pwrdm_has_voltdm = omap4_check_vcvp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) .pwrdm_save_context = omap4_pwrdm_save_context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) .pwrdm_restore_context = omap4_pwrdm_restore_context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) static int omap44xx_prm_late_init(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static void prm_save_context(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) omap_prm_context.irq_enable =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) omap4_prm_read_inst_reg(AM43XX_PRM_OCP_SOCKET_INST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) omap4_prcm_irq_setup.mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) omap_prm_context.pm_ctrl =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) omap4_prm_read_inst_reg(AM43XX_PRM_DEVICE_INST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) omap4_prcm_irq_setup.pm_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) static void prm_restore_context(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) omap4_prm_write_inst_reg(omap_prm_context.irq_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) OMAP4430_PRM_OCP_SOCKET_INST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) omap4_prcm_irq_setup.mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) omap4_prm_write_inst_reg(omap_prm_context.pm_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) AM43XX_PRM_DEVICE_INST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) omap4_prcm_irq_setup.pm_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) case CPU_CLUSTER_PM_ENTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (enable_off_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) prm_save_context();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) case CPU_CLUSTER_PM_EXIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) if (enable_off_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) prm_restore_context();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return NOTIFY_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) * XXX document
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) static struct prm_ll_data omap44xx_prm_ll_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) .read_reset_sources = &omap44xx_prm_read_reset_sources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) .was_any_context_lost_old = &omap44xx_prm_was_any_context_lost_old,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) .clear_context_loss_flags_old = &omap44xx_prm_clear_context_loss_flags_old,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) .late_init = &omap44xx_prm_late_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) .assert_hardreset = omap4_prminst_assert_hardreset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) .deassert_hardreset = omap4_prminst_deassert_hardreset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) .is_hardreset_asserted = omap4_prminst_is_hardreset_asserted,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) .reset_system = omap4_prminst_global_warm_sw_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) .vp_check_txdone = omap4_prm_vp_check_txdone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) .vp_clear_txdone = omap4_prm_vp_clear_txdone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) static const struct omap_prcm_init_data *prm_init_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) int __init omap44xx_prm_init(const struct omap_prcm_init_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) static struct notifier_block nb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) omap_prm_base_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) prm_init_data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (data->flags & PRM_HAS_IO_WAKEUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) prm_features |= PRM_HAS_IO_WAKEUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (data->flags & PRM_HAS_VOLTAGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) prm_features |= PRM_HAS_VOLTAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) omap4_prminst_set_prm_dev_inst(data->device_inst_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) /* Add AM437X specific differences */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) if (of_device_is_compatible(data->np, "ti,am4-prcm")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) omap4_prcm_irq_setup.nr_irqs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) omap4_prcm_irq_setup.nr_regs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) omap4_prcm_irq_setup.pm_ctrl = AM43XX_PRM_IO_PMCTRL_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) omap4_prcm_irq_setup.ack = AM43XX_PRM_IRQSTATUS_MPU_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) omap4_prcm_irq_setup.mask = AM43XX_PRM_IRQENABLE_MPU_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) /* Only AM43XX can lose prm context during rtc-ddr suspend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (soc_is_am43xx()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) nb.notifier_call = cpu_notifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) cpu_pm_register_notifier(&nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) return prm_register(&omap44xx_prm_ll_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) static int omap44xx_prm_late_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) int irq_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (!(prm_features & PRM_HAS_IO_WAKEUP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) irq_num = of_irq_get(prm_init_data->np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) if (irq_num == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) return irq_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) omap4_prcm_irq_setup.irq = irq_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) omap44xx_prm_enable_io_wakeup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) static void __exit omap44xx_prm_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) prm_unregister(&omap44xx_prm_ll_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) __exitcall(omap44xx_prm_exit);