Unverified Commit b81cf416 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!2620 coresight: etm4x: Migrate ACPI AMBA devices to platform drive

Merge Pull Request from: @ci-robot 
 
PR sync from: Junhao He <hejunhao3@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/NDURFIOYEZDZJJRMECJM53R2YVSDVE3R/ 
CoreSight ETM4x devices could be accessed either via MMIO (handled via
amba_driver) or CPU system instructions (handled via platform driver). But
this has the following issues :

  - Each new CPU comes up with its own PID and thus we need to keep on
    adding the "known" PIDs to get it working with AMBA driver. While
    the ETM4 architecture (and CoreSight architecture) defines way to
    identify a device as ETM4. Thus older kernels  won't be able to
    "discover" a newer CPU, unless we add the PIDs.

  - With ACPI, the ETM4x devices have the same HID to identify the device
    different drivers (both AMBA based driver and platform driver) would
    hook into the "HID" and could conflict. e.g., if AMBA driver gets
    hold of a non-MMIO device, the probe fails. If we have single driver
    hooked into the given "HID", we could handle them seamlessly,

  - CoreSight is heavily dependent on the runtime power management. With
    ACPI, amba_driver doesn't get us anywhere with handling the power
    and thus one need to always turn the power ON to use them. Moving to
    platform driver gives us the power management for free.

Due to all of the above, we are moving ACPI MMIO based etm4x devices to be
supported via tha platform driver. The series makes the existing platform
AMBA driver would still continue to support DT based etm4x MMIO devices.
Although some problems still remain, such as manually adding PIDs for all
new AMBA DT based devices.


Anshuman Khandual (5):
  coresight: etm4x: Allocate and device assign 'struct etmv4_drvdata'
    earlier
  coresight: etm4x: Drop iomem 'base' argument from etm4_probe()
  coresight: etm4x: Drop pid argument from etm4_probe()
  coresight: etm4x: Change etm4_platform_driver driver for MMIO devices
  coresight: etm4x: Ensure valid drvdata and clock before clk_put()

Junhao He (1):
  Revert "coresight: ete: Add acpi match id for Hip09"

Suzuki K Poulose (2):
  coresight: platform: acpi: Ignore the absence of graph
  coresight: etm4x: Add ACPI support in platform driver


-- 
2.33.0
 
https://gitee.com/openeuler/kernel/issues/I89TNS 
 
Link:https://gitee.com/openeuler/kernel/pulls/2620

 

Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents 37a2ee54 2e480726
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@

static const struct acpi_device_id amba_id_list[] = {
	{"ARMH0061", 0}, /* PL061 GPIO Device */
	{"ARMHC500", 0}, /* ARM CoreSight ETM4x */
	{"ARMHC501", 0}, /* ARM CoreSight ETR */
	{"ARMHC502", 0}, /* ARM CoreSight STM */
	{"ARMHC503", 0}, /* ARM CoreSight Debug */
+94 −25
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
 */

#include <linux/acpi.h>
#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/moduleparam.h>
@@ -30,6 +31,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/clk/clk-conf.h>

#include <asm/barrier.h>
#include <asm/sections.h>
@@ -358,14 +360,22 @@ static void etm4_disable_arch_specific(struct etmv4_drvdata *drvdata)
}

static void etm4_check_arch_features(struct etmv4_drvdata *drvdata,
				      unsigned int id)
				     struct csdev_access *csa)
{
	if (etm4_hisi_match_pid(id)) {
	/*
	 * TRCPIDR* registers are not required for ETMs with system
	 * instructions. They must be identified by the MIDR+REVIDRs.
	 * Skip the TRCPID checks for now.
	 */
	if (!csa->io_mem)
		return;

	if (etm4_hisi_match_pid(coresight_get_pid(csa))) {
		set_bit(ETM4_IMPDEF_HISI_CORE_COMMIT, drvdata->arch_features);
		set_bit(ETM4_IMPDEF_HISI_SET_AUXCTRLR, drvdata->arch_features);
	}

	if (etm4_hisi_hip09_match_pid(id))
	if (etm4_hisi_hip09_match_pid(coresight_get_pid(csa)))
		set_bit(ETM4_IMPDEF_HISI_SET_AUXCTRLR, drvdata->arch_features);
}
#else
@@ -381,7 +391,7 @@ static void etm4_disable_arch_specific(struct etmv4_drvdata *drvdata)
}

static void etm4_check_arch_features(struct etmv4_drvdata *drvdata,
				     unsigned int id)
				     struct csdev_access *csa)
{
}
#endif /* CONFIG_ETM4X_IMPDEF_FEATURE */
@@ -963,12 +973,22 @@ static bool etm4_init_sysreg_access(struct etmv4_drvdata *drvdata,
	return true;
}

static bool is_devtype_cpu_trace(void __iomem *base)
{
	u32 devtype = readl(base + TRCDEVTYPE);

	return (devtype == CS_DEVTYPE_PE_TRACE);
}

