summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSrikar Srimath Tirumala <srikars@nvidia.com>2018-06-28 15:27:52 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2018-07-05 19:53:03 -0400
commita4051c12dc8b22cc0ee05c1a1f14c8f7665b68fa (patch)
treec927c71f5f6ec12848cfb4d642774e9c90938840
parentde9df1f6c982cf39b03d48506c79d50898608a41 (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.txt11
-rw-r--r--drivers/thermal/tegra_thermal_throttle.c43
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
38Required subnodes: The throttle node must provide at least one cooling device 38Required subnodes: The throttle node must provide at least one cooling device
39node with at least one clock to throttle. 39node with at least one clock to throttle.
@@ -95,8 +95,11 @@ Example:
95tegra_thermal_throttle { 95tegra_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
34struct tegra_throt_cdev_clk; 35struct tegra_throt_cdev_clk;
35struct tegra_throt_cdev { 36struct 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
58struct tegra_throt_cdev_clk { 61struct tegra_throt_cdev_clk {
@@ -70,16 +73,24 @@ static LIST_HEAD(tegra_throt_cdev_list);
70static DEFINE_MUTEX(tegra_throt_lock); 73static DEFINE_MUTEX(tegra_throt_lock);
71static struct dentry *tegra_throt_root; 74static struct dentry *tegra_throt_root;
72 75
76static char *cpu_clks[MAX_CPU_CLUSTERS] = { "cpu0", "cpu1", "cpu2", "cpu3" };
77
78static char *gpu_clks[] = { "gpu" };
79
73static struct tegra_throt_clk throt_clks[TEGRA_THROTTLE_MAX] = { 80static 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
532static 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
517static int tegra_throt_clk_init(struct platform_device *pdev, 547static 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);