xref: /openbmc/u-boot/drivers/pci/pci-uclass.c (revision bdac5e18a80427e1f44413dce78aefece956ffc2)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2ff3e077bSSimon Glass /*
3ff3e077bSSimon Glass  * Copyright (c) 2014 Google, Inc
4ff3e077bSSimon Glass  * Written by Simon Glass <sjg@chromium.org>
5ff3e077bSSimon Glass  */
6ff3e077bSSimon Glass 
7ff3e077bSSimon Glass #include <common.h>
8ff3e077bSSimon Glass #include <dm.h>
9ff3e077bSSimon Glass #include <errno.h>
10ff3e077bSSimon Glass #include <pci.h>
1121d1fe7eSSimon Glass #include <asm/io.h>
12ff3e077bSSimon Glass #include <dm/device-internal.h>
13bf501595SSimon Glass #include <dm/lists.h>
14348b744bSBin Meng #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
15348b744bSBin Meng #include <asm/fsp/fsp_support.h>
16348b744bSBin Meng #endif
175e23b8b4SSimon Glass #include "pci_internal.h"
18ff3e077bSSimon Glass 
19ff3e077bSSimon Glass DECLARE_GLOBAL_DATA_PTR;
20ff3e077bSSimon Glass 
pci_get_bus(int busnum,struct udevice ** busp)21a6eb93b3SSimon Glass int pci_get_bus(int busnum, struct udevice **busp)
22983c6ba2SSimon Glass {
23983c6ba2SSimon Glass 	int ret;
24983c6ba2SSimon Glass 
25983c6ba2SSimon Glass 	ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, busp);
26983c6ba2SSimon Glass 
27983c6ba2SSimon Glass 	/* Since buses may not be numbered yet try a little harder with bus 0 */
28983c6ba2SSimon Glass 	if (ret == -ENODEV) {
293f603cbbSSimon Glass 		ret = uclass_first_device_err(UCLASS_PCI, busp);
30983c6ba2SSimon Glass 		if (ret)
31983c6ba2SSimon Glass 			return ret;
32983c6ba2SSimon Glass 		ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, busp);
33983c6ba2SSimon Glass 	}
34983c6ba2SSimon Glass 
35983c6ba2SSimon Glass 	return ret;
36983c6ba2SSimon Glass }
37983c6ba2SSimon Glass 
pci_get_controller(struct udevice * dev)389f60fb0dSSimon Glass struct udevice *pci_get_controller(struct udevice *dev)
399f60fb0dSSimon Glass {
409f60fb0dSSimon Glass 	while (device_is_on_pci_bus(dev))
419f60fb0dSSimon Glass 		dev = dev->parent;
429f60fb0dSSimon Glass 
439f60fb0dSSimon Glass 	return dev;
449f60fb0dSSimon Glass }
459f60fb0dSSimon Glass 
dm_pci_get_bdf(struct udevice * dev)4621ccce1bSSimon Glass pci_dev_t dm_pci_get_bdf(struct udevice *dev)
474b515e4fSSimon Glass {
484b515e4fSSimon Glass 	struct pci_child_platdata *pplat = dev_get_parent_platdata(dev);
494b515e4fSSimon Glass 	struct udevice *bus = dev->parent;
504b515e4fSSimon Glass 
514b515e4fSSimon Glass 	return PCI_ADD_BUS(bus->seq, pplat->devfn);
524b515e4fSSimon Glass }
534b515e4fSSimon Glass 
54ff3e077bSSimon Glass /**
55ff3e077bSSimon Glass  * pci_get_bus_max() - returns the bus number of the last active bus
56ff3e077bSSimon Glass  *
57ff3e077bSSimon Glass  * @return last bus number, or -1 if no active buses
58ff3e077bSSimon Glass  */
pci_get_bus_max(void)59ff3e077bSSimon Glass static int pci_get_bus_max(void)
60ff3e077bSSimon Glass {
61ff3e077bSSimon Glass 	struct udevice *bus;
62ff3e077bSSimon Glass 	struct uclass *uc;
63ff3e077bSSimon Glass 	int ret = -1;
64ff3e077bSSimon Glass 
65ff3e077bSSimon Glass 	ret = uclass_get(UCLASS_PCI, &uc);
66ff3e077bSSimon Glass 	uclass_foreach_dev(bus, uc) {
67ff3e077bSSimon Glass 		if (bus->seq > ret)
68ff3e077bSSimon Glass 			ret = bus->seq;
69ff3e077bSSimon Glass 	}
70ff3e077bSSimon Glass 
71ff3e077bSSimon Glass 	debug("%s: ret=%d\n", __func__, ret);
72ff3e077bSSimon Glass 
73ff3e077bSSimon Glass 	return ret;
74ff3e077bSSimon Glass }
75ff3e077bSSimon Glass 
pci_last_busno(void)76ff3e077bSSimon Glass int pci_last_busno(void)
77ff3e077bSSimon Glass {
78069155cbSBin Meng 	return pci_get_bus_max();
79ff3e077bSSimon Glass }
80ff3e077bSSimon Glass 
pci_get_ff(enum pci_size_t size)81ff3e077bSSimon Glass int pci_get_ff(enum pci_size_t size)
82ff3e077bSSimon Glass {
83ff3e077bSSimon Glass 	switch (size) {
84ff3e077bSSimon Glass 	case PCI_SIZE_8:
85ff3e077bSSimon Glass 		return 0xff;
86ff3e077bSSimon Glass 	case PCI_SIZE_16:
87ff3e077bSSimon Glass 		return 0xffff;
88ff3e077bSSimon Glass 	default:
89ff3e077bSSimon Glass 		return 0xffffffff;
90ff3e077bSSimon Glass 	}
91ff3e077bSSimon Glass }
92ff3e077bSSimon Glass 
pci_dev_find_ofnode(struct udevice * bus,phys_addr_t bdf,ofnode * rnode)9302e4d38dSMarek Vasut static void pci_dev_find_ofnode(struct udevice *bus, phys_addr_t bdf,
9402e4d38dSMarek Vasut 				ofnode *rnode)
9502e4d38dSMarek Vasut {
9602e4d38dSMarek Vasut 	struct fdt_pci_addr addr;
9702e4d38dSMarek Vasut 	ofnode node;
9802e4d38dSMarek Vasut 	int ret;
9902e4d38dSMarek Vasut 
10002e4d38dSMarek Vasut 	dev_for_each_subnode(node, bus) {
10102e4d38dSMarek Vasut 		ret = ofnode_read_pci_addr(node, FDT_PCI_SPACE_CONFIG, "reg",
10202e4d38dSMarek Vasut 					   &addr);
10302e4d38dSMarek Vasut 		if (ret)
10402e4d38dSMarek Vasut 			continue;
10502e4d38dSMarek Vasut 
10602e4d38dSMarek Vasut 		if (PCI_MASK_BUS(addr.phys_hi) != PCI_MASK_BUS(bdf))
10702e4d38dSMarek Vasut 			continue;
10802e4d38dSMarek Vasut 
10902e4d38dSMarek Vasut 		*rnode = node;
11002e4d38dSMarek Vasut 		break;
11102e4d38dSMarek Vasut 	}
11202e4d38dSMarek Vasut };
11302e4d38dSMarek Vasut 
pci_bus_find_devfn(struct udevice * bus,pci_dev_t find_devfn,struct udevice ** devp)114ff3e077bSSimon Glass int pci_bus_find_devfn(struct udevice *bus, pci_dev_t find_devfn,
115ff3e077bSSimon Glass 		       struct udevice **devp)
116ff3e077bSSimon Glass {
117ff3e077bSSimon Glass 	struct udevice *dev;
118ff3e077bSSimon Glass 
119ff3e077bSSimon Glass 	for (device_find_first_child(bus, &dev);
120ff3e077bSSimon Glass 	     dev;
121ff3e077bSSimon Glass 	     device_find_next_child(&dev)) {
122ff3e077bSSimon Glass 		struct pci_child_platdata *pplat;
123ff3e077bSSimon Glass 
124ff3e077bSSimon Glass 		pplat = dev_get_parent_platdata(dev);
125ff3e077bSSimon Glass 		if (pplat && pplat->devfn == find_devfn) {
126ff3e077bSSimon Glass 			*devp = dev;
127ff3e077bSSimon Glass 			return 0;
128ff3e077bSSimon Glass 		}
129ff3e077bSSimon Glass 	}
130ff3e077bSSimon Glass 
131ff3e077bSSimon Glass 	return -ENODEV;
132ff3e077bSSimon Glass }
133ff3e077bSSimon Glass 
dm_pci_bus_find_bdf(pci_dev_t bdf,struct udevice ** devp)134f3f1faefSSimon Glass int dm_pci_bus_find_bdf(pci_dev_t bdf, struct udevice **devp)
135ff3e077bSSimon Glass {
136ff3e077bSSimon Glass 	struct udevice *bus;
137ff3e077bSSimon Glass 	int ret;
138ff3e077bSSimon Glass 
139983c6ba2SSimon Glass 	ret = pci_get_bus(PCI_BUS(bdf), &bus);
140ff3e077bSSimon Glass 	if (ret)
141ff3e077bSSimon Glass 		return ret;
142ff3e077bSSimon Glass 	return pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), devp);
143ff3e077bSSimon Glass }
144ff3e077bSSimon Glass 
pci_device_matches_ids(struct udevice * dev,struct pci_device_id * ids)145ff3e077bSSimon Glass static int pci_device_matches_ids(struct udevice *dev,
146ff3e077bSSimon Glass 				  struct pci_device_id *ids)
147ff3e077bSSimon Glass {
148ff3e077bSSimon Glass 	struct pci_child_platdata *pplat;
149ff3e077bSSimon Glass 	int i;
150ff3e077bSSimon Glass 
151ff3e077bSSimon Glass 	pplat = dev_get_parent_platdata(dev);
152ff3e077bSSimon Glass 	if (!pplat)
153ff3e077bSSimon Glass 		return -EINVAL;
154ff3e077bSSimon Glass 	for (i = 0; ids[i].vendor != 0; i++) {
155ff3e077bSSimon Glass 		if (pplat->vendor == ids[i].vendor &&
156ff3e077bSSimon Glass 		    pplat->device == ids[i].device)
157ff3e077bSSimon Glass 			return i;
158ff3e077bSSimon Glass 	}
159ff3e077bSSimon Glass 
160ff3e077bSSimon Glass 	return -EINVAL;
161ff3e077bSSimon Glass }
162ff3e077bSSimon Glass 
pci_bus_find_devices(struct udevice * bus,struct pci_device_id * ids,int * indexp,struct udevice ** devp)163ff3e077bSSimon Glass int pci_bus_find_devices(struct udevice *bus, struct pci_device_id *ids,
164ff3e077bSSimon Glass 			 int *indexp, struct udevice **devp)
165ff3e077bSSimon Glass {
166ff3e077bSSimon Glass 	struct udevice *dev;
167ff3e077bSSimon Glass 
168ff3e077bSSimon Glass 	/* Scan all devices on this bus */
169ff3e077bSSimon Glass 	for (device_find_first_child(bus, &dev);
170ff3e077bSSimon Glass 	     dev;
171ff3e077bSSimon Glass 	     device_find_next_child(&dev)) {
172ff3e077bSSimon Glass 		if (pci_device_matches_ids(dev, ids) >= 0) {
173ff3e077bSSimon Glass 			if ((*indexp)-- <= 0) {
174ff3e077bSSimon Glass 				*devp = dev;
175ff3e077bSSimon Glass 				return 0;
176ff3e077bSSimon Glass 			}
177ff3e077bSSimon Glass 		}
178ff3e077bSSimon Glass 	}
179ff3e077bSSimon Glass 
180ff3e077bSSimon Glass 	return -ENODEV;
181ff3e077bSSimon Glass }
182ff3e077bSSimon Glass 
pci_find_device_id(struct pci_device_id * ids,int index,struct udevice ** devp)183ff3e077bSSimon Glass int pci_find_device_id(struct pci_device_id *ids, int index,
184ff3e077bSSimon Glass 		       struct udevice **devp)
185ff3e077bSSimon Glass {
186ff3e077bSSimon Glass 	struct udevice *bus;
187ff3e077bSSimon Glass 
188ff3e077bSSimon Glass 	/* Scan all known buses */
189ff3e077bSSimon Glass 	for (uclass_first_device(UCLASS_PCI, &bus);
190ff3e077bSSimon Glass 	     bus;
191ff3e077bSSimon Glass 	     uclass_next_device(&bus)) {
192ff3e077bSSimon Glass 		if (!pci_bus_find_devices(bus, ids, &index, devp))
193ff3e077bSSimon Glass 			return 0;
194ff3e077bSSimon Glass 	}
195ff3e077bSSimon Glass 	*devp = NULL;
196ff3e077bSSimon Glass 
197ff3e077bSSimon Glass 	return -ENODEV;
198ff3e077bSSimon Glass }
199ff3e077bSSimon Glass 
dm_pci_bus_find_device(struct udevice * bus,unsigned int vendor,unsigned int device,int * indexp,struct udevice ** devp)2005c0bf647SSimon Glass static int dm_pci_bus_find_device(struct udevice *bus, unsigned int vendor,
2015c0bf647SSimon Glass 				  unsigned int device, int *indexp,
2025c0bf647SSimon Glass 				  struct udevice **devp)
2035c0bf647SSimon Glass {
2045c0bf647SSimon Glass 	struct pci_child_platdata *pplat;
2055c0bf647SSimon Glass 	struct udevice *dev;
2065c0bf647SSimon Glass 
2075c0bf647SSimon Glass 	for (device_find_first_child(bus, &dev);
2085c0bf647SSimon Glass 	     dev;
2095c0bf647SSimon Glass 	     device_find_next_child(&dev)) {
2105c0bf647SSimon Glass 		pplat = dev_get_parent_platdata(dev);
2115c0bf647SSimon Glass 		if (pplat->vendor == vendor && pplat->device == device) {
2125c0bf647SSimon Glass 			if (!(*indexp)--) {
2135c0bf647SSimon Glass 				*devp = dev;
2145c0bf647SSimon Glass 				return 0;
2155c0bf647SSimon Glass 			}
2165c0bf647SSimon Glass 		}
2175c0bf647SSimon Glass 	}
2185c0bf647SSimon Glass 
2195c0bf647SSimon Glass 	return -ENODEV;
2205c0bf647SSimon Glass }
2215c0bf647SSimon Glass 
dm_pci_find_device(unsigned int vendor,unsigned int device,int index,struct udevice ** devp)2225c0bf647SSimon Glass int dm_pci_find_device(unsigned int vendor, unsigned int device, int index,
2235c0bf647SSimon Glass 		       struct udevice **devp)
2245c0bf647SSimon Glass {
2255c0bf647SSimon Glass 	struct udevice *bus;
2265c0bf647SSimon Glass 
2275c0bf647SSimon Glass 	/* Scan all known buses */
2285c0bf647SSimon Glass 	for (uclass_first_device(UCLASS_PCI, &bus);
2295c0bf647SSimon Glass 	     bus;
2305c0bf647SSimon Glass 	     uclass_next_device(&bus)) {
2315c0bf647SSimon Glass 		if (!dm_pci_bus_find_device(bus, vendor, device, &index, devp))
2325c0bf647SSimon Glass 			return device_probe(*devp);
2335c0bf647SSimon Glass 	}
2345c0bf647SSimon Glass 	*devp = NULL;
2355c0bf647SSimon Glass 
2365c0bf647SSimon Glass 	return -ENODEV;
2375c0bf647SSimon Glass }
2385c0bf647SSimon Glass 
dm_pci_find_class(uint find_class,int index,struct udevice ** devp)239a0eb8356SSimon Glass int dm_pci_find_class(uint find_class, int index, struct udevice **devp)
240a0eb8356SSimon Glass {
241a0eb8356SSimon Glass 	struct udevice *dev;
242a0eb8356SSimon Glass 
243a0eb8356SSimon Glass 	/* Scan all known buses */
244a0eb8356SSimon Glass 	for (pci_find_first_device(&dev);
245a0eb8356SSimon Glass 	     dev;
246a0eb8356SSimon Glass 	     pci_find_next_device(&dev)) {
247a0eb8356SSimon Glass 		struct pci_child_platdata *pplat = dev_get_parent_platdata(dev);
248a0eb8356SSimon Glass 
249a0eb8356SSimon Glass 		if (pplat->class == find_class && !index--) {
250a0eb8356SSimon Glass 			*devp = dev;
251a0eb8356SSimon Glass 			return device_probe(*devp);
252a0eb8356SSimon Glass 		}
253a0eb8356SSimon Glass 	}
254a0eb8356SSimon Glass 	*devp = NULL;
255a0eb8356SSimon Glass 
256a0eb8356SSimon Glass 	return -ENODEV;
257a0eb8356SSimon Glass }
258a0eb8356SSimon Glass 
pci_bus_write_config(struct udevice * bus,pci_dev_t bdf,int offset,unsigned long value,enum pci_size_t size)259ff3e077bSSimon Glass int pci_bus_write_config(struct udevice *bus, pci_dev_t bdf, int offset,
260ff3e077bSSimon Glass 			 unsigned long value, enum pci_size_t size)
261ff3e077bSSimon Glass {
262ff3e077bSSimon Glass 	struct dm_pci_ops *ops;
263ff3e077bSSimon Glass 
264ff3e077bSSimon Glass 	ops = pci_get_ops(bus);
265ff3e077bSSimon Glass 	if (!ops->write_config)
266ff3e077bSSimon Glass 		return -ENOSYS;
267ff3e077bSSimon Glass 	return ops->write_config(bus, bdf, offset, value, size);
268ff3e077bSSimon Glass }
269ff3e077bSSimon Glass 
pci_bus_clrset_config32(struct udevice * bus,pci_dev_t bdf,int offset,u32 clr,u32 set)270319dba1fSSimon Glass int pci_bus_clrset_config32(struct udevice *bus, pci_dev_t bdf, int offset,
271319dba1fSSimon Glass 			    u32 clr, u32 set)
272319dba1fSSimon Glass {
273319dba1fSSimon Glass 	ulong val;
274319dba1fSSimon Glass 	int ret;
275319dba1fSSimon Glass 
276319dba1fSSimon Glass 	ret = pci_bus_read_config(bus, bdf, offset, &val, PCI_SIZE_32);
277319dba1fSSimon Glass 	if (ret)
278319dba1fSSimon Glass 		return ret;
279319dba1fSSimon Glass 	val &= ~clr;
280319dba1fSSimon Glass 	val |= set;
281319dba1fSSimon Glass 
282319dba1fSSimon Glass 	return pci_bus_write_config(bus, bdf, offset, val, PCI_SIZE_32);
283319dba1fSSimon Glass }
284319dba1fSSimon Glass 
pci_write_config(pci_dev_t bdf,int offset,unsigned long value,enum pci_size_t size)285ff3e077bSSimon Glass int pci_write_config(pci_dev_t bdf, int offset, unsigned long value,
286ff3e077bSSimon Glass 		     enum pci_size_t size)
287ff3e077bSSimon Glass {
288ff3e077bSSimon Glass 	struct udevice *bus;
289ff3e077bSSimon Glass 	int ret;
290ff3e077bSSimon Glass 
291983c6ba2SSimon Glass 	ret = pci_get_bus(PCI_BUS(bdf), &bus);
292ff3e077bSSimon Glass 	if (ret)
293ff3e077bSSimon Glass 		return ret;
294ff3e077bSSimon Glass 
2954d8615cbSBin Meng 	return pci_bus_write_config(bus, bdf, offset, value, size);
296ff3e077bSSimon Glass }
297ff3e077bSSimon Glass 
dm_pci_write_config(struct udevice * dev,int offset,unsigned long value,enum pci_size_t size)29866afb4edSSimon Glass int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value,
29966afb4edSSimon Glass 			enum pci_size_t size)
30066afb4edSSimon Glass {
30166afb4edSSimon Glass 	struct udevice *bus;
30266afb4edSSimon Glass 
3031e0f2263SBin Meng 	for (bus = dev; device_is_on_pci_bus(bus);)
30466afb4edSSimon Glass 		bus = bus->parent;
30521ccce1bSSimon Glass 	return pci_bus_write_config(bus, dm_pci_get_bdf(dev), offset, value,
30621ccce1bSSimon Glass 				    size);
30766afb4edSSimon Glass }
30866afb4edSSimon Glass 
pci_write_config32(pci_dev_t bdf,int offset,u32 value)309ff3e077bSSimon Glass int pci_write_config32(pci_dev_t bdf, int offset, u32 value)
310ff3e077bSSimon Glass {
311ff3e077bSSimon Glass 	return pci_write_config(bdf, offset, value, PCI_SIZE_32);
312ff3e077bSSimon Glass }
313ff3e077bSSimon Glass 
pci_write_config16(pci_dev_t bdf,int offset,u16 value)314ff3e077bSSimon Glass int pci_write_config16(pci_dev_t bdf, int offset, u16 value)
315ff3e077bSSimon Glass {
316ff3e077bSSimon Glass 	return pci_write_config(bdf, offset, value, PCI_SIZE_16);
317ff3e077bSSimon Glass }
318ff3e077bSSimon Glass 
pci_write_config8(pci_dev_t bdf,int offset,u8 value)319ff3e077bSSimon Glass int pci_write_config8(pci_dev_t bdf, int offset, u8 value)
320ff3e077bSSimon Glass {
321ff3e077bSSimon Glass 	return pci_write_config(bdf, offset, value, PCI_SIZE_8);
322ff3e077bSSimon Glass }
323ff3e077bSSimon Glass 
dm_pci_write_config8(struct udevice * dev,int offset,u8 value)32466afb4edSSimon Glass int dm_pci_write_config8(struct udevice *dev, int offset, u8 value)
32566afb4edSSimon Glass {
32666afb4edSSimon Glass 	return dm_pci_write_config(dev, offset, value, PCI_SIZE_8);
32766afb4edSSimon Glass }
32866afb4edSSimon Glass 
dm_pci_write_config16(struct udevice * dev,int offset,u16 value)32966afb4edSSimon Glass int dm_pci_write_config16(struct udevice *dev, int offset, u16 value)
33066afb4edSSimon Glass {
33166afb4edSSimon Glass 	return dm_pci_write_config(dev, offset, value, PCI_SIZE_16);
33266afb4edSSimon Glass }
33366afb4edSSimon Glass 
dm_pci_write_config32(struct udevice * dev,int offset,u32 value)33466afb4edSSimon Glass int dm_pci_write_config32(struct udevice *dev, int offset, u32 value)
33566afb4edSSimon Glass {
33666afb4edSSimon Glass 	return dm_pci_write_config(dev, offset, value, PCI_SIZE_32);
33766afb4edSSimon Glass }
33866afb4edSSimon Glass 
pci_bus_read_config(struct udevice * bus,pci_dev_t bdf,int offset,unsigned long * valuep,enum pci_size_t size)339ff3e077bSSimon Glass int pci_bus_read_config(struct udevice *bus, pci_dev_t bdf, int offset,
340ff3e077bSSimon Glass 			unsigned long *valuep, enum pci_size_t size)
341ff3e077bSSimon Glass {
342ff3e077bSSimon Glass 	struct dm_pci_ops *ops;
343ff3e077bSSimon Glass 
344ff3e077bSSimon Glass 	ops = pci_get_ops(bus);
345ff3e077bSSimon Glass 	if (!ops->read_config)
346ff3e077bSSimon Glass 		return -ENOSYS;
347ff3e077bSSimon Glass 	return ops->read_config(bus, bdf, offset, valuep, size);
348ff3e077bSSimon Glass }
349ff3e077bSSimon Glass 
pci_read_config(pci_dev_t bdf,int offset,unsigned long * valuep,enum pci_size_t size)350ff3e077bSSimon Glass int pci_read_config(pci_dev_t bdf, int offset, unsigned long *valuep,
351ff3e077bSSimon Glass 		    enum pci_size_t size)
352ff3e077bSSimon Glass {
353ff3e077bSSimon Glass 	struct udevice *bus;
354ff3e077bSSimon Glass 	int ret;
355ff3e077bSSimon Glass 
356983c6ba2SSimon Glass 	ret = pci_get_bus(PCI_BUS(bdf), &bus);
357ff3e077bSSimon Glass 	if (ret)
358ff3e077bSSimon Glass 		return ret;
359ff3e077bSSimon Glass 
3604d8615cbSBin Meng 	return pci_bus_read_config(bus, bdf, offset, valuep, size);
361ff3e077bSSimon Glass }
362ff3e077bSSimon Glass 
dm_pci_read_config(struct udevice * dev,int offset,unsigned long * valuep,enum pci_size_t size)36366afb4edSSimon Glass int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep,
36466afb4edSSimon Glass 		       enum pci_size_t size)
36566afb4edSSimon Glass {
36666afb4edSSimon Glass 	struct udevice *bus;
36766afb4edSSimon Glass 
3681e0f2263SBin Meng 	for (bus = dev; device_is_on_pci_bus(bus);)
36966afb4edSSimon Glass 		bus = bus->parent;
37021ccce1bSSimon Glass 	return pci_bus_read_config(bus, dm_pci_get_bdf(dev), offset, valuep,
37166afb4edSSimon Glass 				   size);
37266afb4edSSimon Glass }
37366afb4edSSimon Glass 
pci_read_config32(pci_dev_t bdf,int offset,u32 * valuep)374ff3e077bSSimon Glass int pci_read_config32(pci_dev_t bdf, int offset, u32 *valuep)
375ff3e077bSSimon Glass {
376ff3e077bSSimon Glass 	unsigned long value;
377ff3e077bSSimon Glass 	int ret;
378ff3e077bSSimon Glass 
379ff3e077bSSimon Glass 	ret = pci_read_config(bdf, offset, &value, PCI_SIZE_32);
380ff3e077bSSimon Glass 	if (ret)
381ff3e077bSSimon Glass 		return ret;
382ff3e077bSSimon Glass 	*valuep = value;
383ff3e077bSSimon Glass 
384ff3e077bSSimon Glass 	return 0;
385ff3e077bSSimon Glass }
386ff3e077bSSimon Glass 
pci_read_config16(pci_dev_t bdf,int offset,u16 * valuep)387ff3e077bSSimon Glass int pci_read_config16(pci_dev_t bdf, int offset, u16 *valuep)
388ff3e077bSSimon Glass {
389ff3e077bSSimon Glass 	unsigned long value;
390ff3e077bSSimon Glass 	int ret;
391ff3e077bSSimon Glass 
392ff3e077bSSimon Glass 	ret = pci_read_config(bdf, offset, &value, PCI_SIZE_16);
393ff3e077bSSimon Glass 	if (ret)
394ff3e077bSSimon Glass 		return ret;
395ff3e077bSSimon Glass 	*valuep = value;
396ff3e077bSSimon Glass 
397ff3e077bSSimon Glass 	return 0;
398ff3e077bSSimon Glass }
399ff3e077bSSimon Glass 
pci_read_config8(pci_dev_t bdf,int offset,u8 * valuep)400ff3e077bSSimon Glass int pci_read_config8(pci_dev_t bdf, int offset, u8 *valuep)
401ff3e077bSSimon Glass {
402ff3e077bSSimon Glass 	unsigned long value;
403ff3e077bSSimon Glass 	int ret;
404ff3e077bSSimon Glass 
405ff3e077bSSimon Glass 	ret = pci_read_config(bdf, offset, &value, PCI_SIZE_8);
406ff3e077bSSimon Glass 	if (ret)
407ff3e077bSSimon Glass 		return ret;
408ff3e077bSSimon Glass 	*valuep = value;
409ff3e077bSSimon Glass 
410ff3e077bSSimon Glass 	return 0;
411ff3e077bSSimon Glass }
412ff3e077bSSimon Glass 
dm_pci_read_config8(struct udevice * dev,int offset,u8 * valuep)41366afb4edSSimon Glass int dm_pci_read_config8(struct udevice *dev, int offset, u8 *valuep)
41466afb4edSSimon Glass {
41566afb4edSSimon Glass 	unsigned long value;
41666afb4edSSimon Glass 	int ret;
41766afb4edSSimon Glass 
41866afb4edSSimon Glass 	ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_8);
41966afb4edSSimon Glass 	if (ret)
42066afb4edSSimon Glass 		return ret;
42166afb4edSSimon Glass 	*valuep = value;
42266afb4edSSimon Glass 
42366afb4edSSimon Glass 	return 0;
42466afb4edSSimon Glass }
42566afb4edSSimon Glass 
dm_pci_read_config16(struct udevice * dev,int offset,u16 * valuep)42666afb4edSSimon Glass int dm_pci_read_config16(struct udevice *dev, int offset, u16 *valuep)
42766afb4edSSimon Glass {
42866afb4edSSimon Glass 	unsigned long value;
42966afb4edSSimon Glass 	int ret;
43066afb4edSSimon Glass 
43166afb4edSSimon Glass 	ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_16);
43266afb4edSSimon Glass 	if (ret)
43366afb4edSSimon Glass 		return ret;
43466afb4edSSimon Glass 	*valuep = value;
43566afb4edSSimon Glass 
43666afb4edSSimon Glass 	return 0;
43766afb4edSSimon Glass }
43866afb4edSSimon Glass 
dm_pci_read_config32(struct udevice * dev,int offset,u32 * valuep)43966afb4edSSimon Glass int dm_pci_read_config32(struct udevice *dev, int offset, u32 *valuep)
44066afb4edSSimon Glass {
44166afb4edSSimon Glass 	unsigned long value;
44266afb4edSSimon Glass 	int ret;
44366afb4edSSimon Glass 
44466afb4edSSimon Glass 	ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_32);
44566afb4edSSimon Glass 	if (ret)
44666afb4edSSimon Glass 		return ret;
44766afb4edSSimon Glass 	*valuep = value;
44866afb4edSSimon Glass 
44966afb4edSSimon Glass 	return 0;
45066afb4edSSimon Glass }
45166afb4edSSimon Glass 
dm_pci_clrset_config8(struct udevice * dev,int offset,u32 clr,u32 set)452319dba1fSSimon Glass int dm_pci_clrset_config8(struct udevice *dev, int offset, u32 clr, u32 set)
453319dba1fSSimon Glass {
454319dba1fSSimon Glass 	u8 val;
455319dba1fSSimon Glass 	int ret;
456319dba1fSSimon Glass 
457319dba1fSSimon Glass 	ret = dm_pci_read_config8(dev, offset, &val);
458319dba1fSSimon Glass 	if (ret)
459319dba1fSSimon Glass 		return ret;
460319dba1fSSimon Glass 	val &= ~clr;
461319dba1fSSimon Glass 	val |= set;
462319dba1fSSimon Glass 
463319dba1fSSimon Glass 	return dm_pci_write_config8(dev, offset, val);
464319dba1fSSimon Glass }
465319dba1fSSimon Glass 
dm_pci_clrset_config16(struct udevice * dev,int offset,u32 clr,u32 set)466319dba1fSSimon Glass int dm_pci_clrset_config16(struct udevice *dev, int offset, u32 clr, u32 set)
467319dba1fSSimon Glass {
468319dba1fSSimon Glass 	u16 val;
469319dba1fSSimon Glass 	int ret;
470319dba1fSSimon Glass 
471319dba1fSSimon Glass 	ret = dm_pci_read_config16(dev, offset, &val);
472319dba1fSSimon Glass 	if (ret)
473319dba1fSSimon Glass 		return ret;
474319dba1fSSimon Glass 	val &= ~clr;
475319dba1fSSimon Glass 	val |= set;
476319dba1fSSimon Glass 
477319dba1fSSimon Glass 	return dm_pci_write_config16(dev, offset, val);
478319dba1fSSimon Glass }
479319dba1fSSimon Glass 
dm_pci_clrset_config32(struct udevice * dev,int offset,u32 clr,u32 set)480319dba1fSSimon Glass int dm_pci_clrset_config32(struct udevice *dev, int offset, u32 clr, u32 set)
481319dba1fSSimon Glass {
482319dba1fSSimon Glass 	u32 val;
483319dba1fSSimon Glass 	int ret;
484319dba1fSSimon Glass 
485319dba1fSSimon Glass 	ret = dm_pci_read_config32(dev, offset, &val);
486319dba1fSSimon Glass 	if (ret)
487319dba1fSSimon Glass 		return ret;
488319dba1fSSimon Glass 	val &= ~clr;
489319dba1fSSimon Glass 	val |= set;
490319dba1fSSimon Glass 
491319dba1fSSimon Glass 	return dm_pci_write_config32(dev, offset, val);
492319dba1fSSimon Glass }
493319dba1fSSimon Glass 
set_vga_bridge_bits(struct udevice * dev)494bbbcb526SBin Meng static void set_vga_bridge_bits(struct udevice *dev)
495bbbcb526SBin Meng {
496bbbcb526SBin Meng 	struct udevice *parent = dev->parent;
497bbbcb526SBin Meng 	u16 bc;
498bbbcb526SBin Meng 
499bbbcb526SBin Meng 	while (parent->seq != 0) {
500bbbcb526SBin Meng 		dm_pci_read_config16(parent, PCI_BRIDGE_CONTROL, &bc);
501bbbcb526SBin Meng 		bc |= PCI_BRIDGE_CTL_VGA;
502bbbcb526SBin Meng 		dm_pci_write_config16(parent, PCI_BRIDGE_CONTROL, bc);
503bbbcb526SBin Meng 		parent = parent->parent;
504bbbcb526SBin Meng 	}
505bbbcb526SBin Meng }
506bbbcb526SBin Meng 
pci_auto_config_devices(struct udevice * bus)507ff3e077bSSimon Glass int pci_auto_config_devices(struct udevice *bus)
508ff3e077bSSimon Glass {
509ff3e077bSSimon Glass 	struct pci_controller *hose = bus->uclass_priv;
510bbbcb526SBin Meng 	struct pci_child_platdata *pplat;
511ff3e077bSSimon Glass 	unsigned int sub_bus;
512ff3e077bSSimon Glass 	struct udevice *dev;
513ff3e077bSSimon Glass 	int ret;
514ff3e077bSSimon Glass 
515ff3e077bSSimon Glass 	sub_bus = bus->seq;
516ff3e077bSSimon Glass 	debug("%s: start\n", __func__);
517ff3e077bSSimon Glass 	pciauto_config_init(hose);
518ff3e077bSSimon Glass 	for (ret = device_find_first_child(bus, &dev);
519ff3e077bSSimon Glass 	     !ret && dev;
520ff3e077bSSimon Glass 	     ret = device_find_next_child(&dev)) {
521ff3e077bSSimon Glass 		unsigned int max_bus;
5224d21455eSSimon Glass 		int ret;
523ff3e077bSSimon Glass 
524ff3e077bSSimon Glass 		debug("%s: device %s\n", __func__, dev->name);
5255e23b8b4SSimon Glass 		ret = dm_pciauto_config_device(dev);
5264d21455eSSimon Glass 		if (ret < 0)
5274d21455eSSimon Glass 			return ret;
5284d21455eSSimon Glass 		max_bus = ret;
529ff3e077bSSimon Glass 		sub_bus = max(sub_bus, max_bus);
530bbbcb526SBin Meng 
531bbbcb526SBin Meng 		pplat = dev_get_parent_platdata(dev);
532bbbcb526SBin Meng 		if (pplat->class == (PCI_CLASS_DISPLAY_VGA << 8))
533bbbcb526SBin Meng 			set_vga_bridge_bits(dev);
534ff3e077bSSimon Glass 	}
535ff3e077bSSimon Glass 	debug("%s: done\n", __func__);
536ff3e077bSSimon Glass 
537ff3e077bSSimon Glass 	return sub_bus;
538ff3e077bSSimon Glass }
539ff3e077bSSimon Glass 
pci_generic_mmap_write_config(struct udevice * bus,int (* addr_f)(struct udevice * bus,pci_dev_t bdf,uint offset,void ** addrp),pci_dev_t bdf,uint offset,ulong value,enum pci_size_t size)540badb9922STuomas Tynkkynen int pci_generic_mmap_write_config(
541badb9922STuomas Tynkkynen 	struct udevice *bus,
542badb9922STuomas Tynkkynen 	int (*addr_f)(struct udevice *bus, pci_dev_t bdf, uint offset, void **addrp),
543badb9922STuomas Tynkkynen 	pci_dev_t bdf,
544badb9922STuomas Tynkkynen 	uint offset,
545badb9922STuomas Tynkkynen 	ulong value,
546badb9922STuomas Tynkkynen 	enum pci_size_t size)
547badb9922STuomas Tynkkynen {
548badb9922STuomas Tynkkynen 	void *address;
549badb9922STuomas Tynkkynen 
550badb9922STuomas Tynkkynen 	if (addr_f(bus, bdf, offset, &address) < 0)
551badb9922STuomas Tynkkynen 		return 0;
552badb9922STuomas Tynkkynen 
553badb9922STuomas Tynkkynen 	switch (size) {
554badb9922STuomas Tynkkynen 	case PCI_SIZE_8:
555badb9922STuomas Tynkkynen 		writeb(value, address);
556badb9922STuomas Tynkkynen 		return 0;
557badb9922STuomas Tynkkynen 	case PCI_SIZE_16:
558badb9922STuomas Tynkkynen 		writew(value, address);
559badb9922STuomas Tynkkynen 		return 0;
560badb9922STuomas Tynkkynen 	case PCI_SIZE_32:
561badb9922STuomas Tynkkynen 		writel(value, address);
562badb9922STuomas Tynkkynen 		return 0;
563badb9922STuomas Tynkkynen 	default:
564badb9922STuomas Tynkkynen 		return -EINVAL;
565badb9922STuomas Tynkkynen 	}
566badb9922STuomas Tynkkynen }
567badb9922STuomas Tynkkynen 
pci_generic_mmap_read_config(struct udevice * bus,int (* addr_f)(struct udevice * bus,pci_dev_t bdf,uint offset,void ** addrp),pci_dev_t bdf,uint offset,ulong * valuep,enum pci_size_t size)568badb9922STuomas Tynkkynen int pci_generic_mmap_read_config(
569badb9922STuomas Tynkkynen 	struct udevice *bus,
570badb9922STuomas Tynkkynen 	int (*addr_f)(struct udevice *bus, pci_dev_t bdf, uint offset, void **addrp),
571badb9922STuomas Tynkkynen 	pci_dev_t bdf,
572badb9922STuomas Tynkkynen 	uint offset,
573badb9922STuomas Tynkkynen 	ulong *valuep,
574badb9922STuomas Tynkkynen 	enum pci_size_t size)
575badb9922STuomas Tynkkynen {
576badb9922STuomas Tynkkynen 	void *address;
577badb9922STuomas Tynkkynen 
578badb9922STuomas Tynkkynen 	if (addr_f(bus, bdf, offset, &address) < 0) {
579badb9922STuomas Tynkkynen 		*valuep = pci_get_ff(size);
580badb9922STuomas Tynkkynen 		return 0;
581badb9922STuomas Tynkkynen 	}
582badb9922STuomas Tynkkynen 
583badb9922STuomas Tynkkynen 	switch (size) {
584badb9922STuomas Tynkkynen 	case PCI_SIZE_8:
585badb9922STuomas Tynkkynen 		*valuep = readb(address);
586badb9922STuomas Tynkkynen 		return 0;
587badb9922STuomas Tynkkynen 	case PCI_SIZE_16:
588badb9922STuomas Tynkkynen 		*valuep = readw(address);
589badb9922STuomas Tynkkynen 		return 0;
590badb9922STuomas Tynkkynen 	case PCI_SIZE_32:
591badb9922STuomas Tynkkynen 		*valuep = readl(address);
592badb9922STuomas Tynkkynen 		return 0;
593badb9922STuomas Tynkkynen 	default:
594badb9922STuomas Tynkkynen 		return -EINVAL;
595badb9922STuomas Tynkkynen 	}
596badb9922STuomas Tynkkynen }
597badb9922STuomas Tynkkynen 
dm_pci_hose_probe_bus(struct udevice * bus)5985e23b8b4SSimon Glass int dm_pci_hose_probe_bus(struct udevice *bus)
599ff3e077bSSimon Glass {
600ff3e077bSSimon Glass 	int sub_bus;
601ff3e077bSSimon Glass 	int ret;
602ff3e077bSSimon Glass 
603ff3e077bSSimon Glass 	debug("%s\n", __func__);
604ff3e077bSSimon Glass 
605ff3e077bSSimon Glass 	sub_bus = pci_get_bus_max() + 1;
606ff3e077bSSimon Glass 	debug("%s: bus = %d/%s\n", __func__, sub_bus, bus->name);
6075e23b8b4SSimon Glass 	dm_pciauto_prescan_setup_bridge(bus, sub_bus);
608ff3e077bSSimon Glass 
609ff3e077bSSimon Glass 	ret = device_probe(bus);
610ff3e077bSSimon Glass 	if (ret) {
6113129ace4SSimon Glass 		debug("%s: Cannot probe bus %s: %d\n", __func__, bus->name,
612ff3e077bSSimon Glass 		      ret);
613ff3e077bSSimon Glass 		return ret;
614ff3e077bSSimon Glass 	}
615ff3e077bSSimon Glass 	if (sub_bus != bus->seq) {
616ff3e077bSSimon Glass 		printf("%s: Internal error, bus '%s' got seq %d, expected %d\n",
617ff3e077bSSimon Glass 		       __func__, bus->name, bus->seq, sub_bus);
618ff3e077bSSimon Glass 		return -EPIPE;
619ff3e077bSSimon Glass 	}
620ff3e077bSSimon Glass 	sub_bus = pci_get_bus_max();
6215e23b8b4SSimon Glass 	dm_pciauto_postscan_setup_bridge(bus, sub_bus);
622ff3e077bSSimon Glass 
623ff3e077bSSimon Glass 	return sub_bus;
624ff3e077bSSimon Glass }
625ff3e077bSSimon Glass 
626aba92962SSimon Glass /**
627aba92962SSimon Glass  * pci_match_one_device - Tell if a PCI device structure has a matching
628aba92962SSimon Glass  *                        PCI device id structure
629aba92962SSimon Glass  * @id: single PCI device id structure to match
6300367bd4dSHou Zhiqiang  * @find: the PCI device id structure to match against
631aba92962SSimon Glass  *
6320367bd4dSHou Zhiqiang  * Returns true if the finding pci_device_id structure matched or false if
6330367bd4dSHou Zhiqiang  * there is no match.
634aba92962SSimon Glass  */
pci_match_one_id(const struct pci_device_id * id,const struct pci_device_id * find)635aba92962SSimon Glass static bool pci_match_one_id(const struct pci_device_id *id,
636aba92962SSimon Glass 			     const struct pci_device_id *find)
637aba92962SSimon Glass {
638aba92962SSimon Glass 	if ((id->vendor == PCI_ANY_ID || id->vendor == find->vendor) &&
639aba92962SSimon Glass 	    (id->device == PCI_ANY_ID || id->device == find->device) &&
640aba92962SSimon Glass 	    (id->subvendor == PCI_ANY_ID || id->subvendor == find->subvendor) &&
641aba92962SSimon Glass 	    (id->subdevice == PCI_ANY_ID || id->subdevice == find->subdevice) &&
642aba92962SSimon Glass 	    !((id->class ^ find->class) & id->class_mask))
643aba92962SSimon Glass 		return true;
644aba92962SSimon Glass 
645aba92962SSimon Glass 	return false;
646aba92962SSimon Glass }
647aba92962SSimon Glass 
648aba92962SSimon Glass /**
649aba92962SSimon Glass  * pci_find_and_bind_driver() - Find and bind the right PCI driver
650aba92962SSimon Glass  *
651aba92962SSimon Glass  * This only looks at certain fields in the descriptor.
6525dbcf3a0SSimon Glass  *
6535dbcf3a0SSimon Glass  * @parent:	Parent bus
6545dbcf3a0SSimon Glass  * @find_id:	Specification of the driver to find
6555dbcf3a0SSimon Glass  * @bdf:	Bus/device/function addreess - see PCI_BDF()
6565dbcf3a0SSimon Glass  * @devp:	Returns a pointer to the device created
6575dbcf3a0SSimon Glass  * @return 0 if OK, -EPERM if the device is not needed before relocation and
6585dbcf3a0SSimon Glass  *	   therefore was not created, other -ve value on error
659aba92962SSimon Glass  */
pci_find_and_bind_driver(struct udevice * parent,struct pci_device_id * find_id,pci_dev_t bdf,struct udevice ** devp)660aba92962SSimon Glass static int pci_find_and_bind_driver(struct udevice *parent,
6615dbcf3a0SSimon Glass 				    struct pci_device_id *find_id,
6625dbcf3a0SSimon Glass 				    pci_dev_t bdf, struct udevice **devp)
663aba92962SSimon Glass {
664aba92962SSimon Glass 	struct pci_driver_entry *start, *entry;
66502e4d38dSMarek Vasut 	ofnode node = ofnode_null();
666aba92962SSimon Glass 	const char *drv;
667aba92962SSimon Glass 	int n_ents;
668aba92962SSimon Glass 	int ret;
669aba92962SSimon Glass 	char name[30], *str;
67008fc7b8fSBin Meng 	bool bridge;
671aba92962SSimon Glass 
672aba92962SSimon Glass 	*devp = NULL;
673aba92962SSimon Glass 
674aba92962SSimon Glass 	debug("%s: Searching for driver: vendor=%x, device=%x\n", __func__,
675aba92962SSimon Glass 	      find_id->vendor, find_id->device);
67602e4d38dSMarek Vasut 
67702e4d38dSMarek Vasut 	/* Determine optional OF node */
67802e4d38dSMarek Vasut 	pci_dev_find_ofnode(parent, bdf, &node);
67902e4d38dSMarek Vasut 
680aba92962SSimon Glass 	start = ll_entry_start(struct pci_driver_entry, pci_driver_entry);
681aba92962SSimon Glass 	n_ents = ll_entry_count(struct pci_driver_entry, pci_driver_entry);
682aba92962SSimon Glass 	for (entry = start; entry != start + n_ents; entry++) {
683aba92962SSimon Glass 		const struct pci_device_id *id;
684aba92962SSimon Glass 		struct udevice *dev;
685aba92962SSimon Glass 		const struct driver *drv;
686aba92962SSimon Glass 
687aba92962SSimon Glass 		for (id = entry->match;
688aba92962SSimon Glass 		     id->vendor || id->subvendor || id->class_mask;
689aba92962SSimon Glass 		     id++) {
690aba92962SSimon Glass 			if (!pci_match_one_id(id, find_id))
691aba92962SSimon Glass 				continue;
692aba92962SSimon Glass 
693aba92962SSimon Glass 			drv = entry->driver;
69408fc7b8fSBin Meng 
69508fc7b8fSBin Meng 			/*
69608fc7b8fSBin Meng 			 * In the pre-relocation phase, we only bind devices
69708fc7b8fSBin Meng 			 * whose driver has the DM_FLAG_PRE_RELOC set, to save
69808fc7b8fSBin Meng 			 * precious memory space as on some platforms as that
69908fc7b8fSBin Meng 			 * space is pretty limited (ie: using Cache As RAM).
70008fc7b8fSBin Meng 			 */
70108fc7b8fSBin Meng 			if (!(gd->flags & GD_FLG_RELOC) &&
70208fc7b8fSBin Meng 			    !(drv->flags & DM_FLAG_PRE_RELOC))
7035dbcf3a0SSimon Glass 				return -EPERM;
70408fc7b8fSBin Meng 
705aba92962SSimon Glass 			/*
706aba92962SSimon Glass 			 * We could pass the descriptor to the driver as
707aba92962SSimon Glass 			 * platdata (instead of NULL) and allow its bind()
708aba92962SSimon Glass 			 * method to return -ENOENT if it doesn't support this
709aba92962SSimon Glass 			 * device. That way we could continue the search to
710aba92962SSimon Glass 			 * find another driver. For now this doesn't seem
711aba92962SSimon Glass 			 * necesssary, so just bind the first match.
712aba92962SSimon Glass 			 */
71302e4d38dSMarek Vasut 			ret = device_bind_ofnode(parent, drv, drv->name, NULL,
71402e4d38dSMarek Vasut 						 node, &dev);
715aba92962SSimon Glass 			if (ret)
716aba92962SSimon Glass 				goto error;
717aba92962SSimon Glass 			debug("%s: Match found: %s\n", __func__, drv->name);
718ed698aa7SBin Meng 			dev->driver_data = id->driver_data;
719aba92962SSimon Glass 			*devp = dev;
720aba92962SSimon Glass 			return 0;
721aba92962SSimon Glass 		}
722aba92962SSimon Glass 	}
723aba92962SSimon Glass 
72408fc7b8fSBin Meng 	bridge = (find_id->class >> 8) == PCI_CLASS_BRIDGE_PCI;
72508fc7b8fSBin Meng 	/*
72608fc7b8fSBin Meng 	 * In the pre-relocation phase, we only bind bridge devices to save
72708fc7b8fSBin Meng 	 * precious memory space as on some platforms as that space is pretty
72808fc7b8fSBin Meng 	 * limited (ie: using Cache As RAM).
72908fc7b8fSBin Meng 	 */
73008fc7b8fSBin Meng 	if (!(gd->flags & GD_FLG_RELOC) && !bridge)
7315dbcf3a0SSimon Glass 		return -EPERM;
73208fc7b8fSBin Meng 
733aba92962SSimon Glass 	/* Bind a generic driver so that the device can be used */
7344d8615cbSBin Meng 	sprintf(name, "pci_%x:%x.%x", parent->seq, PCI_DEV(bdf),
7354d8615cbSBin Meng 		PCI_FUNC(bdf));
736aba92962SSimon Glass 	str = strdup(name);
737aba92962SSimon Glass 	if (!str)
738aba92962SSimon Glass 		return -ENOMEM;
73908fc7b8fSBin Meng 	drv = bridge ? "pci_bridge_drv" : "pci_generic_drv";
74008fc7b8fSBin Meng 
74102e4d38dSMarek Vasut 	ret = device_bind_driver_to_node(parent, drv, str, node, devp);
742aba92962SSimon Glass 	if (ret) {
7433129ace4SSimon Glass 		debug("%s: Failed to bind generic driver: %d\n", __func__, ret);
744c42640c7Sxypron.glpk@gmx.de 		free(str);
745aba92962SSimon Glass 		return ret;
746aba92962SSimon Glass 	}
747aba92962SSimon Glass 	debug("%s: No match found: bound generic driver instead\n", __func__);
748aba92962SSimon Glass 
749aba92962SSimon Glass 	return 0;
750aba92962SSimon Glass 
751aba92962SSimon Glass error:
752aba92962SSimon Glass 	debug("%s: No match found: error %d\n", __func__, ret);
753aba92962SSimon Glass 	return ret;
754aba92962SSimon Glass }
755aba92962SSimon Glass 
pci_bind_bus_devices(struct udevice * bus)756ff3e077bSSimon Glass int pci_bind_bus_devices(struct udevice *bus)
757ff3e077bSSimon Glass {
758ff3e077bSSimon Glass 	ulong vendor, device;
759ff3e077bSSimon Glass 	ulong header_type;
7604d8615cbSBin Meng 	pci_dev_t bdf, end;
761ff3e077bSSimon Glass 	bool found_multi;
762ff3e077bSSimon Glass 	int ret;
763ff3e077bSSimon Glass 
764ff3e077bSSimon Glass 	found_multi = false;
7654d8615cbSBin Meng 	end = PCI_BDF(bus->seq, PCI_MAX_PCI_DEVICES - 1,
7664d8615cbSBin Meng 		      PCI_MAX_PCI_FUNCTIONS - 1);
7676d9f5b03SYoshinori Sato 	for (bdf = PCI_BDF(bus->seq, 0, 0); bdf <= end;
7684d8615cbSBin Meng 	     bdf += PCI_BDF(0, 0, 1)) {
769ff3e077bSSimon Glass 		struct pci_child_platdata *pplat;
770ff3e077bSSimon Glass 		struct udevice *dev;
771ff3e077bSSimon Glass 		ulong class;
772ff3e077bSSimon Glass 
77364e45f73SBin Meng 		if (!PCI_FUNC(bdf))
77464e45f73SBin Meng 			found_multi = false;
7754d8615cbSBin Meng 		if (PCI_FUNC(bdf) && !found_multi)
776ff3e077bSSimon Glass 			continue;
7772a87f7fdSHou Zhiqiang 
778ff3e077bSSimon Glass 		/* Check only the first access, we don't expect problems */
7792a87f7fdSHou Zhiqiang 		ret = pci_bus_read_config(bus, bdf, PCI_VENDOR_ID, &vendor,
7802a87f7fdSHou Zhiqiang 					  PCI_SIZE_16);
781ff3e077bSSimon Glass 		if (ret)
782ff3e077bSSimon Glass 			goto error;
7832a87f7fdSHou Zhiqiang 
784ff3e077bSSimon Glass 		if (vendor == 0xffff || vendor == 0x0000)
785ff3e077bSSimon Glass 			continue;
786ff3e077bSSimon Glass 
7872a87f7fdSHou Zhiqiang 		pci_bus_read_config(bus, bdf, PCI_HEADER_TYPE,
7882a87f7fdSHou Zhiqiang 				    &header_type, PCI_SIZE_8);
7892a87f7fdSHou Zhiqiang 
7904d8615cbSBin Meng 		if (!PCI_FUNC(bdf))
791ff3e077bSSimon Glass 			found_multi = header_type & 0x80;
792ff3e077bSSimon Glass 
793ff3e077bSSimon Glass 		debug("%s: bus %d/%s: found device %x, function %d\n", __func__,
7944d8615cbSBin Meng 		      bus->seq, bus->name, PCI_DEV(bdf), PCI_FUNC(bdf));
7954d8615cbSBin Meng 		pci_bus_read_config(bus, bdf, PCI_DEVICE_ID, &device,
796ff3e077bSSimon Glass 				    PCI_SIZE_16);
7974d8615cbSBin Meng 		pci_bus_read_config(bus, bdf, PCI_CLASS_REVISION, &class,
798aba92962SSimon Glass 				    PCI_SIZE_32);
799aba92962SSimon Glass 		class >>= 8;
800ff3e077bSSimon Glass 
801ff3e077bSSimon Glass 		/* Find this device in the device tree */
8024d8615cbSBin Meng 		ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), &dev);
803ff3e077bSSimon Glass 
8048bd42525SSimon Glass 		/* If nothing in the device tree, bind a device */
805ff3e077bSSimon Glass 		if (ret == -ENODEV) {
806aba92962SSimon Glass 			struct pci_device_id find_id;
807aba92962SSimon Glass 			ulong val;
808ff3e077bSSimon Glass 
809aba92962SSimon Glass 			memset(&find_id, '\0', sizeof(find_id));
810aba92962SSimon Glass 			find_id.vendor = vendor;
811aba92962SSimon Glass 			find_id.device = device;
812aba92962SSimon Glass 			find_id.class = class;
813aba92962SSimon Glass 			if ((header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL) {
8144d8615cbSBin Meng 				pci_bus_read_config(bus, bdf,
815aba92962SSimon Glass 						    PCI_SUBSYSTEM_VENDOR_ID,
816aba92962SSimon Glass 						    &val, PCI_SIZE_32);
817aba92962SSimon Glass 				find_id.subvendor = val & 0xffff;
818aba92962SSimon Glass 				find_id.subdevice = val >> 16;
819aba92962SSimon Glass 			}
8204d8615cbSBin Meng 			ret = pci_find_and_bind_driver(bus, &find_id, bdf,
821aba92962SSimon Glass 						       &dev);
822ff3e077bSSimon Glass 		}
8235dbcf3a0SSimon Glass 		if (ret == -EPERM)
8245dbcf3a0SSimon Glass 			continue;
8255dbcf3a0SSimon Glass 		else if (ret)
826ff3e077bSSimon Glass 			return ret;
827ff3e077bSSimon Glass 
828ff3e077bSSimon Glass 		/* Update the platform data */
829ff3e077bSSimon Glass 		pplat = dev_get_parent_platdata(dev);
8304d8615cbSBin Meng 		pplat->devfn = PCI_MASK_BUS(bdf);
831ff3e077bSSimon Glass 		pplat->vendor = vendor;
832ff3e077bSSimon Glass 		pplat->device = device;
833ff3e077bSSimon Glass 		pplat->class = class;
834ff3e077bSSimon Glass 	}
835ff3e077bSSimon Glass 
836ff3e077bSSimon Glass 	return 0;
837ff3e077bSSimon Glass error:
838ff3e077bSSimon Glass 	printf("Cannot read bus configuration: %d\n", ret);
839ff3e077bSSimon Glass 
840ff3e077bSSimon Glass 	return ret;
841ff3e077bSSimon Glass }
842ff3e077bSSimon Glass 
decode_regions(struct pci_controller * hose,ofnode parent_node,ofnode node)843f2825f6eSChristian Gmeiner static void decode_regions(struct pci_controller *hose, ofnode parent_node,
844bf501595SSimon Glass 			   ofnode node)
845ff3e077bSSimon Glass {
846ff3e077bSSimon Glass 	int pci_addr_cells, addr_cells, size_cells;
847ff3e077bSSimon Glass 	int cells_per_record;
848ff3e077bSSimon Glass 	const u32 *prop;
849ff3e077bSSimon Glass 	int len;
850ff3e077bSSimon Glass 	int i;
851ff3e077bSSimon Glass 
85261e51babSMasahiro Yamada 	prop = ofnode_get_property(node, "ranges", &len);
853f2825f6eSChristian Gmeiner 	if (!prop) {
854f2825f6eSChristian Gmeiner 		debug("%s: Cannot decode regions\n", __func__);
855f2825f6eSChristian Gmeiner 		return;
856f2825f6eSChristian Gmeiner 	}
857f2825f6eSChristian Gmeiner 
858878d68c0SSimon Glass 	pci_addr_cells = ofnode_read_simple_addr_cells(node);
859878d68c0SSimon Glass 	addr_cells = ofnode_read_simple_addr_cells(parent_node);
860878d68c0SSimon Glass 	size_cells = ofnode_read_simple_size_cells(node);
861ff3e077bSSimon Glass 
862ff3e077bSSimon Glass 	/* PCI addresses are always 3-cells */
863ff3e077bSSimon Glass 	len /= sizeof(u32);
864ff3e077bSSimon Glass 	cells_per_record = pci_addr_cells + addr_cells + size_cells;
865ff3e077bSSimon Glass 	hose->region_count = 0;
866ff3e077bSSimon Glass 	debug("%s: len=%d, cells_per_record=%d\n", __func__, len,
867ff3e077bSSimon Glass 	      cells_per_record);
868ff3e077bSSimon Glass 	for (i = 0; i < MAX_PCI_REGIONS; i++, len -= cells_per_record) {
869ff3e077bSSimon Glass 		u64 pci_addr, addr, size;
870ff3e077bSSimon Glass 		int space_code;
871ff3e077bSSimon Glass 		u32 flags;
872ff3e077bSSimon Glass 		int type;
8739526d83aSSimon Glass 		int pos;
874ff3e077bSSimon Glass 
875ff3e077bSSimon Glass 		if (len < cells_per_record)
876ff3e077bSSimon Glass 			break;
877ff3e077bSSimon Glass 		flags = fdt32_to_cpu(prop[0]);
878ff3e077bSSimon Glass 		space_code = (flags >> 24) & 3;
879ff3e077bSSimon Glass 		pci_addr = fdtdec_get_number(prop + 1, 2);
880ff3e077bSSimon Glass 		prop += pci_addr_cells;
881ff3e077bSSimon Glass 		addr = fdtdec_get_number(prop, addr_cells);
882ff3e077bSSimon Glass 		prop += addr_cells;
883ff3e077bSSimon Glass 		size = fdtdec_get_number(prop, size_cells);
884ff3e077bSSimon Glass 		prop += size_cells;
885dee37fc9SMasahiro Yamada 		debug("%s: region %d, pci_addr=%llx, addr=%llx, size=%llx, space_code=%d\n",
886dee37fc9SMasahiro Yamada 		      __func__, hose->region_count, pci_addr, addr, size, space_code);
887ff3e077bSSimon Glass 		if (space_code & 2) {
888ff3e077bSSimon Glass 			type = flags & (1U << 30) ? PCI_REGION_PREFETCH :
889ff3e077bSSimon Glass 					PCI_REGION_MEM;
890ff3e077bSSimon Glass 		} else if (space_code & 1) {
891ff3e077bSSimon Glass 			type = PCI_REGION_IO;
892ff3e077bSSimon Glass 		} else {
893ff3e077bSSimon Glass 			continue;
894ff3e077bSSimon Glass 		}
89552ba9073STuomas Tynkkynen 
89652ba9073STuomas Tynkkynen 		if (!IS_ENABLED(CONFIG_SYS_PCI_64BIT) &&
89752ba9073STuomas Tynkkynen 		    type == PCI_REGION_MEM && upper_32_bits(pci_addr)) {
89852ba9073STuomas Tynkkynen 			debug(" - beyond the 32-bit boundary, ignoring\n");
89952ba9073STuomas Tynkkynen 			continue;
90052ba9073STuomas Tynkkynen 		}
90152ba9073STuomas Tynkkynen 
9029526d83aSSimon Glass 		pos = -1;
9039526d83aSSimon Glass 		for (i = 0; i < hose->region_count; i++) {
9049526d83aSSimon Glass 			if (hose->regions[i].flags == type)
9059526d83aSSimon Glass 				pos = i;
9069526d83aSSimon Glass 		}
9079526d83aSSimon Glass 		if (pos == -1)
9089526d83aSSimon Glass 			pos = hose->region_count++;
9099526d83aSSimon Glass 		debug(" - type=%d, pos=%d\n", type, pos);
9109526d83aSSimon Glass 		pci_set_region(hose->regions + pos, pci_addr, addr, size, type);
911ff3e077bSSimon Glass 	}
912ff3e077bSSimon Glass 
913ff3e077bSSimon Glass 	/* Add a region for our local memory */
914664758c3SBernhard Messerklinger #ifdef CONFIG_NR_DRAM_BANKS
915664758c3SBernhard Messerklinger 	bd_t *bd = gd->bd;
916664758c3SBernhard Messerklinger 
9171eaf7800SBin Meng 	if (!bd)
918f2825f6eSChristian Gmeiner 		return;
9191eaf7800SBin Meng 
920664758c3SBernhard Messerklinger 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
921664758c3SBernhard Messerklinger 		if (bd->bi_dram[i].size) {
922664758c3SBernhard Messerklinger 			pci_set_region(hose->regions + hose->region_count++,
923664758c3SBernhard Messerklinger 				       bd->bi_dram[i].start,
924664758c3SBernhard Messerklinger 				       bd->bi_dram[i].start,
925664758c3SBernhard Messerklinger 				       bd->bi_dram[i].size,
926664758c3SBernhard Messerklinger 				       PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
927664758c3SBernhard Messerklinger 		}
928664758c3SBernhard Messerklinger 	}
929664758c3SBernhard Messerklinger #else
930664758c3SBernhard Messerklinger 	phys_addr_t base = 0, size;
931664758c3SBernhard Messerklinger 
9322084c5afSSimon Glass 	size = gd->ram_size;
9332084c5afSSimon Glass #ifdef CONFIG_SYS_SDRAM_BASE
9342084c5afSSimon Glass 	base = CONFIG_SYS_SDRAM_BASE;
9352084c5afSSimon Glass #endif
9362084c5afSSimon Glass 	if (gd->pci_ram_top && gd->pci_ram_top < base + size)
9372084c5afSSimon Glass 		size = gd->pci_ram_top - base;
938ee1109bbSBin Meng 	if (size)
939ee1109bbSBin Meng 		pci_set_region(hose->regions + hose->region_count++, base,
940ee1109bbSBin Meng 			base, size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
941664758c3SBernhard Messerklinger #endif
942ff3e077bSSimon Glass 
943f2825f6eSChristian Gmeiner 	return;
944ff3e077bSSimon Glass }
945ff3e077bSSimon Glass 
pci_uclass_pre_probe(struct udevice * bus)946ff3e077bSSimon Glass static int pci_uclass_pre_probe(struct udevice *bus)
947ff3e077bSSimon Glass {
948ff3e077bSSimon Glass 	struct pci_controller *hose;
949ff3e077bSSimon Glass 
950ff3e077bSSimon Glass 	debug("%s, bus=%d/%s, parent=%s\n", __func__, bus->seq, bus->name,
951ff3e077bSSimon Glass 	      bus->parent->name);
952ff3e077bSSimon Glass 	hose = bus->uclass_priv;
953ff3e077bSSimon Glass 
954ff3e077bSSimon Glass 	/* For bridges, use the top-level PCI controller */
95565f62b1cSPaul Burton 	if (!device_is_on_pci_bus(bus)) {
956ff3e077bSSimon Glass 		hose->ctlr = bus;
957f2825f6eSChristian Gmeiner 		decode_regions(hose, dev_ofnode(bus->parent), dev_ofnode(bus));
958ff3e077bSSimon Glass 	} else {
959ff3e077bSSimon Glass 		struct pci_controller *parent_hose;
960ff3e077bSSimon Glass 
961ff3e077bSSimon Glass 		parent_hose = dev_get_uclass_priv(bus->parent);
962ff3e077bSSimon Glass 		hose->ctlr = parent_hose->bus;
963ff3e077bSSimon Glass 	}
964ff3e077bSSimon Glass 	hose->bus = bus;
965ff3e077bSSimon Glass 	hose->first_busno = bus->seq;
966ff3e077bSSimon Glass 	hose->last_busno = bus->seq;
967ff3e077bSSimon Glass 
968ff3e077bSSimon Glass 	return 0;
969ff3e077bSSimon Glass }
970ff3e077bSSimon Glass 
pci_uclass_post_probe(struct udevice * bus)971ff3e077bSSimon Glass static int pci_uclass_post_probe(struct udevice *bus)
972ff3e077bSSimon Glass {
973ff3e077bSSimon Glass 	int ret;
974ff3e077bSSimon Glass 
975ff3e077bSSimon Glass 	debug("%s: probing bus %d\n", __func__, bus->seq);
976ff3e077bSSimon Glass 	ret = pci_bind_bus_devices(bus);
977ff3e077bSSimon Glass 	if (ret)
978ff3e077bSSimon Glass 		return ret;
979ff3e077bSSimon Glass 
980ff3e077bSSimon Glass #ifdef CONFIG_PCI_PNP
981ff3e077bSSimon Glass 	ret = pci_auto_config_devices(bus);
9824d21455eSSimon Glass 	if (ret < 0)
9834d21455eSSimon Glass 		return ret;
984ff3e077bSSimon Glass #endif
985ff3e077bSSimon Glass 
986348b744bSBin Meng #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
987348b744bSBin Meng 	/*
988348b744bSBin Meng 	 * Per Intel FSP specification, we should call FSP notify API to
989348b744bSBin Meng 	 * inform FSP that PCI enumeration has been done so that FSP will
990348b744bSBin Meng 	 * do any necessary initialization as required by the chipset's
991348b744bSBin Meng 	 * BIOS Writer's Guide (BWG).
992348b744bSBin Meng 	 *
993348b744bSBin Meng 	 * Unfortunately we have to put this call here as with driver model,
994348b744bSBin Meng 	 * the enumeration is all done on a lazy basis as needed, so until
995348b744bSBin Meng 	 * something is touched on PCI it won't happen.
996348b744bSBin Meng 	 *
997348b744bSBin Meng 	 * Note we only call this 1) after U-Boot is relocated, and 2)
998348b744bSBin Meng 	 * root bus has finished probing.
999348b744bSBin Meng 	 */
10004d21455eSSimon Glass 	if ((gd->flags & GD_FLG_RELOC) && (bus->seq == 0)) {
1001348b744bSBin Meng 		ret = fsp_init_phase_pci();
10024d21455eSSimon Glass 		if (ret)
10034d21455eSSimon Glass 			return ret;
10044d21455eSSimon Glass 	}
1005348b744bSBin Meng #endif
1006348b744bSBin Meng 
10074d21455eSSimon Glass 	return 0;
1008ff3e077bSSimon Glass }
1009ff3e077bSSimon Glass 
pci_get_devfn(struct udevice * dev)1010*b5214200SStefan Roese int pci_get_devfn(struct udevice *dev)
1011*b5214200SStefan Roese {
1012*b5214200SStefan Roese 	struct fdt_pci_addr addr;
1013*b5214200SStefan Roese 	int ret;
1014*b5214200SStefan Roese 
1015*b5214200SStefan Roese 	/* Extract the devfn from fdt_pci_addr */
1016*b5214200SStefan Roese 	ret = ofnode_read_pci_addr(dev_ofnode(dev), FDT_PCI_SPACE_CONFIG,
1017*b5214200SStefan Roese 				   "reg", &addr);
1018*b5214200SStefan Roese 	if (ret) {
1019*b5214200SStefan Roese 		if (ret != -ENOENT)
1020*b5214200SStefan Roese 			return -EINVAL;
1021*b5214200SStefan Roese 	}
1022*b5214200SStefan Roese 
1023*b5214200SStefan Roese 	return addr.phys_hi & 0xff00;
1024*b5214200SStefan Roese }
1025*b5214200SStefan Roese 
pci_uclass_child_post_bind(struct udevice * dev)1026ff3e077bSSimon Glass static int pci_uclass_child_post_bind(struct udevice *dev)
1027ff3e077bSSimon Glass {
1028ff3e077bSSimon Glass 	struct pci_child_platdata *pplat;
1029ff3e077bSSimon Glass 
1030bf501595SSimon Glass 	if (!dev_of_valid(dev))
1031ff3e077bSSimon Glass 		return 0;
1032ff3e077bSSimon Glass 
1033ff3e077bSSimon Glass 	pplat = dev_get_parent_platdata(dev);
10341f6b08b9SBin Meng 
10351f6b08b9SBin Meng 	/* Extract vendor id and device id if available */
10361f6b08b9SBin Meng 	ofnode_read_pci_vendev(dev_ofnode(dev), &pplat->vendor, &pplat->device);
10371f6b08b9SBin Meng 
10381f6b08b9SBin Meng 	/* Extract the devfn from fdt_pci_addr */
1039*b5214200SStefan Roese 	pplat->devfn = pci_get_devfn(dev);
1040ff3e077bSSimon Glass 
1041ff3e077bSSimon Glass 	return 0;
1042ff3e077bSSimon Glass }
1043ff3e077bSSimon Glass 
pci_bridge_read_config(struct udevice * bus,pci_dev_t bdf,uint offset,ulong * valuep,enum pci_size_t size)10444d8615cbSBin Meng static int pci_bridge_read_config(struct udevice *bus, pci_dev_t bdf,
10454d8615cbSBin Meng 				  uint offset, ulong *valuep,
10464d8615cbSBin Meng 				  enum pci_size_t size)
1047ff3e077bSSimon Glass {
1048ff3e077bSSimon Glass 	struct pci_controller *hose = bus->uclass_priv;
1049ff3e077bSSimon Glass 
1050ff3e077bSSimon Glass 	return pci_bus_read_config(hose->ctlr, bdf, offset, valuep, size);
1051ff3e077bSSimon Glass }
1052ff3e077bSSimon Glass 
pci_bridge_write_config(struct udevice * bus,pci_dev_t bdf,uint offset,ulong value,enum pci_size_t size)10534d8615cbSBin Meng static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf,
10544d8615cbSBin Meng 				   uint offset, ulong value,
10554d8615cbSBin Meng 				   enum pci_size_t size)
1056ff3e077bSSimon Glass {
1057ff3e077bSSimon Glass 	struct pci_controller *hose = bus->uclass_priv;
1058ff3e077bSSimon Glass 
1059ff3e077bSSimon Glass 	return pci_bus_write_config(hose->ctlr, bdf, offset, value, size);
1060ff3e077bSSimon Glass }
1061ff3e077bSSimon Glass 
skip_to_next_device(struct udevice * bus,struct udevice ** devp)106276c3fbcdSSimon Glass static int skip_to_next_device(struct udevice *bus, struct udevice **devp)
106376c3fbcdSSimon Glass {
106476c3fbcdSSimon Glass 	struct udevice *dev;
106576c3fbcdSSimon Glass 	int ret = 0;
106676c3fbcdSSimon Glass 
106776c3fbcdSSimon Glass 	/*
106876c3fbcdSSimon Glass 	 * Scan through all the PCI controllers. On x86 there will only be one
106976c3fbcdSSimon Glass 	 * but that is not necessarily true on other hardware.
107076c3fbcdSSimon Glass 	 */
107176c3fbcdSSimon Glass 	do {
107276c3fbcdSSimon Glass 		device_find_first_child(bus, &dev);
107376c3fbcdSSimon Glass 		if (dev) {
107476c3fbcdSSimon Glass 			*devp = dev;
107576c3fbcdSSimon Glass 			return 0;
107676c3fbcdSSimon Glass 		}
107776c3fbcdSSimon Glass 		ret = uclass_next_device(&bus);
107876c3fbcdSSimon Glass 		if (ret)
107976c3fbcdSSimon Glass 			return ret;
108076c3fbcdSSimon Glass 	} while (bus);
108176c3fbcdSSimon Glass 
108276c3fbcdSSimon Glass 	return 0;
108376c3fbcdSSimon Glass }
108476c3fbcdSSimon Glass 
pci_find_next_device(struct udevice ** devp)108576c3fbcdSSimon Glass int pci_find_next_device(struct udevice **devp)
108676c3fbcdSSimon Glass {
108776c3fbcdSSimon Glass 	struct udevice *child = *devp;
108876c3fbcdSSimon Glass 	struct udevice *bus = child->parent;
108976c3fbcdSSimon Glass 	int ret;
109076c3fbcdSSimon Glass 
109176c3fbcdSSimon Glass 	/* First try all the siblings */
109276c3fbcdSSimon Glass 	*devp = NULL;
109376c3fbcdSSimon Glass 	while (child) {
109476c3fbcdSSimon Glass 		device_find_next_child(&child);
109576c3fbcdSSimon Glass 		if (child) {
109676c3fbcdSSimon Glass 			*devp = child;
109776c3fbcdSSimon Glass 			return 0;
109876c3fbcdSSimon Glass 		}
109976c3fbcdSSimon Glass 	}
110076c3fbcdSSimon Glass 
110176c3fbcdSSimon Glass 	/* We ran out of siblings. Try the next bus */
110276c3fbcdSSimon Glass 	ret = uclass_next_device(&bus);
110376c3fbcdSSimon Glass 	if (ret)
110476c3fbcdSSimon Glass 		return ret;
110576c3fbcdSSimon Glass 
110676c3fbcdSSimon Glass 	return bus ? skip_to_next_device(bus, devp) : 0;
110776c3fbcdSSimon Glass }
110876c3fbcdSSimon Glass 
pci_find_first_device(struct udevice ** devp)110976c3fbcdSSimon Glass int pci_find_first_device(struct udevice **devp)
111076c3fbcdSSimon Glass {
111176c3fbcdSSimon Glass 	struct udevice *bus;
111276c3fbcdSSimon Glass 	int ret;
111376c3fbcdSSimon Glass 
111476c3fbcdSSimon Glass 	*devp = NULL;
111576c3fbcdSSimon Glass 	ret = uclass_first_device(UCLASS_PCI, &bus);
111676c3fbcdSSimon Glass 	if (ret)
111776c3fbcdSSimon Glass 		return ret;
111876c3fbcdSSimon Glass 
111976c3fbcdSSimon Glass 	return skip_to_next_device(bus, devp);
112076c3fbcdSSimon Glass }
112176c3fbcdSSimon Glass 
pci_conv_32_to_size(ulong value,uint offset,enum pci_size_t size)11229289db6cSSimon Glass ulong pci_conv_32_to_size(ulong value, uint offset, enum pci_size_t size)
11239289db6cSSimon Glass {
11249289db6cSSimon Glass 	switch (size) {
11259289db6cSSimon Glass 	case PCI_SIZE_8:
11269289db6cSSimon Glass 		return (value >> ((offset & 3) * 8)) & 0xff;
11279289db6cSSimon Glass 	case PCI_SIZE_16:
11289289db6cSSimon Glass 		return (value >> ((offset & 2) * 8)) & 0xffff;
11299289db6cSSimon Glass 	default:
11309289db6cSSimon Glass 		return value;
11319289db6cSSimon Glass 	}
11329289db6cSSimon Glass }
11339289db6cSSimon Glass 
pci_conv_size_to_32(ulong old,ulong value,uint offset,enum pci_size_t size)11349289db6cSSimon Glass ulong pci_conv_size_to_32(ulong old, ulong value, uint offset,
11359289db6cSSimon Glass 			  enum pci_size_t size)
11369289db6cSSimon Glass {
11379289db6cSSimon Glass 	uint off_mask;
11389289db6cSSimon Glass 	uint val_mask, shift;
11399289db6cSSimon Glass 	ulong ldata, mask;
11409289db6cSSimon Glass 
11419289db6cSSimon Glass 	switch (size) {
11429289db6cSSimon Glass 	case PCI_SIZE_8:
11439289db6cSSimon Glass 		off_mask = 3;
11449289db6cSSimon Glass 		val_mask = 0xff;
11459289db6cSSimon Glass 		break;
11469289db6cSSimon Glass 	case PCI_SIZE_16:
11479289db6cSSimon Glass 		off_mask = 2;
11489289db6cSSimon Glass 		val_mask = 0xffff;
11499289db6cSSimon Glass 		break;
11509289db6cSSimon Glass 	default:
11519289db6cSSimon Glass 		return value;
11529289db6cSSimon Glass 	}
11539289db6cSSimon Glass 	shift = (offset & off_mask) * 8;
11549289db6cSSimon Glass 	ldata = (value & val_mask) << shift;
11559289db6cSSimon Glass 	mask = val_mask << shift;
11569289db6cSSimon Glass 	value = (old & ~mask) | ldata;
11579289db6cSSimon Glass 
11589289db6cSSimon Glass 	return value;
11599289db6cSSimon Glass }
11609289db6cSSimon Glass 
pci_get_regions(struct udevice * dev,struct pci_region ** iop,struct pci_region ** memp,struct pci_region ** prefp)1161f9260336SSimon Glass int pci_get_regions(struct udevice *dev, struct pci_region **iop,
1162f9260336SSimon Glass 		    struct pci_region **memp, struct pci_region **prefp)
1163f9260336SSimon Glass {
1164f9260336SSimon Glass 	struct udevice *bus = pci_get_controller(dev);
1165f9260336SSimon Glass 	struct pci_controller *hose = dev_get_uclass_priv(bus);
1166f9260336SSimon Glass 	int i;
1167f9260336SSimon Glass 
1168f9260336SSimon Glass 	*iop = NULL;
1169f9260336SSimon Glass 	*memp = NULL;
1170f9260336SSimon Glass 	*prefp = NULL;
1171f9260336SSimon Glass 	for (i = 0; i < hose->region_count; i++) {
1172f9260336SSimon Glass 		switch (hose->regions[i].flags) {
1173f9260336SSimon Glass 		case PCI_REGION_IO:
1174f9260336SSimon Glass 			if (!*iop || (*iop)->size < hose->regions[i].size)
1175f9260336SSimon Glass 				*iop = hose->regions + i;
1176f9260336SSimon Glass 			break;
1177f9260336SSimon Glass 		case PCI_REGION_MEM:
1178f9260336SSimon Glass 			if (!*memp || (*memp)->size < hose->regions[i].size)
1179f9260336SSimon Glass 				*memp = hose->regions + i;
1180f9260336SSimon Glass 			break;
1181f9260336SSimon Glass 		case (PCI_REGION_MEM | PCI_REGION_PREFETCH):
1182f9260336SSimon Glass 			if (!*prefp || (*prefp)->size < hose->regions[i].size)
1183f9260336SSimon Glass 				*prefp = hose->regions + i;
1184f9260336SSimon Glass 			break;
1185f9260336SSimon Glass 		}
1186f9260336SSimon Glass 	}
1187f9260336SSimon Glass 
1188f9260336SSimon Glass 	return (*iop != NULL) + (*memp != NULL) + (*prefp != NULL);
1189f9260336SSimon Glass }
1190f9260336SSimon Glass 
dm_pci_read_bar32(struct udevice * dev,int barnum)1191bab17cf1SSimon Glass u32 dm_pci_read_bar32(struct udevice *dev, int barnum)
1192bab17cf1SSimon Glass {
1193bab17cf1SSimon Glass 	u32 addr;
1194bab17cf1SSimon Glass 	int bar;
1195bab17cf1SSimon Glass 
1196bab17cf1SSimon Glass 	bar = PCI_BASE_ADDRESS_0 + barnum * 4;
1197bab17cf1SSimon Glass 	dm_pci_read_config32(dev, bar, &addr);
1198bab17cf1SSimon Glass 	if (addr & PCI_BASE_ADDRESS_SPACE_IO)
1199bab17cf1SSimon Glass 		return addr & PCI_BASE_ADDRESS_IO_MASK;
1200bab17cf1SSimon Glass 	else
1201bab17cf1SSimon Glass 		return addr & PCI_BASE_ADDRESS_MEM_MASK;
1202bab17cf1SSimon Glass }
1203bab17cf1SSimon Glass 
dm_pci_write_bar32(struct udevice * dev,int barnum,u32 addr)12049d731c82SSimon Glass void dm_pci_write_bar32(struct udevice *dev, int barnum, u32 addr)
12059d731c82SSimon Glass {
12069d731c82SSimon Glass 	int bar;
12079d731c82SSimon Glass 
12089d731c82SSimon Glass 	bar = PCI_BASE_ADDRESS_0 + barnum * 4;
12099d731c82SSimon Glass 	dm_pci_write_config32(dev, bar, addr);
12109d731c82SSimon Glass }
12119d731c82SSimon Glass 
_dm_pci_bus_to_phys(struct udevice * ctlr,pci_addr_t bus_addr,unsigned long flags,unsigned long skip_mask,phys_addr_t * pa)121221d1fe7eSSimon Glass static int _dm_pci_bus_to_phys(struct udevice *ctlr,
121321d1fe7eSSimon Glass 			       pci_addr_t bus_addr, unsigned long flags,
121421d1fe7eSSimon Glass 			       unsigned long skip_mask, phys_addr_t *pa)
121521d1fe7eSSimon Glass {
121621d1fe7eSSimon Glass 	struct pci_controller *hose = dev_get_uclass_priv(ctlr);
121721d1fe7eSSimon Glass 	struct pci_region *res;
121821d1fe7eSSimon Glass 	int i;
121921d1fe7eSSimon Glass 
12206f95d89cSChristian Gmeiner 	if (hose->region_count == 0) {
12216f95d89cSChristian Gmeiner 		*pa = bus_addr;
12226f95d89cSChristian Gmeiner 		return 0;
12236f95d89cSChristian Gmeiner 	}
12246f95d89cSChristian Gmeiner 
122521d1fe7eSSimon Glass 	for (i = 0; i < hose->region_count; i++) {
122621d1fe7eSSimon Glass 		res = &hose->regions[i];
122721d1fe7eSSimon Glass 
122821d1fe7eSSimon Glass 		if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
122921d1fe7eSSimon Glass 			continue;
123021d1fe7eSSimon Glass 
123121d1fe7eSSimon Glass 		if (res->flags & skip_mask)
123221d1fe7eSSimon Glass 			continue;
123321d1fe7eSSimon Glass 
123421d1fe7eSSimon Glass 		if (bus_addr >= res->bus_start &&
123521d1fe7eSSimon Glass 		    (bus_addr - res->bus_start) < res->size) {
123621d1fe7eSSimon Glass 			*pa = (bus_addr - res->bus_start + res->phys_start);
123721d1fe7eSSimon Glass 			return 0;
123821d1fe7eSSimon Glass 		}
123921d1fe7eSSimon Glass 	}
124021d1fe7eSSimon Glass 
124121d1fe7eSSimon Glass 	return 1;
124221d1fe7eSSimon Glass }
124321d1fe7eSSimon Glass 
dm_pci_bus_to_phys(struct udevice * dev,pci_addr_t bus_addr,unsigned long flags)124421d1fe7eSSimon Glass phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t bus_addr,
124521d1fe7eSSimon Glass 			       unsigned long flags)
124621d1fe7eSSimon Glass {
124721d1fe7eSSimon Glass 	phys_addr_t phys_addr = 0;
124821d1fe7eSSimon Glass 	struct udevice *ctlr;
124921d1fe7eSSimon Glass 	int ret;
125021d1fe7eSSimon Glass 
125121d1fe7eSSimon Glass 	/* The root controller has the region information */
125221d1fe7eSSimon Glass 	ctlr = pci_get_controller(dev);
125321d1fe7eSSimon Glass 
125421d1fe7eSSimon Glass 	/*
125521d1fe7eSSimon Glass 	 * if PCI_REGION_MEM is set we do a two pass search with preference
125621d1fe7eSSimon Glass 	 * on matches that don't have PCI_REGION_SYS_MEMORY set
125721d1fe7eSSimon Glass 	 */
125821d1fe7eSSimon Glass 	if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) {
125921d1fe7eSSimon Glass 		ret = _dm_pci_bus_to_phys(ctlr, bus_addr,
126021d1fe7eSSimon Glass 					  flags, PCI_REGION_SYS_MEMORY,
126121d1fe7eSSimon Glass 					  &phys_addr);
126221d1fe7eSSimon Glass 		if (!ret)
126321d1fe7eSSimon Glass 			return phys_addr;
126421d1fe7eSSimon Glass 	}
126521d1fe7eSSimon Glass 
126621d1fe7eSSimon Glass 	ret = _dm_pci_bus_to_phys(ctlr, bus_addr, flags, 0, &phys_addr);
126721d1fe7eSSimon Glass 
126821d1fe7eSSimon Glass 	if (ret)
126921d1fe7eSSimon Glass 		puts("pci_hose_bus_to_phys: invalid physical address\n");
127021d1fe7eSSimon Glass 
127121d1fe7eSSimon Glass 	return phys_addr;
127221d1fe7eSSimon Glass }
127321d1fe7eSSimon Glass 
_dm_pci_phys_to_bus(struct udevice * dev,phys_addr_t phys_addr,unsigned long flags,unsigned long skip_mask,pci_addr_t * ba)127421d1fe7eSSimon Glass int _dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr,
127521d1fe7eSSimon Glass 			unsigned long flags, unsigned long skip_mask,
127621d1fe7eSSimon Glass 			pci_addr_t *ba)
127721d1fe7eSSimon Glass {
127821d1fe7eSSimon Glass 	struct pci_region *res;
127921d1fe7eSSimon Glass 	struct udevice *ctlr;
128021d1fe7eSSimon Glass 	pci_addr_t bus_addr;
128121d1fe7eSSimon Glass 	int i;
128221d1fe7eSSimon Glass 	struct pci_controller *hose;
128321d1fe7eSSimon Glass 
128421d1fe7eSSimon Glass 	/* The root controller has the region information */
128521d1fe7eSSimon Glass 	ctlr = pci_get_controller(dev);
128621d1fe7eSSimon Glass 	hose = dev_get_uclass_priv(ctlr);
128721d1fe7eSSimon Glass 
12886f95d89cSChristian Gmeiner 	if (hose->region_count == 0) {
12896f95d89cSChristian Gmeiner 		*ba = phys_addr;
12906f95d89cSChristian Gmeiner 		return 0;
12916f95d89cSChristian Gmeiner 	}
12926f95d89cSChristian Gmeiner 
129321d1fe7eSSimon Glass 	for (i = 0; i < hose->region_count; i++) {
129421d1fe7eSSimon Glass 		res = &hose->regions[i];
129521d1fe7eSSimon Glass 
129621d1fe7eSSimon Glass 		if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
129721d1fe7eSSimon Glass 			continue;
129821d1fe7eSSimon Glass 
129921d1fe7eSSimon Glass 		if (res->flags & skip_mask)
130021d1fe7eSSimon Glass 			continue;
130121d1fe7eSSimon Glass 
130221d1fe7eSSimon Glass 		bus_addr = phys_addr - res->phys_start + res->bus_start;
130321d1fe7eSSimon Glass 
130421d1fe7eSSimon Glass 		if (bus_addr >= res->bus_start &&
130521d1fe7eSSimon Glass 		    (bus_addr - res->bus_start) < res->size) {
130621d1fe7eSSimon Glass 			*ba = bus_addr;
130721d1fe7eSSimon Glass 			return 0;
130821d1fe7eSSimon Glass 		}
130921d1fe7eSSimon Glass 	}
131021d1fe7eSSimon Glass 
131121d1fe7eSSimon Glass 	return 1;
131221d1fe7eSSimon Glass }
131321d1fe7eSSimon Glass 
dm_pci_phys_to_bus(struct udevice * dev,phys_addr_t phys_addr,unsigned long flags)131421d1fe7eSSimon Glass pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr,
131521d1fe7eSSimon Glass 			      unsigned long flags)
131621d1fe7eSSimon Glass {
131721d1fe7eSSimon Glass 	pci_addr_t bus_addr = 0;
131821d1fe7eSSimon Glass 	int ret;
131921d1fe7eSSimon Glass 
132021d1fe7eSSimon Glass 	/*
132121d1fe7eSSimon Glass 	 * if PCI_REGION_MEM is set we do a two pass search with preference
132221d1fe7eSSimon Glass 	 * on matches that don't have PCI_REGION_SYS_MEMORY set
132321d1fe7eSSimon Glass 	 */
132421d1fe7eSSimon Glass 	if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) {
132521d1fe7eSSimon Glass 		ret = _dm_pci_phys_to_bus(dev, phys_addr, flags,
132621d1fe7eSSimon Glass 					  PCI_REGION_SYS_MEMORY, &bus_addr);
132721d1fe7eSSimon Glass 		if (!ret)
132821d1fe7eSSimon Glass 			return bus_addr;
132921d1fe7eSSimon Glass 	}
133021d1fe7eSSimon Glass 
133121d1fe7eSSimon Glass 	ret = _dm_pci_phys_to_bus(dev, phys_addr, flags, 0, &bus_addr);
133221d1fe7eSSimon Glass 
133321d1fe7eSSimon Glass 	if (ret)
133421d1fe7eSSimon Glass 		puts("pci_hose_phys_to_bus: invalid physical address\n");
133521d1fe7eSSimon Glass 
133621d1fe7eSSimon Glass 	return bus_addr;
133721d1fe7eSSimon Glass }
133821d1fe7eSSimon Glass 
dm_pci_map_bar(struct udevice * dev,int bar,int flags)133921d1fe7eSSimon Glass void *dm_pci_map_bar(struct udevice *dev, int bar, int flags)
134021d1fe7eSSimon Glass {
134121d1fe7eSSimon Glass 	pci_addr_t pci_bus_addr;
134221d1fe7eSSimon Glass 	u32 bar_response;
134321d1fe7eSSimon Glass 
134421d1fe7eSSimon Glass 	/* read BAR address */
134521d1fe7eSSimon Glass 	dm_pci_read_config32(dev, bar, &bar_response);
134621d1fe7eSSimon Glass 	pci_bus_addr = (pci_addr_t)(bar_response & ~0xf);
134721d1fe7eSSimon Glass 
134821d1fe7eSSimon Glass 	/*
134921d1fe7eSSimon Glass 	 * Pass "0" as the length argument to pci_bus_to_virt.  The arg
135021d1fe7eSSimon Glass 	 * isn't actualy used on any platform because u-boot assumes a static
135121d1fe7eSSimon Glass 	 * linear mapping.  In the future, this could read the BAR size
135221d1fe7eSSimon Glass 	 * and pass that as the size if needed.
135321d1fe7eSSimon Glass 	 */
135421d1fe7eSSimon Glass 	return dm_pci_bus_to_virt(dev, pci_bus_addr, flags, 0, MAP_NOCACHE);
135521d1fe7eSSimon Glass }
135621d1fe7eSSimon Glass 
_dm_pci_find_next_capability(struct udevice * dev,u8 pos,int cap)1357a8c5f8d3SBin Meng static int _dm_pci_find_next_capability(struct udevice *dev, u8 pos, int cap)
1358dac01fd8SBin Meng {
1359dac01fd8SBin Meng 	int ttl = PCI_FIND_CAP_TTL;
1360dac01fd8SBin Meng 	u8 id;
1361dac01fd8SBin Meng 	u16 ent;
1362dac01fd8SBin Meng 
1363dac01fd8SBin Meng 	dm_pci_read_config8(dev, pos, &pos);
1364a8c5f8d3SBin Meng 
1365dac01fd8SBin Meng 	while (ttl--) {
1366dac01fd8SBin Meng 		if (pos < PCI_STD_HEADER_SIZEOF)
1367dac01fd8SBin Meng 			break;
1368dac01fd8SBin Meng 		pos &= ~3;
1369dac01fd8SBin Meng 		dm_pci_read_config16(dev, pos, &ent);
1370dac01fd8SBin Meng 
1371dac01fd8SBin Meng 		id = ent & 0xff;
1372dac01fd8SBin Meng 		if (id == 0xff)
1373dac01fd8SBin Meng 			break;
1374dac01fd8SBin Meng 		if (id == cap)
1375dac01fd8SBin Meng 			return pos;
1376dac01fd8SBin Meng 		pos = (ent >> 8);
1377dac01fd8SBin Meng 	}
1378dac01fd8SBin Meng 
1379dac01fd8SBin Meng 	return 0;
1380dac01fd8SBin Meng }
1381dac01fd8SBin Meng 
dm_pci_find_next_capability(struct udevice * dev,u8 start,int cap)1382a8c5f8d3SBin Meng int dm_pci_find_next_capability(struct udevice *dev, u8 start, int cap)
1383a8c5f8d3SBin Meng {
1384a8c5f8d3SBin Meng 	return _dm_pci_find_next_capability(dev, start + PCI_CAP_LIST_NEXT,
1385a8c5f8d3SBin Meng 					    cap);
1386a8c5f8d3SBin Meng }
1387a8c5f8d3SBin Meng 
dm_pci_find_capability(struct udevice * dev,int cap)1388a8c5f8d3SBin Meng int dm_pci_find_capability(struct udevice *dev, int cap)
1389a8c5f8d3SBin Meng {
1390a8c5f8d3SBin Meng 	u16 status;
1391a8c5f8d3SBin Meng 	u8 header_type;
1392a8c5f8d3SBin Meng 	u8 pos;
1393a8c5f8d3SBin Meng 
1394a8c5f8d3SBin Meng 	dm_pci_read_config16(dev, PCI_STATUS, &status);
1395a8c5f8d3SBin Meng 	if (!(status & PCI_STATUS_CAP_LIST))
1396a8c5f8d3SBin Meng 		return 0;
1397a8c5f8d3SBin Meng 
1398a8c5f8d3SBin Meng 	dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type);
1399a8c5f8d3SBin Meng 	if ((header_type & 0x7f) == PCI_HEADER_TYPE_CARDBUS)
1400a8c5f8d3SBin Meng 		pos = PCI_CB_CAPABILITY_LIST;
1401a8c5f8d3SBin Meng 	else
1402a8c5f8d3SBin Meng 		pos = PCI_CAPABILITY_LIST;
1403a8c5f8d3SBin Meng 
1404a8c5f8d3SBin Meng 	return _dm_pci_find_next_capability(dev, pos, cap);
1405a8c5f8d3SBin Meng }
1406a8c5f8d3SBin Meng 
dm_pci_find_next_ext_capability(struct udevice * dev,int start,int cap)1407a8c5f8d3SBin Meng int dm_pci_find_next_ext_capability(struct udevice *dev, int start, int cap)
1408dac01fd8SBin Meng {
1409dac01fd8SBin Meng 	u32 header;
1410dac01fd8SBin Meng 	int ttl;
1411dac01fd8SBin Meng 	int pos = PCI_CFG_SPACE_SIZE;
1412dac01fd8SBin Meng 
1413dac01fd8SBin Meng 	/* minimum 8 bytes per capability */
1414dac01fd8SBin Meng 	ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
1415dac01fd8SBin Meng 
1416a8c5f8d3SBin Meng 	if (start)
1417a8c5f8d3SBin Meng 		pos = start;
1418a8c5f8d3SBin Meng 
1419dac01fd8SBin Meng 	dm_pci_read_config32(dev, pos, &header);
1420dac01fd8SBin Meng 	/*
1421dac01fd8SBin Meng 	 * If we have no capabilities, this is indicated by cap ID,
1422dac01fd8SBin Meng 	 * cap version and next pointer all being 0.
1423dac01fd8SBin Meng 	 */
1424dac01fd8SBin Meng 	if (header == 0)
1425dac01fd8SBin Meng 		return 0;
1426dac01fd8SBin Meng 
1427dac01fd8SBin Meng 	while (ttl--) {
1428dac01fd8SBin Meng 		if (PCI_EXT_CAP_ID(header) == cap)
1429dac01fd8SBin Meng 			return pos;
1430dac01fd8SBin Meng 
1431dac01fd8SBin Meng 		pos = PCI_EXT_CAP_NEXT(header);
1432dac01fd8SBin Meng 		if (pos < PCI_CFG_SPACE_SIZE)
1433dac01fd8SBin Meng 			break;
1434dac01fd8SBin Meng 
1435dac01fd8SBin Meng 		dm_pci_read_config32(dev, pos, &header);
1436dac01fd8SBin Meng 	}
1437dac01fd8SBin Meng 
1438dac01fd8SBin Meng 	return 0;
1439dac01fd8SBin Meng }
1440dac01fd8SBin Meng 
dm_pci_find_ext_capability(struct udevice * dev,int cap)1441a8c5f8d3SBin Meng int dm_pci_find_ext_capability(struct udevice *dev, int cap)
1442a8c5f8d3SBin Meng {
1443a8c5f8d3SBin Meng 	return dm_pci_find_next_ext_capability(dev, 0, cap);
1444a8c5f8d3SBin Meng }
1445a8c5f8d3SBin Meng 
1446ff3e077bSSimon Glass UCLASS_DRIVER(pci) = {
1447ff3e077bSSimon Glass 	.id		= UCLASS_PCI,
1448ff3e077bSSimon Glass 	.name		= "pci",
14492bb02e4fSSimon Glass 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
145091195485SSimon Glass 	.post_bind	= dm_scan_fdt_dev,
1451ff3e077bSSimon Glass 	.pre_probe	= pci_uclass_pre_probe,
1452ff3e077bSSimon Glass 	.post_probe	= pci_uclass_post_probe,
1453ff3e077bSSimon Glass 	.child_post_bind = pci_uclass_child_post_bind,
1454ff3e077bSSimon Glass 	.per_device_auto_alloc_size = sizeof(struct pci_controller),
1455ff3e077bSSimon Glass 	.per_child_platdata_auto_alloc_size =
1456ff3e077bSSimon Glass 			sizeof(struct pci_child_platdata),
1457ff3e077bSSimon Glass };
1458ff3e077bSSimon Glass 
1459ff3e077bSSimon Glass static const struct dm_pci_ops pci_bridge_ops = {
1460ff3e077bSSimon Glass 	.read_config	= pci_bridge_read_config,
1461ff3e077bSSimon Glass 	.write_config	= pci_bridge_write_config,
1462ff3e077bSSimon Glass };
1463ff3e077bSSimon Glass 
1464ff3e077bSSimon Glass static const struct udevice_id pci_bridge_ids[] = {
1465ff3e077bSSimon Glass 	{ .compatible = "pci-bridge" },
1466ff3e077bSSimon Glass 	{ }
1467ff3e077bSSimon Glass };
1468ff3e077bSSimon Glass 
1469ff3e077bSSimon Glass U_BOOT_DRIVER(pci_bridge_drv) = {
1470ff3e077bSSimon Glass 	.name		= "pci_bridge_drv",
1471ff3e077bSSimon Glass 	.id		= UCLASS_PCI,
1472ff3e077bSSimon Glass 	.of_match	= pci_bridge_ids,
1473ff3e077bSSimon Glass 	.ops		= &pci_bridge_ops,
1474ff3e077bSSimon Glass };
1475ff3e077bSSimon Glass 
1476ff3e077bSSimon Glass UCLASS_DRIVER(pci_generic) = {
1477ff3e077bSSimon Glass 	.id		= UCLASS_PCI_GENERIC,
1478ff3e077bSSimon Glass 	.name		= "pci_generic",
1479ff3e077bSSimon Glass };
1480ff3e077bSSimon Glass 
1481ff3e077bSSimon Glass static const struct udevice_id pci_generic_ids[] = {
1482ff3e077bSSimon Glass 	{ .compatible = "pci-generic" },
1483ff3e077bSSimon Glass 	{ }
1484ff3e077bSSimon Glass };
1485ff3e077bSSimon Glass 
1486ff3e077bSSimon Glass U_BOOT_DRIVER(pci_generic_drv) = {
1487ff3e077bSSimon Glass 	.name		= "pci_generic_drv",
1488ff3e077bSSimon Glass 	.id		= UCLASS_PCI_GENERIC,
1489ff3e077bSSimon Glass 	.of_match	= pci_generic_ids,
1490ff3e077bSSimon Glass };
1491e578b92cSStephen Warren 
pci_init(void)1492e578b92cSStephen Warren void pci_init(void)
1493e578b92cSStephen Warren {
1494e578b92cSStephen Warren 	struct udevice *bus;
1495e578b92cSStephen Warren 
1496e578b92cSStephen Warren 	/*
1497e578b92cSStephen Warren 	 * Enumerate all known controller devices. Enumeration has the side-
1498e578b92cSStephen Warren 	 * effect of probing them, so PCIe devices will be enumerated too.
1499e578b92cSStephen Warren 	 */
1500e578b92cSStephen Warren 	for (uclass_first_device(UCLASS_PCI, &bus);
1501e578b92cSStephen Warren 	     bus;
1502e578b92cSStephen Warren 	     uclass_next_device(&bus)) {
1503e578b92cSStephen Warren 		;
1504e578b92cSStephen Warren 	}
1505e578b92cSStephen Warren }
1506