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 etm4_enable_hw(void *info) { int i; struct etmv4_drvdata *drvdata = info; struct etmv4_config *config = &drvdata->config; CS_UNLOCK(drvdata->base); etm4_os_unlock(drvdata); /* Disable the trace unit before programming trace registers */ writel_relaxed(0, drvdata->base + TRCPRGCTLR); /* wait for TRCSTATR.IDLE to go up */ if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) dev_err(drvdata->dev, "timeout while waiting for Idle Trace Status\n"); writel_relaxed(config->pe_sel, drvdata->base + TRCPROCSELR); writel_relaxed(config->cfg, drvdata->base + TRCCONFIGR); /* nothing specific implemented */ writel_relaxed(0x0, drvdata->base + TRCAUXCTLR); writel_relaxed(config->eventctrl0, drvdata->base + TRCEVENTCTL0R); writel_relaxed(config->eventctrl1, drvdata->base + TRCEVENTCTL1R); writel_relaxed(config->stall_ctrl, drvdata->base + TRCSTALLCTLR); writel_relaxed(config->ts_ctrl, drvdata->base + TRCTSCTLR); writel_relaxed(config->syncfreq, drvdata->base + TRCSYNCPR); writel_relaxed(config->ccctlr, drvdata->base + TRCCCCTLR); writel_relaxed(config->bb_ctrl, drvdata->base + TRCBBCTLR); writel_relaxed(drvdata->trcid, drvdata->base + TRCTRACEIDR); writel_relaxed(config->vinst_ctrl, drvdata->base + TRCVICTLR); writel_relaxed(config->viiectlr, drvdata->base + TRCVIIECTLR); writel_relaxed(config->vissctlr, drvdata->base + TRCVISSCTLR); writel_relaxed(config->vipcssctlr, drvdata->base + TRCVIPCSSCTLR); for (i = 0; i < drvdata->nrseqstate - 1; i++) writel_relaxed(config->seq_ctrl[i], drvdata->base + TRCSEQEVRn(i)); writel_relaxed(config->seq_rst, drvdata->base + TRCSEQRSTEVR); writel_relaxed(config->seq_state, drvdata->base + TRCSEQSTR); writel_relaxed(config->ext_inp, drvdata->base + TRCEXTINSELR); for (i = 0; i < drvdata->nr_cntr; i++) { writel_relaxed(config->cntrldvr[i], drvdata->base + TRCCNTRLDVRn(i)); writel_relaxed(config->cntr_ctrl[i], drvdata->base + TRCCNTCTLRn(i)); writel_relaxed(config->cntr_val[i], drvdata->base + TRCCNTVRn(i)); } /* Resource selector pair 0 is always implemented and reserved */ for (i = 0; i < drvdata->nr_resource * 2; i++) writel_relaxed(config->res_ctrl[i], drvdata->base + TRCRSCTLRn(i)); for (i = 0; i < drvdata->nr_ss_cmp; i++) { writel_relaxed(config->ss_ctrl[i], drvdata->base + TRCSSCCRn(i)); writel_relaxed(config->ss_status[i], drvdata->base + TRCSSCSRn(i)); writel_relaxed(config->ss_pe_cmp[i], drvdata->base + TRCSSPCICRn(i)); } for (i = 0; i < drvdata->nr_addr_cmp; i++) { writeq_relaxed(config->addr_val[i], drvdata->base + TRCACVRn(i)); writeq_relaxed(config->addr_acc[i], drvdata->base + TRCACATRn(i)); } for (i = 0; i < drvdata->numcidc; i++) writeq_relaxed(config->ctxid_pid[i], drvdata->base + TRCCIDCVRn(i)); writel_relaxed(config->ctxid_mask0, drvdata->base + TRCCIDCCTLR0); writel_relaxed(config->ctxid_mask1, drvdata->base + TRCCIDCCTLR1); for (i = 0; i < drvdata->numvmidc; i++) writeq_relaxed(config->vmid_val[i], drvdata->base + TRCVMIDCVRn(i)); writel_relaxed(config->vmid_mask0, drvdata->base + TRCVMIDCCTLR0); writel_relaxed(config->vmid_mask1, drvdata->base + TRCVMIDCCTLR1); /* * Request to keep the trace unit powered and also * emulation of powerdown */ writel_relaxed(readl_relaxed(drvdata->base + TRCPDCR) | TRCPDCR_PU, drvdata->base + TRCPDCR); /* Enable the trace unit */ writel_relaxed(1, drvdata->base + TRCPRGCTLR); /* wait for TRCSTATR.IDLE to go back down to '0' */ if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 0)) dev_err(drvdata->dev, "timeout while waiting for Idle Trace Status\n"); CS_LOCK(drvdata->base); dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu); }
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); }