From nobody Sun Feb 8 23:06:05 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1565021265; cv=none; d=zoho.com; s=zohoarc; b=C5P8Y+4UjrpCbMOWEnagKYTJCf7cKa/Lz5t8l7lrJ6pcnx4V0PDtJn3N/aeO3PROyo0wdqqIdah+wYlE8mMwDqlHkjncUVEjTnw91P6dTk6T7NAq7HsfLnRgMw6eAyP1YPXCGxPo/D4P5JrWKK+NCQrcTBoDRzzvO5auxAPnPlM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1565021265; h=Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=2ms6qzywynSYGndXaBF2HCSrVQr5HrR87UomFY43oOo=; b=c2SvT7Q3rigyNKuACggKRllvfRqAKWFvSsSi3rleOwGBjfBfU5sq7mba1I+Y00VvMZoB8Cp8GJ91gJwR/jY7H2q5kKt+GJJ2EJBMnVtoNRLS4AXyw3UgICaHYyxHI+2tUBmThCKDrmKb9ut9Wzls+ZMpU8NCOX3/8ZvS7KIWBiQ= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1565021265428105.25434081057165; Mon, 5 Aug 2019 09:07:45 -0700 (PDT) Received: from localhost ([::1]:55598 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hufWS-00056I-Cj for importer@patchew.org; Mon, 05 Aug 2019 12:07:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58598) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hufPu-0000mw-49 for qemu-devel@nongnu.org; Mon, 05 Aug 2019 12:01:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hufPr-00032l-3s for qemu-devel@nongnu.org; Mon, 05 Aug 2019 12:00:57 -0400 Received: from mail-pf1-x444.google.com ([2607:f8b0:4864:20::444]:45309) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hufPn-0002yc-6g; Mon, 05 Aug 2019 12:00:52 -0400 Received: by mail-pf1-x444.google.com with SMTP id r1so39861385pfq.12; Mon, 05 Aug 2019 09:00:48 -0700 (PDT) Received: from localhost.localdomain (unknown-224-80.windriver.com. [147.11.224.80]) by smtp.gmail.com with ESMTPSA id d18sm47728793pgi.40.2019.08.05.09.00.46 (version=TLS1 cipher=AES128-SHA bits=128/128); Mon, 05 Aug 2019 09:00:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references; bh=2ms6qzywynSYGndXaBF2HCSrVQr5HrR87UomFY43oOo=; b=QvC4bLRX7/Un2bwF6t1LcfjWRSrTf1kSbJlIKjKtm2omg+/8uoItJiDxknXwcda7Ns xBKevTlUYkiMm4IDCLEwr6JWz1gIiEKiTdE+G3Dl9Cpt+k5jSOm8jK+y0JuY4LEozooU EcQcHVNjPtfdt2ZYza30z0a8iIj3Gm4SkmJpDU+Fwr0ui79Va06Q1q9v42Ws2KClIg+e KiwxhszK+j82YIO+5pvdHGk7r7HsLozKgQq3SaKLN4bDy/SljiB+iCUwtrsJp5N87Kcz 5FGCDWZFVYBC0uGWMtVyYKJKhDDwAlO2kb7tyHTqHXINab4d+GmLbCc1vI7svvLYvBNQ pRtw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=2ms6qzywynSYGndXaBF2HCSrVQr5HrR87UomFY43oOo=; b=HLx9jmYL9YaTZnW4HOUyKPkLCxpl6dAuCD0FirLh5LdBqIdJ4XFKKSaoxHsK/zWWI1 uwoxXvv7QYwqh8GEO6x+ILpit0nhZWcecLrPZZZmAPafx0VbxSi75vNpeeUCDCjSBBNa 8OL96TV1SaEMZtv14ISP7SEm2cFp9bLpnuaYrespW6prIoePpPEj09V4JrlO5B/5lcxx pYSLm9lTv2RCFosNK/3h5B2AcsQWTj5mpuwZ/Zm+WH2ZDBZUfLH3fF8G6nAxQfayn+RD X+izXAwZiwTaRbGc/zre1HLVj4mSiCUpthkLGIA0PexsRNW5/XG5irkVACgWzPmLmUZk fkMg== X-Gm-Message-State: APjAAAWjnghmXl7Gqs4H8PxcMoNvWJpKUx9scKgXjN+IsXI/AAy/iDyk Cs4Ae4qXa+B2dOPjgOlAH/FGY1Y7 X-Google-Smtp-Source: APXvYqxfva+PWi8e3QiT9G1GxXpJrXe+H8jP672rmwkV9AxzNlxs1PdT9YzSNNTYq6o4G1TM/+VSeg== X-Received: by 2002:aa7:96a4:: with SMTP id g4mr76499241pfk.193.1565020847412; Mon, 05 Aug 2019 09:00:47 -0700 (PDT) From: Bin Meng To: Alistair Francis , Bastian Koppelmann , Palmer Dabbelt , Sagar Karandikar , qemu-devel@nongnu.org, qemu-riscv@nongnu.org Date: Mon, 5 Aug 2019 09:00:13 -0700 Message-Id: <1565020823-24223-19-git-send-email-bmeng.cn@gmail.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1565020823-24223-1-git-send-email-bmeng.cn@gmail.com> References: <1565020823-24223-1-git-send-email-bmeng.cn@gmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::444 Subject: [Qemu-devel] [PATCH 18/28] riscv: hw: Implement a model for SiFive FU540 OTP 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+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This implements a simple model for SiFive FU540 OTP (One-Time Programmable) Memory interface, primarily for reading out the stored serial number from the first 1 KiB of the 16 KiB OTP memory reserved by SiFive for internal use. Signed-off-by: Bin Meng --- hw/riscv/Makefile.objs | 1 + hw/riscv/sifive_u_otp.c | 194 ++++++++++++++++++++++++++++++++++++= ++++ include/hw/riscv/sifive_u_otp.h | 90 +++++++++++++++++++ 3 files changed, 285 insertions(+) create mode 100644 hw/riscv/sifive_u_otp.c create mode 100644 include/hw/riscv/sifive_u_otp.h diff --git a/hw/riscv/Makefile.objs b/hw/riscv/Makefile.objs index b95bbd5..fc3c6dd 100644 --- a/hw/riscv/Makefile.objs +++ b/hw/riscv/Makefile.objs @@ -8,6 +8,7 @@ obj-$(CONFIG_SIFIVE) +=3D sifive_gpio.o obj-$(CONFIG_SIFIVE) +=3D sifive_plic.o obj-$(CONFIG_SIFIVE) +=3D sifive_test.o obj-$(CONFIG_SIFIVE_U) +=3D sifive_u.o +obj-$(CONFIG_SIFIVE_U) +=3D sifive_u_otp.o obj-$(CONFIG_SIFIVE_U) +=3D sifive_u_prci.o obj-$(CONFIG_SIFIVE) +=3D sifive_uart.o obj-$(CONFIG_SPIKE) +=3D spike.o diff --git a/hw/riscv/sifive_u_otp.c b/hw/riscv/sifive_u_otp.c new file mode 100644 index 0000000..f21d9f4 --- /dev/null +++ b/hw/riscv/sifive_u_otp.c @@ -0,0 +1,194 @@ +/* + * QEMU SiFive U OTP (One-Time Programmable) Memory interface + * + * Copyright (c) 2019 Bin Meng + * + * Simple model of the OTP to emulate register reads made by the SDK BSP + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 f= or + * 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 "hw/sysbus.h" +#include "qemu/module.h" +#include "target/riscv/cpu.h" +#include "hw/riscv/sifive_u_otp.h" + +static uint64_t sifive_otp_read(void *opaque, hwaddr addr, unsigned int si= ze) +{ + SiFiveOTPState *s =3D opaque; + + switch (addr) { + case SIFIVE_OTP_PA: + return s->pa; + case SIFIVE_OTP_PAIO: + return s->paio; + case SIFIVE_OTP_PAS: + return s->pas; + case SIFIVE_OTP_PCE: + return s->pce; + case SIFIVE_OTP_PCLK: + return s->pclk; + case SIFIVE_OTP_PDIN: + return s->pdin; + case SIFIVE_OTP_PDOUT: + if ((s->pce & SIFIVE_OTP_PCE_EN) && + (s->pdstb & SIFIVE_OTP_PDSTB_EN) && + (s->ptrim & SIFIVE_OTP_PTRIM_EN)) { + return s->fuse[s->pa & SIFIVE_OTP_PA_MASK]; + } else { + return 0xff; + } + case SIFIVE_OTP_PDSTB: + return s->pdstb; + case SIFIVE_OTP_PPROG: + return s->pprog; + case SIFIVE_OTP_PTC: + return s->ptc; + case SIFIVE_OTP_PTM: + return s->ptm; + case SIFIVE_OTP_PTM_REP: + return s->ptm_rep; + case SIFIVE_OTP_PTR: + return s->ptr; + case SIFIVE_OTP_PTRIM: + return s->ptrim; + case SIFIVE_OTP_PWE: + return s->pwe; + } + + hw_error("%s: read: addr=3D0x%x\n", __func__, (int)addr); + return 0; +} + +static void sifive_otp_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned int size) +{ + SiFiveOTPState *s =3D opaque; + + switch (addr) { + case SIFIVE_OTP_PA: + s->pa =3D (uint32_t) val64 & SIFIVE_OTP_PA_MASK; + break; + case SIFIVE_OTP_PAIO: + s->paio =3D (uint32_t) val64; + break; + case SIFIVE_OTP_PAS: + s->pas =3D (uint32_t) val64; + break; + case SIFIVE_OTP_PCE: + s->pce =3D (uint32_t) val64; + break; + case SIFIVE_OTP_PCLK: + s->pclk =3D (uint32_t) val64; + break; + case SIFIVE_OTP_PDIN: + s->pdin =3D (uint32_t) val64; + break; + case SIFIVE_OTP_PDOUT: + /* read-only */ + break; + case SIFIVE_OTP_PDSTB: + s->pdstb =3D (uint32_t) val64; + break; + case SIFIVE_OTP_PPROG: + s->pprog =3D (uint32_t) val64; + break; + case SIFIVE_OTP_PTC: + s->ptc =3D (uint32_t) val64; + break; + case SIFIVE_OTP_PTM: + s->ptm =3D (uint32_t) val64; + break; + case SIFIVE_OTP_PTM_REP: + s->ptm_rep =3D (uint32_t) val64; + break; + case SIFIVE_OTP_PTR: + s->ptr =3D (uint32_t) val64; + break; + case SIFIVE_OTP_PTRIM: + s->ptrim =3D (uint32_t) val64; + break; + case SIFIVE_OTP_PWE: + s->pwe =3D (uint32_t) val64; + break; + default: + hw_error("%s: bad write: addr=3D0x%x v=3D0x%x\n", + __func__, (int)addr, (int)val64); + } +} + +static const MemoryRegionOps sifive_otp_ops =3D { + .read =3D sifive_otp_read, + .write =3D sifive_otp_write, + .endianness =3D DEVICE_NATIVE_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 4 + } +}; + +static Property sifive_otp_properties[] =3D { + DEFINE_PROP_UINT32("serial", SiFiveOTPState, serial, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void sifive_otp_realize(DeviceState *dev, Error **errp) +{ + SiFiveOTPState *s =3D SIFIVE_U_OTP(dev); + + memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_otp_ops, s, + TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); + + /* Initialize all fuses' initial value to 0xFFs */ + memset(s->fuse, 0xff, sizeof(s->fuse)); + + /* Make a valid content of serial number */ + s->fuse[SIFIVE_OTP_SERIAL_ADDR] =3D s->serial; + s->fuse[SIFIVE_OTP_SERIAL_ADDR + 1] =3D ~(s->serial); +} + +static void sifive_otp_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->props =3D sifive_otp_properties; + dc->realize =3D sifive_otp_realize; +} + +static const TypeInfo sifive_otp_info =3D { + .name =3D TYPE_SIFIVE_U_OTP, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(SiFiveOTPState), + .class_init =3D sifive_otp_class_init, +}; + +static void sifive_otp_register_types(void) +{ + type_register_static(&sifive_otp_info); +} + +type_init(sifive_otp_register_types) + + +/* Create OTP device */ +DeviceState *sifive_u_otp_create(hwaddr addr, uint32_t serial) +{ + DeviceState *dev =3D qdev_create(NULL, TYPE_SIFIVE_U_OTP); + qdev_prop_set_uint32(dev, "serial", serial); + qdev_init_nofail(dev); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); + + return dev; +} diff --git a/include/hw/riscv/sifive_u_otp.h b/include/hw/riscv/sifive_u_ot= p.h new file mode 100644 index 0000000..16095b0 --- /dev/null +++ b/include/hw/riscv/sifive_u_otp.h @@ -0,0 +1,90 @@ +/* + * QEMU SiFive U OTP (One-Time Programmable) Memory interface + * + * Copyright (c) 2019 Bin Meng + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + */ + +#ifndef HW_SIFIVE_U_OTP_H +#define HW_SIFIVE_U_OTP_H + +enum { + SIFIVE_OTP_PA =3D 0x00, + SIFIVE_OTP_PAIO =3D 0x04, + SIFIVE_OTP_PAS =3D 0x08, + SIFIVE_OTP_PCE =3D 0x0C, + SIFIVE_OTP_PCLK =3D 0x10, + SIFIVE_OTP_PDIN =3D 0x14, + SIFIVE_OTP_PDOUT =3D 0x18, + SIFIVE_OTP_PDSTB =3D 0x1C, + SIFIVE_OTP_PPROG =3D 0x20, + SIFIVE_OTP_PTC =3D 0x24, + SIFIVE_OTP_PTM =3D 0x28, + SIFIVE_OTP_PTM_REP =3D 0x2C, + SIFIVE_OTP_PTR =3D 0x30, + SIFIVE_OTP_PTRIM =3D 0x34, + SIFIVE_OTP_PWE =3D 0x38 +}; + +enum { + SIFIVE_OTP_PCE_EN =3D (1 << 0) +}; + +enum { + SIFIVE_OTP_PDSTB_EN =3D (1 << 0) +}; + +enum { + SIFIVE_OTP_PTRIM_EN =3D (1 << 0) +}; + +#define SIFIVE_OTP_PA_MASK 0xfff +#define SIFIVE_OTP_NUM_FUSES 0x1000 +#define SIFIVE_OTP_SERIAL_ADDR 0xfc + +#define SIFIVE_U_OTP_REG_SIZE 0x1000 + +#define TYPE_SIFIVE_U_OTP "riscv.sifive.u.otp" + +#define SIFIVE_U_OTP(obj) \ + OBJECT_CHECK(SiFiveOTPState, (obj), TYPE_SIFIVE_U_OTP) + +typedef struct SiFiveOTPState { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + MemoryRegion mmio; + uint32_t pa; + uint32_t paio; + uint32_t pas; + uint32_t pce; + uint32_t pclk; + uint32_t pdin; + uint32_t pdstb; + uint32_t pprog; + uint32_t ptc; + uint32_t ptm; + uint32_t ptm_rep; + uint32_t ptr; + uint32_t ptrim; + uint32_t pwe; + uint32_t fuse[SIFIVE_OTP_NUM_FUSES]; + /* config */ + uint32_t serial; +} SiFiveOTPState; + +DeviceState *sifive_u_otp_create(hwaddr addr, uint32_t serial); + +#endif /* HW_SIFIVE_U_OTP_H */ --=20 2.7.4