thermal: exynos: add ->tmu_initialize method
authorBartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Thu, 13 Nov 2014 15:01:13 +0000 (16:01 +0100)
committerEduardo Valentin <edubezval@gmail.com>
Thu, 20 Nov 2014 14:53:46 +0000 (10:53 -0400)
Add ->tmu_initialize method to struct exynos_tmu_data and
use it in exynos_tmu_initialize().  Then add ->tmu_initialize
implementations for Exynos4210, Exynos4412+ and Exynos5440.
Finally remove no longer needed reg->threshold_th[0,1],
reg->intclr_[fall,rise]_shift and reg->intclr_[rise,fall]_mask
abstractions.

There are more improvements available in the future on top
of this patch like merging HW_TRIP level setting with setting
of other levels for Exynos4412+ or adding separate method
for clearing IRQs using INTCLEAR register (for Exynos5420,
Exynos5260 and Exynos4412+).

There should be no functional changes caused by this patch.

Cc: Amit Daniel Kachhap <amit.daniel@samsung.com>
Cc: Lukasz Majewski <l.majewski@samsung.com>
Cc: Eduardo Valentin <edubezval@gmail.com>
Cc: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Tested-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
drivers/thermal/samsung/exynos_tmu.c
drivers/thermal/samsung/exynos_tmu.h
drivers/thermal/samsung/exynos_tmu_data.c

index 6e82fdd860b0a8ea21ae3096c23fb3dd9a91e348..736ef7885878b68d7a036359894f72ce1f7e8c87 100644 (file)
@@ -52,6 +52,7 @@
  * @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.
+ * @tmu_initialize: SoC specific TMU initialization method
  */
 struct exynos_tmu_data {
        int id;
@@ -66,6 +67,7 @@ struct exynos_tmu_data {
        u8 temp_error1, temp_error2;
        struct regulator *regulator;
        struct thermal_sensor_conf *reg_conf;
+       int (*tmu_initialize)(struct platform_device *pdev);
 };
 
 /*
@@ -180,118 +182,13 @@ static u32 get_th_reg(struct exynos_tmu_data *data, u32 threshold, bool falling)
 static int exynos_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 exynos_tmu_registers *reg = pdata->registers;
-       unsigned int status, trim_info = 0, con, ctrl;
-       unsigned int rising_threshold = 0, falling_threshold = 0;
-       int ret = 0, threshold_code, i;
+       int ret;
 
        mutex_lock(&data->lock);
        clk_enable(data->clk);
        if (!IS_ERR(data->clk_sec))
                clk_enable(data->clk_sec);
-
-       if (data->soc != SOC_ARCH_EXYNOS5440) {
-               status = readb(data->base + EXYNOS_TMU_REG_STATUS);
-               if (!status) {
-                       ret = -EBUSY;
-                       goto out;
-               }
-       }
-
-       if (data->soc == SOC_ARCH_EXYNOS3250 ||
-           data->soc == SOC_ARCH_EXYNOS4412 ||
-           data->soc == SOC_ARCH_EXYNOS5250) {
-               if (data->soc == SOC_ARCH_EXYNOS3250) {
-                       ctrl = readl(data->base + EXYNOS_TMU_TRIMINFO_CON1);
-                       ctrl |= EXYNOS_TRIMINFO_RELOAD_ENABLE;
-                       writel(ctrl, data->base + EXYNOS_TMU_TRIMINFO_CON1);
-               }
-               ctrl = readl(data->base + EXYNOS_TMU_TRIMINFO_CON2);
-               ctrl |= EXYNOS_TRIMINFO_RELOAD_ENABLE;
-               writel(ctrl, data->base + EXYNOS_TMU_TRIMINFO_CON2);
-       }
-
-       /* Save trimming info in order to perform calibration */
-       if (data->soc == SOC_ARCH_EXYNOS5440) {
-               /*
-                * For exynos5440 soc triminfo value is swapped between TMU0 and
-                * TMU2, so the below logic is needed.
-                */
-               switch (data->id) {
-               case 0:
-                       trim_info = readl(data->base +
-                       EXYNOS5440_EFUSE_SWAP_OFFSET + EXYNOS5440_TMU_S0_7_TRIM);
-                       break;
-               case 1:
-                       trim_info = readl(data->base + EXYNOS5440_TMU_S0_7_TRIM);
-                       break;
-               case 2:
-                       trim_info = readl(data->base -
-                       EXYNOS5440_EFUSE_SWAP_OFFSET + EXYNOS5440_TMU_S0_7_TRIM);
-               }
-       } else {
-               /* On exynos5420 the triminfo register is in the shared space */
-               if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO)
-                       trim_info = readl(data->base_second +
-                                               EXYNOS_TMU_REG_TRIMINFO);
-               else
-                       trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
-       }
-       sanitize_temp_error(data, trim_info);
-
-       if (data->soc == SOC_ARCH_EXYNOS4210) {
-               /* Write temperature code for threshold */
-               threshold_code = temp_to_code(data, pdata->threshold);
-               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 +
-                       reg->threshold_th0 + i * sizeof(reg->threshold_th0));
-
-               exynos_tmu_clear_irqs(data);
-       } else {
-               /* Write temperature code for rising and falling threshold */
-               rising_threshold = readl(data->base + reg->threshold_th0);
-               rising_threshold = get_th_reg(data, rising_threshold, false);
-               if (data->soc != SOC_ARCH_EXYNOS5440)
-                       falling_threshold = get_th_reg(data, 0, true);
-
-               writel(rising_threshold,
-                               data->base + reg->threshold_th0);
-               writel(falling_threshold,
-                               data->base + reg->threshold_th1);
-
-               exynos_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->soc != SOC_ARCH_EXYNOS5440) {
-                               /* 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);
-                       } else {
-                               /* 5th level to be assigned in th2 reg */
-                               rising_threshold =
-                               threshold_code << EXYNOS5440_TMU_TH_RISE4_SHIFT;
-                               writel(rising_threshold,
-                                       data->base + EXYNOS5440_TMU_S0_7_TH2);
-                       }
-                       con = readl(data->base + reg->tmu_ctrl);
-                       con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
-                       writel(con, data->base + reg->tmu_ctrl);
-               }
-       }
-       /*Clear the PMIN in the common TMU register*/
-       if (data->soc == SOC_ARCH_EXYNOS5440 && !data->id)
-               writel(0, data->base_second + EXYNOS5440_TMU_PMIN);
-out:
+       ret = data->tmu_initialize(pdev);
        clk_disable(data->clk);
        mutex_unlock(&data->lock);
        if (!IS_ERR(data->clk_sec))
