Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 58f19d6c authored by Pratik Patel's avatar Pratik Patel Committed by Stephen Boyd
Browse files

cs: rename driver state data to drvdata and dynamically allocate it



In preparation for using the CoreSight core layer code, rename driver
state data to drvdata. Dynamically allocate drvdata to support more
than one device instance and hence more than one drvdata instance.

Change-Id: I6f98f3194ff012c34ff6851e60e4429febfb15bd
Signed-off-by: default avatarPratik Patel <pratikp@codeaurora.org>
parent 5b57608e
Loading
Loading
Loading
Loading
+93 −84
Original line number Diff line number Diff line
@@ -29,8 +29,8 @@

#include "cs-priv.h"

#define etb_writel(etb, val, off)	__raw_writel((val), etb.base + off)
#define etb_readl(etb, off)		__raw_readl(etb.base + off)
#define etb_writel(drvdata, val, off)	__raw_writel((val), drvdata->base + off)
#define etb_readl(drvdata, off)		__raw_readl(drvdata->base + off)

#define ETB_RAM_DEPTH_REG	(0x004)
#define ETB_STATUS_REG		(0x00C)
@@ -58,15 +58,15 @@
#define ETB_LOCK()							\
do {									\
	mb();								\
	etb_writel(etb, 0x0, CS_LAR);					\
	etb_writel(drvdata, 0x0, CS_LAR);				\
} while (0)
#define ETB_UNLOCK()							\
do {									\
	etb_writel(etb, CS_UNLOCK_MAGIC, CS_LAR);			\
	etb_writel(drvdata, CS_UNLOCK_MAGIC, CS_LAR);			\
	mb();								\
} while (0)

struct etb_ctx {
struct etb_drvdata {
	uint8_t		*buf;
	void __iomem	*base;
	bool		enabled;
@@ -79,7 +79,7 @@ struct etb_ctx {
	uint32_t	trigger_cntr;
};

static struct etb_ctx etb;
static struct etb_drvdata *drvdata;

static void __etb_enable(void)
{
@@ -87,16 +87,16 @@ static void __etb_enable(void)

	ETB_UNLOCK();

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

	etb_writel(etb, 0x0, ETB_RAM_WRITE_POINTER);
	etb_writel(etb, 0x0, ETB_RAM_READ_POINTER);
	etb_writel(drvdata, 0x0, ETB_RAM_WRITE_POINTER);
	etb_writel(drvdata, 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_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();
}
@@ -106,15 +106,15 @@ int etb_enable(void)
	int ret;
	unsigned long flags;

	ret = clk_prepare_enable(etb.clk);
	ret = clk_prepare_enable(drvdata->clk);
	if (ret)
		return ret;

	spin_lock_irqsave(&etb.spinlock, flags);
	spin_lock_irqsave(&drvdata->spinlock, flags);
	__etb_enable();
	etb.enabled = true;
	dev_info(etb.dev, "ETB enabled\n");
	spin_unlock_irqrestore(&etb.spinlock, flags);
	drvdata->enabled = true;
	dev_info(drvdata->dev, "ETB enabled\n");
	spin_unlock_irqrestore(&drvdata->spinlock, flags);

	return 0;
}
@@ -126,23 +126,23 @@ static void __etb_disable(void)

	ETB_UNLOCK();

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

