From patchwork Tue Oct 27 14:08:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bin Meng X-Patchwork-Id: 11860607 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CC4A661C for ; Tue, 27 Oct 2020 14:28:26 +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 5402A206DC for ; Tue, 27 Oct 2020 14:28:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="qQtLZvRM" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5402A206DC Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:50898 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kXPxZ-0007E9-CV for patchwork-qemu-devel@patchwork.kernel.org; Tue, 27 Oct 2020 10:28:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39928) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kXPep-0007DO-2x; Tue, 27 Oct 2020 10:09:04 -0400 Received: from mail-pf1-x442.google.com ([2607:f8b0:4864:20::442]:39164) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kXPem-0006Jd-Q8; Tue, 27 Oct 2020 10:09:02 -0400 Received: by mail-pf1-x442.google.com with SMTP id e15so977615pfh.6; Tue, 27 Oct 2020 07:08:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=jT3uqzM9FA3JIF+RFkZXptg5x6mgESw+EJwKoS3k08U=; b=qQtLZvRMfKdC9/UFqTgH9IM382cQ1qIA1wx0E5DsNoxQtQ0NQG4awMx4pNo6TV62rf Zz7JQhrI+JRGHVNTvtMHXv/vu8TZV4a6+7hYfwzG61/VIkQwotR4MSC733vdjwxNThWp NqoiQmR1qJNVqN0LDzrfTVS/R0NUT/E82ugQXi3cDQEuEM0qHrkphJd0AZrSj9hjRznU 9/SaZCKf7h0HTeV3alh1KIS8J+mA/uTqlmnC5DwQTsu0NkLq+faW0qSgS9kmq2Kwe+I3 sd4ZFsShbnE8k8csPn6obV+9HQ+Goa6TH3VXbzz8pp/r+apU89JDKEHBFCgUlsRHlGdC JPUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=jT3uqzM9FA3JIF+RFkZXptg5x6mgESw+EJwKoS3k08U=; b=fsCkDUqFlIn+hd2KIXlp19ftZVpFDRamaCMMR9PLPV6cOVPU72A2tPd6z9fz9WBA1R VZ6oM4J/dp5QqzVnryCTCzv00QbKSRBOy3Z2mhsWnbPyW52pZD53/3wx1JeSs1F2aq9B EgXMUpjXui2a5dGpsvmPlJvvOZHUYITf2rQoist5dBNP3AdViQG6eTsmYGYU3Y2p25C7 eJ4Uu1V86q0pc2MxM6tk+rg7UAOY8AtSgKzEySyTOnZ63Wq1339LdDvslbmUyO/dOAFw t86nFHsioOSbPT4W9ED5SOhQ9YSZCr6TiQdLlTkFF7IFMctGPgihkRIYfh+oGzBmMp8t y89g== X-Gm-Message-State: AOAM533phc53KdPRymM0/TZyf+VCMXt+wxiVyBck1JW3tZXsYi18K3sy dDn5RR2QlOKCQAKMfHGcsO3xaMyzjqU= X-Google-Smtp-Source: ABdhPJzN7mHw5/kqUGb0j8f6G3o0wrpAmObFiqTwHO4eFBanB33praNmlJKq2mKD4u7ymAZO12y4Rw== X-Received: by 2002:a65:5809:: with SMTP id g9mr2133593pgr.35.1603807737124; Tue, 27 Oct 2020 07:08:57 -0700 (PDT) Received: from i9-aorus-gtx1080.localdomain (144.168.56.201.16clouds.com. [144.168.56.201]) by smtp.gmail.com with ESMTPSA id r22sm2540856pfg.51.2020.10.27.07.08.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 27 Oct 2020 07:08:56 -0700 (PDT) From: Bin Meng X-Google-Original-From: Bin Meng To: Alistair Francis , qemu-devel@nongnu.org, qemu-riscv@nongnu.org Subject: [PATCH 1/9] hw/misc: Add Microchip PolarFire SoC DDR Memory Controller support Date: Tue, 27 Oct 2020 22:08:32 +0800 Message-Id: <20201027140840.18030-2-bin.meng@windriver.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201027140840.18030-1-bin.meng@windriver.com> References: <20201027140840.18030-1-bin.meng@windriver.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::442; envelope-from=bmeng.cn@gmail.com; helo=mail-pf1-x442.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: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-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: , Cc: Bin Meng , Atish Patra , Anup Patel , Ivan Griffin Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" The PolarFire SoC DDR Memory Controller mainly includes 2 modules, called SGMII PHY module and the CFG module, as documented in the chipset datasheet. This creates a single file that groups these 2 modules, providing the minimum functionalities that make the HSS DDR initialization codes happy. Signed-off-by: Bin Meng --- MAINTAINERS | 2 + hw/misc/Kconfig | 3 + hw/misc/mchp_pfsoc_dmc.c | 216 +++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + include/hw/misc/mchp_pfsoc_dmc.h | 56 ++++++++ 5 files changed, 278 insertions(+) create mode 100644 hw/misc/mchp_pfsoc_dmc.c create mode 100644 include/hw/misc/mchp_pfsoc_dmc.h diff --git a/MAINTAINERS b/MAINTAINERS index ef6f5c7399..caacec401c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1326,8 +1326,10 @@ L: qemu-riscv@nongnu.org S: Supported F: hw/riscv/microchip_pfsoc.c F: hw/char/mchp_pfsoc_mmuart.c +F: hw/misc/mchp_pfsoc_dmc.c F: include/hw/riscv/microchip_pfsoc.h F: include/hw/char/mchp_pfsoc_mmuart.h +F: include/hw/misc/mchp_pfsoc_dmc.h RX Machines ----------- diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 3185456110..198bb1c6ba 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -134,6 +134,9 @@ config MAC_VIA config AVR_POWER bool +config MCHP_PFSOC_DMC + bool + config SIFIVE_TEST bool diff --git a/hw/misc/mchp_pfsoc_dmc.c b/hw/misc/mchp_pfsoc_dmc.c new file mode 100644 index 0000000000..15cf3d7725 --- /dev/null +++ b/hw/misc/mchp_pfsoc_dmc.c @@ -0,0 +1,216 @@ +/* + * Microchip PolarFire SoC DDR Memory Controller module emulation + * + * Copyright (c) 2020 Wind River Systems, Inc. + * + * Author: + * Bin Meng + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#include "qemu/osdep.h" +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/misc/mchp_pfsoc_dmc.h" + +/* DDR SGMII PHY module */ + +#define SGMII_PHY_IOC_REG1 0x208 +#define SGMII_PHY_TRAINING_STATUS 0x814 +#define SGMII_PHY_DQ_DQS_ERR_DONE 0x834 +#define SGMII_PHY_DQDQS_STATUS1 0x84c +#define SGMII_PHY_PVT_STAT 0xc20 + +static uint64_t mchp_pfsoc_ddr_sgmii_phy_read(void *opaque, hwaddr offset, + unsigned size) +{ + uint32_t val = 0; + static int training_status_bit; + + switch (offset) { + case SGMII_PHY_IOC_REG1: + /* See ddr_pvt_calibration() in HSS */ + val = BIT(4) | BIT(2); + break; + case SGMII_PHY_TRAINING_STATUS: + /* + * The codes logic emulates the training status change from + * DDR_TRAINING_IP_SM_BCLKSCLK to DDR_TRAINING_IP_SM_DQ_DQS. + * + * See ddr_setup() in mss_ddr.c in the HSS source codes. + */ + val = 1 << training_status_bit; + training_status_bit = (training_status_bit + 1) % 5; + break; + case SGMII_PHY_DQ_DQS_ERR_DONE: + /* + * DDR_TRAINING_IP_SM_VERIFY state in ddr_setup(), + * check that DQ/DQS training passed without error. + */ + val = 8; + break; + case SGMII_PHY_DQDQS_STATUS1: + /* + * DDR_TRAINING_IP_SM_VERIFY state in ddr_setup(), + * check that DQ/DQS calculated window is above 5 taps. + */ + val = 0xff; + break; + case SGMII_PHY_PVT_STAT: + /* See sgmii_channel_setup() in HSS */ + val = BIT(14) | BIT(6); + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read " + "(size %d, offset 0x%" HWADDR_PRIx ")\n", + __func__, size, offset); + break; + } + + return val; +} + +static void mchp_pfsoc_ddr_sgmii_phy_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device write " + "(size %d, value 0x%" PRIx64 + ", offset 0x%" HWADDR_PRIx ")\n", + __func__, size, value, offset); +} + +static const MemoryRegionOps mchp_pfsoc_ddr_sgmii_phy_ops = { + .read = mchp_pfsoc_ddr_sgmii_phy_read, + .write = mchp_pfsoc_ddr_sgmii_phy_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void mchp_pfsoc_ddr_sgmii_phy_realize(DeviceState *dev, Error **errp) +{ + MchpPfSoCDdrSgmiiPhyState *s = MCHP_PFSOC_DDR_SGMII_PHY(dev); + + memory_region_init_io(&s->sgmii_phy, OBJECT(dev), + &mchp_pfsoc_ddr_sgmii_phy_ops, s, + "mchp.pfsoc.ddr_sgmii_phy", + MCHP_PFSOC_DDR_SGMII_PHY_REG_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->sgmii_phy); +} + +static void mchp_pfsoc_ddr_sgmii_phy_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "Microchip PolarFire SoC DDR SGMII PHY module"; + dc->realize = mchp_pfsoc_ddr_sgmii_phy_realize; +} + +static const TypeInfo mchp_pfsoc_ddr_sgmii_phy_info = { + .name = TYPE_MCHP_PFSOC_DDR_SGMII_PHY, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(MchpPfSoCDdrSgmiiPhyState), + .class_init = mchp_pfsoc_ddr_sgmii_phy_class_init, +}; + +static void mchp_pfsoc_ddr_sgmii_phy_register_types(void) +{ + type_register_static(&mchp_pfsoc_ddr_sgmii_phy_info); +} + +type_init(mchp_pfsoc_ddr_sgmii_phy_register_types) + +/* DDR CFG module */ + +#define CFG_MT_DONE_ACK 0x4428 +#define CFG_STAT_DFI_INIT_COMPLETE 0x10034 +#define CFG_STAT_DFI_TRAINING_COMPLETE 0x10038 + +static uint64_t mchp_pfsoc_ddr_cfg_read(void *opaque, hwaddr offset, + unsigned size) +{ + uint32_t val = 0; + + switch (offset) { + case CFG_MT_DONE_ACK: + /* memory test in MTC_test() */ + val = BIT(0); + break; + case CFG_STAT_DFI_INIT_COMPLETE: + /* DDR_TRAINING_IP_SM_START_CHECK state in ddr_setup() */ + val = BIT(0); + break; + case CFG_STAT_DFI_TRAINING_COMPLETE: + /* DDR_TRAINING_IP_SM_VERIFY state in ddr_setup() */ + val = BIT(0); + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read " + "(size %d, offset 0x%" HWADDR_PRIx ")\n", + __func__, size, offset); + break; + } + + return val; +} + +static void mchp_pfsoc_ddr_cfg_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device write " + "(size %d, value 0x%" PRIx64 + ", offset 0x%" HWADDR_PRIx ")\n", + __func__, size, value, offset); +} + +static const MemoryRegionOps mchp_pfsoc_ddr_cfg_ops = { + .read = mchp_pfsoc_ddr_cfg_read, + .write = mchp_pfsoc_ddr_cfg_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void mchp_pfsoc_ddr_cfg_realize(DeviceState *dev, Error **errp) +{ + MchpPfSoCDdrCfgState *s = MCHP_PFSOC_DDR_CFG(dev); + + memory_region_init_io(&s->cfg, OBJECT(dev), + &mchp_pfsoc_ddr_cfg_ops, s, + "mchp.pfsoc.ddr_cfg", + MCHP_PFSOC_DDR_CFG_REG_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->cfg); +} + +static void mchp_pfsoc_ddr_cfg_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "Microchip PolarFire SoC DDR CFG module"; + dc->realize = mchp_pfsoc_ddr_cfg_realize; +} + +static const TypeInfo mchp_pfsoc_ddr_cfg_info = { + .name = TYPE_MCHP_PFSOC_DDR_CFG, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(MchpPfSoCDdrCfgState), + .class_init = mchp_pfsoc_ddr_cfg_class_init, +}; + +static void mchp_pfsoc_ddr_cfg_register_types(void) +{ + type_register_static(&mchp_pfsoc_ddr_cfg_info); +} + +type_init(mchp_pfsoc_ddr_cfg_register_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 793d45b1dc..2d79a657e0 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -22,6 +22,7 @@ softmmu_ss.add(when: 'CONFIG_ARM11SCU', if_true: files('arm11scu.c')) softmmu_ss.add(when: 'CONFIG_MOS6522', if_true: files('mos6522.c')) # RISC-V devices +softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_DMC', if_true: files('mchp_pfsoc_dmc.c')) softmmu_ss.add(when: 'CONFIG_SIFIVE_TEST', if_true: files('sifive_test.c')) softmmu_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true: files('sifive_e_prci.c')) softmmu_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true: files('sifive_u_otp.c')) diff --git a/include/hw/misc/mchp_pfsoc_dmc.h b/include/hw/misc/mchp_pfsoc_dmc.h new file mode 100644 index 0000000000..2baa1413b0 --- /dev/null +++ b/include/hw/misc/mchp_pfsoc_dmc.h @@ -0,0 +1,56 @@ +/* + * Microchip PolarFire SoC DDR Memory Controller module emulation + * + * Copyright (c) 2020 Wind River Systems, Inc. + * + * Author: + * Bin Meng + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#ifndef MCHP_PFSOC_DMC_H +#define MCHP_PFSOC_DMC_H + +/* DDR SGMII PHY module */ + +#define MCHP_PFSOC_DDR_SGMII_PHY_REG_SIZE 0x1000 + +typedef struct MchpPfSoCDdrSgmiiPhyState { + SysBusDevice parent; + MemoryRegion sgmii_phy; +} MchpPfSoCDdrSgmiiPhyState; + +#define TYPE_MCHP_PFSOC_DDR_SGMII_PHY "mchp.pfsoc.ddr_sgmii_phy" + +#define MCHP_PFSOC_DDR_SGMII_PHY(obj) \ + OBJECT_CHECK(MchpPfSoCDdrSgmiiPhyState, (obj), \ + TYPE_MCHP_PFSOC_DDR_SGMII_PHY) + +/* DDR CFG module */ + +#define MCHP_PFSOC_DDR_CFG_REG_SIZE 0x40000 + +typedef struct MchpPfSoCDdrCfgState { + SysBusDevice parent; + MemoryRegion cfg; +} MchpPfSoCDdrCfgState; + +#define TYPE_MCHP_PFSOC_DDR_CFG "mchp.pfsoc.ddr_cfg" + +#define MCHP_PFSOC_DDR_CFG(obj) \ + OBJECT_CHECK(MchpPfSoCDdrCfgState, (obj), \ + TYPE_MCHP_PFSOC_DDR_CFG) + +#endif /* MCHP_PFSOC_DMC_H */