dv-bfin_gptimer.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /* Blackfin General Purpose Timers (GPtimer) model
  2. Copyright (C) 2010-2015 Free Software Foundation, Inc.
  3. Contributed by Analog Devices, Inc.
  4. This file is part of simulators.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  15. #include "config.h"
  16. #include "sim-main.h"
  17. #include "devices.h"
  18. #include "dv-bfin_gptimer.h"
  19. /* XXX: This is merely a stub. */
  20. struct bfin_gptimer
  21. {
  22. /* This top portion matches common dv_bfin struct. */
  23. bu32 base;
  24. struct hw *dma_master;
  25. bool acked;
  26. struct hw_event *handler;
  27. char saved_byte;
  28. int saved_count;
  29. /* Order after here is important -- matches hardware MMR layout. */
  30. bu16 BFIN_MMR_16(config);
  31. bu32 counter, period, width;
  32. };
  33. #define mmr_base() offsetof(struct bfin_gptimer, config)
  34. #define mmr_offset(mmr) (offsetof(struct bfin_gptimer, mmr) - mmr_base())
  35. static const char * const mmr_names[] =
  36. {
  37. "TIMER_CONFIG", "TIMER_COUNTER", "TIMER_PERIOD", "TIMER_WIDTH",
  38. };
  39. #define mmr_name(off) mmr_names[(off) / 4]
  40. static unsigned
  41. bfin_gptimer_io_write_buffer (struct hw *me, const void *source, int space,
  42. address_word addr, unsigned nr_bytes)
  43. {
  44. struct bfin_gptimer *gptimer = hw_data (me);
  45. bu32 mmr_off;
  46. bu32 value;
  47. bu16 *value16p;
  48. bu32 *value32p;
  49. void *valuep;
  50. if (nr_bytes == 4)
  51. value = dv_load_4 (source);
  52. else
  53. value = dv_load_2 (source);
  54. mmr_off = addr - gptimer->base;
  55. valuep = (void *)((unsigned long)gptimer + mmr_base() + mmr_off);
  56. value16p = valuep;
  57. value32p = valuep;
  58. HW_TRACE_WRITE ();
  59. switch (mmr_off)
  60. {
  61. case mmr_offset(config):
  62. dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
  63. *value16p = value;
  64. break;
  65. case mmr_offset(counter):
  66. case mmr_offset(period):
  67. case mmr_offset(width):
  68. dv_bfin_mmr_require_32 (me, addr, nr_bytes, true);
  69. *value32p = value;
  70. break;
  71. default:
  72. dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
  73. break;
  74. }
  75. return nr_bytes;
  76. }
  77. static unsigned
  78. bfin_gptimer_io_read_buffer (struct hw *me, void *dest, int space,
  79. address_word addr, unsigned nr_bytes)
  80. {
  81. struct bfin_gptimer *gptimer = hw_data (me);
  82. bu32 mmr_off;
  83. bu16 *value16p;
  84. bu32 *value32p;
  85. void *valuep;
  86. mmr_off = addr - gptimer->base;
  87. valuep = (void *)((unsigned long)gptimer + mmr_base() + mmr_off);
  88. value16p = valuep;
  89. value32p = valuep;
  90. HW_TRACE_READ ();
  91. switch (mmr_off)
  92. {
  93. case mmr_offset(config):
  94. dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
  95. dv_store_2 (dest, *value16p);
  96. break;
  97. case mmr_offset(counter):
  98. case mmr_offset(period):
  99. case mmr_offset(width):
  100. dv_bfin_mmr_require_32 (me, addr, nr_bytes, false);
  101. dv_store_4 (dest, *value32p);
  102. break;
  103. default:
  104. dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
  105. break;
  106. }
  107. return nr_bytes;
  108. }
  109. static const struct hw_port_descriptor bfin_gptimer_ports[] =
  110. {
  111. { "stat", 0, 0, output_port, },
  112. { NULL, 0, 0, 0, },
  113. };
  114. static void
  115. attach_bfin_gptimer_regs (struct hw *me, struct bfin_gptimer *gptimer)
  116. {
  117. address_word attach_address;
  118. int attach_space;
  119. unsigned attach_size;
  120. reg_property_spec reg;
  121. if (hw_find_property (me, "reg") == NULL)
  122. hw_abort (me, "Missing \"reg\" property");
  123. if (!hw_find_reg_array_property (me, "reg", 0, &reg))
  124. hw_abort (me, "\"reg\" property must contain three addr/size entries");
  125. hw_unit_address_to_attach_address (hw_parent (me),
  126. &reg.address,
  127. &attach_space, &attach_address, me);
  128. hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
  129. if (attach_size != BFIN_MMR_GPTIMER_SIZE)
  130. hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_GPTIMER_SIZE);
  131. hw_attach_address (hw_parent (me),
  132. 0, attach_space, attach_address, attach_size, me);
  133. gptimer->base = attach_address;
  134. }
  135. static void
  136. bfin_gptimer_finish (struct hw *me)
  137. {
  138. struct bfin_gptimer *gptimer;
  139. gptimer = HW_ZALLOC (me, struct bfin_gptimer);
  140. set_hw_data (me, gptimer);
  141. set_hw_io_read_buffer (me, bfin_gptimer_io_read_buffer);
  142. set_hw_io_write_buffer (me, bfin_gptimer_io_write_buffer);
  143. set_hw_ports (me, bfin_gptimer_ports);
  144. attach_bfin_gptimer_regs (me, gptimer);
  145. }
  146. const struct hw_descriptor dv_bfin_gptimer_descriptor[] =
  147. {
  148. {"bfin_gptimer", bfin_gptimer_finish,},
  149. {NULL, NULL},
  150. };