xref: /OK3568_Linux_fs/kernel/arch/arm/mach-footbridge/dc21285.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  linux/arch/arm/kernel/dec21285.c: PCI functions for DC21285
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *  Copyright (C) 1998-2001 Russell King
6*4882a593Smuzhiyun  *  Copyright (C) 1998-2000 Phil Blundell
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun #include <linux/kernel.h>
9*4882a593Smuzhiyun #include <linux/pci.h>
10*4882a593Smuzhiyun #include <linux/interrupt.h>
11*4882a593Smuzhiyun #include <linux/mm.h>
12*4882a593Smuzhiyun #include <linux/slab.h>
13*4882a593Smuzhiyun #include <linux/init.h>
14*4882a593Smuzhiyun #include <linux/ioport.h>
15*4882a593Smuzhiyun #include <linux/irq.h>
16*4882a593Smuzhiyun #include <linux/io.h>
17*4882a593Smuzhiyun #include <linux/spinlock.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #include <asm/irq.h>
20*4882a593Smuzhiyun #include <asm/mach/pci.h>
21*4882a593Smuzhiyun #include <asm/hardware/dec21285.h>
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #define MAX_SLOTS		21
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define PCICMD_ABORT		((PCI_STATUS_REC_MASTER_ABORT| \
26*4882a593Smuzhiyun 				  PCI_STATUS_REC_TARGET_ABORT)<<16)
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #define PCICMD_ERROR_BITS	((PCI_STATUS_DETECTED_PARITY | \
29*4882a593Smuzhiyun 				  PCI_STATUS_REC_MASTER_ABORT | \
30*4882a593Smuzhiyun 				  PCI_STATUS_REC_TARGET_ABORT | \
31*4882a593Smuzhiyun 				  PCI_STATUS_PARITY) << 16)
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun extern int setup_arm_irq(int, struct irqaction *);
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun static unsigned long
dc21285_base_address(struct pci_bus * bus,unsigned int devfn)36*4882a593Smuzhiyun dc21285_base_address(struct pci_bus *bus, unsigned int devfn)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	unsigned long addr = 0;
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 	if (bus->number == 0) {
41*4882a593Smuzhiyun 		if (PCI_SLOT(devfn) == 0)
42*4882a593Smuzhiyun 			/*
43*4882a593Smuzhiyun 			 * For devfn 0, point at the 21285
44*4882a593Smuzhiyun 			 */
45*4882a593Smuzhiyun 			addr = ARMCSR_BASE;
46*4882a593Smuzhiyun 		else {
47*4882a593Smuzhiyun 			devfn -= 1 << 3;
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 			if (devfn < PCI_DEVFN(MAX_SLOTS, 0))
50*4882a593Smuzhiyun 				addr = PCICFG0_BASE | 0xc00000 | (devfn << 8);
51*4882a593Smuzhiyun 		}
52*4882a593Smuzhiyun 	} else
53*4882a593Smuzhiyun 		addr = PCICFG1_BASE | (bus->number << 16) | (devfn << 8);
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	return addr;
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun static int
dc21285_read_config(struct pci_bus * bus,unsigned int devfn,int where,int size,u32 * value)59*4882a593Smuzhiyun dc21285_read_config(struct pci_bus *bus, unsigned int devfn, int where,
60*4882a593Smuzhiyun 		    int size, u32 *value)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun 	unsigned long addr = dc21285_base_address(bus, devfn);
63*4882a593Smuzhiyun 	u32 v = 0xffffffff;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	if (addr)
66*4882a593Smuzhiyun 		switch (size) {
67*4882a593Smuzhiyun 		case 1:
68*4882a593Smuzhiyun 			asm volatile("ldrb	%0, [%1, %2]"
69*4882a593Smuzhiyun 				: "=r" (v) : "r" (addr), "r" (where) : "cc");
70*4882a593Smuzhiyun 			break;
71*4882a593Smuzhiyun 		case 2:
72*4882a593Smuzhiyun 			asm volatile("ldrh	%0, [%1, %2]"
73*4882a593Smuzhiyun 				: "=r" (v) : "r" (addr), "r" (where) : "cc");
74*4882a593Smuzhiyun 			break;
75*4882a593Smuzhiyun 		case 4:
76*4882a593Smuzhiyun 			asm volatile("ldr	%0, [%1, %2]"
77*4882a593Smuzhiyun 				: "=r" (v) : "r" (addr), "r" (where) : "cc");
78*4882a593Smuzhiyun 			break;
79*4882a593Smuzhiyun 		}
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	*value = v;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	v = *CSR_PCICMD;
84*4882a593Smuzhiyun 	if (v & PCICMD_ABORT) {
85*4882a593Smuzhiyun 		*CSR_PCICMD = v & (0xffff|PCICMD_ABORT);
86*4882a593Smuzhiyun 		return -1;
87*4882a593Smuzhiyun 	}
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	return PCIBIOS_SUCCESSFUL;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun static int
dc21285_write_config(struct pci_bus * bus,unsigned int devfn,int where,int size,u32 value)93*4882a593Smuzhiyun dc21285_write_config(struct pci_bus *bus, unsigned int devfn, int where,
94*4882a593Smuzhiyun 		     int size, u32 value)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	unsigned long addr = dc21285_base_address(bus, devfn);
97*4882a593Smuzhiyun 	u32 v;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	if (addr)
100*4882a593Smuzhiyun 		switch (size) {
101*4882a593Smuzhiyun 		case 1:
102*4882a593Smuzhiyun 			asm volatile("strb	%0, [%1, %2]"
103*4882a593Smuzhiyun 				: : "r" (value), "r" (addr), "r" (where)
104*4882a593Smuzhiyun 				: "cc");
105*4882a593Smuzhiyun 			break;
106*4882a593Smuzhiyun 		case 2:
107*4882a593Smuzhiyun 			asm volatile("strh	%0, [%1, %2]"
108*4882a593Smuzhiyun 				: : "r" (value), "r" (addr), "r" (where)
109*4882a593Smuzhiyun 				: "cc");
110*4882a593Smuzhiyun 			break;
111*4882a593Smuzhiyun 		case 4:
112*4882a593Smuzhiyun 			asm volatile("str	%0, [%1, %2]"
113*4882a593Smuzhiyun 				: : "r" (value), "r" (addr), "r" (where)
114*4882a593Smuzhiyun 				: "cc");
115*4882a593Smuzhiyun 			break;
116*4882a593Smuzhiyun 		}
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	v = *CSR_PCICMD;
119*4882a593Smuzhiyun 	if (v & PCICMD_ABORT) {
120*4882a593Smuzhiyun 		*CSR_PCICMD = v & (0xffff|PCICMD_ABORT);
121*4882a593Smuzhiyun 		return -1;
122*4882a593Smuzhiyun 	}
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	return PCIBIOS_SUCCESSFUL;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun struct pci_ops dc21285_ops = {
128*4882a593Smuzhiyun 	.read	= dc21285_read_config,
129*4882a593Smuzhiyun 	.write	= dc21285_write_config,
130*4882a593Smuzhiyun };
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun static struct timer_list serr_timer;
133*4882a593Smuzhiyun static struct timer_list perr_timer;
134*4882a593Smuzhiyun 
dc21285_enable_error(struct timer_list * timer)135*4882a593Smuzhiyun static void dc21285_enable_error(struct timer_list *timer)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	del_timer(timer);
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	if (timer == &serr_timer)
140*4882a593Smuzhiyun 		enable_irq(IRQ_PCI_SERR);
141*4882a593Smuzhiyun 	else if (timer == &perr_timer)
142*4882a593Smuzhiyun 		enable_irq(IRQ_PCI_PERR);
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun /*
146*4882a593Smuzhiyun  * Warn on PCI errors.
147*4882a593Smuzhiyun  */
dc21285_abort_irq(int irq,void * dev_id)148*4882a593Smuzhiyun static irqreturn_t dc21285_abort_irq(int irq, void *dev_id)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun 	unsigned int cmd;
151*4882a593Smuzhiyun 	unsigned int status;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	cmd = *CSR_PCICMD;
154*4882a593Smuzhiyun 	status = cmd >> 16;
155*4882a593Smuzhiyun 	cmd = cmd & 0xffff;
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	if (status & PCI_STATUS_REC_MASTER_ABORT) {
158*4882a593Smuzhiyun 		printk(KERN_DEBUG "PCI: master abort, pc=0x%08lx\n",
159*4882a593Smuzhiyun 			instruction_pointer(get_irq_regs()));
160*4882a593Smuzhiyun 		cmd |= PCI_STATUS_REC_MASTER_ABORT << 16;
161*4882a593Smuzhiyun 	}
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	if (status & PCI_STATUS_REC_TARGET_ABORT) {
164*4882a593Smuzhiyun 		printk(KERN_DEBUG "PCI: target abort: ");
165*4882a593Smuzhiyun 		pcibios_report_status(PCI_STATUS_REC_MASTER_ABORT |
166*4882a593Smuzhiyun 				      PCI_STATUS_SIG_TARGET_ABORT |
167*4882a593Smuzhiyun 				      PCI_STATUS_REC_TARGET_ABORT, 1);
168*4882a593Smuzhiyun 		printk("\n");
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 		cmd |= PCI_STATUS_REC_TARGET_ABORT << 16;
171*4882a593Smuzhiyun 	}
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	*CSR_PCICMD = cmd;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	return IRQ_HANDLED;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun 
dc21285_serr_irq(int irq,void * dev_id)178*4882a593Smuzhiyun static irqreturn_t dc21285_serr_irq(int irq, void *dev_id)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun 	struct timer_list *timer = dev_id;
181*4882a593Smuzhiyun 	unsigned int cntl;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	printk(KERN_DEBUG "PCI: system error received: ");
184*4882a593Smuzhiyun 	pcibios_report_status(PCI_STATUS_SIG_SYSTEM_ERROR, 1);
185*4882a593Smuzhiyun 	printk("\n");
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	cntl = *CSR_SA110_CNTL & 0xffffdf07;
188*4882a593Smuzhiyun 	*CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR;
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	/*
191*4882a593Smuzhiyun 	 * back off this interrupt
192*4882a593Smuzhiyun 	 */
193*4882a593Smuzhiyun 	disable_irq(irq);
194*4882a593Smuzhiyun 	timer->expires = jiffies + HZ;
195*4882a593Smuzhiyun 	add_timer(timer);
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	return IRQ_HANDLED;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun 
dc21285_discard_irq(int irq,void * dev_id)200*4882a593Smuzhiyun static irqreturn_t dc21285_discard_irq(int irq, void *dev_id)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	printk(KERN_DEBUG "PCI: discard timer expired\n");
203*4882a593Smuzhiyun 	*CSR_SA110_CNTL &= 0xffffde07;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	return IRQ_HANDLED;
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun 
dc21285_dparity_irq(int irq,void * dev_id)208*4882a593Smuzhiyun static irqreturn_t dc21285_dparity_irq(int irq, void *dev_id)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun 	unsigned int cmd;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	printk(KERN_DEBUG "PCI: data parity error detected: ");
213*4882a593Smuzhiyun 	pcibios_report_status(PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY, 1);
214*4882a593Smuzhiyun 	printk("\n");
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	cmd = *CSR_PCICMD & 0xffff;
217*4882a593Smuzhiyun 	*CSR_PCICMD = cmd | 1 << 24;
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	return IRQ_HANDLED;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun 
dc21285_parity_irq(int irq,void * dev_id)222*4882a593Smuzhiyun static irqreturn_t dc21285_parity_irq(int irq, void *dev_id)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun 	struct timer_list *timer = dev_id;
225*4882a593Smuzhiyun 	unsigned int cmd;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	printk(KERN_DEBUG "PCI: parity error detected: ");
228*4882a593Smuzhiyun 	pcibios_report_status(PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY, 1);
229*4882a593Smuzhiyun 	printk("\n");
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	cmd = *CSR_PCICMD & 0xffff;
232*4882a593Smuzhiyun 	*CSR_PCICMD = cmd | 1 << 31;
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	/*
235*4882a593Smuzhiyun 	 * back off this interrupt
236*4882a593Smuzhiyun 	 */
237*4882a593Smuzhiyun 	disable_irq(irq);
238*4882a593Smuzhiyun 	timer->expires = jiffies + HZ;
239*4882a593Smuzhiyun 	add_timer(timer);
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	return IRQ_HANDLED;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun 
dc21285_setup(int nr,struct pci_sys_data * sys)244*4882a593Smuzhiyun int __init dc21285_setup(int nr, struct pci_sys_data *sys)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun 	struct resource *res;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	if (nr || !footbridge_cfn_mode())
249*4882a593Smuzhiyun 		return 0;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	res = kcalloc(2, sizeof(struct resource), GFP_KERNEL);
252*4882a593Smuzhiyun 	if (!res) {
253*4882a593Smuzhiyun 		printk("out of memory for root bus resources");
254*4882a593Smuzhiyun 		return 0;
255*4882a593Smuzhiyun 	}
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	res[0].flags = IORESOURCE_MEM;
258*4882a593Smuzhiyun 	res[0].name  = "Footbridge non-prefetch";
259*4882a593Smuzhiyun 	res[1].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
260*4882a593Smuzhiyun 	res[1].name  = "Footbridge prefetch";
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	allocate_resource(&iomem_resource, &res[1], 0x20000000,
263*4882a593Smuzhiyun 			  0xa0000000, 0xffffffff, 0x20000000, NULL, NULL);
264*4882a593Smuzhiyun 	allocate_resource(&iomem_resource, &res[0], 0x40000000,
265*4882a593Smuzhiyun 			  0x80000000, 0xffffffff, 0x40000000, NULL, NULL);
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	sys->mem_offset  = DC21285_PCI_MEM;
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	pci_add_resource_offset(&sys->resources, &res[0], sys->mem_offset);
270*4882a593Smuzhiyun 	pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	return 1;
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun #define dc21285_request_irq(_a, _b, _c, _d, _e) \
276*4882a593Smuzhiyun 	WARN_ON(request_irq(_a, _b, _c, _d, _e) < 0)
277*4882a593Smuzhiyun 
dc21285_preinit(void)278*4882a593Smuzhiyun void __init dc21285_preinit(void)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun 	unsigned int mem_size, mem_mask;
281*4882a593Smuzhiyun 	int cfn_mode;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	pcibios_min_mem = 0x81000000;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	mem_size = (unsigned int)high_memory - PAGE_OFFSET;
286*4882a593Smuzhiyun 	for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1)
287*4882a593Smuzhiyun 		if (mem_mask >= mem_size)
288*4882a593Smuzhiyun 			break;
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 	/*
291*4882a593Smuzhiyun 	 * These registers need to be set up whether we're the
292*4882a593Smuzhiyun 	 * central function or not.
293*4882a593Smuzhiyun 	 */
294*4882a593Smuzhiyun 	*CSR_SDRAMBASEMASK    = (mem_mask - 1) & 0x0ffc0000;
295*4882a593Smuzhiyun 	*CSR_SDRAMBASEOFFSET  = 0;
296*4882a593Smuzhiyun 	*CSR_ROMBASEMASK      = 0x80000000;
297*4882a593Smuzhiyun 	*CSR_CSRBASEMASK      = 0;
298*4882a593Smuzhiyun 	*CSR_CSRBASEOFFSET    = 0;
299*4882a593Smuzhiyun 	*CSR_PCIADDR_EXTN     = 0;
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 	cfn_mode = __footbridge_cfn_mode();
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 	printk(KERN_INFO "PCI: DC21285 footbridge, revision %02lX, in "
304*4882a593Smuzhiyun 		"%s mode\n", *CSR_CLASSREV & 0xff, cfn_mode ?
305*4882a593Smuzhiyun 		"central function" : "addin");
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	if (footbridge_cfn_mode()) {
308*4882a593Smuzhiyun 		/*
309*4882a593Smuzhiyun 		 * Clear any existing errors - we aren't
310*4882a593Smuzhiyun 		 * interested in historical data...
311*4882a593Smuzhiyun 		 */
312*4882a593Smuzhiyun 		*CSR_SA110_CNTL	= (*CSR_SA110_CNTL & 0xffffde07) |
313*4882a593Smuzhiyun 				  SA110_CNTL_RXSERR;
314*4882a593Smuzhiyun 		*CSR_PCICMD = (*CSR_PCICMD & 0xffff) | PCICMD_ERROR_BITS;
315*4882a593Smuzhiyun 	}
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	timer_setup(&serr_timer, dc21285_enable_error, 0);
318*4882a593Smuzhiyun 	timer_setup(&perr_timer, dc21285_enable_error, 0);
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	/*
321*4882a593Smuzhiyun 	 * We don't care if these fail.
322*4882a593Smuzhiyun 	 */
323*4882a593Smuzhiyun 	dc21285_request_irq(IRQ_PCI_SERR, dc21285_serr_irq, 0,
324*4882a593Smuzhiyun 			    "PCI system error", &serr_timer);
325*4882a593Smuzhiyun 	dc21285_request_irq(IRQ_PCI_PERR, dc21285_parity_irq, 0,
326*4882a593Smuzhiyun 			    "PCI parity error", &perr_timer);
327*4882a593Smuzhiyun 	dc21285_request_irq(IRQ_PCI_ABORT, dc21285_abort_irq, 0,
328*4882a593Smuzhiyun 			    "PCI abort", NULL);
329*4882a593Smuzhiyun 	dc21285_request_irq(IRQ_DISCARD_TIMER, dc21285_discard_irq, 0,
330*4882a593Smuzhiyun 			    "Discard timer", NULL);
331*4882a593Smuzhiyun 	dc21285_request_irq(IRQ_PCI_DPERR, dc21285_dparity_irq, 0,
332*4882a593Smuzhiyun 			    "PCI data parity", NULL);
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	if (cfn_mode) {
335*4882a593Smuzhiyun 		/*
336*4882a593Smuzhiyun 		 * Map our SDRAM at a known address in PCI space, just in case
337*4882a593Smuzhiyun 		 * the firmware had other ideas.  Using a nonzero base is
338*4882a593Smuzhiyun 		 * necessary, since some VGA cards forcefully use PCI addresses
339*4882a593Smuzhiyun 		 * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards).
340*4882a593Smuzhiyun 		 */
341*4882a593Smuzhiyun 		*CSR_PCICSRBASE       = 0xf4000000;
342*4882a593Smuzhiyun 		*CSR_PCICSRIOBASE     = 0;
343*4882a593Smuzhiyun 		*CSR_PCISDRAMBASE     = __virt_to_bus(PAGE_OFFSET);
344*4882a593Smuzhiyun 		*CSR_PCIROMBASE       = 0;
345*4882a593Smuzhiyun 		*CSR_PCICMD = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
346*4882a593Smuzhiyun 			      PCI_COMMAND_INVALIDATE | PCICMD_ERROR_BITS;
347*4882a593Smuzhiyun 	} else if (footbridge_cfn_mode() != 0) {
348*4882a593Smuzhiyun 		/*
349*4882a593Smuzhiyun 		 * If we are not compiled to accept "add-in" mode, then
350*4882a593Smuzhiyun 		 * we are using a constant virt_to_bus translation which
351*4882a593Smuzhiyun 		 * can not hope to cater for the way the host BIOS  has
352*4882a593Smuzhiyun 		 * set up the machine.
353*4882a593Smuzhiyun 		 */
354*4882a593Smuzhiyun 		panic("PCI: this kernel is compiled for central "
355*4882a593Smuzhiyun 			"function mode only");
356*4882a593Smuzhiyun 	}
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun 
dc21285_postinit(void)359*4882a593Smuzhiyun void __init dc21285_postinit(void)
360*4882a593Smuzhiyun {
361*4882a593Smuzhiyun 	register_isa_ports(DC21285_PCI_MEM, DC21285_PCI_IO, 0);
362*4882a593Smuzhiyun }
363