change TARGET_PHYS_ADDR_BITS t0 64 bits(same as qemu)
[qemu/qemu-JZ.git] / hw / mips_jz_glue.h
blobc974e6344edf4a3a4d508bca2adc932e96876f37
1 /*
2 * QEMU JZ Soc emulation glue code
4 * Copyright (c) 2009 yajin (yajin@vm-kernel.org)
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
27 #ifdef TCU_INDEX
28 static inline void glue(jz4740_tcu_time_sync,
29 TCU_INDEX) (struct jz4740_tcu_s * s)
31 int64_t distance;
32 int64_t temp;
34 if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))
35 && (s->freq[TCU_INDEX] != 0))
37 //debug_out(DEBUG_TCU, "jz4740_tcu_time_sync%x \n", TCU_INDEX);
38 /*first enable timer */
39 if (s->time[TCU_INDEX] == 0)
41 s->time[TCU_INDEX] = qemu_get_clock(vm_clock);
42 s->tcnt[TCU_INDEX] = 0;
43 return;
45 distance = qemu_get_clock(vm_clock) - s->time[TCU_INDEX];
46 //debug_out(DEBUG_TCU,
47 // "s->freq[TCU_INDEX] %d s->prescale[TCU_INDEX] %d \n",
48 // s->freq[TCU_INDEX], s->prescale[TCU_INDEX]);
49 // debug_out(DEBUG_TCU, "distance %lld s->time[TCU_INDEX] %lld \n",
50 // distance, s->time[TCU_INDEX]);
51 //temp = muldiv64(distance,(s->freq[TCU_INDEX]/s->prescale[TCU_INDEX]),ticks_per_sec);
52 temp = muldiv64(distance, 46875, ticks_per_sec);
53 if (temp != 0)
55 /*distance is too short */
56 s->tcnt[TCU_INDEX] += temp;
57 s->time[TCU_INDEX] = qemu_get_clock(vm_clock);
59 else
61 /*distance is too short.
62 * Do not sync timer this timer.
66 //printf("%lld distance %lld \n",muldiv64(distance,(s->freq[TCU_INDEX]/s->prescale[TCU_INDEX]),ticks_per_sec),distance);
68 if (s->tcnt[TCU_INDEX] >= 0x10000)
69 s->tcnt[TCU_INDEX] = 0x0;
75 static inline void glue(jz4740_tcu_start_half,
76 TCU_INDEX) (struct jz4740_tcu_s * s)
78 int64_t next = qemu_get_clock(vm_clock);
79 int64_t count;
81 /*The timer has not beed initialized */
82 if (!s->half_timer[TCU_INDEX])
83 return;
85 if ((!(s->tsr & (1 << (TCU_INDEX+16)))) && (s->ter & (1 << (TCU_INDEX+16)))
86 && (s->freq[TCU_INDEX] != 0))
88 glue(jz4740_tcu_time_sync, TCU_INDEX) (s);
89 /*calculate next fire time */
90 count =
91 (s->tdhr[TCU_INDEX] - s->tcnt[TCU_INDEX]) * s->prescale[TCU_INDEX];
92 next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);
93 qemu_mod_timer(s->half_timer[TCU_INDEX], next);
96 else
97 qemu_del_timer(s->half_timer[TCU_INDEX]);
101 static inline void glue(jz4740_tcu_start_full,
102 TCU_INDEX) (struct jz4740_tcu_s * s)
104 int64_t next = qemu_get_clock(vm_clock);
105 int64_t count;
107 /*The timer has not beed initialized */
108 if (!s->full_timer[TCU_INDEX])
109 return;
111 debug_out(DEBUG_TCU, "s->tsr %d s->ter %d s->freq[TCU_INDEX] %d \n",
112 s->tsr , s->ter ,s->freq[TCU_INDEX]);
113 if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))
114 && (s->freq[TCU_INDEX] != 0))
116 glue(jz4740_tcu_time_sync, TCU_INDEX) (s);
117 /*calculate next fire time */
118 count =
119 (s->tdfr[TCU_INDEX] - s->tcnt[TCU_INDEX]) * s->prescale[TCU_INDEX];
120 next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);
121 qemu_mod_timer(s->full_timer[TCU_INDEX], next);
122 debug_out(DEBUG_TCU, "s->tdfr[TCU_INDEX] %d s->tcnt[TCU_INDEX] %d next %lld \n",
123 s->tdfr[TCU_INDEX] , s->tcnt[TCU_INDEX] ,next);
125 else
126 qemu_del_timer(s->full_timer[TCU_INDEX]);
131 * TCNT will reset to 0 if it reach to TDFR.
132 * So for the half compare, the next fire count is (TDFR-TDHR) + TDHR
135 static void glue(jz4740_tcu_half_cb, TCU_INDEX) (void *opaque)
137 struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;
138 int64_t next = qemu_get_clock(vm_clock);
139 int64_t count;
141 if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))
142 && (s->freq[TCU_INDEX] != 0))
144 count = s->tdfr[TCU_INDEX] * s->prescale[TCU_INDEX];
145 next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);
146 qemu_mod_timer(s->half_timer[TCU_INDEX], next);
147 s->tfr |= 1 << (16 + TCU_INDEX);
148 jz4740_tcu_update_interrupt(s);
149 s->tcnt[TCU_INDEX] = s->tdhr[TCU_INDEX];
150 s->time[TCU_INDEX] = qemu_get_clock(vm_clock);
152 else
153 qemu_del_timer(s->half_timer[TCU_INDEX]);
157 static void glue(jz4740_tcu_full_cb, TCU_INDEX) (void *opaque)
159 struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;
160 int64_t next = qemu_get_clock(vm_clock);
161 int64_t count;
163 if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))
164 && (s->freq[TCU_INDEX] != 0))
166 count = s->tdfr[TCU_INDEX] * s->prescale[TCU_INDEX];
167 next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);
168 qemu_mod_timer(s->full_timer[TCU_INDEX], next);
169 s->tfr |= 1 << TCU_INDEX;
170 jz4740_tcu_update_interrupt(s);
171 s->tcnt[TCU_INDEX] = 0;
172 s->time[TCU_INDEX] = qemu_get_clock(vm_clock);
174 else
175 qemu_del_timer(s->full_timer[TCU_INDEX]);
178 static uint32_t glue(jz4740_tcu_read, TCU_INDEX) (void *opaque,
179 target_phys_addr_t addr)
181 struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;
183 debug_out(DEBUG_TCU, "jz4740_tcu_read%x addr %x\n", TCU_INDEX, addr);
184 addr -= 0x40 + TCU_INDEX * 0x10;
186 switch (addr)
188 case 0x0:
189 return s->tdfr[TCU_INDEX];
190 case 0x4:
191 return s->tdhr[TCU_INDEX];
192 case 0x8:
193 glue(jz4740_tcu_time_sync, TCU_INDEX) (s);
194 return s->tcnt[TCU_INDEX];
195 case 0xc:
196 return s->tcsr[TCU_INDEX];
197 default:
198 cpu_abort(s->soc->env,
199 "jz4740_tcu_read undefined addr "JZ_FMT_plx" timer %x \n", addr,
200 TCU_INDEX);
202 return (0);
205 static void glue(jz4740_tcu_write, TCU_INDEX) (void *opaque,
206 target_phys_addr_t addr,
207 uint32_t value)
209 struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;
211 debug_out(DEBUG_TCU, "jz4740_tcu_write%x addr "JZ_FMT_plx" value %x \n", TCU_INDEX,
212 addr, value);
213 addr -= 0x40 + TCU_INDEX * 0x10;
215 switch (addr)
217 case 0x0:
218 /*TDFR*/
219 s->tdfr[TCU_INDEX] = value & 0xffff;
220 glue(jz4740_tcu_start_full, TCU_INDEX) (s);
221 break;
222 case 0x4:
223 /*TDHR*/ s->tdhr[TCU_INDEX] = value & 0xffff;
224 glue(jz4740_tcu_start_half, TCU_INDEX) (s);
225 break;
226 case 0x8:
227 /*TCNT*/ s->tcnt[TCU_INDEX] = value & 0xffff;
228 s->time[TCU_INDEX] = qemu_get_clock(vm_clock);
229 glue(jz4740_tcu_start_half, TCU_INDEX) (s);
230 glue(jz4740_tcu_start_full, TCU_INDEX) (s);
231 break;
232 case 0xc:
233 s->tcsr[TCU_INDEX] = value & 0x3bf;
234 switch (value & 0x7)
236 case 0x1:
237 s->freq[TCU_INDEX] = jz_clk_getrate(jz_findclk(s->soc, "pclk"));
238 break;
239 case 0x2:
240 s->freq[TCU_INDEX] = jz_clk_getrate(jz_findclk(s->soc, "osc_32K"));
241 break;
242 case 0x4:
243 s->freq[TCU_INDEX] =
244 jz_clk_getrate(jz_findclk(s->soc, "osc_extal"));
245 break;
246 default:
247 s->freq[TCU_INDEX] = 0x0;
248 break;
250 s->prescale[TCU_INDEX] = 1 << (((value & 0x38) >> 3) * 2);
251 glue(jz4740_tcu_start_half, TCU_INDEX) (s);
252 glue(jz4740_tcu_start_full, TCU_INDEX) (s);
253 break;
254 default:
255 cpu_abort(s->soc->env,
256 "jz4740_tcu_write undefined addr "JZ_FMT_plx" timer %x \n", addr,
257 TCU_INDEX);
263 static CPUReadMemoryFunc *glue(jz4740_tcu_readfn, TCU_INDEX)[] =
265 jz4740_badwidth_read16,
266 glue(jz4740_tcu_read, TCU_INDEX), jz4740_badwidth_read16,};
268 static CPUWriteMemoryFunc *glue(jz4740_tcu_writefn, TCU_INDEX)[] =
270 jz4740_badwidth_write16,
271 glue(jz4740_tcu_write, TCU_INDEX), jz4740_badwidth_write16,};
273 static void glue(jz4740_tcu_init, TCU_INDEX) (struct jz_state_s * soc,
274 struct jz4740_tcu_s * s)
276 int iomemtype;
278 s->half_timer[TCU_INDEX] =
279 qemu_new_timer(vm_clock, glue(jz4740_tcu_half_cb, TCU_INDEX), s);
280 s->full_timer[TCU_INDEX] =
281 qemu_new_timer(vm_clock, glue(jz4740_tcu_full_cb, TCU_INDEX), s);
283 iomemtype =
284 cpu_register_io_memory(0, glue(jz4740_tcu_readfn, TCU_INDEX),
285 glue(jz4740_tcu_writefn, TCU_INDEX), s);
286 cpu_register_physical_memory(s->base + 0x00000040 + TCU_INDEX * 0x10,
287 0x00000010, iomemtype);
290 #undef TCU_INDEX
291 #endif
295 #ifdef JZ4740_LCD_PANEL
297 #if DEPTH == 8
298 # define BPP 1
299 # define PIXEL_TYPE uint8_t
300 #elif DEPTH == 15 || DEPTH == 16
301 # define BPP 2
302 # define PIXEL_TYPE uint16_t
303 #elif DEPTH == 24
304 # define BPP 3
305 # define PIXEL_TYPE uint32_t
306 #elif DEPTH == 32
307 # define BPP 4
308 # define PIXEL_TYPE uint32_t
309 #else
310 # error unsupport depth
311 #endif
314 * 2-bit colour
316 static void glue(draw_line2_, DEPTH) (uint8_t * d, const uint8_t * s, int width,
317 const uint16_t * pal)
319 uint8_t v, r, g, b;
323 v = ldub_raw((void *) s);
324 r = (pal[v & 3] >> 4) & 0xf0;
325 g = pal[v & 3] & 0xf0;
326 b = (pal[v & 3] << 4) & 0xf0;
327 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
328 d += BPP;
329 v >>= 2;
330 r = (pal[v & 3] >> 4) & 0xf0;
331 g = pal[v & 3] & 0xf0;
332 b = (pal[v & 3] << 4) & 0xf0;
333 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
334 d += BPP;
335 v >>= 2;
336 r = (pal[v & 3] >> 4) & 0xf0;
337 g = pal[v & 3] & 0xf0;
338 b = (pal[v & 3] << 4) & 0xf0;
339 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
340 d += BPP;
341 v >>= 2;
342 r = (pal[v & 3] >> 4) & 0xf0;
343 g = pal[v & 3] & 0xf0;
344 b = (pal[v & 3] << 4) & 0xf0;
345 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
346 d += BPP;
347 s++;
348 width -= 4;
350 while (width > 0);
354 * 4-bit colour
356 static void glue(draw_line4_, DEPTH) (uint8_t * d, const uint8_t * s, int width,
357 const uint16_t * pal)
359 uint8_t v, r, g, b;
363 v = ldub_raw((void *) s);
364 r = (pal[v & 0xf] >> 4) & 0xf0;
365 g = pal[v & 0xf] & 0xf0;
366 b = (pal[v & 0xf] << 4) & 0xf0;
367 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
368 d += BPP;
369 v >>= 4;
370 r = (pal[v & 0xf] >> 4) & 0xf0;
371 g = pal[v & 0xf] & 0xf0;
372 b = (pal[v & 0xf] << 4) & 0xf0;
373 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
374 d += BPP;
375 s++;
376 width -= 2;
378 while (width > 0);
382 * 8-bit colour
384 static void glue(draw_line8_, DEPTH) (uint8_t * d, const uint8_t * s, int width,
385 const uint16_t * pal)
387 uint8_t v, r, g, b;
391 v = ldub_raw((void *) s);
392 r = (pal[v] >> 4) & 0xf0;
393 g = pal[v] & 0xf0;
394 b = (pal[v] << 4) & 0xf0;
395 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
396 s++;
397 d += BPP;
399 while (--width != 0);
404 * 16-bit colour
406 static void glue(draw_line16_, DEPTH) (uint8_t * d, const uint8_t * s,
407 int width, const uint16_t * pal)
409 #if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
410 memcpy(d, s, width * 2);
411 #else
412 uint16_t v;
413 uint8_t r, g, b;
417 v = lduw_raw((void *) s);
418 r = (v >> 8) & 0xf8;
419 g = (v >> 3) & 0xfc;
420 b = (v << 3) & 0xf8;
421 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
422 s += 2;
423 d += BPP;
425 while (--width != 0);
426 #endif
430 * 24-bit colour. JZ4740 uses 4 bytes to store 18/24 bit color.
432 static void glue(draw_line24_, DEPTH) (uint8_t * d, const uint8_t * s,
433 int width, const uint16_t * pal)
435 #if DEPTH == 32 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
436 memcpy(d, s, width * 4);
437 #else
438 uint32_t v;
439 uint8_t r, g, b;
443 v = ldl_raw((void *) s);
444 r = (v >> 16) & 0xff;
445 g = (v >> 8) & 0xff;
446 b = (v >> 0) & 0xff;
447 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
448 s += 3;
449 d += BPP;
451 while (--width != 0);
452 #endif
455 static jz4740_lcd_fn_t glue(jz4740_lcd_draw_fn_, DEPTH)[6] =
457 NULL, /*0x0 *//*1 bit per pixel */
458 (jz4740_lcd_fn_t) glue(draw_line2_, DEPTH), /*0x1 *//*2 bit per pixel */
459 (jz4740_lcd_fn_t) glue(draw_line4_, DEPTH), /*0x2 *//*4 bit per pixel */
460 (jz4740_lcd_fn_t) glue(draw_line8_, DEPTH), /*0x3 *//*8 bit per pixel */
461 (jz4740_lcd_fn_t) glue(draw_line16_, DEPTH), /*0x4 *//*15/16 bit per pixel */
462 (jz4740_lcd_fn_t) glue(draw_line24_, DEPTH), /*0x5 *//*18/24 bit per pixel */
466 #undef DEPTH
467 #undef BPP
468 #undef PIXEL_TYPE
470 #endif