1/* 2 * arch/arm/mach-ixp2000/ixdp2x00.c 3 * 4 * Code common to IXDP2400 and IXDP2800 platforms. 5 * 6 * Original Author: Naeem Afzal <naeem.m.afzal@intel.com> 7 * Maintainer: Deepak Saxena <dsaxena@plexity.net> 8 * 9 * Copyright (C) 2002 Intel Corp. 10 * Copyright (C) 2003-2004 MontaVista Software, Inc. 11 * 12 * This program is free software; you can redistribute it and/or modify it 13 * under the terms of the GNU General Public License as published by the 14 * Free Software Foundation; either version 2 of the License, or (at your 15 * option) any later version. 16 */ 17#include <linux/kernel.h> 18#include <linux/init.h> 19#include <linux/mm.h> 20#include <linux/sched.h> 21#include <linux/interrupt.h> 22#include <linux/platform_device.h> 23#include <linux/bitops.h> 24#include <linux/pci.h> 25#include <linux/ioport.h> 26#include <linux/delay.h> 27#include <linux/io.h> 28 29#include <asm/irq.h> 30#include <asm/pgtable.h> 31#include <asm/page.h> 32#include <asm/system.h> 33#include <mach/hardware.h> 34#include <asm/mach-types.h> 35 36#include <asm/mach/pci.h> 37#include <asm/mach/map.h> 38#include <asm/mach/irq.h> 39#include <asm/mach/time.h> 40#include <asm/mach/flash.h> 41#include <asm/mach/arch.h> 42 43#include <mach/gpio.h> 44 45 46/************************************************************************* 47 * IXDP2x00 IRQ Initialization 48 *************************************************************************/ 49static volatile unsigned long *board_irq_mask; 50static volatile unsigned long *board_irq_stat; 51static unsigned long board_irq_count; 52 53#ifdef CONFIG_ARCH_IXDP2400 54/* 55 * Slowport configuration for accessing CPLD registers on IXDP2x00 56 */ 57static struct slowport_cfg slowport_cpld_cfg = { 58 .CCR = SLOWPORT_CCR_DIV_2, 59 .WTC = 0x00000070, 60 .RTC = 0x00000070, 61 .PCR = SLOWPORT_MODE_FLASH, 62 .ADC = SLOWPORT_ADDR_WIDTH_24 | SLOWPORT_DATA_WIDTH_8 63}; 64#endif 65 66static void ixdp2x00_irq_mask(unsigned int irq) 67{ 68 unsigned long dummy; 69 static struct slowport_cfg old_cfg; 70 71 /* 72 * This is ugly in common code but really don't know 73 * of a better way to handle it. :( 74 */ 75#ifdef CONFIG_ARCH_IXDP2400 76 if (machine_is_ixdp2400()) 77 ixp2000_acquire_slowport(&slowport_cpld_cfg, &old_cfg); 78#endif 79 80 dummy = *board_irq_mask; 81 dummy |= IXP2000_BOARD_IRQ_MASK(irq); 82 ixp2000_reg_wrb(board_irq_mask, dummy); 83 84#ifdef CONFIG_ARCH_IXDP2400 85 if (machine_is_ixdp2400()) 86 ixp2000_release_slowport(&old_cfg); 87#endif 88} 89 90static void ixdp2x00_irq_unmask(unsigned int irq) 91{ 92 unsigned long dummy; 93 static struct slowport_cfg old_cfg; 94 95#ifdef CONFIG_ARCH_IXDP2400 96 if (machine_is_ixdp2400()) 97 ixp2000_acquire_slowport(&slowport_cpld_cfg, &old_cfg); 98#endif 99 100 dummy = *board_irq_mask; 101 dummy &= ~IXP2000_BOARD_IRQ_MASK(irq); 102 ixp2000_reg_wrb(board_irq_mask, dummy); 103 104 if (machine_is_ixdp2400()) 105 ixp2000_release_slowport(&old_cfg); 106} 107 108static void ixdp2x00_irq_handler(unsigned int irq, struct irq_desc *desc) 109{ 110 volatile u32 ex_interrupt = 0; 111 static struct slowport_cfg old_cfg; 112 int i; 113 114 desc->chip->mask(irq); 115 116#ifdef CONFIG_ARCH_IXDP2400 117 if (machine_is_ixdp2400()) 118 ixp2000_acquire_slowport(&slowport_cpld_cfg, &old_cfg); 119#endif 120 ex_interrupt = *board_irq_stat & 0xff; 121 if (machine_is_ixdp2400()) 122 ixp2000_release_slowport(&old_cfg); 123 124 if(!ex_interrupt) { 125 printk(KERN_ERR "Spurious IXDP2x00 CPLD interrupt!\n"); 126 return; 127 } 128 129 for(i = 0; i < board_irq_count; i++) { 130 if(ex_interrupt & (1 << i)) { 131 int cpld_irq = IXP2000_BOARD_IRQ(0) + i; 132 generic_handle_irq(cpld_irq); 133 } 134 } 135 136 desc->chip->unmask(irq); 137} 138 139static struct irq_chip ixdp2x00_cpld_irq_chip = { 140 .ack = ixdp2x00_irq_mask, 141 .mask = ixdp2x00_irq_mask, 142 .unmask = ixdp2x00_irq_unmask 143}; 144 145void __init ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long *mask_reg, unsigned long nr_of_irqs) 146{ 147 unsigned int irq; 148 149 ixp2000_init_irq(); 150 151 if (!ixdp2x00_master_npu()) 152 return; 153 154 board_irq_stat = stat_reg; 155 board_irq_mask = mask_reg; 156 board_irq_count = nr_of_irqs; 157 158 *board_irq_mask = 0xffffffff; 159 160 for(irq = IXP2000_BOARD_IRQ(0); irq < IXP2000_BOARD_IRQ(board_irq_count); irq++) { 161 set_irq_chip(irq, &ixdp2x00_cpld_irq_chip); 162 set_irq_handler(irq, handle_level_irq); 163 set_irq_flags(irq, IRQF_VALID); 164 } 165 166 /* Hook into PCI interrupt */ 167 set_irq_chained_handler(IRQ_IXP2000_PCIB, ixdp2x00_irq_handler); 168} 169 170/************************************************************************* 171 * IXDP2x00 memory map 172 *************************************************************************/ 173static struct map_desc ixdp2x00_io_desc __initdata = { 174 .virtual = IXDP2X00_VIRT_CPLD_BASE, 175 .pfn = __phys_to_pfn(IXDP2X00_PHYS_CPLD_BASE), 176 .length = IXDP2X00_CPLD_SIZE, 177 .type = MT_DEVICE 178}; 179 180void __init ixdp2x00_map_io(void) 181{ 182 ixp2000_map_io(); 183 184 iotable_init(&ixdp2x00_io_desc, 1); 185} 186 187/************************************************************************* 188 * IXDP2x00-common PCI init 189 * 190 * The IXDP2[48]00 has a horrid PCI bus layout. Basically the board 191 * contains two NPUs (ingress and egress) connected over PCI, both running 192 * instances of the kernel. So far so good. Peers on the PCI bus running 193 * Linux is a common design in telecom systems. The problem is that instead 194 * of all the devices being controlled by a single host, different 195 * devices are controlled by different NPUs on the same bus, leading to 196 * multiple hosts on the bus. The exact bus layout looks like: 197 * 198 * Bus 0 199 * Master NPU <-------------------+-------------------> Slave NPU 200 * | 201 * | 202 * P2P 203 * | 204 * 205 * Bus 1 | 206 * <--+------+---------+---------+------+--> 207 * | | | | | 208 * | | | | | 209 * ... Dev PMC Media Eth0 Eth1 ... 210 * 211 * The master controls all but Eth1, which is controlled by the 212 * slave. What this means is that the both the master and the slave 213 * have to scan the bus, but only one of them can enumerate the bus. 214 * In addition, after the bus is scanned, each kernel must remove 215 * the device(s) it does not control from the PCI dev list otherwise 216 * a driver on each NPU will try to manage it and we will have horrible 217 * conflicts. Oh..and the slave NPU needs to see the master NPU 218 * for Intel's drivers to work properly. Closed source drivers... 219 * 220 * The way we deal with this is fairly simple but ugly: 221 * 222 * 1) Let master scan and enumerate the bus completely. 223 * 2) Master deletes Eth1 from device list. 224 * 3) Slave scans bus and then deletes all but Eth1 (Eth0 on slave) 225 * from device list. 226 * 4) Find HW designers and LART them. 227 * 228 * The boards also do not do normal PCI IRQ routing, or any sort of 229 * sensical swizzling, so we just need to check where on the bus a 230 * device sits and figure out to which CPLD pin the interrupt is routed. 231 * See ixdp2[48]00.c files. 232 * 233 *************************************************************************/ 234void ixdp2x00_slave_pci_postinit(void) 235{ 236 struct pci_dev *dev; 237 238 /* 239 * Remove PMC device is there is one 240 */ 241 if((dev = pci_get_bus_and_slot(1, IXDP2X00_PMC_DEVFN))) { 242 pci_remove_bus_device(dev); 243 pci_dev_put(dev); 244 } 245 246 dev = pci_get_bus_and_slot(0, IXDP2X00_21555_DEVFN); 247 pci_remove_bus_device(dev); 248 pci_dev_put(dev); 249} 250 251/************************************************************************** 252 * IXDP2x00 Machine Setup 253 *************************************************************************/ 254static struct flash_platform_data ixdp2x00_platform_data = { 255 .map_name = "cfi_probe", 256 .width = 1, 257}; 258 259static struct ixp2000_flash_data ixdp2x00_flash_data = { 260 .platform_data = &ixdp2x00_platform_data, 261 .nr_banks = 1 262}; 263 264static struct resource ixdp2x00_flash_resource = { 265 .start = 0xc4000000, 266 .end = 0xc4000000 + 0x00ffffff, 267 .flags = IORESOURCE_MEM, 268}; 269 270static struct platform_device ixdp2x00_flash = { 271 .name = "IXP2000-Flash", 272 .id = 0, 273 .dev = { 274 .platform_data = &ixdp2x00_flash_data, 275 }, 276 .num_resources = 1, 277 .resource = &ixdp2x00_flash_resource, 278}; 279 280static struct ixp2000_i2c_pins ixdp2x00_i2c_gpio_pins = { 281 .sda_pin = IXDP2X00_GPIO_SDA, 282 .scl_pin = IXDP2X00_GPIO_SCL, 283}; 284 285static struct platform_device ixdp2x00_i2c_controller = { 286 .name = "IXP2000-I2C", 287 .id = 0, 288 .dev = { 289 .platform_data = &ixdp2x00_i2c_gpio_pins, 290 }, 291 .num_resources = 0 292}; 293 294static struct platform_device *ixdp2x00_devices[] __initdata = { 295 &ixdp2x00_flash, 296 &ixdp2x00_i2c_controller 297}; 298 299void __init ixdp2x00_init_machine(void) 300{ 301 gpio_line_set(IXDP2X00_GPIO_I2C_ENABLE, 1); 302 gpio_line_config(IXDP2X00_GPIO_I2C_ENABLE, GPIO_OUT); 303 304 platform_add_devices(ixdp2x00_devices, ARRAY_SIZE(ixdp2x00_devices)); 305 ixp2000_uart_init(); 306} 307