vexpress-hwmon.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. *
  4. * Copyright (C) 2012 ARM Limited
  5. */
  6. #define DRVNAME "vexpress-hwmon"
  7. #define pr_fmt(fmt) DRVNAME ": " fmt
  8. #include <linux/device.h>
  9. #include <linux/err.h>
  10. #include <linux/hwmon.h>
  11. #include <linux/hwmon-sysfs.h>
  12. #include <linux/module.h>
  13. #include <linux/of.h>
  14. #include <linux/of_device.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/vexpress.h>
  17. struct vexpress_hwmon_data {
  18. struct device *hwmon_dev;
  19. struct regmap *reg;
  20. };
  21. static ssize_t vexpress_hwmon_label_show(struct device *dev,
  22. struct device_attribute *dev_attr, char *buffer)
  23. {
  24. const char *label = of_get_property(dev->of_node, "label", NULL);
  25. return sysfs_emit(buffer, "%s\n", label);
  26. }
  27. static ssize_t vexpress_hwmon_u32_show(struct device *dev,
  28. struct device_attribute *dev_attr, char *buffer)
  29. {
  30. struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
  31. int err;
  32. u32 value;
  33. err = regmap_read(data->reg, 0, &value);
  34. if (err)
  35. return err;
  36. return sysfs_emit(buffer, "%u\n", value /
  37. to_sensor_dev_attr(dev_attr)->index);
  38. }
  39. static ssize_t vexpress_hwmon_u64_show(struct device *dev,
  40. struct device_attribute *dev_attr, char *buffer)
  41. {
  42. struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
  43. int err;
  44. u32 value_hi, value_lo;
  45. err = regmap_read(data->reg, 0, &value_lo);
  46. if (err)
  47. return err;
  48. err = regmap_read(data->reg, 1, &value_hi);
  49. if (err)
  50. return err;
  51. return sysfs_emit(buffer, "%llu\n",
  52. div_u64(((u64)value_hi << 32) | value_lo,
  53. to_sensor_dev_attr(dev_attr)->index));
  54. }
  55. static umode_t vexpress_hwmon_attr_is_visible(struct kobject *kobj,
  56. struct attribute *attr, int index)
  57. {
  58. struct device *dev = kobj_to_dev(kobj);
  59. struct device_attribute *dev_attr = container_of(attr,
  60. struct device_attribute, attr);
  61. if (dev_attr->show == vexpress_hwmon_label_show &&
  62. !of_get_property(dev->of_node, "label", NULL))
  63. return 0;
  64. return attr->mode;
  65. }
  66. struct vexpress_hwmon_type {
  67. const char *name;
  68. const struct attribute_group **attr_groups;
  69. };
  70. #if !defined(CONFIG_REGULATOR_VEXPRESS)
  71. static DEVICE_ATTR(in1_label, 0444, vexpress_hwmon_label_show, NULL);
  72. static SENSOR_DEVICE_ATTR_RO(in1_input, vexpress_hwmon_u32, 1000);
  73. static struct attribute *vexpress_hwmon_attrs_volt[] = {
  74. &dev_attr_in1_label.attr,
  75. &sensor_dev_attr_in1_input.dev_attr.attr,
  76. NULL
  77. };
  78. static struct attribute_group vexpress_hwmon_group_volt = {
  79. .is_visible = vexpress_hwmon_attr_is_visible,
  80. .attrs = vexpress_hwmon_attrs_volt,
  81. };
  82. static struct vexpress_hwmon_type vexpress_hwmon_volt = {
  83. .name = "vexpress_volt",
  84. .attr_groups = (const struct attribute_group *[]) {
  85. &vexpress_hwmon_group_volt,
  86. NULL,
  87. },
  88. };
  89. #endif
  90. static DEVICE_ATTR(curr1_label, 0444, vexpress_hwmon_label_show, NULL);
  91. static SENSOR_DEVICE_ATTR_RO(curr1_input, vexpress_hwmon_u32, 1000);
  92. static struct attribute *vexpress_hwmon_attrs_amp[] = {
  93. &dev_attr_curr1_label.attr,
  94. &sensor_dev_attr_curr1_input.dev_attr.attr,
  95. NULL
  96. };
  97. static struct attribute_group vexpress_hwmon_group_amp = {
  98. .is_visible = vexpress_hwmon_attr_is_visible,
  99. .attrs = vexpress_hwmon_attrs_amp,
  100. };
  101. static struct vexpress_hwmon_type vexpress_hwmon_amp = {
  102. .name = "vexpress_amp",
  103. .attr_groups = (const struct attribute_group *[]) {
  104. &vexpress_hwmon_group_amp,
  105. NULL
  106. },
  107. };
  108. static DEVICE_ATTR(temp1_label, 0444, vexpress_hwmon_label_show, NULL);
  109. static SENSOR_DEVICE_ATTR_RO(temp1_input, vexpress_hwmon_u32, 1000);
  110. static struct attribute *vexpress_hwmon_attrs_temp[] = {
  111. &dev_attr_temp1_label.attr,
  112. &sensor_dev_attr_temp1_input.dev_attr.attr,
  113. NULL
  114. };
  115. static struct attribute_group vexpress_hwmon_group_temp = {
  116. .is_visible = vexpress_hwmon_attr_is_visible,
  117. .attrs = vexpress_hwmon_attrs_temp,
  118. };
  119. static struct vexpress_hwmon_type vexpress_hwmon_temp = {
  120. .name = "vexpress_temp",
  121. .attr_groups = (const struct attribute_group *[]) {
  122. &vexpress_hwmon_group_temp,
  123. NULL
  124. },
  125. };
  126. static DEVICE_ATTR(power1_label, 0444, vexpress_hwmon_label_show, NULL);
  127. static SENSOR_DEVICE_ATTR_RO(power1_input, vexpress_hwmon_u32, 1);
  128. static struct attribute *vexpress_hwmon_attrs_power[] = {
  129. &dev_attr_power1_label.attr,
  130. &sensor_dev_attr_power1_input.dev_attr.attr,
  131. NULL
  132. };
  133. static struct attribute_group vexpress_hwmon_group_power = {
  134. .is_visible = vexpress_hwmon_attr_is_visible,
  135. .attrs = vexpress_hwmon_attrs_power,
  136. };
  137. static struct vexpress_hwmon_type vexpress_hwmon_power = {
  138. .name = "vexpress_power",
  139. .attr_groups = (const struct attribute_group *[]) {
  140. &vexpress_hwmon_group_power,
  141. NULL
  142. },
  143. };
  144. static DEVICE_ATTR(energy1_label, 0444, vexpress_hwmon_label_show, NULL);
  145. static SENSOR_DEVICE_ATTR_RO(energy1_input, vexpress_hwmon_u64, 1);
  146. static struct attribute *vexpress_hwmon_attrs_energy[] = {
  147. &dev_attr_energy1_label.attr,
  148. &sensor_dev_attr_energy1_input.dev_attr.attr,
  149. NULL
  150. };
  151. static struct attribute_group vexpress_hwmon_group_energy = {
  152. .is_visible = vexpress_hwmon_attr_is_visible,
  153. .attrs = vexpress_hwmon_attrs_energy,
  154. };
  155. static struct vexpress_hwmon_type vexpress_hwmon_energy = {
  156. .name = "vexpress_energy",
  157. .attr_groups = (const struct attribute_group *[]) {
  158. &vexpress_hwmon_group_energy,
  159. NULL
  160. },
  161. };
  162. static const struct of_device_id vexpress_hwmon_of_match[] = {
  163. #if !defined(CONFIG_REGULATOR_VEXPRESS)
  164. {
  165. .compatible = "arm,vexpress-volt",
  166. .data = &vexpress_hwmon_volt,
  167. },
  168. #endif
  169. {
  170. .compatible = "arm,vexpress-amp",
  171. .data = &vexpress_hwmon_amp,
  172. }, {
  173. .compatible = "arm,vexpress-temp",
  174. .data = &vexpress_hwmon_temp,
  175. }, {
  176. .compatible = "arm,vexpress-power",
  177. .data = &vexpress_hwmon_power,
  178. }, {
  179. .compatible = "arm,vexpress-energy",
  180. .data = &vexpress_hwmon_energy,
  181. },
  182. {}
  183. };
  184. MODULE_DEVICE_TABLE(of, vexpress_hwmon_of_match);
  185. static int vexpress_hwmon_probe(struct platform_device *pdev)
  186. {
  187. struct vexpress_hwmon_data *data;
  188. const struct vexpress_hwmon_type *type;
  189. data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
  190. if (!data)
  191. return -ENOMEM;
  192. platform_set_drvdata(pdev, data);
  193. type = of_device_get_match_data(&pdev->dev);
  194. if (!type)
  195. return -ENODEV;
  196. data->reg = devm_regmap_init_vexpress_config(&pdev->dev);
  197. if (IS_ERR(data->reg))
  198. return PTR_ERR(data->reg);
  199. data->hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev,
  200. type->name, data, type->attr_groups);
  201. return PTR_ERR_OR_ZERO(data->hwmon_dev);
  202. }
  203. static struct platform_driver vexpress_hwmon_driver = {
  204. .probe = vexpress_hwmon_probe,
  205. .driver = {
  206. .name = DRVNAME,
  207. .of_match_table = vexpress_hwmon_of_match,
  208. },
  209. };
  210. module_platform_driver(vexpress_hwmon_driver);
  211. MODULE_AUTHOR("Pawel Moll <[email protected]>");
  212. MODULE_DESCRIPTION("Versatile Express hwmon sensors driver");
  213. MODULE_LICENSE("GPL");
  214. MODULE_ALIAS("platform:vexpress-hwmon");