void tmc_etb_enable_hw(struct tmc_drvdata *drvdata) { CS_UNLOCK(drvdata->base); /* Wait for TMCSReady bit to be set */ tmc_wait_for_tmcready(drvdata); writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE); writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI | TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT | TMC_FFCR_TRIGON_TRIGIN, drvdata->base + TMC_FFCR); writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG); tmc_enable_hw(drvdata); CS_LOCK(drvdata->base); }
static ssize_t etmsr_show(struct device *dev, struct device_attribute *attr, char *buf) { unsigned long flags, val; struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); pm_runtime_get_sync(drvdata->dev); spin_lock_irqsave(&drvdata->spinlock, flags); CS_UNLOCK(drvdata->base); val = etm_readl(drvdata, ETMSR); CS_LOCK(drvdata->base); spin_unlock_irqrestore(&drvdata->spinlock, flags); pm_runtime_put(drvdata->dev); return sprintf(buf, "%#lx\n", val); }
static void tmc_etb_enable_hw(struct tmc_drvdata *drvdata) { /* Zero out the memory to help with debug */ memset(drvdata->buf, 0, drvdata->size); CS_UNLOCK(drvdata->base); writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE); writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI | TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT | TMC_FFCR_TRIGON_TRIGIN, drvdata->base + TMC_FFCR); writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG); tmc_enable_hw(drvdata); CS_LOCK(drvdata->base); }
static void stm_enable_hw(struct stm_drvdata *drvdata) { if (drvdata->stmheer) stm_hwevent_enable_hw(drvdata); stm_port_enable_hw(drvdata); CS_UNLOCK(drvdata->base); /* 4096 byte between synchronisation packets */ writel_relaxed(0xFFF, drvdata->base + STMSYNCR); writel_relaxed((drvdata->traceid << 16 | /* trace id */ 0x02 | /* timestamp enable */ 0x01), /* global STM enable */ drvdata->base + STMTCSR); CS_LOCK(drvdata->base); }
static void etm_init_arch_data(void *info) { u32 etmidr; u32 etmccr; struct etm_drvdata *drvdata = info; /* Make sure all registers are accessible */ etm_os_unlock(drvdata); CS_UNLOCK(drvdata->base); /* First dummy read */ (void)etm_readl(drvdata, ETMPDSR); /* Provide power to ETM: ETMPDCR[3] == 1 */ etm_set_pwrup(drvdata); /* * Clear power down bit since when this bit is set writes to * certain registers might be ignored. */ etm_clr_pwrdwn(drvdata); /* * Set prog bit. It will be set from reset but this is included to * ensure it is set */ etm_set_prog(drvdata); /* Find all capabilities */ etmidr = etm_readl(drvdata, ETMIDR); drvdata->arch = BMVAL(etmidr, 4, 11); drvdata->port_size = etm_readl(drvdata, ETMCR) & PORT_SIZE_MASK; drvdata->etmccer = etm_readl(drvdata, ETMCCER); etmccr = etm_readl(drvdata, ETMCCR); drvdata->etmccr = etmccr; drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2; drvdata->nr_cntr = BMVAL(etmccr, 13, 15); drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19); drvdata->nr_ext_out = BMVAL(etmccr, 20, 22); drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25); etm_set_pwrdwn(drvdata); etm_clr_pwrup(drvdata); CS_LOCK(drvdata->base); }
static void etm_disable_perf(struct coresight_device *csdev) { struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id())) return; CS_UNLOCK(drvdata->base); /* Setting the prog bit disables tracing immediately */ etm_set_prog(drvdata); /* * There is no way to know when the tracer will be used again so * power down the tracer. */ etm_set_pwrdwn(drvdata); CS_LOCK(drvdata->base); }
static int etm4_trace_id(struct coresight_device *csdev) { struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); unsigned long flags; int trace_id = -1; if (!local_read(&drvdata->mode)) return drvdata->trcid; spin_lock_irqsave(&drvdata->spinlock, flags); CS_UNLOCK(drvdata->base); trace_id = readl_relaxed(drvdata->base + TRCTRACEIDR); trace_id &= ETM_TRACEID_MASK; CS_LOCK(drvdata->base); spin_unlock_irqrestore(&drvdata->spinlock, flags); return trace_id; }
static void etm_disable_hw(void *info) { int i; struct etm_drvdata *drvdata = info; struct etm_config *config = &drvdata->config; CS_UNLOCK(drvdata->base); etm_set_prog(drvdata); /* Read back sequencer and counters for post trace analysis */ config->seq_curr_state = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK); for (i = 0; i < drvdata->nr_cntr; i++) config->cntr_val[i] = etm_readl(drvdata, ETMCNTVRn(i)); etm_set_pwrdwn(drvdata); CS_LOCK(drvdata->base); dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu); }
static void etm4_disable_hw(void *info) { u32 control; struct etmv4_drvdata *drvdata = info; CS_UNLOCK(drvdata->base); control = readl_relaxed(drvdata->base + TRCPRGCTLR); /* EN, bit[0] Trace unit enable bit */ control &= ~0x1; /* make sure everything completes before disabling */ mb(); isb(); writel_relaxed(control, drvdata->base + TRCPRGCTLR); CS_LOCK(drvdata->base); dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu); }
static int etm_trace_id(struct coresight_device *csdev) { struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); unsigned long flags; int trace_id = -1; if (!drvdata->enable) return drvdata->traceid; pm_runtime_get_sync(csdev->dev.parent); spin_lock_irqsave(&drvdata->spinlock, flags); CS_UNLOCK(drvdata->base); trace_id = (etm_readl(drvdata, ETMTRACEIDR) & ETM_TRACEID_MASK); CS_LOCK(drvdata->base); spin_unlock_irqrestore(&drvdata->spinlock, flags); pm_runtime_put(csdev->dev.parent); return trace_id; }
static ssize_t status_show(struct device *dev, struct device_attribute *attr, char *buf) { unsigned long flags; u32 etb_rdr, etb_sr, etb_rrp, etb_rwp; u32 etb_trg, etb_cr, etb_ffsr, etb_ffcr; struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent); pm_runtime_get_sync(drvdata->dev); spin_lock_irqsave(&drvdata->spinlock, flags); CS_UNLOCK(drvdata->base); etb_rdr = readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG); etb_sr = readl_relaxed(drvdata->base + ETB_STATUS_REG); etb_rrp = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER); etb_rwp = readl_relaxed(drvdata->base + ETB_RAM_WRITE_POINTER); etb_trg = readl_relaxed(drvdata->base + ETB_TRG); etb_cr = readl_relaxed(drvdata->base + ETB_CTL_REG); etb_ffsr = readl_relaxed(drvdata->base + ETB_FFSR); etb_ffcr = readl_relaxed(drvdata->base + ETB_FFCR); CS_LOCK(drvdata->base); spin_unlock_irqrestore(&drvdata->spinlock, flags); pm_runtime_put(drvdata->dev); return sprintf(buf, "Depth:\t\t0x%x\n" "Status:\t\t0x%x\n" "RAM read ptr:\t0x%x\n" "RAM wrt ptr:\t0x%x\n" "Trigger cnt:\t0x%x\n" "Control:\t0x%x\n" "Flush status:\t0x%x\n" "Flush ctrl:\t0x%x\n", etb_rdr, etb_sr, etb_rrp, etb_rwp, etb_trg, etb_cr, etb_ffsr, etb_ffcr); return -EINVAL; }
static void etm_disable_hw(void *info) { int i; struct etm_drvdata *drvdata = info; CS_UNLOCK(drvdata->base); etm_set_prog(drvdata); /* Program trace enable to low by using always false event */ etm_writel(drvdata, ETM_HARD_WIRE_RES_A | ETM_EVENT_NOT_A, ETMTEEVR); /* Read back sequencer and counters for post trace analysis */ drvdata->seq_curr_state = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK); for (i = 0; i < drvdata->nr_cntr; i++) drvdata->cntr_val[i] = etm_readl(drvdata, ETMCNTVRn(i)); etm_set_pwrdwn(drvdata); CS_LOCK(drvdata->base); dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu); }
static ssize_t traceid_show(struct device *dev, struct device_attribute *attr, char *buf) { unsigned long val, flags; struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); if (!drvdata->enable) { val = drvdata->traceid; goto out; } pm_runtime_get_sync(drvdata->dev); spin_lock_irqsave(&drvdata->spinlock, flags); CS_UNLOCK(drvdata->base); val = (etm_readl(drvdata, ETMTRACEIDR) & ETM_TRACEID_MASK); CS_LOCK(drvdata->base); spin_unlock_irqrestore(&drvdata->spinlock, flags); pm_runtime_put(drvdata->dev); out: return sprintf(buf, "%#lx\n", val); }
static ssize_t seq_curr_state_show(struct device *dev, struct device_attribute *attr, char *buf) { unsigned long val, flags; struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etm_config *config = &drvdata->config; if (!local_read(&drvdata->mode)) { val = config->seq_curr_state; goto out; } pm_runtime_get_sync(drvdata->dev); spin_lock_irqsave(&drvdata->spinlock, flags); CS_UNLOCK(drvdata->base); val = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK); CS_LOCK(drvdata->base); spin_unlock_irqrestore(&drvdata->spinlock, flags); pm_runtime_put(drvdata->dev); out: return sprintf(buf, "%#lx\n", val); }
static ssize_t port_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent); unsigned long val; int ret = 0; ret = kstrtoul(buf, 16, &val); if (ret) return ret; spin_lock(&drvdata->spinlock); drvdata->stmsper = val; if (local_read(&drvdata->mode)) { CS_UNLOCK(drvdata->base); writel_relaxed(drvdata->stmsper, drvdata->base + STMSPER); CS_LOCK(drvdata->base); } spin_unlock(&drvdata->spinlock); return size; }
void tmc_etr_enable_hw(struct tmc_drvdata *drvdata) { u32 axictl; /* Zero out the memory to help with debug */ memset(drvdata->vaddr, 0, drvdata->size); CS_UNLOCK(drvdata->base); /* Wait for TMCSReady bit to be set */ tmc_wait_for_tmcready(drvdata); writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ); writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE); axictl = readl_relaxed(drvdata->base + TMC_AXICTL); axictl |= TMC_AXICTL_WR_BURST_16; writel_relaxed(axictl, drvdata->base + TMC_AXICTL); axictl &= ~TMC_AXICTL_SCT_GAT_MODE; writel_relaxed(axictl, drvdata->base + TMC_AXICTL); axictl = (axictl & ~(TMC_AXICTL_PROT_CTL_B0 | TMC_AXICTL_PROT_CTL_B1)) | TMC_AXICTL_PROT_CTL_B1; writel_relaxed(axictl, drvdata->base + TMC_AXICTL); writel_relaxed(drvdata->paddr, drvdata->base + TMC_DBALO); writel_relaxed(0x0, drvdata->base + TMC_DBAHI); writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI | TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT | TMC_FFCR_TRIGON_TRIGIN, drvdata->base + TMC_FFCR); writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG); tmc_enable_hw(drvdata); CS_LOCK(drvdata->base); }
static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, struct perf_output_handle *handle, void *sink_config) { bool lost = false; int i, cur; const u32 *barrier; u32 *buf_ptr; u64 read_ptr, write_ptr; u32 status; unsigned long offset, to_read = 0, flags; struct cs_buffers *buf = sink_config; struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); if (!buf) return 0; /* This shouldn't happen */ if (WARN_ON_ONCE(drvdata->mode != CS_MODE_PERF)) return 0; spin_lock_irqsave(&drvdata->spinlock, flags); /* Don't do anything if another tracer is using this sink */ if (atomic_read(csdev->refcnt) != 1) goto out; CS_UNLOCK(drvdata->base); tmc_flush_and_stop(drvdata); read_ptr = tmc_read_rrp(drvdata); write_ptr = tmc_read_rwp(drvdata); /* * Get a hold of the status register and see if a wrap around * has occurred. If so adjust things accordingly. */ status = readl_relaxed(drvdata->base + TMC_STS); if (status & TMC_STS_FULL) { lost = true; to_read = drvdata->size; } else { to_read = CIRC_CNT(write_ptr, read_ptr, drvdata->size); } /* * The TMC RAM buffer may be bigger than the space available in the * perf ring buffer (handle->size). If so advance the RRP so that we * get the latest trace data. */ if (to_read > handle->size) { u32 mask = 0; /* * The value written to RRP must be byte-address aligned to * the width of the trace memory databus _and_ to a frame * boundary (16 byte), whichever is the biggest. For example, * for 32-bit, 64-bit and 128-bit wide trace memory, the four * LSBs must be 0s. For 256-bit wide trace memory, the five * LSBs must be 0s. */ switch (drvdata->memwidth) { case TMC_MEM_INTF_WIDTH_32BITS: case TMC_MEM_INTF_WIDTH_64BITS: case TMC_MEM_INTF_WIDTH_128BITS: mask = GENMASK(31, 4); break; case TMC_MEM_INTF_WIDTH_256BITS: mask = GENMASK(31, 5); break; } /* * Make sure the new size is aligned in accordance with the * requirement explained above. */ to_read = handle->size & mask; /* Move the RAM read pointer up */ read_ptr = (write_ptr + drvdata->size) - to_read; /* Make sure we are still within our limits */ if (read_ptr > (drvdata->size - 1)) read_ptr -= drvdata->size; /* Tell the HW */ tmc_write_rrp(drvdata, read_ptr); lost = true; } if (lost) perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); cur = buf->cur; offset = buf->offset; barrier = barrier_pkt; /* for every byte to read */ for (i = 0; i < to_read; i += 4) { buf_ptr = buf->data_pages[cur] + offset; *buf_ptr = readl_relaxed(drvdata->base + TMC_RRD); if (lost && *barrier) { *buf_ptr = *barrier; barrier++; } offset += 4; if (offset >= PAGE_SIZE) { offset = 0; cur++; /* wrap around at the end of the buffer */ cur &= buf->nr_pages - 1; } } /* In snapshot mode we have to update the head */ if (buf->snapshot) { handle->head = (cur * PAGE_SIZE) + offset; to_read = buf->nr_pages << PAGE_SHIFT; } CS_LOCK(drvdata->base); out: spin_unlock_irqrestore(&drvdata->spinlock, flags); return to_read; }
CWebShopPktQueue::QUEUE_RESULT CWebShopPktQueue::Pop(OUT char* pOutBuf) { if(pBuf == NULL) { return QRES_NOT_INITIALIZED; } #define RESERVED_CHAR_SIZE 1 /*ReservedChar*/ #define CONTENT_LEN_SIZE 2 /*ContentLength(2)*/ #define PKT_HEADER_SIZE (RESERVED_CHAR_SIZE + CONTENT_LEN_SIZE) CS_LOCK(csThis); // read packet header int iDataSize = _GetDataSize(); int iFrontDataSize = _GetFrontDataSize(); int r_old = r; if(iDataSize < PKT_HEADER_SIZE) { CS_UNLOCK(csThis); return QRES_NOT_ENOUGH_DATA; } if(iFrontDataSize > PKT_HEADER_SIZE) { memcpy(pOutBuf, pBuf + r, PKT_HEADER_SIZE); r += PKT_HEADER_SIZE; } else if(iFrontDataSize < PKT_HEADER_SIZE) { memcpy(pOutBuf, pBuf + r, iFrontDataSize); memcpy(pOutBuf + iFrontDataSize, pBuf, PKT_HEADER_SIZE - iFrontDataSize); r = PKT_HEADER_SIZE - iFrontDataSize; } else if(iFrontDataSize == PKT_HEADER_SIZE) { memcpy(pOutBuf, pBuf + r, PKT_HEADER_SIZE); r = 0; } int iContentLen = *(LPWORD)(pOutBuf + RESERVED_CHAR_SIZE); // read packet data iDataSize = _GetDataSize(); iFrontDataSize = _GetFrontDataSize(); if(iDataSize < iContentLen) { r = r_old; CS_UNLOCK(csThis); return QRES_NOT_ENOUGH_DATA; } if(iFrontDataSize == iContentLen) { memcpy(pOutBuf, pBuf + r, iContentLen); r = f; } else if(iFrontDataSize > iContentLen) { memcpy(pOutBuf, pBuf + r, iContentLen); r += iContentLen; } else if(iFrontDataSize < iContentLen) { memcpy(pOutBuf, pBuf + r, iFrontDataSize); memcpy(pOutBuf + iFrontDataSize, pBuf, iContentLen - iFrontDataSize); r = iContentLen - iFrontDataSize; } CS_UNLOCK(csThis); return QRES_OK; #undef RESERVED_CHAR_SIZE #undef CONTENT_LEN_SIZE #undef PKT_HEADER_SIZE }
static void etm_enable_hw(void *info) { int i; u32 etmcr; struct etm_drvdata *drvdata = info; CS_UNLOCK(drvdata->base); /* Turn engine on */ etm_clr_pwrdwn(drvdata); /* Apply power to trace registers */ etm_set_pwrup(drvdata); /* Make sure all registers are accessible */ etm_os_unlock(drvdata); etm_set_prog(drvdata); etmcr = etm_readl(drvdata, ETMCR); etmcr &= (ETMCR_PWD_DWN | ETMCR_ETM_PRG); etmcr |= drvdata->port_size; etm_writel(drvdata, drvdata->ctrl | etmcr, ETMCR); etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER); etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR); etm_writel(drvdata, drvdata->enable_event, ETMTEEVR); etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1); etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR); for (i = 0; i < drvdata->nr_addr_cmp; i++) { etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i)); etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i)); } for (i = 0; i < drvdata->nr_cntr; i++) { etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i)); etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i)); etm_writel(drvdata, drvdata->cntr_rld_event[i], ETMCNTRLDEVRn(i)); etm_writel(drvdata, drvdata->cntr_val[i], ETMCNTVRn(i)); } etm_writel(drvdata, drvdata->seq_12_event, ETMSQ12EVR); etm_writel(drvdata, drvdata->seq_21_event, ETMSQ21EVR); etm_writel(drvdata, drvdata->seq_23_event, ETMSQ23EVR); etm_writel(drvdata, drvdata->seq_31_event, ETMSQ31EVR); etm_writel(drvdata, drvdata->seq_32_event, ETMSQ32EVR); etm_writel(drvdata, drvdata->seq_13_event, ETMSQ13EVR); etm_writel(drvdata, drvdata->seq_curr_state, ETMSQR); for (i = 0; i < drvdata->nr_ext_out; i++) etm_writel(drvdata, ETM_DEFAULT_EVENT_VAL, ETMEXTOUTEVRn(i)); for (i = 0; i < drvdata->nr_ctxid_cmp; i++) etm_writel(drvdata, drvdata->ctxid_pid[i], ETMCIDCVRn(i)); etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR); etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR); /* No external input selected */ etm_writel(drvdata, 0x0, ETMEXTINSELR); etm_writel(drvdata, drvdata->timestamp_event, ETMTSEVR); /* No auxiliary control selected */ etm_writel(drvdata, 0x0, ETMAUXCR); etm_writel(drvdata, drvdata->traceid, ETMTRACEIDR); /* No VMID comparator value selected */ etm_writel(drvdata, 0x0, ETMVMIDCVR); /* Ensures trace output is enabled from this ETM */ etm_writel(drvdata, drvdata->ctrl | ETMCR_ETM_EN | etmcr, ETMCR); etm_clr_prog(drvdata); CS_LOCK(drvdata->base); dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu); }
void coresight_disclaim_device(void __iomem *base) { CS_UNLOCK(base); coresight_disclaim_device_unlocked(base); CS_LOCK(base); }
static int etm_enable_hw(struct etm_drvdata *drvdata) { int i, rc; u32 etmcr; struct etm_config *config = &drvdata->config; CS_UNLOCK(drvdata->base); rc = coresight_claim_device_unlocked(drvdata->base); if (rc) goto done; /* Turn engine on */ etm_clr_pwrdwn(drvdata); /* Apply power to trace registers */ etm_set_pwrup(drvdata); /* Make sure all registers are accessible */ etm_os_unlock(drvdata); etm_set_prog(drvdata); etmcr = etm_readl(drvdata, ETMCR); /* Clear setting from a previous run if need be */ etmcr &= ~ETM3X_SUPPORTED_OPTIONS; etmcr |= drvdata->port_size; etmcr |= ETMCR_ETM_EN; etm_writel(drvdata, config->ctrl | etmcr, ETMCR); etm_writel(drvdata, config->trigger_event, ETMTRIGGER); etm_writel(drvdata, config->startstop_ctrl, ETMTSSCR); etm_writel(drvdata, config->enable_event, ETMTEEVR); etm_writel(drvdata, config->enable_ctrl1, ETMTECR1); etm_writel(drvdata, config->fifofull_level, ETMFFLR); for (i = 0; i < drvdata->nr_addr_cmp; i++) { etm_writel(drvdata, config->addr_val[i], ETMACVRn(i)); etm_writel(drvdata, config->addr_acctype[i], ETMACTRn(i)); } for (i = 0; i < drvdata->nr_cntr; i++) { etm_writel(drvdata, config->cntr_rld_val[i], ETMCNTRLDVRn(i)); etm_writel(drvdata, config->cntr_event[i], ETMCNTENRn(i)); etm_writel(drvdata, config->cntr_rld_event[i], ETMCNTRLDEVRn(i)); etm_writel(drvdata, config->cntr_val[i], ETMCNTVRn(i)); } etm_writel(drvdata, config->seq_12_event, ETMSQ12EVR); etm_writel(drvdata, config->seq_21_event, ETMSQ21EVR); etm_writel(drvdata, config->seq_23_event, ETMSQ23EVR); etm_writel(drvdata, config->seq_31_event, ETMSQ31EVR); etm_writel(drvdata, config->seq_32_event, ETMSQ32EVR); etm_writel(drvdata, config->seq_13_event, ETMSQ13EVR); etm_writel(drvdata, config->seq_curr_state, ETMSQR); for (i = 0; i < drvdata->nr_ext_out; i++) etm_writel(drvdata, ETM_DEFAULT_EVENT_VAL, ETMEXTOUTEVRn(i)); for (i = 0; i < drvdata->nr_ctxid_cmp; i++) etm_writel(drvdata, config->ctxid_pid[i], ETMCIDCVRn(i)); etm_writel(drvdata, config->ctxid_mask, ETMCIDCMR); etm_writel(drvdata, config->sync_freq, ETMSYNCFR); /* No external input selected */ etm_writel(drvdata, 0x0, ETMEXTINSELR); etm_writel(drvdata, config->timestamp_event, ETMTSEVR); /* No auxiliary control selected */ etm_writel(drvdata, 0x0, ETMAUXCR); etm_writel(drvdata, drvdata->traceid, ETMTRACEIDR); /* No VMID comparator value selected */ etm_writel(drvdata, 0x0, ETMVMIDCVR); etm_clr_prog(drvdata); done: CS_LOCK(drvdata->base); dev_dbg(&drvdata->csdev->dev, "cpu: %d enable smp call done: %d\n", drvdata->cpu, rc); return rc; }
static void etb_update_buffer(struct coresight_device *csdev, struct perf_output_handle *handle, void *sink_config) { bool lost = false; int i, cur; u8 *buf_ptr; const u32 *barrier; u32 read_ptr, write_ptr, capacity; u32 status, read_data, to_read; unsigned long offset; struct cs_buffers *buf = sink_config; struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); if (!buf) return; capacity = drvdata->buffer_depth * ETB_FRAME_SIZE_WORDS; etb_disable_hw(drvdata); CS_UNLOCK(drvdata->base); /* unit is in words, not bytes */ read_ptr = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER); write_ptr = readl_relaxed(drvdata->base + ETB_RAM_WRITE_POINTER); /* * Entries should be aligned to the frame size. If they are not * go back to the last alignment point to give decoding tools a * chance to fix things. */ if (write_ptr % ETB_FRAME_SIZE_WORDS) { dev_err(drvdata->dev, "write_ptr: %lu not aligned to formatter frame size\n", (unsigned long)write_ptr); write_ptr &= ~(ETB_FRAME_SIZE_WORDS - 1); lost = true; } /* * Get a hold of the status register and see if a wrap around * has occurred. If so adjust things accordingly. Otherwise * start at the beginning and go until the write pointer has * been reached. */ status = readl_relaxed(drvdata->base + ETB_STATUS_REG); if (status & ETB_STATUS_RAM_FULL) { lost = true; to_read = capacity; read_ptr = write_ptr; } else { to_read = CIRC_CNT(write_ptr, read_ptr, drvdata->buffer_depth); to_read *= ETB_FRAME_SIZE_WORDS; } /* * Make sure we don't overwrite data that hasn't been consumed yet. * It is entirely possible that the HW buffer has more data than the * ring buffer can currently handle. If so adjust the start address * to take only the last traces. * * In snapshot mode we are looking to get the latest traces only and as * such, we don't care about not overwriting data that hasn't been * processed by user space. */ if (!buf->snapshot && to_read > handle->size) { u32 mask = ~(ETB_FRAME_SIZE_WORDS - 1); /* The new read pointer must be frame size aligned */ to_read = handle->size & mask; /* * Move the RAM read pointer up, keeping in mind that * everything is in frame size units. */ read_ptr = (write_ptr + drvdata->buffer_depth) - to_read / ETB_FRAME_SIZE_WORDS; /* Wrap around if need be*/ if (read_ptr > (drvdata->buffer_depth - 1)) read_ptr -= drvdata->buffer_depth; /* let the decoder know we've skipped ahead */ lost = true; } if (lost) perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); /* finally tell HW where we want to start reading from */ writel_relaxed(read_ptr, drvdata->base + ETB_RAM_READ_POINTER); cur = buf->cur; offset = buf->offset; barrier = barrier_pkt; for (i = 0; i < to_read; i += 4) { buf_ptr = buf->data_pages[cur] + offset; read_data = readl_relaxed(drvdata->base + ETB_RAM_READ_DATA_REG); if (lost && *barrier) { read_data = *barrier; barrier++; } *(u32 *)buf_ptr = read_data; buf_ptr += 4; offset += 4; if (offset >= PAGE_SIZE) { offset = 0; cur++; /* wrap around at the end of the buffer */ cur &= buf->nr_pages - 1; } } /* reset ETB buffer for next run */ writel_relaxed(0x0, drvdata->base + ETB_RAM_READ_POINTER); writel_relaxed(0x0, drvdata->base + ETB_RAM_WRITE_POINTER); /* * In snapshot mode all we have to do is communicate to * perf_aux_output_end() the address of the current head. In full * trace mode the same function expects a size to move rb->aux_head * forward. */ if (buf->snapshot) local_set(&buf->data_size, (cur * PAGE_SIZE) + offset); else local_add(to_read, &buf->data_size); etb_enable_hw(drvdata); CS_LOCK(drvdata->base); }
static void etb_dump_hw(struct etb_drvdata *drvdata) { bool lost = false; int i; u8 *buf_ptr; const u32 *barrier; u32 read_data, depth; u32 read_ptr, write_ptr; u32 frame_off, frame_endoff; CS_UNLOCK(drvdata->base); read_ptr = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER); write_ptr = readl_relaxed(drvdata->base + ETB_RAM_WRITE_POINTER); frame_off = write_ptr % ETB_FRAME_SIZE_WORDS; frame_endoff = ETB_FRAME_SIZE_WORDS - frame_off; if (frame_off) { dev_err(drvdata->dev, "write_ptr: %lu not aligned to formatter frame size\n", (unsigned long)write_ptr); dev_err(drvdata->dev, "frameoff: %lu, frame_endoff: %lu\n", (unsigned long)frame_off, (unsigned long)frame_endoff); write_ptr += frame_endoff; } if ((readl_relaxed(drvdata->base + ETB_STATUS_REG) & ETB_STATUS_RAM_FULL) == 0) { writel_relaxed(0x0, drvdata->base + ETB_RAM_READ_POINTER); } else { writel_relaxed(write_ptr, drvdata->base + ETB_RAM_READ_POINTER); lost = true; } depth = drvdata->buffer_depth; buf_ptr = drvdata->buf; barrier = barrier_pkt; for (i = 0; i < depth; i++) { read_data = readl_relaxed(drvdata->base + ETB_RAM_READ_DATA_REG); if (lost && *barrier) { read_data = *barrier; barrier++; } *(u32 *)buf_ptr = read_data; buf_ptr += 4; } if (frame_off) { buf_ptr -= (frame_endoff * 4); for (i = 0; i < frame_endoff; i++) { *buf_ptr++ = 0x0; *buf_ptr++ = 0x0; *buf_ptr++ = 0x0; *buf_ptr++ = 0x0; } } writel_relaxed(read_ptr, drvdata->base + ETB_RAM_READ_POINTER); CS_LOCK(drvdata->base); }
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 void etm4_init_arch_data(void *info) { u32 etmidr0; u32 etmidr1; u32 etmidr2; u32 etmidr3; u32 etmidr4; u32 etmidr5; struct etmv4_drvdata *drvdata = info; /* Make sure all registers are accessible */ etm4_os_unlock(drvdata); CS_UNLOCK(drvdata->base); /* find all capabilities of the tracing unit */ etmidr0 = readl_relaxed(drvdata->base + TRCIDR0); /* INSTP0, bits[2:1] P0 tracing support field */ if (BMVAL(etmidr0, 1, 1) && BMVAL(etmidr0, 2, 2)) drvdata->instrp0 = true; else drvdata->instrp0 = false; /* TRCBB, bit[5] Branch broadcast tracing support bit */ if (BMVAL(etmidr0, 5, 5)) drvdata->trcbb = true; else drvdata->trcbb = false; /* TRCCOND, bit[6] Conditional instruction tracing support bit */ if (BMVAL(etmidr0, 6, 6)) drvdata->trccond = true; else drvdata->trccond = false; /* TRCCCI, bit[7] Cycle counting instruction bit */ if (BMVAL(etmidr0, 7, 7)) drvdata->trccci = true; else drvdata->trccci = false; /* RETSTACK, bit[9] Return stack bit */ if (BMVAL(etmidr0, 9, 9)) drvdata->retstack = true; else drvdata->retstack = false; /* NUMEVENT, bits[11:10] Number of events field */ drvdata->nr_event = BMVAL(etmidr0, 10, 11); /* QSUPP, bits[16:15] Q element support field */ drvdata->q_support = BMVAL(etmidr0, 15, 16); /* TSSIZE, bits[28:24] Global timestamp size field */ drvdata->ts_size = BMVAL(etmidr0, 24, 28); /* base architecture of trace unit */ etmidr1 = readl_relaxed(drvdata->base + TRCIDR1); /* * TRCARCHMIN, bits[7:4] architecture the minor version number * TRCARCHMAJ, bits[11:8] architecture major versin number */ drvdata->arch = BMVAL(etmidr1, 4, 11); /* maximum size of resources */ etmidr2 = readl_relaxed(drvdata->base + TRCIDR2); /* CIDSIZE, bits[9:5] Indicates the Context ID size */ drvdata->ctxid_size = BMVAL(etmidr2, 5, 9); /* VMIDSIZE, bits[14:10] Indicates the VMID size */ drvdata->vmid_size = BMVAL(etmidr2, 10, 14); /* CCSIZE, bits[28:25] size of the cycle counter in bits minus 12 */ drvdata->ccsize = BMVAL(etmidr2, 25, 28); etmidr3 = readl_relaxed(drvdata->base + TRCIDR3); /* CCITMIN, bits[11:0] minimum threshold value that can be programmed */ drvdata->ccitmin = BMVAL(etmidr3, 0, 11); /* EXLEVEL_S, bits[19:16] Secure state instruction tracing */ drvdata->s_ex_level = BMVAL(etmidr3, 16, 19); /* EXLEVEL_NS, bits[23:20] Non-secure state instruction tracing */ drvdata->ns_ex_level = BMVAL(etmidr3, 20, 23); /* * TRCERR, bit[24] whether a trace unit can trace a * system error exception. */ if (BMVAL(etmidr3, 24, 24)) drvdata->trc_error = true; else drvdata->trc_error = false; /* SYNCPR, bit[25] implementation has a fixed synchronization period? */ if (BMVAL(etmidr3, 25, 25)) drvdata->syncpr = true; else drvdata->syncpr = false; /* STALLCTL, bit[26] is stall control implemented? */ if (BMVAL(etmidr3, 26, 26)) drvdata->stallctl = true; else drvdata->stallctl = false; /* SYSSTALL, bit[27] implementation can support stall control? */ if (BMVAL(etmidr3, 27, 27)) drvdata->sysstall = true; else drvdata->sysstall = false; /* NUMPROC, bits[30:28] the number of PEs available for tracing */ drvdata->nr_pe = BMVAL(etmidr3, 28, 30); /* NOOVERFLOW, bit[31] is trace overflow prevention supported */ if (BMVAL(etmidr3, 31, 31)) drvdata->nooverflow = true; else drvdata->nooverflow = false; /* number of resources trace unit supports */ etmidr4 = readl_relaxed(drvdata->base + TRCIDR4); /* NUMACPAIRS, bits[0:3] number of addr comparator pairs for tracing */ drvdata->nr_addr_cmp = BMVAL(etmidr4, 0, 3); /* NUMPC, bits[15:12] number of PE comparator inputs for tracing */ drvdata->nr_pe_cmp = BMVAL(etmidr4, 12, 15); /* * NUMRSPAIR, bits[19:16] * The number of resource pairs conveyed by the HW starts at 0, i.e a * value of 0x0 indicate 1 resource pair, 0x1 indicate two and so on. * As such add 1 to the value of NUMRSPAIR for a better representation. */ drvdata->nr_resource = BMVAL(etmidr4, 16, 19) + 1; /* * NUMSSCC, bits[23:20] the number of single-shot * comparator control for tracing */ drvdata->nr_ss_cmp = BMVAL(etmidr4, 20, 23); /* NUMCIDC, bits[27:24] number of Context ID comparators for tracing */ drvdata->numcidc = BMVAL(etmidr4, 24, 27); /* NUMVMIDC, bits[31:28] number of VMID comparators for tracing */ drvdata->numvmidc = BMVAL(etmidr4, 28, 31); etmidr5 = readl_relaxed(drvdata->base + TRCIDR5); /* NUMEXTIN, bits[8:0] number of external inputs implemented */ drvdata->nr_ext_inp = BMVAL(etmidr5, 0, 8); /* TRACEIDSIZE, bits[21:16] indicates the trace ID width */ drvdata->trcid_size = BMVAL(etmidr5, 16, 21); /* ATBTRIG, bit[22] implementation can support ATB triggers? */ if (BMVAL(etmidr5, 22, 22)) drvdata->atbtrig = true; else drvdata->atbtrig = false; /* * LPOVERRIDE, bit[23] implementation supports * low-power state override */ if (BMVAL(etmidr5, 23, 23)) drvdata->lpoverride = true; else drvdata->lpoverride = false; /* NUMSEQSTATE, bits[27:25] number of sequencer states implemented */ drvdata->nrseqstate = BMVAL(etmidr5, 25, 27); /* NUMCNTR, bits[30:28] number of counters available for tracing */ drvdata->nr_cntr = BMVAL(etmidr5, 28, 30); CS_LOCK(drvdata->base); }
static void tmc_update_etf_buffer(struct coresight_device *csdev, struct perf_output_handle *handle, void *sink_config) { int i, cur; u32 *buf_ptr; u32 read_ptr, write_ptr; u32 status, to_read; unsigned long offset; struct cs_buffers *buf = sink_config; struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); if (!buf) return; /* This shouldn't happen */ if (WARN_ON_ONCE(local_read(&drvdata->mode) != CS_MODE_PERF)) return; CS_UNLOCK(drvdata->base); tmc_flush_and_stop(drvdata); read_ptr = readl_relaxed(drvdata->base + TMC_RRP); write_ptr = readl_relaxed(drvdata->base + TMC_RWP); /* * Get a hold of the status register and see if a wrap around * has occurred. If so adjust things accordingly. */ status = readl_relaxed(drvdata->base + TMC_STS); if (status & TMC_STS_FULL) { local_inc(&buf->lost); to_read = drvdata->size; } else { to_read = CIRC_CNT(write_ptr, read_ptr, drvdata->size); } /* * The TMC RAM buffer may be bigger than the space available in the * perf ring buffer (handle->size). If so advance the RRP so that we * get the latest trace data. */ if (to_read > handle->size) { u32 mask = 0; /* * The value written to RRP must be byte-address aligned to * the width of the trace memory databus _and_ to a frame * boundary (16 byte), whichever is the biggest. For example, * for 32-bit, 64-bit and 128-bit wide trace memory, the four * LSBs must be 0s. For 256-bit wide trace memory, the five * LSBs must be 0s. */ switch (drvdata->memwidth) { case TMC_MEM_INTF_WIDTH_32BITS: case TMC_MEM_INTF_WIDTH_64BITS: case TMC_MEM_INTF_WIDTH_128BITS: mask = GENMASK(31, 5); break; case TMC_MEM_INTF_WIDTH_256BITS: mask = GENMASK(31, 6); break; } /* * Make sure the new size is aligned in accordance with the * requirement explained above. */ to_read = handle->size & mask; /* Move the RAM read pointer up */ read_ptr = (write_ptr + drvdata->size) - to_read; /* Make sure we are still within our limits */ if (read_ptr > (drvdata->size - 1)) read_ptr -= drvdata->size; /* Tell the HW */ writel_relaxed(read_ptr, drvdata->base + TMC_RRP); local_inc(&buf->lost); } cur = buf->cur; offset = buf->offset; /* for every byte to read */ for (i = 0; i < to_read; i += 4) { buf_ptr = buf->data_pages[cur] + offset; *buf_ptr = readl_relaxed(drvdata->base + TMC_RRD); offset += 4; if (offset >= PAGE_SIZE) { offset = 0; cur++; /* wrap around at the end of the buffer */ cur &= buf->nr_pages - 1; } } /* * In snapshot mode all we have to do is communicate to * perf_aux_output_end() the address of the current head. In full * trace mode the same function expects a size to move rb->aux_head * forward. */ if (buf->snapshot) local_set(&buf->data_size, (cur * PAGE_SIZE) + offset); else local_add(to_read, &buf->data_size); CS_LOCK(drvdata->base); }
void CWebShopPktQueue::ReInitThis() { CS_LOCK(csThis); f = r = 0; CS_UNLOCK(csThis); }