diff options
author | Srikar Srimath Tirumala <srikars@nvidia.com> | 2018-06-28 15:27:52 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2018-07-05 19:53:03 -0400 |
commit | a4051c12dc8b22cc0ee05c1a1f14c8f7665b68fa (patch) | |
tree | c927c71f5f6ec12848cfb4d642774e9c90938840 | |
parent | de9df1f6c982cf39b03d48506c79d50898608a41 (diff) |
thermal: throttle: fix for floorswept platforms
Pass the clock handles for all the CPU clusters instead of just the
one cluster from DT. The NAFLLL CLUSTER clock id refers to the
physical cluster and is not guaranteed to be present on floorswept
configurations.
Add logic to look for the appropriate clock handle from a list of
clock handles and fail the driver registration if a missing clock
is referenced in the cooling device.
Bug 2224577
Change-Id: I36a7d308eaa573c6b99390e3fbf36a3828377494
Signed-off-by: Srikar Srimath Tirumala <srikars@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1764644
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Bo Yan <byan@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r-- | Documentation/devicetree/bindings/platform/tegra/nvidia,tegra_thermal_throttle.txt | 11 | ||||
-rw-r--r-- | drivers/thermal/tegra_thermal_throttle.c | 43 |
2 files changed, 43 insertions, 11 deletions
diff --git a/Documentation/devicetree/bindings/platform/tegra/nvidia,tegra_thermal_throttle.txt b/Documentation/devicetree/bindings/platform/tegra/nvidia,tegra_thermal_throttle.txt index 7444ef0ce..e1f0cbfe5 100644 --- a/Documentation/devicetree/bindings/platform/tegra/nvidia,tegra_thermal_throttle.txt +++ b/Documentation/devicetree/bindings/platform/tegra/nvidia,tegra_thermal_throttle.txt | |||
@@ -31,9 +31,9 @@ Required properties: | |||
31 | - clocks : This property provides a list of clocks that can be throttled. Must | 31 | - clocks : This property provides a list of clocks that can be throttled. Must |
32 | provide at least one valid clock. Must contain one entry for each entry in | 32 | provide at least one valid clock. Must contain one entry for each entry in |
33 | clock-names. See ../clocks/clock-bindings.txt for details. | 33 | clock-names. See ../clocks/clock-bindings.txt for details. |
34 | - clock-names: Must include one of the following entries: | 34 | - clock-names: Must include either: |
35 | - cpu: for throttling the clocks of all the CPUs. | 35 | - Clock names for all CPUs "cpu0, cpu1, cpu2, cpu3", to throttle all CPUs. Or |
36 | - gpu: for thorttling the GPU clock. | 36 | - Clock name for GPU "gpu" to throttle the GPU. |
37 | 37 | ||
38 | Required subnodes: The throttle node must provide at least one cooling device | 38 | Required subnodes: The throttle node must provide at least one cooling device |
39 | node with at least one clock to throttle. | 39 | node with at least one clock to throttle. |
@@ -95,8 +95,11 @@ Example: | |||
95 | tegra_thermal_throttle { | 95 | tegra_thermal_throttle { |
96 | compatible = "nvidia,tegra-thermal-throttle"; | 96 | compatible = "nvidia,tegra-thermal-throttle"; |
97 | clocks = <&bpmp_clks TEGRA194_CLK_NAFLL_CLUSTER0>, | 97 | clocks = <&bpmp_clks TEGRA194_CLK_NAFLL_CLUSTER0>, |
98 | <&bpmp_clks TEGRA194_CLK_NAFLL_CLUSTER1>, | ||
99 | <&bpmp_clks TEGRA194_CLK_NAFLL_CLUSTER2>, | ||
100 | <&bpmp_clks TEGRA194_CLK_NAFLL_CLUSTER3>, | ||
98 | <&bpmp_clks TEGRA194_CLK_NAFLL_GPU>; | 101 | <&bpmp_clks TEGRA194_CLK_NAFLL_GPU>; |
99 | clock-names = "cpu", "gpu"; | 102 | clock-names = "cpu0", "cpu1", "cpu2", "cpu3", "gpu"; |
100 | cpu_balanced { | 103 | cpu_balanced { |
101 | cdev-type = "cpu-balanced"; | 104 | cdev-type = "cpu-balanced"; |
102 | #cooling-cells = <2>; | 105 | #cooling-cells = <2>; |
diff --git a/drivers/thermal/tegra_thermal_throttle.c b/drivers/thermal/tegra_thermal_throttle.c index c2c9dd68c..dde456b0b 100644 --- a/drivers/thermal/tegra_thermal_throttle.c +++ b/drivers/thermal/tegra_thermal_throttle.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #define KHZ_TO_HZ 1000 | 30 | #define KHZ_TO_HZ 1000 |
31 | #define CPU_STEP_HZ (76800 * KHZ_TO_HZ) | 31 | #define CPU_STEP_HZ (76800 * KHZ_TO_HZ) |
32 | #define GPU_STEP_HZ (102 * KHZ_TO_HZ * KHZ_TO_HZ) | 32 | #define GPU_STEP_HZ (102 * KHZ_TO_HZ * KHZ_TO_HZ) |
33 | #define MAX_CPU_CLUSTERS 4 | ||
33 | 34 | ||
34 | struct tegra_throt_cdev_clk; | 35 | struct tegra_throt_cdev_clk; |
35 | struct tegra_throt_cdev { | 36 | struct tegra_throt_cdev { |
@@ -53,6 +54,8 @@ struct tegra_throt_clk { | |||
53 | int type; | 54 | int type; |
54 | int steps; | 55 | int steps; |
55 | char *name; | 56 | char *name; |
57 | char **clk_names; | ||
58 | int num_clk_handles; | ||
56 | }; | 59 | }; |
57 | 60 | ||
58 | struct tegra_throt_cdev_clk { | 61 | struct tegra_throt_cdev_clk { |
@@ -70,16 +73,24 @@ static LIST_HEAD(tegra_throt_cdev_list); | |||
70 | static DEFINE_MUTEX(tegra_throt_lock); | 73 | static DEFINE_MUTEX(tegra_throt_lock); |
71 | static struct dentry *tegra_throt_root; | 74 | static struct dentry *tegra_throt_root; |
72 | 75 | ||
76 | static char *cpu_clks[MAX_CPU_CLUSTERS] = { "cpu0", "cpu1", "cpu2", "cpu3" }; | ||
77 | |||
78 | static char *gpu_clks[] = { "gpu" }; | ||
79 | |||
73 | static struct tegra_throt_clk throt_clks[TEGRA_THROTTLE_MAX] = { | 80 | static struct tegra_throt_clk throt_clks[TEGRA_THROTTLE_MAX] = { |
74 | { | 81 | { |
75 | .name = "cpu", | 82 | .name = "cpu", |
83 | .clk_names = cpu_clks, | ||
76 | .step_hz = CPU_STEP_HZ, | 84 | .step_hz = CPU_STEP_HZ, |
77 | .type = TEGRA_THROTTLE_CPU | 85 | .type = TEGRA_THROTTLE_CPU, |
86 | .num_clk_handles = MAX_CPU_CLUSTERS, | ||
78 | }, | 87 | }, |
79 | { | 88 | { |
80 | .name = "gpu", | 89 | .name = "gpu", |
90 | .clk_names = gpu_clks, | ||
81 | .step_hz = GPU_STEP_HZ, | 91 | .step_hz = GPU_STEP_HZ, |
82 | .type = TEGRA_THROTTLE_GPU | 92 | .type = TEGRA_THROTTLE_GPU, |
93 | .num_clk_handles = 1, | ||
83 | }, | 94 | }, |
84 | }; | 95 | }; |
85 | 96 | ||
@@ -131,7 +142,11 @@ static struct tegra_throt_clk *tegra_throt_find_clk( | |||
131 | 142 | ||
132 | for (i = 0; i < TEGRA_THROTTLE_MAX; i++) | 143 | for (i = 0; i < TEGRA_THROTTLE_MAX; i++) |
133 | if (pclks[i].type == type) | 144 | if (pclks[i].type == type) |
134 | return &pclks[i]; | 145 | break; |
146 | |||
147 | if (!IS_ERR(pclks[i].clk)) | ||
148 | return &pclks[i]; | ||
149 | |||
135 | return NULL; | 150 | return NULL; |
136 | } | 151 | } |
137 | 152 | ||
@@ -410,8 +425,8 @@ static int tegra_throt_cdev_clk_init(struct platform_device *pdev, | |||
410 | for (i = 0, j = 0; j < tcd->num_clks; i = i + 3, j++) { | 425 | for (i = 0, j = 0; j < tcd->num_clks; i = i + 3, j++) { |
411 | tcc = &tcd->clks[j]; | 426 | tcc = &tcd->clks[j]; |
412 | tclk = tegra_throt_find_clk(pclks, prop[i]); | 427 | tclk = tegra_throt_find_clk(pclks, prop[i]); |
413 | if (IS_ERR(tclk)) | 428 | if (!tclk) |
414 | return -EINVAL; | 429 | return -ENODEV; |
415 | 430 | ||
416 | tcc->throt_clk = tclk; | 431 | tcc->throt_clk = tclk; |
417 | tcc->slope_adj = prop[i+1]; | 432 | tcc->slope_adj = prop[i+1]; |
@@ -514,6 +529,21 @@ static int tegra_throt_freq_gov_init(int type) | |||
514 | return ret; | 529 | return ret; |
515 | } | 530 | } |
516 | 531 | ||
532 | static int tegra_throt_clk_get(struct platform_device *pdev, | ||
533 | struct tegra_throt_clk *pclk) | ||
534 | { | ||
535 | int i; | ||
536 | |||
537 | for (i = 0; i < pclk->num_clk_handles; i++) { | ||
538 | pclk->clk = devm_clk_get(&pdev->dev, pclk->clk_names[i]); | ||
539 | if (!IS_ERR(pclk->clk)) | ||
540 | return 0; | ||
541 | } | ||
542 | |||
543 | dev_err(&pdev->dev, "failed to get clk:%s\n", pclk[i].name); | ||
544 | return -ENODEV; | ||
545 | } | ||
546 | |||
517 | static int tegra_throt_clk_init(struct platform_device *pdev, | 547 | static int tegra_throt_clk_init(struct platform_device *pdev, |
518 | struct tegra_throt_clk *pclks) | 548 | struct tegra_throt_clk *pclks) |
519 | { | 549 | { |
@@ -526,8 +556,7 @@ static int tegra_throt_clk_init(struct platform_device *pdev, | |||
526 | continue; | 556 | continue; |
527 | } | 557 | } |
528 | 558 | ||
529 | pclks[i].clk = devm_clk_get(&pdev->dev, pclks[i].name); | 559 | if (tegra_throt_clk_get(pdev, &pclks[i]) != 0) |
530 | if (IS_ERR(pclks[i].clk)) | ||
531 | continue; | 560 | continue; |
532 | 561 | ||
533 | INIT_LIST_HEAD(&pclks[i].cdev_clk_list); | 562 | INIT_LIST_HEAD(&pclks[i].cdev_clk_list); |