	for (count = TIMEOUT_US; BVAL(etb_readl(etb, ETB_FFCR), 6) != 0
	for (count = TIMEOUT_US; BVAL(etb_readl(drvdata, 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));
	WARN(count == 0, "timeout while flushing DRVDATA, ETB_FFCR: %#x\n",
	     etb_readl(drvdata, ETB_FFCR));

	etb_writel(etb, 0x0, ETB_CTL_REG);
	etb_writel(drvdata, 0x0, ETB_CTL_REG);

	for (count = TIMEOUT_US; BVAL(etb_readl(etb, ETB_FFSR), 1) != 1
	for (count = TIMEOUT_US; BVAL(etb_readl(drvdata, 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));
	WARN(count == 0, "timeout while disabling DRVDATA, ETB_FFSR: %#x\n",
	     etb_readl(drvdata, ETB_FFSR));

	ETB_LOCK();
}
@@ -151,13 +151,13 @@ void etb_disable(void)
{
	unsigned long flags;

	spin_lock_irqsave(&etb.spinlock, flags);
	spin_lock_irqsave(&drvdata->spinlock, flags);
	__etb_disable();
	etb.enabled = false;
	dev_info(etb.dev, "ETB disabled\n");
	spin_unlock_irqrestore(&etb.spinlock, flags);
	drvdata->enabled = false;
	dev_info(drvdata->dev, "ETB disabled\n");
	spin_unlock_irqrestore(&drvdata->spinlock, flags);

	clk_disable_unprepare(etb.clk);
	clk_disable_unprepare(drvdata->clk);
}

static void __etb_dump(void)
@@ -172,27 +172,27 @@ static void __etb_dump(void)

	ETB_UNLOCK();

	read_ptr = etb_readl(etb, ETB_RAM_READ_POINTER);
	write_ptr = etb_readl(etb, ETB_RAM_WRITE_POINTER);
	read_ptr = etb_readl(drvdata, ETB_RAM_READ_POINTER);
	write_ptr = etb_readl(drvdata, 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 "
		dev_err(drvdata->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",
		dev_err(drvdata->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);
	if ((etb_readl(drvdata, ETB_STATUS_REG) & BIT(0)) == 0)
		etb_writel(drvdata, 0x0, ETB_RAM_READ_POINTER);
	else
		etb_writel(etb, write_ptr, ETB_RAM_READ_POINTER);
		etb_writel(drvdata, write_ptr, ETB_RAM_READ_POINTER);

	buf_ptr = etb.buf;
	buf_ptr = drvdata->buf;
	for (i = 0; i < ETB_SIZE_WORDS; i++) {
		read_data = etb_readl(etb, ETB_RAM_READ_DATA_REG);
		read_data = etb_readl(drvdata, ETB_RAM_READ_DATA_REG);
		*buf_ptr++ = read_data >> 0;
		*buf_ptr++ = read_data >> 8;
		*buf_ptr++ = read_data >> 16;
@@ -209,7 +209,7 @@ static void __etb_dump(void)
		}
	}

	etb_writel(etb, read_ptr, ETB_RAM_READ_POINTER);
	etb_writel(drvdata, read_ptr, ETB_RAM_READ_POINTER);

	ETB_LOCK();
}
@@ -218,45 +218,45 @@ void etb_dump(void)
{
	unsigned long flags;

	spin_lock_irqsave(&etb.spinlock, flags);
	if (etb.enabled) {
	spin_lock_irqsave(&drvdata->spinlock, flags);
	if (drvdata->enabled) {
		__etb_disable();
		__etb_dump();
		__etb_enable();

		dev_info(etb.dev, "ETB dumped\n");
		dev_info(drvdata->dev, "ETB dumped\n");
	}
	spin_unlock_irqrestore(&etb.spinlock, flags);
	spin_unlock_irqrestore(&drvdata->spinlock, flags);
}

static int etb_open(struct inode *inode, struct file *file)
{
	if (atomic_cmpxchg(&etb.in_use, 0, 1))
	if (atomic_cmpxchg(&drvdata->in_use, 0, 1))
		return -EBUSY;

	dev_dbg(etb.dev, "%s: successfully opened\n", __func__);
	dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
	return 0;
}

static ssize_t etb_read(struct file *file, char __user *data,
				size_t len, loff_t *ppos)
{
	if (etb.reading == false) {
	if (drvdata->reading == false) {
		etb_dump();
		etb.reading = true;
		drvdata->reading = true;
	}

	if (*ppos + len > ETB_SIZE_WORDS * BYTES_PER_WORD)
		len = ETB_SIZE_WORDS * BYTES_PER_WORD - *ppos;

	if (copy_to_user(data, etb.buf + *ppos, len)) {
		dev_dbg(etb.dev, "%s: copy_to_user failed\n", __func__);
	if (copy_to_user(data, drvdata->buf + *ppos, len)) {
		dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
		return -EFAULT;
	}

	*ppos += len;

	dev_dbg(etb.dev, "%s: %d bytes copied, %d bytes left\n",
	dev_dbg(drvdata->dev, "%s: %d bytes copied, %d bytes left\n",
		__func__, len, (int) (ETB_SIZE_WORDS * BYTES_PER_WORD - *ppos));

	return len;
@@ -264,11 +264,11 @@ static ssize_t etb_read(struct file *file, char __user *data,

static int etb_release(struct inode *inode, struct file *file)
{
	etb.reading = false;
	drvdata->reading = false;

	atomic_set(&etb.in_use, 0);
	atomic_set(&drvdata->in_use, 0);

	dev_dbg(etb.dev, "%s: released\n", __func__);
	dev_dbg(drvdata->dev, "%s: released\n", __func__);

	return 0;
}
@@ -289,7 +289,7 @@ static struct miscdevice etb_misc = {
static ssize_t etb_show_trigger_cntr(struct device *dev,
				     struct device_attribute *attr, char *buf)
{
	unsigned long val = etb.trigger_cntr;
	unsigned long val = drvdata->trigger_cntr;
	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}

@@ -302,7 +302,7 @@ static ssize_t etb_store_trigger_cntr(struct device *dev,
	if (sscanf(buf, "%lx", &val) != 1)
		return -EINVAL;

	etb.trigger_cntr = val;
	drvdata->trigger_cntr = val;
	return size;
}
static DEVICE_ATTR(trigger_cntr, S_IRUGO | S_IWUSR, etb_show_trigger_cntr,
@@ -312,31 +312,31 @@ static int etb_sysfs_init(void)
{
	int ret;

	etb.kobj = kobject_create_and_add("etb", qdss_get_modulekobj());
	if (!etb.kobj) {
		dev_err(etb.dev, "failed to create ETB sysfs kobject\n");
	drvdata->kobj = kobject_create_and_add("etb", qdss_get_modulekobj());
	if (!drvdata->kobj) {
		dev_err(drvdata->dev, "failed to create ETB sysfs kobject\n");
		ret = -ENOMEM;
		goto err_create;
	}

	ret = sysfs_create_file(etb.kobj, &dev_attr_trigger_cntr.attr);
	ret = sysfs_create_file(drvdata->kobj, &dev_attr_trigger_cntr.attr);
	if (ret) {
		dev_err(etb.dev, "failed to create ETB sysfs trigger_cntr"
		dev_err(drvdata->dev, "failed to create ETB sysfs trigger_cntr"
		" attribute\n");
		goto err_file;
	}

	return 0;
err_file:
	kobject_put(etb.kobj);
	kobject_put(drvdata->kobj);
err_create:
	return ret;
}

static void etb_sysfs_exit(void)
{
	sysfs_remove_file(etb.kobj, &dev_attr_trigger_cntr.attr);
	kobject_put(etb.kobj);
	sysfs_remove_file(drvdata->kobj, &dev_attr_trigger_cntr.attr);
	kobject_put(drvdata->kobj);
}

static int etb_probe(struct platform_device *pdev)
@@ -344,29 +344,35 @@ static int etb_probe(struct platform_device *pdev)
	int ret;
	struct resource *res;

	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
	if (!drvdata) {
		ret = -ENOMEM;
		goto err_kzalloc_drvdata;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		ret = -EINVAL;
		goto err_res;
	}

	etb.base = ioremap_nocache(res->start, resource_size(res));
	if (!etb.base) {
	drvdata->base = ioremap_nocache(res->start, resource_size(res));
	if (!drvdata->base) {
		ret = -EINVAL;
		goto err_ioremap;
	}

	etb.dev = &pdev->dev;
	drvdata->dev = &pdev->dev;

	spin_lock_init(&etb.spinlock);
	spin_lock_init(&drvdata->spinlock);

	etb.clk = clk_get(etb.dev, "core_clk");
	if (IS_ERR(etb.clk)) {
		ret = PTR_ERR(etb.clk);
	drvdata->clk = clk_get(drvdata->dev, "core_clk");
	if (IS_ERR(drvdata->clk)) {
		ret = PTR_ERR(drvdata->clk);
		goto err_clk_get;
	}

	ret = clk_set_rate(etb.clk, CS_CLK_RATE_TRACE);
	ret = clk_set_rate(drvdata->clk, CS_CLK_RATE_TRACE);
	if (ret)
		goto err_clk_rate;

@@ -374,39 +380,42 @@ static int etb_probe(struct platform_device *pdev)
	if (ret)
		goto err_misc;

	etb.buf = kzalloc(ETB_SIZE_WORDS * BYTES_PER_WORD, GFP_KERNEL);
	if (!etb.buf) {
	drvdata->buf = kzalloc(ETB_SIZE_WORDS * BYTES_PER_WORD, GFP_KERNEL);
	if (!drvdata->buf) {
		ret = -ENOMEM;
		goto err_alloc;
	}

	etb_sysfs_init();

	dev_info(etb.dev, "ETB initialized\n");
	dev_info(drvdata->dev, "ETB initialized\n");
	return 0;

err_alloc:
	misc_deregister(&etb_misc);
err_misc:
err_clk_rate:
	clk_put(etb.clk);
	clk_put(drvdata->clk);
err_clk_get:
	iounmap(etb.base);
	iounmap(drvdata->base);
err_ioremap:
err_res:
	dev_err(etb.dev, "ETB init failed\n");
	kfree(drvdata);
err_kzalloc_drvdata:
	dev_err(drvdata->dev, "ETB init failed\n");
	return ret;
}

static int etb_remove(struct platform_device *pdev)
{
	if (etb.enabled)
	if (drvdata->enabled)
		etb_disable();
	etb_sysfs_exit();
	kfree(etb.buf);
	kfree(drvdata->buf);
	misc_deregister(&etb_misc);
	clk_put(etb.clk);
	iounmap(etb.base);
	clk_put(drvdata->clk);
	iounmap(drvdata->base);
	kfree(drvdata);

	return 0;
}
+400 −375

File changed.

Preview size limit exceeded, changes collapsed.

+60 −50
Original line number Diff line number Diff line
@@ -18,15 +18,16 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/cs.h>

#include "cs-priv.h"

#define funnel_writel(funnel, id, val, off)	\
			__raw_writel((val), funnel.base + (SZ_4K * id) + off)
#define funnel_readl(funnel, id, off)		\
			__raw_readl(funnel.base + (SZ_4K * id) + off)
#define funnel_writel(drvdata, id, val, off)	\
			__raw_writel((val), drvdata->base + (SZ_4K * id) + off)
#define funnel_readl(drvdata, id, off)		\
			__raw_readl(drvdata->base + (SZ_4K * id) + off)

#define FUNNEL_FUNCTL			(0x000)
#define FUNNEL_PRICTL			(0x004)
@@ -39,11 +40,11 @@
#define FUNNEL_LOCK(id)							\
do {									\
	mb();								\
	funnel_writel(funnel, id, 0x0, CS_LAR);				\
	funnel_writel(drvdata, id, 0x0, CS_LAR);			\
} while (0)
#define FUNNEL_UNLOCK(id)						\
do {									\
	funnel_writel(funnel, id, CS_UNLOCK_MAGIC, CS_LAR);		\
	funnel_writel(drvdata, id, CS_UNLOCK_MAGIC, CS_LAR);		\
	mb();								\
} while (0)

@@ -51,7 +52,7 @@ do { \
#define FUNNEL_HOLDTIME_SHFT		(0x8)
#define FUNNEL_HOLDTIME			(0x7 << FUNNEL_HOLDTIME_SHFT)

struct funnel_ctx {
struct funnel_drvdata {
	void __iomem	*base;
	bool		enabled;
	struct mutex	mutex;
@@ -61,7 +62,7 @@ struct funnel_ctx {
	uint32_t	priority;
};

static struct funnel_ctx funnel;
static struct funnel_drvdata *drvdata;

static void __funnel_enable(uint8_t id, uint32_t port_mask)
{
@@ -69,12 +70,12 @@ static void __funnel_enable(uint8_t id, uint32_t port_mask)

	FUNNEL_UNLOCK(id);

	functl = funnel_readl(funnel, id, FUNNEL_FUNCTL);
	functl = funnel_readl(drvdata, id, FUNNEL_FUNCTL);
	functl &= ~FUNNEL_HOLDTIME_MASK;
	functl |= FUNNEL_HOLDTIME;
	functl |= port_mask;
	funnel_writel(funnel, id, functl, FUNNEL_FUNCTL);
	funnel_writel(funnel, id, funnel.priority, FUNNEL_PRICTL);
	funnel_writel(drvdata, id, functl, FUNNEL_FUNCTL);
	funnel_writel(drvdata, id, drvdata->priority, FUNNEL_PRICTL);

	FUNNEL_LOCK(id);
}
@@ -83,16 +84,16 @@ int funnel_enable(uint8_t id, uint32_t port_mask)
{
	int ret;

	ret = clk_prepare_enable(funnel.clk);
	ret = clk_prepare_enable(drvdata->clk);
	if (ret)
		return ret;

	mutex_lock(&funnel.mutex);
	mutex_lock(&drvdata->mutex);
	__funnel_enable(id, port_mask);
	funnel.enabled = true;
	dev_info(funnel.dev, "FUNNEL port mask 0x%lx enabled\n",
	drvdata->enabled = true;
	dev_info(drvdata->dev, "FUNNEL port mask 0x%lx enabled\n",
					(unsigned long) port_mask);
	mutex_unlock(&funnel.mutex);
	mutex_unlock(&drvdata->mutex);

	return 0;
}
@@ -103,29 +104,29 @@ static void __funnel_disable(uint8_t id, uint32_t port_mask)

	FUNNEL_UNLOCK(id);

	functl = funnel_readl(funnel, id, FUNNEL_FUNCTL);
	functl = funnel_readl(drvdata, id, FUNNEL_FUNCTL);
	functl &= ~port_mask;
	funnel_writel(funnel, id, functl, FUNNEL_FUNCTL);
	funnel_writel(drvdata, id, functl, FUNNEL_FUNCTL);

	FUNNEL_LOCK(id);
}

void funnel_disable(uint8_t id, uint32_t port_mask)
{
	mutex_lock(&funnel.mutex);
	mutex_lock(&drvdata->mutex);
	__funnel_disable(id, port_mask);
	funnel.enabled = false;
	dev_info(funnel.dev, "FUNNEL port mask 0x%lx disabled\n",
	drvdata->enabled = false;
	dev_info(drvdata->dev, "FUNNEL port mask 0x%lx disabled\n",
					(unsigned long) port_mask);
	mutex_unlock(&funnel.mutex);
	mutex_unlock(&drvdata->mutex);

	clk_disable_unprepare(funnel.clk);
	clk_disable_unprepare(drvdata->clk);
}

static ssize_t funnel_show_priority(struct device *dev,
				    struct device_attribute *attr, char *buf)
{
	unsigned long val = funnel.priority;
	unsigned long val = drvdata->priority;
	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}

@@ -138,7 +139,7 @@ static ssize_t funnel_store_priority(struct device *dev,
	if (sscanf(buf, "%lx", &val) != 1)
		return -EINVAL;

	funnel.priority = val;
	drvdata->priority = val;
	return size;
}
static DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, funnel_show_priority,
@@ -148,31 +149,31 @@ static int funnel_sysfs_init(void)
{
	int ret;

	funnel.kobj = kobject_create_and_add("funnel", qdss_get_modulekobj());
	if (!funnel.kobj) {
		dev_err(funnel.dev, "failed to create FUNNEL sysfs kobject\n");
	drvdata->kobj = kobject_create_and_add("funnel", qdss_get_modulekobj());
	if (!drvdata->kobj) {
		dev_err(drvdata->dev, "failed to create FUNNEL sysfs kobject\n");
		ret = -ENOMEM;
		goto err_create;
	}

	ret = sysfs_create_file(funnel.kobj, &dev_attr_priority.attr);
	ret = sysfs_create_file(drvdata->kobj, &dev_attr_priority.attr);
	if (ret) {
		dev_err(funnel.dev, "failed to create FUNNEL sysfs priority"
		dev_err(drvdata->dev, "failed to create FUNNEL sysfs priority"
		" attribute\n");
		goto err_file;
	}

	return 0;
err_file:
	kobject_put(funnel.kobj);
	kobject_put(drvdata->kobj);
err_create:
	return ret;
}

static void funnel_sysfs_exit(void)
{
	sysfs_remove_file(funnel.kobj, &dev_attr_priority.attr);
	kobject_put(funnel.kobj);
	sysfs_remove_file(drvdata->kobj, &dev_attr_priority.attr);
	kobject_put(drvdata->kobj);
}

static int funnel_probe(struct platform_device *pdev)
@@ -180,56 +181,65 @@ static int funnel_probe(struct platform_device *pdev)
	int ret;
	struct resource *res;

	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
	if (!drvdata) {
		ret = -ENOMEM;
		goto err_kzalloc_drvdata;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		ret = -EINVAL;
		goto err_res;
	}

	funnel.base = ioremap_nocache(res->start, resource_size(res));
	if (!funnel.base) {
	drvdata->base = ioremap_nocache(res->start, resource_size(res));
	if (!drvdata->base) {
		ret = -EINVAL;
		goto err_ioremap;
	}

	funnel.dev = &pdev->dev;
	drvdata->dev = &pdev->dev;

	mutex_init(&funnel.mutex);
	mutex_init(&drvdata->mutex);

	funnel.clk = clk_get(funnel.dev, "core_clk");
	if (IS_ERR(funnel.clk)) {
		ret = PTR_ERR(funnel.clk);
	drvdata->clk = clk_get(drvdata->dev, "core_clk");
	if (IS_ERR(drvdata->clk)) {
		ret = PTR_ERR(drvdata->clk);
		goto err_clk_get;
	}

	ret = clk_set_rate(funnel.clk, CS_CLK_RATE_TRACE);
	ret = clk_set_rate(drvdata->clk, CS_CLK_RATE_TRACE);
	if (ret)
		goto err_clk_rate;

	funnel_sysfs_init();

	dev_info(funnel.dev, "FUNNEL initialized\n");
	dev_info(drvdata->dev, "FUNNEL initialized\n");
	return 0;

err_clk_rate:
	clk_put(funnel.clk);
	clk_put(drvdata->clk);
err_clk_get:
	mutex_destroy(&funnel.mutex);
	iounmap(funnel.base);
	mutex_destroy(&drvdata->mutex);
	iounmap(drvdata->base);
err_ioremap:
err_res:
	dev_err(funnel.dev, "FUNNEL init failed\n");
	kfree(drvdata);
err_kzalloc_drvdata:
	dev_err(drvdata->dev, "FUNNEL init failed\n");
	return ret;
}

static int funnel_remove(struct platform_device *pdev)
{
	if (funnel.enabled)
	if (drvdata->enabled)
		funnel_disable(0x0, 0xFF);
	funnel_sysfs_exit();
	clk_put(funnel.clk);
	mutex_destroy(&funnel.mutex);
	iounmap(funnel.base);
	clk_put(drvdata->clk);
	mutex_destroy(&drvdata->mutex);
	iounmap(drvdata->base);
	kfree(drvdata);

	return 0;
}
+91 −80
Original line number Diff line number Diff line
@@ -29,10 +29,10 @@

#include "cs-priv.h"

#define stm_writel(stm, val, off)	\
			__raw_writel((val), stm.base + off)
#define stm_readl(stm, val, off)	\
			__raw_readl(stm.base + off)
#define stm_writel(drvdata, val, off)	\
			__raw_writel((val), drvdata->base + off)
#define stm_readl(drvdata, val, off)	\
			__raw_readl(drvdata->base + off)

#define NR_STM_CHANNEL		(32)
#define BYTES_PER_CHANNEL	(256)
@@ -53,17 +53,17 @@ enum {
#define OST_VERSION		(0x1)

#define stm_channel_addr(ch)						\
				(stm.chs.base + (ch * BYTES_PER_CHANNEL))
				(drvdata->chs.base + (ch * BYTES_PER_CHANNEL))
#define stm_channel_off(type, opts)	(type & ~opts)

#define STM_LOCK()							\
do {									\
	mb();								\
	stm_writel(stm, 0x0, CS_LAR);					\
	stm_writel(drvdata, 0x0, CS_LAR);				\
} while (0)
#define STM_UNLOCK()							\
do {									\
	stm_writel(stm, CS_UNLOCK_MAGIC, CS_LAR);			\
	stm_writel(drvdata, CS_UNLOCK_MAGIC, CS_LAR);			\
	mb();								\
} while (0)

@@ -93,7 +93,7 @@ struct channel_space {
	unsigned long		*bitmap;
};

struct stm_ctx {
struct stm_drvdata {
	void __iomem		*base;
	bool			enabled;
	struct qdss_source	*src;
@@ -104,19 +104,16 @@ struct stm_ctx {
	struct channel_space	chs;
};

static struct stm_ctx stm = {
	.entity		= OST_ENTITY_ALL,
};

static struct stm_drvdata *drvdata;

static void __stm_enable(void)
{
	STM_UNLOCK();

	stm_writel(stm, 0x80, STMSYNCR);
	stm_writel(stm, 0xFFFFFFFF, STMSPTER);
	stm_writel(stm, 0xFFFFFFFF, STMSPER);
	stm_writel(stm, 0x30003, STMTCSR);
	stm_writel(drvdata, 0x80, STMSYNCR);
	stm_writel(drvdata, 0xFFFFFFFF, STMSPTER);
	stm_writel(drvdata, 0xFFFFFFFF, STMSPER);
	stm_writel(drvdata, 0x30003, STMTCSR);

	STM_LOCK();
}
@@ -125,29 +122,29 @@ static int stm_enable(void)
{
	int ret;

	if (stm.enabled) {
		dev_err(stm.dev, "STM tracing already enabled\n");
	if (drvdata->enabled) {
		dev_err(drvdata->dev, "STM tracing already enabled\n");
		ret = -EINVAL;
		goto err;
	}

	ret = clk_prepare_enable(stm.clk);
	ret = clk_prepare_enable(drvdata->clk);
	if (ret)
		goto err_clk;

	ret = qdss_enable(stm.src);
	ret = qdss_enable(drvdata->src);
	if (ret)
		goto err_qdss;

	__stm_enable();

	stm.enabled = true;
	drvdata->enabled = true;

	dev_info(stm.dev, "STM tracing enabled\n");
	dev_info(drvdata->dev, "STM tracing enabled\n");
	return 0;

err_qdss:
	clk_disable_unprepare(stm.clk);
	clk_disable_unprepare(drvdata->clk);
err_clk:
err:
	return ret;
@@ -157,9 +154,9 @@ static void __stm_disable(void)
{
	STM_UNLOCK();

	stm_writel(stm, 0x30000, STMTCSR);
	stm_writel(stm, 0x0, STMSPER);
	stm_writel(stm, 0x0, STMSPTER);
	stm_writel(drvdata, 0x30000, STMTCSR);
	stm_writel(drvdata, 0x0, STMSPER);
	stm_writel(drvdata, 0x0, STMSPTER);

	STM_LOCK();
}
@@ -168,21 +165,21 @@ static int stm_disable(void)
{
	int ret;

	if (!stm.enabled) {
		dev_err(stm.dev, "STM tracing already disabled\n");
	if (!drvdata->enabled) {
		dev_err(drvdata->dev, "STM tracing already disabled\n");
		ret = -EINVAL;
		goto err;
	}

	__stm_disable();

	stm.enabled = false;
	drvdata->enabled = false;

	qdss_disable(stm.src);
	qdss_disable(drvdata->src);

	clk_disable_unprepare(stm.clk);
	clk_disable_unprepare(drvdata->clk);

	dev_info(stm.dev, "STM tracing disabled\n");
	dev_info(drvdata->dev, "STM tracing disabled\n");
	return 0;

err:
@@ -194,15 +191,17 @@ static uint32_t stm_channel_alloc(uint32_t off)
	uint32_t ch;

	do {
		ch = find_next_zero_bit(stm.chs.bitmap,	NR_STM_CHANNEL, off);
	} while ((ch < NR_STM_CHANNEL) && test_and_set_bit(ch, stm.chs.bitmap));
		ch = find_next_zero_bit(drvdata->chs.bitmap,
					NR_STM_CHANNEL, off);
	} while ((ch < NR_STM_CHANNEL) &&
		 test_and_set_bit(ch, drvdata->chs.bitmap));

	return ch;
}

static void stm_channel_free(uint32_t ch)
{
	clear_bit(ch, stm.chs.bitmap);
	clear_bit(ch, drvdata->chs.bitmap);
}

static int stm_send(void *addr, const void *data, uint32_t size)
@@ -346,7 +345,7 @@ int stm_trace(uint32_t options, uint8_t entity_id, uint8_t proto_id,
	      const void *data, uint32_t size)
{
	/* we don't support sizes more than 24bits (0 to 23) */
	if (!(stm.enabled && (stm.entity & entity_id) &&
	if (!(drvdata->enabled && (drvdata->entity & entity_id) &&
	      (size < 0x1000000)))
		return 0;

@@ -359,10 +358,10 @@ static ssize_t stm_write(struct file *file, const char __user *data,
{
	char *buf;

	if (!stm.enabled)
	if (!drvdata->enabled)
		return -EINVAL;

	if (!(stm.entity & OST_ENTITY_DEV_NODE))
	if (!(drvdata->entity & OST_ENTITY_DEV_NODE))
		return size;

	if (size > STM_TRACE_BUF_SIZE)
@@ -374,7 +373,7 @@ static ssize_t stm_write(struct file *file, const char __user *data,

	if (copy_from_user(buf, data, size)) {
		kfree(buf);
		dev_dbg(stm.dev, "%s: copy_from_user failed\n", __func__);
		dev_dbg(drvdata->dev, "%s: copy_from_user failed\n", __func__);
		return -EFAULT;
	}

@@ -400,7 +399,7 @@ static struct miscdevice stm_misc = {
static ssize_t stm_show_enabled(struct device *dev,
				struct device_attribute *attr, char *buf)
{
	unsigned long val = stm.enabled;
	unsigned long val = drvdata->enabled;
	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}

@@ -429,7 +428,7 @@ static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, stm_show_enabled,
static ssize_t stm_show_entity(struct device *dev,
			       struct device_attribute *attr, char *buf)
{
	unsigned long val = stm.entity;
	unsigned long val = drvdata->entity;
	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}

@@ -442,7 +441,7 @@ static ssize_t stm_store_entity(struct device *dev,
	if (sscanf(buf, "%lx", &val) != 1)
		return -EINVAL;

	stm.entity = val;
	drvdata->entity = val;
	return size;
}
static DEVICE_ATTR(entity, S_IRUGO | S_IWUSR, stm_show_entity,
@@ -452,34 +451,34 @@ static int stm_sysfs_init(void)
{
	int ret;

	stm.kobj = kobject_create_and_add("stm", qdss_get_modulekobj());
	if (!stm.kobj) {
		dev_err(stm.dev, "failed to create STM sysfs kobject\n");
	drvdata->kobj = kobject_create_and_add("stm", qdss_get_modulekobj());
	if (!drvdata->kobj) {
		dev_err(drvdata->dev, "failed to create STM sysfs kobject\n");
		ret = -ENOMEM;
		goto err_create;
	}

	ret = sysfs_create_file(stm.kobj, &dev_attr_enabled.attr);
	ret = sysfs_create_file(drvdata->kobj, &dev_attr_enabled.attr);
	if (ret) {
		dev_err(stm.dev, "failed to create STM sysfs enabled attr\n");
		dev_err(drvdata->dev, "failed to create STM sysfs enabled attr\n");
		goto err_file;
	}

	if (sysfs_create_file(stm.kobj, &dev_attr_entity.attr))
		dev_err(stm.dev, "failed to create STM sysfs entity attr\n");
	if (sysfs_create_file(drvdata->kobj, &dev_attr_entity.attr))
		dev_err(drvdata->dev, "failed to create STM sysfs entity attr\n");

	return 0;
err_file:
	kobject_put(stm.kobj);
	kobject_put(drvdata->kobj);
err_create:
	return ret;
}

static void stm_sysfs_exit(void)
{
	sysfs_remove_file(stm.kobj, &dev_attr_entity.attr);
	sysfs_remove_file(stm.kobj, &dev_attr_enabled.attr);
	kobject_put(stm.kobj);
	sysfs_remove_file(drvdata->kobj, &dev_attr_entity.attr);
	sysfs_remove_file(drvdata->kobj, &dev_attr_enabled.attr);
	kobject_put(drvdata->kobj);
}

static int stm_probe(struct platform_device *pdev)
@@ -488,14 +487,20 @@ static int stm_probe(struct platform_device *pdev)
	struct resource *res;
	size_t res_size, bitmap_size;

	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
	if (!drvdata) {
		ret = -ENOMEM;
		goto err_kzalloc_drvdata;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		ret = -EINVAL;
		goto err_res0;
	}

	stm.base = ioremap_nocache(res->start, resource_size(res));
	if (!stm.base) {
	drvdata->base = ioremap_nocache(res->start, resource_size(res));
	if (!drvdata->base) {
		ret = -EINVAL;
		goto err_ioremap0;
	}
@@ -516,40 +521,42 @@ static int stm_probe(struct platform_device *pdev)
		bitmap_size = NR_STM_CHANNEL * sizeof(long);
	}

	stm.chs.bitmap = kzalloc(bitmap_size, GFP_KERNEL);
	if (!stm.chs.bitmap) {
	drvdata->chs.bitmap = kzalloc(bitmap_size, GFP_KERNEL);
	if (!drvdata->chs.bitmap) {
		ret = -ENOMEM;
		goto err_bitmap;
	}

	stm.chs.base = ioremap_nocache(res->start, res_size);
	if (!stm.chs.base) {
	drvdata->chs.base = ioremap_nocache(res->start, res_size);
	if (!drvdata->chs.base) {
		ret = -EINVAL;
		goto err_ioremap1;
	}

	stm.dev = &pdev->dev;
	drvdata->dev = &pdev->dev;

	ret = misc_register(&stm_misc);
	if (ret)
		goto err_misc;

	stm.src = qdss_get("msm_stm");
	if (IS_ERR(stm.src)) {
		ret = PTR_ERR(stm.src);
	drvdata->src = qdss_get("msm_stm");
	if (IS_ERR(drvdata->src)) {
		ret = PTR_ERR(drvdata->src);
		goto err_qdssget;
	}

	stm.clk = clk_get(stm.dev, "core_clk");
	if (IS_ERR(stm.clk)) {
		ret = PTR_ERR(stm.clk);
	drvdata->clk = clk_get(drvdata->dev, "core_clk");
	if (IS_ERR(drvdata->clk)) {
		ret = PTR_ERR(drvdata->clk);
		goto err_clk_get;
	}

	ret = clk_set_rate(stm.clk, CS_CLK_RATE_TRACE);
	ret = clk_set_rate(drvdata->clk, CS_CLK_RATE_TRACE);
	if (ret)
		goto err_clk_rate;

	drvdata->entity = OST_ENTITY_ALL;

	ret = stm_sysfs_init();
	if (ret)
		goto err_sysfs;
@@ -557,40 +564,44 @@ static int stm_probe(struct platform_device *pdev)
	if (stm_boot_enable)
		stm_enable();

	dev_info(stm.dev, "STM initialized\n");
	dev_info(drvdata->dev, "STM initialized\n");
	return 0;

err_sysfs:
err_clk_rate:
	clk_put(stm.clk);
	clk_put(drvdata->clk);
err_clk_get:
	qdss_put(stm.src);
	qdss_put(drvdata->src);
err_qdssget:
	misc_deregister(&stm_misc);
err_misc:
	iounmap(stm.chs.base);
	iounmap(drvdata->chs.base);
err_ioremap1:
	kfree(stm.chs.bitmap);
	kfree(drvdata->chs.bitmap);
err_bitmap:
err_res1:
	iounmap(stm.base);
	iounmap(drvdata->base);
err_ioremap0:
err_res0:
	dev_err(stm.dev, "STM init failed\n");
	kfree(drvdata);
err_kzalloc_drvdata:

	dev_err(drvdata->dev, "STM init failed\n");
	return ret;
}

static int stm_remove(struct platform_device *pdev)
{
	if (stm.enabled)
	if (drvdata->enabled)
		stm_disable();
	stm_sysfs_exit();
	clk_put(stm.clk);
	qdss_put(stm.src);
	clk_put(drvdata->clk);
	qdss_put(drvdata->src);
	misc_deregister(&stm_misc);
	iounmap(stm.chs.base);
	kfree(stm.chs.bitmap);
	iounmap(stm.base);
	iounmap(drvdata->chs.base);
	kfree(drvdata->chs.bitmap);
	iounmap(drvdata->base);
	kfree(drvdata);

	return 0;
}
+34 −24
Original line number Diff line number Diff line
@@ -17,13 +17,14 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/cs.h>

#include "cs-priv.h"

#define tpiu_writel(tpiu, val, off)	__raw_writel((val), tpiu.base + off)
#define tpiu_readl(tpiu, off)		__raw_readl(tpiu.base + off)
#define tpiu_writel(drvdata, val, off)	__raw_writel((val), drvdata->base + off)
#define tpiu_readl(drvdata, off)	__raw_readl(drvdata->base + off)

#define TPIU_SUPP_PORTSZ				(0x000)
#define TPIU_CURR_PORTSZ				(0x004)
@@ -49,29 +50,29 @@
#define TPIU_LOCK()							\
do {									\
	mb();								\
	tpiu_writel(tpiu, 0x0, CS_LAR);					\
	tpiu_writel(drvdata, 0x0, CS_LAR);				\
} while (0)
#define TPIU_UNLOCK()							\
do {									\
	tpiu_writel(tpiu, CS_UNLOCK_MAGIC, CS_LAR);			\
	tpiu_writel(drvdata, CS_UNLOCK_MAGIC, CS_LAR);			\
	mb();								\
} while (0)

struct tpiu_ctx {
struct tpiu_drvdata {
	void __iomem	*base;
	bool		enabled;
	struct device	*dev;
	struct clk	*clk;
};

static struct tpiu_ctx tpiu;
static struct tpiu_drvdata *drvdata;

static void __tpiu_disable(void)
{
	TPIU_UNLOCK();

	tpiu_writel(tpiu, 0x3000, TPIU_FFCR);
	tpiu_writel(tpiu, 0x3040, TPIU_FFCR);
	tpiu_writel(drvdata, 0x3000, TPIU_FFCR);
	tpiu_writel(drvdata, 0x3040, TPIU_FFCR);

	TPIU_LOCK();
}
@@ -79,8 +80,8 @@ static void __tpiu_disable(void)
void tpiu_disable(void)
{
	__tpiu_disable();
	tpiu.enabled = false;
	dev_info(tpiu.dev, "TPIU disabled\n");
	drvdata->enabled = false;
	dev_info(drvdata->dev, "TPIU disabled\n");
}

static int tpiu_probe(struct platform_device *pdev)
@@ -88,49 +89,58 @@ static int tpiu_probe(struct platform_device *pdev)
	int ret;
	struct resource *res;

	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
	if (!drvdata) {
		ret = -ENOMEM;
		goto err_kzalloc_drvdata;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		ret = -EINVAL;
		goto err_res;
	}

	tpiu.base = ioremap_nocache(res->start, resource_size(res));
	if (!tpiu.base) {
	drvdata->base = ioremap_nocache(res->start, resource_size(res));
	if (!drvdata->base) {
		ret = -EINVAL;
		goto err_ioremap;
	}

	tpiu.dev = &pdev->dev;
	drvdata->dev = &pdev->dev;

	tpiu.clk = clk_get(tpiu.dev, "core_clk");
	if (IS_ERR(tpiu.clk)) {
		ret = PTR_ERR(tpiu.clk);
	drvdata->clk = clk_get(drvdata->dev, "core_clk");
	if (IS_ERR(drvdata->clk)) {
		ret = PTR_ERR(drvdata->clk);
		goto err_clk_get;
	}

	ret = clk_set_rate(tpiu.clk, CS_CLK_RATE_TRACE);
	ret = clk_set_rate(drvdata->clk, CS_CLK_RATE_TRACE);
	if (ret)
		goto err_clk_rate;

	dev_info(tpiu.dev, "TPIU initialized\n");
	dev_info(drvdata->dev, "TPIU initialized\n");
	return 0;

err_clk_rate:
	clk_put(tpiu.clk);
	clk_put(drvdata->clk);
err_clk_get:
	iounmap(tpiu.base);
	iounmap(drvdata->base);
err_ioremap:
err_res:
	dev_err(tpiu.dev, "TPIU init failed\n");
	kfree(drvdata);
err_kzalloc_drvdata:
	dev_err(drvdata->dev, "TPIU init failed\n");
	return ret;
}

static int tpiu_remove(struct platform_device *pdev)
{
	if (tpiu.enabled)
	if (drvdata->enabled)
		tpiu_disable();
	clk_put(tpiu.clk);
	iounmap(tpiu.base);
	clk_put(drvdata->clk);
	iounmap(drvdata->base);
	kfree(drvdata);

	return 0;
}