xref: /rk3399_rockchip-uboot/drivers/pci/pci-uclass.c (revision 0367bd4d605fa17b0e8ee8b45bc7afa6bd2307f9)
1ff3e077bSSimon Glass /*
2ff3e077bSSimon Glass  * Copyright (c) 2014 Google, Inc
3ff3e077bSSimon Glass  * Written by Simon Glass <sjg@chromium.org>
4ff3e077bSSimon Glass  *
5ff3e077bSSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
6ff3e077bSSimon Glass  */
7ff3e077bSSimon Glass 
8ff3e077bSSimon Glass #include <common.h>
9ff3e077bSSimon Glass #include <dm.h>
10ff3e077bSSimon Glass #include <errno.h>
11ff3e077bSSimon Glass #include <fdtdec.h>
12ff3e077bSSimon Glass #include <inttypes.h>
13ff3e077bSSimon Glass #include <pci.h>
1421d1fe7eSSimon Glass #include <asm/io.h>
15ff3e077bSSimon Glass #include <dm/lists.h>
16ff3e077bSSimon Glass #include <dm/device-internal.h>
17348b744bSBin Meng #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
18348b744bSBin Meng #include <asm/fsp/fsp_support.h>
19348b744bSBin Meng #endif
205e23b8b4SSimon Glass #include "pci_internal.h"
21ff3e077bSSimon Glass 
22ff3e077bSSimon Glass DECLARE_GLOBAL_DATA_PTR;
23ff3e077bSSimon Glass 
24a6eb93b3SSimon Glass int pci_get_bus(int busnum, struct udevice **busp)
25983c6ba2SSimon Glass {
26983c6ba2SSimon Glass 	int ret;
27983c6ba2SSimon Glass 
28983c6ba2SSimon Glass 	ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, busp);
29983c6ba2SSimon Glass 
30983c6ba2SSimon Glass 	/* Since buses may not be numbered yet try a little harder with bus 0 */
31983c6ba2SSimon Glass 	if (ret == -ENODEV) {
323f603cbbSSimon Glass 		ret = uclass_first_device_err(UCLASS_PCI, busp);
33983c6ba2SSimon Glass 		if (ret)
34983c6ba2SSimon Glass 			return ret;
35983c6ba2SSimon Glass 		ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, busp);
36983c6ba2SSimon Glass 	}
37983c6ba2SSimon Glass 
38983c6ba2SSimon Glass 	return ret;
39983c6ba2SSimon Glass }
40983c6ba2SSimon Glass 
419f60fb0dSSimon Glass struct udevice *pci_get_controller(struct udevice *dev)
429f60fb0dSSimon Glass {
439f60fb0dSSimon Glass 	while (device_is_on_pci_bus(dev))
449f60fb0dSSimon Glass 		dev = dev->parent;
459f60fb0dSSimon Glass 
469f60fb0dSSimon Glass 	return dev;
479f60fb0dSSimon Glass }
489f60fb0dSSimon Glass 
4921ccce1bSSimon Glass pci_dev_t dm_pci_get_bdf(struct udevice *dev)
504b515e4fSSimon Glass {
514b515e4fSSimon Glass 	struct pci_child_platdata *pplat = dev_get_parent_platdata(dev);
524b515e4fSSimon Glass 	struct udevice *bus = dev->parent;
534b515e4fSSimon Glass 
544b515e4fSSimon Glass 	return PCI_ADD_BUS(bus->seq, pplat->devfn);
554b515e4fSSimon Glass }
564b515e4fSSimon Glass 
57ff3e077bSSimon Glass /**
58ff3e077bSSimon Glass  * pci_get_bus_max() - returns the bus number of the last active bus
59ff3e077bSSimon Glass  *
60ff3e077bSSimon Glass  * @return last bus number, or -1 if no active buses
61ff3e077bSSimon Glass  */
62ff3e077bSSimon Glass static int pci_get_bus_max(void)
63ff3e077bSSimon Glass {
64ff3e077bSSimon Glass 	struct udevice *bus;
65ff3e077bSSimon Glass 	struct uclass *uc;
66ff3e077bSSimon Glass 	int ret = -1;
67ff3e077bSSimon Glass 
68ff3e077bSSimon Glass 	ret = uclass_get(UCLASS_PCI, &uc);
69ff3e077bSSimon Glass 	uclass_foreach_dev(bus, uc) {
70ff3e077bSSimon Glass 		if (bus->seq > ret)
71ff3e077bSSimon Glass 			ret = bus->seq;
72ff3e077bSSimon Glass 	}
73ff3e077bSSimon Glass 
74ff3e077bSSimon Glass 	debug("%s: ret=%d\n", __func__, ret);
75ff3e077bSSimon Glass 
76ff3e077bSSimon Glass 	return ret;
77ff3e077bSSimon Glass }
78ff3e077bSSimon Glass 
79ff3e077bSSimon Glass int pci_last_busno(void)
80ff3e077bSSimon Glass {
81069155cbSBin Meng 	return pci_get_bus_max();
82ff3e077bSSimon Glass }
83ff3e077bSSimon Glass 
84ff3e077bSSimon Glass int pci_get_ff(enum pci_size_t size)
85ff3e077bSSimon Glass {
86ff3e077bSSimon Glass 	switch (size) {
87ff3e077bSSimon Glass 	case PCI_SIZE_8:
88ff3e077bSSimon Glass 		return 0xff;
89ff3e077bSSimon Glass 	case PCI_SIZE_16:
90ff3e077bSSimon Glass 		return 0xffff;
91ff3e077bSSimon Glass 	default:
92ff3e077bSSimon Glass 		return 0xffffffff;
93ff3e077bSSimon Glass 	}
94ff3e077bSSimon Glass }
95ff3e077bSSimon Glass 
96ff3e077bSSimon Glass int pci_bus_find_devfn(struct udevice *bus, pci_dev_t find_devfn,
97ff3e077bSSimon Glass 		       struct udevice **devp)
98ff3e077bSSimon Glass {
99ff3e077bSSimon Glass 	struct udevice *dev;
100ff3e077bSSimon Glass 
101ff3e077bSSimon Glass 	for (device_find_first_child(bus, &dev);
102ff3e077bSSimon Glass 	     dev;
103ff3e077bSSimon Glass 	     device_find_next_child(&dev)) {
104ff3e077bSSimon Glass 		struct pci_child_platdata *pplat;
105ff3e077bSSimon Glass 
106ff3e077bSSimon Glass 		pplat = dev_get_parent_platdata(dev);
107ff3e077bSSimon Glass 		if (pplat && pplat->devfn == find_devfn) {
108ff3e077bSSimon Glass 			*devp = dev;
109ff3e077bSSimon Glass 			return 0;
110ff3e077bSSimon Glass 		}
111ff3e077bSSimon Glass 	}
112ff3e077bSSimon Glass 
113ff3e077bSSimon Glass 	return -ENODEV;
114ff3e077bSSimon Glass }
115ff3e077bSSimon Glass 
116f3f1faefSSimon Glass int dm_pci_bus_find_bdf(pci_dev_t bdf, struct udevice **devp)
117ff3e077bSSimon Glass {
118ff3e077bSSimon Glass 	struct udevice *bus;
119ff3e077bSSimon Glass 	int ret;
120ff3e077bSSimon Glass 
121983c6ba2SSimon Glass 	ret = pci_get_bus(PCI_BUS(bdf), &bus);
122ff3e077bSSimon Glass 	if (ret)
123ff3e077bSSimon Glass 		return ret;
124ff3e077bSSimon Glass 	return pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), devp);
125ff3e077bSSimon Glass }
126ff3e077bSSimon Glass 
127ff3e077bSSimon Glass static int pci_device_matches_ids(struct udevice *dev,
128ff3e077bSSimon Glass 				  struct pci_device_id *ids)
129ff3e077bSSimon Glass {
130ff3e077bSSimon Glass 	struct pci_child_platdata *pplat;
131ff3e077bSSimon Glass 	int i;
132ff3e077bSSimon Glass 
133ff3e077bSSimon Glass 	pplat = dev_get_parent_platdata(dev);
134ff3e077bSSimon Glass 	if (!pplat)
135ff3e077bSSimon Glass 		return -EINVAL;
136ff3e077bSSimon Glass 	for (i = 0; ids[i].vendor != 0; i++) {
137ff3e077bSSimon Glass 		if (pplat->vendor == ids[i].vendor &&
138ff3e077bSSimon Glass 		    pplat->device == ids[i].device)
139ff3e077bSSimon Glass 			return i;
140ff3e077bSSimon Glass 	}
141ff3e077bSSimon Glass 
142ff3e077bSSimon Glass 	return -EINVAL;
143ff3e077bSSimon Glass }
144ff3e077bSSimon Glass 
145ff3e077bSSimon Glass int pci_bus_find_devices(struct udevice *bus, struct pci_device_id *ids,
146ff3e077bSSimon Glass 			 int *indexp, struct udevice **devp)
147ff3e077bSSimon Glass {
148ff3e077bSSimon Glass 	struct udevice *dev;
149ff3e077bSSimon Glass 
150ff3e077bSSimon Glass 	/* Scan all devices on this bus */
151ff3e077bSSimon Glass 	for (device_find_first_child(bus, &dev);
152ff3e077bSSimon Glass 	     dev;
153ff3e077bSSimon Glass 	     device_find_next_child(&dev)) {
154ff3e077bSSimon Glass 		if (pci_device_matches_ids(dev, ids) >= 0) {
155ff3e077bSSimon Glass 			if ((*indexp)-- <= 0) {
156ff3e077bSSimon Glass 				*devp = dev;
157ff3e077bSSimon Glass 				return 0;
158ff3e077bSSimon Glass 			}
159ff3e077bSSimon Glass 		}
160ff3e077bSSimon Glass 	}
161ff3e077bSSimon Glass 
162ff3e077bSSimon Glass 	return -ENODEV;
163ff3e077bSSimon Glass }
164ff3e077bSSimon Glass 
165ff3e077bSSimon Glass int pci_find_device_id(struct pci_device_id *ids, int index,
166ff3e077bSSimon Glass 		       struct udevice **devp)
167ff3e077bSSimon Glass {
168ff3e077bSSimon Glass 	struct udevice *bus;
169ff3e077bSSimon Glass 
170ff3e077bSSimon Glass 	/* Scan all known buses */
171ff3e077bSSimon Glass 	for (uclass_first_device(UCLASS_PCI, &bus);
172ff3e077bSSimon Glass 	     bus;
173ff3e077bSSimon Glass 	     uclass_next_device(&bus)) {
174ff3e077bSSimon Glass 		if (!pci_bus_find_devices(bus, ids, &index, devp))
175ff3e077bSSimon Glass 			return 0;
176ff3e077bSSimon Glass 	}
177ff3e077bSSimon Glass 	*devp = NULL;
178ff3e077bSSimon Glass 
179ff3e077bSSimon Glass 	return -ENODEV;
180ff3e077bSSimon Glass }
181ff3e077bSSimon Glass 
1825c0bf647SSimon Glass static int dm_pci_bus_find_device(struct udevice *bus, unsigned int vendor,
1835c0bf647SSimon Glass 				  unsigned int device, int *indexp,
1845c0bf647SSimon Glass 				  struct udevice **devp)
1855c0bf647SSimon Glass {
1865c0bf647SSimon Glass 	struct pci_child_platdata *pplat;
1875c0bf647SSimon Glass 	struct udevice *dev;
1885c0bf647SSimon Glass 
1895c0bf647SSimon Glass 	for (device_find_first_child(bus, &dev);
1905c0bf647SSimon Glass 	     dev;
1915c0bf647SSimon Glass 	     device_find_next_child(&dev)) {
1925c0bf647SSimon Glass 		pplat = dev_get_parent_platdata(dev);
1935c0bf647SSimon Glass 		if (pplat->vendor == vendor && pplat->device == device) {
1945c0bf647SSimon Glass 			if (!(*indexp)--) {
1955c0bf647SSimon Glass 				*devp = dev;
1965c0bf647SSimon Glass 				return 0;
1975c0bf647SSimon Glass 			}
1985c0bf647SSimon Glass 		}
1995c0bf647SSimon Glass 	}
2005c0bf647SSimon Glass 
2015c0bf647SSimon Glass 	return -ENODEV;
2025c0bf647SSimon Glass }
2035c0bf647SSimon Glass 
2045c0bf647SSimon Glass int dm_pci_find_device(unsigned int vendor, unsigned int device, int index,
2055c0bf647SSimon Glass 		       struct udevice **devp)
2065c0bf647SSimon Glass {
2075c0bf647SSimon Glass 	struct udevice *bus;
2085c0bf647SSimon Glass 
2095c0bf647SSimon Glass 	/* Scan all known buses */
2105c0bf647SSimon Glass 	for (uclass_first_device(UCLASS_PCI, &bus);
2115c0bf647SSimon Glass 	     bus;
2125c0bf647SSimon Glass 	     uclass_next_device(&bus)) {
2135c0bf647SSimon Glass 		if (!dm_pci_bus_find_device(bus, vendor, device, &index, devp))
2145c0bf647SSimon Glass 			return device_probe(*devp);
2155c0bf647SSimon Glass 	}
2165c0bf647SSimon Glass 	*devp = NULL;
2175c0bf647SSimon Glass 
2185c0bf647SSimon Glass 	return -ENODEV;
2195c0bf647SSimon Glass }
2205c0bf647SSimon Glass 
221a0eb8356SSimon Glass int dm_pci_find_class(uint find_class, int index, struct udevice **devp)
222a0eb8356SSimon Glass {
223a0eb8356SSimon Glass 	struct udevice *dev;
224a0eb8356SSimon Glass 
225a0eb8356SSimon Glass 	/* Scan all known buses */
226a0eb8356SSimon Glass 	for (pci_find_first_device(&dev);
227a0eb8356SSimon Glass 	     dev;
228a0eb8356SSimon Glass 	     pci_find_next_device(&dev)) {
229a0eb8356SSimon Glass 		struct pci_child_platdata *pplat = dev_get_parent_platdata(dev);
230a0eb8356SSimon Glass 
231a0eb8356SSimon Glass 		if (pplat->class == find_class && !index--) {
232a0eb8356SSimon Glass 			*devp = dev;
233a0eb8356SSimon Glass 			return device_probe(*devp);
234a0eb8356SSimon Glass 		}
235a0eb8356SSimon Glass 	}
236a0eb8356SSimon Glass 	*devp = NULL;
237a0eb8356SSimon Glass 
238a0eb8356SSimon Glass 	return -ENODEV;
239a0eb8356SSimon Glass }
240a0eb8356SSimon Glass 
241ff3e077bSSimon Glass int pci_bus_write_config(struct udevice *bus, pci_dev_t bdf, int offset,
242ff3e077bSSimon Glass 			 unsigned long value, enum pci_size_t size)
243ff3e077bSSimon Glass {
244ff3e077bSSimon Glass 	struct dm_pci_ops *ops;
245ff3e077bSSimon Glass 
246ff3e077bSSimon Glass 	ops = pci_get_ops(bus);
247ff3e077bSSimon Glass 	if (!ops->write_config)
248ff3e077bSSimon Glass 		return -ENOSYS;
249ff3e077bSSimon Glass 	return ops->write_config(bus, bdf, offset, value, size);
250ff3e077bSSimon Glass }
251ff3e077bSSimon Glass 
252319dba1fSSimon Glass int pci_bus_clrset_config32(struct udevice *bus, pci_dev_t bdf, int offset,
253319dba1fSSimon Glass 			    u32 clr, u32 set)
254319dba1fSSimon Glass {
255319dba1fSSimon Glass 	ulong val;
256319dba1fSSimon Glass 	int ret;
257319dba1fSSimon Glass 
258319dba1fSSimon Glass 	ret = pci_bus_read_config(bus, bdf, offset, &val, PCI_SIZE_32);
259319dba1fSSimon Glass 	if (ret)
260319dba1fSSimon Glass 		return ret;
261319dba1fSSimon Glass 	val &= ~clr;
262319dba1fSSimon Glass 	val |= set;
263319dba1fSSimon Glass 
264319dba1fSSimon Glass 	return pci_bus_write_config(bus, bdf, offset, val, PCI_SIZE_32);
265319dba1fSSimon Glass }
266319dba1fSSimon Glass 
267ff3e077bSSimon Glass int pci_write_config(pci_dev_t bdf, int offset, unsigned long value,
268ff3e077bSSimon Glass 		     enum pci_size_t size)
269ff3e077bSSimon Glass {
270ff3e077bSSimon Glass 	struct udevice *bus;
271ff3e077bSSimon Glass 	int ret;
272ff3e077bSSimon Glass 
273983c6ba2SSimon Glass 	ret = pci_get_bus(PCI_BUS(bdf), &bus);
274ff3e077bSSimon Glass 	if (ret)
275ff3e077bSSimon Glass 		return ret;
276ff3e077bSSimon Glass 
2774d8615cbSBin Meng 	return pci_bus_write_config(bus, bdf, offset, value, size);
278ff3e077bSSimon Glass }
279ff3e077bSSimon Glass 
28066afb4edSSimon Glass int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value,
28166afb4edSSimon Glass 			enum pci_size_t size)
28266afb4edSSimon Glass {
28366afb4edSSimon Glass 	struct udevice *bus;
28466afb4edSSimon Glass 
2851e0f2263SBin Meng 	for (bus = dev; device_is_on_pci_bus(bus);)
28666afb4edSSimon Glass 		bus = bus->parent;
28721ccce1bSSimon Glass 	return pci_bus_write_config(bus, dm_pci_get_bdf(dev), offset, value,
28821ccce1bSSimon Glass 				    size);
28966afb4edSSimon Glass }
29066afb4edSSimon Glass 
291ff3e077bSSimon Glass int pci_write_config32(pci_dev_t bdf, int offset, u32 value)
292ff3e077bSSimon Glass {
293ff3e077bSSimon Glass 	return pci_write_config(bdf, offset, value, PCI_SIZE_32);
294ff3e077bSSimon Glass }
295ff3e077bSSimon Glass 
296ff3e077bSSimon Glass int pci_write_config16(pci_dev_t bdf, int offset, u16 value)
297ff3e077bSSimon Glass {
298ff3e077bSSimon Glass 	return pci_write_config(bdf, offset, value, PCI_SIZE_16);
299ff3e077bSSimon Glass }
300ff3e077bSSimon Glass 
301ff3e077bSSimon Glass int pci_write_config8(pci_dev_t bdf, int offset, u8 value)
302ff3e077bSSimon Glass {
303ff3e077bSSimon Glass 	return pci_write_config(bdf, offset, value, PCI_SIZE_8);
304ff3e077bSSimon Glass }
305ff3e077bSSimon Glass 
30666afb4edSSimon Glass int dm_pci_write_config8(struct udevice *dev, int offset, u8 value)
30766afb4edSSimon Glass {
30866afb4edSSimon Glass 	return dm_pci_write_config(dev, offset, value, PCI_SIZE_8);
30966afb4edSSimon Glass }
31066afb4edSSimon Glass 
31166afb4edSSimon Glass int dm_pci_write_config16(struct udevice *dev, int offset, u16 value)
31266afb4edSSimon Glass {
31366afb4edSSimon Glass 	return dm_pci_write_config(dev, offset, value, PCI_SIZE_16);
31466afb4edSSimon Glass }
31566afb4edSSimon Glass 
31666afb4edSSimon Glass int dm_pci_write_config32(struct udevice *dev, int offset, u32 value)
31766afb4edSSimon Glass {
31866afb4edSSimon Glass 	return dm_pci_write_config(dev, offset, value, PCI_SIZE_32);
31966afb4edSSimon Glass }
32066afb4edSSimon Glass 
321ff3e077bSSimon Glass int pci_bus_read_config(struct udevice *bus, pci_dev_t bdf, int offset,
322ff3e077bSSimon Glass 			unsigned long *valuep, enum pci_size_t size)
323ff3e077bSSimon Glass {
324ff3e077bSSimon Glass 	struct dm_pci_ops *ops;
325ff3e077bSSimon Glass 
326ff3e077bSSimon Glass 	ops = pci_get_ops(bus);
327ff3e077bSSimon Glass 	if (!ops->read_config)
328ff3e077bSSimon Glass 		return -ENOSYS;
329ff3e077bSSimon Glass 	return ops->read_config(bus, bdf, offset, valuep, size);
330ff3e077bSSimon Glass }
331ff3e077bSSimon Glass 
332ff3e077bSSimon Glass int pci_read_config(pci_dev_t bdf, int offset, unsigned long *valuep,
333ff3e077bSSimon Glass 		    enum pci_size_t size)
334ff3e077bSSimon Glass {
335ff3e077bSSimon Glass 	struct udevice *bus;
336ff3e077bSSimon Glass 	int ret;
337ff3e077bSSimon Glass 
338983c6ba2SSimon Glass 	ret = pci_get_bus(PCI_BUS(bdf), &bus);
339ff3e077bSSimon Glass 	if (ret)
340ff3e077bSSimon Glass 		return ret;
341ff3e077bSSimon Glass 
3424d8615cbSBin Meng 	return pci_bus_read_config(bus, bdf, offset, valuep, size);
343ff3e077bSSimon Glass }
344ff3e077bSSimon Glass 
34566afb4edSSimon Glass int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep,
34666afb4edSSimon Glass 		       enum pci_size_t size)
34766afb4edSSimon Glass {
34866afb4edSSimon Glass 	struct udevice *bus;
34966afb4edSSimon Glass 
3501e0f2263SBin Meng 	for (bus = dev; device_is_on_pci_bus(bus);)
35166afb4edSSimon Glass 		bus = bus->parent;
35221ccce1bSSimon Glass 	return pci_bus_read_config(bus, dm_pci_get_bdf(dev), offset, valuep,
35366afb4edSSimon Glass 				   size);
35466afb4edSSimon Glass }
35566afb4edSSimon Glass 
356ff3e077bSSimon Glass int pci_read_config32(pci_dev_t bdf, int offset, u32 *valuep)
357ff3e077bSSimon Glass {
358ff3e077bSSimon Glass 	unsigned long value;
359ff3e077bSSimon Glass 	int ret;
360ff3e077bSSimon Glass 
361ff3e077bSSimon Glass 	ret = pci_read_config(bdf, offset, &value, PCI_SIZE_32);
362ff3e077bSSimon Glass 	if (ret)
363ff3e077bSSimon Glass 		return ret;
364ff3e077bSSimon Glass 	*valuep = value;
365ff3e077bSSimon Glass 
366ff3e077bSSimon Glass 	return 0;
367ff3e077bSSimon Glass }
368ff3e077bSSimon Glass 
369ff3e077bSSimon Glass int pci_read_config16(pci_dev_t bdf, int offset, u16 *valuep)
370ff3e077bSSimon Glass {
371ff3e077bSSimon Glass 	unsigned long value;
372ff3e077bSSimon Glass 	int ret;
373ff3e077bSSimon Glass 
374ff3e077bSSimon Glass 	ret = pci_read_config(bdf, offset, &value, PCI_SIZE_16);
375ff3e077bSSimon Glass 	if (ret)
376ff3e077bSSimon Glass 		return ret;
377ff3e077bSSimon Glass 	*valuep = value;
378ff3e077bSSimon Glass 
379ff3e077bSSimon Glass 	return 0;
380ff3e077bSSimon Glass }
381ff3e077bSSimon Glass 
382ff3e077bSSimon Glass int pci_read_config8(pci_dev_t bdf, int offset, u8 *valuep)
383ff3e077bSSimon Glass {
384ff3e077bSSimon Glass 	unsigned long value;
385ff3e077bSSimon Glass 	int ret;
386ff3e077bSSimon Glass 
387ff3e077bSSimon Glass 	ret = pci_read_config(bdf, offset, &value, PCI_SIZE_8);
388ff3e077bSSimon Glass 	if (ret)
389ff3e077bSSimon Glass 		return ret;
390ff3e077bSSimon Glass 	*valuep = value;
391ff3e077bSSimon Glass 
392ff3e077bSSimon Glass 	return 0;
393ff3e077bSSimon Glass }
394ff3e077bSSimon Glass 
39566afb4edSSimon Glass int dm_pci_read_config8(struct udevice *dev, int offset, u8 *valuep)
39666afb4edSSimon Glass {
39766afb4edSSimon Glass 	unsigned long value;
39866afb4edSSimon Glass 	int ret;
39966afb4edSSimon Glass 
40066afb4edSSimon Glass 	ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_8);
40166afb4edSSimon Glass 	if (ret)
40266afb4edSSimon Glass 		return ret;
40366afb4edSSimon Glass 	*valuep = value;
40466afb4edSSimon Glass 
40566afb4edSSimon Glass 	return 0;
40666afb4edSSimon Glass }
40766afb4edSSimon Glass 
40866afb4edSSimon Glass int dm_pci_read_config16(struct udevice *dev, int offset, u16 *valuep)
40966afb4edSSimon Glass {
41066afb4edSSimon Glass 	unsigned long value;
41166afb4edSSimon Glass 	int ret;
41266afb4edSSimon Glass 
41366afb4edSSimon Glass 	ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_16);
41466afb4edSSimon Glass 	if (ret)
41566afb4edSSimon Glass 		return ret;
41666afb4edSSimon Glass 	*valuep = value;
41766afb4edSSimon Glass 
41866afb4edSSimon Glass 	return 0;
41966afb4edSSimon Glass }
42066afb4edSSimon Glass 
42166afb4edSSimon Glass int dm_pci_read_config32(struct udevice *dev, int offset, u32 *valuep)
42266afb4edSSimon Glass {
42366afb4edSSimon Glass 	unsigned long value;
42466afb4edSSimon Glass 	int ret;
42566afb4edSSimon Glass 
42666afb4edSSimon Glass 	ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_32);
42766afb4edSSimon Glass 	if (ret)
42866afb4edSSimon Glass 		return ret;
42966afb4edSSimon Glass 	*valuep = value;
43066afb4edSSimon Glass 
43166afb4edSSimon Glass 	return 0;
43266afb4edSSimon Glass }
43366afb4edSSimon Glass 
434319dba1fSSimon Glass int dm_pci_clrset_config8(struct udevice *dev, int offset, u32 clr, u32 set)
435319dba1fSSimon Glass {
436319dba1fSSimon Glass 	u8 val;
437319dba1fSSimon Glass 	int ret;
438319dba1fSSimon Glass 
439319dba1fSSimon Glass 	ret = dm_pci_read_config8(dev, offset, &val);
440319dba1fSSimon Glass 	if (ret)
441319dba1fSSimon Glass 		return ret;
442319dba1fSSimon Glass 	val &= ~clr;
443319dba1fSSimon Glass 	val |= set;
444319dba1fSSimon Glass 
445319dba1fSSimon Glass 	return dm_pci_write_config8(dev, offset, val);
446319dba1fSSimon Glass }
447319dba1fSSimon Glass 
448319dba1fSSimon Glass int dm_pci_clrset_config16(struct udevice *dev, int offset, u32 clr, u32 set)
449319dba1fSSimon Glass {
450319dba1fSSimon Glass 	u16 val;
451319dba1fSSimon Glass 	int ret;
452319dba1fSSimon Glass 
453319dba1fSSimon Glass 	ret = dm_pci_read_config16(dev, offset, &val);
454319dba1fSSimon Glass 	if (ret)
455319dba1fSSimon Glass 		return ret;
456319dba1fSSimon Glass 	val &= ~clr;
457319dba1fSSimon Glass 	val |= set;
458319dba1fSSimon Glass 
459319dba1fSSimon Glass 	return dm_pci_write_config16(dev, offset, val);
460319dba1fSSimon Glass }
461319dba1fSSimon Glass 
462319dba1fSSimon Glass int dm_pci_clrset_config32(struct udevice *dev, int offset, u32 clr, u32 set)
463319dba1fSSimon Glass {
464319dba1fSSimon Glass 	u32 val;
465319dba1fSSimon Glass 	int ret;
466319dba1fSSimon Glass 
467319dba1fSSimon Glass 	ret = dm_pci_read_config32(dev, offset, &val);
468319dba1fSSimon Glass 	if (ret)
469319dba1fSSimon Glass 		return ret;
470319dba1fSSimon Glass 	val &= ~clr;
471319dba1fSSimon Glass 	val |= set;
472319dba1fSSimon Glass 
473319dba1fSSimon Glass 	return dm_pci_write_config32(dev, offset, val);
474319dba1fSSimon Glass }
475319dba1fSSimon Glass 
476bbbcb526SBin Meng static void set_vga_bridge_bits(struct udevice *dev)
477bbbcb526SBin Meng {
478bbbcb526SBin Meng 	struct udevice *parent = dev->parent;
479bbbcb526SBin Meng 	u16 bc;
480bbbcb526SBin Meng 
481bbbcb526SBin Meng 	while (parent->seq != 0) {
482bbbcb526SBin Meng 		dm_pci_read_config16(parent, PCI_BRIDGE_CONTROL, &bc);
483bbbcb526SBin Meng 		bc |= PCI_BRIDGE_CTL_VGA;
484bbbcb526SBin Meng 		dm_pci_write_config16(parent, PCI_BRIDGE_CONTROL, bc);
485bbbcb526SBin Meng 		parent = parent->parent;
486bbbcb526SBin Meng 	}
487bbbcb526SBin Meng }
488bbbcb526SBin Meng 
489ff3e077bSSimon Glass int pci_auto_config_devices(struct udevice *bus)
490ff3e077bSSimon Glass {
491ff3e077bSSimon Glass 	struct pci_controller *hose = bus->uclass_priv;
492bbbcb526SBin Meng 	struct pci_child_platdata *pplat;
493ff3e077bSSimon Glass 	unsigned int sub_bus;
494ff3e077bSSimon Glass 	struct udevice *dev;
495ff3e077bSSimon Glass 	int ret;
496ff3e077bSSimon Glass 
497ff3e077bSSimon Glass 	sub_bus = bus->seq;
498ff3e077bSSimon Glass 	debug("%s: start\n", __func__);
499ff3e077bSSimon Glass 	pciauto_config_init(hose);
500ff3e077bSSimon Glass 	for (ret = device_find_first_child(bus, &dev);
501ff3e077bSSimon Glass 	     !ret && dev;
502ff3e077bSSimon Glass 	     ret = device_find_next_child(&dev)) {
503ff3e077bSSimon Glass 		unsigned int max_bus;
5044d21455eSSimon Glass 		int ret;
505ff3e077bSSimon Glass 
506ff3e077bSSimon Glass 		debug("%s: device %s\n", __func__, dev->name);
5075e23b8b4SSimon Glass 		ret = dm_pciauto_config_device(dev);
5084d21455eSSimon Glass 		if (ret < 0)
5094d21455eSSimon Glass 			return ret;
5104d21455eSSimon Glass 		max_bus = ret;
511ff3e077bSSimon Glass 		sub_bus = max(sub_bus, max_bus);
512bbbcb526SBin Meng 
513bbbcb526SBin Meng 		pplat = dev_get_parent_platdata(dev);
514bbbcb526SBin Meng 		if (pplat->class == (PCI_CLASS_DISPLAY_VGA << 8))
515bbbcb526SBin Meng 			set_vga_bridge_bits(dev);
516ff3e077bSSimon Glass 	}
517ff3e077bSSimon Glass 	debug("%s: done\n", __func__);
518ff3e077bSSimon Glass 
519ff3e077bSSimon Glass 	return sub_bus;
520ff3e077bSSimon Glass }
521ff3e077bSSimon Glass 
5225e23b8b4SSimon Glass int dm_pci_hose_probe_bus(struct udevice *bus)
523ff3e077bSSimon Glass {
524ff3e077bSSimon Glass 	int sub_bus;
525ff3e077bSSimon Glass 	int ret;
526ff3e077bSSimon Glass 
527ff3e077bSSimon Glass 	debug("%s\n", __func__);
528ff3e077bSSimon Glass 
529ff3e077bSSimon Glass 	sub_bus = pci_get_bus_max() + 1;
530ff3e077bSSimon Glass 	debug("%s: bus = %d/%s\n", __func__, sub_bus, bus->name);
5315e23b8b4SSimon Glass 	dm_pciauto_prescan_setup_bridge(bus, sub_bus);
532ff3e077bSSimon Glass 
533ff3e077bSSimon Glass 	ret = device_probe(bus);
534ff3e077bSSimon Glass 	if (ret) {
5353129ace4SSimon Glass 		debug("%s: Cannot probe bus %s: %d\n", __func__, bus->name,
536ff3e077bSSimon Glass 		      ret);
537ff3e077bSSimon Glass 		return ret;
538ff3e077bSSimon Glass 	}
539ff3e077bSSimon Glass 	if (sub_bus != bus->seq) {
540ff3e077bSSimon Glass 		printf("%s: Internal error, bus '%s' got seq %d, expected %d\n",
541ff3e077bSSimon Glass 		       __func__, bus->name, bus->seq, sub_bus);
542ff3e077bSSimon Glass 		return -EPIPE;
543ff3e077bSSimon Glass 	}
544ff3e077bSSimon Glass 	sub_bus = pci_get_bus_max();
5455e23b8b4SSimon Glass 	dm_pciauto_postscan_setup_bridge(bus, sub_bus);
546ff3e077bSSimon Glass 
547ff3e077bSSimon Glass 	return sub_bus;
548ff3e077bSSimon Glass }
549ff3e077bSSimon Glass 
550aba92962SSimon Glass /**
551aba92962SSimon Glass  * pci_match_one_device - Tell if a PCI device structure has a matching
552aba92962SSimon Glass  *                        PCI device id structure
553aba92962SSimon Glass  * @id: single PCI device id structure to match
554*0367bd4dSHou Zhiqiang  * @find: the PCI device id structure to match against
555aba92962SSimon Glass  *
556*0367bd4dSHou Zhiqiang  * Returns true if the finding pci_device_id structure matched or false if
557*0367bd4dSHou Zhiqiang  * there is no match.
558aba92962SSimon Glass  */
559aba92962SSimon Glass static bool pci_match_one_id(const struct pci_device_id *id,
560aba92962SSimon Glass 			     const struct pci_device_id *find)
561aba92962SSimon Glass {
562aba92962SSimon Glass 	if ((id->vendor == PCI_ANY_ID || id->vendor == find->vendor) &&
563aba92962SSimon Glass 	    (id->device == PCI_ANY_ID || id->device == find->device) &&
564aba92962SSimon Glass 	    (id->subvendor == PCI_ANY_ID || id->subvendor == find->subvendor) &&
565aba92962SSimon Glass 	    (id->subdevice == PCI_ANY_ID || id->subdevice == find->subdevice) &&
566aba92962SSimon Glass 	    !((id->class ^ find->class) & id->class_mask))
567aba92962SSimon Glass 		return true;
568aba92962SSimon Glass 
569aba92962SSimon Glass 	return false;
570aba92962SSimon Glass }
571aba92962SSimon Glass 
572aba92962SSimon Glass /**
573aba92962SSimon Glass  * pci_find_and_bind_driver() - Find and bind the right PCI driver
574aba92962SSimon Glass  *
575aba92962SSimon Glass  * This only looks at certain fields in the descriptor.
5765dbcf3a0SSimon Glass  *
5775dbcf3a0SSimon Glass  * @parent:	Parent bus
5785dbcf3a0SSimon Glass  * @find_id:	Specification of the driver to find
5795dbcf3a0SSimon Glass  * @bdf:	Bus/device/function addreess - see PCI_BDF()
5805dbcf3a0SSimon Glass  * @devp:	Returns a pointer to the device created
5815dbcf3a0SSimon Glass  * @return 0 if OK, -EPERM if the device is not needed before relocation and
5825dbcf3a0SSimon Glass  *	   therefore was not created, other -ve value on error
583aba92962SSimon Glass  */
584aba92962SSimon Glass static int pci_find_and_bind_driver(struct udevice *parent,
5855dbcf3a0SSimon Glass 				    struct pci_device_id *find_id,
5865dbcf3a0SSimon Glass 				    pci_dev_t bdf, struct udevice **devp)
587aba92962SSimon Glass {
588aba92962SSimon Glass 	struct pci_driver_entry *start, *entry;
589aba92962SSimon Glass 	const char *drv;
590aba92962SSimon Glass 	int n_ents;
591aba92962SSimon Glass 	int ret;
592aba92962SSimon Glass 	char name[30], *str;
59308fc7b8fSBin Meng 	bool bridge;
594aba92962SSimon Glass 
595aba92962SSimon Glass 	*devp = NULL;
596aba92962SSimon Glass 
597aba92962SSimon Glass 	debug("%s: Searching for driver: vendor=%x, device=%x\n", __func__,
598aba92962SSimon Glass 	      find_id->vendor, find_id->device);
599aba92962SSimon Glass 	start = ll_entry_start(struct pci_driver_entry, pci_driver_entry);
600aba92962SSimon Glass 	n_ents = ll_entry_count(struct pci_driver_entry, pci_driver_entry);
601aba92962SSimon Glass 	for (entry = start; entry != start + n_ents; entry++) {
602aba92962SSimon Glass 		const struct pci_device_id *id;
603aba92962SSimon Glass 		struct udevice *dev;
604aba92962SSimon Glass 		const struct driver *drv;
605aba92962SSimon Glass 
606aba92962SSimon Glass 		for (id = entry->match;
607aba92962SSimon Glass 		     id->vendor || id->subvendor || id->class_mask;
608aba92962SSimon Glass 		     id++) {
609aba92962SSimon Glass 			if (!pci_match_one_id(id, find_id))
610aba92962SSimon Glass 				continue;
611aba92962SSimon Glass 
612aba92962SSimon Glass 			drv = entry->driver;
61308fc7b8fSBin Meng 
61408fc7b8fSBin Meng 			/*
61508fc7b8fSBin Meng 			 * In the pre-relocation phase, we only bind devices
61608fc7b8fSBin Meng 			 * whose driver has the DM_FLAG_PRE_RELOC set, to save
61708fc7b8fSBin Meng 			 * precious memory space as on some platforms as that
61808fc7b8fSBin Meng 			 * space is pretty limited (ie: using Cache As RAM).
61908fc7b8fSBin Meng 			 */
62008fc7b8fSBin Meng 			if (!(gd->flags & GD_FLG_RELOC) &&
62108fc7b8fSBin Meng 			    !(drv->flags & DM_FLAG_PRE_RELOC))
6225dbcf3a0SSimon Glass 				return -EPERM;
62308fc7b8fSBin Meng 
624aba92962SSimon Glass 			/*
625aba92962SSimon Glass 			 * We could pass the descriptor to the driver as
626aba92962SSimon Glass 			 * platdata (instead of NULL) and allow its bind()
627aba92962SSimon Glass 			 * method to return -ENOENT if it doesn't support this
628aba92962SSimon Glass 			 * device. That way we could continue the search to
629aba92962SSimon Glass 			 * find another driver. For now this doesn't seem
630aba92962SSimon Glass 			 * necesssary, so just bind the first match.
631aba92962SSimon Glass 			 */
632aba92962SSimon Glass 			ret = device_bind(parent, drv, drv->name, NULL, -1,
633aba92962SSimon Glass 					  &dev);
634aba92962SSimon Glass 			if (ret)
635aba92962SSimon Glass 				goto error;
636aba92962SSimon Glass 			debug("%s: Match found: %s\n", __func__, drv->name);
637aba92962SSimon Glass 			dev->driver_data = find_id->driver_data;
638aba92962SSimon Glass 			*devp = dev;
639aba92962SSimon Glass 			return 0;
640aba92962SSimon Glass 		}
641aba92962SSimon Glass 	}
642aba92962SSimon Glass 
64308fc7b8fSBin Meng 	bridge = (find_id->class >> 8) == PCI_CLASS_BRIDGE_PCI;
64408fc7b8fSBin Meng 	/*
64508fc7b8fSBin Meng 	 * In the pre-relocation phase, we only bind bridge devices to save
64608fc7b8fSBin Meng 	 * precious memory space as on some platforms as that space is pretty
64708fc7b8fSBin Meng 	 * limited (ie: using Cache As RAM).
64808fc7b8fSBin Meng 	 */
64908fc7b8fSBin Meng 	if (!(gd->flags & GD_FLG_RELOC) && !bridge)
6505dbcf3a0SSimon Glass 		return -EPERM;
65108fc7b8fSBin Meng 
652aba92962SSimon Glass 	/* Bind a generic driver so that the device can be used */
6534d8615cbSBin Meng 	sprintf(name, "pci_%x:%x.%x", parent->seq, PCI_DEV(bdf),
6544d8615cbSBin Meng 		PCI_FUNC(bdf));
655aba92962SSimon Glass 	str = strdup(name);
656aba92962SSimon Glass 	if (!str)
657aba92962SSimon Glass 		return -ENOMEM;
65808fc7b8fSBin Meng 	drv = bridge ? "pci_bridge_drv" : "pci_generic_drv";
65908fc7b8fSBin Meng 
660aba92962SSimon Glass 	ret = device_bind_driver(parent, drv, str, devp);
661aba92962SSimon Glass 	if (ret) {
6623129ace4SSimon Glass 		debug("%s: Failed to bind generic driver: %d\n", __func__, ret);
663aba92962SSimon Glass 		return ret;
664aba92962SSimon Glass 	}
665aba92962SSimon Glass 	debug("%s: No match found: bound generic driver instead\n", __func__);
666aba92962SSimon Glass 
667aba92962SSimon Glass 	return 0;
668aba92962SSimon Glass 
669aba92962SSimon Glass error:
670aba92962SSimon Glass 	debug("%s: No match found: error %d\n", __func__, ret);
671aba92962SSimon Glass 	return ret;
672aba92962SSimon Glass }
673aba92962SSimon Glass 
674ff3e077bSSimon Glass int pci_bind_bus_devices(struct udevice *bus)
675ff3e077bSSimon Glass {
676ff3e077bSSimon Glass 	ulong vendor, device;
677ff3e077bSSimon Glass 	ulong header_type;
6784d8615cbSBin Meng 	pci_dev_t bdf, end;
679ff3e077bSSimon Glass 	bool found_multi;
680ff3e077bSSimon Glass 	int ret;
681ff3e077bSSimon Glass 
682ff3e077bSSimon Glass 	found_multi = false;
6834d8615cbSBin Meng 	end = PCI_BDF(bus->seq, PCI_MAX_PCI_DEVICES - 1,
6844d8615cbSBin Meng 		      PCI_MAX_PCI_FUNCTIONS - 1);
6856d9f5b03SYoshinori Sato 	for (bdf = PCI_BDF(bus->seq, 0, 0); bdf <= end;
6864d8615cbSBin Meng 	     bdf += PCI_BDF(0, 0, 1)) {
687ff3e077bSSimon Glass 		struct pci_child_platdata *pplat;
688ff3e077bSSimon Glass 		struct udevice *dev;
689ff3e077bSSimon Glass 		ulong class;
690ff3e077bSSimon Glass 
6914d8615cbSBin Meng 		if (PCI_FUNC(bdf) && !found_multi)
692ff3e077bSSimon Glass 			continue;
693ff3e077bSSimon Glass 		/* Check only the first access, we don't expect problems */
6944d8615cbSBin Meng 		ret = pci_bus_read_config(bus, bdf, PCI_HEADER_TYPE,
695ff3e077bSSimon Glass 					  &header_type, PCI_SIZE_8);
696ff3e077bSSimon Glass 		if (ret)
697ff3e077bSSimon Glass 			goto error;
6984d8615cbSBin Meng 		pci_bus_read_config(bus, bdf, PCI_VENDOR_ID, &vendor,
699ff3e077bSSimon Glass 				    PCI_SIZE_16);
700ff3e077bSSimon Glass 		if (vendor == 0xffff || vendor == 0x0000)
701ff3e077bSSimon Glass 			continue;
702ff3e077bSSimon Glass 
7034d8615cbSBin Meng 		if (!PCI_FUNC(bdf))
704ff3e077bSSimon Glass 			found_multi = header_type & 0x80;
705ff3e077bSSimon Glass 
706ff3e077bSSimon Glass 		debug("%s: bus %d/%s: found device %x, function %d\n", __func__,
7074d8615cbSBin Meng 		      bus->seq, bus->name, PCI_DEV(bdf), PCI_FUNC(bdf));
7084d8615cbSBin Meng 		pci_bus_read_config(bus, bdf, PCI_DEVICE_ID, &device,
709ff3e077bSSimon Glass 				    PCI_SIZE_16);
7104d8615cbSBin Meng 		pci_bus_read_config(bus, bdf, PCI_CLASS_REVISION, &class,
711aba92962SSimon Glass 				    PCI_SIZE_32);
712aba92962SSimon Glass 		class >>= 8;
713ff3e077bSSimon Glass 
714ff3e077bSSimon Glass 		/* Find this device in the device tree */
7154d8615cbSBin Meng 		ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), &dev);
716ff3e077bSSimon Glass 
7178bd42525SSimon Glass 		/* If nothing in the device tree, bind a device */
718ff3e077bSSimon Glass 		if (ret == -ENODEV) {
719aba92962SSimon Glass 			struct pci_device_id find_id;
720aba92962SSimon Glass 			ulong val;
721ff3e077bSSimon Glass 
722aba92962SSimon Glass 			memset(&find_id, '\0', sizeof(find_id));
723aba92962SSimon Glass 			find_id.vendor = vendor;
724aba92962SSimon Glass 			find_id.device = device;
725aba92962SSimon Glass 			find_id.class = class;
726aba92962SSimon Glass 			if ((header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL) {
7274d8615cbSBin Meng 				pci_bus_read_config(bus, bdf,
728aba92962SSimon Glass 						    PCI_SUBSYSTEM_VENDOR_ID,
729aba92962SSimon Glass 						    &val, PCI_SIZE_32);
730aba92962SSimon Glass 				find_id.subvendor = val & 0xffff;
731aba92962SSimon Glass 				find_id.subdevice = val >> 16;
732aba92962SSimon Glass 			}
7334d8615cbSBin Meng 			ret = pci_find_and_bind_driver(bus, &find_id, bdf,
734aba92962SSimon Glass 						       &dev);
735ff3e077bSSimon Glass 		}
7365dbcf3a0SSimon Glass 		if (ret == -EPERM)
7375dbcf3a0SSimon Glass 			continue;
7385dbcf3a0SSimon Glass 		else if (ret)
739ff3e077bSSimon Glass 			return ret;
740ff3e077bSSimon Glass 
741ff3e077bSSimon Glass 		/* Update the platform data */
742ff3e077bSSimon Glass 		pplat = dev_get_parent_platdata(dev);
7434d8615cbSBin Meng 		pplat->devfn = PCI_MASK_BUS(bdf);
744ff3e077bSSimon Glass 		pplat->vendor = vendor;
745ff3e077bSSimon Glass 		pplat->device = device;
746ff3e077bSSimon Glass 		pplat->class = class;
747ff3e077bSSimon Glass 	}
748ff3e077bSSimon Glass 
749ff3e077bSSimon Glass 	return 0;
750ff3e077bSSimon Glass error:
751ff3e077bSSimon Glass 	printf("Cannot read bus configuration: %d\n", ret);
752ff3e077bSSimon Glass 
753ff3e077bSSimon Glass 	return ret;
754ff3e077bSSimon Glass }
755ff3e077bSSimon Glass 
756ff3e077bSSimon Glass static int decode_regions(struct pci_controller *hose, const void *blob,
757ff3e077bSSimon Glass 			  int parent_node, int node)
758ff3e077bSSimon Glass {
759ff3e077bSSimon Glass 	int pci_addr_cells, addr_cells, size_cells;
7602084c5afSSimon Glass 	phys_addr_t base = 0, size;
761ff3e077bSSimon Glass 	int cells_per_record;
762ff3e077bSSimon Glass 	const u32 *prop;
763ff3e077bSSimon Glass 	int len;
764ff3e077bSSimon Glass 	int i;
765ff3e077bSSimon Glass 
766ff3e077bSSimon Glass 	prop = fdt_getprop(blob, node, "ranges", &len);
767ff3e077bSSimon Glass 	if (!prop)
768ff3e077bSSimon Glass 		return -EINVAL;
769ff3e077bSSimon Glass 	pci_addr_cells = fdt_address_cells(blob, node);
770ff3e077bSSimon Glass 	addr_cells = fdt_address_cells(blob, parent_node);
771ff3e077bSSimon Glass 	size_cells = fdt_size_cells(blob, node);
772ff3e077bSSimon Glass 
773ff3e077bSSimon Glass 	/* PCI addresses are always 3-cells */
774ff3e077bSSimon Glass 	len /= sizeof(u32);
775ff3e077bSSimon Glass 	cells_per_record = pci_addr_cells + addr_cells + size_cells;
776ff3e077bSSimon Glass 	hose->region_count = 0;
777ff3e077bSSimon Glass 	debug("%s: len=%d, cells_per_record=%d\n", __func__, len,
778ff3e077bSSimon Glass 	      cells_per_record);
779ff3e077bSSimon Glass 	for (i = 0; i < MAX_PCI_REGIONS; i++, len -= cells_per_record) {
780ff3e077bSSimon Glass 		u64 pci_addr, addr, size;
781ff3e077bSSimon Glass 		int space_code;
782ff3e077bSSimon Glass 		u32 flags;
783ff3e077bSSimon Glass 		int type;
7849526d83aSSimon Glass 		int pos;
785ff3e077bSSimon Glass 
786ff3e077bSSimon Glass 		if (len < cells_per_record)
787ff3e077bSSimon Glass 			break;
788ff3e077bSSimon Glass 		flags = fdt32_to_cpu(prop[0]);
789ff3e077bSSimon Glass 		space_code = (flags >> 24) & 3;
790ff3e077bSSimon Glass 		pci_addr = fdtdec_get_number(prop + 1, 2);
791ff3e077bSSimon Glass 		prop += pci_addr_cells;
792ff3e077bSSimon Glass 		addr = fdtdec_get_number(prop, addr_cells);
793ff3e077bSSimon Glass 		prop += addr_cells;
794ff3e077bSSimon Glass 		size = fdtdec_get_number(prop, size_cells);
795ff3e077bSSimon Glass 		prop += size_cells;
796ff3e077bSSimon Glass 		debug("%s: region %d, pci_addr=%" PRIx64 ", addr=%" PRIx64
797ff3e077bSSimon Glass 		      ", size=%" PRIx64 ", space_code=%d\n", __func__,
798ff3e077bSSimon Glass 		      hose->region_count, pci_addr, addr, size, space_code);
799ff3e077bSSimon Glass 		if (space_code & 2) {
800ff3e077bSSimon Glass 			type = flags & (1U << 30) ? PCI_REGION_PREFETCH :
801ff3e077bSSimon Glass 					PCI_REGION_MEM;
802ff3e077bSSimon Glass 		} else if (space_code & 1) {
803ff3e077bSSimon Glass 			type = PCI_REGION_IO;
804ff3e077bSSimon Glass 		} else {
805ff3e077bSSimon Glass 			continue;
806ff3e077bSSimon Glass 		}
8079526d83aSSimon Glass 		pos = -1;
8089526d83aSSimon Glass 		for (i = 0; i < hose->region_count; i++) {
8099526d83aSSimon Glass 			if (hose->regions[i].flags == type)
8109526d83aSSimon Glass 				pos = i;
8119526d83aSSimon Glass 		}
8129526d83aSSimon Glass 		if (pos == -1)
8139526d83aSSimon Glass 			pos = hose->region_count++;
8149526d83aSSimon Glass 		debug(" - type=%d, pos=%d\n", type, pos);
8159526d83aSSimon Glass 		pci_set_region(hose->regions + pos, pci_addr, addr, size, type);
816ff3e077bSSimon Glass 	}
817ff3e077bSSimon Glass 
818ff3e077bSSimon Glass 	/* Add a region for our local memory */
8192084c5afSSimon Glass 	size = gd->ram_size;
8202084c5afSSimon Glass #ifdef CONFIG_SYS_SDRAM_BASE
8212084c5afSSimon Glass 	base = CONFIG_SYS_SDRAM_BASE;
8222084c5afSSimon Glass #endif
8232084c5afSSimon Glass 	if (gd->pci_ram_top && gd->pci_ram_top < base + size)
8242084c5afSSimon Glass 		size = gd->pci_ram_top - base;
8252084c5afSSimon Glass 	pci_set_region(hose->regions + hose->region_count++, base, base,
8262084c5afSSimon Glass 		       size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
827ff3e077bSSimon Glass 
828ff3e077bSSimon Glass 	return 0;
829ff3e077bSSimon Glass }
830ff3e077bSSimon Glass 
831ff3e077bSSimon Glass static int pci_uclass_pre_probe(struct udevice *bus)
832ff3e077bSSimon Glass {
833ff3e077bSSimon Glass 	struct pci_controller *hose;
834ff3e077bSSimon Glass 	int ret;
835ff3e077bSSimon Glass 
836ff3e077bSSimon Glass 	debug("%s, bus=%d/%s, parent=%s\n", __func__, bus->seq, bus->name,
837ff3e077bSSimon Glass 	      bus->parent->name);
838ff3e077bSSimon Glass 	hose = bus->uclass_priv;
839ff3e077bSSimon Glass 
840ff3e077bSSimon Glass 	/* For bridges, use the top-level PCI controller */
84165f62b1cSPaul Burton 	if (!device_is_on_pci_bus(bus)) {
842ff3e077bSSimon Glass 		hose->ctlr = bus;
843e160f7d4SSimon Glass 		ret = decode_regions(hose, gd->fdt_blob,
844e160f7d4SSimon Glass 				     dev_of_offset(bus->parent),
845e160f7d4SSimon Glass 				     dev_of_offset(bus));
846ff3e077bSSimon Glass 		if (ret) {
847ff3e077bSSimon Glass 			debug("%s: Cannot decode regions\n", __func__);
848ff3e077bSSimon Glass 			return ret;
849ff3e077bSSimon Glass 		}
850ff3e077bSSimon Glass 	} else {
851ff3e077bSSimon Glass 		struct pci_controller *parent_hose;
852ff3e077bSSimon Glass 
853ff3e077bSSimon Glass 		parent_hose = dev_get_uclass_priv(bus->parent);
854ff3e077bSSimon Glass 		hose->ctlr = parent_hose->bus;
855ff3e077bSSimon Glass 	}
856ff3e077bSSimon Glass 	hose->bus = bus;
857ff3e077bSSimon Glass 	hose->first_busno = bus->seq;
858ff3e077bSSimon Glass 	hose->last_busno = bus->seq;
859ff3e077bSSimon Glass 
860ff3e077bSSimon Glass 	return 0;
861ff3e077bSSimon Glass }
862ff3e077bSSimon Glass 
863ff3e077bSSimon Glass static int pci_uclass_post_probe(struct udevice *bus)
864ff3e077bSSimon Glass {
865ff3e077bSSimon Glass 	int ret;
866ff3e077bSSimon Glass 
867ff3e077bSSimon Glass 	debug("%s: probing bus %d\n", __func__, bus->seq);
868ff3e077bSSimon Glass 	ret = pci_bind_bus_devices(bus);
869ff3e077bSSimon Glass 	if (ret)
870ff3e077bSSimon Glass 		return ret;
871ff3e077bSSimon Glass 
872ff3e077bSSimon Glass #ifdef CONFIG_PCI_PNP
873ff3e077bSSimon Glass 	ret = pci_auto_config_devices(bus);
8744d21455eSSimon Glass 	if (ret < 0)
8754d21455eSSimon Glass 		return ret;
876ff3e077bSSimon Glass #endif
877ff3e077bSSimon Glass 
878348b744bSBin Meng #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
879348b744bSBin Meng 	/*
880348b744bSBin Meng 	 * Per Intel FSP specification, we should call FSP notify API to
881348b744bSBin Meng 	 * inform FSP that PCI enumeration has been done so that FSP will
882348b744bSBin Meng 	 * do any necessary initialization as required by the chipset's
883348b744bSBin Meng 	 * BIOS Writer's Guide (BWG).
884348b744bSBin Meng 	 *
885348b744bSBin Meng 	 * Unfortunately we have to put this call here as with driver model,
886348b744bSBin Meng 	 * the enumeration is all done on a lazy basis as needed, so until
887348b744bSBin Meng 	 * something is touched on PCI it won't happen.
888348b744bSBin Meng 	 *
889348b744bSBin Meng 	 * Note we only call this 1) after U-Boot is relocated, and 2)
890348b744bSBin Meng 	 * root bus has finished probing.
891348b744bSBin Meng 	 */
8924d21455eSSimon Glass 	if ((gd->flags & GD_FLG_RELOC) && (bus->seq == 0)) {
893348b744bSBin Meng 		ret = fsp_init_phase_pci();
8944d21455eSSimon Glass 		if (ret)
8954d21455eSSimon Glass 			return ret;
8964d21455eSSimon Glass 	}
897348b744bSBin Meng #endif
898348b744bSBin Meng 
8994d21455eSSimon Glass 	return 0;
900ff3e077bSSimon Glass }
901ff3e077bSSimon Glass 
902ff3e077bSSimon Glass static int pci_uclass_child_post_bind(struct udevice *dev)
903ff3e077bSSimon Glass {
904ff3e077bSSimon Glass 	struct pci_child_platdata *pplat;
905ff3e077bSSimon Glass 	struct fdt_pci_addr addr;
906ff3e077bSSimon Glass 	int ret;
907ff3e077bSSimon Glass 
908e160f7d4SSimon Glass 	if (dev_of_offset(dev) == -1)
909ff3e077bSSimon Glass 		return 0;
910ff3e077bSSimon Glass 
911ff3e077bSSimon Glass 	/*
912ff3e077bSSimon Glass 	 * We could read vendor, device, class if available. But for now we
913ff3e077bSSimon Glass 	 * just check the address.
914ff3e077bSSimon Glass 	 */
915ff3e077bSSimon Glass 	pplat = dev_get_parent_platdata(dev);
916e160f7d4SSimon Glass 	ret = fdtdec_get_pci_addr(gd->fdt_blob, dev_of_offset(dev),
917ff3e077bSSimon Glass 				  FDT_PCI_SPACE_CONFIG, "reg", &addr);
918ff3e077bSSimon Glass 
919ff3e077bSSimon Glass 	if (ret) {
920ff3e077bSSimon Glass 		if (ret != -ENOENT)
921ff3e077bSSimon Glass 			return -EINVAL;
922ff3e077bSSimon Glass 	} else {
923dce54dd6SBin Meng 		/* extract the devfn from fdt_pci_addr */
924dce54dd6SBin Meng 		pplat->devfn = addr.phys_hi & 0xff00;
925ff3e077bSSimon Glass 	}
926ff3e077bSSimon Glass 
927ff3e077bSSimon Glass 	return 0;
928ff3e077bSSimon Glass }
929ff3e077bSSimon Glass 
9304d8615cbSBin Meng static int pci_bridge_read_config(struct udevice *bus, pci_dev_t bdf,
9314d8615cbSBin Meng 				  uint offset, ulong *valuep,
9324d8615cbSBin Meng 				  enum pci_size_t size)
933ff3e077bSSimon Glass {
934ff3e077bSSimon Glass 	struct pci_controller *hose = bus->uclass_priv;
935ff3e077bSSimon Glass 
936ff3e077bSSimon Glass 	return pci_bus_read_config(hose->ctlr, bdf, offset, valuep, size);
937ff3e077bSSimon Glass }
938ff3e077bSSimon Glass 
9394d8615cbSBin Meng static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf,
9404d8615cbSBin Meng 				   uint offset, ulong value,
9414d8615cbSBin Meng 				   enum pci_size_t size)
942ff3e077bSSimon Glass {
943ff3e077bSSimon Glass 	struct pci_controller *hose = bus->uclass_priv;
944ff3e077bSSimon Glass 
945ff3e077bSSimon Glass 	return pci_bus_write_config(hose->ctlr, bdf, offset, value, size);
946ff3e077bSSimon Glass }
947ff3e077bSSimon Glass 
94876c3fbcdSSimon Glass static int skip_to_next_device(struct udevice *bus, struct udevice **devp)
94976c3fbcdSSimon Glass {
95076c3fbcdSSimon Glass 	struct udevice *dev;
95176c3fbcdSSimon Glass 	int ret = 0;
95276c3fbcdSSimon Glass 
95376c3fbcdSSimon Glass 	/*
95476c3fbcdSSimon Glass 	 * Scan through all the PCI controllers. On x86 there will only be one
95576c3fbcdSSimon Glass 	 * but that is not necessarily true on other hardware.
95676c3fbcdSSimon Glass 	 */
95776c3fbcdSSimon Glass 	do {
95876c3fbcdSSimon Glass 		device_find_first_child(bus, &dev);
95976c3fbcdSSimon Glass 		if (dev) {
96076c3fbcdSSimon Glass 			*devp = dev;
96176c3fbcdSSimon Glass 			return 0;
96276c3fbcdSSimon Glass 		}
96376c3fbcdSSimon Glass 		ret = uclass_next_device(&bus);
96476c3fbcdSSimon Glass 		if (ret)
96576c3fbcdSSimon Glass 			return ret;
96676c3fbcdSSimon Glass 	} while (bus);
96776c3fbcdSSimon Glass 
96876c3fbcdSSimon Glass 	return 0;
96976c3fbcdSSimon Glass }
97076c3fbcdSSimon Glass 
97176c3fbcdSSimon Glass int pci_find_next_device(struct udevice **devp)
97276c3fbcdSSimon Glass {
97376c3fbcdSSimon Glass 	struct udevice *child = *devp;
97476c3fbcdSSimon Glass 	struct udevice *bus = child->parent;
97576c3fbcdSSimon Glass 	int ret;
97676c3fbcdSSimon Glass 
97776c3fbcdSSimon Glass 	/* First try all the siblings */
97876c3fbcdSSimon Glass 	*devp = NULL;
97976c3fbcdSSimon Glass 	while (child) {
98076c3fbcdSSimon Glass 		device_find_next_child(&child);
98176c3fbcdSSimon Glass 		if (child) {
98276c3fbcdSSimon Glass 			*devp = child;
98376c3fbcdSSimon Glass 			return 0;
98476c3fbcdSSimon Glass 		}
98576c3fbcdSSimon Glass 	}
98676c3fbcdSSimon Glass 
98776c3fbcdSSimon Glass 	/* We ran out of siblings. Try the next bus */
98876c3fbcdSSimon Glass 	ret = uclass_next_device(&bus);
98976c3fbcdSSimon Glass 	if (ret)
99076c3fbcdSSimon Glass 		return ret;
99176c3fbcdSSimon Glass 
99276c3fbcdSSimon Glass 	return bus ? skip_to_next_device(bus, devp) : 0;
99376c3fbcdSSimon Glass }
99476c3fbcdSSimon Glass 
99576c3fbcdSSimon Glass int pci_find_first_device(struct udevice **devp)
99676c3fbcdSSimon Glass {
99776c3fbcdSSimon Glass 	struct udevice *bus;
99876c3fbcdSSimon Glass 	int ret;
99976c3fbcdSSimon Glass 
100076c3fbcdSSimon Glass 	*devp = NULL;
100176c3fbcdSSimon Glass 	ret = uclass_first_device(UCLASS_PCI, &bus);
100276c3fbcdSSimon Glass 	if (ret)
100376c3fbcdSSimon Glass 		return ret;
100476c3fbcdSSimon Glass 
100576c3fbcdSSimon Glass 	return skip_to_next_device(bus, devp);
100676c3fbcdSSimon Glass }
100776c3fbcdSSimon Glass 
10089289db6cSSimon Glass ulong pci_conv_32_to_size(ulong value, uint offset, enum pci_size_t size)
10099289db6cSSimon Glass {
10109289db6cSSimon Glass 	switch (size) {
10119289db6cSSimon Glass 	case PCI_SIZE_8:
10129289db6cSSimon Glass 		return (value >> ((offset & 3) * 8)) & 0xff;
10139289db6cSSimon Glass 	case PCI_SIZE_16:
10149289db6cSSimon Glass 		return (value >> ((offset & 2) * 8)) & 0xffff;
10159289db6cSSimon Glass 	default:
10169289db6cSSimon Glass 		return value;
10179289db6cSSimon Glass 	}
10189289db6cSSimon Glass }
10199289db6cSSimon Glass 
10209289db6cSSimon Glass ulong pci_conv_size_to_32(ulong old, ulong value, uint offset,
10219289db6cSSimon Glass 			  enum pci_size_t size)
10229289db6cSSimon Glass {
10239289db6cSSimon Glass 	uint off_mask;
10249289db6cSSimon Glass 	uint val_mask, shift;
10259289db6cSSimon Glass 	ulong ldata, mask;
10269289db6cSSimon Glass 
10279289db6cSSimon Glass 	switch (size) {
10289289db6cSSimon Glass 	case PCI_SIZE_8:
10299289db6cSSimon Glass 		off_mask = 3;
10309289db6cSSimon Glass 		val_mask = 0xff;
10319289db6cSSimon Glass 		break;
10329289db6cSSimon Glass 	case PCI_SIZE_16:
10339289db6cSSimon Glass 		off_mask = 2;
10349289db6cSSimon Glass 		val_mask = 0xffff;
10359289db6cSSimon Glass 		break;
10369289db6cSSimon Glass 	default:
10379289db6cSSimon Glass 		return value;
10389289db6cSSimon Glass 	}
10399289db6cSSimon Glass 	shift = (offset & off_mask) * 8;
10409289db6cSSimon Glass 	ldata = (value & val_mask) << shift;
10419289db6cSSimon Glass 	mask = val_mask << shift;
10429289db6cSSimon Glass 	value = (old & ~mask) | ldata;
10439289db6cSSimon Glass 
10449289db6cSSimon Glass 	return value;
10459289db6cSSimon Glass }
10469289db6cSSimon Glass 
1047f9260336SSimon Glass int pci_get_regions(struct udevice *dev, struct pci_region **iop,
1048f9260336SSimon Glass 		    struct pci_region **memp, struct pci_region **prefp)
1049f9260336SSimon Glass {
1050f9260336SSimon Glass 	struct udevice *bus = pci_get_controller(dev);
1051f9260336SSimon Glass 	struct pci_controller *hose = dev_get_uclass_priv(bus);
1052f9260336SSimon Glass 	int i;
1053f9260336SSimon Glass 
1054f9260336SSimon Glass 	*iop = NULL;
1055f9260336SSimon Glass 	*memp = NULL;
1056f9260336SSimon Glass 	*prefp = NULL;
1057f9260336SSimon Glass 	for (i = 0; i < hose->region_count; i++) {
1058f9260336SSimon Glass 		switch (hose->regions[i].flags) {
1059f9260336SSimon Glass 		case PCI_REGION_IO:
1060f9260336SSimon Glass 			if (!*iop || (*iop)->size < hose->regions[i].size)
1061f9260336SSimon Glass 				*iop = hose->regions + i;
1062f9260336SSimon Glass 			break;
1063f9260336SSimon Glass 		case PCI_REGION_MEM:
1064f9260336SSimon Glass 			if (!*memp || (*memp)->size < hose->regions[i].size)
1065f9260336SSimon Glass 				*memp = hose->regions + i;
1066f9260336SSimon Glass 			break;
1067f9260336SSimon Glass 		case (PCI_REGION_MEM | PCI_REGION_PREFETCH):
1068f9260336SSimon Glass 			if (!*prefp || (*prefp)->size < hose->regions[i].size)
1069f9260336SSimon Glass 				*prefp = hose->regions + i;
1070f9260336SSimon Glass 			break;
1071f9260336SSimon Glass 		}
1072f9260336SSimon Glass 	}
1073f9260336SSimon Glass 
1074f9260336SSimon Glass 	return (*iop != NULL) + (*memp != NULL) + (*prefp != NULL);
1075f9260336SSimon Glass }
1076f9260336SSimon Glass 
1077bab17cf1SSimon Glass u32 dm_pci_read_bar32(struct udevice *dev, int barnum)
1078bab17cf1SSimon Glass {
1079bab17cf1SSimon Glass 	u32 addr;
1080bab17cf1SSimon Glass 	int bar;
1081bab17cf1SSimon Glass 
1082bab17cf1SSimon Glass 	bar = PCI_BASE_ADDRESS_0 + barnum * 4;
1083bab17cf1SSimon Glass 	dm_pci_read_config32(dev, bar, &addr);
1084bab17cf1SSimon Glass 	if (addr & PCI_BASE_ADDRESS_SPACE_IO)
1085bab17cf1SSimon Glass 		return addr & PCI_BASE_ADDRESS_IO_MASK;
1086bab17cf1SSimon Glass 	else
1087bab17cf1SSimon Glass 		return addr & PCI_BASE_ADDRESS_MEM_MASK;
1088bab17cf1SSimon Glass }
1089bab17cf1SSimon Glass 
10909d731c82SSimon Glass void dm_pci_write_bar32(struct udevice *dev, int barnum, u32 addr)
10919d731c82SSimon Glass {
10929d731c82SSimon Glass 	int bar;
10939d731c82SSimon Glass 
10949d731c82SSimon Glass 	bar = PCI_BASE_ADDRESS_0 + barnum * 4;
10959d731c82SSimon Glass 	dm_pci_write_config32(dev, bar, addr);
10969d731c82SSimon Glass }
10979d731c82SSimon Glass 
109821d1fe7eSSimon Glass static int _dm_pci_bus_to_phys(struct udevice *ctlr,
109921d1fe7eSSimon Glass 			       pci_addr_t bus_addr, unsigned long flags,
110021d1fe7eSSimon Glass 			       unsigned long skip_mask, phys_addr_t *pa)
110121d1fe7eSSimon Glass {
110221d1fe7eSSimon Glass 	struct pci_controller *hose = dev_get_uclass_priv(ctlr);
110321d1fe7eSSimon Glass 	struct pci_region *res;
110421d1fe7eSSimon Glass 	int i;
110521d1fe7eSSimon Glass 
110621d1fe7eSSimon Glass 	for (i = 0; i < hose->region_count; i++) {
110721d1fe7eSSimon Glass 		res = &hose->regions[i];
110821d1fe7eSSimon Glass 
110921d1fe7eSSimon Glass 		if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
111021d1fe7eSSimon Glass 			continue;
111121d1fe7eSSimon Glass 
111221d1fe7eSSimon Glass 		if (res->flags & skip_mask)
111321d1fe7eSSimon Glass 			continue;
111421d1fe7eSSimon Glass 
111521d1fe7eSSimon Glass 		if (bus_addr >= res->bus_start &&
111621d1fe7eSSimon Glass 		    (bus_addr - res->bus_start) < res->size) {
111721d1fe7eSSimon Glass 			*pa = (bus_addr - res->bus_start + res->phys_start);
111821d1fe7eSSimon Glass 			return 0;
111921d1fe7eSSimon Glass 		}
112021d1fe7eSSimon Glass 	}
112121d1fe7eSSimon Glass 
112221d1fe7eSSimon Glass 	return 1;
112321d1fe7eSSimon Glass }
112421d1fe7eSSimon Glass 
112521d1fe7eSSimon Glass phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t bus_addr,
112621d1fe7eSSimon Glass 			       unsigned long flags)
112721d1fe7eSSimon Glass {
112821d1fe7eSSimon Glass 	phys_addr_t phys_addr = 0;
112921d1fe7eSSimon Glass 	struct udevice *ctlr;
113021d1fe7eSSimon Glass 	int ret;
113121d1fe7eSSimon Glass 
113221d1fe7eSSimon Glass 	/* The root controller has the region information */
113321d1fe7eSSimon Glass 	ctlr = pci_get_controller(dev);
113421d1fe7eSSimon Glass 
113521d1fe7eSSimon Glass 	/*
113621d1fe7eSSimon Glass 	 * if PCI_REGION_MEM is set we do a two pass search with preference
113721d1fe7eSSimon Glass 	 * on matches that don't have PCI_REGION_SYS_MEMORY set
113821d1fe7eSSimon Glass 	 */
113921d1fe7eSSimon Glass 	if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) {
114021d1fe7eSSimon Glass 		ret = _dm_pci_bus_to_phys(ctlr, bus_addr,
114121d1fe7eSSimon Glass 					  flags, PCI_REGION_SYS_MEMORY,
114221d1fe7eSSimon Glass 					  &phys_addr);
114321d1fe7eSSimon Glass 		if (!ret)
114421d1fe7eSSimon Glass 			return phys_addr;
114521d1fe7eSSimon Glass 	}
114621d1fe7eSSimon Glass 
114721d1fe7eSSimon Glass 	ret = _dm_pci_bus_to_phys(ctlr, bus_addr, flags, 0, &phys_addr);
114821d1fe7eSSimon Glass 
114921d1fe7eSSimon Glass 	if (ret)
115021d1fe7eSSimon Glass 		puts("pci_hose_bus_to_phys: invalid physical address\n");
115121d1fe7eSSimon Glass 
115221d1fe7eSSimon Glass 	return phys_addr;
115321d1fe7eSSimon Glass }
115421d1fe7eSSimon Glass 
115521d1fe7eSSimon Glass int _dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr,
115621d1fe7eSSimon Glass 			unsigned long flags, unsigned long skip_mask,
115721d1fe7eSSimon Glass 			pci_addr_t *ba)
115821d1fe7eSSimon Glass {
115921d1fe7eSSimon Glass 	struct pci_region *res;
116021d1fe7eSSimon Glass 	struct udevice *ctlr;
116121d1fe7eSSimon Glass 	pci_addr_t bus_addr;
116221d1fe7eSSimon Glass 	int i;
116321d1fe7eSSimon Glass 	struct pci_controller *hose;
116421d1fe7eSSimon Glass 
116521d1fe7eSSimon Glass 	/* The root controller has the region information */
116621d1fe7eSSimon Glass 	ctlr = pci_get_controller(dev);
116721d1fe7eSSimon Glass 	hose = dev_get_uclass_priv(ctlr);
116821d1fe7eSSimon Glass 
116921d1fe7eSSimon Glass 	for (i = 0; i < hose->region_count; i++) {
117021d1fe7eSSimon Glass 		res = &hose->regions[i];
117121d1fe7eSSimon Glass 
117221d1fe7eSSimon Glass 		if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
117321d1fe7eSSimon Glass 			continue;
117421d1fe7eSSimon Glass 
117521d1fe7eSSimon Glass 		if (res->flags & skip_mask)
117621d1fe7eSSimon Glass 			continue;
117721d1fe7eSSimon Glass 
117821d1fe7eSSimon Glass 		bus_addr = phys_addr - res->phys_start + res->bus_start;
117921d1fe7eSSimon Glass 
118021d1fe7eSSimon Glass 		if (bus_addr >= res->bus_start &&
118121d1fe7eSSimon Glass 		    (bus_addr - res->bus_start) < res->size) {
118221d1fe7eSSimon Glass 			*ba = bus_addr;
118321d1fe7eSSimon Glass 			return 0;
118421d1fe7eSSimon Glass 		}
118521d1fe7eSSimon Glass 	}
118621d1fe7eSSimon Glass 
118721d1fe7eSSimon Glass 	return 1;
118821d1fe7eSSimon Glass }
118921d1fe7eSSimon Glass 
119021d1fe7eSSimon Glass pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr,
119121d1fe7eSSimon Glass 			      unsigned long flags)
119221d1fe7eSSimon Glass {
119321d1fe7eSSimon Glass 	pci_addr_t bus_addr = 0;
119421d1fe7eSSimon Glass 	int ret;
119521d1fe7eSSimon Glass 
119621d1fe7eSSimon Glass 	/*
119721d1fe7eSSimon Glass 	 * if PCI_REGION_MEM is set we do a two pass search with preference
119821d1fe7eSSimon Glass 	 * on matches that don't have PCI_REGION_SYS_MEMORY set
119921d1fe7eSSimon Glass 	 */
120021d1fe7eSSimon Glass 	if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) {
120121d1fe7eSSimon Glass 		ret = _dm_pci_phys_to_bus(dev, phys_addr, flags,
120221d1fe7eSSimon Glass 					  PCI_REGION_SYS_MEMORY, &bus_addr);
120321d1fe7eSSimon Glass 		if (!ret)
120421d1fe7eSSimon Glass 			return bus_addr;
120521d1fe7eSSimon Glass 	}
120621d1fe7eSSimon Glass 
120721d1fe7eSSimon Glass 	ret = _dm_pci_phys_to_bus(dev, phys_addr, flags, 0, &bus_addr);
120821d1fe7eSSimon Glass 
120921d1fe7eSSimon Glass 	if (ret)
121021d1fe7eSSimon Glass 		puts("pci_hose_phys_to_bus: invalid physical address\n");
121121d1fe7eSSimon Glass 
121221d1fe7eSSimon Glass 	return bus_addr;
121321d1fe7eSSimon Glass }
121421d1fe7eSSimon Glass 
121521d1fe7eSSimon Glass void *dm_pci_map_bar(struct udevice *dev, int bar, int flags)
121621d1fe7eSSimon Glass {
121721d1fe7eSSimon Glass 	pci_addr_t pci_bus_addr;
121821d1fe7eSSimon Glass 	u32 bar_response;
121921d1fe7eSSimon Glass 
122021d1fe7eSSimon Glass 	/* read BAR address */
122121d1fe7eSSimon Glass 	dm_pci_read_config32(dev, bar, &bar_response);
122221d1fe7eSSimon Glass 	pci_bus_addr = (pci_addr_t)(bar_response & ~0xf);
122321d1fe7eSSimon Glass 
122421d1fe7eSSimon Glass 	/*
122521d1fe7eSSimon Glass 	 * Pass "0" as the length argument to pci_bus_to_virt.  The arg
122621d1fe7eSSimon Glass 	 * isn't actualy used on any platform because u-boot assumes a static
122721d1fe7eSSimon Glass 	 * linear mapping.  In the future, this could read the BAR size
122821d1fe7eSSimon Glass 	 * and pass that as the size if needed.
122921d1fe7eSSimon Glass 	 */
123021d1fe7eSSimon Glass 	return dm_pci_bus_to_virt(dev, pci_bus_addr, flags, 0, MAP_NOCACHE);
123121d1fe7eSSimon Glass }
123221d1fe7eSSimon Glass 
1233ff3e077bSSimon Glass UCLASS_DRIVER(pci) = {
1234ff3e077bSSimon Glass 	.id		= UCLASS_PCI,
1235ff3e077bSSimon Glass 	.name		= "pci",
12362bb02e4fSSimon Glass 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
123791195485SSimon Glass 	.post_bind	= dm_scan_fdt_dev,
1238ff3e077bSSimon Glass 	.pre_probe	= pci_uclass_pre_probe,
1239ff3e077bSSimon Glass 	.post_probe	= pci_uclass_post_probe,
1240ff3e077bSSimon Glass 	.child_post_bind = pci_uclass_child_post_bind,
1241ff3e077bSSimon Glass 	.per_device_auto_alloc_size = sizeof(struct pci_controller),
1242ff3e077bSSimon Glass 	.per_child_platdata_auto_alloc_size =
1243ff3e077bSSimon Glass 			sizeof(struct pci_child_platdata),
1244ff3e077bSSimon Glass };
1245ff3e077bSSimon Glass 
1246ff3e077bSSimon Glass static const struct dm_pci_ops pci_bridge_ops = {
1247ff3e077bSSimon Glass 	.read_config	= pci_bridge_read_config,
1248ff3e077bSSimon Glass 	.write_config	= pci_bridge_write_config,
1249ff3e077bSSimon Glass };
1250ff3e077bSSimon Glass 
1251ff3e077bSSimon Glass static const struct udevice_id pci_bridge_ids[] = {
1252ff3e077bSSimon Glass 	{ .compatible = "pci-bridge" },
1253ff3e077bSSimon Glass 	{ }
1254ff3e077bSSimon Glass };
1255ff3e077bSSimon Glass 
1256ff3e077bSSimon Glass U_BOOT_DRIVER(pci_bridge_drv) = {
1257ff3e077bSSimon Glass 	.name		= "pci_bridge_drv",
1258ff3e077bSSimon Glass 	.id		= UCLASS_PCI,
1259ff3e077bSSimon Glass 	.of_match	= pci_bridge_ids,
1260ff3e077bSSimon Glass 	.ops		= &pci_bridge_ops,
1261ff3e077bSSimon Glass };
1262ff3e077bSSimon Glass 
1263ff3e077bSSimon Glass UCLASS_DRIVER(pci_generic) = {
1264ff3e077bSSimon Glass 	.id		= UCLASS_PCI_GENERIC,
1265ff3e077bSSimon Glass 	.name		= "pci_generic",
1266ff3e077bSSimon Glass };
1267ff3e077bSSimon Glass 
1268ff3e077bSSimon Glass static const struct udevice_id pci_generic_ids[] = {
1269ff3e077bSSimon Glass 	{ .compatible = "pci-generic" },
1270ff3e077bSSimon Glass 	{ }
1271ff3e077bSSimon Glass };
1272ff3e077bSSimon Glass 
1273ff3e077bSSimon Glass U_BOOT_DRIVER(pci_generic_drv) = {
1274ff3e077bSSimon Glass 	.name		= "pci_generic_drv",
1275ff3e077bSSimon Glass 	.id		= UCLASS_PCI_GENERIC,
1276ff3e077bSSimon Glass 	.of_match	= pci_generic_ids,
1277ff3e077bSSimon Glass };
1278e578b92cSStephen Warren 
1279e578b92cSStephen Warren void pci_init(void)
1280e578b92cSStephen Warren {
1281e578b92cSStephen Warren 	struct udevice *bus;
1282e578b92cSStephen Warren 
1283e578b92cSStephen Warren 	/*
1284e578b92cSStephen Warren 	 * Enumerate all known controller devices. Enumeration has the side-
1285e578b92cSStephen Warren 	 * effect of probing them, so PCIe devices will be enumerated too.
1286e578b92cSStephen Warren 	 */
1287e578b92cSStephen Warren 	for (uclass_first_device(UCLASS_PCI, &bus);
1288e578b92cSStephen Warren 	     bus;
1289e578b92cSStephen Warren 	     uclass_next_device(&bus)) {
1290e578b92cSStephen Warren 		;
1291e578b92cSStephen Warren 	}
1292e578b92cSStephen Warren }
1293