149 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * i5500_temp - Driver for Intel 5500/5520/X58 chipset thermal sensor4 *5 * Copyright (C) 2012, 2014 Jean Delvare <jdelvare@suse.de>6 */7 8#include <linux/bitops.h>9#include <linux/module.h>10#include <linux/init.h>11#include <linux/slab.h>12#include <linux/jiffies.h>13#include <linux/device.h>14#include <linux/pci.h>15#include <linux/hwmon.h>16#include <linux/err.h>17#include <linux/mutex.h>18 19/* Register definitions from datasheet */20#define REG_TSTHRCATA 0xE221#define REG_TSCTRL 0xE822#define REG_TSTHRRPEX 0xEB23#define REG_TSTHRLO 0xEC24#define REG_TSTHRHI 0xEE25#define REG_CTHINT 0xF026#define REG_TSFSC 0xF327#define REG_CTSTS 0xF428#define REG_TSTHRRQPI 0xF529#define REG_CTCTRL 0xF730#define REG_TSTIMER 0xF831 32static umode_t i5500_is_visible(const void *drvdata, enum hwmon_sensor_types type, u32 attr,33 int channel)34{35 return 0444;36}37 38static int i5500_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,39 long *val)40{41 struct pci_dev *pdev = to_pci_dev(dev->parent);42 u16 tsthr;43 s8 tsfsc;44 u8 ctsts;45 46 switch (type) {47 case hwmon_temp:48 switch (attr) {49 /* Sensor resolution : 0.5 degree C */50 case hwmon_temp_input:51 pci_read_config_word(pdev, REG_TSTHRHI, &tsthr);52 pci_read_config_byte(pdev, REG_TSFSC, &tsfsc);53 *val = (tsthr - tsfsc) * 500;54 return 0;55 case hwmon_temp_max:56 pci_read_config_word(pdev, REG_TSTHRHI, &tsthr);57 *val = tsthr * 500;58 return 0;59 case hwmon_temp_max_hyst:60 pci_read_config_word(pdev, REG_TSTHRLO, &tsthr);61 *val = tsthr * 500;62 return 0;63 case hwmon_temp_crit:64 pci_read_config_word(pdev, REG_TSTHRCATA, &tsthr);65 *val = tsthr * 500;66 return 0;67 case hwmon_temp_max_alarm:68 pci_read_config_byte(pdev, REG_CTSTS, &ctsts);69 *val = !!(ctsts & BIT(1));70 return 0;71 case hwmon_temp_crit_alarm:72 pci_read_config_byte(pdev, REG_CTSTS, &ctsts);73 *val = !!(ctsts & BIT(0));74 return 0;75 default:76 break;77 }78 break;79 default:80 break;81 }82 83 return -EOPNOTSUPP;84}85 86static const struct hwmon_ops i5500_ops = {87 .is_visible = i5500_is_visible,88 .read = i5500_read,89};90 91static const struct hwmon_channel_info * const i5500_info[] = {92 HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),93 HWMON_CHANNEL_INFO(temp,94 HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST | HWMON_T_CRIT |95 HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM96 ),97 NULL98};99 100static const struct hwmon_chip_info i5500_chip_info = {101 .ops = &i5500_ops,102 .info = i5500_info,103};104 105static const struct pci_device_id i5500_temp_ids[] = {106 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3438) },107 { 0 },108};109 110MODULE_DEVICE_TABLE(pci, i5500_temp_ids);111 112static int i5500_temp_probe(struct pci_dev *pdev,113 const struct pci_device_id *id)114{115 int err;116 struct device *hwmon_dev;117 u32 tstimer;118 s8 tsfsc;119 120 err = pcim_enable_device(pdev);121 if (err) {122 dev_err(&pdev->dev, "Failed to enable device\n");123 return err;124 }125 126 pci_read_config_byte(pdev, REG_TSFSC, &tsfsc);127 pci_read_config_dword(pdev, REG_TSTIMER, &tstimer);128 if (tsfsc == 0x7F && tstimer == 0x07D30D40) {129 dev_notice(&pdev->dev, "Sensor seems to be disabled\n");130 return -ENODEV;131 }132 133 hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev, "intel5500", NULL,134 &i5500_chip_info, NULL);135 return PTR_ERR_OR_ZERO(hwmon_dev);136}137 138static struct pci_driver i5500_temp_driver = {139 .name = "i5500_temp",140 .id_table = i5500_temp_ids,141 .probe = i5500_temp_probe,142};143 144module_pci_driver(i5500_temp_driver);145 146MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");147MODULE_DESCRIPTION("Intel 5500/5520/X58 chipset thermal sensor driver");148MODULE_LICENSE("GPL");149