Merge the easy part of the IOP branch
authorRussell King <rmk@dyn-67.arm.linux.org.uk>
Sun, 18 Feb 2007 11:31:14 +0000 (11:31 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sun, 18 Feb 2007 11:31:14 +0000 (11:31 +0000)
13 files changed:
arch/arm/Kconfig
arch/arm/kernel/traps.c
arch/arm/mach-iop13xx/irq.c
arch/arm/mach-iop32x/irq.c
arch/arm/mach-iop33x/irq.c
arch/arm/plat-iop/Makefile
arch/arm/plat-iop/cp6.c [new file with mode: 0644]
arch/arm/plat-iop/io.c [new file with mode: 0644]
arch/arm/plat-iop/pci.c
drivers/i2c/busses/i2c-iop3xx.c
include/asm-arm/arch-iop32x/io.h
include/asm-arm/arch-iop33x/io.h
include/asm-arm/hardware/iop3xx.h

index 8136d32cd78fbb35b7d88746b841d5212483b79b..2c32c8702cfda39d42446cf1ddef9c4b2773527d 100644 (file)
@@ -233,6 +233,8 @@ config ARCH_IOP33X
 
 config ARCH_IOP13XX
        bool "IOP13xx-based"
+       depends on MMU
+       select PLAT_IOP
        select PCI
        help
          Support for Intel's IOP13XX (XScale) family of processors.
index 329609b84d3bee3717069fe497bbe8fbe0797814..24095601359b94e04b9d8b83b2b9ab70cb9a2135 100644 (file)
@@ -282,7 +282,10 @@ asmlinkage void do_undefinstr(struct pt_regs *regs)
        regs->ARM_pc -= correction;
 
        pc = (void __user *)instruction_pointer(regs);
-       if (thumb_mode(regs)) {
+
+       if (processor_mode(regs) == SVC_MODE) {
+               instr = *(u32 *) pc;
+       } else if (thumb_mode(regs)) {
                get_user(instr, (u16 __user *)pc);
        } else {
                get_user(instr, (u32 __user *)pc);
index dbbc07c38b141349f9883b78019407517cf32a33..162b93214965435d395a95b437162d49a49c935f 100644 (file)
@@ -250,11 +250,14 @@ static struct irq_chip iop13xx_irqchip4 = {
        .unmask = iop13xx_irq_unmask3,
 };
 
+extern void iop_init_cp6_handler(void);
+
 void __init iop13xx_init_irq(void)
 {
        unsigned int i;
 
        u32 cp_flags = iop13xx_cp6_save();
+       iop_init_cp6_handler();
 
        /* disable all interrupts */
        write_intctl_0(0);
index 3ec1cd5c4f99733e4b1e76a9116f27b6040709b9..8b0ac5590ae4611ad2ac519b220dd75bde0b33fd 100644 (file)
@@ -60,6 +60,8 @@ void __init iop32x_init_irq(void)
 {
        int i;
 
+       iop_init_cp6_handler();
+
        intctl_write(0);
        intstr_write(0);
        if (machine_is_glantank() ||
index 00b37f32d72e0c9a9314d93412850babd7c8c926..effbe6b782d04b2dc3d7f6f0abbc5839013ba044 100644 (file)
@@ -110,6 +110,8 @@ void __init iop33x_init_irq(void)
 {
        int i;
 
+       iop_init_cp6_handler();
+
        intctl0_write(0);
        intctl1_write(0);
        intstr0_write(0);
index 23da00b11517768c9129a418492c8eafb0ffd3cb..3250d732a17142fec31636d18a551df97b57e1ba 100644 (file)
@@ -2,7 +2,29 @@
 # Makefile for the linux kernel.
 #
 
-obj-y                  := gpio.o i2c.o pci.o setup.o time.o
-obj-m                  :=
-obj-n                  :=
-obj-                   :=
+obj-y :=
+
+# IOP32X
+obj-$(CONFIG_ARCH_IOP32X) += gpio.o
+obj-$(CONFIG_ARCH_IOP32X) += i2c.o
+obj-$(CONFIG_ARCH_IOP32X) += pci.o
+obj-$(CONFIG_ARCH_IOP32X) += setup.o
+obj-$(CONFIG_ARCH_IOP32X) += time.o
+obj-$(CONFIG_ARCH_IOP32X) += io.o
+obj-$(CONFIG_ARCH_IOP32X) += cp6.o
+
+# IOP33X
+obj-$(CONFIG_ARCH_IOP33X) += gpio.o
+obj-$(CONFIG_ARCH_IOP33X) += i2c.o
+obj-$(CONFIG_ARCH_IOP33X) += pci.o
+obj-$(CONFIG_ARCH_IOP33X) += setup.o
+obj-$(CONFIG_ARCH_IOP33X) += time.o
+obj-$(CONFIG_ARCH_IOP33X) += io.o
+obj-$(CONFIG_ARCH_IOP33X) += cp6.o
+
+# IOP13XX
+obj-$(CONFIG_ARCH_IOP13XX) += cp6.o
+
+obj-m                  :=
+obj-n                  :=
+obj-                   :=
diff --git a/arch/arm/plat-iop/cp6.c b/arch/arm/plat-iop/cp6.c
new file mode 100644 (file)
index 0000000..9612a87
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * IOP Coprocessor-6 access handler
+ * Copyright (c) 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 <asm/traps.h>
+
+static int cp6_trap(struct pt_regs *regs, unsigned int instr)
+{
+       u32 temp;
+
+        /* enable cp6 access */
+        asm volatile (
+               "mrc    p15, 0, %0, c15, c1, 0\n\t"
+               "orr    %0, %0, #(1 << 6)\n\t"
+               "mcr    p15, 0, %0, c15, c1, 0\n\t"
+               : "=r"(temp));
+
+       return 0;
+}
+
+/* permit kernel space cp6 access
+ * deny user space cp6 access
+ */
+static struct undef_hook cp6_hook = {
+       .instr_mask     = 0x0f000ff0,
+       .instr_val      = 0x0e000610,
+       .cpsr_mask      = MODE_MASK,
+       .cpsr_val       = SVC_MODE,
+       .fn             = cp6_trap,
+};
+
+void __init iop_init_cp6_handler(void)
+{
+       register_undef_hook(&cp6_hook);
+}
diff --git a/arch/arm/plat-iop/io.c b/arch/arm/plat-iop/io.c
new file mode 100644 (file)
index 0000000..f7eccec
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * iop3xx custom ioremap implementation
+ * Copyright (c) 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 __iop3xx_ioremap(unsigned long cookie, size_t size,
+       unsigned long flags)
+{
+       void __iomem * retval;
+
+       switch (cookie) {
+       case IOP3XX_PCI_LOWER_IO_PA ... IOP3XX_PCI_UPPER_IO_PA:
+               retval = (void *) IOP3XX_PCI_IO_PHYS_TO_VIRT(cookie);
+               break;
+       case IOP3XX_PERIPHERAL_PHYS_BASE ... IOP3XX_PERIPHERAL_UPPER_PA:
+               retval = (void *) IOP3XX_PMMR_PHYS_TO_VIRT(cookie);
+               break;
+       default:
+               retval = __ioremap(cookie, size, flags);
+       }
+
+       return retval;
+}
+EXPORT_SYMBOL(__iop3xx_ioremap);
+
+void __iop3xx_iounmap(void __iomem *addr)
+{
+       extern void __iounmap(volatile void __iomem *addr);
+
+       switch ((u32) addr) {
+       case IOP3XX_PCI_LOWER_IO_VA ... IOP3XX_PCI_UPPER_IO_VA:
+       case IOP3XX_PERIPHERAL_VIRT_BASE ... IOP3XX_PERIPHERAL_UPPER_VA:
+               goto skip;
+       }
+       __iounmap(addr);
+
+skip:
+       return;
+}
+EXPORT_SYMBOL(__iop3xx_iounmap);
index e647812654f2c0bcdf0b47c76c83e807419414a8..b5f6ec35aafb59e2b9fd1597e615e7000a157769 100644 (file)
@@ -196,8 +196,8 @@ int iop3xx_pci_setup(int nr, struct pci_sys_data *sys)
        if (!res)
                panic("PCI: unable to alloc resources");
 
-       res[0].start = IOP3XX_PCI_LOWER_IO_VA;
-       res[0].end   = IOP3XX_PCI_LOWER_IO_VA + IOP3XX_PCI_IO_WINDOW_SIZE - 1;
+       res[0].start = IOP3XX_PCI_LOWER_IO_PA;
+       res[0].end   = IOP3XX_PCI_LOWER_IO_PA + IOP3XX_PCI_IO_WINDOW_SIZE - 1;
        res[0].name  = "IOP3XX PCI I/O Space";
        res[0].flags = IORESOURCE_IO;
        request_resource(&ioport_resource, &res[0]);
@@ -209,7 +209,7 @@ int iop3xx_pci_setup(int nr, struct pci_sys_data *sys)
        request_resource(&iomem_resource, &res[1]);
 
        sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - IOP3XX_PCI_LOWER_MEM_BA;
-       sys->io_offset  = IOP3XX_PCI_LOWER_IO_VA - IOP3XX_PCI_LOWER_IO_BA;
+       sys->io_offset  = IOP3XX_PCI_LOWER_IO_PA - IOP3XX_PCI_LOWER_IO_BA;
 
        sys->resource[0] = &res[0];
        sys->resource[1] = &res[1];
index d108ab4974cc222bfb433b585868ba6b2f48b3af..b70a7f7daacc034e4457973eeecd5ae01faa958f 100644 (file)
@@ -84,7 +84,7 @@ iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
         * Every time unit enable is asserted, GPOD needs to be cleared
         * on IOP3XX to avoid data corruption on the bus.
         */
-#ifdef CONFIG_PLAT_IOP
+#if defined(CONFIG_ARCH_IOP32X) || defined(CONFIG_ARCH_IOP33X)
        if (iop3xx_adap->id == 0) {
                gpio_line_set(IOP3XX_GPIO_LINE(7), GPIO_LOW);
                gpio_line_set(IOP3XX_GPIO_LINE(6), GPIO_LOW);
index 12d9ee02cde31c26c8421c38a70c140f97ac14a7..5f570a598a376919ba839da1750a7fe3f6bbe2ec 100644 (file)
 
 #include <asm/hardware.h>
 
-#define IO_SPACE_LIMIT         0xffffffff
+extern void __iomem * __ioremap(unsigned long, size_t, unsigned long);
+extern void __iomem *__iop3xx_ioremap(unsigned long cookie, size_t size,
+       unsigned long flags);
+extern void __iop3xx_iounmap(void __iomem *addr);
 
-#define __io(p)                        ((void __iomem *)(p))
+#define IO_SPACE_LIMIT         0xffffffff
+#define __io(p)                ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
 #define __mem_pci(a)           (a)
 
+#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
+#define __arch_iounmap(a)       __iop3xx_iounmap(a)
 
 #endif
index c017402bab965d52fcdc88f10aadd233e27f3004..1bb5071e1fa8b98b4c1549a6797aa1083cc21905 100644 (file)
 
 #include <asm/hardware.h>
 
+extern void __iomem * __ioremap(unsigned long, size_t, unsigned long);
+extern void __iomem *__iop3xx_ioremap(unsigned long cookie, size_t size,
+       unsigned long flags);
+extern void __iop3xx_iounmap(void __iomem *addr);
+
 #define IO_SPACE_LIMIT         0xffffffff
-#define __io(p)                        ((void __iomem *)(p))
+#define __io(p)                ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
 #define __mem_pci(a)           (a)
 
+#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
+#define __arch_iounmap(a)       __iop3xx_iounmap(a)
 
 #endif
index 13ac8a4cd01f6ba7fc070d88a6aa9023ac442f4f..c91b546e20ef8040419fbd86cb9170192581d915 100644 (file)
@@ -37,6 +37,13 @@ extern void gpio_line_set(int line, int value);
 #define IOP3XX_PERIPHERAL_PHYS_BASE    0xffffe000
 #define IOP3XX_PERIPHERAL_VIRT_BASE    0xfeffe000
 #define IOP3XX_PERIPHERAL_SIZE         0x00002000
+#define IOP3XX_PERIPHERAL_UPPER_PA (IOP3XX_PERIPHERAL_PHYS_BASE +\
+                                       IOP3XX_PERIPHERAL_SIZE - 1)
+#define IOP3XX_PERIPHERAL_UPPER_VA (IOP3XX_PERIPHERAL_VIRT_BASE +\
+                                       IOP3XX_PERIPHERAL_SIZE - 1)
+#define IOP3XX_PMMR_PHYS_TO_VIRT(addr) (u32) ((u32) addr -\
+                                       (IOP3XX_PERIPHERAL_PHYS_BASE\
+                                       - IOP3XX_PERIPHERAL_VIRT_BASE))
 #define IOP3XX_REG_ADDR(reg)           (IOP3XX_PERIPHERAL_VIRT_BASE + (reg))
 
 /* Address Translation Unit  */
@@ -258,12 +265,20 @@ extern void gpio_line_set(int line, int value);
 #define IOP3XX_PCI_LOWER_IO_PA         0x90000000
 #define IOP3XX_PCI_LOWER_IO_VA         0xfe000000
 #define IOP3XX_PCI_LOWER_IO_BA         (*IOP3XX_OIOWTVR)
+#define IOP3XX_PCI_UPPER_IO_PA         (IOP3XX_PCI_LOWER_IO_PA +\
+                                       IOP3XX_PCI_IO_WINDOW_SIZE - 1)
+#define IOP3XX_PCI_UPPER_IO_VA         (IOP3XX_PCI_LOWER_IO_VA +\
+                                       IOP3XX_PCI_IO_WINDOW_SIZE - 1)
+#define IOP3XX_PCI_IO_PHYS_TO_VIRT(addr) (((u32) addr -\
+                                       IOP3XX_PCI_LOWER_IO_PA) +\
+                                       IOP3XX_PCI_LOWER_IO_VA)
 
 
 #ifndef __ASSEMBLY__
 void iop3xx_map_io(void);
 void iop3xx_init_time(unsigned long);
 unsigned long iop3xx_gettimeoffset(void);
+void iop_init_cp6_handler(void);
 
 extern struct platform_device iop3xx_i2c0_device;
 extern struct platform_device iop3xx_i2c1_device;