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,15 +72,23 @@ static void at91_tc_tick(void *opaque)
72 { 72 {
73 TCChannelState *s = opaque; 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 s->sr |= SR_CPCS; 92 s->sr |= SR_CPCS;
85 if (s->mr & MR_RCTRIG) { 93 if (s->mr & MR_RCTRIG) {
86 s->cv = 0; 94 s->cv = 0;
@@ -106,7 +114,7 @@ static uint32_t at91_tc_channel_read(TCChannelState *s, @@ -106,7 +114,7 @@ static uint32_t at91_tc_channel_read(TCChannelState *s,
106 case TC_RB: 114 case TC_RB:
107 return s->rb; 115 return s->rb;
108 case TC_RC: 116 case TC_RC:
109 - return s->rb; 117 + return s->rc;
110 case TC_SR: 118 case TC_SR:
111 sr = s->sr; 119 sr = s->sr;
112 s->sr = 0; 120 s->sr = 0;
@@ -119,6 +127,23 @@ static uint32_t at91_tc_channel_read(TCChannelState *s, @@ -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 static void at91_tc_channel_write(TCChannelState *s, 147 static void at91_tc_channel_write(TCChannelState *s,
123 target_phys_addr_t offset, uint32_t value) 148 target_phys_addr_t offset, uint32_t value)
124 { 149 {
@@ -127,30 +152,36 @@ static void at91_tc_channel_write(TCChannelState *s, @@ -127,30 +152,36 @@ static void at91_tc_channel_write(TCChannelState *s,
127 switch (offset) { 152 switch (offset) {
128 case TC_CCR: 153 case TC_CCR:
129 if ((value & 3) == 1) { 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 } else if (value & 2) { 175 } else if (value & 2) {
136 ptimer_stop(s->timer); 176 ptimer_stop(s->timer);
  177 + ptimer_set_limit(s->timer, 1, 1);
137 } 178 }
138 break; 179 break;
139 case TC_CMR: 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 s->mr = value; 185 s->mr = value;
155 break; 186 break;
156 case TC_RA: 187 case TC_RA:
@@ -175,6 +206,7 @@ static uint32_t at91_tc_mem_read(void *opaque, target_phys_addr_t offset) @@ -175,6 +206,7 @@ static uint32_t at91_tc_mem_read(void *opaque, target_phys_addr_t offset)
175 { 206 {
176 TCState *s = opaque; 207 TCState *s = opaque;
177 208
  209 + offset &= TC_SIZE - 1;
178 switch (offset) { 210 switch (offset) {
179 case TC_BMR: 211 case TC_BMR:
180 return 0; /* TODO */ 212 return 0; /* TODO */
@@ -194,6 +226,8 @@ static void at91_tc_mem_write(void *opaque, target_phys_addr_t offset, @@ -194,6 +226,8 @@ static void at91_tc_mem_write(void *opaque, target_phys_addr_t offset,
194 { 226 {
195 TCState *s = opaque; 227 TCState *s = opaque;
196 228
  229 + offset &= TC_SIZE - 1;
  230 +
197 switch (offset) { 231 switch (offset) {
198 case TC_BCR: 232 case TC_BCR:
199 return; /* TODO */ 233 return; /* TODO */