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 <env.h>
15 #include <errno.h>
16 #include <pci.h>
17 #include <asm/io.h>
18 
pci_class_str(u8 class)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 
pci_skip_dev(struct pci_controller * hose,pci_dev_t dev)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 (env_get("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 */
pci_map_bar(pci_dev_t pdev,int bar,int flags)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 
pci_write_bar32(struct pci_controller * hose,pci_dev_t dev,int barnum,u32 addr_and_ctrl)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 
pci_read_bar32(struct pci_controller * hose,pci_dev_t dev,int barnum)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 
__pci_hose_bus_to_phys(struct pci_controller * hose,pci_addr_t bus_addr,unsigned long flags,unsigned long skip_mask,phys_addr_t * pa)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 
pci_hose_bus_to_phys(struct pci_controller * hose,pci_addr_t bus_addr,unsigned long flags)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 	/*
185 	 * if PCI_REGION_MEM is set we do a two pass search with preference
186 	 * on matches that don't have PCI_REGION_SYS_MEMORY set
187 	 */
188 	if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) {
189 		ret = __pci_hose_bus_to_phys(hose, bus_addr,
190 				flags, PCI_REGION_SYS_MEMORY, &phys_addr);
191 		if (!ret)
192 			return phys_addr;
193 	}
194 
195 	ret = __pci_hose_bus_to_phys(hose, bus_addr, flags, 0, &phys_addr);
196 
197 	if (ret)
198 		puts("pci_hose_bus_to_phys: invalid physical address\n");
199 
200 	return phys_addr;
201 }
202 
__pci_hose_phys_to_bus(struct pci_controller * hose,phys_addr_t phys_addr,unsigned long flags,unsigned long skip_mask,pci_addr_t * ba)203 int __pci_hose_phys_to_bus(struct pci_controller *hose,
204 			   phys_addr_t phys_addr,
205 			   unsigned long flags,
206 			   unsigned long skip_mask,
207 			   pci_addr_t *ba)
208 {
209 	struct pci_region *res;
210 	pci_addr_t bus_addr;
211 	int i;
212 
213 	for (i = 0; i < hose->region_count; i++) {
214 		res = &hose->regions[i];
215 
216 		if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
217 			continue;
218 
219 		if (res->flags & skip_mask)
220 			continue;
221 
222 		bus_addr = phys_addr - res->phys_start + res->bus_start;
223 
224 		if (bus_addr >= res->bus_start &&
225 		    (bus_addr - res->bus_start) < res->size) {
226 			*ba = bus_addr;
227 			return 0;
228 		}
229 	}
230 
231 	return 1;
232 }
233 
234 /*
235  * pci_hose_phys_to_bus(): Convert physical address to bus address
236  * @hose:	PCI hose of the root PCI controller
237  * @phys_addr:	physical address to convert
238  * @flags:	flags of pci regions
239  * @return bus address if OK, 0 on error
240  */
pci_hose_phys_to_bus(struct pci_controller * hose,phys_addr_t phys_addr,unsigned long flags)241 pci_addr_t pci_hose_phys_to_bus(struct pci_controller *hose,
242 				phys_addr_t phys_addr,
243 				unsigned long flags)
244 {
245 	pci_addr_t bus_addr = 0;
246 	int ret;
247 
248 	if (!hose) {
249 		puts("pci_hose_phys_to_bus: invalid hose\n");
250 		return bus_addr;
251 	}
252 
253 	/*
254 	 * if PCI_REGION_MEM is set we do a two pass search with preference
255 	 * on matches that don't have PCI_REGION_SYS_MEMORY set
256 	 */
257 	if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) {
258 		ret = __pci_hose_phys_to_bus(hose, phys_addr,
259 				flags, PCI_REGION_SYS_MEMORY, &bus_addr);
260 		if (!ret)
261 			return bus_addr;
262 	}
263 
264 	ret = __pci_hose_phys_to_bus(hose, phys_addr, flags, 0, &bus_addr);
265 
266 	if (ret)
267 		puts("pci_hose_phys_to_bus: invalid physical address\n");
268 
269 	return bus_addr;
270 }
271 
pci_find_device(unsigned int vendor,unsigned int device,int index)272 pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
273 {
274 	struct pci_device_id ids[2] = { {}, {0, 0} };
275 
276 	ids[0].vendor = vendor;
277 	ids[0].device = device;
278 
279 	return pci_find_devices(ids, index);
280 }
281 
pci_hose_find_devices(struct pci_controller * hose,int busnum,struct pci_device_id * ids,int * indexp)282 pci_dev_t pci_hose_find_devices(struct pci_controller *hose, int busnum,
283 				struct pci_device_id *ids, int *indexp)
284 {
285 	int found_multi = 0;
286 	u16 vendor, device;
287 	u8 header_type;
288 	pci_dev_t bdf;
289 	int i;
290 
291 	for (bdf = PCI_BDF(busnum, 0, 0);
292 	     bdf < PCI_BDF(busnum + 1, 0, 0);
293 	     bdf += PCI_BDF(0, 0, 1)) {
294 		if (pci_skip_dev(hose, bdf))
295 			continue;
296 
297 		if (!PCI_FUNC(bdf)) {
298 			pci_read_config_byte(bdf, PCI_HEADER_TYPE,
299 					     &header_type);
300 			found_multi = header_type & 0x80;
301 		} else {
302 			if (!found_multi)
303 				continue;
304 		}
305 
306 		pci_read_config_word(bdf, PCI_VENDOR_ID, &vendor);
307 		pci_read_config_word(bdf, PCI_DEVICE_ID, &device);
308 
309 		for (i = 0; ids[i].vendor != 0; i++) {
310 			if (vendor == ids[i].vendor &&
311 			    device == ids[i].device) {
312 				if ((*indexp) <= 0)
313 					return bdf;
314 
315 				(*indexp)--;
316 			}
317 		}
318 	}
319 
320 	return -1;
321 }
322 
pci_find_class(uint find_class,int index)323 pci_dev_t pci_find_class(uint find_class, int index)
324 {
325 	int bus;
326 	int devnum;
327 	pci_dev_t bdf;
328 	uint32_t class;
329 
330 	for (bus = 0; bus <= pci_last_busno(); bus++) {
331 		for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES - 1; devnum++) {
332 			pci_read_config_dword(PCI_BDF(bus, devnum, 0),
333 					      PCI_CLASS_REVISION, &class);
334 			if (class >> 16 == 0xffff)
335 				continue;
336 
337 			for (bdf = PCI_BDF(bus, devnum, 0);
338 					bdf <= PCI_BDF(bus, devnum,
339 						PCI_MAX_PCI_FUNCTIONS - 1);
340 					bdf += PCI_BDF(0, 0, 1)) {
341 				pci_read_config_dword(bdf, PCI_CLASS_REVISION,
342 						      &class);
343 				class >>= 8;
344 
345 				if (class != find_class)
346 					continue;
347 				/*
348 				 * Decrement the index. We want to return the
349 				 * correct device, so index is 0 for the first
350 				 * matching device, 1 for the second, etc.
351 				 */
352 				if (index) {
353 					index--;
354 					continue;
355 				}
356 				/* Return index'th controller. */
357 				return bdf;
358 			}
359 		}
360 	}
361 
362 	return -ENODEV;
363 }
364 #endif /* !CONFIG_DM_PCI || CONFIG_DM_PCI_COMPAT */
365