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