Commit 8f3ce74c authored by Sai Prakash Ranjan's avatar Sai Prakash Ranjan Committed by Greg Kroah-Hartman
Browse files

coresight: replicator: Reset replicator if context is lost



On some QCOM SoCs, replicators in Always-On domain loses its
context as soon as the clock is disabled. Currently as a part
of pm_runtime workqueue, clock is disabled after the replicator
is initialized by amba_pm_runtime_suspend assuming that context
is not lost which is not true for replicators with such
limitations. So add a new property "qcom,replicator-loses-context"
to identify such replicators and reset them.

Suggested-by: default avatarMike Leach <mike.leach@linaro.org>
Reviewed-by: default avatarMike Leach <mike.leach@linaro.org>
Signed-off-by: default avatarSai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
Signed-off-by: default avatarMathieu Poirier <mathieu.poirier@linaro.org>
Link: https://lore.kernel.org/r/20200716175746.3338735-6-mathieu.poirier@linaro.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 7f1a1c2c
Loading
Loading
Loading
Loading
+38 −17
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/clk.h>
#include <linux/of.h>
#include <linux/coresight.h>
@@ -32,12 +33,14 @@ DEFINE_CORESIGHT_DEVLIST(replicator_devs, "replicator");
 * @atclk:	optional clock for the core parts of the replicator.
 * @csdev:	component vitals needed by the framework
 * @spinlock:	serialize enable/disable operations.
 * @check_idfilter_val: check if the context is lost upon clock removal.
 */
struct replicator_drvdata {
	void __iomem		*base;
	struct clk		*atclk;
	struct coresight_device	*csdev;
	spinlock_t		spinlock;
	bool			check_idfilter_val;
};

static void dynamic_replicator_reset(struct replicator_drvdata *drvdata)
@@ -66,29 +69,43 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata,
				     int inport, int outport)
{
	int rc = 0;
	u32 reg;
	u32 id0val, id1val;

	CS_UNLOCK(drvdata->base);

	id0val = readl_relaxed(drvdata->base + REPLICATOR_IDFILTER0);
	id1val = readl_relaxed(drvdata->base + REPLICATOR_IDFILTER1);

	/*
	 * Some replicator designs lose context when AMBA clocks are removed,
	 * so have a check for this.
	 */
	if (drvdata->check_idfilter_val && id0val == 0x0 && id1val == 0x0)
		id0val = id1val = 0xff;

	if (id0val == 0xff && id1val == 0xff)
		rc = coresight_claim_device_unlocked(drvdata->base);

	if (!rc) {
		switch (outport) {
		case 0:
		reg = REPLICATOR_IDFILTER0;
			id0val = 0x0;
			break;
		case 1:
		reg = REPLICATOR_IDFILTER1;
			id1val = 0x0;
			break;
		default:
			WARN_ON(1);
		return -EINVAL;
			rc = -EINVAL;
		}
	}

	CS_UNLOCK(drvdata->base);

	if ((readl_relaxed(drvdata->base + REPLICATOR_IDFILTER0) == 0xff) &&
	    (readl_relaxed(drvdata->base + REPLICATOR_IDFILTER1) == 0xff))
		rc = coresight_claim_device_unlocked(drvdata->base);

	/* Ensure that the outport is enabled. */
	if (!rc)
		writel_relaxed(0x00, drvdata->base + reg);
	if (!rc) {
		writel_relaxed(id0val, drvdata->base + REPLICATOR_IDFILTER0);
		writel_relaxed(id1val, drvdata->base + REPLICATOR_IDFILTER1);
	}

	CS_LOCK(drvdata->base);

	return rc;
@@ -239,6 +256,10 @@ static int replicator_probe(struct device *dev, struct resource *res)
		desc.groups = replicator_groups;
	}

	if (fwnode_property_present(dev_fwnode(dev),
				    "qcom,replicator-loses-context"))
		drvdata->check_idfilter_val = true;

	dev_set_drvdata(dev, drvdata);

	pdata = coresight_get_platform_data(dev);