@@ -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
new file mode 100644
@@ -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);
@@ -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);