root/drivers/thermal/intel/intel_soc_dts_iosf.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_tj_max
  2. sys_get_trip_temp
  3. update_trip_temp
  4. sys_set_trip_temp
  5. sys_get_trip_type
  6. sys_get_curr_temp
  7. soc_dts_enable
  8. remove_dts_thermal_zone
  9. add_dts_thermal_zone
  10. intel_soc_dts_iosf_add_read_only_critical_trip
  11. intel_soc_dts_iosf_interrupt_handler
  12. intel_soc_dts_iosf_init
  13. intel_soc_dts_iosf_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * intel_soc_dts_iosf.c
   4  * Copyright (c) 2015, Intel Corporation.
   5  */
   6 
   7 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   8 
   9 #include <linux/module.h>
  10 #include <linux/slab.h>
  11 #include <linux/interrupt.h>
  12 #include <asm/iosf_mbi.h>
  13 #include "intel_soc_dts_iosf.h"
  14 
  15 #define SOC_DTS_OFFSET_ENABLE           0xB0
  16 #define SOC_DTS_OFFSET_TEMP             0xB1
  17 
  18 #define SOC_DTS_OFFSET_PTPS             0xB2
  19 #define SOC_DTS_OFFSET_PTTS             0xB3
  20 #define SOC_DTS_OFFSET_PTTSS            0xB4
  21 #define SOC_DTS_OFFSET_PTMC             0x80
  22 #define SOC_DTS_TE_AUX0                 0xB5
  23 #define SOC_DTS_TE_AUX1                 0xB6
  24 
  25 #define SOC_DTS_AUX0_ENABLE_BIT         BIT(0)
  26 #define SOC_DTS_AUX1_ENABLE_BIT         BIT(1)
  27 #define SOC_DTS_CPU_MODULE0_ENABLE_BIT  BIT(16)
  28 #define SOC_DTS_CPU_MODULE1_ENABLE_BIT  BIT(17)
  29 #define SOC_DTS_TE_SCI_ENABLE           BIT(9)
  30 #define SOC_DTS_TE_SMI_ENABLE           BIT(10)
  31 #define SOC_DTS_TE_MSI_ENABLE           BIT(11)
  32 #define SOC_DTS_TE_APICA_ENABLE         BIT(14)
  33 #define SOC_DTS_PTMC_APIC_DEASSERT_BIT  BIT(4)
  34 
  35 /* DTS encoding for TJ MAX temperature */
  36 #define SOC_DTS_TJMAX_ENCODING          0x7F
  37 
  38 /* Only 2 out of 4 is allowed for OSPM */
  39 #define SOC_MAX_DTS_TRIPS               2
  40 
  41 /* Mask for two trips in status bits */
  42 #define SOC_DTS_TRIP_MASK               0x03
  43 
  44 /* DTS0 and DTS 1 */
  45 #define SOC_MAX_DTS_SENSORS             2
  46 
  47 static int get_tj_max(u32 *tj_max)
  48 {
  49         u32 eax, edx;
  50         u32 val;
  51         int err;
  52 
  53         err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
  54         if (err)
  55                 goto err_ret;
  56         else {
  57                 val = (eax >> 16) & 0xff;
  58                 if (val)
  59                         *tj_max = val * 1000;
  60                 else {
  61                         err = -EINVAL;
  62                         goto err_ret;
  63                 }
  64         }
  65 
  66         return 0;
  67 err_ret:
  68         *tj_max = 0;
  69 
  70         return err;
  71 }
  72 
  73 static int sys_get_trip_temp(struct thermal_zone_device *tzd, int trip,
  74                              int *temp)
  75 {
  76         int status;
  77         u32 out;
  78         struct intel_soc_dts_sensor_entry *dts;
  79         struct intel_soc_dts_sensors *sensors;
  80 
  81         dts = tzd->devdata;
  82         sensors = dts->sensors;
  83         mutex_lock(&sensors->dts_update_lock);
  84         status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
  85                                SOC_DTS_OFFSET_PTPS, &out);
  86         mutex_unlock(&sensors->dts_update_lock);
  87         if (status)
  88                 return status;
  89 
  90         out = (out >> (trip * 8)) & SOC_DTS_TJMAX_ENCODING;
  91         if (!out)
  92                 *temp = 0;
  93         else
  94                 *temp = sensors->tj_max - out * 1000;
  95 
  96         return 0;
  97 }
  98 
  99 static int update_trip_temp(struct intel_soc_dts_sensor_entry *dts,
 100                             int thres_index, int temp,
 101                             enum thermal_trip_type trip_type)
 102 {
 103         int status;
 104         u32 temp_out;
 105         u32 out;
 106         u32 store_ptps;
 107         u32 store_ptmc;
 108         u32 store_te_out;
 109         u32 te_out;
 110         u32 int_enable_bit = SOC_DTS_TE_APICA_ENABLE;
 111         struct intel_soc_dts_sensors *sensors = dts->sensors;
 112 
 113         if (sensors->intr_type == INTEL_SOC_DTS_INTERRUPT_MSI)
 114                 int_enable_bit |= SOC_DTS_TE_MSI_ENABLE;
 115 
 116         temp_out = (sensors->tj_max - temp) / 1000;
 117 
 118         status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
 119                                SOC_DTS_OFFSET_PTPS, &store_ptps);
 120         if (status)
 121                 return status;
 122 
 123         out = (store_ptps & ~(0xFF << (thres_index * 8)));
 124         out |= (temp_out & 0xFF) << (thres_index * 8);
 125         status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
 126                                 SOC_DTS_OFFSET_PTPS, out);
 127         if (status)
 128                 return status;
 129 
 130         pr_debug("update_trip_temp PTPS = %x\n", out);
 131         status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
 132                                SOC_DTS_OFFSET_PTMC, &out);
 133         if (status)
 134                 goto err_restore_ptps;
 135 
 136         store_ptmc = out;
 137 
 138         status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
 139                                SOC_DTS_TE_AUX0 + thres_index,
 140                                &te_out);
 141         if (status)
 142                 goto err_restore_ptmc;
 143 
 144         store_te_out = te_out;
 145         /* Enable for CPU module 0 and module 1 */
 146         out |= (SOC_DTS_CPU_MODULE0_ENABLE_BIT |
 147                                         SOC_DTS_CPU_MODULE1_ENABLE_BIT);
 148         if (temp) {
 149                 if (thres_index)
 150                         out |= SOC_DTS_AUX1_ENABLE_BIT;
 151                 else
 152                         out |= SOC_DTS_AUX0_ENABLE_BIT;
 153                 te_out |= int_enable_bit;
 154         } else {
 155                 if (thres_index)
 156                         out &= ~SOC_DTS_AUX1_ENABLE_BIT;
 157                 else
 158                         out &= ~SOC_DTS_AUX0_ENABLE_BIT;
 159                 te_out &= ~int_enable_bit;
 160         }
 161         status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
 162                                 SOC_DTS_OFFSET_PTMC, out);
 163         if (status)
 164                 goto err_restore_te_out;
 165 
 166         status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
 167                                 SOC_DTS_TE_AUX0 + thres_index,
 168                                 te_out);
 169         if (status)
 170                 goto err_restore_te_out;
 171 
 172         dts->trip_types[thres_index] = trip_type;
 173 
 174         return 0;
 175 err_restore_te_out:
 176         iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
 177                        SOC_DTS_OFFSET_PTMC, store_te_out);
 178 err_restore_ptmc:
 179         iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
 180                        SOC_DTS_OFFSET_PTMC, store_ptmc);
 181 err_restore_ptps:
 182         iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
 183                        SOC_DTS_OFFSET_PTPS, store_ptps);
 184         /* Nothing we can do if restore fails */
 185 
 186         return status;
 187 }
 188 
 189 static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
 190                              int temp)
 191 {
 192         struct intel_soc_dts_sensor_entry *dts = tzd->devdata;
 193         struct intel_soc_dts_sensors *sensors = dts->sensors;
 194         int status;
 195 
 196         if (temp > sensors->tj_max)
 197                 return -EINVAL;
 198 
 199         mutex_lock(&sensors->dts_update_lock);
 200         status = update_trip_temp(tzd->devdata, trip, temp,
 201                                   dts->trip_types[trip]);
 202         mutex_unlock(&sensors->dts_update_lock);
 203 
 204         return status;
 205 }
 206 
 207 static int sys_get_trip_type(struct thermal_zone_device *tzd,
 208                              int trip, enum thermal_trip_type *type)
 209 {
 210         struct intel_soc_dts_sensor_entry *dts;
 211 
 212         dts = tzd->devdata;
 213 
 214         *type = dts->trip_types[trip];
 215 
 216         return 0;
 217 }
 218 
 219 static int sys_get_curr_temp(struct thermal_zone_device *tzd,
 220                              int *temp)
 221 {
 222         int status;
 223         u32 out;
 224         struct intel_soc_dts_sensor_entry *dts;
 225         struct intel_soc_dts_sensors *sensors;
 226 
 227         dts = tzd->devdata;
 228         sensors = dts->sensors;
 229         status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
 230                                SOC_DTS_OFFSET_TEMP, &out);
 231         if (status)
 232                 return status;
 233 
 234         out = (out & dts->temp_mask) >> dts->temp_shift;
 235         out -= SOC_DTS_TJMAX_ENCODING;
 236         *temp = sensors->tj_max - out * 1000;
 237 
 238         return 0;
 239 }
 240 
 241 static struct thermal_zone_device_ops tzone_ops = {
 242         .get_temp = sys_get_curr_temp,
 243         .get_trip_temp = sys_get_trip_temp,
 244         .get_trip_type = sys_get_trip_type,
 245         .set_trip_temp = sys_set_trip_temp,
 246 };
 247 
 248 static int soc_dts_enable(int id)
 249 {
 250         u32 out;
 251         int ret;
 252 
 253         ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
 254                             SOC_DTS_OFFSET_ENABLE, &out);
 255         if (ret)
 256                 return ret;
 257 
 258         if (!(out & BIT(id))) {
 259                 out |= BIT(id);
 260                 ret = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
 261                                      SOC_DTS_OFFSET_ENABLE, out);
 262                 if (ret)
 263                         return ret;
 264         }
 265 
 266         return ret;
 267 }
 268 
 269 static void remove_dts_thermal_zone(struct intel_soc_dts_sensor_entry *dts)
 270 {
 271         if (dts) {
 272                 iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
 273                                SOC_DTS_OFFSET_ENABLE, dts->store_status);
 274                 thermal_zone_device_unregister(dts->tzone);
 275         }
 276 }
 277 
 278 static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts,
 279                                 bool notification_support, int trip_cnt,
 280                                 int read_only_trip_cnt)
 281 {
 282         char name[10];
 283         int trip_count = 0;
 284         int trip_mask = 0;
 285         u32 store_ptps;
 286         int ret;
 287         int i;
 288 
 289         /* Store status to restor on exit */
 290         ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
 291                             SOC_DTS_OFFSET_ENABLE, &dts->store_status);
 292         if (ret)
 293                 goto err_ret;
 294 
 295         dts->id = id;
 296         dts->temp_mask = 0x00FF << (id * 8);
 297         dts->temp_shift = id * 8;
 298         if (notification_support) {
 299                 trip_count = min(SOC_MAX_DTS_TRIPS, trip_cnt);
 300                 trip_mask = BIT(trip_count - read_only_trip_cnt) - 1;
 301         }
 302 
 303         /* Check if the writable trip we provide is not used by BIOS */
 304         ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
 305                             SOC_DTS_OFFSET_PTPS, &store_ptps);
 306         if (ret)
 307                 trip_mask = 0;
 308         else {
 309                 for (i = 0; i < trip_count; ++i) {
 310                         if (trip_mask & BIT(i))
 311                                 if (store_ptps & (0xff << (i * 8)))
 312                                         trip_mask &= ~BIT(i);
 313                 }
 314         }
 315         dts->trip_mask = trip_mask;
 316         dts->trip_count = trip_count;
 317         snprintf(name, sizeof(name), "soc_dts%d", id);
 318         dts->tzone = thermal_zone_device_register(name,
 319                                                   trip_count,
 320                                                   trip_mask,
 321                                                   dts, &tzone_ops,
 322                                                   NULL, 0, 0);
 323         if (IS_ERR(dts->tzone)) {
 324                 ret = PTR_ERR(dts->tzone);
 325                 goto err_ret;
 326         }
 327 
 328         ret = soc_dts_enable(id);
 329         if (ret)
 330                 goto err_enable;
 331 
 332         return 0;
 333 err_enable:
 334         thermal_zone_device_unregister(dts->tzone);
 335 err_ret:
 336         return ret;
 337 }
 338 
 339 int intel_soc_dts_iosf_add_read_only_critical_trip(
 340         struct intel_soc_dts_sensors *sensors, int critical_offset)
 341 {
 342         int i, j;
 343 
 344         for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
 345                 for (j = 0; j < sensors->soc_dts[i].trip_count; ++j) {
 346                         if (!(sensors->soc_dts[i].trip_mask & BIT(j))) {
 347                                 return update_trip_temp(&sensors->soc_dts[i], j,
 348                                         sensors->tj_max - critical_offset,
 349                                         THERMAL_TRIP_CRITICAL);
 350                         }
 351                 }
 352         }
 353 
 354         return -EINVAL;
 355 }
 356 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_add_read_only_critical_trip);
 357 
 358 void intel_soc_dts_iosf_interrupt_handler(struct intel_soc_dts_sensors *sensors)
 359 {
 360         u32 sticky_out;
 361         int status;
 362         u32 ptmc_out;
 363         unsigned long flags;
 364 
 365         spin_lock_irqsave(&sensors->intr_notify_lock, flags);
 366 
 367         status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
 368                                SOC_DTS_OFFSET_PTMC, &ptmc_out);
 369         ptmc_out |= SOC_DTS_PTMC_APIC_DEASSERT_BIT;
 370         status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
 371                                 SOC_DTS_OFFSET_PTMC, ptmc_out);
 372 
 373         status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
 374                                SOC_DTS_OFFSET_PTTSS, &sticky_out);
 375         pr_debug("status %d PTTSS %x\n", status, sticky_out);
 376         if (sticky_out & SOC_DTS_TRIP_MASK) {
 377                 int i;
 378                 /* reset sticky bit */
 379                 status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
 380                                         SOC_DTS_OFFSET_PTTSS, sticky_out);
 381                 spin_unlock_irqrestore(&sensors->intr_notify_lock, flags);
 382 
 383                 for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
 384                         pr_debug("TZD update for zone %d\n", i);
 385                         thermal_zone_device_update(sensors->soc_dts[i].tzone,
 386                                                    THERMAL_EVENT_UNSPECIFIED);
 387                 }
 388         } else
 389                 spin_unlock_irqrestore(&sensors->intr_notify_lock, flags);
 390 }
 391 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_interrupt_handler);
 392 
 393 struct intel_soc_dts_sensors *intel_soc_dts_iosf_init(
 394         enum intel_soc_dts_interrupt_type intr_type, int trip_count,
 395         int read_only_trip_count)
 396 {
 397         struct intel_soc_dts_sensors *sensors;
 398         bool notification;
 399         u32 tj_max;
 400         int ret;
 401         int i;
 402 
 403         if (!iosf_mbi_available())
 404                 return ERR_PTR(-ENODEV);
 405 
 406         if (!trip_count || read_only_trip_count > trip_count)
 407                 return ERR_PTR(-EINVAL);
 408 
 409         if (get_tj_max(&tj_max))
 410                 return ERR_PTR(-EINVAL);
 411 
 412         sensors = kzalloc(sizeof(*sensors), GFP_KERNEL);
 413         if (!sensors)
 414                 return ERR_PTR(-ENOMEM);
 415 
 416         spin_lock_init(&sensors->intr_notify_lock);
 417         mutex_init(&sensors->dts_update_lock);
 418         sensors->intr_type = intr_type;
 419         sensors->tj_max = tj_max;
 420         if (intr_type == INTEL_SOC_DTS_INTERRUPT_NONE)
 421                 notification = false;
 422         else
 423                 notification = true;
 424         for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
 425                 sensors->soc_dts[i].sensors = sensors;
 426                 ret = add_dts_thermal_zone(i, &sensors->soc_dts[i],
 427                                            notification, trip_count,
 428                                            read_only_trip_count);
 429                 if (ret)
 430                         goto err_free;
 431         }
 432 
 433         for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
 434                 ret = update_trip_temp(&sensors->soc_dts[i], 0, 0,
 435                                        THERMAL_TRIP_PASSIVE);
 436                 if (ret)
 437                         goto err_remove_zone;
 438 
 439                 ret = update_trip_temp(&sensors->soc_dts[i], 1, 0,
 440                                        THERMAL_TRIP_PASSIVE);
 441                 if (ret)
 442                         goto err_remove_zone;
 443         }
 444 
 445         return sensors;
 446 err_remove_zone:
 447         for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i)
 448                 remove_dts_thermal_zone(&sensors->soc_dts[i]);
 449 
 450 err_free:
 451         kfree(sensors);
 452         return ERR_PTR(ret);
 453 }
 454 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_init);
 455 
 456 void intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors *sensors)
 457 {
 458         int i;
 459 
 460         for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
 461                 update_trip_temp(&sensors->soc_dts[i], 0, 0, 0);
 462                 update_trip_temp(&sensors->soc_dts[i], 1, 0, 0);
 463                 remove_dts_thermal_zone(&sensors->soc_dts[i]);
 464         }
 465         kfree(sensors);
 466 }
 467 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_exit);
 468 
 469 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */