Hi Eduardo,

> On Mon, Jan 19, 2015 at 12:20:51PM +0100, Lukasz Majewski wrote:
> > Up till now exynos_tmu_data.c was used for storing CPU cooling
> > configuration data. Now the Exynos thermal core code uses device
> > tree to get this data. For this purpose generic thermal code for
> > configuring CPU cooling was used.
> > 
> > Signed-off-by: Lukasz Majewski <l.majew...@samsung.com>
> > ---
> > Changes for v2:
> > - None
> > Changes for v3:
> > - Rewrite code responsible for registering CPU cooling device to
> > not depend on explicit "/cpus/cpu@0" path since now Exynos SoCs use
> > new cpu node names (e.g. cpu@A00). New approach iterates over
> > "cpus" node children.
> > - Patch title changed to thermal: exynos
> > Changes for v4:
> > - None
> > Changes for v5:
> > - None
> > 
> > ---
> >  drivers/cpufreq/exynos-cpufreq.c                |  30 +++++-
> >  drivers/thermal/samsung/exynos_thermal_common.c | 122
> > ++++++++++++++----------
> > drivers/thermal/samsung/exynos_tmu.c            |   7 --
> > drivers/thermal/samsung/exynos_tmu.h            |   5 -
> > drivers/thermal/samsung/exynos_tmu_data.c       |  42 +------- 5
> > files changed, 101 insertions(+), 105 deletions(-)
> > 
> > diff --git a/drivers/cpufreq/exynos-cpufreq.c
> > b/drivers/cpufreq/exynos-cpufreq.c index f99a0b0..32bc64d 100644
> > --- a/drivers/cpufreq/exynos-cpufreq.c
> > +++ b/drivers/cpufreq/exynos-cpufreq.c
> > @@ -18,10 +18,13 @@
> >  #include <linux/cpufreq.h>
> >  #include <linux/platform_device.h>
> >  #include <linux/of.h>
> > +#include <linux/cpu_cooling.h>
> > +#include <linux/cpu.h>
> >  
> >  #include "exynos-cpufreq.h"
> >  
> >  static struct exynos_dvfs_info *exynos_info;
> > +static struct thermal_cooling_device *cdev;
> >  static struct regulator *arm_regulator;
> >  static unsigned int locking_frequency;
> >  
> > @@ -156,6 +159,7 @@ static struct cpufreq_driver exynos_driver = {
> >  
> >  static int exynos_cpufreq_probe(struct platform_device *pdev)
> >  {
> > +   struct device_node *cpus, *np;
> >     int ret = -EINVAL;
> >  
> >     exynos_info = kzalloc(sizeof(*exynos_info), GFP_KERNEL);
> > @@ -198,9 +202,31 @@ static int exynos_cpufreq_probe(struct
> > platform_device *pdev) /* Done here as we want to capture boot
> > frequency */ locking_frequency =
> > clk_get_rate(exynos_info->cpu_clk) / 1000; 
> > -   if (!cpufreq_register_driver(&exynos_driver))
> > -           return 0;
> > +   if (cpufreq_register_driver(&exynos_driver))
> > +           goto err;
> >  
> > +   cpus = of_find_node_by_path("/cpus");
> > +   if (!cpus) {
> > +           pr_err("failed to find cpus node\n");
> > +           return -ENOENT;
> > +   }
> > +
> > +   for (np = of_get_next_child(cpus, NULL); np;
> > +        of_node_put(np), np = of_get_next_child(cpus, np)) {
> > +           if (of_find_property(np, "#cooling-cells", NULL)) {
> > +                   cdev = of_cpufreq_cooling_register(np,
> > +
> > cpu_present_mask);
> > +                   if (IS_ERR(cdev))
> > +                           pr_err("running cpufreq without
> > cooling device: %ld\n",
> > +                                  PTR_ERR(cdev));
> > +                   break;
> > +           }
> > +   }
> > +   of_node_put(np);
> > +   of_node_put(cpus);
> > +
> > +   return 0;
> > + err:
> >     dev_err(&pdev->dev, "failed to register cpufreq driver\n");
> >     regulator_put(arm_regulator);
> >  err_vdd_arm:
> 
> You need at least an ack from a cpufreq maintainer to get this patch
> in. I would prefer if you split the cpufreq part from the thermal
> part. It avoids merge conflicts in the upstreaming process.

Please note that exynos-cpufreq part has around 30 LOC (which only
prevents from a regression). 

When I split it, then if by some mishap this not find its way to
mainline in the same time as thermal, then we would have pretty nasty
regression.

I will ask Viresh to look into this code and NAK/ACK it.

> 
> > diff --git a/drivers/thermal/samsung/exynos_thermal_common.c
> > b/drivers/thermal/samsung/exynos_thermal_common.c index
> > 6dc3815..00aa688 100644 ---
> > a/drivers/thermal/samsung/exynos_thermal_common.c +++
> > b/drivers/thermal/samsung/exynos_thermal_common.c @@ -133,47
> > +133,62 @@ static int exynos_get_crit_temp(struct
> > thermal_zone_device *thermal, static int exynos_bind(struct
> > thermal_zone_device *thermal, struct thermal_cooling_device *cdev) {
> > -   int ret = 0, i, tab_size, level;
> > -   struct freq_clip_table *tab_ptr, *clip_data;
> >     struct exynos_thermal_zone *th_zone = thermal->devdata;
> >     struct thermal_sensor_conf *data = th_zone->sensor_conf;
> > +   struct device_node *child, *gchild, *np;
> > +   struct of_phandle_args cooling_spec;
> > +   unsigned long max, state = 0;
> > +   int ret = 0, i = 0;
> >  
> > -   tab_ptr = (struct freq_clip_table
> > *)data->cooling_data.freq_data;
> > -   tab_size = data->cooling_data.freq_clip_count;
> > -
> > -   if (tab_ptr == NULL || tab_size == 0)
> > +   /*
> > +    * Below code is necessary to skip binding when cpufreq's
> > +    * frequency table is not yet initialized.
> > +    */
> > +   cdev->ops->get_max_state(cdev, &state);
> > +   if (!state && !th_zone->cool_dev_size) {
> > +           th_zone->cool_dev_size = 1;
> > +           th_zone->cool_dev[0] = cdev;
> > +           th_zone->bind = false;
> >             return 0;
> > +   }
> >  
> > -   /* find the cooling device registered*/
> > -   for (i = 0; i < th_zone->cool_dev_size; i++)
> > -           if (cdev == th_zone->cool_dev[i])
> > -                   break;
> > +   np = of_find_node_by_path("/thermal-zones/cpu-thermal");
> > +   if (!np) {
> > +           pr_err("failed to find thmerla-zones/cpu-thermal
> > node\n");
> > +           return -ENOENT;
> > +   }
> >  
> > -   /* No matching cooling device */
> > -   if (i == th_zone->cool_dev_size)
> > -           return 0;
> > +   child = of_get_child_by_name(np, "cooling-maps");
> >  
> > -   /* Bind the thermal zone to the cpufreq cooling device */
> > -   for (i = 0; i < tab_size; i++) {
> > -           clip_data = (struct freq_clip_table
> > *)&(tab_ptr[i]);
> > -           level = cpufreq_cooling_get_level(0,
> > clip_data->freq_clip_max);
> > -           if (level == THERMAL_CSTATE_INVALID)
> > -                   return 0;
> > -           switch (GET_ZONE(i)) {
> > -           case MONITOR_ZONE:
> > -           case WARN_ZONE:
> > -                   if
> > (thermal_zone_bind_cooling_device(thermal, i, cdev,
> > -
> > level, 0)) {
> > -                           dev_err(data->dev,
> > -                                   "error unbinding cdev
> > inst=%d\n", i);
> > -                           ret = -EINVAL;
> > -                   }
> > -                   th_zone->bind = true;
> > -                   break;
> > -           default:
> > +   for_each_child_of_node(child, gchild) {
> > +           ret = of_parse_phandle_with_args(gchild,
> > "cooling-device",
> > +                                            "#cooling-cells",
> > +                                            0, &cooling_spec);
> > +           if (ret < 0) {
> > +                   pr_err("missing cooling_device
> > property\n");
> > +                   goto end;
> > +           }
> > +
> > +           if (cooling_spec.args_count < 2) {
> >                     ret = -EINVAL;
> > +                   goto end;
> >             }
> > +
> > +           max = cooling_spec.args[0];
> > +           if (thermal_zone_bind_cooling_device(thermal, i,
> > cdev,
> > +                                                max, 0)) {
> > +                   dev_err(data->dev,
> > +                           "thermal error unbinding cdev
> > inst=%d\n", i); +
> > +                   ret = -EINVAL;
> > +                   goto end;
> > +           }
> > +           i++;
> >     }
> > +   th_zone->bind = true;
> > +end:
> > +   of_node_put(child);
> > +   of_node_put(np);
> >  
> >     return ret;
> >  }
> > @@ -182,16 +197,12 @@ static int exynos_bind(struct
> > thermal_zone_device *thermal, static int exynos_unbind(struct
> > thermal_zone_device *thermal, struct thermal_cooling_device *cdev)
> >  {
> > -   int ret = 0, i, tab_size;
> > +   int ret = 0, i;
> >     struct exynos_thermal_zone *th_zone = thermal->devdata;
> >     struct thermal_sensor_conf *data = th_zone->sensor_conf;
> > +   struct device_node *child, *gchild, *np;
> >  
> > -   if (th_zone->bind == false)
> > -           return 0;
> > -
> > -   tab_size = data->cooling_data.freq_clip_count;
> > -
> > -   if (tab_size == 0)
> > +   if (th_zone->bind == false || !th_zone->cool_dev_size)
> >             return 0;
> >  
> >     /* find the cooling device registered*/
> > @@ -203,23 +214,30 @@ static int exynos_unbind(struct
> > thermal_zone_device *thermal, if (i == th_zone->cool_dev_size)
> >             return 0;
> >  
> > -   /* Bind the thermal zone to the cpufreq cooling device */
> > -   for (i = 0; i < tab_size; i++) {
> > -           switch (GET_ZONE(i)) {
> > -           case MONITOR_ZONE:
> > -           case WARN_ZONE:
> > -                   if
> > (thermal_zone_unbind_cooling_device(thermal, i,
> > -
> > cdev)) {
> > -                           dev_err(data->dev,
> > -                                   "error unbinding cdev
> > inst=%d\n", i);
> > -                           ret = -EINVAL;
> > -                   }
> > -                   th_zone->bind = false;
> > -                   break;
> > -           default:
> > +   np = of_find_node_by_path("/thermal-zones/cpu-thermal");
> > +   if (!np) {
> > +           pr_err("failed to find thmerla-zones/cpu-thermal
> > node\n");
> > +           return -ENOENT;
> > +   }
> > +
> > +   child = of_get_child_by_name(np, "cooling-maps");
> > +
> > +   i = 0;
> > +   for_each_child_of_node(child, gchild) {
> > +           if (thermal_zone_unbind_cooling_device(thermal, i,
> > +                                                  cdev)) {
> > +                   dev_err(data->dev,
> > +                           "error unbinding cdev inst=%d\n",
> > i); ret = -EINVAL;
> > +                   goto end;
> >             }
> > +           i++;
> >     }
> > +   th_zone->bind = false;
> > +end:
> > +   of_node_put(child);
> > +   of_node_put(np);
> > +
> >     return ret;
> >  }
> >  
> > diff --git a/drivers/thermal/samsung/exynos_tmu.c
> > b/drivers/thermal/samsung/exynos_tmu.c index 5000727..ae30f6a 100644
> > --- a/drivers/thermal/samsung/exynos_tmu.c
> > +++ b/drivers/thermal/samsung/exynos_tmu.c
> > @@ -916,13 +916,6 @@ static int exynos_tmu_probe(struct
> > platform_device *pdev) 
> >     sensor_conf->trip_data.trigger_falling =
> > pdata->threshold_falling; 
> > -   sensor_conf->cooling_data.freq_clip_count =
> > pdata->freq_tab_count;
> > -   for (i = 0; i < pdata->freq_tab_count; i++) {
> > -
> > sensor_conf->cooling_data.freq_data[i].freq_clip_max =
> > -
> > pdata->freq_tab[i].freq_clip_max;
> > -           sensor_conf->cooling_data.freq_data[i].temp_level =
> > -
> > pdata->freq_tab[i].temp_level;
> > -   }
> >     sensor_conf->dev = &pdev->dev;
> >     /* Register the sensor with thermal management interface */
> >     ret = exynos_register_thermal(sensor_conf);
> > diff --git a/drivers/thermal/samsung/exynos_tmu.h
> > b/drivers/thermal/samsung/exynos_tmu.h index 7f880d2..627dec9 100644
> > --- a/drivers/thermal/samsung/exynos_tmu.h
> > +++ b/drivers/thermal/samsung/exynos_tmu.h
> > @@ -83,9 +83,6 @@ enum soc_type {
> >   * @second_point_trim: temp value of the second point trimming
> >   * @default_temp_offset: default temperature offset in case of no
> > trimming
> >   * @cal_type: calibration type for temperature
> > - * @freq_clip_table: Table representing frequency reduction
> > percentage.
> > - * @freq_tab_count: Count of the above table as frequency
> > reduction may
> > - * applicable to only some of the trigger levels.
> >   *
> >   * This structure is required for configuration of exynos_tmu
> > driver. */
> > @@ -111,8 +108,6 @@ struct exynos_tmu_platform_data {
> >     enum soc_type type;
> >     u32 cal_type;
> >     u32 cal_mode;
> > -   struct freq_clip_table freq_tab[4];
> > -   unsigned int freq_tab_count;
> >  };
> >  
> >  /**
> > diff --git a/drivers/thermal/samsung/exynos_tmu_data.c
> > b/drivers/thermal/samsung/exynos_tmu_data.c index b239100..a993f3d
> > 100644 --- a/drivers/thermal/samsung/exynos_tmu_data.c
> > +++ b/drivers/thermal/samsung/exynos_tmu_data.c
> > @@ -47,15 +47,6 @@ struct exynos_tmu_init_data const
> > exynos4210_default_tmu_data = { .first_point_trim = 25,
> >             .second_point_trim = 85,
> >             .default_temp_offset = 50,
> > -           .freq_tab[0] = {
> > -                   .freq_clip_max = 800 * 1000,
> > -                   .temp_level = 85,
> > -                   },
> > -           .freq_tab[1] = {
> > -                   .freq_clip_max = 200 * 1000,
> > -                   .temp_level = 100,
> > -           },
> > -           .freq_tab_count = 2,
> >             .type = SOC_ARCH_EXYNOS4210,
> >             },
> >     },
> > @@ -87,16 +78,7 @@ struct exynos_tmu_init_data const
> > exynos4210_default_tmu_data = { .max_efuse_value = 100, \
> >     .first_point_trim = 25, \
> >     .second_point_trim = 85, \
> > -   .default_temp_offset = 50, \
> > -   .freq_tab[0] = { \
> > -           .freq_clip_max = 800 * 1000, \
> > -           .temp_level = 70, \
> > -   }, \
> > -   .freq_tab[1] = { \
> > -           .freq_clip_max = 400 * 1000, \
> > -           .temp_level = 95, \
> > -   }, \
> > -   .freq_tab_count = 2
> > +   .default_temp_offset = 50
> >  
> >  struct exynos_tmu_init_data const exynos3250_default_tmu_data = {
> >     .tmu_data = {
> > @@ -133,16 +115,7 @@ struct exynos_tmu_init_data const
> > exynos3250_default_tmu_data = { .max_efuse_value = 100, \
> >     .first_point_trim = 25, \
> >     .second_point_trim = 85, \
> > -   .default_temp_offset = 50, \
> > -   .freq_tab[0] = { \
> > -           .freq_clip_max = 1400 * 1000, \
> > -           .temp_level = 70, \
> > -   }, \
> > -   .freq_tab[1] = { \
> > -           .freq_clip_max = 400 * 1000, \
> > -           .temp_level = 95, \
> > -   }, \
> > -   .freq_tab_count = 2
> > +   .default_temp_offset = 50
> >  
> >  struct exynos_tmu_init_data const exynos4412_default_tmu_data = {
> >     .tmu_data = {
> > @@ -189,16 +162,7 @@ struct exynos_tmu_init_data const
> > exynos5250_default_tmu_data = { .max_efuse_value = 100, \
> >     .first_point_trim = 25, \
> >     .second_point_trim = 85, \
> > -   .default_temp_offset = 50, \
> > -   .freq_tab[0] = { \
> > -           .freq_clip_max = 800 * 1000, \
> > -           .temp_level = 85, \
> > -   }, \
> > -   .freq_tab[1] = { \
> > -           .freq_clip_max = 200 * 1000, \
> > -           .temp_level = 103, \
> > -   }, \
> > -   .freq_tab_count = 2, \
> > +   .default_temp_offset = 50,
> >  
> >  #define EXYNOS5260_TMU_DATA \
> >     __EXYNOS5260_TMU_DATA \
> > -- 
> > 2.0.0.rc2
> > 



-- 
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group
--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to