858bd129d0e3592f37817350e6bf5951131d7b1e
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
28 static inline void glue(jz4740_tcu_time_sync
,
29 TCU_INDEX
) (struct jz4740_tcu_s
* s
)
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;
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
);
55 /*distance is too short */
56 s
->tcnt
[TCU_INDEX
] += temp
;
57 s
->time
[TCU_INDEX
] = qemu_get_clock(vm_clock
);
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
);
81 /*The timer has not beed initialized */
82 if (!s
->half_timer
[TCU_INDEX
])
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 */
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
);
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
);
107 /*The timer has not beed initialized */
108 if (!s
->full_timer
[TCU_INDEX
])
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 */
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);
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
);
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
);
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
);
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
);
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;
198 return s
->tdfr
[TCU_INDEX
];
200 return s
->tdhr
[TCU_INDEX
];
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
];
207 return s
->tcsr
[TCU_INDEX
];
209 cpu_abort(s
->soc
->env
,
210 "jz4740_tcu_read undefined addr %x timer %x \n", addr
,
216 static void glue(jz4740_tcu_write
, TCU_INDEX
) (void *opaque
,
217 target_phys_addr_t addr
,
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
,
224 //printf( "jz4740_tcu_write%x addr %x value %x \n", TCU_INDEX,
226 addr
-= 0x40 + TCU_INDEX
* 0x10;
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
);
238 /*TDHR*/ s
->tdhr
[TCU_INDEX
] = value
& 0xffff;
239 glue(jz4740_tcu_start_half
, TCU_INDEX
) (s
);
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
);
248 s
->tcsr
[TCU_INDEX
] = value
& 0x3bf;
252 s
->freq
[TCU_INDEX
] = jz_clk_getrate(jz_findclk(s
->soc
, "pclk"));
255 s
->freq
[TCU_INDEX
] = jz_clk_getrate(jz_findclk(s
->soc
, "osc_32K"));
259 jz_clk_getrate(jz_findclk(s
->soc
, "osc_extal"));
262 s
->freq
[TCU_INDEX
] = 0x0;
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
);
270 cpu_abort(s
->soc
->env
,
271 "jz4740_tcu_write undefined addr %x timer %x \n", addr
,
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
)
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
);
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
);
310 #ifdef JZ4740_LCD_PANEL
314 # define PIXEL_TYPE uint8_t
315 #elif DEPTH == 15 || DEPTH == 16
317 # define PIXEL_TYPE uint16_t
320 # define PIXEL_TYPE uint32_t
323 # define PIXEL_TYPE uint32_t
325 # error unsupport depth
331 static void glue(draw_line2_
, DEPTH
) (uint8_t * d
, const uint8_t * s
, int width
,
332 const uint16_t * pal
)
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
);
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
);
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
);
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
);
371 static void glue(draw_line4_
, DEPTH
) (uint8_t * d
, const uint8_t * s
, int width
,
372 const uint16_t * pal
)
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
);
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
);
399 static void glue(draw_line8_
, DEPTH
) (uint8_t * d
, const uint8_t * s
, int width
,
400 const uint16_t * pal
)
406 v
= ldub_raw((void *) s
);
407 r
= (pal
[v
] >> 4) & 0xf0;
409 b
= (pal
[v
] << 4) & 0xf0;
410 ((PIXEL_TYPE
*) d
)[0] = glue(rgb_to_pixel
, DEPTH
) (r
, g
, b
);
414 while (--width
!= 0);
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);
432 v
= lduw_raw((void *) s
);
436 ((PIXEL_TYPE
*) d
)[0] = glue(rgb_to_pixel
, DEPTH
) (r
, g
, b
);
440 while (--width
!= 0);
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);
458 v
= ldl_raw((void *) s
);
459 r
= (v
>> 16) & 0xff;
462 ((PIXEL_TYPE
*) d
)[0] = glue(rgb_to_pixel
, DEPTH
) (r
, g
, b
);
466 while (--width
!= 0);
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 */