mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 14:19:09 -04:00
iommu: arm-smmu: add capturebus support for smmuv500
add a debugfs interface under /sys/kernel/debug/iommu/capturebus to support capture bus for smmuv500. Change-Id: Ibf2a2daf87941387c1b3f990f05d86a1cd4dbfff Signed-off-by: Vijayanand Jitta <vjitta@codeaurora.org> [guptap@codeaurora.org: refactored implementation] Signed-off-by: Prakash Gupta <guptap@codeaurora.org>
This commit is contained in:
parent
5168327a4f
commit
38edc27806
4 changed files with 476 additions and 11 deletions
|
|
@ -223,3 +223,66 @@ void arm_smmu_debug_dump_tcu_testbus(struct device *dev, phys_addr_t phys_addr,
|
|||
arm_smmu_debug_tcu_testbus_select(phys_addr, tcu_base,
|
||||
CLK_TESTBUS, READ, 0));
|
||||
}
|
||||
|
||||
void arm_smmu_debug_set_tnx_tcr_cntl(void __iomem *tbu_base, u64 val)
|
||||
{
|
||||
u64 tcr_cntl_val = readq_relaxed(tbu_base + TNX_TCR_CNTL);
|
||||
|
||||
/* Don't override OT_CAPTURE configuration*/
|
||||
if (!(tcr_cntl_val & TNX_TCR_CNTL_TBU_OT_CAPTURE_EN))
|
||||
writeq_relaxed(val, tbu_base + TNX_TCR_CNTL);
|
||||
else
|
||||
pr_err_ratelimited("OT capture enbl, skip TCR CNTL write\n");
|
||||
}
|
||||
|
||||
u64 arm_smmu_debug_get_tnx_tcr_cntl(void __iomem *tbu_base)
|
||||
{
|
||||
return readq_relaxed(tbu_base + TNX_TCR_CNTL);
|
||||
}
|
||||
|
||||
void arm_smmu_debug_set_mask_and_match(void __iomem *tbu_base, u64 sel,
|
||||
u64 mask, u64 match)
|
||||
{
|
||||
writeq_relaxed(mask, tbu_base + ARM_SMMU_CAPTURE1_MASK(sel));
|
||||
writeq_relaxed(match, tbu_base + ARM_SMMU_CAPTURE1_MATCH(sel));
|
||||
}
|
||||
|
||||
void arm_smmu_debug_get_mask_and_match(void __iomem *tbu_base, u64 *mask,
|
||||
u64 *match)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NO_OF_MASK_AND_MATCH; ++i) {
|
||||
mask[i] = readq_relaxed(tbu_base +
|
||||
ARM_SMMU_CAPTURE1_MASK(i+1));
|
||||
match[i] = readq_relaxed(tbu_base +
|
||||
ARM_SMMU_CAPTURE1_MATCH(i+1));
|
||||
}
|
||||
}
|
||||
|
||||
void arm_smmu_debug_get_capture_snapshot(void __iomem *tbu_base,
|
||||
u64 snapshot[NO_OF_CAPTURE_POINTS][REGS_PER_CAPTURE_POINT])
|
||||
{
|
||||
int i, j;
|
||||
u64 valid;
|
||||
|
||||
valid = readl_relaxed(tbu_base + TNX_TCR_CNTL_2);
|
||||
|
||||
for (i = 0; i < NO_OF_CAPTURE_POINTS ; ++i) {
|
||||
if (valid & BIT(i))
|
||||
for (j = 0; j < REGS_PER_CAPTURE_POINT; ++j)
|
||||
snapshot[i][j] = readq_relaxed(tbu_base +
|
||||
ARM_SMMU_CAPTURE_SNAPSHOT(i, j));
|
||||
else
|
||||
for (j = 0; j < REGS_PER_CAPTURE_POINT; ++j)
|
||||
snapshot[i][j] = 0xdededede;
|
||||
}
|
||||
}
|
||||
|
||||
void arm_smmu_debug_clear_intr_and_validbits(void __iomem *tbu_base)
|
||||
{
|
||||
u64 val = 0;
|
||||
|
||||
val |= INTR_CLR | RESET_VALID;
|
||||
writeq_relaxed(val, tbu_base + TNX_TCR_CNTL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,28 @@
|
|||
extern int tbu_testbus_sel;
|
||||
extern int tcu_testbus_sel;
|
||||
|
||||
#define TNX_TCR_CNTL 0x130
|
||||
#define TNX_TCR_CNTL_TBU_OT_CAPTURE_EN BIT(18)
|
||||
#define TNX_TCR_CNTL_ALWAYS_CAPTURE BIT(15)
|
||||
#define TNX_TCR_CNTL_MATCH_MASK_UPD BIT(7)
|
||||
#define TNX_TCR_CNTL_MATCH_MASK_VALID BIT(6)
|
||||
|
||||
#define CAPTURE1_SNAPSHOT_1 0x138
|
||||
|
||||
#define TNX_TCR_CNTL_2 0x178
|
||||
#define TNX_TCR_CNTL_2_CAP1_VALID BIT(0)
|
||||
|
||||
#define ARM_SMMU_CAPTURE1_MASK(i) (0x100 + (0x8 * (i-1)))
|
||||
#define ARM_SMMU_CAPTURE1_MATCH(i) (0x118 + (0x8 * (i-1)))
|
||||
#define ARM_SMMU_CAPTURE_SNAPSHOT(i, j) (CAPTURE1_SNAPSHOT_1 + \
|
||||
(0x10 * (i)) + ((j) * 0x8))
|
||||
|
||||
#define NO_OF_MASK_AND_MATCH 0x3
|
||||
#define NO_OF_CAPTURE_POINTS 0x4
|
||||
#define REGS_PER_CAPTURE_POINT 0x2
|
||||
#define INTR_CLR BIT(0)
|
||||
#define RESET_VALID BIT(7)
|
||||
|
||||
enum tcu_testbus {
|
||||
PTW_AND_CACHE_TESTBUS,
|
||||
CLK_TESTBUS,
|
||||
|
|
@ -66,7 +88,15 @@ void arm_smmu_debug_dump_tbu_testbus(struct device *dev, void __iomem *tbu_base,
|
|||
int tbu_testbus_sel);
|
||||
void arm_smmu_debug_dump_tcu_testbus(struct device *dev, phys_addr_t phys_addr,
|
||||
void __iomem *tcu_base, int tcu_testbus_sel);
|
||||
|
||||
void arm_smmu_debug_set_tnx_tcr_cntl(void __iomem *tbu_base, u64 val);
|
||||
u64 arm_smmu_debug_get_tnx_tcr_cntl(void __iomem *tbu_base);
|
||||
void arm_smmu_debug_set_mask_and_match(void __iomem *tbu_base, u64 sel,
|
||||
u64 mask, u64 match);
|
||||
void arm_smmu_debug_get_mask_and_match(void __iomem *tbu_base,
|
||||
u64 *mask, u64 *match);
|
||||
void arm_smmu_debug_get_capture_snapshot(void __iomem *tbu_base,
|
||||
u64 snapshot[NO_OF_CAPTURE_POINTS][REGS_PER_CAPTURE_POINT]);
|
||||
void arm_smmu_debug_clear_intr_and_validbits(void __iomem *tbu_base);
|
||||
#else
|
||||
static inline u32 arm_smmu_debug_tbu_testbus_select(void __iomem *tbu_base,
|
||||
bool write, u32 val)
|
||||
|
|
@ -95,5 +125,30 @@ static inline void arm_smmu_debug_dump_tcu_testbus(struct device *dev,
|
|||
int tcu_testbus_sel)
|
||||
{
|
||||
}
|
||||
static inline void arm_smmu_debug_set_tnx_tcr_cntl(void __iomem *tbu_base,
|
||||
u64 val)
|
||||
{
|
||||
}
|
||||
static inline u64 arm_smmu_debug_get_tnx_tcr_cntl(void __iomem *tbu_base)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void arm_smmu_debug_set_mask_and_match(void __iomem *tbu_base, u64
|
||||
sel, u64 mask, u64 match)
|
||||
{
|
||||
}
|
||||
static inline void arm_smmu_debug_get_mask_and_match(void __iomem *tbu_base,
|
||||
u64 *mask, u64 *match)
|
||||
{
|
||||
}
|
||||
static inline void arm_smmu_debug_get_capture_snapshot(void __iomem *tbu_base,
|
||||
u64 snapshot[NO_OF_CAPTURE_POINTS][REGS_PER_CAPTURE_POINT])
|
||||
{
|
||||
}
|
||||
static inline void arm_smmu_debug_clear_intr_and_validbits(void __iomem
|
||||
*tbu_base)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/of.h>
|
||||
|
|
@ -378,16 +379,6 @@ static const struct arm_smmu_impl qcom_smmu_impl = {
|
|||
|
||||
#define TBU_DBG_TIMEOUT_US 100
|
||||
|
||||
#define TNX_TCR_CNTL 0x130
|
||||
#define TNX_TCR_CNTL_TBU_OT_CAPTURE_EN BIT(18)
|
||||
#define TNX_TCR_CNTL_ALWAYS_CAPTURE BIT(15)
|
||||
#define TNX_TCR_CNTL_MATCH_MASK_UPD BIT(7)
|
||||
#define TNX_TCR_CNTL_MATCH_MASK_VALID BIT(6)
|
||||
|
||||
#define CAPTURE1_SNAPSHOT_1 0x138
|
||||
|
||||
#define TNX_TCR_CNTL_2 0x178
|
||||
#define TNX_TCR_CNTL_2_CAP1_VALID BIT(0)
|
||||
|
||||
struct actlr_setting {
|
||||
struct arm_smmu_smr smr;
|
||||
|
|
@ -426,6 +417,10 @@ static struct qsmmuv500_tbu_device *qsmmuv500_find_tbu(
|
|||
static DEFINE_MUTEX(capture_reg_lock);
|
||||
static DEFINE_SPINLOCK(testbus_lock);
|
||||
|
||||
#ifdef CONFIG_IOMMU_DEBUGFS
|
||||
static struct dentry *debugfs_capturebus_dir;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARM_SMMU_TESTBUS_DEBUGFS
|
||||
static struct dentry *debugfs_testbus_dir;
|
||||
|
||||
|
|
@ -829,6 +824,325 @@ bug:
|
|||
BUG_ON(IS_ENABLED(CONFIG_IOMMU_TLBSYNC_DEBUG));
|
||||
}
|
||||
|
||||
static ssize_t arm_smmu_debug_capturebus_snapshot_read(struct file *file,
|
||||
char __user *ubuf, size_t count, loff_t *offset)
|
||||
{
|
||||
struct qsmmuv500_tbu_device *tbu = file->private_data;
|
||||
struct arm_smmu_device *smmu = tbu->smmu;
|
||||
void __iomem *tbu_base = tbu->base;
|
||||
u64 snapshot[NO_OF_CAPTURE_POINTS][REGS_PER_CAPTURE_POINT];
|
||||
char buf[400];
|
||||
ssize_t retval;
|
||||
size_t buflen;
|
||||
int buf_len = sizeof(buf);
|
||||
int i, j;
|
||||
|
||||
if (*offset)
|
||||
return 0;
|
||||
|
||||
memset(buf, 0, buf_len);
|
||||
|
||||
if (arm_smmu_power_on(smmu->pwr))
|
||||
return -EINVAL;
|
||||
|
||||
if (arm_smmu_power_on(tbu->pwr)) {
|
||||
arm_smmu_power_off(smmu, smmu->pwr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!mutex_trylock(&capture_reg_lock)) {
|
||||
dev_warn_ratelimited(smmu->dev,
|
||||
"capture bus regs in use, not dumping it.\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
arm_smmu_debug_get_capture_snapshot(tbu_base, snapshot);
|
||||
|
||||
mutex_unlock(&capture_reg_lock);
|
||||
arm_smmu_power_off(tbu->smmu, tbu->pwr);
|
||||
arm_smmu_power_off(smmu, smmu->pwr);
|
||||
|
||||
for (i = 0; i < NO_OF_CAPTURE_POINTS ; ++i) {
|
||||
for (j = 0; j < REGS_PER_CAPTURE_POINT; ++j) {
|
||||
scnprintf(buf + strlen(buf), buf_len - strlen(buf),
|
||||
"Capture_%d_Snapshot_%d : 0x%0llx\n",
|
||||
i+1, j+1, snapshot[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
buflen = min(count, strlen(buf));
|
||||
if (copy_to_user(ubuf, buf, buflen)) {
|
||||
dev_err_ratelimited(smmu->dev, "Couldn't copy_to_user\n");
|
||||
retval = -EFAULT;
|
||||
} else {
|
||||
*offset = 1;
|
||||
retval = buflen;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static const struct file_operations arm_smmu_debug_capturebus_snapshot_fops = {
|
||||
.open = simple_open,
|
||||
.read = arm_smmu_debug_capturebus_snapshot_read,
|
||||
};
|
||||
|
||||
static ssize_t arm_smmu_debug_capturebus_config_write(struct file *file,
|
||||
const char __user *ubuf, size_t count, loff_t *offset)
|
||||
{
|
||||
struct qsmmuv500_tbu_device *tbu = file->private_data;
|
||||
struct arm_smmu_device *smmu = tbu->smmu;
|
||||
void __iomem *tbu_base = tbu->base;
|
||||
char *comma1, *comma2;
|
||||
char buf[100];
|
||||
u64 sel, mask, match, val;
|
||||
|
||||
if (count >= sizeof(buf)) {
|
||||
dev_err_ratelimited(smmu->dev, "Input too large\n");
|
||||
goto invalid_format;
|
||||
}
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (copy_from_user(buf, ubuf, count)) {
|
||||
dev_err_ratelimited(smmu->dev, "Couldn't copy from user\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
comma1 = strnchr(buf, count, ',');
|
||||
if (!comma1)
|
||||
goto invalid_format;
|
||||
|
||||
*comma1 = '\0';
|
||||
|
||||
if (kstrtou64(buf, 0, &sel))
|
||||
goto invalid_format;
|
||||
|
||||
if (sel > 4) {
|
||||
goto invalid_format;
|
||||
} else if (sel == 4) {
|
||||
if (kstrtou64(comma1 + 1, 0, &val))
|
||||
goto invalid_format;
|
||||
goto program_capturebus;
|
||||
}
|
||||
|
||||
comma2 = strnchr(comma1 + 1, count, ',');
|
||||
if (!comma2)
|
||||
goto invalid_format;
|
||||
|
||||
/* split up the words */
|
||||
*comma2 = '\0';
|
||||
|
||||
if (kstrtou64(comma1 + 1, 0, &mask))
|
||||
goto invalid_format;
|
||||
|
||||
if (kstrtou64(comma2 + 1, 0, &match))
|
||||
goto invalid_format;
|
||||
|
||||
program_capturebus:
|
||||
if (arm_smmu_power_on(smmu->pwr))
|
||||
return -EINVAL;
|
||||
|
||||
if (arm_smmu_power_on(tbu->pwr)) {
|
||||
arm_smmu_power_off(smmu, smmu->pwr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!mutex_trylock(&capture_reg_lock)) {
|
||||
dev_warn_ratelimited(smmu->dev,
|
||||
"capture bus regs in use, not configuring it.\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (sel == 4)
|
||||
arm_smmu_debug_set_tnx_tcr_cntl(tbu_base, val);
|
||||
else
|
||||
arm_smmu_debug_set_mask_and_match(tbu_base, sel, mask, match);
|
||||
|
||||
mutex_unlock(&capture_reg_lock);
|
||||
arm_smmu_power_off(tbu->smmu, tbu->pwr);
|
||||
arm_smmu_power_off(smmu, smmu->pwr);
|
||||
|
||||
return count;
|
||||
|
||||
invalid_format:
|
||||
dev_err_ratelimited(smmu->dev, "Invalid format\n");
|
||||
dev_err_ratelimited(smmu->dev,
|
||||
"Expected:<1/2/3,Mask,Match> <4,TNX_TCR_CNTL>\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static ssize_t arm_smmu_debug_capturebus_config_read(struct file *file,
|
||||
char __user *ubuf, size_t count, loff_t *offset)
|
||||
{
|
||||
struct qsmmuv500_tbu_device *tbu = file->private_data;
|
||||
struct arm_smmu_device *smmu = tbu->smmu;
|
||||
void __iomem *tbu_base = tbu->base;
|
||||
u64 val;
|
||||
u64 mask[NO_OF_MASK_AND_MATCH], match[NO_OF_MASK_AND_MATCH];
|
||||
char buf[400];
|
||||
ssize_t retval;
|
||||
size_t buflen;
|
||||
int buf_len = sizeof(buf);
|
||||
int i;
|
||||
|
||||
if (*offset)
|
||||
return 0;
|
||||
|
||||
memset(buf, 0, buf_len);
|
||||
|
||||
if (arm_smmu_power_on(smmu->pwr))
|
||||
return -EINVAL;
|
||||
|
||||
if (arm_smmu_power_on(tbu->pwr)) {
|
||||
arm_smmu_power_off(smmu, smmu->pwr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!mutex_trylock(&capture_reg_lock)) {
|
||||
dev_warn_ratelimited(smmu->dev,
|
||||
"capture bus regs in use, not configuring it.\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
arm_smmu_debug_get_mask_and_match(tbu_base,
|
||||
mask, match);
|
||||
val = arm_smmu_debug_get_tnx_tcr_cntl(tbu_base);
|
||||
|
||||
mutex_unlock(&capture_reg_lock);
|
||||
arm_smmu_power_off(tbu->smmu, tbu->pwr);
|
||||
arm_smmu_power_off(smmu, smmu->pwr);
|
||||
|
||||
for (i = 0; i < NO_OF_MASK_AND_MATCH; ++i) {
|
||||
scnprintf(buf + strlen(buf), buf_len - strlen(buf),
|
||||
"Mask_%d : 0x%0llx\t", i+1, mask[i]);
|
||||
scnprintf(buf + strlen(buf), buf_len - strlen(buf),
|
||||
"Match_%d : 0x%0llx\n", i+1, match[i]);
|
||||
}
|
||||
scnprintf(buf + strlen(buf), buf_len - strlen(buf), "0x%0lx\n", val);
|
||||
|
||||
buflen = min(count, strlen(buf));
|
||||
if (copy_to_user(ubuf, buf, buflen)) {
|
||||
dev_err_ratelimited(smmu->dev, "Couldn't copy_to_user\n");
|
||||
retval = -EFAULT;
|
||||
} else {
|
||||
*offset = 1;
|
||||
retval = buflen;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static const struct file_operations arm_smmu_debug_capturebus_config_fops = {
|
||||
.open = simple_open,
|
||||
.write = arm_smmu_debug_capturebus_config_write,
|
||||
.read = arm_smmu_debug_capturebus_config_read,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IOMMU_DEBUGFS
|
||||
static int qsmmuv500_capturebus_init(struct qsmmuv500_tbu_device *tbu)
|
||||
{
|
||||
struct dentry *capturebus_dir;
|
||||
|
||||
if (!iommu_debugfs_dir)
|
||||
return 0;
|
||||
|
||||
if (!debugfs_capturebus_dir) {
|
||||
debugfs_capturebus_dir = debugfs_create_dir(
|
||||
"capturebus", iommu_debugfs_dir);
|
||||
if (IS_ERR(debugfs_capturebus_dir)) {
|
||||
dev_err_ratelimited(tbu->dev, "Couldn't create iommu/capturebus debugfs directory\n");
|
||||
return PTR_ERR(debugfs_capturebus_dir);
|
||||
}
|
||||
}
|
||||
|
||||
capturebus_dir = debugfs_create_dir(dev_name(tbu->dev),
|
||||
debugfs_capturebus_dir);
|
||||
if (IS_ERR(capturebus_dir)) {
|
||||
dev_err_ratelimited(tbu->dev, "Couldn't create iommu/capturebus/%s debugfs directory\n",
|
||||
dev_name(tbu->dev));
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (IS_ERR(debugfs_create_file("config", 0400, capturebus_dir, tbu,
|
||||
&arm_smmu_debug_capturebus_config_fops))) {
|
||||
dev_err_ratelimited(tbu->dev, "Couldn't create iommu/capturebus/%s/config debugfs file\n",
|
||||
dev_name(tbu->dev));
|
||||
goto err_rmdir;
|
||||
}
|
||||
|
||||
if (IS_ERR(debugfs_create_file("snapshot", 0400, capturebus_dir, tbu,
|
||||
&arm_smmu_debug_capturebus_snapshot_fops))) {
|
||||
dev_err_ratelimited(tbu->dev, "Couldn't create iommu/capturebus/%s/snapshot debugfs file\n",
|
||||
dev_name(tbu->dev));
|
||||
goto err_rmdir;
|
||||
}
|
||||
return 0;
|
||||
err_rmdir:
|
||||
debugfs_remove_recursive(capturebus_dir);
|
||||
err:
|
||||
return -ENODEV;
|
||||
}
|
||||
#else
|
||||
static int qsmmuv500_capturebus_init(struct qsmmuv500_tbu_device *tbu)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static irqreturn_t arm_smmu_debug_capture_bus_match(int irq, void *dev)
|
||||
{
|
||||
struct qsmmuv500_tbu_device *tbu = dev;
|
||||
struct arm_smmu_device *smmu = tbu->smmu;
|
||||
void __iomem *tbu_base = tbu->base;
|
||||
u64 mask[NO_OF_MASK_AND_MATCH], match[NO_OF_MASK_AND_MATCH];
|
||||
u64 snapshot[NO_OF_CAPTURE_POINTS][REGS_PER_CAPTURE_POINT];
|
||||
int i, j;
|
||||
u64 val;
|
||||
|
||||
if (arm_smmu_power_on(smmu->pwr))
|
||||
return IRQ_NONE;
|
||||
|
||||
if (arm_smmu_power_on(tbu->pwr)) {
|
||||
arm_smmu_power_off(smmu, smmu->pwr);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
if (!mutex_trylock(&capture_reg_lock)) {
|
||||
dev_warn_ratelimited(smmu->dev,
|
||||
"capture bus regs in use, not dumping it.\n");
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
val = arm_smmu_debug_get_tnx_tcr_cntl(tbu_base);
|
||||
arm_smmu_debug_get_mask_and_match(tbu_base, mask, match);
|
||||
arm_smmu_debug_get_capture_snapshot(tbu_base, snapshot);
|
||||
arm_smmu_debug_clear_intr_and_validbits(tbu_base);
|
||||
|
||||
mutex_unlock(&capture_reg_lock);
|
||||
arm_smmu_power_off(tbu->smmu, tbu->pwr);
|
||||
arm_smmu_power_off(smmu, smmu->pwr);
|
||||
|
||||
dev_info(tbu->dev, "TNX_TCR_CNTL : 0x%0llx\n", val);
|
||||
|
||||
for (i = 0; i < NO_OF_MASK_AND_MATCH; ++i) {
|
||||
dev_info(tbu->dev,
|
||||
"Mask_%d : 0x%0llx\n", i+1, mask[i]);
|
||||
dev_info(tbu->dev,
|
||||
"Match_%d : 0x%0llx\n", i+1, match[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < NO_OF_CAPTURE_POINTS ; ++i) {
|
||||
for (j = 0; j < REGS_PER_CAPTURE_POINT; ++j) {
|
||||
dev_info(tbu->dev,
|
||||
"Capture_%d_Snapshot_%d : 0x%0llx\n",
|
||||
i+1, j+1, snapshot[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void qsmmuv500_tlb_sync_timeout(struct arm_smmu_device *smmu)
|
||||
{
|
||||
u32 sync_inv_ack, tbu_pwr_status, sync_inv_progress;
|
||||
|
|
@ -1385,8 +1699,11 @@ static void qsmmuv500_init_cb(struct arm_smmu_domain *smmu_domain,
|
|||
|
||||
static int qsmmuv500_tbu_register(struct device *dev, void *cookie)
|
||||
{
|
||||
struct resource *res;
|
||||
struct qsmmuv500_tbu_device *tbu;
|
||||
struct qsmmuv500_archdata *data = cookie;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
int i, err, num_irqs = 0;
|
||||
|
||||
if (!dev->driver) {
|
||||
dev_err(dev, "TBU failed probe, QSMMUV500 cannot continue!\n");
|
||||
|
|
@ -1399,7 +1716,36 @@ static int qsmmuv500_tbu_register(struct device *dev, void *cookie)
|
|||
tbu->smmu = &data->smmu;
|
||||
list_add(&tbu->list, &data->tbus);
|
||||
|
||||
while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, num_irqs)))
|
||||
num_irqs++;
|
||||
|
||||
tbu->irqs = devm_kzalloc(dev, sizeof(*tbu->irqs) * num_irqs,
|
||||
GFP_KERNEL);
|
||||
if (!tbu->irqs)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < num_irqs; ++i) {
|
||||
int irq = platform_get_irq(pdev, i);
|
||||
|
||||
if (irq < 0) {
|
||||
dev_err(dev, "failed to get irq index %d\n", i);
|
||||
return -ENODEV;
|
||||
}
|
||||
tbu->irqs[i] = irq;
|
||||
|
||||
err = devm_request_threaded_irq(tbu->dev, tbu->irqs[i],
|
||||
NULL, arm_smmu_debug_capture_bus_match,
|
||||
IRQF_ONESHOT | IRQF_SHARED,
|
||||
"capture bus", tbu);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to request capture bus irq%d (%u)\n",
|
||||
i, tbu->irqs[i]);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
qsmmuv500_tbu_testbus_init(tbu);
|
||||
qsmmuv500_capturebus_init(tbu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -418,6 +418,7 @@ struct qsmmuv500_tbu_device {
|
|||
/* Protects halt count */
|
||||
spinlock_t halt_lock;
|
||||
u32 halt_count;
|
||||
unsigned int *irqs;
|
||||
};
|
||||
|
||||
struct arm_smmu_master_cfg {
|
||||
|
|
|
|||
Loading…
Reference in a new issue