coresight: add coresight fuse driver
Add support for CoreSight Fuse driver which can be used by other CoreSight drivers to query the state of the CoreSight fuses to determine if the Hardware they manage is functionally disabled or not. Drivers can then take necessary actions like failing the probe if the Hardware they manage is functionally disabled. Change-Id: I2c2a2af064db750539b0ffa33870ddb7a2832e68 Signed-off-by: Pratik Patel <pratikp@codeaurora.org>
This commit is contained in:
parent
3c2d525dfc
commit
9266be3791
|
@ -21,6 +21,7 @@ Required properties:
|
|||
"qcom,coresight-csr" for coresight csr device,
|
||||
"arm,coresight-cti" for coresight cti devices,
|
||||
"qcom,coresight-hwevent" for coresight hardware event devices
|
||||
"arm,coresight-fuse" for coresight fuse device,
|
||||
- reg : physical base address and length of the register set(s) of the component
|
||||
- reg-names : names corresponding to each reg property value. The reg-names that
|
||||
need to be used with corresponding compatible string for a coresight device
|
||||
|
@ -68,6 +69,10 @@ Required properties:
|
|||
"<ss-mux>" - physical base address of hardware event mux
|
||||
control registers where <ss-mux> is subsystem mux it
|
||||
represents
|
||||
- for coresight fuse device:
|
||||
compatible : should be "arm,coresight-fuse"
|
||||
reg-names : should be:
|
||||
"fuse-base" - physical base address of fuse registers
|
||||
- coresight-id : unique integer identifier for the component
|
||||
- coresight-name : unique descriptive name of the component
|
||||
- coresight-nr-inports : number of input ports on the component
|
||||
|
@ -236,3 +241,13 @@ Examples:
|
|||
|
||||
qcom,hwevent-clks = "core_mmss_clk";
|
||||
};
|
||||
|
||||
fuse: fuse@fc4be024 {
|
||||
compatible = "arm,coresight-fuse";
|
||||
reg = <0xfc4be024 0x8>;
|
||||
reg-names = "fuse-base";
|
||||
|
||||
coresight-id = <30>;
|
||||
coresight-name = "coresight-fuse";
|
||||
coresight-nr-inports = <0>;
|
||||
};
|
||||
|
|
|
@ -24,6 +24,15 @@ if CORESIGHT
|
|||
config HAVE_CORESIGHT_SINK
|
||||
bool
|
||||
|
||||
config CORESIGHT_FUSE
|
||||
bool "CoreSight Fuse driver"
|
||||
help
|
||||
This driver provides support for CoreSight Fuse state checks that
|
||||
other CoreSight drivers can query to determine existence of
|
||||
Hardware functionality they support. Drivers can then take necessary
|
||||
actions like failing the probe if the Hardware they manage is
|
||||
functionally disabled.
|
||||
|
||||
config CORESIGHT_CTI
|
||||
bool "CoreSight Cross Trigger Interface driver"
|
||||
help
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
# Makefile for CoreSight drivers.
|
||||
#
|
||||
obj-$(CONFIG_CORESIGHT) += coresight.o
|
||||
obj-$(CONFIG_CORESIGHT_FUSE) += coresight-fuse.o
|
||||
obj-$(CONFIG_CORESIGHT_CTI) += coresight-cti.o
|
||||
obj-$(CONFIG_CORESIGHT_CSR) += coresight-csr.o
|
||||
obj-$(CONFIG_CORESIGHT_TMC) += coresight-tmc.o
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_coresight.h>
|
||||
#include <linux/coresight.h>
|
||||
|
||||
#include "coresight-priv.h"
|
||||
|
||||
#define fuse_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
|
||||
#define fuse_readl(drvdata, off) __raw_readl(drvdata->base + off)
|
||||
|
||||
#define OEM_CONFIG0 (0x000)
|
||||
#define OEM_CONFIG1 (0x004)
|
||||
|
||||
#define ALL_DEBUG_DISABLE BIT(21)
|
||||
#define APPS_DBGEN_DISABLE BIT(0)
|
||||
#define APPS_NIDEN_DISABLE BIT(1)
|
||||
#define APPS_SPIDEN_DISABLE BIT(2)
|
||||
#define APPS_SPNIDEN_DISABLE BIT(3)
|
||||
#define DAP_DBGEN_DISABLE BIT(4)
|
||||
#define DAP_NIDEN_DISABLE BIT(5)
|
||||
#define DAP_SPIDEN_DISABLE BIT(6)
|
||||
#define DAP_SPNIDEN_DISABLE BIT(7)
|
||||
#define DAP_DEVICEEN_DISABLE BIT(8)
|
||||
|
||||
struct fuse_drvdata {
|
||||
void __iomem *base;
|
||||
struct device *dev;
|
||||
struct coresight_device *csdev;
|
||||
};
|
||||
|
||||
static struct fuse_drvdata *fusedrvdata;
|
||||
|
||||
bool coresight_fuse_access_disabled(void)
|
||||
{
|
||||
struct fuse_drvdata *drvdata = fusedrvdata;
|
||||
uint32_t config0, config1;
|
||||
bool ret;
|
||||
|
||||
config0 = fuse_readl(drvdata, OEM_CONFIG0);
|
||||
config1 = fuse_readl(drvdata, OEM_CONFIG1);
|
||||
|
||||
dev_dbg(drvdata->dev, "config0: %lx\n", (unsigned long)config0);
|
||||
dev_dbg(drvdata->dev, "config1: %lx\n", (unsigned long)config1);
|
||||
|
||||
if (config0 & ALL_DEBUG_DISABLE)
|
||||
ret = true;
|
||||
else if (config1 & DAP_DBGEN_DISABLE)
|
||||
ret = true;
|
||||
else if (config1 & DAP_NIDEN_DISABLE)
|
||||
ret = true;
|
||||
else if (config1 & DAP_SPIDEN_DISABLE)
|
||||
ret = true;
|
||||
else if (config1 & DAP_SPNIDEN_DISABLE)
|
||||
ret = true;
|
||||
else if (config1 & DAP_DEVICEEN_DISABLE)
|
||||
ret = true;
|
||||
else
|
||||
ret = false;
|
||||
|
||||
if (ret)
|
||||
dev_dbg(drvdata->dev, "coresight fuse disabled\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(coresight_fuse_access_disabled);
|
||||
|
||||
bool coresight_fuse_apps_access_disabled(void)
|
||||
{
|
||||
struct fuse_drvdata *drvdata = fusedrvdata;
|
||||
uint32_t config0, config1;
|
||||
bool ret;
|
||||
|
||||
config0 = fuse_readl(drvdata, OEM_CONFIG0);
|
||||
config1 = fuse_readl(drvdata, OEM_CONFIG1);
|
||||
|
||||
dev_dbg(drvdata->dev, "apps config0: %lx\n", (unsigned long)config0);
|
||||
dev_dbg(drvdata->dev, "apps config1: %lx\n", (unsigned long)config1);
|
||||
|
||||
if (config0 & ALL_DEBUG_DISABLE)
|
||||
ret = true;
|
||||
else if (config1 & APPS_DBGEN_DISABLE)
|
||||
ret = true;
|
||||
else if (config1 & APPS_NIDEN_DISABLE)
|
||||
ret = true;
|
||||
else if (config1 & APPS_SPIDEN_DISABLE)
|
||||
ret = true;
|
||||
else if (config1 & APPS_SPNIDEN_DISABLE)
|
||||
ret = true;
|
||||
else if (config1 & DAP_DEVICEEN_DISABLE)
|
||||
ret = true;
|
||||
else
|
||||
ret = false;
|
||||
|
||||
if (ret)
|
||||
dev_dbg(drvdata->dev, "apps fuse disabled\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(coresight_fuse_apps_access_disabled);
|
||||
|
||||
static int __devinit fuse_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct coresight_platform_data *pdata;
|
||||
struct fuse_drvdata *drvdata;
|
||||
struct resource *res;
|
||||
struct coresight_desc *desc;
|
||||
|
||||
if (pdev->dev.of_node) {
|
||||
pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
|
||||
if (IS_ERR(pdata))
|
||||
return PTR_ERR(pdata);
|
||||
pdev->dev.platform_data = pdata;
|
||||
}
|
||||
|
||||
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
/* Store the driver data pointer for use in exported functions */
|
||||
fusedrvdata = drvdata;
|
||||
drvdata->dev = &pdev->dev;
|
||||
platform_set_drvdata(pdev, drvdata);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fuse-base");
|
||||
if (!res)
|
||||
return -ENODEV;
|
||||
|
||||
drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
|
||||
if (!drvdata->base)
|
||||
return -ENOMEM;
|
||||
|
||||
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
|
||||
if (!desc)
|
||||
return -ENOMEM;
|
||||
desc->type = CORESIGHT_DEV_TYPE_NONE;
|
||||
desc->pdata = pdev->dev.platform_data;
|
||||
desc->dev = &pdev->dev;
|
||||
desc->owner = THIS_MODULE;
|
||||
drvdata->csdev = coresight_register(desc);
|
||||
if (IS_ERR(drvdata->csdev))
|
||||
return PTR_ERR(drvdata->csdev);
|
||||
|
||||
dev_info(dev, "Fuse initialized\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit fuse_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct fuse_drvdata *drvdata = platform_get_drvdata(pdev);
|
||||
|
||||
coresight_unregister(drvdata->csdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id fuse_match[] = {
|
||||
{.compatible = "arm,coresight-fuse"},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver fuse_driver = {
|
||||
.probe = fuse_probe,
|
||||
.remove = __devexit_p(fuse_remove),
|
||||
.driver = {
|
||||
.name = "coresight-fuse",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = fuse_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init fuse_init(void)
|
||||
{
|
||||
return platform_driver_register(&fuse_driver);
|
||||
}
|
||||
module_init(fuse_init);
|
||||
|
||||
static void __exit fuse_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&fuse_driver);
|
||||
}
|
||||
module_exit(fuse_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("CoreSight Fuse driver");
|
|
@ -36,6 +36,13 @@
|
|||
#define BMVAL(val, lsb, msb) ((val & BM(lsb, msb)) >> lsb)
|
||||
#define BVAL(val, n) ((val & BIT(n)) >> n)
|
||||
|
||||
#ifdef CONFIG_CORESIGHT_FUSE
|
||||
extern bool coresight_fuse_access_disabled(void);
|
||||
extern bool coresight_fuse_apps_access_disabled(void);
|
||||
#else
|
||||
static inline bool coresight_fuse_access_disabled(void) { return false; }
|
||||
static inline bool coresight_fuse_apps_access_disabled(void) { return false; }
|
||||
#endif
|
||||
#ifdef CONFIG_CORESIGHT_CSR
|
||||
extern void msm_qdss_csr_enable_bam_to_usb(void);
|
||||
extern void msm_qdss_csr_disable_bam_to_usb(void);
|
||||
|
|
Loading…
Reference in New Issue