Merge "msm_11ad: align to the new SMMU API"

This commit is contained in:
qctecmdr Service 2019-03-26 17:04:09 -07:00 committed by Gerrit - the friendly Code Review server
commit 6405f05ee1
2 changed files with 94 additions and 163 deletions

View file

@ -9,11 +9,6 @@ bus-scaling and SMMU initialization by the driver.
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:
@ -29,6 +24,7 @@ Optional properties:
- qcom,use-ext-supply: Boolean flag to indicate if 11ad SIP uses external power supply
- vdd-supply: phandle to 11ad VDD regulator node
- vddio-supply: phandle to 11ad VDDIO regulator node
- vdd-ldo-supply: phandle to 11ad VDD LDO regulator node
- qcom,use-ext-clocks: Boolean flag to indicate if 11ad SIP uses external clocks
- clocks : List of phandle and clock specifier pairs
- clock-names : List of clock input name strings sorted in the same
@ -39,11 +35,6 @@ Optional properties:
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,wigig-dc = <&tlmm 81 0>;
@ -56,6 +47,7 @@ Example:
qcom,use-ext-supply;
vdd-supply= <&pm8998_s7>;
vddio-supply= <&pm8998_s5>;
vdd-ldo-supply = <&pm8150_l15>;
qcom,use-ext-clocks;
clocks = <&clock_gcc clk_rf_clk3>,
<&clock_gcc clk_rf_clk3_pin>;
@ -63,3 +55,32 @@ Example:
qcom,keep-radio-on-during-sleep;
};
Wil6210 client node under PCIe RP node needed for SMMU initialization by
PCI framework when devices are discovered.
Required properties:
- qcom,iommu-dma-addr-pool: specifies the base address and size of SMMU space
- qcom,iommu-dma: define the SMMU mode - bypass/fastmap/disabled
- qcom,iommu-pagetable: indicating SMMU dma and page table coherency
Example:
&pcie1_rp {
#address-cells = <5>;
#size-cells = <0>;
wil6210_pci: wil6210_pci {
reg = <0 0 0 0 0>;
#address-cells = <1>;
#size-cells = <1>;
qcom,iommu-group = <&wil6210_pci_iommu_group>;
wil6210_pci_iommu_group: wil6210_pci_iommu_group {
qcom,iommu-dma-addr-pool = <0x20000000 0xe0000000>;
qcom,iommu-dma = "fastmap";
qcom,iommu-pagetable = "coherent";
};
};
};

View file

