ixdp2400.c 4.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/*
 * arch/arm/mach-ixp2000/ixdp2400.c
 *
 * IXDP2400 platform support
 *
 * Original Author: Naeem Afzal <naeem.m.afzal@intel.com>
 * Maintainer: Deepak Saxena <dsaxena@plexity.net>
 *
 * Copyright (C) 2002 Intel Corp.
 * Copyright (C) 2003-2004 MontaVista Software, Inc.
 *
 *  This program is free software; you can redistribute  it and/or modify it
 *  under  the terms of  the GNU General  Public License as published by the
 *  Free Software Foundation;  either version 2 of the  License, or (at your
 *  option) any later version.
 */
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/bitops.h>
#include <linux/pci.h>
#include <linux/ioport.h>
#include <linux/delay.h>
27
#include <linux/io.h>
L
Linus Torvalds 已提交
28 29 30 31 32

#include <asm/irq.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/system.h>
33
#include <mach/hardware.h>
L
Linus Torvalds 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
#include <asm/mach-types.h>

#include <asm/mach/pci.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
#include <asm/mach/flash.h>
#include <asm/mach/arch.h>

/*************************************************************************
 * IXDP2400 timer tick
 *************************************************************************/
static void __init ixdp2400_timer_init(void)
{
	int numerator, denominator;
	int denom_array[] = {2, 4, 8, 16, 1, 2, 4, 8};

	numerator = (*(IXDP2400_CPLD_SYS_CLK_M) & 0xFF) *2;
	denominator = denom_array[(*(IXDP2400_CPLD_SYS_CLK_N) & 0x7)];

	ixp2000_init_time(((3125000 * numerator) / (denominator)) / 2);
}

static struct sys_timer ixdp2400_timer = {
	.init		= ixdp2400_timer_init,
	.offset		= ixp2000_gettimeoffset,
};

/*************************************************************************
 * IXDP2400 PCI
 *************************************************************************/
void __init ixdp2400_pci_preinit(void)
{
	ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00100000);
	ixp2000_pci_preinit();
69
	pcibios_setup("firmware");
L
Linus Torvalds 已提交
70 71 72 73 74 75 76 77 78 79 80
}

int ixdp2400_pci_setup(int nr, struct pci_sys_data *sys)
{
	sys->mem_offset = 0xe0000000;

	ixp2000_pci_setup(nr, sys);

	return 1;
}

81 82
static int __init ixdp2400_pci_map_irq(const struct pci_dev *dev, u8 slot,
	u8 pin)
L
Linus Torvalds 已提交
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
{
	if (ixdp2x00_master_npu()) {

		/*
		 * Root bus devices.  Slave NPU is only one with interrupt.
		 * Everything else, we just return -1 b/c nothing else
		 * on the root bus has interrupts.
		 */
		if(!dev->bus->self) {
			if(dev->devfn == IXDP2X00_SLAVE_NPU_DEVFN )
				return IRQ_IXDP2400_INGRESS_NPU;

			return -1;
		}

		/*
		 * Bridge behind the PMC slot.
		 * NOTE: Only INTA from the PMC slot is routed. VERY BAD.
		 */
		if(dev->bus->self->devfn == IXDP2X00_PMC_DEVFN &&
			dev->bus->parent->self->devfn == IXDP2X00_P2P_DEVFN &&
			!dev->bus->parent->self->bus->parent)
				  return IRQ_IXDP2400_PMC;

		/*
		 * Device behind the first bridge
		 */
		if(dev->bus->self->devfn == IXDP2X00_P2P_DEVFN) {
			switch(dev->devfn) {
				case IXDP2400_MASTER_ENET_DEVFN:	
					return IRQ_IXDP2400_ENET;	
			
				case IXDP2400_MEDIA_DEVFN:
					return IRQ_IXDP2400_MEDIA_PCI;

				case IXDP2400_SWITCH_FABRIC_DEVFN:
					return IRQ_IXDP2400_SF_PCI;

				case IXDP2X00_PMC_DEVFN:
					return IRQ_IXDP2400_PMC;
			}
		}

		return -1;
	} else return IRQ_IXP2000_PCIB; /* Slave NIC interrupt */
}


static void ixdp2400_pci_postinit(void)
{
	struct pci_dev *dev;

	if (ixdp2x00_master_npu()) {
136
		dev = pci_get_bus_and_slot(1, IXDP2400_SLAVE_ENET_DEVFN);
L
Linus Torvalds 已提交
137
		pci_remove_bus_device(dev);
138
		pci_dev_put(dev);
L
Linus Torvalds 已提交
139
	} else {
140
		dev = pci_get_bus_and_slot(1, IXDP2400_MASTER_ENET_DEVFN);
L
Linus Torvalds 已提交
141
		pci_remove_bus_device(dev);
142
		pci_dev_put(dev);
L
Linus Torvalds 已提交
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166

		ixdp2x00_slave_pci_postinit();
	}
}

static struct hw_pci ixdp2400_pci __initdata = {
	.nr_controllers	= 1,
	.setup		= ixdp2400_pci_setup,
	.preinit	= ixdp2400_pci_preinit,
	.postinit	= ixdp2400_pci_postinit,
	.scan		= ixp2000_pci_scan_bus,
	.map_irq	= ixdp2400_pci_map_irq,
};

int __init ixdp2400_pci_init(void)
{
	if (machine_is_ixdp2400())
		pci_common_init(&ixdp2400_pci);

	return 0;
}

subsys_initcall(ixdp2400_pci_init);

167
void __init ixdp2400_init_irq(void)
L
Linus Torvalds 已提交
168 169 170 171 172
{
	ixdp2x00_init_irq(IXDP2400_CPLD_INT_STAT, IXDP2400_CPLD_INT_MASK, IXDP2400_NR_IRQS);
}

MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform")
173
	/* Maintainer: MontaVista Software, Inc. */
174
	.atag_offset	= 0x100,
175 176
	.map_io		= ixdp2x00_map_io,
	.init_irq	= ixdp2400_init_irq,
L
Linus Torvalds 已提交
177
	.timer		= &ixdp2400_timer,
178
	.init_machine	= ixdp2x00_init_machine,
L
Linus Torvalds 已提交
179 180
MACHINE_END