brintos

brintos / linux-shallow public Read only

0
0
Text · 7.7 KiB · b048e14 Raw
335 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.4 *5 * Description: CoreSight Trace Port Interface Unit driver6 */7 8#include <linux/acpi.h>9#include <linux/amba/bus.h>10#include <linux/atomic.h>11#include <linux/clk.h>12#include <linux/coresight.h>13#include <linux/device.h>14#include <linux/err.h>15#include <linux/init.h>16#include <linux/io.h>17#include <linux/kernel.h>18#include <linux/platform_device.h>19#include <linux/pm_runtime.h>20#include <linux/slab.h>21 22#include "coresight-priv.h"23 24#define TPIU_SUPP_PORTSZ	0x00025#define TPIU_CURR_PORTSZ	0x00426#define TPIU_SUPP_TRIGMODES	0x10027#define TPIU_TRIG_CNTRVAL	0x10428#define TPIU_TRIG_MULT		0x10829#define TPIU_SUPP_TESTPATM	0x20030#define TPIU_CURR_TESTPATM	0x20431#define TPIU_TEST_PATREPCNTR	0x20832#define TPIU_FFSR		0x30033#define TPIU_FFCR		0x30434#define TPIU_FSYNC_CNTR		0x30835#define TPIU_EXTCTL_INPORT	0x40036#define TPIU_EXTCTL_OUTPORT	0x40437#define TPIU_ITTRFLINACK	0xee438#define TPIU_ITTRFLIN		0xee839#define TPIU_ITATBDATA0		0xeec40#define TPIU_ITATBCTR2		0xef041#define TPIU_ITATBCTR1		0xef442#define TPIU_ITATBCTR0		0xef843 44/** register definition **/45/* FFSR - 0x300 */46#define FFSR_FT_STOPPED_BIT	147/* FFCR - 0x304 */48#define FFCR_FON_MAN_BIT	649#define FFCR_FON_MAN		BIT(6)50#define FFCR_STOP_FI		BIT(12)51 52DEFINE_CORESIGHT_DEVLIST(tpiu_devs, "tpiu");53 54/*55 * @base:	memory mapped base address for this component.56 * @atclk:	optional clock for the core parts of the TPIU.57 * @pclk:	APB clock if present, otherwise NULL58 * @csdev:	component vitals needed by the framework.59 */60struct tpiu_drvdata {61	void __iomem		*base;62	struct clk		*atclk;63	struct clk		*pclk;64	struct coresight_device	*csdev;65	spinlock_t		spinlock;66};67 68static void tpiu_enable_hw(struct csdev_access *csa)69{70	CS_UNLOCK(csa->base);71 72	/* TODO: fill this up */73 74	CS_LOCK(csa->base);75}76 77static int tpiu_enable(struct coresight_device *csdev, enum cs_mode mode,78		       void *__unused)79{80	struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);81 82	guard(spinlock)(&drvdata->spinlock);83	tpiu_enable_hw(&csdev->access);84	csdev->refcnt++;85	dev_dbg(&csdev->dev, "TPIU enabled\n");86	return 0;87}88 89static void tpiu_disable_hw(struct csdev_access *csa)90{91	CS_UNLOCK(csa->base);92 93	/* Clear formatter and stop on flush */94	csdev_access_relaxed_write32(csa, FFCR_STOP_FI, TPIU_FFCR);95	/* Generate manual flush */96	csdev_access_relaxed_write32(csa, FFCR_STOP_FI | FFCR_FON_MAN, TPIU_FFCR);97	/* Wait for flush to complete */98	coresight_timeout(csa, TPIU_FFCR, FFCR_FON_MAN_BIT, 0);99	/* Wait for formatter to stop */100	coresight_timeout(csa, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);101 102	CS_LOCK(csa->base);103}104 105static int tpiu_disable(struct coresight_device *csdev)106{107	struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);108 109	guard(spinlock)(&drvdata->spinlock);110	csdev->refcnt--;111	if (csdev->refcnt)112		return -EBUSY;113 114	tpiu_disable_hw(&csdev->access);115 116	dev_dbg(&csdev->dev, "TPIU disabled\n");117	return 0;118}119 120static const struct coresight_ops_sink tpiu_sink_ops = {121	.enable		= tpiu_enable,122	.disable	= tpiu_disable,123};124 125static const struct coresight_ops tpiu_cs_ops = {126	.sink_ops	= &tpiu_sink_ops,127};128 129static int __tpiu_probe(struct device *dev, struct resource *res)130{131	int ret;132	void __iomem *base;133	struct coresight_platform_data *pdata = NULL;134	struct tpiu_drvdata *drvdata;135	struct coresight_desc desc = { 0 };136 137	desc.name = coresight_alloc_device_name(&tpiu_devs, dev);138	if (!desc.name)139		return -ENOMEM;140 141	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);142	if (!drvdata)143		return -ENOMEM;144 145	spin_lock_init(&drvdata->spinlock);146 147	drvdata->atclk = devm_clk_get(dev, "atclk"); /* optional */148	if (!IS_ERR(drvdata->atclk)) {149		ret = clk_prepare_enable(drvdata->atclk);150		if (ret)151			return ret;152	}153 154	drvdata->pclk = coresight_get_enable_apb_pclk(dev);155	if (IS_ERR(drvdata->pclk))156		return -ENODEV;157	dev_set_drvdata(dev, drvdata);158 159	/* Validity for the resource is already checked by the AMBA core */160	base = devm_ioremap_resource(dev, res);161	if (IS_ERR(base))162		return PTR_ERR(base);163 164	drvdata->base = base;165	desc.access = CSDEV_ACCESS_IOMEM(base);166 167	/* Disable tpiu to support older devices */168	tpiu_disable_hw(&desc.access);169 170	pdata = coresight_get_platform_data(dev);171	if (IS_ERR(pdata))172		return PTR_ERR(pdata);173	dev->platform_data = pdata;174 175	desc.type = CORESIGHT_DEV_TYPE_SINK;176	desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_PORT;177	desc.ops = &tpiu_cs_ops;178	desc.pdata = pdata;179	desc.dev = dev;180	drvdata->csdev = coresight_register(&desc);181 182	if (!IS_ERR(drvdata->csdev))183		return 0;184 185	return PTR_ERR(drvdata->csdev);186}187 188static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)189{190	int ret;191 192	ret = __tpiu_probe(&adev->dev, &adev->res);193	if (!ret)194		pm_runtime_put(&adev->dev);195	return ret;196}197 198static void __tpiu_remove(struct device *dev)199{200	struct tpiu_drvdata *drvdata = dev_get_drvdata(dev);201 202	coresight_unregister(drvdata->csdev);203}204 205static void tpiu_remove(struct amba_device *adev)206{207	__tpiu_remove(&adev->dev);208}209 210#ifdef CONFIG_PM211static int tpiu_runtime_suspend(struct device *dev)212{213	struct tpiu_drvdata *drvdata = dev_get_drvdata(dev);214 215	if (drvdata && !IS_ERR(drvdata->atclk))216		clk_disable_unprepare(drvdata->atclk);217 218	if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))219		clk_disable_unprepare(drvdata->pclk);220	return 0;221}222 223static int tpiu_runtime_resume(struct device *dev)224{225	struct tpiu_drvdata *drvdata = dev_get_drvdata(dev);226 227	if (drvdata && !IS_ERR(drvdata->atclk))228		clk_prepare_enable(drvdata->atclk);229 230	if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))231		clk_prepare_enable(drvdata->pclk);232	return 0;233}234#endif235 236static const struct dev_pm_ops tpiu_dev_pm_ops = {237	SET_RUNTIME_PM_OPS(tpiu_runtime_suspend, tpiu_runtime_resume, NULL)238};239 240static const struct amba_id tpiu_ids[] = {241	{242		.id	= 0x000bb912,243		.mask	= 0x000fffff,244	},245	{246		.id	= 0x0004b912,247		.mask	= 0x0007ffff,248	},249	{250		/* Coresight SoC-600 */251		.id	= 0x000bb9e7,252		.mask	= 0x000fffff,253	},254	{ 0, 0, NULL },255};256 257MODULE_DEVICE_TABLE(amba, tpiu_ids);258 259static struct amba_driver tpiu_driver = {260	.drv = {261		.name	= "coresight-tpiu",262		.pm	= &tpiu_dev_pm_ops,263		.suppress_bind_attrs = true,264	},265	.probe		= tpiu_probe,266	.remove         = tpiu_remove,267	.id_table	= tpiu_ids,268};269 270static int tpiu_platform_probe(struct platform_device *pdev)271{272	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);273	int ret;274 275	pm_runtime_get_noresume(&pdev->dev);276	pm_runtime_set_active(&pdev->dev);277	pm_runtime_enable(&pdev->dev);278 279	ret = __tpiu_probe(&pdev->dev, res);280	pm_runtime_put(&pdev->dev);281	if (ret)282		pm_runtime_disable(&pdev->dev);283 284	return ret;285}286 287static void tpiu_platform_remove(struct platform_device *pdev)288{289	struct tpiu_drvdata *drvdata = dev_get_drvdata(&pdev->dev);290 291	if (WARN_ON(!drvdata))292		return;293 294	__tpiu_remove(&pdev->dev);295	pm_runtime_disable(&pdev->dev);296	if (!IS_ERR_OR_NULL(drvdata->pclk))297		clk_put(drvdata->pclk);298}299 300#ifdef CONFIG_ACPI301static const struct acpi_device_id tpiu_acpi_ids[] = {302	{"ARMHC979", 0, 0, 0}, /* ARM CoreSight TPIU */303	{}304};305MODULE_DEVICE_TABLE(acpi, tpiu_acpi_ids);306#endif307 308static struct platform_driver tpiu_platform_driver = {309	.probe	= tpiu_platform_probe,310	.remove_new = tpiu_platform_remove,311	.driver = {312		.name			= "coresight-tpiu-platform",313		.acpi_match_table	= ACPI_PTR(tpiu_acpi_ids),314		.suppress_bind_attrs	= true,315		.pm			= &tpiu_dev_pm_ops,316	},317};318 319static int __init tpiu_init(void)320{321	return coresight_init_driver("tpiu", &tpiu_driver, &tpiu_platform_driver);322}323 324static void __exit tpiu_exit(void)325{326	coresight_remove_driver(&tpiu_driver, &tpiu_platform_driver);327}328module_init(tpiu_init);329module_exit(tpiu_exit);330 331MODULE_AUTHOR("Pratik Patel <pratikp@codeaurora.org>");332MODULE_AUTHOR("Mathieu Poirier <mathieu.poirier@linaro.org>");333MODULE_DESCRIPTION("Arm CoreSight TPIU (Trace Port Interface Unit) driver");334MODULE_LICENSE("GPL v2");335