pci-dc.c 4.2 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
/*
Linus Torvalds's avatar
Linus Torvalds committed
2
 $	$Id: pci-dc.c,v 1.5 2001/08/24 12:38:19 dwmw2 Exp $
Linus Torvalds's avatar
Linus Torvalds committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
 *	Dreamcast PCI: Supports SEGA Broadband Adaptor only.
 */

#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/pci.h>

#include <asm/io.h>
#include <asm/irq.h>
#include <asm/dc_sysasic.h>

#define	GAPSPCI_REGS		0x01001400
#define GAPSPCI_DMA_BASE	0x01840000
#define GAPSPCI_DMA_SIZE	32768
#define GAPSPCI_BBA_CONFIG	0x01001600

#define	GAPSPCI_IRQ		HW_EVENT_EXTERNAL

static int gapspci_dma_used;

static struct pci_bus *pci_root_bus;

struct pci_fixup pcibios_fixups[] = {
	{0, 0, 0, NULL}
};

34
#define BBA_SELECTED(bus,devfn) (bus->number==0 && devfn==0)
Linus Torvalds's avatar
Linus Torvalds committed
35

36
static int gapspci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val)
Linus Torvalds's avatar
Linus Torvalds committed
37
{
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
	switch (size) {
	case 1:
		if (BBA_SELECTED(bus, devfn))
			*val = (u8)inb(GAPSPCI_BBA_CONFIG+where);
		else
			*val = (u8)0xff;
		break;
	case 2:
		if (BBA_SELECTED(bus, devfn))
			*val = (u16)inw(GAPSPCI_BBA_CONFIG+where);
		else
			*val = (u16)0xffff;
		break;
	case 4:
		if (BBA_SELECTED(bus, devfn))
			*val = inl(GAPSPCI_BBA_CONFIG+where);
		else
			*val = 0xffffffff;
		break;
	}	
Linus Torvalds's avatar
Linus Torvalds committed
58 59 60
	return PCIBIOS_SUCCESSFUL;
}

61
static int gapspci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
Linus Torvalds's avatar
Linus Torvalds committed
62
{
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
	if (BBA_SELECTED(bus, devfn)) {
		switch (size) {
		case 1:
			if (BBA_SELECTED(bus, devfn))
				outb((u8)val, GAPSPCI_BBA_CONFIG+where);
			break;
		case 2:
			if (BBA_SELECTED(bus, devfn))
				outw((u16)val, GAPSPCI_BBA_CONFIG+where);
			break;
		case 4:
			if (BBA_SELECTED(bus, devfn))
				outl(val, GAPSPCI_BBA_CONFIG+where);
			break;
		}
	}
	return PCIBIOS_SUCCESSFUL;
Linus Torvalds's avatar
Linus Torvalds committed
80 81 82
}

static struct pci_ops pci_config_ops = {
83 84
	.read = 	gapspci_read,
	.write = 	gapspci_write,
Linus Torvalds's avatar
Linus Torvalds committed
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
};


void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
			   dma_addr_t * dma_handle)
{
	unsigned long buf;

	if (gapspci_dma_used+size > GAPSPCI_DMA_SIZE)
		return NULL;

	buf = GAPSPCI_DMA_BASE+gapspci_dma_used;

	gapspci_dma_used = PAGE_ALIGN(gapspci_dma_used+size);
	
Linus Torvalds's avatar
Linus Torvalds committed
100
	printk("pci_alloc_consistent: %ld bytes at 0x%lx\n", (long)size, buf);
Linus Torvalds's avatar
Linus Torvalds committed
101 102 103 104 105 106 107 108 109 110 111

	*dma_handle = (dma_addr_t)buf;

	return (void *)P2SEGADDR(buf);
}


void pci_free_consistent(struct pci_dev *hwdev, size_t size,
			 void *vaddr, dma_addr_t dma_handle)
{
	/* XXX */
Linus Torvalds's avatar
Linus Torvalds committed
112
	gapspci_dma_used = 0;
Linus Torvalds's avatar
Linus Torvalds committed
113 114 115 116 117 118 119 120 121 122 123 124 125 126
}


void __init pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
{
}                                                                                

void __init pcibios_fixup_bus(struct pci_bus *bus)
{
	struct list_head *ln;
	struct pci_dev *dev;

	for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
		dev = pci_dev_b(ln);
127
		if (!BBA_SELECTED(bus, dev->devfn)) continue;
Linus Torvalds's avatar
Linus Torvalds committed
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202

		printk("PCI: MMIO fixup to %s\n", dev->name);
		dev->resource[1].start=0x01001700;
		dev->resource[1].end=0x010017ff;
	}
}


static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
{
	return PCI_SLOT(dev->devfn);
}


static int __init map_dc_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
	return GAPSPCI_IRQ;
}


void __init pcibios_init(void)
{
	pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL);
	/* pci_assign_unassigned_resources(); */
	pci_fixup_irqs(no_swizzle, map_dc_irq);
}


/* Haven't done anything here as yet */
char * __init pcibios_setup(char *str)
{
	return str;
}


int __init gapspci_init(void)
{
	int i;
	char idbuf[16];

	for(i=0; i<16; i++)
		idbuf[i]=inb(GAPSPCI_REGS+i);

	if(strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16))
		return -1;

	outl(0x5a14a501, GAPSPCI_REGS+0x18);

	for(i=0; i<1000000; i++);

	if(inl(GAPSPCI_REGS+0x18)!=1)
		return -1;

	outl(0x01000000, GAPSPCI_REGS+0x20);
	outl(0x01000000, GAPSPCI_REGS+0x24);

	outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28);
	outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c);

	outl(1, GAPSPCI_REGS+0x14);
	outl(1, GAPSPCI_REGS+0x34);

	gapspci_dma_used=0;

	/* Setting Broadband Adapter */
	outw(0xf900, GAPSPCI_BBA_CONFIG+0x06);
	outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30);
	outb(0x00, GAPSPCI_BBA_CONFIG+0x3c);
	outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d);
	outw(0x0006, GAPSPCI_BBA_CONFIG+0x04);
	outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10);
	outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14);

	return 0;
}