2
0

nrf51_gpio.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /*
  2. * nRF51 System-on-Chip general purpose input/output register definition
  3. *
  4. * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
  5. * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
  6. *
  7. * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
  8. *
  9. * This code is licensed under the GPL version 2 or later. See
  10. * the COPYING file in the top-level directory.
  11. */
  12. #include "qemu/osdep.h"
  13. #include "qemu/log.h"
  14. #include "qemu/module.h"
  15. #include "hw/gpio/nrf51_gpio.h"
  16. #include "hw/irq.h"
  17. #include "migration/vmstate.h"
  18. #include "trace.h"
  19. /*
  20. * Check if the output driver is connected to the direction switch
  21. * given the current configuration and logic level.
  22. * It is not differentiated between standard and "high"(-power) drive modes.
  23. */
  24. static bool is_connected(uint32_t config, uint32_t level)
  25. {
  26. bool state;
  27. uint32_t drive_config = extract32(config, 8, 3);
  28. switch (drive_config) {
  29. case 0 ... 3:
  30. state = true;
  31. break;
  32. case 4 ... 5:
  33. state = level != 0;
  34. break;
  35. case 6 ... 7:
  36. state = level == 0;
  37. break;
  38. default:
  39. g_assert_not_reached();
  40. break;
  41. }
  42. return state;
  43. }
  44. static int pull_value(uint32_t config)
  45. {
  46. int pull = extract32(config, 2, 2);
  47. if (pull == NRF51_GPIO_PULLDOWN) {
  48. return 0;
  49. } else if (pull == NRF51_GPIO_PULLUP) {
  50. return 1;
  51. }
  52. return -1;
  53. }
  54. static void update_output_irq(NRF51GPIOState *s, size_t i,
  55. bool connected, bool level)
  56. {
  57. int64_t irq_level = connected ? level : -1;
  58. bool old_connected = extract32(s->old_out_connected, i, 1);
  59. bool old_level = extract32(s->old_out, i, 1);
  60. if ((old_connected != connected) || (old_level != level)) {
  61. qemu_set_irq(s->output[i], irq_level);
  62. trace_nrf51_gpio_update_output_irq(i, irq_level);
  63. }
  64. s->old_out = deposit32(s->old_out, i, 1, level);
  65. s->old_out_connected = deposit32(s->old_out_connected, i, 1, connected);
  66. }
  67. static void update_state(NRF51GPIOState *s)
  68. {
  69. int pull;
  70. size_t i;
  71. bool connected_out, dir, connected_in, out, in, input;
  72. for (i = 0; i < NRF51_GPIO_PINS; i++) {
  73. pull = pull_value(s->cnf[i]);
  74. dir = extract32(s->cnf[i], 0, 1);
  75. connected_in = extract32(s->in_mask, i, 1);
  76. out = extract32(s->out, i, 1);
  77. in = extract32(s->in, i, 1);
  78. input = !extract32(s->cnf[i], 1, 1);
  79. connected_out = is_connected(s->cnf[i], out) && dir;
  80. if (!input) {
  81. if (pull >= 0) {
  82. /* Input buffer disconnected from external drives */
  83. s->in = deposit32(s->in, i, 1, pull);
  84. }
  85. } else {
  86. if (connected_out && connected_in && out != in) {
  87. /* Pin both driven externally and internally */
  88. qemu_log_mask(LOG_GUEST_ERROR,
  89. "GPIO pin %zu short circuited\n", i);
  90. }
  91. if (!connected_in) {
  92. /*
  93. * Floating input: the output stimulates IN if connected,
  94. * otherwise pull-up/pull-down resistors put a value on both
  95. * IN and OUT.
  96. */
  97. if (pull >= 0 && !connected_out) {
  98. connected_out = true;
  99. out = pull;
  100. }
  101. if (connected_out) {
  102. s->in = deposit32(s->in, i, 1, out);
  103. }
  104. }
  105. }
  106. update_output_irq(s, i, connected_out, out);
  107. }
  108. }
  109. /*
  110. * Direction is exposed in both the DIR register and the DIR bit
  111. * of each PINs CNF configuration register. Reflect bits for pins in DIR
  112. * to individual pin configuration registers.
  113. */
  114. static void reflect_dir_bit_in_cnf(NRF51GPIOState *s)
  115. {
  116. size_t i;
  117. uint32_t value = s->dir;
  118. for (i = 0; i < NRF51_GPIO_PINS; i++) {
  119. s->cnf[i] = (s->cnf[i] & ~(1UL)) | ((value >> i) & 0x01);
  120. }
  121. }
  122. static uint64_t nrf51_gpio_read(void *opaque, hwaddr offset, unsigned int size)
  123. {
  124. NRF51GPIOState *s = NRF51_GPIO(opaque);
  125. uint64_t r = 0;
  126. size_t idx;
  127. switch (offset) {
  128. case NRF51_GPIO_REG_OUT ... NRF51_GPIO_REG_OUTCLR:
  129. r = s->out;
  130. break;
  131. case NRF51_GPIO_REG_IN:
  132. r = s->in;
  133. break;
  134. case NRF51_GPIO_REG_DIR ... NRF51_GPIO_REG_DIRCLR:
  135. r = s->dir;
  136. break;
  137. case NRF51_GPIO_REG_CNF_START ... NRF51_GPIO_REG_CNF_END:
  138. idx = (offset - NRF51_GPIO_REG_CNF_START) / 4;
  139. r = s->cnf[idx];
  140. break;
  141. default:
  142. qemu_log_mask(LOG_GUEST_ERROR,
  143. "%s: bad read offset 0x%" HWADDR_PRIx "\n",
  144. __func__, offset);
  145. }
  146. trace_nrf51_gpio_read(offset, r);
  147. return r;
  148. }
  149. static void nrf51_gpio_write(void *opaque, hwaddr offset,
  150. uint64_t value, unsigned int size)
  151. {
  152. NRF51GPIOState *s = NRF51_GPIO(opaque);
  153. size_t idx;
  154. trace_nrf51_gpio_write(offset, value);
  155. switch (offset) {
  156. case NRF51_GPIO_REG_OUT:
  157. s->out = value;
  158. break;
  159. case NRF51_GPIO_REG_OUTSET:
  160. s->out |= value;
  161. break;
  162. case NRF51_GPIO_REG_OUTCLR:
  163. s->out &= ~value;
  164. break;
  165. case NRF51_GPIO_REG_DIR:
  166. s->dir = value;
  167. reflect_dir_bit_in_cnf(s);
  168. break;
  169. case NRF51_GPIO_REG_DIRSET:
  170. s->dir |= value;
  171. reflect_dir_bit_in_cnf(s);
  172. break;
  173. case NRF51_GPIO_REG_DIRCLR:
  174. s->dir &= ~value;
  175. reflect_dir_bit_in_cnf(s);
  176. break;
  177. case NRF51_GPIO_REG_CNF_START ... NRF51_GPIO_REG_CNF_END:
  178. idx = (offset - NRF51_GPIO_REG_CNF_START) / 4;
  179. s->cnf[idx] = value;
  180. /*
  181. * direction is exposed in both the DIR register and the DIR bit
  182. * of each PINs CNF configuration register.
  183. */
  184. s->dir = (s->dir & ~(1UL << idx)) | ((value & 0x01) << idx);
  185. break;
  186. default:
  187. qemu_log_mask(LOG_GUEST_ERROR,
  188. "%s: bad write offset 0x%" HWADDR_PRIx "\n",
  189. __func__, offset);
  190. }
  191. update_state(s);
  192. }
  193. static const MemoryRegionOps gpio_ops = {
  194. .read = nrf51_gpio_read,
  195. .write = nrf51_gpio_write,
  196. .endianness = DEVICE_LITTLE_ENDIAN,
  197. .impl.min_access_size = 4,
  198. .impl.max_access_size = 4,
  199. };
  200. static void nrf51_gpio_set(void *opaque, int line, int value)
  201. {
  202. NRF51GPIOState *s = NRF51_GPIO(opaque);
  203. trace_nrf51_gpio_set(line, value);
  204. assert(line >= 0 && line < NRF51_GPIO_PINS);
  205. s->in_mask = deposit32(s->in_mask, line, 1, value >= 0);
  206. if (value >= 0) {
  207. s->in = deposit32(s->in, line, 1, value != 0);
  208. }
  209. update_state(s);
  210. }
  211. static void nrf51_gpio_reset(DeviceState *dev)
  212. {
  213. NRF51GPIOState *s = NRF51_GPIO(dev);
  214. size_t i;
  215. s->out = 0;
  216. s->old_out = 0;
  217. s->old_out_connected = 0;
  218. s->in = 0;
  219. s->in_mask = 0;
  220. s->dir = 0;
  221. for (i = 0; i < NRF51_GPIO_PINS; i++) {
  222. s->cnf[i] = 0x00000002;
  223. }
  224. }
  225. static const VMStateDescription vmstate_nrf51_gpio = {
  226. .name = TYPE_NRF51_GPIO,
  227. .version_id = 1,
  228. .minimum_version_id = 1,
  229. .fields = (VMStateField[]) {
  230. VMSTATE_UINT32(out, NRF51GPIOState),
  231. VMSTATE_UINT32(in, NRF51GPIOState),
  232. VMSTATE_UINT32(in_mask, NRF51GPIOState),
  233. VMSTATE_UINT32(dir, NRF51GPIOState),
  234. VMSTATE_UINT32_ARRAY(cnf, NRF51GPIOState, NRF51_GPIO_PINS),
  235. VMSTATE_UINT32(old_out, NRF51GPIOState),
  236. VMSTATE_UINT32(old_out_connected, NRF51GPIOState),
  237. VMSTATE_END_OF_LIST()
  238. }
  239. };
  240. static void nrf51_gpio_init(Object *obj)
  241. {
  242. NRF51GPIOState *s = NRF51_GPIO(obj);
  243. memory_region_init_io(&s->mmio, obj, &gpio_ops, s,
  244. TYPE_NRF51_GPIO, NRF51_GPIO_SIZE);
  245. sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
  246. qdev_init_gpio_in(DEVICE(s), nrf51_gpio_set, NRF51_GPIO_PINS);
  247. qdev_init_gpio_out(DEVICE(s), s->output, NRF51_GPIO_PINS);
  248. }
  249. static void nrf51_gpio_class_init(ObjectClass *klass, void *data)
  250. {
  251. DeviceClass *dc = DEVICE_CLASS(klass);
  252. dc->vmsd = &vmstate_nrf51_gpio;
  253. dc->reset = nrf51_gpio_reset;
  254. dc->desc = "nRF51 GPIO";
  255. }
  256. static const TypeInfo nrf51_gpio_info = {
  257. .name = TYPE_NRF51_GPIO,
  258. .parent = TYPE_SYS_BUS_DEVICE,
  259. .instance_size = sizeof(NRF51GPIOState),
  260. .instance_init = nrf51_gpio_init,
  261. .class_init = nrf51_gpio_class_init
  262. };
  263. static void nrf51_gpio_register_types(void)
  264. {
  265. type_register_static(&nrf51_gpio_info);
  266. }
  267. type_init(nrf51_gpio_register_types)