2 * A hwmon driver for the Gateworks System Controller
3 * Copyright (C) 2009 Gateworks Corporation
5 * Author: Chris Lang <clang@gateworks.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License,
9 * as published by the Free Software Foundation - version 2.
12 #include <linux/module.h>
13 #include <linux/i2c.h>
14 #include <linux/hwmon.h>
15 #include <linux/hwmon-sysfs.h>
16 #include <linux/err.h>
17 #include <linux/slab.h>
19 #define DRV_VERSION "0.2"
23 /* AD7418 registers */
24 #define GSP_REG_TEMP_IN 0x00
25 #define GSP_REG_VIN 0x02
26 #define GSP_REG_3P3 0x05
27 #define GSP_REG_BAT 0x08
28 #define GSP_REG_5P0 0x0b
29 #define GSP_REG_CORE 0x0e
30 #define GSP_REG_CPU1 0x11
31 #define GSP_REG_CPU2 0x14
32 #define GSP_REG_DRAM 0x17
33 #define GSP_REG_EXT_BAT 0x1a
34 #define GSP_REG_IO1 0x1d
35 #define GSP_REG_IO2 0x20
36 #define GSP_REG_PCIE 0x23
37 #define GSP_REG_CURRENT 0x26
38 #define GSP_FAN_0 0x2C
39 #define GSP_FAN_1 0x2E
40 #define GSP_FAN_2 0x30
41 #define GSP_FAN_3 0x32
42 #define GSP_FAN_4 0x34
43 #define GSP_FAN_5 0x36
45 struct gsp_sensor_info
{
50 static const struct gsp_sensor_info gsp_sensors
[] = {
51 {"temp", GSP_REG_TEMP_IN
},
56 {"core", GSP_REG_CORE
},
57 {"cpu1", GSP_REG_CPU1
},
58 {"cpu2", GSP_REG_CPU2
},
59 {"dram", GSP_REG_DRAM
},
60 {"ext_bat", GSP_REG_EXT_BAT
},
63 {"pci2", GSP_REG_PCIE
},
64 {"current", GSP_REG_CURRENT
},
65 {"fan_point0", GSP_FAN_0
},
66 {"fan_point1", GSP_FAN_1
},
67 {"fan_point2", GSP_FAN_2
},
68 {"fan_point3", GSP_FAN_3
},
69 {"fan_point4", GSP_FAN_4
},
70 {"fan_point5", GSP_FAN_5
},
74 struct device
*hwmon_dev
;
75 struct attribute_group attrs
;
79 static int gsp_probe(struct i2c_client
*client
,
80 const struct i2c_device_id
*id
);
81 static int gsp_remove(struct i2c_client
*client
);
83 static const struct i2c_device_id gsp_id
[] = {
87 MODULE_DEVICE_TABLE(i2c
, gsp_id
);
89 static struct i2c_driver gsp_driver
= {
98 /* All registers are word-sized, except for the configuration registers.
99 * AD7418 uses a high-byte first convention. Do NOT use those functions to
100 * access the configuration registers CONF and CONF2, as they are byte-sized.
102 static inline int gsp_read(struct i2c_client
*client
, u8 reg
)
104 unsigned int adc
= 0;
105 if (reg
== GSP_REG_TEMP_IN
|| reg
> GSP_REG_CURRENT
)
107 adc
|= i2c_smbus_read_byte_data(client
, reg
);
108 adc
|= i2c_smbus_read_byte_data(client
, reg
+ 1) << 8;
113 adc
|= i2c_smbus_read_byte_data(client
, reg
);
114 adc
|= i2c_smbus_read_byte_data(client
, reg
+ 1) << 8;
115 adc
|= i2c_smbus_read_byte_data(client
, reg
+ 2) << 16;
120 static inline int gsp_write(struct i2c_client
*client
, u8 reg
, u16 value
)
122 i2c_smbus_write_byte_data(client
, reg
, value
& 0xff);
123 i2c_smbus_write_byte_data(client
, reg
+ 1, ((value
>> 8) & 0xff));
127 static ssize_t
show_adc(struct device
*dev
, struct device_attribute
*devattr
,
130 struct sensor_device_attribute
*attr
= to_sensor_dev_attr(devattr
);
131 struct i2c_client
*client
= to_i2c_client(dev
);
132 return sprintf(buf
, "%d\n", gsp_read(client
, gsp_sensors
[attr
->index
].reg
));
135 static ssize_t
show_label(struct device
*dev
,
136 struct device_attribute
*devattr
, char *buf
)
138 struct sensor_device_attribute
*attr
= to_sensor_dev_attr(devattr
);
140 return sprintf(buf
, "%s\n", gsp_sensors
[attr
->index
].name
);
143 static ssize_t
store_fan(struct device
*dev
,
144 struct device_attribute
*devattr
, const char *buf
, size_t count
)
147 struct sensor_device_attribute
*attr
= to_sensor_dev_attr(devattr
);
148 struct i2c_client
*client
= to_i2c_client(dev
);
149 val
= simple_strtoul(buf
, NULL
, 10);
150 gsp_write(client
, gsp_sensors
[attr
->index
].reg
, val
);
154 static SENSOR_DEVICE_ATTR(temp0_input
, S_IRUGO
, show_adc
, NULL
, 0);
155 static SENSOR_DEVICE_ATTR(temp0_label
, S_IRUGO
, show_label
, NULL
, 0);
157 static SENSOR_DEVICE_ATTR(in0_input
, S_IRUGO
, show_adc
, NULL
, 1);
158 static SENSOR_DEVICE_ATTR(in0_label
, S_IRUGO
, show_label
, NULL
, 1);
159 static SENSOR_DEVICE_ATTR(in1_input
, S_IRUGO
, show_adc
, NULL
, 2);
160 static SENSOR_DEVICE_ATTR(in1_label
, S_IRUGO
, show_label
, NULL
, 2);
161 static SENSOR_DEVICE_ATTR(in2_input
, S_IRUGO
, show_adc
, NULL
, 3);
162 static SENSOR_DEVICE_ATTR(in2_label
, S_IRUGO
, show_label
, NULL
, 3);
163 static SENSOR_DEVICE_ATTR(in3_input
, S_IRUGO
, show_adc
, NULL
, 4);
164 static SENSOR_DEVICE_ATTR(in3_label
, S_IRUGO
, show_label
, NULL
, 4);
165 static SENSOR_DEVICE_ATTR(in4_input
, S_IRUGO
, show_adc
, NULL
, 5);
166 static SENSOR_DEVICE_ATTR(in4_label
, S_IRUGO
, show_label
, NULL
, 5);
167 static SENSOR_DEVICE_ATTR(in5_input
, S_IRUGO
, show_adc
, NULL
, 6);
168 static SENSOR_DEVICE_ATTR(in5_label
, S_IRUGO
, show_label
, NULL
, 6);
169 static SENSOR_DEVICE_ATTR(in6_input
, S_IRUGO
, show_adc
, NULL
, 7);
170 static SENSOR_DEVICE_ATTR(in6_label
, S_IRUGO
, show_label
, NULL
, 7);
171 static SENSOR_DEVICE_ATTR(in7_input
, S_IRUGO
, show_adc
, NULL
, 8);
172 static SENSOR_DEVICE_ATTR(in7_label
, S_IRUGO
, show_label
, NULL
, 8);
173 static SENSOR_DEVICE_ATTR(in8_input
, S_IRUGO
, show_adc
, NULL
, 9);
174 static SENSOR_DEVICE_ATTR(in8_label
, S_IRUGO
, show_label
, NULL
, 9);
175 static SENSOR_DEVICE_ATTR(in9_input
, S_IRUGO
, show_adc
, NULL
, 10);
176 static SENSOR_DEVICE_ATTR(in9_label
, S_IRUGO
, show_label
, NULL
, 10);
177 static SENSOR_DEVICE_ATTR(in10_input
, S_IRUGO
, show_adc
, NULL
, 11);
178 static SENSOR_DEVICE_ATTR(in10_label
, S_IRUGO
, show_label
, NULL
, 11);
179 static SENSOR_DEVICE_ATTR(in11_input
, S_IRUGO
, show_adc
, NULL
, 12);
180 static SENSOR_DEVICE_ATTR(in11_label
, S_IRUGO
, show_label
, NULL
, 12);
181 static SENSOR_DEVICE_ATTR(in12_input
, S_IRUGO
, show_adc
, NULL
, 13);
182 static SENSOR_DEVICE_ATTR(in12_label
, S_IRUGO
, show_label
, NULL
, 13);
184 static SENSOR_DEVICE_ATTR(fan0_point0
, S_IRUGO
| S_IWUSR
, show_adc
, store_fan
, 14);
185 static SENSOR_DEVICE_ATTR(fan0_point1
, S_IRUGO
| S_IWUSR
, show_adc
, store_fan
, 15);
186 static SENSOR_DEVICE_ATTR(fan0_point2
, S_IRUGO
| S_IWUSR
, show_adc
, store_fan
, 16);
187 static SENSOR_DEVICE_ATTR(fan0_point3
, S_IRUGO
| S_IWUSR
, show_adc
, store_fan
, 17);
188 static SENSOR_DEVICE_ATTR(fan0_point4
, S_IRUGO
| S_IWUSR
, show_adc
, store_fan
, 18);
189 static SENSOR_DEVICE_ATTR(fan0_point5
, S_IRUGO
| S_IWUSR
, show_adc
, store_fan
, 19);
191 static struct attribute
*gsp_attributes
[] = {
192 &sensor_dev_attr_temp0_input
.dev_attr
.attr
,
193 &sensor_dev_attr_in0_input
.dev_attr
.attr
,
194 &sensor_dev_attr_in1_input
.dev_attr
.attr
,
195 &sensor_dev_attr_in2_input
.dev_attr
.attr
,
196 &sensor_dev_attr_in3_input
.dev_attr
.attr
,
197 &sensor_dev_attr_in4_input
.dev_attr
.attr
,
198 &sensor_dev_attr_in5_input
.dev_attr
.attr
,
199 &sensor_dev_attr_in6_input
.dev_attr
.attr
,
200 &sensor_dev_attr_in7_input
.dev_attr
.attr
,
201 &sensor_dev_attr_in8_input
.dev_attr
.attr
,
202 &sensor_dev_attr_in9_input
.dev_attr
.attr
,
203 &sensor_dev_attr_in10_input
.dev_attr
.attr
,
204 &sensor_dev_attr_in11_input
.dev_attr
.attr
,
205 &sensor_dev_attr_in12_input
.dev_attr
.attr
,
207 &sensor_dev_attr_temp0_label
.dev_attr
.attr
,
208 &sensor_dev_attr_in0_label
.dev_attr
.attr
,
209 &sensor_dev_attr_in1_label
.dev_attr
.attr
,
210 &sensor_dev_attr_in2_label
.dev_attr
.attr
,
211 &sensor_dev_attr_in3_label
.dev_attr
.attr
,
212 &sensor_dev_attr_in4_label
.dev_attr
.attr
,
213 &sensor_dev_attr_in5_label
.dev_attr
.attr
,
214 &sensor_dev_attr_in6_label
.dev_attr
.attr
,
215 &sensor_dev_attr_in7_label
.dev_attr
.attr
,
216 &sensor_dev_attr_in8_label
.dev_attr
.attr
,
217 &sensor_dev_attr_in9_label
.dev_attr
.attr
,
218 &sensor_dev_attr_in10_label
.dev_attr
.attr
,
219 &sensor_dev_attr_in11_label
.dev_attr
.attr
,
220 &sensor_dev_attr_in12_label
.dev_attr
.attr
,
222 &sensor_dev_attr_fan0_point0
.dev_attr
.attr
,
223 &sensor_dev_attr_fan0_point1
.dev_attr
.attr
,
224 &sensor_dev_attr_fan0_point2
.dev_attr
.attr
,
225 &sensor_dev_attr_fan0_point3
.dev_attr
.attr
,
226 &sensor_dev_attr_fan0_point4
.dev_attr
.attr
,
227 &sensor_dev_attr_fan0_point5
.dev_attr
.attr
,
232 static int gsp_probe(struct i2c_client
*client
,
233 const struct i2c_device_id
*id
)
235 struct i2c_adapter
*adapter
= client
->adapter
;
236 struct gsp_data
*data
;
239 if (!i2c_check_functionality(adapter
, I2C_FUNC_SMBUS_BYTE_DATA
|
240 I2C_FUNC_SMBUS_WORD_DATA
)) {
245 if (!(data
= kzalloc(sizeof(struct gsp_data
), GFP_KERNEL
))) {
250 i2c_set_clientdata(client
, data
);
252 data
->type
= id
->driver_data
;
254 switch (data
->type
) {
256 data
->attrs
.attrs
= gsp_attributes
;
260 dev_info(&client
->dev
, "%s chip found\n", client
->name
);
262 /* Register sysfs hooks */
263 if ((err
= sysfs_create_group(&client
->dev
.kobj
, &data
->attrs
)))
266 data
->hwmon_dev
= hwmon_device_register(&client
->dev
);
267 if (IS_ERR(data
->hwmon_dev
)) {
268 err
= PTR_ERR(data
->hwmon_dev
);
275 sysfs_remove_group(&client
->dev
.kobj
, &data
->attrs
);
282 static int gsp_remove(struct i2c_client
*client
)
284 struct gsp_data
*data
= i2c_get_clientdata(client
);
285 hwmon_device_unregister(data
->hwmon_dev
);
286 sysfs_remove_group(&client
->dev
.kobj
, &data
->attrs
);
291 static int __init
gsp_init(void)
293 return i2c_add_driver(&gsp_driver
);
296 static void __exit
gsp_exit(void)
298 i2c_del_driver(&gsp_driver
);
301 module_init(gsp_init
);
302 module_exit(gsp_exit
);
304 MODULE_AUTHOR("Chris Lang <clang@gateworks.com>");
305 MODULE_DESCRIPTION("GSC HWMON driver");
306 MODULE_LICENSE("GPL");
307 MODULE_VERSION(DRV_VERSION
);