From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KNNBa-0005Xz-Tr for qemu-devel@nongnu.org; Mon, 28 Jul 2008 03:30:26 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KNNBY-0005WP-Tj for qemu-devel@nongnu.org; Mon, 28 Jul 2008 03:30:25 -0400 Received: from [199.232.76.173] (port=57249 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KNNBY-0005WM-Nx for qemu-devel@nongnu.org; Mon, 28 Jul 2008 03:30:24 -0400 Received: from mx20.gnu.org ([199.232.41.8]:12697) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1KNNBY-0000XS-1Q for qemu-devel@nongnu.org; Mon, 28 Jul 2008 03:30:24 -0400 Received: from mailout3.samsung.com ([203.254.224.33]) by mx20.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1KNNBW-0000F4-FR for qemu-devel@nongnu.org; Mon, 28 Jul 2008 03:30:23 -0400 Received: from epmmp1 (mailout3.samsung.com [203.254.224.33]) by mailout3.samsung.com (iPlanet Messaging Server 5.2 Patch 2 (built Jul 14 2004)) with ESMTP id <0K4P008H0GUDWX@mailout3.samsung.com> for qemu-devel@nongnu.org; Mon, 28 Jul 2008 16:30:13 +0900 (KST) Received: from spapp01.rdscm.com ([165.213.149.150]) by mmp1.samsung.com (iPlanet Messaging Server 5.2 Patch 2 (built Jul 14 2004)) with ESMTPA id <0K4P00K23GUDE7@mmp1.samsung.com> for qemu-devel@nongnu.org; Mon, 28 Jul 2008 16:30:13 +0900 (KST) Date: Mon, 28 Jul 2008 16:24:03 +0900 From: Kyungmin Park Message-id: <20080728072403.GA564@july> MIME-version: 1.0 Content-type: text/plain; charset=us-ascii Content-transfer-encoding: 7BIT Content-disposition: inline Subject: [Qemu-devel] [PATCH] Add Apollon (OMAP24xx) board support (take #2) Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Add apollon (OMAP24xx) board initial support with board descriptions Signed-off-by: Kyungmin Park --- 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 + * + * 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) +@item 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: +@itemize @minus +@item +Texas Instruments OMAP2420 System-on-chip (ARM 1136 core) +@item +RAM and non-volatile OneNAND Flash memories +@item +LAN91C96 Ethernet +@item +(TODO) Display connected to internal framebuffer chip and OMAP on-chip +display controller and a Samsung LCD controller +@item +(TODO) TI TSC2101 touchscreen controllers driven through SPI bus +@item +Secure Digital card connected to OMAP MMC/SD host +@item +One OMAP on-chip UARTs +@item +(TODO) External USB transceiver chip connected to USB controller embedded in a TI +@item +(TODO) Three GPIO switches and GPIO indicate LEDs +@end 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);