@@ -347,6 +244,143 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
        mutex_unlock(&data->lock);
 }
 
+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;
+       int ret = 0, threshold_code, i;
+
+       status = readb(data->base + EXYNOS_TMU_REG_STATUS);
+       if (!status) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO));
+
+       /* Write temperature code for threshold */
+       threshold_code = temp_to_code(data, pdata->threshold);
+       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 +
+                      EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
+
+       exynos_tmu_clear_irqs(data);
+out:
+       return ret;
+}
+
+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;
+       unsigned int status, trim_info, con, ctrl, rising_threshold;
+       int ret = 0, threshold_code, i;
+
+       status = readb(data->base + EXYNOS_TMU_REG_STATUS);
+       if (!status) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       if (data->soc == SOC_ARCH_EXYNOS3250 ||
+           data->soc == SOC_ARCH_EXYNOS4412 ||
+           data->soc == SOC_ARCH_EXYNOS5250) {
+               if (data->soc == SOC_ARCH_EXYNOS3250) {
+                       ctrl = readl(data->base + EXYNOS_TMU_TRIMINFO_CON1);
+                       ctrl |= EXYNOS_TRIMINFO_RELOAD_ENABLE;
+                       writel(ctrl, data->base + EXYNOS_TMU_TRIMINFO_CON1);
+               }
+               ctrl = readl(data->base + EXYNOS_TMU_TRIMINFO_CON2);
+               ctrl |= EXYNOS_TRIMINFO_RELOAD_ENABLE;
+               writel(ctrl, data->base + EXYNOS_TMU_TRIMINFO_CON2);
+       }
+
+       /* On exynos5420 the triminfo register is in the shared space */
+       if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO)
+               trim_info = readl(data->base_second + EXYNOS_TMU_REG_TRIMINFO);
+       else
+               trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
+
+       sanitize_temp_error(data, trim_info);
+
+       /* Write temperature code for rising and falling threshold */
+       rising_threshold = readl(data->base + EXYNOS_THD_TEMP_RISE);
+       rising_threshold = get_th_reg(data, rising_threshold, false);
+       writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE);
+       writel(get_th_reg(data, 0, true), data->base + EXYNOS_THD_TEMP_FALL);
+
+       exynos_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);
+       }
+out:
+       return ret;
+}
+
+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;
+
+       /*
+        * For exynos5440 soc triminfo value is swapped between TMU0 and
+        * TMU2, so the below logic is needed.
+        */
+       switch (data->id) {
+       case 0:
+               trim_info = readl(data->base + EXYNOS5440_EFUSE_SWAP_OFFSET +
+                                EXYNOS5440_TMU_S0_7_TRIM);
+               break;
+       case 1:
+               trim_info = readl(data->base + EXYNOS5440_TMU_S0_7_TRIM);
+               break;
+       case 2:
+               trim_info = readl(data->base - EXYNOS5440_EFUSE_SWAP_OFFSET +
+                                 EXYNOS5440_TMU_S0_7_TRIM);
+       }
+       sanitize_temp_error(data, trim_info);
+
+       /* Write temperature code for rising and falling threshold */
+       rising_threshold = readl(data->base + EXYNOS5440_TMU_S0_7_TH0);
+       rising_threshold = get_th_reg(data, rising_threshold, false);
+       writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH0);
+       writel(0, data->base + EXYNOS5440_TMU_S0_7_TH1);
+
+       exynos_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]);
+               /* 5th level to be assigned in th2 reg */
+               rising_threshold =
+                       threshold_code << EXYNOS5440_TMU_TH_RISE4_SHIFT;
+               writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH2);
+               con = readl(data->base + EXYNOS5440_TMU_S0_7_CTRL);
+               con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
+               writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL);
+       }
+       /* Clear the PMIN in the common TMU register */
+       if (!data->id)
+               writel(0, data->base_second + EXYNOS5440_TMU_PMIN);
+       return ret;
+}
+
 static int exynos_tmu_read(struct exynos_tmu_data *data)
 {
        struct exynos_tmu_platform_data *pdata = data->pdata;
@@ -639,16 +673,24 @@ static int exynos_tmu_probe(struct platform_device *pdev)
                goto err_clk_sec;
        }
 
