aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-ixp2000/ixdp2400.c
blob: 5f1068762979b3d2432a440f01992cc24e0c615f (plain)
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
27
28
29
30
31
32
33
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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
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
/*
 * 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/slab.h>
#include <linux/delay.h>

#include <asm/io.h>
#include <asm/irq.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/system.h>
#include <asm/arch/hardware.h>
#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();
	pcibios_setup("firmware");
}

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

	ixp2000_pci_setup(nr, sys);

	return 1;
}

static int __init ixdp2400_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
	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()) {
		dev = pci_get_bus_and_slot(1, IXDP2400_SLAVE_ENET_DEVFN);
		pci_remove_bus_device(dev);
		pci_dev_put(dev);
	} else {
		dev = pci_get_bus_and_slot(1, IXDP2400_MASTER_ENET_DEVFN);
		pci_remove_bus_device(dev);
		pci_dev_put(dev);

		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);

void __init ixdp2400_init_irq(void)
{
	ixdp2x00_init_irq(IXDP2400_CPLD_INT_STAT, IXDP2400_CPLD_INT_MASK, IXDP2400_NR_IRQS);
}

MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform")
	/* Maintainer: MontaVista Software, Inc. */
	.phys_io	= IXP2000_UART_PHYS_BASE,
	.io_pg_offst	= ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
	.boot_params	= 0x00000100,
	.map_io		= ixdp2x00_map_io,
	.init_irq	= ixdp2400_init_irq,
	.timer		= &ixdp2400_timer,
	.init_machine	= ixdp2x00_init_machine,
MACHINE_END