880-gateworks_system_controller.patch 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. --- a/drivers/hwmon/Kconfig
  2. +++ b/drivers/hwmon/Kconfig
  3. @@ -507,6 +507,15 @@ config SENSORS_G762
  4. This driver can also be built as a module. If so, the module
  5. will be called g762.
  6. +config SENSORS_GSC
  7. + tristate "Gateworks System Controller"
  8. + depends on I2C
  9. + help
  10. + If you say yes here you get support for the Gateworks System Controller.
  11. +
  12. + This driver can also be built as a module. If so, the module
  13. + will be called gsc.
  14. +
  15. config SENSORS_GPIO_FAN
  16. tristate "GPIO fan"
  17. depends on GPIOLIB
  18. --- a/drivers/hwmon/Makefile
  19. +++ b/drivers/hwmon/Makefile
  20. @@ -156,6 +156,7 @@ obj-$(CONFIG_SENSORS_W83L785TS) += w83l7
  21. obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o
  22. obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o
  23. obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o
  24. +obj-$(CONFIG_SENSORS_GSC) += gsc.o
  25. obj-$(CONFIG_PMBUS) += pmbus/
  26. --- /dev/null
  27. +++ b/drivers/hwmon/gsc.c
  28. @@ -0,0 +1,308 @@
  29. +/*
  30. + * A hwmon driver for the Gateworks System Controller
  31. + * Copyright (C) 2009 Gateworks Corporation
  32. + *
  33. + * Author: Chris Lang <clang@gateworks.com>
  34. + *
  35. + * This program is free software; you can redistribute it and/or modify
  36. + * it under the terms of the GNU General Public License,
  37. + * as published by the Free Software Foundation - version 2.
  38. + */
  39. +
  40. +#include <linux/module.h>
  41. +#include <linux/i2c.h>
  42. +#include <linux/hwmon.h>
  43. +#include <linux/hwmon-sysfs.h>
  44. +#include <linux/err.h>
  45. +#include <linux/slab.h>
  46. +
  47. +#define DRV_VERSION "0.2"
  48. +
  49. +enum chips { gsp };
  50. +
  51. +/* AD7418 registers */
  52. +#define GSP_REG_TEMP_IN 0x00
  53. +#define GSP_REG_VIN 0x02
  54. +#define GSP_REG_3P3 0x05
  55. +#define GSP_REG_BAT 0x08
  56. +#define GSP_REG_5P0 0x0b
  57. +#define GSP_REG_CORE 0x0e
  58. +#define GSP_REG_CPU1 0x11
  59. +#define GSP_REG_CPU2 0x14
  60. +#define GSP_REG_DRAM 0x17
  61. +#define GSP_REG_EXT_BAT 0x1a
  62. +#define GSP_REG_IO1 0x1d
  63. +#define GSP_REG_IO2 0x20
  64. +#define GSP_REG_PCIE 0x23
  65. +#define GSP_REG_CURRENT 0x26
  66. +#define GSP_FAN_0 0x2C
  67. +#define GSP_FAN_1 0x2E
  68. +#define GSP_FAN_2 0x30
  69. +#define GSP_FAN_3 0x32
  70. +#define GSP_FAN_4 0x34
  71. +#define GSP_FAN_5 0x36
  72. +
  73. +struct gsp_sensor_info {
  74. + const char* name;
  75. + int reg;
  76. +};
  77. +
  78. +static const struct gsp_sensor_info gsp_sensors[] = {
  79. + {"temp", GSP_REG_TEMP_IN},
  80. + {"vin", GSP_REG_VIN},
  81. + {"3p3", GSP_REG_3P3},
  82. + {"bat", GSP_REG_BAT},
  83. + {"5p0", GSP_REG_5P0},
  84. + {"core", GSP_REG_CORE},
  85. + {"cpu1", GSP_REG_CPU1},
  86. + {"cpu2", GSP_REG_CPU2},
  87. + {"dram", GSP_REG_DRAM},
  88. + {"ext_bat", GSP_REG_EXT_BAT},
  89. + {"io1", GSP_REG_IO1},
  90. + {"io2", GSP_REG_IO2},
  91. + {"pci2", GSP_REG_PCIE},
  92. + {"current", GSP_REG_CURRENT},
  93. + {"fan_point0", GSP_FAN_0},
  94. + {"fan_point1", GSP_FAN_1},
  95. + {"fan_point2", GSP_FAN_2},
  96. + {"fan_point3", GSP_FAN_3},
  97. + {"fan_point4", GSP_FAN_4},
  98. + {"fan_point5", GSP_FAN_5},
  99. +};
  100. +
  101. +struct gsp_data {
  102. + struct device *hwmon_dev;
  103. + struct attribute_group attrs;
  104. + enum chips type;
  105. +};
  106. +
  107. +static int gsp_probe(struct i2c_client *client,
  108. + const struct i2c_device_id *id);
  109. +static int gsp_remove(struct i2c_client *client);
  110. +
  111. +static const struct i2c_device_id gsp_id[] = {
  112. + { "gsp", 0 },
  113. + { }
  114. +};
  115. +MODULE_DEVICE_TABLE(i2c, gsp_id);
  116. +
  117. +static struct i2c_driver gsp_driver = {
  118. + .driver = {
  119. + .name = "gsp",
  120. + },
  121. + .probe = gsp_probe,
  122. + .remove = gsp_remove,
  123. + .id_table = gsp_id,
  124. +};
  125. +
  126. +/* All registers are word-sized, except for the configuration registers.
  127. + * AD7418 uses a high-byte first convention. Do NOT use those functions to
  128. + * access the configuration registers CONF and CONF2, as they are byte-sized.
  129. + */
  130. +static inline int gsp_read(struct i2c_client *client, u8 reg)
  131. +{
  132. + unsigned int adc = 0;
  133. + if (reg == GSP_REG_TEMP_IN || reg > GSP_REG_CURRENT)
  134. + {
  135. + adc |= i2c_smbus_read_byte_data(client, reg);
  136. + adc |= i2c_smbus_read_byte_data(client, reg + 1) << 8;
  137. + return adc;
  138. + }
  139. + else
  140. + {
  141. + adc |= i2c_smbus_read_byte_data(client, reg);
  142. + adc |= i2c_smbus_read_byte_data(client, reg + 1) << 8;
  143. + adc |= i2c_smbus_read_byte_data(client, reg + 2) << 16;
  144. + return adc;
  145. + }
  146. +}
  147. +
  148. +static inline int gsp_write(struct i2c_client *client, u8 reg, u16 value)
  149. +{
  150. + i2c_smbus_write_byte_data(client, reg, value & 0xff);
  151. + i2c_smbus_write_byte_data(client, reg + 1, ((value >> 8) & 0xff));
  152. + return 1;
  153. +}
  154. +
  155. +static ssize_t show_adc(struct device *dev, struct device_attribute *devattr,
  156. + char *buf)
  157. +{
  158. + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  159. + struct i2c_client *client = to_i2c_client(dev);
  160. + return sprintf(buf, "%d\n", gsp_read(client, gsp_sensors[attr->index].reg));
  161. +}
  162. +
  163. +static ssize_t show_label(struct device *dev,
  164. + struct device_attribute *devattr, char *buf)
  165. +{
  166. + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  167. +
  168. + return sprintf(buf, "%s\n", gsp_sensors[attr->index].name);
  169. +}
  170. +
  171. +static ssize_t store_fan(struct device *dev,
  172. + struct device_attribute *devattr, const char *buf, size_t count)
  173. +{
  174. + u16 val;
  175. + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
  176. + struct i2c_client *client = to_i2c_client(dev);
  177. + val = simple_strtoul(buf, NULL, 10);
  178. + gsp_write(client, gsp_sensors[attr->index].reg, val);
  179. + return count;
  180. +}
  181. +
  182. +static SENSOR_DEVICE_ATTR(temp0_input, S_IRUGO, show_adc, NULL, 0);
  183. +static SENSOR_DEVICE_ATTR(temp0_label, S_IRUGO, show_label, NULL, 0);
  184. +
  185. +static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_adc, NULL, 1);
  186. +static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, show_label, NULL, 1);
  187. +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_adc, NULL, 2);
  188. +static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_label, NULL, 2);
  189. +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_adc, NULL, 3);
  190. +static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_label, NULL, 3);
  191. +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_adc, NULL, 4);
  192. +static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 4);
  193. +static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_adc, NULL, 5);
  194. +static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, show_label, NULL, 5);
  195. +static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_adc, NULL, 6);
  196. +static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, show_label, NULL, 6);
  197. +static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_adc, NULL, 7);
  198. +static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, show_label, NULL, 7);
  199. +static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_adc, NULL, 8);
  200. +static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 8);
  201. +static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_adc, NULL, 9);
  202. +static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_label, NULL, 9);
  203. +static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_adc, NULL, 10);
  204. +static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_label, NULL, 10);
  205. +static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_adc, NULL, 11);
  206. +static SENSOR_DEVICE_ATTR(in10_label, S_IRUGO, show_label, NULL, 11);
  207. +static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_adc, NULL, 12);
  208. +static SENSOR_DEVICE_ATTR(in11_label, S_IRUGO, show_label, NULL, 12);
  209. +static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_adc, NULL, 13);
  210. +static SENSOR_DEVICE_ATTR(in12_label, S_IRUGO, show_label, NULL, 13);
  211. +
  212. +static SENSOR_DEVICE_ATTR(fan0_point0, S_IRUGO | S_IWUSR, show_adc, store_fan, 14);
  213. +static SENSOR_DEVICE_ATTR(fan0_point1, S_IRUGO | S_IWUSR, show_adc, store_fan, 15);
  214. +static SENSOR_DEVICE_ATTR(fan0_point2, S_IRUGO | S_IWUSR, show_adc, store_fan, 16);
  215. +static SENSOR_DEVICE_ATTR(fan0_point3, S_IRUGO | S_IWUSR, show_adc, store_fan, 17);
  216. +static SENSOR_DEVICE_ATTR(fan0_point4, S_IRUGO | S_IWUSR, show_adc, store_fan, 18);
  217. +static SENSOR_DEVICE_ATTR(fan0_point5, S_IRUGO | S_IWUSR, show_adc, store_fan, 19);
  218. +
  219. +static struct attribute *gsp_attributes[] = {
  220. + &sensor_dev_attr_temp0_input.dev_attr.attr,
  221. + &sensor_dev_attr_in0_input.dev_attr.attr,
  222. + &sensor_dev_attr_in1_input.dev_attr.attr,
  223. + &sensor_dev_attr_in2_input.dev_attr.attr,
  224. + &sensor_dev_attr_in3_input.dev_attr.attr,
  225. + &sensor_dev_attr_in4_input.dev_attr.attr,
  226. + &sensor_dev_attr_in5_input.dev_attr.attr,
  227. + &sensor_dev_attr_in6_input.dev_attr.attr,
  228. + &sensor_dev_attr_in7_input.dev_attr.attr,
  229. + &sensor_dev_attr_in8_input.dev_attr.attr,
  230. + &sensor_dev_attr_in9_input.dev_attr.attr,
  231. + &sensor_dev_attr_in10_input.dev_attr.attr,
  232. + &sensor_dev_attr_in11_input.dev_attr.attr,
  233. + &sensor_dev_attr_in12_input.dev_attr.attr,
  234. +
  235. + &sensor_dev_attr_temp0_label.dev_attr.attr,
  236. + &sensor_dev_attr_in0_label.dev_attr.attr,
  237. + &sensor_dev_attr_in1_label.dev_attr.attr,
  238. + &sensor_dev_attr_in2_label.dev_attr.attr,
  239. + &sensor_dev_attr_in3_label.dev_attr.attr,
  240. + &sensor_dev_attr_in4_label.dev_attr.attr,
  241. + &sensor_dev_attr_in5_label.dev_attr.attr,
  242. + &sensor_dev_attr_in6_label.dev_attr.attr,
  243. + &sensor_dev_attr_in7_label.dev_attr.attr,
  244. + &sensor_dev_attr_in8_label.dev_attr.attr,
  245. + &sensor_dev_attr_in9_label.dev_attr.attr,
  246. + &sensor_dev_attr_in10_label.dev_attr.attr,
  247. + &sensor_dev_attr_in11_label.dev_attr.attr,
  248. + &sensor_dev_attr_in12_label.dev_attr.attr,
  249. +
  250. + &sensor_dev_attr_fan0_point0.dev_attr.attr,
  251. + &sensor_dev_attr_fan0_point1.dev_attr.attr,
  252. + &sensor_dev_attr_fan0_point2.dev_attr.attr,
  253. + &sensor_dev_attr_fan0_point3.dev_attr.attr,
  254. + &sensor_dev_attr_fan0_point4.dev_attr.attr,
  255. + &sensor_dev_attr_fan0_point5.dev_attr.attr,
  256. + NULL
  257. +};
  258. +
  259. +
  260. +static int gsp_probe(struct i2c_client *client,
  261. + const struct i2c_device_id *id)
  262. +{
  263. + struct i2c_adapter *adapter = client->adapter;
  264. + struct gsp_data *data;
  265. + int err;
  266. +
  267. + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
  268. + I2C_FUNC_SMBUS_WORD_DATA)) {
  269. + err = -EOPNOTSUPP;
  270. + goto exit;
  271. + }
  272. +
  273. + if (!(data = kzalloc(sizeof(struct gsp_data), GFP_KERNEL))) {
  274. + err = -ENOMEM;
  275. + goto exit;
  276. + }
  277. +
  278. + i2c_set_clientdata(client, data);
  279. +
  280. + data->type = id->driver_data;
  281. +
  282. + switch (data->type) {
  283. + case 0:
  284. + data->attrs.attrs = gsp_attributes;
  285. + break;
  286. + }
  287. +
  288. + dev_info(&client->dev, "%s chip found\n", client->name);
  289. +
  290. + /* Register sysfs hooks */
  291. + if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs)))
  292. + goto exit_free;
  293. +
  294. + data->hwmon_dev = hwmon_device_register(&client->dev);
  295. + if (IS_ERR(data->hwmon_dev)) {
  296. + err = PTR_ERR(data->hwmon_dev);
  297. + goto exit_remove;
  298. + }
  299. +
  300. + return 0;
  301. +
  302. +exit_remove:
  303. + sysfs_remove_group(&client->dev.kobj, &data->attrs);
  304. +exit_free:
  305. + kfree(data);
  306. +exit:
  307. + return err;
  308. +}
  309. +
  310. +static int gsp_remove(struct i2c_client *client)
  311. +{
  312. + struct gsp_data *data = i2c_get_clientdata(client);
  313. + hwmon_device_unregister(data->hwmon_dev);
  314. + sysfs_remove_group(&client->dev.kobj, &data->attrs);
  315. + kfree(data);
  316. + return 0;
  317. +}
  318. +
  319. +static int __init gsp_init(void)
  320. +{
  321. + return i2c_add_driver(&gsp_driver);
  322. +}
  323. +
  324. +static void __exit gsp_exit(void)
  325. +{
  326. + i2c_del_driver(&gsp_driver);
  327. +}
  328. +
  329. +module_init(gsp_init);
  330. +module_exit(gsp_exit);
  331. +
  332. +MODULE_AUTHOR("Chris Lang <clang@gateworks.com>");
  333. +MODULE_DESCRIPTION("GSC HWMON driver");
  334. +MODULE_LICENSE("GPL");
  335. +MODULE_VERSION(DRV_VERSION);
  336. +