static bool etm4_init_iomem_access(struct etmv4_drvdata *drvdata,
				   struct csdev_access *csa)
{
	u32 devarch = readl_relaxed(drvdata->base + TRCDEVARCH);
	u32 idr1 = readl_relaxed(drvdata->base + TRCIDR1);

	if (!is_coresight_device(drvdata->base) || !is_devtype_cpu_trace(drvdata->base))
		return false;

	/*
	 * All ETMs must implement TRCDEVARCH to indicate that
	 * the component is an ETMv4. To support any broken
@@ -1911,22 +1931,19 @@ static void etm4_pm_clear(void)
	}
}

static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)
static int etm4_probe(struct device *dev)
{
	int ret;
	struct coresight_platform_data *pdata = NULL;
	struct etmv4_drvdata *drvdata;
	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
	struct coresight_desc desc = { 0 };
	struct etm4_init_arg init_arg = { 0 };
	u8 major, minor;
	char *type_name;

	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
	if (!drvdata)
	if (WARN_ON(!drvdata))
		return -ENOMEM;

	dev_set_drvdata(dev, drvdata);

	if (pm_save_enable == PARAM_PM_SAVE_FIRMWARE)
		pm_save_enable = coresight_loses_context_with_cpu(dev) ?
			       PARAM_PM_SAVE_SELF_HOSTED : PARAM_PM_SAVE_NEVER;
@@ -1938,8 +1955,6 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)
			return -ENOMEM;
	}

	drvdata->base = base;

	spin_lock_init(&drvdata->spinlock);

	drvdata->cpu = coresight_get_cpu(dev);
@@ -2012,13 +2027,14 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)
		drvdata->boot_enable = true;
	}

	etm4_check_arch_features(drvdata, etm_pid);
	etm4_check_arch_features(drvdata, &desc.access);

	return 0;
}

static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id)
{
	struct etmv4_drvdata *drvdata;
	void __iomem *base;
	struct device *dev = &adev->dev;
	struct resource *res = &adev->res;
@@ -2029,7 +2045,13 @@ static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id)
	if (IS_ERR(base))
		return PTR_ERR(base);

	ret = etm4_probe(dev, base, id->id);
	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
	if (!drvdata)
		return -ENOMEM;

	drvdata->base = base;
	dev_set_drvdata(dev, drvdata);
	ret = etm4_probe(dev);
	if (!ret)
		pm_runtime_put(&adev->dev);

@@ -2038,18 +2060,32 @@ static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id)

static int etm4_probe_platform_dev(struct platform_device *pdev)
{
	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	struct etmv4_drvdata *drvdata;
	int ret;

	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
	if (!drvdata)
		return -ENOMEM;

	drvdata->pclk = coresight_get_enable_apb_pclk(&pdev->dev);
	if (IS_ERR(drvdata->pclk))
		return -ENODEV;

	if (res) {
		drvdata->base = devm_ioremap_resource(&pdev->dev, res);
		if (IS_ERR(drvdata->base)) {
			clk_put(drvdata->pclk);
			return PTR_ERR(drvdata->base);
		}
	}

	dev_set_drvdata(&pdev->dev, drvdata);
	pm_runtime_get_noresume(&pdev->dev);
	pm_runtime_set_active(&pdev->dev);
	pm_runtime_enable(&pdev->dev);

	/*
	 * System register based devices could match the
	 * HW by reading appropriate registers on the HW
	 * and thus we could skip the PID.
	 */
	ret = etm4_probe(&pdev->dev, NULL, 0);
	ret = etm4_probe(&pdev->dev);

	pm_runtime_put(&pdev->dev);
	return ret;
@@ -2060,7 +2096,7 @@ static struct amba_cs_uci_id uci_id_etm4[] = {
		/*  ETMv4 UCI data */
		.devarch	= ETM_DEVARCH_ETMv4x_ARCH,
		.devarch_mask	= ETM_DEVARCH_ID_MASK,
		.devtype	= 0x00000013,
		.devtype	= CS_DEVTYPE_PE_TRACE,
	}
};

@@ -2111,6 +2147,10 @@ static int __exit etm4_remove_platform_dev(struct platform_device *pdev)
	if (drvdata)
		ret = etm4_remove_dev(drvdata);
	pm_runtime_disable(&pdev->dev);

	if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
		clk_put(drvdata->pclk);

	return ret;
}

@@ -2151,17 +2191,45 @@ static struct amba_driver etm4x_amba_driver = {
	.id_table	= etm4_ids,
};

#ifdef CONFIG_PM
static int etm4_runtime_suspend(struct device *dev)
{
	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);

	if (drvdata->pclk && !IS_ERR(drvdata->pclk))
		clk_disable_unprepare(drvdata->pclk);

	return 0;
}

static int etm4_runtime_resume(struct device *dev)
{
	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);

	if (drvdata->pclk && !IS_ERR(drvdata->pclk))
		clk_prepare_enable(drvdata->pclk);

	return 0;
}
#endif

static const struct dev_pm_ops etm4_dev_pm_ops = {
	SET_RUNTIME_PM_OPS(etm4_runtime_suspend, etm4_runtime_resume, NULL)
};

