qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] Add Apollon (OMAP24xx) board support (take #2)


From: Kyungmin Park
Subject: [Qemu-devel] [PATCH] Add Apollon (OMAP24xx) board support (take #2)
Date: Mon, 28 Jul 2008 16:24:03 +0900
User-agent: Mutt/1.5.14 (2007-02-12)

Add apollon (OMAP24xx) board initial support
with board descriptions

Signed-off-by: Kyungmin Park <address@hidden>
---
diff --git a/Makefile.target b/Makefile.target
index ff105c1..2d124e4 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -603,6 +603,7 @@ OBJS+= omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o 
omap_i2c.o
 OBJS+= omap2.o omap_dss.o soc_dma.o
 OBJS+= palm.o tsc210x.o
 OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
+OBJS+= apollon.o
 OBJS+= tsc2005.o
 OBJS+= mst_fpga.o mainstone.o
 OBJS+= musicpal.o pflash_cfi02.o
diff --git a/hw/apollon.c b/hw/apollon.c
new file mode 100644
index 0000000..f3719b0
--- /dev/null
+++ b/hw/apollon.c
@@ -0,0 +1,299 @@
+/*
+ * Samsung Apollon OneNAND board
+ *
+ * Copyright (C) 2008 Samsung Electronics
+ * Written by Kyungmin Park <address@hidden>
+ *
+ * Derived from nseries.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "qemu-common.h"
+#include "sysemu.h"
+#include "omap.h"
+#include "arm-misc.h"
+#include "irq.h"
+#include "console.h"
+#include "boards.h"
+#include "devices.h"
+#include "flash.h"
+#include "hw.h"
+#include "net.h"
+
+/* Samsung apollon support */
+struct apollon_s {
+    struct omap_mpu_state_s *cpu;
+
+    struct {
+        void *opaque;
+        uint32_t (*txrx)(void *opaque, uint32_t value, int len);
+        struct uwire_slave_s *chip;
+    } ts;
+};
+
+/* GPIO pins */
+#define APOLLON_BLIZZARD_RESET_GPIO    30
+#define APOLLON_MMC_CS_GPIO            37
+#define APOLLON_ONENAND_GPIO           72
+#define APOLLON_ETHERNET_GPIO          74
+
+/* Chipselects on GPMC OneNAND interface */
+#define APOLLON_ONENAND_CS             0
+
+static void apollon_mmc_cs_cb(void *opaque, int line, int level)
+{
+    /* TODO: this seems to actually be connected to the menelaus, to
+     * which also both MMC slots connect.  */
+    omap_mmc_enable((struct omap_mmc_s *) opaque, !level);
+
+    printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1);
+}
+
+static void apollon_gpio_setup(struct apollon_s *s)
+{
+    qemu_irq *mmc_cs = qemu_allocate_irqs(apollon_mmc_cs_cb, s->cpu->mmc, 1);
+    omap2_gpio_out_set(s->cpu->gpif, APOLLON_MMC_CS_GPIO, mmc_cs[0]);
+}
+
+static void apollon_onenand_setup(struct apollon_s *s)
+{
+    /* Either ec40xx or ec48xx are OK for the ID */
+    omap_gpmc_attach(s->cpu->gpmc, APOLLON_ONENAND_CS, 0, onenand_base_update,
+                    onenand_base_unmap,
+                    onenand_init(0xec4800, 1,
+                            omap2_gpio_in_get(s->cpu->gpif,
+                                    APOLLON_ONENAND_GPIO)[0]));
+}
+
+/* This task is normally performed by the bootloader.  If we're loading
+ * a kernel directly, we need to set up GPMC mappings ourselves.  */
+static void apollon_gpmc_init(struct apollon_s *s)
+{
+    uint32_t config7 =
+            (0xf << 8) |       /* MASKADDRESS */
+            (1 << 6) |         /* CSVALID */
+            (4 << 0);          /* BASEADDRESS */
+
+    cpu_physical_memory_write(0x6800a078,              /* GPMC_CONFIG7_0 */
+                    (void *) &config7, sizeof(config7));
+
+    /* Set GPMC1 for ethernet at apollon */
+    config7 = 0x00000F40 | (0x08000000 >> 24);
+    cpu_physical_memory_write(0x6800a0a8,              /* GPMC_CONFIG7_1 */
+                    (void *) &config7, sizeof(config7));
+}
+
+/* Setup sequence done by the bootloader */
+static void apollon_boot_init(void *opaque)
+{
+    struct apollon_s *s = (struct apollon_s *) opaque;
+    uint32_t buf;
+
+    /* PRCM setup */
+#define omap_writel(addr, val) \
+    buf = (val);                       \
+    cpu_physical_memory_write(addr, (void *) &buf, sizeof(buf))
+
+    omap_writel(0x48008060, 0x41);             /* PRCM_CLKSRC_CTRL */
+    omap_writel(0x48008070, 1);                        /* PRCM_CLKOUT_CTRL */
+    omap_writel(0x48008078, 0);                        /* PRCM_CLKEMUL_CTRL */
+    omap_writel(0x48008090, 0);                        /* PRCM_VOLTSETUP */
+    omap_writel(0x48008094, 0);                        /* PRCM_CLKSSETUP */
+    omap_writel(0x48008098, 0);                        /* PRCM_POLCTRL */
+    omap_writel(0x48008140, 2);                        /* CM_CLKSEL_MPU */
+    omap_writel(0x48008148, 0);                        /* CM_CLKSTCTRL_MPU */
+    omap_writel(0x48008158, 1);                        /* RM_RSTST_MPU */
+    omap_writel(0x480081c8, 0x15);             /* PM_WKDEP_MPU */
+    omap_writel(0x480081d4, 0x1d4);            /* PM_EVGENCTRL_MPU */
+    omap_writel(0x480081d8, 0);                        /* PM_EVEGENONTIM_MPU */
+    omap_writel(0x480081dc, 0);                        /* PM_EVEGENOFFTIM_MPU 
*/
+    omap_writel(0x480081e0, 0xc);              /* PM_PWSTCTRL_MPU */
+    omap_writel(0x48008200, 0x047e7ff7);       /* CM_FCLKEN1_CORE */
+    omap_writel(0x48008204, 0x00000004);       /* CM_FCLKEN2_CORE */
+    omap_writel(0x48008210, 0x047e7ff1);       /* CM_ICLKEN1_CORE */
+    omap_writel(0x48008214, 0x00000004);       /* CM_ICLKEN2_CORE */
+    omap_writel(0x4800821c, 0x00000000);       /* CM_ICLKEN4_CORE */
+    omap_writel(0x48008230, 0);                        /* CM_AUTOIDLE1_CORE */
+    omap_writel(0x48008234, 0);                        /* CM_AUTOIDLE2_CORE */
+    omap_writel(0x48008238, 7);                        /* CM_AUTOIDLE3_CORE */
+    omap_writel(0x4800823c, 0);                        /* CM_AUTOIDLE4_CORE */
+    omap_writel(0x48008240, 0x04360626);       /* CM_CLKSEL1_CORE */
+    omap_writel(0x48008244, 0x00000014);       /* CM_CLKSEL2_CORE */
+    omap_writel(0x48008248, 0);                        /* CM_CLKSTCTRL_CORE */
+    omap_writel(0x48008300, 0x00000000);       /* CM_FCLKEN_GFX */
+    omap_writel(0x48008310, 0x00000000);       /* CM_ICLKEN_GFX */
+    omap_writel(0x48008340, 0x00000001);       /* CM_CLKSEL_GFX */
+    omap_writel(0x48008400, 0x00000004);       /* CM_FCLKEN_WKUP */
+    omap_writel(0x48008410, 0x00000004);       /* CM_ICLKEN_WKUP */
+    omap_writel(0x48008440, 0x00000000);       /* CM_CLKSEL_WKUP */
+    omap_writel(0x48008500, 0x000000cf);       /* CM_CLKEN_PLL */
+    omap_writel(0x48008530, 0x0000000c);       /* CM_AUTOIDLE_PLL */
+    omap_writel(0x48008540,                    /* CM_CLKSEL1_PLL */
+                    (0x78 << 12) | (6 << 8));
+    omap_writel(0x48008544, 2);                        /* CM_CLKSEL2_PLL */
+
+    /* GPMC setup */
+    apollon_gpmc_init(s);
+
+    /* CPU setup */
+    s->cpu->env->regs[15] = s->cpu->env->boot_info->loader_start;
+    s->cpu->env->GE = 0x5;
+}
+
+static struct omap_partition_info_s {
+    uint32_t offset;
+    uint32_t size;
+    int mask;
+    const char *name;
+} apollon_part_info[] = {
+    { 0x00000000, 0x00020000, 0x3, "bootloader" },
+    { 0x00020000, 0x00020000, 0x0, "params" },
+    { 0x00040000, 0x00200000, 0x0, "kernel" },
+    { 0x00240000, 0x01000000, 0x3, "rootfs" },
+    { 0x01240000, 0x0f000000, 0x3, "fs" },
+
+    { 0, 0, 0, 0 }
+};
+
+static int apollon_atag_setup(struct arm_boot_info *info, void *p)
+{
+    uint16_t *w;
+    uint32_t *l;
+    struct omap_partition_info_s *partition;
+
+    w = p;
+
+    stw_raw(w ++, OMAP_TAG_UART);              /* u16 tag */
+    stw_raw(w ++, 4);                          /* u16 len */
+    stw_raw(w ++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
+    w ++;
+
+    stw_raw(w ++, OMAP_TAG_MMC);               /* u16 tag */
+    stw_raw(w ++, 16);                         /* u16 len */
+    stw_raw(w ++, 0xf);                                /* unsigned flags */
+    stw_raw(w ++, -1);                         /* s16 power_pin */
+    stw_raw(w ++, -1);                         /* s16 switch_pin */
+    stw_raw(w ++, -1);                         /* s16 wp_pin */
+    stw_raw(w ++, 0);                          /* unsigned flags */
+    stw_raw(w ++, 0);                          /* s16 power_pin */
+    stw_raw(w ++, 0);                          /* s16 switch_pin */
+    stw_raw(w ++, 0);                          /* s16 wp_pin */
+
+    w ++;
+
+    partition = apollon_part_info;
+    for (; partition->name; partition ++) {
+        stw_raw(w ++, OMAP_TAG_PARTITION);     /* u16 tag */
+        stw_raw(w ++, 28);                     /* u16 len */
+        strcpy((void *) w, partition->name);   /* char name[16] */
+        l = (void *) (w + 8);
+        stl_raw(l ++, partition->size);                /* unsigned int size */
+        stl_raw(l ++, partition->offset);      /* unsigned int offset */
+        stl_raw(l ++, partition->mask);                /* unsigned int 
mask_flags */
+        w = (void *) l;
+    }
+
+    stw_raw(w ++, OMAP_TAG_BOOT_REASON);       /* u16 tag */
+    stw_raw(w ++, 12);                         /* u16 len */
+#if 0
+    strcpy((void *) w, "por");                 /* char reason_str[12] */
+    strcpy((void *) w, "charger");             /* char reason_str[12] */
+    strcpy((void *) w, "32wd_to");             /* char reason_str[12] */
+    strcpy((void *) w, "sw_rst");              /* char reason_str[12] */
+    strcpy((void *) w, "mbus");                        /* char reason_str[12] 
*/
+    strcpy((void *) w, "unknown");             /* char reason_str[12] */
+    strcpy((void *) w, "swdg_to");             /* char reason_str[12] */
+    strcpy((void *) w, "sec_vio");             /* char reason_str[12] */
+    strcpy((void *) w, "pwr_key");             /* char reason_str[12] */
+    strcpy((void *) w, "rtc_alarm");           /* char reason_str[12] */
+#else
+    strcpy((void *) w, "pwr_key");             /* char reason_str[12] */
+#endif
+    w += 6;
+
+    return (void *) w - p;
+}
+
+static struct arm_boot_info apollon_binfo = {
+    .loader_start = OMAP2_Q2_BASE,
+    /* Actually two chips of 0x4000000 bytes each */
+    .ram_size = 0x08000000,
+    .board_id = 0x397,
+    .atag_board = apollon_atag_setup,
+};
+
+static void apollon_init(ram_addr_t ram_size, int vga_ram_size,
+                const char *boot_device, DisplayState *ds,
+                const char *kernel_filename, const char *kernel_cmdline,
+                const char *initrd_filename, const char *cpu_model)
+{
+    struct apollon_s *s = (struct apollon_s *) qemu_mallocz(sizeof(*s));
+    struct arm_boot_info *binfo = &apollon_binfo;
+    int sdram_size = binfo->ram_size;
+    int onenandram_size = 0x00010000;
+
+    if (ram_size < sdram_size + onenandram_size + OMAP242X_SRAM_SIZE) {
+        fprintf(stderr, "This architecture uses %i bytes of memory\n",
+                        sdram_size + onenandram_size + OMAP242X_SRAM_SIZE);
+        exit(1);
+    }
+
+    s->cpu = omap2420_mpu_init(sdram_size, NULL, cpu_model);
+
+    /* Setup peripherals
+     *
+     * Believed external peripherals layout in the apollon:
+     * (spi bus 1)
+     *   tsc2101
+     */
+    apollon_gpio_setup(s);
+    apollon_onenand_setup(s);
+
+    /* Setup initial (reset) machine state */
+
+    /* Start at the OneNAND bootloader.  */
+    s->cpu->env->regs[15] = 0;
+
+    if (kernel_filename) {
+        /* Or at the linux loader.  */
+        binfo->kernel_filename = kernel_filename;
+        binfo->kernel_cmdline = kernel_cmdline;
+        binfo->initrd_filename = initrd_filename;
+        arm_load_kernel(s->cpu->env, binfo);
+
+        qemu_register_reset(apollon_boot_init, s);
+        apollon_boot_init(s);
+    }
+
+#if 0
+    /* FIXME: We shouldn't really be doing this here.  The LCD controller
+       will set the size once configured, so this just sets an initial
+       size until the guest activates the display.  */
+    dpy_resize(ds, 800, 480);
+#endif
+
+    /* Interrupt line of NIC is connected to GPIO line 74 */
+    smc91c111_init(&nd_table[0], 0x08000300,
+                omap2_gpio_in_get(s->cpu->gpif, APOLLON_ETHERNET_GPIO)[0]);
+}
+
+QEMUMachine apollon_machine = {
+    "apollon",
+    "Samsung Apollon (OMAP2420)",
+    apollon_init,
+    (0x08000000 + 0x00010000 + OMAP242X_SRAM_SIZE) | RAMSIZE_FIXED,
+};
diff --git a/hw/boards.h b/hw/boards.h
index 22ac332..64c7ae6 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -89,6 +89,9 @@ extern QEMUMachine palmte_machine;
 extern QEMUMachine n800_machine;
 extern QEMUMachine n810_machine;
 
+/* apollon.c */
+extern QEMUMachine apollon_machine;
+
 /* gumstix.c */
 extern QEMUMachine connex_machine;
 extern QEMUMachine verdex_machine;
diff --git a/qemu-doc.texi b/qemu-doc.texi
index eb29a9f..2bb30d6 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -88,6 +88,7 @@ For system emulation, the following hardware targets are 
supported:
 @item Arnewsh MCF5206 evaluation board (ColdFire V2).
 @item Palm Tungsten|E PDA (OMAP310 processor)
 @item N800 and N810 tablets (OMAP2420 processor)
address@hidden Samsung apollon OneNAND board (OMAP2420 processor)
 @item MusicPal (MV88W8618 ARM processor)
 @end itemize
 
@@ -2604,6 +2605,29 @@ Nokia RETU and TAHVO multi-purpose chips with an RTC, 
connected
 through CBUS
 @end itemize
 
+Samsung Apollon OneNAND development board emulation supports the following 
elements:
address@hidden @minus
address@hidden
+Texas Instruments OMAP2420 System-on-chip (ARM 1136 core)
address@hidden
+RAM and non-volatile OneNAND Flash memories
address@hidden
+LAN91C96 Ethernet
address@hidden
+(TODO) Display connected to internal framebuffer chip and OMAP on-chip
+display controller and a Samsung LCD controller
address@hidden
+(TODO) TI TSC2101 touchscreen controllers driven through SPI bus
address@hidden
+Secure Digital card connected to OMAP MMC/SD host
address@hidden
+One OMAP on-chip UARTs
address@hidden
+(TODO) External USB transceiver chip connected to USB controller embedded in a 
TI
address@hidden
+(TODO) Three GPIO switches and GPIO indicate LEDs
address@hidden itemize
+
 The Luminary Micro Stellaris LM3S811EVB emulation includes the following
 devices:
 
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 42ff584..c92bb15 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -14,6 +14,7 @@ void register_machines(void)
     qemu_register_machine(&palmte_machine);
     qemu_register_machine(&n800_machine);
     qemu_register_machine(&n810_machine);
+    qemu_register_machine(&apollon_machine);
     qemu_register_machine(&lm3s811evb_machine);
     qemu_register_machine(&lm3s6965evb_machine);
     qemu_register_machine(&connex_machine);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]