Commit 602372237dc783d1cf947b766e00d6ec75dfdb38

Authored by edgar_igl
1 parent f062058f

ETRAX timers: Improve the support for timer1 and let the board-setup choose irq nr.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4301 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 54 additions and 65 deletions
hw/etraxfs_timer.c
@@ -48,27 +48,23 @@ struct fs_timer_t { @@ -48,27 +48,23 @@ struct fs_timer_t {
48 48
49 QEMUBH *bh; 49 QEMUBH *bh;
50 ptimer_state *ptimer; 50 ptimer_state *ptimer;
51 - unsigned int limit;  
52 - int scale;  
53 - uint32_t mask;  
54 struct timeval last; 51 struct timeval last;
55 52
  53 + /* Control registers. */
  54 + uint32_t rw_tmr0_div;
  55 + uint32_t r_tmr0_data;
  56 + uint32_t rw_tmr0_ctrl;
  57 +
  58 + uint32_t rw_tmr1_div;
  59 + uint32_t r_tmr1_data;
  60 + uint32_t rw_tmr1_ctrl;
  61 +
56 uint32_t rw_intr_mask; 62 uint32_t rw_intr_mask;
57 uint32_t rw_ack_intr; 63 uint32_t rw_ack_intr;
58 uint32_t r_intr; 64 uint32_t r_intr;
  65 + uint32_t r_masked_intr;
59 }; 66 };
60 67
61 -/* diff two timevals. Return a single int in us. */  
62 -int diff_timeval_us(struct timeval *a, struct timeval *b)  
63 -{  
64 - int diff;  
65 -  
66 - /* assume these values are signed. */  
67 - diff = (a->tv_sec - b->tv_sec) * 1000 * 1000;  
68 - diff += (a->tv_usec - b->tv_usec);  
69 - return diff;  
70 -}  
71 -  
72 static uint32_t timer_rinvalid (void *opaque, target_phys_addr_t addr) 68 static uint32_t timer_rinvalid (void *opaque, target_phys_addr_t addr)
73 { 69 {
74 struct fs_timer_t *t = opaque; 70 struct fs_timer_t *t = opaque;
@@ -93,19 +89,8 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) @@ -93,19 +89,8 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr)
93 D(printf ("R_TMR1_DATA\n")); 89 D(printf ("R_TMR1_DATA\n"));
94 break; 90 break;
95 case R_TIME: 91 case R_TIME:
96 - {  
97 - struct timeval now;  
98 - gettimeofday(&now, NULL);  
99 - if (!(t->last.tv_sec == 0  
100 - && t->last.tv_usec == 0)) {  
101 - r = diff_timeval_us(&now, &t->last);  
102 - r *= 1000; /* convert to ns. */  
103 - r++; /* make sure we increase for each call. */  
104 - }  
105 - t->last = now; 92 + r = qemu_get_clock(vm_clock) * 10;
106 break; 93 break;
107 - }  
108 -  
109 case RW_INTR_MASK: 94 case RW_INTR_MASK:
110 r = t->rw_intr_mask; 95 r = t->rw_intr_mask;
111 break; 96 break;
@@ -128,14 +113,16 @@ timer_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value) @@ -128,14 +113,16 @@ timer_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value)
128 addr, env->pc); 113 addr, env->pc);
129 } 114 }
130 115
131 -static void write_ctrl(struct fs_timer_t *t, uint32_t v) 116 +#define TIMER_SLOWDOWN 4
  117 +static void update_ctrl(struct fs_timer_t *t)
132 { 118 {
133 - int op;  
134 - int freq;  
135 - int freq_hz; 119 + unsigned int op;
  120 + unsigned int freq;
  121 + unsigned int freq_hz;
  122 + unsigned int div;
136 123
137 - op = v & 3;  
138 - freq = v >> 2; 124 + op = t->rw_tmr0_ctrl & 3;
  125 + freq = t->rw_tmr0_ctrl >> 2;
139 freq_hz = 32000000; 126 freq_hz = 32000000;
140 127
141 switch (freq) 128 switch (freq)
@@ -153,25 +140,26 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v) @@ -153,25 +140,26 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v)
153 break; 140 break;
154 } 141 }
155 142
156 - D(printf ("freq_hz=%d limit=%d\n", freq_hz, t->limit));  
157 - t->scale = 0;  
158 - if (t->limit > 2048)  
159 - {  
160 - t->scale = 2048;  
161 - ptimer_set_period(t->ptimer, freq_hz / t->scale);  
162 - } 143 + D(printf ("freq_hz=%d div=%d\n", freq_hz, t->rw_tmr0_div));
  144 + div = t->rw_tmr0_div * TIMER_SLOWDOWN;
  145 + div >>= 15;
  146 + freq_hz >>= 15;
  147 + ptimer_set_freq(t->ptimer, freq_hz);
  148 + ptimer_set_limit(t->ptimer, div, 0);
