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 
pci_class_str(u8 class)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 
pci_skip_dev(struct pci_controller * hose,pci_dev_t dev)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 */
pci_map_bar(pci_dev_t pdev,int bar,int flags)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 
pci_write_bar32(struct pci_controller * hose,pci_dev_t dev,int barnum,u32 addr_and_ctrl)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 
pci_read_bar32(struct pci_controller * hose,pci_dev_t dev,int barnum)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 
__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)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 
pci_hose_bus_to_phys(struct pci_controller * hose,pci_addr_t bus_addr,unsigned long flags)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 
__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)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  */
pci_hose_phys_to_bus(struct pci_controller * hose,phys_addr_t phys_addr,unsigned long flags)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 
pci_find_device(unsigned int vendor,unsigned int device,int index)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 
pci_hose_find_devices(struct pci_controller * hose,int busnum,struct pci_device_id * ids,int * indexp)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 
pci_find_class(uint find_class,int index)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 */
364