All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] Add ARM S3C SOC core, drivers and boards
@ 2009-05-06  8:44 Vincent Sanders
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 01/15] Add ARM 920T CPU identifier Vincent Sanders
                   ` (15 more replies)
  0 siblings, 16 replies; 23+ messages in thread
From: Vincent Sanders @ 2009-05-06  8:44 UTC (permalink / raw)
  To: qemu-devel

This is an updated series integrating the feedback from Paul Brook 
and Jean-Christophe plagniol-villard and rebased to current git head. 

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 git head. 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.

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

* [Qemu-devel] [PATCH 01/15] Add ARM 920T CPU identifier
  2009-05-06  8:44 [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
@ 2009-05-06  8:44 ` Vincent Sanders
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 02/15] S3C system on chip integrated peripheral device state header Vincent Sanders
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Vincent Sanders @ 2009-05-06  8:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Vincent Sanders

Add the CPU Identifier required for ARM 920T cpu cores

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 target-arm/cpu.h    |    1 +
 target-arm/helper.c |    5 +++++
 2 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index f98655f..eafaeaf 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -370,6 +370,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 #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 --git a/target-arm/helper.c b/target-arm/helper.c
index 701629a..2b05d15 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -37,6 +37,10 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
 {
     env->cp15.c0_cpuid = id;
     switch (id) {
+    case ARM_CPUID_ARM920T:
+        env->cp15.c0_cachetype = 0x0d172172;
+        env->cp15.c1_sys = 0x00000078;
+        break;
     case ARM_CPUID_ARM926:
         set_feature(env, ARM_FEATURE_VFP);
         env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
@@ -277,6 +281,7 @@ struct arm_cpu_t {
 };
 
 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"},
-- 
1.5.4.3

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

* [Qemu-devel] [PATCH 02/15] S3C system on chip integrated peripheral device state header
  2009-05-06  8:44 [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 01/15] Add ARM 920T CPU identifier Vincent Sanders
@ 2009-05-06  8:44 ` Vincent Sanders
  2009-05-15 22:33   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 03/15] Peripheral driver for S3C SOC SDRAM controller Vincent Sanders
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 23+ messages in thread
From: Vincent Sanders @ 2009-05-06  8:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Vincent Sanders

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 hw/s3c24xx.h |   73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 73 insertions(+), 0 deletions(-)
 create mode 100644 hw/s3c24xx.h

diff --git a/hw/s3c24xx.h b/hw/s3c24xx.h
new file mode 100644
index 0000000..38d4a32
--- /dev/null
+++ b/hw/s3c24xx.h
@@ -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 */
-- 
1.5.4.3

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

* [Qemu-devel] [PATCH 03/15] Peripheral driver for S3C SOC SDRAM controller.
  2009-05-06  8:44 [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 01/15] Add ARM 920T CPU identifier Vincent Sanders
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 02/15] S3C system on chip integrated peripheral device state header Vincent Sanders
@ 2009-05-06  8:44 ` Vincent Sanders
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 04/15] Peripheral driver for S3C SOC IRQ controller Vincent Sanders
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Vincent Sanders @ 2009-05-06  8:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Vincent Sanders

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 Makefile.target   |    1 +
 hw/s3c24xx_memc.c |   70 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 71 insertions(+), 0 deletions(-)
 create mode 100644 hw/s3c24xx_memc.c

diff --git a/Makefile.target b/Makefile.target
index f735105..c5e6402 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -674,6 +674,7 @@ OBJS+= omap_sx1.o palm.o tsc210x.o
 OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 OBJS+= mst_fpga.o mainstone.o
 OBJS+= musicpal.o pflash_cfi02.o
+OBJS+= s3c24xx_memc.o
 OBJS+= framebuffer.o
 CPPFLAGS += -DHAS_AUDIO
 endif
diff --git a/hw/s3c24xx_memc.c b/hw/s3c24xx_memc.c
new file mode 100644
index 0000000..07c0f6d
--- /dev/null
+++ b/hw/s3c24xx_memc.c
@@ -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;
+}
-- 
1.5.4.3

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

* [Qemu-devel] [PATCH 04/15] Peripheral driver for S3C SOC IRQ controller.
  2009-05-06  8:44 [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
                   ` (2 preceding siblings ...)
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 03/15] Peripheral driver for S3C SOC SDRAM controller Vincent Sanders
@ 2009-05-06  8:44 ` Vincent Sanders
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 05/15] Peripheral driver for S3C SOC clock control Vincent Sanders
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Vincent Sanders @ 2009-05-06  8:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Vincent Sanders

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 Makefile.target  |    2 +-
 hw/s3c24xx_irq.c |  200 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 201 insertions(+), 1 deletions(-)
 create mode 100644 hw/s3c24xx_irq.c

