2
0

emc141x.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /*
  2. * SMSC EMC141X temperature sensor.
  3. *
  4. * Copyright (c) 2020 Bytedance Corporation
  5. * Written by John Wang <wangzhiqiang.bj@bytedance.com>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 or
  10. * (at your option) version 3 of the License.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program; if not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include "qemu/osdep.h"
  21. #include "hw/i2c/i2c.h"
  22. #include "migration/vmstate.h"
  23. #include "qapi/error.h"
  24. #include "qapi/visitor.h"
  25. #include "qemu/module.h"
  26. #include "qom/object.h"
  27. #include "hw/sensor/emc141x_regs.h"
  28. #define SENSORS_COUNT_MAX 4
  29. struct EMC141XState {
  30. I2CSlave parent_obj;
  31. struct {
  32. uint8_t raw_temp_min;
  33. uint8_t raw_temp_current;
  34. uint8_t raw_temp_max;
  35. } sensor[SENSORS_COUNT_MAX];
  36. uint8_t len;
  37. uint8_t data;
  38. uint8_t pointer;
  39. };
  40. struct EMC141XClass {
  41. I2CSlaveClass parent_class;
  42. uint8_t model;
  43. unsigned sensors_count;
  44. };
  45. #define TYPE_EMC141X "emc141x"
  46. OBJECT_DECLARE_TYPE(EMC141XState, EMC141XClass, EMC141X)
  47. static void emc141x_get_temperature(Object *obj, Visitor *v, const char *name,
  48. void *opaque, Error **errp)
  49. {
  50. EMC141XState *s = EMC141X(obj);
  51. EMC141XClass *sc = EMC141X_GET_CLASS(s);
  52. int64_t value;
  53. unsigned tempid;
  54. if (sscanf(name, "temperature%u", &tempid) != 1) {
  55. error_setg(errp, "error reading %s: %s", name, g_strerror(errno));
  56. return;
  57. }
  58. if (tempid >= sc->sensors_count) {
  59. error_setg(errp, "error reading %s", name);
  60. return;
  61. }
  62. value = s->sensor[tempid].raw_temp_current * 1000;
  63. visit_type_int(v, name, &value, errp);
  64. }
  65. static void emc141x_set_temperature(Object *obj, Visitor *v, const char *name,
  66. void *opaque, Error **errp)
  67. {
  68. EMC141XState *s = EMC141X(obj);
  69. EMC141XClass *sc = EMC141X_GET_CLASS(s);
  70. int64_t temp;
  71. unsigned tempid;
  72. if (!visit_type_int(v, name, &temp, errp)) {
  73. return;
  74. }
  75. if (sscanf(name, "temperature%u", &tempid) != 1) {
  76. error_setg(errp, "error reading %s: %s", name, g_strerror(errno));
  77. return;
  78. }
  79. if (tempid >= sc->sensors_count) {
  80. error_setg(errp, "error reading %s", name);
  81. return;
  82. }
  83. s->sensor[tempid].raw_temp_current = temp / 1000;
  84. }
  85. static void emc141x_read(EMC141XState *s)
  86. {
  87. EMC141XClass *sc = EMC141X_GET_CLASS(s);
  88. switch (s->pointer) {
  89. case EMC141X_DEVICE_ID:
  90. s->data = sc->model;
  91. break;
  92. case EMC141X_MANUFACTURER_ID:
  93. s->data = MANUFACTURER_ID;
  94. break;
  95. case EMC141X_REVISION:
  96. s->data = REVISION;
  97. break;
  98. case EMC141X_TEMP_HIGH0:
  99. s->data = s->sensor[0].raw_temp_current;
  100. break;
  101. case EMC141X_TEMP_HIGH1:
  102. s->data = s->sensor[1].raw_temp_current;
  103. break;
  104. case EMC141X_TEMP_HIGH2:
  105. s->data = s->sensor[2].raw_temp_current;
  106. break;
  107. case EMC141X_TEMP_HIGH3:
  108. s->data = s->sensor[3].raw_temp_current;
  109. break;
  110. case EMC141X_TEMP_MAX_HIGH0:
  111. s->data = s->sensor[0].raw_temp_max;
  112. break;
  113. case EMC141X_TEMP_MAX_HIGH1:
  114. s->data = s->sensor[1].raw_temp_max;
  115. break;
  116. case EMC141X_TEMP_MAX_HIGH2:
  117. s->data = s->sensor[2].raw_temp_max;
  118. break;
  119. case EMC141X_TEMP_MAX_HIGH3:
  120. s->data = s->sensor[3].raw_temp_max;
  121. break;
  122. case EMC141X_TEMP_MIN_HIGH0:
  123. s->data = s->sensor[0].raw_temp_min;
  124. break;
  125. case EMC141X_TEMP_MIN_HIGH1:
  126. s->data = s->sensor[1].raw_temp_min;
  127. break;
  128. case EMC141X_TEMP_MIN_HIGH2:
  129. s->data = s->sensor[2].raw_temp_min;
  130. break;
  131. case EMC141X_TEMP_MIN_HIGH3:
  132. s->data = s->sensor[3].raw_temp_min;
  133. break;
  134. default:
  135. s->data = 0;
  136. }
  137. }
  138. static void emc141x_write(EMC141XState *s)
  139. {
  140. switch (s->pointer) {
  141. case EMC141X_TEMP_MAX_HIGH0:
  142. s->sensor[0].raw_temp_max = s->data;
  143. break;
  144. case EMC141X_TEMP_MAX_HIGH1:
  145. s->sensor[1].raw_temp_max = s->data;
  146. break;
  147. case EMC141X_TEMP_MAX_HIGH2:
  148. s->sensor[2].raw_temp_max = s->data;
  149. break;
  150. case EMC141X_TEMP_MAX_HIGH3:
  151. s->sensor[3].raw_temp_max = s->data;
  152. break;
  153. case EMC141X_TEMP_MIN_HIGH0:
  154. s->sensor[0].raw_temp_min = s->data;
  155. break;
  156. case EMC141X_TEMP_MIN_HIGH1:
  157. s->sensor[1].raw_temp_min = s->data;
  158. break;
  159. case EMC141X_TEMP_MIN_HIGH2:
  160. s->sensor[2].raw_temp_min = s->data;
  161. break;
  162. case EMC141X_TEMP_MIN_HIGH3:
  163. s->sensor[3].raw_temp_min = s->data;
  164. break;
  165. default:
  166. s->data = 0;
  167. }
  168. }
  169. static uint8_t emc141x_rx(I2CSlave *i2c)
  170. {
  171. EMC141XState *s = EMC141X(i2c);
  172. if (s->len == 0) {
  173. s->len++;
  174. return s->data;
  175. } else {
  176. return 0xff;
  177. }
  178. }
  179. static int emc141x_tx(I2CSlave *i2c, uint8_t data)
  180. {
  181. EMC141XState *s = EMC141X(i2c);
  182. if (s->len == 0) {
  183. /* first byte is the reg pointer */
  184. s->pointer = data;
  185. s->len++;
  186. } else if (s->len == 1) {
  187. s->data = data;
  188. emc141x_write(s);
  189. }
  190. return 0;
  191. }
  192. static int emc141x_event(I2CSlave *i2c, enum i2c_event event)
  193. {
  194. EMC141XState *s = EMC141X(i2c);
  195. if (event == I2C_START_RECV) {
  196. emc141x_read(s);
  197. }
  198. s->len = 0;
  199. return 0;
  200. }
  201. static const VMStateDescription vmstate_emc141x = {
  202. .name = "EMC141X",
  203. .version_id = 0,
  204. .minimum_version_id = 0,
  205. .fields = (const VMStateField[]) {
  206. VMSTATE_UINT8(len, EMC141XState),
  207. VMSTATE_UINT8(data, EMC141XState),
  208. VMSTATE_UINT8(pointer, EMC141XState),
  209. VMSTATE_I2C_SLAVE(parent_obj, EMC141XState),
  210. VMSTATE_END_OF_LIST()
  211. }
  212. };
  213. static void emc141x_reset(DeviceState *dev)
  214. {
  215. EMC141XState *s = EMC141X(dev);
  216. int i;
  217. for (i = 0; i < SENSORS_COUNT_MAX; i++) {
  218. s->sensor[i].raw_temp_max = 0x55;
  219. }
  220. s->pointer = 0;
  221. s->len = 0;
  222. }
  223. static void emc141x_initfn(Object *obj)
  224. {
  225. object_property_add(obj, "temperature0", "int",
  226. emc141x_get_temperature,
  227. emc141x_set_temperature, NULL, NULL);
  228. object_property_add(obj, "temperature1", "int",
  229. emc141x_get_temperature,
  230. emc141x_set_temperature, NULL, NULL);
  231. object_property_add(obj, "temperature2", "int",
  232. emc141x_get_temperature,
  233. emc141x_set_temperature, NULL, NULL);
  234. object_property_add(obj, "temperature3", "int",
  235. emc141x_get_temperature,
  236. emc141x_set_temperature, NULL, NULL);
  237. }
  238. static void emc141x_class_init(ObjectClass *klass, const void *data)
  239. {
  240. DeviceClass *dc = DEVICE_CLASS(klass);
  241. I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
  242. device_class_set_legacy_reset(dc, emc141x_reset);
  243. k->event = emc141x_event;
  244. k->recv = emc141x_rx;
  245. k->send = emc141x_tx;
  246. dc->vmsd = &vmstate_emc141x;
  247. }
  248. static void emc1413_class_init(ObjectClass *klass, void *data)
  249. {
  250. EMC141XClass *ec = EMC141X_CLASS(klass);
  251. emc141x_class_init(klass, data);
  252. ec->model = EMC1413_DEVICE_ID;
  253. ec->sensors_count = 3;
  254. }
  255. static void emc1414_class_init(ObjectClass *klass, void *data)
  256. {
  257. EMC141XClass *ec = EMC141X_CLASS(klass);
  258. emc141x_class_init(klass, data);
  259. ec->model = EMC1414_DEVICE_ID;
  260. ec->sensors_count = 4;
  261. }
  262. static const TypeInfo emc141x_info = {
  263. .name = TYPE_EMC141X,
  264. .parent = TYPE_I2C_SLAVE,
  265. .instance_size = sizeof(EMC141XState),
  266. .class_size = sizeof(EMC141XClass),
  267. .instance_init = emc141x_initfn,
  268. .abstract = true,
  269. };
  270. static const TypeInfo emc1413_info = {
  271. .name = "emc1413",
  272. .parent = TYPE_EMC141X,
  273. .class_init = emc1413_class_init,
  274. };
  275. static const TypeInfo emc1414_info = {
  276. .name = "emc1414",
  277. .parent = TYPE_EMC141X,
  278. .class_init = emc1414_class_init,
  279. };
  280. static void emc141x_register_types(void)
  281. {
  282. type_register_static(&emc141x_info);
  283. type_register_static(&emc1413_info);
  284. type_register_static(&emc1414_info);
  285. }
  286. type_init(emc141x_register_types)