xref: /openbmc/linux/arch/sh/drivers/pci/pci-sh7780.c (revision ef407beefbd9928792ccc93857e408e0057bc17b)
15283ecb5SPaul Mundt /*
25283ecb5SPaul Mundt  * Low-Level PCI Support for the SH7780
35283ecb5SPaul Mundt  *
4a45635dfSPaul Mundt  *  Copyright (C) 2005 - 2010  Paul Mundt
55283ecb5SPaul Mundt  *
662c7ae87SPaul Mundt  * This file is subject to the terms and conditions of the GNU General Public
762c7ae87SPaul Mundt  * License.  See the file "COPYING" in the main directory of this archive
862c7ae87SPaul Mundt  * for more details.
95283ecb5SPaul Mundt  */
105283ecb5SPaul Mundt #include <linux/types.h>
115283ecb5SPaul Mundt #include <linux/kernel.h>
125283ecb5SPaul Mundt #include <linux/init.h>
135283ecb5SPaul Mundt #include <linux/pci.h>
14*ef407beeSPaul Mundt #include <linux/interrupt.h>
15*ef407beeSPaul Mundt #include <linux/timer.h>
16*ef407beeSPaul Mundt #include <linux/irq.h>
175283ecb5SPaul Mundt #include <linux/errno.h>
185283ecb5SPaul Mundt #include <linux/delay.h>
19aee4467bSPaul Mundt #include <linux/log2.h>
20959f85f8SPaul Mundt #include "pci-sh4.h"
21a45635dfSPaul Mundt #include <asm/mmu.h>
22a45635dfSPaul Mundt #include <asm/sizes.h>
235283ecb5SPaul Mundt 
24e79066a6SPaul Mundt static struct resource sh7785_io_resource = {
25e79066a6SPaul Mundt 	.name	= "SH7785_IO",
26a45635dfSPaul Mundt 	.start	= 0x1000,
27a45635dfSPaul Mundt 	.end	= SH7780_PCI_IO_SIZE - 1,
28e79066a6SPaul Mundt 	.flags	= IORESOURCE_IO
29e79066a6SPaul Mundt };
30e79066a6SPaul Mundt 
31e79066a6SPaul Mundt static struct resource sh7785_mem_resource = {
32e79066a6SPaul Mundt 	.name	= "SH7785_mem",
33e79066a6SPaul Mundt 	.start	= SH7780_PCI_MEMORY_BASE,
34e79066a6SPaul Mundt 	.end	= SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
35e79066a6SPaul Mundt 	.flags	= IORESOURCE_MEM
36e79066a6SPaul Mundt };
37e79066a6SPaul Mundt 
38e79066a6SPaul Mundt static struct pci_channel sh7780_pci_controller = {
39e79066a6SPaul Mundt 	.pci_ops	= &sh4_pci_ops,
40e79066a6SPaul Mundt 	.mem_resource	= &sh7785_mem_resource,
4109cfeb13SPaul Mundt 	.mem_offset	= 0x00000000,
42e79066a6SPaul Mundt 	.io_resource	= &sh7785_io_resource,
4309cfeb13SPaul Mundt 	.io_offset	= 0x00000000,
445582b064SPaul Mundt 	.io_map_base	= SH7780_PCI_IO_BASE,
45*ef407beeSPaul Mundt 	.serr_irq	= evt2irq(0xa00),
46*ef407beeSPaul Mundt 	.err_irq	= evt2irq(0xaa0),
47e79066a6SPaul Mundt };
48e79066a6SPaul Mundt 
49*ef407beeSPaul Mundt struct pci_errors {
50*ef407beeSPaul Mundt 	unsigned int	mask;
51*ef407beeSPaul Mundt 	const char	*str;
52*ef407beeSPaul Mundt } pci_arbiter_errors[] = {
53*ef407beeSPaul Mundt 	{ SH4_PCIAINT_MBKN,	"master broken" },
54*ef407beeSPaul Mundt 	{ SH4_PCIAINT_TBTO,	"target bus time out" },
55*ef407beeSPaul Mundt 	{ SH4_PCIAINT_MBTO,	"master bus time out" },
56*ef407beeSPaul Mundt 	{ SH4_PCIAINT_TABT,	"target abort" },
57*ef407beeSPaul Mundt 	{ SH4_PCIAINT_MABT,	"master abort" },
58*ef407beeSPaul Mundt 	{ SH4_PCIAINT_RDPE,	"read data parity error" },
59*ef407beeSPaul Mundt 	{ SH4_PCIAINT_WDPE,	"write data parity error" },
60*ef407beeSPaul Mundt }, pci_interrupt_errors[] = {
61*ef407beeSPaul Mundt 	{ SH4_PCIINT_MLCK,	"master lock error" },
62*ef407beeSPaul Mundt 	{ SH4_PCIINT_TABT,	"target-target abort" },
63*ef407beeSPaul Mundt 	{ SH4_PCIINT_TRET,	"target retry time out" },
64*ef407beeSPaul Mundt 	{ SH4_PCIINT_MFDE,	"master function disable erorr" },
65*ef407beeSPaul Mundt 	{ SH4_PCIINT_PRTY,	"address parity error" },
66*ef407beeSPaul Mundt 	{ SH4_PCIINT_SERR,	"SERR" },
67*ef407beeSPaul Mundt 	{ SH4_PCIINT_TWDP,	"data parity error for target write" },
68*ef407beeSPaul Mundt 	{ SH4_PCIINT_TRDP,	"PERR detected for target read" },
69*ef407beeSPaul Mundt 	{ SH4_PCIINT_MTABT,	"target abort for master" },
70*ef407beeSPaul Mundt 	{ SH4_PCIINT_MMABT,	"master abort for master" },
71*ef407beeSPaul Mundt 	{ SH4_PCIINT_MWPD,	"master write data parity error" },
72*ef407beeSPaul Mundt 	{ SH4_PCIINT_MRPD,	"master read data parity error" },
73*ef407beeSPaul Mundt };
74*ef407beeSPaul Mundt 
75*ef407beeSPaul Mundt static irqreturn_t sh7780_pci_err_irq(int irq, void *dev_id)
76*ef407beeSPaul Mundt {
77*ef407beeSPaul Mundt 	struct pci_channel *hose = dev_id;
78*ef407beeSPaul Mundt 	unsigned long addr;
79*ef407beeSPaul Mundt 	unsigned int status;
80*ef407beeSPaul Mundt 	unsigned int cmd;
81*ef407beeSPaul Mundt 	int i;
82*ef407beeSPaul Mundt 
83*ef407beeSPaul Mundt 	addr = __raw_readl(hose->reg_base + SH4_PCIALR);
84*ef407beeSPaul Mundt 
85*ef407beeSPaul Mundt 	/*
86*ef407beeSPaul Mundt 	 * Handle status errors.
87*ef407beeSPaul Mundt 	 */
88*ef407beeSPaul Mundt 	status = __raw_readw(hose->reg_base + PCI_STATUS);
89*ef407beeSPaul Mundt 	if (status & (PCI_STATUS_PARITY |
90*ef407beeSPaul Mundt 		      PCI_STATUS_DETECTED_PARITY |
91*ef407beeSPaul Mundt 		      PCI_STATUS_SIG_TARGET_ABORT |
92*ef407beeSPaul Mundt 		      PCI_STATUS_REC_TARGET_ABORT |
93*ef407beeSPaul Mundt 		      PCI_STATUS_REC_MASTER_ABORT)) {
94*ef407beeSPaul Mundt 		cmd = pcibios_handle_status_errors(addr, status, hose);
95*ef407beeSPaul Mundt 		if (likely(cmd))
96*ef407beeSPaul Mundt 			__raw_writew(cmd, hose->reg_base + PCI_STATUS);
97*ef407beeSPaul Mundt 	}
98*ef407beeSPaul Mundt 
99*ef407beeSPaul Mundt 	/*
100*ef407beeSPaul Mundt 	 * Handle arbiter errors.
101*ef407beeSPaul Mundt 	 */
102*ef407beeSPaul Mundt 	status = __raw_readl(hose->reg_base + SH4_PCIAINT);
103*ef407beeSPaul Mundt 	for (i = cmd = 0; i < ARRAY_SIZE(pci_arbiter_errors); i++) {
104*ef407beeSPaul Mundt 		if (status & pci_arbiter_errors[i].mask) {
105*ef407beeSPaul Mundt 			printk(KERN_DEBUG "PCI: %s, addr=%08lx\n",
106*ef407beeSPaul Mundt 			       pci_arbiter_errors[i].str, addr);
107*ef407beeSPaul Mundt 			cmd |= pci_arbiter_errors[i].mask;
108*ef407beeSPaul Mundt 		}
109*ef407beeSPaul Mundt 	}
110*ef407beeSPaul Mundt 	__raw_writel(cmd, hose->reg_base + SH4_PCIAINT);
111*ef407beeSPaul Mundt 
112*ef407beeSPaul Mundt 	/*
113*ef407beeSPaul Mundt 	 * Handle the remaining PCI errors.
114*ef407beeSPaul Mundt 	 */
115*ef407beeSPaul Mundt 	status = __raw_readl(hose->reg_base + SH4_PCIINT);
116*ef407beeSPaul Mundt 	for (i = cmd = 0; i < ARRAY_SIZE(pci_interrupt_errors); i++) {
117*ef407beeSPaul Mundt 		if (status & pci_interrupt_errors[i].mask) {
118*ef407beeSPaul Mundt 			printk(KERN_DEBUG "PCI: %s, addr=%08lx\n",
119*ef407beeSPaul Mundt 			       pci_interrupt_errors[i].str, addr);
120*ef407beeSPaul Mundt 			cmd |= pci_interrupt_errors[i].mask;
121*ef407beeSPaul Mundt 		}
122*ef407beeSPaul Mundt 	}
123*ef407beeSPaul Mundt 	__raw_writel(cmd, hose->reg_base + SH4_PCIINT);
124*ef407beeSPaul Mundt 
125*ef407beeSPaul Mundt 	return IRQ_HANDLED;
126*ef407beeSPaul Mundt }
127*ef407beeSPaul Mundt 
128*ef407beeSPaul Mundt static irqreturn_t sh7780_pci_serr_irq(int irq, void *dev_id)
129*ef407beeSPaul Mundt {
130*ef407beeSPaul Mundt 	struct pci_channel *hose = dev_id;
131*ef407beeSPaul Mundt 
132*ef407beeSPaul Mundt 	printk(KERN_DEBUG "PCI: system error received: ");
133*ef407beeSPaul Mundt 	pcibios_report_status(PCI_STATUS_SIG_SYSTEM_ERROR, 1);
134*ef407beeSPaul Mundt 	printk("\n");
135*ef407beeSPaul Mundt 
136*ef407beeSPaul Mundt 	/* Deassert SERR */
137*ef407beeSPaul Mundt 	__raw_writel(SH4_PCIINTM_SDIM, hose->reg_base + SH4_PCIINTM);
138*ef407beeSPaul Mundt 
139*ef407beeSPaul Mundt 	/* Back off the IRQ for awhile */
140*ef407beeSPaul Mundt 	disable_irq(irq);
141*ef407beeSPaul Mundt 	hose->serr_timer.expires = jiffies + HZ;
142*ef407beeSPaul Mundt 	add_timer(&hose->serr_timer);
143*ef407beeSPaul Mundt 
144*ef407beeSPaul Mundt 	return IRQ_HANDLED;
145*ef407beeSPaul Mundt }
146*ef407beeSPaul Mundt 
147*ef407beeSPaul Mundt static int __init sh7780_pci_setup_irqs(struct pci_channel *hose)
148*ef407beeSPaul Mundt {
149*ef407beeSPaul Mundt 	int ret;
150*ef407beeSPaul Mundt 
151*ef407beeSPaul Mundt 	/* Clear out PCI arbiter IRQs */
152*ef407beeSPaul Mundt 	__raw_writel(0, hose->reg_base + SH4_PCIAINT);
153*ef407beeSPaul Mundt 
154*ef407beeSPaul Mundt 	/* Clear all error conditions */
155*ef407beeSPaul Mundt 	__raw_writew(PCI_STATUS_DETECTED_PARITY  | \
156*ef407beeSPaul Mundt 		     PCI_STATUS_SIG_SYSTEM_ERROR | \
157*ef407beeSPaul Mundt 		     PCI_STATUS_REC_MASTER_ABORT | \
158*ef407beeSPaul Mundt 		     PCI_STATUS_REC_TARGET_ABORT | \
159*ef407beeSPaul Mundt 		     PCI_STATUS_SIG_TARGET_ABORT | \
160*ef407beeSPaul Mundt 		     PCI_STATUS_PARITY, hose->reg_base + PCI_STATUS);
161*ef407beeSPaul Mundt 
162*ef407beeSPaul Mundt 	ret = request_irq(hose->serr_irq, sh7780_pci_serr_irq, IRQF_DISABLED,
163*ef407beeSPaul Mundt 			  "PCI SERR interrupt", hose);
164*ef407beeSPaul Mundt 	if (unlikely(ret)) {
165*ef407beeSPaul Mundt 		printk(KERN_ERR "PCI: Failed hooking SERR IRQ\n");
166*ef407beeSPaul Mundt 		return ret;
167*ef407beeSPaul Mundt 	}
168*ef407beeSPaul Mundt 
169*ef407beeSPaul Mundt 	/*
170*ef407beeSPaul Mundt 	 * The PCI ERR IRQ needs to be IRQF_SHARED since all of the power
171*ef407beeSPaul Mundt 	 * down IRQ vectors are routed through the ERR IRQ vector. We
172*ef407beeSPaul Mundt 	 * only request_irq() once as there is only a single masking
173*ef407beeSPaul Mundt 	 * source for multiple events.
174*ef407beeSPaul Mundt 	 */
175*ef407beeSPaul Mundt 	ret = request_irq(hose->err_irq, sh7780_pci_err_irq, IRQF_SHARED,
176*ef407beeSPaul Mundt 			  "PCI ERR interrupt", hose);
177*ef407beeSPaul Mundt 	if (unlikely(ret)) {
178*ef407beeSPaul Mundt 		free_irq(hose->serr_irq, hose);
179*ef407beeSPaul Mundt 		return ret;
180*ef407beeSPaul Mundt 	}
181*ef407beeSPaul Mundt 
182*ef407beeSPaul Mundt 	/* Unmask all of the arbiter IRQs. */
183*ef407beeSPaul Mundt 	__raw_writel(SH4_PCIAINT_MBKN | SH4_PCIAINT_TBTO | SH4_PCIAINT_MBTO | \
184*ef407beeSPaul Mundt 		     SH4_PCIAINT_TABT | SH4_PCIAINT_MABT | SH4_PCIAINT_RDPE | \
185*ef407beeSPaul Mundt 		     SH4_PCIAINT_WDPE, hose->reg_base + SH4_PCIAINTM);
186*ef407beeSPaul Mundt 
187*ef407beeSPaul Mundt 	/* Unmask all of the PCI IRQs */
188*ef407beeSPaul Mundt 	__raw_writel(SH4_PCIINTM_TTADIM  | SH4_PCIINTM_TMTOIM  | \
189*ef407beeSPaul Mundt 		     SH4_PCIINTM_MDEIM   | SH4_PCIINTM_APEDIM  | \
190*ef407beeSPaul Mundt 		     SH4_PCIINTM_SDIM    | SH4_PCIINTM_DPEITWM | \
191*ef407beeSPaul Mundt 		     SH4_PCIINTM_PEDITRM | SH4_PCIINTM_TADIMM  | \
192*ef407beeSPaul Mundt 		     SH4_PCIINTM_MADIMM  | SH4_PCIINTM_MWPDIM  | \
193*ef407beeSPaul Mundt 		     SH4_PCIINTM_MRDPEIM, hose->reg_base + SH4_PCIINTM);
194*ef407beeSPaul Mundt 
195*ef407beeSPaul Mundt 	return ret;
196*ef407beeSPaul Mundt }
197*ef407beeSPaul Mundt 
198*ef407beeSPaul Mundt static inline void __init sh7780_pci_teardown_irqs(struct pci_channel *hose)
199*ef407beeSPaul Mundt {
200*ef407beeSPaul Mundt 	free_irq(hose->err_irq, hose);
201*ef407beeSPaul Mundt 	free_irq(hose->serr_irq, hose);
202*ef407beeSPaul Mundt }
203*ef407beeSPaul Mundt 
20485b59f5bSPaul Mundt static void __init sh7780_pci66_init(struct pci_channel *hose)
20585b59f5bSPaul Mundt {
20685b59f5bSPaul Mundt 	unsigned int tmp;
20785b59f5bSPaul Mundt 
20885b59f5bSPaul Mundt 	if (!pci_is_66mhz_capable(hose, 0, 0))
20985b59f5bSPaul Mundt 		return;
21085b59f5bSPaul Mundt 
21185b59f5bSPaul Mundt 	/* Enable register access */
21285b59f5bSPaul Mundt 	tmp = __raw_readl(hose->reg_base + SH4_PCICR);
21385b59f5bSPaul Mundt 	tmp |= SH4_PCICR_PREFIX;
21485b59f5bSPaul Mundt 	__raw_writel(tmp, hose->reg_base + SH4_PCICR);
21585b59f5bSPaul Mundt 
21685b59f5bSPaul Mundt 	/* Enable 66MHz operation */
21785b59f5bSPaul Mundt 	tmp = __raw_readw(hose->reg_base + PCI_STATUS);
21885b59f5bSPaul Mundt 	tmp |= PCI_STATUS_66MHZ;
21985b59f5bSPaul Mundt 	__raw_writew(tmp, hose->reg_base + PCI_STATUS);
22085b59f5bSPaul Mundt 
22185b59f5bSPaul Mundt 	/* Done */
22285b59f5bSPaul Mundt 	tmp = __raw_readl(hose->reg_base + SH4_PCICR);
22385b59f5bSPaul Mundt 	tmp |= SH4_PCICR_PREFIX | SH4_PCICR_CFIN;
22485b59f5bSPaul Mundt 	__raw_writel(tmp, hose->reg_base + SH4_PCICR);
22585b59f5bSPaul Mundt }
22685b59f5bSPaul Mundt 
227e79066a6SPaul Mundt static int __init sh7780_pci_init(void)
2285283ecb5SPaul Mundt {
229e79066a6SPaul Mundt 	struct pci_channel *chan = &sh7780_pci_controller;
230a45635dfSPaul Mundt 	phys_addr_t memphys;
231a45635dfSPaul Mundt 	size_t memsize;
232959f85f8SPaul Mundt 	unsigned int id;
233a45635dfSPaul Mundt 	const char *type;
234bcf39352SPaul Mundt 	int ret;
2355283ecb5SPaul Mundt 
2364e7b7fdbSPaul Mundt 	printk(KERN_NOTICE "PCI: Starting intialization.\n");
2375283ecb5SPaul Mundt 
238e4c6a360SMagnus Damm 	chan->reg_base = 0xfe040000;
239e4c6a360SMagnus Damm 
2404e7b7fdbSPaul Mundt 	/* Enable CPU access to the PCIC registers. */
2414e7b7fdbSPaul Mundt 	__raw_writel(PCIECR_ENBL, PCIECR);
242959f85f8SPaul Mundt 
243a45635dfSPaul Mundt 	/* Reset */
244a45635dfSPaul Mundt 	__raw_writel(SH4_PCICR_PREFIX | SH4_PCICR_PRST,
245a45635dfSPaul Mundt 		     chan->reg_base + SH4_PCICR);
246a45635dfSPaul Mundt 
247aee4467bSPaul Mundt 	/*
248aee4467bSPaul Mundt 	 * Wait for it to come back up. The spec says to allow for up to
249aee4467bSPaul Mundt 	 * 1 second after toggling the reset pin, but in practice 100ms
250aee4467bSPaul Mundt 	 * is more than enough.
251aee4467bSPaul Mundt 	 */
252a45635dfSPaul Mundt 	mdelay(100);
253a45635dfSPaul Mundt 
254a45635dfSPaul Mundt 	id = __raw_readw(chan->reg_base + PCI_VENDOR_ID);
255a45635dfSPaul Mundt 	if (id != PCI_VENDOR_ID_RENESAS) {
2564e7b7fdbSPaul Mundt 		printk(KERN_ERR "PCI: Unknown vendor ID 0x%04x.\n", id);
257959f85f8SPaul Mundt 		return -ENODEV;
258959f85f8SPaul Mundt 	}
259959f85f8SPaul Mundt 
260a45635dfSPaul Mundt 	id = __raw_readw(chan->reg_base + PCI_DEVICE_ID);
261a45635dfSPaul Mundt 	type = (id == PCI_DEVICE_ID_RENESAS_SH7763) ? "SH7763" :
262a45635dfSPaul Mundt 	       (id == PCI_DEVICE_ID_RENESAS_SH7780) ? "SH7780" :
263a45635dfSPaul Mundt 	       (id == PCI_DEVICE_ID_RENESAS_SH7781) ? "SH7781" :
264a45635dfSPaul Mundt 	       (id == PCI_DEVICE_ID_RENESAS_SH7785) ? "SH7785" :
2654e7b7fdbSPaul Mundt 					  NULL;
2664e7b7fdbSPaul Mundt 	if (unlikely(!type)) {
2674e7b7fdbSPaul Mundt 		printk(KERN_ERR "PCI: Found an unsupported Renesas host "
2684e7b7fdbSPaul Mundt 		       "controller, device id 0x%04x.\n", id);
2694e7b7fdbSPaul Mundt 		return -EINVAL;
2704e7b7fdbSPaul Mundt 	}
2714e7b7fdbSPaul Mundt 
2724e7b7fdbSPaul Mundt 	printk(KERN_NOTICE "PCI: Found a Renesas %s host "
2734e7b7fdbSPaul Mundt 	       "controller, revision %d.\n", type,
274a45635dfSPaul Mundt 	       __raw_readb(chan->reg_base + PCI_REVISION_ID));
2754e7b7fdbSPaul Mundt 
276c66c1d79SPaul Mundt 	/*
277a45635dfSPaul Mundt 	 * Now throw it in to register initialization mode and
278a45635dfSPaul Mundt 	 * start the real work.
279c66c1d79SPaul Mundt 	 */
280a45635dfSPaul Mundt 	__raw_writel(SH4_PCICR_PREFIX, chan->reg_base + SH4_PCICR);
281a45635dfSPaul Mundt 
282a45635dfSPaul Mundt 	__raw_writel(0, chan->reg_base + PCI_BASE_ADDRESS_0);
2835283ecb5SPaul Mundt 
284aee4467bSPaul Mundt 	memphys = __pa(memory_start);
285aee4467bSPaul Mundt 	memsize = roundup_pow_of_two(memory_end - memory_start);
286aee4467bSPaul Mundt 
287aee4467bSPaul Mundt 	/*
288aee4467bSPaul Mundt 	 * If there's more than 512MB of memory, we need to roll over to
289aee4467bSPaul Mundt 	 * LAR1/LSR1.
290aee4467bSPaul Mundt 	 */
291aee4467bSPaul Mundt 	if (memsize > SZ_512M) {
292aee4467bSPaul Mundt 		__raw_writel(memphys + SZ_512M, chan->reg_base + SH4_PCILAR1);
293aee4467bSPaul Mundt 		__raw_writel((((memsize - SZ_512M) - SZ_1M) & 0x1ff00000) | 1,
294aee4467bSPaul Mundt 			     chan->reg_base + SH4_PCILSR1);
295aee4467bSPaul Mundt 		memsize = SZ_512M;
296aee4467bSPaul Mundt 	} else {
297aee4467bSPaul Mundt 		/*
298aee4467bSPaul Mundt 		 * Otherwise just zero it out and disable it.
299aee4467bSPaul Mundt 		 */
300aee4467bSPaul Mundt 		__raw_writel(0, chan->reg_base + SH4_PCILAR1);
301aee4467bSPaul Mundt 		__raw_writel(0, chan->reg_base + SH4_PCILSR1);
302aee4467bSPaul Mundt 	}
303aee4467bSPaul Mundt 
304aee4467bSPaul Mundt 	/*
305aee4467bSPaul Mundt 	 * LAR0/LSR0 covers up to the first 512MB, which is enough to
306aee4467bSPaul Mundt 	 * cover all of lowmem on most platforms.
307aee4467bSPaul Mundt 	 */
308a45635dfSPaul Mundt 	__raw_writel(memphys, chan->reg_base + SH4_PCILAR0);
309aee4467bSPaul Mundt 	__raw_writel(((memsize - SZ_1M) & 0x1ff00000) | 1,
310a45635dfSPaul Mundt 		     chan->reg_base + SH4_PCILSR0);
31162c7ae87SPaul Mundt 
312*ef407beeSPaul Mundt 	/*
313*ef407beeSPaul Mundt 	 * Hook up the ERR and SERR IRQs.
314*ef407beeSPaul Mundt 	 */
315*ef407beeSPaul Mundt 	ret = sh7780_pci_setup_irqs(chan);
316*ef407beeSPaul Mundt 	if (unlikely(ret))
317*ef407beeSPaul Mundt 		return ret;
31862c7ae87SPaul Mundt 
319a45635dfSPaul Mundt 	/*
320a45635dfSPaul Mundt 	 * Disable the cache snoop controller for non-coherent DMA.
321a45635dfSPaul Mundt 	 */
322a45635dfSPaul Mundt 	__raw_writel(0, chan->reg_base + SH7780_PCICSCR0);
323a45635dfSPaul Mundt 	__raw_writel(0, chan->reg_base + SH7780_PCICSAR0);
324a45635dfSPaul Mundt 	__raw_writel(0, chan->reg_base + SH7780_PCICSCR1);
325a45635dfSPaul Mundt 	__raw_writel(0, chan->reg_base + SH7780_PCICSAR1);
32662c7ae87SPaul Mundt 
327a45635dfSPaul Mundt 	__raw_writel(0xfd000000, chan->reg_base + SH7780_PCIMBR0);
328a45635dfSPaul Mundt 	__raw_writel(0x00fc0000, chan->reg_base + SH7780_PCIMBMR0);
329a45635dfSPaul Mundt 
330a45635dfSPaul Mundt 	__raw_writel(0, chan->reg_base + SH7780_PCIIOBR);
331a45635dfSPaul Mundt 	__raw_writel(0, chan->reg_base + SH7780_PCIIOBMR);
332a45635dfSPaul Mundt 
333*ef407beeSPaul Mundt 	__raw_writew(PCI_COMMAND_SERR   | PCI_COMMAND_WAIT   | \
334*ef407beeSPaul Mundt 		     PCI_COMMAND_PARITY | PCI_COMMAND_MASTER | \
335*ef407beeSPaul Mundt 		     PCI_COMMAND_MEMORY, chan->reg_base + PCI_COMMAND);
336*ef407beeSPaul Mundt 
337a45635dfSPaul Mundt 	/*
338a45635dfSPaul Mundt 	 * Initialization mode complete, release the control register and
339a45635dfSPaul Mundt 	 * enable round robin mode to stop device overruns/starvation.
340a45635dfSPaul Mundt 	 */
341a45635dfSPaul Mundt 	__raw_writel(SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO,
342a45635dfSPaul Mundt 		     chan->reg_base + SH4_PCICR);
3435283ecb5SPaul Mundt 
344bcf39352SPaul Mundt 	ret = register_pci_controller(chan);
345bcf39352SPaul Mundt 	if (unlikely(ret))
346*ef407beeSPaul Mundt 		goto err;
347e79066a6SPaul Mundt 
34885b59f5bSPaul Mundt 	sh7780_pci66_init(chan);
34985b59f5bSPaul Mundt 
35085b59f5bSPaul Mundt 	printk(KERN_NOTICE "PCI: Running at %dMHz.\n",
35185b59f5bSPaul Mundt 	       (__raw_readw(chan->reg_base + PCI_STATUS) & PCI_STATUS_66MHZ) ?
35285b59f5bSPaul Mundt 	       66 : 33);
35385b59f5bSPaul Mundt 
354d0e3db40SMagnus Damm 	return 0;
355*ef407beeSPaul Mundt 
356*ef407beeSPaul Mundt err:
357*ef407beeSPaul Mundt 	sh7780_pci_teardown_irqs(chan);
358*ef407beeSPaul Mundt 	return ret;
3595283ecb5SPaul Mundt }
360e79066a6SPaul Mundt arch_initcall(sh7780_pci_init);
361