brintos

brintos / linux-shallow public Read only

0
0
Text · 3.5 KiB · 7b00b38 Raw
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