From patchwork Thu Dec 16 01:54:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joe Komlodi X-Patchwork-Id: 12679833 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 965AFC433F5 for ; Thu, 16 Dec 2021 02:08:02 +0000 (UTC) Received: from localhost ([::1]:40524 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mxgBd-0004tj-Ih for qemu-devel@archiver.kernel.org; Wed, 15 Dec 2021 21:08:01 -0500 Received: from eggs.gnu.org ([209.51.188.92]:50812) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3S5y6YQcKCoIqusrujomuumrk.iuswks0-jk1krtutmt0.uxm@flex--komlodi.bounces.google.com>) id 1mxg5U-000616-GJ for qemu-devel@nongnu.org; Wed, 15 Dec 2021 21:01:40 -0500 Received: from [2607:f8b0:4864:20::349] (port=54996 helo=mail-ot1-x349.google.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3S5y6YQcKCoIqusrujomuumrk.iuswks0-jk1krtutmt0.uxm@flex--komlodi.bounces.google.com>) id 1mxg5Q-0007k5-SV for qemu-devel@nongnu.org; Wed, 15 Dec 2021 21:01:39 -0500 Received: by mail-ot1-x349.google.com with SMTP id p3-20020a05683019c300b0058663e33ba5so4032252otp.21 for ; Wed, 15 Dec 2021 18:01:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=EPpz9NJRStRYbMsFvYissWf1+qt9BE74PmOZ3x6mxmA=; b=OfbNUaFRYW5GgxdCQ7L/a8h11hEYQaDkiYoa3pR2PECTAv2h0MP7ofjssHSCbvDY+0 PwGa0388uzVf/KUApUWNFY89nhzCbYFZI7YKwstY9dU2cX5p/L4pvRxxMKLaPAzhnR7u uwzywxe9WMLWxw80TGgWrGoTT0mVFczn/25kMbgiO3LVKrNJ8iXBa/ll6yh0d4UMCKgI 6tPhwdL1Eb4tWTEt5+U33fDnFgnreDTMPCgvSH9UimKV/QRP6I+rChw0tnG9zusFZjNa evZEruzXFlMre06XfNVG7PzwqzvHrlflfV7o05PRR8kU2ePOgMQTQ6iyYYvudF+Fcdh4 RyGw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=EPpz9NJRStRYbMsFvYissWf1+qt9BE74PmOZ3x6mxmA=; b=H52kgOEyTL7UvioWqjoTYOzbMpMiiNy+DI3jIGliSLL68DG0JinvsOHaMk9QlRhg44 X/jg82pWAsLXftPwplDvIzFxUWmch//6IflQsdcRhibrdi+LEFMwxly6rVjvTQUiSzsw e1GXbOk2b8mL6eZcGNAuiLi9dBbi/j7bvn6V5B1FO/zwDBAujT9Jtqg62glIHBQ1+WHP oY1iCOz23Efu6XbkucvQlUrXRX1lBz2LDOeB08a07waLvs9m+xniYxC1zMt0bdliP0/C 4oCfweGok0ppu3CkC7Ay68YFX8n9ucOuM2xnHXN0pU9Zh2q6VAJ+cIe4JotxLVkzT90P I/4Q== X-Gm-Message-State: AOAM533BD9fJanYIAO8SgBAzlvIxl8E8cr2y04P3/dFFI/wB25nwwWJK YDarqBmODxJ1QZ6oLW6Nwx+vgx8S1tqEyrwOoVgnyFL10v4n9Shqjtf7bEnUlHOk+3T5YkJZzAx CGaD25k6nt08xRDUXxo1fYy75qWBGOh/XcAukuUxRX6rw7xq15dbfqoEu6Zl5P6A= X-Google-Smtp-Source: ABdhPJzsrTWXqFkW733DPBSWHcjAl/DXV5u6s5urlClt4Bz4k8GzdRm2UOJDP0Q0cxMH3m2noYIXY61mK5Wk X-Received: from komlodi.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:35ee]) (user=komlodi job=sendgmr) by 2002:a17:90a:3d42:: with SMTP id o2mr234654pjf.1.1639619659829; Wed, 15 Dec 2021 17:54:19 -0800 (PST) Date: Thu, 16 Dec 2021 01:54:12 +0000 In-Reply-To: <20211216015417.1234812-1-komlodi@google.com> Message-Id: <20211216015417.1234812-2-komlodi@google.com> Mime-Version: 1.0 References: <20211216015417.1234812-1-komlodi@google.com> X-Mailer: git-send-email 2.34.1.173.g76aa8bc2d0-goog Subject: [RFC PATCH 1/6] hw/gpio/gpio_transmitter: Add Device From: Joe Komlodi To: qemu-devel@nongnu.org Cc: peter.maydell@linaro.org, venture@google.com, hskinnemoen@google.com, kfting@nuvoton.com X-Host-Lookup-Failed: Reverse DNS lookup failed for 2607:f8b0:4864:20::349 (failed) Received-SPF: pass client-ip=2607:f8b0:4864:20::349; envelope-from=3S5y6YQcKCoIqusrujomuumrk.iuswks0-jk1krtutmt0.uxm@flex--komlodi.bounces.google.com; helo=mail-ot1-x349.google.com X-Spam_score_int: -87 X-Spam_score: -8.8 X-Spam_bar: -------- X-Spam_report: (-8.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 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 --- 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 */ From patchwork Thu Dec 16 01:54:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joe Komlodi X-Patchwork-Id: 12679811 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 9F41CC433F5 for ; Thu, 16 Dec 2021 02:01:35 +0000 (UTC) Received: from localhost ([::1]:56772 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mxg5O-00055m-12 for qemu-devel@archiver.kernel.org; Wed, 15 Dec 2021 21:01:34 -0500 Received: from eggs.gnu.org ([209.51.188.92]:50262) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3TZy6YQcKCoQswutwlqowwotm.kwuymu2-lm3mtvwvov2.wzo@flex--komlodi.bounces.google.com>) id 1mxg3Z-0003I7-47 for qemu-devel@nongnu.org; Wed, 15 Dec 2021 20:59:41 -0500 Received: from [2607:f8b0:4864:20::34a] (port=48664 helo=mail-ot1-x34a.google.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3TZy6YQcKCoQswutwlqowwotm.kwuymu2-lm3mtvwvov2.wzo@flex--komlodi.bounces.google.com>) id 1mxg3W-0007Rh-Lf for qemu-devel@nongnu.org; Wed, 15 Dec 2021 20:59:40 -0500 Received: by mail-ot1-x34a.google.com with SMTP id v13-20020a056830140d00b0055c8421bd62so10715567otp.15 for ; Wed, 15 Dec 2021 17:59:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=QQN9Ad1Yq1PXKvpv4A5/4edmKsppTSY8pdqUGWCYZGo=; b=JKf1dTM61Oh8+25BUatVQcSjvZQgGrik/qq+kMl5XPXShBsYiPRhcumNP4x2bSSovU JdyUuNfPjBKkWnG57j3Q/CZ3e1G5PRrT+JJgPPjnBIh/oZuZ/WatD0+a3tBrN0+y90Tn J7MxYide1PFQeiZdJlKESpauIgpNXtwo24gF5yd39qb6zWIXW3M5OmI8Y7iPmXyFy+GB zCB1h8alDuvoShsXvX8JEuYWwUBTh6x6sWQn45/xxd9L/bhBMpo/vPnsyRZtyFwssAcf AueE+rYimdkce+SSRyoxrnTrYXu9WEe3UlDS5qQjKPOuxJGTDu7mFoWdrc9Z164Eud0L MfLw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=QQN9Ad1Yq1PXKvpv4A5/4edmKsppTSY8pdqUGWCYZGo=; b=WBBoWN33aTxCMmIYas25EfnLlZmKf+TO9lNgw3XcR9t2YWzUYdTOgDlyLsv7jz2Cx9 HweG/vac3lVhMIKPbSTjlj6QRDRFEE5iRmz3bjDev2PYtrJE74g6AcwKuMdc8P7vJmVQ Q05Q+6rENgdbe0PS1syDtzoxYiHu3b3PYKwnE4eCyHOc6c+ZklfGQ3OUdAQi0NhUUFbu 8LWHh6JugXibbTQlZ5C26An5mOJy/yr4aweqMSoGDqa0XWuCsBtfEsZ1PJ9rpfpaZ6kr RcmlO9aJ0T+0KdJn3nuNnGnB0C4NjexMp/TL3X62J9KYViKoYjNXzsoiT/sSZNuSycsi lB3w== X-Gm-Message-State: AOAM532P29RVx2rli8a18Yt35Ewue6YkZZfHR7yB8JfNDtmNR3njcLIo yCrKXQzYJ/UftIcAnqcXEBV4cdXFYGOMFofC3s8C3fZ6A0goqYJcIWJFiDyemLx7iYBc2LCCIy5 vjc63b3Zm+SCwTrAnk/84ui3/BFKUn97sIE7QPr1oYQfg7lZuzfIVKhIJiwLC1b8= X-Google-Smtp-Source: ABdhPJw5++u6Kwml2mpt3jQTcimpBlVHlrTNVDzlnpEhHOXhdWOL4Y7lWKJjBx9bkXg5SdbAbOOjuIb788Ja X-Received: from komlodi.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:35ee]) (user=komlodi job=sendgmr) by 2002:a17:90b:128e:: with SMTP id fw14mr3231350pjb.173.1639619661681; Wed, 15 Dec 2021 17:54:21 -0800 (PST) Date: Thu, 16 Dec 2021 01:54:13 +0000 In-Reply-To: <20211216015417.1234812-1-komlodi@google.com> Message-Id: <20211216015417.1234812-3-komlodi@google.com> Mime-Version: 1.0 References: <20211216015417.1234812-1-komlodi@google.com> X-Mailer: git-send-email 2.34.1.173.g76aa8bc2d0-goog Subject: [RFC PATCH 2/6] hw/gpio/gpio_transmitter: Add allowlist From: Joe Komlodi To: qemu-devel@nongnu.org Cc: peter.maydell@linaro.org, venture@google.com, hskinnemoen@google.com, kfting@nuvoton.com X-Host-Lookup-Failed: Reverse DNS lookup failed for 2607:f8b0:4864:20::34a (failed) Received-SPF: pass client-ip=2607:f8b0:4864:20::34a; envelope-from=3TZy6YQcKCoQswutwlqowwotm.kwuymu2-lm3mtvwvov2.wzo@flex--komlodi.bounces.google.com; helo=mail-ot1-x34a.google.com X-Spam_score_int: -87 X-Spam_score: -8.8 X-Spam_bar: -------- X-Spam_report: (-8.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 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 --- 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 */ From patchwork Thu Dec 16 01:54:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joe Komlodi X-Patchwork-Id: 12679815 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5FD28C433EF for ; Thu, 16 Dec 2021 02:03:12 +0000 (UTC) Received: from localhost ([::1]:33854 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mxg6x-0000Cg-Ix for qemu-devel@archiver.kernel.org; Wed, 15 Dec 2021 21:03:11 -0500 Received: from eggs.gnu.org ([209.51.188.92]:50916) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3T5y6YQcKCoYuywvynsqyyqvo.myw0ow4-no5ovxyxqx4.y1q@flex--komlodi.bounces.google.com>) id 1mxg5t-0006F3-Pj for qemu-devel@nongnu.org; Wed, 15 Dec 2021 21:02:06 -0500 Received: from [2607:f8b0:4864:20::249] (port=36588 helo=mail-oi1-x249.google.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3T5y6YQcKCoYuywvynsqyyqvo.myw0ow4-no5ovxyxqx4.y1q@flex--komlodi.bounces.google.com>) id 1mxg5r-0007rY-PD for qemu-devel@nongnu.org; Wed, 15 Dec 2021 21:02:05 -0500 Received: by mail-oi1-x249.google.com with SMTP id e3-20020aca3703000000b002c1f9ecb392so8870452oia.3 for ; Wed, 15 Dec 2021 18:02:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=6qi5FujVcKqpsTRdgntkPSLgLU+R3PZ9Af/Wfz1k8V4=; b=icTy68oIXhSUnegyqXN5M0qvdWpmUiqAXps6OzNYKHTYEKsrFnd2hLJCl+u2bBTwvj nE21B3k9sTHxsUuc85xgehYkmONnHBaFdkQcrKUcGMZXbJOub4I3Xqzf7pm+AmSpHZtc kwx148jjjLb3lCFW9KVOCwg9yUy7ddM0L1AkJWtxGQikF/wA6Cb48U8SzVd4dzVvZMsY flcLxkhQzKuCmWzjeZFkVPIyBVbZhQ6MLKFrQt++S8Bp473Ojj5ctMViz1ll2G29QR4Y 4PK2EOwCaYFA9+Nup9s6FXzgjOIuWUhonXcr2danxHgVi0ZPkpZU14FI6Vi40GsZui7B 4GiQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=6qi5FujVcKqpsTRdgntkPSLgLU+R3PZ9Af/Wfz1k8V4=; b=1Sp074zwfT/fNvjLoYHp5OqpboIfYgmF20TuoO9FLwbWIk13YviqVWMwTIqeFY1iTM ZGq5vmYwDNPj2TvCZCi8HOrsnzSMgnBaVydMwyWiqx9lxhpLA7i6tZCYbjHqahso5sth LQPXv5ydG7i478RAH6x92c2x+qW9zjMdCqDZ095KpnUtDO4OIDniPBme83rSvLGMk4Ti zJPMA49qBFibwl6h10PJRePJceJkWLS2dHSWMc2hc0t4w3oTDd5qTEiqHM4wEl8qW40g 4UhT0KZ/pYKNI2Jc4Ov0BxfAA9uSNQg48xjQJwHZMAp73pjlAj/gA3/IZu91ksMezi0a hMLQ== X-Gm-Message-State: AOAM531hHVZZthjvTFIAp+RpXCOvFwgPn3Doqws+eQkV1+7uz8Tfb0EO uq9XCCDXBtHXSs+QZq9zEe3W6GqpadJVGXw/P3GrlQFSYxIYQtnsbRllAMXo15EObriUeaym+bC S4jw0AvL7X27RaCdrFCN9HWUhEOsLVp1MyJBk5+V22A6h65ZE5cFzENqRY+KY1a0= X-Google-Smtp-Source: ABdhPJxrTHsG5+2c+sQSlHFBBnUm8KLUXsPGSsDXbA7TYndLV52eCGbryefwyD1JyF6VC3iqLm9TzO67HfTO X-Received: from komlodi.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:35ee]) (user=komlodi job=sendgmr) by 2002:a17:90b:4c44:: with SMTP id np4mr3215030pjb.195.1639619663012; Wed, 15 Dec 2021 17:54:23 -0800 (PST) Date: Thu, 16 Dec 2021 01:54:14 +0000 In-Reply-To: <20211216015417.1234812-1-komlodi@google.com> Message-Id: <20211216015417.1234812-4-komlodi@google.com> Mime-Version: 1.0 References: <20211216015417.1234812-1-komlodi@google.com> X-Mailer: git-send-email 2.34.1.173.g76aa8bc2d0-goog Subject: [RFC PATCH 3/6] hw/gpio/npcm7xx: Number controllers From: Joe Komlodi To: qemu-devel@nongnu.org Cc: peter.maydell@linaro.org, venture@google.com, hskinnemoen@google.com, kfting@nuvoton.com X-Host-Lookup-Failed: Reverse DNS lookup failed for 2607:f8b0:4864:20::249 (failed) Received-SPF: pass client-ip=2607:f8b0:4864:20::249; envelope-from=3T5y6YQcKCoYuywvynsqyyqvo.myw0ow4-no5ovxyxqx4.y1q@flex--komlodi.bounces.google.com; helo=mail-oi1-x249.google.com X-Spam_score_int: -87 X-Spam_score: -8.8 X-Spam_bar: -------- X-Spam_report: (-8.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 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 --- 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; From patchwork Thu Dec 16 01:54:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joe Komlodi X-Patchwork-Id: 12679813 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2DAC1C433EF for ; Thu, 16 Dec 2021 02:02:26 +0000 (UTC) Received: from localhost ([::1]:58258 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mxg6D-00067K-0q for qemu-devel@archiver.kernel.org; Wed, 15 Dec 2021 21:02:25 -0500 Received: from eggs.gnu.org ([209.51.188.92]:50380) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3UJy6YQcKCocvzxwzotrzzrwp.nzx1px5-op6pwyzyry5.z2r@flex--komlodi.bounces.google.com>) id 1mxg48-0003sQ-91 for qemu-devel@nongnu.org; Wed, 15 Dec 2021 21:00:16 -0500 Received: from [2607:f8b0:4864:20::d49] (port=38558 helo=mail-io1-xd49.google.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3UJy6YQcKCocvzxwzotrzzrwp.nzx1px5-op6pwyzyry5.z2r@flex--komlodi.bounces.google.com>) id 1mxg45-0007Wh-Ts for qemu-devel@nongnu.org; Wed, 15 Dec 2021 21:00:15 -0500 Received: by mail-io1-xd49.google.com with SMTP id l124-20020a6b3e82000000b005ed165a1506so22193215ioa.5 for ; Wed, 15 Dec 2021 18:00:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=ZF0n7aVexYT+BTUKeAvJyOqsxB7EfrBsefo6NLji1Bo=; b=dHv+faqbOJsYE+RUZEX99tuzzSz2NBMNeW7NvNraPgq7ITRKxOsb7PLiOaXLy9xkMe sT0vz0PbDX5vowvmnCwf+BQqqv0fHl4rUGa3PDboDlgknqCvgsXmh1Fr+KEQSy7eIy/y IDvkFVmQgF2LM6krUs9M+EyrgF6F+ODNhrYGupjOYLHWItocI6MUNPjUIZYh/nvqeoTZ 2ibA2hBRhvCE+pHPQ9PoQ0GVZBlcnTsHmpmshChZEn9ujRWBIyfzwrh9E1m9EqvXFtu2 sfgEsmVet4gQyuvREDLmNcQxOYaiHb/PU5uyvf+rvmwHa1LxPJPJaBBWNVEPNTTuQOD5 AiyA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=ZF0n7aVexYT+BTUKeAvJyOqsxB7EfrBsefo6NLji1Bo=; b=sDUjjBY35+S3QNTmqONGqWajZl7YOECSaxATQDLZZuHKlGI0WglcBCBP/QkAwR4Qv5 PaOpVwnWHl3+i1p63U2sRnZPbod1MFfKUdnN5rh69KvtKKu2lB10el0+W+kzG/VkDvym Q/Jrkk3PBICuHCSCgyz2H8NwfpPaZ4bR6eNuj448C00TB4q8DLOPlNhj54zV0KXkMLcN SzUFNW2cxzAWmgaXsfbR9+91+iiruTyDxroOQpVn0qiPauX52JIsY9suH/IiviYsaTtB DoHoYEsIdLwgYQw7AAo2DKis8FUZ8KUs5dZdW8Z1NEBLwTy9VGA2LTE6WM9YRtdyiFdn zRVg== X-Gm-Message-State: AOAM531xVJ8BfjZuSTl/M0G4YGVxkCFM2vtSlobzEg3a8LWA7cMaybyN XOqDuYilyrDdz3q3hfTZU70/6xrsi6eCOebCwg5w9D/G5SXGf5UBQIDsezfNF781sLXnvl0EjSK +MCZJtfmN6sDMwLdKs8UCg4y4LS5jrlsB7Ztd3Spx4imWcLbLt7+FMLrehaQ6h5g= X-Google-Smtp-Source: ABdhPJzK9wrxr8YKExMGuleXZlcSoFToh4sDhgkCfkq0QjTRMIttnvqY+rrij8qmdPfsNVimMLcGcGQ19UY7 X-Received: from komlodi.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:35ee]) (user=komlodi job=sendgmr) by 2002:a63:510a:: with SMTP id f10mr10158838pgb.17.1639619664706; Wed, 15 Dec 2021 17:54:24 -0800 (PST) Date: Thu, 16 Dec 2021 01:54:15 +0000 In-Reply-To: <20211216015417.1234812-1-komlodi@google.com> Message-Id: <20211216015417.1234812-5-komlodi@google.com> Mime-Version: 1.0 References: <20211216015417.1234812-1-komlodi@google.com> X-Mailer: git-send-email 2.34.1.173.g76aa8bc2d0-goog Subject: [RFC PATCH 4/6] hw/arm/npcm7xx: gpio: Add GPIO transmitter From: Joe Komlodi To: qemu-devel@nongnu.org Cc: peter.maydell@linaro.org, venture@google.com, hskinnemoen@google.com, kfting@nuvoton.com X-Host-Lookup-Failed: Reverse DNS lookup failed for 2607:f8b0:4864:20::d49 (failed) Received-SPF: pass client-ip=2607:f8b0:4864:20::d49; envelope-from=3UJy6YQcKCocvzxwzotrzzrwp.nzx1px5-op6pwyzyry5.z2r@flex--komlodi.bounces.google.com; helo=mail-io1-xd49.google.com X-Spam_score_int: -87 X-Spam_score: -8.8 X-Spam_bar: -------- X-Spam_report: (-8.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This adds the GPIO transmitter to the NPCM7xx GPIO controller and transmits packets any time the pin state changes. Signed-off-by: Joe Komlodi --- 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; From patchwork Thu Dec 16 01:54:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joe Komlodi X-Patchwork-Id: 12679819 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 70DECC433F5 for ; Thu, 16 Dec 2021 02:04:48 +0000 (UTC) Received: from localhost ([::1]:38130 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mxg8V-000374-I2 for qemu-devel@archiver.kernel.org; Wed, 15 Dec 2021 21:04:47 -0500 Received: from eggs.gnu.org ([209.51.188.92]:50692) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3Upy6YQcKCokx1zy1qvt11tyr.p1z3rz7-qr8ry010t07.14t@flex--komlodi.bounces.google.com>) id 1mxg4v-0005NX-M0 for qemu-devel@nongnu.org; Wed, 15 Dec 2021 21:01:06 -0500 Received: from [2607:f8b0:4864:20::64a] (port=53160 helo=mail-pl1-x64a.google.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3Upy6YQcKCokx1zy1qvt11tyr.p1z3rz7-qr8ry010t07.14t@flex--komlodi.bounces.google.com>) id 1mxg4s-0007bd-Gy for qemu-devel@nongnu.org; Wed, 15 Dec 2021 21:01:04 -0500 Received: by mail-pl1-x64a.google.com with SMTP id m15-20020a170902bb8f00b0014382b67873so7261762pls.19 for ; Wed, 15 Dec 2021 18:01:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=37v2VvpScxCBaS0yW36wU3F/iIJvmW0p9+Vo6UzvkpM=; b=jvHxr9MSxqEC89mZYCXp4kDoB1cM1hHHK38nzV3szzRqUHBiBa5IprPD7WEwEonhFF nB4SfkY50LeYiuGMi33pZYKuRyFq6pN0rMko634gSEBNzF439qP2EqNdBDZAgUW4xfpU A6jYA8sykWkj7OY75G5VLEpGqrpOYozVXUtAKdyV3RJN43dsBFLrMdexEzpeQCdeUVTr 33v0EtSRn95S4QY7XABfS28yHLd4Gp4rm/8Qg2FWqxesgDuChorGoFmjjd6T/hWgrm/f 2EUkQ/WaamtxuB2kicis0KVjsDueVFEmFXvjjumrWsyZabS2eclh96LgT48qgi0RtPRd z63g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=37v2VvpScxCBaS0yW36wU3F/iIJvmW0p9+Vo6UzvkpM=; b=iyxGuboufIrOowd0zkYPAp4op8afa42acKh2J/DNOnPd7Dam8gN/Es4UGXv0Txie/H GPYzOG49qJZVYs+mOEhl9BgNxxYlg4fQhfCykymYbJ7g9wmqvR6HnDfao+RvV0qoy3DF taQeuT4BFXOAxuzbpcVE/1DD1M0CO6WCvYWx8Nn1rZr7dz7fOY02S7TM4His+SQ47ZZ+ VoiqsSSZ/n5J25x08OX/BICoeSkHMqVFPYVz1GaTdmhnaT/SkP//rFFPjcgYODEBYbW3 ydL47FaiFOXIxjsBwFP08kt1D/j8nM/fv2lohKcKo+h0Mvtgxf/XwuF/BlPYcGF9G2CM K01w== X-Gm-Message-State: AOAM531LXoDNQsQKdvXk73O8WGzZlzpa3EqhIjEby+69kEE4mVPAYTeC pRfbrEx4hnb7IXYMOBjDUK+lRRIlQv/6BaIiLkHQhFewGfmgppYjmNrvSk1R3QfRceX68w95HPc wzNBzMTlYicSgjiwwXwxLGosjRST1ilgmpZgri7ni1/KGCMe0bRsSAT8YTH57PRU= X-Google-Smtp-Source: ABdhPJznhZrrt3HH0xbjBe/6rR50dzZa2K4WdZBFtzEufuHLtAkpvjr6AkhUaHVD4RqCTfjcl15J4BJxxXrB X-Received: from komlodi.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:35ee]) (user=komlodi job=sendgmr) by 2002:a05:6a00:1945:b0:44c:a955:35ea with SMTP id s5-20020a056a00194500b0044ca95535eamr11358119pfk.85.1639619666320; Wed, 15 Dec 2021 17:54:26 -0800 (PST) Date: Thu, 16 Dec 2021 01:54:16 +0000 In-Reply-To: <20211216015417.1234812-1-komlodi@google.com> Message-Id: <20211216015417.1234812-6-komlodi@google.com> Mime-Version: 1.0 References: <20211216015417.1234812-1-komlodi@google.com> X-Mailer: git-send-email 2.34.1.173.g76aa8bc2d0-goog Subject: [RFC PATCH 5/6] hw/gpio/npcm7xx: init GPIO transmitter allowlist From: Joe Komlodi To: qemu-devel@nongnu.org Cc: peter.maydell@linaro.org, venture@google.com, hskinnemoen@google.com, kfting@nuvoton.com X-Host-Lookup-Failed: Reverse DNS lookup failed for 2607:f8b0:4864:20::64a (failed) Received-SPF: pass client-ip=2607:f8b0:4864:20::64a; envelope-from=3Upy6YQcKCokx1zy1qvt11tyr.p1z3rz7-qr8ry010t07.14t@flex--komlodi.bounces.google.com; helo=mail-pl1-x64a.google.com X-Spam_score_int: -87 X-Spam_score: -8.8 X-Spam_bar: -------- X-Spam_report: (-8.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 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 --- 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); From patchwork Thu Dec 16 01:54:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joe Komlodi X-Patchwork-Id: 12679809 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A2460C433FE for ; Thu, 16 Dec 2021 02:01:35 +0000 (UTC) Received: from localhost ([::1]:56936 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mxg5N-0005CT-Sc for qemu-devel@archiver.kernel.org; Wed, 15 Dec 2021 21:01:34 -0500 Received: from eggs.gnu.org ([209.51.188.92]:50276) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3VJy6YQcKCosz3103sxv33v0t.r315t19-stAt0232v29.36v@flex--komlodi.bounces.google.com>) id 1mxg3b-0003Iw-Gd for qemu-devel@nongnu.org; Wed, 15 Dec 2021 20:59:45 -0500 Received: from [2607:f8b0:4864:20::94a] (port=37481 helo=mail-ua1-x94a.google.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3VJy6YQcKCosz3103sxv33v0t.r315t19-stAt0232v29.36v@flex--komlodi.bounces.google.com>) id 1mxg3Z-0007S2-Mt for qemu-devel@nongnu.org; Wed, 15 Dec 2021 20:59:43 -0500 Received: by mail-ua1-x94a.google.com with SMTP id h6-20020a9f3006000000b002e6e81fda51so15015280uab.4 for ; Wed, 15 Dec 2021 17:59:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=8HmnuyfVD1e8skDf3kwtgBZA9JjXZYqlKEdQrXjs434=; b=Q9WR+kLzH/DI29s1faGyrK0mLaxfY067/tClQY55KiCGSsdphf1jy91WUupZqWP7AK BVaV2b/O4e91iwvF+g3ycPa8aw9i4oE5GUuVnDV/Ap6yhPEo9Byk0QezDC2qrcgTVUxI 8cFIGZPvM2t/jTEKFmgd2e49unoD8m/3aDBVEAcB9NAwVfpEzePohPMsrUOx9oR2xTnQ Sh8gcJTYvTymsNl8ihRwxsoWRCq49YSZH3HCa4S8gVl+k9G+2i/tIkg7N4wO+/0v+mxY FpVOX3V02Jt25FmArHIq/IT0spnkQmwfmovQUPd762tnftQDliQKeN7LIjSY/V5Up1IC mxWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=8HmnuyfVD1e8skDf3kwtgBZA9JjXZYqlKEdQrXjs434=; b=y0xzr/jpPgETf66YoskE0Z+AtJTXiOqC1pVFi8SCRVRc/nZWMmcaam4LHNrGlk3nwl pHjbpy1JV+vl+5OwAaZpcp3F09hAku6j1RYfCchoG5zdNXgAP2mqnfODebEg65GLEPSg svmfgSKRhdcMmnpnGdv/PSRNubxsRMZpfJNBFD2D4agL27OLMY89WQJ7DLM/3FB08DzZ HJfpP+s7Zt6ukCZUAaRla/AExqPgw76Om8WDamT/tKgrbgrEoKk4NOsyl6WPKpnbqH84 wdVFsRQNTJ8gOfL03pNCDvboGq6ahSyUmB4+ZJwPjrh7K2kbg+wLYZEX9lGaqnYWC30P jr1A== X-Gm-Message-State: AOAM531ame4cZFsDfLiC4XclMauzPHGH395WrbX3+yKlf2ym+Z1yKf6+ aQezhaTGMtw/onNZo7VgcNxhZJrBwqmM3jKHXN3PfVMVEIJElBiDTTbP4+8Xx0aGeTtPnrq+Ac3 Jzi52aJtoD0B8YG7oRBDVvkFMde9iYNLNBNOdhaOf/nikLgp3gJnuAj9+nspKVi0= X-Google-Smtp-Source: ABdhPJwsDE1I0kaeU7Rage8Beh2K0W0uSFfSDt/trYdhh4bKsu+frQLim6oGkNeWkOGHDNvo4Uw850jVobO5 X-Received: from komlodi.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:35ee]) (user=komlodi job=sendgmr) by 2002:a17:903:1246:b0:148:a658:8d32 with SMTP id u6-20020a170903124600b00148a6588d32mr6333901plh.117.1639619668013; Wed, 15 Dec 2021 17:54:28 -0800 (PST) Date: Thu, 16 Dec 2021 01:54:17 +0000 In-Reply-To: <20211216015417.1234812-1-komlodi@google.com> Message-Id: <20211216015417.1234812-7-komlodi@google.com> Mime-Version: 1.0 References: <20211216015417.1234812-1-komlodi@google.com> X-Mailer: git-send-email 2.34.1.173.g76aa8bc2d0-goog Subject: [RFC PATCH 6/6] qtests/gpio_transmitter: Add test From: Joe Komlodi To: qemu-devel@nongnu.org Cc: peter.maydell@linaro.org, venture@google.com, hskinnemoen@google.com, kfting@nuvoton.com X-Host-Lookup-Failed: Reverse DNS lookup failed for 2607:f8b0:4864:20::94a (failed) Received-SPF: pass client-ip=2607:f8b0:4864:20::94a; envelope-from=3VJy6YQcKCosz3103sxv33v0t.r315t19-stAt0232v29.36v@flex--komlodi.bounces.google.com; helo=mail-ua1-x94a.google.com X-Spam_score_int: -87 X-Spam_score: -8.8 X-Spam_bar: -------- X-Spam_report: (-8.8 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" 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 --- 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',