Commit 3e17ffbb44cd24c53504179ff51a835502b183ed
Committed by
Bin Meng
1 parent
89694de514
Exists in
smarc_8mq_lf_v2020.04
and in
9 other branches
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
- arch/sandbox/include/asm/test.h
- configs/sandbox64_defconfig
- configs/sandbox_defconfig
- configs/sandbox_flattree_defconfig
- configs/sandbox_spl_defconfig
- configs/tools-only_defconfig
- drivers/misc/Makefile
- drivers/misc/p2sb_emul.c
- drivers/misc/p2sb_sandbox.c
- drivers/misc/sandbox_adder.c
- test/dm/Makefile
- test/dm/p2sb.c
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
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
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 | +}; |
test/dm/Makefile
test/dm/p2sb.c
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); |