Commit b7f4e50311a708f1d07c6add476b4f7812d25bd4

Authored by Evgeniy Dushistov
1 parent 2a3e33f7

TC:

- access to register not working
- acess to rc return rb register
- emulate TC usage for fast delay
Showing 1 changed file with 62 additions and 28 deletions
hw/at91_tc.c
... ... @@ -72,15 +72,23 @@ static void at91_tc_tick(void *opaque)
72 72 {
73 73 TCChannelState *s = opaque;
74 74  
75   - s->cv++;
76   - /* TODO: Overflow check */
77   - if (s->cv == s->ra) {
78   - s->sr |= SR_CPAS;
79   - }
80   - if (s->cv == s->rb) {
81   - s->sr |= SR_CPBS;
82   - }
83   - if (s->cv == s->rc) {
  75 + if (s->mr & MR_WAVE) {
  76 + s->cv++;
  77 + /* TODO: Overflow check */
  78 + if (s->cv == s->ra) {
  79 + s->sr |= SR_CPAS;
  80 + }
  81 + if (s->cv == s->rb) {
  82 + s->sr |= SR_CPBS;
  83 + }
  84 + if (s->cv == s->rc) {
  85 + s->sr |= SR_CPCS;
  86 + if (s->mr & MR_RCTRIG) {
  87 + s->cv = 0;
  88 + }
  89 + }
  90 + } else {
  91 + s->cv = s->rc;
84 92 s->sr |= SR_CPCS;
85 93 if (s->mr & MR_RCTRIG) {
86 94 s->cv = 0;
... ... @@ -106,7 +114,7 @@ static uint32_t at91_tc_channel_read(TCChannelState *s,
106 114 case TC_RB:
107 115 return s->rb;
108 116 case TC_RC:
109   - return s->rb;
  117 + return s->rc;
110 118 case TC_SR:
111 119 sr = s->sr;
112 120 s->sr = 0;
... ... @@ -119,6 +127,23 @@ static uint32_t at91_tc_channel_read(TCChannelState *s,
119 127 }
120 128 }
121 129  
  130 +static int at91_tc_get_freq(uint32_t cmr)
  131 +{
  132 + int freq;
  133 +
  134 + switch (cmr & 7) {
  135 + case 0: freq = at91_master_clock_frequency / 2; break;
  136 + case 1: freq = at91_master_clock_frequency / 8; break;
  137 + case 2: freq = at91_master_clock_frequency / 32; break;
  138 + case 3: freq = at91_master_clock_frequency / 128; break;
  139 + case 4: freq = at91_master_clock_frequency / 1024; break;
  140 + default: /* TODO: External clocks */
  141 + freq = at91_master_clock_frequency / 16;
  142 + break;
  143 + }
  144 + return freq;
  145 +}
  146 +
122 147 static void at91_tc_channel_write(TCChannelState *s,
123 148 target_phys_addr_t offset, uint32_t value)
124 149 {
... ... @@ -127,30 +152,36 @@ static void at91_tc_channel_write(TCChannelState *s,
127 152 switch (offset) {
128 153 case TC_CCR:
129 154 if ((value & 3) == 1) {
130   - if (s->mr & MR_WAVE) {
131   - s->cv = 0;
132   - ptimer_run(s->timer, 0);
  155 + if (!(s->mr & MR_WAVE)) {
  156 + if (s->imr == 0 && s->rc != 0) {
  157 + freq = at91_tc_get_freq(s->mr);
  158 + freq /= s->rc;
  159 + if (freq > 1000) {
  160 + //just busy loop too wait something, with resolution more then 1ms
  161 + s->cv = s->rc;
  162 + s->sr |= SR_CPCS;
  163 + if (s->mr & MR_RCTRIG) {
  164 + s->cv = 0;
  165 + }
  166 + break;
  167 + }
  168 + }
  169 + //tick only once, this should speedup system
  170 + ptimer_set_limit(s->timer, s->rc, 1);
133 171 }
134   - /* TODO: Counter mode */
  172 +
  173 + s->cv = 0;
  174 + ptimer_run(s->timer, 0);
135 175 } else if (value & 2) {
136 176 ptimer_stop(s->timer);
  177 + ptimer_set_limit(s->timer, 1, 1);
137 178 }
138 179 break;
139 180 case TC_CMR:
140   - if (value & MR_WAVE) {
141   - switch (value & 7) {
142   - case 0: freq = at91_master_clock_frequency / 2; break;
143   - case 1: freq = at91_master_clock_frequency / 8; break;
144   - case 2: freq = at91_master_clock_frequency / 32; break;
145   - case 3: freq = at91_master_clock_frequency / 128; break;
146   - case 4: freq = at91_master_clock_frequency / 1024; break;
147   - default: /* TODO: External clocks */
148   - freq = at91_master_clock_frequency / 16;
149   - break;
150   - }
151   - ptimer_set_freq(s->timer, freq);
152   - }
153   - /* TODO: Counter mode */
  181 + freq = at91_tc_get_freq(value);
  182 +
  183 + ptimer_set_freq(s->timer, freq);
  184 +
154 185 s->mr = value;
155 186 break;
156 187 case TC_RA:
... ... @@ -175,6 +206,7 @@ static uint32_t at91_tc_mem_read(void *opaque, target_phys_addr_t offset)
175 206 {
176 207 TCState *s = opaque;
177 208  
  209 + offset &= TC_SIZE - 1;
178 210 switch (offset) {
179 211 case TC_BMR:
180 212 return 0; /* TODO */
... ... @@ -194,6 +226,8 @@ static void at91_tc_mem_write(void *opaque, target_phys_addr_t offset,
194 226 {
195 227 TCState *s = opaque;
196 228  
  229 + offset &= TC_SIZE - 1;
  230 +
197 231 switch (offset) {
198 232 case TC_BCR:
199 233 return; /* TODO */
... ...