]> git.sur5r.net Git - u-boot/blob - drivers/pci/pci_common.c
Merge git://git.denx.de/u-boot-fdt
[u-boot] / drivers / pci / pci_common.c
1 /*
2  * Copyright (c) 2014 Google, Inc
3  *
4  * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
5  * Andreas Heppel <aheppel@sysgo.de>
6  *
7  * (C) Copyright 2002, 2003
8  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
9  *
10  * SPDX-License-Identifier:     GPL-2.0+
11  */
12
13 #include <common.h>
14 #include <errno.h>
15 #include <pci.h>
16 #include <asm/io.h>
17
18 const char *pci_class_str(u8 class)
19 {
20         switch (class) {
21         case PCI_CLASS_NOT_DEFINED:
22                 return "Build before PCI Rev2.0";
23                 break;
24         case PCI_BASE_CLASS_STORAGE:
25                 return "Mass storage controller";
26                 break;
27         case PCI_BASE_CLASS_NETWORK:
28                 return "Network controller";
29                 break;
30         case PCI_BASE_CLASS_DISPLAY:
31                 return "Display controller";
32                 break;
33         case PCI_BASE_CLASS_MULTIMEDIA:
34                 return "Multimedia device";
35                 break;
36         case PCI_BASE_CLASS_MEMORY:
37                 return "Memory controller";
38                 break;
39         case PCI_BASE_CLASS_BRIDGE:
40                 return "Bridge device";
41                 break;
42         case PCI_BASE_CLASS_COMMUNICATION:
43                 return "Simple comm. controller";
44                 break;
45         case PCI_BASE_CLASS_SYSTEM:
46                 return "Base system peripheral";
47                 break;
48         case PCI_BASE_CLASS_INPUT:
49                 return "Input device";
50                 break;
51         case PCI_BASE_CLASS_DOCKING:
52                 return "Docking station";
53                 break;
54         case PCI_BASE_CLASS_PROCESSOR:
55                 return "Processor";
56                 break;
57         case PCI_BASE_CLASS_SERIAL:
58                 return "Serial bus controller";
59                 break;
60         case PCI_BASE_CLASS_INTELLIGENT:
61                 return "Intelligent controller";
62                 break;
63         case PCI_BASE_CLASS_SATELLITE:
64                 return "Satellite controller";
65                 break;
66         case PCI_BASE_CLASS_CRYPT:
67                 return "Cryptographic device";
68                 break;
69         case PCI_BASE_CLASS_SIGNAL_PROCESSING:
70                 return "DSP";
71                 break;
72         case PCI_CLASS_OTHERS:
73                 return "Does not fit any class";
74                 break;
75         default:
76         return  "???";
77                 break;
78         };
79 }
80
81 pci_dev_t pci_find_class(uint find_class, int index)
82 {
83         int bus;
84         int devnum;
85         pci_dev_t bdf;
86         uint32_t class;
87
88         for (bus = 0; bus <= pci_last_busno(); bus++) {
89                 for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES - 1; devnum++) {
90                         pci_read_config_dword(PCI_BDF(bus, devnum, 0),
91                                               PCI_CLASS_REVISION, &class);
92                         if (class >> 16 == 0xffff)
93                                 continue;
94
95                         for (bdf = PCI_BDF(bus, devnum, 0);
96                                         bdf <= PCI_BDF(bus, devnum,
97                                                 PCI_MAX_PCI_FUNCTIONS - 1);
98                                         bdf += PCI_BDF(0, 0, 1)) {
99                                 pci_read_config_dword(bdf, PCI_CLASS_REVISION,
100                                                       &class);
101                                 class >>= 8;
102
103                                 if (class != find_class)
104                                         continue;
105                                 /*
106                                  * Decrement the index. We want to return the
107                                  * correct device, so index is 0 for the first
108                                  * matching device, 1 for the second, etc.
109                                  */
110                                 if (index) {
111                                         index--;
112                                         continue;
113                                 }
114                                 /* Return index'th controller. */
115                                 return bdf;
116                         }
117                 }
118         }
119
120         return -ENODEV;
121 }
122
123 __weak int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
124 {
125         /*
126          * Check if pci device should be skipped in configuration
127          */
128         if (dev == PCI_BDF(hose->first_busno, 0, 0)) {
129 #if defined(CONFIG_PCI_CONFIG_HOST_BRIDGE) /* don't skip host bridge */
130                 /*
131                  * Only skip configuration if "pciconfighost" is not set
132                  */
133                 if (getenv("pciconfighost") == NULL)
134                         return 1;
135 #else
136                 return 1;
137 #endif
138         }
139
140         return 0;
141 }
142
143 /* Get a virtual address associated with a BAR region */
144 void *pci_map_bar(pci_dev_t pdev, int bar, int flags)
145 {
146         pci_addr_t pci_bus_addr;
147         u32 bar_response;
148
149         /* read BAR address */
150         pci_read_config_dword(pdev, bar, &bar_response);
151         pci_bus_addr = (pci_addr_t)(bar_response & ~0xf);
152
153         /*
154          * Pass "0" as the length argument to pci_bus_to_virt.  The arg
155          * isn't actualy used on any platform because u-boot assumes a static
156          * linear mapping.  In the future, this could read the BAR size
157          * and pass that as the size if needed.
158          */
159         return pci_bus_to_virt(pdev, pci_bus_addr, flags, 0, MAP_NOCACHE);
160 }
161
162 void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum,
163                      u32 addr_and_ctrl)
164 {
165         int bar;
166
167         bar = PCI_BASE_ADDRESS_0 + barnum * 4;
168         pci_hose_write_config_dword(hose, dev, bar, addr_and_ctrl);
169 }
170
171 u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum)
172 {
173         u32 addr;
174         int bar;
175
176         bar = PCI_BASE_ADDRESS_0 + barnum * 4;
177         pci_hose_read_config_dword(hose, dev, bar, &addr);
178         if (addr & PCI_BASE_ADDRESS_SPACE_IO)
179                 return addr & PCI_BASE_ADDRESS_IO_MASK;
180         else
181                 return addr & PCI_BASE_ADDRESS_MEM_MASK;
182 }
183
184 int __pci_hose_bus_to_phys(struct pci_controller *hose,
185                            pci_addr_t bus_addr,
186                            unsigned long flags,
187                            unsigned long skip_mask,
188                            phys_addr_t *pa)
189 {
190         struct pci_region *res;
191         int i;
192
193         for (i = 0; i < hose->region_count; i++) {
194                 res = &hose->regions[i];
195
196                 if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
197                         continue;
198
199                 if (res->flags & skip_mask)
200                         continue;
201
202                 if (bus_addr >= res->bus_start &&
203                     (bus_addr - res->bus_start) < res->size) {
204                         *pa = (bus_addr - res->bus_start + res->phys_start);
205                         return 0;
206                 }
207         }
208
209         return 1;
210 }
211
212 phys_addr_t pci_hose_bus_to_phys(struct pci_controller *hose,
213                                  pci_addr_t bus_addr,
214                                  unsigned long flags)
215 {
216         phys_addr_t phys_addr = 0;
217         int ret;
218
219         if (!hose) {
220                 puts("pci_hose_bus_to_phys: invalid hose\n");
221                 return phys_addr;
222         }
223
224         /*
225          * if PCI_REGION_MEM is set we do a two pass search with preference
226          * on matches that don't have PCI_REGION_SYS_MEMORY set
227          */
228         if ((flags & PCI_REGION_MEM) == PCI_REGION_MEM) {
229                 ret = __pci_hose_bus_to_phys(hose, bus_addr,
230                                 flags, PCI_REGION_SYS_MEMORY, &phys_addr);
231                 if (!ret)
232                         return phys_addr;
233         }
234
235         ret = __pci_hose_bus_to_phys(hose, bus_addr, flags, 0, &phys_addr);
236
237         if (ret)
238                 puts("pci_hose_bus_to_phys: invalid physical address\n");
239
240         return phys_addr;
241 }
242
243 int __pci_hose_phys_to_bus(struct pci_controller *hose,
244                            phys_addr_t phys_addr,
245                            unsigned long flags,
246                            unsigned long skip_mask,
247                            pci_addr_t *ba)
248 {
249         struct pci_region *res;
250         pci_addr_t bus_addr;
251         int i;
252
253         for (i = 0; i < hose->region_count; i++) {
254                 res = &hose->regions[i];
255
256                 if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
257                         continue;
258
259                 if (res->flags & skip_mask)
260                         continue;
261
262                 bus_addr = phys_addr - res->phys_start + res->bus_start;
263
264                 if (bus_addr >= res->bus_start &&
265                     bus_addr < res->bus_start + res->size) {
266                         *ba = bus_addr;
267                         return 0;
268                 }
269         }
270
271         return 1;
272 }
273
274 pci_addr_t pci_hose_phys_to_bus(struct pci_controller *hose,
275                                 phys_addr_t phys_addr,
276                                 unsigned long flags)
277 {
278         pci_addr_t bus_addr = 0;
279         int ret;
280
281         if (!hose) {
282                 puts("pci_hose_phys_to_bus: invalid hose\n");
283                 return bus_addr;
284         }
285
286         /*
287          * if PCI_REGION_MEM is set we do a two pass search with preference
288          * on matches that don't have PCI_REGION_SYS_MEMORY set
289          */
290         if ((flags & PCI_REGION_MEM) == PCI_REGION_MEM) {
291                 ret = __pci_hose_phys_to_bus(hose, phys_addr,
292                                 flags, PCI_REGION_SYS_MEMORY, &bus_addr);
293                 if (!ret)
294                         return bus_addr;
295         }
296
297         ret = __pci_hose_phys_to_bus(hose, phys_addr, flags, 0, &bus_addr);
298
299         if (ret)
300                 puts("pci_hose_phys_to_bus: invalid physical address\n");
301
302         return bus_addr;
303 }
304
305 pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
306 {
307         struct pci_device_id ids[2] = { {}, {0, 0} };
308
309         ids[0].vendor = vendor;
310         ids[0].device = device;
311
312         return pci_find_devices(ids, index);
313 }
314
315 pci_dev_t pci_hose_find_devices(struct pci_controller *hose, int busnum,
316                                 struct pci_device_id *ids, int *indexp)
317 {
318         int found_multi = 0;
319         u16 vendor, device;
320         u8 header_type;
321         pci_dev_t bdf;
322         int i;
323
324         for (bdf = PCI_BDF(busnum, 0, 0);
325              bdf < PCI_BDF(busnum + 1, 0, 0);
326              bdf += PCI_BDF(0, 0, 1)) {
327                 if (pci_skip_dev(hose, bdf))
328                         continue;
329
330                 if (!PCI_FUNC(bdf)) {
331                         pci_read_config_byte(bdf, PCI_HEADER_TYPE,
332                                              &header_type);
333                         found_multi = header_type & 0x80;
334                 } else {
335                         if (!found_multi)
336                                 continue;
337                 }
338
339                 pci_read_config_word(bdf, PCI_VENDOR_ID, &vendor);
340                 pci_read_config_word(bdf, PCI_DEVICE_ID, &device);
341
342                 for (i = 0; ids[i].vendor != 0; i++) {
343                         if (vendor == ids[i].vendor &&
344                             device == ids[i].device) {
345                                 if ((*indexp) <= 0)
346                                         return bdf;
347
348                                 (*indexp)--;
349                         }
350                 }
351         }
352
353         return -1;
354 }