mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-13 00:00:00 -04:00
iommu/arm-smmu: Add implementation infrastructure
Add some nascent infrastructure for handling implementation-specific
details outside the flow of the architectural code. This will allow us
to keep mutually-incompatible vendor-specific hooks in their own files
where the respective interested parties can maintain them with minimal
chance of conflicts. As somewhat of a template, we'll start with a
general place to collect the relatively trivial existing quirks.
Change-Id: Ie1ee37e9250a8295bc07cb78d879b98452f50920
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Will Deacon <will@kernel.org>
Git-commit: fc058d37b3
Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
[isaacm@codeaurora.org: resolved merge conflics and build errors]
Signed-off-by: Isaac J. Manjarres <isaacm@codeaurora.org>
This commit is contained in:
parent
e0ced41cce
commit
2027b20101
5 changed files with 164 additions and 138 deletions
|
|
@ -1350,8 +1350,7 @@ M: Will Deacon <will@kernel.org>
|
|||
R: Robin Murphy <robin.murphy@arm.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: drivers/iommu/arm-smmu.c
|
||||
F: drivers/iommu/arm-smmu-v3.c
|
||||
F: drivers/iommu/arm-smmu*
|
||||
F: drivers/iommu/io-pgtable-arm.c
|
||||
F: drivers/iommu/io-pgtable-arm-v7s.c
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
|
|||
obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
|
||||
obj-$(CONFIG_AMD_IOMMU_DEBUGFS) += amd_iommu_debugfs.o
|
||||
obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
|
||||
obj-$(CONFIG_ARM_SMMU) += arm-smmu.o
|
||||
obj-$(CONFIG_ARM_SMMU) += arm-smmu.o arm-smmu-impl.o
|
||||
obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o
|
||||
obj-$(CONFIG_DMAR_TABLE) += dmar.o
|
||||
obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o intel-pasid.o
|
||||
|
|
|
|||
13
drivers/iommu/arm-smmu-impl.c
Normal file
13
drivers/iommu/arm-smmu-impl.c
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// Miscellaneous Arm SMMU implementation and integration quirks
|
||||
// Copyright (C) 2019 Arm Limited
|
||||
|
||||
#define pr_fmt(fmt) "arm-smmu: " fmt
|
||||
|
||||
#include "arm-smmu.h"
|
||||
|
||||
|
||||
struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu)
|
||||
{
|
||||
return smmu;
|
||||
}
|
||||
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/acpi_iort.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
|
|
@ -32,7 +31,6 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/io-64-nonatomic-hi-lo.h>
|
||||
#include <linux/io-pgtable.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/interconnect.h>
|
||||
|
|
@ -45,7 +43,6 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <soc/qcom/secure_buffer.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/irq.h>
|
||||
|
|
@ -83,9 +80,6 @@
|
|||
#define ARM_SMMU_IMPL_DEF1(smmu) \
|
||||
((smmu)->base + (6 * (1 << (smmu)->pgshift)))
|
||||
|
||||
/* Maximum number of context banks per SMMU */
|
||||
#define ARM_SMMU_MAX_CBS 128
|
||||
|
||||
#define MSI_IOVA_BASE 0x8000000
|
||||
#define MSI_IOVA_LENGTH 0x100000
|
||||
|
||||
|
|
@ -107,25 +101,6 @@ module_param(disable_bypass, bool, S_IRUGO);
|
|||
MODULE_PARM_DESC(disable_bypass,
|
||||
"Disable bypass streams such that incoming transactions from devices that are not attached to an iommu domain will report an abort back to the device and will not be allowed to pass through the SMMU.");
|
||||
|
||||
enum arm_smmu_arch_version {
|
||||
ARM_SMMU_V1,
|
||||
ARM_SMMU_V1_64K,
|
||||
ARM_SMMU_V2,
|
||||
};
|
||||
|
||||
enum arm_smmu_implementation {
|
||||
GENERIC_SMMU,
|
||||
ARM_MMU500,
|
||||
CAVIUM_SMMUV2,
|
||||
QCOM_SMMUV2,
|
||||
QCOM_SMMUV500,
|
||||
};
|
||||
|
||||
struct arm_smmu_impl_def_reg {
|
||||
u32 offset;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
/*
|
||||
* attach_count
|
||||
* The SMR and S2CR registers are only programmed when the number of
|
||||
|
|
@ -173,116 +148,6 @@ struct arm_smmu_master_cfg {
|
|||
#define for_each_cfg_sme(fw, i, idx) \
|
||||
for (i = 0; idx = fwspec_smendx(fw, i), i < fw->num_ids; ++i)
|
||||
|
||||
/*
|
||||
* Describes resources required for on/off power operation.
|
||||
* Separate reference count is provided for atomic/nonatomic
|
||||
* operations.
|
||||
*/
|
||||
struct arm_smmu_power_resources {
|
||||
struct platform_device *pdev;
|
||||
struct device *dev;
|
||||
|
||||
struct clk **clocks;
|
||||
int num_clocks;
|
||||
|
||||
struct regulator_bulk_data *gdscs;
|
||||
int num_gdscs;
|
||||
|
||||
struct icc_path *icc_path;
|
||||
|
||||
/* Protects power_count */
|
||||
struct mutex power_lock;
|
||||
int power_count;
|
||||
|
||||
/* Protects clock_refs_count */
|
||||
spinlock_t clock_refs_lock;
|
||||
int clock_refs_count;
|
||||
int regulator_defer;
|
||||
};
|
||||
|
||||
struct arm_smmu_arch_ops;
|
||||
struct arm_smmu_device {
|
||||
struct device *dev;
|
||||
|
||||
void __iomem *base;
|
||||
phys_addr_t phys_addr;
|
||||
unsigned int numpage;
|
||||
unsigned int pgshift;
|
||||
|
||||
#define ARM_SMMU_FEAT_COHERENT_WALK (1 << 0)
|
||||
#define ARM_SMMU_FEAT_STREAM_MATCH (1 << 1)
|
||||
#define ARM_SMMU_FEAT_TRANS_S1 (1 << 2)
|
||||
#define ARM_SMMU_FEAT_TRANS_S2 (1 << 3)
|
||||
#define ARM_SMMU_FEAT_TRANS_NESTED (1 << 4)
|
||||
#define ARM_SMMU_FEAT_TRANS_OPS (1 << 5)
|
||||
#define ARM_SMMU_FEAT_VMID16 (1 << 6)
|
||||
#define ARM_SMMU_FEAT_FMT_AARCH64_4K (1 << 7)
|
||||
#define ARM_SMMU_FEAT_FMT_AARCH64_16K (1 << 8)
|
||||
#define ARM_SMMU_FEAT_FMT_AARCH64_64K (1 << 9)
|
||||
#define ARM_SMMU_FEAT_FMT_AARCH32_L (1 << 10)
|
||||
#define ARM_SMMU_FEAT_FMT_AARCH32_S (1 << 11)
|
||||
#define ARM_SMMU_FEAT_EXIDS (1 << 12)
|
||||
u32 features;
|
||||
|
||||
#define ARM_SMMU_OPT_SECURE_CFG_ACCESS (1 << 0)
|
||||
#define ARM_SMMU_OPT_FATAL_ASF (1 << 1)
|
||||
#define ARM_SMMU_OPT_SKIP_INIT (1 << 2)
|
||||
#define ARM_SMMU_OPT_3LVL_TABLES (1 << 4)
|
||||
#define ARM_SMMU_OPT_NO_ASID_RETENTION (1 << 5)
|
||||
#define ARM_SMMU_OPT_DISABLE_ATOS (1 << 6)
|
||||
u32 options;
|
||||
enum arm_smmu_arch_version version;
|
||||
enum arm_smmu_implementation model;
|
||||
|
||||
u32 num_context_banks;
|
||||
u32 num_s2_context_banks;
|
||||
DECLARE_BITMAP(context_map, ARM_SMMU_MAX_CBS);
|
||||
struct arm_smmu_cb *cbs;
|
||||
atomic_t irptndx;
|
||||
|
||||
u32 num_mapping_groups;
|
||||
u16 streamid_mask;
|
||||
u16 smr_mask_mask;
|
||||
struct arm_smmu_smr *smrs;
|
||||
struct arm_smmu_s2cr *s2crs;
|
||||
struct mutex stream_map_mutex;
|
||||
struct mutex iommu_group_mutex;
|
||||
unsigned long va_size;
|
||||
unsigned long ipa_size;
|
||||
unsigned long pa_size;
|
||||
unsigned long pgsize_bitmap;
|
||||
|
||||
u32 num_global_irqs;
|
||||
u32 num_context_irqs;
|
||||
unsigned int *irqs;
|
||||
struct clk_bulk_data *clks;
|
||||
int num_clks;
|
||||
|
||||
struct list_head list;
|
||||
|
||||
u32 cavium_id_base; /* Specific to Cavium */
|
||||
|
||||
spinlock_t global_sync_lock;
|
||||
|
||||
/* IOMMU core code handle */
|
||||
struct iommu_device iommu;
|
||||
|
||||
/* Specific to QCOM */
|
||||
struct arm_smmu_impl_def_reg *impl_def_attach_registers;
|
||||
unsigned int num_impl_def_attach_registers;
|
||||
|
||||
struct arm_smmu_power_resources *pwr;
|
||||
|
||||
spinlock_t atos_lock;
|
||||
|
||||
/* protects idr */
|
||||
struct mutex idr_mutex;
|
||||
struct idr asid_idr;
|
||||
|
||||
struct arm_smmu_arch_ops *arch_ops;
|
||||
void *archdata;
|
||||
};
|
||||
|
||||
enum arm_smmu_context_fmt {
|
||||
ARM_SMMU_CTX_FMT_NONE,
|
||||
ARM_SMMU_CTX_FMT_AARCH64,
|
||||
|
|
@ -4845,6 +4710,10 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
|
|||
if (of_dma_is_coherent(dev->of_node))
|
||||
smmu->features |= ARM_SMMU_FEAT_COHERENT_WALK;
|
||||
|
||||
smmu = arm_smmu_impl_init(smmu);
|
||||
if (IS_ERR(smmu))
|
||||
return PTR_ERR(smmu);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (res == NULL) {
|
||||
dev_err(dev, "no MEM resource info\n");
|
||||
|
|
|
|||
|
|
@ -10,7 +10,14 @@
|
|||
#ifndef _ARM_SMMU_REGS_H
|
||||
#define _ARM_SMMU_REGS_H
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Configuration registers */
|
||||
#define ARM_SMMU_GR0_sCR0 0x0
|
||||
|
|
@ -223,4 +230,142 @@ enum arm_smmu_cbar_type {
|
|||
#define ARM_SMMU_CB_ATSR 0x8f0
|
||||
#define ATSR_ACTIVE BIT(0)
|
||||
|
||||
|
||||
/* Maximum number of context banks per SMMU */
|
||||
#define ARM_SMMU_MAX_CBS 128
|
||||
|
||||
|
||||
/* Shared driver definitions */
|
||||
enum arm_smmu_arch_version {
|
||||
ARM_SMMU_V1,
|
||||
ARM_SMMU_V1_64K,
|
||||
ARM_SMMU_V2,
|
||||
};
|
||||
|
||||
enum arm_smmu_implementation {
|
||||
GENERIC_SMMU,
|
||||
ARM_MMU500,
|
||||
CAVIUM_SMMUV2,
|
||||
QCOM_SMMUV2,
|
||||
QCOM_SMMUV500,
|
||||
};
|
||||
|
||||
struct arm_smmu_impl_def_reg {
|
||||
u32 offset;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
/*
|
||||
* Describes resources required for on/off power operation.
|
||||
* Separate reference count is provided for atomic/nonatomic
|
||||
* operations.
|
||||
*/
|
||||
struct arm_smmu_power_resources {
|
||||
struct platform_device *pdev;
|
||||
struct device *dev;
|
||||
|
||||
struct clk **clocks;
|
||||
int num_clocks;
|
||||
|
||||
struct regulator_bulk_data *gdscs;
|
||||
int num_gdscs;
|
||||
|
||||
struct icc_path *icc_path;
|
||||
|
||||
/* Protects power_count */
|
||||
struct mutex power_lock;
|
||||
int power_count;
|
||||
|
||||
/* Protects clock_refs_count */
|
||||
spinlock_t clock_refs_lock;
|
||||
int clock_refs_count;
|
||||
int regulator_defer;
|
||||
};
|
||||
|
||||
struct arm_smmu_device {
|
||||
struct device *dev;
|
||||
|
||||
void __iomem *base;
|
||||
phys_addr_t phys_addr;
|
||||
unsigned int numpage;
|
||||
unsigned int pgshift;
|
||||
|
||||
#define ARM_SMMU_FEAT_COHERENT_WALK (1 << 0)
|
||||
#define ARM_SMMU_FEAT_STREAM_MATCH (1 << 1)
|
||||
#define ARM_SMMU_FEAT_TRANS_S1 (1 << 2)
|
||||
#define ARM_SMMU_FEAT_TRANS_S2 (1 << 3)
|
||||
#define ARM_SMMU_FEAT_TRANS_NESTED (1 << 4)
|
||||
#define ARM_SMMU_FEAT_TRANS_OPS (1 << 5)
|
||||
#define ARM_SMMU_FEAT_VMID16 (1 << 6)
|
||||
#define ARM_SMMU_FEAT_FMT_AARCH64_4K (1 << 7)
|
||||
#define ARM_SMMU_FEAT_FMT_AARCH64_16K (1 << 8)
|
||||
#define ARM_SMMU_FEAT_FMT_AARCH64_64K (1 << 9)
|
||||
#define ARM_SMMU_FEAT_FMT_AARCH32_L (1 << 10)
|
||||
#define ARM_SMMU_FEAT_FMT_AARCH32_S (1 << 11)
|
||||
#define ARM_SMMU_FEAT_EXIDS (1 << 12)
|
||||
u32 features;
|
||||
|
||||
#define ARM_SMMU_OPT_SECURE_CFG_ACCESS (1 << 0)
|
||||
#define ARM_SMMU_OPT_FATAL_ASF (1 << 1)
|
||||
#define ARM_SMMU_OPT_SKIP_INIT (1 << 2)
|
||||
#define ARM_SMMU_OPT_3LVL_TABLES (1 << 4)
|
||||
#define ARM_SMMU_OPT_NO_ASID_RETENTION (1 << 5)
|
||||
#define ARM_SMMU_OPT_DISABLE_ATOS (1 << 6)
|
||||
u32 options;
|
||||
enum arm_smmu_arch_version version;
|
||||
enum arm_smmu_implementation model;
|
||||
|
||||
u32 num_context_banks;
|
||||
u32 num_s2_context_banks;
|
||||
DECLARE_BITMAP(context_map, ARM_SMMU_MAX_CBS);
|
||||
struct arm_smmu_cb *cbs;
|
||||
atomic_t irptndx;
|
||||
|
||||
u32 num_mapping_groups;
|
||||
u16 streamid_mask;
|
||||
u16 smr_mask_mask;
|
||||
struct arm_smmu_smr *smrs;
|
||||
struct arm_smmu_s2cr *s2crs;
|
||||
struct mutex stream_map_mutex;
|
||||
struct mutex iommu_group_mutex;
|
||||
unsigned long va_size;
|
||||
unsigned long ipa_size;
|
||||
unsigned long pa_size;
|
||||
unsigned long pgsize_bitmap;
|
||||
|
||||
u32 num_global_irqs;
|
||||
u32 num_context_irqs;
|
||||
unsigned int *irqs;
|
||||
struct clk_bulk_data *clks;
|
||||
int num_clks;
|
||||
|
||||
struct list_head list;
|
||||
|
||||
u32 cavium_id_base; /* Specific to Cavium */
|
||||
|
||||
spinlock_t global_sync_lock;
|
||||
|
||||
/* IOMMU core code handle */
|
||||
struct iommu_device iommu;
|
||||
|
||||
/* Specific to QCOM */
|
||||
struct arm_smmu_impl_def_reg *impl_def_attach_registers;
|
||||
unsigned int num_impl_def_attach_registers;
|
||||
|
||||
struct arm_smmu_power_resources *pwr;
|
||||
|
||||
spinlock_t atos_lock;
|
||||
|
||||
/* protects idr */
|
||||
struct mutex idr_mutex;
|
||||
struct idr asid_idr;
|
||||
|
||||
struct arm_smmu_arch_ops *arch_ops;
|
||||
void *archdata;
|
||||
};
|
||||
|
||||
|
||||
/* Implementation details, yay! */
|
||||
struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu);
|
||||
|
||||
#endif /* _ARM_SMMU_REGS_H */
|
||||
|
|
|
|||
Loading…
Reference in a new issue