0aebbc3b567846248a4faac2e17c816a468fb0d4
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 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
);
271 cpu_abort(s
->soc
->env
,
272 "jz4740_tcu_write undefined addr %x timer %x \n", addr
,
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
)
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
);
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
);
311 #ifdef JZ4740_LCD_PANEL
315 # define PIXEL_TYPE uint8_t
316 #elif DEPTH == 15 || DEPTH == 16
318 # define PIXEL_TYPE uint16_t
321 # define PIXEL_TYPE uint32_t
324 # define PIXEL_TYPE uint32_t
326 # error unsupport depth
332 static void glue(draw_line2_
, DEPTH
) (uint8_t * d
, const uint8_t * s
, int width
,
333 const uint16_t * pal
)
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
);
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
);
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
);
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
);
372 static void glue(draw_line4_
, DEPTH
) (uint8_t * d
, const uint8_t * s
, int width
,
373 const uint16_t * pal
)
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
);
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
);
400 static void glue(draw_line8_
, DEPTH
) (uint8_t * d
, const uint8_t * s
, int width
,
401 const uint16_t * pal
)
407 v
= ldub_raw((void *) s
);
408 r
= (pal
[v
] >> 4) & 0xf0;
410 b
= (pal
[v
] << 4) & 0xf0;
411 ((PIXEL_TYPE
*) d
)[0] = glue(rgb_to_pixel
, DEPTH
) (r
, g
, b
);
415 while (--width
!= 0);
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);
433 v
= lduw_raw((void *) s
);
437 ((PIXEL_TYPE
*) d
)[0] = glue(rgb_to_pixel
, DEPTH
) (r
, g
, b
);
441 while (--width
!= 0);
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);
459 v
= ldl_raw((void *) s
);
460 r
= (v
>> 16) & 0xff;
463 ((PIXEL_TYPE
*) d
)[0] = glue(rgb_to_pixel
, DEPTH
) (r
, g
, b
);
467 while (--width
!= 0);
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 */