xref: /rk3399_rockchip-uboot/drivers/pci/pci-uclass.c (revision 3f603cbbb8e175e545d6037a783e1ef82bab30f9)
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/root.h>
17ff3e077bSSimon Glass #include <dm/device-internal.h>
18348b744bSBin Meng #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
19348b744bSBin Meng #include <asm/fsp/fsp_support.h>
20348b744bSBin Meng #endif
215e23b8b4SSimon Glass #include "pci_internal.h"
22ff3e077bSSimon Glass 
23ff3e077bSSimon Glass DECLARE_GLOBAL_DATA_PTR;
24ff3e077bSSimon Glass 
25a6eb93b3SSimon Glass int pci_get_bus(int busnum, struct udevice **busp)
26983c6ba2SSimon Glass {
27983c6ba2SSimon Glass 	int ret;
28983c6ba2SSimon Glass 
29983c6ba2SSimon Glass 	ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, busp);
30983c6ba2SSimon Glass 
31983c6ba2SSimon Glass 	/* Since buses may not be numbered yet try a little harder with bus 0 */
32983c6ba2SSimon Glass 	if (ret == -ENODEV) {
33*3f603cbbSSimon Glass 		ret = uclass_first_device_err(UCLASS_PCI, busp);
34983c6ba2SSimon Glass 		if (ret)
35983c6ba2SSimon Glass 			return ret;
36983c6ba2SSimon Glass 		ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, busp);
37983c6ba2SSimon Glass 	}
38983c6ba2SSimon Glass 
39983c6ba2SSimon Glass 	return ret;
40983c6ba2SSimon Glass }
41983c6ba2SSimon Glass 
429f60fb0dSSimon Glass struct udevice *pci_get_controller(struct udevice *dev)
439f60fb0dSSimon Glass {
449f60fb0dSSimon Glass 	while (device_is_on_pci_bus(dev))
459f60fb0dSSimon Glass 		dev = dev->parent;
469f60fb0dSSimon Glass 
479f60fb0dSSimon Glass 	return dev;
489f60fb0dSSimon Glass }
499f60fb0dSSimon Glass 
5021ccce1bSSimon Glass pci_dev_t dm_pci_get_bdf(struct udevice *dev)
514b515e4fSSimon Glass {
524b515e4fSSimon Glass 	struct pci_child_platdata *pplat = dev_get_parent_platdata(dev);
534b515e4fSSimon Glass 	struct udevice *bus = dev->parent;
544b515e4fSSimon Glass 
554b515e4fSSimon Glass 	return PCI_ADD_BUS(bus->seq, pplat->devfn);
564b515e4fSSimon Glass }
574b515e4fSSimon Glass 
58ff3e077bSSimon Glass /**
59ff3e077bSSimon Glass  * pci_get_bus_max() - returns the bus number of the last active bus
60ff3e077bSSimon Glass  *
61ff3e077bSSimon Glass  * @return last bus number, or -1 if no active buses
62ff3e077bSSimon Glass  */
63ff3e077bSSimon Glass static int pci_get_bus_max(void)
64ff3e077bSSimon Glass {
65ff3e077bSSimon Glass 	struct udevice *bus;
66ff3e077bSSimon Glass 	struct uclass *uc;
67ff3e077bSSimon Glass 	int ret = -1;
68ff3e077bSSimon Glass 
69ff3e077bSSimon Glass 	ret = uclass_get(UCLASS_PCI, &uc);
70ff3e077bSSimon Glass 	uclass_foreach_dev(bus, uc) {
71ff3e077bSSimon Glass 		if (bus->seq > ret)
72ff3e077bSSimon Glass 			ret = bus->seq;
73ff3e077bSSimon Glass 	}
74ff3e077bSSimon Glass 
75ff3e077bSSimon Glass 	debug("%s: ret=%d\n", __func__, ret);
76ff3e077bSSimon Glass 
77ff3e077bSSimon Glass 	return ret;
78ff3e077bSSimon Glass }
79ff3e077bSSimon Glass 
80ff3e077bSSimon Glass int pci_last_busno(void)
81ff3e077bSSimon Glass {
82069155cbSBin Meng 	return pci_get_bus_max();
83ff3e077bSSimon Glass }
84ff3e077bSSimon Glass 
85ff3e077bSSimon Glass int pci_get_ff(enum pci_size_t size)
86ff3e077bSSimon Glass {
87ff3e077bSSimon Glass 	switch (size) {
88ff3e077bSSimon Glass 	case PCI_SIZE_8:
89ff3e077bSSimon Glass 		return 0xff;
90ff3e077bSSimon Glass 	case PCI_SIZE_16:
91ff3e077bSSimon Glass 		return 0xffff;
92ff3e077bSSimon Glass 	default:
93ff3e077bSSimon Glass 		return 0xffffffff;
94ff3e077bSSimon Glass 	}
95ff3e077bSSimon Glass }
96ff3e077bSSimon Glass 
97ff3e077bSSimon Glass int pci_bus_find_devfn(struct udevice *bus, pci_dev_t find_devfn,
98ff3e077bSSimon Glass 		       struct udevice **devp)
99ff3e077bSSimon Glass {
100ff3e077bSSimon Glass 	struct udevice *dev;
101ff3e077bSSimon Glass 
102ff3e077bSSimon Glass 	for (device_find_first_child(bus, &dev);
103ff3e077bSSimon Glass 	     dev;
104ff3e077bSSimon Glass 	     device_find_next_child(&dev)) {
105ff3e077bSSimon Glass 		struct pci_child_platdata *pplat;
106ff3e077bSSimon Glass 
107ff3e077bSSimon Glass 		pplat = dev_get_parent_platdata(dev);
108ff3e077bSSimon Glass 		if (pplat && pplat->devfn == find_devfn) {
109ff3e077bSSimon Glass 			*devp = dev;
110ff3e077bSSimon Glass 			return 0;
111ff3e077bSSimon Glass 		}
112ff3e077bSSimon Glass 	}
113ff3e077bSSimon Glass 
114ff3e077bSSimon Glass 	return -ENODEV;
115ff3e077bSSimon Glass }
116ff3e077bSSimon Glass 
117f3f1faefSSimon Glass int dm_pci_bus_find_bdf(pci_dev_t bdf, struct udevice **devp)
118ff3e077bSSimon Glass {
119ff3e077bSSimon Glass 	struct udevice *bus;
120ff3e077bSSimon Glass 	int ret;
121ff3e077bSSimon Glass 
122983c6ba2SSimon Glass 	ret = pci_get_bus(PCI_BUS(bdf), &bus);
123ff3e077bSSimon Glass 	if (ret)
124ff3e077bSSimon Glass 		return ret;
125ff3e077bSSimon Glass 	return pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), devp);
126ff3e077bSSimon Glass }
127ff3e077bSSimon Glass 
128ff3e077bSSimon Glass static int pci_device_matches_ids(struct udevice *dev,
129ff3e077bSSimon Glass 				  struct pci_device_id *ids)
130ff3e077bSSimon Glass {
131ff3e077bSSimon Glass 	struct pci_child_platdata *pplat;
132ff3e077bSSimon Glass 	int i;
133ff3e077bSSimon Glass 
134ff3e077bSSimon Glass 	pplat = dev_get_parent_platdata(dev);
135ff3e077bSSimon Glass 	if (!pplat)
136ff3e077bSSimon Glass 		return -EINVAL;
137ff3e077bSSimon Glass 	for (i = 0; ids[i].vendor != 0; i++) {
138ff3e077bSSimon Glass 		if (pplat->vendor == ids[i].vendor &&
139ff3e077bSSimon Glass 		    pplat->device == ids[i].device)
140ff3e077bSSimon Glass 			return i;
141ff3e077bSSimon Glass 	}
142ff3e077bSSimon Glass 
143ff3e077bSSimon Glass 	return -EINVAL;
144ff3e077bSSimon Glass }
145ff3e077bSSimon Glass 
146ff3e077bSSimon Glass int pci_bus_find_devices(struct udevice *bus, struct pci_device_id *ids,
147ff3e077bSSimon Glass 			 int *indexp, struct udevice **devp)
148ff3e077bSSimon Glass {
149ff3e077bSSimon Glass 	struct udevice *dev;
150ff3e077bSSimon Glass 
151ff3e077bSSimon Glass 	/* Scan all devices on this bus */
152ff3e077bSSimon Glass 	for (device_find_first_child(bus, &dev);
153ff3e077bSSimon Glass 	     dev;
154ff3e077bSSimon Glass 	     device_find_next_child(&dev)) {
155ff3e077bSSimon Glass 		if (pci_device_matches_ids(dev, ids) >= 0) {
156ff3e077bSSimon Glass 			if ((*indexp)-- <= 0) {
157ff3e077bSSimon Glass 				*devp = dev;
158ff3e077bSSimon Glass 				return 0;
159ff3e077bSSimon Glass 			}
160ff3e077bSSimon Glass 		}
161ff3e077bSSimon Glass 	}
162ff3e077bSSimon Glass 
163ff3e077bSSimon Glass 	return -ENODEV;
164ff3e077bSSimon Glass }
165ff3e077bSSimon Glass 
166ff3e077bSSimon Glass int pci_find_device_id(struct pci_device_id *ids, int index,
167ff3e077bSSimon Glass 		       struct udevice **devp)
168ff3e077bSSimon Glass {
169ff3e077bSSimon Glass 	struct udevice *bus;
170ff3e077bSSimon Glass 
171ff3e077bSSimon Glass 	/* Scan all known buses */
172ff3e077bSSimon Glass 	for (uclass_first_device(UCLASS_PCI, &bus);
173ff3e077bSSimon Glass 	     bus;
174ff3e077bSSimon Glass 	     uclass_next_device(&bus)) {
175ff3e077bSSimon Glass 		if (!pci_bus_find_devices(bus, ids, &index, devp))
176ff3e077bSSimon Glass 			return 0;
177ff3e077bSSimon Glass 	}
178ff3e077bSSimon Glass 	*devp = NULL;
179ff3e077bSSimon Glass 
180ff3e077bSSimon Glass 	return -ENODEV;
181ff3e077bSSimon Glass }
182ff3e077bSSimon Glass 
1835c0bf647SSimon Glass static int dm_pci_bus_find_device(struct udevice *bus, unsigned int vendor,
1845c0bf647SSimon Glass 				  unsigned int device, int *indexp,
1855c0bf647SSimon Glass 				  struct udevice **devp)
1865c0bf647SSimon Glass {
1875c0bf647SSimon Glass 	struct pci_child_platdata *pplat;
1885c0bf647SSimon Glass 	struct udevice *dev;
1895c0bf647SSimon Glass 
1905c0bf647SSimon Glass 	for (device_find_first_child(bus, &dev);
1915c0bf647SSimon Glass 	     dev;
1925c0bf647SSimon Glass 	     device_find_next_child(&dev)) {
1935c0bf647SSimon Glass 		pplat = dev_get_parent_platdata(dev);
1945c0bf647SSimon Glass 		if (pplat->vendor == vendor && pplat->device == device) {
1955c0bf647SSimon Glass 			if (!(*indexp)--) {
1965c0bf647SSimon Glass 				*devp = dev;
1975c0bf647SSimon Glass 				return 0;
1985c0bf647SSimon Glass 			}
1995c0bf647SSimon Glass 		}
2005c0bf647SSimon Glass 	}
2015c0bf647SSimon Glass 
2025c0bf647SSimon Glass 	return -ENODEV;
2035c0bf647SSimon Glass }
2045c0bf647SSimon Glass 
2055c0bf647SSimon Glass int dm_pci_find_device(unsigned int vendor, unsigned int device, int index,
2065c0bf647SSimon Glass 		       struct udevice **devp)
2075c0bf647SSimon Glass {
2085c0bf647SSimon Glass 	struct udevice *bus;
2095c0bf647SSimon Glass 
2105c0bf647SSimon Glass 	/* Scan all known buses */
2115c0bf647SSimon Glass 	for (uclass_first_device(UCLASS_PCI, &bus);
2125c0bf647SSimon Glass 	     bus;
2135c0bf647SSimon Glass 	     uclass_next_device(&bus)) {
2145c0bf647SSimon Glass 		if (!dm_pci_bus_find_device(bus, vendor, device, &index, devp))
2155c0bf647SSimon Glass 			return device_probe(*devp);
2165c0bf647SSimon Glass 	}
2175c0bf647SSimon Glass 	*devp = NULL;
2185c0bf647SSimon Glass 
2195c0bf647SSimon Glass 	return -ENODEV;
2205c0bf647SSimon Glass }
2215c0bf647SSimon Glass 
222a0eb8356SSimon Glass int dm_pci_find_class(uint find_class, int index, struct udevice **devp)
223a0eb8356SSimon Glass {
224a0eb8356SSimon Glass 	struct udevice *dev;
225a0eb8356SSimon Glass 
226a0eb8356SSimon Glass 	/* Scan all known buses */
227a0eb8356SSimon Glass 	for (pci_find_first_device(&dev);
228a0eb8356SSimon Glass 	     dev;
229a0eb8356SSimon Glass 	     pci_find_next_device(&dev)) {
230a0eb8356SSimon Glass 		struct pci_child_platdata *pplat = dev_get_parent_platdata(dev);
231a0eb8356SSimon Glass 
232a0eb8356SSimon Glass 		if (pplat->class == find_class && !index--) {
233a0eb8356SSimon Glass 			*devp = dev;
234a0eb8356SSimon Glass 			return device_probe(*devp);
235a0eb8356SSimon Glass 		}
236a0eb8356SSimon Glass 	}
237a0eb8356SSimon Glass 	*devp = NULL;
238a0eb8356SSimon Glass 
239a0eb8356SSimon Glass 	return -ENODEV;
240a0eb8356SSimon Glass }
241a0eb8356SSimon Glass 
242ff3e077bSSimon Glass int pci_bus_write_config(struct udevice *bus, pci_dev_t bdf, int offset,
243ff3e077bSSimon Glass 			 unsigned long value, enum pci_size_t size)
244ff3e077bSSimon Glass {
245ff3e077bSSimon Glass 	struct dm_pci_ops *ops;
246ff3e077bSSimon Glass 
247ff3e077bSSimon Glass 	ops = pci_get_ops(bus);
248ff3e077bSSimon Glass 	if (!ops->write_config)
249ff3e077bSSimon Glass 		return -ENOSYS;
250ff3e077bSSimon Glass 	return ops->write_config(bus, bdf, offset, value, size);
251ff3e077bSSimon Glass }
252ff3e077bSSimon Glass 
253ff3e077bSSimon Glass int pci_write_config(pci_dev_t bdf, int offset, unsigned long value,
254ff3e077bSSimon Glass 		     enum pci_size_t size)
255ff3e077bSSimon Glass {
256ff3e077bSSimon Glass 	struct udevice *bus;
257ff3e077bSSimon Glass 	int ret;
258ff3e077bSSimon Glass 
259983c6ba2SSimon Glass 	ret = pci_get_bus(PCI_BUS(bdf), &bus);
260ff3e077bSSimon Glass 	if (ret)
261ff3e077bSSimon Glass 		return ret;
262ff3e077bSSimon Glass 
2634d8615cbSBin Meng 	return pci_bus_write_config(bus, bdf, offset, value, size);
264ff3e077bSSimon Glass }
265ff3e077bSSimon Glass 
26666afb4edSSimon Glass int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value,
26766afb4edSSimon Glass 			enum pci_size_t size)
26866afb4edSSimon Glass {
26966afb4edSSimon Glass 	struct udevice *bus;
27066afb4edSSimon Glass 
2711e0f2263SBin Meng 	for (bus = dev; device_is_on_pci_bus(bus);)
27266afb4edSSimon Glass 		bus = bus->parent;
27321ccce1bSSimon Glass 	return pci_bus_write_config(bus, dm_pci_get_bdf(dev), offset, value,
27421ccce1bSSimon Glass 				    size);
27566afb4edSSimon Glass }
27666afb4edSSimon Glass 
27766afb4edSSimon Glass 
278ff3e077bSSimon Glass int pci_write_config32(pci_dev_t bdf, int offset, u32 value)
279ff3e077bSSimon Glass {
280ff3e077bSSimon Glass 	return pci_write_config(bdf, offset, value, PCI_SIZE_32);
281ff3e077bSSimon Glass }
282ff3e077bSSimon Glass 
283ff3e077bSSimon Glass int pci_write_config16(pci_dev_t bdf, int offset, u16 value)
284ff3e077bSSimon Glass {
285ff3e077bSSimon Glass 	return pci_write_config(bdf, offset, value, PCI_SIZE_16);
286ff3e077bSSimon Glass }
287ff3e077bSSimon Glass 
288ff3e077bSSimon Glass int pci_write_config8(pci_dev_t bdf, int offset, u8 value)
289ff3e077bSSimon Glass {
290ff3e077bSSimon Glass 	return pci_write_config(bdf, offset, value, PCI_SIZE_8);
291ff3e077bSSimon Glass }
292ff3e077bSSimon Glass 
29366afb4edSSimon Glass int dm_pci_write_config8(struct udevice *dev, int offset, u8 value)
29466afb4edSSimon Glass {
29566afb4edSSimon Glass 	return dm_pci_write_config(dev, offset, value, PCI_SIZE_8);
29666afb4edSSimon Glass }
29766afb4edSSimon Glass 
29866afb4edSSimon Glass int dm_pci_write_config16(struct udevice *dev, int offset, u16 value)
29966afb4edSSimon Glass {
30066afb4edSSimon Glass 	return dm_pci_write_config(dev, offset, value, PCI_SIZE_16);
30166afb4edSSimon Glass }
30266afb4edSSimon Glass 
30366afb4edSSimon Glass int dm_pci_write_config32(struct udevice *dev, int offset, u32 value)
30466afb4edSSimon Glass {
30566afb4edSSimon Glass 	return dm_pci_write_config(dev, offset, value, PCI_SIZE_32);
30666afb4edSSimon Glass }
30766afb4edSSimon Glass 
308ff3e077bSSimon Glass int pci_bus_read_config(struct udevice *bus, pci_dev_t bdf, int offset,
309ff3e077bSSimon Glass 			unsigned long *valuep, enum pci_size_t size)
310ff3e077bSSimon Glass {
311ff3e077bSSimon Glass 	struct dm_pci_ops *ops;
312ff3e077bSSimon Glass 
313ff3e077bSSimon Glass 	ops = pci_get_ops(bus);
314ff3e077bSSimon Glass 	if (!ops->read_config)
315ff3e077bSSimon Glass 		return -ENOSYS;
316ff3e077bSSimon Glass 	return ops->read_config(bus, bdf, offset, valuep, size);
317ff3e077bSSimon Glass }
318ff3e077bSSimon Glass 
319ff3e077bSSimon Glass int pci_read_config(pci_dev_t bdf, int offset, unsigned long *valuep,
320ff3e077bSSimon Glass 		    enum pci_size_t size)
321ff3e077bSSimon Glass {
322ff3e077bSSimon Glass 	struct udevice *bus;
323ff3e077bSSimon Glass 	int ret;
324ff3e077bSSimon Glass 
325983c6ba2SSimon Glass 	ret = pci_get_bus(PCI_BUS(bdf), &bus);
326ff3e077bSSimon Glass 	if (ret)
327ff3e077bSSimon Glass 		return ret;
328ff3e077bSSimon Glass 
3294d8615cbSBin Meng 	return pci_bus_read_config(bus, bdf, offset, valuep, size);
330ff3e077bSSimon Glass }
331ff3e077bSSimon Glass 
33266afb4edSSimon Glass int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep,
33366afb4edSSimon Glass 		       enum pci_size_t size)
33466afb4edSSimon Glass {
33566afb4edSSimon Glass 	struct udevice *bus;
33666afb4edSSimon Glass 
3371e0f2263SBin Meng 	for (bus = dev; device_is_on_pci_bus(bus);)
33866afb4edSSimon Glass 		bus = bus->parent;
33921ccce1bSSimon Glass 	return pci_bus_read_config(bus, dm_pci_get_bdf(dev), offset, valuep,
34066afb4edSSimon Glass 				   size);
34166afb4edSSimon Glass }
34266afb4edSSimon Glass 
343ff3e077bSSimon Glass int pci_read_config32(pci_dev_t bdf, int offset, u32 *valuep)
344ff3e077bSSimon Glass {
345ff3e077bSSimon Glass 	unsigned long value;
346ff3e077bSSimon Glass 	int ret;
347ff3e077bSSimon Glass 
348ff3e077bSSimon Glass 	ret = pci_read_config(bdf, offset, &value, PCI_SIZE_32);
349ff3e077bSSimon Glass 	if (ret)
350ff3e077bSSimon Glass 		return ret;
351ff3e077bSSimon Glass 	*valuep = value;
352ff3e077bSSimon Glass 
353ff3e077bSSimon Glass 	return 0;
354ff3e077bSSimon Glass }
355ff3e077bSSimon Glass 
356ff3e077bSSimon Glass int pci_read_config16(pci_dev_t bdf, int offset, u16 *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_16);
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_config8(pci_dev_t bdf, int offset, u8 *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_8);
375ff3e077bSSimon Glass 	if (ret)
376ff3e077bSSimon Glass 		return ret;
377ff3e077bSSimon Glass 	*valuep = value;
378ff3e077bSSimon Glass 
379ff3e077bSSimon Glass 	return 0;
380ff3e077bSSimon Glass }
381ff3e077bSSimon Glass 
38266afb4edSSimon Glass int dm_pci_read_config8(struct udevice *dev, int offset, u8 *valuep)
38366afb4edSSimon Glass {
38466afb4edSSimon Glass 	unsigned long value;
38566afb4edSSimon Glass 	int ret;
38666afb4edSSimon Glass 
38766afb4edSSimon Glass 	ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_8);
38866afb4edSSimon Glass 	if (ret)
38966afb4edSSimon Glass 		return ret;
39066afb4edSSimon Glass 	*valuep = value;
39166afb4edSSimon Glass 
39266afb4edSSimon Glass 	return 0;
39366afb4edSSimon Glass }
39466afb4edSSimon Glass 
39566afb4edSSimon Glass int dm_pci_read_config16(struct udevice *dev, int offset, u16 *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_16);
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_config32(struct udevice *dev, int offset, u32 *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_32);
41466afb4edSSimon Glass 	if (ret)
41566afb4edSSimon Glass 		return ret;
41666afb4edSSimon Glass 	*valuep = value;
41766afb4edSSimon Glass 
41866afb4edSSimon Glass 	return 0;
41966afb4edSSimon Glass }
42066afb4edSSimon Glass 
421bbbcb526SBin Meng static void set_vga_bridge_bits(struct udevice *dev)
422bbbcb526SBin Meng {
423bbbcb526SBin Meng 	struct udevice *parent = dev->parent;
424bbbcb526SBin Meng 	u16 bc;
425bbbcb526SBin Meng 
426bbbcb526SBin Meng 	while (parent->seq != 0) {
427bbbcb526SBin Meng 		dm_pci_read_config16(parent, PCI_BRIDGE_CONTROL, &bc);
428bbbcb526SBin Meng 		bc |= PCI_BRIDGE_CTL_VGA;
429bbbcb526SBin Meng 		dm_pci_write_config16(parent, PCI_BRIDGE_CONTROL, bc);
430bbbcb526SBin Meng 		parent = parent->parent;
431bbbcb526SBin Meng 	}
432bbbcb526SBin Meng }
433bbbcb526SBin Meng 
434ff3e077bSSimon Glass int pci_auto_config_devices(struct udevice *bus)
435ff3e077bSSimon Glass {
436ff3e077bSSimon Glass 	struct pci_controller *hose = bus->uclass_priv;
437bbbcb526SBin Meng 	struct pci_child_platdata *pplat;
438ff3e077bSSimon Glass 	unsigned int sub_bus;
439ff3e077bSSimon Glass 	struct udevice *dev;
440ff3e077bSSimon Glass 	int ret;
441ff3e077bSSimon Glass 
442ff3e077bSSimon Glass 	sub_bus = bus->seq;
443ff3e077bSSimon Glass 	debug("%s: start\n", __func__);
444ff3e077bSSimon Glass 	pciauto_config_init(hose);
445ff3e077bSSimon Glass 	for (ret = device_find_first_child(bus, &dev);
446ff3e077bSSimon Glass 	     !ret && dev;
447ff3e077bSSimon Glass 	     ret = device_find_next_child(&dev)) {
448ff3e077bSSimon Glass 		unsigned int max_bus;
4494d21455eSSimon Glass 		int ret;
450ff3e077bSSimon Glass 
451ff3e077bSSimon Glass 		debug("%s: device %s\n", __func__, dev->name);
4525e23b8b4SSimon Glass 		ret = dm_pciauto_config_device(dev);
4534d21455eSSimon Glass 		if (ret < 0)
4544d21455eSSimon Glass 			return ret;
4554d21455eSSimon Glass 		max_bus = ret;
456ff3e077bSSimon Glass 		sub_bus = max(sub_bus, max_bus);
457bbbcb526SBin Meng 
458bbbcb526SBin Meng 		pplat = dev_get_parent_platdata(dev);
459bbbcb526SBin Meng 		if (pplat->class == (PCI_CLASS_DISPLAY_VGA << 8))
460bbbcb526SBin Meng 			set_vga_bridge_bits(dev);
461ff3e077bSSimon Glass 	}
462ff3e077bSSimon Glass 	debug("%s: done\n", __func__);
463ff3e077bSSimon Glass 
464ff3e077bSSimon Glass 	return sub_bus;
465ff3e077bSSimon Glass }
466ff3e077bSSimon Glass 
4675e23b8b4SSimon Glass int dm_pci_hose_probe_bus(struct udevice *bus)
468ff3e077bSSimon Glass {
469ff3e077bSSimon Glass 	int sub_bus;
470ff3e077bSSimon Glass 	int ret;
471ff3e077bSSimon Glass 
472ff3e077bSSimon Glass 	debug("%s\n", __func__);
473ff3e077bSSimon Glass 
474ff3e077bSSimon Glass 	sub_bus = pci_get_bus_max() + 1;
475ff3e077bSSimon Glass 	debug("%s: bus = %d/%s\n", __func__, sub_bus, bus->name);
4765e23b8b4SSimon Glass 	dm_pciauto_prescan_setup_bridge(bus, sub_bus);
477ff3e077bSSimon Glass 
478ff3e077bSSimon Glass 	ret = device_probe(bus);
479ff3e077bSSimon Glass 	if (ret) {
4803129ace4SSimon Glass 		debug("%s: Cannot probe bus %s: %d\n", __func__, bus->name,
481ff3e077bSSimon Glass 		      ret);
482ff3e077bSSimon Glass 		return ret;
483ff3e077bSSimon Glass 	}
484ff3e077bSSimon Glass 	if (sub_bus != bus->seq) {
485ff3e077bSSimon Glass 		printf("%s: Internal error, bus '%s' got seq %d, expected %d\n",
486ff3e077bSSimon Glass 		       __func__, bus->name, bus->seq, sub_bus);
487ff3e077bSSimon Glass 		return -EPIPE;
488ff3e077bSSimon Glass 	}
489ff3e077bSSimon Glass 	sub_bus = pci_get_bus_max();
4905e23b8b4SSimon Glass 	dm_pciauto_postscan_setup_bridge(bus, sub_bus);
491ff3e077bSSimon Glass 
492ff3e077bSSimon Glass 	return sub_bus;
493ff3e077bSSimon Glass }
494ff3e077bSSimon Glass 
495aba92962SSimon Glass /**
496aba92962SSimon Glass  * pci_match_one_device - Tell if a PCI device structure has a matching
497aba92962SSimon Glass  *                        PCI device id structure
498aba92962SSimon Glass  * @id: single PCI device id structure to match
499aba92962SSimon Glass  * @dev: the PCI device structure to match against
500aba92962SSimon Glass  *
501aba92962SSimon Glass  * Returns the matching pci_device_id structure or %NULL if there is no match.
502aba92962SSimon Glass  */
503aba92962SSimon Glass static bool pci_match_one_id(const struct pci_device_id *id,
504aba92962SSimon Glass 			     const struct pci_device_id *find)
505aba92962SSimon Glass {
506aba92962SSimon Glass 	if ((id->vendor == PCI_ANY_ID || id->vendor == find->vendor) &&
507aba92962SSimon Glass 	    (id->device == PCI_ANY_ID || id->device == find->device) &&
508aba92962SSimon Glass 	    (id->subvendor == PCI_ANY_ID || id->subvendor == find->subvendor) &&
509aba92962SSimon Glass 	    (id->subdevice == PCI_ANY_ID || id->subdevice == find->subdevice) &&
510aba92962SSimon Glass 	    !((id->class ^ find->class) & id->class_mask))
511aba92962SSimon Glass 		return true;
512aba92962SSimon Glass 
513aba92962SSimon Glass 	return false;
514aba92962SSimon Glass }
515aba92962SSimon Glass 
516aba92962SSimon Glass /**
517aba92962SSimon Glass  * pci_find_and_bind_driver() - Find and bind the right PCI driver
518aba92962SSimon Glass  *
519aba92962SSimon Glass  * This only looks at certain fields in the descriptor.
5205dbcf3a0SSimon Glass  *
5215dbcf3a0SSimon Glass  * @parent:	Parent bus
5225dbcf3a0SSimon Glass  * @find_id:	Specification of the driver to find
5235dbcf3a0SSimon Glass  * @bdf:	Bus/device/function addreess - see PCI_BDF()
5245dbcf3a0SSimon Glass  * @devp:	Returns a pointer to the device created
5255dbcf3a0SSimon Glass  * @return 0 if OK, -EPERM if the device is not needed before relocation and
5265dbcf3a0SSimon Glass  *	   therefore was not created, other -ve value on error
527aba92962SSimon Glass  */
528aba92962SSimon Glass static int pci_find_and_bind_driver(struct udevice *parent,
5295dbcf3a0SSimon Glass 				    struct pci_device_id *find_id,
5305dbcf3a0SSimon Glass 				    pci_dev_t bdf, struct udevice **devp)
531aba92962SSimon Glass {
532aba92962SSimon Glass 	struct pci_driver_entry *start, *entry;
533aba92962SSimon Glass 	const char *drv;
534aba92962SSimon Glass 	int n_ents;
535aba92962SSimon Glass 	int ret;
536aba92962SSimon Glass 	char name[30], *str;
53708fc7b8fSBin Meng 	bool bridge;
538aba92962SSimon Glass 
539aba92962SSimon Glass 	*devp = NULL;
540aba92962SSimon Glass 
541aba92962SSimon Glass 	debug("%s: Searching for driver: vendor=%x, device=%x\n", __func__,
542aba92962SSimon Glass 	      find_id->vendor, find_id->device);
543aba92962SSimon Glass 	start = ll_entry_start(struct pci_driver_entry, pci_driver_entry);
544aba92962SSimon Glass 	n_ents = ll_entry_count(struct pci_driver_entry, pci_driver_entry);
545aba92962SSimon Glass 	for (entry = start; entry != start + n_ents; entry++) {
546aba92962SSimon Glass 		const struct pci_device_id *id;
547aba92962SSimon Glass 		struct udevice *dev;
548aba92962SSimon Glass 		const struct driver *drv;
549aba92962SSimon Glass 
550aba92962SSimon Glass 		for (id = entry->match;
551aba92962SSimon Glass 		     id->vendor || id->subvendor || id->class_mask;
552aba92962SSimon Glass 		     id++) {
553aba92962SSimon Glass 			if (!pci_match_one_id(id, find_id))
554aba92962SSimon Glass 				continue;
555aba92962SSimon Glass 
556aba92962SSimon Glass 			drv = entry->driver;
55708fc7b8fSBin Meng 
55808fc7b8fSBin Meng 			/*
55908fc7b8fSBin Meng 			 * In the pre-relocation phase, we only bind devices
56008fc7b8fSBin Meng 			 * whose driver has the DM_FLAG_PRE_RELOC set, to save
56108fc7b8fSBin Meng 			 * precious memory space as on some platforms as that
56208fc7b8fSBin Meng 			 * space is pretty limited (ie: using Cache As RAM).
56308fc7b8fSBin Meng 			 */
56408fc7b8fSBin Meng 			if (!(gd->flags & GD_FLG_RELOC) &&
56508fc7b8fSBin Meng 			    !(drv->flags & DM_FLAG_PRE_RELOC))
5665dbcf3a0SSimon Glass 				return -EPERM;
56708fc7b8fSBin Meng 
568aba92962SSimon Glass 			/*
569aba92962SSimon Glass 			 * We could pass the descriptor to the driver as
570aba92962SSimon Glass 			 * platdata (instead of NULL) and allow its bind()
571aba92962SSimon Glass 			 * method to return -ENOENT if it doesn't support this
572aba92962SSimon Glass 			 * device. That way we could continue the search to
573aba92962SSimon Glass 			 * find another driver. For now this doesn't seem
574aba92962SSimon Glass 			 * necesssary, so just bind the first match.
575aba92962SSimon Glass 			 */
576aba92962SSimon Glass 			ret = device_bind(parent, drv, drv->name, NULL, -1,
577aba92962SSimon Glass 					  &dev);
578aba92962SSimon Glass 			if (ret)
579aba92962SSimon Glass 				goto error;
580aba92962SSimon Glass 			debug("%s: Match found: %s\n", __func__, drv->name);
581aba92962SSimon Glass 			dev->driver_data = find_id->driver_data;
582aba92962SSimon Glass 			*devp = dev;
583aba92962SSimon Glass 			return 0;
584aba92962SSimon Glass 		}
585aba92962SSimon Glass 	}
586aba92962SSimon Glass 
58708fc7b8fSBin Meng 	bridge = (find_id->class >> 8) == PCI_CLASS_BRIDGE_PCI;
58808fc7b8fSBin Meng 	/*
58908fc7b8fSBin Meng 	 * In the pre-relocation phase, we only bind bridge devices to save
59008fc7b8fSBin Meng 	 * precious memory space as on some platforms as that space is pretty
59108fc7b8fSBin Meng 	 * limited (ie: using Cache As RAM).
59208fc7b8fSBin Meng 	 */
59308fc7b8fSBin Meng 	if (!(gd->flags & GD_FLG_RELOC) && !bridge)
5945dbcf3a0SSimon Glass 		return -EPERM;
59508fc7b8fSBin Meng 
596aba92962SSimon Glass 	/* Bind a generic driver so that the device can be used */
5974d8615cbSBin Meng 	sprintf(name, "pci_%x:%x.%x", parent->seq, PCI_DEV(bdf),
5984d8615cbSBin Meng 		PCI_FUNC(bdf));
599aba92962SSimon Glass 	str = strdup(name);
600aba92962SSimon Glass 	if (!str)
601aba92962SSimon Glass 		return -ENOMEM;
60208fc7b8fSBin Meng 	drv = bridge ? "pci_bridge_drv" : "pci_generic_drv";
60308fc7b8fSBin Meng 
604aba92962SSimon Glass 	ret = device_bind_driver(parent, drv, str, devp);
605aba92962SSimon Glass 	if (ret) {
6063129ace4SSimon Glass 		debug("%s: Failed to bind generic driver: %d\n", __func__, ret);
607aba92962SSimon Glass 		return ret;
608aba92962SSimon Glass 	}
609aba92962SSimon Glass 	debug("%s: No match found: bound generic driver instead\n", __func__);
610aba92962SSimon Glass 
611aba92962SSimon Glass 	return 0;
612aba92962SSimon Glass 
613aba92962SSimon Glass error:
614aba92962SSimon Glass 	debug("%s: No match found: error %d\n", __func__, ret);
615aba92962SSimon Glass 	return ret;
616aba92962SSimon Glass }
617aba92962SSimon Glass 
618ff3e077bSSimon Glass int pci_bind_bus_devices(struct udevice *bus)
619ff3e077bSSimon Glass {
620ff3e077bSSimon Glass 	ulong vendor, device;
621ff3e077bSSimon Glass 	ulong header_type;
6224d8615cbSBin Meng 	pci_dev_t bdf, end;
623ff3e077bSSimon Glass 	bool found_multi;
624ff3e077bSSimon Glass 	int ret;
625ff3e077bSSimon Glass 
626ff3e077bSSimon Glass 	found_multi = false;
6274d8615cbSBin Meng 	end = PCI_BDF(bus->seq, PCI_MAX_PCI_DEVICES - 1,
6284d8615cbSBin Meng 		      PCI_MAX_PCI_FUNCTIONS - 1);
6294d8615cbSBin Meng 	for (bdf = PCI_BDF(bus->seq, 0, 0); bdf < end;
6304d8615cbSBin Meng 	     bdf += PCI_BDF(0, 0, 1)) {
631ff3e077bSSimon Glass 		struct pci_child_platdata *pplat;
632ff3e077bSSimon Glass 		struct udevice *dev;
633ff3e077bSSimon Glass 		ulong class;
634ff3e077bSSimon Glass 
6354d8615cbSBin Meng 		if (PCI_FUNC(bdf) && !found_multi)
636ff3e077bSSimon Glass 			continue;
637ff3e077bSSimon Glass 		/* Check only the first access, we don't expect problems */
6384d8615cbSBin Meng 		ret = pci_bus_read_config(bus, bdf, PCI_HEADER_TYPE,
639ff3e077bSSimon Glass 					  &header_type, PCI_SIZE_8);
640ff3e077bSSimon Glass 		if (ret)
641ff3e077bSSimon Glass 			goto error;
6424d8615cbSBin Meng 		pci_bus_read_config(bus, bdf, PCI_VENDOR_ID, &vendor,
643ff3e077bSSimon Glass 				    PCI_SIZE_16);
644ff3e077bSSimon Glass 		if (vendor == 0xffff || vendor == 0x0000)
645ff3e077bSSimon Glass 			continue;
646ff3e077bSSimon Glass 
6474d8615cbSBin Meng 		if (!PCI_FUNC(bdf))
648ff3e077bSSimon Glass 			found_multi = header_type & 0x80;
649ff3e077bSSimon Glass 
650ff3e077bSSimon Glass 		debug("%s: bus %d/%s: found device %x, function %d\n", __func__,
6514d8615cbSBin Meng 		      bus->seq, bus->name, PCI_DEV(bdf), PCI_FUNC(bdf));
6524d8615cbSBin Meng 		pci_bus_read_config(bus, bdf, PCI_DEVICE_ID, &device,
653ff3e077bSSimon Glass 				    PCI_SIZE_16);
6544d8615cbSBin Meng 		pci_bus_read_config(bus, bdf, PCI_CLASS_REVISION, &class,
655aba92962SSimon Glass 				    PCI_SIZE_32);
656aba92962SSimon Glass 		class >>= 8;
657ff3e077bSSimon Glass 
658ff3e077bSSimon Glass 		/* Find this device in the device tree */
6594d8615cbSBin Meng 		ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), &dev);
660ff3e077bSSimon Glass 
6618bd42525SSimon Glass 		/* If nothing in the device tree, bind a device */
662ff3e077bSSimon Glass 		if (ret == -ENODEV) {
663aba92962SSimon Glass 			struct pci_device_id find_id;
664aba92962SSimon Glass 			ulong val;
665ff3e077bSSimon Glass 
666aba92962SSimon Glass 			memset(&find_id, '\0', sizeof(find_id));
667aba92962SSimon Glass 			find_id.vendor = vendor;
668aba92962SSimon Glass 			find_id.device = device;
669aba92962SSimon Glass 			find_id.class = class;
670aba92962SSimon Glass 			if ((header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL) {
6714d8615cbSBin Meng 				pci_bus_read_config(bus, bdf,
672aba92962SSimon Glass 						    PCI_SUBSYSTEM_VENDOR_ID,
673aba92962SSimon Glass 						    &val, PCI_SIZE_32);
674aba92962SSimon Glass 				find_id.subvendor = val & 0xffff;
675aba92962SSimon Glass 				find_id.subdevice = val >> 16;
676aba92962SSimon Glass 			}
6774d8615cbSBin Meng 			ret = pci_find_and_bind_driver(bus, &find_id, bdf,
678aba92962SSimon Glass 						       &dev);
679ff3e077bSSimon Glass 		}
6805dbcf3a0SSimon Glass 		if (ret == -EPERM)
6815dbcf3a0SSimon Glass 			continue;
6825dbcf3a0SSimon Glass 		else if (ret)
683ff3e077bSSimon Glass 			return ret;
684ff3e077bSSimon Glass 
685ff3e077bSSimon Glass 		/* Update the platform data */
686ff3e077bSSimon Glass 		pplat = dev_get_parent_platdata(dev);
6874d8615cbSBin Meng 		pplat->devfn = PCI_MASK_BUS(bdf);
688ff3e077bSSimon Glass 		pplat->vendor = vendor;
689ff3e077bSSimon Glass 		pplat->device = device;
690ff3e077bSSimon Glass 		pplat->class = class;
691ff3e077bSSimon Glass 	}
692ff3e077bSSimon Glass 
693ff3e077bSSimon Glass 	return 0;
694ff3e077bSSimon Glass error:
695ff3e077bSSimon Glass 	printf("Cannot read bus configuration: %d\n", ret);
696ff3e077bSSimon Glass 
697ff3e077bSSimon Glass 	return ret;
698ff3e077bSSimon Glass }
699ff3e077bSSimon Glass 
700ff3e077bSSimon Glass static int pci_uclass_post_bind(struct udevice *bus)
701ff3e077bSSimon Glass {
702ff3e077bSSimon Glass 	/*
7031887ed3aSBin Meng 	 * If there is no pci device listed in the device tree,
7041887ed3aSBin Meng 	 * don't bother scanning the device tree.
7051887ed3aSBin Meng 	 */
7061887ed3aSBin Meng 	if (bus->of_offset == -1)
7071887ed3aSBin Meng 		return 0;
7081887ed3aSBin Meng 
7091887ed3aSBin Meng 	/*
710ff3e077bSSimon Glass 	 * Scan the device tree for devices. This does not probe the PCI bus,
711ff3e077bSSimon Glass 	 * as this is not permitted while binding. It just finds devices
712ff3e077bSSimon Glass 	 * mentioned in the device tree.
713ff3e077bSSimon Glass 	 *
714ff3e077bSSimon Glass 	 * Before relocation, only bind devices marked for pre-relocation
715ff3e077bSSimon Glass 	 * use.
716ff3e077bSSimon Glass 	 */
717ff3e077bSSimon Glass 	return dm_scan_fdt_node(bus, gd->fdt_blob, bus->of_offset,
718ff3e077bSSimon Glass 				gd->flags & GD_FLG_RELOC ? false : true);
719ff3e077bSSimon Glass }
720ff3e077bSSimon Glass 
721ff3e077bSSimon Glass static int decode_regions(struct pci_controller *hose, const void *blob,
722ff3e077bSSimon Glass 			  int parent_node, int node)
723ff3e077bSSimon Glass {
724ff3e077bSSimon Glass 	int pci_addr_cells, addr_cells, size_cells;
7252084c5afSSimon Glass 	phys_addr_t base = 0, size;
726ff3e077bSSimon Glass 	int cells_per_record;
727ff3e077bSSimon Glass 	const u32 *prop;
728ff3e077bSSimon Glass 	int len;
729ff3e077bSSimon Glass 	int i;
730ff3e077bSSimon Glass 
731ff3e077bSSimon Glass 	prop = fdt_getprop(blob, node, "ranges", &len);
732ff3e077bSSimon Glass 	if (!prop)
733ff3e077bSSimon Glass 		return -EINVAL;
734ff3e077bSSimon Glass 	pci_addr_cells = fdt_address_cells(blob, node);
735ff3e077bSSimon Glass 	addr_cells = fdt_address_cells(blob, parent_node);
736ff3e077bSSimon Glass 	size_cells = fdt_size_cells(blob, node);
737ff3e077bSSimon Glass 
738ff3e077bSSimon Glass 	/* PCI addresses are always 3-cells */
739ff3e077bSSimon Glass 	len /= sizeof(u32);
740ff3e077bSSimon Glass 	cells_per_record = pci_addr_cells + addr_cells + size_cells;
741ff3e077bSSimon Glass 	hose->region_count = 0;
742ff3e077bSSimon Glass 	debug("%s: len=%d, cells_per_record=%d\n", __func__, len,
743ff3e077bSSimon Glass 	      cells_per_record);
744ff3e077bSSimon Glass 	for (i = 0; i < MAX_PCI_REGIONS; i++, len -= cells_per_record) {
745ff3e077bSSimon Glass 		u64 pci_addr, addr, size;
746ff3e077bSSimon Glass 		int space_code;
747ff3e077bSSimon Glass 		u32 flags;
748ff3e077bSSimon Glass 		int type;
7499526d83aSSimon Glass 		int pos;
750ff3e077bSSimon Glass 
751ff3e077bSSimon Glass 		if (len < cells_per_record)
752ff3e077bSSimon Glass 			break;
753ff3e077bSSimon Glass 		flags = fdt32_to_cpu(prop[0]);
754ff3e077bSSimon Glass 		space_code = (flags >> 24) & 3;
755ff3e077bSSimon Glass 		pci_addr = fdtdec_get_number(prop + 1, 2);
756ff3e077bSSimon Glass 		prop += pci_addr_cells;
757ff3e077bSSimon Glass 		addr = fdtdec_get_number(prop, addr_cells);
758ff3e077bSSimon Glass 		prop += addr_cells;
759ff3e077bSSimon Glass 		size = fdtdec_get_number(prop, size_cells);
760ff3e077bSSimon Glass 		prop += size_cells;
761ff3e077bSSimon Glass 		debug("%s: region %d, pci_addr=%" PRIx64 ", addr=%" PRIx64
762ff3e077bSSimon Glass 		      ", size=%" PRIx64 ", space_code=%d\n", __func__,
763ff3e077bSSimon Glass 		      hose->region_count, pci_addr, addr, size, space_code);
764ff3e077bSSimon Glass 		if (space_code & 2) {
765ff3e077bSSimon Glass 			type = flags & (1U << 30) ? PCI_REGION_PREFETCH :
766ff3e077bSSimon Glass 					PCI_REGION_MEM;
767ff3e077bSSimon Glass 		} else if (space_code & 1) {
768ff3e077bSSimon Glass 			type = PCI_REGION_IO;
769ff3e077bSSimon Glass 		} else {
770ff3e077bSSimon Glass 			continue;
771ff3e077bSSimon Glass 		}
7729526d83aSSimon Glass 		pos = -1;
7739526d83aSSimon Glass 		for (i = 0; i < hose->region_count; i++) {
7749526d83aSSimon Glass 			if (hose->regions[i].flags == type)
7759526d83aSSimon Glass 				pos = i;
7769526d83aSSimon Glass 		}
7779526d83aSSimon Glass 		if (pos == -1)
7789526d83aSSimon Glass 			pos = hose->region_count++;
7799526d83aSSimon Glass 		debug(" - type=%d, pos=%d\n", type, pos);
7809526d83aSSimon Glass 		pci_set_region(hose->regions + pos, pci_addr, addr, size, type);
781ff3e077bSSimon Glass 	}
782ff3e077bSSimon Glass 
783ff3e077bSSimon Glass 	/* Add a region for our local memory */
7842084c5afSSimon Glass 	size = gd->ram_size;
7852084c5afSSimon Glass #ifdef CONFIG_SYS_SDRAM_BASE
7862084c5afSSimon Glass 	base = CONFIG_SYS_SDRAM_BASE;
7872084c5afSSimon Glass #endif
7882084c5afSSimon Glass 	if (gd->pci_ram_top && gd->pci_ram_top < base + size)
7892084c5afSSimon Glass 		size = gd->pci_ram_top - base;
7902084c5afSSimon Glass 	pci_set_region(hose->regions + hose->region_count++, base, base,
7912084c5afSSimon Glass 		       size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
792ff3e077bSSimon Glass 
793ff3e077bSSimon Glass 	return 0;
794ff3e077bSSimon Glass }
795ff3e077bSSimon Glass 
796ff3e077bSSimon Glass static int pci_uclass_pre_probe(struct udevice *bus)
797ff3e077bSSimon Glass {
798ff3e077bSSimon Glass 	struct pci_controller *hose;
799ff3e077bSSimon Glass 	int ret;
800ff3e077bSSimon Glass 
801ff3e077bSSimon Glass 	debug("%s, bus=%d/%s, parent=%s\n", __func__, bus->seq, bus->name,
802ff3e077bSSimon Glass 	      bus->parent->name);
803ff3e077bSSimon Glass 	hose = bus->uclass_priv;
804ff3e077bSSimon Glass 
805ff3e077bSSimon Glass 	/* For bridges, use the top-level PCI controller */
806ff3e077bSSimon Glass 	if (device_get_uclass_id(bus->parent) == UCLASS_ROOT) {
807ff3e077bSSimon Glass 		hose->ctlr = bus;
808ff3e077bSSimon Glass 		ret = decode_regions(hose, gd->fdt_blob, bus->parent->of_offset,
809ff3e077bSSimon Glass 				bus->of_offset);
810ff3e077bSSimon Glass 		if (ret) {
811ff3e077bSSimon Glass 			debug("%s: Cannot decode regions\n", __func__);
812ff3e077bSSimon Glass 			return ret;
813ff3e077bSSimon Glass 		}
814ff3e077bSSimon Glass 	} else {
815ff3e077bSSimon Glass 		struct pci_controller *parent_hose;
816ff3e077bSSimon Glass 
817ff3e077bSSimon Glass 		parent_hose = dev_get_uclass_priv(bus->parent);
818ff3e077bSSimon Glass 		hose->ctlr = parent_hose->bus;
819ff3e077bSSimon Glass 	}
820ff3e077bSSimon Glass 	hose->bus = bus;
821ff3e077bSSimon Glass 	hose->first_busno = bus->seq;
822ff3e077bSSimon Glass 	hose->last_busno = bus->seq;
823ff3e077bSSimon Glass 
824ff3e077bSSimon Glass 	return 0;
825ff3e077bSSimon Glass }
826ff3e077bSSimon Glass 
827ff3e077bSSimon Glass static int pci_uclass_post_probe(struct udevice *bus)
828ff3e077bSSimon Glass {
829ff3e077bSSimon Glass 	int ret;
830ff3e077bSSimon Glass 
831ff3e077bSSimon Glass 	debug("%s: probing bus %d\n", __func__, bus->seq);
832ff3e077bSSimon Glass 	ret = pci_bind_bus_devices(bus);
833ff3e077bSSimon Glass 	if (ret)
834ff3e077bSSimon Glass 		return ret;
835ff3e077bSSimon Glass 
836ff3e077bSSimon Glass #ifdef CONFIG_PCI_PNP
837ff3e077bSSimon Glass 	ret = pci_auto_config_devices(bus);
8384d21455eSSimon Glass 	if (ret < 0)
8394d21455eSSimon Glass 		return ret;
840ff3e077bSSimon Glass #endif
841ff3e077bSSimon Glass 
842348b744bSBin Meng #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
843348b744bSBin Meng 	/*
844348b744bSBin Meng 	 * Per Intel FSP specification, we should call FSP notify API to
845348b744bSBin Meng 	 * inform FSP that PCI enumeration has been done so that FSP will
846348b744bSBin Meng 	 * do any necessary initialization as required by the chipset's
847348b744bSBin Meng 	 * BIOS Writer's Guide (BWG).
848348b744bSBin Meng 	 *
849348b744bSBin Meng 	 * Unfortunately we have to put this call here as with driver model,
850348b744bSBin Meng 	 * the enumeration is all done on a lazy basis as needed, so until
851348b744bSBin Meng 	 * something is touched on PCI it won't happen.
852348b744bSBin Meng 	 *
853348b744bSBin Meng 	 * Note we only call this 1) after U-Boot is relocated, and 2)
854348b744bSBin Meng 	 * root bus has finished probing.
855348b744bSBin Meng 	 */
8564d21455eSSimon Glass 	if ((gd->flags & GD_FLG_RELOC) && (bus->seq == 0)) {
857348b744bSBin Meng 		ret = fsp_init_phase_pci();
8584d21455eSSimon Glass 		if (ret)
8594d21455eSSimon Glass 			return ret;
8604d21455eSSimon Glass 	}
861348b744bSBin Meng #endif
862348b744bSBin Meng 
8634d21455eSSimon Glass 	return 0;
864ff3e077bSSimon Glass }
865ff3e077bSSimon Glass 
866ff3e077bSSimon Glass static int pci_uclass_child_post_bind(struct udevice *dev)
867ff3e077bSSimon Glass {
868ff3e077bSSimon Glass 	struct pci_child_platdata *pplat;
869ff3e077bSSimon Glass 	struct fdt_pci_addr addr;
870ff3e077bSSimon Glass 	int ret;
871ff3e077bSSimon Glass 
872ff3e077bSSimon Glass 	if (dev->of_offset == -1)
873ff3e077bSSimon Glass 		return 0;
874ff3e077bSSimon Glass 
875ff3e077bSSimon Glass 	/*
876ff3e077bSSimon Glass 	 * We could read vendor, device, class if available. But for now we
877ff3e077bSSimon Glass 	 * just check the address.
878ff3e077bSSimon Glass 	 */
879ff3e077bSSimon Glass 	pplat = dev_get_parent_platdata(dev);
880ff3e077bSSimon Glass 	ret = fdtdec_get_pci_addr(gd->fdt_blob, dev->of_offset,
881ff3e077bSSimon Glass 				  FDT_PCI_SPACE_CONFIG, "reg", &addr);
882ff3e077bSSimon Glass 
883ff3e077bSSimon Glass 	if (ret) {
884ff3e077bSSimon Glass 		if (ret != -ENOENT)
885ff3e077bSSimon Glass 			return -EINVAL;
886ff3e077bSSimon Glass 	} else {
887dce54dd6SBin Meng 		/* extract the devfn from fdt_pci_addr */
888dce54dd6SBin Meng 		pplat->devfn = addr.phys_hi & 0xff00;
889ff3e077bSSimon Glass 	}
890ff3e077bSSimon Glass 
891ff3e077bSSimon Glass 	return 0;
892ff3e077bSSimon Glass }
893ff3e077bSSimon Glass 
8944d8615cbSBin Meng static int pci_bridge_read_config(struct udevice *bus, pci_dev_t bdf,
8954d8615cbSBin Meng 				  uint offset, ulong *valuep,
8964d8615cbSBin Meng 				  enum pci_size_t size)
897ff3e077bSSimon Glass {
898ff3e077bSSimon Glass 	struct pci_controller *hose = bus->uclass_priv;
899ff3e077bSSimon Glass 
900ff3e077bSSimon Glass 	return pci_bus_read_config(hose->ctlr, bdf, offset, valuep, size);
901ff3e077bSSimon Glass }
902ff3e077bSSimon Glass 
9034d8615cbSBin Meng static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf,
9044d8615cbSBin Meng 				   uint offset, ulong value,
9054d8615cbSBin Meng 				   enum pci_size_t size)
906ff3e077bSSimon Glass {
907ff3e077bSSimon Glass 	struct pci_controller *hose = bus->uclass_priv;
908ff3e077bSSimon Glass 
909ff3e077bSSimon Glass 	return pci_bus_write_config(hose->ctlr, bdf, offset, value, size);
910ff3e077bSSimon Glass }
911ff3e077bSSimon Glass 
91276c3fbcdSSimon Glass static int skip_to_next_device(struct udevice *bus, struct udevice **devp)
91376c3fbcdSSimon Glass {
91476c3fbcdSSimon Glass 	struct udevice *dev;
91576c3fbcdSSimon Glass 	int ret = 0;
91676c3fbcdSSimon Glass 
91776c3fbcdSSimon Glass 	/*
91876c3fbcdSSimon Glass 	 * Scan through all the PCI controllers. On x86 there will only be one
91976c3fbcdSSimon Glass 	 * but that is not necessarily true on other hardware.
92076c3fbcdSSimon Glass 	 */
92176c3fbcdSSimon Glass 	do {
92276c3fbcdSSimon Glass 		device_find_first_child(bus, &dev);
92376c3fbcdSSimon Glass 		if (dev) {
92476c3fbcdSSimon Glass 			*devp = dev;
92576c3fbcdSSimon Glass 			return 0;
92676c3fbcdSSimon Glass 		}
92776c3fbcdSSimon Glass 		ret = uclass_next_device(&bus);
92876c3fbcdSSimon Glass 		if (ret)
92976c3fbcdSSimon Glass 			return ret;
93076c3fbcdSSimon Glass 	} while (bus);
93176c3fbcdSSimon Glass 
93276c3fbcdSSimon Glass 	return 0;
93376c3fbcdSSimon Glass }
93476c3fbcdSSimon Glass 
93576c3fbcdSSimon Glass int pci_find_next_device(struct udevice **devp)
93676c3fbcdSSimon Glass {
93776c3fbcdSSimon Glass 	struct udevice *child = *devp;
93876c3fbcdSSimon Glass 	struct udevice *bus = child->parent;
93976c3fbcdSSimon Glass 	int ret;
94076c3fbcdSSimon Glass 
94176c3fbcdSSimon Glass 	/* First try all the siblings */
94276c3fbcdSSimon Glass 	*devp = NULL;
94376c3fbcdSSimon Glass 	while (child) {
94476c3fbcdSSimon Glass 		device_find_next_child(&child);
94576c3fbcdSSimon Glass 		if (child) {
94676c3fbcdSSimon Glass 			*devp = child;
94776c3fbcdSSimon Glass 			return 0;
94876c3fbcdSSimon Glass 		}
94976c3fbcdSSimon Glass 	}
95076c3fbcdSSimon Glass 
95176c3fbcdSSimon Glass 	/* We ran out of siblings. Try the next bus */
95276c3fbcdSSimon Glass 	ret = uclass_next_device(&bus);
95376c3fbcdSSimon Glass 	if (ret)
95476c3fbcdSSimon Glass 		return ret;
95576c3fbcdSSimon Glass 
95676c3fbcdSSimon Glass 	return bus ? skip_to_next_device(bus, devp) : 0;
95776c3fbcdSSimon Glass }
95876c3fbcdSSimon Glass 
95976c3fbcdSSimon Glass int pci_find_first_device(struct udevice **devp)
96076c3fbcdSSimon Glass {
96176c3fbcdSSimon Glass 	struct udevice *bus;
96276c3fbcdSSimon Glass 	int ret;
96376c3fbcdSSimon Glass 
96476c3fbcdSSimon Glass 	*devp = NULL;
96576c3fbcdSSimon Glass 	ret = uclass_first_device(UCLASS_PCI, &bus);
96676c3fbcdSSimon Glass 	if (ret)
96776c3fbcdSSimon Glass 		return ret;
96876c3fbcdSSimon Glass 
96976c3fbcdSSimon Glass 	return skip_to_next_device(bus, devp);
97076c3fbcdSSimon Glass }
97176c3fbcdSSimon Glass 
9729289db6cSSimon Glass ulong pci_conv_32_to_size(ulong value, uint offset, enum pci_size_t size)
9739289db6cSSimon Glass {
9749289db6cSSimon Glass 	switch (size) {
9759289db6cSSimon Glass 	case PCI_SIZE_8:
9769289db6cSSimon Glass 		return (value >> ((offset & 3) * 8)) & 0xff;
9779289db6cSSimon Glass 	case PCI_SIZE_16:
9789289db6cSSimon Glass 		return (value >> ((offset & 2) * 8)) & 0xffff;
9799289db6cSSimon Glass 	default:
9809289db6cSSimon Glass 		return value;
9819289db6cSSimon Glass 	}
9829289db6cSSimon Glass }
9839289db6cSSimon Glass 
9849289db6cSSimon Glass ulong pci_conv_size_to_32(ulong old, ulong value, uint offset,
9859289db6cSSimon Glass 			  enum pci_size_t size)
9869289db6cSSimon Glass {
9879289db6cSSimon Glass 	uint off_mask;
9889289db6cSSimon Glass 	uint val_mask, shift;
9899289db6cSSimon Glass 	ulong ldata, mask;
9909289db6cSSimon Glass 
9919289db6cSSimon Glass 	switch (size) {
9929289db6cSSimon Glass 	case PCI_SIZE_8:
9939289db6cSSimon Glass 		off_mask = 3;
9949289db6cSSimon Glass 		val_mask = 0xff;
9959289db6cSSimon Glass 		break;
9969289db6cSSimon Glass 	case PCI_SIZE_16:
9979289db6cSSimon Glass 		off_mask = 2;
9989289db6cSSimon Glass 		val_mask = 0xffff;
9999289db6cSSimon Glass 		break;
10009289db6cSSimon Glass 	default:
10019289db6cSSimon Glass 		return value;
10029289db6cSSimon Glass 	}
10039289db6cSSimon Glass 	shift = (offset & off_mask) * 8;
10049289db6cSSimon Glass 	ldata = (value & val_mask) << shift;
10059289db6cSSimon Glass 	mask = val_mask << shift;
10069289db6cSSimon Glass 	value = (old & ~mask) | ldata;
10079289db6cSSimon Glass 
10089289db6cSSimon Glass 	return value;
10099289db6cSSimon Glass }
10109289db6cSSimon Glass 
1011f9260336SSimon Glass int pci_get_regions(struct udevice *dev, struct pci_region **iop,
1012f9260336SSimon Glass 		    struct pci_region **memp, struct pci_region **prefp)
1013f9260336SSimon Glass {
1014f9260336SSimon Glass 	struct udevice *bus = pci_get_controller(dev);
1015f9260336SSimon Glass 	struct pci_controller *hose = dev_get_uclass_priv(bus);
1016f9260336SSimon Glass 	int i;
1017f9260336SSimon Glass 
1018f9260336SSimon Glass 	*iop = NULL;
1019f9260336SSimon Glass 	*memp = NULL;
1020f9260336SSimon Glass 	*prefp = NULL;
1021f9260336SSimon Glass 	for (i = 0; i < hose->region_count; i++) {
1022f9260336SSimon Glass 		switch (hose->regions[i].flags) {
1023f9260336SSimon Glass 		case PCI_REGION_IO:
1024f9260336SSimon Glass 			if (!*iop || (*iop)->size < hose->regions[i].size)
1025f9260336SSimon Glass 				*iop = hose->regions + i;
1026f9260336SSimon Glass 			break;
1027f9260336SSimon Glass 		case PCI_REGION_MEM:
1028f9260336SSimon Glass 			if (!*memp || (*memp)->size < hose->regions[i].size)
1029f9260336SSimon Glass 				*memp = hose->regions + i;
1030f9260336SSimon Glass 			break;
1031f9260336SSimon Glass 		case (PCI_REGION_MEM | PCI_REGION_PREFETCH):
1032f9260336SSimon Glass 			if (!*prefp || (*prefp)->size < hose->regions[i].size)
1033f9260336SSimon Glass 				*prefp = hose->regions + i;
1034f9260336SSimon Glass 			break;
1035f9260336SSimon Glass 		}
1036f9260336SSimon Glass 	}
1037f9260336SSimon Glass 
1038f9260336SSimon Glass 	return (*iop != NULL) + (*memp != NULL) + (*prefp != NULL);
1039f9260336SSimon Glass }
1040f9260336SSimon Glass 
1041bab17cf1SSimon Glass u32 dm_pci_read_bar32(struct udevice *dev, int barnum)
1042bab17cf1SSimon Glass {
1043bab17cf1SSimon Glass 	u32 addr;
1044bab17cf1SSimon Glass 	int bar;
1045bab17cf1SSimon Glass 
1046bab17cf1SSimon Glass 	bar = PCI_BASE_ADDRESS_0 + barnum * 4;
1047bab17cf1SSimon Glass 	dm_pci_read_config32(dev, bar, &addr);
1048bab17cf1SSimon Glass 	if (addr & PCI_BASE_ADDRESS_SPACE_IO)
1049bab17cf1SSimon Glass 		return addr & PCI_BASE_ADDRESS_IO_MASK;
1050bab17cf1SSimon Glass 	else
1051bab17cf1SSimon Glass 		return addr & PCI_BASE_ADDRESS_MEM_MASK;
1052bab17cf1SSimon Glass }
1053bab17cf1SSimon Glass 
10549d731c82SSimon Glass void dm_pci_write_bar32(struct udevice *dev, int barnum, u32 addr)
10559d731c82SSimon Glass {
10569d731c82SSimon Glass 	int bar;
10579d731c82SSimon Glass 
10589d731c82SSimon Glass 	bar = PCI_BASE_ADDRESS_0 + barnum * 4;
10599d731c82SSimon Glass 	dm_pci_write_config32(dev, bar, addr);
10609d731c82SSimon Glass }
10619d731c82SSimon Glass 
106221d1fe7eSSimon Glass static int _dm_pci_bus_to_phys(struct udevice *ctlr,
106321d1fe7eSSimon Glass 			       pci_addr_t bus_addr, unsigned long flags,
106421d1fe7eSSimon Glass 			       unsigned long skip_mask, phys_addr_t *pa)
106521d1fe7eSSimon Glass {
106621d1fe7eSSimon Glass 	struct pci_controller *hose = dev_get_uclass_priv(ctlr);
106721d1fe7eSSimon Glass 	struct pci_region *res;
106821d1fe7eSSimon Glass 	int i;
106921d1fe7eSSimon Glass 
107021d1fe7eSSimon Glass 	for (i = 0; i < hose->region_count; i++) {
107121d1fe7eSSimon Glass 		res = &hose->regions[i];
107221d1fe7eSSimon Glass 
107321d1fe7eSSimon Glass 		if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
107421d1fe7eSSimon Glass 			continue;
107521d1fe7eSSimon Glass 
107621d1fe7eSSimon Glass 		if (res->flags & skip_mask)
107721d1fe7eSSimon Glass 			continue;
107821d1fe7eSSimon Glass 
107921d1fe7eSSimon Glass 		if (bus_addr >= res->bus_start &&
108021d1fe7eSSimon Glass 		    (bus_addr - res->bus_start) < res->size) {
108121d1fe7eSSimon Glass 			*pa = (bus_addr - res->bus_start + res->phys_start);
108221d1fe7eSSimon Glass 			return 0;
108321d1fe7eSSimon Glass 		}
108421d1fe7eSSimon Glass 	}
108521d1fe7eSSimon Glass 
108621d1fe7eSSimon Glass 	return 1;
108721d1fe7eSSimon Glass }
108821d1fe7eSSimon Glass 
108921d1fe7eSSimon Glass phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t bus_addr,
109021d1fe7eSSimon Glass 			       unsigned long flags)
109121d1fe7eSSimon Glass {
109221d1fe7eSSimon Glass 	phys_addr_t phys_addr = 0;
109321d1fe7eSSimon Glass 	struct udevice *ctlr;
109421d1fe7eSSimon Glass 	int ret;
109521d1fe7eSSimon Glass 
109621d1fe7eSSimon Glass 	/* The root controller has the region information */
109721d1fe7eSSimon Glass 	ctlr = pci_get_controller(dev);
109821d1fe7eSSimon Glass 
109921d1fe7eSSimon Glass 	/*
110021d1fe7eSSimon Glass 	 * if PCI_REGION_MEM is set we do a two pass search with preference
110121d1fe7eSSimon Glass 	 * on matches that don't have PCI_REGION_SYS_MEMORY set
110221d1fe7eSSimon Glass 	 */
110321d1fe7eSSimon Glass 	if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) {
110421d1fe7eSSimon Glass 		ret = _dm_pci_bus_to_phys(ctlr, bus_addr,
110521d1fe7eSSimon Glass 					  flags, PCI_REGION_SYS_MEMORY,
110621d1fe7eSSimon Glass 					  &phys_addr);
110721d1fe7eSSimon Glass 		if (!ret)
110821d1fe7eSSimon Glass 			return phys_addr;
110921d1fe7eSSimon Glass 	}
111021d1fe7eSSimon Glass 
111121d1fe7eSSimon Glass 	ret = _dm_pci_bus_to_phys(ctlr, bus_addr, flags, 0, &phys_addr);
111221d1fe7eSSimon Glass 
111321d1fe7eSSimon Glass 	if (ret)
111421d1fe7eSSimon Glass 		puts("pci_hose_bus_to_phys: invalid physical address\n");
111521d1fe7eSSimon Glass 
111621d1fe7eSSimon Glass 	return phys_addr;
111721d1fe7eSSimon Glass }
111821d1fe7eSSimon Glass 
111921d1fe7eSSimon Glass int _dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr,
112021d1fe7eSSimon Glass 			unsigned long flags, unsigned long skip_mask,
112121d1fe7eSSimon Glass 			pci_addr_t *ba)
112221d1fe7eSSimon Glass {
112321d1fe7eSSimon Glass 	struct pci_region *res;
112421d1fe7eSSimon Glass 	struct udevice *ctlr;
112521d1fe7eSSimon Glass 	pci_addr_t bus_addr;
112621d1fe7eSSimon Glass 	int i;
112721d1fe7eSSimon Glass 	struct pci_controller *hose;
112821d1fe7eSSimon Glass 
112921d1fe7eSSimon Glass 	/* The root controller has the region information */
113021d1fe7eSSimon Glass 	ctlr = pci_get_controller(dev);
113121d1fe7eSSimon Glass 	hose = dev_get_uclass_priv(ctlr);
113221d1fe7eSSimon Glass 
113321d1fe7eSSimon Glass 	for (i = 0; i < hose->region_count; i++) {
113421d1fe7eSSimon Glass 		res = &hose->regions[i];
113521d1fe7eSSimon Glass 
113621d1fe7eSSimon Glass 		if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
113721d1fe7eSSimon Glass 			continue;
113821d1fe7eSSimon Glass 
113921d1fe7eSSimon Glass 		if (res->flags & skip_mask)
114021d1fe7eSSimon Glass 			continue;
114121d1fe7eSSimon Glass 
114221d1fe7eSSimon Glass 		bus_addr = phys_addr - res->phys_start + res->bus_start;
114321d1fe7eSSimon Glass 
114421d1fe7eSSimon Glass 		if (bus_addr >= res->bus_start &&
114521d1fe7eSSimon Glass 		    (bus_addr - res->bus_start) < res->size) {
114621d1fe7eSSimon Glass 			*ba = bus_addr;
114721d1fe7eSSimon Glass 			return 0;
114821d1fe7eSSimon Glass 		}
114921d1fe7eSSimon Glass 	}
115021d1fe7eSSimon Glass 
115121d1fe7eSSimon Glass 	return 1;
115221d1fe7eSSimon Glass }
115321d1fe7eSSimon Glass 
115421d1fe7eSSimon Glass pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr,
115521d1fe7eSSimon Glass 			      unsigned long flags)
115621d1fe7eSSimon Glass {
115721d1fe7eSSimon Glass 	pci_addr_t bus_addr = 0;
115821d1fe7eSSimon Glass 	int ret;
115921d1fe7eSSimon Glass 
116021d1fe7eSSimon Glass 	/*
116121d1fe7eSSimon Glass 	 * if PCI_REGION_MEM is set we do a two pass search with preference
116221d1fe7eSSimon Glass 	 * on matches that don't have PCI_REGION_SYS_MEMORY set
116321d1fe7eSSimon Glass 	 */
116421d1fe7eSSimon Glass 	if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) {
116521d1fe7eSSimon Glass 		ret = _dm_pci_phys_to_bus(dev, phys_addr, flags,
116621d1fe7eSSimon Glass 					  PCI_REGION_SYS_MEMORY, &bus_addr);
116721d1fe7eSSimon Glass 		if (!ret)
116821d1fe7eSSimon Glass 			return bus_addr;
116921d1fe7eSSimon Glass 	}
117021d1fe7eSSimon Glass 
117121d1fe7eSSimon Glass 	ret = _dm_pci_phys_to_bus(dev, phys_addr, flags, 0, &bus_addr);
117221d1fe7eSSimon Glass 
117321d1fe7eSSimon Glass 	if (ret)
117421d1fe7eSSimon Glass 		puts("pci_hose_phys_to_bus: invalid physical address\n");
117521d1fe7eSSimon Glass 
117621d1fe7eSSimon Glass 	return bus_addr;
117721d1fe7eSSimon Glass }
117821d1fe7eSSimon Glass 
117921d1fe7eSSimon Glass void *dm_pci_map_bar(struct udevice *dev, int bar, int flags)
118021d1fe7eSSimon Glass {
118121d1fe7eSSimon Glass 	pci_addr_t pci_bus_addr;
118221d1fe7eSSimon Glass 	u32 bar_response;
118321d1fe7eSSimon Glass 
118421d1fe7eSSimon Glass 	/* read BAR address */
118521d1fe7eSSimon Glass 	dm_pci_read_config32(dev, bar, &bar_response);
118621d1fe7eSSimon Glass 	pci_bus_addr = (pci_addr_t)(bar_response & ~0xf);
118721d1fe7eSSimon Glass 
118821d1fe7eSSimon Glass 	/*
118921d1fe7eSSimon Glass 	 * Pass "0" as the length argument to pci_bus_to_virt.  The arg
119021d1fe7eSSimon Glass 	 * isn't actualy used on any platform because u-boot assumes a static
119121d1fe7eSSimon Glass 	 * linear mapping.  In the future, this could read the BAR size
119221d1fe7eSSimon Glass 	 * and pass that as the size if needed.
119321d1fe7eSSimon Glass 	 */
119421d1fe7eSSimon Glass 	return dm_pci_bus_to_virt(dev, pci_bus_addr, flags, 0, MAP_NOCACHE);
119521d1fe7eSSimon Glass }
119621d1fe7eSSimon Glass 
1197ff3e077bSSimon Glass UCLASS_DRIVER(pci) = {
1198ff3e077bSSimon Glass 	.id		= UCLASS_PCI,
1199ff3e077bSSimon Glass 	.name		= "pci",
12002bb02e4fSSimon Glass 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
1201ff3e077bSSimon Glass 	.post_bind	= pci_uclass_post_bind,
1202ff3e077bSSimon Glass 	.pre_probe	= pci_uclass_pre_probe,
1203ff3e077bSSimon Glass 	.post_probe	= pci_uclass_post_probe,
1204ff3e077bSSimon Glass 	.child_post_bind = pci_uclass_child_post_bind,
1205ff3e077bSSimon Glass 	.per_device_auto_alloc_size = sizeof(struct pci_controller),
1206ff3e077bSSimon Glass 	.per_child_platdata_auto_alloc_size =
1207ff3e077bSSimon Glass 			sizeof(struct pci_child_platdata),
1208ff3e077bSSimon Glass };
1209ff3e077bSSimon Glass 
1210ff3e077bSSimon Glass static const struct dm_pci_ops pci_bridge_ops = {
1211ff3e077bSSimon Glass 	.read_config	= pci_bridge_read_config,
1212ff3e077bSSimon Glass 	.write_config	= pci_bridge_write_config,
1213ff3e077bSSimon Glass };
1214ff3e077bSSimon Glass 
1215ff3e077bSSimon Glass static const struct udevice_id pci_bridge_ids[] = {
1216ff3e077bSSimon Glass 	{ .compatible = "pci-bridge" },
1217ff3e077bSSimon Glass 	{ }
1218ff3e077bSSimon Glass };
1219ff3e077bSSimon Glass 
1220ff3e077bSSimon Glass U_BOOT_DRIVER(pci_bridge_drv) = {
1221ff3e077bSSimon Glass 	.name		= "pci_bridge_drv",
1222ff3e077bSSimon Glass 	.id		= UCLASS_PCI,
1223ff3e077bSSimon Glass 	.of_match	= pci_bridge_ids,
1224ff3e077bSSimon Glass 	.ops		= &pci_bridge_ops,
1225ff3e077bSSimon Glass };
1226ff3e077bSSimon Glass 
1227ff3e077bSSimon Glass UCLASS_DRIVER(pci_generic) = {
1228ff3e077bSSimon Glass 	.id		= UCLASS_PCI_GENERIC,
1229ff3e077bSSimon Glass 	.name		= "pci_generic",
1230ff3e077bSSimon Glass };
1231ff3e077bSSimon Glass 
1232ff3e077bSSimon Glass static const struct udevice_id pci_generic_ids[] = {
1233ff3e077bSSimon Glass 	{ .compatible = "pci-generic" },
1234ff3e077bSSimon Glass 	{ }
1235ff3e077bSSimon Glass };
1236ff3e077bSSimon Glass 
1237ff3e077bSSimon Glass U_BOOT_DRIVER(pci_generic_drv) = {
1238ff3e077bSSimon Glass 	.name		= "pci_generic_drv",
1239ff3e077bSSimon Glass 	.id		= UCLASS_PCI_GENERIC,
1240ff3e077bSSimon Glass 	.of_match	= pci_generic_ids,
1241ff3e077bSSimon Glass };
1242e578b92cSStephen Warren 
1243e578b92cSStephen Warren void pci_init(void)
1244e578b92cSStephen Warren {
1245e578b92cSStephen Warren 	struct udevice *bus;
1246e578b92cSStephen Warren 
1247e578b92cSStephen Warren 	/*
1248e578b92cSStephen Warren 	 * Enumerate all known controller devices. Enumeration has the side-
1249e578b92cSStephen Warren 	 * effect of probing them, so PCIe devices will be enumerated too.
1250e578b92cSStephen Warren 	 */
1251e578b92cSStephen Warren 	for (uclass_first_device(UCLASS_PCI, &bus);
1252e578b92cSStephen Warren 	     bus;
1253e578b92cSStephen Warren 	     uclass_next_device(&bus)) {
1254e578b92cSStephen Warren 		;
1255e578b92cSStephen Warren 	}
1256e578b92cSStephen Warren }
1257