From patchwork Thu Jun 11 22:30:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Havard Skinnemoen X-Patchwork-Id: 280669 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.4 required=3.0 tests=DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT, USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DD97CC433DF for ; Thu, 11 Jun 2020 22:32:27 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id A79762073E for ; Thu, 11 Jun 2020 22:32:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="MYXcyWQ8" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A79762073E Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:59220 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jjVkI-0005da-PI for qemu-devel@archiver.kernel.org; Thu, 11 Jun 2020 18:32:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33506) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3hbDiXgsKCm4TeWUZZQYaQZSaaSXQ.OaYcQYg-PQhQXZaZSZg.adS@flex--hskinnemoen.bounces.google.com>) id 1jjViZ-0003sc-5n for qemu-devel@nongnu.org; Thu, 11 Jun 2020 18:30:40 -0400 Received: from mail-yb1-xb4a.google.com ([2607:f8b0:4864:20::b4a]:36642) by eggs.gnu.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3hbDiXgsKCm4TeWUZZQYaQZSaaSXQ.OaYcQYg-PQhQXZaZSZg.adS@flex--hskinnemoen.bounces.google.com>) id 1jjViX-00041p-0h for qemu-devel@nongnu.org; Thu, 11 Jun 2020 18:30:38 -0400 Received: by mail-yb1-xb4a.google.com with SMTP id c3so8163950ybi.3 for ; Thu, 11 Jun 2020 15:30:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=IQsEaB5zb1n6vsfoAp6zXcRCVesUArc2Mv6NZg2LuPw=; b=MYXcyWQ8nILs+/tnF1h6mYzKlCEpLGtUuV+ye62MtsqJ4JX9MdYKZAxFNu2Ib7eRI7 jRqUYE0L91ddrhLOjkaV3DRdqiyIZBO2KLAepsjRL9gzpFzhFQeQIBW+h1teJVqr4Opl c0fXUsb1WnZ75rqkRpuS3l4Z4SayRumXYC0IqjVgFwDJWFhvETPErqCkQMpYBGZaTEyo cYEXwILmUsoCgjbZzkzDkZU/6MfJDlcaRKes7TLuOrmthEEM25t8pWkEuaiplIMNar0G ViPV2NHflxToheM6zSRwnoBpVwyogGRJTSm2AIHTmaBTRBP1TQYVYtcyAT9gRO4X/N8Z aGWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=IQsEaB5zb1n6vsfoAp6zXcRCVesUArc2Mv6NZg2LuPw=; b=Ma9XYoLPAdMjFAvBbX3XHlkSxrIfjyrSvhvmg3OJeAS157NaYWcZDbSByl1pw0wE6+ AzxHmXW6r79t5eEUaqDZA7zGDdBwCWZEDzkOF/gb3/K2EIfHRjo+IYO8CRftSf8zyp/7 N17fWxKI7jMuFL6RdKc4QFs+F7gFT37UV4d7mOsTOoipR9ekxrouxZ+Oz3VA/Cw9CevU ANPvmqf4oS0V90pOxQH3/Q0Sd3RI9KqgWTIRc8tv+UB7xtgD8u8+1fDaLHP05KKuyl0C d75Nr6HS2ftgfmJKlL1S/dCBcDnyCiXO7b5HkkhjEjcRonzhFOXUINnIm9ghSo2G4Jft UO8w== X-Gm-Message-State: AOAM531JSFy4yT3b3JHPHkCeo0y5nY7iUPBeXBuhBAsJrT5QeFNXYkJu OgjWg2sM7+ZHtaPkSp1s0is7C+gwl8qIb8w/2Q== X-Google-Smtp-Source: ABdhPJxemRcA+QEQAgrqMwTEDGJSv/SQkhWUoMkv32Dbh31TQrn3f5IcMa0GNv+4hS35z23MwRtYhAQ+xOAQ8xC0zw== X-Received: by 2002:a25:3055:: with SMTP id w82mr17824647ybw.21.1591914629653; Thu, 11 Jun 2020 15:30:29 -0700 (PDT) Date: Thu, 11 Jun 2020 15:30:05 -0700 In-Reply-To: <20200611223016.259837-1-hskinnemoen@google.com> Message-Id: <20200611223016.259837-2-hskinnemoen@google.com> Mime-Version: 1.0 References: <20200611223016.259837-1-hskinnemoen@google.com> X-Mailer: git-send-email 2.27.0.290.gba653c62da-goog Subject: [PATCH v2 01/12] npcm7xx: Add config symbol From: Havard Skinnemoen To: peter.maydell@linaro.org, clg@kaod.org, joel@jms.id.au Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org, Avi.Fishman@nuvoton.com, kfting@nuvoton.com, Havard Skinnemoen Received-SPF: pass client-ip=2607:f8b0:4864:20::b4a; envelope-from=3hbDiXgsKCm4TeWUZZQYaQZSaaSXQ.OaYcQYg-PQhQXZaZSZg.adS@flex--hskinnemoen.bounces.google.com; helo=mail-yb1-xb4a.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -105 X-Spam_score: -10.6 X-Spam_bar: ---------- X-Spam_report: (-10.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-1, 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, USER_IN_DEF_DKIM_WL=-7.5 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" Add a config symbol for the NPCM7xx BMC SoC family that subsequent patches can use in Makefiles. Change-Id: I6e4d5c58716cb6fe4ea5d06f148beeafda55f9a5 Reviewed-by: Tyrone Ting Acked-by: Joel Stanley Signed-off-by: Havard Skinnemoen --- default-configs/arm-softmmu.mak | 1 + hw/arm/Kconfig | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index 8fc09a4a51..9a94ebd0be 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -27,6 +27,7 @@ CONFIG_GUMSTIX=y CONFIG_SPITZ=y CONFIG_TOSA=y CONFIG_Z2=y +CONFIG_NPCM7XX=y CONFIG_COLLIE=y CONFIG_ASPEED_SOC=y CONFIG_NETDUINO2=y diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 9afa6eee79..3738c1f5cd 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -354,6 +354,14 @@ config XLNX_VERSAL select VIRTIO_MMIO select UNIMP +config NPCM7XX + bool + select A9MPCORE + select ARM_GIC + select PL310 # cache controller + select SERIAL + select UNIMP + config FSL_IMX25 bool select IMX From patchwork Thu Jun 11 22:30:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Havard Skinnemoen X-Patchwork-Id: 280668 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.4 required=3.0 tests=DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A6D01C433E0 for ; Thu, 11 Jun 2020 22:32:33 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 6285A2073E for ; Thu, 11 Jun 2020 22:32:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="XWfWf8Cl" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6285A2073E Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:59528 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jjVkO-0006CI-KC for qemu-devel@archiver.kernel.org; Thu, 11 Jun 2020 18:32:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33654) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3ibDiXgsKCnIXiaYddUceUdWeeWbU.SecgUck-TUlUbdedWdk.ehW@flex--hskinnemoen.bounces.google.com>) id 1jjVid-0003tF-8f for qemu-devel@nongnu.org; Thu, 11 Jun 2020 18:30:43 -0400 Received: from mail-qk1-x74a.google.com ([2607:f8b0:4864:20::74a]:44131) by eggs.gnu.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3ibDiXgsKCnIXiaYddUceUdWeeWbU.SecgUck-TUlUbdedWdk.ehW@flex--hskinnemoen.bounces.google.com>) id 1jjViZ-00043D-VW for qemu-devel@nongnu.org; Thu, 11 Jun 2020 18:30:42 -0400 Received: by mail-qk1-x74a.google.com with SMTP id j16so6453027qka.11 for ; Thu, 11 Jun 2020 15:30:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc:content-transfer-encoding; bh=UsF2OQs6/N/UD9Ok2d+0MvtdCGtXSPf3cq6HCDsjUyA=; b=XWfWf8ClU3dylSd9HJHXVjnZAuoqwt/kYykWFjtZoXGNELXMEpjbfYKNw4ANReAFa1 EH2Cefd4AXYyad2LMxpLTzmr/C13x5047H2e/BhS51lkRwIecuf7amf76JZaXey/nl+X 8AswyhlbQTrNKMvfWMiiPTmhAMytG56mLDzRqdzXqRNqn68iAzLQpF2taRM8ajF4t5dI Sf7boQGv1e3Wkf5HKEvsh6CTD2Uy42muXtFHfWmnxrI5R8CdxFSqRGar3cfbn7oIzJMY LZdGcABM/XyGjS7HDVOhcQSpcuJYENcx/fSzrC8x3CRG/iQo9eon/5Rzvsc/FRo1hovb BIjA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc:content-transfer-encoding; bh=UsF2OQs6/N/UD9Ok2d+0MvtdCGtXSPf3cq6HCDsjUyA=; b=r1vMZ0pIEajQYv3GMRL34D3wBH3QlVWeBPInepcK+AgnThMqw3b3S6HuE5i872VGsu djCA69vW2CoxNhzd2LLU60AAUdAZeRheS8YVJaOt2IY7J5kov0cLftUhNB54GB6tvBPg ynfUVS01ltTc1YaBIavBtK8D82UkIxurk9hRgT3jhvq5JsKuiybLNBIOWwkK1QScCbPG DR4xW0Rtmahpg2M2d2vmMz2hfavgq8L+359/9wKlhm78y6LERG/jBp5PZJHx6U8kuItq jrwb2hzQ/nEdWl6+h3O8eRILZG4Glz8DUlcgKD7E4qiqKnjX20EaCbQLXahH/VAvsrvq nYKQ== X-Gm-Message-State: AOAM533pXPyzmOb2twpQ0OBNvN0f3V3IdV/+jD7CN3/TGflsJ1a0NFoQ iF3/HMdxDwFn2an81YY9kKhfWkfwZHXoqWE6HA== X-Google-Smtp-Source: ABdhPJxETLatgkYwi8WQ07+rud53GR0Ep1g22SQNN42zAXC/q67dKyg1iYqtgPFcqWDuWKqqMig8i5jBo2dcVAtrYA== X-Received: by 2002:ad4:494c:: with SMTP id o12mr10205726qvy.102.1591914633355; Thu, 11 Jun 2020 15:30:33 -0700 (PDT) Date: Thu, 11 Jun 2020 15:30:07 -0700 In-Reply-To: <20200611223016.259837-1-hskinnemoen@google.com> Message-Id: <20200611223016.259837-4-hskinnemoen@google.com> Mime-Version: 1.0 References: <20200611223016.259837-1-hskinnemoen@google.com> X-Mailer: git-send-email 2.27.0.290.gba653c62da-goog Subject: [PATCH v2 03/12] hw/misc: Add NPCM7xx Clock Controller device model From: Havard Skinnemoen To: peter.maydell@linaro.org, clg@kaod.org, joel@jms.id.au Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org, Avi.Fishman@nuvoton.com, kfting@nuvoton.com, Havard Skinnemoen Received-SPF: pass client-ip=2607:f8b0:4864:20::74a; envelope-from=3ibDiXgsKCnIXiaYddUceUdWeeWbU.SecgUck-TUlUbdedWdk.ehW@flex--hskinnemoen.bounces.google.com; helo=mail-qk1-x74a.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -105 X-Spam_score: -10.6 X-Spam_bar: ---------- X-Spam_report: (-10.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-1, 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, USER_IN_DEF_DKIM_WL=-7.5 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" Enough functionality to boot the Linux kernel has been implemented. This includes: - Correct power-on reset values so the various clock rates can be accurately calculated. - Clock enables stick around when written. In addition, a best effort attempt to implement SECCNT and CNTR25M was made even though I don't think the kernel needs them. Reviewed-by: Tyrone Ting Reviewed-by: Joel Stanley Reviewed-by: Cédric Le Goater Signed-off-by: Havard Skinnemoen --- hw/misc/Makefile.objs | 1 + hw/misc/npcm7xx_clk.c | 216 ++++++++++++++++++++++++++++++++++ hw/misc/trace-events | 4 + include/hw/misc/npcm7xx_clk.h | 65 ++++++++++ 4 files changed, 286 insertions(+) create mode 100644 hw/misc/npcm7xx_clk.c create mode 100644 include/hw/misc/npcm7xx_clk.h diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 40a9d1c01e..2e74803005 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -51,6 +51,7 @@ common-obj-$(CONFIG_IMX) += imx_rngc.o common-obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o common-obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o common-obj-$(CONFIG_MAINSTONE) += mst_fpga.o +common-obj-$(CONFIG_NPCM7XX) += npcm7xx_clk.o common-obj-$(CONFIG_NPCM7XX) += npcm7xx_gcr.o common-obj-$(CONFIG_OMAP) += omap_clk.o common-obj-$(CONFIG_OMAP) += omap_gpmc.o diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c new file mode 100644 index 0000000000..2348683305 --- /dev/null +++ b/hw/misc/npcm7xx_clk.c @@ -0,0 +1,216 @@ +/* + * Nuvoton NPCM7xx Clock Control Registers. + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "qemu/osdep.h" + +#include "hw/misc/npcm7xx_clk.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/timer.h" +#include "qemu/units.h" +#include "trace.h" + +#define PLLCON_LOKI BIT(31) +#define PLLCON_LOKS BIT(30) +#define PLLCON_PWDEN BIT(12) + +/* + * These reset values were taken from version 0.91 of the NPCM750R data sheet. + * + * All are loaded on power-up reset. CLKENx and SWRSTR should also be loaded on + * core domain reset, but this reset type is not yet supported by QEMU. + */ +static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = { + [NPCM7XX_CLK_CLKEN1] = 0xffffffff, + [NPCM7XX_CLK_CLKSEL] = 0x004aaaaa, + [NPCM7XX_CLK_CLKDIV1] = 0x5413f855, + [NPCM7XX_CLK_PLLCON0] = 0x00222101 | PLLCON_LOKI, + [NPCM7XX_CLK_PLLCON1] = 0x00202101 | PLLCON_LOKI, + [NPCM7XX_CLK_IPSRST1] = 0x00001000, + [NPCM7XX_CLK_IPSRST2] = 0x80000000, + [NPCM7XX_CLK_CLKEN2] = 0xffffffff, + [NPCM7XX_CLK_CLKDIV2] = 0xaa4f8f9f, + [NPCM7XX_CLK_CLKEN3] = 0xffffffff, + [NPCM7XX_CLK_IPSRST3] = 0x03000000, + [NPCM7XX_CLK_WD0RCR] = 0xffffffff, + [NPCM7XX_CLK_WD1RCR] = 0xffffffff, + [NPCM7XX_CLK_WD2RCR] = 0xffffffff, + [NPCM7XX_CLK_SWRSTC1] = 0x00000003, + [NPCM7XX_CLK_PLLCON2] = 0x00c02105 | PLLCON_LOKI, + [NPCM7XX_CLK_CORSTC] = 0x04000003, + [NPCM7XX_CLK_PLLCONG] = 0x01228606 | PLLCON_LOKI, + [NPCM7XX_CLK_AHBCKFI] = 0x000000c8, +}; + +static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size) +{ + uint32_t reg = offset / sizeof(uint32_t); + NPCM7xxCLKState *s = opaque; + int64_t now_ns; + uint32_t value = 0; + + if (reg >= NPCM7XX_CLK_NR_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: offset 0x%04x out of range\n", + __func__, (unsigned int)offset); + return 0; + } + + switch (reg) { + case NPCM7XX_CLK_SWRSTR: + qemu_log_mask(LOG_GUEST_ERROR, "%s: register @ 0x%04x is write-only\n", + __func__, (unsigned int)offset); + break; + + case NPCM7XX_CLK_SECCNT: + now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + value = (now_ns - s->ref_ns) / NANOSECONDS_PER_SECOND; + break; + + case NPCM7XX_CLK_CNTR25M: + now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + /* + * This register counts 25 MHz cycles, updating every 640 ns. It rolls + * over to zero every second. + * + * The 4 LSBs are always zero: (1e9 / 640) << 4 = 25000000. + */ + value = (((now_ns - s->ref_ns) / 640) << 4) % 25000000; + break; + + default: + value = s->regs[reg]; + break; + }; + + trace_npcm7xx_clk_read(offset, value); + + return value; +} + +static void npcm7xx_clk_write(void *opaque, hwaddr offset, + uint64_t v, unsigned size) +{ + uint32_t reg = offset / sizeof(uint32_t); + NPCM7xxCLKState *s = opaque; + uint32_t value = v; + + trace_npcm7xx_clk_write(offset, value); + + if (reg >= NPCM7XX_CLK_NR_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: offset 0x%04x out of range\n", + __func__, (unsigned int)offset); + return; + } + + switch (reg) { + case NPCM7XX_CLK_SWRSTR: + qemu_log_mask(LOG_UNIMP, "%s: SW reset not implemented: 0x%02x\n", + __func__, value); + value = 0; + break; + + case NPCM7XX_CLK_PLLCON0: + case NPCM7XX_CLK_PLLCON1: + case NPCM7XX_CLK_PLLCON2: + case NPCM7XX_CLK_PLLCONG: + if (value & PLLCON_PWDEN) { + /* Power down -- clear lock and indicate loss of lock */ + value &= ~PLLCON_LOKI; + value |= PLLCON_LOKS; + } else { + /* Normal mode -- assume always locked */ + value |= PLLCON_LOKI; + /* Keep LOKS unchanged unless cleared by writing 1 */ + if (value & PLLCON_LOKS) { + value &= ~PLLCON_LOKS; + } else { + value |= (value & PLLCON_LOKS); + } + } + break; + + case NPCM7XX_CLK_CNTR25M: + qemu_log_mask(LOG_GUEST_ERROR, "%s: register @ 0x%04x is read-only\n", + __func__, (unsigned int)offset); + return; + } + + s->regs[reg] = value; +} + +static const struct MemoryRegionOps npcm7xx_clk_ops = { + .read = npcm7xx_clk_read, + .write = npcm7xx_clk_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + .unaligned = false, + }, +}; + +static void npcm7xx_clk_enter_reset(Object *obj, ResetType type) +{ + NPCM7xxCLKState *s = NPCM7XX_CLK(obj); + + QEMU_BUILD_BUG_ON(sizeof(s->regs) != sizeof(cold_reset_values)); + + switch (type) { + case RESET_TYPE_COLD: + memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values)); + s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + return; + } + + /* + * A small number of registers need to be reset on a core domain reset, + * but no such reset type exists yet. + */ + qemu_log_mask(LOG_UNIMP, "%s: reset type %d not implemented.", + __func__, type); +} + +static void npcm7xx_clk_init(Object *obj) +{ + NPCM7xxCLKState *s = NPCM7XX_CLK(obj); + + memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s, + TYPE_NPCM7XX_CLK, 4 * KiB); + sysbus_init_mmio(&s->parent, &s->iomem); +} + +static void npcm7xx_clk_class_init(ObjectClass *klass, void *data) +{ + ResettableClass *rc = RESETTABLE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "NPCM7xx Clock Control Registers"; + rc->phases.enter = npcm7xx_clk_enter_reset; +} + +static const TypeInfo npcm7xx_clk_info = { + .name = TYPE_NPCM7XX_CLK, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(NPCM7xxCLKState), + .instance_init = npcm7xx_clk_init, + .class_init = npcm7xx_clk_class_init, +}; + +static void npcm7xx_clk_register_type(void) +{ + type_register_static(&npcm7xx_clk_info); +} +type_init(npcm7xx_clk_register_type); diff --git a/hw/misc/trace-events b/hw/misc/trace-events index 1a20ce659a..cdc41fe391 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -107,6 +107,10 @@ mos6522_set_sr_int(void) "set sr_int" mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64 mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x" +# npcm7xx_clk.c +npcm7xx_clk_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 +npcm7xx_clk_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 + # npcm7xx_gcr.c npcm7xx_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h new file mode 100644 index 0000000000..a678b50ede --- /dev/null +++ b/include/hw/misc/npcm7xx_clk.h @@ -0,0 +1,65 @@ +/* + * Nuvoton NPCM7xx Clock Control Registers. + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef NPCM7XX_CLK_H +#define NPCM7XX_CLK_H + +#include "exec/memory.h" +#include "hw/sysbus.h" + +enum NPCM7xxCLKRegisters { + NPCM7XX_CLK_CLKEN1, + NPCM7XX_CLK_CLKSEL, + NPCM7XX_CLK_CLKDIV1, + NPCM7XX_CLK_PLLCON0, + NPCM7XX_CLK_PLLCON1, + NPCM7XX_CLK_SWRSTR, + NPCM7XX_CLK_IPSRST1 = 0x20 / sizeof(uint32_t), + NPCM7XX_CLK_IPSRST2, + NPCM7XX_CLK_CLKEN2, + NPCM7XX_CLK_CLKDIV2, + NPCM7XX_CLK_CLKEN3, + NPCM7XX_CLK_IPSRST3, + NPCM7XX_CLK_WD0RCR, + NPCM7XX_CLK_WD1RCR, + NPCM7XX_CLK_WD2RCR, + NPCM7XX_CLK_SWRSTC1, + NPCM7XX_CLK_SWRSTC2, + NPCM7XX_CLK_SWRSTC3, + NPCM7XX_CLK_SWRSTC4, + NPCM7XX_CLK_PLLCON2, + NPCM7XX_CLK_CLKDIV3, + NPCM7XX_CLK_CORSTC, + NPCM7XX_CLK_PLLCONG, + NPCM7XX_CLK_AHBCKFI, + NPCM7XX_CLK_SECCNT, + NPCM7XX_CLK_CNTR25M, + NPCM7XX_CLK_NR_REGS, +}; + +typedef struct NPCM7xxCLKState { + SysBusDevice parent; + + MemoryRegion iomem; + + uint32_t regs[NPCM7XX_CLK_NR_REGS]; + + /* Time reference for SECCNT and CNTR25M, initialized by power on reset */ + int64_t ref_ns; +} NPCM7xxCLKState; + +#define TYPE_NPCM7XX_CLK "npcm7xx-clk" +#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK) + +#endif /* NPCM7XX_CLK_H */ From patchwork Thu Jun 11 22:30:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Havard Skinnemoen X-Patchwork-Id: 280667 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.4 required=3.0 tests=DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2C025C433E0 for ; Thu, 11 Jun 2020 22:34:55 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id D766A2073E for ; Thu, 11 Jun 2020 22:34:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="hZa7CikX" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D766A2073E Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:40068 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jjVmg-0001v5-1B for qemu-devel@archiver.kernel.org; Thu, 11 Jun 2020 18:34:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33854) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3jLDiXgsKCnUaldbggXfhXgZhhZeX.VhfjXfn-WXoXeghgZgn.hkZ@flex--hskinnemoen.bounces.google.com>) id 1jjVii-0003xi-II for qemu-devel@nongnu.org; Thu, 11 Jun 2020 18:30:48 -0400 Received: from mail-yb1-xb49.google.com ([2607:f8b0:4864:20::b49]:32888) by eggs.gnu.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3jLDiXgsKCnUaldbggXfhXgZhhZeX.VhfjXfn-WXoXeghgZgn.hkZ@flex--hskinnemoen.bounces.google.com>) id 1jjVie-000477-JX for qemu-devel@nongnu.org; Thu, 11 Jun 2020 18:30:47 -0400 Received: by mail-yb1-xb49.google.com with SMTP id o84so8329857ybg.0 for ; Thu, 11 Jun 2020 15:30:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=ciOZoSVEXB4hCdxbs56mK0tCSIMyNwldRnd0zOpw/hk=; b=hZa7CikX4dbBTbvFX9ibd2T0YoORUfisOXmpatAptAwT0+yOFZhxYODHerHnbPmQ35 /Fxc3YJwRZXr4xI83cdGvjcj86moBryXgOVELRBwIo3cbXCAmbijT+fR3gwohgvCljcZ wJKLG/TOHRy9BzNqhl0kzoMw7Siy/+96zRk8RD/gGR36/t1UZ3dO3Ni4+9TTq1/g3k81 JPLuA14sGbo5xl3YpLzQk0a+K7xnM2zoQPiC2Npb2pxiKY3bxRMwmSFyT30yid3CQw0B /5Nkt05aBAKoPanX+fBoW/ADSosMynCaIkO5lG2Jfad8p60LRhDA2EdAemUj12Khn7jk avEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=ciOZoSVEXB4hCdxbs56mK0tCSIMyNwldRnd0zOpw/hk=; b=NNUkbn/VcO7SyQfgIYQd5y5wpCNn6bStfCZcsUsAjtU2UBQlJtMHsiEHIi6QxrYYbV pG0HLM0AO72coI2madqzoQGkVxVo/kgDkPZ/nmvbZx66uwZc6qxr94m8M39cwXq3+A2A c2ZHOMP0Z0R8bfWyGSJ6FwWmlVVYY35obUrMVlf4Z7iSLtQFQ07HO1iDX1nxgGHxoGat 66sfgPRhALjrlQobZhNfpw9sI3EF2onXFs9Rk+qLk20rD9V3vkVuRRnkv9WOVYEogDiT cbVMxe5Bx6cYJoF14DAwugT+/OpNo/nV19OnbQ5wsMbgdLdQTtCt2GKiJDOyh2jlgM1o UBMQ== X-Gm-Message-State: AOAM533ktJRwbATGxsGFs01JGyg6PqZw60kXypNpcsp2Eixc3BZ0/Fnk mdvknc5cM0hd3WH/nZEvstbzphL7Lta34D/ocg== X-Google-Smtp-Source: ABdhPJzN2Ie037Uxu3EwQr0icaTZ+E0nnXkp0v5JxiPHhkbMoQl6Mw029sYNvKJp8jIenj6CoTFuYhEVKuqp4TAVBg== X-Received: by 2002:a25:ec3:: with SMTP id 186mr18972179ybo.475.1591914636999; Thu, 11 Jun 2020 15:30:36 -0700 (PDT) Date: Thu, 11 Jun 2020 15:30:09 -0700 In-Reply-To: <20200611223016.259837-1-hskinnemoen@google.com> Message-Id: <20200611223016.259837-6-hskinnemoen@google.com> Mime-Version: 1.0 References: <20200611223016.259837-1-hskinnemoen@google.com> X-Mailer: git-send-email 2.27.0.290.gba653c62da-goog Subject: [PATCH v2 05/12] hw/arm: Add NPCM730 and NPCM750 SoC models From: Havard Skinnemoen To: peter.maydell@linaro.org, clg@kaod.org, joel@jms.id.au Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org, Avi.Fishman@nuvoton.com, kfting@nuvoton.com, Havard Skinnemoen Received-SPF: pass client-ip=2607:f8b0:4864:20::b49; envelope-from=3jLDiXgsKCnUaldbggXfhXgZhhZeX.VhfjXfn-WXoXeghgZgn.hkZ@flex--hskinnemoen.bounces.google.com; helo=mail-yb1-xb49.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -105 X-Spam_score: -10.6 X-Spam_bar: ---------- X-Spam_report: (-10.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-1, 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, URIBL_BLOCKED=0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" The Nuvoton NPCM7xx SoC family are used to implement Baseboard Management Controllers in servers. While the family includes four SoCs, this patch implements limited support for two of them: NPCM730 (targeted for Data Center applications) and NPCM750 (targeted for Enterprise applications). This patch includes little more than the bare minimum needed to boot a Linux kernel built with NPCM7xx support in direct-kernel mode: - Two Cortex-A9 CPU cores with built-in periperhals. - Global Configuration Registers. - Clock Management. - 3 Timer Modules with 5 timers each. - 4 serial ports. The chips themselves have a lot more features, some of which will be added to the model at a later stage. Reviewed-by: Tyrone Ting Reviewed-by: Joel Stanley Signed-off-by: Havard Skinnemoen --- MAINTAINERS | 2 + hw/arm/Makefile.objs | 1 + hw/arm/npcm7xx.c | 330 +++++++++++++++++++++++++++++++++++++++ include/hw/arm/npcm7xx.h | 80 ++++++++++ 4 files changed, 413 insertions(+) create mode 100644 hw/arm/npcm7xx.c create mode 100644 include/hw/arm/npcm7xx.h diff --git a/MAINTAINERS b/MAINTAINERS index 97d24b1443..077c86643c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -726,8 +726,10 @@ M: Havard Skinnemoen M: Tyrone Ting L: qemu-arm@nongnu.org S: Supported +F: hw/arm/npcm7xx* F: hw/misc/npcm7xx* F: hw/timer/npcm7xx* +F: include/hw/arm/npcm7xx* F: include/hw/misc/npcm7xx* F: include/hw/timer/npcm7xx* diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index 534a6a119e..13d163a599 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -41,6 +41,7 @@ obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o +obj-$(CONFIG_NPCM7XX) += npcm7xx.o obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c new file mode 100644 index 0000000000..a5dbf08c00 --- /dev/null +++ b/hw/arm/npcm7xx.c @@ -0,0 +1,330 @@ +/* + * Nuvoton NPCM7xx SoC family. + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "qemu/osdep.h" + +#include "exec/address-spaces.h" +#include "hw/arm/npcm7xx.h" +#include "hw/char/serial.h" +#include "hw/loader.h" +#include "hw/misc/unimp.h" +#include "hw/qdev-properties.h" +#include "qapi/error.h" +#include "qemu/units.h" +#include "sysemu/sysemu.h" + +/* The first half of the address space is reserved for DDR4 DRAM. */ +#define NPCM7XX_DRAM_BA (0x00000000) +#define NPCM7XX_DRAM_SZ (2 * GiB) + +/* + * This covers the whole MMIO space. We'll use this to catch any MMIO accesses + * that aren't handled by any device. + */ +#define NPCM7XX_MMIO_BA (0x80000000) +#define NPCM7XX_MMIO_SZ (0x7FFD0000) + +/* Core system modules. */ +#define NPCM7XX_L2C_BA (0xF03FC000) +#define NPCM7XX_CPUP_BA (0xF03FE000) +#define NPCM7XX_GCR_BA (0xF0800000) +#define NPCM7XX_CLK_BA (0xF0801000) + +/* Memory blocks at the end of the address space */ +#define NPCM7XX_RAM2_BA (0xFFFD0000) +#define NPCM7XX_RAM2_SZ (128 * KiB) +#define NPCM7XX_ROM_BA (0xFFFF0000) +#define NPCM7XX_ROM_SZ (64 * KiB) + +/* + * Interrupt lines going into the GIC. This does not include internal Cortex-A9 + * interrupts. + */ +enum NPCM7xxInterrupt { + NPCM7XX_UART0_IRQ = 2, + NPCM7XX_UART1_IRQ, + NPCM7XX_UART2_IRQ, + NPCM7XX_UART3_IRQ, + NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */ + NPCM7XX_TIMER1_IRQ, + NPCM7XX_TIMER2_IRQ, + NPCM7XX_TIMER3_IRQ, + NPCM7XX_TIMER4_IRQ, + NPCM7XX_TIMER5_IRQ, /* Timer Module 1 */ + NPCM7XX_TIMER6_IRQ, + NPCM7XX_TIMER7_IRQ, + NPCM7XX_TIMER8_IRQ, + NPCM7XX_TIMER9_IRQ, + NPCM7XX_TIMER10_IRQ, /* Timer Module 2 */ + NPCM7XX_TIMER11_IRQ, + NPCM7XX_TIMER12_IRQ, + NPCM7XX_TIMER13_IRQ, + NPCM7XX_TIMER14_IRQ, +}; + +/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */ +#define NPCM7XX_NUM_IRQ (160) + +/* Register base address for each Timer Module */ +static const hwaddr npcm7xx_tim_addr[] = { + 0xF0008000, + 0xF0009000, + 0xF000A000, +}; + +/* Register base address for each 16550 UART */ +static const hwaddr npcm7xx_uart_addr[] = { + 0xF0001000, + 0xF0002000, + 0xF0003000, + 0xF0004000, +}; + +void npcm7xx_write_secondary_boot(ARMCPU *cpu, const struct arm_boot_info *info) +{ + /* + * The default smpboot stub halts the secondary CPU with a 'wfi' + * instruction, but the arch/arm/mach-npcm/platsmp.c in the Linux kernel + * does not send an IPI to wake it up, so the second CPU fails to boot. So + * we need to provide our own smpboot stub that can not use 'wfi', it has + * to spin the secondary CPU until the first CPU writes to the SCRPAD reg. + */ + static const uint8_t smpboot[] = { + 0x18, 0x20, 0x9f, 0xe5, /* ldr r2, bootreg_addr */ + 0x00, 0x00, 0xa0, 0xe3, /* mov r0, #0 */ + 0x00, 0x00, 0x82, 0xe5, /* str r0, [r2] */ + 0x02, 0xf0, 0x20, 0xe3, /* wfe */ + 0x00, 0x10, 0x92, 0xe5, /* ldr r1, [r2] */ + 0x01, 0x00, 0x11, 0xe1, /* tst r1, r1 */ + 0xfb, 0xff, 0xff, 0x0a, /* beq */ + 0x11, 0xff, 0x2f, 0xe1, /* bx r1 */ + (NPCM7XX_SMP_BOOTREG_ADDR >> 0) & 0xff, + (NPCM7XX_SMP_BOOTREG_ADDR >> 8) & 0xff, + (NPCM7XX_SMP_BOOTREG_ADDR >> 16) & 0xff, + (NPCM7XX_SMP_BOOTREG_ADDR >> 24) & 0xff, + }; + + rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), + NPCM7XX_SMP_LOADER_START); +} + +static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n) +{ + return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n); +} + +static void npcm7xx_init(Object *obj) +{ + NPCM7xxState *s = NPCM7XX(obj); + int i; + + for (i = 0; i < NPCM7XX_MAX_NUM_CPUS; i++) { + object_initialize_child(obj, "cpu[*]", OBJECT(&s->cpu[i]), + sizeof(s->cpu[i]), + ARM_CPU_TYPE_NAME("cortex-a9"), + &error_abort, NULL); + } + + sysbus_init_child_obj(obj, "a9mpcore", &s->a9mpcore, + sizeof(s->a9mpcore), TYPE_A9MPCORE_PRIV); + sysbus_init_child_obj(obj, "gcr", OBJECT(&s->gcr), sizeof(s->gcr), + TYPE_NPCM7XX_GCR); + sysbus_init_child_obj(obj, "clk", OBJECT(&s->clk), sizeof(s->clk), + TYPE_NPCM7XX_CLK); + + for (i = 0; i < ARRAY_SIZE(s->tim); i++) { + sysbus_init_child_obj(obj, "tim[*]", OBJECT(&s->tim[i]), + sizeof(s->tim[i]), TYPE_NPCM7XX_TIMER); + } +} + +static void npcm7xx_realize(DeviceState *dev, Error **errp) +{ + NPCM7xxState *s = NPCM7XX(dev); + NPCM7xxClass *sc = NPCM7XX_GET_CLASS(s); + Error *err = NULL; + int i; + + /* I/O space -- unimplemented unless overridden below. */ + create_unimplemented_device("npcm7xx.io", NPCM7XX_MMIO_BA, NPCM7XX_MMIO_SZ); + + /* CPUs */ + for (i = 0; i < sc->num_cpus; i++) { + object_property_set_int(OBJECT(&s->cpu[i]), + arm_cpu_mp_affinity(i, NPCM7XX_MAX_NUM_CPUS), + "mp-affinity", &error_abort); + object_property_set_int(OBJECT(&s->cpu[i]), NPCM7XX_GIC_CPU_IF_ADDR, + "reset-cbar", &error_abort); + object_property_set_bool(OBJECT(&s->cpu[i]), true, + "reset-hivecs", &error_abort); + + /* Disable security extensions. */ + if (object_property_find(OBJECT(&s->cpu[i]), "has_el3", NULL)) { + object_property_set_bool(OBJECT(&s->cpu[i]), false, "has_el3", + &error_abort); + } + + object_property_set_bool(OBJECT(&s->cpu[i]), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + } + + /* A9MPCORE peripherals */ + object_property_set_int(OBJECT(&s->a9mpcore), sc->num_cpus, "num-cpu", + &error_abort); + object_property_set_int(OBJECT(&s->a9mpcore), NPCM7XX_NUM_IRQ, "num-irq", + &error_abort); + object_property_set_bool(OBJECT(&s->a9mpcore), true, "realized", + &error_abort); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->a9mpcore), 0, NPCM7XX_CPUP_BA); + + for (i = 0; i < sc->num_cpus; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i, + qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_IRQ)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i + sc->num_cpus, + qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_FIQ)); + } + + /* L2 cache controller */ + sysbus_create_simple("l2x0", NPCM7XX_L2C_BA, NULL); + + /* System Global Control Registers (GCR) */ + object_property_set_int(OBJECT(&s->gcr), sc->disabled_modules, + "disabled-modules", &err); + object_property_set_link(OBJECT(&s->gcr), OBJECT(s->dram), "dram", &err); + if (err) { + error_propagate(errp, err); + return; + } + object_property_set_bool(OBJECT(&s->gcr), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gcr), 0, NPCM7XX_GCR_BA); + + /* Clock Control Registers (CLK) */ + object_property_set_bool(OBJECT(&s->clk), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->clk), 0, NPCM7XX_CLK_BA); + + /* Timer Modules (TIM) */ + QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim)); + for (i = 0; i < ARRAY_SIZE(s->tim); i++) { + Object *t = OBJECT(&s->tim[i]); + int first_irq; + int j; + + object_property_set_bool(t, true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(t), 0, npcm7xx_tim_addr[i]); + + first_irq = NPCM7XX_TIMER0_IRQ + i * NPCM7XX_TIMERS_PER_CTRL; + for (j = 0; j < NPCM7XX_TIMERS_PER_CTRL; j++) { + qemu_irq irq = npcm7xx_irq(s, first_irq + j); + sysbus_connect_irq(SYS_BUS_DEVICE(t), j, irq); + } + } + + /* UART0..3 (16550 compatible) */ + for (i = 0; i < ARRAY_SIZE(npcm7xx_uart_addr); i++) { + serial_mm_init(get_system_memory(), npcm7xx_uart_addr[i], 2, + npcm7xx_irq(s, NPCM7XX_UART0_IRQ + i), 115200, + serial_hd(i), DEVICE_LITTLE_ENDIAN); + } + + /* RAM2 (SRAM) */ + memory_region_init_ram(&s->sram, OBJECT(dev), "ram2", + NPCM7XX_RAM2_SZ, &err); + if (err) { + error_propagate(errp, err); + return; + } + memory_region_add_subregion(get_system_memory(), NPCM7XX_RAM2_BA, &s->sram); + + /* Internal ROM */ + memory_region_init_rom(&s->irom, OBJECT(dev), "irom", NPCM7XX_ROM_SZ, &err); + if (err) { + error_propagate(errp, err); + return; + } + memory_region_add_subregion(get_system_memory(), NPCM7XX_ROM_BA, &s->irom); + + /* External DDR4 SDRAM */ + memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, s->dram); +} + +static Property npcm7xx_properties[] = { + DEFINE_PROP_LINK("dram", NPCM7xxState, dram, TYPE_MEMORY_REGION, + MemoryRegion *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void npcm7xx_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = npcm7xx_realize; + dc->user_creatable = false; + device_class_set_props(dc, npcm7xx_properties); +} + +static void npcm730_class_init(ObjectClass *oc, void *data) +{ + NPCM7xxClass *nc = NPCM7XX_CLASS(oc); + + /* NPCM730 is optimized for data center use, so no graphics, etc. */ + nc->disabled_modules = 0x00300395; + nc->num_cpus = 2; +} + +static void npcm750_class_init(ObjectClass *oc, void *data) +{ + NPCM7xxClass *nc = NPCM7XX_CLASS(oc); + + /* NPCM750 has 2 cores and a full set of peripherals */ + nc->disabled_modules = 0x00000000; + nc->num_cpus = 2; +} + +static const TypeInfo npcm7xx_soc_types[] = { + { + .name = TYPE_NPCM7XX, + .parent = TYPE_DEVICE, + .instance_size = sizeof(NPCM7xxState), + .instance_init = npcm7xx_init, + .class_size = sizeof(NPCM7xxClass), + .class_init = npcm7xx_class_init, + .abstract = true, + }, { + .name = TYPE_NPCM730, + .parent = TYPE_NPCM7XX, + .class_init = npcm730_class_init, + }, { + .name = TYPE_NPCM750, + .parent = TYPE_NPCM7XX, + .class_init = npcm750_class_init, + }, +}; + +DEFINE_TYPES(npcm7xx_soc_types); diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h new file mode 100644 index 0000000000..38b8c33729 --- /dev/null +++ b/include/hw/arm/npcm7xx.h @@ -0,0 +1,80 @@ +/* + * Nuvoton NPCM7xx SoC family. + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef NPCM7XX_H +#define NPCM7XX_H + +#include "hw/boards.h" +#include "hw/cpu/a9mpcore.h" +#include "hw/misc/npcm7xx_clk.h" +#include "hw/misc/npcm7xx_gcr.h" +#include "hw/timer/npcm7xx_timer.h" +#include "target/arm/cpu.h" + +#define NPCM7XX_MAX_NUM_CPUS (2) + +/* Magic addresses for setting up direct kernel booting and SMP boot stubs. */ +#define NPCM7XX_LOADER_START (0x00000000) /* Start of SDRAM */ +#define NPCM7XX_SMP_LOADER_START (0xFFFF0000) /* Boot ROM */ +#define NPCM7XX_SMP_BOOTREG_ADDR (0xF080013C) /* GCR.SCRPAD */ +#define NPCM7XX_GIC_CPU_IF_ADDR (0xF03FE100) /* GIC within A9 */ + +typedef struct NPCM7xxState { + DeviceState parent; + + ARMCPU cpu[NPCM7XX_MAX_NUM_CPUS]; + A9MPPrivState a9mpcore; + + MemoryRegion sram; + MemoryRegion irom; + MemoryRegion *dram; + + NPCM7xxGCRState gcr; + NPCM7xxCLKState clk; + NPCM7xxTimerCtrlState tim[3]; +} NPCM7xxState; + +#define TYPE_NPCM7XX "npcm7xx" +#define NPCM7XX(obj) OBJECT_CHECK(NPCM7xxState, (obj), TYPE_NPCM7XX) + +#define TYPE_NPCM730 "npcm730" +#define TYPE_NPCM750 "npcm750" + +typedef struct NPCM7xxClass { + DeviceClass parent; + + /* Bitmask of modules that are permanently disabled on this chip. */ + uint32_t disabled_modules; + /* Number of CPU cores enabled in this SoC class (may be 1 or 2). */ + uint32_t num_cpus; +} NPCM7xxClass; + +#define NPCM7XX_CLASS(klass) \ + OBJECT_CLASS_CHECK(NPCM7xxClass, (klass), TYPE_NPCM7XX) +#define NPCM7XX_GET_CLASS(obj) \ + OBJECT_GET_CLASS(NPCM7xxClass, (obj), TYPE_NPCM7XX) + +/** + * npcm7xx_write_secondary_boot - Write stub for booting secondary CPU. + * @cpu: The CPU to be booted. + * @info: Boot info structure for the board. + * + * This will write a short code stub to the internal ROM that will keep the + * secondary CPU spinning until the primary CPU writes an address to the SCRPAD + * register in the GCR, after which the secondary CPU will jump there. + */ +extern void npcm7xx_write_secondary_boot(ARMCPU *cpu, + const struct arm_boot_info *info); + +#endif /* NPCM7XX_H */ From patchwork Thu Jun 11 22:30:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Havard Skinnemoen X-Patchwork-Id: 280666 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-22.4 required=3.0 tests=DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7B407C433DF for ; Thu, 11 Jun 2020 22:35:24 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 442BA2068E for ; Thu, 11 Jun 2020 22:35:24 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="tXzfT3N8" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 442BA2068E Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:41870 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jjVn9-0002ej-GF for qemu-devel@archiver.kernel.org; Thu, 11 Jun 2020 18:35:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33952) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3kLDiXgsKCnkephfkkbjlbkdlldib.Zljnbjr-absbiklkdkr.lod@flex--hskinnemoen.bounces.google.com>) id 1jjVik-00041I-QT for qemu-devel@nongnu.org; Thu, 11 Jun 2020 18:30:50 -0400 Received: from mail-yb1-xb49.google.com ([2607:f8b0:4864:20::b49]:34848) by eggs.gnu.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3kLDiXgsKCnkephfkkbjlbkdlldib.Zljnbjr-absbiklkdkr.lod@flex--hskinnemoen.bounces.google.com>) id 1jjVii-00049Z-UF for qemu-devel@nongnu.org; Thu, 11 Jun 2020 18:30:50 -0400 Received: by mail-yb1-xb49.google.com with SMTP id w9so8339388ybt.2 for ; Thu, 11 Jun 2020 15:30:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=oSdui/Du7unAC6uctVO3rzywqjb0HcKiSu95MGjPi34=; b=tXzfT3N8pyKe8hMoNVzbztNe5BZdTMZxKYehpDacvvpxhEgL4PvzeLnW9lRR/gnJrF bWj7wOhwqoMrBAd0LRfmE1ywPuZwTQabE6tNBtnsWDTBNciGecy+RXP4kMXptVZ3N6g/ ze/0tSEbL5uWYer7YwByBlcs+xlnqw/tMcep6Ogt7j/avDecSZYCNNbOIr5aDtSt0A1Q kQPyalCQEACpGHAxBiOKUsxgsyE3/neP3WFx2U/G4v9o0ZfUM9thDr4Pd6sHmoh9LjVN H20HGZiKOoSXF628as46B+TLSvRchhNsLXtepMefjgKvR5nUGfvN+cwPSTFkpQ8Y3mxl N0Iw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=oSdui/Du7unAC6uctVO3rzywqjb0HcKiSu95MGjPi34=; b=YOWPRHXf+cXoHsu7sZIggWhDILmszPkJJ2Hw9iSX/SzKSVUJAjGoJDG10U5FokJcws ltAMZS4bsiWV6SNtUajSaHgbmuAde0rhoKXwiI16/V9yH/hSV2DF3Bith80/qPgFZdJ1 Mm1W50pcr5Nvt3Yv6KaWncQW10KzQFyvMigLWj2oBFGCvw1ZSe6PO8OL+zre6UyFsRCc e8GbjGr5TD1Y9qlmeK3AgraCZEUqdbo1NzSAvnlWFL4O+mCdwkg9lb1O1Y1AyVUIhVYX JvaobmcbVeH9scq/VldsChBbOYwerQspTBCxfrhA84yWCyUGcULFPWA1ae7GFH+t6uNC SPPA== X-Gm-Message-State: AOAM531lg++PTRIKc5f9oIfPZyPuJVimbevJBBgVUkvCnY0cq+SgxOfB uj243vnic+RfxMF/9JN6uEn1vOIQuWTJaONlhg== X-Google-Smtp-Source: ABdhPJz8KHHNCqPidaGhncG+RfSlWVi4excxeEd/mURg7Ymfx4f9ssl7QG4b9QfJOb6n6h5mwpLhxw489sZ/4XqO4w== X-Received: by 2002:a25:ce50:: with SMTP id x77mr18453626ybe.253.1591914640626; Thu, 11 Jun 2020 15:30:40 -0700 (PDT) Date: Thu, 11 Jun 2020 15:30:11 -0700 In-Reply-To: <20200611223016.259837-1-hskinnemoen@google.com> Message-Id: <20200611223016.259837-8-hskinnemoen@google.com> Mime-Version: 1.0 References: <20200611223016.259837-1-hskinnemoen@google.com> X-Mailer: git-send-email 2.27.0.290.gba653c62da-goog Subject: [PATCH v2 07/12] hw/arm: Load -bios image as a boot ROM for npcm7xx From: Havard Skinnemoen To: peter.maydell@linaro.org, clg@kaod.org, joel@jms.id.au Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org, Avi.Fishman@nuvoton.com, kfting@nuvoton.com, Havard Skinnemoen Received-SPF: pass client-ip=2607:f8b0:4864:20::b49; envelope-from=3kLDiXgsKCnkephfkkbjlbkdlldib.Zljnbjr-absbiklkdkr.lod@flex--hskinnemoen.bounces.google.com; helo=mail-yb1-xb49.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -105 X-Spam_score: -10.6 X-Spam_bar: ---------- X-Spam_report: (-10.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-1, 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, USER_IN_DEF_DKIM_WL=-7.5 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" If a -bios option is specified on the command line, load the image into the internal ROM memory region, which contains the first instructions run by the CPU after reset. A minimal Apache-2.0-licensed boot ROM can be found at https://github.com/google/vbootrom It is by no means feature complete, but it is enough to launch the Nuvoton bootblock[1] from offset 0 in the flash, which in turn will launch u-boot and finally the Linux kernel. [1] https://github.com/Nuvoton-Israel/bootblock Change-Id: I41eae4fc7786d33f532c14087e930bf1b5012562 Reviewed-by: Tyrone Ting Signed-off-by: Havard Skinnemoen --- hw/arm/npcm7xx.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c index a5dbf08c00..417bc16b5c 100644 --- a/hw/arm/npcm7xx.c +++ b/hw/arm/npcm7xx.c @@ -22,6 +22,7 @@ #include "hw/misc/unimp.h" #include "hw/qdev-properties.h" #include "qapi/error.h" +#include "qemu-common.h" #include "qemu/units.h" #include "sysemu/sysemu.h" @@ -270,6 +271,22 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp) } memory_region_add_subregion(get_system_memory(), NPCM7XX_ROM_BA, &s->irom); + if (bios_name) { + g_autofree char *filename = NULL; + int ret; + + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + if (!filename) { + error_setg(errp, "Could not find ROM image '%s'", bios_name); + return; + } + ret = load_image_mr(filename, &s->irom); + if (ret < 0) { + error_setg(errp, "Failed to load ROM image '%s'", filename); + return; + } + } + /* External DDR4 SDRAM */ memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, s->dram); } From patchwork Thu Jun 11 22:30:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Havard Skinnemoen X-Patchwork-Id: 280665 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.4 required=3.0 tests=DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BF179C433DF for ; Thu, 11 Jun 2020 22:37:32 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 7BF272073E for ; Thu, 11 Jun 2020 22:37:32 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="iCKQe0pM" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7BF272073E Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:49106 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jjVpD-0006hO-Kj for qemu-devel@archiver.kernel.org; Thu, 11 Jun 2020 18:37:31 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34012) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3krDiXgsKCnsgrjhmmdlndmfnnfkd.bnlpdlt-cdudkmnmfmt.nqf@flex--hskinnemoen.bounces.google.com>) id 1jjVim-00044X-2h for qemu-devel@nongnu.org; Thu, 11 Jun 2020 18:30:52 -0400 Received: from mail-yb1-xb4a.google.com ([2607:f8b0:4864:20::b4a]:32889) by eggs.gnu.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3krDiXgsKCnsgrjhmmdlndmfnnfkd.bnlpdlt-cdudkmnmfmt.nqf@flex--hskinnemoen.bounces.google.com>) id 1jjVij-0004An-K0 for qemu-devel@nongnu.org; Thu, 11 Jun 2020 18:30:51 -0400 Received: by mail-yb1-xb4a.google.com with SMTP id o84so8330222ybg.0 for ; Thu, 11 Jun 2020 15:30:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=i4tv8xxRdBtrus7+nTWEmLZQCTSTfD0hL1Td9tmJuSs=; b=iCKQe0pMTCc8VwHEObS4C0isTsuCvbl/3GXC73vCI0JoXY6e87IM2kM7op2Yvmw4kF BmBlqR75En7GGp5+kZU97UFknKZAOYz31V5nU1sN/RzfVOSb6tz2AlSaqtNGgARtwgn0 uXnELIpmMqJfZJgd3+lUyeoPrZ7S7SWvjwIk5ma30t/IkiQtoBChxNUIdj18k/V9EY/j VSAU7qpOZqW6USQl0KKEd00LSDGAIlKEfYl8HZNyPvOClGE6ZR73y/IdVj5ziJN3ylgO T6OVcH7skvdii6YJFHOvZs0RgxJ+6Kf/pzdt09dNgUHHeXQXSQb8PVhDSllL88Mf0DlZ KxsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=i4tv8xxRdBtrus7+nTWEmLZQCTSTfD0hL1Td9tmJuSs=; b=FBG+EU2Si3M1i0oi5I3e9lDaJLtBjob6cH3YE5qtdyS8nxxy98kDoOND/1/E+KPmIE HL2a3YqxMDLdvwCq5Jji2Oku1Pk3U0Vbr8EqIMKZFPyUzRcpOTQBQNRaDhc9dendDhQz 5V0TXwIFnJUXkPwLyeL6UEYRc+GCDk2i1RbSqvir1RCfPlTIVxRR+TUDQ7J2q0nP6h8L tilpdODseA4RqfttP6vwcc7IuXGLIsShO5ut8pQG2zItwaKabDlyo5YLr5QrJVR6BmlK flhHon8cJdf8yINXueuNLu8x/8ZqRurHc2yfO3LVYgq/xqhkMxnxbsq2OMnVj0cEtjWv 62jQ== X-Gm-Message-State: AOAM531XVXA1yv2ULh220gqWuw1BdMqxNsgu8MYUAvtfaxeS7Eh+V3m9 OCaryYvgShsDvq1xTc6uwI63Sb+mHbaX6mQL6g== X-Google-Smtp-Source: ABdhPJyJSTR0kubUFkz3NG+ZFJgeJDe7sWQzeLtBUM2V1SLvfEC5Usn1Grh9so0TWw+3xKAmb6ogfsiKLrdFzuipvQ== X-Received: by 2002:a25:e747:: with SMTP id e68mr13588358ybh.341.1591914642389; Thu, 11 Jun 2020 15:30:42 -0700 (PDT) Date: Thu, 11 Jun 2020 15:30:12 -0700 In-Reply-To: <20200611223016.259837-1-hskinnemoen@google.com> Message-Id: <20200611223016.259837-9-hskinnemoen@google.com> Mime-Version: 1.0 References: <20200611223016.259837-1-hskinnemoen@google.com> X-Mailer: git-send-email 2.27.0.290.gba653c62da-goog Subject: [PATCH v2 08/12] hw/nvram: NPCM7xx OTP device model From: Havard Skinnemoen To: peter.maydell@linaro.org, clg@kaod.org, joel@jms.id.au Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org, Avi.Fishman@nuvoton.com, kfting@nuvoton.com, Havard Skinnemoen , Avi Fishman Received-SPF: pass client-ip=2607:f8b0:4864:20::b4a; envelope-from=3krDiXgsKCnsgrjhmmdlndmfnnfkd.bnlpdlt-cdudkmnmfmt.nqf@flex--hskinnemoen.bounces.google.com; helo=mail-yb1-xb4a.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -105 X-Spam_score: -10.6 X-Spam_bar: ---------- X-Spam_report: (-10.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-1, 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, USER_IN_DEF_DKIM_WL=-7.5 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This supports reading and writing OTP fuses and keys. Only fuse reading has been tested. Protection is not implemented. Change-Id: Ie67d7e2ed5e1010061b7383c71a8ba0611794103 Reviewed-by: Avi Fishman Signed-off-by: Havard Skinnemoen --- MAINTAINERS | 2 + hw/arm/npcm7xx.c | 32 +++ hw/nvram/Makefile.objs | 1 + hw/nvram/npcm7xx_otp.c | 391 +++++++++++++++++++++++++++++++++ include/hw/arm/npcm7xx.h | 3 + include/hw/nvram/npcm7xx_otp.h | 93 ++++++++ 6 files changed, 522 insertions(+) create mode 100644 hw/nvram/npcm7xx_otp.c create mode 100644 include/hw/nvram/npcm7xx_otp.h diff --git a/MAINTAINERS b/MAINTAINERS index 077c86643c..9814e7b4c4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -728,9 +728,11 @@ L: qemu-arm@nongnu.org S: Supported F: hw/arm/npcm7xx* F: hw/misc/npcm7xx* +F: hw/nvram/npcm7xx* F: hw/timer/npcm7xx* F: include/hw/arm/npcm7xx* F: include/hw/misc/npcm7xx* +F: include/hw/nvram/npcm7xx* F: include/hw/timer/npcm7xx* nSeries diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c index 417bc16b5c..f9e3b5842b 100644 --- a/hw/arm/npcm7xx.c +++ b/hw/arm/npcm7xx.c @@ -37,6 +37,10 @@ #define NPCM7XX_MMIO_BA (0x80000000) #define NPCM7XX_MMIO_SZ (0x7FFD0000) +/* OTP key storage and fuse strap array */ +#define NPCM7XX_OTP1_BA (0xF0189000) +#define NPCM7XX_OTP2_BA (0xF018a000) + /* Core system modules. */ #define NPCM7XX_L2C_BA (0xF03FC000) #define NPCM7XX_CPUP_BA (0xF03FE000) @@ -121,6 +125,15 @@ void npcm7xx_write_secondary_boot(ARMCPU *cpu, const struct arm_boot_info *info) NPCM7XX_SMP_LOADER_START); } +static void npcm7xx_init_fuses(NPCM7xxState *s) +{ + NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s); + uint32_t value; + + value = tswap32(nc->disabled_modules); + npcm7xx_otp_array_write(&s->fuse_array, &value, 64, sizeof(value)); +} + static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n) { return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n); @@ -144,6 +157,10 @@ static void npcm7xx_init(Object *obj) TYPE_NPCM7XX_GCR); sysbus_init_child_obj(obj, "clk", OBJECT(&s->clk), sizeof(s->clk), TYPE_NPCM7XX_CLK); + sysbus_init_child_obj(obj, "otp1", OBJECT(&s->key_storage), + sizeof(s->key_storage), TYPE_NPCM7XX_KEY_STORAGE); + sysbus_init_child_obj(obj, "otp2", OBJECT(&s->fuse_array), + sizeof(s->fuse_array), TYPE_NPCM7XX_FUSE_ARRAY); for (i = 0; i < ARRAY_SIZE(s->tim); i++) { sysbus_init_child_obj(obj, "tim[*]", OBJECT(&s->tim[i]), @@ -226,6 +243,21 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp) } sysbus_mmio_map(SYS_BUS_DEVICE(&s->clk), 0, NPCM7XX_CLK_BA); + /* OTP key storage and fuse strap array */ + object_property_set_bool(OBJECT(&s->key_storage), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->key_storage), 0, NPCM7XX_OTP1_BA); + object_property_set_bool(OBJECT(&s->fuse_array), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->fuse_array), 0, NPCM7XX_OTP2_BA); + npcm7xx_init_fuses(s); + /* Timer Modules (TIM) */ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim)); for (i = 0; i < ARRAY_SIZE(s->tim); i++) { diff --git a/hw/nvram/Makefile.objs b/hw/nvram/Makefile.objs index f3ad921382..0270f0bbf7 100644 --- a/hw/nvram/Makefile.objs +++ b/hw/nvram/Makefile.objs @@ -4,5 +4,6 @@ common-obj-$(CONFIG_AT24C) += eeprom_at24c.o common-obj-y += fw_cfg.o common-obj-$(CONFIG_CHRP_NVRAM) += chrp_nvram.o common-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o +common-obj-$(CONFIG_NPCM7XX) += npcm7xx_otp.o common-obj-$(CONFIG_NRF51_SOC) += nrf51_nvm.o obj-$(CONFIG_PSERIES) += spapr_nvram.o diff --git a/hw/nvram/npcm7xx_otp.c b/hw/nvram/npcm7xx_otp.c new file mode 100644 index 0000000000..71fc728a2d --- /dev/null +++ b/hw/nvram/npcm7xx_otp.c @@ -0,0 +1,391 @@ +/* + * Nuvoton NPCM7xx OTP (Fuse Array) Interface + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "qemu/osdep.h" + +#include "hw/nvram/npcm7xx_otp.h" +#include "qapi/error.h" +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/units.h" + +/* Each module has 4 KiB of register space. Only a fraction of it is used. */ +#define NPCM7XX_OTP_REGS_SIZE (4 * KiB) + +/* Register field definitions. */ +#define FST_RIEN BIT(2) +#define FST_RDST BIT(1) +#define FST_RDY BIT(0) +#define FST_RO_MASK (FST_RDST | FST_RDY) + +#define FADDR_BYTEADDR(rv) extract32((rv), 0, 10) +#define FADDR_BITPOS(rv) extract32((rv), 10, 3) + +#define FDATA_CLEAR 0x00000001 + +#define FCFG_FDIS BIT(31) +#define FCFG_FCFGLK_MASK 0x00ff0000 + +#define FCTL_PROG_CMD1 0x00000001 +#define FCTL_PROG_CMD2 0xbf79e5d0 +#define FCTL_READ_CMD 0x00000002 + +static uint8_t ecc_encode_nibble(uint8_t n) +{ + uint8_t result = n; + + result |= (((n >> 0) & 1) ^ ((n >> 1) & 1)) << 4; + result |= (((n >> 2) & 1) ^ ((n >> 3) & 1)) << 5; + result |= (((n >> 0) & 1) ^ ((n >> 2) & 1)) << 6; + result |= (((n >> 1) & 1) ^ ((n >> 3) & 1)) << 7; + + return result; +} + +void npcm7xx_otp_array_write(NPCM7xxOTPState *s, const void *data, + unsigned int offset, unsigned int len) +{ + const uint8_t *src = data; + uint8_t *dst = s->array + offset; + + while (len-- > 0) { + uint8_t c = *src++; + + *dst++ = ecc_encode_nibble(extract8(c, 0, 4)); + *dst++ = ecc_encode_nibble(extract8(c, 4, 4)); + } +} + +/* Common register read handler for both OTP classes. */ +static uint64_t npcm7xx_otp_read(NPCM7xxOTPState *s, NPCM7xxOTPRegister reg) +{ + uint32_t value = 0; + + switch (reg) { + case NPCM7XX_OTP_FST: + case NPCM7XX_OTP_FADDR: + case NPCM7XX_OTP_FDATA: + case NPCM7XX_OTP_FCFG: + value = s->regs[reg]; + break; + + case NPCM7XX_OTP_FCTL: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: read from write-only FCTL register\n", + DEVICE(s)->canonical_path); + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: read from invalid offset 0x%zx\n", + DEVICE(s)->canonical_path, reg * sizeof(uint32_t)); + break; + } + + return value; +} + +/* Read a byte from the OTP array into the data register. */ +static void npcm7xx_otp_read_array(NPCM7xxOTPState *s) +{ + uint32_t faddr = s->regs[NPCM7XX_OTP_FADDR]; + + s->regs[NPCM7XX_OTP_FDATA] = s->array[FADDR_BYTEADDR(faddr)]; + s->regs[NPCM7XX_OTP_FST] |= FST_RDST | FST_RDY; +} + +/* Program a byte from the data register into the OTP array. */ +static void npcm7xx_otp_program_array(NPCM7xxOTPState *s) +{ + uint32_t faddr = s->regs[NPCM7XX_OTP_FADDR]; + + /* Bits can only go 0->1, never 1->0. */ + s->array[FADDR_BYTEADDR(faddr)] |= (1U << FADDR_BITPOS(faddr)); + s->regs[NPCM7XX_OTP_FST] |= FST_RDST | FST_RDY; +} + +/* Compute the next value of the FCFG register. */ +static uint32_t npcm7xx_otp_compute_fcfg(uint32_t cur_value, uint32_t new_value) +{ + uint32_t lock_mask; + uint32_t value; + + /* + * FCFGLK holds sticky bits 16..23, indicating which bits in FPRGLK (8..15) + * and FRDLK (0..7) that are read-only. + */ + lock_mask = (cur_value & FCFG_FCFGLK_MASK) >> 8; + lock_mask |= lock_mask >> 8; + /* FDIS and FCFGLK bits are sticky (write 1 to set; can't clear). */ + value = cur_value & (FCFG_FDIS | FCFG_FCFGLK_MASK); + /* Preserve read-only bits in FPRGLK and FRDLK */ + value |= cur_value & lock_mask; + /* Set all bits that aren't read-only. */ + value |= new_value & ~lock_mask; + + return value; +} + +/* Common register write handler for both OTP classes. */ +static void npcm7xx_otp_write(NPCM7xxOTPState *s, NPCM7xxOTPRegister reg, + uint32_t value) +{ + switch (reg) { + case NPCM7XX_OTP_FST: + /* RDST is cleared by writing 1 to it. */ + if (value & FST_RDST) { + s->regs[NPCM7XX_OTP_FST] &= ~FST_RDST; + } + /* Preserve read-only and write-one-to-clear bits */ + value = + (value & ~FST_RO_MASK) | (s->regs[NPCM7XX_OTP_FST] & FST_RO_MASK); + break; + + case NPCM7XX_OTP_FADDR: + break; + + case NPCM7XX_OTP_FDATA: + /* + * This register is cleared by writing a magic value to it; no other + * values can be written. + */ + if (value == FDATA_CLEAR) { + value = 0; + } else { + value = s->regs[NPCM7XX_OTP_FDATA]; + } + break; + + case NPCM7XX_OTP_FCFG: + value = npcm7xx_otp_compute_fcfg(s->regs[NPCM7XX_OTP_FCFG], value); + break; + + case NPCM7XX_OTP_FCTL: + switch (value) { + case FCTL_READ_CMD: + npcm7xx_otp_read_array(s); + break; + + case FCTL_PROG_CMD1: + /* + * Programming requires writing two separate magic values to this + * register; this is the first one. Just store it so it can be + * verified later when the second magic value is received. + */ + break; + + case FCTL_PROG_CMD2: + /* + * Only initiate programming if we received the first half of the + * command immediately before this one. + */ + if (s->regs[NPCM7XX_OTP_FCTL] == FCTL_PROG_CMD1) { + npcm7xx_otp_program_array(s); + } + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: unrecognized FCNTL value 0x%" PRIx32 "\n", + DEVICE(s)->canonical_path, value); + break; + } + if (value != FCTL_PROG_CMD1) { + value = 0; + } + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: write to invalid offset 0x%zx\n", + DEVICE(s)->canonical_path, reg * sizeof(uint32_t)); + return; + } + + s->regs[reg] = value; +} + +/* Register read handler specific to the fuse array OTP module. */ +static uint64_t npcm7xx_fuse_array_read(void *opaque, hwaddr addr, + unsigned int size) +{ + NPCM7xxOTPRegister reg = addr / sizeof(uint32_t); + NPCM7xxOTPState *s = opaque; + uint32_t value; + + /* + * Only the Fuse Strap register needs special handling; all other registers + * work the same way for both kinds of OTP modules. + */ + if (reg != NPCM7XX_OTP_FUSTRAP) { + value = npcm7xx_otp_read(s, reg); + } else { + /* FUSTRAP is stored as three copies in the OTP array. */ + uint32_t fustrap[3]; + + memcpy(fustrap, &s->array[0], sizeof(fustrap)); + + /* Determine value by a majority vote on each bit. */ + value = (fustrap[0] & fustrap[1]) | (fustrap[0] & fustrap[2]) | + (fustrap[1] & fustrap[2]); + } + + return value; +} + +/* Register write handler specific to the fuse array OTP module. */ +static void npcm7xx_fuse_array_write(void *opaque, hwaddr addr, uint64_t v, + unsigned int size) +{ + NPCM7xxOTPRegister reg = addr / sizeof(uint32_t); + NPCM7xxOTPState *s = opaque; + + /* + * The Fuse Strap register is read-only. Other registers are handled by + * common code. + */ + if (reg != NPCM7XX_OTP_FUSTRAP) { + npcm7xx_otp_write(s, reg, v); + } +} + +static const MemoryRegionOps npcm7xx_fuse_array_ops = { + .read = npcm7xx_fuse_array_read, + .write = npcm7xx_fuse_array_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + .unaligned = false, + }, +}; + +/* Register read handler specific to the key storage OTP module. */ +static uint64_t npcm7xx_key_storage_read(void *opaque, hwaddr addr, + unsigned int size) +{ + NPCM7xxOTPRegister reg = addr / sizeof(uint32_t); + NPCM7xxOTPState *s = opaque; + + /* + * Only the Fuse Key Index register needs special handling; all other + * registers work the same way for both kinds of OTP modules. + */ + if (reg != NPCM7XX_OTP_FKEYIND) { + return npcm7xx_otp_read(s, reg); + } + + qemu_log_mask(LOG_UNIMP, "%s: FKEYIND is not implemented\n", __func__); + + return s->regs[NPCM7XX_OTP_FKEYIND]; +} + +/* Register write handler specific to the key storage OTP module. */ +static void npcm7xx_key_storage_write(void *opaque, hwaddr addr, uint64_t v, + unsigned int size) +{ + NPCM7xxOTPRegister reg = addr / sizeof(uint32_t); + NPCM7xxOTPState *s = opaque; + + /* + * Only the Fuse Key Index register needs special handling; all other + * registers work the same way for both kinds of OTP modules. + */ + if (reg != NPCM7XX_OTP_FKEYIND) { + npcm7xx_otp_write(s, reg, v); + return; + } + + qemu_log_mask(LOG_UNIMP, "%s: FKEYIND is not implemented\n", __func__); + + s->regs[NPCM7XX_OTP_FKEYIND] = v; +} + +static const MemoryRegionOps npcm7xx_key_storage_ops = { + .read = npcm7xx_key_storage_read, + .write = npcm7xx_key_storage_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + .unaligned = false, + }, +}; + +static void npcm7xx_otp_enter_reset(Object *obj, ResetType type) +{ + NPCM7xxOTPState *s = NPCM7XX_OTP(obj); + + memset(s->regs, 0, sizeof(s->regs)); + + s->regs[NPCM7XX_OTP_FST] = 0x00000001; + s->regs[NPCM7XX_OTP_FCFG] = 0x20000000; +} + +static void npcm7xx_otp_realize(DeviceState *dev, Error **errp) +{ + NPCM7xxOTPClass *oc = NPCM7XX_OTP_GET_CLASS(dev); + NPCM7xxOTPState *s = NPCM7XX_OTP(dev); + SysBusDevice *sbd = &s->parent; + + s->array = g_malloc0(NPCM7XX_OTP_ARRAY_BYTES); + + memory_region_init_io(&s->mmio, OBJECT(s), oc->mmio_ops, s, "regs", + NPCM7XX_OTP_REGS_SIZE); + sysbus_init_mmio(sbd, &s->mmio); +} + +static void npcm7xx_otp_class_init(ObjectClass *klass, void *data) +{ + ResettableClass *rc = RESETTABLE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = npcm7xx_otp_realize; + rc->phases.enter = npcm7xx_otp_enter_reset; +} + +static void npcm7xx_key_storage_class_init(ObjectClass *klass, void *data) +{ + NPCM7xxOTPClass *oc = NPCM7XX_OTP_CLASS(klass); + + oc->mmio_ops = &npcm7xx_key_storage_ops; +} + +static void npcm7xx_fuse_array_class_init(ObjectClass *klass, void *data) +{ + NPCM7xxOTPClass *oc = NPCM7XX_OTP_CLASS(klass); + + oc->mmio_ops = &npcm7xx_fuse_array_ops; +} + +static const TypeInfo npcm7xx_otp_types[] = { + { + .name = TYPE_NPCM7XX_OTP, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(NPCM7xxOTPState), + .class_init = npcm7xx_otp_class_init, + .abstract = true, + }, + { + .name = TYPE_NPCM7XX_KEY_STORAGE, + .parent = TYPE_NPCM7XX_OTP, + .class_init = npcm7xx_key_storage_class_init, + }, + { + .name = TYPE_NPCM7XX_FUSE_ARRAY, + .parent = TYPE_NPCM7XX_OTP, + .class_init = npcm7xx_fuse_array_class_init, + }, +}; +DEFINE_TYPES(npcm7xx_otp_types); diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h index a241af0b8c..360cd965a7 100644 --- a/include/hw/arm/npcm7xx.h +++ b/include/hw/arm/npcm7xx.h @@ -19,6 +19,7 @@ #include "hw/cpu/a9mpcore.h" #include "hw/misc/npcm7xx_clk.h" #include "hw/misc/npcm7xx_gcr.h" +#include "hw/nvram/npcm7xx_otp.h" #include "hw/timer/npcm7xx_timer.h" #include "target/arm/cpu.h" @@ -62,6 +63,8 @@ typedef struct NPCM7xxState { NPCM7xxGCRState gcr; NPCM7xxCLKState clk; NPCM7xxTimerCtrlState tim[3]; + NPCM7xxOTPState key_storage; + NPCM7xxOTPState fuse_array; } NPCM7xxState; #define TYPE_NPCM7XX "npcm7xx" diff --git a/include/hw/nvram/npcm7xx_otp.h b/include/hw/nvram/npcm7xx_otp.h new file mode 100644 index 0000000000..1127c48fef --- /dev/null +++ b/include/hw/nvram/npcm7xx_otp.h @@ -0,0 +1,93 @@ +/* + * Nuvoton NPCM7xx OTP (Fuse Array) Interface + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef NPCM7XX_OTP_H +#define NPCM7XX_OTP_H + +#include "exec/memory.h" +#include "hw/sysbus.h" + +/* Each OTP module holds 8192 bits of one-time programmable storage */ +#define NPCM7XX_OTP_ARRAY_BITS (8192) +#define NPCM7XX_OTP_ARRAY_BYTES (NPCM7XX_OTP_ARRAY_BITS / 8) + +/** + * enum NPCM7xxOTPRegister - 32-bit register indices. + */ +typedef enum NPCM7xxOTPRegister { + NPCM7XX_OTP_FST, + NPCM7XX_OTP_FADDR, + NPCM7XX_OTP_FDATA, + NPCM7XX_OTP_FCFG, + /* Offset 0x10 is FKEYIND in OTP1, FUSTRAP in OTP2 */ + NPCM7XX_OTP_FKEYIND = 0x0010 / sizeof(uint32_t), + NPCM7XX_OTP_FUSTRAP = 0x0010 / sizeof(uint32_t), + NPCM7XX_OTP_FCTL, + NPCM7XX_OTP_NR_REGS, +} NPCM7xxOTPRegister; + +/** + * struct NPCM7xxOTPState - Device state for one OTP module. + * @parent: System bus device. + * @mmio: Memory region through which registers are accessed. + * @regs: Register contents. + * @array: OTP storage array. + */ +typedef struct NPCM7xxOTPState { + SysBusDevice parent; + + MemoryRegion mmio; + uint32_t regs[NPCM7XX_OTP_NR_REGS]; + uint8_t *array; +} NPCM7xxOTPState; + +#define TYPE_NPCM7XX_OTP "npcm7xx-otp" +#define NPCM7XX_OTP(obj) OBJECT_CHECK(NPCM7xxOTPState, (obj), TYPE_NPCM7XX_OTP) + +#define TYPE_NPCM7XX_KEY_STORAGE "npcm7xx-key-storage" +#define TYPE_NPCM7XX_FUSE_ARRAY "npcm7xx-fuse-array" + +/** + * struct NPCM7xxOTPClass - OTP module class. + * @parent: System bus device class. + * @mmio_ops: MMIO register operations for this type of module. + * + * The two OTP modules (key-storage and fuse-array) have slightly different + * behavior, so we give them different MMIO register operations. + */ +typedef struct NPCM7xxOTPClass { + SysBusDeviceClass parent; + + const MemoryRegionOps *mmio_ops; +} NPCM7xxOTPClass; + +#define NPCM7XX_OTP_CLASS(klass) \ + OBJECT_CLASS_CHECK(NPCM7xxOTPClass, (klass), TYPE_NPCM7XX_OTP) +#define NPCM7XX_OTP_GET_CLASS(obj) \ + OBJECT_GET_CLASS(NPCM7xxOTPClass, (obj), TYPE_NPCM7XX_OTP) + +/** + * npcm7xx_otp_array_write - ECC encode and write data to OTP array. + * @s: OTP module. + * @data: Data to be encoded and written. + * @offset: Offset of first byte to be written in the OTP array. + * @len: Number of bytes before ECC encoding. + * + * Each nibble of data is encoded into a byte, so the number of bytes written + * to the array will be @len * 2. + */ +extern void npcm7xx_otp_array_write(NPCM7xxOTPState *s, const void *data, + unsigned int offset, unsigned int len); + +#endif /* NPCM7XX_OTP_H */ From patchwork Thu Jun 11 22:30:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Havard Skinnemoen X-Patchwork-Id: 280664 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.4 required=3.0 tests=DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 95616C433E0 for ; Thu, 11 Jun 2020 22:38:14 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 5B2C8206D7 for ; Thu, 11 Jun 2020 22:38:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Dq5yOKPs" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5B2C8206D7 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:52524 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jjVpt-00085Q-Kz for qemu-devel@archiver.kernel.org; Thu, 11 Jun 2020 18:38:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34052) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3lLDiXgsKCn0itljoofnpfohpphmf.dpnrfnv-efwfmopohov.psh@flex--hskinnemoen.bounces.google.com>) id 1jjVin-00048A-Cd for qemu-devel@nongnu.org; Thu, 11 Jun 2020 18:30:53 -0400 Received: from mail-yb1-xb49.google.com ([2607:f8b0:4864:20::b49]:48127) by eggs.gnu.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3lLDiXgsKCn0itljoofnpfohpphmf.dpnrfnv-efwfmopohov.psh@flex--hskinnemoen.bounces.google.com>) id 1jjVil-0004Co-GK for qemu-devel@nongnu.org; Thu, 11 Jun 2020 18:30:53 -0400 Received: by mail-yb1-xb49.google.com with SMTP id y189so8340063ybc.14 for ; Thu, 11 Jun 2020 15:30:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=z5aae+ulEUK36/+EU0k/QX5fzrntAEb4TfxbdpR4q+E=; b=Dq5yOKPsDL70LTwsJNsmbJzATvmIqQxoJwbKDgYFusQUAAcWBjh2AXW48dObXeKxoO uITiGsU+lDWrNkYN7EiwOknKgJveXEGqIA5CR/Mc4UfhSPuCGROHK+wvt0HDZ65hffxC GQuE37fq7rUh0maGsiXZwtm8yzB78P6xvK8MG4Y90+RmGbf/XoURsyhJHN8tPodOXEZD 3zDiLPfZBQBOKxikn+SVXsKbAL5wSk0IGJhXsZ1oZDddNSwytV4BWBlIqtnx+KaW8UqM Q0//5pI8Nv5q6uBfQjgUVrU9/GHGQtNs9+erNNrM//1YCdXNkvmiwLlcpJdEr1KKyDys 936g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=z5aae+ulEUK36/+EU0k/QX5fzrntAEb4TfxbdpR4q+E=; b=kaEUZLUTo8Ynlp7mKhy8ns0sb/EFn6p8IriS/UaFgEh0Dh5k32VXVP0FbWCpSMrTNu dBfO/s0XduX3k3jjRoLQf2lr0bXqGjr65VgbUch+1pj2J3X2dBU5lsHr4lBGnFr0NzrD ypwPTcb0ea0ewGc9rNDwlTOke5W7/fD6Ii5DuM7m4/nPEY6zrWbpqY1J5ZAaItyp6B89 8I1PecXq56lX0c2k9goWtCj7jDxHA9T1IR39txMGQiDxlnMndIagJrTp3c7fvNILCeER y2pZgyF5a0smZaNIWJDtervy58mQK++5C01KrFy+mPX64Q1UwmeAAFIjWk+5IgoiUYUy BK0w== X-Gm-Message-State: AOAM5331e+LfhAgsOz8WggNXrlrp7XzCXf3Dm3tuZOLjmh6yhtAO1xDp 58iojinqLW6fG70gQH6mI4ApLidsPpf0AyRXew== X-Google-Smtp-Source: ABdhPJwAScGXKu2uxz/Yexi0PPEqZ6SjWjH9Gvd5BBkmCxWQHqHGFysnrJ81KqA1tiv0WMQRPD0JFv94hpmUuGKVXg== X-Received: by 2002:a25:d088:: with SMTP id h130mr18262495ybg.451.1591914644261; Thu, 11 Jun 2020 15:30:44 -0700 (PDT) Date: Thu, 11 Jun 2020 15:30:13 -0700 In-Reply-To: <20200611223016.259837-1-hskinnemoen@google.com> Message-Id: <20200611223016.259837-10-hskinnemoen@google.com> Mime-Version: 1.0 References: <20200611223016.259837-1-hskinnemoen@google.com> X-Mailer: git-send-email 2.27.0.290.gba653c62da-goog Subject: [PATCH v2 09/12] hw/mem: Stubbed out NPCM7xx Memory Controller model From: Havard Skinnemoen To: peter.maydell@linaro.org, clg@kaod.org, joel@jms.id.au Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org, Avi.Fishman@nuvoton.com, kfting@nuvoton.com, Havard Skinnemoen Received-SPF: pass client-ip=2607:f8b0:4864:20::b49; envelope-from=3lLDiXgsKCn0itljoofnpfohpphmf.dpnrfnv-efwfmopohov.psh@flex--hskinnemoen.bounces.google.com; helo=mail-yb1-xb49.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -105 X-Spam_score: -10.6 X-Spam_bar: ---------- X-Spam_report: (-10.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-1, 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, USER_IN_DEF_DKIM_WL=-7.5 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This just implements the bare minimum to cause the boot block to skip memory intialization. Change-Id: I26fd5f3b2af5d07a24911e7e58789f7b52f78d71 Reviewed-by: Tyrone Ting Signed-off-by: Havard Skinnemoen --- MAINTAINERS | 2 + hw/arm/npcm7xx.c | 11 +++++ hw/mem/Makefile.objs | 1 + hw/mem/npcm7xx_mc.c | 83 +++++++++++++++++++++++++++++++++++++ include/hw/arm/npcm7xx.h | 2 + include/hw/mem/npcm7xx_mc.h | 35 ++++++++++++++++ 6 files changed, 134 insertions(+) create mode 100644 hw/mem/npcm7xx_mc.c create mode 100644 include/hw/mem/npcm7xx_mc.h diff --git a/MAINTAINERS b/MAINTAINERS index 9814e7b4c4..9a289366ba 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -727,10 +727,12 @@ M: Tyrone Ting L: qemu-arm@nongnu.org S: Supported F: hw/arm/npcm7xx* +F: hw/mem/npcm7xx* F: hw/misc/npcm7xx* F: hw/nvram/npcm7xx* F: hw/timer/npcm7xx* F: include/hw/arm/npcm7xx* +F: include/hw/mem/npcm7xx* F: include/hw/misc/npcm7xx* F: include/hw/nvram/npcm7xx* F: include/hw/timer/npcm7xx* diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c index f9e3b5842b..54d84bafa1 100644 --- a/hw/arm/npcm7xx.c +++ b/hw/arm/npcm7xx.c @@ -46,6 +46,7 @@ #define NPCM7XX_CPUP_BA (0xF03FE000) #define NPCM7XX_GCR_BA (0xF0800000) #define NPCM7XX_CLK_BA (0xF0801000) +#define NPCM7XX_MC_BA (0xF0824000) /* Memory blocks at the end of the address space */ #define NPCM7XX_RAM2_BA (0xFFFD0000) @@ -161,6 +162,8 @@ static void npcm7xx_init(Object *obj) sizeof(s->key_storage), TYPE_NPCM7XX_KEY_STORAGE); sysbus_init_child_obj(obj, "otp2", OBJECT(&s->fuse_array), sizeof(s->fuse_array), TYPE_NPCM7XX_FUSE_ARRAY); + sysbus_init_child_obj(obj, "mc", OBJECT(&s->mc), sizeof(s->mc), + TYPE_NPCM7XX_MC); for (i = 0; i < ARRAY_SIZE(s->tim); i++) { sysbus_init_child_obj(obj, "tim[*]", OBJECT(&s->tim[i]), @@ -258,6 +261,14 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(&s->fuse_array), 0, NPCM7XX_OTP2_BA); npcm7xx_init_fuses(s); + /* Fake Memory Controller (MC) */ + object_property_set_bool(OBJECT(&s->mc), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->mc), 0, NPCM7XX_MC_BA); + /* Timer Modules (TIM) */ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim)); for (i = 0; i < ARRAY_SIZE(s->tim); i++) { diff --git a/hw/mem/Makefile.objs b/hw/mem/Makefile.objs index 56345befd0..9a33ef7b35 100644 --- a/hw/mem/Makefile.objs +++ b/hw/mem/Makefile.objs @@ -1,3 +1,4 @@ common-obj-$(CONFIG_DIMM) += pc-dimm.o common-obj-y += memory-device.o +common-obj-$(CONFIG_NPCM7XX) += npcm7xx_mc.o common-obj-$(CONFIG_NVDIMM) += nvdimm.o diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c new file mode 100644 index 0000000000..03a7fb53dc --- /dev/null +++ b/hw/mem/npcm7xx_mc.c @@ -0,0 +1,83 @@ +/* + * Nuvoton NPCM7xx Memory Controller stub + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "qemu/osdep.h" + +#include "hw/mem/npcm7xx_mc.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/units.h" + +#define NPCM7XX_MC_REGS_SIZE (4 * KiB) + +static uint64_t npcm7xx_mc_read(void *opaque, hwaddr addr, unsigned int size) +{ + /* + * If bits 8..11 @ offset 0 are not zero, the boot block thinks the memory + * controller has already been initialized and will skip DDR training. + */ + if (addr == 0) { + return 0x100; + } + + qemu_log_mask(LOG_UNIMP, "%s: mostly unimplemented\n", __func__); + + return 0; +} + +static void npcm7xx_mc_write(void *opaque, hwaddr addr, uint64_t v, + unsigned int size) +{ + qemu_log_mask(LOG_UNIMP, "%s: mostly unimplemented\n", __func__); +} + +static const MemoryRegionOps npcm7xx_mc_ops = { + .read = npcm7xx_mc_read, + .write = npcm7xx_mc_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + .unaligned = false, + }, +}; + +static void npcm7xx_mc_realize(DeviceState *dev, Error **errp) +{ + NPCM7xxMCState *s = NPCM7XX_MC(dev); + + memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_mc_ops, s, "regs", + NPCM7XX_MC_REGS_SIZE); + sysbus_init_mmio(&s->parent, &s->mmio); +} + +static void npcm7xx_mc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "NPCM7xx Memory Controller stub"; + dc->realize = npcm7xx_mc_realize; +} + +static const TypeInfo npcm7xx_mc_types[] = { + { + .name = TYPE_NPCM7XX_MC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(NPCM7xxMCState), + .class_init = npcm7xx_mc_class_init, + }, +}; +DEFINE_TYPES(npcm7xx_mc_types); diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h index 360cd965a7..8f49f7015c 100644 --- a/include/hw/arm/npcm7xx.h +++ b/include/hw/arm/npcm7xx.h @@ -17,6 +17,7 @@ #include "hw/boards.h" #include "hw/cpu/a9mpcore.h" +#include "hw/mem/npcm7xx_mc.h" #include "hw/misc/npcm7xx_clk.h" #include "hw/misc/npcm7xx_gcr.h" #include "hw/nvram/npcm7xx_otp.h" @@ -65,6 +66,7 @@ typedef struct NPCM7xxState { NPCM7xxTimerCtrlState tim[3]; NPCM7xxOTPState key_storage; NPCM7xxOTPState fuse_array; + NPCM7xxMCState mc; } NPCM7xxState; #define TYPE_NPCM7XX "npcm7xx" diff --git a/include/hw/mem/npcm7xx_mc.h b/include/hw/mem/npcm7xx_mc.h new file mode 100644 index 0000000000..8781f5c979 --- /dev/null +++ b/include/hw/mem/npcm7xx_mc.h @@ -0,0 +1,35 @@ +/* + * Nuvoton NPCM7xx Memory Controller stub + * + * Copyright 2020 Google LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef NPCM7XX_MC_H +#define NPCM7XX_MC_H + +#include "exec/memory.h" +#include "hw/sysbus.h" + +/** + * struct NPCM7xxMCState - Device state for the memory controller. + * @parent: System bus device. + * @mmio: Memory region through which registers are accessed. + */ +typedef struct NPCM7xxMCState { + SysBusDevice parent; + + MemoryRegion mmio; +} NPCM7xxMCState; + +#define TYPE_NPCM7XX_MC "npcm7xx-mc" +#define NPCM7XX_MC(obj) OBJECT_CHECK(NPCM7xxMCState, (obj), TYPE_NPCM7XX_MC) + +#endif /* NPCM7XX_MC_H */ From patchwork Thu Jun 11 22:30:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Havard Skinnemoen X-Patchwork-Id: 280663 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-14.6 required=3.0 tests=DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED, USER_AGENT_GIT, USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B40BDC433DF for ; Thu, 11 Jun 2020 22:40:12 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 7E7E2206D7 for ; Thu, 11 Jun 2020 22:40:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="OQGSX1oB" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7E7E2206D7 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:58690 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jjVrn-0002JD-RA for qemu-devel@archiver.kernel.org; Thu, 11 Jun 2020 18:40:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34320) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <3l7DiXgsKCoAlwomrriqsirksskpi.gsquiqy-hiziprsrkry.svk@flex--hskinnemoen.bounces.google.com>) id 1jjVj0-0004XA-Kn for qemu-devel@nongnu.org; Thu, 11 Jun 2020 18:31:06 -0400 Received: from mail-yb1-xb49.google.com ([2607:f8b0:4864:20::b49]:44210) by eggs.gnu.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3l7DiXgsKCoAlwomrriqsirksskpi.gsquiqy-hiziprsrkry.svk@flex--hskinnemoen.bounces.google.com>) id 1jjViz-0004Hy-4P for qemu-devel@nongnu.org; Thu, 11 Jun 2020 18:31:06 -0400 Received: by mail-yb1-xb49.google.com with SMTP id b135so8212352yba.11 for ; Thu, 11 Jun 2020 15:30:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=E/t7NCqU4xlcbST0JMpIAE4l1XlKmG5L/C+Lk5feEf8=; b=OQGSX1oBgM+amV109UBZs/Bd60eKPvh7a/6Dhp9nZ9sR7DJn25hfs2d4l4GtcqaAsF xVZju6mRreiX+Vo2eqZcBn630JAYc058IL+uqDMsPsgCTe4MTI42VGslhba+Vw2Sn3al S/0ITzCKdb26GW2tW0LJObDcDQ1yEVtLoZYPfW3mFCSnxs72lq+kpr4cOx9pAs/Lz0Jq Ud9D3JWrSQ2AfM6DLf5oQTQmREV0X/vnIZlY7tfdkTh6NTmqqfvJwJP8qHryWmDzdTl+ r2lgV/4HUSf3wkbQC9Z4gE1CSr8Cs6yXlyFkPfEuLKxuuZ7jF9srxwvY3FiLigYV8RW2 JJEw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=E/t7NCqU4xlcbST0JMpIAE4l1XlKmG5L/C+Lk5feEf8=; b=UtTqjcw1H8dmN17F//1me3KkOMq+wx0BF/dhi8v2+Fp2aa05TP9E+mpshU4boXymeo pzQAgeSP+KoW7+7LVuzsQYS8ih1XAyV7hGVqu50q1rNayqk3Ok7reDtA7roLTCanl/aj WOFYDdxI/Shf/qvfTuT8drHKxBKBQFcCZiDc63lk/bZc8Dfs15Vp7V06umym0DBjGDc9 XT1FFRV/N7lVcU0O2y8MpS/Uf7tibIf7si5GbdjiRAirzVYzNVgUA+Sh1pemUSvDUVEK nWYjqnN+WCv9jcUiBUUBSKA+YdE6TwfyQTNP351fF7RPrqqwHYn//Y4nOy8IvBHeYm+I VCfg== X-Gm-Message-State: AOAM533Jb9rleu7N08ucyJalK8ca4Az0RDv834+1X6fK+A/RKtjRE5ZI dhqNoQP+ooeBRzA3Nyia+8bJE4AltRT30yVW6A== X-Google-Smtp-Source: ABdhPJw/5NDeBKdsUCIDwvQXbTXlnGE6RA0ZqRTwnXaejXYDzzTqVnoy1uGd/19I4qog35Wlj3A6pgHZdvn0TOGssQ== X-Received: by 2002:a5b:4cd:: with SMTP id u13mr6632708ybp.323.1591914647790; Thu, 11 Jun 2020 15:30:47 -0700 (PDT) Date: Thu, 11 Jun 2020 15:30:15 -0700 In-Reply-To: <20200611223016.259837-1-hskinnemoen@google.com> Message-Id: <20200611223016.259837-12-hskinnemoen@google.com> Mime-Version: 1.0 References: <20200611223016.259837-1-hskinnemoen@google.com> X-Mailer: git-send-email 2.27.0.290.gba653c62da-goog Subject: [PATCH v2 11/12] hw/arm: Wire up BMC boot flash for npcm750-evb and quanta-gsj From: Havard Skinnemoen To: peter.maydell@linaro.org, clg@kaod.org, joel@jms.id.au Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org, Avi.Fishman@nuvoton.com, kfting@nuvoton.com, Havard Skinnemoen Received-SPF: pass client-ip=2607:f8b0:4864:20::b49; envelope-from=3l7DiXgsKCoAlwomrriqsirksskpi.gsquiqy-hiziprsrkry.svk@flex--hskinnemoen.bounces.google.com; helo=mail-yb1-xb49.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -105 X-Spam_score: -10.6 X-Spam_bar: ---------- X-Spam_report: (-10.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-1, 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, USER_IN_DEF_DKIM_WL=-7.5 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This allows these NPCM7xx-based boards to boot from a flash image, e.g. one built with OpenBMC. For example like this: IMAGE=${OPENBMC}/build/tmp/deploy/images/gsj/image-bmc qemu-system-arm -machine quanta-gsj -nographic \ -bios ~/qemu/bootrom/npcm7xx_bootrom.bin \ -drive file=${IMAGE},if=mtd,bus=0,unit=0,format=raw,snapshot=on Change-Id: I158a4d9952c0e90f2b1b7280443a7305b6ae57cf Reviewed-by: Tyrone Ting Signed-off-by: Havard Skinnemoen --- hw/arm/npcm7xx_boards.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index 86e18af2d7..1ec772fa59 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -18,6 +18,7 @@ #include "hw/arm/boot.h" #include "hw/arm/npcm7xx.h" #include "hw/core/cpu.h" +#include "hw/qdev-properties.h" #include "qapi/error.h" #include "qemu/units.h" @@ -40,6 +41,20 @@ static void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc) arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo); } +static void npcm7xx_connect_flash(NPCM7xxFIUState *fiu, int cs_no, + const char *flash_type, DriveInfo *dinfo) { + DeviceState *flash; + qemu_irq flash_cs; + + flash = ssi_create_slave_no_init(fiu->spi, flash_type); + qdev_prop_set_drive(flash, "drive", blk_by_legacy_dinfo(dinfo), + &error_abort); + qdev_init_nofail(flash); + + flash_cs = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0); + sysbus_connect_irq(SYS_BUS_DEVICE(fiu), cs_no, flash_cs); +} + static NPCM7xxState *npcm7xx_create_soc(MachineState *machine) { NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine); @@ -57,18 +72,30 @@ static NPCM7xxState *npcm7xx_create_soc(MachineState *machine) static void npcm750_evb_init(MachineState *machine) { NPCM7xxState *soc; + DriveInfo *dinfo; soc = npcm7xx_create_soc(machine); + dinfo = drive_get(IF_MTD, 0, 0); + if (dinfo) { + npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", dinfo); + } + npcm7xx_load_kernel(machine, soc); } static void quanta_gsj_init(MachineState *machine) { NPCM7xxState *soc; + DriveInfo *dinfo; soc = npcm7xx_create_soc(machine); + dinfo = drive_get(IF_MTD, 0, 0); + if (dinfo) { + npcm7xx_connect_flash(&soc->fiu[0], 0, "mx25l25635e", dinfo); + } + npcm7xx_load_kernel(machine, soc); }