Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * intel_soc_dts_iosf.c
0004  * Copyright (c) 2015, Intel Corporation.
0005  */
0006 
0007 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0008 
0009 #include <linux/bitops.h>
0010 #include <linux/module.h>
0011 #include <linux/slab.h>
0012 #include <linux/interrupt.h>
0013 #include <asm/iosf_mbi.h>
0014 #include "intel_soc_dts_iosf.h"
0015 
0016 #define SOC_DTS_OFFSET_ENABLE       0xB0
0017 #define SOC_DTS_OFFSET_TEMP     0xB1
0018 
0019 #define SOC_DTS_OFFSET_PTPS     0xB2
0020 #define SOC_DTS_OFFSET_PTTS     0xB3
0021 #define SOC_DTS_OFFSET_PTTSS        0xB4
0022 #define SOC_DTS_OFFSET_PTMC     0x80
0023 #define SOC_DTS_TE_AUX0         0xB5
0024 #define SOC_DTS_TE_AUX1         0xB6
0025 
0026 #define SOC_DTS_AUX0_ENABLE_BIT     BIT(0)
0027 #define SOC_DTS_AUX1_ENABLE_BIT     BIT(1)
0028 #define SOC_DTS_CPU_MODULE0_ENABLE_BIT  BIT(16)
0029 #define SOC_DTS_CPU_MODULE1_ENABLE_BIT  BIT(17)
0030 #define SOC_DTS_TE_SCI_ENABLE       BIT(9)
0031 #define SOC_DTS_TE_SMI_ENABLE       BIT(10)
0032 #define SOC_DTS_TE_MSI_ENABLE       BIT(11)
0033 #define SOC_DTS_TE_APICA_ENABLE     BIT(14)
0034 #define SOC_DTS_PTMC_APIC_DEASSERT_BIT  BIT(4)
0035 
0036 /* DTS encoding for TJ MAX temperature */
0037 #define SOC_DTS_TJMAX_ENCODING      0x7F
0038 
0039 /* Only 2 out of 4 is allowed for OSPM */
0040 #define SOC_MAX_DTS_TRIPS       2
0041 
0042 /* Mask for two trips in status bits */
0043 #define SOC_DTS_TRIP_MASK       0x03
0044 
0045 /* DTS0 and DTS 1 */
0046 #define SOC_MAX_DTS_SENSORS     2
0047 
0048 static int get_tj_max(u32 *tj_max)
0049 {
0050     u32 eax, edx;
0051     u32 val;
0052     int err;
0053 
0054     err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
0055     if (err)
0056         goto err_ret;
0057     else {
0058         val = (eax >> 16) & 0xff;
0059         if (val)
0060             *tj_max = val * 1000;
0061         else {
0062             err = -EINVAL;
0063             goto err_ret;
0064         }
0065     }
0066 
0067     return 0;
0068 err_ret:
0069     *tj_max = 0;
0070 
0071     return err;
0072 }
0073 
0074 static int sys_get_trip_temp(struct thermal_zone_device *tzd, int trip,
0075                  int *temp)
0076 {
0077     int status;
0078     u32 out;
0079     struct intel_soc_dts_sensor_entry *dts;
0080     struct intel_soc_dts_sensors *sensors;
0081 
0082     dts = tzd->devdata;
0083     sensors = dts->sensors;
0084     mutex_lock(&sensors->dts_update_lock);
0085     status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
0086                    SOC_DTS_OFFSET_PTPS, &out);
0087     mutex_unlock(&sensors->dts_update_lock);
0088     if (status)
0089         return status;
0090 
0091     out = (out >> (trip * 8)) & SOC_DTS_TJMAX_ENCODING;
0092     if (!out)
0093         *temp = 0;
0094     else
0095         *temp = sensors->tj_max - out * 1000;
0096 
0097     return 0;
0098 }
0099 
0100 static int update_trip_temp(struct intel_soc_dts_sensor_entry *dts,
0101                 int thres_index, int temp,
0102                 enum thermal_trip_type trip_type)
0103 {
0104     int status;
0105     u32 temp_out;
0106     u32 out;
0107     unsigned long update_ptps;
0108     u32 store_ptps;
0109     u32 store_ptmc;
0110     u32 store_te_out;
0111     u32 te_out;
0112     u32 int_enable_bit = SOC_DTS_TE_APICA_ENABLE;
0113     struct intel_soc_dts_sensors *sensors = dts->sensors;
0114 
0115     if (sensors->intr_type == INTEL_SOC_DTS_INTERRUPT_MSI)
0116         int_enable_bit |= SOC_DTS_TE_MSI_ENABLE;
0117 
0118     temp_out = (sensors->tj_max - temp) / 1000;
0119 
0120     status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
0121                    SOC_DTS_OFFSET_PTPS, &store_ptps);
0122     if (status)
0123         return status;
0124 
0125     update_ptps = store_ptps;
0126     bitmap_set_value8(&update_ptps, temp_out & 0xFF, thres_index * 8);
0127     out = update_ptps;
0128 
0129     status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
0130                 SOC_DTS_OFFSET_PTPS, out);
0131     if (status)
0132         return status;
0133 
0134     pr_debug("update_trip_temp PTPS = %x\n", out);
0135     status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
0136                    SOC_DTS_OFFSET_PTMC, &out);
0137     if (status)
0138         goto err_restore_ptps;
0139 
0140     store_ptmc = out;
0141 
0142     status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
0143                    SOC_DTS_TE_AUX0 + thres_index,
0144                    &te_out);
0145     if (status)
0146         goto err_restore_ptmc;
0147 
0148     store_te_out = te_out;
0149     /* Enable for CPU module 0 and module 1 */
0150     out |= (SOC_DTS_CPU_MODULE0_ENABLE_BIT |
0151                     SOC_DTS_CPU_MODULE1_ENABLE_BIT);
0152     if (temp) {
0153         if (thres_index)
0154             out |= SOC_DTS_AUX1_ENABLE_BIT;
0155         else
0156             out |= SOC_DTS_AUX0_ENABLE_BIT;
0157         te_out |= int_enable_bit;
0158     } else {
0159         if (thres_index)
0160             out &= ~SOC_DTS_AUX1_ENABLE_BIT;
0161         else
0162             out &= ~SOC_DTS_AUX0_ENABLE_BIT;
0163         te_out &= ~int_enable_bit;
0164     }
0165     status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
0166                 SOC_DTS_OFFSET_PTMC, out);
0167     if (status)
0168         goto err_restore_te_out;
0169 
0170     status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
0171                 SOC_DTS_TE_AUX0 + thres_index,
0172                 te_out);
0173     if (status)
0174         goto err_restore_te_out;
0175 
0176     dts->trip_types[thres_index] = trip_type;
0177 
0178     return 0;
0179 err_restore_te_out:
0180     iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
0181                SOC_DTS_OFFSET_PTMC, store_te_out);
0182 err_restore_ptmc:
0183     iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
0184                SOC_DTS_OFFSET_PTMC, store_ptmc);
0185 err_restore_ptps:
0186     iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
0187                SOC_DTS_OFFSET_PTPS, store_ptps);
0188     /* Nothing we can do if restore fails */
0189 
0190     return status;
0191 }
0192 
0193 static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
0194                  int temp)
0195 {
0196     struct intel_soc_dts_sensor_entry *dts = tzd->devdata;
0197     struct intel_soc_dts_sensors *sensors = dts->sensors;
0198     int status;
0199 
0200     if (temp > sensors->tj_max)
0201         return -EINVAL;
0202 
0203     mutex_lock(&sensors->dts_update_lock);
0204     status = update_trip_temp(tzd->devdata, trip, temp,
0205                   dts->trip_types[trip]);
0206     mutex_unlock(&sensors->dts_update_lock);
0207 
0208     return status;
0209 }
0210 
0211 static int sys_get_trip_type(struct thermal_zone_device *tzd,
0212                  int trip, enum thermal_trip_type *type)
0213 {
0214     struct intel_soc_dts_sensor_entry *dts;
0215 
0216     dts = tzd->devdata;
0217 
0218     *type = dts->trip_types[trip];
0219 
0220     return 0;
0221 }
0222 
0223 static int sys_get_curr_temp(struct thermal_zone_device *tzd,
0224                  int *temp)
0225 {
0226     int status;
0227     u32 out;
0228     struct intel_soc_dts_sensor_entry *dts;
0229     struct intel_soc_dts_sensors *sensors;
0230     unsigned long raw;
0231 
0232     dts = tzd->devdata;
0233     sensors = dts->sensors;
0234     status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
0235                    SOC_DTS_OFFSET_TEMP, &out);
0236     if (status)
0237         return status;
0238 
0239     raw = out;
0240     out = bitmap_get_value8(&raw, dts->id * 8) - SOC_DTS_TJMAX_ENCODING;
0241     *temp = sensors->tj_max - out * 1000;
0242 
0243     return 0;
0244 }
0245 
0246 static struct thermal_zone_device_ops tzone_ops = {
0247     .get_temp = sys_get_curr_temp,
0248     .get_trip_temp = sys_get_trip_temp,
0249     .get_trip_type = sys_get_trip_type,
0250     .set_trip_temp = sys_set_trip_temp,
0251 };
0252 
0253 static int soc_dts_enable(int id)
0254 {
0255     u32 out;
0256     int ret;
0257 
0258     ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
0259                 SOC_DTS_OFFSET_ENABLE, &out);
0260     if (ret)
0261         return ret;
0262 
0263     if (!(out & BIT(id))) {
0264         out |= BIT(id);
0265         ret = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
0266                      SOC_DTS_OFFSET_ENABLE, out);
0267         if (ret)
0268             return ret;
0269     }
0270 
0271     return ret;
0272 }
0273 
0274 static void remove_dts_thermal_zone(struct intel_soc_dts_sensor_entry *dts)
0275 {
0276     if (dts) {
0277         iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
0278                    SOC_DTS_OFFSET_ENABLE, dts->store_status);
0279         thermal_zone_device_unregister(dts->tzone);
0280     }
0281 }
0282 
0283 static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts,
0284                 bool notification_support, int trip_cnt,
0285                 int read_only_trip_cnt)
0286 {
0287     char name[10];
0288     unsigned long trip;
0289     int trip_count = 0;
0290     int trip_mask = 0;
0291     int writable_trip_cnt = 0;
0292     unsigned long ptps;
0293     u32 store_ptps;
0294     unsigned long i;
0295     int ret;
0296 
0297     /* Store status to restor on exit */
0298     ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
0299                 SOC_DTS_OFFSET_ENABLE, &dts->store_status);
0300     if (ret)
0301         goto err_ret;
0302 
0303     dts->id = id;
0304     if (notification_support) {
0305         trip_count = min(SOC_MAX_DTS_TRIPS, trip_cnt);
0306         writable_trip_cnt = trip_count - read_only_trip_cnt;
0307         trip_mask = GENMASK(writable_trip_cnt - 1, 0);
0308     }
0309 
0310     /* Check if the writable trip we provide is not used by BIOS */
0311     ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
0312                 SOC_DTS_OFFSET_PTPS, &store_ptps);
0313     if (ret)
0314         trip_mask = 0;
0315     else {
0316         ptps = store_ptps;
0317         for_each_set_clump8(i, trip, &ptps, writable_trip_cnt * 8)
0318             trip_mask &= ~BIT(i / 8);
0319     }
0320     dts->trip_mask = trip_mask;
0321     dts->trip_count = trip_count;
0322     snprintf(name, sizeof(name), "soc_dts%d", id);
0323     dts->tzone = thermal_zone_device_register(name,
0324                           trip_count,
0325                           trip_mask,
0326                           dts, &tzone_ops,
0327                           NULL, 0, 0);
0328     if (IS_ERR(dts->tzone)) {
0329         ret = PTR_ERR(dts->tzone);
0330         goto err_ret;
0331     }
0332     ret = thermal_zone_device_enable(dts->tzone);
0333     if (ret)
0334         goto err_enable;
0335 
0336     ret = soc_dts_enable(id);
0337     if (ret)
0338         goto err_enable;
0339 
0340     return 0;
0341 err_enable:
0342     thermal_zone_device_unregister(dts->tzone);
0343 err_ret:
0344     return ret;
0345 }
0346 
0347 int intel_soc_dts_iosf_add_read_only_critical_trip(
0348     struct intel_soc_dts_sensors *sensors, int critical_offset)
0349 {
0350     int i, j;
0351 
0352     for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
0353         struct intel_soc_dts_sensor_entry *entry = &sensors->soc_dts[i];
0354         int temp = sensors->tj_max - critical_offset;
0355         unsigned long count = entry->trip_count;
0356         unsigned long mask = entry->trip_mask;
0357 
0358         j = find_first_zero_bit(&mask, count);
0359         if (j < count)
0360             return update_trip_temp(entry, j, temp, THERMAL_TRIP_CRITICAL);
0361     }
0362 
0363     return -EINVAL;
0364 }
0365 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_add_read_only_critical_trip);
0366 
0367 void intel_soc_dts_iosf_interrupt_handler(struct intel_soc_dts_sensors *sensors)
0368 {
0369     u32 sticky_out;
0370     int status;
0371     u32 ptmc_out;
0372     unsigned long flags;
0373 
0374     spin_lock_irqsave(&sensors->intr_notify_lock, flags);
0375 
0376     status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
0377                    SOC_DTS_OFFSET_PTMC, &ptmc_out);
0378     ptmc_out |= SOC_DTS_PTMC_APIC_DEASSERT_BIT;
0379     status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
0380                 SOC_DTS_OFFSET_PTMC, ptmc_out);
0381 
0382     status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
0383                    SOC_DTS_OFFSET_PTTSS, &sticky_out);
0384     pr_debug("status %d PTTSS %x\n", status, sticky_out);
0385     if (sticky_out & SOC_DTS_TRIP_MASK) {
0386         int i;
0387         /* reset sticky bit */
0388         status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
0389                     SOC_DTS_OFFSET_PTTSS, sticky_out);
0390         spin_unlock_irqrestore(&sensors->intr_notify_lock, flags);
0391 
0392         for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
0393             pr_debug("TZD update for zone %d\n", i);
0394             thermal_zone_device_update(sensors->soc_dts[i].tzone,
0395                            THERMAL_EVENT_UNSPECIFIED);
0396         }
0397     } else
0398         spin_unlock_irqrestore(&sensors->intr_notify_lock, flags);
0399 }
0400 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_interrupt_handler);
0401 
0402 struct intel_soc_dts_sensors *intel_soc_dts_iosf_init(
0403     enum intel_soc_dts_interrupt_type intr_type, int trip_count,
0404     int read_only_trip_count)
0405 {
0406     struct intel_soc_dts_sensors *sensors;
0407     bool notification;
0408     u32 tj_max;
0409     int ret;
0410     int i;
0411 
0412     if (!iosf_mbi_available())
0413         return ERR_PTR(-ENODEV);
0414 
0415     if (!trip_count || read_only_trip_count > trip_count)
0416         return ERR_PTR(-EINVAL);
0417 
0418     if (get_tj_max(&tj_max))
0419         return ERR_PTR(-EINVAL);
0420 
0421     sensors = kzalloc(sizeof(*sensors), GFP_KERNEL);
0422     if (!sensors)
0423         return ERR_PTR(-ENOMEM);
0424 
0425     spin_lock_init(&sensors->intr_notify_lock);
0426     mutex_init(&sensors->dts_update_lock);
0427     sensors->intr_type = intr_type;
0428     sensors->tj_max = tj_max;
0429     if (intr_type == INTEL_SOC_DTS_INTERRUPT_NONE)
0430         notification = false;
0431     else
0432         notification = true;
0433     for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
0434         sensors->soc_dts[i].sensors = sensors;
0435         ret = add_dts_thermal_zone(i, &sensors->soc_dts[i],
0436                        notification, trip_count,
0437                        read_only_trip_count);
0438         if (ret)
0439             goto err_free;
0440     }
0441 
0442     for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
0443         ret = update_trip_temp(&sensors->soc_dts[i], 0, 0,
0444                        THERMAL_TRIP_PASSIVE);
0445         if (ret)
0446             goto err_remove_zone;
0447 
0448         ret = update_trip_temp(&sensors->soc_dts[i], 1, 0,
0449                        THERMAL_TRIP_PASSIVE);
0450         if (ret)
0451             goto err_remove_zone;
0452     }
0453 
0454     return sensors;
0455 err_remove_zone:
0456     for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i)
0457         remove_dts_thermal_zone(&sensors->soc_dts[i]);
0458 
0459 err_free:
0460     kfree(sensors);
0461     return ERR_PTR(ret);
0462 }
0463 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_init);
0464 
0465 void intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors *sensors)
0466 {
0467     int i;
0468 
0469     for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
0470         update_trip_temp(&sensors->soc_dts[i], 0, 0, 0);
0471         update_trip_temp(&sensors->soc_dts[i], 1, 0, 0);
0472         remove_dts_thermal_zone(&sensors->soc_dts[i]);
0473     }
0474     kfree(sensors);
0475 }
0476 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_exit);
0477 
0478 MODULE_LICENSE("GPL v2");