opal-sensor.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * PowerNV sensor code
  4. *
  5. * Copyright (C) 2013 IBM
  6. */
  7. #include <linux/delay.h>
  8. #include <linux/of.h>
  9. #include <linux/of_platform.h>
  10. #include <linux/platform_device.h>
  11. #include <asm/opal.h>
  12. #include <asm/machdep.h>
  13. /*
  14. * This will return sensor information to driver based on the requested sensor
  15. * handle. A handle is an opaque id for the powernv, read by the driver from the
  16. * device tree..
  17. */
  18. int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data)
  19. {
  20. int ret, token;
  21. struct opal_msg msg;
  22. __be32 data;
  23. token = opal_async_get_token_interruptible();
  24. if (token < 0)
  25. return token;
  26. ret = opal_sensor_read(sensor_hndl, token, &data);
  27. switch (ret) {
  28. case OPAL_ASYNC_COMPLETION:
  29. ret = opal_async_wait_response(token, &msg);
  30. if (ret) {
  31. pr_err("%s: Failed to wait for the async response, %d\n",
  32. __func__, ret);
  33. goto out;
  34. }
  35. ret = opal_error_code(opal_get_async_rc(msg));
  36. *sensor_data = be32_to_cpu(data);
  37. break;
  38. case OPAL_SUCCESS:
  39. ret = 0;
  40. *sensor_data = be32_to_cpu(data);
  41. break;
  42. case OPAL_WRONG_STATE:
  43. ret = -EIO;
  44. break;
  45. default:
  46. ret = opal_error_code(ret);
  47. break;
  48. }
  49. out:
  50. opal_async_release_token(token);
  51. return ret;
  52. }
  53. EXPORT_SYMBOL_GPL(opal_get_sensor_data);
  54. int opal_get_sensor_data_u64(u32 sensor_hndl, u64 *sensor_data)
  55. {
  56. int ret, token;
  57. struct opal_msg msg;
  58. __be64 data;
  59. if (!opal_check_token(OPAL_SENSOR_READ_U64)) {
  60. u32 sdata;
  61. ret = opal_get_sensor_data(sensor_hndl, &sdata);
  62. if (!ret)
  63. *sensor_data = sdata;
  64. return ret;
  65. }
  66. token = opal_async_get_token_interruptible();
  67. if (token < 0)
  68. return token;
  69. ret = opal_sensor_read_u64(sensor_hndl, token, &data);
  70. switch (ret) {
  71. case OPAL_ASYNC_COMPLETION:
  72. ret = opal_async_wait_response(token, &msg);
  73. if (ret) {
  74. pr_err("%s: Failed to wait for the async response, %d\n",
  75. __func__, ret);
  76. goto out_token;
  77. }
  78. ret = opal_error_code(opal_get_async_rc(msg));
  79. *sensor_data = be64_to_cpu(data);
  80. break;
  81. case OPAL_SUCCESS:
  82. ret = 0;
  83. *sensor_data = be64_to_cpu(data);
  84. break;
  85. case OPAL_WRONG_STATE:
  86. ret = -EIO;
  87. break;
  88. default:
  89. ret = opal_error_code(ret);
  90. break;
  91. }
  92. out_token:
  93. opal_async_release_token(token);
  94. return ret;
  95. }
  96. EXPORT_SYMBOL_GPL(opal_get_sensor_data_u64);
  97. int __init opal_sensor_init(void)
  98. {
  99. struct platform_device *pdev;
  100. struct device_node *sensor;
  101. sensor = of_find_node_by_path("/ibm,opal/sensors");
  102. if (!sensor) {
  103. pr_err("Opal node 'sensors' not found\n");
  104. return -ENODEV;
  105. }
  106. pdev = of_platform_device_create(sensor, "opal-sensor", NULL);
  107. of_node_put(sensor);
  108. return PTR_ERR_OR_ZERO(pdev);
  109. }