linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/9] Support for NXP LPC2K SoCs
@ 2011-03-17 15:54 Ithamar R. Adema
  2011-03-17 15:54 ` [PATCH 1/9] lpc2k: Core support Ithamar R. Adema
                   ` (10 more replies)
  0 siblings, 11 replies; 30+ messages in thread
From: Ithamar R. Adema @ 2011-03-17 15:54 UTC (permalink / raw)
  To: linux-arm-kernel

The following patch series implements support for the ARM7TDMI-S based
NXP LPC2K System-on-Chips, and, as first board, the EmbeddedArtists
LPC2478 Developer's Kit.

This code will work on the LPC23XX and LPC24XX ranges of chips, but will
need some more work for LPC21XX and LPC22XX chips.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 1/9] lpc2k: Core support
  2011-03-17 15:54 [PATCH 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
@ 2011-03-17 15:54 ` Ithamar R. Adema
  2011-03-17 21:26   ` Jamie Iles
                     ` (2 more replies)
  2011-03-17 15:54 ` [PATCH 2/9] lpc2k: Exception vector handling Ithamar R. Adema
                   ` (9 subsequent siblings)
  10 siblings, 3 replies; 30+ messages in thread
From: Ithamar R. Adema @ 2011-03-17 15:54 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>
---
 arch/arm/Kconfig                               |   14 +++++++
 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    |   23 +++++++++++
 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/system.h      |   23 +++++++++++
 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 ++++++++
 15 files changed, 286 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/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 e34bf02..331540d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -490,6 +490,18 @@ 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_TIME
+	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
@@ -928,6 +940,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 5c7114b..601f52a 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..7663e97
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/hardware.h
@@ -0,0 +1,23 @@
+/*
+ * 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_TIMER0_BASE		0xe0004000
+#define APB_TIMER1_BASE		0xe0008000
+#define APB_UART0_BASE		0xe000c000
+#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/system.h b/arch/arm/mach-lpc2k/include/mach/system.h
new file mode 100644
index 0000000..fbbea43
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/system.h
@@ -0,0 +1,23 @@
+/*
+ * 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
+
+static void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+	cpu_reset(0);
+}
+
+#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] 30+ messages in thread

* [PATCH 2/9] lpc2k: Exception vector handling
  2011-03-17 15:54 [PATCH 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
  2011-03-17 15:54 ` [PATCH 1/9] lpc2k: Core support Ithamar R. Adema
@ 2011-03-17 15:54 ` Ithamar R. Adema
  2011-03-17 16:18   ` Uwe Kleine-König
  2011-03-17 15:54 ` [PATCH 3/9] lpc2k: clk API Ithamar R. Adema
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Ithamar R. Adema @ 2011-03-17 15:54 UTC (permalink / raw)
  To: linux-arm-kernel

Since the LPC2K does not have an MMU (ARM7TDMI based), it expects the vectors to be
stored in on-chip SRAM. However, this moves the vectors too far away from the stubs
page, requiring the vector jumps to be indirect.

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>
---
 arch/arm/Kconfig             |    1 +
 arch/arm/kernel/entry-armv.S |   18 ++++++++++++++++++
 arch/arm/kernel/traps.c      |    2 +-
 arch/arm/mm/nommu.c          |    2 ++
 4 files changed, 22 insertions(+), 1 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 331540d..9c12d71 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..618a971 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,23 @@ __vectors_start:
 	W(b)	vector_addrexcptn + stubs_offset
 	W(b)	vector_irq + stubs_offset
 	W(b)	vector_fiq + stubs_offset
+#else /* CONFIG_ARCH_LPC2K */
+	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] 30+ messages in thread

* [PATCH 3/9] lpc2k: clk API
  2011-03-17 15:54 [PATCH 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
  2011-03-17 15:54 ` [PATCH 1/9] lpc2k: Core support Ithamar R. Adema
  2011-03-17 15:54 ` [PATCH 2/9] lpc2k: Exception vector handling Ithamar R. Adema
@ 2011-03-17 15:54 ` Ithamar R. Adema
  2011-03-17 22:08   ` Kevin Wells
  2011-03-17 22:16   ` Kevin Wells
  2011-03-17 15:54 ` [PATCH 4/9] lpc2k: generic time and clockevents Ithamar R. Adema
                   ` (7 subsequent siblings)
  10 siblings, 2 replies; 30+ messages in thread
From: Ithamar R. Adema @ 2011-03-17 15:54 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>
---
 arch/arm/Kconfig                              |    1 +
 arch/arm/mach-lpc2k/Makefile                  |    2 +-
 arch/arm/mach-lpc2k/clock.c                   |  355 +++++++++++++++++++++++++
 arch/arm/mach-lpc2k/include/mach/clkdev.h     |   17 ++
 arch/arm/mach-lpc2k/include/mach/hardware.h   |    1 +
 arch/arm/mach-lpc2k/include/mach/regs-clock.h |   36 +++
 6 files changed, 411 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-lpc2k/clock.c
 create mode 100644 arch/arm/mach-lpc2k/include/mach/clkdev.h
 create mode 100644 arch/arm/mach-lpc2k/include/mach/regs-clock.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9c12d71..35297f9 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_TIME
 	select GENERIC_CLOCKEVENTS
 	help
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..3ef4521
--- /dev/null
+++ b/arch/arm/mach-lpc2k/clock.c
@@ -0,0 +1,355 @@
+/*
+ * 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-clock.h>
+
+#define clk_readl(a)	\
+	__raw_readl((void __iomem *)APB_SCB_BASE + (a))
+#define clk_writel(v, a)	\
+	__raw_writel(v, (void __iomem *)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_MUTEX(clocks_mutex);
+
+/*-------------------------------------------------------------------------
+ * 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)
+{
+	int ret = 0;
+
+	if (!clk)
+		return -EINVAL;
+
+	mutex_lock(&clocks_mutex);
+	ret = __clk_enable(clk);
+	mutex_unlock(&clocks_mutex);
+
+	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)
+{
+	if (!clk)
+		return;
+
+	mutex_lock(&clocks_mutex);
+	__clk_disable(clk);
+	mutex_unlock(&clocks_mutex);
+}
+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)
+{
+	int ret = -EINVAL;
+
+	if (!clk)
+		return ret;
+	if (!clk->set_rate || !rate)
+		return ret;
+
+	mutex_lock(&clocks_mutex);
+	ret = clk->set_rate(clk, rate);
+	mutex_unlock(&clocks_mutex);
+
+	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)
+{
+	struct clk *old;
+	int ret = -EINVAL;
+
+	if (!clk)
+		return ret;
+	if (!clk->set_parent || !parent)
+		return ret;
+
+	mutex_lock(&clocks_mutex);
+	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);
+	mutex_unlock(&clocks_mutex);
+
+	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 */
diff --git a/arch/arm/mach-lpc2k/include/mach/hardware.h b/arch/arm/mach-lpc2k/include/mach/hardware.h
index 7663e97..ce19ff7 100644
--- a/arch/arm/mach-lpc2k/include/mach/hardware.h
+++ b/arch/arm/mach-lpc2k/include/mach/hardware.h
@@ -18,6 +18,7 @@
 #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/regs-clock.h b/arch/arm/mach-lpc2k/include/mach/regs-clock.h
new file mode 100644
index 0000000..1c94582
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/regs-clock.h
@@ -0,0 +1,36 @@
+/*
+ * 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_CLOCK_H
+#define MACH_LPC2K_REGS_CLOCK_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) & 0xf) + 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 INTWAKE		0x144
+#define PCONP		0x0c4
+
+#endif /* MACH_LPC2K_REGS_CLOCK_H */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 4/9] lpc2k: generic time and clockevents
  2011-03-17 15:54 [PATCH 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
                   ` (2 preceding siblings ...)
  2011-03-17 15:54 ` [PATCH 3/9] lpc2k: clk API Ithamar R. Adema
@ 2011-03-17 15:54 ` Ithamar R. Adema
  2011-03-17 21:38   ` Jamie Iles
  2011-03-17 15:54 ` [PATCH 5/9] lpc2k: gpiolib Ithamar R. Adema
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Ithamar R. Adema @ 2011-03-17 15:54 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>
---
 arch/arm/mach-lpc2k/Makefile |    2 +-
 arch/arm/mach-lpc2k/time.c   |  174 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 175 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..b430f7c
--- /dev/null
+++ b/arch/arm/mach-lpc2k/time.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2011 Team Embeded VOF
+ * 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,
+	.shift		= 32,
+	.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_put(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. */
+	lpc2k_clkevt.mult = div_sc(rate, NSEC_PER_SEC,
+		lpc2k_clkevt.shift);
+	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] 30+ messages in thread

* [PATCH 5/9] lpc2k: gpiolib
  2011-03-17 15:54 [PATCH 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
                   ` (3 preceding siblings ...)
  2011-03-17 15:54 ` [PATCH 4/9] lpc2k: generic time and clockevents Ithamar R. Adema
@ 2011-03-17 15:54 ` Ithamar R. Adema
  2011-03-17 15:54 ` [PATCH 6/9] lpc2k: multifunction pin configuration Ithamar R. Adema
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 30+ messages in thread
From: Ithamar R. Adema @ 2011-03-17 15:54 UTC (permalink / raw)
  To: linux-arm-kernel

gpiolib support, including gpio interrupts.

Signed-off-by: Ithamar R. Adema <ithamar.adema@team-embedded.nl>
---
 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     |   22 +++
 arch/arm/mach-lpc2k/include/mach/hardware.h |    2 +
 arch/arm/mach-lpc2k/include/mach/irqs.h     |   69 +++++++-
 6 files changed, 359 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 35297f9..fce855d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -499,6 +499,7 @@ config ARCH_LPC2K
 	select CLKDEV_LOOKUP
 	select GENERIC_TIME
 	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..44f0eb9
--- /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_GPIO0),
+	LPC2K_GPIO_CHIP("P1", 32, 32, -1),
+	LPC2K_GPIO_CHIP("P2", 64, 32, IRQ_LPC2K_GPIO64),
+	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_GPIO0 + 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_GPIO64 + 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_GPIO0; i <= IRQ_LPC2K_GPIO31; 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_GPIO64; i <= IRQ_LPC2K_GPIO95; 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..efa970a
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/gpio.h
@@ -0,0 +1,22 @@
+/*
+ *  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
+
+#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 ce19ff7..0d7c10c 100644
--- a/arch/arm/mach-lpc2k/include/mach/hardware.h
+++ b/arch/arm/mach-lpc2k/include/mach/hardware.h
@@ -15,9 +15,11 @@
 /* Default memory size if no ATAGS found */
 #define MEM_SIZE	(SZ_32M)
 
+#define FAST_GPIO_BASE		0x3fffc000
 #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..b7b2410 100644
--- a/arch/arm/mach-lpc2k/include/mach/irqs.h
+++ b/arch/arm/mach-lpc2k/include/mach/irqs.h
@@ -44,6 +44,73 @@
 #define IRQ_LPC2K_I2C2		30
 #define IRQ_LPC2K_I2S		31
 
-#define NR_IRQS			32
+#define IRQ_LPC2K_GPIO0		32
+#define IRQ_LPC2K_GPIO1		33
+#define IRQ_LPC2K_GPIO2		34
+#define IRQ_LPC2K_GPIO3		35
+#define IRQ_LPC2K_GPIO4		36
+#define IRQ_LPC2K_GPIO5		37
+#define IRQ_LPC2K_GPIO6		38
+#define IRQ_LPC2K_GPIO7		39
+#define IRQ_LPC2K_GPIO8		40
+#define IRQ_LPC2K_GPIO9		41
+#define IRQ_LPC2K_GPIO10	42
+#define IRQ_LPC2K_GPIO11	43
+#define IRQ_LPC2K_GPIO12	44
+#define IRQ_LPC2K_GPIO13	45
+#define IRQ_LPC2K_GPIO14	46
+#define IRQ_LPC2K_GPIO15	47
+#define IRQ_LPC2K_GPIO16	48
+#define IRQ_LPC2K_GPIO17	49
+#define IRQ_LPC2K_GPIO18	50
+#define IRQ_LPC2K_GPIO19	51
+#define IRQ_LPC2K_GPIO20	52
+#define IRQ_LPC2K_GPIO21	53
+#define IRQ_LPC2K_GPIO22	54
+#define IRQ_LPC2K_GPIO23	55
+#define IRQ_LPC2K_GPIO24	56
+#define IRQ_LPC2K_GPIO25	57
+#define IRQ_LPC2K_GPIO26	58
+#define IRQ_LPC2K_GPIO27	59
+#define IRQ_LPC2K_GPIO28	60
+#define IRQ_LPC2K_GPIO29	61
+#define IRQ_LPC2K_GPIO30	62
+#define IRQ_LPC2K_GPIO31	63
+
+/* GPIO P2 */
+#define IRQ_LPC2K_GPIO64	64
+#define IRQ_LPC2K_GPIO65	65
+#define IRQ_LPC2K_GPIO66	66
+#define IRQ_LPC2K_GPIO67	67
+#define IRQ_LPC2K_GPIO68	68
+#define IRQ_LPC2K_GPIO69	69
+#define IRQ_LPC2K_GPIO70	70
+#define IRQ_LPC2K_GPIO71	71
+#define IRQ_LPC2K_GPIO72	72
+#define IRQ_LPC2K_GPIO73	73
+#define IRQ_LPC2K_GPIO74	74
+#define IRQ_LPC2K_GPIO75	75
+#define IRQ_LPC2K_GPIO76	76
+#define IRQ_LPC2K_GPIO77	77
+#define IRQ_LPC2K_GPIO78	78
+#define IRQ_LPC2K_GPIO79	79
+#define IRQ_LPC2K_GPIO80	80
+#define IRQ_LPC2K_GPIO81	81
+#define IRQ_LPC2K_GPIO82	82
+#define IRQ_LPC2K_GPIO83	83
+#define IRQ_LPC2K_GPIO84	84
+#define IRQ_LPC2K_GPIO85	85
+#define IRQ_LPC2K_GPIO86	86
+#define IRQ_LPC2K_GPIO87	87
+#define IRQ_LPC2K_GPIO88	88
+#define IRQ_LPC2K_GPIO89	89
+#define IRQ_LPC2K_GPIO90	90
+#define IRQ_LPC2K_GPIO91	91
+#define IRQ_LPC2K_GPIO92	92
+#define IRQ_LPC2K_GPIO93	93
+#define IRQ_LPC2K_GPIO94	94
+#define IRQ_LPC2K_GPIO95	95
+
+#define NR_IRQS			96
 
 #endif /* MACH_LPC2K_IRQS_H */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 6/9] lpc2k: multifunction pin configuration
  2011-03-17 15:54 [PATCH 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
                   ` (4 preceding siblings ...)
  2011-03-17 15:54 ` [PATCH 5/9] lpc2k: gpiolib Ithamar R. Adema
@ 2011-03-17 15:54 ` Ithamar R. Adema
  2011-03-17 15:54 ` [PATCH 7/9] lpc2k: Add EmbeddedArtists LPC2478 Developer's Kit board Ithamar R. Adema
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 30+ messages in thread
From: Ithamar R. Adema @ 2011-03-17 15:54 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>
---
 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         |  209 ++++++++++++++++++++++++
 arch/arm/mach-lpc2k/mfp.c                      |   99 +++++++++++
 5 files changed, 408 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 0d7c10c..29c561a 100644
--- a/arch/arm/mach-lpc2k/include/mach/hardware.h
+++ b/arch/arm/mach-lpc2k/include/mach/hardware.h
@@ -20,6 +20,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..9b6bec4
--- /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 GPIO0_RD1		MFP_CFG(GPIO0, AF1)
+#define GPIO0_TXD3		MFP_CFG(GPIO0, AF2)
+#define GPIO0_SDA1		MFP_CFG(GPIO0, AF3)
+#define GPIO1_TD1		MFP_CFG(GPIO1, AF1)
+#define GPIO1_RXD3		MFP_CFG(GPIO1, AF2)
+#define GPIO1_SCL1		MFP_CFG(GPIO1, AF3)
+#define GPIO2_TXD0		MFP_CFG(GPIO2, AF1)
+#define GPIO3_RXD0		MFP_CFG(GPIO3, AF1)
+#define GPIO4_LCDVD0		MFP_CFG(GPIO4, AF1)
+#define GPIO5_LCDVD1		MFP_CFG(GPIO5, AF1)
+#define GPIO6_LCDVD8		MFP_CFG(GPIO6, AF1)
+#define GPIO7_LCDVD9		MFP_CFG(GPIO7, AF1)
+#define GPIO8_LCDVD16		MFP_CFG(GPIO8, AF1)
+#define GPIO9_LCDVD17		MFP_CFG(GPIO9, AF1)
+#define GPIO10_TXD2		MFP_CFG(GPIO10, AF1)
+#define GPIO11_RXD2		MFP_CFG(GPIO11, AF1)
+#define GPIO12_USB_PPWR2	MFP_CFG(GPIO12, AF1)
+#define GPIO13_USB_UP_LED2	MFP_CFG(GPIO13, AF1)
+#define GPIO15_SCK		MFP_CFG(GPIO15, AF3)
+#define GPIO17_MISO		MFP_CFG(GPIO17, AF3)
+#define GPIO18_MOSI		MFP_CFG(GPIO18, AF3)
+#define GPIO27_SDA0		MFP_CFG(GPIO27, AF1)
+#define GPIO28_SCL0		MFP_CFG(GPIO28, AF1)
+#define GPIO29_USB_Dp1		MFP_CFG(GPIO29, AF1)
+#define GPIO30_USB_Dn1		MFP_CFG(GPIO30, AF1)
+#define GPIO31_USB_Dp2		MFP_CFG(GPIO31, AF1)
+#define GPIO32_ENET_TXD0	MFP_CFG(GPIO32, AF1)
+#define GPIO33_ENET_TXD1	MFP_CFG(GPIO33, AF1)
+#define GPIO34_MCICLK		MFP_CFG(GPIO34, AF2)
+#define GPIO35_MCICMD		MFP_CFG(GPIO35, AF2)
+#define GPIO36_ENET_TX_EN	MFP_CFG(GPIO36, AF1)
+#define GPIO37_MCIPWR		MFP_CFG(GPIO37, AF2)
+#define GPIO38_ENET_TX_CLK	MFP_CFG(GPIO38, AF1)
+#define GPIO38_MCIDAT0		MFP_CFG(GPIO38, AF2)
+#define GPIO39_MCIDAT1		MFP_CFG(GPIO39, AF2)
+#define GPIO40_ENET_CRS		MFP_CFG(GPIO40, AF1)
+#define GPIO41_ENET_RXD0	MFP_CFG(GPIO41, AF1)
+#define GPIO42_ENET_RXD1	MFP_CFG(GPIO42, AF1)
+#define GPIO43_MCIDAT2		MFP_CFG(GPIO43, AF2)
+#define GPIO44_MCIDAT3		MFP_CFG(GPIO44, AF2)
+#define GPIO46_ENET_RX_ERR	MFP_CFG(GPIO46, AF1)
+#define GPIO47_ENET_REF_CLK	MFP_CFG(GPIO47, AF1)
+#define GPIO48_ENET_MDC		MFP_CFG(GPIO48, AF1)
+#define GPIO49_ENET_MDIO	MFP_CFG(GPIO49, AF1)
+#define GPIO50_PWM1		MFP_CFG(GPIO50, AF2)
+#define GPIO52_LCDVD10		MFP_CFG(GPIO52, AF1)
+#define GPIO53_LCDVD11		MFP_CFG(GPIO53, AF1)
+#define GPIO54_LCDVD12		MFP_CFG(GPIO54, AF1)
+#define GPIO55_LCDVD13		MFP_CFG(GPIO55, AF1)
+#define GPIO56_LCDVD14		MFP_CFG(GPIO56, AF1)
+#define GPIO57_LCDVD15		MFP_CFG(GPIO57, AF1)
+#define GPIO58_LCDVD20		MFP_CFG(GPIO58, AF1)
+#define GPIO59_LCDVD21		MFP_CFG(GPIO59, AF1)
+#define GPIO60_LCDVD22		MFP_CFG(GPIO60, AF1)
+#define GPIO61_LCDVD23		MFP_CFG(GPIO61, AF1)
+#define GPIO62_VBUS		MFP_CFG(GPIO62, AF2)
+#define GPIO63_USB_OVRCR2	MFP_CFG(GPIO63, AF1)
+#define GPIO64_LCDPWR		MFP_CFG(GPIO64, AF3)
+#define GPIO65_LCDLE		MFP_CFG(GPIO65, AF3)
+#define GPIO66_LCDDCLK		MFP_CFG(GPIO66, AF3)
+#define GPIO67_LCDFP		MFP_CFG(GPIO67, AF3)
+#define GPIO68_LCDM		MFP_CFG(GPIO68, AF3)
+#define GPIO69_LCDLP		MFP_CFG(GPIO69, AF3)
+#define GPIO70_LCDVP4		MFP_CFG(GPIO70, AF3)
+#define GPIO71_LCDVP5		MFP_CFG(GPIO71, AF3)
+#define GPIO72_LCDVP6		MFP_CFG(GPIO72, AF3)
+#define GPIO73_LCDVP7		MFP_CFG(GPIO73, AF3)
+#define GPIO75_LCDCLKIN		MFP_CFG(GPIO75, AF1)
+#define GPIO76_LCDVP18		MFP_CFG(GPIO76, AF1)
+#define GPIO77_LCDVP19		MFP_CFG(GPIO77, AF1)
+#define GPIO112_TXD1		MFP_CFG(GPIO112, AF3)
+#define GPIO113_RXD1		MFP_CFG(GPIO113, AF3)
+#define GPIO114_CTS1		MFP_CFG(GPIO114, AF3)
+#define GPIO115_DCD1		MFP_CFG(GPIO115, AF3)
+#define GPIO116_DSR1		MFP_CFG(GPIO116, AF3)
+#define GPIO117_DR1		MFP_CFG(GPIO117, AF3)
+#define GPIO118_RI1		MFP_CFG(GPIO118, AF3)
+#define GPIO126_RTS1		MFP_CFG(GPIO126, AF3)
+#define GPIO156_TXD3		MFP_CFG(GPIO156, AF3)
+#define GPIO156_LCDVP2		MFP_CFG(GPIO156, AF2)
+#define GPIO157_RXD3		MFP_CFG(GPIO157, AF3)
+#define GPIO157_LCDVP3		MFP_CFG(GPIO157, 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..3c919c8
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/mfp.h
@@ -0,0 +1,209 @@
+/*
+ * 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)
+
+/* list of all the configurable MFP pins */
+enum {
+	MFP_PIN_INVALID = -1,
+
+	MFP_PIN_GPIO0 = 0,
+	MFP_PIN_GPIO1,
+	MFP_PIN_GPIO2,
+	MFP_PIN_GPIO3,
+	MFP_PIN_GPIO4,
+	MFP_PIN_GPIO5,
+	MFP_PIN_GPIO6,
+	MFP_PIN_GPIO7,
+	MFP_PIN_GPIO8,
+	MFP_PIN_GPIO9,
+	MFP_PIN_GPIO10,
+	MFP_PIN_GPIO11,
+	MFP_PIN_GPIO12,
+	MFP_PIN_GPIO13,
+	MFP_PIN_GPIO14,
+	MFP_PIN_GPIO15,
+	MFP_PIN_GPIO16,
+	MFP_PIN_GPIO17,
+	MFP_PIN_GPIO18,
+	MFP_PIN_GPIO19,
+	MFP_PIN_GPIO20,
+	MFP_PIN_GPIO21,
+	MFP_PIN_GPIO22,
+	MFP_PIN_GPIO23,
+	MFP_PIN_GPIO24,
+	MFP_PIN_GPIO25,
+	MFP_PIN_GPIO26,
+	MFP_PIN_GPIO27,
+	MFP_PIN_GPIO28,
+	MFP_PIN_GPIO29,
+	MFP_PIN_GPIO30,
+	MFP_PIN_GPIO31,
+	MFP_PIN_GPIO32,
+	MFP_PIN_GPIO33,
+	MFP_PIN_GPIO34,
+	MFP_PIN_GPIO35,
+	MFP_PIN_GPIO36,
+	MFP_PIN_GPIO37,
+	MFP_PIN_GPIO38,
+	MFP_PIN_GPIO39,
+	MFP_PIN_GPIO40,
+	MFP_PIN_GPIO41,
+	MFP_PIN_GPIO42,
+	MFP_PIN_GPIO43,
+	MFP_PIN_GPIO44,
+	MFP_PIN_GPIO45,
+	MFP_PIN_GPIO46,
+	MFP_PIN_GPIO47,
+	MFP_PIN_GPIO48,
+	MFP_PIN_GPIO49,
+	MFP_PIN_GPIO50,
+	MFP_PIN_GPIO51,
+	MFP_PIN_GPIO52,
+	MFP_PIN_GPIO53,
+	MFP_PIN_GPIO54,
+	MFP_PIN_GPIO55,
+	MFP_PIN_GPIO56,
+	MFP_PIN_GPIO57,
+	MFP_PIN_GPIO58,
+	MFP_PIN_GPIO59,
+	MFP_PIN_GPIO60,
+	MFP_PIN_GPIO61,
+	MFP_PIN_GPIO62,
+	MFP_PIN_GPIO63,
+	MFP_PIN_GPIO64,
+	MFP_PIN_GPIO65,
+	MFP_PIN_GPIO66,
+	MFP_PIN_GPIO67,
+	MFP_PIN_GPIO68,
+	MFP_PIN_GPIO69,
+	MFP_PIN_GPIO70,
+	MFP_PIN_GPIO71,
+	MFP_PIN_GPIO72,
+	MFP_PIN_GPIO73,
+	MFP_PIN_GPIO74,
+	MFP_PIN_GPIO75,
+	MFP_PIN_GPIO76,
+	MFP_PIN_GPIO77,
+	MFP_PIN_GPIO78,
+	MFP_PIN_GPIO79,
+	MFP_PIN_GPIO80,
+	MFP_PIN_GPIO81,
+	MFP_PIN_GPIO82,
+	MFP_PIN_GPIO83,
+	MFP_PIN_GPIO84,
+	MFP_PIN_GPIO85,
+	MFP_PIN_GPIO86,
+	MFP_PIN_GPIO87,
+	MFP_PIN_GPIO88,
+	MFP_PIN_GPIO89,
+	MFP_PIN_GPIO90,
+	MFP_PIN_GPIO91,
+	MFP_PIN_GPIO92,
+	MFP_PIN_GPIO93,
+	MFP_PIN_GPIO94,
+	MFP_PIN_GPIO95,
+	MFP_PIN_GPIO96,
+	MFP_PIN_GPIO97,
+	MFP_PIN_GPIO98,
+	MFP_PIN_GPIO99,
+	MFP_PIN_GPIO100,
+	MFP_PIN_GPIO101,
+	MFP_PIN_GPIO102,
+	MFP_PIN_GPIO103,
+	MFP_PIN_GPIO104,
+	MFP_PIN_GPIO105,
+	MFP_PIN_GPIO106,
+	MFP_PIN_GPIO107,
+	MFP_PIN_GPIO108,
+	MFP_PIN_GPIO109,
+	MFP_PIN_GPIO110,
+	MFP_PIN_GPIO111,
+	MFP_PIN_GPIO112,
+	MFP_PIN_GPIO113,
+	MFP_PIN_GPIO114,
+	MFP_PIN_GPIO115,
+	MFP_PIN_GPIO116,
+	MFP_PIN_GPIO117,
+	MFP_PIN_GPIO118,
+	MFP_PIN_GPIO119,
+	MFP_PIN_GPIO120,
+	MFP_PIN_GPIO121,
+	MFP_PIN_GPIO122,
+	MFP_PIN_GPIO123,
+	MFP_PIN_GPIO124,
+	MFP_PIN_GPIO125,
+	MFP_PIN_GPIO126,
+	MFP_PIN_GPIO127,
+	MFP_PIN_GPIO128,
+	MFP_PIN_GPIO129,
+	MFP_PIN_GPIO130,
+	MFP_PIN_GPIO131,
+	MFP_PIN_GPIO132,
+	MFP_PIN_GPIO133,
+	MFP_PIN_GPIO134,
+	MFP_PIN_GPIO135,
+	MFP_PIN_GPIO136,
+	MFP_PIN_GPIO137,
+	MFP_PIN_GPIO138,
+	MFP_PIN_GPIO139,
+	MFP_PIN_GPIO140,
+	MFP_PIN_GPIO141,
+	MFP_PIN_GPIO142,
+	MFP_PIN_GPIO143,
+	MFP_PIN_GPIO144,
+	MFP_PIN_GPIO145,
+	MFP_PIN_GPIO146,
+	MFP_PIN_GPIO147,
+	MFP_PIN_GPIO148,
+	MFP_PIN_GPIO149,
+	MFP_PIN_GPIO150,
+	MFP_PIN_GPIO151,
+	MFP_PIN_GPIO152,
+	MFP_PIN_GPIO153,
+	MFP_PIN_GPIO154,
+	MFP_PIN_GPIO155,
+	MFP_PIN_GPIO156,
+	MFP_PIN_GPIO157,
+	MFP_PIN_GPIO158,
+	MFP_PIN_GPIO159,
+};
+
+/* 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(MFP_PIN_##pin) | MFP_##af))
+
+#define MFP_CFG_PULL(pin, af, pull)	\
+	((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_PULL_MASK)) |\
+	 (MFP_PIN(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..6e4779d
--- /dev/null
+++ b/arch/arm/mach-lpc2k/mfp.c
@@ -0,0 +1,99 @@
+/*
+ * 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/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[MFP_PIN_GPIO159 + 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 = MFP_PIN_GPIO0; i <= MFP_PIN_GPIO159; i++)
+		gpio_desc[i].valid = 1;
+
+	return 0;
+}
+
+postcore_initcall(lpc2k_mfp_init);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 7/9] lpc2k: Add EmbeddedArtists LPC2478 Developer's Kit board
  2011-03-17 15:54 [PATCH 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
                   ` (5 preceding siblings ...)
  2011-03-17 15:54 ` [PATCH 6/9] lpc2k: multifunction pin configuration Ithamar R. Adema
@ 2011-03-17 15:54 ` Ithamar R. Adema
  2011-03-17 22:07   ` Kevin Wells
  2011-03-17 22:33   ` Kevin Wells
  2011-03-17 15:54 ` [PATCH 8/9] lpc2k: Add UART, SSP, and MCI devices Ithamar R. Adema
                   ` (3 subsequent siblings)
  10 siblings, 2 replies; 30+ messages in thread
From: Ithamar R. Adema @ 2011-03-17 15:54 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

Signed-off-by: Ithamar R. Adema <ithamar.adema@team-embedded.nl>
---
 arch/arm/mach-lpc2k/Kconfig           |    7 ++
 arch/arm/mach-lpc2k/Makefile          |    2 +
 arch/arm/mach-lpc2k/common.h          |   21 ++++++
 arch/arm/mach-lpc2k/mach-lpc2478oem.c |  121 +++++++++++++++++++++++++++++++++
 4 files changed, 151 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-lpc2k/common.h
 create mode 100644 arch/arm/mach-lpc2k/mach-lpc2478oem.c

diff --git a/arch/arm/mach-lpc2k/Kconfig b/arch/arm/mach-lpc2k/Kconfig
index fad47b8..162d616 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_LPC2478OEM
+	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..a969f44 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_LPC2478OEM) += mach-lpc2478oem.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-lpc2478oem.c b/arch/arm/mach-lpc2k/mach-lpc2478oem.c
new file mode 100644
index 0000000..fec98e2
--- /dev/null
+++ b/arch/arm/mach-lpc2k/mach-lpc2478oem.c
@@ -0,0 +1,121 @@
+/*
+ * 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/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[] = {
+	/* UART0 */
+	GPIO2_TXD0,
+	GPIO3_RXD0,
+	/* USB Host */
+	GPIO12_USB_PPWR2,
+	GPIO13_USB_UP_LED2,
+	GPIO31_USB_Dp2,
+	GPIO62_VBUS,
+	GPIO63_USB_OVRCR2,
+	/* USB Gadget */
+	GPIO29_USB_Dp1,
+	GPIO30_USB_Dn1,
+	/* Ethernet */
+	GPIO32_ENET_TXD0,
+	GPIO33_ENET_TXD1,
+	GPIO36_ENET_TX_EN,
+	GPIO40_ENET_CRS,
+	GPIO41_ENET_RXD0,
+	GPIO42_ENET_RXD1,
+	GPIO46_ENET_RX_ERR,
+	GPIO47_ENET_REF_CLK,
+	GPIO48_ENET_MDC,
+	GPIO49_ENET_MDIO,
+	/* I2C0 */
+	GPIO27_SDA0,
+	GPIO28_SCL0,
+	/* SPI */
+	GPIO15_SCK,
+	GPIO17_MISO,
+	GPIO18_MOSI,
+	/* LCD */
+	GPIO4_LCDVD0,
+	GPIO5_LCDVD1,
+	GPIO6_LCDVD8,
+	GPIO7_LCDVD9,
+	GPIO8_LCDVD16,
+	GPIO9_LCDVD17,
+	GPIO52_LCDVD10,
+	GPIO53_LCDVD11,
+	GPIO54_LCDVD12,
+	GPIO55_LCDVD13,
+	GPIO56_LCDVD14,
+	GPIO57_LCDVD15,
+	GPIO58_LCDVD20,
+	GPIO59_LCDVD21,
+	GPIO60_LCDVD22,
+	GPIO61_LCDVD23,
+	GPIO64_LCDPWR,
+	GPIO65_LCDLE,
+	GPIO66_LCDDCLK,
+	GPIO67_LCDFP,
+	GPIO68_LCDM,
+	GPIO69_LCDLP,
+	GPIO70_LCDVP4,
+	GPIO71_LCDVP5,
+	GPIO72_LCDVP6,
+	GPIO73_LCDVP7,
+	GPIO75_LCDCLKIN,
+	GPIO76_LCDVP18,
+	GPIO77_LCDVP19,
+	GPIO156_LCDVP2,
+	GPIO157_LCDVP3,
+	/* Backlight */
+	GPIO50_PWM1,
+	/* MMC/SD */
+	GPIO34_MCICLK,
+	GPIO35_MCICMD,
+	GPIO37_MCIPWR,
+	GPIO38_MCIDAT0,
+	GPIO39_MCIDAT1,
+	GPIO43_MCIDAT2,
+	GPIO44_MCIDAT3,
+};
+
+void __init lpc2478oem_init_machine(void)
+{
+	lpc2k_mfp_config(mfp_cfgs, ARRAY_SIZE(mfp_cfgs));
+}
+
+static void __init lpc2478oem_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, 32768000UL);
+}
+
+MACHINE_START(LPC2478OEM, "Embedded Artists LPC2478 OEM Board")
+	.init_irq	= lpc2478oem_init_irq,
+	.timer		= &lpc2k_timer,
+	.init_machine	= lpc2478oem_init_machine,
+MACHINE_END
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 8/9] lpc2k: Add UART, SSP, and MCI devices
  2011-03-17 15:54 [PATCH 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
                   ` (6 preceding siblings ...)
  2011-03-17 15:54 ` [PATCH 7/9] lpc2k: Add EmbeddedArtists LPC2478 Developer's Kit board Ithamar R. Adema
@ 2011-03-17 15:54 ` Ithamar R. Adema
  2011-03-17 15:54 ` [PATCH 9/9] lpc2k: defconfig for NXP LPC2K platform Ithamar R. Adema
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 30+ messages in thread
From: Ithamar R. Adema @ 2011-03-17 15:54 UTC (permalink / raw)
  To: linux-arm-kernel

Adds devices for which the drivers are already in the tree. For
the relevant devices, let the lpc2478oem board set them up.

Signed-off-by: Ithamar R. Adema <ithamar.adema@team-embedded.nl>
---
 arch/arm/Kconfig                            |    1 +
 arch/arm/mach-lpc2k/Makefile                |    2 +-
 arch/arm/mach-lpc2k/common.h                |    4 +
 arch/arm/mach-lpc2k/devices.c               |  174 +++++++++++++++++++++++++++
 arch/arm/mach-lpc2k/include/mach/hardware.h |    6 +
 arch/arm/mach-lpc2k/mach-lpc2478oem.c       |   20 +++
 6 files changed, 206 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-lpc2k/devices.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index fce855d..1735b02 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_TIME
 	select GENERIC_CLOCKEVENTS
diff --git a/arch/arm/mach-lpc2k/Makefile b/arch/arm/mach-lpc2k/Makefile
index a969f44..af6a1c2 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_LPC2478OEM) += mach-lpc2478oem.o
+obj-$(CONFIG_MACH_LPC2478OEM) += mach-lpc2478oem.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..8855e8a
--- /dev/null
+++ b/arch/arm/mach-lpc2k/devices.c
@@ -0,0 +1,174 @@
+/*
+ * 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);
+	clk_put(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 29c561a..3054a9e 100644
--- a/arch/arm/mach-lpc2k/include/mach/hardware.h
+++ b/arch/arm/mach-lpc2k/include/mach/hardware.h
@@ -19,8 +19,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-lpc2478oem.c b/arch/arm/mach-lpc2k/mach-lpc2478oem.c
index fec98e2..9261574 100644
--- a/arch/arm/mach-lpc2k/mach-lpc2478oem.c
+++ b/arch/arm/mach-lpc2k/mach-lpc2478oem.c
@@ -8,6 +8,8 @@
  */
 
 #include <linux/module.h>
+#include <linux/amba/pl022.h>
+#include <linux/amba/mmci.h>
 #include <linux/io.h>
 
 #include <asm/mach/arch.h>
@@ -95,9 +97,27 @@ static unsigned long mfp_cfgs[] = {
 	GPIO44_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 lpc2478oem_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 lpc2478oem_init_irq(void)
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 9/9] lpc2k: defconfig for NXP LPC2K platform
  2011-03-17 15:54 [PATCH 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
                   ` (7 preceding siblings ...)
  2011-03-17 15:54 ` [PATCH 8/9] lpc2k: Add UART, SSP, and MCI devices Ithamar R. Adema
@ 2011-03-17 15:54 ` Ithamar R. Adema
  2011-03-17 17:18 ` [PATCH 0/9] Support for NXP LPC2K SoCs Kevin Wells
  2011-03-18  0:45 ` Greg Ungerer
  10 siblings, 0 replies; 30+ messages in thread
From: Ithamar R. Adema @ 2011-03-17 15:54 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>
---
 arch/arm/configs/lpc2k_defconfig |   56 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 56 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..6278dd8
--- /dev/null
+++ b/arch/arm/configs/lpc2k_defconfig
@@ -0,0 +1,56 @@
+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_LPC2478OEM=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_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] 30+ messages in thread

* [PATCH 2/9] lpc2k: Exception vector handling
  2011-03-17 15:54 ` [PATCH 2/9] lpc2k: Exception vector handling Ithamar R. Adema
@ 2011-03-17 16:18   ` Uwe Kleine-König
  2011-03-17 16:28     ` Ithamar R. Adema
  0 siblings, 1 reply; 30+ messages in thread
From: Uwe Kleine-König @ 2011-03-17 16:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 17, 2011 at 04:54:17PM +0100, Ithamar R. Adema wrote:
> Since the LPC2K does not have an MMU (ARM7TDMI based), it expects the vectors to be
> stored in on-chip SRAM. However, this moves the vectors too far away from the stubs
> page, requiring the vector jumps to be indirect.
> 
> 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>
> ---
>  arch/arm/Kconfig             |    1 +
>  arch/arm/kernel/entry-armv.S |   18 ++++++++++++++++++
>  arch/arm/kernel/traps.c      |    2 +-
>  arch/arm/mm/nommu.c          |    2 ++
>  4 files changed, 22 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 331540d..9c12d71 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..618a971 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,23 @@ __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 description from the commit log should be repeated here.

And I wonder if this shouldn't depend on CONFIG_ARCH_LPC2K but
CONFIG_MMU.

> +	swi	SYS_ERROR0
I think arm7tdmi doesn't have thumb2, does it? If it has you need to do
ARM(swi SYS_ERROR0)
THUMB(svc ..)
...

as above

> +	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
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 2/9] lpc2k: Exception vector handling
  2011-03-17 16:18   ` Uwe Kleine-König
@ 2011-03-17 16:28     ` Ithamar R. Adema
  2011-03-18  0:43       ` Greg Ungerer
  0 siblings, 1 reply; 30+ messages in thread
From: Ithamar R. Adema @ 2011-03-17 16:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2011-03-17 at 17:18 +0100, Uwe Kleine-K?nig wrote:
> On Thu, Mar 17, 2011 at 04:54:17PM +0100, Ithamar R. Adema wrote:
> > diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
> > index e8d8856..618a971 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,23 @@ __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 description from the commit log should be repeated here.

OK, will include the description as comment there in the next version.

> And I wonder if this shouldn't depend on CONFIG_ARCH_LPC2K but
> CONFIG_MMU.

Well, looking at th uClinux kernel tree, it seems this was only done for
the NXP LPC2K range, so that's why I kept it under CONFIG_ARCH_LPC2K.

> > +	swi	SYS_ERROR0
> I think arm7tdmi doesn't have thumb2, does it? If it has you need to do
> ARM(swi SYS_ERROR0)
> THUMB(svc ..)
> ...
> 
> as above

Correct, the ARM7TDMI-S only supports Thumb, not Thumb2.

Thanks for reviewing!

Ithamar.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 0/9] Support for NXP LPC2K SoCs
  2011-03-17 15:54 [PATCH 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
                   ` (8 preceding siblings ...)
  2011-03-17 15:54 ` [PATCH 9/9] lpc2k: defconfig for NXP LPC2K platform Ithamar R. Adema
@ 2011-03-17 17:18 ` Kevin Wells
  2011-03-18  0:45 ` Greg Ungerer
  10 siblings, 0 replies; 30+ messages in thread
From: Kevin Wells @ 2011-03-17 17:18 UTC (permalink / raw)
  To: linux-arm-kernel

> Subject: [PATCH 0/9] Support for NXP LPC2K SoCs
> 
> The following patch series implements support for the ARM7TDMI-S based
> NXP LPC2K System-on-Chips, and, as first board, the EmbeddedArtists
> LPC2478 Developer's Kit.
> 
> This code will work on the LPC23XX and LPC24XX ranges of chips, but will
> need some more work for LPC21XX and LPC22XX chips.
> 

Excellent timing on releasing this patch series! I was 1 day into starting
a new release for this! I'll happily check out your patches on our boards
here..

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 1/9] lpc2k: Core support
  2011-03-17 15:54 ` [PATCH 1/9] lpc2k: Core support Ithamar R. Adema
