qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards
@ 2009-04-23 17:15 Vincent Sanders
  2009-04-23 17:45 ` [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers Vincent Sanders
                   ` (15 more replies)
  0 siblings, 16 replies; 29+ messages in thread
From: Vincent Sanders @ 2009-04-23 17:15 UTC (permalink / raw)
  To: qemu-devel

The following series adds Samsung S3C support to Qemu. The approach
taken is to create a series of generic s3c24xx peripheral blocks and
then to create a SOC device which collects a number of these generic
blocks together.

The SOC device is then instansiated by the board driver and additional
external peripherals added as appropriate.

Two actual SOC are currently implemented (however the generic
peripherals are used throughout the entire Samsung range from S3C2400
to S3C6410) are the S3C2410 and S3C2440. 

These two SOC were chosen as representative samples because they are
two of the most popular ARM 9 class devices and have been used in many
devices from handhelds to the openmoko phones.

These SOC also have extremely good Linux kernel support, a single
default configuration covers 22 boards.

Only a pair of boards have been included in this series purely to
demostrate the most basic intended usage of the implementation. A
subsequent series will introduce all the omited peripherals for these
boards.

This series is the smallest set of changes required to support these
devices and is current against SVN revision 7233. The implementation
of some peripheral blocks although not complete is sufficient to
successfully run Linux kernels. Improved peripheral support is
envisaged after the core support is merged.

-- 
Regards Vincent
http://www.kyllikki.org/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers
  2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
@ 2009-04-23 17:45 ` Vincent Sanders
  2009-04-30 16:08   ` Paul Brook
  2009-04-23 17:48 ` [Qemu-devel] [PATCH 2/16] Add s3c SOC header Vincent Sanders
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 29+ messages in thread
From: Vincent Sanders @ 2009-04-23 17:45 UTC (permalink / raw)
  To: qemu-devel

Add ARM 920T CPU ID

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 cpu.h    |    1 +
 helper.c |    3 +++
 2 files changed, 4 insertions(+)


diff -urN qemusvnclean/target-arm/cpu.h qemusvnpatches/target-arm/cpu.h
--- qemusvnclean/target-arm/cpu.h	2009-04-20 20:26:52.000000000 +0100
+++ qemusvnpatches/target-arm/cpu.h	2009-04-20 21:16:58.000000000 +0100
@@ -370,6 +370,7 @@
 #define ARM_CPUID_ARM1026     0x4106a262
 #define ARM_CPUID_ARM926      0x41069265
 #define ARM_CPUID_ARM946      0x41059461
+#define ARM_CPUID_ARM920T     0x41129200
 #define ARM_CPUID_TI915T      0x54029152
 #define ARM_CPUID_TI925T      0x54029252
 #define ARM_CPUID_PXA250      0x69052100
diff -urN qemusvnclean/target-arm/helper.c qemusvnpatches/target-arm/helper.c
--- qemusvnclean/target-arm/helper.c	2009-04-20 20:26:52.000000000 +0100
+++ qemusvnpatches/target-arm/helper.c	2009-04-20 21:16:49.000000000 +0100
@@ -37,6 +37,8 @@
 {
     env->cp15.c0_cpuid = id;
     switch (id) {
+    case ARM_CPUID_ARM920T:
+       break;
     case ARM_CPUID_ARM926:
         set_feature(env, ARM_FEATURE_VFP);
         env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
@@ -276,6 +278,7 @@
 };
 
 static const struct arm_cpu_t arm_cpu_names[] = {
+    { ARM_CPUID_ARM920T, "arm920t"},
     { ARM_CPUID_ARM926, "arm926"},
     { ARM_CPUID_ARM946, "arm946"},
     { ARM_CPUID_ARM1026, "arm1026"},

-- 
Regards Vincent
http://www.kyllikki.org/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 2/16] Add s3c SOC header
  2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
  2009-04-23 17:45 ` [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers Vincent Sanders
@ 2009-04-23 17:48 ` Vincent Sanders
  2009-04-23 17:50 ` [Qemu-devel] [PATCH 3/16] S3C SDRAM memory controller Peripheral Vincent Sanders
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 29+ messages in thread
From: Vincent Sanders @ 2009-04-23 17:48 UTC (permalink / raw)
  To: qemu-devel

S3C SOC integrated peripheral devices structure

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 s3c24xx.h |   73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)


diff -urN qemusvnclean/hw/s3c24xx.h qemusvnpatches/hw/s3c24xx.h
--- qemusvnclean/hw/s3c24xx.h	1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/s3c24xx.h	2009-04-23 15:53:57.000000000 +0100
@@ -0,0 +1,73 @@
+/* hw/s3c24xx.h
+ *
+ * Samsung s3c24xx cpu state and functions.
+ *
+ * Copyright 2006, 2007, 2008 Daniel Silverstone and Vincent Sanders
+ *
+ * This file is under the terms of the GNU General Public
+ * License Version 2.
+ */
+
+#ifndef S3C24XX_H
+#define S3C24XX_H 1
+
+/* This structure type encapsulates the state of a S3C24XX SoC. */
+typedef struct S3CState_s {
+    CPUState *cpu_env;
+    qemu_irq *irqs;
+    qemu_irq *eirqs;
+
+    /* Memory controller */
+    uint32_t memc_reg[13];
+
+    /* Interrupt controller */
+    uint32_t irq_main_level, irq_subsrc_level;
+    uint32_t irq_reg[8];
+
+    /* Clock controller */
+    uint32_t clkcon_reg[6];
+
+    uint32_t tclk0; /* first timer clock source frequency */
+    uint32_t tclk1; /* second timer clock source frequency */
+
+    /* GPIO block */
+    uint32_t gpio_reg[47];
+
+    /* Realtime clock */
+    uint8_t rtc_reg[19];
+
+    /* i2c */
+    struct s3c24xx_i2c_state_s *iic;
+    
+    /* Timers, (Specifically timer4) */
+    uint32_t timers_reg[17];
+    QEMUTimer *timer4;
+    uint32_t timer4_reload_value;
+    int64_t timer4_last_ticked;
+
+    /* LCD controller */
+    struct s3c24xx_lcd_state_s *lcd;
+
+    /* NAND controller, and chip attached */
+    uint32_t nand_reg[5];
+    struct nand_flash_s *nand_chip;
+} S3CState;
+
+/* Internal functions for s3c24xx implementation */
+void s3c24xx_memc_init(S3CState *soc, target_phys_addr_t base_addr);
+qemu_irq *s3c24xx_irq_init(S3CState *soc, target_phys_addr_t base_addr);
+void s3c24xx_clkcon_init(S3CState *soc, target_phys_addr_t base_addr);
+void s3c24xx_timers_init(S3CState *soc, target_phys_addr_t base_addr);
+void s3c24xx_serial_init(S3CState *soc, int port, target_phys_addr_t base_addr);
+void s3c24xx_rtc_init(S3CState *soc, target_phys_addr_t base_addr);
+void s3c24xx_gpio_init(S3CState *soc, target_phys_addr_t base_addr,uint32_t cpu_id );
+void s3c24xx_iic_init(S3CState *soc, target_phys_addr_t base_addr);
+struct s3c24xx_lcd_state_s *s3c24xx_lcd_init(target_phys_addr_t base, qemu_irq irq);
+void s3c24xx_nand_init(S3CState *soc, target_phys_addr_t base_addr);
+
+/* attach a NAND device to the s3c24xx controller */
+void s3c24xx_nand_attach(S3CState *soc, struct nand_flash_s *nand_chip);
+
+i2c_bus *s3c24xx_i2c_bus(struct s3c24xx_i2c_state_s *s);
+
+#endif /* S3C24XX_H */

-- 
Regards Vincent
http://www.kyllikki.org/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 3/16] S3C SDRAM memory controller Peripheral
  2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
  2009-04-23 17:45 ` [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers Vincent Sanders
  2009-04-23 17:48 ` [Qemu-devel] [PATCH 2/16] Add s3c SOC header Vincent Sanders
@ 2009-04-23 17:50 ` Vincent Sanders
  2009-04-23 17:52 ` [Qemu-devel] [PATCH 4/16] S3C irq controller Vincent Sanders
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 29+ messages in thread
From: Vincent Sanders @ 2009-04-23 17:50 UTC (permalink / raw)
  To: qemu-devel

Peripheral driver for S3C SOC SDRAM controller.
Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 s3c24xx_memc.c |   70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff -urN qemusvnclean/hw/s3c24xx_memc.c qemusvnpatches/hw/s3c24xx_memc.c
--- qemusvnclean/hw/s3c24xx_memc.c	1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/s3c24xx_memc.c	2009-04-23 15:57:46.000000000 +0100
@@ -0,0 +1,70 @@
+/* hw/s3c24xx_memc.c
+ *
+ * Samsung S3C24XX memory controller emulation.
+ *
+ * The SDRAM controller on several S3C SOC is generic, the emulation needs to
+ * be little more than backing the registers.
+ *
+ * Copyright 2006, 2007 Daniel Silverstone and Vincent Sanders
+ *
+ * This file is under the terms of the GNU General Public
+ * License Version 2
+ */
+
+#include "hw.h"
+
+#include "s3c24xx.h"
+
+static void
+s3c24xx_memc_write_f(void *opaque, target_phys_addr_t addr_, uint32_t value)
+{
+    S3CState *soc = (S3CState *)opaque;
+    int addr = (addr_ & 0x3f) >> 2;
+
+    if (addr < 0 || addr > 12) 
+        addr = 12;
+
+    soc->memc_reg[addr] = value;
+}
+
+static uint32_t
+s3c24xx_memc_read_f(void *opaque, target_phys_addr_t addr_)
+{
+    S3CState *soc = (S3CState *)opaque;
+    int addr = (addr_ & 0x3f) >> 2;
+
+    if (addr < 0 || addr > 12) 
+        addr = 12;
+
+    return soc->memc_reg[addr];
+}
+
+static CPUReadMemoryFunc *s3c24xx_memc_read[] = {
+    &s3c24xx_memc_read_f,
+    &s3c24xx_memc_read_f,
+    &s3c24xx_memc_read_f,
+};
+
+static CPUWriteMemoryFunc *s3c24xx_memc_write[] = {
+    &s3c24xx_memc_write_f,
+    &s3c24xx_memc_write_f,
+    &s3c24xx_memc_write_f,
+};
+
+
+void
+s3c24xx_memc_init(S3CState *soc, target_phys_addr_t base_addr)
+{
+    /* Memory controller is simple SDRAM control. As SDRAM is emulated and
+     * requires no setup the emulation needs to be nothing more than memory
+     * backing the registers.
+     *
+     * There are 13 registers, each 4 bytes.
+     */
+    int tag;
+    tag = cpu_register_io_memory(0, s3c24xx_memc_read, s3c24xx_memc_write, soc);
+    cpu_register_physical_memory(base_addr, 13 * 4, tag);
+  
+    for (tag = 0; tag < 13; tag++)
+        soc->memc_reg[tag] = 0;
+}


-- 
Regards Vincent
http://www.kyllikki.org/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 4/16] S3C irq controller
  2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
                   ` (2 preceding siblings ...)
  2009-04-23 17:50 ` [Qemu-devel] [PATCH 3/16] S3C SDRAM memory controller Peripheral Vincent Sanders
@ 2009-04-23 17:52 ` Vincent Sanders
  2009-04-23 17:58 ` [Qemu-devel] [PATCH 05/16] S3C Clock controller peripheral Vincent Sanders
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 29+ messages in thread
From: Vincent Sanders @ 2009-04-23 17:52 UTC (permalink / raw)
  To: qemu-devel

S3C IRQ controller

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 s3c24xx_irq.c |  200 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 200 insertions(+)


diff -urN qemusvnclean/hw/s3c24xx_irq.c qemusvnpatches/hw/s3c24xx_irq.c
--- qemusvnclean/hw/s3c24xx_irq.c	1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/s3c24xx_irq.c	2009-04-23 16:00:07.000000000 +0100
@@ -0,0 +1,200 @@
+/* hw/s3c24xx_irq.c
+ *
+ * Samsung S3C24XX IRQ controller emulation
+ *
+ * Copyright 2006, 2007, 2008 Daniel Silverstone and Vincent Sanders
+ *
+ * This file is under the terms of the GNU General Public
+ * License Version 2
+ */
+
+#include "hw.h"
+
+#include "s3c24xx.h"
+
+/* IRQ request status              RW WORD */
+#define S3C_IRQ_SRCPND 0
+/* Interrupt mode control          WR WORD */
+#define S3C_IRQ_INTMOD 1
+/* Interrupt mask control          RW WORD */
+#define S3C_IRQ_INTMSK 2
+/* IRQ priority control            WR WORD */
+#define S3C_IRQ_PRIORITY 3
+/* Interrupt request status        RW WORD */
+#define S3C_IRQ_INTPND 4
+/* Interrupt request source offset RO WORD */
+#define S3C_IRQ_OFFSET 5
+/* Sub-source pending              RW WORD */
+#define S3C_IRQ_SUBSRCPND 6
+/* Interrupt sub-mask              RW WORD */
+#define S3C_IRQ_INTSUBMSK 7
+
+
+static void
+s3c24xx_percolate_interrupt(S3CState *soc)
+{
+    /* Take the status of the srcpnd register, percolate it through, raise to
+     * CPU if necessary */
+    uint32_t ints = (soc->irq_reg[S3C_IRQ_SRCPND] & 
+                     ~soc->irq_reg[S3C_IRQ_INTMSK]);
+    int fsb = ffs(ints);
+  
+    /* TODO: Priority encoder could go here */
+    if (ints & soc->irq_reg[S3C_IRQ_INTMOD]) {
+        /* Detected a FIQ */
+        cpu_interrupt(soc->cpu_env, CPU_INTERRUPT_FIQ);
+        return;
+    } else {
+        /* No FIQ here today */
+        cpu_reset_interrupt(soc->cpu_env, CPU_INTERRUPT_FIQ);
+    }
+
+    /* No FIQ, check for a normal IRQ */
+    if (fsb) {
+        if ((soc->irq_reg[S3C_IRQ_INTPND] == 0) ||
+            (soc->irq_reg[S3C_IRQ_INTPND] > 1<<(fsb-1))) {
+            /* Current INTPND is lower priority than fsb of ints (or empty) */
+            soc->irq_reg[S3C_IRQ_INTPND] = 1<<(fsb-1);
+            soc->irq_reg[S3C_IRQ_OFFSET] = fsb-1;
+        }
+    } else {
+        /* No FSB, thus no IRQ, thus nothing to do yet */
+    }
+
+    if (soc->irq_reg[S3C_IRQ_INTPND] != 0) {
+        cpu_interrupt(soc->cpu_env, CPU_INTERRUPT_HARD);
+    } else {
+        cpu_reset_interrupt(soc->cpu_env, CPU_INTERRUPT_HARD);
+    }
+}
+
+static void
+s3c24xx_percolate_subsrc_interrupt(S3CState *soc)
+{
+    uint32_t ints;
+  
+    soc->irq_reg[S3C_IRQ_SRCPND] |= soc->irq_main_level;
+    soc->irq_reg[S3C_IRQ_SUBSRCPND] |= soc->irq_subsrc_level;
+  
+    ints = (soc->irq_reg[S3C_IRQ_SUBSRCPND] &
+            ~soc->irq_reg[S3C_IRQ_INTSUBMSK]);
+   
+    /* If UART0 has asserted, raise that */
+    if( ints & 0x7 ) {
+        soc->irq_reg[S3C_IRQ_SRCPND] |= (1<<28);
+    }
+
+    /* Ditto UART1 */
+    if( ints & 0x7<<3 ) soc->irq_reg[S3C_IRQ_SRCPND] |= (1<<23);
+
+    /* Ditto UART2 */
+    if( ints & 0x7<<6 ) soc->irq_reg[S3C_IRQ_SRCPND] |= (1<<15);
+
+    /* And percolate it through */
+    s3c24xx_percolate_interrupt(soc);
+}
+
+static void
+s3c24xx_irq_write_f(void *opaque, target_phys_addr_t addr_, uint32_t value)
+{
+    S3CState *soc = (S3CState *)opaque;
+    int addr = (addr_ >> 2) & 7;
+
+    if (addr == S3C_IRQ_SRCPND ||
+        addr == S3C_IRQ_INTPND ||
+        addr == S3C_IRQ_SUBSRCPND) {
+        soc->irq_reg[addr] &= ~value;
+    } else {
+        soc->irq_reg[addr] = value;
+    }
+
+    /* Start at the subsrc irqs and percolate from there */
+    s3c24xx_percolate_subsrc_interrupt(soc);
+}
+
+static uint32_t
+s3c24xx_irq_read_f(void *opaque, target_phys_addr_t addr_)
+{
+    S3CState *soc = (S3CState *)opaque;
+    int addr = (addr_ >> 2) & 0x7;
+
+    return soc->irq_reg[addr];
+}
+
+
+static CPUReadMemoryFunc *s3c24xx_irq_read[] = {
+    &s3c24xx_irq_read_f,
+    &s3c24xx_irq_read_f,
+    &s3c24xx_irq_read_f,
+};
+
+static CPUWriteMemoryFunc *s3c24xx_irq_write[] = {
+    &s3c24xx_irq_write_f,
+    &s3c24xx_irq_write_f,
+    &s3c24xx_irq_write_f,
+};
+
+static void
+s3c24xx_irq_set_interrupt_level(S3CState *soc, int irq_num, int level, int set_level)
+{
+    if (level) {
+        if (set_level) soc->irq_main_level |= 1<<irq_num;
+        soc->irq_reg[S3C_IRQ_SRCPND] |= 1<<irq_num;
+    } else {
+        soc->irq_main_level &= ~(1<<irq_num);
+        soc->irq_reg[S3C_IRQ_SRCPND] &= ~(1<<irq_num);
+    }
+    s3c24xx_percolate_subsrc_interrupt(soc);
+}
+
+static void
+s3c24xx_irq_set_subsrc_interrupt_level(S3CState *soc, int irq_num, int level, int set_level)
+{
+
+    if (level) {
+        if (set_level) soc->irq_subsrc_level |= 1<<irq_num;
+        soc->irq_reg[S3C_IRQ_SUBSRCPND] |= 1<<irq_num;
+    } else {
+        soc->irq_subsrc_level &= ~(1<<irq_num);
+        soc->irq_reg[S3C_IRQ_SUBSRCPND] &= ~(1<<irq_num);
+    }
+    s3c24xx_percolate_subsrc_interrupt(soc);
+}
+
+static void
+s3c24xx_irq_handler(void *opaque, int _n, int level)
+{
+    S3CState *soc = (S3CState *)opaque;
+    int irq_num = _n % 32;
+    int is_subsrc = (_n & 32)?1:0;
+    int is_level = (_n & 64)?1:0;
+
+    if (is_subsrc == 0)
+        s3c24xx_irq_set_interrupt_level(soc, irq_num, level, is_level);
+    else
+        s3c24xx_irq_set_subsrc_interrupt_level(soc, irq_num, level, is_level);
+}
+
+qemu_irq *
+s3c24xx_irq_init(S3CState *soc, target_phys_addr_t base_addr)
+{
+    /* Samsung S3C2410X IRQ registration. */
+    int tag = cpu_register_io_memory(0, s3c24xx_irq_read, s3c24xx_irq_write, soc);
+    cpu_register_physical_memory(base_addr, 8 * 4, tag);
+
+    /* Set up registers to power on values */
+    soc->irq_reg[S3C_IRQ_SRCPND] = 0x00;
+    soc->irq_reg[S3C_IRQ_INTMOD] = 0x00;
+    soc->irq_reg[S3C_IRQ_INTMSK] = 0xFFFFFFFF;
+    soc->irq_reg[S3C_IRQ_PRIORITY] = 0x7F; 
+    soc->irq_reg[S3C_IRQ_INTPND] = 0x00;
+    soc->irq_reg[S3C_IRQ_OFFSET] = 0x00;
+    soc->irq_reg[S3C_IRQ_SUBSRCPND] = 0x00;
+    soc->irq_reg[S3C_IRQ_INTSUBMSK] = 0x7FF;
+
+    /* Allocate the interrupts and return them. All 64 potential ones.
+     * We return them doubled up because the latter half are level where
+     * the former half are edge.
+     */
+    return qemu_allocate_irqs(s3c24xx_irq_handler, soc, 128);
+}

