core_hwmon.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /* Copyright (c) 2015-2018 Mellanox Technologies. All rights reserved */
  3. #include <linux/kernel.h>
  4. #include <linux/types.h>
  5. #include <linux/device.h>
  6. #include <linux/sysfs.h>
  7. #include <linux/hwmon.h>
  8. #include <linux/err.h>
  9. #include "core.h"
  10. #define MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT 127
  11. #define MLXSW_HWMON_ATTR_COUNT (MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT * 4 + \
  12. MLXSW_MFCR_TACHOS_MAX + MLXSW_MFCR_PWMS_MAX)
  13. struct mlxsw_hwmon_attr {
  14. struct device_attribute dev_attr;
  15. struct mlxsw_hwmon *hwmon;
  16. unsigned int type_index;
  17. char name[32];
  18. };
  19. struct mlxsw_hwmon {
  20. struct mlxsw_core *core;
  21. const struct mlxsw_bus_info *bus_info;
  22. struct device *hwmon_dev;
  23. struct attribute_group group;
  24. const struct attribute_group *groups[2];
  25. struct attribute *attrs[MLXSW_HWMON_ATTR_COUNT + 1];
  26. struct mlxsw_hwmon_attr hwmon_attrs[MLXSW_HWMON_ATTR_COUNT];
  27. unsigned int attrs_count;
  28. };
  29. static ssize_t mlxsw_hwmon_temp_show(struct device *dev,
  30. struct device_attribute *attr,
  31. char *buf)
  32. {
  33. struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
  34. container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
  35. struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
  36. char mtmp_pl[MLXSW_REG_MTMP_LEN];
  37. unsigned int temp;
  38. int err;
  39. mlxsw_reg_mtmp_pack(mtmp_pl, mlwsw_hwmon_attr->type_index,
  40. false, false);
  41. err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
  42. if (err) {
  43. dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n");
  44. return err;
  45. }
  46. mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
  47. return sprintf(buf, "%u\n", temp);
  48. }
  49. static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev,
  50. struct device_attribute *attr,
  51. char *buf)
  52. {
  53. struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
  54. container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
  55. struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
  56. char mtmp_pl[MLXSW_REG_MTMP_LEN];
  57. unsigned int temp_max;
  58. int err;
  59. mlxsw_reg_mtmp_pack(mtmp_pl, mlwsw_hwmon_attr->type_index,
  60. false, false);
  61. err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
  62. if (err) {
  63. dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n");
  64. return err;
  65. }
  66. mlxsw_reg_mtmp_unpack(mtmp_pl, NULL, &temp_max, NULL);
  67. return sprintf(buf, "%u\n", temp_max);
  68. }
  69. static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev,
  70. struct device_attribute *attr,
  71. const char *buf, size_t len)
  72. {
  73. struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
  74. container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
  75. struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
  76. char mtmp_pl[MLXSW_REG_MTMP_LEN];
  77. unsigned long val;
  78. int err;
  79. err = kstrtoul(buf, 10, &val);
  80. if (err)
  81. return err;
  82. if (val != 1)
  83. return -EINVAL;
  84. mlxsw_reg_mtmp_pack(mtmp_pl, mlwsw_hwmon_attr->type_index, true, true);
  85. err = mlxsw_reg_write(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
  86. if (err) {
  87. dev_err(mlxsw_hwmon->bus_info->dev, "Failed to reset temp sensor history\n");
  88. return err;
  89. }
  90. return len;
  91. }
  92. static ssize_t mlxsw_hwmon_fan_rpm_show(struct device *dev,
  93. struct device_attribute *attr,
  94. char *buf)
  95. {
  96. struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
  97. container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
  98. struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
  99. char mfsm_pl[MLXSW_REG_MFSM_LEN];
  100. int err;
  101. mlxsw_reg_mfsm_pack(mfsm_pl, mlwsw_hwmon_attr->type_index);
  102. err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfsm), mfsm_pl);
  103. if (err) {
  104. dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query fan\n");
  105. return err;
  106. }
  107. return sprintf(buf, "%u\n", mlxsw_reg_mfsm_rpm_get(mfsm_pl));
  108. }
  109. static ssize_t mlxsw_hwmon_pwm_show(struct device *dev,
  110. struct device_attribute *attr,
  111. char *buf)
  112. {
  113. struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
  114. container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
  115. struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
  116. char mfsc_pl[MLXSW_REG_MFSC_LEN];
  117. int err;
  118. mlxsw_reg_mfsc_pack(mfsc_pl, mlwsw_hwmon_attr->type_index, 0);
  119. err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfsc), mfsc_pl);
  120. if (err) {
  121. dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query PWM\n");
  122. return err;
  123. }
  124. return sprintf(buf, "%u\n",
  125. mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl));
  126. }
  127. static ssize_t mlxsw_hwmon_pwm_store(struct device *dev,
  128. struct device_attribute *attr,
  129. const char *buf, size_t len)
  130. {
  131. struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
  132. container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
  133. struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
  134. char mfsc_pl[MLXSW_REG_MFSC_LEN];
  135. unsigned long val;
  136. int err;
  137. err = kstrtoul(buf, 10, &val);
  138. if (err)
  139. return err;
  140. if (val > 255)
  141. return -EINVAL;
  142. mlxsw_reg_mfsc_pack(mfsc_pl, mlwsw_hwmon_attr->type_index, val);
  143. err = mlxsw_reg_write(mlxsw_hwmon->core, MLXSW_REG(mfsc), mfsc_pl);
  144. if (err) {
  145. dev_err(mlxsw_hwmon->bus_info->dev, "Failed to write PWM\n");
  146. return err;
  147. }
  148. return len;
  149. }
  150. enum mlxsw_hwmon_attr_type {
  151. MLXSW_HWMON_ATTR_TYPE_TEMP,
  152. MLXSW_HWMON_ATTR_TYPE_TEMP_MAX,
  153. MLXSW_HWMON_ATTR_TYPE_TEMP_RST,
  154. MLXSW_HWMON_ATTR_TYPE_FAN_RPM,
  155. MLXSW_HWMON_ATTR_TYPE_PWM,
  156. };
  157. static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon,
  158. enum mlxsw_hwmon_attr_type attr_type,
  159. unsigned int type_index, unsigned int num) {
  160. struct mlxsw_hwmon_attr *mlxsw_hwmon_attr;
  161. unsigned int attr_index;
  162. attr_index = mlxsw_hwmon->attrs_count;
  163. mlxsw_hwmon_attr = &mlxsw_hwmon->hwmon_attrs[attr_index];
  164. switch (attr_type) {
  165. case MLXSW_HWMON_ATTR_TYPE_TEMP:
  166. mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_temp_show;
  167. mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
  168. snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
  169. "temp%u_input", num + 1);
  170. break;
  171. case MLXSW_HWMON_ATTR_TYPE_TEMP_MAX:
  172. mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_temp_max_show;
  173. mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
  174. snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
  175. "temp%u_highest", num + 1);
  176. break;
  177. case MLXSW_HWMON_ATTR_TYPE_TEMP_RST:
  178. mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_temp_rst_store;
  179. mlxsw_hwmon_attr->dev_attr.attr.mode = 0200;
  180. snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
  181. "temp%u_reset_history", num + 1);
  182. break;
  183. case MLXSW_HWMON_ATTR_TYPE_FAN_RPM:
  184. mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_fan_rpm_show;
  185. mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
  186. snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
  187. "fan%u_input", num + 1);
  188. break;
  189. case MLXSW_HWMON_ATTR_TYPE_PWM:
  190. mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_pwm_show;
  191. mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_pwm_store;
  192. mlxsw_hwmon_attr->dev_attr.attr.mode = 0644;
  193. snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
  194. "pwm%u", num + 1);
  195. break;
  196. default:
  197. WARN_ON(1);
  198. }
  199. mlxsw_hwmon_attr->type_index = type_index;
  200. mlxsw_hwmon_attr->hwmon = mlxsw_hwmon;
  201. mlxsw_hwmon_attr->dev_attr.attr.name = mlxsw_hwmon_attr->name;
  202. sysfs_attr_init(&mlxsw_hwmon_attr->dev_attr.attr);
  203. mlxsw_hwmon->attrs[attr_index] = &mlxsw_hwmon_attr->dev_attr.attr;
  204. mlxsw_hwmon->attrs_count++;
  205. }
  206. static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon)
  207. {
  208. char mtcap_pl[MLXSW_REG_MTCAP_LEN] = {0};
  209. char mtmp_pl[MLXSW_REG_MTMP_LEN];
  210. u8 sensor_count;
  211. int i;
  212. int err;
  213. err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtcap), mtcap_pl);
  214. if (err) {
  215. dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get number of temp sensors\n");
  216. return err;
  217. }
  218. sensor_count = mlxsw_reg_mtcap_sensor_count_get(mtcap_pl);
  219. for (i = 0; i < sensor_count; i++) {
  220. mlxsw_reg_mtmp_pack(mtmp_pl, i, true, true);
  221. err = mlxsw_reg_write(mlxsw_hwmon->core,
  222. MLXSW_REG(mtmp), mtmp_pl);
  223. if (err) {
  224. dev_err(mlxsw_hwmon->bus_info->dev, "Failed to setup temp sensor number %d\n",
  225. i);
  226. return err;
  227. }
  228. mlxsw_hwmon_attr_add(mlxsw_hwmon,
  229. MLXSW_HWMON_ATTR_TYPE_TEMP, i, i);
  230. mlxsw_hwmon_attr_add(mlxsw_hwmon,
  231. MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, i, i);
  232. mlxsw_hwmon_attr_add(mlxsw_hwmon,
  233. MLXSW_HWMON_ATTR_TYPE_TEMP_RST, i, i);
  234. }
  235. return 0;
  236. }
  237. static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon)
  238. {
  239. char mfcr_pl[MLXSW_REG_MFCR_LEN] = {0};
  240. enum mlxsw_reg_mfcr_pwm_frequency freq;
  241. unsigned int type_index;
  242. unsigned int num;
  243. u16 tacho_active;
  244. u8 pwm_active;
  245. int err;
  246. err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfcr), mfcr_pl);
  247. if (err) {
  248. dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get to probe PWMs and Tachometers\n");
  249. return err;
  250. }
  251. mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
  252. num = 0;
  253. for (type_index = 0; type_index < MLXSW_MFCR_TACHOS_MAX; type_index++) {
  254. if (tacho_active & BIT(type_index))
  255. mlxsw_hwmon_attr_add(mlxsw_hwmon,
  256. MLXSW_HWMON_ATTR_TYPE_FAN_RPM,
  257. type_index, num++);
  258. }
  259. num = 0;
  260. for (type_index = 0; type_index < MLXSW_MFCR_PWMS_MAX; type_index++) {
  261. if (pwm_active & BIT(type_index))
  262. mlxsw_hwmon_attr_add(mlxsw_hwmon,
  263. MLXSW_HWMON_ATTR_TYPE_PWM,
  264. type_index, num++);
  265. }
  266. return 0;
  267. }
  268. int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
  269. const struct mlxsw_bus_info *mlxsw_bus_info,
  270. struct mlxsw_hwmon **p_hwmon)
  271. {
  272. struct mlxsw_hwmon *mlxsw_hwmon;
  273. struct device *hwmon_dev;
  274. int err;
  275. mlxsw_hwmon = kzalloc(sizeof(*mlxsw_hwmon), GFP_KERNEL);
  276. if (!mlxsw_hwmon)
  277. return -ENOMEM;
  278. mlxsw_hwmon->core = mlxsw_core;
  279. mlxsw_hwmon->bus_info = mlxsw_bus_info;
  280. err = mlxsw_hwmon_temp_init(mlxsw_hwmon);
  281. if (err)
  282. goto err_temp_init;
  283. err = mlxsw_hwmon_fans_init(mlxsw_hwmon);
  284. if (err)
  285. goto err_fans_init;
  286. mlxsw_hwmon->groups[0] = &mlxsw_hwmon->group;
  287. mlxsw_hwmon->group.attrs = mlxsw_hwmon->attrs;
  288. hwmon_dev = hwmon_device_register_with_groups(mlxsw_bus_info->dev,
  289. "mlxsw", mlxsw_hwmon,
  290. mlxsw_hwmon->groups);
  291. if (IS_ERR(hwmon_dev)) {
  292. err = PTR_ERR(hwmon_dev);
  293. goto err_hwmon_register;
  294. }
  295. mlxsw_hwmon->hwmon_dev = hwmon_dev;
  296. *p_hwmon = mlxsw_hwmon;
  297. return 0;
  298. err_hwmon_register:
  299. err_fans_init:
  300. err_temp_init:
  301. kfree(mlxsw_hwmon);
  302. return err;
  303. }
  304. void mlxsw_hwmon_fini(struct mlxsw_hwmon *mlxsw_hwmon)
  305. {
  306. hwmon_device_unregister(mlxsw_hwmon->hwmon_dev);
  307. kfree(mlxsw_hwmon);
  308. }