sensors.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * System Control and Management Interface (SCMI) Sensor Protocol
  4. *
  5. * Copyright (C) 2018 ARM Ltd.
  6. */
  7. #include "common.h"
  8. enum scmi_sensor_protocol_cmd {
  9. SENSOR_DESCRIPTION_GET = 0x3,
  10. SENSOR_CONFIG_SET = 0x4,
  11. SENSOR_TRIP_POINT_SET = 0x5,
  12. SENSOR_READING_GET = 0x6,
  13. };
  14. struct scmi_msg_resp_sensor_attributes {
  15. __le16 num_sensors;
  16. u8 max_requests;
  17. u8 reserved;
  18. __le32 reg_addr_low;
  19. __le32 reg_addr_high;
  20. __le32 reg_size;
  21. };
  22. struct scmi_msg_resp_sensor_description {
  23. __le16 num_returned;
  24. __le16 num_remaining;
  25. struct {
  26. __le32 id;
  27. __le32 attributes_low;
  28. #define SUPPORTS_ASYNC_READ(x) ((x) & BIT(31))
  29. #define NUM_TRIP_POINTS(x) ((x) & 0xff)
  30. __le32 attributes_high;
  31. #define SENSOR_TYPE(x) ((x) & 0xff)
  32. #define SENSOR_SCALE(x) (((x) >> 11) & 0x1f)
  33. #define SENSOR_UPDATE_SCALE(x) (((x) >> 22) & 0x1f)
  34. #define SENSOR_UPDATE_BASE(x) (((x) >> 27) & 0x1f)
  35. u8 name[SCMI_MAX_STR_SIZE];
  36. } desc[0];
  37. };
  38. struct scmi_msg_set_sensor_config {
  39. __le32 id;
  40. __le32 event_control;
  41. };
  42. struct scmi_msg_set_sensor_trip_point {
  43. __le32 id;
  44. __le32 event_control;
  45. #define SENSOR_TP_EVENT_MASK (0x3)
  46. #define SENSOR_TP_DISABLED 0x0
  47. #define SENSOR_TP_POSITIVE 0x1
  48. #define SENSOR_TP_NEGATIVE 0x2
  49. #define SENSOR_TP_BOTH 0x3
  50. #define SENSOR_TP_ID(x) (((x) & 0xff) << 4)
  51. __le32 value_low;
  52. __le32 value_high;
  53. };
  54. struct scmi_msg_sensor_reading_get {
  55. __le32 id;
  56. __le32 flags;
  57. #define SENSOR_READ_ASYNC BIT(0)
  58. };
  59. struct sensors_info {
  60. int num_sensors;
  61. int max_requests;
  62. u64 reg_addr;
  63. u32 reg_size;
  64. struct scmi_sensor_info *sensors;
  65. };
  66. static int scmi_sensor_attributes_get(const struct scmi_handle *handle,
  67. struct sensors_info *si)
  68. {
  69. int ret;
  70. struct scmi_xfer *t;
  71. struct scmi_msg_resp_sensor_attributes *attr;
  72. ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES,
  73. SCMI_PROTOCOL_SENSOR, 0, sizeof(*attr), &t);
  74. if (ret)
  75. return ret;
  76. attr = t->rx.buf;
  77. ret = scmi_do_xfer(handle, t);
  78. if (!ret) {
  79. si->num_sensors = le16_to_cpu(attr->num_sensors);
  80. si->max_requests = attr->max_requests;
  81. si->reg_addr = le32_to_cpu(attr->reg_addr_low) |
  82. (u64)le32_to_cpu(attr->reg_addr_high) << 32;
  83. si->reg_size = le32_to_cpu(attr->reg_size);
  84. }
  85. scmi_xfer_put(handle, t);
  86. return ret;
  87. }
  88. static int scmi_sensor_description_get(const struct scmi_handle *handle,
  89. struct sensors_info *si)
  90. {
  91. int ret, cnt;
  92. u32 desc_index = 0;
  93. u16 num_returned, num_remaining;
  94. struct scmi_xfer *t;
  95. struct scmi_msg_resp_sensor_description *buf;
  96. ret = scmi_xfer_get_init(handle, SENSOR_DESCRIPTION_GET,
  97. SCMI_PROTOCOL_SENSOR, sizeof(__le32), 0, &t);
  98. if (ret)
  99. return ret;
  100. buf = t->rx.buf;
  101. do {
  102. /* Set the number of sensors to be skipped/already read */
  103. *(__le32 *)t->tx.buf = cpu_to_le32(desc_index);
  104. ret = scmi_do_xfer(handle, t);
  105. if (ret)
  106. break;
  107. num_returned = le16_to_cpu(buf->num_returned);
  108. num_remaining = le16_to_cpu(buf->num_remaining);
  109. if (desc_index + num_returned > si->num_sensors) {
  110. dev_err(handle->dev, "No. of sensors can't exceed %d",
  111. si->num_sensors);
  112. break;
  113. }
  114. for (cnt = 0; cnt < num_returned; cnt++) {
  115. u32 attrh;
  116. struct scmi_sensor_info *s;
  117. attrh = le32_to_cpu(buf->desc[cnt].attributes_high);
  118. s = &si->sensors[desc_index + cnt];
  119. s->id = le32_to_cpu(buf->desc[cnt].id);
  120. s->type = SENSOR_TYPE(attrh);
  121. strlcpy(s->name, buf->desc[cnt].name, SCMI_MAX_STR_SIZE);
  122. }
  123. desc_index += num_returned;
  124. /*
  125. * check for both returned and remaining to avoid infinite
  126. * loop due to buggy firmware
  127. */
  128. } while (num_returned && num_remaining);
  129. scmi_xfer_put(handle, t);
  130. return ret;
  131. }
  132. static int
  133. scmi_sensor_configuration_set(const struct scmi_handle *handle, u32 sensor_id)
  134. {
  135. int ret;
  136. u32 evt_cntl = BIT(0);
  137. struct scmi_xfer *t;
  138. struct scmi_msg_set_sensor_config *cfg;
  139. ret = scmi_xfer_get_init(handle, SENSOR_CONFIG_SET,
  140. SCMI_PROTOCOL_SENSOR, sizeof(*cfg), 0, &t);
  141. if (ret)
  142. return ret;
  143. cfg = t->tx.buf;
  144. cfg->id = cpu_to_le32(sensor_id);
  145. cfg->event_control = cpu_to_le32(evt_cntl);
  146. ret = scmi_do_xfer(handle, t);
  147. scmi_xfer_put(handle, t);
  148. return ret;
  149. }
  150. static int scmi_sensor_trip_point_set(const struct scmi_handle *handle,
  151. u32 sensor_id, u8 trip_id, u64 trip_value)
  152. {
  153. int ret;
  154. u32 evt_cntl = SENSOR_TP_BOTH;
  155. struct scmi_xfer *t;
  156. struct scmi_msg_set_sensor_trip_point *trip;
  157. ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_SET,
  158. SCMI_PROTOCOL_SENSOR, sizeof(*trip), 0, &t);
  159. if (ret)
  160. return ret;
  161. trip = t->tx.buf;
  162. trip->id = cpu_to_le32(sensor_id);
  163. trip->event_control = cpu_to_le32(evt_cntl | SENSOR_TP_ID(trip_id));
  164. trip->value_low = cpu_to_le32(trip_value & 0xffffffff);
  165. trip->value_high = cpu_to_le32(trip_value >> 32);
  166. ret = scmi_do_xfer(handle, t);
  167. scmi_xfer_put(handle, t);
  168. return ret;
  169. }
  170. static int scmi_sensor_reading_get(const struct scmi_handle *handle,
  171. u32 sensor_id, bool async, u64 *value)
  172. {
  173. int ret;
  174. struct scmi_xfer *t;
  175. struct scmi_msg_sensor_reading_get *sensor;
  176. ret = scmi_xfer_get_init(handle, SENSOR_READING_GET,
  177. SCMI_PROTOCOL_SENSOR, sizeof(*sensor),
  178. sizeof(u64), &t);
  179. if (ret)
  180. return ret;
  181. sensor = t->tx.buf;
  182. sensor->id = cpu_to_le32(sensor_id);
  183. sensor->flags = cpu_to_le32(async ? SENSOR_READ_ASYNC : 0);
  184. ret = scmi_do_xfer(handle, t);
  185. if (!ret) {
  186. __le32 *pval = t->rx.buf;
  187. *value = le32_to_cpu(*pval);
  188. *value |= (u64)le32_to_cpu(*(pval + 1)) << 32;
  189. }
  190. scmi_xfer_put(handle, t);
  191. return ret;
  192. }
  193. static const struct scmi_sensor_info *
  194. scmi_sensor_info_get(const struct scmi_handle *handle, u32 sensor_id)
  195. {
  196. struct sensors_info *si = handle->sensor_priv;
  197. return si->sensors + sensor_id;
  198. }
  199. static int scmi_sensor_count_get(const struct scmi_handle *handle)
  200. {
  201. struct sensors_info *si = handle->sensor_priv;
  202. return si->num_sensors;
  203. }
  204. static struct scmi_sensor_ops sensor_ops = {
  205. .count_get = scmi_sensor_count_get,
  206. .info_get = scmi_sensor_info_get,
  207. .configuration_set = scmi_sensor_configuration_set,
  208. .trip_point_set = scmi_sensor_trip_point_set,
  209. .reading_get = scmi_sensor_reading_get,
  210. };
  211. static int scmi_sensors_protocol_init(struct scmi_handle *handle)
  212. {
  213. u32 version;
  214. struct sensors_info *sinfo;
  215. scmi_version_get(handle, SCMI_PROTOCOL_SENSOR, &version);
  216. dev_dbg(handle->dev, "Sensor Version %d.%d\n",
  217. PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version));
  218. sinfo = devm_kzalloc(handle->dev, sizeof(*sinfo), GFP_KERNEL);
  219. if (!sinfo)
  220. return -ENOMEM;
  221. scmi_sensor_attributes_get(handle, sinfo);
  222. sinfo->sensors = devm_kcalloc(handle->dev, sinfo->num_sensors,
  223. sizeof(*sinfo->sensors), GFP_KERNEL);
  224. if (!sinfo->sensors)
  225. return -ENOMEM;
  226. scmi_sensor_description_get(handle, sinfo);
  227. handle->sensor_ops = &sensor_ops;
  228. handle->sensor_priv = sinfo;
  229. return 0;
  230. }
  231. static int __init scmi_sensors_init(void)
  232. {
  233. return scmi_protocol_register(SCMI_PROTOCOL_SENSOR,
  234. &scmi_sensors_protocol_init);
  235. }
  236. subsys_initcall(scmi_sensors_init);