858bd129d0e3592f37817350e6bf5951131d7b1e
[qemu/qemu-JZ.git] / hw / mips_jz_glue.h
blob858bd129d0e3592f37817350e6bf5951131d7b1e
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 //printf("s->tsr %d s->ter %d s->freq[TCU_INDEX] %d \n",
114 // s->tsr , s->ter ,s->freq[TCU_INDEX]);
115 if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))
116 && (s->freq[TCU_INDEX] != 0))
118 glue(jz4740_tcu_time_sync, TCU_INDEX) (s);
119 //printf("tdfr %x \n",s->tdfr[TCU_INDEX] );
120 /*calculate next fire time */
121 count =
122 (s->tdfr[TCU_INDEX] - s->tcnt[TCU_INDEX]) * s->prescale[TCU_INDEX];
123 //printf("tdfr11 %x count %lld\n",s->tdfr[TCU_INDEX],count );
124 next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);
125 qemu_mod_timer(s->full_timer[TCU_INDEX], next);
126 debug_out(DEBUG_TCU, "s->tdfr[TCU_INDEX] %d s->tcnt[TCU_INDEX] %d next %lld \n",
127 s->tdfr[TCU_INDEX] , s->tcnt[TCU_INDEX] ,next);
128 //printf("s->tdfr[TCU_INDEX]22 %x s->tcnt[TCU_INDEX] %x next %lld \n",
129 // s->tdfr[TCU_INDEX] , s->tcnt[TCU_INDEX] ,next);
132 else
133 qemu_del_timer(s->full_timer[TCU_INDEX]);
138 * TCNT will reset to 0 if it reach to TDFR.
139 * So for the half compare, the next fire count is (TDFR-TDHR) + TDHR
142 static void glue(jz4740_tcu_half_cb, TCU_INDEX) (void *opaque)
144 struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;
145 int64_t next = qemu_get_clock(vm_clock);
146 int64_t count;
148 if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))
149 && (s->freq[TCU_INDEX] != 0))
151 count = s->tdfr[TCU_INDEX] * s->prescale[TCU_INDEX];
152 next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);
153 qemu_mod_timer(s->half_timer[TCU_INDEX], next);
154 s->tfr |= 1 << (16 + TCU_INDEX);
155 jz4740_tcu_update_interrupt(s);
156 s->tcnt[TCU_INDEX] = s->tdhr[TCU_INDEX];
157 s->time[TCU_INDEX] = qemu_get_clock(vm_clock);
159 else
160 qemu_del_timer(s->half_timer[TCU_INDEX]);
164 static void glue(jz4740_tcu_full_cb, TCU_INDEX) (void *opaque)
166 struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;
167 int64_t next = qemu_get_clock(vm_clock);
168 int64_t count;
170 if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))
171 && (s->freq[TCU_INDEX] != 0))
173 //printf("s->tdfr[TCU_INDEX] %x s->prescale[TCU_INDEX] %x \n",s->tdfr[TCU_INDEX] ,s->prescale[TCU_INDEX] );
174 count = s->tdfr[TCU_INDEX] * s->prescale[TCU_INDEX];
175 next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);
176 //printf("count %lld next %lld \n",count,next);
177 qemu_mod_timer(s->full_timer[TCU_INDEX], next);
178 s->tfr |= 1 << TCU_INDEX;
179 jz4740_tcu_update_interrupt(s);
180 s->tcnt[TCU_INDEX] = 0;
181 s->time[TCU_INDEX] = qemu_get_clock(vm_clock);
183 else
184 qemu_del_timer(s->full_timer[TCU_INDEX]);
187 static uint32_t glue(jz4740_tcu_read, TCU_INDEX) (void *opaque,
188 target_phys_addr_t addr)
190 struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;
192 debug_out(DEBUG_TCU, "jz4740_tcu_read%x addr %x\n", TCU_INDEX, addr);
193 addr -= 0x40 + TCU_INDEX * 0x10;
195 switch (addr)
197 case 0x0:
198 return s->tdfr[TCU_INDEX];
199 case 0x4:
200 return s->tdhr[TCU_INDEX];
201 case 0x8:
202 glue(jz4740_tcu_time_sync, TCU_INDEX) (s);
203 //debug_out(DEBUG_TCU, "s->tcnt %x\n", s->tcnt[TCU_INDEX]);
204 //printf("s->tcnt %x\n", s->tcnt[TCU_INDEX]);
205 return s->tcnt[TCU_INDEX];
206 case 0xc:
207 return s->tcsr[TCU_INDEX];
208 default:
209 cpu_abort(s->soc->env,
210 "jz4740_tcu_read undefined addr %x timer %x \n", addr,
211 TCU_INDEX);
213 return (0);
216 static void glue(jz4740_tcu_write, TCU_INDEX) (void *opaque,
217 target_phys_addr_t addr,
218 uint32_t value)
220 struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;
222 debug_out(DEBUG_TCU, "jz4740_tcu_write%x addr %x value %x \n", TCU_INDEX,
223 addr, value);
224 //printf( "jz4740_tcu_write%x addr %x value %x \n", TCU_INDEX,
225 // addr, value);
226 addr -= 0x40 + TCU_INDEX * 0x10;
228 switch (addr)
230 case 0x0:
231 /*TDFR*/
233 s->tdfr[TCU_INDEX] = value & 0xffff;
234 //printf("s->tdfr[TCU_INDEX] %x \n",s->tdfr[TCU_INDEX] );
235 glue(jz4740_tcu_start_full, TCU_INDEX) (s);
236 break;
237 case 0x4:
238 /*TDHR*/ s->tdhr[TCU_INDEX] = value & 0xffff;
239 glue(jz4740_tcu_start_half, TCU_INDEX) (s);
240 break;
241 case 0x8:
242 /*TCNT*/ s->tcnt[TCU_INDEX] = value & 0xffff;
243 s->time[TCU_INDEX] = qemu_get_clock(vm_clock);
244 glue(jz4740_tcu_start_half, TCU_INDEX) (s);
245 glue(jz4740_tcu_start_full, TCU_INDEX) (s);
246 break;
247 case 0xc:
248 s->tcsr[TCU_INDEX] = value & 0x3bf;
249 switch (value & 0x7)
251 case 0x1:
252 s->freq[TCU_INDEX] = jz_clk_getrate(jz_findclk(s->soc, "pclk"));
253 break;
254 case 0x2:
255 s->freq[TCU_INDEX] = jz_clk_getrate(jz_findclk(s->soc, "osc_32K"));
256 break;
257 case 0x4:
258 s->freq[TCU_INDEX] =
259 jz_clk_getrate(jz_findclk(s->soc, "osc_extal"));
260 break;
261 default:
262 s->freq[TCU_INDEX] = 0x0;
263 break;
265 s->prescale[TCU_INDEX] = 1 << (((value & 0x38) >> 3) * 2);
266 glue(jz4740_tcu_start_half, TCU_INDEX) (s);
267 glue(jz4740_tcu_start_full, TCU_INDEX) (s);
268 break;
269 default:
270 cpu_abort(s->soc->env,
271 "jz4740_tcu_write undefined addr %x timer %x \n", addr,
272 TCU_INDEX);
278 static CPUReadMemoryFunc *glue(jz4740_tcu_readfn, TCU_INDEX)[] =
280 jz4740_badwidth_read16,
281 glue(jz4740_tcu_read, TCU_INDEX), jz4740_badwidth_read16,};
283 static CPUWriteMemoryFunc *glue(jz4740_tcu_writefn, TCU_INDEX)[] =
285 jz4740_badwidth_write16,
286 glue(jz4740_tcu_write, TCU_INDEX), jz4740_badwidth_write16,};
288 static void glue(jz4740_tcu_init, TCU_INDEX) (struct jz_state_s * soc,
289 struct jz4740_tcu_s * s)
291 int iomemtype;
293 s->half_timer[TCU_INDEX] =
294 qemu_new_timer(vm_clock, glue(jz4740_tcu_half_cb, TCU_INDEX), s);
295 s->full_timer[TCU_INDEX] =
296 qemu_new_timer(vm_clock, glue(jz4740_tcu_full_cb, TCU_INDEX), s);
298 iomemtype =
299 cpu_register_io_memory(0, glue(jz4740_tcu_readfn, TCU_INDEX),
300 glue(jz4740_tcu_writefn, TCU_INDEX), s);
301 cpu_register_physical_memory(s->base + 0x00000040 + TCU_INDEX * 0x10,
302 0x00000010, iomemtype);
305 #undef TCU_INDEX
306 #endif
310 #ifdef JZ4740_LCD_PANEL
312 #if DEPTH == 8
313 # define BPP 1
314 # define PIXEL_TYPE uint8_t
315 #elif DEPTH == 15 || DEPTH == 16
316 # define BPP 2
317 # define PIXEL_TYPE uint16_t
318 #elif DEPTH == 24
319 # define BPP 3
320 # define PIXEL_TYPE uint32_t
321 #elif DEPTH == 32
322 # define BPP 4
323 # define PIXEL_TYPE uint32_t
324 #else
325 # error unsupport depth
326 #endif
329 * 2-bit colour
331 static void glue(draw_line2_, DEPTH) (uint8_t * d, const uint8_t * s, int width,
332 const uint16_t * pal)
334 uint8_t v, r, g, b;
338 v = ldub_raw((void *) s);
339 r = (pal[v & 3] >> 4) & 0xf0;
340 g = pal[v & 3] & 0xf0;
341 b = (pal[v & 3] << 4) & 0xf0;
342 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
343 d += BPP;
344 v >>= 2;
345 r = (pal[v & 3] >> 4) & 0xf0;
346 g = pal[v & 3] & 0xf0;
347 b = (pal[v & 3] << 4) & 0xf0;
348 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
349 d += BPP;
350 v >>= 2;
351 r = (pal[v & 3] >> 4) & 0xf0;
352 g = pal[v & 3] & 0xf0;
353 b = (pal[v & 3] << 4) & 0xf0;
354 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
355 d += BPP;
356 v >>= 2;
357 r = (pal[v & 3] >> 4) & 0xf0;
358 g = pal[v & 3] & 0xf0;
359 b = (pal[v & 3] << 4) & 0xf0;
360 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
361 d += BPP;
362 s++;
363 width -= 4;
365 while (width > 0);
369 * 4-bit colour
371 static void glue(draw_line4_, DEPTH) (uint8_t * d, const uint8_t * s, int width,
372 const uint16_t * pal)
374 uint8_t v, r, g, b;
378 v = ldub_raw((void *) s);
379 r = (pal[v & 0xf] >> 4) & 0xf0;
380 g = pal[v & 0xf] & 0xf0;
381 b = (pal[v & 0xf] << 4) & 0xf0;
382 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
383 d += BPP;
384 v >>= 4;
385 r = (pal[v & 0xf] >> 4) & 0xf0;
386 g = pal[v & 0xf] & 0xf0;
387 b = (pal[v & 0xf] << 4) & 0xf0;
388 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
389 d += BPP;
390 s++;
391 width -= 2;
393 while (width > 0);
397 * 8-bit colour
399 static void glue(draw_line8_, DEPTH) (uint8_t * d, const uint8_t * s, int width,
400 const uint16_t * pal)
402 uint8_t v, r, g, b;
406 v = ldub_raw((void *) s);
407 r = (pal[v] >> 4) & 0xf0;
408 g = pal[v] & 0xf0;
409 b = (pal[v] << 4) & 0xf0;
410 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
411 s++;
412 d += BPP;
414 while (--width != 0);
419 * 16-bit colour
421 static void glue(draw_line16_, DEPTH) (uint8_t * d, const uint8_t * s,
422 int width, const uint16_t * pal)
424 #if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
425 memcpy(d, s, width * 2);
426 #else
427 uint16_t v;
428 uint8_t r, g, b;
432 v = lduw_raw((void *) s);
433 r = (v >> 8) & 0xf8;
434 g = (v >> 3) & 0xfc;
435 b = (v << 3) & 0xf8;
436 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
437 s += 2;
438 d += BPP;
440 while (--width != 0);
441 #endif
445 * 24-bit colour. JZ4740 uses 4 bytes to store 18/24 bit color.
447 static void glue(draw_line24_, DEPTH) (uint8_t * d, const uint8_t * s,
448 int width, const uint16_t * pal)
450 #if DEPTH == 32 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
451 memcpy(d, s, width * 4);
452 #else
453 uint32_t v;
454 uint8_t r, g, b;
458 v = ldl_raw((void *) s);
459 r = (v >> 16) & 0xff;
460 g = (v >> 8) & 0xff;
461 b = (v >> 0) & 0xff;
462 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
463 s += 3;
464 d += BPP;
466 while (--width != 0);
467 #endif
470 static jz4740_lcd_fn_t glue(jz4740_lcd_draw_fn_, DEPTH)[6] =
472 NULL, /*0x0 *//*1 bit per pixel */
473 (jz4740_lcd_fn_t) glue(draw_line2_, DEPTH), /*0x1 *//*2 bit per pixel */
474 (jz4740_lcd_fn_t) glue(draw_line4_, DEPTH), /*0x2 *//*4 bit per pixel */
475 (jz4740_lcd_fn_t) glue(draw_line8_, DEPTH), /*0x3 *//*8 bit per pixel */
476 (jz4740_lcd_fn_t) glue(draw_line16_, DEPTH), /*0x4 *//*15/16 bit per pixel */
477 (jz4740_lcd_fn_t) glue(draw_line24_, DEPTH), /*0x5 *//*18/24 bit per pixel */
481 #undef DEPTH
482 #undef BPP
483 #undef PIXEL_TYPE
485 #endif