Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // Copyright (C) 2020 Spreadtrum Communications Inc.
0003 
0004 #include <linux/clk.h>
0005 #include <linux/io.h>
0006 #include <linux/iopoll.h>
0007 #include <linux/module.h>
0008 #include <linux/nvmem-consumer.h>
0009 #include <linux/of_device.h>
0010 #include <linux/platform_device.h>
0011 #include <linux/slab.h>
0012 #include <linux/thermal.h>
0013 
0014 #define SPRD_THM_CTL            0x0
0015 #define SPRD_THM_INT_EN         0x4
0016 #define SPRD_THM_INT_STS        0x8
0017 #define SPRD_THM_INT_RAW_STS        0xc
0018 #define SPRD_THM_DET_PERIOD     0x10
0019 #define SPRD_THM_INT_CLR        0x14
0020 #define SPRD_THM_INT_CLR_ST     0x18
0021 #define SPRD_THM_MON_PERIOD     0x4c
0022 #define SPRD_THM_MON_CTL        0x50
0023 #define SPRD_THM_INTERNAL_STS1      0x54
0024 #define SPRD_THM_RAW_READ_MSK       0x3ff
0025 
0026 #define SPRD_THM_OFFSET(id)     ((id) * 0x4)
0027 #define SPRD_THM_TEMP(id)       (SPRD_THM_OFFSET(id) + 0x5c)
0028 #define SPRD_THM_THRES(id)      (SPRD_THM_OFFSET(id) + 0x2c)
0029 
0030 #define SPRD_THM_SEN(id)        BIT((id) + 2)
0031 #define SPRD_THM_SEN_OVERHEAT_EN(id)    BIT((id) + 8)
0032 #define SPRD_THM_SEN_OVERHEAT_ALARM_EN(id)  BIT((id) + 0)
0033 
0034 /* bits definitions for register THM_CTL */
0035 #define SPRD_THM_SET_RDY_ST     BIT(13)
0036 #define SPRD_THM_SET_RDY        BIT(12)
0037 #define SPRD_THM_MON_EN         BIT(1)
0038 #define SPRD_THM_EN         BIT(0)
0039 
0040 /* bits definitions for register THM_INT_CTL */
0041 #define SPRD_THM_BIT_INT_EN     BIT(26)
0042 #define SPRD_THM_OVERHEAT_EN        BIT(25)
0043 #define SPRD_THM_OTP_TRIP_SHIFT     10
0044 
0045 /* bits definitions for register SPRD_THM_INTERNAL_STS1 */
0046 #define SPRD_THM_TEMPER_RDY     BIT(0)
0047 
0048 #define SPRD_THM_DET_PERIOD_DATA    0x800
0049 #define SPRD_THM_DET_PERIOD_MASK    GENMASK(19, 0)
0050 #define SPRD_THM_MON_MODE       0x7
0051 #define SPRD_THM_MON_MODE_MASK      GENMASK(3, 0)
0052 #define SPRD_THM_MON_PERIOD_DATA    0x10
0053 #define SPRD_THM_MON_PERIOD_MASK    GENMASK(15, 0)
0054 #define SPRD_THM_THRES_MASK     GENMASK(19, 0)
0055 #define SPRD_THM_INT_CLR_MASK       GENMASK(24, 0)
0056 
0057 /* thermal sensor calibration parameters */
0058 #define SPRD_THM_TEMP_LOW       -40000
0059 #define SPRD_THM_TEMP_HIGH      120000
0060 #define SPRD_THM_OTP_TEMP       120000
0061 #define SPRD_THM_HOT_TEMP       75000
0062 #define SPRD_THM_RAW_DATA_LOW       0
0063 #define SPRD_THM_RAW_DATA_HIGH      1000
0064 #define SPRD_THM_SEN_NUM        8
0065 #define SPRD_THM_DT_OFFSET      24
0066 #define SPRD_THM_RATION_OFFSET      17
0067 #define SPRD_THM_RATION_SIGN        16
0068 
0069 #define SPRD_THM_RDYST_POLLING_TIME 10
0070 #define SPRD_THM_RDYST_TIMEOUT      700
0071 #define SPRD_THM_TEMP_READY_POLL_TIME   10000
0072 #define SPRD_THM_TEMP_READY_TIMEOUT 600000
0073 #define SPRD_THM_MAX_SENSOR     8
0074 
0075 struct sprd_thermal_sensor {
0076     struct thermal_zone_device *tzd;
0077     struct sprd_thermal_data *data;
0078     struct device *dev;
0079     int cal_slope;
0080     int cal_offset;
0081     int id;
0082 };
0083 
0084 struct sprd_thermal_data {
0085     const struct sprd_thm_variant_data *var_data;
0086     struct sprd_thermal_sensor *sensor[SPRD_THM_MAX_SENSOR];
0087     struct clk *clk;
0088     void __iomem *base;
0089     u32 ratio_off;
0090     int ratio_sign;
0091     int nr_sensors;
0092 };
0093 
0094 /*
0095  * The conversion between ADC and temperature is based on linear relationship,
0096  * and use idea_k to specify the slope and ideal_b to specify the offset.
0097  *
0098  * Since different Spreadtrum SoCs have different ideal_k and ideal_b,
0099  * we should save ideal_k and ideal_b in the device data structure.
0100  */
0101 struct sprd_thm_variant_data {
0102     u32 ideal_k;
0103     u32 ideal_b;
0104 };
0105 
0106 static const struct sprd_thm_variant_data ums512_data = {
0107     .ideal_k = 262,
0108     .ideal_b = 66400,
0109 };
0110 
0111 static inline void sprd_thm_update_bits(void __iomem *reg, u32 mask, u32 val)
0112 {
0113     u32 tmp, orig;
0114 
0115     orig = readl(reg);
0116     tmp = orig & ~mask;
0117     tmp |= val & mask;
0118     writel(tmp, reg);
0119 }
0120 
0121 static int sprd_thm_cal_read(struct device_node *np, const char *cell_id,
0122                  u32 *val)
0123 {
0124     struct nvmem_cell *cell;
0125     void *buf;
0126     size_t len;
0127 
0128     cell = of_nvmem_cell_get(np, cell_id);
0129     if (IS_ERR(cell))
0130         return PTR_ERR(cell);
0131 
0132     buf = nvmem_cell_read(cell, &len);
0133     nvmem_cell_put(cell);
0134     if (IS_ERR(buf))
0135         return PTR_ERR(buf);
0136 
0137     if (len > sizeof(u32)) {
0138         kfree(buf);
0139         return -EINVAL;
0140     }
0141 
0142     memcpy(val, buf, len);
0143 
0144     kfree(buf);
0145     return 0;
0146 }
0147 
0148 static int sprd_thm_sensor_calibration(struct device_node *np,
0149                        struct sprd_thermal_data *thm,
0150                        struct sprd_thermal_sensor *sen)
0151 {
0152     int ret;
0153     /*
0154      * According to thermal datasheet, the default calibration offset is 64,
0155      * and the default ratio is 1000.
0156      */
0157     int dt_offset = 64, ratio = 1000;
0158 
0159     ret = sprd_thm_cal_read(np, "sen_delta_cal", &dt_offset);
0160     if (ret)
0161         return ret;
0162 
0163     ratio += thm->ratio_sign * thm->ratio_off;
0164 
0165     /*
0166      * According to the ideal slope K and ideal offset B, combined with
0167      * calibration value of thermal from efuse, then calibrate the real
0168      * slope k and offset b:
0169      * k_cal = (k * ratio) / 1000.
0170      * b_cal = b + (dt_offset - 64) * 500.
0171      */
0172     sen->cal_slope = (thm->var_data->ideal_k * ratio) / 1000;
0173     sen->cal_offset = thm->var_data->ideal_b + (dt_offset - 128) * 250;
0174 
0175     return 0;
0176 }
0177 
0178 static int sprd_thm_rawdata_to_temp(struct sprd_thermal_sensor *sen,
0179                     u32 rawdata)
0180 {
0181     clamp(rawdata, (u32)SPRD_THM_RAW_DATA_LOW, (u32)SPRD_THM_RAW_DATA_HIGH);
0182 
0183     /*
0184      * According to the thermal datasheet, the formula of converting
0185      * adc value to the temperature value should be:
0186      * T_final = k_cal * x - b_cal.
0187      */
0188     return sen->cal_slope * rawdata - sen->cal_offset;
0189 }
0190 
0191 static int sprd_thm_temp_to_rawdata(int temp, struct sprd_thermal_sensor *sen)
0192 {
0193     u32 val;
0194 
0195     clamp(temp, (int)SPRD_THM_TEMP_LOW, (int)SPRD_THM_TEMP_HIGH);
0196 
0197     /*
0198      * According to the thermal datasheet, the formula of converting
0199      * adc value to the temperature value should be:
0200      * T_final = k_cal * x - b_cal.
0201      */
0202     val = (temp + sen->cal_offset) / sen->cal_slope;
0203 
0204     return clamp(val, val, (u32)(SPRD_THM_RAW_DATA_HIGH - 1));
0205 }
0206 
0207 static int sprd_thm_read_temp(void *devdata, int *temp)
0208 {
0209     struct sprd_thermal_sensor *sen = devdata;
0210     u32 data;
0211 
0212     data = readl(sen->data->base + SPRD_THM_TEMP(sen->id)) &
0213         SPRD_THM_RAW_READ_MSK;
0214 
0215     *temp = sprd_thm_rawdata_to_temp(sen, data);
0216 
0217     return 0;
0218 }
0219 
0220 static const struct thermal_zone_of_device_ops sprd_thm_ops = {
0221     .get_temp = sprd_thm_read_temp,
0222 };
0223 
0224 static int sprd_thm_poll_ready_status(struct sprd_thermal_data *thm)
0225 {
0226     u32 val;
0227     int ret;
0228 
0229     /*
0230      * Wait for thermal ready status before configuring thermal parameters.
0231      */
0232     ret = readl_poll_timeout(thm->base + SPRD_THM_CTL, val,
0233                  !(val & SPRD_THM_SET_RDY_ST),
0234                  SPRD_THM_RDYST_POLLING_TIME,
0235                  SPRD_THM_RDYST_TIMEOUT);
0236     if (ret)
0237         return ret;
0238 
0239     sprd_thm_update_bits(thm->base + SPRD_THM_CTL, SPRD_THM_MON_EN,
0240                  SPRD_THM_MON_EN);
0241     sprd_thm_update_bits(thm->base + SPRD_THM_CTL, SPRD_THM_SET_RDY,
0242                  SPRD_THM_SET_RDY);
0243     return 0;
0244 }
0245 
0246 static int sprd_thm_wait_temp_ready(struct sprd_thermal_data *thm)
0247 {
0248     u32 val;
0249 
0250     /* Wait for first temperature data ready before reading temperature */
0251     return readl_poll_timeout(thm->base + SPRD_THM_INTERNAL_STS1, val,
0252                   !(val & SPRD_THM_TEMPER_RDY),
0253                   SPRD_THM_TEMP_READY_POLL_TIME,
0254                   SPRD_THM_TEMP_READY_TIMEOUT);
0255 }
0256 
0257 static int sprd_thm_set_ready(struct sprd_thermal_data *thm)
0258 {
0259     int ret;
0260 
0261     ret = sprd_thm_poll_ready_status(thm);
0262     if (ret)
0263         return ret;
0264 
0265     /*
0266      * Clear interrupt status, enable thermal interrupt and enable thermal.
0267      *
0268      * The SPRD thermal controller integrates a hardware interrupt signal,
0269      * which means if the temperature is overheat, it will generate an
0270      * interrupt and notify the event to PMIC automatically to shutdown the
0271      * system. So here we should enable the interrupt bits, though we have
0272      * not registered an irq handler.
0273      */
0274     writel(SPRD_THM_INT_CLR_MASK, thm->base + SPRD_THM_INT_CLR);
0275     sprd_thm_update_bits(thm->base + SPRD_THM_INT_EN,
0276                  SPRD_THM_BIT_INT_EN, SPRD_THM_BIT_INT_EN);
0277     sprd_thm_update_bits(thm->base + SPRD_THM_CTL,
0278                  SPRD_THM_EN, SPRD_THM_EN);
0279     return 0;
0280 }
0281 
0282 static void sprd_thm_sensor_init(struct sprd_thermal_data *thm,
0283                  struct sprd_thermal_sensor *sen)
0284 {
0285     u32 otp_rawdata, hot_rawdata;
0286 
0287     otp_rawdata = sprd_thm_temp_to_rawdata(SPRD_THM_OTP_TEMP, sen);
0288     hot_rawdata = sprd_thm_temp_to_rawdata(SPRD_THM_HOT_TEMP, sen);
0289 
0290     /* Enable the sensor' overheat temperature protection interrupt */
0291     sprd_thm_update_bits(thm->base + SPRD_THM_INT_EN,
0292                  SPRD_THM_SEN_OVERHEAT_ALARM_EN(sen->id),
0293                  SPRD_THM_SEN_OVERHEAT_ALARM_EN(sen->id));
0294 
0295     /* Set the sensor' overheat and hot threshold temperature */
0296     sprd_thm_update_bits(thm->base + SPRD_THM_THRES(sen->id),
0297                  SPRD_THM_THRES_MASK,
0298                  (otp_rawdata << SPRD_THM_OTP_TRIP_SHIFT) |
0299                  hot_rawdata);
0300 
0301     /* Enable the corresponding sensor */
0302     sprd_thm_update_bits(thm->base + SPRD_THM_CTL, SPRD_THM_SEN(sen->id),
0303                  SPRD_THM_SEN(sen->id));
0304 }
0305 
0306 static void sprd_thm_para_config(struct sprd_thermal_data *thm)
0307 {
0308     /* Set the period of two valid temperature detection action */
0309     sprd_thm_update_bits(thm->base + SPRD_THM_DET_PERIOD,
0310                  SPRD_THM_DET_PERIOD_MASK, SPRD_THM_DET_PERIOD);
0311 
0312     /* Set the sensors' monitor mode */
0313     sprd_thm_update_bits(thm->base + SPRD_THM_MON_CTL,
0314                  SPRD_THM_MON_MODE_MASK, SPRD_THM_MON_MODE);
0315 
0316     /* Set the sensors' monitor period */
0317     sprd_thm_update_bits(thm->base + SPRD_THM_MON_PERIOD,
0318                  SPRD_THM_MON_PERIOD_MASK, SPRD_THM_MON_PERIOD);
0319 }
0320 
0321 static void sprd_thm_toggle_sensor(struct sprd_thermal_sensor *sen, bool on)
0322 {
0323     struct thermal_zone_device *tzd = sen->tzd;
0324 
0325     if (on)
0326         thermal_zone_device_enable(tzd);
0327     else
0328         thermal_zone_device_disable(tzd);
0329 }
0330 
0331 static int sprd_thm_probe(struct platform_device *pdev)
0332 {
0333     struct device_node *np = pdev->dev.of_node;
0334     struct device_node *sen_child;
0335     struct sprd_thermal_data *thm;
0336     struct sprd_thermal_sensor *sen;
0337     const struct sprd_thm_variant_data *pdata;
0338     int ret, i;
0339     u32 val;
0340 
0341     pdata = of_device_get_match_data(&pdev->dev);
0342     if (!pdata) {
0343         dev_err(&pdev->dev, "No matching driver data found\n");
0344         return -EINVAL;
0345     }
0346 
0347     thm = devm_kzalloc(&pdev->dev, sizeof(*thm), GFP_KERNEL);
0348     if (!thm)
0349         return -ENOMEM;
0350 
0351     thm->var_data = pdata;
0352     thm->base = devm_platform_ioremap_resource(pdev, 0);
0353     if (IS_ERR(thm->base))
0354         return PTR_ERR(thm->base);
0355 
0356     thm->nr_sensors = of_get_child_count(np);
0357     if (thm->nr_sensors == 0 || thm->nr_sensors > SPRD_THM_MAX_SENSOR) {
0358         dev_err(&pdev->dev, "incorrect sensor count\n");
0359         return -EINVAL;
0360     }
0361 
0362     thm->clk = devm_clk_get(&pdev->dev, "enable");
0363     if (IS_ERR(thm->clk)) {
0364         dev_err(&pdev->dev, "failed to get enable clock\n");
0365         return PTR_ERR(thm->clk);
0366     }
0367 
0368     ret = clk_prepare_enable(thm->clk);
0369     if (ret)
0370         return ret;
0371 
0372     sprd_thm_para_config(thm);
0373 
0374     ret = sprd_thm_cal_read(np, "thm_sign_cal", &val);
0375     if (ret)
0376         goto disable_clk;
0377 
0378     if (val > 0)
0379         thm->ratio_sign = -1;
0380     else
0381         thm->ratio_sign = 1;
0382 
0383     ret = sprd_thm_cal_read(np, "thm_ratio_cal", &thm->ratio_off);
0384     if (ret)
0385         goto disable_clk;
0386 
0387     for_each_child_of_node(np, sen_child) {
0388         sen = devm_kzalloc(&pdev->dev, sizeof(*sen), GFP_KERNEL);
0389         if (!sen) {
0390             ret = -ENOMEM;
0391             goto of_put;
0392         }
0393 
0394         sen->data = thm;
0395         sen->dev = &pdev->dev;
0396 
0397         ret = of_property_read_u32(sen_child, "reg", &sen->id);
0398         if (ret) {
0399             dev_err(&pdev->dev, "get sensor reg failed");
0400             goto of_put;
0401         }
0402 
0403         ret = sprd_thm_sensor_calibration(sen_child, thm, sen);
0404         if (ret) {
0405             dev_err(&pdev->dev, "efuse cal analysis failed");
0406             goto of_put;
0407         }
0408 
0409         sprd_thm_sensor_init(thm, sen);
0410 
0411         sen->tzd = devm_thermal_zone_of_sensor_register(sen->dev,
0412                                 sen->id,
0413                                 sen,
0414                                 &sprd_thm_ops);
0415         if (IS_ERR(sen->tzd)) {
0416             dev_err(&pdev->dev, "register thermal zone failed %d\n",
0417                 sen->id);
0418             ret = PTR_ERR(sen->tzd);
0419             goto of_put;
0420         }
0421 
0422         thm->sensor[sen->id] = sen;
0423     }
0424     /* sen_child set to NULL at this point */
0425 
0426     ret = sprd_thm_set_ready(thm);
0427     if (ret)
0428         goto of_put;
0429 
0430     ret = sprd_thm_wait_temp_ready(thm);
0431     if (ret)
0432         goto of_put;
0433 
0434     for (i = 0; i < thm->nr_sensors; i++)
0435         sprd_thm_toggle_sensor(thm->sensor[i], true);
0436 
0437     platform_set_drvdata(pdev, thm);
0438     return 0;
0439 
0440 of_put:
0441     of_node_put(sen_child);
0442 disable_clk:
0443     clk_disable_unprepare(thm->clk);
0444     return ret;
0445 }
0446 
0447 #ifdef CONFIG_PM_SLEEP
0448 static void sprd_thm_hw_suspend(struct sprd_thermal_data *thm)
0449 {
0450     int i;
0451 
0452     for (i = 0; i < thm->nr_sensors; i++) {
0453         sprd_thm_update_bits(thm->base + SPRD_THM_CTL,
0454                      SPRD_THM_SEN(thm->sensor[i]->id), 0);
0455     }
0456 
0457     sprd_thm_update_bits(thm->base + SPRD_THM_CTL,
0458                  SPRD_THM_EN, 0x0);
0459 }
0460 
0461 static int sprd_thm_suspend(struct device *dev)
0462 {
0463     struct sprd_thermal_data *thm = dev_get_drvdata(dev);
0464     int i;
0465 
0466     for (i = 0; i < thm->nr_sensors; i++)
0467         sprd_thm_toggle_sensor(thm->sensor[i], false);
0468 
0469     sprd_thm_hw_suspend(thm);
0470     clk_disable_unprepare(thm->clk);
0471 
0472     return 0;
0473 }
0474 
0475 static int sprd_thm_hw_resume(struct sprd_thermal_data *thm)
0476 {
0477     int ret, i;
0478 
0479     for (i = 0; i < thm->nr_sensors; i++) {
0480         sprd_thm_update_bits(thm->base + SPRD_THM_CTL,
0481                      SPRD_THM_SEN(thm->sensor[i]->id),
0482                      SPRD_THM_SEN(thm->sensor[i]->id));
0483     }
0484 
0485     ret = sprd_thm_poll_ready_status(thm);
0486     if (ret)
0487         return ret;
0488 
0489     writel(SPRD_THM_INT_CLR_MASK, thm->base + SPRD_THM_INT_CLR);
0490     sprd_thm_update_bits(thm->base + SPRD_THM_CTL,
0491                  SPRD_THM_EN, SPRD_THM_EN);
0492     return sprd_thm_wait_temp_ready(thm);
0493 }
0494 
0495 static int sprd_thm_resume(struct device *dev)
0496 {
0497     struct sprd_thermal_data *thm = dev_get_drvdata(dev);
0498     int ret, i;
0499 
0500     ret = clk_prepare_enable(thm->clk);
0501     if (ret)
0502         return ret;
0503 
0504     ret = sprd_thm_hw_resume(thm);
0505     if (ret)
0506         goto disable_clk;
0507 
0508     for (i = 0; i < thm->nr_sensors; i++)
0509         sprd_thm_toggle_sensor(thm->sensor[i], true);
0510 
0511     return 0;
0512 
0513 disable_clk:
0514     clk_disable_unprepare(thm->clk);
0515     return ret;
0516 }
0517 #endif
0518 
0519 static int sprd_thm_remove(struct platform_device *pdev)
0520 {
0521     struct sprd_thermal_data *thm = platform_get_drvdata(pdev);
0522     int i;
0523 
0524     for (i = 0; i < thm->nr_sensors; i++) {
0525         sprd_thm_toggle_sensor(thm->sensor[i], false);
0526         devm_thermal_zone_of_sensor_unregister(&pdev->dev,
0527                                thm->sensor[i]->tzd);
0528     }
0529 
0530     clk_disable_unprepare(thm->clk);
0531     return 0;
0532 }
0533 
0534 static const struct of_device_id sprd_thermal_of_match[] = {
0535     { .compatible = "sprd,ums512-thermal", .data = &ums512_data },
0536     { },
0537 };
0538 MODULE_DEVICE_TABLE(of, sprd_thermal_of_match);
0539 
0540 static const struct dev_pm_ops sprd_thermal_pm_ops = {
0541     SET_SYSTEM_SLEEP_PM_OPS(sprd_thm_suspend, sprd_thm_resume)
0542 };
0543 
0544 static struct platform_driver sprd_thermal_driver = {
0545     .probe = sprd_thm_probe,
0546     .remove = sprd_thm_remove,
0547     .driver = {
0548         .name = "sprd-thermal",
0549         .pm = &sprd_thermal_pm_ops,
0550         .of_match_table = sprd_thermal_of_match,
0551     },
0552 };
0553 
0554 module_platform_driver(sprd_thermal_driver);
0555 
0556 MODULE_AUTHOR("Freeman Liu <freeman.liu@unisoc.com>");
0557 MODULE_DESCRIPTION("Spreadtrum thermal driver");
0558 MODULE_LICENSE("GPL v2");