Skip to content

Commit

Permalink
[ARM] 4184/1: iop: cp6 access handler (undef_hook)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Dan Williams authored and Russell King committed Feb 14, 2007
1 parent dfc544c commit 588ef76
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 5 deletions.
2 changes: 2 additions & 0 deletions arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
3 changes: 3 additions & 0 deletions arch/arm/mach-iop13xx/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions arch/arm/mach-iop32x/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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() ||
Expand Down
2 changes: 2 additions & 0 deletions arch/arm/mach-iop33x/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
30 changes: 26 additions & 4 deletions arch/arm/plat-iop/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,29 @@
# Makefile for the linux kernel.
#

obj-y := gpio.o i2c.o pci.o setup.o time.o io.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- :=
50 changes: 50 additions & 0 deletions arch/arm/plat-iop/cp6.c
Original file line number Diff line number Diff line change
@@ -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);
}
2 changes: 1 addition & 1 deletion drivers/i2c/busses/i2c-iop3xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions include/asm-arm/hardware/iop3xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ extern void gpio_line_set(int line, int value);
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;
Expand Down

0 comments on commit 588ef76

Please sign in to comment.