-       if (pdata->type == SOC_ARCH_EXYNOS3250 ||
-           pdata->type == SOC_ARCH_EXYNOS4210 ||
-           pdata->type == SOC_ARCH_EXYNOS4412 ||
-           pdata->type == SOC_ARCH_EXYNOS5250 ||
-           pdata->type == SOC_ARCH_EXYNOS5260 ||
-           pdata->type == SOC_ARCH_EXYNOS5420 ||
-           pdata->type == SOC_ARCH_EXYNOS5420_TRIMINFO ||
-           pdata->type == SOC_ARCH_EXYNOS5440)
-               data->soc = pdata->type;
-       else {
+       data->soc = pdata->type;
+
+       switch (data->soc) {
+       case SOC_ARCH_EXYNOS4210:
+               data->tmu_initialize = exynos4210_tmu_initialize;
+               break;
+       case SOC_ARCH_EXYNOS3250:
+       case SOC_ARCH_EXYNOS4412:
+       case SOC_ARCH_EXYNOS5250:
+       case SOC_ARCH_EXYNOS5260:
+       case SOC_ARCH_EXYNOS5420:
+       case SOC_ARCH_EXYNOS5420_TRIMINFO:
+               data->tmu_initialize = exynos4412_tmu_initialize;
+               break;
+       case SOC_ARCH_EXYNOS5440:
+               data->tmu_initialize = exynos5440_tmu_initialize;
+               break;
+       default:
                ret = -EINVAL;
                dev_err(&pdev->dev, "Platform not supported\n");
                goto err_clk;
index adecc7ff5b8ad05ae90c5f52df46ec439fadc4f0..f186f4ff44c4445861996fe542615e1665702ecd 100644 (file)
@@ -73,8 +73,6 @@ enum soc_type {
  * slightly across different exynos SOC's.
  * @tmu_ctrl: TMU main controller register.
  * @tmu_cur_temp: register containing the current temperature of the TMU.
- * @threshold_th0: Register containing first set of rising levels.
- * @threshold_th1: Register containing second set of rising levels.
  * @tmu_inten: register containing the different threshold interrupt
        enable bits.
  * @inten_rise0_shift: shift bits of rising 0 interrupt bits.
@@ -91,9 +89,6 @@ struct exynos_tmu_registers {
 
        u32     tmu_cur_temp;
 
-       u32     threshold_th0;
-       u32     threshold_th1;
-
        u32     tmu_inten;
        u32     inten_rise0_shift;
        u32     inten_rise1_shift;
index 1ed8bdc117a0f214d230366c2ffecaf65c6da713..db3b3bc53f768e49925e185c7129f2f6489406fc 100644 (file)
@@ -28,7 +28,6 @@
 static const struct exynos_tmu_registers exynos4210_tmu_registers = {
        .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
        .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
-       .threshold_th0 = EXYNOS4210_TMU_REG_TRIG_LEVEL0,
        .tmu_inten = EXYNOS_TMU_REG_INTEN,
        .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
        .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
@@ -83,8 +82,6 @@ struct exynos_tmu_init_data const exynos4210_default_tmu_data = {
 static const struct exynos_tmu_registers exynos3250_tmu_registers = {
        .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
        .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
-       .threshold_th0 = EXYNOS_THD_TEMP_RISE,
-       .threshold_th1 = EXYNOS_THD_TEMP_FALL,
        .tmu_inten = EXYNOS_TMU_REG_INTEN,
        .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
        .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
@@ -152,8 +149,6 @@ struct exynos_tmu_init_data const exynos3250_default_tmu_data = {
 static const struct exynos_tmu_registers exynos4412_tmu_registers = {
        .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
        .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
-       .threshold_th0 = EXYNOS_THD_TEMP_RISE,
-       .threshold_th1 = EXYNOS_THD_TEMP_FALL,
        .tmu_inten = EXYNOS_TMU_REG_INTEN,
        .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
        .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
@@ -234,8 +229,6 @@ struct exynos_tmu_init_data const exynos5250_default_tmu_data = {
 static const struct exynos_tmu_registers exynos5260_tmu_registers = {
        .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
        .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
-       .threshold_th0 = EXYNOS_THD_TEMP_RISE,
-       .threshold_th1 = EXYNOS_THD_TEMP_FALL,
        .tmu_inten = EXYNOS5260_TMU_REG_INTEN,
        .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
        .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
@@ -306,8 +299,6 @@ struct exynos_tmu_init_data const exynos5260_default_tmu_data = {
 static const struct exynos_tmu_registers exynos5420_tmu_registers = {
        .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
        .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
-       .threshold_th0 = EXYNOS_THD_TEMP_RISE,
-       .threshold_th1 = EXYNOS_THD_TEMP_FALL,
        .tmu_inten = EXYNOS_TMU_REG_INTEN,
        .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
        .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
@@ -385,8 +376,6 @@ struct exynos_tmu_init_data const exynos5420_default_tmu_data = {
 static const struct exynos_tmu_registers exynos5440_tmu_registers = {
        .tmu_ctrl = EXYNOS5440_TMU_S0_7_CTRL,
        .tmu_cur_temp = EXYNOS5440_TMU_S0_7_TEMP,
-       .threshold_th0 = EXYNOS5440_TMU_S0_7_TH0,
-       .threshold_th1 = EXYNOS5440_TMU_S0_7_TH1,
        .tmu_inten = EXYNOS5440_TMU_S0_7_IRQEN,
        .inten_rise0_shift = EXYNOS5440_TMU_INTEN_RISE0_SHIFT,
        .inten_rise1_shift = EXYNOS5440_TMU_INTEN_RISE1_SHIFT,