From patchwork Fri Mar 26 16:06:52 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Riku Voipio X-Patchwork-Id: 48686 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id F0190B7C98 for ; Sat, 27 Mar 2010 04:43:05 +1100 (EST) Received: from localhost ([127.0.0.1]:34040 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NvDYi-0002EC-OD for incoming@patchwork.ozlabs.org; Fri, 26 Mar 2010 13:43:00 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NvC5h-0004Fs-6z for qemu-devel@nongnu.org; Fri, 26 Mar 2010 12:08:57 -0400 Received: from [140.186.70.92] (port=41537 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NvC4i-0003be-FW for qemu-devel@nongnu.org; Fri, 26 Mar 2010 12:08:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1NvC4G-0006w5-0t for qemu-devel@nongnu.org; Fri, 26 Mar 2010 12:07:54 -0400 Received: from afflict.kos.to ([92.243.29.197]:33646) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1NvC4C-0006up-OI for qemu-devel@nongnu.org; Fri, 26 Mar 2010 12:07:25 -0400 Received: by afflict.kos.to (Postfix, from userid 1000) id 39AFD26591; Fri, 26 Mar 2010 16:07:24 +0000 (UTC) From: Riku Voipio To: qemu-devel@nongnu.org Date: Fri, 26 Mar 2010 16:06:52 +0000 Message-Id: <28d02f3566af81a62325a039f896ead5eaaf0bd8.1269617186.git.riku.voipio@nokia.com> X-Mailer: git-send-email 1.6.5 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) Cc: yajin@vm-kernel.org, Riku Voipio , =?UTF-8?q?Juha=20Riihim=C3=A4ki?= Subject: [Qemu-devel] [PATCH 32/48] Add beagleboard and n900 machine definitions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Riku Voipio Wire in all the code from previous patches. Beagleboard code based on Yajin's initial work. Cc: yajin@vm-kernel.org Signed-Off-By: Riku Voipio Signed-Off-By: Juha Riihimäki --- Makefile.target | 7 +- hw/beagle.c | 108 +++++++++++++++++++++ hw/nseries.c | 288 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 397 insertions(+), 6 deletions(-) create mode 100644 hw/beagle.c diff --git a/Makefile.target b/Makefile.target index eb4d010..c14d496 100644 --- a/Makefile.target +++ b/Makefile.target @@ -269,8 +269,11 @@ obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o obj-arm-y += pflash_cfi01.o gumstix.o obj-arm-y += zaurus.o ide/core.o ide/microdrive.o spitz.o tosa.o tc6393xb.o -obj-arm-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o -obj-arm-y += omap2.o omap_dss.o soc_dma.o +obj-arm-y += omap_gpio.o omap_uart.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o +obj-arm-y += omap_i2c.o omap_spi.o omap_intc.o omap_dss.o soc_dma.o omap_gptimer.o +obj-arm-y += omap_synctimer.o omap_sdrc.o omap_gpmc.o omap_tap.o omap_l4.o +obj-arm-y += omap_usb.o omap3_mmc.o omap3_lcd.o omap3_boot.o omap1.o omap2.o omap3.o +obj-arm-y += beagle.o twl4030.o obj-arm-y += omap_sx1.o palm.o tsc210x.o obj-arm-y += nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o obj-arm-y += mst_fpga.o mainstone.o diff --git a/hw/beagle.c b/hw/beagle.c new file mode 100644 index 0000000..ae4da1c --- /dev/null +++ b/hw/beagle.c @@ -0,0 +1,108 @@ +/* + * Beagle board emulation. http://beagleboard.org/ + * + * Copyright (c) 2009 Nokia Corporation + * + * 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) any later version 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 "boards.h" +#include "i2c.h" +#include "net.h" +#include "devices.h" +#include "flash.h" + +#ifdef CONFIG_GLHW +#include "helper_opengl.h" +#endif + +#define BEAGLE_NAND_CS 0 +#define BEAGLE_SMC_CS 1 +#define BEAGLE_NAND_PAGESIZE 0x800 +#define BEAGLE_SDRAM_SIZE (128 * 1024 * 1024) /* 128MB */ + +/* Beagle board support */ +struct beagle_s { + struct omap_mpu_state_s *cpu; + + NANDFlashState *nand; + struct omap3_lcd_panel_s *lcd_panel; + i2c_bus *i2c; + void *twl4030; + void *smc; +#ifdef CONFIG_GLHW + void *gl; +#endif +}; + +static void beagle_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, + const char *cpu_model) +{ + struct beagle_s *s = (struct beagle_s *) qemu_mallocz(sizeof(*s)); + DriveInfo *dmtd = drive_get(IF_MTD, 0, 0); + DriveInfo *dsd = drive_get(IF_SD, 0, 0); + + if (!dmtd && !dsd) { + hw_error("%s: SD or NAND image required", __FUNCTION__); + } + s->cpu = omap3530_mpu_init(ram_size, NULL, NULL, serial_hds[0]); + + s->nand = nand_init(NAND_MFR_MICRON, 0xba, dmtd); + nand_setpins(s->nand, 0, 0, 0, 1, 0); /* no write-protect */ + omap_gpmc_attach(s->cpu->gpmc, BEAGLE_NAND_CS, 0, NULL, NULL, s->nand, 2); + if (dsd) { + omap3_mmc_attach(s->cpu->omap3_mmc[0], dsd, 0, 0); + } + + s->i2c = omap_i2c_bus(s->cpu->i2c[0]); + s->twl4030 = twl4030_init(s->i2c, + s->cpu->irq[0][OMAP_INT_3XXX_SYS_NIRQ], + NULL, NULL); + s->smc = smc91c111_init_lite(&nd_table[0], /*0x08000000,*/ + omap2_gpio_in_get(s->cpu->gpif, 54)); + omap_gpmc_attach(s->cpu->gpmc, BEAGLE_SMC_CS, smc91c111_iomemtype(s->smc), + NULL, NULL, s->smc, 0); + + s->lcd_panel = omap3_lcd_panel_init(s->cpu->dss); + omap_lcd_panel_attach(s->cpu->dss, omap3_lcd_panel_get(s->lcd_panel)); + +#ifdef CONFIG_GLHW + s->gl = helper_opengl_init(s->cpu->env); +#endif + + omap3_boot_rom_emu(s->cpu); +} + +QEMUMachine beagle_machine = { + .name = "beagle", + .desc = "Beagle board (OMAP3530)", + .init = beagle_init, +}; + +static void beagle_machine_init(void) +{ + qemu_register_machine(&beagle_machine); +} + +machine_init(beagle_machine_init); diff --git a/hw/nseries.c b/hw/nseries.c index ec8f8d1..27d517b 100644 --- a/hw/nseries.c +++ b/hw/nseries.c @@ -1554,10 +1554,6 @@ static QEMUMachine n810_machine = { .init = n810_init, }; -#ifdef CONFIG_GLES2 -#include "gles2.h" -#endif - #define N900_SDRAM_SIZE (256 * 1024 * 1024) #define N900_ONENAND_CS 0 #define N900_ONENAND_BUFSIZE (0xc000 << 1) @@ -2128,6 +2124,289 @@ static I2CSlaveInfo tpa6130_info = { .send = tpa6130_tx }; +struct n900_s { + struct omap_mpu_state_s *cpu; + void *twl4030; + void *nand; + void *lcd; + struct mipid_s *mipid; + void *tsc2005; + void *bq2415x; + void *tpa6130; + void *lis302dl; + void *smc; + int extended_key; + int slide_open; + int camera_cover_open; + int headphone_connected; + QEMUTimer *shutdown_timer; +}; + +/* this takes care of the keys which are not located on the + * n900 keypad (note that volume up/down keys are handled by + * the keypad eventhough the keys are not located on the keypad) + * as well as triggering some other hardware button/switch-like + * events that are mapped to the host keyboard: + * + * escape ... power + * f1 ....... keypad slider open/close + * f2 ....... keypad lock + * f3 ....... camera lens cover open/close + * f4 ....... camera focus + * f5 ....... camera take picture + * f6 ....... stereo headphone connect/disconnect + * kp1 ...... decrease accelerometer x axis value + * kp2 ...... increase accelerometer x axis value + * kp4 ...... decrease accelerometer y axis value + * kp5 ...... increase accelerometer y axis value + * kp7 ...... decrease accelerometer z axis value + * kp8 ...... increase accelerometer z axis value + */ +static void n900_key_handler(void *opaque, int keycode) +{ + struct n900_s *s = opaque; + if (!s->extended_key && keycode == 0xe0) { + s->extended_key = 0x80; + } else { + int release = keycode & 0x80; + keycode = (keycode & 0x7f) | s->extended_key; + s->extended_key = 0; + switch (keycode) { + case 0x01: /* escape */ + twl4030_set_powerbutton_state(s->twl4030, !release); + break; + case 0x3b: /* f1 */ + if (release) { + s->slide_open = !s->slide_open; + qemu_set_irq(omap2_gpio_in_get(s->cpu->gpif, + N900_SLIDE_GPIO), + !s->slide_open); + } + break; + case 0x3c: /* f2 */ + qemu_set_irq(omap2_gpio_in_get(s->cpu->gpif, + N900_KBLOCK_GPIO), + !!release); + break; + case 0x3d: /* f3 */ + if (release) { + s->camera_cover_open = !s->camera_cover_open; + qemu_set_irq(omap2_gpio_in_get(s->cpu->gpif, + N900_CAMCOVER_GPIO), + s->camera_cover_open); + } + break; + case 0x3e: /* f4 */ + qemu_set_irq(omap2_gpio_in_get(s->cpu->gpif, + N900_CAMFOCUS_GPIO), + !!release); + break; + case 0x3f: /* f5 */ + qemu_set_irq(omap2_gpio_in_get(s->cpu->gpif, + N900_CAMLAUNCH_GPIO), + !!release); + break; + case 0x40: /* f6 */ + if (release) { + s->headphone_connected = !s->headphone_connected; + qemu_set_irq(omap2_gpio_in_get(s->cpu->gpif, + N900_HEADPHONE_GPIO), + !s->headphone_connected); + } + break; + case 0x4f ... 0x50: /* kp1,2 */ + lis302dl_trigger(s->lis302dl, 0, keycode - 0x4f, !release); + break; + case 0x4b ... 0x4c: /* kp4,5 */ + lis302dl_trigger(s->lis302dl, 1, keycode - 0x4b, !release); + break; + case 0x47 ... 0x48: /* kp7,8 */ + lis302dl_trigger(s->lis302dl, 2, keycode - 0x47, !release); + break; + default: + break; + } + } +} + +static void n900_reset(void *opaque) +{ + struct n900_s *s = opaque; + omap_gpmc_attach(s->cpu->gpmc, N900_ONENAND_CS, 0, onenand_base_update, + onenand_base_unmap, s->nand, 0); + omap_gpmc_attach(s->cpu->gpmc, N900_SMC_CS, smc91c111_iomemtype(s->smc), + NULL, NULL, s->smc, 0); + qemu_irq_raise(omap2_gpio_in_get(s->cpu->gpif, N900_KBLOCK_GPIO)); + qemu_irq_raise(omap2_gpio_in_get(s->cpu->gpif, N900_HEADPHONE_GPIO)); + qemu_irq_raise(omap2_gpio_in_get(s->cpu->gpif, N900_CAMLAUNCH_GPIO)); + qemu_irq_raise(omap2_gpio_in_get(s->cpu->gpif, N900_CAMFOCUS_GPIO)); + qemu_irq_lower(omap2_gpio_in_get(s->cpu->gpif, N900_CAMCOVER_GPIO)); + qemu_irq_lower(omap2_gpio_in_get(s->cpu->gpif, N900_SLIDE_GPIO)); + s->slide_open = 1; + s->camera_cover_open = 0; + s->headphone_connected = 0; + omap3_boot_rom_emu(s->cpu); +} + +static void n900_shutdown_timer_callback(void *opaque) +{ + static int power_state = 0; + struct n900_s *s = opaque; + power_state = !power_state; + twl4030_set_powerbutton_state(s->twl4030, power_state); + qemu_mod_timer(s->shutdown_timer, + qemu_get_clock(vm_clock) + + get_ticks_per_sec() * (power_state ? 5LL : 1LL)); +} + +static int n900_display_close_callback(void *opaque) +{ + struct n900_s *s = opaque; + if (s->shutdown_timer == NULL) { + s->shutdown_timer = qemu_new_timer(vm_clock, + n900_shutdown_timer_callback, + s); + n900_shutdown_timer_callback(s); + } + return 0; +} + +static const TWL4030KeyMap n900_twl4030_keymap[] = { + {0x10, 0, 0}, /* Q */ + {0x11, 0, 1}, /* W */ + {0x12, 0, 2}, /* E */ + {0x13, 0, 3}, /* R */ + {0x14, 0, 4}, /* T */ + {0x15, 0, 5}, /* Y */ + {0x16, 0, 6}, /* U */ + {0x17, 0, 7}, /* I */ + {0x18, 1, 0}, /* O */ + {0x20, 1, 1}, /* D */ + {0x34, 1, 2}, /* . */ + {0x2f, 1, 3}, /* V */ + {0xd0, 1, 4}, /* DOWN */ + {0x41, 1, 7}, /* F7 -- volume/zoom down */ + {0x19, 2, 0}, /* P */ + {0x21, 2, 1}, /* F */ + {0xc8, 2, 2}, /* UP */ + {0x30, 2, 3}, /* B */ + {0xcd, 2, 4}, /* RIGHT */ + {0x42, 2, 7}, /* F8 -- volume/zoom up */ + {0x33, 3, 0}, /* , */ + {0x22, 3, 1}, /* G */ + {0x1c, 3, 2}, /* ENTER */ + {0x31, 3, 3}, /* N */ + {0x0e, 4, 0}, /* BACKSPACE */ + {0x23, 4, 1}, /* H */ + {0x32, 4, 3}, /* M */ + {0x1d, 4, 4}, /* LEFTCTRL */ + {0x24, 5, 1}, /* J */ + {0x2c, 5, 2}, /* Z */ + {0x39, 5, 3}, /* SPACE */ + {0x38, 5, 4}, /* LEFTALT -- "fn" */ + {0x1e, 6, 0}, /* A */ + {0x25, 6, 1}, /* K */ + {0x2d, 6, 2}, /* X */ + {0x39, 6, 3}, /* SPACE */ + {0x2a, 6, 4}, /* LEFTSHIFT */ + {0x1f, 7, 0}, /* S */ + {0x26, 7, 1}, /* L */ + {0x2e, 7, 2}, /* C */ + {0xcb, 7, 3}, /* LEFT */ + // {0x10, 0xff, 2}, /* F9 */ + // {0x10, 0xff, 4}, /* F10 */ + // {0x10, 0xff, 5}, /* F11 */ + {-1, -1, -1} +}; + +static MouseTransformInfo n900_pointercal = { + .x = 800, + .y = 480, + .a = {14114, 18, -2825064, 34, -8765, 32972906, 65536}, +}; + +static void n900_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, + const char *cpu_model) +{ + struct n900_s *s = qemu_mallocz(sizeof(*s)); + DriveInfo *dmtd = drive_get(IF_MTD, 0, 0); + DriveInfo *dsd = drive_get(IF_SD, 0, 0); + + if (!dmtd && !dsd) { + hw_error("%s: SD or NAND image required", __FUNCTION__); + } + s->cpu = omap3530_mpu_init(N900_SDRAM_SIZE, + serial_hds[1], + serial_hds[2], + serial_hds[0]); + s->lcd = omap3_lcd_panel_init(s->cpu->dss); + omap_lcd_panel_attach(s->cpu->dss, omap3_lcd_panel_get(s->lcd)); + + s->tsc2005 = tsc2005_init(omap2_gpio_in_get(s->cpu->gpif, + N900_TSC2005_IRQ_GPIO)); + tsc2005_set_transform(s->tsc2005, &n900_pointercal, 600, 1500); + omap_mcspi_attach(s->cpu->mcspi[0], tsc2005_txrx, s->tsc2005, 0); + cursor_hide = 0; // who wants to use touchscreen without a pointer? + cursor_allow_grab = 0; // ...and please, don't stop the host cursor + + s->mipid = mipid_init(); + s->mipid->n900 = 1; + s->mipid->id = 0x101234; + omap_mcspi_attach(s->cpu->mcspi[0], mipid_txrx, s->mipid, 2); + + s->nand = onenand_init(NAND_MFR_SAMSUNG, 0x40, 0x121, 1, + omap2_gpio_in_get(s->cpu->gpif, N900_ONENAND_GPIO), + dmtd); + + if (dsd) { + omap3_mmc_attach(s->cpu->omap3_mmc[1], dsd, 0, 1); + } + if ((dsd = drive_get(IF_SD, 0, 1)) >= 0) { + omap3_mmc_attach(s->cpu->omap3_mmc[0], dsd, 0, 0); + //qemu_irq_raise(omap2_gpio_in_get(s->cpu->gpif, N900_SDCOVER_GPIO)); + } + + cpu_register_physical_memory(0x48058000, 0x3c00, + cpu_register_io_memory(ssi_read_func, + ssi_write_func, + 0)); + + s->twl4030 = twl4030_init(omap_i2c_bus(s->cpu->i2c[0]), + s->cpu->irq[0][OMAP_INT_3XXX_SYS_NIRQ], + NULL, n900_twl4030_keymap); + s->bq2415x = i2c_create_slave(omap_i2c_bus(s->cpu->i2c[1]), + "bq2415x", 0x6b); + s->tpa6130 = i2c_create_slave(omap_i2c_bus(s->cpu->i2c[1]), + "tpa6130", 0x60); + omap2_gpio_out_set(s->cpu->gpif, N900_HEADPHONE_EN_GPIO, + tpa6130_get_irq(s->tpa6130, 0)); + s->lis302dl = lis302dl_init(i2c_create_slave(omap_i2c_bus(s->cpu->i2c[2]), + "lis302dl", 0x1d), + omap2_gpio_in_get(s->cpu->gpif, + N900_LIS302DL_INT1_GPIO), + omap2_gpio_in_get(s->cpu->gpif, + N900_LIS302DL_INT2_GPIO)); + + s->smc = smc91c111_init_lite(&nd_table[0], /*0x08000000,*/ + omap2_gpio_in_get(s->cpu->gpif, 54)); + + qemu_add_kbd_event_handler(n900_key_handler, s); + qemu_set_display_close_handler(n900_display_close_callback, s); + + qemu_register_reset(n900_reset, s); + n900_reset(s); +} + +static QEMUMachine n900_machine = { + .name = "n900", + .desc = "Nokia N900 (OMAP3)", + .init = n900_init, +}; + static void nseries_register_devices(void) { i2c_register_slave(&bq2415x_info); @@ -2139,6 +2418,7 @@ static void nseries_machine_init(void) { qemu_register_machine(&n800_machine); qemu_register_machine(&n810_machine); + qemu_register_machine(&n900_machine); } device_init(nseries_register_devices);