diff options
Diffstat (limited to 'arch/m68knommu/platform/5272')
-rw-r--r-- | arch/m68knommu/platform/5272/Makefile | 2 | ||||
-rw-r--r-- | arch/m68knommu/platform/5272/config.c | 78 | ||||
-rw-r--r-- | arch/m68knommu/platform/5272/gpio.c | 81 | ||||
-rw-r--r-- | arch/m68knommu/platform/5272/intc.c | 138 |
4 files changed, 228 insertions, 71 deletions
diff --git a/arch/m68knommu/platform/5272/Makefile b/arch/m68knommu/platform/5272/Makefile index 26135d92b34d..93673ef8e2c1 100644 --- a/arch/m68knommu/platform/5272/Makefile +++ b/arch/m68knommu/platform/5272/Makefile @@ -14,5 +14,5 @@ asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1 -obj-y := config.o +obj-y := config.o gpio.o intc.o diff --git a/arch/m68knommu/platform/5272/config.c b/arch/m68knommu/platform/5272/config.c index 5f95fcde05fd..59278c0887d0 100644 --- a/arch/m68knommu/platform/5272/config.c +++ b/arch/m68knommu/platform/5272/config.c @@ -20,12 +20,6 @@ /***************************************************************************/ -extern unsigned int mcf_timervector; -extern unsigned int mcf_profilevector; -extern unsigned int mcf_timerlevel; - -/***************************************************************************/ - /* * Some platforms need software versions of the GPIO data registers. */ @@ -37,11 +31,11 @@ unsigned char ledbank = 0xff; static struct mcf_platform_uart m5272_uart_platform[] = { { .mapbase = MCF_MBAR + MCFUART_BASE1, - .irq = 73, + .irq = MCF_IRQ_UART1, }, { .mapbase = MCF_MBAR + MCFUART_BASE2, - .irq = 74, + .irq = MCF_IRQ_UART2, }, { }, }; @@ -59,18 +53,18 @@ static struct resource m5272_fec_resources[] = { .flags = IORESOURCE_MEM, }, { - .start = 86, - .end = 86, + .start = MCF_IRQ_ERX, + .end = MCF_IRQ_ERX, .flags = IORESOURCE_IRQ, }, { - .start = 87, - .end = 87, + .start = MCF_IRQ_ETX, + .end = MCF_IRQ_ETX, .flags = IORESOURCE_IRQ, }, { - .start = 88, - .end = 88, + .start = MCF_IRQ_ENTC, + .end = MCF_IRQ_ENTC, .flags = IORESOURCE_IRQ, }, }; @@ -94,9 +88,6 @@ static void __init m5272_uart_init_line(int line, int irq) u32 v; if ((line >= 0) && (line < 2)) { - v = (line) ? 0x0e000000 : 0xe0000000; - writel(v, MCF_MBAR + MCFSIM_ICR2); - /* Enable the output lines for the serial ports */ v = readl(MCF_MBAR + MCFSIM_PBCNT); v = (v & ~0x000000ff) | 0x00000055; @@ -119,54 +110,6 @@ static void __init m5272_uarts_init(void) /***************************************************************************/ -static void __init m5272_fec_init(void) -{ - u32 imr; - - /* Unmask FEC interrupts at ColdFire interrupt controller */ - imr = readl(MCF_MBAR + MCFSIM_ICR3); - imr = (imr & ~0x00000fff) | 0x00000ddd; - writel(imr, MCF_MBAR + MCFSIM_ICR3); - - imr = readl(MCF_MBAR + MCFSIM_ICR1); - imr = (imr & ~0x0f000000) | 0x0d000000; - writel(imr, MCF_MBAR + MCFSIM_ICR1); -} - -/***************************************************************************/ - -void mcf_disableall(void) -{ - volatile unsigned long *icrp; - - icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); - icrp[0] = 0x88888888; - icrp[1] = 0x88888888; - icrp[2] = 0x88888888; - icrp[3] = 0x88888888; -} - -/***************************************************************************/ - -void mcf_autovector(unsigned int vec) -{ - /* Everything is auto-vectored on the 5272 */ -} - -/***************************************************************************/ - -void mcf_settimericr(int timer, int level) -{ - volatile unsigned long *icrp; - - if ((timer >= 1 ) && (timer <= 4)) { - icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); - *icrp = (0x8 | level) << ((4 - timer) * 4); - } -} - -/***************************************************************************/ - static void m5272_cpu_reset(void) { local_irq_disable(); @@ -190,8 +133,6 @@ void __init config_BSP(char *commandp, int size) *pivrp = 0x40; #endif - mcf_disableall(); - #if defined(CONFIG_NETtel) || defined(CONFIG_SCALES) /* Copy command line from FLASH to local buffer... */ memcpy(commandp, (char *) 0xf0004000, size); @@ -202,8 +143,6 @@ void __init config_BSP(char *commandp, int size) commandp[size-1] = 0; #endif - mcf_timervector = 69; - mcf_profilevector = 70; mach_reset = m5272_cpu_reset; } @@ -212,7 +151,6 @@ void __init config_BSP(char *commandp, int size) static int __init init_BSP(void) { m5272_uarts_init(); - m5272_fec_init(); platform_add_devices(m5272_devices, ARRAY_SIZE(m5272_devices)); return 0; } diff --git a/arch/m68knommu/platform/5272/gpio.c b/arch/m68knommu/platform/5272/gpio.c new file mode 100644 index 000000000000..459db89a89cc --- /dev/null +++ b/arch/m68knommu/platform/5272/gpio.c @@ -0,0 +1,81 @@ +/* + * Coldfire generic GPIO support + * + * (C) Copyright 2009, Steven King <sfking@fdwdc.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that 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. +*/ + +#include <linux/kernel.h> +#include <linux/init.h> + +#include <asm/coldfire.h> +#include <asm/mcfsim.h> +#include <asm/mcfgpio.h> + +static struct mcf_gpio_chip mcf_gpio_chips[] = { + { + .gpio_chip = { + .label = "PA", + .request = mcf_gpio_request, + .free = mcf_gpio_free, + .direction_input = mcf_gpio_direction_input, + .direction_output = mcf_gpio_direction_output, + .get = mcf_gpio_get_value, + .set = mcf_gpio_set_value, + .ngpio = 16, + }, + .pddr = MCFSIM_PADDR, + .podr = MCFSIM_PADAT, + .ppdr = MCFSIM_PADAT, + }, + { + .gpio_chip = { + .label = "PB", + .request = mcf_gpio_request, + .free = mcf_gpio_free, + .direction_input = mcf_gpio_direction_input, + .direction_output = mcf_gpio_direction_output, + .get = mcf_gpio_get_value, + .set = mcf_gpio_set_value, + .base = 16, + .ngpio = 16, + }, + .pddr = MCFSIM_PBDDR, + .podr = MCFSIM_PBDAT, + .ppdr = MCFSIM_PBDAT, + }, + { + .gpio_chip = { + .label = "PC", + .request = mcf_gpio_request, + .free = mcf_gpio_free, + .direction_input = mcf_gpio_direction_input, + .direction_output = mcf_gpio_direction_output, + .get = mcf_gpio_get_value, + .set = mcf_gpio_set_value, + .base = 32, + .ngpio = 16, + }, + .pddr = MCFSIM_PCDDR, + .podr = MCFSIM_PCDAT, + .ppdr = MCFSIM_PCDAT, + }, +}; + +static int __init mcf_gpio_init(void) +{ + unsigned i = 0; + while (i < ARRAY_SIZE(mcf_gpio_chips)) + (void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]); + return 0; +} + +core_initcall(mcf_gpio_init); diff --git a/arch/m68knommu/platform/5272/intc.c b/arch/m68knommu/platform/5272/intc.c new file mode 100644 index 000000000000..7081e0a9720e --- /dev/null +++ b/arch/m68knommu/platform/5272/intc.c @@ -0,0 +1,138 @@ +/* + * intc.c -- interrupt controller or ColdFire 5272 SoC + * + * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/io.h> +#include <asm/coldfire.h> +#include <asm/mcfsim.h> +#include <asm/traps.h> + +/* + * The 5272 ColdFire interrupt controller is nothing like any other + * ColdFire interrupt controller - it truly is completely different. + * Given its age it is unlikely to be used on any other ColdFire CPU. + */ + +/* + * The masking and priproty setting of interrupts on the 5272 is done + * via a set of 4 "Interrupt Controller Registers" (ICR). There is a + * loose mapping of vector number to register and internal bits, but + * a table is the easiest and quickest way to map them. + */ +struct irqmap { + unsigned char icr; + unsigned char index; + unsigned char ack; +}; + +static struct irqmap intc_irqmap[MCFINT_VECMAX - MCFINT_VECBASE] = { + /*MCF_IRQ_SPURIOUS*/ { .icr = 0, .index = 0, .ack = 0, }, + /*MCF_IRQ_EINT1*/ { .icr = MCFSIM_ICR1, .index = 28, .ack = 1, }, + /*MCF_IRQ_EINT2*/ { .icr = MCFSIM_ICR1, .index = 24, .ack = 1, }, + /*MCF_IRQ_EINT3*/ { .icr = MCFSIM_ICR1, .index = 20, .ack = 1, }, + /*MCF_IRQ_EINT4*/ { .icr = MCFSIM_ICR1, .index = 16, .ack = 1, }, + /*MCF_IRQ_TIMER1*/ { .icr = MCFSIM_ICR1, .index = 12, .ack = 0, }, + /*MCF_IRQ_TIMER2*/ { .icr = MCFSIM_ICR1, .index = 8, .ack = 0, }, + /*MCF_IRQ_TIMER3*/ { .icr = MCFSIM_ICR1, .index = 4, .ack = 0, }, + /*MCF_IRQ_TIMER4*/ { .icr = MCFSIM_ICR1, .index = 0, .ack = 0, }, + /*MCF_IRQ_UART1*/ { .icr = MCFSIM_ICR2, .index = 28, .ack = 0, }, + /*MCF_IRQ_UART2*/ { .icr = MCFSIM_ICR2, .index = 24, .ack = 0, }, + /*MCF_IRQ_PLIP*/ { .icr = MCFSIM_ICR2, .index = 20, .ack = 0, }, + /*MCF_IRQ_PLIA*/ { .icr = MCFSIM_ICR2, .index = 16, .ack = 0, }, + /*MCF_IRQ_USB0*/ { .icr = MCFSIM_ICR2, .index = 12, .ack = 0, }, + /*MCF_IRQ_USB1*/ { .icr = MCFSIM_ICR2, .index = 8, .ack = 0, }, + /*MCF_IRQ_USB2*/ { .icr = MCFSIM_ICR2, .index = 4, .ack = 0, }, + /*MCF_IRQ_USB3*/ { .icr = MCFSIM_ICR2, .index = 0, .ack = 0, }, + /*MCF_IRQ_USB4*/ { .icr = MCFSIM_ICR3, .index = 28, .ack = 0, }, + /*MCF_IRQ_USB5*/ { .icr = MCFSIM_ICR3, .index = 24, .ack = 0, }, + /*MCF_IRQ_USB6*/ { .icr = MCFSIM_ICR3, .index = 20, .ack = 0, }, + /*MCF_IRQ_USB7*/ { .icr = MCFSIM_ICR3, .index = 16, .ack = 0, }, + /*MCF_IRQ_DMA*/ { .icr = MCFSIM_ICR3, .index = 12, .ack = 0, }, + /*MCF_IRQ_ERX*/ { .icr = MCFSIM_ICR3, .index = 8, .ack = 0, }, + /*MCF_IRQ_ETX*/ { .icr = MCFSIM_ICR3, .index = 4, .ack = 0, }, + /*MCF_IRQ_ENTC*/ { .icr = MCFSIM_ICR3, .index = 0, .ack = 0, }, + /*MCF_IRQ_QSPI*/ { .icr = MCFSIM_ICR4, .index = 28, .ack = 0, }, + /*MCF_IRQ_EINT5*/ { .icr = MCFSIM_ICR4, .index = 24, .ack = 1, }, + /*MCF_IRQ_EINT6*/ { .icr = MCFSIM_ICR4, .index = 20, .ack = 1, }, + /*MCF_IRQ_SWTO*/ { .icr = MCFSIM_ICR4, .index = 16, .ack = 0, }, +}; + +static void intc_irq_mask(unsigned int irq) +{ + if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) { + u32 v; + irq -= MCFINT_VECBASE; + v = 0x8 << intc_irqmap[irq].index; + writel(v, MCF_MBAR + intc_irqmap[irq].icr); + } +} + +static void intc_irq_unmask(unsigned int irq) +{ + if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) { + u32 v; + irq -= MCFINT_VECBASE; + v = 0xd << intc_irqmap[irq].index; + writel(v, MCF_MBAR + intc_irqmap[irq].icr); + } +} + +static void intc_irq_ack(unsigned int irq) +{ + /* Only external interrupts are acked */ + if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) { + irq -= MCFINT_VECBASE; + if (intc_irqmap[irq].ack) { + u32 v; + v = 0xd << intc_irqmap[irq].index; + writel(v, MCF_MBAR + intc_irqmap[irq].icr); + } + } +} + +static int intc_irq_set_type(unsigned int irq, unsigned int type) +{ + /* We can set the edge type here for external interrupts */ + 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) +{ + int irq; + + init_vectors(); + + /* Mask all interrupt sources */ + writel(0x88888888, MCF_MBAR + MCFSIM_ICR1); + writel(0x88888888, MCF_MBAR + MCFSIM_ICR2); + writel(0x88888888, MCF_MBAR + MCFSIM_ICR3); + 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); + } +} + |