1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
4 * Copyright (C) 2003, 2004 Paul Mundt
5 * Copyright (C) 2004 Richard Curnow
7 * Support functions for the SH5 PCI hardware.
10 #include <linux/kernel.h>
11 #include <linux/rwsem.h>
12 #include <linux/smp.h>
13 #include <linux/interrupt.h>
14 #include <linux/init.h>
15 #include <linux/errno.h>
16 #include <linux/pci.h>
17 #include <linux/delay.h>
18 #include <linux/types.h>
19 #include <linux/irq.h>
24 unsigned long pcicr_virt
;
25 unsigned long PCI_IO_AREA
;
27 /* Rounds a number UP to the nearest power of two. Used for
28 * sizing the PCI window.
30 static u32 __init
r2p2(u32 num
)
46 /* If the original number isn't a power of 2, round it up */
53 static irqreturn_t
pcish5_err_irq(int irq
, void *dev_id
)
55 struct pt_regs
*regs
= get_irq_regs();
56 unsigned pci_int
, pci_air
, pci_cir
, pci_aint
;
58 pci_int
= SH5PCI_READ(INT
);
59 pci_cir
= SH5PCI_READ(CIR
);
60 pci_air
= SH5PCI_READ(AIR
);
63 printk("PCI INTERRUPT (at %08llx)!\n", regs
->pc
);
64 printk("PCI INT -> 0x%x\n", pci_int
& 0xffff);
65 printk("PCI AIR -> 0x%x\n", pci_air
);
66 printk("PCI CIR -> 0x%x\n", pci_cir
);
67 SH5PCI_WRITE(INT
, ~0);
70 pci_aint
= SH5PCI_READ(AINT
);
72 printk("PCI ARB INTERRUPT!\n");
73 printk("PCI AINT -> 0x%x\n", pci_aint
);
74 printk("PCI AIR -> 0x%x\n", pci_air
);
75 printk("PCI CIR -> 0x%x\n", pci_cir
);
76 SH5PCI_WRITE(AINT
, ~0);
82 static irqreturn_t
pcish5_serr_irq(int irq
, void *dev_id
)
89 static struct resource sh5_pci_resources
[2];
91 static struct pci_channel sh5pci_controller
= {
92 .pci_ops
= &sh5_pci_ops
,
93 .resources
= sh5_pci_resources
,
94 .nr_resources
= ARRAY_SIZE(sh5_pci_resources
),
95 .mem_offset
= 0x00000000,
96 .io_offset
= 0x00000000,
99 static int __init
sh5pci_init(void)
101 unsigned long memStart
= __pa(memory_start
);
102 unsigned long memSize
= __pa(memory_end
) - memStart
;
106 if (request_irq(IRQ_ERR
, pcish5_err_irq
,
107 0, "PCI Error",NULL
) < 0) {
108 printk(KERN_ERR
"PCISH5: Cannot hook PCI_PERR interrupt\n");
112 if (request_irq(IRQ_SERR
, pcish5_serr_irq
,
113 0, "PCI SERR interrupt", NULL
) < 0) {
114 printk(KERN_ERR
"PCISH5: Cannot hook PCI_SERR interrupt\n");
118 pcicr_virt
= (unsigned long)ioremap_nocache(SH5PCI_ICR_BASE
, 1024);
120 panic("Unable to remap PCICR\n");
123 PCI_IO_AREA
= (unsigned long)ioremap_nocache(SH5PCI_IO_BASE
, 0x10000);
125 panic("Unable to remap PCIIO\n");
128 /* Clear snoop registers */
129 SH5PCI_WRITE(CSCR0
, 0);
130 SH5PCI_WRITE(CSCR1
, 0);
132 /* Switch off interrupts */
133 SH5PCI_WRITE(INTM
, 0);
134 SH5PCI_WRITE(AINTM
, 0);
135 SH5PCI_WRITE(PINTM
, 0);
137 /* Set bus active, take it out of reset */
138 uval
= SH5PCI_READ(CR
);
140 /* Set command Register */
141 SH5PCI_WRITE(CR
, uval
| CR_LOCK_MASK
| CR_CFINT
| CR_FTO
| CR_PFE
|
144 uval
=SH5PCI_READ(CR
);
146 /* Allow it to be a master */
147 /* NB - WE DISABLE I/O ACCESS to stop overlap */
148 /* set WAIT bit to enable stepping, an attempt to improve stability */
149 SH5PCI_WRITE_SHORT(CSR_CMD
,
150 PCI_COMMAND_MEMORY
| PCI_COMMAND_MASTER
|
154 ** Set translation mapping memory in order to convert the address
155 ** used for the main bus, to the PCI internal address.
157 SH5PCI_WRITE(MBR
,0x40000000);
159 /* Always set the max size 512M */
160 SH5PCI_WRITE(MBMR
, PCISH5_MEM_SIZCONV(512*1024*1024));
163 ** I/O addresses are mapped at internal PCI specific address
164 ** as is described into the configuration bridge table.
165 ** These are changed to 0, to allow cards that have legacy
166 ** io such as vga to function correctly. We set the SH5 IOBAR to
167 ** 256K, which is a bit big as we can only have 64K of address space
170 SH5PCI_WRITE(IOBR
,0x0);
172 /* Set up a 256K window. Totally pointless waste of address space */
173 SH5PCI_WRITE(IOBMR
,0);
175 /* The SH5 has a HUGE 256K I/O region, which breaks the PCI spec.
176 * Ideally, we would want to map the I/O region somewhere, but it
177 * is so big this is not that easy!
179 SH5PCI_WRITE(CSR_IBAR0
,~0);
180 /* Set memory size value */
181 memSize
= memory_end
- memory_start
;
183 /* Now we set up the mbars so the PCI bus can see the memory of
185 if (memSize
< (1024 * 1024)) {
186 printk(KERN_ERR
"PCISH5: Ridiculous memory size of 0x%lx?\n",
192 lsr0
= (memSize
> (512 * 1024 * 1024)) ? 0x1ff00001 :
193 ((r2p2(memSize
) - 0x100000) | 0x1);
194 SH5PCI_WRITE(LSR0
, lsr0
);
197 SH5PCI_WRITE(CSR_MBAR0
, memory_start
);
198 SH5PCI_WRITE(LAR0
, memory_start
);
200 SH5PCI_WRITE(CSR_MBAR1
,0);
201 SH5PCI_WRITE(LAR1
,0);
202 SH5PCI_WRITE(LSR1
,0);
204 /* Enable the PCI interrupts on the device */
205 SH5PCI_WRITE(INTM
, ~0);
206 SH5PCI_WRITE(AINTM
, ~0);
207 SH5PCI_WRITE(PINTM
, ~0);
209 sh5_pci_resources
[0].start
= PCI_IO_AREA
;
210 sh5_pci_resources
[0].end
= PCI_IO_AREA
+ 0x10000;
212 sh5_pci_resources
[1].start
= memStart
;
213 sh5_pci_resources
[1].end
= memStart
+ memSize
;
215 return register_pci_controller(&sh5pci_controller
);
217 arch_initcall(sh5pci_init
);