summaryrefslogtreecommitdiff
path: root/drivers/platform
diff options
context:
space:
mode:
authorChenhui Zhao <chenhui.zhao@freescale.com>2014-05-21 09:23:48 (GMT)
committerJose Rivera <German.Rivera@freescale.com>2014-05-23 13:07:16 (GMT)
commit3fe6b293a154089a030a5e7ee86a283fab2eb54a (patch)
treeea1127c9f17729b2a24e91434dc61b117ba97df2 /drivers/platform
parent1e9d843f2df037e209c18abce82803420b8949a1 (diff)
downloadlinux-fsl-qoriq-3fe6b293a154089a030a5e7ee86a283fab2eb54a.tar.xz
powerpc/t104x: fix the deep sleep issue on T1042
T1042 will trigger an Machine Check Exception when clearing the EPU registers in resume process. The cause is that the sequence of clearing the EPU registers is critical to make things right, especiallly for T1042. Therefore, follow the exact sequence in RM to clear the EPU registers. Change-Id: Icec8b3fd37b0e122801c19eede81592000abb5f5 Signed-off-by: Chenhui Zhao <chenhui.zhao@freescale.com> Reviewed-on: http://git.am.freescale.net:8181/12784 Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com> Reviewed-by: Dongsheng Wang <dongsheng.wang@freescale.com> Reviewed-by: Jose Rivera <German.Rivera@freescale.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/fsl/sleep_fsm.c103
1 files changed, 57 insertions, 46 deletions
diff --git a/drivers/platform/fsl/sleep_fsm.c b/drivers/platform/fsl/sleep_fsm.c
index 195a09c..35b033e 100644
--- a/drivers/platform/fsl/sleep_fsm.c
+++ b/drivers/platform/fsl/sleep_fsm.c
@@ -26,6 +26,7 @@
/* EPEVTCR0-9 (Event Processor EVT Pin Control Registers) */
#define EPEVTCR0 0x050
+#define EPEVTCR9 0x074
#define EPEVTCR_STRIDE FSL_STRIDE_4B
/* EPXTRIGCR (Event Processor Crosstrigger Control Register) */
@@ -33,30 +34,37 @@
/* EPIMCR0-31 (Event Processor Input Mux Control Registers) */
#define EPIMCR0 0x100
+#define EPIMCR31 0x17C
#define EPIMCR_STRIDE FSL_STRIDE_4B
/* EPSMCR0-15 (Event Processor SCU Mux Control Registers) */
#define EPSMCR0 0x200
+#define EPSMCR15 0x278
#define EPSMCR_STRIDE FSL_STRIDE_8B
/* EPECR0-15 (Event Processor Event Control Registers) */
#define EPECR0 0x300
+#define EPECR15 0x33C
#define EPECR_STRIDE FSL_STRIDE_4B
/* EPACR0-15 (Event Processor Action Control Registers) */
#define EPACR0 0x400
+#define EPACR15 0x43C
#define EPACR_STRIDE FSL_STRIDE_4B
/* EPCCRi0-15 (Event Processor Counter Control Registers) */
#define EPCCR0 0x800
+#define EPCCR15 0x83C
#define EPCCR_STRIDE FSL_STRIDE_4B
/* EPCMPR0-15 (Event Processor Counter Compare Registers) */
#define EPCMPR0 0x900
+#define EPCMPR15 0x93C
#define EPCMPR_STRIDE FSL_STRIDE_4B
/* EPCTR0-31 (Event Processor Counter Register) */
#define EPCTR0 0xA00
+#define EPCTR31 0xA7C
#define EPCTR_STRIDE FSL_STRIDE_4B
/* NPC triggered Memory-Mapped Access Registers */
@@ -101,39 +109,6 @@ struct fsm_reg_vals {
struct fsm_reg_vals fsm_default_val[] = {
/* EPGCR (Event Processor Global Control Register) */
{EPU_BLOCK_OFFSET + EPGCR, 0},
- /* EPCTR (Event Processor Counter Register) */
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 0, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 1, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 2, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 3, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 4, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 5, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 6, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 7, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 8, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 9, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 10, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 11, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 12, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 13, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 14, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 15, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 16, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 17, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 18, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 19, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 20, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 21, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 22, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 23, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 24, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 25, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 26, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 27, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 28, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 29, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 30, 0},
- {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 31, 0},
/* EPECR (Event Processor Event Control Registers) */
{EPU_BLOCK_OFFSET + EPECR0 + EPECR_STRIDE * 0, 0},
{EPU_BLOCK_OFFSET + EPECR0 + EPECR_STRIDE * 1, 0},
@@ -298,19 +273,57 @@ struct fsm_reg_vals fsm_default_val[] = {
*/
void fsl_dp_fsm_clean(void __iomem *dcsr_base, struct fsm_reg_vals *val)
{
+ void *epu_base = dcsr_base + EPU_BLOCK_OFFSET;
+ u32 offset;
struct fsm_reg_vals *data;
- /* if NULL, use the default values */
- if (val)
+ if (val) {
data = val;
- else
- data = fsm_default_val;
-
- while (data->offset != FSM_END_FLAG) {
- out_be32(dcsr_base + data->offset, 0);
- in_be32(dcsr_base + data->offset);
- data++;
+ while (data->offset != FSM_END_FLAG) {
+ out_be32(dcsr_base + data->offset, 0);
+ data++;
+ }
+ return;
}
+
+ /* follow the exact sequence to clear the registers */
+ /* Clear EPACRn */
+ for (offset = EPACR0; offset <= EPACR15; offset += EPACR_STRIDE)
+ out_be32(epu_base + offset, 0);
+
+ /* Clear EPEVTCRn */
+ for (offset = EPEVTCR0; offset <= EPEVTCR9; offset += EPEVTCR_STRIDE)
+ out_be32(epu_base + offset, 0);
+
+ /* Clear EPGCR */
+ out_be32(epu_base + EPGCR, 0);
+
+ /* Clear EPSMCRn */
+ for (offset = EPSMCR0; offset <= EPSMCR15; offset += EPSMCR_STRIDE)
+ out_be32(epu_base + offset, 0);
+
+ /* Clear EPCCRn */
+ for (offset = EPCCR0; offset <= EPCCR15; offset += EPCCR_STRIDE)
+ out_be32(epu_base + offset, 0);
+
+ /* Clear EPCMPRn */
+ for (offset = EPCMPR0; offset <= EPCMPR15; offset += EPCMPR_STRIDE)
+ out_be32(epu_base + offset, 0);
+
+ /* Clear EPCTRn */
+ for (offset = EPCTR0; offset <= EPCTR31; offset += EPCTR_STRIDE)
+ out_be32(epu_base + offset, 0);
+
+ /* Clear EPIMCRn */
+ for (offset = EPIMCR0; offset <= EPIMCR31; offset += EPIMCR_STRIDE)
+ out_be32(epu_base + offset, 0);
+
+ /* Clear EPXTRIGCRn */
+ out_be32(epu_base + EPXTRIGCR, 0);
+
+ /* Clear EPECRn */
+ for (offset = EPECR0; offset <= EPECR15; offset += EPECR_STRIDE)
+ out_be32(epu_base + offset, 0);
}
/**
@@ -330,13 +343,11 @@ void fsl_dp_fsm_setup(void __iomem *dcsr_base, struct fsm_reg_vals *val)
data = fsm_default_val;
/* clear all registers */
- fsl_dp_fsm_clean(dcsr_base, data);
+ fsl_dp_fsm_clean(dcsr_base, NULL);
while (data->offset != FSM_END_FLAG) {
- if (data->value) {
+ if (data->value)
out_be32(dcsr_base + data->offset, data->value);
- in_be32(dcsr_base + data->offset);
- }
data++;
}
}