Example #1
0
static void __etb_dump(void)
{
	int i;
	uint8_t *buf_ptr;
	uint32_t read_data;
	uint32_t read_ptr;
	uint32_t write_ptr;

	ETB_UNLOCK();

	read_ptr = etb_readl(etb, ETB_RAM_READ_POINTER);
	write_ptr = etb_readl(etb, ETB_RAM_WRITE_POINTER);

	if ((etb_readl(etb, ETB_STATUS_REG) & BIT(0)) == 0)
		etb_writel(etb, 0x0, ETB_RAM_READ_POINTER);
	else
		etb_writel(etb, write_ptr, ETB_RAM_READ_POINTER);

	buf_ptr = etb.buf;
	for (i = 0; i < ETB_SIZE_WORDS; i++) {
		read_data = etb_readl(etb, ETB_RAM_READ_DATA_REG);
		*buf_ptr = read_data >> 0;
		buf_ptr++;
		*buf_ptr = read_data >> 8;
		buf_ptr++;
		*buf_ptr = read_data >> 16;
		buf_ptr++;
		*buf_ptr = read_data >> 24;
		buf_ptr++;
	}

	etb_writel(etb, read_ptr, ETB_RAM_READ_POINTER);

	ETB_LOCK();
}
Example #2
0
static void __etb_disable(void)
{
	int count;
	uint32_t ffcr;

	ETB_UNLOCK();

	ffcr = etb_readl(etb, ETB_FFCR);
	ffcr |= (BIT(12) | BIT(6));
	etb_writel(etb, ffcr, ETB_FFCR);

	for (count = TIMEOUT_US; BVAL(etb_readl(etb, ETB_FFCR), 6) != 0
				&& count > 0; count--)
		udelay(1);
	WARN(count == 0, "timeout while flushing ETB, ETB_FFCR: %#x\n",
	     etb_readl(etb, ETB_FFCR));

	etb_writel(etb, 0x0, ETB_CTL_REG);

	for (count = TIMEOUT_US; BVAL(etb_readl(etb, ETB_FFSR), 1) != 1
				&& count > 0; count--)
		udelay(1);
	WARN(count == 0, "timeout while disabling ETB, ETB_FFSR: %#x\n",
	     etb_readl(etb, ETB_FFSR));

	ETB_LOCK();
}
Example #3
0
static void __etb_disable(void)
{
	int count;
	uint32_t ffcr;

	/* Avoid oopsing in panic() if called before the device is probed. */
	if (!etb.base)
		return;

	ETB_UNLOCK();

	ffcr = etb_readl(etb, ETB_FFCR);
	ffcr |= (BIT(12) | BIT(6));
	etb_writel(etb, ffcr, ETB_FFCR);

	for (count = TIMEOUT_US; BVAL(etb_readl(etb, ETB_FFCR), 6) != 0
				&& count > 0; count--)
		udelay(1);
	WARN(count == 0, "timeout while flushing ETB, ETB_FFCR: %#x\n",
	     etb_readl(etb, ETB_FFCR));

	etb_writel(etb, 0x0, ETB_CTL_REG);

	for (count = TIMEOUT_US; BVAL(etb_readl(etb, ETB_FFSR), 1) != 1
				&& count > 0; count--)
		udelay(1);
	WARN(count == 0, "timeout while disabling ETB, ETB_FFSR: %#x\n",
	     etb_readl(etb, ETB_FFSR));

	ETB_LOCK();
}
Example #4
0
File: etm.c Project: 08opt/linux
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;
}
Example #5
0
File: etm.c Project: 08opt/linux
static int __devinit etb_probe(struct amba_device *dev, const struct amba_id *id)
{
	struct tracectx *t = &tracer;
	int ret = 0;

	ret = amba_request_regions(dev, NULL);
	if (ret)
		goto out;

	t->etb_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res));
	if (!t->etb_regs) {
		ret = -ENOMEM;
		goto out_release;
	}

	amba_set_drvdata(dev, t);

	etb_miscdev.parent = &dev->dev;

	ret = misc_register(&etb_miscdev);
	if (ret)
		goto out_unmap;

	t->emu_clk = clk_get(&dev->dev, "emu_src_ck");
	if (IS_ERR(t->emu_clk)) {
		dev_dbg(&dev->dev, "Failed to obtain emu_src_ck.\n");
		return -EFAULT;
	}

	clk_enable(t->emu_clk);

	etb_unlock(t);
	t->etb_bufsz = etb_readl(t, ETBR_DEPTH);
	dev_dbg(&dev->dev, "Size: %x\n", t->etb_bufsz);

	/* make sure trace capture is disabled */
	etb_writel(t, 0, ETBR_CTRL);
	etb_writel(t, 0x1000, ETBR_FORMATTERCTRL);
	etb_lock(t);

	dev_dbg(&dev->dev, "ETB AMBA driver initialized.\n");

