* [PATCH v3 1/9] lpc2k: Core support
2011-03-20 20:30 [PATCH v3 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
@ 2011-03-20 20:30 ` Ithamar R. Adema
2011-03-20 20:30 ` [PATCH v3 2/9] lpc2k: Exception vector handling Ithamar R. Adema
` (7 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Ithamar R. Adema @ 2011-03-20 20:30 UTC (permalink / raw)
To: linux-arm-kernel
Core files (including IRQ handling) for NXP LPC2K architecture.
Signed-off-by: Ithamar R. Adema <ithamar.adema@team-embedded.nl>
---
changes since v2:
* Removed GENERIC_TIME from selects.
changes since v1:
* implement arch_idle() using PCON register.
* implement arch_reset() using WDT block.
* Fix PLL 'N' mask in regs-scb.h
---
arch/arm/Kconfig | 13 ++++++
arch/arm/Makefile | 1 +
arch/arm/mach-lpc2k/Kconfig | 5 ++
arch/arm/mach-lpc2k/Makefile | 1 +
arch/arm/mach-lpc2k/Makefile.boot | 3 +
arch/arm/mach-lpc2k/include/mach/debug-macro.S | 19 +++++++++
arch/arm/mach-lpc2k/include/mach/entry-macro.S | 33 +++++++++++++++
arch/arm/mach-lpc2k/include/mach/hardware.h | 25 ++++++++++++
arch/arm/mach-lpc2k/include/mach/io.h | 18 ++++++++
arch/arm/mach-lpc2k/include/mach/irqs.h | 49 +++++++++++++++++++++++
arch/arm/mach-lpc2k/include/mach/memory.h | 15 +++++++
arch/arm/mach-lpc2k/include/mach/regs-scb.h | 42 +++++++++++++++++++
arch/arm/mach-lpc2k/include/mach/regs-wdt.h | 26 ++++++++++++
arch/arm/mach-lpc2k/include/mach/system.h | 51 ++++++++++++++++++++++++
arch/arm/mach-lpc2k/include/mach/timex.h | 15 +++++++
arch/arm/mach-lpc2k/include/mach/uncompress.h | 50 +++++++++++++++++++++++
arch/arm/mach-lpc2k/irq.c | 17 ++++++++
17 files changed, 383 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-lpc2k/Kconfig
create mode 100644 arch/arm/mach-lpc2k/Makefile
create mode 100644 arch/arm/mach-lpc2k/Makefile.boot
create mode 100644 arch/arm/mach-lpc2k/include/mach/debug-macro.S
create mode 100644 arch/arm/mach-lpc2k/include/mach/entry-macro.S
create mode 100644 arch/arm/mach-lpc2k/include/mach/hardware.h
create mode 100644 arch/arm/mach-lpc2k/include/mach/io.h
create mode 100644 arch/arm/mach-lpc2k/include/mach/irqs.h
create mode 100644 arch/arm/mach-lpc2k/include/mach/memory.h
create mode 100644 arch/arm/mach-lpc2k/include/mach/regs-scb.h
create mode 100644 arch/arm/mach-lpc2k/include/mach/regs-wdt.h
create mode 100644 arch/arm/mach-lpc2k/include/mach/system.h
create mode 100644 arch/arm/mach-lpc2k/include/mach/timex.h
create mode 100644 arch/arm/mach-lpc2k/include/mach/uncompress.h
create mode 100644 arch/arm/mach-lpc2k/irq.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 599e163..a74c200 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -490,6 +490,17 @@ config ARCH_LOKI
help
Support for the Marvell Loki (88RC8480) SoC.
+config ARCH_LPC2K
+ bool "NXP LPC2K Family"
+ depends on !MMU
+ select CPU_ARM7TDMI
+ select ARM_VIC
+ select GENERIC_CLOCKEVENTS
+ help
+ Support for NXP LPC2K family of SoCs. These SoCs are based on
+ an ARM7TDMI-S core, and have optional on-chip flash and SRAM,
+ also UART, I2C, SPI, SSP, CAN, RTC, and other peripherals.
+
config ARCH_LPC32XX
bool "NXP LPC32XX"
select CPU_ARM926T
@@ -931,6 +942,8 @@ source "arch/arm/mach-ks8695/Kconfig"
source "arch/arm/mach-loki/Kconfig"
+source "arch/arm/mach-lpc2k/Kconfig"
+
source "arch/arm/mach-lpc32xx/Kconfig"
source "arch/arm/mach-msm/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index c7d321a..9bf8421 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -151,6 +151,7 @@ machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx
machine-$(CONFIG_ARCH_KIRKWOOD) := kirkwood
machine-$(CONFIG_ARCH_KS8695) := ks8695
machine-$(CONFIG_ARCH_LOKI) := loki
+machine-$(CONFIG_ARCH_LPC2K) := lpc2k
machine-$(CONFIG_ARCH_LPC32XX) := lpc32xx
machine-$(CONFIG_ARCH_MMP) := mmp
machine-$(CONFIG_ARCH_MSM) := msm
diff --git a/arch/arm/mach-lpc2k/Kconfig b/arch/arm/mach-lpc2k/Kconfig
new file mode 100644
index 0000000..fad47b8
--- /dev/null
+++ b/arch/arm/mach-lpc2k/Kconfig
@@ -0,0 +1,5 @@
+if ARCH_LPC2K
+
+comment "LPC2K machines"
+
+endif
diff --git a/arch/arm/mach-lpc2k/Makefile b/arch/arm/mach-lpc2k/Makefile
new file mode 100644
index 0000000..546666b
--- /dev/null
+++ b/arch/arm/mach-lpc2k/Makefile
@@ -0,0 +1 @@
+obj-y := irq.o
diff --git a/arch/arm/mach-lpc2k/Makefile.boot b/arch/arm/mach-lpc2k/Makefile.boot
new file mode 100644
index 0000000..8b6b745
--- /dev/null
+++ b/arch/arm/mach-lpc2k/Makefile.boot
@@ -0,0 +1,3 @@
+ zreladdr-y := 0xa0008000
+params_phys-y := 0xa0000100
+initrd_phys-y := 0xa1800000
diff --git a/arch/arm/mach-lpc2k/include/mach/debug-macro.S b/arch/arm/mach-lpc2k/include/mach/debug-macro.S
new file mode 100644
index 0000000..0f581d3
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/debug-macro.S
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#include <mach/hardware.h>
+
+ .macro addruart, rp, rv
+ ldr \rp, =APB_UART0_BASE
+ ldr \rv, =APB_UART0_BASE
+ .endm
+
+#define UART_SHIFT 2
+#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-lpc2k/include/mach/entry-macro.S b/arch/arm/mach-lpc2k/include/mach/entry-macro.S
new file mode 100644
index 0000000..f6c7a46
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/entry-macro.S
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <mach/hardware.h>
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_preamble, base, tmp
+ ldr \base, =APH_VIC_BASE
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ ldr \irqstat, [\base, #0]
+ mov \irqnr, #0
+1001:
+ tst \irqstat, #1
+ bne 1002f
+ add \irqnr, \irqnr, #1
+ mov \irqstat, \irqstat, lsr #1
+ cmp \irqnr, #32
+ bcc 1001b
+1002:
+ .endm
diff --git a/arch/arm/mach-lpc2k/include/mach/hardware.h b/arch/arm/mach-lpc2k/include/mach/hardware.h
new file mode 100644
index 0000000..3463b47
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/hardware.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MACH_LPC2K_HARDWARE_H
+#define MACH_LPC2K_HARDWARE_H
+
+#include <asm/sizes.h>
+
+/* Default memory size if no ATAGS found */
+#define MEM_SIZE (SZ_32M)
+
+#define APB_WDT_BASE 0xe0000000
+#define APB_TIMER0_BASE 0xe0004000
+#define APB_TIMER1_BASE 0xe0008000
+#define APB_UART0_BASE 0xe000c000
+#define APB_SCB_BASE 0xe01fc000
+#define APH_VIC_BASE 0xfffff000
+
+#endif /* MACH_LPC2K_HARDWARE_H */
diff --git a/arch/arm/mach-lpc2k/include/mach/io.h b/arch/arm/mach-lpc2k/include/mach/io.h
new file mode 100644
index 0000000..e1a2b7f
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/io.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MACH_LPC2K_IO_H
+#define MACH_LPC2K_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __mem_pci(a) (a)
+#define __io(a) __typesafe_io(a)
+
+#endif /* MACH_LPC2K_IO_H */
diff --git a/arch/arm/mach-lpc2k/include/mach/irqs.h b/arch/arm/mach-lpc2k/include/mach/irqs.h
new file mode 100644
index 0000000..87b80dd
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/irqs.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MACH_LPC2K_IRQS_H
+#define MACH_LPC2K_IRQS_H
+
+/* VIC */
+#define IRQ_LPC2K_WDINT 0
+#define IRQ_LPC2K_RSV0 1
+#define IRQ_LPC2K_DBGRX 2
+#define IRQ_LPC2K_DBGTX 3
+#define IRQ_LPC2K_TIMER0 4
+#define IRQ_LPC2K_TIMER1 5
+#define IRQ_LPC2K_UART0 6
+#define IRQ_LPC2K_UART1 7
+#define IRQ_LPC2K_PWM0 8
+#define IRQ_LPC2K_I2C0 9
+#define IRQ_LPC2K_SPI0 10
+#define IRQ_LPC2K_SPI1 11
+#define IRQ_LPC2K_PLL 12
+#define IRQ_LPC2K_RTC 13
+#define IRQ_LPC2K_EINT0 14
+#define IRQ_LPC2K_EINT1 15
+#define IRQ_LPC2K_EINT2 16
+#define IRQ_LPC2K_EINT3 17
+#define IRQ_LPC2K_ADC 18
+#define IRQ_LPC2K_I2C1 19
+#define IRQ_LPC2K_BOD 20
+#define IRQ_LPC2K_ETH 21
+#define IRQ_LPC2K_USB 22
+#define IRQ_LPC2K_CAN 23
+#define IRQ_LPC2K_MCI 24
+#define IRQ_LPC2K_DMA 25
+#define IRQ_LPC2K_TIMER2 26
+#define IRQ_LPC2K_TIMER3 27
+#define IRQ_LPC2K_UART2 28
+#define IRQ_LPC2K_UART3 29
+#define IRQ_LPC2K_I2C2 30
+#define IRQ_LPC2K_I2S 31
+
+#define NR_IRQS 32
+
+#endif /* MACH_LPC2K_IRQS_H */
diff --git a/arch/arm/mach-lpc2k/include/mach/memory.h b/arch/arm/mach-lpc2k/include/mach/memory.h
new file mode 100644
index 0000000..6432147
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/memory.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MACH_LPC2K_MEMORY_H
+#define MACH_LPC2K_MEMORY_H
+
+#define PHYS_OFFSET 0xa0000000
+
+#endif /* MACH_LPC2K_MEMORY_H */
diff --git a/arch/arm/mach-lpc2k/include/mach/regs-scb.h b/arch/arm/mach-lpc2k/include/mach/regs-scb.h
new file mode 100644
index 0000000..d914de9
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/regs-scb.h
@@ -0,0 +1,42 @@
+/*
+ * System Control Block register definitions
+ *
+ * Copyright 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MACH_LPC2K_REGS_SCB_H
+#define MACH_LPC2K_REGS_SCB_H
+
+#define CLKSRCSEL 0x10c
+#define CLKSRC(x) ((x) & 3)
+#define PLLCON 0x080
+#define PLLCFG 0x084
+#define PLLSTAT 0x088
+#define M(x) (((x) & 0x7fff) + 1)
+#define N(x) ((((x) >> 16) & 0xff) + 1)
+#define PLLE (1 << 24)
+#define PLLC (1 << 25)
+#define PLLFEED 0x08c
+
+#define CCLKCFG 0x104
+#define CCLKSEL(x) ((x) & 0xff)
+#define USBCLKCFG 0x108
+#define USBSEL(x) ((x) & 0xf)
+#define IRCTRIM 0x1a4
+#define PCLKSEL0 0x1a8
+#define PCLKSEL1 0x1ac
+
+#define PCON 0x0c0
+#define PCON_PM0 (1 << 0)
+#define PCON_PM1 (1 << 1)
+#define PCON_PM2 (1 << 7)
+#define PCON_PMMASK (PCON_PM0 | PCON_PM1 | PCON_PM2)
+#define INTWAKE 0x144
+#define PCONP 0x0c4
+
+#endif /* MACH_LPC2K_REGS_SCB_H */
diff --git a/arch/arm/mach-lpc2k/include/mach/regs-wdt.h b/arch/arm/mach-lpc2k/include/mach/regs-wdt.h
new file mode 100644
index 0000000..eb6ab91
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/regs-wdt.h
@@ -0,0 +1,26 @@
+/*
+ * Watchdog Timer register definitions
+ *
+ * Copyright 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MACH_LPC2K_REGS_WDT_H
+#define MACH_LPC2K_REGS_WDT_H
+
+#define WDMOD 0x0000
+#define WDTC 0x0004
+#define WDFEED 0x0008
+#define WDTV 0x000a
+#define WDCLKSEL 0x0010
+
+#define WDMOD_WDEN (1 << 0)
+#define WDMOD_WDRESET (1 << 1)
+#define WDMOD_WDTOF (1 << 2)
+#define WDMOD_WDINT (1 << 3)
+
+#endif /* MACH_LPC2K_REGS_WDT_H */
diff --git a/arch/arm/mach-lpc2k/include/mach/system.h b/arch/arm/mach-lpc2k/include/mach/system.h
new file mode 100644
index 0000000..48209e1
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/system.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MACH_LPC2K_SYSTEM_H
+#define MACH_LPC2K_SYSTEM_H
+
+#include <mach/regs-scb.h>
+#include <mach/regs-wdt.h>
+#include <mach/hardware.h>
+
+static void arch_idle(void)
+{
+ /* Set PM0, IDL: idle mode */
+ iowrite32((ioread32(APB_SCB_BASE + PCON) & ~PCON_PMMASK) | PCON_PM0,
+ APB_SCB_BASE + PCON);
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+ switch (mode) {
+ case 's':
+ case 'h':
+ printk(KERN_CRIT "RESET: Rebooting system\n");
+
+ /* Disable interrupts */
+ local_irq_disable();
+
+ /* Setup WDT to fire on shortest allowed time */
+ iowrite32(0xff, APB_WDT_BASE + WDTC);
+ iowrite32(WDMOD_WDEN | WDMOD_WDRESET, APB_WDT_BASE + WDMOD);
+ iowrite32(0xaa, APB_WDT_BASE + WDFEED);
+ iowrite32(0x55, APB_WDT_BASE + WDFEED);
+ break;
+
+ default:
+ /* Do nothing */
+ break;
+ }
+
+ /* Wait for watchdog to reset system */
+ while (1)
+ ;
+}
+
+#endif /* MACH_LPC2K_SYSTEM_H */
diff --git a/arch/arm/mach-lpc2k/include/mach/timex.h b/arch/arm/mach-lpc2k/include/mach/timex.h
new file mode 100644
index 0000000..ba7c8dc
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/timex.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MACH_LPC2K_TIMEX_H
+#define MACH_LPC2K_TIMEX_H
+
+#define CLOCK_TICK_RATE (HZ * 100UL)
+
+#endif /* MACH_LPC2K_TIMEX_H */
diff --git a/arch/arm/mach-lpc2k/include/mach/uncompress.h b/arch/arm/mach-lpc2k/include/mach/uncompress.h
new file mode 100644
index 0000000..1724d72
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/uncompress.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * based on uncompress.h from mach-loki.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/serial_reg.h>
+#include <mach/hardware.h>
+
+#define SERIAL_BASE ((unsigned char *)APB_UART0_BASE)
+
+static void putc(const char c)
+{
+ unsigned char *base = SERIAL_BASE;
+ int i;
+
+ for (i = 0; i < 0x1000; i++) {
+ if (base[UART_LSR << 2] & UART_LSR_THRE)
+ break;
+ barrier();
+ }
+
+ base[UART_TX << 2] = c;
+}
+
+static void flush(void)
+{
+ unsigned char *base = SERIAL_BASE;
+ unsigned char mask;
+ int i;
+
+ mask = UART_LSR_TEMT | UART_LSR_THRE;
+
+ for (i = 0; i < 0x1000; i++) {
+ if ((base[UART_LSR << 2] & mask) == mask)
+ break;
+ barrier();
+ }
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/arch/arm/mach-lpc2k/irq.c b/arch/arm/mach-lpc2k/irq.c
new file mode 100644
index 0000000..58d291d
--- /dev/null
+++ b/arch/arm/mach-lpc2k/irq.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2011 Team Embeded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <asm/hardware/vic.h>
+#include <mach/hardware.h>
+
+void __init lpc2k_init_irq(void)
+{
+ vic_init((void __iomem *)APH_VIC_BASE, 0, ~0, 0);
+}
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 2/9] lpc2k: Exception vector handling
2011-03-20 20:30 [PATCH v3 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
2011-03-20 20:30 ` [PATCH v3 1/9] lpc2k: Core support Ithamar R. Adema
@ 2011-03-20 20:30 ` Ithamar R. Adema
2011-03-20 20:30 ` [PATCH v3 3/9] lpc2k: clk API Ithamar R. Adema
` (6 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Ithamar R. Adema @ 2011-03-20 20:30 UTC (permalink / raw)
To: linux-arm-kernel
The LPC2K optionally remaps the first 64 bytes of SRAM to address 0, to facilitate
writable low vectors. However, since it only remaps the first 64 bytes the stubs
can't be copied there and end up too far away from the vectors, requiring the
vectors to use an indirect jump instead of branch to get to the stubs.
Since now VECTOR_BASE is below PHYS_OFFSET, do not try to reserve the vector
page, as it will fail (and prevent the kernel from booting).
Also, commit 247055aa (6384/1: Remove the domain switching on ARMv6k/v7 CPUs) broke
the placement of vectors in the !MMU case, so fix this too.
Signed-off-by: Ithamar R. Adema <ithamar.adema@team-embedded.nl>
---
changes since v2:
* reworded reason for vector branch changes.
changes since v1:
* added comment to entry-armv.S vector #ifdef.
---
arch/arm/Kconfig | 1 +
arch/arm/kernel/entry-armv.S | 23 +++++++++++++++++++++++
arch/arm/kernel/traps.c | 2 +-
arch/arm/mm/nommu.c | 2 ++
4 files changed, 27 insertions(+), 1 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a74c200..7b5adab 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -186,6 +186,7 @@ config VECTORS_BASE
hex
default 0xffff0000 if MMU || CPU_HIGH_VECTOR
default DRAM_BASE if REMAP_VECTORS_TO_RAM
+ default 0x40000000 if ARCH_LPC2K
default 0x00000000
help
The base address of exception vectors.
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index e8d8856..65be7b1 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -1208,6 +1208,7 @@ __stubs_end:
.globl __vectors_start
__vectors_start:
+#ifndef CONFIG_ARCH_LPC2K
ARM( swi SYS_ERROR0 )
THUMB( svc #0 )
THUMB( nop )
@@ -1218,6 +1219,28 @@ __vectors_start:
W(b) vector_addrexcptn + stubs_offset
W(b) vector_irq + stubs_offset
W(b) vector_fiq + stubs_offset
+#else /* CONFIG_ARCH_LPC2K */
+ /*
+ * The LPC2K remaps 64 bytes of SRAM to address 0 for vectors. This
+ * means that the stubs can't be in the same page, and end up too far
+ * away from the vectors to use a branch instruction.
+ */
+ swi SYS_ERROR0
+ ldr pc, .vector_und
+ ldr pc, .vector_swi
+ ldr pc, .vector_pabt
+ ldr pc, .vector_dabt
+ ldr pc, .vector_addrexcptn
+ ldr pc, .vector_irq
+ ldr pc, .vector_fiq
+.vector_und: .word vector_und
+.vector_swi: .word vector_swi
+.vector_pabt: .word vector_pabt
+.vector_dabt: .word vector_dabt
+.vector_addrexcptn: .word vector_addrexcptn
+.vector_irq: .word vector_irq
+.vector_fiq: .word vector_fiq
+#endif
.globl __vectors_end
__vectors_end:
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 21ac43f..639c4c8 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -758,7 +758,7 @@ static void __init kuser_get_tls_init(unsigned long vectors)
void __init early_trap_init(void)
{
-#if defined(CONFIG_CPU_USE_DOMAINS)
+#if defined(CONFIG_CPU_USE_DOMAINS) || !defined(CONFIG_MMU)
unsigned long vectors = CONFIG_VECTORS_BASE;
#else
unsigned long vectors = (unsigned long)vectors_page;
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index 687d023..e3bec02 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -24,7 +24,9 @@ void __init arm_mm_memblock_reserve(void)
* some architectures which the DRAM is the exception vector to trap,
* alloc_page breaks with error, although it is not NULL, but "0."
*/
+#if PHYS_OFFSET <= CONFIG_VECTORS_BASE
memblock_reserve(CONFIG_VECTORS_BASE, PAGE_SIZE);
+#endif
}
/*
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 3/9] lpc2k: clk API
2011-03-20 20:30 [PATCH v3 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
2011-03-20 20:30 ` [PATCH v3 1/9] lpc2k: Core support Ithamar R. Adema
2011-03-20 20:30 ` [PATCH v3 2/9] lpc2k: Exception vector handling Ithamar R. Adema
@ 2011-03-20 20:30 ` Ithamar R. Adema
2011-03-22 0:16 ` Kevin Wells
2011-03-20 20:30 ` [PATCH v3 4/9] lpc2k: generic time and clockevents Ithamar R. Adema
` (5 subsequent siblings)
8 siblings, 1 reply; 12+ messages in thread
From: Ithamar R. Adema @ 2011-03-20 20:30 UTC (permalink / raw)
To: linux-arm-kernel
Implements clock API using the CLKDEV_LOOKUP common code.
Signed-off-by: Ithamar R. Adema <ithamar.adema@team-embedded.nl>
---
no changes since v2.
changes since v1:
* changed mutex into spinlock
* simplified clk_readl/clk_writel macros
---
arch/arm/Kconfig | 1 +
arch/arm/mach-lpc2k/Makefile | 2 +-
arch/arm/mach-lpc2k/clock.c | 360 +++++++++++++++++++++++++++++
arch/arm/mach-lpc2k/include/mach/clkdev.h | 17 ++
4 files changed, 379 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/mach-lpc2k/clock.c
create mode 100644 arch/arm/mach-lpc2k/include/mach/clkdev.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 7b5adab..b046a49 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -496,6 +496,7 @@ config ARCH_LPC2K
depends on !MMU
select CPU_ARM7TDMI
select ARM_VIC
+ select CLKDEV_LOOKUP
select GENERIC_CLOCKEVENTS
help
Support for NXP LPC2K family of SoCs. These SoCs are based on
diff --git a/arch/arm/mach-lpc2k/Makefile b/arch/arm/mach-lpc2k/Makefile
index 546666b..9eb0a6a 100644
--- a/arch/arm/mach-lpc2k/Makefile
+++ b/arch/arm/mach-lpc2k/Makefile
@@ -1 +1 @@
-obj-y := irq.o
+obj-y := clock.o irq.o
diff --git a/arch/arm/mach-lpc2k/clock.c b/arch/arm/mach-lpc2k/clock.c
new file mode 100644
index 0000000..7631c89
--- /dev/null
+++ b/arch/arm/mach-lpc2k/clock.c
@@ -0,0 +1,360 @@
+/*
+ * Copyright 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <linux/clkdev.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-scb.h>
+
+#define clk_readl(a) \
+ ioread32(APB_SCB_BASE + (a))
+#define clk_writel(v, a) \
+ iowrite32(v, APB_SCB_BASE + (a))
+
+struct clk {
+ int refcount;
+ struct clk *parent;
+ unsigned long rate;
+
+ u32 enable_mask;
+
+ long (*round_rate)(struct clk *clk, unsigned long rate);
+ int (*set_rate)(struct clk *clk, unsigned long rate);
+ unsigned long (*get_rate)(struct clk *clk);
+ int (*set_parent)(struct clk *clk, struct clk *parent);
+};
+
+static DEFINE_SPINLOCK(clk_lock);
+
+/*-------------------------------------------------------------------------
+ * Standard clock functions defined in include/linux/clk.h
+ *-------------------------------------------------------------------------*/
+
+static void __clk_disable(struct clk *clk)
+{
+ BUG_ON(clk->refcount == 0);
+
+ if (!(--clk->refcount)) {
+ if (clk->parent)
+ __clk_disable(clk->parent);
+
+ if (clk->enable_mask) {
+ /* Unconditionally disable the clock in hardware */
+ u32 value = clk_readl(PCONP);
+ clk_writel(value & ~clk->enable_mask, PCONP);
+ }
+ }
+}
+
+static int __clk_enable(struct clk *clk)
+{
+ int ret = 0;
+
+ if (clk->refcount++ == 0) {
+ if (clk->parent)
+ ret = __clk_enable(clk->parent);
+ if (ret)
+ return ret;
+ else if (clk->enable_mask) {
+ u32 value = clk_readl(PCONP);
+ clk_writel(value | clk->enable_mask, PCONP);
+ }
+ }
+
+ return 0;
+}
+
+/* This function increments the reference count on the clock and enables the
+ * clock if not already enabled. The parent clock tree is recursively enabled
+ */
+int clk_enable(struct clk *clk)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (!clk)
+ return -EINVAL;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ ret = __clk_enable(clk);
+ spin_unlock_irqrestore(&clk_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+/* This function decrements the reference count on the clock and disables
+ * the clock when reference count is 0. The parent clock tree is
+ * recursively disabled
+ */
+void clk_disable(struct clk *clk)
+{
+ unsigned long flags;
+
+ if (!clk)
+ return;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ __clk_disable(clk);
+ spin_unlock_irqrestore(&clk_lock, flags);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+/* Retrieve the *current* clock rate. If the clock itself
+ * does not provide a special calculation routine, ask
+ * its parent and so on, until one is able to return
+ * a valid clock rate
+ */
+unsigned long clk_get_rate(struct clk *clk)
+{
+ if (!clk)
+ return 0UL;
+
+ if (clk->get_rate)
+ return clk->get_rate(clk);
+
+ if (clk->parent)
+ return clk_get_rate(clk->parent);
+
+ return clk->rate;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+/* Round the requested clock rate to the nearest supported
+ * rate that is less than or equal to the requested rate.
+ * This is dependent on the clock's current parent.
+ */
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ if (!clk)
+ return 0;
+ if (!clk->round_rate)
+ return 0;
+
+ return clk->round_rate(clk, rate);
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+/* Set the clock to the requested clock rate. The rate must
+ * match a supported rate exactly based on what clk_round_rate returns
+ */
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long flags;
+ int ret = -EINVAL;
+
+ if (!clk)
+ return ret;
+ if (!clk->set_rate || !rate)
+ return ret;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ ret = clk->set_rate(clk, rate);
+ spin_unlock_irqrestore(&clk_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+/* Set the clock's parent to another clock source */
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ unsigned long flags;
+ struct clk *old;
+ int ret = -EINVAL;
+
+ if (!clk)
+ return ret;
+ if (!clk->set_parent || !parent)
+ return ret;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ old = clk->parent;
+ if (clk->refcount)
+ __clk_enable(parent);
+ ret = clk->set_parent(clk, parent);
+ if (ret)
+ old = parent;
+ if (clk->refcount)
+ __clk_disable(old);
+ spin_unlock_irqrestore(&clk_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+/* Retrieve the clock's parent clock source */
+struct clk *clk_get_parent(struct clk *clk)
+{
+ if (!clk)
+ return NULL;
+
+ return clk->parent;
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
+
+static struct clk clk_irc = {
+ .rate = 4000000
+};
+
+static struct clk clk_xtal;
+static struct clk clk_xrtc;
+
+static unsigned long pll_get_rate(struct clk *clk)
+{
+ unsigned long rate = clk_get_rate(clk->parent);
+ u32 pll_stat = clk_readl(PLLSTAT);
+
+ if (pll_stat & PLLE && pll_stat & PLLC)
+ rate = (2 * M(pll_stat) * rate) / N(pll_stat);
+
+ return rate;
+}
+
+static struct clk clk_pll = {
+ .parent = NULL,
+ .get_rate = pll_get_rate,
+};
+
+static unsigned long cpu_get_rate(struct clk *clk)
+{
+ unsigned long rate = clk_get_rate(clk->parent);
+ return rate / (CCLKSEL(clk_readl(CCLKCFG)) + 1);
+}
+
+static struct clk clk_cpu = {
+ .parent = &clk_pll,
+ .get_rate = cpu_get_rate,
+};
+
+static unsigned long usb_get_rate(struct clk *clk)
+{
+ unsigned long rate = clk_get_rate(clk->parent);
+ return rate / (USBSEL(clk_readl(USBCLKCFG)) + 1);
+}
+
+static struct clk clk_usb = {
+ .enable_mask = (1 << 31),
+ .parent = &clk_pll,
+ .get_rate = usb_get_rate,
+};
+
+static struct clk clk_apbpclk;
+
+static unsigned long pclkdiv[] = { 4, 1, 2, 8 };
+
+#define PERCLK(name, pnum) \
+ static unsigned long name ## _get_rate(struct clk *clk) \
+ { \
+ unsigned long rate = clk_get_rate(clk->parent); \
+ u32 val = clk_readl((pnum < 16) ? PCLKSEL0 : PCLKSEL1); \
+ val >>= (pnum < 16) ? pnum * 2 : (pnum - 16) * 2; \
+ return rate / pclkdiv[val & 3]; \
+ } \
+ struct clk clk_ ## name = { \
+ .parent = &clk_cpu, \
+ .enable_mask = (1 << pnum), \
+ .get_rate = name ## _get_rate, \
+ }
+
+PERCLK(timer0, 1);
+PERCLK(timer1, 2);
+PERCLK(uart0, 3);
+PERCLK(uart1, 4);
+PERCLK(pwm0, 5);
+PERCLK(pwm1, 6);
+PERCLK(i2c0, 7);
+PERCLK(spi, 8);
+PERCLK(prtc, 9);
+PERCLK(ssp1, 10);
+PERCLK(emc, 11);
+PERCLK(adc, 12);
+PERCLK(can1, 13);
+PERCLK(can2, 14);
+PERCLK(i2c1, 19);
+PERCLK(lcd, 20);
+PERCLK(ssp0, 21);
+PERCLK(timer2, 22);
+PERCLK(timer3, 23);
+PERCLK(uart2, 24);
+PERCLK(uart3, 25);
+PERCLK(i2c2, 26);
+PERCLK(i2s, 27);
+PERCLK(mci, 28);
+PERCLK(dma, 29);
+PERCLK(eth, 30);
+
+#define INIT_CK(dev, con, ck) \
+ { .dev_id = dev, .con_id = con, .clk = ck }
+
+
+/* clk_rtc is a virtual clock used as glue to adjust at runtime
+ * if we're using the normal peripheral clock or an extern osc.
+ */
+static struct clk clk_rtc;
+
+static struct clk_lookup clocks[] = {
+ INIT_CK(NULL, "apb_pclk", &clk_apbpclk),
+ INIT_CK(NULL, "irc", &clk_irc),
+ INIT_CK(NULL, "xtal", &clk_xtal),
+ INIT_CK(NULL, "pll", &clk_pll),
+ INIT_CK(NULL, "cpu", &clk_cpu),
+ INIT_CK(NULL, "usb", &clk_usb),
+ INIT_CK(NULL, "timer0", &clk_timer0),
+ INIT_CK(NULL, "timer1", &clk_timer1),
+ INIT_CK(NULL, "timer2", &clk_timer2),
+ INIT_CK(NULL, "timer3", &clk_timer3),
+ INIT_CK("lpc2k-pwm.0", NULL, &clk_pwm0),
+ INIT_CK("lpc2k-pwm.1", NULL, &clk_pwm1),
+ INIT_CK("lpc2k-adc", NULL, &clk_adc),
+ INIT_CK("lpc2k-i2c.0", NULL, &clk_i2c0),
+ INIT_CK("lpc2k-i2c.1", NULL, &clk_i2c1),
+ INIT_CK("lpc2k-i2c.2", NULL, &clk_i2c2),
+ INIT_CK("serial8250.0", NULL, &clk_uart0),
+ INIT_CK("serial8250.1", NULL, &clk_uart1),
+ INIT_CK("serial8250.2", NULL, &clk_uart2),
+ INIT_CK("serial8250.3", NULL, &clk_uart3),
+ INIT_CK("lpc2k-ohci", NULL, &clk_usb),
+ INIT_CK("lpc2k-spi.0", NULL, &clk_ssp0),
+ INIT_CK("lpc2k-spi.1", NULL, &clk_ssp1),
+ INIT_CK("lpc2k-eth", NULL, &clk_eth),
+ INIT_CK("lpc2k-rtc", NULL, &clk_rtc),
+ INIT_CK("ssp0", NULL, &clk_ssp0),
+ INIT_CK("ssp1", NULL, &clk_ssp1),
+ INIT_CK("mci", NULL, &clk_mci),
+ INIT_CK("lcd", NULL, &clk_lcd),
+ INIT_CK("dma", NULL, &clk_dma),
+};
+
+void __init lpc2k_init_clocks(unsigned long xtal, unsigned long rtc)
+{
+ struct clk *pll_src_clk[] = { &clk_irc, &clk_xtal, &clk_xrtc };
+ int i;
+
+ clk_xtal.rate = xtal;
+
+ clk_pll.parent = pll_src_clk[CLKSRC(clk_readl(CLKSRCSEL))];
+ clk_xrtc.rate = rtc;
+ /* If no external RTC osc. is specified, make RTC clock child
+ of peripheral RTC (CPU) clock */
+ clk_rtc.parent = rtc ? &clk_xrtc : &clk_prtc;
+
+ for (i = 0; i < ARRAY_SIZE(clocks); i++) {
+ pr_debug("clock '%s', rate %luHz\n",
+ clocks[i].con_id ? clocks[i].con_id : clocks[i].dev_id,
+ clk_get_rate(clocks[i].clk));
+
+ clkdev_add(&clocks[i]);
+ }
+}
diff --git a/arch/arm/mach-lpc2k/include/mach/clkdev.h b/arch/arm/mach-lpc2k/include/mach/clkdev.h
new file mode 100644
index 0000000..92267cc
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/clkdev.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef MACH_LPC2K_CLKDEV_H
+#define MACH_LPC2K_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif /* MACH_LPC2K_CLKDEV_H */
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 3/9] lpc2k: clk API
2011-03-20 20:30 ` [PATCH v3 3/9] lpc2k: clk API Ithamar R. Adema
@ 2011-03-22 0:16 ` Kevin Wells
2011-03-22 1:13 ` Ithamar R. Adema
0 siblings, 1 reply; 12+ messages in thread
From: Kevin Wells @ 2011-03-22 0:16 UTC (permalink / raw)
To: linux-arm-kernel
Hi Ithamar,
> +#define clk_readl(a) \
> + ioread32(APB_SCB_BASE + (a))
> +#define clk_writel(v, a) \
> + iowrite32(v, APB_SCB_BASE + (a))
> +
> +struct clk {
> + int refcount;
> + struct clk *parent;
> + unsigned long rate;
It looks like this rate field is only used in 3 clock
descriptors. It might save some space to get rid of this field
and associated code and have those 3 clocks just use functions
for get_rate() that return the direct value.
> +
> +static unsigned long pclkdiv[] = { 4, 1, 2, 8 };
> +
> +#define PERCLK(name, pnum) \
> + static unsigned long name ## _get_rate(struct clk *clk) \
> + { \
> + unsigned long rate = clk_get_rate(clk->parent); \
> + u32 val = clk_readl((pnum < 16) ? PCLKSEL0 : PCLKSEL1); \
> + val >>= (pnum < 16) ? pnum * 2 : (pnum - 16) * 2; \
> + return rate / pclkdiv[val & 3]; \
> + } \
> + struct clk clk_ ## name = { \
> + .parent = &clk_cpu, \
> + .enable_mask = (1 << pnum), \
> + .get_rate = name ## _get_rate, \
> + }
> +
This macro will generate multiple functions with different names but the same
code. Can the function be made common to the supported clocks and the macro
just handle clock descriptor setup?
> +PERCLK(timer0, 1);
> +PERCLK(timer1, 2);
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v3 3/9] lpc2k: clk API
2011-03-22 0:16 ` Kevin Wells
@ 2011-03-22 1:13 ` Ithamar R. Adema
0 siblings, 0 replies; 12+ messages in thread
From: Ithamar R. Adema @ 2011-03-22 1:13 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, 2011-03-22 at 01:16 +0100, Kevin Wells wrote:
> > +struct clk {
> > + int refcount;
> > + struct clk *parent;
> > + unsigned long rate;
>
> It looks like this rate field is only used in 3 clock
> descriptors. It might save some space to get rid of this field
> and associated code and have those 3 clocks just use functions
> for get_rate() that return the direct value.
Fair enough, I can update that....
> > +static unsigned long pclkdiv[] = { 4, 1, 2, 8 };
> > +
> > +#define PERCLK(name, pnum) \
> > + static unsigned long name ## _get_rate(struct clk *clk) \
> > + { \
> > + unsigned long rate = clk_get_rate(clk->parent); \
> > + u32 val = clk_readl((pnum < 16) ? PCLKSEL0 : PCLKSEL1); \
> > + val >>= (pnum < 16) ? pnum * 2 : (pnum - 16) * 2; \
> > + return rate / pclkdiv[val & 3]; \
> > + } \
> > + struct clk clk_ ## name = { \
> > + .parent = &clk_cpu, \
> > + .enable_mask = (1 << pnum), \
> > + .get_rate = name ## _get_rate, \
> > + }
> > +
>
> This macro will generate multiple functions with different names but the same
> code. Can the function be made common to the supported clocks and the macro
> just handle clock descriptor setup?
I could add a field to the clk struct to store it, since the peripheral
clock is the most common type of clk in the system, so it wouldn't waste
too much.
Regards,
Ithamar.
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v3 4/9] lpc2k: generic time and clockevents
2011-03-20 20:30 [PATCH v3 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
` (2 preceding siblings ...)
2011-03-20 20:30 ` [PATCH v3 3/9] lpc2k: clk API Ithamar R. Adema
@ 2011-03-20 20:30 ` Ithamar R. Adema
2011-03-20 20:30 ` [PATCH v3 5/9] lpc2k: gpiolib Ithamar R. Adema
` (4 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Ithamar R. Adema @ 2011-03-20 20:30 UTC (permalink / raw)
To: linux-arm-kernel
This code was mostly "borrowed" form the lpc32xx implementation.
Signed-off-by: Ithamar R. Adema <ithamar.adema@team-embedded.nl>
---
changes since v2:
* Removed clk_put() from init code.
* Added clk_get()/clk_enable() for timer0.
changes since v1:
* make use of clockevents_calc_mult_shift.
---
arch/arm/mach-lpc2k/Makefile | 2 +-
arch/arm/mach-lpc2k/time.c | 176 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 177 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/mach-lpc2k/time.c
diff --git a/arch/arm/mach-lpc2k/Makefile b/arch/arm/mach-lpc2k/Makefile
index 9eb0a6a..267432c 100644
--- a/arch/arm/mach-lpc2k/Makefile
+++ b/arch/arm/mach-lpc2k/Makefile
@@ -1 +1 @@
-obj-y := clock.o irq.o
+obj-y := clock.o irq.o time.o
diff --git a/arch/arm/mach-lpc2k/time.c b/arch/arm/mach-lpc2k/time.c
new file mode 100644
index 0000000..1d1c9d6
--- /dev/null
+++ b/arch/arm/mach-lpc2k/time.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2011 Team Embeded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ * Copyright (C) 2009 - 2010 NXP Semiconductors
+ * Copyright (C) 2009 Fontys University of Applied Sciences, Eindhoven
+ * Ed Schouten <e.schouten@fontys.nl>
+ * Laurens Timmermans <l.timmermans@fontys.nl>
+ *
+ * Based on timer code from plat-lpc32xx.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/time.h>
+#include <linux/err.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+
+#include <asm/mach/time.h>
+
+#include <mach/hardware.h>
+
+#define IR 0x00
+#define TCR 0x04
+#define TC 0x08
+#define PR 0x0c
+#define PC 0x10
+#define MCR 0x14
+#define MR0 0x18
+#define MR1 0x1c
+#define MR2 0x20
+#define CCR 0x28
+#define CR0 0x2c
+#define CR1 0x30
+#define CR2 0x34
+#define CR3 0x38
+#define EMR 0x3c
+#define CTCR 0x70
+
+#define IR_MR_SHIFT 0
+#define IR_CR_SHIFT 4
+
+#define TCR_EN (1 << 0)
+#define TCR_RESET (1 << 1)
+
+
+static void __iomem *timer0 = (void __iomem *)APB_TIMER0_BASE;
+static void __iomem *timer1 = (void __iomem *)APB_TIMER1_BASE;
+
+static cycle_t lpc2k_clksrc_read(struct clocksource *cs)
+{
+ return __raw_readl(timer1 + TC);
+}
+
+static struct clocksource lpc2k_clksrc = {
+ .name = "lpc2k_clksrc",
+ .rating = 300,
+ .read = lpc2k_clksrc_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int lpc2k_clkevt_next_event(unsigned long delta,
+ struct clock_event_device *dev)
+{
+ __raw_writel(TCR_RESET, timer0 + TCR);
+ __raw_writel(delta, timer0 + PR);
+ __raw_writel(TCR_EN, timer0 + TCR);
+
+ return 0;
+}
+
+static void lpc2k_clkevt_mode(enum clock_event_mode mode,
+ struct clock_event_device *dev)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ BUG();
+ break;
+
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ /*
+ * Disable the timer. When using oneshot, we must also
+ * disable the timer to wait for the first call to
+ * set_next_event().
+ */
+ __raw_writel(0, timer0 + TCR);
+ break;
+
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_RESUME:
+ break;
+ }
+}
+
+static struct clock_event_device lpc2k_clkevt = {
+ .name = "lpc2k_clkevt",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .rating = 300,
+ .set_next_event = lpc2k_clkevt_next_event,
+ .set_mode = lpc2k_clkevt_mode,
+};
+
+static irqreturn_t lpc2k_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = &lpc2k_clkevt;
+
+ /* Clear match */
+ __raw_writel((1 << IR_MR_SHIFT), timer0 + IR);
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction lpc2k_timer_irq = {
+ .name = "LPC2K Timer Tick",
+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = lpc2k_timer_interrupt,
+};
+
+/*
+ * The clock management driver isn't initialized at this point, so the
+ * clocks need to be enabled here manually and then tagged as used in
+ * the clock driver initialization
+ */
+static void __init lpc2k_timer_init(void)
+{
+ unsigned long rate;
+ struct clk *clk;
+
+ clk = clk_get(NULL, "timer1");
+ BUG_ON(IS_ERR(clk));
+ clk_enable(clk);
+
+ rate = clk_get_rate(clk);
+
+ clk = clk_get(NULL, "timer0");
+ BUG_ON(IS_ERR(clk));
+ clk_enable(clk);
+
+ /* Initial timer setup */
+ __raw_writel(0, timer0 + TCR);
+ __raw_writel(1 << IR_MR_SHIFT, timer0 + IR);
+ __raw_writel(1, timer0 + MR0);
+ __raw_writel(3 << 0, timer0 + MCR);
+
+ /* Setup tick interrupt */
+ setup_irq(IRQ_LPC2K_TIMER0, &lpc2k_timer_irq);
+
+ /* Setup the clockevent structure. */
+ clockevents_calc_mult_shift(&lpc2k_clkevt, rate, 5);
+ lpc2k_clkevt.max_delta_ns = clockevent_delta2ns(-1,
+ &lpc2k_clkevt);
+ lpc2k_clkevt.min_delta_ns = clockevent_delta2ns(1,
+ &lpc2k_clkevt) + 1;
+ lpc2k_clkevt.cpumask = cpumask_of(0);
+ clockevents_register_device(&lpc2k_clkevt);
+
+ /* Use timer1 as clock source. */
+ __raw_writel(TCR_RESET, timer1 + TCR);
+ __raw_writel(0, timer1 + PR);
+ __raw_writel(0, timer1 + MCR);
+ __raw_writel(TCR_EN, timer1 + TCR);
+ clocksource_register_hz(&lpc2k_clksrc, rate);
+}
+
+struct sys_timer lpc2k_timer = {
+ .init = &lpc2k_timer_init,
+};
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 5/9] lpc2k: gpiolib
2011-03-20 20:30 [PATCH v3 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
` (3 preceding siblings ...)
2011-03-20 20:30 ` [PATCH v3 4/9] lpc2k: generic time and clockevents Ithamar R. Adema
@ 2011-03-20 20:30 ` Ithamar R. Adema
2011-03-20 20:30 ` [PATCH v3 6/9] lpc2k: multifunction pin configuration Ithamar R. Adema
` (3 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Ithamar R. Adema @ 2011-03-20 20:30 UTC (permalink / raw)
To: linux-arm-kernel
gpiolib support, including gpio interrupts.
Signed-off-by: Ithamar R. Adema <ithamar.adema@team-embedded.nl>
---
changes since v2:
* Added LPC2K_GPIO(port,pin) macro and used similar macros
to minimize declarations of GPIO IRQs.
no changes since v1.
---
arch/arm/Kconfig | 1 +
arch/arm/mach-lpc2k/Makefile | 2 +-
arch/arm/mach-lpc2k/gpio.c | 265 +++++++++++++++++++++++++++
arch/arm/mach-lpc2k/include/mach/gpio.h | 25 +++
arch/arm/mach-lpc2k/include/mach/hardware.h | 2 +
arch/arm/mach-lpc2k/include/mach/irqs.h | 5 +-
6 files changed, 298 insertions(+), 2 deletions(-)
create mode 100644 arch/arm/mach-lpc2k/gpio.c
create mode 100644 arch/arm/mach-lpc2k/include/mach/gpio.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b046a49..a95a232 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -498,6 +498,7 @@ config ARCH_LPC2K
select ARM_VIC
select CLKDEV_LOOKUP
select GENERIC_CLOCKEVENTS
+ select ARCH_REQUIRE_GPIOLIB
help
Support for NXP LPC2K family of SoCs. These SoCs are based on
an ARM7TDMI-S core, and have optional on-chip flash and SRAM,
diff --git a/arch/arm/mach-lpc2k/Makefile b/arch/arm/mach-lpc2k/Makefile
index 267432c..89596a7 100644
--- a/arch/arm/mach-lpc2k/Makefile
+++ b/arch/arm/mach-lpc2k/Makefile
@@ -1 +1 @@
-obj-y := clock.o irq.o time.o
+obj-y := clock.o irq.o gpio.o time.o
diff --git a/arch/arm/mach-lpc2k/gpio.c b/arch/arm/mach-lpc2k/gpio.c
new file mode 100644
index 0000000..b55864c
--- /dev/null
+++ b/arch/arm/mach-lpc2k/gpio.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2011 Team Embeded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+
+#define LPC2K_GPIO_CHIP(name, base_gpio, nr_gpio, irqbase) \
+ { \
+ .chip = { \
+ .label = name, \
+ .direction_input = lpc2k_dir_input, \
+ .direction_output = lpc2k_dir_output, \
+ .to_irq = lpc2k_to_irq, \
+ .get = lpc2k_gpio_get, \
+ .set = lpc2k_gpio_set, \
+ .base = base_gpio, \
+ .ngpio = nr_gpio, \
+ }, \
+ .irq_base = irqbase, \
+ }
+
+#define to_lpc2k_gpio_chip(c) container_of(c, struct lpc2k_gpio_chip, chip)
+
+#define FIODIR 0x00
+#define FIOMASK 0x10
+#define FIOPIN 0x14
+#define FIOSET 0x18
+#define FIOCLR 0x1c
+
+struct lpc2k_gpio_chip {
+ struct gpio_chip chip;
+ void __iomem *regbase;
+ int irq_base;
+ spinlock_t gpio_lock;
+};
+
+static int lpc2k_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ struct lpc2k_gpio_chip *lpc2k_gpio = to_lpc2k_gpio_chip(chip);
+ if (lpc2k_gpio->irq_base < 0)
+ return -EINVAL;
+
+ return lpc2k_gpio->irq_base + offset;
+}
+
+static int lpc2k_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct lpc2k_gpio_chip *lpc2k_gpio = to_lpc2k_gpio_chip(chip);
+
+ return !!(readl(lpc2k_gpio->regbase + FIOPIN) & (1 << offset));
+}
+
+static void lpc2k_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+ struct lpc2k_gpio_chip *lpc2k_gpio = to_lpc2k_gpio_chip(chip);
+
+ writel(1 << offset, lpc2k_gpio->regbase + (val ? FIOSET : FIOCLR));
+}
+
+static int lpc2k_dir_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct lpc2k_gpio_chip *lpc2k_gpio = to_lpc2k_gpio_chip(chip);
+ void __iomem *pio = lpc2k_gpio->regbase + FIODIR;
+ unsigned int regval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&lpc2k_gpio->gpio_lock, flags);
+
+ regval = readl(pio);
+ regval &= ~(1 << offset);
+ writel(regval, pio);
+
+ spin_unlock_irqrestore(&lpc2k_gpio->gpio_lock, flags);
+
+ return 0;
+}
+
+static int lpc2k_dir_output(struct gpio_chip *chip, unsigned offset, int val)
+{
+ struct lpc2k_gpio_chip *lpc2k_gpio = to_lpc2k_gpio_chip(chip);
+ unsigned int regval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&lpc2k_gpio->gpio_lock, flags);
+
+ regval = readl(lpc2k_gpio->regbase + FIODIR);
+ regval |= (1 << offset);
+ writel(regval, lpc2k_gpio->regbase + FIODIR);
+
+ writel(1 << offset, lpc2k_gpio->regbase + (val ? FIOSET : FIOCLR));
+
+ spin_unlock_irqrestore(&lpc2k_gpio->gpio_lock, flags);
+
+ return 0;
+}
+
+static struct lpc2k_gpio_chip lpc2k_gpio[] = {
+ LPC2K_GPIO_CHIP("P0", 0, 32, IRQ_LPC2K_PORT0(0)),
+ LPC2K_GPIO_CHIP("P1", 32, 32, -1),
+ LPC2K_GPIO_CHIP("P2", 64, 32, IRQ_LPC2K_PORT2(0)),
+ LPC2K_GPIO_CHIP("P3", 96, 32, -1),
+ LPC2K_GPIO_CHIP("P4", 128, 32, -1),
+};
+
+#define IOINTSTAT 0x0080
+#define IO0INT 0x0084
+#define IO2INT 0x00a4
+
+#define IOINTSTATR 0x0000
+#define IOINTSTATF 0x0004
+#define IOINTCLR 0x0008
+#define IOINTENR 0x000c
+#define IOINTENF 0x0010
+
+static void lpc2k_gpio_enable_irq(struct irq_data *d)
+{
+ void __iomem *base = irq_data_get_irq_chip_data(d);
+ unsigned irq = d->irq & 31;
+ unsigned status = irq_to_desc(d->irq)->status;
+
+ status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
+ if (!status)
+ status = IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
+
+ if (status & IRQ_TYPE_EDGE_RISING)
+ writel(readl(base + IOINTENR) | (1 << irq), base + IOINTENR);
+ else
+ writel(readl(base + IOINTENR) & ~(1 << irq), base + IOINTENR);
+
+ if (status & IRQ_TYPE_EDGE_FALLING)
+ writel(readl(base + IOINTENF) | (1 << irq), base + IOINTENF);
+ else
+ writel(readl(base + IOINTENF) & ~(1 << irq), base + IOINTENF);
+}
+
+static void lpc2k_gpio_disable_irq(struct irq_data *d)
+{
+ void __iomem *base = irq_data_get_irq_chip_data(d);
+ unsigned irq = d->irq & 31;
+
+ writel(readl(base + IOINTENR) & ~(1 << irq), base + IOINTENR);
+ writel(readl(base + IOINTENF) & ~(1 << irq), base + IOINTENF);
+}
+
+static int lpc2k_gpio_set_type(struct irq_data *d, unsigned trigger)
+{
+ void __iomem *base = irq_data_get_irq_chip_data(d);
+ struct irq_desc *desc = irq_to_desc(d->irq);
+ unsigned irq = d->irq & 31;
+
+ if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+ return -EINVAL;
+
+ desc->status &= ~IRQ_TYPE_SENSE_MASK;
+ desc->status |= trigger;
+
+ /* don't enable the IRQ if it's currently disabled */
+ if (desc->depth == 0) {
+ if (trigger & IRQ_TYPE_EDGE_RISING)
+ writel(readl(base + IOINTENR) | (1 << irq),
+ base + IOINTENR);
+ else
+ writel(readl(base + IOINTENR) & ~(1 << irq),
+ base + IOINTENR);
+
+ if (trigger & IRQ_TYPE_EDGE_FALLING)
+ writel(readl(base + IOINTENF) | (1 << irq),
+ base + IOINTENF);
+ else
+ writel(readl(base + IOINTENF) & ~(1 << irq),
+ base + IOINTENF);
+ }
+
+ return 0;
+}
+
+struct irq_chip gpio_irq_chip_p0 = {
+ .name = "GPIO-P0",
+ .irq_enable = lpc2k_gpio_enable_irq,
+ .irq_disable = lpc2k_gpio_disable_irq,
+ .irq_set_type = lpc2k_gpio_set_type,
+};
+
+struct irq_chip gpio_irq_chip_p2 = {
+ .name = "GPIO-P2",
+ .irq_enable = lpc2k_gpio_enable_irq,
+ .irq_disable = lpc2k_gpio_disable_irq,
+ .irq_set_type = lpc2k_gpio_set_type,
+};
+
+static void lpc2k_demux_gpio_irq(unsigned int irq, struct irq_desc *desc)
+{
+ u32 status = readl(APB_GPIO_BASE + IOINTSTAT);
+ if (status & 1) {
+ int i, stat = readl(APB_GPIO_BASE + IO0INT + IOINTSTATR) |
+ readl(APB_GPIO_BASE + IO0INT + IOINTSTATF);
+
+ writel(stat, APB_GPIO_BASE + IO0INT + IOINTCLR);
+
+ for (i = 0; i < 32; i++)
+ if (stat & (1 << i))
+ generic_handle_irq(IRQ_LPC2K_PORT0(i));
+ }
+
+ if (status & 4) {
+ int i, stat = readl(APB_GPIO_BASE + IO2INT + IOINTSTATR) |
+ readl(APB_GPIO_BASE + IO2INT + IOINTSTATF);
+
+ writel(stat, APB_GPIO_BASE + IO2INT + IOINTCLR);
+
+ for (i = 0; i < 32; i++)
+ if (stat & (1 << i))
+ generic_handle_irq(IRQ_LPC2K_PORT2(i));
+ }
+}
+
+static int __init lpc2k_init_gpio(void)
+{
+ struct lpc2k_gpio_chip *gpio_chip;
+ void __iomem *base;
+ unsigned i;
+
+ for (i = 0; i < ARRAY_SIZE(lpc2k_gpio); i++) {
+ gpio_chip = &lpc2k_gpio[i];
+ spin_lock_init(&gpio_chip->gpio_lock);
+ gpio_chip->regbase =
+ (void __iomem *)(FAST_GPIO_BASE + i * 0x20);
+ gpiochip_add(&gpio_chip->chip);
+
+ writel(0, gpio_chip->regbase + FIOMASK);
+ }
+
+ base = (void __iomem *)(APB_GPIO_BASE + IO0INT);
+ for (i = IRQ_LPC2K_PORT0(0); i <= IRQ_LPC2K_PORT0(31); i++) {
+ set_irq_chip(i, &gpio_irq_chip_p0);
+ set_irq_chip_data(i, base);
+ set_irq_handler(i, handle_simple_irq);
+ set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+ }
+
+ base = (void __iomem *)(APB_GPIO_BASE + IO2INT);
+ for (i = IRQ_LPC2K_PORT2(0); i <= IRQ_LPC2K_PORT2(31); i++) {
+ set_irq_chip(i, &gpio_irq_chip_p2);
+ set_irq_chip_data(i, base);
+ set_irq_handler(i, handle_simple_irq);
+ set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+ }
+
+ set_irq_chained_handler(IRQ_LPC2K_EINT3, lpc2k_demux_gpio_irq);
+
+ return 0;
+}
+
+postcore_initcall(lpc2k_init_gpio);
diff --git a/arch/arm/mach-lpc2k/include/mach/gpio.h b/arch/arm/mach-lpc2k/include/mach/gpio.h
new file mode 100644
index 0000000..533e3da
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/gpio.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#ifndef MACH_LPC2K_GPIO_H
+#define MACH_LPC2K_GPIO_H
+
+#include <asm-generic/gpio.h>
+
+#define gpio_get_value __gpio_get_value
+#define gpio_set_value __gpio_set_value
+#define gpio_cansleep __gpio_cansleep
+#define gpio_to_irq __gpio_to_irq
+
+/* Convert from PX.Y notation to GPIO number */
+#define LPC2K_GPIO(port,pin) (((port) * 32) + (pin))
+
+#endif /* MACH_LPC2K_GPIO_H */
diff --git a/arch/arm/mach-lpc2k/include/mach/hardware.h b/arch/arm/mach-lpc2k/include/mach/hardware.h
index 3463b47..b8c471b 100644
--- a/arch/arm/mach-lpc2k/include/mach/hardware.h
+++ b/arch/arm/mach-lpc2k/include/mach/hardware.h
@@ -15,10 +15,12 @@
/* Default memory size if no ATAGS found */
#define MEM_SIZE (SZ_32M)
+#define FAST_GPIO_BASE 0x3fffc000
#define APB_WDT_BASE 0xe0000000
#define APB_TIMER0_BASE 0xe0004000
#define APB_TIMER1_BASE 0xe0008000
#define APB_UART0_BASE 0xe000c000
+#define APB_GPIO_BASE 0xe0028000
#define APB_SCB_BASE 0xe01fc000
#define APH_VIC_BASE 0xfffff000
diff --git a/arch/arm/mach-lpc2k/include/mach/irqs.h b/arch/arm/mach-lpc2k/include/mach/irqs.h
index 87b80dd..9207702 100644
--- a/arch/arm/mach-lpc2k/include/mach/irqs.h
+++ b/arch/arm/mach-lpc2k/include/mach/irqs.h
@@ -44,6 +44,9 @@
#define IRQ_LPC2K_I2C2 30
#define IRQ_LPC2K_I2S 31
-#define NR_IRQS 32
+#define IRQ_LPC2K_PORT0(pin) (32 + (pin))
+#define IRQ_LPC2K_PORT2(pin) (64 + (pin))
+
+#define NR_IRQS 96
#endif /* MACH_LPC2K_IRQS_H */
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 6/9] lpc2k: multifunction pin configuration
2011-03-20 20:30 [PATCH v3 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
` (4 preceding siblings ...)
2011-03-20 20:30 ` [PATCH v3 5/9] lpc2k: gpiolib Ithamar R. Adema
@ 2011-03-20 20:30 ` Ithamar R. Adema
2011-03-20 20:30 ` [PATCH v3 7/9] lpc2k: Add EmbeddedArtists LPC2478 Developer's Kit board Ithamar R. Adema
` (2 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Ithamar R. Adema @ 2011-03-20 20:30 UTC (permalink / raw)
To: linux-arm-kernel
Inspired by the mfp support in PXA. Includes definition of pins
for NXP LPC2468/78.
Signed-off-by: Ithamar R. Adema <ithamar.adema@team-embedded.nl>
---
changes since v2:
* Removed MFP_PIN_* enum.
* Renamed GPIOx_signal defines to Px_y_signal.
no changes since v1.
---
arch/arm/mach-lpc2k/Makefile | 2 +-
arch/arm/mach-lpc2k/include/mach/hardware.h | 1 +
arch/arm/mach-lpc2k/include/mach/mfp-lpc24xx.h | 98 +++++++++++++++++++++++
arch/arm/mach-lpc2k/include/mach/mfp.h | 43 ++++++++++
arch/arm/mach-lpc2k/mfp.c | 100 ++++++++++++++++++++++++
5 files changed, 243 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/mach-lpc2k/include/mach/mfp-lpc24xx.h
create mode 100644 arch/arm/mach-lpc2k/include/mach/mfp.h
create mode 100644 arch/arm/mach-lpc2k/mfp.c
diff --git a/arch/arm/mach-lpc2k/Makefile b/arch/arm/mach-lpc2k/Makefile
index 89596a7..2c50bb9 100644
--- a/arch/arm/mach-lpc2k/Makefile
+++ b/arch/arm/mach-lpc2k/Makefile
@@ -1 +1 @@
-obj-y := clock.o irq.o gpio.o time.o
+obj-y := clock.o irq.o gpio.o mfp.o time.o
diff --git a/arch/arm/mach-lpc2k/include/mach/hardware.h b/arch/arm/mach-lpc2k/include/mach/hardware.h
index b8c471b..1a20126 100644
--- a/arch/arm/mach-lpc2k/include/mach/hardware.h
+++ b/arch/arm/mach-lpc2k/include/mach/hardware.h
@@ -21,6 +21,7 @@
#define APB_TIMER1_BASE 0xe0008000
#define APB_UART0_BASE 0xe000c000
#define APB_GPIO_BASE 0xe0028000
+#define APB_PINSEL_BASE 0xe002c000
#define APB_SCB_BASE 0xe01fc000
#define APH_VIC_BASE 0xfffff000
diff --git a/arch/arm/mach-lpc2k/include/mach/mfp-lpc24xx.h b/arch/arm/mach-lpc2k/include/mach/mfp-lpc24xx.h
new file mode 100644
index 0000000..dafb8f1
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/mfp-lpc24xx.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MACH_LPC2K_MFP_LPC24XX_H
+#define MACH_LPC2K_MFP_LPC24XX_H
+
+#include <mach/mfp.h>
+
+#define P0_0_RD1 MFP_CFG(LPC2K_GPIO(0,0), AF1)
+#define P0_0_TXD3 MFP_CFG(LPC2K_GPIO(0,0), AF2)
+#define P0_0_SDA1 MFP_CFG(LPC2K_GPIO(0,0), AF3)
+#define P0_1_TD1 MFP_CFG(LPC2K_GPIO(0,1), AF1)
+#define P0_1_RXD3 MFP_CFG(LPC2K_GPIO(0,1), AF2)
+#define P0_1_SCL1 MFP_CFG(LPC2K_GPIO(0,1), AF3)
+#define P0_2_TXD0 MFP_CFG(LPC2K_GPIO(0,2), AF1)
+#define P0_3_RXD0 MFP_CFG(LPC2K_GPIO(0,3), AF1)
+#define P0_4_LCDVD0 MFP_CFG(LPC2K_GPIO(0,4), AF1)
+#define P0_5_LCDVD1 MFP_CFG(LPC2K_GPIO(0,5), AF1)
+#define P0_6_LCDVD8 MFP_CFG(LPC2K_GPIO(0,6), AF1)
+#define P0_7_LCDVD9 MFP_CFG(LPC2K_GPIO(0,7), AF1)
+#define P0_8_LCDVD16 MFP_CFG(LPC2K_GPIO(0,8), AF1)
+#define P0_9_LCDVD17 MFP_CFG(LPC2K_GPIO(0,9), AF1)
+#define P0_10_TXD2 MFP_CFG(LPC2K_GPIO(0,10), AF1)
+#define P0_11_RXD2 MFP_CFG(LPC2K_GPIO(0,11), AF1)
+#define P0_12_USB_PPWR2 MFP_CFG(LPC2K_GPIO(0,12), AF1)
+#define P0_13_USB_UP_LED2 MFP_CFG(LPC2K_GPIO(0,13), AF1)
+#define P0_15_SCK MFP_CFG(LPC2K_GPIO(0,15), AF3)
+#define P0_17_MISO MFP_CFG(LPC2K_GPIO(0,17), AF3)
+#define P0_18_MOSI MFP_CFG(LPC2K_GPIO(0,18), AF3)
+#define P0_27_SDA0 MFP_CFG(LPC2K_GPIO(0,27), AF1)
+#define P0_28_SCL0 MFP_CFG(LPC2K_GPIO(0,28), AF1)
+#define P0_29_USB_Dp1 MFP_CFG(LPC2K_GPIO(0,29), AF1)
+#define P0_30_USB_Dn1 MFP_CFG(LPC2K_GPIO(0,30), AF1)
+#define P0_31_USB_Dp2 MFP_CFG(LPC2K_GPIO(0,31), AF1)
+#define P1_0_ENET_TXD0 MFP_CFG(LPC2K_GPIO(1,0), AF1)
+#define P1_1_ENET_TXD1 MFP_CFG(LPC2K_GPIO(1,1), AF1)
+#define P1_2_MCICLK MFP_CFG(LPC2K_GPIO(1,2), AF2)
+#define P1_3_MCICMD MFP_CFG(LPC2K_GPIO(1,3), AF2)
+#define P1_4_ENET_TX_EN MFP_CFG(LPC2K_GPIO(1,4), AF1)
+#define P1_5_MCIPWR MFP_CFG(LPC2K_GPIO(1,5), AF2)
+#define P1_6_ENET_TX_CLK MFP_CFG(LPC2K_GPIO(1,6), AF1)
+#define P1_6_MCIDAT0 MFP_CFG(LPC2K_GPIO(1,6), AF2)
+#define P1_7_MCIDAT1 MFP_CFG(LPC2K_GPIO(1,7), AF2)
+#define P1_8_ENET_CRS MFP_CFG(LPC2K_GPIO(1,8), AF1)
+#define P1_9_ENET_RXD0 MFP_CFG(LPC2K_GPIO(1,9), AF1)
+#define P1_10_ENET_RXD1 MFP_CFG(LPC2K_GPIO(1,10), AF1)
+#define P1_11_MCIDAT2 MFP_CFG(LPC2K_GPIO(1,11), AF2)
+#define P1_12_MCIDAT3 MFP_CFG(LPC2K_GPIO(1,12), AF2)
+#define P1_14_ENET_RX_ERR MFP_CFG(LPC2K_GPIO(1,14), AF1)
+#define P1_15_ENET_REF_CLK MFP_CFG(LPC2K_GPIO(1,15), AF1)
+#define P1_16_ENET_MDC MFP_CFG(LPC2K_GPIO(1,16), AF1)
+#define P1_17_ENET_MDIO MFP_CFG(LPC2K_GPIO(1,17), AF1)
+#define P1_18_PWM1 MFP_CFG(LPC2K_GPIO(1,18), AF2)
+#define P1_20_LCDVD10 MFP_CFG(LPC2K_GPIO(1,20), AF1)
+#define P1_21_LCDVD11 MFP_CFG(LPC2K_GPIO(1,21), AF1)
+#define P1_22_LCDVD12 MFP_CFG(LPC2K_GPIO(1,22), AF1)
+#define P1_23_LCDVD13 MFP_CFG(LPC2K_GPIO(1,23), AF1)
+#define P1_24_LCDVD14 MFP_CFG(LPC2K_GPIO(1,24), AF1)
+#define P1_25_LCDVD15 MFP_CFG(LPC2K_GPIO(1,25), AF1)
+#define P1_26_LCDVD20 MFP_CFG(LPC2K_GPIO(1,26), AF1)
+#define P1_27_LCDVD21 MFP_CFG(LPC2K_GPIO(1,27), AF1)
+#define P1_28_LCDVD22 MFP_CFG(LPC2K_GPIO(1,28), AF1)
+#define P1_29_LCDVD23 MFP_CFG(LPC2K_GPIO(1,29), AF1)
+#define P1_30_VBUS MFP_CFG(LPC2K_GPIO(1,30), AF2)
+#define P1_31_USB_OVRCR2 MFP_CFG(LPC2K_GPIO(1,31), AF1)
+#define P2_0_LCDPWR MFP_CFG(LPC2K_GPIO(2,0), AF3)
+#define P2_1_LCDLE MFP_CFG(LPC2K_GPIO(2,1), AF3)
+#define P2_2_LCDDCLK MFP_CFG(LPC2K_GPIO(2,2), AF3)
+#define P2_3_LCDFP MFP_CFG(LPC2K_GPIO(2,3), AF3)
+#define P2_4_LCDM MFP_CFG(LPC2K_GPIO(2,4), AF3)
+#define P2_5_LCDLP MFP_CFG(LPC2K_GPIO(2,5), AF3)
+#define P2_6_LCDVP4 MFP_CFG(LPC2K_GPIO(2,6), AF3)
+#define P2_7_LCDVP5 MFP_CFG(LPC2K_GPIO(2,7), AF3)
+#define P2_8_LCDVP6 MFP_CFG(LPC2K_GPIO(2,8), AF3)
+#define P2_9_LCDVP7 MFP_CFG(LPC2K_GPIO(2,9), AF3)
+#define P2_11_LCDCLKIN MFP_CFG(LPC2K_GPIO(2,11), AF1)
+#define P2_12_LCDVP18 MFP_CFG(LPC2K_GPIO(2,12), AF1)
+#define P2_13_LCDVP19 MFP_CFG(LPC2K_GPIO(2,13), AF1)
+#define P3_16_TXD1 MFP_CFG(LPC2K_GPIO(3,16), AF3)
+#define P3_17_RXD1 MFP_CFG(LPC2K_GPIO(3,17), AF3)
+#define P3_18_CTS1 MFP_CFG(LPC2K_GPIO(3,18), AF3)
+#define P3_19_DCD1 MFP_CFG(LPC2K_GPIO(3,19), AF3)
+#define P3_20_DSR1 MFP_CFG(LPC2K_GPIO(3,20), AF3)
+#define P3_21_DR1 MFP_CFG(LPC2K_GPIO(3,21), AF3)
+#define P3_22_RI1 MFP_CFG(LPC2K_GPIO(3,22), AF3)
+#define P3_30_RTS1 MFP_CFG(LPC2K_GPIO(3,30), AF3)
+#define P4_28_TXD3 MFP_CFG(LPC2K_GPIO(4,28), AF3)
+#define P4_28_LCDVP2 MFP_CFG(LPC2K_GPIO(4,28), AF2)
+#define P4_29_RXD3 MFP_CFG(LPC2K_GPIO(4,29), AF3)
+#define P4_29_LCDVP3 MFP_CFG(LPC2K_GPIO(4,29), AF2)
+
+#endif /* MACH_LPC2K_MFP_LPC24XX_H */
diff --git a/arch/arm/mach-lpc2k/include/mach/mfp.h b/arch/arm/mach-lpc2k/include/mach/mfp.h
new file mode 100644
index 0000000..c3d0378
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/mfp.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef ARCH_LPC2K_MFP_H
+#define ARCH_LPC2K_MFP_H
+
+#define mfp_to_gpio(m) ((m) % 160)
+
+/* pin number; currently only 0-159 are used */
+#define MFP_PIN(x) ((x) & 0x3ff)
+
+/* Alternate functions, currently only 0-3 are used */
+#define MFP_AF0 (0x0 << 10)
+#define MFP_AF1 (0x1 << 10)
+#define MFP_AF2 (0x2 << 10)
+#define MFP_AF3 (0x3 << 10)
+#define MFP_AF_MASK (0x3 << 10)
+#define MFP_AF(x) (((x) >> 10) & 0x3)
+
+/* Pullup/down configuration, currently only none/high/low are used */
+#define MFP_PULL_NONE (0x2 << 21)
+#define MFP_PULL_LOW (0x3 << 21)
+#define MFP_PULL_HIGH (0x0 << 21)
+#define MFP_PULL_MASK (0x3 << 21)
+#define MFP_PULL(x) (((x) >> 21) & 0x3)
+
+#define MFP_CFG_DEFAULT (MFP_PULL_HIGH | MFP_AF0)
+
+#define MFP_CFG(pin, af) \
+ ((MFP_CFG_DEFAULT & ~MFP_AF_MASK) |\
+ (MFP_PIN(pin) | MFP_##af))
+
+#define MFP_CFG_PULL(pin, af, pull) \
+ ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_PULL_MASK)) |\
+ (MFP_PIN(pin) | MFP_##af | MFP_##pull))
+
+#endif /* ARCH_LPC2K_MFP_H */
diff --git a/arch/arm/mach-lpc2k/mfp.c b/arch/arm/mach-lpc2k/mfp.c
new file mode 100644
index 0000000..c0d356b
--- /dev/null
+++ b/arch/arm/mach-lpc2k/mfp.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2011 Team Embeded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * Based on MFP code from mach-pxa.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mfp.h>
+
+#define PINSEL(bank) (0x00 + (bank)*4)
+#define PINMODE(bank) (0x40 + (bank)*4)
+
+struct gpio_desc {
+ unsigned valid:1;
+ unsigned long config;
+};
+
+static struct gpio_desc gpio_desc[LPC2K_GPIO(4,31) + 1];
+
+static int __mfp_config_gpio(unsigned gpio, unsigned long c)
+{
+ unsigned bank = gpio >> 4;
+ unsigned shift = (gpio & 0xf) * 2;
+ unsigned val;
+
+ /* Configure alternate function */
+ val = __raw_readl(APB_PINSEL_BASE + PINSEL(bank));
+ if ((val & (3 << shift)) &&
+ (val & (3 << shift)) != (MFP_AF(c) << shift))
+ pr_warning
+ ("GPIO%d is already configured (%x), not reconfigured!\n",
+ gpio, (val & (3 << shift)) >> shift);
+ else {
+ val &= ~(0x3 << shift);
+ val |= MFP_AF(c) << shift;
+ __raw_writel(val, APB_PINSEL_BASE + PINSEL(bank));
+ }
+
+ /* Configuration pullup/dn */
+ val = __raw_readl(APB_PINSEL_BASE + PINMODE(bank));
+ val &= ~(0x3 << shift);
+ val |= MFP_PULL(c) << shift;
+ __raw_writel(val, APB_PINSEL_BASE + PINMODE(bank));
+
+ return 0;
+}
+
+static inline int __mfp_validate(int mfp)
+{
+ int gpio = mfp_to_gpio(mfp);
+
+ if (!gpio_desc[gpio].valid) {
+ pr_warning("%s: GPIO%d is invalid pin\n", __func__, gpio);
+ return -1;
+ }
+
+ return gpio;
+}
+
+void lpc2k_mfp_config(unsigned long *mfp_cfgs, int num)
+{
+ unsigned long flags;
+ unsigned long *c;
+ int i, gpio;
+
+ for (i = 0, c = mfp_cfgs; i < num; i++, c++) {
+
+ gpio = __mfp_validate(MFP_PIN(*c));
+ if (gpio < 0)
+ continue;
+
+ local_irq_save(flags);
+
+ gpio_desc[gpio].config = *c;
+ __mfp_config_gpio(gpio, *c);
+
+ local_irq_restore(flags);
+ }
+}
+
+static int __init lpc2k_mfp_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(gpio_desc); i++)
+ gpio_desc[i].valid = 1;
+
+ return 0;
+}
+
+postcore_initcall(lpc2k_mfp_init);
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 7/9] lpc2k: Add EmbeddedArtists LPC2478 Developer's Kit board
2011-03-20 20:30 [PATCH v3 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
` (5 preceding siblings ...)
2011-03-20 20:30 ` [PATCH v3 6/9] lpc2k: multifunction pin configuration Ithamar R. Adema
@ 2011-03-20 20:30 ` Ithamar R. Adema
2011-03-20 20:30 ` [PATCH v3 8/9] lpc2k: Add UART, SSP, and MCI devices Ithamar R. Adema
2011-03-20 20:30 ` [PATCH v3 9/9] lpc2k: defconfig for NXP LPC2K platform Ithamar R. Adema
8 siblings, 0 replies; 12+ messages in thread
From: Ithamar R. Adema @ 2011-03-20 20:30 UTC (permalink / raw)
To: linux-arm-kernel
Add support for EmbeddedArtists LPC2478 Developer's Kit, consisting
of the LPC2478OEM board, with QVGA base board. For details, see:
http://www.embeddedartists.com/products/kits/lpc2478_kit.php
The mach-types change included is simply one generated from
http://www.arm.linux.org.uk/developer/machines/, and is only
included so this patch can be build.
Signed-off-by: Ithamar R. Adema <ithamar.adema@team-embedded.nl>
---
changes since v2:
* Changed machine name from web interface, and
included mach-types update generated from there.
changes since v1:
* Fixed RTC clock rate
* Marked mfp_cfgs as __initdata.
* renamed LPC2478OEM to more appropriate EA2478DEVKIT.
---
arch/arm/mach-lpc2k/Kconfig | 7 ++
arch/arm/mach-lpc2k/Makefile | 2 +
arch/arm/mach-lpc2k/common.h | 21 +++++
arch/arm/mach-lpc2k/mach-ea2478devkit.c | 122 +++++++++++++++++++++++++++++++
arch/arm/tools/mach-types | 113 +++++++++++++++++++++-------
5 files changed, 237 insertions(+), 28 deletions(-)
create mode 100644 arch/arm/mach-lpc2k/common.h
create mode 100644 arch/arm/mach-lpc2k/mach-ea2478devkit.c
diff --git a/arch/arm/mach-lpc2k/Kconfig b/arch/arm/mach-lpc2k/Kconfig
index fad47b8..210b641 100644
--- a/arch/arm/mach-lpc2k/Kconfig
+++ b/arch/arm/mach-lpc2k/Kconfig
@@ -2,4 +2,11 @@ if ARCH_LPC2K
comment "LPC2K machines"
+config MACH_EA2478DEVKIT
+ bool "Embedded Artists LPC2478 Developer's Kit"
+ help
+ Say Y if you want the kernel to support the EmbeddedArtists
+ LPC2478 Developer's Kit. For more hardware details, see:
+ http://www.embeddedartists.com/products/kits/lpc2478_kit.php
+
endif
diff --git a/arch/arm/mach-lpc2k/Makefile b/arch/arm/mach-lpc2k/Makefile
index 2c50bb9..93e27fb 100644
--- a/arch/arm/mach-lpc2k/Makefile
+++ b/arch/arm/mach-lpc2k/Makefile
@@ -1 +1,3 @@
obj-y := clock.o irq.o gpio.o mfp.o time.o
+
+obj-$(CONFIG_MACH_EA2478DEVKIT) += mach-ea2478devkit.o
diff --git a/arch/arm/mach-lpc2k/common.h b/arch/arm/mach-lpc2k/common.h
new file mode 100644
index 0000000..6b775d9
--- /dev/null
+++ b/arch/arm/mach-lpc2k/common.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef LPC2K_COMMON_H
+#define LPC2K_COMMON_H
+
+struct sys_timer;
+
+extern void lpc2k_init_clocks(unsigned long xtal, unsigned long rtc);
+extern void lpc2k_mfp_config(unsigned long *mfp_cfgs, int num);
+extern void lpc2k_init_irq(void);
+
+extern struct sys_timer lpc2k_timer;
+
+#endif /* LPC2K_COMMON_H */
diff --git a/arch/arm/mach-lpc2k/mach-ea2478devkit.c b/arch/arm/mach-lpc2k/mach-ea2478devkit.c
new file mode 100644
index 0000000..d59f5ba
--- /dev/null
+++ b/arch/arm/mach-lpc2k/mach-ea2478devkit.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2011 Team Embeded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <mach/mfp-lpc24xx.h>
+#include <mach/hardware.h>
+
+#include "common.h"
+
+#define EXTPOLAR 0x14c
+
+static unsigned long mfp_cfgs[] __initdata = {
+ /* UART0 */
+ P0_2_TXD0,
+ P0_3_RXD0,
+ /* USB Host */
+ P0_12_USB_PPWR2,
+ P0_13_USB_UP_LED2,
+ P0_31_USB_Dp2,
+ P1_30_VBUS,
+ P1_31_USB_OVRCR2,
+ /* USB Gadget */
+ P0_29_USB_Dp1,
+ P0_30_USB_Dn1,
+ /* Ethernet */
+ P1_0_ENET_TXD0,
+ P1_1_ENET_TXD1,
+ P1_4_ENET_TX_EN,
+ P1_8_ENET_CRS,
+ P1_9_ENET_RXD0,
+ P1_10_ENET_RXD1,
+ P1_14_ENET_RX_ERR,
+ P1_15_ENET_REF_CLK,
+ P1_16_ENET_MDC,
+ P1_17_ENET_MDIO,
+ /* I2C0 */
+ P0_27_SDA0,
+ P0_28_SCL0,
+ /* SPI */
+ P0_15_SCK,
+ P0_17_MISO,
+ P0_18_MOSI,
+ /* LCD */
+ P0_4_LCDVD0,
+ P0_5_LCDVD1,
+ P0_6_LCDVD8,
+ P0_7_LCDVD9,
+ P0_8_LCDVD16,
+ P0_9_LCDVD17,
+ P1_20_LCDVD10,
+ P1_21_LCDVD11,
+ P1_22_LCDVD12,
+ P1_23_LCDVD13,
+ P1_24_LCDVD14,
+ P1_25_LCDVD15,
+ P1_26_LCDVD20,
+ P1_27_LCDVD21,
+ P1_28_LCDVD22,
+ P1_29_LCDVD23,
+ P2_0_LCDPWR,
+ P2_1_LCDLE,
+ P2_2_LCDDCLK,
+ P2_3_LCDFP,
+ P2_4_LCDM,
+ P2_5_LCDLP,
+ P2_6_LCDVP4,
+ P2_7_LCDVP5,
+ P2_8_LCDVP6,
+ P2_9_LCDVP7,
+ P2_11_LCDCLKIN,
+ P2_12_LCDVP18,
+ P2_13_LCDVP19,
+ P4_28_LCDVP2,
+ P4_29_LCDVP3,
+ /* Backlight */
+ P1_18_PWM1,
+ /* MMC/SD */
+ P1_2_MCICLK,
+ P1_3_MCICMD,
+ P1_5_MCIPWR,
+ P1_6_MCIDAT0,
+ P1_7_MCIDAT1,
+ P1_11_MCIDAT2,
+ P1_12_MCIDAT3,
+};
+
+void __init ea2478devkit_init_machine(void)
+{
+ lpc2k_mfp_config(mfp_cfgs, ARRAY_SIZE(mfp_cfgs));
+}
+
+static void __init ea2478devkit_init_irq(void)
+{
+ /* XXX workaround for the fact that EINT3 is connected to high-active
+ * signal, but can't be disabled. As the EINT3 interrupt is also used
+ * for GPIO interrupts, this will cause an interrupt storm without
+ * this setting.
+ */
+ iowrite32(ioread32(APB_SCB_BASE + EXTPOLAR) | (1 << 3),
+ APB_SCB_BASE + EXTPOLAR);
+
+ lpc2k_init_irq();
+ lpc2k_init_clocks(12000000UL, 32768UL);
+}
+
+MACHINE_START(EA2478DEVKIT, "Embedded Artists LPC2478 Developer's Kit")
+ .init_irq = ea2478devkit_init_irq,
+ .timer = &lpc2k_timer,
+ .init_machine = ea2478devkit_init_machine,
+MACHINE_END
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 9d6feaa..852cc95 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -12,7 +12,7 @@
#
# http://www.arm.linux.org.uk/developer/machines/?action=new
#
-# Last update: Mon Feb 7 08:59:27 2011
+# Last update: Fri Mar 18 20:55:51 2011
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
@@ -1319,7 +1319,6 @@ mistral MACH_MISTRAL MISTRAL 1315
msm MACH_MSM MSM 1316
ct5910 MACH_CT5910 CT5910 1317
ct5912 MACH_CT5912 CT5912 1318
-hynet_ine MACH_HYNET_INE HYNET_INE 1319
hynet_app MACH_HYNET_APP HYNET_APP 1320
msm7200 MACH_MSM7200 MSM7200 1321
msm7600 MACH_MSM7600 MSM7600 1322
@@ -1777,7 +1776,6 @@ wdg002 MACH_WDG002 WDG002 1785
sg560adsl MACH_SG560ADSL SG560ADSL 1786
nextio_n2800_ica MACH_NEXTIO_N2800_ICA NEXTIO_N2800_ICA 1787
dove_db MACH_DOVE_DB DOVE_DB 1788
-marvell_newdb MACH_MARVELL_NEWDB MARVELL_NEWDB 1789
vandihud MACH_VANDIHUD VANDIHUD 1790
magx_e8 MACH_MAGX_E8 MAGX_E8 1791
magx_z6 MACH_MAGX_Z6 MAGX_Z6 1792
@@ -1877,7 +1875,6 @@ ued MACH_UED UED 1885
esiblade MACH_ESIBLADE ESIBLADE 1886
eye02 MACH_EYE02 EYE02 1887
imx27kbd MACH_IMX27KBD IMX27KBD 1888
-sst61vc010_fpga MACH_SST61VC010_FPGA SST61VC010_FPGA 1889
kixvp435 MACH_KIXVP435 KIXVP435 1890
kixnp435 MACH_KIXNP435 KIXNP435 1891
africa MACH_AFRICA AFRICA 1892
@@ -2308,7 +2305,6 @@ ecac2378 MACH_ECAC2378 ECAC2378 2319
tazkiosk MACH_TAZKIOSK TAZKIOSK 2320
whiterabbit_mch MACH_WHITERABBIT_MCH WHITERABBIT_MCH 2321
sbox9263 MACH_SBOX9263 SBOX9263 2322
-oreo MACH_OREO OREO 2323
smdk6442 MACH_SMDK6442 SMDK6442 2324
openrd_base MACH_OPENRD_BASE OPENRD_BASE 2325
incredible MACH_INCREDIBLE INCREDIBLE 2326
@@ -2374,7 +2370,6 @@ sch_m490 MACH_SCH_M490 SCH_M490 2386
rbl01 MACH_RBL01 RBL01 2387
omnifi MACH_OMNIFI OMNIFI 2388
otavalo MACH_OTAVALO OTAVALO 2389
-sienna MACH_SIENNA SIENNA 2390
htc_excalibur_s620 MACH_HTC_EXCALIBUR_S620 HTC_EXCALIBUR_S620 2391
htc_opal MACH_HTC_OPAL HTC_OPAL 2392
touchbook MACH_TOUCHBOOK TOUCHBOOK 2393
@@ -2446,7 +2441,6 @@ siogentoo1 MACH_SIOGENTOO1 SIOGENTOO1 2458
siogentoo2 MACH_SIOGENTOO2 SIOGENTOO2 2459
sm3k MACH_SM3K SM3K 2460
acer_tempo_f900 MACH_ACER_TEMPO_F900 ACER_TEMPO_F900 2461
-sst61vc010_dev MACH_SST61VC010_DEV SST61VC010_DEV 2462
glittertind MACH_GLITTERTIND GLITTERTIND 2463
omap_zoom3 MACH_OMAP_ZOOM3 OMAP_ZOOM3 2464
omap_3630sdp MACH_OMAP_3630SDP OMAP_3630SDP 2465
@@ -2498,7 +2492,6 @@ hiram MACH_HIRAM HIRAM 2510
phy3250 MACH_PHY3250 PHY3250 2511
ea3250 MACH_EA3250 EA3250 2512
fdi3250 MACH_FDI3250 FDI3250 2513
-whitestone MACH_WHITESTONE WHITESTONE 2514
at91sam9263nit MACH_AT91SAM9263NIT AT91SAM9263NIT 2515
ccmx51 MACH_CCMX51 CCMX51 2516
ccmx51js MACH_CCMX51JS CCMX51JS 2517
@@ -2561,7 +2554,6 @@ magnolia2 MACH_MAGNOLIA2 MAGNOLIA2 2573
emxx MACH_EMXX EMXX 2574
outlaw MACH_OUTLAW OUTLAW 2575
riot_bei2 MACH_RIOT_BEI2 RIOT_BEI2 2576
-riot_vox MACH_RIOT_VOX RIOT_VOX 2577
riot_x37 MACH_RIOT_X37 RIOT_X37 2578
mega25mx MACH_MEGA25MX MEGA25MX 2579
benzina2 MACH_BENZINA2 BENZINA2 2580
@@ -2582,7 +2574,6 @@ omap3_bulldog MACH_OMAP3_BULLDOG OMAP3_BULLDOG 2594
pca101 MACH_PCA101 PCA101 2595
buzzc MACH_BUZZC BUZZC 2596
sasie2 MACH_SASIE2 SASIE2 2597
-davinci_cio MACH_DAVINCI_CIO DAVINCI_CIO 2598
smartmeter_dl MACH_SMARTMETER_DL SMARTMETER_DL 2599
wzl6410 MACH_WZL6410 WZL6410 2600
wzl6410m MACH_WZL6410M WZL6410M 2601
@@ -2591,7 +2582,6 @@ wzl6410i MACH_WZL6410I WZL6410I 2603
spacecom1 MACH_SPACECOM1 SPACECOM1 2604
pingu920 MACH_PINGU920 PINGU920 2605
bravoc MACH_BRAVOC BRAVOC 2606
-cybo2440 MACH_CYBO2440 CYBO2440 2607
vdssw MACH_VDSSW VDSSW 2608
romulus MACH_ROMULUS ROMULUS 2609
omap_magic MACH_OMAP_MAGIC OMAP_MAGIC 2610
@@ -2667,7 +2657,7 @@ msm7x30_surf MACH_MSM7X30_SURF MSM7X30_SURF 2679
micro2440 MACH_MICRO2440 MICRO2440 2680
am2440 MACH_AM2440 AM2440 2681
tq2440 MACH_TQ2440 TQ2440 2682
-lpc2478oem MACH_LPC2478OEM LPC2478OEM 2683
+ea2478devkit MACH_EA2478DEVKIT EA2478DEVKIT 2683
ak880x MACH_AK880X AK880X 2684
cobra3530 MACH_COBRA3530 COBRA3530 2685
pmppb MACH_PMPPB PMPPB 2686
@@ -2683,7 +2673,6 @@ lkevm MACH_LKEVM LKEVM 2695
mw6410 MACH_MW6410 MW6410 2696
terastation_wxl MACH_TERASTATION_WXL TERASTATION_WXL 2697
cpu8000e MACH_CPU8000E CPU8000E 2698
-catania MACH_CATANIA CATANIA 2699
tokyo MACH_TOKYO TOKYO 2700
msm7201a_surf MACH_MSM7201A_SURF MSM7201A_SURF 2701
msm7201a_ffa MACH_MSM7201A_FFA MSM7201A_FFA 2702
@@ -2741,7 +2730,6 @@ wbd222 MACH_WBD222 WBD222 2753
mt65xx MACH_MT65XX MT65XX 2754
msm8x60_surf MACH_MSM8X60_SURF MSM8X60_SURF 2755
msm8x60_sim MACH_MSM8X60_SIM MSM8X60_SIM 2756
-vmc300 MACH_VMC300 VMC300 2757
tcc8000_sdk MACH_TCC8000_SDK TCC8000_SDK 2758
nanos MACH_NANOS NANOS 2759
stamp9g10 MACH_STAMP9G10 STAMP9G10 2760
@@ -2750,7 +2738,6 @@ h6053 MACH_H6053 H6053 2762
smint01 MACH_SMINT01 SMINT01 2763
prtlvt2 MACH_PRTLVT2 PRTLVT2 2764
ap420 MACH_AP420 AP420 2765
-htcshift MACH_HTCSHIFT HTCSHIFT 2766
davinci_dm365_fc MACH_DAVINCI_DM365_FC DAVINCI_DM365_FC 2767
msm8x55_surf MACH_MSM8X55_SURF MSM8X55_SURF 2768
msm8x55_ffa MACH_MSM8X55_FFA MSM8X55_FFA 2769
@@ -2761,7 +2748,6 @@ oreo_controller MACH_OREO_CONTROLLER OREO_CONTROLLER 2773
kopin_models MACH_KOPIN_MODELS KOPIN_MODELS 2774
ttc_vision2 MACH_TTC_VISION2 TTC_VISION2 2775
cns3420vb MACH_CNS3420VB CNS3420VB 2776
-lpc2 MACH_LPC2 LPC2 2777
olympus MACH_OLYMPUS OLYMPUS 2778
vortex MACH_VORTEX VORTEX 2779
s5pc200 MACH_S5PC200 S5PC200 2780
@@ -2788,7 +2774,6 @@ ti8168evm MACH_TI8168EVM TI8168EVM 2800
neocoreomap MACH_NEOCOREOMAP NEOCOREOMAP 2801
withings_wbp MACH_WITHINGS_WBP WITHINGS_WBP 2802
dbps MACH_DBPS DBPS 2803
-sbc9261 MACH_SBC9261 SBC9261 2804
pcbfp0001 MACH_PCBFP0001 PCBFP0001 2805
speedy MACH_SPEEDY SPEEDY 2806
chrysaor MACH_CHRYSAOR CHRYSAOR 2807
@@ -2812,7 +2797,6 @@ p565 MACH_P565 P565 2824
acer_a4 MACH_ACER_A4 ACER_A4 2825
davinci_dm368_bip MACH_DAVINCI_DM368_BIP DAVINCI_DM368_BIP 2826
eshare MACH_ESHARE ESHARE 2827
-hw_omapl138_europa MACH_HW_OMAPL138_EUROPA HW_OMAPL138_EUROPA 2828
wlbargn MACH_WLBARGN WLBARGN 2829
bm170 MACH_BM170 BM170 2830
netspace_mini_v2 MACH_NETSPACE_MINI_V2 NETSPACE_MINI_V2 2831
@@ -2879,7 +2863,6 @@ davinci_picto MACH_DAVINCI_PICTO DAVINCI_PICTO 2891
mecha MACH_MECHA MECHA 2892
bubba3 MACH_BUBBA3 BUBBA3 2893
pupitre MACH_PUPITRE PUPITRE 2894
-tegra_harmony MACH_TEGRA_HARMONY TEGRA_HARMONY 2895
tegra_vogue MACH_TEGRA_VOGUE TEGRA_VOGUE 2896
tegra_e1165 MACH_TEGRA_E1165 TEGRA_E1165 2897
simplenet MACH_SIMPLENET SIMPLENET 2898
@@ -2969,7 +2952,6 @@ netspace_lite_v2 MACH_NETSPACE_LITE_V2 NETSPACE_LITE_V2 2983
ssc MACH_SSC SSC 2984
premierwave_en MACH_PREMIERWAVE_EN PREMIERWAVE_EN 2985
wasabi MACH_WASABI WASABI 2986
-vivow MACH_VIVOW VIVOW 2987
mx50_rdp MACH_MX50_RDP MX50_RDP 2988
universal_c210 MACH_UNIVERSAL_C210 UNIVERSAL_C210 2989
real6410 MACH_REAL6410 REAL6410 2990
@@ -3017,12 +2999,10 @@ remus MACH_REMUS REMUS 3031
at91cap7xdk MACH_AT91CAP7XDK AT91CAP7XDK 3032
at91cap7stk MACH_AT91CAP7STK AT91CAP7STK 3033
kt_sbc_sam9_1 MACH_KT_SBC_SAM9_1 KT_SBC_SAM9_1 3034
-oratisrouter MACH_ORATISROUTER ORATISROUTER 3035
armada_xp_db MACH_ARMADA_XP_DB ARMADA_XP_DB 3036
spdm MACH_SPDM SPDM 3037
gtib MACH_GTIB GTIB 3038
dgm3240 MACH_DGM3240 DGM3240 3039
-atlas_i_lpe MACH_ATLAS_I_LPE ATLAS_I_LPE 3040
htcmega MACH_HTCMEGA HTCMEGA 3041
tricorder MACH_TRICORDER TRICORDER 3042
tx28 MACH_TX28 TX28 3043
@@ -3062,7 +3042,6 @@ clod MACH_CLOD CLOD 3077
rump MACH_RUMP RUMP 3078
tenderloin MACH_TENDERLOIN TENDERLOIN 3079
shortloin MACH_SHORTLOIN SHORTLOIN 3080
-crespo MACH_CRESPO CRESPO 3081
antares MACH_ANTARES ANTARES 3082
wb40n MACH_WB40N WB40N 3083
herring MACH_HERRING HERRING 3084
@@ -3111,7 +3090,6 @@ smartqv3 MACH_SMARTQV3 SMARTQV3 3126
smartqv7 MACH_SMARTQV7 SMARTQV7 3127
paz00 MACH_PAZ00 PAZ00 3128
acmenetusfoxg20 MACH_ACMENETUSFOXG20 ACMENETUSFOXG20 3129
-htcwillow MACH_HTCWILLOW HTCWILLOW 3130
fwbd_0404 MACH_FWBD_0404 FWBD_0404 3131
hdgu MACH_HDGU HDGU 3132
pyramid MACH_PYRAMID PYRAMID 3133
@@ -3162,7 +3140,6 @@ b5500 MACH_B5500 B5500 3177
s5500 MACH_S5500 S5500 3178
icon MACH_ICON ICON 3179
elephant MACH_ELEPHANT ELEPHANT 3180
-msm8x60_fusion MACH_MSM8X60_FUSION MSM8X60_FUSION 3181
shooter MACH_SHOOTER SHOOTER 3182
spade_lte MACH_SPADE_LTE SPADE_LTE 3183
philhwani MACH_PHILHWANI PHILHWANI 3184
@@ -3174,13 +3151,11 @@ ag5evm MACH_AG5EVM AG5EVM 3189
sc575plc MACH_SC575PLC SC575PLC 3190
sc575hmi MACH_SC575IPC SC575IPC 3191
omap3_tdm3730 MACH_OMAP3_TDM3730 OMAP3_TDM3730 3192
-g7 MACH_G7 G7 3193
top9000_eval MACH_TOP9000_EVAL TOP9000_EVAL 3194
top9000_su MACH_TOP9000_SU TOP9000_SU 3195
utm300 MACH_UTM300 UTM300 3196
tsunagi MACH_TSUNAGI TSUNAGI 3197
ts75xx MACH_TS75XX TS75XX 3198
-msm8x60_fusn_ffa MACH_MSM8X60_FUSN_FFA MSM8X60_FUSN_FFA 3199
ts47xx MACH_TS47XX TS47XX 3200
da850_k5 MACH_DA850_K5 DA850_K5 3201
ax502 MACH_AX502 AX502 3202
@@ -3285,7 +3260,7 @@ rfl109145_ssrv MACH_RFL109145_SSRV RFL109145_SSRV 3304
nmh MACH_NMH NMH 3305
wn802t MACH_WN802T WN802T 3306
dragonet MACH_DRAGONET DRAGONET 3307
-geneva_b MACH_GENEVA_B GENEVA_B 3308
+geneva_b4 MACH_GENEVA_B GENEVA_B 3308
at91sam9263desk16l MACH_AT91SAM9263DESK16L AT91SAM9263DESK16L 3309
bcmhana_sv MACH_BCMHANA_SV BCMHANA_SV 3310
bcmhana_tablet MACH_BCMHANA_TABLET BCMHANA_TABLET 3311
@@ -3316,3 +3291,85 @@ rover_g8 MACH_ROVER_G8 ROVER_G8 3335
t5388p MACH_T5388P T5388P 3336
dingo MACH_DINGO DINGO 3337
goflexhome MACH_GOFLEXHOME GOFLEXHOME 3338
+lanreadyfn511 MACH_LANREADYFN511 LANREADYFN511 3340
+omap3_baia MACH_OMAP3_BAIA OMAP3_BAIA 3341
+omap3smartdisplay MACH_OMAP3SMARTDISPLAY OMAP3SMARTDISPLAY 3342
+xilinx MACH_XILINX XILINX 3343
+a2f MACH_A2F A2F 3344
+sky25 MACH_SKY25 SKY25 3345
+ccmx53 MACH_CCMX53 CCMX53 3346
+ccmx53js MACH_CCMX53JS CCMX53JS 3347
+ccwmx53 MACH_CCWMX53 CCWMX53 3348
+ccwmx53js MACH_CCWMX53JS CCWMX53JS 3349
+frisms MACH_FRISMS FRISMS 3350
+msm7x27a_ffa MACH_MSM7X27A_FFA MSM7X27A_FFA 3351
+msm7x27a_surf MACH_MSM7X27A_SURF MSM7X27A_SURF 3352
+msm7x27a_rumi3 MACH_MSM7X27A_RUMI3 MSM7X27A_RUMI3 3353
+dimmsam9g20 MACH_DIMMSAM9G20 DIMMSAM9G20 3354
+dimm_imx28 MACH_DIMM_IMX28 DIMM_IMX28 3355
+amk_a4 MACH_AMK_A4 AMK_A4 3356
+gnet_sgme MACH_GNET_SGME GNET_SGME 3357
+shooter_u MACH_SHOOTER_U SHOOTER_U 3358
+vmx53 MACH_VMX53 VMX53 3359
+rhino MACH_RHINO RHINO 3360
+armlex4210 MACH_ARMLEX4210 ARMLEX4210 3361
+swarcoextmodem MACH_SWARCOEXTMODEM SWARCOEXTMODEM 3362
+snowball MACH_SNOWBALL SNOWBALL 3363
+pcm049 MACH_PCM049 PCM049 3364
+vigor MACH_VIGOR VIGOR 3365
+oslo_amundsen MACH_OSLO_AMUNDSEN OSLO_AMUNDSEN 3366
+gsl_diamond MACH_GSL_DIAMOND GSL_DIAMOND 3367
+cv2201 MACH_CV2201 CV2201 3368
+cv2202 MACH_CV2202 CV2202 3369
+cv2203 MACH_CV2203 CV2203 3370
+vit_ibox MACH_VIT_IBOX VIT_IBOX 3371
+dm6441_esp MACH_DM6441_ESP DM6441_ESP 3372
+at91sam9x5ek MACH_AT91SAM9X5EK AT91SAM9X5EK 3373
+libra MACH_LIBRA LIBRA 3374
+easycrrh MACH_EASYCRRH EASYCRRH 3375
+tripel MACH_TRIPEL TRIPEL 3376
+endian_mini MACH_ENDIAN_MINI ENDIAN_MINI 3377
+xilinx_ep107 MACH_XILINX_EP107 XILINX_EP107 3378
+nuri MACH_NURI NURI 3379
+janus MACH_JANUS JANUS 3380
+ddnas MACH_DDNAS DDNAS 3381
+tag MACH_TAG TAG 3382
+tagw MACH_TAGW TAGW 3383
+nitrogen_vm_imx51 MACH_NITROGEN_VM_IMX51 NITROGEN_VM_IMX51 3384
+viprinet MACH_VIPRINET VIPRINET 3385
+bockw MACH_BOCKW BOCKW 3386
+eva2000 MACH_EVA2000 EVA2000 3387
+steelyard MACH_STEELYARD STEELYARD 3388
+ea2468devkit MACH_LPC2468OEM LPC2468OEM 3389
+sdh001 MACH_MACH_SDH001 MACH_SDH001 3390
+fe2478microblox MACH_LPC2478MICROBLOX LPC2478MICROBLOX 3391
+nsslsboard MACH_NSSLSBOARD NSSLSBOARD 3392
+geneva_b5 MACH_GENEVA_B5 GENEVA_B5 3393
+spear1340 MACH_SPEAR1340 SPEAR1340 3394
+rexmas MACH_REXMAS REXMAS 3395
+msm8960_cdp MACH_MSM8960_CDP MSM8960_CDP 3396
+msm8960_mdp MACH_MSM8960_MDP MSM8960_MDP 3397
+msm8960_fluid MACH_MSM8960_FLUID MSM8960_FLUID 3398
+msm8960_apq MACH_MSM8960_APQ MSM8960_APQ 3399
+helios_v2 MACH_HELIOS_V2 HELIOS_V2 3400
+mif10p MACH_MIF10P MIF10P 3401
+iam28 MACH_IAM28 IAM28 3402
+picasso MACH_PICASSO PICASSO 3403
+mr301a MACH_MR301A MR301A 3404
+notle MACH_NOTLE NOTLE 3405
+eelx2 MACH_EELX2 EELX2 3406
+moon MACH_MOON MOON 3407
+ruby MACH_RUBY RUBY 3408
+goldengate MACH_GOLDENGATE GOLDENGATE 3409
+ctbu_gen2 MACH_CTBU_GEN2 CTBU_GEN2 3410
+kmp_am17_01 MACH_KMP_AM17_01 KMP_AM17_01 3411
+wtplug MACH_WTPLUG WTPLUG 3412
+mx27su2 MACH_MX27SU2 MX27SU2 3413
+nb31 MACH_NB31 NB31 3414
+hjsdu MACH_HJSDU HJSDU 3415
+td3_rev1 MACH_TD3_REV1 TD3_REV1 3416
+eag_ci4000 MACH_EAG_CI4000 EAG_CI4000 3417
+net5big_nand_v2 MACH_NET5BIG_NAND_V2 NET5BIG_NAND_V2 3418
+cpx2 MACH_CPX2 CPX2 3419
+net2big_nand_v2 MACH_NET2BIG_NAND_V2 NET2BIG_NAND_V2 3420
+ecuv5 MACH_ECUV5 ECUV5 3421
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 8/9] lpc2k: Add UART, SSP, and MCI devices
2011-03-20 20:30 [PATCH v3 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
` (6 preceding siblings ...)
2011-03-20 20:30 ` [PATCH v3 7/9] lpc2k: Add EmbeddedArtists LPC2478 Developer's Kit board Ithamar R. Adema
@ 2011-03-20 20:30 ` Ithamar R. Adema
2011-03-20 20:30 ` [PATCH v3 9/9] lpc2k: defconfig for NXP LPC2K platform Ithamar R. Adema
8 siblings, 0 replies; 12+ messages in thread
From: Ithamar R. Adema @ 2011-03-20 20:30 UTC (permalink / raw)
To: linux-arm-kernel
Adds devices for which the drivers are already in the tree. For
the relevant devices, let the ea2478devkit board set them up.
Signed-off-by: Ithamar R. Adema <ithamar.adema@team-embedded.nl>
---
changes since v2:
* removed clk_put() from UART init routine.
no changes since v1.
---
arch/arm/Kconfig | 1 +
arch/arm/mach-lpc2k/Makefile | 2 +-
arch/arm/mach-lpc2k/common.h | 4 +
arch/arm/mach-lpc2k/devices.c | 173 +++++++++++++++++++++++++++
arch/arm/mach-lpc2k/include/mach/hardware.h | 6 +
arch/arm/mach-lpc2k/mach-ea2478devkit.c | 20 +++
6 files changed, 205 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/mach-lpc2k/devices.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a95a232..13b436b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -496,6 +496,7 @@ config ARCH_LPC2K
depends on !MMU
select CPU_ARM7TDMI
select ARM_VIC
+ select ARM_AMBA
select CLKDEV_LOOKUP
select GENERIC_CLOCKEVENTS
select ARCH_REQUIRE_GPIOLIB
diff --git a/arch/arm/mach-lpc2k/Makefile b/arch/arm/mach-lpc2k/Makefile
index 93e27fb..aa2b353 100644
--- a/arch/arm/mach-lpc2k/Makefile
+++ b/arch/arm/mach-lpc2k/Makefile
@@ -1,3 +1,3 @@
obj-y := clock.o irq.o gpio.o mfp.o time.o
-obj-$(CONFIG_MACH_EA2478DEVKIT) += mach-ea2478devkit.o
+obj-$(CONFIG_MACH_EA2478DEVKIT) += mach-ea2478devkit.o devices.o
diff --git a/arch/arm/mach-lpc2k/common.h b/arch/arm/mach-lpc2k/common.h
index 6b775d9..1d4c21e 100644
--- a/arch/arm/mach-lpc2k/common.h
+++ b/arch/arm/mach-lpc2k/common.h
@@ -16,6 +16,10 @@ extern void lpc2k_init_clocks(unsigned long xtal, unsigned long rtc);
extern void lpc2k_mfp_config(unsigned long *mfp_cfgs, int num);
extern void lpc2k_init_irq(void);
+extern void lpc2k_add_uart(int nr);
+extern void lpc2k_add_ssp(int nr, void *platform_data);
+extern void lpc2k_add_mci(void *platform_data, int pwr_high);
+
extern struct sys_timer lpc2k_timer;
#endif /* LPC2K_COMMON_H */
diff --git a/arch/arm/mach-lpc2k/devices.c b/arch/arm/mach-lpc2k/devices.c
new file mode 100644
index 0000000..8e7de6d
--- /dev/null
+++ b/arch/arm/mach-lpc2k/devices.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2011 Team Embeded VOF
+ * Ithamar R. Adema <ihamar.adema@team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <linux/amba/bus.h>
+#include <linux/amba/mmci.h>
+#include <linux/amba/pl022.h>
+
+#include <mach/hardware.h>
+
+/* System Control Block - System Controls and Status register */
+#define SCS 0x1a0
+
+#define __IORESOURCE_MEM_16K(x) { \
+ .start = x, \
+ .end = x + SZ_16K - 1, \
+ .flags = IORESOURCE_MEM, \
+ }
+
+#define __IORESOURCE_IRQ(x) { \
+ .start = x, \
+ . end = x, \
+ }
+
+/* UARTs
+ * 0/1 are available on all LPC2Ks
+ * 2/3 are available on LPC23XX and up.
+ *
+ * NOTE: the dev.init_name assignment is there so we can use the clk API to
+ * retrieve and enable the clock, since dev_name() is called from
+ * the clk_get implementation before the platform device is registered.
+ */
+
+#define LPC2K_UART(uartnum) \
+ static struct plat_serial8250_port lpc2k_pdata_uart##uartnum[] = { \
+ { \
+ .mapbase = APB_UART##uartnum##_BASE, \
+ .membase = (void __iomem *) \
+ APB_UART##uartnum##_BASE, \
+ .irq = IRQ_LPC2K_UART##uartnum, \
+ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF, \
+ .iotype = UPIO_MEM, \
+ .regshift = 2, \
+ .uartclk = 0, \
+ }, \
+ { }, \
+ }; \
+ static struct resource lpc2k_resources_uart##uartnum[] = { \
+ [0] = __IORESOURCE_MEM_16K(APB_UART##uartnum##_BASE), \
+ [1] = __IORESOURCE_IRQ(IRQ_LPC2K_UART##uartnum), \
+ }; \
+ static struct platform_device lpc2k_device_uart##uartnum = { \
+ .dev = { \
+ .init_name = "serial8250." __stringify(uartnum), \
+ .platform_data = lpc2k_pdata_uart##uartnum, \
+ }, \
+ .name = "serial8250", \
+ .id = uartnum, \
+ .resource = lpc2k_resources_uart##uartnum, \
+ .num_resources = ARRAY_SIZE(lpc2k_resources_uart##uartnum), \
+ }
+
+
+LPC2K_UART(0);
+LPC2K_UART(1);
+LPC2K_UART(2);
+LPC2K_UART(3);
+
+static struct platform_device *uarts[] __initdata = {
+ &lpc2k_device_uart0,
+ &lpc2k_device_uart1,
+ &lpc2k_device_uart2,
+ &lpc2k_device_uart3,
+};
+
+void __init lpc2k_add_uart(int nr)
+{
+ struct platform_device *pdev;
+ struct clk *clk;
+ int res;
+
+ BUG_ON(nr < 0 || nr > ARRAY_SIZE(uarts));
+ pdev = uarts[nr];
+
+ clk = clk_get(&pdev->dev, NULL);
+ BUG_ON(IS_ERR(clk));
+ clk_enable(clk);
+ ((struct plat_serial8250_port *)pdev->dev.platform_data)->uartclk =
+ clk_get_rate(clk);
+
+ res = platform_device_register(pdev);
+ if (res)
+ dev_err(&pdev->dev, "Unable to register: %d\n", res);
+}
+
+/* SSP, aka pl022
+ *
+ * 1-only available on enhanced LPC21XX and LPC22XX.
+ * 0/1 available on LPC23XX and up.
+ */
+
+static struct amba_device lpc2k_device_ssp0 = {
+ .dev = {
+ .coherent_dma_mask = ~0,
+ .init_name = "ssp0",
+ },
+ .res = __IORESOURCE_MEM_16K(APB_SSP0_BASE),
+ .irq = { IRQ_LPC2K_SPI0, NO_IRQ },
+};
+
+static struct amba_device lpc2k_device_ssp1 = {
+ .dev = {
+ .coherent_dma_mask = ~0,
+ .init_name = "ssp1",
+ },
+ .res = __IORESOURCE_MEM_16K(APB_SSP1_BASE),
+ .irq = { IRQ_LPC2K_SPI1, NO_IRQ },
+};
+
+void __init lpc2k_add_ssp(int nr, void *platform_data)
+{
+ struct amba_device *adev;
+ int res;
+
+ BUG_ON(nr < 0 || nr > 1);
+ adev = nr ? &lpc2k_device_ssp1 : &lpc2k_device_ssp0;
+ adev->dev.platform_data = platform_data;
+
+ res = amba_device_register(adev, &iomem_resource);
+ if (res)
+ dev_err(&adev->dev, "Unable to register: %d\n", res);
+}
+
+/* SD/MMC, aka pl180/1
+ *
+ * Available on LPC23XX and up.
+ */
+
+static struct amba_device lpc2k_device_mci = {
+ .dev = {
+ .coherent_dma_mask = ~0,
+ .init_name = "mci",
+ },
+ .res = __IORESOURCE_MEM_16K(APB_MCI_BASE),
+ .irq = { IRQ_LPC2K_MCI, NO_IRQ },
+};
+
+void __init lpc2k_add_mci(void *platform_data, int pwr_high)
+{
+ int res;
+ u32 scs;
+
+ /* Set MCIPWR pin to be active high or low */
+ scs = ioread32(APB_SCB_BASE + SCS);
+ scs = pwr_high ? scs | (1 << 3) : scs & ~(1 << 3);
+ iowrite32(scs, APB_SCB_BASE + SCS);
+
+ lpc2k_device_mci.dev.platform_data = platform_data;
+ res = amba_device_register(&lpc2k_device_mci, &iomem_resource);
+ if (res)
+ dev_err(&lpc2k_device_mci.dev, "Unable to register: %d\n", res);
+}
diff --git a/arch/arm/mach-lpc2k/include/mach/hardware.h b/arch/arm/mach-lpc2k/include/mach/hardware.h
index 1a20126..b2e3a18 100644
--- a/arch/arm/mach-lpc2k/include/mach/hardware.h
+++ b/arch/arm/mach-lpc2k/include/mach/hardware.h
@@ -20,8 +20,14 @@
#define APB_TIMER0_BASE 0xe0004000
#define APB_TIMER1_BASE 0xe0008000
#define APB_UART0_BASE 0xe000c000
+#define APB_UART1_BASE 0xe0010000
#define APB_GPIO_BASE 0xe0028000
#define APB_PINSEL_BASE 0xe002c000
+#define APB_SSP1_BASE 0xe0030000
+#define APB_SSP0_BASE 0xe0068000
+#define APB_UART2_BASE 0xe0078000
+#define APB_UART3_BASE 0xe007c000
+#define APB_MCI_BASE 0xe008c000
#define APB_SCB_BASE 0xe01fc000
#define APH_VIC_BASE 0xfffff000
diff --git a/arch/arm/mach-lpc2k/mach-ea2478devkit.c b/arch/arm/mach-lpc2k/mach-ea2478devkit.c
index d59f5ba..4d7e95b 100644
--- a/arch/arm/mach-lpc2k/mach-ea2478devkit.c
+++ b/arch/arm/mach-lpc2k/mach-ea2478devkit.c
@@ -8,6 +8,8 @@
*/
#include <linux/module.h>
+#include <linux/amba/pl022.h>
+#include <linux/amba/mmci.h>
#include <linux/gpio.h>
#include <linux/io.h>
@@ -96,9 +98,27 @@ static unsigned long mfp_cfgs[] __initdata = {
P1_12_MCIDAT3,
};
+static struct pl022_ssp_controller ssp0_plat_data = {
+ .bus_id = 0,
+ .enable_dma = 0,
+ .num_chipselect = 1,
+};
+
+static struct mmci_platform_data mci_plat_data = {
+ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
+ .capabilities = MMC_CAP_4_BIT_DATA,
+ .f_max = 200000,
+ .gpio_cd = -1,
+ .gpio_wp = -1,
+};
+
void __init ea2478devkit_init_machine(void)
{
lpc2k_mfp_config(mfp_cfgs, ARRAY_SIZE(mfp_cfgs));
+
+ lpc2k_add_uart(0);
+ lpc2k_add_ssp(0, &ssp0_plat_data);
+ lpc2k_add_mci(&mci_plat_data, 0 /* active low */);
}
static void __init ea2478devkit_init_irq(void)
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v3 9/9] lpc2k: defconfig for NXP LPC2K platform
2011-03-20 20:30 [PATCH v3 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
` (7 preceding siblings ...)
2011-03-20 20:30 ` [PATCH v3 8/9] lpc2k: Add UART, SSP, and MCI devices Ithamar R. Adema
@ 2011-03-20 20:30 ` Ithamar R. Adema
8 siblings, 0 replies; 12+ messages in thread
From: Ithamar R. Adema @ 2011-03-20 20:30 UTC (permalink / raw)
To: linux-arm-kernel
Add a defconfig that is setup to support booting a uClinux based
system. This enables ROMFS/CRAMFS, initrd, and FLAT binaries besides
the drivers for the devices added in the previous patch.
Signed-off-by: Ithamar R. Adema <ithamar.adema@team-embedded.nl>
---
no changes since v2.
changes since v1:
* enabled CONFIG_MAGIC_SYSRQ for testing arch_reset.
---
arch/arm/configs/lpc2k_defconfig | 57 ++++++++++++++++++++++++++++++++++++++
1 files changed, 57 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/configs/lpc2k_defconfig
diff --git a/arch/arm/configs/lpc2k_defconfig b/arch/arm/configs/lpc2k_defconfig
new file mode 100644
index 0000000..47a7bcf
--- /dev/null
+++ b/arch/arm/configs/lpc2k_defconfig
@@ -0,0 +1,57 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_TINY_RCU=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_MMU is not set
+CONFIG_ARCH_LPC2K=y
+CONFIG_MACH_EA2478DEVKIT=y
+CONFIG_PROCESSOR_ID=0x41007700
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_CMDLINE="root=/dev/ram initrd=0xa1a00000,4000k console=ttyS0,115200N8 debug rw earlyprintk"
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+CONFIG_BINFMT_SHARED_FLAT=y
+# CONFIG_SUSPEND is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_SPI=y
+CONFIG_SPI_PL022=y
+# CONFIG_HWMON is not set
+# CONFIG_MFD_SUPPORT is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+CONFIG_MMC_ARMMMCI=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_FTRACE is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
--
1.7.1
^ permalink raw reply related [flat|nested] 12+ messages in thread