static void coresight_etm_restore(void) { struct etm_info *p_etm_info; void __iomem *p_etm_base = ETM_BASE(raw_smp_processor_id()); /* unlock software lock */ etm_unlock(); /* Fix me, normally, lock OS lock can disable trace unit and external access, * but found OS lock can't lock/unlock issue when doing MBTF test, so replace * with TRC_PRGCTLR to disabel trace unit */ #if USE_OSLOCK etm_os_lock(); #else writel_relaxed(0x0, p_etm_base + TRC_PRGCTLR); #endif /* restore registers */ p_etm_info = this_cpu_ptr(&cpu_etm_info); writel_relaxed(p_etm_info->trc_config, p_etm_base + TRC_CONFIGR); writel_relaxed(p_etm_info->trc_eventctl0, p_etm_base + TRC_EVENTCTL0R); writel_relaxed(p_etm_info->trc_eventctl1, p_etm_base + TRC_EVENTCTL1R); writel_relaxed(p_etm_info->trc_stallctl, p_etm_base + TRC_STALLCTLR); writel_relaxed(p_etm_info->trc_tsctlr, p_etm_base + TRC_TSCTLR); writel_relaxed(p_etm_info->trc_syncpr, p_etm_base + TRC_SYNCPR); writel_relaxed(p_etm_info->trc_bbctl, p_etm_base + TRC_BBCTLR); writel_relaxed(p_etm_info->trc_traceid, p_etm_base + TRC_TRACEIDR); writel_relaxed(p_etm_info->trc_victlr, p_etm_base + TRC_VICTLR); writel_relaxed(p_etm_info->trc_viiectl, p_etm_base + TRC_VIIECTLR); writel_relaxed(p_etm_info->trc_vissctl, p_etm_base + TRC_VISSCTLR); #if USE_OSLOCK writel_relaxed(p_etm_info->trc_prgctl, p_etm_base + TRC_PRGCTLR); #else writel_relaxed(0x1, p_etm_base + TRC_PRGCTLR); #endif /* unlock os lock */ etm_os_unlock(); /* lock software lock */ etm_lock(); }
static inline void etm_restore_state(struct etm_ctx *etmdata) { int i, j; i = 0; ETM_UNLOCK(etmdata); switch (etmdata->arch) { case ETM_ARCH_V4: atomic_notifier_call_chain(&etm_restore_notifier_list, 0, NULL); /* check OS lock is locked */ if (BVAL(etm_readl(etmdata, TRCOSLSR), 1) != 1) { pr_err_ratelimited("OS lock is unlocked\n"); etm_os_lock(etmdata); } /* main control and configuration registers */ etm_writel(etmdata, etmdata->state[i++], TRCPROCSELR); etm_writel(etmdata, etmdata->state[i++], TRCCONFIGR); etm_writel(etmdata, etmdata->state[i++], TRCAUXCTLR); etm_writel(etmdata, etmdata->state[i++], TRCEVENTCTL0R); etm_writel(etmdata, etmdata->state[i++], TRCEVENTCTL1R); etm_writel(etmdata, etmdata->state[i++], TRCSTALLCTLR); etm_writel(etmdata, etmdata->state[i++], TRCTSCTLR); etm_writel(etmdata, etmdata->state[i++], TRCSYNCPR); etm_writel(etmdata, etmdata->state[i++], TRCCCCTLR); etm_writel(etmdata, etmdata->state[i++], TRCBBCTLR); etm_writel(etmdata, etmdata->state[i++], TRCTRACEIDR); etm_writel(etmdata, etmdata->state[i++], TRCQCTLR); /* filtering control registers */ etm_writel(etmdata, etmdata->state[i++], TRCVICTLR); etm_writel(etmdata, etmdata->state[i++], TRCVIIECTLR); etm_writel(etmdata, etmdata->state[i++], TRCVISSCTLR); etm_writel(etmdata, etmdata->state[i++], TRCVIPCSSCTLR); etm_writel(etmdata, etmdata->state[i++], TRCVDCTLR); etm_writel(etmdata, etmdata->state[i++], TRCVDSACCTLR); etm_writel(etmdata, etmdata->state[i++], TRCVDARCCTLR); /* derived resources registers */ for (j = 0; j < etmdata->nr_seq_state-1; j++) etm_writel(etmdata, etmdata->state[i++], TRCSEQEVRn(j)); etm_writel(etmdata, etmdata->state[i++], TRCSEQRSTEVR); etm_writel(etmdata, etmdata->state[i++], TRCSEQSTR); etm_writel(etmdata, etmdata->state[i++], TRCEXTINSELR); for (j = 0; j < etmdata->nr_cntr; j++) { etm_writel(etmdata, etmdata->state[i++], TRCCNTRLDVRn(j)); etm_writel(etmdata, etmdata->state[i++], TRCCNTCTLRn(j)); etm_writel(etmdata, etmdata->state[i++], TRCCNTVRn(j)); } /* resource selection registers */ for (j = 0; j < etmdata->nr_resource; j++) etm_writel(etmdata, etmdata->state[i++], TRCRSCTLRn(j)); /* comparator registers */ for (j = 0; j < etmdata->nr_addr_cmp * 2; j++) { etm_writeq(etmdata, etmdata->state[i++], TRCACVRn(j)); etm_writeq(etmdata, etmdata->state[i++], TRCACATRn(j)); } for (j = 0; j < etmdata->nr_data_cmp; j++) { etm_writeq(etmdata, etmdata->state[i++], TRCDVCVRn(j)); etm_writeq(etmdata, etmdata->state[i++], TRCDVCMRn(j)); } for (j = 0; j < etmdata->nr_ctxid_cmp; j++) etm_writeq(etmdata, etmdata->state[i++], TRCCIDCVRn(j)); etm_writel(etmdata, etmdata->state[i++], TRCCIDCCTLR0); etm_writel(etmdata, etmdata->state[i++], TRCCIDCCTLR1); for (j = 0; j < etmdata->nr_vmid_cmp; j++) etm_writeq(etmdata, etmdata->state[i++], TRCVMIDCVRn(j)); etm_writel(etmdata, etmdata->state[i++], TRCVMIDCCTLR0); etm_writel(etmdata, etmdata->state[i++], TRCVMIDCCTLR1); /* e-shot comparator registers */ for (j = 0; j < etmdata->nr_ss_cmp; j++) { etm_writel(etmdata, etmdata->state[i++], TRCSSCCRn(j)); etm_writel(etmdata, etmdata->state[i++], TRCSSCSRn(j)); etm_writel(etmdata, etmdata->state[i++], TRCSSPCICRn(j)); } /* claim tag registers */ etm_writel(etmdata, etmdata->state[i++], TRCCLAIMSET); /* program ctrl register */ etm_writel(etmdata, etmdata->state[i++], TRCPRGCTLR); etm_os_unlock(etmdata); break; default: pr_err_ratelimited("unsupported etm arch %d in %s\n", etmdata->arch, __func__); } ETM_LOCK(etmdata); }
static void coresight_etm_save(void) { struct etm_info *p_etm_info; u32 timeout, val; void __iomem *p_etm_base = ETM_BASE(raw_smp_processor_id()); mb(); isb(); /* unlock software lock */ etm_unlock(); /* Fix me, normally, lock OS lock can disable trace unit and external access, * but found OS lock can't lock/unlock issue when doing MBTF test, so replace * with TRC_PRGCTLR to disabel trace unit */ #if USE_OSLOCK etm_os_lock(); #else writel_relaxed(0x0, p_etm_base + TRC_PRGCTLR); #endif /* Check the programmers' model is stable */ timeout = 100; do { val = readl(p_etm_base + TRC_STATR); if (val & (0x1 << 1)) break; udelay(1); } while (--timeout); if (!timeout) pr_info("cpu%d's programmer model is unstable.\n", raw_smp_processor_id()); /* save register */ p_etm_info = this_cpu_ptr(&cpu_etm_info); p_etm_info->trc_config = readl_relaxed(p_etm_base + TRC_CONFIGR); p_etm_info->trc_eventctl0 = readl_relaxed(p_etm_base + TRC_EVENTCTL0R); p_etm_info->trc_eventctl1 = readl_relaxed(p_etm_base + TRC_EVENTCTL1R); p_etm_info->trc_stallctl = readl_relaxed(p_etm_base + TRC_STALLCTLR); p_etm_info->trc_tsctlr = readl_relaxed(p_etm_base + TRC_TSCTLR); p_etm_info->trc_syncpr = readl_relaxed(p_etm_base + TRC_SYNCPR); p_etm_info->trc_bbctl = readl_relaxed(p_etm_base + TRC_BBCTLR); p_etm_info->trc_traceid = readl_relaxed(p_etm_base + TRC_TRACEIDR); p_etm_info->trc_victlr = readl_relaxed(p_etm_base + TRC_VICTLR); p_etm_info->trc_viiectl = readl_relaxed(p_etm_base + TRC_VIIECTLR); p_etm_info->trc_vissctl = readl_relaxed(p_etm_base + TRC_VISSCTLR); #if USE_OSLOCK p_etm_info->trc_prgctl = readl_relaxed(p_etm_base + TRC_PRGCTLR); #endif /* ensure trace unit is idle to be powered down */ timeout = 100; do { val = readl(p_etm_base + TRC_STATR); if (val & (0x1 << 0)) break; udelay(1); } while (--timeout); if (!timeout) pr_info("cpu%d's programmer model is not idle.\n", raw_smp_processor_id()); /* lock software lock */ etm_lock(); }
static inline void etm_save_state(struct etm_ctx *etmdata) { int i, j, count; i = 0; mb(); isb(); ETM_UNLOCK(etmdata); switch (etmdata->arch) { case ETM_ARCH_V4: etm_os_lock(etmdata); /* poll until programmers' model becomes stable */ for (count = TIMEOUT_US; (BVAL(etm_readl(etmdata, TRCSTATR), 1) != 1) && count > 0; count--) udelay(1); if (count == 0) pr_err_ratelimited("programmers model is not stable\n" ); /* main control and configuration registers */ etmdata->state[i++] = etm_readl(etmdata, TRCPROCSELR); etmdata->state[i++] = etm_readl(etmdata, TRCCONFIGR); etmdata->state[i++] = etm_readl(etmdata, TRCAUXCTLR); etmdata->state[i++] = etm_readl(etmdata, TRCEVENTCTL0R); etmdata->state[i++] = etm_readl(etmdata, TRCEVENTCTL1R); etmdata->state[i++] = etm_readl(etmdata, TRCSTALLCTLR); etmdata->state[i++] = etm_readl(etmdata, TRCTSCTLR); etmdata->state[i++] = etm_readl(etmdata, TRCSYNCPR); etmdata->state[i++] = etm_readl(etmdata, TRCCCCTLR); etmdata->state[i++] = etm_readl(etmdata, TRCBBCTLR); etmdata->state[i++] = etm_readl(etmdata, TRCTRACEIDR); etmdata->state[i++] = etm_readl(etmdata, TRCQCTLR); /* filtering control registers */ etmdata->state[i++] = etm_readl(etmdata, TRCVICTLR); etmdata->state[i++] = etm_readl(etmdata, TRCVIIECTLR); etmdata->state[i++] = etm_readl(etmdata, TRCVISSCTLR); etmdata->state[i++] = etm_readl(etmdata, TRCVIPCSSCTLR); etmdata->state[i++] = etm_readl(etmdata, TRCVDCTLR); etmdata->state[i++] = etm_readl(etmdata, TRCVDSACCTLR); etmdata->state[i++] = etm_readl(etmdata, TRCVDARCCTLR); /* derived resource registers */ for (j = 0; j < etmdata->nr_seq_state-1; j++) etmdata->state[i++] = etm_readl(etmdata, TRCSEQEVRn(j)); etmdata->state[i++] = etm_readl(etmdata, TRCSEQRSTEVR); etmdata->state[i++] = etm_readl(etmdata, TRCSEQSTR); etmdata->state[i++] = etm_readl(etmdata, TRCEXTINSELR); for (j = 0; j < etmdata->nr_cntr; j++) { etmdata->state[i++] = etm_readl(etmdata, TRCCNTRLDVRn(j)); etmdata->state[i++] = etm_readl(etmdata, TRCCNTCTLRn(j)); etmdata->state[i++] = etm_readl(etmdata, TRCCNTVRn(j)); } /* resource selection registers */ for (j = 0; j < etmdata->nr_resource; j++) etmdata->state[i++] = etm_readl(etmdata, TRCRSCTLRn(j)); /* comparator registers */ for (j = 0; j < etmdata->nr_addr_cmp * 2; j++) { etmdata->state[i++] = etm_readq(etmdata, TRCACVRn(j)); etmdata->state[i++] = etm_readq(etmdata, TRCACATRn(j)); } for (j = 0; j < etmdata->nr_data_cmp; j++) { etmdata->state[i++] = etm_readq(etmdata, TRCDVCVRn(j)); etmdata->state[i++] = etm_readq(etmdata, TRCDVCMRn(i)); } for (j = 0; j < etmdata->nr_ctxid_cmp; j++) etmdata->state[i++] = etm_readq(etmdata, TRCCIDCVRn(j)); etmdata->state[i++] = etm_readl(etmdata, TRCCIDCCTLR0); etmdata->state[i++] = etm_readl(etmdata, TRCCIDCCTLR1); for (j = 0; j < etmdata->nr_vmid_cmp; j++) etmdata->state[i++] = etm_readq(etmdata, TRCVMIDCVRn(j)); etmdata->state[i++] = etm_readl(etmdata, TRCVMIDCCTLR0); etmdata->state[i++] = etm_readl(etmdata, TRCVMIDCCTLR1); /* single-shot comparator registers */ for (j = 0; j < etmdata->nr_ss_cmp; j++) { etmdata->state[i++] = etm_readl(etmdata, TRCSSCCRn(j)); etmdata->state[i++] = etm_readl(etmdata, TRCSSCSRn(j)); etmdata->state[i++] = etm_readl(etmdata, TRCSSPCICRn(j)); } /* claim tag registers */ etmdata->state[i++] = etm_readl(etmdata, TRCCLAIMCLR); /* program ctrl register */ etmdata->state[i++] = etm_readl(etmdata, TRCPRGCTLR); /* ensure trace unit is idle to be powered down */ for (count = TIMEOUT_US; (BVAL(etm_readl(etmdata, TRCSTATR), 0) != 1) && count > 0; count--) udelay(1); if (count == 0) pr_err_ratelimited("timeout waiting for idle state\n"); atomic_notifier_call_chain(&etm_save_notifier_list, 0, NULL); break; default: pr_err_ratelimited("unsupported etm arch %d in %s\n", etmdata->arch, __func__); } ETM_LOCK(etmdata); }