Merge "iommu: arm-smmu: Use device-tree based msm_bus api" into msm-4.8
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
index d9149dd..0a74f48 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
@@ -93,8 +93,11 @@
 - vdd-supply    : Phandle of the regulator that should be powered on during
                   SMMU register access.
 
-- qcom,bus-master-id : The master ID of the bus, if a bus vote is needed.
-                       See include/dt-bindings/msm/msm-bus-ids.h.
+- qcom,msm-bus,name
+- qcom,msm-bus,num-cases
+- qcom,msm-bus,num-paths
+- qcom,msm-bus,vectors-KBps
+		: Refer to devicetree/bindings/arm/msm/msm_bus.txt
 
 Example:
 
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index abb0b2e..5417b7e 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -402,8 +402,8 @@
 
 	struct regulator		*gdsc;
 
-	struct msm_bus_client_handle	*bus_client;
-	char				*bus_client_name;
+	uint32_t			bus_client;
+	struct msm_bus_scale_pdata	*bus_dt_data;
 
 	/* Protects power_count */
 	struct mutex			power_lock;
@@ -877,21 +877,20 @@
 	return regulator_disable(smmu->gdsc);
 }
 
-static int arm_smmu_request_bus(struct arm_smmu_device *smmu)
+static int arm_smmu_request_bus(uint32_t client)
 {
-	if (!smmu->bus_client)
+	if (!client)
 		return 0;
-	return msm_bus_scale_update_bw(smmu->bus_client, 0, 1000);
+	return msm_bus_scale_client_update_request(client, 1);
 }
 
-static int arm_smmu_unrequest_bus(struct arm_smmu_device *smmu)
+static void arm_smmu_unrequest_bus(uint32_t client)
 {
-	if (!smmu->bus_client)
-		return 0;
-	return msm_bus_scale_update_bw(smmu->bus_client, 0, 0);
+	if (!client)
+		return;
+	WARN_ON(msm_bus_scale_client_update_request(client, 0));
 }
 
-
 static int arm_smmu_power_on_slow(struct arm_smmu_device *smmu)
 {
 	int ret;
@@ -907,7 +906,7 @@
 	if (ret)
 		goto out_unlock;
 
-	ret = arm_smmu_request_bus(smmu);
+	ret = arm_smmu_request_bus(smmu->bus_client);
 	if (ret)
 		goto out_disable_regulators;
 
@@ -920,7 +919,7 @@
 	return 0;
 
 out_disable_bus:
-	arm_smmu_unrequest_bus(smmu);
+	arm_smmu_unrequest_bus(smmu->bus_client);
 out_disable_regulators:
 	arm_smmu_disable_regulators(smmu);
 out_unlock:
@@ -940,7 +939,7 @@
 	}
 
 	arm_smmu_unprepare_clocks(smmu);
-	arm_smmu_unrequest_bus(smmu);
+	arm_smmu_unrequest_bus(smmu->bus_client);
 	arm_smmu_disable_regulators(smmu);
 
 	mutex_unlock(&smmu->power_lock);
@@ -3219,36 +3218,43 @@
 }
 
 static int arm_smmu_init_bus_scaling(struct platform_device *pdev,
-				     struct arm_smmu_device *smmu)
+				     uint32_t *client,
+				     struct msm_bus_scale_pdata **data)
 {
-	u32 master_id;
+	uint32_t __client;
 
-	if (of_property_read_u32(pdev->dev.of_node, "qcom,bus-master-id",
-				 &master_id)) {
-		dev_dbg(smmu->dev, "No bus scaling info\n");
+	if (!of_find_property(pdev->dev.of_node, "qcom,msm-bus,name", NULL)) {
+		dev_dbg(&pdev->dev, "No bus scaling info\n");
 		return 0;
 	}
 
-	smmu->bus_client_name = devm_kasprintf(
-		smmu->dev, GFP_KERNEL, "smmu-bus-client-%s",
-		dev_name(smmu->dev));
-
-	if (!smmu->bus_client_name)
-		return -ENOMEM;
-
-	smmu->bus_client = msm_bus_scale_register(
-		master_id, MSM_BUS_SLAVE_EBI_CH0, smmu->bus_client_name, true);
-	if (IS_ERR(&smmu->bus_client)) {
-		int ret = PTR_ERR(smmu->bus_client);
-
-		if (ret != -EPROBE_DEFER)
-			dev_err(smmu->dev, "Bus client registration failed\n");
-		return ret;
+	*data = msm_bus_cl_get_pdata(pdev);
+	if (*data) {
+		dev_err(&pdev->dev, "Unable to read bus-scaling from devicetree\n");
+		return -EINVAL;
 	}
 
+	__client = msm_bus_scale_register_client(*data);
+	if (!__client) {
+		dev_err(&pdev->dev, "Bus client registration failed\n");
+		msm_bus_cl_clear_pdata(*data);
+		return -EINVAL;
+	}
+
+	*client = __client;
 	return 0;
 }
 
+/*
+ * Bus APIs are not devm-safe.
+ */
+static void arm_smmu_exit_bus_scaling(uint32_t *client,
+				      struct msm_bus_scale_pdata **data)
+{
+	msm_bus_scale_unregister_client(*client);
+	msm_bus_cl_clear_pdata(*data);
+}
+
 static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
 {
 	unsigned long size;
@@ -3583,13 +3589,14 @@
 	if (err)
 		return err;
 
-	err = arm_smmu_init_bus_scaling(pdev, smmu);
+	err = arm_smmu_init_bus_scaling(pdev, &smmu->bus_client,
+					&smmu->bus_dt_data);
 	if (err)
 		return err;
 
 	err = arm_smmu_power_on(smmu);
 	if (err)
-		return err;
+		goto out_exit_bus;
 
 	err = arm_smmu_device_cfg_probe(smmu);
 	if (err)
@@ -3653,6 +3660,9 @@
 out_power_off:
 	arm_smmu_power_off(smmu);
 
+out_exit_bus:
+	arm_smmu_exit_bus_scaling(&smmu->bus_client, &smmu->bus_dt_data);
+
 	return err;
 }
 
@@ -3697,7 +3707,7 @@
 	writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
 	arm_smmu_power_off(smmu);
 
-	msm_bus_scale_unregister(smmu->bus_client);
+	arm_smmu_exit_bus_scaling(&smmu->bus_client, &smmu->bus_dt_data);
 
 	return 0;
 }