@ 2011-03-17 21:26   ` Jamie Iles
  2011-03-17 21:32   ` Vitaly Wool
  2011-03-17 22:08   ` Kevin Wells
  2 siblings, 0 replies; 30+ messages in thread
From: Jamie Iles @ 2011-03-17 21:26 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Thu, Mar 17, 2011 at 04:54:16PM +0100, Ithamar R. Adema wrote:
> Core files (including IRQ handling) for NXP LPC2K architecture.
> 
> Signed-off-by: Ithamar R. Adema <ithamar.adema@team-embedded.nl>
> ---
[...]
> 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:

Could you adapt the code in arch/arm/include/asm/entry-macro-vic2.S for 
a single VIC?  That eliminates the looping that you have here.

Jamie

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 1/9] lpc2k: Core support
  2011-03-17 15:54 ` [PATCH 1/9] lpc2k: Core support Ithamar R. Adema
  2011-03-17 21:26   ` Jamie Iles
@ 2011-03-17 21:32   ` Vitaly Wool
  2011-03-17 21:50     ` Ithamar R. Adema
  2011-03-17 22:08   ` Kevin Wells
  2 siblings, 1 reply; 30+ messages in thread
From: Vitaly Wool @ 2011-03-17 21:32 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Thu, Mar 17, 2011 at 4:54 PM, Ithamar R. Adema
<ithamar.adema@team-embedded.nl> wrote:
> Core files (including IRQ handling) for NXP LPC2K architecture.