out:
	return ret;

out_unmap:
	amba_set_drvdata(dev, NULL);
	iounmap(t->etb_regs);

out_release:
	amba_release_regions(dev);

	return ret;
}
Example #6
0
static void __etb_dump(void)
{
	int i;
	uint8_t *buf_ptr;
	uint32_t read_data;
	uint32_t read_ptr;
	uint32_t write_ptr;
	uint32_t frame_off;
	uint32_t frame_endoff;

	ETB_UNLOCK();

	read_ptr = etb_readl(etb, ETB_RAM_READ_POINTER);
	write_ptr = etb_readl(etb, ETB_RAM_WRITE_POINTER);

	frame_off = write_ptr % FRAME_SIZE_WORDS;
	frame_endoff = FRAME_SIZE_WORDS - frame_off;
	if (frame_off) {
		dev_err(etb.dev, "write_ptr: %lu not aligned to formatter "
				"frame size\n", (unsigned long)write_ptr);
		dev_err(etb.dev, "frameoff: %lu, frame_endoff: %lu\n",
			(unsigned long)frame_off, (unsigned long)frame_endoff);
		write_ptr += frame_endoff;
	}

	if ((etb_readl(etb, ETB_STATUS_REG) & BIT(0)) == 0)
		etb_writel(etb, 0x0, ETB_RAM_READ_POINTER);
	else
		etb_writel(etb, write_ptr, ETB_RAM_READ_POINTER);

	buf_ptr = etb.buf;
	for (i = 0; i < ETB_SIZE_WORDS; i++) {
		read_data = etb_readl(etb, ETB_RAM_READ_DATA_REG);
		*buf_ptr++ = read_data >> 0;
		*buf_ptr++ = read_data >> 8;
		*buf_ptr++ = read_data >> 16;
		*buf_ptr++ = read_data >> 24;
	}

	if (frame_off) {
		buf_ptr -= (frame_endoff * BYTES_PER_WORD);
		for (i = 0; i < frame_endoff; i++) {
			*buf_ptr++ = 0x0;
			*buf_ptr++ = 0x0;
			*buf_ptr++ = 0x0;
			*buf_ptr++ = 0x0;
		}
	}

	etb_writel(etb, read_ptr, ETB_RAM_READ_POINTER);

	ETB_LOCK();
}
Example #7
0
static void __etb_disable(void)
{
	int count;

	ETB_UNLOCK();

	etb_writel(etb, BIT(12) | BIT(13), ETB_FFCR);
	etb_writel(etb, 0x0, ETB_CTL_REG);

	for (count = TIMEOUT_US; BVAL(etb_readl(etb, ETB_FFSR), 1) != 1
				&& count > 0; count--)
		udelay(1);
	WARN(count == 0, "timeout while disabling etb\n");

	ETB_LOCK();
}
static int etb_probe(struct platform_device *pdev)
{
	struct etb_driver_data *data = dev_get_platdata(&pdev->dev);

	mutex_lock(&tracer.mutex);

	tracer.etb_regs = data->etb_regs;
	tracer.funnel_regs = data->funnel_regs;
	tracer.tpiu_regs = data->tpiu_regs;
	tracer.dem_regs = data->dem_regs;
	tracer.etr_virt = data->etr_virt;
	tracer.etr_phys = data->etr_phys;
	tracer.etr_len = data->etr_len;
	tracer.use_etr = data->use_etr;
  
	if (unlikely(misc_register(&etb_device) != 0)) {
		pr_err("Fail to register etb device\n");
	}

	/* AHBAP_EN to enable master port, then ETR could write the trace to bus */
	__raw_writel(DEM_UNLOCK_MAGIC, DEM_UNLOCK);
	mt65xx_reg_sync_writel(AHB_EN, AHBAP_EN);

	etb_unlock(&tracer);

	if (tracer.use_etr) {
		pr_info("ETR virt = 0x%x, phys = 0x%x\n", tracer.etr_virt, tracer.etr_phys);
		/* Set up ETR memory buffer address */  
		etb_writel(&tracer, tracer.etr_phys, 0x118);
		/* Set up ETR memory buffer size */
		etb_writel(&tracer, tracer.etr_len, 0x4);
	}

	/* Disable ETB capture (ETB_CTL bit0 = 0x0) */
	/* For wdt reset */
	cs_cpu_write(tracer.etb_regs, 0x20, 0x0);

	tracer.etb_total_buf_size = etb_readl(&tracer, ETBRDP);
	tracer.state = TRACE_STATE_STOP;

	mutex_unlock(&tracer.mutex);

	return 0;
}
/**
 * enable further write access to ETB registers
 * @param ctx trace context
 */
