aspeed_adc.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. /*
  2. * Aspeed ADC
  3. *
  4. * Copyright 2017-2021 IBM Corp.
  5. *
  6. * Andrew Jeffery <andrew@aj.id.au>
  7. *
  8. * SPDX-License-Identifier: GPL-2.0-or-later
  9. */
  10. #include "qemu/osdep.h"
  11. #include "qapi/error.h"
  12. #include "qemu/log.h"
  13. #include "hw/irq.h"
  14. #include "hw/qdev-properties.h"
  15. #include "migration/vmstate.h"
  16. #include "hw/adc/aspeed_adc.h"
  17. #include "trace.h"
  18. #define ASPEED_ADC_MEMORY_REGION_SIZE 0x1000
  19. #define ASPEED_ADC_ENGINE_MEMORY_REGION_SIZE 0x100
  20. #define ASPEED_ADC_ENGINE_CH_EN_MASK 0xffff0000
  21. #define ASPEED_ADC_ENGINE_CH_EN(x) ((BIT(x)) << 16)
  22. #define ASPEED_ADC_ENGINE_INIT BIT(8)
  23. #define ASPEED_ADC_ENGINE_AUTO_COMP BIT(5)
  24. #define ASPEED_ADC_ENGINE_COMP BIT(4)
  25. #define ASPEED_ADC_ENGINE_MODE_MASK 0x0000000e
  26. #define ASPEED_ADC_ENGINE_MODE_OFF (0b000 << 1)
  27. #define ASPEED_ADC_ENGINE_MODE_STANDBY (0b001 << 1)
  28. #define ASPEED_ADC_ENGINE_MODE_NORMAL (0b111 << 1)
  29. #define ASPEED_ADC_ENGINE_EN BIT(0)
  30. #define ASPEED_ADC_HYST_EN BIT(31)
  31. #define ASPEED_ADC_L_MASK ((1 << 10) - 1)
  32. #define ASPEED_ADC_L(x) ((x) & ASPEED_ADC_L_MASK)
  33. #define ASPEED_ADC_H(x) (((x) >> 16) & ASPEED_ADC_L_MASK)
  34. #define ASPEED_ADC_LH_MASK (ASPEED_ADC_L_MASK << 16 | ASPEED_ADC_L_MASK)
  35. #define LOWER_CHANNEL_MASK ((1 << 10) - 1)
  36. #define LOWER_CHANNEL_DATA(x) ((x) & LOWER_CHANNEL_MASK)
  37. #define UPPER_CHANNEL_DATA(x) (((x) >> 16) & LOWER_CHANNEL_MASK)
  38. #define TO_REG(addr) (addr >> 2)
  39. #define ENGINE_CONTROL TO_REG(0x00)
  40. #define INTERRUPT_CONTROL TO_REG(0x04)
  41. #define VGA_DETECT_CONTROL TO_REG(0x08)
  42. #define CLOCK_CONTROL TO_REG(0x0C)
  43. #define DATA_CHANNEL_1_AND_0 TO_REG(0x10)
  44. #define DATA_CHANNEL_7_AND_6 TO_REG(0x1C)
  45. #define DATA_CHANNEL_9_AND_8 TO_REG(0x20)
  46. #define DATA_CHANNEL_15_AND_14 TO_REG(0x2C)
  47. #define BOUNDS_CHANNEL_0 TO_REG(0x30)
  48. #define BOUNDS_CHANNEL_7 TO_REG(0x4C)
  49. #define BOUNDS_CHANNEL_8 TO_REG(0x50)
  50. #define BOUNDS_CHANNEL_15 TO_REG(0x6C)
  51. #define HYSTERESIS_CHANNEL_0 TO_REG(0x70)
  52. #define HYSTERESIS_CHANNEL_7 TO_REG(0x8C)
  53. #define HYSTERESIS_CHANNEL_8 TO_REG(0x90)
  54. #define HYSTERESIS_CHANNEL_15 TO_REG(0xAC)
  55. #define INTERRUPT_SOURCE TO_REG(0xC0)
  56. #define COMPENSATING_AND_TRIMMING TO_REG(0xC4)
  57. static inline uint32_t update_channels(uint32_t current)
  58. {
  59. return ((((current >> 16) & ASPEED_ADC_L_MASK) + 7) << 16) |
  60. ((current + 5) & ASPEED_ADC_L_MASK);
  61. }
  62. static bool breaks_threshold(AspeedADCEngineState *s, int reg)
  63. {
  64. assert(reg >= DATA_CHANNEL_1_AND_0 &&
  65. reg < DATA_CHANNEL_1_AND_0 + s->nr_channels / 2);
  66. int a_bounds_reg = BOUNDS_CHANNEL_0 + (reg - DATA_CHANNEL_1_AND_0) * 2;
  67. int b_bounds_reg = a_bounds_reg + 1;
  68. uint32_t a_and_b = s->regs[reg];
  69. uint32_t a_bounds = s->regs[a_bounds_reg];
  70. uint32_t b_bounds = s->regs[b_bounds_reg];
  71. uint32_t a = ASPEED_ADC_L(a_and_b);
  72. uint32_t b = ASPEED_ADC_H(a_and_b);
  73. uint32_t a_lower = ASPEED_ADC_L(a_bounds);
  74. uint32_t a_upper = ASPEED_ADC_H(a_bounds);
  75. uint32_t b_lower = ASPEED_ADC_L(b_bounds);
  76. uint32_t b_upper = ASPEED_ADC_H(b_bounds);
  77. return (a < a_lower || a > a_upper) ||
  78. (b < b_lower || b > b_upper);
  79. }
  80. static uint32_t read_channel_sample(AspeedADCEngineState *s, int reg)
  81. {
  82. assert(reg >= DATA_CHANNEL_1_AND_0 &&
  83. reg < DATA_CHANNEL_1_AND_0 + s->nr_channels / 2);
  84. /* Poor man's sampling */
  85. uint32_t value = s->regs[reg];
  86. s->regs[reg] = update_channels(s->regs[reg]);
  87. if (breaks_threshold(s, reg)) {
  88. s->regs[INTERRUPT_CONTROL] |= BIT(reg - DATA_CHANNEL_1_AND_0);
  89. qemu_irq_raise(s->irq);
  90. }
  91. return value;
  92. }
  93. static uint64_t aspeed_adc_engine_read(void *opaque, hwaddr addr,
  94. unsigned int size)
  95. {
  96. AspeedADCEngineState *s = ASPEED_ADC_ENGINE(opaque);
  97. int reg = TO_REG(addr);
  98. uint32_t value = 0;
  99. switch (reg) {
  100. case BOUNDS_CHANNEL_8 ... BOUNDS_CHANNEL_15:
  101. if (s->nr_channels <= 8) {
  102. qemu_log_mask(LOG_GUEST_ERROR, "%s: engine[%u]: "
  103. "bounds register %u invalid, only 0...7 valid\n",
  104. __func__, s->engine_id, reg - BOUNDS_CHANNEL_0);
  105. break;
  106. }
  107. /* fallthrough */
  108. case HYSTERESIS_CHANNEL_8 ... HYSTERESIS_CHANNEL_15:
  109. if (s->nr_channels <= 8) {
  110. qemu_log_mask(LOG_GUEST_ERROR, "%s: engine[%u]: "
  111. "hysteresis register %u invalid, only 0...7 valid\n",
  112. __func__, s->engine_id, reg - HYSTERESIS_CHANNEL_0);
  113. break;
  114. }
  115. /* fallthrough */
  116. case BOUNDS_CHANNEL_0 ... BOUNDS_CHANNEL_7:
  117. case HYSTERESIS_CHANNEL_0 ... HYSTERESIS_CHANNEL_7:
  118. case ENGINE_CONTROL:
  119. case INTERRUPT_CONTROL:
  120. case VGA_DETECT_CONTROL:
  121. case CLOCK_CONTROL:
  122. case INTERRUPT_SOURCE:
  123. case COMPENSATING_AND_TRIMMING:
  124. value = s->regs[reg];
  125. break;
  126. case DATA_CHANNEL_9_AND_8 ... DATA_CHANNEL_15_AND_14:
  127. if (s->nr_channels <= 8) {
  128. qemu_log_mask(LOG_GUEST_ERROR, "%s: engine[%u]: "
  129. "data register %u invalid, only 0...3 valid\n",
  130. __func__, s->engine_id, reg - DATA_CHANNEL_1_AND_0);
  131. break;
  132. }
  133. /* fallthrough */
  134. case DATA_CHANNEL_1_AND_0 ... DATA_CHANNEL_7_AND_6:
  135. value = read_channel_sample(s, reg);
  136. /* Allow 16-bit reads of the data registers */
  137. if (addr & 0x2) {
  138. assert(size == 2);
  139. value >>= 16;
  140. }
  141. break;
  142. default:
  143. qemu_log_mask(LOG_UNIMP, "%s: engine[%u]: 0x%" HWADDR_PRIx "\n",
  144. __func__, s->engine_id, addr);
  145. break;
  146. }
  147. trace_aspeed_adc_engine_read(s->engine_id, addr, value);
  148. return value;
  149. }
  150. static void aspeed_adc_engine_write(void *opaque, hwaddr addr, uint64_t value,
  151. unsigned int size)
  152. {
  153. AspeedADCEngineState *s = ASPEED_ADC_ENGINE(opaque);
  154. int reg = TO_REG(addr);
  155. uint32_t init = 0;
  156. trace_aspeed_adc_engine_write(s->engine_id, addr, value);
  157. switch (reg) {
  158. case ENGINE_CONTROL:
  159. init = !!(value & ASPEED_ADC_ENGINE_EN);
  160. init *= ASPEED_ADC_ENGINE_INIT;
  161. value &= ~ASPEED_ADC_ENGINE_INIT;
  162. value |= init;
  163. value &= ~ASPEED_ADC_ENGINE_AUTO_COMP;
  164. break;
  165. case INTERRUPT_CONTROL:
  166. case VGA_DETECT_CONTROL:
  167. case CLOCK_CONTROL:
  168. break;
  169. case DATA_CHANNEL_9_AND_8 ... DATA_CHANNEL_15_AND_14:
  170. if (s->nr_channels <= 8) {
  171. qemu_log_mask(LOG_GUEST_ERROR, "%s: engine[%u]: "
  172. "data register %u invalid, only 0...3 valid\n",
  173. __func__, s->engine_id, reg - DATA_CHANNEL_1_AND_0);
  174. return;
  175. }
  176. /* fallthrough */
  177. case BOUNDS_CHANNEL_8 ... BOUNDS_CHANNEL_15:
  178. if (s->nr_channels <= 8) {
  179. qemu_log_mask(LOG_GUEST_ERROR, "%s: engine[%u]: "
  180. "bounds register %u invalid, only 0...7 valid\n",
  181. __func__, s->engine_id, reg - BOUNDS_CHANNEL_0);
  182. return;
  183. }
  184. /* fallthrough */
  185. case DATA_CHANNEL_1_AND_0 ... DATA_CHANNEL_7_AND_6:
  186. case BOUNDS_CHANNEL_0 ... BOUNDS_CHANNEL_7:
  187. value &= ASPEED_ADC_LH_MASK;
  188. break;
  189. case HYSTERESIS_CHANNEL_8 ... HYSTERESIS_CHANNEL_15:
  190. if (s->nr_channels <= 8) {
  191. qemu_log_mask(LOG_GUEST_ERROR, "%s: engine[%u]: "
  192. "hysteresis register %u invalid, only 0...7 valid\n",
  193. __func__, s->engine_id, reg - HYSTERESIS_CHANNEL_0);
  194. return;
  195. }
  196. /* fallthrough */
  197. case HYSTERESIS_CHANNEL_0 ... HYSTERESIS_CHANNEL_7:
  198. value &= (ASPEED_ADC_HYST_EN | ASPEED_ADC_LH_MASK);
  199. break;
  200. case INTERRUPT_SOURCE:
  201. value &= 0xffff;
  202. break;
  203. case COMPENSATING_AND_TRIMMING:
  204. value &= 0xf;
  205. break;
  206. default:
  207. qemu_log_mask(LOG_UNIMP, "%s: engine[%u]: "
  208. "0x%" HWADDR_PRIx " 0x%" PRIx64 "\n",
  209. __func__, s->engine_id, addr, value);
  210. break;
  211. }
  212. s->regs[reg] = value;
  213. }
  214. static const MemoryRegionOps aspeed_adc_engine_ops = {
  215. .read = aspeed_adc_engine_read,
  216. .write = aspeed_adc_engine_write,
  217. .endianness = DEVICE_LITTLE_ENDIAN,
  218. .valid = {
  219. .min_access_size = 2,
  220. .max_access_size = 4,
  221. .unaligned = false,
  222. },
  223. };
  224. static const uint32_t aspeed_adc_resets[ASPEED_ADC_NR_REGS] = {
  225. [ENGINE_CONTROL] = 0x00000000,
  226. [INTERRUPT_CONTROL] = 0x00000000,
  227. [VGA_DETECT_CONTROL] = 0x0000000f,
  228. [CLOCK_CONTROL] = 0x0000000f,
  229. };
  230. static void aspeed_adc_engine_reset(DeviceState *dev)
  231. {
  232. AspeedADCEngineState *s = ASPEED_ADC_ENGINE(dev);
  233. memcpy(s->regs, aspeed_adc_resets, sizeof(aspeed_adc_resets));
  234. }
  235. static void aspeed_adc_engine_realize(DeviceState *dev, Error **errp)
  236. {
  237. AspeedADCEngineState *s = ASPEED_ADC_ENGINE(dev);
  238. SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
  239. g_autofree char *name = g_strdup_printf(TYPE_ASPEED_ADC_ENGINE ".%d",
  240. s->engine_id);
  241. assert(s->engine_id < 2);
  242. sysbus_init_irq(sbd, &s->irq);
  243. memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_adc_engine_ops, s, name,
  244. ASPEED_ADC_ENGINE_MEMORY_REGION_SIZE);
  245. sysbus_init_mmio(sbd, &s->mmio);
  246. }
  247. static const VMStateDescription vmstate_aspeed_adc_engine = {
  248. .name = TYPE_ASPEED_ADC,
  249. .version_id = 1,
  250. .minimum_version_id = 1,
  251. .fields = (const VMStateField[]) {
  252. VMSTATE_UINT32_ARRAY(regs, AspeedADCEngineState, ASPEED_ADC_NR_REGS),
  253. VMSTATE_END_OF_LIST(),
  254. }
  255. };
  256. static const Property aspeed_adc_engine_properties[] = {
  257. DEFINE_PROP_UINT32("engine-id", AspeedADCEngineState, engine_id, 0),
  258. DEFINE_PROP_UINT32("nr-channels", AspeedADCEngineState, nr_channels, 0),
  259. };
  260. static void aspeed_adc_engine_class_init(ObjectClass *klass, void *data)
  261. {
  262. DeviceClass *dc = DEVICE_CLASS(klass);
  263. dc->realize = aspeed_adc_engine_realize;
  264. device_class_set_legacy_reset(dc, aspeed_adc_engine_reset);
  265. device_class_set_props(dc, aspeed_adc_engine_properties);
  266. dc->desc = "Aspeed Analog-to-Digital Engine";
  267. dc->vmsd = &vmstate_aspeed_adc_engine;
  268. }
  269. static const TypeInfo aspeed_adc_engine_info = {
  270. .name = TYPE_ASPEED_ADC_ENGINE,
  271. .parent = TYPE_SYS_BUS_DEVICE,
  272. .instance_size = sizeof(AspeedADCEngineState),
  273. .class_init = aspeed_adc_engine_class_init,
  274. };
  275. static void aspeed_adc_instance_init(Object *obj)
  276. {
  277. AspeedADCState *s = ASPEED_ADC(obj);
  278. AspeedADCClass *aac = ASPEED_ADC_GET_CLASS(obj);
  279. uint32_t nr_channels = ASPEED_ADC_NR_CHANNELS / aac->nr_engines;
  280. for (int i = 0; i < aac->nr_engines; i++) {
  281. AspeedADCEngineState *engine = &s->engines[i];
  282. object_initialize_child(obj, "engine[*]", engine,
  283. TYPE_ASPEED_ADC_ENGINE);
  284. qdev_prop_set_uint32(DEVICE(engine), "engine-id", i);
  285. qdev_prop_set_uint32(DEVICE(engine), "nr-channels", nr_channels);
  286. }
  287. }
  288. static void aspeed_adc_set_irq(void *opaque, int n, int level)
  289. {
  290. AspeedADCState *s = opaque;
  291. AspeedADCClass *aac = ASPEED_ADC_GET_CLASS(s);
  292. uint32_t pending = 0;
  293. /* TODO: update Global IRQ status register on AST2600 (Need specs) */
  294. for (int i = 0; i < aac->nr_engines; i++) {
  295. uint32_t irq_status = s->engines[i].regs[INTERRUPT_CONTROL] & 0xFF;
  296. pending |= irq_status << (i * 8);
  297. }
  298. qemu_set_irq(s->irq, !!pending);
  299. }
  300. static void aspeed_adc_realize(DeviceState *dev, Error **errp)
  301. {
  302. AspeedADCState *s = ASPEED_ADC(dev);
  303. SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
  304. AspeedADCClass *aac = ASPEED_ADC_GET_CLASS(dev);
  305. qdev_init_gpio_in_named_with_opaque(DEVICE(sbd), aspeed_adc_set_irq,
  306. s, NULL, aac->nr_engines);
  307. sysbus_init_irq(sbd, &s->irq);
  308. memory_region_init(&s->mmio, OBJECT(s), TYPE_ASPEED_ADC,
  309. ASPEED_ADC_MEMORY_REGION_SIZE);
  310. sysbus_init_mmio(sbd, &s->mmio);
  311. for (int i = 0; i < aac->nr_engines; i++) {
  312. Object *eng = OBJECT(&s->engines[i]);
  313. if (!sysbus_realize(SYS_BUS_DEVICE(eng), errp)) {
  314. return;
  315. }
  316. sysbus_connect_irq(SYS_BUS_DEVICE(eng), 0,
  317. qdev_get_gpio_in(DEVICE(sbd), i));
  318. memory_region_add_subregion(&s->mmio,
  319. i * ASPEED_ADC_ENGINE_MEMORY_REGION_SIZE,
  320. &s->engines[i].mmio);
  321. }
  322. }
  323. static void aspeed_adc_class_init(ObjectClass *klass, void *data)
  324. {
  325. DeviceClass *dc = DEVICE_CLASS(klass);
  326. AspeedADCClass *aac = ASPEED_ADC_CLASS(klass);
  327. dc->realize = aspeed_adc_realize;
  328. dc->desc = "Aspeed Analog-to-Digital Converter";
  329. aac->nr_engines = 1;
  330. }
  331. static void aspeed_2600_adc_class_init(ObjectClass *klass, void *data)
  332. {
  333. DeviceClass *dc = DEVICE_CLASS(klass);
  334. AspeedADCClass *aac = ASPEED_ADC_CLASS(klass);
  335. dc->desc = "ASPEED 2600 ADC Controller";
  336. aac->nr_engines = 2;
  337. }
  338. static void aspeed_1030_adc_class_init(ObjectClass *klass, void *data)
  339. {
  340. DeviceClass *dc = DEVICE_CLASS(klass);
  341. AspeedADCClass *aac = ASPEED_ADC_CLASS(klass);
  342. dc->desc = "ASPEED 1030 ADC Controller";
  343. aac->nr_engines = 2;
  344. }
  345. static void aspeed_2700_adc_class_init(ObjectClass *klass, void *data)
  346. {
  347. DeviceClass *dc = DEVICE_CLASS(klass);
  348. AspeedADCClass *aac = ASPEED_ADC_CLASS(klass);
  349. dc->desc = "ASPEED 2700 ADC Controller";
  350. aac->nr_engines = 2;
  351. }
  352. static const TypeInfo aspeed_adc_info = {
  353. .name = TYPE_ASPEED_ADC,
  354. .parent = TYPE_SYS_BUS_DEVICE,
  355. .instance_init = aspeed_adc_instance_init,
  356. .instance_size = sizeof(AspeedADCState),
  357. .class_init = aspeed_adc_class_init,
  358. .class_size = sizeof(AspeedADCClass),
  359. .abstract = true,
  360. };
  361. static const TypeInfo aspeed_2400_adc_info = {
  362. .name = TYPE_ASPEED_2400_ADC,
  363. .parent = TYPE_ASPEED_ADC,
  364. };
  365. static const TypeInfo aspeed_2500_adc_info = {
  366. .name = TYPE_ASPEED_2500_ADC,
  367. .parent = TYPE_ASPEED_ADC,
  368. };
  369. static const TypeInfo aspeed_2600_adc_info = {
  370. .name = TYPE_ASPEED_2600_ADC,
  371. .parent = TYPE_ASPEED_ADC,
  372. .class_init = aspeed_2600_adc_class_init,
  373. };
  374. static const TypeInfo aspeed_1030_adc_info = {
  375. .name = TYPE_ASPEED_1030_ADC,
  376. .parent = TYPE_ASPEED_ADC,
  377. .class_init = aspeed_1030_adc_class_init, /* No change since AST2600 */
  378. };
  379. static const TypeInfo aspeed_2700_adc_info = {
  380. .name = TYPE_ASPEED_2700_ADC,
  381. .parent = TYPE_ASPEED_ADC,
  382. .class_init = aspeed_2700_adc_class_init,
  383. };
  384. static void aspeed_adc_register_types(void)
  385. {
  386. type_register_static(&aspeed_adc_engine_info);
  387. type_register_static(&aspeed_adc_info);
  388. type_register_static(&aspeed_2400_adc_info);
  389. type_register_static(&aspeed_2500_adc_info);
  390. type_register_static(&aspeed_2600_adc_info);
  391. type_register_static(&aspeed_1030_adc_info);
  392. type_register_static(&aspeed_2700_adc_info);
  393. }
  394. type_init(aspeed_adc_register_types);