Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
  1/*
  2 * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
  3 *
  4 * This program is free software; you can redistribute it and/or modify
  5 * it under the terms of the GNU General Public License version 2 and
  6 * only version 2 as published by the Free Software Foundation.
  7 *
  8 * This program is distributed in the hope that it will be useful,
  9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 11 * GNU General Public License for more details.
 12 */
 13
 14#include <linux/amba/bus.h>
 15#include <linux/clk.h>
 16#include <linux/coresight.h>
 17#include <linux/device.h>
 18#include <linux/err.h>
 19#include <linux/init.h>
 20#include <linux/io.h>
 21#include <linux/kernel.h>
 22#include <linux/of.h>
 23#include <linux/pm_runtime.h>
 24#include <linux/slab.h>
 25
 26#include "coresight-priv.h"
 27
 28#define REPLICATOR_IDFILTER0		0x000
 29#define REPLICATOR_IDFILTER1		0x004
 30
 31/**
 32 * struct replicator_state - specifics associated to a replicator component
 33 * @base:	memory mapped base address for this component.
 34 * @dev:	the device entity associated with this component
 35 * @atclk:	optional clock for the core parts of the replicator.
 36 * @csdev:	component vitals needed by the framework
 37 */
 38struct replicator_state {
 39	void __iomem		*base;
 40	struct device		*dev;
 41	struct clk		*atclk;
 42	struct coresight_device	*csdev;
 43};
 44
 45static int replicator_enable(struct coresight_device *csdev, int inport,
 46			      int outport)
 47{
 48	struct replicator_state *drvdata = dev_get_drvdata(csdev->dev.parent);
 49
 50	CS_UNLOCK(drvdata->base);
 51
 52	/*
 53	 * Ensure that the other port is disabled
 54	 * 0x00 - passing through the replicator unimpeded
 55	 * 0xff - disable (or impede) the flow of ATB data
 56	 */
 57	if (outport == 0) {
 58		writel_relaxed(0x00, drvdata->base + REPLICATOR_IDFILTER0);
 59		writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER1);
 60	} else {
 61		writel_relaxed(0x00, drvdata->base + REPLICATOR_IDFILTER1);
 62		writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER0);
 63	}
 64
 65	CS_LOCK(drvdata->base);
 66
 67	dev_info(drvdata->dev, "REPLICATOR enabled\n");
 68	return 0;
 69}
 70
 71static void replicator_disable(struct coresight_device *csdev, int inport,
 72				int outport)
 73{
 74	struct replicator_state *drvdata = dev_get_drvdata(csdev->dev.parent);
 75
 76	CS_UNLOCK(drvdata->base);
 77
 78	/* disable the flow of ATB data through port */
 79	if (outport == 0)
 80		writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER0);
 81	else
 82		writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER1);
 83
 84	CS_LOCK(drvdata->base);
 85
 86	dev_info(drvdata->dev, "REPLICATOR disabled\n");
 87}
 88
 89static const struct coresight_ops_link replicator_link_ops = {
 90	.enable		= replicator_enable,
 91	.disable	= replicator_disable,
 92};
 93
 94static const struct coresight_ops replicator_cs_ops = {
 95	.link_ops	= &replicator_link_ops,
 96};
 97
 98#define coresight_replicator_reg(name, offset) \
 99	coresight_simple_reg32(struct replicator_state, name, offset)
100
101coresight_replicator_reg(idfilter0, REPLICATOR_IDFILTER0);
102coresight_replicator_reg(idfilter1, REPLICATOR_IDFILTER1);
103
104static struct attribute *replicator_mgmt_attrs[] = {
105	&dev_attr_idfilter0.attr,
106	&dev_attr_idfilter1.attr,
107	NULL,
108};
109
110static const struct attribute_group replicator_mgmt_group = {
111	.attrs = replicator_mgmt_attrs,
112	.name = "mgmt",
113};
114
115static const struct attribute_group *replicator_groups[] = {
116	&replicator_mgmt_group,
117	NULL,
118};
119
120static int replicator_probe(struct amba_device *adev, const struct amba_id *id)
121{
122	int ret;
123	struct device *dev = &adev->dev;
124	struct resource *res = &adev->res;
125	struct coresight_platform_data *pdata = NULL;
126	struct replicator_state *drvdata;
127	struct coresight_desc desc = { 0 };
128	struct device_node *np = adev->dev.of_node;
129	void __iomem *base;
130
131	if (np) {
132		pdata = of_get_coresight_platform_data(dev, np);
133		if (IS_ERR(pdata))
134			return PTR_ERR(pdata);
135		adev->dev.platform_data = pdata;
136	}
137
138	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
139	if (!drvdata)
140		return -ENOMEM;
141
142	drvdata->dev = &adev->dev;
143	drvdata->atclk = devm_clk_get(&adev->dev, "atclk"); /* optional */
144	if (!IS_ERR(drvdata->atclk)) {
145		ret = clk_prepare_enable(drvdata->atclk);
146		if (ret)
147			return ret;
148	}
149
150	/* Validity for the resource is already checked by the AMBA core */
151	base = devm_ioremap_resource(dev, res);
152	if (IS_ERR(base))
153		return PTR_ERR(base);
154
155	drvdata->base = base;
156	dev_set_drvdata(dev, drvdata);
157	pm_runtime_put(&adev->dev);
158
159	desc.type = CORESIGHT_DEV_TYPE_LINK;
160	desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT;
161	desc.ops = &replicator_cs_ops;
162	desc.pdata = adev->dev.platform_data;
163	desc.dev = &adev->dev;
164	desc.groups = replicator_groups;
165	drvdata->csdev = coresight_register(&desc);
166
167	return PTR_ERR_OR_ZERO(drvdata->csdev);
168}
169
170#ifdef CONFIG_PM
171static int replicator_runtime_suspend(struct device *dev)
172{
173	struct replicator_state *drvdata = dev_get_drvdata(dev);
174
175	if (drvdata && !IS_ERR(drvdata->atclk))
176		clk_disable_unprepare(drvdata->atclk);
177
178	return 0;
179}
180
181static int replicator_runtime_resume(struct device *dev)
182{
183	struct replicator_state *drvdata = dev_get_drvdata(dev);
184
185	if (drvdata && !IS_ERR(drvdata->atclk))
186		clk_prepare_enable(drvdata->atclk);
187
188	return 0;
189}
190#endif
191
192static const struct dev_pm_ops replicator_dev_pm_ops = {
193	SET_RUNTIME_PM_OPS(replicator_runtime_suspend,
194			   replicator_runtime_resume,
195			   NULL)
196};
197
198static const struct amba_id replicator_ids[] = {
199	{
200		.id     = 0x000bb909,
201		.mask   = 0x000fffff,
202	},
203	{
204		/* Coresight SoC-600 */
205		.id     = 0x000bb9ec,
206		.mask   = 0x000fffff,
207	},
208	{ 0, 0 },
209};
210
211static struct amba_driver replicator_driver = {
212	.drv = {
213		.name	= "coresight-dynamic-replicator",
214		.pm	= &replicator_dev_pm_ops,
215		.suppress_bind_attrs = true,
216	},
217	.probe		= replicator_probe,
218	.id_table	= replicator_ids,
219};
220builtin_amba_driver(replicator_driver);