intel-m10-bmc-hwmon.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Intel MAX 10 BMC HWMON Driver
  4. *
  5. * Copyright (C) 2018-2020 Intel Corporation. All rights reserved.
  6. *
  7. */
  8. #include <linux/device.h>
  9. #include <linux/hwmon.h>
  10. #include <linux/mfd/intel-m10-bmc.h>
  11. #include <linux/module.h>
  12. #include <linux/mod_devicetable.h>
  13. #include <linux/platform_device.h>
  14. struct m10bmc_sdata {
  15. unsigned int reg_input;
  16. unsigned int reg_max;
  17. unsigned int reg_crit;
  18. unsigned int reg_hyst;
  19. unsigned int reg_min;
  20. unsigned int multiplier;
  21. const char *label;
  22. };
  23. struct m10bmc_hwmon_board_data {
  24. const struct m10bmc_sdata *tables[hwmon_max];
  25. const struct hwmon_channel_info **hinfo;
  26. };
  27. struct m10bmc_hwmon {
  28. struct device *dev;
  29. struct hwmon_chip_info chip;
  30. char *hw_name;
  31. struct intel_m10bmc *m10bmc;
  32. const struct m10bmc_hwmon_board_data *bdata;
  33. };
  34. static const struct m10bmc_sdata n3000bmc_temp_tbl[] = {
  35. { 0x100, 0x104, 0x108, 0x10c, 0x0, 500, "Board Temperature" },
  36. { 0x110, 0x114, 0x118, 0x0, 0x0, 500, "FPGA Die Temperature" },
  37. { 0x11c, 0x124, 0x120, 0x0, 0x0, 500, "QSFP0 Temperature" },
  38. { 0x12c, 0x134, 0x130, 0x0, 0x0, 500, "QSFP1 Temperature" },
  39. { 0x168, 0x0, 0x0, 0x0, 0x0, 500, "Retimer A Temperature" },
  40. { 0x16c, 0x0, 0x0, 0x0, 0x0, 500, "Retimer A SerDes Temperature" },
  41. { 0x170, 0x0, 0x0, 0x0, 0x0, 500, "Retimer B Temperature" },
  42. { 0x174, 0x0, 0x0, 0x0, 0x0, 500, "Retimer B SerDes Temperature" },
  43. };
  44. static const struct m10bmc_sdata n3000bmc_in_tbl[] = {
  45. { 0x128, 0x0, 0x0, 0x0, 0x0, 1, "QSFP0 Supply Voltage" },
  46. { 0x138, 0x0, 0x0, 0x0, 0x0, 1, "QSFP1 Supply Voltage" },
  47. { 0x13c, 0x0, 0x0, 0x0, 0x0, 1, "FPGA Core Voltage" },
  48. { 0x144, 0x0, 0x0, 0x0, 0x0, 1, "12V Backplane Voltage" },
  49. { 0x14c, 0x0, 0x0, 0x0, 0x0, 1, "1.2V Voltage" },
  50. { 0x150, 0x0, 0x0, 0x0, 0x0, 1, "12V AUX Voltage" },
  51. { 0x158, 0x0, 0x0, 0x0, 0x0, 1, "1.8V Voltage" },
  52. { 0x15c, 0x0, 0x0, 0x0, 0x0, 1, "3.3V Voltage" },
  53. };
  54. static const struct m10bmc_sdata n3000bmc_curr_tbl[] = {
  55. { 0x140, 0x0, 0x0, 0x0, 0x0, 1, "FPGA Core Current" },
  56. { 0x148, 0x0, 0x0, 0x0, 0x0, 1, "12V Backplane Current" },
  57. { 0x154, 0x0, 0x0, 0x0, 0x0, 1, "12V AUX Current" },
  58. };
  59. static const struct m10bmc_sdata n3000bmc_power_tbl[] = {
  60. { 0x160, 0x0, 0x0, 0x0, 0x0, 1000, "Board Power" },
  61. };
  62. static const struct hwmon_channel_info *n3000bmc_hinfo[] = {
  63. HWMON_CHANNEL_INFO(temp,
  64. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST |
  65. HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_LABEL,
  66. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
  67. HWMON_T_LABEL,
  68. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
  69. HWMON_T_LABEL,
  70. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
  71. HWMON_T_LABEL,
  72. HWMON_T_INPUT | HWMON_T_LABEL,
  73. HWMON_T_INPUT | HWMON_T_LABEL,
  74. HWMON_T_INPUT | HWMON_T_LABEL,
  75. HWMON_T_INPUT | HWMON_T_LABEL),
  76. HWMON_CHANNEL_INFO(in,
  77. HWMON_I_INPUT | HWMON_I_LABEL,
  78. HWMON_I_INPUT | HWMON_I_LABEL,
  79. HWMON_I_INPUT | HWMON_I_LABEL,
  80. HWMON_I_INPUT | HWMON_I_LABEL,
  81. HWMON_I_INPUT | HWMON_I_LABEL,
  82. HWMON_I_INPUT | HWMON_I_LABEL,
  83. HWMON_I_INPUT | HWMON_I_LABEL,
  84. HWMON_I_INPUT | HWMON_I_LABEL),
  85. HWMON_CHANNEL_INFO(curr,
  86. HWMON_C_INPUT | HWMON_C_LABEL,
  87. HWMON_C_INPUT | HWMON_C_LABEL,
  88. HWMON_C_INPUT | HWMON_C_LABEL),
  89. HWMON_CHANNEL_INFO(power,
  90. HWMON_P_INPUT | HWMON_P_LABEL),
  91. NULL
  92. };
  93. static const struct m10bmc_sdata d5005bmc_temp_tbl[] = {
  94. { 0x100, 0x104, 0x108, 0x10c, 0x0, 500, "Board Inlet Air Temperature" },
  95. { 0x110, 0x114, 0x118, 0x0, 0x0, 500, "FPGA Core Temperature" },
  96. { 0x11c, 0x120, 0x124, 0x128, 0x0, 500, "Board Exhaust Air Temperature" },
  97. { 0x12c, 0x130, 0x134, 0x0, 0x0, 500, "FPGA Transceiver Temperature" },
  98. { 0x138, 0x13c, 0x140, 0x144, 0x0, 500, "RDIMM0 Temperature" },
  99. { 0x148, 0x14c, 0x150, 0x154, 0x0, 500, "RDIMM1 Temperature" },
  100. { 0x158, 0x15c, 0x160, 0x164, 0x0, 500, "RDIMM2 Temperature" },
  101. { 0x168, 0x16c, 0x170, 0x174, 0x0, 500, "RDIMM3 Temperature" },
  102. { 0x178, 0x17c, 0x180, 0x0, 0x0, 500, "QSFP0 Temperature" },
  103. { 0x188, 0x18c, 0x190, 0x0, 0x0, 500, "QSFP1 Temperature" },
  104. { 0x1a0, 0x1a4, 0x1a8, 0x0, 0x0, 500, "3.3v Temperature" },
  105. { 0x1bc, 0x1c0, 0x1c4, 0x0, 0x0, 500, "VCCERAM Temperature" },
  106. { 0x1d8, 0x1dc, 0x1e0, 0x0, 0x0, 500, "VCCR Temperature" },
  107. { 0x1f4, 0x1f8, 0x1fc, 0x0, 0x0, 500, "VCCT Temperature" },
  108. { 0x210, 0x214, 0x218, 0x0, 0x0, 500, "1.8v Temperature" },
  109. { 0x22c, 0x230, 0x234, 0x0, 0x0, 500, "12v Backplane Temperature" },
  110. { 0x248, 0x24c, 0x250, 0x0, 0x0, 500, "12v AUX Temperature" },
  111. };
  112. static const struct m10bmc_sdata d5005bmc_in_tbl[] = {
  113. { 0x184, 0x0, 0x0, 0x0, 0x0, 1, "QSFP0 Supply Voltage" },
  114. { 0x194, 0x0, 0x0, 0x0, 0x0, 1, "QSFP1 Supply Voltage" },
  115. { 0x198, 0x0, 0x0, 0x0, 0x0, 1, "FPGA Core Voltage" },
  116. { 0x1ac, 0x1b0, 0x1b4, 0x0, 0x0, 1, "3.3v Voltage" },
  117. { 0x1c8, 0x1cc, 0x1d0, 0x0, 0x0, 1, "VCCERAM Voltage" },
  118. { 0x1e4, 0x1e8, 0x1ec, 0x0, 0x0, 1, "VCCR Voltage" },
  119. { 0x200, 0x204, 0x208, 0x0, 0x0, 1, "VCCT Voltage" },
  120. { 0x21c, 0x220, 0x224, 0x0, 0x0, 1, "1.8v Voltage" },
  121. { 0x238, 0x0, 0x0, 0x0, 0x23c, 1, "12v Backplane Voltage" },
  122. { 0x254, 0x0, 0x0, 0x0, 0x258, 1, "12v AUX Voltage" },
  123. };
  124. static const struct m10bmc_sdata d5005bmc_curr_tbl[] = {
  125. { 0x19c, 0x0, 0x0, 0x0, 0x0, 1, "FPGA Core Current" },
  126. { 0x1b8, 0x0, 0x0, 0x0, 0x0, 1, "3.3v Current" },
  127. { 0x1d4, 0x0, 0x0, 0x0, 0x0, 1, "VCCERAM Current" },
  128. { 0x1f0, 0x0, 0x0, 0x0, 0x0, 1, "VCCR Current" },
  129. { 0x20c, 0x0, 0x0, 0x0, 0x0, 1, "VCCT Current" },
  130. { 0x228, 0x0, 0x0, 0x0, 0x0, 1, "1.8v Current" },
  131. { 0x240, 0x244, 0x0, 0x0, 0x0, 1, "12v Backplane Current" },
  132. { 0x25c, 0x260, 0x0, 0x0, 0x0, 1, "12v AUX Current" },
  133. };
  134. static const struct m10bmc_hwmon_board_data n3000bmc_hwmon_bdata = {
  135. .tables = {
  136. [hwmon_temp] = n3000bmc_temp_tbl,
  137. [hwmon_in] = n3000bmc_in_tbl,
  138. [hwmon_curr] = n3000bmc_curr_tbl,
  139. [hwmon_power] = n3000bmc_power_tbl,
  140. },
  141. .hinfo = n3000bmc_hinfo,
  142. };
  143. static const struct hwmon_channel_info *d5005bmc_hinfo[] = {
  144. HWMON_CHANNEL_INFO(temp,
  145. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST |
  146. HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_LABEL,
  147. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
  148. HWMON_T_LABEL,
  149. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST |
  150. HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_LABEL,
  151. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
  152. HWMON_T_LABEL,
  153. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST |
  154. HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_LABEL,
  155. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST |
  156. HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_LABEL,
  157. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST |
  158. HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_LABEL,
  159. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST |
  160. HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_LABEL,
  161. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
  162. HWMON_T_LABEL,
  163. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
  164. HWMON_T_LABEL,
  165. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
  166. HWMON_T_LABEL,
  167. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
  168. HWMON_T_LABEL,
  169. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
  170. HWMON_T_LABEL,
  171. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
  172. HWMON_T_LABEL,
  173. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
  174. HWMON_T_LABEL,
  175. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
  176. HWMON_T_LABEL,
  177. HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
  178. HWMON_T_LABEL),
  179. HWMON_CHANNEL_INFO(in,
  180. HWMON_I_INPUT | HWMON_I_LABEL,
  181. HWMON_I_INPUT | HWMON_I_LABEL,
  182. HWMON_I_INPUT | HWMON_I_LABEL,
  183. HWMON_I_INPUT | HWMON_I_MAX | HWMON_I_CRIT |
  184. HWMON_I_LABEL,
  185. HWMON_I_INPUT | HWMON_I_MAX | HWMON_I_CRIT |
  186. HWMON_I_LABEL,
  187. HWMON_I_INPUT | HWMON_I_MAX | HWMON_I_CRIT |
  188. HWMON_I_LABEL,
  189. HWMON_I_INPUT | HWMON_I_MAX | HWMON_I_CRIT |
  190. HWMON_I_LABEL,
  191. HWMON_I_INPUT | HWMON_I_MAX | HWMON_I_CRIT |
  192. HWMON_I_LABEL,
  193. HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_LABEL,
  194. HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_LABEL),
  195. HWMON_CHANNEL_INFO(curr,
  196. HWMON_C_INPUT | HWMON_C_LABEL,
  197. HWMON_C_INPUT | HWMON_C_LABEL,
  198. HWMON_C_INPUT | HWMON_C_LABEL,
  199. HWMON_C_INPUT | HWMON_C_LABEL,
  200. HWMON_C_INPUT | HWMON_C_LABEL,
  201. HWMON_C_INPUT | HWMON_C_LABEL,
  202. HWMON_C_INPUT | HWMON_C_MAX | HWMON_C_LABEL,
  203. HWMON_C_INPUT | HWMON_C_MAX | HWMON_C_LABEL),
  204. NULL
  205. };
  206. static const struct m10bmc_hwmon_board_data d5005bmc_hwmon_bdata = {
  207. .tables = {
  208. [hwmon_temp] = d5005bmc_temp_tbl,
  209. [hwmon_in] = d5005bmc_in_tbl,
  210. [hwmon_curr] = d5005bmc_curr_tbl,
  211. },
  212. .hinfo = d5005bmc_hinfo,
  213. };
  214. static const struct m10bmc_sdata n5010bmc_temp_tbl[] = {
  215. { 0x100, 0x0, 0x104, 0x0, 0x0, 1000, "Board Local Temperature" },
  216. { 0x108, 0x0, 0x10c, 0x0, 0x0, 1000, "FPGA 1 Temperature" },
  217. { 0x110, 0x0, 0x114, 0x0, 0x0, 1000, "FPGA 2 Temperature" },
  218. { 0x118, 0x0, 0x0, 0x0, 0x0, 1000, "Card Top Temperature" },
  219. { 0x11c, 0x0, 0x0, 0x0, 0x0, 1000, "Card Bottom Temperature" },
  220. { 0x128, 0x0, 0x0, 0x0, 0x0, 1000, "FPGA 1.2V Temperature" },
  221. { 0x134, 0x0, 0x0, 0x0, 0x0, 1000, "FPGA 5V Temperature" },
  222. { 0x140, 0x0, 0x0, 0x0, 0x0, 1000, "FPGA 0.9V Temperature" },
  223. { 0x14c, 0x0, 0x0, 0x0, 0x0, 1000, "FPGA 0.85V Temperature" },
  224. { 0x158, 0x0, 0x0, 0x0, 0x0, 1000, "AUX 12V Temperature" },
  225. { 0x164, 0x0, 0x0, 0x0, 0x0, 1000, "Backplane 12V Temperature" },
  226. { 0x1a8, 0x0, 0x0, 0x0, 0x0, 1000, "QSFP28-1 Temperature" },
  227. { 0x1ac, 0x0, 0x0, 0x0, 0x0, 1000, "QSFP28-2 Temperature" },
  228. { 0x1b0, 0x0, 0x0, 0x0, 0x0, 1000, "QSFP28-3 Temperature" },
  229. { 0x1b4, 0x0, 0x0, 0x0, 0x0, 1000, "QSFP28-4 Temperature" },
  230. { 0x1b8, 0x0, 0x0, 0x0, 0x0, 1000, "CVL1 Internal Temperature" },
  231. { 0x1bc, 0x0, 0x0, 0x0, 0x0, 1000, "CVL2 Internal Temperature" },
  232. };
  233. static const struct m10bmc_sdata n5010bmc_in_tbl[] = {
  234. { 0x120, 0x0, 0x0, 0x0, 0x0, 1, "FPGA 1.2V Voltage" },
  235. { 0x12c, 0x0, 0x0, 0x0, 0x0, 1, "FPGA 5V Voltage" },
  236. { 0x138, 0x0, 0x0, 0x0, 0x0, 1, "FPGA 0.9V Voltage" },
  237. { 0x144, 0x0, 0x0, 0x0, 0x0, 1, "FPGA 0.85V Voltage" },
  238. { 0x150, 0x0, 0x0, 0x0, 0x0, 1, "AUX 12V Voltage" },
  239. { 0x15c, 0x0, 0x0, 0x0, 0x0, 1, "Backplane 12V Voltage" },
  240. { 0x16c, 0x0, 0x0, 0x0, 0x0, 1, "DDR4 1.2V Voltage" },
  241. { 0x17c, 0x0, 0x0, 0x0, 0x0, 1, "FPGA 1.8V Voltage" },
  242. { 0x184, 0x0, 0x0, 0x0, 0x0, 1, "QDR 1.3V Voltage" },
  243. { 0x18c, 0x0, 0x0, 0x0, 0x0, 1, "CVL1 0.8V Voltage" },
  244. { 0x194, 0x0, 0x0, 0x0, 0x0, 1, "CVL1 1.05V Voltage" },
  245. { 0x19c, 0x0, 0x0, 0x0, 0x0, 1, "CVL2 1.05V Voltage" },
  246. { 0x1a4, 0x0, 0x0, 0x0, 0x0, 1, "CVL2 0.8V Voltage" },
  247. };
  248. static const struct m10bmc_sdata n5010bmc_curr_tbl[] = {
  249. { 0x124, 0x0, 0x0, 0x0, 0x0, 1, "FPGA 1.2V Current" },
  250. { 0x130, 0x0, 0x0, 0x0, 0x0, 1, "FPGA 5V Current" },
  251. { 0x13c, 0x0, 0x0, 0x0, 0x0, 1, "FPGA 0.9V Current" },
  252. { 0x148, 0x0, 0x0, 0x0, 0x0, 1, "FPGA 0.85V Current" },
  253. { 0x154, 0x0, 0x0, 0x0, 0x0, 1, "AUX 12V Current" },
  254. { 0x160, 0x0, 0x0, 0x0, 0x0, 1, "Backplane 12V Current" },
  255. { 0x168, 0x0, 0x0, 0x0, 0x0, 1, "DDR4 1.2V Current" },
  256. { 0x178, 0x0, 0x0, 0x0, 0x0, 1, "FPGA 1.8V Current" },
  257. { 0x180, 0x0, 0x0, 0x0, 0x0, 1, "QDR 1.3V Current" },
  258. { 0x188, 0x0, 0x0, 0x0, 0x0, 1, "CVL1 0.8V Current" },
  259. { 0x190, 0x0, 0x0, 0x0, 0x0, 1, "CVL1 1.05V Current" },
  260. { 0x198, 0x0, 0x0, 0x0, 0x0, 1, "CVL2 1.05V Current" },
  261. { 0x1a0, 0x0, 0x0, 0x0, 0x0, 1, "CVL2 0.8V Current" },
  262. };
  263. static const struct hwmon_channel_info *n5010bmc_hinfo[] = {
  264. HWMON_CHANNEL_INFO(temp,
  265. HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_LABEL,
  266. HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_LABEL,
  267. HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_LABEL,
  268. HWMON_T_INPUT | HWMON_T_LABEL,
  269. HWMON_T_INPUT | HWMON_T_LABEL,
  270. HWMON_T_INPUT | HWMON_T_LABEL,
  271. HWMON_T_INPUT | HWMON_T_LABEL,
  272. HWMON_T_INPUT | HWMON_T_LABEL,
  273. HWMON_T_INPUT | HWMON_T_LABEL,
  274. HWMON_T_INPUT | HWMON_T_LABEL,
  275. HWMON_T_INPUT | HWMON_T_LABEL,
  276. HWMON_T_INPUT | HWMON_T_LABEL,
  277. HWMON_T_INPUT | HWMON_T_LABEL,
  278. HWMON_T_INPUT | HWMON_T_LABEL,
  279. HWMON_T_INPUT | HWMON_T_LABEL,
  280. HWMON_T_INPUT | HWMON_T_LABEL,
  281. HWMON_T_INPUT | HWMON_T_LABEL),
  282. HWMON_CHANNEL_INFO(in,
  283. HWMON_I_INPUT | HWMON_I_LABEL,
  284. HWMON_I_INPUT | HWMON_I_LABEL,
  285. HWMON_I_INPUT | HWMON_I_LABEL,
  286. HWMON_I_INPUT | HWMON_I_LABEL,
  287. HWMON_I_INPUT | HWMON_I_LABEL,
  288. HWMON_I_INPUT | HWMON_I_LABEL,
  289. HWMON_I_INPUT | HWMON_I_LABEL,
  290. HWMON_I_INPUT | HWMON_I_LABEL,
  291. HWMON_I_INPUT | HWMON_I_LABEL,
  292. HWMON_I_INPUT | HWMON_I_LABEL,
  293. HWMON_I_INPUT | HWMON_I_LABEL,
  294. HWMON_I_INPUT | HWMON_I_LABEL,
  295. HWMON_I_INPUT | HWMON_I_LABEL),
  296. HWMON_CHANNEL_INFO(curr,
  297. HWMON_C_INPUT | HWMON_C_LABEL,
  298. HWMON_C_INPUT | HWMON_C_LABEL,
  299. HWMON_C_INPUT | HWMON_C_LABEL,
  300. HWMON_C_INPUT | HWMON_C_LABEL,
  301. HWMON_C_INPUT | HWMON_C_LABEL,
  302. HWMON_C_INPUT | HWMON_C_LABEL,
  303. HWMON_C_INPUT | HWMON_C_LABEL,
  304. HWMON_C_INPUT | HWMON_C_LABEL,
  305. HWMON_C_INPUT | HWMON_C_LABEL,
  306. HWMON_C_INPUT | HWMON_C_LABEL,
  307. HWMON_C_INPUT | HWMON_C_LABEL,
  308. HWMON_C_INPUT | HWMON_C_LABEL,
  309. HWMON_C_INPUT | HWMON_C_LABEL),
  310. NULL
  311. };
  312. static const struct m10bmc_hwmon_board_data n5010bmc_hwmon_bdata = {
  313. .tables = {
  314. [hwmon_temp] = n5010bmc_temp_tbl,
  315. [hwmon_in] = n5010bmc_in_tbl,
  316. [hwmon_curr] = n5010bmc_curr_tbl,
  317. },
  318. .hinfo = n5010bmc_hinfo,
  319. };
  320. static umode_t
  321. m10bmc_hwmon_is_visible(const void *data, enum hwmon_sensor_types type,
  322. u32 attr, int channel)
  323. {
  324. return 0444;
  325. }
  326. static const struct m10bmc_sdata *
  327. find_sensor_data(struct m10bmc_hwmon *hw, enum hwmon_sensor_types type,
  328. int channel)
  329. {
  330. const struct m10bmc_sdata *tbl;
  331. tbl = hw->bdata->tables[type];
  332. if (!tbl)
  333. return ERR_PTR(-EOPNOTSUPP);
  334. return &tbl[channel];
  335. }
  336. static int do_sensor_read(struct m10bmc_hwmon *hw,
  337. const struct m10bmc_sdata *data,
  338. unsigned int regoff, long *val)
  339. {
  340. unsigned int regval;
  341. int ret;
  342. ret = m10bmc_sys_read(hw->m10bmc, regoff, &regval);
  343. if (ret)
  344. return ret;
  345. /*
  346. * BMC Firmware will return 0xdeadbeef if the sensor value is invalid
  347. * at that time. This usually happens on sensor channels which connect
  348. * to external pluggable modules, e.g. QSFP temperature and voltage.
  349. * When the QSFP is unplugged from cage, driver will get 0xdeadbeef
  350. * from their registers.
  351. */
  352. if (regval == 0xdeadbeef)
  353. return -ENODATA;
  354. *val = regval * data->multiplier;
  355. return 0;
  356. }
  357. static int m10bmc_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
  358. u32 attr, int channel, long *val)
  359. {
  360. struct m10bmc_hwmon *hw = dev_get_drvdata(dev);
  361. unsigned int reg = 0, reg_hyst = 0;
  362. const struct m10bmc_sdata *data;
  363. long hyst, value;
  364. int ret;
  365. data = find_sensor_data(hw, type, channel);
  366. if (IS_ERR(data))
  367. return PTR_ERR(data);
  368. switch (type) {
  369. case hwmon_temp:
  370. switch (attr) {
  371. case hwmon_temp_input:
  372. reg = data->reg_input;
  373. break;
  374. case hwmon_temp_max_hyst:
  375. reg_hyst = data->reg_hyst;
  376. fallthrough;
  377. case hwmon_temp_max:
  378. reg = data->reg_max;
  379. break;
  380. case hwmon_temp_crit_hyst:
  381. reg_hyst = data->reg_hyst;
  382. fallthrough;
  383. case hwmon_temp_crit:
  384. reg = data->reg_crit;
  385. break;
  386. default:
  387. return -EOPNOTSUPP;
  388. }
  389. break;
  390. case hwmon_in:
  391. switch (attr) {
  392. case hwmon_in_input:
  393. reg = data->reg_input;
  394. break;
  395. case hwmon_in_max:
  396. reg = data->reg_max;
  397. break;
  398. case hwmon_in_crit:
  399. reg = data->reg_crit;
  400. break;
  401. case hwmon_in_min:
  402. reg = data->reg_min;
  403. break;
  404. default:
  405. return -EOPNOTSUPP;
  406. }
  407. break;
  408. case hwmon_curr:
  409. switch (attr) {
  410. case hwmon_curr_input:
  411. reg = data->reg_input;
  412. break;
  413. case hwmon_curr_max:
  414. reg = data->reg_max;
  415. break;
  416. case hwmon_curr_crit:
  417. reg = data->reg_crit;
  418. break;
  419. default:
  420. return -EOPNOTSUPP;
  421. }
  422. break;
  423. case hwmon_power:
  424. switch (attr) {
  425. case hwmon_power_input:
  426. reg = data->reg_input;
  427. break;
  428. default:
  429. return -EOPNOTSUPP;
  430. }
  431. break;
  432. default:
  433. return -EOPNOTSUPP;
  434. }
  435. if (!reg)
  436. return -EOPNOTSUPP;
  437. ret = do_sensor_read(hw, data, reg, &value);
  438. if (ret)
  439. return ret;
  440. if (reg_hyst) {
  441. ret = do_sensor_read(hw, data, reg_hyst, &hyst);
  442. if (ret)
  443. return ret;
  444. value -= hyst;
  445. }
  446. *val = value;
  447. return 0;
  448. }
  449. static int m10bmc_hwmon_read_string(struct device *dev,
  450. enum hwmon_sensor_types type,
  451. u32 attr, int channel, const char **str)
  452. {
  453. struct m10bmc_hwmon *hw = dev_get_drvdata(dev);
  454. const struct m10bmc_sdata *data;
  455. data = find_sensor_data(hw, type, channel);
  456. if (IS_ERR(data))
  457. return PTR_ERR(data);
  458. *str = data->label;
  459. return 0;
  460. }
  461. static const struct hwmon_ops m10bmc_hwmon_ops = {
  462. .is_visible = m10bmc_hwmon_is_visible,
  463. .read = m10bmc_hwmon_read,
  464. .read_string = m10bmc_hwmon_read_string,
  465. };
  466. static int m10bmc_hwmon_probe(struct platform_device *pdev)
  467. {
  468. const struct platform_device_id *id = platform_get_device_id(pdev);
  469. struct intel_m10bmc *m10bmc = dev_get_drvdata(pdev->dev.parent);
  470. struct device *hwmon_dev, *dev = &pdev->dev;
  471. struct m10bmc_hwmon *hw;
  472. hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
  473. if (!hw)
  474. return -ENOMEM;
  475. hw->dev = dev;
  476. hw->m10bmc = m10bmc;
  477. hw->bdata = (const struct m10bmc_hwmon_board_data *)id->driver_data;
  478. hw->chip.info = hw->bdata->hinfo;
  479. hw->chip.ops = &m10bmc_hwmon_ops;
  480. hw->hw_name = devm_hwmon_sanitize_name(dev, id->name);
  481. if (IS_ERR(hw->hw_name))
  482. return PTR_ERR(hw->hw_name);
  483. hwmon_dev = devm_hwmon_device_register_with_info(dev, hw->hw_name,
  484. hw, &hw->chip, NULL);
  485. return PTR_ERR_OR_ZERO(hwmon_dev);
  486. }
  487. static const struct platform_device_id intel_m10bmc_hwmon_ids[] = {
  488. {
  489. .name = "n3000bmc-hwmon",
  490. .driver_data = (unsigned long)&n3000bmc_hwmon_bdata,
  491. },
  492. {
  493. .name = "d5005bmc-hwmon",
  494. .driver_data = (unsigned long)&d5005bmc_hwmon_bdata,
  495. },
  496. {
  497. .name = "n5010bmc-hwmon",
  498. .driver_data = (unsigned long)&n5010bmc_hwmon_bdata,
  499. },
  500. { }
  501. };
  502. static struct platform_driver intel_m10bmc_hwmon_driver = {
  503. .probe = m10bmc_hwmon_probe,
  504. .driver = {
  505. .name = "intel-m10-bmc-hwmon",
  506. },
  507. .id_table = intel_m10bmc_hwmon_ids,
  508. };
  509. module_platform_driver(intel_m10bmc_hwmon_driver);
  510. MODULE_DEVICE_TABLE(platform, intel_m10bmc_hwmon_ids);
  511. MODULE_AUTHOR("Intel Corporation");
  512. MODULE_DESCRIPTION("Intel MAX 10 BMC hardware monitor");
  513. MODULE_LICENSE("GPL");