static int trace_start(struct tracectx *t) { u32 v; unsigned long timeout = TRACER_TIMEOUT; etb_unlock(t); etb_writel(t, 0, ETBR_FORMATTERCTRL); etb_writel(t, 1, ETBR_CTRL); etb_lock(t); /* configure etm */ v = ETMCTRL_OPTS | ETMCTRL_PROGRAM | ETMCTRL_PORTSIZE(t->etm_portsz); if (t->flags & TRACER_CYCLE_ACC) v |= ETMCTRL_CYCLEACCURATE; etm_unlock(t); etm_writel(t, v, ETMR_CTRL); while (!(etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout) ; if (!timeout) { dev_dbg(t->dev, "Waiting for progbit to assert timed out\n"); etm_lock(t); return -EFAULT; } etm_setup_address_range(t, 1, (unsigned long)_stext, (unsigned long)_etext, 0, 0); etm_writel(t, 0, ETMR_TRACEENCTRL2); etm_writel(t, 0, ETMR_TRACESSCTRL); etm_writel(t, 0x6f, ETMR_TRACEENEVT); v &= ~ETMCTRL_PROGRAM; v |= ETMCTRL_PORTSEL; etm_writel(t, v, ETMR_CTRL); timeout = TRACER_TIMEOUT; while (etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM && --timeout) ; if (!timeout) { dev_dbg(t->dev, "Waiting for progbit to deassert timed out\n"); etm_lock(t); return -EFAULT; } etm_lock(t); t->flags |= TRACER_RUNNING; return 0; }
static int trace_stop(struct tracectx *t) { unsigned long timeout = TRACER_TIMEOUT; etm_unlock(t); etm_writel(t, 0x440, ETMR_CTRL); while (!(etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout) ; if (!timeout) { dev_dbg(t->dev, "Waiting for progbit to assert timed out\n"); etm_lock(t); return -EFAULT; } etm_lock(t); etb_unlock(t); etb_writel(t, ETBFF_MANUAL_FLUSH, ETBR_FORMATTERCTRL); timeout = TRACER_TIMEOUT; while (etb_readl(t, ETBR_FORMATTERCTRL) & ETBFF_MANUAL_FLUSH && --timeout) ; if (!timeout) { dev_dbg(t->dev, "Waiting for formatter flush to commence " "timed out\n"); etb_lock(t); return -EFAULT; } etb_writel(t, 0, ETBR_CTRL); etb_lock(t); t->flags &= ~TRACER_RUNNING; return 0; }
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 ssize_t trace_info_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { u32 etb_wa, etb_ra, etb_st, etb_fc, etm_ctrl, etm_st; int datalen; etb_unlock(&tracer); datalen = etb_getdatalen(&tracer); etb_wa = etb_readl(&tracer, ETBR_WRITEADDR); etb_ra = etb_readl(&tracer, ETBR_READADDR); etb_st = etb_readl(&tracer, ETBR_STATUS); etb_fc = etb_readl(&tracer, ETBR_FORMATTERCTRL); etb_lock(&tracer); etm_unlock(&tracer); etm_ctrl = etm_readl(&tracer, ETMR_CTRL); etm_st = etm_readl(&tracer, ETMR_STATUS); etm_lock(&tracer); return sprintf(buf, "Trace buffer len: %d\nComparator pairs: %d\n" "ETBR_WRITEADDR:\t%08x\n" "ETBR_READADDR:\t%08x\n" "ETBR_STATUS:\t%08x\n" "ETBR_FORMATTERCTRL:\t%08x\n" "ETMR_CTRL:\t%08x\n" "ETMR_STATUS:\t%08x\n", datalen, tracer.ncmppairs, etb_wa, etb_ra, etb_st, etb_fc, etm_ctrl, etm_st ); }
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 int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id) { struct tracectx *t = &tracer; int ret = 0; if (t->etm_regs) { dev_dbg(&dev->dev, "ETM already initialized\n"); ret = -EBUSY; goto out; } ret = amba_request_regions(dev, NULL); if (ret) goto out; t->etm_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res)); if (!t->etm_regs) { ret = -ENOMEM; goto out_release; } amba_set_drvdata(dev, t); mutex_init(&t->mutex); t->dev = &dev->dev; t->flags = TRACER_CYCLE_ACC; t->etm_portsz = 1; etm_unlock(t); (void)etm_readl(t, ETMMR_PDSR); /* dummy first read */ (void)etm_readl(&tracer, ETMMR_OSSRR); t->ncmppairs = etm_readl(t, ETMR_CONFCODE) & 0xf; etm_writel(t, 0x440, ETMR_CTRL); etm_lock(t); ret = sysfs_create_file(&dev->dev.kobj, &trace_running_attr.attr); if (ret) goto out_unmap; /* failing to create any of these two is not fatal */ ret = sysfs_create_file(&dev->dev.kobj, &trace_info_attr.attr); if (ret) dev_dbg(&dev->dev, "Failed to create trace_info in sysfs\n"); ret = sysfs_create_file(&dev->dev.kobj, &trace_mode_attr.attr); if (ret) dev_dbg(&dev->dev, "Failed to create trace_mode in sysfs\n"); dev_dbg(t->dev, "ETM AMBA driver initialized.\n"); out: return ret; out_unmap: amba_set_drvdata(dev, NULL); iounmap(t->etm_regs); out_release: amba_release_regions(dev); return ret; }