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