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