diff --git a/Makefile.target b/Makefile.target
index c5e6402..9d6d5fd 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -674,7 +674,7 @@ OBJS+= omap_sx1.o palm.o tsc210x.o
 OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 OBJS+= mst_fpga.o mainstone.o
 OBJS+= musicpal.o pflash_cfi02.o
-OBJS+= s3c24xx_memc.o
+OBJS+= s3c24xx_memc.o s3c24xx_irq.o
 OBJS+= framebuffer.o
 CPPFLAGS += -DHAS_AUDIO
 endif
diff --git a/hw/s3c24xx_irq.c b/hw/s3c24xx_irq.c
new file mode 100644
index 0000000..8084cd0
--- /dev/null
+++ b/hw/s3c24xx_irq.c
@@ -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);
+}
-- 
1.5.4.3

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

* [Qemu-devel] [PATCH 05/15] Peripheral driver for S3C SOC clock control.
  2009-05-06  8:44 [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
                   ` (3 preceding siblings ...)
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 04/15] Peripheral driver for S3C SOC IRQ controller Vincent Sanders
@ 2009-05-06  8:44 ` Vincent Sanders
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 06/15] Peripheral driver for S3C SOC timers Vincent Sanders
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Vincent Sanders @ 2009-05-06  8:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Vincent Sanders

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 Makefile.target     |    2 +-
 hw/s3c24xx_clkcon.c |  100 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 101 insertions(+), 1 deletions(-)
 create mode 100644 hw/s3c24xx_clkcon.c

diff --git a/Makefile.target b/Makefile.target
index 9d6d5fd..f5594fb 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -674,7 +674,7 @@ OBJS+= omap_sx1.o palm.o tsc210x.o
 OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 OBJS+= mst_fpga.o mainstone.o
 OBJS+= musicpal.o pflash_cfi02.o
-OBJS+= s3c24xx_memc.o s3c24xx_irq.o
+OBJS+= s3c24xx_memc.o s3c24xx_irq.o s3c24xx_clkcon.o
 OBJS+= framebuffer.o
 CPPFLAGS += -DHAS_AUDIO
 endif
diff --git a/hw/s3c24xx_clkcon.c b/hw/s3c24xx_clkcon.c
new file mode 100644
index 0000000..bdae2c2
--- /dev/null
+++ b/hw/s3c24xx_clkcon.c
@@ -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;
+
+}
-- 
1.5.4.3

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

* [Qemu-devel] [PATCH 06/15] Peripheral driver for S3C SOC timers.
  2009-05-06  8:44 [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
                   ` (4 preceding siblings ...)
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 05/15] Peripheral driver for S3C SOC clock control Vincent Sanders
@ 2009-05-06  8:44 ` Vincent Sanders
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 07/15] Peripheral driver for S3C SOC Serial ports Vincent Sanders
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Vincent Sanders @ 2009-05-06  8:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Vincent Sanders

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 Makefile.target     |    2 +-
 hw/s3c24xx_timers.c |  136 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 137 insertions(+), 1 deletions(-)
 create mode 100644 hw/s3c24xx_timers.c

diff --git a/Makefile.target b/Makefile.target
index f5594fb..2b35da7 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -674,7 +674,7 @@ OBJS+= omap_sx1.o palm.o tsc210x.o
 OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 OBJS+= mst_fpga.o mainstone.o
 OBJS+= musicpal.o pflash_cfi02.o
-OBJS+= s3c24xx_memc.o s3c24xx_irq.o s3c24xx_clkcon.o
+OBJS+= s3c24xx_memc.o s3c24xx_irq.o s3c24xx_clkcon.o s3c24xx_timers.o
 OBJS+= framebuffer.o
 CPPFLAGS += -DHAS_AUDIO
 endif
