pinctrl: rockchip: fix pull setting error for rk3399
[firefly-linux-kernel-4.4.55.git] / drivers / thermal / rockchip_thermal.c
index e845841ab036cc82033d0a6829058a0f15f2543e..b4e3639fba79aceb333e94d853af59ba5a78ac6d 100644 (file)
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/reset.h>
 #include <linux/thermal.h>
+#include <linux/mfd/syscon.h>
 #include <linux/pinctrl/consumer.h>
 
 /**
@@ -38,7 +40,7 @@ enum tshut_mode {
 };
 
 /**
- * the system Temperature Sensors tshut(tshut) polarity
+ * The system Temperature Sensors tshut(tshut) polarity
  * the bit 8 is tshut polarity.
  * 0: low active, 1: high active
  */
@@ -57,10 +59,10 @@ enum sensor_id {
 };
 
 /**
-* The conversion table has the adc value and temperature.
-* ADC_DECREMENT is the adc value decremnet.(e.g. v2_code_table)
-* ADC_INCREMNET is the adc value incremnet.(e.g. v3_code_table)
-*/
+ * The conversion table has the adc value and temperature.
+ * ADC_DECREMENT: the adc value is of diminishing.(e.g. rk3288_code_table)
+ * ADC_INCREMENT: the adc value is incremental.(e.g. rk3368_code_table)
+ */
 enum adc_sort_mode {
        ADC_DECREMENT = 0,
        ADC_INCREMENT,
@@ -72,16 +74,17 @@ enum adc_sort_mode {
  */
 #define SOC_MAX_SENSORS        2
 
+/**
+ * struct chip_tsadc_table: hold information about chip-specific differences
+ * @id: conversion table
+ * @length: size of conversion table
+ * @data_mask: mask to apply on data inputs
+ * @mode: sort mode of this adc variant (incrementing or decrementing)
+ */
 struct chip_tsadc_table {
        const struct tsadc_table *id;
-
-       /* the array table size*/
        unsigned int length;
-
-       /* that analogic mask data */
        u32 data_mask;
-
-       /* the sort mode is adc value that increment or decrement in table */
        enum adc_sort_mode mode;
 };
 
@@ -96,7 +99,8 @@ struct rockchip_tsadc_chip {
        enum tshut_polarity tshut_polarity;
 
        /* Chip-wide methods */
-       void (*initialize)(void __iomem *reg, enum tshut_polarity p);
+       void (*initialize)(struct regmap *grf,
+                          void __iomem *reg, enum tshut_polarity p);
        void (*irq_ack)(void __iomem *reg);
        void (*control)(void __iomem *reg, bool on);
 
@@ -127,6 +131,7 @@ struct rockchip_thermal_data {
        struct clk *clk;
        struct clk *pclk;
 
+       struct regmap *grf;
        void __iomem *regs;
 
        int tshut_temp;
@@ -134,7 +139,13 @@ struct rockchip_thermal_data {
        enum tshut_polarity tshut_polarity;
 };
 
-/* TSADC Sensor info define: */
+/**
+ * TSADC Sensor Register description:
+ *
+ * TSADCV2_* are used for RK3288 SoCs, the other chips can reuse it.
+ * TSADCV3_* are used for newer SoCs than RK3288. (e.g: RK3228, RK3399)
+ *
+ */
 #define TSADCV2_AUTO_CON                       0x04
 #define TSADCV2_INT_EN                         0x08
 #define TSADCV2_INT_PD                         0x0c
@@ -148,12 +159,20 @@ struct rockchip_thermal_data {
 #define TSADCV2_AUTO_EN                                BIT(0)
 #define TSADCV2_AUTO_SRC_EN(chn)               BIT(4 + (chn))
 #define TSADCV2_AUTO_TSHUT_POLARITY_HIGH       BIT(8)
+/**
+ * TSADCV1_AUTO_Q_SEL_EN:
+ * whether select (1024 - tsadc_q) as output
+ * 1'b0:use tsadc_q as output(temperature-code is rising sequence)
+ * 1'b1:use(1024 - tsadc_q) as output (temperature-code is falling sequence)
+ */
+#define TSADCV3_AUTO_Q_SEL_EN                  BIT(1)
 
 #define TSADCV2_INT_SRC_EN(chn)                        BIT(chn)
 #define TSADCV2_SHUT_2GPIO_SRC_EN(chn)         BIT(4 + (chn))
 #define TSADCV2_SHUT_2CRU_SRC_EN(chn)          BIT(8 + (chn))
 
 #define TSADCV2_INT_PD_CLEAR_MASK              ~BIT(8)
+#define TSADCV3_INT_PD_CLEAR_MASK              ~BIT(16)
 
 #define TSADCV2_DATA_MASK                      0xfff
 #define TSADCV3_DATA_MASK                      0x3ff
@@ -163,12 +182,67 @@ struct rockchip_thermal_data {
 #define TSADCV2_AUTO_PERIOD_TIME               250 /* msec */
 #define TSADCV2_AUTO_PERIOD_HT_TIME            50  /* msec */
 
+#define GRF_SARADC_TESTBIT                     0x0e644
+#define GRF_TSADC_TESTBIT_L                    0x0e648
+#define GRF_TSADC_TESTBIT_H                    0x0e64c
+
+#define GRF_TSADC_TSEN_PD_ON                   (0x30003 << 0)
+#define GRF_TSADC_TSEN_PD_OFF                  (0x30000 << 0)
+#define GRF_SARADC_TESTBIT_ON                  (0x10001 << 2)
+#define GRF_TSADC_TESTBIT_H_ON                 (0x10001 << 2)
+
 struct tsadc_table {
        u32 code;
        int temp;
 };
 
-static const struct tsadc_table v2_code_table[] = {
+/**
+ * Note:
+ * Code to Temperature mapping of the Temperature sensor is a piece wise linear
+ * curve.Any temperature, code faling between to 2 give temperatures can be
+ * linearly interpolated.
+ * Code to Temperature mapping should be updated based on sillcon results.
+ */
+static const struct tsadc_table rk3228_code_table[] = {
+       {0, -40000},
+       {588, -40000},
+       {593, -35000},
+       {598, -30000},
+       {603, -25000},
+       {608, -20000},
+       {613, -15000},
+       {618, -10000},
+       {623, -5000},
+       {629, 0},
+       {634, 5000},
+       {639, 10000},
+       {644, 15000},
+       {649, 20000},
+       {654, 25000},
+       {660, 30000},
+       {665, 35000},
+       {670, 40000},
+       {675, 45000},
+       {681, 50000},
+       {686, 55000},
+       {691, 60000},
+       {696, 65000},
+       {702, 70000},
+       {707, 75000},
+       {712, 80000},
+       {717, 85000},
+       {723, 90000},
+       {728, 95000},
+       {733, 100000},
+       {738, 105000},
+       {744, 110000},
+       {749, 115000},
+       {754, 120000},
+       {760, 125000},
+       {TSADCV2_DATA_MASK, 125000},
+};
+
+static const struct tsadc_table rk3288_code_table[] = {
        {TSADCV2_DATA_MASK, -40000},
        {3800, -40000},
        {3792, -35000},
@@ -206,7 +280,7 @@ static const struct tsadc_table v2_code_table[] = {
        {3421, 125000},
 };
 
-static const struct tsadc_table v3_code_table[] = {
+static const struct tsadc_table rk3368_code_table[] = {
        {0, -40000},
        {106, -40000},
        {108, -35000},
@@ -245,6 +319,45 @@ static const struct tsadc_table v3_code_table[] = {
        {TSADCV3_DATA_MASK, 125000},
 };
 
+static const struct tsadc_table rk3399_code_table[] = {
+       {0, -40000},
+       {402, -40000},
+       {410, -35000},
+       {419, -30000},
+       {427, -25000},
+       {436, -20000},
+       {444, -15000},
+       {453, -10000},
+       {461, -5000},
+       {470, 0},
+       {478, 5000},
+       {487, 10000},
+       {496, 15000},
+       {504, 20000},
+       {513, 25000},
+       {521, 30000},
+       {530, 35000},
+       {538, 40000},
+       {547, 45000},
+       {555, 50000},
+       {564, 55000},
+       {573, 60000},
+       {581, 65000},
+       {590, 70000},
+       {599, 75000},
+       {607, 80000},
+       {616, 85000},
+       {624, 90000},
+       {633, 95000},
+       {642, 100000},
+       {650, 105000},
+       {659, 110000},
+       {668, 115000},
+       {677, 120000},
+       {685, 125000},
+       {TSADCV3_DATA_MASK, 125000},
+};
+
 static u32 rk_tsadcv2_temp_to_code(struct chip_tsadc_table table,
                                   int temp)
 {
@@ -326,7 +439,7 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code,
         * temperature between 2 table entries is linear and interpolate
         * to produce less granular result.
         */
-       num = table.id[mid].temp - v2_code_table[mid - 1].temp;
+       num = table.id[mid].temp - table.id[mid - 1].temp;
        num *= abs(table.id[mid - 1].code - code);
        denom = abs(table.id[mid - 1].code - table.id[mid].code);
        *temp = table.id[mid - 1].temp + (num / denom);
@@ -349,9 +462,63 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code,
  *     If the temperature is higher than COMP_INT or COMP_SHUT for
  *     "debounce" times, TSADC controller will generate interrupt or TSHUT.
  */
-static void rk_tsadcv2_initialize(void __iomem *regs,
+static void rk_tsadcv2_initialize(struct regmap *grf, void __iomem *regs,
+                                 enum tshut_polarity tshut_polarity)
+{
+       if (tshut_polarity == TSHUT_HIGH_ACTIVE)
+               writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
+                              regs + TSADCV2_AUTO_CON);
+       else
+               writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
+                              regs + TSADCV2_AUTO_CON);
+
+       writel_relaxed(TSADCV2_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD);
+       writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT,
+                      regs + TSADCV2_HIGHT_INT_DEBOUNCE);
+       writel_relaxed(TSADCV2_AUTO_PERIOD_HT_TIME,
+                      regs + TSADCV2_AUTO_PERIOD_HT);
+       writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT,
+                      regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
+
+       if (IS_ERR(grf)) {
+               pr_warn("%s: Missing rockchip,grf property\n", __func__);
+               return;
+       }
+}
+
+/**
+ * rk_tsadcv3_initialize - initialize TASDC Controller.
+ * (1) The tsadc control power sequence.
+ *
+ * (2) Set TSADC_V2_AUTO_PERIOD:
+ *     Configure the interleave between every two accessing of
+ *     TSADC in normal operation.
+ *
+ * (2) Set TSADCV2_AUTO_PERIOD_HT:
+ *     Configure the interleave between every two accessing of
+ *     TSADC after the temperature is higher than COM_SHUT or COM_INT.
+ *
+ * (3) Set TSADCV2_HIGH_INT_DEBOUNCE and TSADC_HIGHT_TSHUT_DEBOUNCE:
+ *     If the temperature is higher than COMP_INT or COMP_SHUT for
+ *     "debounce" times, TSADC controller will generate interrupt or TSHUT.
+ */
+static void rk_tsadcv3_initialize(struct regmap *grf, void __iomem *regs,
                                  enum tshut_polarity tshut_polarity)
 {
+       if (IS_ERR(grf)) {
+               pr_warn("%s: Missing rockchip,grf property\n", __func__);
+               return;
+       }
+
+       /* The tsadc control power sequence */
+       regmap_write(grf, GRF_TSADC_TESTBIT_L, GRF_TSADC_TSEN_PD_ON);
+       mdelay(10);
+       regmap_write(grf, GRF_TSADC_TESTBIT_L, GRF_TSADC_TSEN_PD_OFF);
+       udelay(100); /* The spec note says at least 15 us */
+       regmap_write(grf, GRF_SARADC_TESTBIT, GRF_SARADC_TESTBIT_ON);
+       regmap_write(grf, GRF_TSADC_TESTBIT_H, GRF_TSADC_TESTBIT_H_ON);
+       udelay(200); /* The spec note says at least 90 us */
+
        if (tshut_polarity == TSHUT_HIGH_ACTIVE)
                writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
                               regs + TSADCV2_AUTO_CON);
@@ -376,6 +543,14 @@ static void rk_tsadcv2_irq_ack(void __iomem *regs)
        writel_relaxed(val & TSADCV2_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD);
 }
 
+static void rk_tsadcv3_irq_ack(void __iomem *regs)
+{
+       u32 val;
+
+       val = readl_relaxed(regs + TSADCV2_INT_PD);
+       writel_relaxed(val & TSADCV3_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD);
+}
+
 static void rk_tsadcv2_control(void __iomem *regs, bool enable)
 {
        u32 val;
@@ -389,6 +564,25 @@ static void rk_tsadcv2_control(void __iomem *regs, bool enable)
        writel_relaxed(val, regs + TSADCV2_AUTO_CON);
 }
 
+/**
+ * @rk_tsadcv3_control:
+ * TSADC controller works at auto mode, and some SoCs need set the tsadc_q_sel
+ * bit on TSADCV2_AUTO_CON[1]. The (1024 - tsadc_q) as output adc value if
+ * setting this bit to enable.
+ */
+static void rk_tsadcv3_control(void __iomem *regs, bool enable)
+{
+       u32 val;
+
+       val = readl_relaxed(regs + TSADCV2_AUTO_CON);
+       if (enable)
+               val |= TSADCV2_AUTO_EN | TSADCV3_AUTO_Q_SEL_EN;
+       else
+               val &= ~TSADCV2_AUTO_EN;
+
+       writel_relaxed(val, regs + TSADCV2_AUTO_CON);
+}
+
 static int rk_tsadcv2_get_temp(struct chip_tsadc_table table,
                               int chn, void __iomem *regs, int *temp)
 {
@@ -429,6 +623,29 @@ static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs,
        writel_relaxed(val, regs + TSADCV2_INT_EN);
 }
 
+static const struct rockchip_tsadc_chip rk3228_tsadc_data = {
+       .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
+       .chn_num = 1, /* one channel for tsadc */
+
+       .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
+       .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
+       .tshut_temp = 95000,
+
+       .initialize = rk_tsadcv2_initialize,
+       .irq_ack = rk_tsadcv3_irq_ack,
+       .control = rk_tsadcv3_control,
+       .get_temp = rk_tsadcv2_get_temp,
+       .set_tshut_temp = rk_tsadcv2_tshut_temp,
+       .set_tshut_mode = rk_tsadcv2_tshut_mode,
+
+       .table = {
+               .id = rk3228_code_table,
+               .length = ARRAY_SIZE(rk3228_code_table),
+               .data_mask = TSADCV3_DATA_MASK,
+               .mode = ADC_INCREMENT,
+       },
+};
+
 static const struct rockchip_tsadc_chip rk3288_tsadc_data = {
        .chn_id[SENSOR_CPU] = 1, /* cpu sensor is channel 1 */
        .chn_id[SENSOR_GPU] = 2, /* gpu sensor is channel 2 */
@@ -446,8 +663,8 @@ static const struct rockchip_tsadc_chip rk3288_tsadc_data = {
        .set_tshut_mode = rk_tsadcv2_tshut_mode,
 
        .table = {
-               .id = v2_code_table,
-               .length = ARRAY_SIZE(v2_code_table),
+               .id = rk3288_code_table,
+               .length = ARRAY_SIZE(rk3288_code_table),
                .data_mask = TSADCV2_DATA_MASK,
                .mode = ADC_DECREMENT,
        },
@@ -470,14 +687,42 @@ static const struct rockchip_tsadc_chip rk3368_tsadc_data = {
        .set_tshut_mode = rk_tsadcv2_tshut_mode,
 
        .table = {
-               .id = v3_code_table,
-               .length = ARRAY_SIZE(v3_code_table),
+               .id = rk3368_code_table,
+               .length = ARRAY_SIZE(rk3368_code_table),
+               .data_mask = TSADCV3_DATA_MASK,
+               .mode = ADC_INCREMENT,
+       },
+};
+
+static const struct rockchip_tsadc_chip rk3399_tsadc_data = {
+       .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
+       .chn_id[SENSOR_GPU] = 1, /* gpu sensor is channel 1 */
+       .chn_num = 2, /* two channels for tsadc */
+
+       .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
+       .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
+       .tshut_temp = 95000,
+
+       .initialize = rk_tsadcv3_initialize,
+       .irq_ack = rk_tsadcv3_irq_ack,
+       .control = rk_tsadcv3_control,
+       .get_temp = rk_tsadcv2_get_temp,
+       .set_tshut_temp = rk_tsadcv2_tshut_temp,
+       .set_tshut_mode = rk_tsadcv2_tshut_mode,
+
+       .table = {
+               .id = rk3399_code_table,
+               .length = ARRAY_SIZE(rk3399_code_table),
                .data_mask = TSADCV3_DATA_MASK,
                .mode = ADC_INCREMENT,
        },
 };
 
 static const struct of_device_id of_rockchip_thermal_match[] = {
+       {
+               .compatible = "rockchip,rk3228-tsadc",
+               .data = (void *)&rk3228_tsadc_data,
+       },
        {
                .compatible = "rockchip,rk3288-tsadc",
                .data = (void *)&rk3288_tsadc_data,
@@ -486,6 +731,10 @@ static const struct of_device_id of_rockchip_thermal_match[] = {
                .compatible = "rockchip,rk3368-tsadc",
                .data = (void *)&rk3368_tsadc_data,
        },
+       {
+               .compatible = "rockchip,rk3399-tsadc",
+               .data = (void *)&rk3399_tsadc_data,
+       },
        { /* end */ },
 };
 MODULE_DEVICE_TABLE(of, of_rockchip_thermal_match);
@@ -545,15 +794,14 @@ static int rockchip_configure_from_dt(struct device *dev,
                         thermal->chip->tshut_temp);
                thermal->tshut_temp = thermal->chip->tshut_temp;
        } else {
+               if (shut_temp > INT_MAX) {
+                       dev_err(dev, "Invalid tshut temperature specified: %d\n",
+                               shut_temp);
+                       return -ERANGE;
+               }
                thermal->tshut_temp = shut_temp;
        }
 
-       if (thermal->tshut_temp > INT_MAX) {
-               dev_err(dev, "Invalid tshut temperature specified: %d\n",
-                       thermal->tshut_temp);
-               return -ERANGE;
-       }
-
        if (of_property_read_u32(np, "rockchip,hw-tshut-mode", &tshut_mode)) {
                dev_warn(dev,
                         "Missing tshut mode property, using default (%s)\n",
@@ -587,6 +835,11 @@ static int rockchip_configure_from_dt(struct device *dev,
                return -EINVAL;
        }
 
+       /* The tsadc wont to handle the error in here since some SoCs didn't
+        * need this property.
+        */
+       thermal->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
+
        return 0;
 }
 
@@ -617,7 +870,7 @@ rockchip_thermal_register_sensor(struct platform_device *pdev,
        return 0;
 }
 
-/*
+/**
  * Reset TSADC Controller, reset all tsadc registers.
  */
 static void rockchip_thermal_reset_controller(struct reset_control *reset)
@@ -707,7 +960,8 @@ static int rockchip_thermal_probe(struct platform_device *pdev)
                goto err_disable_pclk;
        }
 
-       thermal->chip->initialize(thermal->regs, thermal->tshut_polarity);
+       thermal->chip->initialize(thermal->grf, thermal->regs,
+                                 thermal->tshut_polarity);
 
        for (i = 0; i < thermal->chip->chn_num; i++) {
                error = rockchip_thermal_register_sensor(pdev, thermal,
@@ -812,7 +1066,8 @@ static int __maybe_unused rockchip_thermal_resume(struct device *dev)
 
        rockchip_thermal_reset_controller(thermal->reset);
 
-       thermal->chip->initialize(thermal->regs, thermal->tshut_polarity);
+       thermal->chip->initialize(thermal->grf, thermal->regs,
+                                 thermal->tshut_polarity);
 
        for (i = 0; i < thermal->chip->chn_num; i++) {
                int id = thermal->sensors[i].id;