-- 
Regards Vincent
http://www.kyllikki.org/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 05/16] S3C Clock controller peripheral
  2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
                   ` (3 preceding siblings ...)
  2009-04-23 17:52 ` [Qemu-devel] [PATCH 4/16] S3C irq controller Vincent Sanders
@ 2009-04-23 17:58 ` Vincent Sanders
  2009-04-23 18:00 ` [Qemu-devel] [PATCH 7/16] S3C serial peripheral Vincent Sanders
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 29+ messages in thread
From: Vincent Sanders @ 2009-04-23 17:58 UTC (permalink / raw)
  To: qemu-devel

S3C Clock control support.

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 s3c24xx_clkcon.c |  100 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 100 insertions(+)


diff -urN qemusvnclean/hw/s3c24xx_clkcon.c qemusvnpatches/hw/s3c24xx_clkcon.c
--- qemusvnclean/hw/s3c24xx_clkcon.c	1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/s3c24xx_clkcon.c	2009-04-23 16:00:56.000000000 +0100
@@ -0,0 +1,100 @@
+/* hw/s3c24xx_clkcon.c
+ *
+ * Samsung S3C24XX Clock control emulation
+ *
+ * Copyright 2006, 2007, 2008 Daniel Silverstone and Vincent Sanders
+ *
+ * This file is under the terms of the GNU General Public
+ * License Version 2
+ */
+
+#include "hw.h"
+
+#include "s3c24xx.h"
+
+/* Lock time RW */
+#define S3C_REG_LOCKTIME 0
+
+/* MPLL Control RW */
+#define S3C_REG_MPLLCON 1
+
+/* UPLL Control RW */
+#define S3C_REG_UPLLCON 2
+
+/* Clock Generator Control RW */
+#define S3C_REG_CLKCON 3
+
+/* CLKCON IDLE */
+#define S3C_REG_CLKCON_IDLE (1<<2)
+
+/* Slow Clock Control RW */
+#define S3C_REG_CLKSLOW 4
+
+/* Clock divider control RW */
+#define S3C_REG_CLKDIVN 5
+
+static void
+s3c24xx_clkcon_write_f(void *opaque, target_phys_addr_t addr_, uint32_t value)
+{
+    S3CState *soc = (S3CState *)opaque;
+    int addr = (addr_ & 0x1F) >> 2;
+    int idle_rising_edge = 0;
+
+    if (addr < 0 || addr > 5) 
+        addr = 5;
+
+    if (addr == S3C_REG_CLKCON) {
+        if( !(soc->clkcon_reg[addr] & S3C_REG_CLKCON_IDLE) &&
+            (value & S3C_REG_CLKCON_IDLE) ) idle_rising_edge = 1;
+    }
+    soc->clkcon_reg[addr] = value;
+    if (idle_rising_edge) {
+        cpu_interrupt(soc->cpu_env, CPU_INTERRUPT_HALT);
+    }
+}
+
+static uint32_t
+s3c24xx_clkcon_read_f(void *opaque, target_phys_addr_t addr_)
+{
+    S3CState *soc = (S3CState *)opaque;
+    int addr = (addr_ & 0x1F) >> 2;
+
+    if (addr < 0 || addr > 5) 
+        addr = 5;
+
+    return soc->clkcon_reg[addr];
+}
+
+static CPUReadMemoryFunc *s3c24xx_clkcon_read[] = {
+    &s3c24xx_clkcon_read_f,
+    &s3c24xx_clkcon_read_f,
+    &s3c24xx_clkcon_read_f,
+};
+
+static CPUWriteMemoryFunc *s3c24xx_clkcon_write[] = {
+    &s3c24xx_clkcon_write_f,
+    &s3c24xx_clkcon_write_f,
+    &s3c24xx_clkcon_write_f,
+};
+
+
+void
+s3c24xx_clkcon_init(S3CState *soc, target_phys_addr_t base_addr)
+{
+    int tag;
+
+    tag = cpu_register_io_memory(0, s3c24xx_clkcon_read, s3c24xx_clkcon_write, soc);
+    cpu_register_physical_memory(base_addr, 6 * 4, tag);
+
+    /* initialise register values to power on defaults */  
+    soc->clkcon_reg[S3C_REG_LOCKTIME] = 0x00FFFFFF;
+    soc->clkcon_reg[S3C_REG_MPLLCON] = 0x0005C080;
+    soc->clkcon_reg[S3C_REG_UPLLCON] = 0x00028080;
+    soc->clkcon_reg[S3C_REG_CLKCON] = 0x0007FFF0;
+    soc->clkcon_reg[S3C_REG_CLKSLOW] = 0x00000004;
+    soc->clkcon_reg[S3C_REG_CLKDIVN] = 0x00000000;
+
+    /* Currently it is assumed the t1 clock will be fed by a 12MHz source */
+    soc->tclk1 = 12000000;
+
+}

-- 
Regards Vincent
http://www.kyllikki.org/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 7/16] S3C serial peripheral
  2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
                   ` (4 preceding siblings ...)
  2009-04-23 17:58 ` [Qemu-devel] [PATCH 05/16] S3C Clock controller peripheral Vincent Sanders
@ 2009-04-23 18:00 ` Vincent Sanders
  2009-04-23 18:02 ` [Qemu-devel] [PATCH 6/16] S3C Timers Vincent Sanders
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 29+ messages in thread
From: Vincent Sanders @ 2009-04-23 18:00 UTC (permalink / raw)
  To: qemu-devel

S3C serial peripheral.

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 s3c24xx_serial.c |  266 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 266 insertions(+)

diff -urN qemusvnclean/hw/s3c24xx_serial.c qemusvnpatches/hw/s3c24xx_serial.c
--- qemusvnclean/hw/s3c24xx_serial.c	1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/s3c24xx_serial.c	2009-04-23 17:06:16.000000000 +0100
@@ -0,0 +1,266 @@
+/* hw/s3c24xx_serial.c
+ *
+ * Samsung S3C24XX Serial block
+ *
+ * Copyright 2006, 2007 Daniel Silverstone and Vincent Sanders
+ *
+ * This file is under the terms of the GNU General Public
+ * License Version 2
+ */
+
+#include "hw.h"
+#include "qemu-char.h"
+#include "sysemu.h"
+
+#include "s3c24xx.h"
+
+/* S3C24XX serial port registers */
+
+/* port spacing */
+#define S3C_SERIAL_PORT_STRIDE 0x4000
+
+/* Line control         RW WORD */
+#define S3C_SERIAL_ULCON 0x00
+/* General control      RW WORD */
+#define S3C_SERIAL_UCON  0x04
+/* Fifo control         RW WORD */
+#define S3C_SERIAL_UFCON 0x08
+/* Modem control        RW WORD */
+#define S3C_SERIAL_UMCON 0x0C
+/* TX/RX Status         RO WORD */
+#define S3C_SERIAL_UTRSTAT 0x10
+/* Receive Error Status RO WORD */
+#define S3C_SERIAL_UERSTAT 0x14
+/* FiFo Status          RO WORD */
+#define S3C_SERIAL_UFSTAT 0x18
+/* Modem Status         RO WORD */
+#define S3C_SERIAL_UMSTAT 0x1C
+/* TX buffer            WR BYTE */
+#define S3C_SERIAL_UTXH 0x20
+/* RX buffer            RO BYTE */
+#define S3C_SERIAL_URXH 0x24
+/* BAUD Divisor         RW WORD */
+#define S3C_SERIAL_UBRDIV 0x28
+
+/* S3C24XX serial port state */
+typedef struct {
+    uint32_t ulcon, ucon, ufcon, umcon, ubrdiv;
+    unsigned char rx_byte;
+    /* Byte is available to be read */
+    unsigned int rx_available : 1;
+    CharDriverState *chr;
+    int port;
+    qemu_irq tx_irq;
+    qemu_irq rx_irq;
+    qemu_irq tx_level;
+    qemu_irq rx_level;
+} s3c24xx_serial_dev;
+
+static void 
+s3c24xx_serial_write_f(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    s3c24xx_serial_dev *s = opaque;
+    int reg = addr & 0x3f;
+
+    switch(reg) {
+    case S3C_SERIAL_ULCON:
+        s->ulcon = value;
+        break;
+
+    case S3C_SERIAL_UCON:
+        s->ucon = value;
+        if( s->ucon & 1<<9 ) {
+            qemu_set_irq(s->tx_level, 1);
+        } else {
+            qemu_set_irq(s->tx_level, 0);
+        }
+        if( !(s->ucon & 1<<8) ) {
+            qemu_set_irq(s->rx_level, 0);
+        }
+        break;
+
+    case S3C_SERIAL_UFCON:
+        s->ufcon = (value & ~6);
+        break;
+
+    case S3C_SERIAL_UMCON:
+        s->umcon = value;
+        break;
+
+    case S3C_SERIAL_UTRSTAT:
+        break;
+
+    case S3C_SERIAL_UERSTAT:
+        break;
+
+    case S3C_SERIAL_UFSTAT:
+        break;
+
+    case S3C_SERIAL_UMSTAT:
+        break;
+
+    case S3C_SERIAL_UTXH: {
+        unsigned char ch = value & 0xff;
+        if (s->chr && ((s->ucon & 1<<5)==0))
+            qemu_chr_write(s->chr, &ch, 1);
+        else {
+            s->rx_byte = ch;
+            s->rx_available = 1;
+            if( s->ucon & 1<<8 ) {
+                qemu_set_irq(s->rx_level, 1);
+            } else {
+                qemu_set_irq(s->rx_irq, 1);
+            }
+        }
+        if( s->ucon & 1<<9 ) {
+            qemu_set_irq(s->tx_level, 1);
+        } else {
+            qemu_set_irq(s->tx_irq, 1);
+        }
+        break;
+    }
+
+    case S3C_SERIAL_URXH:
+        break;
+
+    case S3C_SERIAL_UBRDIV:
+        s->ubrdiv = value;
+        break;
+
+    default:
+        break;
+    };
+}
+
+static uint32_t
+s3c24xx_serial_read_f(void *opaque, target_phys_addr_t addr)
+{
+    s3c24xx_serial_dev *s = opaque;
+    int reg = addr & 0x3f;
+
+    switch(reg) {
+    case S3C_SERIAL_ULCON:
+        return s->ulcon;
+
+    case S3C_SERIAL_UCON:
+        return s->ucon;
+
+    case S3C_SERIAL_UFCON:
+        return s->ufcon & ~0x8; /* bit 3 is reserved, must be zero */
+
+    case S3C_SERIAL_UMCON:
+        return s->umcon & 0x11; /* Rest are reserved, must be zero */
+
+    case S3C_SERIAL_UTRSTAT:
+        return 6 | s->rx_available; /* TX always clear, RX when available */
+
+    case S3C_SERIAL_UERSTAT:
+        return 0; /* Later, break detect comes in here */
+
+    case S3C_SERIAL_UFSTAT:
+        return s->rx_available; /* TXFIFO, always empty, RXFIFO 0 or 1 bytes */
+
+    case S3C_SERIAL_UMSTAT:
+        return 0;
+
+    case S3C_SERIAL_UTXH:
+        return 0;
+
+    case S3C_SERIAL_URXH:
+        s->rx_available = 0;
+        if( s->ucon & 1<<8 ) {
+            qemu_set_irq(s->rx_level, 0);
+        }
+        return s->rx_byte;
+
+    case S3C_SERIAL_UBRDIV:
+        return s->ubrdiv;
+
+    default:
+        return 0;
+    };
+}
+
+static CPUReadMemoryFunc *s3c24xx_serial_read[] = {
+    &s3c24xx_serial_read_f,
+    &s3c24xx_serial_read_f,
+    &s3c24xx_serial_read_f,
+};
+
+static CPUWriteMemoryFunc *s3c24xx_serial_write[] = {
+    &s3c24xx_serial_write_f,
+    &s3c24xx_serial_write_f,
+    &s3c24xx_serial_write_f,
+};
+
+
+static void s3c24xx_serial_event(void *opaque, int event)
+{
+}
+
+static int 
+s3c24xx_serial_can_receive(void *opaque)
+{
+    s3c24xx_serial_dev *s = opaque;
+
+    /* If there's no byte to be read, we can receive a new one */
+    return !s->rx_available;
+}
+
+static void 
+s3c24xx_serial_receive(void *opaque, const uint8_t *buf, int size)
+{
+    s3c24xx_serial_dev *s = opaque;
+    s->rx_byte = buf[0];
+    s->rx_available = 1;
+    if ( s->ucon & 1 << 8 ) {
+        qemu_set_irq(s->rx_level, 1);
+    } else {
+        /* Is there something we can do here to ensure it's just a pulse ? */
+        qemu_set_irq(s->rx_irq, 1); 
+    }
+}
+
+/* Create a S3C serial port, the port implementation is common to all
+ * current s3c devices only differing in the I/O base address and number of 
+ * ports.
+ */
+void
+s3c24xx_serial_init(S3CState *soc, int port, target_phys_addr_t base_addr)
+{
+    /* Initialise a serial port at the given port address */
+    s3c24xx_serial_dev *s;
+    int serial_io;
+  
+    s = qemu_mallocz(sizeof(s3c24xx_serial_dev));
+    if (!s) 
+        return;
+
+    /* initialise serial port context */
+    s->chr = serial_hds[port];
+    s->ulcon = 0;
+    s->ucon = 0;
+    s->ufcon = 0;
+    s->umcon = 0;
+    s->ubrdiv = 0;
+    s->port = port;
+    s->rx_available = 0;
+    s->tx_irq = soc->irqs[32 + (port * 3) + 1];
+    s->rx_irq = soc->irqs[32 + (port * 3)];
+    s->tx_level = soc->irqs[64 + 32 + (port * 3) + 1];
+    s->rx_level = soc->irqs[64 + 32 + (port * 3)];
+
+    /* Prepare our MMIO tag */
+    serial_io = cpu_register_io_memory(0, s3c24xx_serial_read, s3c24xx_serial_write, s);
+    /* Register the region with the tag */
+    cpu_register_physical_memory(base_addr + (port * S3C_SERIAL_PORT_STRIDE), 44, serial_io);
+
+    if (s->chr) {
+        /* If the port is present add to the character device's IO handlers. */
+        qemu_chr_add_handlers(s->chr, 
+                              s3c24xx_serial_can_receive,
+                              s3c24xx_serial_receive, 
+                              s3c24xx_serial_event, 
+                              s);
+    }
+}


-- 
Regards Vincent
http://www.kyllikki.org/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 6/16] S3C Timers
  2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
                   ` (5 preceding siblings ...)
  2009-04-23 18:00 ` [Qemu-devel] [PATCH 7/16] S3C serial peripheral Vincent Sanders
@ 2009-04-23 18:02 ` Vincent Sanders
  2009-04-23 18:04 ` [Qemu-devel] [PATCH 8/16] S3C Real Time Clock Vincent Sanders
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 29+ messages in thread
From: Vincent Sanders @ 2009-04-23 18:02 UTC (permalink / raw)
  To: qemu-devel

S3C Timer implementation

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 s3c24xx_timers.c |  137 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 137 insertions(+)

