iommu/arm-smmu: program ACTLR register for qcom SMMUs

The ACTLR must be programmed according to the hardware design in order
for the coherent table walk feature to work on certain Qualcomm
hardware. Provide a new compatible string ("qcom,smmu-v2") to indicate
the relevant hardware and do the programming as needed.

Change-Id: I7e807384c821fc3d07274f35726abb28d0d75ee0
Signed-off-by: Mitchel Humpherys <mitchelh@codeaurora.org>
This commit is contained in:
Mitchel Humpherys 2014-08-08 16:18:36 -07:00 committed by David Keitel
parent 9bbc577a32
commit 0347486148
2 changed files with 31 additions and 0 deletions

View file

@ -16,6 +16,7 @@ conditions.
"arm,mmu-400"
"arm,mmu-401"
"arm,mmu-500"
"qcom,smmu-v2"
depending on the particular implementation and/or the
version of the architecture implemented.

View file

@ -229,6 +229,7 @@
#define ARM_SMMU_CB(smmu, n) ((n) * (1 << (smmu)->pgshift))
#define ARM_SMMU_CB_SCTLR 0x0
#define ARM_SMMU_CB_ACTLR 0x4
#define ARM_SMMU_CB_RESUME 0x8
#define ARM_SMMU_CB_TTBCR2 0x10
#define ARM_SMMU_CB_TTBR0_LO 0x20
@ -331,6 +332,17 @@
#define FSR_AFF (1 << 2)
#define FSR_TF (1 << 1)
/* Definitions for implementation-defined registers */
#define ACTLR_QCOM_OSH_SHIFT 28
#define ACTLR_QCOM_OSH 1
#define ACTLR_QCOM_ISH_SHIFT 29
#define ACTLR_QCOM_ISH 1
#define ACTLR_QCOM_NSH_SHIFT 30
#define ACTLR_QCOM_NSH 1
#define FSR_IGN (FSR_AFF | FSR_ASF | \
FSR_TLBMCF | FSR_TLBLKF)
#define FSR_FAULT (FSR_MULTI | FSR_SS | FSR_UUT | \
@ -366,9 +378,16 @@ struct arm_smmu_master {
struct arm_smmu_master_cfg cfg;
};
enum smmu_model_id {
SMMU_MODEL_DEFAULT,
SMMU_MODEL_QCOM_V2,
};
struct arm_smmu_device {
struct device *dev;
enum smmu_model_id model;
void __iomem *base;
unsigned long size;
unsigned long pgshift;
@ -1018,6 +1037,13 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR);
if (smmu->model == SMMU_MODEL_QCOM_V2) {
reg = ACTLR_QCOM_ISH << ACTLR_QCOM_ISH_SHIFT |
ACTLR_QCOM_OSH << ACTLR_QCOM_OSH_SHIFT |
ACTLR_QCOM_NSH << ACTLR_QCOM_NSH_SHIFT;
writel_relaxed(reg, cb_base + ARM_SMMU_CB_ACTLR);
}
/* MAIR0 (stage-1 only) */
if (stage1) {
reg = (MAIR_ATTR_NC << MAIR_ATTR_SHIFT(MAIR_ATTR_IDX_NC)) |
@ -2246,6 +2272,7 @@ static const struct of_device_id arm_smmu_of_match[] = {
{ .compatible = "arm,mmu-400", .data = (void *)ARM_SMMU_V1 },
{ .compatible = "arm,mmu-401", .data = (void *)ARM_SMMU_V1 },
{ .compatible = "arm,mmu-500", .data = (void *)ARM_SMMU_V2 },
{ .compatible = "qcom,smmu-v2", .data = (void *)ARM_SMMU_V2 },
{ },
};
MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
@ -2338,6 +2365,9 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
parse_driver_options(smmu);
if (of_device_is_compatible(dev->of_node, "qcom,smmu-v2"))
smmu->model = SMMU_MODEL_QCOM_V2;
if (smmu->version > ARM_SMMU_V1 &&
smmu->num_context_banks != smmu->num_context_irqs) {
dev_err(dev,