mirror of
https://github.com/torvalds/linux
synced 2024-09-06 18:01:05 +00:00
coresight: hwtracing subsystem updates for v6.10
CoreSight/hwtracing updates for the next release includes: - ACPI power management support for CoreSight legacy components, via migration from AMBA to platform device - Fixes for ETE register save/restore during CPU Idle. - ACPI support TMC for Scatter-Gather mode. - his_ptt driver update to set the parent device for PMU and documentation fixes - Qcomm Trace component DT binding fixes - Miscellaneous cleanups Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEuFy0byloRoXZHaWBxcXRZPKyBqEFAmYzcecACgkQxcXRZPKy BqEyrw//fsxpXrjt9Uz1QSmpEH+5eV//RQIO8vOOibihLrQYYMl8ZrwHp1n0lS0B Cj9P6MIRs8XztOBh5f0w57NoUOD9eJJ4/BdPRpixDPyZsm3acV/7JFMh1TIYQG6z ETlRGr5GRlLlx6VXkytMVfxRCtNlPR3PA3/fy5QR5BQ74ux+AlxuiX5krk6pEvak j8Vf35eNofqIDjNvr8ffY59kxDP+ULtiv+JWfAW+hzjjlQd+RxyamLUSJHr5Mh1N AqFjt+bqCVoT7MdtZoCrLX1b4gcgi1W/55Ph3ODdvy9vwErj2MpaNAW4829I5m1l dK5WmXFSQ/vb6UGj5laIu4ssZ0sMShu4jzatiGBBSo4FwAazSg2Lk3F6gNhXHBE2 iyrU+Pr8mRnxh59FDtnldCD1ww0cUPZOQz29aNwNy1x52nkeEMOg2KYx3sXy/Sbx TK5qJ7Fv6DOEZ/fWDPxvZjKM8IbsvJI2XTL7WyyCt3hOT+bcdzQIwnlS8q+EdBL/ zk/HAdb6/IA1vyg3kgmTCejC0EXwklME01UTs591HQ6U0iG+YxlklFFXLL9sw4Ij v6FVAbrtsgC8ov9UtmECqvjUlkZ5pwXkFU0php51R0MKvOWEU7vSxhtIjzvTumhu /lxyAQA+V112RWQS3nlxmUq3FWbqXIiFZSo1zvTavhxOtMVg06s= =yu6I -----END PGP SIGNATURE----- Merge tag 'coresight-next-v6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/coresight/linux into char-misc-next Suzuki writes: coresight: hwtracing subsystem updates for v6.10 CoreSight/hwtracing updates for the next release includes: - ACPI power management support for CoreSight legacy components, via migration from AMBA to platform device - Fixes for ETE register save/restore during CPU Idle. - ACPI support TMC for Scatter-Gather mode. - his_ptt driver update to set the parent device for PMU and documentation fixes - Qcomm Trace component DT binding fixes - Miscellaneous cleanups Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> * tag 'coresight-next-v6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/coresight/linux: (28 commits) hwtracing: hisi_ptt: Assign parent for event_source device Documentation: ABI + trace: hisi_ptt: update paths to bus/event_source coresight: tmc: Enable SG capability on ACPI based SoC-400 TMC ETR devices coresight: Docs/ABI/testing/sysfs-bus-coresight-devices: Fix spelling errors coresight: tpiu: Convert to platform remove callback returning void coresight: tmc: Convert to platform remove callback returning void coresight: stm: Convert to platform remove callback returning void coresight: debug: Convert to platform remove callback returning void coresight: catu: Convert to platform remove callback returning void coresight: Remove duplicate linux/amba/bus.h header coresight: stm: Remove duplicate linux/acpi.h header coresight: etm4x: Fix access to resource selector registers coresight: etm4x: Safe access for TRCQCLTR coresight: etm4x: Do not save/restore Data trace control registers coresight: etm4x: Do not hardcode IOMEM access for register restore coresight: debug: Move ACPI support from AMBA driver to platform driver coresight: stm: Move ACPI support from AMBA driver to platform driver coresight: tmc: Move ACPI support from AMBA driver to platform driver coresight: tpiu: Move ACPI support from AMBA driver to platform driver coresight: catu: Move ACPI support from AMBA driver to platform driver ...
This commit is contained in:
commit
d629cfcfed
|
@ -22,7 +22,7 @@ Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
|
|||
Description: (RW) Used in conjunction with @addr_idx. Specifies
|
||||
characteristics about the address comparator being configure,
|
||||
for example the access type, the kind of instruction to trace,
|
||||
processor contect ID to trigger on, etc. Individual fields in
|
||||
processor context ID to trigger on, etc. Individual fields in
|
||||
the access type register may vary on the version of the trace
|
||||
entity.
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ Date: August 2023
|
|||
KernelVersion: 6.7
|
||||
Contact: Anshuman Khandual <anshuman.khandual@arm.com>
|
||||
Description: (Read) Shows all supported Coresight TMC-ETR buffer modes available
|
||||
for the users to configure explicitly. This file is avaialble only
|
||||
for the users to configure explicitly. This file is available only
|
||||
for TMC ETR devices.
|
||||
|
||||
What: /sys/bus/coresight/devices/<memory_map>.tmc/buf_mode_preferred
|
||||
|
|
|
@ -244,7 +244,7 @@ KernelVersion 6.9
|
|||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||
Description:
|
||||
(RW) Read or write the status of timestamp upon all interface.
|
||||
Only value 0 and 1 can be written to this node. Set this node to 1 to requeset
|
||||
Only value 0 and 1 can be written to this node. Set this node to 1 to request
|
||||
timestamp to all trace packet.
|
||||
Accepts only one of the 2 values - 0 or 1.
|
||||
0 : Disable the timestamp of all trace packets.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
What: /sys/devices/hisi_ptt<sicl_id>_<core_id>/tune
|
||||
What: /sys/bus/event_source/devices/hisi_ptt<sicl_id>_<core_id>/tune
|
||||
Date: October 2022
|
||||
KernelVersion: 6.1
|
||||
Contact: Yicong Yang <yangyicong@hisilicon.com>
|
||||
|
@ -8,7 +8,7 @@ Description: This directory contains files for tuning the PCIe link
|
|||
|
||||
See Documentation/trace/hisi-ptt.rst for more information.
|
||||
|
||||
What: /sys/devices/hisi_ptt<sicl_id>_<core_id>/tune/qos_tx_cpl
|
||||
What: /sys/bus/event_source/devices/hisi_ptt<sicl_id>_<core_id>/tune/qos_tx_cpl
|
||||
Date: October 2022
|
||||
KernelVersion: 6.1
|
||||
Contact: Yicong Yang <yangyicong@hisilicon.com>
|
||||
|
@ -18,7 +18,7 @@ Description: (RW) Controls the weight of Tx completion TLPs, which influence
|
|||
will return an error, and out of range values will be converted
|
||||
to 2. The value indicates a probable level of the event.
|
||||
|
||||
What: /sys/devices/hisi_ptt<sicl_id>_<core_id>/tune/qos_tx_np
|
||||
What: /sys/bus/event_source/devices/hisi_ptt<sicl_id>_<core_id>/tune/qos_tx_np
|
||||
Date: October 2022
|
||||
KernelVersion: 6.1
|
||||
Contact: Yicong Yang <yangyicong@hisilicon.com>
|
||||
|
@ -28,7 +28,7 @@ Description: (RW) Controls the weight of Tx non-posted TLPs, which influence
|
|||
will return an error, and out of range values will be converted
|
||||
to 2. The value indicates a probable level of the event.
|
||||
|
||||
What: /sys/devices/hisi_ptt<sicl_id>_<core_id>/tune/qos_tx_p
|
||||
What: /sys/bus/event_source/devices/hisi_ptt<sicl_id>_<core_id>/tune/qos_tx_p
|
||||
Date: October 2022
|
||||
KernelVersion: 6.1
|
||||
Contact: Yicong Yang <yangyicong@hisilicon.com>
|
||||
|
@ -38,7 +38,7 @@ Description: (RW) Controls the weight of Tx posted TLPs, which influence the
|
|||
will return an error, and out of range values will be converted
|
||||
to 2. The value indicates a probable level of the event.
|
||||
|
||||
What: /sys/devices/hisi_ptt<sicl_id>_<core_id>/tune/rx_alloc_buf_level
|
||||
What: /sys/bus/event_source/devices/hisi_ptt<sicl_id>_<core_id>/tune/rx_alloc_buf_level
|
||||
Date: October 2022
|
||||
KernelVersion: 6.1
|
||||
Contact: Yicong Yang <yangyicong@hisilicon.com>
|
||||
|
@ -49,7 +49,7 @@ Description: (RW) Control the allocated buffer watermark for inbound packets.
|
|||
will return an error, and out of range values will be converted
|
||||
to 2. The value indicates a probable level of the event.
|
||||
|
||||
What: /sys/devices/hisi_ptt<sicl_id>_<core_id>/tune/tx_alloc_buf_level
|
||||
What: /sys/bus/event_source/devices/hisi_ptt<sicl_id>_<core_id>/tune/tx_alloc_buf_level
|
||||
Date: October 2022
|
||||
KernelVersion: 6.1
|
||||
Contact: Yicong Yang <yangyicong@hisilicon.com>
|
|
@ -66,13 +66,11 @@ properties:
|
|||
- const: apb_pclk
|
||||
|
||||
in-ports:
|
||||
type: object
|
||||
description: |
|
||||
Input connections from TPDM to TPDA
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
out-ports:
|
||||
type: object
|
||||
description: |
|
||||
Output connections from the TPDA to legacy CoreSight trace bus.
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
@ -97,33 +95,31 @@ examples:
|
|||
# minimum tpda definition.
|
||||
- |
|
||||
tpda@6004000 {
|
||||
compatible = "qcom,coresight-tpda", "arm,primecell";
|
||||
reg = <0x6004000 0x1000>;
|
||||
compatible = "qcom,coresight-tpda", "arm,primecell";
|
||||
reg = <0x6004000 0x1000>;
|
||||
|
||||
clocks = <&aoss_qmp>;
|
||||
clock-names = "apb_pclk";
|
||||
clocks = <&aoss_qmp>;
|
||||
clock-names = "apb_pclk";
|
||||
|
||||
in-ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
in-ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
tpda_qdss_0_in_tpdm_dcc: endpoint {
|
||||
remote-endpoint =
|
||||
<&tpdm_dcc_out_tpda_qdss_0>;
|
||||
};
|
||||
remote-endpoint = <&tpdm_dcc_out_tpda_qdss_0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
out-ports {
|
||||
port {
|
||||
tpda_qdss_out_funnel_in0: endpoint {
|
||||
remote-endpoint =
|
||||
<&funnel_in0_in_tpda_qdss>;
|
||||
};
|
||||
out-ports {
|
||||
port {
|
||||
tpda_qdss_out_funnel_in0: endpoint {
|
||||
remote-endpoint = <&funnel_in0_in_tpda_qdss>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
|
|
|
@ -40,7 +40,7 @@ IO dies (SICL, Super I/O Cluster), where there's one PCIe Root
|
|||
Complex for each SICL.
|
||||
::
|
||||
|
||||
/sys/devices/hisi_ptt<sicl_id>_<core_id>
|
||||
/sys/bus/event_source/devices/hisi_ptt<sicl_id>_<core_id>
|
||||
|
||||
Tune
|
||||
====
|
||||
|
@ -53,7 +53,7 @@ Each event is presented as a file under $(PTT PMU dir)/tune, and
|
|||
a simple open/read/write/close cycle will be used to tune the event.
|
||||
::
|
||||
|
||||
$ cd /sys/devices/hisi_ptt<sicl_id>_<core_id>/tune
|
||||
$ cd /sys/bus/event_source/devices/hisi_ptt<sicl_id>_<core_id>/tune
|
||||
$ ls
|
||||
qos_tx_cpl qos_tx_np qos_tx_p
|
||||
tx_path_rx_req_alloc_buf_level
|
||||
|
|
|
@ -9816,7 +9816,7 @@ M: Yicong Yang <yangyicong@hisilicon.com>
|
|||
M: Jonathan Cameron <jonathan.cameron@huawei.com>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-devices-hisi_ptt
|
||||
F: Documentation/ABI/testing/sysfs-bus-event_source-devices-hisi_ptt
|
||||
F: Documentation/trace/hisi-ptt.rst
|
||||
F: drivers/hwtracing/ptt/
|
||||
F: tools/perf/arch/arm64/util/hisi-ptt.c
|
||||
|
|
|
@ -22,14 +22,6 @@
|
|||
static const struct acpi_device_id amba_id_list[] = {
|
||||
{"ARMH0061", 0}, /* PL061 GPIO Device */
|
||||
{"ARMH0330", 0}, /* ARM DMA Controller DMA-330 */
|
||||
{"ARMHC501", 0}, /* ARM CoreSight ETR */
|
||||
{"ARMHC502", 0}, /* ARM CoreSight STM */
|
||||
{"ARMHC503", 0}, /* ARM CoreSight Debug */
|
||||
{"ARMHC979", 0}, /* ARM CoreSight TPIU */
|
||||
{"ARMHC97C", 0}, /* ARM CoreSight SoC-400 TMC, SoC-600 ETF/ETB */
|
||||
{"ARMHC98D", 0}, /* ARM CoreSight Dynamic Replicator */
|
||||
{"ARMHC9CA", 0}, /* ARM CoreSight CATU */
|
||||
{"ARMHC9FF", 0}, /* ARM CoreSight Dynamic Funnel */
|
||||
{"", 0},
|
||||
};
|
||||
|
||||
|
|
|
@ -7,11 +7,13 @@
|
|||
* Author: Suzuki K Poulose <suzuki.poulose@arm.com>
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "coresight-catu.h"
|
||||
|
@ -502,28 +504,20 @@ static const struct coresight_ops catu_ops = {
|
|||
.helper_ops = &catu_helper_ops,
|
||||
};
|
||||
|
||||
static int catu_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
static int __catu_probe(struct device *dev, struct resource *res)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 dma_mask;
|
||||
struct catu_drvdata *drvdata;
|
||||
struct catu_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
struct coresight_desc catu_desc;
|
||||
struct coresight_platform_data *pdata = NULL;
|
||||
struct device *dev = &adev->dev;
|
||||
void __iomem *base;
|
||||
|
||||
catu_desc.name = coresight_alloc_device_name(&catu_devs, dev);
|
||||
if (!catu_desc.name)
|
||||
return -ENOMEM;
|
||||
|
||||
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_set_drvdata(dev, drvdata);
|
||||
base = devm_ioremap_resource(dev, &adev->res);
|
||||
base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(base)) {
|
||||
ret = PTR_ERR(base);
|
||||
goto out;
|
||||
|
@ -567,19 +561,39 @@ static int catu_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
drvdata->csdev = coresight_register(&catu_desc);
|
||||
if (IS_ERR(drvdata->csdev))
|
||||
ret = PTR_ERR(drvdata->csdev);
|
||||
else
|
||||
pm_runtime_put(&adev->dev);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void catu_remove(struct amba_device *adev)
|
||||
static int catu_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
{
|
||||
struct catu_drvdata *drvdata = dev_get_drvdata(&adev->dev);
|
||||
struct catu_drvdata *drvdata;
|
||||
int ret;
|
||||
|
||||
drvdata = devm_kzalloc(&adev->dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
|
||||
amba_set_drvdata(adev, drvdata);
|
||||
ret = __catu_probe(&adev->dev, &adev->res);
|
||||
if (!ret)
|
||||
pm_runtime_put(&adev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __catu_remove(struct device *dev)
|
||||
{
|
||||
struct catu_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
|
||||
coresight_unregister(drvdata->csdev);
|
||||
}
|
||||
|
||||
static void catu_remove(struct amba_device *adev)
|
||||
{
|
||||
__catu_remove(&adev->dev);
|
||||
}
|
||||
|
||||
static struct amba_id catu_ids[] = {
|
||||
CS_AMBA_ID(0x000bb9ee),
|
||||
{},
|
||||
|
@ -598,13 +612,98 @@ static struct amba_driver catu_driver = {
|
|||
.id_table = catu_ids,
|
||||
};
|
||||
|
||||
static int catu_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
struct catu_drvdata *drvdata;
|
||||
int ret = 0;
|
||||
|
||||
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;
|
||||
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
dev_set_drvdata(&pdev->dev, drvdata);
|
||||
ret = __catu_probe(&pdev->dev, res);
|
||||
pm_runtime_put(&pdev->dev);
|
||||
if (ret) {
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
if (!IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_put(drvdata->pclk);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void catu_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct catu_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
if (WARN_ON(!drvdata))
|
||||
return;
|
||||
|
||||
__catu_remove(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
if (!IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_put(drvdata->pclk);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int catu_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct catu_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
|
||||
if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_disable_unprepare(drvdata->pclk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int catu_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct catu_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
|
||||
if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_prepare_enable(drvdata->pclk);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops catu_dev_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(catu_runtime_suspend, catu_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id catu_acpi_ids[] = {
|
||||
{"ARMHC9CA", 0, 0, 0}, /* ARM CoreSight CATU */
|
||||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(acpi, catu_acpi_ids);
|
||||
#endif
|
||||
|
||||
static struct platform_driver catu_platform_driver = {
|
||||
.probe = catu_platform_probe,
|
||||
.remove_new = catu_platform_remove,
|
||||
.driver = {
|
||||
.name = "coresight-catu-platform",
|
||||
.acpi_match_table = ACPI_PTR(catu_acpi_ids),
|
||||
.suppress_bind_attrs = true,
|
||||
.pm = &catu_dev_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init catu_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = amba_driver_register(&catu_driver);
|
||||
if (ret)
|
||||
pr_info("Error registering catu driver\n");
|
||||
ret = coresight_init_driver("catu", &catu_driver, &catu_platform_driver);
|
||||
tmc_etr_set_catu_ops(&etr_catu_buf_ops);
|
||||
return ret;
|
||||
}
|
||||
|
@ -612,7 +711,7 @@ static int __init catu_init(void)
|
|||
static void __exit catu_exit(void)
|
||||
{
|
||||
tmc_etr_remove_catu_ops();
|
||||
amba_driver_unregister(&catu_driver);
|
||||
coresight_remove_driver(&catu_driver, &catu_platform_driver);
|
||||
}
|
||||
|
||||
module_init(catu_init);
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#define CATU_IRQEN_OFF 0x0
|
||||
|
||||
struct catu_drvdata {
|
||||
struct clk *pclk;
|
||||
void __iomem *base;
|
||||
struct coresight_device *csdev;
|
||||
int irq;
|
||||
|
|
|
@ -1398,6 +1398,35 @@ static void __exit coresight_exit(void)
|
|||
module_init(coresight_init);
|
||||
module_exit(coresight_exit);
|
||||
|
||||
int coresight_init_driver(const char *drv, struct amba_driver *amba_drv,
|
||||
struct platform_driver *pdev_drv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = amba_driver_register(amba_drv);
|
||||
if (ret) {
|
||||
pr_err("%s: error registering AMBA driver\n", drv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = platform_driver_register(pdev_drv);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
pr_err("%s: error registering platform driver\n", drv);
|
||||
amba_driver_unregister(amba_drv);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_init_driver);
|
||||
|
||||
void coresight_remove_driver(struct amba_driver *amba_drv,
|
||||
struct platform_driver *pdev_drv)
|
||||
{
|
||||
amba_driver_unregister(amba_drv);
|
||||
platform_driver_unregister(pdev_drv);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_remove_driver);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Pratik Patel <pratikp@codeaurora.org>");
|
||||
MODULE_AUTHOR("Mathieu Poirier <mathieu.poirier@linaro.org>");
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*
|
||||
* Author: Leo Yan <leo.yan@linaro.org>
|
||||
*/
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/coresight.h>
|
||||
#include <linux/cpu.h>
|
||||
|
@ -18,6 +19,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/panic_notifier.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_qos.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smp.h>
|
||||
|
@ -84,6 +86,7 @@
|
|||
#define DEBUG_WAIT_TIMEOUT 32000
|
||||
|
||||
struct debug_drvdata {
|
||||
struct clk *pclk;
|
||||
void __iomem *base;
|
||||
struct device *dev;
|
||||
int cpu;
|
||||
|
@ -557,18 +560,12 @@ static void debug_func_exit(void)
|
|||
debugfs_remove_recursive(debug_debugfs_dir);
|
||||
}
|
||||
|
||||
static int debug_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
static int __debug_probe(struct device *dev, struct resource *res)
|
||||
{
|
||||
struct debug_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
void __iomem *base;
|
||||
struct device *dev = &adev->dev;
|
||||
struct debug_drvdata *drvdata;
|
||||
struct resource *res = &adev->res;
|
||||
int ret;
|
||||
|
||||
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
|
||||
drvdata->cpu = coresight_get_cpu(dev);
|
||||
if (drvdata->cpu < 0)
|
||||
return drvdata->cpu;
|
||||
|
@ -579,10 +576,7 @@ static int debug_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
drvdata->dev = &adev->dev;
|
||||
amba_set_drvdata(adev, drvdata);
|
||||
|
||||
/* Validity for the resource is already checked by the AMBA core */
|
||||
drvdata->dev = dev;
|
||||
base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
@ -629,10 +623,21 @@ static int debug_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void debug_remove(struct amba_device *adev)
|
||||
static int debug_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
{
|
||||
struct device *dev = &adev->dev;
|
||||
struct debug_drvdata *drvdata = amba_get_drvdata(adev);
|
||||
struct debug_drvdata *drvdata;
|
||||
|
||||
drvdata = devm_kzalloc(&adev->dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
|
||||
amba_set_drvdata(adev, drvdata);
|
||||
return __debug_probe(&adev->dev, &adev->res);
|
||||
}
|
||||
|
||||
static void __debug_remove(struct device *dev)
|
||||
{
|
||||
struct debug_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
|
||||
per_cpu(debug_drvdata, drvdata->cpu) = NULL;
|
||||
|
||||
|
@ -646,6 +651,11 @@ static void debug_remove(struct amba_device *adev)
|
|||
debug_func_exit();
|
||||
}
|
||||
|
||||
static void debug_remove(struct amba_device *adev)
|
||||
{
|
||||
__debug_remove(&adev->dev);
|
||||
}
|
||||
|
||||
static const struct amba_cs_uci_id uci_id_debug[] = {
|
||||
{
|
||||
/* CPU Debug UCI data */
|
||||
|
@ -677,7 +687,102 @@ static struct amba_driver debug_driver = {
|
|||
.id_table = debug_ids,
|
||||
};
|
||||
|
||||
module_amba_driver(debug_driver);
|
||||
static int debug_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
struct debug_drvdata *drvdata;
|
||||
int ret = 0;
|
||||
|
||||
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;
|
||||
|
||||
dev_set_drvdata(&pdev->dev, drvdata);
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
ret = __debug_probe(&pdev->dev, res);
|
||||
if (ret) {
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
if (!IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_put(drvdata->pclk);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void debug_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct debug_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
if (WARN_ON(!drvdata))
|
||||
return;
|
||||
|
||||
__debug_remove(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
if (!IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_put(drvdata->pclk);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id debug_platform_ids[] = {
|
||||
{"ARMHC503", 0, 0, 0}, /* ARM CoreSight Debug */
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, debug_platform_ids);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int debug_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct debug_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
|
||||
if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_disable_unprepare(drvdata->pclk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int debug_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct debug_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
|
||||
if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_prepare_enable(drvdata->pclk);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops debug_dev_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(debug_runtime_suspend, debug_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static struct platform_driver debug_platform_driver = {
|
||||
.probe = debug_platform_probe,
|
||||
.remove_new = debug_platform_remove,
|
||||
.driver = {
|
||||
.name = "coresight-debug-platform",
|
||||
.acpi_match_table = ACPI_PTR(debug_platform_ids),
|
||||
.suppress_bind_attrs = true,
|
||||
.pm = &debug_dev_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init debug_init(void)
|
||||
{
|
||||
return coresight_init_driver("debug", &debug_driver, &debug_platform_driver);
|
||||
}
|
||||
|
||||
static void __exit debug_exit(void)
|
||||
{
|
||||
coresight_remove_driver(&debug_driver, &debug_platform_driver);
|
||||
}
|
||||
module_init(debug_init);
|
||||
module_exit(debug_exit);
|
||||
|
||||
MODULE_AUTHOR("Leo Yan <leo.yan@linaro.org>");
|
||||
MODULE_DESCRIPTION("ARM Coresight CPU Debug Driver");
|
||||
|
|
|
@ -1240,6 +1240,8 @@ static void etm4_init_arch_data(void *info)
|
|||
drvdata->nr_event = FIELD_GET(TRCIDR0_NUMEVENT_MASK, etmidr0);
|
||||
/* QSUPP, bits[16:15] Q element support field */
|
||||
drvdata->q_support = FIELD_GET(TRCIDR0_QSUPP_MASK, etmidr0);
|
||||
if (drvdata->q_support)
|
||||
drvdata->q_filt = !!(etmidr0 & TRCIDR0_QFILT);
|
||||
/* TSSIZE, bits[28:24] Global timestamp size field */
|
||||
drvdata->ts_size = FIELD_GET(TRCIDR0_TSSIZE_MASK, etmidr0);
|
||||
|
||||
|
@ -1732,16 +1734,14 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata)
|
|||
state->trcccctlr = etm4x_read32(csa, TRCCCCTLR);
|
||||
state->trcbbctlr = etm4x_read32(csa, TRCBBCTLR);
|
||||
state->trctraceidr = etm4x_read32(csa, TRCTRACEIDR);
|
||||
state->trcqctlr = etm4x_read32(csa, TRCQCTLR);
|
||||
if (drvdata->q_filt)
|
||||
state->trcqctlr = etm4x_read32(csa, TRCQCTLR);
|
||||
|
||||
state->trcvictlr = etm4x_read32(csa, TRCVICTLR);
|
||||
state->trcviiectlr = etm4x_read32(csa, TRCVIIECTLR);
|
||||
state->trcvissctlr = etm4x_read32(csa, TRCVISSCTLR);
|
||||
if (drvdata->nr_pe_cmp)
|
||||
state->trcvipcssctlr = etm4x_read32(csa, TRCVIPCSSCTLR);
|
||||
state->trcvdctlr = etm4x_read32(csa, TRCVDCTLR);
|
||||
state->trcvdsacctlr = etm4x_read32(csa, TRCVDSACCTLR);
|
||||
state->trcvdarcctlr = etm4x_read32(csa, TRCVDARCCTLR);
|
||||
|
||||
for (i = 0; i < drvdata->nrseqstate - 1; i++)
|
||||
state->trcseqevr[i] = etm4x_read32(csa, TRCSEQEVRn(i));
|
||||
|
@ -1758,7 +1758,8 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata)
|
|||
state->trccntvr[i] = etm4x_read32(csa, TRCCNTVRn(i));
|
||||
}
|
||||
|
||||
for (i = 0; i < drvdata->nr_resource * 2; i++)
|
||||
/* Resource selector pair 0 is reserved */
|
||||
for (i = 2; i < drvdata->nr_resource * 2; i++)
|
||||
state->trcrsctlr[i] = etm4x_read32(csa, TRCRSCTLRn(i));
|
||||
|
||||
for (i = 0; i < drvdata->nr_ss_cmp; i++) {
|
||||
|
@ -1843,8 +1844,10 @@ static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata)
|
|||
{
|
||||
int i;
|
||||
struct etmv4_save_state *state = drvdata->save_state;
|
||||
struct csdev_access tmp_csa = CSDEV_ACCESS_IOMEM(drvdata->base);
|
||||
struct csdev_access *csa = &tmp_csa;
|
||||
struct csdev_access *csa = &drvdata->csdev->access;
|
||||
|
||||
if (WARN_ON(!drvdata->csdev))
|
||||
return;
|
||||
|
||||
etm4_cs_unlock(drvdata, csa);
|
||||
etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET);
|
||||
|
@ -1863,16 +1866,14 @@ static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata)
|
|||
etm4x_relaxed_write32(csa, state->trcccctlr, TRCCCCTLR);
|
||||
etm4x_relaxed_write32(csa, state->trcbbctlr, TRCBBCTLR);
|
||||
etm4x_relaxed_write32(csa, state->trctraceidr, TRCTRACEIDR);
|
||||
etm4x_relaxed_write32(csa, state->trcqctlr, TRCQCTLR);
|
||||
if (drvdata->q_filt)
|
||||
etm4x_relaxed_write32(csa, state->trcqctlr, TRCQCTLR);
|
||||
|
||||
etm4x_relaxed_write32(csa, state->trcvictlr, TRCVICTLR);
|
||||
etm4x_relaxed_write32(csa, state->trcviiectlr, TRCVIIECTLR);
|
||||
etm4x_relaxed_write32(csa, state->trcvissctlr, TRCVISSCTLR);
|
||||
if (drvdata->nr_pe_cmp)
|
||||
etm4x_relaxed_write32(csa, state->trcvipcssctlr, TRCVIPCSSCTLR);
|
||||
etm4x_relaxed_write32(csa, state->trcvdctlr, TRCVDCTLR);
|
||||
etm4x_relaxed_write32(csa, state->trcvdsacctlr, TRCVDSACCTLR);
|
||||
etm4x_relaxed_write32(csa, state->trcvdarcctlr, TRCVDARCCTLR);
|
||||
|
||||
for (i = 0; i < drvdata->nrseqstate - 1; i++)
|
||||
etm4x_relaxed_write32(csa, state->trcseqevr[i], TRCSEQEVRn(i));
|
||||
|
@ -1889,7 +1890,8 @@ static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata)
|
|||
etm4x_relaxed_write32(csa, state->trccntvr[i], TRCCNTVRn(i));
|
||||
}
|
||||
|
||||
for (i = 0; i < drvdata->nr_resource * 2; i++)
|
||||
/* Resource selector pair 0 is reserved */
|
||||
for (i = 2; i < drvdata->nr_resource * 2; i++)
|
||||
etm4x_relaxed_write32(csa, state->trcrsctlr[i], TRCRSCTLRn(i));
|
||||
|
||||
for (i = 0; i < drvdata->nr_ss_cmp; i++) {
|
||||
|
@ -2213,6 +2215,9 @@ static int etm4_probe_platform_dev(struct platform_device *pdev)
|
|||
ret = etm4_probe(&pdev->dev);
|
||||
|
||||
pm_runtime_put(&pdev->dev);
|
||||
if (ret)
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,9 +43,6 @@
|
|||
#define TRCVIIECTLR 0x084
|
||||
#define TRCVISSCTLR 0x088
|
||||
#define TRCVIPCSSCTLR 0x08C
|
||||
#define TRCVDCTLR 0x0A0
|
||||
#define TRCVDSACCTLR 0x0A4
|
||||
#define TRCVDARCCTLR 0x0A8
|
||||
/* Derived resources registers */
|
||||
#define TRCSEQEVRn(n) (0x100 + (n * 4)) /* n = 0-2 */
|
||||
#define TRCSEQRSTEVR 0x118
|
||||
|
@ -90,9 +87,6 @@
|
|||
/* Address Comparator registers n = 0-15 */
|
||||
#define TRCACVRn(n) (0x400 + (n * 8))
|
||||
#define TRCACATRn(n) (0x480 + (n * 8))
|
||||
/* Data Value Comparator Value registers, n = 0-7 */
|
||||
#define TRCDVCVRn(n) (0x500 + (n * 16))
|
||||
#define TRCDVCMRn(n) (0x580 + (n * 16))
|
||||
/* ContextID/Virtual ContextID comparators, n = 0-7 */
|
||||
#define TRCCIDCVRn(n) (0x600 + (n * 8))
|
||||
#define TRCVMIDCVRn(n) (0x640 + (n * 8))
|
||||
|
@ -141,6 +135,7 @@
|
|||
#define TRCIDR0_TRCCCI BIT(7)
|
||||
#define TRCIDR0_RETSTACK BIT(9)
|
||||
#define TRCIDR0_NUMEVENT_MASK GENMASK(11, 10)
|
||||
#define TRCIDR0_QFILT BIT(14)
|
||||
#define TRCIDR0_QSUPP_MASK GENMASK(16, 15)
|
||||
#define TRCIDR0_TSSIZE_MASK GENMASK(28, 24)
|
||||
|
||||
|
@ -272,9 +267,6 @@
|
|||
/* List of registers accessible via System instructions */
|
||||
#define ETM4x_ONLY_SYSREG_LIST(op, val) \
|
||||
CASE_##op((val), TRCPROCSELR) \
|
||||
CASE_##op((val), TRCVDCTLR) \
|
||||
CASE_##op((val), TRCVDSACCTLR) \
|
||||
CASE_##op((val), TRCVDARCCTLR) \
|
||||
CASE_##op((val), TRCOSLAR)
|
||||
|
||||
#define ETM_COMMON_SYSREG_LIST(op, val) \
|
||||
|
@ -422,22 +414,6 @@
|
|||
CASE_##op((val), TRCACATRn(13)) \
|
||||
CASE_##op((val), TRCACATRn(14)) \
|
||||
CASE_##op((val), TRCACATRn(15)) \
|
||||
CASE_##op((val), TRCDVCVRn(0)) \
|
||||
CASE_##op((val), TRCDVCVRn(1)) \
|
||||
CASE_##op((val), TRCDVCVRn(2)) \
|
||||
CASE_##op((val), TRCDVCVRn(3)) \
|
||||
CASE_##op((val), TRCDVCVRn(4)) \
|
||||
CASE_##op((val), TRCDVCVRn(5)) \
|
||||
CASE_##op((val), TRCDVCVRn(6)) \
|
||||
CASE_##op((val), TRCDVCVRn(7)) \
|
||||
CASE_##op((val), TRCDVCMRn(0)) \
|
||||
CASE_##op((val), TRCDVCMRn(1)) \
|
||||
CASE_##op((val), TRCDVCMRn(2)) \
|
||||
CASE_##op((val), TRCDVCMRn(3)) \
|
||||
CASE_##op((val), TRCDVCMRn(4)) \
|
||||
CASE_##op((val), TRCDVCMRn(5)) \
|
||||
CASE_##op((val), TRCDVCMRn(6)) \
|
||||
CASE_##op((val), TRCDVCMRn(7)) \
|
||||
CASE_##op((val), TRCCIDCVRn(0)) \
|
||||
CASE_##op((val), TRCCIDCVRn(1)) \
|
||||
CASE_##op((val), TRCCIDCVRn(2)) \
|
||||
|
@ -907,9 +883,6 @@ struct etmv4_save_state {
|
|||
u32 trcviiectlr;
|
||||
u32 trcvissctlr;
|
||||
u32 trcvipcssctlr;
|
||||
u32 trcvdctlr;
|
||||
u32 trcvdsacctlr;
|
||||
u32 trcvdarcctlr;
|
||||
|
||||
u32 trcseqevr[ETM_MAX_SEQ_STATES];
|
||||
u32 trcseqrstevr;
|
||||
|
@ -982,6 +955,7 @@ struct etmv4_save_state {
|
|||
* @os_unlock: True if access to management registers is allowed.
|
||||
* @instrp0: Tracing of load and store instructions
|
||||
* as P0 elements is supported.
|
||||
* @q_filt: Q element filtering support, if Q elements are supported.
|
||||
* @trcbb: Indicates if the trace unit supports branch broadcast tracing.
|
||||
* @trccond: If the trace unit supports conditional
|
||||
* instruction tracing.
|
||||
|
@ -1044,6 +1018,7 @@ struct etmv4_drvdata {
|
|||
bool boot_enable;
|
||||
bool os_unlock;
|
||||
bool instrp0;
|
||||
bool q_filt;
|
||||
bool trcbb;
|
||||
bool trccond;
|
||||
bool retstack;
|
||||
|
|
|
@ -36,6 +36,7 @@ DEFINE_CORESIGHT_DEVLIST(funnel_devs, "funnel");
|
|||
* struct funnel_drvdata - specifics associated to a funnel component
|
||||
* @base: memory mapped base address for this component.
|
||||
* @atclk: optional clock for the core parts of the funnel.
|
||||
* @pclk: APB clock if present, otherwise NULL
|
||||
* @csdev: component vitals needed by the framework.
|
||||
* @priority: port selection order.
|
||||
* @spinlock: serialize enable/disable operations.
|
||||
|
@ -43,6 +44,7 @@ DEFINE_CORESIGHT_DEVLIST(funnel_devs, "funnel");
|
|||
struct funnel_drvdata {
|
||||
void __iomem *base;
|
||||
struct clk *atclk;
|
||||
struct clk *pclk;
|
||||
struct coresight_device *csdev;
|
||||
unsigned long priority;
|
||||
spinlock_t spinlock;
|
||||
|
@ -236,6 +238,10 @@ static int funnel_probe(struct device *dev, struct resource *res)
|
|||
return ret;
|
||||
}
|
||||
|
||||
drvdata->pclk = coresight_get_enable_apb_pclk(dev);
|
||||
if (IS_ERR(drvdata->pclk))
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* Map the device base for dynamic-funnel, which has been
|
||||
* validated by AMBA core.
|
||||
|
@ -272,12 +278,13 @@ static int funnel_probe(struct device *dev, struct resource *res)
|
|||
goto out_disable_clk;
|
||||
}
|
||||
|
||||
pm_runtime_put(dev);
|
||||
ret = 0;
|
||||
|
||||
out_disable_clk:
|
||||
if (ret && !IS_ERR_OR_NULL(drvdata->atclk))
|
||||
clk_disable_unprepare(drvdata->atclk);
|
||||
if (ret && !IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_disable_unprepare(drvdata->pclk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -298,6 +305,9 @@ static int funnel_runtime_suspend(struct device *dev)
|
|||
if (drvdata && !IS_ERR(drvdata->atclk))
|
||||
clk_disable_unprepare(drvdata->atclk);
|
||||
|
||||
if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_disable_unprepare(drvdata->pclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -308,6 +318,8 @@ static int funnel_runtime_resume(struct device *dev)
|
|||
if (drvdata && !IS_ERR(drvdata->atclk))
|
||||
clk_prepare_enable(drvdata->atclk);
|
||||
|
||||
if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_prepare_enable(drvdata->pclk);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -316,55 +328,61 @@ static const struct dev_pm_ops funnel_dev_pm_ops = {
|
|||
SET_RUNTIME_PM_OPS(funnel_runtime_suspend, funnel_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static int static_funnel_probe(struct platform_device *pdev)
|
||||
static int funnel_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
int ret;
|
||||
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
/* Static funnel do not have programming base */
|
||||
ret = funnel_probe(&pdev->dev, NULL);
|
||||
|
||||
if (ret) {
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
ret = funnel_probe(&pdev->dev, res);
|
||||
pm_runtime_put(&pdev->dev);
|
||||
if (ret)
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void static_funnel_remove(struct platform_device *pdev)
|
||||
static void funnel_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct funnel_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
if (WARN_ON(!drvdata))
|
||||
return;
|
||||
|
||||
funnel_remove(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
if (!IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_put(drvdata->pclk);
|
||||
}
|
||||
|
||||
static const struct of_device_id static_funnel_match[] = {
|
||||
static const struct of_device_id funnel_match[] = {
|
||||
{.compatible = "arm,coresight-static-funnel"},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, static_funnel_match);
|
||||
MODULE_DEVICE_TABLE(of, funnel_match);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id static_funnel_ids[] = {
|
||||
{"ARMHC9FE", 0, 0, 0},
|
||||
static const struct acpi_device_id funnel_acpi_ids[] = {
|
||||
{"ARMHC9FE", 0, 0, 0}, /* ARM Coresight Static Funnel */
|
||||
{"ARMHC9FF", 0, 0, 0}, /* ARM CoreSight Dynamic Funnel */
|
||||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(acpi, static_funnel_ids);
|
||||
MODULE_DEVICE_TABLE(acpi, funnel_acpi_ids);
|
||||
#endif
|
||||
|
||||
static struct platform_driver static_funnel_driver = {
|
||||
.probe = static_funnel_probe,
|
||||
.remove_new = static_funnel_remove,
|
||||
.driver = {
|
||||
.name = "coresight-static-funnel",
|
||||
static struct platform_driver funnel_driver = {
|
||||
.probe = funnel_platform_probe,
|
||||
.remove_new = funnel_platform_remove,
|
||||
.driver = {
|
||||
.name = "coresight-funnel",
|
||||
/* THIS_MODULE is taken care of by platform_driver_register() */
|
||||
.of_match_table = static_funnel_match,
|
||||
.acpi_match_table = ACPI_PTR(static_funnel_ids),
|
||||
.of_match_table = funnel_match,
|
||||
.acpi_match_table = ACPI_PTR(funnel_acpi_ids),
|
||||
.pm = &funnel_dev_pm_ops,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
|
@ -373,7 +391,13 @@ static struct platform_driver static_funnel_driver = {
|
|||
static int dynamic_funnel_probe(struct amba_device *adev,
|
||||
const struct amba_id *id)
|
||||
{
|
||||
return funnel_probe(&adev->dev, &adev->res);
|
||||
int ret;
|
||||
|
||||
ret = funnel_probe(&adev->dev, &adev->res);
|
||||
if (!ret)
|
||||
pm_runtime_put(&adev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dynamic_funnel_remove(struct amba_device *adev)
|
||||
|
@ -410,27 +434,12 @@ static struct amba_driver dynamic_funnel_driver = {
|
|||
|
||||
static int __init funnel_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&static_funnel_driver);
|
||||
if (ret) {
|
||||
pr_info("Error registering platform driver\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = amba_driver_register(&dynamic_funnel_driver);
|
||||
if (ret) {
|
||||
pr_info("Error registering amba driver\n");
|
||||
platform_driver_unregister(&static_funnel_driver);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return coresight_init_driver("funnel", &dynamic_funnel_driver, &funnel_driver);
|
||||
}
|
||||
|
||||
static void __exit funnel_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&static_funnel_driver);
|
||||
amba_driver_unregister(&dynamic_funnel_driver);
|
||||
coresight_remove_driver(&dynamic_funnel_driver, &funnel_driver);
|
||||
}
|
||||
|
||||
module_init(funnel_init);
|
||||
|
|
|
@ -222,6 +222,16 @@ static inline void *coresight_get_uci_data(const struct amba_id *id)
|
|||
return uci_id->data;
|
||||
}
|
||||
|
||||
static inline void *coresight_get_uci_data_from_amba(const struct amba_id *table, u32 pid)
|
||||
{
|
||||
while (table->mask) {
|
||||
if ((pid & table->mask) == table->id)
|
||||
return coresight_get_uci_data(table);
|
||||
table++;
|
||||
};
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void coresight_release_platform_data(struct coresight_device *csdev,
|
||||
struct device *dev,
|
||||
struct coresight_platform_data *pdata);
|
||||
|
|
|
@ -31,6 +31,7 @@ DEFINE_CORESIGHT_DEVLIST(replicator_devs, "replicator");
|
|||
* @base: memory mapped base address for this component. Also indicates
|
||||
* whether this one is programmable or not.
|
||||
* @atclk: optional clock for the core parts of the replicator.
|
||||
* @pclk: APB clock if present, otherwise NULL
|
||||
* @csdev: component vitals needed by the framework
|
||||
* @spinlock: serialize enable/disable operations.
|
||||
* @check_idfilter_val: check if the context is lost upon clock removal.
|
||||
|
@ -38,6 +39,7 @@ DEFINE_CORESIGHT_DEVLIST(replicator_devs, "replicator");
|
|||
struct replicator_drvdata {
|
||||
void __iomem *base;
|
||||
struct clk *atclk;
|
||||
struct clk *pclk;
|
||||
struct coresight_device *csdev;
|
||||
spinlock_t spinlock;
|
||||
bool check_idfilter_val;
|
||||
|
@ -243,6 +245,10 @@ static int replicator_probe(struct device *dev, struct resource *res)
|
|||
return ret;
|
||||
}
|
||||
|
||||
drvdata->pclk = coresight_get_enable_apb_pclk(dev);
|
||||
if (IS_ERR(drvdata->pclk))
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* Map the device base for dynamic-replicator, which has been
|
||||
* validated by AMBA core
|
||||
|
@ -285,11 +291,12 @@ static int replicator_probe(struct device *dev, struct resource *res)
|
|||
}
|
||||
|
||||
replicator_reset(drvdata);
|
||||
pm_runtime_put(dev);
|
||||
|
||||
out_disable_clk:
|
||||
if (ret && !IS_ERR_OR_NULL(drvdata->atclk))
|
||||
clk_disable_unprepare(drvdata->atclk);
|
||||
if (ret && !IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_disable_unprepare(drvdata->pclk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -301,29 +308,34 @@ static int replicator_remove(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int static_replicator_probe(struct platform_device *pdev)
|
||||
static int replicator_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
int ret;
|
||||
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
/* Static replicators do not have programming base */
|
||||
ret = replicator_probe(&pdev->dev, NULL);
|
||||
|
||||
if (ret) {
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
ret = replicator_probe(&pdev->dev, res);
|
||||
pm_runtime_put(&pdev->dev);
|
||||
if (ret)
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void static_replicator_remove(struct platform_device *pdev)
|
||||
static void replicator_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct replicator_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
if (WARN_ON(!drvdata))
|
||||
return;
|
||||
|
||||
replicator_remove(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
if (!IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_put(drvdata->pclk);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
@ -334,6 +346,8 @@ static int replicator_runtime_suspend(struct device *dev)
|
|||
if (drvdata && !IS_ERR(drvdata->atclk))
|
||||
clk_disable_unprepare(drvdata->atclk);
|
||||
|
||||
if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_disable_unprepare(drvdata->pclk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -344,6 +358,8 @@ static int replicator_runtime_resume(struct device *dev)
|
|||
if (drvdata && !IS_ERR(drvdata->atclk))
|
||||
clk_prepare_enable(drvdata->atclk);
|
||||
|
||||
if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_prepare_enable(drvdata->pclk);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -353,31 +369,32 @@ static const struct dev_pm_ops replicator_dev_pm_ops = {
|
|||
replicator_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static const struct of_device_id static_replicator_match[] = {
|
||||
static const struct of_device_id replicator_match[] = {
|
||||
{.compatible = "arm,coresight-replicator"},
|
||||
{.compatible = "arm,coresight-static-replicator"},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, static_replicator_match);
|
||||
MODULE_DEVICE_TABLE(of, replicator_match);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id static_replicator_acpi_ids[] = {
|
||||
static const struct acpi_device_id replicator_acpi_ids[] = {
|
||||
{"ARMHC985", 0, 0, 0}, /* ARM CoreSight Static Replicator */
|
||||
{"ARMHC98D", 0, 0, 0}, /* ARM CoreSight Dynamic Replicator */
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(acpi, static_replicator_acpi_ids);
|
||||
MODULE_DEVICE_TABLE(acpi, replicator_acpi_ids);
|
||||
#endif
|
||||
|
||||
static struct platform_driver static_replicator_driver = {
|
||||
.probe = static_replicator_probe,
|
||||
.remove_new = static_replicator_remove,
|
||||
static struct platform_driver replicator_driver = {
|
||||
.probe = replicator_platform_probe,
|
||||
.remove_new = replicator_platform_remove,
|
||||
.driver = {
|
||||
.name = "coresight-static-replicator",
|
||||
.name = "coresight-replicator",
|
||||
/* THIS_MODULE is taken care of by platform_driver_register() */
|
||||
.of_match_table = of_match_ptr(static_replicator_match),
|
||||
.acpi_match_table = ACPI_PTR(static_replicator_acpi_ids),
|
||||
.of_match_table = of_match_ptr(replicator_match),
|
||||
.acpi_match_table = ACPI_PTR(replicator_acpi_ids),
|
||||
.pm = &replicator_dev_pm_ops,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
|
@ -386,7 +403,13 @@ static struct platform_driver static_replicator_driver = {
|
|||
static int dynamic_replicator_probe(struct amba_device *adev,
|
||||
const struct amba_id *id)
|
||||
{
|
||||
return replicator_probe(&adev->dev, &adev->res);
|
||||
int ret;
|
||||
|
||||
ret = replicator_probe(&adev->dev, &adev->res);
|
||||
if (!ret)
|
||||
pm_runtime_put(&adev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dynamic_replicator_remove(struct amba_device *adev)
|
||||
|
@ -416,27 +439,12 @@ static struct amba_driver dynamic_replicator_driver = {
|
|||
|
||||
static int __init replicator_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&static_replicator_driver);
|
||||
if (ret) {
|
||||
pr_info("Error registering platform driver\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = amba_driver_register(&dynamic_replicator_driver);
|
||||
if (ret) {
|
||||
pr_info("Error registering amba driver\n");
|
||||
platform_driver_unregister(&static_replicator_driver);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return coresight_init_driver("replicator", &dynamic_replicator_driver, &replicator_driver);
|
||||
}
|
||||
|
||||
static void __exit replicator_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&static_replicator_driver);
|
||||
amba_driver_unregister(&dynamic_replicator_driver);
|
||||
coresight_remove_driver(&dynamic_replicator_driver, &replicator_driver);
|
||||
}
|
||||
|
||||
module_init(replicator_init);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <linux/perf_event.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/stm.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "coresight-priv.h"
|
||||
#include "coresight-trace-id.h"
|
||||
|
@ -115,6 +116,7 @@ DEFINE_CORESIGHT_DEVLIST(stm_devs, "stm");
|
|||
* struct stm_drvdata - specifics associated to an STM component
|
||||
* @base: memory mapped base address for this component.
|
||||
* @atclk: optional clock for the core parts of the STM.
|
||||
* @pclk: APB clock if present, otherwise NULL
|
||||
* @csdev: component vitals needed by the framework.
|
||||
* @spinlock: only one at a time pls.
|
||||
* @chs: the channels accociated to this STM.
|
||||
|
@ -131,6 +133,7 @@ DEFINE_CORESIGHT_DEVLIST(stm_devs, "stm");
|
|||
struct stm_drvdata {
|
||||
void __iomem *base;
|
||||
struct clk *atclk;
|
||||
struct clk *pclk;
|
||||
struct coresight_device *csdev;
|
||||
spinlock_t spinlock;
|
||||
struct channel_space chs;
|
||||
|
@ -800,14 +803,22 @@ static void stm_init_generic_data(struct stm_drvdata *drvdata,
|
|||
drvdata->stm.set_options = stm_generic_set_options;
|
||||
}
|
||||
|
||||
static int stm_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
static const struct amba_id stm_ids[];
|
||||
|
||||
static char *stm_csdev_name(struct coresight_device *csdev)
|
||||
{
|
||||
u32 stm_pid = coresight_get_pid(&csdev->access);
|
||||
void *uci_data = coresight_get_uci_data_from_amba(stm_ids, stm_pid);
|
||||
|
||||
return uci_data ? (char *)uci_data : "STM";
|
||||
}
|
||||
|
||||
static int __stm_probe(struct device *dev, struct resource *res)
|
||||
{
|
||||
int ret, trace_id;
|
||||
void __iomem *base;
|
||||
struct device *dev = &adev->dev;
|
||||
struct coresight_platform_data *pdata = NULL;
|
||||
struct stm_drvdata *drvdata;
|
||||
struct resource *res = &adev->res;
|
||||
struct resource ch_res;
|
||||
struct coresight_desc desc = { 0 };
|
||||
|
||||
|
@ -819,12 +830,16 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
|
||||
drvdata->atclk = devm_clk_get(&adev->dev, "atclk"); /* optional */
|
||||
drvdata->atclk = devm_clk_get(dev, "atclk"); /* optional */
|
||||
if (!IS_ERR(drvdata->atclk)) {
|
||||
ret = clk_prepare_enable(drvdata->atclk);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
drvdata->pclk = coresight_get_enable_apb_pclk(dev);
|
||||
if (IS_ERR(drvdata->pclk))
|
||||
return -ENODEV;
|
||||
dev_set_drvdata(dev, drvdata);
|
||||
|
||||
base = devm_ioremap_resource(dev, res);
|
||||
|
@ -872,7 +887,7 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
ret = PTR_ERR(pdata);
|
||||
goto stm_unregister;
|
||||
}
|
||||
adev->dev.platform_data = pdata;
|
||||
dev->platform_data = pdata;
|
||||
|
||||
desc.type = CORESIGHT_DEV_TYPE_SOURCE;
|
||||
desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE;
|
||||
|
@ -893,10 +908,8 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
}
|
||||
drvdata->traceid = (u8)trace_id;
|
||||
|
||||
pm_runtime_put(&adev->dev);
|
||||
|
||||
dev_info(&drvdata->csdev->dev, "%s initialized\n",
|
||||
(char *)coresight_get_uci_data(id));
|
||||
stm_csdev_name(drvdata->csdev));
|
||||
return 0;
|
||||
|
||||
cs_unregister:
|
||||
|
@ -907,9 +920,20 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void stm_remove(struct amba_device *adev)
|
||||
static int stm_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
{
|
||||
struct stm_drvdata *drvdata = dev_get_drvdata(&adev->dev);
|
||||
int ret;
|
||||
|
||||
ret = __stm_probe(&adev->dev, &adev->res);
|
||||
if (!ret)
|
||||
pm_runtime_put(&adev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __stm_remove(struct device *dev)
|
||||
{
|
||||
struct stm_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
|
||||
coresight_trace_id_put_system_id(drvdata->traceid);
|
||||
coresight_unregister(drvdata->csdev);
|
||||
|
@ -917,6 +941,11 @@ static void stm_remove(struct amba_device *adev)
|
|||
stm_unregister_device(&drvdata->stm);
|
||||
}
|
||||
|
||||
static void stm_remove(struct amba_device *adev)
|
||||
{
|
||||
__stm_remove(&adev->dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int stm_runtime_suspend(struct device *dev)
|
||||
{
|
||||
|
@ -925,6 +954,8 @@ static int stm_runtime_suspend(struct device *dev)
|
|||
if (drvdata && !IS_ERR(drvdata->atclk))
|
||||
clk_disable_unprepare(drvdata->atclk);
|
||||
|
||||
if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_disable_unprepare(drvdata->pclk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -935,6 +966,8 @@ static int stm_runtime_resume(struct device *dev)
|
|||
if (drvdata && !IS_ERR(drvdata->atclk))
|
||||
clk_prepare_enable(drvdata->atclk);
|
||||
|
||||
if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_prepare_enable(drvdata->pclk);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -963,7 +996,66 @@ static struct amba_driver stm_driver = {
|
|||
.id_table = stm_ids,
|
||||
};
|
||||
|
||||
module_amba_driver(stm_driver);
|
||||
static int stm_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
int ret = 0;
|
||||
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
ret = __stm_probe(&pdev->dev, res);
|
||||
pm_runtime_put(&pdev->dev);
|
||||
if (ret)
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void stm_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct stm_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
if (WARN_ON(!drvdata))
|
||||
return;
|
||||
|
||||
__stm_remove(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
if (!IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_put(drvdata->pclk);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id stm_acpi_ids[] = {
|
||||
{"ARMHC502", 0, 0, 0}, /* ARM CoreSight STM */
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, stm_acpi_ids);
|
||||
#endif
|
||||
|
||||
static struct platform_driver stm_platform_driver = {
|
||||
.probe = stm_platform_probe,
|
||||
.remove_new = stm_platform_remove,
|
||||
.driver = {
|
||||
.name = "coresight-stm-platform",
|
||||
.acpi_match_table = ACPI_PTR(stm_acpi_ids),
|
||||
.suppress_bind_attrs = true,
|
||||
.pm = &stm_dev_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init stm_init(void)
|
||||
{
|
||||
return coresight_init_driver("stm", &stm_driver, &stm_platform_driver);
|
||||
}
|
||||
|
||||
static void __exit stm_exit(void)
|
||||
{
|
||||
coresight_remove_driver(&stm_driver, &stm_platform_driver);
|
||||
}
|
||||
module_init(stm_init);
|
||||
module_exit(stm_exit);
|
||||
|
||||
MODULE_AUTHOR("Pratik Patel <pratikp@codeaurora.org>");
|
||||
MODULE_DESCRIPTION("Arm CoreSight System Trace Macrocell driver");
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Description: CoreSight Trace Memory Controller driver
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
|
@ -24,6 +25,8 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/coresight.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#include "coresight-priv.h"
|
||||
#include "coresight-tmc.h"
|
||||
|
@ -360,7 +363,32 @@ static const struct attribute_group *coresight_etr_groups[] = {
|
|||
|
||||
static inline bool tmc_etr_can_use_sg(struct device *dev)
|
||||
{
|
||||
return fwnode_property_present(dev->fwnode, "arm,scatter-gather");
|
||||
int ret;
|
||||
u8 val_u8;
|
||||
|
||||
/*
|
||||
* Presence of the property 'arm,scatter-gather' is checked
|
||||
* on the platform for the feature support, rather than its
|
||||
* value.
|
||||
*/
|
||||
if (is_of_node(dev->fwnode)) {
|
||||
return fwnode_property_present(dev->fwnode, "arm,scatter-gather");
|
||||
} else if (is_acpi_device_node(dev->fwnode)) {
|
||||
/*
|
||||
* TMC_DEVID_NOSCAT test in tmc_etr_setup_caps(), has already ensured
|
||||
* this property is only checked for Coresight SoC 400 TMC configured
|
||||
* as ETR.
|
||||
*/
|
||||
ret = fwnode_property_read_u8(dev->fwnode, "arm-armhc97c-sg-enable", &val_u8);
|
||||
if (!ret)
|
||||
return !!val_u8;
|
||||
|
||||
if (fwnode_property_present(dev->fwnode, "arm,scatter-gather")) {
|
||||
pr_warn_once("Deprecated ACPI property - arm,scatter-gather\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool tmc_etr_has_non_secure_access(struct tmc_drvdata *drvdata)
|
||||
|
@ -370,16 +398,23 @@ static inline bool tmc_etr_has_non_secure_access(struct tmc_drvdata *drvdata)
|
|||
return (auth & TMC_AUTH_NSID_MASK) == 0x3;
|
||||
}
|
||||
|
||||
static const struct amba_id tmc_ids[];
|
||||
|
||||
/* Detect and initialise the capabilities of a TMC ETR */
|
||||
static int tmc_etr_setup_caps(struct device *parent, u32 devid, void *dev_caps)
|
||||
static int tmc_etr_setup_caps(struct device *parent, u32 devid,
|
||||
struct csdev_access *access)
|
||||
{
|
||||
int rc;
|
||||
u32 dma_mask = 0;
|
||||
u32 tmc_pid, dma_mask = 0;
|
||||
struct tmc_drvdata *drvdata = dev_get_drvdata(parent);
|
||||
void *dev_caps;
|
||||
|
||||
if (!tmc_etr_has_non_secure_access(drvdata))
|
||||
return -EACCES;
|
||||
|
||||
tmc_pid = coresight_get_pid(access);
|
||||
dev_caps = coresight_get_uci_data_from_amba(tmc_ids, tmc_pid);
|
||||
|
||||
/* Set the unadvertised capabilities */
|
||||
tmc_etr_init_caps(drvdata, (u32)(unsigned long)dev_caps);
|
||||
|
||||
|
@ -437,24 +472,17 @@ static u32 tmc_etr_get_max_burst_size(struct device *dev)
|
|||
return burst_size;
|
||||
}
|
||||
|
||||
static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
static int __tmc_probe(struct device *dev, struct resource *res)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 devid;
|
||||
void __iomem *base;
|
||||
struct device *dev = &adev->dev;
|
||||
struct coresight_platform_data *pdata = NULL;
|
||||
struct tmc_drvdata *drvdata;
|
||||
struct resource *res = &adev->res;
|
||||
struct tmc_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
struct coresight_desc desc = { 0 };
|
||||
struct coresight_dev_list *dev_list = NULL;
|
||||
|
||||
ret = -ENOMEM;
|
||||
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata)
|
||||
goto out;
|
||||
|
||||
dev_set_drvdata(dev, drvdata);
|
||||
|
||||
/* Validity for the resource is already checked by the AMBA core */
|
||||
base = devm_ioremap_resource(dev, res);
|
||||
|
@ -497,8 +525,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
desc.type = CORESIGHT_DEV_TYPE_SINK;
|
||||
desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM;
|
||||
desc.ops = &tmc_etr_cs_ops;
|
||||
ret = tmc_etr_setup_caps(dev, devid,
|
||||
coresight_get_uci_data(id));
|
||||
ret = tmc_etr_setup_caps(dev, devid, &desc.access);
|
||||
if (ret)
|
||||
goto out;
|
||||
idr_init(&drvdata->idr);
|
||||
|
@ -530,7 +557,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
ret = PTR_ERR(pdata);
|
||||
goto out;
|
||||
}
|
||||
adev->dev.platform_data = pdata;
|
||||
dev->platform_data = pdata;
|
||||
desc.pdata = pdata;
|
||||
|
||||
drvdata->csdev = coresight_register(&desc);
|
||||
|
@ -545,12 +572,27 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
ret = misc_register(&drvdata->miscdev);
|
||||
if (ret)
|
||||
coresight_unregister(drvdata->csdev);
|
||||
else
|
||||
pm_runtime_put(&adev->dev);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
{
|
||||
struct tmc_drvdata *drvdata;
|
||||
int ret;
|
||||
|
||||
drvdata = devm_kzalloc(&adev->dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
|
||||
amba_set_drvdata(adev, drvdata);
|
||||
ret = __tmc_probe(&adev->dev, &adev->res);
|
||||
if (!ret)
|
||||
pm_runtime_put(&adev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void tmc_shutdown(struct amba_device *adev)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
@ -573,9 +615,9 @@ static void tmc_shutdown(struct amba_device *adev)
|
|||
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
}
|
||||
|
||||
static void tmc_remove(struct amba_device *adev)
|
||||
static void __tmc_remove(struct device *dev)
|
||||
{
|
||||
struct tmc_drvdata *drvdata = dev_get_drvdata(&adev->dev);
|
||||
struct tmc_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
|
||||
/*
|
||||
* Since misc_open() holds a refcount on the f_ops, which is
|
||||
|
@ -586,6 +628,11 @@ static void tmc_remove(struct amba_device *adev)
|
|||
coresight_unregister(drvdata->csdev);
|
||||
}
|
||||
|
||||
static void tmc_remove(struct amba_device *adev)
|
||||
{
|
||||
__tmc_remove(&adev->dev);
|
||||
}
|
||||
|
||||
static const struct amba_id tmc_ids[] = {
|
||||
CS_AMBA_ID(0x000bb961),
|
||||
/* Coresight SoC 600 TMC-ETR/ETS */
|
||||
|
@ -611,7 +658,101 @@ static struct amba_driver tmc_driver = {
|
|||
.id_table = tmc_ids,
|
||||
};
|
||||
|
||||
module_amba_driver(tmc_driver);
|
||||
static int tmc_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
struct tmc_drvdata *drvdata;
|
||||
int ret = 0;
|
||||
|
||||
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;
|
||||
|
||||
dev_set_drvdata(&pdev->dev, drvdata);
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
ret = __tmc_probe(&pdev->dev, res);
|
||||
pm_runtime_put(&pdev->dev);
|
||||
if (ret)
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void tmc_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tmc_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
if (WARN_ON(!drvdata))
|
||||
return;
|
||||
|
||||
__tmc_remove(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
if (!IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_put(drvdata->pclk);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int tmc_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct tmc_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
|
||||
if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_disable_unprepare(drvdata->pclk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tmc_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct tmc_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
|
||||
if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_prepare_enable(drvdata->pclk);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops tmc_dev_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(tmc_runtime_suspend, tmc_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id tmc_acpi_ids[] = {
|
||||
{"ARMHC501", 0, 0, 0}, /* ARM CoreSight ETR */
|
||||
{"ARMHC97C", 0, 0, 0}, /* ARM CoreSight SoC-400 TMC, SoC-600 ETF/ETB */
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, tmc_acpi_ids);
|
||||
#endif
|
||||
|
||||
static struct platform_driver tmc_platform_driver = {
|
||||
.probe = tmc_platform_probe,
|
||||
.remove_new = tmc_platform_remove,
|
||||
.driver = {
|
||||
.name = "coresight-tmc-platform",
|
||||
.acpi_match_table = ACPI_PTR(tmc_acpi_ids),
|
||||
.suppress_bind_attrs = true,
|
||||
.pm = &tmc_dev_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init tmc_init(void)
|
||||
{
|
||||
return coresight_init_driver("tmc", &tmc_driver, &tmc_platform_driver);
|
||||
}
|
||||
|
||||
static void __exit tmc_exit(void)
|
||||
{
|
||||
coresight_remove_driver(&tmc_driver, &tmc_platform_driver);
|
||||
}
|
||||
module_init(tmc_init);
|
||||
module_exit(tmc_exit);
|
||||
|
||||
MODULE_AUTHOR("Pratik Patel <pratikp@codeaurora.org>");
|
||||
MODULE_DESCRIPTION("Arm CoreSight Trace Memory Controller driver");
|
||||
|
|
|
@ -166,6 +166,7 @@ struct etr_buf {
|
|||
|
||||
/**
|
||||
* struct tmc_drvdata - specifics associated to an TMC component
|
||||
* @pclk: APB clock if present, otherwise NULL
|
||||
* @base: memory mapped base address for this component.
|
||||
* @csdev: component vitals needed by the framework.
|
||||
* @miscdev: specifics to handle "/dev/xyz.tmc" entry.
|
||||
|
@ -189,6 +190,7 @@ struct etr_buf {
|
|||
* @perf_buf: PERF buffer for ETR.
|
||||
*/
|
||||
struct tmc_drvdata {
|
||||
struct clk *pclk;
|
||||
void __iomem *base;
|
||||
struct coresight_device *csdev;
|
||||
struct miscdevice miscdev;
|
||||
|
|
|
@ -5,17 +5,19 @@
|
|||
* Description: CoreSight Trace Port Interface Unit driver
|
||||
*/
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/coresight.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/coresight.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "coresight-priv.h"
|
||||
|
||||
|
@ -52,11 +54,13 @@ DEFINE_CORESIGHT_DEVLIST(tpiu_devs, "tpiu");
|
|||
/*
|
||||
* @base: memory mapped base address for this component.
|
||||
* @atclk: optional clock for the core parts of the TPIU.
|
||||
* @pclk: APB clock if present, otherwise NULL
|
||||
* @csdev: component vitals needed by the framework.
|
||||
*/
|
||||
struct tpiu_drvdata {
|
||||
void __iomem *base;
|
||||
struct clk *atclk;
|
||||
struct clk *pclk;
|
||||
struct coresight_device *csdev;
|
||||
spinlock_t spinlock;
|
||||
};
|
||||
|
@ -122,14 +126,12 @@ static const struct coresight_ops tpiu_cs_ops = {
|
|||
.sink_ops = &tpiu_sink_ops,
|
||||
};
|
||||
|
||||
static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
static int __tpiu_probe(struct device *dev, struct resource *res)
|
||||
{
|
||||
int ret;
|
||||
void __iomem *base;
|
||||
struct device *dev = &adev->dev;
|
||||
struct coresight_platform_data *pdata = NULL;
|
||||
struct tpiu_drvdata *drvdata;
|
||||
struct resource *res = &adev->res;
|
||||
struct coresight_desc desc = { 0 };
|
||||
|
||||
desc.name = coresight_alloc_device_name(&tpiu_devs, dev);
|
||||
|
@ -142,12 +144,16 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
|
||||
spin_lock_init(&drvdata->spinlock);
|
||||
|
||||
drvdata->atclk = devm_clk_get(&adev->dev, "atclk"); /* optional */
|
||||
drvdata->atclk = devm_clk_get(dev, "atclk"); /* optional */
|
||||
if (!IS_ERR(drvdata->atclk)) {
|
||||
ret = clk_prepare_enable(drvdata->atclk);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
drvdata->pclk = coresight_get_enable_apb_pclk(dev);
|
||||
if (IS_ERR(drvdata->pclk))
|
||||
return -ENODEV;
|
||||
dev_set_drvdata(dev, drvdata);
|
||||
|
||||
/* Validity for the resource is already checked by the AMBA core */
|
||||
|
@ -173,21 +179,34 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
desc.dev = dev;
|
||||
drvdata->csdev = coresight_register(&desc);
|
||||
|
||||
if (!IS_ERR(drvdata->csdev)) {
|
||||
pm_runtime_put(&adev->dev);
|
||||
if (!IS_ERR(drvdata->csdev))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return PTR_ERR(drvdata->csdev);
|
||||
}
|
||||
|
||||
static void tpiu_remove(struct amba_device *adev)
|
||||
static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
{
|
||||
struct tpiu_drvdata *drvdata = dev_get_drvdata(&adev->dev);
|
||||
int ret;
|
||||
|
||||
ret = __tpiu_probe(&adev->dev, &adev->res);
|
||||
if (!ret)
|
||||
pm_runtime_put(&adev->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __tpiu_remove(struct device *dev)
|
||||
{
|
||||
struct tpiu_drvdata *drvdata = dev_get_drvdata(dev);
|
||||
|
||||
coresight_unregister(drvdata->csdev);
|
||||
}
|
||||
|
||||
static void tpiu_remove(struct amba_device *adev)
|
||||
{
|
||||
__tpiu_remove(&adev->dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int tpiu_runtime_suspend(struct device *dev)
|
||||
{
|
||||
|
@ -196,6 +215,8 @@ static int tpiu_runtime_suspend(struct device *dev)
|
|||
if (drvdata && !IS_ERR(drvdata->atclk))
|
||||
clk_disable_unprepare(drvdata->atclk);
|
||||
|
||||
if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_disable_unprepare(drvdata->pclk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -206,6 +227,8 @@ static int tpiu_runtime_resume(struct device *dev)
|
|||
if (drvdata && !IS_ERR(drvdata->atclk))
|
||||
clk_prepare_enable(drvdata->atclk);
|
||||
|
||||
if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_prepare_enable(drvdata->pclk);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -245,7 +268,66 @@ static struct amba_driver tpiu_driver = {
|
|||
.id_table = tpiu_ids,
|
||||
};
|
||||
|
||||
module_amba_driver(tpiu_driver);
|
||||
static int tpiu_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
int ret;
|
||||
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
ret = __tpiu_probe(&pdev->dev, res);
|
||||
pm_runtime_put(&pdev->dev);
|
||||
if (ret)
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void tpiu_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tpiu_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
if (WARN_ON(!drvdata))
|
||||
return;
|
||||
|
||||
__tpiu_remove(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
if (!IS_ERR_OR_NULL(drvdata->pclk))
|
||||
clk_put(drvdata->pclk);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id tpiu_acpi_ids[] = {
|
||||
{"ARMHC979", 0, 0, 0}, /* ARM CoreSight TPIU */
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, tpiu_acpi_ids);
|
||||
#endif
|
||||
|
||||
static struct platform_driver tpiu_platform_driver = {
|
||||
.probe = tpiu_platform_probe,
|
||||
.remove_new = tpiu_platform_remove,
|
||||
.driver = {
|
||||
.name = "coresight-tpiu-platform",
|
||||
.acpi_match_table = ACPI_PTR(tpiu_acpi_ids),
|
||||
.suppress_bind_attrs = true,
|
||||
.pm = &tpiu_dev_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init tpiu_init(void)
|
||||
{
|
||||
return coresight_init_driver("tpiu", &tpiu_driver, &tpiu_platform_driver);
|
||||
}
|
||||
|
||||
static void __exit tpiu_exit(void)
|
||||
{
|
||||
coresight_remove_driver(&tpiu_driver, &tpiu_platform_driver);
|
||||
}
|
||||
module_init(tpiu_init);
|
||||
module_exit(tpiu_exit);
|
||||
|
||||
MODULE_AUTHOR("Pratik Patel <pratikp@codeaurora.org>");
|
||||
MODULE_AUTHOR("Mathieu Poirier <mathieu.poirier@linaro.org>");
|
||||
|
|
|
@ -1221,6 +1221,7 @@ static int hisi_ptt_register_pmu(struct hisi_ptt *hisi_ptt)
|
|||
|
||||
hisi_ptt->hisi_ptt_pmu = (struct pmu) {
|
||||
.module = THIS_MODULE,
|
||||
.parent = &hisi_ptt->pdev->dev,
|
||||
.capabilities = PERF_PMU_CAP_EXCLUSIVE | PERF_PMU_CAP_NO_EXCLUDE,
|
||||
.task_ctx_nr = perf_sw_context,
|
||||
.attr_groups = hisi_ptt_pmu_groups,
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
/* Peripheral id registers (0xFD0-0xFEC) */
|
||||
#define CORESIGHT_PERIPHIDR4 0xfd0
|
||||
|
@ -658,4 +659,9 @@ coresight_find_output_type(struct coresight_platform_data *pdata,
|
|||
enum coresight_dev_type type,
|
||||
union coresight_dev_subtype subtype);
|
||||
|
||||
int coresight_init_driver(const char *drv, struct amba_driver *amba_drv,
|
||||
struct platform_driver *pdev_drv);
|
||||
|
||||
void coresight_remove_driver(struct amba_driver *amba_drv,
|
||||
struct platform_driver *pdev_drv);
|
||||
#endif /* _LINUX_COREISGHT_H */
|
||||
|
|
Loading…
Reference in a new issue