Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9983ecbf authored by Charan Teja Reddy's avatar Charan Teja Reddy Committed by Archana Sriram
Browse files

iommu/arm-smmu: override writel_relaxed in smmu global address space



Skip writes to global space of SMMU on targets with slave side
protection where this space was preprogrammed by TZ that need to be
wkept intact.

Change-Id: I03f8ba708144ad9846ec8d6b8a89bd53773bdded
Signed-off-by: default avatarCharan Teja Reddy <charante@codeaurora.org>
Signed-off-by: default avatarVishwanath Raju K <vishk@codeaurora.org>
Signed-off-by: default avatarArchana Sriram <apsrir@codeaurora.org>
parent 0c0b80d0
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -3916,6 +3916,35 @@ static size_t msm_secure_smmu_map_sg(struct iommu_domain *domain,
	return ret;
}

void *get_smmu_from_addr(struct iommu_device *iommu, void __iomem *addr)
{
	struct arm_smmu_device *smmu = NULL;
	unsigned long base, mask;

	smmu = arm_smmu_get_by_fwnode(iommu->fwnode);
	if (!smmu)
		return NULL;

	base = (unsigned long)smmu->base;
	mask = ~(smmu->size - 1);

	if ((base & mask) == ((unsigned long)addr & mask))
		return (void *)smmu;

	return NULL;
}

bool arm_smmu_skip_write(void __iomem *addr)
{
	struct arm_smmu_device *smmu;

	smmu = arm_smmu_get_by_addr(addr);
	if (smmu &&
	    ((unsigned long)addr & (smmu->size - 1)) >= (smmu->size >> 1))
		return false;
	else
		return true;
}
#endif

static int arm_smmu_add_device(struct device *dev)
+23 −0
Original line number Diff line number Diff line
@@ -34,6 +34,9 @@
#include <linux/debugfs.h>
#include <linux/property.h>
#include <trace/events/iommu.h>
#ifdef CONFIG_MSM_TZ_SMMU
#include <soc/qcom/msm_tz_smmu.h>
#endif

static struct kset *iommu_group_kset;
static DEFINE_IDA(iommu_group_ida);
@@ -133,6 +136,26 @@ void iommu_device_unregister(struct iommu_device *iommu)
	spin_unlock(&iommu_device_lock);
}

#ifdef CONFIG_MSM_TZ_SMMU
void *arm_smmu_get_by_addr(void __iomem *addr)
{
	struct iommu_device *iommu;
	unsigned long flags;
	void *smmu = NULL;

	spin_lock_irqsave(&iommu_device_lock, flags);
	list_for_each_entry(iommu, &iommu_device_list, list) {
		smmu = get_smmu_from_addr(iommu, addr);
		if (!smmu)
			continue;
		break;
	}
	spin_unlock_irqrestore(&iommu_device_lock, flags);

	return smmu;
}
#endif

static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,
						 unsigned type);
static int __iommu_attach_device(struct iommu_domain *domain,
+12 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2018,2021, The Linux Foundation. All rights reserved.
 */

#ifndef __MSM_TZ_SMMU_H__
#define __MSM_TZ_SMMU_H__

#include <linux/device.h>
#include <linux/iommu.h>

enum tz_smmu_device_id {
	TZ_DEVICE_START = 0,
@@ -49,6 +50,16 @@ enum tz_smmu_device_id msm_dev_to_device_id(struct device *dev);
int msm_tz_set_cb_format(enum tz_smmu_device_id sec_id, int cbndx);
int msm_iommu_sec_pgtbl_init(void);
int register_iommu_sec_ptbl(void);
bool arm_smmu_skip_write(void __iomem *addr);
extern void *get_smmu_from_addr(struct iommu_device *iommu, void __iomem *addr);
extern void *arm_smmu_get_by_addr(void __iomem *addr);
/* Donot write to smmu global space with CONFIG_MSM_TZ_SMMU */
#undef writel_relaxed
#define writel_relaxed(v, c)	do {					\
	if (!arm_smmu_skip_write(c))					\
		((void)__raw_writel((u32)cpu_to_le32(v), (c)));	\
	} while (0)

#else

static inline int msm_tz_smmu_atos_start(struct device *dev, int cb_num)