Re: [PATCH v3 14/16] thermal: samsung: core: Exynos TMU rework to use device tree for configuration

Eduardo Valentin
2015-01-21T09:20:14Z

[-- Attachment #1: Type: text/plain, Size: 36122 bytes --]

On Wed, Jan 21, 2015 at 09:10:15AM +0100, Lukasz Majewski wrote:
> Hi Eduardo,
>
> > On Thu, Jan 15, 2015 at 04:17:52PM +0100, Lukasz Majewski wrote:
> > > Hi Eduardo,
> > >
> > > > On Wed, Jan 14, 2015 at 02:41:12PM +0100, Lukasz Majewski wrote:
> > > > > This patch brings support for providing configuration via device
> > > > > tree. Previously this data has been hardcoded in the
> > > > > exynos_tmu_data.c file. Such approach was not scalable and very
> > > > > often required copying the whole data.
> > > > >
> > > > > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > > > > ---
> > > > > Changes for v2:
> > > > > - Adjust exynos_tmu.c code to the newest ti-soc-thermal
> > > > > repository
> > > > > - Usage of of-thermal.c exported trip points table
> > > > > Changes for v3:
> > > > > - Adding exynos_of_get_soc_type() method to set SOC type from
> > > > > device's compatible string
> > > > > - "samsung,tmu_" prefix for TMU specific properties has been
> > > > > added
> > > > >
> > > > > ---
> > > > > drivers/thermal/samsung/Makefile | 2 -
> > > > > drivers/thermal/samsung/exynos_tmu.c | 345
> > > > > +++++++++++++++++++++++------------
> > > > > drivers/thermal/samsung/exynos_tmu.h | 53 +----- 3 files
> > > > > changed, 226 insertions(+), 174 deletions(-)
> > > > >
> > > > > diff --git a/drivers/thermal/samsung/Makefile
> > > > > b/drivers/thermal/samsung/Makefile index c09d830..1e47d0d 100644
> > > > > --- a/drivers/thermal/samsung/Makefile
> > > > > +++ b/drivers/thermal/samsung/Makefile
> > > > > @@ -3,5 +3,3 @@
> > > > > #
> > > > > obj-$(CONFIG_EXYNOS_THERMAL) +=
> > > > > exynos_thermal.o
> > > > > exynos_thermal-y := exynos_tmu.o
> > > > > -exynos_thermal-y +=
> > > > > exynos_tmu_data.o
> > > >
> > > > Can this makefile change be part of the patch that removes
> > > > exynos_tmu_data.c?
> > > >
> > > > > -exynos_thermal-$(CONFIG_EXYNOS_THERMAL_CORE) +=
> > > > > exynos_thermal_common.o
> > > >
> > > > Can this makefile change be part of the patch that removes
> > > > exynos_thermal_common.c?
> > >
> > > Unfortunately, this code cannot be moved to the next patch, in
> > > which I remove the files, since this causes build break of the
> > > series.
> > >
> > > The code structure as is, provides working, bisectable thermal
> > > solution - thermal and cpu_cooling functionality is preserved across
> > > all commits in the series.
> >
> > My concern here is simply that this specific commit is leaving unused
> > files in the tree.
> >
> > One option would be to remove the files altogether in this specific
> > commit.
>
> Is is really necessary?
>
> This patch itself changes around 400 LOC. Those changes __are__
> important and in my opinion deserve their own commit.
>
> When I squash following patches, which remove old exynos files, we
> would have around 1.2K LOC in a single commit.
>
> I think that current approach is far more readable.

I agree that separating is far more readable. However, the commit leaves
zombie files.

>
> Eduardo, is there a chance for this series (the newest version is v5 -
> which include Ablibash comments) to be included to yours -next tree
> before v3.19 is out?

Yes, we can target this. I have sent couple of minor comments on v5.
Despite them, there are also some parts of this series that are supposed
to be merged via other trees. The cpufreq part seams to be too little
and Viresh has already flagged that I can merge it as long it is in a
separated patch. However, most part of this series touches arch/arm
directory and those should go via your platform tree. Is there a change
you could either as your Exynos maintainer to queue the patches touching
arch/arm or ask him if he is fine if I merge them via my tree?

Cheers,

>
> >
> > >
> > > >
> > > > > diff --git a/drivers/thermal/samsung/exynos_tmu.c
> > > > > b/drivers/thermal/samsung/exynos_tmu.c index ae30f6a..633a9e2
> > > > > 100644 --- a/drivers/thermal/samsung/exynos_tmu.c
> > > > > +++ b/drivers/thermal/samsung/exynos_tmu.c
> > > > > @@ -1,6 +1,10 @@
> > > > > /*
> > > > > * exynos_tmu.c - Samsung EXYNOS TMU (Thermal Management Unit)
> > > > > *
> > > > > + * Copyright (C) 2014 Samsung Electronics
> > > > > + * Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> > > > > + * Lukasz Majewski <l.majewski@samsung.com>
> > > > > + *
> > > > > * Copyright (C) 2011 Samsung Electronics
> > > > > * Donggeun Kim <dg77.kim@samsung.com>
> > > > > * Amit Daniel Kachhap <amit.kachhap@linaro.org>
> > > > > @@ -31,8 +35,8 @@
> > > > > #include <linux/platform_device.h>
> > > > > #include <linux/regulator/consumer.h>
> > > > >
> > > > > -#include "exynos_thermal_common.h"
> > > > > #include "exynos_tmu.h"
> > > > > +#include "../thermal_core.h"
> > > > >
> > > > > /* Exynos generic registers */
> > > > > #define EXYNOS_TMU_REG_TRIMINFO 0x0
> > > > > @@ -115,6 +119,7 @@
> > > > > #define EXYNOS5440_TMU_TH_RISE4_SHIFT 24
> > > > > #define EXYNOS5440_EFUSE_SWAP_OFFSET 8
> > > > >
> > > > > +#define MCELSIUS 1000
> > > > > /**
> > > > > * struct exynos_tmu_data : A structure to hold the private
> > > > > data of the TMU driver
> > > > > @@ -150,7 +155,8 @@ struct exynos_tmu_data {
> > > > > struct clk *clk, *clk_sec;
> > > > > u8 temp_error1, temp_error2;
> > > > > struct regulator *regulator;
> > > > > - struct thermal_sensor_conf *reg_conf;
> > > > > + struct thermal_zone_device *tzd;
> > > > > +
> > > > > int (*tmu_initialize)(struct platform_device *pdev);
> > > > > void (*tmu_control)(struct platform_device *pdev, bool
> > > > > on); int (*tmu_read)(struct exynos_tmu_data *data);
> > > > > @@ -159,6 +165,33 @@ struct exynos_tmu_data {
> > > > > void (*tmu_clear_irqs)(struct exynos_tmu_data *data);
> > > > > };
> > > > >
> > > > > +static void exynos_report_trigger(struct exynos_tmu_data *p)
> > > > > +{
> > > > > + char data[10], *envp[] = { data, NULL };
> > > > > + struct thermal_zone_device *tz = p->tzd;
> > > > > + unsigned long temp;
> > > > > + unsigned int i;
> > > > > +
> > > > > + if (!p) {
> > > > > + pr_err("Wrong temperature configuration
> > > > > data\n");
> > > > > + return;
> > > > > + }
> > > > > +
> > > > > + thermal_zone_device_update(tz);
> > > > > +
> > > > > + mutex_lock(&tz->lock);
> > > > > + /* Find the level for which trip happened */
> > > > > + for (i = 0; i < of_thermal_get_ntrips(tz); i++) {
> > > > > + tz->ops->get_trip_temp(tz, i, &temp);
> > > > > + if (tz->last_temperature < temp)
> > > > > + break;
> > > > > + }
> > > > > +
> > > > > + snprintf(data, sizeof(data), "%u", i);
> > > > > + kobject_uevent_env(&tz->device.kobj, KOBJ_CHANGE,
> > > > > envp);
> > > > > + mutex_unlock(&tz->lock);
> > > > > +}
> > > > > +
> > > > > /*
> > > > > * TMU treats temperature as a mapped temperature code.
> > > > > * The temperature is converted differently depending on the
> > > > > calibration type. @@ -234,14 +267,25 @@ static void
> > > > > sanitize_temp_error(struct exynos_tmu_data *data, u32
> > > > > trim_info) static u32 get_th_reg(struct exynos_tmu_data *data,
> > > > > u32 threshold, bool falling) {
> > > > > - struct exynos_tmu_platform_data *pdata = data->pdata;
> > > > > + struct thermal_zone_device *tz = data->tzd;
> > > > > + const struct thermal_trip * const trips =
> > > > > + of_thermal_get_trip_points(tz);
> > > > > + unsigned long temp;
> > > > > int i;
> > > > >
> > > > > - for (i = 0; i < pdata->non_hw_trigger_levels; i++) {
> > > > > - u8 temp = pdata->trigger_levels[i];
> > > > > + if (!trips) {
> > > > > + pr_err("%s: Cannot get trip points from
> > > > > of-thermal.c!\n",
> > > > > + __func__);
> > > > > + return 0;
> > > > > + }
> > > > > +
> > > > > + for (i = 0; i < of_thermal_get_ntrips(tz); i++) {
> > > > > + if (trips[i].type == THERMAL_TRIP_CRITICAL)
> > > > > + continue;
> > > > >
> > > > > + temp = trips[i].temperature / MCELSIUS;
> > > > > if (falling)
> > > > > - temp -= pdata->threshold_falling;
> > > > > + temp -= (trips[i].hysteresis /
> > > > > MCELSIUS); else
> > > > > threshold &= ~(0xff << 8 * i);
> > > > >
> > > > > @@ -305,9 +349,19 @@ static void exynos_tmu_control(struct
> > > > > platform_device *pdev, bool on) static int
> > > > > exynos4210_tmu_initialize(struct platform_device *pdev) {
> > > > > struct exynos_tmu_data *data =
> > > > > platform_get_drvdata(pdev);
> > > > > - struct exynos_tmu_platform_data *pdata = data->pdata;
> > > > > - unsigned int status;
> > > > > + struct thermal_zone_device *tz = data->tzd;
> > > > > + const struct thermal_trip * const trips =
> > > > > + of_thermal_get_trip_points(tz);
> > > > > int ret = 0, threshold_code, i;
> > > > > + unsigned long reference, temp;
> > > > > + unsigned int status;
> > > > > +
> > > > > + if (!trips) {
> > > > > + pr_err("%s: Cannot get trip points from
> > > > > of-thermal.c!\n",
> > > > > + __func__);
> > > > > + ret = -ENODEV;
> > > > > + goto out;
> > > > > + }
> > > > >
> > > > > status = readb(data->base + EXYNOS_TMU_REG_STATUS);
> > > > > if (!status) {
> > > > > @@ -318,12 +372,19 @@ static int
> > > > > exynos4210_tmu_initialize(struct platform_device *pdev)
> > > > > sanitize_temp_error(data, readl(data->base +
> > > > > EXYNOS_TMU_REG_TRIMINFO)); /* Write temperature code for
> > > > > threshold */
> > > > > - threshold_code = temp_to_code(data, pdata->threshold);
> > > > > + reference = trips[0].temperature / MCELSIUS;
> > > > > + threshold_code = temp_to_code(data, reference);
> > > > > + if (threshold_code < 0) {
> > > > > + ret = threshold_code;
> > > > > + goto out;
> > > > > + }
> > > > > writeb(threshold_code, data->base +
> > > > > EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
> > > > > - for (i = 0; i < pdata->non_hw_trigger_levels; i++)
> > > > > - writeb(pdata->trigger_levels[i], data->base +
> > > > > + for (i = 0; i < of_thermal_get_ntrips(tz); i++) {
> > > > > + temp = trips[i].temperature / MCELSIUS;
> > > > > + writeb(temp - reference, data->base +
> > > > > EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
> > > > > + }
> > > > >
> > > > > data->tmu_clear_irqs(data);
> > > > > out:
> > > > > @@ -333,9 +394,11 @@ out:
> > > > > static int exynos4412_tmu_initialize(struct platform_device
> > > > > *pdev) {
> > > > > struct exynos_tmu_data *data =
> > > > > platform_get_drvdata(pdev);
> > > > > - struct exynos_tmu_platform_data *pdata = data->pdata;
> > > > > + const struct thermal_trip * const trips =
> > > > > + of_thermal_get_trip_points(data->tzd);
> > > > > unsigned int status, trim_info, con, ctrl,
> > > > > rising_threshold; int ret = 0, threshold_code, i;
> > > > > + unsigned long crit_temp = 0;
> > > > >
> > > > > status = readb(data->base + EXYNOS_TMU_REG_STATUS);
> > > > > if (!status) {
> > > > > @@ -373,17 +436,29 @@ static int
> > > > > exynos4412_tmu_initialize(struct platform_device *pdev)
> > > > > data->tmu_clear_irqs(data);
> > > > > /* if last threshold limit is also present */
> > > > > - i = pdata->max_trigger_level - 1;
> > > > > - if (pdata->trigger_levels[i] && pdata->trigger_type[i]
> > > > > == HW_TRIP) {
> > > > > - threshold_code = temp_to_code(data,
> > > > > pdata->trigger_levels[i]);
> > > > > - /* 1-4 level to be assigned in th0 reg */
> > > > > - rising_threshold &= ~(0xff << 8 * i);
> > > > > - rising_threshold |= threshold_code << 8 * i;
> > > > > - writel(rising_threshold, data->base +
> > > > > EXYNOS_THD_TEMP_RISE);
> > > > > - con = readl(data->base +
> > > > > EXYNOS_TMU_REG_CONTROL);
> > > > > - con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
> > > > > - writel(con, data->base +
> > > > > EXYNOS_TMU_REG_CONTROL);
> > > > > + for (i = 0; i < of_thermal_get_ntrips(data->tzd); i++)
> > > > > {
> > > > > + if (trips[i].type == THERMAL_TRIP_CRITICAL) {
> > > > > + crit_temp = trips[i].temperature;
> > > > > + break;
> > > > > + }
> > > > > }
> > > > > +
> > > > > + if (i == of_thermal_get_ntrips(data->tzd)) {
> > > > > + pr_err("%s: No CRITICAL trip point defined at
> > > > > of-thermal.c!\n",
> > > > > + __func__);
> > > > > + ret = -EINVAL;
> > > > > + goto out;
> > > > > + }
> > > > > +
> > > > > + threshold_code = temp_to_code(data, crit_temp /
> > > > > MCELSIUS);
> > > > > + /* 1-4 level to be assigned in th0 reg */
> > > > > + rising_threshold &= ~(0xff << 8 * i);
> > > > > + rising_threshold |= threshold_code << 8 * i;
> > > > > + writel(rising_threshold, data->base +
> > > > > EXYNOS_THD_TEMP_RISE);
> > > > > + con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
> > > > > + con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
> > > > > + writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
> > > > > +
> > > > > out:
> > > > > return ret;
> > > > > }
> > > > > @@ -391,9 +466,9 @@ out:
> > > > > static int exynos5440_tmu_initialize(struct platform_device
> > > > > *pdev) {
> > > > > struct exynos_tmu_data *data =
> > > > > platform_get_drvdata(pdev);
> > > > > - struct exynos_tmu_platform_data *pdata = data->pdata;
> > > > > unsigned int trim_info = 0, con, rising_threshold;
> > > > > - int ret = 0, threshold_code, i;
> > > > > + int ret = 0, threshold_code;
> > > > > + unsigned long crit_temp = 0;
> > > > >
> > > > > /*
> > > > > * For exynos5440 soc triminfo value is swapped between
> > > > > TMU0 and @@ -422,9 +497,8 @@ static int
> > > > > exynos5440_tmu_initialize(struct platform_device *pdev)
> > > > > data->tmu_clear_irqs(data);
> > > > > /* if last threshold limit is also present */
> > > > > - i = pdata->max_trigger_level - 1;
> > > > > - if (pdata->trigger_levels[i] && pdata->trigger_type[i]
> > > > > == HW_TRIP) {
> > > > > - threshold_code = temp_to_code(data,
> > > > > pdata->trigger_levels[i]);
> > > > > + if (!data->tzd->ops->get_crit_temp(data->tzd,
> > > > > &crit_temp)) {
> > > > > + threshold_code = temp_to_code(data, crit_temp /
> > > > > MCELSIUS); /* 5th level to be assigned in th2 reg */
> > > > > rising_threshold =
> > > > > threshold_code <<
> > > > > EXYNOS5440_TMU_TH_RISE4_SHIFT; @@ -442,7 +516,7 @@ static int
> > > > > exynos5440_tmu_initialize(struct platform_device *pdev) static
> > > > > void exynos4210_tmu_control(struct platform_device *pdev, bool
> > > > > on) { struct exynos_tmu_data *data = platform_get_drvdata(pdev);
> > > > > - struct exynos_tmu_platform_data *pdata = data->pdata;
> > > > > + struct thermal_zone_device *tz = data->tzd;
> > > > > unsigned int con, interrupt_en;
> > > > >
> > > > > con = get_con_reg(data, readl(data->base +
> > > > > EXYNOS_TMU_REG_CONTROL)); @@ -450,10 +524,15 @@ static void
> > > > > exynos4210_tmu_control(struct platform_device *pdev, bool on) if
> > > > > (on) { con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
> > > > > interrupt_en =
> > > > > - pdata->trigger_enable[3] <<
> > > > > EXYNOS_TMU_INTEN_RISE3_SHIFT |
> > > > > - pdata->trigger_enable[2] <<
> > > > > EXYNOS_TMU_INTEN_RISE2_SHIFT |
> > > > > - pdata->trigger_enable[1] <<
> > > > > EXYNOS_TMU_INTEN_RISE1_SHIFT |
> > > > > - pdata->trigger_enable[0] <<
> > > > > EXYNOS_TMU_INTEN_RISE0_SHIFT;
> > > > > + (of_thermal_is_trip_valid(tz, 3)
> > > > > + << EXYNOS_TMU_INTEN_RISE3_SHIFT) |
> > > > > + (of_thermal_is_trip_valid(tz, 2)
> > > > > + << EXYNOS_TMU_INTEN_RISE2_SHIFT) |
> > > > > + (of_thermal_is_trip_valid(tz, 1)
> > > > > + << EXYNOS_TMU_INTEN_RISE1_SHIFT) |
> > > > > + (of_thermal_is_trip_valid(tz, 0)
> > > > > + << EXYNOS_TMU_INTEN_RISE0_SHIFT);
> > > > > +
> > > > > if (data->soc != SOC_ARCH_EXYNOS4210)
> > > > > interrupt_en |=
> > > > > interrupt_en <<
> > > > > EXYNOS_TMU_INTEN_FALL0_SHIFT; @@ -468,7 +547,7 @@ static void
> > > > > exynos4210_tmu_control(struct platform_device *pdev, bool on)
> > > > > static void exynos5440_tmu_control(struct platform_device *pdev,
> > > > > bool on) { struct exynos_tmu_data *data =
> > > > > platform_get_drvdata(pdev);
> > > > > - struct exynos_tmu_platform_data *pdata = data->pdata;
> > > > > + struct thermal_zone_device *tz = data->tzd;
> > > > > unsigned int con, interrupt_en;
> > > > >
> > > > > con = get_con_reg(data, readl(data->base +
> > > > > EXYNOS5440_TMU_S0_7_CTRL)); @@ -476,11 +555,16 @@ static void
> > > > > exynos5440_tmu_control(struct platform_device *pdev, bool on) if
> > > > > (on) { con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
> > > > > interrupt_en =
> > > > > - pdata->trigger_enable[3] <<
> > > > > EXYNOS5440_TMU_INTEN_RISE3_SHIFT |
> > > > > - pdata->trigger_enable[2] <<
> > > > > EXYNOS5440_TMU_INTEN_RISE2_SHIFT |
> > > > > - pdata->trigger_enable[1] <<
> > > > > EXYNOS5440_TMU_INTEN_RISE1_SHIFT |
> > > > > - pdata->trigger_enable[0] <<
> > > > > EXYNOS5440_TMU_INTEN_RISE0_SHIFT;
> > > > > - interrupt_en |= interrupt_en <<
> > > > > EXYNOS5440_TMU_INTEN_FALL0_SHIFT;
> > > > > + (of_thermal_is_trip_valid(tz, 3)
> > > > > + << EXYNOS5440_TMU_INTEN_RISE3_SHIFT) |
> > > > > + (of_thermal_is_trip_valid(tz, 2)
> > > > > + << EXYNOS5440_TMU_INTEN_RISE2_SHIFT) |
> > > > > + (of_thermal_is_trip_valid(tz, 1)
> > > > > + << EXYNOS5440_TMU_INTEN_RISE1_SHIFT) |
> > > > > + (of_thermal_is_trip_valid(tz, 0)
> > > > > + << EXYNOS5440_TMU_INTEN_RISE0_SHIFT);
> > > > > + interrupt_en |=
> > > > > + interrupt_en <<
> > > > > EXYNOS5440_TMU_INTEN_FALL0_SHIFT; } else {
> > > > > con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
> > > > > interrupt_en = 0; /* Disable all interrupts */
> > > > > @@ -489,19 +573,22 @@ static void exynos5440_tmu_control(struct
> > > > > platform_device *pdev, bool on) writel(con, data->base +
> > > > > EXYNOS5440_TMU_S0_7_CTRL); }
> > > > >
> > > > > -static int exynos_tmu_read(struct exynos_tmu_data *data)
> > > > > +int exynos_get_temp(void *p, long *temp)
> > > > > {
> > > > > - int ret;
> > > > > + struct exynos_tmu_data *data = p;
> > > > > +
> > > > > + if (!data)
> > > > > + return -EINVAL;
> > > > >
> > > > > mutex_lock(&data->lock);
> > > > > clk_enable(data->clk);
> > > > > - ret = data->tmu_read(data);
> > > > > - if (ret >= 0)
> > > > > - ret = code_to_temp(data, ret);
> > > > > +
> > > > > + *temp = code_to_temp(data, data->tmu_read(data)) *
> > > > > MCELSIUS; +
> > > > > clk_disable(data->clk);
> > > > > mutex_unlock(&data->lock);
> > > > >
> > > > > - return ret;
> > > > > + return 0;
> > > > > }
> > > > >
> > > > > #ifdef CONFIG_THERMAL_EMULATION
> > > > > @@ -613,7 +700,7 @@ static void exynos_tmu_work(struct
> > > > > work_struct *work) if (!IS_ERR(data->clk_sec))
> > > > > clk_disable(data->clk_sec);
> > > > >
> > > > > - exynos_report_trigger(data->reg_conf);
> > > > > + exynos_report_trigger(data);
> > > > > mutex_lock(&data->lock);
> > > > > clk_enable(data->clk);
> > > > >
> > > > > @@ -673,55 +760,89 @@ static irqreturn_t exynos_tmu_irq(int irq,
> > > > > void *id) static const struct of_device_id exynos_tmu_match[] =
> > > > > { {
> > > > > .compatible = "samsung,exynos3250-tmu",
> > > > > - .data = &exynos3250_default_tmu_data,
> > > > > },
> > > > > {
> > > > > .compatible = "samsung,exynos4210-tmu",
> > > > > - .data = &exynos4210_default_tmu_data,
> > > > > },
> > > > > {
> > > > > .compatible = "samsung,exynos4412-tmu",
> > > > > - .data = &exynos4412_default_tmu_data,
> > > > > },
> > > > > {
> > > > > .compatible = "samsung,exynos5250-tmu",
> > > > > - .data = &exynos5250_default_tmu_data,
> > > > > },
> > > > > {
> > > > > .compatible = "samsung,exynos5260-tmu",
> > > > > - .data = &exynos5260_default_tmu_data,
> > > > > },
> > > > > {
> > > > > .compatible = "samsung,exynos5420-tmu",
> > > > > - .data = &exynos5420_default_tmu_data,
> > > > > },
> > > > > {
> > > > > .compatible =
> > > > > "samsung,exynos5420-tmu-ext-triminfo",
> > > > > - .data = &exynos5420_default_tmu_data,
> > > > > },
> > > > > {
> > > > > .compatible = "samsung,exynos5440-tmu",
> > > > > - .data = &exynos5440_default_tmu_data,
> > > > > },
> > > > > {},
> > > > > };
> > > > > MODULE_DEVICE_TABLE(of, exynos_tmu_match);
> > > > >
> > > > > -static inline struct exynos_tmu_platform_data
> > > > > *exynos_get_driver_data(
> > > > > - struct platform_device *pdev, int id)
> > > > > +static int exynos_of_get_soc_type(struct device_node *np)
> > > > > {
> > > > > - struct exynos_tmu_init_data *data_table;
> > > > > - struct exynos_tmu_platform_data *tmu_data;
> > > > > - const struct of_device_id *match;
> > > > > + if (of_device_is_compatible(np,
> > > > > "samsung,exynos3250-tmu"))
> > > > > + return SOC_ARCH_EXYNOS3250;
> > > > > + else if (of_device_is_compatible(np,
> > > > > "samsung,exynos4210-tmu"))
> > > > > + return SOC_ARCH_EXYNOS4210;
> > > > > + else if (of_device_is_compatible(np,
> > > > > "samsung,exynos4412-tmu"))
> > > > > + return SOC_ARCH_EXYNOS4412;
> > > > > + else if (of_device_is_compatible(np,
> > > > > "samsung,exynos5250-tmu"))
> > > > > + return SOC_ARCH_EXYNOS5250;
> > > > > + else if (of_device_is_compatible(np,
> > > > > "samsung,exynos5260-tmu"))
> > > > > + return SOC_ARCH_EXYNOS5260;
> > > > > + else if (of_device_is_compatible(np,
> > > > > "samsung,exynos5420-tmu"))
> > > > > + return SOC_ARCH_EXYNOS5420;
> > > > > + else if (of_device_is_compatible(np,
> > > > > +
> > > > > "samsung,exynos5420-tmu-ext-triminfo"))
> > > > > + return SOC_ARCH_EXYNOS5420_TRIMINFO;
> > > > > + else if (of_device_is_compatible(np,
> > > > > "samsung,exynos5440-tmu"))
> > > > > + return SOC_ARCH_EXYNOS5440;
> > > > > +
> > > > > + return -EINVAL;
> > > > > +}
> > > > >
> > > > > - match = of_match_node(exynos_tmu_match,
> > > > > pdev->dev.of_node);
> > > > > - if (!match)
> > > > > - return NULL;
> > > > > - data_table = (struct exynos_tmu_init_data *)
> > > > > match->data;
> > > > > - if (!data_table || id >= data_table->tmu_count)
> > > > > - return NULL;
> > > > > - tmu_data = data_table->tmu_data;
> > > > > - return (struct exynos_tmu_platform_data *) (tmu_data +
> > > > > id); +static int exynos_of_sensor_conf(struct device_node *np,
> > > > > + struct
> > > > > exynos_tmu_platform_data *pdata) +{
> > > > > + u32 value;
> > > > > + int ret;
> > > > > +
> > > > > + of_node_get(np);
> > > > > +
> > > > > + ret = of_property_read_u32(np, "samsung,tmu_gain",
> > > > > &value);
> > > > > + pdata->gain = (u8) value;
> > > > > + of_property_read_u32(np,
> > > > > "samsung,tmu_reference_voltage", &value);
> > > > > + pdata->reference_voltage = (u8) value;
> > > > > + of_property_read_u32(np,
> > > > > "samsung,tmu_noise_cancel_mode", &value);
> > > > > + pdata->noise_cancel_mode = (u8) value;
> > > > > +
> > > > > + of_property_read_u32(np, "samsung,tmu_efuse_value",
> > > > > + &pdata->efuse_value);
> > > > > + of_property_read_u32(np, "samsung,tmu_min_efuse_value",
> > > > > + &pdata->min_efuse_value);
> > > > > + of_property_read_u32(np, "samsung,tmu_max_efuse_value",
> > > > > + &pdata->max_efuse_value);
> > > > > +
> > > > > + of_property_read_u32(np,
> > > > > "samsung,tmu_first_point_trim", &value);
> > > > > + pdata->first_point_trim = (u8) value;
> > > > > + of_property_read_u32(np,
> > > > > "samsung,tmu_second_point_trim", &value);
> > > > > + pdata->second_point_trim = (u8) value;
> > > > > + of_property_read_u32(np,
> > > > > "samsung,tmu_default_temp_offset", &value);
> > > > > + pdata->default_temp_offset = (u8) value;
> > > > > +
> > > > > + of_property_read_u32(np, "samsung,tmu_cal_type",
> > > > > &pdata->cal_type);
> > > > > + of_property_read_u32(np, "samsung,tmu_cal_mode",
> > > > > &pdata->cal_mode); +
> > > > > + of_node_put(np);
> > > > > + return 0;
> > > > > }
> > > > >
> > > > > static int exynos_map_dt_data(struct platform_device *pdev)
> > > > > @@ -771,14 +892,15 @@ static int exynos_map_dt_data(struct
> > > > > platform_device *pdev) return -EADDRNOTAVAIL;
> > > > > }
> > > > >
> > > > > - pdata = exynos_get_driver_data(pdev, data->id);
> > > > > - if (!pdata) {
> > > > > - dev_err(&pdev->dev, "No platform init data
> > > > > supplied.\n");
> > > > > - return -ENODEV;
> > > > > - }
> > > > > + pdata = devm_kzalloc(&pdev->dev,
> > > > > + sizeof(struct
> > > > > exynos_tmu_platform_data),
> > > > > + GFP_KERNEL);
> > > > > + if (!pdata)
> > > > > + return -ENOMEM;
> > > > >
> > > > > + exynos_of_sensor_conf(pdev->dev.of_node, pdata);
> > > > > data->pdata = pdata;
> > > > > - data->soc = pdata->type;
> > > > > + data->soc = exynos_of_get_soc_type(pdev->dev.of_node);
> > > > >
> > > > > switch (data->soc) {
> > > > > case SOC_ARCH_EXYNOS4210:
> > > > > @@ -834,12 +956,16 @@ static int exynos_map_dt_data(struct
> > > > > platform_device *pdev) return 0;
> > > > > }
> > > > >
> > > > > +static struct thermal_zone_of_device_ops exynos_sensor_ops = {
> > > > > + .get_temp = exynos_get_temp,
> > > > > + .set_emul_temp = exynos_tmu_set_emulation,
> > > > > +};
> > > > > +
> > > > > static int exynos_tmu_probe(struct platform_device *pdev)
> > > > > {
> > > > > - struct exynos_tmu_data *data;
> > > > > struct exynos_tmu_platform_data *pdata;
> > > > > - struct thermal_sensor_conf *sensor_conf;
> > > > > - int ret, i;
> > > > > + struct exynos_tmu_data *data;
> > > > > + int ret;
> > > > >
> > > > > data = devm_kzalloc(&pdev->dev, sizeof(struct
> > > > > exynos_tmu_data), GFP_KERNEL);
> > > > > @@ -849,9 +975,15 @@ static int exynos_tmu_probe(struct
> > > > > platform_device *pdev) platform_set_drvdata(pdev, data);
> > > > > mutex_init(&data->lock);
> > > > >
> > > > > + data->tzd =
> > > > > thermal_zone_of_sensor_register(&pdev->dev, 0, data,
> > > > > +
> > > > > &exynos_sensor_ops);
> > > > > + if (IS_ERR(data->tzd)) {
> > > > > + pr_err("thermal: tz: %p ERROR\n", data->tzd);
> > > > > + return PTR_ERR(data->tzd);
> > > > > + }
> > > > > ret = exynos_map_dt_data(pdev);
> > > > > if (ret)
> > > > > - return ret;
> > > > > + goto err_sensor;
> > > > >
> > > > > pdata = data->pdata;
> > > > >
> > > > > @@ -860,20 +992,22 @@ static int exynos_tmu_probe(struct
> > > > > platform_device *pdev) data->clk = devm_clk_get(&pdev->dev,
> > > > > "tmu_apbif"); if (IS_ERR(data->clk)) {
> > > > > dev_err(&pdev->dev, "Failed to get clock\n");
> > > > > - return PTR_ERR(data->clk);
> > > > > + ret = PTR_ERR(data->clk);
> > > > > + goto err_sensor;
> > > > > }
> > > > >
> > > > > data->clk_sec = devm_clk_get(&pdev->dev,
> > > > > "tmu_triminfo_apbif"); if (IS_ERR(data->clk_sec)) {
> > > > > if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO)
> > > > > { dev_err(&pdev->dev, "Failed to get
> > > > > triminfo clock\n");
> > > > > - return PTR_ERR(data->clk_sec);
> > > > > + ret = PTR_ERR(data->clk_sec);
> > > > > + goto err_sensor;
> > > > > }
> > > > > } else {
> > > > > ret = clk_prepare(data->clk_sec);
> > > > > if (ret) {
> > > > > dev_err(&pdev->dev, "Failed to get
> > > > > clock\n");
> > > > > - return ret;
> > > > > + goto err_sensor;
> > > > > }
> > > > > }
> > > > >
> > > > > @@ -889,45 +1023,6 @@ static int exynos_tmu_probe(struct
> > > > > platform_device *pdev) goto err_clk;
> > > > > }
> > > > >
> > > > > - exynos_tmu_control(pdev, true);
> > > > > -
> > > > > - /* Allocate a structure to register with the exynos
> > > > > core thermal */
> > > > > - sensor_conf = devm_kzalloc(&pdev->dev,
> > > > > - sizeof(struct
> > > > > thermal_sensor_conf), GFP_KERNEL);
> > > > > - if (!sensor_conf) {
> > > > > - ret = -ENOMEM;
> > > > > - goto err_clk;
> > > > > - }
> > > > > - sprintf(sensor_conf->name, "therm_zone%d", data->id);
> > > > > - sensor_conf->read_temperature = (int (*)(void
> > > > > *))exynos_tmu_read;
> > > > > - sensor_conf->write_emul_temp =
> > > > > - (int (*)(void *, unsigned
> > > > > long))exynos_tmu_set_emulation;
> > > > > - sensor_conf->driver_data = data;
> > > > > - sensor_conf->trip_data.trip_count =
> > > > > pdata->trigger_enable[0] +
> > > > > - pdata->trigger_enable[1] +
> > > > > pdata->trigger_enable[2]+
> > > > > - pdata->trigger_enable[3];
> > > > > -
> > > > > - for (i = 0; i < sensor_conf->trip_data.trip_count;
> > > > > i++) {
> > > > > - sensor_conf->trip_data.trip_val[i] =
> > > > > - pdata->threshold +
> > > > > pdata->trigger_levels[i];
> > > > > - sensor_conf->trip_data.trip_type[i] =
> > > > > - pdata->trigger_type[i];
> > > > > - }
> > > > > -
> > > > > - sensor_conf->trip_data.trigger_falling =
> > > > > pdata->threshold_falling; -
> > > > > - sensor_conf->dev = &pdev->dev;
> > > > > - /* Register the sensor with thermal management
> > > > > interface */
> > > > > - ret = exynos_register_thermal(sensor_conf);
> > > > > - if (ret) {
> > > > > - if (ret != -EPROBE_DEFER)
> > > > > - dev_err(&pdev->dev,
> > > > > - "Failed to register thermal
> > > > > interface: %d\n",
> > > > > - ret);
> > > > > - goto err_clk;
> > > > > - }
> > > > > - data->reg_conf = sensor_conf;
> > > > > -
> > > > > ret = devm_request_irq(&pdev->dev, data->irq,
> > > > > exynos_tmu_irq, IRQF_TRIGGER_RISING | IRQF_SHARED,
> > > > > dev_name(&pdev->dev), data); if (ret) {
> > > > > @@ -935,21 +1030,31 @@ static int exynos_tmu_probe(struct
> > > > > platform_device *pdev) goto err_clk;
> > > > > }
> > > > >
> > > > > + ret = exynos_tmu_initialize(pdev);
> > > > > + if (ret) {
> > > > > + dev_err(&pdev->dev, "Failed to initialize
> > > > > TMU\n");
> > > > > + goto err_clk;
> > > > > + }
> > > > > + exynos_tmu_control(pdev, true);
> > > > > return 0;
> > > > > +
> > > > > err_clk:
> > > > > clk_unprepare(data->clk);
> > > > > err_clk_sec:
> > > > > if (!IS_ERR(data->clk_sec))
> > > > > clk_unprepare(data->clk_sec);
> > > > > +err_sensor:
> > > > > + thermal_zone_of_sensor_unregister(&pdev->dev,
> > > > > data->tzd); +
> > > > > return ret;
> > > > > }
> > > > >
> > > > > static int exynos_tmu_remove(struct platform_device *pdev)
> > > > > {
> > > > > struct exynos_tmu_data *data =
> > > > > platform_get_drvdata(pdev);
> > > > > + struct thermal_zone_device *tzd = data->tzd;
> > > > >
> > > > > - exynos_unregister_thermal(data->reg_conf);
> > > > > -
> > > > > + thermal_zone_of_sensor_unregister(&pdev->dev, tzd);
> > > > > exynos_tmu_control(pdev, false);
> > > > >
> > > > > clk_unprepare(data->clk);
> > > > > diff --git a/drivers/thermal/samsung/exynos_tmu.h
> > > > > b/drivers/thermal/samsung/exynos_tmu.h index 627dec9..d876d4c
> > > > > 100644 --- a/drivers/thermal/samsung/exynos_tmu.h
> > > > > +++ b/drivers/thermal/samsung/exynos_tmu.h
> > > > > @@ -23,8 +23,7 @@
> > > > > #ifndef _EXYNOS_TMU_H
> > > > > #define _EXYNOS_TMU_H
> > > > > #include <linux/cpu_cooling.h>
> > > > > -
> > > > > -#include "exynos_thermal_common.h"
> > > > > +#include <dt-bindings/thermal/thermal_exynos.h>
> > > > >
> > > > > enum soc_type {
> > > > > SOC_ARCH_EXYNOS3250 = 1,
> > > > > @@ -36,38 +35,9 @@ enum soc_type {
> > > > > SOC_ARCH_EXYNOS5420_TRIMINFO,
> > > > > SOC_ARCH_EXYNOS5440,
> > > > > };
> > > > > -#include <dt-bindings/thermal/thermal_exynos.h>
> > > > >
> > > > > /**
> > > > > * struct exynos_tmu_platform_data
> > > > > - * @threshold: basic temperature for generating interrupt
> > > > > - * 25 <= threshold <= 125 [unit: degree Celsius]
> > > > > - * @threshold_falling: differntial value for setting threshold
> > > > > - * of temperature falling interrupt.
> > > > > - * @trigger_levels: array for each interrupt levels
> > > > > - * [unit: degree Celsius]
> > > > > - * 0: temperature for trigger_level0 interrupt
> > > > > - * condition for trigger_level0 interrupt:
> > > > > - * current temperature > threshold +
> > > > > trigger_levels[0]
> > > > > - * 1: temperature for trigger_level1 interrupt
> > > > > - * condition for trigger_level1 interrupt:
> > > > > - * current temperature > threshold +
> > > > > trigger_levels[1]
> > > > > - * 2: temperature for trigger_level2 interrupt
> > > > > - * condition for trigger_level2 interrupt:
> > > > > - * current temperature > threshold +
> > > > > trigger_levels[2]
> > > > > - * 3: temperature for trigger_level3 interrupt
> > > > > - * condition for trigger_level3 interrupt:
> > > > > - * current temperature > threshold +
> > > > > trigger_levels[3]
> > > > > - * @trigger_type: defines the type of trigger. Possible values
> > > > > are,
> > > > > - * THROTTLE_ACTIVE trigger type
> > > > > - * THROTTLE_PASSIVE trigger type
> > > > > - * SW_TRIP trigger type
> > > > > - * HW_TRIP
> > > > > - * @trigger_enable[]: array to denote which trigger levels are
> > > > > enabled.
> > > > > - * 1 = enable trigger_level[] interrupt,
> > > > > - * 0 = disable trigger_level[] interrupt
> > > > > - * @max_trigger_level: max trigger level supported by the TMU
> > > > > - * @non_hw_trigger_levels: number of defined non-hardware
> > > > > trigger levels
> > > > > * @gain: gain of amplifier in the positive-TC generator block
> > > > > * 0 < gain <= 15
> > > > > * @reference_voltage: reference voltage of amplifier
> > > > > @@ -79,21 +49,12 @@ enum soc_type {
> > > > > * @efuse_value: platform defined fuse value
> > > > > * @min_efuse_value: minimum valid trimming data
> > > > > * @max_efuse_value: maximum valid trimming data
> > > > > - * @first_point_trim: temp value of the first point trimming
> > > > > - * @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
> > > > > *
> > > > > * This structure is required for configuration of exynos_tmu
> > > > > driver. */
> > > > > struct exynos_tmu_platform_data {
> > > > > - u8 threshold;
> > > > > - u8 threshold_falling;
> > > > > - u8 trigger_levels[MAX_TRIP_COUNT];
> > > > > - enum trigger_type trigger_type[MAX_TRIP_COUNT];
> > > > > - bool trigger_enable[MAX_TRIP_COUNT];
> > > > > - u8 max_trigger_level;
> > > > > - u8 non_hw_trigger_levels;
> > > > > u8 gain;
> > > > > u8 reference_voltage;
> > > > > u8 noise_cancel_mode;
> > > > > @@ -110,18 +71,6 @@ struct exynos_tmu_platform_data {
> > > > > u32 cal_mode;
> > > > > };
> > > > >
> > > > > -/**
> > > > > - * struct exynos_tmu_init_data
> > > > > - * @tmu_count: number of TMU instances.
> > > > > - * @tmu_data: platform data of all TMU instances.
> > > > > - * This structure is required to store data for multi-instance
> > > > > exynos tmu
> > > > > - * driver.
> > > > > - */
> > > > > -struct exynos_tmu_init_data {
> > > > > - int tmu_count;
> > > > > - struct exynos_tmu_platform_data tmu_data[];
> > > > > -};
> > > > > -
> > > > > extern struct exynos_tmu_init_data const
> > > > > exynos3250_default_tmu_data; extern struct exynos_tmu_init_data
> > > > > const exynos4210_default_tmu_data; extern struct
> > > > > exynos_tmu_init_data const exynos4412_default_tmu_data; --
> > > > > 2.0.0.rc2
> > > > >
> > >
> > >
> > >
> > > --
> > > Best regards,
> > >
> > > Lukasz Majewski
> > >
> > > Samsung R&D Institute Poland (SRPOL) | Linux Platform Group
>
>
>
> --
> Best regards,
>
> Lukasz Majewski
>
> Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]