stm32f2xx_adc.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. * STM32F2XX ADC
  3. *
  4. * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "qemu/osdep.h"
  25. #include "hw/sysbus.h"
  26. #include "migration/vmstate.h"
  27. #include "qemu/log.h"
  28. #include "qemu/module.h"
  29. #include "hw/adc/stm32f2xx_adc.h"
  30. #ifndef STM_ADC_ERR_DEBUG
  31. #define STM_ADC_ERR_DEBUG 0
  32. #endif
  33. #define DB_PRINT_L(lvl, fmt, args...) do { \
  34. if (STM_ADC_ERR_DEBUG >= lvl) { \
  35. qemu_log("%s: " fmt, __func__, ## args); \
  36. } \
  37. } while (0)
  38. #define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
  39. static void stm32f2xx_adc_reset(DeviceState *dev)
  40. {
  41. STM32F2XXADCState *s = STM32F2XX_ADC(dev);
  42. s->adc_sr = 0x00000000;
  43. s->adc_cr1 = 0x00000000;
  44. s->adc_cr2 = 0x00000000;
  45. s->adc_smpr1 = 0x00000000;
  46. s->adc_smpr2 = 0x00000000;
  47. s->adc_jofr[0] = 0x00000000;
  48. s->adc_jofr[1] = 0x00000000;
  49. s->adc_jofr[2] = 0x00000000;
  50. s->adc_jofr[3] = 0x00000000;
  51. s->adc_htr = 0x00000FFF;
  52. s->adc_ltr = 0x00000000;
  53. s->adc_sqr1 = 0x00000000;
  54. s->adc_sqr2 = 0x00000000;
  55. s->adc_sqr3 = 0x00000000;
  56. s->adc_jsqr = 0x00000000;
  57. s->adc_jdr[0] = 0x00000000;
  58. s->adc_jdr[1] = 0x00000000;
  59. s->adc_jdr[2] = 0x00000000;
  60. s->adc_jdr[3] = 0x00000000;
  61. s->adc_dr = 0x00000000;
  62. }
  63. static uint32_t stm32f2xx_adc_generate_value(STM32F2XXADCState *s)
  64. {
  65. /* Attempts to fake some ADC values */
  66. s->adc_dr = s->adc_dr + 7;
  67. switch ((s->adc_cr1 & ADC_CR1_RES) >> 24) {
  68. case 0:
  69. /* 12-bit */
  70. s->adc_dr &= 0xFFF;
  71. break;
  72. case 1:
  73. /* 10-bit */
  74. s->adc_dr &= 0x3FF;
  75. break;
  76. case 2:
  77. /* 8-bit */
  78. s->adc_dr &= 0xFF;
  79. break;
  80. default:
  81. /* 6-bit */
  82. s->adc_dr &= 0x3F;
  83. }
  84. if (s->adc_cr2 & ADC_CR2_ALIGN) {
  85. return (s->adc_dr << 1) & 0xFFF0;
  86. } else {
  87. return s->adc_dr;
  88. }
  89. }
  90. static uint64_t stm32f2xx_adc_read(void *opaque, hwaddr addr,
  91. unsigned int size)
  92. {
  93. STM32F2XXADCState *s = opaque;
  94. DB_PRINT("Address: 0x%" HWADDR_PRIx "\n", addr);
  95. if (addr >= ADC_COMMON_ADDRESS) {
  96. qemu_log_mask(LOG_UNIMP,
  97. "%s: ADC Common Register Unsupported\n", __func__);
  98. }
  99. switch (addr) {
  100. case ADC_SR:
  101. return s->adc_sr;
  102. case ADC_CR1:
  103. return s->adc_cr1;
  104. case ADC_CR2:
  105. return s->adc_cr2 & 0xFFFFFFF;
  106. case ADC_SMPR1:
  107. return s->adc_smpr1;
  108. case ADC_SMPR2:
  109. return s->adc_smpr2;
  110. case ADC_JOFR1:
  111. case ADC_JOFR2:
  112. case ADC_JOFR3:
  113. case ADC_JOFR4:
  114. qemu_log_mask(LOG_UNIMP, "%s: " \
  115. "Injection ADC is not implemented, the registers are " \
  116. "included for compatibility\n", __func__);
  117. return s->adc_jofr[(addr - ADC_JOFR1) / 4];
  118. case ADC_HTR:
  119. return s->adc_htr;
  120. case ADC_LTR:
  121. return s->adc_ltr;
  122. case ADC_SQR1:
  123. return s->adc_sqr1;
  124. case ADC_SQR2:
  125. return s->adc_sqr2;
  126. case ADC_SQR3:
  127. return s->adc_sqr3;
  128. case ADC_JSQR:
  129. qemu_log_mask(LOG_UNIMP, "%s: " \
  130. "Injection ADC is not implemented, the registers are " \
  131. "included for compatibility\n", __func__);
  132. return s->adc_jsqr;
  133. case ADC_JDR1:
  134. case ADC_JDR2:
  135. case ADC_JDR3:
  136. case ADC_JDR4:
  137. qemu_log_mask(LOG_UNIMP, "%s: " \
  138. "Injection ADC is not implemented, the registers are " \
  139. "included for compatibility\n", __func__);
  140. return s->adc_jdr[(addr - ADC_JDR1) / 4] -
  141. s->adc_jofr[(addr - ADC_JDR1) / 4];
  142. case ADC_DR:
  143. if ((s->adc_cr2 & ADC_CR2_ADON) && (s->adc_cr2 & ADC_CR2_SWSTART)) {
  144. s->adc_cr2 ^= ADC_CR2_SWSTART;
  145. return stm32f2xx_adc_generate_value(s);
  146. } else {
  147. return 0;
  148. }
  149. default:
  150. qemu_log_mask(LOG_GUEST_ERROR,
  151. "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
  152. }
  153. return 0;
  154. }
  155. static void stm32f2xx_adc_write(void *opaque, hwaddr addr,
  156. uint64_t val64, unsigned int size)
  157. {
  158. STM32F2XXADCState *s = opaque;
  159. uint32_t value = (uint32_t) val64;
  160. DB_PRINT("Address: 0x%" HWADDR_PRIx ", Value: 0x%x\n",
  161. addr, value);
  162. if (addr >= 0x100) {
  163. qemu_log_mask(LOG_UNIMP,
  164. "%s: ADC Common Register Unsupported\n", __func__);
  165. }
  166. switch (addr) {
  167. case ADC_SR:
  168. s->adc_sr &= (value & 0x3F);
  169. break;
  170. case ADC_CR1:
  171. s->adc_cr1 = value;
  172. break;
  173. case ADC_CR2:
  174. s->adc_cr2 = value;
  175. break;
  176. case ADC_SMPR1:
  177. s->adc_smpr1 = value;
  178. break;
  179. case ADC_SMPR2:
  180. s->adc_smpr2 = value;
  181. break;
  182. case ADC_JOFR1:
  183. case ADC_JOFR2:
  184. case ADC_JOFR3:
  185. case ADC_JOFR4:
  186. s->adc_jofr[(addr - ADC_JOFR1) / 4] = (value & 0xFFF);
  187. qemu_log_mask(LOG_UNIMP, "%s: " \
  188. "Injection ADC is not implemented, the registers are " \
  189. "included for compatibility\n", __func__);
  190. break;
  191. case ADC_HTR:
  192. s->adc_htr = value;
  193. break;
  194. case ADC_LTR:
  195. s->adc_ltr = value;
  196. break;
  197. case ADC_SQR1:
  198. s->adc_sqr1 = value;
  199. break;
  200. case ADC_SQR2:
  201. s->adc_sqr2 = value;
  202. break;
  203. case ADC_SQR3:
  204. s->adc_sqr3 = value;
  205. break;
  206. case ADC_JSQR:
  207. s->adc_jsqr = value;
  208. qemu_log_mask(LOG_UNIMP, "%s: " \
  209. "Injection ADC is not implemented, the registers are " \
  210. "included for compatibility\n", __func__);
  211. break;
  212. case ADC_JDR1:
  213. case ADC_JDR2:
  214. case ADC_JDR3:
  215. case ADC_JDR4:
  216. s->adc_jdr[(addr - ADC_JDR1) / 4] = value;
  217. qemu_log_mask(LOG_UNIMP, "%s: " \
  218. "Injection ADC is not implemented, the registers are " \
  219. "included for compatibility\n", __func__);
  220. break;
  221. default:
  222. qemu_log_mask(LOG_GUEST_ERROR,
  223. "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
  224. }
  225. }
  226. static const MemoryRegionOps stm32f2xx_adc_ops = {
  227. .read = stm32f2xx_adc_read,
  228. .write = stm32f2xx_adc_write,
  229. .endianness = DEVICE_NATIVE_ENDIAN,
  230. .impl.min_access_size = 4,
  231. .impl.max_access_size = 4,
  232. };
  233. static const VMStateDescription vmstate_stm32f2xx_adc = {
  234. .name = TYPE_STM32F2XX_ADC,
  235. .version_id = 1,
  236. .minimum_version_id = 1,
  237. .fields = (const VMStateField[]) {
  238. VMSTATE_UINT32(adc_sr, STM32F2XXADCState),
  239. VMSTATE_UINT32(adc_cr1, STM32F2XXADCState),
  240. VMSTATE_UINT32(adc_cr2, STM32F2XXADCState),
  241. VMSTATE_UINT32(adc_smpr1, STM32F2XXADCState),
  242. VMSTATE_UINT32(adc_smpr2, STM32F2XXADCState),
  243. VMSTATE_UINT32_ARRAY(adc_jofr, STM32F2XXADCState, 4),
  244. VMSTATE_UINT32(adc_htr, STM32F2XXADCState),
  245. VMSTATE_UINT32(adc_ltr, STM32F2XXADCState),
  246. VMSTATE_UINT32(adc_sqr1, STM32F2XXADCState),
  247. VMSTATE_UINT32(adc_sqr2, STM32F2XXADCState),
  248. VMSTATE_UINT32(adc_sqr3, STM32F2XXADCState),
  249. VMSTATE_UINT32(adc_jsqr, STM32F2XXADCState),
  250. VMSTATE_UINT32_ARRAY(adc_jdr, STM32F2XXADCState, 4),
  251. VMSTATE_UINT32(adc_dr, STM32F2XXADCState),
  252. VMSTATE_END_OF_LIST()
  253. }
  254. };
  255. static void stm32f2xx_adc_init(Object *obj)
  256. {
  257. STM32F2XXADCState *s = STM32F2XX_ADC(obj);
  258. sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
  259. memory_region_init_io(&s->mmio, obj, &stm32f2xx_adc_ops, s,
  260. TYPE_STM32F2XX_ADC, 0x100);
  261. sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
  262. }
  263. static void stm32f2xx_adc_class_init(ObjectClass *klass, void *data)
  264. {
  265. DeviceClass *dc = DEVICE_CLASS(klass);
  266. device_class_set_legacy_reset(dc, stm32f2xx_adc_reset);
  267. dc->vmsd = &vmstate_stm32f2xx_adc;
  268. }
  269. static const TypeInfo stm32f2xx_adc_info = {
  270. .name = TYPE_STM32F2XX_ADC,
  271. .parent = TYPE_SYS_BUS_DEVICE,
  272. .instance_size = sizeof(STM32F2XXADCState),
  273. .instance_init = stm32f2xx_adc_init,
  274. .class_init = stm32f2xx_adc_class_init,
  275. };
  276. static void stm32f2xx_adc_register_types(void)
  277. {
  278. type_register_static(&stm32f2xx_adc_info);
  279. }
  280. type_init(stm32f2xx_adc_register_types)