2
0

aspeed_adc.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  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 = (VMStateField[]) {
  252. VMSTATE_UINT32_ARRAY(regs, AspeedADCEngineState, ASPEED_ADC_NR_REGS),
  253. VMSTATE_END_OF_LIST(),
  254. }
  255. };
  256. static 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. DEFINE_PROP_END_OF_LIST(),
  260. };
  261. static void aspeed_adc_engine_class_init(ObjectClass *klass, void *data)
  262. {
  263. DeviceClass *dc = DEVICE_CLASS(klass);
  264. dc->realize = aspeed_adc_engine_realize;
  265. dc->reset = aspeed_adc_engine_reset;
  266. device_class_set_props(dc, aspeed_adc_engine_properties);
  267. dc->desc = "Aspeed Analog-to-Digital Engine";
  268. dc->vmsd = &vmstate_aspeed_adc_engine;
  269. }
  270. static const TypeInfo aspeed_adc_engine_info = {
  271. .name = TYPE_ASPEED_ADC_ENGINE,
  272. .parent = TYPE_SYS_BUS_DEVICE,
  273. .instance_size = sizeof(AspeedADCEngineState),
  274. .class_init = aspeed_adc_engine_class_init,
  275. };
  276. static void aspeed_adc_instance_init(Object *obj)
  277. {
  278. AspeedADCState *s = ASPEED_ADC(obj);
  279. AspeedADCClass *aac = ASPEED_ADC_GET_CLASS(obj);
  280. uint32_t nr_channels = ASPEED_ADC_NR_CHANNELS / aac->nr_engines;
  281. for (int i = 0; i < aac->nr_engines; i++) {
  282. AspeedADCEngineState *engine = &s->engines[i];
  283. object_initialize_child(obj, "engine[*]", engine,
  284. TYPE_ASPEED_ADC_ENGINE);
  285. qdev_prop_set_uint32(DEVICE(engine), "engine-id", i);
  286. qdev_prop_set_uint32(DEVICE(engine), "nr-channels", nr_channels);
  287. }
  288. }
  289. static void aspeed_adc_set_irq(void *opaque, int n, int level)
  290. {
  291. AspeedADCState *s = opaque;
  292. AspeedADCClass *aac = ASPEED_ADC_GET_CLASS(s);
  293. uint32_t pending = 0;
  294. /* TODO: update Global IRQ status register on AST2600 (Need specs) */
  295. for (int i = 0; i < aac->nr_engines; i++) {
  296. uint32_t irq_status = s->engines[i].regs[INTERRUPT_CONTROL] & 0xFF;
  297. pending |= irq_status << (i * 8);
  298. }
  299. qemu_set_irq(s->irq, !!pending);
  300. }
  301. static void aspeed_adc_realize(DeviceState *dev, Error **errp)
  302. {
  303. AspeedADCState *s = ASPEED_ADC(dev);
  304. SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
  305. AspeedADCClass *aac = ASPEED_ADC_GET_CLASS(dev);
  306. qdev_init_gpio_in_named_with_opaque(DEVICE(sbd), aspeed_adc_set_irq,
  307. s, NULL, aac->nr_engines);
  308. sysbus_init_irq(sbd, &s->irq);
  309. memory_region_init(&s->mmio, OBJECT(s), TYPE_ASPEED_ADC,
  310. ASPEED_ADC_MEMORY_REGION_SIZE);
  311. sysbus_init_mmio(sbd, &s->mmio);
  312. for (int i = 0; i < aac->nr_engines; i++) {
  313. Object *eng = OBJECT(&s->engines[i]);
  314. if (!sysbus_realize(SYS_BUS_DEVICE(eng), errp)) {
  315. return;
  316. }
  317. sysbus_connect_irq(SYS_BUS_DEVICE(eng), 0,
  318. qdev_get_gpio_in(DEVICE(sbd), i));
  319. memory_region_add_subregion(&s->mmio,
  320. i * ASPEED_ADC_ENGINE_MEMORY_REGION_SIZE,
  321. &s->engines[i].mmio);
  322. }
  323. }
  324. static void aspeed_adc_class_init(ObjectClass *klass, void *data)
  325. {
  326. DeviceClass *dc = DEVICE_CLASS(klass);
  327. AspeedADCClass *aac = ASPEED_ADC_CLASS(klass);
  328. dc->realize = aspeed_adc_realize;
  329. dc->desc = "Aspeed Analog-to-Digital Converter";
  330. aac->nr_engines = 1;
  331. }
  332. static void aspeed_2600_adc_class_init(ObjectClass *klass, void *data)
  333. {
  334. DeviceClass *dc = DEVICE_CLASS(klass);
  335. AspeedADCClass *aac = ASPEED_ADC_CLASS(klass);
  336. dc->desc = "ASPEED 2600 ADC Controller";
  337. aac->nr_engines = 2;
  338. }
  339. static void aspeed_1030_adc_class_init(ObjectClass *klass, void *data)
  340. {
  341. DeviceClass *dc = DEVICE_CLASS(klass);
  342. AspeedADCClass *aac = ASPEED_ADC_CLASS(klass);
  343. dc->desc = "ASPEED 1030 ADC Controller";
  344. aac->nr_engines = 2;
  345. }
  346. static const TypeInfo aspeed_adc_info = {
  347. .name = TYPE_ASPEED_ADC,
  348. .parent = TYPE_SYS_BUS_DEVICE,
  349. .instance_init = aspeed_adc_instance_init,
  350. .instance_size = sizeof(AspeedADCState),
  351. .class_init = aspeed_adc_class_init,
  352. .class_size = sizeof(AspeedADCClass),
  353. .abstract = true,
  354. };
  355. static const TypeInfo aspeed_2400_adc_info = {
  356. .name = TYPE_ASPEED_2400_ADC,
  357. .parent = TYPE_ASPEED_ADC,
  358. };
  359. static const TypeInfo aspeed_2500_adc_info = {
  360. .name = TYPE_ASPEED_2500_ADC,
  361. .parent = TYPE_ASPEED_ADC,
  362. };
  363. static const TypeInfo aspeed_2600_adc_info = {
  364. .name = TYPE_ASPEED_2600_ADC,
  365. .parent = TYPE_ASPEED_ADC,
  366. .class_init = aspeed_2600_adc_class_init,
  367. };
  368. static const TypeInfo aspeed_1030_adc_info = {
  369. .name = TYPE_ASPEED_1030_ADC,
  370. .parent = TYPE_ASPEED_ADC,
  371. .class_init = aspeed_1030_adc_class_init, /* No change since AST2600 */
  372. };
  373. static void aspeed_adc_register_types(void)
  374. {
  375. type_register_static(&aspeed_adc_engine_info);
  376. type_register_static(&aspeed_adc_info);
  377. type_register_static(&aspeed_2400_adc_info);
  378. type_register_static(&aspeed_2500_adc_info);
  379. type_register_static(&aspeed_2600_adc_info);
  380. type_register_static(&aspeed_1030_adc_info);
  381. }
  382. type_init(aspeed_adc_register_types);