static const struct of_device_id etm4_sysreg_match[] = {
	{ .compatible	= "arm,coresight-etm4x-sysreg" },
	{ .compatible	= "arm,embedded-trace-extension" },
	{}
};

static const struct acpi_device_id static_ete_ids[] = {
	{"HISI0461", 0},
#ifdef CONFIG_ACPI
static const struct acpi_device_id etm4x_acpi_ids[] = {
	{"ARMHC500", 0}, /* ARM CoreSight ETM4x */
	{}
};
MODULE_DEVICE_TABLE(acpi, static_ete_ids);
MODULE_DEVICE_TABLE(acpi, etm4x_acpi_ids);
#endif

static struct platform_driver etm4_platform_driver = {
	.probe		= etm4_probe_platform_dev,
@@ -2169,8 +2237,9 @@ static struct platform_driver etm4_platform_driver = {
	.driver			= {
		.name			= "coresight-etm4x",
		.of_match_table		= etm4_sysreg_match,
		.acpi_match_table       = static_ete_ids,
		.acpi_match_table       = ACPI_PTR(etm4x_acpi_ids),
		.suppress_bind_attrs	= true,
		.pm                     = &etm4_dev_pm_ops,
	},
};

+4 −0
Original line number Diff line number Diff line
@@ -597,6 +597,8 @@
#define ETM_DEVARCH_ETE_ARCH						\
	(ETM_DEVARCH_ARCHITECT_ARM | ETM_DEVARCH_ARCHID_ETE | ETM_DEVARCH_PRESENT)

#define CS_DEVTYPE_PE_TRACE		0x00000013

#define TRCSTATR_IDLE_BIT		0
#define TRCSTATR_PMSTABLE_BIT		1
#define ETM_DEFAULT_ADDR_COMP		0
@@ -844,6 +846,7 @@ struct etmv4_save_state {

/**
 * struct etm4_drvdata - specifics associated to an ETM component
 * @pclk        APB clock if present, otherwise NULL
 * @base:       Memory mapped base address for this component.
 * @csdev:      Component vitals needed by the framework.
 * @spinlock:   Only one at a time pls.
@@ -909,6 +912,7 @@ struct etmv4_save_state {
 * @arch_features: Bitmap of arch features of etmv4 devices.
 */
struct etmv4_drvdata {
	struct clk			*pclk;
	void __iomem			*base;
	struct coresight_device		*csdev;
	spinlock_t			spinlock;
+5 −1
Original line number Diff line number Diff line
@@ -692,8 +692,12 @@ static int acpi_coresight_parse_graph(struct acpi_device *adev,

	pdata->nr_inport = pdata->nr_outport = 0;
	graph = acpi_get_coresight_graph(adev);
	/*
	 * There are no graph connections, which is fine for some components.
	 * e.g., ETE
	 */
	if (!graph)
		return -ENOENT;
		return 0;

	nlinks = graph->package.elements[2].integer.value;
	if (!nlinks)
+59 −0
Original line number Diff line number Diff line
@@ -6,6 +6,8 @@
#ifndef _LINUX_CORESIGHT_H
#define _LINUX_CORESIGHT_H

#include <linux/amba/bus.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/perf_event.h>
@@ -370,6 +372,63 @@ static inline u32 csdev_access_relaxed_read32(struct csdev_access *csa,
	return csa->read(offset, true, false);
}

#define CORESIGHT_CIDRn(i)	(0xFF0 + ((i) * 4))

static inline u32 coresight_get_cid(void __iomem *base)
{
	u32 i, cid = 0;

	for (i = 0; i < 4; i++)
		cid |= readl(base + CORESIGHT_CIDRn(i)) << (i * 8);

	return cid;
}

static inline bool is_coresight_device(void __iomem *base)
{
	u32 cid = coresight_get_cid(base);

	return cid == CORESIGHT_CID;
}

/*
 * Attempt to find and enable "APB clock" for the given device
 *
 * Returns:
 *
 * clk   - Clock is found and enabled
 * NULL  - clock is not found
 * ERROR - Clock is found but failed to enable
 */
static inline struct clk *coresight_get_enable_apb_pclk(struct device *dev)
{
	struct clk *pclk;
	int ret;

	pclk = clk_get(dev, "apb_pclk");
	if (IS_ERR(pclk))
		return NULL;

	ret = clk_prepare_enable(pclk);
	if (ret) {
		clk_put(pclk);
		return ERR_PTR(ret);
	}
	return pclk;
}

#define CORESIGHT_PIDRn(i)	(0xFE0 + ((i) * 4))

static inline u32 coresight_get_pid(struct csdev_access *csa)
{
	u32 i, pid = 0;

	for (i = 0; i < 4; i++)
		pid |= csdev_access_relaxed_read32(csa, CORESIGHT_PIDRn(i)) << (i * 8);

	return pid;
}

static inline u64 csdev_access_relaxed_read_pair(struct csdev_access *csa,
						 u32 lo_offset, u32 hi_offset)
{