Skip to content

Commit 8eb6859

Browse files
thierryredingkrzk
authored andcommitted
iommu/arm-smmu: tegra: Implement SID override programming
The secure firmware keeps some SID override registers set as passthrough in order to allow devices such as the display controller to operate with no knowledge of SMMU translations until an operating system driver takes over. This is needed in order to seamlessly transition from the firmware framebuffer to the OS framebuffer. Upon successfully attaching a device to the SMMU and in the process creating identity mappings for memory regions that are being accessed, the Tegra implementation will call into the memory controller driver to program the override SIDs appropriately. Signed-off-by: Thierry Reding <treding@nvidia.com> Link: https://lore.kernel.org/r/20210603164632.1000458-6-thierry.reding@gmail.com Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
1 parent 7ecbf25 commit 8eb6859

1 file changed

Lines changed: 30 additions & 3 deletions

File tree

drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include <linux/platform_device.h>
88
#include <linux/slab.h>
99

10+
#include <soc/tegra/mc.h>
11+
1012
#include "arm-smmu.h"
1113

1214
/*
@@ -15,17 +17,25 @@
1517
* interleaved IOVA accesses across them and translates accesses from
1618
* non-isochronous HW devices.
1719
* Third one is used for translating accesses from isochronous HW devices.
20+
*
21+
* In addition, the SMMU driver needs to coordinate with the memory controller
22+
* driver to ensure that the right SID override is programmed for any given
23+
* memory client. This is necessary to allow for use-case such as seamlessly
24+
* handing over the display controller configuration from the firmware to the
25+
* kernel.
26+
*
1827
* This implementation supports programming of the two instances that must
19-
* be programmed identically.
20-
* The third instance usage is through standard arm-smmu driver itself and
21-
* is out of scope of this implementation.
28+
* be programmed identically and takes care of invoking the memory controller
29+
* driver for SID override programming after devices have been attached to an
30+
* SMMU instance.
2231
*/
2332
#define MAX_SMMU_INSTANCES 2
2433

2534
struct nvidia_smmu {
2635
struct arm_smmu_device smmu;
2736
void __iomem *bases[MAX_SMMU_INSTANCES];
2837
unsigned int num_instances;
38+
struct tegra_mc *mc;
2939
};
3040

3141
static inline struct nvidia_smmu *to_nvidia_smmu(struct arm_smmu_device *smmu)
@@ -237,6 +247,17 @@ static irqreturn_t nvidia_smmu_context_fault(int irq, void *dev)
237247
return ret;
238248
}
239249

250+
static void nvidia_smmu_probe_finalize(struct arm_smmu_device *smmu, struct device *dev)
251+
{
252+
struct nvidia_smmu *nvidia = to_nvidia_smmu(smmu);
253+
int err;
254+
255+
err = tegra_mc_probe_device(nvidia->mc, dev);
256+
if (err < 0)
257+
dev_err(smmu->dev, "memory controller probe failed for %s: %d\n",
258+
dev_name(dev), err);
259+
}
260+
240261
static const struct arm_smmu_impl nvidia_smmu_impl = {
241262
.read_reg = nvidia_smmu_read_reg,
242263
.write_reg = nvidia_smmu_write_reg,
@@ -246,9 +267,11 @@ static const struct arm_smmu_impl nvidia_smmu_impl = {
246267
.tlb_sync = nvidia_smmu_tlb_sync,
247268
.global_fault = nvidia_smmu_global_fault,
248269
.context_fault = nvidia_smmu_context_fault,
270+
.probe_finalize = nvidia_smmu_probe_finalize,
249271
};
250272

251273
static const struct arm_smmu_impl nvidia_smmu_single_impl = {
274+
.probe_finalize = nvidia_smmu_probe_finalize,
252275
};
253276

254277
struct arm_smmu_device *nvidia_smmu_impl_init(struct arm_smmu_device *smmu)
@@ -263,6 +286,10 @@ struct arm_smmu_device *nvidia_smmu_impl_init(struct arm_smmu_device *smmu)
263286
if (!nvidia_smmu)
264287
return ERR_PTR(-ENOMEM);
265288

289+
nvidia_smmu->mc = devm_tegra_memory_controller_get(dev);
290+
if (IS_ERR(nvidia_smmu->mc))
291+
return ERR_CAST(nvidia_smmu->mc);
292+
266293
/* Instance 0 is ioremapped by arm-smmu.c. */
267294
nvidia_smmu->bases[0] = smmu->base;
268295
nvidia_smmu->num_instances++;

0 commit comments

Comments
 (0)