From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MERkz-0004LV-VL for qemu-devel@nongnu.org; Wed, 10 Jun 2009 13:38:38 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MERkv-0004Ig-V8 for qemu-devel@nongnu.org; Wed, 10 Jun 2009 13:38:37 -0400 Received: from [199.232.76.173] (port=51294 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MERkv-0004Ib-CG for qemu-devel@nongnu.org; Wed, 10 Jun 2009 13:38:33 -0400 Received: from gateway.codesourcery.com ([65.74.133.9]:52179) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1MERku-00020E-CI for qemu-devel@nongnu.org; Wed, 10 Jun 2009 13:38:33 -0400 Received: from wren.home (localhost [127.0.0.1]) by gateway.codesourcery.com (Postfix) with ESMTP id BFD5468053 for ; Wed, 10 Jun 2009 10:38:30 -0700 (PDT) From: Paul Brook Date: Wed, 10 Jun 2009 18:38:29 +0100 Message-ID: <20090610173829.4674.2315.stgit@wren.home> In-Reply-To: <20090610173803.4674.82538.stgit@wren.home> References: <20090610173803.4674.82538.stgit@wren.home> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [PATCH 3/4] Stellaris machine config List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Replace hardcoded stellaris boards with machine configs Signed-off-by: Paul Brook --- Makefile | 4 - Makefile.hw | 2 hw/arm-cpu.c | 3 hw/armv7m.c | 61 +++++++++ hw/gpio-buttons.c | 124 ++++++++++++++++++ hw/pl011.c | 2 hw/pl061.c | 25 +++- hw/stellaris.c | 272 +++++++++------------------------------- hw/stellaris_enet.c | 2 hw/stellaris_input.c | 91 ------------- pc-bios/boards/lm3s6965evb.dts | 212 +++++++++++++++++++++++++++++++ pc-bios/boards/lm3s811evb.dts | 155 +++++++++++++++++++++++ 12 files changed, 645 insertions(+), 308 deletions(-) create mode 100644 hw/gpio-buttons.c delete mode 100644 hw/stellaris_input.c create mode 100644 pc-bios/boards/lm3s6965evb.dts create mode 100644 pc-bios/boards/lm3s811evb.dts diff --git a/Makefile b/Makefile index 6d15c44..48a3ec3 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ endif ####################################################################### # Board descriptions -BOARDS = syborg +BOARDS = syborg lm3s811evb lm3s6965evb ifdef DTC BOARDS_BIN = $(BOARDS:%=pc-bios/boards/%.dtb) @@ -115,7 +115,7 @@ OBJS+=readline.o console.o OBJS+=irq.o ptimer.o OBJS+=i2c.o smbus.o smbus_eeprom.o max7310.o max111x.o wm8750.o -OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o twl92230.o +OBJS+=ssd0303.o ssd0323.o ads7846.o twl92230.o OBJS+=tmp105.o lm832x.o eeprom93xx.o tsc2005.o OBJS+=scsi-disk.o cdrom.o OBJS+=scsi-generic.o diff --git a/Makefile.hw b/Makefile.hw index 6accb3b..1953b85 100644 --- a/Makefile.hw +++ b/Makefile.hw @@ -28,6 +28,8 @@ OBJS+= lsi53c895a.o esp.o OBJS+= dma-helpers.o sysbus.o +OBJS+= gpio-buttons.o + all: $(HWLIB) # Dummy command so that make thinks it has done something @true diff --git a/hw/arm-cpu.c b/hw/arm-cpu.c index c15eb12..4c128d1 100644 --- a/hw/arm-cpu.c +++ b/hw/arm-cpu.c @@ -17,7 +17,8 @@ static const struct { const char *cpuname; } cpu_device_name_map[] = { {"ARM,ARM926EJ-S", "arm926"}, - {"ARM,Cortex-A8", "cortex-a8"} + {"ARM,Cortex-A8", "cortex-a8"}, + {"ARM,Cortex-M3", "cortex-m3"} }; typedef struct { diff --git a/hw/armv7m.c b/hw/armv7m.c index c3c5b9e..d74a2fb 100644 --- a/hw/armv7m.c +++ b/hw/armv7m.c @@ -10,6 +10,7 @@ #include "sysbus.h" #include "arm-misc.h" #include "sysemu.h" +#include "boards.h" /* Bitbanded IO. Each word corresponds to a single bit. */ @@ -149,6 +150,47 @@ static void armv7m_bitband_init(void) } /* Board init. */ +/* Reset initialization and iage loading for ARMv7-M cores. */ +static void armv7m_bootstrap(ram_addr_t ram_size, const char *boot_device, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename) +{ + CPUState *env = first_cpu; + uint32_t pc; + int image_size; + uint64_t entry; + uint64_t lowaddr; + + image_size = load_elf(kernel_filename, 0, &entry, &lowaddr, NULL); + if (image_size < 0) { + image_size = load_image_targphys(kernel_filename, 0, ram_size); + lowaddr = 0; + } + if (image_size < 0) { + fprintf(stderr, "qemu: could not load kernel '%s'\n", + kernel_filename); + exit(1); + } + + /* If the image was loaded at address zero then assume it is a + regular ROM image and perform the normal CPU reset sequence. + Otherwise jump directly to the entry point. */ + if (lowaddr == 0) { + env->regs[13] = ldl_phys(0); + pc = ldl_phys(4); + } else { + pc = entry; + } + env->thumb = pc & 1; + env->regs[15] = pc & ~1; + + /* Hack to map an additional page of ram at the top of the address + space. This stops qemu complaining about executing code outside RAM + when returning from an exception. */ + cpu_register_physical_memory(0xfffff000, 0x1000, + qemu_ram_alloc(0x1000) | IO_MEM_RAM); +} + /* Init CPU and memory for a v7-M based board. flash_size and sram_size are in kb. Returns the NVIC array. */ @@ -238,10 +280,25 @@ qemu_irq *armv7m_init(int flash_size, int sram_size, return pic; } +static SysBusDeviceInfo bitband_info = { + .init = bitband_init, + .qdev.props = (DevicePropList[]) { + {.name = "base", .type = PROP_TYPE_INT}, + {.name = NULL} + } +}; + static void armv7m_register_devices(void) { - sysbus_register_dev("ARM,bitband-memory", sizeof(BitBandState), - bitband_init); + sysbus_register_withprop("ARM,bitband-memory", sizeof(BitBandState), + &bitband_info); } device_init(armv7m_register_devices) + +static void armv7m_boot_register(void) +{ + register_machine_bootstrap("ARMv7-M", armv7m_bootstrap); +} + +machine_init(armv7m_boot_register); diff --git a/hw/gpio-buttons.c b/hw/gpio-buttons.c new file mode 100644 index 0000000..0627818 --- /dev/null +++ b/hw/gpio-buttons.c @@ -0,0 +1,124 @@ +/* + * Buttons connected directly to GPIO pins. + * + * Copyright (c) 2009 CodeSourcery. + * Written by Paul Brook + * + * This code is licenced under the GNU GPL v2. + */ +#include "sysbus.h" +#include "console.h" + +#define KEY_INVERT 0x80000000u +#define KEY_CODE_MASK 0x0000ffffu + +typedef struct { + SysBusDevice busdev; + qemu_irq *irq; + const uint32_t *keys; + int *pressed; + int num_buttons; + int extension; +} GPIOButtonsState; + +static void gpio_buttons_put_key(void *opaque, int keycode) +{ + GPIOButtonsState *s = (GPIOButtonsState *)opaque; + int i; + int down; + + if (keycode == 0xe0 && !s->extension) { + s->extension = 0x80; + return; + } + + down = (keycode & 0x80) == 0; + keycode = (keycode & 0x7f) | s->extension; + + for (i = 0; i < s->num_buttons; i++) { + if ((s->keys[i] & KEY_CODE_MASK) == keycode + && s->pressed[i] != down) { + s->pressed[i] = down; + if (s->keys[i] & KEY_INVERT) { + qemu_set_irq(s->irq[i], !down); + } else { + qemu_set_irq(s->irq[i], down); + } + } + } + + s->extension = 0; +} + +static void gpio_buttons_save(QEMUFile *f, void *opaque) +{ + GPIOButtonsState *s = (GPIOButtonsState *)opaque; + int i; + + qemu_put_be32(f, s->extension); + for (i = 0; i < s->num_buttons; i++) + qemu_put_byte(f, s->pressed[i]); +} + +static int gpio_buttons_load(QEMUFile *f, void *opaque, int version_id) +{ + GPIOButtonsState *s = (GPIOButtonsState *)opaque; + int i; + + if (version_id != 1) + return -EINVAL; + + s->extension = qemu_get_be32(f); + for (i = 0; i < s->num_buttons; i++) + s->pressed[i] = qemu_get_byte(f); + + return 0; +} + +static void gpio_buttons_late_init(DeviceState *dev) +{ + GPIOButtonsState *s = FROM_SYSBUS(GPIOButtonsState, sysbus_from_qdev(dev)); + int i; + + for (i = 0; i < s->num_buttons; i++) { + if (s->keys[i] & KEY_INVERT) { + qemu_irq_raise(s->irq[i]); + } + } +} + +static void gpio_buttons_init(SysBusDevice *dev) +{ + GPIOButtonsState *s = FROM_SYSBUS(GPIOButtonsState, dev); + + s->num_buttons = qdev_get_prop_array(&dev->qdev, "keys", &s->keys); + if (s->num_buttons <= 0) { + hw_error("gpio-buttons: Missing keys property"); + } + + s->irq = qemu_mallocz(sizeof(qemu_irq) * s->num_buttons); + qdev_init_gpio_out(&dev->qdev, s->irq, s->num_buttons); + s->pressed = qemu_mallocz(sizeof(int) * s->num_buttons); + qemu_add_kbd_event_handler(gpio_buttons_put_key, s); + register_savevm("gpio-buttons", -1, 1, + gpio_buttons_save, gpio_buttons_load, s); +} + +static SysBusDeviceInfo gpio_buttons_info = { + .init = gpio_buttons_init, + .qdev.late_init = gpio_buttons_late_init, + .qdev.props = (DevicePropList[]) { + {.name = "keys", .type = PROP_TYPE_ARRAY}, + {.name = NULL} + } +}; + +static void gpio_buttons_register_devices(void) +{ + /* ??? This isn't really attached to the system bus, but it's as good + a place as any to put it. */ + sysbus_register_withprop("qemu,gpio-buttons", sizeof(GPIOButtonsState), + &gpio_buttons_info); +} + +device_init(gpio_buttons_register_devices) diff --git a/hw/pl011.c b/hw/pl011.c index 3a1a4cb..f167bec 100644 --- a/hw/pl011.c +++ b/hw/pl011.c @@ -323,7 +323,7 @@ static void pl011_register_devices(void) { sysbus_register_dev("pl011", sizeof(pl011_state), pl011_init_arm); - sysbus_register_dev("pl011_luminary", sizeof(pl011_state), + sysbus_register_dev("luminary,pl011", sizeof(pl011_state), pl011_init_luminary); } diff --git a/hw/pl061.c b/hw/pl061.c index aa0a322..8e38bd6 100644 --- a/hw/pl061.c +++ b/hw/pl061.c @@ -291,6 +291,18 @@ static int pl061_load(QEMUFile *f, void *opaque, int version_id) return 0; } +static void pl061_late_init(DeviceState *dev) +{ + pl061_state *s = FROM_SYSBUS(pl061_state, sysbus_from_qdev(dev)); + int i; + + for (i = 0; i < 8; i++) { + if (s->float_high & (1 << i)) { + qemu_irq_raise(s->out[i]); + } + } +} + static void pl061_init(SysBusDevice *dev) { int iomemtype; @@ -302,14 +314,23 @@ static void pl061_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); qdev_init_gpio_in(&dev->qdev, pl061_set_irq, 8); qdev_init_gpio_out(&dev->qdev, s->out, 8); + s->float_high = qdev_get_prop_int(&dev->qdev, "float-high", 0); pl061_reset(s); register_savevm("pl061_gpio", -1, 1, pl061_save, pl061_load, s); } +static SysBusDeviceInfo pl061_info = { + .init = pl061_init, + .qdev.late_init = pl061_late_init, + .qdev.props = (DevicePropList[]) { + {.name = "float-high", .type = PROP_TYPE_INT}, + {.name = NULL} + } +}; static void pl061_register_devices(void) { - sysbus_register_dev("pl061", sizeof(pl061_state), - pl061_init); + sysbus_register_withprop("pl061", sizeof(pl061_state), + &pl061_info); } device_init(pl061_register_devices) diff --git a/hw/stellaris.c b/hw/stellaris.c index 38b9830..ba5b11f 100644 --- a/hw/stellaris.c +++ b/hw/stellaris.c @@ -361,6 +361,7 @@ static void stellaris_gptm_init(SysBusDevice *dev) /* System controller. */ typedef struct { + SysBusDevice busdev; uint32_t pborctl; uint32_t ldopctl; uint32_t int_status; @@ -374,8 +375,12 @@ typedef struct { uint32_t ldoarst; uint32_t user0; uint32_t user1; + uint32_t did0; + uint32_t did1; + uint32_t dc[4]; qemu_irq irq; - stellaris_board_info *board; + int got_mac; + DeviceState *netdev; } ssys_state; static void ssys_update(ssys_state *s) @@ -421,25 +426,38 @@ static uint32_t pllcfg_fury[16] = { 0xb11c /* 8.192 Mhz */ }; +static void ssys_get_mac(ssys_state *s) +{ + uint8_t macaddr[6]; + + s->got_mac = 1; + if (!s->netdev) { + return; + } + qdev_get_macaddr(s->netdev, macaddr); + s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16); + s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16); +} + static uint32_t ssys_read(void *opaque, target_phys_addr_t offset) { ssys_state *s = (ssys_state *)opaque; switch (offset) { case 0x000: /* DID0 */ - return s->board->did0; + return s->did0; case 0x004: /* DID1 */ - return s->board->did1; + return s->did1; case 0x008: /* DC0 */ - return s->board->dc0; + return s->dc[0]; case 0x010: /* DC1 */ - return s->board->dc1; + return s->dc[1]; case 0x014: /* DC2 */ - return s->board->dc2; + return s->dc[2]; case 0x018: /* DC3 */ - return s->board->dc3; + return s->dc[3]; case 0x01c: /* DC4 */ - return s->board->dc4; + return s->dc[4]; case 0x030: /* PBORCTL */ return s->pborctl; case 0x034: /* LDOPCTL */ @@ -464,7 +482,7 @@ static uint32_t ssys_read(void *opaque, target_phys_addr_t offset) { int xtal; xtal = (s->rcc >> 6) & 0xf; - if (s->board->did0 & (1 << 16)) { + if (s->did0 & (1 << 16)) { return pllcfg_fury[xtal]; } else { return pllcfg_sandstorm[xtal]; @@ -493,8 +511,14 @@ static uint32_t ssys_read(void *opaque, target_phys_addr_t offset) case 0x160: /* LDOARST */ return s->ldoarst; case 0x1e0: /* USER0 */ + if (!s->got_mac) { + ssys_get_mac(s); + } return s->user0; case 0x1e4: /* USER1 */ + if (!s->got_mac) { + ssys_get_mac(s); + } return s->user1; default: hw_error("ssys_read: Bad offset 0x%x\n", (int)offset); @@ -654,23 +678,25 @@ static int ssys_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static void stellaris_sys_init(uint32_t base, qemu_irq irq, - stellaris_board_info * board, - uint8_t *macaddr) +static void stellaris_sysctl_init(SysBusDevice *dev) { int iomemtype; - ssys_state *s; - - s = (ssys_state *)qemu_mallocz(sizeof(ssys_state)); - s->irq = irq; - s->board = board; - /* Most devices come preprogrammed with a MAC address in the user data. */ - s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16); - s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16); + ssys_state *s = FROM_SYSBUS(ssys_state, dev); iomemtype = cpu_register_io_memory(0, ssys_readfn, ssys_writefn, s); - cpu_register_physical_memory(base, 0x00001000, iomemtype); + sysbus_init_mmio(dev, 0x1000, iomemtype); + sysbus_init_irq(dev, &s->irq); + s->netdev = qdev_get_prop_dev(&dev->qdev, "enet"); + s->got_mac = 0; + s->did0 = qdev_get_prop_int(&dev->qdev, "did0", 0); + s->did1 = qdev_get_prop_int(&dev->qdev, "did1", 0); + s->dc[0] = qdev_get_prop_int(&dev->qdev, "dc0", 0); + s->dc[1] = qdev_get_prop_int(&dev->qdev, "dc1", 0); + s->dc[2] = qdev_get_prop_int(&dev->qdev, "dc2", 0); + s->dc[3] = qdev_get_prop_int(&dev->qdev, "dc3", 0); + s->dc[4] = qdev_get_prop_int(&dev->qdev, "dc4", 0); + ssys_reset(s); register_savevm("stellaris_sys", -1, 1, ssys_save, ssys_load, s); } @@ -1256,200 +1282,30 @@ static void stellaris_ssi_bus_init(SSISlave *dev) stellaris_ssi_bus_save, stellaris_ssi_bus_load, s); } -/* Board init. */ -static stellaris_board_info stellaris_boards[] = { - { "LM3S811EVB", - 0, - 0x0032000e, - 0x001f001f, /* dc0 */ - 0x001132bf, - 0x01071013, - 0x3f0f01ff, - 0x0000001f, - BP_OLED_I2C - }, - { "LM3S6965EVB", - 0x10010002, - 0x1073402e, - 0x00ff007f, /* dc0 */ - 0x001133ff, - 0x030f5317, - 0x0f0f87ff, - 0x5000007f, - BP_OLED_SSI | BP_GAMEPAD - } -}; - -static void stellaris_init(const char *kernel_filename, const char *cpu_model, - stellaris_board_info *board) -{ - static const int uart_irq[] = {5, 6, 33, 34}; - static const int timer_irq[] = {19, 21, 23, 35}; - static const uint32_t gpio_addr[7] = - { 0x40004000, 0x40005000, 0x40006000, 0x40007000, - 0x40024000, 0x40025000, 0x40026000}; - static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31}; - - qemu_irq *pic; - DeviceState *gpio_dev[7]; - qemu_irq gpio_in[7][8]; - qemu_irq gpio_out[7][8]; - qemu_irq adc; - int sram_size; - int flash_size; - i2c_bus *i2c; - DeviceState *dev; - int i; - int j; - - flash_size = ((board->dc0 & 0xffff) + 1) << 1; - sram_size = (board->dc0 >> 18) + 1; - pic = armv7m_init(flash_size, sram_size, kernel_filename, cpu_model); - - if (board->dc1 & (1 << 16)) { - dev = sysbus_create_varargs("stellaris-adc", 0x40038000, - pic[14], pic[15], pic[16], pic[17], NULL); - adc = qdev_get_gpio_in(dev, 0); - } else { - adc = NULL; - } - for (i = 0; i < 4; i++) { - if (board->dc2 & (0x10000 << i)) { - dev = sysbus_create_simple("stellaris-gptm", - 0x40030000 + i * 0x1000, - pic[timer_irq[i]]); - /* TODO: This is incorrect, but we get away with it because - the ADC output is only ever pulsed. */ - qdev_connect_gpio_out(dev, 0, adc); - } - } - - stellaris_sys_init(0x400fe000, pic[28], board, nd_table[0].macaddr); - - for (i = 0; i < 7; i++) { - if (board->dc4 & (1 << i)) { - gpio_dev[i] = sysbus_create_simple("pl061", gpio_addr[i], - pic[gpio_irq[i]]); - for (j = 0; j < 8; j++) { - gpio_in[i][j] = qdev_get_gpio_in(gpio_dev[i], j); - gpio_out[i][j] = NULL; - } - } - } - - if (board->dc2 & (1 << 12)) { - dev = sysbus_create_simple("stellaris-i2c", 0x40020000, pic[8]); - i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c"); - if (board->peripherals & BP_OLED_I2C) { - i2c_create_slave(i2c, "ssd0303", 0x3d); - } - } - - for (i = 0; i < 4; i++) { - if (board->dc2 & (1 << i)) { - sysbus_create_simple("pl011_luminary", 0x4000c000 + i * 0x1000, - pic[uart_irq[i]]); - } - } - if (board->dc2 & (1 << 4)) { - dev = sysbus_create_simple("pl022", 0x40008000, pic[7]); - if (board->peripherals & BP_OLED_SSI) { - DeviceState *mux; - void *bus; - - bus = qdev_get_child_bus(dev, "ssi"); - mux = ssi_create_slave(bus, "evb6965-ssi"); - gpio_out[GPIO_D][0] = qdev_get_gpio_in(mux, 0); - - bus = qdev_get_child_bus(mux, "ssi0"); - dev = ssi_create_slave(bus, "ssi-sd"); - - bus = qdev_get_child_bus(mux, "ssi1"); - dev = ssi_create_slave(bus, "ssd0323"); - gpio_out[GPIO_C][7] = qdev_get_gpio_in(dev, 0); - - /* Make sure the select pin is high. */ - qemu_irq_raise(gpio_out[GPIO_D][0]); - } - } - if (board->dc4 & (1 << 28)) { - DeviceState *enet; - - qemu_check_nic_model(&nd_table[0], "stellaris"); - - enet = qdev_create(NULL, "stellaris_enet"); - qdev_set_netdev(enet, &nd_table[0]); - qdev_init(enet); - sysbus_mmio_map(sysbus_from_qdev(enet), 0, 0x40048000); - sysbus_connect_irq(sysbus_from_qdev(enet), 0, pic[42]); - } - if (board->peripherals & BP_GAMEPAD) { - qemu_irq gpad_irq[5]; - static const int gpad_keycode[5] = { 0xc8, 0xd0, 0xcb, 0xcd, 0x1d }; - - gpad_irq[0] = qemu_irq_invert(gpio_in[GPIO_E][0]); /* up */ - gpad_irq[1] = qemu_irq_invert(gpio_in[GPIO_E][1]); /* down */ - gpad_irq[2] = qemu_irq_invert(gpio_in[GPIO_E][2]); /* left */ - gpad_irq[3] = qemu_irq_invert(gpio_in[GPIO_E][3]); /* right */ - gpad_irq[4] = qemu_irq_invert(gpio_in[GPIO_F][1]); /* select */ - - stellaris_gamepad_init(5, gpad_irq, gpad_keycode); - } - for (i = 0; i < 7; i++) { - if (board->dc4 & (1 << i)) { - for (j = 0; j < 8; j++) { - if (gpio_out[i][j]) { - qdev_connect_gpio_out(gpio_dev[i], j, gpio_out[i][j]); - } - } - } - } -} - -/* FIXME: Figure out how to generate these from stellaris_boards. */ -static void lm3s811evb_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) -{ - stellaris_init(kernel_filename, cpu_model, &stellaris_boards[0]); -} - -static void lm3s6965evb_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) -{ - stellaris_init(kernel_filename, cpu_model, &stellaris_boards[1]); -} - -static QEMUMachine lm3s811evb_machine = { - .name = "lm3s811evb", - .desc = "Stellaris LM3S811EVB", - .init = lm3s811evb_init, -}; - -static QEMUMachine lm3s6965evb_machine = { - .name = "lm3s6965evb", - .desc = "Stellaris LM3S6965EVB", - .init = lm3s6965evb_init, -}; - -static void stellaris_machine_init(void) -{ - qemu_register_machine(&lm3s811evb_machine); - qemu_register_machine(&lm3s6965evb_machine); -} - -machine_init(stellaris_machine_init); - static SSISlaveInfo stellaris_ssi_bus_info = { .init = stellaris_ssi_bus_init, .transfer = stellaris_ssi_bus_transfer }; +static SysBusDeviceInfo ssys_info = { + .init = stellaris_sysctl_init, + .qdev.props = (DevicePropList[]) { + {.name = "enet", .type = PROP_TYPE_DEV}, + {.name = "did0", .type = PROP_TYPE_INT}, + {.name = "did1", .type = PROP_TYPE_INT}, + {.name = "dc0", .type = PROP_TYPE_INT}, + {.name = "dc1", .type = PROP_TYPE_INT}, + {.name = "dc2", .type = PROP_TYPE_INT}, + {.name = "dc3", .type = PROP_TYPE_INT}, + {.name = "dc4", .type = PROP_TYPE_INT}, + {.name = NULL} + } +}; + static void stellaris_register_devices(void) { + sysbus_register_withprop("stellaris-sysctl", sizeof(ssys_state), + &ssys_info); sysbus_register_dev("stellaris-i2c", sizeof(stellaris_i2c_state), stellaris_i2c_init); sysbus_register_dev("stellaris-gptm", sizeof(gptm_state), diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c index 36fabd3..86df231 100644 --- a/hw/stellaris_enet.c +++ b/hw/stellaris_enet.c @@ -417,7 +417,7 @@ static void stellaris_enet_init(SysBusDevice *dev) static void stellaris_enet_register_devices(void) { - sysbus_register_dev("stellaris_enet", sizeof(stellaris_enet_state), + sysbus_register_dev("stellaris-enet", sizeof(stellaris_enet_state), stellaris_enet_init); } diff --git a/hw/stellaris_input.c b/hw/stellaris_input.c deleted file mode 100644 index 33395a4..0000000 --- a/hw/stellaris_input.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Gamepad style buttons connected to IRQ/GPIO lines - * - * Copyright (c) 2007 CodeSourcery. - * Written by Paul Brook - * - * This code is licenced under the GPL. - */ -#include "hw.h" -#include "devices.h" -#include "console.h" - -typedef struct { - qemu_irq irq; - int keycode; - int pressed; -} gamepad_button; - -typedef struct { - gamepad_button *buttons; - int num_buttons; - int extension; -} gamepad_state; - -static void stellaris_gamepad_put_key(void * opaque, int keycode) -{ - gamepad_state *s = (gamepad_state *)opaque; - int i; - int down; - - if (keycode == 0xe0 && !s->extension) { - s->extension = 0x80; - return; - } - - down = (keycode & 0x80) == 0; - keycode = (keycode & 0x7f) | s->extension; - - for (i = 0; i < s->num_buttons; i++) { - if (s->buttons[i].keycode == keycode - && s->buttons[i].pressed != down) { - s->buttons[i].pressed = down; - qemu_set_irq(s->buttons[i].irq, down); - } - } - - s->extension = 0; -} - -static void stellaris_gamepad_save(QEMUFile *f, void *opaque) -{ - gamepad_state *s = (gamepad_state *)opaque; - int i; - - qemu_put_be32(f, s->extension); - for (i = 0; i < s->num_buttons; i++) - qemu_put_byte(f, s->buttons[i].pressed); -} - -static int stellaris_gamepad_load(QEMUFile *f, void *opaque, int version_id) -{ - gamepad_state *s = (gamepad_state *)opaque; - int i; - - if (version_id != 1) - return -EINVAL; - - s->extension = qemu_get_be32(f); - for (i = 0; i < s->num_buttons; i++) - s->buttons[i].pressed = qemu_get_byte(f); - - return 0; -} - -/* Returns an array 5 ouput slots. */ -void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode) -{ - gamepad_state *s; - int i; - - s = (gamepad_state *)qemu_mallocz(sizeof (gamepad_state)); - s->buttons = (gamepad_button *)qemu_mallocz(n * sizeof (gamepad_button)); - for (i = 0; i < n; i++) { - s->buttons[i].irq = irq[i]; - s->buttons[i].keycode = keycode[i]; - } - s->num_buttons = n; - qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s); - register_savevm("stellaris_gamepad", -1, 1, - stellaris_gamepad_save, stellaris_gamepad_load, s); -} diff --git a/pc-bios/boards/lm3s6965evb.dts b/pc-bios/boards/lm3s6965evb.dts new file mode 100644 index 0000000..9bc0128 --- /dev/null +++ b/pc-bios/boards/lm3s6965evb.dts @@ -0,0 +1,212 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu0: ARM,Cortex-M3@0 { + device_type = "cpu"; + reg = <0>; + #interrupt-cells = <1>; + nvic = <&nvic>; + }; + }; + flash@0 { + device_type = "rom"; + reg = <00000000 00040000>; + }; + memory@0 { + device_type = "memory"; + reg = <20000000 00010000>; + }; + bitband@0 { + model = "ARM,bitband-memory"; + reg = <22000000 02000000>; + base = <20000000>; + }; + bitband@1 { + model = "ARM,bitband-memory"; + reg = <42000000 02000000>; + base = <40000000>; + }; + nvic: nvic@0 { + model = "armv7m_nvic"; + interrupt-parent = <&cpu0>; + interrupts = <0>; + interrupt-controller; + #interrupt-cells = <1>; + }; + lm3s6965@0 { + #address-cells = <1>; + #size-cells = <0>; + qemu,fold-bus; + // TODO Watchdog at 0x40000000 + gpioA: gpio@0 { + model = "pl061"; + reg = <40004000>; + interrupt-parent = <&nvic>; + interrupts = <0>; + qemu,gpio = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>; + }; + gpioB: gpio@1 { + model = "pl061"; + reg = <40005000>; + interrupt-parent = <&nvic>; + interrupts = <1>; + qemu,gpio = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>; + }; + gpioC: gpio@2 { + model = "pl061"; + reg = <40006000>; + interrupt-parent = <&nvic>; + interrupts = <2>; + qemu,gpio = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 &oled 0>; + }; + gpioD: gpio@3 { + model = "pl061"; + reg = <40007000>; + interrupt-parent = <&nvic>; + interrupts = <3>; + qemu,gpio = <&ssimux 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>; + float-high = <01>; + }; + ssi@0 { + model = "pl022"; + reg = <40008000>; + interrupt-parent = <&nvic>; + interrupts = <7>; + ssimux: mux@0 { + model = "evb6965-ssi"; + sd@0 { + model = "ssi-sd"; + qemu,parent-bus = "ssi0"; + }; + oled: oled@1 { + model = "ssd0323"; + qemu,parent-bus = "ssi1"; + }; + }; + }; + uart@0 { + model = "luminary,pl011"; + reg = <4000c000>; + interrupt-parent = <&nvic>; + interrupts = <5>; + }; + uart@1 { + model = "luminary,pl011"; + reg = <4000d000>; + interrupt-parent = <&nvic>; + interrupts = <6>; + }; + uart@2 { + model = "luminary,pl011"; + reg = <4000e000>; + interrupt-parent = <&nvic>; + interrupts = ; + }; + i2c@0 { + model = "stellaris-i2c"; + reg = <40020000>; + interrupt-parent = <&nvic>; + interrupts = <8>; + }; + i2c@1 { + model = "stellaris-i2c"; + reg = <40021000>; + interrupt-parent = <&nvic>; + interrupts = ; + }; + gpioE: gpio@4 { + model = "pl061"; + reg = <40024000>; + interrupt-parent = <&nvic>; + interrupts = <4>; + qemu,gpio = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>; + }; + gpioF: gpio@5 { + model = "pl061"; + reg = <40025000>; + interrupt-parent = <&nvic>; + interrupts = ; + qemu,gpio = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>; + }; + gpioG: gpio@6 { + model = "pl061"; + reg = <40026000>; + interrupt-parent = <&nvic>; + interrupts = ; + qemu,gpio = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>; + }; + // TODO PWM at 0x40028000 + // TODO QEI0 at 0x4002c000 + // TODO QEI1 at 0x4002d000 + gptm@0 { + model = "stellaris-gptm"; + reg = <40030000>; + interrupt-parent = <&nvic>; + interrupts = ; + qemu,gpio = <&adc0 0>; + }; + gptm@1 { + model = "stellaris-gptm"; + reg = <40031000>; + interrupt-parent = <&nvic>; + interrupts = ; + qemu,gpio = <&adc0 0>; + }; + gptm@2 { + model = "stellaris-gptm"; + reg = <40032000>; + interrupt-parent = <&nvic>; + interrupts = ; + qemu,gpio = <&adc0 0>; + }; + gptm@3 { + model = "stellaris-gptm"; + reg = <40033000>; + interrupt-parent = <&nvic>; + interrupts = ; + qemu,gpio = <&adc0 0>; + }; + adc0: adc@0 { + model = "stellaris-adc"; + reg = <40038000>; + interrupt-parent = <&nvic>; + interrupts = ; + }; + // TODO Comparator at 0x4003c000 + enet: enet@0 { + model = "stellaris-enet"; + reg = <40048000>; + interrupt-parent = <&nvic>; + interrupts = ; + }; + // TODO Hybernation module at 0x400fc000 + sysctl@0 { + model = "stellaris-sysctl"; + reg = <400fe000>; + interrupt-parent = <&nvic>; + interrupts = ; + did0 = <10010002>; + did1 = <1073402e>; + dc0 = <00ff007f>; + dc1 = <001133ff>; + dc2 = <030f5317>; + dc3 = <0f0f87ff>; + dc4 = <5000007f>; + enet = <&enet>; + }; + buttons@0 { + model = "qemu,gpio-buttons"; + keys = <800000c8 800000d0 800000cb 800000cd 8000001d>; + qemu,gpio = <&gpioE 0 &gpioE 1 &gpioE 2 &gpioE 3 &gpioF 1>; + }; + }; + chosen { + qemu { + bootstrap = "ARMv7-M"; + }; + }; +}; diff --git a/pc-bios/boards/lm3s811evb.dts b/pc-bios/boards/lm3s811evb.dts new file mode 100644 index 0000000..977d080 --- /dev/null +++ b/pc-bios/boards/lm3s811evb.dts @@ -0,0 +1,155 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu0: ARM,Cortex-M3@0 { + device_type = "cpu"; + reg = <0>; + #interrupt-cells = <1>; + nvic = <&nvic>; + }; + }; + flash@0 { + device_type = "rom"; + reg = <00000000 00010000>; + }; + memory@0 { + device_type = "memory"; + reg = <20000000 00002000>; + }; + bitband@0 { + model = "ARM,bitband-memory"; + reg = <22000000 02000000>; + base = <20000000>; + }; + bitband@1 { + model = "ARM,bitband-memory"; + reg = <42000000 02000000>; + base = <40000000>; + }; + nvic: nvic@0 { + model = "armv7m_nvic"; + interrupt-parent = <&cpu0>; + interrupts = <0>; + interrupt-controller; + #interrupt-cells = <1>; + }; + lm3s811@0 { + #address-cells = <1>; + #size-cells = <0>; + qemu,fold-bus; + // TODO Watchdog at 0x40000000 + gpioA: gpio@0 { + model = "pl061"; + reg = <40004000>; + interrupt-parent = <&nvic>; + interrupts = <0>; + qemu,gpio = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>; + }; + gpioB: gpio@1 { + model = "pl061"; + reg = <40005000>; + interrupt-parent = <&nvic>; + interrupts = <1>; + qemu,gpio = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>; + }; + gpioC: gpio@2 { + model = "pl061"; + reg = <40006000>; + interrupt-parent = <&nvic>; + interrupts = <2>; + qemu,gpio = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>; + }; + gpioD: gpio@3 { + model = "pl061"; + reg = <40007000>; + interrupt-parent = <&nvic>; + interrupts = <3>; + qemu,gpio = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>; + }; + ssi@0 { + model = "pl022"; + reg = <40008000>; + interrupt-parent = <&nvic>; + interrupts = <7>; + }; + uart@0 { + model = "luminary,pl011"; + reg = <4000c000>; + interrupt-parent = <&nvic>; + interrupts = <5>; + }; + uart@1 { + model = "luminary,pl011"; + reg = <4000d000>; + interrupt-parent = <&nvic>; + interrupts = <6>; + }; + i2c@0 { + model = "stellaris-i2c"; + reg = <40020000>; + interrupt-parent = <&nvic>; + interrupts = <8>; + oled@0 { + model = "ssd0303"; + address = <3d>; + }; + }; + gpioE: gpio@4 { + model = "pl061"; + reg = <40024000>; + interrupt-parent = <&nvic>; + interrupts = <4>; + qemu,gpio = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>; + }; + // TODO PWM at 0x40028000 + gptm@0 { + model = "stellaris-gptm"; + reg = <40030000>; + interrupt-parent = <&nvic>; + interrupts = ; + qemu,gpio = <&adc0 0>; + }; + gptm@1 { + model = "stellaris-gptm"; + reg = <40031000>; + interrupt-parent = <&nvic>; + interrupts = ; + qemu,gpio = <&adc0 0>; + }; + gptm@2 { + model = "stellaris-gptm"; + reg = <40032000>; + interrupt-parent = <&nvic>; + interrupts = ; + qemu,gpio = <&adc0 0>; + }; + adc0: adc@0 { + model = "stellaris-adc"; + reg = <40038000>; + interrupt-parent = <&nvic>; + interrupts = ; + }; + sysctl@0 { + model = "stellaris-sysctl"; + reg = <400fe000>; + interrupt-parent = <&nvic>; + interrupts = ; + did0 = <00000000>; + did1 = <0032000e>; + dc0 = <001f001f>; + dc1 = <001132bf>; + dc2 = <01071013>; + dc3 = <3f0f01ff>; + dc4 = <0000001f>; + }; + }; + chosen { + qemu { + bootstrap = "ARMv7-M"; + }; + }; +};