xref: /openbmc/u-boot/test/dm/pci.c (revision 1d6edcbf)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2d3b7ff14SSimon Glass /*
3d3b7ff14SSimon Glass  * Copyright (C) 2015 Google, Inc
4d3b7ff14SSimon Glass  */
5d3b7ff14SSimon Glass 
6d3b7ff14SSimon Glass #include <common.h>
7d3b7ff14SSimon Glass #include <dm.h>
8d3b7ff14SSimon Glass #include <asm/io.h>
93839b4e8SBin Meng #include <asm/test.h>
10d3b7ff14SSimon Glass #include <dm/test.h>
11e721b882SJoe Hershberger #include <test/ut.h>
12d3b7ff14SSimon Glass 
13d3b7ff14SSimon Glass /* Test that sandbox PCI works correctly */
dm_test_pci_base(struct unit_test_state * uts)14e721b882SJoe Hershberger static int dm_test_pci_base(struct unit_test_state *uts)
15d3b7ff14SSimon Glass {
16d3b7ff14SSimon Glass 	struct udevice *bus;
17d3b7ff14SSimon Glass 
18d3b7ff14SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_PCI, 0, &bus));
19d3b7ff14SSimon Glass 
20d3b7ff14SSimon Glass 	return 0;
21d3b7ff14SSimon Glass }
22d3b7ff14SSimon Glass DM_TEST(dm_test_pci_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
23d3b7ff14SSimon Glass 
242db7f2b7SBin Meng /* Test that sandbox PCI bus numbering and device works correctly */
dm_test_pci_busdev(struct unit_test_state * uts)252db7f2b7SBin Meng static int dm_test_pci_busdev(struct unit_test_state *uts)
262bb02e4fSSimon Glass {
272bb02e4fSSimon Glass 	struct udevice *bus;
283839b4e8SBin Meng 	struct udevice *swap;
293839b4e8SBin Meng 	u16 vendor, device;
302bb02e4fSSimon Glass 
31dee4d752SBin Meng 	/* Test bus#0 and its devices */
322bb02e4fSSimon Glass 	ut_assertok(uclass_get_device_by_seq(UCLASS_PCI, 0, &bus));
332bb02e4fSSimon Glass 
342db7f2b7SBin Meng 	ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x00, 0), &swap));
353839b4e8SBin Meng 	vendor = 0;
363839b4e8SBin Meng 	ut_assertok(dm_pci_read_config16(swap, PCI_VENDOR_ID, &vendor));
373839b4e8SBin Meng 	ut_asserteq(SANDBOX_PCI_VENDOR_ID, vendor);
382db7f2b7SBin Meng 	ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap));
393839b4e8SBin Meng 	device = 0;
403839b4e8SBin Meng 	ut_assertok(dm_pci_read_config16(swap, PCI_DEVICE_ID, &device));
413839b4e8SBin Meng 	ut_asserteq(SANDBOX_PCI_DEVICE_ID, device);
422db7f2b7SBin Meng 
43dee4d752SBin Meng 	/* Test bus#1 and its devices */
44dee4d752SBin Meng 	ut_assertok(uclass_get_device_by_seq(UCLASS_PCI, 1, &bus));
45dee4d752SBin Meng 
46dee4d752SBin Meng 	ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(1, 0x08, 0), &swap));
473839b4e8SBin Meng 	vendor = 0;
483839b4e8SBin Meng 	ut_assertok(dm_pci_read_config16(swap, PCI_VENDOR_ID, &vendor));
493839b4e8SBin Meng 	ut_asserteq(SANDBOX_PCI_VENDOR_ID, vendor);
50dee4d752SBin Meng 	ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(1, 0x0c, 0), &swap));
513839b4e8SBin Meng 	device = 0;
523839b4e8SBin Meng 	ut_assertok(dm_pci_read_config16(swap, PCI_DEVICE_ID, &device));
533839b4e8SBin Meng 	ut_asserteq(SANDBOX_PCI_DEVICE_ID, device);
54dee4d752SBin Meng 
552bb02e4fSSimon Glass 	return 0;
562bb02e4fSSimon Glass }
572db7f2b7SBin Meng DM_TEST(dm_test_pci_busdev, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
582bb02e4fSSimon Glass 
59d3b7ff14SSimon Glass /* Test that we can use the swapcase device correctly */
dm_test_pci_swapcase(struct unit_test_state * uts)60e721b882SJoe Hershberger static int dm_test_pci_swapcase(struct unit_test_state *uts)
61d3b7ff14SSimon Glass {
62dd4808f9SBin Meng 	struct udevice *swap;
63d3b7ff14SSimon Glass 	ulong io_addr, mem_addr;
64d3b7ff14SSimon Glass 	char *ptr;
65d3b7ff14SSimon Glass 
662db7f2b7SBin Meng 	/* Check that asking for the device 0 automatically fires up PCI */
672db7f2b7SBin Meng 	ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x00, 0), &swap));
682db7f2b7SBin Meng 
692db7f2b7SBin Meng 	/* First test I/O */
702db7f2b7SBin Meng 	io_addr = dm_pci_read_bar32(swap, 0);
712db7f2b7SBin Meng 	outb(2, io_addr);
722db7f2b7SBin Meng 	ut_asserteq(2, inb(io_addr));
732db7f2b7SBin Meng 
742db7f2b7SBin Meng 	/*
752db7f2b7SBin Meng 	 * Now test memory mapping - note we must unmap and remap to cause
762db7f2b7SBin Meng 	 * the swapcase emulation to see our data and response.
772db7f2b7SBin Meng 	 */
782db7f2b7SBin Meng 	mem_addr = dm_pci_read_bar32(swap, 1);
792db7f2b7SBin Meng 	ptr = map_sysmem(mem_addr, 20);
802db7f2b7SBin Meng 	strcpy(ptr, "This is a TesT");
812db7f2b7SBin Meng 	unmap_sysmem(ptr);
822db7f2b7SBin Meng 
832db7f2b7SBin Meng 	ptr = map_sysmem(mem_addr, 20);
842db7f2b7SBin Meng 	ut_asserteq_str("tHIS IS A tESt", ptr);
852db7f2b7SBin Meng 	unmap_sysmem(ptr);
862db7f2b7SBin Meng 
872db7f2b7SBin Meng 	/* Check that asking for the device 1 automatically fires up PCI */
88c0322412SSimon Glass 	ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap));
89d3b7ff14SSimon Glass 
90d3b7ff14SSimon Glass 	/* First test I/O */
91c0322412SSimon Glass 	io_addr = dm_pci_read_bar32(swap, 0);
92d3b7ff14SSimon Glass 	outb(2, io_addr);
93d3b7ff14SSimon Glass 	ut_asserteq(2, inb(io_addr));
94d3b7ff14SSimon Glass 
95d3b7ff14SSimon Glass 	/*
96d3b7ff14SSimon Glass 	 * Now test memory mapping - note we must unmap and remap to cause
97d3b7ff14SSimon Glass 	 * the swapcase emulation to see our data and response.
98d3b7ff14SSimon Glass 	 */
99c0322412SSimon Glass 	mem_addr = dm_pci_read_bar32(swap, 1);
100d3b7ff14SSimon Glass 	ptr = map_sysmem(mem_addr, 20);
101d3b7ff14SSimon Glass 	strcpy(ptr, "This is a TesT");
102d3b7ff14SSimon Glass 	unmap_sysmem(ptr);
103d3b7ff14SSimon Glass 
104d3b7ff14SSimon Glass 	ptr = map_sysmem(mem_addr, 20);
105d3b7ff14SSimon Glass 	ut_asserteq_str("tHIS IS A tESt", ptr);
106d3b7ff14SSimon Glass 	unmap_sysmem(ptr);
107d3b7ff14SSimon Glass 
108d3b7ff14SSimon Glass 	return 0;
109d3b7ff14SSimon Glass }
110d3b7ff14SSimon Glass DM_TEST(dm_test_pci_swapcase, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
11182b31043SBin Meng 
11282b31043SBin Meng /* Test that we can dynamically bind the device driver correctly */
dm_test_pci_drvdata(struct unit_test_state * uts)11382b31043SBin Meng static int dm_test_pci_drvdata(struct unit_test_state *uts)
11482b31043SBin Meng {
11582b31043SBin Meng 	struct udevice *bus, *swap;
11682b31043SBin Meng 
11782b31043SBin Meng 	/* Check that asking for the device automatically fires up PCI */
11882b31043SBin Meng 	ut_assertok(uclass_get_device_by_seq(UCLASS_PCI, 1, &bus));
11982b31043SBin Meng 
12082b31043SBin Meng 	ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(1, 0x08, 0), &swap));
12182b31043SBin Meng 	ut_asserteq(SWAP_CASE_DRV_DATA, swap->driver_data);
12225db3403SMarek Vasut 	ut_assertok(dev_of_valid(swap));
12382b31043SBin Meng 	ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(1, 0x0c, 0), &swap));
12482b31043SBin Meng 	ut_asserteq(SWAP_CASE_DRV_DATA, swap->driver_data);
12525db3403SMarek Vasut 	ut_assertok(dev_of_valid(swap));
12625db3403SMarek Vasut 	ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(1, 0x10, 0), &swap));
12725db3403SMarek Vasut 	ut_asserteq(SWAP_CASE_DRV_DATA, swap->driver_data);
12825db3403SMarek Vasut 	ut_assertok(!dev_of_valid(swap));
12982b31043SBin Meng 
13082b31043SBin Meng 	return 0;
13182b31043SBin Meng }
13282b31043SBin Meng DM_TEST(dm_test_pci_drvdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
1333ed214acSBin Meng 
1343ed214acSBin Meng /* Test that devices on PCI bus#2 can be accessed correctly */
dm_test_pci_mixed(struct unit_test_state * uts)1353ed214acSBin Meng static int dm_test_pci_mixed(struct unit_test_state *uts)
1363ed214acSBin Meng {
1373ed214acSBin Meng 	/* PCI bus#2 has both statically and dynamic declared devices */
1383ed214acSBin Meng 	struct udevice *bus, *swap;
1393ed214acSBin Meng 	u16 vendor, device;
1403ed214acSBin Meng 	ulong io_addr, mem_addr;
1413ed214acSBin Meng 	char *ptr;
1423ed214acSBin Meng 
1433ed214acSBin Meng 	ut_assertok(uclass_get_device_by_seq(UCLASS_PCI, 2, &bus));
1443ed214acSBin Meng 
1453ed214acSBin Meng 	/* Test the dynamic device */
1463ed214acSBin Meng 	ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(2, 0x08, 0), &swap));
1473ed214acSBin Meng 	vendor = 0;
1483ed214acSBin Meng 	ut_assertok(dm_pci_read_config16(swap, PCI_VENDOR_ID, &vendor));
1493ed214acSBin Meng 	ut_asserteq(SANDBOX_PCI_VENDOR_ID, vendor);
1503ed214acSBin Meng 
1513ed214acSBin Meng 	/* First test I/O */
1523ed214acSBin Meng 	io_addr = dm_pci_read_bar32(swap, 0);
1533ed214acSBin Meng 	outb(2, io_addr);
1543ed214acSBin Meng 	ut_asserteq(2, inb(io_addr));
1553ed214acSBin Meng 
1563ed214acSBin Meng 	/*
1573ed214acSBin Meng 	 * Now test memory mapping - note we must unmap and remap to cause
1583ed214acSBin Meng 	 * the swapcase emulation to see our data and response.
1593ed214acSBin Meng 	 */
1603ed214acSBin Meng 	mem_addr = dm_pci_read_bar32(swap, 1);
1613ed214acSBin Meng 	ptr = map_sysmem(mem_addr, 30);
1623ed214acSBin Meng 	strcpy(ptr, "This is a TesT oN dYNAMIc");
1633ed214acSBin Meng 	unmap_sysmem(ptr);
1643ed214acSBin Meng 
1653ed214acSBin Meng 	ptr = map_sysmem(mem_addr, 30);
1663ed214acSBin Meng 	ut_asserteq_str("tHIS IS A tESt On DynamiC", ptr);
1673ed214acSBin Meng 	unmap_sysmem(ptr);
1683ed214acSBin Meng 
1693ed214acSBin Meng 	/* Test the static device */
1703ed214acSBin Meng 	ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(2, 0x1f, 0), &swap));
1713ed214acSBin Meng 	device = 0;
1723ed214acSBin Meng 	ut_assertok(dm_pci_read_config16(swap, PCI_DEVICE_ID, &device));
1733ed214acSBin Meng 	ut_asserteq(SANDBOX_PCI_DEVICE_ID, device);
1743ed214acSBin Meng 
1753ed214acSBin Meng 	/* First test I/O */
1763ed214acSBin Meng 	io_addr = dm_pci_read_bar32(swap, 0);
1773ed214acSBin Meng 	outb(2, io_addr);
1783ed214acSBin Meng 	ut_asserteq(2, inb(io_addr));
1793ed214acSBin Meng 
1803ed214acSBin Meng 	/*
1813ed214acSBin Meng 	 * Now test memory mapping - note we must unmap and remap to cause
1823ed214acSBin Meng 	 * the swapcase emulation to see our data and response.
1833ed214acSBin Meng 	 */
1843ed214acSBin Meng 	mem_addr = dm_pci_read_bar32(swap, 1);
1853ed214acSBin Meng 	ptr = map_sysmem(mem_addr, 30);
1863ed214acSBin Meng 	strcpy(ptr, "This is a TesT oN sTATIc");
1873ed214acSBin Meng 	unmap_sysmem(ptr);
1883ed214acSBin Meng 
1893ed214acSBin Meng 	ptr = map_sysmem(mem_addr, 30);
1903ed214acSBin Meng 	ut_asserteq_str("tHIS IS A tESt On StatiC", ptr);
1913ed214acSBin Meng 	unmap_sysmem(ptr);
1923ed214acSBin Meng 
1933ed214acSBin Meng 	return 0;
1943ed214acSBin Meng }
1953ed214acSBin Meng DM_TEST(dm_test_pci_mixed, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
19695e11069SBin Meng 
19795e11069SBin Meng /* Test looking up PCI capability and extended capability */
dm_test_pci_cap(struct unit_test_state * uts)19895e11069SBin Meng static int dm_test_pci_cap(struct unit_test_state *uts)
19995e11069SBin Meng {
20095e11069SBin Meng 	struct udevice *bus, *swap;
20195e11069SBin Meng 	int cap;
20295e11069SBin Meng 
20395e11069SBin Meng 	ut_assertok(uclass_get_device_by_seq(UCLASS_PCI, 0, &bus));
20495e11069SBin Meng 	ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap));
20595e11069SBin Meng 
20695e11069SBin Meng 	/* look up PCI_CAP_ID_EXP */
20795e11069SBin Meng 	cap = dm_pci_find_capability(swap, PCI_CAP_ID_EXP);
20895e11069SBin Meng 	ut_asserteq(PCI_CAP_ID_EXP_OFFSET, cap);
20995e11069SBin Meng 
21095e11069SBin Meng 	/* look up PCI_CAP_ID_PCIX */
21195e11069SBin Meng 	cap = dm_pci_find_capability(swap, PCI_CAP_ID_PCIX);
21295e11069SBin Meng 	ut_asserteq(0, cap);
21395e11069SBin Meng 
214*7a20614eSBin Meng 	/* look up PCI_CAP_ID_MSIX starting from PCI_CAP_ID_PM_OFFSET */
215*7a20614eSBin Meng 	cap = dm_pci_find_next_capability(swap, PCI_CAP_ID_PM_OFFSET,
216*7a20614eSBin Meng 					  PCI_CAP_ID_MSIX);
217*7a20614eSBin Meng 	ut_asserteq(PCI_CAP_ID_MSIX_OFFSET, cap);
218*7a20614eSBin Meng 
219*7a20614eSBin Meng 	/* look up PCI_CAP_ID_VNDR starting from PCI_CAP_ID_EXP_OFFSET */
220*7a20614eSBin Meng 	cap = dm_pci_find_next_capability(swap, PCI_CAP_ID_EXP_OFFSET,
221*7a20614eSBin Meng 					  PCI_CAP_ID_VNDR);
222*7a20614eSBin Meng 	ut_asserteq(0, cap);
223*7a20614eSBin Meng 
22495e11069SBin Meng 	ut_assertok(uclass_get_device_by_seq(UCLASS_PCI, 1, &bus));
22595e11069SBin Meng 	ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(1, 0x08, 0), &swap));
22695e11069SBin Meng 
22795e11069SBin Meng 	/* look up PCI_EXT_CAP_ID_DSN */
22895e11069SBin Meng 	cap = dm_pci_find_ext_capability(swap, PCI_EXT_CAP_ID_DSN);
22995e11069SBin Meng 	ut_asserteq(PCI_EXT_CAP_ID_DSN_OFFSET, cap);
23095e11069SBin Meng 
23195e11069SBin Meng 	/* look up PCI_EXT_CAP_ID_SRIOV */
23295e11069SBin Meng 	cap = dm_pci_find_ext_capability(swap, PCI_EXT_CAP_ID_SRIOV);
23395e11069SBin Meng 	ut_asserteq(0, cap);
23495e11069SBin Meng 
235*7a20614eSBin Meng 	/* look up PCI_EXT_CAP_ID_DSN starting from PCI_EXT_CAP_ID_ERR_OFFSET */
236*7a20614eSBin Meng 	cap = dm_pci_find_next_ext_capability(swap, PCI_EXT_CAP_ID_ERR_OFFSET,
237*7a20614eSBin Meng 					      PCI_EXT_CAP_ID_DSN);
238*7a20614eSBin Meng 	ut_asserteq(PCI_EXT_CAP_ID_DSN_OFFSET, cap);
239*7a20614eSBin Meng 
240*7a20614eSBin Meng 	/* look up PCI_EXT_CAP_ID_RCRB starting from PCI_EXT_CAP_ID_VC_OFFSET */
241*7a20614eSBin Meng 	cap = dm_pci_find_next_ext_capability(swap, PCI_EXT_CAP_ID_VC_OFFSET,
242*7a20614eSBin Meng 					      PCI_EXT_CAP_ID_RCRB);
243*7a20614eSBin Meng 	ut_asserteq(0, cap);
244*7a20614eSBin Meng 
24595e11069SBin Meng 	return 0;
24695e11069SBin Meng }
24795e11069SBin Meng DM_TEST(dm_test_pci_cap, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
248