OSDN Git Service

iommu: arm-smmu: Move to using bus bandwidth voting for bus clocks
authorPratik Patel <pratikp@codeaurora.org>
Mon, 16 Jan 2017 20:44:48 +0000 (12:44 -0800)
committerPatrick Daly <pdaly@codeaurora.org>
Sat, 21 Jan 2017 00:05:03 +0000 (16:05 -0800)
Bus clocks are managed via bus apis and hence move to using them for
enabling bus clocks. The previous method could enable a bus clock at a
higher than required frequency, wasting power.

The power on sequence is regulator on, bus vote, and then enable
remaining clocks.

Remove all clocks which are of RPM_SMD type (including mmssnoc_axi_clk)
since these are managed by the bus driver. Using an active-only bus vote
instead should save power when APPS is power collapsed.

Keep the mmss_mnoc_ahb_clk because it is a branch clock type which is
not managed by the bus driver. No active-only mode is available for this
clock.

Change-Id: I3b35d81098b8bd5299b27e85d27aa959e7cf415a
Signed-off-by: Pratik Patel <pratikp@codeaurora.org>
Signed-off-by: Patrick Daly <pdaly@codeaurora.org>
Documentation/devicetree/bindings/iommu/arm,smmu.txt
arch/arm/boot/dts/qcom/msm-arm-smmu-8998.dtsi
drivers/iommu/arm-smmu.c

index d00a5c1..9e512d1 100644 (file)
@@ -139,8 +139,8 @@ conditions.
                   time. This should be a list of 2-tuples of the format:
                   <offset reg_value>.
 
-- 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.
+Optional bus bindings as defined in
+Documentation/devicetree/bindings/arm/msm/msm_bus.txt may also be present.
 
 Example:
 
index 0ba86e8..ecfff13 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
                           <GIC_SPI 367 IRQ_TYPE_EDGE_RISING>,
                           <GIC_SPI 368 IRQ_TYPE_EDGE_RISING>,
                           <GIC_SPI 369 IRQ_TYPE_EDGE_RISING>;
