0aebbc3b567846248a4faac2e17c816a468fb0d4
[qemu/qemu-JZ.git] / hw / mips_jz_glue.h
blob0aebbc3b567846248a4faac2e17c816a468fb0d4
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 printf("s->prescale[TCU_INDEX] %x\n",s->prescale[TCU_INDEX] );
267 glue(jz4740_tcu_start_half, TCU_INDEX) (s);
268 glue(jz4740_tcu_start_full, TCU_INDEX) (s);
269 break;
270 default:
271 cpu_abort(s->soc->env,
272 "jz4740_tcu_write undefined addr %x timer %x \n", addr,
273 TCU_INDEX);
279 static CPUReadMemoryFunc *glue(jz4740_tcu_readfn, TCU_INDEX)[] =
281 jz4740_badwidth_read16,
282 glue(jz4740_tcu_read, TCU_INDEX), jz4740_badwidth_read16,};
284 static CPUWriteMemoryFunc *glue(jz4740_tcu_writefn, TCU_INDEX)[] =
286 jz4740_badwidth_write16,
287 glue(jz4740_tcu_write, TCU_INDEX), jz4740_badwidth_write16,};
289 static void glue(jz4740_tcu_init, TCU_INDEX) (struct jz_state_s * soc,
290 struct jz4740_tcu_s * s)
292 int iomemtype;
294 s->half_timer[TCU_INDEX] =
295 qemu_new_timer(vm_clock, glue(jz4740_tcu_half_cb, TCU_INDEX), s);
296 s->full_timer[TCU_INDEX] =
297 qemu_new_timer(vm_clock, glue(jz4740_tcu_full_cb, TCU_INDEX), s);
299 iomemtype =
300 cpu_register_io_memory(0, glue(jz4740_tcu_readfn, TCU_INDEX),
301 glue(jz4740_tcu_writefn, TCU_INDEX), s);
302 cpu_register_physical_memory(s->base + 0x00000040 + TCU_INDEX * 0x10,
303 0x00000010, iomemtype);
306 #undef TCU_INDEX
307 #endif
311 #ifdef JZ4740_LCD_PANEL
313 #if DEPTH == 8
314 # define BPP 1
315 # define PIXEL_TYPE uint8_t
316 #elif DEPTH == 15 || DEPTH == 16
317 # define BPP 2
318 # define PIXEL_TYPE uint16_t
319 #elif DEPTH == 24
320 # define BPP 3
321 # define PIXEL_TYPE uint32_t
322 #elif DEPTH == 32
323 # define BPP 4
324 # define PIXEL_TYPE uint32_t
325 #else
326 # error unsupport depth
327 #endif
330 * 2-bit colour
332 static void glue(draw_line2_, DEPTH) (uint8_t * d, const uint8_t * s, int width,
333 const uint16_t * pal)
335 uint8_t v, r, g, b;
339 v = ldub_raw((void *) s);
340 r = (pal[v & 3] >> 4) & 0xf0;
341 g = pal[v & 3] & 0xf0;
342 b = (pal[v & 3] << 4) & 0xf0;
343 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
344 d += BPP;
345 v >>= 2;
346 r = (pal[v & 3] >> 4) & 0xf0;
347 g = pal[v & 3] & 0xf0;
348 b = (pal[v & 3] << 4) & 0xf0;
349 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
350 d += BPP;
351 v >>= 2;
352 r = (pal[v & 3] >> 4) & 0xf0;
353 g = pal[v & 3] & 0xf0;
354 b = (pal[v & 3] << 4) & 0xf0;
355 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
356 d += BPP;
357 v >>= 2;
358 r = (pal[v & 3] >> 4) & 0xf0;
359 g = pal[v & 3] & 0xf0;
360 b = (pal[v & 3] << 4) & 0xf0;
361 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
362 d += BPP;
363 s++;
364 width -= 4;
366 while (width > 0);
370 * 4-bit colour
372 static void glue(draw_line4_, DEPTH) (uint8_t * d, const uint8_t * s, int width,
373 const uint16_t * pal)
375 uint8_t v, r, g, b;
379 v = ldub_raw((void *) s);
380 r = (pal[v & 0xf] >> 4) & 0xf0;
381 g = pal[v & 0xf] & 0xf0;
382 b = (pal[v & 0xf] << 4) & 0xf0;
383 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
384 d += BPP;
385 v >>= 4;
386 r = (pal[v & 0xf] >> 4) & 0xf0;
387 g = pal[v & 0xf] & 0xf0;
388 b = (pal[v & 0xf] << 4) & 0xf0;
389 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
390 d += BPP;
391 s++;
392 width -= 2;
394 while (width > 0);
398 * 8-bit colour
400 static void glue(draw_line8_, DEPTH) (uint8_t * d, const uint8_t * s, int width,
401 const uint16_t * pal)
403 uint8_t v, r, g, b;
407 v = ldub_raw((void *) s);
408 r = (pal[v] >> 4) & 0xf0;
409 g = pal[v] & 0xf0;
410 b = (pal[v] << 4) & 0xf0;
411 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
412 s++;
413 d += BPP;
415 while (--width != 0);
420 * 16-bit colour
422 static void glue(draw_line16_, DEPTH) (uint8_t * d, const uint8_t * s,
423 int width, const uint16_t * pal)
425 #if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
426 memcpy(d, s, width * 2);
427 #else
428 uint16_t v;
429 uint8_t r, g, b;
433 v = lduw_raw((void *) s);
434 r = (v >> 8) & 0xf8;
435 g = (v >> 3) & 0xfc;
436 b = (v << 3) & 0xf8;
437 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
438 s += 2;
439 d += BPP;
441 while (--width != 0);
442 #endif
446 * 24-bit colour. JZ4740 uses 4 bytes to store 18/24 bit color.
448 static void glue(draw_line24_, DEPTH) (uint8_t * d, const uint8_t * s,
449 int width, const uint16_t * pal)
451 #if DEPTH == 32 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
452 memcpy(d, s, width * 4);
453 #else
454 uint32_t v;
455 uint8_t r, g, b;
459 v = ldl_raw((void *) s);
460 r = (v >> 16) & 0xff;
461 g = (v >> 8) & 0xff;
462 b = (v >> 0) & 0xff;
463 ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
464 s += 3;
465 d += BPP;
467 while (--width != 0);
468 #endif
471 static jz4740_lcd_fn_t glue(jz4740_lcd_draw_fn_, DEPTH)[6] =
473 NULL, /*0x0 *//*1 bit per pixel */
474 (jz4740_lcd_fn_t) glue(draw_line2_, DEPTH), /*0x1 *//*2 bit per pixel */
475 (jz4740_lcd_fn_t) glue(draw_line4_, DEPTH), /*0x2 *//*4 bit per pixel */
476 (jz4740_lcd_fn_t) glue(draw_line8_, DEPTH), /*0x3 *//*8 bit per pixel */
477 (jz4740_lcd_fn_t) glue(draw_line16_, DEPTH), /*0x4 *//*15/16 bit per pixel */
478 (jz4740_lcd_fn_t) glue(draw_line24_, DEPTH), /*0x5 *//*18/24 bit per pixel */
482 #undef DEPTH
483 #undef BPP
484 #undef PIXEL_TYPE
486 #endif