Skip to content

Commit 7f2ef1b

Browse files
Bibek Kumar Patrowilldeacon
authored andcommitted
iommu/arm-smmu: Add support for PRR bit setup
Add an adreno-smmu-priv interface for drm/msm to call into arm-smmu-qcom and initiate the "Partially Resident Region" (PRR) bit setup or reset sequence as per request. This will be used by GPU to setup the PRR bit and related configuration registers through adreno-smmu private interface instead of directly poking the smmu hardware. Suggested-by: Rob Clark <[email protected]> Signed-off-by: Bibek Kumar Patro <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 445d7a8 commit 7f2ef1b

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
#define QCOM_DUMMY_VAL -1
1818

19+
#define GFX_ACTLR_PRR (1 << 5)
20+
1921
static struct qcom_smmu *to_qcom_smmu(struct arm_smmu_device *smmu)
2022
{
2123
return container_of(smmu, struct qcom_smmu, smmu);
@@ -99,6 +101,47 @@ static void qcom_adreno_smmu_resume_translation(const void *cookie, bool termina
99101
arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_RESUME, reg);
100102
}
101103

104+
static void qcom_adreno_smmu_set_prr_bit(const void *cookie, bool set)
105+
{
106+
struct arm_smmu_domain *smmu_domain = (void *)cookie;
107+
struct arm_smmu_device *smmu = smmu_domain->smmu;
108+
struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
109+
u32 reg = 0;
110+
int ret;
111+
112+
ret = pm_runtime_resume_and_get(smmu->dev);
113+
if (ret < 0) {
114+
dev_err(smmu->dev, "failed to get runtime PM: %d\n", ret);
115+
return;
116+
}
117+
118+
reg = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_ACTLR);
119+
reg &= ~GFX_ACTLR_PRR;
120+
if (set)
121+
reg |= FIELD_PREP(GFX_ACTLR_PRR, 1);
122+
arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_ACTLR, reg);
123+
pm_runtime_put_autosuspend(smmu->dev);
124+
}
125+
126+
static void qcom_adreno_smmu_set_prr_addr(const void *cookie, phys_addr_t page_addr)
127+
{
128+
struct arm_smmu_domain *smmu_domain = (void *)cookie;
129+
struct arm_smmu_device *smmu = smmu_domain->smmu;
130+
int ret;
131+
132+
ret = pm_runtime_resume_and_get(smmu->dev);
133+
if (ret < 0) {
134+
dev_err(smmu->dev, "failed to get runtime PM: %d\n", ret);
135+
return;
136+
}
137+
138+
writel_relaxed(lower_32_bits(page_addr),
139+
smmu->base + ARM_SMMU_GFX_PRR_CFG_LADDR);
140+
writel_relaxed(upper_32_bits(page_addr),
141+
smmu->base + ARM_SMMU_GFX_PRR_CFG_UADDR);
142+
pm_runtime_put_autosuspend(smmu->dev);
143+
}
144+
102145
#define QCOM_ADRENO_SMMU_GPU_SID 0
103146

104147
static bool qcom_adreno_smmu_is_gpu_device(struct device *dev)
@@ -210,6 +253,7 @@ static bool qcom_adreno_can_do_ttbr1(struct arm_smmu_device *smmu)
210253
static int qcom_adreno_smmu_init_context(struct arm_smmu_domain *smmu_domain,
211254
struct io_pgtable_cfg *pgtbl_cfg, struct device *dev)
212255
{
256+
const struct device_node *np = smmu_domain->smmu->dev->of_node;
213257
struct adreno_smmu_priv *priv;
214258

215259
smmu_domain->cfg.flush_walk_prefer_tlbiasid = true;
@@ -239,6 +283,14 @@ static int qcom_adreno_smmu_init_context(struct arm_smmu_domain *smmu_domain,
239283
priv->get_fault_info = qcom_adreno_smmu_get_fault_info;
240284
priv->set_stall = qcom_adreno_smmu_set_stall;
241285
priv->resume_translation = qcom_adreno_smmu_resume_translation;
286+
priv->set_prr_bit = NULL;
287+
priv->set_prr_addr = NULL;
288+
289+
if (of_device_is_compatible(np, "qcom,smmu-500") &&
290+
of_device_is_compatible(np, "qcom,adreno-smmu")) {
291+
priv->set_prr_bit = qcom_adreno_smmu_set_prr_bit;
292+
priv->set_prr_addr = qcom_adreno_smmu_set_prr_addr;
293+
}
242294

243295
return 0;
244296
}

drivers/iommu/arm/arm-smmu/arm-smmu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ enum arm_smmu_cbar_type {
154154
#define ARM_SMMU_SCTLR_M BIT(0)
155155

156156
#define ARM_SMMU_CB_ACTLR 0x4
157+
#define ARM_SMMU_GFX_PRR_CFG_LADDR 0x6008
158+
#define ARM_SMMU_GFX_PRR_CFG_UADDR 0x600C
157159

158160
#define ARM_SMMU_CB_RESUME 0x8
159161
#define ARM_SMMU_RESUME_TERMINATE BIT(0)

include/linux/adreno-smmu-priv.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ struct adreno_smmu_fault_info {
5050
* the GPU driver must call resume_translation()
5151
* @resume_translation: Resume translation after a fault
5252
*
53+
* @set_prr_bit: [optional] Configure the GPU's Partially Resident
54+
* Region (PRR) bit in the ACTLR register.
55+
* @set_prr_addr: [optional] Configure the PRR_CFG_*ADDR register with
56+
* the physical address of PRR page passed from GPU
57+
* driver.
5358
*
5459
* The GPU driver (drm/msm) and adreno-smmu work together for controlling
5560
* the GPU's SMMU instance. This is by necessity, as the GPU is directly
@@ -67,6 +72,8 @@ struct adreno_smmu_priv {
6772
void (*get_fault_info)(const void *cookie, struct adreno_smmu_fault_info *info);
6873
void (*set_stall)(const void *cookie, bool enabled);
6974
void (*resume_translation)(const void *cookie, bool terminate);
75+
void (*set_prr_bit)(const void *cookie, bool set);
76+
void (*set_prr_addr)(const void *cookie, phys_addr_t page_addr);
7077
};
7178

7279
#endif /* __ADRENO_SMMU_PRIV_H */

0 commit comments

Comments
 (0)