Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[ARM] 4184/1: iop: cp6 access handler (undef_hook)

Enable svc access to cp6 via an undefined instruction hook. Do not enable
access for usr code.

This patch also makes iop13xx select PLAT_IOP, this requires a small change
to drivers/i2c/busses/i2c-iop3xx.c.

Per Lennert Buytenhek's note, the cp6 trap routine is moved to arch/arm/plat-iop
Per Nicolas Pitre's note, the cp_wait is skipped since the latency to
return to the faulting function is longer than cp_wait.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by

Dan Williams and committed by
Russell King
588ef769 dfc544c7

+87 -5
+2
arch/arm/Kconfig
··· 233 233 234 234 config ARCH_IOP13XX 235 235 bool "IOP13xx-based" 236 + depends on MMU 237 + select PLAT_IOP 236 238 select PCI 237 239 help 238 240 Support for Intel's IOP13XX (XScale) family of processors.
+3
arch/arm/mach-iop13xx/irq.c
··· 250 250 .unmask = iop13xx_irq_unmask3, 251 251 }; 252 252 253 + extern void iop_init_cp6_handler(void); 254 + 253 255 void __init iop13xx_init_irq(void) 254 256 { 255 257 unsigned int i; 256 258 257 259 u32 cp_flags = iop13xx_cp6_save(); 260 + iop_init_cp6_handler(); 258 261 259 262 /* disable all interrupts */ 260 263 write_intctl_0(0);
+2
arch/arm/mach-iop32x/irq.c
··· 60 60 { 61 61 int i; 62 62 63 + iop_init_cp6_handler(); 64 + 63 65 intctl_write(0); 64 66 intstr_write(0); 65 67 if (machine_is_glantank() ||
+2
arch/arm/mach-iop33x/irq.c
··· 110 110 { 111 111 int i; 112 112 113 + iop_init_cp6_handler(); 114 + 113 115 intctl0_write(0); 114 116 intctl1_write(0); 115 117 intstr0_write(0);
+26 -4
arch/arm/plat-iop/Makefile
··· 2 2 # Makefile for the linux kernel. 3 3 # 4 4 5 - obj-y := gpio.o i2c.o pci.o setup.o time.o io.o 6 - obj-m := 7 - obj-n := 8 - obj- := 5 + obj-y := 6 + 7 + # IOP32X 8 + obj-$(CONFIG_ARCH_IOP32X) += gpio.o 9 + obj-$(CONFIG_ARCH_IOP32X) += i2c.o 10 + obj-$(CONFIG_ARCH_IOP32X) += pci.o 11 + obj-$(CONFIG_ARCH_IOP32X) += setup.o 12 + obj-$(CONFIG_ARCH_IOP32X) += time.o 13 + obj-$(CONFIG_ARCH_IOP32X) += io.o 14 + obj-$(CONFIG_ARCH_IOP32X) += cp6.o 15 + 16 + # IOP33X 17 + obj-$(CONFIG_ARCH_IOP33X) += gpio.o 18 + obj-$(CONFIG_ARCH_IOP33X) += i2c.o 19 + obj-$(CONFIG_ARCH_IOP33X) += pci.o 20 + obj-$(CONFIG_ARCH_IOP33X) += setup.o 21 + obj-$(CONFIG_ARCH_IOP33X) += time.o 22 + obj-$(CONFIG_ARCH_IOP33X) += io.o 23 + obj-$(CONFIG_ARCH_IOP33X) += cp6.o 24 + 25 + # IOP13XX 26 + obj-$(CONFIG_ARCH_IOP13XX) += cp6.o 27 + 28 + obj-m := 29 + obj-n := 30 + obj- :=
+50
arch/arm/plat-iop/cp6.c
··· 1 + /* 2 + * IOP Coprocessor-6 access handler 3 + * Copyright (c) 2006, Intel Corporation. 4 + * 5 + * This program is free software; you can redistribute it and/or modify it 6 + * under the terms and conditions of the GNU General Public License, 7 + * version 2, as published by the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope it will be useful, but WITHOUT 10 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 + * more details. 13 + * 14 + * You should have received a copy of the GNU General Public License along with 15 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 16 + * Place - Suite 330, Boston, MA 02111-1307 USA. 17 + * 18 + */ 19 + #include <linux/init.h> 20 + #include <asm/traps.h> 21 + 22 + static int cp6_trap(struct pt_regs *regs, unsigned int instr) 23 + { 24 + u32 temp; 25 + 26 + /* enable cp6 access */ 27 + asm volatile ( 28 + "mrc p15, 0, %0, c15, c1, 0\n\t" 29 + "orr %0, %0, #(1 << 6)\n\t" 30 + "mcr p15, 0, %0, c15, c1, 0\n\t" 31 + : "=r"(temp)); 32 + 33 + return 0; 34 + } 35 + 36 + /* permit kernel space cp6 access 37 + * deny user space cp6 access 38 + */ 39 + static struct undef_hook cp6_hook = { 40 + .instr_mask = 0x0f000ff0, 41 + .instr_val = 0x0e000610, 42 + .cpsr_mask = MODE_MASK, 43 + .cpsr_val = SVC_MODE, 44 + .fn = cp6_trap, 45 + }; 46 + 47 + void __init iop_init_cp6_handler(void) 48 + { 49 + register_undef_hook(&cp6_hook); 50 + }
+1 -1
drivers/i2c/busses/i2c-iop3xx.c
··· 84 84 * Every time unit enable is asserted, GPOD needs to be cleared 85 85 * on IOP3XX to avoid data corruption on the bus. 86 86 */ 87 - #ifdef CONFIG_PLAT_IOP 87 + #if defined(CONFIG_ARCH_IOP32X) || defined(CONFIG_ARCH_IOP33X) 88 88 if (iop3xx_adap->id == 0) { 89 89 gpio_line_set(IOP3XX_GPIO_LINE(7), GPIO_LOW); 90 90 gpio_line_set(IOP3XX_GPIO_LINE(6), GPIO_LOW);
+1
include/asm-arm/hardware/iop3xx.h
··· 278 278 void iop3xx_map_io(void); 279 279 void iop3xx_init_time(unsigned long); 280 280 unsigned long iop3xx_gettimeoffset(void); 281 + void iop_init_cp6_handler(void); 281 282 282 283 extern struct platform_device iop3xx_i2c0_device; 283 284 extern struct platform_device iop3xx_i2c1_device;