0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/kernel.h>
0011 #include <linux/irqchip/arm-gic.h>
0012 #include <linux/delay.h>
0013 #include <linux/io.h>
0014 #include <linux/suspend.h>
0015 #include <linux/platform_data/arm-ux500-pm.h>
0016 #include <linux/of.h>
0017 #include <linux/of_address.h>
0018
0019 #include "db8500-regs.h"
0020
0021
0022 #define PRCM_ARM_WFI_STANDBY (prcmu_base + 0x130)
0023 #define PRCM_ARM_WFI_STANDBY_WFI0 0x08
0024 #define PRCM_ARM_WFI_STANDBY_WFI1 0x10
0025 #define PRCM_IOCR (prcmu_base + 0x310)
0026 #define PRCM_IOCR_IOFORCE 0x1
0027
0028
0029 #define PRCM_A9_MASK_REQ (prcmu_base + 0x328)
0030 #define PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ 0x1
0031
0032 #define PRCM_A9_MASK_ACK (prcmu_base + 0x32c)
0033 #define PRCM_ARMITMSK31TO0 (prcmu_base + 0x11c)
0034 #define PRCM_ARMITMSK63TO32 (prcmu_base + 0x120)
0035 #define PRCM_ARMITMSK95TO64 (prcmu_base + 0x124)
0036 #define PRCM_ARMITMSK127TO96 (prcmu_base + 0x128)
0037 #define PRCM_POWER_STATE_VAL (prcmu_base + 0x25C)
0038 #define PRCM_ARMITVAL31TO0 (prcmu_base + 0x260)
0039 #define PRCM_ARMITVAL63TO32 (prcmu_base + 0x264)
0040 #define PRCM_ARMITVAL95TO64 (prcmu_base + 0x268)
0041 #define PRCM_ARMITVAL127TO96 (prcmu_base + 0x26C)
0042
0043 static void __iomem *prcmu_base;
0044 static void __iomem *dist_base;
0045
0046
0047 int prcmu_gic_decouple(void)
0048 {
0049 u32 val = readl(PRCM_A9_MASK_REQ);
0050
0051
0052 writel(val | PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ,
0053 PRCM_A9_MASK_REQ);
0054
0055
0056 readl(PRCM_A9_MASK_REQ);
0057
0058
0059 udelay(1);
0060
0061 return 0;
0062 }
0063
0064
0065 int prcmu_gic_recouple(void)
0066 {
0067 u32 val = readl(PRCM_A9_MASK_REQ);
0068
0069
0070 writel(val & ~PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ, PRCM_A9_MASK_REQ);
0071
0072 return 0;
0073 }
0074
0075 #define PRCMU_GIC_NUMBER_REGS 5
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 bool prcmu_gic_pending_irq(void)
0088 {
0089 u32 pr;
0090 u32 er;
0091 int i;
0092
0093
0094 for (i = 0; i < PRCMU_GIC_NUMBER_REGS; i++) {
0095
0096 pr = readl_relaxed(dist_base + GIC_DIST_PENDING_SET + i * 4);
0097 er = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
0098
0099 if (pr & er)
0100 return true;
0101 }
0102
0103 return false;
0104 }
0105
0106
0107
0108
0109
0110
0111 bool prcmu_pending_irq(void)
0112 {
0113 u32 it, im;
0114 int i;
0115
0116 for (i = 0; i < PRCMU_GIC_NUMBER_REGS - 1; i++) {
0117 it = readl(PRCM_ARMITVAL31TO0 + i * 4);
0118 im = readl(PRCM_ARMITMSK31TO0 + i * 4);
0119 if (it & im)
0120 return true;
0121 }
0122
0123 return false;
0124 }
0125
0126
0127
0128
0129
0130
0131
0132 bool prcmu_is_cpu_in_wfi(int cpu)
0133 {
0134 return readl(PRCM_ARM_WFI_STANDBY) &
0135 (cpu ? PRCM_ARM_WFI_STANDBY_WFI1 : PRCM_ARM_WFI_STANDBY_WFI0);
0136 }
0137
0138
0139
0140
0141
0142 int prcmu_copy_gic_settings(void)
0143 {
0144 u32 er;
0145 int i;
0146
0147
0148 for (i = 0; i < PRCMU_GIC_NUMBER_REGS - 1; i++) {
0149 er = readl_relaxed(dist_base +
0150 GIC_DIST_ENABLE_SET + (i + 1) * 4);
0151 writel(er, PRCM_ARMITMSK31TO0 + i * 4);
0152 }
0153
0154 return 0;
0155 }
0156
0157 #ifdef CONFIG_SUSPEND
0158 static int ux500_suspend_enter(suspend_state_t state)
0159 {
0160 cpu_do_idle();
0161 return 0;
0162 }
0163
0164 static int ux500_suspend_valid(suspend_state_t state)
0165 {
0166 return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY;
0167 }
0168
0169 static const struct platform_suspend_ops ux500_suspend_ops = {
0170 .enter = ux500_suspend_enter,
0171 .valid = ux500_suspend_valid,
0172 };
0173 #define UX500_SUSPEND_OPS (&ux500_suspend_ops)
0174 #else
0175 #define UX500_SUSPEND_OPS NULL
0176 #endif
0177
0178 void __init ux500_pm_init(u32 phy_base, u32 size)
0179 {
0180 struct device_node *np;
0181
0182 prcmu_base = ioremap(phy_base, size);
0183 if (!prcmu_base) {
0184 pr_err("could not remap PRCMU for PM functions\n");
0185 return;
0186 }
0187 np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-gic");
0188 dist_base = of_iomap(np, 0);
0189 of_node_put(np);
0190 if (!dist_base) {
0191 pr_err("could not remap GIC dist base for PM functions\n");
0192 return;
0193 }
0194
0195
0196
0197
0198
0199 prcmu_gic_recouple();
0200
0201
0202 suspend_set_ops(UX500_SUSPEND_OPS);
0203 }