]> git.sur5r.net Git - u-boot/blob - drivers/pci/pci_common.c
Merge branch 'master' of git://git.denx.de/u-boot-sunxi
[u-boot] / drivers / pci / pci_common.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2014 Google, Inc
4  *
5  * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
6  * Andreas Heppel <aheppel@sysgo.de>
7  *
8  * (C) Copyright 2002, 2003
9  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
10  */
11
12 #include <common.h>
13 #include <dm.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 __weak int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
82 {
83         /*
84          * Check if pci device should be skipped in configuration
85          */
86         if (dev == PCI_BDF(hose->first_busno, 0, 0)) {
87 #if defined(CONFIG_PCI_CONFIG_HOST_BRIDGE) /* don't skip host bridge */
88                 /*
89                  * Only skip configuration if "pciconfighost" is not set
90                  */
91                 if (env_get("pciconfighost") == NULL)
92                         return 1;
93 #else
94                 return 1;
95 #endif
96         }
97
98         return 0;
99 }
100
101 #if !defined(CONFIG_DM_PCI) || defined(CONFIG_DM_PCI_COMPAT)
102 /* Get a virtual address associated with a BAR region */
103 void *pci_map_bar(pci_dev_t pdev, int bar, int flags)
104 {
105         pci_addr_t pci_bus_addr;
106         u32 bar_response;
107
108         /* read BAR address */
109         pci_read_config_dword(pdev, bar, &bar_response);
110         pci_bus_addr = (pci_addr_t)(bar_response & ~0xf);
111
112         /*
113          * Pass "0" as the length argument to pci_bus_to_virt.  The arg
114          * isn't actualy used on any platform because u-boot assumes a static
115          * linear mapping.  In the future, this could read the BAR size
116          * and pass that as the size if needed.
117          */
118         return pci_bus_to_virt(pdev, pci_bus_addr, flags, 0, MAP_NOCACHE);
119 }
120
121 void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum,
122                      u32 addr_and_ctrl)
123 {
124         int bar;
125
126         bar = PCI_BASE_ADDRESS_0 + barnum * 4;
127         pci_hose_write_config_dword(hose, dev, bar, addr_and_ctrl);
128 }
129
130 u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum)
131 {
132         u32 addr;
133         int bar;
134
135         bar = PCI_BASE_ADDRESS_0 + barnum * 4;
136         pci_hose_read_config_dword(hose, dev, bar, &addr);
137         if (addr & PCI_BASE_ADDRESS_SPACE_IO)
138                 return addr & PCI_BASE_ADDRESS_IO_MASK;
139         else
140                 return addr & PCI_BASE_ADDRESS_MEM_MASK;
141 }
142
143 int __pci_hose_bus_to_phys(struct pci_controller *hose,
144                            pci_addr_t bus_addr,
145                            unsigned long flags,
146                            unsigned long skip_mask,
147                            phys_addr_t *pa)
148 {
149         struct pci_region *res;
150         int i;
151
152         for (i = 0; i < hose->region_count; i++) {
153                 res = &hose->regions[i];
154
155                 if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
156                         continue;
157
158                 if (res->flags & skip_mask)
159                         continue;
160
161                 if (bus_addr >= res->bus_start &&
162                     (bus_addr - res->bus_start) < res->size) {
163                         *pa = (bus_addr - res->bus_start + res->phys_start);
164                         return 0;
165                 }
166         }
167
168         return 1;
169 }
170
171 phys_addr_t pci_hose_bus_to_phys(struct pci_controller *hose,
172                                  pci_addr_t bus_addr,
173                                  unsigned long flags)
174 {
175         phys_addr_t phys_addr = 0;
176         int ret;
177
178         if (!hose) {
179                 puts("pci_hose_bus_to_phys: invalid hose\n");
180                 return phys_addr;
181         }
182
183         /*
184          * if PCI_REGION_MEM is set we do a two pass search with preference
185          * on matches that don't have PCI_REGION_SYS_MEMORY set
186          */
187         if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) {
188                 ret = __pci_hose_bus_to_phys(hose, bus_addr,
189                                 flags, PCI_REGION_SYS_MEMORY, &phys_addr);
190                 if (!ret)
191                         return phys_addr;
192         }
193
194         ret = __pci_hose_bus_to_phys(hose, bus_addr, flags, 0, &phys_addr);
195
196         if (ret)
197                 puts("pci_hose_bus_to_phys: invalid physical address\n");
198
199         return phys_addr;
200 }
201
202 int __pci_hose_phys_to_bus(struct pci_controller *hose,
203                            phys_addr_t phys_addr,
204                            unsigned long flags,
205                            unsigned long skip_mask,
206                            pci_addr_t *ba)
207 {
208         struct pci_region *res;
209         pci_addr_t bus_addr;
210         int i;
211
212         for (i = 0; i < hose->region_count; i++) {
213                 res = &hose->regions[i];
214
215                 if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
216                         continue;
217
218                 if (res->flags & skip_mask)
219                         continue;
220
221                 bus_addr = phys_addr - res->phys_start + res->bus_start;
222
223                 if (bus_addr >= res->bus_start &&
224                     (bus_addr - res->bus_start) < res->size) {
225                         *ba = bus_addr;
226                         return 0;
227                 }
228         }
229
230         return 1;
231 }
232
233 /*
234  * pci_hose_phys_to_bus(): Convert physical address to bus address
235  * @hose:       PCI hose of the root PCI controller
236  * @phys_addr:  physical address to convert
237  * @flags:      flags of pci regions
238  * @return bus address if OK, 0 on error
239  */
240 pci_addr_t pci_hose_phys_to_bus(struct pci_controller *hose,
241                                 phys_addr_t phys_addr,
242                                 unsigned long flags)
243 {
244         pci_addr_t bus_addr = 0;
245         int ret;
246
247         if (!hose) {
248                 puts("pci_hose_phys_to_bus: invalid hose\n");
249                 return bus_addr;
250         }
251
252         /*
253          * if PCI_REGION_MEM is set we do a two pass search with preference
254          * on matches that don't have PCI_REGION_SYS_MEMORY set
255          */
256         if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) {
257                 ret = __pci_hose_phys_to_bus(hose, phys_addr,
258                                 flags, PCI_REGION_SYS_MEMORY, &bus_addr);
259                 if (!ret)
260                         return bus_addr;
261         }
262
263         ret = __pci_hose_phys_to_bus(hose, phys_addr, flags, 0, &bus_addr);
264
265         if (ret)
266                 puts("pci_hose_phys_to_bus: invalid physical address\n");
267
268         return bus_addr;
269 }
270
271 pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
272 {
273         struct pci_device_id ids[2] = { {}, {0, 0} };
274
275         ids[0].vendor = vendor;
276         ids[0].device = device;
277
278         return pci_find_devices(ids, index);
279 }
280
281 pci_dev_t pci_hose_find_devices(struct pci_controller *hose, int busnum,
282                                 struct pci_device_id *ids, int *indexp)
283 {
284         int found_multi = 0;
285         u16 vendor, device;
286         u8 header_type;
287         pci_dev_t bdf;
288         int i;
289
290         for (bdf = PCI_BDF(busnum, 0, 0);
291              bdf < PCI_BDF(busnum + 1, 0, 0);
292              bdf += PCI_BDF(0, 0, 1)) {
293                 if (pci_skip_dev(hose, bdf))
294                         continue;
295
296                 if (!PCI_FUNC(bdf)) {
297                         pci_read_config_byte(bdf, PCI_HEADER_TYPE,
298                                              &header_type);
299                         found_multi = header_type & 0x80;
300                 } else {
301                         if (!found_multi)
302                                 continue;
303                 }
304
305                 pci_read_config_word(bdf, PCI_VENDOR_ID, &vendor);
306                 pci_read_config_word(bdf, PCI_DEVICE_ID, &device);
307
308                 for (i = 0; ids[i].vendor != 0; i++) {
309                         if (vendor == ids[i].vendor &&
310                             device == ids[i].device) {
311                                 if ((*indexp) <= 0)
312                                         return bdf;
313
314                                 (*indexp)--;
315                         }
316                 }
317         }
318
319         return -1;
320 }
321
322 pci_dev_t pci_find_class(uint find_class, int index)
323 {
324         int bus;
325         int devnum;
326         pci_dev_t bdf;
327         uint32_t class;
328
329         for (bus = 0; bus <= pci_last_busno(); bus++) {
330                 for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES - 1; devnum++) {
331                         pci_read_config_dword(PCI_BDF(bus, devnum, 0),
332                                               PCI_CLASS_REVISION, &class);
333                         if (class >> 16 == 0xffff)
334                                 continue;
335
336                         for (bdf = PCI_BDF(bus, devnum, 0);
337                                         bdf <= PCI_BDF(bus, devnum,
338                                                 PCI_MAX_PCI_FUNCTIONS - 1);
339                                         bdf += PCI_BDF(0, 0, 1)) {
340                                 pci_read_config_dword(bdf, PCI_CLASS_REVISION,
341                                                       &class);
342                                 class >>= 8;
343
344                                 if (class != find_class)
345                                         continue;
346                                 /*
347                                  * Decrement the index. We want to return the
348                                  * correct device, so index is 0 for the first
349                                  * matching device, 1 for the second, etc.
350                                  */
351                                 if (index) {
352                                         index--;
353                                         continue;
354                                 }
355                                 /* Return index'th controller. */
356                                 return bdf;
357                         }
358                 }
359         }
360
361         return -ENODEV;
362 }
363 #endif /* !CONFIG_DM_PCI || CONFIG_DM_PCI_COMPAT */