<snip>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index e34bf02..331540d 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -490,6 +490,18 @@ 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_TIME
> + ? ? ? 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
> @@ -928,6 +940,8 @@ source "arch/arm/mach-ks8695/Kconfig"
>
> ?source "arch/arm/mach-loki/Kconfig"
>
> +source "arch/arm/mach-lpc2k/Kconfig"
> +

is there any good reason why you don't add your stuff to lpc32xx?

~Vitaly

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 4/9] lpc2k: generic time and clockevents
  2011-03-17 15:54 ` [PATCH 4/9] lpc2k: generic time and clockevents Ithamar R. Adema
@ 2011-03-17 21:38   ` Jamie Iles
  2011-03-17 22:00     ` Ithamar R. Adema
  0 siblings, 1 reply; 30+ messages in thread
From: Jamie Iles @ 2011-03-17 21:38 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

One pedantic nitpick, but otherwise looks nice to me.

Jamie

On Thu, Mar 17, 2011 at 04:54:19PM +0100, Ithamar R. Adema wrote:
> This code was mostly "borrowed" form the lpc32xx implementation.
> 
> Signed-off-by: Ithamar R. Adema <ithamar.adema@team-embedded.nl>
> ---
>  arch/arm/mach-lpc2k/Makefile |    2 +-
>  arch/arm/mach-lpc2k/time.c   |  174 ++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 175 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..b430f7c
> --- /dev/null
> +++ b/arch/arm/mach-lpc2k/time.c
> @@ -0,0 +1,174 @@
> +/*
> + * Copyright (C) 2011 Team Embeded VOF
> + * 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,
> +	.shift		= 32,

You shouldn't need to specify a shift if you use 
clockevents_calc_mult_shift() and let the core code calculate mult and 
shift for you.

> +	.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_put(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. */
> +	lpc2k_clkevt.mult = div_sc(rate, NSEC_PER_SEC,
> +		lpc2k_clkevt.shift);

clockevents_calc_mult_shift() will take care of this for you.

> +	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	[flat|nested] 30+ messages in thread

* [PATCH 1/9] lpc2k: Core support
  2011-03-17 21:32   ` Vitaly Wool
@ 2011-03-17 21:50     ` Ithamar R. Adema
  0 siblings, 0 replies; 30+ messages in thread
From: Ithamar R. Adema @ 2011-03-17 21:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2011-03-17 at 22:32 +0100, Vitaly Wool wrote:
> is there any good reason why you don't add your stuff to lpc32xx?

Most of the code (interrupt controller, clocks, etc) are completely
different on the ARM7TDMI based LPC2K socs compared to the ARM9 based
LPC3K SoCs. One of the only things that is fairly similar is the timers
block ;-)

I've looked at solutions introducing a plat-lpc directory but it ended
up introducing more "red tape" then actual shared code...

Regards,

Ithamar.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 4/9] lpc2k: generic time and clockevents
  2011-03-17 21:38   ` Jamie Iles
@ 2011-03-17 22:00     ` Ithamar R. Adema
  0 siblings, 0 replies; 30+ messages in thread
From: Ithamar R. Adema @ 2011-03-17 22:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2011-03-17 at 21:38 +0000, Jamie Iles wrote:
> One pedantic nitpick, but otherwise looks nice to me.

Thanks for reviewing, and pedantic nitpicks are always welcome ;)

> On Thu, Mar 17, 2011 at 04:54:19PM +0100, Ithamar R. Adema wrote:
[....]
> > +static struct clock_event_device lpc2k_clkevt = {
> > +	.name		= "lpc2k_clkevt",
> > +	.features	= CLOCK_EVT_FEAT_ONESHOT,
> > +	.shift		= 32,
> 
> You shouldn't need to specify a shift if you use 
> clockevents_calc_mult_shift() and let the core code calculate mult and 
> shift for you.

Good point, I should use that. Will include this in the next version of
these patches!

Regards,

Ithamar.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 7/9] lpc2k: Add EmbeddedArtists LPC2478 Developer's Kit board
  2011-03-17 15:54 ` [PATCH 7/9] lpc2k: Add EmbeddedArtists LPC2478 Developer's Kit board Ithamar R. Adema
@ 2011-03-17 22:07   ` Kevin Wells
  2011-03-17 22:18     ` Ithamar R. Adema
  2011-03-17 22:33   ` Kevin Wells
  1 sibling, 1 reply; 30+ messages in thread
From: Kevin Wells @ 2011-03-17 22:07 UTC (permalink / raw)
  To: linux-arm-kernel

> +
> +#define EXTPOLAR	0x14c
> +
> +static unsigned long mfp_cfgs[] = {

Should this be initdata?

> +
> +MACHINE_START(LPC2478OEM, "Embedded Artists LPC2478 OEM Board")

Just a nit, but the machine ID should probably be unique to this
board and not the 2478, ie EA2478OEM. If someone else releases a
LPC2478 based board, it can't use this same id. This would apply
to the filename too (lpc2478oem.c) - the name is somewhat generic
and might be better named something like plat-ea2478oem.c.

> +	.init_irq	= lpc2478oem_init_irq,
> +	.timer		= &lpc2k_timer,
> +	.init_machine	= lpc2478oem_init_machine,
> +MACHINE_END
> --
> 1.7.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 1/9] lpc2k: Core support
  2011-03-17 15:54 ` [PATCH 1/9] lpc2k: Core support Ithamar R. Adema
  2011-03-17 21:26   ` Jamie Iles
  2011-03-17 21:32   ` Vitaly Wool
