mips jz glue function
authoryajin <yajin@vm-kernel.org>
Wed, 14 Jan 2009 19:59:57 +0000 (15 03:59 +0800)
committeryajin <yajin@vm-kernel.org>
Wed, 14 Jan 2009 19:59:57 +0000 (15 03:59 +0800)
hw/mips_jz_glue.h [new file with mode: 0755]

diff --git a/hw/mips_jz_glue.h b/hw/mips_jz_glue.h
new file mode 100755 (executable)
index 0000000..0aebbc3
--- /dev/null
@@ -0,0 +1,486 @@
+/*\r
+ * QEMU JZ Soc emulation glue code\r
+ *\r
+ * Copyright (c) 2009 yajin (yajin@vm-kernel.org)\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ * of this software and associated documentation files (the "Software"), to deal\r
+ * in the Software without restriction, including without limitation the rights\r
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ * copies of the Software, and to permit persons to whom the Software is\r
+ * furnished to do so, subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in\r
+ * all copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
+ * THE SOFTWARE.\r
+ */\r
+\r
+\r
\r
+#ifdef TCU_INDEX\r
+static inline void glue(jz4740_tcu_time_sync,\r
+                        TCU_INDEX) (struct jz4740_tcu_s * s)\r
+{\r
+    int64_t distance;\r
+    int64_t temp;\r
+\r
+    if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))\r
+        && (s->freq[TCU_INDEX] != 0))\r
+    {\r
+        //debug_out(DEBUG_TCU, "jz4740_tcu_time_sync%x \n", TCU_INDEX);\r
+        /*first enable timer */\r
+        if (s->time[TCU_INDEX] == 0)\r
+        {\r
+            s->time[TCU_INDEX] = qemu_get_clock(vm_clock);\r
+            s->tcnt[TCU_INDEX] = 0;\r
+            return;\r
+        }\r
+        distance = qemu_get_clock(vm_clock) - s->time[TCU_INDEX];\r
+        //debug_out(DEBUG_TCU,\r
+         //         "s->freq[TCU_INDEX]  %d s->prescale[TCU_INDEX] %d \n",\r
+         //         s->freq[TCU_INDEX], s->prescale[TCU_INDEX]);\r
+       // debug_out(DEBUG_TCU, "distance %lld s->time[TCU_INDEX] %lld \n",\r
+       //           distance, s->time[TCU_INDEX]);\r
+        //temp = muldiv64(distance,(s->freq[TCU_INDEX]/s->prescale[TCU_INDEX]),ticks_per_sec);\r
+        temp = muldiv64(distance, 46875, ticks_per_sec);\r
+        if (temp != 0)\r
+        {\r
+            /*distance is too short */\r
+            s->tcnt[TCU_INDEX] += temp;\r
+            s->time[TCU_INDEX] = qemu_get_clock(vm_clock);\r
+        }\r
+        else\r
+        {\r
+            /*distance is too short.\r
+             * Do not sync timer this timer.\r
+             */\r
+        }\r
+\r
+        //printf("%lld distance %lld \n",muldiv64(distance,(s->freq[TCU_INDEX]/s->prescale[TCU_INDEX]),ticks_per_sec),distance);\r
+\r
+        if (s->tcnt[TCU_INDEX] >= 0x10000)\r
+            s->tcnt[TCU_INDEX] = 0x0;\r
+\r
+\r
+    }\r
+}\r
+\r
+static inline void glue(jz4740_tcu_start_half,\r
+                        TCU_INDEX) (struct jz4740_tcu_s * s)\r
+{\r
+    int64_t next = qemu_get_clock(vm_clock);\r
+    int64_t count;\r
+\r
+    /*The timer has not beed initialized */\r
+    if (!s->half_timer[TCU_INDEX])\r
+        return;\r
+       \r
+    if ((!(s->tsr & (1 << (TCU_INDEX+16)))) && (s->ter & (1 << (TCU_INDEX+16)))\r
+        && (s->freq[TCU_INDEX] != 0))\r
+    {\r
+        glue(jz4740_tcu_time_sync, TCU_INDEX) (s);\r
+        /*calculate next fire time */\r
+        count =\r
+            (s->tdhr[TCU_INDEX] - s->tcnt[TCU_INDEX]) * s->prescale[TCU_INDEX];\r
+        next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);\r
+        qemu_mod_timer(s->half_timer[TCU_INDEX], next);\r
+\r
+    }\r
+    else\r
+        qemu_del_timer(s->half_timer[TCU_INDEX]);\r
+\r
+}\r
+\r
+static inline void glue(jz4740_tcu_start_full,\r
+                        TCU_INDEX) (struct jz4740_tcu_s * s)\r
+{\r
+    int64_t next = qemu_get_clock(vm_clock);\r
+    int64_t count;\r
+\r
+    /*The timer has not beed initialized */\r
+    if (!s->full_timer[TCU_INDEX])\r
+        return;\r
+        \r
+       debug_out(DEBUG_TCU, "s->tsr %d  s->ter %d  s->freq[TCU_INDEX]  %d \n",\r
+                                         s->tsr ,  s->ter ,s->freq[TCU_INDEX]);\r
+printf("s->tsr %d  s->ter %d  s->freq[TCU_INDEX]  %d \n",\r
+                                         s->tsr ,  s->ter ,s->freq[TCU_INDEX]);\r
+    if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))\r
+        && (s->freq[TCU_INDEX] != 0))\r
+    {\r
+        glue(jz4740_tcu_time_sync, TCU_INDEX) (s);\r
+        printf("tdfr %x \n",s->tdfr[TCU_INDEX] );\r
+        /*calculate next fire time */\r
+        count =\r
+            (s->tdfr[TCU_INDEX] - s->tcnt[TCU_INDEX]) * s->prescale[TCU_INDEX];\r
+        printf("tdfr11 %x count %lld\n",s->tdfr[TCU_INDEX],count );\r
+        next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);\r
+        qemu_mod_timer(s->full_timer[TCU_INDEX], next);\r
+                debug_out(DEBUG_TCU, "s->tdfr[TCU_INDEX]  %d  s->tcnt[TCU_INDEX] %d  next  %lld \n",\r
+                                         s->tdfr[TCU_INDEX] ,  s->tcnt[TCU_INDEX]  ,next);\r
+                       printf("s->tdfr[TCU_INDEX]22  %x  s->tcnt[TCU_INDEX] %x next  %lld \n",\r
+                                         s->tdfr[TCU_INDEX] ,  s->tcnt[TCU_INDEX]  ,next);\r
+\r
+    }\r
+    else\r
+        qemu_del_timer(s->full_timer[TCU_INDEX]);\r
+}\r
+\r
+\r
+/* \r
+ *     TCNT will reset to 0 if it reach to TDFR.\r
+ *       So for the half compare, the next fire count is (TDFR-TDHR) + TDHR\r
+ *                                                                                            \r
+ */\r
+static void glue(jz4740_tcu_half_cb, TCU_INDEX) (void *opaque)\r
+{\r
+    struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;\r
+    int64_t next = qemu_get_clock(vm_clock);\r
+    int64_t count;\r
+\r
+    if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))\r
+        && (s->freq[TCU_INDEX] != 0))\r
+    {\r
+        count = s->tdfr[TCU_INDEX] * s->prescale[TCU_INDEX];\r
+        next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);\r
+        qemu_mod_timer(s->half_timer[TCU_INDEX], next);\r
+        s->tfr |= 1 << (16 + TCU_INDEX);\r
+        jz4740_tcu_update_interrupt(s);\r
+        s->tcnt[TCU_INDEX] = s->tdhr[TCU_INDEX];\r
+        s->time[TCU_INDEX] = qemu_get_clock(vm_clock);\r
+    }\r
+    else\r
+        qemu_del_timer(s->half_timer[TCU_INDEX]);\r
+}\r
+\r
+\r
+static void glue(jz4740_tcu_full_cb, TCU_INDEX) (void *opaque)\r
+{\r
+    struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;\r
+    int64_t next = qemu_get_clock(vm_clock);\r
+    int64_t count;\r
+\r
+    if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))\r
+        && (s->freq[TCU_INDEX] != 0))\r
+    {\r
+        //printf("s->tdfr[TCU_INDEX]  %x s->prescale[TCU_INDEX]  %x \n",s->tdfr[TCU_INDEX] ,s->prescale[TCU_INDEX] );\r
+        count = s->tdfr[TCU_INDEX] * s->prescale[TCU_INDEX];\r
+        next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);\r
+        //printf("count  %lld next  %lld \n",count,next);\r
+        qemu_mod_timer(s->full_timer[TCU_INDEX], next);\r
+        s->tfr |= 1 << TCU_INDEX;\r
+        jz4740_tcu_update_interrupt(s);\r
+        s->tcnt[TCU_INDEX] = 0;\r
+        s->time[TCU_INDEX] = qemu_get_clock(vm_clock);\r
+    }\r
+    else\r
+        qemu_del_timer(s->full_timer[TCU_INDEX]);\r
+}\r
+\r
+static uint32_t glue(jz4740_tcu_read, TCU_INDEX) (void *opaque,\r
+                                                  target_phys_addr_t addr)\r
+{\r
+    struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;\r
+\r
+    debug_out(DEBUG_TCU, "jz4740_tcu_read%x addr %x\n", TCU_INDEX, addr);\r
+    addr -= 0x40 + TCU_INDEX * 0x10;\r
+\r
+    switch (addr)\r
+    {\r
+    case 0x0:\r
+        return s->tdfr[TCU_INDEX];\r
+    case 0x4:\r
+        return s->tdhr[TCU_INDEX];\r
+    case 0x8:\r
+        glue(jz4740_tcu_time_sync, TCU_INDEX) (s);\r
+        //debug_out(DEBUG_TCU, "s->tcnt  %x\n", s->tcnt[TCU_INDEX]);\r
+        //printf("s->tcnt  %x\n", s->tcnt[TCU_INDEX]);\r
+        return s->tcnt[TCU_INDEX];\r
+    case 0xc:\r
+        return s->tcsr[TCU_INDEX];\r
+    default:\r
+        cpu_abort(s->soc->env,\r
+                  "jz4740_tcu_read undefined addr %x timer %x \n", addr,\r
+                  TCU_INDEX);\r
+    }\r
+    return (0);\r
+}\r
+\r
+static void glue(jz4740_tcu_write, TCU_INDEX) (void *opaque,\r
+                                               target_phys_addr_t addr,\r
+                                               uint32_t value)\r
+{\r
+    struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;\r
+\r
+    debug_out(DEBUG_TCU, "jz4740_tcu_write%x addr %x value %x \n", TCU_INDEX,\r
+              addr, value);\r
+printf( "jz4740_tcu_write%x addr %x value %x \n", TCU_INDEX,\r
+              addr, value);\r
+    addr -= 0x40 + TCU_INDEX * 0x10;\r
+\r
+    switch (addr)\r
+    {\r
+    case 0x0:\r
+         /*TDFR*/ \r
+         \r
+         s->tdfr[TCU_INDEX] = value & 0xffff;\r
+         printf("s->tdfr[TCU_INDEX]  %x \n",s->tdfr[TCU_INDEX] );\r
+        glue(jz4740_tcu_start_full, TCU_INDEX) (s);\r
+        break;\r
+    case 0x4:\r
+         /*TDHR*/ s->tdhr[TCU_INDEX] = value & 0xffff;\r
+        glue(jz4740_tcu_start_half, TCU_INDEX) (s);\r
+        break;\r
+    case 0x8:\r
+         /*TCNT*/ s->tcnt[TCU_INDEX] = value & 0xffff;\r
+        s->time[TCU_INDEX] = qemu_get_clock(vm_clock);\r
+        glue(jz4740_tcu_start_half, TCU_INDEX) (s);\r
+        glue(jz4740_tcu_start_full, TCU_INDEX) (s);\r
+        break;\r
+    case 0xc:\r
+        s->tcsr[TCU_INDEX] = value & 0x3bf;\r
+        switch (value & 0x7)\r
+        {\r
+        case 0x1:\r
+            s->freq[TCU_INDEX] = jz_clk_getrate(jz_findclk(s->soc, "pclk"));\r
+            break;\r
+        case 0x2:\r
+            s->freq[TCU_INDEX] = jz_clk_getrate(jz_findclk(s->soc, "osc_32K"));\r
+            break;\r
+        case 0x4:\r
+            s->freq[TCU_INDEX] =\r
+                jz_clk_getrate(jz_findclk(s->soc, "osc_extal"));\r
+            break;\r
+        default:\r
+            s->freq[TCU_INDEX] = 0x0;\r
+            break;\r
+        }\r
+        s->prescale[TCU_INDEX] = 1 << (((value & 0x38) >> 3) * 2);\r
+        printf("s->prescale[TCU_INDEX]  %x\n",s->prescale[TCU_INDEX] );\r
+        glue(jz4740_tcu_start_half, TCU_INDEX) (s);\r
+        glue(jz4740_tcu_start_full, TCU_INDEX) (s);\r
+        break;\r
+    default:\r
+        cpu_abort(s->soc->env,\r
+                  "jz4740_tcu_write undefined addr %x timer %x \n", addr,\r
+                  TCU_INDEX);\r
+\r
+    }\r
+}\r
+\r
+\r
+static CPUReadMemoryFunc *glue(jz4740_tcu_readfn, TCU_INDEX)[] =\r
+{\r
+jz4740_badwidth_read16,\r
+        glue(jz4740_tcu_read, TCU_INDEX), jz4740_badwidth_read16,};\r
+\r
+static CPUWriteMemoryFunc *glue(jz4740_tcu_writefn, TCU_INDEX)[] =\r
+{\r
+jz4740_badwidth_write16,\r
+        glue(jz4740_tcu_write, TCU_INDEX), jz4740_badwidth_write16,};\r
+\r
+static void glue(jz4740_tcu_init, TCU_INDEX) (struct jz_state_s * soc,\r
+                                              struct jz4740_tcu_s * s)\r
+{\r
+    int iomemtype;\r
+\r
+    s->half_timer[TCU_INDEX] =\r
+        qemu_new_timer(vm_clock, glue(jz4740_tcu_half_cb, TCU_INDEX), s);\r
+    s->full_timer[TCU_INDEX] =\r
+        qemu_new_timer(vm_clock, glue(jz4740_tcu_full_cb, TCU_INDEX), s);\r
+\r
+    iomemtype =\r
+        cpu_register_io_memory(0, glue(jz4740_tcu_readfn, TCU_INDEX),\r
+                               glue(jz4740_tcu_writefn, TCU_INDEX), s);\r
+    cpu_register_physical_memory(s->base + 0x00000040 + TCU_INDEX * 0x10,\r
+                                 0x00000010, iomemtype);\r
+}\r
+\r
+#undef TCU_INDEX\r
+#endif\r
+\r
+\r
+\r
+#ifdef JZ4740_LCD_PANEL\r
+\r
+#if DEPTH == 8\r
+# define BPP 1\r
+# define PIXEL_TYPE uint8_t\r
+#elif DEPTH == 15 || DEPTH == 16\r
+# define BPP 2\r
+# define PIXEL_TYPE uint16_t\r
+#elif DEPTH == 24\r
+# define BPP 3\r
+# define PIXEL_TYPE uint32_t\r
+#elif DEPTH == 32\r
+# define BPP 4\r
+# define PIXEL_TYPE uint32_t\r
+#else\r
+# error unsupport depth\r
+#endif\r
+\r
+/*\r
+ * 2-bit colour\r
+ */\r
+static void glue(draw_line2_, DEPTH) (uint8_t * d, const uint8_t * s, int width,\r
+                                      const uint16_t * pal)\r
+{\r
+    uint8_t v, r, g, b;\r
+\r
+    do\r
+    {\r
+        v = ldub_raw((void *) s);\r
+        r = (pal[v & 3] >> 4) & 0xf0;\r
+        g = pal[v & 3] & 0xf0;\r
+        b = (pal[v & 3] << 4) & 0xf0;\r
+        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);\r
+        d += BPP;\r
+        v >>= 2;\r
+        r = (pal[v & 3] >> 4) & 0xf0;\r
+        g = pal[v & 3] & 0xf0;\r
+        b = (pal[v & 3] << 4) & 0xf0;\r
+        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);\r
+        d += BPP;\r
+        v >>= 2;\r
+        r = (pal[v & 3] >> 4) & 0xf0;\r
+        g = pal[v & 3] & 0xf0;\r
+        b = (pal[v & 3] << 4) & 0xf0;\r
+        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);\r
+        d += BPP;\r
+        v >>= 2;\r
+        r = (pal[v & 3] >> 4) & 0xf0;\r
+        g = pal[v & 3] & 0xf0;\r
+        b = (pal[v & 3] << 4) & 0xf0;\r
+        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);\r
+        d += BPP;\r
+        s++;\r
+        width -= 4;\r
+    }\r
+    while (width > 0);\r
+}\r
+\r
+/*\r
+ * 4-bit colour\r
+ */\r
+static void glue(draw_line4_, DEPTH) (uint8_t * d, const uint8_t * s, int width,\r
+                                      const uint16_t * pal)\r
+{\r
+    uint8_t v, r, g, b;\r
+\r
+    do\r
+    {\r
+        v = ldub_raw((void *) s);\r
+        r = (pal[v & 0xf] >> 4) & 0xf0;\r
+        g = pal[v & 0xf] & 0xf0;\r
+        b = (pal[v & 0xf] << 4) & 0xf0;\r
+        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);\r
+        d += BPP;\r
+        v >>= 4;\r
+        r = (pal[v & 0xf] >> 4) & 0xf0;\r
+        g = pal[v & 0xf] & 0xf0;\r
+        b = (pal[v & 0xf] << 4) & 0xf0;\r
+        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);\r
+        d += BPP;\r
+        s++;\r
+        width -= 2;\r
+    }\r
+    while (width > 0);\r
+}\r
+\r
+/*\r
+ * 8-bit colour\r
+ */\r
+static void glue(draw_line8_, DEPTH) (uint8_t * d, const uint8_t * s, int width,\r
+                                      const uint16_t * pal)\r
+{\r
+    uint8_t v, r, g, b;\r
+\r
+    do\r
+    {\r
+        v = ldub_raw((void *) s);\r
+        r = (pal[v] >> 4) & 0xf0;\r
+        g = pal[v] & 0xf0;\r
+        b = (pal[v] << 4) & 0xf0;\r
+        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);\r
+        s++;\r
+        d += BPP;\r
+    }\r
+    while (--width != 0);\r
+}\r
+\r
+\r
+/*\r
+ * 16-bit colour\r
+ */\r
+static void glue(draw_line16_, DEPTH) (uint8_t * d, const uint8_t * s,\r
+                                       int width, const uint16_t * pal)\r
+{\r
+#if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)\r
+    memcpy(d, s, width * 2);\r
+#else\r
+    uint16_t v;\r
+    uint8_t r, g, b;\r
+\r
+    do\r
+    {\r
+        v = lduw_raw((void *) s);\r
+        r = (v >> 8) & 0xf8;\r
+        g = (v >> 3) & 0xfc;\r
+        b = (v << 3) & 0xf8;\r
+        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);\r
+        s += 2;\r
+        d += BPP;\r
+    }\r
+    while (--width != 0);\r
+#endif\r
+}\r
+\r
+/*\r
+ * 24-bit colour.  JZ4740 uses 4 bytes to store 18/24 bit color.\r
+ */\r
+static void glue(draw_line24_, DEPTH) (uint8_t * d, const uint8_t * s,\r
+                                       int width, const uint16_t * pal)\r
+{\r
+#if DEPTH == 32 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)\r
+    memcpy(d, s, width * 4);\r
+#else\r
+    uint32_t v;\r
+    uint8_t r, g, b;\r
+\r
+    do\r
+    {\r
+        v = ldl_raw((void *) s);\r
+        r = (v >> 16) & 0xff;\r
+        g = (v >> 8) & 0xff;\r
+        b = (v >> 0) & 0xff;\r
+        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);\r
+        s += 3;\r
+        d += BPP;\r
+    }\r
+    while (--width != 0);\r
+#endif\r
+}\r
+\r
+static jz4740_lcd_fn_t glue(jz4740_lcd_draw_fn_, DEPTH)[6] =\r
+{\r
+    NULL,                       /*0x0 *//*1 bit per pixel */\r
+        (jz4740_lcd_fn_t) glue(draw_line2_, DEPTH),     /*0x1 *//*2 bit per pixel */\r
+        (jz4740_lcd_fn_t) glue(draw_line4_, DEPTH),     /*0x2 *//*4 bit per pixel */\r
+        (jz4740_lcd_fn_t) glue(draw_line8_, DEPTH),     /*0x3 *//*8 bit per pixel */\r
+        (jz4740_lcd_fn_t) glue(draw_line16_, DEPTH),    /*0x4 *//*15/16 bit per pixel */\r
+        (jz4740_lcd_fn_t) glue(draw_line24_, DEPTH),    /*0x5 *//*18/24 bit per pixel */\r
+};\r
+\r
+\r
+#undef DEPTH\r
+#undef BPP\r
+#undef PIXEL_TYPE\r
+\r
+#endif\r