From nobody Fri Apr 4 06:07:07 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=kernel.org ARC-Seal: i=1; a=rsa-sha256; t=1742388825; cv=none; d=zohomail.com; s=zohoarc; b=PqqrDSTH173pNYyeqR9AvbzgxmnjAX+x/fc+DrL9EImc4Xdcdm13dTC7TJ6fAf5KoDhDKhxva1gevDjV5sGtISoNA1CCQP9hhSaREJSAtQ7YOicEDQgMOgLWxJX0ecWsO6qWsjM6KZXZ2DgkqiVS2tu5FZ1lCpSnt3BF1wpk1XM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1742388825; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=IZ+48d2orLFzO9JlR3aBhvRp8i2Wff1k+rqPsGV2ubQ=; b=SER4XQRNYZRfV8jtP5d9Ci/cXrtvdouIiS+BFiyUFD/Cuot02zOPO/SwURj3ZUAJRGYVxkheM4qpoClG/REGqqy+DGhQkN0HROVzgKxnScLCsftEGWjRpsUetiSX+xyZ9pk4hhuXGxodVwp3hsj++hSE/+Kg00Tpu2Xt2TS5VpM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1742388825666261.3225775177425; Wed, 19 Mar 2025 05:53:45 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tusrf-0000Pw-RE; Wed, 19 Mar 2025 08:49:43 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tuoJT-0006G2-Sb; Wed, 19 Mar 2025 03:58:08 -0400 Received: from nyc.source.kernel.org ([2604:1380:45d1:ec00::3]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tuoJQ-0003df-Bw; Wed, 19 Mar 2025 03:58:07 -0400 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id C2486A48FE1; Wed, 19 Mar 2025 07:52:25 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id CBBA9C4CEF6; Wed, 19 Mar 2025 07:57:54 +0000 (UTC) Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id BC5E4C35FFA; Wed, 19 Mar 2025 07:57:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1742371074; bh=/FXbuVk2kxneP1NDtfBB0y/MWnfDsP3dDD2KxydWs9E=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=ASjpQQU8NZQ54aoHigkVzhqQwLHZzgh5/W9Yfa+9+Pd+jpmKqUW0D7TD6BlQY+7BN u2wPdVNOmB3KeYdiqS//dY9qDN7rL/ZyX3WWL0XZSI1lM+yJmP2hVlogV2NZL2otKG uM9WtyyeHRcO6hVsT7YMjWHtRrBb/rseT4075OKfEub9LtMKi88sGIstZmG621PZDr M6+aHuEoFYZR5JEywwiFaejmVIat87fBasovE7sDFKDDJUFQGmd3KHQtQBKKZOU8Wo pwn+kWc5Gnzrh39f4C9CkiCxejfWRc15IRlM5jPKXBIZC2C/AT5IUU6qnAxp8oBqWA ePLfzV7W28zgg== From: Nikita Shubin via B4 Relay Date: Wed, 19 Mar 2025 10:57:55 +0300 Subject: [PATCH PoC 5/7] hw/gpio/aspeed: Add gpiodev support MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250319-gpiodev-v1-5-76da4e5800a1@yadro.com> References: <20250319-gpiodev-v1-0-76da4e5800a1@yadro.com> In-Reply-To: <20250319-gpiodev-v1-0-76da4e5800a1@yadro.com> To: qemu-devel@nongnu.org Cc: Linus Walleij , Bartosz Golaszewski , "Enrico Weigelt, metux IT consult" , Viresh Kumar , Eric Blake , Markus Armbruster , Michael Roth , Paolo Bonzini , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Eduardo Habkost , =?utf-8?q?C=C3=A9dric_Le_Goater?= , Peter Maydell , Steven Lee , Troy Lee , Jamin Lin , Andrew Jeffery , Joel Stanley , qemu-arm@nongnu.org, Nikita Shubin , Nikita Shubin X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1742371072; l=9057; i=n.shubin@yadro.com; s=20230718; h=from:subject:message-id; bh=LCxwVdVyHaytyw7TlHjgwh2ubyN+clkLCBd91HD+W6s=; b=QY/eH0K/w+TXRSupwDbLRlk8MNe53AnT+V9sWX4EEshbkn/JpR8nRJRRsJ7onmtw1mKnV0NPj /slWcVxjxBNDDCSgSIZCjkWz8kTwTdGE+mMjMqeXGuDuqvQhaTvi5lp X-Developer-Key: i=n.shubin@yadro.com; a=ed25519; pk=vqf5YIUJ7BJv3EJFaNNxWZgGuMgDH6rwufTLflwU9ac= X-Endpoint-Received: by B4 Relay for n.shubin@yadro.com/20230718 with auth_id=161 X-Original-From: Nikita Shubin Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2604:1380:45d1:ec00::3; envelope-from=devnull+n.shubin.yadro.com@kernel.org; helo=nyc.source.kernel.org X-Spam_score_int: -23 X-Spam_score: -2.4 X-Spam_bar: -- X-Spam_report: (-2.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.332, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Wed, 19 Mar 2025 08:49:30 -0400 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: , Reply-To: n.shubin@yadro.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @kernel.org) X-ZM-MESSAGEID: 1742388827248019100 From: Nikita Shubin Add gpiodev support for: - getting line info - getting/setting lines - monitoring line events - monitoting config events Binding is done via id, i.e.: ... -gpiodev chardev,id=3Daspeed-gpio0 Signed-off-by: Nikita Shubin --- hw/gpio/aspeed_gpio.c | 127 ++++++++++++++++++++++++++++++++++++++= ++++ include/hw/gpio/aspeed_gpio.h | 3 + 2 files changed, 130 insertions(+) diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c index a5b3f454e800dc9440600562b6295b069cb536fb..0c8b27c9a0cbef313254405dde3= f1e1910f9bf57 100644 --- a/hw/gpio/aspeed_gpio.c +++ b/hw/gpio/aspeed_gpio.c @@ -291,6 +291,8 @@ static int aspeed_evaluate_irq(GPIOSets *regs, int gpio= _prev_high, int gpio) return 0; } =20 +static void aspeed_gpio_line_event(AspeedGPIOState *s, uint32_t set_idx, u= int32_t pin_idx); + #define nested_struct_index(ta, pa, m, tb, pb) \ (pb - ((tb *)(((char *)pa) + offsetof(ta, m)))) =20 @@ -337,6 +339,9 @@ static void aspeed_gpio_update(AspeedGPIOState *s, GPIO= Sets *regs, /* ...trigger the line-state IRQ */ ptrdiff_t set =3D aspeed_gpio_set_idx(s, regs); qemu_set_irq(s->gpios[set][gpio], !!(new & mask)); + + /* ...notify gpio backend if any */ + aspeed_gpio_line_event(s, set, gpio); } else { /* ...otherwise if we meet the line's current IRQ policy..= . */ if (aspeed_evaluate_irq(regs, old & mask, gpio)) { @@ -360,6 +365,18 @@ static bool aspeed_gpio_get_pin_level(AspeedGPIOState = *s, uint32_t set_idx, return !!(reg_val & pin_mask); } =20 +static void aspeed_gpio_line_event(AspeedGPIOState *s, uint32_t set_idx, u= int32_t pin_idx) +{ + uint32_t offset =3D set_idx * ASPEED_GPIOS_PER_SET + pin_idx; + QEMUGpioLineEvent event =3D GPIO_EVENT_FALLING_EDGE; + + if (aspeed_gpio_get_pin_level(s, set_idx, pin_idx)) { + event =3D GPIO_EVENT_RISING_EDGE; + } + + qemu_gpio_fe_line_event(&s->gpiodev, offset, event); +} + static void aspeed_gpio_set_pin_level(AspeedGPIOState *s, uint32_t set_idx, uint32_t pin, bool level) { @@ -659,6 +676,13 @@ static uint64_t aspeed_gpio_read(void *opaque, hwaddr = offset, uint32_t size) return value; } =20 +static void aspeed_gpio_config_event(AspeedGPIOState *s, uint32_t set_idx,= uint32_t pin_idx) +{ + uint32_t offset =3D set_idx * ASPEED_GPIOS_PER_SET + pin_idx; + + qemu_gpio_fe_config_event(&s->gpiodev, offset, GPIO_LINE_CHANGED_CONFI= G); +} + static void aspeed_gpio_write_index_mode(void *opaque, hwaddr offset, uint64_t data, uint32_t si= ze) { @@ -674,6 +698,7 @@ static void aspeed_gpio_write_index_mode(void *opaque, = hwaddr offset, uint32_t group_idx =3D pin_idx / GPIOS_PER_GROUP; uint32_t reg_value =3D 0; uint32_t pending =3D 0; + uint32_t old_direction; =20 set =3D &s->sets[set_idx]; props =3D &agc->props[set_idx]; @@ -711,8 +736,12 @@ static void aspeed_gpio_write_index_mode(void *opaque,= hwaddr offset, * data =3D ( data | ~input) & output; */ reg_value =3D (reg_value | ~props->input) & props->output; + old_direction =3D set->direction; set->direction =3D update_value_control_source(set, set->direction, reg_value); + if (set->direction !=3D old_direction) { + aspeed_gpio_config_event(s, set_idx, pin_idx); + } break; case gpio_reg_idx_interrupt: reg_value =3D set->int_enable; @@ -813,6 +842,7 @@ static void aspeed_gpio_write(void *opaque, hwaddr offs= et, uint64_t data, const AspeedGPIOReg *reg; GPIOSets *set; uint32_t cleared; + uint32_t old_direction; =20 trace_aspeed_gpio_write(offset, data); =20 @@ -867,7 +897,17 @@ static void aspeed_gpio_write(void *opaque, hwaddr off= set, uint64_t data, * data =3D ( data | ~input) & output; */ data =3D (data | ~props->input) & props->output; + old_direction =3D set->direction; set->direction =3D update_value_control_source(set, set->direction= , data); + qemu_log("gpio_reg_direction: 0x%x 0x%x\n", set->direction, old_di= rection); + if (set->direction !=3D old_direction) { + unsigned long changed =3D set->direction ^ old_direction; + int idx =3D find_first_bit(&changed, ASPEED_GPIOS_PER_SET); + while (idx < ASPEED_GPIOS_PER_SET) { + aspeed_gpio_config_event(s, reg->set_idx, idx); + idx =3D find_next_bit(&changed, ASPEED_GPIOS_PER_SET, idx = + 1); + } + } break; case gpio_reg_int_enable: set->int_enable =3D update_value_control_source(set, set->int_enab= le, @@ -1392,11 +1432,85 @@ static void aspeed_gpio_reset(DeviceState *dev) memset(s->sets, 0, sizeof(s->sets)); } =20 +static void aspeed_gpio_line_info(void *opaque, gpio_line_info *info) +{ + AspeedGPIOState *s =3D ASPEED_GPIO(opaque); + AspeedGPIOClass *agc =3D ASPEED_GPIO_GET_CLASS(s); + uint32_t group_idx =3D 0, pin_idx =3D 0, idx =3D 0; + uint32_t offset =3D info->offset; + const GPIOSetProperties *props; + bool direction; + const char *group; + int i, set_idx, grp_idx, pin; + + for (i =3D 0; i < ASPEED_GPIO_MAX_NR_SETS; i++) { + props =3D &agc->props[i]; + uint32_t skip =3D ~(props->input | props->output); + for (int j =3D 0; j < ASPEED_GPIOS_PER_SET; j++) { + if (skip >> j & 1) { + continue; + } + + group_idx =3D j / GPIOS_PER_GROUP; + pin_idx =3D j % GPIOS_PER_GROUP; + if (idx =3D=3D offset) { + goto found; + } + + idx++; + } + } + + return; + +found: + group =3D &props->group_label[group_idx][0]; + set_idx =3D get_set_idx(s, group, &grp_idx); + snprintf(info->name, sizeof(info->name), "gpio%s%d", group, pin_idx); + pin =3D pin_idx + group_idx * GPIOS_PER_GROUP; + direction =3D !!(s->sets[set_idx].direction & BIT_ULL(pin)); + + if (direction) { + info->flags |=3D GPIO_LINE_FLAG_OUTPUT; + } else { + info->flags |=3D GPIO_LINE_FLAG_INPUT; + } + + qemu_log("%u: %s: set_idx=3D%d, grp_idx=3D%d, group_idx=3D%u, pin_idx= =3D%u\n", offset, info->name, set_idx, grp_idx, group_idx, pin_idx); +} + +static int aspeed_gpio_get_line(void *opaque, uint32_t offset) +{ + AspeedGPIOState *s =3D ASPEED_GPIO(opaque); + int set_idx, pin_idx; + + set_idx =3D offset / ASPEED_GPIOS_PER_SET; + pin_idx =3D offset % ASPEED_GPIOS_PER_SET; + + return aspeed_gpio_get_pin_level(s, set_idx, pin_idx); +} + +static int aspeed_gpio_set_line(void *opaque, uint32_t offset, uint8_t val= ue) +{ + AspeedGPIOState *s =3D ASPEED_GPIO(opaque); + int set_idx, pin_idx; + + set_idx =3D offset / ASPEED_GPIOS_PER_SET; + pin_idx =3D offset % ASPEED_GPIOS_PER_SET; + + aspeed_gpio_set_pin_level(s, set_idx, pin_idx, value); + + return 0; +} + static void aspeed_gpio_realize(DeviceState *dev, Error **errp) { AspeedGPIOState *s =3D ASPEED_GPIO(dev); SysBusDevice *sbd =3D SYS_BUS_DEVICE(dev); AspeedGPIOClass *agc =3D ASPEED_GPIO_GET_CLASS(s); + DeviceState *d =3D DEVICE(s); + Object *backend; + Gpiodev *gpio; =20 /* Interrupt parent line */ sysbus_init_irq(sbd, &s->irq); @@ -1417,6 +1531,19 @@ static void aspeed_gpio_realize(DeviceState *dev, Er= ror **errp) TYPE_ASPEED_GPIO, agc->mem_size); =20 sysbus_init_mmio(sbd, &s->iomem); + + /* NOTE: or we can create one per set */ + if (d->id) { + backend =3D object_resolve_path_type(d->id, TYPE_GPIODEV, NULL); + if (backend) { + gpio =3D GPIODEV(backend); + qemu_gpio_fe_init(&s->gpiodev, gpio, agc->nr_gpio_pins, d->id, + "ASPEED GPIO", NULL); + qemu_gpio_fe_set_handlers(&s->gpiodev, aspeed_gpio_line_info, + aspeed_gpio_get_line, + aspeed_gpio_set_line, s); + } + } } =20 static void aspeed_gpio_init(Object *obj) diff --git a/include/hw/gpio/aspeed_gpio.h b/include/hw/gpio/aspeed_gpio.h index e1e6c543339ef9ddff99124d7a267e9c8544c556..f0a1207b24421f4129182fbcbb8= 8650604313a6c 100644 --- a/include/hw/gpio/aspeed_gpio.h +++ b/include/hw/gpio/aspeed_gpio.h @@ -12,6 +12,8 @@ =20 #include "hw/sysbus.h" #include "qom/object.h" +#include "gpiodev/gpio.h" +#include "gpiodev/gpio-fe.h" =20 #define TYPE_ASPEED_GPIO "aspeed.gpio" OBJECT_DECLARE_TYPE(AspeedGPIOState, AspeedGPIOClass, ASPEED_GPIO) @@ -85,6 +87,7 @@ struct AspeedGPIOState { SysBusDevice parent; =20 /*< public >*/ + GpioBackend gpiodev; MemoryRegion iomem; int pending; qemu_irq irq; --=20 2.45.2