arm: tegra: Register tegra-throttle cdev as driver
Arun Kumar Swain [Thu, 31 Jul 2014 03:52:25 +0000 (20:52 -0700)]
1. Register tegra-throttle cooling device as a
platform driver.
2. Obtain all the platform data (throtlle table
info) for all instances of blanced-throtlled cdev
from device tree and register them.

Change-Id: Ie92685eea3eb5cb18068b195adc9ab5f83762399
Signed-off-by: Arun Kumar Swain <arswain@nvidia.com>
Reviewed-on: http://git-master/r/449104
Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>
Tested-by: Diwakar Tundlam <dtundlam@nvidia.com>

12 files changed:
arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/cpu-tegra.c
arch/arm/mach-tegra/cpu-tegra.h
arch/arm/mach-tegra/dvfs.h
arch/arm/mach-tegra/edp_core.c
drivers/gpu/nvgpu/gk20a/clk_gk20a.c
drivers/gpu/nvgpu/gm20b/clk_gm20b.c
drivers/platform/tegra/Makefile
drivers/platform/tegra/tegra3_throttle.c [deleted file]
drivers/platform/tegra/tegra_throttle.c [moved from arch/arm/mach-tegra/tegra3_throttle.c with 72% similarity]
drivers/thermal/tmp006.c
include/linux/tegra_throttle.h [moved from arch/arm/mach-tegra/include/mach/thermal.h with 83% similarity]

index 9814233..7d0ec77 100644 (file)
@@ -103,9 +103,6 @@ else
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)         += cpu-tegra3.o
 endif
 endif
-ifeq ($(CONFIG_TEGRA_THERMAL_THROTTLE),y)
-obj-$(CONFIG_ARCH_TEGRA_12x_SOC)        += tegra3_throttle.o
-endif
 obj-$(CONFIG_DEBUG_ICEDCC)              += sysfs-dcc.o
 obj-$(CONFIG_TEGRA_CLUSTER_CONTROL)     += sysfs-cluster.o
 obj-$(CONFIG_TEGRA_DYNAMIC_PWRDET)      += powerdetect.o
index a791d7c..5aa6dbf 100644 (file)
@@ -1133,10 +1133,6 @@ static int __init tegra_cpufreq_init(void)
 
        suspend_index = table_data->suspend_index;
 
-       ret = tegra_throttle_init(&tegra_cpu_lock);
-       if (ret)
-               return ret;
-
        ret = tegra_auto_hotplug_init(&tegra_cpu_lock);
        if (ret)
                return ret;
