diff options
Diffstat (limited to 'arch/m68knommu')
21 files changed, 765 insertions, 35 deletions
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig index 064f5913db1a..63be09e58d4a 100644 --- a/arch/m68knommu/Kconfig +++ b/arch/m68knommu/Kconfig @@ -59,6 +59,10 @@ config GENERIC_HARDIRQS bool default y +config GENERIC_HARDIRQS_NO__DO_IRQ + bool + default y + config GENERIC_CALIBRATE_DELAY bool default y diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c index 5c9ecd427090..959cb249c759 100644 --- a/arch/m68knommu/kernel/process.c +++ b/arch/m68knommu/kernel/process.c @@ -221,6 +221,10 @@ int copy_thread(unsigned long clone_flags, p->thread.usp = usp; p->thread.ksp = (unsigned long)childstack; + + if (clone_flags & CLONE_SETTLS) + task_thread_info(p)->tp_value = regs->d5; + /* * Must save the current SFC/DFC value, NOT the value when * the parent was last descheduled - RGH 10-08-96 diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c index 4d3828959fb0..85ed2f988f98 100644 --- a/arch/m68knommu/kernel/ptrace.c +++ b/arch/m68knommu/kernel/ptrace.c @@ -319,6 +319,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) } #endif + case PTRACE_GET_THREAD_AREA: + ret = put_user(task_thread_info(child)->tp_value, + (unsigned long __user *)data); + break; + default: ret = -EIO; break; diff --git a/arch/m68knommu/kernel/sys_m68k.c b/arch/m68knommu/kernel/sys_m68k.c index b67cbc735a9b..923dd4aab875 100644 --- a/arch/m68knommu/kernel/sys_m68k.c +++ b/arch/m68knommu/kernel/sys_m68k.c @@ -190,3 +190,39 @@ int kernel_execve(const char *filename, char *const argv[], char *const envp[]) : "d" (__a), "d" (__b), "d" (__c)); return __res; } + +asmlinkage unsigned long sys_get_thread_area(void) +{ + return current_thread_info()->tp_value; +} + +asmlinkage int sys_set_thread_area(unsigned long tp) +{ + current_thread_info()->tp_value = tp; + return 0; +} + +/* This syscall gets its arguments in A0 (mem), D2 (oldval) and + D1 (newval). */ +asmlinkage int +sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5, + unsigned long __user * mem) +{ + struct mm_struct *mm = current->mm; + unsigned long mem_value; + + down_read(&mm->mmap_sem); + + mem_value = *mem; + if (mem_value == oldval) + *mem = newval; + + up_read(&mm->mmap_sem); + return mem_value; +} + +asmlinkage int sys_atomic_barrier(void) +{ + /* no code needed for uniprocs */ + return 0; +} diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S index 486837efa3d7..56dd01ded148 100644 --- a/arch/m68knommu/kernel/syscalltable.S +++ b/arch/m68knommu/kernel/syscalltable.S @@ -351,6 +351,10 @@ ENTRY(sys_call_table) .long sys_pwritev /* 330 */ .long sys_rt_tgsigqueueinfo .long sys_perf_event_open + .long sys_get_thread_area + .long sys_set_thread_area + .long sys_atomic_cmpxchg_32 /* 335 */ + .long sys_atomic_barrier .rept NR_syscalls-(.-sys_call_table)/4 .long sys_ni_syscall diff --git a/arch/m68knommu/platform/5206/config.c b/arch/m68knommu/platform/5206/config.c index 9c335465e66d..bb31b3448c3d 100644 --- a/arch/m68knommu/platform/5206/config.c +++ b/arch/m68knommu/platform/5206/config.c @@ -17,6 +17,7 @@ #include <asm/coldfire.h> #include <asm/mcfsim.h> #include <asm/mcfuart.h> +#include <asm/mcfi2c.h> /***************************************************************************/ @@ -38,8 +39,45 @@ static struct platform_device m5206_uart = { .dev.platform_data = m5206_uart_platform, }; +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) +static struct resource m5206_i2c_resources[] = { + { + .start = MCFI2C_IOBASE, + .end = MCFI2C_IOBASE + MCFI2C_IOSIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = MCF_IRQ_I2C, + .end = MCF_IRQ_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mcfi2c_platform_data m5206_i2c_platform_data = { + .bitrate = 100000, +}; + +static struct platform_device m5206_i2c = { + .name = "i2c-mcf", + .id = 0, + .num_resources = ARRAY_SIZE(m5206_i2c_resources), + .resource = m5206_i2c_resources, + .dev.platform_data = &m5206_i2c_platform_data, +}; + +static void __init m5206_i2c_init(void) +{ + writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0, + MCF_MBAR + MCFSIM_I2CICR); + mcf_mapirq2imr(MCF_IRQ_I2C, MCFINTC_I2C); +} +#endif + static struct platform_device *m5206_devices[] __initdata = { &m5206_uart, +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + &m5206_i2c, +#endif }; /***************************************************************************/ @@ -101,6 +139,9 @@ void __init config_BSP(char *commandp, int size) mach_reset = m5206_cpu_reset; m5206_timers_init(); m5206_uarts_init(); +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + m5206_i2c_init(); +#endif /* Only support the external interrupts on their primary level */ mcf_mapirq2imr(25, MCFINTC_EINT1); diff --git a/arch/m68knommu/platform/5206e/config.c b/arch/m68knommu/platform/5206e/config.c index 942397984c66..a10d9d130387 100644 --- a/arch/m68knommu/platform/5206e/config.c +++ b/arch/m68knommu/platform/5206e/config.c @@ -17,6 +17,7 @@ #include <asm/mcfsim.h> #include <asm/mcfuart.h> #include <asm/mcfdma.h> +#include <asm/mcfi2c.h> /***************************************************************************/ @@ -38,8 +39,45 @@ static struct platform_device m5206e_uart = { .dev.platform_data = m5206e_uart_platform, }; +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) +static struct resource m5206e_i2c_resources[] = { + { + .start = MCFI2C_IOBASE, + .end = MCFI2C_IOBASE + MCFI2C_IOSIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = MCF_IRQ_I2C, + .end = MCF_IRQ_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mcfi2c_platform_data m5206e_i2c_platform_data = { + .bitrate = 100000, +}; + +static struct platform_device m5206e_i2c = { + .name = "i2c-mcf", + .id = 0, + .num_resources = ARRAY_SIZE(m5206e_i2c_resources), + .resource = m5206e_i2c_resources, + .dev.platform_data = &m5206e_i2c_platform_data, +}; + +static void __init m5206e_i2c_init(void) +{ + writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0, + MCF_MBAR + MCFSIM_I2CICR); + mcf_mapirq2imr(MCF_IRQ_I2C, MCFINTC_I2C); +} +#endif + static struct platform_device *m5206e_devices[] __initdata = { &m5206e_uart, +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + &m5206e_i2c, +#endif }; /***************************************************************************/ @@ -107,6 +145,9 @@ void __init config_BSP(char *commandp, int size) mach_reset = m5206e_cpu_reset; m5206e_timers_init(); m5206e_uarts_init(); +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + m5206e_i2c_init(); +#endif /* Only support the external interrupts on their primary level */ mcf_mapirq2imr(25, MCFINTC_EINT1); diff --git a/arch/m68knommu/platform/520x/config.c b/arch/m68knommu/platform/520x/config.c index 92614de42cd3..3206f7ecf27e 100644 --- a/arch/m68knommu/platform/520x/config.c +++ b/arch/m68knommu/platform/520x/config.c @@ -19,6 +19,7 @@ #include <asm/coldfire.h> #include <asm/mcfsim.h> #include <asm/mcfuart.h> +#include <asm/mcfi2c.h> /***************************************************************************/ @@ -74,9 +75,50 @@ static struct platform_device m520x_fec = { .resource = m520x_fec_resources, }; +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) +static struct resource m520x_i2c_resources[] = { + { + .start = MCFI2C_IOBASE, + .end = MCFI2C_IOBASE + MCFI2C_IOSIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = MCFINT_VECBASE + MCFINT_I2C, + .end = MCFINT_VECBASE + MCFINT_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mcfi2c_platform_data m520x_i2c_platform_data = { + .bitrate = 100000, +}; + +static struct platform_device m520x_i2c = { + .name = "i2c-mcf", + .id = 0, + .num_resources = ARRAY_SIZE(m520x_i2c_resources), + .resource = m520x_i2c_resources, + .dev.platform_data = &m520x_i2c_platform_data, +}; + +static void __init m520x_i2c_init(void) +{ + u8 par; + + /* setup Port FECI2C Pin Assignment Register for I2C */ + /* set PAR_SCL to SCL and PAR_SDA to SDA */ + par = readb(MCF_IPSBAR + MCF_GPIO_PAR_FECI2C); + par |= 0x0f; + writeb(par, MCF_IPSBAR + MCF_GPIO_PAR_FECI2C); +} +#endif + static struct platform_device *m520x_devices[] __initdata = { &m520x_uart, &m520x_fec, +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + &m520x_i2c, +#endif }; /***************************************************************************/ @@ -147,6 +189,9 @@ void __init config_BSP(char *commandp, int size) mach_reset = m520x_cpu_reset; m520x_uarts_init(); m520x_fec_init(); +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + m520x_i2c_init(); +#endif } /***************************************************************************/ diff --git a/arch/m68knommu/platform/523x/config.c b/arch/m68knommu/platform/523x/config.c index 6ba84f2aa397..05b4ab9996d7 100644 --- a/arch/m68knommu/platform/523x/config.c +++ b/arch/m68knommu/platform/523x/config.c @@ -20,6 +20,7 @@ #include <asm/coldfire.h> #include <asm/mcfsim.h> #include <asm/mcfuart.h> +#include <asm/mcfi2c.h> /***************************************************************************/ @@ -75,9 +76,51 @@ static struct platform_device m523x_fec = { .resource = m523x_fec_resources, }; +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) +static struct resource m523x_i2c_resources[] = { + { + .start = MCFI2C_IOBASE, + .end = MCFI2C_IOBASE + MCFI2C_IOSIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = MCFINT_VECBASE + MCFINT_I2C, + .end = MCFINT_VECBASE + MCFINT_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mcfi2c_platform_data m523x_i2c_platform_data = { + .bitrate = 100000, +}; + +static struct platform_device m523x_i2c = { + .name = "i2c-mcf", + .id = 0, + .num_resources = ARRAY_SIZE(m523x_i2c_resources), + .resource = m523x_i2c_resources, + .dev.platform_data = &m523x_i2c_platform_data, +}; + +static void __init m523x_i2c_init(void) +{ + u8 par; + + /* setup Port AS Pin Assignment Register for I2C */ + /* set PASPA0 to SCL and PASPA1 to SDA */ + par = readb(MCF_IPSBAR + MCFGPIO_PAR_FECI2C); + par |= 0x0f; + writeb(par, MCF_IPSBAR + MCFGPIO_PAR_FECI2C); +} + +#endif + static struct platform_device *m523x_devices[] __initdata = { &m523x_uart, &m523x_fec, +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + &m523x_i2c, +#endif }; /***************************************************************************/ @@ -114,6 +157,9 @@ void __init config_BSP(char *commandp, int size) static int __init init_BSP(void) { m523x_fec_init(); +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + m523x_i2c_init(); +#endif platform_add_devices(m523x_devices, ARRAY_SIZE(m523x_devices)); return 0; } diff --git a/arch/m68knommu/platform/5249/config.c b/arch/m68knommu/platform/5249/config.c index 646f5ba462fc..bd085427c43a 100644 --- a/arch/m68knommu/platform/5249/config.c +++ b/arch/m68knommu/platform/5249/config.c @@ -16,6 +16,7 @@ #include <asm/coldfire.h> #include <asm/mcfsim.h> #include <asm/mcfuart.h> +#include <asm/mcfi2c.h> /***************************************************************************/ @@ -37,8 +38,81 @@ static struct platform_device m5249_uart = { .dev.platform_data = m5249_uart_platform, }; +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) +static struct resource m5249_i2c0_resources[] = { + { + .start = MCFI2C_IOBASE, + .end = MCFI2C_IOBASE + MCFI2C_IOSIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = MCF_IRQ_I2C, + .end = MCF_IRQ_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource m5249_i2c1_resources[] = { + { + .start = MCFI2C_IOBASE2, + .end = MCFI2C_IOBASE2 + MCFI2C_IOSIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = MCFINTC2_I2C, + .end = MCFINTC2_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mcfi2c_platform_data m5249_i2c0_platform_data = { + .bitrate = 100000, +}; + +static struct mcfi2c_platform_data m5249_i2c1_platform_data = { + .bitrate = 100000, +}; + +static struct platform_device m5249_i2c[] = { + { + .name = "i2c-mcf", + .id = 0, + .num_resources = ARRAY_SIZE(m5249_i2c0_resources), + .resource = m5249_i2c0_resources, + .dev.platform_data = &m5249_i2c0_platform_data, + }, + { + .name = "i2c-mcf", + .id = 1, + .num_resources = ARRAY_SIZE(m5249_i2c1_resources), + .resource = m5249_i2c1_resources, + .dev.platform_data = &m5249_i2c1_platform_data, + }, +}; + +static void __init m5249_i2c_init(void) +{ + u32 pri; + + /* first I2C controller uses regular irq setup */ + writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0, + MCF_MBAR + MCFSIM_I2CICR); + mcf_mapirq2imr(MCF_IRQ_I2C, MCFINTC_I2C); + + /* second I2C controller is completely different */ + pri = readl(MCF_MBAR2 + MCFSIM2_INTLEVEL8); + pri &= ~MCFSIM2_INTPRI_62; + pri |= MCFSIM2_INTPRI_I2C; + writel(pri, MCF_MBAR2 + MCFSIM2_INTLEVEL8); +} +#endif + static struct platform_device *m5249_devices[] __initdata = { &m5249_uart, +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + &m5249_i2c[0], + &m5249_i2c[1], +#endif }; /***************************************************************************/ @@ -100,6 +174,9 @@ void __init config_BSP(char *commandp, int size) mach_reset = m5249_cpu_reset; m5249_timers_init(); m5249_uarts_init(); +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + m5249_i2c_init(); +#endif } /***************************************************************************/ diff --git a/arch/m68knommu/platform/5272/intc.c b/arch/m68knommu/platform/5272/intc.c index 7081e0a9720e..2889f7d7cf70 100644 --- a/arch/m68knommu/platform/5272/intc.c +++ b/arch/m68knommu/platform/5272/intc.c @@ -103,8 +103,26 @@ static void intc_irq_ack(unsigned int irq) static int intc_irq_set_type(unsigned int irq, unsigned int type) { - /* We can set the edge type here for external interrupts */ - return 0; + /* set the edge type for external interrupts */ + u32 pitr; + + if ((type != IRQF_TRIGGER_RISING) || (type != IRQF_TRIGGER_FALLING)) + return -EINVAL; + + switch (irq) { + case MCF_IRQ_EINT1 ... MCF_IRQ_EINT4: + case MCF_IRQ_EINT5 ... MCF_IRQ_EINT6: + pitr = __raw_readl(MCFSIM_PITR); + if (type & IRQF_TRIGGER_RISING) + pitr |= 1 << (96 - irq); + else + pitr &= ~(1 << (96 - irq)); + __raw_writel(pitr, MCFSIM_PITR); + + return 0; + default: + return -EINVAL; + } } static struct irq_chip intc_irq_chip = { @@ -128,11 +146,16 @@ void __init init_IRQ(void) writel(0x88888888, MCF_MBAR + MCFSIM_ICR4); for (irq = 0; (irq < NR_IRQS); irq++) { - irq_desc[irq].status = IRQ_DISABLED; - irq_desc[irq].action = NULL; - irq_desc[irq].depth = 1; - irq_desc[irq].chip = &intc_irq_chip; - intc_irq_set_type(irq, 0); + switch (irq) { + case MCF_IRQ_EINT1 ... MCF_IRQ_EINT4: + case MCF_IRQ_EINT5 ... MCF_IRQ_EINT6: + set_irq_chip_and_handler(irq, &intc_irq_chip, + handle_edge_irq); + break; + default: + set_irq_chip_and_handler(irq, &intc_irq_chip, + handle_level_irq); + break; + } } } - diff --git a/arch/m68knommu/platform/527x/config.c b/arch/m68knommu/platform/527x/config.c index fa51be172830..001fa362021c 100644 --- a/arch/m68knommu/platform/527x/config.c +++ b/arch/m68knommu/platform/527x/config.c @@ -20,6 +20,7 @@ #include <asm/coldfire.h> #include <asm/mcfsim.h> #include <asm/mcfuart.h> +#include <asm/mcfi2c.h> /***************************************************************************/ @@ -106,12 +107,67 @@ static struct platform_device m527x_fec[] = { }, }; +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) +static struct resource m527x_i2c_resources[] = { + { + .start = MCFI2C_IOBASE, + .end = MCFI2C_IOBASE + MCFI2C_IOSIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = MCFINT_VECBASE + MCFINT_I2C, + .end = MCFINT_VECBASE + MCFINT_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mcfi2c_platform_data m527x_i2c_platform_data = { + .bitrate = 100000, +}; + +static struct platform_device m527x_i2c = { + .name = "i2c-mcf", + .id = 0, + .num_resources = ARRAY_SIZE(m527x_i2c_resources), + .resource = m527x_i2c_resources, + .dev.platform_data = &m527x_i2c_platform_data, +}; + +#if defined(CONFIG_M5271) +static void __init m527x_i2c_init(void) +{ + u8 par; + + /* setup Port FECI2C Pin Assignment Register for I2C */ + /* set PAR_SCL to SCL and PAR_SDA to SDA */ + par = readb(MCF_IPSBAR + MCF_GPIO_PAR_FECI2C); + par |= 0x0f; + writeb(par, MCF_IPSBAR + MCF_GPIO_PAR_FECI2C); +} +#endif +#if defined(CONFIG_M5275) +static void __init m527x_i2c_init(void) +{ + u16 par; + + /* setup Port FECI2C Pin Assignment Register for I2C */ + /* set PAR_SCL to SCL and PAR_SDA to SDA */ + par = readw(MCF_IPSBAR + MCF_GPIO_PAR_FECI2C); + par |= 0x0f; + writew(par, MCF_IPSBAR + MCF_GPIO_PAR_FECI2C); +} +#endif +#endif + static struct platform_device *m527x_devices[] __initdata = { &m527x_uart, &m527x_fec[0], #ifdef CONFIG_FEC2 &m527x_fec[1], #endif +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + &m527x_i2c, +#endif }; /***************************************************************************/ @@ -187,6 +243,10 @@ void __init config_BSP(char *commandp, int size) mach_reset = m527x_cpu_reset; m527x_uarts_init(); m527x_fec_init(); +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + m527x_i2c_init(); +#endif + } /***************************************************************************/ diff --git a/arch/m68knommu/platform/528x/config.c b/arch/m68knommu/platform/528x/config.c index 6e608d1836f1..f7516d8ea08d 100644 --- a/arch/m68knommu/platform/528x/config.c +++ b/arch/m68knommu/platform/528x/config.c @@ -21,6 +21,7 @@ #include <asm/coldfire.h> #include <asm/mcfsim.h> #include <asm/mcfuart.h> +#include <asm/mcfi2c.h> /***************************************************************************/ @@ -76,10 +77,57 @@ static struct platform_device m528x_fec = { .resource = m528x_fec_resources, }; +#if defined(CONFIG_GPIO_PCF857X) || defined(CONFIG_GPIO_PCF857X_MODULE) +static struct pcf857x_platform_data pcf857x_data[] = { + { + .gpio_base = MCFGPIO_PIN_MAX, + }, +}; +#endif +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) +static struct resource m528x_i2c_resources[] = { + { + .start = MCFI2C_IOBASE, + .end = MCFI2C_IOBASE + MCFI2C_IOSIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = MCFINT_VECBASE + MCFINT_I2C, + .end = MCFINT_VECBASE + MCFINT_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mcfi2c_platform_data m528x_i2c_platform_data = { + .bitrate = 100000, +}; + +static struct platform_device m528x_i2c = { + .name = "i2c-mcf", + .id = 0, + .num_resources = ARRAY_SIZE(m528x_i2c_resources), + .resource = m528x_i2c_resources, + .dev.platform_data = &m528x_i2c_platform_data, +}; + +static void __init m528x_i2c_init(void) +{ + u16 paspar; + + /* setup Port AS Pin Assignment Register for I2C */ + /* set PASPA0 to SCL and PASPA1 to SDA */ + paspar = __raw_readw(MCF_IPSBAR + MCF5282_GPIO_PASPAR); + paspar |= 0xF; + __raw_writew(paspar, MCF_IPSBAR + MCF5282_GPIO_PASPAR); +} +#endif static struct platform_device *m528x_devices[] __initdata = { &m528x_uart, &m528x_fec, +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + &m528x_i2c, +#endif }; /***************************************************************************/ @@ -174,6 +222,9 @@ static int __init init_BSP(void) mach_reset = m528x_cpu_reset; m528x_uarts_init(); m528x_fec_init(); +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + m528x_i2c_init(); +#endif platform_add_devices(m528x_devices, ARRAY_SIZE(m528x_devices)); return 0; } diff --git a/arch/m68knommu/platform/5307/config.c b/arch/m68knommu/platform/5307/config.c index 00900ac06a9c..57f51ab3ae29 100644 --- a/arch/m68knommu/platform/5307/config.c +++ b/arch/m68knommu/platform/5307/config.c @@ -18,6 +18,7 @@ #include <asm/mcfsim.h> #include <asm/mcfuart.h> #include <asm/mcfwdebug.h> +#include <asm/mcfi2c.h> /***************************************************************************/ @@ -47,8 +48,45 @@ static struct platform_device m5307_uart = { .dev.platform_data = m5307_uart_platform, }; +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) +static struct resource m5307_i2c_resources[] = { + { + .start = MCFI2C_IOBASE, + .end = MCFI2C_IOBASE + MCFI2C_IOSIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = MCF_IRQ_I2C, + .end = MCF_IRQ_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mcfi2c_platform_data m5307_i2c_platform_data = { + .bitrate = 100000, +}; + +static struct platform_device m5307_i2c = { + .name = "i2c-mcf", + .id = 0, + .num_resources = ARRAY_SIZE(m5307_i2c_resources), + .resource = m5307_i2c_resources, + .dev.platform_data = &m5307_i2c_platform_data, +}; + +static void __init m5307_i2c_init(void) +{ + writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0, + MCF_MBAR + MCFSIM_I2CICR); + mcf_mapirq2imr(MCF_IRQ_I2C, MCFINTC_I2C); +} +#endif + static struct platform_device *m5307_devices[] __initdata = { &m5307_uart, +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + &m5307_i2c, +#endif }; /***************************************************************************/ @@ -117,7 +155,9 @@ void __init config_BSP(char *commandp, int size) mach_reset = m5307_cpu_reset; m5307_timers_init(); m5307_uarts_init(); - +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + m5307_i2c_init(); +#endif /* Only support the external interrupts on their primary level */ mcf_mapirq2imr(25, MCFINTC_EINT1); mcf_mapirq2imr(27, MCFINTC_EINT3); diff --git a/arch/m68knommu/platform/532x/config.c b/arch/m68knommu/platform/532x/config.c index d632948e64e5..7a0f14ec3460 100644 --- a/arch/m68knommu/platform/532x/config.c +++ b/arch/m68knommu/platform/532x/config.c @@ -27,6 +27,7 @@ #include <asm/mcfuart.h> #include <asm/mcfdma.h> #include <asm/mcfwdebug.h> +#include <asm/mcfi2c.h> /***************************************************************************/ @@ -82,9 +83,50 @@ static struct platform_device m532x_fec = { .resource = m532x_fec_resources, }; +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) +static struct resource m532x_i2c_resources[] = { + { + .start = MCFI2C_IOBASE, + .end = MCFI2C_IOBASE + MCFI2C_IOSIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = MCFINT_VECBASE + MCFINT_I2C, + .end = MCFINT_VECBASE + MCFINT_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mcfi2c_platform_data m532x_i2c_platform_data = { + .bitrate = 100000, +}; + +static struct platform_device m532x_i2c = { + .name = "i2c-mcf", + .id = 0, + .num_resources = ARRAY_SIZE(m532x_i2c_resources), + .resource = m532x_i2c_resources, + .dev.platform_data = &m532x_i2c_platform_data, +}; + +static void __init m532x_i2c_init(void) +{ + u8 par; + + /* setup Port AS Pin Assignment Register for I2C */ + /* set PASPA0 to SCL and PASPA1 to SDA */ + par = __raw_readb(MCF_GPIO_PAR_FECI2C); + par |= 0x0f; + __raw_writeb(par, MCF_GPIO_PAR_FECI2C); +} +#endif + static struct platform_device *m532x_devices[] __initdata = { &m532x_uart, &m532x_fec, +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + &m532x_i2c, +#endif }; /***************************************************************************/ @@ -158,6 +200,9 @@ static int __init init_BSP(void) { m532x_uarts_init(); m532x_fec_init(); +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + m532x_i2c_init(); +#endif platform_add_devices(m532x_devices, ARRAY_SIZE(m532x_devices)); return 0; } diff --git a/arch/m68knommu/platform/5407/config.c b/arch/m68knommu/platform/5407/config.c index 70ea789a400c..b8ceb3762c3f 100644 --- a/arch/m68knommu/platform/5407/config.c +++ b/arch/m68knommu/platform/5407/config.c @@ -17,6 +17,7 @@ #include <asm/coldfire.h> #include <asm/mcfsim.h> #include <asm/mcfuart.h> +#include <asm/mcfi2c.h> /***************************************************************************/ @@ -38,8 +39,45 @@ static struct platform_device m5407_uart = { .dev.platform_data = m5407_uart_platform, }; +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) +static struct resource m5407_i2c_resources[] = { + { + .start = MCFI2C_IOBASE, + .end = MCFI2C_IOBASE + MCFI2C_IOSIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = MCF_IRQ_I2C, + .end = MCF_IRQ_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mcfi2c_platform_data m5407_i2c_platform_data = { + .bitrate = 100000, +}; + +static struct platform_device m5407_i2c = { + .name = "i2c-mcf", + .id = 0, + .num_resources = ARRAY_SIZE(m5407_i2c_resources), + .resource = m5407_i2c_resources, + .dev.platform_data = &m5407_i2c_platform_data, +}; + +static void __init m5407_i2c_init(void) +{ + writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0, + MCF_MBAR + MCFSIM_I2CICR); + mcf_mapirq2imr(MCF_IRQ_I2C, MCFINTC_I2C); +} +#endif + static struct platform_device *m5407_devices[] __initdata = { &m5407_uart, +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + &m5407_i2c, +#endif }; /***************************************************************************/ @@ -101,6 +139,9 @@ void __init config_BSP(char *commandp, int size) mach_reset = m5407_cpu_reset; m5407_timers_init(); m5407_uarts_init(); +#if defined(CONFIG_I2C_MCF) || defined(CONFIG_I2C_MCF_MODULE) + m5407_i2c_init(); +#endif /* Only support the external interrupts on their primary level */ mcf_mapirq2imr(25, MCFINTC_EINT1); diff --git a/arch/m68knommu/platform/68328/ints.c b/arch/m68knommu/platform/68328/ints.c index b91ee85d4b5d..8a6a10212fb5 100644 --- a/arch/m68knommu/platform/68328/ints.c +++ b/arch/m68knommu/platform/68328/ints.c @@ -178,11 +178,7 @@ void __init init_IRQ(void) /* turn off all interrupts */ IMR = ~0; - for (i = 0; (i < NR_IRQS); i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 1; - irq_desc[i].chip = &intc_irq_chip; - } + for (i = 0; (i < NR_IRQS); i++) + set_irq_chip_and_handler(i, &intc_irq_chip, handle_level_irq); } diff --git a/arch/m68knommu/platform/68360/ints.c b/arch/m68knommu/platform/68360/ints.c index 1143f77caca4..9b94c52daa55 100644 --- a/arch/m68knommu/platform/68360/ints.c +++ b/arch/m68knommu/platform/68360/ints.c @@ -132,11 +132,7 @@ void init_IRQ(void) /* turn off all CPM interrupts */ pquicc->intr_cimr = 0x00000000; - for (i = 0; (i < NR_IRQS); i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 1; - irq_desc[i].chip = &intc_irq_chip; - } + for (i = 0; (i < NR_IRQS); i++) + set_irq_chip_and_handler(i, &intc_irq_chip, handle_level_irq); } diff --git a/arch/m68knommu/platform/coldfire/intc-2.c b/arch/m68knommu/platform/coldfire/intc-2.c index 5598c8b8661f..2863285927de 100644 --- a/arch/m68knommu/platform/coldfire/intc-2.c +++ b/arch/m68knommu/platform/coldfire/intc-2.c @@ -39,6 +39,15 @@ static void intc_irq_mask(unsigned int irq) val = __raw_readl(imraddr); __raw_writel(val | imrbit, imraddr); + + /* only on eport */ + if (irq >= MCFGPIO_IRQ_VECBASE || + irq < (MCFGPIO_IRQ_VECBASE + MCFGPIO_IRQ_MAX)) { + + u8 epier = __raw_readb(MCFEPORT_EPIER); + epier &= ~(1 << (irq - MCFGPIO_IRQ_VECBASE)); + __raw_writeb(epier, MCFEPORT_EPIER); + } } } @@ -64,13 +73,72 @@ static void intc_irq_unmask(unsigned int irq) val = __raw_readl(imraddr); __raw_writel(val & ~imrbit, imraddr); + + /* only on eport */ + if (irq >= MCFGPIO_IRQ_VECBASE || + irq < (MCFGPIO_IRQ_VECBASE + MCFGPIO_IRQ_MAX)) { + + u8 epier = __raw_readb(MCFEPORT_EPIER); + epier |= 1 << (irq - MCFGPIO_IRQ_VECBASE); + __raw_writeb(epier, MCFEPORT_EPIER); + } + } +} + +static void intc_irq_ack(unsigned int irq) +{ + /* only on eport */ + if (irq >= MCFGPIO_IRQ_VECBASE || + irq < (MCFGPIO_IRQ_VECBASE + MCFGPIO_IRQ_MAX)) { + u8 epfr = __raw_readb(MCFEPORT_EPFR); + epfr |= 1 << (irq - MCFGPIO_IRQ_VECBASE); + __raw_writeb(epfr, MCFEPORT_EPFR); } } +static int intc_irq_set_type(unsigned int irq, unsigned int flow_type) +{ + unsigned shift; + u16 eppar; + + /* only on eport */ + if (irq < MCFGPIO_IRQ_VECBASE || + irq >= (MCFGPIO_IRQ_VECBASE + MCFGPIO_IRQ_MAX)) + return -EINVAL; + + /* we only support TRIGGER_LOW or either (or both) RISING and FALLING */ + if ((flow_type & IRQF_TRIGGER_HIGH) || + ((flow_type & IRQF_TRIGGER_LOW) && + (flow_type & (IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING)))) + return -EINVAL; + + shift = (irq - MCFGPIO_IRQ_VECBASE) * 2; + + /* default to TRIGGER_LOW */ + eppar = 0; + if (flow_type & IRQF_TRIGGER_RISING) + eppar |= (0x01 << shift); + if (flow_type & IRQF_TRIGGER_FALLING) + eppar |= (0x02 << shift); + + if (eppar) + set_irq_handler(irq, handle_edge_irq); + else + set_irq_handler(irq, handle_level_irq); + + eppar |= (__raw_readw(MCFEPORT_EPPAR) & ~(0x3 << shift)); + __raw_writew(eppar, MCFEPORT_EPPAR); + + return 0; +} + static struct irq_chip intc_irq_chip = { .name = "CF-INTC", .mask = intc_irq_mask, .unmask = intc_irq_unmask, + .ack = intc_irq_ack, + .set_type = intc_irq_set_type, }; void __init init_IRQ(void) @@ -83,11 +151,7 @@ void __init init_IRQ(void) __raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL); __raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC1 + MCFINTC_IMRL); - for (irq = 0; (irq < NR_IRQS); irq++) { - irq_desc[irq].status = IRQ_DISABLED; - irq_desc[irq].action = NULL; - irq_desc[irq].depth = 1; - irq_desc[irq].chip = &intc_irq_chip; - } + for (irq = 0; (irq < NR_IRQS); irq++) + set_irq_chip_and_handler(irq, &intc_irq_chip, handle_level_irq); } diff --git a/arch/m68knommu/platform/coldfire/intc-simr.c b/arch/m68knommu/platform/coldfire/intc-simr.c index 1b01e79c2f63..cc5473f6c2c7 100644 --- a/arch/m68knommu/platform/coldfire/intc-simr.c +++ b/arch/m68knommu/platform/coldfire/intc-simr.c @@ -26,6 +26,15 @@ static void intc_irq_mask(unsigned int irq) else if ((irq < MCFINT_VECBASE + 128) && MCFINTC1_SIMR) __raw_writeb(irq - MCFINT_VECBASE - 64, MCFINTC1_SIMR); } + + /* only on eport */ + if (irq >= MCFGPIO_IRQ_VECBASE || + irq < (MCFGPIO_IRQ_VECBASE + MCFGPIO_IRQ_MAX)) { + + u8 epier = __raw_readb(MCFEPORT_EPIER); + epier &= ~(1 << (irq - MCFGPIO_IRQ_VECBASE)); + __raw_writeb(epier, MCFEPORT_EPIER); + } } static void intc_irq_unmask(unsigned int irq) @@ -36,10 +45,63 @@ static void intc_irq_unmask(unsigned int irq) else if ((irq < MCFINT_VECBASE + 128) && MCFINTC1_CIMR) __raw_writeb(irq - MCFINT_VECBASE - 64, MCFINTC1_CIMR); } + + /* only on eport */ + if (irq >= MCFGPIO_IRQ_VECBASE || + irq < (MCFGPIO_IRQ_VECBASE + MCFGPIO_IRQ_MAX)) { + + u8 epier = __raw_readb(MCFEPORT_EPIER); + epier |= 1 << (irq - MCFGPIO_IRQ_VECBASE); + __raw_writeb(epier, MCFEPORT_EPIER); + } +} + +static void intc_irq_ack(unsigned int irq) +{ + /* only on eport */ + if (irq >= MCFGPIO_IRQ_VECBASE || + irq < (MCFGPIO_IRQ_VECBASE + MCFGPIO_IRQ_MAX)) { + u8 epfr = __raw_readb(MCFEPORT_EPFR); + epfr |= 1 << (irq - MCFGPIO_IRQ_VECBASE); + __raw_writeb(epfr, MCFEPORT_EPFR); + } } static int intc_irq_set_type(unsigned int irq, unsigned int type) { + unsigned shift; + u16 eppar; + + /* only on eport */ + if (irq < MCFGPIO_IRQ_VECBASE || + irq >= (MCFGPIO_IRQ_VECBASE + MCFGPIO_IRQ_MAX)) + return -EINVAL; + + /* we only support TRIGGER_LOW or either (or both) RISING and FALLING */ + if ((type & IRQF_TRIGGER_HIGH) || + ((type & IRQF_TRIGGER_LOW) && + (type & (IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING)))) + return -EINVAL; + + shift = (irq - MCFGPIO_IRQ_VECBASE) * 2; + + /* default to TRIGGER_LOW */ + eppar = 0; + if (type & IRQF_TRIGGER_RISING) + eppar |= (0x01 << shift); + if (type & IRQF_TRIGGER_FALLING) + eppar |= (0x02 << shift); + + if (eppar) + set_irq_handler(irq, handle_edge_irq); + else + set_irq_handler(irq, handle_level_irq); + + eppar |= (__raw_readw(MCFEPORT_EPPAR) & ~(0x3 << shift)); + __raw_writew(eppar, MCFEPORT_EPPAR); + + if (irq >= MCFINT_VECBASE) { if (irq < MCFINT_VECBASE + 64) __raw_writeb(5, MCFINTC0_ICR0 + irq - MCFINT_VECBASE); @@ -53,6 +115,7 @@ static struct irq_chip intc_irq_chip = { .name = "CF-INTC", .mask = intc_irq_mask, .unmask = intc_irq_unmask, + .ack = intc_irq_ack, .set_type = intc_irq_set_type, }; @@ -68,10 +131,7 @@ void __init init_IRQ(void) __raw_writeb(0xff, MCFINTC1_SIMR); for (irq = 0; (irq < NR_IRQS); irq++) { - irq_desc[irq].status = IRQ_DISABLED; - irq_desc[irq].action = NULL; - irq_desc[irq].depth = 1; - irq_desc[irq].chip = &intc_irq_chip; + set_irq_chip_and_handler(irq, &intc_irq_chip, handle_level_irq); intc_irq_set_type(irq, 0); } } diff --git a/arch/m68knommu/platform/coldfire/intc.c b/arch/m68knommu/platform/coldfire/intc.c index a4560c86db71..ad392a515cd2 100644 --- a/arch/m68knommu/platform/coldfire/intc.c +++ b/arch/m68knommu/platform/coldfire/intc.c @@ -115,16 +115,69 @@ static void intc_irq_mask(unsigned int irq) { if (mcf_irq2imr[irq]) mcf_setimr(mcf_irq2imr[irq]); + +#if defined MCFINTC2_GPIOIRQ0 + if (irq >= MCFINTC2_GPIOIRQ0 && irq <= MCFINTC2_GPIOIRQ7) { + u32 gpiointenable = __raw_readl(MCFSIM2_GPIOINTENABLE); + + gpiointenable &= ~(0x101 << (irq - MCFINTC2_GPIOIRQ0)); + __raw_writel(gpiointenable, MCFSIM2_GPIOINTENABLE); + } +#endif } static void intc_irq_unmask(unsigned int irq) { if (mcf_irq2imr[irq]) mcf_clrimr(mcf_irq2imr[irq]); + +#if defined MCFINTC2_GPIOIRQ0 + if (irq >= MCFINTC2_GPIOIRQ0 && irq <= MCFINTC2_GPIOIRQ7) { + struct irq_desc *desc = irq_to_desc(irq); + u32 gpiointenable = __raw_readl(MCFSIM2_GPIOINTENABLE); + + if (desc->status & IRQF_TRIGGER_RISING) + gpiointenable |= 0x0001 << (irq - MCFINTC2_GPIOIRQ0); + if (desc->status & IRQF_TRIGGER_FALLING) + gpiointenable |= 0x0100 << (irq - MCFINTC2_GPIOIRQ0); + __raw_writel(gpiointenable, MCFSIM2_GPIOINTENABLE); + } +#endif +} + +static void intc_irq_ack(unsigned int irq) +{ +#if defined MCFINTC2_GPIOIRQ0 + if (irq >= MCFINTC2_GPIOIRQ0 && irq <= MCFINTC2_GPIOIRQ7) { + u32 gpiointclear = __raw_readl(MCFSIM2_GPIOINTCLEAR); + + gpiointclear |= 0x0101 << (irq - MCFINTC2_GPIOIRQ0); + __raw_writel(gpiointclear, MCFSIM2_GPIOINTCLEAR); + } +#endif } static int intc_irq_set_type(unsigned int irq, unsigned int type) { +#if defined MCFINTC2_GPIOIRQ0 + u32 gpiointenable; + + if (type & ~(IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) + return -EINVAL; + + if ((irq < MCFINTC2_GPIOIRQ0) || (irq > MCFINTC2_GPIOIRQ7)) + return -EINVAL; + + /* enable rising or falling or both */ + gpiointenable = __raw_readl(MCFSIM2_GPIOINTENABLE); + gpiointenable &= ~(0x101 << (irq - MCFINTC2_GPIOIRQ0)); + if (type & IRQF_TRIGGER_RISING) + gpiointenable |= 0x0001 << (irq - MCFINTC2_GPIOIRQ0); + if (type & IRQF_TRIGGER_FALLING) + gpiointenable |= 0x0100 << (irq - MCFINTC2_GPIOIRQ0); + __raw_writel(gpiointenable, MCFSIM2_GPIOINTENABLE); +#endif + return 0; } @@ -132,6 +185,7 @@ static struct irq_chip intc_irq_chip = { .name = "CF-INTC", .mask = intc_irq_mask, .unmask = intc_irq_unmask, + .ack = intc_irq_ack, .set_type = intc_irq_set_type, }; @@ -143,10 +197,7 @@ void __init init_IRQ(void) mcf_maskimr(0xffffffff); for (irq = 0; (irq < NR_IRQS); irq++) { - irq_desc[irq].status = IRQ_DISABLED; - irq_desc[irq].action = NULL; - irq_desc[irq].depth = 1; - irq_desc[irq].chip = &intc_irq_chip; + set_irq_chip_and_handler(irq, &intc_irq_chip, handle_level_irq); intc_irq_set_type(irq, 0); } } |