diff --git a/hw/s3c24xx_timers.c b/hw/s3c24xx_timers.c
new file mode 100644
index 0000000..073c2f8
--- /dev/null
+++ b/hw/s3c24xx_timers.c
@@ -0,0 +1,136 @@
+/* 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);
+}
-- 
1.5.4.3

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

* [Qemu-devel] [PATCH 07/15] Peripheral driver for S3C SOC Serial ports.
  2009-05-06  8:44 [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
                   ` (5 preceding siblings ...)
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 06/15] Peripheral driver for S3C SOC timers Vincent Sanders
@ 2009-05-06  8:44 ` Vincent Sanders
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 08/15] Peripheral driver for S3C SOC real time clock Vincent Sanders
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Vincent Sanders @ 2009-05-06  8:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Vincent Sanders

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 Makefile.target     |    1 +
 hw/s3c24xx_serial.c |  266 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 267 insertions(+), 0 deletions(-)
 create mode 100644 hw/s3c24xx_serial.c

diff --git a/Makefile.target b/Makefile.target
index 2b35da7..679c9e7 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -675,6 +675,7 @@ OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 OBJS+= mst_fpga.o mainstone.o
 OBJS+= musicpal.o pflash_cfi02.o
 OBJS+= s3c24xx_memc.o s3c24xx_irq.o s3c24xx_clkcon.o s3c24xx_timers.o
+OBJS+= s3c24xx_serial.o
 OBJS+= framebuffer.o
 CPPFLAGS += -DHAS_AUDIO
 endif
diff --git a/hw/s3c24xx_serial.c b/hw/s3c24xx_serial.c
new file mode 100644
index 0000000..7e84fe1
--- /dev/null
+++ b/hw/s3c24xx_serial.c
@@ -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);
+    }
+}
-- 
1.5.4.3

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

* [Qemu-devel] [PATCH 08/15] Peripheral driver for S3C SOC real time clock.
  2009-05-06  8:44 [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
                   ` (6 preceding siblings ...)
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 07/15] Peripheral driver for S3C SOC Serial ports Vincent Sanders
@ 2009-05-06  8:44 ` Vincent Sanders
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 09/15] Peripheral driver for S3C SOC general purpose I/O Vincent Sanders
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Vincent Sanders @ 2009-05-06  8:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Vincent Sanders

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 Makefile.target  |    2 +-
 hw/s3c24xx_rtc.c |  123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 124 insertions(+), 1 deletions(-)
 create mode 100644 hw/s3c24xx_rtc.c

diff --git a/Makefile.target b/Makefile.target
index 679c9e7..02bb9f1 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -675,7 +675,7 @@ OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 OBJS+= mst_fpga.o mainstone.o
 OBJS+= musicpal.o pflash_cfi02.o
 OBJS+= s3c24xx_memc.o s3c24xx_irq.o s3c24xx_clkcon.o s3c24xx_timers.o
-OBJS+= s3c24xx_serial.o
+OBJS+= s3c24xx_serial.o s3c24xx_rtc.o
 OBJS+= framebuffer.o
 CPPFLAGS += -DHAS_AUDIO
 endif
diff --git a/hw/s3c24xx_rtc.c b/hw/s3c24xx_rtc.c
new file mode 100644
index 0000000..2c799fd
--- /dev/null
+++ b/hw/s3c24xx_rtc.c
@@ -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;
+}
-- 
1.5.4.3

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

* [Qemu-devel] [PATCH 09/15] Peripheral driver for S3C SOC general purpose I/O
  2009-05-06  8:44 [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
                   ` (7 preceding siblings ...)
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 08/15] Peripheral driver for S3C SOC real time clock Vincent Sanders
@ 2009-05-06  8:44 ` Vincent Sanders
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 10/15] Peripheral driver for S3C SOC I2C controller Vincent Sanders
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Vincent Sanders @ 2009-05-06  8:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Vincent Sanders

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 Makefile.target   |    2 +-
 hw/s3c24xx_gpio.c |  190 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 191 insertions(+), 1 deletions(-)
 create mode 100644 hw/s3c24xx_gpio.c

diff --git a/Makefile.target b/Makefile.target
index 02bb9f1..d869171 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -675,7 +675,7 @@ OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 OBJS+= mst_fpga.o mainstone.o
 OBJS+= musicpal.o pflash_cfi02.o
 OBJS+= s3c24xx_memc.o s3c24xx_irq.o s3c24xx_clkcon.o s3c24xx_timers.o
-OBJS+= s3c24xx_serial.o s3c24xx_rtc.o
+OBJS+= s3c24xx_serial.o s3c24xx_rtc.o s3c24xx_gpio.o
 OBJS+= framebuffer.o
 CPPFLAGS += -DHAS_AUDIO
 endif
diff --git a/hw/s3c24xx_gpio.c b/hw/s3c24xx_gpio.c
new file mode 100644
index 0000000..372cfed
--- /dev/null
+++ b/hw/s3c24xx_gpio.c
@@ -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);
+}
-- 
1.5.4.3

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

* [Qemu-devel] [PATCH 10/15] Peripheral driver for S3C SOC I2C controller.
  2009-05-06  8:44 [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
                   ` (8 preceding siblings ...)
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 09/15] Peripheral driver for S3C SOC general purpose I/O Vincent Sanders
@ 2009-05-06  8:44 ` Vincent Sanders
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 11/15] Peripheral driver for S3C SOC LCD controller Vincent Sanders
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Vincent Sanders @ 2009-05-06  8:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Vincent Sanders

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 Makefile.target  |    2 +-
 hw/s3c24xx_iic.c |  321 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 322 insertions(+), 1 deletions(-)
 create mode 100644 hw/s3c24xx_iic.c

diff --git a/Makefile.target b/Makefile.target
index d869171..4cf323b 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -675,7 +675,7 @@ OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
 OBJS+= mst_fpga.o mainstone.o
 OBJS+= musicpal.o pflash_cfi02.o
 OBJS+= s3c24xx_memc.o s3c24xx_irq.o s3c24xx_clkcon.o s3c24xx_timers.o
-OBJS+= s3c24xx_serial.o s3c24xx_rtc.o s3c24xx_gpio.o
+OBJS+= s3c24xx_serial.o s3c24xx_rtc.o s3c24xx_gpio.o s3c24xx_iic.o
 OBJS+= framebuffer.o
 CPPFLAGS += -DHAS_AUDIO
 endif
diff --git a/hw/s3c24xx_iic.c b/hw/s3c24xx_iic.c
new file mode 100644
index 0000000..b9b5fff
--- /dev/null
+++ b/hw/s3c24xx_iic.c
@@ -0,0 +1,321 @@
+/* hw/s3c24xx_iic.c
+ *
+ * Samsung S3C24XX i2c peripheral 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;
+}
-- 
1.5.4.3

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

* [Qemu-devel] [PATCH 11/15] Peripheral driver for S3C SOC LCD controller
  2009-05-06  8:44 [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
                   ` (9 preceding siblings ...)
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 10/15] Peripheral driver for S3C SOC I2C controller Vincent Sanders
@ 2009-05-06  8:44 ` Vincent Sanders
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 12/15] Peripheral driver for S3C SOC NAND controller Vincent Sanders
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Vincent Sanders @ 2009-05-06  8:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Vincent Sanders

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 Makefile.target       |    1 +
 hw/s3c24xx_lcd.c      |  560 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/s3c24xx_template.h |  266 +++++++++++++++++++++++
 3 files changed, 827 insertions(+), 0 deletions(-)
 create mode 100644 hw/s3c24xx_lcd.c
 create mode 100644 hw/s3c24xx_template.h

diff --git a/Makefile.target b/Makefile.target
index 4cf323b..b5dae70 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -676,6 +676,7 @@ OBJS+= mst_fpga.o mainstone.o
 OBJS+= musicpal.o pflash_cfi02.o
 OBJS+= s3c24xx_memc.o s3c24xx_irq.o s3c24xx_clkcon.o s3c24xx_timers.o
 OBJS+= s3c24xx_serial.o s3c24xx_rtc.o s3c24xx_gpio.o s3c24xx_iic.o
+OBJS+= s3c24xx_lcd.o
 OBJS+= framebuffer.o
 CPPFLAGS += -DHAS_AUDIO
 endif
diff --git a/hw/s3c24xx_lcd.c b/hw/s3c24xx_lcd.c
new file mode 100644
index 0000000..bb74531
--- /dev/null
+++ b/hw/s3c24xx_lcd.c
@@ -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 --git a/hw/s3c24xx_template.h b/hw/s3c24xx_template.h
new file mode 100644
index 0000000..f6cbf44
--- /dev/null
+++ b/hw/s3c24xx_template.h
@@ -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
-- 
1.5.4.3

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

* [Qemu-devel] [PATCH 12/15] Peripheral driver for S3C SOC NAND controller
  2009-05-06  8:44 [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
                   ` (10 preceding siblings ...)
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 11/15] Peripheral driver for S3C SOC LCD controller Vincent Sanders
@ 2009-05-06  8:44 ` Vincent Sanders
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 13/15] S3C2410 SOC implementation using S3C peripheral blocks Vincent Sanders
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Vincent Sanders @ 2009-05-06  8:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Vincent Sanders

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 Makefile.target   |    2 +-
 hw/s3c24xx_nand.c |  136 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 137 insertions(+), 1 deletions(-)
 create mode 100644 hw/s3c24xx_nand.c

diff --git a/Makefile.target b/Makefile.target
index b5dae70..67226cc 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -676,7 +676,7 @@ OBJS+= mst_fpga.o mainstone.o
 OBJS+= musicpal.o pflash_cfi02.o
 OBJS+= s3c24xx_memc.o s3c24xx_irq.o s3c24xx_clkcon.o s3c24xx_timers.o
 OBJS+= s3c24xx_serial.o s3c24xx_rtc.o s3c24xx_gpio.o s3c24xx_iic.o
-OBJS+= s3c24xx_lcd.o
+OBJS+= s3c24xx_lcd.o s3c24xx_nand.o
 OBJS+= framebuffer.o
 CPPFLAGS += -DHAS_AUDIO
 endif
diff --git a/hw/s3c24xx_nand.c b/hw/s3c24xx_nand.c
new file mode 100644
index 0000000..e4a8a9e
--- /dev/null
+++ b/hw/s3c24xx_nand.c
@@ -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;
+}
-- 
1.5.4.3

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

* [Qemu-devel] [PATCH 13/15] S3C2410 SOC implementation using S3C peripheral blocks.
  2009-05-06  8:44 [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
                   ` (11 preceding siblings ...)
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 12/15] Peripheral driver for S3C SOC NAND controller Vincent Sanders
@ 2009-05-06  8:44 ` Vincent Sanders
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 14/15] S3C2440 Implementation using S3C periperals Vincent Sanders
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Vincent Sanders @ 2009-05-06  8:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Vincent Sanders

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 Makefile.target |    1 +
 hw/s3c2410x.c   |  117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/s3c2410x.h   |   30 ++++++++++++++
 3 files changed, 148 insertions(+), 0 deletions(-)
 create mode 100644 hw/s3c2410x.c
 create mode 100644 hw/s3c2410x.h

diff --git a/Makefile.target b/Makefile.target
index 67226cc..4384d8c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -677,6 +677,7 @@ OBJS+= musicpal.o pflash_cfi02.o
 OBJS+= s3c24xx_memc.o s3c24xx_irq.o s3c24xx_clkcon.o s3c24xx_timers.o
 OBJS+= s3c24xx_serial.o s3c24xx_rtc.o s3c24xx_gpio.o s3c24xx_iic.o
 OBJS+= s3c24xx_lcd.o s3c24xx_nand.o
+OBJS+= s3c2410x.o
 OBJS+= framebuffer.o
 CPPFLAGS += -DHAS_AUDIO
 endif
diff --git a/hw/s3c2410x.c b/hw/s3c2410x.c
new file mode 100644
index 0000000..dbb0cab
--- /dev/null
+++ b/hw/s3c2410x.c
@@ -0,0 +1,117 @@
+/* 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 --git a/hw/s3c2410x.h b/hw/s3c2410x.h
new file mode 100644
index 0000000..ca68cd1
--- /dev/null
+++ b/hw/s3c2410x.h
@@ -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 */
-- 
1.5.4.3

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

