iommu: arm-smmu: Move to using bus bandwidth voting for bus clocks
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>
This commit is contained in:
parent
2829116b1e
commit
10f058a6e2
3 changed files with 55 additions and 36 deletions
|
@ -139,8 +139,8 @@ conditions.
|
||||||
time. This should be a list of 2-tuples of the format:
|
time. This should be a list of 2-tuples of the format:
|
||||||
<offset reg_value>.
|
<offset reg_value>.
|
||||||
|
|
||||||
- qcom,bus-master-id : The master ID of the bus, if a bus vote is needed.
|
Optional bus bindings as defined in
|
||||||
See include/dt-bindings/msm/msm-bus-ids.h.
|
Documentation/devicetree/bindings/arm/msm/msm_bus.txt may also be present.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
|
|
@ -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
|
* 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
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
@ -29,9 +29,14 @@
|
||||||
<GIC_SPI 367 IRQ_TYPE_EDGE_RISING>,
|
<GIC_SPI 367 IRQ_TYPE_EDGE_RISING>,
|
||||||
<GIC_SPI 368 IRQ_TYPE_EDGE_RISING>,
|
<GIC_SPI 368 IRQ_TYPE_EDGE_RISING>,
|
||||||
<GIC_SPI 369 IRQ_TYPE_EDGE_RISING>;
|
<GIC_SPI 369 IRQ_TYPE_EDGE_RISING>;
|
||||||
clocks = <&clock_gcc clk_aggre1_noc_clk>;
|
qcom,msm-bus,name = "smmu-bus-client-anoc1";
|
||||||
clock-names = "smmu_aggre1_noc_clk";
|
qcom,msm-bus,num-cases = <2>;
|
||||||
#clock-cells = <1>;
|
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 {
|
anoc2_smmu: arm,smmu-anoc2@16c0000 {
|
||||||
|
@ -52,9 +57,14 @@
|
||||||
<GIC_SPI 463 IRQ_TYPE_EDGE_RISING>,
|
<GIC_SPI 463 IRQ_TYPE_EDGE_RISING>,
|
||||||
<GIC_SPI 464 IRQ_TYPE_EDGE_RISING>,
|
<GIC_SPI 464 IRQ_TYPE_EDGE_RISING>,
|
||||||
<GIC_SPI 465 IRQ_TYPE_EDGE_RISING>;
|
<GIC_SPI 465 IRQ_TYPE_EDGE_RISING>;
|
||||||
clocks = <&clock_gcc clk_aggre2_noc_clk>;
|
qcom,msm-bus,name = "smmu-bus-client-anoc2";
|
||||||
clock-names = "smmu_aggre2_noc_clk";
|
qcom,msm-bus,num-cases = <2>;
|
||||||
#clock-cells = <1>;
|
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 {
|
lpass_q6_smmu: arm,smmu-lpass_q6@5100000 {
|
||||||
|
@ -116,15 +126,20 @@
|
||||||
<GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
|
<GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
vdd-supply = <&gdsc_bimc_smmu>;
|
vdd-supply = <&gdsc_bimc_smmu>;
|
||||||
clocks = <&clock_mmss clk_mmss_mnoc_ahb_clk>,
|
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_ahb_clk>,
|
||||||
<&clock_mmss clk_mmss_bimc_smmu_axi_clk>;
|
<&clock_mmss clk_mmss_bimc_smmu_axi_clk>;
|
||||||
clock-names = "mmss_mnoc_ahb_clk",
|
clock-names = "mmss_mnoc_ahb_clk",
|
||||||
"mmssnoc_axi_clk",
|
|
||||||
"mmss_bimc_smmu_ahb_clk",
|
"mmss_bimc_smmu_ahb_clk",
|
||||||
"mmss_bimc_smmu_axi_clk";
|
"mmss_bimc_smmu_axi_clk";
|
||||||
#clock-cells = <1>;
|
#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 {
|
kgsl_smmu: arm,smmu-kgsl@5040000 {
|
||||||
|
|
|
@ -410,8 +410,8 @@ struct arm_smmu_device {
|
||||||
struct mutex power_lock;
|
struct mutex power_lock;
|
||||||
unsigned int power_count;
|
unsigned int power_count;
|
||||||
|
|
||||||
struct msm_bus_client_handle *bus_client;
|
u32 bus_client;
|
||||||
char *bus_client_name;
|
struct msm_bus_scale_pdata *bus_pdata;
|
||||||
|
|
||||||
enum tz_smmu_device_id sec_id;
|
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)
|
if (!smmu->bus_client)
|
||||||
return 0;
|
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)
|
static int arm_smmu_unrequest_bus(struct arm_smmu_device *smmu)
|
||||||
{
|
{
|
||||||
if (!smmu->bus_client)
|
if (!smmu->bus_client)
|
||||||
return 0;
|
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)
|
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,
|
static int arm_smmu_init_bus_scaling(struct platform_device *pdev,
|
||||||
struct arm_smmu_device *smmu)
|
struct arm_smmu_device *smmu)
|
||||||
{
|
{
|
||||||
u32 master_id;
|
if (!of_find_property(pdev->dev.of_node, "qcom,msm-bus,name", NULL)) {
|
||||||
|
dev_dbg(&pdev->dev, "No bus scaling info\n");
|
||||||
if (of_property_read_u32(pdev->dev.of_node, "qcom,bus-master-id",
|
|
||||||
&master_id)) {
|
|
||||||
dev_dbg(smmu->dev, "No bus scaling info\n");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
smmu->bus_client_name = devm_kasprintf(
|
smmu->bus_pdata = msm_bus_cl_get_pdata(pdev);
|
||||||
smmu->dev, GFP_KERNEL, "smmu-bus-client-%s",
|
if (!smmu->bus_pdata) {
|
||||||
dev_name(smmu->dev));
|
dev_err(&pdev->dev, "Unable to read bus-scaling from DT\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!smmu->bus_client_name)
|
smmu->bus_client = msm_bus_scale_register_client(smmu->bus_pdata);
|
||||||
return -ENOMEM;
|
if (!smmu->bus_client) {
|
||||||
|
dev_err(&pdev->dev, "Bus client registration failed\n");
|
||||||
smmu->bus_client = msm_bus_scale_register(
|
return -EINVAL;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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)
|
static int arm_smmu_parse_impl_def_registers(struct arm_smmu_device *smmu)
|
||||||
{
|
{
|
||||||
struct device *dev = smmu->dev;
|
struct device *dev = smmu->dev;
|
||||||
|
@ -4035,6 +4038,7 @@ out_free_irqs:
|
||||||
free_irq(smmu->irqs[i], smmu);
|
free_irq(smmu->irqs[i], smmu);
|
||||||
|
|
||||||
out_put_masters:
|
out_put_masters:
|
||||||
|
arm_smmu_exit_bus_scaling(smmu);
|
||||||
for (node = rb_first(&smmu->masters); node; node = rb_next(node)) {
|
for (node = rb_first(&smmu->masters); node; node = rb_next(node)) {
|
||||||
struct arm_smmu_master *master
|
struct arm_smmu_master *master
|
||||||
= container_of(node, struct arm_smmu_master, node);
|
= 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);
|
arm_smmu_power_off(smmu);
|
||||||
mutex_unlock(&smmu->attach_lock);
|
mutex_unlock(&smmu->attach_lock);
|
||||||
|
|
||||||
msm_bus_scale_unregister(smmu->bus_client);
|
arm_smmu_exit_bus_scaling(smmu);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue