aboutsummaryrefslogtreecommitdiff
path: root/arch/m68knommu/platform/5272
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68knommu/platform/5272')
-rw-r--r--arch/m68knommu/platform/5272/Makefile2
-rw-r--r--arch/m68knommu/platform/5272/config.c78
-rw-r--r--arch/m68knommu/platform/5272/gpio.c81
-rw-r--r--arch/m68knommu/platform/5272/intc.c138
4 files changed, 228 insertions, 71 deletions
diff --git a/arch/m68knommu/platform/5272/Makefile b/arch/m68knommu/platform/5272/Makefile
index 26135d92b34..93673ef8e2c 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 5f95fcde05f..59278c0887d 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 00000000000..459db89a89c
--- /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 00000000000..7081e0a9720
--- /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);
+ }
+}
+