diff -urN qemusvnclean/hw/s3c24xx_timers.c qemusvnpatches/hw/s3c24xx_timers.c
--- qemusvnclean/hw/s3c24xx_timers.c	1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/s3c24xx_timers.c	2009-04-23 16:03:04.000000000 +0100
@@ -0,0 +1,137 @@
+/* hw/s3c24xx_timers.c
+ *
+ * Samsung S3C24XX emulation
+ *
+ * Copyright 2006, 2007, 2008 Daniel Silverstone and Vincent Sanders
+ *
+ * This file is under the terms of the GNU General Public
+ * License Version 2
+ */
+
+#include "hw.h"
+#include "qemu-timer.h"
+
+#include "s3c24xx.h"
+
+/*
+  QEMU_TIMER_BASE is ticks per second for the qemu clocks
+  TCLK1 (assumed input for timer4) is 12 MHz
+  Thus, period in ticks of timer4 is:
+
+  (timer4_period * QEMU_TIMER_BASE) / TCLK1
+*/
+  
+/* Timer configuration 0 */
+#define S3C_TIMERS_TCFG0 0
+/* Timer configuration 1 */
+#define S3C_TIMERS_TCFG1 1
+/* Timer control */
+#define S3C_TIMERS_TCON 2
+/* Timer count buffer 0 */
+#define S3C_TIMERS_TCNTB0 3
+/* Timer compare buffer 0 */
+#define S3C_TIMERS_TCMPB0 4
+/* Timer count observation 0 */
+#define S3C_TIMERS_TCNTO0 5
+/* Timer count buffer 1 */
+#define S3C_TIMERS_TCNTB1 6
+/* Timer compare buffer 1 */
+#define S3C_TIMERS_TCMPB1 7
+/* Timer count observation 1 */
+#define S3C_TIMERS_TCNTO1 8
+/* Timer count buffer 2 */
+#define S3C_TIMERS_TCNTB2 9
+/* Timer compare buffer 2 */
+#define S3C_TIMERS_TCMPB2 10
+/* Timer count observation 2 */
+#define S3C_TIMERS_TCNTO2 11
+/* Timer count buffer 3 */
+#define S3C_TIMERS_TCNTB3 12
+/* Timer compare buffer 3 */
+#define S3C_TIMERS_TCMPB3 13
+/* Timer count observation 3 */
+#define S3C_TIMERS_TCNTO3 14
+/* Timer count buffer 4 */
+#define S3C_TIMERS_TCNTB4 15
+/* Timer count observation 4 */
+#define S3C_TIMERS_TCNTO4 16
+
+static void
+s3c24xx_schedule_timer4(S3CState *soc)
+{
+    soc->timers_reg[S3C_TIMERS_TCNTB4] = soc->timer4_reload_value;
+    soc->timer4_last_ticked = qemu_get_clock(vm_clock);
+    qemu_mod_timer(soc->timer4, 
+                   soc->timer4_last_ticked + ((soc->timer4_reload_value * ticks_per_sec) / soc->tclk1));
+}
+
+static void
+s3c24xx_timer4_tick(void *opaque)
+{
+    S3CState *soc = (S3CState *)opaque;
+
+    qemu_set_irq(soc->irqs[14], 1);
+    if (soc->timers_reg[S3C_TIMERS_TCON] && (1<<22)) {
+        s3c24xx_schedule_timer4(soc);
+    }
+}
+
+static void
+s3c24xx_timers_write_f(void *opaque, target_phys_addr_t addr_, uint32_t value)
+{
+    S3CState *soc = (S3CState *)opaque;
+    int addr = (addr_ >> 2) & 0x1f;
+
+    soc->timers_reg[addr] = value;
+    if (addr == S3C_TIMERS_TCON) {
+        /* If Timer4's manual update is set, copy in the reload value */
+        if (value & (1 << 21) ) 
+            soc->timer4_reload_value = soc->timers_reg[S3C_TIMERS_TCNTB4];
+
+        /* If Timer4's manual update is unset, and the timer is running, start it */
+        if (!(value & (1 << 21)) && 
+            value & (1 << 20)) {
+            s3c24xx_schedule_timer4(soc);
+        }
+    }
+}
+
+static uint32_t
+s3c24xx_timers_read_f(void *opaque, target_phys_addr_t addr_)
+{
+    S3CState *soc = (S3CState *)opaque;
+    int addr = (addr_ >> 2) & 0x1f;
+
+    if (addr == S3C_TIMERS_TCNTO4 ) {
+        return soc->timer4_reload_value - 
+            (((qemu_get_clock(vm_clock) - soc->timer4_last_ticked) * soc->tclk1) / ticks_per_sec);
+    }
+    return soc->timers_reg[addr];
+}
+
+
+static CPUReadMemoryFunc *s3c24xx_timers_read[] = {
+    &s3c24xx_timers_read_f,
+    &s3c24xx_timers_read_f,
+    &s3c24xx_timers_read_f,
+};
+
+static CPUWriteMemoryFunc *s3c24xx_timers_write[] = {
+    &s3c24xx_timers_write_f,
+    &s3c24xx_timers_write_f,
+    &s3c24xx_timers_write_f,
+};
+
+void
+s3c24xx_timers_init(S3CState *soc, target_phys_addr_t base_addr)
+{
+    /* Samsung S3C2410X timer registration.
+     *
+     * Specifically the PWM timer4.
+     */
+    int tag = cpu_register_io_memory(0, s3c24xx_timers_read, s3c24xx_timers_write, soc);
+    cpu_register_physical_memory(base_addr, 17 * 4, tag);
+
+    soc->timer4 = qemu_new_timer(vm_clock, s3c24xx_timer4_tick, soc);
+}
+


-- 
Regards Vincent
http://www.kyllikki.org/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 8/16] S3C Real Time Clock
  2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
                   ` (6 preceding siblings ...)
  2009-04-23 18:02 ` [Qemu-devel] [PATCH 6/16] S3C Timers Vincent Sanders
@ 2009-04-23 18:04 ` Vincent Sanders
  2009-04-23 18:05 ` [Qemu-devel] [PATCH 9/16] S3C General Purpose IO Vincent Sanders
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 29+ messages in thread
From: Vincent Sanders @ 2009-04-23 18:04 UTC (permalink / raw)
  To: qemu-devel

Real Time clock

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 s3c24xx_rtc.c |  123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 123 insertions(+)

diff -urN qemusvnclean/hw/s3c24xx_rtc.c qemusvnpatches/hw/s3c24xx_rtc.c
--- qemusvnclean/hw/s3c24xx_rtc.c	1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/s3c24xx_rtc.c	2009-04-23 17:07:07.000000000 +0100
@@ -0,0 +1,123 @@
+/* hw/s3c24xx_rtc.c
+ *
+ * Samsung S3C24XX RTC emulation
+ *
+ * Copyright 2006, 2007, 2008 Daniel Silverstone and Vincent Sanders
+ *
+ * This file is under the terms of the GNU General Public
+ * License Version 2
+ */
+
+#include "hw.h"
+
+#include "s3c24xx.h"
+
+
+/* RTC Control RW Byte */
+#define S3C_REG_RTCCON 0
+/* Tick time count RW Byte */
+#define S3C_REG_TICNT 1
+/* RTC Alarm Control RW Byte */
+#define S3C_REG_RTCALM 4
+/* Alarm second */
+#define S3C_REG_ALMSEC 5
+/* Alarm minute */
+#define S3C_REG_ALMMIN 6
+/* Alarm hour */
+#define S3C_REG_ALMHOUR 7
+/* Alarm day */
+#define S3C_REG_ALMDATE 8
+/* Alarm month */
+#define S3C_REG_ALMMON 9
+/* Alarm year */
+#define S3C_REG_ALMYEAR 10
+/* RTC Round Reset */
+#define S3C_REG_RTCRST 11
+/* BCD Second */
+#define S3C_REG_BCDSEC 12
+/* BCD Minute */
+#define S3C_REG_BCDMIN 13
+/* BCD Hour */
+#define S3C_REG_BCDHOUR 14
+/* BCD Day */
+#define S3C_REG_BCDDATE 15
+/* BCD Day of week */
+#define S3C_REG_BCDDAY 16
+/* BCD Month */
+#define S3C_REG_BCDMON 17
+/* BCD Year */
+#define S3C_REG_BCDYEAR 18
+
+static inline int to_bcd(int a)
+{
+    return ((a/10)<<4) | (a%10);
+}
+
+static void update_time(S3CState *soc)
+{
+    time_t ti;
+    struct tm *tm;
+    /* update the RTC registers from system time */
+    time(&ti);
+    tm = gmtime(&ti);
+    soc->rtc_reg[S3C_REG_BCDSEC] = to_bcd(tm->tm_sec);
+    soc->rtc_reg[S3C_REG_BCDMIN] = to_bcd(tm->tm_min);
+    soc->rtc_reg[S3C_REG_BCDHOUR] = to_bcd(tm->tm_hour);
+    soc->rtc_reg[S3C_REG_BCDDATE] = to_bcd(tm->tm_mday);
+    soc->rtc_reg[S3C_REG_BCDDAY] = to_bcd(tm->tm_wday + 1);
+    soc->rtc_reg[S3C_REG_BCDMON] = to_bcd(tm->tm_mon + 1);
+    soc->rtc_reg[S3C_REG_BCDYEAR] =  to_bcd(tm->tm_year - 100);
+}
+
+static void
+s3c24xx_rtc_write_f(void *opaque, target_phys_addr_t addr_, uint32_t value)
+{
+    S3CState *soc = (S3CState *)opaque;
+    int addr = (addr_ - 0x40) >> 2;
+    if (addr < 0 || addr > 18) 
+        addr = 18;
+
+    soc->rtc_reg[addr] = value;
+}
+
+static uint32_t
+s3c24xx_rtc_read_f(void *opaque, target_phys_addr_t addr_)
+{
+    S3CState *soc = (S3CState *)opaque;
+    int addr = (addr_ - 0x40) >> 2;
+
+    if (addr < 0 || addr > 18) 
+        addr = 18;
+
+    update_time(soc);        
+
+    return soc->rtc_reg[addr];
+}
+
+static CPUReadMemoryFunc *s3c24xx_rtc_read[] = {
+    &s3c24xx_rtc_read_f,
+    &s3c24xx_rtc_read_f,
+    &s3c24xx_rtc_read_f,
+};
+
+static CPUWriteMemoryFunc *s3c24xx_rtc_write[] = {
+    &s3c24xx_rtc_write_f,
+    &s3c24xx_rtc_write_f,
+    &s3c24xx_rtc_write_f,
+};
+
+
+void
+s3c24xx_rtc_init(S3CState *soc, target_phys_addr_t base_addr)
+{
+    int tag;
+    tag = cpu_register_io_memory(0, s3c24xx_rtc_read, s3c24xx_rtc_write, soc);
+
+    /* there are only 19 real registers but they start at offset 0x40 into the
+     * range so we have 35 registers mapped 
+     */
+    cpu_register_physical_memory(base_addr, 35 * 4, tag);
+
+    /* set the RTC so it appears active */
+    soc->rtc_reg[S3C_REG_RTCCON] = 1;
+}

-- 
Regards Vincent
http://www.kyllikki.org/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 9/16] S3C General Purpose IO
  2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
                   ` (7 preceding siblings ...)
  2009-04-23 18:04 ` [Qemu-devel] [PATCH 8/16] S3C Real Time Clock Vincent Sanders
@ 2009-04-23 18:05 ` Vincent Sanders
  2009-04-23 18:07 ` [Qemu-devel] [PATCH 10/16] S3C I2C peripheral Vincent Sanders
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 29+ messages in thread
From: Vincent Sanders @ 2009-04-23 18:05 UTC (permalink / raw)
  To: qemu-devel

S3C GPIO support

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 s3c24xx_gpio.c |  190 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 190 insertions(+)

diff -urN qemusvnclean/hw/s3c24xx_gpio.c qemusvnpatches/hw/s3c24xx_gpio.c
--- qemusvnclean/hw/s3c24xx_gpio.c	1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/s3c24xx_gpio.c	2009-04-23 17:07:45.000000000 +0100
@@ -0,0 +1,190 @@
+/* hw/s3c24xx_gpio.c
+ *
+ * Samsung S3C24XX GPIO emulation (mostly for E-INT)
+ *
+ * Copyright 2006, 2007 Daniel Silverstone and Vincent Sanders
+ *
+ * This file is under the terms of the GNU General Public
+ * License Version 2
+ */
+
+#include "hw.h"
+#include "s3c24xx.h"
+
+#define S3C_GPIO_GPECON (0x40)
+#define S3C_GPIO_GPEDAT (0x44)
+#define S3C_GPIO_GPEUP (0x48)
+
+#define S3C_GPIO_EINT_MASK (0xA4)
+#define S3C_GPIO_EINT_PEND (0xA8)
+#define S3C_GPIO_GSTATUS0 (0xAC)
+#define S3C_GPIO_GSTATUS1 (0xB0)
+#define S3C_GPIO_GSTATUS2 (0xB4)
+#define S3C_GPIO_GSTATUS3 (0xB8)
+#define S3C_GPIO_GSTATUS4 (0xBC)
+
+
+#define GPRN(r) (r>>2)
+#define GPR(P) soc->gpio_reg[P>>2]
+
+static void
+s3c24xx_gpio_propogate_eint(S3CState *soc)
+{
+    uint32_t ints, i;
+
+    ints = GPR(S3C_GPIO_EINT_PEND) & ~GPR(S3C_GPIO_EINT_MASK);
+
+    /* EINT0 - EINT3 are INT0 - INT3 */
+    for (i=0; i < 4; ++i)
+        qemu_set_irq(soc->irqs[i], (ints&(1<<i))?1:0);
+
+    /* EINT4 - EINT7 are INT4 */
+    qemu_set_irq(soc->irqs[4], (ints & 0xf0)?1:0);
+
+    /* EINT8 - EINT23 are INT5 */
+    qemu_set_irq(soc->irqs[5], (ints & 0x00ffff00)?1:0);
+}
+
+static uint32_t
+gpio_con_to_mask(uint32_t con)
+{
+    uint32_t mask = 0x0;
+    int bit;
+
+    for (bit = 0; bit < 16; bit++) {
+        if (((con >> (bit*2)) & 0x3) == 0x01)
+            mask |= 1 << bit;
+    }
+
+    return mask;
+}
+
+static void
+s3c24xx_gpio_write_f(void *opaque, target_phys_addr_t addr_, uint32_t value)
+{
+    S3CState *soc = (S3CState *)opaque;
+    int addr = (addr_ >> 2) & 0x3f;
+
+    if (addr < 0 || addr > 47) 
+        addr = 47;
+
+    if (addr == (S3C_GPIO_EINT_MASK>>2)) 
+        value &= ~0xf; /* cannot mask EINT0-EINT3 */
+
+    if (addr == (S3C_GPIO_EINT_PEND>>2)) {
+        soc->gpio_reg[addr] &= ~value;
+    } else {
+        if (addr < (0x80/4) && (addr_ & 0xf) == 0x04) {
+            uint32_t mask = gpio_con_to_mask(soc->gpio_reg[addr-1]);
+
+            value &= mask;
+
+            soc->gpio_reg[addr] &= ~mask;
+            soc->gpio_reg[addr] |= value;
+        } else
+            soc->gpio_reg[addr] = value;
+    }
+
+    if ((addr == (S3C_GPIO_EINT_MASK)>>2) || 
+        (addr == (S3C_GPIO_EINT_PEND)>>2)) {
+        /* A write to the EINT regs leads us to determine the interrupts to
+         * propagate 
+         */
+        s3c24xx_gpio_propogate_eint(soc);
+    }
+}
+
+static uint32_t
+s3c24xx_gpio_read_f(void *opaque, target_phys_addr_t addr_)
+{
+    S3CState *soc = (S3CState *)opaque;
+    uint32_t addr = (addr_ >> 2);
+    uint32_t ret;
+
+    if (addr > GPRN(S3C_GPIO_GSTATUS4))
+        addr = GPRN(S3C_GPIO_GSTATUS4);
+
+    ret = soc->gpio_reg[addr];
+
+    if (addr == GPRN(S3C_GPIO_GPEDAT)) {
+        /* IIC pins are special function pins on GPE14 and GPE15. If GPE is is
+         * in input mode make the IIC lines appear to be pulled high. This is
+         * neccissary because OS i2c drivers use this to ensure the I2C bus is
+         * clear.
+         */
+        if ((GPR(S3C_GPIO_GPECON) & (3<<28)) == 0) 
+            ret |= 1 << 14;
+
+        if ((GPR(S3C_GPIO_GPECON) & (3<<30)) == 0) 
+            ret |= 1 << 15;
+    }
+
+    return ret;
+}
+
+
+static CPUReadMemoryFunc *s3c24xx_gpio_read[] = {
+    &s3c24xx_gpio_read_f,
+    &s3c24xx_gpio_read_f,
+    &s3c24xx_gpio_read_f,
+};
+
+static CPUWriteMemoryFunc *s3c24xx_gpio_write[] = {
+    &s3c24xx_gpio_write_f,
+    &s3c24xx_gpio_write_f,
+    &s3c24xx_gpio_write_f,
+};
+
+static void
+s3c24xx_gpio_irq_handler(void *opaque, int n, int level)
+{
+    S3CState *soc = (S3CState *)opaque;
+    if (level)
+        GPR(S3C_GPIO_EINT_PEND) |= (1<<n);
+
+    s3c24xx_gpio_propogate_eint(soc);
+}
+
+void
+s3c24xx_gpio_init(S3CState *soc, target_phys_addr_t base_addr, uint32_t cpu_id)
+{
+    /* Samsung S3C24XX GPIO
+     *
+     * The primary operation here is the ID register and IRQs
+     */
+    int tag = cpu_register_io_memory(0, s3c24xx_gpio_read, s3c24xx_gpio_write, soc);
+    cpu_register_physical_memory(base_addr, 47 * 4, tag);
+
+    GPR(0x00) = 0x7fffff;
+    GPR(0x10) = 0;
+    GPR(0x18) = 0;
+    GPR(0x20) = 0;
+    GPR(0x28) = 0;
+    GPR(0x30) = 0;
+    GPR(0x34) = 0xfefc;	
+    GPR(0x38) = 0xf000;
+    GPR(0x40) = 0;
+    GPR(0x48) = 0;
+    GPR(0x50) = 0;
+    GPR(0x58) = 0;
+    GPR(0x60) = 0;
+    GPR(0x68) = 0xf800;
+    GPR(0x70) = 0;
+    GPR(0x78) = 0;
+    GPR(0x80) = 0x10330;
+    GPR(0x84) = 0;
+    GPR(0x88) = 0;
+    GPR(0x8C) = 0;
+    GPR(0x90) = 0;
+    GPR(0x9C) = 0;
+    GPR(0xA0) = 0;
+    GPR(0xA4) = 0xfffff0;
+    GPR(0xA8) = 0;
+    GPR(S3C_GPIO_GSTATUS1) = cpu_id;
+    GPR(S3C_GPIO_GSTATUS2) = 1;
+    GPR(S3C_GPIO_GSTATUS3) = 0;
+    GPR(S3C_GPIO_GSTATUS4) = 0;
+
+    /* EINTs 0-23 -- Only 24, not 48 because EINTs are not level */
+    soc->eirqs = qemu_allocate_irqs(s3c24xx_gpio_irq_handler, soc, 24);
+}


-- 
Regards Vincent
http://www.kyllikki.org/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 10/16] S3C I2C peripheral
  2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
                   ` (8 preceding siblings ...)
  2009-04-23 18:05 ` [Qemu-devel] [PATCH 9/16] S3C General Purpose IO Vincent Sanders
@ 2009-04-23 18:07 ` Vincent Sanders
  2009-04-23 18:08 ` [Qemu-devel] [PATCH 11/16] S3C LCD display Vincent Sanders
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 29+ messages in thread
From: Vincent Sanders @ 2009-04-23 18:07 UTC (permalink / raw)
  To: qemu-devel

S3C I2C peripheral

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 s3c24xx_iic.c |  322 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 322 insertions(+)

