1/*
2 * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
3 * Copyright (C) 2003, 2004 Paul Mundt
4 * Copyright (C) 2004 Richard Curnow
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License.  See linux/COPYING for more information.
8 *
9 * Support functions for the SH5 PCI hardware.
10 */
11
12#include <linux/kernel.h>
13#include <linux/rwsem.h>
14#include <linux/smp.h>
15#include <linux/interrupt.h>
16#include <linux/init.h>
17#include <linux/errno.h>
18#include <linux/pci.h>
19#include <linux/delay.h>
20#include <linux/types.h>
21#include <asm/pci.h>
22#include <linux/irq.h>
23
24#include <asm/io.h>
25#include <asm/hardware.h>
26#include "pci_sh5.h"
27
28static unsigned long pcicr_virt;
29unsigned long pciio_virt;
30
31static void __init pci_fixup_ide_bases(struct pci_dev *d)
32{
33	int i;
34
35	/*
36	 * PCI IDE controllers use non-standard I/O port decoding, respect it.
37	 */
38	if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
39		return;
40	printk("PCI: IDE base address fixup for %s\n", pci_name(d));
41	for(i=0; i<4; i++) {
42		struct resource *r = &d->resource[i];
43		if ((r->start & ~0x80) == 0x374) {
44			r->start |= 2;
45			r->end = r->start;
46		}
47	}
48}
49DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
50
51char * __init pcibios_setup(char *str)
52{
53	return str;
54}
55
56/* Rounds a number UP to the nearest power of two. Used for
57 * sizing the PCI window.
58 */
59static u32 __init r2p2(u32 num)
60{
61	int i = 31;
62	u32 tmp = num;
63
64	if (num == 0)
65		return 0;
66
67	do {
68		if (tmp & (1 << 31))
69			break;
70		i--;
71		tmp <<= 1;
72	} while (i >= 0);
73
74	tmp = 1 << i;
75	/* If the original number isn't a power of 2, round it up */
76	if (tmp != num)
77		tmp <<= 1;
78
79	return tmp;
80}
81
82extern unsigned long long memory_start, memory_end;
83
84int __init sh5pci_init(unsigned memStart, unsigned memSize)
85{
86	u32 lsr0;
87	u32 uval;
88
89	pcicr_virt = onchip_remap(SH5PCI_ICR_BASE, 1024, "PCICR");
90	if (!pcicr_virt) {
91		panic("Unable to remap PCICR\n");
92	}
93
94	pciio_virt = onchip_remap(SH5PCI_IO_BASE, 0x10000, "PCIIO");
95	if (!pciio_virt) {
96		panic("Unable to remap PCIIO\n");
97	}
98
99	pr_debug("Register base addres is 0x%08lx\n", pcicr_virt);
100
101	/* Clear snoop registers */
102        SH5PCI_WRITE(CSCR0, 0);
103        SH5PCI_WRITE(CSCR1, 0);
104
105	pr_debug("Wrote to reg\n");
106
107        /* Switch off interrupts */
108        SH5PCI_WRITE(INTM,  0);
109        SH5PCI_WRITE(AINTM, 0);
110        SH5PCI_WRITE(PINTM, 0);
111
112        /* Set bus active, take it out of reset */
113        uval = SH5PCI_READ(CR);
114
115	/* Set command Register */
116        SH5PCI_WRITE(CR, uval | CR_LOCK_MASK | CR_CFINT| CR_FTO | CR_PFE | CR_PFCS | CR_BMAM);
117
118	uval=SH5PCI_READ(CR);
119        pr_debug("CR is actually 0x%08x\n",uval);
120
121        /* Allow it to be a master */
122	/* NB - WE DISABLE I/O ACCESS to stop overlap */
123        /* set WAIT bit to enable stepping, an attempt to improve stability */
124	SH5PCI_WRITE_SHORT(CSR_CMD,
125			    PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_WAIT);
126
127        /*
128        ** Set translation mapping memory in order to convert the address
129        ** used for the main bus, to the PCI internal address.
130        */
131        SH5PCI_WRITE(MBR,0x40000000);
132
133        /* Always set the max size 512M */
134        SH5PCI_WRITE(MBMR, PCISH5_MEM_SIZCONV(512*1024*1024));
135
136        /*
137        ** I/O addresses are mapped at internal PCI specific address
138        ** as is described into the configuration bridge table.
139        ** These are changed to 0, to allow cards that have legacy
140        ** io such as vga to function correctly. We set the SH5 IOBAR to
141        ** 256K, which is a bit big as we can only have 64K of address space
142        */
143
144        SH5PCI_WRITE(IOBR,0x0);
145
146	pr_debug("PCI:Writing 0x%08x to IOBR\n",0);
147
148        /* Set up a 256K window. Totally pointless waste  of address space */
149        SH5PCI_WRITE(IOBMR,0);
150	pr_debug("PCI:Writing 0x%08x to IOBMR\n",0);
151
152	/* The SH5 has a HUGE 256K I/O region, which breaks the PCI spec. Ideally,
153         * we would want to map the I/O region somewhere, but it is so big this is not
154         * that easy!
155         */
156	SH5PCI_WRITE(CSR_IBAR0,~0);
157	/* Set memory size value */
158        memSize = memory_end - memory_start;
159
160        /* Now we set up the mbars so the PCI bus can see the memory of the machine */
161        if (memSize < (1024 * 1024)) {
162                printk(KERN_ERR "PCISH5: Ridiculous memory size of 0x%x?\n", memSize);
163                return -EINVAL;
164        }
165
166        /* Set LSR 0 */
167        lsr0 = (memSize > (512 * 1024 * 1024)) ? 0x1ff00001 : ((r2p2(memSize) - 0x100000) | 0x1);
168        SH5PCI_WRITE(LSR0, lsr0);
169
170	pr_debug("PCI:Writing 0x%08x to LSR0\n",lsr0);
171
172        /* Set MBAR 0 */
173        SH5PCI_WRITE(CSR_MBAR0, memory_start);
174        SH5PCI_WRITE(LAR0, memory_start);
175
176        SH5PCI_WRITE(CSR_MBAR1,0);
177        SH5PCI_WRITE(LAR1,0);
178        SH5PCI_WRITE(LSR1,0);
179
180	pr_debug("PCI:Writing 0x%08llx to CSR_MBAR0\n",memory_start);
181	pr_debug("PCI:Writing 0x%08llx to LAR0\n",memory_start);
182
183        /* Enable the PCI interrupts on the device */
184        SH5PCI_WRITE(INTM,  ~0);
185        SH5PCI_WRITE(AINTM, ~0);
186        SH5PCI_WRITE(PINTM, ~0);
187
188	pr_debug("Switching on all error interrupts\n");
189
190        return(0);
191}
192
193static int sh5pci_read(struct pci_bus *bus, unsigned int devfn, int where,
194			int size, u32 *val)
195{
196	SH5PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where));
197
198	switch (size) {
199		case 1:
200			*val = (u8)SH5PCI_READ_BYTE(PDR + (where & 3));
201			break;
202		case 2:
203			*val = (u16)SH5PCI_READ_SHORT(PDR + (where & 2));
204			break;
205		case 4:
206			*val = SH5PCI_READ(PDR);
207			break;
208	}
209
210	return PCIBIOS_SUCCESSFUL;
211}
212
213static int sh5pci_write(struct pci_bus *bus, unsigned int devfn, int where,
214			 int size, u32 val)
215{
216	SH5PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where));
217
218	switch (size) {
219		case 1:
220			SH5PCI_WRITE_BYTE(PDR + (where & 3), (u8)val);
221			break;
222		case 2:
223			SH5PCI_WRITE_SHORT(PDR + (where & 2), (u16)val);
224			break;
225		case 4:
226			SH5PCI_WRITE(PDR, val);
227			break;
228	}
229
230	return PCIBIOS_SUCCESSFUL;
231}
232
233static struct pci_ops pci_config_ops = {
234	.read =		sh5pci_read,
235	.write =	sh5pci_write,
236};
237
238/* Everything hangs off this */
239static struct pci_bus *pci_root_bus;
240
241
242static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
243{
244	pr_debug("swizzle for dev %d on bus %d slot %d pin is %d\n",
245	         dev->devfn,dev->bus->number, PCI_SLOT(dev->devfn),*pin);
246	return PCI_SLOT(dev->devfn);
247}
248
249static inline u8 bridge_swizzle(u8 pin, u8 slot)
250{
251	return (((pin-1) + slot) % 4) + 1;
252}
253
254u8 __init common_swizzle(struct pci_dev *dev, u8 *pinp)
255{
256	if (dev->bus->number != 0) {
257		u8 pin = *pinp;
258		do {
259			pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
260			/* Move up the chain of bridges. */
261			dev = dev->bus->self;
262		} while (dev->bus->self);
263		*pinp = pin;
264
265		/* The slot is the slot of the last bridge. */
266	}
267
268	return PCI_SLOT(dev->devfn);
269}
270
271/* This needs to be shunted out of here into the board specific bit */
272
273static int __init map_cayman_irq(struct pci_dev *dev, u8 slot, u8 pin)
274{
275	int result = -1;
276
277	/* The complication here is that the PCI IRQ lines from the Cayman's 2
278	   5V slots get into the CPU via a different path from the IRQ lines
279	   from the 3 3.3V slots.  Thus, we have to detect whether the card's
280	   interrupts go via the 5V or 3.3V path, i.e. the 'bridge swizzling'
281	   at the point where we cross from 5V to 3.3V is not the normal case.
282
283	   The added complication is that we don't know that the 5V slots are
284	   always bus 2, because a card containing a PCI-PCI bridge may be
285	   plugged into a 3.3V slot, and this changes the bus numbering.
286
287	   Also, the Cayman has an intermediate PCI bus that goes a custom
288	   expansion board header (and to the secondary bridge).  This bus has
289	   never been used in practice.
290
291	   The 1ary onboard PCI-PCI bridge is device 3 on bus 0
292	   The 2ary onboard PCI-PCI bridge is device 0 on the 2ary bus of the 1ary bridge.
293	   */
294
295	struct slot_pin {
296		int slot;
297		int pin;
298	} path[4];
299	int i=0;
300
301	while (dev->bus->number > 0) {
302
303		slot = path[i].slot = PCI_SLOT(dev->devfn);
304		pin = path[i].pin = bridge_swizzle(pin, slot);
305		dev = dev->bus->self;
306		i++;
307		if (i > 3) panic("PCI path to root bus too long!\n");
308	}
309
310	slot = PCI_SLOT(dev->devfn);
311	/* This is the slot on bus 0 through which the device is eventually
312	   reachable. */
313
314	/* Now work back up. */
315	if ((slot < 3) || (i == 0)) {
316		/* Bus 0 (incl. PCI-PCI bridge itself) : perform the final
317		   swizzle now. */
318		result = IRQ_INTA + bridge_swizzle(pin, slot) - 1;
319	} else {
320		i--;
321		slot = path[i].slot;
322		pin  = path[i].pin;
323		if (slot > 0) {
324			panic("PCI expansion bus device found - not handled!\n");
325		} else {
326			if (i > 0) {
327				/* 5V slots */
328				i--;
329				slot = path[i].slot;
330				pin  = path[i].pin;
331				/* 'pin' was swizzled earlier wrt slot, don't do it again. */
332				result = IRQ_P2INTA + (pin - 1);
333			} else {
334				/* IRQ for 2ary PCI-PCI bridge : unused */
335				result = -1;
336			}
337		}
338	}
339
340	return result;
341}
342
343static irqreturn_t pcish5_err_irq(int irq, void *dev_id)
344{
345	struct pt_regs *regs = get_irq_regs();
346	unsigned pci_int, pci_air, pci_cir, pci_aint;
347
348	pci_int = SH5PCI_READ(INT);
349	pci_cir = SH5PCI_READ(CIR);
350	pci_air = SH5PCI_READ(AIR);
351
352	if (pci_int) {
353		printk("PCI INTERRUPT (at %08llx)!\n", regs->pc);
354		printk("PCI INT -> 0x%x\n", pci_int & 0xffff);
355		printk("PCI AIR -> 0x%x\n", pci_air);
356		printk("PCI CIR -> 0x%x\n", pci_cir);
357		SH5PCI_WRITE(INT, ~0);
358	}
359
360	pci_aint = SH5PCI_READ(AINT);
361	if (pci_aint) {
362		printk("PCI ARB INTERRUPT!\n");
363		printk("PCI AINT -> 0x%x\n", pci_aint);
364		printk("PCI AIR -> 0x%x\n", pci_air);
365		printk("PCI CIR -> 0x%x\n", pci_cir);
366		SH5PCI_WRITE(AINT, ~0);
367	}
368
369	return IRQ_HANDLED;
370}
371
372static irqreturn_t pcish5_serr_irq(int irq, void *dev_id)
373{
374	printk("SERR IRQ\n");
375
376	return IRQ_NONE;
377}
378
379static void __init
380pcibios_size_bridge(struct pci_bus *bus, struct resource *ior,
381		    struct resource *memr)
382{
383	struct resource io_res, mem_res;
384	struct pci_dev *dev;
385	struct pci_dev *bridge = bus->self;
386	struct list_head *ln;
387
388	if (!bridge)
389		return;	/* host bridge, nothing to do */
390
391	/* set reasonable default locations for pcibios_align_resource */
392	io_res.start = PCIBIOS_MIN_IO;
393	mem_res.start = PCIBIOS_MIN_MEM;
394
395	io_res.end = io_res.start;
396	mem_res.end = mem_res.start;
397
398	/* Collect information about how our direct children are layed out. */
399	for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
400		int i;
401		dev = pci_dev_b(ln);
402
403		/* Skip bridges for now */
404		if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
405			continue;
406
407		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
408			struct resource res;
409			unsigned long size;
410
411			memcpy(&res, &dev->resource[i], sizeof(res));
412			size = res.end - res.start + 1;
413
414			if (res.flags & IORESOURCE_IO) {
415				res.start = io_res.end;
416				pcibios_align_resource(dev, &res, size, 0);
417				io_res.end = res.start + size;
418			} else if (res.flags & IORESOURCE_MEM) {
419				res.start = mem_res.end;
420				pcibios_align_resource(dev, &res, size, 0);
421				mem_res.end = res.start + size;
422			}
423		}
424	}
425
426	/* And for all of the subordinate busses. */
427	for (ln=bus->children.next; ln != &bus->children; ln=ln->next)
428		pcibios_size_bridge(pci_bus_b(ln), &io_res, &mem_res);
429
430	/* turn the ending locations into sizes (subtract start) */
431	io_res.end -= io_res.start;
432	mem_res.end -= mem_res.start;
433
434	/* Align the sizes up by bridge rules */
435	io_res.end = ALIGN(io_res.end, 4*1024) - 1;
436	mem_res.end = ALIGN(mem_res.end, 1*1024*1024) - 1;
437
438	/* Adjust the bridge's allocation requirements */
439	bridge->resource[0].end = bridge->resource[0].start + io_res.end;
440	bridge->resource[1].end = bridge->resource[1].start + mem_res.end;
441
442	bridge->resource[PCI_BRIDGE_RESOURCES].end =
443	    bridge->resource[PCI_BRIDGE_RESOURCES].start + io_res.end;
444	bridge->resource[PCI_BRIDGE_RESOURCES+1].end =
445	    bridge->resource[PCI_BRIDGE_RESOURCES+1].start + mem_res.end;
446
447	/* adjust parent's resource requirements */
448	if (ior) {
449		ior->end = ALIGN(ior->end, 4*1024);
450		ior->end += io_res.end;
451	}
452
453	if (memr) {
454		memr->end = ALIGN(memr->end, 1*1024*1024);
455		memr->end += mem_res.end;
456	}
457}
458
459static void __init pcibios_size_bridges(void)
460{
461	struct resource io_res, mem_res;
462
463	memset(&io_res, 0, sizeof(io_res));
464	memset(&mem_res, 0, sizeof(mem_res));
465
466	pcibios_size_bridge(pci_root_bus, &io_res, &mem_res);
467}
468
469static int __init pcibios_init(void)
470{
471        if (request_irq(IRQ_ERR, pcish5_err_irq,
472                        IRQF_DISABLED, "PCI Error",NULL) < 0) {
473                printk(KERN_ERR "PCISH5: Cannot hook PCI_PERR interrupt\n");
474                return -EINVAL;
475        }
476
477        if (request_irq(IRQ_SERR, pcish5_serr_irq,
478                        IRQF_DISABLED, "PCI SERR interrupt", NULL) < 0) {
479                printk(KERN_ERR "PCISH5: Cannot hook PCI_SERR interrupt\n");
480                return -EINVAL;
481        }
482
483	/* The pci subsytem needs to know where memory is and how much
484	 * of it there is. I've simply made these globals. A better mechanism
485	 * is probably needed.
486	 */
487	sh5pci_init(__pa(memory_start),
488		     __pa(memory_end) - __pa(memory_start));
489
490	pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL);
491	pcibios_size_bridges();
492	pci_assign_unassigned_resources();
493	pci_fixup_irqs(no_swizzle, map_cayman_irq);
494
495	return 0;
496}
497
498subsys_initcall(pcibios_init);
499
500void __init pcibios_fixup_bus(struct pci_bus *bus)
501{
502	struct pci_dev *dev = bus->self;
503	int i;
504
505	if(dev) {
506		for(i=0; i<3; i++) {
507			bus->resource[i] =
508				&dev->resource[PCI_BRIDGE_RESOURCES+i];
509			bus->resource[i]->name = bus->name;
510		}
511		bus->resource[0]->flags |= IORESOURCE_IO;
512		bus->resource[1]->flags |= IORESOURCE_MEM;
513
514		/* For now, propagate host limits to the bus;
515		 * we'll adjust them later. */
516
517		bus->resource[0]->end = 64*1024 - 1 ;
518		bus->resource[1]->end = PCIBIOS_MIN_MEM+(256*1024*1024)-1;
519		bus->resource[0]->start = PCIBIOS_MIN_IO;
520		bus->resource[1]->start = PCIBIOS_MIN_MEM;
521		/* Turn off downstream PF memory address range by default */
522		bus->resource[2]->start = 1024*1024;
523		bus->resource[2]->end = bus->resource[2]->start - 1;
524	}
525
526}
527