1/*
2 * arch/arm/mach-ixp2000/enp2611.c
3 *
4 * Radisys ENP-2611 support.
5 *
6 * Created 2004 by Lennert Buytenhek from the ixdp2x01 code.  The
7 * original version carries the following notices:
8 *
9 * Original Author: Andrzej Mialkowski <andrzej.mialkowski@intel.com>
10 * Maintainer: Deepak Saxena <dsaxena@plexity.net>
11 *
12 * Copyright (C) 2002-2003 Intel Corp.
13 * Copyright (C) 2003-2004 MontaVista Software, Inc.
14 *
15 *  This program is free software; you can redistribute  it and/or modify it
16 *  under  the terms of  the GNU General  Public License as published by the
17 *  Free Software Foundation;  either version 2 of the  License, or (at your
18 *  option) any later version.
19 */
20
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/mm.h>
24#include <linux/sched.h>
25#include <linux/interrupt.h>
26#include <linux/bitops.h>
27#include <linux/pci.h>
28#include <linux/ioport.h>
29#include <linux/slab.h>
30#include <linux/delay.h>
31#include <linux/serial.h>
32#include <linux/tty.h>
33#include <linux/serial_core.h>
34#include <linux/platform_device.h>
35
36#include <asm/io.h>
37#include <asm/irq.h>
38#include <asm/pgtable.h>
39#include <asm/page.h>
40#include <asm/system.h>
41#include <asm/hardware.h>
42#include <asm/mach-types.h>
43
44#include <asm/mach/pci.h>
45#include <asm/mach/map.h>
46#include <asm/mach/irq.h>
47#include <asm/mach/time.h>
48#include <asm/mach/arch.h>
49#include <asm/mach/flash.h>
50
51/*************************************************************************
52 * ENP-2611 timer tick configuration
53 *************************************************************************/
54static void __init enp2611_timer_init(void)
55{
56	ixp2000_init_time(50 * 1000 * 1000);
57}
58
59static struct sys_timer enp2611_timer = {
60	.init		= enp2611_timer_init,
61	.offset		= ixp2000_gettimeoffset,
62};
63
64
65/*************************************************************************
66 * ENP-2611 I/O
67 *************************************************************************/
68static struct map_desc enp2611_io_desc[] __initdata = {
69	{
70		.virtual	= ENP2611_CALEB_VIRT_BASE,
71		.pfn		= __phys_to_pfn(ENP2611_CALEB_PHYS_BASE),
72		.length		= ENP2611_CALEB_SIZE,
73		.type		= MT_DEVICE_IXP2000,
74	}, {
75		.virtual	= ENP2611_PM3386_0_VIRT_BASE,
76		.pfn		= __phys_to_pfn(ENP2611_PM3386_0_PHYS_BASE),
77		.length		= ENP2611_PM3386_0_SIZE,
78		.type		= MT_DEVICE_IXP2000,
79	}, {
80		.virtual	= ENP2611_PM3386_1_VIRT_BASE,
81		.pfn		= __phys_to_pfn(ENP2611_PM3386_1_PHYS_BASE),
82		.length		= ENP2611_PM3386_1_SIZE,
83		.type		= MT_DEVICE_IXP2000,
84	}
85};
86
87void __init enp2611_map_io(void)
88{
89	ixp2000_map_io();
90	iotable_init(enp2611_io_desc, ARRAY_SIZE(enp2611_io_desc));
91}
92
93
94/*************************************************************************
95 * ENP-2611 PCI
96 *************************************************************************/
97static int enp2611_pci_setup(int nr, struct pci_sys_data *sys)
98{
99	sys->mem_offset = 0xe0000000;
100	ixp2000_pci_setup(nr, sys);
101	return 1;
102}
103
104static void __init enp2611_pci_preinit(void)
105{
106	ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00100000);
107	ixp2000_pci_preinit();
108	pcibios_setup("firmware");
109}
110
111static inline int enp2611_pci_valid_device(struct pci_bus *bus,
112						unsigned int devfn)
113{
114	/* The 82559 ethernet controller appears at both PCI:1:0:0 and
115	 * PCI:1:2:0, so let's pretend the second one isn't there.
116	 */
117	if (bus->number == 0x01 && devfn == 0x10)
118		return 0;
119
120	return 1;
121}
122
123static int enp2611_pci_read_config(struct pci_bus *bus, unsigned int devfn,
124					int where, int size, u32 *value)
125{
126	if (enp2611_pci_valid_device(bus, devfn))
127		return ixp2000_pci_read_config(bus, devfn, where, size, value);
128
129	return PCIBIOS_DEVICE_NOT_FOUND;
130}
131
132static int enp2611_pci_write_config(struct pci_bus *bus, unsigned int devfn,
133					int where, int size, u32 value)
134{
135	if (enp2611_pci_valid_device(bus, devfn))
136		return ixp2000_pci_write_config(bus, devfn, where, size, value);
137
138	return PCIBIOS_DEVICE_NOT_FOUND;
139}
140
141static struct pci_ops enp2611_pci_ops = {
142	.read   = enp2611_pci_read_config,
143	.write  = enp2611_pci_write_config
144};
145
146static struct pci_bus * __init enp2611_pci_scan_bus(int nr,
147						struct pci_sys_data *sys)
148{
149	return pci_scan_bus(sys->busnr, &enp2611_pci_ops, sys);
150}
151
152static int __init enp2611_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
153{
154	int irq;
155
156	if (dev->bus->number == 0 && PCI_SLOT(dev->devfn) == 0) {
157		/* IXP2400. */
158		irq = IRQ_IXP2000_PCIA;
159	} else if (dev->bus->number == 0 && PCI_SLOT(dev->devfn) == 1) {
160		/* 21555 non-transparent bridge.  */
161		irq = IRQ_IXP2000_PCIB;
162	} else if (dev->bus->number == 0 && PCI_SLOT(dev->devfn) == 4) {
163		/* PCI2050B transparent bridge.  */
164		irq = -1;
165	} else if (dev->bus->number == 1 && PCI_SLOT(dev->devfn) == 0) {
166		/* 82559 ethernet.  */
167		irq = IRQ_IXP2000_PCIA;
168	} else if (dev->bus->number == 1 && PCI_SLOT(dev->devfn) == 1) {
169		/* SPI-3 option board.  */
170		irq = IRQ_IXP2000_PCIB;
171	} else {
172		printk(KERN_ERR "enp2611_pci_map_irq() called for unknown "
173				"device PCI:%d:%d:%d\n", dev->bus->number,
174				PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
175		irq = -1;
176	}
177
178	return irq;
179}
180
181struct hw_pci enp2611_pci __initdata = {
182	.nr_controllers	= 1,
183	.setup		= enp2611_pci_setup,
184	.preinit	= enp2611_pci_preinit,
185	.scan		= enp2611_pci_scan_bus,
186	.map_irq	= enp2611_pci_map_irq,
187};
188
189int __init enp2611_pci_init(void)
190{
191	if (machine_is_enp2611())
192		pci_common_init(&enp2611_pci);
193
194	return 0;
195}
196
197subsys_initcall(enp2611_pci_init);
198
199
200/*************************************************************************
201 * ENP-2611 Machine Initialization
202 *************************************************************************/
203static struct flash_platform_data enp2611_flash_platform_data = {
204	.map_name	= "cfi_probe",
205	.width		= 1,
206};
207
208static struct ixp2000_flash_data enp2611_flash_data = {
209	.platform_data	= &enp2611_flash_platform_data,
210	.nr_banks	= 1
211};
212
213static struct resource enp2611_flash_resource = {
214	.start		= 0xc4000000,
215	.end		= 0xc4000000 + 0x00ffffff,
216	.flags		= IORESOURCE_MEM,
217};
218
219static struct platform_device enp2611_flash = {
220	.name		= "IXP2000-Flash",
221	.id		= 0,
222	.dev		= {
223		.platform_data = &enp2611_flash_data,
224	},
225	.num_resources	= 1,
226	.resource	= &enp2611_flash_resource,
227};
228
229static struct ixp2000_i2c_pins enp2611_i2c_gpio_pins = {
230	.sda_pin	= ENP2611_GPIO_SDA,
231	.scl_pin	= ENP2611_GPIO_SCL,
232};
233
234static struct platform_device enp2611_i2c_controller = {
235	.name		= "IXP2000-I2C",
236	.id		= 0,
237	.dev		= {
238		.platform_data = &enp2611_i2c_gpio_pins
239	},
240	.num_resources	= 0
241};
242
243static struct platform_device *enp2611_devices[] __initdata = {
244	&enp2611_flash,
245	&enp2611_i2c_controller
246};
247
248static void __init enp2611_init_machine(void)
249{
250	platform_add_devices(enp2611_devices, ARRAY_SIZE(enp2611_devices));
251	ixp2000_uart_init();
252}
253
254
255MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board")
256	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
257	.phys_io	= IXP2000_UART_PHYS_BASE,
258	.io_pg_offst	= ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
259	.boot_params	= 0x00000100,
260	.map_io		= enp2611_map_io,
261	.init_irq	= ixp2000_init_irq,
262	.timer		= &enp2611_timer,
263	.init_machine	= enp2611_init_machine,
264MACHINE_END
265