163 149
164 switch (op) 150 switch (op)
165 { 151 {
166 case 0: 152 case 0:
167 - D(printf ("limit=%d %d\n",  
168 - t->limit, t->limit/t->scale));  
169 - ptimer_set_limit(t->ptimer, t->limit / t->scale, 1); 153 + /* Load. */
  154 + ptimer_set_limit(t->ptimer, div, 1);
  155 + ptimer_run(t->ptimer, 1);
170 break; 156 break;
171 case 1: 157 case 1:
  158 + /* Hold. */
172 ptimer_stop(t->ptimer); 159 ptimer_stop(t->ptimer);
173 break; 160 break;
174 case 2: 161 case 2:
  162 + /* Run. */
175 ptimer_run(t->ptimer, 0); 163 ptimer_run(t->ptimer, 0);
176 break; 164 break;
177 default: 165 default:
@@ -180,34 +168,44 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v) @@ -180,34 +168,44 @@ static void write_ctrl(struct fs_timer_t *t, uint32_t v)
180 } 168 }
181 } 169 }
182 170
183 -static void timer_ack_irq(struct fs_timer_t *t) 171 +static void timer_update_irq(struct fs_timer_t *t)
184 { 172 {
185 - if (!(t->r_intr & t->mask & t->rw_intr_mask)) 173 + t->r_intr &= ~(t->rw_ack_intr);
  174 + t->r_masked_intr = t->r_intr & t->rw_intr_mask;
  175 +
  176 + D(printf("%s: masked_intr=%x\n", __func__, t->r_masked_intr));
  177 + if (t->r_masked_intr & 1)
  178 + qemu_irq_raise(t->irq[0]);
  179 + else
186 qemu_irq_lower(t->irq[0]); 180 qemu_irq_lower(t->irq[0]);
187 } 181 }
188 182
  183 +static void timer_hit(struct fs_timer_t *t)
  184 +{
  185 + t->r_intr |= 1;
  186 + timer_update_irq(t);
  187 +}
  188 +
189 static void 189 static void
190 timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) 190 timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
191 { 191 {
192 struct fs_timer_t *t = opaque; 192 struct fs_timer_t *t = opaque;
193 CPUState *env = t->env; 193 CPUState *env = t->env;
194 194
195 - D(printf ("%s %x %x pc=%x\n",  
196 - __func__, addr, value, env->pc));  
197 /* Make addr relative to this instances base. */ 195 /* Make addr relative to this instances base. */
198 addr -= t->base; 196 addr -= t->base;
199 switch (addr) 197 switch (addr)
200 { 198 {
201 case RW_TMR0_DIV: 199 case RW_TMR0_DIV:
202 - D(printf ("RW_TMR0_DIV=%x\n", value));  
203 - t->limit = value; 200 + t->rw_tmr0_div = value;
204 break; 201 break;
205 case RW_TMR0_CTRL: 202 case RW_TMR0_CTRL:
206 D(printf ("RW_TMR0_CTRL=%x\n", value)); 203 D(printf ("RW_TMR0_CTRL=%x\n", value));
207 - write_ctrl(t, value); 204 + t->rw_tmr0_ctrl = value;
  205 + update_ctrl(t);
208 break; 206 break;
209 case RW_TMR1_DIV: 207 case RW_TMR1_DIV:
210 - D(printf ("RW_TMR1_DIV=%x\n", value)); 208 + t->rw_tmr1_div = value;
211 break; 209 break;
212 case RW_TMR1_CTRL: 210 case RW_TMR1_CTRL:
213 D(printf ("RW_TMR1_CTRL=%x\n", value)); 211 D(printf ("RW_TMR1_CTRL=%x\n", value));
@@ -215,13 +213,15 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) @@ -215,13 +213,15 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
215 case RW_INTR_MASK: 213 case RW_INTR_MASK:
216 D(printf ("RW_INTR_MASK=%x\n", value)); 214 D(printf ("RW_INTR_MASK=%x\n", value));
217 t->rw_intr_mask = value; 215 t->rw_intr_mask = value;
  216 + timer_update_irq(t);
218 break; 217 break;
219 case RW_WD_CTRL: 218 case RW_WD_CTRL:
220 D(printf ("RW_WD_CTRL=%x\n", value)); 219 D(printf ("RW_WD_CTRL=%x\n", value));
221 break; 220 break;
222 case RW_ACK_INTR: 221 case RW_ACK_INTR:
223 - t->r_intr &= ~value;  
224 - timer_ack_irq(t); 222 + t->rw_ack_intr = value;
  223 + timer_update_irq(t);
  224 + t->rw_ack_intr = 0;
225 break; 225 break;
226 default: 226 default:
227 printf ("%s %x %x pc=%x\n", 227 printf ("%s %x %x pc=%x\n",
@@ -242,16 +242,6 @@ static CPUWriteMemoryFunc *timer_write[] = { @@ -242,16 +242,6 @@ static CPUWriteMemoryFunc *timer_write[] = {
242 &timer_writel, 242 &timer_writel,
243 }; 243 };
244 244
245 -static void timer_irq(void *opaque)  
246 -{  
247 - struct fs_timer_t *t = opaque;  
248 - t->r_intr |= t->mask;  
249 - if (t->mask & t->rw_intr_mask) {  
250 - D(printf("%s raise\n", __func__));  
251 - qemu_irq_raise(t->irq[0]);  
252 - }  
253 -}  
254 -  
255 void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, 245 void etraxfs_timer_init(CPUState *env, qemu_irq *irqs,
256 target_phys_addr_t base) 246 target_phys_addr_t base)
257 { 247 {
@@ -262,10 +252,9 @@ void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, @@ -262,10 +252,9 @@ void etraxfs_timer_init(CPUState *env, qemu_irq *irqs,
262 if (!t) 252 if (!t)
263 return; 253 return;
264 254
265 - t->bh = qemu_bh_new(timer_irq, t); 255 + t->bh = qemu_bh_new(timer_hit, t);
266 t->ptimer = ptimer_init(t->bh); 256 t->ptimer = ptimer_init(t->bh);
267 - t->irq = irqs + 26;  
268 - t->mask = 1; 257 + t->irq = irqs;
269 t->env = env; 258 t->env = env;
270 t->base = base; 259 t->base = base;
271 260