diff -urN qemusvnclean/hw/s3c24xx_iic.c qemusvnpatches/hw/s3c24xx_iic.c
--- qemusvnclean/hw/s3c24xx_iic.c	1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/s3c24xx_iic.c	2009-04-23 17:09:08.000000000 +0100
@@ -0,0 +1,322 @@
+/* hw/s3c24xx_iic.c
+ *
+ * Samsung S3C24XX emulation
+ *
+ * Copyright 2006, 2007, 2008 Daniel Silverstone, Ben Dooks
+ *  and Vincent Sanders
+ *
+ * This file is under the terms of the GNU General Public
+ * License Version 2
+ */
+
+#include "hw.h"
+#include "i2c.h"
+
+#include "s3c24xx.h"
+
+/* i2c controller registers */
+#define S3C_IICCON  (0x00)
+#define S3C_IICSTAT (0x04)
+#define S3C_IICADD  (0x08)
+#define S3C_IICDS   (0x0C)
+#define S3C_IICLC   (0x10)
+
+#define S3C_IICCON_ACKEN	(1<<7)
+#define S3C_IICCON_TXDIV_16	(0<<6)
+#define S3C_IICCON_TXDIV_512	(1<<6)
+#define S3C_IICCON_IRQEN	(1<<5)
+#define S3C_IICCON_IRQPEND	(1<<4)
+#define S3C_IICCON_SCALE(x)	((x)&15)
+#define S3C_IICCON_SCALEMASK	(0xf)
+
+#define S3C_IICSTAT_MASTER_RX	(2<<6)
+#define S3C_IICSTAT_MASTER_TX	(3<<6)
+#define S3C_IICSTAT_SLAVE_RX	(0<<6)
+#define S3C_IICSTAT_SLAVE_TX	(1<<6)
+#define S3C_IICSTAT_MODEMASK	(3<<6)
+
+#define S3C_IICSTAT_START	(1<<5)
+#define S3C_IICSTAT_BUSBUSY	(1<<5)
+#define S3C_IICSTAT_TXRXEN	(1<<4)
+#define S3C_IICSTAT_ARBITR	(1<<3)
+#define S3C_IICSTAT_ASSLAVE	(1<<2)
+#define S3C_IICSTAT_ADDR0	 (1<<1)
+#define S3C_IICSTAT_LASTBIT	 (1<<0)
+
+#define S3C_IICLC_SDA_DELAY0	 (0 << 0)
+#define S3C_IICLC_SDA_DELAY5	 (1 << 0)
+#define S3C_IICLC_SDA_DELAY10	 (2 << 0)
+#define S3C_IICLC_SDA_DELAY15	 (3 << 0)
+#define S3C_IICLC_SDA_DELAY_MASK (3 << 0)
+
+#define S3C_IICLC_FILTER_ON      (1<<2)
+
+/* IIC-bus serial interface */
+struct s3c24xx_i2c_state_s {
+    i2c_slave slave;
+    i2c_bus *bus;
+    target_phys_addr_t base;
+    qemu_irq irq;
+
+    uint8_t control;
+    uint8_t status;
+    uint8_t data;
+    uint8_t addy;
+    int busy;
+    int newstart;
+};
+
+static void s3c24xx_i2c_irq(struct s3c24xx_i2c_state_s *s)
+{
+    s->control |= 1 << 4;
+
+    if (s->control & (1 << 5)) {
+        qemu_irq_raise(s->irq);
+    }
+}
+
+static void s3c24xx_i2c_reset(struct s3c24xx_i2c_state_s *s)
+{
+    s->control = 0x00;
+    s->status = 0x00;
+    s->busy = 0;
+    s->newstart = 0;
+}
+
+static void s3c24xx_i2c_event(i2c_slave *i2c, enum i2c_event event)
+{
+    struct s3c24xx_i2c_state_s *s = (struct s3c24xx_i2c_state_s *) i2c;
+
+    if (!(s->status & (1 << 4)))
+        return;
+
+    switch (event) {
+    case I2C_START_RECV:
+
+    case I2C_START_SEND:
+        s->status |= 1 << 2;
+        s3c24xx_i2c_irq(s);
+        break;
+
+    case I2C_FINISH:
+        s->status &= ~6;
+        break;
+
+    case I2C_NACK:
+        s->status |= 1 << 0;
+        break;
+
+    default:
+        break;
+    }
+}
+
+static int s3c24xx_i2c_tx(i2c_slave *i2c, uint8_t data)
+{
+    struct s3c24xx_i2c_state_s *s = (struct s3c24xx_i2c_state_s *) i2c;
+    if (!(s->status & (1 << 4)))
+        return 1;
+
+    if ((s->status >> 6) == 0)
+        s->data = data;						/* TODO */
+
+    s->status &= ~(1 << 0);
+    s3c24xx_i2c_irq(s);
+
+    return !(s->control & (1 << 7));
+}
+
+static int s3c24xx_i2c_rx(i2c_slave *i2c)
+{
+    struct s3c24xx_i2c_state_s *s = (struct s3c24xx_i2c_state_s *) i2c;
+    if (!(s->status & (1 << 4)))
+        return 1;
+
+    if ((s->status >> 6) == 1) {
+        s->status &= ~(1 << 0);
+        s3c24xx_i2c_irq(s);
+        return s->data;
+    }
+
+    return 0x00;
+}
+
+static void s3c_master_work(void *opaque)
+{
+    struct s3c24xx_i2c_state_s *s = (struct s3c24xx_i2c_state_s *) opaque;
+    int start = 0, stop = 0, ack = 1;
+    
+    if (s->control & (1 << 4))				/* Interrupt pending */
+        return;
+    if ((s->status & 0x90) != 0x90)			/* Master */
+        return;
+    
+    stop = ~s->status & (1 << 5);
+    if (s->newstart && s->status & (1 << 5)) {		/* START */
+        s->busy = 1;
+        start = 1;
+    }
+    s->newstart = 0;
+    
+    if (!s->busy) {
+        return;
+    }
+
+    if (start) {
+        ack = !i2c_start_transfer(s->bus, s->data >> 1, (~s->status >> 6) & 1);
+    } else if (stop) {
+        i2c_end_transfer(s->bus);
+    } else if (s->status & (1 << 6)) { 
+        ack = !i2c_send(s->bus, s->data);
+    } else {
+        s->data = i2c_recv(s->bus);
+
+        if (!(s->control & (1 << 7)))			/* ACK */
+            i2c_nack(s->bus);
+    }
+
+    if (!(s->status & (1 << 5))) {
+        s->busy = 0;
+        return;
+    }
+
+    s->status &= ~1;
+    s->status |= !ack;
+
+    if (!ack) {
+        s->busy = 0;
+    }
+    s3c24xx_i2c_irq(s);
+}
+
+static uint32_t s3c24xx_i2c_read(void *opaque, target_phys_addr_t addr)
+{
+    struct s3c24xx_i2c_state_s *s = (struct s3c24xx_i2c_state_s *) opaque;
+    
+    switch (addr) {
+    case S3C_IICCON:
+        return s->control;
+
+    case S3C_IICSTAT:
+        return s->status & ~(1 << 5);			/* Busy signal */
+
+    case S3C_IICADD:
+        return s->addy;
+
+    case S3C_IICDS:
+        return s->data;
+
+    default:
+        printf("%s: Bad register 0x%lx\n", __func__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void s3c24xx_i2c_write(void *opaque, target_phys_addr_t addr,
+                              uint32_t value)
+{
+    struct s3c24xx_i2c_state_s *s = (struct s3c24xx_i2c_state_s *) opaque;
+    
+    switch (addr) {
+    case S3C_IICCON:
+        s->control = (s->control | 0xef) & value;
+        if (s->busy || ((s->control & (1<<4)) == 0))
+            s3c_master_work(s);
+        break;
+
+    case S3C_IICSTAT:
+        s->status &= 0x0f;
+        s->status |= value & 0xf0;
+        if (s->status & (1 << 5))
+            s->newstart = 1;
+        s3c_master_work(s);
+        break;
+
+    case S3C_IICADD:
+        s->addy = value & 0x7f;
+        i2c_set_slave_address(&s->slave, s->addy);
+        break;
+
+    case S3C_IICDS:
+        s->data = value & 0xff;
+        s->busy = 1;
+        break;
+
+    default:
+        printf("%s: Bad register 0x%lx\n", __func__, addr);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc *s3c24xx_i2c_readfn[] = {
+    s3c24xx_i2c_read,
+    s3c24xx_i2c_read,
+    s3c24xx_i2c_read,
+};
+
+static CPUWriteMemoryFunc *s3c24xx_i2c_writefn[] = {
+    s3c24xx_i2c_write,
+    s3c24xx_i2c_write,
+    s3c24xx_i2c_write,
+};
+
+static void s3c24xx_i2c_save(QEMUFile *f, void *opaque)
+{
+    struct s3c24xx_i2c_state_s *s = (struct s3c24xx_i2c_state_s *) opaque;
+    qemu_put_8s(f, &s->control);
+    qemu_put_8s(f, &s->status);
+    qemu_put_8s(f, &s->data);
+    qemu_put_8s(f, &s->addy);
+
+    qemu_put_be32(f, s->busy);
+    qemu_put_be32(f, s->newstart);
+
+    /* i2c_bus_save(f, s->bus); */
+    i2c_slave_save(f, &s->slave);
+}
+
+static int s3c24xx_i2c_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct s3c24xx_i2c_state_s *s = (struct s3c24xx_i2c_state_s *) opaque;
+    qemu_get_8s(f, &s->control);
+    qemu_get_8s(f, &s->status);
+    qemu_get_8s(f, &s->data);
+    qemu_get_8s(f, &s->addy);
+
+    s->busy = qemu_get_be32(f);
+    s->newstart = qemu_get_be32(f);
+
+    /* i2c_bus_load(f, s->bus); */
+    i2c_slave_load(f, &s->slave);
+    return 0;
+}
+
+void s3c24xx_iic_init(S3CState *soc, target_phys_addr_t base_addr)
+{
+    int iomemtype;
+    struct s3c24xx_i2c_state_s *s = qemu_mallocz(sizeof(struct s3c24xx_i2c_state_s));
+
+    s->base = base_addr;
+    s->irq = soc->irqs[27];
+    s->slave.event = s3c24xx_i2c_event;
+    s->slave.send = s3c24xx_i2c_tx;
+    s->slave.recv = s3c24xx_i2c_rx;
+    s->bus = i2c_init_bus();
+
+    s3c24xx_i2c_reset(s);
+
+    iomemtype = cpu_register_io_memory(0, s3c24xx_i2c_readfn,
+                                       s3c24xx_i2c_writefn, s);
+    cpu_register_physical_memory(base_addr, 0xffffff, iomemtype);
+
+    register_savevm("s3c24xx_i2c", 0, 0, s3c24xx_i2c_save, s3c24xx_i2c_load, s);
+
+    soc->iic = s;
+}
+
+i2c_bus *s3c24xx_i2c_bus(struct s3c24xx_i2c_state_s *s)
+{
+    return s->bus;
+}
+


-- 
Regards Vincent
http://www.kyllikki.org/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 11/16] S3C LCD display
  2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
                   ` (9 preceding siblings ...)
  2009-04-23 18:07 ` [Qemu-devel] [PATCH 10/16] S3C I2C peripheral Vincent Sanders
@ 2009-04-23 18:08 ` Vincent Sanders
  2009-04-23 18:09 ` [Qemu-devel] [PATCH 12/16] S3C NAND controller Vincent Sanders
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 29+ messages in thread
From: Vincent Sanders @ 2009-04-23 18:08 UTC (permalink / raw)
  To: qemu-devel

S3C LCD driver

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 s3c24xx_lcd.c      |  560 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 s3c24xx_template.h |  266 +++++++++++++++++++++++++
 2 files changed, 826 insertions(+)

diff -urN qemusvnclean/hw/s3c24xx_lcd.c qemusvnpatches/hw/s3c24xx_lcd.c
--- qemusvnclean/hw/s3c24xx_lcd.c	1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/s3c24xx_lcd.c	2009-04-23 17:11:46.000000000 +0100
@@ -0,0 +1,560 @@
+/*
+ * Samsung S3C24xx series LCD controller.
+ *
+ * Copyright (c) 2007 OpenMoko, Inc.
+ * Author: Andrzej Zaborowski <andrew@openedhand.com>
+ *
+ * This code is licenced under the GNU GPL v2.
+ */
+
+#include "hw.h"
+#include "console.h"
+#include "framebuffer.h"
+
+#include "s3c24xx.h"
+
+struct s3c24xx_lcd_state_s {
+    target_phys_addr_t base;
+    void *irq;
+    DisplayState *ds;
+    drawfn *line_fn;
+
+    uint32_t con[5];
+    uint32_t saddr[3];
+    uint32_t r;
+    uint32_t g;
+    uint16_t b;
+    uint32_t dithmode;
+    uint32_t tpal;
+    uint8_t intpnd;
+    uint8_t srcpnd;
+    uint8_t intmsk;
+    uint8_t lpcsel;
+
+    uint16_t raw_pal[0x100];
+
+    int width;
+    int height;
+    int bpp;
+    int enable;
+    int msb;
+    int frm565;
+    target_phys_addr_t fb;
+    uint32_t palette[0x100];
+    int invalidate;
+    int invalidatep;
+    int src_width;
+    int dest_width;
+    drawfn fn;
+};
+
+static void s3c24xx_lcd_update(struct s3c24xx_lcd_state_s *s)
+{
+    s->intpnd |= s->srcpnd & ~s->intmsk;
+    qemu_set_irq(s->irq, !!s->intpnd);
+}
+
+static void s3c24xx_lcd_reset(struct s3c24xx_lcd_state_s *s)
+{
+    s->enable = 0;
+    s->invalidate = 1;
+    s->invalidatep = 1;
+    s->width = -1;
+    s->height = -1;
+
+    s->con[0] = 0x00000000;
+    s->con[1] = 0x00000000;
+    s->con[2] = 0x00000000;
+    s->con[3] = 0x00000000;
+    s->con[4] = 0x00000000;
+    s->saddr[0] = 0x00000000;
+    s->saddr[1] = 0x00000000;
+    s->saddr[2] = 0x00000000;
+    s->r = 0x00000000;
+    s->g = 0x00000000;
+    s->b = 0x0000;
+    s->dithmode = 0x00000;
+    s->tpal = 0x00000000;
+    s->intpnd = 0;
+    s->srcpnd = 0;
+    s->intmsk = 3;
+    s->lpcsel = 4;
+    s3c24xx_lcd_update(s);
+}
+
+#define S3C24XX_LCDCON1	0x00	/* LCD Control register 1 */
+#define S3C24XX_LCDCON2	0x04	/* LCD Control register 2 */
+#define S3C24XX_LCDCON3	0x08	/* LCD Control register 3 */
+#define S3C24XX_LCDCON4	0x0c	/* LCD Control register 4 */
+#define S3C24XX_LCDCON5	0x10	/* LCD Control register 5 */
+#define S3C24XX_LCDSADDR1 0x14	/* Framebuffer Start Address 1 register */
+#define S3C24XX_LCDSADDR2 0x18	/* Framebuffer Start Address 2 register */
+#define S3C24XX_LCDSADDR3 0x1c	/* Framebuffer Start Address 3 register */
+#define S3C24XX_REDLUT 0x20	/* Red Lookup Table register */
+#define S3C24XX_GREENLUT 0x24	/* Green Lookup Table register */
+#define S3C24XX_BLUELUT	0x28	/* Blue Lookup Table register */
+#define S3C24XX_DITHMODE 0x4c	/* Dithering Mode register */
+#define S3C24XX_TPAL 0x50	/* Temporary Palette register */
+#define S3C24XX_LCDINTPND 0x54	/* LCD Interrupt Pending register */
+#define S3C24XX_LCDSRCPND 0x58	/* LCD Interrupt Source Pending register */
+#define S3C24XX_LCDINTMSK 0x5c	/* LCD Interrupt Mask register */
+#define S3C24XX_LPCSEL 0x60	/* LPC3600 Control register */
+
+#define S3C24XX_PALETTE	0x400	/* Palette IO start offset */
+#define S3C24XX_PALETTEEND 0x7fc	/* Palette IO end offset */
+
+static uint32_t s3c24xx_lcd_read(void *opaque, target_phys_addr_t addr)
+{
+    struct s3c24xx_lcd_state_s *s = (struct s3c24xx_lcd_state_s *) opaque;
+
+    switch (addr) {
+    case S3C24XX_LCDCON1:
+        return s->con[0];		/* XXX Return random LINECNT? */
+    case S3C24XX_LCDCON2:
+        return s->con[1];
+    case S3C24XX_LCDCON3:
+        return s->con[2];
+    case S3C24XX_LCDCON4:
+        return s->con[3];
+    case S3C24XX_LCDCON5:
+        return s->con[4];		/* XXX Return random STATUS? */
+    case S3C24XX_LCDSADDR1:
+        return s->saddr[0];
+    case S3C24XX_LCDSADDR2:
+        return s->saddr[1];
+    case S3C24XX_LCDSADDR3:
+        return s->saddr[2];
+    case S3C24XX_REDLUT:
+        return s->r;
+    case S3C24XX_GREENLUT:
+        return s->g;
+    case S3C24XX_BLUELUT:
+        return s->b;
+    case S3C24XX_DITHMODE:
+        return s->dithmode;
+    case S3C24XX_TPAL:
+        return s->tpal;
+    case S3C24XX_LCDINTPND:
+        return s->intpnd;
+    case S3C24XX_LCDSRCPND:
+        return s->srcpnd;
+    case S3C24XX_LCDINTMSK:
+        return s->intmsk;
+    case S3C24XX_LPCSEL:
+        return s->lpcsel;
+    case S3C24XX_PALETTE ... S3C24XX_PALETTEEND:
+        /* XXX assuming 16bit access */
+        return s->raw_pal[(addr - S3C24XX_PALETTE) >> 2];
+    default:
+        printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void s3c24xx_lcd_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct s3c24xx_lcd_state_s *s = (struct s3c24xx_lcd_state_s *) opaque;
+
+    switch (addr) {
+    case S3C24XX_LCDCON1:
+        s->con[0] = value & 0x0003ffff;
+        s->enable = value & 1;
+        s->bpp = (value >> 1) & 0xf;
+        s->invalidate = 1;
+        s->invalidatep = 1;
+        break;
+    case S3C24XX_LCDCON2:
+        s->con[1] = value;
+        s->invalidate = 1;
+        break;
+    case S3C24XX_LCDCON3:
+        s->con[2] = value;
+        s->invalidate = 1;
+        break;
+    case S3C24XX_LCDCON4:
+        s->con[3] = value & 0xffff;
+        break;
+    case S3C24XX_LCDCON5:
+        s->con[4] = value & 0x1fff;
+        s->frm565 = (value >> 11) & 1;
+        s->msb = (value >> 12) & 1;
+        s->invalidatep = 1;
+        s->invalidate = 1;
+        break;
+    case S3C24XX_LCDSADDR1:
+        s->saddr[0] = value;
+        s->fb = ((s->saddr[0] << 1) & 0x7ffffffe);
+        s->invalidate = 1;
+        break;
+    case S3C24XX_LCDSADDR2:
+        s->saddr[1] = value;
+        s->invalidate = 1;
+        break;
+    case S3C24XX_LCDSADDR3:
+        s->saddr[2] = value;
+        s->invalidate = 1;
+        break;
+    case S3C24XX_REDLUT:
+        s->r = value;
+        s->invalidatep = 1;
+        s->invalidate = 1;
+        break;
+    case S3C24XX_GREENLUT:
+        s->g = value;
+        s->invalidatep = 1;
+        s->invalidate = 1;
+        break;
+    case S3C24XX_BLUELUT:
+        s->b = value;
+        s->invalidatep = 1;
+        s->invalidate = 1;
+        break;
+    case S3C24XX_DITHMODE:
+        s->dithmode = value;
+        break;
+    case S3C24XX_TPAL:
+        s->tpal = value;
+        s->invalidatep = 1;
+        s->invalidate = 1;
+        break;
+    case S3C24XX_LCDINTPND:
+        s->intpnd = value & 3;
+        break;
+    case S3C24XX_LCDSRCPND:
+        s->srcpnd = value & 3;
+        break;
+    case S3C24XX_LCDINTMSK:
+        s->intmsk = value & 7;
+        s3c24xx_lcd_update(s);
+        break;
+    case S3C24XX_LPCSEL:
+        s->lpcsel = (value & 3) | 4;
+        if (value & 1)
+            printf("%s: attempt to enable LPC3600\n", __FUNCTION__);
+        break;
+    case S3C24XX_PALETTE ... S3C24XX_PALETTEEND:
+        /* XXX assuming 16bit access */
+        s->raw_pal[(addr - S3C24XX_PALETTE) >> 2] = value;
+        break;
+    default:
+        printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);
+    }
+}
+
+static CPUReadMemoryFunc *s3c24xx_lcd_readfn[] = {
+    s3c24xx_lcd_read,
+    s3c24xx_lcd_read,
+    s3c24xx_lcd_read,
+};
+
+static CPUWriteMemoryFunc *s3c24xx_lcd_writefn[] = {
+    s3c24xx_lcd_write,
+    s3c24xx_lcd_write,
+    s3c24xx_lcd_write,
+};
+
+static inline void s3c24xx_lcd_resize(struct s3c24xx_lcd_state_s *s)
+{
+    int new_width, new_height;
+    new_height = ((s->con[1] >> 14) & 0x3ff) + 1;
+    new_width = ((s->con[2] >> 8) & 0x7ff) + 1;
+    if (s->width != new_width || s->height != new_height) {
+        s->width = new_width;
+        s->height = new_height;
+        qemu_console_resize(s->ds, s->width, s->height);
+        s->invalidate = 1;
+    }
+}
+
+static inline
+uint32_t s3c24xx_rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
+{
+    return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
+}
+
+static inline
+uint32_t s3c24xx_rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
+{
+    return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
+}
+
+static inline
+uint32_t s3c24xx_rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
+{
+    return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
+}
+
+static inline
+uint32_t s3c24xx_rgb_to_pixel24(unsigned int r, unsigned int g, unsigned b)
+{
+    return (r << 16) | (g << 8) | b;
+}
+
+static inline
+uint32_t s3c24xx_rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
+{
+    return (r << 16) | (g << 8) | b;
+}
+
+static inline uint32_t s3c24xx_rgb(struct s3c24xx_lcd_state_s *s,
+                unsigned int r, unsigned int g, unsigned b)
+{
+    switch (ds_get_bits_per_pixel(s->ds)) {
+    case 8:
+        return s3c24xx_rgb_to_pixel32(r << 2, g << 2, b << 2);
+    case 15:
+        return s3c24xx_rgb_to_pixel15(r << 2, g << 2, b << 2);
+    case 16:
+        return s3c24xx_rgb_to_pixel16(r << 2, g << 2, b << 2);
+    case 24:
+        return s3c24xx_rgb_to_pixel24(r << 2, g << 2, b << 2);
+    case 32:
+        return s3c24xx_rgb_to_pixel32(r << 2, g << 2, b << 2);
+    default:
+        fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__);
+        exit(1);
+    }
+}
+
+static void s3c24xx_lcd_palette_load(struct s3c24xx_lcd_state_s *s)
+{
+    int i, n;
+    switch (s->bpp) {
+    case 0:
+    case 8:
+        n = 2;
+        s->src_width = s->width >> 3;
+        s->fn = s->line_fn[0];
+        break;
+    case 1:
+    case 9:
+        n = 4;
+        s->src_width = s->width >> 2;
+        s->fn = s->line_fn[1];
+        break;
+    case 2:
+    case 10:
+        n = 16;
+        s->src_width = s->width >> 1;
+        s->fn = s->line_fn[2];
+        break;
+    case 3:
+    case 11:
+        n = 256;
+        s->src_width = s->width >> 0;
+        s->fn = s->line_fn[3];
+        break;
+    case 6:
+        s->src_width = (s->width * 3) >> 1;
+        s->fn = s->line_fn[4];
+        return;
+    case 12:
+        s->src_width = s->width << 1;
+        if (s->frm565)
+            s->fn = s->line_fn[5];
+        else
+            s->fn = s->line_fn[6];
+        return;
+    case 13:
+        s->src_width = s->width << 2;
+        s->fn = s->line_fn[7];
+        return;
+    default:
+        return;
+    }
+    if (s->bpp & 8) {
+        for (i = 0; i < n; i ++)
+            if (s->frm565)
+                s->palette[i] = s3c24xx_rgb(s,
+                        (s->raw_pal[i] >> 10) & 0x3e,
+                        (s->raw_pal[i] >> 5) & 0x3f,
+                        (s->raw_pal[i] << 1) & 0x3e);
+            else
+                s->palette[i] = s3c24xx_rgb(s,
+                        ((s->raw_pal[i] >> 10) & 0x3e) | (s->raw_pal[i] & 1),
+                        ((s->raw_pal[i] >> 6) & 0x3e) | (s->raw_pal[i] & 1),
+                        s->raw_pal[i] & 0x3f);
+    } else {
+        for (i = 0; i < n; i ++)
+            if (n < 256)
+                s->palette[i] = s3c24xx_rgb(s,
+                        ((s->r >> (i * 4)) & 0xf) << 2,
+                        ((s->g >> (i * 4)) & 0xf) << 2,
+                        ((s->b >> (i * 4)) & 0xf) << 2);
+            else
+                s->palette[i] = s3c24xx_rgb(s,
+                        ((s->r >> (((i >> 5) & 7) * 4)) & 0xf) << 2,
+                        ((s->g >> (((i >> 2) & 7) * 4)) & 0xf) << 2,
+                        ((s->b >> ((i & 3) * 4)) & 0xf) << 2);
+    }
+}
+
+static void s3c24xx_update_display(void *opaque)
+{
+    struct s3c24xx_lcd_state_s *s = (struct s3c24xx_lcd_state_s *) opaque;
+    int src_width, dest_width, miny = 0, maxy = 0;
+    target_phys_addr_t addr;
+
+    addr = s->fb;
+
+    if (!s->enable || !s->dest_width)
+        return;
+
+    s3c24xx_lcd_resize(s);
+
+    if (s->invalidatep) {
+        s3c24xx_lcd_palette_load(s);
+        s->invalidatep = 0;
+    }
+
+    src_width = s->src_width;
+    dest_width = s->width * s->dest_width;
+
+    framebuffer_update_display(s->ds,
+                               addr, s->width, s->height,
+                               src_width, dest_width, s->dest_width,
+                               s->invalidate,
+                               s->fn, s->palette, &miny, &maxy);
+
+
+    s->srcpnd |= (1 << 1);			/* INT_FrSyn */
+    s3c24xx_lcd_update(s);
+    dpy_update(s->ds, 0, miny, s->width, maxy);
+}
+
+static void s3c24xx_invalidate_display(void *opaque)
+{
+    struct s3c24xx_lcd_state_s *s = (struct s3c24xx_lcd_state_s *) opaque;
+    s->invalidate = 1;
+}
+
+static void s3c24xx_screen_dump(void *opaque, const char *filename)
+{
+    /* TODO */
+}
+
+#define BITS 8
+#include "s3c24xx_template.h"
+#define BITS 15
+#include "s3c24xx_template.h"
+#define BITS 16
+#include "s3c24xx_template.h"
+#define BITS 24
+#include "s3c24xx_template.h"
+#define BITS 32
+#include "s3c24xx_template.h"
+
+static void s3c24xx_lcd_save(QEMUFile *f, void *opaque)
+{
+    struct s3c24xx_lcd_state_s *s = (struct s3c24xx_lcd_state_s *) opaque;
+    int i;
+    for (i = 0; i < 5; i ++)
+        qemu_put_be32s(f, &s->con[i]);
+    for (i = 0; i < 3; i ++)
+        qemu_put_be32s(f, &s->saddr[i]);
+    qemu_put_be32s(f, &s->r);
+    qemu_put_be32s(f, &s->g);
+    qemu_put_be16s(f, &s->b);
+    qemu_put_be32s(f, &s->dithmode);
+    qemu_put_be32s(f, &s->tpal);
+    qemu_put_8s(f, &s->intpnd);
+    qemu_put_8s(f, &s->srcpnd);
+    qemu_put_8s(f, &s->intmsk);
+    qemu_put_8s(f, &s->lpcsel);
+    for (i = 0; i < 0x100; i ++)
+        qemu_put_be16s(f, &s->raw_pal[i]);
+}
+
+static int s3c24xx_lcd_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct s3c24xx_lcd_state_s *s = (struct s3c24xx_lcd_state_s *) opaque;
+    int i;
+    for (i = 0; i < 5; i ++)
+        qemu_get_be32s(f, &s->con[i]);
+    for (i = 0; i < 3; i ++)
+        qemu_get_be32s(f, &s->saddr[i]);
+    qemu_get_be32s(f, &s->r);
+    qemu_get_be32s(f, &s->g);
+    qemu_get_be16s(f, &s->b);
+    qemu_get_be32s(f, &s->dithmode);
+    qemu_get_be32s(f, &s->tpal);
+    qemu_get_8s(f, &s->intpnd);
+    qemu_get_8s(f, &s->srcpnd);
+    qemu_get_8s(f, &s->intmsk);
+    qemu_get_8s(f, &s->lpcsel);
+
+    s->invalidate = 1;
+    s->invalidatep = 1;
+    s->width = -1;
+    s->height = -1;
+    s->bpp = (s->con[0] >> 1) & 0xf;
+    s->enable = s->con[0] & 1;
+    s->msb = (s->con[4] >> 12) & 1;
+    s->frm565 = (s->con[4] >> 11) & 1;
+    s->fb = ((s->saddr[0] << 1) & 0x7ffffffe);
+
+    for (i = 0; i < 0x100; i ++)
+        qemu_get_be16s(f, &s->raw_pal[i]);
+
+    return 0;
+}
+
+struct s3c24xx_lcd_state_s *s3c24xx_lcd_init(target_phys_addr_t base, qemu_irq irq)
+{
+    int iomemtype;
+    struct s3c24xx_lcd_state_s *s = (struct s3c24xx_lcd_state_s *)
+            qemu_mallocz(sizeof(struct s3c24xx_lcd_state_s));
+
+    s->base = base;
+    s->irq = irq;
+
+    s3c24xx_lcd_reset(s);
+
+    s->ds = graphic_console_init(s3c24xx_update_display,
+                                      s3c24xx_invalidate_display, 
+                                      s3c24xx_screen_dump, NULL, s);
+
+    iomemtype = cpu_register_io_memory(0, s3c24xx_lcd_readfn,
+                    s3c24xx_lcd_writefn, s);
+    cpu_register_physical_memory(s->base, 0xffffff, iomemtype);
+
+    register_savevm("s3c24xx_lcd", 0, 0, s3c24xx_lcd_save, s3c24xx_lcd_load, s);
+
+    switch (ds_get_bits_per_pixel(s->ds)) {
+    case 0:
+        s->dest_width = 0;
+        break;
+
+    case 8:
+        s->line_fn = s3c24xx_draw_fn_8;
+        s->dest_width = 1;
+        break;
+
+    case 15:
+        s->line_fn = s3c24xx_draw_fn_15;
+        s->dest_width = 2;
+        break;
+
+    case 16:
+        s->line_fn = s3c24xx_draw_fn_16;
+        s->dest_width = 2;
+        break;
+
+    case 24:
+        s->line_fn = s3c24xx_draw_fn_24;
+        s->dest_width = 3;
+        break;
+
+    case 32:
+        s->line_fn = s3c24xx_draw_fn_32;
+        s->dest_width = 4;
+        break;
+
+    default:
+        fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__);
+        exit(1);
+    }
+    return s;
+}
diff -urN qemusvnclean/hw/s3c24xx_template.h qemusvnpatches/hw/s3c24xx_template.h
--- qemusvnclean/hw/s3c24xx_template.h	1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/s3c24xx_template.h	2009-04-23 17:11:52.000000000 +0100
@@ -0,0 +1,266 @@
+/*
+ * Samsung S3C2410A LCD controller emulation.
+ *
+ * Copyright (c) 2007 OpenMoko, Inc.
+ * Author: Andrzej Zaborowski <andrew@openedhand.com>
+ *
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Framebuffer format conversion routines.
+ */
+
+# define SKIP_PIXEL(to)		to += deststep
+#if BITS == 8
+# define COPY_PIXEL(to, from)	*to = from; SKIP_PIXEL(to)
+#elif BITS == 15 || BITS == 16
+# define COPY_PIXEL(to, from)	*(uint16_t *) to = from; SKIP_PIXEL(to)
+#elif BITS == 24 
+# define COPY_PIXEL(to, from)	\
+	*(uint16_t *) to = from; *(to + 2) = (from) >> 16; SKIP_PIXEL(to)
+#elif BITS == 32
+# define COPY_PIXEL(to, from)	*(uint32_t *) to = from; SKIP_PIXEL(to)
+#else
+# error unknown bit depth
+#endif
+
+#ifdef WORDS_BIGENDIAN
+# define SWAP_WORDS	1
+#endif
+
+#define FN_2(x)		FN(x + 1) FN(x)
+#define FN_4(x)		FN_2(x + 2) FN_2(x)
+#define FN_8(x)		FN_4(x + 4) FN_4(x)
+
+static void glue(s3c24xx_draw_line1_, BITS)(void *opaque,
+                uint8_t *dest, const uint8_t *src, int width, int deststep)
+{
+    uint32_t *palette = opaque;
+    uint32_t data;
+    while (width > 0) {
+        data = *(uint32_t *) src;
+#define FN(x)		COPY_PIXEL(dest, palette[(data >> (x)) & 1]);
+#ifdef SWAP_WORDS
+        FN_8(24)
+        FN_8(16)
+        FN_8(8)
+        FN_8(0)
+#else
+        FN_8(0)
+        FN_8(8)
+        FN_8(16)
+        FN_8(24)
+#endif
+#undef FN
+        width -= 32;
+        src += 4;
+    }
+}
+
+static void glue(s3c24xx_draw_line2_, BITS)(void *opaque,
+                uint8_t *dest, const uint8_t *src, int width, int deststep)
+{
+    uint32_t *palette = opaque;
+    uint32_t data;
+    while (width > 0) {
+        data = *(uint32_t *) src;
+#define FN(x)		COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]);
+#ifdef SWAP_WORDS
+        FN_4(12)
+        FN_4(8)
+        FN_4(4)
+        FN_4(0)
+#else
+        FN_4(0)
+        FN_4(4)
+        FN_4(8)
+        FN_4(12)
+#endif
+#undef FN
+        width -= 16;
+        src += 4;
+    }
+}
+
+static void glue(s3c24xx_draw_line4_, BITS)(void *opaque,
+                uint8_t *dest, const uint8_t *src, int width, int deststep)
+{
+    uint32_t *palette = opaque;
+    uint32_t data;
+    while (width > 0) {
+        data = *(uint32_t *) src;
+#define FN(x)		COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]);
+#ifdef SWAP_WORDS
+        FN_2(6)
+        FN_2(4)
+        FN_2(2)
+        FN_2(0)
+#else
+        FN_2(0)
+        FN_2(2)
+        FN_2(4)
+        FN_2(6)
+#endif
+#undef FN
+        width -= 8;
+        src += 4;
+    }
+}
+
+static void glue(s3c24xx_draw_line8_, BITS)(void *opaque,
+                uint8_t *dest, const uint8_t *src, int width, int deststep)
+{
+    uint32_t *palette = opaque;
+    uint32_t data;
+    while (width > 0) {
+        data = *(uint32_t *) src;
+#define FN(x)		COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]);
+#ifdef SWAP_WORDS
+        FN(24)
+        FN(16)
+        FN(8)
+        FN(0)
+#else
+        FN(0)
+        FN(8)
+        FN(16)
+        FN(24)
+#endif
+#undef FN
+        width -= 4;
+        src += 4;
+    }
+}
+
+static void glue(s3c24xx_draw_line16a_, BITS)(void *opaque,
+                uint8_t *dest, const uint8_t *src, int width, int deststep)
+{
+    uint32_t data;
+    unsigned int r, g, b;
+    while (width > 0) {
+        data = *(uint32_t *) src;
+#ifdef SWAP_WORDS
+        data = bswap32(data);
+#endif
+        b = (data & 0x1f) << 3;
+        data >>= 5;
+        g = (data & 0x3f) << 2;
+        data >>= 6;
+        r = (data & 0x1f) << 3;
+        data >>= 5;
+        COPY_PIXEL(dest, glue(s3c24xx_rgb_to_pixel, BITS)(r, g, b));
+        b = (data & 0x1f) << 3;
+        data >>= 5;
+        g = (data & 0x3f) << 2;
+        data >>= 6;
+        r = (data & 0x1f) << 3;
+        COPY_PIXEL(dest, glue(s3c24xx_rgb_to_pixel, BITS)(r, g, b));
+        width -= 2;
+        src += 4;
+    }
+}
+
+static void glue(s3c24xx_draw_line16b_, BITS)(void *opaque,
+                uint8_t *dest, const uint8_t *src, int width, int deststep)
+{
+    uint32_t data;
+    unsigned int r, g, b;
+    while (width > 0) {
+        data = *(uint32_t *) src;
+#ifdef SWAP_WORDS
+        data = bswap32(data);
+#endif
+        b = (data & 0x1f) << 3;
+        data >>= 5;
+        g = (data & 0x1f) << 3;
+        data >>= 5;
+        r = (data & 0x3f) << 2;
+        data >>= 5;
+        COPY_PIXEL(dest, glue(s3c24xx_rgb_to_pixel, BITS)(r, g, b));
+        b = (data & 0x1f) << 3;
+        data >>= 5;
+        g = (data & 0x1f) << 3;
+        data >>= 5;
+        r = (data & 0x3f) << 2;
+        COPY_PIXEL(dest, glue(s3c24xx_rgb_to_pixel, BITS)(r, g, b));
+        width -= 2;
+        src += 4;
+    }
+}
+
+static void glue(s3c24xx_draw_line12_, BITS)(void *opaque,
+                uint8_t *dest, const uint8_t *src, int width, int deststep)
+{
+    uint32_t data;
+    unsigned int r, g, b;
+    while (width > 0) {
+        data = *(uint32_t *) src;
+        src += 3;
+#ifdef SWAP_WORDS
+        data = bswap32(data);
+#endif
+        /* XXX should use (x & 0xf) << 4) | (x & 0xf) for natural
+         * colours.  Otherwise the image may be a bit darkened.  */
+        b = (data & 0xf00) >> 4;
+        g = (data & 0xf0) << 0;
+        r = (data & 0xf) << 4;
+        data >>= 12;
+        COPY_PIXEL(dest, glue(s3c24xx_rgb_to_pixel, BITS)(r, g, b));
+        b = (data & 0xf00) >> 4;
+        g = (data & 0xf0) << 0;
+        r = (data & 0xf) << 4;
+        data >>= 12;
+        COPY_PIXEL(dest, glue(s3c24xx_rgb_to_pixel, BITS)(r, g, b));
+        b = (data & 0xf00) >> 4;
+        g = (data & 0xf0) << 0;
+        r = (data & 0xf) << 4;
+        data >>= 12;
+        COPY_PIXEL(dest, glue(s3c24xx_rgb_to_pixel, BITS)(r, g, b));
+        b = (data & 0xf00) >> 4;
+        g = (data & 0xf0) << 0;
+        r = (data & 0xf) << 4;
+        data >>= 12;
+        COPY_PIXEL(dest, glue(s3c24xx_rgb_to_pixel, BITS)(r, g, b));
+        width -= 4;
+    }
+}
+
+static void glue(s3c24xx_draw_line24_, BITS)(void *opaque,
+                uint8_t *dest, const uint8_t *src, int width, int deststep)
+{
+    uint32_t data;
+    unsigned int r, g, b;
+    while (width > 0) {
+        data = *(uint32_t *) src;
+#ifdef SWAP_WORDS
+        data = bswap32(data);
+#endif
+        b = data & 0xff;
+        data >>= 8;
+        g = data & 0xff;
+        data >>= 8;
+        r = data & 0xff;
+        COPY_PIXEL(dest, glue(s3c24xx_rgb_to_pixel, BITS)(r, g, b));
+        width -= 1;
+        src += 4;
+    }
+}
+
+static drawfn glue(s3c24xx_draw_fn_, BITS)[] =
+{
+    glue(s3c24xx_draw_line1_, BITS),
+    glue(s3c24xx_draw_line2_, BITS),
+    glue(s3c24xx_draw_line4_, BITS),
+    glue(s3c24xx_draw_line8_, BITS),
+    glue(s3c24xx_draw_line12_, BITS),
+    glue(s3c24xx_draw_line16a_, BITS),
+    glue(s3c24xx_draw_line16b_, BITS),
+    glue(s3c24xx_draw_line24_, BITS),
+};
+
+#undef BITS
+#undef COPY_PIXEL
+#undef SKIP_PIXEL
+
+#ifdef SWAP_WORDS
+# undef SWAP_WORDS
+#endif

-- 
Regards Vincent
http://www.kyllikki.org/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 12/16] S3C NAND controller
  2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
                   ` (10 preceding siblings ...)
  2009-04-23 18:08 ` [Qemu-devel] [PATCH 11/16] S3C LCD display Vincent Sanders
@ 2009-04-23 18:09 ` Vincent Sanders
  2009-04-23 18:11 ` [Qemu-devel] [PATCH 13/16] S3C2410 SOC implementation Vincent Sanders
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 29+ messages in thread
From: Vincent Sanders @ 2009-04-23 18:09 UTC (permalink / raw)
  To: qemu-devel

S3C NAND Driver

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 s3c24xx_nand.c |  136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 136 insertions(+)


diff -urN qemusvnclean/hw/s3c24xx_nand.c qemusvnpatches/hw/s3c24xx_nand.c
--- qemusvnclean/hw/s3c24xx_nand.c	1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/s3c24xx_nand.c	2009-04-23 17:13:06.000000000 +0100
@@ -0,0 +1,136 @@
+/* hw/s3c24xx_nand.c
+ *
+ * Samsung S3C24XX NAND emulation
+ *
+ * Copyright 2006, 2008 Ben Dooks, Daniel Silverstone and Vincent Sanders
+ *
+ * This file is under the terms of the GNU General Public
+ * License Version 2
+ */
+
+#include "hw.h"
+#include "flash.h"
+
+#include "s3c24xx.h"
+
+#define NFCONF 0
+#define NFCMD 1
+#define NFADDR 2
+#define NFDATA 3
+#define NFSTAT 4
+#define NFECC 5
+
+#define NFCE ((soc->nand_reg[NFCONF] & 1<<11) != 0)
+
+static void
+s3c24xx_nand_write_f(void *opaque, target_phys_addr_t addr,
+                     uint32_t value)
+{
+    S3CState *soc = (S3CState *)opaque;
+    int reg = (addr & 0x1f) >> 2;
+
+    if ((reg != NFCONF) && ((soc->nand_reg[NFCONF] & 1<<15) == 0)) {
+        return; /* Ignore the write, the nand is not enabled */
+    }
+
+    switch (reg) {
+    case NFCONF:
+        soc->nand_reg[reg] = value;
+        if (soc->nand_chip != NULL)
+            nand_setpins(soc->nand_chip, 0, 0, NFCE, 1, 0);
+        break;
+
+    case NFCMD:
+        soc->nand_reg[reg] = value;
+        if (soc->nand_chip != NULL) {
+            nand_setpins(soc->nand_chip, 1, 0, NFCE, 1, 0);
+            nand_setio(soc->nand_chip, value);
+        }
+        break;
+
+    case NFADDR:
+        soc->nand_reg[reg] = value;
+        if (soc->nand_chip != NULL) {
+            nand_setpins(soc->nand_chip, 0, 1, NFCE, 1, 0);
+            nand_setio(soc->nand_chip, value);
+        }
+        break;
+
+    case NFDATA:
+        soc->nand_reg[reg] = value;
+        if (soc->nand_chip != NULL) {
+            nand_setpins(soc->nand_chip, 0, 0, NFCE, 1, 0);
+            nand_setio(soc->nand_chip, value);
+        }
+        break;
+
+    default:
+        /* Do nothing because the other registers are read only */
+        break;
+    }
+}
+
+static uint32_t
+s3c24xx_nand_read_f(void *opaque, target_phys_addr_t addr)
+{
+    S3CState *soc = (S3CState *)opaque;
+    int reg = (addr & 0x1f) >> 2;
+    uint32_t ret = soc->nand_reg[reg];
+
+    switch (reg) {
+    case NFDATA:
+        if (soc->nand_chip != NULL) {
+            nand_setpins(soc->nand_chip, 0, 0, NFCE, 1, 0);
+            ret = soc->nand_reg[reg] = nand_getio(soc->nand_chip);
+        } else {
+            ret = soc->nand_reg[ret] = 0;
+        }
+        break;
+
+    case NFSTAT:
+        if (soc->nand_chip != NULL) {
+            nand_getpins(soc->nand_chip, (int *)&ret);
+            soc->nand_reg[reg] = ret;
+        } else {
+            ret = soc->nand_reg[ret] = 0;
+        }
+
+    default:
+        /* The rest read-back what was written to them */
+        break;
+    }
+
+    return ret;
+}
+
+static CPUReadMemoryFunc *s3c24xx_nand_read[] = {
+    &s3c24xx_nand_read_f,
+    &s3c24xx_nand_read_f,
+    &s3c24xx_nand_read_f,
+};
+
+static CPUWriteMemoryFunc *s3c24xx_nand_write[] = {
+    &s3c24xx_nand_write_f,
+    &s3c24xx_nand_write_f,
+    &s3c24xx_nand_write_f,
+};
+
+void
+s3c24xx_nand_init(S3CState *soc, target_phys_addr_t base_addr)
+{
+    int tag = cpu_register_io_memory(0, s3c24xx_nand_read, s3c24xx_nand_write, soc);
+    cpu_register_physical_memory(base_addr, 0x40, tag);
+
+    memset(soc->nand_reg, 0, sizeof(uint32_t) * 5);
+}
+
+void
+s3c24xx_nand_attach(S3CState *soc, struct nand_flash_s *nand_chip)
+{
+    if (soc->nand_chip != NULL) {
+        /* Detach current nand device */
+        /* no cmd, no addr, not enabled, write protected, no 'gnd' */
+        nand_setpins(soc->nand_chip, 0, 0, 1, 0, 0); 
+    }
+    soc->nand_chip = nand_chip;
+}

-- 
Regards Vincent
http://www.kyllikki.org/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 13/16] S3C2410 SOC implementation
  2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
                   ` (11 preceding siblings ...)
  2009-04-23 18:09 ` [Qemu-devel] [PATCH 12/16] S3C NAND controller Vincent Sanders
@ 2009-04-23 18:11 ` Vincent Sanders
  2009-04-23 18:14 ` [Qemu-devel] [PATCH 14/16] S3C2440 SOC impementation Vincent Sanders
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 29+ messages in thread
From: Vincent Sanders @ 2009-04-23 18:11 UTC (permalink / raw)
  To: qemu-devel

S3C2410 SOC implementation using generic S3C peripheral blocks.

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 s3c2410x.c |  118 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 s3c2410x.h |   30 +++++++++++++++
 2 files changed, 148 insertions(+)

diff -urN qemusvnclean/hw/s3c2410x.c qemusvnpatches/hw/s3c2410x.c
--- qemusvnclean/hw/s3c2410x.c	1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/s3c2410x.c	2009-04-23 17:17:53.000000000 +0100
@@ -0,0 +1,118 @@
+/* hw/s3c2410x.c
+ *
+ * Samsung S3C2410X emulation
+ *
+ * Copyright 2006, 2007 Daniel Silverstone and Vincent Sanders
+ *
+ * This file is under the terms of the GNU General Public
+ * License Version 2
+ */
+
+#include "hw.h"
+
+#include "s3c2410x.h"
+
+/* We use the PXA style OHCI USB mapping */
+#include "pxa.h"
+
+/* S3C2410 SoC IDs */
+#define CPU_S3C2410X_IDENT_S3C2410X 0x32410000
+#define CPU_S3C2410X_IDENT_S3C2410A 0x32410002
+
+/* Integrated SOC peripherals */
+
+/* SRAM */
+#define CPU_S3C2410X_SRAM_BASE (0x40000000)
+
+/* Memory control */
+#define CPU_S3C2410X_MEMC_BASE (0x48000000)
+
+/* USB controller */
+#define CPU_S3C2410X_OHCI (0x49000000)
+
+/* Interrupt controller */
+#define CPU_S3C2410X_IRQ_BASE (0x4A000000)
+
+/* Clock control */
+#define CPU_S3C2410X_CLKCON_BASE (0x4C000000)
+
+/* LCD */
+#define CPU_S3C2410X_LCD_BASE (0x4D000000)
+
+/* NAND */
+#define CPU_S3C2410X_NAND_BASE (0x4E000000)
+
+/* serial port base */
+#define CPU_S3C2410X_SERIAL_BASE (0x50000000)
+
+/* Timers */
+#define CPU_S3C2410X_TIMERS_BASE (0x51000000)
+
+/* Watchdog */
+#define CPU_S3C2410X_WDOG_BASE (0x53000000)
+
+/* IIC */
+#define CPU_S3C2410X_IIC_BASE (0x54000000)
+
+/* GPIO */
+#define CPU_S3C2410X_GPIO_BASE (0x56000000)
+
+/* Real time clock */
+#define CPU_S3C2410X_RTC_BASE (0x57000000)
+
+/* Initialise a Samsung S3C2410X SOC ARM core and internal peripherals. */
+S3CState *
+s3c2410x_init(int sdram_size)
+{
+    S3CState *s = (S3CState *)qemu_mallocz(sizeof(S3CState));
+
+    /* Prepare the ARM 920T core */
+    s->cpu_env = cpu_init("arm920t");
+
+    /* S3C2410X SDRAM memory is always at the same physical location */
+    cpu_register_physical_memory(CPU_S3C2410X_RAM, 
+                                 ram_size, 
+                                 qemu_ram_alloc(sdram_size) | IO_MEM_RAM);
+
+    /* Memory controller */
+    s3c24xx_memc_init(s, CPU_S3C2410X_MEMC_BASE);
+
+    /* S3C2410X SRAM */
+    cpu_register_physical_memory(CPU_S3C2410X_SRAM_BASE, 
+                                 4096, 
+                                 qemu_ram_alloc(4096) | IO_MEM_RAM);
+
+    /* Add the interrupt controller */
+    s->irqs = s3c24xx_irq_init(s, CPU_S3C2410X_IRQ_BASE);
+
+    /* clock and power control */
+    s3c24xx_clkcon_init(s, CPU_S3C2410X_CLKCON_BASE);
+
+    /* PWM control used for timers */
+    s3c24xx_timers_init(s, CPU_S3C2410X_TIMERS_BASE);
+
+    /* And some GPIO */
+    s3c24xx_gpio_init(s, CPU_S3C2410X_GPIO_BASE, CPU_S3C2410X_IDENT_S3C2410A); 
+
+    /* Serial ports */
+    s3c24xx_serial_init(s, 0, CPU_S3C2410X_SERIAL_BASE);
+    s3c24xx_serial_init(s, 1, CPU_S3C2410X_SERIAL_BASE);
+    s3c24xx_serial_init(s, 2, CPU_S3C2410X_SERIAL_BASE);
+
+    /* RTC for time */
+    s3c24xx_rtc_init(s, CPU_S3C2410X_RTC_BASE);
+
+    /* And some IIC */
+    s3c24xx_iic_init(s, CPU_S3C2410X_IIC_BASE);
+
+    /* A two port OHCI controller on IRQ 26 */
+    usb_ohci_init_pxa(CPU_S3C2410X_OHCI, 2, -1, s->irqs[26]);
+
+    /* LCD controller */
+    s->lcd = s3c24xx_lcd_init(CPU_S3C2410X_LCD_BASE, s->irqs[16]);
+
+    /* NAND controller */
+    s3c24xx_nand_init(s, CPU_S3C2410X_NAND_BASE);
+    return s;
+}
+
diff -urN qemusvnclean/hw/s3c2410x.h qemusvnpatches/hw/s3c2410x.h
--- qemusvnclean/hw/s3c2410x.h	1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/s3c2410x.h	2009-04-23 17:17:53.000000000 +0100
@@ -0,0 +1,30 @@
+/* hw/s3c2410x.h
+ *
+ * Samsung s3c2410x cpu register definitions
+ *
+ * Copyright 2006, 2007, 2008 Daniel Silverstone and Vincent Sanders
+ *
+ * This file is under the terms of the GNU General Public
+ * License Version 2.
+ */
+
+#ifndef S3C2410X_H
+#define S3C2410X_H 1
+
+#include "s3c24xx.h"
+
+/* S3C2410 Physical memory areas */
+
+/* Chip select 0 */
+#define CPU_S3C2410X_CS0 (0x00000000)
+#define CPU_S3C2410X_CS1 (0x08000000)
+#define CPU_S3C2410X_CS2 (0x10000000)
+#define CPU_S3C2410X_CS3 (0x18000000)
+#define CPU_S3C2410X_CS4 (0x20000000)
+#define CPU_S3C2410X_CS5 (0x28000000)
+#define CPU_S3C2410X_RAM (0x30000000)
+
+/* s3c2410 SOC initialisation */
+S3CState *s3c2410x_init(int sdram_size);
+
+#endif /* S3C2410X_H */

-- 
Regards Vincent
http://www.kyllikki.org/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 14/16] S3C2440 SOC impementation
  2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
                   ` (12 preceding siblings ...)
  2009-04-23 18:11 ` [Qemu-devel] [PATCH 13/16] S3C2410 SOC implementation Vincent Sanders
@ 2009-04-23 18:14 ` Vincent Sanders
  2009-04-23 18:15 ` [Qemu-devel] [PATCH 15/16] Add S3C SOC files to Makefile Vincent Sanders
  2009-04-23 18:17 ` [Qemu-devel] [PATCH 16/16] Add two boards which use S3C2410 SOC Vincent Sanders
  15 siblings, 0 replies; 29+ messages in thread
From: Vincent Sanders @ 2009-04-23 18:14 UTC (permalink / raw)
  To: qemu-devel

S3C2440 Implementation using generic S3C periperals.

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 s3c2440x.c |  117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 s3c2440x.h |   30 +++++++++++++++
 2 files changed, 147 insertions(+)

diff -urN qemusvnclean/hw/s3c2440x.c qemusvnpatches/hw/s3c2440x.c
--- qemusvnclean/hw/s3c2440x.c	1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/s3c2440x.c	2009-04-23 17:25:05.000000000 +0100
@@ -0,0 +1,117 @@
+/* hw/s3c2440x.c
+ *
+ * Samsung S3C2440X emulation
+ *
+ * Copyright 2006, 2007 Daniel Silverstone and Vincent Sanders
+ *
+ * This file is under the terms of the GNU General Public
+ * License Version 2
+ */
+
+#include "hw.h"
+
+#include "s3c2440x.h"
+
+/* We use the PXA style OHCI USB mapping */
+#include "pxa.h"
+
+/* S3C2440 SoC IDs */
+#define CPU_S3C2440X_IDENT_S3C2440A 0x32440001
+
+/* Integrated SOC peripherals */
+
+/* SRAM */
+#define CPU_S3C2440X_SRAM_BASE (0x40000000)
+
+/* Memory control */
+#define CPU_S3C2440X_MEMC_BASE (0x48000000)
+
+/* USB controller */
+#define CPU_S3C2440X_OHCI (0x49000000)
+
+/* Interrupt controller */
+#define CPU_S3C2440X_IRQ_BASE (0x4A000000)
+
+/* Clock control */
+#define CPU_S3C2440X_CLKCON_BASE (0x4C000000)
+
+/* LCD */
+#define CPU_S3C2440X_LCD_BASE (0x4D000000)
+
+/* NAND */
+#define CPU_S3C2440X_NAND_BASE (0x4E000000)
+
+/* serial port base */
+#define CPU_S3C2440X_SERIAL_BASE (0x50000000)
+
+/* Timers */
+#define CPU_S3C2440X_TIMERS_BASE (0x51000000)
+
+/* Watchdog */
+#define CPU_S3C2440X_WDOG_BASE (0x53000000)
+
+/* IIC */
+#define CPU_S3C2440X_IIC_BASE (0x54000000)
+
+/* GPIO */
+#define CPU_S3C2440X_GPIO_BASE (0x56000000)
+
+/* Real time clock */
+#define CPU_S3C2440X_RTC_BASE (0x57000000)
+
+/* Initialise a Samsung S3C2440X SOC ARM core and internal peripherals. */
+S3CState *
+s3c2440x_init(int sdram_size)
+{
+    S3CState *s = (S3CState *)qemu_mallocz(sizeof(S3CState));
+
+    /* Prepare the ARM 920T core */
+    s->cpu_env = cpu_init("arm920t");
+
+    /* S3C2440X SDRAM memory is always at the same physical location */
+    cpu_register_physical_memory(CPU_S3C2440X_RAM, 
+                                 ram_size, 
+                                 qemu_ram_alloc(sdram_size) | IO_MEM_RAM);
+
+    /* Memory controller */
+    s3c24xx_memc_init(s, CPU_S3C2440X_MEMC_BASE);
+
+    /* S3C2440X SRAM */
+    cpu_register_physical_memory(CPU_S3C2440X_SRAM_BASE, 
+                                 4096, 
+                                 qemu_ram_alloc(4096) | IO_MEM_RAM);
+
+    /* Add the interrupt controller */
+    s->irqs = s3c24xx_irq_init(s, CPU_S3C2440X_IRQ_BASE);
+
+    /* clock and power control */
+    s3c24xx_clkcon_init(s, CPU_S3C2440X_CLKCON_BASE);
+
+    /* PWM control used for timers */
+    s3c24xx_timers_init(s, CPU_S3C2440X_TIMERS_BASE);
+
+    /* And some GPIO */
+    s3c24xx_gpio_init(s, CPU_S3C2440X_GPIO_BASE, CPU_S3C2440X_IDENT_S3C2440A); 
+
+    /* Serial ports */
+    s3c24xx_serial_init(s, 0, CPU_S3C2440X_SERIAL_BASE);
+    s3c24xx_serial_init(s, 1, CPU_S3C2440X_SERIAL_BASE);
+    s3c24xx_serial_init(s, 2, CPU_S3C2440X_SERIAL_BASE);
+
+    /* RTC for time */
+    s3c24xx_rtc_init(s, CPU_S3C2440X_RTC_BASE);
+
+    /* And some IIC */
+    s3c24xx_iic_init(s, CPU_S3C2440X_IIC_BASE);
+
+    /* A two port OHCI controller on IRQ 26 */
+    usb_ohci_init_pxa(CPU_S3C2440X_OHCI, 2, -1, s->irqs[26]);
+
+    /* LCD controller */
+    s->lcd = s3c24xx_lcd_init(CPU_S3C2440X_LCD_BASE, s->irqs[16]);
+
+    /* NAND controller */
+    s3c24xx_nand_init(s, CPU_S3C2440X_NAND_BASE);
+    return s;
+}
+
diff -urN qemusvnclean/hw/s3c2440x.h qemusvnpatches/hw/s3c2440x.h
--- qemusvnclean/hw/s3c2440x.h	1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/s3c2440x.h	2009-04-23 17:25:05.000000000 +0100
@@ -0,0 +1,30 @@
+/* hw/s3c2440x.h
+ *
+ * Samsung s3c2440x cpu register definitions
+ *
+ * Copyright 2006, 2007, 2008 Daniel Silverstone and Vincent Sanders
+ *
+ * This file is under the terms of the GNU General Public
+ * License Version 2.
+ */
+
+#ifndef S3C2440X_H
+#define S3C2440X_H 1
+
+#include "s3c24xx.h"
+
+/* S3C2440 Physical memory areas */
+
+/* Chip select 0 */
+#define CPU_S3C2440X_CS0 (0x00000000)
+#define CPU_S3C2440X_CS1 (0x08000000)
+#define CPU_S3C2440X_CS2 (0x10000000)
+#define CPU_S3C2440X_CS3 (0x18000000)
+#define CPU_S3C2440X_CS4 (0x20000000)
+#define CPU_S3C2440X_CS5 (0x28000000)
+#define CPU_S3C2440X_RAM (0x30000000)
+
+/* s3c2440 SOC initialisation */
+S3CState *s3c2440x_init(int sdram_size);
+
+#endif /* S3C2440X_H */

-- 
Regards Vincent
http://www.kyllikki.org/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 15/16] Add S3C SOC files to Makefile
  2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
                   ` (13 preceding siblings ...)
  2009-04-23 18:14 ` [Qemu-devel] [PATCH 14/16] S3C2440 SOC impementation Vincent Sanders
@ 2009-04-23 18:15 ` Vincent Sanders
  2009-04-23 18:17 ` [Qemu-devel] [PATCH 16/16] Add two boards which use S3C2410 SOC Vincent Sanders
  15 siblings, 0 replies; 29+ messages in thread
From: Vincent Sanders @ 2009-04-23 18:15 UTC (permalink / raw)
  To: qemu-devel

Add S3C SOC files to Makefile

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 Makefile.target |    4 ++++
 1 file changed, 4 insertions(+)

diff -urN qemusvnclean/Makefile.target qemusvnpatches/Makefile.target
--- qemusvnclean/Makefile.target	2009-04-23 14:49:39.000000000 +0100
+++ qemusvnpatches/Makefile.target	2009-04-23 17:30:24.000000000 +0100
@@ -661,6 +661,10 @@
 OBJS+= arm-semi.o
 OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
+OBJS+= s3c2410x.o s3c2440x.o
+OBJS+= s3c24xx_clkcon.o s3c24xx_gpio.o s3c24xx_iic.o
+OBJS+= s3c24xx_irq.o s3c24xx_lcd.o s3c24xx_memc.o s3c24xx_nand.o
+OBJS+= s3c24xx_rtc.o s3c24xx_serial.o s3c24xx_timers.o
 OBJS+= pflash_cfi01.o gumstix.o
 OBJS+= zaurus.o ide.o serial.o nand.o ecc.o spitz.o tosa.o tc6393xb.o
 OBJS+= omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o


-- 
Regards Vincent
http://www.kyllikki.org/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 16/16] Add two boards which use S3C2410 SOC
  2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
                   ` (14 preceding siblings ...)
  2009-04-23 18:15 ` [Qemu-devel] [PATCH 15/16] Add S3C SOC files to Makefile Vincent Sanders
@ 2009-04-23 18:17 ` Vincent Sanders
  2009-04-25 12:44   ` Jean-Christophe PLAGNIOL-VILLARD
  15 siblings, 1 reply; 29+ messages in thread
From: Vincent Sanders @ 2009-04-23 18:17 UTC (permalink / raw)
  To: qemu-devel

Add bast and smdk2410 boards which use S3C2410 SOC 

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 Makefile.target      |    1 
 hw/bast.c            |  176 +++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/boards.h          |    6 +
 hw/smdk2410.c        |  120 ++++++++++++++++++++++++++++++++++
 target-arm/machine.c |    2 
 5 files changed, 305 insertions(+)

diff -urN qemusvnclean/hw/bast.c qemusvnpatches/hw/bast.c
--- qemusvnclean/hw/bast.c	1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/bast.c	2009-04-23 17:45:53.000000000 +0100
@@ -0,0 +1,176 @@
+/* hw/bast.c
+ *
+ * System emulation for the Simtec Electronics BAST
+ *
+ * Copyright 2006, 2008 Daniel Silverstone and Vincent Sanders
+ *
+ * This file is under the terms of the GNU General Public
+ * License Version 2.
+ */
+
+#include "hw.h"
+#include "sysemu.h"
+#include "arm-misc.h"
+#include "net.h"
+#include "smbus.h"
+#include "flash.h"
+#include "devices.h"
+#include "boards.h"
+
+#include "s3c2410x.h"
+
+#define BIOS_FILENAME "able.bin"
+
+typedef struct {
+    S3CState *soc;
+    unsigned char cpld_ctrl2;
+    struct nand_flash_s *nand[4];
+} STCBState;
+
+/* Bytes in a Kilobyte */
+#define KILO 1024
+/* Bytes in a megabyte */
+#define MEGA 1024 * KILO
+/* Bytes */
+#define BYTE 1
+/* Bits in a byte */
+#define BIT 8
+
+/* Useful defines */
+#define BAST_NOR_BASE CPU_S3C2410X_CS0
+#define BAST_NOR_SIZE 16 * MEGA / BIT
+#define BAST_BOARD_ID 331
+
+#define BAST_CS1_CPLD_BASE ((target_phys_addr_t)(CPU_S3C2410X_CS1 | (0xc << 23)))
+#define BAST_CS5_CPLD_BASE ((target_phys_addr_t)(CPU_S3C2410X_CS5 | (0xc << 23)))
+#define BAST_CPLD_SIZE (4<<23)
+
+static uint32_t cpld_read(void *opaque, target_phys_addr_t address)
+{
+    STCBState *stcb = (STCBState *)opaque;
+    int reg = (address >> 23) & 0xf;
+    if (reg == 0xc)
+        return stcb->cpld_ctrl2;
+    return 0;
+}
+
+static void cpld_write(void *opaque, target_phys_addr_t address,
+                       uint32_t value)
+{
+    STCBState *stcb = (STCBState *)opaque;
+    int reg = (address >> 23) & 0xf;
+    if (reg == 0xc) {
+        stcb->cpld_ctrl2 = value;
+        s3c24xx_nand_attach(stcb->soc, stcb->nand[stcb->cpld_ctrl2 & 3]);
+    }
+}
+
+static CPUReadMemoryFunc *cpld_readfn[] = {
+    cpld_read,
+    cpld_read,
+    cpld_read
+};
+
+static CPUWriteMemoryFunc *cpld_writefn[] = {
+    cpld_write,
+    cpld_write,
+    cpld_write
+};
+
+static void stcb_cpld_register(STCBState *stcb)
+{
+    int tag = cpu_register_io_memory(0, cpld_readfn, cpld_writefn, stcb);
+    cpu_register_physical_memory(BAST_CS1_CPLD_BASE, BAST_CPLD_SIZE, tag);
+    cpu_register_physical_memory(BAST_CS5_CPLD_BASE, BAST_CPLD_SIZE, tag);
+    stcb->cpld_ctrl2 = 0;
+}
+
+static void stcb_i2c_setup(STCBState *stcb)
+{
+    i2c_bus *bus = s3c24xx_i2c_bus(stcb->soc->iic);
+}
+
+static struct arm_boot_info bast_binfo = {
+    .board_id = BAST_BOARD_ID,
+    .ram_size = 0x10000000, /* 256MB */
+};
+
+static void stcb_init(ram_addr_t _ram_size, 
+                      int vga_ram_size, 
+                      const char *boot_device,
+                      const char *kernel_filename, const char *kernel_cmdline,
+                      const char *initrd_filename, const char *cpu_model)
+{
+    STCBState *stcb;
+    int ret, index;
+
+    /* ensure memory is limited to 256MB */
+    if (_ram_size > (256 * MEGA * BYTE)) 
+        _ram_size = 256 * MEGA * BYTE;
+    ram_size = _ram_size;
+  
+    /* allocate storage for board state */
+    stcb = malloc(sizeof(STCBState));
+  
+    /* initialise SOC */
+    stcb->soc = s3c2410x_init(ram_size);
+
+    /* Register the NOR flash ROM */
+    cpu_register_physical_memory(BAST_NOR_BASE, 
+                                 BAST_NOR_SIZE,
+                                 qemu_ram_alloc(BAST_NOR_SIZE) | IO_MEM_ROM);
+
+    /* initialise board informations */
+    bast_binfo.ram_size = ram_size;
+    bast_binfo.kernel_filename = kernel_filename;
+    bast_binfo.kernel_cmdline = kernel_cmdline;
+    bast_binfo.initrd_filename = initrd_filename;
+    bast_binfo.nb_cpus = 1;
+    bast_binfo.loader_start = BAST_NOR_BASE;
+  
+    if (kernel_filename == NULL) {
+        /* No kernel given so try and aquire a bootloader */
+        char buf[PATH_MAX]; 
+
+        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+        ret = load_image_targphys(buf, bast_binfo.loader_start, BAST_NOR_SIZE);
+        if (ret <= 0) {
+            perror("qemu");
+            fprintf(stderr, "qemu: warning, could not load BAST BIOS from %s\n", buf);
+            exit (1);
+        } else {
+            fprintf(stdout, "qemu: info, loaded BAST BIOS %d bytes from %s\n", ret, buf);
+        }
+    } else {
+        bast_binfo.loader_start = CPU_S3C2410X_RAM;    
+        arm_load_kernel(stcb->soc->cpu_env, &bast_binfo);
+    }
+  
+    /* Setup initial (reset) program counter */
+    stcb->soc->cpu_env->regs[15] = bast_binfo.loader_start;
+
+    /* Initialise the BAST CPLD */
+    stcb_cpld_register(stcb);
+  
+    /* attach i2c devices */
+    stcb_i2c_setup(stcb);
+
+    /* Attach some NAND devices */
+    stcb->nand[0] = NULL;
+    stcb->nand[1] = NULL;
+    index = drive_get_index(IF_MTD, 0, 0);
+    if (index == -1)
+        stcb->nand[2] = NULL;
+    else
+        stcb->nand[2] = nand_init(0xEC, 0x79); /* 128MiB small-page */
+  
+    /* And we're good to go */
+}
+
+
+QEMUMachine bast_machine = {
+  .name = "bast",
+  .desc = "Simtec Electronics BAST (S3C2410A, ARM920T)",
+  .init = stcb_init,
+  .max_cpus = 1,
+};
diff -urN qemusvnclean/hw/boards.h qemusvnpatches/hw/boards.h
--- qemusvnclean/hw/boards.h	2009-04-23 14:49:39.000000000 +0100
+++ qemusvnpatches/hw/boards.h	2009-04-23 17:39:07.000000000 +0100
@@ -128,4 +128,10 @@
 /* tosa.c */
 extern QEMUMachine tosapda_machine;
 
+/* bast.c */
+extern QEMUMachine bast_machine;
+
+/* smdk2410.c */
+extern QEMUMachine smdk2410_machine;
+
 #endif
diff -urN qemusvnclean/hw/smdk2410.c qemusvnpatches/hw/smdk2410.c
--- qemusvnclean/hw/smdk2410.c	1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/smdk2410.c	2009-04-23 17:37:27.000000000 +0100
@@ -0,0 +1,120 @@
+/* hw/smdk2410.c
+ *
+ * System emulation for the Samsung SMDK2410
+ *
+ * Copyright 2006, 2008 Daniel Silverstone and Vincent Sanders
+ *
+ * This file is under the terms of the GNU General Public
+ * License Version 2.
+ */
+
+#include "hw.h"
+#include "sysemu.h"
+#include "arm-misc.h"
+#include "net.h"
+#include "smbus.h"
+#include "flash.h"
+#include "devices.h"
+#include "boards.h"
+
+#include "s3c2410x.h"
+
+#define BIOS_FILENAME "smdk2410.bin"
+
+typedef struct {
+    S3CState *soc;
+    unsigned char cpld_ctrl2;
+    struct nand_flash_s *nand[4];
+} SMDK2410State;
+
+/* Bytes in a Kilobyte */
+#define KILO 1024
+/* Bytes in a megabyte */
+#define MEGA 1024 * KILO
+/* Bytes */
+#define BYTE 1
+/* Bits in a byte */
+#define BIT 8
+
+/* Useful defines */
+#define SMDK2410_NOR_BASE CPU_S3C2410X_CS0
+#define SMDK2410_NOR_SIZE 16 * MEGA / BIT
+#define SMDK2410_BOARD_ID 193
+
+static struct arm_boot_info smdk2410_binfo = {
+    .board_id = SMDK2410_BOARD_ID,
+    .ram_size = 0x10000000, /* 256MB */
+};
+
+static void smdk2410_init(ram_addr_t _ram_size, 
+                      int vga_ram_size, 
+                      const char *boot_device,
+                      const char *kernel_filename, const char *kernel_cmdline,
+                      const char *initrd_filename, const char *cpu_model)
+{
+    SMDK2410State *stcb;
+    int ret, index;
+
+    /* ensure memory is limited to 256MB */
+    if (_ram_size > (256 * MEGA * BYTE)) 
+        _ram_size = 256 * MEGA * BYTE;
+    ram_size = _ram_size;
+  
+    /* allocate storage for board state */
+    stcb = malloc(sizeof(SMDK2410State));
+  
+    /* initialise CPU and memory */
+    stcb->soc = s3c2410x_init(ram_size);
+
+    /* Register the NOR flash ROM */
+    cpu_register_physical_memory(SMDK2410_NOR_BASE, 
+                                 SMDK2410_NOR_SIZE,
+                                 qemu_ram_alloc(SMDK2410_NOR_SIZE) | IO_MEM_ROM);
+
+    /* initialise board informations */
+    smdk2410_binfo.ram_size = ram_size;
+    smdk2410_binfo.kernel_filename = kernel_filename;
+    smdk2410_binfo.kernel_cmdline = kernel_cmdline;
+    smdk2410_binfo.initrd_filename = initrd_filename;
+    smdk2410_binfo.nb_cpus = 1;
+    smdk2410_binfo.loader_start = SMDK2410_NOR_BASE;
+  
+    if (kernel_filename == NULL) {
+        /* No kernel given so try and aquire a bootloader */
+        char buf[PATH_MAX]; 
+
+        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+        ret = load_image_targphys(buf, smdk2410_binfo.loader_start, SMDK2410_NOR_SIZE);
+        if (ret <= 0) {
+            perror("qemu");
+            fprintf(stderr, "qemu: warning, could not load SMDK2410 BIOS from %s\n", buf);
+            exit (1);
+        } else {
+            fprintf(stdout, "qemu: info, loaded SMDK2410 BIOS %d bytes from %s\n", ret, buf);
+        }
+    } else {
+        smdk2410_binfo.loader_start = CPU_S3C2410X_RAM;    
+        arm_load_kernel(stcb->soc->cpu_env, &smdk2410_binfo);
+    }
+  
+    /* Setup initial (reset) program counter */
+    stcb->soc->cpu_env->regs[15] = smdk2410_binfo.loader_start;
+
+    /* Attach some NAND devices */
+    stcb->nand[0] = NULL;
+    stcb->nand[1] = NULL;
+    index = drive_get_index(IF_MTD, 0, 0);
+    if (index == -1)
+        stcb->nand[2] = NULL;
+    else
+        stcb->nand[2] = nand_init(0xEC, 0x79); /* 128MiB small-page */
+  
+}
+
+
+QEMUMachine smdk2410_machine = {
+  .name = "smdk2410",
+  .desc = "Samsung SMDK2410 (S3C2410A, ARM920T)",
+  .init = smdk2410_init,
+  .max_cpus = 1,
+};
diff -urN qemusvnclean/Makefile.target qemusvnpatches/Makefile.target
--- qemusvnclean/Makefile.target	2009-04-23 17:30:24.000000000 +0100
+++ qemusvnpatches/Makefile.target	2009-04-23 17:41:39.000000000 +0100
@@ -665,6 +665,7 @@
 OBJS+= s3c24xx_clkcon.o s3c24xx_gpio.o s3c24xx_iic.o
 OBJS+= s3c24xx_irq.o s3c24xx_lcd.o s3c24xx_memc.o s3c24xx_nand.o
 OBJS+= s3c24xx_rtc.o s3c24xx_serial.o s3c24xx_timers.o
+OBJS+= bast.o smdk2410.o
 OBJS+= pflash_cfi01.o gumstix.o
 OBJS+= zaurus.o ide.o serial.o nand.o ecc.o spitz.o tosa.o tc6393xb.o
 OBJS+= omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o
diff -urN qemusvnclean/target-arm/machine.c qemusvnpatches/target-arm/machine.c
--- qemusvnclean/target-arm/machine.c	2009-04-20 20:26:52.000000000 +0100
+++ qemusvnpatches/target-arm/machine.c	2009-04-23 17:38:07.000000000 +0100
@@ -7,6 +7,8 @@
     qemu_register_machine(&versatilepb_machine);
     qemu_register_machine(&versatileab_machine);
     qemu_register_machine(&realview_machine);
+    qemu_register_machine(&bast_machine);
+    qemu_register_machine(&smdk2410_machine);
     qemu_register_machine(&akitapda_machine);
     qemu_register_machine(&spitzpda_machine);
     qemu_register_machine(&borzoipda_machine);

-- 
Regards Vincent
http://www.kyllikki.org/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 16/16] Add two boards which use S3C2410 SOC
  2009-04-23 18:17 ` [Qemu-devel] [PATCH 16/16] Add two boards which use S3C2410 SOC Vincent Sanders
@ 2009-04-25 12:44   ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 0 replies; 29+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-04-25 12:44 UTC (permalink / raw)
  To: Vincent Sanders; +Cc: qemu-devel

On 19:17 Thu 23 Apr     , Vincent Sanders wrote:
> Add bast and smdk2410 boards which use S3C2410 SOC 
> 
> Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
> ---
>  Makefile.target      |    1 
>  hw/bast.c            |  176 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/boards.h          |    6 +
>  hw/smdk2410.c        |  120 ++++++++++++++++++++++++++++++++++
>  target-arm/machine.c |    2 
>  5 files changed, 305 insertions(+)
> 
> diff -urN qemusvnclean/hw/bast.c qemusvnpatches/hw/bast.c
> --- qemusvnclean/hw/bast.c	1970-01-01 01:00:00.000000000 +0100
> +++ qemusvnpatches/hw/bast.c	2009-04-23 17:45:53.000000000 +0100
> @@ -0,0 +1,176 @@
> +/* hw/bast.c
> + *
> + * System emulation for the Simtec Electronics BAST
> + *
> + * Copyright 2006, 2008 Daniel Silverstone and Vincent Sanders
> + *
> + * This file is under the terms of the GNU General Public
> + * License Version 2.
> + */
> +
> +#include "hw.h"
> +#include "sysemu.h"
> +#include "arm-misc.h"
> +#include "net.h"
> +#include "smbus.h"
> +#include "flash.h"
> +#include "devices.h"
> +#include "boards.h"
> +
> +#include "s3c2410x.h"
> +
> +#define BIOS_FILENAME "able.bin"
> +
> +typedef struct {
> +    S3CState *soc;
> +    unsigned char cpld_ctrl2;
> +    struct nand_flash_s *nand[4];
> +} STCBState;
> +
> +/* Bytes in a Kilobyte */
> +#define KILO 1024
> +/* Bytes in a megabyte */
> +#define MEGA 1024 * KILO
> +/* Bytes */
> +#define BYTE 1
> +/* Bits in a byte */
> +#define BIT 8
> +
> +/* Useful defines */
> +#define BAST_NOR_BASE CPU_S3C2410X_CS0
> +#define BAST_NOR_SIZE 16 * MEGA / BIT
> +#define BAST_BOARD_ID 331
> +
> +    if (_ram_size > (256 * MEGA * BYTE)) 
> +        _ram_size = 256 * MEGA * BYTE;
> +    ram_size = _ram_size;
> +  
> +    /* allocate storage for board state */
> +    stcb = malloc(sizeof(STCBState));
> +  
> +    /* initialise SOC */
> +    stcb->soc = s3c2410x_init(ram_size);
> +
> +    /* Register the NOR flash ROM */
> +    cpu_register_physical_memory(BAST_NOR_BASE, 
> +                                 BAST_NOR_SIZE,
> +                                 qemu_ram_alloc(BAST_NOR_SIZE) | IO_MEM_ROM);
> +
> +    /* initialise board informations */
> +    bast_binfo.ram_size = ram_size;
> +    bast_binfo.kernel_filename = kernel_filename;
> +    bast_binfo.kernel_cmdline = kernel_cmdline;
> +    bast_binfo.initrd_filename = initrd_filename;
> +    bast_binfo.nb_cpus = 1;
> +    bast_binfo.loader_start = BAST_NOR_BASE;
> +  
> +    if (kernel_filename == NULL) {
> +        /* No kernel given so try and aquire a bootloader */
it will be nice if you use the cfi flash support
that will allow us to use the -pflash to specify the flash file and also use
main u-boot without any update

Best Regards,
J.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers
  2009-04-23 17:45 ` [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers Vincent Sanders
@ 2009-04-30 16:08   ` Paul Brook
  2009-05-23 16:50     ` Vincent Sanders
  0 siblings, 1 reply; 29+ messages in thread
From: Paul Brook @ 2009-04-30 16:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Vincent Sanders

>      env->cp15.c0_cpuid = id;
>      switch (id) {
> +    case ARM_CPUID_ARM920T:
> +       break;

This is woefully incomplete. At minimum it needs a comment describing how this 
is a lie.

Paul

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers
  2009-04-30 16:08   ` Paul Brook
@ 2009-05-23 16:50     ` Vincent Sanders
  2009-05-24 18:31       ` Paul Brook
  0 siblings, 1 reply; 29+ messages in thread
From: Vincent Sanders @ 2009-05-23 16:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paul Brook

On Thu, Apr 30, 2009 at 05:08:01PM +0100, Paul Brook wrote:
> >      env->cp15.c0_cpuid = id;
> >      switch (id) {
> > +    case ARM_CPUID_ARM920T:
> > +       break;
> 
> This is woefully incomplete. At minimum it needs a comment describing how this 
> is a lie.

I have worked out what you meant was that the copro 15 registers
needed configuring appropriately in this case. This I have done and
the new series, integrating others feedback, has been posted. This is
against the git server as of a few minutes ago.

I would be grateful if you would at least consider this series for
merging. If it is not yet suitable could you please provide some
constructive explanation as to what further changes are required? At
the very least the core ARM920T patch could be merged without much
controversy?

The series has been presented several times over a number of years
always incorporating all feedback given. Despite this little progress
seems to have been made and I am beginning to wonder if there is any
point in continuing?

-- 
Regards Vincent

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers
  2009-05-23 16:50     ` Vincent Sanders
@ 2009-05-24 18:31       ` Paul Brook
  2009-05-26  9:39         ` Vincent Sanders
  0 siblings, 1 reply; 29+ messages in thread
From: Paul Brook @ 2009-05-24 18:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Vincent Sanders

On Saturday 23 May 2009, Vincent Sanders wrote:
> On Thu, Apr 30, 2009 at 05:08:01PM +0100, Paul Brook wrote:
> > >      env->cp15.c0_cpuid = id;
> > >      switch (id) {
> > > +    case ARM_CPUID_ARM920T:
> > > +       break;
> >
> > This is woefully incomplete. At minimum it needs a comment describing how
> > this is a lie.
>
> I have worked out what you meant was that the copro 15 registers
> needed configuring appropriately in this case.

More fundamental than that. We emulate armv5te. The arm920t is armv4t.
i.e. even usermode code may not work right.

Paul

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers
  2009-05-24 18:31       ` Paul Brook
@ 2009-05-26  9:39         ` Vincent Sanders
  2009-05-26  9:42           ` Laurent Desnogues
  0 siblings, 1 reply; 29+ messages in thread
From: Vincent Sanders @ 2009-05-26  9:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paul Brook

On Sun, May 24, 2009 at 07:31:19PM +0100, Paul Brook wrote:
> On Saturday 23 May 2009, Vincent Sanders wrote:
> > On Thu, Apr 30, 2009 at 05:08:01PM +0100, Paul Brook wrote:
> > > >      env->cp15.c0_cpuid = id;
> > > >      switch (id) {
> > > > +    case ARM_CPUID_ARM920T:
> > > > +       break;
> > >
> > > This is woefully incomplete. At minimum it needs a comment describing how
> > > this is a lie.
> >
> > I have worked out what you meant was that the copro 15 registers
> > needed configuring appropriately in this case.
> 
> More fundamental than that. We emulate armv5te. The arm920t is armv4t.
> i.e. even usermode code may not work right.
> 

Thankyou, right, now I understand. Perhaps if you had been a little
more explicit in your first reply I would have been able to grasp what
you wanted sooner.

I will post the updated patch to the list shortly. Please be assured
that every program we have tried (boot loaders, Linux, BSD etc.)
appears to function as expected, to the point it had not been
apparient the 920 was a different ISA version to the default emulation.

So while this is indeed a technical issue, in practice it doesnt seem
to be a major problem. 

-- 
Regards Vincent

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers
  2009-05-26  9:39         ` Vincent Sanders
@ 2009-05-26  9:42           ` Laurent Desnogues
  2009-05-26  9:56             ` Jamie Lokier
  0 siblings, 1 reply; 29+ messages in thread
From: Laurent Desnogues @ 2009-05-26  9:42 UTC (permalink / raw)
  To: Vincent Sanders; +Cc: qemu-devel

On Tue, May 26, 2009 at 11:39 AM, Vincent Sanders <vince@kyllikki.org> wrote:
> I will post the updated patch to the list shortly. Please be assured
> that every program we have tried (boot loaders, Linux, BSD etc.)
> appears to function as expected, to the point it had not been
> apparient the 920 was a different ISA version to the default emulation.
>
> So while this is indeed a technical issue, in practice it doesnt seem
> to be a major problem.

It could be a major problem if you start playing with ARM/Thumb
interworking.


Laurent

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers
  2009-05-26  9:42           ` Laurent Desnogues
@ 2009-05-26  9:56             ` Jamie Lokier
  2009-05-26 10:08               ` Laurent Desnogues
  2009-05-26 10:16               ` Paul Brook
  0 siblings, 2 replies; 29+ messages in thread
From: Jamie Lokier @ 2009-05-26  9:56 UTC (permalink / raw)
  To: Laurent Desnogues; +Cc: Vincent Sanders, qemu-devel

Laurent Desnogues wrote:
> On Tue, May 26, 2009 at 11:39 AM, Vincent Sanders <vince@kyllikki.org> wrote:
> > I will post the updated patch to the list shortly. Please be assured
> > that every program we have tried (boot loaders, Linux, BSD etc.)
> > appears to function as expected, to the point it had not been
> > apparient the 920 was a different ISA version to the default emulation.
> >
> > So while this is indeed a technical issue, in practice it doesnt seem
> > to be a major problem.
> 
> It could be a major problem if you start playing with ARM/Thumb
> interworking.

I'm curious.  How would code built for ARMv4T interworking fail on an
ARMv5T emulator?

-- Jamie

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers
  2009-05-26  9:56             ` Jamie Lokier
@ 2009-05-26 10:08               ` Laurent Desnogues
  2009-05-26 11:29                 ` Jamie Lokier
  2009-05-26 10:16               ` Paul Brook
  1 sibling, 1 reply; 29+ messages in thread
From: Laurent Desnogues @ 2009-05-26 10:08 UTC (permalink / raw)
  To: Jamie Lokier; +Cc: Vincent Sanders, qemu-devel

On Tue, May 26, 2009 at 11:56 AM, Jamie Lokier <jamie@shareable.org> wrote:
> Laurent Desnogues wrote:
>> On Tue, May 26, 2009 at 11:39 AM, Vincent Sanders <vince@kyllikki.org> wrote:
>> > I will post the updated patch to the list shortly. Please be assured
>> > that every program we have tried (boot loaders, Linux, BSD etc.)
>> > appears to function as expected, to the point it had not been
>> > apparient the 920 was a different ISA version to the default emulation.
>> >
>> > So while this is indeed a technical issue, in practice it doesnt seem
>> > to be a major problem.
>>
>> It could be a major problem if you start playing with ARM/Thumb
>> interworking.
>
> I'm curious.  How would code built for ARMv4T interworking fail on an
> ARMv5T emulator?

It shouldn't.  I was thinking about how most people are misusing their
toolchain and think that if QEMU runs correctly some code, it should
run on the target.  In that particular case, that will fail :-)  For instance
LDM with PC used as procedure return does not behave the same
in v4T and v5 IIRC.


Laurent

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers
  2009-05-26  9:56             ` Jamie Lokier
  2009-05-26 10:08               ` Laurent Desnogues
@ 2009-05-26 10:16               ` Paul Brook
  2009-05-26 11:18                 ` Vincent Sanders
  1 sibling, 1 reply; 29+ messages in thread
From: Paul Brook @ 2009-05-26 10:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Desnogues, Vincent Sanders

> > It could be a major problem if you start playing with ARM/Thumb
> > interworking.
>
> I'm curious.  How would code built for ARMv4T interworking fail on an
> ARMv5T emulator?

Usually the reverse is true - code works on v5, but fails on v4t.
However the following will work on armv4t and fail on armv5:

test:
adr r0, 1f
orr r0, r0, #1
str r0, [sp, #-4]!
ldr pc, [sp], #4
1:
bx lr

Admittedly this is a fairly contrived example, but the circumstances aren't 
completely implausible. Imagine someone using the low bit of a pointer as an 
additional flag, and relying on the hardware ignoring that bit.

Paul

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers
  2009-05-26 10:16               ` Paul Brook
@ 2009-05-26 11:18                 ` Vincent Sanders
  0 siblings, 0 replies; 29+ messages in thread
From: Vincent Sanders @ 2009-05-26 11:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paul Brook

On Tue, May 26, 2009 at 11:16:18AM +0100, Paul Brook wrote:
> > > It could be a major problem if you start playing with ARM/Thumb
> > > interworking.
> >
> > I'm curious.  How would code built for ARMv4T interworking fail on an
> > ARMv5T emulator?
> 
> Usually the reverse is true - code works on v5, but fails on v4t.
> However the following will work on armv4t and fail on armv5:
> 
> test:
> adr r0, 1f
> orr r0, r0, #1
> str r0, [sp, #-4]!
> ldr pc, [sp], #4
> 1:
> bx lr
> 
> Admittedly this is a fairly contrived example, but the circumstances aren't 
> completely implausible. Imagine someone using the low bit of a pointer as an 
> additional flag, and relying on the hardware ignoring that bit.

ok, aside from that (very very unlikey) case are you going to accept
the new patch with the comment or do I need to alter translate.c to
perform V4 operations and add the v5 feature flag.

I am happy to do that if there is any chance of it being
accepted. However I am now at the point I feel I am just wasting my
time and you have no intention whatsoever of accepting anything we
submit. 

If you have no desire whatsoever to accept our work, thats fine, and I
shall desist from attempting to contribute any futher. Please
communicate your intentions clearly so there is no futher ambiguity,
thankyou.

-- 
Regards Vincent

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers
  2009-05-26 10:08               ` Laurent Desnogues
@ 2009-05-26 11:29                 ` Jamie Lokier
  2009-05-26 11:46                   ` Laurent Desnogues
  0 siblings, 1 reply; 29+ messages in thread
From: Jamie Lokier @ 2009-05-26 11:29 UTC (permalink / raw)
  To: Laurent Desnogues; +Cc: Vincent Sanders, qemu-devel

Laurent Desnogues wrote:
> On Tue, May 26, 2009 at 11:56 AM, Jamie Lokier <jamie@shareable.org> wrote:
> > Laurent Desnogues wrote:
> >> On Tue, May 26, 2009 at 11:39 AM, Vincent Sanders <vince@kyllikki.org> wrote:
> >> > I will post the updated patch to the list shortly. Please be assured
> >> > that every program we have tried (boot loaders, Linux, BSD etc.)
> >> > appears to function as expected, to the point it had not been
> >> > apparient the 920 was a different ISA version to the default emulation.
> >> >
> >> > So while this is indeed a technical issue, in practice it doesnt seem
> >> > to be a major problem.
> >>
> >> It could be a major problem if you start playing with ARM/Thumb
> >> interworking.
> >
> > I'm curious.  How would code built for ARMv4T interworking fail on an
> > ARMv5T emulator?
> 
> It shouldn't.  I was thinking about how most people are misusing their
> toolchain and think that if QEMU runs correctly some code, it should
> run on the target.  In that particular case, that will fail :-)  For instance
> LDM with PC used as procedure return does not behave the same
> in v4T and v5 IIRC.

I agree.  Especially for testing toolchains and architecture-specific
code, it would be quite nice :-)

I gather the x86 target is similarly lax with checking some things
that a real x86 checks.

-- Jamie

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers
  2009-05-26 11:29                 ` Jamie Lokier
@ 2009-05-26 11:46                   ` Laurent Desnogues
  0 siblings, 0 replies; 29+ messages in thread
From: Laurent Desnogues @ 2009-05-26 11:46 UTC (permalink / raw)
  To: Jamie Lokier; +Cc: Vincent Sanders, qemu-devel

On Tue, May 26, 2009 at 1:29 PM, Jamie Lokier <jamie@shareable.org> wrote:
> Laurent Desnogues wrote:
[...]
>> It shouldn't.  I was thinking about how most people are misusing their
>> toolchain and think that if QEMU runs correctly some code, it should
>> run on the target.  In that particular case, that will fail :-)  For instance
>> LDM with PC used as procedure return does not behave the same
>> in v4T and v5 IIRC.
>
> I agree.  Especially for testing toolchains and architecture-specific
> code, it would be quite nice :-)
>
> I gather the x86 target is similarly lax with checking some things
> that a real x86 checks.

