msm_11ad: 11AD SMMU changes to allow enabling of SMMU stage1

Add the following changes to support enabling of SMMU stage1:
- Enable DMA coherency and PAGE_TABLE_FORCE_COHERENT attr
to allow cache coherency when SMMU stage1 is enabled
- Add the option to define SMMU base address and size in DT
- Add DT node flag to determine if stage1 is enabled

Change-Id: I38b0ee3d5c4bf533f91077ee69bd464dfdd358c8
Signed-off-by: Maya Erez <merez@codeaurora.org>
This commit is contained in:
Maya Erez 2017-03-27 09:31:39 +03:00
parent ba53c4518c
commit b30b481b14
2 changed files with 66 additions and 17 deletions

View file

@ -10,6 +10,10 @@ Required properties:
- compatible: "qcom,wil6210"
- qcom,smmu-support: Boolean flag indicating whether PCIe has SMMU support
- qcom,smmu-s1-en: Boolean flag indicating whether SMMU stage1 should be enabled
- qcom,smmu-fast-map: Boolean flag indicating whether SMMU fast mapping should be enabled
- qcom,smmu-coherent: Boolean flag indicating SMMU dma and page table coherency
- qcom,smmu-mapping: specifies the base address and size of SMMU space
- qcom,pcie-parent: phandle for the PCIe root complex to which 11ad card is connected
- Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
the below optional properties:
@ -33,6 +37,10 @@ Example:
wil6210: qcom,wil6210 {
compatible = "qcom,wil6210";
qcom,smmu-support;
qcom,smmu-s1-en;
qcom,smmu-fast-map;
qcom,smmu-coherent;
qcom,smmu-mapping = <0x20000000 0xe0000000>;
qcom,pcie-parent = <&pcie1>;
qcom,wigig-en = <&tlmm 94 0>;
qcom,msm-bus,name = "wil6210";

View file

@ -36,7 +36,7 @@
#define WIGIG_VENDOR (0x1ae9)
#define WIGIG_DEVICE (0x0310)
#define SMMU_BASE 0x10000000 /* Device address range base */
#define SMMU_BASE 0x20000000 /* Device address range base */
#define SMMU_SIZE ((SZ_1G * 4ULL) - SMMU_BASE)
#define WIGIG_ENABLE_DELAY 50
@ -93,9 +93,12 @@ struct msm11ad_ctx {
/* SMMU */
bool use_smmu; /* have SMMU enabled? */
int smmu_bypass;
int smmu_s1_en;
int smmu_fast_map;
int smmu_coherent;
struct dma_iommu_mapping *mapping;
u32 smmu_base;
u32 smmu_size;
/* bus frequency scaling */
struct msm_bus_scale_pdata *bus_scale;
@ -638,15 +641,17 @@ static int msm_11ad_smmu_init(struct msm11ad_ctx *ctx)
{
int atomic_ctx = 1;
int rc;
int force_pt_coherent = 1;
int smmu_bypass = !ctx->smmu_s1_en;
if (!ctx->use_smmu)
return 0;
dev_info(ctx->dev, "Initialize SMMU, bypass = %d, fastmap = %d\n",
ctx->smmu_bypass, ctx->smmu_fast_map);
dev_info(ctx->dev, "Initialize SMMU, bypass=%d, fastmap=%d, coherent=%d\n",
smmu_bypass, ctx->smmu_fast_map, ctx->smmu_coherent);
ctx->mapping = arm_iommu_create_mapping(&platform_bus_type,
SMMU_BASE, SMMU_SIZE);
ctx->smmu_base, ctx->smmu_size);
if (IS_ERR_OR_NULL(ctx->mapping)) {
rc = PTR_ERR(ctx->mapping) ?: -ENODEV;
dev_err(ctx->dev, "Failed to create IOMMU mapping (%d)\n", rc);
@ -662,16 +667,31 @@ static int msm_11ad_smmu_init(struct msm11ad_ctx *ctx)
goto release_mapping;
}
if (ctx->smmu_bypass) {
if (smmu_bypass) {
rc = iommu_domain_set_attr(ctx->mapping->domain,
DOMAIN_ATTR_S1_BYPASS,
&ctx->smmu_bypass);
&smmu_bypass);
if (rc) {
dev_err(ctx->dev, "Set bypass attribute to SMMU failed (%d)\n",
rc);
goto release_mapping;
}
} else if (ctx->smmu_fast_map) {
} else {
/* Set dma-coherent and page table coherency */
if (ctx->smmu_coherent) {
arch_setup_dma_ops(&ctx->pcidev->dev, 0, 0, NULL, true);
rc = iommu_domain_set_attr(ctx->mapping->domain,
DOMAIN_ATTR_PAGE_TABLE_FORCE_COHERENT,
&force_pt_coherent);
if (rc) {
dev_err(ctx->dev,
"Set SMMU PAGE_TABLE_FORCE_COHERENT attr failed (%d)\n",
rc);
goto release_mapping;
}
}
if (ctx->smmu_fast_map) {
rc = iommu_domain_set_attr(ctx->mapping->domain,
DOMAIN_ATTR_FAST,
&ctx->smmu_fast_map);
@ -681,6 +701,7 @@ static int msm_11ad_smmu_init(struct msm11ad_ctx *ctx)
goto release_mapping;
}
}
}
rc = arm_iommu_attach_device(&ctx->pcidev->dev, ctx->mapping);
if (rc) {
@ -900,6 +921,7 @@ static int msm_11ad_probe(struct platform_device *pdev)
struct device_node *of_node = dev->of_node;
struct device_node *rc_node;
struct pci_dev *pcidev = NULL;
u32 smmu_mapping[2];
int rc;
u32 val;
@ -954,8 +976,27 @@ static int msm_11ad_probe(struct platform_device *pdev)
ctx->use_smmu = of_property_read_bool(of_node, "qcom,smmu-support");
ctx->bus_scale = msm_bus_cl_get_pdata(pdev);
ctx->smmu_bypass = 1;
ctx->smmu_fast_map = 0;
ctx->smmu_s1_en = of_property_read_bool(of_node, "qcom,smmu-s1-en");
if (ctx->smmu_s1_en) {
ctx->smmu_fast_map = of_property_read_bool(
of_node, "qcom,smmu-fast-map");
ctx->smmu_coherent = of_property_read_bool(
of_node, "qcom,smmu-coherent");
}
rc = of_property_read_u32_array(dev->of_node, "qcom,smmu-mapping",
smmu_mapping, 2);
if (rc) {
dev_err(ctx->dev,
"Failed to read base/size smmu addresses %d, fallback to default\n",
rc);
ctx->smmu_base = SMMU_BASE;
ctx->smmu_size = SMMU_SIZE;
} else {
ctx->smmu_base = smmu_mapping[0];
ctx->smmu_size = smmu_mapping[1];
}
dev_dbg(ctx->dev, "smmu_base=0x%x smmu_sise=0x%x\n",
ctx->smmu_base, ctx->smmu_size);
/*== execute ==*/
/* turn device on */