xref: /aosp_15_r20/external/coreboot/payloads/libpayload/drivers/pci_ops.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /*
2  *
3  * Copyright (C) 2008 Advanced Micro Devices, Inc.
4  * Copyright (C) 2008 coresystems GmbH
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include <libpayload.h>
31 #include <pci.h>
32 
find_on_bus(int bus,unsigned short vid,unsigned short did,pcidev_t * dev)33 static int find_on_bus(int bus, unsigned short vid, unsigned short did,
34 		       pcidev_t * dev)
35 {
36 	int devfn;
37 	u32 val;
38 	unsigned char hdr;
39 
40 	for (devfn = 0; devfn < 0x100; devfn++) {
41 		int func = devfn & 0x7;
42 		int slot = (devfn >> 3) & 0x1f;
43 
44 		val = pci_read_config32(PCI_DEV(bus, slot, func),
45 					REG_VENDOR_ID);
46 
47 		if (val == 0xffffffff || val == 0x00000000 ||
48 		    val == 0x0000ffff || val == 0xffff0000)
49 			continue;
50 
51 		if (val == ((did << 16) | vid)) {
52 			*dev = PCI_DEV(bus, slot, func);
53 			return 1;
54 		}
55 
56 		hdr = pci_read_config8(PCI_DEV(bus, slot, func),
57 				       REG_HEADER_TYPE);
58 		hdr &= 0x7F;
59 
60 		if (hdr == HEADER_TYPE_BRIDGE || hdr == HEADER_TYPE_CARDBUS) {
61 			unsigned int busses;
62 			busses = pci_read_config32(PCI_DEV(bus, slot, func),
63 						   REG_PRIMARY_BUS);
64 			busses = (busses >> 8) & 0xFF;
65 
66 			/* Avoid recursion if the new bus is the same as
67 			 * the old bus (insert lame The Who joke here) */
68 
69 			if ((busses != bus) &&
70 			    find_on_bus(busses, vid, did, dev))
71 				return 1;
72 		}
73 	}
74 
75 	return 0;
76 }
77 
pci_find_device(u16 vid,u16 did,pcidev_t * dev)78 int pci_find_device(u16 vid, u16 did, pcidev_t * dev)
79 {
80 	return find_on_bus(0, vid, did, dev);
81 }
82 
pci_read_resource(pcidev_t dev,int bar)83 u32 pci_read_resource(pcidev_t dev, int bar)
84 {
85 	return pci_read_config32(dev, 0x10 + (bar * 4));
86 }
87 
pci_set_bus_master(pcidev_t dev)88 void pci_set_bus_master(pcidev_t dev)
89 {
90 	u16 val = pci_read_config16(dev, REG_COMMAND);
91 	val |= REG_COMMAND_BM;
92 	pci_write_config16(dev, REG_COMMAND, val);
93 }
94