scmi-hwmon.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * System Control and Management Interface(SCMI) based hwmon sensor driver
  4. *
  5. * Copyright (C) 2018 ARM Ltd.
  6. * Sudeep Holla <sudeep.holla@arm.com>
  7. */
  8. #include <linux/hwmon.h>
  9. #include <linux/module.h>
  10. #include <linux/scmi_protocol.h>
  11. #include <linux/slab.h>
  12. #include <linux/sysfs.h>
  13. #include <linux/thermal.h>
  14. struct scmi_sensors {
  15. const struct scmi_handle *handle;
  16. const struct scmi_sensor_info **info[hwmon_max];
  17. };
  18. static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
  19. u32 attr, int channel, long *val)
  20. {
  21. int ret;
  22. u64 value;
  23. const struct scmi_sensor_info *sensor;
  24. struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev);
  25. const struct scmi_handle *h = scmi_sensors->handle;
  26. sensor = *(scmi_sensors->info[type] + channel);
  27. ret = h->sensor_ops->reading_get(h, sensor->id, false, &value);
  28. if (!ret)
  29. *val = value;
  30. return ret;
  31. }
  32. static int
  33. scmi_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type,
  34. u32 attr, int channel, const char **str)
  35. {
  36. const struct scmi_sensor_info *sensor;
  37. struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev);
  38. sensor = *(scmi_sensors->info[type] + channel);
  39. *str = sensor->name;
  40. return 0;
  41. }
  42. static umode_t
  43. scmi_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_types type,
  44. u32 attr, int channel)
  45. {
  46. const struct scmi_sensor_info *sensor;
  47. const struct scmi_sensors *scmi_sensors = drvdata;
  48. sensor = *(scmi_sensors->info[type] + channel);
  49. if (sensor && sensor->name)
  50. return S_IRUGO;
  51. return 0;
  52. }
  53. static const struct hwmon_ops scmi_hwmon_ops = {
  54. .is_visible = scmi_hwmon_is_visible,
  55. .read = scmi_hwmon_read,
  56. .read_string = scmi_hwmon_read_string,
  57. };
  58. static struct hwmon_chip_info scmi_chip_info = {
  59. .ops = &scmi_hwmon_ops,
  60. .info = NULL,
  61. };
  62. static int scmi_hwmon_add_chan_info(struct hwmon_channel_info *scmi_hwmon_chan,
  63. struct device *dev, int num,
  64. enum hwmon_sensor_types type, u32 config)
  65. {
  66. int i;
  67. u32 *cfg = devm_kcalloc(dev, num + 1, sizeof(*cfg), GFP_KERNEL);
  68. if (!cfg)
  69. return -ENOMEM;
  70. scmi_hwmon_chan->type = type;
  71. scmi_hwmon_chan->config = cfg;
  72. for (i = 0; i < num; i++, cfg++)
  73. *cfg = config;
  74. return 0;
  75. }
  76. static enum hwmon_sensor_types scmi_types[] = {
  77. [TEMPERATURE_C] = hwmon_temp,
  78. [VOLTAGE] = hwmon_in,
  79. [CURRENT] = hwmon_curr,
  80. [POWER] = hwmon_power,
  81. [ENERGY] = hwmon_energy,
  82. };
  83. static u32 hwmon_attributes[hwmon_max] = {
  84. [hwmon_chip] = HWMON_C_REGISTER_TZ,
  85. [hwmon_temp] = HWMON_T_INPUT | HWMON_T_LABEL,
  86. [hwmon_in] = HWMON_I_INPUT | HWMON_I_LABEL,
  87. [hwmon_curr] = HWMON_C_INPUT | HWMON_C_LABEL,
  88. [hwmon_power] = HWMON_P_INPUT | HWMON_P_LABEL,
  89. [hwmon_energy] = HWMON_E_INPUT | HWMON_E_LABEL,
  90. };
  91. static int scmi_hwmon_probe(struct scmi_device *sdev)
  92. {
  93. int i, idx;
  94. u16 nr_sensors;
  95. enum hwmon_sensor_types type;
  96. struct scmi_sensors *scmi_sensors;
  97. const struct scmi_sensor_info *sensor;
  98. int nr_count[hwmon_max] = {0}, nr_types = 0;
  99. const struct hwmon_chip_info *chip_info;
  100. struct device *hwdev, *dev = &sdev->dev;
  101. struct hwmon_channel_info *scmi_hwmon_chan;
  102. const struct hwmon_channel_info **ptr_scmi_ci;
  103. const struct scmi_handle *handle = sdev->handle;
  104. if (!handle || !handle->sensor_ops)
  105. return -ENODEV;
  106. nr_sensors = handle->sensor_ops->count_get(handle);
  107. if (!nr_sensors)
  108. return -EIO;
  109. scmi_sensors = devm_kzalloc(dev, sizeof(*scmi_sensors), GFP_KERNEL);
  110. if (!scmi_sensors)
  111. return -ENOMEM;
  112. scmi_sensors->handle = handle;
  113. for (i = 0; i < nr_sensors; i++) {
  114. sensor = handle->sensor_ops->info_get(handle, i);
  115. if (!sensor)
  116. return -EINVAL;
  117. switch (sensor->type) {
  118. case TEMPERATURE_C:
  119. case VOLTAGE:
  120. case CURRENT:
  121. case POWER:
  122. case ENERGY:
  123. type = scmi_types[sensor->type];
  124. if (!nr_count[type])
  125. nr_types++;
  126. nr_count[type]++;
  127. break;
  128. }
  129. }
  130. if (nr_count[hwmon_temp])
  131. nr_count[hwmon_chip]++, nr_types++;
  132. scmi_hwmon_chan = devm_kcalloc(dev, nr_types, sizeof(*scmi_hwmon_chan),
  133. GFP_KERNEL);
  134. if (!scmi_hwmon_chan)
  135. return -ENOMEM;
  136. ptr_scmi_ci = devm_kcalloc(dev, nr_types + 1, sizeof(*ptr_scmi_ci),
  137. GFP_KERNEL);
  138. if (!ptr_scmi_ci)
  139. return -ENOMEM;
  140. scmi_chip_info.info = ptr_scmi_ci;
  141. chip_info = &scmi_chip_info;
  142. for (type = 0; type < hwmon_max; type++) {
  143. if (!nr_count[type])
  144. continue;
  145. scmi_hwmon_add_chan_info(scmi_hwmon_chan, dev, nr_count[type],
  146. type, hwmon_attributes[type]);
  147. *ptr_scmi_ci++ = scmi_hwmon_chan++;
  148. scmi_sensors->info[type] =
  149. devm_kcalloc(dev, nr_count[type],
  150. sizeof(*scmi_sensors->info), GFP_KERNEL);
  151. if (!scmi_sensors->info[type])
  152. return -ENOMEM;
  153. }
  154. for (i = nr_sensors - 1; i >= 0 ; i--) {
  155. sensor = handle->sensor_ops->info_get(handle, i);
  156. if (!sensor)
  157. continue;
  158. switch (sensor->type) {
  159. case TEMPERATURE_C:
  160. case VOLTAGE:
  161. case CURRENT:
  162. case POWER:
  163. case ENERGY:
  164. type = scmi_types[sensor->type];
  165. idx = --nr_count[type];
  166. *(scmi_sensors->info[type] + idx) = sensor;
  167. break;
  168. }
  169. }
  170. hwdev = devm_hwmon_device_register_with_info(dev, "scmi_sensors",
  171. scmi_sensors, chip_info,
  172. NULL);
  173. return PTR_ERR_OR_ZERO(hwdev);
  174. }
  175. static const struct scmi_device_id scmi_id_table[] = {
  176. { SCMI_PROTOCOL_SENSOR },
  177. { },
  178. };
  179. MODULE_DEVICE_TABLE(scmi, scmi_id_table);
  180. static struct scmi_driver scmi_hwmon_drv = {
  181. .name = "scmi-hwmon",
  182. .probe = scmi_hwmon_probe,
  183. .id_table = scmi_id_table,
  184. };
  185. module_scmi_driver(scmi_hwmon_drv);
  186. MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
  187. MODULE_DESCRIPTION("ARM SCMI HWMON interface driver");
  188. MODULE_LICENSE("GPL v2");