blob: 24c66bbef2f62222863cc853e02fc5fc140fd8f9 [file] [log] [blame]
Simon Glass75532d82015-03-05 12:25:24 -07001/*
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
18const 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
81pci_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 */
144void *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
162void 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
171u32 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
184int __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
212phys_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
243pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
244{
245 struct pci_device_id ids[2] = { {}, {0, 0} };
246
247 ids[0].vendor = vendor;
248 ids[0].device = device;
249
250 return pci_find_devices(ids, index);
251}
252
253pci_dev_t pci_hose_find_devices(struct pci_controller *hose, int busnum,
254 struct pci_device_id *ids, int *indexp)
255{
256 int found_multi = 0;
257 u16 vendor, device;
258 u8 header_type;
259 pci_dev_t bdf;
260 int i;
261
262 for (bdf = PCI_BDF(busnum, 0, 0);
263 bdf < PCI_BDF(busnum + 1, 0, 0);
264 bdf += PCI_BDF(0, 0, 1)) {
265 if (pci_skip_dev(hose, bdf))
266 continue;
267
268 if (!PCI_FUNC(bdf)) {
269 pci_read_config_byte(bdf, PCI_HEADER_TYPE,
270 &header_type);
271 found_multi = header_type & 0x80;
272 } else {
273 if (!found_multi)
274 continue;
275 }
276
277 pci_read_config_word(bdf, PCI_VENDOR_ID, &vendor);
278 pci_read_config_word(bdf, PCI_DEVICE_ID, &device);
279
280 for (i = 0; ids[i].vendor != 0; i++) {
281 if (vendor == ids[i].vendor &&
282 device == ids[i].device) {
283 if ((*indexp) <= 0)
284 return bdf;
285
286 (*indexp)--;
287 }
288 }
289 }
290
291 return -1;
292}