omap_gpio.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /*
  2. * TI OMAP processors GPIO emulation.
  3. *
  4. * Copyright (C) 2006-2008 Andrzej Zaborowski <balrog@zabor.org>
  5. * Copyright (C) 2007-2009 Nokia Corporation
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 or
  10. * (at your option) version 3 of the License.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program; if not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include "qemu/osdep.h"
  21. #include "qemu/log.h"
  22. #include "hw/irq.h"
  23. #include "hw/qdev-properties.h"
  24. #include "hw/arm/omap.h"
  25. #include "hw/sysbus.h"
  26. #include "qemu/error-report.h"
  27. #include "qemu/module.h"
  28. #include "qapi/error.h"
  29. struct omap_gpio_s {
  30. qemu_irq irq;
  31. qemu_irq handler[16];
  32. uint16_t inputs;
  33. uint16_t outputs;
  34. uint16_t dir;
  35. uint16_t edge;
  36. uint16_t mask;
  37. uint16_t ints;
  38. uint16_t pins;
  39. };
  40. struct Omap1GpioState {
  41. SysBusDevice parent_obj;
  42. MemoryRegion iomem;
  43. int mpu_model;
  44. void *clk;
  45. struct omap_gpio_s omap1;
  46. };
  47. /* General-Purpose I/O of OMAP1 */
  48. static void omap_gpio_set(void *opaque, int line, int level)
  49. {
  50. Omap1GpioState *p = opaque;
  51. struct omap_gpio_s *s = &p->omap1;
  52. uint16_t prev = s->inputs;
  53. if (level)
  54. s->inputs |= 1 << line;
  55. else
  56. s->inputs &= ~(1 << line);
  57. if (((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) &
  58. (1 << line) & s->dir & ~s->mask) {
  59. s->ints |= 1 << line;
  60. qemu_irq_raise(s->irq);
  61. }
  62. }
  63. static uint64_t omap_gpio_read(void *opaque, hwaddr addr,
  64. unsigned size)
  65. {
  66. struct omap_gpio_s *s = opaque;
  67. int offset = addr & OMAP_MPUI_REG_MASK;
  68. if (size != 2) {
  69. return omap_badwidth_read16(opaque, addr);
  70. }
  71. switch (offset) {
  72. case 0x00: /* DATA_INPUT */
  73. return s->inputs & s->pins;
  74. case 0x04: /* DATA_OUTPUT */
  75. return s->outputs;
  76. case 0x08: /* DIRECTION_CONTROL */
  77. return s->dir;
  78. case 0x0c: /* INTERRUPT_CONTROL */
  79. return s->edge;
  80. case 0x10: /* INTERRUPT_MASK */
  81. return s->mask;
  82. case 0x14: /* INTERRUPT_STATUS */
  83. return s->ints;
  84. case 0x18: /* PIN_CONTROL (not in OMAP310) */
  85. OMAP_BAD_REG(addr);
  86. return s->pins;
  87. }
  88. OMAP_BAD_REG(addr);
  89. return 0;
  90. }
  91. static void omap_gpio_write(void *opaque, hwaddr addr,
  92. uint64_t value, unsigned size)
  93. {
  94. struct omap_gpio_s *s = opaque;
  95. int offset = addr & OMAP_MPUI_REG_MASK;
  96. uint16_t diff;
  97. int ln;
  98. if (size != 2) {
  99. omap_badwidth_write16(opaque, addr, value);
  100. return;
  101. }
  102. switch (offset) {
  103. case 0x00: /* DATA_INPUT */
  104. OMAP_RO_REG(addr);
  105. return;
  106. case 0x04: /* DATA_OUTPUT */
  107. diff = (s->outputs ^ value) & ~s->dir;
  108. s->outputs = value;
  109. while ((ln = ctz32(diff)) != 32) {
  110. if (s->handler[ln])
  111. qemu_set_irq(s->handler[ln], (value >> ln) & 1);
  112. diff &= ~(1 << ln);
  113. }
  114. break;
  115. case 0x08: /* DIRECTION_CONTROL */
  116. diff = s->outputs & (s->dir ^ value);
  117. s->dir = value;
  118. value = s->outputs & ~s->dir;
  119. while ((ln = ctz32(diff)) != 32) {
  120. if (s->handler[ln])
  121. qemu_set_irq(s->handler[ln], (value >> ln) & 1);
  122. diff &= ~(1 << ln);
  123. }
  124. break;
  125. case 0x0c: /* INTERRUPT_CONTROL */
  126. s->edge = value;
  127. break;
  128. case 0x10: /* INTERRUPT_MASK */
  129. s->mask = value;
  130. break;
  131. case 0x14: /* INTERRUPT_STATUS */
  132. s->ints &= ~value;
  133. if (!s->ints)
  134. qemu_irq_lower(s->irq);
  135. break;
  136. case 0x18: /* PIN_CONTROL (not in OMAP310 TRM) */
  137. OMAP_BAD_REG(addr);
  138. s->pins = value;
  139. break;
  140. default:
  141. OMAP_BAD_REG(addr);
  142. return;
  143. }
  144. }
  145. /* *Some* sources say the memory region is 32-bit. */
  146. static const MemoryRegionOps omap_gpio_ops = {
  147. .read = omap_gpio_read,
  148. .write = omap_gpio_write,
  149. .endianness = DEVICE_NATIVE_ENDIAN,
  150. };
  151. static void omap_gpio_reset(struct omap_gpio_s *s)
  152. {
  153. s->inputs = 0;
  154. s->outputs = ~0;
  155. s->dir = ~0;
  156. s->edge = ~0;
  157. s->mask = ~0;
  158. s->ints = 0;
  159. s->pins = ~0;
  160. }
  161. static void omap_gpif_reset(DeviceState *dev)
  162. {
  163. Omap1GpioState *s = OMAP1_GPIO(dev);
  164. omap_gpio_reset(&s->omap1);
  165. }
  166. static void omap_gpio_init(Object *obj)
  167. {
  168. DeviceState *dev = DEVICE(obj);
  169. Omap1GpioState *s = OMAP1_GPIO(obj);
  170. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  171. qdev_init_gpio_in(dev, omap_gpio_set, 16);
  172. qdev_init_gpio_out(dev, s->omap1.handler, 16);
  173. sysbus_init_irq(sbd, &s->omap1.irq);
  174. memory_region_init_io(&s->iomem, obj, &omap_gpio_ops, &s->omap1,
  175. "omap.gpio", 0x1000);
  176. sysbus_init_mmio(sbd, &s->iomem);
  177. }
  178. static void omap_gpio_realize(DeviceState *dev, Error **errp)
  179. {
  180. Omap1GpioState *s = OMAP1_GPIO(dev);
  181. if (!s->clk) {
  182. error_setg(errp, "omap-gpio: clk not connected");
  183. }
  184. }
  185. void omap_gpio_set_clk(Omap1GpioState *gpio, omap_clk clk)
  186. {
  187. gpio->clk = clk;
  188. }
  189. static const Property omap_gpio_properties[] = {
  190. DEFINE_PROP_INT32("mpu_model", Omap1GpioState, mpu_model, 0),
  191. };
  192. static void omap_gpio_class_init(ObjectClass *klass, void *data)
  193. {
  194. DeviceClass *dc = DEVICE_CLASS(klass);
  195. dc->realize = omap_gpio_realize;
  196. device_class_set_legacy_reset(dc, omap_gpif_reset);
  197. device_class_set_props(dc, omap_gpio_properties);
  198. /* Reason: pointer property "clk" */
  199. dc->user_creatable = false;
  200. }
  201. static const TypeInfo omap_gpio_info = {
  202. .name = TYPE_OMAP1_GPIO,
  203. .parent = TYPE_SYS_BUS_DEVICE,
  204. .instance_size = sizeof(Omap1GpioState),
  205. .instance_init = omap_gpio_init,
  206. .class_init = omap_gpio_class_init,
  207. };
  208. static void omap_gpio_register_types(void)
  209. {
  210. type_register_static(&omap_gpio_info);
  211. }
  212. type_init(omap_gpio_register_types)