snet_hwmon.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * SolidRun DPU driver for control plane
  4. *
  5. * Copyright (C) 2022-2023 SolidRun
  6. *
  7. * Author: Alvaro Karsz <alvaro.karsz@solid-run.com>
  8. *
  9. */
  10. #include <linux/hwmon.h>
  11. #include "snet_vdpa.h"
  12. /* Monitor offsets */
  13. #define SNET_MON_TMP0_IN_OFF 0x00
  14. #define SNET_MON_TMP0_MAX_OFF 0x08
  15. #define SNET_MON_TMP0_CRIT_OFF 0x10
  16. #define SNET_MON_TMP1_IN_OFF 0x18
  17. #define SNET_MON_TMP1_CRIT_OFF 0x20
  18. #define SNET_MON_CURR_IN_OFF 0x28
  19. #define SNET_MON_CURR_MAX_OFF 0x30
  20. #define SNET_MON_CURR_CRIT_OFF 0x38
  21. #define SNET_MON_PWR_IN_OFF 0x40
  22. #define SNET_MON_VOLT_IN_OFF 0x48
  23. #define SNET_MON_VOLT_CRIT_OFF 0x50
  24. #define SNET_MON_VOLT_LCRIT_OFF 0x58
  25. static void snet_hwmon_read_reg(struct psnet *psnet, u32 reg, long *out)
  26. {
  27. *out = psnet_read64(psnet, psnet->cfg.hwmon_off + reg);
  28. }
  29. static umode_t snet_howmon_is_visible(const void *data,
  30. enum hwmon_sensor_types type,
  31. u32 attr, int channel)
  32. {
  33. return 0444;
  34. }
  35. static int snet_howmon_read(struct device *dev, enum hwmon_sensor_types type,
  36. u32 attr, int channel, long *val)
  37. {
  38. struct psnet *psnet = dev_get_drvdata(dev);
  39. int ret = 0;
  40. switch (type) {
  41. case hwmon_in:
  42. switch (attr) {
  43. case hwmon_in_lcrit:
  44. snet_hwmon_read_reg(psnet, SNET_MON_VOLT_LCRIT_OFF, val);
  45. break;
  46. case hwmon_in_crit:
  47. snet_hwmon_read_reg(psnet, SNET_MON_VOLT_CRIT_OFF, val);
  48. break;
  49. case hwmon_in_input:
  50. snet_hwmon_read_reg(psnet, SNET_MON_VOLT_IN_OFF, val);
  51. break;
  52. default:
  53. ret = -EOPNOTSUPP;
  54. break;
  55. }
  56. break;
  57. case hwmon_power:
  58. switch (attr) {
  59. case hwmon_power_input:
  60. snet_hwmon_read_reg(psnet, SNET_MON_PWR_IN_OFF, val);
  61. break;
  62. default:
  63. ret = -EOPNOTSUPP;
  64. break;
  65. }
  66. break;
  67. case hwmon_curr:
  68. switch (attr) {
  69. case hwmon_curr_input:
  70. snet_hwmon_read_reg(psnet, SNET_MON_CURR_IN_OFF, val);
  71. break;
  72. case hwmon_curr_max:
  73. snet_hwmon_read_reg(psnet, SNET_MON_CURR_MAX_OFF, val);
  74. break;
  75. case hwmon_curr_crit:
  76. snet_hwmon_read_reg(psnet, SNET_MON_CURR_CRIT_OFF, val);
  77. break;
  78. default:
  79. ret = -EOPNOTSUPP;
  80. break;
  81. }
  82. break;
  83. case hwmon_temp:
  84. switch (attr) {
  85. case hwmon_temp_input:
  86. if (channel == 0)
  87. snet_hwmon_read_reg(psnet, SNET_MON_TMP0_IN_OFF, val);
  88. else
  89. snet_hwmon_read_reg(psnet, SNET_MON_TMP1_IN_OFF, val);
  90. break;
  91. case hwmon_temp_max:
  92. if (channel == 0)
  93. snet_hwmon_read_reg(psnet, SNET_MON_TMP0_MAX_OFF, val);
  94. else
  95. ret = -EOPNOTSUPP;
  96. break;
  97. case hwmon_temp_crit:
  98. if (channel == 0)
  99. snet_hwmon_read_reg(psnet, SNET_MON_TMP0_CRIT_OFF, val);
  100. else
  101. snet_hwmon_read_reg(psnet, SNET_MON_TMP1_CRIT_OFF, val);
  102. break;
  103. default:
  104. ret = -EOPNOTSUPP;
  105. break;
  106. }
  107. break;
  108. default:
  109. ret = -EOPNOTSUPP;
  110. break;
  111. }
  112. return ret;
  113. }
  114. static int snet_hwmon_read_string(struct device *dev,
  115. enum hwmon_sensor_types type, u32 attr,
  116. int channel, const char **str)
  117. {
  118. int ret = 0;
  119. switch (type) {
  120. case hwmon_in:
  121. *str = "main_vin";
  122. break;
  123. case hwmon_power:
  124. *str = "soc_pin";
  125. break;
  126. case hwmon_curr:
  127. *str = "soc_iin";
  128. break;
  129. case hwmon_temp:
  130. if (channel == 0)
  131. *str = "power_stage_temp";
  132. else
  133. *str = "ic_junction_temp";
  134. break;
  135. default:
  136. ret = -EOPNOTSUPP;
  137. break;
  138. }
  139. return ret;
  140. }
  141. static const struct hwmon_ops snet_hwmon_ops = {
  142. .is_visible = snet_howmon_is_visible,
  143. .read = snet_howmon_read,
  144. .read_string = snet_hwmon_read_string
  145. };
  146. static const struct hwmon_channel_info * const snet_hwmon_info[] = {
  147. HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT | HWMON_T_LABEL,
  148. HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_LABEL),
  149. HWMON_CHANNEL_INFO(power, HWMON_P_INPUT | HWMON_P_LABEL),
  150. HWMON_CHANNEL_INFO(curr, HWMON_C_INPUT | HWMON_C_MAX | HWMON_C_CRIT | HWMON_C_LABEL),
  151. HWMON_CHANNEL_INFO(in, HWMON_I_INPUT | HWMON_I_CRIT | HWMON_I_LCRIT | HWMON_I_LABEL),
  152. NULL
  153. };
  154. static const struct hwmon_chip_info snet_hwmono_info = {
  155. .ops = &snet_hwmon_ops,
  156. .info = snet_hwmon_info,
  157. };
  158. /* Create an HW monitor device */
  159. void psnet_create_hwmon(struct pci_dev *pdev)
  160. {
  161. struct device *hwmon;
  162. struct psnet *psnet = pci_get_drvdata(pdev);
  163. snprintf(psnet->hwmon_name, SNET_NAME_SIZE, "snet_%s", pci_name(pdev));
  164. hwmon = devm_hwmon_device_register_with_info(&pdev->dev, psnet->hwmon_name, psnet,
  165. &snet_hwmono_info, NULL);
  166. /* The monitor is not mandatory, Just alert user in case of an error */
  167. if (IS_ERR(hwmon))
  168. SNET_WARN(pdev, "Failed to create SNET hwmon, error %ld\n", PTR_ERR(hwmon));
  169. }