Commit 285f5fa7 authored by Dan Williams's avatar Dan Williams Committed by Russell King

[ARM] 3995/1: iop13xx: add iop13xx support

The iop348 processor integrates an Xscale (XSC3 512KB L2 Cache) core with a
Serial Attached SCSI (SAS) controller, multi-ported DDR2 memory
controller, 3 Application Direct Memory Access (DMA) controllers, a 133Mhz
PCI-X interface, a x8 PCI-Express interface, and other peripherals to form
a system-on-a-chip RAID subsystem engine.

The iop342 processor replaces the SAS controller with a second Xscale core
for dual core embedded applications.

The iop341 processor is the single core version of iop342.

This patch supports the two Intel customer reference platforms iq81340mc
for external storage and iq81340sc for direct attach (HBA) development.

The developer's manual is available here:
ftp://download.intel.com/design/iio/docs/31503701.pdf

Changelog:
* removed virtual addresses from resource definitions
* cleaned up some unnecessary #include's
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 4dbda6a5
......@@ -223,6 +223,12 @@ config ARCH_IOP33X
help
Support for Intel's IOP33X (XScale) family of processors.
config ARCH_IOP13XX
bool "IOP13xx-based"
select PCI
help
Support for Intel's IOP13XX (XScale) family of processors.
config ARCH_IXP4XX
bool "IXP4xx-based"
depends on MMU
......@@ -331,6 +337,8 @@ source "arch/arm/mach-iop32x/Kconfig"
source "arch/arm/mach-iop33x/Kconfig"
source "arch/arm/mach-iop13xx/Kconfig"
source "arch/arm/mach-ixp4xx/Kconfig"
source "arch/arm/mach-ixp2000/Kconfig"
......
......@@ -108,6 +108,7 @@ endif
machine-$(CONFIG_ARCH_CLPS711X) := clps711x
machine-$(CONFIG_ARCH_IOP32X) := iop32x
machine-$(CONFIG_ARCH_IOP33X) := iop33x
machine-$(CONFIG_ARCH_IOP13XX) := iop13xx
machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx
machine-$(CONFIG_ARCH_IXP2000) := ixp2000
machine-$(CONFIG_ARCH_IXP23XX) := ixp23xx
......
if ARCH_IOP13XX
menu "IOP13XX Implementation Options"
comment "IOP13XX Platform Support"
config MACH_IQ81340SC
bool "Enable IQ81340SC Hardware Support"
help
Say Y here if you want to support running on the Intel IQ81340SC
evaluation kit.
config MACH_IQ81340MC
bool "Enable IQ81340MC Hardware Support"
help
Say Y here if you want to support running on the Intel IQ81340MC
evaluation kit.
endmenu
endif
obj-y :=
obj-m :=
obj-n :=
obj- :=
obj-$(CONFIG_ARCH_IOP13XX) += setup.o
obj-$(CONFIG_ARCH_IOP13XX) += irq.o
obj-$(CONFIG_ARCH_IOP13XX) += time.o
obj-$(CONFIG_ARCH_IOP13XX) += pci.o
obj-$(CONFIG_ARCH_IOP13XX) += io.o
obj-$(CONFIG_MACH_IQ81340SC) += iq81340sc.o
obj-$(CONFIG_MACH_IQ81340MC) += iq81340mc.o
zreladdr-y := 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000
/*
* iop13xx custom ioremap implementation
* Copyright (c) 2005-2006, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/hardware.h>
#include <asm/io.h>
void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size,
unsigned long flags)
{
void __iomem * retval;
switch (cookie) {
case IOP13XX_PCIX_LOWER_MEM_RA ... IOP13XX_PCIX_UPPER_MEM_RA:
if (unlikely(!iop13xx_atux_mem_base))
retval = NULL;
else
retval = (void *)(iop13xx_atux_mem_base +
(cookie - IOP13XX_PCIX_LOWER_MEM_RA));
break;
case IOP13XX_PCIE_LOWER_MEM_RA ... IOP13XX_PCIE_UPPER_MEM_RA:
if (unlikely(!iop13xx_atue_mem_base))
retval = NULL;
else
retval = (void *)(iop13xx_atue_mem_base +
(cookie - IOP13XX_PCIE_LOWER_MEM_RA));
break;
case IOP13XX_PBI_LOWER_MEM_RA ... IOP13XX_PBI_UPPER_MEM_RA:
retval = __ioremap(IOP13XX_PBI_LOWER_MEM_PA +
(cookie - IOP13XX_PBI_LOWER_MEM_RA),
size, flags);
break;
case IOP13XX_PCIE_LOWER_IO_PA ... IOP13XX_PCIE_UPPER_IO_PA:
retval = (void *) IOP13XX_PCIE_IO_PHYS_TO_VIRT(cookie);
break;
case IOP13XX_PCIX_LOWER_IO_PA ... IOP13XX_PCIX_UPPER_IO_PA:
retval = (void *) IOP13XX_PCIX_IO_PHYS_TO_VIRT(cookie);
break;
case IOP13XX_PMMR_PHYS_MEM_BASE ... IOP13XX_PMMR_UPPER_MEM_PA:
retval = (void *) IOP13XX_PMMR_PHYS_TO_VIRT(cookie);
break;
default:
retval = __ioremap(cookie, size, flags);
}
return retval;
}
EXPORT_SYMBOL(__iop13xx_ioremap);
void __iop13xx_iounmap(void __iomem *addr)
{
extern void __iounmap(volatile void __iomem *addr);
if (iop13xx_atue_mem_base)
if (addr >= (void __iomem *) iop13xx_atue_mem_base &&
addr < (void __iomem *) (iop13xx_atue_mem_base +
iop13xx_atue_mem_size))
goto skip;
if (iop13xx_atux_mem_base)
if (addr >= (void __iomem *) iop13xx_atux_mem_base &&
addr < (void __iomem *) (iop13xx_atux_mem_base +
iop13xx_atux_mem_size))
goto skip;
switch ((u32) addr) {
case IOP13XX_PCIE_LOWER_IO_VA ... IOP13XX_PCIE_UPPER_IO_VA:
case IOP13XX_PCIX_LOWER_IO_VA ... IOP13XX_PCIX_UPPER_IO_VA:
case IOP13XX_PMMR_VIRT_MEM_BASE ... IOP13XX_PMMR_UPPER_MEM_VA:
goto skip;
}
__iounmap(addr);
skip:
return;
}
EXPORT_SYMBOL(__iop13xx_iounmap);
/*
* iq81340mc board support
* Copyright (c) 2005-2006, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*
*/
#include <linux/pci.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/mach/pci.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/arch/pci.h>
#include <asm/mach/time.h>
extern int init_atu; /* Flag to select which ATU(s) to initialize / disable */
static int __init
iq81340mc_pcix_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
{
switch (idsel) {
case 1:
switch (pin) {
case 1: return ATUX_INTB;
case 2: return ATUX_INTC;
case 3: return ATUX_INTD;
case 4: return ATUX_INTA;
default: return -1;
}
case 2:
switch (pin) {
case 1: return ATUX_INTC;
case 2: return ATUX_INTD;
case 3: return ATUX_INTC;
case 4: return ATUX_INTD;
default: return -1;
}
default: return -1;
}
}
static struct hw_pci iq81340mc_pci __initdata = {
.swizzle = pci_std_swizzle,
.nr_controllers = 0,
.setup = iop13xx_pci_setup,
.map_irq = iq81340mc_pcix_map_irq,
.scan = iop13xx_scan_bus,
.preinit = iop13xx_pci_init,
};
static int __init iq81340mc_pci_init(void)
{
iop13xx_atu_select(&iq81340mc_pci);
pci_common_init(&iq81340mc_pci);
iop13xx_map_pci_memory();
return 0;
}
static void __init iq81340mc_init(void)
{
iop13xx_platform_init();
iq81340mc_pci_init();
}
static void __init iq81340mc_timer_init(void)
{
iop13xx_init_time(400000000);
}
static struct sys_timer iq81340mc_timer = {
.init = iq81340mc_timer_init,
.offset = iop13xx_gettimeoffset,
};
MACHINE_START(IQ81340MC, "Intel IQ81340MC")
/* Maintainer: Dan Williams <dan.j.williams@intel.com> */
.phys_io = PHYS_IO,
.io_pg_offst = IO_PG_OFFSET,
.map_io = iop13xx_map_io,
.init_irq = iop13xx_init_irq,
.timer = &iq81340mc_timer,
.boot_params = BOOT_PARAM_OFFSET,
.init_machine = iq81340mc_init,
MACHINE_END
/*
* iq81340sc board support
* Copyright (c) 2005-2006, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*
*/
#include <linux/pci.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/mach/pci.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/arch/pci.h>
#include <asm/mach/time.h>
extern int init_atu;
static int __init
iq81340sc_atux_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
{
WARN_ON(idsel < 1 || idsel > 2);
switch (idsel) {
case 1:
switch (pin) {
case 1: return ATUX_INTB;
case 2: return ATUX_INTC;
case 3: return ATUX_INTD;
case 4: return ATUX_INTA;
default: return -1;
}
case 2:
switch (pin) {
case 1: return ATUX_INTC;
case 2: return ATUX_INTC;
case 3: return ATUX_INTC;
case 4: return ATUX_INTC;
default: return -1;
}
default: return -1;
}
}
static struct hw_pci iq81340sc_pci __initdata = {
.swizzle = pci_std_swizzle,
.nr_controllers = 0,
.setup = iop13xx_pci_setup,
.scan = iop13xx_scan_bus,
.map_irq = iq81340sc_atux_map_irq,
.preinit = iop13xx_pci_init
};
static int __init iq81340sc_pci_init(void)
{
iop13xx_atu_select(&iq81340sc_pci);
pci_common_init(&iq81340sc_pci);
iop13xx_map_pci_memory();
return 0;
}
static void __init iq81340sc_init(void)
{
iop13xx_platform_init();
iq81340sc_pci_init();
}
static void __init iq81340sc_timer_init(void)
{
iop13xx_init_time(400000000);
}
static struct sys_timer iq81340sc_timer = {
.init = iq81340sc_timer_init,
.offset = iop13xx_gettimeoffset,
};
MACHINE_START(IQ81340SC, "Intel IQ81340SC")
/* Maintainer: Dan Williams <dan.j.williams@intel.com> */
.phys_io = PHYS_IO,
.io_pg_offst = IO_PG_OFFSET,
.map_io = iop13xx_map_io,
.init_irq = iop13xx_init_irq,
.timer = &iq81340sc_timer,
.boot_params = BOOT_PARAM_OFFSET,
.init_machine = iq81340sc_init,
MACHINE_END
/*
* iop13xx IRQ handling / support functions
* Copyright (c) 2005-2006, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*
*/
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/sysctl.h>
#include <asm/uaccess.h>
#include <asm/mach/irq.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/arch/irqs.h>
/* INTCTL0 CP6 R0 Page 4
*/
static inline u32 read_intctl_0(void)
{
u32 val;
asm volatile("mrc p6, 0, %0, c0, c4, 0":"=r" (val));
return val;
}
static inline void write_intctl_0(u32 val)
{
asm volatile("mcr p6, 0, %0, c0, c4, 0"::"r" (val));
}
/* INTCTL1 CP6 R1 Page 4
*/
static inline u32 read_intctl_1(void)
{
u32 val;
asm volatile("mrc p6, 0, %0, c1, c4, 0":"=r" (val));
return val;
}
static inline void write_intctl_1(u32 val)
{
asm volatile("mcr p6, 0, %0, c1, c4, 0"::"r" (val));
}
/* INTCTL2 CP6 R2 Page 4
*/
static inline u32 read_intctl_2(void)
{
u32 val;
asm volatile("mrc p6, 0, %0, c2, c4, 0":"=r" (val));
return val;
}
static inline void write_intctl_2(u32 val)
{
asm volatile("mcr p6, 0, %0, c2, c4, 0"::"r" (val));
}
/* INTCTL3 CP6 R3 Page 4
*/
static inline u32 read_intctl_3(void)
{
u32 val;
asm volatile("mrc p6, 0, %0, c3, c4, 0":"=r" (val));
return val;
}
static inline void write_intctl_3(u32 val)
{
asm volatile("mcr p6, 0, %0, c3, c4, 0"::"r" (val));
}
/* INTSTR0 CP6 R0 Page 5
*/
static inline u32 read_intstr_0(void)
{
u32 val;
asm volatile("mrc p6, 0, %0, c0, c5, 0":"=r" (val));
return val;
}
static inline void write_intstr_0(u32 val)
{
asm volatile("mcr p6, 0, %0, c0, c5, 0"::"r" (val));
}
/* INTSTR1 CP6 R1 Page 5
*/
static inline u32 read_intstr_1(void)
{
u32 val;
asm volatile("mrc p6, 0, %0, c1, c5, 0":"=r" (val));
return val;
}
static void write_intstr_1(u32 val)
{
asm volatile("mcr p6, 0, %0, c1, c5, 0"::"r" (val));
}
/* INTSTR2 CP6 R2 Page 5
*/
static inline u32 read_intstr_2(void)
{
u32 val;
asm volatile("mrc p6, 0, %0, c2, c5, 0":"=r" (val));
return val;
}
static void write_intstr_2(u32 val)
{
asm volatile("mcr p6, 0, %0, c2, c5, 0"::"r" (val));
}
/* INTSTR3 CP6 R3 Page 5
*/
static inline u32 read_intstr_3(void)
{
u32 val;
asm volatile("mrc p6, 0, %0, c3, c5, 0":"=r" (val));
return val;
}
static void write_intstr_3(u32 val)
{
asm volatile("mcr p6, 0, %0, c3, c5, 0"::"r" (val));
}
/* INTBASE CP6 R0 Page 2
*/
static inline u32 read_intbase(void)
{
u32 val;
asm volatile("mrc p6, 0, %0, c0, c2, 0":"=r" (val));
return val;
}
static void write_intbase(u32 val)
{
asm volatile("mcr p6, 0, %0, c0, c2, 0"::"r" (val));
}
/* INTSIZE CP6 R2 Page 2
*/
static inline u32 read_intsize(void)
{
u32 val;
asm volatile("mrc p6, 0, %0, c2, c2, 0":"=r" (val));
return val;
}
static void write_intsize(u32 val)
{
asm volatile("mcr p6, 0, %0, c2, c2, 0"::"r" (val));
}
/* 0 = Interrupt Masked and 1 = Interrupt not masked */
static void
iop13xx_irq_mask0 (unsigned int irq)
{
u32 cp_flags = iop13xx_cp6_save();
write_intctl_0(read_intctl_0() & ~(1 << (irq - 0)));
iop13xx_cp6_restore(cp_flags);
}
static void
iop13xx_irq_mask1 (unsigned int irq)
{
u32 cp_flags = iop13xx_cp6_save();
write_intctl_1(read_intctl_1() & ~(1 << (irq - 32)));
iop13xx_cp6_restore(cp_flags);
}
static void
iop13xx_irq_mask2 (unsigned int irq)
{
u32 cp_flags = iop13xx_cp6_save();
write_intctl_2(read_intctl_2() & ~(1 << (irq - 64)));
iop13xx_cp6_restore(cp_flags);
}
static void
iop13xx_irq_mask3 (unsigned int irq)
{
u32 cp_flags = iop13xx_cp6_save();
write_intctl_3(read_intctl_3() & ~(1 << (irq - 96)));
iop13xx_cp6_restore(cp_flags);
}
static void
iop13xx_irq_unmask0(unsigned int irq)
{
u32 cp_flags = iop13xx_cp6_save();
write_intctl_0(read_intctl_0() | (1 << (irq - 0)));
iop13xx_cp6_restore(cp_flags);
}
static void
iop13xx_irq_unmask1(unsigned int irq)
{
u32 cp_flags = iop13xx_cp6_save();
write_intctl_1(read_intctl_1() | (1 << (irq - 32)));
iop13xx_cp6_restore(cp_flags);
}
static void
iop13xx_irq_unmask2(unsigned int irq)
{
u32 cp_flags = iop13xx_cp6_save();
write_intctl_2(read_intctl_2() | (1 << (irq - 64)));
iop13xx_cp6_restore(cp_flags);
}
static void
iop13xx_irq_unmask3(unsigned int irq)
{
u32 cp_flags = iop13xx_cp6_save();
write_intctl_3(read_intctl_3() | (1 << (irq - 96)));
iop13xx_cp6_restore(cp_flags);
}
static struct irqchip iop13xx_irqchip0 = {
.ack = iop13xx_irq_mask0,
.mask = iop13xx_irq_mask0,
.unmask = iop13xx_irq_unmask0,
};
static struct irqchip iop13xx_irqchip1 = {
.ack = iop13xx_irq_mask1,
.mask = iop13xx_irq_mask1,
.unmask = iop13xx_irq_unmask1,
};
static struct irqchip iop13xx_irqchip2 = {
.ack = iop13xx_irq_mask2,
.mask = iop13xx_irq_mask2,
.unmask = iop13xx_irq_unmask2,
};
static struct irqchip iop13xx_irqchip3 = {
.ack = iop13xx_irq_mask3,
.mask = iop13xx_irq_mask3,
.unmask = iop13xx_irq_unmask3,
};
void __init iop13xx_init_irq(void)
{
unsigned int i;