From patchwork Wed Sep 25 14:32:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 174359 Delivered-To: patch@linaro.org Received: by 2002:a92:7e96:0:0:0:0:0 with SMTP id q22csp721892ill; Wed, 25 Sep 2019 07:37:36 -0700 (PDT) X-Google-Smtp-Source: APXvYqwt55VMThc2jPCJABztsSVcQCXmhUnFhHM3TvTKqBg7xFUuc0HYqCKO7DMK3FhlNRX62b+i X-Received: by 2002:a17:906:4801:: with SMTP id w1mr4377861ejq.245.1569422256665; Wed, 25 Sep 2019 07:37:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1569422256; cv=none; d=google.com; s=arc-20160816; b=FsrbQEcMhovqhpczwVZKv6vbnPq/wNW0P0esxQHAdpF3hoB75tY6OLCZTJnsIGkdRK rzmD+DmX7rrkBg8nVzqyJRs4Tn3Elv4LO/Lbe7IwXuzuUsYOy/zqg0W+/Ri45Z/Vrgdv luP3JdEvLcdg/AG+HXN0IoV+X7jWF+1nrjB7UdtZuGjuiLNCZnLuTCdMobQCjCzxrKXl GULF9zIU+OvYn95mCOXC9wGUP19e+PwI0dHhOOrUJNtxcDXdbELQb0VBnGhjvng6at8X V42/O6vXIOQYv97VSYYVPw3r+KrrtzK3RqDljAE73gfNkeVeEcLa1eKFiBeTPvBpiklH PemQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from; bh=sEwfkNcdHqYBzuzr+NLWPG25XlVahl2L3OCthx5IHS4=; b=OKjro0dgleSgCQFKjARLj9XrbgaTmpzz5jlIjwx+wedhYD7Sb3iU3CfXcMYVMIpYl5 B9TSbwRVUzAoLHfzAJN5GkuAVj/w4YDrUchN0v+yh1ZWSUqmaUQmaDjhqQUXT2ovfII2 bGtaLyhDWRToNVUfVBtgVJy17Ip6qaledxDES+MqlGUMMqheeI+zFW7Y4t52rsxPXovt UZGztSjhATqye28tvgvKWHnKzFr8SVi+qjAylLWKzRXXkL7UcElhWuSOCTMqQ/x6j309 5V74S3JwfGhQLQL+MuCDyIzVZH06IN6bpo6y6OMxf+P5PRTO0vobMDY2feCOc7dL6Dko XH2w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org" Return-Path: Received: from lists.gnu.org (lists.gnu.org. [209.51.188.17]) by mx.google.com with ESMTPS id k2si3447429ede.311.2019.09.25.07.37.36 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 25 Sep 2019 07:37:36 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; Authentication-Results: mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org" Received: from localhost ([::1]:53010 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iD8QB-0006lI-7A for patch@linaro.org; Wed, 25 Sep 2019 10:37:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:52326) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iD8MH-0003N0-Ib for qemu-devel@nongnu.org; Wed, 25 Sep 2019 10:33:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iD8MF-0000Pn-2Z for qemu-devel@nongnu.org; Wed, 25 Sep 2019 10:33:33 -0400 Received: from 9.mo178.mail-out.ovh.net ([46.105.75.45]:49030) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iD8ME-0000Mu-P9 for qemu-devel@nongnu.org; Wed, 25 Sep 2019 10:33:31 -0400 Received: from player786.ha.ovh.net (unknown [10.109.160.253]) by mo178.mail-out.ovh.net (Postfix) with ESMTP id 6F30D7A52F for ; Wed, 25 Sep 2019 16:33:26 +0200 (CEST) Received: from kaod.org (lfbn-1-2229-223.w90-76.abo.wanadoo.fr [90.76.50.223]) (Authenticated sender: clg@kaod.org) by player786.ha.ovh.net (Postfix) with ESMTPSA id D9A73A4D3C35; Wed, 25 Sep 2019 14:33:19 +0000 (UTC) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: Peter Maydell Subject: [PATCH v2 03/23] hw: aspeed_scu: Add AST2600 support Date: Wed, 25 Sep 2019 16:32:28 +0200 Message-Id: <20190925143248.10000-4-clg@kaod.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190925143248.10000-1-clg@kaod.org> References: <20190925143248.10000-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 8842254921771485969 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedufedrfedvgdejkecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfqggfjpdevjffgvefmvefgnecuuegrihhlohhuthemucehtddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 46.105.75.45 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: Andrew Jeffery , =?utf-8?q?C=C3=A9dric_Le_Goater?= , qemu-arm@nongnu.org, qemu-devel@nongnu.org, Joel Stanley Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Joel Stanley The SCU controller on the AST2600 SoC has extra registers. Increase the number of regs of the model and introduce a new field in the class to customize the MemoryRegion operations depending on the SoC model. Signed-off-by: Joel Stanley [clg: - improved commit log - changed vmstate version - reworked model integration into new object class - included AST2600_HPLL_PARAM value ] Signed-off-by: Cédric Le Goater --- include/hw/misc/aspeed_scu.h | 7 +- hw/misc/aspeed_scu.c | 192 +++++++++++++++++++++++++++++++++-- 2 files changed, 191 insertions(+), 8 deletions(-) -- 2.21.0 diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h index 239e94fe2c47..1d7f7ffc1598 100644 --- a/include/hw/misc/aspeed_scu.h +++ b/include/hw/misc/aspeed_scu.h @@ -17,8 +17,10 @@ #define ASPEED_SCU(obj) OBJECT_CHECK(AspeedSCUState, (obj), TYPE_ASPEED_SCU) #define TYPE_ASPEED_2400_SCU TYPE_ASPEED_SCU "-ast2400" #define TYPE_ASPEED_2500_SCU TYPE_ASPEED_SCU "-ast2500" +#define TYPE_ASPEED_2600_SCU TYPE_ASPEED_SCU "-ast2600" #define ASPEED_SCU_NR_REGS (0x1A8 >> 2) +#define ASPEED_AST2600_SCU_NR_REGS (0xE20 >> 2) typedef struct AspeedSCUState { /*< private >*/ @@ -27,7 +29,7 @@ typedef struct AspeedSCUState { /*< public >*/ MemoryRegion iomem; - uint32_t regs[ASPEED_SCU_NR_REGS]; + uint32_t regs[ASPEED_AST2600_SCU_NR_REGS]; uint32_t silicon_rev; uint32_t hw_strap1; uint32_t hw_strap2; @@ -38,6 +40,7 @@ typedef struct AspeedSCUState { #define AST2400_A1_SILICON_REV 0x02010303U #define AST2500_A0_SILICON_REV 0x04000303U #define AST2500_A1_SILICON_REV 0x04010303U +#define AST2600_A0_SILICON_REV 0x05000303U #define ASPEED_IS_AST2500(si_rev) ((((si_rev) >> 24) & 0xff) == 0x04) @@ -54,6 +57,8 @@ typedef struct AspeedSCUClass { const uint32_t *resets; uint32_t (*calc_hpll)(AspeedSCUState *s, uint32_t hpll_reg); uint32_t apb_divider; + uint32_t nr_regs; + const MemoryRegionOps *ops; } AspeedSCUClass; #define ASPEED_SCU_PROT_KEY 0x1688A8A8 diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c index 620b25c20476..84699b78d4ce 100644 --- a/hw/misc/aspeed_scu.c +++ b/hw/misc/aspeed_scu.c @@ -88,6 +88,35 @@ #define BMC_REV TO_REG(0x19C) #define BMC_DEV_ID TO_REG(0x1A4) +#define AST2600_PROT_KEY TO_REG(0x00) +#define AST2600_SILICON_REV TO_REG(0x04) +#define AST2600_SILICON_REV2 TO_REG(0x14) +#define AST2600_SYS_RST_CTRL TO_REG(0x40) +#define AST2600_SYS_RST_CTRL_CLR TO_REG(0x44) +#define AST2600_SYS_RST_CTRL2 TO_REG(0x50) +#define AST2600_SYS_RST_CTRL2_CLR TO_REG(0x54) +#define AST2600_CLK_STOP_CTRL TO_REG(0x80) +#define AST2600_CLK_STOP_CTRL_CLR TO_REG(0x84) +#define AST2600_CLK_STOP_CTRL2 TO_REG(0x90) +#define AST2600_CLK_STOP_CTR2L_CLR TO_REG(0x94) +#define AST2600_HPLL_PARAM TO_REG(0x200) +#define AST2600_HPLL_EXT TO_REG(0x204) +#define AST2600_MPLL_EXT TO_REG(0x224) +#define AST2600_EPLL_EXT TO_REG(0x244) +#define AST2600_CLK_SEL TO_REG(0x300) +#define AST2600_CLK_SEL2 TO_REG(0x304) +#define AST2600_CLK_SEL3 TO_REG(0x310) +#define AST2600_HW_STRAP1 TO_REG(0x500) +#define AST2600_HW_STRAP1_CLR TO_REG(0x504) +#define AST2600_HW_STRAP1_PROT TO_REG(0x508) +#define AST2600_HW_STRAP2 TO_REG(0x510) +#define AST2600_HW_STRAP2_CLR TO_REG(0x514) +#define AST2600_HW_STRAP2_PROT TO_REG(0x518) +#define AST2600_RNG_CTRL TO_REG(0x524) +#define AST2600_RNG_DATA TO_REG(0x540) + +#define AST2600_CLK TO_REG(0x40) + #define SCU_IO_REGION_SIZE 0x1000 static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = { @@ -178,7 +207,7 @@ static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size) AspeedSCUState *s = ASPEED_SCU(opaque); int reg = TO_REG(offset); - if (reg >= ARRAY_SIZE(s->regs)) { + if (reg >= ASPEED_SCU_NR_REGS) { qemu_log_mask(LOG_GUEST_ERROR, "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", __func__, offset); @@ -208,7 +237,7 @@ static void aspeed_scu_write(void *opaque, hwaddr offset, uint64_t data, AspeedSCUState *s = ASPEED_SCU(opaque); int reg = TO_REG(offset); - if (reg >= ARRAY_SIZE(s->regs)) { + if (reg >= ASPEED_SCU_NR_REGS) { qemu_log_mask(LOG_GUEST_ERROR, "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n", __func__, offset); @@ -346,7 +375,7 @@ static void aspeed_scu_reset(DeviceState *dev) AspeedSCUState *s = ASPEED_SCU(dev); AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev); - memcpy(s->regs, asc->resets, sizeof(s->regs)); + memcpy(s->regs, asc->resets, asc->nr_regs * 4); s->regs[SILICON_REV] = s->silicon_rev; s->regs[HW_STRAP1] = s->hw_strap1; s->regs[HW_STRAP2] = s->hw_strap2; @@ -358,6 +387,7 @@ static uint32_t aspeed_silicon_revs[] = { AST2400_A1_SILICON_REV, AST2500_A0_SILICON_REV, AST2500_A1_SILICON_REV, + AST2600_A0_SILICON_REV, }; bool is_supported_silicon_rev(uint32_t silicon_rev) @@ -377,6 +407,7 @@ static void aspeed_scu_realize(DeviceState *dev, Error **errp) { SysBusDevice *sbd = SYS_BUS_DEVICE(dev); AspeedSCUState *s = ASPEED_SCU(dev); + AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev); if (!is_supported_silicon_rev(s->silicon_rev)) { error_setg(errp, "Unknown silicon revision: 0x%" PRIx32, @@ -384,7 +415,7 @@ static void aspeed_scu_realize(DeviceState *dev, Error **errp) return; } - memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_scu_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), asc->ops, s, TYPE_ASPEED_SCU, SCU_IO_REGION_SIZE); sysbus_init_mmio(sbd, &s->iomem); @@ -392,10 +423,10 @@ static void aspeed_scu_realize(DeviceState *dev, Error **errp) static const VMStateDescription vmstate_aspeed_scu = { .name = "aspeed.scu", - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, AspeedSCUState, ASPEED_SCU_NR_REGS), + VMSTATE_UINT32_ARRAY(regs, AspeedSCUState, ASPEED_AST2600_SCU_NR_REGS), VMSTATE_END_OF_LIST() } }; @@ -436,6 +467,8 @@ static void aspeed_2400_scu_class_init(ObjectClass *klass, void *data) asc->resets = ast2400_a0_resets; asc->calc_hpll = aspeed_2400_scu_calc_hpll; asc->apb_divider = 2; + asc->nr_regs = ASPEED_SCU_NR_REGS; + asc->ops = &aspeed_scu_ops; } static const TypeInfo aspeed_2400_scu_info = { @@ -454,6 +487,8 @@ static void aspeed_2500_scu_class_init(ObjectClass *klass, void *data) asc->resets = ast2500_a1_resets; asc->calc_hpll = aspeed_2500_scu_calc_hpll; asc->apb_divider = 4; + asc->nr_regs = ASPEED_SCU_NR_REGS; + asc->ops = &aspeed_scu_ops; } static const TypeInfo aspeed_2500_scu_info = { @@ -463,11 +498,154 @@ static const TypeInfo aspeed_2500_scu_info = { .class_init = aspeed_2500_scu_class_init, }; +static uint64_t aspeed_ast2600_scu_read(void *opaque, hwaddr offset, + unsigned size) +{ + AspeedSCUState *s = ASPEED_SCU(opaque); + int reg = TO_REG(offset); + + if (reg >= ASPEED_AST2600_SCU_NR_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", + __func__, offset); + return 0; + } + + switch (reg) { + case AST2600_HPLL_EXT: + case AST2600_EPLL_EXT: + case AST2600_MPLL_EXT: + /* PLLs are always "locked" */ + return s->regs[reg] | BIT(31); + case AST2600_RNG_DATA: + /* + * On hardware, RNG_DATA works regardless of the state of the + * enable bit in RNG_CTRL + * + * TODO: Check this is true for ast2600 + */ + s->regs[AST2600_RNG_DATA] = aspeed_scu_get_random(); + break; + } + + return s->regs[reg]; +} + +static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset, uint64_t data, + unsigned size) +{ + AspeedSCUState *s = ASPEED_SCU(opaque); + int reg = TO_REG(offset); + + if (reg >= ASPEED_AST2600_SCU_NR_REGS) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n", + __func__, offset); + return; + } + + if (reg > PROT_KEY && !s->regs[PROT_KEY]) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__); + } + + trace_aspeed_scu_write(offset, size, data); + + switch (reg) { + case AST2600_PROT_KEY: + s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0; + return; + case AST2600_HW_STRAP1: + case AST2600_HW_STRAP2: + if (s->regs[reg + 2]) { + return; + } + /* fall through */ + case AST2600_SYS_RST_CTRL: + case AST2600_SYS_RST_CTRL2: + /* W1S (Write 1 to set) registers */ + s->regs[reg] |= data; + return; + case AST2600_SYS_RST_CTRL_CLR: + case AST2600_SYS_RST_CTRL2_CLR: + case AST2600_HW_STRAP1_CLR: + case AST2600_HW_STRAP2_CLR: + /* W1C (Write 1 to clear) registers */ + s->regs[reg] &= ~data; + return; + + case AST2600_RNG_DATA: + case AST2600_SILICON_REV: + case AST2600_SILICON_REV2: + /* Add read only registers here */ + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n", + __func__, offset); + return; + } + + s->regs[reg] = data; +} + +static const MemoryRegionOps aspeed_ast2600_scu_ops = { + .read = aspeed_ast2600_scu_read, + .write = aspeed_ast2600_scu_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid.min_access_size = 4, + .valid.max_access_size = 4, + .valid.unaligned = false, +}; + +static const uint32_t ast2600_a0_resets[ASPEED_AST2600_SCU_NR_REGS] = { + [AST2600_SILICON_REV] = AST2600_SILICON_REV, + [AST2600_SILICON_REV2] = AST2600_SILICON_REV, + [AST2600_SYS_RST_CTRL] = 0xF7CFFEDC | 0x100, + [AST2600_SYS_RST_CTRL2] = 0xFFFFFFFC, + [AST2600_CLK_STOP_CTRL] = 0xEFF43E8B, + [AST2600_CLK_STOP_CTRL2] = 0xFFF0FFF0, + [AST2600_HPLL_PARAM] = 0x1000405F, +}; + +static void aspeed_ast2600_scu_reset(DeviceState *dev) +{ + AspeedSCUState *s = ASPEED_SCU(dev); + AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev); + + memcpy(s->regs, asc->resets, asc->nr_regs * 4); + + s->regs[AST2600_SILICON_REV] = s->silicon_rev; + s->regs[AST2600_SILICON_REV2] = s->silicon_rev; + s->regs[AST2600_HW_STRAP1] = s->hw_strap1; + s->regs[AST2600_HW_STRAP2] = s->hw_strap2; + s->regs[PROT_KEY] = s->hw_prot_key; +} + +static void aspeed_2600_scu_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass); + + dc->desc = "ASPEED 2600 System Control Unit"; + dc->reset = aspeed_ast2600_scu_reset; + asc->resets = ast2600_a0_resets; + asc->calc_hpll = aspeed_2500_scu_calc_hpll; /* No change since AST2500 */ + asc->apb_divider = 4; + asc->nr_regs = ASPEED_AST2600_SCU_NR_REGS; + asc->ops = &aspeed_ast2600_scu_ops; +} + +static const TypeInfo aspeed_2600_scu_info = { + .name = TYPE_ASPEED_2600_SCU, + .parent = TYPE_ASPEED_SCU, + .instance_size = sizeof(AspeedSCUState), + .class_init = aspeed_2600_scu_class_init, +}; + static void aspeed_scu_register_types(void) { type_register_static(&aspeed_scu_info); type_register_static(&aspeed_2400_scu_info); type_register_static(&aspeed_2500_scu_info); + type_register_static(&aspeed_2600_scu_info); } type_init(aspeed_scu_register_types);