1/* 2 * arch/arm/mach-ixp2000/ixdp2x01.c 3 * 4 * Code common to Intel IXDP2401 and IXDP2801 platforms 5 * 6 * Original Author: Andrzej Mialkowski <andrzej.mialkowski@intel.com> 7 * Maintainer: Deepak Saxena <dsaxena@plexity.net> 8 * 9 * Copyright (C) 2002-2003 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 18#include <linux/kernel.h> 19#include <linux/init.h> 20#include <linux/mm.h> 21#include <linux/sched.h> 22#include <linux/interrupt.h> 23#include <linux/bitops.h> 24#include <linux/pci.h> 25#include <linux/ioport.h> 26#include <linux/slab.h> 27#include <linux/delay.h> 28#include <linux/serial.h> 29#include <linux/tty.h> 30#include <linux/serial_core.h> 31#include <linux/platform_device.h> 32#include <linux/serial_8250.h> 33 34#include <asm/io.h> 35#include <asm/irq.h> 36#include <asm/pgtable.h> 37#include <asm/page.h> 38#include <asm/system.h> 39#include <asm/hardware.h> 40#include <asm/mach-types.h> 41 42#include <asm/mach/pci.h> 43#include <asm/mach/map.h> 44#include <asm/mach/irq.h> 45#include <asm/mach/time.h> 46#include <asm/mach/arch.h> 47#include <asm/mach/flash.h> 48 49/************************************************************************* 50 * IXDP2x01 IRQ Handling 51 *************************************************************************/ 52static void ixdp2x01_irq_mask(unsigned int irq) 53{ 54 ixp2000_reg_wrb(IXDP2X01_INT_MASK_SET_REG, 55 IXP2000_BOARD_IRQ_MASK(irq)); 56} 57 58static void ixdp2x01_irq_unmask(unsigned int irq) 59{ 60 ixp2000_reg_write(IXDP2X01_INT_MASK_CLR_REG, 61 IXP2000_BOARD_IRQ_MASK(irq)); 62} 63 64static u32 valid_irq_mask; 65 66static void ixdp2x01_irq_handler(unsigned int irq, struct irq_desc *desc) 67{ 68 u32 ex_interrupt; 69 int i; 70 71 desc->chip->mask(irq); 72 73 ex_interrupt = *IXDP2X01_INT_STAT_REG & valid_irq_mask; 74 75 if (!ex_interrupt) { 76 printk(KERN_ERR "Spurious IXDP2X01 CPLD interrupt!\n"); 77 return; 78 } 79 80 for (i = 0; i < IXP2000_BOARD_IRQS; i++) { 81 if (ex_interrupt & (1 << i)) { 82 struct irq_desc *cpld_desc; 83 int cpld_irq = IXP2000_BOARD_IRQ(0) + i; 84 cpld_desc = irq_desc + cpld_irq; 85 desc_handle_irq(cpld_irq, cpld_desc); 86 } 87 } 88 89 desc->chip->unmask(irq); 90} 91 92static struct irq_chip ixdp2x01_irq_chip = { 93 .mask = ixdp2x01_irq_mask, 94 .ack = ixdp2x01_irq_mask, 95 .unmask = ixdp2x01_irq_unmask 96}; 97 98/* 99 * We only do anything if we are the master NPU on the board. 100 * The slave NPU only has the ethernet chip going directly to 101 * the PCIB interrupt input. 102 */ 103void __init ixdp2x01_init_irq(void) 104{ 105 int irq = 0; 106 107 /* initialize chip specific interrupts */ 108 ixp2000_init_irq(); 109 110 if (machine_is_ixdp2401()) 111 valid_irq_mask = IXDP2401_VALID_IRQ_MASK; 112 else 113 valid_irq_mask = IXDP2801_VALID_IRQ_MASK; 114 115 /* Mask all interrupts from CPLD, disable simulation */ 116 ixp2000_reg_write(IXDP2X01_INT_MASK_SET_REG, 0xffffffff); 117 ixp2000_reg_wrb(IXDP2X01_INT_SIM_REG, 0); 118 119 for (irq = NR_IXP2000_IRQS; irq < NR_IXDP2X01_IRQS; irq++) { 120 if (irq & valid_irq_mask) { 121 set_irq_chip(irq, &ixdp2x01_irq_chip); 122 set_irq_handler(irq, handle_level_irq); 123 set_irq_flags(irq, IRQF_VALID); 124 } else { 125 set_irq_flags(irq, 0); 126 } 127 } 128 129 /* Hook into PCI interrupts */ 130 set_irq_chained_handler(IRQ_IXP2000_PCIB, ixdp2x01_irq_handler); 131} 132 133 134/************************************************************************* 135 * IXDP2x01 memory map 136 *************************************************************************/ 137static struct map_desc ixdp2x01_io_desc __initdata = { 138 .virtual = IXDP2X01_VIRT_CPLD_BASE, 139 .pfn = __phys_to_pfn(IXDP2X01_PHYS_CPLD_BASE), 140 .length = IXDP2X01_CPLD_REGION_SIZE, 141 .type = MT_DEVICE 142}; 143 144static void __init ixdp2x01_map_io(void) 145{ 146 ixp2000_map_io(); 147 iotable_init(&ixdp2x01_io_desc, 1); 148} 149 150 151/************************************************************************* 152 * IXDP2x01 serial ports 153 *************************************************************************/ 154static struct plat_serial8250_port ixdp2x01_serial_port1[] = { 155 { 156 .mapbase = (unsigned long)IXDP2X01_UART1_PHYS_BASE, 157 .membase = (char *)IXDP2X01_UART1_VIRT_BASE, 158 .irq = IRQ_IXDP2X01_UART1, 159 .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, 160 .iotype = UPIO_MEM32, 161 .regshift = 2, 162 .uartclk = IXDP2X01_UART_CLK, 163 }, 164 { } 165}; 166 167static struct resource ixdp2x01_uart_resource1 = { 168 .start = IXDP2X01_UART1_PHYS_BASE, 169 .end = IXDP2X01_UART1_PHYS_BASE + 0xffff, 170 .flags = IORESOURCE_MEM, 171}; 172 173static struct platform_device ixdp2x01_serial_device1 = { 174 .name = "serial8250", 175 .id = PLAT8250_DEV_PLATFORM1, 176 .dev = { 177 .platform_data = ixdp2x01_serial_port1, 178 }, 179 .num_resources = 1, 180 .resource = &ixdp2x01_uart_resource1, 181}; 182 183static struct plat_serial8250_port ixdp2x01_serial_port2[] = { 184 { 185 .mapbase = (unsigned long)IXDP2X01_UART2_PHYS_BASE, 186 .membase = (char *)IXDP2X01_UART2_VIRT_BASE, 187 .irq = IRQ_IXDP2X01_UART2, 188 .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, 189 .iotype = UPIO_MEM32, 190 .regshift = 2, 191 .uartclk = IXDP2X01_UART_CLK, 192 }, 193 { } 194}; 195 196static struct resource ixdp2x01_uart_resource2 = { 197 .start = IXDP2X01_UART2_PHYS_BASE, 198 .end = IXDP2X01_UART2_PHYS_BASE + 0xffff, 199 .flags = IORESOURCE_MEM, 200}; 201 202static struct platform_device ixdp2x01_serial_device2 = { 203 .name = "serial8250", 204 .id = PLAT8250_DEV_PLATFORM2, 205 .dev = { 206 .platform_data = ixdp2x01_serial_port2, 207 }, 208 .num_resources = 1, 209 .resource = &ixdp2x01_uart_resource2, 210}; 211 212static void ixdp2x01_uart_init(void) 213{ 214 platform_device_register(&ixdp2x01_serial_device1); 215 platform_device_register(&ixdp2x01_serial_device2); 216} 217 218 219/************************************************************************* 220 * IXDP2x01 timer tick configuration 221 *************************************************************************/ 222static unsigned int ixdp2x01_clock; 223 224static int __init ixdp2x01_clock_setup(char *str) 225{ 226 ixdp2x01_clock = simple_strtoul(str, NULL, 10); 227 228 return 1; 229} 230 231__setup("ixdp2x01_clock=", ixdp2x01_clock_setup); 232 233static void __init ixdp2x01_timer_init(void) 234{ 235 if (!ixdp2x01_clock) 236 ixdp2x01_clock = 50000000; 237 238 ixp2000_init_time(ixdp2x01_clock); 239} 240 241static struct sys_timer ixdp2x01_timer = { 242 .init = ixdp2x01_timer_init, 243 .offset = ixp2000_gettimeoffset, 244}; 245 246/************************************************************************* 247 * IXDP2x01 PCI 248 *************************************************************************/ 249void __init ixdp2x01_pci_preinit(void) 250{ 251 ixp2000_reg_write(IXP2000_PCI_ADDR_EXT, 0x00000000); 252 ixp2000_pci_preinit(); 253 pcibios_setup("firmware"); 254} 255 256#define DEVPIN(dev, pin) ((pin) | ((dev) << 3)) 257 258static int __init ixdp2x01_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) 259{ 260 u8 bus = dev->bus->number; 261 u32 devpin = DEVPIN(PCI_SLOT(dev->devfn), pin); 262 struct pci_bus *tmp_bus = dev->bus; 263 264 /* Primary bus, no interrupts here */ 265 if (bus == 0) { 266 return -1; 267 } 268 269 /* Lookup first leaf in bus tree */ 270 while ((tmp_bus->parent != NULL) && (tmp_bus->parent->parent != NULL)) { 271 tmp_bus = tmp_bus->parent; 272 } 273 274 /* Select between known bridges */ 275 switch (tmp_bus->self->devfn | (tmp_bus->self->bus->number << 8)) { 276 /* Device is located after first MB bridge */ 277 case 0x0008: 278 if (tmp_bus == dev->bus) { 279 /* Device is located directly after first MB bridge */ 280 switch (devpin) { 281 case DEVPIN(1, 1): /* Onboard 82546 ch 0 */ 282 if (machine_is_ixdp2401()) 283 return IRQ_IXDP2401_INTA_82546; 284 return -1; 285 case DEVPIN(1, 2): /* Onboard 82546 ch 1 */ 286 if (machine_is_ixdp2401()) 287 return IRQ_IXDP2401_INTB_82546; 288 return -1; 289 case DEVPIN(0, 1): /* PMC INTA# */ 290 return IRQ_IXDP2X01_SPCI_PMC_INTA; 291 case DEVPIN(0, 2): /* PMC INTB# */ 292 return IRQ_IXDP2X01_SPCI_PMC_INTB; 293 case DEVPIN(0, 3): /* PMC INTC# */ 294 return IRQ_IXDP2X01_SPCI_PMC_INTC; 295 case DEVPIN(0, 4): /* PMC INTD# */ 296 return IRQ_IXDP2X01_SPCI_PMC_INTD; 297 } 298 } 299 break; 300 case 0x0010: 301 if (tmp_bus == dev->bus) { 302 /* Device is located directly after second MB bridge */ 303 /* Secondary bus of second bridge */ 304 switch (devpin) { 305 case DEVPIN(0, 1): /* DB#0 */ 306 return IRQ_IXDP2X01_SPCI_DB_0; 307 case DEVPIN(1, 1): /* DB#1 */ 308 return IRQ_IXDP2X01_SPCI_DB_1; 309 } 310 } else { 311 /* Device is located indirectly after second MB bridge */ 312 /* Not supported now */ 313 } 314 break; 315 } 316 317 return -1; 318} 319 320 321static int ixdp2x01_pci_setup(int nr, struct pci_sys_data *sys) 322{ 323 sys->mem_offset = 0xe0000000; 324 325 if (machine_is_ixdp2801() || machine_is_ixdp28x5()) 326 sys->mem_offset -= ((*IXP2000_PCI_ADDR_EXT & 0xE000) << 16); 327 328 return ixp2000_pci_setup(nr, sys); 329} 330 331struct hw_pci ixdp2x01_pci __initdata = { 332 .nr_controllers = 1, 333 .setup = ixdp2x01_pci_setup, 334 .preinit = ixdp2x01_pci_preinit, 335 .scan = ixp2000_pci_scan_bus, 336 .map_irq = ixdp2x01_pci_map_irq, 337}; 338 339int __init ixdp2x01_pci_init(void) 340{ 341 if (machine_is_ixdp2401() || machine_is_ixdp2801() ||\ 342 machine_is_ixdp28x5()) 343 pci_common_init(&ixdp2x01_pci); 344 345 return 0; 346} 347 348subsys_initcall(ixdp2x01_pci_init); 349 350/************************************************************************* 351 * IXDP2x01 Machine Initialization 352 *************************************************************************/ 353static struct flash_platform_data ixdp2x01_flash_platform_data = { 354 .map_name = "cfi_probe", 355 .width = 1, 356}; 357 358static unsigned long ixdp2x01_flash_bank_setup(unsigned long ofs) 359{ 360 ixp2000_reg_wrb(IXDP2X01_CPLD_FLASH_REG, 361 ((ofs >> IXDP2X01_FLASH_WINDOW_BITS) | IXDP2X01_CPLD_FLASH_INTERN)); 362 return (ofs & IXDP2X01_FLASH_WINDOW_MASK); 363} 364 365static struct ixp2000_flash_data ixdp2x01_flash_data = { 366 .platform_data = &ixdp2x01_flash_platform_data, 367 .bank_setup = ixdp2x01_flash_bank_setup 368}; 369 370static struct resource ixdp2x01_flash_resource = { 371 .start = 0xc4000000, 372 .end = 0xc4000000 + 0x01ffffff, 373 .flags = IORESOURCE_MEM, 374}; 375 376static struct platform_device ixdp2x01_flash = { 377 .name = "IXP2000-Flash", 378 .id = 0, 379 .dev = { 380 .platform_data = &ixdp2x01_flash_data, 381 }, 382 .num_resources = 1, 383 .resource = &ixdp2x01_flash_resource, 384}; 385 386static struct ixp2000_i2c_pins ixdp2x01_i2c_gpio_pins = { 387 .sda_pin = IXDP2X01_GPIO_SDA, 388 .scl_pin = IXDP2X01_GPIO_SCL, 389}; 390 391static struct platform_device ixdp2x01_i2c_controller = { 392 .name = "IXP2000-I2C", 393 .id = 0, 394 .dev = { 395 .platform_data = &ixdp2x01_i2c_gpio_pins, 396 }, 397 .num_resources = 0 398}; 399 400static struct platform_device *ixdp2x01_devices[] __initdata = { 401 &ixdp2x01_flash, 402 &ixdp2x01_i2c_controller 403}; 404 405static void __init ixdp2x01_init_machine(void) 406{ 407 ixp2000_reg_wrb(IXDP2X01_CPLD_FLASH_REG, 408 (IXDP2X01_CPLD_FLASH_BANK_MASK | IXDP2X01_CPLD_FLASH_INTERN)); 409 410 ixdp2x01_flash_data.nr_banks = 411 ((*IXDP2X01_CPLD_FLASH_REG & IXDP2X01_CPLD_FLASH_BANK_MASK) + 1); 412 413 platform_add_devices(ixdp2x01_devices, ARRAY_SIZE(ixdp2x01_devices)); 414 ixp2000_uart_init(); 415 ixdp2x01_uart_init(); 416} 417 418 419#ifdef CONFIG_ARCH_IXDP2401 420MACHINE_START(IXDP2401, "Intel IXDP2401 Development Platform") 421 /* Maintainer: MontaVista Software, Inc. */ 422 .phys_io = IXP2000_UART_PHYS_BASE, 423 .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, 424 .boot_params = 0x00000100, 425 .map_io = ixdp2x01_map_io, 426 .init_irq = ixdp2x01_init_irq, 427 .timer = &ixdp2x01_timer, 428 .init_machine = ixdp2x01_init_machine, 429MACHINE_END 430#endif 431 432#ifdef CONFIG_ARCH_IXDP2801 433MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform") 434 /* Maintainer: MontaVista Software, Inc. */ 435 .phys_io = IXP2000_UART_PHYS_BASE, 436 .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, 437 .boot_params = 0x00000100, 438 .map_io = ixdp2x01_map_io, 439 .init_irq = ixdp2x01_init_irq, 440 .timer = &ixdp2x01_timer, 441 .init_machine = ixdp2x01_init_machine, 442MACHINE_END 443 444/* 445 * IXDP28x5 is basically an IXDP2801 with a different CPU but Intel 446 * changed the machine ID in the bootloader 447 */ 448MACHINE_START(IXDP28X5, "Intel IXDP2805/2855 Development Platform") 449 /* Maintainer: MontaVista Software, Inc. */ 450 .phys_io = IXP2000_UART_PHYS_BASE, 451 .io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc, 452 .boot_params = 0x00000100, 453 .map_io = ixdp2x01_map_io, 454 .init_irq = ixdp2x01_init_irq, 455 .timer = &ixdp2x01_timer, 456 .init_machine = ixdp2x01_init_machine, 457MACHINE_END 458#endif 459