Loading drivers/iommu/arm-smmu.c +74 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ #include <trace/events/iommu.h> #include <soc/qcom/msm_tz_smmu.h> #include <soc/qcom/scm.h> #include <linux/notifier.h> #include <linux/amba/bus.h> Loading Loading @@ -440,6 +441,7 @@ struct arm_smmu_device { #define ARM_SMMU_OPT_DISABLE_ATOS (1 << 6) #define ARM_SMMU_OPT_MMU500_ERRATA1 (1 << 7) #define ARM_SMMU_OPT_STATIC_CB (1 << 8) #define ARM_SMMU_OPT_HALT (1 << 9) u32 options; enum arm_smmu_arch_version version; enum arm_smmu_implementation model; Loading Loading @@ -473,6 +475,7 @@ struct arm_smmu_device { unsigned int num_impl_def_attach_registers; struct arm_smmu_power_resources *pwr; struct notifier_block regulator_nb; spinlock_t atos_lock; Loading Loading @@ -570,6 +573,7 @@ static struct arm_smmu_option_prop arm_smmu_options[] = { { ARM_SMMU_OPT_DISABLE_ATOS, "qcom,disable-atos" }, { ARM_SMMU_OPT_MMU500_ERRATA1, "qcom,mmu500-errata-1" }, { ARM_SMMU_OPT_STATIC_CB, "qcom,enable-static-cb"}, { ARM_SMMU_OPT_HALT, "qcom,enable-smmu-halt"}, { 0, NULL}, }; Loading Loading @@ -3817,6 +3821,71 @@ static int arm_smmu_init_clocks(struct arm_smmu_power_resources *pwr) return 0; } static int regulator_notifier(struct notifier_block *nb, unsigned long event, void *data) { int ret = 0; struct arm_smmu_device *smmu = container_of(nb, struct arm_smmu_device, regulator_nb); if (event != REGULATOR_EVENT_PRE_DISABLE && event != REGULATOR_EVENT_ENABLE) return NOTIFY_OK; ret = arm_smmu_prepare_clocks(smmu->pwr); if (ret) goto out; ret = arm_smmu_power_on_atomic(smmu->pwr); if (ret) goto unprepare_clock; if (event == REGULATOR_EVENT_PRE_DISABLE) qsmmuv2_halt(smmu); else if (event == REGULATOR_EVENT_ENABLE) { if (arm_smmu_restore_sec_cfg(smmu)) goto power_off; qsmmuv2_resume(smmu); } power_off: arm_smmu_power_off_atomic(smmu->pwr); unprepare_clock: arm_smmu_unprepare_clocks(smmu->pwr); out: return NOTIFY_OK; } static int register_regulator_notifier(struct arm_smmu_device *smmu) { struct device *dev = smmu->dev; struct regulator_bulk_data *consumers; int ret = 0, num_consumers; struct arm_smmu_power_resources *pwr = smmu->pwr; if (!(smmu->options & ARM_SMMU_OPT_HALT)) goto out; num_consumers = pwr->num_gdscs; consumers = pwr->gdscs; if (!num_consumers) { dev_info(dev, "no regulator info exist for %s\n", dev_name(dev)); goto out; } smmu->regulator_nb.notifier_call = regulator_notifier; /* registering the notifier against one gdsc is sufficient as * we do enable/disable regulators in group. */ ret = regulator_register_notifier(consumers[0].consumer, &smmu->regulator_nb); if (ret) dev_err(dev, "Regulator notifier request failed\n"); out: return ret; } static int arm_smmu_init_regulators(struct arm_smmu_power_resources *pwr) { const char *cname; Loading Loading @@ -4377,6 +4446,11 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) else bus_for_each_dev(&platform_bus_type, NULL, &arm_smmu_ops, arm_smmu_add_device_fixup); err = register_regulator_notifier(smmu); if (err) goto out_power_off; #ifdef CONFIG_ARM_AMBA if (!iommu_present(&amba_bustype)) bus_set_iommu(&amba_bustype, &arm_smmu_ops); Loading Loading
drivers/iommu/arm-smmu.c +74 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ #include <trace/events/iommu.h> #include <soc/qcom/msm_tz_smmu.h> #include <soc/qcom/scm.h> #include <linux/notifier.h> #include <linux/amba/bus.h> Loading Loading @@ -440,6 +441,7 @@ struct arm_smmu_device { #define ARM_SMMU_OPT_DISABLE_ATOS (1 << 6) #define ARM_SMMU_OPT_MMU500_ERRATA1 (1 << 7) #define ARM_SMMU_OPT_STATIC_CB (1 << 8) #define ARM_SMMU_OPT_HALT (1 << 9) u32 options; enum arm_smmu_arch_version version; enum arm_smmu_implementation model; Loading Loading @@ -473,6 +475,7 @@ struct arm_smmu_device { unsigned int num_impl_def_attach_registers; struct arm_smmu_power_resources *pwr; struct notifier_block regulator_nb; spinlock_t atos_lock; Loading Loading @@ -570,6 +573,7 @@ static struct arm_smmu_option_prop arm_smmu_options[] = { { ARM_SMMU_OPT_DISABLE_ATOS, "qcom,disable-atos" }, { ARM_SMMU_OPT_MMU500_ERRATA1, "qcom,mmu500-errata-1" }, { ARM_SMMU_OPT_STATIC_CB, "qcom,enable-static-cb"}, { ARM_SMMU_OPT_HALT, "qcom,enable-smmu-halt"}, { 0, NULL}, }; Loading Loading @@ -3817,6 +3821,71 @@ static int arm_smmu_init_clocks(struct arm_smmu_power_resources *pwr) return 0; } static int regulator_notifier(struct notifier_block *nb, unsigned long event, void *data) { int ret = 0; struct arm_smmu_device *smmu = container_of(nb, struct arm_smmu_device, regulator_nb); if (event != REGULATOR_EVENT_PRE_DISABLE && event != REGULATOR_EVENT_ENABLE) return NOTIFY_OK; ret = arm_smmu_prepare_clocks(smmu->pwr); if (ret) goto out; ret = arm_smmu_power_on_atomic(smmu->pwr); if (ret) goto unprepare_clock; if (event == REGULATOR_EVENT_PRE_DISABLE) qsmmuv2_halt(smmu); else if (event == REGULATOR_EVENT_ENABLE) { if (arm_smmu_restore_sec_cfg(smmu)) goto power_off; qsmmuv2_resume(smmu); } power_off: arm_smmu_power_off_atomic(smmu->pwr); unprepare_clock: arm_smmu_unprepare_clocks(smmu->pwr); out: return NOTIFY_OK; } static int register_regulator_notifier(struct arm_smmu_device *smmu) { struct device *dev = smmu->dev; struct regulator_bulk_data *consumers; int ret = 0, num_consumers; struct arm_smmu_power_resources *pwr = smmu->pwr; if (!(smmu->options & ARM_SMMU_OPT_HALT)) goto out; num_consumers = pwr->num_gdscs; consumers = pwr->gdscs; if (!num_consumers) { dev_info(dev, "no regulator info exist for %s\n", dev_name(dev)); goto out; } smmu->regulator_nb.notifier_call = regulator_notifier; /* registering the notifier against one gdsc is sufficient as * we do enable/disable regulators in group. */ ret = regulator_register_notifier(consumers[0].consumer, &smmu->regulator_nb); if (ret) dev_err(dev, "Regulator notifier request failed\n"); out: return ret; } static int arm_smmu_init_regulators(struct arm_smmu_power_resources *pwr) { const char *cname; Loading Loading @@ -4377,6 +4446,11 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) else bus_for_each_dev(&platform_bus_type, NULL, &arm_smmu_ops, arm_smmu_add_device_fixup); err = register_regulator_notifier(smmu); if (err) goto out_power_off; #ifdef CONFIG_ARM_AMBA if (!iommu_present(&amba_bustype)) bus_set_iommu(&amba_bustype, &arm_smmu_ops); Loading