/* * SMMU-500 TRM defines BIT(0) as CMTLB (Enable context caching in the * macro TLB) and BIT(1) as CPRE (Enable context caching in the prefetch * buffer). The remaining bits are implementation defined and vary across * SoCs.
*/
if (enabled)
qsmmu->stall_enabled |= mask; else
qsmmu->stall_enabled &= ~mask;
/* * If the device is on and we changed the setting, update the register. * The spec pseudocode says that CFCFG is resampled after a fault, and * we believe that no implementations cache it in the TLB, so it should * be safe to change it without a TLB invalidation.
*/ if (stall_changed && pm_runtime_get_if_active(smmu->dev) > 0) {
u32 reg;
/* * The GPU will always use SID 0 so that is a handy way to uniquely * identify it and configure it for per-instance pagetables
*/ for (i = 0; i < fwspec->num_ids; i++) {
u16 sid = FIELD_GET(ARM_SMMU_SMR_ID, fwspec->ids[i]);
if (sid == QCOM_ADRENO_SMMU_GPU_SID) returntrue;
}
/* * Local implementation to configure TTBR0 with the specified pagetable config. * The GPU driver will call this to enable TTBR0 when per-instance pagetables * are active
*/
/* The domain must have split pagetables already enabled */ if (cb->tcr[0] & ARM_SMMU_TCR_EPD1) return -EINVAL;
/* If the pagetable config is NULL, disable TTBR0 */ if (!pgtbl_cfg) { /* Do nothing if it is already disabled */ if ((cb->tcr[0] & ARM_SMMU_TCR_EPD0)) return -EINVAL;
/* Set TCR to the original configuration */
cb->tcr[0] = arm_smmu_lpae_tcr(&pgtable->cfg);
cb->ttbr[0] = FIELD_PREP(ARM_SMMU_TTBRn_ASID, cb->cfg->asid);
} else {
u32 tcr = cb->tcr[0];
/* Don't call this again if TTBR0 is already enabled */ if (!(cb->tcr[0] & ARM_SMMU_TCR_EPD0)) return -EINVAL;
if (client_match)
qcom_smmu_set_actlr_dev(dev, smmu, cbndx, client_match);
/* Only enable split pagetables for the GPU device (SID 0) */ if (!qcom_adreno_smmu_is_gpu_device(dev)) return 0;
/* * All targets that use the qcom,adreno-smmu compatible string *should* * be AARCH64 stage 1 but double check because the arm-smmu code assumes * that is the case when the TTBR1 quirk is enabled
*/ if (qcom_adreno_can_do_ttbr1(smmu_domain->smmu) &&
(smmu_domain->stage == ARM_SMMU_DOMAIN_S1) &&
(smmu_domain->cfg.fmt == ARM_SMMU_CTX_FMT_AARCH64))
pgtbl_cfg->quirks |= IO_PGTABLE_QUIRK_ARM_TTBR1;
/* * MSM8998 LPASS SMMU reports 13 context banks, but accessing * the last context bank crashes the system.
*/ if (of_device_is_compatible(smmu->dev->of_node, "qcom,msm8998-smmu-v2") &&
smmu->num_context_banks == 13) {
smmu->num_context_banks = 12;
} elseif (of_device_is_compatible(smmu->dev->of_node, "qcom,sdm630-smmu-v2")) { if (smmu->num_context_banks == 21) /* SDM630 / SDM660 A2NOC SMMU */
smmu->num_context_banks = 7; elseif (smmu->num_context_banks == 14) /* SDM630 / SDM660 LPASS SMMU */
smmu->num_context_banks = 13;
}
/* * Some platforms support more than the Arm SMMU architected maximum of * 128 stream matching groups. For unknown reasons, the additional * groups don't exhibit the same behavior as the architected registers, * so limit the groups to 128 until the behavior is fixed for the other * groups.
*/ if (smmu->num_mapping_groups > 128) {
dev_notice(smmu->dev, "\tLimiting the stream matching groups to 128\n");
smmu->num_mapping_groups = 128;
}
/* * With some firmware versions writes to S2CR of type FAULT are * ignored, and writing BYPASS will end up written as FAULT in the * register. Perform a write to S2CR to detect if this is the case and * if so reserve a context bank to emulate bypass streams.
*/
reg = FIELD_PREP(ARM_SMMU_S2CR_TYPE, S2CR_TYPE_BYPASS) |
FIELD_PREP(ARM_SMMU_S2CR_CBNDX, 0xff) |
FIELD_PREP(ARM_SMMU_S2CR_PRIVCFG, S2CR_PRIVCFG_DEFAULT);
arm_smmu_gr0_write(smmu, last_s2cr, reg);
reg = arm_smmu_gr0_read(smmu, last_s2cr); if (FIELD_GET(ARM_SMMU_S2CR_TYPE, reg) != S2CR_TYPE_BYPASS) {
qsmmu->bypass_quirk = true;
qsmmu->bypass_cbndx = smmu->num_context_banks - 1;
staticint qcom_adreno_smmuv2_cfg_probe(struct arm_smmu_device *smmu)
{ /* Support for 16K pages is advertised on some SoCs, but it doesn't seem to work */
smmu->features &= ~ARM_SMMU_FEAT_FMT_AARCH64_16K;
/* TZ protects several last context banks, hide them from Linux */ if (of_device_is_compatible(smmu->dev->of_node, "qcom,sdm630-smmu-v2") &&
smmu->num_context_banks == 5)
smmu->num_context_banks = 2;
if (qsmmu->bypass_quirk) { if (type == S2CR_TYPE_BYPASS) { /* * Firmware with quirky S2CR handling will substitute * BYPASS writes with FAULT, so point the stream to the * reserved context bank and ask for translation on the * stream
*/
type = S2CR_TYPE_TRANS;
cbndx = qsmmu->bypass_cbndx;
} elseif (type == S2CR_TYPE_FAULT) { /* * Firmware with quirky S2CR handling will ignore FAULT * writes, so trick it to write FAULT by asking for a * BYPASS.
*/
type = S2CR_TYPE_BYPASS;
cbndx = 0xff;
}
}
staticint qcom_sdm845_smmu500_reset(struct arm_smmu_device *smmu)
{ int ret;
arm_mmu500_reset(smmu);
/* * To address performance degradation in non-real time clients, * such as USB and UFS, turn off wait-for-safe on sdm845 based boards, * such as MTP and db845, whose firmwares implement secure monitor * call handlers to turn on/off the wait-for-safe logic.
*/
ret = qcom_scm_qsmmu500_wait_safe_toggle(0); if (ret)
dev_warn(smmu->dev, "Failed to turn off SAFE logic\n");
/* Check to make sure qcom_scm has finished probing */ if (!qcom_scm_is_available()) return ERR_PTR(dev_err_probe(smmu->dev, -EPROBE_DEFER, "qcom_scm not ready\n"));
qsmmu = devm_krealloc(smmu->dev, smmu, sizeof(*qsmmu), GFP_KERNEL); if (!qsmmu) return ERR_PTR(-ENOMEM);
/* * It is not yet possible to use MDP SMMU with the bypass quirk on the msm8996, * there are not enough context banks.
*/ staticconststruct qcom_smmu_match_data msm8996_smmu_data = {
.impl = NULL,
.adreno_impl = &qcom_adreno_smmu_v2_impl,
};
staticconststruct qcom_smmu_match_data sdm845_smmu_500_data = {
.impl = &sdm845_smmu_500_impl, /* * No need for adreno impl here. On sdm845 the Adreno SMMU is handled * by the separate sdm845-smmu-v2 device.
*/ /* Also no debug configuration. */
};
if (!tbu_registered++)
platform_driver_register(&qcom_smmu_tbu_driver);
#ifdef CONFIG_ACPI if (np == NULL) { /* Match platform for ACPI boot */ if (acpi_match_platform_list(qcom_acpi_platlist) >= 0) return qcom_smmu_create(smmu, &qcom_smmu_500_impl0_data);
} #endif
match = of_match_node(qcom_smmu_impl_of_match, np); if (match) return qcom_smmu_create(smmu, match->data);
/* * If you hit this WARN_ON() you are missing an entry in the * qcom_smmu_impl_of_match[] table, and GPU per-process page- * tables will be broken.
*/
WARN(of_device_is_compatible(np, "qcom,adreno-smmu"), "Missing qcom_smmu_impl_of_match entry for: %s",
dev_name(smmu->dev));
return smmu;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.79 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.