void etb_unlock(const struct etm_trace_context_t *ctx)
{
	if (etb_supports_lock(ctx)) {
		do {
			etb_writel(ctx, ETBLA_UNLOCK_MAGIC, ETBLA);
		} while (unlikely(etb_is_locked(ctx)));
	} else {
		pr_warning("ETB does not support lock\n");
	}
}
Example #10
0
File: etm.c Project: 08opt/linux
static int etb_getdatalen(struct tracectx *t)
{
	u32 v;
	int rp, wp;

	v = etb_readl(t, ETBR_STATUS);

	if (v & 1)
		return t->etb_bufsz;

	rp = etb_readl(t, ETBR_READADDR);
	wp = etb_readl(t, ETBR_WRITEADDR);

	if (rp > wp) {
		etb_writel(t, 0, ETBR_READADDR);
		etb_writel(t, 0, ETBR_WRITEADDR);

		return 0;
	}

	return wp - rp;
}
Example #11
0
File: etm.c Project: 08opt/linux
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;
}
Example #12
0
File: etm.c Project: 08opt/linux
static ssize_t etb_read(struct file *file, char __user *data,
		size_t len, loff_t *ppos)
{
	int total, i;
	long length;
	struct tracectx *t = file->private_data;
	u32 first = 0;
	u32 *buf;

	mutex_lock(&t->mutex);

	if (trace_isrunning(t)) {
		length = 0;
		goto out;
	}

	etb_unlock(t);

	total = etb_getdatalen(t);
	if (total == t->etb_bufsz)
		first = etb_readl(t, ETBR_WRITEADDR);

	etb_writel(t, first, ETBR_READADDR);

	length = min(total * 4, (int)len);
	buf = vmalloc(length);

	dev_dbg(t->dev, "ETB buffer length: %d\n", total);
	dev_dbg(t->dev, "ETB status reg: %x\n", etb_readl(t, ETBR_STATUS));
	for (i = 0; i < length / 4; i++)
		buf[i] = etb_readl(t, ETBR_READMEM);

	/* the only way to deassert overflow bit in ETB status is this */
	etb_writel(t, 1, ETBR_CTRL);
	etb_writel(t, 0, ETBR_CTRL);

	etb_writel(t, 0, ETBR_WRITEADDR);
	etb_writel(t, 0, ETBR_READADDR);
	etb_writel(t, 0, ETBR_TRIGGERCOUNT);

	etb_lock(t);

	length -= copy_to_user(data, buf, length);
	vfree(buf);

out:
	mutex_unlock(&t->mutex);

	return length;
}
Example #13
0
static void __etb_enable(void)
{
	int i;

	ETB_UNLOCK();

	etb_writel(etb, 0x0, ETB_RAM_WRITE_POINTER);
	for (i = 0; i < ETB_SIZE_WORDS; i++)
		etb_writel(etb, 0x0, ETB_RWD_REG);

	etb_writel(etb, 0x0, ETB_RAM_WRITE_POINTER);
	etb_writel(etb, 0x0, ETB_RAM_READ_POINTER);

	etb_writel(etb, etb.trigger_cntr, ETB_TRG);
	etb_writel(etb, BIT(13) | BIT(0), ETB_FFCR);
	etb_writel(etb, BIT(0), ETB_CTL_REG);

	ETB_LOCK();
}
Example #14
0
static void __etb_enable(struct etb_drvdata *drvdata)
{
	int i;

	ETB_UNLOCK(drvdata);

	etb_writel(drvdata, 0x0, ETB_RAM_WRITE_POINTER);
	for (i = 0; i < ETB_SIZE_WORDS; i++)
		etb_writel(drvdata, 0x0, ETB_RWD_REG);

	etb_writel(drvdata, 0x0, ETB_RAM_WRITE_POINTER);
	etb_writel(drvdata, 0x0, ETB_RAM_READ_POINTER);

	etb_writel(drvdata, drvdata->trigger_cntr, ETB_TRG);
	etb_writel(drvdata, BIT(13) | BIT(0), ETB_FFCR);
	etb_writel(drvdata, BIT(0), ETB_CTL_REG);

	ETB_LOCK(drvdata);
}
Example #15
0
File: etm.c Project: 08opt/linux
/* sysrq+v will always stop the running trace and leave it at that */
static void etm_dump(void)
{
	struct tracectx *t = &tracer;
	u32 first = 0;
	int length;

	if (!t->etb_regs) {
		printk(KERN_INFO "No tracing hardware found\n");
		return;
	}

	if (trace_isrunning(t))
		trace_stop(t);

	etb_unlock(t);

	length = etb_getdatalen(t);

	if (length == t->etb_bufsz)
		first = etb_readl(t, ETBR_WRITEADDR);

	etb_writel(t, first, ETBR_READADDR);

	printk(KERN_INFO "Trace buffer contents length: %d\n", length);
	printk(KERN_INFO "--- ETB buffer begin ---\n");
	for (; length; length--)
		printk("%08x", cpu_to_be32(etb_readl(t, ETBR_READMEM)));
	printk(KERN_INFO "\n--- ETB buffer end ---\n");

	/* deassert the overflow bit */
	etb_writel(t, 1, ETBR_CTRL);
	etb_writel(t, 0, ETBR_CTRL);

	etb_writel(t, 0, ETBR_TRIGGERCOUNT);
	etb_writel(t, 0, ETBR_READADDR);
	etb_writel(t, 0, ETBR_WRITEADDR);

	etb_lock(t);
}
static ssize_t etb_read(struct file *file, char __user *data,
					size_t len, loff_t *ppos)
{
	int total, i;
	long length;
	struct etm_trace_context_t *t = file->private_data;
	u32 first = 0, buffer_end = 0;
	u32 *buf;
	int wpos;
	int skip;
	long wlength;
	loff_t pos = *ppos;

	mutex_lock(&t->mutex);

	if (t->state == TRACE_STATE_TRACING) {
		length = 0;
		pr_err("Need to stop trace\n");
		goto out;
	}

	etb_unlock(t);

	total = etb_get_data_length(t);
	if (total == t->etb_total_buf_size) {
		first = etb_readl(t, ETBRWP);
		if (t->use_etr) {
			first = (first - t->etr_phys) / 4;
		}
	}

	if (pos > total * 4) {
		skip = 0;
		wpos = total;
	} else {
		skip = (int)pos % 4;
		wpos = (int)pos / 4;
	}
	total -= wpos;
	first = (first + wpos) % t->etb_total_buf_size;

	etb_writel(t, first, ETBRRP);

	wlength = min(total, DIV_ROUND_UP(skip + (int)len, 4));
	length = min(total * 4 - skip, (int)len);
	if (wlength == 0) {
		goto out;
	}

	buf = vmalloc(wlength * 4);

	pr_info("ETB read %ld bytes to %lld from %ld words at %d\n",
		length, pos, wlength, first);
	pr_info("ETB buffer length: %d\n", total + wpos);
	pr_info("ETB status reg: 0x%x\n", etb_readl(t, ETBSTS));

	if (t->use_etr) {
		/* 
		 * XXX: ETBRRP cannot wrap around correctly on ETR. 
		 *	  The workaround is to read the buffer from WTBRWP directly.
		 */

		pr_info("ETR virt = 0x%x, phys = 0x%x\n", t->etr_virt, t->etr_phys);

		/* translate first and buffer_end from phys to virt */
		first *= 4;
		first += t->etr_virt;
		buffer_end = t->etr_virt + (t->etr_len * 4);
		pr_info("first(virt) = 0x%x\n\n", first);

		for (i = 0; i < wlength; i++) {
			buf[i] = *((unsigned int*)(first));
			first += 4;
			if (first >= buffer_end) {
				first = t->etr_virt;  
			}
		}
	} else {
		for (i = 0; i < wlength; i++) {
			buf[i] = etb_readl(t, ETBRRD);
		}
	}

	etb_lock(t);

	length -= copy_to_user(data, (u8 *)buf + skip, length);
	vfree(buf);
	*ppos = pos + length;

out:
	mutex_unlock(&t->mutex);

	return length;
}
/* 
 * trace_start_by_cpus: Restart traces of the given CPUs.
 * @mask: cpu mask
 * @init_etb: a flag to re-initialize ETB, funnel, ... etc
 */
