xref: /rk3399_rockchip-uboot/drivers/pci/pci-uclass.c (revision 10dd02abedc0b56a54ea4bd652d80c9d87786704)
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 <inttypes.h>
12ff3e077bSSimon Glass #include <pci.h>
1321d1fe7eSSimon Glass #include <asm/io.h>
14ff3e077bSSimon Glass #include <dm/device-internal.h>
15bf501595SSimon Glass #include <dm/lists.h>
16348b744bSBin Meng #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
17348b744bSBin Meng #include <asm/fsp/fsp_support.h>
18348b744bSBin Meng #endif
195e23b8b4SSimon Glass #include "pci_internal.h"
20ff3e077bSSimon Glass 
21ff3e077bSSimon Glass DECLARE_GLOBAL_DATA_PTR;
22ff3e077bSSimon Glass 
pci_get_bus(int busnum,struct udevice ** busp)23a6eb93b3SSimon Glass int pci_get_bus(int busnum, struct udevice **busp)
24983c6ba2SSimon Glass {
25983c6ba2SSimon Glass 	int ret;
26983c6ba2SSimon Glass 
27983c6ba2SSimon Glass 	ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, busp);
28983c6ba2SSimon Glass 
29983c6ba2SSimon Glass 	/* Since buses may not be numbered yet try a little harder with bus 0 */
30983c6ba2SSimon Glass 	if (ret == -ENODEV) {
313f603cbbSSimon Glass 		ret = uclass_first_device_err(UCLASS_PCI, busp);
32983c6ba2SSimon Glass 		if (ret)
33983c6ba2SSimon Glass 			return ret;
34983c6ba2SSimon Glass 		ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, busp);
35983c6ba2SSimon Glass 	}
36983c6ba2SSimon Glass 
37983c6ba2SSimon Glass 	return ret;
38983c6ba2SSimon Glass }
39983c6ba2SSimon Glass 
pci_get_controller(struct udevice * dev)409f60fb0dSSimon Glass struct udevice *pci_get_controller(struct udevice *dev)
419f60fb0dSSimon Glass {
429f60fb0dSSimon Glass 	while (device_is_on_pci_bus(dev))
439f60fb0dSSimon Glass 		dev = dev->parent;
449f60fb0dSSimon Glass 
459f60fb0dSSimon Glass 	return dev;
469f60fb0dSSimon Glass }
479f60fb0dSSimon Glass 
dm_pci_get_bdf(struct udevice * dev)4821ccce1bSSimon Glass pci_dev_t dm_pci_get_bdf(struct udevice *dev)
494b515e4fSSimon Glass {
504b515e4fSSimon Glass 	struct pci_child_platdata *pplat = dev_get_parent_platdata(dev);
514b515e4fSSimon Glass 	struct udevice *bus = dev->parent;
524b515e4fSSimon Glass 
534b515e4fSSimon Glass 	return PCI_ADD_BUS(bus->seq, pplat->devfn);
544b515e4fSSimon Glass }
554b515e4fSSimon Glass 
56ff3e077bSSimon Glass /**
57ff3e077bSSimon Glass  * pci_get_bus_max() - returns the bus number of the last active bus
58ff3e077bSSimon Glass  *
59ff3e077bSSimon Glass  * @return last bus number, or -1 if no active buses
60ff3e077bSSimon Glass  */
pci_get_bus_max(void)61ff3e077bSSimon Glass static int pci_get_bus_max(void)
62ff3e077bSSimon Glass {
63ff3e077bSSimon Glass 	struct udevice *bus;
64ff3e077bSSimon Glass 	struct uclass *uc;
65ff3e077bSSimon Glass 	int ret = -1;
66ff3e077bSSimon Glass 
67ff3e077bSSimon Glass 	ret = uclass_get(UCLASS_PCI, &uc);
68ff3e077bSSimon Glass 	uclass_foreach_dev(bus, uc) {
69ff3e077bSSimon Glass 		if (bus->seq > ret)
70ff3e077bSSimon Glass 			ret = bus->seq;
71ff3e077bSSimon Glass 	}
72ff3e077bSSimon Glass 
73ff3e077bSSimon Glass 	debug("%s: ret=%d\n", __func__, ret);
74ff3e077bSSimon Glass 
75ff3e077bSSimon Glass 	return ret;
76ff3e077bSSimon Glass }
77ff3e077bSSimon Glass 
pci_last_busno(void)78ff3e077bSSimon Glass int pci_last_busno(void)
79ff3e077bSSimon Glass {
80069155cbSBin Meng 	return pci_get_bus_max();
81ff3e077bSSimon Glass }
82ff3e077bSSimon Glass 
pci_get_ff(enum pci_size_t size)83ff3e077bSSimon Glass int pci_get_ff(enum pci_size_t size)
84ff3e077bSSimon Glass {
85ff3e077bSSimon Glass 	switch (size) {
86ff3e077bSSimon Glass 	case PCI_SIZE_8:
87ff3e077bSSimon Glass 		return 0xff;
88ff3e077bSSimon Glass 	case PCI_SIZE_16:
89ff3e077bSSimon Glass 		return 0xffff;
90ff3e077bSSimon Glass 	default:
91ff3e077bSSimon Glass 		return 0xffffffff;
92ff3e077bSSimon Glass 	}
93ff3e077bSSimon Glass }
94ff3e077bSSimon Glass 
pci_bus_find_devfn(struct udevice * bus,pci_dev_t find_devfn,struct udevice ** devp)95ff3e077bSSimon Glass int pci_bus_find_devfn(struct udevice *bus, pci_dev_t find_devfn,
96ff3e077bSSimon Glass 		       struct udevice **devp)
97ff3e077bSSimon Glass {
98ff3e077bSSimon Glass 	struct udevice *dev;
99ff3e077bSSimon Glass 
100ff3e077bSSimon Glass 	for (device_find_first_child(bus, &dev);
101ff3e077bSSimon Glass 	     dev;
102ff3e077bSSimon Glass 	     device_find_next_child(&dev)) {
103ff3e077bSSimon Glass 		struct pci_child_platdata *pplat;
104ff3e077bSSimon Glass 
105ff3e077bSSimon Glass 		pplat = dev_get_parent_platdata(dev);
106ff3e077bSSimon Glass 		if (pplat && pplat->devfn == find_devfn) {
107ff3e077bSSimon Glass 			*devp = dev;
108ff3e077bSSimon Glass 			return 0;
109ff3e077bSSimon Glass 		}
110ff3e077bSSimon Glass 	}
111ff3e077bSSimon Glass 
112ff3e077bSSimon Glass 	return -ENODEV;
113ff3e077bSSimon Glass }
114ff3e077bSSimon Glass 
dm_pci_bus_find_bdf(pci_dev_t bdf,struct udevice ** devp)115f3f1faefSSimon Glass int dm_pci_bus_find_bdf(pci_dev_t bdf, struct udevice **devp)
116ff3e077bSSimon Glass {
117ff3e077bSSimon Glass 	struct udevice *bus;
118ff3e077bSSimon Glass 	int ret;
119ff3e077bSSimon Glass 
120983c6ba2SSimon Glass 	ret = pci_get_bus(PCI_BUS(bdf), &bus);
121ff3e077bSSimon Glass 	if (ret)
122ff3e077bSSimon Glass 		return ret;
123ff3e077bSSimon Glass 	return pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), devp);
124ff3e077bSSimon Glass }
125ff3e077bSSimon Glass 
pci_device_matches_ids(struct udevice * dev,struct pci_device_id * ids)126ff3e077bSSimon Glass static int pci_device_matches_ids(struct udevice *dev,
127ff3e077bSSimon Glass 				  struct pci_device_id *ids)
128ff3e077bSSimon Glass {
129ff3e077bSSimon Glass 	struct pci_child_platdata *pplat;
130ff3e077bSSimon Glass 	int i;
131ff3e077bSSimon Glass 
132ff3e077bSSimon Glass 	pplat = dev_get_parent_platdata(dev);
133ff3e077bSSimon Glass 	if (!pplat)
134ff3e077bSSimon Glass 		return -EINVAL;
135ff3e077bSSimon Glass 	for (i = 0; ids[i].vendor != 0; i++) {
136ff3e077bSSimon Glass 		if (pplat->vendor == ids[i].vendor &&
137ff3e077bSSimon Glass 		    pplat->device == ids[i].device)
138ff3e077bSSimon Glass 			return i;
139ff3e077bSSimon Glass 	}
140ff3e077bSSimon Glass 
141ff3e077bSSimon Glass 	return -EINVAL;
142ff3e077bSSimon Glass }
143ff3e077bSSimon Glass 
pci_bus_find_devices(struct udevice * bus,struct pci_device_id * ids,int * indexp,struct udevice ** devp)144ff3e077bSSimon Glass int pci_bus_find_devices(struct udevice *bus, struct pci_device_id *ids,
145ff3e077bSSimon Glass 			 int *indexp, struct udevice **devp)
146ff3e077bSSimon Glass {
147ff3e077bSSimon Glass 	struct udevice *dev;
148ff3e077bSSimon Glass 
149ff3e077bSSimon Glass 	/* Scan all devices on this bus */
150ff3e077bSSimon Glass 	for (device_find_first_child(bus, &dev);
151ff3e077bSSimon Glass 	     dev;
152ff3e077bSSimon Glass 	     device_find_next_child(&dev)) {
153ff3e077bSSimon Glass 		if (pci_device_matches_ids(dev, ids) >= 0) {
154ff3e077bSSimon Glass 			if ((*indexp)-- <= 0) {
155ff3e077bSSimon Glass 				*devp = dev;
156ff3e077bSSimon Glass 				return 0;
157ff3e077bSSimon Glass 			}
158ff3e077bSSimon Glass 		}
159ff3e077bSSimon Glass 	}
160ff3e077bSSimon Glass 
161ff3e077bSSimon Glass 	return -ENODEV;
162ff3e077bSSimon Glass }
163ff3e077bSSimon Glass 
pci_find_device_id(struct pci_device_id * ids,int index,struct udevice ** devp)164ff3e077bSSimon Glass int pci_find_device_id(struct pci_device_id *ids, int index,
165ff3e077bSSimon Glass 		       struct udevice **devp)
166ff3e077bSSimon Glass {
167ff3e077bSSimon Glass 	struct udevice *bus;
168ff3e077bSSimon Glass 
169ff3e077bSSimon Glass 	/* Scan all known buses */
170ff3e077bSSimon Glass 	for (uclass_first_device(UCLASS_PCI, &bus);
171ff3e077bSSimon Glass 	     bus;
172ff3e077bSSimon Glass 	     uclass_next_device(&bus)) {
173ff3e077bSSimon Glass 		if (!pci_bus_find_devices(bus, ids, &index, devp))
174ff3e077bSSimon Glass 			return 0;
175ff3e077bSSimon Glass 	}
176ff3e077bSSimon Glass 	*devp = NULL;
177ff3e077bSSimon Glass 
178ff3e077bSSimon Glass 	return -ENODEV;
179ff3e077bSSimon Glass }
180ff3e077bSSimon Glass 
dm_pci_bus_find_device(struct udevice * bus,unsigned int vendor,unsigned int device,int * indexp,struct udevice ** devp)1815c0bf647SSimon Glass static int dm_pci_bus_find_device(struct udevice *bus, unsigned int vendor,
1825c0bf647SSimon Glass 				  unsigned int device, int *indexp,
1835c0bf647SSimon Glass 				  struct udevice **devp)
1845c0bf647SSimon Glass {
1855c0bf647SSimon Glass 	struct pci_child_platdata *pplat;
1865c0bf647SSimon Glass 	struct udevice *dev;
1875c0bf647SSimon Glass 
1885c0bf647SSimon Glass 	for (device_find_first_child(bus, &dev);
1895c0bf647SSimon Glass 	     dev;
1905c0bf647SSimon Glass 	     device_find_next_child(&dev)) {
1915c0bf647SSimon Glass 		pplat = dev_get_parent_platdata(dev);
1925c0bf647SSimon Glass 		if (pplat->vendor == vendor && pplat->device == device) {
1935c0bf647SSimon Glass 			if (!(*indexp)--) {
1945c0bf647SSimon Glass 				*devp = dev;
1955c0bf647SSimon Glass 				return 0;
1965c0bf647SSimon Glass 			}
1975c0bf647SSimon Glass 		}
1985c0bf647SSimon Glass 	}
1995c0bf647SSimon Glass 
2005c0bf647SSimon Glass 	return -ENODEV;
2015c0bf647SSimon Glass }
2025c0bf647SSimon Glass 
dm_pci_find_device(unsigned int vendor,unsigned int device,int index,struct udevice ** devp)2035c0bf647SSimon Glass int dm_pci_find_device(unsigned int vendor, unsigned int device, int index,
2045c0bf647SSimon Glass 		       struct udevice **devp)
2055c0bf647SSimon Glass {
2065c0bf647SSimon Glass 	struct udevice *bus;
2075c0bf647SSimon Glass 
2085c0bf647SSimon Glass 	/* Scan all known buses */
2095c0bf647SSimon Glass 	for (uclass_first_device(UCLASS_PCI, &bus);
2105c0bf647SSimon Glass 	     bus;
2115c0bf647SSimon Glass 	     uclass_next_device(&bus)) {
2125c0bf647SSimon Glass 		if (!dm_pci_bus_find_device(bus, vendor, device, &index, devp))
2135c0bf647SSimon Glass 			return device_probe(*devp);
2145c0bf647SSimon Glass 	}
2155c0bf647SSimon Glass 	*devp = NULL;
2165c0bf647SSimon Glass 
2175c0bf647SSimon Glass 	return -ENODEV;
2185c0bf647SSimon Glass }
2195c0bf647SSimon Glass 
dm_pci_find_class(uint find_class,int index,struct udevice ** devp)220a0eb8356SSimon Glass int dm_pci_find_class(uint find_class, int index, struct udevice **devp)
221a0eb8356SSimon Glass {
222a0eb8356SSimon Glass 	struct udevice *dev;
223a0eb8356SSimon Glass 
224a0eb8356SSimon Glass 	/* Scan all known buses */
225a0eb8356SSimon Glass 	for (pci_find_first_device(&dev);
226a0eb8356SSimon Glass 	     dev;
227a0eb8356SSimon Glass 	     pci_find_next_device(&dev)) {
228a0eb8356SSimon Glass 		struct pci_child_platdata *pplat = dev_get_parent_platdata(dev);
229a0eb8356SSimon Glass 
230a0eb8356SSimon Glass 		if (pplat->class == find_class && !index--) {
231a0eb8356SSimon Glass 			*devp = dev;
232a0eb8356SSimon Glass 			return device_probe(*devp);
233a0eb8356SSimon Glass 		}
234a0eb8356SSimon Glass 	}
235a0eb8356SSimon Glass 	*devp = NULL;
236a0eb8356SSimon Glass 
237a0eb8356SSimon Glass 	return -ENODEV;
238a0eb8356SSimon Glass }
239a0eb8356SSimon Glass 
240e8697d50SShawn Lin /**
241e8697d50SShawn Lin  * pci_retrain_link - Trigger PCIe link retrain for a device
242e8697d50SShawn Lin  * @udev: PCI device to retrain link
243e8697d50SShawn Lin  * @dev:  PCI device and function address
244e8697d50SShawn Lin  *
245e8697d50SShawn Lin  * Return: 0 on success, negative error code on failure.
246e8697d50SShawn Lin  */
pci_retrain_link(struct udevice * udev,pci_dev_t dev)247e8697d50SShawn Lin int pci_retrain_link(struct udevice *udev, pci_dev_t dev)
248e8697d50SShawn Lin {
249e8697d50SShawn Lin 	u16 link_control, link_status;
250e8697d50SShawn Lin 	int pcie_cap_ptr;
251e8697d50SShawn Lin 	int timeout = 100; /* Timeout in milliseconds */
252e8697d50SShawn Lin 
253e8697d50SShawn Lin 	/* Find the PCIe Capability */
254e8697d50SShawn Lin 	pcie_cap_ptr = dm_pci_find_capability(udev, PCI_CAP_ID_EXP);
255e8697d50SShawn Lin 	if (!pcie_cap_ptr) {
256e8697d50SShawn Lin 		printf("PCIe Capability not found for device %04x:%04x\n",
257e8697d50SShawn Lin 			PCI_BUS(dev), PCI_DEV(dev));
258e8697d50SShawn Lin 		return -ENODEV;
259e8697d50SShawn Lin 	}
260e8697d50SShawn Lin 
261e8697d50SShawn Lin 	/* Read the Link Control Register */
262e8697d50SShawn Lin 	dm_pci_read_config16(udev, pcie_cap_ptr + PCI_EXP_LNKCTL, &link_control);
263e8697d50SShawn Lin 
264e8697d50SShawn Lin 	/* Set the Retrain Link bit (bit 5) */
265e8697d50SShawn Lin 	link_control |= (1 << 5);
266e8697d50SShawn Lin 
267e8697d50SShawn Lin 	/* Write the updated value back to the Link Control Register */
268e8697d50SShawn Lin 	dm_pci_write_config16(udev, pcie_cap_ptr + PCI_EXP_LNKCTL, link_control);
269e8697d50SShawn Lin 
270e8697d50SShawn Lin 	printf("Retrain triggered for device %04x:%04x\n", PCI_BUS(dev), PCI_DEV(dev));
271e8697d50SShawn Lin 
272e8697d50SShawn Lin 	/* Wait for the link to complete training */
273e8697d50SShawn Lin 	while (timeout--) {
274e8697d50SShawn Lin 		/* Read the Link Status Register */
275e8697d50SShawn Lin 		dm_pci_read_config16(udev, pcie_cap_ptr + PCI_EXP_LNKSTA, &link_status);
276e8697d50SShawn Lin 
277e8697d50SShawn Lin 		/* Check if the link is up and training is complete */
278e8697d50SShawn Lin 		if (!(link_status & PCI_EXP_LNKSTA_LT))
279e8697d50SShawn Lin 			break;
280e8697d50SShawn Lin 
281e8697d50SShawn Lin 		mdelay(10); /* Wait 1 millisecond */
282e8697d50SShawn Lin 	}
283e8697d50SShawn Lin 
284e8697d50SShawn Lin 	if (link_status & PCI_EXP_LNKSTA_LT) {
285e8697d50SShawn Lin 		printf("Link training failed for device %04x:%04x\n",
286e8697d50SShawn Lin 			PCI_BUS(dev), PCI_DEV(dev));
287e8697d50SShawn Lin 		return -ETIMEDOUT;
288e8697d50SShawn Lin 	}
289e8697d50SShawn Lin 
290e8697d50SShawn Lin 	printf("Link Status for device %04x:%04x: 0x%x\n",
291e8697d50SShawn Lin 		PCI_BUS(dev), PCI_DEV(dev), link_status);
292e8697d50SShawn Lin 	printf("  Speed: Gen%d\n", (link_status & PCI_EXP_LNKSTA_CLS) >> 0);
293e8697d50SShawn Lin 	printf("  Width: x%d\n", (link_status & PCI_EXP_LNKSTA_NLW) >> 4);
294e8697d50SShawn Lin 	printf("  Link Up: %s\n", (link_status & PCI_EXP_LNKSTA_LT) ? "No" : "Yes");
295e8697d50SShawn Lin 
296e8697d50SShawn Lin 	return 0;
297e8697d50SShawn Lin }
298e8697d50SShawn Lin 
pci_is_bridge(pci_dev_t dev)299*10dd02abSShawn Lin static int pci_is_bridge(pci_dev_t dev)
300*10dd02abSShawn Lin {
301*10dd02abSShawn Lin 	u8 header_type;
302*10dd02abSShawn Lin 
303*10dd02abSShawn Lin 	pci_read_config8(dev, PCI_HEADER_TYPE, &header_type);
304*10dd02abSShawn Lin 	header_type = header_type & 0x7f;
305*10dd02abSShawn Lin 
306*10dd02abSShawn Lin 	return (header_type == PCI_HEADER_TYPE_BRIDGE);
307*10dd02abSShawn Lin }
308*10dd02abSShawn Lin 
save_pci_state(pci_dev_t dev,struct pci_device_state * state)309*10dd02abSShawn Lin static void save_pci_state(pci_dev_t dev, struct pci_device_state *state)
310*10dd02abSShawn Lin {
311*10dd02abSShawn Lin 	int i;
312*10dd02abSShawn Lin 
313*10dd02abSShawn Lin 	/* Save BARs */
314*10dd02abSShawn Lin 	for (i = 0; i < 6; i++)
315*10dd02abSShawn Lin 		pci_read_config32(dev, PCI_BASE_ADDRESS_0 + i * 4, &state->bar[i]);
316*10dd02abSShawn Lin 
317*10dd02abSShawn Lin 	/* Save Command Register */
318*10dd02abSShawn Lin 	pci_read_config16(dev, PCI_COMMAND, &state->command);
319*10dd02abSShawn Lin 
320*10dd02abSShawn Lin 	/* Save Bus Numbers (for bridge devices) */
321*10dd02abSShawn Lin 	if (pci_is_bridge(dev)) {
322*10dd02abSShawn Lin 		pci_read_config8(dev, PCI_PRIMARY_BUS, &state->primary_bus);
323*10dd02abSShawn Lin 		pci_read_config8(dev, PCI_SECONDARY_BUS, &state->secondary_bus);
324*10dd02abSShawn Lin 		pci_read_config8(dev, PCI_SUBORDINATE_BUS, &state->subordinate_bus);
325*10dd02abSShawn Lin 	}
326*10dd02abSShawn Lin }
327*10dd02abSShawn Lin 
restore_pci_state(pci_dev_t dev,struct pci_device_state * state)328*10dd02abSShawn Lin static void restore_pci_state(pci_dev_t dev, struct pci_device_state *state)
329*10dd02abSShawn Lin {
330*10dd02abSShawn Lin 	int i;
331*10dd02abSShawn Lin 
332*10dd02abSShawn Lin 	/* Restore BARs */
333*10dd02abSShawn Lin 	for (i = 0; i < 6; i++)
334*10dd02abSShawn Lin 		pci_write_config32(dev, PCI_BASE_ADDRESS_0 + i * 4,
335*10dd02abSShawn Lin 				   state->bar[i]);
336*10dd02abSShawn Lin 
337*10dd02abSShawn Lin 	/* Restore Command Register */
338*10dd02abSShawn Lin 	pci_write_config16(dev, PCI_COMMAND, state->command);
339*10dd02abSShawn Lin 
340*10dd02abSShawn Lin 	/* Restore Bus Numbers (for bridge devices) */
341*10dd02abSShawn Lin 	if (pci_is_bridge(dev)) {
342*10dd02abSShawn Lin 		pci_write_config8(dev, PCI_PRIMARY_BUS, state->primary_bus);
343*10dd02abSShawn Lin 		pci_write_config8(dev, PCI_SECONDARY_BUS, state->secondary_bus);
344*10dd02abSShawn Lin 		pci_write_config8(dev, PCI_SUBORDINATE_BUS, state->subordinate_bus);
345*10dd02abSShawn Lin 	}
346*10dd02abSShawn Lin }
347*10dd02abSShawn Lin 
pci_flr(struct udevice * udev,pci_dev_t dev)348*10dd02abSShawn Lin static int pci_flr(struct udevice *udev, pci_dev_t dev)
349*10dd02abSShawn Lin {
350*10dd02abSShawn Lin 	u32 pcie_cap;
351*10dd02abSShawn Lin 	u16 devctl;
352*10dd02abSShawn Lin 	int pos;
353*10dd02abSShawn Lin 
354*10dd02abSShawn Lin 	pos = dm_pci_find_capability(udev, PCI_CAP_ID_EXP);
355*10dd02abSShawn Lin 	if (!pos) {
356*10dd02abSShawn Lin 		printf("PCIe Capability not found\n");
357*10dd02abSShawn Lin 		return -1;
358*10dd02abSShawn Lin 	}
359*10dd02abSShawn Lin 
360*10dd02abSShawn Lin 	/* Check if FLR is supported */
361*10dd02abSShawn Lin 	dm_pci_read_config32(udev, pos + PCI_EXP_DEVCAP, &pcie_cap);
362*10dd02abSShawn Lin 	if (!(pcie_cap & PCI_EXP_DEVCAP_FLR)) {
363*10dd02abSShawn Lin 		printf("FLR not supported by device, pos 0x%x, cap 0x%x\n", pos, pcie_cap);
364*10dd02abSShawn Lin 		return -1;
365*10dd02abSShawn Lin 	}
366*10dd02abSShawn Lin 
367*10dd02abSShawn Lin 	devctl = pcie_cap | PCI_EXP_DEVCTL_FLR;
368*10dd02abSShawn Lin 	dm_pci_write_config16(udev, pos + PCI_EXP_DEVCTL, devctl);
369*10dd02abSShawn Lin 	mdelay(100);
370*10dd02abSShawn Lin 	dm_pci_write_config16(udev, pos + PCI_EXP_DEVCTL, pcie_cap);
371*10dd02abSShawn Lin 
372*10dd02abSShawn Lin 	return 0;
373*10dd02abSShawn Lin }
374*10dd02abSShawn Lin 
pci_reset_function(struct udevice * udev,pci_dev_t dev)375*10dd02abSShawn Lin int pci_reset_function(struct udevice *udev, pci_dev_t dev)
376*10dd02abSShawn Lin {
377*10dd02abSShawn Lin 	struct pci_device_state state;
378*10dd02abSShawn Lin 
379*10dd02abSShawn Lin 	/* Save the current state */
380*10dd02abSShawn Lin 	save_pci_state(dev, &state);
381*10dd02abSShawn Lin 
382*10dd02abSShawn Lin 	/* Trigger FLR */
383*10dd02abSShawn Lin 	if (pci_flr(udev, dev)) {
384*10dd02abSShawn Lin 		printf("FLR failed\n");
385*10dd02abSShawn Lin 		return -1;
386*10dd02abSShawn Lin 	}
387*10dd02abSShawn Lin 
388*10dd02abSShawn Lin 	/* Restore the saved state */
389*10dd02abSShawn Lin 	restore_pci_state(dev, &state);
390*10dd02abSShawn Lin 
391*10dd02abSShawn Lin 	printf("FLR completed and state restored for device %02x:%02x.%d\n",
392*10dd02abSShawn Lin 		PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev));
393*10dd02abSShawn Lin 
394*10dd02abSShawn Lin 	return 0;
395*10dd02abSShawn Lin }
396*10dd02abSShawn Lin 
pci_bus_write_config(struct udevice * bus,pci_dev_t bdf,int offset,unsigned long value,enum pci_size_t size)397ff3e077bSSimon Glass int pci_bus_write_config(struct udevice *bus, pci_dev_t bdf, int offset,
398ff3e077bSSimon Glass 			 unsigned long value, enum pci_size_t size)
399ff3e077bSSimon Glass {
400ff3e077bSSimon Glass 	struct dm_pci_ops *ops;
401ff3e077bSSimon Glass 
402ff3e077bSSimon Glass 	ops = pci_get_ops(bus);
403ff3e077bSSimon Glass 	if (!ops->write_config)
404ff3e077bSSimon Glass 		return -ENOSYS;
405ff3e077bSSimon Glass 	return ops->write_config(bus, bdf, offset, value, size);
406ff3e077bSSimon Glass }
407ff3e077bSSimon Glass 
pci_bus_clrset_config32(struct udevice * bus,pci_dev_t bdf,int offset,u32 clr,u32 set)408319dba1fSSimon Glass int pci_bus_clrset_config32(struct udevice *bus, pci_dev_t bdf, int offset,
409319dba1fSSimon Glass 			    u32 clr, u32 set)
410319dba1fSSimon Glass {
411319dba1fSSimon Glass 	ulong val;
412319dba1fSSimon Glass 	int ret;
413319dba1fSSimon Glass 
414319dba1fSSimon Glass 	ret = pci_bus_read_config(bus, bdf, offset, &val, PCI_SIZE_32);
415319dba1fSSimon Glass 	if (ret)
416319dba1fSSimon Glass 		return ret;
417319dba1fSSimon Glass 	val &= ~clr;
418319dba1fSSimon Glass 	val |= set;
419319dba1fSSimon Glass 
420319dba1fSSimon Glass 	return pci_bus_write_config(bus, bdf, offset, val, PCI_SIZE_32);
421319dba1fSSimon Glass }
422319dba1fSSimon Glass 
pci_write_config(pci_dev_t bdf,int offset,unsigned long value,enum pci_size_t size)423ff3e077bSSimon Glass int pci_write_config(pci_dev_t bdf, int offset, unsigned long value,
424ff3e077bSSimon Glass 		     enum pci_size_t size)
425ff3e077bSSimon Glass {
426ff3e077bSSimon Glass 	struct udevice *bus;
427ff3e077bSSimon Glass 	int ret;
428ff3e077bSSimon Glass 
429983c6ba2SSimon Glass 	ret = pci_get_bus(PCI_BUS(bdf), &bus);
430ff3e077bSSimon Glass 	if (ret)
431ff3e077bSSimon Glass 		return ret;
432ff3e077bSSimon Glass 
4334d8615cbSBin Meng 	return pci_bus_write_config(bus, bdf, offset, value, size);
434ff3e077bSSimon Glass }
435ff3e077bSSimon Glass 
dm_pci_write_config(struct udevice * dev,int offset,unsigned long value,enum pci_size_t size)43666afb4edSSimon Glass int dm_pci_write_config(struct udevice *dev, int offset, unsigned long value,
43766afb4edSSimon Glass 			enum pci_size_t size)
43866afb4edSSimon Glass {
43966afb4edSSimon Glass 	struct udevice *bus;
44066afb4edSSimon Glass 
4411e0f2263SBin Meng 	for (bus = dev; device_is_on_pci_bus(bus);)
44266afb4edSSimon Glass 		bus = bus->parent;
44321ccce1bSSimon Glass 	return pci_bus_write_config(bus, dm_pci_get_bdf(dev), offset, value,
44421ccce1bSSimon Glass 				    size);
44566afb4edSSimon Glass }
44666afb4edSSimon Glass 
pci_write_config32(pci_dev_t bdf,int offset,u32 value)447ff3e077bSSimon Glass int pci_write_config32(pci_dev_t bdf, int offset, u32 value)
448ff3e077bSSimon Glass {
449ff3e077bSSimon Glass 	return pci_write_config(bdf, offset, value, PCI_SIZE_32);
450ff3e077bSSimon Glass }
451ff3e077bSSimon Glass 
pci_write_config16(pci_dev_t bdf,int offset,u16 value)452ff3e077bSSimon Glass int pci_write_config16(pci_dev_t bdf, int offset, u16 value)
453ff3e077bSSimon Glass {
454ff3e077bSSimon Glass 	return pci_write_config(bdf, offset, value, PCI_SIZE_16);
455ff3e077bSSimon Glass }
456ff3e077bSSimon Glass 
pci_write_config8(pci_dev_t bdf,int offset,u8 value)457ff3e077bSSimon Glass int pci_write_config8(pci_dev_t bdf, int offset, u8 value)
458ff3e077bSSimon Glass {
459ff3e077bSSimon Glass 	return pci_write_config(bdf, offset, value, PCI_SIZE_8);
460ff3e077bSSimon Glass }
461ff3e077bSSimon Glass 
dm_pci_write_config8(struct udevice * dev,int offset,u8 value)46266afb4edSSimon Glass int dm_pci_write_config8(struct udevice *dev, int offset, u8 value)
46366afb4edSSimon Glass {
46466afb4edSSimon Glass 	return dm_pci_write_config(dev, offset, value, PCI_SIZE_8);
46566afb4edSSimon Glass }
46666afb4edSSimon Glass 
dm_pci_write_config16(struct udevice * dev,int offset,u16 value)46766afb4edSSimon Glass int dm_pci_write_config16(struct udevice *dev, int offset, u16 value)
46866afb4edSSimon Glass {
46966afb4edSSimon Glass 	return dm_pci_write_config(dev, offset, value, PCI_SIZE_16);
47066afb4edSSimon Glass }
47166afb4edSSimon Glass 
dm_pci_write_config32(struct udevice * dev,int offset,u32 value)47266afb4edSSimon Glass int dm_pci_write_config32(struct udevice *dev, int offset, u32 value)
47366afb4edSSimon Glass {
47466afb4edSSimon Glass 	return dm_pci_write_config(dev, offset, value, PCI_SIZE_32);
47566afb4edSSimon Glass }
47666afb4edSSimon Glass 
pci_bus_read_config(struct udevice * bus,pci_dev_t bdf,int offset,unsigned long * valuep,enum pci_size_t size)477ff3e077bSSimon Glass int pci_bus_read_config(struct udevice *bus, pci_dev_t bdf, int offset,
478ff3e077bSSimon Glass 			unsigned long *valuep, enum pci_size_t size)
479ff3e077bSSimon Glass {
480ff3e077bSSimon Glass 	struct dm_pci_ops *ops;
481ff3e077bSSimon Glass 
482ff3e077bSSimon Glass 	ops = pci_get_ops(bus);
483ff3e077bSSimon Glass 	if (!ops->read_config)
484ff3e077bSSimon Glass 		return -ENOSYS;
485ff3e077bSSimon Glass 	return ops->read_config(bus, bdf, offset, valuep, size);
486ff3e077bSSimon Glass }
487ff3e077bSSimon Glass 
pci_read_config(pci_dev_t bdf,int offset,unsigned long * valuep,enum pci_size_t size)488ff3e077bSSimon Glass int pci_read_config(pci_dev_t bdf, int offset, unsigned long *valuep,
489ff3e077bSSimon Glass 		    enum pci_size_t size)
490ff3e077bSSimon Glass {
491ff3e077bSSimon Glass 	struct udevice *bus;
492ff3e077bSSimon Glass 	int ret;
493ff3e077bSSimon Glass 
494983c6ba2SSimon Glass 	ret = pci_get_bus(PCI_BUS(bdf), &bus);
495ff3e077bSSimon Glass 	if (ret)
496ff3e077bSSimon Glass 		return ret;
497ff3e077bSSimon Glass 
4984d8615cbSBin Meng 	return pci_bus_read_config(bus, bdf, offset, valuep, size);
499ff3e077bSSimon Glass }
500ff3e077bSSimon Glass 
dm_pci_read_config(struct udevice * dev,int offset,unsigned long * valuep,enum pci_size_t size)50166afb4edSSimon Glass int dm_pci_read_config(struct udevice *dev, int offset, unsigned long *valuep,
50266afb4edSSimon Glass 		       enum pci_size_t size)
50366afb4edSSimon Glass {
50466afb4edSSimon Glass 	struct udevice *bus;
50566afb4edSSimon Glass 
5061e0f2263SBin Meng 	for (bus = dev; device_is_on_pci_bus(bus);)
50766afb4edSSimon Glass 		bus = bus->parent;
50821ccce1bSSimon Glass 	return pci_bus_read_config(bus, dm_pci_get_bdf(dev), offset, valuep,
50966afb4edSSimon Glass 				   size);
51066afb4edSSimon Glass }
51166afb4edSSimon Glass 
pci_read_config32(pci_dev_t bdf,int offset,u32 * valuep)512ff3e077bSSimon Glass int pci_read_config32(pci_dev_t bdf, int offset, u32 *valuep)
513ff3e077bSSimon Glass {
514ff3e077bSSimon Glass 	unsigned long value;
515ff3e077bSSimon Glass 	int ret;
516ff3e077bSSimon Glass 
517ff3e077bSSimon Glass 	ret = pci_read_config(bdf, offset, &value, PCI_SIZE_32);
518ff3e077bSSimon Glass 	if (ret)
519ff3e077bSSimon Glass 		return ret;
520ff3e077bSSimon Glass 	*valuep = value;
521ff3e077bSSimon Glass 
522ff3e077bSSimon Glass 	return 0;
523ff3e077bSSimon Glass }
524ff3e077bSSimon Glass 
pci_read_config16(pci_dev_t bdf,int offset,u16 * valuep)525ff3e077bSSimon Glass int pci_read_config16(pci_dev_t bdf, int offset, u16 *valuep)
526ff3e077bSSimon Glass {
527ff3e077bSSimon Glass 	unsigned long value;
528ff3e077bSSimon Glass 	int ret;
529ff3e077bSSimon Glass 
530ff3e077bSSimon Glass 	ret = pci_read_config(bdf, offset, &value, PCI_SIZE_16);
531ff3e077bSSimon Glass 	if (ret)
532ff3e077bSSimon Glass 		return ret;
533ff3e077bSSimon Glass 	*valuep = value;
534ff3e077bSSimon Glass 
535ff3e077bSSimon Glass 	return 0;
536ff3e077bSSimon Glass }
537ff3e077bSSimon Glass 
pci_read_config8(pci_dev_t bdf,int offset,u8 * valuep)538ff3e077bSSimon Glass int pci_read_config8(pci_dev_t bdf, int offset, u8 *valuep)
539ff3e077bSSimon Glass {
540ff3e077bSSimon Glass 	unsigned long value;
541ff3e077bSSimon Glass 	int ret;
542ff3e077bSSimon Glass 
543ff3e077bSSimon Glass 	ret = pci_read_config(bdf, offset, &value, PCI_SIZE_8);
544ff3e077bSSimon Glass 	if (ret)
545ff3e077bSSimon Glass 		return ret;
546ff3e077bSSimon Glass 	*valuep = value;
547ff3e077bSSimon Glass 
548ff3e077bSSimon Glass 	return 0;
549ff3e077bSSimon Glass }
550ff3e077bSSimon Glass 
dm_pci_read_config8(struct udevice * dev,int offset,u8 * valuep)55166afb4edSSimon Glass int dm_pci_read_config8(struct udevice *dev, int offset, u8 *valuep)
55266afb4edSSimon Glass {
55366afb4edSSimon Glass 	unsigned long value;
55466afb4edSSimon Glass 	int ret;
55566afb4edSSimon Glass 
55666afb4edSSimon Glass 	ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_8);
55766afb4edSSimon Glass 	if (ret)
55866afb4edSSimon Glass 		return ret;
55966afb4edSSimon Glass 	*valuep = value;
56066afb4edSSimon Glass 
56166afb4edSSimon Glass 	return 0;
56266afb4edSSimon Glass }
56366afb4edSSimon Glass 
dm_pci_read_config16(struct udevice * dev,int offset,u16 * valuep)56466afb4edSSimon Glass int dm_pci_read_config16(struct udevice *dev, int offset, u16 *valuep)
56566afb4edSSimon Glass {
56666afb4edSSimon Glass 	unsigned long value;
56766afb4edSSimon Glass 	int ret;
56866afb4edSSimon Glass 
56966afb4edSSimon Glass 	ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_16);
57066afb4edSSimon Glass 	if (ret)
57166afb4edSSimon Glass 		return ret;
57266afb4edSSimon Glass 	*valuep = value;
57366afb4edSSimon Glass 
57466afb4edSSimon Glass 	return 0;
57566afb4edSSimon Glass }
57666afb4edSSimon Glass 
dm_pci_read_config32(struct udevice * dev,int offset,u32 * valuep)57766afb4edSSimon Glass int dm_pci_read_config32(struct udevice *dev, int offset, u32 *valuep)
57866afb4edSSimon Glass {
57966afb4edSSimon Glass 	unsigned long value;
58066afb4edSSimon Glass 	int ret;
58166afb4edSSimon Glass 
58266afb4edSSimon Glass 	ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_32);
58366afb4edSSimon Glass 	if (ret)
58466afb4edSSimon Glass 		return ret;
58566afb4edSSimon Glass 	*valuep = value;
58666afb4edSSimon Glass 
58766afb4edSSimon Glass 	return 0;
58866afb4edSSimon Glass }
58966afb4edSSimon Glass 
dm_pci_clrset_config8(struct udevice * dev,int offset,u32 clr,u32 set)590319dba1fSSimon Glass int dm_pci_clrset_config8(struct udevice *dev, int offset, u32 clr, u32 set)
591319dba1fSSimon Glass {
592319dba1fSSimon Glass 	u8 val;
593319dba1fSSimon Glass 	int ret;
594319dba1fSSimon Glass 
595319dba1fSSimon Glass 	ret = dm_pci_read_config8(dev, offset, &val);
596319dba1fSSimon Glass 	if (ret)
597319dba1fSSimon Glass 		return ret;
598319dba1fSSimon Glass 	val &= ~clr;
599319dba1fSSimon Glass 	val |= set;
600319dba1fSSimon Glass 
601319dba1fSSimon Glass 	return dm_pci_write_config8(dev, offset, val);
602319dba1fSSimon Glass }
603319dba1fSSimon Glass 
dm_pci_clrset_config16(struct udevice * dev,int offset,u32 clr,u32 set)604319dba1fSSimon Glass int dm_pci_clrset_config16(struct udevice *dev, int offset, u32 clr, u32 set)
605319dba1fSSimon Glass {
606319dba1fSSimon Glass 	u16 val;
607319dba1fSSimon Glass 	int ret;
608319dba1fSSimon Glass 
609319dba1fSSimon Glass 	ret = dm_pci_read_config16(dev, offset, &val);
610319dba1fSSimon Glass 	if (ret)
611319dba1fSSimon Glass 		return ret;
612319dba1fSSimon Glass 	val &= ~clr;
613319dba1fSSimon Glass 	val |= set;
614319dba1fSSimon Glass 
615319dba1fSSimon Glass 	return dm_pci_write_config16(dev, offset, val);
616319dba1fSSimon Glass }
617319dba1fSSimon Glass 
dm_pci_clrset_config32(struct udevice * dev,int offset,u32 clr,u32 set)618319dba1fSSimon Glass int dm_pci_clrset_config32(struct udevice *dev, int offset, u32 clr, u32 set)
619319dba1fSSimon Glass {
620319dba1fSSimon Glass 	u32 val;
621319dba1fSSimon Glass 	int ret;
622319dba1fSSimon Glass 
623319dba1fSSimon Glass 	ret = dm_pci_read_config32(dev, offset, &val);
624319dba1fSSimon Glass 	if (ret)
625319dba1fSSimon Glass 		return ret;
626319dba1fSSimon Glass 	val &= ~clr;
627319dba1fSSimon Glass 	val |= set;
628319dba1fSSimon Glass 
629319dba1fSSimon Glass 	return dm_pci_write_config32(dev, offset, val);
630319dba1fSSimon Glass }
631319dba1fSSimon Glass 
set_vga_bridge_bits(struct udevice * dev)632bbbcb526SBin Meng static void set_vga_bridge_bits(struct udevice *dev)
633bbbcb526SBin Meng {
634bbbcb526SBin Meng 	struct udevice *parent = dev->parent;
635bbbcb526SBin Meng 	u16 bc;
636bbbcb526SBin Meng 
637bbbcb526SBin Meng 	while (parent->seq != 0) {
638bbbcb526SBin Meng 		dm_pci_read_config16(parent, PCI_BRIDGE_CONTROL, &bc);
639bbbcb526SBin Meng 		bc |= PCI_BRIDGE_CTL_VGA;
640bbbcb526SBin Meng 		dm_pci_write_config16(parent, PCI_BRIDGE_CONTROL, bc);
641bbbcb526SBin Meng 		parent = parent->parent;
642bbbcb526SBin Meng 	}
643bbbcb526SBin Meng }
644bbbcb526SBin Meng 
pci_auto_config_devices(struct udevice * bus)645ff3e077bSSimon Glass int pci_auto_config_devices(struct udevice *bus)
646ff3e077bSSimon Glass {
647ff3e077bSSimon Glass 	struct pci_controller *hose = bus->uclass_priv;
648bbbcb526SBin Meng 	struct pci_child_platdata *pplat;
649ff3e077bSSimon Glass 	unsigned int sub_bus;
650ff3e077bSSimon Glass 	struct udevice *dev;
651ff3e077bSSimon Glass 	int ret;
652ff3e077bSSimon Glass 
653ff3e077bSSimon Glass 	sub_bus = bus->seq;
654ff3e077bSSimon Glass 	debug("%s: start\n", __func__);
655ff3e077bSSimon Glass 	pciauto_config_init(hose);
656ff3e077bSSimon Glass 	for (ret = device_find_first_child(bus, &dev);
657ff3e077bSSimon Glass 	     !ret && dev;
658ff3e077bSSimon Glass 	     ret = device_find_next_child(&dev)) {
659ff3e077bSSimon Glass 		unsigned int max_bus;
6604d21455eSSimon Glass 		int ret;
661ff3e077bSSimon Glass 
662ff3e077bSSimon Glass 		debug("%s: device %s\n", __func__, dev->name);
6635e23b8b4SSimon Glass 		ret = dm_pciauto_config_device(dev);
6644d21455eSSimon Glass 		if (ret < 0)
6654d21455eSSimon Glass 			return ret;
6664d21455eSSimon Glass 		max_bus = ret;
667ff3e077bSSimon Glass 		sub_bus = max(sub_bus, max_bus);
668bbbcb526SBin Meng 
669bbbcb526SBin Meng 		pplat = dev_get_parent_platdata(dev);
670bbbcb526SBin Meng 		if (pplat->class == (PCI_CLASS_DISPLAY_VGA << 8))
671bbbcb526SBin Meng 			set_vga_bridge_bits(dev);
672ff3e077bSSimon Glass 	}
673ff3e077bSSimon Glass 	debug("%s: done\n", __func__);
674ff3e077bSSimon Glass 
675ff3e077bSSimon Glass 	return sub_bus;
676ff3e077bSSimon Glass }
677ff3e077bSSimon Glass 
dm_pci_hose_probe_bus(struct udevice * bus)6785e23b8b4SSimon Glass int dm_pci_hose_probe_bus(struct udevice *bus)
679ff3e077bSSimon Glass {
680ff3e077bSSimon Glass 	int sub_bus;
681ff3e077bSSimon Glass 	int ret;
682ff3e077bSSimon Glass 
683ff3e077bSSimon Glass 	debug("%s\n", __func__);
684ff3e077bSSimon Glass 
685ff3e077bSSimon Glass 	sub_bus = pci_get_bus_max() + 1;
686ff3e077bSSimon Glass 	debug("%s: bus = %d/%s\n", __func__, sub_bus, bus->name);
6875e23b8b4SSimon Glass 	dm_pciauto_prescan_setup_bridge(bus, sub_bus);
688ff3e077bSSimon Glass 
689ff3e077bSSimon Glass 	ret = device_probe(bus);
690ff3e077bSSimon Glass 	if (ret) {
6913129ace4SSimon Glass 		debug("%s: Cannot probe bus %s: %d\n", __func__, bus->name,
692ff3e077bSSimon Glass 		      ret);
693ff3e077bSSimon Glass 		return ret;
694ff3e077bSSimon Glass 	}
695ff3e077bSSimon Glass 	if (sub_bus != bus->seq) {
696ff3e077bSSimon Glass 		printf("%s: Internal error, bus '%s' got seq %d, expected %d\n",
697ff3e077bSSimon Glass 		       __func__, bus->name, bus->seq, sub_bus);
698ff3e077bSSimon Glass 		return -EPIPE;
699ff3e077bSSimon Glass 	}
700ff3e077bSSimon Glass 	sub_bus = pci_get_bus_max();
7015e23b8b4SSimon Glass 	dm_pciauto_postscan_setup_bridge(bus, sub_bus);
702ff3e077bSSimon Glass 
703ff3e077bSSimon Glass 	return sub_bus;
704ff3e077bSSimon Glass }
705ff3e077bSSimon Glass 
706aba92962SSimon Glass /**
707aba92962SSimon Glass  * pci_match_one_device - Tell if a PCI device structure has a matching
708aba92962SSimon Glass  *                        PCI device id structure
709aba92962SSimon Glass  * @id: single PCI device id structure to match
7100367bd4dSHou Zhiqiang  * @find: the PCI device id structure to match against
711aba92962SSimon Glass  *
7120367bd4dSHou Zhiqiang  * Returns true if the finding pci_device_id structure matched or false if
7130367bd4dSHou Zhiqiang  * there is no match.
714aba92962SSimon Glass  */
pci_match_one_id(const struct pci_device_id * id,const struct pci_device_id * find)715aba92962SSimon Glass static bool pci_match_one_id(const struct pci_device_id *id,
716aba92962SSimon Glass 			     const struct pci_device_id *find)
717aba92962SSimon Glass {
718aba92962SSimon Glass 	if ((id->vendor == PCI_ANY_ID || id->vendor == find->vendor) &&
719aba92962SSimon Glass 	    (id->device == PCI_ANY_ID || id->device == find->device) &&
720aba92962SSimon Glass 	    (id->subvendor == PCI_ANY_ID || id->subvendor == find->subvendor) &&
721aba92962SSimon Glass 	    (id->subdevice == PCI_ANY_ID || id->subdevice == find->subdevice) &&
722aba92962SSimon Glass 	    !((id->class ^ find->class) & id->class_mask))
723aba92962SSimon Glass 		return true;
724aba92962SSimon Glass 
725aba92962SSimon Glass 	return false;
726aba92962SSimon Glass }
727aba92962SSimon Glass 
728aba92962SSimon Glass /**
729aba92962SSimon Glass  * pci_find_and_bind_driver() - Find and bind the right PCI driver
730aba92962SSimon Glass  *
731aba92962SSimon Glass  * This only looks at certain fields in the descriptor.
7325dbcf3a0SSimon Glass  *
7335dbcf3a0SSimon Glass  * @parent:	Parent bus
7345dbcf3a0SSimon Glass  * @find_id:	Specification of the driver to find
7355dbcf3a0SSimon Glass  * @bdf:	Bus/device/function addreess - see PCI_BDF()
7365dbcf3a0SSimon Glass  * @devp:	Returns a pointer to the device created
7375dbcf3a0SSimon Glass  * @return 0 if OK, -EPERM if the device is not needed before relocation and
7385dbcf3a0SSimon Glass  *	   therefore was not created, other -ve value on error
739aba92962SSimon Glass  */
pci_find_and_bind_driver(struct udevice * parent,struct pci_device_id * find_id,pci_dev_t bdf,struct udevice ** devp)740aba92962SSimon Glass static int pci_find_and_bind_driver(struct udevice *parent,
7415dbcf3a0SSimon Glass 				    struct pci_device_id *find_id,
7425dbcf3a0SSimon Glass 				    pci_dev_t bdf, struct udevice **devp)
743aba92962SSimon Glass {
744aba92962SSimon Glass 	struct pci_driver_entry *start, *entry;
745aba92962SSimon Glass 	const char *drv;
746aba92962SSimon Glass 	int n_ents;
747aba92962SSimon Glass 	int ret;
748aba92962SSimon Glass 	char name[30], *str;
74908fc7b8fSBin Meng 	bool bridge;
750aba92962SSimon Glass 
751aba92962SSimon Glass 	*devp = NULL;
752aba92962SSimon Glass 
753aba92962SSimon Glass 	debug("%s: Searching for driver: vendor=%x, device=%x\n", __func__,
754aba92962SSimon Glass 	      find_id->vendor, find_id->device);
755aba92962SSimon Glass 	start = ll_entry_start(struct pci_driver_entry, pci_driver_entry);
756aba92962SSimon Glass 	n_ents = ll_entry_count(struct pci_driver_entry, pci_driver_entry);
757aba92962SSimon Glass 	for (entry = start; entry != start + n_ents; entry++) {
758aba92962SSimon Glass 		const struct pci_device_id *id;
759aba92962SSimon Glass 		struct udevice *dev;
760aba92962SSimon Glass 		const struct driver *drv;
761aba92962SSimon Glass 
762aba92962SSimon Glass 		for (id = entry->match;
763aba92962SSimon Glass 		     id->vendor || id->subvendor || id->class_mask;
764aba92962SSimon Glass 		     id++) {
765aba92962SSimon Glass 			if (!pci_match_one_id(id, find_id))
766aba92962SSimon Glass 				continue;
767aba92962SSimon Glass 
768aba92962SSimon Glass 			drv = entry->driver;
76908fc7b8fSBin Meng 
77008fc7b8fSBin Meng 			/*
77108fc7b8fSBin Meng 			 * In the pre-relocation phase, we only bind devices
77208fc7b8fSBin Meng 			 * whose driver has the DM_FLAG_PRE_RELOC set, to save
77308fc7b8fSBin Meng 			 * precious memory space as on some platforms as that
77408fc7b8fSBin Meng 			 * space is pretty limited (ie: using Cache As RAM).
77508fc7b8fSBin Meng 			 */
77608fc7b8fSBin Meng 			if (!(gd->flags & GD_FLG_RELOC) &&
77708fc7b8fSBin Meng 			    !(drv->flags & DM_FLAG_PRE_RELOC))
7785dbcf3a0SSimon Glass 				return -EPERM;
77908fc7b8fSBin Meng 
780aba92962SSimon Glass 			/*
781aba92962SSimon Glass 			 * We could pass the descriptor to the driver as
782aba92962SSimon Glass 			 * platdata (instead of NULL) and allow its bind()
783aba92962SSimon Glass 			 * method to return -ENOENT if it doesn't support this
784aba92962SSimon Glass 			 * device. That way we could continue the search to
785aba92962SSimon Glass 			 * find another driver. For now this doesn't seem
786aba92962SSimon Glass 			 * necesssary, so just bind the first match.
787aba92962SSimon Glass 			 */
788aba92962SSimon Glass 			ret = device_bind(parent, drv, drv->name, NULL, -1,
789aba92962SSimon Glass 					  &dev);
790aba92962SSimon Glass 			if (ret)
791aba92962SSimon Glass 				goto error;
792aba92962SSimon Glass 			debug("%s: Match found: %s\n", __func__, drv->name);
793aba92962SSimon Glass 			dev->driver_data = find_id->driver_data;
794aba92962SSimon Glass 			*devp = dev;
795aba92962SSimon Glass 			return 0;
796aba92962SSimon Glass 		}
797aba92962SSimon Glass 	}
798aba92962SSimon Glass 
79908fc7b8fSBin Meng 	bridge = (find_id->class >> 8) == PCI_CLASS_BRIDGE_PCI;
80008fc7b8fSBin Meng 	/*
80108fc7b8fSBin Meng 	 * In the pre-relocation phase, we only bind bridge devices to save
80208fc7b8fSBin Meng 	 * precious memory space as on some platforms as that space is pretty
80308fc7b8fSBin Meng 	 * limited (ie: using Cache As RAM).
80408fc7b8fSBin Meng 	 */
80508fc7b8fSBin Meng 	if (!(gd->flags & GD_FLG_RELOC) && !bridge)
8065dbcf3a0SSimon Glass 		return -EPERM;
80708fc7b8fSBin Meng 
808aba92962SSimon Glass 	/* Bind a generic driver so that the device can be used */
8094d8615cbSBin Meng 	sprintf(name, "pci_%x:%x.%x", parent->seq, PCI_DEV(bdf),
8104d8615cbSBin Meng 		PCI_FUNC(bdf));
811aba92962SSimon Glass 	str = strdup(name);
812aba92962SSimon Glass 	if (!str)
813aba92962SSimon Glass 		return -ENOMEM;
81408fc7b8fSBin Meng 	drv = bridge ? "pci_bridge_drv" : "pci_generic_drv";
81508fc7b8fSBin Meng 
816aba92962SSimon Glass 	ret = device_bind_driver(parent, drv, str, devp);
817aba92962SSimon Glass 	if (ret) {
8183129ace4SSimon Glass 		debug("%s: Failed to bind generic driver: %d\n", __func__, ret);
819c42640c7Sxypron.glpk@gmx.de 		free(str);
820aba92962SSimon Glass 		return ret;
821aba92962SSimon Glass 	}
822aba92962SSimon Glass 	debug("%s: No match found: bound generic driver instead\n", __func__);
823aba92962SSimon Glass 
824aba92962SSimon Glass 	return 0;
825aba92962SSimon Glass 
826aba92962SSimon Glass error:
827aba92962SSimon Glass 	debug("%s: No match found: error %d\n", __func__, ret);
828aba92962SSimon Glass 	return ret;
829aba92962SSimon Glass }
830aba92962SSimon Glass 
pci_bind_bus_devices(struct udevice * bus)831ff3e077bSSimon Glass int pci_bind_bus_devices(struct udevice *bus)
832ff3e077bSSimon Glass {
833ff3e077bSSimon Glass 	ulong vendor, device;
834ff3e077bSSimon Glass 	ulong header_type;
8354d8615cbSBin Meng 	pci_dev_t bdf, end;
836ff3e077bSSimon Glass 	bool found_multi;
837ff3e077bSSimon Glass 	int ret;
838ff3e077bSSimon Glass 
839ff3e077bSSimon Glass 	found_multi = false;
8404d8615cbSBin Meng 	end = PCI_BDF(bus->seq, PCI_MAX_PCI_DEVICES - 1,
8414d8615cbSBin Meng 		      PCI_MAX_PCI_FUNCTIONS - 1);
8426d9f5b03SYoshinori Sato 	for (bdf = PCI_BDF(bus->seq, 0, 0); bdf <= end;
8434d8615cbSBin Meng 	     bdf += PCI_BDF(0, 0, 1)) {
844ff3e077bSSimon Glass 		struct pci_child_platdata *pplat;
845ff3e077bSSimon Glass 		struct udevice *dev;
846ff3e077bSSimon Glass 		ulong class;
847ff3e077bSSimon Glass 
8484d8615cbSBin Meng 		if (PCI_FUNC(bdf) && !found_multi)
849ff3e077bSSimon Glass 			continue;
850ff3e077bSSimon Glass 		/* Check only the first access, we don't expect problems */
8514d8615cbSBin Meng 		ret = pci_bus_read_config(bus, bdf, PCI_HEADER_TYPE,
852ff3e077bSSimon Glass 					  &header_type, PCI_SIZE_8);
853ff3e077bSSimon Glass 		if (ret)
854ff3e077bSSimon Glass 			goto error;
8554d8615cbSBin Meng 		pci_bus_read_config(bus, bdf, PCI_VENDOR_ID, &vendor,
856ff3e077bSSimon Glass 				    PCI_SIZE_16);
857ff3e077bSSimon Glass 		if (vendor == 0xffff || vendor == 0x0000)
858ff3e077bSSimon Glass 			continue;
859ff3e077bSSimon Glass 
8604d8615cbSBin Meng 		if (!PCI_FUNC(bdf))
861ff3e077bSSimon Glass 			found_multi = header_type & 0x80;
862ff3e077bSSimon Glass 
863ff3e077bSSimon Glass 		debug("%s: bus %d/%s: found device %x, function %d\n", __func__,
8644d8615cbSBin Meng 		      bus->seq, bus->name, PCI_DEV(bdf), PCI_FUNC(bdf));
8654d8615cbSBin Meng 		pci_bus_read_config(bus, bdf, PCI_DEVICE_ID, &device,
866ff3e077bSSimon Glass 				    PCI_SIZE_16);
8674d8615cbSBin Meng 		pci_bus_read_config(bus, bdf, PCI_CLASS_REVISION, &class,
868aba92962SSimon Glass 				    PCI_SIZE_32);
869aba92962SSimon Glass 		class >>= 8;
870ff3e077bSSimon Glass 
871ff3e077bSSimon Glass 		/* Find this device in the device tree */
8724d8615cbSBin Meng 		ret = pci_bus_find_devfn(bus, PCI_MASK_BUS(bdf), &dev);
873ff3e077bSSimon Glass 
8748bd42525SSimon Glass 		/* If nothing in the device tree, bind a device */
875ff3e077bSSimon Glass 		if (ret == -ENODEV) {
876aba92962SSimon Glass 			struct pci_device_id find_id;
877aba92962SSimon Glass 			ulong val;
878ff3e077bSSimon Glass 
879aba92962SSimon Glass 			memset(&find_id, '\0', sizeof(find_id));
880aba92962SSimon Glass 			find_id.vendor = vendor;
881aba92962SSimon Glass 			find_id.device = device;
882aba92962SSimon Glass 			find_id.class = class;
883aba92962SSimon Glass 			if ((header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL) {
8844d8615cbSBin Meng 				pci_bus_read_config(bus, bdf,
885aba92962SSimon Glass 						    PCI_SUBSYSTEM_VENDOR_ID,
886aba92962SSimon Glass 						    &val, PCI_SIZE_32);
887aba92962SSimon Glass 				find_id.subvendor = val & 0xffff;
888aba92962SSimon Glass 				find_id.subdevice = val >> 16;
889aba92962SSimon Glass 			}
8904d8615cbSBin Meng 			ret = pci_find_and_bind_driver(bus, &find_id, bdf,
891aba92962SSimon Glass 						       &dev);
892ff3e077bSSimon Glass 		}
8935dbcf3a0SSimon Glass 		if (ret == -EPERM)
8945dbcf3a0SSimon Glass 			continue;
8955dbcf3a0SSimon Glass 		else if (ret)
896ff3e077bSSimon Glass 			return ret;
897ff3e077bSSimon Glass 
898ff3e077bSSimon Glass 		/* Update the platform data */
899ff3e077bSSimon Glass 		pplat = dev_get_parent_platdata(dev);
9004d8615cbSBin Meng 		pplat->devfn = PCI_MASK_BUS(bdf);
901ff3e077bSSimon Glass 		pplat->vendor = vendor;
902ff3e077bSSimon Glass 		pplat->device = device;
903ff3e077bSSimon Glass 		pplat->class = class;
904ff3e077bSSimon Glass 	}
905ff3e077bSSimon Glass 
906ff3e077bSSimon Glass 	return 0;
907ff3e077bSSimon Glass error:
908ff3e077bSSimon Glass 	printf("Cannot read bus configuration: %d\n", ret);
909ff3e077bSSimon Glass 
910ff3e077bSSimon Glass 	return ret;
911ff3e077bSSimon Glass }
912ff3e077bSSimon Glass 
decode_regions(struct pci_controller * hose,ofnode parent_node,ofnode node)913bf501595SSimon Glass static int decode_regions(struct pci_controller *hose, ofnode parent_node,
914bf501595SSimon Glass 			  ofnode node)
915ff3e077bSSimon Glass {
916ff3e077bSSimon Glass 	int pci_addr_cells, addr_cells, size_cells;
9172084c5afSSimon Glass 	phys_addr_t base = 0, size;
918ff3e077bSSimon Glass 	int cells_per_record;
919ff3e077bSSimon Glass 	const u32 *prop;
920ff3e077bSSimon Glass 	int len;
921ff3e077bSSimon Glass 	int i;
922ff3e077bSSimon Glass 
92361e51babSMasahiro Yamada 	prop = ofnode_get_property(node, "ranges", &len);
924ff3e077bSSimon Glass 	if (!prop)
925ff3e077bSSimon Glass 		return -EINVAL;
926878d68c0SSimon Glass 	pci_addr_cells = ofnode_read_simple_addr_cells(node);
927878d68c0SSimon Glass 	addr_cells = ofnode_read_simple_addr_cells(parent_node);
928878d68c0SSimon Glass 	size_cells = ofnode_read_simple_size_cells(node);
929ff3e077bSSimon Glass 
930ff3e077bSSimon Glass 	/* PCI addresses are always 3-cells */
931ff3e077bSSimon Glass 	len /= sizeof(u32);
932ff3e077bSSimon Glass 	cells_per_record = pci_addr_cells + addr_cells + size_cells;
933ff3e077bSSimon Glass 	hose->region_count = 0;
934ff3e077bSSimon Glass 	debug("%s: len=%d, cells_per_record=%d\n", __func__, len,
935ff3e077bSSimon Glass 	      cells_per_record);
936ff3e077bSSimon Glass 	for (i = 0; i < MAX_PCI_REGIONS; i++, len -= cells_per_record) {
937ff3e077bSSimon Glass 		u64 pci_addr, addr, size;
938ff3e077bSSimon Glass 		int space_code;
939ff3e077bSSimon Glass 		u32 flags;
940ff3e077bSSimon Glass 		int type;
9419526d83aSSimon Glass 		int pos;
942ff3e077bSSimon Glass 
943ff3e077bSSimon Glass 		if (len < cells_per_record)
944ff3e077bSSimon Glass 			break;
945ff3e077bSSimon Glass 		flags = fdt32_to_cpu(prop[0]);
946ff3e077bSSimon Glass 		space_code = (flags >> 24) & 3;
947ff3e077bSSimon Glass 		pci_addr = fdtdec_get_number(prop + 1, 2);
948ff3e077bSSimon Glass 		prop += pci_addr_cells;
949ff3e077bSSimon Glass 		addr = fdtdec_get_number(prop, addr_cells);
950ff3e077bSSimon Glass 		prop += addr_cells;
951ff3e077bSSimon Glass 		size = fdtdec_get_number(prop, size_cells);
952ff3e077bSSimon Glass 		prop += size_cells;
953ff3e077bSSimon Glass 		debug("%s: region %d, pci_addr=%" PRIx64 ", addr=%" PRIx64
954ff3e077bSSimon Glass 		      ", size=%" PRIx64 ", space_code=%d\n", __func__,
955ff3e077bSSimon Glass 		      hose->region_count, pci_addr, addr, size, space_code);
956ff3e077bSSimon Glass 		if (space_code & 2) {
957ff3e077bSSimon Glass 			type = flags & (1U << 30) ? PCI_REGION_PREFETCH :
958ff3e077bSSimon Glass 					PCI_REGION_MEM;
959fdb7e29cSShawn Lin #ifndef CONFIG_SYS_PCI_64BIT
960fdb7e29cSShawn Lin 			if (upper_32_bits(pci_addr))
961fdb7e29cSShawn Lin 				continue;
962fdb7e29cSShawn Lin #endif
963ff3e077bSSimon Glass 		} else if (space_code & 1) {
964ff3e077bSSimon Glass 			type = PCI_REGION_IO;
965ff3e077bSSimon Glass 		} else {
966ff3e077bSSimon Glass 			continue;
967ff3e077bSSimon Glass 		}
9689526d83aSSimon Glass 		pos = -1;
9699526d83aSSimon Glass 		for (i = 0; i < hose->region_count; i++) {
970fdb7e29cSShawn Lin 			if (hose->regions[i].flags == type) {
971fdb7e29cSShawn Lin #if defined(CONFIG_SYS_PCI_64BIT)
972fdb7e29cSShawn Lin 				if (type == PCI_REGION_MEM) {
973fdb7e29cSShawn Lin 					if ((upper_32_bits(pci_addr) &&
974fdb7e29cSShawn Lin 					    !upper_32_bits(hose->regions[i].bus_start)) ||
975fdb7e29cSShawn Lin 					    (!upper_32_bits(pci_addr) &&
976fdb7e29cSShawn Lin 					    upper_32_bits(hose->regions[i].bus_start)))
977fdb7e29cSShawn Lin 					    continue;
978fdb7e29cSShawn Lin 				}
979fdb7e29cSShawn Lin #endif
9809526d83aSSimon Glass 				pos = i;
9819526d83aSSimon Glass 			}
982fdb7e29cSShawn Lin 		}
9839526d83aSSimon Glass 		if (pos == -1)
9849526d83aSSimon Glass 			pos = hose->region_count++;
9859526d83aSSimon Glass 		debug(" - type=%d, pos=%d\n", type, pos);
9869526d83aSSimon Glass 		pci_set_region(hose->regions + pos, pci_addr, addr, size, type);
987ff3e077bSSimon Glass 	}
988ff3e077bSSimon Glass 
989ff3e077bSSimon Glass 	/* Add a region for our local memory */
9902084c5afSSimon Glass 	size = gd->ram_size;
9912084c5afSSimon Glass #ifdef CONFIG_SYS_SDRAM_BASE
9922084c5afSSimon Glass 	base = CONFIG_SYS_SDRAM_BASE;
9932084c5afSSimon Glass #endif
9942084c5afSSimon Glass 	if (gd->pci_ram_top && gd->pci_ram_top < base + size)
9952084c5afSSimon Glass 		size = gd->pci_ram_top - base;
9962084c5afSSimon Glass 	pci_set_region(hose->regions + hose->region_count++, base, base,
9972084c5afSSimon Glass 		       size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
998ff3e077bSSimon Glass 
999ff3e077bSSimon Glass 	return 0;
1000ff3e077bSSimon Glass }
1001ff3e077bSSimon Glass 
pci_uclass_pre_probe(struct udevice * bus)1002ff3e077bSSimon Glass static int pci_uclass_pre_probe(struct udevice *bus)
1003ff3e077bSSimon Glass {
1004ff3e077bSSimon Glass 	struct pci_controller *hose;
1005ff3e077bSSimon Glass 	int ret;
1006ff3e077bSSimon Glass 
1007ff3e077bSSimon Glass 	debug("%s, bus=%d/%s, parent=%s\n", __func__, bus->seq, bus->name,
1008ff3e077bSSimon Glass 	      bus->parent->name);
1009ff3e077bSSimon Glass 	hose = bus->uclass_priv;
1010ff3e077bSSimon Glass 
1011ff3e077bSSimon Glass 	/* For bridges, use the top-level PCI controller */
101265f62b1cSPaul Burton 	if (!device_is_on_pci_bus(bus)) {
1013ff3e077bSSimon Glass 		hose->ctlr = bus;
1014bf501595SSimon Glass 		ret = decode_regions(hose, dev_ofnode(bus->parent),
1015bf501595SSimon Glass 				     dev_ofnode(bus));
1016ff3e077bSSimon Glass 		if (ret) {
1017ff3e077bSSimon Glass 			debug("%s: Cannot decode regions\n", __func__);
1018ff3e077bSSimon Glass 			return ret;
1019ff3e077bSSimon Glass 		}
1020ff3e077bSSimon Glass 	} else {
1021ff3e077bSSimon Glass 		struct pci_controller *parent_hose;
1022ff3e077bSSimon Glass 
1023ff3e077bSSimon Glass 		parent_hose = dev_get_uclass_priv(bus->parent);
1024ff3e077bSSimon Glass 		hose->ctlr = parent_hose->bus;
1025ff3e077bSSimon Glass 	}
1026ff3e077bSSimon Glass 	hose->bus = bus;
1027ff3e077bSSimon Glass 	hose->first_busno = bus->seq;
1028ff3e077bSSimon Glass 	hose->last_busno = bus->seq;
1029ff3e077bSSimon Glass 
1030ff3e077bSSimon Glass 	return 0;
1031ff3e077bSSimon Glass }
1032ff3e077bSSimon Glass 
pci_uclass_post_probe(struct udevice * bus)1033ff3e077bSSimon Glass static int pci_uclass_post_probe(struct udevice *bus)
1034ff3e077bSSimon Glass {
1035ff3e077bSSimon Glass 	int ret;
1036ff3e077bSSimon Glass 
1037ff3e077bSSimon Glass 	debug("%s: probing bus %d\n", __func__, bus->seq);
1038ff3e077bSSimon Glass 	ret = pci_bind_bus_devices(bus);
1039ff3e077bSSimon Glass 	if (ret)
1040ff3e077bSSimon Glass 		return ret;
1041ff3e077bSSimon Glass 
1042ff3e077bSSimon Glass #ifdef CONFIG_PCI_PNP
1043ff3e077bSSimon Glass 	ret = pci_auto_config_devices(bus);
10444d21455eSSimon Glass 	if (ret < 0)
10454d21455eSSimon Glass 		return ret;
1046ff3e077bSSimon Glass #endif
1047ff3e077bSSimon Glass 
1048348b744bSBin Meng #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
1049348b744bSBin Meng 	/*
1050348b744bSBin Meng 	 * Per Intel FSP specification, we should call FSP notify API to
1051348b744bSBin Meng 	 * inform FSP that PCI enumeration has been done so that FSP will
1052348b744bSBin Meng 	 * do any necessary initialization as required by the chipset's
1053348b744bSBin Meng 	 * BIOS Writer's Guide (BWG).
1054348b744bSBin Meng 	 *
1055348b744bSBin Meng 	 * Unfortunately we have to put this call here as with driver model,
1056348b744bSBin Meng 	 * the enumeration is all done on a lazy basis as needed, so until
1057348b744bSBin Meng 	 * something is touched on PCI it won't happen.
1058348b744bSBin Meng 	 *
1059348b744bSBin Meng 	 * Note we only call this 1) after U-Boot is relocated, and 2)
1060348b744bSBin Meng 	 * root bus has finished probing.
1061348b744bSBin Meng 	 */
10624d21455eSSimon Glass 	if ((gd->flags & GD_FLG_RELOC) && (bus->seq == 0)) {
1063348b744bSBin Meng 		ret = fsp_init_phase_pci();
10644d21455eSSimon Glass 		if (ret)
10654d21455eSSimon Glass 			return ret;
10664d21455eSSimon Glass 	}
1067348b744bSBin Meng #endif
1068348b744bSBin Meng 
10694d21455eSSimon Glass 	return 0;
1070ff3e077bSSimon Glass }
1071ff3e077bSSimon Glass 
pci_uclass_child_post_bind(struct udevice * dev)1072ff3e077bSSimon Glass static int pci_uclass_child_post_bind(struct udevice *dev)
1073ff3e077bSSimon Glass {
1074ff3e077bSSimon Glass 	struct pci_child_platdata *pplat;
1075ff3e077bSSimon Glass 	struct fdt_pci_addr addr;
1076ff3e077bSSimon Glass 	int ret;
1077ff3e077bSSimon Glass 
1078bf501595SSimon Glass 	if (!dev_of_valid(dev))
1079ff3e077bSSimon Glass 		return 0;
1080ff3e077bSSimon Glass 
1081ff3e077bSSimon Glass 	/*
1082ff3e077bSSimon Glass 	 * We could read vendor, device, class if available. But for now we
1083ff3e077bSSimon Glass 	 * just check the address.
1084ff3e077bSSimon Glass 	 */
1085ff3e077bSSimon Glass 	pplat = dev_get_parent_platdata(dev);
1086bf501595SSimon Glass 	ret = ofnode_read_pci_addr(dev_ofnode(dev), FDT_PCI_SPACE_CONFIG, "reg",
1087bf501595SSimon Glass 				   &addr);
1088ff3e077bSSimon Glass 
1089ff3e077bSSimon Glass 	if (ret) {
1090ff3e077bSSimon Glass 		if (ret != -ENOENT)
1091ff3e077bSSimon Glass 			return -EINVAL;
1092ff3e077bSSimon Glass 	} else {
1093dce54dd6SBin Meng 		/* extract the devfn from fdt_pci_addr */
1094dce54dd6SBin Meng 		pplat->devfn = addr.phys_hi & 0xff00;
1095ff3e077bSSimon Glass 	}
1096ff3e077bSSimon Glass 
1097ff3e077bSSimon Glass 	return 0;
1098ff3e077bSSimon Glass }
1099ff3e077bSSimon Glass 
pci_bridge_read_config(struct udevice * bus,pci_dev_t bdf,uint offset,ulong * valuep,enum pci_size_t size)11004d8615cbSBin Meng static int pci_bridge_read_config(struct udevice *bus, pci_dev_t bdf,
11014d8615cbSBin Meng 				  uint offset, ulong *valuep,
11024d8615cbSBin Meng 				  enum pci_size_t size)
1103ff3e077bSSimon Glass {
1104ff3e077bSSimon Glass 	struct pci_controller *hose = bus->uclass_priv;
1105ff3e077bSSimon Glass 
1106ff3e077bSSimon Glass 	return pci_bus_read_config(hose->ctlr, bdf, offset, valuep, size);
1107ff3e077bSSimon Glass }
1108ff3e077bSSimon Glass 
pci_bridge_write_config(struct udevice * bus,pci_dev_t bdf,uint offset,ulong value,enum pci_size_t size)11094d8615cbSBin Meng static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf,
11104d8615cbSBin Meng 				   uint offset, ulong value,
11114d8615cbSBin Meng 				   enum pci_size_t size)
1112ff3e077bSSimon Glass {
1113ff3e077bSSimon Glass 	struct pci_controller *hose = bus->uclass_priv;
1114ff3e077bSSimon Glass 
1115ff3e077bSSimon Glass 	return pci_bus_write_config(hose->ctlr, bdf, offset, value, size);
1116ff3e077bSSimon Glass }
1117ff3e077bSSimon Glass 
skip_to_next_device(struct udevice * bus,struct udevice ** devp)111876c3fbcdSSimon Glass static int skip_to_next_device(struct udevice *bus, struct udevice **devp)
111976c3fbcdSSimon Glass {
112076c3fbcdSSimon Glass 	struct udevice *dev;
112176c3fbcdSSimon Glass 
112276c3fbcdSSimon Glass 	/*
112376c3fbcdSSimon Glass 	 * Scan through all the PCI controllers. On x86 there will only be one
112476c3fbcdSSimon Glass 	 * but that is not necessarily true on other hardware.
112576c3fbcdSSimon Glass 	 */
112676c3fbcdSSimon Glass 	do {
112776c3fbcdSSimon Glass 		device_find_first_child(bus, &dev);
112876c3fbcdSSimon Glass 		if (dev) {
112976c3fbcdSSimon Glass 			*devp = dev;
113076c3fbcdSSimon Glass 			return 0;
113176c3fbcdSSimon Glass 		}
11325395ac06SMichal Suchanek 		uclass_next_device(&bus);
113376c3fbcdSSimon Glass 	} while (bus);
113476c3fbcdSSimon Glass 
113576c3fbcdSSimon Glass 	return 0;
113676c3fbcdSSimon Glass }
113776c3fbcdSSimon Glass 
pci_find_next_device(struct udevice ** devp)113876c3fbcdSSimon Glass int pci_find_next_device(struct udevice **devp)
113976c3fbcdSSimon Glass {
114076c3fbcdSSimon Glass 	struct udevice *child = *devp;
114176c3fbcdSSimon Glass 	struct udevice *bus = child->parent;
114276c3fbcdSSimon Glass 
114376c3fbcdSSimon Glass 	/* First try all the siblings */
114476c3fbcdSSimon Glass 	*devp = NULL;
114576c3fbcdSSimon Glass 	while (child) {
114676c3fbcdSSimon Glass 		device_find_next_child(&child);
114776c3fbcdSSimon Glass 		if (child) {
114876c3fbcdSSimon Glass 			*devp = child;
114976c3fbcdSSimon Glass 			return 0;
115076c3fbcdSSimon Glass 		}
115176c3fbcdSSimon Glass 	}
115276c3fbcdSSimon Glass 
115376c3fbcdSSimon Glass 	/* We ran out of siblings. Try the next bus */
11545395ac06SMichal Suchanek 	uclass_next_device(&bus);
115576c3fbcdSSimon Glass 
115676c3fbcdSSimon Glass 	return bus ? skip_to_next_device(bus, devp) : 0;
115776c3fbcdSSimon Glass }
115876c3fbcdSSimon Glass 
pci_find_first_device(struct udevice ** devp)115976c3fbcdSSimon Glass int pci_find_first_device(struct udevice **devp)
116076c3fbcdSSimon Glass {
116176c3fbcdSSimon Glass 	struct udevice *bus;
116276c3fbcdSSimon Glass 
116376c3fbcdSSimon Glass 	*devp = NULL;
11645395ac06SMichal Suchanek 	uclass_first_device(UCLASS_PCI, &bus);
116576c3fbcdSSimon Glass 
116676c3fbcdSSimon Glass 	return skip_to_next_device(bus, devp);
116776c3fbcdSSimon Glass }
116876c3fbcdSSimon Glass 
pci_conv_32_to_size(ulong value,uint offset,enum pci_size_t size)11699289db6cSSimon Glass ulong pci_conv_32_to_size(ulong value, uint offset, enum pci_size_t size)
11709289db6cSSimon Glass {
11719289db6cSSimon Glass 	switch (size) {
11729289db6cSSimon Glass 	case PCI_SIZE_8:
11739289db6cSSimon Glass 		return (value >> ((offset & 3) * 8)) & 0xff;
11749289db6cSSimon Glass 	case PCI_SIZE_16:
11759289db6cSSimon Glass 		return (value >> ((offset & 2) * 8)) & 0xffff;
11769289db6cSSimon Glass 	default:
11779289db6cSSimon Glass 		return value;
11789289db6cSSimon Glass 	}
11799289db6cSSimon Glass }
11809289db6cSSimon Glass 
pci_conv_size_to_32(ulong old,ulong value,uint offset,enum pci_size_t size)11819289db6cSSimon Glass ulong pci_conv_size_to_32(ulong old, ulong value, uint offset,
11829289db6cSSimon Glass 			  enum pci_size_t size)
11839289db6cSSimon Glass {
11849289db6cSSimon Glass 	uint off_mask;
11859289db6cSSimon Glass 	uint val_mask, shift;
11869289db6cSSimon Glass 	ulong ldata, mask;
11879289db6cSSimon Glass 
11889289db6cSSimon Glass 	switch (size) {
11899289db6cSSimon Glass 	case PCI_SIZE_8:
11909289db6cSSimon Glass 		off_mask = 3;
11919289db6cSSimon Glass 		val_mask = 0xff;
11929289db6cSSimon Glass 		break;
11939289db6cSSimon Glass 	case PCI_SIZE_16:
11949289db6cSSimon Glass 		off_mask = 2;
11959289db6cSSimon Glass 		val_mask = 0xffff;
11969289db6cSSimon Glass 		break;
11979289db6cSSimon Glass 	default:
11989289db6cSSimon Glass 		return value;
11999289db6cSSimon Glass 	}
12009289db6cSSimon Glass 	shift = (offset & off_mask) * 8;
12019289db6cSSimon Glass 	ldata = (value & val_mask) << shift;
12029289db6cSSimon Glass 	mask = val_mask << shift;
12039289db6cSSimon Glass 	value = (old & ~mask) | ldata;
12049289db6cSSimon Glass 
12059289db6cSSimon Glass 	return value;
12069289db6cSSimon Glass }
12079289db6cSSimon Glass 
pci_get_regions(struct udevice * dev,struct pci_region ** iop,struct pci_region ** memp,struct pci_region ** prefp)1208f9260336SSimon Glass int pci_get_regions(struct udevice *dev, struct pci_region **iop,
1209f9260336SSimon Glass 		    struct pci_region **memp, struct pci_region **prefp)
1210f9260336SSimon Glass {
1211f9260336SSimon Glass 	struct udevice *bus = pci_get_controller(dev);
1212f9260336SSimon Glass 	struct pci_controller *hose = dev_get_uclass_priv(bus);
1213f9260336SSimon Glass 	int i;
1214f9260336SSimon Glass 
1215f9260336SSimon Glass 	*iop = NULL;
1216f9260336SSimon Glass 	*memp = NULL;
1217f9260336SSimon Glass 	*prefp = NULL;
1218f9260336SSimon Glass 	for (i = 0; i < hose->region_count; i++) {
1219f9260336SSimon Glass 		switch (hose->regions[i].flags) {
1220f9260336SSimon Glass 		case PCI_REGION_IO:
1221f9260336SSimon Glass 			if (!*iop || (*iop)->size < hose->regions[i].size)
1222f9260336SSimon Glass 				*iop = hose->regions + i;
1223f9260336SSimon Glass 			break;
1224f9260336SSimon Glass 		case PCI_REGION_MEM:
1225f9260336SSimon Glass 			if (!*memp || (*memp)->size < hose->regions[i].size)
1226f9260336SSimon Glass 				*memp = hose->regions + i;
1227f9260336SSimon Glass 			break;
1228f9260336SSimon Glass 		case (PCI_REGION_MEM | PCI_REGION_PREFETCH):
1229f9260336SSimon Glass 			if (!*prefp || (*prefp)->size < hose->regions[i].size)
1230f9260336SSimon Glass 				*prefp = hose->regions + i;
1231f9260336SSimon Glass 			break;
1232f9260336SSimon Glass 		}
1233f9260336SSimon Glass 	}
1234f9260336SSimon Glass 
1235f9260336SSimon Glass 	return (*iop != NULL) + (*memp != NULL) + (*prefp != NULL);
1236f9260336SSimon Glass }
1237f9260336SSimon Glass 
dm_pci_read_bar32(struct udevice * dev,int barnum)1238bab17cf1SSimon Glass u32 dm_pci_read_bar32(struct udevice *dev, int barnum)
1239bab17cf1SSimon Glass {
1240bab17cf1SSimon Glass 	u32 addr;
1241bab17cf1SSimon Glass 	int bar;
1242bab17cf1SSimon Glass 
1243bab17cf1SSimon Glass 	bar = PCI_BASE_ADDRESS_0 + barnum * 4;
1244bab17cf1SSimon Glass 	dm_pci_read_config32(dev, bar, &addr);
1245bab17cf1SSimon Glass 	if (addr & PCI_BASE_ADDRESS_SPACE_IO)
1246bab17cf1SSimon Glass 		return addr & PCI_BASE_ADDRESS_IO_MASK;
1247bab17cf1SSimon Glass 	else
1248bab17cf1SSimon Glass 		return addr & PCI_BASE_ADDRESS_MEM_MASK;
1249bab17cf1SSimon Glass }
1250bab17cf1SSimon Glass 
dm_pci_write_bar32(struct udevice * dev,int barnum,u32 addr)12519d731c82SSimon Glass void dm_pci_write_bar32(struct udevice *dev, int barnum, u32 addr)
12529d731c82SSimon Glass {
12539d731c82SSimon Glass 	int bar;
12549d731c82SSimon Glass 
12559d731c82SSimon Glass 	bar = PCI_BASE_ADDRESS_0 + barnum * 4;
12569d731c82SSimon Glass 	dm_pci_write_config32(dev, bar, addr);
12579d731c82SSimon Glass }
12589d731c82SSimon Glass 
_dm_pci_bus_to_phys(struct udevice * ctlr,pci_addr_t bus_addr,unsigned long flags,unsigned long skip_mask,phys_addr_t * pa)125921d1fe7eSSimon Glass static int _dm_pci_bus_to_phys(struct udevice *ctlr,
126021d1fe7eSSimon Glass 			       pci_addr_t bus_addr, unsigned long flags,
126121d1fe7eSSimon Glass 			       unsigned long skip_mask, phys_addr_t *pa)
126221d1fe7eSSimon Glass {
126321d1fe7eSSimon Glass 	struct pci_controller *hose = dev_get_uclass_priv(ctlr);
126421d1fe7eSSimon Glass 	struct pci_region *res;
126521d1fe7eSSimon Glass 	int i;
126621d1fe7eSSimon Glass 
126721d1fe7eSSimon Glass 	for (i = 0; i < hose->region_count; i++) {
126821d1fe7eSSimon Glass 		res = &hose->regions[i];
126921d1fe7eSSimon Glass 
127021d1fe7eSSimon Glass 		if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
127121d1fe7eSSimon Glass 			continue;
127221d1fe7eSSimon Glass 
127321d1fe7eSSimon Glass 		if (res->flags & skip_mask)
127421d1fe7eSSimon Glass 			continue;
127521d1fe7eSSimon Glass 
127621d1fe7eSSimon Glass 		if (bus_addr >= res->bus_start &&
127721d1fe7eSSimon Glass 		    (bus_addr - res->bus_start) < res->size) {
127821d1fe7eSSimon Glass 			*pa = (bus_addr - res->bus_start + res->phys_start);
127921d1fe7eSSimon Glass 			return 0;
128021d1fe7eSSimon Glass 		}
128121d1fe7eSSimon Glass 	}
128221d1fe7eSSimon Glass 
128321d1fe7eSSimon Glass 	return 1;
128421d1fe7eSSimon Glass }
128521d1fe7eSSimon Glass 
dm_pci_bus_to_phys(struct udevice * dev,pci_addr_t bus_addr,unsigned long flags)128621d1fe7eSSimon Glass phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t bus_addr,
128721d1fe7eSSimon Glass 			       unsigned long flags)
128821d1fe7eSSimon Glass {
128921d1fe7eSSimon Glass 	phys_addr_t phys_addr = 0;
129021d1fe7eSSimon Glass 	struct udevice *ctlr;
129121d1fe7eSSimon Glass 	int ret;
129221d1fe7eSSimon Glass 
129321d1fe7eSSimon Glass 	/* The root controller has the region information */
129421d1fe7eSSimon Glass 	ctlr = pci_get_controller(dev);
129521d1fe7eSSimon Glass 
129621d1fe7eSSimon Glass 	/*
129721d1fe7eSSimon Glass 	 * if PCI_REGION_MEM is set we do a two pass search with preference
129821d1fe7eSSimon Glass 	 * on matches that don't have PCI_REGION_SYS_MEMORY set
129921d1fe7eSSimon Glass 	 */
130021d1fe7eSSimon Glass 	if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) {
130121d1fe7eSSimon Glass 		ret = _dm_pci_bus_to_phys(ctlr, bus_addr,
130221d1fe7eSSimon Glass 					  flags, PCI_REGION_SYS_MEMORY,
130321d1fe7eSSimon Glass 					  &phys_addr);
130421d1fe7eSSimon Glass 		if (!ret)
130521d1fe7eSSimon Glass 			return phys_addr;
130621d1fe7eSSimon Glass 	}
130721d1fe7eSSimon Glass 
130821d1fe7eSSimon Glass 	ret = _dm_pci_bus_to_phys(ctlr, bus_addr, flags, 0, &phys_addr);
130921d1fe7eSSimon Glass 
131021d1fe7eSSimon Glass 	if (ret)
131121d1fe7eSSimon Glass 		puts("pci_hose_bus_to_phys: invalid physical address\n");
131221d1fe7eSSimon Glass 
131321d1fe7eSSimon Glass 	return phys_addr;
131421d1fe7eSSimon Glass }
131521d1fe7eSSimon Glass 
_dm_pci_phys_to_bus(struct udevice * dev,phys_addr_t phys_addr,unsigned long flags,unsigned long skip_mask,pci_addr_t * ba)131621d1fe7eSSimon Glass int _dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr,
131721d1fe7eSSimon Glass 			unsigned long flags, unsigned long skip_mask,
131821d1fe7eSSimon Glass 			pci_addr_t *ba)
131921d1fe7eSSimon Glass {
132021d1fe7eSSimon Glass 	struct pci_region *res;
132121d1fe7eSSimon Glass 	struct udevice *ctlr;
132221d1fe7eSSimon Glass 	pci_addr_t bus_addr;
132321d1fe7eSSimon Glass 	int i;
132421d1fe7eSSimon Glass 	struct pci_controller *hose;
132521d1fe7eSSimon Glass 
132621d1fe7eSSimon Glass 	/* The root controller has the region information */
132721d1fe7eSSimon Glass 	ctlr = pci_get_controller(dev);
132821d1fe7eSSimon Glass 	hose = dev_get_uclass_priv(ctlr);
132921d1fe7eSSimon Glass 
133021d1fe7eSSimon Glass 	for (i = 0; i < hose->region_count; i++) {
133121d1fe7eSSimon Glass 		res = &hose->regions[i];
133221d1fe7eSSimon Glass 
133321d1fe7eSSimon Glass 		if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
133421d1fe7eSSimon Glass 			continue;
133521d1fe7eSSimon Glass 
133621d1fe7eSSimon Glass 		if (res->flags & skip_mask)
133721d1fe7eSSimon Glass 			continue;
133821d1fe7eSSimon Glass 
133921d1fe7eSSimon Glass 		bus_addr = phys_addr - res->phys_start + res->bus_start;
134021d1fe7eSSimon Glass 
134121d1fe7eSSimon Glass 		if (bus_addr >= res->bus_start &&
134221d1fe7eSSimon Glass 		    (bus_addr - res->bus_start) < res->size) {
134321d1fe7eSSimon Glass 			*ba = bus_addr;
134421d1fe7eSSimon Glass 			return 0;
134521d1fe7eSSimon Glass 		}
134621d1fe7eSSimon Glass 	}
134721d1fe7eSSimon Glass 
134821d1fe7eSSimon Glass 	return 1;
134921d1fe7eSSimon Glass }
135021d1fe7eSSimon Glass 
dm_pci_phys_to_bus(struct udevice * dev,phys_addr_t phys_addr,unsigned long flags)135121d1fe7eSSimon Glass pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr,
135221d1fe7eSSimon Glass 			      unsigned long flags)
135321d1fe7eSSimon Glass {
135421d1fe7eSSimon Glass 	pci_addr_t bus_addr = 0;
135521d1fe7eSSimon Glass 	int ret;
135621d1fe7eSSimon Glass 
135721d1fe7eSSimon Glass 	/*
135821d1fe7eSSimon Glass 	 * if PCI_REGION_MEM is set we do a two pass search with preference
135921d1fe7eSSimon Glass 	 * on matches that don't have PCI_REGION_SYS_MEMORY set
136021d1fe7eSSimon Glass 	 */
136121d1fe7eSSimon Glass 	if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) {
136221d1fe7eSSimon Glass 		ret = _dm_pci_phys_to_bus(dev, phys_addr, flags,
136321d1fe7eSSimon Glass 					  PCI_REGION_SYS_MEMORY, &bus_addr);
136421d1fe7eSSimon Glass 		if (!ret)
136521d1fe7eSSimon Glass 			return bus_addr;
136621d1fe7eSSimon Glass 	}
136721d1fe7eSSimon Glass 
136821d1fe7eSSimon Glass 	ret = _dm_pci_phys_to_bus(dev, phys_addr, flags, 0, &bus_addr);
136921d1fe7eSSimon Glass 
137021d1fe7eSSimon Glass 	if (ret)
137121d1fe7eSSimon Glass 		puts("pci_hose_phys_to_bus: invalid physical address\n");
137221d1fe7eSSimon Glass 
137321d1fe7eSSimon Glass 	return bus_addr;
137421d1fe7eSSimon Glass }
137521d1fe7eSSimon Glass 
dm_pci_map_bar(struct udevice * dev,int bar,int flags)137621d1fe7eSSimon Glass void *dm_pci_map_bar(struct udevice *dev, int bar, int flags)
137721d1fe7eSSimon Glass {
137821d1fe7eSSimon Glass 	pci_addr_t pci_bus_addr;
137921d1fe7eSSimon Glass 	u32 bar_response;
138021d1fe7eSSimon Glass 
138121d1fe7eSSimon Glass 	/* read BAR address */
138221d1fe7eSSimon Glass 	dm_pci_read_config32(dev, bar, &bar_response);
138321d1fe7eSSimon Glass 	pci_bus_addr = (pci_addr_t)(bar_response & ~0xf);
138421d1fe7eSSimon Glass 
1385fdb7e29cSShawn Lin #if defined(CONFIG_SYS_PCI_64BIT)
1386fdb7e29cSShawn Lin         if (bar_response & PCI_BASE_ADDRESS_MEM_TYPE_64) {
1387fdb7e29cSShawn Lin 		dm_pci_read_config32(dev, bar + 4, &bar_response);
1388fdb7e29cSShawn Lin 		pci_bus_addr |= (pci_addr_t)bar_response << 32;				        }
1389fdb7e29cSShawn Lin #endif /* CONFIG_SYS_PCI_64BIT */
139021d1fe7eSSimon Glass 	/*
139121d1fe7eSSimon Glass 	 * Pass "0" as the length argument to pci_bus_to_virt.  The arg
139221d1fe7eSSimon Glass 	 * isn't actualy used on any platform because u-boot assumes a static
139321d1fe7eSSimon Glass 	 * linear mapping.  In the future, this could read the BAR size
139421d1fe7eSSimon Glass 	 * and pass that as the size if needed.
139521d1fe7eSSimon Glass 	 */
139621d1fe7eSSimon Glass 	return dm_pci_bus_to_virt(dev, pci_bus_addr, flags, 0, MAP_NOCACHE);
139721d1fe7eSSimon Glass }
139821d1fe7eSSimon Glass 
_dm_pci_find_next_capability(struct udevice * dev,u8 pos,int cap)13990f141368SBin Meng static int _dm_pci_find_next_capability(struct udevice *dev, u8 pos, int cap)
1400c3a16692SBin Meng {
1401c3a16692SBin Meng 	int ttl = PCI_FIND_CAP_TTL;
1402c3a16692SBin Meng 	u8 id;
1403c3a16692SBin Meng 	u16 ent;
1404c3a16692SBin Meng 
1405c3a16692SBin Meng 	dm_pci_read_config8(dev, pos, &pos);
14060f141368SBin Meng 
1407c3a16692SBin Meng 	while (ttl--) {
1408c3a16692SBin Meng 		if (pos < PCI_STD_HEADER_SIZEOF)
1409c3a16692SBin Meng 			break;
1410c3a16692SBin Meng 		pos &= ~3;
1411c3a16692SBin Meng 		dm_pci_read_config16(dev, pos, &ent);
1412c3a16692SBin Meng 
1413c3a16692SBin Meng 		id = ent & 0xff;
1414c3a16692SBin Meng 		if (id == 0xff)
1415c3a16692SBin Meng 			break;
1416c3a16692SBin Meng 		if (id == cap)
1417c3a16692SBin Meng 			return pos;
1418c3a16692SBin Meng 		pos = (ent >> 8);
1419c3a16692SBin Meng 	}
1420c3a16692SBin Meng 
1421c3a16692SBin Meng 	return 0;
1422c3a16692SBin Meng }
1423c3a16692SBin Meng 
dm_pci_find_next_capability(struct udevice * dev,u8 start,int cap)14240f141368SBin Meng int dm_pci_find_next_capability(struct udevice *dev, u8 start, int cap)
14250f141368SBin Meng {
14260f141368SBin Meng 	return _dm_pci_find_next_capability(dev, start + PCI_CAP_LIST_NEXT,
14270f141368SBin Meng 					    cap);
14280f141368SBin Meng }
14290f141368SBin Meng 
dm_pci_find_capability(struct udevice * dev,int cap)14300f141368SBin Meng int dm_pci_find_capability(struct udevice *dev, int cap)
14310f141368SBin Meng {
14320f141368SBin Meng 	u16 status;
14330f141368SBin Meng 	u8 header_type;
14340f141368SBin Meng 	u8 pos;
14350f141368SBin Meng 
14360f141368SBin Meng 	dm_pci_read_config16(dev, PCI_STATUS, &status);
14370f141368SBin Meng 	if (!(status & PCI_STATUS_CAP_LIST))
14380f141368SBin Meng 		return 0;
14390f141368SBin Meng 
14400f141368SBin Meng 	dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type);
14410f141368SBin Meng 	if ((header_type & 0x7f) == PCI_HEADER_TYPE_CARDBUS)
14420f141368SBin Meng 		pos = PCI_CB_CAPABILITY_LIST;
14430f141368SBin Meng 	else
14440f141368SBin Meng 		pos = PCI_CAPABILITY_LIST;
14450f141368SBin Meng 
14460f141368SBin Meng 	return _dm_pci_find_next_capability(dev, pos, cap);
14470f141368SBin Meng }
14480f141368SBin Meng 
dm_pci_find_next_ext_capability(struct udevice * dev,int start,int cap)14490f141368SBin Meng int dm_pci_find_next_ext_capability(struct udevice *dev, int start, int cap)
1450c3a16692SBin Meng {
1451c3a16692SBin Meng 	u32 header;
1452c3a16692SBin Meng 	int ttl;
1453c3a16692SBin Meng 	int pos = PCI_CFG_SPACE_SIZE;
1454c3a16692SBin Meng 
1455c3a16692SBin Meng 	/* minimum 8 bytes per capability */
1456c3a16692SBin Meng 	ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
1457c3a16692SBin Meng 
14580f141368SBin Meng 	if (start)
14590f141368SBin Meng 		pos = start;
14600f141368SBin Meng 
1461c3a16692SBin Meng 	dm_pci_read_config32(dev, pos, &header);
1462c3a16692SBin Meng 	/*
1463c3a16692SBin Meng 	 * If we have no capabilities, this is indicated by cap ID,
1464c3a16692SBin Meng 	 * cap version and next pointer all being 0.
1465c3a16692SBin Meng 	 */
1466c3a16692SBin Meng 	if (header == 0)
1467c3a16692SBin Meng 		return 0;
1468c3a16692SBin Meng 
1469c3a16692SBin Meng 	while (ttl--) {
1470c3a16692SBin Meng 		if (PCI_EXT_CAP_ID(header) == cap)
1471c3a16692SBin Meng 			return pos;
1472c3a16692SBin Meng 
1473c3a16692SBin Meng 		pos = PCI_EXT_CAP_NEXT(header);
1474c3a16692SBin Meng 		if (pos < PCI_CFG_SPACE_SIZE)
1475c3a16692SBin Meng 			break;
1476c3a16692SBin Meng 
1477c3a16692SBin Meng 		dm_pci_read_config32(dev, pos, &header);
1478c3a16692SBin Meng 	}
1479c3a16692SBin Meng 
1480c3a16692SBin Meng 	return 0;
1481c3a16692SBin Meng }
1482c3a16692SBin Meng 
dm_pci_find_ext_capability(struct udevice * dev,int cap)14830f141368SBin Meng int dm_pci_find_ext_capability(struct udevice *dev, int cap)
14840f141368SBin Meng {
14850f141368SBin Meng 	return dm_pci_find_next_ext_capability(dev, 0, cap);
14860f141368SBin Meng }
14870f141368SBin Meng 
1488ff3e077bSSimon Glass UCLASS_DRIVER(pci) = {
1489ff3e077bSSimon Glass 	.id		= UCLASS_PCI,
1490ff3e077bSSimon Glass 	.name		= "pci",
14912bb02e4fSSimon Glass 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
149291195485SSimon Glass 	.post_bind	= dm_scan_fdt_dev,
1493ff3e077bSSimon Glass 	.pre_probe	= pci_uclass_pre_probe,
1494ff3e077bSSimon Glass 	.post_probe	= pci_uclass_post_probe,
1495ff3e077bSSimon Glass 	.child_post_bind = pci_uclass_child_post_bind,
1496ff3e077bSSimon Glass 	.per_device_auto_alloc_size = sizeof(struct pci_controller),
1497ff3e077bSSimon Glass 	.per_child_platdata_auto_alloc_size =
1498ff3e077bSSimon Glass 			sizeof(struct pci_child_platdata),
1499ff3e077bSSimon Glass };
1500ff3e077bSSimon Glass 
1501ff3e077bSSimon Glass static const struct dm_pci_ops pci_bridge_ops = {
1502ff3e077bSSimon Glass 	.read_config	= pci_bridge_read_config,
1503ff3e077bSSimon Glass 	.write_config	= pci_bridge_write_config,
1504ff3e077bSSimon Glass };
1505ff3e077bSSimon Glass 
1506ff3e077bSSimon Glass static const struct udevice_id pci_bridge_ids[] = {
1507ff3e077bSSimon Glass 	{ .compatible = "pci-bridge" },
1508ff3e077bSSimon Glass 	{ }
1509ff3e077bSSimon Glass };
1510ff3e077bSSimon Glass 
1511ff3e077bSSimon Glass U_BOOT_DRIVER(pci_bridge_drv) = {
1512ff3e077bSSimon Glass 	.name		= "pci_bridge_drv",
1513ff3e077bSSimon Glass 	.id		= UCLASS_PCI,
1514ff3e077bSSimon Glass 	.of_match	= pci_bridge_ids,
1515ff3e077bSSimon Glass 	.ops		= &pci_bridge_ops,
1516ff3e077bSSimon Glass };
1517ff3e077bSSimon Glass 
1518ff3e077bSSimon Glass UCLASS_DRIVER(pci_generic) = {
1519ff3e077bSSimon Glass 	.id		= UCLASS_PCI_GENERIC,
1520ff3e077bSSimon Glass 	.name		= "pci_generic",
1521ff3e077bSSimon Glass };
1522ff3e077bSSimon Glass 
1523ff3e077bSSimon Glass static const struct udevice_id pci_generic_ids[] = {
1524ff3e077bSSimon Glass 	{ .compatible = "pci-generic" },
1525ff3e077bSSimon Glass 	{ }
1526ff3e077bSSimon Glass };
1527ff3e077bSSimon Glass 
1528ff3e077bSSimon Glass U_BOOT_DRIVER(pci_generic_drv) = {
1529ff3e077bSSimon Glass 	.name		= "pci_generic_drv",
1530ff3e077bSSimon Glass 	.id		= UCLASS_PCI_GENERIC,
1531ff3e077bSSimon Glass 	.of_match	= pci_generic_ids,
1532ff3e077bSSimon Glass };
1533e578b92cSStephen Warren 
pci_init(void)1534e578b92cSStephen Warren void pci_init(void)
1535e578b92cSStephen Warren {
1536e578b92cSStephen Warren 	struct udevice *bus;
1537e578b92cSStephen Warren 
1538e578b92cSStephen Warren 	/*
1539e578b92cSStephen Warren 	 * Enumerate all known controller devices. Enumeration has the side-
1540e578b92cSStephen Warren 	 * effect of probing them, so PCIe devices will be enumerated too.
1541e578b92cSStephen Warren 	 */
1542e578b92cSStephen Warren 	for (uclass_first_device(UCLASS_PCI, &bus);
1543e578b92cSStephen Warren 	     bus;
1544e578b92cSStephen Warren 	     uclass_next_device(&bus)) {
1545e578b92cSStephen Warren 		;
1546e578b92cSStephen Warren 	}
1547e578b92cSStephen Warren }
1548