Commit 3e17ffbb44cd24c53504179ff51a835502b183ed

Authored by Simon Glass
Committed by Bin Meng
1 parent 89694de514

sandbox: Add PCI driver and test for p2sb

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 <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Showing 13 changed files with 428 additions and 0 deletions Side-by-side Diff

arch/sandbox/dts/test.dts
... ... @@ -471,6 +471,16 @@
471 471 0x01000810 0 0 0 0>;
472 472 sandbox,emul = <&swap_case_emul0_1>;
473 473 };
  474 + p2sb-pci@2,0 {
  475 + compatible = "sandbox,p2sb";
  476 + reg = <0x02001010 0 0 0 0>;
  477 + sandbox,emul = <&p2sb_emul>;
  478 +
  479 + adder {
  480 + intel,p2sb-port-id = <3>;
  481 + compatible = "sandbox,adder";
  482 + };
  483 + };
474 484 pci@1e,0 {
475 485 compatible = "sandbox,pmc";
476 486 reg = <0xf000 0 0 0 0>;
... ... @@ -501,6 +511,9 @@
501 511 };
502 512 swap_case_emul0_1f: emul0@1f,0 {
503 513 compatible = "sandbox,swap-case";
  514 + };
  515 + p2sb_emul: emul@2,0 {
  516 + compatible = "sandbox,p2sb-emul";
504 517 };
505 518 pmc_emul1e: emul@1e,0 {
506 519 compatible = "sandbox,pmc-emul";
arch/sandbox/include/asm/test.h
... ... @@ -14,6 +14,7 @@
14 14 #define SANDBOX_PCI_VENDOR_ID 0x1234
15 15 #define SANDBOX_PCI_SWAP_CASE_EMUL_ID 0x5678
16 16 #define SANDBOX_PCI_PMC_EMUL_ID 0x5677
  17 +#define SANDBOX_PCI_P2SB_EMUL_ID 0x5676
17 18 #define SANDBOX_PCI_CLASS_CODE PCI_CLASS_CODE_COMM
18 19 #define SANDBOX_PCI_CLASS_SUB_CODE PCI_CLASS_SUB_CODE_COMM_SERIAL
19 20  
configs/sandbox64_defconfig
... ... @@ -83,6 +83,8 @@
83 83 CONFIG_DEBUG_DEVRES=y
84 84 CONFIG_ADC=y
85 85 CONFIG_ADC_SANDBOX=y
  86 +CONFIG_AXI=y
  87 +CONFIG_AXI_SANDBOX=y
86 88 CONFIG_CLK=y
87 89 CONFIG_CPU=y
88 90 CONFIG_DM_DEMO=y
... ... @@ -203,4 +205,5 @@
203 205 CONFIG_UNIT_TEST=y
204 206 CONFIG_UT_TIME=y
205 207 CONFIG_UT_DM=y
  208 +CONFIG_P2SB=y
configs/sandbox_defconfig
... ... @@ -132,6 +132,7 @@
132 132 CONFIG_CROS_EC_LPC=y
133 133 CONFIG_CROS_EC_SANDBOX=y
134 134 CONFIG_CROS_EC_SPI=y
  135 +CONFIG_P2SB=y
135 136 CONFIG_PWRSEQ=y
136 137 CONFIG_SPL_PWRSEQ=y
137 138 CONFIG_I2C_EEPROM=y
configs/sandbox_flattree_defconfig
... ... @@ -67,6 +67,8 @@
67 67 CONFIG_DEBUG_DEVRES=y
68 68 CONFIG_ADC=y
69 69 CONFIG_ADC_SANDBOX=y
  70 +CONFIG_AXI=y
  71 +CONFIG_AXI_SANDBOX=y
70 72 CONFIG_CLK=y
71 73 CONFIG_CLK_COMPOSITE_CCF=y
72 74 CONFIG_SANDBOX_CLK_CCF=y
... ... @@ -117,6 +119,7 @@
117 119 CONFIG_DM_PCI=y
118 120 CONFIG_DM_PCI_COMPAT=y
119 121 CONFIG_PCI_SANDBOX=y
  122 +CONFIG_P2SB=y
120 123 CONFIG_PHY=y
121 124 CONFIG_PHY_SANDBOX=y
122 125 CONFIG_PINCTRL=y
configs/sandbox_spl_defconfig
... ... @@ -88,6 +88,8 @@
88 88 # CONFIG_SPL_SIMPLE_BUS is not set
89 89 CONFIG_ADC=y
90 90 CONFIG_ADC_SANDBOX=y
  91 +CONFIG_AXI=y
  92 +CONFIG_AXI_SANDBOX=y
91 93 CONFIG_CLK=y
92 94 CONFIG_CPU=y
93 95 CONFIG_DM_DEMO=y
... ... @@ -202,4 +204,5 @@
202 204 CONFIG_UNIT_TEST=y
203 205 CONFIG_UT_TIME=y
204 206 CONFIG_UT_DM=y
  207 +CONFIG_P2SB=y
configs/tools-only_defconfig
... ... @@ -13,6 +13,8 @@
13 13 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
14 14 CONFIG_IP_DEFRAG=y
15 15 # CONFIG_UDP_FUNCTION_FASTBOOT is not set
  16 +CONFIG_AXI=y
  17 +CONFIG_AXI_SANDBOX=y
16 18 CONFIG_SANDBOX_GPIO=y
17 19 CONFIG_PCI=y
18 20 CONFIG_DM_PCI=y
drivers/misc/Makefile
... ... @@ -10,8 +10,10 @@
10 10 obj-$(CONFIG_$(SPL_TPL_)CROS_EC_LPC) += cros_ec_lpc.o
11 11  
12 12 ifndef CONFIG_SPL_BUILD
  13 +obj-$(CONFIG_SANDBOX) += sandbox_adder.o
13 14 obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o
14 15 obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o
  16 +obj-$(CONFIG_SANDBOX) += p2sb_sandbox.o p2sb_emul.o
15 17 obj-$(CONFIG_SANDBOX) += swap_case.o
16 18 endif
17 19  
drivers/misc/p2sb_emul.c
  1 +// SPDX-License-Identifier: GPL-2.0+
  2 +/*
  3 + * PCI emulation device for an x86 Primary-to-Sideband bus
  4 + *
  5 + * Copyright 2019 Google LLC
  6 + * Written by Simon Glass <sjg@chromium.org>
  7 + */
  8 +
  9 +#define LOG_CATEGORY UCLASS_MISC
  10 +#define LOG_DEBUG
  11 +
  12 +#include <common.h>
  13 +#include <axi.h>
  14 +#include <dm.h>
  15 +#include <pci.h>
  16 +#include <asm/test.h>
  17 +#include <p2sb.h>
  18 +
  19 +/**
  20 + * struct p2sb_emul_platdata - platform data for this device
  21 + *
  22 + * @command: Current PCI command value
  23 + * @bar: Current base address values
  24 + */
  25 +struct p2sb_emul_platdata {
  26 + u16 command;
  27 + u32 bar[6];
  28 +};
  29 +
  30 +enum {
  31 + /* This emulator supports 16 different devices */
  32 + MEMMAP_SIZE = 16 << PCR_PORTID_SHIFT,
  33 +};
  34 +
  35 +static struct pci_bar {
  36 + int type;
  37 + u32 size;
  38 +} barinfo[] = {
  39 + { PCI_BASE_ADDRESS_MEM_TYPE_32, MEMMAP_SIZE },
  40 + { 0, 0 },
  41 + { 0, 0 },
  42 + { 0, 0 },
  43 + { 0, 0 },
  44 + { 0, 0 },
  45 +};
  46 +
  47 +struct p2sb_emul_priv {
  48 + u8 regs[16];
  49 +};
  50 +
  51 +static int sandbox_p2sb_emul_read_config(struct udevice *emul, uint offset,
  52 + ulong *valuep, enum pci_size_t size)
  53 +{
  54 + struct p2sb_emul_platdata *plat = dev_get_platdata(emul);
  55 +
  56 + switch (offset) {
  57 + case PCI_COMMAND:
  58 + *valuep = plat->command;
  59 + break;
  60 + case PCI_HEADER_TYPE:
  61 + *valuep = PCI_HEADER_TYPE_NORMAL;
  62 + break;
  63 + case PCI_VENDOR_ID:
  64 + *valuep = SANDBOX_PCI_VENDOR_ID;
  65 + break;
  66 + case PCI_DEVICE_ID:
  67 + *valuep = SANDBOX_PCI_P2SB_EMUL_ID;
  68 + break;
  69 + case PCI_CLASS_DEVICE:
  70 + if (size == PCI_SIZE_8) {
  71 + *valuep = SANDBOX_PCI_CLASS_SUB_CODE;
  72 + } else {
  73 + *valuep = (SANDBOX_PCI_CLASS_CODE << 8) |
  74 + SANDBOX_PCI_CLASS_SUB_CODE;
  75 + }
  76 + break;
  77 + case PCI_CLASS_CODE:
  78 + *valuep = SANDBOX_PCI_CLASS_CODE;
  79 + break;
  80 + case PCI_BASE_ADDRESS_0:
  81 + case PCI_BASE_ADDRESS_1:
  82 + case PCI_BASE_ADDRESS_2:
  83 + case PCI_BASE_ADDRESS_3:
  84 + case PCI_BASE_ADDRESS_4:
  85 + case PCI_BASE_ADDRESS_5: {
  86 + int barnum;
  87 + u32 *bar;
  88 +
  89 + barnum = pci_offset_to_barnum(offset);
  90 + bar = &plat->bar[barnum];
  91 +
  92 + *valuep = sandbox_pci_read_bar(*bar, barinfo[barnum].type,
  93 + barinfo[barnum].size);
  94 + break;
  95 + }
  96 + case PCI_CAPABILITY_LIST:
  97 + *valuep = PCI_CAP_ID_PM_OFFSET;
  98 + break;
  99 + }
  100 +
  101 + return 0;
  102 +}
  103 +
  104 +static int sandbox_p2sb_emul_write_config(struct udevice *emul, uint offset,
  105 + ulong value, enum pci_size_t size)
  106 +{
  107 + struct p2sb_emul_platdata *plat = dev_get_platdata(emul);
  108 +
  109 + switch (offset) {
  110 + case PCI_COMMAND:
  111 + plat->command = value;
  112 + break;
  113 + case PCI_BASE_ADDRESS_0:
  114 + case PCI_BASE_ADDRESS_1: {
  115 + int barnum;
  116 + u32 *bar;
  117 +
  118 + barnum = pci_offset_to_barnum(offset);
  119 + bar = &plat->bar[barnum];
  120 +
  121 + log_debug("w bar %d=%lx\n", barnum, value);
  122 + *bar = value;
  123 + /* space indicator (bit#0) is read-only */
  124 + *bar |= barinfo[barnum].type;
  125 + break;
  126 + }
  127 + }
  128 +
  129 + return 0;
  130 +}
  131 +
  132 +static int sandbox_p2sb_emul_find_bar(struct udevice *emul, unsigned int addr,
  133 + int *barnump, unsigned int *offsetp)
  134 +{
  135 + struct p2sb_emul_platdata *plat = dev_get_platdata(emul);
  136 + int barnum;
  137 +
  138 + for (barnum = 0; barnum < ARRAY_SIZE(barinfo); barnum++) {
  139 + unsigned int size = barinfo[barnum].size;
  140 + u32 base = plat->bar[barnum] & ~PCI_BASE_ADDRESS_SPACE;
  141 +
  142 + if (addr >= base && addr < base + size) {
  143 + *barnump = barnum;
  144 + *offsetp = addr - base;
  145 + return 0;
  146 + }
  147 + }
  148 + *barnump = -1;
  149 +
  150 + return -ENOENT;
  151 +}
  152 +
  153 +static int sandbox_p2sb_emul_read_io(struct udevice *dev, unsigned int addr,
  154 + ulong *valuep, enum pci_size_t size)
  155 +{
  156 + unsigned int offset;
  157 + int barnum;
  158 + int ret;
  159 +
  160 + ret = sandbox_p2sb_emul_find_bar(dev, addr, &barnum, &offset);
  161 + if (ret)
  162 + return ret;
  163 +
  164 + if (barnum == 4)
  165 + *valuep = offset;
  166 + else if (barnum == 0)
  167 + *valuep = offset;
  168 +
  169 + return 0;
  170 +}
  171 +
  172 +static int sandbox_p2sb_emul_write_io(struct udevice *dev, unsigned int addr,
  173 + ulong value, enum pci_size_t size)
  174 +{
  175 + unsigned int offset;
  176 + int barnum;
  177 + int ret;
  178 +
  179 + ret = sandbox_p2sb_emul_find_bar(dev, addr, &barnum, &offset);
  180 + if (ret)
  181 + return ret;
  182 +
  183 + return 0;
  184 +}
  185 +
  186 +static int find_p2sb_channel(struct udevice *emul, uint offset,
  187 + struct udevice **devp)
  188 +{
  189 + uint pid = offset >> PCR_PORTID_SHIFT;
  190 + struct udevice *p2sb, *dev;
  191 + int ret;
  192 +
  193 + ret = sandbox_pci_get_client(emul, &p2sb);
  194 + if (ret)
  195 + return log_msg_ret("No client", ret);
  196 +
  197 + device_foreach_child(dev, p2sb) {
  198 + struct p2sb_child_platdata *pplat =
  199 + dev_get_parent_platdata(dev);
  200 +
  201 + log_debug(" - child %s, pid %d, want %d\n", dev->name,
  202 + pplat->pid, pid);
  203 + if (pid == pplat->pid) {
  204 + *devp = dev;
  205 + return 0;
  206 + }
  207 + }
  208 +
  209 + return -ENOENT;
  210 +}
  211 +
  212 +static int sandbox_p2sb_emul_map_physmem(struct udevice *dev,
  213 + phys_addr_t addr, unsigned long *lenp,
  214 + void **ptrp)
  215 +{
  216 + struct p2sb_emul_priv *priv = dev_get_priv(dev);
  217 + struct udevice *child;
  218 + unsigned int offset;
  219 + int barnum;
  220 + int ret;
  221 +
  222 + log_debug("map %x: ", (uint)addr);
  223 + ret = sandbox_p2sb_emul_find_bar(dev, addr, &barnum, &offset);
  224 + if (ret)
  225 + return log_msg_ret("Cannot find bar", ret);
  226 + log_debug("bar %d, offset %x\n", barnum, offset);
  227 +
  228 + if (barnum != 0)
  229 + return log_msg_ret("Unknown BAR", -EINVAL);
  230 +
  231 + ret = find_p2sb_channel(dev, offset, &child);
  232 + if (ret)
  233 + return log_msg_ret("Cannot find channel", ret);
  234 +
  235 + offset &= ((1 << PCR_PORTID_SHIFT) - 1);
  236 + ret = axi_read(child, offset, priv->regs, AXI_SIZE_32);
  237 + if (ret)
  238 + return log_msg_ret("Child read failed", ret);
  239 + *ptrp = priv->regs + (offset & 3);
  240 + *lenp = 4;
  241 +
  242 + return 0;
  243 +}
  244 +
  245 +static struct dm_pci_emul_ops sandbox_p2sb_emul_emul_ops = {
  246 + .read_config = sandbox_p2sb_emul_read_config,
  247 + .write_config = sandbox_p2sb_emul_write_config,
  248 + .read_io = sandbox_p2sb_emul_read_io,
  249 + .write_io = sandbox_p2sb_emul_write_io,
  250 + .map_physmem = sandbox_p2sb_emul_map_physmem,
  251 +};
  252 +
  253 +static const struct udevice_id sandbox_p2sb_emul_ids[] = {
  254 + { .compatible = "sandbox,p2sb-emul" },
  255 + { }
  256 +};
  257 +
  258 +U_BOOT_DRIVER(sandbox_p2sb_emul_emul) = {
  259 + .name = "sandbox_p2sb_emul_emul",
  260 + .id = UCLASS_PCI_EMUL,
  261 + .of_match = sandbox_p2sb_emul_ids,
  262 + .ops = &sandbox_p2sb_emul_emul_ops,
  263 + .priv_auto_alloc_size = sizeof(struct p2sb_emul_priv),
  264 + .platdata_auto_alloc_size = sizeof(struct p2sb_emul_platdata),
  265 +};
  266 +
  267 +static struct pci_device_id sandbox_p2sb_emul_supported[] = {
  268 + { PCI_VDEVICE(SANDBOX, SANDBOX_PCI_PMC_EMUL_ID) },
  269 + {},
  270 +};
  271 +
  272 +U_BOOT_PCI_DEVICE(sandbox_p2sb_emul_emul, sandbox_p2sb_emul_supported);
drivers/misc/p2sb_sandbox.c
  1 +// SPDX-License-Identifier: GPL-2.0
  2 +/*
  3 + * Sandbox P2SB for testing
  4 + *
  5 + * Copyright 2019 Google LLC
  6 + */
  7 +
  8 +#define LOG_CATEGORY UCLASS_P2SB
  9 +
  10 +#include <common.h>
  11 +#include <dm.h>
  12 +#include <asm/io.h>
  13 +#include <p2sb.h>
  14 +
  15 +struct sandbox_p2sb_priv {
  16 + ulong base;
  17 +};
  18 +
  19 +static int sandbox_p2sb_probe(struct udevice *dev)
  20 +{
  21 + struct p2sb_uc_priv *upriv = dev_get_uclass_priv(dev);
  22 +
  23 + upriv->mmio_base = dm_pci_read_bar32(dev, 0);
  24 +
  25 + return 0;
  26 +}
  27 +
  28 +static const struct udevice_id sandbox_p2sb_ids[] = {
  29 + { .compatible = "sandbox,p2sb" },
  30 + { }
  31 +};
  32 +
  33 +U_BOOT_DRIVER(p2sb_sandbox) = {
  34 + .name = "p2sb_sandbox",
  35 + .id = UCLASS_P2SB,
  36 + .of_match = sandbox_p2sb_ids,
  37 + .probe = sandbox_p2sb_probe,
  38 + .priv_auto_alloc_size = sizeof(struct sandbox_p2sb_priv),
  39 +};
drivers/misc/sandbox_adder.c
  1 +// SPDX-License-Identifier: GPL-2.0
  2 +/*
  3 + * Sandbox adder for p2sb testing
  4 + *
  5 + * Copyright 2019 Google LLC
  6 + */
  7 +
  8 +#define LOG_CATEGORY UCLASS_MISC
  9 +
  10 +#include <common.h>
  11 +#include <axi.h>
  12 +#include <dm.h>
  13 +#include <misc.h>
  14 +#include <p2sb.h>
  15 +#include <asm/io.h>
  16 +
  17 +struct sandbox_adder_priv {
  18 + ulong base;
  19 +};
  20 +
  21 +int sandbox_adder_read(struct udevice *dev, ulong address, void *data,
  22 + enum axi_size_t size)
  23 +{
  24 + struct p2sb_child_platdata *pplat = dev_get_parent_platdata(dev);
  25 + u32 *val = data;
  26 +
  27 + *val = pplat->pid << 24 | address;
  28 +
  29 + return 0;
  30 +}
  31 +
  32 +int sandbox_adder_write(struct udevice *dev, ulong address, void *data,
  33 + enum axi_size_t size)
  34 +{
  35 + return 0;
  36 +}
  37 +
  38 +static int sandbox_adder_probe(struct udevice *dev)
  39 +{
  40 + return 0;
  41 +}
  42 +
  43 +static struct axi_ops sandbox_adder_ops = {
  44 + .read = sandbox_adder_read,
  45 + .write = sandbox_adder_write,
  46 +};
  47 +
  48 +static const struct udevice_id sandbox_adder_ids[] = {
  49 + { .compatible = "sandbox,adder" },
  50 + { }
  51 +};
  52 +
  53 +U_BOOT_DRIVER(adder_sandbox) = {
  54 + .name = "sandbox_adder",
  55 + .id = UCLASS_AXI,
  56 + .of_match = sandbox_adder_ids,
  57 + .probe = sandbox_adder_probe,
  58 + .ops = &sandbox_adder_ops,
  59 + .priv_auto_alloc_size = sizeof(struct sandbox_adder_priv),
  60 +};
... ... @@ -32,6 +32,7 @@
32 32 obj-$(CONFIG_OSD) += osd.o
33 33 obj-$(CONFIG_DM_VIDEO) += panel.o
34 34 obj-$(CONFIG_DM_PCI) += pci.o
  35 +obj-$(CONFIG_P2SB) += p2sb.o
35 36 obj-$(CONFIG_PCI_ENDPOINT) += pci_ep.o
36 37 obj-$(CONFIG_PCH) += pch.o
37 38 obj-$(CONFIG_PHY) += phy.o
  1 +// SPDX-License-Identifier: GPL-2.0+
  2 +/*
  3 + * Test for Primary-to-Sideband bus (P2SB)
  4 + *
  5 + * Copyright 2019 Google LLC
  6 + */
  7 +
  8 +#include <common.h>
  9 +#include <dm.h>
  10 +#include <p2sb.h>
  11 +#include <asm/test.h>
  12 +#include <dm/test.h>
  13 +#include <test/ut.h>
  14 +
  15 +/* Base test of the PMC uclass */
  16 +static int dm_test_p2sb_base(struct unit_test_state *uts)
  17 +{
  18 + struct udevice *dev;
  19 +
  20 + sandbox_set_enable_memio(true);
  21 + ut_assertok(uclass_get_device_by_name(UCLASS_AXI, "adder", &dev));
  22 + ut_asserteq(0x03000004, pcr_read32(dev, 4));
  23 + ut_asserteq(0x300, pcr_read16(dev, 6));
  24 + ut_asserteq(4, pcr_read8(dev, 4));
  25 +
  26 + return 0;
  27 +}
  28 +DM_TEST(dm_test_p2sb_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);