@ 2011-03-17 22:08   ` Kevin Wells
  2011-03-17 22:25     ` Ithamar R. Adema
  2 siblings, 1 reply; 30+ messages in thread
From: Kevin Wells @ 2011-03-17 22:08 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ithamar,

> 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..fbbea43
> --- /dev/null
> +++ b/arch/arm/mach-lpc2k/include/mach/system.h
> @@ -0,0 +1,23 @@
> +/*
> + * 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
> +
> +static void arch_idle(void)
> +{
> +	cpu_do_idle();
> +}

The 24xx devices have a CPU idle down register (PCON) that will suspend
the CPU clock until the next interrupt. *pcon = 1;

> +
> +static inline void arch_reset(char mode, const char *cmd)
> +{
> +	cpu_reset(0);
> +}

The entire system can be reset via RESETOUT using the watchdog timer.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 3/9] lpc2k: clk API
  2011-03-17 15:54 ` [PATCH 3/9] lpc2k: clk API Ithamar R. Adema
@ 2011-03-17 22:08   ` Kevin Wells
  2011-03-18  9:44     ` Ithamar R. Adema
  2011-03-17 22:16   ` Kevin Wells
  1 sibling, 1 reply; 30+ messages in thread
From: Kevin Wells @ 2011-03-17 22:08 UTC (permalink / raw)
  To: linux-arm-kernel

> +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_MUTEX(clocks_mutex);

I tried this lock mechanism and occasionally I get warnings when mutex
checking is enabled and multiple calls occur to the clk_* functions
with active clock management. Spinlocks might be better, but maybe some
one else can chime in here.

> +
> +/*-----------------------------------------------------------------------
> --
> + * Standard clock functions defined in include/linux/clk.h
> + *-----------------------------------------------------------------------
> --*/
> +

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 3/9] lpc2k: clk API
  2011-03-17 15:54 ` [PATCH 3/9] lpc2k: clk API Ithamar R. Adema
  2011-03-17 22:08   ` Kevin Wells
@ 2011-03-17 22:16   ` Kevin Wells
  2011-03-17 22:29     ` Ithamar R. Adema
  1 sibling, 1 reply; 30+ messages in thread
From: Kevin Wells @ 2011-03-17 22:16 UTC (permalink / raw)
  To: linux-arm-kernel

