Blame view

drivers/hwmon/hwmon.c 3.33 KB
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
1
2
3
4
5
6
7
8
9
10
11
  /*
      hwmon.c - part of lm_sensors, Linux kernel modules for hardware monitoring
  
      This file defines the sysfs class "hwmon", for use by sensors drivers.
  
      Copyright (C) 2005 Mark M. Hoffman <mhoffman@lightlink.com>
  
      This program is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
      the Free Software Foundation; version 2 of the License.
  */
c95df1ae6   Joe Perches   hwmon: (core) Use...
12
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
13
14
15
16
17
18
  #include <linux/module.h>
  #include <linux/device.h>
  #include <linux/err.h>
  #include <linux/kdev_t.h>
  #include <linux/idr.h>
  #include <linux/hwmon.h>
8c65b4a60   Tim Schmielau   [PATCH] fix remai...
19
  #include <linux/gfp.h>
ded2b6661   Mark M. Hoffman   [PATCH] hwmon: ad...
20
  #include <linux/spinlock.h>
2958b1ec6   Jean Delvare   hwmon: PCI quirk ...
21
  #include <linux/pci.h>
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
22
23
24
25
26
27
28
  
  #define HWMON_ID_PREFIX "hwmon"
  #define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
  
  static struct class *hwmon_class;
  
  static DEFINE_IDR(hwmon_idr);
ded2b6661   Mark M. Hoffman   [PATCH] hwmon: ad...
29
  static DEFINE_SPINLOCK(idr_lock);
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
30
31
  
  /**
1beeffe43   Tony Jones   hwmon: Convert fr...
32
   * hwmon_device_register - register w/ hwmon
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
33
34
   * @dev: the device to register
   *
1beeffe43   Tony Jones   hwmon: Convert fr...
35
   * hwmon_device_unregister() must be called when the device is no
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
36
37
   * longer needed.
   *
1beeffe43   Tony Jones   hwmon: Convert fr...
38
   * Returns the pointer to the new device.
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
39
   */
1beeffe43   Tony Jones   hwmon: Convert fr...
40
  struct device *hwmon_device_register(struct device *dev)
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
41
  {
1beeffe43   Tony Jones   hwmon: Convert fr...
42
  	struct device *hwdev;
ded2b6661   Mark M. Hoffman   [PATCH] hwmon: ad...
43
  	int id, err;
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
44

ded2b6661   Mark M. Hoffman   [PATCH] hwmon: ad...
45
46
  again:
  	if (unlikely(idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0))
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
47
  		return ERR_PTR(-ENOMEM);
ded2b6661   Mark M. Hoffman   [PATCH] hwmon: ad...
48
49
50
51
52
53
54
55
  	spin_lock(&idr_lock);
  	err = idr_get_new(&hwmon_idr, NULL, &id);
  	spin_unlock(&idr_lock);
  
  	if (unlikely(err == -EAGAIN))
  		goto again;
  	else if (unlikely(err))
  		return ERR_PTR(err);
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
56
57
  
  	id = id & MAX_ID_MASK;
a9b12619f   Greg Kroah-Hartman   device create: mi...
58
59
  	hwdev = device_create(hwmon_class, dev, MKDEV(0, 0), NULL,
  			      HWMON_ID_FORMAT, id);
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
60

1beeffe43   Tony Jones   hwmon: Convert fr...
61
  	if (IS_ERR(hwdev)) {
ded2b6661   Mark M. Hoffman   [PATCH] hwmon: ad...
62
  		spin_lock(&idr_lock);
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
63
  		idr_remove(&hwmon_idr, id);
ded2b6661   Mark M. Hoffman   [PATCH] hwmon: ad...
64
65
  		spin_unlock(&idr_lock);
  	}
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
66

1beeffe43   Tony Jones   hwmon: Convert fr...
67
  	return hwdev;
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
68
69
70
71
72
  }
  
  /**
   * hwmon_device_unregister - removes the previously registered class device
   *
1beeffe43   Tony Jones   hwmon: Convert fr...
73
   * @dev: the class device to destroy
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
74
   */
1beeffe43   Tony Jones   hwmon: Convert fr...
75
  void hwmon_device_unregister(struct device *dev)
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
76
77
  {
  	int id;
739cf3a26   Kay Sievers   hwmon: struct dev...
78
  	if (likely(sscanf(dev_name(dev), HWMON_ID_FORMAT, &id) == 1)) {
1beeffe43   Tony Jones   hwmon: Convert fr...
79
  		device_unregister(dev);
ded2b6661   Mark M. Hoffman   [PATCH] hwmon: ad...
80
  		spin_lock(&idr_lock);
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
81
  		idr_remove(&hwmon_idr, id);
ded2b6661   Mark M. Hoffman   [PATCH] hwmon: ad...
82
  		spin_unlock(&idr_lock);
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
83
  	} else
1beeffe43   Tony Jones   hwmon: Convert fr...
84
  		dev_dbg(dev->parent,
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
85
86
87
  			"hwmon_device_unregister() failed: bad class ID!
  ");
  }
2958b1ec6   Jean Delvare   hwmon: PCI quirk ...
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  static void __init hwmon_pci_quirks(void)
  {
  #if defined CONFIG_X86 && defined CONFIG_PCI
  	struct pci_dev *sb;
  	u16 base;
  	u8 enable;
  
  	/* Open access to 0x295-0x296 on MSI MS-7031 */
  	sb = pci_get_device(PCI_VENDOR_ID_ATI, 0x436c, NULL);
  	if (sb &&
  	    (sb->subsystem_vendor == 0x1462 &&	/* MSI */
  	     sb->subsystem_device == 0x0031)) {	/* MS-7031 */
  
  		pci_read_config_byte(sb, 0x48, &enable);
  		pci_read_config_word(sb, 0x64, &base);
  
  		if (base == 0 && !(enable & BIT(2))) {
  			dev_info(&sb->dev,
  				 "Opening wide generic port at 0x295
  ");
  			pci_write_config_word(sb, 0x64, 0x295);
  			pci_write_config_byte(sb, 0x48, enable | BIT(2));
  		}
  	}
  #endif
  }
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
114
115
  static int __init hwmon_init(void)
  {
2958b1ec6   Jean Delvare   hwmon: PCI quirk ...
116
  	hwmon_pci_quirks();
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
117
118
  	hwmon_class = class_create(THIS_MODULE, "hwmon");
  	if (IS_ERR(hwmon_class)) {
c95df1ae6   Joe Perches   hwmon: (core) Use...
119
120
  		pr_err("couldn't create sysfs class
  ");
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
121
122
123
124
125
126
127
128
129
  		return PTR_ERR(hwmon_class);
  	}
  	return 0;
  }
  
  static void __exit hwmon_exit(void)
  {
  	class_destroy(hwmon_class);
  }
37f54ee54   David Brownell   hwmon: Use subsys...
130
  subsys_initcall(hwmon_init);
1236441f3   Mark M. Hoffman   [PATCH] I2C hwmon...
131
132
133
134
135
136
137
138
  module_exit(hwmon_exit);
  
  EXPORT_SYMBOL_GPL(hwmon_device_register);
  EXPORT_SYMBOL_GPL(hwmon_device_unregister);
  
  MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
  MODULE_DESCRIPTION("hardware monitoring sysfs/class support");
  MODULE_LICENSE("GPL");