From patchwork Wed Sep 25 14:56:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1167459 X-Patchwork-Delegate: bmeng.cn@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="XKxjlow2"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46djlR4Ycxz9sNx for ; Thu, 26 Sep 2019 02:13:07 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 3C81FC2200F; Wed, 25 Sep 2019 16:10:19 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 44695C221FE; Wed, 25 Sep 2019 15:04:14 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 0D26FC220B2; Wed, 25 Sep 2019 15:04:12 +0000 (UTC) Received: from mail-io1-f68.google.com (mail-io1-f68.google.com [209.85.166.68]) by lists.denx.de (Postfix) with ESMTPS id 51D0DC220B2 for ; Wed, 25 Sep 2019 14:59:01 +0000 (UTC) Received: by mail-io1-f68.google.com with SMTP id c25so14583531iot.12 for ; Wed, 25 Sep 2019 07:59:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=R6H0yCaiyZtHzJ6xodYSU6u3z1LaGswFeO1iA2k6SrQ=; b=XKxjlow26eMSeiqM7i4c4u4di/YyUluEN/YxQ79jjTX76SHNz3c+aH7zCmp2AfqZBy 2adrN33c8+aEuepyfUpk2Wt/u4U2wS8nhKwxrGpDvH6ZrpxpZ+walF30g3rGJ9YT/wYJ +7BA0zoNQx/lAAzsEoyFlTtHdHDz1w5xys+FU= 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=R6H0yCaiyZtHzJ6xodYSU6u3z1LaGswFeO1iA2k6SrQ=; b=QECDBOFj5OKZsc4UzWacOYD0oq84cAaD6o37iX8riQlVg1p67n4cNUO4eubi1tFEW9 yvFufpNrCgKW4CeDBt+Oo3XtOfiiMjyhraA/jqk4GoN2rdLpSHQ4xHKilYQhoQlVzz29 OY56f+MrIMa2ZXVTYDNmuka6z28DK73e+zcbRuwbLBHpWFmQd5dovKubOvDaHGmz8j/L hYjsee73619V0qceiSN5Kp6Q1AD9Xi95ifCGh4x8pdzW+Xsca2IWBWPe/LOHwDTaRBGG /HcnBYNg6KhhEZxEpVosUsVUk2jPE09Eb8D/hoJtZY861pxDWizSVdJkQ2wd/sSStRLn 2Zeg== X-Gm-Message-State: APjAAAVJstBQJiK0w5HqY46IApb8kWJLZVn2DpNRzxUwwyh+oX1erfq6 K71rCU9jJVuvxfv6xGhZ84Aqxi7bqLM= X-Google-Smtp-Source: APXvYqwxNv+QSCyX1+kc65ib5vty4OZgvxzygFZTA0ps8nkcF6NdIkBkMFcH8YU/Tthi8hyiLoDMkQ== X-Received: by 2002:a6b:3705:: with SMTP id e5mr9113034ioa.213.1569423539883; Wed, 25 Sep 2019 07:58:59 -0700 (PDT) Received: from kiwi.bld.corp.google.com ([2620:15c:183:0:8223:87c:a681:66aa]) by smtp.gmail.com with ESMTPSA id d9sm4254964ioq.9.2019.09.25.07.58.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 25 Sep 2019 07:58:59 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Date: Wed, 25 Sep 2019 08:56:59 -0600 Message-Id: <20190925145750.200592-76-sjg@chromium.org> X-Mailer: git-send-email 2.23.0.444.g18eeb5a265-goog In-Reply-To: <20190925145750.200592-1-sjg@chromium.org> References: <20190925145750.200592-1-sjg@chromium.org> MIME-Version: 1.0 Subject: [U-Boot] [PATCH 075/126] sandbox: Add PCI driver and test for p2sb X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Add a sandbox driver and PCI-device emulator for p2sb. Also add a test which uses a simple 'adder' driver to test the p2sb functionality. Signed-off-by: Simon Glass --- arch/sandbox/cpu/state.c | 1 + arch/sandbox/dts/test.dts | 13 ++ arch/sandbox/include/asm/test.h | 10 ++ drivers/misc/Makefile | 2 + drivers/misc/p2sb_emul.c | 272 ++++++++++++++++++++++++++++++++ drivers/misc/p2sb_sandbox.c | 44 ++++++ drivers/misc/sandbox_adder.c | 60 +++++++ test/dm/Makefile | 1 + test/dm/p2sb.c | 28 ++++ 9 files changed, 431 insertions(+) create mode 100644 drivers/misc/p2sb_emul.c create mode 100644 drivers/misc/p2sb_sandbox.c create mode 100644 drivers/misc/sandbox_adder.c create mode 100644 test/dm/p2sb.c diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c index dee5fde4f73..cd46e000f5e 100644 --- a/arch/sandbox/cpu/state.c +++ b/arch/sandbox/cpu/state.c @@ -356,6 +356,7 @@ void state_reset_for_test(struct sandbox_state *state) /* No reset yet, so mark it as such. Always allow power reset */ state->last_sysreset = SYSRESET_COUNT; state->sysreset_allowed[SYSRESET_POWER_OFF] = true; + state->allow_memio = false; memset(&state->wdt, '\0', sizeof(state->wdt)); memset(state->spi, '\0', sizeof(state->spi)); diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 9b72c2f279c..cd4409b7aea 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -461,6 +461,16 @@ 0x0100f810 0 0 0 0>; sandbox,emul = <&swap_case_emul1>; }; + p2sb-pci@2,0 { + compatible = "sandbox,p2sb"; + reg = <0x02001010 0 0 0 0>; + sandbox,emul = <&p2sb_emul>; + + adder { + intel,p2sb-port-id = <3>; + compatible = "sandbox,adder"; + }; + }; pci@1e,0 { compatible = "sandbox,pmc"; reg = <0xf000 0 0 0 0>; @@ -489,6 +499,9 @@ compatible = "sandbox,swap-case"; use-ea; }; + p2sb_emul: emul@2,0 { + compatible = "sandbox,p2sb-emul"; + }; pmc_emul1e: emul@1e,0 { compatible = "sandbox,pmc-emul"; }; diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h index 7f9e7fc26f5..77fff529e19 100644 --- a/arch/sandbox/include/asm/test.h +++ b/arch/sandbox/include/asm/test.h @@ -14,6 +14,7 @@ #define SANDBOX_PCI_VENDOR_ID 0x1234 #define SANDBOX_PCI_SWAP_CASE_EMUL_ID 0x5678 #define SANDBOX_PCI_PMC_EMUL_ID 0x5677 +#define SANDBOX_PCI_P2SB_EMUL_ID 0x5676 #define SANDBOX_PCI_CLASS_CODE PCI_CLASS_CODE_COMM #define SANDBOX_PCI_CLASS_SUB_CODE PCI_CLASS_SUB_CODE_COMM_SERIAL @@ -214,4 +215,13 @@ int sandbox_get_pci_ep_irq_count(struct udevice *dev); */ uint sandbox_pci_read_bar(u32 barval, int type, uint size); +/** + * sandbox_set_enable_memio() - Enable memory-mapped I/O read/write + * + * Normally readl(), writel() and the like are nops on sandbox. If this function + * is called with true, those function do real memory accesses. This is useful + * for certain tests. + */ +void sandbox_set_enable_memio(bool enable); + #endif diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 840d9fa5e39..90ef92806b9 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_$(SPL_TPL_)CROS_EC_SANDBOX) += cros_ec_sandbox.o obj-$(CONFIG_$(SPL_TPL_)CROS_EC_LPC) += cros_ec_lpc.o ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_SANDBOX) += sandbox_adder.o obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o obj-$(CONFIG_SANDBOX) += swap_case.o @@ -50,6 +51,7 @@ obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o obj-$(CONFIG_NS87308) += ns87308.o obj-$(CONFIG_NUVOTON_NCT6102D) += nuvoton_nct6102d.o obj-$(CONFIG_P2SB) += p2sb-uclass.o +obj-$(CONFIG_SANDBOX) += p2sb_sandbox.o p2sb_emul.o obj-$(CONFIG_PCA9551_LED) += pca9551_led.o obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o obj-$(CONFIG_QFW) += qfw.o diff --git a/drivers/misc/p2sb_emul.c b/drivers/misc/p2sb_emul.c new file mode 100644 index 00000000000..c51db143495 --- /dev/null +++ b/drivers/misc/p2sb_emul.c @@ -0,0 +1,272 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * PCI emulation device for an x86 Primary-to-Sideband bus + * + * Copyright 2019 Google LLC + * Written by Simon Glass + */ + +#define LOG_CATEGORY UCLASS_MISC +#define LOG_DEBUG + +#include +#include +#include +#include +#include +#include + +/** + * struct p2sb_emul_platdata - platform data for this device + * + * @command: Current PCI command value + * @bar: Current base address values + */ +struct p2sb_emul_platdata { + u16 command; + u32 bar[6]; +}; + +enum { + /* This emulator supports 16 different devices */ + MEMMAP_SIZE = 16 << PCR_PORTID_SHIFT, +}; + +static struct pci_bar { + int type; + u32 size; +} barinfo[] = { + { PCI_BASE_ADDRESS_MEM_TYPE_32, MEMMAP_SIZE }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, +}; + +struct p2sb_emul_priv { + u8 regs[16]; +}; + +static int sandbox_p2sb_emul_read_config(struct udevice *emul, uint offset, + ulong *valuep, enum pci_size_t size) +{ + struct p2sb_emul_platdata *plat = dev_get_platdata(emul); + + switch (offset) { + case PCI_COMMAND: + *valuep = plat->command; + break; + case PCI_HEADER_TYPE: + *valuep = PCI_HEADER_TYPE_NORMAL; + break; + case PCI_VENDOR_ID: + *valuep = SANDBOX_PCI_VENDOR_ID; + break; + case PCI_DEVICE_ID: + *valuep = SANDBOX_PCI_P2SB_EMUL_ID; + break; + case PCI_CLASS_DEVICE: + if (size == PCI_SIZE_8) { + *valuep = SANDBOX_PCI_CLASS_SUB_CODE; + } else { + *valuep = (SANDBOX_PCI_CLASS_CODE << 8) | + SANDBOX_PCI_CLASS_SUB_CODE; + } + break; + case PCI_CLASS_CODE: + *valuep = SANDBOX_PCI_CLASS_CODE; + break; + case PCI_BASE_ADDRESS_0: + case PCI_BASE_ADDRESS_1: + case PCI_BASE_ADDRESS_2: + case PCI_BASE_ADDRESS_3: + case PCI_BASE_ADDRESS_4: + case PCI_BASE_ADDRESS_5: { + int barnum; + u32 *bar; + + barnum = pci_offset_to_barnum(offset); + bar = &plat->bar[barnum]; + + *valuep = sandbox_pci_read_bar(*bar, barinfo[barnum].type, + barinfo[barnum].size); + break; + } + case PCI_CAPABILITY_LIST: + *valuep = PCI_CAP_ID_PM_OFFSET; + break; + } + + return 0; +} + +static int sandbox_p2sb_emul_write_config(struct udevice *emul, uint offset, + ulong value, enum pci_size_t size) +{ + struct p2sb_emul_platdata *plat = dev_get_platdata(emul); + + switch (offset) { + case PCI_COMMAND: + plat->command = value; + break; + case PCI_BASE_ADDRESS_0: + case PCI_BASE_ADDRESS_1: { + int barnum; + u32 *bar; + + barnum = pci_offset_to_barnum(offset); + bar = &plat->bar[barnum]; + + log_debug("w bar %d=%lx\n", barnum, value); + *bar = value; + /* space indicator (bit#0) is read-only */ + *bar |= barinfo[barnum].type; + break; + } + } + + return 0; +} + +static int sandbox_p2sb_emul_find_bar(struct udevice *emul, unsigned int addr, + int *barnump, unsigned int *offsetp) +{ + struct p2sb_emul_platdata *plat = dev_get_platdata(emul); + int barnum; + + for (barnum = 0; barnum < ARRAY_SIZE(barinfo); barnum++) { + unsigned int size = barinfo[barnum].size; + u32 base = plat->bar[barnum] & ~PCI_BASE_ADDRESS_SPACE; + + if (addr >= base && addr < base + size) { + *barnump = barnum; + *offsetp = addr - base; + return 0; + } + } + *barnump = -1; + + return -ENOENT; +} + +static int sandbox_p2sb_emul_read_io(struct udevice *dev, unsigned int addr, + ulong *valuep, enum pci_size_t size) +{ + unsigned int offset; + int barnum; + int ret; + + ret = sandbox_p2sb_emul_find_bar(dev, addr, &barnum, &offset); + if (ret) + return ret; + + if (barnum == 4) + *valuep = offset; + else if (barnum == 0) + *valuep = offset; + + return 0; +} + +static int sandbox_p2sb_emul_write_io(struct udevice *dev, unsigned int addr, + ulong value, enum pci_size_t size) +{ + unsigned int offset; + int barnum; + int ret; + + ret = sandbox_p2sb_emul_find_bar(dev, addr, &barnum, &offset); + if (ret) + return ret; + + return 0; +} + +static int find_p2sb_channel(struct udevice *emul, uint offset, + struct udevice **devp) +{ + uint pid = offset >> PCR_PORTID_SHIFT; + struct udevice *p2sb, *dev; + int ret; + + ret = sandbox_pci_get_client(emul, &p2sb); + if (ret) + return log_msg_ret("No client", ret); + + device_foreach_child(dev, p2sb) { + struct p2sb_child_platdata *pplat = + dev_get_parent_platdata(dev); + + log_debug(" - child %s, pid %d, want %d\n", dev->name, + pplat->pid, pid); + if (pid == pplat->pid) { + *devp = dev; + return 0; + } + } + + return -ENOENT; +} + +static int sandbox_p2sb_emul_map_physmem(struct udevice *dev, + phys_addr_t addr, unsigned long *lenp, + void **ptrp) +{ + struct p2sb_emul_priv *priv = dev_get_priv(dev); + struct udevice *child; + unsigned int offset; + int barnum; + int ret; + + log_debug("map %x: ", addr); + ret = sandbox_p2sb_emul_find_bar(dev, addr, &barnum, &offset); + if (ret) + return log_msg_ret("Cannot find bar", ret); + log_debug("bar %d, offset %x\n", barnum, offset); + + if (barnum != 0) + return log_msg_ret("Unknown BAR", -EINVAL); + + ret = find_p2sb_channel(dev, offset, &child); + if (ret) + return log_msg_ret("Cannot find channel", ret); + + offset &= ((1 << PCR_PORTID_SHIFT) - 1); + ret = axi_read(child, offset, priv->regs, AXI_SIZE_32); + if (ret) + return log_msg_ret("Child read failed", ret); + *ptrp = priv->regs + (offset & 3); + *lenp = 4; + + return 0; +} + +static struct dm_pci_emul_ops sandbox_p2sb_emul_emul_ops = { + .read_config = sandbox_p2sb_emul_read_config, + .write_config = sandbox_p2sb_emul_write_config, + .read_io = sandbox_p2sb_emul_read_io, + .write_io = sandbox_p2sb_emul_write_io, + .map_physmem = sandbox_p2sb_emul_map_physmem, +}; + +static const struct udevice_id sandbox_p2sb_emul_ids[] = { + { .compatible = "sandbox,p2sb-emul" }, + { } +}; + +U_BOOT_DRIVER(sandbox_p2sb_emul_emul) = { + .name = "sandbox_p2sb_emul_emul", + .id = UCLASS_PCI_EMUL, + .of_match = sandbox_p2sb_emul_ids, + .ops = &sandbox_p2sb_emul_emul_ops, + .priv_auto_alloc_size = sizeof(struct p2sb_emul_priv), + .platdata_auto_alloc_size = sizeof(struct p2sb_emul_platdata), +}; + +static struct pci_device_id sandbox_p2sb_emul_supported[] = { + { PCI_VDEVICE(SANDBOX, SANDBOX_PCI_PMC_EMUL_ID) }, + {}, +}; + +U_BOOT_PCI_DEVICE(sandbox_p2sb_emul_emul, sandbox_p2sb_emul_supported); diff --git a/drivers/misc/p2sb_sandbox.c b/drivers/misc/p2sb_sandbox.c new file mode 100644 index 00000000000..2337df9951d --- /dev/null +++ b/drivers/misc/p2sb_sandbox.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Sandbox P2SB for testing + * + * Copyright 2019 Google LLC + */ + +#define LOG_CATEGORY UCLASS_P2SB + +#include +#include +#include +#include + +struct sandbox_p2sb_priv { + ulong base; +}; + +static int sandbox_p2sb_probe(struct udevice *dev) +{ + struct p2sb_uc_priv *upriv = dev_get_uclass_priv(dev); + + upriv->mmio_base = dm_pci_read_bar32(dev, 0); + printf("mmio base %x\n", upriv->mmio_base); + + return 0; +} + +static struct p2sb_ops sandbox_p2sb_ops = { +}; + +static const struct udevice_id sandbox_p2sb_ids[] = { + { .compatible = "sandbox,p2sb" }, + { } +}; + +U_BOOT_DRIVER(p2sb_sandbox) = { + .name = "pmic_pm8916", + .id = UCLASS_P2SB, + .of_match = sandbox_p2sb_ids, + .probe = sandbox_p2sb_probe, + .ops = &sandbox_p2sb_ops, + .priv_auto_alloc_size = sizeof(struct sandbox_p2sb_priv), +}; diff --git a/drivers/misc/sandbox_adder.c b/drivers/misc/sandbox_adder.c new file mode 100644 index 00000000000..df262e62555 --- /dev/null +++ b/drivers/misc/sandbox_adder.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Sandbox adder for p2sb testing + * + * Copyright 2019 Google LLC + */ + +#define LOG_CATEGORY UCLASS_MISC + +#include +#include +#include +#include +#include +#include + +struct sandbox_adder_priv { + ulong base; +}; + +int sandbox_adder_read(struct udevice *dev, ulong address, void *data, + enum axi_size_t size) +{ + struct p2sb_child_platdata *pplat = dev_get_parent_platdata(dev); + u32 *val = data; + + *val = pplat->pid << 24 | address; + + return 0; +} + +int sandbox_adder_write(struct udevice *dev, ulong address, void *data, + enum axi_size_t size) +{ + return 0; +} + +static int sandbox_adder_probe(struct udevice *dev) +{ + return 0; +} + +static struct axi_ops sandbox_adder_ops = { + .read = sandbox_adder_read, + .write = sandbox_adder_write, +}; + +static const struct udevice_id sandbox_adder_ids[] = { + { .compatible = "sandbox,adder" }, + { } +}; + +U_BOOT_DRIVER(adder_sandbox) = { + .name = "sandbox_adder", + .id = UCLASS_AXI, + .of_match = sandbox_adder_ids, + .probe = sandbox_adder_probe, + .ops = &sandbox_adder_ops, + .priv_auto_alloc_size = sizeof(struct sandbox_adder_priv), +}; diff --git a/test/dm/Makefile b/test/dm/Makefile index c1d34bfbbe7..52a2392a8e9 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -31,6 +31,7 @@ obj-y += ofnode.o obj-$(CONFIG_OSD) += osd.o obj-$(CONFIG_DM_VIDEO) += panel.o obj-$(CONFIG_DM_PCI) += pci.o +obj-$(CONFIG_P2SB) += p2sb.o obj-$(CONFIG_PCI_ENDPOINT) += pci_ep.o obj-$(CONFIG_PCH) += pch.o obj-$(CONFIG_PHY) += phy.o diff --git a/test/dm/p2sb.c b/test/dm/p2sb.c new file mode 100644 index 00000000000..ccb75cf3753 --- /dev/null +++ b/test/dm/p2sb.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for Primary-to-Sideband bus (P2SB) + * + * Copyright 2019 Google LLC + */ + +#include +#include +#include +#include +#include +#include + +/* Base test of the PMC uclass */ +static int dm_test_p2sb_base(struct unit_test_state *uts) +{ + struct udevice *dev; + + sandbox_set_enable_memio(true); + ut_assertok(uclass_get_device_by_name(UCLASS_AXI, "adder", &dev)); + ut_asserteq(0x03000004, pcr_read32(dev, 4)); + ut_asserteq(0x300, pcr_read16(dev, 6)); + ut_asserteq(4, pcr_read8(dev, 4)); + + return 0; +} +DM_TEST(dm_test_p2sb_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);