The existing ARM target is lax too, but quite close.  The main problem
is that the ARM architecture defines what is IMPLEMENTATION
DEFINED and also contains many UNPREDICTABLE behaviors, and
there are programs that rely on both, which basically means that if
one wanted an accurate simulation of all that, the ARM target would
be even more unreadable than it is now :)  Anyway architectural
compliance would be enough and I think it's highly desirable.


Laurent

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2009-05-26 11:46 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
2009-04-23 17:45 ` [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers Vincent Sanders
2009-04-30 16:08   ` Paul Brook
2009-05-23 16:50     ` Vincent Sanders
2009-05-24 18:31       ` Paul Brook
2009-05-26  9:39         ` Vincent Sanders
2009-05-26  9:42           ` Laurent Desnogues
2009-05-26  9:56             ` Jamie Lokier
2009-05-26 10:08               ` Laurent Desnogues
2009-05-26 11:29                 ` Jamie Lokier
2009-05-26 11:46                   ` Laurent Desnogues
2009-05-26 10:16               ` Paul Brook
2009-05-26 11:18                 ` Vincent Sanders
2009-04-23 17:48 ` [Qemu-devel] [PATCH 2/16] Add s3c SOC header Vincent Sanders
2009-04-23 17:50 ` [Qemu-devel] [PATCH 3/16] S3C SDRAM memory controller Peripheral Vincent Sanders
2009-04-23 17:52 ` [Qemu-devel] [PATCH 4/16] S3C irq controller Vincent Sanders
2009-04-23 17:58 ` [Qemu-devel] [PATCH 05/16] S3C Clock controller peripheral Vincent Sanders
2009-04-23 18:00 ` [Qemu-devel] [PATCH 7/16] S3C serial peripheral Vincent Sanders
2009-04-23 18:02 ` [Qemu-devel] [PATCH 6/16] S3C Timers Vincent Sanders
2009-04-23 18:04 ` [Qemu-devel] [PATCH 8/16] S3C Real Time Clock Vincent Sanders
2009-04-23 18:05 ` [Qemu-devel] [PATCH 9/16] S3C General Purpose IO Vincent Sanders
2009-04-23 18:07 ` [Qemu-devel] [PATCH 10/16] S3C I2C peripheral Vincent Sanders
2009-04-23 18:08 ` [Qemu-devel] [PATCH 11/16] S3C LCD display Vincent Sanders
2009-04-23 18:09 ` [Qemu-devel] [PATCH 12/16] S3C NAND controller Vincent Sanders
2009-04-23 18:11 ` [Qemu-devel] [PATCH 13/16] S3C2410 SOC implementation Vincent Sanders
2009-04-23 18:14 ` [Qemu-devel] [PATCH 14/16] S3C2440 SOC impementation Vincent Sanders
2009-04-23 18:15 ` [Qemu-devel] [PATCH 15/16] Add S3C SOC files to Makefile Vincent Sanders
2009-04-23 18:17 ` [Qemu-devel] [PATCH 16/16] Add two boards which use S3C2410 SOC Vincent Sanders
2009-04-25 12:44   ` Jean-Christophe PLAGNIOL-VILLARD

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).