* [RFC PATCH 0/6] Introduce GPIO transmitter and connect to NPCM7xx
@ 2021-12-16 1:54 Joe Komlodi
2021-12-16 1:54 ` [RFC PATCH 1/6] hw/gpio/gpio_transmitter: Add Device Joe Komlodi
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: Joe Komlodi @ 2021-12-16 1:54 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, venture, hskinnemoen, kfting
Hi all,
This series introduces a GPIO transmitter, which allows the transmission
of GPIO controller pin state over chardev, and attaches it to the NPCM7xx
GPIO controller.
The GPIO transmitter takes in a GPIO controller number and a bitfield
containing the GPIO state of that controller, then formats a packet and
sends it via chardev to whomever is listening for it.
The purpose of this is for external software to receive the packet and
interpret it so it can do any actions it needs to, based on GPIO state.
For example, in our use case, we have a VM manager managing an x86 guest
and an ARM (NPCM7xx) guest. On real hardware, the ARM SoC is a BMC which
has some power control over the x86 SoC.
Because of this, we need to relay GPIO power events from the BMC to the
x86 machine (i.e. reset, power off, etc), so we have software read in
the GPIO transmitter packets, keep track of what power state the x86
machine is in based on the GPIO state of the BMC, and notify the VM
manager of any important changes.
The VM manager can then power up/down and reset the x86 machine as
needed.
Thanks!
Joe
Joe Komlodi (6):
hw/gpio/gpio_transmitter: Add Device
hw/gpio/gpio_transmitter: Add allowlist
hw/gpio/npcm7xx: Number controllers
hw/arm/npcm7xx: gpio: Add GPIO transmitter
hw/gpio/npcm7xx: init GPIO transmitter allowlist
qtests/gpio_transmitter: Add test
hw/arm/Kconfig | 1 +
hw/arm/npcm7xx.c | 8 +
hw/gpio/Kconfig | 3 +
hw/gpio/google_gpio_transmitter.c | 249 ++++++++++++++++++++++
hw/gpio/meson.build | 1 +
hw/gpio/npcm7xx_gpio.c | 25 +++
include/hw/arm/npcm7xx.h | 2 +
include/hw/gpio/google_gpio_transmitter.h | 66 ++++++
include/hw/gpio/npcm7xx_gpio.h | 4 +
tests/qtest/google_gpio_tx-test.c | 216 +++++++++++++++++++
tests/qtest/meson.build | 1 +
11 files changed, 576 insertions(+)
create mode 100644 hw/gpio/google_gpio_transmitter.c
create mode 100644 include/hw/gpio/google_gpio_transmitter.h
create mode 100644 tests/qtest/google_gpio_tx-test.c
--
2.34.1.173.g76aa8bc2d0-goog
^ permalink raw reply [flat|nested] 8+ messages in thread
* [RFC PATCH 1/6] hw/gpio/gpio_transmitter: Add Device
2021-12-16 1:54 [RFC PATCH 0/6] Introduce GPIO transmitter and connect to NPCM7xx Joe Komlodi
@ 2021-12-16 1:54 ` Joe Komlodi
2021-12-16 1:54 ` [RFC PATCH 2/6] hw/gpio/gpio_transmitter: Add allowlist Joe Komlodi
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Joe Komlodi @ 2021-12-16 1:54 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, venture, hskinnemoen, kfting
This adds a GPIO transmitter, a device which takes in the GPIO state of
a GPIO controller and transmits it via chardev.
The purpose of this device is to relay any GPIO changes to external
software that may need to act on them.
To integrate this device into a GPIO controller, the GPIO transmitter
should be initialized like any other device, then any GPIO controllers
being initialized should get a pointer to the transmitter.
To transmit data, the GPIO controller calls google_gpio_tx_transmit()
with the GPIO controller's controller number (i.e. which controller is
currently transmitting out of how many exist in the machine), and the
state of the GPIO pins on that controller.
On an error, the GPIO transmitter doesn't provide any feedback to the
controller and only logs a guest error. This is because it is a
completely separate entity from the GPIO controller and the GPIO
controller doesn't care about it, and because any
errors would be the fault of the external software receiving the GPIO
transmitter packets.
Signed-off-by: Joe Komlodi <komlodi@google.com>
---
hw/gpio/Kconfig | 3 +
hw/gpio/google_gpio_transmitter.c | 127 ++++++++++++++++++++++
hw/gpio/meson.build | 1 +
include/hw/gpio/google_gpio_transmitter.h | 46 ++++++++
4 files changed, 177 insertions(+)
create mode 100644 hw/gpio/google_gpio_transmitter.c
create mode 100644 include/hw/gpio/google_gpio_transmitter.h
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
index f0e7405f6e..760646cc3a 100644
--- a/hw/gpio/Kconfig
+++ b/hw/gpio/Kconfig
@@ -13,3 +13,6 @@ config GPIO_PWR
config SIFIVE_GPIO
bool
+
+config GOOGLE_GPIO_TRANSMITTER
+ bool
diff --git a/hw/gpio/google_gpio_transmitter.c b/hw/gpio/google_gpio_transmitter.c
new file mode 100644
index 0000000000..3429121ccb
--- /dev/null
+++ b/hw/gpio/google_gpio_transmitter.c
@@ -0,0 +1,127 @@
+/*
+ * Google GPIO Transmitter.
+ *
+ * This is a fake hardware model that does not exist on any board or IC.
+ * The purpose of this model is to aggregate GPIO state changes from a GPIO
+ * controller and transmit them via chardev.
+ *
+ * Copyright 2021 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/gpio/google_gpio_transmitter.h"
+#include "hw/qdev-properties-system.h"
+#include "hw/sysbus.h"
+#include "chardev/char-fe.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+
+#define PACKET_REVISION 0x01
+
+void google_gpio_tx_transmit(GoogleGPIOTXState *s, uint8_t controller,
+ uint32_t gpios)
+{
+ uint8_t packet[6];
+
+ packet[0] = PACKET_REVISION;
+ packet[1] = controller;
+ memcpy(&packet[2], &gpios, sizeof(gpios));
+ qemu_chr_fe_write_all(&s->chr, packet, ARRAY_SIZE(packet));
+}
+
+static void google_gpio_tx_event(void *opaque, QEMUChrEvent evt)
+{
+ switch (evt) {
+ case CHR_EVENT_OPENED:
+ case CHR_EVENT_CLOSED:
+ case CHR_EVENT_BREAK:
+ case CHR_EVENT_MUX_IN:
+ case CHR_EVENT_MUX_OUT:
+ /*
+ * Ignore events.
+ * Our behavior stays the same regardless of what happens.
+ */
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static void google_gpio_tx_receive(void *opaque, const uint8_t *buf, int size)
+{
+ GoogleGPIOTXState *s = GOOGLE_GPIO_TX(opaque);
+
+ switch (buf[0]) {
+ case GPIOTXCODE_OK:
+ break;
+ case GPIOTXCODE_MALFORMED_PKT:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Transmitted malformed packet\n",
+ object_get_canonical_path(OBJECT(s)));
+ break;
+ case GPIOTXCODE_UNKNOWN_VERSION:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Transmitted malformed packet "
+ "with a version the recipent can't handle. Sent "
+ "version %d\n", object_get_canonical_path(OBJECT(s)),
+ PACKET_REVISION);
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Unknown response 0x%x\n",
+ object_get_canonical_path(OBJECT(s)), buf[0]);
+ break;
+ }
+
+ if (size != 1) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Expects packets only of length 1\n",
+ object_get_canonical_path(OBJECT(s)));
+ }
+}
+
+static int google_gpio_tx_can_receive(void *opaque)
+{
+ return 1;
+}
+
+static void google_gpio_tx_realize(DeviceState *dev, Error **errp)
+{
+ GoogleGPIOTXState *s = GOOGLE_GPIO_TX(dev);
+
+ qemu_chr_fe_set_handlers(&s->chr, google_gpio_tx_can_receive,
+ google_gpio_tx_receive,
+ google_gpio_tx_event,
+ NULL, OBJECT(s), NULL, true);
+}
+
+static Property google_gpio_properties[] = {
+ DEFINE_PROP_CHR("gpio-chardev", GoogleGPIOTXState, chr),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void google_gpio_tx_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->desc = "Google GPIO Controller Transmitter";
+ dc->realize = google_gpio_tx_realize;
+ device_class_set_props(dc, google_gpio_properties);
+}
+
+static const TypeInfo google_gpio_tx_types[] = {
+ {
+ .name = TYPE_GOOGLE_GPIO_TRANSMITTER,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(GoogleGPIOTXState),
+ .class_init = google_gpio_tx_class_init,
+ },
+};
+
+DEFINE_TYPES(google_gpio_tx_types);
diff --git a/include/hw/gpio/google_gpio_transmitter.h b/include/hw/gpio/google_gpio_transmitter.h
new file mode 100644
index 0000000000..fa7d7b3b77
--- /dev/null
+++ b/include/hw/gpio/google_gpio_transmitter.h
@@ -0,0 +1,46 @@
+/*
+ * Google GPIO Transmitter.
+ *
+ * This is a fake hardware model that does not exist on any board or IC.
+ * The purpose of this model is to aggregate GPIO state changes from a GPIO
+ * controller and transmit them via chardev.
+ *
+ * Copyright 2021 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+#ifndef GOOGLE_GPIO_TRANSMITTER_H
+#define GOOGLE_GPIO_TRANSMITTER_H
+
+#include "chardev/char-fe.h"
+#include "hw/sysbus.h"
+
+#define TYPE_GOOGLE_GPIO_TRANSMITTER "google.gpio-transmitter"
+#define GOOGLE_GPIO_TX(obj) \
+ OBJECT_CHECK(GoogleGPIOTXState, (obj), TYPE_GOOGLE_GPIO_TRANSMITTER)
+
+#define GPIO_TX_NUM_CONTROLLERS 8
+
+typedef enum {
+ GPIOTXCODE_OK = 0x00,
+ GPIOTXCODE_MALFORMED_PKT = 0xe0,
+ GPIOTXCODE_UNKNOWN_VERSION = 0xe1,
+} GoogleGPIOTXCode;
+
+typedef struct {
+ SysBusDevice parent;
+
+ CharBackend chr;
+} GoogleGPIOTXState;
+
+void google_gpio_tx_transmit(GoogleGPIOTXState *s, uint8_t controller,
+ uint32_t gpios);
+
+#endif /* GOOGLE_GPIO_TRANSMITTER_H */
--
2.34.1.173.g76aa8bc2d0-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [RFC PATCH 2/6] hw/gpio/gpio_transmitter: Add allowlist
2021-12-16 1:54 [RFC PATCH 0/6] Introduce GPIO transmitter and connect to NPCM7xx Joe Komlodi
2021-12-16 1:54 ` [RFC PATCH 1/6] hw/gpio/gpio_transmitter: Add Device Joe Komlodi
@ 2021-12-16 1:54 ` Joe Komlodi
2021-12-16 1:54 ` [RFC PATCH 3/6] hw/gpio/npcm7xx: Number controllers Joe Komlodi
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Joe Komlodi @ 2021-12-16 1:54 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, venture, hskinnemoen, kfting
To avoid spamming whoever is connected to the chardev any time a pin state
changes, we'll provide an allowlist so the transmitter only transmits on
state changes the user cares about.
The allowlist is a qdev property that takes in an array of pin numbers
to pay attention to, and maps it to a relative pin number on a
controller, assuming each controller has 32-bits of pins.
If no allowlist is specified, we transmit on any pin update.
Signed-off-by: Joe Komlodi <komlodi@google.com>
---
hw/gpio/google_gpio_transmitter.c | 122 ++++++++++++++++++++++
include/hw/gpio/google_gpio_transmitter.h | 20 ++++
2 files changed, 142 insertions(+)
diff --git a/hw/gpio/google_gpio_transmitter.c b/hw/gpio/google_gpio_transmitter.c
index 3429121ccb..b0331e8f03 100644
--- a/hw/gpio/google_gpio_transmitter.c
+++ b/hw/gpio/google_gpio_transmitter.c
@@ -19,6 +19,7 @@
#include "qemu/osdep.h"
+#include "migration/vmstate.h"
#include "hw/gpio/google_gpio_transmitter.h"
#include "hw/qdev-properties-system.h"
#include "hw/sysbus.h"
@@ -28,11 +29,36 @@
#define PACKET_REVISION 0x01
+static bool google_gpio_tx_check_allowlist(GoogleGPIOTXState *s,
+ uint32_t controller, uint32_t gpios)
+{
+ /* If the user didn't give us a list, allow everything */
+ if (!s->gpio_state_by_ctlr) {
+ return true;
+ }
+
+ GPIOCtlrState *gs = g_hash_table_lookup(s->gpio_state_by_ctlr, &controller);
+
+ if (!gs) {
+ return false;
+ }
+
+ bool updated = (gs->gpios & gs->allowed) != (gpios & gs->allowed);
+ /* Update the new state */
+ gs->gpios = gpios;
+
+ return updated;
+}
+
void google_gpio_tx_transmit(GoogleGPIOTXState *s, uint8_t controller,
uint32_t gpios)
{
uint8_t packet[6];
+ if (!google_gpio_tx_check_allowlist(s, controller, gpios)) {
+ return;
+ }
+
packet[0] = PACKET_REVISION;
packet[1] = controller;
memcpy(&packet[2], &gpios, sizeof(gpios));
@@ -91,18 +117,112 @@ static int google_gpio_tx_can_receive(void *opaque)
return 1;
}
+void google_gpio_tx_state_init(GoogleGPIOTXState *s, uint8_t controller,
+ uint32_t gpios)
+{
+ if (!s->gpio_state_by_ctlr) {
+ return;
+ }
+
+ GPIOCtlrState *gs = g_hash_table_lookup(s->gpio_state_by_ctlr, &controller);
+ if (gs) {
+ gs->gpios = gpios;
+ }
+}
+
+void google_gpio_tx_allowlist_qdev_init(GoogleGPIOTXState *s,
+ const uint32_t *allowed_pins,
+ size_t num)
+{
+ size_t i;
+ char propname[64];
+
+ qdev_prop_set_uint32(DEVICE(s), "len-gpio-allowlist", num);
+
+ for (i = 0; i < num; i++) {
+ snprintf(propname, sizeof(propname), "gpio-allowlist[%zu]", i);
+ qdev_prop_set_uint32(DEVICE(s), propname, allowed_pins[i]);
+ }
+}
+
+static void google_gpio_tx_allowlist_init(GoogleGPIOTXState *s)
+{
+ size_t i;
+ GPIOCtlrState *gs;
+
+ if (!s->gpio_allowlist) {
+ return;
+ }
+
+ s->gpio_state_by_ctlr = g_hash_table_new_full(g_int_hash, g_int_equal,
+ g_free, g_free);
+
+ for (i = 0; i < s->gpio_allowlist_sz; i++) {
+ uint32_t controller = s->gpio_allowlist[i] / 32;
+ uint32_t pin = (1 << (s->gpio_allowlist[i] % 32));
+
+ gs = g_hash_table_lookup(s->gpio_state_by_ctlr, &controller);
+ if (gs) {
+ gs->allowed |= pin;
+ } else {
+ gs = g_malloc0(sizeof(*gs));
+ gs->allowed |= pin;
+ /*
+ * The hash table relies on a pointer to be the key, so the pointer
+ * containing the controller num must remain unchanged.
+ * Because of that, just allocate a new key with the controller num.
+ */
+ uint32_t *ctlr = g_memdup(&controller, sizeof(controller));
+ g_hash_table_insert(s->gpio_state_by_ctlr, ctlr, gs);
+ }
+ }
+}
+
static void google_gpio_tx_realize(DeviceState *dev, Error **errp)
{
GoogleGPIOTXState *s = GOOGLE_GPIO_TX(dev);
+ google_gpio_tx_allowlist_init(s);
+
qemu_chr_fe_set_handlers(&s->chr, google_gpio_tx_can_receive,
google_gpio_tx_receive,
google_gpio_tx_event,
NULL, OBJECT(s), NULL, true);
}
+static void google_gpio_tx_finalize(Object *obj)
+{
+ GoogleGPIOTXState *s = GOOGLE_GPIO_TX(obj);
+
+ g_hash_table_destroy(s->gpio_state_by_ctlr);
+ g_free(s->gpio_allowlist);
+}
+
+static int google_gpio_tx_post_load(void *opaque, int version_id)
+{
+ GoogleGPIOTXState *s = GOOGLE_GPIO_TX(opaque);
+
+ google_gpio_tx_allowlist_init(s);
+ return 0;
+}
+
+static const VMStateDescription vmstate_google_gpio_tx = {
+ .name = "gpio_transmitter",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .post_load = google_gpio_tx_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_VARRAY_UINT32(gpio_allowlist, GoogleGPIOTXState,
+ gpio_allowlist_sz, 0, vmstate_info_uint32,
+ uint32_t),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static Property google_gpio_properties[] = {
DEFINE_PROP_CHR("gpio-chardev", GoogleGPIOTXState, chr),
+ DEFINE_PROP_ARRAY("gpio-allowlist", GoogleGPIOTXState, gpio_allowlist_sz,
+ gpio_allowlist, qdev_prop_uint32, uint32_t),
DEFINE_PROP_END_OF_LIST(),
};
@@ -112,6 +232,7 @@ static void google_gpio_tx_class_init(ObjectClass *klass, void *data)
dc->desc = "Google GPIO Controller Transmitter";
dc->realize = google_gpio_tx_realize;
+ dc->vmsd = &vmstate_google_gpio_tx;
device_class_set_props(dc, google_gpio_properties);
}
@@ -120,6 +241,7 @@ static const TypeInfo google_gpio_tx_types[] = {
.name = TYPE_GOOGLE_GPIO_TRANSMITTER,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(GoogleGPIOTXState),
+ .instance_finalize = google_gpio_tx_finalize,
.class_init = google_gpio_tx_class_init,
},
};
diff --git a/include/hw/gpio/google_gpio_transmitter.h b/include/hw/gpio/google_gpio_transmitter.h
index fa7d7b3b77..ddc3561372 100644
--- a/include/hw/gpio/google_gpio_transmitter.h
+++ b/include/hw/gpio/google_gpio_transmitter.h
@@ -34,13 +34,33 @@ typedef enum {
GPIOTXCODE_UNKNOWN_VERSION = 0xe1,
} GoogleGPIOTXCode;
+typedef struct {
+ uint32_t gpios;
+ uint32_t allowed;
+} GPIOCtlrState;
+
typedef struct {
SysBusDevice parent;
+ GHashTable *gpio_state_by_ctlr;
+ uint32_t *gpio_allowlist;
+ uint32_t gpio_allowlist_sz;
+
CharBackend chr;
} GoogleGPIOTXState;
void google_gpio_tx_transmit(GoogleGPIOTXState *s, uint8_t controller,
uint32_t gpios);
+/*
+ * If using an allowlist, this function should be called by the GPIO controller
+ * to set an initial state of the controller's GPIO pins.
+ * Otherwise all pins will be assumed to have an initial state of 0.
+ */
+void google_gpio_tx_state_init(GoogleGPIOTXState *s, uint8_t controller,
+ uint32_t gpios);
+/* Helper function to be called to initialize the allowlist qdev properties */
+void google_gpio_tx_allowlist_qdev_init(GoogleGPIOTXState *s,
+ const uint32_t *allowed_pins,
+ size_t num);
#endif /* GOOGLE_GPIO_TRANSMITTER_H */
--
2.34.1.173.g76aa8bc2d0-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [RFC PATCH 3/6] hw/gpio/npcm7xx: Number controllers
2021-12-16 1:54 [RFC PATCH 0/6] Introduce GPIO transmitter and connect to NPCM7xx Joe Komlodi
2021-12-16 1:54 ` [RFC PATCH 1/6] hw/gpio/gpio_transmitter: Add Device Joe Komlodi
2021-12-16 1:54 ` [RFC PATCH 2/6] hw/gpio/gpio_transmitter: Add allowlist Joe Komlodi
@ 2021-12-16 1:54 ` Joe Komlodi
2021-12-16 1:54 ` [RFC PATCH 4/6] hw/arm/npcm7xx: gpio: Add GPIO transmitter Joe Komlodi
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Joe Komlodi @ 2021-12-16 1:54 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, venture, hskinnemoen, kfting
For transmitting the GPIO state to the outside world, the GPIO transmitter will
need to know which controller's state has been updated.
To do this, we'll just number each controller at initialization.
Signed-off-by: Joe Komlodi <komlodi@google.com>
---
hw/arm/npcm7xx.c | 1 +
hw/gpio/npcm7xx_gpio.c | 2 ++
include/hw/gpio/npcm7xx_gpio.h | 1 +
3 files changed, 4 insertions(+)
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index ace21d8943..6a48a9a6d4 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -595,6 +595,7 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
for (i = 0; i < ARRAY_SIZE(s->gpio); i++) {
Object *obj = OBJECT(&s->gpio[i]);
+ object_property_set_uint(obj, "controller-num", i, &error_abort);
object_property_set_uint(obj, "reset-pullup",
npcm7xx_gpio[i].reset_pu, &error_abort);
object_property_set_uint(obj, "reset-pulldown",
diff --git a/hw/gpio/npcm7xx_gpio.c b/hw/gpio/npcm7xx_gpio.c
index 3376901ab1..5075f61b3b 100644
--- a/hw/gpio/npcm7xx_gpio.c
+++ b/hw/gpio/npcm7xx_gpio.c
@@ -387,6 +387,8 @@ static const VMStateDescription vmstate_npcm7xx_gpio = {
};
static Property npcm7xx_gpio_properties[] = {
+ /* The GPIO controller number (out of 8) */
+ DEFINE_PROP_UINT8("controller-num", NPCM7xxGPIOState, controller_num, 0),
/* Bit n set => pin n has pullup enabled by default. */
DEFINE_PROP_UINT32("reset-pullup", NPCM7xxGPIOState, reset_pu, 0),
/* Bit n set => pin n has pulldown enabled by default. */
diff --git a/include/hw/gpio/npcm7xx_gpio.h b/include/hw/gpio/npcm7xx_gpio.h
index b1d771bd77..b065bba1c5 100644
--- a/include/hw/gpio/npcm7xx_gpio.h
+++ b/include/hw/gpio/npcm7xx_gpio.h
@@ -35,6 +35,7 @@ typedef struct NPCM7xxGPIOState {
uint32_t reset_pd;
uint32_t reset_osrc;
uint32_t reset_odsc;
+ uint8_t controller_num;
MemoryRegion mmio;
--
2.34.1.173.g76aa8bc2d0-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [RFC PATCH 4/6] hw/arm/npcm7xx: gpio: Add GPIO transmitter
2021-12-16 1:54 [RFC PATCH 0/6] Introduce GPIO transmitter and connect to NPCM7xx Joe Komlodi
` (2 preceding siblings ...)
2021-12-16 1:54 ` [RFC PATCH 3/6] hw/gpio/npcm7xx: Number controllers Joe Komlodi
@ 2021-12-16 1:54 ` Joe Komlodi
2021-12-16 1:54 ` [RFC PATCH 5/6] hw/gpio/npcm7xx: init GPIO transmitter allowlist Joe Komlodi
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Joe Komlodi @ 2021-12-16 1:54 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, venture, hskinnemoen, kfting
This adds the GPIO transmitter to the NPCM7xx GPIO controller and
transmits packets any time the pin state changes.
Signed-off-by: Joe Komlodi <komlodi@google.com>
---
hw/arm/Kconfig | 1 +
hw/arm/npcm7xx.c | 7 +++++++
hw/gpio/npcm7xx_gpio.c | 14 ++++++++++++++
include/hw/arm/npcm7xx.h | 2 ++
include/hw/gpio/npcm7xx_gpio.h | 3 +++
5 files changed, 27 insertions(+)
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index ac11493667..046e277db8 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -399,6 +399,7 @@ config NPCM7XX
select UNIMP
select PCA954X
+ select GOOGLE_GPIO_TRANSMITTER
config FSL_IMX25
bool
select IMX
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 6a48a9a6d4..b3a65e5298 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -433,6 +433,9 @@ static void npcm7xx_init(Object *obj)
object_initialize_child(obj, "gpio[*]", &s->gpio[i], TYPE_NPCM7XX_GPIO);
}
+ object_initialize_child(obj, "gpiotx", &s->gpiotx,
+ TYPE_GOOGLE_GPIO_TRANSMITTER);
+
for (i = 0; i < ARRAY_SIZE(s->smbus); i++) {
object_initialize_child(obj, "smbus[*]", &s->smbus[i],
TYPE_NPCM7XX_SMBUS);
@@ -590,11 +593,15 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
sysbus_realize(SYS_BUS_DEVICE(&s->rng), &error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->rng), 0, NPCM7XX_RNG_BA);
+ sysbus_realize(SYS_BUS_DEVICE(&s->gpiotx), &error_abort);
+
/* GPIO modules. Cannot fail. */
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_gpio) != ARRAY_SIZE(s->gpio));
for (i = 0; i < ARRAY_SIZE(s->gpio); i++) {
Object *obj = OBJECT(&s->gpio[i]);
+ object_property_set_link(obj, "gpio-tx", OBJECT(&s->gpiotx),
+ &error_abort);
object_property_set_uint(obj, "controller-num", i, &error_abort);
object_property_set_uint(obj, "reset-pullup",
npcm7xx_gpio[i].reset_pu, &error_abort);
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
index db62c4ed00..900436f901 100644
--- a/hw/gpio/meson.build
+++ b/hw/gpio/meson.build
@@ -7,6 +7,7 @@ softmmu_ss.add(when: 'CONFIG_ZAURUS', if_true: files('zaurus.c'))
softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_gpio.c'))
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_gpio.c'))
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('google_gpio_transmitter.c'))
softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_gpio.c'))
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_gpio.c'))
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_gpio.c'))
diff --git a/hw/gpio/npcm7xx_gpio.c b/hw/gpio/npcm7xx_gpio.c
index 5075f61b3b..0d683903a2 100644
--- a/hw/gpio/npcm7xx_gpio.c
+++ b/hw/gpio/npcm7xx_gpio.c
@@ -65,6 +65,16 @@ enum NPCM7xxGPIORegister {
#define NPCM7XX_GPIO_LOCK_MAGIC1 (0xc0defa73)
#define NPCM7XX_GPIO_LOCK_MAGIC2 (0xc0de1248)
+static void npcm7xx_gpio_tx_state(NPCM7xxGPIOState *s)
+{
+ uint32_t state = s->regs[NPCM7XX_GPIO_DOUT] | s->regs[NPCM7XX_GPIO_DIN];
+
+ /* Only TX if we have a transmitter */
+ if (s->txs) {
+ google_gpio_tx_transmit(s->txs, s->controller_num, state);
+ }
+}
+
static void npcm7xx_gpio_update_events(NPCM7xxGPIOState *s, uint32_t din_diff)
{
uint32_t din_new = s->regs[NPCM7XX_GPIO_DIN];
@@ -147,6 +157,7 @@ static void npcm7xx_gpio_update_pins(NPCM7xxGPIOState *s, uint32_t diff)
/* See if any new events triggered because of all this. */
npcm7xx_gpio_update_events(s, din_old ^ s->regs[NPCM7XX_GPIO_DIN]);
+ npcm7xx_gpio_tx_state(s);
}
static bool npcm7xx_gpio_is_locked(NPCM7xxGPIOState *s)
@@ -387,6 +398,9 @@ static const VMStateDescription vmstate_npcm7xx_gpio = {
};
static Property npcm7xx_gpio_properties[] = {
+ /* Pointer to the GPIO state transmitter */
+ DEFINE_PROP_LINK("gpio-tx", NPCM7xxGPIOState, txs,
+ TYPE_GOOGLE_GPIO_TRANSMITTER, GoogleGPIOTXState *),
/* The GPIO controller number (out of 8) */
DEFINE_PROP_UINT8("controller-num", NPCM7xxGPIOState, controller_num, 0),
/* Bit n set => pin n has pullup enabled by default. */
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index 106cfb55bf..a52650010f 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -21,6 +21,7 @@
#include "hw/core/split-irq.h"
#include "hw/cpu/a9mpcore.h"
#include "hw/gpio/npcm7xx_gpio.h"
+#include "hw/gpio/google_gpio_transmitter.h"
#include "hw/i2c/npcm7xx_smbus.h"
#include "hw/mem/npcm7xx_mc.h"
#include "hw/misc/npcm7xx_clk.h"
@@ -99,6 +100,7 @@ typedef struct NPCM7xxState {
NPCM7xxMCState mc;
NPCM7xxRNGState rng;
NPCM7xxGPIOState gpio[8];
+ GoogleGPIOTXState gpiotx;
NPCM7xxSMBusState smbus[16];
EHCISysBusState ehci;
OHCISysBusState ohci;
diff --git a/include/hw/gpio/npcm7xx_gpio.h b/include/hw/gpio/npcm7xx_gpio.h
index b065bba1c5..69c1004a6c 100644
--- a/include/hw/gpio/npcm7xx_gpio.h
+++ b/include/hw/gpio/npcm7xx_gpio.h
@@ -17,6 +17,7 @@
#include "exec/memory.h"
#include "hw/sysbus.h"
+#include "hw/gpio/google_gpio_transmitter.h"
/* Number of pins managed by each controller. */
#define NPCM7XX_GPIO_NR_PINS (32)
@@ -30,6 +31,8 @@
typedef struct NPCM7xxGPIOState {
SysBusDevice parent;
+ GoogleGPIOTXState *txs;
+
/* Properties to be defined by the SoC */
uint32_t reset_pu;
uint32_t reset_pd;
--
2.34.1.173.g76aa8bc2d0-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [RFC PATCH 5/6] hw/gpio/npcm7xx: init GPIO transmitter allowlist
2021-12-16 1:54 [RFC PATCH 0/6] Introduce GPIO transmitter and connect to NPCM7xx Joe Komlodi
` (3 preceding siblings ...)
2021-12-16 1:54 ` [RFC PATCH 4/6] hw/arm/npcm7xx: gpio: Add GPIO transmitter Joe Komlodi
@ 2021-12-16 1:54 ` Joe Komlodi
2021-12-16 1:54 ` [RFC PATCH 6/6] qtests/gpio_transmitter: Add test Joe Komlodi
2021-12-16 9:24 ` [RFC PATCH 0/6] Introduce GPIO transmitter and connect to NPCM7xx Philippe Mathieu-Daudé
6 siblings, 0 replies; 8+ messages in thread
From: Joe Komlodi @ 2021-12-16 1:54 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, venture, hskinnemoen, kfting
For the GPIO transmitter to properly transmit on pin changes, it must
know the initial state of the GPIO pins on the controller.
Signed-off-by: Joe Komlodi <komlodi@google.com>
---
hw/gpio/npcm7xx_gpio.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/hw/gpio/npcm7xx_gpio.c b/hw/gpio/npcm7xx_gpio.c
index 0d683903a2..64a74c87a5 100644
--- a/hw/gpio/npcm7xx_gpio.c
+++ b/hw/gpio/npcm7xx_gpio.c
@@ -370,6 +370,14 @@ static void npcm7xx_gpio_hold_reset(Object *obj)
npcm7xx_gpio_update_pins(s, -1);
}
+static void npcm7xx_gpio_realize(DeviceState *dev, Error **errp)
+{
+ NPCM7xxGPIOState *s = NPCM7XX_GPIO(dev);
+ uint32_t state = s->regs[NPCM7XX_GPIO_DOUT] | s->regs[NPCM7XX_GPIO_DIN];
+
+ google_gpio_tx_state_init(s->txs, s->controller_num, state);
+}
+
static void npcm7xx_gpio_init(Object *obj)
{
NPCM7xxGPIOState *s = NPCM7XX_GPIO(obj);
@@ -423,6 +431,7 @@ static void npcm7xx_gpio_class_init(ObjectClass *klass, void *data)
dc->desc = "NPCM7xx GPIO Controller";
dc->vmsd = &vmstate_npcm7xx_gpio;
+ dc->realize = npcm7xx_gpio_realize;
reset->phases.enter = npcm7xx_gpio_enter_reset;
reset->phases.hold = npcm7xx_gpio_hold_reset;
device_class_set_props(dc, npcm7xx_gpio_properties);
--
2.34.1.173.g76aa8bc2d0-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [RFC PATCH 6/6] qtests/gpio_transmitter: Add test
2021-12-16 1:54 [RFC PATCH 0/6] Introduce GPIO transmitter and connect to NPCM7xx Joe Komlodi
` (4 preceding siblings ...)
2021-12-16 1:54 ` [RFC PATCH 5/6] hw/gpio/npcm7xx: init GPIO transmitter allowlist Joe Komlodi
@ 2021-12-16 1:54 ` Joe Komlodi
2021-12-16 9:24 ` [RFC PATCH 0/6] Introduce GPIO transmitter and connect to NPCM7xx Philippe Mathieu-Daudé
6 siblings, 0 replies; 8+ messages in thread
From: Joe Komlodi @ 2021-12-16 1:54 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, venture, hskinnemoen, kfting
This tests each NPCM7xx GPIO controller to make sure that when GPIO state is
updated, the controller sends a request to the GPIO transmitter to transmit the
data via chardev.
Along with that, we verify that the data is formatted correctly.
Signed-off-by: Joe Komlodi <komlodi@google.com>
---
tests/qtest/google_gpio_tx-test.c | 216 ++++++++++++++++++++++++++++++
tests/qtest/meson.build | 1 +
2 files changed, 217 insertions(+)
create mode 100644 tests/qtest/google_gpio_tx-test.c
diff --git a/tests/qtest/google_gpio_tx-test.c b/tests/qtest/google_gpio_tx-test.c
new file mode 100644
index 0000000000..651c0501bc
--- /dev/null
+++ b/tests/qtest/google_gpio_tx-test.c
@@ -0,0 +1,216 @@
+/*
+ * QTest testcase for the Google GPIO Transmitter, using the NPCM7xx GPIO
+ * controller.
+ *
+ * Copyright 2021 Google LLC
+ *
+ * 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 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.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest-single.h"
+#include "libqos/libqtest.h"
+
+#define NR_GPIO_DEVICES (8)
+#define GPIO(x) (0xf0010000 + (x) * 0x1000)
+
+/* GPIO registers */
+#define GP_N_TLOCK1 0x00
+#define GP_N_DIN 0x04 /* Data IN */
+#define GP_N_POL 0x08 /* Polarity */
+#define GP_N_DOUT 0x0c /* Data OUT */
+#define GP_N_OE 0x10 /* Output Enable */
+#define GP_N_OTYP 0x14
+#define GP_N_MP 0x18
+#define GP_N_PU 0x1c /* Pull-up */
+#define GP_N_PD 0x20 /* Pull-down */
+#define GP_N_DBNC 0x24 /* Debounce */
+#define GP_N_EVTYP 0x28 /* Event Type */
+#define GP_N_EVBE 0x2c /* Event Both Edge */
+#define GP_N_OBL0 0x30
+#define GP_N_OBL1 0x34
+#define GP_N_OBL2 0x38
+#define GP_N_OBL3 0x3c
+#define GP_N_EVEN 0x40 /* Event Enable */
+#define GP_N_EVENS 0x44 /* Event Set (enable) */
+#define GP_N_EVENC 0x48 /* Event Clear (disable) */
+#define GP_N_EVST 0x4c /* Event Status */
+#define GP_N_SPLCK 0x50
+#define GP_N_MPLCK 0x54
+#define GP_N_IEM 0x58 /* Input Enable */
+#define GP_N_OSRC 0x5c
+#define GP_N_ODSC 0x60
+#define GP_N_DOS 0x68 /* Data OUT Set */
+#define GP_N_DOC 0x6c /* Data OUT Clear */
+#define GP_N_OES 0x70 /* Output Enable Set */
+#define GP_N_OEC 0x74 /* Output Enable Clear */
+#define GP_N_TLOCK2 0x7c
+
+#define PACKET_REVISION 0x01
+
+typedef enum {
+ GPIOTXCODE_OK = 0x00,
+ GPIOTXCODE_MALFORMED_PKT = 0xe0,
+ GPIOTXCODE_UNKNOWN_VERSION = 0xe1,
+} GPIOTXCode;
+
+static int sock;
+static int fd;
+
+static in_port_t open_socket(void)
+{
+ struct sockaddr_in myaddr;
+ struct timeval timeout = { .tv_sec = 1, };
+ socklen_t addrlen;
+
+ myaddr.sin_family = AF_INET;
+ myaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ myaddr.sin_port = 0;
+ sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ g_assert(sock != -1);
+ g_assert(bind(sock, (struct sockaddr *) &myaddr, sizeof(myaddr)) != -1);
+ setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
+
+ addrlen = sizeof(myaddr);
+ g_assert(getsockname(sock, (struct sockaddr *) &myaddr , &addrlen) != -1);
+ g_assert(listen(sock, 1) != -1);
+ return ntohs(myaddr.sin_port);
+}
+
+static void setup_fd(void)
+{
+ fd_set readfds;
+
+ FD_ZERO(&readfds);
+ FD_SET(sock, &readfds);
+ g_assert(select(sock + 1, &readfds, NULL, NULL, NULL) == 1);
+
+ fd = accept(sock, NULL, 0);
+}
+
+/*
+ * The GPIO controller is naturally chatty and will send us state updates when
+ * any register is written to, since it could impact the GPIO state.
+ * For our purposes, we only care when we set DOUT, so we use this to discard
+
+ * state changes we don't care about.
+ */
+static void purge_read_queue(void)
+{
+ uint8_t buf[256];
+ ssize_t ret;
+
+ do {
+ ret = read(fd, buf, sizeof(buf));
+ } while (ret > 0);
+}
+
+static void gpio_unlock(int n)
+{
+ if (readl(GPIO(n) + GP_N_TLOCK1) != 0) {
+ writel(GPIO(n) + GP_N_TLOCK2, 0xc0de1248);
+ writel(GPIO(n) + GP_N_TLOCK1, 0xc0defa73);
+ }
+}
+
+/* Restore the GPIO controller to a sensible default state. */
+static void gpio_reset(int n)
+{
+ gpio_unlock(0);
+
+ writel(GPIO(n) + GP_N_EVEN, 0x00000000);
+ writel(GPIO(n) + GP_N_EVST, 0xffffffff);
+ writel(GPIO(n) + GP_N_POL, 0x00000000);
+ writel(GPIO(n) + GP_N_DOUT, 0x00000000);
+ writel(GPIO(n) + GP_N_OE, 0x00000000);
+ writel(GPIO(n) + GP_N_OTYP, 0x00000000);
+ writel(GPIO(n) + GP_N_PU, 0xffffffff);
+ writel(GPIO(n) + GP_N_PD, 0x00000000);
+ writel(GPIO(n) + GP_N_IEM, 0xffffffff);
+}
+
+static void set_dout(int n, uint32_t val)
+{
+ gpio_reset(n);
+ writel(GPIO(n) + GP_N_OE, 0xffffffff);
+ /* Remove anything the controller TXed from reset and OEN */
+ purge_read_queue();
+
+ writel(GPIO(n) + GP_N_DOUT, val);
+ g_assert_cmphex(readl(GPIO(n) + GP_N_DOUT), ==, val);
+}
+
+static void read_data(uint8_t *data, size_t len)
+{
+ ssize_t ret;
+ size_t len_read = 0;
+
+ while (len_read < len) {
+ ret = read(fd, &data[len_read], len);
+ g_assert_cmpint(ret, !=, -1);
+
+ len_read += ret;
+ }
+}
+
+/*
+ * Set DOUT, ensure only the allowed pin triggers a packet tx, then receive the
+ * state update TXed by the controller.
+ */
+static void test_gpio_n_tx(gconstpointer test_data)
+{
+ uint8_t packet[6];
+ uint32_t gpio_state;
+ intptr_t n = (intptr_t)test_data;
+ uint8_t resp;
+ ssize_t ret;
+
+ set_dout(n, 0xaa55aa55);
+ read_data(packet, sizeof(packet));
+ gpio_state = *(uint32_t *)&packet[2];
+
+ g_assert_cmpint(packet[0], ==, PACKET_REVISION);
+ g_assert_cmpint(packet[1], ==, n);
+ g_assert_cmpint(gpio_state, ==, 0xaa55aa55);
+
+ /* All good */
+ resp = 0x00;
+ ret = write(fd, &resp, sizeof(resp));
+ g_assert_cmpint(ret, !=, -1);
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+ size_t i;
+ int port;
+
+ g_test_init(&argc, &argv, NULL);
+ port = open_socket();
+
+ global_qtest = qtest_initf("-machine npcm750-evb "
+ "-chardev socket,id=google-gpio-tx-chr,port=%d,host=localhost "
+ "-global driver=google.gpio-transmitter,property=gpio-chardev,"
+ "value=google-gpio-tx-chr",
+ port);
+ setup_fd();
+
+ for (i = 0; i < NR_GPIO_DEVICES; i++) {
+ g_autofree char *test_name =
+ g_strdup_printf("/google_gpio_tx/gpio[%zu]/tx", i);
+ qtest_add_data_func(test_name, (void *)(intptr_t)i, test_gpio_n_tx);
+ }
+
+ ret = g_test_run();
+ qtest_end();
+
+ return ret;
+}
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index ee171f7423..d7b36f89af 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -160,6 +160,7 @@ qtests_sparc64 = \
qtests_npcm7xx = \
['npcm7xx_adc-test',
'npcm7xx_gpio-test',
+ 'google_gpio_tx-test',
'npcm7xx_pwm-test',
'npcm7xx_rng-test',
'npcm7xx_smbus-test',
--
2.34.1.173.g76aa8bc2d0-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [RFC PATCH 0/6] Introduce GPIO transmitter and connect to NPCM7xx
2021-12-16 1:54 [RFC PATCH 0/6] Introduce GPIO transmitter and connect to NPCM7xx Joe Komlodi
` (5 preceding siblings ...)
2021-12-16 1:54 ` [RFC PATCH 6/6] qtests/gpio_transmitter: Add test Joe Komlodi
@ 2021-12-16 9:24 ` Philippe Mathieu-Daudé
6 siblings, 0 replies; 8+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-12-16 9:24 UTC (permalink / raw)
To: Joe Komlodi, qemu-devel, Marc-André Lureau,
Dr. David Alan Gilbert
Cc: peter.maydell, kfting, hskinnemoen, venture
+Marc-André (chardev) & Dave
On 12/16/21 02:54, Joe Komlodi wrote:
> Hi all,
>
> This series introduces a GPIO transmitter, which allows the transmission
> of GPIO controller pin state over chardev, and attaches it to the NPCM7xx
> GPIO controller.
>
> The GPIO transmitter takes in a GPIO controller number and a bitfield
> containing the GPIO state of that controller, then formats a packet and
> sends it via chardev to whomever is listening for it.
> The purpose of this is for external software to receive the packet and
> interpret it so it can do any actions it needs to, based on GPIO state.
>
> For example, in our use case, we have a VM manager managing an x86 guest
> and an ARM (NPCM7xx) guest. On real hardware, the ARM SoC is a BMC which
> has some power control over the x86 SoC.
> Because of this, we need to relay GPIO power events from the BMC to the
> x86 machine (i.e. reset, power off, etc), so we have software read in
> the GPIO transmitter packets, keep track of what power state the x86
> machine is in based on the GPIO state of the BMC, and notify the VM
> manager of any important changes.
> The VM manager can then power up/down and reset the x86 machine as
> needed.
>
> Thanks!
> Joe
>
> Joe Komlodi (6):
> hw/gpio/gpio_transmitter: Add Device
> hw/gpio/gpio_transmitter: Add allowlist
> hw/gpio/npcm7xx: Number controllers
> hw/arm/npcm7xx: gpio: Add GPIO transmitter
> hw/gpio/npcm7xx: init GPIO transmitter allowlist
> qtests/gpio_transmitter: Add test
>
> hw/arm/Kconfig | 1 +
> hw/arm/npcm7xx.c | 8 +
> hw/gpio/Kconfig | 3 +
> hw/gpio/google_gpio_transmitter.c | 249 ++++++++++++++++++++++
> hw/gpio/meson.build | 1 +
> hw/gpio/npcm7xx_gpio.c | 25 +++
> include/hw/arm/npcm7xx.h | 2 +
> include/hw/gpio/google_gpio_transmitter.h | 66 ++++++
> include/hw/gpio/npcm7xx_gpio.h | 4 +
> tests/qtest/google_gpio_tx-test.c | 216 +++++++++++++++++++
> tests/qtest/meson.build | 1 +
> 11 files changed, 576 insertions(+)
> create mode 100644 hw/gpio/google_gpio_transmitter.c
> create mode 100644 include/hw/gpio/google_gpio_transmitter.h
> create mode 100644 tests/qtest/google_gpio_tx-test.c
>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2021-12-16 9:25 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-12-16 1:54 [RFC PATCH 0/6] Introduce GPIO transmitter and connect to NPCM7xx Joe Komlodi
2021-12-16 1:54 ` [RFC PATCH 1/6] hw/gpio/gpio_transmitter: Add Device Joe Komlodi
2021-12-16 1:54 ` [RFC PATCH 2/6] hw/gpio/gpio_transmitter: Add allowlist Joe Komlodi
2021-12-16 1:54 ` [RFC PATCH 3/6] hw/gpio/npcm7xx: Number controllers Joe Komlodi
2021-12-16 1:54 ` [RFC PATCH 4/6] hw/arm/npcm7xx: gpio: Add GPIO transmitter Joe Komlodi
2021-12-16 1:54 ` [RFC PATCH 5/6] hw/gpio/npcm7xx: init GPIO transmitter allowlist Joe Komlodi
2021-12-16 1:54 ` [RFC PATCH 6/6] qtests/gpio_transmitter: Add test Joe Komlodi
2021-12-16 9:24 ` [RFC PATCH 0/6] Introduce GPIO transmitter and connect to NPCM7xx Philippe Mathieu-Daudé
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).