From nobody Tue Feb 10 02:00:14 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=telecom-paris.fr ARC-Seal: i=1; a=rsa-sha256; t=1706630923; cv=none; d=zohomail.com; s=zohoarc; b=Gu2fmXIJ6a53Jl0nOJ/T/m0JBypSzuS5BPArOau4NfjS1wX645kxmi+LhvGxIV7ElMXmQnqMjQ1QeXSjYVai8U06Zf3zeKdvaqKuYYj+JaGl7FRHj3F9yp48J87tApL3QoO5ZGN2SWkqsuA6JBOwTdk+w+VsK+J/7uRitkkKack= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1706630923; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=cydMrBGp9rIzyfNKxMqXR/yNK4y0yE6pkBwZmEDnAb4=; b=eByaa9+UnAjjiVFXPNc7MPm4vdow3ezwGeMMeTL7kMUCoyxfvmVwUbDaA04O/lMtwCfv+Bgql6vU/JJ/9mDN5AKNsVyrCIQszGbh6t47vPwPilG27Qv0c2PvHEkXwDU43WxD0Uh8i5CDUgzuZ33PaShnehbLQDa+bSB5lTpEgmk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1706630922626859.119593429424; Tue, 30 Jan 2024 08:08:42 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rUqeb-000052-0c; Tue, 30 Jan 2024 11:08: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 1rUqe0-0008GE-2H; Tue, 30 Jan 2024 11:07:32 -0500 Received: from zproxy3.enst.fr ([2001:660:330f:2::de]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rUqdx-00070b-Rn; Tue, 30 Jan 2024 11:07:27 -0500 Received: from localhost (localhost [IPv6:::1]) by zproxy3.enst.fr (Postfix) with ESMTP id EBC3BA075B; Tue, 30 Jan 2024 17:07:12 +0100 (CET) Received: from zproxy3.enst.fr ([IPv6:::1]) by localhost (zproxy3.enst.fr [IPv6:::1]) (amavis, port 10032) with ESMTP id qw2SjUx57aeq; Tue, 30 Jan 2024 17:07:12 +0100 (CET) Received: from localhost (localhost [IPv6:::1]) by zproxy3.enst.fr (Postfix) with ESMTP id 0A3DDA0657; Tue, 30 Jan 2024 17:07:11 +0100 (CET) Received: from zproxy3.enst.fr ([IPv6:::1]) by localhost (zproxy3.enst.fr [IPv6:::1]) (amavis, port 10026) with ESMTP id BKTc7acmDOLq; Tue, 30 Jan 2024 17:07:11 +0100 (CET) Received: from AM-Inspiron-3585.numericable.fr (38.162.10.109.rev.sfr.net [109.10.162.38]) by zproxy3.enst.fr (Postfix) with ESMTPSA id 7AAD4A0753; Tue, 30 Jan 2024 17:07:11 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.10.3 zproxy3.enst.fr 0A3DDA0657 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=telecom-paris.fr; s=A35C7578-1106-11E5-A17F-C303FDDA8F2E; t=1706630832; bh=cydMrBGp9rIzyfNKxMqXR/yNK4y0yE6pkBwZmEDnAb4=; h=From:To:Date:Message-Id:MIME-Version; b=QiuWdL/FvfuEUJOeQeiPdWV40UqRNxWRWgIfwKcoAQ8cMjAEKbEc91vwh5as7I/73 Qp7+5zD/XCwfS1HqSH8rEMI612GkTkBf8OZuz+hmUA6dzzJScLvfEK6oOXcmHCx8xk 6vqwC2NPcRJHYFh0Tj/eKizeCEil8vGwQzp15vyI= X-Virus-Scanned: amavis at enst.fr From: Arnaud Minier To: qemu-devel@nongnu.org Cc: Laurent Vivier , Alistair Francis , =?UTF-8?q?In=C3=A8s=20Varhol?= , Peter Maydell , Paolo Bonzini , Thomas Huth , qemu-arm@nongnu.org, Arnaud Minier Subject: [PATCH v4 6/8] Add write protections to CR register Date: Tue, 30 Jan 2024 17:06:54 +0100 Message-Id: <20240130160656.113112-7-arnaud.minier@telecom-paris.fr> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240130160656.113112-1-arnaud.minier@telecom-paris.fr> References: <20240130160656.113112-1-arnaud.minier@telecom-paris.fr> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2001:660:330f:2::de; envelope-from=arnaud.minier@telecom-paris.fr; helo=zproxy3.enst.fr 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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @telecom-paris.fr) X-ZM-MESSAGEID: 1706630926897100001 Content-Type: text/plain; charset="utf-8" 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=C3=A8s Varhol --- hw/misc/stm32l4x5_rcc.c | 164 ++++++++++++++++++++++++++++------------ 1 file changed, 114 insertions(+), 50 deletions(-) diff --git a/hw/misc/stm32l4x5_rcc.c b/hw/misc/stm32l4x5_rcc.c index 3bf4b41552..a192ce16d7 100644 --- a/hw/misc/stm32l4x5_rcc.c +++ b/hw/misc/stm32l4x5_rcc.c @@ -345,9 +345,47 @@ static void rcc_update_irq(Stm32l4x5RccState *s) } } =20 -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[] =3D { + 100000, 200000, 400000, 800000, 1000000, 2000000, + 4000000, 8000000, 16000000, 24000000, 32000000, 48000000 + }; + /* MSIRANGE and MSIRGSEL */ + val =3D extract32(s->cr, R_CR_MSIRGSEL_SHIFT, R_CR_MSIRGSEL_LENGTH); + if (val) { + /* MSIRGSEL is set, use the MSIRANGE field */ + val =3D extract32(s->cr, R_CR_MSIRANGE_SHIFT, R_CR_MSIRANGE_LENGTH= ); + } else { + /* MSIRGSEL is not set, use the MSISRANGE field */ + val =3D extract32(s->csr, R_CSR_MSISRANGE_SHIFT, R_CSR_MSISRANGE_L= ENGTH); + } + + 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 bou= nd. + * Restore the previous value. + */ + s->cr =3D (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 =3D + CLOCK_MUX_INIT_INFO[RCC_CLOCK_MUX_PLL_INPUT].src_mapping[ + s->clock_muxes[RCC_CLOCK_MUX_PLL_INPUT].src]; =20 /* PLLSAI2ON and update PLLSAI2RDY */ val =3D extract32(s->cr, R_CR_PLLSAI2ON_SHIFT, R_CR_PLLSAI2ON_LENGTH); @@ -367,77 +405,101 @@ static void rcc_update_cr_register(Stm32l4x5RccState= *s) s->cifr |=3D R_CIFR_PLLSAI1RDYF_MASK; } =20 - /* PLLON and update PLLRDY */ + /* + * PLLON and update PLLRDY + * PLLON cannot be reset if the PLL clock is used as the system clock. + */ val =3D extract32(s->cr, R_CR_PLLON_SHIFT, R_CR_PLLON_LENGTH); - pll_set_enable(&s->plls[RCC_PLL_PLL], val); - s->cr =3D (s->cr & ~R_CR_PLLRDY_MASK) | - (val << R_CR_PLLRDY_SHIFT); - if (s->cier & R_CIER_PLLRDYIE_MASK) { - s->cifr |=3D R_CIFR_PLLRDYF_MASK; + if (extract32(s->cfgr, R_CFGR_SWS_SHIFT, R_CFGR_SWS_LENGTH) !=3D 0b11)= { + pll_set_enable(&s->plls[RCC_PLL_PLL], val); + s->cr =3D (s->cr & ~R_CR_PLLRDY_MASK) | + (val << R_CR_PLLRDY_SHIFT); + if (s->cier & R_CIER_PLLRDYIE_MASK) { + s->cifr |=3D R_CIFR_PLLRDYF_MASK; + } + } else { + s->cr |=3D R_CR_PLLON_MASK; } =20 /* CSSON: TODO */ /* HSEBYP: TODO */ =20 - /* 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 =3D extract32(s->cr, R_CR_HSEON_SHIFT, R_CR_HSEON_LENGTH); - s->cr =3D (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 |=3D R_CIFR_HSERDYF_MASK; + if (extract32(s->cfgr, R_CFGR_SWS_SHIFT, R_CFGR_SWS_LENGTH) !=3D 0b10 = && + current_pll_src !=3D RCC_CLOCK_MUX_SRC_HSE) { + s->cr =3D (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 |=3D R_CIFR_HSERDYF_MASK; + } + } else { + clock_update_hz(s->hse, 0); } } else { - clock_update_hz(s->hse, 0); + s->cr |=3D R_CR_HSEON_MASK; } =20 /* HSIAFS: TODO*/ /* HSIKERON: TODO*/ =20 - /* HSION and update HSIRDY*/ - val =3D extract32(s->cr, R_CR_HSION_SHIFT, R_CR_HSION_LENGTH); - s->cr =3D (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 (extract32(s->cfgr, R_CFGR_SWS_SHIFT, R_CFGR_SWS_LENGTH) =3D=3D 0b0= 1 || + current_pll_src =3D=3D RCC_CLOCK_MUX_SRC_HSI) { + s->cr |=3D (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 |=3D R_CIFR_HSIRDYF_MASK; } } else { - clock_update_hz(s->hsi16_rc, 0); + val =3D extract32(s->cr, R_CR_HSION_SHIFT, R_CR_HSION_LENGTH); + if (val) { + clock_update_hz(s->hsi16_rc, HSI_FRQ); + s->cr |=3D R_CR_HSIRDY_MASK; + if (s->cier & R_CIER_HSIRDYIE_MASK) { + s->cifr |=3D R_CIFR_HSIRDYF_MASK; + } + } else { + clock_update_hz(s->hsi16_rc, 0); + s->cr &=3D ~R_CR_HSIRDY_MASK; + } } =20 - static const uint32_t msirange[] =3D { - 100000, 200000, 400000, 800000, 1000000, 2000000, - 4000000, 8000000, 16000000, 24000000, 32000000, 48000000 - }; - /* MSIRANGE and MSIRGSEL */ - val =3D extract32(s->cr, R_CR_MSIRGSEL_SHIFT, R_CR_MSIRGSEL_LENGTH); - if (val) { - /* MSIRGSEL is set, use the MSIRANGE field */ - val =3D extract32(s->cr, R_CR_MSIRANGE_SHIFT, R_CR_MSIRANGE_LENGTH= ); - } else { - /* MSIRGSEL is not set, use the MSISRANGE field */ - val =3D extract32(s->csr, R_CSR_MSISRANGE_SHIFT, R_CSR_MSISRANGE_L= ENGTH); - } + /* MSIPLLEN: TODO */ =20 - if (val < ARRAY_SIZE(msirange)) { - clock_update_hz(s->msi_rc, msirange[val]); + /* + * MSION and update MSIRDY + * Set by hardware when used directly or indirectly as system clock. + */ + if (extract32(s->cfgr, R_CFGR_SWS_SHIFT, R_CFGR_SWS_LENGTH) =3D=3D 0b0= 0 || + current_pll_src =3D=3D RCC_CLOCK_MUX_SRC_MSI) { + s->cr |=3D (R_CR_MSION_MASK | R_CR_MSIRDY_MASK); + if (!(previous_value & R_CR_MSION_MASK) && (s->cier & R_CIER_M= SIRDYIE_MASK)) { + s->cifr |=3D R_CIFR_MSIRDYF_MASK; + } + rcc_update_msi(s, previous_value); } 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 =3D extract32(s->cr, R_CR_MSION_SHIFT, R_CR_MSION_LENGTH); - s->cr =3D (s->cr & ~R_CR_MSIRDY_MASK) | - (val << R_CR_MSIRDY_SHIFT); - if (s->cier & R_CIER_MSIRDYIE_MASK) { - s->cifr |=3D R_CIFR_MSIRDYF_MASK; + val =3D extract32(s->cr, R_CR_MSION_SHIFT, R_CR_MSION_LENGTH); + if (val) { + s->cr |=3D R_CR_MSIRDY_MASK; + rcc_update_msi(s, previous_value); + if (s->cier & R_CIER_MSIRDYIE_MASK) { + s->cifr |=3D R_CIFR_MSIRDYF_MASK; + } + } else { + s->cr &=3D ~R_CR_MSIRDY_MASK; + clock_update_hz(s->msi_rc, 0); + } } rcc_update_irq(s); } @@ -962,15 +1024,17 @@ static void stm32l4x5_rcc_write(void *opaque, hwaddr= addr, uint64_t val64, unsigned int size) { Stm32l4x5RccState *s =3D opaque; + uint32_t previous_value =3D 0; const uint32_t value =3D val64; =20 trace_stm32l4x5_rcc_write(addr, value); =20 switch (addr) { case A_CR: + previous_value =3D s->cr; s->cr =3D (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 =3D value & ~ICSCR_READ_ONLY_MASK; --=20 2.34.1