summaryrefslogtreecommitdiffstats
path: root/qemu/hw/gpio
diff options
context:
space:
mode:
authorJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-05-18 13:18:31 +0300
committerJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-05-18 13:42:15 +0300
commit437fd90c0250dee670290f9b714253671a990160 (patch)
treeb871786c360704244a07411c69fb58da9ead4a06 /qemu/hw/gpio
parent5bbd6fe9b8bab2a93e548c5a53b032d1939eec05 (diff)
These changes are the raw update to qemu-2.6.
Collission happened in the following patches: migration: do cleanup operation after completion(738df5b9) Bug fix.(1750c932f86) kvmclock: add a new function to update env->tsc.(b52baab2) The code provided by the patches was already in the upstreamed version. Change-Id: I3cc11841a6a76ae20887b2e245710199e1ea7f9a Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'qemu/hw/gpio')
-rw-r--r--qemu/hw/gpio/Makefile.objs2
-rw-r--r--qemu/hw/gpio/gpio_key.c104
-rw-r--r--qemu/hw/gpio/imx_gpio.c350
-rw-r--r--qemu/hw/gpio/max7310.c1
-rw-r--r--qemu/hw/gpio/mpc8xxx.c1
-rw-r--r--qemu/hw/gpio/omap_gpio.c34
-rw-r--r--qemu/hw/gpio/pl061.c68
-rw-r--r--qemu/hw/gpio/puv3_gpio.c1
-rw-r--r--qemu/hw/gpio/zaurus.c6
9 files changed, 536 insertions, 31 deletions
diff --git a/qemu/hw/gpio/Makefile.objs b/qemu/hw/gpio/Makefile.objs
index 1abcf1798..a43c7cf44 100644
--- a/qemu/hw/gpio/Makefile.objs
+++ b/qemu/hw/gpio/Makefile.objs
@@ -3,5 +3,7 @@ common-obj-$(CONFIG_PL061) += pl061.o
common-obj-$(CONFIG_PUV3) += puv3_gpio.o
common-obj-$(CONFIG_ZAURUS) += zaurus.o
common-obj-$(CONFIG_E500) += mpc8xxx.o
+common-obj-$(CONFIG_GPIO_KEY) += gpio_key.o
obj-$(CONFIG_OMAP) += omap_gpio.o
+obj-$(CONFIG_IMX) += imx_gpio.o
diff --git a/qemu/hw/gpio/gpio_key.c b/qemu/hw/gpio/gpio_key.c
new file mode 100644
index 000000000..ef287727b
--- /dev/null
+++ b/qemu/hw/gpio/gpio_key.c
@@ -0,0 +1,104 @@
+/*
+ * GPIO key
+ *
+ * Copyright (c) 2016 Linaro Limited
+ *
+ * Author: Shannon Zhao <shannon.zhao@linaro.org>
+ *
+ * Emulate a (human) keypress -- when the key is triggered by
+ * setting the incoming gpio line, the outbound irq line is
+ * raised for 100ms before being dropped again.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+
+#define TYPE_GPIOKEY "gpio-key"
+#define GPIOKEY(obj) OBJECT_CHECK(GPIOKEYState, (obj), TYPE_GPIOKEY)
+#define GPIO_KEY_LATENCY 100 /* 100ms */
+
+typedef struct GPIOKEYState {
+ SysBusDevice parent_obj;
+
+ QEMUTimer *timer;
+ qemu_irq irq;
+} GPIOKEYState;
+
+static const VMStateDescription vmstate_gpio_key = {
+ .name = "gpio-key",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_TIMER_PTR(timer, GPIOKEYState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void gpio_key_reset(DeviceState *dev)
+{
+ GPIOKEYState *s = GPIOKEY(dev);
+
+ timer_del(s->timer);
+}
+
+static void gpio_key_timer_expired(void *opaque)
+{
+ GPIOKEYState *s = (GPIOKEYState *)opaque;
+
+ qemu_set_irq(s->irq, 0);
+ timer_del(s->timer);
+}
+
+static void gpio_key_set_irq(void *opaque, int irq, int level)
+{
+ GPIOKEYState *s = (GPIOKEYState *)opaque;
+
+ qemu_set_irq(s->irq, 1);
+ timer_mod(s->timer,
+ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + GPIO_KEY_LATENCY);
+}
+
+static void gpio_key_realize(DeviceState *dev, Error **errp)
+{
+ GPIOKEYState *s = GPIOKEY(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+ sysbus_init_irq(sbd, &s->irq);
+ qdev_init_gpio_in(dev, gpio_key_set_irq, 1);
+ s->timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, gpio_key_timer_expired, s);
+}
+
+static void gpio_key_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = gpio_key_realize;
+ dc->vmsd = &vmstate_gpio_key;
+ dc->reset = &gpio_key_reset;
+}
+
+static const TypeInfo gpio_key_info = {
+ .name = TYPE_GPIOKEY,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(GPIOKEYState),
+ .class_init = gpio_key_class_init,
+};
+
+static void gpio_key_register_types(void)
+{
+ type_register_static(&gpio_key_info);
+}
+
+type_init(gpio_key_register_types)
diff --git a/qemu/hw/gpio/imx_gpio.c b/qemu/hw/gpio/imx_gpio.c
new file mode 100644
index 000000000..ed7e247f5
--- /dev/null
+++ b/qemu/hw/gpio/imx_gpio.c
@@ -0,0 +1,350 @@
+/*
+ * i.MX processors GPIO emulation.
+ *
+ * Copyright (C) 2015 Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/gpio/imx_gpio.h"
+
+#ifndef DEBUG_IMX_GPIO
+#define DEBUG_IMX_GPIO 0
+#endif
+
+typedef enum IMXGPIOLevel {
+ IMX_GPIO_LEVEL_LOW = 0,
+ IMX_GPIO_LEVEL_HIGH = 1,
+} IMXGPIOLevel;
+
+#define DPRINTF(fmt, args...) \
+ do { \
+ if (DEBUG_IMX_GPIO) { \
+ fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_GPIO, \
+ __func__, ##args); \
+ } \
+ } while (0)
+
+static const char *imx_gpio_reg_name(uint32_t reg)
+{
+ switch (reg) {
+ case DR_ADDR:
+ return "DR";
+ case GDIR_ADDR:
+ return "GDIR";
+ case PSR_ADDR:
+ return "PSR";
+ case ICR1_ADDR:
+ return "ICR1";
+ case ICR2_ADDR:
+ return "ICR2";
+ case IMR_ADDR:
+ return "IMR";
+ case ISR_ADDR:
+ return "ISR";
+ case EDGE_SEL_ADDR:
+ return "EDGE_SEL";
+ default:
+ return "[?]";
+ }
+}
+
+static void imx_gpio_update_int(IMXGPIOState *s)
+{
+ if (s->has_upper_pin_irq) {
+ qemu_set_irq(s->irq[0], (s->isr & s->imr & 0x0000FFFF) ? 1 : 0);
+ qemu_set_irq(s->irq[1], (s->isr & s->imr & 0xFFFF0000) ? 1 : 0);
+ } else {
+ qemu_set_irq(s->irq[0], (s->isr & s->imr) ? 1 : 0);
+ }
+}
+
+static void imx_gpio_set_int_line(IMXGPIOState *s, int line, IMXGPIOLevel level)
+{
+ /* if this signal isn't configured as an input signal, nothing to do */
+ if (!extract32(s->gdir, line, 1)) {
+ return;
+ }
+
+ /* When set, EDGE_SEL overrides the ICR config */
+ if (extract32(s->edge_sel, line, 1)) {
+ /* we detect interrupt on rising and falling edge */
+ if (extract32(s->psr, line, 1) != level) {
+ /* level changed */
+ s->isr = deposit32(s->isr, line, 1, 1);
+ }
+ } else if (extract64(s->icr, 2*line + 1, 1)) {
+ /* interrupt is edge sensitive */
+ if (extract32(s->psr, line, 1) != level) {
+ /* level changed */
+ if (extract64(s->icr, 2*line, 1) != level) {
+ s->isr = deposit32(s->isr, line, 1, 1);
+ }
+ }
+ } else {
+ /* interrupt is level sensitive */
+ if (extract64(s->icr, 2*line, 1) == level) {
+ s->isr = deposit32(s->isr, line, 1, 1);
+ }
+ }
+}
+
+static void imx_gpio_set(void *opaque, int line, int level)
+{
+ IMXGPIOState *s = IMX_GPIO(opaque);
+ IMXGPIOLevel imx_level = level ? IMX_GPIO_LEVEL_HIGH : IMX_GPIO_LEVEL_LOW;
+
+ imx_gpio_set_int_line(s, line, imx_level);
+
+ /* this is an input signal, so set PSR */
+ s->psr = deposit32(s->psr, line, 1, imx_level);
+
+ imx_gpio_update_int(s);
+}
+
+static void imx_gpio_set_all_int_lines(IMXGPIOState *s)
+{
+ int i;
+
+ for (i = 0; i < IMX_GPIO_PIN_COUNT; i++) {
+ IMXGPIOLevel imx_level = extract32(s->psr, i, 1);
+ imx_gpio_set_int_line(s, i, imx_level);
+ }
+
+ imx_gpio_update_int(s);
+}
+
+static inline void imx_gpio_set_all_output_lines(IMXGPIOState *s)
+{
+ int i;
+
+ for (i = 0; i < IMX_GPIO_PIN_COUNT; i++) {
+ /*
+ * if the line is set as output, then forward the line
+ * level to its user.
+ */
+ if (extract32(s->gdir, i, 1) && s->output[i]) {
+ qemu_set_irq(s->output[i], extract32(s->dr, i, 1));
+ }
+ }
+}
+
+static uint64_t imx_gpio_read(void *opaque, hwaddr offset, unsigned size)
+{
+ IMXGPIOState *s = IMX_GPIO(opaque);
+ uint32_t reg_value = 0;
+
+ switch (offset) {
+ case DR_ADDR:
+ /*
+ * depending on the "line" configuration, the bit values
+ * are coming either from DR or PSR
+ */
+ reg_value = (s->dr & s->gdir) | (s->psr & ~s->gdir);
+ break;
+
+ case GDIR_ADDR:
+ reg_value = s->gdir;
+ break;
+
+ case PSR_ADDR:
+ reg_value = s->psr & ~s->gdir;
+ break;
+
+ case ICR1_ADDR:
+ reg_value = extract64(s->icr, 0, 32);
+ break;
+
+ case ICR2_ADDR:
+ reg_value = extract64(s->icr, 32, 32);
+ break;
+
+ case IMR_ADDR:
+ reg_value = s->imr;
+ break;
+
+ case ISR_ADDR:
+ reg_value = s->isr;
+ break;
+
+ case EDGE_SEL_ADDR:
+ if (s->has_edge_sel) {
+ reg_value = s->edge_sel;
+ } else {
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: EDGE_SEL register not "
+ "present on this version of GPIO device\n",
+ TYPE_IMX_GPIO, __func__);
+ }
+ break;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
+ HWADDR_PRIx "\n", TYPE_IMX_GPIO, __func__, offset);
+ break;
+ }
+
+ DPRINTF("(%s) = 0x%" PRIx32 "\n", imx_gpio_reg_name(offset), reg_value);
+
+ return reg_value;
+}
+
+static void imx_gpio_write(void *opaque, hwaddr offset, uint64_t value,
+ unsigned size)
+{
+ IMXGPIOState *s = IMX_GPIO(opaque);
+
+ DPRINTF("(%s, value = 0x%" PRIx32 ")\n", imx_gpio_reg_name(offset),
+ (uint32_t)value);
+
+ switch (offset) {
+ case DR_ADDR:
+ s->dr = value;
+ imx_gpio_set_all_output_lines(s);
+ break;
+
+ case GDIR_ADDR:
+ s->gdir = value;
+ imx_gpio_set_all_output_lines(s);
+ imx_gpio_set_all_int_lines(s);
+ break;
+
+ case ICR1_ADDR:
+ s->icr = deposit64(s->icr, 0, 32, value);
+ imx_gpio_set_all_int_lines(s);
+ break;
+
+ case ICR2_ADDR:
+ s->icr = deposit64(s->icr, 32, 32, value);
+ imx_gpio_set_all_int_lines(s);
+ break;
+
+ case IMR_ADDR:
+ s->imr = value;
+ imx_gpio_update_int(s);
+ break;
+
+ case ISR_ADDR:
+ s->isr |= ~value;
+ imx_gpio_set_all_int_lines(s);
+ break;
+
+ case EDGE_SEL_ADDR:
+ if (s->has_edge_sel) {
+ s->edge_sel = value;
+ imx_gpio_set_all_int_lines(s);
+ } else {
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: EDGE_SEL register not "
+ "present on this version of GPIO device\n",
+ TYPE_IMX_GPIO, __func__);
+ }
+ break;
+
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
+ HWADDR_PRIx "\n", TYPE_IMX_GPIO, __func__, offset);
+ break;
+ }
+
+ return;
+}
+
+static const MemoryRegionOps imx_gpio_ops = {
+ .read = imx_gpio_read,
+ .write = imx_gpio_write,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_imx_gpio = {
+ .name = TYPE_IMX_GPIO,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(dr, IMXGPIOState),
+ VMSTATE_UINT32(gdir, IMXGPIOState),
+ VMSTATE_UINT32(psr, IMXGPIOState),
+ VMSTATE_UINT64(icr, IMXGPIOState),
+ VMSTATE_UINT32(imr, IMXGPIOState),
+ VMSTATE_UINT32(isr, IMXGPIOState),
+ VMSTATE_BOOL(has_edge_sel, IMXGPIOState),
+ VMSTATE_UINT32(edge_sel, IMXGPIOState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static Property imx_gpio_properties[] = {
+ DEFINE_PROP_BOOL("has-edge-sel", IMXGPIOState, has_edge_sel, true),
+ DEFINE_PROP_BOOL("has-upper-pin-irq", IMXGPIOState, has_upper_pin_irq,
+ false),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void imx_gpio_reset(DeviceState *dev)
+{
+ IMXGPIOState *s = IMX_GPIO(dev);
+
+ s->dr = 0;
+ s->gdir = 0;
+ s->psr = 0;
+ s->icr = 0;
+ s->imr = 0;
+ s->isr = 0;
+ s->edge_sel = 0;
+
+ imx_gpio_set_all_output_lines(s);
+ imx_gpio_update_int(s);
+}
+
+static void imx_gpio_realize(DeviceState *dev, Error **errp)
+{
+ IMXGPIOState *s = IMX_GPIO(dev);
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &imx_gpio_ops, s,
+ TYPE_IMX_GPIO, IMX_GPIO_MEM_SIZE);
+
+ qdev_init_gpio_in(DEVICE(s), imx_gpio_set, IMX_GPIO_PIN_COUNT);
+ qdev_init_gpio_out(DEVICE(s), s->output, IMX_GPIO_PIN_COUNT);
+
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[0]);
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[1]);
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
+}
+
+static void imx_gpio_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = imx_gpio_realize;
+ dc->reset = imx_gpio_reset;
+ dc->props = imx_gpio_properties;
+ dc->vmsd = &vmstate_imx_gpio;
+ dc->desc = "i.MX GPIO controller";
+}
+
+static const TypeInfo imx_gpio_info = {
+ .name = TYPE_IMX_GPIO,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IMXGPIOState),
+ .class_init = imx_gpio_class_init,
+};
+
+static void imx_gpio_register_types(void)
+{
+ type_register_static(&imx_gpio_info);
+}
+
+type_init(imx_gpio_register_types)
diff --git a/qemu/hw/gpio/max7310.c b/qemu/hw/gpio/max7310.c
index 2f59b134e..1bd5eaf91 100644
--- a/qemu/hw/gpio/max7310.c
+++ b/qemu/hw/gpio/max7310.c
@@ -7,6 +7,7 @@
* This file is licensed under GNU GPL.
*/
+#include "qemu/osdep.h"
#include "hw/i2c/i2c.h"
#define TYPE_MAX7310 "max7310"
diff --git a/qemu/hw/gpio/mpc8xxx.c b/qemu/hw/gpio/mpc8xxx.c
index 1aeaaaaf0..d14971946 100644
--- a/qemu/hw/gpio/mpc8xxx.c
+++ b/qemu/hw/gpio/mpc8xxx.c
@@ -19,6 +19,7 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
#include "hw/sysbus.h"
#define TYPE_MPC8XXX_GPIO "mpc8xxx_gpio"
diff --git a/qemu/hw/gpio/omap_gpio.c b/qemu/hw/gpio/omap_gpio.c
index d92f8cfba..9b1b004fc 100644
--- a/qemu/hw/gpio/omap_gpio.c
+++ b/qemu/hw/gpio/omap_gpio.c
@@ -18,9 +18,11 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/arm/omap.h"
#include "hw/sysbus.h"
+#include "qemu/error-report.h"
struct omap_gpio_s {
qemu_irq irq;
@@ -682,7 +684,8 @@ static int omap_gpio_init(SysBusDevice *sbd)
struct omap_gpif_s *s = OMAP1_GPIO(dev);
if (!s->clk) {
- hw_error("omap-gpio: clk not connected\n");
+ error_report("omap-gpio: clk not connected");
+ return -1;
}
qdev_init_gpio_in(dev, omap_gpio_set, 16);
qdev_init_gpio_out(dev, s->omap1.handler, 16);
@@ -700,25 +703,35 @@ static int omap2_gpio_init(SysBusDevice *sbd)
int i;
if (!s->iclk) {
- hw_error("omap2-gpio: iclk not connected\n");
+ error_report("omap2-gpio: iclk not connected");
+ return -1;
}
+
+ s->modulecount = s->mpu_model < omap2430 ? 4
+ : s->mpu_model < omap3430 ? 5
+ : 6;
+
+ for (i = 0; i < s->modulecount; i++) {
+ if (!s->fclk[i]) {
+ error_report("omap2-gpio: fclk%d not connected", i);
+ return -1;
+ }
+ }
+
if (s->mpu_model < omap3430) {
- s->modulecount = (s->mpu_model < omap2430) ? 4 : 5;
memory_region_init_io(&s->iomem, OBJECT(s), &omap2_gpif_top_ops, s,
"omap2.gpio", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
- } else {
- s->modulecount = 6;
}
- s->modules = g_malloc0(s->modulecount * sizeof(struct omap2_gpio_s));
- s->handler = g_malloc0(s->modulecount * 32 * sizeof(qemu_irq));
+
+ s->modules = g_new0(struct omap2_gpio_s, s->modulecount);
+ s->handler = g_new0(qemu_irq, s->modulecount * 32);
qdev_init_gpio_in(dev, omap2_gpio_set, s->modulecount * 32);
qdev_init_gpio_out(dev, s->handler, s->modulecount * 32);
+
for (i = 0; i < s->modulecount; i++) {
struct omap2_gpio_s *m = &s->modules[i];
- if (!s->fclk[i]) {
- hw_error("omap2-gpio: fclk%d not connected\n", i);
- }
+
m->revision = (s->mpu_model < omap3430) ? 0x18 : 0x25;
m->handler = &s->handler[i * 32];
sysbus_init_irq(sbd, &m->irq[0]); /* mpu irq */
@@ -728,6 +741,7 @@ static int omap2_gpio_init(SysBusDevice *sbd)
"omap.gpio-module", 0x1000);
sysbus_init_mmio(sbd, &m->iomem);
}
+
return 0;
}
diff --git a/qemu/hw/gpio/pl061.c b/qemu/hw/gpio/pl061.c
index 4ba730b47..29dc7fc38 100644
--- a/qemu/hw/gpio/pl061.c
+++ b/qemu/hw/gpio/pl061.c
@@ -8,6 +8,7 @@
* This code is licensed under the GPL.
*/
+#include "qemu/osdep.h"
#include "hw/sysbus.h"
//#define DEBUG_PL061 1
@@ -55,17 +56,17 @@ typedef struct PL061State {
uint32_t slr;
uint32_t den;
uint32_t cr;
- uint32_t float_high;
uint32_t amsel;
qemu_irq irq;
qemu_irq out[8];
const unsigned char *id;
+ uint32_t rsvd_start; /* reserved area: [rsvd_start, 0xfcc] */
} PL061State;
static const VMStateDescription vmstate_pl061 = {
.name = "pl061",
- .version_id = 3,
- .minimum_version_id = 3,
+ .version_id = 4,
+ .minimum_version_id = 4,
.fields = (VMStateField[]) {
VMSTATE_UINT32(locked, PL061State),
VMSTATE_UINT32(data, PL061State),
@@ -87,7 +88,6 @@ static const VMStateDescription vmstate_pl061 = {
VMSTATE_UINT32(slr, PL061State),
VMSTATE_UINT32(den, PL061State),
VMSTATE_UINT32(cr, PL061State),
- VMSTATE_UINT32(float_high, PL061State),
VMSTATE_UINT32_V(amsel, PL061State, 2),
VMSTATE_END_OF_LIST()
}
@@ -153,12 +153,15 @@ static uint64_t pl061_read(void *opaque, hwaddr offset,
{
PL061State *s = (PL061State *)opaque;
- if (offset >= 0xfd0 && offset < 0x1000) {
- return s->id[(offset - 0xfd0) >> 2];
- }
if (offset < 0x400) {
return s->data & (offset >> 2);
}
+ if (offset >= s->rsvd_start && offset <= 0xfcc) {
+ goto err_out;
+ }
+ if (offset >= 0xfd0 && offset < 0x1000) {
+ return s->id[(offset - 0xfd0) >> 2];
+ }
switch (offset) {
case 0x400: /* Direction */
return s->dir;
@@ -199,10 +202,12 @@ static uint64_t pl061_read(void *opaque, hwaddr offset,
case 0x528: /* Analog mode select */
return s->amsel;
default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "pl061_read: Bad offset %x\n", (int)offset);
- return 0;
+ break;
}
+err_out:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "pl061_read: Bad offset %x\n", (int)offset);
+ return 0;
}
static void pl061_write(void *opaque, hwaddr offset,
@@ -217,6 +222,9 @@ static void pl061_write(void *opaque, hwaddr offset,
pl061_update(s);
return;
}
+ if (offset >= s->rsvd_start) {
+ goto err_out;
+ }
switch (offset) {
case 0x400: /* Direction */
s->dir = value & 0xff;
@@ -275,16 +283,41 @@ static void pl061_write(void *opaque, hwaddr offset,
s->amsel = value & 0xff;
break;
default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "pl061_write: Bad offset %x\n", (int)offset);
+ goto err_out;
}
pl061_update(s);
+ return;
+err_out:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "pl061_write: Bad offset %x\n", (int)offset);
}
-static void pl061_reset(PL061State *s)
+static void pl061_reset(DeviceState *dev)
{
- s->locked = 1;
- s->cr = 0xff;
+ PL061State *s = PL061(dev);
+
+ /* reset values from PL061 TRM, Stellaris LM3S5P31 & LM3S8962 Data Sheet */
+ s->data = 0;
+ s->old_out_data = 0;
+ s->old_in_data = 0;
+ s->dir = 0;
+ s->isense = 0;
+ s->ibe = 0;
+ s->iev = 0;
+ s->im = 0;
+ s->istate = 0;
+ s->afsel = 0;
+ s->dr2r = 0xff;
+ s->dr4r = 0;
+ s->dr8r = 0;
+ s->odr = 0;
+ s->pur = 0;
+ s->pdr = 0;
+ s->slr = 0;
+ s->den = 0;
+ s->locked = 1;
+ s->cr = 0xff;
+ s->amsel = 0;
}
static void pl061_set_irq(void * opaque, int irq, int level)
@@ -317,7 +350,7 @@ static int pl061_initfn(SysBusDevice *sbd)
sysbus_init_irq(sbd, &s->irq);
qdev_init_gpio_in(dev, pl061_set_irq, 8);
qdev_init_gpio_out(dev, s->out, 8);
- pl061_reset(s);
+
return 0;
}
@@ -326,6 +359,7 @@ static void pl061_luminary_init(Object *obj)
PL061State *s = PL061(obj);
s->id = pl061_id_luminary;
+ s->rsvd_start = 0x52c;
}
static void pl061_init(Object *obj)
@@ -333,6 +367,7 @@ static void pl061_init(Object *obj)
PL061State *s = PL061(obj);
s->id = pl061_id;
+ s->rsvd_start = 0x424;
}
static void pl061_class_init(ObjectClass *klass, void *data)
@@ -342,6 +377,7 @@ static void pl061_class_init(ObjectClass *klass, void *data)
k->init = pl061_initfn;
dc->vmsd = &vmstate_pl061;
+ dc->reset = &pl061_reset;
}
static const TypeInfo pl061_info = {
diff --git a/qemu/hw/gpio/puv3_gpio.c b/qemu/hw/gpio/puv3_gpio.c
index 39840aa73..445afccf9 100644
--- a/qemu/hw/gpio/puv3_gpio.c
+++ b/qemu/hw/gpio/puv3_gpio.c
@@ -8,6 +8,7 @@
* published by the Free Software Foundation, or any later version.
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/sysbus.h"
diff --git a/qemu/hw/gpio/zaurus.c b/qemu/hw/gpio/zaurus.c
index 24a77272d..555da281c 100644
--- a/qemu/hw/gpio/zaurus.c
+++ b/qemu/hw/gpio/zaurus.c
@@ -15,6 +15,7 @@
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/arm/sharpsl.h"
#include "hw/sysbus.h"
@@ -235,10 +236,6 @@ static const VMStateDescription vmstate_scoop_regs = {
},
};
-static Property scoop_sysbus_properties[] = {
- DEFINE_PROP_END_OF_LIST(),
-};
-
static void scoop_sysbus_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -247,7 +244,6 @@ static void scoop_sysbus_class_init(ObjectClass *klass, void *data)
k->init = scoop_init;
dc->desc = "Scoop2 Sharp custom ASIC";
dc->vmsd = &vmstate_scoop_regs;
- dc->props = scoop_sysbus_properties;
}
static const TypeInfo scoop_sysbus_info = {