#include "thermal_core.h"
+#if defined(CONFIG_ECT)
+#include <soc/samsung/ect_parser.h>
+#include "samsung/exynos_tmu.h"
+#endif
+
/*** Private data structures to represent thermal device tree data ***/
/**
struct device_node *np, *child, *sensor_np;
struct thermal_zone_device *tzd = ERR_PTR(-ENODEV);
+#if defined(CONFIG_ECT)
+ struct thermal_instance *instance;
+ struct __thermal_zone *__tz;
+ void *thermal_block;
+ struct ect_ap_thermal_function *function;
+ int i = 0, j = 0;
+ struct exynos_tmu_data *tmu_data;
+ int hotplug_threshold_temp = 0, hotplug_flag = 0;
+ unsigned int level, freq;
+ int temperature;
+#endif
+
np = of_find_node_by_name(NULL, "thermal-zones");
if (!np)
return ERR_PTR(-ENODEV);
if (sensor_specs.np == sensor_np && id == sensor_id) {
tzd = thermal_zone_of_add_sensor(child, sensor_np,
data, ops);
+#if defined(CONFIG_ECT)
+ __tz = tzd->devdata;
+ tmu_data = (struct exynos_tmu_data *)data;
+
+ thermal_block = ect_get_block(BLOCK_AP_THERMAL);
+ if (thermal_block == NULL) {
+ dev_err(dev, "Failed to get thermal block");
+ return ERR_PTR(-EINVAL);
+ }
+
+ pr_info("%s %d thermal zone_name = %s \n", __func__, __LINE__, tzd->type);
+ function = ect_ap_thermal_get_function(thermal_block, tzd->type);
+ if (function == NULL) {
+ dev_err(dev, "Failed to get thermal block %s", tzd->type);
+ return ERR_PTR(-EINVAL);
+ }
+
+ __tz->ntrips = __tz->num_tbps = function->num_of_range;
+ dev_info(dev, "Trip count parsed from ECT : %d, zone : %s", function->num_of_range, tzd->type);
+
+ instance = list_first_entry(&tzd->thermal_instances, typeof(*instance), tz_node);
+
+ for (i = 0; i < function->num_of_range; ++i) {
+ temperature = function->range_list[i].lower_bound_temperature;
+ freq = function->range_list[i].max_frequency;
+
+ for (j = 0; j < ARRAY_SIZE(tz_zone_names); j++)
+ if (!strcasecmp(tzd->type, tz_zone_names[j])) {
+ switch (j) {
+ case MNGS_QUAD :
+ level = cpufreq_cooling_get_level(4, freq);
+ break;
+ case APOLLO :
+ level = cpufreq_cooling_get_level(0, freq);
+ break;
+ case GPU :
+ level = gpufreq_cooling_get_level(0, freq);
+ break;
+ case ISP :
+ level = isp_cooling_get_fps(0, freq);
+ break;
+ case MNGS_DUAL :
+ level = cpufreq_cooling_get_level(4, freq);
+ break;
+ }
+ }
+
+ if (level > 100) {
+ dev_err(dev, "Level is strange!!! freq = %u, level = %u\n", freq, level);
+ level = 0;
+ }
+
+ /* Change 'trips' and 'tbps' data with ECT data instead of DT data */
+ __tz->trips[i].temperature = temperature * MCELSIUS;
+ __tz->tbps[i].max = level;
+
+ /* Change thermal instance information with tbps data */
+ instance->upper = __tz->tbps[i].max;
+ instance = list_next_entry(instance, tz_node);
+ pr_info("Parsed From ECT : [%d] Temperature : %d, frequency : %u, level = %lu\n", i, temperature, freq, __tz->tbps[i].max);
+
+ if (function->range_list[i].flag != hotplug_flag) {
+ hotplug_threshold_temp = temperature;
+ hotplug_flag = function->range_list[i].flag;
+ tmu_data->hotplug_out_threshold = temperature;
+
+ if (i)
+ tmu_data->hotplug_in_threshold = function->range_list[i-1].lower_bound_temperature;
+
+ pr_info("[ECT]hotplug_threshold : %d \n", hotplug_threshold_temp);
+ pr_info("[ECT]hotplug_in_threshold : %d \n", tmu_data->hotplug_in_threshold);
+ pr_info("[ECT]hotplug_out_threshold : %d \n", tmu_data->hotplug_out_threshold);
+ }
+ }
+
+ if (hotplug_threshold_temp != 0)
+ tmu_data->hotplug_enable = true;
+ else
+ tmu_data->hotplug_enable = false;
+#endif
of_node_put(sensor_specs.np);
of_node_put(child);
#define EXYNOS_TMU_DEM_ENABLE (1)
#define EXYNOS_TMU_DEM_SHIFT (4)
-#define MCELSIUS 1000
-
#define TOTAL_SENSORS 8
static bool suspended;
static LIST_HEAD(dtm_dev_list);
struct cpufreq_frequency_table gpu_freq_table[10];
-struct sensor_info {
- u8 sensor_num;
- u16 cal_type;
- u32 temp_error1;
- u32 temp_error2;
-};
-
-/**
- * struct exynos_tmu_data : A structure to hold the private data of the TMU
- driver
- * @id: identifier of the one instance of the TMU controller.
- * @pdata: pointer to the tmu platform/configuration data
- * @base: base address of the single instance of the TMU controller.
- * @base_second: base address of the common registers of the TMU controller.
- * @irq: irq number of the TMU controller.
- * @soc: id of the SOC type.
- * @irq_work: pointer to the irq work structure.
- * @lock: lock to implement synchronization.
- * @temp_error1: fused value of the first point trim.
- * @temp_error2: fused value of the second point trim.
- * @regulator: pointer to the TMU regulator structure.
- * @reg_conf: pointer to structure to register with core thermal.
- * @ntrip: number of supported trip points.
- * @tmu_initialize: SoC specific TMU initialization method
- * @tmu_control: SoC specific TMU control method
- * @tmu_read: SoC specific TMU temperature read method
- * @tmu_set_emulation: SoC specific TMU emulation setting method
- * @tmu_clear_irqs: SoC specific TMU interrupts clearing method
- */
-struct exynos_tmu_data {
- int id;
- /* Throttle hotplug related variables */
- bool hotplug_enable;
- int hotplug_in_threshold;
- int hotplug_out_threshold;
- struct exynos_tmu_platform_data *pdata;
- void __iomem *base;
- int irq;
- enum soc_type soc;
- struct work_struct irq_work;
- struct mutex lock;
- u16 temp_error1, temp_error2;
- struct thermal_zone_device *tzd;
- unsigned int ntrip;
- struct thermal_cooling_device *cool_dev;
- struct list_head node;
- u32 sensors;
- int num_of_sensors;
- struct sensor_info *sensor_info;
- int sensing_mode;
- char tmu_name[THERMAL_NAME_LENGTH];
- struct device_node *np;
-
- int (*tmu_initialize)(struct platform_device *pdev);
- void (*tmu_control)(struct platform_device *pdev, bool on);
- int (*tmu_read)(struct exynos_tmu_data *data);
- void (*tmu_set_emulation)(struct exynos_tmu_data *data, int temp);
- void (*tmu_clear_irqs)(struct exynos_tmu_data *data);
-};
-
static int find_sensor(struct exynos_tmu_data *data, int start)
{
int i;
#ifndef _EXYNOS_TMU_H
#define _EXYNOS_TMU_H
#include <linux/cpu_cooling.h>
+#include <linux/gpu_cooling.h>
+#include <linux/isp_cooling.h>
#include <dt-bindings/thermal/thermal_exynos.h>
#define NR_HOTPLUG_CPUS 4
+#define MCELSIUS 1000
enum soc_type {
SOC_ARCH_EXYNOS8890 = 1,
[MIN] = "min",
};
+enum thermal_zone_name {
+ MNGS_QUAD = 0,
+ APOLLO,
+ GPU,
+ ISP,
+ MNGS_DUAL,
+ END_ZONE_NAME,
+};
+
+/**
+ * It maps 'enum znoe_name' defined in above and is used to define zone name.
+ */
+static const char * const tz_zone_names[] = {
+ [MNGS_QUAD]= "MNGS_QUAD",
+ [APOLLO] = "APOLLO",
+ [GPU] = "GPU",
+ [ISP] = "ISP",
+ [MNGS_DUAL]= "MNGS_DUAL",
+};
+
+struct sensor_info {
+ u16 sensor_num;
+ u16 cal_type;
+ u32 temp_error1;
+ u32 temp_error2;
+};
+
+/**
+ * struct exynos_tmu_data : A structure to hold the private data of the TMU
+ driver
+ * @id: identifier of the one instance of the TMU controller.
+ * @pdata: pointer to the tmu platform/configuration data
+ * @base: base address of the single instance of the TMU controller.
+ * @base_second: base address of the common registers of the TMU controller.
+ * @irq: irq number of the TMU controller.
+ * @soc: id of the SOC type.
+ * @irq_work: pointer to the irq work structure.
+ * @lock: lock to implement synchronization.
+ * @temp_error1: fused value of the first point trim.
+ * @temp_error2: fused value of the second point trim.
+ * @regulator: pointer to the TMU regulator structure.
+ * @reg_conf: pointer to structure to register with core thermal.
+ * @ntrip: number of supported trip points.
+ * @tmu_initialize: SoC specific TMU initialization method
+ * @tmu_control: SoC specific TMU control method
+ * @tmu_read: SoC specific TMU temperature read method
+ * @tmu_set_emulation: SoC specific TMU emulation setting method
+ * @tmu_clear_irqs: SoC specific TMU interrupts clearing method
+ */
+struct exynos_tmu_data {
+ int id;
+ /* Throttle hotplug related variables */
+ bool hotplug_enable;
+ int hotplug_in_threshold;
+ int hotplug_out_threshold;
+ struct exynos_tmu_platform_data *pdata;
+ void __iomem *base;
+ int irq;
+ enum soc_type soc;
+ struct work_struct irq_work;
+ struct mutex lock;
+ u16 temp_error1, temp_error2;
+ struct thermal_zone_device *tzd;
+ unsigned int ntrip;
+ struct thermal_cooling_device *cool_dev;
+ struct list_head node;
+ u32 sensors;
+ int num_of_sensors;
+ struct sensor_info *sensor_info;
+ int sensing_mode;
+ char tmu_name[THERMAL_NAME_LENGTH];
+ struct device_node *np;
+
+ int (*tmu_initialize)(struct platform_device *pdev);
+ void (*tmu_control)(struct platform_device *pdev, bool on);
+ int (*tmu_read)(struct exynos_tmu_data *data);
+ void (*tmu_set_emulation)(struct exynos_tmu_data *data, int temp);
+ void (*tmu_clear_irqs)(struct exynos_tmu_data *data);
+};
#endif /* _EXYNOS_TMU_H */