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" - compatible: "qcom,wil6210"
- qcom,smmu-support: Boolean flag indicating whether PCIe has SMMU support - 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 - 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 - Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
the below optional properties: the below optional properties:
@ -33,6 +37,10 @@ Example:
wil6210: qcom,wil6210 { wil6210: qcom,wil6210 {
compatible = "qcom,wil6210"; compatible = "qcom,wil6210";
qcom,smmu-support; qcom,smmu-support;
qcom,smmu-s1-en;
qcom,smmu-fast-map;
qcom,smmu-coherent;
qcom,smmu-mapping = <0x20000000 0xe0000000>;
qcom,pcie-parent = <&pcie1>; qcom,pcie-parent = <&pcie1>;
qcom,wigig-en = <&tlmm 94 0>; qcom,wigig-en = <&tlmm 94 0>;
qcom,msm-bus,name = "wil6210"; qcom,msm-bus,name = "wil6210";

View file

@ -36,7 +36,7 @@
#define WIGIG_VENDOR (0x1ae9) #define WIGIG_VENDOR (0x1ae9)
#define WIGIG_DEVICE (0x0310) #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 SMMU_SIZE ((SZ_1G * 4ULL) - SMMU_BASE)
#define WIGIG_ENABLE_DELAY 50 #define WIGIG_ENABLE_DELAY 50
@ -93,9 +93,12 @@ struct msm11ad_ctx {
/* SMMU */ /* SMMU */
bool use_smmu; /* have SMMU enabled? */ bool use_smmu; /* have SMMU enabled? */
int smmu_bypass; int smmu_s1_en;
int smmu_fast_map; int smmu_fast_map;
int smmu_coherent;
struct dma_iommu_mapping *mapping; struct dma_iommu_mapping *mapping;
u32 smmu_base;
u32 smmu_size;
/* bus frequency scaling */ /* bus frequency scaling */
struct msm_bus_scale_pdata *bus_scale; 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 atomic_ctx = 1;
int rc; int rc;
int force_pt_coherent = 1;
int smmu_bypass = !ctx->smmu_s1_en;
if (!ctx->use_smmu) if (!ctx->use_smmu)
return 0; return 0;
dev_info(ctx->dev, "Initialize SMMU, bypass = %d, fastmap = %d\n", dev_info(ctx->dev, "Initialize SMMU, bypass=%d, fastmap=%d, coherent=%d\n",
ctx->smmu_bypass, ctx->smmu_fast_map); smmu_bypass, ctx->smmu_fast_map, ctx->smmu_coherent);
ctx->mapping = arm_iommu_create_mapping(&platform_bus_type, 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)) { if (IS_ERR_OR_NULL(ctx->mapping)) {
rc = PTR_ERR(ctx->mapping) ?: -ENODEV; rc = PTR_ERR(ctx->mapping) ?: -ENODEV;
dev_err(ctx->dev, "Failed to create IOMMU mapping (%d)\n", rc); dev_err(ctx->dev, "Failed to create IOMMU mapping (%d)\n", rc);
@ -662,23 +667,39 @@ static int msm_11ad_smmu_init(struct msm11ad_ctx *ctx)
goto release_mapping; goto release_mapping;
} }
if (ctx->smmu_bypass) { if (smmu_bypass) {
rc = iommu_domain_set_attr(ctx->mapping->domain, rc = iommu_domain_set_attr(ctx->mapping->domain,
DOMAIN_ATTR_S1_BYPASS, DOMAIN_ATTR_S1_BYPASS,
&ctx->smmu_bypass); &smmu_bypass);
if (rc) { if (rc) {
dev_err(ctx->dev, "Set bypass attribute to SMMU failed (%d)\n", dev_err(ctx->dev, "Set bypass attribute to SMMU failed (%d)\n",
rc); rc);
goto release_mapping; goto release_mapping;
} }
} else if (ctx->smmu_fast_map) { } else {
rc = iommu_domain_set_attr(ctx->mapping->domain, /* Set dma-coherent and page table coherency */
DOMAIN_ATTR_FAST, if (ctx->smmu_coherent) {
&ctx->smmu_fast_map); arch_setup_dma_ops(&ctx->pcidev->dev, 0, 0, NULL, true);
if (rc) { rc = iommu_domain_set_attr(ctx->mapping->domain,
dev_err(ctx->dev, "Set fast attribute to SMMU failed (%d)\n", DOMAIN_ATTR_PAGE_TABLE_FORCE_COHERENT,
rc); &force_pt_coherent);
goto release_mapping; 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);
if (rc) {
dev_err(ctx->dev, "Set fast attribute to SMMU failed (%d)\n",
rc);
goto release_mapping;
}
} }
} }
@ -900,6 +921,7 @@ static int msm_11ad_probe(struct platform_device *pdev)
struct device_node *of_node = dev->of_node; struct device_node *of_node = dev->of_node;
struct device_node *rc_node; struct device_node *rc_node;
struct pci_dev *pcidev = NULL; struct pci_dev *pcidev = NULL;
u32 smmu_mapping[2];
int rc; int rc;
u32 val; 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->use_smmu = of_property_read_bool(of_node, "qcom,smmu-support");
ctx->bus_scale = msm_bus_cl_get_pdata(pdev); ctx->bus_scale = msm_bus_cl_get_pdata(pdev);
ctx->smmu_bypass = 1; ctx->smmu_s1_en = of_property_read_bool(of_node, "qcom,smmu-s1-en");
ctx->smmu_fast_map = 0; 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 ==*/ /*== execute ==*/
/* turn device on */ /* turn device on */