-               clocks = <&clock_gcc clk_aggre1_noc_clk>;
-               clock-names = "smmu_aggre1_noc_clk";
-               #clock-cells = <1>;
+               qcom,msm-bus,name = "smmu-bus-client-anoc1";
+               qcom,msm-bus,num-cases = <2>;
+               qcom,msm-bus,active-only;
+               qcom,msm-bus,num-paths = <1>;
+               /* aggre1_noc_clk */
+               qcom,msm-bus,vectors-KBps =
+                               <84 10062 0 0>,
+                               <84 10062 0 1000>;
        };
 
        anoc2_smmu: arm,smmu-anoc2@16c0000 {
                           <GIC_SPI 463 IRQ_TYPE_EDGE_RISING>,
                           <GIC_SPI 464 IRQ_TYPE_EDGE_RISING>,
                           <GIC_SPI 465 IRQ_TYPE_EDGE_RISING>;
-               clocks = <&clock_gcc clk_aggre2_noc_clk>;
-               clock-names = "smmu_aggre2_noc_clk";
-               #clock-cells = <1>;
+               qcom,msm-bus,name = "smmu-bus-client-anoc2";
+               qcom,msm-bus,num-cases = <2>;
+               qcom,msm-bus,active-only;
+               qcom,msm-bus,num-paths = <1>;
+               /* aggre2_noc_clk */
+               qcom,msm-bus,vectors-KBps =
+                               <117 10065 0 0>,
+                               <117 10065 0 1000>;
        };
 
        lpass_q6_smmu: arm,smmu-lpass_q6@5100000 {
                           <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
                vdd-supply = <&gdsc_bimc_smmu>;
                clocks = <&clock_mmss clk_mmss_mnoc_ahb_clk>,
-                       <&clock_gcc clk_mmssnoc_axi_clk>,
                        <&clock_mmss clk_mmss_bimc_smmu_ahb_clk>,
                        <&clock_mmss clk_mmss_bimc_smmu_axi_clk>;
                clock-names = "mmss_mnoc_ahb_clk",
-                       "mmssnoc_axi_clk",
                        "mmss_bimc_smmu_ahb_clk",
                        "mmss_bimc_smmu_axi_clk";
                #clock-cells = <1>;
-               qcom,bus-master-id = <MSM_BUS_MNOC_BIMC_MAS>;
+               qcom,msm-bus,name = "smmu-bus-client-mmss";
+               qcom,msm-bus,num-cases = <2>;
+               qcom,msm-bus,active-only;
+               qcom,msm-bus,num-paths = <2>;
+               /* ahb_clk_src, mmssnoc_axi_clk */
+               qcom,msm-bus,vectors-KBps =
+                               <102 722 0 0>, <29 512 0 0>,
+                               <102 722 0 1000>, <29 512 0 1000>;
        };
 
        kgsl_smmu: arm,smmu-kgsl@5040000 {
index fbe2302..ce15e15 100644 (file)
@@ -410,8 +410,8 @@ struct arm_smmu_device {
        struct mutex                    power_lock;
        unsigned int                    power_count;
 
-       struct msm_bus_client_handle    *bus_client;
-       char                            *bus_client_name;
+       u32                             bus_client;
+       struct msm_bus_scale_pdata      *bus_pdata;
 
        enum tz_smmu_device_id          sec_id;
 };
@@ -912,14 +912,14 @@ static int arm_smmu_request_bus(struct arm_smmu_device *smmu)
 {
        if (!smmu->bus_client)
                return 0;
-       return msm_bus_scale_update_bw(smmu->bus_client, 0, 1000);
+       return msm_bus_scale_client_update_request(smmu->bus_client, 1);
 }
 
 static int arm_smmu_unrequest_bus(struct arm_smmu_device *smmu)
 {
        if (!smmu->bus_client)
                return 0;
-       return msm_bus_scale_update_bw(smmu->bus_client, 0, 0);
+       return msm_bus_scale_client_update_request(smmu->bus_client, 0);
 }
 
 static int arm_smmu_disable_regulators(struct arm_smmu_device *smmu)
@@ -3571,34 +3571,37 @@ static int arm_smmu_init_clocks(struct arm_smmu_device *smmu)
 static int arm_smmu_init_bus_scaling(struct platform_device *pdev,
                                     struct arm_smmu_device *smmu)
 {
-       u32 master_id;
-
-       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);
+       smmu->bus_pdata = msm_bus_cl_get_pdata(pdev);
+       if (!smmu->bus_pdata) {
+               dev_err(&pdev->dev, "Unable to read bus-scaling from DT\n");
+               return -EINVAL;
+       }
 
-               if (ret != -EPROBE_DEFER)
-                       dev_err(smmu->dev, "Bus client registration failed\n");
-               return ret;
+       smmu->bus_client = msm_bus_scale_register_client(smmu->bus_pdata);
+       if (!smmu->bus_client) {
+               dev_err(&pdev->dev, "Bus client registration failed\n");
+               return -EINVAL;
        }
 
        return 0;
 }
 
+static void arm_smmu_exit_bus_scaling(struct arm_smmu_device *smmu)
+{
+       if (smmu->bus_client)
+               msm_bus_scale_unregister_client(smmu->bus_client);
+       if (smmu->bus_pdata)
+               msm_bus_cl_clear_pdata(smmu->bus_pdata);
+
+       smmu->bus_client = 0;
+       smmu->bus_pdata = NULL;
+}
+
 static int arm_smmu_parse_impl_def_registers(struct arm_smmu_device *smmu)
 {
        struct device *dev = smmu->dev;
@@ -4035,6 +4038,7 @@ out_free_irqs:
                free_irq(smmu->irqs[i], smmu);
 
 out_put_masters:
+       arm_smmu_exit_bus_scaling(smmu);
        for (node = rb_first(&smmu->masters); node; node = rb_next(node)) {
                struct arm_smmu_master *master
                        = container_of(node, struct arm_smmu_master, node);
@@ -4086,7 +4090,7 @@ static int arm_smmu_device_remove(struct platform_device *pdev)
                arm_smmu_power_off(smmu);
        mutex_unlock(&smmu->attach_lock);
 
-       msm_bus_scale_unregister(smmu->bus_client);
+       arm_smmu_exit_bus_scaling(smmu);
 
        return 0;
 }