Linux Audio

Check our new training course

Loading...
v3.1
  1/*
  2    hwmon.c - part of lm_sensors, Linux kernel modules for hardware monitoring
  3
  4    This file defines the sysfs class "hwmon", for use by sensors drivers.
  5
  6    Copyright (C) 2005 Mark M. Hoffman <mhoffman@lightlink.com>
  7
  8    This program is free software; you can redistribute it and/or modify
  9    it under the terms of the GNU General Public License as published by
 10    the Free Software Foundation; version 2 of the License.
 11*/
 12
 13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 14
 15#include <linux/module.h>
 16#include <linux/device.h>
 17#include <linux/err.h>
 18#include <linux/kdev_t.h>
 19#include <linux/idr.h>
 20#include <linux/hwmon.h>
 21#include <linux/gfp.h>
 22#include <linux/spinlock.h>
 23#include <linux/pci.h>
 24
 25#define HWMON_ID_PREFIX "hwmon"
 26#define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
 27
 28static struct class *hwmon_class;
 29
 30static DEFINE_IDR(hwmon_idr);
 31static DEFINE_SPINLOCK(idr_lock);
 32
 33/**
 34 * hwmon_device_register - register w/ hwmon
 35 * @dev: the device to register
 36 *
 37 * hwmon_device_unregister() must be called when the device is no
 38 * longer needed.
 39 *
 40 * Returns the pointer to the new device.
 41 */
 42struct device *hwmon_device_register(struct device *dev)
 43{
 44	struct device *hwdev;
 45	int id, err;
 46
 47again:
 48	if (unlikely(idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0))
 49		return ERR_PTR(-ENOMEM);
 50
 51	spin_lock(&idr_lock);
 52	err = idr_get_new(&hwmon_idr, NULL, &id);
 53	spin_unlock(&idr_lock);
 54
 55	if (unlikely(err == -EAGAIN))
 56		goto again;
 57	else if (unlikely(err))
 58		return ERR_PTR(err);
 59
 60	id = id & MAX_ID_MASK;
 61	hwdev = device_create(hwmon_class, dev, MKDEV(0, 0), NULL,
 62			      HWMON_ID_FORMAT, id);
 63
 64	if (IS_ERR(hwdev)) {
 65		spin_lock(&idr_lock);
 66		idr_remove(&hwmon_idr, id);
 67		spin_unlock(&idr_lock);
 68	}
 69
 70	return hwdev;
 71}
 
 72
 73/**
 74 * hwmon_device_unregister - removes the previously registered class device
 75 *
 76 * @dev: the class device to destroy
 77 */
 78void hwmon_device_unregister(struct device *dev)
 79{
 80	int id;
 81
 82	if (likely(sscanf(dev_name(dev), HWMON_ID_FORMAT, &id) == 1)) {
 83		device_unregister(dev);
 84		spin_lock(&idr_lock);
 85		idr_remove(&hwmon_idr, id);
 86		spin_unlock(&idr_lock);
 87	} else
 88		dev_dbg(dev->parent,
 89			"hwmon_device_unregister() failed: bad class ID!\n");
 90}
 
 91
 92static void __init hwmon_pci_quirks(void)
 93{
 94#if defined CONFIG_X86 && defined CONFIG_PCI
 95	struct pci_dev *sb;
 96	u16 base;
 97	u8 enable;
 98
 99	/* Open access to 0x295-0x296 on MSI MS-7031 */
100	sb = pci_get_device(PCI_VENDOR_ID_ATI, 0x436c, NULL);
101	if (sb &&
102	    (sb->subsystem_vendor == 0x1462 &&	/* MSI */
103	     sb->subsystem_device == 0x0031)) {	/* MS-7031 */
104
105		pci_read_config_byte(sb, 0x48, &enable);
106		pci_read_config_word(sb, 0x64, &base);
107
108		if (base == 0 && !(enable & BIT(2))) {
109			dev_info(&sb->dev,
110				 "Opening wide generic port at 0x295\n");
111			pci_write_config_word(sb, 0x64, 0x295);
112			pci_write_config_byte(sb, 0x48, enable | BIT(2));
113		}
114	}
115#endif
116}
117
118static int __init hwmon_init(void)
119{
120	hwmon_pci_quirks();
121
122	hwmon_class = class_create(THIS_MODULE, "hwmon");
123	if (IS_ERR(hwmon_class)) {
124		pr_err("couldn't create sysfs class\n");
125		return PTR_ERR(hwmon_class);
126	}
127	return 0;
128}
129
130static void __exit hwmon_exit(void)
131{
132	class_destroy(hwmon_class);
133}
134
135subsys_initcall(hwmon_init);
136module_exit(hwmon_exit);
137
138EXPORT_SYMBOL_GPL(hwmon_device_register);
139EXPORT_SYMBOL_GPL(hwmon_device_unregister);
140
141MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
142MODULE_DESCRIPTION("hardware monitoring sysfs/class support");
143MODULE_LICENSE("GPL");
144
v3.5.6
  1/*
  2 * hwmon.c - part of lm_sensors, Linux kernel modules for hardware monitoring
  3 *
  4 * This file defines the sysfs class "hwmon", for use by sensors drivers.
  5 *
  6 * Copyright (C) 2005 Mark M. Hoffman <mhoffman@lightlink.com>
  7 *
  8 * This program is free software; you can redistribute it and/or modify
  9 * it under the terms of the GNU General Public License as published by
 10 * the Free Software Foundation; version 2 of the License.
 11 */
 12
 13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 14
 15#include <linux/module.h>
 16#include <linux/device.h>
 17#include <linux/err.h>
 18#include <linux/kdev_t.h>
 19#include <linux/idr.h>
 20#include <linux/hwmon.h>
 21#include <linux/gfp.h>
 22#include <linux/spinlock.h>
 23#include <linux/pci.h>
 24
 25#define HWMON_ID_PREFIX "hwmon"
 26#define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
 27
 28static struct class *hwmon_class;
 29
 30static DEFINE_IDA(hwmon_ida);
 
 31
 32/**
 33 * hwmon_device_register - register w/ hwmon
 34 * @dev: the device to register
 35 *
 36 * hwmon_device_unregister() must be called when the device is no
 37 * longer needed.
 38 *
 39 * Returns the pointer to the new device.
 40 */
 41struct device *hwmon_device_register(struct device *dev)
 42{
 43	struct device *hwdev;
 44	int id;
 45
 46	id = ida_simple_get(&hwmon_ida, 0, 0, GFP_KERNEL);
 47	if (id < 0)
 48		return ERR_PTR(id);
 
 
 
 
 
 
 
 
 
 49
 
 50	hwdev = device_create(hwmon_class, dev, MKDEV(0, 0), NULL,
 51			      HWMON_ID_FORMAT, id);
 52
 53	if (IS_ERR(hwdev))
 54		ida_simple_remove(&hwmon_ida, id);
 
 
 
 55
 56	return hwdev;
 57}
 58EXPORT_SYMBOL_GPL(hwmon_device_register);
 59
 60/**
 61 * hwmon_device_unregister - removes the previously registered class device
 62 *
 63 * @dev: the class device to destroy
 64 */
 65void hwmon_device_unregister(struct device *dev)
 66{
 67	int id;
 68
 69	if (likely(sscanf(dev_name(dev), HWMON_ID_FORMAT, &id) == 1)) {
 70		device_unregister(dev);
 71		ida_simple_remove(&hwmon_ida, id);
 
 
 72	} else
 73		dev_dbg(dev->parent,
 74			"hwmon_device_unregister() failed: bad class ID!\n");
 75}
 76EXPORT_SYMBOL_GPL(hwmon_device_unregister);
 77
 78static void __init hwmon_pci_quirks(void)
 79{
 80#if defined CONFIG_X86 && defined CONFIG_PCI
 81	struct pci_dev *sb;
 82	u16 base;
 83	u8 enable;
 84
 85	/* Open access to 0x295-0x296 on MSI MS-7031 */
 86	sb = pci_get_device(PCI_VENDOR_ID_ATI, 0x436c, NULL);
 87	if (sb &&
 88	    (sb->subsystem_vendor == 0x1462 &&	/* MSI */
 89	     sb->subsystem_device == 0x0031)) {	/* MS-7031 */
 90
 91		pci_read_config_byte(sb, 0x48, &enable);
 92		pci_read_config_word(sb, 0x64, &base);
 93
 94		if (base == 0 && !(enable & BIT(2))) {
 95			dev_info(&sb->dev,
 96				 "Opening wide generic port at 0x295\n");
 97			pci_write_config_word(sb, 0x64, 0x295);
 98			pci_write_config_byte(sb, 0x48, enable | BIT(2));
 99		}
100	}
101#endif
102}
103
104static int __init hwmon_init(void)
105{
106	hwmon_pci_quirks();
107
108	hwmon_class = class_create(THIS_MODULE, "hwmon");
109	if (IS_ERR(hwmon_class)) {
110		pr_err("couldn't create sysfs class\n");
111		return PTR_ERR(hwmon_class);
112	}
113	return 0;
114}
115
116static void __exit hwmon_exit(void)
117{
118	class_destroy(hwmon_class);
119}
120
121subsys_initcall(hwmon_init);
122module_exit(hwmon_exit);
 
 
 
123
124MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
125MODULE_DESCRIPTION("hardware monitoring sysfs/class support");
126MODULE_LICENSE("GPL");
127