scmi-hwmon.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * System Control and Management Interface(SCMI) based hwmon sensor driver
  4. *
  5. * Copyright (C) 2018-2021 ARM Ltd.
  6. * Sudeep Holla <[email protected]>
  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. static const struct scmi_sensor_proto_ops *sensor_ops;
  15. struct scmi_sensors {
  16. const struct scmi_protocol_handle *ph;
  17. const struct scmi_sensor_info **info[hwmon_max];
  18. };
  19. struct scmi_thermal_sensor {
  20. const struct scmi_protocol_handle *ph;
  21. const struct scmi_sensor_info *info;
  22. };
  23. static inline u64 __pow10(u8 x)
  24. {
  25. u64 r = 1;
  26. while (x--)
  27. r *= 10;
  28. return r;
  29. }
  30. static int scmi_hwmon_scale(const struct scmi_sensor_info *sensor, u64 *value)
  31. {
  32. int scale = sensor->scale;
  33. u64 f;
  34. switch (sensor->type) {
  35. case TEMPERATURE_C:
  36. case VOLTAGE:
  37. case CURRENT:
  38. scale += 3;
  39. break;
  40. case POWER:
  41. case ENERGY:
  42. scale += 6;
  43. break;
  44. default:
  45. break;
  46. }
  47. if (scale == 0)
  48. return 0;
  49. if (abs(scale) > 19)
  50. return -E2BIG;
  51. f = __pow10(abs(scale));
  52. if (scale > 0)
  53. *value *= f;
  54. else
  55. *value = div64_u64(*value, f);
  56. return 0;
  57. }
  58. static int scmi_hwmon_read_scaled_value(const struct scmi_protocol_handle *ph,
  59. const struct scmi_sensor_info *sensor,
  60. long *val)
  61. {
  62. int ret;
  63. u64 value;
  64. ret = sensor_ops->reading_get(ph, sensor->id, &value);
  65. if (ret)
  66. return ret;
  67. ret = scmi_hwmon_scale(sensor, &value);
  68. if (!ret)
  69. *val = value;
  70. return ret;
  71. }
  72. static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
  73. u32 attr, int channel, long *val)
  74. {
  75. const struct scmi_sensor_info *sensor;
  76. struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev);
  77. sensor = *(scmi_sensors->info[type] + channel);
  78. return scmi_hwmon_read_scaled_value(scmi_sensors->ph, sensor, val);
  79. }
  80. static int
  81. scmi_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type,
  82. u32 attr, int channel, const char **str)
  83. {
  84. const struct scmi_sensor_info *sensor;
  85. struct scmi_sensors *scmi_sensors = dev_get_drvdata(dev);
  86. sensor = *(scmi_sensors->info[type] + channel);
  87. *str = sensor->name;
  88. return 0;
  89. }
  90. static umode_t
  91. scmi_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_types type,
  92. u32 attr, int channel)
  93. {
  94. const struct scmi_sensor_info *sensor;
  95. const struct scmi_sensors *scmi_sensors = drvdata;
  96. sensor = *(scmi_sensors->info[type] + channel);
  97. if (sensor)
  98. return 0444;
  99. return 0;
  100. }
  101. static const struct hwmon_ops scmi_hwmon_ops = {
  102. .is_visible = scmi_hwmon_is_visible,
  103. .read = scmi_hwmon_read,
  104. .read_string = scmi_hwmon_read_string,
  105. };
  106. static struct hwmon_chip_info scmi_chip_info = {
  107. .ops = &scmi_hwmon_ops,
  108. .info = NULL,
  109. };
  110. static int scmi_hwmon_thermal_get_temp(struct thermal_zone_device *tz,
  111. int *temp)
  112. {
  113. int ret;
  114. long value;
  115. struct scmi_thermal_sensor *th_sensor = tz->devdata;
  116. ret = scmi_hwmon_read_scaled_value(th_sensor->ph, th_sensor->info,
  117. &value);
  118. if (!ret)
  119. *temp = value;
  120. return ret;
  121. }
  122. static const struct thermal_zone_device_ops scmi_hwmon_thermal_ops = {
  123. .get_temp = scmi_hwmon_thermal_get_temp,
  124. };
  125. static int scmi_hwmon_add_chan_info(struct hwmon_channel_info *scmi_hwmon_chan,
  126. struct device *dev, int num,
  127. enum hwmon_sensor_types type, u32 config)
  128. {
  129. int i;
  130. u32 *cfg = devm_kcalloc(dev, num + 1, sizeof(*cfg), GFP_KERNEL);
  131. if (!cfg)
  132. return -ENOMEM;
  133. scmi_hwmon_chan->type = type;
  134. scmi_hwmon_chan->config = cfg;
  135. for (i = 0; i < num; i++, cfg++)
  136. *cfg = config;
  137. return 0;
  138. }
  139. static enum hwmon_sensor_types scmi_types[] = {
  140. [TEMPERATURE_C] = hwmon_temp,
  141. [VOLTAGE] = hwmon_in,
  142. [CURRENT] = hwmon_curr,
  143. [POWER] = hwmon_power,
  144. [ENERGY] = hwmon_energy,
  145. };
  146. static u32 hwmon_attributes[hwmon_max] = {
  147. [hwmon_temp] = HWMON_T_INPUT | HWMON_T_LABEL,
  148. [hwmon_in] = HWMON_I_INPUT | HWMON_I_LABEL,
  149. [hwmon_curr] = HWMON_C_INPUT | HWMON_C_LABEL,
  150. [hwmon_power] = HWMON_P_INPUT | HWMON_P_LABEL,
  151. [hwmon_energy] = HWMON_E_INPUT | HWMON_E_LABEL,
  152. };
  153. static int scmi_thermal_sensor_register(struct device *dev,
  154. const struct scmi_protocol_handle *ph,
  155. const struct scmi_sensor_info *sensor)
  156. {
  157. struct scmi_thermal_sensor *th_sensor;
  158. struct thermal_zone_device *tzd;
  159. th_sensor = devm_kzalloc(dev, sizeof(*th_sensor), GFP_KERNEL);
  160. if (!th_sensor)
  161. return -ENOMEM;
  162. th_sensor->ph = ph;
  163. th_sensor->info = sensor;
  164. /*
  165. * Try to register a temperature sensor with the Thermal Framework:
  166. * skip sensors not defined as part of any thermal zone (-ENODEV) but
  167. * report any other errors related to misconfigured zones/sensors.
  168. */
  169. tzd = devm_thermal_of_zone_register(dev, th_sensor->info->id, th_sensor,
  170. &scmi_hwmon_thermal_ops);
  171. if (IS_ERR(tzd)) {
  172. devm_kfree(dev, th_sensor);
  173. if (PTR_ERR(tzd) != -ENODEV)
  174. return PTR_ERR(tzd);
  175. dev_dbg(dev, "Sensor '%s' not attached to any thermal zone.\n",
  176. sensor->name);
  177. } else {
  178. dev_dbg(dev, "Sensor '%s' attached to thermal zone ID:%d\n",
  179. sensor->name, tzd->id);
  180. }
  181. return 0;
  182. }
  183. static int scmi_hwmon_probe(struct scmi_device *sdev)
  184. {
  185. int i, idx;
  186. u16 nr_sensors;
  187. enum hwmon_sensor_types type;
  188. struct scmi_sensors *scmi_sensors;
  189. const struct scmi_sensor_info *sensor;
  190. int nr_count[hwmon_max] = {0}, nr_types = 0, nr_count_temp = 0;
  191. const struct hwmon_chip_info *chip_info;
  192. struct device *hwdev, *dev = &sdev->dev;
  193. struct hwmon_channel_info *scmi_hwmon_chan;
  194. const struct hwmon_channel_info **ptr_scmi_ci;
  195. const struct scmi_handle *handle = sdev->handle;
  196. struct scmi_protocol_handle *ph;
  197. if (!handle)
  198. return -ENODEV;
  199. sensor_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_SENSOR, &ph);
  200. if (IS_ERR(sensor_ops))
  201. return PTR_ERR(sensor_ops);
  202. nr_sensors = sensor_ops->count_get(ph);
  203. if (!nr_sensors)
  204. return -EIO;
  205. scmi_sensors = devm_kzalloc(dev, sizeof(*scmi_sensors), GFP_KERNEL);
  206. if (!scmi_sensors)
  207. return -ENOMEM;
  208. scmi_sensors->ph = ph;
  209. for (i = 0; i < nr_sensors; i++) {
  210. sensor = sensor_ops->info_get(ph, i);
  211. if (!sensor)
  212. return -EINVAL;
  213. switch (sensor->type) {
  214. case TEMPERATURE_C:
  215. case VOLTAGE:
  216. case CURRENT:
  217. case POWER:
  218. case ENERGY:
  219. type = scmi_types[sensor->type];
  220. if (!nr_count[type])
  221. nr_types++;
  222. nr_count[type]++;
  223. break;
  224. }
  225. }
  226. if (nr_count[hwmon_temp])
  227. nr_count_temp = nr_count[hwmon_temp];
  228. scmi_hwmon_chan = devm_kcalloc(dev, nr_types, sizeof(*scmi_hwmon_chan),
  229. GFP_KERNEL);
  230. if (!scmi_hwmon_chan)
  231. return -ENOMEM;
  232. ptr_scmi_ci = devm_kcalloc(dev, nr_types + 1, sizeof(*ptr_scmi_ci),
  233. GFP_KERNEL);
  234. if (!ptr_scmi_ci)
  235. return -ENOMEM;
  236. scmi_chip_info.info = ptr_scmi_ci;
  237. chip_info = &scmi_chip_info;
  238. for (type = 0; type < hwmon_max; type++) {
  239. if (!nr_count[type])
  240. continue;
  241. scmi_hwmon_add_chan_info(scmi_hwmon_chan, dev, nr_count[type],
  242. type, hwmon_attributes[type]);
  243. *ptr_scmi_ci++ = scmi_hwmon_chan++;
  244. scmi_sensors->info[type] =
  245. devm_kcalloc(dev, nr_count[type],
  246. sizeof(*scmi_sensors->info), GFP_KERNEL);
  247. if (!scmi_sensors->info[type])
  248. return -ENOMEM;
  249. }
  250. for (i = nr_sensors - 1; i >= 0 ; i--) {
  251. sensor = sensor_ops->info_get(ph, i);
  252. if (!sensor)
  253. continue;
  254. switch (sensor->type) {
  255. case TEMPERATURE_C:
  256. case VOLTAGE:
  257. case CURRENT:
  258. case POWER:
  259. case ENERGY:
  260. type = scmi_types[sensor->type];
  261. idx = --nr_count[type];
  262. *(scmi_sensors->info[type] + idx) = sensor;
  263. break;
  264. }
  265. }
  266. hwdev = devm_hwmon_device_register_with_info(dev, "scmi_sensors",
  267. scmi_sensors, chip_info,
  268. NULL);
  269. if (IS_ERR(hwdev))
  270. return PTR_ERR(hwdev);
  271. for (i = 0; i < nr_count_temp; i++) {
  272. int ret;
  273. sensor = *(scmi_sensors->info[hwmon_temp] + i);
  274. if (!sensor)
  275. continue;
  276. /*
  277. * Warn on any misconfiguration related to thermal zones but
  278. * bail out of probing only on memory errors.
  279. */
  280. ret = scmi_thermal_sensor_register(dev, ph, sensor);
  281. if (ret) {
  282. if (ret == -ENOMEM)
  283. return ret;
  284. dev_warn(dev,
  285. "Thermal zone misconfigured for %s. err=%d\n",
  286. sensor->name, ret);
  287. }
  288. }
  289. return 0;
  290. }
  291. static const struct scmi_device_id scmi_id_table[] = {
  292. { SCMI_PROTOCOL_SENSOR, "hwmon" },
  293. { },
  294. };
  295. MODULE_DEVICE_TABLE(scmi, scmi_id_table);
  296. static struct scmi_driver scmi_hwmon_drv = {
  297. .name = "scmi-hwmon",
  298. .probe = scmi_hwmon_probe,
  299. .id_table = scmi_id_table,
  300. };
  301. module_scmi_driver(scmi_hwmon_drv);
  302. MODULE_AUTHOR("Sudeep Holla <[email protected]>");
  303. MODULE_DESCRIPTION("ARM SCMI HWMON interface driver");
  304. MODULE_LICENSE("GPL v2");