void trace_start_by_cpus(const struct cpumask *mask, int init_etb)
{
	int i;

	if (!mask) {
		return ;
	}

	if (init_etb) {
		/* enable master port such that ETR could write the trace to bus */
		mt65xx_reg_sync_writel(AHB_EN, (volatile u32 *)AHBAP_EN);

		etb_unlock(&tracer);

		if (tracer.use_etr) {
			/* Set up ETR memory buffer address */  
			etb_writel(&tracer, tracer.etr_phys, 0x118);
			/* Set up ETR memory buffer size */
			etb_writel(&tracer, tracer.etr_len, 0x4);
		}

		/* Disable ETB capture (ETB_CTL bit0 = 0x0) */
		/* For wdt reset */
		cs_cpu_write (tracer.etb_regs, 0x20, 0x0);
	}

	for (i = 0; i < tracer.nr_etm_regs; i++) {
		if (cpumask_test_cpu(i, mask)) {
			cs_cpu_unlock(tracer.etm_regs[i]);
		}
	}

	if (init_etb) {
		cs_cpu_unlock(tracer.tpiu_regs);
		cs_cpu_unlock(tracer.funnel_regs);
		cs_cpu_unlock(tracer.etb_regs);
  
		cs_cpu_funnel_setup();
		cs_cpu_etb_setup();
	}

	/* Power-up PTMs */
	for (i = 0; i < tracer.nr_etm_regs; i++) {
		if (cpumask_test_cpu(i, mask)) {
			cs_cpu_ptm_powerup(tracer.etm_regs[i]);
		}
	}

	/* Disable PTMs so that they can be set up safely */
	for (i = 0; i < tracer.nr_etm_regs; i++) {
		if (cpumask_test_cpu(i, mask)) {
			cs_cpu_ptm_progbit(tracer.etm_regs[i]);
		}
	}

	/* Set up PTMs */
	for (i = 0; i < tracer.nr_etm_regs; i++) {
		if (cpumask_test_cpu(i, mask)) {
			cs_cpu_test_common_ptm_setup(tracer.etm_regs[i], i);
		}
	}
  
	/* Set up CoreSightTraceID */
	for (i = 0; i < tracer.nr_etm_regs; i++) {
		if (cpumask_test_cpu(i, mask)) {
			cs_cpu_write(tracer.etm_regs[i], 0x200, i + 1);
		}
	}
 
	/* Enable PTMs now everything has been set up */
	for (i = 0; i < tracer.nr_etm_regs; i++) {
		if (cpumask_test_cpu(i, mask)) {
			cs_cpu_ptm_clear_progbit(tracer.etm_regs[i]);
		}
	}

	if (init_etb) { 
		/* Avoid DBG_sys being reset */
		mt65xx_reg_sync_writel(DEM_UNLOCK_MAGIC, (volatile u32 *)DEM_UNLOCK);
		mt65xx_reg_sync_writel(POWER_ON_RESET, (volatile u32 *)DBGRST_ALL);
		mt65xx_reg_sync_writel(BUSCLK_EN, (volatile u32 *)DBGBUSCLK_EN);
		mt65xx_reg_sync_writel(SYSCLK_EN, (volatile u32 *)DBGSYSCLK_EN);

		etb_lock(&tracer);
	}
}