Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Processor thermal device for newer processors
0004  * Copyright (c) 2020, Intel Corporation.
0005  */
0006 
0007 #include <linux/acpi.h>
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/pci.h>
0011 #include <linux/thermal.h>
0012 
0013 #include "int340x_thermal_zone.h"
0014 #include "processor_thermal_device.h"
0015 
0016 #define DRV_NAME "proc_thermal_pci"
0017 
0018 struct proc_thermal_pci {
0019     struct pci_dev *pdev;
0020     struct proc_thermal_device *proc_priv;
0021     struct thermal_zone_device *tzone;
0022     struct delayed_work work;
0023     int stored_thres;
0024     int no_legacy;
0025 };
0026 
0027 enum proc_thermal_mmio_type {
0028     PROC_THERMAL_MMIO_TJMAX,
0029     PROC_THERMAL_MMIO_PP0_TEMP,
0030     PROC_THERMAL_MMIO_PP1_TEMP,
0031     PROC_THERMAL_MMIO_PKG_TEMP,
0032     PROC_THERMAL_MMIO_THRES_0,
0033     PROC_THERMAL_MMIO_THRES_1,
0034     PROC_THERMAL_MMIO_INT_ENABLE_0,
0035     PROC_THERMAL_MMIO_INT_ENABLE_1,
0036     PROC_THERMAL_MMIO_INT_STATUS_0,
0037     PROC_THERMAL_MMIO_INT_STATUS_1,
0038     PROC_THERMAL_MMIO_MAX
0039 };
0040 
0041 struct proc_thermal_mmio_info {
0042     enum proc_thermal_mmio_type mmio_type;
0043     u64 mmio_addr;
0044     u64 shift;
0045     u64 mask;
0046 };
0047 
0048 static struct proc_thermal_mmio_info proc_thermal_mmio_info[] = {
0049     { PROC_THERMAL_MMIO_TJMAX, 0x599c, 16, 0xff },
0050     { PROC_THERMAL_MMIO_PP0_TEMP, 0x597c, 0, 0xff },
0051     { PROC_THERMAL_MMIO_PP1_TEMP, 0x5980, 0, 0xff },
0052     { PROC_THERMAL_MMIO_PKG_TEMP, 0x5978, 0, 0xff },
0053     { PROC_THERMAL_MMIO_THRES_0, 0x5820, 8, 0x7F },
0054     { PROC_THERMAL_MMIO_THRES_1, 0x5820, 16, 0x7F },
0055     { PROC_THERMAL_MMIO_INT_ENABLE_0, 0x5820, 15, 0x01 },
0056     { PROC_THERMAL_MMIO_INT_ENABLE_1, 0x5820, 23, 0x01 },
0057     { PROC_THERMAL_MMIO_INT_STATUS_0, 0x7200, 6, 0x01 },
0058     { PROC_THERMAL_MMIO_INT_STATUS_1, 0x7200, 8, 0x01 },
0059 };
0060 
0061 #define B0D4_THERMAL_NOTIFY_DELAY   1000
0062 static int notify_delay_ms = B0D4_THERMAL_NOTIFY_DELAY;
0063 
0064 static void proc_thermal_mmio_read(struct proc_thermal_pci *pci_info,
0065                     enum proc_thermal_mmio_type type,
0066                     u32 *value)
0067 {
0068     *value = ioread32(((u8 __iomem *)pci_info->proc_priv->mmio_base +
0069                 proc_thermal_mmio_info[type].mmio_addr));
0070     *value >>= proc_thermal_mmio_info[type].shift;
0071     *value &= proc_thermal_mmio_info[type].mask;
0072 }
0073 
0074 static void proc_thermal_mmio_write(struct proc_thermal_pci *pci_info,
0075                      enum proc_thermal_mmio_type type,
0076                      u32 value)
0077 {
0078     u32 current_val;
0079     u32 mask;
0080 
0081     current_val = ioread32(((u8 __iomem *)pci_info->proc_priv->mmio_base +
0082                 proc_thermal_mmio_info[type].mmio_addr));
0083     mask = proc_thermal_mmio_info[type].mask << proc_thermal_mmio_info[type].shift;
0084     current_val &= ~mask;
0085 
0086     value &= proc_thermal_mmio_info[type].mask;
0087     value <<= proc_thermal_mmio_info[type].shift;
0088 
0089     current_val |= value;
0090     iowrite32(current_val, ((u8 __iomem *)pci_info->proc_priv->mmio_base +
0091                 proc_thermal_mmio_info[type].mmio_addr));
0092 }
0093 
0094 /*
0095  * To avoid sending two many messages to user space, we have 1 second delay.
0096  * On interrupt we are disabling interrupt and enabling after 1 second.
0097  * This workload function is delayed by 1 second.
0098  */
0099 static void proc_thermal_threshold_work_fn(struct work_struct *work)
0100 {
0101     struct delayed_work *delayed_work = to_delayed_work(work);
0102     struct proc_thermal_pci *pci_info = container_of(delayed_work,
0103                         struct proc_thermal_pci, work);
0104     struct thermal_zone_device *tzone = pci_info->tzone;
0105 
0106     if (tzone)
0107         thermal_zone_device_update(tzone, THERMAL_TRIP_VIOLATED);
0108 
0109     /* Enable interrupt flag */
0110     proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1);
0111 }
0112 
0113 static void pkg_thermal_schedule_work(struct delayed_work *work)
0114 {
0115     unsigned long ms = msecs_to_jiffies(notify_delay_ms);
0116 
0117     schedule_delayed_work(work, ms);
0118 }
0119 
0120 static irqreturn_t proc_thermal_irq_handler(int irq, void *devid)
0121 {
0122     struct proc_thermal_pci *pci_info = devid;
0123     u32 status;
0124 
0125     proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_INT_STATUS_0, &status);
0126 
0127     /* Disable enable interrupt flag */
0128     proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0);
0129     pci_write_config_byte(pci_info->pdev, 0xdc, 0x01);
0130 
0131     pkg_thermal_schedule_work(&pci_info->work);
0132 
0133     return IRQ_HANDLED;
0134 }
0135 
0136 static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
0137 {
0138     struct proc_thermal_pci *pci_info = tzd->devdata;
0139     u32 _temp;
0140 
0141     proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_PKG_TEMP, &_temp);
0142     *temp = (unsigned long)_temp * 1000;
0143 
0144     return 0;
0145 }
0146 
0147 static int sys_get_trip_temp(struct thermal_zone_device *tzd,
0148                  int trip, int *temp)
0149 {
0150     struct proc_thermal_pci *pci_info = tzd->devdata;
0151     u32 _temp;
0152 
0153     proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_THRES_0, &_temp);
0154     if (!_temp) {
0155         *temp = THERMAL_TEMP_INVALID;
0156     } else {
0157         int tjmax;
0158 
0159         proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax);
0160         _temp = tjmax - _temp;
0161         *temp = (unsigned long)_temp * 1000;
0162     }
0163 
0164     return 0;
0165 }
0166 
0167 static int sys_get_trip_type(struct thermal_zone_device *tzd, int trip,
0168                   enum thermal_trip_type *type)
0169 {
0170     *type = THERMAL_TRIP_PASSIVE;
0171 
0172     return 0;
0173 }
0174 
0175 static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
0176 {
0177     struct proc_thermal_pci *pci_info = tzd->devdata;
0178     int tjmax, _temp;
0179 
0180     if (temp <= 0) {
0181         cancel_delayed_work_sync(&pci_info->work);
0182         proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0);
0183         proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 0);
0184         thermal_zone_device_disable(tzd);
0185         pci_info->stored_thres = 0;
0186         return 0;
0187     }
0188 
0189     proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax);
0190     _temp = tjmax - (temp / 1000);
0191     if (_temp < 0)
0192         return -EINVAL;
0193 
0194     proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, _temp);
0195     proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1);
0196 
0197     thermal_zone_device_enable(tzd);
0198     pci_info->stored_thres = temp;
0199 
0200     return 0;
0201 }
0202 
0203 static struct thermal_zone_device_ops tzone_ops = {
0204     .get_temp = sys_get_curr_temp,
0205     .get_trip_temp = sys_get_trip_temp,
0206     .get_trip_type = sys_get_trip_type,
0207     .set_trip_temp  = sys_set_trip_temp,
0208 };
0209 
0210 static struct thermal_zone_params tzone_params = {
0211     .governor_name = "user_space",
0212     .no_hwmon = true,
0213 };
0214 
0215 static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
0216 {
0217     struct proc_thermal_device *proc_priv;
0218     struct proc_thermal_pci *pci_info;
0219     int irq_flag = 0, irq, ret;
0220 
0221     proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL);
0222     if (!proc_priv)
0223         return -ENOMEM;
0224 
0225     pci_info = devm_kzalloc(&pdev->dev, sizeof(*pci_info), GFP_KERNEL);
0226     if (!pci_info)
0227         return -ENOMEM;
0228 
0229     pci_info->pdev = pdev;
0230     ret = pcim_enable_device(pdev);
0231     if (ret < 0) {
0232         dev_err(&pdev->dev, "error: could not enable device\n");
0233         return ret;
0234     }
0235 
0236     pci_set_master(pdev);
0237 
0238     INIT_DELAYED_WORK(&pci_info->work, proc_thermal_threshold_work_fn);
0239 
0240     ret = proc_thermal_add(&pdev->dev, proc_priv);
0241     if (ret) {
0242         dev_err(&pdev->dev, "error: proc_thermal_add, will continue\n");
0243         pci_info->no_legacy = 1;
0244     }
0245 
0246     proc_priv->priv_data = pci_info;
0247     pci_info->proc_priv = proc_priv;
0248     pci_set_drvdata(pdev, proc_priv);
0249 
0250     ret = proc_thermal_mmio_add(pdev, proc_priv, id->driver_data);
0251     if (ret)
0252         goto err_ret_thermal;
0253 
0254     pci_info->tzone = thermal_zone_device_register("TCPU_PCI", 1, 1, pci_info,
0255                             &tzone_ops,
0256                             &tzone_params, 0, 0);
0257     if (IS_ERR(pci_info->tzone)) {
0258         ret = PTR_ERR(pci_info->tzone);
0259         goto err_ret_mmio;
0260     }
0261 
0262     /* request and enable interrupt */
0263     ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
0264     if (ret < 0) {
0265         dev_err(&pdev->dev, "Failed to allocate vectors!\n");
0266         goto err_ret_tzone;
0267     }
0268     if (!pdev->msi_enabled && !pdev->msix_enabled)
0269         irq_flag = IRQF_SHARED;
0270 
0271     irq =  pci_irq_vector(pdev, 0);
0272     ret = devm_request_threaded_irq(&pdev->dev, irq,
0273                     proc_thermal_irq_handler, NULL,
0274                     irq_flag, KBUILD_MODNAME, pci_info);
0275     if (ret) {
0276         dev_err(&pdev->dev, "Request IRQ %d failed\n", pdev->irq);
0277         goto err_free_vectors;
0278     }
0279 
0280     return 0;
0281 
0282 err_free_vectors:
0283     pci_free_irq_vectors(pdev);
0284 err_ret_tzone:
0285     thermal_zone_device_unregister(pci_info->tzone);
0286 err_ret_mmio:
0287     proc_thermal_mmio_remove(pdev, proc_priv);
0288 err_ret_thermal:
0289     if (!pci_info->no_legacy)
0290         proc_thermal_remove(proc_priv);
0291     pci_disable_device(pdev);
0292 
0293     return ret;
0294 }
0295 
0296 static void proc_thermal_pci_remove(struct pci_dev *pdev)
0297 {
0298     struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev);
0299     struct proc_thermal_pci *pci_info = proc_priv->priv_data;
0300 
0301     cancel_delayed_work_sync(&pci_info->work);
0302 
0303     proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 0);
0304     proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0);
0305 
0306     devm_free_irq(&pdev->dev, pdev->irq, pci_info);
0307     pci_free_irq_vectors(pdev);
0308 
0309     thermal_zone_device_unregister(pci_info->tzone);
0310     proc_thermal_mmio_remove(pdev, pci_info->proc_priv);
0311     if (!pci_info->no_legacy)
0312         proc_thermal_remove(proc_priv);
0313     pci_disable_device(pdev);
0314 }
0315 
0316 #ifdef CONFIG_PM_SLEEP
0317 static int proc_thermal_pci_suspend(struct device *dev)
0318 {
0319     struct pci_dev *pdev = to_pci_dev(dev);
0320     struct proc_thermal_device *proc_priv;
0321     struct proc_thermal_pci *pci_info;
0322 
0323     proc_priv = pci_get_drvdata(pdev);
0324     pci_info = proc_priv->priv_data;
0325 
0326     if (!pci_info->no_legacy)
0327         return proc_thermal_suspend(dev);
0328 
0329     return 0;
0330 }
0331 static int proc_thermal_pci_resume(struct device *dev)
0332 {
0333     struct pci_dev *pdev = to_pci_dev(dev);
0334     struct proc_thermal_device *proc_priv;
0335     struct proc_thermal_pci *pci_info;
0336 
0337     proc_priv = pci_get_drvdata(pdev);
0338     pci_info = proc_priv->priv_data;
0339 
0340     if (pci_info->stored_thres) {
0341         proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0,
0342                      pci_info->stored_thres / 1000);
0343         proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1);
0344     }
0345 
0346     if (!pci_info->no_legacy)
0347         return proc_thermal_resume(dev);
0348 
0349     return 0;
0350 }
0351 #else
0352 #define proc_thermal_pci_suspend NULL
0353 #define proc_thermal_pci_resume NULL
0354 #endif
0355 
0356 static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend,
0357              proc_thermal_pci_resume);
0358 
0359 static const struct pci_device_id proc_thermal_pci_ids[] = {
0360     { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) },
0361     { PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) },
0362     { PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) },
0363     { },
0364 };
0365 
0366 MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids);
0367 
0368 static struct pci_driver proc_thermal_pci_driver = {
0369     .name       = DRV_NAME,
0370     .probe      = proc_thermal_pci_probe,
0371     .remove = proc_thermal_pci_remove,
0372     .id_table   = proc_thermal_pci_ids,
0373     .driver.pm  = &proc_thermal_pci_pm,
0374 };
0375 
0376 static int __init proc_thermal_init(void)
0377 {
0378     return pci_register_driver(&proc_thermal_pci_driver);
0379 }
0380 
0381 static void __exit proc_thermal_exit(void)
0382 {
0383     pci_unregister_driver(&proc_thermal_pci_driver);
0384 }
0385 
0386 module_init(proc_thermal_init);
0387 module_exit(proc_thermal_exit);
0388 
0389 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
0390 MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver");
0391 MODULE_LICENSE("GPL v2");