blob: 932eab85bf5629bdd8f0435701bb249bba03427c [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
Stefan Roesea47a12b2010-04-15 16:07:28 +02002 * arch/powerpc/kernel/pci_auto.c
wdenkc6097192002-11-03 00:24:07 +00003 *
4 * PCI autoconfiguration library
5 *
6 * Author: Matt Porter <mporter@mvista.com>
7 *
8 * Copyright 2000 MontaVista Software Inc.
9 *
Wolfgang Denk1a459662013-07-08 09:37:19 +020010 * SPDX-License-Identifier: GPL-2.0+
wdenkc6097192002-11-03 00:24:07 +000011 */
12
13#include <common.h>
Simon Glass4a2708a2015-01-14 21:37:04 -070014#include <errno.h>
wdenkc6097192002-11-03 00:24:07 +000015#include <pci.h>
16
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020017/* the user can define CONFIG_SYS_PCI_CACHE_LINE_SIZE to avoid problems */
18#ifndef CONFIG_SYS_PCI_CACHE_LINE_SIZE
19#define CONFIG_SYS_PCI_CACHE_LINE_SIZE 8
Gary Jennejohn81b73de2007-08-31 15:21:46 +020020#endif
21
wdenkc6097192002-11-03 00:24:07 +000022/*
23 *
24 */
25
wdenkc6097192002-11-03 00:24:07 +000026void pciauto_setup_device(struct pci_controller *hose,
27 pci_dev_t dev, int bars_num,
28 struct pci_region *mem,
Kumar Galaa1790122006-01-11 13:24:15 -060029 struct pci_region *prefetch,
wdenkc6097192002-11-03 00:24:07 +000030 struct pci_region *io)
31{
Kumar Galacf5787f2012-09-19 04:47:36 +000032 u32 bar_response;
Kumar Gala30e76d52008-10-21 08:36:08 -050033 pci_size_t bar_size;
Andrew Sharpaf778c62012-08-01 12:27:16 +000034 u16 cmdstat = 0;
wdenkc6097192002-11-03 00:24:07 +000035 int bar, bar_nr = 0;
Simon Glass53292ad2015-07-31 09:31:34 -060036#ifndef CONFIG_PCI_ENUM_ONLY
Bin Meng6c896632015-07-08 13:06:40 +080037 u8 header_type;
38 int rom_addr;
Andrew Sharp69fd2d32012-08-29 14:16:32 +000039 pci_addr_t bar_value;
40 struct pci_region *bar_res;
wdenkc6097192002-11-03 00:24:07 +000041 int found_mem64 = 0;
Andrew Sharp69fd2d32012-08-29 14:16:32 +000042#endif
Bin Mengcdf9f082015-10-01 00:35:59 -070043 u16 class;
wdenkc6097192002-11-03 00:24:07 +000044
Andrew Sharpaf778c62012-08-01 12:27:16 +000045 pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat);
wdenkc6097192002-11-03 00:24:07 +000046 cmdstat = (cmdstat & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) | PCI_COMMAND_MASTER;
47
Andrew Sharpcb2bf932012-08-29 14:16:29 +000048 for (bar = PCI_BASE_ADDRESS_0;
49 bar < PCI_BASE_ADDRESS_0 + (bars_num * 4); bar += 4) {
wdenkc6097192002-11-03 00:24:07 +000050 /* Tickle the BAR and get the response */
Andrew Sharp69fd2d32012-08-29 14:16:32 +000051#ifndef CONFIG_PCI_ENUM_ONLY
wdenkc6097192002-11-03 00:24:07 +000052 pci_hose_write_config_dword(hose, dev, bar, 0xffffffff);
Andrew Sharp69fd2d32012-08-29 14:16:32 +000053#endif
wdenkc6097192002-11-03 00:24:07 +000054 pci_hose_read_config_dword(hose, dev, bar, &bar_response);
55
56 /* If BAR is not implemented go to the next BAR */
57 if (!bar_response)
58 continue;
59
Andrew Sharp69fd2d32012-08-29 14:16:32 +000060#ifndef CONFIG_PCI_ENUM_ONLY
wdenkc6097192002-11-03 00:24:07 +000061 found_mem64 = 0;
Andrew Sharp69fd2d32012-08-29 14:16:32 +000062#endif
wdenkc6097192002-11-03 00:24:07 +000063
64 /* Check the BAR type and set our address mask */
wdenk3c74e322004-02-22 23:46:08 +000065 if (bar_response & PCI_BASE_ADDRESS_SPACE) {
Jin Zhengxiong-R64188bd22c2b2006-06-27 18:12:02 +080066 bar_size = ((~(bar_response & PCI_BASE_ADDRESS_IO_MASK))
67 & 0xffff) + 1;
Andrew Sharp69fd2d32012-08-29 14:16:32 +000068#ifndef CONFIG_PCI_ENUM_ONLY
wdenkc6097192002-11-03 00:24:07 +000069 bar_res = io;
Andrew Sharp69fd2d32012-08-29 14:16:32 +000070#endif
wdenkc6097192002-11-03 00:24:07 +000071
Simon Glassda4b1592015-07-31 09:31:33 -060072 debug("PCI Autoconfig: BAR %d, I/O, size=0x%llx, ",
73 bar_nr, (unsigned long long)bar_size);
wdenk3c74e322004-02-22 23:46:08 +000074 } else {
Andrew Sharpcb2bf932012-08-29 14:16:29 +000075 if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
Kumar Gala30e76d52008-10-21 08:36:08 -050076 PCI_BASE_ADDRESS_MEM_TYPE_64) {
77 u32 bar_response_upper;
78 u64 bar64;
Andrew Sharp69fd2d32012-08-29 14:16:32 +000079
80#ifndef CONFIG_PCI_ENUM_ONLY
Andrew Sharpcb2bf932012-08-29 14:16:29 +000081 pci_hose_write_config_dword(hose, dev, bar + 4,
82 0xffffffff);
Andrew Sharp69fd2d32012-08-29 14:16:32 +000083#endif
Andrew Sharpcb2bf932012-08-29 14:16:29 +000084 pci_hose_read_config_dword(hose, dev, bar + 4,
85 &bar_response_upper);
wdenkc6097192002-11-03 00:24:07 +000086
Kumar Gala30e76d52008-10-21 08:36:08 -050087 bar64 = ((u64)bar_response_upper << 32) | bar_response;
88
89 bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + 1;
Andrew Sharp69fd2d32012-08-29 14:16:32 +000090#ifndef CONFIG_PCI_ENUM_ONLY
Kumar Gala30e76d52008-10-21 08:36:08 -050091 found_mem64 = 1;
Andrew Sharp69fd2d32012-08-29 14:16:32 +000092#endif
Kumar Gala30e76d52008-10-21 08:36:08 -050093 } else {
94 bar_size = (u32)(~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1);
95 }
Andrew Sharp69fd2d32012-08-29 14:16:32 +000096#ifndef CONFIG_PCI_ENUM_ONLY
Kumar Galaa1790122006-01-11 13:24:15 -060097 if (prefetch && (bar_response & PCI_BASE_ADDRESS_MEM_PREFETCH))
98 bar_res = prefetch;
99 else
100 bar_res = mem;
Andrew Sharp69fd2d32012-08-29 14:16:32 +0000101#endif
wdenkc6097192002-11-03 00:24:07 +0000102
Simon Glass4bad2e72015-07-27 15:47:18 -0600103 debug("PCI Autoconfig: BAR %d, %s, size=0x%llx, ",
104 bar_nr, bar_res == prefetch ? "Prf" : "Mem",
105 (unsigned long long)bar_size);
wdenkc6097192002-11-03 00:24:07 +0000106 }
107
Andrew Sharp69fd2d32012-08-29 14:16:32 +0000108#ifndef CONFIG_PCI_ENUM_ONLY
wdenk3c74e322004-02-22 23:46:08 +0000109 if (pciauto_region_allocate(bar_res, bar_size, &bar_value) == 0) {
wdenkc6097192002-11-03 00:24:07 +0000110 /* Write it out and update our limit */
Kumar Gala30e76d52008-10-21 08:36:08 -0500111 pci_hose_write_config_dword(hose, dev, bar, (u32)bar_value);
wdenkc6097192002-11-03 00:24:07 +0000112
wdenk3c74e322004-02-22 23:46:08 +0000113 if (found_mem64) {
wdenkc6097192002-11-03 00:24:07 +0000114 bar += 4;
Kumar Gala30e76d52008-10-21 08:36:08 -0500115#ifdef CONFIG_SYS_PCI_64BIT
116 pci_hose_write_config_dword(hose, dev, bar, (u32)(bar_value>>32));
117#else
118 /*
119 * If we are a 64-bit decoder then increment to the
120 * upper 32 bits of the bar and force it to locate
121 * in the lower 4GB of memory.
122 */
wdenkc6097192002-11-03 00:24:07 +0000123 pci_hose_write_config_dword(hose, dev, bar, 0x00000000);
Kumar Gala30e76d52008-10-21 08:36:08 -0500124#endif
wdenkc6097192002-11-03 00:24:07 +0000125 }
126
wdenkc6097192002-11-03 00:24:07 +0000127 }
Andrew Sharp69fd2d32012-08-29 14:16:32 +0000128#endif
129 cmdstat |= (bar_response & PCI_BASE_ADDRESS_SPACE) ?
130 PCI_COMMAND_IO : PCI_COMMAND_MEMORY;
wdenkc6097192002-11-03 00:24:07 +0000131
Simon Glassda4b1592015-07-31 09:31:33 -0600132 debug("\n");
wdenkc6097192002-11-03 00:24:07 +0000133
134 bar_nr++;
135 }
136
Simon Glass53292ad2015-07-31 09:31:34 -0600137#ifndef CONFIG_PCI_ENUM_ONLY
Bin Meng6c896632015-07-08 13:06:40 +0800138 /* Configure the expansion ROM address */
139 pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &header_type);
Bin Meng74454352015-10-07 02:13:18 -0700140 header_type &= 0x7f;
Bin Meng6c896632015-07-08 13:06:40 +0800141 if (header_type != PCI_HEADER_TYPE_CARDBUS) {
142 rom_addr = (header_type == PCI_HEADER_TYPE_NORMAL) ?
143 PCI_ROM_ADDRESS : PCI_ROM_ADDRESS1;
144 pci_hose_write_config_dword(hose, dev, rom_addr, 0xfffffffe);
145 pci_hose_read_config_dword(hose, dev, rom_addr, &bar_response);
146 if (bar_response) {
147 bar_size = -(bar_response & ~1);
Simon Glassda4b1592015-07-31 09:31:33 -0600148 debug("PCI Autoconfig: ROM, size=%#x, ",
149 (unsigned int)bar_size);
Bin Meng6c896632015-07-08 13:06:40 +0800150 if (pciauto_region_allocate(mem, bar_size,
151 &bar_value) == 0) {
152 pci_hose_write_config_dword(hose, dev, rom_addr,
153 bar_value);
154 }
155 cmdstat |= PCI_COMMAND_MEMORY;
Simon Glassda4b1592015-07-31 09:31:33 -0600156 debug("\n");
Bin Meng6c896632015-07-08 13:06:40 +0800157 }
158 }
Simon Glass53292ad2015-07-31 09:31:34 -0600159#endif
Bin Meng6c896632015-07-08 13:06:40 +0800160
Bin Mengcdf9f082015-10-01 00:35:59 -0700161 /* PCI_COMMAND_IO must be set for VGA device */
162 pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class);
163 if (class == PCI_CLASS_DISPLAY_VGA)
164 cmdstat |= PCI_COMMAND_IO;
165
Andrew Sharpaf778c62012-08-01 12:27:16 +0000166 pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat);
Gary Jennejohn81b73de2007-08-31 15:21:46 +0200167 pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200168 CONFIG_SYS_PCI_CACHE_LINE_SIZE);
wdenkc6097192002-11-03 00:24:07 +0000169 pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
170}
171
Ed Swarthoutba5feb12007-07-11 14:51:48 -0500172void pciauto_prescan_setup_bridge(struct pci_controller *hose,
wdenkc6097192002-11-03 00:24:07 +0000173 pci_dev_t dev, int sub_bus)
174{
Bin Mengd11d9ef2015-07-19 00:20:06 +0800175 struct pci_region *pci_mem;
176 struct pci_region *pci_prefetch;
177 struct pci_region *pci_io;
David Feng6eefd522015-02-02 16:53:13 +0800178 u16 cmdstat, prefechable_64;
wdenkc6097192002-11-03 00:24:07 +0000179
Bin Mengd11d9ef2015-07-19 00:20:06 +0800180#ifdef CONFIG_DM_PCI
181 /* The root controller has the region information */
182 struct pci_controller *ctlr_hose = pci_bus_to_hose(0);
183
184 pci_mem = ctlr_hose->pci_mem;
185 pci_prefetch = ctlr_hose->pci_prefetch;
186 pci_io = ctlr_hose->pci_io;
187#else
188 pci_mem = hose->pci_mem;
189 pci_prefetch = hose->pci_prefetch;
190 pci_io = hose->pci_io;
191#endif
192
Andrew Sharpaf778c62012-08-01 12:27:16 +0000193 pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat);
David Feng6eefd522015-02-02 16:53:13 +0800194 pci_hose_read_config_word(hose, dev, PCI_PREF_MEMORY_BASE,
195 &prefechable_64);
196 prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK;
wdenkc6097192002-11-03 00:24:07 +0000197
198 /* Configure bus number registers */
Bin Meng95f3aa22015-07-19 00:20:03 +0800199#ifdef CONFIG_DM_PCI
200 pci_hose_write_config_byte(hose, dev, PCI_PRIMARY_BUS, PCI_BUS(dev));
201 pci_hose_write_config_byte(hose, dev, PCI_SECONDARY_BUS, sub_bus);
202#else
Ed Swarthoute8b85f32007-07-11 14:52:08 -0500203 pci_hose_write_config_byte(hose, dev, PCI_PRIMARY_BUS,
204 PCI_BUS(dev) - hose->first_busno);
205 pci_hose_write_config_byte(hose, dev, PCI_SECONDARY_BUS,
206 sub_bus - hose->first_busno);
Bin Meng95f3aa22015-07-19 00:20:03 +0800207#endif
wdenkc6097192002-11-03 00:24:07 +0000208 pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, 0xff);
209
wdenk3c74e322004-02-22 23:46:08 +0000210 if (pci_mem) {
wdenkc6097192002-11-03 00:24:07 +0000211 /* Round memory allocator to 1MB boundary */
212 pciauto_region_align(pci_mem, 0x100000);
213
214 /* Set up memory and I/O filter limits, assume 32-bit I/O space */
215 pci_hose_write_config_word(hose, dev, PCI_MEMORY_BASE,
216 (pci_mem->bus_lower & 0xfff00000) >> 16);
217
218 cmdstat |= PCI_COMMAND_MEMORY;
219 }
220
Kumar Galaa1790122006-01-11 13:24:15 -0600221 if (pci_prefetch) {
222 /* Round memory allocator to 1MB boundary */
223 pciauto_region_align(pci_prefetch, 0x100000);
224
225 /* Set up memory and I/O filter limits, assume 32-bit I/O space */
226 pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE,
227 (pci_prefetch->bus_lower & 0xfff00000) >> 16);
David Feng6eefd522015-02-02 16:53:13 +0800228 if (prefechable_64 == PCI_PREF_RANGE_TYPE_64)
229#ifdef CONFIG_SYS_PCI_64BIT
230 pci_hose_write_config_dword(hose, dev,
231 PCI_PREF_BASE_UPPER32,
232 pci_prefetch->bus_lower >> 32);
233#else
234 pci_hose_write_config_dword(hose, dev,
235 PCI_PREF_BASE_UPPER32,
236 0x0);
237#endif
Kumar Galaa1790122006-01-11 13:24:15 -0600238
239 cmdstat |= PCI_COMMAND_MEMORY;
240 } else {
241 /* We don't support prefetchable memory for now, so disable */
242 pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE, 0x1000);
Matthew McClintocka4e11552006-06-28 10:44:23 -0500243 pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, 0x0);
David Feng6eefd522015-02-02 16:53:13 +0800244 if (prefechable_64 == PCI_PREF_RANGE_TYPE_64) {
245 pci_hose_write_config_word(hose, dev, PCI_PREF_BASE_UPPER32, 0x0);
246 pci_hose_write_config_word(hose, dev, PCI_PREF_LIMIT_UPPER32, 0x0);
247 }
Kumar Galaa1790122006-01-11 13:24:15 -0600248 }
249
wdenk3c74e322004-02-22 23:46:08 +0000250 if (pci_io) {
wdenkc6097192002-11-03 00:24:07 +0000251 /* Round I/O allocator to 4KB boundary */
252 pciauto_region_align(pci_io, 0x1000);
253
254 pci_hose_write_config_byte(hose, dev, PCI_IO_BASE,
255 (pci_io->bus_lower & 0x0000f000) >> 8);
256 pci_hose_write_config_word(hose, dev, PCI_IO_BASE_UPPER16,
257 (pci_io->bus_lower & 0xffff0000) >> 16);
258
259 cmdstat |= PCI_COMMAND_IO;
260 }
261
wdenkc6097192002-11-03 00:24:07 +0000262 /* Enable memory and I/O accesses, enable bus master */
Andrew Sharpaf778c62012-08-01 12:27:16 +0000263 pci_hose_write_config_word(hose, dev, PCI_COMMAND,
264 cmdstat | PCI_COMMAND_MASTER);
wdenkc6097192002-11-03 00:24:07 +0000265}
266
Ed Swarthoutba5feb12007-07-11 14:51:48 -0500267void pciauto_postscan_setup_bridge(struct pci_controller *hose,
wdenkc6097192002-11-03 00:24:07 +0000268 pci_dev_t dev, int sub_bus)
269{
Bin Mengd11d9ef2015-07-19 00:20:06 +0800270 struct pci_region *pci_mem;
271 struct pci_region *pci_prefetch;
272 struct pci_region *pci_io;
273
274#ifdef CONFIG_DM_PCI
275 /* The root controller has the region information */
276 struct pci_controller *ctlr_hose = pci_bus_to_hose(0);
277
278 pci_mem = ctlr_hose->pci_mem;
279 pci_prefetch = ctlr_hose->pci_prefetch;
280 pci_io = ctlr_hose->pci_io;
281#else
282 pci_mem = hose->pci_mem;
283 pci_prefetch = hose->pci_prefetch;
284 pci_io = hose->pci_io;
285#endif
wdenkc6097192002-11-03 00:24:07 +0000286
287 /* Configure bus number registers */
Bin Meng95f3aa22015-07-19 00:20:03 +0800288#ifdef CONFIG_DM_PCI
289 pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, sub_bus);
290#else
Ed Swarthoute8b85f32007-07-11 14:52:08 -0500291 pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS,
292 sub_bus - hose->first_busno);
Bin Meng95f3aa22015-07-19 00:20:03 +0800293#endif
wdenkc6097192002-11-03 00:24:07 +0000294
wdenk3c74e322004-02-22 23:46:08 +0000295 if (pci_mem) {
wdenkc6097192002-11-03 00:24:07 +0000296 /* Round memory allocator to 1MB boundary */
297 pciauto_region_align(pci_mem, 0x100000);
298
299 pci_hose_write_config_word(hose, dev, PCI_MEMORY_LIMIT,
Andrew Sharpcb2bf932012-08-29 14:16:29 +0000300 (pci_mem->bus_lower - 1) >> 16);
wdenkc6097192002-11-03 00:24:07 +0000301 }
302
Kumar Galaa1790122006-01-11 13:24:15 -0600303 if (pci_prefetch) {
David Feng6eefd522015-02-02 16:53:13 +0800304 u16 prefechable_64;
305
306 pci_hose_read_config_word(hose, dev,
307 PCI_PREF_MEMORY_LIMIT,
308 &prefechable_64);
309 prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK;
310
Kumar Galaa1790122006-01-11 13:24:15 -0600311 /* Round memory allocator to 1MB boundary */
312 pciauto_region_align(pci_prefetch, 0x100000);
313
314 pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT,
Andrew Sharpcb2bf932012-08-29 14:16:29 +0000315 (pci_prefetch->bus_lower - 1) >> 16);
David Feng6eefd522015-02-02 16:53:13 +0800316 if (prefechable_64 == PCI_PREF_RANGE_TYPE_64)
317#ifdef CONFIG_SYS_PCI_64BIT
318 pci_hose_write_config_dword(hose, dev,
319 PCI_PREF_LIMIT_UPPER32,
320 (pci_prefetch->bus_lower - 1) >> 32);
321#else
322 pci_hose_write_config_dword(hose, dev,
323 PCI_PREF_LIMIT_UPPER32,
324 0x0);
325#endif
Kumar Galaa1790122006-01-11 13:24:15 -0600326 }
327
wdenk3c74e322004-02-22 23:46:08 +0000328 if (pci_io) {
wdenkc6097192002-11-03 00:24:07 +0000329 /* Round I/O allocator to 4KB boundary */
330 pciauto_region_align(pci_io, 0x1000);
331
332 pci_hose_write_config_byte(hose, dev, PCI_IO_LIMIT,
Andrew Sharpcb2bf932012-08-29 14:16:29 +0000333 ((pci_io->bus_lower - 1) & 0x0000f000) >> 8);
wdenkc6097192002-11-03 00:24:07 +0000334 pci_hose_write_config_word(hose, dev, PCI_IO_LIMIT_UPPER16,
Andrew Sharpcb2bf932012-08-29 14:16:29 +0000335 ((pci_io->bus_lower - 1) & 0xffff0000) >> 16);
wdenkc6097192002-11-03 00:24:07 +0000336 }
337}
338
wdenkc6097192002-11-03 00:24:07 +0000339
Andrew Sharpcb2bf932012-08-29 14:16:29 +0000340/*
341 * HJF: Changed this to return int. I think this is required
wdenkc7de8292002-11-19 11:04:11 +0000342 * to get the correct result when scanning bridges
343 */
344int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)
wdenkc6097192002-11-03 00:24:07 +0000345{
Bin Mengd11d9ef2015-07-19 00:20:06 +0800346 struct pci_region *pci_mem;
347 struct pci_region *pci_prefetch;
348 struct pci_region *pci_io;
wdenkc7de8292002-11-19 11:04:11 +0000349 unsigned int sub_bus = PCI_BUS(dev);
wdenkc6097192002-11-03 00:24:07 +0000350 unsigned short class;
wdenk5653fc32004-02-08 22:55:38 +0000351 int n;
wdenkc6097192002-11-03 00:24:07 +0000352
Bin Mengd11d9ef2015-07-19 00:20:06 +0800353#ifdef CONFIG_DM_PCI
354 /* The root controller has the region information */
355 struct pci_controller *ctlr_hose = pci_bus_to_hose(0);
356
357 pci_mem = ctlr_hose->pci_mem;
358 pci_prefetch = ctlr_hose->pci_prefetch;
359 pci_io = ctlr_hose->pci_io;
360#else
361 pci_mem = hose->pci_mem;
362 pci_prefetch = hose->pci_prefetch;
363 pci_io = hose->pci_io;
364#endif
365
wdenkc6097192002-11-03 00:24:07 +0000366 pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class);
367
Andrew Sharpcb2bf932012-08-29 14:16:29 +0000368 switch (class) {
wdenkc6097192002-11-03 00:24:07 +0000369 case PCI_CLASS_BRIDGE_PCI:
Simon Glassda4b1592015-07-31 09:31:33 -0600370 debug("PCI Autoconfig: Found P2P bridge, device %d\n",
371 PCI_DEV(dev));
Simon Glassff3e0772015-03-05 12:25:25 -0700372
Bin Mengd11d9ef2015-07-19 00:20:06 +0800373 pciauto_setup_device(hose, dev, 2, pci_mem,
374 pci_prefetch, pci_io);
wdenkc6097192002-11-03 00:24:07 +0000375
Simon Glassff3e0772015-03-05 12:25:25 -0700376#ifdef CONFIG_DM_PCI
377 n = dm_pci_hose_probe_bus(hose, dev);
378 if (n < 0)
379 return n;
380 sub_bus = (unsigned int)n;
381#else
wdenk3c74e322004-02-22 23:46:08 +0000382 /* Passing in current_busno allows for sibling P2P bridges */
Simon Glassff3e0772015-03-05 12:25:25 -0700383 hose->current_busno++;
wdenk5653fc32004-02-08 22:55:38 +0000384 pciauto_prescan_setup_bridge(hose, dev, hose->current_busno);
wdenkcd37d9e2004-02-10 00:03:41 +0000385 /*
wdenk3c74e322004-02-22 23:46:08 +0000386 * need to figure out if this is a subordinate bridge on the bus
wdenk5653fc32004-02-08 22:55:38 +0000387 * to be able to properly set the pri/sec/sub bridge registers.
388 */
389 n = pci_hose_scan_bus(hose, hose->current_busno);
wdenk8bde7f72003-06-27 21:31:46 +0000390
wdenk3c74e322004-02-22 23:46:08 +0000391 /* figure out the deepest we've gone for this leg */
Masahiro Yamadab4141192014-11-07 03:03:31 +0900392 sub_bus = max((unsigned int)n, sub_bus);
wdenkdb2f721f2003-03-06 00:58:30 +0000393 pciauto_postscan_setup_bridge(hose, dev, sub_bus);
wdenk5653fc32004-02-08 22:55:38 +0000394
wdenkdb2f721f2003-03-06 00:58:30 +0000395 sub_bus = hose->current_busno;
Simon Glassff3e0772015-03-05 12:25:25 -0700396#endif
wdenkc6097192002-11-03 00:24:07 +0000397 break;
398
wdenk1cb8e982003-03-06 21:55:29 +0000399 case PCI_CLASS_BRIDGE_CARDBUS:
Andrew Sharpcb2bf932012-08-29 14:16:29 +0000400 /*
401 * just do a minimal setup of the bridge,
402 * let the OS take care of the rest
403 */
Bin Mengd11d9ef2015-07-19 00:20:06 +0800404 pciauto_setup_device(hose, dev, 0, pci_mem,
405 pci_prefetch, pci_io);
wdenk1cb8e982003-03-06 21:55:29 +0000406
Simon Glassda4b1592015-07-31 09:31:33 -0600407 debug("PCI Autoconfig: Found P2CardBus bridge, device %d\n",
408 PCI_DEV(dev));
wdenk1cb8e982003-03-06 21:55:29 +0000409
Simon Glassff3e0772015-03-05 12:25:25 -0700410#ifndef CONFIG_DM_PCI
wdenk1cb8e982003-03-06 21:55:29 +0000411 hose->current_busno++;
Simon Glassff3e0772015-03-05 12:25:25 -0700412#endif
wdenk1cb8e982003-03-06 21:55:29 +0000413 break;
414
TsiChung Liewf33fca22008-03-30 01:19:06 -0500415#if defined(CONFIG_PCIAUTO_SKIP_HOST_BRIDGE)
wdenke0ac62d2003-08-17 18:55:18 +0000416 case PCI_CLASS_BRIDGE_OTHER:
Simon Glassda4b1592015-07-31 09:31:33 -0600417 debug("PCI Autoconfig: Skipping bridge device %d\n",
418 PCI_DEV(dev));
wdenke0ac62d2003-08-17 18:55:18 +0000419 break;
420#endif
Reinhard Arltc2e49f72009-07-25 06:19:12 +0200421#if defined(CONFIG_MPC834x) && !defined(CONFIG_VME8349)
Rafal Jaworowski6902df52005-10-17 02:39:53 +0200422 case PCI_CLASS_BRIDGE_OTHER:
423 /*
424 * The host/PCI bridge 1 seems broken in 8349 - it presents
425 * itself as 'PCI_CLASS_BRIDGE_OTHER' and appears as an _agent_
426 * device claiming resources io/mem/irq.. we only allow for
427 * the PIMMR window to be allocated (BAR0 - 1MB size)
428 */
Simon Glassda4b1592015-07-31 09:31:33 -0600429 debug("PCI Autoconfig: Broken bridge found, only minimal config\n");
Andrew Sharpcb2bf932012-08-29 14:16:29 +0000430 pciauto_setup_device(hose, dev, 0, hose->pci_mem,
431 hose->pci_prefetch, hose->pci_io);
Rafal Jaworowski6902df52005-10-17 02:39:53 +0200432 break;
433#endif
Andrew Sharp69fd2d32012-08-29 14:16:32 +0000434
435 case PCI_CLASS_PROCESSOR_POWERPC: /* an agent or end-point */
Simon Glassda4b1592015-07-31 09:31:33 -0600436 debug("PCI AutoConfig: Found PowerPC device\n");
Andrew Sharp69fd2d32012-08-29 14:16:32 +0000437
wdenkc6097192002-11-03 00:24:07 +0000438 default:
Bin Mengd11d9ef2015-07-19 00:20:06 +0800439 pciauto_setup_device(hose, dev, 6, pci_mem,
440 pci_prefetch, pci_io);
wdenkc6097192002-11-03 00:24:07 +0000441 break;
442 }
wdenkc7de8292002-11-19 11:04:11 +0000443
444 return sub_bus;
wdenkc6097192002-11-03 00:24:07 +0000445}