@ -26,9 +26,6 @@
#include "wil_platform.h"
#include "msm_11ad.h"
#define SMMU_BASE 0x20000000 /* Device address range base */
#define SMMU_SIZE ((SZ_1G * 4ULL) - SMMU_BASE)
#define WIGIG_ENABLE_DELAY 50
#define WIGIG_SUBSYS_NAME "WIGIG"
@ -39,9 +36,12 @@
#define VDD_MIN_UV 1028000
#define VDD_MAX_UV 1028000
#define VDD_MAX_UA 575000
#define VDDIO_MIN_UV 1950000
#define VDDIO_MIN_UV 1824000
#define VDDIO_MAX_UV 2040000
#define VDDIO_MAX_UA 70300
#define VDD_LDO_MIN_UV 1800000
#define VDD_LDO_MAX_UV 1800000
#define VDD_LDO_MAX_UA 100000
#define WIGIG_MIN_CPU_BOOST_KBPS 150000
@ -92,15 +92,6 @@ struct msm11ad_ctx {
struct pci_saved_state *golden_state;
struct msm_pcie_register_event pci_event;
/* SMMU */
bool use_smmu; /* have SMMU enabled? */
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;
u32 msm_bus_handle;
@ -122,8 +113,9 @@ struct msm11ad_ctx {
/* external vregs and clocks */
struct msm11ad_vreg vdd;
struct msm11ad_vreg vddio;
struct msm11ad_clk rf_clk3;
struct msm11ad_clk rf_clk3_pin;
struct msm11ad_vreg vdd_ldo;
struct msm11ad_clk rf_clk;
struct msm11ad_clk rf_clk_pin;
/* cpu boost support */
bool use_cpu_boost;
@ -256,8 +248,18 @@ static int msm_11ad_init_vregs(struct msm11ad_ctx *ctx)
ctx->vddio.min_uV = VDDIO_MIN_UV;
ctx->vddio.max_uA = VDDIO_MAX_UA;
rc = msm_11ad_init_vreg(dev, &ctx->vdd_ldo, "vdd-ldo");
if (rc)
goto vdd_ldo_fail;
ctx->vdd_ldo.max_uV = VDD_LDO_MAX_UV;
ctx->vdd_ldo.min_uV = VDD_LDO_MIN_UV;
ctx->vdd_ldo.max_uA = VDD_LDO_MAX_UA;
return rc;
vdd_ldo_fail:
msm_11ad_release_vreg(dev, &ctx->vddio);
vddio_fail:
msm_11ad_release_vreg(dev, &ctx->vdd);
out:
@ -266,6 +268,7 @@ static int msm_11ad_init_vregs(struct msm11ad_ctx *ctx)
static void msm_11ad_release_vregs(struct msm11ad_ctx *ctx)
{
msm_11ad_release_vreg(ctx->dev, &ctx->vdd_ldo);
msm_11ad_release_vreg(ctx->dev, &ctx->vdd);
msm_11ad_release_vreg(ctx->dev, &ctx->vddio);
}
@ -381,8 +384,14 @@ static int msm_11ad_enable_vregs(struct msm11ad_ctx *ctx)
if (rc)
goto vddio_fail;
rc = msm_11ad_enable_vreg(ctx, &ctx->vdd_ldo);
if (rc)
goto vdd_ldo_fail;
return rc;
vdd_ldo_fail:
msm_11ad_disable_vreg(ctx, &ctx->vddio);
vddio_fail:
msm_11ad_disable_vreg(ctx, &ctx->vdd);
out:
@ -391,10 +400,11 @@ static int msm_11ad_enable_vregs(struct msm11ad_ctx *ctx)
static int msm_11ad_disable_vregs(struct msm11ad_ctx *ctx)
{
if (!ctx->vdd.reg && !ctx->vddio.reg)
if (!ctx->vdd.reg && !ctx->vddio.reg && !ctx->vdd_ldo.reg)
goto out;
/* ignore errors on disable vreg */
msm_11ad_disable_vreg(ctx, &ctx->vdd_ldo);
msm_11ad_disable_vreg(ctx, &ctx->vdd);
msm_11ad_disable_vreg(ctx, &ctx->vddio);
@ -446,13 +456,13 @@ static int msm_11ad_enable_clocks(struct msm11ad_ctx *ctx)
{
int rc;
rc = msm_11ad_enable_clk(ctx, &ctx->rf_clk3);
rc = msm_11ad_enable_clk(ctx, &ctx->rf_clk);
if (rc)
return rc;
rc = msm_11ad_enable_clk(ctx, &ctx->rf_clk3_pin);
rc = msm_11ad_enable_clk(ctx, &ctx->rf_clk_pin);
if (rc)
msm_11ad_disable_clk(ctx, &ctx->rf_clk3);
msm_11ad_disable_clk(ctx, &ctx->rf_clk);
return rc;
}
@ -461,22 +471,22 @@ static int msm_11ad_init_clocks(struct msm11ad_ctx *ctx)
{
int rc;
struct device *dev = ctx->dev;
int rf_clk3_pin_idx;
int rf_clk_pin_idx;
if (!of_property_read_bool(dev->of_node, "qcom,use-ext-clocks"))
return 0;
rc = msm_11ad_init_clk(dev, &ctx->rf_clk3, "rf_clk3_clk");
rc = msm_11ad_init_clk(dev, &ctx->rf_clk, "rf_clk_clk");
if (rc)
return rc;
rf_clk3_pin_idx = of_property_match_string(dev->of_node, "clock-names",
"rf_clk3_pin_clk");
if (rf_clk3_pin_idx >= 0) {
rc = msm_11ad_init_clk(dev, &ctx->rf_clk3_pin,
"rf_clk3_pin_clk");
rf_clk_pin_idx = of_property_match_string(dev->of_node, "clock-names",
"rf_clk_pin_clk");
if (rf_clk_pin_idx >= 0) {
rc = msm_11ad_init_clk(dev, &ctx->rf_clk_pin,
"rf_clk_pin_clk");
if (rc)
msm_11ad_release_clk(ctx->dev, &ctx->rf_clk3);
msm_11ad_release_clk(ctx->dev, &ctx->rf_clk);
}
return rc;
@ -484,14 +494,14 @@ static int msm_11ad_init_clocks(struct msm11ad_ctx *ctx)
static void msm_11ad_release_clocks(struct msm11ad_ctx *ctx)
{
msm_11ad_release_clk(ctx->dev, &ctx->rf_clk3_pin);
msm_11ad_release_clk(ctx->dev, &ctx->rf_clk3);
msm_11ad_release_clk(ctx->dev, &ctx->rf_clk_pin);
msm_11ad_release_clk(ctx->dev, &ctx->rf_clk);
}
static void msm_11ad_disable_clocks(struct msm11ad_ctx *ctx)
{
msm_11ad_disable_clk(ctx, &ctx->rf_clk3_pin);
msm_11ad_disable_clk(ctx, &ctx->rf_clk3);
msm_11ad_disable_clk(ctx, &ctx->rf_clk_pin);
msm_11ad_disable_clk(ctx, &ctx->rf_clk);
}
static int msm_11ad_turn_device_power_off(struct msm11ad_ctx *ctx)
@ -769,86 +779,6 @@ static int ops_resume(void *handle, bool device_powered_on)
return rc;
}
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, coherent=%d\n",
smmu_bypass, ctx->smmu_fast_map, ctx->smmu_coherent);
ctx->mapping = __depr_arm_iommu_create_mapping(&platform_bus_type,
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);
return rc;
}
rc = iommu_domain_set_attr(ctx->mapping->domain,
DOMAIN_ATTR_ATOMIC,
&atomic_ctx);
if (rc) {
dev_err(ctx->dev, "Set atomic attribute to SMMU failed (%d)\n",
rc);
goto release_mapping;
}
if (smmu_bypass) {
rc = iommu_domain_set_attr(ctx->mapping->domain,
DOMAIN_ATTR_S1_BYPASS,
&smmu_bypass);
if (rc) {
dev_err(ctx->dev, "Set bypass attribute to SMMU failed (%d)\n",
rc);
goto release_mapping;
}
} 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);
if (rc) {
dev_err(ctx->dev, "Set fast attribute to SMMU failed (%d)\n",
rc);
goto release_mapping;
}
}
}
rc = __depr_arm_iommu_attach_device(&ctx->pcidev->dev, ctx->mapping);
if (rc) {
dev_err(ctx->dev, "arm_iommu_attach_device failed (%d)\n", rc);
goto release_mapping;
}
dev_dbg(ctx->dev, "attached to IOMMU\n");
return 0;
release_mapping:
__depr_arm_iommu_release_mapping(ctx->mapping);
ctx->mapping = NULL;
return rc;
}
static int msm_11ad_ssr_shutdown(const struct subsys_desc *subsys,
bool force_stop)
{
@ -1091,7 +1021,6 @@ 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, i;
bool pcidev_found = false;
struct msm_pcie_register_event *pci_event;
@ -1118,7 +1047,6 @@ static int msm_11ad_probe(struct platform_device *pdev)
* qcom,msm-bus,vectors-KBps =
* <100 512 0 0>,
* <100 512 600000 800000>;
* qcom,smmu-support;
*};
* rc_node stands for "qcom,pcie", selected entries:
* cell-index = <1>; (ctx->rc_index)
@ -1149,7 +1077,6 @@ static int msm_11ad_probe(struct platform_device *pdev)
dev_err(ctx->dev, "Parent PCIE device index not found\n");
return -EINVAL;
}
ctx->use_smmu = of_property_read_bool(of_node, "qcom,smmu-support");
ctx->keep_radio_on_during_sleep = of_property_read_bool(of_node,
"qcom,keep-radio-on-during-sleep");
ctx->bus_scale = msm_bus_cl_get_pdata(pdev);
@ -1158,28 +1085,6 @@ static int msm_11ad_probe(struct platform_device *pdev)
return -EINVAL;
}
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 */
rc = msm_11ad_init_vregs(ctx);
@ -1310,10 +1215,9 @@ static int msm_11ad_probe(struct platform_device *pdev)
" gpio_dc = %d\n"
" sleep_clk_en = %d\n"
" rc_index = %d\n"
" use_smmu = %d\n"
" pcidev = %pK\n"
"}\n", ctx, ctx->gpio_en, ctx->gpio_dc, ctx->sleep_clk_en,
ctx->rc_index, ctx->use_smmu, ctx->pcidev);
ctx->rc_index, ctx->pcidev);
platform_set_drvdata(pdev, ctx);
device_disable_async_suspend(&pcidev->dev);
@ -1543,12 +1447,6 @@ static void ops_uninit(void *handle)
ctx->msm_bus_handle = 0;
}
if (ctx->use_smmu) {
__depr_arm_iommu_detach_device(&ctx->pcidev->dev);
__depr_arm_iommu_release_mapping(ctx->mapping);
ctx->mapping = NULL;
}
memset(&ctx->rops, 0, sizeof(ctx->rops));
ctx->wil_handle = NULL;
@ -1587,12 +1485,12 @@ static int ops_notify(void *handle, enum wil_platform_event evt)
break;
case WIL_PLATFORM_EVT_PRE_RESET:
/*
* Enable rf_clk3 clock before resetting the device to ensure
* Enable rf_clk clock before resetting the device to ensure
* stable ref clock during the device reset
*/
if (ctx->features &
BIT(WIL_PLATFORM_FEATURE_FW_EXT_CLK_CONTROL)) {
rc = msm_11ad_enable_clk(ctx, &ctx->rf_clk3);
rc = msm_11ad_enable_clk(ctx, &ctx->rf_clk);
if (rc) {
dev_err(ctx->dev,
"failed to enable clk, rc %d\n", rc);
@ -1602,12 +1500,12 @@ static int ops_notify(void *handle, enum wil_platform_event evt)
break;
case WIL_PLATFORM_EVT_FW_RDY:
/*
* Disable rf_clk3 clock after the device is up to allow
* Disable rf_clk clock after the device is up to allow
* the device to control it via its GPIO for power saving
*/
if (ctx->features &
BIT(WIL_PLATFORM_FEATURE_FW_EXT_CLK_CONTROL))
msm_11ad_disable_clk(ctx, &ctx->rf_clk3);
msm_11ad_disable_clk(ctx, &ctx->rf_clk);
/*
* Save golden config space for pci linkdown recovery.
@ -1659,6 +1557,10 @@ void *msm_11ad_dev_init(struct device *dev, struct wil_platform_ops *ops,
{
struct pci_dev *pcidev = to_pci_dev(dev);
struct msm11ad_ctx *ctx = pcidev2ctx(pcidev);
struct iommu_domain *domain;
int bypass = 0;
int fastmap = 0;
int coherent = 0;
if (!ctx) {
pr_err("Context not found for pcidev %pK\n", pcidev);
@ -1673,11 +1575,19 @@ void *msm_11ad_dev_init(struct device *dev, struct wil_platform_ops *ops,
return NULL;
}
dev_info(ctx->dev, "msm_bus handle 0x%x\n", ctx->msm_bus_handle);
/* smmu */
if (msm_11ad_smmu_init(ctx)) {
msm_bus_scale_unregister_client(ctx->msm_bus_handle);
ctx->msm_bus_handle = 0;
return NULL;
domain = iommu_get_domain_for_dev(&pcidev->dev);
if (domain) {
iommu_domain_get_attr(domain, DOMAIN_ATTR_S1_BYPASS, &bypass);
iommu_domain_get_attr(domain, DOMAIN_ATTR_FAST, &fastmap);
iommu_domain_get_attr(domain,
DOMAIN_ATTR_PAGE_TABLE_IS_COHERENT,
&coherent);
dev_info(ctx->dev, "SMMU initialized, bypass=%d, fastmap=%d, coherent=%d\n",
bypass, fastmap, coherent);
} else {
dev_warn(ctx->dev, "Unable to get iommu domain\n");
}
/* subsystem restart */