* [Qemu-devel] [PATCH 14/15] S3C2440 Implementation using S3C periperals.
  2009-05-06  8:44 [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
                   ` (12 preceding siblings ...)
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 13/15] S3C2410 SOC implementation using S3C peripheral blocks Vincent Sanders
@ 2009-05-06  8:44 ` Vincent Sanders
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 15/15] Add bast and smdk2410 boards which use S3C2410 SOC Vincent Sanders
  2009-05-14  8:58 ` [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
  15 siblings, 0 replies; 23+ messages in thread
From: Vincent Sanders @ 2009-05-06  8:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Vincent Sanders

Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
 Makefile.target |    2 +-
 hw/s3c2440x.c   |  116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/s3c2440x.h   |   30 ++++++++++++++
 3 files changed, 147 insertions(+), 1 deletions(-)
 create mode 100644 hw/s3c2440x.c
 create mode 100644 hw/s3c2440x.h

diff --git a/Makefile.target b/Makefile.target
index 4384d8c..b8074ad 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -677,7 +677,7 @@ OBJS+= musicpal.o pflash_cfi02.o
 OBJS+= s3c24xx_memc.o s3c24xx_irq.o s3c24xx_clkcon.o s3c24xx_timers.o
 OBJS+= s3c24xx_serial.o s3c24xx_rtc.o s3c24xx_gpio.o s3c24xx_iic.o
 OBJS+= s3c24xx_lcd.o s3c24xx_nand.o
-OBJS+= s3c2410x.o
+OBJS+= s3c2410x.o s3c2440x.o
 OBJS+= framebuffer.o
 CPPFLAGS += -DHAS_AUDIO
 endif
diff --git a/hw/s3c2440x.c b/hw/s3c2440x.c
new file mode 100644
index 0000000..d99b381
--- /dev/null
+++ b/hw/s3c2440x.c
@@ -0,0 +1,116 @@
+/* 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 --git a/hw/s3c2440x.h b/hw/s3c2440x.h
new file mode 100644
index 0000000..86191aa
--- /dev/null
+++ b/hw/s3c2440x.h
@@ -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 */
-- 
1.5.4.3

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

* [Qemu-devel] [PATCH 15/15] Add bast and smdk2410 boards which use S3C2410 SOC
  2009-05-06  8:44 [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
                   ` (13 preceding siblings ...)
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 14/15] S3C2440 Implementation using S3C periperals Vincent Sanders
@ 2009-05-06  8:44 ` Vincent Sanders
  2009-05-14 12:35   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-05-14  8:58 ` [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
  15 siblings, 1 reply; 23+ messages in thread
From: Vincent Sanders @ 2009-05-06  8:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Vincent Sanders

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

diff --git a/Makefile.target b/Makefile.target
index b8074ad..e6f74b3 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -678,6 +678,7 @@ OBJS+= s3c24xx_memc.o s3c24xx_irq.o s3c24xx_clkcon.o s3c24xx_timers.o
 OBJS+= s3c24xx_serial.o s3c24xx_rtc.o s3c24xx_gpio.o s3c24xx_iic.o
 OBJS+= s3c24xx_lcd.o s3c24xx_nand.o
 OBJS+= s3c2410x.o s3c2440x.o
+OBJS+= bast.o smdk2410.o
 OBJS+= framebuffer.o
 CPPFLAGS += -DHAS_AUDIO
 endif
diff --git a/hw/bast.c b/hw/bast.c
new file mode 100644
index 0000000..1725de4
--- /dev/null
+++ b/hw/bast.c
@@ -0,0 +1,187 @@
+/* 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_RO_BASE CPU_S3C2410X_CS0
+#define BAST_NOR_RW_BASE (CPU_S3C2410X_CS1 + 0x4000000)
+#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;
+    ram_addr_t flash_mem;
+    BlockDriverState *flash_bds = NULL;
+
+    /* ensure memory is limited to 256MB */
+    if (_ram_size > (256 * MEGA * BYTE))
+        _ram_size = 256 * MEGA * BYTE;
+    ram_size = _ram_size;
+
+    /* 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_RO_BASE;
+
+    /* allocate storage for board state */
+    stcb = malloc(sizeof(STCBState));
+
+    /* initialise SOC */
+    stcb->soc = s3c2410x_init(ram_size);
+
+    /* Register the NOR flash ROM */
+    flash_mem = qemu_ram_alloc(BAST_NOR_SIZE);
+
+    /* Read only ROM type mapping */
+    cpu_register_physical_memory(BAST_NOR_RO_BASE,
+                                 BAST_NOR_SIZE,
+                                 flash_mem | IO_MEM_ROM);
+
+    /* Aquire flash contents and register pflash device */
+    index = drive_get_index(IF_PFLASH, 0, 0);
+    if (index != -1) {
+        /* load from specified flash device */
+        flash_bds = drives_table[index].bdrv;
+    } else {
+        /* Try and load default bootloader image */
+        char buf[PATH_MAX];
+
+        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+        ret = load_image_targphys(buf, BAST_NOR_RO_BASE, BAST_NOR_SIZE);
+    }
+    pflash_cfi02_register(BAST_NOR_RW_BASE, flash_mem, flash_bds,
+                          65536, 32, 1, 2,
+                          0x00BF, 0x234B, 0x0000, 0x0000, 0x5555, 0x2AAA);
+
+
+    /* if kernel is given, boot that directly */
+    if (kernel_filename != NULL) {
+        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 --git a/hw/boards.h b/hw/boards.h
index 5611d2c..327b2b5 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -128,4 +128,10 @@ extern QEMUMachine musicpal_machine;
 /* tosa.c */
 extern QEMUMachine tosapda_machine;
 
+/* bast.c */
+extern QEMUMachine bast_machine;
+
+/* smdk2410.c */
+extern QEMUMachine smdk2410_machine;
+
 #endif
diff --git a/hw/smdk2410.c b/hw/smdk2410.c
new file mode 100644
index 0000000..371f2aa
--- /dev/null
+++ b/hw/smdk2410.c
@@ -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 --git a/target-arm/machine.c b/target-arm/machine.c
index 323bace..ed97185 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -7,6 +7,8 @@ void register_machines(void)
     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);
-- 
1.5.4.3

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

* Re: [Qemu-devel] Add ARM S3C SOC core, drivers and boards
  2009-05-06  8:44 [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
                   ` (14 preceding siblings ...)
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 15/15] Add bast and smdk2410 boards which use S3C2410 SOC Vincent Sanders
@ 2009-05-14  8:58 ` Vincent Sanders
  15 siblings, 0 replies; 23+ messages in thread
From: Vincent Sanders @ 2009-05-14  8:58 UTC (permalink / raw)
  To: qemu-devel

Its been over a week since I posted this series. I know everyones busy
but I was wondering what I need to do to progress the inclusion of
this series? 

I have addressed all the issues raised previously, and this series is
now three years old and I would like to see it on the road to being
merged.

-- 
Regards Vincent

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

* Re: [Qemu-devel] [PATCH 15/15] Add bast and smdk2410 boards which use S3C2410 SOC
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 15/15] Add bast and smdk2410 boards which use S3C2410 SOC Vincent Sanders
@ 2009-05-14 12:35   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-05-15  9:41     ` Vincent Sanders
  0 siblings, 1 reply; 23+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-05-14 12:35 UTC (permalink / raw)
  To: Vincent Sanders; +Cc: qemu-devel

On 09:44 Wed 06 May     , Vincent Sanders wrote:
> Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
> ---
tks for the pflash support forhe bast
is it possible to have the same on the smdk2410?
 
IIRC there is a 8Mib

Best Regards,
J.

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

* Re: [Qemu-devel] [PATCH 15/15] Add bast and smdk2410 boards which use S3C2410 SOC
  2009-05-14 12:35   ` Jean-Christophe PLAGNIOL-VILLARD
@ 2009-05-15  9:41     ` Vincent Sanders
  2009-05-15 19:52       ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 1 reply; 23+ messages in thread
From: Vincent Sanders @ 2009-05-15  9:41 UTC (permalink / raw)
  To: qemu-devel

On Thu, May 14, 2009 at 02:35:19PM +0200, Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 09:44 Wed 06 May     , Vincent Sanders wrote:
> > Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
> > ---
> tks for the pflash support forhe bast
> is it possible to have the same on the smdk2410?
>  
> IIRC there is a 8Mib

I would, of course, be happy to accomodate. However I dont have data
on where the writable flash copy is mapped.

The s3c2410 chip select 0 (where the NOR is booted from) has no write
line so a second writable mapping is required (hence the second
mapping on the bast).

It may turn out the flash cannot be reprogramed with the CPU and the
external JTAG boundry scan must be used. If this is the case it really
is a ROM mapping from an emulation POV. 

If anyone can provide information on if/where the smdk2410 writable
flash area is I will gladly add it.

> 
> Best Regards,
> J.
> 
> 

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

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

* Re: [Qemu-devel] [PATCH 15/15] Add bast and smdk2410 boards which use S3C2410 SOC
  2009-05-15  9:41     ` Vincent Sanders
@ 2009-05-15 19:52       ` Jean-Christophe PLAGNIOL-VILLARD
  2009-05-15 20:29         ` Ben Dooks
  0 siblings, 1 reply; 23+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-05-15 19:52 UTC (permalink / raw)
  To: Vincent Sanders; +Cc: qemu-devel, Ben Dooks

On 10:41 Fri 15 May     , Vincent Sanders wrote:
> On Thu, May 14, 2009 at 02:35:19PM +0200, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > On 09:44 Wed 06 May     , Vincent Sanders wrote:
> > > Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
> > > ---
> > tks for the pflash support forhe bast
> > is it possible to have the same on the smdk2410?
> >  
> > IIRC there is a 8Mib
> 
> I would, of course, be happy to accomodate. However I dont have data
> on where the writable flash copy is mapped.
> 
> The s3c2410 chip select 0 (where the NOR is booted from) has no write
> line so a second writable mapping is required (hence the second
> mapping on the bast).
> 
> It may turn out the flash cannot be reprogramed with the CPU and the
> external JTAG boundry scan must be used. If this is the case it really
> is a ROM mapping from an emulation POV. 
> 
> If anyone can provide information on if/where the smdk2410 writable
> flash area is I will gladly add it.
Based on u-boot code
there is 2 version of the boards
one with a 8Mbit AMD flash
and an other one with a 4Mbit AMD flash

map at 0x00000000
and writeable as the u-boot env is stored at 0xF0000 and 0x70000

Ben could maybe confirm us

Best Regards,
J.

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

* Re: [Qemu-devel] [PATCH 15/15] Add bast and smdk2410 boards which use S3C2410 SOC
  2009-05-15 19:52       ` Jean-Christophe PLAGNIOL-VILLARD
@ 2009-05-15 20:29         ` Ben Dooks
  0 siblings, 0 replies; 23+ messages in thread
From: Ben Dooks @ 2009-05-15 20:29 UTC (permalink / raw)
  To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: Vincent Sanders, qemu-devel, Ben Dooks

On Fri, May 15, 2009 at 09:52:57PM +0200, Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 10:41 Fri 15 May     , Vincent Sanders wrote:
> > On Thu, May 14, 2009 at 02:35:19PM +0200, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > > On 09:44 Wed 06 May     , Vincent Sanders wrote:
> > > > Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
> > > > ---
> > > tks for the pflash support forhe bast
> > > is it possible to have the same on the smdk2410?
> > >  
> > > IIRC there is a 8Mib
> > 
> > I would, of course, be happy to accomodate. However I dont have data
> > on where the writable flash copy is mapped.

I've not seen anything in the UBoot sources, and having looked at the
schematic there is an link option to change the ROM nCS from nGCS0 to
nGCS1. However looking at the uboot sources it seems to only use the
nGCS0 addressing.
 
> > The s3c2410 chip select 0 (where the NOR is booted from) has no write
> > line so a second writable mapping is required (hence the second
> > mapping on the bast).
> > 
> > It may turn out the flash cannot be reprogramed with the CPU and the
> > external JTAG boundry scan must be used. If this is the case it really
> > is a ROM mapping from an emulation POV. 
> > 
> > If anyone can provide information on if/where the smdk2410 writable
> > flash area is I will gladly add it.
> Based on u-boot code
> there is 2 version of the boards
> one with a 8Mbit AMD flash
> and an other one with a 4Mbit AMD flash
> 
> map at 0x00000000
> and writeable as the u-boot env is stored at 0xF0000 and 0x70000
> 
> Ben could maybe confirm us

The manual says that nGCS0 is read-only, but unfortunately I've not
got an SMDK2410 available to verify that the manual is correct in
this respect. I might still have a board with an S3C2410 on to see
if this can be reproduced by experimentation over the weekend.
 
> Best Regards,
> J.

-- 
-- 
Ben

Q:      What's a light-year?
A:      One-third less calories than a regular year.

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

* Re: [Qemu-devel] [PATCH 02/15] S3C system on chip integrated peripheral device state header
  2009-05-06  8:44 ` [Qemu-devel] [PATCH 02/15] S3C system on chip integrated peripheral device state header Vincent Sanders
@ 2009-05-15 22:33   ` Jean-Christophe PLAGNIOL-VILLARD
  2009-05-23 16:39     ` Vincent Sanders
  0 siblings, 1 reply; 23+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-05-15 22:33 UTC (permalink / raw)
  To: Vincent Sanders; +Cc: qemu-devel

> +    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];
it will be better to define a struct with the timers_reg content
same with the other arry
> +    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;
Best Regards,
J.

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

* Re: [Qemu-devel] [PATCH 02/15] S3C system on chip integrated peripheral device state header
  2009-05-15 22:33   ` Jean-Christophe PLAGNIOL-VILLARD
@ 2009-05-23 16:39     ` Vincent Sanders
  0 siblings, 0 replies; 23+ messages in thread
From: Vincent Sanders @ 2009-05-23 16:39 UTC (permalink / raw)
  To: qemu-devel

On Sat, May 16, 2009 at 12:33:12AM +0200, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > +    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];
> it will be better to define a struct with the timers_reg content
> same with the other arry

I had a good hard look at this and decided you were right. I have
restructured all the SOC devices to be completely self contained. I
just posted the new series against git head, it looks a fair bit
neater.

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

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

end of thread, other threads:[~2009-05-23 16:39 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-06  8:44 [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders
2009-05-06  8:44 ` [Qemu-devel] [PATCH 01/15] Add ARM 920T CPU identifier Vincent Sanders
2009-05-06  8:44 ` [Qemu-devel] [PATCH 02/15] S3C system on chip integrated peripheral device state header Vincent Sanders
2009-05-15 22:33   ` Jean-Christophe PLAGNIOL-VILLARD
2009-05-23 16:39     ` Vincent Sanders
2009-05-06  8:44 ` [Qemu-devel] [PATCH 03/15] Peripheral driver for S3C SOC SDRAM controller Vincent Sanders
2009-05-06  8:44 ` [Qemu-devel] [PATCH 04/15] Peripheral driver for S3C SOC IRQ controller Vincent Sanders
2009-05-06  8:44 ` [Qemu-devel] [PATCH 05/15] Peripheral driver for S3C SOC clock control Vincent Sanders
2009-05-06  8:44 ` [Qemu-devel] [PATCH 06/15] Peripheral driver for S3C SOC timers Vincent Sanders
2009-05-06  8:44 ` [Qemu-devel] [PATCH 07/15] Peripheral driver for S3C SOC Serial ports Vincent Sanders
2009-05-06  8:44 ` [Qemu-devel] [PATCH 08/15] Peripheral driver for S3C SOC real time clock Vincent Sanders
2009-05-06  8:44 ` [Qemu-devel] [PATCH 09/15] Peripheral driver for S3C SOC general purpose I/O Vincent Sanders
2009-05-06  8:44 ` [Qemu-devel] [PATCH 10/15] Peripheral driver for S3C SOC I2C controller Vincent Sanders
2009-05-06  8:44 ` [Qemu-devel] [PATCH 11/15] Peripheral driver for S3C SOC LCD controller Vincent Sanders
2009-05-06  8:44 ` [Qemu-devel] [PATCH 12/15] Peripheral driver for S3C SOC NAND controller Vincent Sanders
2009-05-06  8:44 ` [Qemu-devel] [PATCH 13/15] S3C2410 SOC implementation using S3C peripheral blocks Vincent Sanders
2009-05-06  8:44 ` [Qemu-devel] [PATCH 14/15] S3C2440 Implementation using S3C periperals Vincent Sanders
2009-05-06  8:44 ` [Qemu-devel] [PATCH 15/15] Add bast and smdk2410 boards which use S3C2410 SOC Vincent Sanders
2009-05-14 12:35   ` Jean-Christophe PLAGNIOL-VILLARD
2009-05-15  9:41     ` Vincent Sanders
2009-05-15 19:52       ` Jean-Christophe PLAGNIOL-VILLARD
2009-05-15 20:29         ` Ben Dooks
2009-05-14  8:58 ` [Qemu-devel] Add ARM S3C SOC core, drivers and boards Vincent Sanders

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.