Commit b7f4e50311a708f1d07c6add476b4f7812d25bd4
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 */ |