> diff --git a/arch/arm/mach-lpc2k/include/mach/regs-clock.h
> b/arch/arm/mach-lpc2k/include/mach/regs-clock.h
> new file mode 100644
> index 0000000..1c94582
> --- /dev/null
> +++ b/arch/arm/mach-lpc2k/include/mach/regs-clock.h
> @@ -0,0 +1,36 @@
> +/*
> + * 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_CLOCK_H
> +#define MACH_LPC2K_REGS_CLOCK_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) & 0xf) + 1)

N has a field size of 8 bits? Mask should be 0xff

> +#define PLLE		(1 << 24)

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 7/9] lpc2k: Add EmbeddedArtists LPC2478 Developer's Kit board
  2011-03-17 22:07   ` Kevin Wells
@ 2011-03-17 22:18     ` Ithamar R. Adema
  0 siblings, 0 replies; 30+ messages in thread
From: Ithamar R. Adema @ 2011-03-17 22:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2011-03-17 at 23:07 +0100, Kevin Wells wrote:
> > +
> > +#define EXTPOLAR	0x14c
> > +
> > +static unsigned long mfp_cfgs[] = {
> 
> Should this be initdata?

Yes, good catch!

> > +MACHINE_START(LPC2478OEM, "Embedded Artists LPC2478 OEM Board")
> 
> Just a nit, but the machine ID should probably be unique to this
> board and not the 2478, ie EA2478OEM. If someone else releases a
> LPC2478 based board, it can't use this same id. This would apply
> to the filename too (lpc2478oem.c) - the name is somewhat generic
> and might be better named something like plat-ea2478oem.c.

True, a more concise name there would be helpful. It is a bit of a
mixture since the LPC2478OEM is just the CPU board, and the 'Developer's
Kit' includes a baseboard with peripheral devices.

I'll come up with a better name for it, it will just require another
board registration and update of arch/arm/tools/mach-types :(

Regards,

Ithamar.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 1/9] lpc2k: Core support
  2011-03-17 22:08   ` Kevin Wells
@ 2011-03-17 22:25     ` Ithamar R. Adema
  0 siblings, 0 replies; 30+ messages in thread
From: Ithamar R. Adema @ 2011-03-17 22:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2011-03-17 at 23:08 +0100, Kevin Wells wrote:
[...]
> > +static void arch_idle(void)
> > +{
> > +	cpu_do_idle();
> > +}
> 
> The 24xx devices have a CPU idle down register (PCON) that will suspend
> the CPU clock until the next interrupt. *pcon = 1;

Yes, I know, but was planning on introducing that together with
suspend/resume in a next patch series. I've had it in locally already
but got some interrupt disable/enable errors during exit of idle mode
that need further investigation.

> > +
> > +static inline void arch_reset(char mode, const char *cmd)
> > +{
> > +	cpu_reset(0);
> > +}
> 
> The entire system can be reset via RESETOUT using the watchdog timer.

Again, was planning that for the patch set that will introduce the
watchdog driver.

Regards,

Ithamar.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 3/9] lpc2k: clk API
  2011-03-17 22:16   ` Kevin Wells
@ 2011-03-17 22:29     ` Ithamar R. Adema
  0 siblings, 0 replies; 30+ messages in thread
From: Ithamar R. Adema @ 2011-03-17 22:29 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Kevin,

On Thu, 2011-03-17 at 23:16 +0100, Kevin Wells wrote:
> > diff --git a/arch/arm/mach-lpc2k/include/mach/regs-clock.h
> > b/arch/arm/mach-lpc2k/include/mach/regs-clock.h
> > new file mode 100644
> > index 0000000..1c94582
> > --- /dev/null
> > +++ b/arch/arm/mach-lpc2k/include/mach/regs-clock.h
> > @@ -0,0 +1,36 @@
> > +/*
> > + * 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_CLOCK_H
> > +#define MACH_LPC2K_REGS_CLOCK_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) & 0xf) + 1)
> 
> N has a field size of 8 bits? Mask should be 0xff

Ouch, will fix for v2 of this patchset!

Ithamar.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 7/9] lpc2k: Add EmbeddedArtists LPC2478 Developer's Kit board
  2011-03-17 15:54 ` [PATCH 7/9] lpc2k: Add EmbeddedArtists LPC2478 Developer's Kit board Ithamar R. Adema
  2011-03-17 22:07   ` Kevin Wells
@ 2011-03-17 22:33   ` Kevin Wells
  2011-03-17 22:49     ` Ithamar R. Adema
  1 sibling, 1 reply; 30+ messages in thread
From: Kevin Wells @ 2011-03-17 22:33 UTC (permalink / raw)
  To: linux-arm-kernel

> +static void __init lpc2478oem_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, 32768000UL);

Should the RTC clock be 32768?

> +}
> +
> +MACHINE_START(LPC2478OEM, "Embedded Artists LPC2478 OEM Board")
> +	.init_irq	= lpc2478oem_init_irq,
> +	.timer		= &lpc2k_timer,
> +	.init_machine	= lpc2478oem_init_machine,
> +MACHINE_END

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 7/9] lpc2k: Add EmbeddedArtists LPC2478 Developer's Kit board
  2011-03-17 22:33   ` Kevin Wells
@ 2011-03-17 22:49     ` Ithamar R. Adema
  0 siblings, 0 replies; 30+ messages in thread
From: Ithamar R. Adema @ 2011-03-17 22:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2011-03-17 at 23:33 +0100, Kevin Wells wrote:
> > +     lpc2k_init_clocks(12000000UL, 32768000UL);
> 
> Should the RTC clock be 32768? 

Yes, it should be. Will fix.

Ithamar.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 2/9] lpc2k: Exception vector handling
  2011-03-17 16:28     ` Ithamar R. Adema
@ 2011-03-18  0:43       ` Greg Ungerer
  0 siblings, 0 replies; 30+ messages in thread
From: Greg Ungerer @ 2011-03-18  0:43 UTC (permalink / raw)
  To: linux-arm-kernel

On 18/03/11 02:28, Ithamar R. Adema wrote:
> On Thu, 2011-03-17 at 17:18 +0100, Uwe Kleine-K??nig wrote:
>> On Thu, Mar 17, 2011 at 04:54:17PM +0100, Ithamar R. Adema wrote:
>>> diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
>>> index e8d8856..618a971 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,23 @@ __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 description from the commit log should be repeated here.
>
> OK, will include the description as comment there in the next version.
>
>> And I wonder if this shouldn't depend on CONFIG_ARCH_LPC2K but
>> CONFIG_MMU.
>
> Well, looking at th uClinux kernel tree, it seems this was only done for
> the NXP LPC2K range, so that's why I kept it under CONFIG_ARCH_LPC2K.

IIRC most of the non-MMU ARMs had the vectors in normal RAM, so they
would end up close to the code. That is why this may have been the
only one with the vectors ending up a long way away. So it is not
specific to non-MMU, but one day there may be other types that need
to do this too.

Regards
Greg


>>> +	swi	SYS_ERROR0
>> I think arm7tdmi doesn't have thumb2, does it? If it has you need to do
>> ARM(swi SYS_ERROR0)
>> THUMB(svc ..)
>> ...
>>
>> as above
>
> Correct, the ARM7TDMI-S only supports Thumb, not Thumb2.
>
> Thanks for reviewing!
>
> Ithamar.
>
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
>
>


-- 
------------------------------------------------------------------------
Greg Ungerer  --  Principal Engineer        EMAIL:     gerg at snapgear.com
SnapGear Group, McAfee                      PHONE:       +61 7 3435 2888
8 Gardner Close                             FAX:         +61 7 3217 5323
Milton, QLD, 4064, Australia                WEB: http://www.SnapGear.com

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 0/9] Support for NXP LPC2K SoCs
  2011-03-17 15:54 [PATCH 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
                   ` (9 preceding siblings ...)
  2011-03-17 17:18 ` [PATCH 0/9] Support for NXP LPC2K SoCs Kevin Wells
@ 2011-03-18  0:45 ` Greg Ungerer
  10 siblings, 0 replies; 30+ messages in thread
From: Greg Ungerer @ 2011-03-18  0:45 UTC (permalink / raw)
  To: linux-arm-kernel

On 18/03/11 01:54, Ithamar R. Adema wrote:
> The following patch series implements support for the ARM7TDMI-S based
> NXP LPC2K System-on-Chips, and, as first board, the EmbeddedArtists
> LPC2478 Developer's Kit.
>
> This code will work on the LPC23XX and LPC24XX ranges of chips, but will
> need some more work for LPC21XX and LPC22XX chips.

Nice to see some more non-MMU SoC parts getting pushed towards mainline!

Regards
Greg


------------------------------------------------------------------------
Greg Ungerer  --  Principal Engineer        EMAIL:     gerg at snapgear.com
SnapGear Group, McAfee                      PHONE:       +61 7 3435 2888
8 Gardner Close                             FAX:         +61 7 3217 5323
Milton, QLD, 4064, Australia                WEB: http://www.SnapGear.com

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 3/9] lpc2k: clk API
  2011-03-17 22:08   ` Kevin Wells
@ 2011-03-18  9:44     ` Ithamar R. Adema
  0 siblings, 0 replies; 30+ messages in thread
From: Ithamar R. Adema @ 2011-03-18  9:44 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Kevin,

On Thu, 2011-03-17 at 23:08 +0100, Kevin Wells wrote:
> > +static DEFINE_MUTEX(clocks_mutex);
> 
> I tried this lock mechanism and occasionally I get warnings when mutex
> checking is enabled and multiple calls occur to the clk_* functions
> with active clock management. Spinlocks might be better, but maybe
> some one else can chime in here.

Looking at the other mach-*/clock.c implementations, most seem to agree
on spinlocks. Will change for v2.

Regards,

Ithamar.

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2011-03-18  9:44 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-17 15:54 [PATCH 0/9] Support for NXP LPC2K SoCs Ithamar R. Adema
2011-03-17 15:54 ` [PATCH 1/9] lpc2k: Core support Ithamar R. Adema
2011-03-17 21:26   ` Jamie Iles
2011-03-17 21:32   ` Vitaly Wool
2011-03-17 21:50     ` Ithamar R. Adema
2011-03-17 22:08   ` Kevin Wells
2011-03-17 22:25     ` Ithamar R. Adema
2011-03-17 15:54 ` [PATCH 2/9] lpc2k: Exception vector handling Ithamar R. Adema
2011-03-17 16:18   ` Uwe Kleine-König
2011-03-17 16:28     ` Ithamar R. Adema
2011-03-18  0:43       ` Greg Ungerer
2011-03-17 15:54 ` [PATCH 3/9] lpc2k: clk API Ithamar R. Adema
2011-03-17 22:08   ` Kevin Wells
2011-03-18  9:44     ` Ithamar R. Adema
2011-03-17 22:16   ` Kevin Wells
2011-03-17 22:29     ` Ithamar R. Adema
2011-03-17 15:54 ` [PATCH 4/9] lpc2k: generic time and clockevents Ithamar R. Adema
2011-03-17 21:38   ` Jamie Iles
2011-03-17 22:00     ` Ithamar R. Adema
2011-03-17 15:54 ` [PATCH 5/9] lpc2k: gpiolib Ithamar R. Adema
2011-03-17 15:54 ` [PATCH 6/9] lpc2k: multifunction pin configuration Ithamar R. Adema
2011-03-17 15:54 ` [PATCH 7/9] lpc2k: Add EmbeddedArtists LPC2478 Developer's Kit board Ithamar R. Adema
2011-03-17 22:07   ` Kevin Wells
2011-03-17 22:18     ` Ithamar R. Adema
2011-03-17 22:33   ` Kevin Wells
2011-03-17 22:49     ` Ithamar R. Adema
2011-03-17 15:54 ` [PATCH 8/9] lpc2k: Add UART, SSP, and MCI devices Ithamar R. Adema
2011-03-17 15:54 ` [PATCH 9/9] lpc2k: defconfig for NXP LPC2K platform Ithamar R. Adema
2011-03-17 17:18 ` [PATCH 0/9] Support for NXP LPC2K SoCs Kevin Wells
2011-03-18  0:45 ` Greg Ungerer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).