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