From patchwork Tue Mar 5 13:52:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582476 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 2B26EC54798 for ; Tue, 5 Mar 2024 13:55:46 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVEy-000299-R9; Tue, 05 Mar 2024 08:53:56 -0500 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 1rhVDt-0000vb-C2 for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:49 -0500 Received: from mail-wr1-x435.google.com ([2a00:1450:4864:20::435]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDl-0005x6-KM for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:48 -0500 Received: by mail-wr1-x435.google.com with SMTP id ffacd0b85a97d-33e4d36f288so323453f8f.1 for ; Tue, 05 Mar 2024 05:52:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646759; x=1710251559; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=pY5HNRAMy12I3t0xs8LV6YLNkKiX6S8/PFI0OQH7qIA=; b=vjFhzAYnhCOus2wrfJIJ+1obSc3BlC9k4KiX8qJ+bBldKSbKR9f4VJ9bVcTkfTz1XL NIbTPBdsR2FICv/ltjdkY/reaxJoChV+neZo8jxGB4+vNCnlqWc663dELGl6uA1uPQIW Chl+rjW5HqiUeC81+UifMKEKd7wSoJWWIENQIX9o6JqoTmOVYdor6Z1cNRAwnxDEkqtU DjVj9W73A8C1qF3xJT2TyIVHrCD8GPp0hT/QbrSI97psZCNk6qAX0N6L+ui6ehGTcLM2 jtXjQmR5cjjr35S55Hzwry6UKHG3QP3vDipMyU8e1Vp3nHFujvAPyPm67AqM2g3e7S2X UU9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646759; x=1710251559; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=pY5HNRAMy12I3t0xs8LV6YLNkKiX6S8/PFI0OQH7qIA=; b=LPXxPQ3CMU69FyxCNmQX+SCS4/gV7ZT1NT3Du7YD+TGihDNodFIsjKerCWE8XUa9Km 4NPooU75kqwtLP5XuA/1oKYXFX/qHb7Fonb244Sp71w9c3RRsWp3zJOkKeXsyzFHmmcm z92fWE9mY2FcRKGDgyYgCcFV1aJ5DK9OtnBByE3Bt1aa41ndXcQf1s9UQYUMLnnX2s3Q BZH87ISAY6YOu276cgFKZl8I6d+jGx3pcWuL7WEp+SO8ACPgdWBd0bGlMlpt/5gUYi9D BCjXyiZs9RMqJ3QShKgdu587e7agEjvIE5uJZUBD5+0euM2RTgQYb4vj1g7Q71pGZAVW /zwg== X-Gm-Message-State: AOJu0Ywfn5j4fsTaikQ2UbrJCwlPdvDZ/hYRFhb3Bq4x3VsWU+UaQc2/ sjtARgAk+jLZ7j1UvBP4bnRm87igZ28MWtdaY1mHSFWqCYCMbKL5Wph/rK3TzG59oDzfEibQW1n 1 X-Google-Smtp-Source: AGHT+IGbgAnsV8ig7Z7xiCSBtx43KyhsEz60cwxB3xHYXa8WQII246xkUIjWD+vk6/WJVAQQtK/1rw== X-Received: by 2002:adf:ab47:0:b0:33e:1cd7:6434 with SMTP id r7-20020adfab47000000b0033e1cd76434mr2293326wrc.19.1709646759266; Tue, 05 Mar 2024 05:52:39 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.38 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:39 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 01/20] hw/i2c: Implement Broadcom Serial Controller (BSC) Date: Tue, 5 Mar 2024 13:52:18 +0000 Message-Id: <20240305135237.3111642-2-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::435; envelope-from=peter.maydell@linaro.org; helo=mail-wr1-x435.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Rayhan Faizel A few deficiencies in the current device model need to be noted. 1. FIFOs are not used. All sends and receives are done directly. 2. Repeated starts are not emulated. Repeated starts can be triggered in real hardware by sending a new read transfer request in the window time between transfer active set of write transfer request and done bit set of the same. Signed-off-by: Rayhan Faizel Reviewed-by: Peter Maydell Message-id: 20240224191038.2409945-2-rayhan.faizel@gmail.com Signed-off-by: Peter Maydell --- docs/system/arm/raspi.rst | 1 + include/hw/i2c/bcm2835_i2c.h | 80 ++++++++++ hw/i2c/bcm2835_i2c.c | 282 +++++++++++++++++++++++++++++++++++ hw/i2c/Kconfig | 4 + hw/i2c/meson.build | 1 + 5 files changed, 368 insertions(+) create mode 100644 include/hw/i2c/bcm2835_i2c.h create mode 100644 hw/i2c/bcm2835_i2c.c diff --git a/docs/system/arm/raspi.rst b/docs/system/arm/raspi.rst index bb417c34241..fbec1da6a1e 100644 --- a/docs/system/arm/raspi.rst +++ b/docs/system/arm/raspi.rst @@ -35,6 +35,7 @@ Implemented devices * MailBox controller (MBOX) * VideoCore firmware (property) * Peripheral SPI controller (SPI) + * Broadcom Serial Controller (I2C) Missing devices --------------- diff --git a/include/hw/i2c/bcm2835_i2c.h b/include/hw/i2c/bcm2835_i2c.h new file mode 100644 index 00000000000..0a56df4720b --- /dev/null +++ b/include/hw/i2c/bcm2835_i2c.h @@ -0,0 +1,80 @@ +/* + * Broadcom Serial Controller (BSC) + * + * Copyright (c) 2024 Rayhan Faizel + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hw/sysbus.h" +#include "hw/i2c/i2c.h" +#include "qom/object.h" + +#define TYPE_BCM2835_I2C "bcm2835-i2c" +OBJECT_DECLARE_SIMPLE_TYPE(BCM2835I2CState, BCM2835_I2C) + +#define BCM2835_I2C_C 0x0 /* Control */ +#define BCM2835_I2C_S 0x4 /* Status */ +#define BCM2835_I2C_DLEN 0x8 /* Data Length */ +#define BCM2835_I2C_A 0xc /* Slave Address */ +#define BCM2835_I2C_FIFO 0x10 /* FIFO */ +#define BCM2835_I2C_DIV 0x14 /* Clock Divider */ +#define BCM2835_I2C_DEL 0x18 /* Data Delay */ +#define BCM2835_I2C_CLKT 0x20 /* Clock Stretch Timeout */ + +#define BCM2835_I2C_C_I2CEN BIT(15) /* I2C enable */ +#define BCM2835_I2C_C_INTR BIT(10) /* Interrupt on RXR */ +#define BCM2835_I2C_C_INTT BIT(9) /* Interrupt on TXW */ +#define BCM2835_I2C_C_INTD BIT(8) /* Interrupt on DONE */ +#define BCM2835_I2C_C_ST BIT(7) /* Start transfer */ +#define BCM2835_I2C_C_CLEAR (BIT(5) | BIT(4)) /* Clear FIFO */ +#define BCM2835_I2C_C_READ BIT(0) /* I2C read mode */ + +#define BCM2835_I2C_S_CLKT BIT(9) /* Clock stretch timeout */ +#define BCM2835_I2C_S_ERR BIT(8) /* Slave error */ +#define BCM2835_I2C_S_RXF BIT(7) /* RX FIFO full */ +#define BCM2835_I2C_S_TXE BIT(6) /* TX FIFO empty */ +#define BCM2835_I2C_S_RXD BIT(5) /* RX bytes available */ +#define BCM2835_I2C_S_TXD BIT(4) /* TX space available */ +#define BCM2835_I2C_S_RXR BIT(3) /* RX FIFO needs reading */ +#define BCM2835_I2C_S_TXW BIT(2) /* TX FIFO needs writing */ +#define BCM2835_I2C_S_DONE BIT(1) /* I2C Transfer complete */ +#define BCM2835_I2C_S_TA BIT(0) /* I2C Transfer active */ + +struct BCM2835I2CState { + /* */ + SysBusDevice parent_obj; + + /* */ + MemoryRegion iomem; + I2CBus *bus; + qemu_irq irq; + + uint32_t c; + uint32_t s; + uint32_t dlen; + uint32_t a; + uint32_t div; + uint32_t del; + uint32_t clkt; + + uint32_t last_dlen; +}; diff --git a/hw/i2c/bcm2835_i2c.c b/hw/i2c/bcm2835_i2c.c new file mode 100644 index 00000000000..20ec46eeabc --- /dev/null +++ b/hw/i2c/bcm2835_i2c.c @@ -0,0 +1,282 @@ +/* + * Broadcom Serial Controller (BSC) + * + * Copyright (c) 2024 Rayhan Faizel + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "hw/i2c/bcm2835_i2c.h" +#include "hw/irq.h" +#include "migration/vmstate.h" + +static void bcm2835_i2c_update_interrupt(BCM2835I2CState *s) +{ + int do_interrupt = 0; + /* Interrupt on RXR (Needs reading) */ + if (s->c & BCM2835_I2C_C_INTR && s->s & BCM2835_I2C_S_RXR) { + do_interrupt = 1; + } + + /* Interrupt on TXW (Needs writing) */ + if (s->c & BCM2835_I2C_C_INTT && s->s & BCM2835_I2C_S_TXW) { + do_interrupt = 1; + } + + /* Interrupt on DONE (Transfer complete) */ + if (s->c & BCM2835_I2C_C_INTD && s->s & BCM2835_I2C_S_DONE) { + do_interrupt = 1; + } + qemu_set_irq(s->irq, do_interrupt); +} + +static void bcm2835_i2c_begin_transfer(BCM2835I2CState *s) +{ + int direction = s->c & BCM2835_I2C_C_READ; + if (i2c_start_transfer(s->bus, s->a, direction)) { + s->s |= BCM2835_I2C_S_ERR; + } + s->s |= BCM2835_I2C_S_TA; + + if (direction) { + s->s |= BCM2835_I2C_S_RXR | BCM2835_I2C_S_RXD; + } else { + s->s |= BCM2835_I2C_S_TXW; + } +} + +static void bcm2835_i2c_finish_transfer(BCM2835I2CState *s) +{ + /* + * STOP is sent when DLEN counts down to zero. + * + * https://github.com/torvalds/linux/blob/v6.7/drivers/i2c/busses/i2c-bcm2835.c#L223-L261 + * It is possible to initiate repeated starts on real hardware. + * However, this requires sending another ST request before the bytes in + * TX FIFO are shifted out. + * + * This is not emulated currently. + */ + i2c_end_transfer(s->bus); + s->s |= BCM2835_I2C_S_DONE; + + /* Ensure RXD is cleared, otherwise the driver registers an error */ + s->s &= ~(BCM2835_I2C_S_TA | BCM2835_I2C_S_RXR | + BCM2835_I2C_S_TXW | BCM2835_I2C_S_RXD); +} + +static uint64_t bcm2835_i2c_read(void *opaque, hwaddr addr, unsigned size) +{ + BCM2835I2CState *s = opaque; + uint32_t readval = 0; + + switch (addr) { + case BCM2835_I2C_C: + readval = s->c; + break; + case BCM2835_I2C_S: + readval = s->s; + break; + case BCM2835_I2C_DLEN: + readval = s->dlen; + break; + case BCM2835_I2C_A: + readval = s->a; + break; + case BCM2835_I2C_FIFO: + /* We receive I2C messages directly instead of using FIFOs */ + if (s->s & BCM2835_I2C_S_TA) { + readval = i2c_recv(s->bus); + s->dlen -= 1; + + if (s->dlen == 0) { + bcm2835_i2c_finish_transfer(s); + } + } + bcm2835_i2c_update_interrupt(s); + break; + case BCM2835_I2C_DIV: + readval = s->div; + break; + case BCM2835_I2C_DEL: + readval = s->del; + break; + case BCM2835_I2C_CLKT: + readval = s->clkt; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr); + } + + return readval; +} + +static void bcm2835_i2c_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + BCM2835I2CState *s = opaque; + uint32_t writeval = value; + + switch (addr) { + case BCM2835_I2C_C: + /* ST is a one-shot operation; it must read back as 0 */ + s->c = writeval & ~BCM2835_I2C_C_ST; + + /* Start transfer */ + if (writeval & (BCM2835_I2C_C_ST | BCM2835_I2C_C_I2CEN)) { + bcm2835_i2c_begin_transfer(s); + /* + * Handle special case where transfer starts with zero data length. + * Required for zero length i2c quick messages to work. + */ + if (s->dlen == 0) { + bcm2835_i2c_finish_transfer(s); + } + } + + bcm2835_i2c_update_interrupt(s); + break; + case BCM2835_I2C_S: + if (writeval & BCM2835_I2C_S_DONE && s->s & BCM2835_I2C_S_DONE) { + /* When DONE is cleared, DLEN should read last written value. */ + s->dlen = s->last_dlen; + } + + /* Clear DONE, CLKT and ERR by writing 1 */ + s->s &= ~(writeval & (BCM2835_I2C_S_DONE | + BCM2835_I2C_S_ERR | BCM2835_I2C_S_CLKT)); + break; + case BCM2835_I2C_DLEN: + s->dlen = writeval; + s->last_dlen = writeval; + break; + case BCM2835_I2C_A: + s->a = writeval; + break; + case BCM2835_I2C_FIFO: + /* We send I2C messages directly instead of using FIFOs */ + if (s->s & BCM2835_I2C_S_TA) { + if (s->s & BCM2835_I2C_S_TXD) { + if (!i2c_send(s->bus, writeval & 0xff)) { + s->dlen -= 1; + } else { + s->s |= BCM2835_I2C_S_ERR; + } + } + + if (s->dlen == 0) { + bcm2835_i2c_finish_transfer(s); + } + } + bcm2835_i2c_update_interrupt(s); + break; + case BCM2835_I2C_DIV: + s->div = writeval; + break; + case BCM2835_I2C_DEL: + s->del = writeval; + break; + case BCM2835_I2C_CLKT: + s->clkt = writeval; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr); + } +} + +static const MemoryRegionOps bcm2835_i2c_ops = { + .read = bcm2835_i2c_read, + .write = bcm2835_i2c_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + +static void bcm2835_i2c_realize(DeviceState *dev, Error **errp) +{ + BCM2835I2CState *s = BCM2835_I2C(dev); + s->bus = i2c_init_bus(dev, NULL); + + memory_region_init_io(&s->iomem, OBJECT(dev), &bcm2835_i2c_ops, s, + TYPE_BCM2835_I2C, 0x24); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); + sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq); +} + +static void bcm2835_i2c_reset(DeviceState *dev) +{ + BCM2835I2CState *s = BCM2835_I2C(dev); + + /* Reset values according to BCM2835 Peripheral Documentation */ + s->c = 0x0; + s->s = BCM2835_I2C_S_TXD | BCM2835_I2C_S_TXE; + s->dlen = 0x0; + s->a = 0x0; + s->div = 0x5dc; + s->del = 0x00300030; + s->clkt = 0x40; +} + +static const VMStateDescription vmstate_bcm2835_i2c = { + .name = TYPE_BCM2835_I2C, + .version_id = 1, + .minimum_version_id = 1, + .fields = (const VMStateField[]) { + VMSTATE_UINT32(c, BCM2835I2CState), + VMSTATE_UINT32(s, BCM2835I2CState), + VMSTATE_UINT32(dlen, BCM2835I2CState), + VMSTATE_UINT32(a, BCM2835I2CState), + VMSTATE_UINT32(div, BCM2835I2CState), + VMSTATE_UINT32(del, BCM2835I2CState), + VMSTATE_UINT32(clkt, BCM2835I2CState), + VMSTATE_UINT32(last_dlen, BCM2835I2CState), + VMSTATE_END_OF_LIST() + } +}; + +static void bcm2835_i2c_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = bcm2835_i2c_reset; + dc->realize = bcm2835_i2c_realize; + dc->vmsd = &vmstate_bcm2835_i2c; +} + +static const TypeInfo bcm2835_i2c_info = { + .name = TYPE_BCM2835_I2C, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(BCM2835I2CState), + .class_init = bcm2835_i2c_class_init, +}; + +static void bcm2835_i2c_register_types(void) +{ + type_register_static(&bcm2835_i2c_info); +} + +type_init(bcm2835_i2c_register_types) diff --git a/hw/i2c/Kconfig b/hw/i2c/Kconfig index 14886b35dac..596a7a3165a 100644 --- a/hw/i2c/Kconfig +++ b/hw/i2c/Kconfig @@ -45,3 +45,7 @@ config PCA954X config PMBUS bool select SMBUS + +config BCM2835_I2C + bool + select I2C diff --git a/hw/i2c/meson.build b/hw/i2c/meson.build index b58bc167dbc..c459adcb596 100644 --- a/hw/i2c/meson.build +++ b/hw/i2c/meson.build @@ -17,4 +17,5 @@ i2c_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_i2c.c')) i2c_ss.add(when: 'CONFIG_PPC4XX', if_true: files('ppc4xx_i2c.c')) i2c_ss.add(when: 'CONFIG_PCA954X', if_true: files('i2c_mux_pca954x.c')) i2c_ss.add(when: 'CONFIG_PMBUS', if_true: files('pmbus_device.c')) +i2c_ss.add(when: 'CONFIG_BCM2835_I2C', if_true: files('bcm2835_i2c.c')) system_ss.add_all(when: 'CONFIG_I2C', if_true: i2c_ss) From patchwork Tue Mar 5 13:52:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582474 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 C8993C54E41 for ; Tue, 5 Mar 2024 13:54:49 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVEo-0001Vq-Pi; Tue, 05 Mar 2024 08:53:48 -0500 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 1rhVE0-0000xQ-DW for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:53:09 -0500 Received: from mail-wm1-x331.google.com ([2a00:1450:4864:20::331]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDl-0005xA-Ku for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:56 -0500 Received: by mail-wm1-x331.google.com with SMTP id 5b1f17b1804b1-412e4619e5eso14927335e9.2 for ; Tue, 05 Mar 2024 05:52:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646760; x=1710251560; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=0JKYOkSiA03lg7OUJXJjM4ddPzSRWI5RZ/kNlzuzX60=; b=D1rcJLyeQ2PiUOb2D30FgExMbMZEtXlwhqSpalXn3ERQ5TXA3s+ncI3y0cNy8oaAXg kB/ShYrsZ5H79i2IOyphOipciU9uLAtQO7v0KDDapyLfpLKVk4wcAw8r5mrI0uE9bXkC Y6aFUkrfS9NY/Ege83WRjq/1L+m/Kt469GPiR6JddWA53oN4wfdKTLzzoWuaCT5MKW9Y srDwqFEasKzhlRls5FM7jwY9dcXCWtyvOttnfi0DYC3lPB9bDEDuonz8EbZAScb7N/4L BVBbCrOY9KeDql/UZw5srhW6RFdxwdmjGUqdV1VrmrcfP+6sxr13QPiWq9jSdCo/KqSb L2aQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646760; x=1710251560; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=0JKYOkSiA03lg7OUJXJjM4ddPzSRWI5RZ/kNlzuzX60=; b=qd0PisARcNy+KV1+QZ9TgZb08dCzW+JZw+3nVtpOLOw2Cr+sYbkCUUuEaSYNdQ6VPy JP1q47U3/Nc1+ONRNqzizLP0+v4EM+D0IbKyXP59ZhGGe8e6lTRHCsWK88HoMn8kh9Vn K2LveXHGHoxArToTvy5UCdfTnFc9xYx+1ulnYvXjXQtBbXyi5WbDGLLFVMZr0ldsh+1T z2uALbU6rsVa2Ru8/hFEH3qNe7TVWZd9dnA66TGxBFJhi3oCyAGDBzMrvJT9PKHjeClL DfRzWlkTdUfxTVYDbdsc/tN0LaL/7l62dRzfgPBZ2tQ5irCYNElmrUN68YKAMdgipZkl 7yQg== X-Gm-Message-State: AOJu0Yw56zWkxW4Jhuv7EUhQXe0sEnBvOqyWMqQcD+L6ZEeSJaTWEivg YODMxQe8rqv+AxpRAHF764nUtSYuSn3Q/fl+I1aNfllaCWJkIyeOxVnq3Zdu7TSkBiFNbF9RIEp C X-Google-Smtp-Source: AGHT+IESMTb40rfLN+eVEomIVwYgZ4YAgp6J+3yvU2V0IpDUkQd3CxwMbmy4mywL0soppmyaB6r69w== X-Received: by 2002:adf:db0f:0:b0:33e:c9b:396d with SMTP id s15-20020adfdb0f000000b0033e0c9b396dmr10725192wri.8.1709646759722; Tue, 05 Mar 2024 05:52:39 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.39 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:39 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 02/20] hw/arm: Connect BSC to BCM2835 board as I2C0, I2C1 and I2C2 Date: Tue, 5 Mar 2024 13:52:19 +0000 Message-Id: <20240305135237.3111642-3-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::331; envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x331.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Rayhan Faizel BCM2835 has three I2C controllers. All of them share the same interrupt line. Signed-off-by: Rayhan Faizel Reviewed-by: Philippe Mathieu-Daudé Message-id: 20240224191038.2409945-3-rayhan.faizel@gmail.com Signed-off-by: Peter Maydell --- include/hw/arm/bcm2835_peripherals.h | 4 ++- hw/arm/bcm2835_peripherals.c | 45 ++++++++++++++++++++++++++-- hw/arm/Kconfig | 1 + 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h index 1fc96218f82..636203baa5a 100644 --- a/include/hw/arm/bcm2835_peripherals.h +++ b/include/hw/arm/bcm2835_peripherals.h @@ -32,6 +32,7 @@ #include "hw/timer/bcm2835_systmr.h" #include "hw/usb/hcd-dwc2.h" #include "hw/ssi/bcm2835_spi.h" +#include "hw/i2c/bcm2835_i2c.h" #include "hw/misc/unimp.h" #include "qom/object.h" @@ -68,7 +69,8 @@ struct BCMSocPeripheralBaseState { BCM2835SDHostState sdhost; UnimplementedDeviceState i2s; BCM2835SPIState spi[1]; - UnimplementedDeviceState i2c[3]; + BCM2835I2CState i2c[3]; + OrIRQState orgated_i2c_irq; UnimplementedDeviceState otp; UnimplementedDeviceState dbus; UnimplementedDeviceState ave0; diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c index a0bbe76f264..1695d8b453a 100644 --- a/hw/arm/bcm2835_peripherals.c +++ b/hw/arm/bcm2835_peripherals.c @@ -30,6 +30,9 @@ #define SEPARATE_DMA_IRQ_MAX 10 #define ORGATED_DMA_IRQ_COUNT 4 +/* All three I2C controllers share the same IRQ */ +#define ORGATED_I2C_IRQ_COUNT 3 + void create_unimp(BCMSocPeripheralBaseState *ps, UnimplementedDeviceState *uds, const char *name, hwaddr ofs, hwaddr size) @@ -157,6 +160,19 @@ static void raspi_peripherals_base_init(Object *obj) /* SPI */ object_initialize_child(obj, "bcm2835-spi0", &s->spi[0], TYPE_BCM2835_SPI); + + /* I2C */ + object_initialize_child(obj, "bcm2835-i2c0", &s->i2c[0], + TYPE_BCM2835_I2C); + object_initialize_child(obj, "bcm2835-i2c1", &s->i2c[1], + TYPE_BCM2835_I2C); + object_initialize_child(obj, "bcm2835-i2c2", &s->i2c[2], + TYPE_BCM2835_I2C); + + object_initialize_child(obj, "orgated-i2c-irq", + &s->orgated_i2c_irq, TYPE_OR_IRQ); + object_property_set_int(OBJECT(&s->orgated_i2c_irq), "num-lines", + ORGATED_I2C_IRQ_COUNT, &error_abort); } static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) @@ -453,14 +469,37 @@ void bcm_soc_peripherals_common_realize(DeviceState *dev, Error **errp) BCM2835_IC_GPU_IRQ, INTERRUPT_SPI)); + /* I2C */ + for (n = 0; n < 3; n++) { + if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c[n]), errp)) { + return; + } + } + + memory_region_add_subregion(&s->peri_mr, BSC0_OFFSET, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->i2c[0]), 0)); + memory_region_add_subregion(&s->peri_mr, BSC1_OFFSET, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->i2c[1]), 0)); + memory_region_add_subregion(&s->peri_mr, BSC2_OFFSET, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->i2c[2]), 0)); + + if (!qdev_realize(DEVICE(&s->orgated_i2c_irq), NULL, errp)) { + return; + } + for (n = 0; n < ORGATED_I2C_IRQ_COUNT; n++) { + sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[n]), 0, + qdev_get_gpio_in(DEVICE(&s->orgated_i2c_irq), n)); + } + qdev_connect_gpio_out(DEVICE(&s->orgated_i2c_irq), 0, + qdev_get_gpio_in_named(DEVICE(&s->ic), + BCM2835_IC_GPU_IRQ, + INTERRUPT_I2C)); + create_unimp(s, &s->txp, "bcm2835-txp", TXP_OFFSET, 0x1000); create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40); create_unimp(s, &s->i2s, "bcm2835-i2s", I2S_OFFSET, 0x100); create_unimp(s, &s->smi, "bcm2835-smi", SMI_OFFSET, 0x100); create_unimp(s, &s->bscsl, "bcm2835-spis", BSC_SL_OFFSET, 0x100); - create_unimp(s, &s->i2c[0], "bcm2835-i2c0", BSC0_OFFSET, 0x20); - create_unimp(s, &s->i2c[1], "bcm2835-i2c1", BSC1_OFFSET, 0x20); - create_unimp(s, &s->i2c[2], "bcm2835-i2c2", BSC2_OFFSET, 0x20); create_unimp(s, &s->otp, "bcm2835-otp", OTP_OFFSET, 0x80); create_unimp(s, &s->dbus, "bcm2835-dbus", DBUS_OFFSET, 0x8000); create_unimp(s, &s->ave0, "bcm2835-ave0", AVE0_OFFSET, 0x8000); diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 7caebdd98e1..3c157376844 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -438,6 +438,7 @@ config RASPI select SDHCI select USB_DWC2 select BCM2835_SPI + select BCM2835_I2C config STM32F100_SOC bool From patchwork Tue Mar 5 13:52:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582460 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 28A62C54E49 for ; Tue, 5 Mar 2024 13:53:41 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVEZ-0001DJ-L2; Tue, 05 Mar 2024 08:53:31 -0500 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 1rhVDt-0000va-4Z for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:49 -0500 Received: from mail-wm1-x32b.google.com ([2a00:1450:4864:20::32b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDm-0005xD-Na for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:48 -0500 Received: by mail-wm1-x32b.google.com with SMTP id 5b1f17b1804b1-412ebda8772so5739195e9.3 for ; Tue, 05 Mar 2024 05:52:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646760; x=1710251560; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=tz7e0axdRAsRzGQKByGesEJpVfUbUyDvuhdaeTdsD0U=; b=E+eMU5rQw/pSo0mUybSI7MEnUrJ1OREIoizoqPGXUU6HQ1czCik36e0AcmSjV/9x3/ H61X577PV44i/WsgT8UPZs3C4lggTtwCE5qXNS0vrM+mCe+v1JtRvFgoQfWDeYTxowJF fxV+lBycJH1vGJFX+i2hVxPl/82b5uGl5vixa+oxCjABs5LJLWNPJ2r3TxpQWoz+M+dl y8Veb0NGGQfKzBg6pZ0KvVzeIidyOGTvwKQdV2CzOUFIialETcdCqTCZ+t+8AIpjqKYB lC5QrRDY0k0VQBwhJbXMxfdU/uomtokYzZYDJB6NsLmQXKFMLEpbvCxfisTGERmBTABW 99hA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646760; x=1710251560; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tz7e0axdRAsRzGQKByGesEJpVfUbUyDvuhdaeTdsD0U=; b=FIux1pFvrxhJbBbqEFUQaA0ZYGUfTNBbvxYHGwLAvqz3OyJaY2C2ApPsgRQ7DcC0c/ +dQnQQTYrNKHRw7VwH/2k65CSzM0AH/+jNQpSlTB5F8flnrdWNjeUXVEmnl482ixTl79 9sUgxnZslYe91fNkaG2MYfjmfORlGRqK9olLNYOqh7uYOX+uizt9GjELfcY8EkECvJot 3BXCLJAQJj3u10w4v+1qd3RDYpLNXd27gwet/ggVt0uesknYp0reVcfPF4KO/ef/T8cp fVL3Cgu5OkCx7iadBKKw56NGVsMuDwQ4RQqmeOenplLB+bZzChCQXNtAEOIc2k2/bTiG +7iQ== X-Gm-Message-State: AOJu0YxvamRkJHrNuZetW0mlNbOqT0RmfYCo4eo/GoCjjncKkPGIXmK9 ZTB8eEd9TevTT+dZgCDuMtgld6BNHDGZAdjULnlFVPvxhzKFgAvU1wAWwVQBg33np/xFl6LS6i7 7 X-Google-Smtp-Source: AGHT+IFP0lcLf6uV7kNSKmVZzdFHd4uE+otSmPKCJaNoji+QvPjUBYTzJ1By1ndT7yegsVfzmmUdLQ== X-Received: by 2002:adf:f6c7:0:b0:33d:dcd4:9d8f with SMTP id y7-20020adff6c7000000b0033ddcd49d8fmr8178037wrp.65.1709646760123; Tue, 05 Mar 2024 05:52:40 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.39 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:39 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 03/20] tests/qtest: Add testcase for BCM2835 BSC Date: Tue, 5 Mar 2024 13:52:20 +0000 Message-Id: <20240305135237.3111642-4-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::32b; envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x32b.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Rayhan Faizel Simple testcase for validating proper operation of read and write for all three BSC controllers. Signed-off-by: Rayhan Faizel Reviewed-by: Peter Maydell Message-id: 20240224191038.2409945-4-rayhan.faizel@gmail.com Signed-off-by: Peter Maydell --- tests/qtest/bcm2835-i2c-test.c | 115 +++++++++++++++++++++++++++++++++ tests/qtest/meson.build | 2 +- 2 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 tests/qtest/bcm2835-i2c-test.c diff --git a/tests/qtest/bcm2835-i2c-test.c b/tests/qtest/bcm2835-i2c-test.c new file mode 100644 index 00000000000..513ecce61dc --- /dev/null +++ b/tests/qtest/bcm2835-i2c-test.c @@ -0,0 +1,115 @@ +/* + * QTest testcase for Broadcom Serial Controller (BSC) + * + * Copyright (c) 2024 Rayhan Faizel + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "libqtest-single.h" + +#include "hw/i2c/bcm2835_i2c.h" +#include "hw/sensor/tmp105_regs.h" + +static const uint32_t bsc_base_addrs[] = { + 0x3f205000, /* I2C0 */ + 0x3f804000, /* I2C1 */ + 0x3f805000, /* I2C2 */ +}; + +static void bcm2835_i2c_init_transfer(uint32_t base_addr, bool read) +{ + /* read flag is bit 0 so we can write it directly */ + int interrupt = read ? BCM2835_I2C_C_INTR : BCM2835_I2C_C_INTT; + + writel(base_addr + BCM2835_I2C_C, + BCM2835_I2C_C_I2CEN | BCM2835_I2C_C_INTD | + BCM2835_I2C_C_ST | BCM2835_I2C_C_CLEAR | interrupt | read); +} + +static void test_i2c_read_write(gconstpointer data) +{ + uint32_t i2cdata; + intptr_t index = (intptr_t) data; + uint32_t base_addr = bsc_base_addrs[index]; + + /* Write to TMP105 register */ + writel(base_addr + BCM2835_I2C_A, 0x50); + writel(base_addr + BCM2835_I2C_DLEN, 3); + + bcm2835_i2c_init_transfer(base_addr, 0); + + writel(base_addr + BCM2835_I2C_FIFO, TMP105_REG_T_HIGH); + writel(base_addr + BCM2835_I2C_FIFO, 0xde); + writel(base_addr + BCM2835_I2C_FIFO, 0xad); + + /* Clear flags */ + writel(base_addr + BCM2835_I2C_S, BCM2835_I2C_S_DONE | BCM2835_I2C_S_ERR | + BCM2835_I2C_S_CLKT); + + /* Read from TMP105 register */ + writel(base_addr + BCM2835_I2C_A, 0x50); + writel(base_addr + BCM2835_I2C_DLEN, 1); + + bcm2835_i2c_init_transfer(base_addr, 0); + + writel(base_addr + BCM2835_I2C_FIFO, TMP105_REG_T_HIGH); + + writel(base_addr + BCM2835_I2C_DLEN, 2); + bcm2835_i2c_init_transfer(base_addr, 1); + + i2cdata = readl(base_addr + BCM2835_I2C_FIFO); + g_assert_cmpint(i2cdata, ==, 0xde); + + i2cdata = readl(base_addr + BCM2835_I2C_FIFO); + g_assert_cmpint(i2cdata, ==, 0xad); + + /* Clear flags */ + writel(base_addr + BCM2835_I2C_S, BCM2835_I2C_S_DONE | BCM2835_I2C_S_ERR | + BCM2835_I2C_S_CLKT); + +} + +int main(int argc, char **argv) +{ + int ret; + int i; + + g_test_init(&argc, &argv, NULL); + + for (i = 0; i < 3; i++) { + g_autofree char *test_name = + g_strdup_printf("/bcm2835/bcm2835-i2c%d/read_write", i); + qtest_add_data_func(test_name, (void *)(intptr_t) i, + test_i2c_read_write); + } + + /* Run I2C tests with TMP105 slaves on all three buses */ + qtest_start("-M raspi3b " + "-device tmp105,address=0x50,bus=i2c-bus.0 " + "-device tmp105,address=0x50,bus=i2c-bus.1 " + "-device tmp105,address=0x50,bus=i2c-bus.2"); + ret = g_test_run(); + qtest_end(); + + return ret; +} diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 6ea77893f50..bdc8bba7a98 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -230,7 +230,7 @@ qtests_aarch64 = \ ['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) + \ (config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test', 'fuzz-xlnx-dp-test'] : []) + \ (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test', 'xlnx-versal-trng-test'] : []) + \ - (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) + \ + (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test', 'bcm2835-i2c-test'] : []) + \ (config_all_accel.has_key('CONFIG_TCG') and \ config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \ ['arm-cpu-features', From patchwork Tue Mar 5 13:52:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582472 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 016B2C54798 for ; Tue, 5 Mar 2024 13:54:26 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVF1-0002Vw-SN; Tue, 05 Mar 2024 08:53:59 -0500 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 1rhVDs-0000vX-To for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:49 -0500 Received: from mail-wr1-x432.google.com ([2a00:1450:4864:20::432]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDm-0005xL-Ff for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:48 -0500 Received: by mail-wr1-x432.google.com with SMTP id ffacd0b85a97d-33e1207bba1so4538489f8f.1 for ; Tue, 05 Mar 2024 05:52:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646761; x=1710251561; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=uGzpyI9XVFpyvThOBaS71QfWPFb/RDXMpVkRqMA05YE=; b=Yl29RtKkELLesXUUbkQE0aef3GfYs+BdON3/l/KX62P8UXBtgYPaBaGF75i0x6lF/H f60lyxYOG6SItTcsqvEE58jZXD4JXEZmIXpKYD06VV0xpxUerEVMZ+UZYZe2Y5k/491o geuGyh5d29Jq0ZOsb7tBejZY7OuEcv2RTjAktD5cm5BsZmqFbVSVfTQh0zHEpe0n4r2C 3xZGnJpzCK2CJJS03K59S544rhmtYRBhe10dOmpViNfnNqhCO9VghCduKYWYTI7EwTBB ufIXyft6lK7nPJrC0hRmYM70CnKwhmMl2EHifzwBeKjQtDqd6bx1cOVuY2i9v+E+OxPU K5NA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646761; x=1710251561; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=uGzpyI9XVFpyvThOBaS71QfWPFb/RDXMpVkRqMA05YE=; b=rsy/NbPp43uhc6sFzenwPKZbgzQMBPYuh+0QXqwgx2SUm3LV/c25fPKO8hY4jUj8GR wdzSesUU7uDziFUdfJ9ignLoJun6CwrXhq3B3F36Th8jHbj5CVKGwBPa5/G4aJLYY0f8 sHDHW+DMZJO9J2y4UhX7Ro5WufKIL/+d5dBzUFjmcQVmaEAuBYH3W9msqWzykE7z0w7p pvFMOtFHPHiwtXMHywNaBj84+CZx47Fyony0y0lS0/XzMIxM1HUB0Vk7VW4dYNkzE6Sy T/A4FYaySvy9WVrswRqB+o4L8rtQs1tL2BNRR/g2/R0HW1hdPUkGIfnXPROEFRGx50zJ 22Bg== X-Gm-Message-State: AOJu0YxVnCzjlxMG5/dSF1W4pfrt9DMxe/HQLDTVEv8QufZKt6iSGLpH wdZIFIQP3dLtfRd6x3brxqnQHCVJGHraaSezVmDyyiFcqlZgknODq8NiuQZo6S/MWkdG9INrSER g X-Google-Smtp-Source: AGHT+IF1tpbbhyrfDT7BQo/U8AM4lwnoAt54qWA/eR04pb5K6RWfmRdX7q891H9PSPPEcYxjp/9jHQ== X-Received: by 2002:adf:ec4f:0:b0:33e:3d71:445f with SMTP id w15-20020adfec4f000000b0033e3d71445fmr4631228wrn.32.1709646761095; Tue, 05 Mar 2024 05:52:41 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.40 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:40 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 04/20] hw/char/pl011: Add support for loopback Date: Tue, 5 Mar 2024 13:52:21 +0000 Message-Id: <20240305135237.3111642-5-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::432; envelope-from=peter.maydell@linaro.org; helo=mail-wr1-x432.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Tong Ho This patch adds loopback for sent characters, sent BREAK, and modem-control signals. Loopback of send and modem-control is often used for uart self tests in real hardware but missing from current pl011 model, resulting in self-test failures when running in QEMU. This implementation matches what is observed in real pl011 hardware placed in loopback mode: 1. Input characters and BREAK events from serial backend are ignored, but 2. Both TX characters and BREAK events are still sent to serial backend, in addition to be looped back to RX. Signed-off-by: Tong Ho Signed-off-by: Francisco Iglesias Message-id: 20240227054855.44204-1-tong.ho@amd.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/char/pl011.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 108 insertions(+), 2 deletions(-) diff --git a/hw/char/pl011.c b/hw/char/pl011.c index 855cb82d08d..8753b84a842 100644 --- a/hw/char/pl011.c +++ b/hw/char/pl011.c @@ -49,10 +49,14 @@ DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr) } /* Flag Register, UARTFR */ +#define PL011_FLAG_RI 0x100 #define PL011_FLAG_TXFE 0x80 #define PL011_FLAG_RXFF 0x40 #define PL011_FLAG_TXFF 0x20 #define PL011_FLAG_RXFE 0x10 +#define PL011_FLAG_DCD 0x04 +#define PL011_FLAG_DSR 0x02 +#define PL011_FLAG_CTS 0x01 /* Data Register, UARTDR */ #define DR_BE (1 << 10) @@ -76,6 +80,13 @@ DeviceState *pl011_create(hwaddr addr, qemu_irq irq, Chardev *chr) #define LCR_FEN (1 << 4) #define LCR_BRK (1 << 0) +/* Control Register, UARTCR */ +#define CR_OUT2 (1 << 13) +#define CR_OUT1 (1 << 12) +#define CR_RTS (1 << 11) +#define CR_DTR (1 << 10) +#define CR_LBE (1 << 7) + static const unsigned char pl011_id_arm[8] = { 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 }; static const unsigned char pl011_id_luminary[8] = @@ -251,6 +262,89 @@ static void pl011_trace_baudrate_change(const PL011State *s) s->ibrd, s->fbrd); } +static bool pl011_loopback_enabled(PL011State *s) +{ + return !!(s->cr & CR_LBE); +} + +static void pl011_loopback_mdmctrl(PL011State *s) +{ + uint32_t cr, fr, il; + + if (!pl011_loopback_enabled(s)) { + return; + } + + /* + * Loopback software-driven modem control outputs to modem status inputs: + * FR.RI <= CR.Out2 + * FR.DCD <= CR.Out1 + * FR.CTS <= CR.RTS + * FR.DSR <= CR.DTR + * + * The loopback happens immediately even if this call is triggered + * by setting only CR.LBE. + * + * CTS/RTS updates due to enabled hardware flow controls are not + * dealt with here. + */ + cr = s->cr; + fr = s->flags & ~(PL011_FLAG_RI | PL011_FLAG_DCD | + PL011_FLAG_DSR | PL011_FLAG_CTS); + fr |= (cr & CR_OUT2) ? PL011_FLAG_RI : 0; + fr |= (cr & CR_OUT1) ? PL011_FLAG_DCD : 0; + fr |= (cr & CR_RTS) ? PL011_FLAG_CTS : 0; + fr |= (cr & CR_DTR) ? PL011_FLAG_DSR : 0; + + /* Change interrupts based on updated FR */ + il = s->int_level & ~(INT_DSR | INT_DCD | INT_CTS | INT_RI); + il |= (fr & PL011_FLAG_DSR) ? INT_DSR : 0; + il |= (fr & PL011_FLAG_DCD) ? INT_DCD : 0; + il |= (fr & PL011_FLAG_CTS) ? INT_CTS : 0; + il |= (fr & PL011_FLAG_RI) ? INT_RI : 0; + + s->flags = fr; + s->int_level = il; + pl011_update(s); +} + +static void pl011_put_fifo(void *opaque, uint32_t value); + +static void pl011_loopback_tx(PL011State *s, uint32_t value) +{ + if (!pl011_loopback_enabled(s)) { + return; + } + + /* + * Caveat: + * + * In real hardware, TX loopback happens at the serial-bit level + * and then reassembled by the RX logics back into bytes and placed + * into the RX fifo. That is, loopback happens after TX fifo. + * + * Because the real hardware TX fifo is time-drained at the frame + * rate governed by the configured serial format, some loopback + * bytes in TX fifo may still be able to get into the RX fifo + * that could be full at times while being drained at software + * pace. + * + * In such scenario, the RX draining pace is the major factor + * deciding which loopback bytes get into the RX fifo, unless + * hardware flow-control is enabled. + * + * For simplicity, the above described is not emulated. + */ + pl011_put_fifo(s, value); +} + +static void pl011_loopback_break(PL011State *s, int brk_enable) +{ + if (brk_enable) { + pl011_loopback_tx(s, DR_BE); + } +} + static void pl011_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { @@ -266,6 +360,7 @@ static void pl011_write(void *opaque, hwaddr offset, /* XXX this blocks entire thread. Rewrite to use * qemu_chr_fe_write and background I/O callbacks */ qemu_chr_fe_write_all(&s->chr, &ch, 1); + pl011_loopback_tx(s, ch); s->int_level |= INT_TX; pl011_update(s); break; @@ -295,13 +390,15 @@ static void pl011_write(void *opaque, hwaddr offset, int break_enable = value & LCR_BRK; qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_BREAK, &break_enable); + pl011_loopback_break(s, break_enable); } s->lcr = value; pl011_set_read_trigger(s); break; case 12: /* UARTCR */ - /* ??? Need to implement the enable and loopback bits. */ + /* ??? Need to implement the enable bit. */ s->cr = value; + pl011_loopback_mdmctrl(s); break; case 13: /* UARTIFS */ s->ifl = value; @@ -361,12 +458,21 @@ static void pl011_put_fifo(void *opaque, uint32_t value) static void pl011_receive(void *opaque, const uint8_t *buf, int size) { + /* + * In loopback mode, the RX input signal is internally disconnected + * from the entire receiving logics; thus, all inputs are ignored, + * and BREAK detection on RX input signal is also not performed. + */ + if (pl011_loopback_enabled(opaque)) { + return; + } + pl011_put_fifo(opaque, *buf); } static void pl011_event(void *opaque, QEMUChrEvent event) { - if (event == CHR_EVENT_BREAK) { + if (event == CHR_EVENT_BREAK && !pl011_loopback_enabled(opaque)) { pl011_put_fifo(opaque, DR_BE); } } From patchwork Tue Mar 5 13:52:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582483 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 DE81EC54E41 for ; Tue, 5 Mar 2024 13:57:58 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVF2-0002Yp-H8; Tue, 05 Mar 2024 08:54:00 -0500 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 1rhVDv-0000wT-Rp for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:53:06 -0500 Received: from mail-wm1-x331.google.com ([2a00:1450:4864:20::331]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDn-0005xP-3U for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:51 -0500 Received: by mail-wm1-x331.google.com with SMTP id 5b1f17b1804b1-412e80e13abso12753235e9.3 for ; Tue, 05 Mar 2024 05:52:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646762; x=1710251562; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=eaqVPRt6BcQcR103zq7Y8/ZWh4N8YJjgwkhqJ9UI0Q0=; b=VFvg5xRzSQhABKY2Wj7+OywBvjh6sD9VxlrgRk1GNkhTju5yg2g87hEkPQHUgw+0b0 567bMB464qP8Wlyb/THvXcYNCox8eWYJDIH8BBGcTu0gxP8wdSDXrj9U/PyQkWpjUSD6 hgq8gvsZ+trQsGOu0CweMhsAAXOV+iB7YGhzP3dYX7XXF0WeLuWB6hFg+2z8fNAT8+uB 1SbFO42oMq5lE0aJQ8vUbtiEvjsAmnS1iQX0pZeq1wqHSYoeN9ypJTfWQMojP3/Qosxu RZ2ZHDyoC1J5KqtXGIXqKSfOOzToU2zvg8awwcaOfdh7psy42IeuOJ0XHyvqkqc+GvJX xOKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646762; x=1710251562; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=eaqVPRt6BcQcR103zq7Y8/ZWh4N8YJjgwkhqJ9UI0Q0=; b=YDSOFu1rAE0RHrXhcqnPt3JGescbWk2b/t4ZFOO31RLyhgj+MVjDqfrxALhiOADL4h dhlh6r3no89NipW83mTRkIhXDFxgwlHLaUJ5WbfzqUwx/WiYw8QEvLBdwEUc2a2JJOPU RzM5GekVhobHYJ71bwb09/WSQrW5/vjc4OMnpx9ZQXf3kZC3n4xGk5+J7/lXSqmoY20j TnsM6NiFzi+/Wq+kvBEe5s5KxiL+HIU6rzzKWBOacCrkSn/55hi6DdP/vEhXThatlpnL M8WC+cZjnRjoBESlbwVC+gF8LTxiBvRsg4PgwswuXV+SYtOx4i2ZvWZp3f/fOzS70G6w 94eg== X-Gm-Message-State: AOJu0YyjmKeGU1ektFZiXa2cXA7NtQ3mi9YgqbCeDnG9ZJ1iVGMcYkgg 7NsUYhXCkoEqij71J4Tl8CTIlk3vI2Bm5m43zje6/+LZY4Kug2/hX/COB6Wh2k+d5BMsiYQxc1/ K X-Google-Smtp-Source: AGHT+IHAd48cZ2LH0dUBlFv1isabJTdQj8c+XRw9md0teR2bJyBVBqtcdIq0u3A9pKy6f5p0jWuudQ== X-Received: by 2002:a05:6000:1947:b0:33d:29d5:d970 with SMTP id e7-20020a056000194700b0033d29d5d970mr8048877wry.45.1709646761564; Tue, 05 Mar 2024 05:52:41 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.41 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:41 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 05/20] hw/misc/stm32l4x5_rcc: Implement STM32L4x5_RCC skeleton Date: Tue, 5 Mar 2024 13:52:22 +0000 Message-Id: <20240305135237.3111642-6-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::331; envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x331.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01, WEIRD_QUOTING=0.001 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Arnaud Minier Add the necessary files to add a simple RCC implementation with just reads from and writes to registers. Also instantiate the RCC in the STM32L4x5_SoC. It is needed for accurate emulation of all the SoC clocks and timers. Signed-off-by: Arnaud Minier Signed-off-by: Inès Varhol Acked-by: Alistair Francis Reviewed-by: Peter Maydell Message-id: 20240303140643.81957-2-arnaud.minier@telecom-paris.fr Signed-off-by: Peter Maydell --- MAINTAINERS | 5 +- docs/system/arm/b-l475e-iot01a.rst | 2 +- include/hw/arm/stm32l4x5_soc.h | 2 + include/hw/misc/stm32l4x5_rcc.h | 80 ++++ include/hw/misc/stm32l4x5_rcc_internals.h | 286 ++++++++++++++ hw/arm/stm32l4x5_soc.c | 12 +- hw/misc/stm32l4x5_rcc.c | 446 ++++++++++++++++++++++ hw/arm/Kconfig | 1 + hw/misc/Kconfig | 3 + hw/misc/meson.build | 1 + hw/misc/trace-events | 4 + 11 files changed, 839 insertions(+), 3 deletions(-) create mode 100644 include/hw/misc/stm32l4x5_rcc.h create mode 100644 include/hw/misc/stm32l4x5_rcc_internals.h create mode 100644 hw/misc/stm32l4x5_rcc.c diff --git a/MAINTAINERS b/MAINTAINERS index 65dfdc9677e..4183f2f3abb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1130,7 +1130,10 @@ M: Inès Varhol L: qemu-arm@nongnu.org S: Maintained F: hw/arm/stm32l4x5_soc.c -F: include/hw/arm/stm32l4x5_soc.h +F: hw/misc/stm32l4x5_exti.c +F: hw/misc/stm32l4x5_syscfg.c +F: hw/misc/stm32l4x5_rcc.c +F: include/hw/*/stm32l4x5_*.h B-L475E-IOT01A IoT Node M: Arnaud Minier diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst index 1a021b306a6..b857a56ca4e 100644 --- a/docs/system/arm/b-l475e-iot01a.rst +++ b/docs/system/arm/b-l475e-iot01a.rst @@ -17,13 +17,13 @@ Currently B-L475E-IOT01A machine's only supports the following devices: - Cortex-M4F based STM32L4x5 SoC - STM32L4x5 EXTI (Extended interrupts and events controller) - STM32L4x5 SYSCFG (System configuration controller) +- STM32L4x5 RCC (Reset and clock control) Missing devices """"""""""""""" The B-L475E-IOT01A does *not* support the following devices: -- Reset and clock control (RCC) - Serial ports (UART) - General-purpose I/Os (GPIO) - Analog to Digital Converter (ADC) diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h index 4f314b7a933..0b4f97e240e 100644 --- a/include/hw/arm/stm32l4x5_soc.h +++ b/include/hw/arm/stm32l4x5_soc.h @@ -29,6 +29,7 @@ #include "hw/or-irq.h" #include "hw/misc/stm32l4x5_syscfg.h" #include "hw/misc/stm32l4x5_exti.h" +#include "hw/misc/stm32l4x5_rcc.h" #include "qom/object.h" #define TYPE_STM32L4X5_SOC "stm32l4x5-soc" @@ -47,6 +48,7 @@ struct Stm32l4x5SocState { Stm32l4x5ExtiState exti; OrIRQState exti_or_gates[NUM_EXTI_OR_GATES]; Stm32l4x5SyscfgState syscfg; + Stm32l4x5RccState rcc; MemoryRegion sram1; MemoryRegion sram2; diff --git a/include/hw/misc/stm32l4x5_rcc.h b/include/hw/misc/stm32l4x5_rcc.h new file mode 100644 index 00000000000..5157e966352 --- /dev/null +++ b/include/hw/misc/stm32l4x5_rcc.h @@ -0,0 +1,80 @@ +/* + * STM32L4X5 RCC (Reset and clock control) + * + * Copyright (c) 2023 Arnaud Minier + * Copyright (c) 2023 Inès Varhol + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * The reference used is the STMicroElectronics RM0351 Reference manual + * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs. + * + * Inspired by the BCM2835 CPRMAN clock manager by Luc Michel. + */ + +#ifndef HW_STM32L4X5_RCC_H +#define HW_STM32L4X5_RCC_H + +#include "hw/sysbus.h" +#include "qom/object.h" + +#define TYPE_STM32L4X5_RCC "stm32l4x5-rcc" +OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5RccState, STM32L4X5_RCC) + +/* In the Stm32l4x5 clock tree, mux have at most 7 sources */ +#define RCC_NUM_CLOCK_MUX_SRC 7 +struct Stm32l4x5RccState { + SysBusDevice parent_obj; + + MemoryRegion mmio; + + uint32_t cr; + uint32_t icscr; + uint32_t cfgr; + uint32_t pllcfgr; + uint32_t pllsai1cfgr; + uint32_t pllsai2cfgr; + uint32_t cier; + uint32_t cifr; + uint32_t ahb1rstr; + uint32_t ahb2rstr; + uint32_t ahb3rstr; + uint32_t apb1rstr1; + uint32_t apb1rstr2; + uint32_t apb2rstr; + uint32_t ahb1enr; + uint32_t ahb2enr; + uint32_t ahb3enr; + uint32_t apb1enr1; + uint32_t apb1enr2; + uint32_t apb2enr; + uint32_t ahb1smenr; + uint32_t ahb2smenr; + uint32_t ahb3smenr; + uint32_t apb1smenr1; + uint32_t apb1smenr2; + uint32_t apb2smenr; + uint32_t ccipr; + uint32_t bdcr; + uint32_t csr; + + /* Clock sources */ + Clock *gnd; + Clock *hsi16_rc; + Clock *msi_rc; + Clock *hse; + Clock *lsi_rc; + Clock *lse_crystal; + Clock *sai1_extclk; + Clock *sai2_extclk; + + qemu_irq irq; + uint64_t hse_frequency; + uint64_t sai1_extclk_frequency; + uint64_t sai2_extclk_frequency; +}; + +#endif /* HW_STM32L4X5_RCC_H */ diff --git a/include/hw/misc/stm32l4x5_rcc_internals.h b/include/hw/misc/stm32l4x5_rcc_internals.h new file mode 100644 index 00000000000..331ea30db57 --- /dev/null +++ b/include/hw/misc/stm32l4x5_rcc_internals.h @@ -0,0 +1,286 @@ +/* + * STM32L4X5 RCC (Reset and clock control) + * + * Copyright (c) 2023 Arnaud Minier + * Copyright (c) 2023 Inès Varhol + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * The reference used is the STMicroElectronics RM0351 Reference manual + * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs. + * + * Inspired by the BCM2835 CPRMAN clock manager implementation by Luc Michel. + */ + +#ifndef HW_STM32L4X5_RCC_INTERNALS_H +#define HW_STM32L4X5_RCC_INTERNALS_H + +#include "hw/registerfields.h" +#include "hw/misc/stm32l4x5_rcc.h" + + +/* Register map */ +REG32(CR, 0x00) + FIELD(CR, PLLSAI2RDY, 29, 1) + FIELD(CR, PLLSAI2ON, 28, 1) + FIELD(CR, PLLSAI1RDY, 27, 1) + FIELD(CR, PLLSAI1ON, 26, 1) + FIELD(CR, PLLRDY, 25, 1) + FIELD(CR, PLLON, 24, 1) + FIELD(CR, CSSON, 19, 1) + FIELD(CR, HSEBYP, 18, 1) + FIELD(CR, HSERDY, 17, 1) + FIELD(CR, HSEON, 16, 1) + FIELD(CR, HSIASFS, 11, 1) + FIELD(CR, HSIRDY, 10, 1) + FIELD(CR, HSIKERON, 9, 1) + FIELD(CR, HSION, 8, 1) + FIELD(CR, MSIRANGE, 4, 4) + FIELD(CR, MSIRGSEL, 3, 1) + FIELD(CR, MSIPLLEN, 2, 1) + FIELD(CR, MSIRDY, 1, 1) + FIELD(CR, MSION, 0, 1) +REG32(ICSCR, 0x04) + FIELD(ICSCR, HSITRIM, 24, 7) + FIELD(ICSCR, HSICAL, 16, 8) + FIELD(ICSCR, MSITRIM, 8, 8) + FIELD(ICSCR, MSICAL, 0, 8) +REG32(CFGR, 0x08) + FIELD(CFGR, MCOPRE, 28, 3) + /* MCOSEL[2:0] only for STM32L475xx/476xx/486xx devices */ + FIELD(CFGR, MCOSEL, 24, 3) + FIELD(CFGR, STOPWUCK, 15, 1) + FIELD(CFGR, PPRE2, 11, 3) + FIELD(CFGR, PPRE1, 8, 3) + FIELD(CFGR, HPRE, 4, 4) + FIELD(CFGR, SWS, 2, 2) + FIELD(CFGR, SW, 0, 2) +REG32(PLLCFGR, 0x0C) + FIELD(PLLCFGR, PLLPDIV, 27, 5) + FIELD(PLLCFGR, PLLR, 25, 2) + FIELD(PLLCFGR, PLLREN, 24, 1) + FIELD(PLLCFGR, PLLQ, 21, 2) + FIELD(PLLCFGR, PLLQEN, 20, 1) + FIELD(PLLCFGR, PLLP, 17, 1) + FIELD(PLLCFGR, PLLPEN, 16, 1) + FIELD(PLLCFGR, PLLN, 8, 7) + FIELD(PLLCFGR, PLLM, 4, 3) + FIELD(PLLCFGR, PLLSRC, 0, 2) +REG32(PLLSAI1CFGR, 0x10) + FIELD(PLLSAI1CFGR, PLLSAI1PDIV, 27, 5) + FIELD(PLLSAI1CFGR, PLLSAI1R, 25, 2) + FIELD(PLLSAI1CFGR, PLLSAI1REN, 24, 1) + FIELD(PLLSAI1CFGR, PLLSAI1Q, 21, 2) + FIELD(PLLSAI1CFGR, PLLSAI1QEN, 20, 1) + FIELD(PLLSAI1CFGR, PLLSAI1P, 17, 1) + FIELD(PLLSAI1CFGR, PLLSAI1PEN, 16, 1) + FIELD(PLLSAI1CFGR, PLLSAI1N, 8, 7) +REG32(PLLSAI2CFGR, 0x14) + FIELD(PLLSAI2CFGR, PLLSAI2PDIV, 27, 5) + FIELD(PLLSAI2CFGR, PLLSAI2R, 25, 2) + FIELD(PLLSAI2CFGR, PLLSAI2REN, 24, 1) + FIELD(PLLSAI2CFGR, PLLSAI2Q, 21, 2) + FIELD(PLLSAI2CFGR, PLLSAI2QEN, 20, 1) + FIELD(PLLSAI2CFGR, PLLSAI2P, 17, 1) + FIELD(PLLSAI2CFGR, PLLSAI2PEN, 16, 1) + FIELD(PLLSAI2CFGR, PLLSAI2N, 8, 7) +REG32(CIER, 0x18) + /* HSI48RDYIE: only on STM32L496xx/4A6xx devices */ + FIELD(CIER, LSECSSIE, 9, 1) + FIELD(CIER, PLLSAI2RDYIE, 7, 1) + FIELD(CIER, PLLSAI1RDYIE, 6, 1) + FIELD(CIER, PLLRDYIE, 5, 1) + FIELD(CIER, HSERDYIE, 4, 1) + FIELD(CIER, HSIRDYIE, 3, 1) + FIELD(CIER, MSIRDYIE, 2, 1) + FIELD(CIER, LSERDYIE, 1, 1) + FIELD(CIER, LSIRDYIE, 0, 1) +REG32(CIFR, 0x1C) + /* HSI48RDYF: only on STM32L496xx/4A6xx devices */ + FIELD(CIFR, LSECSSF, 9, 1) + FIELD(CIFR, CSSF, 8, 1) + FIELD(CIFR, PLLSAI2RDYF, 7, 1) + FIELD(CIFR, PLLSAI1RDYF, 6, 1) + FIELD(CIFR, PLLRDYF, 5, 1) + FIELD(CIFR, HSERDYF, 4, 1) + FIELD(CIFR, HSIRDYF, 3, 1) + FIELD(CIFR, MSIRDYF, 2, 1) + FIELD(CIFR, LSERDYF, 1, 1) + FIELD(CIFR, LSIRDYF, 0, 1) +REG32(CICR, 0x20) + /* HSI48RDYC: only on STM32L496xx/4A6xx devices */ + FIELD(CICR, LSECSSC, 9, 1) + FIELD(CICR, CSSC, 8, 1) + FIELD(CICR, PLLSAI2RDYC, 7, 1) + FIELD(CICR, PLLSAI1RDYC, 6, 1) + FIELD(CICR, PLLRDYC, 5, 1) + FIELD(CICR, HSERDYC, 4, 1) + FIELD(CICR, HSIRDYC, 3, 1) + FIELD(CICR, MSIRDYC, 2, 1) + FIELD(CICR, LSERDYC, 1, 1) + FIELD(CICR, LSIRDYC, 0, 1) +REG32(AHB1RSTR, 0x28) +REG32(AHB2RSTR, 0x2C) +REG32(AHB3RSTR, 0x30) +REG32(APB1RSTR1, 0x38) +REG32(APB1RSTR2, 0x3C) +REG32(APB2RSTR, 0x40) +REG32(AHB1ENR, 0x48) + /* DMA2DEN: reserved for STM32L475xx */ + FIELD(AHB1ENR, TSCEN, 16, 1) + FIELD(AHB1ENR, CRCEN, 12, 1) + FIELD(AHB1ENR, FLASHEN, 8, 1) + FIELD(AHB1ENR, DMA2EN, 1, 1) + FIELD(AHB1ENR, DMA1EN, 0, 1) +REG32(AHB2ENR, 0x4C) + FIELD(AHB2ENR, RNGEN, 18, 1) + /* HASHEN: reserved for STM32L475xx */ + FIELD(AHB2ENR, AESEN, 16, 1) + /* DCMIEN: reserved for STM32L475xx */ + FIELD(AHB2ENR, ADCEN, 13, 1) + FIELD(AHB2ENR, OTGFSEN, 12, 1) + /* GPIOIEN: reserved for STM32L475xx */ + FIELD(AHB2ENR, GPIOHEN, 7, 1) + FIELD(AHB2ENR, GPIOGEN, 6, 1) + FIELD(AHB2ENR, GPIOFEN, 5, 1) + FIELD(AHB2ENR, GPIOEEN, 4, 1) + FIELD(AHB2ENR, GPIODEN, 3, 1) + FIELD(AHB2ENR, GPIOCEN, 2, 1) + FIELD(AHB2ENR, GPIOBEN, 1, 1) + FIELD(AHB2ENR, GPIOAEN, 0, 1) +REG32(AHB3ENR, 0x50) + FIELD(AHB3ENR, QSPIEN, 8, 1) + FIELD(AHB3ENR, FMCEN, 0, 1) +REG32(APB1ENR1, 0x58) + FIELD(APB1ENR1, LPTIM1EN, 31, 1) + FIELD(APB1ENR1, OPAMPEN, 30, 1) + FIELD(APB1ENR1, DAC1EN, 29, 1) + FIELD(APB1ENR1, PWREN, 28, 1) + FIELD(APB1ENR1, CAN2EN, 26, 1) + FIELD(APB1ENR1, CAN1EN, 25, 1) + /* CRSEN: reserved for STM32L475xx */ + FIELD(APB1ENR1, I2C3EN, 23, 1) + FIELD(APB1ENR1, I2C2EN, 22, 1) + FIELD(APB1ENR1, I2C1EN, 21, 1) + FIELD(APB1ENR1, UART5EN, 20, 1) + FIELD(APB1ENR1, UART4EN, 19, 1) + FIELD(APB1ENR1, USART3EN, 18, 1) + FIELD(APB1ENR1, USART2EN, 17, 1) + FIELD(APB1ENR1, SPI3EN, 15, 1) + FIELD(APB1ENR1, SPI2EN, 14, 1) + FIELD(APB1ENR1, WWDGEN, 11, 1) + /* RTCAPBEN: reserved for STM32L475xx */ + FIELD(APB1ENR1, LCDEN, 9, 1) + FIELD(APB1ENR1, TIM7EN, 5, 1) + FIELD(APB1ENR1, TIM6EN, 4, 1) + FIELD(APB1ENR1, TIM5EN, 3, 1) + FIELD(APB1ENR1, TIM4EN, 2, 1) + FIELD(APB1ENR1, TIM3EN, 1, 1) + FIELD(APB1ENR1, TIM2EN, 0, 1) +REG32(APB1ENR2, 0x5C) + FIELD(APB1ENR2, LPTIM2EN, 5, 1) + FIELD(APB1ENR2, SWPMI1EN, 2, 1) + /* I2C4EN: reserved for STM32L475xx */ + FIELD(APB1ENR2, LPUART1EN, 0, 1) +REG32(APB2ENR, 0x60) + FIELD(APB2ENR, DFSDM1EN, 24, 1) + FIELD(APB2ENR, SAI2EN, 22, 1) + FIELD(APB2ENR, SAI1EN, 21, 1) + FIELD(APB2ENR, TIM17EN, 18, 1) + FIELD(APB2ENR, TIM16EN, 17, 1) + FIELD(APB2ENR, TIM15EN, 16, 1) + FIELD(APB2ENR, USART1EN, 14, 1) + FIELD(APB2ENR, TIM8EN, 13, 1) + FIELD(APB2ENR, SPI1EN, 12, 1) + FIELD(APB2ENR, TIM1EN, 11, 1) + FIELD(APB2ENR, SDMMC1EN, 10, 1) + FIELD(APB2ENR, FWEN, 7, 1) + FIELD(APB2ENR, SYSCFGEN, 0, 1) +REG32(AHB1SMENR, 0x68) +REG32(AHB2SMENR, 0x6C) +REG32(AHB3SMENR, 0x70) +REG32(APB1SMENR1, 0x78) +REG32(APB1SMENR2, 0x7C) +REG32(APB2SMENR, 0x80) +REG32(CCIPR, 0x88) + FIELD(CCIPR, DFSDM1SEL, 31, 1) + FIELD(CCIPR, SWPMI1SEL, 30, 1) + FIELD(CCIPR, ADCSEL, 28, 2) + FIELD(CCIPR, CLK48SEL, 26, 2) + FIELD(CCIPR, SAI2SEL, 24, 2) + FIELD(CCIPR, SAI1SEL, 22, 2) + FIELD(CCIPR, LPTIM2SEL, 20, 2) + FIELD(CCIPR, LPTIM1SEL, 18, 2) + FIELD(CCIPR, I2C3SEL, 16, 2) + FIELD(CCIPR, I2C2SEL, 14, 2) + FIELD(CCIPR, I2C1SEL, 12, 2) + FIELD(CCIPR, LPUART1SEL, 10, 2) + FIELD(CCIPR, UART5SEL, 8, 2) + FIELD(CCIPR, UART4SEL, 6, 2) + FIELD(CCIPR, USART3SEL, 4, 2) + FIELD(CCIPR, USART2SEL, 2, 2) + FIELD(CCIPR, USART1SEL, 0, 2) +REG32(BDCR, 0x90) + FIELD(BDCR, LSCOSEL, 25, 1) + FIELD(BDCR, LSCOEN, 24, 1) + FIELD(BDCR, BDRST, 16, 1) + FIELD(BDCR, RTCEN, 15, 1) + FIELD(BDCR, RTCSEL, 8, 2) + FIELD(BDCR, LSECSSD, 6, 1) + FIELD(BDCR, LSECSSON, 5, 1) + FIELD(BDCR, LSEDRV, 3, 2) + FIELD(BDCR, LSEBYP, 2, 1) + FIELD(BDCR, LSERDY, 1, 1) + FIELD(BDCR, LSEON, 0, 1) +REG32(CSR, 0x94) + FIELD(CSR, LPWRRSTF, 31, 1) + FIELD(CSR, WWDGRSTF, 30, 1) + FIELD(CSR, IWWGRSTF, 29, 1) + FIELD(CSR, SFTRSTF, 28, 1) + FIELD(CSR, BORRSTF, 27, 1) + FIELD(CSR, PINRSTF, 26, 1) + FIELD(CSR, OBLRSTF, 25, 1) + FIELD(CSR, FWRSTF, 24, 1) + FIELD(CSR, RMVF, 23, 1) + FIELD(CSR, MSISRANGE, 8, 4) + FIELD(CSR, LSIRDY, 1, 1) + FIELD(CSR, LSION, 0, 1) +/* CRRCR and CCIPR2 registers are present on L496/L4A6 devices only. */ + +/* Read Only masks to prevent writes in unauthorized bits */ +#define CR_READ_ONLY_MASK (R_CR_PLLSAI2RDY_MASK | \ + R_CR_PLLSAI1RDY_MASK | \ + R_CR_PLLRDY_MASK | \ + R_CR_HSERDY_MASK | \ + R_CR_HSIRDY_MASK | \ + R_CR_MSIRDY_MASK) +#define CR_READ_SET_MASK (R_CR_CSSON_MASK | R_CR_MSIRGSEL_MASK) +#define ICSCR_READ_ONLY_MASK (R_ICSCR_HSICAL_MASK | R_ICSCR_MSICAL_MASK) +#define CFGR_READ_ONLY_MASK (R_CFGR_SWS_MASK) +#define CIFR_READ_ONLY_MASK (R_CIFR_LSECSSF_MASK | \ + R_CIFR_CSSF_MASK | \ + R_CIFR_PLLSAI2RDYF_MASK | \ + R_CIFR_PLLSAI1RDYF_MASK | \ + R_CIFR_PLLRDYF_MASK | \ + R_CIFR_HSERDYF_MASK | \ + R_CIFR_HSIRDYF_MASK | \ + R_CIFR_MSIRDYF_MASK | \ + R_CIFR_LSERDYF_MASK | \ + R_CIFR_LSIRDYF_MASK) +#define CIFR_IRQ_MASK CIFR_READ_ONLY_MASK +#define APB2ENR_READ_SET_MASK (R_APB2ENR_FWEN_MASK) +#define BDCR_READ_ONLY_MASK (R_BDCR_LSECSSD_MASK | R_BDCR_LSERDY_MASK) +#define CSR_READ_ONLY_MASK (R_CSR_LPWRRSTF_MASK | \ + R_CSR_WWDGRSTF_MASK | \ + R_CSR_IWWGRSTF_MASK | \ + R_CSR_SFTRSTF_MASK | \ + R_CSR_BORRSTF_MASK | \ + R_CSR_PINRSTF_MASK | \ + R_CSR_OBLRSTF_MASK | \ + R_CSR_FWRSTF_MASK | \ + R_CSR_LSIRDY_MASK) + +#endif /* HW_STM32L4X5_RCC_INTERNALS_H */ diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c index d1786e0da1c..cb147050091 100644 --- a/hw/arm/stm32l4x5_soc.c +++ b/hw/arm/stm32l4x5_soc.c @@ -76,6 +76,8 @@ static const int exti_irq[NUM_EXTI_IRQ] = { -1, -1, -1, -1, /* PVM[1..4] OR gate 1 */ 78 /* LCD wakeup, Direct */ }; +#define RCC_BASE_ADDRESS 0x40021000 +#define RCC_IRQ 5 static const int exti_or_gates_out[NUM_EXTI_OR_GATES] = { 23, 40, 63, 1, @@ -107,6 +109,7 @@ static void stm32l4x5_soc_initfn(Object *obj) TYPE_OR_IRQ); } object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_STM32L4X5_SYSCFG); + object_initialize_child(obj, "rcc", &s->rcc, TYPE_STM32L4X5_RCC); s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0); s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0); @@ -244,6 +247,14 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp) qdev_get_gpio_in(DEVICE(&s->exti), i)); } + /* RCC device */ + busdev = SYS_BUS_DEVICE(&s->rcc); + if (!sysbus_realize(busdev, errp)) { + return; + } + sysbus_mmio_map(busdev, 0, RCC_BASE_ADDRESS); + sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, RCC_IRQ)); + /* APB1 BUS */ create_unimplemented_device("TIM2", 0x40000000, 0x400); create_unimplemented_device("TIM3", 0x40000400, 0x400); @@ -306,7 +317,6 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp) create_unimplemented_device("DMA1", 0x40020000, 0x400); create_unimplemented_device("DMA2", 0x40020400, 0x400); /* RESERVED: 0x40020800, 0x800 */ - create_unimplemented_device("RCC", 0x40021000, 0x400); /* RESERVED: 0x40021400, 0xC00 */ create_unimplemented_device("FLASH", 0x40022000, 0x400); /* RESERVED: 0x40022400, 0xC00 */ diff --git a/hw/misc/stm32l4x5_rcc.c b/hw/misc/stm32l4x5_rcc.c new file mode 100644 index 00000000000..269e50b85a0 --- /dev/null +++ b/hw/misc/stm32l4x5_rcc.c @@ -0,0 +1,446 @@ +/* + * STM32L4X5 RCC (Reset and clock control) + * + * Copyright (c) 2023 Arnaud Minier + * Copyright (c) 2023 Inès Varhol + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * The reference used is the STMicroElectronics RM0351 Reference manual + * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs. + * + * Inspired by the BCM2835 CPRMAN clock manager implementation by Luc Michel. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/timer.h" +#include "qapi/error.h" +#include "migration/vmstate.h" +#include "hw/misc/stm32l4x5_rcc.h" +#include "hw/misc/stm32l4x5_rcc_internals.h" +#include "hw/clock.h" +#include "hw/irq.h" +#include "hw/qdev-clock.h" +#include "hw/qdev-properties.h" +#include "hw/qdev-properties-system.h" +#include "trace.h" + +#define HSE_DEFAULT_FRQ 48000000ULL +#define HSI_FRQ 16000000ULL +#define MSI_DEFAULT_FRQ 4000000ULL +#define LSE_FRQ 32768ULL +#define LSI_FRQ 32000ULL + +static void rcc_update_irq(Stm32l4x5RccState *s) +{ + if (s->cifr & CIFR_IRQ_MASK) { + qemu_irq_raise(s->irq); + } else { + qemu_irq_lower(s->irq); + } +} + +static void stm32l4x5_rcc_reset_hold(Object *obj) +{ + Stm32l4x5RccState *s = STM32L4X5_RCC(obj); + s->cr = 0x00000063; + /* + * Factory-programmed calibration data + * From the reference manual: 0x10XX 00XX + * Value taken from a real card. + */ + s->icscr = 0x106E0082; + s->cfgr = 0x0; + s->pllcfgr = 0x00001000; + s->pllsai1cfgr = 0x00001000; + s->pllsai2cfgr = 0x00001000; + s->cier = 0x0; + s->cifr = 0x0; + s->ahb1rstr = 0x0; + s->ahb2rstr = 0x0; + s->ahb3rstr = 0x0; + s->apb1rstr1 = 0x0; + s->apb1rstr2 = 0x0; + s->apb2rstr = 0x0; + s->ahb1enr = 0x00000100; + s->ahb2enr = 0x0; + s->ahb3enr = 0x0; + s->apb1enr1 = 0x0; + s->apb1enr2 = 0x0; + s->apb2enr = 0x0; + s->ahb1smenr = 0x00011303; + s->ahb2smenr = 0x000532FF; + s->ahb3smenr = 0x00000101; + s->apb1smenr1 = 0xF2FECA3F; + s->apb1smenr2 = 0x00000025; + s->apb2smenr = 0x01677C01; + s->ccipr = 0x0; + s->bdcr = 0x0; + s->csr = 0x0C000600; +} + +static uint64_t stm32l4x5_rcc_read(void *opaque, hwaddr addr, + unsigned int size) +{ + Stm32l4x5RccState *s = opaque; + uint64_t retvalue = 0; + + switch (addr) { + case A_CR: + retvalue = s->cr; + break; + case A_ICSCR: + retvalue = s->icscr; + break; + case A_CFGR: + retvalue = s->cfgr; + break; + case A_PLLCFGR: + retvalue = s->pllcfgr; + break; + case A_PLLSAI1CFGR: + retvalue = s->pllsai1cfgr; + break; + case A_PLLSAI2CFGR: + retvalue = s->pllsai2cfgr; + break; + case A_CIER: + retvalue = s->cier; + break; + case A_CIFR: + retvalue = s->cifr; + break; + case A_CICR: + /* CICR is write only, return the reset value = 0 */ + break; + case A_AHB1RSTR: + retvalue = s->ahb1rstr; + break; + case A_AHB2RSTR: + retvalue = s->ahb2rstr; + break; + case A_AHB3RSTR: + retvalue = s->ahb3rstr; + break; + case A_APB1RSTR1: + retvalue = s->apb1rstr1; + break; + case A_APB1RSTR2: + retvalue = s->apb1rstr2; + break; + case A_APB2RSTR: + retvalue = s->apb2rstr; + break; + case A_AHB1ENR: + retvalue = s->ahb1enr; + break; + case A_AHB2ENR: + retvalue = s->ahb2enr; + break; + case A_AHB3ENR: + retvalue = s->ahb3enr; + break; + case A_APB1ENR1: + retvalue = s->apb1enr1; + break; + case A_APB1ENR2: + retvalue = s->apb1enr2; + break; + case A_APB2ENR: + retvalue = s->apb2enr; + break; + case A_AHB1SMENR: + retvalue = s->ahb1smenr; + break; + case A_AHB2SMENR: + retvalue = s->ahb2smenr; + break; + case A_AHB3SMENR: + retvalue = s->ahb3smenr; + break; + case A_APB1SMENR1: + retvalue = s->apb1smenr1; + break; + case A_APB1SMENR2: + retvalue = s->apb1smenr2; + break; + case A_APB2SMENR: + retvalue = s->apb2smenr; + break; + case A_CCIPR: + retvalue = s->ccipr; + break; + case A_BDCR: + retvalue = s->bdcr; + break; + case A_CSR: + retvalue = s->csr; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); + break; + } + + trace_stm32l4x5_rcc_read(addr, retvalue); + + return retvalue; +} + +static void stm32l4x5_rcc_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned int size) +{ + Stm32l4x5RccState *s = opaque; + const uint32_t value = val64; + + trace_stm32l4x5_rcc_write(addr, value); + + switch (addr) { + case A_CR: + s->cr = (s->cr & CR_READ_SET_MASK) | + (value & (CR_READ_SET_MASK | ~CR_READ_ONLY_MASK)); + break; + case A_ICSCR: + s->icscr = value & ~ICSCR_READ_ONLY_MASK; + break; + case A_CFGR: + s->cfgr = value & ~CFGR_READ_ONLY_MASK; + break; + case A_PLLCFGR: + s->pllcfgr = value; + break; + case A_PLLSAI1CFGR: + s->pllsai1cfgr = value; + break; + case A_PLLSAI2CFGR: + s->pllsai2cfgr = value; + break; + case A_CIER: + s->cier = value; + break; + case A_CIFR: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Write attempt into read-only register (CIFR) 0x%"PRIx32"\n", + __func__, value); + break; + case A_CICR: + /* Clear interrupt flags by writing a 1 to the CICR register */ + s->cifr &= ~value; + rcc_update_irq(s); + break; + /* Reset behaviors are not implemented */ + case A_AHB1RSTR: + s->ahb1rstr = value; + break; + case A_AHB2RSTR: + s->ahb2rstr = value; + break; + case A_AHB3RSTR: + s->ahb3rstr = value; + break; + case A_APB1RSTR1: + s->apb1rstr1 = value; + break; + case A_APB1RSTR2: + s->apb1rstr2 = value; + break; + case A_APB2RSTR: + s->apb2rstr = value; + break; + case A_AHB1ENR: + s->ahb1enr = value; + break; + case A_AHB2ENR: + s->ahb2enr = value; + break; + case A_AHB3ENR: + s->ahb3enr = value; + break; + case A_APB1ENR1: + s->apb1enr1 = value; + break; + case A_APB1ENR2: + s->apb1enr2 = value; + break; + case A_APB2ENR: + s->apb2enr = (s->apb2enr & APB2ENR_READ_SET_MASK) | value; + break; + /* Behaviors for Sleep and Stop modes are not implemented */ + case A_AHB1SMENR: + s->ahb1smenr = value; + break; + case A_AHB2SMENR: + s->ahb2smenr = value; + break; + case A_AHB3SMENR: + s->ahb3smenr = value; + break; + case A_APB1SMENR1: + s->apb1smenr1 = value; + break; + case A_APB1SMENR2: + s->apb1smenr2 = value; + break; + case A_APB2SMENR: + s->apb2smenr = value; + break; + case A_CCIPR: + s->ccipr = value; + break; + case A_BDCR: + s->bdcr = value & ~BDCR_READ_ONLY_MASK; + break; + case A_CSR: + s->csr = value & ~CSR_READ_ONLY_MASK; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); + } +} + +static const MemoryRegionOps stm32l4x5_rcc_ops = { + .read = stm32l4x5_rcc_read, + .write = stm32l4x5_rcc_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .max_access_size = 4, + .min_access_size = 4, + .unaligned = false + }, + .impl = { + .max_access_size = 4, + .min_access_size = 4, + .unaligned = false + }, +}; + +static const ClockPortInitArray stm32l4x5_rcc_clocks = { + QDEV_CLOCK_IN(Stm32l4x5RccState, hsi16_rc, NULL, 0), + QDEV_CLOCK_IN(Stm32l4x5RccState, msi_rc, NULL, 0), + QDEV_CLOCK_IN(Stm32l4x5RccState, hse, NULL, 0), + QDEV_CLOCK_IN(Stm32l4x5RccState, lsi_rc, NULL, 0), + QDEV_CLOCK_IN(Stm32l4x5RccState, lse_crystal, NULL, 0), + QDEV_CLOCK_IN(Stm32l4x5RccState, sai1_extclk, NULL, 0), + QDEV_CLOCK_IN(Stm32l4x5RccState, sai2_extclk, NULL, 0), + QDEV_CLOCK_END +}; + + +static void stm32l4x5_rcc_init(Object *obj) +{ + Stm32l4x5RccState *s = STM32L4X5_RCC(obj); + + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); + + memory_region_init_io(&s->mmio, obj, &stm32l4x5_rcc_ops, s, + TYPE_STM32L4X5_RCC, 0x400); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); + + qdev_init_clocks(DEVICE(s), stm32l4x5_rcc_clocks); + + s->gnd = clock_new(obj, "gnd"); +} + +static const VMStateDescription vmstate_stm32l4x5_rcc = { + .name = TYPE_STM32L4X5_RCC, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(cr, Stm32l4x5RccState), + VMSTATE_UINT32(icscr, Stm32l4x5RccState), + VMSTATE_UINT32(cfgr, Stm32l4x5RccState), + VMSTATE_UINT32(pllcfgr, Stm32l4x5RccState), + VMSTATE_UINT32(pllsai1cfgr, Stm32l4x5RccState), + VMSTATE_UINT32(pllsai2cfgr, Stm32l4x5RccState), + VMSTATE_UINT32(cier, Stm32l4x5RccState), + VMSTATE_UINT32(cifr, Stm32l4x5RccState), + VMSTATE_UINT32(ahb1rstr, Stm32l4x5RccState), + VMSTATE_UINT32(ahb2rstr, Stm32l4x5RccState), + VMSTATE_UINT32(ahb3rstr, Stm32l4x5RccState), + VMSTATE_UINT32(apb1rstr1, Stm32l4x5RccState), + VMSTATE_UINT32(apb1rstr2, Stm32l4x5RccState), + VMSTATE_UINT32(apb2rstr, Stm32l4x5RccState), + VMSTATE_UINT32(ahb1enr, Stm32l4x5RccState), + VMSTATE_UINT32(ahb2enr, Stm32l4x5RccState), + VMSTATE_UINT32(ahb3enr, Stm32l4x5RccState), + VMSTATE_UINT32(apb1enr1, Stm32l4x5RccState), + VMSTATE_UINT32(apb1enr2, Stm32l4x5RccState), + VMSTATE_UINT32(apb2enr, Stm32l4x5RccState), + VMSTATE_UINT32(ahb1smenr, Stm32l4x5RccState), + VMSTATE_UINT32(ahb2smenr, Stm32l4x5RccState), + VMSTATE_UINT32(ahb3smenr, Stm32l4x5RccState), + VMSTATE_UINT32(apb1smenr1, Stm32l4x5RccState), + VMSTATE_UINT32(apb1smenr2, Stm32l4x5RccState), + VMSTATE_UINT32(apb2smenr, Stm32l4x5RccState), + VMSTATE_UINT32(ccipr, Stm32l4x5RccState), + VMSTATE_UINT32(bdcr, Stm32l4x5RccState), + VMSTATE_UINT32(csr, Stm32l4x5RccState), + VMSTATE_CLOCK(hsi16_rc, Stm32l4x5RccState), + VMSTATE_CLOCK(msi_rc, Stm32l4x5RccState), + VMSTATE_CLOCK(hse, Stm32l4x5RccState), + VMSTATE_CLOCK(lsi_rc, Stm32l4x5RccState), + VMSTATE_CLOCK(lse_crystal, Stm32l4x5RccState), + VMSTATE_CLOCK(sai1_extclk, Stm32l4x5RccState), + VMSTATE_CLOCK(sai2_extclk, Stm32l4x5RccState), + VMSTATE_END_OF_LIST() + } +}; + + +static void stm32l4x5_rcc_realize(DeviceState *dev, Error **errp) +{ + Stm32l4x5RccState *s = STM32L4X5_RCC(dev); + + if (s->hse_frequency < 4000000ULL || + s->hse_frequency > 48000000ULL) { + error_setg(errp, + "HSE frequency is outside of the allowed [4-48]Mhz range: %" PRIx64 "", + s->hse_frequency); + return; + } + + clock_update_hz(s->msi_rc, MSI_DEFAULT_FRQ); + clock_update_hz(s->sai1_extclk, s->sai1_extclk_frequency); + clock_update_hz(s->sai2_extclk, s->sai2_extclk_frequency); + clock_update(s->gnd, 0); +} + +static Property stm32l4x5_rcc_properties[] = { + DEFINE_PROP_UINT64("hse_frequency", Stm32l4x5RccState, + hse_frequency, HSE_DEFAULT_FRQ), + DEFINE_PROP_UINT64("sai1_extclk_frequency", Stm32l4x5RccState, + sai1_extclk_frequency, 0), + DEFINE_PROP_UINT64("sai2_extclk_frequency", Stm32l4x5RccState, + sai2_extclk_frequency, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void stm32l4x5_rcc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); + + + rc->phases.hold = stm32l4x5_rcc_reset_hold; + device_class_set_props(dc, stm32l4x5_rcc_properties); + dc->realize = stm32l4x5_rcc_realize; + dc->vmsd = &vmstate_stm32l4x5_rcc; +} + +static const TypeInfo stm32l4x5_rcc_types[] = { + { + .name = TYPE_STM32L4X5_RCC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Stm32l4x5RccState), + .instance_init = stm32l4x5_rcc_init, + .class_init = stm32l4x5_rcc_class_init, + } +}; + +DEFINE_TYPES(stm32l4x5_rcc_types) diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 3c157376844..d58d820788c 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -475,6 +475,7 @@ config STM32L4X5_SOC select OR_IRQ select STM32L4X5_SYSCFG select STM32L4X5_EXTI + select STM32L4X5_RCC config XLNX_ZYNQMP_ARM bool diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 83ad849b62e..1e08785b832 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -97,6 +97,9 @@ config STM32L4X5_EXTI config STM32L4X5_SYSCFG bool +config STM32L4X5_RCC + bool + config MIPS_ITU bool diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 746686835b0..265b2c26274 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -113,6 +113,7 @@ system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg. system_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c')) system_ss.add(when: 'CONFIG_STM32L4X5_EXTI', if_true: files('stm32l4x5_exti.c')) system_ss.add(when: 'CONFIG_STM32L4X5_SYSCFG', if_true: files('stm32l4x5_syscfg.c')) +system_ss.add(when: 'CONFIG_STM32L4X5_RCC', if_true: files('stm32l4x5_rcc.c')) system_ss.add(when: 'CONFIG_MPS2_FPGAIO', if_true: files('mps2-fpgaio.c')) system_ss.add(when: 'CONFIG_MPS2_SCC', if_true: files('mps2-scc.c')) diff --git a/hw/misc/trace-events b/hw/misc/trace-events index 5f5bc922223..38169ccbc10 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -174,6 +174,10 @@ stm32l4x5_exti_set_irq(int irq, int level) "Set EXTI: %d to %d" stm32l4x5_exti_read(uint64_t addr, uint64_t data) "reg read: addr: 0x%" PRIx64 " val: 0x%" PRIx64 "" stm32l4x5_exti_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 "" +# stm32l4x5_rcc.c +stm32l4x5_rcc_read(uint64_t addr, uint32_t data) "RCC: Read <0x%" PRIx64 "> -> 0x%" PRIx32 +stm32l4x5_rcc_write(uint64_t addr, uint32_t data) "RCC: Write <0x%" PRIx64 "> <- 0x%" PRIx32 + # tz-mpc.c tz_mpc_reg_read(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs read: offset 0x%x data 0x%" PRIx64 " size %u" tz_mpc_reg_write(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs write: offset 0x%x data 0x%" PRIx64 " size %u" From patchwork Tue Mar 5 13:52:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582462 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 BD406C54E41 for ; Tue, 5 Mar 2024 13:53:42 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVEO-00014P-J0; Tue, 05 Mar 2024 08:53:22 -0500 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 1rhVDu-0000w7-U4 for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:51 -0500 Received: from mail-wr1-x431.google.com ([2a00:1450:4864:20::431]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDn-0005xW-GH for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:50 -0500 Received: by mail-wr1-x431.google.com with SMTP id ffacd0b85a97d-33dd2f0a0c4so3289958f8f.0 for ; Tue, 05 Mar 2024 05:52:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646762; x=1710251562; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=vTSqwIO9P4ISrMhGaC6cCKlCKl6nQ7JcgEadIqESrFU=; b=ON0OOAKpxB0n1OzgQCPrefU+lzr6hTDcyEo2YAvJOUf6XUhBqzme20JkRlwBBHyE22 XYVZ8b7fDZvm2twIUfZc63yMMFUJ3Yr1XqQge/AuETvYKEsKPHl3AKlupwqblhsiV6aN Kbs8V2NlbtaaoSpg2x8jL5TeFtkM2zZdzMCuvUA/ravxU1gifzSE/TY+4AQEBgITl8u0 AsZZDLa7NAaVcI3ZNWgkNF+ENDI4EYOBv/K7fEw9C7NqhRaJhDv5G4q/MzGDikqoAje0 6N+KMj909B0AvcufHGmc9aYYG9Fm7i+BvuHEIRI9hozcl3zhRqKkE3phAAmjZJGCM70T DUNg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646762; x=1710251562; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vTSqwIO9P4ISrMhGaC6cCKlCKl6nQ7JcgEadIqESrFU=; b=l3RxmpDSiuqg4nbOp4ns5BeIVI+35A5Vdd5YKwcNknjREJ0Gz36IraGv05OwiJPnYr 4OUlxIhE9uWsgHLwAbbPS5CfF599f4nWFbiYZI5zGDH7nNXl+uPmHAoFS48nnV9ezFV/ RN11QSgIpra8VoTrDoLdeEmZ1wOjogFsmFvdO/k5VK28JLj/w43d6QfEO73BaLDofB9W +Ai4Cv6l9IE2oZ8ULC/ODTcCS0TLvbXiX+DLzy/1Uo2hOGCTmN28Hsv8uSc1i45j/H3B chDdzBzEgBtWMnwuCkBVW9TR5N+MRRp/z3DOEUlGcR+9xx5H6BC9v4dhzcPfqnkcBF4M 0R1A== X-Gm-Message-State: AOJu0YzDqRMFmHB+nDKmAFzPyEEYswMf/zrJUfqSifEmi7lpyyC/h1Lg 2jynVdO3KKyCK3CeJ6thzJF5Ex86Rzl4kze5d0tmyH1G2Tg0QhG1y05s341YhqcEyE0rLXuyCEF 6 X-Google-Smtp-Source: AGHT+IGQ6CyPIkO4GZURHS1FgdOYp6oBenfPXkTB7YqYqtiyNIaoz8pWVXqbSmtsOIGfBfOkzJ2Szw== X-Received: by 2002:a5d:624e:0:b0:33d:87ed:626 with SMTP id m14-20020a5d624e000000b0033d87ed0626mr7750596wrv.58.1709646762006; Tue, 05 Mar 2024 05:52:42 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.41 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:41 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 06/20] hw/misc/stm32l4x5_rcc: Add an internal clock multiplexer object Date: Tue, 5 Mar 2024 13:52:23 +0000 Message-Id: <20240305135237.3111642-7-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::431; envelope-from=peter.maydell@linaro.org; helo=mail-wr1-x431.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Arnaud Minier This object is used to represent every multiplexer in the clock tree as well as every clock output, every presecaler, frequency multiplier, etc. This allows to use a generic approach for every component of the clock tree (except the PLLs). The migration handling is based on hw/misc/zynq_sclr.c. Three phase reset will be handled in a later commit. Signed-off-by: Arnaud Minier Signed-off-by: Inès Varhol Acked-by: Alistair Francis Message-id: 20240303140643.81957-3-arnaud.minier@telecom-paris.fr Signed-off-by: Peter Maydell Reviewed-by: Peter Maydell --- include/hw/misc/stm32l4x5_rcc.h | 119 ++++++++++++++++ include/hw/misc/stm32l4x5_rcc_internals.h | 29 ++++ hw/misc/stm32l4x5_rcc.c | 160 ++++++++++++++++++++++ hw/misc/trace-events | 5 + 4 files changed, 313 insertions(+) diff --git a/include/hw/misc/stm32l4x5_rcc.h b/include/hw/misc/stm32l4x5_rcc.h index 5157e966352..6719be9fbee 100644 --- a/include/hw/misc/stm32l4x5_rcc.h +++ b/include/hw/misc/stm32l4x5_rcc.h @@ -26,6 +26,122 @@ OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5RccState, STM32L4X5_RCC) /* In the Stm32l4x5 clock tree, mux have at most 7 sources */ #define RCC_NUM_CLOCK_MUX_SRC 7 +/* NB: Prescaler are assimilated to mux with one source and one output */ +typedef enum RccClockMux { + /* Internal muxes that arent't exposed publicly to other peripherals */ + RCC_CLOCK_MUX_SYSCLK, + RCC_CLOCK_MUX_PLL_INPUT, + RCC_CLOCK_MUX_HCLK, + RCC_CLOCK_MUX_PCLK1, + RCC_CLOCK_MUX_PCLK2, + RCC_CLOCK_MUX_HSE_OVER_32, + RCC_CLOCK_MUX_LCD_AND_RTC_COMMON, + + /* Muxes with a publicly available output */ + RCC_CLOCK_MUX_CORTEX_REFCLK, + RCC_CLOCK_MUX_USART1, + RCC_CLOCK_MUX_USART2, + RCC_CLOCK_MUX_USART3, + RCC_CLOCK_MUX_UART4, + RCC_CLOCK_MUX_UART5, + RCC_CLOCK_MUX_LPUART1, + RCC_CLOCK_MUX_I2C1, + RCC_CLOCK_MUX_I2C2, + RCC_CLOCK_MUX_I2C3, + RCC_CLOCK_MUX_LPTIM1, + RCC_CLOCK_MUX_LPTIM2, + RCC_CLOCK_MUX_SWPMI1, + RCC_CLOCK_MUX_MCO, + RCC_CLOCK_MUX_LSCO, + RCC_CLOCK_MUX_DFSDM1, + RCC_CLOCK_MUX_ADC, + RCC_CLOCK_MUX_CLK48, + RCC_CLOCK_MUX_SAI1, + RCC_CLOCK_MUX_SAI2, + + /* + * Mux that have only one input and one output assigned to as peripheral. + * They could be direct lines but it is simpler + * to use the same logic for all outputs. + */ + /* - AHB1 */ + RCC_CLOCK_MUX_TSC, + RCC_CLOCK_MUX_CRC, + RCC_CLOCK_MUX_FLASH, + RCC_CLOCK_MUX_DMA2, + RCC_CLOCK_MUX_DMA1, + + /* - AHB2 */ + RCC_CLOCK_MUX_RNG, + RCC_CLOCK_MUX_AES, + RCC_CLOCK_MUX_OTGFS, + RCC_CLOCK_MUX_GPIOA, + RCC_CLOCK_MUX_GPIOB, + RCC_CLOCK_MUX_GPIOC, + RCC_CLOCK_MUX_GPIOD, + RCC_CLOCK_MUX_GPIOE, + RCC_CLOCK_MUX_GPIOF, + RCC_CLOCK_MUX_GPIOG, + RCC_CLOCK_MUX_GPIOH, + + /* - AHB3 */ + RCC_CLOCK_MUX_QSPI, + RCC_CLOCK_MUX_FMC, + + /* - APB1 */ + RCC_CLOCK_MUX_OPAMP, + RCC_CLOCK_MUX_DAC1, + RCC_CLOCK_MUX_PWR, + RCC_CLOCK_MUX_CAN1, + RCC_CLOCK_MUX_SPI3, + RCC_CLOCK_MUX_SPI2, + RCC_CLOCK_MUX_WWDG, + RCC_CLOCK_MUX_LCD, + RCC_CLOCK_MUX_TIM7, + RCC_CLOCK_MUX_TIM6, + RCC_CLOCK_MUX_TIM5, + RCC_CLOCK_MUX_TIM4, + RCC_CLOCK_MUX_TIM3, + RCC_CLOCK_MUX_TIM2, + + /* - APB2 */ + RCC_CLOCK_MUX_TIM17, + RCC_CLOCK_MUX_TIM16, + RCC_CLOCK_MUX_TIM15, + RCC_CLOCK_MUX_TIM8, + RCC_CLOCK_MUX_SPI1, + RCC_CLOCK_MUX_TIM1, + RCC_CLOCK_MUX_SDMMC1, + RCC_CLOCK_MUX_FW, + RCC_CLOCK_MUX_SYSCFG, + + /* - BDCR */ + RCC_CLOCK_MUX_RTC, + + /* - OTHER */ + RCC_CLOCK_MUX_CORTEX_FCLK, + + RCC_NUM_CLOCK_MUX +} RccClockMux; + +typedef struct RccClockMuxState { + DeviceState parent_obj; + + RccClockMux id; + Clock *srcs[RCC_NUM_CLOCK_MUX_SRC]; + Clock *out; + bool enabled; + uint32_t src; + uint32_t multiplier; + uint32_t divider; + + /* + * Used by clock srcs update callback to retrieve both the clock and the + * source number. + */ + struct RccClockMuxState *backref[RCC_NUM_CLOCK_MUX_SRC]; +} RccClockMuxState; + struct Stm32l4x5RccState { SysBusDevice parent_obj; @@ -71,6 +187,9 @@ struct Stm32l4x5RccState { Clock *sai1_extclk; Clock *sai2_extclk; + /* Muxes ~= outputs */ + RccClockMuxState clock_muxes[RCC_NUM_CLOCK_MUX]; + qemu_irq irq; uint64_t hse_frequency; uint64_t sai1_extclk_frequency; diff --git a/include/hw/misc/stm32l4x5_rcc_internals.h b/include/hw/misc/stm32l4x5_rcc_internals.h index 331ea30db57..4aa836848b4 100644 --- a/include/hw/misc/stm32l4x5_rcc_internals.h +++ b/include/hw/misc/stm32l4x5_rcc_internals.h @@ -21,6 +21,8 @@ #include "hw/registerfields.h" #include "hw/misc/stm32l4x5_rcc.h" +#define TYPE_RCC_CLOCK_MUX "stm32l4x5-rcc-clock-mux" +OBJECT_DECLARE_SIMPLE_TYPE(RccClockMuxState, RCC_CLOCK_MUX) /* Register map */ REG32(CR, 0x00) @@ -283,4 +285,31 @@ REG32(CSR, 0x94) R_CSR_FWRSTF_MASK | \ R_CSR_LSIRDY_MASK) +typedef enum RccClockMuxSource { + RCC_CLOCK_MUX_SRC_GND = 0, + RCC_CLOCK_MUX_SRC_HSI, + RCC_CLOCK_MUX_SRC_HSE, + RCC_CLOCK_MUX_SRC_MSI, + RCC_CLOCK_MUX_SRC_LSI, + RCC_CLOCK_MUX_SRC_LSE, + RCC_CLOCK_MUX_SRC_SAI1_EXTCLK, + RCC_CLOCK_MUX_SRC_SAI2_EXTCLK, + RCC_CLOCK_MUX_SRC_PLL, + RCC_CLOCK_MUX_SRC_PLLSAI1, + RCC_CLOCK_MUX_SRC_PLLSAI2, + RCC_CLOCK_MUX_SRC_PLLSAI3, + RCC_CLOCK_MUX_SRC_PLL48M1, + RCC_CLOCK_MUX_SRC_PLL48M2, + RCC_CLOCK_MUX_SRC_PLLADC1, + RCC_CLOCK_MUX_SRC_PLLADC2, + RCC_CLOCK_MUX_SRC_SYSCLK, + RCC_CLOCK_MUX_SRC_HCLK, + RCC_CLOCK_MUX_SRC_PCLK1, + RCC_CLOCK_MUX_SRC_PCLK2, + RCC_CLOCK_MUX_SRC_HSE_OVER_32, + RCC_CLOCK_MUX_SRC_LCD_AND_RTC_COMMON, + + RCC_CLOCK_MUX_SRC_NUMBER, +} RccClockMuxSource; + #endif /* HW_STM32L4X5_RCC_INTERNALS_H */ diff --git a/hw/misc/stm32l4x5_rcc.c b/hw/misc/stm32l4x5_rcc.c index 269e50b85a0..ace4083e837 100644 --- a/hw/misc/stm32l4x5_rcc.c +++ b/hw/misc/stm32l4x5_rcc.c @@ -36,6 +36,134 @@ #define LSE_FRQ 32768ULL #define LSI_FRQ 32000ULL +static void clock_mux_update(RccClockMuxState *mux) +{ + uint64_t src_freq; + Clock *current_source = mux->srcs[mux->src]; + uint32_t freq_multiplier = 0; + /* + * To avoid rounding errors, we use the clock period instead of the + * frequency. + * This means that the multiplier of the mux becomes the divider of + * the clock and the divider of the mux becomes the multiplier of the + * clock. + */ + if (mux->enabled && mux->divider) { + freq_multiplier = mux->divider; + } + + clock_set_mul_div(mux->out, freq_multiplier, mux->multiplier); + clock_update(mux->out, clock_get(current_source)); + + src_freq = clock_get_hz(current_source); + /* TODO: can we simply detect if the config changed so that we reduce log spam ? */ + trace_stm32l4x5_rcc_mux_update(mux->id, mux->src, src_freq, + mux->multiplier, mux->divider); +} + +static void clock_mux_src_update(void *opaque, ClockEvent event) +{ + RccClockMuxState **backref = opaque; + RccClockMuxState *s = *backref; + /* + * The backref value is equal to: + * s->backref + (sizeof(RccClockMuxState *) * update_src). + * By subtracting we can get back the index of the updated clock. + */ + const uint32_t update_src = backref - s->backref; + /* Only update if the clock that was updated is the current source */ + if (update_src == s->src) { + clock_mux_update(s); + } +} + +static void clock_mux_init(Object *obj) +{ + RccClockMuxState *s = RCC_CLOCK_MUX(obj); + size_t i; + + for (i = 0; i < RCC_NUM_CLOCK_MUX_SRC; i++) { + char *name = g_strdup_printf("srcs[%zu]", i); + s->backref[i] = s; + s->srcs[i] = qdev_init_clock_in(DEVICE(s), name, + clock_mux_src_update, + &s->backref[i], + ClockUpdate); + g_free(name); + } + + s->out = qdev_init_clock_out(DEVICE(s), "out"); +} + +static void clock_mux_reset_hold(Object *obj) +{ } + +static const VMStateDescription clock_mux_vmstate = { + .name = TYPE_RCC_CLOCK_MUX, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(id, RccClockMuxState), + VMSTATE_ARRAY_CLOCK(srcs, RccClockMuxState, + RCC_NUM_CLOCK_MUX_SRC), + VMSTATE_BOOL(enabled, RccClockMuxState), + VMSTATE_UINT32(src, RccClockMuxState), + VMSTATE_UINT32(multiplier, RccClockMuxState), + VMSTATE_UINT32(divider, RccClockMuxState), + VMSTATE_END_OF_LIST() + } +}; + +static void clock_mux_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); + + rc->phases.hold = clock_mux_reset_hold; + dc->vmsd = &clock_mux_vmstate; +} + +static void clock_mux_set_enable(RccClockMuxState *mux, bool enabled) +{ + if (mux->enabled == enabled) { + return; + } + + if (enabled) { + trace_stm32l4x5_rcc_mux_enable(mux->id); + } else { + trace_stm32l4x5_rcc_mux_disable(mux->id); + } + + mux->enabled = enabled; + clock_mux_update(mux); +} + +static void clock_mux_set_factor(RccClockMuxState *mux, + uint32_t multiplier, uint32_t divider) +{ + if (mux->multiplier == multiplier && mux->divider == divider) { + return; + } + trace_stm32l4x5_rcc_mux_set_factor(mux->id, + mux->multiplier, multiplier, mux->divider, divider); + + mux->multiplier = multiplier; + mux->divider = divider; + clock_mux_update(mux); +} + +static void clock_mux_set_source(RccClockMuxState *mux, RccClockMuxSource src) +{ + if (mux->src == src) { + return; + } + + trace_stm32l4x5_rcc_mux_set_src(mux->id, mux->src, src); + mux->src = src; + clock_mux_update(mux); +} + static void rcc_update_irq(Stm32l4x5RccState *s) { if (s->cifr & CIFR_IRQ_MASK) { @@ -335,6 +463,7 @@ static const ClockPortInitArray stm32l4x5_rcc_clocks = { static void stm32l4x5_rcc_init(Object *obj) { Stm32l4x5RccState *s = STM32L4X5_RCC(obj); + size_t i; sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); @@ -344,6 +473,14 @@ static void stm32l4x5_rcc_init(Object *obj) qdev_init_clocks(DEVICE(s), stm32l4x5_rcc_clocks); + for (i = 0; i < RCC_NUM_CLOCK_MUX; i++) { + + object_initialize_child(obj, "clock[*]", + &s->clock_muxes[i], + TYPE_RCC_CLOCK_MUX); + + } + s->gnd = clock_new(obj, "gnd"); } @@ -396,6 +533,7 @@ static const VMStateDescription vmstate_stm32l4x5_rcc = { static void stm32l4x5_rcc_realize(DeviceState *dev, Error **errp) { Stm32l4x5RccState *s = STM32L4X5_RCC(dev); + size_t i; if (s->hse_frequency < 4000000ULL || s->hse_frequency > 48000000ULL) { @@ -405,10 +543,26 @@ static void stm32l4x5_rcc_realize(DeviceState *dev, Error **errp) return; } + for (i = 0; i < RCC_NUM_CLOCK_MUX; i++) { + RccClockMuxState *clock_mux = &s->clock_muxes[i]; + + if (!qdev_realize(DEVICE(clock_mux), NULL, errp)) { + return; + } + } + clock_update_hz(s->msi_rc, MSI_DEFAULT_FRQ); clock_update_hz(s->sai1_extclk, s->sai1_extclk_frequency); clock_update_hz(s->sai2_extclk, s->sai2_extclk_frequency); clock_update(s->gnd, 0); + + /* + * Dummy values to make compilation pass. + * Removed in later commits. + */ + clock_mux_set_source(&s->clock_muxes[0], RCC_CLOCK_MUX_SRC_GND); + clock_mux_set_enable(&s->clock_muxes[0], true); + clock_mux_set_factor(&s->clock_muxes[0], 1, 1); } static Property stm32l4x5_rcc_properties[] = { @@ -440,6 +594,12 @@ static const TypeInfo stm32l4x5_rcc_types[] = { .instance_size = sizeof(Stm32l4x5RccState), .instance_init = stm32l4x5_rcc_init, .class_init = stm32l4x5_rcc_class_init, + }, { + .name = TYPE_RCC_CLOCK_MUX, + .parent = TYPE_DEVICE, + .instance_size = sizeof(RccClockMuxState), + .instance_init = clock_mux_init, + .class_init = clock_mux_class_init, } }; diff --git a/hw/misc/trace-events b/hw/misc/trace-events index 38169ccbc10..4b97641475b 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -177,6 +177,11 @@ stm32l4x5_exti_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 # stm32l4x5_rcc.c stm32l4x5_rcc_read(uint64_t addr, uint32_t data) "RCC: Read <0x%" PRIx64 "> -> 0x%" PRIx32 stm32l4x5_rcc_write(uint64_t addr, uint32_t data) "RCC: Write <0x%" PRIx64 "> <- 0x%" PRIx32 +stm32l4x5_rcc_mux_enable(uint32_t mux_id) "RCC: Mux %d enabled" +stm32l4x5_rcc_mux_disable(uint32_t mux_id) "RCC: Mux %d disabled" +stm32l4x5_rcc_mux_set_factor(uint32_t mux_id, uint32_t old_multiplier, uint32_t new_multiplier, uint32_t old_divider, uint32_t new_divider) "RCC: Mux %d factor changed: multiplier (%u -> %u), divider (%u -> %u)" +stm32l4x5_rcc_mux_set_src(uint32_t mux_id, uint32_t old_src, uint32_t new_src) "RCC: Mux %d source changed: from %u to %u" +stm32l4x5_rcc_mux_update(uint32_t mux_id, uint32_t src, uint64_t src_freq, uint32_t multiplier, uint32_t divider) "RCC: Mux %d src %d update: src_freq %" PRIu64 " multiplier %" PRIu32 " divider %" PRIu32 # tz-mpc.c tz_mpc_reg_read(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs read: offset 0x%x data 0x%" PRIx64 " size %u" From patchwork Tue Mar 5 13:52:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582467 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 18AB3C54E41 for ; Tue, 5 Mar 2024 13:54:11 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVEo-0001V2-LV; Tue, 05 Mar 2024 08:53:46 -0500 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 1rhVDv-0000wD-4s for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:56 -0500 Received: from mail-wr1-x42c.google.com ([2a00:1450:4864:20::42c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDo-0005xd-6k for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:50 -0500 Received: by mail-wr1-x42c.google.com with SMTP id ffacd0b85a97d-33e1878e357so2773883f8f.3 for ; Tue, 05 Mar 2024 05:52:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646762; x=1710251562; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=dpO++rSHH7rGO28AplCu9nZCf5+X/352HOhoAKdjtuM=; b=q3HMeF3SLTKlGrMa/3LfvMl6GoJ/IrvE6pyFVlgvMih16sVroOz4R3dF+KCyU9xcBN vFHT02P6am0shzyQpDQpDifhLpoB54xikbUX29GfDquD3ZWM0H3EuJrZ3BuomReszrRn X1sQnlWfoCPKMoCu7UTCi0MsGTjrLRhK3q1ArYhhSGXqFtuV412esUq4NrRYA7ZUASA0 OP+QLS8eay+Vc+eMtMQobpx6LdFAoWZDrSkP89iwE/SiaVgA1arFq+CklhuSLBgFf9le qzG2YKmN/XaRcX3177a2xMfd+g1jwFLFmcH0iuQXS4e9J2E+PUbBEd/Lr9dJQ/8bf/ZY 4Z/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646762; x=1710251562; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=dpO++rSHH7rGO28AplCu9nZCf5+X/352HOhoAKdjtuM=; b=pY67WKfKVxuf5zli5CawNq23DB5kbKA6pnVrdqbe+T6UM+e5O5eQKU49Z0kueSwpsi eiUqcO9CMuNdvXijgez9vyAUx4TfGwsvCls0Yr0MyPZjdfiBdcPvdojhSMa7nA8zR3LM HymdnYp1cGiOMAY8jCsM7T2Aja9T1PmGf5wUh/tUP/IwmIV520s/ibgHnHYo9EHrgqPv aHAJFCMsQWaupujeBdRbjQBxQiI1XPZq8TdwCGIh63/rL2zSuHx1IUiJz7bPZTfJjIX0 vfOMBVTHj580e9kXei9CbpKlgJNxWqNKwAYay/fKc29Cn361L3tTspXdVXa7Jc44s77P Hfug== X-Gm-Message-State: AOJu0YyaAApiQLpmepGCTkw8MNIcpgFCx6gS5cFdX6anfc8n/5z8vyi1 0/q1j3W8QaYV5QPPeTW3cSrx7qITvFv/GZdu6mYs9VcTE+bmvS3LVvWP786kf9mIKFIO6HfI1Qw b X-Google-Smtp-Source: AGHT+IE0GdRVrS1xqqvUPxWignENzOo7m1hTdDz7M+BCJLYMiyB+FSAC/r33mYCUXdjdejUy/nCx9g== X-Received: by 2002:adf:e74a:0:b0:33d:3665:666f with SMTP id c10-20020adfe74a000000b0033d3665666fmr8444550wrn.44.1709646762552; Tue, 05 Mar 2024 05:52:42 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.42 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:42 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 07/20] hw/misc/stm32l4x5_rcc: Add an internal PLL Clock object Date: Tue, 5 Mar 2024 13:52:24 +0000 Message-Id: <20240305135237.3111642-8-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::42c; envelope-from=peter.maydell@linaro.org; helo=mail-wr1-x42c.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Arnaud Minier This object represents the PLLs and their channels. The PLLs allow for a more fine-grained control of the clocks frequency. The migration handling is based on hw/misc/zynq_sclr.c. Three phase reset will be handled in a later commit. Signed-off-by: Arnaud Minier Signed-off-by: Inès Varhol Message-id: 20240303140643.81957-4-arnaud.minier@telecom-paris.fr Signed-off-by: Peter Maydell Reviewed-by: Peter Maydell --- include/hw/misc/stm32l4x5_rcc.h | 40 +++++ include/hw/misc/stm32l4x5_rcc_internals.h | 22 +++ hw/misc/stm32l4x5_rcc.c | 176 ++++++++++++++++++++++ hw/misc/trace-events | 5 + 4 files changed, 243 insertions(+) diff --git a/include/hw/misc/stm32l4x5_rcc.h b/include/hw/misc/stm32l4x5_rcc.h index 6719be9fbee..0fbfba5c40b 100644 --- a/include/hw/misc/stm32l4x5_rcc.h +++ b/include/hw/misc/stm32l4x5_rcc.h @@ -26,6 +26,15 @@ OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5RccState, STM32L4X5_RCC) /* In the Stm32l4x5 clock tree, mux have at most 7 sources */ #define RCC_NUM_CLOCK_MUX_SRC 7 + +typedef enum PllCommonChannels { + RCC_PLL_COMMON_CHANNEL_P = 0, + RCC_PLL_COMMON_CHANNEL_Q = 1, + RCC_PLL_COMMON_CHANNEL_R = 2, + + RCC_NUM_CHANNEL_PLL_OUT = 3 +} PllCommonChannels; + /* NB: Prescaler are assimilated to mux with one source and one output */ typedef enum RccClockMux { /* Internal muxes that arent't exposed publicly to other peripherals */ @@ -124,6 +133,14 @@ typedef enum RccClockMux { RCC_NUM_CLOCK_MUX } RccClockMux; +typedef enum RccPll { + RCC_PLL_PLL, + RCC_PLL_PLLSAI1, + RCC_PLL_PLLSAI2, + + RCC_NUM_PLL +} RccPll; + typedef struct RccClockMuxState { DeviceState parent_obj; @@ -142,6 +159,26 @@ typedef struct RccClockMuxState { struct RccClockMuxState *backref[RCC_NUM_CLOCK_MUX_SRC]; } RccClockMuxState; +typedef struct RccPllState { + DeviceState parent_obj; + + RccPll id; + Clock *in; + uint32_t vco_multiplier; + Clock *channels[RCC_NUM_CHANNEL_PLL_OUT]; + /* Global pll enabled flag */ + bool enabled; + /* 'enabled' refers to the runtime configuration */ + bool channel_enabled[RCC_NUM_CHANNEL_PLL_OUT]; + /* + * 'exists' refers to the physical configuration + * It should only be set at pll initialization. + * e.g. pllsai2 doesn't have a Q output. + */ + bool channel_exists[RCC_NUM_CHANNEL_PLL_OUT]; + uint32_t channel_divider[RCC_NUM_CHANNEL_PLL_OUT]; +} RccPllState; + struct Stm32l4x5RccState { SysBusDevice parent_obj; @@ -187,6 +224,9 @@ struct Stm32l4x5RccState { Clock *sai1_extclk; Clock *sai2_extclk; + /* PLLs */ + RccPllState plls[RCC_NUM_PLL]; + /* Muxes ~= outputs */ RccClockMuxState clock_muxes[RCC_NUM_CLOCK_MUX]; diff --git a/include/hw/misc/stm32l4x5_rcc_internals.h b/include/hw/misc/stm32l4x5_rcc_internals.h index 4aa836848b4..a9da5e3be7d 100644 --- a/include/hw/misc/stm32l4x5_rcc_internals.h +++ b/include/hw/misc/stm32l4x5_rcc_internals.h @@ -22,7 +22,10 @@ #include "hw/misc/stm32l4x5_rcc.h" #define TYPE_RCC_CLOCK_MUX "stm32l4x5-rcc-clock-mux" +#define TYPE_RCC_PLL "stm32l4x5-rcc-pll" + OBJECT_DECLARE_SIMPLE_TYPE(RccClockMuxState, RCC_CLOCK_MUX) +OBJECT_DECLARE_SIMPLE_TYPE(RccPllState, RCC_PLL) /* Register map */ REG32(CR, 0x00) @@ -285,6 +288,25 @@ REG32(CSR, 0x94) R_CSR_FWRSTF_MASK | \ R_CSR_LSIRDY_MASK) +/* Pll Channels */ +enum PllChannels { + RCC_PLL_CHANNEL_PLLSAI3CLK = 0, + RCC_PLL_CHANNEL_PLL48M1CLK = 1, + RCC_PLL_CHANNEL_PLLCLK = 2, +}; + +enum PllSai1Channels { + RCC_PLLSAI1_CHANNEL_PLLSAI1CLK = 0, + RCC_PLLSAI1_CHANNEL_PLL48M2CLK = 1, + RCC_PLLSAI1_CHANNEL_PLLADC1CLK = 2, +}; + +enum PllSai2Channels { + RCC_PLLSAI2_CHANNEL_PLLSAI2CLK = 0, + /* No Q channel */ + RCC_PLLSAI2_CHANNEL_PLLADC2CLK = 2, +}; + typedef enum RccClockMuxSource { RCC_CLOCK_MUX_SRC_GND = 0, RCC_CLOCK_MUX_SRC_HSI, diff --git a/hw/misc/stm32l4x5_rcc.c b/hw/misc/stm32l4x5_rcc.c index ace4083e837..9a9ea6c4702 100644 --- a/hw/misc/stm32l4x5_rcc.c +++ b/hw/misc/stm32l4x5_rcc.c @@ -164,6 +164,157 @@ static void clock_mux_set_source(RccClockMuxState *mux, RccClockMuxSource src) clock_mux_update(mux); } +static void pll_update(RccPllState *pll) +{ + uint64_t vco_freq, old_channel_freq, channel_freq; + int i; + + /* The common PLLM factor is handled by the PLL mux */ + vco_freq = muldiv64(clock_get_hz(pll->in), pll->vco_multiplier, 1); + + for (i = 0; i < RCC_NUM_CHANNEL_PLL_OUT; i++) { + if (!pll->channel_exists[i]) { + continue; + } + + old_channel_freq = clock_get_hz(pll->channels[i]); + if (!pll->enabled || + !pll->channel_enabled[i] || + !pll->channel_divider[i]) { + channel_freq = 0; + } else { + channel_freq = muldiv64(vco_freq, + 1, + pll->channel_divider[i]); + } + + /* No change, early continue to avoid log spam and useless propagation */ + if (old_channel_freq == channel_freq) { + continue; + } + + clock_update_hz(pll->channels[i], channel_freq); + trace_stm32l4x5_rcc_pll_update(pll->id, i, vco_freq, + old_channel_freq, channel_freq); + } +} + +static void pll_src_update(void *opaque, ClockEvent event) +{ + RccPllState *s = opaque; + pll_update(s); +} + +static void pll_init(Object *obj) +{ + RccPllState *s = RCC_PLL(obj); + size_t i; + + s->in = qdev_init_clock_in(DEVICE(s), "in", + pll_src_update, s, ClockUpdate); + + const char *names[] = { + "out-p", "out-q", "out-r", + }; + + for (i = 0; i < RCC_NUM_CHANNEL_PLL_OUT; i++) { + s->channels[i] = qdev_init_clock_out(DEVICE(s), names[i]); + } +} + +static void pll_reset_hold(Object *obj) +{ } + +static const VMStateDescription pll_vmstate = { + .name = TYPE_RCC_PLL, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(id, RccPllState), + VMSTATE_CLOCK(in, RccPllState), + VMSTATE_ARRAY_CLOCK(channels, RccPllState, + RCC_NUM_CHANNEL_PLL_OUT), + VMSTATE_BOOL(enabled, RccPllState), + VMSTATE_UINT32(vco_multiplier, RccPllState), + VMSTATE_BOOL_ARRAY(channel_enabled, RccPllState, RCC_NUM_CHANNEL_PLL_OUT), + VMSTATE_BOOL_ARRAY(channel_exists, RccPllState, RCC_NUM_CHANNEL_PLL_OUT), + VMSTATE_UINT32_ARRAY(channel_divider, RccPllState, RCC_NUM_CHANNEL_PLL_OUT), + VMSTATE_END_OF_LIST() + } +}; + +static void pll_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); + + rc->phases.hold = pll_reset_hold; + dc->vmsd = &pll_vmstate; +} + +static void pll_set_vco_multiplier(RccPllState *pll, uint32_t vco_multiplier) +{ + if (pll->vco_multiplier == vco_multiplier) { + return; + } + + if (vco_multiplier < 8 || vco_multiplier > 86) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: VCO multiplier is out of bound (%u) for PLL %u\n", + __func__, vco_multiplier, pll->id); + return; + } + + trace_stm32l4x5_rcc_pll_set_vco_multiplier(pll->id, + pll->vco_multiplier, vco_multiplier); + + pll->vco_multiplier = vco_multiplier; + pll_update(pll); +} + +static void pll_set_enable(RccPllState *pll, bool enabled) +{ + if (pll->enabled == enabled) { + return; + } + + pll->enabled = enabled; + pll_update(pll); +} + +static void pll_set_channel_enable(RccPllState *pll, + PllCommonChannels channel, + bool enabled) +{ + if (pll->channel_enabled[channel] == enabled) { + return; + } + + if (enabled) { + trace_stm32l4x5_rcc_pll_channel_enable(pll->id, channel); + } else { + trace_stm32l4x5_rcc_pll_channel_disable(pll->id, channel); + } + + pll->channel_enabled[channel] = enabled; + pll_update(pll); +} + +static void pll_set_channel_divider(RccPllState *pll, + PllCommonChannels channel, + uint32_t divider) +{ + if (pll->channel_divider[channel] == divider) { + return; + } + + trace_stm32l4x5_rcc_pll_set_channel_divider(pll->id, + channel, pll->channel_divider[channel], divider); + + pll->channel_divider[channel] = divider; + pll_update(pll); +} + static void rcc_update_irq(Stm32l4x5RccState *s) { if (s->cifr & CIFR_IRQ_MASK) { @@ -473,6 +624,11 @@ static void stm32l4x5_rcc_init(Object *obj) qdev_init_clocks(DEVICE(s), stm32l4x5_rcc_clocks); + for (i = 0; i < RCC_NUM_PLL; i++) { + object_initialize_child(obj, "pll[*]", + &s->plls[i], TYPE_RCC_PLL); + } + for (i = 0; i < RCC_NUM_CLOCK_MUX; i++) { object_initialize_child(obj, "clock[*]", @@ -543,6 +699,16 @@ static void stm32l4x5_rcc_realize(DeviceState *dev, Error **errp) return; } + for (i = 0; i < RCC_NUM_PLL; i++) { + RccPllState *pll = &s->plls[i]; + + clock_set_source(pll->in, s->clock_muxes[RCC_CLOCK_MUX_PLL_INPUT].out); + + if (!qdev_realize(DEVICE(pll), NULL, errp)) { + return; + } + } + for (i = 0; i < RCC_NUM_CLOCK_MUX; i++) { RccClockMuxState *clock_mux = &s->clock_muxes[i]; @@ -563,6 +729,10 @@ static void stm32l4x5_rcc_realize(DeviceState *dev, Error **errp) clock_mux_set_source(&s->clock_muxes[0], RCC_CLOCK_MUX_SRC_GND); clock_mux_set_enable(&s->clock_muxes[0], true); clock_mux_set_factor(&s->clock_muxes[0], 1, 1); + pll_set_channel_divider(&s->plls[0], 0, 1); + pll_set_enable(&s->plls[0], true); + pll_set_channel_enable(&s->plls[0], 0, true); + pll_set_vco_multiplier(&s->plls[0], 1); } static Property stm32l4x5_rcc_properties[] = { @@ -600,6 +770,12 @@ static const TypeInfo stm32l4x5_rcc_types[] = { .instance_size = sizeof(RccClockMuxState), .instance_init = clock_mux_init, .class_init = clock_mux_class_init, + }, { + .name = TYPE_RCC_PLL, + .parent = TYPE_DEVICE, + .instance_size = sizeof(RccPllState), + .instance_init = pll_init, + .class_init = pll_class_init, } }; diff --git a/hw/misc/trace-events b/hw/misc/trace-events index 4b97641475b..7cab1d5cb50 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -182,6 +182,11 @@ stm32l4x5_rcc_mux_disable(uint32_t mux_id) "RCC: Mux %d disabled" stm32l4x5_rcc_mux_set_factor(uint32_t mux_id, uint32_t old_multiplier, uint32_t new_multiplier, uint32_t old_divider, uint32_t new_divider) "RCC: Mux %d factor changed: multiplier (%u -> %u), divider (%u -> %u)" stm32l4x5_rcc_mux_set_src(uint32_t mux_id, uint32_t old_src, uint32_t new_src) "RCC: Mux %d source changed: from %u to %u" stm32l4x5_rcc_mux_update(uint32_t mux_id, uint32_t src, uint64_t src_freq, uint32_t multiplier, uint32_t divider) "RCC: Mux %d src %d update: src_freq %" PRIu64 " multiplier %" PRIu32 " divider %" PRIu32 +stm32l4x5_rcc_pll_set_vco_multiplier(uint32_t pll_id, uint32_t old_multiplier, uint32_t new_multiplier) "RCC: PLL %u: vco_multiplier changed (%u -> %u)" +stm32l4x5_rcc_pll_channel_enable(uint32_t pll_id, uint32_t channel_id) "RCC: PLL %u, channel %u enabled" +stm32l4x5_rcc_pll_channel_disable(uint32_t pll_id, uint32_t channel_id) "RCC: PLL %u, channel %u disabled" +stm32l4x5_rcc_pll_set_channel_divider(uint32_t pll_id, uint32_t channel_id, uint32_t old_divider, uint32_t new_divider) "RCC: PLL %u, channel %u: divider changed (%u -> %u)" +stm32l4x5_rcc_pll_update(uint32_t pll_id, uint32_t channel_id, uint64_t vco_freq, uint64_t old_freq, uint64_t new_freq) "RCC: PLL %d channel %d update: vco_freq %" PRIu64 " old_freq %" PRIu64 " new_freq %" PRIu64 # tz-mpc.c tz_mpc_reg_read(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs read: offset 0x%x data 0x%" PRIx64 " size %u" From patchwork Tue Mar 5 13:52:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582464 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 4BDC6C54E41 for ; Tue, 5 Mar 2024 13:53:50 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVEd-0001Da-DR; Tue, 05 Mar 2024 08:53:37 -0500 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 1rhVDw-0000wW-4U for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:53:06 -0500 Received: from mail-wm1-x335.google.com ([2a00:1450:4864:20::335]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDo-0005xj-H5 for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:51 -0500 Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-412eddd165eso3687465e9.1 for ; Tue, 05 Mar 2024 05:52:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646763; x=1710251563; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=gMBLxtLg8vmsf4UwKbR23mOVuBgWsMOaKSlUcHfsDKo=; b=wfEjN5Jsq7J97yO4VXHJcaHlF+nE2afdw7KxaR/TaS3cBksDo7ihLY9z+jbhk+oD3p RUK1I6nP30nZKpbzSJEILp7YnssUHibKBrPzNFpv+Z4Bj8TL4eqUkVRDIqJNYzPYG/jZ Cadr5buz7R2BA0qki8DeTSjNn8Bd/gKacnCDem7rRIl5iqzv2wAmkeFXJCgt45iwiSns W5Ffs0/Kr6IbNmyDgHDb13MaDy+LRCgfNcQlz9gx6mCc2upnMEoCo7QyDV2Yu92RU77W dFQsnePt8PMT+T/jr/pRUySZktrCbLKP96ocLwv/mm+6bWXaviO+NLfKug1BEHOEFP8i kQVA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646763; x=1710251563; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=gMBLxtLg8vmsf4UwKbR23mOVuBgWsMOaKSlUcHfsDKo=; b=UJYiIPKMgPFg7edrAp5uuShuEBhTrZsU0gSsZLw5il2mKpAMoff5JEEhFozkdPzebc Z0AXwgjtxBn+YOCcSrfn8LKZUTiSXsHMFETAfQ7Opo6ekABCfEO4jPTgje+jfVmTwIrl ZVxWArYdLDOgNxFtUh0yvrFDWsm+GIyx3vGsruQKwSeHYth7TNJuGCdRakgbPgoh/p/X bxJx6j4eqeEdCI5pFZpMhCfVrRg6F0Wu2K6madKP4EVs38OxYteJcK698C0kGAwOmvty mFByrJgizYoooMUihLyFLrvpxLb9T5OjiZJcYW2fKnRRK57Oo9Y69sI3XRgmP71S07LZ 3aLw== X-Gm-Message-State: AOJu0YztXPnB1bVJRJRd08286hbdf9zos5P/DhNaDG9MDC7XJ11Pg2da r0pueIrFYsY4M0QE7qAnIR/mPYVlNxiJZBJsbq/KYu9P+2NF3tNsMMqNsfJXCYaSio5eor5qbvE W X-Google-Smtp-Source: AGHT+IGphrgq89+B7LP9rJ9fXgRQceF6zhJFKABo/evjdsHdhrNFibZdXg6vD8vqrG9dK2TtOJnFEg== X-Received: by 2002:a5d:60cb:0:b0:33d:d791:1164 with SMTP id x11-20020a5d60cb000000b0033dd7911164mr11186432wrt.8.1709646763020; Tue, 05 Mar 2024 05:52:43 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.42 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:42 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 08/20] hw/misc/stm32l4x5_rcc: Initialize PLLs and clock multiplexers Date: Tue, 5 Mar 2024 13:52:25 +0000 Message-Id: <20240305135237.3111642-9-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::335; envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x335.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Arnaud Minier Instantiate the whole clock tree and using the Clock multiplexers and the PLLs defined in the previous commits. This allows to statically define the clock tree and easily follow the clock signal from one end to another. Also handle three-phase reset now that we have defined a known base state for every object. (Reset handling based on hw/misc/zynq_sclr.c) Signed-off-by: Arnaud Minier Signed-off-by: Inès Varhol Message-id: 20240303140643.81957-5-arnaud.minier@telecom-paris.fr Signed-off-by: Peter Maydell Reviewed-by: Peter Maydell --- include/hw/misc/stm32l4x5_rcc_internals.h | 705 ++++++++++++++++++++++ hw/misc/stm32l4x5_rcc.c | 145 ++++- 2 files changed, 833 insertions(+), 17 deletions(-) diff --git a/include/hw/misc/stm32l4x5_rcc_internals.h b/include/hw/misc/stm32l4x5_rcc_internals.h index a9da5e3be7d..ff1c834f694 100644 --- a/include/hw/misc/stm32l4x5_rcc_internals.h +++ b/include/hw/misc/stm32l4x5_rcc_internals.h @@ -334,4 +334,709 @@ typedef enum RccClockMuxSource { RCC_CLOCK_MUX_SRC_NUMBER, } RccClockMuxSource; +/* PLL init info */ +typedef struct PllInitInfo { + const char *name; + + const char *channel_name[RCC_NUM_CHANNEL_PLL_OUT]; + bool channel_exists[RCC_NUM_CHANNEL_PLL_OUT]; + uint32_t default_channel_divider[RCC_NUM_CHANNEL_PLL_OUT]; + + RccClockMuxSource src_mapping[RCC_NUM_CLOCK_MUX_SRC]; +} PllInitInfo; + +static const PllInitInfo PLL_INIT_INFO[] = { + [RCC_PLL_PLL] = { + .name = "pll", + .channel_name = { + "pllsai3clk", + "pll48m1clk", + "pllclk" + }, + .channel_exists = { + true, true, true + }, + /* From PLLCFGR register documentation */ + .default_channel_divider = { + 7, 2, 2 + } + }, + [RCC_PLL_PLLSAI1] = { + .name = "pllsai1", + .channel_name = { + "pllsai1clk", + "pll48m2clk", + "plladc1clk" + }, + .channel_exists = { + true, true, true + }, + /* From PLLSAI1CFGR register documentation */ + .default_channel_divider = { + 7, 2, 2 + } + }, + [RCC_PLL_PLLSAI2] = { + .name = "pllsai2", + .channel_name = { + "pllsai2clk", + NULL, + "plladc2clk" + }, + .channel_exists = { + true, false, true + }, + /* From PLLSAI2CFGR register documentation */ + .default_channel_divider = { + 7, 0, 2 + } + } +}; + +static inline void set_pll_init_info(RccPllState *pll, + RccPll id) +{ + int i; + + pll->id = id; + pll->vco_multiplier = 1; + for (i = 0; i < RCC_NUM_CHANNEL_PLL_OUT; i++) { + pll->channel_enabled[i] = false; + pll->channel_exists[i] = PLL_INIT_INFO[id].channel_exists[i]; + pll->channel_divider[i] = PLL_INIT_INFO[id].default_channel_divider[i]; + } +} + +/* Clock mux init info */ +typedef struct ClockMuxInitInfo { + const char *name; + + uint32_t multiplier; + uint32_t divider; + bool enabled; + /* If this is true, the clock will not be exposed outside of the device */ + bool hidden; + + RccClockMuxSource src_mapping[RCC_NUM_CLOCK_MUX_SRC]; +} ClockMuxInitInfo; + +#define FILL_DEFAULT_FACTOR \ + .multiplier = 1, \ + .divider = 1 + +#define FILL_DEFAULT_INIT_ENABLED \ + FILL_DEFAULT_FACTOR, \ + .enabled = true + +#define FILL_DEFAULT_INIT_DISABLED \ + FILL_DEFAULT_FACTOR, \ + .enabled = false + + +static const ClockMuxInitInfo CLOCK_MUX_INIT_INFO[] = { + [RCC_CLOCK_MUX_SYSCLK] = { + .name = "sysclk", + /* Same mapping as: CFGR_SW */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_MSI, + RCC_CLOCK_MUX_SRC_HSI, + RCC_CLOCK_MUX_SRC_HSE, + RCC_CLOCK_MUX_SRC_PLL, + }, + .hidden = true, + FILL_DEFAULT_INIT_ENABLED, + }, + [RCC_CLOCK_MUX_PLL_INPUT] = { + .name = "pll-input", + /* Same mapping as: PLLCFGR_PLLSRC */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_MSI, + RCC_CLOCK_MUX_SRC_HSI, + RCC_CLOCK_MUX_SRC_HSE, + }, + .hidden = true, + FILL_DEFAULT_INIT_ENABLED, + }, + [RCC_CLOCK_MUX_HCLK] = { + .name = "hclk", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + .hidden = true, + FILL_DEFAULT_INIT_ENABLED, + }, + [RCC_CLOCK_MUX_PCLK1] = { + .name = "pclk1", + .src_mapping = { + RCC_CLOCK_MUX_SRC_HCLK, + }, + .hidden = true, + FILL_DEFAULT_INIT_ENABLED, + }, + [RCC_CLOCK_MUX_PCLK2] = { + .name = "pclk2", + .src_mapping = { + RCC_CLOCK_MUX_SRC_HCLK, + }, + .hidden = true, + FILL_DEFAULT_INIT_ENABLED, + }, + [RCC_CLOCK_MUX_HSE_OVER_32] = { + .name = "hse-divided-by-32", + .multiplier = 1, + .divider = 32, + .enabled = true, + .src_mapping = { + RCC_CLOCK_MUX_SRC_HSE, + }, + .hidden = true, + }, + [RCC_CLOCK_MUX_LCD_AND_RTC_COMMON] = { + .name = "lcd-and-rtc-common-mux", + /* Same mapping as: BDCR_RTCSEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_GND, + RCC_CLOCK_MUX_SRC_LSE, + RCC_CLOCK_MUX_SRC_LSI, + RCC_CLOCK_MUX_SRC_HSE_OVER_32, + }, + .hidden = true, + FILL_DEFAULT_INIT_ENABLED, + }, + /* From now on, muxes with a publicly available output */ + [RCC_CLOCK_MUX_CORTEX_REFCLK] = { + .name = "cortex-refclk", + .multiplier = 1, + /* REFCLK is always HCLK/8 */ + .divider = 8, + .enabled = true, + .src_mapping = { + RCC_CLOCK_MUX_SRC_HCLK, + } + }, + [RCC_CLOCK_MUX_USART1] = { + .name = "usart1", + /* Same mapping as: CCIPR_USART1SEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK2, + RCC_CLOCK_MUX_SRC_SYSCLK, + RCC_CLOCK_MUX_SRC_HSI, + RCC_CLOCK_MUX_SRC_LSE, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_USART2] = { + .name = "usart2", + /* Same mapping as: CCIPR_USART2SEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + RCC_CLOCK_MUX_SRC_SYSCLK, + RCC_CLOCK_MUX_SRC_HSI, + RCC_CLOCK_MUX_SRC_LSE, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_USART3] = { + .name = "usart3", + /* Same mapping as: CCIPR_USART3SEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + RCC_CLOCK_MUX_SRC_SYSCLK, + RCC_CLOCK_MUX_SRC_HSI, + RCC_CLOCK_MUX_SRC_LSE, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_UART4] = { + .name = "uart4", + /* Same mapping as: CCIPR_UART4SEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + RCC_CLOCK_MUX_SRC_SYSCLK, + RCC_CLOCK_MUX_SRC_HSI, + RCC_CLOCK_MUX_SRC_LSE, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_UART5] = { + .name = "uart5", + /* Same mapping as: CCIPR_UART5SEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + RCC_CLOCK_MUX_SRC_SYSCLK, + RCC_CLOCK_MUX_SRC_HSI, + RCC_CLOCK_MUX_SRC_LSE, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_LPUART1] = { + .name = "lpuart1", + /* Same mapping as: CCIPR_LPUART1SEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + RCC_CLOCK_MUX_SRC_SYSCLK, + RCC_CLOCK_MUX_SRC_HSI, + RCC_CLOCK_MUX_SRC_LSE, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_I2C1] = { + .name = "i2c1", + /* Same mapping as: CCIPR_I2C1SEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + RCC_CLOCK_MUX_SRC_SYSCLK, + RCC_CLOCK_MUX_SRC_HSI, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_I2C2] = { + .name = "i2c2", + /* Same mapping as: CCIPR_I2C2SEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + RCC_CLOCK_MUX_SRC_SYSCLK, + RCC_CLOCK_MUX_SRC_HSI, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_I2C3] = { + .name = "i2c3", + /* Same mapping as: CCIPR_I2C3SEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + RCC_CLOCK_MUX_SRC_SYSCLK, + RCC_CLOCK_MUX_SRC_HSI, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_LPTIM1] = { + .name = "lptim1", + /* Same mapping as: CCIPR_LPTIM1SEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + RCC_CLOCK_MUX_SRC_LSI, + RCC_CLOCK_MUX_SRC_HSI, + RCC_CLOCK_MUX_SRC_LSE, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_LPTIM2] = { + .name = "lptim2", + /* Same mapping as: CCIPR_LPTIM2SEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + RCC_CLOCK_MUX_SRC_LSI, + RCC_CLOCK_MUX_SRC_HSI, + RCC_CLOCK_MUX_SRC_LSE, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_SWPMI1] = { + .name = "swpmi1", + /* Same mapping as: CCIPR_SWPMI1SEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + RCC_CLOCK_MUX_SRC_HSI, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_MCO] = { + .name = "mco", + /* Same mapping as: CFGR_MCOSEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + RCC_CLOCK_MUX_SRC_MSI, + RCC_CLOCK_MUX_SRC_HSI, + RCC_CLOCK_MUX_SRC_HSE, + RCC_CLOCK_MUX_SRC_PLL, + RCC_CLOCK_MUX_SRC_LSI, + RCC_CLOCK_MUX_SRC_LSE, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_LSCO] = { + .name = "lsco", + /* Same mapping as: BDCR_LSCOSEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_LSI, + RCC_CLOCK_MUX_SRC_LSE, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_DFSDM1] = { + .name = "dfsdm1", + /* Same mapping as: CCIPR_DFSDM1SEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK2, + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_ADC] = { + .name = "adc", + /* Same mapping as: CCIPR_ADCSEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_GND, + RCC_CLOCK_MUX_SRC_PLLADC1, + RCC_CLOCK_MUX_SRC_PLLADC2, + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_CLK48] = { + .name = "clk48", + /* Same mapping as: CCIPR_CLK48SEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_GND, + RCC_CLOCK_MUX_SRC_PLL48M2, + RCC_CLOCK_MUX_SRC_PLL48M1, + RCC_CLOCK_MUX_SRC_MSI, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_SAI2] = { + .name = "sai2", + /* Same mapping as: CCIPR_SAI2SEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_PLLSAI1, + RCC_CLOCK_MUX_SRC_PLLSAI2, + RCC_CLOCK_MUX_SRC_PLLSAI3, + RCC_CLOCK_MUX_SRC_SAI2_EXTCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_SAI1] = { + .name = "sai1", + /* Same mapping as: CCIPR_SAI1SEL */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_PLLSAI1, + RCC_CLOCK_MUX_SRC_PLLSAI2, + RCC_CLOCK_MUX_SRC_PLLSAI3, + RCC_CLOCK_MUX_SRC_SAI1_EXTCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + /* From now on, these muxes only have one valid source */ + [RCC_CLOCK_MUX_TSC] = { + .name = "tsc", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_CRC] = { + .name = "crc", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_FLASH] = { + .name = "flash", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_DMA2] = { + .name = "dma2", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_DMA1] = { + .name = "dma1", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_RNG] = { + .name = "rng", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_AES] = { + .name = "aes", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_OTGFS] = { + .name = "otgfs", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_GPIOA] = { + .name = "gpioa", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_GPIOB] = { + .name = "gpiob", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_GPIOC] = { + .name = "gpioc", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_GPIOD] = { + .name = "gpiod", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_GPIOE] = { + .name = "gpioe", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_GPIOF] = { + .name = "gpiof", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_GPIOG] = { + .name = "gpiog", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_GPIOH] = { + .name = "gpioh", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_QSPI] = { + .name = "qspi", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_FMC] = { + .name = "fmc", + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_OPAMP] = { + .name = "opamp", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_DAC1] = { + .name = "dac1", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_PWR] = { + .name = "pwr", + /* + * PWREN is in the APB1ENR1 register, + * but PWR uses SYSCLK according to the clock tree. + */ + .src_mapping = { + RCC_CLOCK_MUX_SRC_SYSCLK, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_CAN1] = { + .name = "can1", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_SPI3] = { + .name = "spi3", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_SPI2] = { + .name = "spi2", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_WWDG] = { + .name = "wwdg", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_LCD] = { + .name = "lcd", + .src_mapping = { + RCC_CLOCK_MUX_SRC_LCD_AND_RTC_COMMON, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_TIM7] = { + .name = "tim7", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_TIM6] = { + .name = "tim6", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_TIM5] = { + .name = "tim5", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_TIM4] = { + .name = "tim4", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_TIM3] = { + .name = "tim3", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_TIM2] = { + .name = "tim2", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK1, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_TIM17] = { + .name = "tim17", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK2, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_TIM16] = { + .name = "tim16", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK2, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_TIM15] = { + .name = "tim15", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK2, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_TIM8] = { + .name = "tim8", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK2, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_SPI1] = { + .name = "spi1", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK2, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_TIM1] = { + .name = "tim1", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK2, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_SDMMC1] = { + .name = "sdmmc1", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK2, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_FW] = { + .name = "fw", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK2, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_SYSCFG] = { + .name = "syscfg", + .src_mapping = { + RCC_CLOCK_MUX_SRC_PCLK2, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_RTC] = { + .name = "rtc", + .src_mapping = { + RCC_CLOCK_MUX_SRC_LCD_AND_RTC_COMMON, + }, + FILL_DEFAULT_INIT_DISABLED, + }, + [RCC_CLOCK_MUX_CORTEX_FCLK] = { + .name = "cortex-fclk", + .src_mapping = { + RCC_CLOCK_MUX_SRC_HCLK, + }, + FILL_DEFAULT_INIT_ENABLED, + }, +}; + +static inline void set_clock_mux_init_info(RccClockMuxState *mux, + RccClockMux id) +{ + mux->id = id; + mux->multiplier = CLOCK_MUX_INIT_INFO[id].multiplier; + mux->divider = CLOCK_MUX_INIT_INFO[id].divider; + mux->enabled = CLOCK_MUX_INIT_INFO[id].enabled; + /* + * Every peripheral has the first source of their source list as + * as their default source. + */ + mux->src = 0; +} + #endif /* HW_STM32L4X5_RCC_INTERNALS_H */ diff --git a/hw/misc/stm32l4x5_rcc.c b/hw/misc/stm32l4x5_rcc.c index 9a9ea6c4702..083c0ad9ef5 100644 --- a/hw/misc/stm32l4x5_rcc.c +++ b/hw/misc/stm32l4x5_rcc.c @@ -36,7 +36,13 @@ #define LSE_FRQ 32768ULL #define LSI_FRQ 32000ULL -static void clock_mux_update(RccClockMuxState *mux) +/* + * Function to simply acknowledge and propagate changes in a clock mux + * frequency. + * `bypass_source` allows to bypass the period of the current source and just + * consider it equal to 0. This is useful during the hold phase of reset. + */ +static void clock_mux_update(RccClockMuxState *mux, bool bypass_source) { uint64_t src_freq; Clock *current_source = mux->srcs[mux->src]; @@ -48,7 +54,7 @@ static void clock_mux_update(RccClockMuxState *mux) * the clock and the divider of the mux becomes the multiplier of the * clock. */ - if (mux->enabled && mux->divider) { + if (!bypass_source && mux->enabled && mux->divider) { freq_multiplier = mux->divider; } @@ -73,7 +79,7 @@ static void clock_mux_src_update(void *opaque, ClockEvent event) const uint32_t update_src = backref - s->backref; /* Only update if the clock that was updated is the current source */ if (update_src == s->src) { - clock_mux_update(s); + clock_mux_update(s, false); } } @@ -95,8 +101,23 @@ static void clock_mux_init(Object *obj) s->out = qdev_init_clock_out(DEVICE(s), "out"); } +static void clock_mux_reset_enter(Object *obj, ResetType type) +{ + RccClockMuxState *s = RCC_CLOCK_MUX(obj); + set_clock_mux_init_info(s, s->id); +} + static void clock_mux_reset_hold(Object *obj) -{ } +{ + RccClockMuxState *s = RCC_CLOCK_MUX(obj); + clock_mux_update(s, true); +} + +static void clock_mux_reset_exit(Object *obj) +{ + RccClockMuxState *s = RCC_CLOCK_MUX(obj); + clock_mux_update(s, false); +} static const VMStateDescription clock_mux_vmstate = { .name = TYPE_RCC_CLOCK_MUX, @@ -119,7 +140,9 @@ static void clock_mux_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); ResettableClass *rc = RESETTABLE_CLASS(klass); + rc->phases.enter = clock_mux_reset_enter; rc->phases.hold = clock_mux_reset_hold; + rc->phases.exit = clock_mux_reset_exit; dc->vmsd = &clock_mux_vmstate; } @@ -136,7 +159,7 @@ static void clock_mux_set_enable(RccClockMuxState *mux, bool enabled) } mux->enabled = enabled; - clock_mux_update(mux); + clock_mux_update(mux, false); } static void clock_mux_set_factor(RccClockMuxState *mux, @@ -150,7 +173,7 @@ static void clock_mux_set_factor(RccClockMuxState *mux, mux->multiplier = multiplier; mux->divider = divider; - clock_mux_update(mux); + clock_mux_update(mux, false); } static void clock_mux_set_source(RccClockMuxState *mux, RccClockMuxSource src) @@ -161,10 +184,15 @@ static void clock_mux_set_source(RccClockMuxState *mux, RccClockMuxSource src) trace_stm32l4x5_rcc_mux_set_src(mux->id, mux->src, src); mux->src = src; - clock_mux_update(mux); + clock_mux_update(mux, false); } -static void pll_update(RccPllState *pll) +/* + * Acknowledge and propagate changes in a PLL frequency. + * `bypass_source` allows to bypass the period of the current source and just + * consider it equal to 0. This is useful during the hold phase of reset. + */ +static void pll_update(RccPllState *pll, bool bypass_source) { uint64_t vco_freq, old_channel_freq, channel_freq; int i; @@ -178,7 +206,8 @@ static void pll_update(RccPllState *pll) } old_channel_freq = clock_get_hz(pll->channels[i]); - if (!pll->enabled || + if (bypass_source || + !pll->enabled || !pll->channel_enabled[i] || !pll->channel_divider[i]) { channel_freq = 0; @@ -202,7 +231,7 @@ static void pll_update(RccPllState *pll) static void pll_src_update(void *opaque, ClockEvent event) { RccPllState *s = opaque; - pll_update(s); + pll_update(s, false); } static void pll_init(Object *obj) @@ -222,8 +251,23 @@ static void pll_init(Object *obj) } } +static void pll_reset_enter(Object *obj, ResetType type) +{ + RccPllState *s = RCC_PLL(obj); + set_pll_init_info(s, s->id); +} + static void pll_reset_hold(Object *obj) -{ } +{ + RccPllState *s = RCC_PLL(obj); + pll_update(s, true); +} + +static void pll_reset_exit(Object *obj) +{ + RccPllState *s = RCC_PLL(obj); + pll_update(s, false); +} static const VMStateDescription pll_vmstate = { .name = TYPE_RCC_PLL, @@ -248,7 +292,9 @@ static void pll_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); ResettableClass *rc = RESETTABLE_CLASS(klass); + rc->phases.enter = pll_reset_enter; rc->phases.hold = pll_reset_hold; + rc->phases.exit = pll_reset_exit; dc->vmsd = &pll_vmstate; } @@ -269,7 +315,7 @@ static void pll_set_vco_multiplier(RccPllState *pll, uint32_t vco_multiplier) pll->vco_multiplier, vco_multiplier); pll->vco_multiplier = vco_multiplier; - pll_update(pll); + pll_update(pll, false); } static void pll_set_enable(RccPllState *pll, bool enabled) @@ -279,7 +325,7 @@ static void pll_set_enable(RccPllState *pll, bool enabled) } pll->enabled = enabled; - pll_update(pll); + pll_update(pll, false); } static void pll_set_channel_enable(RccPllState *pll, @@ -297,7 +343,7 @@ static void pll_set_channel_enable(RccPllState *pll, } pll->channel_enabled[channel] = enabled; - pll_update(pll); + pll_update(pll, false); } static void pll_set_channel_divider(RccPllState *pll, @@ -312,7 +358,7 @@ static void pll_set_channel_divider(RccPllState *pll, channel, pll->channel_divider[channel], divider); pll->channel_divider[channel] = divider; - pll_update(pll); + pll_update(pll, false); } static void rcc_update_irq(Stm32l4x5RccState *s) @@ -625,21 +671,79 @@ static void stm32l4x5_rcc_init(Object *obj) qdev_init_clocks(DEVICE(s), stm32l4x5_rcc_clocks); for (i = 0; i < RCC_NUM_PLL; i++) { - object_initialize_child(obj, "pll[*]", + object_initialize_child(obj, PLL_INIT_INFO[i].name, &s->plls[i], TYPE_RCC_PLL); + set_pll_init_info(&s->plls[i], i); } for (i = 0; i < RCC_NUM_CLOCK_MUX; i++) { + char *alias; - object_initialize_child(obj, "clock[*]", + object_initialize_child(obj, CLOCK_MUX_INIT_INFO[i].name, &s->clock_muxes[i], TYPE_RCC_CLOCK_MUX); + set_clock_mux_init_info(&s->clock_muxes[i], i); + if (!CLOCK_MUX_INIT_INFO[i].hidden) { + /* Expose muxes output as RCC outputs */ + alias = g_strdup_printf("%s-out", CLOCK_MUX_INIT_INFO[i].name); + qdev_alias_clock(DEVICE(&s->clock_muxes[i]), "out", DEVICE(obj), alias); + g_free(alias); + } } s->gnd = clock_new(obj, "gnd"); } +static void connect_mux_sources(Stm32l4x5RccState *s, + RccClockMuxState *mux, + const RccClockMuxSource *clk_mapping) +{ + size_t i; + + Clock * const CLK_SRC_MAPPING[] = { + [RCC_CLOCK_MUX_SRC_GND] = s->gnd, + [RCC_CLOCK_MUX_SRC_HSI] = s->hsi16_rc, + [RCC_CLOCK_MUX_SRC_HSE] = s->hse, + [RCC_CLOCK_MUX_SRC_MSI] = s->msi_rc, + [RCC_CLOCK_MUX_SRC_LSI] = s->lsi_rc, + [RCC_CLOCK_MUX_SRC_LSE] = s->lse_crystal, + [RCC_CLOCK_MUX_SRC_SAI1_EXTCLK] = s->sai1_extclk, + [RCC_CLOCK_MUX_SRC_SAI2_EXTCLK] = s->sai2_extclk, + [RCC_CLOCK_MUX_SRC_PLL] = + s->plls[RCC_PLL_PLL].channels[RCC_PLL_CHANNEL_PLLCLK], + [RCC_CLOCK_MUX_SRC_PLLSAI1] = + s->plls[RCC_PLL_PLLSAI1].channels[RCC_PLLSAI1_CHANNEL_PLLSAI1CLK], + [RCC_CLOCK_MUX_SRC_PLLSAI2] = + s->plls[RCC_PLL_PLLSAI2].channels[RCC_PLLSAI2_CHANNEL_PLLSAI2CLK], + [RCC_CLOCK_MUX_SRC_PLLSAI3] = + s->plls[RCC_PLL_PLL].channels[RCC_PLL_CHANNEL_PLLSAI3CLK], + [RCC_CLOCK_MUX_SRC_PLL48M1] = + s->plls[RCC_PLL_PLL].channels[RCC_PLL_CHANNEL_PLL48M1CLK], + [RCC_CLOCK_MUX_SRC_PLL48M2] = + s->plls[RCC_PLL_PLLSAI1].channels[RCC_PLLSAI1_CHANNEL_PLL48M2CLK], + [RCC_CLOCK_MUX_SRC_PLLADC1] = + s->plls[RCC_PLL_PLLSAI1].channels[RCC_PLLSAI1_CHANNEL_PLLADC1CLK], + [RCC_CLOCK_MUX_SRC_PLLADC2] = + s->plls[RCC_PLL_PLLSAI2] .channels[RCC_PLLSAI2_CHANNEL_PLLADC2CLK], + [RCC_CLOCK_MUX_SRC_SYSCLK] = s->clock_muxes[RCC_CLOCK_MUX_SYSCLK].out, + [RCC_CLOCK_MUX_SRC_HCLK] = s->clock_muxes[RCC_CLOCK_MUX_HCLK].out, + [RCC_CLOCK_MUX_SRC_PCLK1] = s->clock_muxes[RCC_CLOCK_MUX_PCLK1].out, + [RCC_CLOCK_MUX_SRC_PCLK2] = s->clock_muxes[RCC_CLOCK_MUX_PCLK2].out, + [RCC_CLOCK_MUX_SRC_HSE_OVER_32] = s->clock_muxes[RCC_CLOCK_MUX_HSE_OVER_32].out, + [RCC_CLOCK_MUX_SRC_LCD_AND_RTC_COMMON] = + s->clock_muxes[RCC_CLOCK_MUX_LCD_AND_RTC_COMMON].out, + }; + + assert(ARRAY_SIZE(CLK_SRC_MAPPING) == RCC_CLOCK_MUX_SRC_NUMBER); + + for (i = 0; i < RCC_NUM_CLOCK_MUX_SRC; i++) { + RccClockMuxSource mapping = clk_mapping[i]; + clock_set_source(mux->srcs[i], CLK_SRC_MAPPING[mapping]); + } +} + + static const VMStateDescription vmstate_stm32l4x5_rcc = { .name = TYPE_STM32L4X5_RCC, .version_id = 1, @@ -712,11 +816,17 @@ static void stm32l4x5_rcc_realize(DeviceState *dev, Error **errp) for (i = 0; i < RCC_NUM_CLOCK_MUX; i++) { RccClockMuxState *clock_mux = &s->clock_muxes[i]; + connect_mux_sources(s, clock_mux, CLOCK_MUX_INIT_INFO[i].src_mapping); + if (!qdev_realize(DEVICE(clock_mux), NULL, errp)) { return; } } + /* + * Start clocks after everything is connected + * to propagate the frequencies along the tree. + */ clock_update_hz(s->msi_rc, MSI_DEFAULT_FRQ); clock_update_hz(s->sai1_extclk, s->sai1_extclk_frequency); clock_update_hz(s->sai2_extclk, s->sai2_extclk_frequency); @@ -750,6 +860,7 @@ static void stm32l4x5_rcc_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); ResettableClass *rc = RESETTABLE_CLASS(klass); + assert(ARRAY_SIZE(CLOCK_MUX_INIT_INFO) == RCC_NUM_CLOCK_MUX); rc->phases.hold = stm32l4x5_rcc_reset_hold; device_class_set_props(dc, stm32l4x5_rcc_properties); From patchwork Tue Mar 5 13:52:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582469 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 CAA2EC54798 for ; Tue, 5 Mar 2024 13:54:23 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVEt-0001dd-Us; Tue, 05 Mar 2024 08:53:52 -0500 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 1rhVDw-0000wb-QH for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:53:06 -0500 Received: from mail-wr1-x42a.google.com ([2a00:1450:4864:20::42a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDo-0005xn-T7 for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:52 -0500 Received: by mail-wr1-x42a.google.com with SMTP id ffacd0b85a97d-33d118a181fso3650373f8f.1 for ; Tue, 05 Mar 2024 05:52:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646763; x=1710251563; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=JNI+Qpco22VWGAbmNYNkaRO2Lu4QWjoV4nttCF019Tw=; b=FWDFtzvPdK8F2XMbz5X8EQPfHNA18peyhQrifWh1FNCz7yUnze41Kwu6sM9KVAEWT4 5fmzObsBX/+pVPbzZRzJR8WY16Fy0prXdFhRm7n9IE4JKwr/AldFqX0qIrkgLtOusP3n caHoF/rjK0pH8qg6Nv6eC09dkKDh7q5xoi8W9EUzOW515404K6Csi5zm3AOtCAd+ok8g sGKiHtzBnjJip6K7FjsLvZi02cG87q5TqrW46HDwLlcRBrfhVRTjSmpOG1bWUj2TdECi 76UdrvX5rc0PufxRI2HsJ6qhK4d69nCi8qoKPJ5rUcskXFxOW/4Vaom7tOUAZM/x+3Y9 EW4w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646763; x=1710251563; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JNI+Qpco22VWGAbmNYNkaRO2Lu4QWjoV4nttCF019Tw=; b=lUtu9y0STLLkHXlfp9CxLXDtwTcwUHTie0yhdjpXCXz9til1suG426ARhaizalQFge mACVKL7efvkox8oObgyGHjklntCPb6ltPdzpEXGzzkZrV/JJ/1e4SunP1dS79m2m7AS6 BLWnM9VsmgkiHy+DfiCNEyCHubWpT7DO/SYY/VXVq8DWksd5hEW1TC5iccARf46weH4R Fb9X5/S3hxjsuFwdOzicDd44hSqNmB5YX7GMqsnc6ug+4+NLh3aglyIH5jurAW87TCK4 kyNy3j+nTP2Hi4nY7mJzwafwbco3YhncXDeDHGW7TFUrb5A3F4qD+V0iFovbBk7+3cR3 OFmA== X-Gm-Message-State: AOJu0Yy3UpmkmVneD2thY/TbwXEtKoXIQb2X80auSyu+hkO9qqwlki8k fy+lbLFYoJ4Vftsu5qndR0B5H5umakK4IIimQHbzZ3akfsSpeO3sqhTaElg6ebvQiDaeBq8MqWF r X-Google-Smtp-Source: AGHT+IFX9fzPerwWVI1nba94s/HZaX2JI3CF1eoPMWG3ZOiCqNik3STSzl3XdanxoXZBTAJW3ioKAQ== X-Received: by 2002:a05:6000:3c5:b0:33e:4590:8bd8 with SMTP id b5-20020a05600003c500b0033e45908bd8mr4370759wrg.60.1709646763442; Tue, 05 Mar 2024 05:52:43 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.43 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:43 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 09/20] hw/misc/stm32l4x5_rcc: Handle Register Updates Date: Tue, 5 Mar 2024 13:52:26 +0000 Message-Id: <20240305135237.3111642-10-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::42a; envelope-from=peter.maydell@linaro.org; helo=mail-wr1-x42a.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Arnaud Minier Update the RCC state and propagate frequency changes when writing to the RCC registers. Currently, ICSCR, CIER, the reset registers and the stop mode registers are not implemented. Some fields have not been implemented due to uncertainty about how to handle them (Like the clock security system or bypassing mecanisms). Signed-off-by: Arnaud Minier Signed-off-by: Inès Varhol Message-id: 20240303140643.81957-6-arnaud.minier@telecom-paris.fr Signed-off-by: Peter Maydell Reviewed-by: Peter Maydell --- hw/misc/stm32l4x5_rcc.c | 524 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 512 insertions(+), 12 deletions(-) diff --git a/hw/misc/stm32l4x5_rcc.c b/hw/misc/stm32l4x5_rcc.c index 083c0ad9ef5..2109f809e2b 100644 --- a/hw/misc/stm32l4x5_rcc.c +++ b/hw/misc/stm32l4x5_rcc.c @@ -28,6 +28,7 @@ #include "hw/qdev-clock.h" #include "hw/qdev-properties.h" #include "hw/qdev-properties-system.h" +#include "hw/registerfields.h" #include "trace.h" #define HSE_DEFAULT_FRQ 48000000ULL @@ -363,6 +364,9 @@ static void pll_set_channel_divider(RccPllState *pll, static void rcc_update_irq(Stm32l4x5RccState *s) { + /* + * TODO: Handle LSECSSF and CSSF flags when the CSS is implemented. + */ if (s->cifr & CIFR_IRQ_MASK) { qemu_irq_raise(s->irq); } else { @@ -370,6 +374,472 @@ static void rcc_update_irq(Stm32l4x5RccState *s) } } +static void rcc_update_cr_register(Stm32l4x5RccState *s) +{ + int val; + + /* PLLSAI2ON and update PLLSAI2RDY */ + val = FIELD_EX32(s->cr, CR, PLLSAI2ON); + pll_set_enable(&s->plls[RCC_PLL_PLLSAI2], val); + s->cr = (s->cr & ~R_CR_PLLSAI2RDY_MASK) | + (val << R_CR_PLLSAI2RDY_SHIFT); + if (s->cier & R_CIER_PLLSAI2RDYIE_MASK) { + s->cifr |= R_CIFR_PLLSAI2RDYF_MASK; + } + + /* PLLSAI1ON and update PLLSAI1RDY */ + val = FIELD_EX32(s->cr, CR, PLLSAI1ON); + pll_set_enable(&s->plls[RCC_PLL_PLLSAI1], val); + s->cr = (s->cr & ~R_CR_PLLSAI1RDY_MASK) | + (val << R_CR_PLLSAI1RDY_SHIFT); + if (s->cier & R_CIER_PLLSAI1RDYIE_MASK) { + s->cifr |= R_CIFR_PLLSAI1RDYF_MASK; + } + + /* PLLON and update PLLRDY */ + val = FIELD_EX32(s->cr, CR, PLLON); + pll_set_enable(&s->plls[RCC_PLL_PLL], val); + s->cr = (s->cr & ~R_CR_PLLRDY_MASK) | + (val << R_CR_PLLRDY_SHIFT); + if (s->cier & R_CIER_PLLRDYIE_MASK) { + s->cifr |= R_CIFR_PLLRDYF_MASK; + } + + /* CSSON: TODO */ + /* HSEBYP: TODO */ + + /* HSEON and update HSERDY */ + val = FIELD_EX32(s->cr, CR, HSEON); + s->cr = (s->cr & ~R_CR_HSERDY_MASK) | + (val << R_CR_HSERDY_SHIFT); + if (val) { + clock_update_hz(s->hse, s->hse_frequency); + if (s->cier & R_CIER_HSERDYIE_MASK) { + s->cifr |= R_CIFR_HSERDYF_MASK; + } + } else { + clock_update(s->hse, 0); + } + + /* HSIAFS: TODO*/ + /* HSIKERON: TODO*/ + + /* HSION and update HSIRDY*/ + val = FIELD_EX32(s->cr, CR, HSION); + s->cr = (s->cr & ~R_CR_HSIRDY_MASK) | + (val << R_CR_HSIRDY_SHIFT); + if (val) { + clock_update_hz(s->hsi16_rc, HSI_FRQ); + if (s->cier & R_CIER_HSIRDYIE_MASK) { + s->cifr |= R_CIFR_HSIRDYF_MASK; + } + } else { + clock_update(s->hsi16_rc, 0); + } + + static const uint32_t msirange[] = { + 100000, 200000, 400000, 800000, 1000000, 2000000, + 4000000, 8000000, 16000000, 24000000, 32000000, 48000000 + }; + /* MSIRANGE and MSIRGSEL */ + val = FIELD_EX32(s->cr, CR, MSIRGSEL); + if (val) { + /* MSIRGSEL is set, use the MSIRANGE field */ + val = FIELD_EX32(s->cr, CR, MSIRANGE); + } else { + /* MSIRGSEL is not set, use the MSISRANGE field */ + val = FIELD_EX32(s->csr, CSR, MSISRANGE); + } + + if (val < ARRAY_SIZE(msirange)) { + clock_update_hz(s->msi_rc, msirange[val]); + } else { + clock_update_hz(s->msi_rc, MSI_DEFAULT_FRQ); + /* TODO: there is a write protection if the value is out of bound, + implement that instead of setting the default */ + } + + /* MSIPLLEN */ + + /* MSION and update MSIRDY */ + val = FIELD_EX32(s->cr, CR, MSION); + s->cr = (s->cr & ~R_CR_MSIRDY_MASK) | + (val << R_CR_MSIRDY_SHIFT); + if (s->cier & R_CIER_MSIRDYIE_MASK) { + s->cifr |= R_CIFR_MSIRDYF_MASK; + } + rcc_update_irq(s); +} + +static void rcc_update_cfgr_register(Stm32l4x5RccState *s) +{ + uint32_t val; + /* MCOPRE */ + val = FIELD_EX32(s->cfgr, CFGR, MCOPRE); + assert(val <= 0b100); + clock_mux_set_factor(&s->clock_muxes[RCC_CLOCK_MUX_MCO], + 1, 1 << val); + + /* MCOSEL */ + val = FIELD_EX32(s->cfgr, CFGR, MCOSEL); + assert(val <= 0b111); + if (val == 0) { + clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_MCO], false); + } else { + clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_MCO], true); + clock_mux_set_source(&s->clock_muxes[RCC_CLOCK_MUX_MCO], + val - 1); + } + + /* STOPWUCK */ + /* TODO */ + + /* PPRE2 */ + val = FIELD_EX32(s->cfgr, CFGR, PPRE2); + if (val < 0b100) { + clock_mux_set_factor(&s->clock_muxes[RCC_CLOCK_MUX_PCLK2], + 1, 1); + } else { + clock_mux_set_factor(&s->clock_muxes[RCC_CLOCK_MUX_PCLK2], + 1, 1 << (val - 0b11)); + } + + /* PPRE1 */ + val = FIELD_EX32(s->cfgr, CFGR, PPRE1); + if (val < 0b100) { + clock_mux_set_factor(&s->clock_muxes[RCC_CLOCK_MUX_PCLK1], + 1, 1); + } else { + clock_mux_set_factor(&s->clock_muxes[RCC_CLOCK_MUX_PCLK1], + 1, 1 << (val - 0b11)); + } + + /* HPRE */ + val = FIELD_EX32(s->cfgr, CFGR, HPRE); + if (val < 0b1000) { + clock_mux_set_factor(&s->clock_muxes[RCC_CLOCK_MUX_HCLK], + 1, 1); + } else { + clock_mux_set_factor(&s->clock_muxes[RCC_CLOCK_MUX_HCLK], + 1, 1 << (val - 0b111)); + } + + /* Update SWS */ + val = FIELD_EX32(s->cfgr, CFGR, SW); + clock_mux_set_source(&s->clock_muxes[RCC_CLOCK_MUX_SYSCLK], + val); + s->cfgr &= ~R_CFGR_SWS_MASK; + s->cfgr |= val << R_CFGR_SWS_SHIFT; +} + +static void rcc_update_ahb1enr(Stm32l4x5RccState *s) +{ + #define AHB1ENR_SET_ENABLE(_peripheral_name) \ + clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \ + FIELD_EX32(s->ahb1enr, AHB1ENR, _peripheral_name##EN)) + + /* DMA2DEN: reserved for STM32L475xx */ + AHB1ENR_SET_ENABLE(TSC); + AHB1ENR_SET_ENABLE(CRC); + AHB1ENR_SET_ENABLE(FLASH); + AHB1ENR_SET_ENABLE(DMA2); + AHB1ENR_SET_ENABLE(DMA1); + + #undef AHB1ENR_SET_ENABLE +} + +static void rcc_update_ahb2enr(Stm32l4x5RccState *s) +{ + #define AHB2ENR_SET_ENABLE(_peripheral_name) \ + clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \ + FIELD_EX32(s->ahb2enr, AHB2ENR, _peripheral_name##EN)) + + AHB2ENR_SET_ENABLE(RNG); + /* HASHEN: reserved for STM32L475xx */ + AHB2ENR_SET_ENABLE(AES); + /* DCMIEN: reserved for STM32L475xx */ + AHB2ENR_SET_ENABLE(ADC); + AHB2ENR_SET_ENABLE(OTGFS); + /* GPIOIEN: reserved for STM32L475xx */ + AHB2ENR_SET_ENABLE(GPIOA); + AHB2ENR_SET_ENABLE(GPIOB); + AHB2ENR_SET_ENABLE(GPIOC); + AHB2ENR_SET_ENABLE(GPIOD); + AHB2ENR_SET_ENABLE(GPIOE); + AHB2ENR_SET_ENABLE(GPIOF); + AHB2ENR_SET_ENABLE(GPIOG); + AHB2ENR_SET_ENABLE(GPIOH); + + #undef AHB2ENR_SET_ENABLE +} + +static void rcc_update_ahb3enr(Stm32l4x5RccState *s) +{ + #define AHB3ENR_SET_ENABLE(_peripheral_name) \ + clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \ + FIELD_EX32(s->ahb3enr, AHB3ENR, _peripheral_name##EN)) + + AHB3ENR_SET_ENABLE(QSPI); + AHB3ENR_SET_ENABLE(FMC); + + #undef AHB3ENR_SET_ENABLE +} + +static void rcc_update_apb1enr(Stm32l4x5RccState *s) +{ + #define APB1ENR1_SET_ENABLE(_peripheral_name) \ + clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \ + FIELD_EX32(s->apb1enr1, APB1ENR1, _peripheral_name##EN)) + #define APB1ENR2_SET_ENABLE(_peripheral_name) \ + clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \ + FIELD_EX32(s->apb1enr2, APB1ENR2, _peripheral_name##EN)) + + /* APB1ENR1 */ + APB1ENR1_SET_ENABLE(LPTIM1); + APB1ENR1_SET_ENABLE(OPAMP); + APB1ENR1_SET_ENABLE(DAC1); + APB1ENR1_SET_ENABLE(PWR); + /* CAN2: reserved for STM32L4x5 */ + APB1ENR1_SET_ENABLE(CAN1); + /* CRSEN: reserved for STM32L4x5 */ + APB1ENR1_SET_ENABLE(I2C3); + APB1ENR1_SET_ENABLE(I2C2); + APB1ENR1_SET_ENABLE(I2C1); + APB1ENR1_SET_ENABLE(UART5); + APB1ENR1_SET_ENABLE(UART4); + APB1ENR1_SET_ENABLE(USART3); + APB1ENR1_SET_ENABLE(USART2); + APB1ENR1_SET_ENABLE(SPI3); + APB1ENR1_SET_ENABLE(SPI2); + APB1ENR1_SET_ENABLE(WWDG); + /* RTCAPB: reserved for STM32L4x5 */ + APB1ENR1_SET_ENABLE(LCD); + APB1ENR1_SET_ENABLE(TIM7); + APB1ENR1_SET_ENABLE(TIM6); + APB1ENR1_SET_ENABLE(TIM5); + APB1ENR1_SET_ENABLE(TIM4); + APB1ENR1_SET_ENABLE(TIM3); + APB1ENR1_SET_ENABLE(TIM2); + + /* APB1ENR2 */ + APB1ENR2_SET_ENABLE(LPTIM2); + APB1ENR2_SET_ENABLE(SWPMI1); + /* I2C4EN: reserved for STM32L4x5 */ + APB1ENR2_SET_ENABLE(LPUART1); + + #undef APB1ENR1_SET_ENABLE + #undef APB1ENR2_SET_ENABLE +} + +static void rcc_update_apb2enr(Stm32l4x5RccState *s) +{ + #define APB2ENR_SET_ENABLE(_peripheral_name) \ + clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \ + FIELD_EX32(s->apb2enr, APB2ENR, _peripheral_name##EN)) + + APB2ENR_SET_ENABLE(DFSDM1); + APB2ENR_SET_ENABLE(SAI2); + APB2ENR_SET_ENABLE(SAI1); + APB2ENR_SET_ENABLE(TIM17); + APB2ENR_SET_ENABLE(TIM16); + APB2ENR_SET_ENABLE(TIM15); + APB2ENR_SET_ENABLE(USART1); + APB2ENR_SET_ENABLE(TIM8); + APB2ENR_SET_ENABLE(SPI1); + APB2ENR_SET_ENABLE(TIM1); + APB2ENR_SET_ENABLE(SDMMC1); + APB2ENR_SET_ENABLE(FW); + APB2ENR_SET_ENABLE(SYSCFG); + + #undef APB2ENR_SET_ENABLE +} + +/* + * The 3 PLLs share the same register layout + * so we can use the same function for all of them + * Note: no frequency bounds checking is done here. + */ +static void rcc_update_pllsaixcfgr(Stm32l4x5RccState *s, RccPll pll_id) +{ + uint32_t reg, val; + switch (pll_id) { + case RCC_PLL_PLL: + reg = s->pllcfgr; + break; + case RCC_PLL_PLLSAI1: + reg = s->pllsai1cfgr; + break; + case RCC_PLL_PLLSAI2: + reg = s->pllsai2cfgr; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Invalid PLL ID: %u\n", __func__, pll_id); + return; + } + + /* PLLPDIV */ + val = FIELD_EX32(reg, PLLCFGR, PLLPDIV); + /* 1 is a reserved value */ + if (val == 0) { + /* Get PLLP value */ + val = FIELD_EX32(reg, PLLCFGR, PLLP); + pll_set_channel_divider(&s->plls[pll_id], RCC_PLL_COMMON_CHANNEL_P, + (val ? 17 : 7)); + } else if (val > 1) { + pll_set_channel_divider(&s->plls[pll_id], RCC_PLL_COMMON_CHANNEL_P, + val); + } + + + /* PLLR */ + val = FIELD_EX32(reg, PLLCFGR, PLLR); + pll_set_channel_divider(&s->plls[pll_id], RCC_PLL_COMMON_CHANNEL_R, + 2 * (val + 1)); + + /* PLLREN */ + val = FIELD_EX32(reg, PLLCFGR, PLLREN); + pll_set_channel_enable(&s->plls[pll_id], RCC_PLL_COMMON_CHANNEL_R, val); + + /* PLLQ */ + val = FIELD_EX32(reg, PLLCFGR, PLLQ); + pll_set_channel_divider(&s->plls[pll_id], RCC_PLL_COMMON_CHANNEL_Q, + 2 * (val + 1)); + + /* PLLQEN */ + val = FIELD_EX32(reg, PLLCFGR, PLLQEN); + pll_set_channel_enable(&s->plls[pll_id], RCC_PLL_COMMON_CHANNEL_Q, val); + + /* PLLPEN */ + val = FIELD_EX32(reg, PLLCFGR, PLLPEN); + pll_set_channel_enable(&s->plls[pll_id], RCC_PLL_COMMON_CHANNEL_P, val); + + /* PLLN */ + val = FIELD_EX32(reg, PLLCFGR, PLLN); + pll_set_vco_multiplier(&s->plls[pll_id], val); +} + +static void rcc_update_pllcfgr(Stm32l4x5RccState *s) +{ + int val; + + /* Use common layout */ + rcc_update_pllsaixcfgr(s, RCC_PLL_PLL); + + /* Fetch specific fields for pllcfgr */ + + /* PLLM */ + val = FIELD_EX32(s->pllcfgr, PLLCFGR, PLLM); + clock_mux_set_factor(&s->clock_muxes[RCC_CLOCK_MUX_PLL_INPUT], 1, (val + 1)); + + /* PLLSRC */ + val = FIELD_EX32(s->pllcfgr, PLLCFGR, PLLSRC); + if (val == 0) { + clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_PLL_INPUT], false); + } else { + clock_mux_set_source(&s->clock_muxes[RCC_CLOCK_MUX_PLL_INPUT], val - 1); + clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_PLL_INPUT], true); + } +} + +static void rcc_update_ccipr(Stm32l4x5RccState *s) +{ + #define CCIPR_SET_SOURCE(_peripheral_name) \ + clock_mux_set_source(&s->clock_muxes[RCC_CLOCK_MUX_##_peripheral_name], \ + FIELD_EX32(s->ccipr, CCIPR, _peripheral_name##SEL)) + + CCIPR_SET_SOURCE(DFSDM1); + CCIPR_SET_SOURCE(SWPMI1); + CCIPR_SET_SOURCE(ADC); + CCIPR_SET_SOURCE(CLK48); + CCIPR_SET_SOURCE(SAI2); + CCIPR_SET_SOURCE(SAI1); + CCIPR_SET_SOURCE(LPTIM2); + CCIPR_SET_SOURCE(LPTIM1); + CCIPR_SET_SOURCE(I2C3); + CCIPR_SET_SOURCE(I2C2); + CCIPR_SET_SOURCE(I2C1); + CCIPR_SET_SOURCE(LPUART1); + CCIPR_SET_SOURCE(UART5); + CCIPR_SET_SOURCE(UART4); + CCIPR_SET_SOURCE(USART3); + CCIPR_SET_SOURCE(USART2); + CCIPR_SET_SOURCE(USART1); + + #undef CCIPR_SET_SOURCE +} + +static void rcc_update_bdcr(Stm32l4x5RccState *s) +{ + int val; + + /* LSCOSEL */ + val = FIELD_EX32(s->bdcr, BDCR, LSCOSEL); + clock_mux_set_source(&s->clock_muxes[RCC_CLOCK_MUX_LSCO], val); + + val = FIELD_EX32(s->bdcr, BDCR, LSCOEN); + clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_LSCO], val); + + /* BDRST */ + /* + * The documentation is not clear if the RTCEN flag disables the RTC and + * the LCD common mux or if it only affects the RTC. + * As the LCDEN flag exists, we assume here that it only affects the RTC. + */ + val = FIELD_EX32(s->bdcr, BDCR, RTCEN); + clock_mux_set_enable(&s->clock_muxes[RCC_CLOCK_MUX_RTC], val); + /* LCD and RTC share the same clock */ + val = FIELD_EX32(s->bdcr, BDCR, RTCSEL); + clock_mux_set_source(&s->clock_muxes[RCC_CLOCK_MUX_LCD_AND_RTC_COMMON], val); + + /* LSECSSON */ + /* LSEDRV[1:0] */ + /* LSEBYP */ + + /* LSEON: Update LSERDY at the same time */ + val = FIELD_EX32(s->bdcr, BDCR, LSEON); + if (val) { + clock_update_hz(s->lse_crystal, LSE_FRQ); + s->bdcr |= R_BDCR_LSERDY_MASK; + if (s->cier & R_CIER_LSERDYIE_MASK) { + s->cifr |= R_CIFR_LSERDYF_MASK; + } + } else { + clock_update(s->lse_crystal, 0); + s->bdcr &= ~R_BDCR_LSERDY_MASK; + } + + rcc_update_irq(s); +} + +static void rcc_update_csr(Stm32l4x5RccState *s) +{ + int val; + + /* Reset flags: Not implemented */ + /* MSISRANGE: Not implemented after reset */ + + /* LSION: Update LSIRDY at the same time */ + val = FIELD_EX32(s->csr, CSR, LSION); + if (val) { + clock_update_hz(s->lsi_rc, LSI_FRQ); + s->csr |= R_CSR_LSIRDY_MASK; + if (s->cier & R_CIER_LSIRDYIE_MASK) { + s->cifr |= R_CIFR_LSIRDYF_MASK; + } + } else { + /* + * TODO: Handle when the LSI is set independently of LSION. + * E.g. when the LSI is set by the RTC. + * See the reference manual for more details. + */ + clock_update(s->lsi_rc, 0); + s->csr &= ~R_CSR_LSIRDY_MASK; + } + + rcc_update_irq(s); +} + static void stm32l4x5_rcc_reset_hold(Object *obj) { Stm32l4x5RccState *s = STM32L4X5_RCC(obj); @@ -529,24 +999,33 @@ static void stm32l4x5_rcc_write(void *opaque, hwaddr addr, case A_CR: s->cr = (s->cr & CR_READ_SET_MASK) | (value & (CR_READ_SET_MASK | ~CR_READ_ONLY_MASK)); + rcc_update_cr_register(s); break; case A_ICSCR: s->icscr = value & ~ICSCR_READ_ONLY_MASK; + qemu_log_mask(LOG_UNIMP, + "%s: Side-effects not implemented for ICSCR\n", __func__); break; case A_CFGR: s->cfgr = value & ~CFGR_READ_ONLY_MASK; + rcc_update_cfgr_register(s); break; case A_PLLCFGR: s->pllcfgr = value; + rcc_update_pllcfgr(s); break; case A_PLLSAI1CFGR: s->pllsai1cfgr = value; + rcc_update_pllsaixcfgr(s, RCC_PLL_PLLSAI1); break; case A_PLLSAI2CFGR: s->pllsai2cfgr = value; + rcc_update_pllsaixcfgr(s, RCC_PLL_PLLSAI2); break; case A_CIER: s->cier = value; + qemu_log_mask(LOG_UNIMP, + "%s: Side-effects not implemented for CIER\n", __func__); break; case A_CIFR: qemu_log_mask(LOG_GUEST_ERROR, @@ -561,67 +1040,100 @@ static void stm32l4x5_rcc_write(void *opaque, hwaddr addr, /* Reset behaviors are not implemented */ case A_AHB1RSTR: s->ahb1rstr = value; + qemu_log_mask(LOG_UNIMP, + "%s: Side-effects not implemented for AHB1RSTR\n", __func__); break; case A_AHB2RSTR: s->ahb2rstr = value; + qemu_log_mask(LOG_UNIMP, + "%s: Side-effects not implemented for AHB2RSTR\n", __func__); break; case A_AHB3RSTR: s->ahb3rstr = value; + qemu_log_mask(LOG_UNIMP, + "%s: Side-effects not implemented for AHB3RSTR\n", __func__); break; case A_APB1RSTR1: s->apb1rstr1 = value; + qemu_log_mask(LOG_UNIMP, + "%s: Side-effects not implemented for APB1RSTR1\n", __func__); break; case A_APB1RSTR2: s->apb1rstr2 = value; + qemu_log_mask(LOG_UNIMP, + "%s: Side-effects not implemented for APB1RSTR2\n", __func__); break; case A_APB2RSTR: s->apb2rstr = value; + qemu_log_mask(LOG_UNIMP, + "%s: Side-effects not implemented for APB2RSTR\n", __func__); break; case A_AHB1ENR: s->ahb1enr = value; + rcc_update_ahb1enr(s); break; case A_AHB2ENR: s->ahb2enr = value; + rcc_update_ahb2enr(s); break; case A_AHB3ENR: s->ahb3enr = value; + rcc_update_ahb3enr(s); break; case A_APB1ENR1: s->apb1enr1 = value; + rcc_update_apb1enr(s); break; case A_APB1ENR2: s->apb1enr2 = value; + rcc_update_apb1enr(s); break; case A_APB2ENR: s->apb2enr = (s->apb2enr & APB2ENR_READ_SET_MASK) | value; + rcc_update_apb2enr(s); break; /* Behaviors for Sleep and Stop modes are not implemented */ case A_AHB1SMENR: s->ahb1smenr = value; + qemu_log_mask(LOG_UNIMP, + "%s: Side-effects not implemented for AHB1SMENR\n", __func__); break; case A_AHB2SMENR: s->ahb2smenr = value; + qemu_log_mask(LOG_UNIMP, + "%s: Side-effects not implemented for AHB2SMENR\n", __func__); break; case A_AHB3SMENR: s->ahb3smenr = value; + qemu_log_mask(LOG_UNIMP, + "%s: Side-effects not implemented for AHB3SMENR\n", __func__); break; case A_APB1SMENR1: s->apb1smenr1 = value; + qemu_log_mask(LOG_UNIMP, + "%s: Side-effects not implemented for APB1SMENR1\n", __func__); break; case A_APB1SMENR2: s->apb1smenr2 = value; + qemu_log_mask(LOG_UNIMP, + "%s: Side-effects not implemented for APB1SMENR2\n", __func__); break; case A_APB2SMENR: s->apb2smenr = value; + qemu_log_mask(LOG_UNIMP, + "%s: Side-effects not implemented for APB2SMENR\n", __func__); break; case A_CCIPR: s->ccipr = value; + rcc_update_ccipr(s); break; case A_BDCR: s->bdcr = value & ~BDCR_READ_ONLY_MASK; + rcc_update_bdcr(s); break; case A_CSR: s->csr = value & ~CSR_READ_ONLY_MASK; + rcc_update_csr(s); break; default: qemu_log_mask(LOG_GUEST_ERROR, @@ -831,18 +1343,6 @@ static void stm32l4x5_rcc_realize(DeviceState *dev, Error **errp) clock_update_hz(s->sai1_extclk, s->sai1_extclk_frequency); clock_update_hz(s->sai2_extclk, s->sai2_extclk_frequency); clock_update(s->gnd, 0); - - /* - * Dummy values to make compilation pass. - * Removed in later commits. - */ - clock_mux_set_source(&s->clock_muxes[0], RCC_CLOCK_MUX_SRC_GND); - clock_mux_set_enable(&s->clock_muxes[0], true); - clock_mux_set_factor(&s->clock_muxes[0], 1, 1); - pll_set_channel_divider(&s->plls[0], 0, 1); - pll_set_enable(&s->plls[0], true); - pll_set_channel_enable(&s->plls[0], 0, true); - pll_set_vco_multiplier(&s->plls[0], 1); } static Property stm32l4x5_rcc_properties[] = { From patchwork Tue Mar 5 13:52:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582466 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 6116EC54E41 for ; Tue, 5 Mar 2024 13:54:04 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVEt-0001dc-V2; Tue, 05 Mar 2024 08:53:52 -0500 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 1rhVDw-0000wa-Lr for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:53:06 -0500 Received: from mail-wm1-x333.google.com ([2a00:1450:4864:20::333]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDp-0005xr-Cw for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:52 -0500 Received: by mail-wm1-x333.google.com with SMTP id 5b1f17b1804b1-412eddd14b9so4116195e9.2 for ; Tue, 05 Mar 2024 05:52:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646764; x=1710251564; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=naDQJUm1BWCDp8wycCBq304iBQf/tU4pZQ1OtaRD1ng=; b=AYiky35Yi+n41/UhLOa1alchbNfw0mStGPwSDv+FAmkMsyXkWDdIQTR/TuWOeTHM4Z iJ8B9Zni+RJZU6MGsRaoxDsY4RUW/f9yNUDEB9+bSxblCSRM+tPgTA7DwoI1p8I5HirU gB0AqJp2d9BlT4Kgd6/fvT+XencI+ayVnls6DLT9htjC5d+w5/tHlUDHut9bDIIM5024 hV3xbFk/VFKH3z3tT3hIBJlstZrbUfW0BU0pEBp2l24ZBxl7F0+NuwTQApRmeSwvnSjJ BDoV4XcTbrfil+0Jud23IkT87CO1c8JgqTzW1wqrtUdguK5iQQjVC2UXBJ88Ngeqex2J SK5A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646764; x=1710251564; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=naDQJUm1BWCDp8wycCBq304iBQf/tU4pZQ1OtaRD1ng=; b=p3JbcvI7atSOXADpeDQJgjUivdfmkLM8+ERHaaU6V6GOec6GB/DpJBp5h9kOywv9qq Ou5L/Drk5OK+yLcTiZcnYl5Z3cHjcwKJ+2VUnOwQ+E0/Do1C7Wmrqdz1CeWcjOi6XS2w D2drsw7xogZbwVoOsRVKS3Es8pOJEclKPhH0IYuY6t23o0ZEMekY+gHIwkrIJV3exj7l VqnfDV84kBgAXmuoa4GSTHq5MY4s78QbkP0OAetfAYwa7XF4BJF5DnQRw1+NzPKd8ZwO DTGhj3qeRs5LZo0TsORcsi1zJEexqVdf8AqAtSnY9BUREr7Qh9JwZlc0oR2Cq43V9yhR dhUw== X-Gm-Message-State: AOJu0YxUl2BGqrgpF4By/Ngpi6sefvNXJXcMB/CGx02fENfQ1NTBMt+d 2AOkdgoShHNb+44wR+bJkPvIQD2nv8kyJ5BIjHKLzOf42Ee5BiR5RY3Z+FILJTNxDHeRYR4hzlf K X-Google-Smtp-Source: AGHT+IEyQzZZOiwJg+/6I3K2YT9t6bJeI302y/YEaUz3b63Qz1ZcMDIDKaOnjBX73XTsAmNZ/XjPqQ== X-Received: by 2002:adf:f20a:0:b0:33d:2473:4716 with SMTP id p10-20020adff20a000000b0033d24734716mr8088802wro.57.1709646763844; Tue, 05 Mar 2024 05:52:43 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.43 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:43 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 10/20] hw/misc/stm32l4x5_rcc: Add write protections to CR register Date: Tue, 5 Mar 2024 13:52:27 +0000 Message-Id: <20240305135237.3111642-11-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::333; envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x333.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Arnaud Minier Add write protections for the fields in the CR register. PLL configuration write protections (among others) have not been handled yet. This is planned in a future patch set. Signed-off-by: Arnaud Minier Signed-off-by: Inès Varhol Message-id: 20240303140643.81957-7-arnaud.minier@telecom-paris.fr Signed-off-by: Peter Maydell Reviewed-by: Peter Maydell --- hw/misc/stm32l4x5_rcc.c | 166 ++++++++++++++++++++++++++++------------ 1 file changed, 115 insertions(+), 51 deletions(-) diff --git a/hw/misc/stm32l4x5_rcc.c b/hw/misc/stm32l4x5_rcc.c index 2109f809e2b..bc2d63528ba 100644 --- a/hw/misc/stm32l4x5_rcc.c +++ b/hw/misc/stm32l4x5_rcc.c @@ -374,9 +374,47 @@ static void rcc_update_irq(Stm32l4x5RccState *s) } } -static void rcc_update_cr_register(Stm32l4x5RccState *s) +static void rcc_update_msi(Stm32l4x5RccState *s, uint32_t previous_value) +{ + uint32_t val; + + static const uint32_t msirange[] = { + 100000, 200000, 400000, 800000, 1000000, 2000000, + 4000000, 8000000, 16000000, 24000000, 32000000, 48000000 + }; + /* MSIRANGE and MSIRGSEL */ + val = extract32(s->cr, R_CR_MSIRGSEL_SHIFT, R_CR_MSIRGSEL_LENGTH); + if (val) { + /* MSIRGSEL is set, use the MSIRANGE field */ + val = extract32(s->cr, R_CR_MSIRANGE_SHIFT, R_CR_MSIRANGE_LENGTH); + } else { + /* MSIRGSEL is not set, use the MSISRANGE field */ + val = extract32(s->csr, R_CSR_MSISRANGE_SHIFT, R_CSR_MSISRANGE_LENGTH); + } + + if (val < ARRAY_SIZE(msirange)) { + clock_update_hz(s->msi_rc, msirange[val]); + } else { + /* + * There is a hardware write protection if the value is out of bound. + * Restore the previous value. + */ + s->cr = (s->cr & ~R_CSR_MSISRANGE_MASK) | + (previous_value & R_CSR_MSISRANGE_MASK); + } +} + +/* + * TODO: Add write-protection for all registers: + * DONE: CR + */ + +static void rcc_update_cr_register(Stm32l4x5RccState *s, uint32_t previous_value) { int val; + const RccClockMuxSource current_pll_src = + CLOCK_MUX_INIT_INFO[RCC_CLOCK_MUX_PLL_INPUT].src_mapping[ + s->clock_muxes[RCC_CLOCK_MUX_PLL_INPUT].src]; /* PLLSAI2ON and update PLLSAI2RDY */ val = FIELD_EX32(s->cr, CR, PLLSAI2ON); @@ -396,77 +434,101 @@ static void rcc_update_cr_register(Stm32l4x5RccState *s) s->cifr |= R_CIFR_PLLSAI1RDYF_MASK; } - /* PLLON and update PLLRDY */ + /* + * PLLON and update PLLRDY + * PLLON cannot be reset if the PLL clock is used as the system clock. + */ val = FIELD_EX32(s->cr, CR, PLLON); - pll_set_enable(&s->plls[RCC_PLL_PLL], val); - s->cr = (s->cr & ~R_CR_PLLRDY_MASK) | - (val << R_CR_PLLRDY_SHIFT); - if (s->cier & R_CIER_PLLRDYIE_MASK) { - s->cifr |= R_CIFR_PLLRDYF_MASK; + if (FIELD_EX32(s->cfgr, CFGR, SWS) != 0b11) { + pll_set_enable(&s->plls[RCC_PLL_PLL], val); + s->cr = (s->cr & ~R_CR_PLLRDY_MASK) | + (val << R_CR_PLLRDY_SHIFT); + if (s->cier & R_CIER_PLLRDYIE_MASK) { + s->cifr |= R_CIFR_PLLRDYF_MASK; + } + } else { + s->cr |= R_CR_PLLON_MASK; } /* CSSON: TODO */ /* HSEBYP: TODO */ - /* HSEON and update HSERDY */ + /* + * HSEON and update HSERDY. + * HSEON cannot be reset if the HSE oscillator is used directly or + * indirectly as the system clock. + */ val = FIELD_EX32(s->cr, CR, HSEON); - s->cr = (s->cr & ~R_CR_HSERDY_MASK) | - (val << R_CR_HSERDY_SHIFT); - if (val) { - clock_update_hz(s->hse, s->hse_frequency); - if (s->cier & R_CIER_HSERDYIE_MASK) { - s->cifr |= R_CIFR_HSERDYF_MASK; + if (FIELD_EX32(s->cfgr, CFGR, SWS) != 0b10 && + current_pll_src != RCC_CLOCK_MUX_SRC_HSE) { + s->cr = (s->cr & ~R_CR_HSERDY_MASK) | + (val << R_CR_HSERDY_SHIFT); + if (val) { + clock_update_hz(s->hse, s->hse_frequency); + if (s->cier & R_CIER_HSERDYIE_MASK) { + s->cifr |= R_CIFR_HSERDYF_MASK; + } + } else { + clock_update(s->hse, 0); } } else { - clock_update(s->hse, 0); + s->cr |= R_CR_HSEON_MASK; } /* HSIAFS: TODO*/ /* HSIKERON: TODO*/ - /* HSION and update HSIRDY*/ - val = FIELD_EX32(s->cr, CR, HSION); - s->cr = (s->cr & ~R_CR_HSIRDY_MASK) | - (val << R_CR_HSIRDY_SHIFT); - if (val) { + /* + * HSION and update HSIRDY + * HSION is set by hardware if the HSI16 is used directly + * or indirectly as system clock. + */ + if (FIELD_EX32(s->cfgr, CFGR, SWS) == 0b01 || + current_pll_src == RCC_CLOCK_MUX_SRC_HSI) { + s->cr |= (R_CR_HSION_MASK | R_CR_HSIRDY_MASK); clock_update_hz(s->hsi16_rc, HSI_FRQ); if (s->cier & R_CIER_HSIRDYIE_MASK) { s->cifr |= R_CIFR_HSIRDYF_MASK; } } else { - clock_update(s->hsi16_rc, 0); + val = FIELD_EX32(s->cr, CR, HSION); + if (val) { + clock_update_hz(s->hsi16_rc, HSI_FRQ); + s->cr |= R_CR_HSIRDY_MASK; + if (s->cier & R_CIER_HSIRDYIE_MASK) { + s->cifr |= R_CIFR_HSIRDYF_MASK; + } + } else { + clock_update(s->hsi16_rc, 0); + s->cr &= ~R_CR_HSIRDY_MASK; + } } - static const uint32_t msirange[] = { - 100000, 200000, 400000, 800000, 1000000, 2000000, - 4000000, 8000000, 16000000, 24000000, 32000000, 48000000 - }; - /* MSIRANGE and MSIRGSEL */ - val = FIELD_EX32(s->cr, CR, MSIRGSEL); - if (val) { - /* MSIRGSEL is set, use the MSIRANGE field */ - val = FIELD_EX32(s->cr, CR, MSIRANGE); + /* MSIPLLEN: TODO */ + + /* + * MSION and update MSIRDY + * Set by hardware when used directly or indirectly as system clock. + */ + if (FIELD_EX32(s->cfgr, CFGR, SWS) == 0b00 || + current_pll_src == RCC_CLOCK_MUX_SRC_MSI) { + s->cr |= (R_CR_MSION_MASK | R_CR_MSIRDY_MASK); + if (!(previous_value & R_CR_MSION_MASK) && (s->cier & R_CIER_MSIRDYIE_MASK)) { + s->cifr |= R_CIFR_MSIRDYF_MASK; + } + rcc_update_msi(s, previous_value); } else { - /* MSIRGSEL is not set, use the MSISRANGE field */ - val = FIELD_EX32(s->csr, CSR, MSISRANGE); - } - - if (val < ARRAY_SIZE(msirange)) { - clock_update_hz(s->msi_rc, msirange[val]); - } else { - clock_update_hz(s->msi_rc, MSI_DEFAULT_FRQ); - /* TODO: there is a write protection if the value is out of bound, - implement that instead of setting the default */ - } - - /* MSIPLLEN */ - - /* MSION and update MSIRDY */ - val = FIELD_EX32(s->cr, CR, MSION); - s->cr = (s->cr & ~R_CR_MSIRDY_MASK) | - (val << R_CR_MSIRDY_SHIFT); - if (s->cier & R_CIER_MSIRDYIE_MASK) { - s->cifr |= R_CIFR_MSIRDYF_MASK; + val = FIELD_EX32(s->cr, CR, MSION); + if (val) { + s->cr |= R_CR_MSIRDY_MASK; + rcc_update_msi(s, previous_value); + if (s->cier & R_CIER_MSIRDYIE_MASK) { + s->cifr |= R_CIFR_MSIRDYF_MASK; + } + } else { + s->cr &= ~R_CR_MSIRDY_MASK; + clock_update(s->msi_rc, 0); + } } rcc_update_irq(s); } @@ -991,15 +1053,17 @@ static void stm32l4x5_rcc_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { Stm32l4x5RccState *s = opaque; + uint32_t previous_value = 0; const uint32_t value = val64; trace_stm32l4x5_rcc_write(addr, value); switch (addr) { case A_CR: + previous_value = s->cr; s->cr = (s->cr & CR_READ_SET_MASK) | (value & (CR_READ_SET_MASK | ~CR_READ_ONLY_MASK)); - rcc_update_cr_register(s); + rcc_update_cr_register(s, previous_value); break; case A_ICSCR: s->icscr = value & ~ICSCR_READ_ONLY_MASK; From patchwork Tue Mar 5 13:52:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582478 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 571DEC54E41 for ; Tue, 5 Mar 2024 13:56:11 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVEy-00021W-4a; Tue, 05 Mar 2024 08:53:56 -0500 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 1rhVDx-0000x2-8U for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:53:06 -0500 Received: from mail-wr1-x42f.google.com ([2a00:1450:4864:20::42f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDp-0005xv-Qw for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:52 -0500 Received: by mail-wr1-x42f.google.com with SMTP id ffacd0b85a97d-33d509ab80eso374434f8f.3 for ; Tue, 05 Mar 2024 05:52:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646764; x=1710251564; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=bVTp8B0By/XCvljzAaX1UWqxflzJT37GS6jVUdEA9Gw=; b=G9EfxxhXb5qWrhLoWn7ZE9ovTfX6ezQG75EHUNMeRP4BahBvt3T5mipTkV37YtwTwa m/I2OlUsINIo4mzSfQ8HjfbB+QywQqN21rHAhIJaR+EsvT8Nvh/HPH7OsbPOhluE0DnG R2wi7pIh5JziBFrFYsl6v6fVSnwdiTWRPbCZ5W/IqDjQ78LtD4W9fQM+2q1RbVXIbxPk +x7ryHtjEyKFVsKvk7c3eXM2irFZYjHeJox71tqRRcIjwerbtafd+wMxSL9hf3yU7X86 FIK9o1efFzl7oEg/kGHR05bwK92FZHFe2g4g5i6gFHGfXRAuYkLVh8Ndg2aCAn4dv+9d sMrg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646764; x=1710251564; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=bVTp8B0By/XCvljzAaX1UWqxflzJT37GS6jVUdEA9Gw=; b=LJXPj/V9JSVH21qY4ZpuYQuvfHcz+mfmr91mImjQD45H19SFqc62+JPrcDQXIwzk+n Nvpc+novlAS/0380hMBuFQgR/P74WaLeiLAfg9heiITWwIcHR8Vdo4BFKFdHvh0VQ7ct OLki74ZpJ9nMP+enNTpRtzXdeSmSquydXFOcVEG8LNYfs71DVLasWj7DS5OQfgZhahTR GH+z/lOkfdQfIuz3HP+WX34DU3iEirp8+hKuzRj5nJUcIynBlJhThPn04lAMo5HAOb7m 8gxzboETNS6bD/imHmCVTA3mWU5rxWJnVqKcQy5TrOJWFTn/m2eNlRrEowcA5Rv4t4Aq 917g== X-Gm-Message-State: AOJu0YzqvTAN22RTp4VNGujnywgfFoFAO51+GXQMkMns9XM+4SPO2am2 G06st48u+4C3JBO09y6e7OamkyivhuzZ8/2vgEHPS+PYT+a6gK6yhGHiI8fZ/a+EuQEGMxp5c8X f X-Google-Smtp-Source: AGHT+IFT0gcBOVZIIdD3Sptm6aZQ+DLOPgb1h1fx53GZFmbsvvflAd5Y9kOzYKOtRub1G09J+rhL+g== X-Received: by 2002:adf:9cc8:0:b0:33e:2155:6da4 with SMTP id h8-20020adf9cc8000000b0033e21556da4mr8901603wre.55.1709646764279; Tue, 05 Mar 2024 05:52:44 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.43 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:44 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 11/20] hw/arm/stm32l4x5_soc.c: Use the RCC Sysclk Date: Tue, 5 Mar 2024 13:52:28 +0000 Message-Id: <20240305135237.3111642-12-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::42f; envelope-from=peter.maydell@linaro.org; helo=mail-wr1-x42f.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Arnaud Minier Now that we can generate reliable clock frequencies from the RCC, remove the hacky definition of the sysclk in the b_l475e_iot01a initialisation code and use the correct RCC clock. Signed-off-by: Arnaud Minier Signed-off-by: Inès Varhol Acked-by: Alistair Francis Reviewed-by: Peter Maydell Message-id: 20240303140643.81957-8-arnaud.minier@telecom-paris.fr Signed-off-by: Peter Maydell --- include/hw/arm/stm32l4x5_soc.h | 3 --- hw/arm/b-l475e-iot01a.c | 10 +--------- hw/arm/stm32l4x5_soc.c | 33 ++++----------------------------- 3 files changed, 5 insertions(+), 41 deletions(-) diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h index 0b4f97e240e..af67b089efc 100644 --- a/include/hw/arm/stm32l4x5_soc.h +++ b/include/hw/arm/stm32l4x5_soc.h @@ -54,9 +54,6 @@ struct Stm32l4x5SocState { MemoryRegion sram2; MemoryRegion flash; MemoryRegion flash_alias; - - Clock *sysclk; - Clock *refclk; }; struct Stm32l4x5SocClass { diff --git a/hw/arm/b-l475e-iot01a.c b/hw/arm/b-l475e-iot01a.c index 6ecde2db15c..d862aa43fc3 100644 --- a/hw/arm/b-l475e-iot01a.c +++ b/hw/arm/b-l475e-iot01a.c @@ -26,27 +26,19 @@ #include "qapi/error.h" #include "hw/boards.h" #include "hw/qdev-properties.h" -#include "hw/qdev-clock.h" #include "qemu/error-report.h" #include "hw/arm/stm32l4x5_soc.h" #include "hw/arm/boot.h" -/* Main SYSCLK frequency in Hz (80MHz) */ -#define MAIN_SYSCLK_FREQ_HZ 80000000ULL +/* B-L475E-IOT01A implementation is derived from netduinoplus2 */ static void b_l475e_iot01a_init(MachineState *machine) { const Stm32l4x5SocClass *sc; DeviceState *dev; - Clock *sysclk; - - /* This clock doesn't need migration because it is fixed-frequency */ - sysclk = clock_new(OBJECT(machine), "SYSCLK"); - clock_set_hz(sysclk, MAIN_SYSCLK_FREQ_HZ); dev = qdev_new(TYPE_STM32L4X5XG_SOC); object_property_add_child(OBJECT(machine), "soc", OBJECT(dev)); - qdev_connect_clock_in(dev, "sysclk", sysclk); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sc = STM32L4X5_SOC_GET_CLASS(dev); diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c index cb147050091..bf9926057be 100644 --- a/hw/arm/stm32l4x5_soc.c +++ b/hw/arm/stm32l4x5_soc.c @@ -110,9 +110,6 @@ static void stm32l4x5_soc_initfn(Object *obj) } object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_STM32L4X5_SYSCFG); object_initialize_child(obj, "rcc", &s->rcc, TYPE_STM32L4X5_RCC); - - s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0); - s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0); } static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp) @@ -124,30 +121,6 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp) DeviceState *armv7m; SysBusDevice *busdev; - /* - * We use s->refclk internally and only define it with qdev_init_clock_in() - * so it is correctly parented and not leaked on an init/deinit; it is not - * intended as an externally exposed clock. - */ - if (clock_has_source(s->refclk)) { - error_setg(errp, "refclk clock must not be wired up by the board code"); - return; - } - - if (!clock_has_source(s->sysclk)) { - error_setg(errp, "sysclk clock must be wired up by the board code"); - return; - } - - /* - * TODO: ideally we should model the SoC RCC and its ability to - * change the sysclk frequency and define different sysclk sources. - */ - - /* The refclk always runs at frequency HCLK / 8 */ - clock_set_mul_div(s->refclk, 8, 1); - clock_set_source(s->refclk, s->sysclk); - if (!memory_region_init_rom(&s->flash, OBJECT(dev_soc), "flash", sc->flash_size, errp)) { return; @@ -177,8 +150,10 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp) qdev_prop_set_uint32(armv7m, "num-prio-bits", 4); qdev_prop_set_string(armv7m, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4")); qdev_prop_set_bit(armv7m, "enable-bitband", true); - qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk); - qdev_connect_clock_in(armv7m, "refclk", s->refclk); + qdev_connect_clock_in(armv7m, "cpuclk", + qdev_get_clock_out(DEVICE(&(s->rcc)), "cortex-fclk-out")); + qdev_connect_clock_in(armv7m, "refclk", + qdev_get_clock_out(DEVICE(&(s->rcc)), "cortex-refclk-out")); object_property_set_link(OBJECT(&s->armv7m), "memory", OBJECT(system_memory), &error_abort); if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) { From patchwork Tue Mar 5 13:52:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582475 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 93A66C54E41 for ; Tue, 5 Mar 2024 13:54:55 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVEy-00029t-TK; Tue, 05 Mar 2024 08:53:56 -0500 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 1rhVE0-0000xR-F6 for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:53:09 -0500 Received: from mail-wr1-x435.google.com ([2a00:1450:4864:20::435]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDq-0005y2-GE for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:56 -0500 Received: by mail-wr1-x435.google.com with SMTP id ffacd0b85a97d-33e17fc5aceso2809900f8f.0 for ; Tue, 05 Mar 2024 05:52:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646765; x=1710251565; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=vOhlpnaKiIrRTqIJyTUzsqtsVnUpM/KK2Ic7nx0Sh9Y=; b=yOuA8s/dbp0qDXLV5edxebPSQDbt8GK3tVkoZxqruEFzSoz9n8o8/frg3qa6yAYKSE EcerqsSzaDAjJZAzy8AAfASXrhv3q/kiuJqHcptFUTanKjLpMPCLzJ+CIDx5eTEZrTh/ KEasIy6i5KFGejRfm0TD8nJvD4YjTFrUUOnGUn4ZU4HMmLYzIYRJMbPEzCPDn3OUhfRM oQxUMbvj5ChfP83pJ2uKEPeS3wWs89ZAiHN546DuhwYORNvVWK9Cky0v8s/pab4dOlKg Upa3z2Ekx9oTdaAAwcL/+zqKx92Q2prHj40wHAdYNK6sw3KrHtyuKSh0fVLUbdjA50+d oGFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646765; x=1710251565; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vOhlpnaKiIrRTqIJyTUzsqtsVnUpM/KK2Ic7nx0Sh9Y=; b=ilIxBsQ01+wMoApC5MuVmJlpfmzRRy6iAk/udu9lksGJSSyRU4Ofu8oLjDBbwvRrpE eZAOp17Zy39IV5GaWUQGA83jK0o/QAmmbUCyAcQTzp/ks5BVWSUF5Wu3YZroKZV3mP7b iiBjXqkNMprXavM71T2Ez7cspsAbeJ6H+FYGohbdqzhAKQB+D68qic/1fNCMFIccZRX0 3VhMKYsGqz4rJay5mCgeTu6CrFMfN+D/k58kywweVtDQZ683WZGqIIxhyg8k+YG8fLUJ 3AQ0+W2Sk8VQgqZvcXWZ6cKbGS/mvaphNzDRSicrBbgebhxP+BpUmXkkNEY9RXWtqIEr XXzA== X-Gm-Message-State: AOJu0YyT0f+a8J5t/7f2b/nGNp4+qC+ApqmrTOSaKO7hel/WwjngqTzQ HCnW/nCUf+Q4e7bfodN/a72rMZ+OOoH28JFsBm9lurLouQmXH1vSEsiZ3AldyOBUtDLfEx/sTds l X-Google-Smtp-Source: AGHT+IH81vnmpCX1h++MpYkRjnTasMN6vldyHEubxFyBF4bpo7tVC33tkdtResnTJpOCwZTHjBZ0DA== X-Received: by 2002:adf:9dc9:0:b0:33e:2219:9804 with SMTP id q9-20020adf9dc9000000b0033e22199804mr1922498wre.25.1709646764694; Tue, 05 Mar 2024 05:52:44 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.44 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:44 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 12/20] tests/qtest/stm32l4x5_rcc-test.c: Add tests for the STM32L4x5_RCC Date: Tue, 5 Mar 2024 13:52:29 +0000 Message-Id: <20240305135237.3111642-13-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::435; envelope-from=peter.maydell@linaro.org; helo=mail-wr1-x435.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Arnaud Minier Tests: - the ability to change the sysclk of the device - the ability to enable/disable/configure the PLLs - if the clock multiplexers work - the register flags and the generation of irqs Signed-off-by: Arnaud Minier Signed-off-by: Inès Varhol Acked-by: Thomas Huth Message-id: 20240303140643.81957-9-arnaud.minier@telecom-paris.fr Signed-off-by: Peter Maydell Reviewed-by: Peter Maydell --- tests/qtest/stm32l4x5_rcc-test.c | 189 +++++++++++++++++++++++++++++++ tests/qtest/meson.build | 3 +- 2 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 tests/qtest/stm32l4x5_rcc-test.c diff --git a/tests/qtest/stm32l4x5_rcc-test.c b/tests/qtest/stm32l4x5_rcc-test.c new file mode 100644 index 00000000000..d927c655d13 --- /dev/null +++ b/tests/qtest/stm32l4x5_rcc-test.c @@ -0,0 +1,189 @@ +/* + * QTest testcase for STM32L4x5_RCC + * + * Copyright (c) 2023 Arnaud Minier + * Copyright (c) 2023 Inès Varhol + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "hw/registerfields.h" +#include "libqtest-single.h" +#include "hw/misc/stm32l4x5_rcc_internals.h" + +#define RCC_BASE_ADDR 0x40021000 +#define NVIC_ISER 0xE000E100 +#define NVIC_ISPR 0xE000E200 +#define NVIC_ICPR 0xE000E280 +#define RCC_IRQ 5 + +static void enable_nvic_irq(unsigned int n) +{ + writel(NVIC_ISER, 1 << n); +} + +static void unpend_nvic_irq(unsigned int n) +{ + writel(NVIC_ICPR, 1 << n); +} + +static bool check_nvic_pending(unsigned int n) +{ + return readl(NVIC_ISPR) & (1 << n); +} + +static void rcc_writel(unsigned int offset, uint32_t value) +{ + writel(RCC_BASE_ADDR + offset, value); +} + +static uint32_t rcc_readl(unsigned int offset) +{ + return readl(RCC_BASE_ADDR + offset); +} + +static void test_init_msi(void) +{ + /* MSIRANGE can be set only when MSI is OFF or READY */ + rcc_writel(A_CR, R_CR_MSION_MASK); + /* Wait until MSI is stable */ + g_assert_true((rcc_readl(A_CR) & R_CR_MSIRDY_MASK) == R_CR_MSIRDY_MASK); + /* TODO find a way to test MSI value */ +} + +static void test_set_msi_as_sysclk(void) +{ + /* Clocking from MSI, in case MSI was not the default source */ + rcc_writel(A_CFGR, 0); + /* Wait until MSI is selected and stable */ + g_assert_true((rcc_readl(A_CFGR) & R_CFGR_SWS_MASK) == 0); +} + +static void test_init_pll(void) +{ + uint32_t value; + + /* + * Update PLL and set MSI as the source clock. + * PLLM = 1 --> 000 + * PLLN = 40 --> 40 + * PPLLR = 2 --> 00 + * PLLDIV = unused, PLLP = unused (SAI3), PLLQ = unused (48M1) + * SRC = MSI --> 01 + */ + rcc_writel(A_PLLCFGR, R_PLLCFGR_PLLREN_MASK | + (40 << R_PLLCFGR_PLLN_SHIFT) | + (0b01 << R_PLLCFGR_PLLSRC_SHIFT)); + + /* PLL activation */ + value = rcc_readl(A_CR); + rcc_writel(A_CR, value | R_CR_PLLON_MASK); + + /* Waiting for PLL lock. */ + g_assert_true((rcc_readl(A_CR) & R_CR_PLLRDY_MASK) == R_CR_PLLRDY_MASK); + + /* Switches on the PLL clock source */ + value = rcc_readl(A_CFGR); + rcc_writel(A_CFGR, (value & ~R_CFGR_SW_MASK) | + (0b11 << R_CFGR_SW_SHIFT)); + + /* Wait until SYSCLK is stable. */ + g_assert_true((rcc_readl(A_CFGR) & R_CFGR_SWS_MASK) == + (0b11 << R_CFGR_SWS_SHIFT)); +} + +static void test_activate_lse(void) +{ + /* LSE activation, no LSE Bypass */ + rcc_writel(A_BDCR, R_BDCR_LSEDRV_MASK | R_BDCR_LSEON_MASK); + g_assert_true((rcc_readl(A_BDCR) & R_BDCR_LSERDY_MASK) == R_BDCR_LSERDY_MASK); +} + +static void test_irq(void) +{ + enable_nvic_irq(RCC_IRQ); + + rcc_writel(A_CIER, R_CIER_LSIRDYIE_MASK); + rcc_writel(A_CSR, R_CSR_LSION_MASK); + g_assert_true(check_nvic_pending(RCC_IRQ)); + rcc_writel(A_CICR, R_CICR_LSIRDYC_MASK); + unpend_nvic_irq(RCC_IRQ); + + rcc_writel(A_CIER, R_CIER_LSERDYIE_MASK); + rcc_writel(A_BDCR, R_BDCR_LSEON_MASK); + g_assert_true(check_nvic_pending(RCC_IRQ)); + rcc_writel(A_CICR, R_CICR_LSERDYC_MASK); + unpend_nvic_irq(RCC_IRQ); + + /* + * MSI has been enabled by previous tests, + * shouln't generate an interruption. + */ + rcc_writel(A_CIER, R_CIER_MSIRDYIE_MASK); + rcc_writel(A_CR, R_CR_MSION_MASK); + g_assert_false(check_nvic_pending(RCC_IRQ)); + + rcc_writel(A_CIER, R_CIER_HSIRDYIE_MASK); + rcc_writel(A_CR, R_CR_HSION_MASK); + g_assert_true(check_nvic_pending(RCC_IRQ)); + rcc_writel(A_CICR, R_CICR_HSIRDYC_MASK); + unpend_nvic_irq(RCC_IRQ); + + rcc_writel(A_CIER, R_CIER_HSERDYIE_MASK); + rcc_writel(A_CR, R_CR_HSEON_MASK); + g_assert_true(check_nvic_pending(RCC_IRQ)); + rcc_writel(A_CICR, R_CICR_HSERDYC_MASK); + unpend_nvic_irq(RCC_IRQ); + + /* + * PLL has been enabled by previous tests, + * shouln't generate an interruption. + */ + rcc_writel(A_CIER, R_CIER_PLLRDYIE_MASK); + rcc_writel(A_CR, R_CR_PLLON_MASK); + g_assert_false(check_nvic_pending(RCC_IRQ)); + + rcc_writel(A_CIER, R_CIER_PLLSAI1RDYIE_MASK); + rcc_writel(A_CR, R_CR_PLLSAI1ON_MASK); + g_assert_true(check_nvic_pending(RCC_IRQ)); + rcc_writel(A_CICR, R_CICR_PLLSAI1RDYC_MASK); + unpend_nvic_irq(RCC_IRQ); + + rcc_writel(A_CIER, R_CIER_PLLSAI2RDYIE_MASK); + rcc_writel(A_CR, R_CR_PLLSAI2ON_MASK); + g_assert_true(check_nvic_pending(RCC_IRQ)); + rcc_writel(A_CICR, R_CICR_PLLSAI2RDYC_MASK); + unpend_nvic_irq(RCC_IRQ); +} + +int main(int argc, char **argv) +{ + int ret; + + g_test_init(&argc, &argv, NULL); + g_test_set_nonfatal_assertions(); + /* + * These test separately that we can enable the plls, change the sysclk, + * and enable different devices. + * They are dependent on one another. + * We assume that all operations that would take some time to have an effect + * (e.g. changing the PLL frequency) are done instantaneously. + */ + qtest_add_func("stm32l4x5/rcc/init_msi", test_init_msi); + qtest_add_func("stm32l4x5/rcc/set_msi_as_sysclk", + test_set_msi_as_sysclk); + qtest_add_func("stm32l4x5/rcc/activate_lse", test_activate_lse); + qtest_add_func("stm32l4x5/rcc/init_pll", test_init_pll); + + qtest_add_func("stm32l4x5/rcc/irq", test_irq); + + qtest_start("-machine b-l475e-iot01a"); + ret = g_test_run(); + qtest_end(); + + return ret; +} diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index bdc8bba7a98..31b9f4ede47 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -203,7 +203,8 @@ qtests_aspeed = \ qtests_stm32l4x5 = \ ['stm32l4x5_exti-test', - 'stm32l4x5_syscfg-test'] + 'stm32l4x5_syscfg-test', + 'stm32l4x5_rcc-test'] qtests_arm = \ (config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \ From patchwork Tue Mar 5 13:52:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582471 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 18930C54E41 for ; Tue, 5 Mar 2024 13:54:27 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVF0-0002Hr-DS; Tue, 05 Mar 2024 08:53:58 -0500 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 1rhVDx-0000x8-Qk for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:53:06 -0500 Received: from mail-wr1-x431.google.com ([2a00:1450:4864:20::431]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDq-0005y6-HH for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:53 -0500 Received: by mail-wr1-x431.google.com with SMTP id ffacd0b85a97d-33d90dfe73cso3056036f8f.0 for ; Tue, 05 Mar 2024 05:52:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646765; x=1710251565; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=fdVthnX6h3tPLZ/up3/0m51wR74fwYyRgEQm5STtv5M=; b=lsi9HgN5xeuAdoqgoLYZekjfyQPOfAz9142+IDLLrMfvpEackRNDvBneEI8UXCjyyf J8KeD9moVWgLS0Rov+oQgFKqvpBuevvzE3q37N3jpfl78YXvYH/WtbUfkA1Pg3vI4Wfn kX0piJ8J+CUp9UKOxGcP91KqJJq1kn18go1SuFIcIeAXTs1D33nQxDXmFRRbggu+CN/a tbzCAMOl+TkpKTN3w4/oejdieSMwkKLP1JmMhcnnwfxU5kUYzMo/FPvvLEoQP3VA4Dgx KKcZ1skRqlHQO6+gjObdrSkdOJfITv7Eazf1NzZI+jQrCIPliQ/kKDhjjAbOALyPfR0P rltg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646765; x=1710251565; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=fdVthnX6h3tPLZ/up3/0m51wR74fwYyRgEQm5STtv5M=; b=hkL26FuDIgiYlWJQPDgNDS5Hq53Xb8dpl1fepptmnzF0Dqi1Es/5ej+ND0m+RHehAe dTRdnBDt8c/JK5s/5WlN8fPth4GxsNNglwrjtM6BnKTZoxpQleIuneubcHNBKSB+um0y hl+dJqF4LIBFrOPB1zagE3M2OFFfY1FXDGTQSUFe3Tx9VvRDxJWSvCuT6X/zsNqrKGrg 4lNVUTrUY51Apc/oqEB4yfrkB20nKvOqDio75JqAXTwHonz9w4X7S1XJJSBPnupTiOaI 4KlaYo/V8jak6nEXnIcUb2zK3O8LprnknWsYnhiCvs5dinvdfXVBpivCMGZzJ7l4g4wD 4oEg== X-Gm-Message-State: AOJu0YxysWMSYZKCBDpgVMWdPnz2jeoCvoMnm9uvOZihtNO6FPeomSgS eOZ1RAmopJtzmlFyzr5fE9T8o7ay8xfUJV2LExCZ4RPMG3inufxDZpsr1QOjOBdXPwrOxhX0tuK K X-Google-Smtp-Source: AGHT+IF+TSwvseQswoO+IT09xQXNmdexvZAq3Ve8Q8uhYS9atC7/sfsEn87Z8xIEBtDuSDwqV5EfNA== X-Received: by 2002:adf:b646:0:b0:33e:1f2b:8cc5 with SMTP id i6-20020adfb646000000b0033e1f2b8cc5mr3250857wre.0.1709646765138; Tue, 05 Mar 2024 05:52:45 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.44 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:44 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 13/20] target/arm: Support 32-byte alignment in pow2_align Date: Tue, 5 Mar 2024 13:52:30 +0000 Message-Id: <20240305135237.3111642-14-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::431; envelope-from=peter.maydell@linaro.org; helo=mail-wr1-x431.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Richard Henderson Now that we have removed TARGET_PAGE_BITS_MIN-6 from TLB_FLAGS_MASK, we can test for 32-byte alignment. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20240301204110.656742-2-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/tcg/translate.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c index f947c62c6be..c8a24706750 100644 --- a/target/arm/tcg/translate.c +++ b/target/arm/tcg/translate.c @@ -900,13 +900,7 @@ static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var) MemOp pow2_align(unsigned i) { static const MemOp mop_align[] = { - 0, MO_ALIGN_2, MO_ALIGN_4, MO_ALIGN_8, MO_ALIGN_16, - /* - * FIXME: TARGET_PAGE_BITS_MIN affects TLB_FLAGS_MASK such - * that 256-bit alignment (MO_ALIGN_32) cannot be supported: - * see get_alignment_bits(). Enforce only 128-bit alignment for now. - */ - MO_ALIGN_16 + 0, MO_ALIGN_2, MO_ALIGN_4, MO_ALIGN_8, MO_ALIGN_16, MO_ALIGN_32 }; g_assert(i < ARRAY_SIZE(mop_align)); return mop_align[i]; From patchwork Tue Mar 5 13:52:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582482 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 A51D2C54E41 for ; Tue, 5 Mar 2024 13:57:53 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVEx-0001qZ-3c; Tue, 05 Mar 2024 08:53:55 -0500 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 1rhVE0-0000xO-9L for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:53:07 -0500 Received: from mail-wr1-x429.google.com ([2a00:1450:4864:20::429]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDr-0005yE-Gy for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:54 -0500 Received: by mail-wr1-x429.google.com with SMTP id ffacd0b85a97d-33d146737e6so4410407f8f.0 for ; Tue, 05 Mar 2024 05:52:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646766; x=1710251566; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=wRXrQVhloM+AHj0Ylfddl3Ax3AHnB24xciIaK6golUE=; b=EbVoc12S37NzYfJ5YNBFTxoGekvHII/FmDhKVsrVxE7CucYK9eaX41uoh3RAy/xDbI kd/FhZ2xhAjH860zIMPU5WSq1mKoTvDrIRy5rUPMQ7Ti4z9Yfx2B3Jw5gw3OBd1lZn5W lOnAaOJi2/dgLDDH8uK9UQIqNm2gE52+uEeqBrb0OxtIDrvRyOdHvi+Qg3rezx8JrQVO ha1Gr6vkJGBhpsDSg81csl5aBu1SH5KCOwI8sMPa6RhikFSYbyvKAplTSZi3dO3ZPiDs bTbwCDtkei78XaX5d3TJ108miVqnleGwi1Xyrkp4CcEeYvAN/pB2VJdFKDvOeBHbOFrA J8Fw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646766; x=1710251566; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=wRXrQVhloM+AHj0Ylfddl3Ax3AHnB24xciIaK6golUE=; b=FFe4Q2NM1JQ14ZMO24dQq4eBRv7bZrZsU7H2uPxxmI/OiaB1/ldYuYOkuJ/anJmtk3 /inmI1/pneF3HSvFBdA/ou8t5MIQtxoTpzbYvoJDh2nK5YmU9B416WQJ7HbqBnHBSiRY sF4pLbKC7FLwxHZEUFG2lVe3Qf4PLhFu/jeFpo45qN73n0YO6YC+q97kf98EkRNAoJ2d jf0QtQqkK8mreG2FAip7f6vR/2/meFV0T4Cc9XQuD3QzDY9c94tXnwjM7DAR76ttt/q4 98i6Ci62lQn8RjhO7aYRuNovlbblg22WledEA1plcCIx8ZOGYnE/r8SIS7qlNFcnPK+e z+9w== X-Gm-Message-State: AOJu0Yy1K5ZWsNDomT7jAVpEzcpndlqCH3SDtfxYbyOLV86FkfJ3VLof s4r95DmWAAMs5cQU0c5AGFQoH2DDRxZp0lv9ISB/wDUTHkMhq1DCm6svrDE53ffQ7x0cFUEPngf 0 X-Google-Smtp-Source: AGHT+IGyKh10ll3bg+lQKB76wb6N3uzN8pqSyxohAwgPbLwxizHku9+3rQl1w2MaL7t8OYoHEZUzmA== X-Received: by 2002:a05:6000:110c:b0:33d:22f4:179b with SMTP id z12-20020a056000110c00b0033d22f4179bmr8537054wrw.21.1709646766009; Tue, 05 Mar 2024 05:52:46 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.45 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:45 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 14/20] exec/memattrs: Remove target_tlb_bit* Date: Tue, 5 Mar 2024 13:52:31 +0000 Message-Id: <20240305135237.3111642-15-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::429; envelope-from=peter.maydell@linaro.org; helo=mail-wr1-x429.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Richard Henderson These fields are no longer used since 937f224559. Target specific extensions to the page tables should be done with TARGET_PAGE_ENTRY_EXTRA. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Message-id: 20240301204110.656742-3-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- include/exec/memattrs.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h index d04170aa27a..afa885f9830 100644 --- a/include/exec/memattrs.h +++ b/include/exec/memattrs.h @@ -54,16 +54,6 @@ typedef struct MemTxAttrs { unsigned int requester_id:16; /* Invert endianness for this page */ unsigned int byte_swap:1; - /* - * The following are target-specific page-table bits. These are not - * related to actual memory transactions at all. However, this structure - * is part of the tlb_fill interface, cached in the cputlb structure, - * and has unused bits. These fields will be read by target-specific - * helpers using env->iotlb[mmu_idx][tlb_index()].attrs.target_tlb_bitN. - */ - unsigned int target_tlb_bit0 : 1; - unsigned int target_tlb_bit1 : 1; - unsigned int target_tlb_bit2 : 1; } MemTxAttrs; /* Bus masters which don't specify any attributes will get this, From patchwork Tue Mar 5 13:52:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582465 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 2AFB3C54E41 for ; Tue, 5 Mar 2024 13:53:56 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVEo-0001V4-Ne; Tue, 05 Mar 2024 08:53:48 -0500 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 1rhVE0-0000xP-CM for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:53:06 -0500 Received: from mail-wr1-x42b.google.com ([2a00:1450:4864:20::42b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDr-0005yL-RA for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:56 -0500 Received: by mail-wr1-x42b.google.com with SMTP id ffacd0b85a97d-33e17fc5aceso2809921f8f.0 for ; Tue, 05 Mar 2024 05:52:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646766; x=1710251566; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=vYTT5LKkD29WLg/lq++0uN/w1V7H7bdZ2aB09S5WWmU=; b=yyw65yUizfuHOcaRTiTiZvnPMkygeNYm7qBTCVjFnyZwgwFoFguRQLHoTx7qQFUiN/ ZqZrU7ss7KPD2ofYJHUhurITxsaytLIy/Nzj8qLiEHXOm+uVQRd1gCxdAbMlJoexBc7l SBZoGJios7RS6vqMliJPkl1isNU0ukc4OG3xNP2Lx3PnN1Aai+9OSJi6Db47HpilDOYS 4wI0oMRdvTJMRQ6JcEXUMh5IF6gseAVnNATimV5IinMmX7ug+J9vMRKgToY9U5L+ch1W +xpGWUjL8d8R/YbUCbf51435mPLfafbPeTxNNHRnDTsP/FDfz/P9K1A5rfZRpvcYnJ8R rg7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646766; x=1710251566; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vYTT5LKkD29WLg/lq++0uN/w1V7H7bdZ2aB09S5WWmU=; b=q4qJ8wgUpGgLnqRulAjbXHgKamDUjUikzpQ4E6roLLM2y2li3xdakmdrI3mhYQtDRq +PJiFcOg82hpevlH0D1OZGeUq2URnhFwkPjHARr3fxuBGy8uMKo84LKb/KGvs0xnZJUh g1YDF4e+cJnyyGjRx2ddrnOB90YkGWc6VYEVZyo7O8BvUfL0EY3KVcKl6WIJny9nyehO iDr6yuhFpp6Opk0KYc+pjrV4bvQrPdh598dwAdG2ZiYNTi1CJvya9rUSwGccDo53GYZ5 fwt22lb7Mm+BmTUKgntxY/FQcYJTv3JP1KCm6RWnYNel85C8IUgyiEMxhI/QPuDFeA+E ik/Q== X-Gm-Message-State: AOJu0Yx0SQswQi1L3w/VG5EIC9L/TTr77ktONeo34m+uCnmPATwApqRb TlsuRme90ytGMg3Z1ViKAfVv2mbimKJH/C9dKhr+it43sux8mb3KdSy4l506kOVBgoBlb41Mqsr u X-Google-Smtp-Source: AGHT+IH4JHeW54sIWhAbnjMSkVOGpZxbpjvvp7KrrvGgqWWP3pf2VIe0a/s0xwyBJsxvEQwfIGa82A== X-Received: by 2002:adf:c793:0:b0:33e:1651:2a04 with SMTP id l19-20020adfc793000000b0033e16512a04mr2689928wrg.8.1709646766497; Tue, 05 Mar 2024 05:52:46 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.46 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:46 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 15/20] accel/tcg: Add tlb_fill_flags to CPUTLBEntryFull Date: Tue, 5 Mar 2024 13:52:32 +0000 Message-Id: <20240305135237.3111642-16-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::42b; envelope-from=peter.maydell@linaro.org; helo=mail-wr1-x42b.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Richard Henderson Allow the target to set tlb flags to apply to all of the comparators. Remove MemTxAttrs.byte_swap, as the bit is not relevant to memory transactions, only the page mapping. Adjust target/sparc to set TLB_BSWAP directly. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Message-id: 20240301204110.656742-4-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- include/exec/memattrs.h | 2 -- include/hw/core/cpu.h | 3 +++ accel/tcg/cputlb.c | 5 +---- target/sparc/mmu_helper.c | 2 +- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h index afa885f9830..14cdd8d5824 100644 --- a/include/exec/memattrs.h +++ b/include/exec/memattrs.h @@ -52,8 +52,6 @@ typedef struct MemTxAttrs { unsigned int memory:1; /* Requester ID (for MSI for example) */ unsigned int requester_id:16; - /* Invert endianness for this page */ - unsigned int byte_swap:1; } MemTxAttrs; /* Bus masters which don't specify any attributes will get this, diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index d0e345419fc..ec14f74ce5d 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -230,6 +230,9 @@ typedef struct CPUTLBEntryFull { /* @lg_page_size contains the log2 of the page size. */ uint8_t lg_page_size; + /* Additional tlb flags requested by tlb_fill. */ + uint8_t tlb_fill_flags; + /* * Additional tlb flags for use by the slow path. If non-zero, * the corresponding CPUTLBEntry comparator must have TLB_FORCE_SLOW. diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 6243bcb1791..ac986cb8ea5 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1145,14 +1145,11 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx, " prot=%x idx=%d\n", addr, full->phys_addr, prot, mmu_idx); - read_flags = 0; + read_flags = full->tlb_fill_flags; if (full->lg_page_size < TARGET_PAGE_BITS) { /* Repeat the MMU check and TLB fill on every access. */ read_flags |= TLB_INVALID_MASK; } - if (full->attrs.byte_swap) { - read_flags |= TLB_BSWAP; - } is_ram = memory_region_is_ram(section->mr); is_romd = memory_region_is_romd(section->mr); diff --git a/target/sparc/mmu_helper.c b/target/sparc/mmu_helper.c index 5170a668bb4..e7b1997d54e 100644 --- a/target/sparc/mmu_helper.c +++ b/target/sparc/mmu_helper.c @@ -580,7 +580,7 @@ static int get_physical_address_data(CPUSPARCState *env, CPUTLBEntryFull *full, int do_fault = 0; if (TTE_IS_IE(env->dtlb[i].tte)) { - full->attrs.byte_swap = true; + full->tlb_fill_flags |= TLB_BSWAP; } /* access ok? */ From patchwork Tue Mar 5 13:52:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582463 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 DEC7FC54798 for ; Tue, 5 Mar 2024 13:53:49 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVEd-0001DR-Cd; Tue, 05 Mar 2024 08:53:37 -0500 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 1rhVE6-0000yE-O7 for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:53:09 -0500 Received: from mail-wr1-x432.google.com ([2a00:1450:4864:20::432]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDs-0005yP-Lt for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:56 -0500 Received: by mail-wr1-x432.google.com with SMTP id ffacd0b85a97d-33d90dfe73cso3056064f8f.0 for ; Tue, 05 Mar 2024 05:52:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646767; x=1710251567; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=FaUm8MeteGmR0lHrGgjk4UbknhXCWtTITJeZHOGMnnU=; b=DhRrq0+4jSKsPcmaWx3cjUh+RKWaXqDW34dU87662cmRxcrBqcKVBrzxJA3HsiDets 4P0d4kDWnj+A88qN3oOIUOwgR71XQZ2Q3KBtrdqco6rn0OF9rc4SXSrc2vs1AB6TEJej w21/2mQlTqt6sbDOv+ulT8Lhk7dNrUbjPOeXq61ncvB1oy1M/0ITsmR3SL2cZFdISgPQ pLP/jThwMKk5q7iJLFjD5lPPrIK3/tfQ75FmfPm5QMfhxgLiayilE8JuadvVlru3cPDP UYmyxDn60hMIFXc44GPxz/80sau0GTF0cRt/qIdMM/cpmrqZ4CGvdnUHA80wrxTQNuVg tSTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646767; x=1710251567; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=FaUm8MeteGmR0lHrGgjk4UbknhXCWtTITJeZHOGMnnU=; b=M0SvjVHZpOl3nfSgBVEMGVziUb9bTeQ/KGr2H7wpvAKPNAHWJDWImhue04M1Els1G0 mOp06HCpSFZpLMmjJPzUjH3u0YBA4pYOs9zHRl2959z1o41/HJlq70qzHlTsoCZk6ft1 K97TFIxjVzO7Zuishi8IUGV5FqLy0ak7+Fj8g6kFG4/txGCu9o+KluDp68Tgjt/lg7JW amK9bgNJigJ1cWtM32aW8tJBTjOpv2tP8ySvKl6PSy/2jqKx1v0HBkv7WZInW4MS0XJr mvTNJqdEHvN3ItzhwkpCyJ8pVwt8PgURuBLTmgBSvGrhJU9Wvj4J7+O47/awJxnR925V Z2oQ== X-Gm-Message-State: AOJu0Yw67cEg+chzKXKQyLMkVn/PjxqYRDCmao/fqcD+g1H2NX2xftSB R49Ds0dZCBpik3CwuI7jgKJAuc85tStpSZVwSMhytorF5exwjaLQ2/NxABY03r12HlsidwOu3av V X-Google-Smtp-Source: AGHT+IH7aoXJuuPvzFeSkf98aDpIc41+MTlwd0Y/juVVpfI1Ng6E832KWTH1qS/wr8OmdzO/03Hh8w== X-Received: by 2002:adf:b509:0:b0:33e:2d7b:c5a8 with SMTP id a9-20020adfb509000000b0033e2d7bc5a8mr2200239wrd.17.1709646766891; Tue, 05 Mar 2024 05:52:46 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.46 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:46 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 16/20] accel/tcg: Add TLB_CHECK_ALIGNED Date: Tue, 5 Mar 2024 13:52:33 +0000 Message-Id: <20240305135237.3111642-17-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::432; envelope-from=peter.maydell@linaro.org; helo=mail-wr1-x432.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Richard Henderson This creates a per-page method for checking of alignment. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Message-id: 20240301204110.656742-5-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- include/exec/cpu-all.h | 4 +++- accel/tcg/cputlb.c | 30 +++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index bc05dce7abe..1a6510fd3bf 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -357,8 +357,10 @@ static inline int cpu_mmu_index(CPUState *cs, bool ifetch) #define TLB_BSWAP (1 << 0) /* Set if TLB entry contains a watchpoint. */ #define TLB_WATCHPOINT (1 << 1) +/* Set if TLB entry requires aligned accesses. */ +#define TLB_CHECK_ALIGNED (1 << 2) -#define TLB_SLOW_FLAGS_MASK (TLB_BSWAP | TLB_WATCHPOINT) +#define TLB_SLOW_FLAGS_MASK (TLB_BSWAP | TLB_WATCHPOINT | TLB_CHECK_ALIGNED) /* The two sets of flags must not overlap. */ QEMU_BUILD_BUG_ON(TLB_FLAGS_MASK & TLB_SLOW_FLAGS_MASK); diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index ac986cb8ea5..93b1ca810bf 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1453,9 +1453,8 @@ static int probe_access_internal(CPUState *cpu, vaddr addr, flags |= full->slow_flags[access_type]; /* Fold all "mmio-like" bits into TLB_MMIO. This is not RAM. */ - if (unlikely(flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY)) - || - (access_type != MMU_INST_FETCH && force_mmio)) { + if (unlikely(flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY | TLB_CHECK_ALIGNED)) + || (access_type != MMU_INST_FETCH && force_mmio)) { *phost = NULL; return TLB_MMIO; } @@ -1836,6 +1835,31 @@ static bool mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi, tcg_debug_assert((flags & TLB_BSWAP) == 0); } + /* + * This alignment check differs from the one above, in that this is + * based on the atomicity of the operation. The intended use case is + * the ARM memory type field of each PTE, where access to pages with + * Device memory type require alignment. + */ + if (unlikely(flags & TLB_CHECK_ALIGNED)) { + MemOp size = l->memop & MO_SIZE; + + switch (l->memop & MO_ATOM_MASK) { + case MO_ATOM_NONE: + size = MO_8; + break; + case MO_ATOM_IFALIGN_PAIR: + case MO_ATOM_WITHIN16_PAIR: + size = size ? size - 1 : 0; + break; + default: + break; + } + if (addr & ((1 << size) - 1)) { + cpu_unaligned_access(cpu, addr, type, l->mmu_idx, ra); + } + } + return crosspage; } From patchwork Tue Mar 5 13:52:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582477 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 6F5ACC54E41 for ; Tue, 5 Mar 2024 13:55:47 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVEv-0001pR-Ih; Tue, 05 Mar 2024 08:53:53 -0500 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 1rhVE6-0000yD-NA for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:53:09 -0500 Received: from mail-wm1-x335.google.com ([2a00:1450:4864:20::335]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDs-0005yV-Mm for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:56 -0500 Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-412cf3c5cdeso27802655e9.2 for ; Tue, 05 Mar 2024 05:52:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646767; x=1710251567; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=J1DzK1oxT+Ly6WdUrENKHs1cSZQkyZRc92vsYauFXPY=; b=PtmHBvHsBSYd/ZWwKQsFObyipiJhX2IaPfWR3sPjUreuM12U8nl2vfnHA0mWZ3nfy0 esEfIX/zACZOyQiyPiMi/iDJR9qkIJo2cWN73CKm5wRHgPqve/wC+pwyRS0vxYpo5jIY grWmzAGnHyoEgFluNRYZ40NgTUzzUwae8A4eSYe+WVDBxvuTsD8pxUMNjtNFHLioooQz A94m4XkblfXUGLjXVQhMYGuYePisQ0grS9Lp0C2UD9HJGoqu2sG/kWflO8I5vo1+gUj+ w6543xVXf8m+U/FHCWQ5aIgI0ArfYuEZwewwHeb531PF3kr365Uo4rGwBmJ4UioddU0p MafA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646767; x=1710251567; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=J1DzK1oxT+Ly6WdUrENKHs1cSZQkyZRc92vsYauFXPY=; b=PEKzXJap6S5y6RpXqVsOuRd798P0MVj/w5LVts6ybxtKbP1QupHrPYDzvL6G/rsVqt 7DVthkYZMFOzIe6MoDvpXN+Fo5twd3vUfWtCONnYRaPB9ajWFssjKibVkgop8NoljKHt fDhmYnViij7LBJFzxlmc6WScgG5lOINwPPQcCtfJEdOtath9TeKASS6KFzwwNZz4bAh+ Y/1n+LKwDvgtIfr0XdbG4y9HXk5nBMJnrLw1PY2W3ZZvnokXmi5FodUZ+s5yoNEIXWs9 fIK056VqfeSSnVRagF/ClO/bI/WPCGj12jvze4xysKWej0OOb53EB/e2V5/4xVPK2OlA vGWA== X-Gm-Message-State: AOJu0YyDxrqVt7R6uVTpH48LKhpnyOoojdiT6rJ6mLfDL+ObGsZMI9gP Pbp77h7/R6SnBB8cOgAXjVH2ZZ40wfAaUlx4dGW22IRZv64UEhMdfRMNsAmwi94+pOjeqXlZXQl T X-Google-Smtp-Source: AGHT+IF2xiwQ8BjRCsLL/QfaZa22vUZOZGBNdw6EvjX5NTQSgcyYmjSKthFYkW2Xj/uxR3DT81hoKQ== X-Received: by 2002:a05:600c:511e:b0:412:b816:1584 with SMTP id o30-20020a05600c511e00b00412b8161584mr8555503wms.32.1709646767331; Tue, 05 Mar 2024 05:52:47 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:47 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 17/20] target/arm: Do memory type alignment check when translation disabled Date: Tue, 5 Mar 2024 13:52:34 +0000 Message-Id: <20240305135237.3111642-18-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::335; envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x335.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Richard Henderson If translation is disabled, the default memory type is Device, which requires alignment checking. This is more optimally done early via the MemOp given to the TCG memory operation. Reviewed-by: Philippe Mathieu-Daudé Reported-by: Idan Horowitz Signed-off-by: Richard Henderson Message-id: 20240301204110.656742-6-richard.henderson@linaro.org Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1204 Signed-off-by: Richard Henderson Signed-off-by: Peter Maydell --- target/arm/tcg/hflags.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c index 8e5d35d9227..5da1b0fc1d4 100644 --- a/target/arm/tcg/hflags.c +++ b/target/arm/tcg/hflags.c @@ -26,6 +26,35 @@ static inline bool fgt_svc(CPUARMState *env, int el) FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, SVC_EL1); } +/* Return true if memory alignment should be enforced. */ +static bool aprofile_require_alignment(CPUARMState *env, int el, uint64_t sctlr) +{ +#ifdef CONFIG_USER_ONLY + return false; +#else + /* Check the alignment enable bit. */ + if (sctlr & SCTLR_A) { + return true; + } + + /* + * If translation is disabled, then the default memory type is + * Device(-nGnRnE) instead of Normal, which requires that alignment + * be enforced. Since this affects all ram, it is most efficient + * to handle this during translation. + */ + if (sctlr & SCTLR_M) { + /* Translation enabled: memory type in PTE via MAIR_ELx. */ + return false; + } + if (el < 2 && (arm_hcr_el2_eff(env) & (HCR_DC | HCR_VM))) { + /* Stage 2 translation enabled: memory type in PTE. */ + return false; + } + return true; +#endif +} + static CPUARMTBFlags rebuild_hflags_common(CPUARMState *env, int fp_el, ARMMMUIdx mmu_idx, CPUARMTBFlags flags) @@ -121,8 +150,9 @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el, { CPUARMTBFlags flags = {}; int el = arm_current_el(env); + uint64_t sctlr = arm_sctlr(env, el); - if (arm_sctlr(env, el) & SCTLR_A) { + if (aprofile_require_alignment(env, el, sctlr)) { DP_TBFLAG_ANY(flags, ALIGN_MEM, 1); } @@ -223,7 +253,7 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, sctlr = regime_sctlr(env, stage1); - if (sctlr & SCTLR_A) { + if (aprofile_require_alignment(env, el, sctlr)) { DP_TBFLAG_ANY(flags, ALIGN_MEM, 1); } From patchwork Tue Mar 5 13:52:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582468 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 2C7C8C54798 for ; Tue, 5 Mar 2024 13:54:21 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVF7-0002mP-1r; Tue, 05 Mar 2024 08:54:05 -0500 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 1rhVE7-0000yX-HD for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:53:09 -0500 Received: from mail-wr1-x435.google.com ([2a00:1450:4864:20::435]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDt-0005yY-I6 for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:53:01 -0500 Received: by mail-wr1-x435.google.com with SMTP id ffacd0b85a97d-33d28468666so3791254f8f.0 for ; Tue, 05 Mar 2024 05:52:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646768; x=1710251568; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=FXV4byW7NW0KAiWMPyEzYmL7ozL2tTK1qICThutJLjQ=; b=zcASCyfmUFjW6ottGt8EJa+TuxnPrNmeHGMBV39T0JkibWYHpsDCq/zz8p0W/KS1he b51re6mcXhj/V0sKt/xNmjTcSF4rlfTaSZk6NcmuUILZ1+dBJ0Ha6v9MEWw5HO1FH2U1 JxwGmgkDGA1CO4zofBrU2xZNe6AK7nBcR/Jftm92Ba3PXItu81/uiew5oNE3iYnG3h8E jILwiFldwApkZwlZCHtkoKayzIq1yyoCe+HgzZZpsSaF+PPlr7gyvkqNQyNe2khhfcED TTNyVMzx3Oxm8GG5s5KyTFIEPD+67KOL5+W1cSolw2IXW7WNUVaCd+rlJS11nQdqc9eM lM0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646768; x=1710251568; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=FXV4byW7NW0KAiWMPyEzYmL7ozL2tTK1qICThutJLjQ=; b=MhUFq/bqhkB9cbQBuHqYM/ImPg4jkKe/D4qhoa9k1j972rzNrB21LMl1/vxo/AP6Rc toyGUyqlWI4U/XKuBGsybDL6Mj3DGw4L4G4tPKE/pN9zEgtK8A8Jb3wDiHc6JZrRPf2v 04FZGCDYU5DAvyXKZRboSGXTjnr/Vaq0eDbPAMTSr4cxSogGCD7NDz9TFmnM3g3xTbQ6 qhG58SRpVA329oQw4lw0cV44rkPBqn4htU856ZEI9z7dXhT6gHTARsGfPiHpVrjoaXkM 4J5WROlfS2joawGa5nNWkyOm27hQTRfMneFm3jE5yRsEvV2PCztrKtRFgCncxnVgtdX4 mzGA== X-Gm-Message-State: AOJu0YxpfK0DlXALXgfL/YtLmwMf0Td/dcaCO02wt6bE3XEdfhVOpP/c ioB5pHjRJ5UHrj0vKIg+IWEfE/zPQtfDuY4LMLmRZG942poSp0eDCZEm28adSgLlz6ueNjgPScp E X-Google-Smtp-Source: AGHT+IEm8P39LQghdUDn7PFnk1waqB1EKiy7jsZThAleW+37bydRn7e8mVahJLHu4Chdjd1RXfNZLQ== X-Received: by 2002:a5d:550b:0:b0:33d:47d1:38c3 with SMTP id b11-20020a5d550b000000b0033d47d138c3mr9364064wrv.36.1709646767727; Tue, 05 Mar 2024 05:52:47 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:47 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 18/20] target/arm: Do memory type alignment check when translation enabled Date: Tue, 5 Mar 2024 13:52:35 +0000 Message-Id: <20240305135237.3111642-19-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::435; envelope-from=peter.maydell@linaro.org; helo=mail-wr1-x435.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Richard Henderson If translation is enabled, and the PTE memory type is Device, enable checking alignment via TLB_CHECK_ALIGNMENT. While the check is done later than it should be per the ARM, it's better than not performing the check at all. Signed-off-by: Richard Henderson Message-id: 20240301204110.656742-7-richard.henderson@linaro.org [PMM: tweaks to comment text] Signed-off-by: Peter Maydell Reviewed-by: Peter Maydell --- target/arm/ptw.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index ba1a27ca2b5..31ae43f60ed 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -471,6 +471,16 @@ static bool granule_protection_check(CPUARMState *env, uint64_t paddress, return false; } +static bool S1_attrs_are_device(uint8_t attrs) +{ + /* + * This slightly under-decodes the MAIR_ELx field: + * 0b0000dd01 is Device with FEAT_XS, otherwise UNPREDICTABLE; + * 0b0000dd1x is UNPREDICTABLE. + */ + return (attrs & 0xf0) == 0; +} + static bool S2_attrs_are_device(uint64_t hcr, uint8_t attrs) { /* @@ -1684,6 +1694,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw, bool aarch64 = arm_el_is_aa64(env, el); uint64_t descriptor, new_descriptor; ARMSecuritySpace out_space; + bool device; /* TODO: This code does not support shareability levels. */ if (aarch64) { @@ -2106,6 +2117,12 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw, if (regime_is_stage2(mmu_idx)) { result->cacheattrs.is_s2_format = true; result->cacheattrs.attrs = extract32(attrs, 2, 4); + /* + * Security state does not really affect HCR_EL2.FWB; + * we only need to filter FWB for aa32 or other FEAT. + */ + device = S2_attrs_are_device(arm_hcr_el2_eff(env), + result->cacheattrs.attrs); } else { /* Index into MAIR registers for cache attributes */ uint8_t attrindx = extract32(attrs, 2, 3); @@ -2118,6 +2135,28 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw, if (aarch64 && cpu_isar_feature(aa64_bti, cpu)) { result->f.extra.arm.guarded = extract64(attrs, 50, 1); /* GP */ } + device = S1_attrs_are_device(result->cacheattrs.attrs); + } + + /* + * Enable alignment checks on Device memory. + * + * Per R_XCHFJ, this check is mis-ordered. The correct ordering + * for alignment, permission, and stage 2 faults should be: + * - Alignment fault caused by the memory type + * - Permission fault + * - A stage 2 fault on the memory access + * but due to the way the TCG softmmu TLB operates, we will have + * implicitly done the permission check and the stage2 lookup in + * finding the TLB entry, so the alignment check cannot be done sooner. + * + * In v7, for a CPU without the Virtualization Extensions this + * access is UNPREDICTABLE; we choose to make it take the alignment + * fault as is required for a v7VE CPU. (QEMU doesn't emulate any + * CPUs with ARM_FEATURE_LPAE but not ARM_FEATURE_V7VE anyway.) + */ + if (device) { + result->f.tlb_fill_flags |= TLB_CHECK_ALIGNED; } /* From patchwork Tue Mar 5 13:52:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582470 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 E2624C54E49 for ; Tue, 5 Mar 2024 13:54:24 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVEw-0001sK-M9; Tue, 05 Mar 2024 08:53:54 -0500 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 1rhVE6-0000yF-OJ for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:53:09 -0500 Received: from mail-wm1-x32b.google.com ([2a00:1450:4864:20::32b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDt-0005yf-IJ for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:52:56 -0500 Received: by mail-wm1-x32b.google.com with SMTP id 5b1f17b1804b1-412e783c94fso13192975e9.1 for ; Tue, 05 Mar 2024 05:52:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646768; x=1710251568; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=Qo1L26oNcI76C41AKC9KqnoX02ELXCqY0+XddiR1gdk=; b=Fd3pAAHCuNku85Ffdpd5V332juMm/Ul+/1O+FIc1ivmJGyEhCYo26NeERdPOg2eXGU 3Hn/SArveE40vEIUISDkN3jEJRnPh5EArW6FlddK2IZeU/U95qD4qy5ETsysIU+Wr7wC 7/r6cbmdg+hoUfWf8LTyw0z06t4GbuyET9sVFz2jX6Seocr6PtqP3jmQUp0zvt03sjMy cIzUMR8BId0hRMe0R8av9KNnyaFGF8wGtCujoE0eZYzh3EnnR34M0g+cXt4Rez2Kg6DD j3HamYT3gZV44sXLspheQIXLBeNBFtbOJC1s9ljPS/iSkY6dKNgQ92k6XUD+Ffncnnfh Yvmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646768; x=1710251568; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Qo1L26oNcI76C41AKC9KqnoX02ELXCqY0+XddiR1gdk=; b=CyOhzsEAGRqxrVsxReZeuMkYsSgaKebXCvvIHgFMHniadaM+2t+DuAnY0i/UFoOYmX mcxVxe8A1fH8agQq2H0DKDiJJjfIwpAB8Pl4HnlyTQxJXdZ9g34NWIeB5RYI325D/Aok ng5jJQLB6paSd2yacHFqs+0QGuNjepXPnMKT+/vHkg65nvPyqIJyU3EggoeWnvw7rR2G HFmhjLPwU3XWbu16EX82I1gr5gxmyrKpU89BMhq08D59/m51W95LIbFtFW7UvL5XKIry oKCwD9yO4ttRihbg4iXCxa73WsSZLqBXPfMpEs22HsUi83Qw6LedmskM+ie9Q7HcLOZU q4qw== X-Gm-Message-State: AOJu0YypXND3CDI8N2fdsiMTri/aPWaopnEuvGb/cQaO8cyyzAirVuAM 8MdjdGMztuK9ooC2ub8UOMHlTvGnvjQFbhkvJr8h1qORMg7UmoVMAKYlJ+OO5Y6ATb3e5yqSxcy Z X-Google-Smtp-Source: AGHT+IGDBzKouDiNBepXRThxi2xvp3tifkJjJqZSWYKvIg5mACroqcZ0+l/uaIB126kDSkJaBODy4A== X-Received: by 2002:a05:600c:1c88:b0:412:e55e:8516 with SMTP id k8-20020a05600c1c8800b00412e55e8516mr3513452wms.12.1709646768214; Tue, 05 Mar 2024 05:52:48 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:47 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 19/20] atomic.h: Reword confusing comment for qatomic_cmpxchg Date: Tue, 5 Mar 2024 13:52:36 +0000 Message-Id: <20240305135237.3111642-20-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::32b; envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x32b.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org The qatomic_cmpxchg() and qatomic_cmpxchg__nocheck() macros have a comment that reads: Returns the eventual value, failed or not This is somewhere between cryptic and wrong, since the value actually returned is the value that was in memory before the cmpxchg. Reword to match how we describe these macros in atomics.rst. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Jonathan Cameron Reviewed-by: Zhao Liu Message-id: 20240223182035.1048541-1-peter.maydell@linaro.org --- include/qemu/atomic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h index f1d3d1702a9..99110abefb3 100644 --- a/include/qemu/atomic.h +++ b/include/qemu/atomic.h @@ -202,7 +202,7 @@ qatomic_xchg__nocheck(ptr, i); \ }) -/* Returns the eventual value, failed or not */ +/* Returns the old value of '*ptr' (whether the cmpxchg failed or not) */ #define qatomic_cmpxchg__nocheck(ptr, old, new) ({ \ typeof_strip_qual(*ptr) _old = (old); \ (void)__atomic_compare_exchange_n(ptr, &_old, new, false, \ From patchwork Tue Mar 5 13:52:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 13582473 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 6D536C54798 for ; Tue, 5 Mar 2024 13:54:33 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rhVF0-0002EP-5z; Tue, 05 Mar 2024 08:53:58 -0500 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 1rhVE7-0000yW-HG for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:53:09 -0500 Received: from mail-wm1-x32a.google.com ([2a00:1450:4864:20::32a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rhVDt-0005yp-Uy for qemu-devel@nongnu.org; Tue, 05 Mar 2024 08:53:01 -0500 Received: by mail-wm1-x32a.google.com with SMTP id 5b1f17b1804b1-412e96284b9so5839505e9.3 for ; Tue, 05 Mar 2024 05:52:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1709646768; x=1710251568; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=uKoVEk1QGKUdsSjizVrNW7gmKUKZFVK6gFXUR6BEh58=; b=BATeu6Y0VC54DjpZRFLbWJ39l61jZff0kQDAA1CPBUOhaaX14hHeMq1eOANBSD29Xs d3WRzY7UqgnaJHHtLyW2EPolKbP6vDMCZJ2eTKRfTkGfhVignKvNyttdoxhBOS/W1HtG lNmWVpsRgrHpD/WP0Y6SwIa/X15G2JUWNHKY1c+8T6sKlCAan0vIJ2Ib0yNQ1Y9X4nAN 4QeglGroIxsK+VDwMusQG/6T2/DNR/gtCshzRWU/eIfRI8JL1tFDgRSl0js/Fg0oTnla qrRKnPXCrgzfBjjIGFvvX1MlxgxlfhEd+p4tKEaVRP8y1EGqVr4l/NvlUSwxu5y0qWZ+ Ss2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709646768; x=1710251568; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=uKoVEk1QGKUdsSjizVrNW7gmKUKZFVK6gFXUR6BEh58=; b=BpkDm0r/mdMX8BnFmVVQh/hYbQ2I8oolZDXMGdHkwrp0aeHKU0gLlGcl2JdKihcI1P BYxf+B+k9Y3FCW7KLSEEQ4LF+Mv6hnjrOGZi7Kjza8laKCFewo7HvEX8EASqQDDKh4Au ar390woWCMnkhHmdCyKW/XudH1FI+XVmcd2xUoyQ1Yt5mDO2OFUX87Pf+etxcwoaSVnN 1MQTGV1lww4lAjmuV/TNS8jhIUjdPN97GQC/Pn+0v6UF8JARhIhffvfbZPN6ex+WwUgq Gal0DM9p6vC3hJ0wo0+QGimLsLrbmbufqPe1gqyNzAwe/L1dukyVtxV7wM1SJJCj+cvd 2OiA== X-Gm-Message-State: AOJu0YyGkJTGiHAcN+2Fw4l9aWNYE21shAl/G7mzPLKSFFPXr0wF+CkT z0iYN32C6JrgDewXCAHrGWE3uVsoSNTUbb4IOj94k7mA5XkXcLpPrpcPXoqa5/rjp1NeRfQ/EPp M X-Google-Smtp-Source: AGHT+IHWVPENsp+FqHTt/+V0Hk1m8S4w64ua1aURcp6+I69ON0MaokItvkuljjN+BgOKabkXCl4YAA== X-Received: by 2002:a05:600c:444f:b0:412:efed:28e2 with SMTP id v15-20020a05600c444f00b00412efed28e2mr630161wmn.41.1709646768591; Tue, 05 Mar 2024 05:52:48 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id x3-20020a5d6503000000b0033e206a0a7asm11797532wru.26.2024.03.05.05.52.48 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Mar 2024 05:52:48 -0800 (PST) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 20/20] qemu-options.hx: Don't claim "-serial" has limit of 4 serial ports Date: Tue, 5 Mar 2024 13:52:37 +0000 Message-Id: <20240305135237.3111642-21-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240305135237.3111642-1-peter.maydell@linaro.org> References: <20240305135237.3111642-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::32a; envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x32a.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, 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, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Steven Shen Before v2.12, the implementation of serial ports was limited to a value of MAX_SERIAL_PORTS = 4. We now dynamically allocate the data structures for serial ports, so this limit is no longer present, but the documentation for the -serial options still reads: "This option can be used several times to simulate up to 4 serial ports." Update to "This option can be used several times to simulate multiple serial ports." to avoid misleading. Signed-off-by: Steven Shen Message-id: 20240305013016.2268-1-steven.shen@jaguarmicro.com Reviewed-by: Peter Maydell [PMM: tweaked commit message] Signed-off-by: Peter Maydell --- qemu-options.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu-options.hx b/qemu-options.hx index 9a47385c157..ac4a30fa834 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4129,7 +4129,7 @@ SRST default device is ``vc`` in graphical mode and ``stdio`` in non graphical mode. - This option can be used several times to simulate up to 4 serial + This option can be used several times to simulate multiple serial ports. You can use ``-serial none`` to suppress the creation of default