imx_gpio.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /*
  2. * i.MX processors GPIO emulation.
  3. *
  4. * Copyright (C) 2015 Jean-Christophe Dubois <jcd@tribudubois.net>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation; either version 2 or
  9. * (at your option) version 3 of the License.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "qemu/osdep.h"
  20. #include "hw/gpio/imx_gpio.h"
  21. #include "hw/irq.h"
  22. #include "hw/qdev-properties.h"
  23. #include "migration/vmstate.h"
  24. #include "qemu/log.h"
  25. #include "qemu/module.h"
  26. #include "trace.h"
  27. #ifndef DEBUG_IMX_GPIO
  28. #define DEBUG_IMX_GPIO 0
  29. #endif
  30. typedef enum IMXGPIOLevel {
  31. IMX_GPIO_LEVEL_LOW = 0,
  32. IMX_GPIO_LEVEL_HIGH = 1,
  33. } IMXGPIOLevel;
  34. static const char *imx_gpio_reg_name(uint32_t reg)
  35. {
  36. switch (reg) {
  37. case DR_ADDR:
  38. return "DR";
  39. case GDIR_ADDR:
  40. return "GDIR";
  41. case PSR_ADDR:
  42. return "PSR";
  43. case ICR1_ADDR:
  44. return "ICR1";
  45. case ICR2_ADDR:
  46. return "ICR2";
  47. case IMR_ADDR:
  48. return "IMR";
  49. case ISR_ADDR:
  50. return "ISR";
  51. case EDGE_SEL_ADDR:
  52. return "EDGE_SEL";
  53. default:
  54. return "[?]";
  55. }
  56. }
  57. static void imx_gpio_update_int(IMXGPIOState *s)
  58. {
  59. if (s->has_upper_pin_irq) {
  60. qemu_set_irq(s->irq[0], (s->isr & s->imr & 0x0000FFFF) ? 1 : 0);
  61. qemu_set_irq(s->irq[1], (s->isr & s->imr & 0xFFFF0000) ? 1 : 0);
  62. } else {
  63. qemu_set_irq(s->irq[0], (s->isr & s->imr) ? 1 : 0);
  64. }
  65. }
  66. static void imx_gpio_set_int_line(IMXGPIOState *s, int line, IMXGPIOLevel level)
  67. {
  68. /* if this signal isn't configured as an input signal, nothing to do */
  69. if (extract32(s->gdir, line, 1)) {
  70. return;
  71. }
  72. /* When set, EDGE_SEL overrides the ICR config */
  73. if (extract32(s->edge_sel, line, 1)) {
  74. /* we detect interrupt on rising and falling edge */
  75. if (extract32(s->psr, line, 1) != level) {
  76. /* level changed */
  77. s->isr = deposit32(s->isr, line, 1, 1);
  78. }
  79. } else if (extract64(s->icr, 2*line + 1, 1)) {
  80. /* interrupt is edge sensitive */
  81. if (extract32(s->psr, line, 1) != level) {
  82. /* level changed */
  83. if (extract64(s->icr, 2*line, 1) != level) {
  84. s->isr = deposit32(s->isr, line, 1, 1);
  85. }
  86. }
  87. } else {
  88. /* interrupt is level sensitive */
  89. if (extract64(s->icr, 2*line, 1) == level) {
  90. s->isr = deposit32(s->isr, line, 1, 1);
  91. }
  92. }
  93. }
  94. static void imx_gpio_set(void *opaque, int line, int level)
  95. {
  96. IMXGPIOState *s = IMX_GPIO(opaque);
  97. IMXGPIOLevel imx_level = level ? IMX_GPIO_LEVEL_HIGH : IMX_GPIO_LEVEL_LOW;
  98. trace_imx_gpio_set(DEVICE(s)->canonical_path, line, imx_level);
  99. imx_gpio_set_int_line(s, line, imx_level);
  100. /* this is an input signal, so set PSR */
  101. s->psr = deposit32(s->psr, line, 1, imx_level);
  102. imx_gpio_update_int(s);
  103. }
  104. static void imx_gpio_set_all_int_lines(IMXGPIOState *s)
  105. {
  106. int i;
  107. for (i = 0; i < IMX_GPIO_PIN_COUNT; i++) {
  108. IMXGPIOLevel imx_level = extract32(s->psr, i, 1);
  109. imx_gpio_set_int_line(s, i, imx_level);
  110. }
  111. imx_gpio_update_int(s);
  112. }
  113. static inline void imx_gpio_set_all_output_lines(IMXGPIOState *s)
  114. {
  115. int i;
  116. for (i = 0; i < IMX_GPIO_PIN_COUNT; i++) {
  117. /*
  118. * if the line is set as output, then forward the line
  119. * level to its user.
  120. */
  121. if (extract32(s->gdir, i, 1) && s->output[i]) {
  122. qemu_set_irq(s->output[i], extract32(s->dr, i, 1));
  123. }
  124. }
  125. }
  126. static uint64_t imx_gpio_read(void *opaque, hwaddr offset, unsigned size)
  127. {
  128. IMXGPIOState *s = IMX_GPIO(opaque);
  129. uint32_t reg_value = 0;
  130. switch (offset) {
  131. case DR_ADDR:
  132. /*
  133. * depending on the "line" configuration, the bit values
  134. * are coming either from DR or PSR
  135. */
  136. reg_value = (s->dr & s->gdir) | (s->psr & ~s->gdir);
  137. break;
  138. case GDIR_ADDR:
  139. reg_value = s->gdir;
  140. break;
  141. case PSR_ADDR:
  142. reg_value = s->psr & ~s->gdir;
  143. break;
  144. case ICR1_ADDR:
  145. reg_value = extract64(s->icr, 0, 32);
  146. break;
  147. case ICR2_ADDR:
  148. reg_value = extract64(s->icr, 32, 32);
  149. break;
  150. case IMR_ADDR:
  151. reg_value = s->imr;
  152. break;
  153. case ISR_ADDR:
  154. reg_value = s->isr;
  155. break;
  156. case EDGE_SEL_ADDR:
  157. if (s->has_edge_sel) {
  158. reg_value = s->edge_sel;
  159. } else {
  160. qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: EDGE_SEL register not "
  161. "present on this version of GPIO device\n",
  162. TYPE_IMX_GPIO, __func__);
  163. }
  164. break;
  165. default:
  166. qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
  167. HWADDR_PRIx "\n", TYPE_IMX_GPIO, __func__, offset);
  168. break;
  169. }
  170. trace_imx_gpio_read(DEVICE(s)->canonical_path, imx_gpio_reg_name(offset),
  171. reg_value);
  172. return reg_value;
  173. }
  174. static void imx_gpio_write(void *opaque, hwaddr offset, uint64_t value,
  175. unsigned size)
  176. {
  177. IMXGPIOState *s = IMX_GPIO(opaque);
  178. trace_imx_gpio_write(DEVICE(s)->canonical_path, imx_gpio_reg_name(offset),
  179. value);
  180. switch (offset) {
  181. case DR_ADDR:
  182. s->dr = value;
  183. imx_gpio_set_all_output_lines(s);
  184. break;
  185. case GDIR_ADDR:
  186. s->gdir = value;
  187. imx_gpio_set_all_output_lines(s);
  188. imx_gpio_set_all_int_lines(s);
  189. break;
  190. case ICR1_ADDR:
  191. s->icr = deposit64(s->icr, 0, 32, value);
  192. imx_gpio_set_all_int_lines(s);
  193. break;
  194. case ICR2_ADDR:
  195. s->icr = deposit64(s->icr, 32, 32, value);
  196. imx_gpio_set_all_int_lines(s);
  197. break;
  198. case IMR_ADDR:
  199. s->imr = value;
  200. imx_gpio_update_int(s);
  201. break;
  202. case ISR_ADDR:
  203. s->isr &= ~value;
  204. imx_gpio_set_all_int_lines(s);
  205. break;
  206. case EDGE_SEL_ADDR:
  207. if (s->has_edge_sel) {
  208. s->edge_sel = value;
  209. imx_gpio_set_all_int_lines(s);
  210. } else {
  211. qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: EDGE_SEL register not "
  212. "present on this version of GPIO device\n",
  213. TYPE_IMX_GPIO, __func__);
  214. }
  215. break;
  216. default:
  217. qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
  218. HWADDR_PRIx "\n", TYPE_IMX_GPIO, __func__, offset);
  219. break;
  220. }
  221. return;
  222. }
  223. static const MemoryRegionOps imx_gpio_ops = {
  224. .read = imx_gpio_read,
  225. .write = imx_gpio_write,
  226. .valid.min_access_size = 4,
  227. .valid.max_access_size = 4,
  228. .endianness = DEVICE_NATIVE_ENDIAN,
  229. };
  230. static const VMStateDescription vmstate_imx_gpio = {
  231. .name = TYPE_IMX_GPIO,
  232. .version_id = 1,
  233. .minimum_version_id = 1,
  234. .fields = (const VMStateField[]) {
  235. VMSTATE_UINT32(dr, IMXGPIOState),
  236. VMSTATE_UINT32(gdir, IMXGPIOState),
  237. VMSTATE_UINT32(psr, IMXGPIOState),
  238. VMSTATE_UINT64(icr, IMXGPIOState),
  239. VMSTATE_UINT32(imr, IMXGPIOState),
  240. VMSTATE_UINT32(isr, IMXGPIOState),
  241. VMSTATE_BOOL(has_edge_sel, IMXGPIOState),
  242. VMSTATE_UINT32(edge_sel, IMXGPIOState),
  243. VMSTATE_END_OF_LIST()
  244. }
  245. };
  246. static const Property imx_gpio_properties[] = {
  247. DEFINE_PROP_BOOL("has-edge-sel", IMXGPIOState, has_edge_sel, true),
  248. DEFINE_PROP_BOOL("has-upper-pin-irq", IMXGPIOState, has_upper_pin_irq,
  249. false),
  250. };
  251. static void imx_gpio_reset(DeviceState *dev)
  252. {
  253. IMXGPIOState *s = IMX_GPIO(dev);
  254. s->dr = 0;
  255. s->gdir = 0;
  256. s->psr = 0;
  257. s->icr = 0;
  258. s->imr = 0;
  259. s->isr = 0;
  260. s->edge_sel = 0;
  261. imx_gpio_set_all_output_lines(s);
  262. imx_gpio_update_int(s);
  263. }
  264. static void imx_gpio_realize(DeviceState *dev, Error **errp)
  265. {
  266. IMXGPIOState *s = IMX_GPIO(dev);
  267. memory_region_init_io(&s->iomem, OBJECT(s), &imx_gpio_ops, s,
  268. TYPE_IMX_GPIO, IMX_GPIO_MEM_SIZE);
  269. qdev_init_gpio_in(DEVICE(s), imx_gpio_set, IMX_GPIO_PIN_COUNT);
  270. qdev_init_gpio_out(DEVICE(s), s->output, IMX_GPIO_PIN_COUNT);
  271. sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[0]);
  272. sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[1]);
  273. sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
  274. }
  275. static void imx_gpio_class_init(ObjectClass *klass, void *data)
  276. {
  277. DeviceClass *dc = DEVICE_CLASS(klass);
  278. dc->realize = imx_gpio_realize;
  279. device_class_set_legacy_reset(dc, imx_gpio_reset);
  280. device_class_set_props(dc, imx_gpio_properties);
  281. dc->vmsd = &vmstate_imx_gpio;
  282. dc->desc = "i.MX GPIO controller";
  283. }
  284. static const TypeInfo imx_gpio_info = {
  285. .name = TYPE_IMX_GPIO,
  286. .parent = TYPE_SYS_BUS_DEVICE,
  287. .instance_size = sizeof(IMXGPIOState),
  288. .class_init = imx_gpio_class_init,
  289. };
  290. static void imx_gpio_register_types(void)
  291. {
  292. type_register_static(&imx_gpio_info);
  293. }
  294. type_init(imx_gpio_register_types)