e90ddd813d
Currently the iop3xx platform support code assumes that RedBoot is the bootloader and has already initialized the ATU. Linux should handle this initialization for three reasons: 1/ The memory map that RedBoot sets up is not optimal (page_to_dma and virt_to_phys return different addresses). The effect of this is that using the dma mapping API for the internal bus dma units generates pci bus addresses that are incorrect for the internal bus. 2/ Not all iop platforms use RedBoot 3/ If the ATU is already initialized it indicates that the iop is an add-in card in another host, it does not own the PCI bus, and should not be re-initialized. Changelog: * rather than change nr_controllers to zero, simply do not call pci_common_init Cc: Lennert Buytenhek <kernel@wantstofly.org> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
196 lines
4.4 KiB
C
196 lines
4.4 KiB
C
/*
|
|
* arch/arm/mach-iop32x/iq80321.c
|
|
*
|
|
* Board support code for the Intel IQ80321 platform.
|
|
*
|
|
* Author: Rory Bolt <rorybolt@pacbell.net>
|
|
* Copyright (C) 2002 Rory Bolt
|
|
* Copyright (C) 2004 Intel Corp.
|
|
*
|
|
* 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/mm.h>
|
|
#include <linux/init.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/string.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/serial_core.h>
|
|
#include <linux/serial_8250.h>
|
|
#include <linux/mtd/physmap.h>
|
|
#include <linux/platform_device.h>
|
|
#include <asm/hardware.h>
|
|
#include <asm/io.h>
|
|
#include <asm/irq.h>
|
|
#include <asm/mach/arch.h>
|
|
#include <asm/mach/map.h>
|
|
#include <asm/mach/pci.h>
|
|
#include <asm/mach/time.h>
|
|
#include <asm/mach-types.h>
|
|
#include <asm/page.h>
|
|
#include <asm/pgtable.h>
|
|
#include <asm/arch/time.h>
|
|
|
|
/*
|
|
* IQ80321 timer tick configuration.
|
|
*/
|
|
static void __init iq80321_timer_init(void)
|
|
{
|
|
/* 33.333 MHz crystal. */
|
|
iop_init_time(200000000);
|
|
}
|
|
|
|
static struct sys_timer iq80321_timer = {
|
|
.init = iq80321_timer_init,
|
|
.offset = iop_gettimeoffset,
|
|
};
|
|
|
|
|
|
/*
|
|
* IQ80321 I/O.
|
|
*/
|
|
static struct map_desc iq80321_io_desc[] __initdata = {
|
|
{ /* on-board devices */
|
|
.virtual = IQ80321_UART,
|
|
.pfn = __phys_to_pfn(IQ80321_UART),
|
|
.length = 0x00100000,
|
|
.type = MT_DEVICE,
|
|
},
|
|
};
|
|
|
|
void __init iq80321_map_io(void)
|
|
{
|
|
iop3xx_map_io();
|
|
iotable_init(iq80321_io_desc, ARRAY_SIZE(iq80321_io_desc));
|
|
}
|
|
|
|
|
|
/*
|
|
* IQ80321 PCI.
|
|
*/
|
|
static inline int __init
|
|
iq80321_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
|
|
{
|
|
int irq;
|
|
|
|
if ((slot == 2 || slot == 6) && pin == 1) {
|
|
/* PCI-X Slot INTA */
|
|
irq = IRQ_IOP32X_XINT2;
|
|
} else if ((slot == 2 || slot == 6) && pin == 2) {
|
|
/* PCI-X Slot INTA */
|
|
irq = IRQ_IOP32X_XINT3;
|
|
} else if ((slot == 2 || slot == 6) && pin == 3) {
|
|
/* PCI-X Slot INTA */
|
|
irq = IRQ_IOP32X_XINT0;
|
|
} else if ((slot == 2 || slot == 6) && pin == 4) {
|
|
/* PCI-X Slot INTA */
|
|
irq = IRQ_IOP32X_XINT1;
|
|
} else if (slot == 4 || slot == 8) {
|
|
/* Gig-E */
|
|
irq = IRQ_IOP32X_XINT0;
|
|
} else {
|
|
printk(KERN_ERR "iq80321_pci_map_irq() called for unknown "
|
|
"device PCI:%d:%d:%d\n", dev->bus->number,
|
|
PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
|
|
irq = -1;
|
|
}
|
|
|
|
return irq;
|
|
}
|
|
|
|
static struct hw_pci iq80321_pci __initdata = {
|
|
.swizzle = pci_std_swizzle,
|
|
.nr_controllers = 1,
|
|
.setup = iop3xx_pci_setup,
|
|
.preinit = iop3xx_pci_preinit,
|
|
.scan = iop3xx_pci_scan_bus,
|
|
.map_irq = iq80321_pci_map_irq,
|
|
};
|
|
|
|
static int __init iq80321_pci_init(void)
|
|
{
|
|
if ((iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) &&
|
|
machine_is_iq80321())
|
|
pci_common_init(&iq80321_pci);
|
|
|
|
return 0;
|
|
}
|
|
|
|
subsys_initcall(iq80321_pci_init);
|
|
|
|
|
|
/*
|
|
* IQ80321 machine initialisation.
|
|
*/
|
|
static struct physmap_flash_data iq80321_flash_data = {
|
|
.width = 1,
|
|
};
|
|
|
|
static struct resource iq80321_flash_resource = {
|
|
.start = 0xf0000000,
|
|
.end = 0xf07fffff,
|
|
.flags = IORESOURCE_MEM,
|
|
};
|
|
|
|
static struct platform_device iq80321_flash_device = {
|
|
.name = "physmap-flash",
|
|
.id = 0,
|
|
.dev = {
|
|
.platform_data = &iq80321_flash_data,
|
|
},
|
|
.num_resources = 1,
|
|
.resource = &iq80321_flash_resource,
|
|
};
|
|
|
|
static struct plat_serial8250_port iq80321_serial_port[] = {
|
|
{
|
|
.mapbase = IQ80321_UART,
|
|
.membase = (char *)IQ80321_UART,
|
|
.irq = IRQ_IOP32X_XINT1,
|
|
.flags = UPF_SKIP_TEST,
|
|
.iotype = UPIO_MEM,
|
|
.regshift = 0,
|
|
.uartclk = 1843200,
|
|
},
|
|
{ },
|
|
};
|
|
|
|
static struct resource iq80321_uart_resource = {
|
|
.start = IQ80321_UART,
|
|
.end = IQ80321_UART + 7,
|
|
.flags = IORESOURCE_MEM,
|
|
};
|
|
|
|
static struct platform_device iq80321_serial_device = {
|
|
.name = "serial8250",
|
|
.id = PLAT8250_DEV_PLATFORM,
|
|
.dev = {
|
|
.platform_data = iq80321_serial_port,
|
|
},
|
|
.num_resources = 1,
|
|
.resource = &iq80321_uart_resource,
|
|
};
|
|
|
|
static void __init iq80321_init_machine(void)
|
|
{
|
|
platform_device_register(&iop3xx_i2c0_device);
|
|
platform_device_register(&iop3xx_i2c1_device);
|
|
platform_device_register(&iq80321_flash_device);
|
|
platform_device_register(&iq80321_serial_device);
|
|
}
|
|
|
|
MACHINE_START(IQ80321, "Intel IQ80321")
|
|
/* Maintainer: Intel Corp. */
|
|
.phys_io = IQ80321_UART,
|
|
.io_pg_offst = ((IQ80321_UART) >> 18) & 0xfffc,
|
|
.boot_params = 0xa0000100,
|
|
.map_io = iq80321_map_io,
|
|
.init_irq = iop32x_init_irq,
|
|
.timer = &iq80321_timer,
|
|
.init_machine = iq80321_init_machine,
|
|
MACHINE_END
|