aboutsummaryrefslogtreecommitdiff
path: root/hw/gpio
diff options
context:
space:
mode:
Diffstat (limited to 'hw/gpio')
-rw-r--r--hw/gpio/pl061.c51
1 files changed, 47 insertions, 4 deletions
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
index 9360c143ee..5ba398fcd4 100644
--- a/hw/gpio/pl061.c
+++ b/hw/gpio/pl061.c
@@ -13,12 +13,28 @@
* + unnamed GPIO inputs 0..7: inputs to connect to the emulated GPIO lines
* + unnamed GPIO outputs 0..7: the emulated GPIO lines, considered as
* outputs
+ * + QOM property "pullups": an integer defining whether non-floating lines
+ * configured as inputs should be pulled up to logical 1 (ie whether in
+ * real hardware they have a pullup resistor on the line out of the PL061).
+ * This should be an 8-bit value, where bit 0 is 1 if GPIO line 0 should
+ * be pulled high, bit 1 configures line 1, and so on. The default is 0xff,
+ * indicating that all GPIO lines are pulled up to logical 1.
+ * + QOM property "pulldowns": an integer defining whether non-floating lines
+ * configured as inputs should be pulled down to logical 0 (ie whether in
+ * real hardware they have a pulldown resistor on the line out of the PL061).
+ * This should be an 8-bit value, where bit 0 is 1 if GPIO line 0 should
+ * be pulled low, bit 1 configures line 1, and so on. The default is 0x0.
+ * It is an error to set a bit in both "pullups" and "pulldowns". If a bit
+ * is 0 in both, then the line is considered to be floating, and it will
+ * not have qemu_set_irq() called on it when it is configured as an input.
*/
#include "qemu/osdep.h"
#include "hw/irq.h"
#include "hw/sysbus.h"
+#include "hw/qdev-properties.h"
#include "migration/vmstate.h"
+#include "qapi/error.h"
#include "qemu/log.h"
#include "qemu/module.h"
#include "qom/object.h"
@@ -62,6 +78,9 @@ struct PL061State {
qemu_irq irq;
qemu_irq out[N_GPIOS];
const unsigned char *id;
+ /* Properties, for non-Luminary PL061 */
+ uint32_t pullups;
+ uint32_t pulldowns;
};
static const VMStateDescription vmstate_pl061 = {
@@ -109,8 +128,7 @@ static uint8_t pl061_floating(PL061State *s)
*/
floating = ~(s->pur | s->pdr);
} else {
- /* Assume outputs are pulled high. FIXME: this is board dependent. */
- floating = 0;
+ floating = ~(s->pullups | s->pulldowns);
}
return floating & ~s->dir;
}
@@ -131,8 +149,7 @@ static uint8_t pl061_pullups(PL061State *s)
*/
pullups = s->pur;
} else {
- /* Assume outputs are pulled high. FIXME: this is board dependent. */
- pullups = 0xff;
+ pullups = s->pullups;
}
return pullups & ~s->dir;
}
@@ -499,12 +516,38 @@ static void pl061_init(Object *obj)
qdev_init_gpio_out(dev, s->out, N_GPIOS);
}
+static void pl061_realize(DeviceState *dev, Error **errp)
+{
+ PL061State *s = PL061(dev);
+
+ if (s->pullups > 0xff) {
+ error_setg(errp, "pullups property must be between 0 and 0xff");
+ return;
+ }
+ if (s->pulldowns > 0xff) {
+ error_setg(errp, "pulldowns property must be between 0 and 0xff");
+ return;
+ }
+ if (s->pullups & s->pulldowns) {
+ error_setg(errp, "no bit may be set both in pullups and pulldowns");
+ return;
+ }
+}
+
+static Property pl061_props[] = {
+ DEFINE_PROP_UINT32("pullups", PL061State, pullups, 0xff),
+ DEFINE_PROP_UINT32("pulldowns", PL061State, pulldowns, 0x0),
+ DEFINE_PROP_END_OF_LIST()
+};
+
static void pl061_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->vmsd = &vmstate_pl061;
dc->reset = &pl061_reset;
+ dc->realize = pl061_realize;
+ device_class_set_props(dc, pl061_props);
}
static const TypeInfo pl061_info = {