@@ -1201,7 +1197,6 @@ late_initcall_sync(tegra_cpufreq_governor_init);
 
 static void __exit tegra_cpufreq_exit(void)
 {
-       tegra_throttle_exit();
        tegra_cpu_edp_exit();
        tegra_auto_hotplug_exit();
        cpufreq_unregister_driver(&tegra_cpufreq_driver);
index 9887cf9..3f479de 100644 (file)
@@ -22,7 +22,7 @@
 #define __MACH_TEGRA_CPU_TEGRA_H
 
 #include <linux/fs.h>
-#include <mach/thermal.h>
+#include <linux/tegra_throttle.h>
 
 unsigned int tegra_getspeed(unsigned int cpu);
 int tegra_update_cpu_speed(unsigned long rate);
index 9999ac5..a337117 100644 (file)
@@ -22,7 +22,7 @@
 #define _TEGRA_DVFS_H_
 
 #include <linux/of.h>
-#include <mach/thermal.h>
+#include <linux/tegra_throttle.h>
 
 #define MAX_DVFS_FREQS 40
 #define MAX_DVFS_TABLES        80
index 1f765fc..0ea2fac 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/tegra-soc.h>
 
 #include <mach/edp.h>
-#include <mach/thermal.h>
 
 #include "clock.h"
 #include "common.h"
index 41305e3..3fd25af 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/module.h>
 #include <linux/debugfs.h>
 #include <linux/clk/tegra.h>
-#include <mach/thermal.h>
 
 #include "gk20a.h"
 #include "hw_trim_gk20a.h"
index 8130f53..78f3669 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/module.h>
 #include <linux/debugfs.h>
 #include <linux/clk/tegra.h>
-#include <mach/thermal.h>
 
 #include "gk20a/gk20a.h"
 #include "hw_trim_gm20b.h"
index 8947e8a..40d9652 100644 (file)
@@ -34,6 +34,11 @@ ccflags-y += -I$(srctree)/arch/arm/mach-tegra
 obj-$(CONFIG_ARCH_TEGRA_12x_SOC) += tegra_soctherm.o
 endif
 
+ifeq ($(CONFIG_TEGRA_THERMAL_THROTTLE),y)
+ccflags-y += -I$(srctree)/arch/arm/mach-tegra
+obj-$(CONFIG_ARCH_TEGRA_12x_SOC)        += tegra_throttle.o
+endif
+
 ifneq ($(CONFIG_ARM64),)
 
 ccflags-y += -I$(srctree)/arch/arm/mach-tegra/include \
@@ -100,9 +105,6 @@ ifeq ($(CONFIG_TEGRA_CPUQUIET),y)
 obj-$(CONFIG_ARCH_TEGRA_13x_SOC)         += cpuquiet.o
 endif
 endif
-ifeq ($(CONFIG_TEGRA_THERMAL_THROTTLE),y)
-obj-$(CONFIG_ARCH_TEGRA_13x_SOC)        += tegra3_throttle.o
-endif
 
 obj-y += latency_allowance.o
 obj-$(CONFIG_ARCH_TEGRA_12x_SOC)        += tegra12x_la.o
diff --git a/drivers/platform/tegra/tegra3_throttle.c b/drivers/platform/tegra/tegra3_throttle.c
deleted file mode 100644 (file)
index e2ed891..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-/* Automatically generated file; DO NOT EDIT. */
-#include "../../../arch/arm/mach-tegra/tegra3_throttle.c"
similarity index 72%
rename from arch/arm/mach-tegra/tegra3_throttle.c
rename to drivers/platform/tegra/tegra_throttle.c
index 0ec071c..53889cd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/arm/mach-tegra/tegra3_throttle.c
+ * drivers/platform/tegra/tegra_throttle.c
  *
  * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved.
  *
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
 #include <linux/thermal.h>
+#include <linux/tegra_throttle.h>
+#include <linux/of.h>
 #include <linux/module.h>
-#include <mach/thermal.h>
+#include <linux/platform_device.h>
 
 #include "clock.h"
 #include "cpu-tegra.h"
 
 /* cpu_throttle_lock is tegra_cpu_lock from cpu-tegra.c */
-static struct mutex *cpu_throttle_lock;
 static DEFINE_MUTEX(bthrot_list_lock);
 static LIST_HEAD(bthrot_list);
+static LIST_HEAD(bthrot_cdev_list);
 static int num_throt;
 static struct cpufreq_frequency_table *cpu_freq_table;
 static unsigned long cpu_throttle_lowest_speed;
@@ -61,6 +63,13 @@ static struct {
 
 static bool tegra_throttle_init_failed;
 
+struct tegra_throttle_data {
+       char *cdev_type;
+       struct throttle_table *throt_tab;
+       u32 num_states;
+       struct list_head list;
+};
+
 #define CAP_TBL_CAP_NAME(index)        (cap_freqs_table[index].cap_name)
 #define CAP_TBL_CAP_CLK(index) (cap_freqs_table[index].cap_clk)
 #define CAP_TBL_CAP_FREQ(index)        (cap_freqs_table[index].cap_freq)
@@ -323,6 +332,16 @@ struct thermal_cooling_device *balanced_throttle_register(
 #ifdef CONFIG_DEBUG_FS
        char name[32];
 #endif
+
+       bthrot->cdev = thermal_cooling_device_register(
+                                               type,
+                                               bthrot,
+                                               &tegra_throttle_cooling_ops);
+       if (IS_ERR(bthrot->cdev)) {
+               bthrot->cdev = NULL;
+               return ERR_PTR(-ENODEV);
+       }
+
        mutex_lock(&bthrot_list_lock);
        num_throt++;
        list_add(&bthrot->node, &bthrot_list);
@@ -336,19 +355,10 @@ struct thermal_cooling_device *balanced_throttle_register(
                return ERR_PTR(-ENODEV);
 #endif
 
-       bthrot->cdev = thermal_cooling_device_register(
-                                               type,
-                                               bthrot,
-                                               &tegra_throttle_cooling_ops);
-       if (IS_ERR(bthrot->cdev)) {
-               bthrot->cdev = NULL;
-               return ERR_PTR(-ENODEV);
-       }
-
        return bthrot->cdev;
 }
 
-int __init tegra_throttle_init(struct mutex *cpu_lock)
+static int tegra_throttle_init(void)
 {
        int i;
        struct clk *c;
@@ -362,8 +372,6 @@ int __init tegra_throttle_init(struct mutex *cpu_lock)
        cpu_throttle_lowest_speed =
                cpu_freq_table[table_data->throttle_lowest_index].frequency;
 
-       cpu_throttle_lock = cpu_lock;
-
 #ifdef CONFIG_DEBUG_FS
        throttle_debugfs_root = debugfs_create_dir("tegra_throttle", NULL);
        if (IS_ERR_OR_NULL(throttle_debugfs_root))
@@ -388,10 +396,158 @@ int __init tegra_throttle_init(struct mutex *cpu_lock)
        return 0;
 }
 
-void tegra_throttle_exit(void)
+static void tegra_throttle_exit(void)
 {
 #ifdef CONFIG_DEBUG_FS
        debugfs_remove_recursive(throttle_debugfs_root);
 #endif
 }
 
+
+static struct throttle_table
+       *throttle_parse_dt_thrt_tbl(struct device *dev,
+               struct device_node *np, int num_states)
+{
+       int i, j;
+       u32 *val;
+       int ret = 0;
+       int count = 0;
+       struct throttle_table *throt_tab;
+
+       throt_tab = devm_kzalloc(dev,
+                       sizeof(struct throttle_table)*num_states, GFP_KERNEL);
+       if (IS_ERR_OR_NULL(throt_tab))
+               return NULL;
+
+       val = kzalloc(sizeof(u32)*num_states*NUM_OF_CAP_FREQS, GFP_KERNEL);
+       if (IS_ERR_OR_NULL(val))
+               return NULL;
+
+       ret = of_property_read_u32_array(np, "throttle_table",
+                                       val, num_states*NUM_OF_CAP_FREQS);
+       if (ret) {
+               dev_err(dev,
+                       "malformed throttle_table property in %s : no. of entries:%d; return value: %d\n",
+                       np->full_name, num_states*NUM_OF_CAP_FREQS, ret);
+               return NULL;
+       }
+
+       for (i = 0; i < num_states; ++i) {
+               for (j = 0; j < NUM_OF_CAP_FREQS; ++j)
+                       throt_tab[i].cap_freqs[j] = val[count++];
+       }
+
+       kfree(val);
+       return throt_tab;
+}
+
+static struct tegra_throttle_data
+               *parse_throttle_dt_data(struct device *dev)
+{
+       u32 val;
+       const char *str;
+       struct device_node *child;
+       struct tegra_throttle_data *pdata = NULL;
+       struct device_node *np = dev->of_node;
+
+       for_each_child_of_node(np, child) {
+               /* Check whether child is enabled or not */
+               if (!of_device_is_available(child))
+                       continue;
+
+               pdata = devm_kzalloc(dev,
+                               sizeof(struct tegra_throttle_data), GFP_KERNEL);
+               if (IS_ERR_OR_NULL(pdata))
+                       return NULL;
+
+               if (of_property_read_string(child, "cdev-type", &str) == 0)
+                       pdata->cdev_type = (char *)str;
+
+               if (of_property_read_u32(child, "num_states", &val) == 0)
+                       pdata->num_states = val;
+
+               pdata->throt_tab =
+                       throttle_parse_dt_thrt_tbl(dev, child, val);
+               if  (!pdata->throt_tab)
+                       return NULL;
+
+               list_add(&pdata->list, &bthrot_cdev_list);
+
+       }
+
+       return pdata;
+}
+
+static int tegra30_throttle_probe(struct platform_device *pdev)
+{
+       char *type;
+       int ret = 0;
+       struct tegra_throttle_data *pdata;
+       struct balanced_throttle *bthrot;
+
+       ret = tegra_throttle_init();
+       if (ret) {
+               dev_err(&pdev->dev, "tegra throttle init failed\n");
+               return -ENOMEM;
+       }
+
+       pdata = parse_throttle_dt_data(&pdev->dev);
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "No Platform data\n");
+               return -EIO;
+       }
+
+       list_for_each_entry(pdata, &bthrot_cdev_list, list) {
+               bthrot = devm_kzalloc(&pdev->dev,
+                       sizeof(struct balanced_throttle), GFP_KERNEL);
+               if (IS_ERR(bthrot))
+                       return -ENOMEM;
+
+               bthrot->throt_tab_size
+                       = pdata->num_states;
+               bthrot->throt_tab = pdata->throt_tab;
+               type = pdata->cdev_type;
+
+               if (IS_ERR_OR_NULL(balanced_throttle_register(bthrot, type)))
+                       dev_err(&pdev->dev, "balanced_throttle_register FAILED\n");
+       }
+
+       return 0;
+}
+
+static int tegra30_throttle_remove(struct platform_device *pdev)
+{
+       struct balanced_throttle *bthrot;
+
+       mutex_lock(&bthrot_list_lock);
+       list_for_each_entry(bthrot, &bthrot_list, node) {
+               thermal_cooling_device_unregister(bthrot->cdev);
+       }
+       mutex_unlock(&bthrot_list_lock);
+
+       tegra_throttle_exit();
+
+       return 0;
+}
+
+static struct of_device_id tegra30_throttle_of_match[] = {
+       { .compatible = "nvidia,tegra30-throttle", },
+       { },
+};
+
+static struct platform_driver tegra30_throtlle_driver = {
+       .driver = {
+               .name = "tegra-throttle",
+               .owner = THIS_MODULE,
+               .of_match_table = tegra30_throttle_of_match,
+       },
+       .probe = tegra30_throttle_probe,
+       .remove = tegra30_throttle_remove,
+};
+
+module_platform_driver(tegra30_throtlle_driver);
+
+MODULE_DESCRIPTION("Tegra Balanced Throttle Driver");
+MODULE_AUTHOR("NVIDIA");
+MODULE_LICENSE("GPL");
index c0d401b..db3060a 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Driver for TMP006, Skin temperature monitoring device
  *
- * Copyright (c) 2013, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2013-2014 NVIDIA Corporation. 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 as published by
@@ -27,8 +27,8 @@
 #include <linux/err.h>
 #include <linux/device.h>
 #include <linux/delay.h>
+#include <linux/tegra_throttle.h>
 #include <linux/thermal.h>
-#include <mach/thermal.h>
 #include <linux/regulator/consumer.h>
 #include <linux/regmap.h>
 
similarity index 83%
rename from arch/arm/mach-tegra/include/mach/thermal.h
rename to include/linux/tegra_throttle.h
index 800eb74..a2d1789 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * arch/arm/mach-tegra/thermal.h
+ * include/linux/tegra_throttle.h
  *
- * Copyright (c) 2010-2013 NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2010-2014 NVIDIA CORPORATION. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -14,8 +14,8 @@
  *
  */
 
-#ifndef __MACH_THERMAL_H
-#define __MACH_THERMAL_H
+#ifndef __TEGRA_THROTTLE_H
+#define __TEGRA_THROTTLE_H
 
 #include <linux/therm_est.h>
 #include <linux/thermal.h>
@@ -59,22 +59,16 @@ struct balanced_throttle {
 };
 
 #ifdef CONFIG_TEGRA_THERMAL_THROTTLE
-int tegra_throttle_init(struct mutex *cpu_lock);
 struct thermal_cooling_device *balanced_throttle_register(
                struct balanced_throttle *bthrot,
                char *type);
-void tegra_throttle_exit(void);
 bool tegra_is_throttling(int *count);
 unsigned long tegra_throttle_governor_speed(unsigned long requested_speed);
 #else
-static inline int tegra_throttle_init(struct mutex *cpu_lock)
-{ return 0; }
 static inline struct thermal_cooling_device *balanced_throttle_register(
                struct balanced_throttle *bthrot,
                char *type)
 { return ERR_PTR(-ENODEV); }
-static inline void tegra_throttle_exit(void)
-{}
 static inline bool tegra_is_throttling(int *count)
 { return false; }
 static inline unsigned long tegra_throttle_governor_speed(
@@ -82,4 +76,4 @@ static inline unsigned long tegra_throttle_governor_speed(
 { return requested_speed; }
 #endif /* CONFIG_TEGRA_THERMAL_THROTTLE */
 
-#endif /* __MACH_THERMAL_H */
+#endif /* __TEGRA_THROTTLE_H */